feat(components): add control and visual components

This commit is contained in:
hexxa 2021-11-26 15:53:19 +08:00 committed by Hexxa
parent 5f0d8e2737
commit 7156c22a56
5 changed files with 204 additions and 23 deletions

View file

@ -0,0 +1,80 @@
import * as React from "react";
import { List, Map, update } from "immutable";
import { updater } from "../state_updater";
import { getIcon } from "../visual/icons";
import { Flexbox } from "../layout/flexbox";
import { ICoreState, MsgProps, UIProps } from "../core_state";
import { AdminProps } from "../pane_admin";
import { LoginProps } from "../pane_login";
import { alertMsg } from "../../common/env";
import { IconProps } from "../visual/icons";
import { colorClass } from "../visual/colors";
const defaultIconProps: IconProps = {
name: "RiFolder2Fill",
size: "1.6rem",
color: `${colorClass("cyan0")}-font`,
};
export interface Props {
targetSwitch: string;
tabIcons: Map<string, IconProps>; // option name -> icon name
login: LoginProps;
admin: AdminProps;
ui: UIProps;
msg: MsgProps;
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
}
export interface State {}
export class Tabs extends React.Component<Props, State, {}> {
constructor(p: Props) {
super(p);
}
setTab = (targetSwitch: string, targetOption: string) => {
if (!updater().setControlOption(targetSwitch, targetOption)) {
alertMsg(this.props.msg.pkg.get("op.fail"));
}
};
render() {
const displaying = this.props.ui.control.controls.get(
this.props.targetSwitch
);
const options = this.props.ui.control.options.get(this.props.targetSwitch);
const tabs = options.map((option: string, targetSwitch: string) => {
const iconProps = this.props.tabIcons.has(option)
? this.props.tabIcons.get(option)
: defaultIconProps;
// <RiFolder2Fill size="1.6rem" className="margin-r-s cyan0-font" />,
const icon = getIcon(iconProps.name, iconProps.size, iconProps.color);
return (
<button
key={`${targetSwitch}-${option}`}
onClick={() => {
this.setTab(targetSwitch, option);
}}
className="float"
>
<Flexbox
children={List([
<span className="margin-r-s">{icon}</span>,
<span>
{this.props.msg.pkg.get(`switch.${targetSwitch}.${option}`)}
</span>,
])}
childrenStyles={List([{ flex: "30%" }, { flex: "70%" }])}
/>
</button>
);
});
return (
<div className={`tabs control-${this.props.targetSwitch}`}>{tabs}</div>
);
}
}

View file

@ -11,10 +11,6 @@ import { AdminProps } from "./pane_admin";
import { MsgPackage } from "../i18n/msger";
import { User, MetadataResp } from "../client";
export interface PanelsProps {
displaying: string;
}
export interface MsgProps {
lan: string;
pkg: Map<string, string>;
@ -30,15 +26,18 @@ export interface UIProps {
position: string;
align: string;
};
control: {
controls: Map<string, string>;
options: Map<string, Set<string>>;
};
}
export interface ICoreState {
panels: PanelsProps;
filesInfo: FilesProps;
uploadingsInfo: UploadingsProps;
sharingsInfo: SharingsProps;
panes: PanesProps;
login: LoginProps;
admin: AdminProps;
login: LoginProps;
panes: PanesProps;
ui: UIProps;
msg: MsgProps;
}
@ -49,9 +48,6 @@ export function newState(): ICoreState {
export function initState(): ICoreState {
return {
panels: {
displaying: "item",
},
filesInfo: {
dirPath: List<string>([]),
items: List<MetadataResp>([]),
@ -112,6 +108,10 @@ export function initState(): ICoreState {
position: "",
align: "",
},
control: {
controls: Map<string, string>(),
options: Map<string, Set<string>>(),
},
},
};
}

View file

@ -554,20 +554,34 @@ export class Updater {
};
setTab = (tabName: string) => {
switch (tabName) {
case "item":
this.props.panels.displaying = tabName;
break;
case "uploading":
this.props.panels.displaying = tabName;
break;
case "sharing":
this.props.panels.displaying = tabName;
break;
default:
this.props.panels.displaying = "item";
break;
// switch (tabName) {
// case "item":
// this.props.panels.displaying = tabName;
// break;
// case "uploading":
// this.props.panels.displaying = tabName;
// break;
// case "sharing":
// this.props.panels.displaying = tabName;
// break;
// default:
// this.props.panels.displaying = "item";
// break;
// }
};
setControlOption = (controlName: string, option: string): boolean => {
const controlExists = this.props.ui.control.controls.has(controlName);
const options = this.props.ui.control.options.get(controlName);
if (!controlExists || !options.has(option)) {
return false;
}
this.props.ui.control.controls = this.props.ui.control.controls.set(
controlName,
option
);
return true;
};
generateHash = async (filePath: string): Promise<boolean> => {

View file

@ -0,0 +1,37 @@
import { Set, Map } from "immutable";
export const colors = Set<string>([
"blue0",
"blue1",
"cyan0",
"cyan1",
"purple0",
"purple1",
"red0",
"red1",
"yellow0",
"yellow1",
"yellow2",
"yellow3",
"green0",
"green1",
"green2",
"white",
"white0",
"white1",
"grey0",
"grey1",
"grey2",
"grey3",
"black",
"black0",
"black1",
]);
export function colorClass(name: string): string {
if (!colors.has(name)) {
console.error(`color ${name} not found`);
return colors.get("black");
}
return colors.get(name);
}

View file

@ -0,0 +1,50 @@
import * as React from "react";
import { Map } from "immutable";
import { IconType, IconBaseProps } from "@react-icons/all-files";
import { RiFolder2Fill } from "@react-icons/all-files/ri/RiFolder2Fill";
import { RiShareBoxLine } from "@react-icons/all-files/ri/RiShareBoxLine";
import { RiUploadCloudFill } from "@react-icons/all-files/ri/RiUploadCloudFill";
import { colorClass } from "./colors";
export interface IconProps {
name: string;
size: string;
color: string;
}
const icons = Map<string, IconType>({
RiFolder2Fill: RiFolder2Fill,
RiShareBoxLine: RiShareBoxLine,
RiUploadCloudFill: RiUploadCloudFill,
});
export function getIconWithProps(
name: string,
props: IconBaseProps
): JSX.Element | null {
const icon = icons.get(name);
if (icon == null) {
throw Error(`icon "${name}" is not found`);
}
return React.createElement(icon, { ...props }, null);
}
export function getIcon(
name: string,
size: string,
color: string
): JSX.Element | null {
const icon = icons.get(name);
if (icon == null) {
throw Error(`icon "${name}" is not found`);
}
return React.createElement(
icon,
{ size, className: `${colorClass(color)}-font` },
null
);
}