aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2025-04-05 14:29:03 -0400
committerbobzel <zzzman@gmail.com>2025-04-05 14:29:03 -0400
commita3d6fae1482c61ca725d0a103f13b621aa32b3e3 (patch)
tree10a7bff8274f36466a41c3303e9c6f682c823590
parent031a607100700f818f96b7fbf478f1b75292be9b (diff)
fixed multitoggle behavior to only toggle submenu closed. switched to hard-light for masking ink. fixed to make menu toggle take effect immediately.
-rw-r--r--packages/components/src/components/Group/Group.tsx68
-rw-r--r--packages/components/src/components/MultiToggle/MultiToggle.stories.tsx125
-rw-r--r--packages/components/src/components/MultiToggle/MultiToggle.tsx36
-rw-r--r--packages/components/src/components/Popup/Popup.tsx22
-rw-r--r--src/client/documents/Documents.ts37
-rw-r--r--src/client/views/collections/CollectionSubView.tsx7
-rw-r--r--src/client/views/collections/FlashcardPracticeUI.tsx5
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx5
-rw-r--r--src/client/views/nodes/FontIconBox/FontIconBox.tsx1
10 files changed, 139 insertions, 169 deletions
diff --git a/packages/components/src/components/Group/Group.tsx b/packages/components/src/components/Group/Group.tsx
index 7abe4a1c7..6275a09dd 100644
--- a/packages/components/src/components/Group/Group.tsx
+++ b/packages/components/src/components/Group/Group.tsx
@@ -1,49 +1,33 @@
-import React from 'react'
-import './Group.scss'
-import { Colors, IGlobalProps, getFontSize, isDark , getFormLabelSize } from '../../global';
+import React from 'react';
+import './Group.scss';
+import { Colors, IGlobalProps, getFontSize, isDark, getFormLabelSize } from '../../global';
export interface IGroupProps extends IGlobalProps {
- children: any
- rowGap?: number;
- columnGap?: number;
- padding?: number | string;
+ children: any;
+ rowGap?: number;
+ columnGap?: number;
+ padding?: number | string;
}
export const Group = (props: IGroupProps) => {
- const {
- children,
- width = '100%',
- rowGap = 5,
- columnGap = 5,
- padding = 0,
- formLabel,
- formLabelPlacement,
- size,
- style,
- color,
- fillWidth
- } = props
+ const { children, width = '100%', rowGap = 5, columnGap = 5, padding = 0, formLabel, formLabelPlacement, size, style, fillWidth } = props;
- const group: JSX.Element =
- (
- <div
- className="group-wrapper"
- style={{ width, padding: padding, ...style }}
- >
- <div className={`group-container`}
- style={{ rowGap, columnGap }}
- >{children}</div>
- </div>
- )
+ const group: JSX.Element = (
+ <div className="group-wrapper" style={{ width, padding: padding, ...style }}>
+ <div className={`group-container`} style={{ rowGap, columnGap }}>
+ {children}
+ </div>
+ </div>
+ );
- return (
- formLabel ?
- <div className={`form-wrapper ${formLabelPlacement}`}
- style={{ width: fillWidth ? '100%' : undefined}}>
- <div className={'formLabel'} style={{fontSize: getFormLabelSize(size)}}>{formLabel}</div>
- {group}
- </div>
- :
- group
- )
-}
+ return formLabel ? (
+ <div className={`form-wrapper ${formLabelPlacement}`} style={{ width: fillWidth ? '100%' : undefined }}>
+ <div className={'formLabel'} style={{ fontSize: getFormLabelSize(size) }}>
+ {formLabel}
+ </div>
+ {group}
+ </div>
+ ) : (
+ group
+ );
+};
diff --git a/packages/components/src/components/MultiToggle/MultiToggle.stories.tsx b/packages/components/src/components/MultiToggle/MultiToggle.stories.tsx
index e71423d7a..b9ba45f72 100644
--- a/packages/components/src/components/MultiToggle/MultiToggle.stories.tsx
+++ b/packages/components/src/components/MultiToggle/MultiToggle.stories.tsx
@@ -1,69 +1,68 @@
-import { Meta, Story } from '@storybook/react'
-import React from 'react'
-import { IMultiToggleProps, MultiToggle } from './MultiToggle'
-import { FaAlignLeft, FaAlignCenter, FaAlignJustify, FaAlignRight } from 'react-icons/fa'
+import { Meta, Story } from '@storybook/react';
+import React from 'react';
+import { IMultiToggleProps, MultiToggle } from './MultiToggle';
+import { FaAlignLeft, FaAlignCenter, FaAlignJustify, FaAlignRight } from 'react-icons/fa';
export default {
- title: 'Dash/MultiToggle',
- component: MultiToggle,
- argTypes: {},
-} as Meta<typeof MultiToggle>
+ title: 'Dash/MultiToggle',
+ component: MultiToggle,
+ argTypes: {},
+} as Meta<typeof MultiToggle>;
-const MultiToggleStory: Story<IMultiToggleProps> = (args) => <MultiToggle {...args} />
-export const MultiToggleOne = MultiToggleStory.bind({})
+const MultiToggleStory: Story<IMultiToggleProps> = args => <MultiToggle {...args} />;
+export const MultiToggleOne = MultiToggleStory.bind({});
MultiToggleOne.args = {
- tooltip: "Text alignment",
- label: "Alignment",
- defaultSelectedItems: "center",
- toggleStatus: true,
- isToggle: false,
- items: [
- {
- icon: <FaAlignLeft/>,
- tooltip: 'Align left',
- val: "left"
- },
- {
- icon: <FaAlignCenter/>,
- tooltip: 'Align center',
- val: "center"
- },
- {
- icon: <FaAlignRight/>,
- tooltip: 'Align right',
- val: "right"
- },
- {
- icon: <FaAlignJustify/>,
- tooltip: 'Justify',
- val: "justify"
- },
- ]
-}
+ tooltip: 'Text alignment',
+ label: 'Alignment',
+ defaultSelectedItems: 'center',
+ toggleStatus: true,
+ items: [
+ {
+ icon: <FaAlignLeft />,
+ tooltip: 'Align left',
+ val: 'left',
+ },
+ {
+ icon: <FaAlignCenter />,
+ tooltip: 'Align center',
+ val: 'center',
+ },
+ {
+ icon: <FaAlignRight />,
+ tooltip: 'Align right',
+ val: 'right',
+ },
+ {
+ icon: <FaAlignJustify />,
+ tooltip: 'Justify',
+ val: 'justify',
+ },
+ ],
+};
-export const MultiToggleTwo = MultiToggleStory.bind({})
+export const MultiToggleTwo = MultiToggleStory.bind({});
MultiToggleTwo.args = {
- tooltip: "Text Tags",
- label: "Tags",
- defaultSelectedItems : ["left"],
- background: "green",
- color: 'white',
- multiSelect: true,
- items: [
- {
- icon: <FaAlignLeft/>,
- tooltip: 'Like',
- val: "left"
- },
- {
- icon: <FaAlignCenter/>,
- tooltip: 'Todo',
- val: "center"
- },
- {
- icon: <FaAlignRight/>,
- tooltip: 'Idea',
- val: "right"
- },
- ]
-}
+ tooltip: 'Text Tags',
+ label: 'Tags',
+ defaultSelectedItems: ['left'],
+ background: 'green',
+ color: 'white',
+ multiSelect: true,
+ items: [
+ {
+ icon: <FaAlignLeft />,
+ tooltip: 'Like',
+ val: 'left',
+ },
+ {
+ icon: <FaAlignCenter />,
+ tooltip: 'Todo',
+ val: 'center',
+ },
+ {
+ icon: <FaAlignRight />,
+ tooltip: 'Idea',
+ val: 'right',
+ },
+ ],
+};
diff --git a/packages/components/src/components/MultiToggle/MultiToggle.tsx b/packages/components/src/components/MultiToggle/MultiToggle.tsx
index 0f659c5ca..0a6fb81c9 100644
--- a/packages/components/src/components/MultiToggle/MultiToggle.tsx
+++ b/packages/components/src/components/MultiToggle/MultiToggle.tsx
@@ -16,7 +16,6 @@ export interface IMultiToggleProps extends IGlobalProps {
defaultSelectedItems?: (string | number) | (string | number)[];
selectedItems?: (string | number) | (string | number)[];
onSelectionChange?: (val: (string | number) | (string | number)[], added: boolean) => unknown;
- isToggle?: boolean;
toggleStatus?: boolean;
}
@@ -37,33 +36,30 @@ export const MultiToggle = (props: IMultiToggleProps) => {
const itemsMap = new Map();
items.forEach(item => itemsMap.set(item.val, item));
return (
- <div className={`multiToggle-container`}>
+ <div className="multiToggle-container">
<Popup
toggle={
- props.isToggle ? undefined : (
- <div style={{ position: 'relative' }}>
- <IconButton
- color={color}
- borderColor={background ? color : undefined}
- label={props.label}
- active={props.toggleStatus}
- background={color}
- {...(itemsMap.get(promoteToArray(selectedItems)[0]) ?? {})}
- tooltip={tooltip}
- tooltipPlacement={tooltipPlacement}
- />
- {promoteToArray(selectedItems).length < 2 ? null : <div style={{ position: 'absolute', top: '0', left: '0', color: color ?? Colors.MEDIUM_BLUE }}>+</div>}
- </div>
- )
+ <div style={{ position: 'relative' }}>
+ <IconButton
+ color={color}
+ borderColor={background ? color : undefined}
+ label={props.label}
+ active={props.toggleStatus}
+ background={color}
+ {...(itemsMap.get(promoteToArray(selectedItems)[0]) ?? {})}
+ tooltip={tooltip}
+ tooltipPlacement={tooltipPlacement}
+ />
+ {promoteToArray(selectedItems).length < 2 ? null : <div style={{ position: 'absolute', top: '0', left: '0', color: color ?? Colors.MEDIUM_BLUE }}>+</div>}
+ </div>
}
- isToggle={props.isToggle}
+ isToggle={true}
toggleFunc={() => {
const selItem = items.find(item => promoteToArray(selectedItems).includes(item.val));
selItem && setSelectedItemsLocal([selItem.val]);
}}
type={props.type}
- label={props.isToggle ? props.label : undefined}
- toggleStatus={props.isToggle ? props.toggleStatus : undefined}
+ label={undefined}
color={color}
background={background}
popup={
diff --git a/packages/components/src/components/Popup/Popup.tsx b/packages/components/src/components/Popup/Popup.tsx
index 82e60f343..9e72ece87 100644
--- a/packages/components/src/components/Popup/Popup.tsx
+++ b/packages/components/src/components/Popup/Popup.tsx
@@ -20,11 +20,10 @@ export interface IPopupProps extends IGlobalProps {
toggle?: JSX.Element;
popup: JSX.Element | string | (() => JSX.Element);
trigger?: PopupTrigger;
- toggleStatus?: boolean;
isOpen?: boolean;
setOpen?: (b: boolean) => void;
background?: string;
- isToggle?: boolean;
+ isToggle?: boolean; // whether popup stays open when background is clicked. muyst click toggle button tp close it.
toggleFunc?: () => void;
popupContainsPt?: (x: number, y: number) => boolean;
}
@@ -71,6 +70,7 @@ export const Popup = (props: IPopupProps) => {
const rect = popperRef.current?.getBoundingClientRect();
const rect2 = toggleRef.current?.getBoundingClientRect();
if (
+ !props.isToggle &&
(!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) &&
@@ -109,8 +109,8 @@ export const Popup = (props: IPopupProps) => {
timeout = setTimeout(() => setOpen(false), 1000);
}
}}>
- {toggle ?? (
- <div ref={toggleRef}>
+ <div ref={toggleRef}>
+ {toggle ?? (
<Toggle
tooltip={tooltip}
size={size}
@@ -122,19 +122,17 @@ export const Popup = (props: IPopupProps) => {
iconPlacement={iconPlacement}
text={text}
label={props.label}
- toggleStatus={isOpen || props.toggleStatus}
+ toggleStatus={isOpen}
onClick={() => {
if (trigger === PopupTrigger.CLICK) {
- if (!props.isToggle || props.toggleStatus) {
- setOpen(!isOpen);
- }
+ setOpen(!isOpen);
props.toggleFunc?.();
}
}}
fillWidth={fillWidth}
/>
- </div>
- )}
+ )}
+ </div>
</div>
<Popper open={isOpen} style={{ zIndex: 20000 }} anchorEl={triggerRef.current} placement={placement} modifiers={[]}>
<div
@@ -142,9 +140,7 @@ export const Popup = (props: IPopupProps) => {
ref={popperRef}
style={{ width, height, background }}
tabIndex={-1}
- onPointerDown={e => {
- e.stopPropagation();
- }}
+ onPointerDown={e => e.stopPropagation()}
onPointerEnter={() => {
if (trigger === PopupTrigger.HOVER || trigger === PopupTrigger.HOVER_DELAY) {
clearTimeout(timeout);
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 8458699fa..f1655e3cf 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -4,7 +4,6 @@ import { basename } from 'path';
import { ClientUtils, OmitKeys } from '../../ClientUtils';
import { DateField } from '../../fields/DateField';
import { CreateLinkToActiveAudio, Doc, FieldType, Opt, updateCachedAcls } from '../../fields/Doc';
-import { Initializing } from '../../fields/DocSymbols';
import { Id } from '../../fields/FieldSymbols';
import { HtmlField } from '../../fields/HtmlField';
import { InkField } from '../../fields/InkField';
@@ -983,26 +982,22 @@ export namespace Docs {
export function InkDocument(points: PointData[], options: DocumentOptions = {}, strokeWidth: number, color: string, strokeBezier: string, fillColor: string, arrowStart: string, arrowEnd: string, dash: string, isInkMask: boolean) {
const ink = InstanceFromProto(Prototypes.get(DocumentType.INK), '', { title: 'ink', ...options });
- const I = Doc.GetProto(ink);
- // I.layout_hideOpenButton = true; // don't show open full screen button when selected
- I.color = color;
- I.fillColor = fillColor && fillColor !== 'transparent' ? fillColor : undefined;
- I.stroke = new InkField(points);
- I.stroke_width = strokeWidth;
- I.stroke_bezier = strokeBezier;
- I.stroke_startMarker = arrowStart;
- I.stroke_endMarker = arrowEnd;
- I.stroke_dash = dash;
- I.stroke_isInkMask = isInkMask;
- I.text_align = 'center';
- I.rotation = 0;
- I.width_min = 1;
- I.height_min = 1;
- I.defaultDoubleClick = 'ignore';
- I.author_date = new DateField();
- I.acl_Guest = Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.View;
- // I.acl_Override = SharingPermissions.Unset;
- I[Initializing] = false;
+ ink.$color = color;
+ ink.$fillColor = fillColor && fillColor !== 'transparent' ? fillColor : undefined;
+ ink.$stroke = new InkField(points);
+ ink.$stroke_width = strokeWidth;
+ ink.$stroke_bezier = strokeBezier;
+ ink.$stroke_startMarker = arrowStart;
+ ink.$stroke_endMarker = arrowEnd;
+ ink.$stroke_dash = dash;
+ ink.$stroke_isInkMask = isInkMask;
+ ink.$text_align = 'center';
+ ink.$rotation = 0;
+ ink.$width_min = 1;
+ ink.$height_min = 1;
+ ink.$defaultDoubleClick = 'ignore';
+ ink.$author_date = new DateField();
+ ink.$acl_Guest = Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.View;
return ink;
}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index cfd52f9ee..a88707c6f 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -13,6 +13,7 @@ import { BoolCast, Cast, DateCast, NumCast, ScriptCast, StrCast, toList } from '
import { WebField } from '../../../fields/URLField';
import { GetEffectiveAcl, TraceMobx } from '../../../fields/util';
import { GestureUtils } from '../../../pen-gestures/GestureUtils';
+import { Upload } from '../../../server/SharedMediaTypes';
import { DocServer } from '../../DocServer';
import { Networking } from '../../Network';
import { DocUtils } from '../../documents/DocUtils';
@@ -24,11 +25,11 @@ import { ImageUtils } from '../../util/Import & Export/ImageUtils';
import { SnappingManager } from '../../util/SnappingManager';
import { UndoManager } from '../../util/UndoManager';
import { ViewBoxBaseComponent } from '../DocComponent';
+import { DocumentViewProps } from '../nodes/DocumentContentsView';
+import { DocumentView } from '../nodes/DocumentView';
import { FieldViewProps } from '../nodes/FieldView';
-import { DocumentView, DocumentViewProps } from '../nodes/DocumentView';
-import { FlashcardPracticeUI } from './FlashcardPracticeUI';
import { OpenWhere, OpenWhereMod } from '../nodes/OpenWhere';
-import { Upload } from '../../../server/SharedMediaTypes';
+import { FlashcardPracticeUI } from './FlashcardPracticeUI';
export enum docSortings {
Time = 'time',
diff --git a/src/client/views/collections/FlashcardPracticeUI.tsx b/src/client/views/collections/FlashcardPracticeUI.tsx
index 3bcdd843e..8cd9c5452 100644
--- a/src/client/views/collections/FlashcardPracticeUI.tsx
+++ b/src/client/views/collections/FlashcardPracticeUI.tsx
@@ -12,10 +12,11 @@ import { BoolCast, NumCast, StrCast } from '../../../fields/Types';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
import { ObservableReactComponent } from '../ObservableReactComponent';
-import { DocumentView, DocumentViewProps } from '../nodes/DocumentView';
+import { DocumentView } from '../nodes/DocumentView';
import './FlashcardPracticeUI.scss';
import { StyleProp } from '../StyleProp';
import { FieldViewProps } from '../nodes/FieldView';
+import { DocumentViewProps } from '../nodes/DocumentContentsView';
export enum practiceMode {
PRACTICE = 'practice',
@@ -142,7 +143,6 @@ export class FlashcardPracticeUI extends ObservableReactComponent<PracticeUIProp
color={SnappingManager.userColor}
background={SnappingManager.userVariantColor}
multiSelect={false}
- isToggle={false}
toggleStatus={!!this.practiceMode}
label="Practice"
items={[
@@ -162,7 +162,6 @@ export class FlashcardPracticeUI extends ObservableReactComponent<PracticeUIProp
color={SnappingManager.userColor}
background={SnappingManager.userVariantColor}
multiSelect={false}
- isToggle={false}
toggleStatus={!!this.practiceMode}
label={StrCast(this._props.layoutDoc.revealOp, flashcardRevealOp.FLIP)}
items={[
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index cce0ff684..6c47a71b0 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -41,7 +41,7 @@
transition: background-color 1s ease 0s;
}
.collectionfreeformview-mask {
- mix-blend-mode: multiply;
+ mix-blend-mode: hard-light;
background-color: rgba(0, 0, 0, 0.8);
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index f01fb8fc7..1f789432d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1601,7 +1601,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const childDoc = pair.layout;
const layoutFrameNumber = Cast(this.Document._currentFrame, 'number'); // frame number that container is at which determines layout frame values
const contentFrameNumber = Cast(childDoc._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed
- const { z, zIndex } = childDoc;
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ const { z, zIndex, stroke_isInkMask } = childDoc;
const { backgroundColor, color } = contentFrameNumber === undefined ? { backgroundColor: undefined, color: undefined } : CollectionFreeFormDocumentView.getStringValues(childDoc, contentFrameNumber);
const { x, y, autoDim, _width, _height, opacity, _rotation } =
layoutFrameNumber === undefined // -1 for width/height means width/height should be PanelWidth/PanelHeight (prevents collectionfreeformdocumentview width/height from getting out of synch with panelWIdth/Height which causes detailView to re-render and lose focus because HTMLtag scaling gets set to a bad intermediate value)
@@ -1717,7 +1718,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
elements.push({
ele: this.getChildDocView(entry[1]),
bounds: entry[1].opacity === 0 ? { payload: undefined, type: '', ...entry[1], width: 0, height: 0 } : { payload: undefined, type: '', ...entry[1] },
- inkMask: BoolCast(entry[1].pair.layout.stroke_isInkMask) ? NumCast(entry[1].pair.layout.opacity, 1) : -1,
+ inkMask: BoolCast(entry[1].pair.layout?.$stroke_isInkMask) ? NumCast(entry[1].pair.layout.opacity, 1) : -1,
})
);
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 966d8d7a0..f83b5e351 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -301,7 +301,6 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
background={background}
multiSelect={true}
onPointerDown={e => script && !toggleStatus && setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => script.run({ this: this.Document, value: undefined, _readOnly_: false }))}
- isToggle={false}
toggleStatus={toggleStatus}
label={selectedItems.length === 1 ? selectedItems[0] : this.label}
items={items.map(item => ({