diff --git a/.eslintrc.js b/.eslintrc.js
index 781ced1..77bfc4e 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,3 +1,4 @@
+// eslint-disable-next-line @typescript-eslint/no-var-requires
const prettierConfig = require('./.prettierrc.js');
module.exports = {
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 03d9549..f21e1f1 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -1,6 +1,7 @@
+
\ No newline at end of file
diff --git a/.idea/jsLinters/eslint.xml b/.idea/jsLinters/eslint.xml
deleted file mode 100644
index 541945b..0000000
--- a/.idea/jsLinters/eslint.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/components/badges.tsx b/app/components/badges.tsx
index 301b9ed..25ba619 100644
--- a/app/components/badges.tsx
+++ b/app/components/badges.tsx
@@ -6,8 +6,14 @@ export default function Badges() {
return (
+
Badges
(
- function ButtonBase({ centralRipple = false, ...props }, ref) {
+ ({ centralRipple = false, variant, ...props }, ref) => {
const [isActive, setIsActive] = useState
(false),
ripplesRef = useRef(null),
buttonId = useId(),
events = useRippleEffect(ripplesRef, setIsActive);
- const { variant, disabled, className } = props;
-
- const classes = className
- ? `m3 ${className} ${variant}${isActive ? ' is-active' : ''}`
+ const classes = props.className
+ ? `m3 ${props.className} ${variant}${isActive ? ' is-active' : ''}`
: `m3 ${variant}${isActive ? ' is-active' : ''}`;
return (
@@ -24,7 +22,7 @@ export const ButtonLayout = forwardRef(
{...props}
{...events}
className={classes}
- disabled={disabled}
+ disabled={props.disabled}
id={buttonId}
ref={ref}
>
@@ -40,6 +38,7 @@ export const ButtonLayout = forwardRef(
);
ButtonLayout.propTypes = {
+ variant: string,
centralRipple: bool,
children: string,
};
diff --git a/src/primitive-components/button-layout/button-layout.types.ts b/src/primitive-components/button-layout/button-layout.types.ts
index 84488b7..208688c 100644
--- a/src/primitive-components/button-layout/button-layout.types.ts
+++ b/src/primitive-components/button-layout/button-layout.types.ts
@@ -1,6 +1,6 @@
import { ButtonHTMLAttributes } from 'react';
import { IRippleProps } from '../ripple/ripple.types';
-export interface ButtonLayoutProps
- extends IRippleProps,
- ButtonHTMLAttributes {}
+export type ButtonLayoutProps = IRippleProps & ButtonHTMLAttributes & {
+ variant?: string;
+};
diff --git a/src/primitive-components/button/button.types.ts b/src/primitive-components/button/button.types.ts
index e4fd1b8..8947a8e 100644
--- a/src/primitive-components/button/button.types.ts
+++ b/src/primitive-components/button/button.types.ts
@@ -5,6 +5,7 @@ export interface ButtonMainProps
extends ButtonHTMLAttributes {
disabled?: boolean;
variant?: 'filled' | 'outlined' | 'elevated' | 'tonal' | 'text';
+ icon?: string;
}
-export interface ButtonProps extends IRippleProps, ButtonMainProps {}
+export type ButtonProps = IRippleProps & ButtonMainProps;
diff --git a/src/primitive-components/checkbox/checkbox.types.ts b/src/primitive-components/checkbox/checkbox.types.ts
index fd0b6a6..05f6bc5 100644
--- a/src/primitive-components/checkbox/checkbox.types.ts
+++ b/src/primitive-components/checkbox/checkbox.types.ts
@@ -1,6 +1,7 @@
import { InputHTMLAttributes } from 'react';
import { IRippleProps } from '../ripple/ripple.types';
-export interface CheckboxProps
- extends InputHTMLAttributes,
- IRippleProps {}
+export type CheckboxProps = InputHTMLAttributes &
+ IRippleProps & {
+ indeterminate?: boolean;
+ };
diff --git a/src/primitive-components/fab/fab.types.ts b/src/primitive-components/fab/fab.types.ts
index 6d7102c..8ffeb51 100644
--- a/src/primitive-components/fab/fab.types.ts
+++ b/src/primitive-components/fab/fab.types.ts
@@ -1,12 +1,14 @@
-import React from 'react';
+import { ButtonHTMLAttributes } from 'react';
import { IRippleProps } from '../ripple/ripple.types';
-export interface FABMainProps
- extends React.ButtonHTMLAttributes {
+export interface FABMainProps {
icon: string;
disabled?: boolean;
+ elevated?: boolean;
size?: 'small' | 'default' | 'large' | 'extended';
variant?: 'surface' | 'primary' | 'secondary' | 'tertiary';
}
-export interface FABProps extends FABMainProps, IRippleProps {}
+export type FABProps = FABMainProps &
+ IRippleProps &
+ ButtonHTMLAttributes;
diff --git a/src/primitive-components/icon-button/icon-button.tsx b/src/primitive-components/icon-button/icon-button.tsx
index 79c7095..248627d 100644
--- a/src/primitive-components/icon-button/icon-button.tsx
+++ b/src/primitive-components/icon-button/icon-button.tsx
@@ -5,6 +5,7 @@ import { ButtonLayout } from '../button-layout/button-layout';
import { IconButtonProps, StateToggleIconType } from './icon-button.types';
import {
forwardRef,
+ MouseEventHandler,
useCallback,
useImperativeHandle,
useRef,
@@ -44,7 +45,7 @@ export const IconButton = forwardRef(
const buttonRef = useRef(null);
const callback = useCallback(
- (e: MouseEvent) => {
+ (event: MouseEventHandler) => {
if (toggled) {
if (toggleIcon.state === 'selected') {
toggle('', toggled.unselected ?? 'add_circle');
@@ -53,7 +54,7 @@ export const IconButton = forwardRef(
}
}
if (props.onClick) {
- props.onClick.apply(null, e);
+ props.onClick.apply(null, event);
}
},
[toggleIcon],
@@ -72,7 +73,7 @@ export const IconButton = forwardRef(
variant={variant ? variant : 'default'}
>
diff --git a/src/primitive-components/icon-button/icon-button.types.ts b/src/primitive-components/icon-button/icon-button.types.ts
index a335b5c..08b3b78 100644
--- a/src/primitive-components/icon-button/icon-button.types.ts
+++ b/src/primitive-components/icon-button/icon-button.types.ts
@@ -1,6 +1,14 @@
-import React from 'react';
+import { ButtonHTMLAttributes } from 'react';
import { IRippleProps } from '../ripple/ripple.types';
+export interface IconButtonMainProps {
+ icon: string;
+ selected?: boolean;
+ disabled?: boolean;
+ toggled?: false | ToggleButtonType;
+ variant?: 'default' | 'filled' | 'tonal' | 'outlined';
+}
+
export type StateToggleIconType = {
state: string;
icon: string;
@@ -11,12 +19,6 @@ export type ToggleButtonType = {
unselected: string;
};
-export interface IconButtonMainProps
- extends React.ButtonHTMLAttributes {
- icon: string;
- toggled?: false | ToggleButtonType;
- disabled?: boolean;
- variant?: 'default' | 'filled' | 'tonal' | 'outlined';
-}
-
-export interface IconButtonProps extends IconButtonMainProps, IRippleProps {}
+export type IconButtonProps = IconButtonMainProps &
+ IRippleProps &
+ ButtonHTMLAttributes;
\ No newline at end of file
diff --git a/src/primitive-components/radio/radio.types.ts b/src/primitive-components/radio/radio.types.ts
index b8a9531..59d2c0a 100644
--- a/src/primitive-components/radio/radio.types.ts
+++ b/src/primitive-components/radio/radio.types.ts
@@ -1,8 +1,7 @@
import { InputHTMLAttributes } from 'react';
import { IRippleProps } from '../ripple/ripple.types';
-export interface RadioProps
- extends InputHTMLAttributes,
- IRippleProps {
- centralRipple?: boolean;
-}
+export type RadioProps = InputHTMLAttributes &
+ IRippleProps & {
+ centralRipple?: boolean;
+ };
diff --git a/src/primitive-components/ripple/hooks/useRippleEffect.ts b/src/primitive-components/ripple/hooks/useRippleEffect.ts
index cb30bdb..f10ab27 100644
--- a/src/primitive-components/ripple/hooks/useRippleEffect.ts
+++ b/src/primitive-components/ripple/hooks/useRippleEffect.ts
@@ -1,17 +1,36 @@
-import React, { useEffect, useState } from 'react';
+import {
+ DragEventHandler,
+ FocusEventHandler,
+ MouseEventHandler,
+ TouchEventHandler,
+ useEffect,
+ useState,
+} from 'react';
interface RippleEventHandlers {
- onBlur: React.FocusEventHandler;
- onContextMenu: React.MouseEventHandler;
- onDragLeave: React.DragEventHandler;
- onMouseDown: React.MouseEventHandler;
- onMouseLeave: React.MouseEventHandler;
- onMouseUp: React.MouseEventHandler;
- onTouchEnd: React.TouchEventHandler;
- onTouchMove: React.TouchEventHandler;
- onTouchStart: React.TouchEventHandler;
+ onBlur: FocusEventHandler;
+ onContextMenu: MouseEventHandler;
+ onDragLeave: DragEventHandler;
+ onMouseDown: MouseEventHandler;
+ onMouseLeave: MouseEventHandler;
+ onMouseUp: MouseEventHandler;
+ onTouchEnd: TouchEventHandler;
+ onTouchMove: TouchEventHandler;
+ onTouchStart: TouchEventHandler;
}
+export type InteractionEventsType = MouseEvent & TouchEvent & DragEvent & FocusEvent
+
+export interface InteractionEvents
+ extends MouseEvent,
+ TouchEvent,
+ DragEvent,
+ FocusEvent,
+ MouseEventHandler,
+ DragEventHandler,
+ FocusEventHandler,
+ TouchEventHandler {}
+
const UseRippleEffect = (ref, callback): undefined | RippleEventHandlers => {
const [mounted, setMounted] = useState(false);
diff --git a/src/primitive-components/ripple/ripple-area.tsx b/src/primitive-components/ripple/ripple-area.tsx
index 52da9e8..c39d17c 100644
--- a/src/primitive-components/ripple/ripple-area.tsx
+++ b/src/primitive-components/ripple/ripple-area.tsx
@@ -2,7 +2,7 @@
import React, {
forwardRef,
- useCallback,
+ ReactElement,
useId,
useImperativeHandle,
useRef,
@@ -11,26 +11,27 @@ import React, {
import { Ripple } from './ripple';
import { Ripples } from './ripple';
import { RippleAreaProps } from './ripple.types';
+import {InteractionEvents, InteractionEventsType} from './hooks/useRippleEffect';
const TIMEOUT: number = 550;
const rippleAreaContext = React.createContext(false);
-const RippleArea = forwardRef(function RippleArea(
- { central = false, callback, ...props }: RippleAreaProps,
- ref,
-) {
- const [ripples, setRipples] = useState>([]),
- rippleDomain = useRef(null),
- clicked = useRef(false),
- uniqueKey = useRef(0),
- uniqueId = useId();
+const RippleArea = forwardRef(
+ ({ central = false, ...props }: RippleAreaProps, ref) => {
+ const [ripples, setRipples] = useState>([]),
+ rippleDomain = useRef(null),
+ clicked = useRef(false),
+ uniqueKey = useRef(0),
+ uniqueId = useId();
- const classes = props.className
- ? `m3 m3-ripple-domain ${props.className}`.trimEnd()
- : 'm3 m3-ripple-domain';
+ const classes = props.className
+ ? `m3 m3-ripple-domain ${props.className}`.trimEnd()
+ : 'm3 m3-ripple-domain';
- const start = useCallback(
- (event: any, cb: (state: boolean) => void): void => {
+ const start = (
+ event: InteractionEventsType,
+ cb: (state: boolean) => void,
+ ): void => {
clicked.current = true;
cb(clicked.current);
@@ -65,7 +66,7 @@ const RippleArea = forwardRef(function RippleArea(
2,
rippleS: number = (rippleSizeX ** 2 + rippleSizeY ** 2) ** 0.5;
- setRipples((prevRipples: Array) => {
+ setRipples((prevRipples: Array) => {
if (prevRipples.length === 0) {
return [
void) => {
- clicked.current = false;
- cb(clicked.current);
+ const stop = (
+ _event: InteractionEventsType,
+ cb: (state: boolean) => void,
+ ) => {
+ clicked.current = false;
+ cb(clicked.current);
- setRipples((prevRipples: Array) => {
- if (prevRipples.length > 0) {
- const old = [...prevRipples];
- old.shift();
- return old;
- }
- return prevRipples;
- });
- }, []);
+ setRipples((prevRipples: Array) => {
+ if (prevRipples.length > 0) {
+ const old = [...prevRipples];
+ old.shift();
+ return old;
+ }
+ return prevRipples;
+ });
+ };
- useImperativeHandle(
- ref,
- () => ({
- start,
- stop,
- }),
- [start, stop],
- );
+ useImperativeHandle(
+ ref,
+ () => ({
+ start,
+ stop,
+ }),
+ [start, stop],
+ );
- return (
-
-
- {ripples}
-
-
- );
-});
+ return (
+
+
+ {ripples}
+
+
+ );
+ },
+);
export { rippleAreaContext, RippleArea };
diff --git a/src/primitive-components/ripple/ripple.tsx b/src/primitive-components/ripple/ripple.tsx
index d173e93..1262dbf 100644
--- a/src/primitive-components/ripple/ripple.tsx
+++ b/src/primitive-components/ripple/ripple.tsx
@@ -1,14 +1,11 @@
'use client';
import isEmpty from './utils/utils';
-import { rippleProps } from './ripple.types';
+import { RippleProps, RipplesProps } from './ripple.types';
import { rippleAreaContext } from './ripple-area';
import RippleEffectBuild from './utils/ripple-effect-builder';
import React, {
- ForwardedRef,
- forwardRef,
- JSX,
- useCallback,
+ ReactElement,
useContext,
useEffect,
useRef,
@@ -16,15 +13,12 @@ import React, {
useTransition,
} from 'react';
-const Ripples = forwardRef(function Ripples(
- props: any,
- ref: ForwardedRef,
-) {
+const Ripples = (props: RipplesProps) => {
const [ripples, setRipples] = useState({});
const firstRender = useRef(true);
const [pending, startTransition] = useTransition();
- const LifetimeEnd = useCallback((child: JSX.Element) => {
+ const LifetimeEnd = (child: ReactElement) => {
if (child.props.endLifetime) {
child.props.endLifetime();
}
@@ -34,10 +28,10 @@ const Ripples = forwardRef(function Ripples(
delete children[child.key];
return children;
});
- }, []);
+ };
useEffect(() => {
- if (props.children.length > 0) {
+ if (props.children.length > 0 && !pending) {
startTransition(() => {
if (firstRender.current || isEmpty(ripples)) {
setRipples(RippleEffectBuild(props.children, LifetimeEnd));
@@ -52,14 +46,15 @@ const Ripples = forwardRef(function Ripples(
}, [props.children]);
return <>{Object.values(ripples)}>;
-});
-
-const Ripple = forwardRef(function Ripple(
- props: rippleProps,
- ref: ForwardedRef,
-) {
- const { rippleX, rippleY, rippleS, endLifetime, lifetime } = props;
+};
+const Ripple = ({
+ rippleX,
+ rippleY,
+ rippleS,
+ endLifetime,
+ lifetime,
+}: RippleProps) => {
const clicked = useContext(rippleAreaContext);
const [classes, setClasses] = useState('m3 ripple visible');
@@ -81,6 +76,6 @@ const Ripple = forwardRef(function Ripple(
}}
/>
);
-});
+};
export { Ripple, Ripples };
diff --git a/src/primitive-components/ripple/ripple.types.ts b/src/primitive-components/ripple/ripple.types.ts
index 43fead5..09e33ac 100644
--- a/src/primitive-components/ripple/ripple.types.ts
+++ b/src/primitive-components/ripple/ripple.types.ts
@@ -1,21 +1,23 @@
-import { Dispatch, SetStateAction } from 'react';
+import { Dispatch, HTMLAttributes, ReactElement, SetStateAction } from 'react';
-export interface IRippleProps extends PropsWithChildren {
+export interface RipplesProps extends HTMLAttributes {
+ children?: ReactElement[];
+}
+
+export interface IRippleProps extends HTMLAttributes {
centralRipple?: boolean;
}
-export interface RippleAreaProps extends PropsWithChildren {
+export interface RippleAreaProps extends HTMLAttributes {
callback: Dispatch>;
central?: boolean;
}
-export type rippleProps = {
+export interface RippleProps extends HTMLAttributes {
rippleX: number;
rippleY: number;
rippleS: number;
endLifetime?: () => void;
lifetime: number;
key?: number;
-};
-
-import { PropsWithChildren } from 'react';
+}
diff --git a/src/primitive-components/ripple/utils/array-convert-to-obj.ts b/src/primitive-components/ripple/utils/array-convert-to-obj.ts
index 8a02e34..c1166ee 100644
--- a/src/primitive-components/ripple/utils/array-convert-to-obj.ts
+++ b/src/primitive-components/ripple/utils/array-convert-to-obj.ts
@@ -1,12 +1,12 @@
import { cloneElement, ReactElement } from 'react';
export default function ArrayConvertToObj(
- obj: Object,
+ obj: object,
nextChildren: ReactElement[],
- callback: (child: any) => void,
+ callback: (child: ReactElement) => void,
): void {
Object.values(nextChildren).forEach(
- (child: JSX.Element) =>
+ (child: ReactElement) =>
(obj[child.key] = cloneElement(child, {
...child.props,
endLifetime: callback.bind(null, child),
diff --git a/src/primitive-components/ripple/utils/ripple-effect-builder.ts b/src/primitive-components/ripple/utils/ripple-effect-builder.ts
index ed8b4eb..0e9655c 100644
--- a/src/primitive-components/ripple/utils/ripple-effect-builder.ts
+++ b/src/primitive-components/ripple/utils/ripple-effect-builder.ts
@@ -1,11 +1,11 @@
+import isEmpty from './utils';
import ArrayConvertToObj from './array-convert-to-obj';
import { cloneElement, ReactElement } from 'react';
-import isEmpty from './utils';
export default function RippleEffectBuild(
nextRipples: ReactElement[],
- callback: (child: any) => void,
- prevRipples?: any | null,
+ callback: (child: ReactElement) => void,
+ prevRipples?: object | null,
) {
const empty: boolean = isEmpty(prevRipples);
const preparedRipples: object = empty ? {} : prevRipples;
diff --git a/src/primitive-components/ripple/utils/utils.ts b/src/primitive-components/ripple/utils/utils.ts
index 770d0fb..7d663b9 100644
--- a/src/primitive-components/ripple/utils/utils.ts
+++ b/src/primitive-components/ripple/utils/utils.ts
@@ -1,4 +1,4 @@
-export default function isEmpty(obj: Object): boolean {
+export default function isEmpty(obj: object): boolean {
for (const _i in obj) {
return false;
}
diff --git a/src/primitive-components/text-field/text-field.tsx b/src/primitive-components/text-field/text-field.tsx
index 67174df..0a8551c 100644
--- a/src/primitive-components/text-field/text-field.tsx
+++ b/src/primitive-components/text-field/text-field.tsx
@@ -15,7 +15,7 @@ export const TextField = forwardRef(
},
ref,
) => {
- const [raised, setRaised] = useState(!props.placeholder);
+ const [raised, setRaised] = useState(!!props.placeholder);
const callback = (e: FocusEvent): void => {
if (
@@ -92,10 +92,10 @@ export const TextField = forwardRef(
TextField.propTypes = {
children: string,
- withBeforeIcon: bool,
- withAfterIcon: bool,
className: string,
- variant: oneOf(['filled', 'outlined']),
placeholder: string,
+ withAfterIcon: bool,
+ withBeforeIcon: bool,
supportingText: string,
+ variant: oneOf(['filled', 'outlined']),
};