Merge branch 'ui_refactor' into develop

This commit is contained in:
Sakamoto Shiina
2025-11-13 10:33:16 +09:00
20 changed files with 519 additions and 700 deletions

View File

@@ -0,0 +1,76 @@
import styles from "./_DropdownMenu.module.scss";
import clsx from "clsx";
import ArrowLeftSvg from "@images/arrow_left.svg?react";
import { useStore_IsOpenedDropdownMenu } from "@store";
export const _DropdownMenu = (props) => {
const { updateIsOpenedDropdownMenu, currentIsOpenedDropdownMenu } = useStore_IsOpenedDropdownMenu();
const toggleDropdownMenu = () => {
if (currentIsOpenedDropdownMenu.data === props.dropdown_id) {
updateIsOpenedDropdownMenu("");
} else {
if (props.openListFunction !== undefined) props.openListFunction();
updateIsOpenedDropdownMenu(props.dropdown_id);
}
};
const selectValue = (key) => {
updateIsOpenedDropdownMenu("");
props.selectFunction({
dropdown_id: props.dropdown_id,
selected_id: key,
});
};
const dropdown_content_wrapper_class_name = clsx(styles["dropdown_content_wrapper"], {
[styles.is_opened]: (currentIsOpenedDropdownMenu.data === props.dropdown_id) ? true : false,
[styles.is_disabled]: props.is_disabled,
});
const dropdown_toggle_button_class_name = clsx(styles["dropdown_toggle_button"], {
[styles.is_pending]: (props.state === "pending") ? true : false,
[styles.is_disabled]: props.is_disabled,
});
const arrow_class_names = clsx(styles["arrow_left_svg"], {
[styles.is_opened]: (currentIsOpenedDropdownMenu.data === props.dropdown_id) ? true : false
});
const getSelectedText = () => {
if (props.state !== "ok") return;
if (props.list[props.selected_id] === undefined) return props.selected_id; // [Fix me]
return props.list[props.selected_id];
};
const list = (props.list === undefined) ? {} : props.list;
return (
<div className={styles.container}>
<div className={dropdown_toggle_button_class_name} onClick={toggleDropdownMenu} style={props.style}>
{(props.state === "pending")
? <p className={styles.dropdown_selected_text}>Loading...</p>
: <p className={styles.dropdown_selected_text}>{getSelectedText()}</p>
}
{(props.state === "pending")
? <span className={styles.loader}></span>
: <ArrowLeftSvg className={arrow_class_names} />
}
</div>
<div className={dropdown_content_wrapper_class_name}>
<div className={styles.dropdown_content}>
{(props.state === "ok")
? Object.entries(list).map(([key, value]) => {
return (
<div key={key} className={styles.value_button} onClick={() => selectValue(key)}>
<p className={styles.value_text}>{value}</p>
</div>
);
})
: null
}
</div>
</div>
</div>
);
};

View File

@@ -0,0 +1,97 @@
@import "@scss_mixins";
.container {
position: relative;
}
.dropdown_toggle_button {
position: relative;
background-color: var(--dark_950_color);
min-width: 20rem;
padding: 0.8rem 1.4rem;
cursor: pointer;
border-radius: 0.4rem;
&:hover {
background-color: var(--dark_925_color);
}
&:active {
background-color: var(--dark_975_color);
}
&.is_pending {
pointer-events: none;
}
&.is_disabled {
pointer-events: none;
.dropdown_selected_text, .arrow_left_svg {
color: var(--dark_550_color);
}
}
}
.dropdown_selected_text {
font-size: 1.4rem;
padding-right: 2.8rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.dropdown_content_wrapper {
display: none;
position: absolute;
top: 100%; // Position it below the toggle button
right: 0;
min-width: 20rem;
z-index: 1;
&.is_opened {
display: block;
}
&.is_disabled {
pointer-events: none;
.value_text {
color: var(--dark_550_color);
}
}
}
.dropdown_content {
background-color: var(--dark_900_color);
border: 0.1rem solid var(--dark_600_color);
display: flex;
flex-direction: column;
gap: 0.1rem;
white-space: nowrap;
max-height: 20rem;
overflow-y: scroll;
}
.value_button {
background-color: var(--dark_875_color);
padding: 1.2rem;
cursor: pointer;
&:hover {
background-color: var(--dark_800_color);
}
&:active {
background-color: var(--dark_900_color);
}
}
.value_text {
font-size: 1.4rem;
}
.loader {
@include loader(2rem, 0.2rem, right, 0);
}
.arrow_left_svg {
position: absolute;
top: 50%;
right: 0;
transform: translate(-50%, -50%) rotate(-90deg);
width: 1.4rem;
&.is_opened {
transform: translate(-50%, -50%) rotate(90deg);
}
}

View File

@@ -0,0 +1,44 @@
import clsx from "clsx";
import { useState } from "react";
import styles from "./_SwitchBox.module.scss";
export const _SwitchBox = (props) => {
const [is_hovered, setIsHovered] = useState(false);
const [is_mouse_down, setIsMouseDown] = useState(false);
const is_pending = (props.variable.state === "pending");
const getClassNames = (base_class) => clsx(base_class, {
[styles.is_active]: (props.variable.data === true),
[styles.is_pending]: is_pending,
[styles.is_hovered]: is_hovered,
[styles.is_mouse_down]: is_mouse_down,
});
const onMouseEnter = () => setIsHovered(true);
const onMouseLeave = () => setIsHovered(false);
const onMouseDown = () => setIsMouseDown(true);
const onMouseUp = () => setIsMouseDown(false);
const toggleFunction = () => {
props.toggleFunction();
};
return (
<div className={styles.switchbox_container}>
<div className={getClassNames(styles.switchbox_wrapper)}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
onMouseDown={onMouseDown}
onMouseUp={onMouseUp}
onClick={toggleFunction}
>
<div className={getClassNames(styles.toggle_control)}>
<span className={getClassNames(styles.control)}></span>
{is_pending && <span className={styles.loader}></span>}
</div>
</div>
</div>
);
};

View File

@@ -0,0 +1,33 @@
@import "@scss_mixins";
.switchbox_container {
display: flex;
justify-content: end;
align-items: center;
height: 2rem;
}
.switchbox_wrapper {
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
padding: 2rem;
height: 100%;
flex-shrink: 0;
&.is_pending {
pointer-events: none;
}
}
.toggle_control {
position: relative;
@include toggle_control_styles;
display: flex;
justify-content: center;
align-items: center;
}
.loader {
@include loader(2rem, 0.2rem, right, -4rem);
}

View File

@@ -1,76 +1,28 @@
import styles from "./DropdownMenu.module.scss"; import styles from "./DropdownMenu.module.scss";
import clsx from "clsx"; import { _DropdownMenu } from "../_atoms/_dropdown_menu/_DropdownMenu";
import ArrowLeftSvg from "@images/arrow_left.svg?react";
import { useStore_IsOpenedDropdownMenu } from "@store";
export const DropdownMenu = (props) => { export const DropdownMenu = (props) => {
const { updateIsOpenedDropdownMenu, currentIsOpenedDropdownMenu } = useStore_IsOpenedDropdownMenu(); return (
<div className={styles.each_dropdown_menu_wrapper}>
const toggleDropdownMenu = () => { {props.secondary_label && <p className={styles.secondary_label}>{props.secondary_label}</p>}
if (currentIsOpenedDropdownMenu.data === props.dropdown_id) { <_DropdownMenu {...props} />
updateIsOpenedDropdownMenu(""); </div>
} else { );
if (props.openListFunction !== undefined) props.openListFunction(); };
updateIsOpenedDropdownMenu(props.dropdown_id);
}
};
const selectValue = (key) => {
updateIsOpenedDropdownMenu("");
props.selectFunction({
dropdown_id: props.dropdown_id,
selected_id: key,
});
};
const dropdown_content_wrapper_class_name = clsx(styles["dropdown_content_wrapper"], {
[styles.is_opened]: (currentIsOpenedDropdownMenu.data === props.dropdown_id) ? true : false,
[styles.is_disabled]: props.is_disabled,
});
const dropdown_toggle_button_class_name = clsx(styles["dropdown_toggle_button"], {
[styles.is_pending]: (props.state === "pending") ? true : false,
[styles.is_disabled]: props.is_disabled,
});
const arrow_class_names = clsx(styles["arrow_left_svg"], {
[styles.is_opened]: (currentIsOpenedDropdownMenu.data === props.dropdown_id) ? true : false
});
const getSelectedText = () => {
if (props.state !== "ok") return;
if (props.list[props.selected_id] === undefined) return props.selected_id; // [Fix me]
return props.list[props.selected_id];
};
const list = (props.list === undefined) ? {} : props.list;
export const MultiDropdownMenu = (props) => {
return ( return (
<div className={styles.container}> <div className={styles.container}>
<div className={dropdown_toggle_button_class_name} onClick={toggleDropdownMenu} style={props.style}> {props.dropdown_settings.map((dropdown_props, index) => {
{(props.state === "pending") if (dropdown_props.insert_component) {
? <p className={styles.dropdown_selected_text}>Loading...</p> const InsertComponent = dropdown_props.insert_component;
: <p className={styles.dropdown_selected_text}>{getSelectedText()}</p> return <InsertComponent key={index} {...dropdown_props.insert_component_props} />;
} }
{(props.state === "pending") return (
? <span className={styles.loader}></span> <DropdownMenu key={dropdown_props.dropdown_id} {...dropdown_props} />
: <ArrowLeftSvg className={arrow_class_names} /> );
} }
</div> )}
<div className={dropdown_content_wrapper_class_name}>
<div className={styles.dropdown_content}>
{(props.state === "ok")
? Object.entries(list).map(([key, value]) => {
return (
<div key={key} className={styles.value_button} onClick={() => selectValue(key)}>
<p className={styles.value_text}>{value}</p>
</div>
);
})
: null
}
</div>
</div>
</div> </div>
); );
}; };

View File

@@ -1,97 +1,26 @@
@import "@scss_mixins"; @import "@scss_mixins";
.container { .container {
position: relative; display: flex;
flex-direction: row;
gap: 2.8rem;
} }
.dropdown_toggle_button { .each_dropdown_menu_wrapper {
position: relative;
background-color: var(--dark_950_color);
min-width: 20rem;
padding: 0.8rem 1.4rem;
cursor: pointer;
border-radius: 0.4rem;
&:hover {
background-color: var(--dark_925_color);
}
&:active {
background-color: var(--dark_975_color);
}
&.is_pending {
pointer-events: none;
}
&.is_disabled {
pointer-events: none;
.dropdown_selected_text, .arrow_left_svg {
color: var(--dark_550_color);
}
}
}
.dropdown_selected_text {
font-size: 1.4rem;
padding-right: 2.8rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.dropdown_content_wrapper {
display: none;
position: absolute;
top: 100%; // Position it below the toggle button
right: 0;
min-width: 20rem;
z-index: 1;
&.is_opened {
display: block;
}
&.is_disabled {
pointer-events: none;
.value_text {
color: var(--dark_550_color);
}
}
}
.dropdown_content {
background-color: var(--dark_900_color);
border: 0.1rem solid var(--dark_600_color);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0.1rem; gap: 0.6rem;
white-space: nowrap; white-space: nowrap;
max-height: 20rem; max-width: 24rem;
overflow-y: scroll; &.is_disabled {
} pointer-events: none;
.value_button {
background-color: var(--dark_875_color);
padding: 1.2rem;
cursor: pointer;
&:hover {
background-color: var(--dark_800_color);
}
&:active {
background-color: var(--dark_900_color);
} }
} }
.value_text { .secondary_label {
padding-left: 0.2rem;
padding-right: 0.4rem;
font-size: 1.4rem; font-size: 1.4rem;
} color: var(--dark_500_color);
white-space: nowrap;
.loader {
@include loader(2rem, 0.2rem, right, 0);
}
.arrow_left_svg {
position: absolute;
top: 50%;
right: 0;
transform: translate(-50%, -50%) rotate(-90deg);
width: 1.4rem;
&.is_opened {
transform: translate(-50%, -50%) rotate(90deg);
}
} }

View File

@@ -1,7 +1,7 @@
export { ActionButton } from "./action_button/ActionButton"; export { ActionButton } from "./action_button/ActionButton";
export { ComputeDevice } from "./compute_device/ComputeDevice"; export { ComputeDevice } from "./compute_device/ComputeDevice";
export { DeeplAuthKey, OpenWebpage_DeeplAuthKey } from "./deepl_auth_key/DeeplAuthKey"; export { DeeplAuthKey, OpenWebpage_DeeplAuthKey } from "./deepl_auth_key/DeeplAuthKey";
export { DropdownMenu } from "./dropdown_menu/DropdownMenu"; export { DropdownMenu, MultiDropdownMenu } from "./dropdown_menu/DropdownMenu";
export { Entry } from "./entry/Entry"; export { Entry } from "./entry/Entry";
export { EntryWithSaveButton } from "./entry_with_save_button/EntryWithSaveButton"; export { EntryWithSaveButton } from "./entry_with_save_button/EntryWithSaveButton";
export { HotkeysEntry } from "./hotkeys_entry/HotkeysEntry"; export { HotkeysEntry } from "./hotkeys_entry/HotkeysEntry";

View File

@@ -1,44 +1,13 @@
import clsx from "clsx"; import clsx from "clsx";
import { useState } from "react"; import { useState } from "react";
import styles from "./SwitchBox.module.scss"; import styles from "./SwitchBox.module.scss";
import { _SwitchBox } from "../_atoms/_switch_box/_SwitchBox";
export const SwitchBox = (props) => { export const SwitchBox = (props) => {
const [is_hovered, setIsHovered] = useState(false);
const [is_mouse_down, setIsMouseDown] = useState(false);
const is_pending = (props.variable.state === "pending");
const getClassNames = (base_class) => clsx(base_class, {
[styles.is_active]: (props.variable.data === true),
[styles.is_pending]: is_pending,
[styles.is_hovered]: is_hovered,
[styles.is_mouse_down]: is_mouse_down,
});
const onMouseEnter = () => setIsHovered(true);
const onMouseLeave = () => setIsHovered(false);
const onMouseDown = () => setIsMouseDown(true);
const onMouseUp = () => setIsMouseDown(false);
const toggleFunction = () => {
props.toggleFunction();
};
return ( return (
<div className={styles.switchbox_container}> <div className={styles.container}>
<div className={getClassNames(styles.switchbox_wrapper)} {props.secondary_label && <p className={styles.secondary_label}>{props.secondary_label}</p>}
onMouseEnter={onMouseEnter} <_SwitchBox {...props} />
onMouseLeave={onMouseLeave}
onMouseDown={onMouseDown}
onMouseUp={onMouseUp}
onClick={toggleFunction}
>
<div className={getClassNames(styles.toggle_control)}>
<span className={getClassNames(styles.control)}></span>
{is_pending && <span className={styles.loader}></span>}
</div>
</div>
</div> </div>
); );
}; };

View File

@@ -1,33 +1,17 @@
@import "@scss_mixins"; @import "@scss_mixins";
.switchbox_container { .container {
display: flex;
justify-content: end;
align-items: center;
height: 2rem;
}
.switchbox_wrapper {
display: flex; display: flex;
flex-direction: column;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
cursor: pointer; gap: 1rem;
padding: 2rem;
height: 100%;
flex-shrink: 0;
&.is_pending {
pointer-events: none;
}
} }
.toggle_control { .secondary_label {
position: relative; padding-left: 0.2rem;
@include toggle_control_styles; padding-right: 0.4rem;
display: flex; font-size: 1.4rem;
justify-content: center; color: var(--dark_500_color);
align-items: center; white-space: nowrap;
}
.loader {
@include loader(2rem, 0.2rem, right, -4rem);
} }

View File

@@ -50,14 +50,14 @@ export const WordFilter = () => {
return ( return (
<div className={styles.container}> <div className={styles.container}>
{ currentIsOpenedMicWordFilterList.data && { currentIsOpenedMicWordFilterList.data && currentMicWordFilterList.data.length > 0 &&
<div className={styles.list_section_wrapper}> <div className={styles.list_section_wrapper}>
{ {
currentMicWordFilterList.data.map((item, index) => { currentMicWordFilterList.data.map((item, index) => {
return <WordFilterItem value={item} key={index} deleteAction={deleteAction}/>; return <WordFilterItem value={item} key={index} deleteAction={deleteAction}/>;
}) })
} }
</div> </div>
} }
<div className={styles.entry_section_wrapper}> <div className={styles.entry_section_wrapper}>
<_Entry width="30rem" onChange={onChangeEntry} ui_variable={input_value}/> <_Entry width="30rem" onChange={onChangeEntry} ui_variable={input_value}/>

View File

@@ -4,11 +4,13 @@
align-items: center; align-items: center;
flex-direction: column; flex-direction: column;
gap: 2rem; gap: 2rem;
width: 100%;
} }
.list_section_wrapper { .list_section_wrapper {
display: flex; display: flex;
justify-content: center;
flex-wrap: wrap; flex-wrap: wrap;
width: 100%; width: 100%;
gap: 0.6rem; gap: 0.6rem;

View File

@@ -5,6 +5,7 @@ import { useStore_IsOpenedDropdownMenu, useStore_IsBreakPoint } from "@store";
import { import {
LabelComponent, LabelComponent,
DropdownMenu, DropdownMenu,
MultiDropdownMenu,
Slider, Slider,
SwitchBox, SwitchBox,
Entry, Entry,
@@ -22,13 +23,6 @@ import {
} from "../_components"; } from "../_components";
import { Checkbox } from "@common_components"; import { Checkbox } from "@common_components";
const LabeledContainer = ({ children, label, desc, custom_class_name }) => (
<div className={clsx(styles.container, custom_class_name)}>
<LabelComponent label={label} desc={desc} />
{children}
</div>
);
export const useOnMouseLeaveDropdownMenu = () => { export const useOnMouseLeaveDropdownMenu = () => {
const { updateIsOpenedDropdownMenu } = useStore_IsOpenedDropdownMenu(); const { updateIsOpenedDropdownMenu } = useStore_IsOpenedDropdownMenu();
@@ -41,27 +35,87 @@ export const useOnMouseLeaveDropdownMenu = () => {
export const DropdownMenuContainer = (props) => { export const DropdownMenuContainer = (props) => {
const { onMouseLeaveFunction } = useOnMouseLeaveDropdownMenu(); const { onMouseLeaveFunction } = useOnMouseLeaveDropdownMenu();
return ( return (
<div className={styles.container} onMouseLeave={onMouseLeaveFunction}> <TemplatesContainerWrapper onMouseLeaveFunction={onMouseLeaveFunction} {...props}>
<LabelComponent label={props.label} desc={props.desc} /> <LabelComponent label={props.label} desc={props.desc} />
<DropdownMenu {...props} /> <DropdownMenu {...props} />
</TemplatesContainerWrapper>
);
};
export const MultiDropdownMenuContainer = (props) => {
const { onMouseLeaveFunction } = useOnMouseLeaveDropdownMenu();
return (
<TemplatesContainerWrapper onMouseLeaveFunction={onMouseLeaveFunction} {...props}>
<LabelComponent label={props.label} desc={props.desc} />
<MultiDropdownMenu dropdown_settings={props.dropdown_settings} />
</TemplatesContainerWrapper>
);
};
const TemplatesContainerWrapper = ({
children,
add_break_point = true,
flex_column = false,
remove_border_bottom = false,
onMouseLeaveFunction = null,
}) => {
const { currentIsBreakPoint } = useStore_IsBreakPoint();
const container_class = clsx(styles.container, {
[styles.is_break_point]: add_break_point && currentIsBreakPoint.data,
[styles.flex_column]: flex_column,
[styles.remove_border_bottom]: remove_border_bottom,
});
return (
<div className={container_class} onMouseLeave={onMouseLeaveFunction}>
{children}
</div> </div>
); );
}; };
const CommonContainer = ({ Component, ...props }) => { const CommonContainer = ({
label_type = "label_component",
add_break_point = true,
flex_column = false,
remove_border_bottom = false,
Component,
...props
}) => {
const { currentIsBreakPoint } = useStore_IsBreakPoint(); const { currentIsBreakPoint } = useStore_IsBreakPoint();
const container_class = clsx(styles.container, { const container_wrapper_props = {
[styles.is_break_point]: props.add_break_point ?? currentIsBreakPoint.data, add_break_point: add_break_point,
}); flex_column: flex_column,
remove_border_bottom: remove_border_bottom,
};
return ( if (label_type === "label_component") {
<LabeledContainer label={props.label} desc={props.desc} custom_class_name={container_class}> return (
<Component {...props} is_break_point={currentIsBreakPoint.data} /> <TemplatesContainerWrapper {...container_wrapper_props}>
</LabeledContainer> <LabelComponent label={props.label} desc={props.desc} />
); <Component {...props} is_break_point={currentIsBreakPoint.data} />
</TemplatesContainerWrapper>
);
} else if (label_type === "no_label") {
return (
<TemplatesContainerWrapper {...container_wrapper_props}>
<Component {...props} is_break_point={currentIsBreakPoint.data} />
</TemplatesContainerWrapper>
);
} else if (label_type === "label_only") {
return (
<TemplatesContainerWrapper {...container_wrapper_props}>
<LabelComponent label={props.label} desc={props.desc} />
</TemplatesContainerWrapper>
);
}
}; };
export const SliderContainer = (props) => ( export const SliderContainer = (props) => (
<CommonContainer Component={Slider} {...props} /> <CommonContainer Component={Slider} {...props} />
); );
@@ -90,19 +144,14 @@ export const RadioButtonContainer = (props) => (
); );
export const DeeplAuthKeyContainer = (props) => { export const DeeplAuthKeyContainer = (props) => {
const { currentIsBreakPoint } = useStore_IsBreakPoint();
const container_class = clsx(styles.container, {
[styles.is_break_point]: currentIsBreakPoint.data,
});
return ( return (
<div className={container_class}> <TemplatesContainerWrapper>
<div className={styles.deepl_auth_key_label_section}> <div className={styles.deepl_auth_key_label_section}>
<LabelComponent label={props.label} desc={props.desc} /> <LabelComponent label={props.label} desc={props.desc} />
<OpenWebpage_DeeplAuthKey /> <OpenWebpage_DeeplAuthKey />
</div> </div>
<DeeplAuthKey {...props} /> <DeeplAuthKey {...props} />
</div> </TemplatesContainerWrapper>
); );
}; };
@@ -114,19 +163,22 @@ export const ComputeDeviceContainer = (props) => (
<CommonContainer Component={ComputeDevice} {...props} /> <CommonContainer Component={ComputeDevice} {...props} />
); );
export const WordFilterContainer = (props) => ( export const WordFilterContainer = (props) => {
<div className={styles.word_filter_container}> return (
<div className={styles.word_filter_switch_section}> <>
<div className={styles.word_filter_label_wrapper}> <CommonContainer
<LabelComponent label={props.label} desc={props.desc} /> Component={WordFilterListToggleComponent}
</div> remove_border_bottom={true}
<WordFilterListToggleComponent /> {...props}
</div> />
<div className={styles.word_filter_section}> <CommonContainer
<WordFilter {...props} /> Component={WordFilter}
</div> label_type="no_label"
</div> {...props}
); />
</>
);
};
export const DownloadModelsContainer = (props) => ( export const DownloadModelsContainer = (props) => (
<CommonContainer Component={DownloadModels} {...props} /> <CommonContainer Component={DownloadModels} {...props} />
@@ -134,13 +186,17 @@ export const DownloadModelsContainer = (props) => (
export const MessageFormatContainer = (props) => { export const MessageFormatContainer = (props) => {
return ( return (
<div className={clsx(styles.container, styles.flex_column)}> <>
<div className={styles.label_only_section}> <CommonContainer
<LabelComponent label={props.label} desc={props.desc} /> remove_border_bottom={true}
</div> label_type="label_only"
<div className={styles.message_format_section}> {...props}
<MessageFormat {...props}/> />
</div> <CommonContainer
</div> Component={MessageFormat}
label_type="no_label"
{...props}
/>
</>
); );
}; };

View File

@@ -8,7 +8,9 @@
&.flex_column { &.flex_column {
flex-direction: column; flex-direction: column;
} }
border-bottom: solid 0.1rem var(--dark_800_color); &:not(.remove_border_bottom) {
border-bottom: solid 0.1rem var(--dark_800_color);
}
&.is_break_point { &.is_break_point {
flex-direction: column; flex-direction: column;
@@ -17,10 +19,6 @@
} }
} }
.label_only_section {
width: 100%;
}
.deepl_auth_key_label_section { .deepl_auth_key_label_section {
max-width: 34rem; max-width: 34rem;
display: flex; display: flex;
@@ -28,30 +26,4 @@
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
gap: 1.4rem; gap: 1.4rem;
}
.message_format_section {
width: 100%;
}
.word_filter_container {
display: flex;
width: 100%;
flex-direction: column;
justify-content: space-between;
align-items: center;
gap: 2rem;
padding: 2rem;
}
.word_filter_switch_section {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
}
.word_filter_label_wrapper {
max-width: 34rem;
} }

View File

@@ -9,11 +9,13 @@ import {
import { import {
useOnMouseLeaveDropdownMenu, useOnMouseLeaveDropdownMenu,
MultiDropdownMenuContainer,
} from "../_templates/Templates"; } from "../_templates/Templates";
import { import {
LabelComponent, LabelComponent,
DropdownMenu, DropdownMenu,
MultiDropdownMenu,
ThresholdComponent, ThresholdComponent,
SwitchBox, SwitchBox,
} from "../_components"; } from "../_components";
@@ -70,53 +72,41 @@ const Mic_Container = () => {
} }
}; };
const { currentIsBreakPoint } = useStore_IsBreakPoint();
const device_container_class = clsx(styles.device_container, {
[styles.is_break_point]: currentIsBreakPoint.data,
});
return ( return (
<div className={styles.mic_container}> <div className={styles.mic_container}>
<div className={device_container_class} onMouseLeave={onMouseLeaveFunction}> <MultiDropdownMenuContainer
<LabelComponent label={t("config_page.device.mic_host_device.label")} /> label={t("config_page.device.mic_host_device.label")}
<div className={styles.device_contents}> remove_border_bottom={true}
dropdown_settings={[
<div className={styles.device_auto_select_wrapper}> {
<p className={styles.device_secondary_label}>{t("config_page.device.label_auto_select")}</p> insert_component: SwitchBox,
<SwitchBox insert_component_props: {
variable={currentEnableAutoMicSelect} secondary_label: t("config_page.device.label_auto_select"),
toggleFunction={toggleEnableAutoMicSelect} variable: currentEnableAutoMicSelect,
/> toggleFunction: toggleEnableAutoMicSelect,
</div> }
},
<div className={styles.device_dropdown_wrapper}> {
<div className={styles.device_dropdown}> dropdown_id: "mic_host",
<p className={styles.device_secondary_label}>{t("config_page.device.label_host")}</p> secondary_label: t("config_page.device.label_host"),
<DropdownMenu selected_id: currentSelectedMicHost.data,
dropdown_id="mic_host" list: currentMicHostList.data,
selected_id={currentSelectedMicHost.data} selectFunction: selectFunction_host,
list={currentMicHostList.data} state: currentSelectedMicHost.state,
selectFunction={selectFunction_host} style: { maxWidth: "20rem", minWidth: "10rem" },
state={currentSelectedMicHost.state} is_disabled: is_disabled_selector,
style={{ maxWidth: "20rem", minWidth: "10rem" }} },
is_disabled={is_disabled_selector} {
/> dropdown_id: "mic_device",
</div> secondary_label: t("config_page.device.label_device"),
selected_id: currentSelectedMicDevice.data,
<div className={styles.device_dropdown}> list: currentMicDeviceList.data,
<p className={styles.device_secondary_label}>{t("config_page.device.label_device")}</p> selectFunction: selectFunction_device,
<DropdownMenu state: currentSelectedMicDevice.state,
dropdown_id="mic_device" is_disabled: is_disabled_selector,
selected_id={currentSelectedMicDevice.data} }
list={currentMicDeviceList.data} ]}
selectFunction={selectFunction_device} />
state={currentSelectedMicDevice.state}
is_disabled={is_disabled_selector}
/>
</div>
</div>
</div>
</div>
<div className={styles.threshold_container}> <div className={styles.threshold_container}>
<div className={styles.threshold_switch_section}> <div className={styles.threshold_switch_section}>
<LabelComponent {...getLabels()} /> <LabelComponent {...getLabels()} />
@@ -181,27 +171,21 @@ const Speaker_Container = () => {
<div className={device_container_class} onMouseLeave={onMouseLeaveFunction}> <div className={device_container_class} onMouseLeave={onMouseLeaveFunction}>
<LabelComponent label={t("config_page.device.speaker_device.label")} /> <LabelComponent label={t("config_page.device.speaker_device.label")} />
<div className={styles.device_contents}> <div className={styles.device_contents}>
<SwitchBox
<div className={styles.device_auto_select_wrapper}> secondary_label={t("config_page.device.label_auto_select")}
<p className={styles.device_secondary_label}>{t("config_page.device.label_auto_select")}</p> variable={currentEnableAutoSpeakerSelect}
<SwitchBox toggleFunction={toggleEnableAutoSpeakerSelect}
variable={currentEnableAutoSpeakerSelect} />
toggleFunction={toggleEnableAutoSpeakerSelect} <DropdownMenu
/> dropdown_id="speaker_device"
</div> secondary_label={t("config_page.device.label_device")}
label={t("config_page.device.speaker_device.label")}
<div className={styles.device_dropdown}> selected_id={currentSelectedSpeakerDevice.data}
<p className={styles.device_secondary_label}>{t("config_page.device.label_device")}</p> list={currentSpeakerDeviceList.data}
<DropdownMenu selectFunction={selectFunction}
dropdown_id="speaker_device" state={currentSelectedSpeakerDevice.state}
label={t("config_page.device.speaker_device.label")} is_disabled={is_disabled_selector}
selected_id={currentSelectedSpeakerDevice.data} />
list={currentSpeakerDeviceList.data}
selectFunction={selectFunction}
state={currentSelectedSpeakerDevice.state}
is_disabled={is_disabled_selector}
/>
</div>
</div> </div>
</div> </div>
<div className={styles.threshold_container}> <div className={styles.threshold_container}>

View File

@@ -77,29 +77,4 @@
gap: 1.2rem; gap: 1.2rem;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
}
.device_dropdown_wrapper {
display: flex;
flex-direction: row;
gap: 2.8rem;
}
.device_dropdown {
display: flex;
flex-direction: column;
gap: 0.6rem;
white-space: nowrap;
max-width: 24rem;
&.is_disabled {
pointer-events: none;
}
}
.device_secondary_label {
padding-left: 0.2rem;
padding-right: 0.4rem;
font-size: 1.4rem;
color: var(--dark_500_color);
white-space: nowrap;
} }

View File

@@ -1,5 +1,5 @@
import { SwitchBox } from "../../_components";
import { _DownloadButton } from "../../_components/_atoms/_download_button/_DownloadButton"; import { _DownloadButton } from "../../_components/_atoms/_download_button/_DownloadButton";
import { _SwitchBox } from "../../_components/_atoms/_switch_box/_SwitchBox";
import styles from "./PluginsControlComponent.module.scss"; import styles from "./PluginsControlComponent.module.scss";
import { useI18n } from "@useI18n"; import { useI18n } from "@useI18n";
@@ -90,7 +90,7 @@ const DownloadedPluginControl = ({
return ( return (
<div className={styles.container}> <div className={styles.container}>
<p>{t("config_page.plugins.no_latest_info")}</p> <p>{t("config_page.plugins.no_latest_info")}</p>
<SwitchBox variable={option} toggleFunction={togglePlugin} /> <_SwitchBox variable={option} toggleFunction={togglePlugin} />
</div> </div>
); );
} else if (plugin_status.is_latest_version_already) { } else if (plugin_status.is_latest_version_already) {
@@ -98,7 +98,7 @@ const DownloadedPluginControl = ({
<div className={styles.container}> <div className={styles.container}>
<p>{latest_version_label}</p> <p>{latest_version_label}</p>
<p>{t("config_page.plugins.using_latest_version")}</p> <p>{t("config_page.plugins.using_latest_version")}</p>
<SwitchBox variable={option} toggleFunction={togglePlugin} /> <_SwitchBox variable={option} toggleFunction={togglePlugin} />
</div> </div>
); );
} else if (plugin_status.is_latest_version_available) { } else if (plugin_status.is_latest_version_available) {
@@ -107,14 +107,14 @@ const DownloadedPluginControl = ({
<p>{latest_version_label}</p> <p>{latest_version_label}</p>
<p>{t("config_page.plugins.available_latest_version")}</p> <p>{t("config_page.plugins.available_latest_version")}</p>
<_DownloadButton option={option} downloadStartFunction={downloadStartFunction} /> <_DownloadButton option={option} downloadStartFunction={downloadStartFunction} />
<SwitchBox variable={option} toggleFunction={togglePlugin} /> <_SwitchBox variable={option} toggleFunction={togglePlugin} />
</div> </div>
); );
} else { } else {
return ( return (
<div className={styles.container}> <div className={styles.container}>
<p>{t("config_page.plugins.available_latest_version")}</p> <p>{t("config_page.plugins.available_latest_version")}</p>
<SwitchBox variable={option} toggleFunction={togglePlugin} /> <_SwitchBox variable={option} toggleFunction={togglePlugin} />
</div> </div>
); );
} }

View File

@@ -11,6 +11,7 @@ import {
import { import {
WordFilterContainer, WordFilterContainer,
DownloadModelsContainer, DownloadModelsContainer,
MultiDropdownMenuContainer,
RadioButtonContainer, RadioButtonContainer,
DropdownMenuContainer, DropdownMenuContainer,
SliderContainer, SliderContainer,
@@ -20,6 +21,7 @@ import {
import { import {
DropdownMenu, DropdownMenu,
MultiDropdownMenu,
LabelComponent, LabelComponent,
SectionLabelComponent, SectionLabelComponent,
} from "../_components"; } from "../_components";
@@ -281,8 +283,6 @@ const TranscriptionComputeDevice_Box = () => {
currentSelectedTranscriptionComputeType, currentSelectedTranscriptionComputeType,
setSelectedTranscriptionComputeType, setSelectedTranscriptionComputeType,
} = useTranscription(); } = useTranscription();
const { onMouseLeaveFunction } = useOnMouseLeaveDropdownMenu();
const { currentIsBreakPoint } = useStore_IsBreakPoint();
const list_for_ui = transformDeviceArray(currentSelectableTranscriptionComputeDeviceList.data); const list_for_ui = transformDeviceArray(currentSelectableTranscriptionComputeDeviceList.data);
@@ -364,50 +364,34 @@ const TranscriptionComputeDevice_Box = () => {
setSelectedTranscriptionComputeType(selected_data.selected_id); setSelectedTranscriptionComputeType(selected_data.selected_id);
}; };
const device_container_class = clsx(styles.device_container, {
[styles.is_break_point]: currentIsBreakPoint.data,
});
const is_disabled_selector = currentSelectedTranscriptionComputeDevice.state === "pending" || currentSelectedTranscriptionComputeType.state === "pending"; const is_disabled_selector = currentSelectedTranscriptionComputeDevice.state === "pending" || currentSelectedTranscriptionComputeType.state === "pending";
return ( return (
<div className={styles.mic_container}> <MultiDropdownMenuContainer
<div className={device_container_class} onMouseLeave={onMouseLeaveFunction}> label={t("config_page.transcription.transcription_compute_device.label")}
<LabelComponent desc={t("config_page.common.compute_device.desc")}
label={t("config_page.transcription.transcription_compute_device.label")} dropdown_settings={[
desc={t("config_page.common.compute_device.desc")} {
/> secondary_label: t("config_page.common.compute_device.label_device"),
<div className={styles.device_contents}> dropdown_id: "transcription_compute_device",
selected_id: target_index,
<div className={styles.device_dropdown_wrapper}> list: list_for_ui,
<div className={styles.device_dropdown}> selectFunction: selectFunction_ComputeDevice,
<p className={styles.device_secondary_label}>{t("config_page.common.compute_device.label_device")}</p> state: currentSelectedTranscriptionComputeDevice.state,
<DropdownMenu style: { maxWidth: "20rem", minWidth: "10rem" },
dropdown_id="transcription_compute_device" is_disabled: is_disabled_selector,
selected_id={target_index} },
list={list_for_ui} {
selectFunction={selectFunction_ComputeDevice} secondary_label: t("config_page.common.compute_device.label_type"),
state={currentSelectedTranscriptionComputeDevice.state} dropdown_id: "transcription_compute_type",
style={{ maxWidth: "20rem", minWidth: "10rem" }} selected_id: currentSelectedTranscriptionComputeType.data,
is_disabled={is_disabled_selector} list: new_compute_types_labels,
/> selectFunction: selectFunction_ComputeType,
</div> state: currentSelectedTranscriptionComputeType.state,
is_disabled: is_disabled_selector,
<div className={styles.device_dropdown}> }
<p className={styles.device_secondary_label}>{t("config_page.common.compute_device.label_type")}</p> ]}
<DropdownMenu />
dropdown_id="transcription_compute_type"
selected_id={currentSelectedTranscriptionComputeType.data}
list={new_compute_types_labels}
selectFunction={selectFunction_ComputeType}
state={currentSelectedTranscriptionComputeType.state}
is_disabled={is_disabled_selector}
/>
</div>
</div>
</div>
</div>
</div>
); );
}; };

View File

@@ -2,120 +2,4 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 6.4rem; gap: 6.4rem;
}
// [Fix me] Need refactor.
.mic_container {
display: flex;
flex-direction: column;
border-bottom: solid 0.1rem var(--dark_800_color);
padding-bottom: 1rem;
}
.speaker_container {
padding-top: 0rem;
}
.device_container {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
padding: 2rem;
margin-bottom: 0rem;
&.is_break_point {
flex-direction: column;
gap: 2rem;
align-items: start;
& .device_contents {
display: flex;
width: 100%;
justify-content: space-between;
padding-left: 0rem;
}
}
}
.threshold_container {
padding: 2rem;
}
.threshold_container {
display: flex;
width: 100%;
flex-direction: column;
justify-content: space-between;
align-items: center;
gap: 2rem;
}
.threshold_switch_section {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
}
.threshold_section {
width: 100%;
}
.device_label {
font-size: 1.8rem;
}
.device_contents {
display: flex;
width: 100%;
justify-content: end;
padding-left: 2rem;
gap: 2rem;
}
.device_auto_select_wrapper {
display: flex;
flex-direction: column;
gap: 1.2rem;
justify-content: center;
align-items: center;
}
.device_dropdown_wrapper {
display: flex;
flex-direction: row;
gap: 2.8rem;
}
.device_dropdown {
display: flex;
flex-direction: column;
gap: 0.6rem;
white-space: nowrap;
max-width: 24rem;
&.is_disabled {
pointer-events: none;
}
}
.device_secondary_label {
padding-left: 0.2rem;
padding-right: 0.4rem;
font-size: 1.4rem;
color: var(--dark_500_color);
white-space: nowrap;
} }

View File

@@ -11,12 +11,14 @@ import {
import { import {
DownloadModelsContainer, DownloadModelsContainer,
DeeplAuthKeyContainer, DeeplAuthKeyContainer,
MultiDropdownMenuContainer,
useOnMouseLeaveDropdownMenu, useOnMouseLeaveDropdownMenu,
} from "../_templates/Templates"; } from "../_templates/Templates";
import { import {
DropdownMenu, DropdownMenu,
MultiDropdownMenu,
LabelComponent, LabelComponent,
} from "../_components"; } from "../_components";
@@ -89,8 +91,6 @@ const TranslationComputeDevice_Box = () => {
currentSelectedTranslationComputeType, currentSelectedTranslationComputeType,
setSelectedTranslationComputeType, setSelectedTranslationComputeType,
} = useTranslation(); } = useTranslation();
const { onMouseLeaveFunction } = useOnMouseLeaveDropdownMenu();
const { currentIsBreakPoint } = useStore_IsBreakPoint();
const list_for_ui = transformDeviceArray(currentSelectableTranslationComputeDeviceList.data); const list_for_ui = transformDeviceArray(currentSelectableTranslationComputeDeviceList.data);
@@ -172,50 +172,34 @@ const TranslationComputeDevice_Box = () => {
setSelectedTranslationComputeType(selected_data.selected_id); setSelectedTranslationComputeType(selected_data.selected_id);
}; };
const device_container_class = clsx(styles.device_container, {
[styles.is_break_point]: currentIsBreakPoint.data,
});
const is_disabled_selector = currentSelectedTranslationComputeDevice.state === "pending" || currentSelectedTranslationComputeType.state === "pending"; const is_disabled_selector = currentSelectedTranslationComputeDevice.state === "pending" || currentSelectedTranslationComputeType.state === "pending";
return ( return (
<div className={styles.mic_container}> <MultiDropdownMenuContainer
<div className={device_container_class} onMouseLeave={onMouseLeaveFunction}> label={t("config_page.translation.translation_compute_device.label")}
<LabelComponent desc={t("config_page.common.compute_device.desc")}
label={t("config_page.translation.translation_compute_device.label")} dropdown_settings={[
desc={t("config_page.common.compute_device.desc")} {
/> dropdown_id: "translation_compute_device",
<div className={styles.device_contents}> secondary_label: t("config_page.common.compute_device.label_device"),
selected_id: target_index,
<div className={styles.device_dropdown_wrapper}> list: list_for_ui,
<div className={styles.device_dropdown}> selectFunction: selectFunction_ComputeDevice,
<p className={styles.device_secondary_label}>{t("config_page.common.compute_device.label_device")}</p> state: currentSelectedTranslationComputeDevice.state,
<DropdownMenu style: { maxWidth: "20rem", minWidth: "10rem" },
dropdown_id="translation_compute_device" is_disabled: is_disabled_selector,
selected_id={target_index} },
list={list_for_ui} {
selectFunction={selectFunction_ComputeDevice} dropdown_id: "translation_compute_type",
state={currentSelectedTranslationComputeDevice.state} secondary_label: t("config_page.common.compute_device.label_type"),
style={{ maxWidth: "20rem", minWidth: "10rem" }} selected_id: currentSelectedTranslationComputeType.data,
is_disabled={is_disabled_selector} list: new_compute_types_labels,
/> selectFunction: selectFunction_ComputeType,
</div> state: currentSelectedTranslationComputeType.state,
is_disabled: is_disabled_selector,
<div className={styles.device_dropdown}> }
<p className={styles.device_secondary_label}>{t("config_page.common.compute_device.label_type")}</p> ]}
<DropdownMenu />
dropdown_id="translation_compute_type"
selected_id={currentSelectedTranslationComputeType.data}
list={new_compute_types_labels}
selectFunction={selectFunction_ComputeType}
state={currentSelectedTranslationComputeType.state}
is_disabled={is_disabled_selector}
/>
</div>
</div>
</div>
</div>
</div>
); );
}; };

View File

@@ -1,106 +0,0 @@
// [Fix me] Need refactor.
.mic_container {
display: flex;
flex-direction: column;
border-bottom: solid 0.1rem var(--dark_800_color);
padding-bottom: 1rem;
}
.speaker_container {
padding-top: 0rem;
}
.device_container {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
padding: 2rem;
margin-bottom: 0rem;
&.is_break_point {
flex-direction: column;
gap: 2rem;
align-items: start;
& .device_contents {
display: flex;
width: 100%;
justify-content: space-between;
padding-left: 0rem;
}
}
}
.threshold_container {
padding: 2rem;
}
.threshold_container {
display: flex;
width: 100%;
flex-direction: column;
justify-content: space-between;
align-items: center;
gap: 2rem;
}
.threshold_switch_section {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
}
.threshold_section {
width: 100%;
}
.device_label {
font-size: 1.8rem;
}
.device_contents {
display: flex;
width: 100%;
justify-content: end;
padding-left: 2rem;
gap: 2rem;
}
.device_auto_select_wrapper {
display: flex;
flex-direction: column;
gap: 1.2rem;
justify-content: center;
align-items: center;
}
.device_dropdown_wrapper {
display: flex;
flex-direction: row;
gap: 2.8rem;
}
.device_dropdown {
display: flex;
flex-direction: column;
gap: 0.6rem;
white-space: nowrap;
max-width: 24rem;
&.is_disabled {
pointer-events: none;
}
}
.device_secondary_label {
padding-left: 0.2rem;
padding-right: 0.4rem;
font-size: 1.4rem;
color: var(--dark_500_color);
white-space: nowrap;
}