aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2025-03-07 13:46:59 -0500
committerbobzel <zzzman@gmail.com>2025-03-07 13:46:59 -0500
commit82ba2c85e22fb809f1a5fba827c73555db0e4cd9 (patch)
tree602f887026e7fdf3ef68f80fef55ee45baef9daf
parent72b264479ea5c039dbba806b6bbd941729b9073a (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.
-rw-r--r--packages/components/src/components/ColorPicker/ColorPicker.tsx336
-rw-r--r--packages/components/src/components/IconButton/IconButton.tsx280
-rw-r--r--packages/components/src/components/Popup/Popup.tsx61
-rw-r--r--src/client/documents/DocUtils.ts4
-rw-r--r--src/client/documents/Documents.ts3
-rw-r--r--src/client/util/CurrentUserUtils.ts8
-rw-r--r--src/client/views/collections/collectionSchema/SchemaTableCell.tsx2
-rw-r--r--src/client/views/nodes/FontIconBox/FontIconBox.scss20
-rw-r--r--src/client/views/nodes/FontIconBox/FontIconBox.tsx5
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.tsx4
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx3
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();