import { Button, ColorPicker, Dropdown, DropdownType, IconButton, IListItemProps, MultiToggle, NumberDropdown, NumberDropdownType, Popup, Size, Toggle, ToggleType, Type } from '@dash/components'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; 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 { InkTool } from '../../../../fields/InkField'; import { ScriptField } from '../../../../fields/ScriptField'; 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; }; /** * Displays custom dropdown menu for fonts -- this is a HACK -- fix for generality, don't copy */ handleFontDropdown = (script: () => string, buttonList: string[]) => { // text = StrCast((RichTextMenu.Instance?.TextView?.EditorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily); return { buttonList, jsx: undefined, selectedVal: script(), toolTip: 'Set text font', getStyle: (val: string) => ({ fontFamily: val }), }; }; /** * Displays custom dropdown menu for view selection -- this is a HACK -- fix for generality, don't copy */ handleViewDropdown = (script: ScriptField, buttonList: string[]) => { const selected = Array.from(script?.script.run({ _readOnly_: true }).result as Doc[]); const noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Card, CollectionViewType.Carousel3D, CollectionViewType.Carousel, CollectionViewType.Stacking, CollectionViewType.NoteTaking]; return selected.length === 1 && selected[0].type === DocumentType.COL ? { buttonList: buttonList.filter(value => !Doc.noviceMode || !noviceList.length || noviceList.includes(value as CollectionViewType)), getStyle: undefined, selectedVal: StrCast(selected[0]._type_collection), toolTip: 'change view type (press Shift to add as a new view)', } : { jsx: selected.length ? ( 1 ? 'caret-down' : (Doc.toIcon(selected.lastElement()) as IconProp)} />} text={selected.length === 1 ? ClientUtils.cleanDocumentType(StrCast(selected[0].type) as DocumentType) : selected.length + ' selected'} type={Type.TERT} color={SnappingManager.userColor} background={SnappingManager.userVariantColor} popup={} fillWidth /> ) : (