Compare commits
35 Commits
456feed128
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
7265eaad18
|
|||
|
53ccfe1d4f
|
|||
|
a5a2f8324e
|
|||
|
dc3d1ac60d
|
|||
|
8fe121951b
|
|||
|
b345982ab1
|
|||
|
ca342cc238
|
|||
|
0de206016a
|
|||
|
326ef4bf5e
|
|||
|
0018e56938
|
|||
|
178f5c88e8
|
|||
|
6c67604efc
|
|||
|
378dae159f
|
|||
|
c55ce3ad77
|
|||
|
434a27d90d
|
|||
|
94f0f3ca13
|
|||
|
637b3a0c34
|
|||
|
a61e7ce19a
|
|||
|
da0db483aa
|
|||
|
61cceb41ba
|
|||
|
bcc5de6d7e
|
|||
|
31c44d3d92
|
|||
|
1743ed6ce4
|
|||
|
6c86fdd58b
|
|||
|
f224f3fa2c
|
|||
|
aaa15b1cfc
|
|||
|
f40845723d
|
|||
|
45ff84b106
|
|||
|
0bf4a6a08c
|
|||
|
1e8e0d3138
|
|||
|
12ee0bc7ad
|
|||
|
c4f1ccd869
|
|||
|
ac042d0a4f
|
|||
|
5abceb7bc7
|
|||
|
2e54b81d8f
|
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,26 +0,0 @@
|
|||||||
import Button from "./button/Button";
|
|
||||||
import DangerButton from "./button/DangerButton";
|
|
||||||
import DarkButton from "./button/DarkButton";
|
|
||||||
import InfoButton from "./button/InfoButton";
|
|
||||||
import LightButton from "./button/LightButton";
|
|
||||||
import MoltenButton from "./button/MoltenButton";
|
|
||||||
import PrimaryButton from "./button/PrimaryButton";
|
|
||||||
import SecondaryButton from "./button/SecondaryButton";
|
|
||||||
import SuccessButton from "./button/SuccessButton";
|
|
||||||
import TertiaryButton from "./button/TertiaryButton";
|
|
||||||
import WarningButton from "./button/WarningButton";
|
|
||||||
|
|
||||||
|
|
||||||
export {
|
|
||||||
Button,
|
|
||||||
DangerButton,
|
|
||||||
DarkButton,
|
|
||||||
InfoButton,
|
|
||||||
LightButton,
|
|
||||||
MoltenButton,
|
|
||||||
PrimaryButton,
|
|
||||||
SecondaryButton,
|
|
||||||
SuccessButton,
|
|
||||||
TertiaryButton,
|
|
||||||
WarningButton
|
|
||||||
};
|
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
import type { ButtonProps } from "$/types/ButtonTypes";
|
import type { ButtonProps } from "$/types/ButtonTypes";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { forwardRef } from "react";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Button = forwardRef<HTMLButtonElement, ButtonProps>((
|
export default function Button({
|
||||||
{
|
|
||||||
className,
|
className,
|
||||||
type="button",
|
type="button",
|
||||||
rounding = "lg",
|
rounding = "lg",
|
||||||
@@ -14,18 +12,16 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>((
|
|||||||
variant = "standard",
|
variant = "standard",
|
||||||
disabled,
|
disabled,
|
||||||
...buttonProps
|
...buttonProps
|
||||||
}, ref ) => {
|
}: Readonly<ButtonProps>){
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
data-testid="mattrixwv-button"
|
data-testid="mattrixwv-button"
|
||||||
ref={ref}
|
|
||||||
type={type}
|
type={type}
|
||||||
{...buttonProps}
|
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
//Focus
|
//Focus
|
||||||
"focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
|
||||||
//Rounding
|
//Rounding
|
||||||
{
|
{
|
||||||
"rounded-sm": rounding === "sm",
|
"rounded-sm": rounding === "sm",
|
||||||
@@ -58,9 +54,7 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>((
|
|||||||
"cursor-not-allowed opacity-75": disabled
|
"cursor-not-allowed opacity-75": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
{...buttonProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
export default Button;
|
|
||||||
|
|||||||
@@ -3,45 +3,43 @@ import clsx from "clsx";
|
|||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
|
|
||||||
|
|
||||||
export default function DangerButton(props: ButtonProps){
|
|
||||||
const {
|
export default function DangerButton({
|
||||||
className,
|
className,
|
||||||
variant = "standard",
|
variant = "standard",
|
||||||
disabled
|
disabled,
|
||||||
} = props;
|
...buttonProps
|
||||||
|
}: Readonly<ButtonProps>){
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
data-testid="mattrixwv-danger-button"
|
data-testid="mattrixwv-danger-button"
|
||||||
{...props}
|
variant={variant}
|
||||||
|
disabled={disabled}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"transition duration-300",
|
"transition duration-300",
|
||||||
className,
|
className,
|
||||||
//Background
|
//Background
|
||||||
{
|
{
|
||||||
"bg-red-600 hover:bg-red-700 active:bg-red-800": (variant === "standard") && (!disabled),
|
"bg-danger active:bg-danger-dark": (variant === "standard") && (!disabled),
|
||||||
"bg-red-400/80": (variant === "standard") && (disabled),
|
"bg-danger-light/80": (variant === "standard") && (disabled),
|
||||||
"bg-transparent": (variant === "outline" || variant === "icon"),
|
"bg-transparent": (variant === "outline" || variant === "icon"),
|
||||||
"bg-transparent hover:bg-red-600 active:bg-red-700": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"bg-transparent hover:bg-danger active:bg-danger-dark": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
||||||
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
||||||
},
|
},
|
||||||
//Outline
|
//Outline
|
||||||
{
|
{
|
||||||
"border-red-600 hover:border-red-700 active:border-red-800": (variant === "standard" || variant === "outline") && (!disabled),
|
"border-danger active:border-danger-dark": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (!disabled),
|
||||||
"border-red-400/80": (variant === "standard" || variant === "outline") && (disabled),
|
"border-danger-light/80": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (disabled)
|
||||||
"border-red-600 hover:border-red-600 active:border-red-700": (variant === "outline-ghost") && (!disabled),
|
|
||||||
"border-red-400/80 ": (variant === "outline-ghost") && (disabled)
|
|
||||||
},
|
},
|
||||||
//Text
|
//Text
|
||||||
{
|
{
|
||||||
"text-white": variant === "standard",
|
"text-white": variant === "standard",
|
||||||
"text-red-600 hover:text-red-700 active:text-red-800": (variant === "outline" || variant === "icon") && (!disabled),
|
"text-danger active:text-danger-dark": (variant === "outline" || variant === "icon") && (!disabled),
|
||||||
"text-red-400/80": (variant === "outline" || variant === "icon") && (disabled),
|
"text-danger-light/80": (variant === "outline" || variant === "icon" || variant === "ghost" || variant === "outline-ghost") && (disabled),
|
||||||
"text-red-600 hover:text-white active:text-white": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"text-danger hover:text-white active:text-white": (variant === "ghost" || variant === "outline-ghost") && (!disabled)
|
||||||
"text-red-400/80 ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
{...buttonProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,45 +3,42 @@ import clsx from "clsx";
|
|||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
|
|
||||||
|
|
||||||
export default function DarkButton(props: ButtonProps){
|
export default function DarkButton({
|
||||||
const {
|
|
||||||
className,
|
className,
|
||||||
variant = "standard",
|
variant = "standard",
|
||||||
disabled
|
disabled,
|
||||||
} = props;
|
...buttonProps
|
||||||
|
}: Readonly<ButtonProps>){
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
data-testid="mattrixwv-dark-button"
|
data-testid="mattrixwv-dark-button"
|
||||||
{...props}
|
variant={variant}
|
||||||
|
disabled={disabled}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"transition duration-300",
|
"transition duration-300",
|
||||||
className,
|
className,
|
||||||
//Background
|
//Background
|
||||||
{
|
{
|
||||||
"bg-black hover:bg-neutral-700 active:bg-neutral-600": (variant === "standard") && (!disabled),
|
"bg-dark active:bg-dark-mid": (variant === "standard") && (!disabled),
|
||||||
"bg-neutral-700/80": (variant === "standard") && (disabled),
|
"bg-dark-mid/80": (variant === "standard") && (disabled),
|
||||||
"bg-transparent": (variant === "outline" || variant === "icon"),
|
"bg-transparent": (variant === "outline" || variant === "icon"),
|
||||||
"bg-transparent hover:bg-black active:bg-neutral-700": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"bg-transparent hover:bg-dark active:bg-dark-mid": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
||||||
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
||||||
},
|
},
|
||||||
//Outline
|
//Outline
|
||||||
{
|
{
|
||||||
"border-black hover:border-neutral-700 active:border-neutral-600": (variant === "standard" || variant === "outline") && (!disabled),
|
"border-dark active:border-dark-mid": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (!disabled),
|
||||||
"border-neutral-700/80": (variant === "standard" || variant === "outline") && (disabled),
|
"border-dark-mid/80": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (disabled)
|
||||||
"border-black hover:border-black active:border-neutral-700": (variant === "outline-ghost") && (!disabled),
|
|
||||||
"border-neutral-700/80 ": (variant === "outline-ghost") && (disabled)
|
|
||||||
},
|
},
|
||||||
//Text
|
//Text
|
||||||
{
|
{
|
||||||
"text-white": variant === "standard",
|
"text-white": variant === "standard",
|
||||||
"text-black hover:text-neutral-700 active:text-neutral-600": (variant === "outline" || variant === "icon") && (!disabled),
|
"text-dark active:text-dark-mid": (variant === "outline" || variant === "icon") && (!disabled),
|
||||||
"text-neutral-700/80": (variant === "outline" || variant === "icon") && (disabled),
|
"text-dark-mid/80": (variant === "outline" || variant === "icon" || variant === "ghost" || variant === "outline-ghost") && (disabled),
|
||||||
"text-black hover:text-white active:text-white": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"text-dark hover:text-white active:text-white": (variant === "ghost" || variant === "outline-ghost") && (!disabled)
|
||||||
"text-neutral-700/80 ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
{...buttonProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,45 +3,42 @@ import clsx from "clsx";
|
|||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
|
|
||||||
|
|
||||||
export default function InfoButton(props: ButtonProps){
|
export default function InfoButton({
|
||||||
const {
|
|
||||||
className,
|
className,
|
||||||
variant = "standard",
|
variant = "standard",
|
||||||
disabled
|
disabled,
|
||||||
} = props;
|
...buttonProps
|
||||||
|
}: Readonly<ButtonProps>){
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
data-testid="mattrixwv-info-button"
|
data-testid="mattrixwv-info-button"
|
||||||
{...props}
|
variant={variant}
|
||||||
|
disabled={disabled}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"transition duration-300",
|
"transition duration-300",
|
||||||
className,
|
className,
|
||||||
//Background
|
//Background
|
||||||
{
|
{
|
||||||
"bg-cyan-500 hover:bg-cyan-600 active:bg-cyan-700": (variant === "standard") && (!disabled),
|
"bg-info active:bg-info-dark": (variant === "standard") && (!disabled),
|
||||||
"bg-sky-300/80": (variant === "standard") && (disabled),
|
"bg-info-light/80": (variant === "standard") && (disabled),
|
||||||
"bg-transparent": (variant === "outline" || variant === "icon"),
|
"bg-transparent": (variant === "outline" || variant === "icon"),
|
||||||
"bg-transparent hover:bg-cyan-500 active:bg-cyan-600": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"bg-transparent hover:bg-info active:bg-info-dark": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
||||||
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
||||||
},
|
},
|
||||||
//Outline
|
//Outline
|
||||||
{
|
{
|
||||||
"border-cyan-500 hover:border-cyan-600 active:border-cyan-700": (variant === "standard" || variant === "outline") && (!disabled),
|
"border-info active:border-info-dark": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (!disabled),
|
||||||
"border-sky-300/80": (variant === "standard" || variant === "outline") && (disabled),
|
"border-info-light/80": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (disabled)
|
||||||
"border-cyan-500 hover:border-cyan-500 active:border-cyan-600": (variant === "outline-ghost") && (!disabled),
|
|
||||||
"border-sky-300/80 ": (variant === "outline-ghost") && (disabled)
|
|
||||||
},
|
},
|
||||||
//Text
|
//Text
|
||||||
{
|
{
|
||||||
"text-black": variant === "standard",
|
"text-black": variant === "standard",
|
||||||
"text-cyan-500 hover:text-cyan-600 active:text-cyan-700": (variant === "outline" || variant === "icon") && (!disabled),
|
"text-info active:text-info-dark": (variant === "outline" || variant === "icon") && (!disabled),
|
||||||
"text-sky-300/80": (variant === "outline" || variant === "icon") && (disabled),
|
"text-info-light/80": (variant === "outline" || variant === "icon" || variant === "ghost" || variant === "outline-ghost") && (disabled),
|
||||||
"text-cyan-500 hover:text-black active:text-black": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"text-info hover:text-black active:text-black": (variant === "ghost" || variant === "outline-ghost") && (!disabled)
|
||||||
"text-sky-300/80 ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
{...buttonProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,45 +3,42 @@ import clsx from "clsx";
|
|||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
|
|
||||||
|
|
||||||
export default function LightButton(props: ButtonProps){
|
export default function LightButton({
|
||||||
const {
|
|
||||||
className,
|
className,
|
||||||
variant = "standard",
|
variant = "standard",
|
||||||
disabled
|
disabled,
|
||||||
} = props;
|
...buttonProps
|
||||||
|
}: Readonly<ButtonProps>){
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
data-testid="mattrixwv-light-button"
|
data-testid="mattrixwv-light-button"
|
||||||
{...props}
|
variant={variant}
|
||||||
|
disabled={disabled}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"transition duration-300",
|
"transition duration-300",
|
||||||
className,
|
className,
|
||||||
//Background
|
//Background
|
||||||
{
|
{
|
||||||
"bg-white hover:bg-neutral-300 active:bg-neutral-400": (variant === "standard") && (!disabled),
|
"bg-light active:bg-light-dark": (variant === "standard") && (!disabled),
|
||||||
"bg-neutral-400/80": (variant === "standard") && (disabled),
|
"bg-light-light/80": (variant === "standard") && (disabled),
|
||||||
"bg-transparent": (variant === "outline" || variant === "icon"),
|
"bg-transparent": (variant === "outline" || variant === "icon"),
|
||||||
"bg-transparent hover:bg-white active:bg-neutral-300": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"bg-transparent hover:bg-light active:bg-light-dark": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
||||||
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
||||||
},
|
},
|
||||||
//Outline
|
//Outline
|
||||||
{
|
{
|
||||||
"border-white hover:border-neutral-300 active:border-neutral-400": (variant === "standard" || variant === "outline") && (!disabled),
|
"border-light active:border-light-dark": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (!disabled),
|
||||||
"border-neutral-400/80": (variant === "standard" || variant === "outline") && (disabled),
|
"border-light-light/80": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (disabled)
|
||||||
"border-white hover:border-white active:border-neutral-300": (variant === "outline-ghost") && (!disabled),
|
|
||||||
"border-neutral-400/80 ": (variant === "outline-ghost") && (disabled)
|
|
||||||
},
|
},
|
||||||
//Text
|
//Text
|
||||||
{
|
{
|
||||||
"text-black": variant === "standard",
|
"text-black": variant === "standard",
|
||||||
"text-white hover:text-neutral-300 active:text-neutral-400": (variant === "outline" || variant === "icon") && (!disabled),
|
"text-light active:text-light-dark": (variant === "outline" || variant === "icon") && (!disabled),
|
||||||
"text-neutral-400/80": (variant === "outline" || variant === "icon") && (disabled),
|
"text-light-light/80": (variant === "outline" || variant === "icon" || variant === "ghost" || variant === "outline-ghost") && (disabled),
|
||||||
"text-white hover:text-black active:text-black": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"text-light hover:text-black active:text-black": (variant === "ghost" || variant === "outline-ghost") && (!disabled)
|
||||||
"text-neutral-400/80 ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
{...buttonProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,45 +3,42 @@ import clsx from "clsx";
|
|||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
|
|
||||||
|
|
||||||
export default function MoltenButton(props: ButtonProps){
|
export default function MoltenButton({
|
||||||
const {
|
|
||||||
className,
|
className,
|
||||||
variant = "standard",
|
variant = "standard",
|
||||||
disabled
|
disabled,
|
||||||
} = props;
|
...buttonProps
|
||||||
|
}: Readonly<ButtonProps>){
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
data-testid="mattrixwv-molten-button"
|
data-testid="mattrixwv-molten-button"
|
||||||
{...props}
|
variant={variant}
|
||||||
|
disabled={disabled}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"transition duration-300",
|
"transition duration-300",
|
||||||
className,
|
className,
|
||||||
//Background
|
//Background
|
||||||
{
|
{
|
||||||
"bg-orange-600 hover:bg-orange-700 active:bg-orange-800": (variant === "standard") && (!disabled),
|
"bg-molten active:bg-molten-dark": (variant === "standard") && (!disabled),
|
||||||
"bg-orange-400/80": (variant === "standard") && (disabled),
|
"bg-molten-light/80": (variant === "standard") && (disabled),
|
||||||
"bg-transparent": (variant === "outline" || variant === "icon"),
|
"bg-transparent": (variant === "outline" || variant === "icon"),
|
||||||
"bg-transparent hover:bg-orange-600 active:bg-orange-700": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"bg-transparent hover:bg-molten active:bg-molten-dark": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
||||||
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
||||||
},
|
},
|
||||||
//Outline
|
//Outline
|
||||||
{
|
{
|
||||||
"border-orange-600 hover:border-orange-700 active:border-orange-800": (variant === "standard" || variant === "outline") && (!disabled),
|
"border-molten active:border-molten-dark": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (!disabled),
|
||||||
"border-orange-400/80": (variant === "standard" || variant === "outline") && (disabled),
|
"border-molten-light/80": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (disabled)
|
||||||
"border-orange-600 hover:border-orange-600 active:border-orange-700": (variant === "outline-ghost") && (!disabled),
|
|
||||||
"border-orange-400/80 ": (variant === "outline-ghost") && (disabled)
|
|
||||||
},
|
},
|
||||||
//Text
|
//Text
|
||||||
{
|
{
|
||||||
"text-white": variant === "standard",
|
"text-black": variant === "standard",
|
||||||
"text-orange-600 hover:text-orange-700 active:text-orange-800": (variant === "outline" || variant === "icon") && (!disabled),
|
"text-molten active:text-molten-dark": (variant === "outline" || variant === "icon") && (!disabled),
|
||||||
"text-orange-400/80": (variant === "outline" || variant === "icon") && (disabled),
|
"text-molten-light/80": (variant === "outline" || variant === "icon" || variant === "ghost" || variant === "outline-ghost") && (disabled),
|
||||||
"text-orange-600 hover:text-white active:text-white": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"text-molten hover:text-black active:text-black": (variant === "ghost" || variant === "outline-ghost") && (!disabled)
|
||||||
"text-orange-400/80 ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
{...buttonProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -3,45 +3,42 @@ import clsx from "clsx";
|
|||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
|
|
||||||
|
|
||||||
export default function PrimaryButton(props: ButtonProps){
|
export default function PrimaryButton({
|
||||||
const {
|
|
||||||
className,
|
className,
|
||||||
variant = "standard",
|
variant = "standard",
|
||||||
disabled
|
disabled,
|
||||||
} = props;
|
...buttonProps
|
||||||
|
}: Readonly<ButtonProps>){
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
data-testid="mattrixwv-primary-button"
|
data-testid="mattrixwv-primary-button"
|
||||||
{...props}
|
variant={variant}
|
||||||
|
disabled={disabled}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"transition duration-300",
|
"transition duration-300",
|
||||||
className,
|
className,
|
||||||
//Background
|
//Background
|
||||||
{
|
{
|
||||||
"bg-blue-600 hover:bg-blue-700 active:bg-blue-800": (variant === "standard") && (!disabled),
|
"bg-primary active:bg-primary-dark": (variant === "standard") && (!disabled),
|
||||||
"bg-blue-400/80": (variant === "standard") && (disabled),
|
"bg-primary-light/80": (variant === "standard") && (disabled),
|
||||||
"bg-transparent": (variant === "outline" || variant === "icon"),
|
"bg-transparent": (variant === "outline" || variant === "icon"),
|
||||||
"bg-transparent hover:bg-blue-600 active:bg-blue-700": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"bg-transparent hover:bg-primary active:bg-primary-dark": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
||||||
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
||||||
},
|
},
|
||||||
//Outline
|
//Outline
|
||||||
{
|
{
|
||||||
"border-blue-600 hover:border-blue-700 active:border-blue-800": (variant === "standard" || variant === "outline") && (!disabled),
|
"border-primary active:border-primary-dark": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (!disabled),
|
||||||
"border-blue-400/80": (variant === "standard" || variant === "outline") && (disabled),
|
"border-primary-light/80": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (disabled)
|
||||||
"border-blue-600 hover:border-blue-600 active:border-blue-700": (variant === "outline-ghost") && (!disabled),
|
|
||||||
"border-blue-400/80 ": (variant === "outline-ghost") && (disabled)
|
|
||||||
},
|
},
|
||||||
//Text
|
//Text
|
||||||
{
|
{
|
||||||
"text-white": variant === "standard",
|
"text-white": variant === "standard",
|
||||||
"text-blue-600 hover:text-blue-700 active:text-blue-800": (variant === "outline" || variant === "icon") && (!disabled),
|
"text-primary active:text-primary-dark": (variant === "outline" || variant === "icon") && (!disabled),
|
||||||
"text-blue-400/80": (variant === "outline" || variant === "icon") && (disabled),
|
"text-primary-light/80": (variant === "outline" || variant === "icon" || variant === "ghost" || variant === "outline-ghost") && (disabled),
|
||||||
"text-blue-600 hover:text-white active:text-white": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"text-primary hover:text-white active:text-white": (variant === "ghost" || variant === "outline-ghost") && (!disabled)
|
||||||
"text-blue-400/80 ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
{...buttonProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,45 +3,42 @@ import clsx from "clsx";
|
|||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
|
|
||||||
|
|
||||||
export default function SecondaryButton(props: ButtonProps){
|
export default function SecondaryButton({
|
||||||
const {
|
|
||||||
className,
|
className,
|
||||||
variant = "standard",
|
variant = "standard",
|
||||||
disabled
|
disabled,
|
||||||
} = props;
|
...buttonProps
|
||||||
|
}: Readonly<ButtonProps>){
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
data-testid="mattrixwv-secondary-button"
|
data-testid="mattrixwv-secondary-button"
|
||||||
{...props}
|
variant={variant}
|
||||||
|
disabled={disabled}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"transition duration-300",
|
"transition duration-300",
|
||||||
className,
|
className,
|
||||||
//Background
|
//Background
|
||||||
{
|
{
|
||||||
"bg-neutral-500 hover:bg-neutral-600 active:bg-neutral-700": (variant === "standard") && (!disabled),
|
"bg-secondary active:bg-secondary-dark": (variant === "standard") && (!disabled),
|
||||||
"bg-neutral-300/80": (variant === "standard") && (disabled),
|
"bg-secondary-light/80": (variant === "standard") && (disabled),
|
||||||
"bg-transparent": (variant === "outline" || variant === "icon"),
|
"bg-transparent": (variant === "outline" || variant === "icon"),
|
||||||
"bg-transparent hover:bg-neutral-500 active:bg-neutral-600": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"bg-transparent hover:bg-secondary active:bg-secondary-dark": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
||||||
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
||||||
},
|
},
|
||||||
//Outline
|
//Outline
|
||||||
{
|
{
|
||||||
"border-neutral-500 hover:border-neutral-600 active:border-neutral-700": (variant === "standard" || variant === "outline") && (!disabled),
|
"border-secondary active:border-secondary-dark": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (!disabled),
|
||||||
"border-neutral-300/80": (variant === "standard" || variant === "outline") && (disabled),
|
"border-secondary-light/80": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (disabled)
|
||||||
"border-neutral-500 hover:border-neutral-500 active:border-neutral-600": (variant === "outline-ghost") && (!disabled),
|
|
||||||
"border-neutral-300/80 ": (variant === "outline-ghost") && (disabled)
|
|
||||||
},
|
},
|
||||||
//Text
|
//Text
|
||||||
{
|
{
|
||||||
"text-white": variant === "standard",
|
"text-white": variant === "standard",
|
||||||
"text-neutral-500 hover:text-neutral-600 active:text-neutral-700": (variant === "outline" || variant === "icon") && (!disabled),
|
"text-secondary active:text-secondary-dark": (variant === "outline" || variant === "icon") && (!disabled),
|
||||||
"text-neutral-300/80": (variant === "outline" || variant === "icon") && (disabled),
|
"text-secondary-light/80": (variant === "outline" || variant === "icon" || variant === "ghost" || variant === "outline-ghost") && (disabled),
|
||||||
"text-neutral-500 hover:text-black active:text-black": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"text-secondary hover:text-white active:text-white": (variant === "ghost" || variant === "outline-ghost") && (!disabled)
|
||||||
"text-neutral-300/80 ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
{...buttonProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,45 +3,42 @@ import clsx from "clsx";
|
|||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
|
|
||||||
|
|
||||||
export default function SuccessButton(props: ButtonProps){
|
export default function SuccessButton({
|
||||||
const {
|
|
||||||
className,
|
className,
|
||||||
variant = "standard",
|
variant = "standard",
|
||||||
disabled
|
disabled,
|
||||||
} = props;
|
...buttonProps
|
||||||
|
}: Readonly<ButtonProps>){
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
data-testid="mattrixwv-success-button"
|
data-testid="mattrixwv-success-button"
|
||||||
{...props}
|
variant={variant}
|
||||||
|
disabled={disabled}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"transition duration-300",
|
"transition duration-300",
|
||||||
className,
|
className,
|
||||||
//Background
|
//Background
|
||||||
{
|
{
|
||||||
"bg-green-600 hover:bg-green-700 active:bg-green-800": (variant === "standard") && (!disabled),
|
"bg-success active:bg-success-dark": (variant === "standard") && (!disabled),
|
||||||
"bg-green-400/80": (variant === "standard") && (disabled),
|
"bg-success-light/80": (variant === "standard") && (disabled),
|
||||||
"bg-transparent": (variant === "outline" || variant === "icon"),
|
"bg-transparent": (variant === "outline" || variant === "icon"),
|
||||||
"bg-transparent hover:bg-green-600 active:bg-green-700": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"bg-transparent hover:bg-success active:bg-success-dark": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
||||||
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
||||||
},
|
},
|
||||||
//Outline
|
//Outline
|
||||||
{
|
{
|
||||||
"border-green-600 hover:border-green-700 active:border-green-800": (variant === "standard" || variant === "outline") && (!disabled),
|
"border-success active:border-success-dark": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (!disabled),
|
||||||
"border-green-400/80": (variant === "standard" || variant === "outline") && (disabled),
|
"border-success-light/80": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (disabled)
|
||||||
"border-green-600 hover:border-green-600 active:border-green-700": (variant === "outline-ghost") && (!disabled),
|
|
||||||
"border-green-400/80 ": (variant === "outline-ghost") && (disabled)
|
|
||||||
},
|
},
|
||||||
//Text
|
//Text
|
||||||
{
|
{
|
||||||
"text-white": variant === "standard",
|
"text-black": variant === "standard",
|
||||||
"text-green-600 hover:text-green-700 active:text-green-800": (variant === "outline" || variant === "icon") && (!disabled),
|
"text-success active:text-success-dark": (variant === "outline" || variant === "icon") && (!disabled),
|
||||||
"text-green-400/80": (variant === "outline" || variant === "icon") && (disabled),
|
"text-success-light/80": (variant === "outline" || variant === "icon" || variant === "ghost" || variant === "outline-ghost") && (disabled),
|
||||||
"text-green-600 hover:text-white active:text-white": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"text-success hover:text-black active:text-black": (variant === "ghost" || variant === "outline-ghost") && (!disabled)
|
||||||
"text-green-400/80 ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
{...buttonProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,45 +3,42 @@ import clsx from "clsx";
|
|||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
|
|
||||||
|
|
||||||
export default function TertiaryButton(props: ButtonProps){
|
export default function TertiaryButton({
|
||||||
const {
|
|
||||||
className,
|
className,
|
||||||
variant = "standard",
|
variant = "standard",
|
||||||
disabled
|
disabled,
|
||||||
} = props;
|
...buttonProps
|
||||||
|
}: Readonly<ButtonProps>){
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
data-testid="mattrixwv-tertiary-button"
|
data-testid="mattrixwv-tertiary-button"
|
||||||
{...props}
|
variant={variant}
|
||||||
|
disabled={disabled}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"transition duration-300",
|
"transition duration-300",
|
||||||
className,
|
className,
|
||||||
//Background
|
//Background
|
||||||
{
|
{
|
||||||
"bg-purple-600 hover:bg-purple-700 active:bg-purple-800": (variant === "standard") && (!disabled),
|
"bg-tertiary active:bg-tertiary-dark": (variant === "standard") && (!disabled),
|
||||||
"bg-purple-400/80": (variant === "standard") && (disabled),
|
"bg-tertiary-light/80": (variant === "standard") && (disabled),
|
||||||
"bg-transparent": (variant === "outline" || variant === "icon"),
|
"bg-transparent": (variant === "outline" || variant === "icon"),
|
||||||
"bg-transparent hover:bg-purple-600 active:bg-purple-700": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"bg-transparent hover:bg-tertiary active:bg-tertiary-dark": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
||||||
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
||||||
},
|
},
|
||||||
//Outline
|
//Outline
|
||||||
{
|
{
|
||||||
"border-purple-600 hover:border-purple-700 active:border-purple-800": (variant === "standard" || variant === "outline") && (!disabled),
|
"border-tertiary active:border-tertiary-dark": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (!disabled),
|
||||||
"border-purple-400/80": (variant === "standard" || variant === "outline") && (disabled),
|
"border-tertiary-light/80": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (disabled)
|
||||||
"border-purple-600 hover:border-purple-600 active:border-purple-700": (variant === "outline-ghost") && (!disabled),
|
|
||||||
"border-purple-400/80 ": (variant === "outline-ghost") && (disabled)
|
|
||||||
},
|
},
|
||||||
//Text
|
//Text
|
||||||
{
|
{
|
||||||
"text-white": variant === "standard",
|
"text-white": variant === "standard",
|
||||||
"text-purple-600 hover:text-purple-700 active:text-purple-800": (variant === "outline" || variant === "icon") && (!disabled),
|
"text-tertiary active:text-tertiary-dark": (variant === "outline" || variant === "icon") && (!disabled),
|
||||||
"text-purple-400/80": (variant === "outline" || variant === "icon") && (disabled),
|
"text-tertiary-light/80": (variant === "outline" || variant === "icon" || variant === "ghost" || variant === "outline-ghost") && (disabled),
|
||||||
"text-purple-600 hover:text-white active:text-white": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"text-tertiary hover:text-white active:text-white": (variant === "ghost" || variant === "outline-ghost") && (!disabled)
|
||||||
"text-purple-400/80 ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
{...buttonProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,45 +3,42 @@ import clsx from "clsx";
|
|||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
|
|
||||||
|
|
||||||
export default function WarningButton(props: ButtonProps){
|
export default function WarningButton({
|
||||||
const {
|
|
||||||
className,
|
className,
|
||||||
variant = "standard",
|
variant = "standard",
|
||||||
disabled
|
disabled,
|
||||||
} = props;
|
...buttonProps
|
||||||
|
}: Readonly<ButtonProps>){
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
data-testid="mattrixwv-warning-button"
|
data-testid="mattrixwv-warning-button"
|
||||||
{...props}
|
variant={variant}
|
||||||
|
disabled={disabled}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"transition duration-300",
|
"transition duration-300",
|
||||||
className,
|
className,
|
||||||
//Background
|
//Background
|
||||||
{
|
{
|
||||||
"bg-yellow-500 hover:bg-yellow-600 active:bg-yellow-700": (variant === "standard") && (!disabled),
|
"bg-warning active:bg-warning-dark": (variant === "standard") && (!disabled),
|
||||||
"bg-yellow-300/80": (variant === "standard") && (disabled),
|
"bg-warning-light/80": (variant === "standard") && (disabled),
|
||||||
"bg-transparent": (variant === "outline" || variant === "icon"),
|
"bg-transparent": (variant === "outline" || variant === "icon"),
|
||||||
"bg-transparent hover:bg-yellow-500 active:bg-yellow-600": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"bg-transparent hover:bg-warning active:bg-warning-dark": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
||||||
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
"bg-transparent ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
||||||
},
|
},
|
||||||
//Outline
|
//Outline
|
||||||
{
|
{
|
||||||
"border-yellow-500 hover:border-yellow-600 active:border-yellow-700": (variant === "standard" || variant === "outline") && (!disabled),
|
"border-warning active:border-warning-dark": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (!disabled),
|
||||||
"border-yellow-300/80": (variant === "standard" || variant === "outline") && (disabled),
|
"border-warning-light/80": (variant === "standard" || variant === "outline" || variant === "outline-ghost") && (disabled)
|
||||||
"border-yellow-500 hover:border-yellow-500 active:border-yellow-600": (variant === "outline-ghost") && (!disabled),
|
|
||||||
"border-yellow-300/80 ": (variant === "outline-ghost") && (disabled)
|
|
||||||
},
|
},
|
||||||
//Text
|
//Text
|
||||||
{
|
{
|
||||||
"text-black": variant === "standard",
|
"text-black": variant === "standard",
|
||||||
"text-yellow-500 hover:text-yellow-600 active:text-yellow-700": (variant === "outline" || variant === "icon") && (!disabled),
|
"text-warning active:text-warning-dark": (variant === "outline" || variant === "icon") && (!disabled),
|
||||||
"text-yellow-300/80": (variant === "outline" || variant === "icon") && (disabled),
|
"text-warning-light/80": (variant === "outline" || variant === "icon" || variant === "ghost" || variant === "outline-ghost") && (disabled),
|
||||||
"text-yellow-500 hover:text-black active:text-black": (variant === "ghost" || variant === "outline-ghost") && (!disabled),
|
"text-warning hover:text-black active:text-black": (variant === "ghost" || variant === "outline-ghost") && (!disabled)
|
||||||
"text-yellow-300/80 ": (variant === "ghost" || variant === "outline-ghost") && (disabled)
|
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
{...buttonProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
12
lib/component/button/index.ts
Normal file
12
lib/component/button/index.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
export { default as Button } from "./Button";
|
||||||
|
export { default as DangerButton } from "./DangerButton";
|
||||||
|
export { default as DarkButton } from "./DarkButton";
|
||||||
|
export { default as InfoButton } from "./InfoButton";
|
||||||
|
export { default as LightButton } from "./LightButton";
|
||||||
|
export { default as MoltenButton } from "./MoltenButton";
|
||||||
|
export { default as PrimaryButton } from "./PrimaryButton";
|
||||||
|
export { default as SecondaryButton } from "./SecondaryButton";
|
||||||
|
export { default as SuccessButton } from "./SuccessButton";
|
||||||
|
export { default as TertiaryButton } from "./TertiaryButton";
|
||||||
|
export { default as WarningButton } from "./WarningButton";
|
||||||
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
import DangerCheckbox from "./input/checkbox/DangerCheckbox";
|
|
||||||
import DarkCheckbox from "./input/checkbox/DarkCheckbox";
|
|
||||||
import InfoCheckbox from "./input/checkbox/InfoCheckbox";
|
|
||||||
import LightCheckbox from "./input/checkbox/LightCheckbox";
|
|
||||||
import MattrixwvCheckbox from "./input/checkbox/MattrixwvCheckbox";
|
|
||||||
import MoltenCheckbox from "./input/checkbox/MoltenCheckbox";
|
|
||||||
import PrimaryCheckbox from "./input/checkbox/PrimaryCheckbox";
|
|
||||||
import SecondaryCheckbox from "./input/checkbox/SecondaryCheckbox";
|
|
||||||
import SuccessCheckbox from "./input/checkbox/SuccessCheckbox";
|
|
||||||
import TertiaryCheckbox from "./input/checkbox/TertiaryCheckbox";
|
|
||||||
import WarningCheckbox from "./input/checkbox/WarningCheckbox";
|
|
||||||
|
|
||||||
|
|
||||||
export {
|
|
||||||
DangerCheckbox,
|
|
||||||
DarkCheckbox,
|
|
||||||
InfoCheckbox,
|
|
||||||
LightCheckbox,
|
|
||||||
MattrixwvCheckbox,
|
|
||||||
MoltenCheckbox,
|
|
||||||
PrimaryCheckbox,
|
|
||||||
SecondaryCheckbox,
|
|
||||||
SuccessCheckbox,
|
|
||||||
TertiaryCheckbox,
|
|
||||||
WarningCheckbox
|
|
||||||
};
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
import DateInput from "./input/date/DateInput";
|
|
||||||
import DateTimeInput from "./input/date/DateTimeInput";
|
|
||||||
import TimeInput from "./input/date/TimeInput";
|
|
||||||
import DragAndDropFileInput from "./input/file/DragAndDropFileInput";
|
|
||||||
import FileInput from "./input/file/FileInput";
|
|
||||||
import NumberInput from "./input/number/NumberInput";
|
|
||||||
import OptionInput from "./input/text/OptionInput";
|
|
||||||
import SelectInput from "./input/text/SelectInput";
|
|
||||||
import TextArea from "./input/text/TextArea";
|
|
||||||
import TextInput from "./input/text/TextInput";
|
|
||||||
|
|
||||||
|
|
||||||
export {
|
|
||||||
DateInput,
|
|
||||||
DateTimeInput,
|
|
||||||
DragAndDropFileInput,
|
|
||||||
FileInput,
|
|
||||||
NumberInput,
|
|
||||||
//NumberSlider,
|
|
||||||
OptionInput,
|
|
||||||
SelectInput,
|
|
||||||
TextArea,
|
|
||||||
TextInput,
|
|
||||||
TimeInput
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -5,19 +5,19 @@ import MattrixwvCheckbox from "./MattrixwvCheckbox";
|
|||||||
|
|
||||||
export default function DangerCheckbox({
|
export default function DangerCheckbox({
|
||||||
className,
|
className,
|
||||||
box = true,
|
showBox = true,
|
||||||
...props
|
...props
|
||||||
}: CheckboxProps){
|
}: Readonly<CheckboxProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvCheckbox
|
<MattrixwvCheckbox
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"group-data-checked:bg-red-600 group-data-checked:stroke-white": box,
|
"group-data-checked:bg-danger group-data-checked:stroke-white": showBox,
|
||||||
"group-data-checked:stroke-red-600": !box
|
"group-data-checked:stroke-danger": !showBox
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
box={box}
|
showBox={showBox}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,19 +5,19 @@ import MattrixwvCheckbox from "./MattrixwvCheckbox";
|
|||||||
|
|
||||||
export default function DarkCheckbox({
|
export default function DarkCheckbox({
|
||||||
className,
|
className,
|
||||||
box = true,
|
showBox = true,
|
||||||
...props
|
...props
|
||||||
}: CheckboxProps){
|
}: Readonly<CheckboxProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvCheckbox
|
<MattrixwvCheckbox
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"group-data-checked:bg-black group-data-checked:stroke-white": box,
|
"group-data-checked:bg-dark group-data-checked:stroke-light": showBox,
|
||||||
"group-data-checked:stroke-black": !box
|
"group-data-checked:stroke-dark": !showBox
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
box={box}
|
showBox={showBox}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,19 +5,19 @@ import MattrixwvCheckbox from "./MattrixwvCheckbox";
|
|||||||
|
|
||||||
export default function InfoCheckbox({
|
export default function InfoCheckbox({
|
||||||
className,
|
className,
|
||||||
box = true,
|
showBox = true,
|
||||||
...props
|
...props
|
||||||
}: CheckboxProps){
|
}: Readonly<CheckboxProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvCheckbox
|
<MattrixwvCheckbox
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"group-data-checked:bg-cyan-500 group-data-checked:stroke-white": box,
|
"group-data-checked:bg-info group-data-checked:stroke-white": showBox,
|
||||||
"group-data-checked:stroke-cyan-500": !box
|
"group-data-checked:stroke-info": !showBox
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
box={box}
|
showBox={showBox}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,19 +5,19 @@ import MattrixwvCheckbox from "./MattrixwvCheckbox";
|
|||||||
|
|
||||||
export default function LightCheckbox({
|
export default function LightCheckbox({
|
||||||
className,
|
className,
|
||||||
box = true,
|
showBox = true,
|
||||||
...props
|
...props
|
||||||
}: CheckboxProps){
|
}: Readonly<CheckboxProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvCheckbox
|
<MattrixwvCheckbox
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"group-data-checked:bg-white group-data-checked:stroke-black": box,
|
"group-data-checked:bg-light group-data-checked:stroke-dark": showBox,
|
||||||
"group-data-checked:stroke-white": !box
|
"group-data-checked:stroke-light": !showBox
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
box={box}
|
showBox={showBox}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,40 +1,50 @@
|
|||||||
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,
|
|
||||||
className,
|
className,
|
||||||
labelClassName,
|
labelClassName,
|
||||||
name,
|
name,
|
||||||
size = "sm",
|
size = "sm",
|
||||||
box = true,
|
showBox = true,
|
||||||
onChange,
|
onChange,
|
||||||
checked,
|
checked,
|
||||||
defaultChecked,
|
defaultChecked,
|
||||||
strokeWidth = 2,
|
strokeWidth = 2,
|
||||||
value,
|
value,
|
||||||
|
disabled,
|
||||||
children
|
children
|
||||||
}: 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 cursor-pointer",
|
"group",
|
||||||
"flex flex-row items-center justify-center gap-x-2"
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
|
||||||
|
{
|
||||||
|
"cursor-pointer": !disabled,
|
||||||
|
"cursor-not-allowed": disabled
|
||||||
|
}
|
||||||
)}
|
)}
|
||||||
name={name}
|
name={name}
|
||||||
checked={checked}
|
checked={checked}
|
||||||
defaultChecked={defaultChecked}
|
defaultChecked={defaultChecked}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
value={value}
|
value={value}
|
||||||
|
disabled={disabled}
|
||||||
>
|
>
|
||||||
|
{/* Checkbox */}
|
||||||
<div
|
<div
|
||||||
|
data-testid="mattrixwv-checkbox-graphic"
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"rounded border": box
|
"border rounded": showBox
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"": size === "none",
|
"": size === "none",
|
||||||
@@ -49,6 +59,7 @@ export default function MattrixwvCheckbox({
|
|||||||
<svg
|
<svg
|
||||||
viewBox="0 0 14 14"
|
viewBox="0 0 14 14"
|
||||||
fill="none"
|
fill="none"
|
||||||
|
aria-hidden="true"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
d="M3 8L6 11L11 3.5"
|
d="M3 8L6 11L11 3.5"
|
||||||
@@ -58,14 +69,17 @@ export default function MattrixwvCheckbox({
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
</Checkbox>
|
||||||
|
{/* Label */}
|
||||||
{
|
{
|
||||||
children &&
|
children &&
|
||||||
<div
|
<Label
|
||||||
|
data-testid="mattrixwv-checkbox-label"
|
||||||
className={labelClassName}
|
className={labelClassName}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</Label>
|
||||||
}
|
}
|
||||||
</Checkbox>
|
</Field>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,19 +5,19 @@ import MattrixwvCheckbox from "./MattrixwvCheckbox";
|
|||||||
|
|
||||||
export default function MoltenCheckbox({
|
export default function MoltenCheckbox({
|
||||||
className,
|
className,
|
||||||
box = true,
|
showBox = true,
|
||||||
...props
|
...props
|
||||||
}: CheckboxProps){
|
}: Readonly<CheckboxProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvCheckbox
|
<MattrixwvCheckbox
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"group-data-checked:bg-orange-600 group-data-checked:stroke-white": box,
|
"group-data-checked:bg-molten group-data-checked:stroke-white": showBox,
|
||||||
"group-data-checked:stroke-orange-600": !box
|
"group-data-checked:stroke-molten": !showBox
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
box={box}
|
showBox={showBox}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,19 +5,19 @@ import MattrixwvCheckbox from "./MattrixwvCheckbox";
|
|||||||
|
|
||||||
export default function PrimaryCheckbox({
|
export default function PrimaryCheckbox({
|
||||||
className,
|
className,
|
||||||
box = true,
|
showBox = true,
|
||||||
...props
|
...props
|
||||||
}: CheckboxProps){
|
}: Readonly<CheckboxProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvCheckbox
|
<MattrixwvCheckbox
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"group-data-checked:bg-blue-600 group-data-checked:stroke-white": box,
|
"group-data-checked:bg-primary group-data-checked:stroke-white": showBox,
|
||||||
"group-data-checked:stroke-blue-600": !box
|
"group-data-checked:stroke-primary": !showBox
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
box={box}
|
showBox={showBox}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,19 +5,19 @@ import MattrixwvCheckbox from "./MattrixwvCheckbox";
|
|||||||
|
|
||||||
export default function SecondaryCheckbox({
|
export default function SecondaryCheckbox({
|
||||||
className,
|
className,
|
||||||
box = true,
|
showBox = true,
|
||||||
...props
|
...props
|
||||||
}: CheckboxProps){
|
}: Readonly<CheckboxProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvCheckbox
|
<MattrixwvCheckbox
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"group-data-checked:bg-neutral-600 group-data-checked:stroke-white": box,
|
"group-data-checked:bg-secondary group-data-checked:stroke-white": showBox,
|
||||||
"group-data-checked:stroke-neutral-600": !box
|
"group-data-checked:stroke-secondary": !showBox
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
box={box}
|
showBox={showBox}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,21 +5,20 @@ import MattrixwvCheckbox from "./MattrixwvCheckbox";
|
|||||||
|
|
||||||
export default function SuccessCheckbox({
|
export default function SuccessCheckbox({
|
||||||
className,
|
className,
|
||||||
box = true,
|
showBox = true,
|
||||||
...props
|
...props
|
||||||
}: CheckboxProps){
|
}: Readonly<CheckboxProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvCheckbox
|
<MattrixwvCheckbox
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"group-data-checked:bg-green-600 group-data-checked:stroke-white": box,
|
"group-data-checked:bg-success group-data-checked:stroke-white": showBox,
|
||||||
"group-data-checked:stroke-green-600": !box
|
"group-data-checked:stroke-success": !showBox
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
box={box}
|
showBox={showBox}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,19 +5,19 @@ import MattrixwvCheckbox from "./MattrixwvCheckbox";
|
|||||||
|
|
||||||
export default function TertiaryCheckbox({
|
export default function TertiaryCheckbox({
|
||||||
className,
|
className,
|
||||||
box = true,
|
showBox = true,
|
||||||
...props
|
...props
|
||||||
}: CheckboxProps){
|
}: Readonly<CheckboxProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvCheckbox
|
<MattrixwvCheckbox
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"group-data-checked:bg-purple-600 group-data-checked:stroke-white": box,
|
"group-data-checked:bg-tertiary group-data-checked:stroke-white": showBox,
|
||||||
"group-data-checked:stroke-purple-600": !box
|
"group-data-checked:stroke-tertiary": !showBox
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
box={box}
|
showBox={showBox}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,19 +5,19 @@ import MattrixwvCheckbox from "./MattrixwvCheckbox";
|
|||||||
|
|
||||||
export default function WarningCheckbox({
|
export default function WarningCheckbox({
|
||||||
className,
|
className,
|
||||||
box = true,
|
showBox = true,
|
||||||
...props
|
...props
|
||||||
}: CheckboxProps){
|
}: Readonly<CheckboxProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvCheckbox
|
<MattrixwvCheckbox
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"group-data-checked:bg-yellow-500 group-data-checked:stroke-white": box,
|
"group-data-checked:bg-warning group-data-checked:stroke-white": showBox,
|
||||||
"group-data-checked:stroke-yellow-500": !box
|
"group-data-checked:stroke-warning": !showBox
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
box={box}
|
showBox={showBox}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,26 +1,47 @@
|
|||||||
import type { DateInputProps } from "$/types/InputTypes";
|
import type { DateInputProps } from "$/types/InputTypes";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import moment from "moment";
|
import { type ChangeEvent } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function DateInput({
|
export default function DateInput({
|
||||||
id,
|
|
||||||
className,
|
className,
|
||||||
defaultValue,
|
|
||||||
value,
|
value,
|
||||||
onChange
|
onChange,
|
||||||
}: DateInputProps){
|
...inputProps
|
||||||
|
}: Readonly<DateInputProps>){
|
||||||
|
//Used to translate the string from the input to a date for onChange
|
||||||
|
const changeDate = (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const [ year, month, day ] = e.target.value.split("-").map(Number);
|
||||||
|
const newDate = new Date(year, month - 1, day);
|
||||||
|
|
||||||
|
onChange(Number.isNaN(newDate.getTime()) ? undefined : newDate);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
id={id}
|
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"border rounded-lg px-2 py-1",
|
"border rounded-lg px-2 py-1",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
defaultValue={defaultValue ? moment(defaultValue).format("YYYY-MM-DD") : undefined}
|
value={formatDate(value)}
|
||||||
value={value ? moment(value).format("YYYY-MM-DD") : undefined}
|
onChange={changeDate}
|
||||||
onChange={(e) => onChange?.(new Date(moment(e.target.value, "YYYY-MM-DD").toDate()))}
|
{...inputProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Used to translate the date to a string for the input
|
||||||
|
function formatDate(date: Date | undefined): string{
|
||||||
|
if(!date || Number.isNaN(date.getTime())){
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||||
|
const day = String(date.getDate()).padStart(2, "0");
|
||||||
|
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,15 +1,38 @@
|
|||||||
import type { DateInputProps } from "$/types/InputTypes";
|
import type { DateInputProps } from "$/types/InputTypes";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import moment from "moment";
|
import type { ChangeEvent } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function DateTimeInput({
|
export default function DateTimeInput({
|
||||||
id,
|
id,
|
||||||
className,
|
className,
|
||||||
defaultValue,
|
step = 60,
|
||||||
value,
|
value,
|
||||||
onChange
|
onChange,
|
||||||
}: DateInputProps){
|
...inputProps
|
||||||
|
}: Readonly<DateInputProps>){
|
||||||
|
const changeDateTime = (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const match = new RegExp(/^(\d+)-(\d+)-(\d+)T(\d+):(\d+)(?::(\d+)(?:\.(\d+))?)?$/).exec(e.target.value);
|
||||||
|
|
||||||
|
if(!match){
|
||||||
|
onChange(undefined);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [ ,
|
||||||
|
y, mo, d,
|
||||||
|
h, mi, s = "0", ms = "0"
|
||||||
|
] = match;
|
||||||
|
|
||||||
|
const date = new Date(
|
||||||
|
Number(y), Number(mo) - 1, Number(d),
|
||||||
|
Number(h), Number(mi), Number(s), Number(ms)
|
||||||
|
);
|
||||||
|
|
||||||
|
onChange(Number.isNaN(date.getTime()) ? undefined : date);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
type="datetime-local"
|
type="datetime-local"
|
||||||
@@ -18,9 +41,28 @@ export default function DateTimeInput({
|
|||||||
"border rounded-lg px-2 py-1 outline-none",
|
"border rounded-lg px-2 py-1 outline-none",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
defaultValue={defaultValue ? moment(defaultValue).format("YYYY-MM-DDTHH:mm") : undefined}
|
value={formatDateTime(value)}
|
||||||
value={value ? moment(value).format("YYYY-MM-DDTHH:mm") : undefined}
|
onChange={changeDateTime}
|
||||||
onChange={(e) => onChange?.(new Date(moment(e.target.value, "YYYY-MM-DDTHH:mm").toDate()))}
|
step={step}
|
||||||
|
{...inputProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function formatDateTime(date: Date | undefined){
|
||||||
|
if(!date || Number.isNaN(date.getTime())){
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const y = date.getFullYear();
|
||||||
|
const mo = String(date.getMonth() + 1).padStart(2, "0");
|
||||||
|
const d = String(date.getDate()).padStart(2, "0");
|
||||||
|
|
||||||
|
const h = String(date.getHours()).padStart(2, "0");
|
||||||
|
const mi = String(date.getMinutes()).padStart(2, "0");
|
||||||
|
const s = String(date.getSeconds()).padStart(2, "0");
|
||||||
|
const ms = String(date.getMilliseconds()).padStart(2, "0");
|
||||||
|
|
||||||
|
return `${y}-${mo}-${d}T${h}:${mi}:${s}.${ms}`;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,15 +1,33 @@
|
|||||||
import type { DateInputProps } from "$/types/InputTypes";
|
import type { DateInputProps } from "$/types/InputTypes";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import moment from "moment";
|
import type { ChangeEvent } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function TimeInput({
|
export default function TimeInput({
|
||||||
id,
|
id,
|
||||||
className,
|
className,
|
||||||
defaultValue,
|
step = 60,
|
||||||
value,
|
value,
|
||||||
onChange
|
onChange,
|
||||||
}: DateInputProps){
|
...inputProps
|
||||||
|
}: Readonly<DateInputProps>){
|
||||||
|
const changeTime = (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const match = new RegExp(/^(\d+):(\d+)(?::(\d+)(?:\.(\d+))?)?$/).exec(e.target.value);
|
||||||
|
|
||||||
|
if(!match){
|
||||||
|
onChange(undefined);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [ , h, m, s = "0", ms = "0"] = match;
|
||||||
|
|
||||||
|
const newDate = new Date();
|
||||||
|
newDate.setHours(Number(h), Number(m), Number(s), Number(ms));
|
||||||
|
|
||||||
|
onChange(Number.isNaN(newDate) ? undefined : newDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
type="time"
|
type="time"
|
||||||
@@ -18,9 +36,32 @@ export default function TimeInput({
|
|||||||
"border rounded-lg px-2 py-1 outline-none",
|
"border rounded-lg px-2 py-1 outline-none",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
defaultValue={defaultValue ? moment(defaultValue).format("YYYY-MM-DDTHH:mm") : undefined}
|
value={formatTime(value, step)}
|
||||||
value={value ? moment(value).format("YYYY-MM-DDTHH:mm") : undefined}
|
onChange={changeTime}
|
||||||
onChange={(e) => onChange?.(new Date(moment(e.target.value, "YYYY-MM-DDTHH:mm").toDate()))}
|
step={step}
|
||||||
|
{...inputProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function formatTime(date: Date | undefined, step: number){
|
||||||
|
if(!date || Number.isNaN(date.getTime())){
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const h = String(date.getHours()).padStart(2, "0");
|
||||||
|
const m = String(date.getMinutes()).padStart(2, "0");
|
||||||
|
const s = String(date.getSeconds()).padStart(2, "0");
|
||||||
|
const ms = String(date.getMilliseconds()).padStart(3, "0");
|
||||||
|
|
||||||
|
let time = `${h}:${m}`;
|
||||||
|
if(step < 60){
|
||||||
|
time += `:${s}`;
|
||||||
|
}
|
||||||
|
if(step < 1){
|
||||||
|
time += `.${ms}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
55
lib/component/input/index.ts
Normal file
55
lib/component/input/index.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
//? Checkboxes
|
||||||
|
export { default as DangerCheckbox } from "./checkbox/DangerCheckbox";
|
||||||
|
export { default as DarkCheckbox } from "./checkbox/DarkCheckbox";
|
||||||
|
export { default as InfoCheckbox } from "./checkbox/InfoCheckbox";
|
||||||
|
export { default as LightCheckbox } from "./checkbox/LightCheckbox";
|
||||||
|
export { default as MattrixwvCheckbox } from "./checkbox/MattrixwvCheckbox";
|
||||||
|
export { default as MoltenCheckbox } from "./checkbox/MoltenCheckbox";
|
||||||
|
export { default as PrimaryCheckbox } from "./checkbox/PrimaryCheckbox";
|
||||||
|
export { default as SecondaryCheckbox } from "./checkbox/SecondaryCheckbox";
|
||||||
|
export { default as SuccessCheckbox } from "./checkbox/SuccessCheckbox";
|
||||||
|
export { default as TertiaryCheckbox } from "./checkbox/TertiaryCheckbox";
|
||||||
|
export { default as WarningCheckbox } from "./checkbox/WarningCheckbox";
|
||||||
|
|
||||||
|
//? Radio Buttons
|
||||||
|
export { default as DangerRadioButton } from "./radio/DangerRadioButton";
|
||||||
|
export { default as DarkRadioButton } from "./radio/DarkRadioButton";
|
||||||
|
export { default as InfoRadioButton } from "./radio/InfoRadioButton";
|
||||||
|
export { default as LightRadioButton } from "./radio/LightRadioButton";
|
||||||
|
export { default as MoltenRadioButton } from "./radio/MoltenRadioButton";
|
||||||
|
export { default as PrimaryRadioButton } from "./radio/PrimaryRadioButton";
|
||||||
|
export { default as RadioButton } from "./radio/RadioButton";
|
||||||
|
export { default as RadioList } from "./radio/RadioList";
|
||||||
|
export { default as SecondaryRadioButton } from "./radio/SecondaryRadioButton";
|
||||||
|
export { default as SuccessRadioButton } from "./radio/SuccessRadioButton";
|
||||||
|
export { default as TertiaryRadioButton } from "./radio/TertiaryRadioButton";
|
||||||
|
export { default as WarningRadioButton } from "./radio/WarningRadioButton";
|
||||||
|
|
||||||
|
//? Switches
|
||||||
|
export { default as ButtonSwitch } from "./switch/ButtonSwitch";
|
||||||
|
export { default as DangerSwitch } from "./switch/DangerSwitch";
|
||||||
|
export { default as DarkSwitch } from "./switch/DarkSwitch";
|
||||||
|
export { default as LightSwitch } from "./switch/LightSwitch";
|
||||||
|
export { default as MattrixwvSwitch } from "./switch/MattrixwvSwitch";
|
||||||
|
export { default as PrimarySwitch } from "./switch/PrimarySwitch";
|
||||||
|
export { default as SecondarySwitch } from "./switch/SecondarySwitch";
|
||||||
|
export { default as SuccessDangerSwitch } from "./switch/SuccessDangerSwitch";
|
||||||
|
export { default as SuccessSwitch } from "./switch/SuccessSwitch";
|
||||||
|
export { default as TertiarySwitch } from "./switch/TertiarySwitch";
|
||||||
|
export { default as WarningSwitch } from "./switch/WarningSwitch";
|
||||||
|
|
||||||
|
|
||||||
|
//? Other imports
|
||||||
|
export { default as DateInput } from "./date/DateInput";
|
||||||
|
export { default as DateTimeInput } from "./date/DateTimeInput";
|
||||||
|
export { default as TimeInput } from "./date/TimeInput";
|
||||||
|
export { default as DragAndDropFileInput } from "./file/DragAndDropFileInput";
|
||||||
|
export { default as FileInput } from "./file/FileInput";
|
||||||
|
export { default as NumberInput } from "./number/NumberInput";
|
||||||
|
export { default as OptionInput } from "./text/OptionInput";
|
||||||
|
export { default as PasswordInput } from "./text/PasswordInput";
|
||||||
|
export { default as PhoneInput } from "./text/PhoneInput";
|
||||||
|
export { default as SelectInput } from "./text/SelectInput";
|
||||||
|
export { default as TextArea } from "./text/TextArea";
|
||||||
|
export { default as TextInput } from "./text/TextInput";
|
||||||
|
|
||||||
@@ -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}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import RadioButton from "./RadioButton";
|
|||||||
export default function DangerRadioButton({
|
export default function DangerRadioButton({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: RadioButtonProps){
|
}: Readonly<RadioButtonProps>){
|
||||||
return (
|
return (
|
||||||
<RadioButton
|
<RadioButton
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"group-data-checked:bg-red-600",
|
"group-data-checked:bg-danger",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import RadioButton from "./RadioButton";
|
|||||||
export default function DarkRadioButton({
|
export default function DarkRadioButton({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: RadioButtonProps){
|
}: Readonly<RadioButtonProps>){
|
||||||
return (
|
return (
|
||||||
<RadioButton
|
<RadioButton
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"group-data-checked:bg-black",
|
"group-data-checked:bg-dark",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import RadioButton from "./RadioButton";
|
|||||||
export default function InfoRadioButton({
|
export default function InfoRadioButton({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: RadioButtonProps){
|
}: Readonly<RadioButtonProps>){
|
||||||
return (
|
return (
|
||||||
<RadioButton
|
<RadioButton
|
||||||
className={clsx(
|
className={clsx(
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import RadioButton from "./RadioButton";
|
|||||||
export default function LightRadioButton({
|
export default function LightRadioButton({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: RadioButtonProps){
|
}: Readonly<RadioButtonProps>){
|
||||||
return (
|
return (
|
||||||
<RadioButton
|
<RadioButton
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"group-data-checked:bg-white",
|
"group-data-checked:bg-light",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import RadioButton from "./RadioButton";
|
|||||||
export default function MoltenRadioButton({
|
export default function MoltenRadioButton({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: RadioButtonProps){
|
}: Readonly<RadioButtonProps>){
|
||||||
return (
|
return (
|
||||||
<RadioButton
|
<RadioButton
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"group-data-checked:bg-orange-600",
|
"group-data-checked:bg-molten",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import RadioButton from "./RadioButton";
|
|||||||
export default function PrimaryRadioButton({
|
export default function PrimaryRadioButton({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: RadioButtonProps){
|
}: Readonly<RadioButtonProps>){
|
||||||
return (
|
return (
|
||||||
<RadioButton
|
<RadioButton
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"group-data-checked:bg-blue-500",
|
"group-data-checked:bg-primary",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -4,18 +4,29 @@ import clsx from "clsx";
|
|||||||
|
|
||||||
|
|
||||||
export default function RadioButton({
|
export default function RadioButton({
|
||||||
id,
|
id = crypto.randomUUID().replaceAll("-", ""),
|
||||||
className,
|
className,
|
||||||
labelClassName,
|
labelClassName,
|
||||||
size = "sm",
|
size = "sm",
|
||||||
value,
|
value,
|
||||||
|
disabled,
|
||||||
children
|
children
|
||||||
}: RadioButtonProps){
|
}: Readonly<RadioButtonProps>){
|
||||||
return (
|
return (
|
||||||
<Radio
|
<Radio
|
||||||
id={id}
|
id={id}
|
||||||
value={value}
|
value={value}
|
||||||
className="group flex flex-row items-center justify-center gap-x-2 cursor-pointer"
|
className={clsx(
|
||||||
|
"group",
|
||||||
|
"flex flex-row items-center justify-center gap-x-2",
|
||||||
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
|
||||||
|
{
|
||||||
|
"cursor-pointer": !disabled,
|
||||||
|
"cursor-not-allowed": disabled
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
disabled={disabled}
|
||||||
|
aria-labelledby={`${id}Label`}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
@@ -33,11 +44,12 @@ export default function RadioButton({
|
|||||||
/>
|
/>
|
||||||
{
|
{
|
||||||
children &&
|
children &&
|
||||||
<div
|
<span
|
||||||
|
id={`${id}Label`}
|
||||||
className={labelClassName}
|
className={labelClassName}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</span>
|
||||||
}
|
}
|
||||||
</Radio>
|
</Radio>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -12,16 +12,16 @@ export default function RadioList({
|
|||||||
defaultValue,
|
defaultValue,
|
||||||
direction = "horizontal",
|
direction = "horizontal",
|
||||||
children
|
children
|
||||||
}: RadioListProps){
|
}: Readonly<RadioListProps>){
|
||||||
return (
|
return (
|
||||||
<RadioGroup
|
<RadioGroup
|
||||||
id={id}
|
id={id}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"flex items-center justify-center",
|
"flex",
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"flex-row gap-x-8": direction === "horizontal",
|
"flex-row items-center justify-center gap-x-8": direction === "horizontal",
|
||||||
"flex-col gap-y-2": direction === "vertical"
|
"flex-col items-start justify-center gap-y-2": direction === "vertical"
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
name={name}
|
name={name}
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import RadioButton from "./RadioButton";
|
|||||||
export default function SecondaryRadioButton({
|
export default function SecondaryRadioButton({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: RadioButtonProps){
|
}: Readonly<RadioButtonProps>){
|
||||||
return (
|
return (
|
||||||
<RadioButton
|
<RadioButton
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"group-data-checked:bg-neutral-600",
|
"group-data-checked:bg-secondary",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import RadioButton from "./RadioButton";
|
|||||||
export default function SuccessRadioButton({
|
export default function SuccessRadioButton({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: RadioButtonProps){
|
}: Readonly<RadioButtonProps>){
|
||||||
return (
|
return (
|
||||||
<RadioButton
|
<RadioButton
|
||||||
className={clsx(
|
className={clsx(
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import RadioButton from "./RadioButton";
|
|||||||
export default function TertiaryRadioButton({
|
export default function TertiaryRadioButton({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: RadioButtonProps){
|
}: Readonly<RadioButtonProps>){
|
||||||
return (
|
return (
|
||||||
<RadioButton
|
<RadioButton
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"group-data-checked:bg-purple-600",
|
"group-data-checked:bg-tertiary",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import RadioButton from "./RadioButton";
|
|||||||
export default function WarningRadioButton({
|
export default function WarningRadioButton({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: RadioButtonProps){
|
}: Readonly<RadioButtonProps>){
|
||||||
return (
|
return (
|
||||||
<RadioButton
|
<RadioButton
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"group-data-checked:bg-yellow-500",
|
"group-data-checked:bg-warning",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export default function ButtonSwitch({
|
|||||||
disabled,
|
disabled,
|
||||||
onNode,
|
onNode,
|
||||||
offNode
|
offNode
|
||||||
}: MattrixwvButtonSwitchProps){
|
}: Readonly<MattrixwvButtonSwitchProps>){
|
||||||
return (
|
return (
|
||||||
<Switch
|
<Switch
|
||||||
id={id}
|
id={id}
|
||||||
|
|||||||
@@ -8,26 +8,26 @@ export default function DangerSwitch({
|
|||||||
knobClassName,
|
knobClassName,
|
||||||
disabled,
|
disabled,
|
||||||
...props
|
...props
|
||||||
}: MattrixwvSwitchProps){
|
}: Readonly<MattrixwvSwitchProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvSwitch
|
<MattrixwvSwitch
|
||||||
{...props}
|
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"bg-gray-400",
|
"bg-neutral-mid",
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"data-checked:bg-red-600": !disabled,
|
"data-checked:bg-danger": !disabled,
|
||||||
"data-checked:bg-red-400/80": disabled
|
"data-checked:bg-danger-light/80": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
knobClassName={clsx(
|
knobClassName={clsx(
|
||||||
knobClassName,
|
knobClassName,
|
||||||
{
|
{
|
||||||
"bg-white": !disabled,
|
"bg-white": !disabled,
|
||||||
"bg-gray-300": disabled
|
"bg-neutral-light": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,26 +8,26 @@ export default function DarkSwitch({
|
|||||||
knobClassName,
|
knobClassName,
|
||||||
disabled,
|
disabled,
|
||||||
...props
|
...props
|
||||||
}: MattrixwvSwitchProps){
|
}: Readonly<MattrixwvSwitchProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvSwitch
|
<MattrixwvSwitch
|
||||||
{...props}
|
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"bg-gray-400",
|
"bg-neutral-mid",
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"data-checked:bg-black": !disabled,
|
"data-checked:bg-dark": !disabled,
|
||||||
"data-checked:bg-neutral-800/80": disabled
|
"data-checked:bg-dark-mid/80": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
knobClassName={clsx(
|
knobClassName={clsx(
|
||||||
knobClassName,
|
knobClassName,
|
||||||
{
|
{
|
||||||
"bg-white": !disabled,
|
"bg-white": !disabled,
|
||||||
"bg-gray-300": disabled
|
"bg-neutral-light": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
33
lib/component/input/switch/InfoSwitch.tsx
Normal file
33
lib/component/input/switch/InfoSwitch.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import type { MattrixwvSwitchProps } from "$/types/InputTypes";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import MattrixwvSwitch from "./MattrixwvSwitch";
|
||||||
|
|
||||||
|
|
||||||
|
export default function InfoSwitch({
|
||||||
|
className,
|
||||||
|
knobClassName,
|
||||||
|
disabled,
|
||||||
|
...props
|
||||||
|
}: Readonly<MattrixwvSwitchProps>){
|
||||||
|
return (
|
||||||
|
<MattrixwvSwitch
|
||||||
|
className={clsx(
|
||||||
|
"bg-gray-400",
|
||||||
|
className,
|
||||||
|
{
|
||||||
|
"data-checked:bg-info": !disabled,
|
||||||
|
"data-checked:bg-info-light/80": disabled
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
knobClassName={clsx(
|
||||||
|
knobClassName,
|
||||||
|
{
|
||||||
|
"bg-white": !disabled,
|
||||||
|
"bg-neutral-light": disabled
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
disabled={disabled}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -8,26 +8,26 @@ export default function LightSwitch({
|
|||||||
knobClassName,
|
knobClassName,
|
||||||
disabled,
|
disabled,
|
||||||
...props
|
...props
|
||||||
}: MattrixwvSwitchProps){
|
}: Readonly<MattrixwvSwitchProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvSwitch
|
<MattrixwvSwitch
|
||||||
{...props}
|
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"bg-gray-400",
|
"bg-neutral-mid",
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"data-checked:bg-white": !disabled,
|
"data-checked:bg-light": !disabled,
|
||||||
"data-checked:bg-neutral-300/80": disabled
|
"data-checked:bg-light/80": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
knobClassName={clsx(
|
knobClassName={clsx(
|
||||||
knobClassName,
|
knobClassName,
|
||||||
{
|
{
|
||||||
"bg-black": !disabled,
|
"bg-black": !disabled,
|
||||||
"bg-neutral-800": disabled
|
"bg-neutral-dark": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export default function MattrixwvSwitch({
|
|||||||
children,
|
children,
|
||||||
offText,
|
offText,
|
||||||
onText
|
onText
|
||||||
}: MattrixwvSwitchProps){
|
}: Readonly<MattrixwvSwitchProps>){
|
||||||
return (
|
return (
|
||||||
<Field as={Fragment}>
|
<Field as={Fragment}>
|
||||||
<Switch
|
<Switch
|
||||||
@@ -29,7 +29,7 @@ export default function MattrixwvSwitch({
|
|||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"cursor-pointer": !disabled,
|
"cursor-pointer": !disabled,
|
||||||
"cursor-default": disabled
|
"cursor-not-allowed": disabled
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
//Normal
|
//Normal
|
||||||
@@ -97,7 +97,7 @@ export default function MattrixwvSwitch({
|
|||||||
className={clsx(
|
className={clsx(
|
||||||
{
|
{
|
||||||
"cursor-pointer": !disabled,
|
"cursor-pointer": !disabled,
|
||||||
"cursor-default": disabled
|
"cursor-not-allowed": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
33
lib/component/input/switch/MoltenSwitch.tsx
Normal file
33
lib/component/input/switch/MoltenSwitch.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import type { MattrixwvSwitchProps } from "$/types/InputTypes";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import MattrixwvSwitch from "./MattrixwvSwitch";
|
||||||
|
|
||||||
|
|
||||||
|
export default function MoltenSwitch({
|
||||||
|
className,
|
||||||
|
knobClassName,
|
||||||
|
disabled,
|
||||||
|
...props
|
||||||
|
}: Readonly<MattrixwvSwitchProps>){
|
||||||
|
return (
|
||||||
|
<MattrixwvSwitch
|
||||||
|
className={clsx(
|
||||||
|
"bg-neutral-mid",
|
||||||
|
className,
|
||||||
|
{
|
||||||
|
"data-checked:bg-molten": !disabled,
|
||||||
|
"data-checked:bg-molten-light/80": disabled
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
knobClassName={clsx(
|
||||||
|
knobClassName,
|
||||||
|
{
|
||||||
|
"bg-white": !disabled,
|
||||||
|
"bg-neutral-light": disabled
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
disabled={disabled}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -8,26 +8,26 @@ export default function PrimarySwitch({
|
|||||||
knobClassName,
|
knobClassName,
|
||||||
disabled,
|
disabled,
|
||||||
...props
|
...props
|
||||||
}: MattrixwvSwitchProps){
|
}: Readonly<MattrixwvSwitchProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvSwitch
|
<MattrixwvSwitch
|
||||||
{...props}
|
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"bg-gray-400",
|
"bg-neutral-mid",
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"data-checked:bg-blue-600": !disabled,
|
"data-checked:bg-primary": !disabled,
|
||||||
"data-checked:bg-blue-400/80": disabled
|
"data-checked:bg-primary-light/80": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
knobClassName={clsx(
|
knobClassName={clsx(
|
||||||
knobClassName,
|
knobClassName,
|
||||||
{
|
{
|
||||||
"bg-white": !disabled,
|
"bg-white": !disabled,
|
||||||
"bg-gray-200": disabled
|
"bg-neutral-light": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,26 +8,26 @@ export default function SecondarySwitch({
|
|||||||
knobClassName,
|
knobClassName,
|
||||||
disabled,
|
disabled,
|
||||||
...props
|
...props
|
||||||
}: MattrixwvSwitchProps){
|
}: Readonly<MattrixwvSwitchProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvSwitch
|
<MattrixwvSwitch
|
||||||
{...props}
|
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"bg-gray-400",
|
"bg-neutral-mid",
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"data-checked:bg-neutral-600": !disabled,
|
"data-checked:bg-secondary": !disabled,
|
||||||
"data-checked:bg-neutral-400/80": disabled
|
"data-checked:bg-secondary-light/80": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
knobClassName={clsx(
|
knobClassName={clsx(
|
||||||
knobClassName,
|
knobClassName,
|
||||||
{
|
{
|
||||||
"bg-white": !disabled,
|
"bg-white": !disabled,
|
||||||
"bg-gray-200": disabled
|
"bg-neutral-light": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,25 +8,25 @@ export default function SuccessDangerSwitch({
|
|||||||
knobClassName,
|
knobClassName,
|
||||||
disabled,
|
disabled,
|
||||||
...props
|
...props
|
||||||
}: MattrixwvSwitchProps){
|
}: Readonly<MattrixwvSwitchProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvSwitch
|
<MattrixwvSwitch
|
||||||
{...props}
|
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"bg-red-600 data-checked:bg-green-600": !disabled,
|
"bg-danger data-checked:bg-success": !disabled,
|
||||||
"bg-red-400/80 data-checked:bg-green-400/80": disabled
|
"bg-danger-light/80 data-checked:bg-success-light/80": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
knobClassName={clsx(
|
knobClassName={clsx(
|
||||||
knobClassName,
|
knobClassName,
|
||||||
{
|
{
|
||||||
"bg-white": !disabled,
|
"bg-white": !disabled,
|
||||||
"bg-gray-200": disabled
|
"bg-neutral-light": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,26 +8,26 @@ export default function SuccessSwitch({
|
|||||||
knobClassName,
|
knobClassName,
|
||||||
disabled,
|
disabled,
|
||||||
...props
|
...props
|
||||||
}: MattrixwvSwitchProps){
|
}: Readonly<MattrixwvSwitchProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvSwitch
|
<MattrixwvSwitch
|
||||||
{...props}
|
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"bg-gray-400",
|
"bg-neutral-mid",
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"data-checked:bg-green-600": !disabled,
|
"data-checked:bg-success": !disabled,
|
||||||
"data-checked:bg-green-400/80": disabled
|
"data-checked:bg-success-light/80": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
knobClassName={clsx(
|
knobClassName={clsx(
|
||||||
knobClassName,
|
knobClassName,
|
||||||
{
|
{
|
||||||
"bg-white": !disabled,
|
"bg-white": !disabled,
|
||||||
"bg-gray-200": disabled
|
"bg-neutral-light": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,26 +8,26 @@ export default function TertiarySwitch({
|
|||||||
knobClassName,
|
knobClassName,
|
||||||
disabled,
|
disabled,
|
||||||
...props
|
...props
|
||||||
}: MattrixwvSwitchProps){
|
}: Readonly<MattrixwvSwitchProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvSwitch
|
<MattrixwvSwitch
|
||||||
{...props}
|
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"bg-gray-400",
|
"bg-gray-400",
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"data-checked:bg-purple-600": !disabled,
|
"data-checked:bg-tertiary": !disabled,
|
||||||
"data-checked:bg-purple-400/80": disabled
|
"data-checked:bg-tertiary-light/80": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
knobClassName={clsx(
|
knobClassName={clsx(
|
||||||
knobClassName,
|
knobClassName,
|
||||||
{
|
{
|
||||||
"bg-white": !disabled,
|
"bg-white": !disabled,
|
||||||
"bg-gray-200": disabled
|
"bg-neutral-light": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,26 +8,26 @@ export default function WarningSwitch({
|
|||||||
knobClassName,
|
knobClassName,
|
||||||
disabled,
|
disabled,
|
||||||
...props
|
...props
|
||||||
}: MattrixwvSwitchProps){
|
}: Readonly<MattrixwvSwitchProps>){
|
||||||
return (
|
return (
|
||||||
<MattrixwvSwitch
|
<MattrixwvSwitch
|
||||||
{...props}
|
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"bg-gray-400",
|
"bg-neutral-mid",
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
"data-checked:bg-yellow-500": !disabled,
|
"data-checked:bg-warning": !disabled,
|
||||||
"data-checked:bg-yellow-300/80": disabled
|
"data-checked:bg-warning-light/80": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
knobClassName={clsx(
|
knobClassName={clsx(
|
||||||
knobClassName,
|
knobClassName,
|
||||||
{
|
{
|
||||||
"bg-white": !disabled,
|
"bg-white": !disabled,
|
||||||
"bg-gray-300": disabled
|
"bg-neutral-light": disabled
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
66
lib/component/input/text/PasswordInput.tsx
Normal file
66
lib/component/input/text/PasswordInput.tsx
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import type { TextInputProps } from "$/types/InputTypes";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
|
export default function PasswordInput({
|
||||||
|
id,
|
||||||
|
className,
|
||||||
|
inputClassName,
|
||||||
|
labelClassName,
|
||||||
|
name,
|
||||||
|
maxLength,
|
||||||
|
spellCheck,
|
||||||
|
placeholder,
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
onKeyDown,
|
||||||
|
disabled
|
||||||
|
}: Readonly<TextInputProps>){
|
||||||
|
const componentId = useId();
|
||||||
|
const activeId = id ?? componentId;
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
"flex flex-row items-center justify-center rounded-lg border-2 w-full",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="relative flex flex-row items-center justify-center px-2 py-1 w-full"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
id={activeId}
|
||||||
|
className={clsx(
|
||||||
|
"peer bg-transparent outline-none placeholder-transparent w-full",
|
||||||
|
inputClassName
|
||||||
|
)}
|
||||||
|
name={name}
|
||||||
|
placeholder={placeholder}
|
||||||
|
maxLength={maxLength}
|
||||||
|
value={value}
|
||||||
|
onChange={(e) => onChange?.(e.target.value)}
|
||||||
|
disabled={disabled}
|
||||||
|
spellCheck={spellCheck}
|
||||||
|
onKeyDown={onKeyDown}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
className={clsx(
|
||||||
|
"absolute ml-2 -top-3 left-0 text-sm rounded-md px-1 select-none cursor-default",
|
||||||
|
"peer-placeholder-shown:top-0 peer-placeholder-shown:-left-1 peer-placeholder-shown:text-inherit peer-placeholder-shown:text-base peer-placeholder-shown:h-full peer-placeholder-shown:cursor-text peer-placeholder-shown:w-[98%]",
|
||||||
|
"peer-focus:-top-3 peer-focus:left-0 peer-focus:text-sm peer-focus:w-auto peer-focus:h-auto",
|
||||||
|
"flex items-center",
|
||||||
|
labelClassName
|
||||||
|
)}
|
||||||
|
style={{ transitionProperty: "top, left, font-size, line-height", transitionTimingFunction: "cubic-bezier(0.4 0, 0.2, 1)", transitionDuration: "250ms" }}
|
||||||
|
htmlFor={activeId}
|
||||||
|
>
|
||||||
|
{placeholder}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
87
lib/component/input/text/PhoneInput.tsx
Normal file
87
lib/component/input/text/PhoneInput.tsx
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import type { TextInputProps } from "$/types/InputTypes";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
|
export default function PhoneInput({
|
||||||
|
id,
|
||||||
|
className,
|
||||||
|
inputClassName,
|
||||||
|
labelClassName,
|
||||||
|
name,
|
||||||
|
maxLength,
|
||||||
|
spellCheck,
|
||||||
|
placeholder,
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
onKeyDown,
|
||||||
|
disabled
|
||||||
|
}: Readonly<TextInputProps>){
|
||||||
|
const componentId = useId();
|
||||||
|
const activeId = id ?? componentId;
|
||||||
|
|
||||||
|
//TODO: Figure out how to setup phone number
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
"flex flex-row items-center justify-center rounded-lg border-2 w-full",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="relative flex flex-row items-center justify-center px-2 py-1 w-full"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id={activeId}
|
||||||
|
className={clsx(
|
||||||
|
"peer bg-transparent outline-none placeholder-transparent w-full",
|
||||||
|
inputClassName
|
||||||
|
)}
|
||||||
|
name={name}
|
||||||
|
placeholder={placeholder}
|
||||||
|
maxLength={maxLength}
|
||||||
|
value={value}
|
||||||
|
onChange={(e) => onChange?.(e.target.value)}
|
||||||
|
onKeyDown={onKeyDown}
|
||||||
|
disabled={disabled}
|
||||||
|
spellCheck={spellCheck}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
className={clsx(
|
||||||
|
"absolute ml-2 -top-3 left-0 text-sm rounded-md px-1 select-none cursor-default",
|
||||||
|
"peer-placeholder-shown:top-0 peer-placeholder-shown:-left-1 peer-placeholder-shown:text-inherit peer-placeholder-shown:text-base peer-placeholder-shown:h-full peer-placeholder-shown:cursor-text peer-placeholder-shown:w-[99%]",
|
||||||
|
"peer-focus:-top-3 peer-focus:left-0 peer-focus:text-sm peer-focus:w-auto peer-focus:h-auto",
|
||||||
|
"flex items-center",
|
||||||
|
labelClassName
|
||||||
|
)}
|
||||||
|
style={{ transitionProperty: "top, left, font-size, line-height", transitionTimingFunction: "cubic-bezier(0.4 0, 0.2, 1)", transitionDuration: "250ms" }}
|
||||||
|
htmlFor={activeId}
|
||||||
|
>
|
||||||
|
{placeholder}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
function formatPhoneNumber(phoneNumber: string): string {
|
||||||
|
const chars: string[] = [];
|
||||||
|
|
||||||
|
// Separate the string into individual characters
|
||||||
|
for(let cnt = 0;cnt < phoneNumber.length;++cnt){
|
||||||
|
chars.push(phoneNumber.charAt(cnt));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add _ for any chars that don't exist
|
||||||
|
for(let cnt = chars.length;cnt < 10;++cnt){
|
||||||
|
chars.push("_");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put the values into the correct format
|
||||||
|
return "(" + chars.slice(0, 3).join() + ") " + chars.slice(3, 6).join() + "-" + chars.slice(6).join();
|
||||||
|
}
|
||||||
|
*/
|
||||||
@@ -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,28 @@
|
|||||||
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,
|
||||||
|
onKeyDown,
|
||||||
disabled
|
disabled
|
||||||
}: TextAreaProps){
|
}: Readonly<TextAreaProps>){
|
||||||
|
const componentId = useId();
|
||||||
|
const activeId = id ?? componentId;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
@@ -29,7 +34,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,22 +44,22 @@ 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={(e) => onChange?.(e.target.value)}
|
||||||
|
onKeyDown={onKeyDown}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
spellCheck={spellCheck}
|
spellCheck={spellCheck}
|
||||||
/>
|
/>
|
||||||
<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",
|
||||||
"peer-placeholder-shown:top-0 peer-placeholder-shown:-left-1 peer-placeholder-shown:text-inherit peer-placeholder-shown:text-base peer-placeholder-shown:bg-transparent peer-placeholder-shown:cursor-text peer-placeholder-shown:w-[99%]",
|
"peer-placeholder-shown:top-0 peer-placeholder-shown:-left-1 peer-placeholder-shown:text-inherit peer-placeholder-shown:text-base peer-placeholder-shown:cursor-text peer-placeholder-shown:w-[98%]",
|
||||||
"peer-focus:-top-3 peer-focus:left-0 peer-focus:text-sm peer-focus:w-auto peer-focus:h-auto",
|
"peer-focus:-top-3 peer-focus:left-0 peer-focus:text-sm peer-focus:w-auto peer-focus:h-auto",
|
||||||
"flex items-center",
|
"flex items-center",
|
||||||
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,15 @@ export default function TextInput({
|
|||||||
maxLength,
|
maxLength,
|
||||||
spellCheck,
|
spellCheck,
|
||||||
placeholder,
|
placeholder,
|
||||||
defaultValue,
|
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
|
onKeyDown,
|
||||||
disabled
|
disabled
|
||||||
}: TextInputProps){
|
}: Readonly<TextInputProps>){
|
||||||
|
const componentId = useId();
|
||||||
|
const activeId = id ?? componentId;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
@@ -28,7 +33,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,22 +41,22 @@ 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={(e) => onChange?.(e.target.value)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
spellCheck={spellCheck}
|
spellCheck={spellCheck}
|
||||||
|
onKeyDown={onKeyDown}
|
||||||
/>
|
/>
|
||||||
<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",
|
||||||
"peer-placeholder-shown:top-0 peer-placeholder-shown:-left-1 peer-placeholder-shown:text-inherit peer-placeholder-shown:text-base peer-placeholder-shown:bg-transparent peer-placeholder-shown:h-full peer-placeholder-shown:cursor-text peer-placeholder-shown:w-[99%]",
|
"peer-placeholder-shown:top-0 peer-placeholder-shown:-left-1 peer-placeholder-shown:text-inherit peer-placeholder-shown:text-base peer-placeholder-shown:h-full peer-placeholder-shown:cursor-text peer-placeholder-shown:w-[98%]",
|
||||||
"peer-focus:-top-3 peer-focus:left-0 peer-focus:text-sm peer-focus:w-auto peer-focus:h-auto",
|
"peer-focus:-top-3 peer-focus:left-0 peer-focus:text-sm peer-focus:w-auto peer-focus:h-auto",
|
||||||
"flex items-center",
|
"flex items-center",
|
||||||
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,90 +0,0 @@
|
|||||||
|
|
||||||
import CenterGrowingBars from "./loading/bar/CenterGrowingBars";
|
|
||||||
import CircleBars from "./loading/bar/CircleBars";
|
|
||||||
import FadingBars from "./loading/bar/FadingBars";
|
|
||||||
import FadingGrowingBars from "./loading/bar/FadingGrowingBars";
|
|
||||||
import GrowingBars from "./loading/bar/GrowingBars";
|
|
||||||
import PulsingBlocks from "./loading/block/PulsingBlocks";
|
|
||||||
import SlidingBlocks2 from "./loading/block/SlidingBlocks2";
|
|
||||||
import SlidingBlocks3 from "./loading/block/SlidingBlocks3";
|
|
||||||
import WaveBlocks from "./loading/block/WaveBlocks";
|
|
||||||
import BouncingDots from "./loading/dot/BouncingDots";
|
|
||||||
import CircleCenterDots from "./loading/dot/CircleCenterDots";
|
|
||||||
import CircleFadingDots from "./loading/dot/CircleFadingDots";
|
|
||||||
import CirclePulsingDots from "./loading/dot/CirclePulsingDots";
|
|
||||||
import CircleRotatingDots from "./loading/dot/CircleRotatingDots";
|
|
||||||
import CircleShrinkingDots from "./loading/dot/CircleShrinkingDots";
|
|
||||||
import CircleSpinningDot from "./loading/dot/CircleSpinningDot";
|
|
||||||
import CyclingDots from "./loading/dot/CyclingDots";
|
|
||||||
import FadingDots from "./loading/dot/FadingDots";
|
|
||||||
import PulsingDots from "./loading/dot/PulsingDots";
|
|
||||||
import RotatingDots from "./loading/dot/RotatingDots";
|
|
||||||
import SwellingDots from "./loading/dot/SwellingDots";
|
|
||||||
import DoubleDrop from "./loading/drop/DoubleDrop";
|
|
||||||
import DoubleWaveDrop from "./loading/drop/DoubleWaveDrop";
|
|
||||||
import Drop from "./loading/drop/Drop";
|
|
||||||
import QuickDrop from "./loading/drop/QuickDrop";
|
|
||||||
import QuickWaveDrop from "./loading/drop/QuickWaveDrop";
|
|
||||||
import TripleDrop from "./loading/drop/TripleDrop";
|
|
||||||
import TripleWaveDrop from "./loading/drop/TripleWaveDrop";
|
|
||||||
import WaveDrop from "./loading/drop/WaveDrop";
|
|
||||||
import HalfSpinner from "./loading/spinner/HalfSpinner";
|
|
||||||
import QuarterSpinner from "./loading/spinner/QuarterSpinner";
|
|
||||||
import RubberSpinner from "./loading/spinner/RubberSpinner";
|
|
||||||
import ThreeQuarterSpinner from "./loading/spinner/ThreeQuarterSpinner";
|
|
||||||
import BouncingDot from "./loading/various/BouncingDot";
|
|
||||||
import PulsingLine from "./loading/various/PulsingLine";
|
|
||||||
import SpinningBinary from "./loading/various/SpinningBinary";
|
|
||||||
import SpinningClock from "./loading/various/SpinningClock";
|
|
||||||
import SpinningEclipse from "./loading/various/SpinningEclipse";
|
|
||||||
import SpinningEclipseHalf from "./loading/various/SpinningEclipseHalf";
|
|
||||||
import SpinningGalaxy from "./loading/various/SpinningGalaxy";
|
|
||||||
import SpinningTadpole from "./loading/various/SpinningTadpole";
|
|
||||||
import Wifi from "./loading/various/Wifi";
|
|
||||||
|
|
||||||
|
|
||||||
export {
|
|
||||||
BouncingDot,
|
|
||||||
BouncingDots,
|
|
||||||
CenterGrowingBars,
|
|
||||||
CircleBars,
|
|
||||||
CircleCenterDots,
|
|
||||||
CircleFadingDots,
|
|
||||||
CirclePulsingDots,
|
|
||||||
CircleRotatingDots,
|
|
||||||
CircleShrinkingDots,
|
|
||||||
CircleSpinningDot,
|
|
||||||
CyclingDots,
|
|
||||||
DoubleDrop,
|
|
||||||
DoubleWaveDrop,
|
|
||||||
Drop,
|
|
||||||
FadingBars,
|
|
||||||
FadingDots,
|
|
||||||
FadingGrowingBars,
|
|
||||||
GrowingBars,
|
|
||||||
HalfSpinner,
|
|
||||||
PulsingBlocks,
|
|
||||||
PulsingDots,
|
|
||||||
PulsingLine,
|
|
||||||
QuarterSpinner,
|
|
||||||
QuickDrop,
|
|
||||||
QuickWaveDrop,
|
|
||||||
RotatingDots,
|
|
||||||
RubberSpinner,
|
|
||||||
SlidingBlocks2,
|
|
||||||
SlidingBlocks3,
|
|
||||||
SpinningBinary,
|
|
||||||
SpinningClock,
|
|
||||||
SpinningEclipse,
|
|
||||||
SpinningEclipseHalf,
|
|
||||||
SpinningGalaxy,
|
|
||||||
SpinningTadpole,
|
|
||||||
SwellingDots,
|
|
||||||
ThreeQuarterSpinner,
|
|
||||||
TripleDrop,
|
|
||||||
TripleWaveDrop,
|
|
||||||
WaveBlocks,
|
|
||||||
WaveDrop,
|
|
||||||
Wifi
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -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"
|
||||||
|
|||||||
44
lib/component/loading/index.ts
Normal file
44
lib/component/loading/index.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
export { default as CenterGrowingBars } from "./bar/CenterGrowingBars";
|
||||||
|
export { default as CircleBars } from "./bar/CircleBars";
|
||||||
|
export { default as FadingBars } from "./bar/FadingBars";
|
||||||
|
export { default as FadingGrowingBars } from "./bar/FadingGrowingBars";
|
||||||
|
export { default as GrowingBars } from "./bar/GrowingBars";
|
||||||
|
export { default as PulsingBlocks } from "./block/PulsingBlocks";
|
||||||
|
export { default as SlidingBlocks2 } from "./block/SlidingBlocks2";
|
||||||
|
export { default as SlidingBlocks3 } from "./block/SlidingBlocks3";
|
||||||
|
export { default as WaveBlocks } from "./block/WaveBlocks";
|
||||||
|
export { default as BouncingDots } from "./dot/BouncingDots";
|
||||||
|
export { default as CircleCenterDots } from "./dot/CircleCenterDots";
|
||||||
|
export { default as CircleFadingDots } from "./dot/CircleFadingDots";
|
||||||
|
export { default as CirclePulsingDots } from "./dot/CirclePulsingDots";
|
||||||
|
export { default as CircleRotatingDots } from "./dot/CircleRotatingDots";
|
||||||
|
export { default as CircleShrinkingDots } from "./dot/CircleShrinkingDots";
|
||||||
|
export { default as CircleSpinningDot } from "./dot/CircleSpinningDot";
|
||||||
|
export { default as CyclingDots } from "./dot/CyclingDots";
|
||||||
|
export { default as FadingDots } from "./dot/FadingDots";
|
||||||
|
export { default as PulsingDots } from "./dot/PulsingDots";
|
||||||
|
export { default as RotatingDots } from "./dot/RotatingDots";
|
||||||
|
export { default as SwellingDots } from "./dot/SwellingDots";
|
||||||
|
export { default as DoubleDrop } from "./drop/DoubleDrop";
|
||||||
|
export { default as DoubleWaveDrop } from "./drop/DoubleWaveDrop";
|
||||||
|
export { default as Drop } from "./drop/Drop";
|
||||||
|
export { default as QuickDrop } from "./drop/QuickDrop";
|
||||||
|
export { default as QuickWaveDrop } from "./drop/QuickWaveDrop";
|
||||||
|
export { default as TripleDrop } from "./drop/TripleDrop";
|
||||||
|
export { default as TripleWaveDrop } from "./drop/TripleWaveDrop";
|
||||||
|
export { default as WaveDrop } from "./drop/WaveDrop";
|
||||||
|
export { default as HalfSpinner } from "./spinner/HalfSpinner";
|
||||||
|
export { default as QuarterSpinner } from "./spinner/QuarterSpinner";
|
||||||
|
export { default as RubberSpinner } from "./spinner/RubberSpinner";
|
||||||
|
export { default as ThreeQuarterSpinner } from "./spinner/ThreeQuarterSpinner";
|
||||||
|
export { default as BouncingDot } from "./various/BouncingDot";
|
||||||
|
export { default as PulsingLine } from "./various/PulsingLine";
|
||||||
|
export { default as SpinningBinary } from "./various/SpinningBinary";
|
||||||
|
export { default as SpinningClock } from "./various/SpinningClock";
|
||||||
|
export { default as SpinningEclipse } from "./various/SpinningEclipse";
|
||||||
|
export { default as SpinningEclipseHalf } from "./various/SpinningEclipseHalf";
|
||||||
|
export { default as SpinningGalaxy } from "./various/SpinningGalaxy";
|
||||||
|
export { default as SpinningTadpole } from "./various/SpinningTadpole";
|
||||||
|
export { default as Wifi } from "./various/Wifi";
|
||||||
|
|
||||||
@@ -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"
|
||||||
/>
|
/>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user