Add behavior list component

This commit is contained in:
2022-03-27 20:49:44 +08:00
parent 87023251a9
commit a36a10dade
10 changed files with 339 additions and 15 deletions
@@ -0,0 +1,128 @@
@import "../Theme/Theme.scss";
$behavior-item-height: 45px;
div.behavior-list {
margin: -5px;
display: flex;
flex-wrap: wrap;
div.behavior-item {
margin: 5px;
height: $behavior-item-height;
border-radius: 3px;
cursor: pointer;
display: flex;
div.behavior-color-view {
height: $behavior-item-height;
width: 3px;
min-width: 3px;
border-radius: 3px;
flex-shrink: 0;
}
div.behavior-icon-view {
height: $behavior-item-height;
min-width: $behavior-item-height;
width: $behavior-item-height;
user-select: none;
display: flex;
justify-content: center;
align-items: center;
i {
font-size: 25px;
}
}
div.behavior-content-view {
width: calc( 100% - 68px );
max-width: 100px;
height: $behavior-item-height;
display: flex;
justify-content: center;
flex-direction: column;
align-items: stretch;
div.title-view {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
width: 100%;
}
div.info-view {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
width: 100%;
opacity: .75;
}
}
div.behavior-action-view {
height: $behavior-item-height;
min-width: 20px;
width: 20px;
flex-shrink: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-content: center;
align-items: center;
div.behavior-action-button {
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
user-select: none;
cursor: pointer;
}
div.behavior-action-button.hover-red:hover i {
color: $lt-red;
}
div.behavior-action-button.hover-blue:hover i {
color: $lt-blue;
}
}
}
}
div.dark.behavior-list {
div.behavior-item {
background-color: $lt-bg-color-lvl3-dark;
}
div.behavior-item:hover {
color: $lt-font-color-lvl2-dark;
background-color: $lt-bg-color-lvl2-dark;
}
div.behavior-item.focus {
color: $lt-font-color-lvl1-dark;
background-color: $lt-bg-color-lvl1-dark;
}
}
div.light.behavior-list {
div.behavior-item {
background-color: $lt-bg-color-lvl3-light;
}
div.behavior-item:hover {
color: $lt-font-color-lvl2-light;
background-color: $lt-bg-color-lvl2-light;
}
div.behavior-item.focus {
color: $lt-font-color-lvl1-light;
background-color: $lt-bg-color-lvl1-light;
}
}
@@ -0,0 +1,138 @@
import { Theme } from "@Component/Theme/Theme";
import { Component, ReactNode } from "react";
import { IRenderBehavior, Behavior, BehaviorRecorder } from "@Model/Behavior";
import { Icon } from "@fluentui/react";
import { Localization } from "@Component/Localization/Localization";
import "./BehaviorList.scss";
interface IBehaviorListProps {
behaviors: IRenderBehavior[];
focusBehaviors?: IRenderBehavior[];
click?: (behavior: IRenderBehavior) => void;
action?: (behavior: IRenderBehavior) => void;
actionType?: "info" | "delete";
}
class BehaviorList extends Component<IBehaviorListProps> {
private isFocus(behavior: IRenderBehavior): boolean {
if (this.props.focusBehaviors) {
for (let i = 0; i < this.props.focusBehaviors.length; i++) {
if (this.props.focusBehaviors[i] === behavior) {
return true;
}
}
}
return false;
}
private renderActionButton(behavior: IRenderBehavior) {
const classList: string[] = ["info-button", "behavior-action-button"];
let iconName = "Info";
switch (this.props.actionType) {
case "delete":
classList.push("hover-red");
iconName = "Delete";
break;
case "info":
classList.push("hover-blue");
iconName = "Info";
break;
default:
classList.push("hover-blue");
}
return <div
className={classList.join(" ")}
onClick={() => {
this.isActionClick = true;
if (this.props.action) {
this.props.action(behavior)
}
}}
>
<Icon iconName={iconName}/>
</div>
}
private renderTerm(key: string, className: string, needLocal: boolean) {
if (needLocal) {
return <div className={className}>
<Localization i18nKey={key as any}/>
</div>;
} else {
return <div className={className}>
{key}
</div>;
}
}
private isActionClick: boolean = false;
private renderBehavior(behavior: IRenderBehavior) {
let id: string = behavior.behaviorId;
let name: string = behavior.behaviorName;
let icon: string = behavior.iconName;
let info: string = behavior.describe;
let color: string = "";
let needLocal: boolean = true;
let focus = this.isFocus(behavior);
if (behavior instanceof Behavior) {
id = behavior.id;
name = behavior.name;
color = behavior.color;
needLocal = false;
}
if (behavior instanceof BehaviorRecorder) {
needLocal = true;
if (focus) {
color = "rgb(81, 79, 235)";
}
}
if (!color) {
color = "transparent";
}
return <div
key={id}
className={"behavior-item" + (focus ? " focus" : "")}
onClick={() => {
if (this.props.click && !this.isActionClick) {
this.props.click(behavior);
}
this.isActionClick = false;
}}
>
<div
className="behavior-color-view"
style={{ backgroundColor: color }}
/>
<div className="behavior-icon-view">
<Icon iconName={icon}/>
</div>
<div className="behavior-content-view">
{this.renderTerm(name, "title-view", needLocal)}
{this.renderTerm(info, "info-view", needLocal)}
</div>
<div className="behavior-action-view">
{this.renderActionButton(behavior)}
</div>
</div>
}
public render(): ReactNode {
return <Theme className="behavior-list">
{this.props.behaviors.map((behavior) => {
return this.renderBehavior(behavior);
})}
</Theme>
}
}
export { BehaviorList };