diff options
author | bobzel <zzzman@gmail.com> | 2025-03-07 13:46:59 -0500 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2025-03-07 13:46:59 -0500 |
commit | 82ba2c85e22fb809f1a5fba827c73555db0e4cd9 (patch) | |
tree | 602f887026e7fdf3ef68f80fef55ee45baef9daf | |
parent | 72b264479ea5c039dbba806b6bbd941729b9073a (diff) |
fixed columnWidth settings for sidebar. fixed color picker and other dropdowns to toggle when button is clicked. fixed dash field views to collapse properly. fixed rtf to honor marks that were set before text box is created and typing starts.
11 files changed, 340 insertions, 386 deletions
diff --git a/packages/components/src/components/ColorPicker/ColorPicker.tsx b/packages/components/src/components/ColorPicker/ColorPicker.tsx index 51b820a37..632b470f0 100644 --- a/packages/components/src/components/ColorPicker/ColorPicker.tsx +++ b/packages/components/src/components/ColorPicker/ColorPicker.tsx @@ -1,204 +1,156 @@ -import React, { useState } from 'react' -import { GithubPicker, ChromePicker, BlockPicker, SliderPicker, SketchPicker } from 'react-color' -import { IGlobalProps, Size, Type , getFormLabelSize } from '../../global' -import { Button } from '../Button' -import { IconButton } from '../IconButton' -import { Popup, PopupTrigger } from '../Popup' -import './ColorPicker.scss' -import { Dropdown, DropdownType } from '../Dropdown' +import React, { useRef, useState } from 'react'; +import { GithubPicker, ChromePicker, BlockPicker, SliderPicker, SketchPicker } from 'react-color'; +import { IGlobalProps, Size, Type, getFormLabelSize } from '../../global'; +import { Button } from '../Button'; +import { IconButton } from '../IconButton'; +import { Popup, PopupTrigger } from '../Popup'; +import './ColorPicker.scss'; +import { Dropdown, DropdownType } from '../Dropdown'; -export const ColorPickerArray= ["Classic", "Chrome", "GitHub", "Block", "Slider"] -export type ColorPickerType= typeof ColorPickerArray[number]; +export const ColorPickerArray = ['Classic', 'Chrome', 'GitHub', 'Block', 'Slider']; +export type ColorPickerType = (typeof ColorPickerArray)[number]; export interface IColorPickerProps extends IGlobalProps { - text?: string - icon?: JSX.Element | string - colorPickerType?: ColorPickerType - defaultPickerType?: ColorPickerType - selectedColor?: string - setSelectedColor: (color: any) => unknown - setFinalColor: (color:any) => unknown + text?: string; + icon?: JSX.Element | string; + colorPickerType?: ColorPickerType; + defaultPickerType?: ColorPickerType; + selectedColor?: string; + setSelectedColor: (color: any) => unknown; + setFinalColor: (color: any) => unknown; } export const ColorPicker = (props: IColorPickerProps) => { - const [selectedColorLoc, setSelectedColorLoc] = useState(); - const { defaultPickerType, text, colorPickerType, fillWidth, formLabelPlacement, size = Size.SMALL, type = Type.TERT, icon, selectedColor = selectedColorLoc, setSelectedColor = setSelectedColorLoc, setFinalColor = setSelectedColorLoc, tooltip, color='black', formLabel } = props - const [isOpen, setOpen] = useState<boolean>(false) - const [pickerSelectorOpen, setPickerSelectorOpen] = useState<boolean>(false); - const decimalToHexString = (number: number) => { - if (number < 0) { - number = 0xffffffff + number + 1; - } - return (number < 16 ? '0' : '') + number.toString(16).toUpperCase(); -} - const colorString = (color: any ) => { - return color.hex === 'transparent' ? color.hex: color.hex + (color.rgb.a ? decimalToHexString(Math.round(color.rgb.a * 255)) : 'ff'); - } - const onChange = (color: any) => { - setSelectedColor(colorString(color) as any); - } - const onChangeComplete = (color: any) => { - setFinalColor(colorString(color) as any); - } - const [picker, setPicker] = useState<string>(defaultPickerType ?? "Classic") + const [selectedColorLoc, setSelectedColorLoc] = useState(); + const { + defaultPickerType, + text, + colorPickerType, + fillWidth, + formLabelPlacement, + size = Size.SMALL, + type = Type.TERT, + icon, + selectedColor = selectedColorLoc, + setSelectedColor = setSelectedColorLoc, + setFinalColor = setSelectedColorLoc, + tooltip, + color = 'black', + formLabel, + } = props; + const [isOpen, setOpen] = useState<boolean>(false); + const [pickerSelectorOpen, setPickerSelectorOpen] = useState<boolean>(false); + const decimalToHexString = (number: number) => { + if (number < 0) { + number = 0xffffffff + number + 1; + } + return (number < 16 ? '0' : '') + number.toString(16).toUpperCase(); + }; + const colorString = (color: any) => { + return color.hex === 'transparent' ? color.hex : color.hex + (color.rgb.a ? decimalToHexString(Math.round(color.rgb.a * 255)) : 'ff'); + }; + const onChange = (color: any) => { + setSelectedColor(colorString(color) as any); + }; + const onChangeComplete = (color: any) => { + setFinalColor(colorString(color) as any); + }; + const [picker, setPicker] = useState<string>(defaultPickerType ?? 'Classic'); - const getToggle = () => { - if (icon && !text) { - return ( - <IconButton - active={isOpen} - tooltip={tooltip} - type={type} - color={color} - size={size} - icon={icon} - colorPicker={selectedColor} - fillWidth={fillWidth} - /> - ) - } else if (text) { - return ( - <Button - active={isOpen} - tooltip={tooltip} - size={size} - type={type} - color={color} - text={text} - icon={icon} - align={'flex-start'} - iconPlacement={'left'} - colorPicker={selectedColor} - fillWidth={fillWidth} - /> - ) - } else { - return ( - <IconButton - active={isOpen} - tooltip={tooltip} - type={type} - color={color} - size={size} - icon={icon} - colorPicker={selectedColor} - fillWidth={fillWidth} - /> - ) - } - } + const toggleRef = useRef<HTMLDivElement | null>(null); + const getToggle = () => ( + <div ref={toggleRef}> + {icon && !text ? ( + <IconButton active={isOpen} tooltip={tooltip} type={type} color={color} size={size} icon={icon} colorPicker={selectedColor} fillWidth={fillWidth} /> + ) : text ? ( + <Button active={isOpen} tooltip={tooltip} size={size} type={type} color={color} text={text} icon={icon} align={'flex-start'} iconPlacement={'left'} colorPicker={selectedColor} fillWidth={fillWidth} /> + ) : ( + <IconButton active={isOpen} tooltip={tooltip} type={type} color={color} size={size} icon={icon} colorPicker={selectedColor} fillWidth={fillWidth} /> + )} + </div> + ); - const getColorPicker = (pickerType: ColorPickerType):JSX.Element => { - const colorPalette = ["FFFFFF", "#F9F6F2", "#E2E2E2", "#D1D1D1", "#737576", "#4b4a4d", "#222021", - '#EB9694', '#FAD0C3', '#FEF3BD', '#C1E1C5', '#BEDADC', '#C4DEF6', '#BED3F3', '#D4C4FB', "transparent" - ] - switch(pickerType) { - case "Block": - return ( - <BlockPicker - color={selectedColor} - triangle={'hide'} - colors={colorPalette} - onChange={onChange} - onChangeComplete={onChangeComplete} - /> - ); - case "Classic": - return (<SketchPicker - onChange={onChange} - onChangeComplete={onChangeComplete} - presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent']} - color={selectedColor} - />); - case "Chrome": - default: - return ( - <ChromePicker - color={selectedColor} - onChange={onChange} - onChangeComplete={onChangeComplete} - /> - ); - case "GitHub": - return ( - <GithubPicker - color={selectedColor} - colors={colorPalette} - triangle={'hide'} - onChange={onChange} - onChangeComplete={onChangeComplete} - /> - ); - case "Slider": - return ( - <div style={{width: 200, height: 50}}> - <SliderPicker - color={selectedColor} - onChange={onChange} - onChangeComplete={onChangeComplete} - /> - </div> - ); - } - } - const openChanged = (isOpen:boolean) => setPickerSelectorOpen(isOpen); + const getColorPicker = (pickerType: ColorPickerType): JSX.Element => { + const colorPalette = ['FFFFFF', '#F9F6F2', '#E2E2E2', '#D1D1D1', '#737576', '#4b4a4d', '#222021', '#EB9694', '#FAD0C3', '#FEF3BD', '#C1E1C5', '#BEDADC', '#C4DEF6', '#BED3F3', '#D4C4FB', 'transparent']; + switch (pickerType) { + case 'Classic': return ( + <SketchPicker + onChange={onChange} + onChangeComplete={onChangeComplete} + presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent']} + color={selectedColor} + /> + ); + case 'Chrome': + default: return <ChromePicker color={selectedColor} onChange={onChange} onChangeComplete={onChangeComplete} />; + case 'GitHub': return <GithubPicker color={selectedColor} colors={colorPalette} triangle={'hide'} onChange={onChange} onChangeComplete={onChangeComplete} />; + case 'Block': return <BlockPicker color={selectedColor} triangle={'hide'} colors={colorPalette} onChange={onChange} onChangeComplete={onChangeComplete} />; + case 'Slider': return ( + <div style={{ width: 200, height: 50 }}> + <SliderPicker color={selectedColor} onChange={onChange} onChangeComplete={onChangeComplete} /> + </div> + ); + } // prettier-ignore + }; + const openChanged = (isOpen: boolean) => setPickerSelectorOpen(isOpen); - const getPopup = ():JSX.Element => { - if (colorPickerType){ - return getColorPicker(colorPickerType) - } else { - // Todo: this would be much easier if the selectedColor was a Color, not a string. - const newColor = (selectedColor === 'transparent' ? 'white': selectedColor?.startsWith("#") ? selectedColor.substring(0,7): - selectedColor?.startsWith('rgba') ? selectedColor?.replace(/,[0-9]*\)/,"1)") : selectedColor); - return <div style={{height: 'fit-content'}}> - <Dropdown - items={ - ColorPickerArray.map((item) => { - return { - text: item, - val: item, - } - }) - } - activeChanged={openChanged} - placement={'right'} - color={newColor} - type={Type.PRIM} - dropdownType={DropdownType.SELECT} - selectedVal={picker} - setSelectedVal={(val) => setPicker(val as string)} - fillWidth - /> - {getColorPicker(picker)} - </div> - } - } + const getPopup = (): JSX.Element => { + if (colorPickerType) { + return getColorPicker(colorPickerType); + } else { + // Todo: this would be much easier if the selectedColor was a Color, not a string. + const newColor = selectedColor === 'transparent' ? 'white' : selectedColor?.startsWith('#') ? selectedColor.substring(0, 7) : selectedColor?.startsWith('rgba') ? selectedColor?.replace(/,[0-9]*\)/, '1)') : selectedColor; + return ( + <div style={{ height: 'fit-content' }}> + <Dropdown + items={ColorPickerArray.map(item => { + return { + text: item, + val: item, + }; + })} + activeChanged={openChanged} + placement={'right'} + color={newColor} + type={Type.PRIM} + dropdownType={DropdownType.SELECT} + selectedVal={picker} + setSelectedVal={val => setPicker(val as string)} + fillWidth + /> + {getColorPicker(picker)} + </div> + ); + } + }; - const popupContainsPt = (x:number, y:number) => pickerSelectorOpen; + const popupContainsPt = (x: number, y: number) => { + const rect = toggleRef.current?.getBoundingClientRect(); + return rect && rect.left < x && rect.top < y && rect.right > x && rect.bottom > y; + }; - const colorPicker: JSX.Element = - ( - <Popup - toggle={getToggle()} - trigger={PopupTrigger.CLICK} - isOpen={isOpen} - setOpen={setOpen} - tooltip={tooltip} - size={size} - color={selectedColor} - popup={getPopup()} - popupContainsPt={popupContainsPt} // this should prohbably test to see if the click pt is actually within the picker selector list popup. - /> - ) + const colorPicker: JSX.Element = ( + <Popup + toggle={getToggle()} + trigger={PopupTrigger.CLICK} + isOpen={isOpen} + setOpen={setOpen} + tooltip={tooltip} + size={size} + color={selectedColor} + popup={getPopup()} + popupContainsPt={popupContainsPt} // this should prohbably test to see if the click pt is actually within the picker selector list popup. + /> + ); - return ( - formLabel ? - <div className={`form-wrapper ${formLabelPlacement}`} -style={{ width: fillWidth ? '100%' : undefined}}> - <div className={'formLabel'} style={{fontSize: getFormLabelSize(size)}}>{formLabel}</div> - {colorPicker} - </div> - : - colorPicker - ) -} + return formLabel ? ( + <div className={`form-wrapper ${formLabelPlacement}`} style={{ width: fillWidth ? '100%' : undefined }}> + <div className={'formLabel'} style={{ fontSize: getFormLabelSize(size) }}> + {formLabel} + </div> + {colorPicker} + </div> + ) : ( + colorPicker + ); +}; diff --git a/packages/components/src/components/IconButton/IconButton.tsx b/packages/components/src/components/IconButton/IconButton.tsx index 7d273e23f..954a0ae44 100644 --- a/packages/components/src/components/IconButton/IconButton.tsx +++ b/packages/components/src/components/IconButton/IconButton.tsx @@ -1,157 +1,153 @@ -import { Tooltip } from '@mui/material' -import React from 'react' -import { Colors, Size, Type, getFontSize, getHeight, isDark, getFormLabelSize } from '../../global' -import { IButtonProps } from '../Button' -import './IconButton.scss' +import { Tooltip } from '@mui/material'; +import React from 'react'; +import { Colors, Size, Type, getFontSize, getHeight, isDark, getFormLabelSize } from '../../global'; +import { IButtonProps } from '../Button'; +import './IconButton.scss'; export interface IIconButtonProps extends IButtonProps {} export const IconButton = (props: IButtonProps) => { - const { - active, - icon, - onClick, - onDoubleClick, - onPointerDown, - inactive, - type = Type.PRIM, - color = Colors.MEDIUM_BLUE, - background, - label, - height, - size = Size.SMALL, - style, - tooltip, - tooltipPlacement = 'top', - colorPicker, - formLabel, - formLabelPlacement, - hideLabel, - fillWidth - } = props + const { + active, + icon, + onClick, + onDoubleClick, + onPointerDown, + inactive, + type = Type.PRIM, + color = Colors.MEDIUM_BLUE, + background, + label, + height, + size = Size.SMALL, + style, + tooltip, + tooltipPlacement = 'top', + colorPicker, + formLabel, + formLabelPlacement, + hideLabel, + fillWidth, + } = props; - /** - * Pointer down - * @param e - */ - const handlePointerDown = (e: React.PointerEvent) => { - - if (!inactive && onPointerDown) { - e.stopPropagation(); - e.preventDefault(); - onPointerDown(e) - } - } + /** + * Pointer down + * @param e + */ + const handlePointerDown = (e: React.PointerEvent) => { + if (!inactive && onPointerDown) { + e.stopPropagation(); + e.preventDefault(); + onPointerDown(e); + } + }; - /** - * In the event that there is a single click - * @param e - */ - const handleClick = (e: React.MouseEvent) => { - if (!inactive && onClick) { - e.stopPropagation(); - e.preventDefault(); - onClick(e) - } - } + /** + * In the event that there is a single click + * @param e + */ + const handleClick = (e: React.MouseEvent) => { + if (!inactive && onClick) { + e.stopPropagation(); + e.preventDefault(); + onClick(e); + } + }; - /** - * Double click - * @param e - */ - const handleDoubleClick = (e: React.MouseEvent) => { - if (!inactive && onDoubleClick){ - e.stopPropagation(); - e.preventDefault(); - onDoubleClick(e) - } - } + /** + * Double click + * @param e + */ + const handleDoubleClick = (e: React.MouseEvent) => { + if (!inactive && onDoubleClick) { + e.stopPropagation(); + e.preventDefault(); + onDoubleClick(e); + } + }; - const getBorderColor = (): Colors | string | undefined => { - switch(type){ - case Type.PRIM: - return undefined; - case Type.SEC: - return color; - case Type.TERT: - if (colorPicker) return colorPicker; - if (active) return color; - else return color; - } - } + const getBorderColor = (): Colors | string | undefined => { + switch (type) { + case Type.PRIM: + return undefined; + case Type.SEC: + return color; + case Type.TERT: + if (colorPicker) return colorPicker; + if (active) return color; + else return color; + } + }; - const getColor = (): Colors | string | undefined => { - if (color && background) return color; - switch(type){ - case Type.PRIM: - return color; - case Type.SEC: - return color; - case Type.TERT: - if (colorPicker) { - if (isDark(colorPicker)) return Colors.WHITE; - else return Colors.BLACK + const getColor = (): Colors | string | undefined => { + if (color && background) return color; + switch (type) { + case Type.PRIM: + return color; + case Type.SEC: + return color; + case Type.TERT: + if (colorPicker) { + if (isDark(colorPicker)) return Colors.WHITE; + else return Colors.BLACK; + } + if (isDark(color)) return Colors.WHITE; + else return Colors.BLACK; } - if (isDark(color)) return Colors.WHITE; - else return Colors.BLACK - } - } + }; - const getBackground = (): Colors | string | undefined => { - if(background) return background; - switch(type){ - case Type.PRIM: - return color; - case Type.SEC: - return color; - case Type.TERT: - if (colorPicker) return colorPicker - else return color - } - } + const getBackground = (): Colors | string | undefined => { + if (background) return background; + switch (type) { + case Type.PRIM: + return color; + case Type.SEC: + return color; + case Type.TERT: + if (colorPicker) return colorPicker; + else return color; + } + }; - const defaultProperties: React.CSSProperties = { - height: getHeight(height, size), - width: fillWidth ? '100%' : getHeight(height, size), - minWidth: getHeight(height, size), - fontWeight: 500, - fontSize: getFontSize(size, true), - borderColor: getBorderColor(), - color: getColor() - } + const defaultProperties: React.CSSProperties = { + height: getHeight(height, size), + width: fillWidth ? '100%' : getHeight(height, size), + minWidth: getHeight(height, size), + fontWeight: 500, + fontSize: getFontSize(size, true), + borderColor: getBorderColor(), + color: getColor(), + }; - const backgroundProperties: React.CSSProperties = { - background: getBackground() - } + const backgroundProperties: React.CSSProperties = { + background: getBackground(), + }; - const iconButton: JSX.Element = ( - <Tooltip disableInteractive={true} arrow={true} placement={tooltipPlacement} title={tooltip}> - <div - className={`iconButton-container ${type} ${inactive && 'inactive'}`} - onClick={handleClick} - onDoubleClick={handleDoubleClick} - onPointerDown={handlePointerDown} - style={{...defaultProperties, ...style}} - tabIndex={-1} - > - <div className="iconButton-content"> - {icon} - {colorPicker && type !== (Type.TERT) && <div className={`color`} style={{background: colorPicker, outlineColor: defaultProperties.color}}/>} - {label && !hideLabel && <div className={'iconButton-label'} style={{color: defaultProperties.color}}>{label}</div>} - </div> - <div className={`background ${active && 'active'} ${inactive && 'inactive'}`} style={backgroundProperties}/> - </div> - </Tooltip> - ) + const iconButton: JSX.Element = ( + <Tooltip disableInteractive={true} arrow={true} placement={tooltipPlacement} title={tooltip}> + <div className={`iconButton-container ${type} ${inactive && 'inactive'}`} onClick={handleClick} onDoubleClick={handleDoubleClick} onPointerDown={handlePointerDown} style={{ ...defaultProperties, ...style }} tabIndex={-1}> + <div className="iconButton-content"> + {icon} + {colorPicker && type !== Type.TERT && <div className={`color`} style={{ background: colorPicker, outlineColor: defaultProperties.color }} />} + {label && !hideLabel && ( + <div className={'iconButton-label'} style={{ color: defaultProperties.color }}> + {label} + </div> + )} + </div> + <div className={`background ${active && 'active'} ${inactive && 'inactive'}`} style={backgroundProperties} /> + </div> + </Tooltip> + ); - return ( - formLabel ? - <div className={`form-wrapper ${formLabelPlacement}`} -style={{ width: fillWidth ? '100%' : undefined}}> - <div className={'formLabel'} style={{fontSize: getFormLabelSize(size)}}>{formLabel}</div> - {iconButton} - </div> - : - iconButton - ) -} + return formLabel ? ( + <div className={`form-wrapper ${formLabelPlacement}`} style={{ width: fillWidth ? '100%' : undefined }}> + <div className={'formLabel'} style={{ fontSize: getFormLabelSize(size) }}> + {formLabel} + </div> + {iconButton} + </div> + ) : ( + iconButton + ); +}; diff --git a/packages/components/src/components/Popup/Popup.tsx b/packages/components/src/components/Popup/Popup.tsx index f0920b723..5a58fee29 100644 --- a/packages/components/src/components/Popup/Popup.tsx +++ b/packages/components/src/components/Popup/Popup.tsx @@ -63,12 +63,19 @@ export const Popup = (props: IPopupProps) => { const triggerRef = useRef(null); const popperRef = useRef<HTMLDivElement | null>(null); + const toggleRef = useRef<HTMLDivElement | null>(null); let timeout = setTimeout(() => {}); const handlePointerAwayDown = (e: PointerEvent) => { const rect = popperRef.current?.getBoundingClientRect(); - if (rect && !(rect.left < e.clientX && rect.top < e.clientY && rect.right > e.clientX && rect.bottom > e.clientY) && !popupContainsPt?.(e.clientX, e.clientY)) { + const rect2 = toggleRef.current?.getBoundingClientRect(); + if ( + (!rect2 || !(rect2.left < e.clientX && rect2.top < e.clientY && rect2.right > e.clientX && rect2.bottom > e.clientY)) && + rect && + !(rect.left < e.clientX && rect.top < e.clientY && rect.right > e.clientX && rect.bottom > e.clientY) && + !popupContainsPt?.(e.clientX, e.clientY) + ) { e.preventDefault(); setOpen(false); e.stopPropagation(); @@ -79,9 +86,7 @@ export const Popup = (props: IPopupProps) => { if (isOpen) { window.removeEventListener('pointerdown', handlePointerAwayDown, { capture: true }); window.addEventListener('pointerdown', handlePointerAwayDown, { capture: true }); - return () => { - window.removeEventListener('pointerdown', handlePointerAwayDown, { capture: true }); - }; + return () => window.removeEventListener('pointerdown', handlePointerAwayDown, { capture: true }); } }, [isOpen, popupContainsPt]); @@ -104,31 +109,31 @@ export const Popup = (props: IPopupProps) => { timeout = setTimeout(() => setOpen(false), 1000); } }}> - {toggle ? ( - toggle - ) : ( - <Toggle - tooltip={tooltip} - size={size} - type={type} - color={color} - background={props.isToggle ? undefined : background} - toggleType={ToggleType.BUTTON} - icon={icon} - iconPlacement={iconPlacement} - text={text} - label={props.label} - toggleStatus={isOpen || props.toggleStatus} - onClick={() => { - if (trigger === PopupTrigger.CLICK) { - if (!props.isToggle || props.toggleStatus) { - setOpen(!isOpen); + {toggle ?? ( + <div ref={toggleRef}> + <Toggle + tooltip={tooltip} + size={size} + type={type} + color={color} + background={props.isToggle ? undefined : background} + toggleType={ToggleType.BUTTON} + icon={icon} + iconPlacement={iconPlacement} + text={text} + label={props.label} + toggleStatus={isOpen || props.toggleStatus} + onClick={() => { + if (trigger === PopupTrigger.CLICK) { + if (!props.isToggle || props.toggleStatus) { + setOpen(!isOpen); + } + props.toggleFunc?.(); } - props.toggleFunc?.(); - } - }} - fillWidth={fillWidth} - /> + }} + fillWidth={fillWidth} + /> + </div> )} </div> <Popper open={isOpen} style={{ zIndex: 20000 }} anchorEl={triggerRef.current} placement={placement} modifiers={[]}> diff --git a/src/client/documents/DocUtils.ts b/src/client/documents/DocUtils.ts index 42ccd0810..b216551d5 100644 --- a/src/client/documents/DocUtils.ts +++ b/src/client/documents/DocUtils.ts @@ -372,7 +372,9 @@ export namespace DocUtils { * @param pivotValue */ export function addDocumentCreatorMenuItems(docTextAdder: (d: Doc) => void, docAdder: (d: Doc) => void, x: number, y: number, simpleMenu: boolean = false, pivotField?: string, pivotValue?: string | number | boolean): void { - const documentList: ContextMenuProps[] = DocListCast(DocListCast(Doc.MyTools?.data)[0]?.data) + const foo = DocListCast(DocListCast(Doc.MyTools?.data)[0]?.data).concat(...DocListCast(DocListCast(Doc.MyTools?.data)[1]?.data)); + + const documentList: ContextMenuProps[] = foo .filter(btnDoc => !btnDoc.hidden) .map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)) .filter(doc => doc && doc !== Doc.UserDoc().emptyTrail && doc.title) diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e1aa9aca2..61b370da4 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -274,6 +274,8 @@ export class DocumentOptions { _layout_noSidebar?: BOOLt = new BoolInfo('whether to display the sidebar toggle button'); layout_boxShadow?: string; // box-shadow css string OR "standard" to use dash standard box shadow layout_maxShown?: NUMt = new NumInfo('maximum number of children to display at one time (see multicolumnview)'); + _layout_columnWidth?: NUMt = new NumInfo('width of table column', false); + _layout_columnCount?: NUMt = new NumInfo('number of columns in a masonry view'); _layout_dontCenter?: STRt = new StrInfo("whether collections will center their content - values of 'x', 'xy', or 'y'"); _layout_autoHeight?: BOOLt = new BoolInfo('whether document automatically resizes vertically to display contents'); _layout_autoHeightMargins?: NUMt = new NumInfo('Margin heights to be added to the computed auto height of a Doc'); @@ -297,7 +299,6 @@ export class DocumentOptions { _xPadding?: NUMt = new NumInfo('x padding', false); _yPadding?: NUMt = new NumInfo('y padding', false); _createDocOnCR?: boolean; // whether carriage returns and tabs create new text documents - _columnWidth?: NUMt = new NumInfo('width of table column', false); _columnsHideIfEmpty?: BOOLt = new BoolInfo('whether stacking view column headings should be hidden'); _caption_xMargin?: NUMt = new NumInfo('x margin of caption inside of a carousel collection', false, true); _caption_yMargin?: NUMt = new NumInfo('y margin of caption inside of a carousel collection', false, true); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index ce875ff6c..778b522c4 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -92,7 +92,7 @@ export class CurrentUserUtils { const reqdOpts:DocumentOptions = { title: "User Tools", _xMargin: 0, _layout_showTitle: "title", _chromeHidden: true, hidden: false, _dragOnlyWithinContainer: true, layout_hideContextMenu: true, isSystem: true, _forceActive: true, - _layout_autoHeight: true, _width: 500, _height: 300, _layout_fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true, + _layout_autoHeight: true, _width: 500, _height: 300, _layout_fitWidth: true, _layout_columnWidth: 35, ignoreClick: true, _lockedPosition: true, }; const reqdScripts = { dropConverter : "convertToButtons(dragData)" }; const reqdFuncs = { /* hidden: "IsNoviceMode()" */ }; @@ -181,7 +181,7 @@ export class CurrentUserUtils { const reqdOpts:DocumentOptions = { title: "Stickers", _xMargin: 0, _layout_showTitle: "title", hidden: false, _chromeHidden: true, _dragOnlyWithinContainer: true, layout_hideContextMenu: true, isSystem: true, _forceActive: true, - _layout_autoHeight: true, _width: 500, _height: 300, _layout_fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true, + _layout_autoHeight: true, _width: 500, _height: 300, _layout_fitWidth: true, _layout_columnWidth: 35, ignoreClick: true, _lockedPosition: true, }; const reqdScripts = { dropConverter: "convertToButtons(dragData)" }; const savedAnnos = DocCast(doc[field]); @@ -469,7 +469,7 @@ pie title Minerals in my tap water const reqdOpts:DocumentOptions = { title: "Document Creators", _layout_showTitle: "title", _xMargin: 0, _dragOnlyWithinContainer: true, layout_hideContextMenu: true, _chromeHidden: true, isSystem: true, - _layout_autoHeight: true, _width: 500, _height: 300, _layout_fitWidth: true, _columnWidth: 40, ignoreClick: true, _lockedPosition: true, _forceActive: true, + _layout_autoHeight: true, _width: 500, _height: 300, _layout_fitWidth: true, _layout_columnWidth: 40, ignoreClick: true, _lockedPosition: true, _forceActive: true, childDragAction: dropActionType.embed }; const reqdScripts = { dropConverter: "convertToButtons(dragData)" }; @@ -516,7 +516,7 @@ pie title Minerals in my tap water const reqdStackOpts:DocumentOptions ={ title: "menuItemPanel", childDragAction: dropActionType.same, layout_boxShadow: "rgba(0,0,0,0)", dontRegisterView: true, ignoreClick: true, _layout_dontCenter: 'y', - _chromeHidden: true, _gridGap: 0, _yMargin: 0, _xMargin: 0, _layout_autoHeight: false, _width: 60, _columnWidth: 60, _lockedPosition: true, isSystem: true, + _chromeHidden: true, _gridGap: 0, _yMargin: 0, _xMargin: 0, _layout_autoHeight: false, _width: 60, _layout_columnWidth: 60, _lockedPosition: true, isSystem: true, }; return DocUtils.AssignDocField(doc, field, (opts, items) => Docs.Create.StackingDocument(items??[], opts), reqdStackOpts, menuBtns, { dropConverter: "convertToButtons(dragData)" }); } diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index cd46ae824..c847bc546 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -402,7 +402,7 @@ export class SchemaDateCell extends ObservableReactComponent<SchemaTableCellProp </div> {pointerEvents === 'none' ? null : ( <Popup - icon={<FontAwesomeIcon size="sm" icon="caret-down" />} + icon={<FontAwesomeIcon size="xs" icon="caret-down" />} size={Size.XSMALL} type={Type.TERT} color={SnappingManager.userColor} diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.scss b/src/client/views/nodes/FontIconBox/FontIconBox.scss index 186d24e92..8bc68c131 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.scss +++ b/src/client/views/nodes/FontIconBox/FontIconBox.scss @@ -1,21 +1,21 @@ @use '../../global/globalCssVariables.module.scss' as global; -// bcz: something's messed up with the IconButton css. this mostly fixes the fit-all button, the color buttons, the undo +/- expander and the dropdown doc type list (eg 'text') -.iconButton-container { - width: unset !important; - min-width: 30px !important; - height: unset !important; - min-height: 30px; - .color { - height: 3px !important; - } -} .fonticonbox { margin: auto; width: 100%; .formLabel { height: 5px; } + // bcz: something's messed up with the IconButton css. this mostly fixes the fit-all button, the color buttons, the undo +/- expander and the dropdown doc type list (eg 'text') + .iconButton-container { + width: unset !important; + min-width: 30px !important; + height: unset !important; + min-height: 30px; + .color { + height: 3px !important; + } + } } .menuButton { height: 100%; diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index 7e0236b74..f699568f1 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -257,10 +257,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() { const tooltip: string = StrCast(this.Document.toolTip); return ( - <div - onPointerDown={e => { - e.stopPropagation(); - }}> + <div onPointerDown={e => e.stopPropagation()}> <ColorPicker setSelectedColor={value => { if (!this.colorBatch) this.colorBatch = UndoManager.StartBatch(`Set ${tooltip} color`); diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index 0684daeb6..18cf36603 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -155,8 +155,8 @@ export class DashFieldViewInternal extends ObservableReactComponent<IDashFieldVi @computed get fieldValueContent() { return !this._dashDoc ? null : ( <div - onClick={action(() => { - this._expanded = !this._props.editable ? !this._expanded : true; + onPointerDown={action(() => { + this._expanded = !this._props.editable ? false : !this._expanded; })} style={{ fontSize: 'smaller', width: !this._hideKey && this._expanded ? this.columnWidth() : undefined }}> <SchemaTableCell diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 83ee619d0..a0eb6067e 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1557,8 +1557,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB const tr1 = this.EditorView.state.tr.setStoredMarks(storedMarks); tr = selLoadChar === 'Enter' ? tr1.insert(this.EditorView.state.doc.content.size - 1, schema.nodes.paragraph.create()) : tr1.insertText(selLoadChar, this.EditorView.state.doc.content.size - 1); } - this.EditorView.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(tr.doc.content.size))).setStoredMarks(storedMarks)); + this.EditorView.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(tr.doc.content.size - 1))).setStoredMarks(storedMarks)); this.tryUpdateDoc(true); // calling select() above will make isContentActive() true only after a render .. which means the selectAll() above won't write to the Document and the incomingValue will overwrite the selection with the non-updated data + console.log(this.EditorView.state); } if (selectOnLoad) { this.EditorView!.focus(); |