/* eslint-disable react/jsx-props-no-spreading */ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Button, ColorPicker, Dropdown, DropdownType, IconButton, IListItemProps, MultiToggle, NumberDropdown, NumberDropdownType, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components'; import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { ClientUtils, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../ClientUtils'; import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc'; import { BoolCast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { emptyFunction } from '../../../../Utils'; import { Docs } from '../../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; import { SnappingManager } from '../../../util/SnappingManager'; import { undoable, UndoManager } from '../../../util/UndoManager'; import { ContextMenu } from '../../ContextMenu'; import { ViewBoxBaseComponent } from '../../DocComponent'; import { EditableView } from '../../EditableView'; import { SelectedDocView } from '../../selectedDoc'; import { StyleProp } from '../../StyleProp'; import { FieldView, FieldViewProps } from '../FieldView'; import { OpenWhere } from '../OpenWhere'; import './FontIconBox.scss'; import TrailsIcon from './TrailsIcon'; export enum ButtonType { TextButton = 'textBtn', MenuButton = 'menuBtn', DropdownList = 'dropdownList', ClickButton = 'clickBtn', ToggleButton = 'toggleBtn', ColorButton = 'colorBtn', ToolButton = 'toolBtn', MultiToggleButton = 'multiToggleBtn', NumberSliderButton = 'numSliderBtn', NumberDropdownButton = 'numDropdownBtn', NumberInlineButton = 'numInlineBtn', EditText = 'editableText', } export interface ButtonProps extends FieldViewProps { type?: ButtonType; } @observer export class FontIconBox extends ViewBoxBaseComponent() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FontIconBox, fieldKey); } constructor(props: ButtonProps) { super(props); makeObservable(this); } @observable noTooltip = false; showTemplate = (dragFactory: Doc) => this._props.addDocTab(dragFactory, OpenWhere.addRight); specificContextMenu = (): void => { const dragFactory = DocCast(this.layoutDoc.dragFactory); if (!Doc.noviceMode && dragFactory) { ContextMenu.Instance.addItem({ description: 'Show Template', event: () => this.showTemplate(dragFactory), icon: 'tag' }); } }; /** * this chooses the appropriate title for the label * if the Document is a template, then we use the title of the data doc that it renders * otherwise, we use the Document's title itself. */ @computed get label() { return StrCast(this.Document.isTemplateDoc ? this.dataDoc.title : this.Document.title); } Icon = (color: string, iconFalse?: boolean) => { let icon; if (iconFalse) { icon = StrCast(this.dataDoc[this.fieldKey ?? 'iconFalse'] ?? this.dataDoc.icon, 'user') as IconProp; if (icon) return ; return null; } icon = StrCast(this.dataDoc[this.fieldKey ?? 'icon'] ?? this.dataDoc.icon, 'user') as IconProp; return !icon ? null : icon === ('pres-trail' as IconProp) ? TrailsIcon(color) : ; }; @computed get dropdown() { return BoolCast(this.Document.dropDownOpen); } @computed get buttonList() { return StrListCast(this.Document.btnList); } @computed get type() { return StrCast(this.Document.btnType); } /** * Types of buttons in dash: * - Main menu button (LHS) * - Tool button * - Expandable button (CollectionLinearView) * - Button inside of CollectionLinearView vs. outside of CollectionLinearView * - Action button * - Dropdown button * - Color button * - Dropdown list * - Number button * */ _batch: UndoManager.Batch | undefined = undefined; /** * Number button */ @computed get numberDropdown() { let type: NumberDropdownType; switch (this.type) { case ButtonType.NumberDropdownButton: type = 'dropdown'; break; case ButtonType.NumberInlineButton: type = 'input'; break; case ButtonType.NumberSliderButton: default: type = 'slider'; break; } // prettier-ignore const numScript = (value?: number) => ScriptCast(this.Document.script).script.run({ this: this.Document, value, _readOnly_: value === undefined }); const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color) as string; // Script for checking the outcome of the toggle const checkResult = Number(Number(numScript().result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3))); return ( numScript(value), `${this.Document.title} button set from list`)} fillWidth /> ); } dropdownItemDown = (e: React.PointerEvent, value: string | number) => { setupMoveUpEvents( this, e, () => ScriptCast(this.Document.onDragScript)?.script.run({ this: this.Document, value: { doc: value, e } }).result as boolean, emptyFunction, emptyFunction ); // prettier-ignore return false; }; /** * Dropdown list */ @computed get dropdownListButton() { const script = ScriptCast(this.Document.script); let noviceList: string[] = []; let text: string | undefined; let getStyle: (val: string) => { [key: string]: string } = () => ({}); let icon: IconProp = 'caret-down'; const isViewDropdown = script?.script.originalScript.startsWith('{ return setView'); if (isViewDropdown) { const selected = Array.from(script?.script.run({ _readOnly_: true }).result as Doc[]); // const selected = DocumentView.SelectedDocs(); if (selected.lastElement()) { if (StrCast(selected.lastElement().type) === DocumentType.COL) { text = StrCast(selected.lastElement()._type_collection); } else { if (selected.length > 1) { text = selected.length + ' selected'; } else { text = ClientUtils.cleanDocumentType(StrCast(selected.lastElement().type) as DocumentType, '' as CollectionViewType); icon = Doc.toIcon(selected.lastElement()); } return ( } text={text} type={Type.TERT} color={SnappingManager.userColor} background={SnappingManager.userVariantColor} popup={} fillWidth /> ); } } else { return