voice-changer/client/demo_DDSP-SVC/src/hooks/useStateControlCheckbox.tsx
2023-03-24 08:47:50 +09:00

101 lines
3.4 KiB
TypeScript

import React, { useMemo, useRef } from "react";
import { useEffect } from "react";
export type StateControlCheckbox = {
trigger: JSX.Element;
updateState: (newVal: boolean) => void;
checked: () => boolean
className: string;
};
export const useStateControlCheckbox = (className: string, changeCallback?: (newVal: boolean) => void): StateControlCheckbox => {
const currentValForTriggerCallbackRef = useRef<boolean>(false);
// (4) トリガチェックボックス
const callback = useMemo(() => {
// console.log("generate callback function", className);
return (newVal: boolean) => {
if (!changeCallback) {
return;
}
// 値が同じときはスルー (== 初期値(undefined)か、値が違ったのみ発火)
if (currentValForTriggerCallbackRef.current === newVal) {
return;
}
// 初期値(undefined)か、値が違ったのみ発火
currentValForTriggerCallbackRef.current = newVal;
changeCallback(currentValForTriggerCallbackRef.current);
};
}, []);
const trigger = useMemo(() => {
if (changeCallback) {
return (
<input
type="checkbox"
className={`${className} state-control-checkbox rotate-button`}
id={`${className}`}
onChange={(e) => {
callback(e.target.checked);
}}
/>
);
} else {
return <input type="checkbox" className={`${className} state-control-checkbox rotate-button`} id={`${className}`} />;
}
}, []);
const checked = useMemo(() => {
return () => {
const checkboxes = document.querySelectorAll(`.${className}`);
if (checkboxes.length == 0) {
return false
}
const box = checkboxes[0] as HTMLInputElement
return box.checked
}
}, []);
useEffect(() => {
const checkboxes = document.querySelectorAll(`.${className}`);
// (1) On/Off同期
checkboxes.forEach((x) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
x.onchange = (ev) => {
updateState(ev.target.checked);
};
});
// (2) 全エレメントoff
const removers = document.querySelectorAll(`.${className}-remover`);
removers.forEach((x) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
x.onclick = (ev) => {
if (ev.target.className.indexOf(`${className}-remover`) > 0) {
updateState(false);
}
};
});
}, []);
// (3) ステート変更
const updateState = useMemo(() => {
return (newVal: boolean) => {
const currentCheckboxes = document.querySelectorAll(`.${className}`);
currentCheckboxes.forEach((y) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
y.checked = newVal;
});
if (changeCallback) {
callback(newVal);
}
};
}, []);
return {
trigger,
updateState,
checked,
className,
};
};