From baf156f58856004279223b2e1f858c5ff7e88686 Mon Sep 17 00:00:00 2001 From: eleanor-park Date: Tue, 4 Jun 2024 13:54:56 -0400 Subject: small fixes --- src/client/apis/gpt/GPT.ts | 6 ++++++ src/client/util/CurrentUserUtils.ts | 1 + src/client/views/MainView.tsx | 1 + src/client/views/SmartDraw.tsx | 0 src/client/views/collections/CollectionMenu.scss | 2 +- .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 6 ++++-- src/client/views/global/globalScripts.ts | 4 ++-- src/fields/Doc.ts | 4 ++-- 8 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 src/client/views/SmartDraw.tsx diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 05007960d..3a5e49731 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -53,6 +53,12 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { temp: 0, prompt: 'List unique differences between the content of the UserAnswer and Rubric. Before each difference, label it and provide any additional information the UserAnswer missed and explain it in second person without separating it into UserAnswer and Rubric content and additional information. If there are no differences, say correct', }, + draw: { + model: 'gpt-4o', + maxTokens: 256, + temp: 0.5, + prompt: 'Given an item to draw, generate a list of Bezier control points that will represent the item. Answer only with the list of coordinates and no additional text', + } }; let lastCall = ''; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index e095bc659..4e379219f 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -745,6 +745,7 @@ pie title Minerals in my tap water { title: "Labels", toolTip: "Lab els", btnType: ButtonType.ToggleButton, icon: "text-width", toolType: "labels", scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}, }, { title: "Width", toolTip: "Stroke width", btnType: ButtonType.NumberSliderButton, toolType: "strokeWidth", ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, numBtnMin: 1}, { title: "Ink", toolTip: "Stroke color", btnType: ButtonType.ColorButton, icon: "pen", toolType: "strokeColor", ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'} }, + { title: "Smart Draw", toolTip: "Draw with GPT", btnType: ButtonType.ToggleButton, icon: "user-pen", toolType: "smartDraw", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}'}, funcs: {hidden: "IsNoviceMode()"}}, ]; } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 31d88fb87..8430db883 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -394,6 +394,7 @@ export class MainView extends ObservableReactComponent<{}> { fa.faArrowsLeftRight, fa.faPause, fa.faPen, + fa.faUserPen, fa.faPenNib, fa.faPhone, fa.faPlay, diff --git a/src/client/views/SmartDraw.tsx b/src/client/views/SmartDraw.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss index 3ec875df4..45d9394ed 100644 --- a/src/client/views/collections/CollectionMenu.scss +++ b/src/client/views/collections/CollectionMenu.scss @@ -6,7 +6,7 @@ align-content: center; justify-content: space-between; background-color: $dark-gray; - height: 35px; + height: 40px; border-bottom: $standard-border; padding: 0 10px; align-items: center; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index b6e1fca77..c6db8290d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -504,12 +504,14 @@ export class CollectionFreeFormView extends CollectionSubView { SetActiveInkColor(StrCast(value)); selected?.type === DocumentType.INK && setActiveTool(GestureOverlay.Instance.InkShape ?? InkTool.Pen, true, false);}, }], [ 'eraserWidth', { - checkResult: () => ActiveEraserWidth(), + checkResult: () => ActiveEraserWidth() === 0 ? 1 : ActiveEraserWidth(), setInk: (doc: Doc) => { }, - setMode: () => { SetEraserWidth(value.toString());}, + setMode: () => { SetEraserWidth(value);}, }] ]); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 1b3d963e8..4a469dfe2 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -185,7 +185,7 @@ export function ActiveArrowScale(): number { return NumCast(ActiveInkPen()?.acti export function ActiveDash(): string { return StrCast(ActiveInkPen()?.activeDash, '0'); } // prettier-ignore export function ActiveInkWidth(): number { return Number(ActiveInkPen()?.activeInkWidth); } // prettier-ignore export function ActiveInkBezierApprox(): string { return StrCast(ActiveInkPen()?.activeInkBezier); } // prettier-ignore -export function ActiveEraserWidth(): number { return Number(ActiveInkPen()?.eraserWidth); } // prettier-ignore +export function ActiveEraserWidth(): number { return NumCast(ActiveInkPen()?.eraserWidth); } // prettier-ignore export function SetActiveInkWidth(width: string): void { !isNaN(parseInt(width)) && ActiveInkPen() && (ActiveInkPen().activeInkWidth = width); @@ -218,7 +218,7 @@ export function SetActiveDash(dash: string): void { !isNaN(parseInt(dash)) && ActiveInkPen() && (ActiveInkPen().activeDash = dash); } export function SetEraserWidth(width: number): void { - ActiveInkPen() && (ActiveInkPen().eraserWidth = width); + !isNaN(width) && ActiveInkPen() && (ActiveInkPen().eraserWidth = width); } @scriptingGlobal -- cgit v1.2.3-70-g09d2 From 2f5757ffaebaec9d459404fec266295abeebd2b0 Mon Sep 17 00:00:00 2001 From: eleanor-park Date: Thu, 6 Jun 2024 11:31:52 -0400 Subject: created input box for gpt draw --- src/client/apis/gpt/GPT.ts | 1 + src/client/util/CurrentUserUtils.ts | 2 +- src/client/views/MainView.tsx | 2 + src/client/views/SmartDraw.tsx | 0 .../collectionFreeForm/CollectionFreeFormView.tsx | 44 ++++-- .../collectionFreeForm/SmartDrawHandler.tsx | 154 +++++++++++++++++++++ src/fields/InkField.ts | 1 + 7 files changed, 195 insertions(+), 9 deletions(-) delete mode 100644 src/client/views/SmartDraw.tsx create mode 100644 src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 3a5e49731..5afb345a0 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -12,6 +12,7 @@ enum GPTCallType { DESCRIBE = 'describe', MERMAID = 'mermaid', DATA = 'data', + DRAW = 'draw', } type GPTCallOpts = { diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 4e379219f..3250f10a8 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -745,7 +745,7 @@ pie title Minerals in my tap water { title: "Labels", toolTip: "Lab els", btnType: ButtonType.ToggleButton, icon: "text-width", toolType: "labels", scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}, }, { title: "Width", toolTip: "Stroke width", btnType: ButtonType.NumberSliderButton, toolType: "strokeWidth", ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, numBtnMin: 1}, { title: "Ink", toolTip: "Stroke color", btnType: ButtonType.ColorButton, icon: "pen", toolType: "strokeColor", ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'} }, - { title: "Smart Draw", toolTip: "Draw with GPT", btnType: ButtonType.ToggleButton, icon: "user-pen", toolType: "smartDraw", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}'}, funcs: {hidden: "IsNoviceMode()"}}, + { title: "Smart Draw", toolTip: "Draw with GPT", btnType: ButtonType.ToggleButton, icon: "user-pen", toolType: "smartdraw", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}'}, funcs: {hidden: "IsNoviceMode()"}}, ]; } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 8430db883..f7e1617fc 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -55,6 +55,7 @@ import { TabDocView } from './collections/TabDocView'; import './collections/TreeView.scss'; import { CollectionFreeFormView } from './collections/collectionFreeForm'; import { ImageLabelHandler } from './collections/collectionFreeForm/ImageLabelHandler'; +import { SmartDrawHandler } from './collections/collectionFreeForm/SmartDrawHandler'; import { MarqueeOptionsMenu } from './collections/collectionFreeForm/MarqueeOptionsMenu'; import { CollectionLinearView } from './collections/collectionLinear'; import { LinkMenu } from './linking/LinkMenu'; @@ -1090,6 +1091,7 @@ export class MainView extends ObservableReactComponent<{}> { + diff --git a/src/client/views/SmartDraw.tsx b/src/client/views/SmartDraw.tsx deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index c6db8290d..194c99c3d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -54,6 +54,8 @@ import { CollectionFreeFormPannableContents } from './CollectionFreeFormPannable import { CollectionFreeFormRemoteCursors } from './CollectionFreeFormRemoteCursors'; import './CollectionFreeFormView.scss'; import { MarqueeView } from './MarqueeView'; +import { SmartDrawHandler } from './SmartDrawHandler'; +import { ImageLabelHandler } from './ImageLabelHandler'; @observer class CollectionFreeFormOverlayView extends React.Component<{ elements: () => ViewDefResult[] }> { @@ -496,30 +498,33 @@ export class CollectionFreeFormView extends CollectionSubView { + SmartDrawHandler.Instance.displaySmartDrawHandler(e.pageX, e.pageY); + if (SmartDrawHandler.Instance.coords) { + // const coords: InkData = SmartDrawHandler.Instance.coords; + // const inkField = new InkField(coords); + // const points = coords.map(p => intersect.inkView.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]); + // const bounds = InkField.getBounds(points); + // const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); + // const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; + // return Docs.Create.InkDocument( + // points, + // { title: 'stroke', + // x: B.x - inkWidth / 2, + // y: B.y - inkWidth / 2, + // _width: B.width + inkWidth, + // _height: B.height + inkWidth, + // stroke_showLabel: BoolCast(Doc.UserDoc().activeInkHideTextLabels)}, // prettier-ignore + // inkWidth + // ); + } + }; + @action zoom = (pointX: number, pointY: number, deltaY: number): void => { if (this.Document.isGroup || this.Document[(this._props.viewField ?? '_') + 'freeform_noZoom']) return; diff --git a/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx b/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx new file mode 100644 index 000000000..fc88b5cc6 --- /dev/null +++ b/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx @@ -0,0 +1,154 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { action, makeObservable, observable } from 'mobx'; +import { observer } from 'mobx-react'; +import React from 'react'; +import { SettingsManager } from '../../../util/SettingsManager'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; +import { Button, IconButton } from 'browndash-components'; +import ReactLoading from 'react-loading'; +import { AiOutlineSend } from 'react-icons/ai'; +import { MarqueeOptionsMenu } from './MarqueeOptionsMenu'; +import './ImageLabelHandler.scss'; +import { gptAPICall, GPTCallType } from '../../../apis/gpt/GPT'; +import { InkingStroke } from '../../InkingStroke'; +import { InkData } from '../../../../fields/InkField'; + +@observer +export class SmartDrawHandler extends ObservableReactComponent<{}> { + static Instance: SmartDrawHandler; + + @observable private _display: boolean = false; + @observable private _pageX: number = 0; + @observable private _pageY: number = 0; + @observable private _yRelativeToTop: boolean = true; + @observable private _isLoading: boolean = false; + @observable private _userInput: string = ''; + @observable public coords: InkData | undefined = undefined; + + constructor(props: any) { + super(props); + makeObservable(this); + SmartDrawHandler.Instance = this; + } + + @action + setIsLoading = (isLoading: boolean) => { + this._isLoading = isLoading; + }; + + @action + setUserInput = (input: string) => { + this._userInput = input; + }; + + @action + displaySmartDrawHandler = (x: number, y: number) => { + this._pageX = x; + this._pageY = y; + this._display = true; + }; + + @action + hideLabelhandler = () => { + this._display = false; + }; + + @action + drawWithGPT = async (startPoint: {X: number, Y: number}, input: string) => { + this.setIsLoading(true); + try { + const res = await gptAPICall(input, GPTCallType.DRAW); + if (!res) { + console.error('GPT call failed'); + return; + } + console.log("GPT response:", res); + // controlPts: {X: number, Y: number}[] = [] + // code to extract list of coords from the string + // this.coords = controlPts.map(pt: {X: number, Y: number } => {pt.X + startPoint.X, pt.Y + startPoint.Y}); + + + } catch (err) { + console.error('GPT call failed'); + } + + this.setIsLoading(false); + this.setUserInput(''); + }; + + render() { + if (this._display) { + return ( +
+
+ } color={MarqueeOptionsMenu.Instance.userColor} style={{ width: '19px' }} /> + { + this.setUserInput(e.target.value); + }} + placeholder="Enter item to draw" + /> +
+
+ {/* {this._labelGroups.map(group => { + return ( +
+

{group}

+ { + this.removeLabel(group); + }} + icon={'x'} + color={MarqueeOptionsMenu.Instance.userColor} + style={{ width: '19px' }} + /> +
+ ); + })} */} +
+
+ ); + } else { + return <>; + } + } +} diff --git a/src/fields/InkField.ts b/src/fields/InkField.ts index 32abf0076..123d32301 100644 --- a/src/fields/InkField.ts +++ b/src/fields/InkField.ts @@ -17,6 +17,7 @@ export enum InkTool { Stamp = 'stamp', Write = 'write', PresentationPin = 'presentationpin', + SmartDraw = 'smartdraw', } export type Segment = Array; -- cgit v1.2.3-70-g09d2 From 2277349fc4d5460e94a7a6b705b56488c0efb184 Mon Sep 17 00:00:00 2001 From: eleanor-park Date: Thu, 6 Jun 2024 13:14:41 -0400 Subject: working on creating ink strokes from pts --- src/client/apis/gpt/GPT.ts | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 37 ++++++++++++---------- .../collectionFreeForm/SmartDrawHandler.tsx | 27 ++++++++++++---- 3 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 5afb345a0..454ea8116 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -58,7 +58,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { model: 'gpt-4o', maxTokens: 256, temp: 0.5, - prompt: 'Given an item to draw, generate a list of Bezier control points that will represent the item. Answer only with the list of coordinates and no additional text', + prompt: 'Given an item to draw, generate Bezier control points that will represent the item. Answer only with a list of lists of coordinates, where each list of coordinates is one Bezier ink stroke. Do not include any text, description, or comments.', } }; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 194c99c3d..d22b3569e 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1233,23 +1233,26 @@ export class CollectionFreeFormView extends CollectionSubView { SmartDrawHandler.Instance.displaySmartDrawHandler(e.pageX, e.pageY); - if (SmartDrawHandler.Instance.coords) { - // const coords: InkData = SmartDrawHandler.Instance.coords; - // const inkField = new InkField(coords); - // const points = coords.map(p => intersect.inkView.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]); - // const bounds = InkField.getBounds(points); - // const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); - // const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; - // return Docs.Create.InkDocument( - // points, - // { title: 'stroke', - // x: B.x - inkWidth / 2, - // y: B.y - inkWidth / 2, - // _width: B.width + inkWidth, - // _height: B.height + inkWidth, - // stroke_showLabel: BoolCast(Doc.UserDoc().activeInkHideTextLabels)}, // prettier-ignore - // inkWidth - // ); + if (SmartDrawHandler.Instance.strokes.length > 0) { + const strokeList: InkData[] = SmartDrawHandler.Instance.strokes; + strokeList.forEach(coords => { + // const stroke = new InkField(coords); + // const points = coords.map(p => intersect.inkView.ComponentView?.ptToScreen?.({ X: p.X, Y: p.Y }) ?? { X: 0, Y: 0 }), [] as PointData[]); + const bounds = InkField.getBounds(coords); + const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); + const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; + const inkDoc = Docs.Create.InkDocument( + coords, + { title: 'stroke', + x: B.x - inkWidth / 2, + y: B.y - inkWidth / 2, + _width: B.width + inkWidth, + _height: B.height + inkWidth, + stroke_showLabel: BoolCast(Doc.UserDoc().activeInkHideTextLabels)}, // prettier-ignore + inkWidth + ); + this.addDocument(inkDoc); + }); } }; diff --git a/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx b/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx index fc88b5cc6..7e66a62d4 100644 --- a/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx +++ b/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx @@ -23,7 +23,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { @observable private _yRelativeToTop: boolean = true; @observable private _isLoading: boolean = false; @observable private _userInput: string = ''; - @observable public coords: InkData | undefined = undefined; + @observable public strokes: InkData[] = []; constructor(props: any) { super(props); @@ -55,6 +55,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { @action drawWithGPT = async (startPoint: {X: number, Y: number}, input: string) => { + console.log("start point is", startPoint); this.setIsLoading(true); try { const res = await gptAPICall(input, GPTCallType.DRAW); @@ -63,13 +64,27 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { return; } console.log("GPT response:", res); - // controlPts: {X: number, Y: number}[] = [] - // code to extract list of coords from the string - // this.coords = controlPts.map(pt: {X: number, Y: number } => {pt.X + startPoint.X, pt.Y + startPoint.Y}); - + try { + // const controlPts: [number, number][][] = JSON.parse(res) as [number, number][][]; + // console.log("Control Points", controlPts); + // const transformedPts: { X: number; Y: number }[][] = []; + // controlPts.forEach(stroke => { + // stroke.map(pt => { + // pt.X += startPoint.X, pt.Y += startPoint.Y; + // }); + // transformedPts.push(stroke); + // }); + + const controlPts: { X: number; Y: number }[][] = JSON.parse(res).map((stroke: [number, number][]) => + stroke.map(([X, Y]) => ({ X: X + startPoint.X, Y: Y + startPoint.Y }))); + console.log("transformed points", controlPts); + this.strokes = controlPts; + } catch (err) { + console.error('Incompatible GPT output type'); + } } catch (err) { - console.error('GPT call failed'); + console.error('GPT call failed', err); } this.setIsLoading(false); -- cgit v1.2.3-70-g09d2 From 33761fc2227458acf36a5cc4b1f08eaae6e58695 Mon Sep 17 00:00:00 2001 From: eleanor-park Date: Tue, 11 Jun 2024 11:15:25 -0400 Subject: some changes --- src/client/apis/gpt/GPT.ts | 2 +- src/client/util/CurrentUserUtils.ts | 1 + src/client/util/bezierFit.ts | 6 + src/client/views/MainView.tsx | 1 + src/client/views/MarqueeAnnotator.tsx | 147 +++++++++++++++++- .../collectionFreeForm/CollectionFreeFormView.tsx | 170 +++++++++++++-------- .../collectionFreeForm/SmartDrawHandler.tsx | 31 ++-- src/client/views/pdf/AnchorMenu.tsx | 14 ++ src/client/views/pdf/PDFViewer.tsx | 3 + 9 files changed, 293 insertions(+), 82 deletions(-) diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 454ea8116..e02488607 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -58,7 +58,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { model: 'gpt-4o', maxTokens: 256, temp: 0.5, - prompt: 'Given an item to draw, generate Bezier control points that will represent the item. Answer only with a list of lists of coordinates, where each list of coordinates is one Bezier ink stroke. Do not include any text, description, or comments.', + prompt: 'Given an item to draw, generate Bezier control points that will represent the item. Answer only with a list of lists of coordinates, where each list of coordinates is one Bezier ink stroke. Remember that Bezier curves will smooth out along control points, so try to keep as much in one stroke as possible. However, if there is an edge or corner be sure to split into a new stroke. Make sure you generate control handle points as well as the actual anchor points. Do not include any text, description, or comments. ONLY USE INTEGERS, NOT DECIMALS.', } }; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 3250f10a8..1eb2d9cc1 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -730,6 +730,7 @@ pie title Minerals in my tap water static inkTools():Button[] { return [ { title: "Pen", toolTip: "Pen (Ctrl+P)", btnType: ButtonType.ToggleButton, icon: "pen-nib", toolType: "pen", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' }}, + { title: "Highlight", toolTip: "Highlight (Ctrl+H)", btnType: ButtonType.ToggleButton, icon: "highlighter",toolType: "highlighter", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' }}, { title: "Write", toolTip: "Write (Ctrl+Shift+P)", btnType: ButtonType.ToggleButton, icon: "pen", toolType: "write", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' }, funcs: {hidden:"IsNoviceMode()" }}, { title: "Eraser", toolTip: "Eraser (Ctrl+E)", btnType: ButtonType.MultiToggleButton, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'}, funcs: {toolType:"activeEraserTool()"}, subMenu: [ diff --git a/src/client/util/bezierFit.ts b/src/client/util/bezierFit.ts index d6f3f2340..bb3b6b1eb 100644 --- a/src/client/util/bezierFit.ts +++ b/src/client/util/bezierFit.ts @@ -557,6 +557,12 @@ function FitCubic(d: Point[], first: number, last: number, tHat1: Point, tHat2: const negThatCenter = new Point(-tHatCenter.X, -tHatCenter.Y); FitCubic(d, splitPoint2D, last, negThatCenter, tHat2, error, result); } +/** + * Convert polyline coordinates to a (multi) segment bezier curve + * @param d - polyline coordinates + * @param error - how much error to allow in fitting (measured in pixels) + * @returns + */ export function FitCurve(d: Point[], error: number) { const tHat1 = ComputeLeftTangent(d, 0); // Unit tangent vectors at endpoints const tHat2 = ComputeRightTangent(d, d.length - 1); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index f7e1617fc..a1cb44106 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -402,6 +402,7 @@ export class MainView extends ObservableReactComponent<{}> { fa.faPortrait, fa.faRedoAlt, fa.faStamp, + fa.faTape, fa.faStickyNote, fa.faArrowsAltV, fa.faTimesCircle, diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index c18ac6738..db48e095d 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -28,6 +28,7 @@ export interface MarqueeAnnotatorProps { marqueeContainer: HTMLDivElement; docView: () => DocumentView; savedAnnotations: () => ObservableMap; + savedTapes: () => ObservableMap; selectionText: () => string; annotationLayer: HTMLDivElement; addDocument: (doc: Doc) => boolean; @@ -73,7 +74,7 @@ export class MarqueeAnnotator extends ObservableReactComponent): Opt => { + // const savedTapeMap = savedTapes?.values() && Array.from(savedTapes?.values()).length ? savedTapes : this.props.savedTapes(); + // if (savedTapeMap.size === 0) return undefined; + // const tapes = Array.from(savedTapeMap.values())[0]; + // const doc = this.props.Document; + // const scale = (this.props.annotationLayerScaling?.() || 1) * NumCast(doc._freeform_scale, 1); + // if (tapes.length && (tapes[0] as any).marqueeing) { + // const anno = tapes[0]; + // const containerOffset = this.props.containerOffset?.() || [0, 0]; + // const tape = Docs.Create.FreeformDocument([], { + // onClick: isLinkButton ? FollowLinkScript() : undefined, + // backgroundColor: color, + // annotationOn: this.props.Document, + // title: 'Tape on ' + this.props.Document.title, + // }); + // tape.x = NumCast(doc.freeform_panX_min) + (parseInt(anno.style.left || '0') - containerOffset[0]) / scale; + // tape.y = NumCast(doc.freeform_panY_min) + (parseInt(anno.style.top || '0') - containerOffset[1]) / scale; + // tape._height = parseInt(anno.style.height || '0') / scale; + // tape._width = parseInt(anno.style.width || '0') / scale; + // anno.remove(); + // savedTapeMap.clear(); + // return tape; + // } + + // const textRegionAnno = Docs.Create.ConfigDocument({ + // annotationOn: this.props.Document, + // text: this.props.selectionText() as any, // text want an RTFfield, but strings are acceptable, too. + // text_html: this.props.selectionText() as any, + // backgroundColor: 'transparent', + // presentation_duration: 2100, + // presentation_transition: 500, + // presentation_zoomText: true, + // title: '>' + this.props.Document.title, + // }); + // const textRegionAnnoProto = textRegionAnno[DocData]; + // let minX = Number.MAX_VALUE; + // let maxX = -Number.MAX_VALUE; + // let minY = Number.MAX_VALUE; + // let maxY = -Number.MIN_VALUE; + // const annoRects: string[] = []; + // savedAnnoMap.forEach((value: HTMLDivElement[]) => + // value.forEach(anno => { + // const x = parseInt(anno.style.left ?? '0'); + // const y = parseInt(anno.style.top ?? '0'); + // const height = parseInt(anno.style.height ?? '0'); + // const width = parseInt(anno.style.width ?? '0'); + // annoRects.push(`${x}:${y}:${width}:${height}`); + // anno.remove(); + // minY = Math.min(NumCast(y), minY); + // minX = Math.min(NumCast(x), minX); + // maxY = Math.max(NumCast(y) + NumCast(height), maxY); + // maxX = Math.max(NumCast(x) + NumCast(width), maxX); + // }) + // ); + + // textRegionAnnoProto.y = Math.max(minY, 0); + // textRegionAnnoProto.x = Math.max(minX, 0); + // textRegionAnnoProto.height = Math.max(maxY, 0) - Math.max(minY, 0); + // textRegionAnnoProto.width = Math.max(maxX, 0) - Math.max(minX, 0); + // textRegionAnnoProto.backgroundColor = color; + // // mainAnnoDocProto.text = this._selectionText; + // textRegionAnnoProto.text_inlineAnnotations = new List(annoRects); + // textRegionAnnoProto.opacity = 0; + // textRegionAnnoProto.layout_unrendered = true; + // savedAnnoMap.clear(); + // return textRegionAnno; + // }; + + @undoBatch + makeTapeDocument = (color: string, isLinkButton?: boolean, savedTapes?: ObservableMap): Opt => { + // const savedAnnoMap = savedTapes?.values() && Array.from(savedTapes?.values()).length ? savedTapes : this.props.savedTapes(); + // if (savedAnnoMap.size === 0) return undefined; + // const savedAnnos = Array.from(savedAnnoMap.values())[0]; + const doc = this.props.Document; + const scale = (this.props.annotationLayerScaling?.() || 1) * NumCast(doc._freeform_scale, 1); + const marqueeAnno = Docs.Create.FreeformDocument([], { + onClick: isLinkButton ? FollowLinkScript() : undefined, + backgroundColor: color, + annotationOn: this.props.Document, + title: 'Annotation on ' + this.props.Document.title, + }); + marqueeAnno.x = NumCast(doc.freeform_panX_min) / scale; + marqueeAnno.y = NumCast(doc.freeform_panY_min) / scale; + marqueeAnno._height = parseInt('100') / scale; + marqueeAnno._width = parseInt('100') / scale; + return marqueeAnno; + // } + + // const textRegionAnno = Docs.Create.ConfigDocument({ + // annotationOn: this.props.Document, + // text: this.props.selectionText() as any, // text want an RTFfield, but strings are acceptable, too. + // text_html: this.props.selectionText() as any, + // backgroundColor: 'transparent', + // presentation_duration: 2100, + // presentation_transition: 500, + // presentation_zoomText: true, + // title: '>' + this.props.Document.title, + // }); + // const textRegionAnnoProto = textRegionAnno[DocData]; + // let minX = Number.MAX_VALUE; + // let maxX = -Number.MAX_VALUE; + // let minY = Number.MAX_VALUE; + // let maxY = -Number.MIN_VALUE; + // const annoRects: string[] = []; + // savedAnnoMap.forEach((value: HTMLDivElement[]) => + // value.forEach(anno => { + // const x = parseInt(anno.style.left ?? '0'); + // const y = parseInt(anno.style.top ?? '0'); + // const height = parseInt(anno.style.height ?? '0'); + // const width = parseInt(anno.style.width ?? '0'); + // annoRects.push(`${x}:${y}:${width}:${height}`); + // anno.remove(); + // minY = Math.min(NumCast(y), minY); + // minX = Math.min(NumCast(x), minX); + // maxY = Math.max(NumCast(y) + NumCast(height), maxY); + // maxX = Math.max(NumCast(x) + NumCast(width), maxX); + // }) + // ); + + // textRegionAnnoProto.y = Math.max(minY, 0); + // textRegionAnnoProto.x = Math.max(minX, 0); + // textRegionAnnoProto.height = Math.max(maxY, 0) - Math.max(minY, 0); + // textRegionAnnoProto.width = Math.max(maxX, 0) - Math.max(minX, 0); + // textRegionAnnoProto.backgroundColor = color; + // // mainAnnoDocProto.text = this._selectionText; + // textRegionAnnoProto.text_inlineAnnotations = new List(annoRects); + // textRegionAnnoProto.opacity = 0; + // textRegionAnnoProto.layout_unrendered = true; + // savedAnnoMap.clear(); + // return textRegionAnno; + }; + @action highlight = (color: string, isLinkButton: boolean, savedAnnotations?: ObservableMap, addAsAnnotation?: boolean) => { // creates annotation documents for current highlights @@ -136,6 +271,15 @@ export class MarqueeAnnotator extends ObservableReactComponent, addAsAnnotation?: boolean) => { + // creates annotation documents for current highlights + const effectiveAcl = GetEffectiveAcl(this.props.Document[DocData]); + const tape = [AclAugment, AclSelfEdit, AclEdit, AclAdmin].includes(effectiveAcl) && this.makeTapeDocument(color, isLinkButton, savedTapes); + addAsAnnotation && tape && this.props.addDocument(tape); + return tape as Doc; + }; + public static previewNewAnnotation = action((savedAnnotations: ObservableMap, annotationLayer: HTMLDivElement, div: HTMLDivElement, page: number) => { div.style.backgroundColor = '#ACCEF7'; div.style.opacity = '0.5'; @@ -182,6 +326,7 @@ export class MarqueeAnnotator extends ObservableReactComponent this.props.anchorMenuClick?.()?.(this.highlight(this.props.highlightDragSrcColor ?? 'rgba(173, 216, 230, 0.75)', true, undefined, true)), 'make sidebar annotation'); AnchorMenu.Instance.OnAudio = unimplementedFunction; AnchorMenu.Instance.Highlight = (color: string) => this.highlight(color, false, undefined, true); + AnchorMenu.Instance.Tape = (color: string) => this.tape(color, false, undefined, true); AnchorMenu.Instance.GetAnchor = (savedAnnotations?: ObservableMap /* , addAsAnnotation?: boolean */) => this.highlight('rgba(173, 216, 230, 0.75)', true, savedAnnotations, true); AnchorMenu.Instance.onMakeAnchor = () => AnchorMenu.Instance.GetAnchor(undefined, true); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index d22b3569e..e66dbd796 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -144,7 +144,10 @@ export class CollectionFreeFormView extends CollectionSubView { + erase = (e: PointerEvent, delta: number[]) => { const currPoint = { X: e.clientX, Y: e.clientY }; this._eraserPts.push([currPoint.X, currPoint.Y]); this._eraserPts = this._eraserPts.slice(Math.max(0, this._eraserPts.length - 5)); - // if (this._eraserLock) return false; // leaving this commented out in case the idea is revisited in the future - this.getEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint).forEach(intersect => { - if (!this._deleteList.includes(intersect.inkView)) { - this._deleteList.push(intersect.inkView); - SetActiveInkWidth(StrCast(intersect.inkView.Document.stroke_width?.toString()) || '1'); - SetActiveInkColor(StrCast(intersect.inkView.Document.color?.toString()) || 'black'); - // create a new curve by appending all curves of the current segment together in order to render a single new stroke. - if (Doc.ActiveTool !== InkTool.StrokeEraser) { - // this._eraserLock++; - const segments = this.segmentErase(intersect.inkView, intersect.t); // intersect.t is where the eraser intersected the ink stroke - want to remove the segment that starts at the intersection just before this t value and goes to the one just after it - const newStrokes = segments?.map(segment => { - const points = segment.reduce((data, curve) => [...data, ...curve.points.map(p => intersect.inkView.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]); - const bounds = InkField.getBounds(points); - const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); - const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; - return Docs.Create.InkDocument( - points, - { title: 'stroke', + if (Doc.ActiveTool === InkTool.RadiusEraser) { + const strokeMap: Map = this.getRadiusEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint); + + strokeMap.forEach((intersects, stroke) => { + if (!this._deleteList.includes(stroke)) { + this._deleteList.push(stroke); + SetActiveInkWidth(StrCast(stroke.Document.stroke_width?.toString()) || '1'); + SetActiveInkColor(StrCast(stroke.Document.color?.toString()) || 'black'); + const segments = this.radiusErase(stroke, intersects.sort()); + segments?.forEach(segment => + this.forceStrokeGesture( + e, + Gestures.Stroke, + segment.reduce((data, curve) => [...data, ...curve.points.map(p => stroke.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]) + ) + ); + } + stroke.layoutDoc.opacity = 0; + stroke.layoutDoc.dontIntersect = true; + }); + } else { + this.getEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint).forEach(intersect => { + if (!this._deleteList.includes(intersect.inkView)) { + this._deleteList.push(intersect.inkView); + SetActiveInkWidth(StrCast(intersect.inkView.Document.stroke_width?.toString()) || '1'); + SetActiveInkColor(StrCast(intersect.inkView.Document.color?.toString()) || 'black'); + // create a new curve by appending all curves of the current segment together in order to render a single new stroke. + if (Doc.ActiveTool !== InkTool.StrokeEraser) { + // this._eraserLock++; + const segments = this.segmentErase(intersect.inkView, intersect.t); // intersect.t is where the eraser intersected the ink stroke - want to remove the segment that starts at the intersection just before this t value and goes to the one just after it + const newStrokes = segments?.map(segment => { + const points = segment.reduce((data, curve) => [...data, ...curve.points.map(p => intersect.inkView.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]); + const bounds = InkField.getBounds(points); + const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); + const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; + return Docs.Create.InkDocument( + points, + { title: 'stroke', x: B.x - inkWidth / 2, y: B.y - inkWidth / 2, _width: B.width + inkWidth, _height: B.height + inkWidth, stroke_showLabel: BoolCast(Doc.UserDoc().activeInkHideTextLabels)}, // prettier-ignore - inkWidth - ); - }); - newStrokes && this.addDocument?.(newStrokes); - // setTimeout(() => this._eraserLock--); + inkWidth + ); + }); + newStrokes && this.addDocument?.(newStrokes); + // setTimeout(() => this._eraserLock--); + } + // Lower ink opacity to give the user a visual indicator of deletion. + intersect.inkView.layoutDoc.opacity = 0; + intersect.inkView.layoutDoc.dontIntersect = true; } - // Lower ink opacity to give the user a visual indicator of deletion. - intersect.inkView.layoutDoc.opacity = 0; - intersect.inkView.layoutDoc.dontIntersect = true; - } - }); + }); + } + return false; + }; + + /** + * Erases strokes by intersecting them with an invisible "eraser stroke". + * By default this iterates through all intersected ink strokes, determines their segmentation, draws back the non-intersected segments, + * and deletes the original stroke. + */ + @action + onEraserMove = (e: PointerEvent, down: number[], delta: number[]) => { + this.erase(e, delta); + // if (this._eraserLock) return false; // leaving this commented out in case the idea is revisited in the future + return false; + }; + + @action + onEraserClick = (e: PointerEvent, doubleTap?: boolean) => { + this.erase(e, [0, 0]); return false; }; @@ -720,7 +753,7 @@ export class CollectionFreeFormView extends CollectionSubView { - SmartDrawHandler.Instance.displaySmartDrawHandler(e.pageX, e.pageY); - if (SmartDrawHandler.Instance.strokes.length > 0) { - const strokeList: InkData[] = SmartDrawHandler.Instance.strokes; - strokeList.forEach(coords => { - // const stroke = new InkField(coords); - // const points = coords.map(p => intersect.inkView.ComponentView?.ptToScreen?.({ X: p.X, Y: p.Y }) ?? { X: 0, Y: 0 }), [] as PointData[]); - const bounds = InkField.getBounds(coords); - const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); - const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; - const inkDoc = Docs.Create.InkDocument( - coords, - { title: 'stroke', + SmartDrawHandler.Instance.displaySmartDrawHandler(e.pageX, e.pageY, this.createInkStroke); + }; + + @action + createInkStroke = (strokeList: InkData[]) => { + strokeList.forEach(coords => { + // const stroke = new InkField(coords); + // const points = coords.map(p => intersect.inkView.ComponentView?.ptToScreen?.({ X: p.X, Y: p.Y }) ?? { X: 0, Y: 0 }), [] as PointData[]); + const bounds = InkField.getBounds(coords); + const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); + const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; + const inkDoc = Docs.Create.InkDocument( + coords, + { title: 'stroke', x: B.x - inkWidth / 2, y: B.y - inkWidth / 2, _width: B.width + inkWidth, _height: B.height + inkWidth, stroke_showLabel: BoolCast(Doc.UserDoc().activeInkHideTextLabels)}, // prettier-ignore - inkWidth - ); - this.addDocument(inkDoc); - }); - } + inkWidth + ); + this.addDocument(inkDoc); + }); }; @action @@ -1849,8 +1883,10 @@ export class CollectionFreeFormView extends CollectionSubView { - this._eraserX = e.clientX; - this._eraserY = e.clientY; + const locPt = this.ScreenToLocalBoxXf().transformPoint(e.clientX, e.clientY); + this._eraserX = locPt[0]; + this._eraserY = locPt[1]; + // Doc.ActiveTool === InkTool.RadiusEraser ? this._childPointerEvents = 'none' : this._childPointerEvents = 'all' // super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY)); }; @@ -2161,8 +2197,8 @@ export class CollectionFreeFormView extends CollectionSubView { @observable private _yRelativeToTop: boolean = true; @observable private _isLoading: boolean = false; @observable private _userInput: string = ''; - @observable public strokes: InkData[] = []; + // @observable public strokes: InkData[] = []; + private _addToDocFunc: (strokeList: InkData[]) => void = () => {}; constructor(props: any) { super(props); @@ -42,10 +42,11 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { }; @action - displaySmartDrawHandler = (x: number, y: number) => { + displaySmartDrawHandler = (x: number, y: number, addToDoc: (strokeList: InkData[]) => void) => { this._pageX = x; this._pageY = y; this._display = true; + this._addToDocFunc = addToDoc; }; @action @@ -54,8 +55,11 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { }; @action - drawWithGPT = async (startPoint: {X: number, Y: number}, input: string) => { - console.log("start point is", startPoint); + waitForCoords = async () => {}; + + @action + drawWithGPT = async (startPoint: { X: number; Y: number }, input: string) => { + console.log('start point is', startPoint); this.setIsLoading(true); try { const res = await gptAPICall(input, GPTCallType.DRAW); @@ -63,8 +67,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { console.error('GPT call failed'); return; } - console.log("GPT response:", res); - try { + console.log('GPT response:', res); // const controlPts: [number, number][][] = JSON.parse(res) as [number, number][][]; // console.log("Control Points", controlPts); // const transformedPts: { X: number; Y: number }[][] = []; @@ -74,15 +77,17 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { // }); // transformedPts.push(stroke); // }); + const simplifiedRes: string = res.replace(/[^\d\[\],]/g, ''); + console.log(simplifiedRes) + try { + const controlPts: { X: number; Y: number }[][] = JSON.parse(simplifiedRes).map((stroke: [number, number][]) => stroke.map(([X, Y]) => ({ X: X + startPoint.X, Y: Y + startPoint.Y }))); + console.log('transformed points', controlPts); - const controlPts: { X: number; Y: number }[][] = JSON.parse(res).map((stroke: [number, number][]) => - stroke.map(([X, Y]) => ({ X: X + startPoint.X, Y: Y + startPoint.Y }))); - console.log("transformed points", controlPts); - this.strokes = controlPts; + // this.strokes = controlPts; + this._addToDocFunc(controlPts); } catch (err) { console.error('Incompatible GPT output type'); } - } catch (err) { console.error('GPT call failed', err); } @@ -124,7 +129,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { iconPlacement="right" color={MarqueeOptionsMenu.Instance.userColor} onClick={e => { - this.drawWithGPT({X: e.clientX, Y: e.clientY}, this._userInput); + this.drawWithGPT({ X: e.clientX, Y: e.clientY }, this._userInput); }} /> {/* { public StartDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction; public StartCropDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction; public Highlight: (color: string) => Opt = (/* color: string */) => undefined; + public Tape: (color: string) => Opt = (/* color: string */) => undefined; public GetAnchor: (savedAnnotations: Opt>, addAsAnnotation: boolean) => Opt = emptyFunction; public Delete: () => void = unimplementedFunction; public PinToPres: () => void = unimplementedFunction; @@ -172,6 +173,12 @@ export class AnchorMenu extends AntimodeMenu { AnchorMenu.Instance.fadeOut(true); }; + @action + tapeClicked = () => { + this.Tape(this.highlightColor); + // AnchorMenu.Instance.fadeOut(true); + }; + @computed get highlighter() { return ( @@ -182,6 +189,13 @@ export class AnchorMenu extends AntimodeMenu { colorPicker={this.highlightColor} color={SettingsManager.userColor} /> + } + onClick={this.tapeClicked} + colorPicker={this.highlightColor} + color={SettingsManager.userColor} + /> ); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 6c1617c38..9ca05965b 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -67,6 +67,7 @@ export class PDFViewer extends ObservableReactComponent { @observable _pageSizes: { width: number; height: number }[] = []; @observable _savedAnnotations = new ObservableMap(); + @observable _savedTapes = new ObservableMap(); @observable _textSelecting = true; @observable _showWaiting = true; @observable Index: number = -1; @@ -583,6 +584,7 @@ export class PDFViewer extends ObservableReactComponent { return
; } savedAnnotations = () => this._savedAnnotations; + savedTapes = () => this._savedTapes; addDocumentWrapper = (doc: Doc | Doc[]) => this._props.addDocument!(doc); render() { TraceMobx(); @@ -616,6 +618,7 @@ export class PDFViewer extends ObservableReactComponent { docView={this._props.pdfBox.DocumentView!} finishMarquee={this.finishMarquee} savedAnnotations={this.savedAnnotations} + savedTapes={this.savedTapes} selectionText={this.selectionText} annotationLayer={this._annotationLayer.current} marqueeContainer={this._mainCont.current} -- cgit v1.2.3-70-g09d2 From b6ae411cfa04f6736d91749e6c99beb8179b3a30 Mon Sep 17 00:00:00 2001 From: eleanor-park Date: Fri, 14 Jun 2024 14:23:56 -0400 Subject: looking for weird error --- src/client/apis/gpt/GPT.ts | 6 +- src/client/util/CurrentUserUtils.ts | 2 +- src/client/util/bezierFit.ts | 26 +++++- src/client/views/MainView.tsx | 4 +- src/client/views/MarqueeAnnotator.tsx | 5 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 26 +++--- .../collectionFreeForm/SmartDrawHandler.tsx | 95 +++++++++------------- 7 files changed, 86 insertions(+), 78 deletions(-) diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index e02488607..0c993680e 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -56,10 +56,10 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { }, draw: { model: 'gpt-4o', - maxTokens: 256, + maxTokens: 1024, temp: 0.5, - prompt: 'Given an item to draw, generate Bezier control points that will represent the item. Answer only with a list of lists of coordinates, where each list of coordinates is one Bezier ink stroke. Remember that Bezier curves will smooth out along control points, so try to keep as much in one stroke as possible. However, if there is an edge or corner be sure to split into a new stroke. Make sure you generate control handle points as well as the actual anchor points. Do not include any text, description, or comments. ONLY USE INTEGERS, NOT DECIMALS.', - } + prompt: 'I would like you to generate me vector art with Bezier curves. Given a prompt, generate a sequence of cubic Bezier coordinates in the range of 0 to 200 (unless specified larger/smaller) that creates a line drawing of the object. Respond only with the coordinates', + }, }; let lastCall = ''; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 1eb2d9cc1..b6a7cacba 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -730,7 +730,7 @@ pie title Minerals in my tap water static inkTools():Button[] { return [ { title: "Pen", toolTip: "Pen (Ctrl+P)", btnType: ButtonType.ToggleButton, icon: "pen-nib", toolType: "pen", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' }}, - { title: "Highlight", toolTip: "Highlight (Ctrl+H)", btnType: ButtonType.ToggleButton, icon: "highlighter",toolType: "highlighter", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' }}, + { title: "Highlight", toolTip: "Highlight (Ctrl+H)", btnType: ButtonType.ToggleButton, icon: "highlighter",toolType: "highlighter", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' }}, { title: "Write", toolTip: "Write (Ctrl+Shift+P)", btnType: ButtonType.ToggleButton, icon: "pen", toolType: "write", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' }, funcs: {hidden:"IsNoviceMode()" }}, { title: "Eraser", toolTip: "Eraser (Ctrl+E)", btnType: ButtonType.MultiToggleButton, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'}, funcs: {toolType:"activeEraserTool()"}, subMenu: [ diff --git a/src/client/util/bezierFit.ts b/src/client/util/bezierFit.ts index bb3b6b1eb..fbc2bb7cd 100644 --- a/src/client/util/bezierFit.ts +++ b/src/client/util/bezierFit.ts @@ -561,7 +561,7 @@ function FitCubic(d: Point[], first: number, last: number, tHat1: Point, tHat2: * Convert polyline coordinates to a (multi) segment bezier curve * @param d - polyline coordinates * @param error - how much error to allow in fitting (measured in pixels) - * @returns + * @returns */ export function FitCurve(d: Point[], error: number) { const tHat1 = ComputeLeftTangent(d, 0); // Unit tangent vectors at endpoints @@ -592,6 +592,30 @@ export function FitOneCurve(d: Point[], tHat1?: Point, tHat2?: Point) { return { finalCtrls, error }; } +// alpha determines how far away the tangents are, or the "tightness" of the bezier +export function GenerateControlPoints(coordinates: Point[], alpha = 0.1) { + const firstEnd = coordinates.length ? [coordinates[0], coordinates[0]] : []; + const lastEnd = coordinates.length ? [coordinates.lastElement(), coordinates.lastElement()] : []; + const points: Point[] = coordinates.slice(1, coordinates.length - 1).flatMap((pt, index, inkData) => { + const prevPt: Point = index === 0 ? firstEnd[0] : inkData[index - 1]; + const nextPt: Point = index === inkData.length - 1 ? lastEnd[0] : inkData[index + 1]; + if (prevPt.X === nextPt.X) { + const verticalDist = nextPt.Y - prevPt.Y; + return [{ X: pt.X, Y: pt.Y - alpha * verticalDist }, pt, pt, { X: pt.X, Y: pt.Y + alpha * verticalDist }]; + } else if (prevPt.Y === nextPt.Y) { + const horizDist = nextPt.X - prevPt.X; + return [{ X: pt.X - alpha * horizDist, Y: pt.Y }, pt, pt, { X: pt.X + alpha * horizDist, Y: pt.Y }]; + } + // tangent vectors between the adjacent points + const tanX = nextPt.X - prevPt.X; + const tanY = nextPt.Y - prevPt.Y; + const ctrlPt1: Point = { X: pt.X - alpha * tanX, Y: pt.Y - alpha * tanY }; + const ctrlPt2: Point = { X: pt.X + alpha * tanX, Y: pt.Y + alpha * tanY }; + return [ctrlPt1, pt, pt, ctrlPt2]; + }); + return [...firstEnd, ...points, ...lastEnd]; +} + /* static double GetTValueFromSValue (const BezierRep &parent, double t, double endT, bool left, double influenceDistance, double &excess) { double dist = 0; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index a1cb44106..44e00396e 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -55,7 +55,6 @@ import { TabDocView } from './collections/TabDocView'; import './collections/TreeView.scss'; import { CollectionFreeFormView } from './collections/collectionFreeForm'; import { ImageLabelHandler } from './collections/collectionFreeForm/ImageLabelHandler'; -import { SmartDrawHandler } from './collections/collectionFreeForm/SmartDrawHandler'; import { MarqueeOptionsMenu } from './collections/collectionFreeForm/MarqueeOptionsMenu'; import { CollectionLinearView } from './collections/collectionLinear'; import { LinkMenu } from './linking/LinkMenu'; @@ -318,6 +317,7 @@ export class MainView extends ObservableReactComponent<{}> { fa.faCompass, fa.faSnowflake, fa.faStar, + fa.faSplotch, fa.faMicrophone, fa.faCircleHalfStroke, fa.faKeyboard, @@ -402,7 +402,6 @@ export class MainView extends ObservableReactComponent<{}> { fa.faPortrait, fa.faRedoAlt, fa.faStamp, - fa.faTape, fa.faStickyNote, fa.faArrowsAltV, fa.faTimesCircle, @@ -1092,7 +1091,6 @@ export class MainView extends ObservableReactComponent<{}> { - diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index db48e095d..f06f3efe0 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -74,7 +74,8 @@ export class MarqueeAnnotator extends ObservableReactComponent ViewDefResult[] }> { @@ -144,10 +145,7 @@ export class CollectionFreeFormView extends CollectionSubView { this.erase(e, [0, 0]); + e.stopPropagation(); return false; }; @@ -1265,19 +1264,20 @@ export class CollectionFreeFormView extends CollectionSubView { - SmartDrawHandler.Instance.displaySmartDrawHandler(e.pageX, e.pageY, this.createInkStroke); + SmartDrawHandler.Instance.displaySmartDrawHandler(e.pageX, e.pageY, this.createInkStrokes); }; @action - createInkStroke = (strokeList: InkData[]) => { - strokeList.forEach(coords => { - // const stroke = new InkField(coords); - // const points = coords.map(p => intersect.inkView.ComponentView?.ptToScreen?.({ X: p.X, Y: p.Y }) ?? { X: 0, Y: 0 }), [] as PointData[]); - const bounds = InkField.getBounds(coords); + createInkStrokes = (strokeList: InkData[], alpha?: number) => { + console.log(strokeList.length); + strokeList.forEach(inkData => { + // const points: InkData = FitCurve(inkData, 20) as InkData; + const allPts = GenerateControlPoints(inkData, alpha); + const bounds = InkField.getBounds(allPts); const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; const inkDoc = Docs.Create.InkDocument( - coords, + allPts, { title: 'stroke', x: B.x - inkWidth / 2, y: B.y - inkWidth / 2, diff --git a/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx b/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx index fc8f7a429..4c2e78e31 100644 --- a/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx +++ b/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx @@ -11,6 +11,7 @@ import { MarqueeOptionsMenu } from './MarqueeOptionsMenu'; import './ImageLabelHandler.scss'; import { gptAPICall, GPTCallType } from '../../../apis/gpt/GPT'; import { InkData } from '../../../../fields/InkField'; +import { ButtonType } from '../../nodes/FontIconBox/FontIconBox'; @observer export class SmartDrawHandler extends ObservableReactComponent<{}> { @@ -22,8 +23,11 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { @observable private _yRelativeToTop: boolean = true; @observable private _isLoading: boolean = false; @observable private _userInput: string = ''; + @observable private _drawingTypeToolTip = 'Create Geometric Drawing'; + @observable private _drawingTypeIcon: 'star' | 'splotch' = 'star'; + @observable private _alpha: number | undefined = undefined; // number between 0 and 1 that determines how rounded a drawing will be // @observable public strokes: InkData[] = []; - private _addToDocFunc: (strokeList: InkData[]) => void = () => {}; + private _addToDocFunc: (strokeList: InkData[], alpha?: number) => void = () => {}; constructor(props: any) { super(props); @@ -42,7 +46,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { }; @action - displaySmartDrawHandler = (x: number, y: number, addToDoc: (strokeList: InkData[]) => void) => { + displaySmartDrawHandler = (x: number, y: number, addToDoc: (strokeList: InkData[], alpha?: number) => void) => { this._pageX = x; this._pageY = y; this._display = true; @@ -50,13 +54,10 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { }; @action - hideLabelhandler = () => { + hideSmartDrawHandler = () => { this._display = false; }; - @action - waitForCoords = async () => {}; - @action drawWithGPT = async (startPoint: { X: number; Y: number }, input: string) => { console.log('start point is', startPoint); @@ -68,25 +69,18 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { return; } console.log('GPT response:', res); - // const controlPts: [number, number][][] = JSON.parse(res) as [number, number][][]; - // console.log("Control Points", controlPts); - // const transformedPts: { X: number; Y: number }[][] = []; - // controlPts.forEach(stroke => { - // stroke.map(pt => { - // pt.X += startPoint.X, pt.Y += startPoint.Y; - // }); - // transformedPts.push(stroke); - // }); const simplifiedRes: string = res.replace(/[^\d\[\],]/g, ''); - console.log(simplifiedRes) try { - const controlPts: { X: number; Y: number }[][] = JSON.parse(simplifiedRes).map((stroke: [number, number][]) => stroke.map(([X, Y]) => ({ X: X + startPoint.X, Y: Y + startPoint.Y }))); - console.log('transformed points', controlPts); - - // this.strokes = controlPts; - this._addToDocFunc(controlPts); + const parsedPts = JSON.parse(simplifiedRes); + if (parsedPts[0][0][0]) { + const controlPts = (parsedPts as [number, number][][]).map((stroke: [number, number][]) => stroke.map(([X, Y]) => ({ X: X + startPoint.X - 100, Y: Y + startPoint.Y - 100 }))); + this._addToDocFunc(controlPts, this._alpha); + } else { + const controlPts = (parsedPts as [number, number][]).map(([X, Y]) => ({ X: X + startPoint.X - 100, Y: Y + startPoint.Y - 100 })); + this._addToDocFunc([controlPts], this._alpha); + } } catch (err) { - console.error('Incompatible GPT output type'); + console.error('Error likely from bad GPT output type'); } } catch (err) { console.error('GPT call failed', err); @@ -94,6 +88,19 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { this.setIsLoading(false); this.setUserInput(''); + this.hideSmartDrawHandler(); + }; + + changeDrawingType = () => { + if (this._drawingTypeIcon === 'star') { + this._drawingTypeIcon = 'splotch'; + this._drawingTypeToolTip = 'Create Rounded Drawing'; + this._alpha = 0.2; + } else { + this._drawingTypeIcon = 'star'; + this._drawingTypeToolTip = 'Create Geometric Drawing'; + this._alpha = 0; + } }; render() { @@ -110,7 +117,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { color: SettingsManager.userColor, }}>
- } color={MarqueeOptionsMenu.Instance.userColor} style={{ width: '19px' }} /> + } color={MarqueeOptionsMenu.Instance.userColor} style={{ width: '19px' }} /> { }} placeholder="Enter item to draw" /> + } color={MarqueeOptionsMenu.Instance.userColor} style={{ width: '14px' }} onClick={this.changeDrawingType} /> + {/* } + color={MarqueeOptionsMenu.Instance.userColor} + style={{ width: '14px' }} + onClick={() => { + this._alpha = 0; + }} + /> */}
-
- {/* {this._labelGroups.map(group => { - return ( -
-

{group}

- { - this.removeLabel(group); - }} - icon={'x'} - color={MarqueeOptionsMenu.Instance.userColor} - style={{ width: '19px' }} - /> -
- ); - })} */}
); -- cgit v1.2.3-70-g09d2 From cf539fc086c27f53cec764202d3212a996113638 Mon Sep 17 00:00:00 2001 From: geireann Date: Mon, 17 Jun 2024 11:40:55 -0400 Subject: updated multitoggle eraser to always toggle --- package-lock.json | 8 ++++---- package.json | 2 +- src/client/views/global/globalScripts.ts | 18 +++++++++++------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 85802cd19..7c531e3a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -68,7 +68,7 @@ "body-parser": "^1.20.2", "bootstrap": "^5.3.2", "brotli": "^1.3.3", - "browndash-components": "^0.1.44", + "browndash-components": "^0.1.45", "browser-assert": "^1.2.1", "bson": "^6.2.0", "canvas": "^2.11.2", @@ -11401,9 +11401,9 @@ } }, "node_modules/browndash-components": { - "version": "0.1.44", - "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.1.44.tgz", - "integrity": "sha512-+QYEHDqd3iauijdKiVA0jXGFkOMEKn+qb7Y2iG+VK0xAh8Fho3rAUoSMv6snfg+kMc1oMGhACzJa5XauTtvguQ==", + "version": "0.1.45", + "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.1.45.tgz", + "integrity": "sha512-A2/3SikcA1kntY8jajwWJjnRGVRP9+DheaOMh9fAdgiQrdMZVMty+nUasbXk9HjyjkMfAUAkGvCR+SS28QL/zA==", "dependencies": { "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", diff --git a/package.json b/package.json index fe1ad8be7..cd5e34e86 100644 --- a/package.json +++ b/package.json @@ -153,7 +153,7 @@ "body-parser": "^1.20.2", "bootstrap": "^5.3.2", "brotli": "^1.3.3", - "browndash-components": "^0.1.44", + "browndash-components": "^0.1.45", "browser-assert": "^1.2.1", "bson": "^6.2.0", "canvas": "^2.11.2", diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 7730ed385..a985986d6 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -450,15 +450,19 @@ function setActiveTool(tool: InkTool | Gestures, keepPrim: boolean, checkResult? GestureOverlay.Instance.InkShape = tool as Gestures; } } else if (tool) { - if ([InkTool.StrokeEraser, InkTool.RadiusEraser, InkTool.SegmentEraser].includes(tool as any)) { - Doc.UserDoc().activeEraserTool = tool; - } - // pen or eraser - if (Doc.ActiveTool === tool && !GestureOverlay.Instance.InkShape && !keepPrim) { + if (Doc.UserDoc().ActiveTool === tool) { Doc.ActiveTool = InkTool.None; } else { - Doc.ActiveTool = tool as any; - GestureOverlay.Instance.InkShape = undefined; + if ([InkTool.StrokeEraser, InkTool.RadiusEraser, InkTool.SegmentEraser].includes(tool as any)) { + Doc.UserDoc().activeEraserTool = tool; + } + // pen or eraser + if (Doc.ActiveTool === tool && !GestureOverlay.Instance.InkShape && !keepPrim) { + Doc.ActiveTool = InkTool.None; + } else { + Doc.ActiveTool = tool as any; + GestureOverlay.Instance.InkShape = undefined; + } } } else { Doc.ActiveTool = InkTool.None; -- cgit v1.2.3-70-g09d2 From bd64bbd29a38ae4979b2165d1fa9b9c76c2600d5 Mon Sep 17 00:00:00 2001 From: eleanor-park Date: Tue, 18 Jun 2024 14:10:40 -0400 Subject: svg to bezier conversion --- package-lock.json | 73 +++++++++++++ package.json | 1 + src/client/apis/gpt/GPT.ts | 3 +- src/client/util/CurrentUserUtils.ts | 2 +- src/client/util/bezierFit.ts | 116 +++++++++++++++++++++ src/client/views/GestureOverlay.tsx | 28 ++--- src/client/views/MainView.tsx | 2 + .../collectionFreeForm/CollectionFreeFormView.tsx | 8 +- .../collectionFreeForm/SmartDrawHandler.tsx | 51 ++++++--- 9 files changed, 252 insertions(+), 32 deletions(-) diff --git a/package-lock.json b/package-lock.json index b143dc5c1..30b2c9124 100644 --- a/package-lock.json +++ b/package-lock.json @@ -219,6 +219,7 @@ "stream-browserify": "^3.0.0", "styled-components": "^6.1.1", "supercluster": "^8.0.1", + "svgson": "^5.3.1", "textarea-caret": "^3.1.0", "tough-cookie": "^4.1.3", "tslint": "^6.1.3", @@ -16641,6 +16642,29 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, + "node_modules/deep-rename-keys": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/deep-rename-keys/-/deep-rename-keys-0.2.1.tgz", + "integrity": "sha512-RHd9ABw4Fvk+gYDWqwOftG849x0bYOySl/RgX0tLI9i27ZIeSO91mLZJEp7oPHOMFqHvpgu21YptmDt0FYD/0A==", + "dependencies": { + "kind-of": "^3.0.2", + "rename-keys": "^1.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-rename-keys/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -22370,6 +22394,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -36944,6 +36973,14 @@ "@types/unist": "*" } }, + "node_modules/rename-keys": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rename-keys/-/rename-keys-1.2.0.tgz", + "integrity": "sha512-U7XpAktpbSgHTRSNRrjKSrjYkZKuhUukfoBlXWXUExCAqhzh1TU3BDRAfJmarcl5voKS+pbKU9MvyLWKZ4UEEg==", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/renderkid": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", @@ -38917,6 +38954,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svgson": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/svgson/-/svgson-5.3.1.tgz", + "integrity": "sha512-qdPgvUNWb40gWktBJnbJRelWcPzkLed/ShhnRsjbayXz8OtdPOzbil9jtiZdrYvSDumAz/VNQr6JaNfPx/gvPA==", + "dependencies": { + "deep-rename-keys": "^0.2.1", + "xml-reader": "2.4.3" + } + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -41766,6 +41812,19 @@ "xtend": "^4.0.0" } }, + "node_modules/xml-lexer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/xml-lexer/-/xml-lexer-0.2.2.tgz", + "integrity": "sha512-G0i98epIwiUEiKmMcavmVdhtymW+pCAohMRgybyIME9ygfVu8QheIi+YoQh3ngiThsT0SQzJT4R0sKDEv8Ou0w==", + "dependencies": { + "eventemitter3": "^2.0.0" + } + }, + "node_modules/xml-lexer/node_modules/eventemitter3": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", + "integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==" + }, "node_modules/xml-name-validator": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", @@ -41780,6 +41839,20 @@ "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==" }, + "node_modules/xml-reader": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/xml-reader/-/xml-reader-2.4.3.tgz", + "integrity": "sha512-xWldrIxjeAMAu6+HSf9t50ot1uL5M+BtOidRCWHXIeewvSeIpscWCsp4Zxjk8kHHhdqFBrfK8U0EJeCcnyQ/gA==", + "dependencies": { + "eventemitter3": "^2.0.0", + "xml-lexer": "^0.2.2" + } + }, + "node_modules/xml-reader/node_modules/eventemitter3": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", + "integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==" + }, "node_modules/xml2js": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", diff --git a/package.json b/package.json index 52f627b63..0b1717721 100644 --- a/package.json +++ b/package.json @@ -304,6 +304,7 @@ "stream-browserify": "^3.0.0", "styled-components": "^6.1.1", "supercluster": "^8.0.1", + "svgson": "^5.3.1", "textarea-caret": "^3.1.0", "tough-cookie": "^4.1.3", "tslint": "^6.1.3", diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 0c993680e..06c562562 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -58,7 +58,8 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { model: 'gpt-4o', maxTokens: 1024, temp: 0.5, - prompt: 'I would like you to generate me vector art with Bezier curves. Given a prompt, generate a sequence of cubic Bezier coordinates in the range of 0 to 200 (unless specified larger/smaller) that creates a line drawing of the object. Respond only with the coordinates', + prompt: 'Given an item, generate a detailed line drawing representation of it. The drawing should be in SVG format with no additional text or comments. For path coordinates, make sure you format with a comma between numbers, like M100,200 C150,250 etc. The only supported commands are line, ellipse, circle, rect, and path with M, Q, C, and L so only use those.', + // prompt: 'I would like you to generate me vector art with Bezier curves. Given a prompt, generate a sequence of cubic Bezier coordinates in the range of 0 to 200 (unless specified larger/smaller) that creates a line drawing of the object. Format your response like this: M (100,30) C (75,10) (25,10) (50,50) C (25,75) (10,125) (50,150) C (25,75) (10,125) (50,150) and give no additional text. If a disconnected stroke is required, repeat that pattern with a new M marker', }, }; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index b6a7cacba..141695d86 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -743,7 +743,7 @@ pie title Minerals in my tap water { title: "Square", toolTip: "Square (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "square", toolType: Gestures.Rectangle, scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} }, { title: "Line", toolTip: "Line (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "minus", toolType: Gestures.Line, scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} }, { title: "Mask", toolTip: "Mask", btnType: ButtonType.ToggleButton, icon: "user-circle",toolType: "inkMask", scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"IsNoviceMode()" } }, - { title: "Labels", toolTip: "Lab els", btnType: ButtonType.ToggleButton, icon: "text-width", toolType: "labels", scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}, }, + { title: "Labels", toolTip: "Labels", btnType: ButtonType.ToggleButton, icon: "text-width", toolType: "labels", scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}, }, { title: "Width", toolTip: "Stroke width", btnType: ButtonType.NumberSliderButton, toolType: "strokeWidth", ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, numBtnMin: 1}, { title: "Ink", toolTip: "Stroke color", btnType: ButtonType.ColorButton, icon: "pen", toolType: "strokeColor", ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'} }, { title: "Smart Draw", toolTip: "Draw with GPT", btnType: ButtonType.ToggleButton, icon: "user-pen", toolType: "smartdraw", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}'}, funcs: {hidden: "IsNoviceMode()"}}, diff --git a/src/client/util/bezierFit.ts b/src/client/util/bezierFit.ts index fbc2bb7cd..f5696afaf 100644 --- a/src/client/util/bezierFit.ts +++ b/src/client/util/bezierFit.ts @@ -2,8 +2,18 @@ /* eslint-disable prefer-destructuring */ /* eslint-disable no-param-reassign */ /* eslint-disable camelcase */ +import e from 'cors'; import { Point } from '../../pen-gestures/ndollar'; +export enum SVGType { + Rect = 'rect', + Path = 'path', + Circle = 'circle', + Ellipse = 'ellipse', + Line = 'line', + Polygon = 'polygon', +} + class SmartRect { minx: number = 0; miny: number = 0; @@ -616,6 +626,112 @@ export function GenerateControlPoints(coordinates: Point[], alpha = 0.1) { return [...firstEnd, ...points, ...lastEnd]; } +export function SVGToBezier(name: SVGType, attributes: any): Point[] { + console.log('in svg to bezier', name, attributes); + switch (name) { + case 'line': + const x1 = parseInt(attributes.x1); + const x2 = parseInt(attributes.x2); + const y1 = parseInt(attributes.y1); + const y2 = parseInt(attributes.y2); + return [ + { X: x1, Y: y1 }, + { X: x1, Y: y1 }, + { X: x2, Y: y2 }, + { X: x2, Y: y2 }, + ]; + case 'circle': + case 'ellipse': + const c = 0.551915024494; + const centerX = parseInt(attributes.cx); + const centerY = parseInt(attributes.cy); + const radiusX = parseInt(attributes.rx) || parseInt(attributes.r); + const radiusY = parseInt(attributes.ry) || parseInt(attributes.r); + return [ + { X: centerX, Y: centerY + radiusY }, + { X: centerX + c * radiusX, Y: centerY + radiusY }, + { X: centerX + radiusX, Y: centerY + c * radiusY }, + { X: centerX + radiusX, Y: centerY }, + { X: centerX + radiusX, Y: centerY }, + { X: centerX + radiusX, Y: centerY - c * radiusY }, + { X: centerX + c * radiusX, Y: centerY - radiusY }, + { X: centerX, Y: centerY - radiusY }, + { X: centerX, Y: centerY - radiusY }, + { X: centerX - c * radiusX, Y: centerY - radiusY }, + { X: centerX - radiusX, Y: centerY - c * radiusY }, + { X: centerX - radiusX, Y: centerY }, + { X: centerX - radiusX, Y: centerY }, + { X: centerX - radiusX, Y: centerY + c * radiusY }, + { X: centerX - c * radiusX, Y: centerY + radiusY }, + { X: centerX, Y: centerY + radiusY }, + ]; + case 'rect': + const x = parseInt(attributes.x); + const y = parseInt(attributes.y); + const width = parseInt(attributes.width); + const height = parseInt(attributes.height); + return [ + { X: x, Y: y }, + { X: x, Y: y }, + { X: x + width, Y: y }, + { X: x + width, Y: y }, + { X: x + width, Y: y }, + { X: x + width, Y: y }, + { X: x + width, Y: y + height }, + { X: x + width, Y: y + height }, + { X: x + width, Y: y + height }, + { X: x + width, Y: y + height }, + { X: x, Y: y + height }, + { X: x, Y: y + height }, + { X: x, Y: y + height }, + { X: x, Y: y + height }, + { X: x, Y: y }, + { X: x, Y: y }, + ]; + case 'path': + const coordList: Point[] = []; + const startPt = attributes.d.match(/M(-?\d+\.?\d*),(-?\d+\.?\d*)/); + coordList.push({ X: parseInt(startPt[1]), Y: parseInt(startPt[2]) }); + const matches: RegExpMatchArray[] = Array.from( + attributes.d.matchAll(/Q(-?\d+\.?\d*),(-?\d+\.?\d*) (-?\d+\.?\d*),(-?\d+\.?\d*)|C(-?\d+\.?\d*),(-?\d+\.?\d*) (-?\d+\.?\d*),(-?\d+\.?\d*) (-?\d+\.?\d*),(-?\d+\.?\d*)|L(-?\d+\.?\d*),(-?\d+\.?\d*)/g) + ); + let lastPt: Point; + matches.forEach(match => { + if (match[0].startsWith('Q')) { + coordList.push({ X: parseInt(match[1]), Y: parseInt(match[2]) }); + coordList.push({ X: parseInt(match[1]), Y: parseInt(match[2]) }); + coordList.push({ X: parseInt(match[3]), Y: parseInt(match[4]) }); + coordList.push({ X: parseInt(match[3]), Y: parseInt(match[4]) }); + lastPt = { X: parseInt(match[3]), Y: parseInt(match[4]) }; + } else if (match[0].startsWith('C')) { + coordList.push({ X: parseInt(match[5]), Y: parseInt(match[6]) }); + coordList.push({ X: parseInt(match[7]), Y: parseInt(match[8]) }); + coordList.push({ X: parseInt(match[9]), Y: parseInt(match[10]) }); + coordList.push({ X: parseInt(match[9]), Y: parseInt(match[10]) }); + lastPt = { X: parseInt(match[9]), Y: parseInt(match[10]) }; + } else { + coordList.push(lastPt || { X: parseInt(startPt[1]), Y: parseInt(startPt[2]) }); + coordList.push({ X: parseInt(match[11]), Y: parseInt(match[12]) }); + coordList.push({ X: parseInt(match[11]), Y: parseInt(match[12]) }); + coordList.push({ X: parseInt(match[11]), Y: parseInt(match[12]) }); + lastPt = { X: parseInt(match[11]), Y: parseInt(match[12]) }; + } + }); + const hasZ = attributes.d.match(/Z/); + if (hasZ) { + coordList.push(lastPt); + coordList.push({ X: parseInt(startPt[1]), Y: parseInt(startPt[2]) }); + coordList.push({ X: parseInt(startPt[1]), Y: parseInt(startPt[2]) }); + } else { + coordList.pop(); + } + return coordList; + case 'polygon': + default: + return []; + } +} + /* static double GetTValueFromSValue (const BezierRep &parent, double t, double endT, bool left, double influenceDistance, double &excess) { double dist = 0; diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 2f26bdaef..dc6edf81d 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -242,15 +242,15 @@ export class GestureOverlay extends ObservableReactComponent { + diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index a27ac2a0c..93b63ac4c 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1267,17 +1267,17 @@ export class CollectionFreeFormView extends CollectionSubView { console.log(strokeList.length); strokeList.forEach(inkData => { // const points: InkData = FitCurve(inkData, 20) as InkData; - const allPts = GenerateControlPoints(inkData, alpha); - const bounds = InkField.getBounds(allPts); + // const allPts = GenerateControlPoints(inkData, alpha); + const bounds = InkField.getBounds(inkData); const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; const inkDoc = Docs.Create.InkDocument( - allPts, + inkData, { title: 'stroke', x: B.x - inkWidth / 2, y: B.y - inkWidth / 2, diff --git a/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx b/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx index 4c2e78e31..956a8d7e9 100644 --- a/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx +++ b/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx @@ -12,6 +12,8 @@ import './ImageLabelHandler.scss'; import { gptAPICall, GPTCallType } from '../../../apis/gpt/GPT'; import { InkData } from '../../../../fields/InkField'; import { ButtonType } from '../../nodes/FontIconBox/FontIconBox'; +import { SVGToBezier } from '../../../util/bezierFit'; +const { parse, stringify } = require('svgson'); @observer export class SmartDrawHandler extends ObservableReactComponent<{}> { @@ -69,19 +71,44 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { return; } console.log('GPT response:', res); - const simplifiedRes: string = res.replace(/[^\d\[\],]/g, ''); - try { - const parsedPts = JSON.parse(simplifiedRes); - if (parsedPts[0][0][0]) { - const controlPts = (parsedPts as [number, number][][]).map((stroke: [number, number][]) => stroke.map(([X, Y]) => ({ X: X + startPoint.X - 100, Y: Y + startPoint.Y - 100 }))); - this._addToDocFunc(controlPts, this._alpha); - } else { - const controlPts = (parsedPts as [number, number][]).map(([X, Y]) => ({ X: X + startPoint.X - 100, Y: Y + startPoint.Y - 100 })); - this._addToDocFunc([controlPts], this._alpha); - } - } catch (err) { - console.error('Error likely from bad GPT output type'); + const svg = res.match(/]*>([\s\S]*?)<\/svg>/g); + console.log('svg', svg); + if (svg) { + const svgObject = await parse(svg[0]); + console.log('svg object', svgObject); + const svgStrokes: any = svgObject.children; + const beziers: InkData[] = []; + svgStrokes.forEach((stroke: any) => { + const convertedBezier: InkData = SVGToBezier(stroke.name, stroke.attributes); + beziers.push( + convertedBezier.map(point => { + return { X: point.X + startPoint.X, Y: point.Y + startPoint.Y }; + }) + ); + }); + this._addToDocFunc(beziers); } + + // const strokes = res.trim().split(/\s*(?=\s*M)/); // prettier-ignore + // const parsedSegments: InkData[] = []; + // console.log('strokes', strokes); + // strokes.forEach(stroke => { + // stroke = stroke.replace(/C\s*\((\d+,\d+)\)\s*\((\d+,\d+)\)\s*\((\d+,\d+)\)/g, (c, p1, p2, p3) => { + // return `C (${p1}) (${p2}) (${p3}) (${p3})`; + // }); + // const coordStrings = stroke.match(/(\d+,\d+)/g); + // const coords: InkData = []; + // if (coordStrings) { + // coordStrings.forEach(coord => { + // const xy = coord.split(','); + // coords.push({ X: parseInt(xy[0]), Y: parseInt(xy[1]) }); + // }); + // coords.pop(); + // parsedSegments.push(coords); + // } + // console.log('coords', coords); + // }); + // this._addToDocFunc(parsedSegments); } catch (err) { console.error('GPT call failed', err); } -- cgit v1.2.3-70-g09d2 From 3d14f06ad1297a6adc851945804211efb9dff7ff Mon Sep 17 00:00:00 2001 From: eleanor-park Date: Thu, 20 Jun 2024 16:42:44 -0400 Subject: user customization added --- src/client/apis/gpt/GPT.ts | 2 +- src/client/views/MainView.tsx | 1 + .../collectionFreeForm/CollectionFreeFormView.tsx | 14 +- .../collectionFreeForm/ImageLabelHandler.scss | 14 ++ .../collectionFreeForm/SmartDrawHandler.tsx | 261 +++++++++++++++------ 5 files changed, 209 insertions(+), 83 deletions(-) diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 06c562562..b5f4c7fe9 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -58,7 +58,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { model: 'gpt-4o', maxTokens: 1024, temp: 0.5, - prompt: 'Given an item, generate a detailed line drawing representation of it. The drawing should be in SVG format with no additional text or comments. For path coordinates, make sure you format with a comma between numbers, like M100,200 C150,250 etc. The only supported commands are line, ellipse, circle, rect, and path with M, Q, C, and L so only use those.', + prompt: 'Given an item, a level of complexity from 1-10, and a size in pixels, generate a detailed and colored line drawing representation of it. More complex drawings will have much more detail and strokes. The drawing should be in SVG format with no additional text or comments. For path coordinates, make sure you format with a comma between numbers, like M100,200 C150,250 etc. The only supported commands are line, ellipse, circle, rect, and path with M, Q, C, and L so only use those.', // prompt: 'I would like you to generate me vector art with Bezier curves. Given a prompt, generate a sequence of cubic Bezier coordinates in the range of 0 to 200 (unless specified larger/smaller) that creates a line drawing of the object. Format your response like this: M (100,30) C (75,10) (25,10) (50,50) C (25,75) (10,125) (50,150) C (25,75) (10,125) (50,150) and give no additional text. If a disconnected stroke is required, repeat that pattern with a new M marker', }, }; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index cbc337860..67b875ecb 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -442,6 +442,7 @@ export class MainView extends ObservableReactComponent<{}> { fa.faEyeDropper, fa.faPaintRoller, fa.faBars, + fa.faBarsStaggered, fa.faBrush, fa.faShapes, fa.faEllipsisH, diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 93b63ac4c..b8257ff31 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1268,23 +1268,25 @@ export class CollectionFreeFormView extends CollectionSubView { - console.log(strokeList.length); - strokeList.forEach(inkData => { + createInkStrokes = (strokeData: [InkData, string, string][]) => { + strokeData.forEach((stroke: [InkData, string, string]) => { // const points: InkData = FitCurve(inkData, 20) as InkData; // const allPts = GenerateControlPoints(inkData, alpha); - const bounds = InkField.getBounds(inkData); + const bounds = InkField.getBounds(stroke[0]); const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; const inkDoc = Docs.Create.InkDocument( - inkData, + stroke[0], { title: 'stroke', x: B.x - inkWidth / 2, y: B.y - inkWidth / 2, _width: B.width + inkWidth, _height: B.height + inkWidth, stroke_showLabel: BoolCast(Doc.UserDoc().activeInkHideTextLabels)}, // prettier-ignore - inkWidth + inkWidth, + stroke[1], + undefined, + stroke[2] === 'none' ? undefined : stroke[2] ); this.addDocument(inkDoc); }); diff --git a/src/client/views/collections/collectionFreeForm/ImageLabelHandler.scss b/src/client/views/collections/collectionFreeForm/ImageLabelHandler.scss index e7413bf8e..9b8727e1a 100644 --- a/src/client/views/collections/collectionFreeForm/ImageLabelHandler.scss +++ b/src/client/views/collections/collectionFreeForm/ImageLabelHandler.scss @@ -42,3 +42,17 @@ } } } + +.complexity-slider { + width: 50%; /* Full-width */ + height: 25px; /* Specified height */ + background: #d3d3d3; /* Grey background */ + outline: none; /* Remove outline */ + opacity: 0.7; /* Set transparency (for mouse-over effects on hover) */ + -webkit-transition: 0.2s; /* 0.2 seconds transition on hover */ + transition: opacity 0.2s; + + :hover { + opacity: 1; /* Fully shown on mouse-over */ + } +} diff --git a/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx b/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx index 956a8d7e9..edb814172 100644 --- a/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx +++ b/src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx @@ -4,16 +4,20 @@ import { observer } from 'mobx-react'; import React from 'react'; import { SettingsManager } from '../../../util/SettingsManager'; import { ObservableReactComponent } from '../../ObservableReactComponent'; -import { Button, IconButton } from 'browndash-components'; +import { Button, IconButton, Size } from 'browndash-components'; import ReactLoading from 'react-loading'; import { AiOutlineSend } from 'react-icons/ai'; -import { MarqueeOptionsMenu } from './MarqueeOptionsMenu'; import './ImageLabelHandler.scss'; import { gptAPICall, GPTCallType } from '../../../apis/gpt/GPT'; import { InkData } from '../../../../fields/InkField'; -import { ButtonType } from '../../nodes/FontIconBox/FontIconBox'; import { SVGToBezier } from '../../../util/bezierFit'; -const { parse, stringify } = require('svgson'); +const { parse } = require('svgson'); +import { Slider, Switch } from '@mui/material'; +import { IconProp } from '@fortawesome/fontawesome-svg-core'; +import { Flex } from '@adobe/react-spectrum'; +import { Row } from 'react-aria-components'; +import { UndoManager } from '../../../util/UndoManager'; +import e from 'cors'; @observer export class SmartDrawHandler extends ObservableReactComponent<{}> { @@ -25,11 +29,15 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { @observable private _yRelativeToTop: boolean = true; @observable private _isLoading: boolean = false; @observable private _userInput: string = ''; - @observable private _drawingTypeToolTip = 'Create Geometric Drawing'; - @observable private _drawingTypeIcon: 'star' | 'splotch' = 'star'; - @observable private _alpha: number | undefined = undefined; // number between 0 and 1 that determines how rounded a drawing will be - // @observable public strokes: InkData[] = []; - private _addToDocFunc: (strokeList: InkData[], alpha?: number) => void = () => {}; + @observable private _showOptions: boolean = false; + @observable private _menuIcon: string = 'caret-right'; + @observable private _complexity: number = 5; + @observable private _size: number = 300; + @observable private _autoColor: boolean = true; + @observable private _showRegenerate: boolean = false; + private _addToDocFunc: (strokeList: [InkData, string, string][]) => void = () => {}; + private _lastX: number = 0; + private _lastY: number = 0; constructor(props: any) { super(props); @@ -37,97 +45,82 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { SmartDrawHandler.Instance = this; } - @action - setIsLoading = (isLoading: boolean) => { - this._isLoading = isLoading; - }; - @action setUserInput = (input: string) => { this._userInput = input; }; @action - displaySmartDrawHandler = (x: number, y: number, addToDoc: (strokeList: InkData[], alpha?: number) => void) => { + displaySmartDrawHandler = (x: number, y: number, addToDoc: (strokeData: [InkData, string, string][]) => void) => { this._pageX = x; this._pageY = y; this._display = true; this._addToDocFunc = addToDoc; }; - @action hideSmartDrawHandler = () => { + this._showRegenerate = false; this._display = false; + this._isLoading = false; + this._showOptions = false; + this._menuIcon = 'caret-right'; + }; + + hideRegenerate = () => { + this._showRegenerate = false; + this._userInput = ''; + this._complexity = 5; + this._size = 300; + this._autoColor = true; + this._isLoading = false; + }; + + toggleMenu = () => { + this._showOptions = !this._showOptions; + this._menuIcon === 'caret-right' ? (this._menuIcon = 'caret-down') : (this._menuIcon = 'caret-right'); }; @action - drawWithGPT = async (startPoint: { X: number; Y: number }, input: string) => { - console.log('start point is', startPoint); - this.setIsLoading(true); + drawWithGPT = async (e: React.MouseEvent, startPoint: { X: number; Y: number }, input: string, regenerate: boolean = false) => { + if (this._userInput === '') return; + e.stopPropagation(); + this._lastX = startPoint.X; + this._lastY = startPoint.Y; + this._isLoading = true; + this._showOptions = false; try { - const res = await gptAPICall(input, GPTCallType.DRAW); + const res = await gptAPICall(`"${input}", "${this._complexity}", "${this._size}"`, GPTCallType.DRAW); if (!res) { console.error('GPT call failed'); return; } - console.log('GPT response:', res); const svg = res.match(/]*>([\s\S]*?)<\/svg>/g); - console.log('svg', svg); if (svg) { const svgObject = await parse(svg[0]); - console.log('svg object', svgObject); const svgStrokes: any = svgObject.children; - const beziers: InkData[] = []; - svgStrokes.forEach((stroke: any) => { - const convertedBezier: InkData = SVGToBezier(stroke.name, stroke.attributes); - beziers.push( + const strokeData: [InkData, string, string][] = []; + svgStrokes.forEach((child: any) => { + const convertedBezier: InkData = SVGToBezier(child.name, child.attributes); + strokeData.push([ convertedBezier.map(point => { - return { X: point.X + startPoint.X, Y: point.Y + startPoint.Y }; - }) - ); + return { X: point.X + startPoint.X - this._size / 1.5, Y: point.Y + startPoint.Y - this._size / 2 }; + }), + this._autoColor ? child.attributes.stroke : undefined, + this._autoColor ? child.attributes.fill : undefined, + ]); }); - this._addToDocFunc(beziers); + if (regenerate) UndoManager.Undo(); + this._addToDocFunc(strokeData); } - - // const strokes = res.trim().split(/\s*(?=\s*M)/); // prettier-ignore - // const parsedSegments: InkData[] = []; - // console.log('strokes', strokes); - // strokes.forEach(stroke => { - // stroke = stroke.replace(/C\s*\((\d+,\d+)\)\s*\((\d+,\d+)\)\s*\((\d+,\d+)\)/g, (c, p1, p2, p3) => { - // return `C (${p1}) (${p2}) (${p3}) (${p3})`; - // }); - // const coordStrings = stroke.match(/(\d+,\d+)/g); - // const coords: InkData = []; - // if (coordStrings) { - // coordStrings.forEach(coord => { - // const xy = coord.split(','); - // coords.push({ X: parseInt(xy[0]), Y: parseInt(xy[1]) }); - // }); - // coords.pop(); - // parsedSegments.push(coords); - // } - // console.log('coords', coords); - // }); - // this._addToDocFunc(parsedSegments); } catch (err) { console.error('GPT call failed', err); } - - this.setIsLoading(false); - this.setUserInput(''); this.hideSmartDrawHandler(); + this._showRegenerate = true; }; - changeDrawingType = () => { - if (this._drawingTypeIcon === 'star') { - this._drawingTypeIcon = 'splotch'; - this._drawingTypeToolTip = 'Create Rounded Drawing'; - this._alpha = 0.2; - } else { - this._drawingTypeIcon = 'star'; - this._drawingTypeToolTip = 'Create Geometric Drawing'; - this._alpha = 0; - } + regenerate = (e: React.MouseEvent) => { + this.drawWithGPT(e, { X: this._lastX, Y: this._lastY }, `Regenerate the item "${this._userInput}"`, true); }; render() { @@ -144,7 +137,16 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { color: SettingsManager.userColor, }}>
- } color={MarqueeOptionsMenu.Instance.userColor} style={{ width: '19px' }} /> + { + this.hideSmartDrawHandler(); + this.hideRegenerate(); + }} + icon={} + color={SettingsManager.userColor} + style={{ width: '19px' }} + /> { }} placeholder="Enter item to draw" /> - } color={MarqueeOptionsMenu.Instance.userColor} style={{ width: '14px' }} onClick={this.changeDrawingType} /> - {/* } - color={MarqueeOptionsMenu.Instance.userColor} + } + color={SettingsManager.userColor} style={{ width: '14px' }} onClick={() => { - this._alpha = 0; + this._showOptions = !this._showOptions; }} - /> */} + />
+ {this._showOptions && ( + <> +
+
+ Auto color + (this._autoColor = !this._autoColor)} + /> +
+
+ Complexity + { + this._complexity = val as number; + }} + valueLabelDisplay="auto" + /> +
+
+ Size (in pixels) + { + this._size = val as number; + }} + valueLabelDisplay="auto" + /> +
+
+ + )} + + ); + } else if (this._showRegenerate) { + return ( +
+
+ } color={SettingsManager.userColor} style={{ width: '19px' }} /> + : } + color={SettingsManager.userColor} onClick={e => { - this.drawWithGPT({ X: e.clientX, Y: e.clientY }, this._userInput); + this.regenerate(e); }} />
-- cgit v1.2.3-70-g09d2 From 50980b834cc41b8048d3e04c5244c6bce652f788 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 21 Jun 2024 11:37:58 -0400 Subject: added renderedPixelDimensions to imageBox --- src/client/util/request-image-size.ts | 1 + src/client/views/nodes/ImageBox.tsx | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/client/util/request-image-size.ts b/src/client/util/request-image-size.ts index 0f98a2710..48cb6e3a5 100644 --- a/src/client/util/request-image-size.ts +++ b/src/client/util/request-image-size.ts @@ -54,6 +54,7 @@ module.exports = function requestImageSize(options: any) { } } catch (err) { /* empty */ + console.log("Error: ", err) } }); diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index e4b3a1b9b..68c313480 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -448,6 +448,11 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { }; focus = (anchor: Doc, options: FocusViewOptions) => (anchor.type === DocumentType.CONFIG ? undefined : this._ffref.current?.focus(anchor, options)); + renderedPixelDimensions = async () => { + const { nativeWidth: width, nativeHeight: height } = await Networking.PostToServer('/inspectImage', { source: this.paths[0] }); + return { width, height }; + }; + savedAnnotations = () => this._savedAnnotations; render() { TraceMobx(); -- cgit v1.2.3-70-g09d2 From 33f416349c00bdec405455340befb0ca85b2fee4 Mon Sep 17 00:00:00 2001 From: eleanor-park Date: Mon, 1 Jul 2024 13:54:07 -0400 Subject: weird error? --- src/client/apis/gpt/GPT.ts | 7 +- src/client/views/LightboxView.scss | 24 +- src/client/views/LightboxView.tsx | 7 + src/client/views/MainView.tsx | 2964 +++++++++++++------- .../collectionFreeForm/CollectionFreeFormView.tsx | 107 +- .../collections/collectionFreeForm/MarqueeView.tsx | 2 + .../collectionFreeForm/SmartDrawHandler.tsx | 295 -- src/client/views/nodes/PDFBox.scss | 16 +- src/client/views/nodes/PDFBox.tsx | 37 +- src/client/views/smartdraw/DrawingPalette.scss | 11 + src/client/views/smartdraw/DrawingPalette.tsx | 89 + src/client/views/smartdraw/SmartDrawHandler.tsx | 407 +++ src/fields/Doc.ts | 1 + 13 files changed, 2563 insertions(+), 1404 deletions(-) delete mode 100644 src/client/views/collections/collectionFreeForm/SmartDrawHandler.tsx create mode 100644 src/client/views/smartdraw/DrawingPalette.scss create mode 100644 src/client/views/smartdraw/DrawingPalette.tsx create mode 100644 src/client/views/smartdraw/SmartDrawHandler.tsx diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index b5f4c7fe9..a7bd05a21 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -58,8 +58,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { model: 'gpt-4o', maxTokens: 1024, temp: 0.5, - prompt: 'Given an item, a level of complexity from 1-10, and a size in pixels, generate a detailed and colored line drawing representation of it. More complex drawings will have much more detail and strokes. The drawing should be in SVG format with no additional text or comments. For path coordinates, make sure you format with a comma between numbers, like M100,200 C150,250 etc. The only supported commands are line, ellipse, circle, rect, and path with M, Q, C, and L so only use those.', - // prompt: 'I would like you to generate me vector art with Bezier curves. Given a prompt, generate a sequence of cubic Bezier coordinates in the range of 0 to 200 (unless specified larger/smaller) that creates a line drawing of the object. Format your response like this: M (100,30) C (75,10) (25,10) (50,50) C (25,75) (10,125) (50,150) C (25,75) (10,125) (50,150) and give no additional text. If a disconnected stroke is required, repeat that pattern with a new M marker', + prompt: 'Given an item, a level of complexity from 1-10, and a size in pixels, generate a detailed and colored line drawing representation of it. Make sure every element has the stroke field filled out. More complex drawings will have much more detail and strokes. The drawing should be in SVG format with no additional text or comments. For path coordinates, make sure you format with a comma between numbers, like M100,200 C150,250 etc. The only supported commands are line, ellipse, circle, rect, and path with M, Q, C, and L so only use those.', }, }; @@ -71,10 +70,10 @@ let lastResp = ''; * @param inputText Text to process * @returns AI Output */ -const gptAPICall = async (inputTextIn: string, callType: GPTCallType, prompt?: any) => { +const gptAPICall = async (inputTextIn: string, callType: GPTCallType, prompt?: any, dontCache?: boolean) => { const inputText = [GPTCallType.SUMMARY, GPTCallType.FLASHCARD, GPTCallType.QUIZ].includes(callType) ? inputTextIn + '.' : inputTextIn; const opts: GPTCallOpts = callTypeMap[callType]; - if (lastCall === inputText) return lastResp; + if (lastCall === inputText && dontCache !== true) return lastResp; try { lastCall = inputText; diff --git a/src/client/views/LightboxView.scss b/src/client/views/LightboxView.scss index 6da5c0338..3e65843df 100644 --- a/src/client/views/LightboxView.scss +++ b/src/client/views/LightboxView.scss @@ -1,7 +1,7 @@ .lightboxView-navBtn { margin: auto; position: absolute; - right: 10; + right: 19; top: 10; background: transparent; border-radius: 8; @@ -16,7 +16,7 @@ .lightboxView-tabBtn { margin: auto; position: absolute; - right: 45; + right: 54; top: 10; background: transparent; border-radius: 8; @@ -28,10 +28,26 @@ opacity: 1; } } +.lightboxView-paletteBtn { + margin: auto; + position: absolute; + right: 89; + top: 10; + background: transparent; + border-radius: 8; + opacity: 0.7; + width: 25; + flex-direction: column; + display: flex; + &:hover { + opacity: 1; + } +} + .lightboxView-penBtn { margin: auto; position: absolute; - right: 80; + right: 124; top: 10; background: transparent; border-radius: 8; @@ -46,7 +62,7 @@ .lightboxView-exploreBtn { margin: auto; position: absolute; - right: 115; + right: 159; top: 10; background: transparent; border-radius: 8; diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index 7198c7f05..e93e4949b 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -23,6 +23,7 @@ import { DocumentView } from './nodes/DocumentView'; import { OpenWhere, OpenWhereMod } from './nodes/OpenWhere'; import { ScriptingGlobals } from '../util/ScriptingGlobals'; import { OverlayView } from './OverlayView'; +import { DrawingPalette } from './smartdraw/DrawingPalette'; interface LightboxViewProps { PanelWidth: number; @@ -59,6 +60,7 @@ export class LightboxView extends ObservableReactComponent { @observable private _doc: Opt = undefined; @observable private _docTarget: Opt = undefined; @observable private _docView: Opt = undefined; + @observable private _showPalette: boolean = false; @computed get leftBorder() { return Math.min(this._props.PanelWidth / 4, this._props.maxBorder[0]); } // prettier-ignore @computed get topBorder() { return Math.min(this._props.PanelHeight / 4, this._props.maxBorder[1]); } // prettier-ignore @@ -202,6 +204,9 @@ export class LightboxView extends ObservableReactComponent { toggleFitWidth = () => { this._doc && (this._doc._layout_fitWidth = !this._doc._layout_fitWidth); }; + togglePalette = () => { + this._showPalette = !this._showPalette; + }; togglePen = () => { Doc.ActiveTool = Doc.ActiveTool === InkTool.Pen ? InkTool.None : InkTool.Pen; }; @@ -319,8 +324,10 @@ export class LightboxView extends ObservableReactComponent { {toggleBtn('lightboxView-navBtn', 'toggle reading view', this._doc?._layout_fitWidth, 'book-open', 'book', this.toggleFitWidth)} {toggleBtn('lightboxView-tabBtn', 'open document in a tab', false, 'file-download', '', this.downloadDoc)} + {toggleBtn('lightboxView-paletteBtn', 'toggle annotation palette', this._showPalette === true, 'palette', '', this.togglePalette)} {toggleBtn('lightboxView-penBtn', 'toggle pen annotation', Doc.ActiveTool === InkTool.Pen, 'pen', '', this.togglePen)} {toggleBtn('lightboxView-exploreBtn', 'toggle navigate only mode', SnappingManager.ExploreMode, 'globe-americas', '', this.toggleExplore)} + {this._showPalette && }
); } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 67b875ecb..f88eb3bca 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,1129 +1,1991 @@ -/* eslint-disable node/no-unpublished-import */ -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faBuffer, faHireAHelper } from '@fortawesome/free-brands-svg-icons'; -import * as far from '@fortawesome/free-regular-svg-icons'; -import * as fa from '@fortawesome/free-solid-svg-icons'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, configure, makeObservable, observable, reaction, runInAction } from 'mobx'; +/* eslint-disable camelcase */ +/* eslint-disable jsx-a11y/control-has-associated-label */ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */ +/* eslint-disable jsx-a11y/click-events-have-key-events */ +/* eslint-disable react/no-array-index-key */ +/* eslint-disable react/jsx-props-no-spreading */ +/* eslint-disable no-return-assign */ +import ArrowLeftIcon from '@mui/icons-material/ArrowLeft'; +import ArrowRightIcon from '@mui/icons-material/ArrowRight'; +import PauseIcon from '@mui/icons-material/Pause'; +import PlayArrowIcon from '@mui/icons-material/PlayArrow'; +import QuestionMarkIcon from '@mui/icons-material/QuestionMark'; +import ReplayIcon from '@mui/icons-material/Replay'; +import { Box, Button, Checkbox, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, FormControl, FormControlLabel, FormGroup, IconButton, LinearProgress, Stack } from '@mui/material'; +import Typography from '@mui/material/Typography'; +import { IReactionDisposer, action, computed, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -// eslint-disable-next-line import/no-relative-packages -import '../../../node_modules/browndash-components/dist/styles/global.min.css'; -import { ClientUtils, lightOrDark, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents } from '../../ClientUtils'; -import { emptyFunction } from '../../Utils'; -import { Doc, DocListCast, GetDocFromUrl, Opt } from '../../fields/Doc'; -import { DocData } from '../../fields/DocSymbols'; -import { Id } from '../../fields/FieldSymbols'; -import { DocCast, StrCast, toList } from '../../fields/Types'; -import { DocServer } from '../DocServer'; -import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; -import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; -import { Docs } from '../documents/Documents'; -import { CalendarManager } from '../util/CalendarManager'; -import { CaptureManager } from '../util/CaptureManager'; -import { DocumentManager } from '../util/DocumentManager'; -import { DragManager } from '../util/DragManager'; -import { dropActionType } from '../util/DropActionTypes'; -import { GroupManager } from '../util/GroupManager'; -import { HistoryUtil } from '../util/History'; -import { Hypothesis } from '../util/HypothesisUtils'; -import { UPDATE_SERVER_CACHE } from '../util/LinkManager'; -import { RTFMarkup } from '../util/RTFMarkup'; -import { ScriptingGlobals } from '../util/ScriptingGlobals'; -import { ServerStats } from '../util/ServerStats'; -import { SettingsManager } from '../util/SettingsManager'; -import { SharingManager } from '../util/SharingManager'; -import { SnappingManager } from '../util/SnappingManager'; -import { Transform } from '../util/Transform'; -import { ReportManager } from '../util/reportManager/ReportManager'; -import { ComponentDecorations } from './ComponentDecorations'; -import { ContextMenu } from './ContextMenu'; -import { DashboardView } from './DashboardView'; -import { DictationOverlay } from './DictationOverlay'; -import { DocumentDecorations } from './DocumentDecorations'; -import { GestureOverlay } from './GestureOverlay'; -import { LightboxView } from './LightboxView'; -import './MainView.scss'; -import { ObservableReactComponent } from './ObservableReactComponent'; -import { PreviewCursor } from './PreviewCursor'; -import { PropertiesView } from './PropertiesView'; -import { DashboardStyleProvider, DefaultStyleProvider, returnEmptyDocViewList } from './StyleProvider'; -import { TimelineMenu } from './animationtimeline/TimelineMenu'; -import { CollectionDockingView } from './collections/CollectionDockingView'; -import { CollectionMenu } from './collections/CollectionMenu'; -import { TabDocView } from './collections/TabDocView'; -import './collections/TreeView.scss'; -import { CollectionFreeFormView } from './collections/collectionFreeForm'; -import { ImageLabelHandler } from './collections/collectionFreeForm/ImageLabelHandler'; -import { MarqueeOptionsMenu } from './collections/collectionFreeForm/MarqueeOptionsMenu'; -import { CollectionLinearView } from './collections/collectionLinear'; -import { LinkMenu } from './linking/LinkMenu'; -import { AudioBox } from './nodes/AudioBox'; -import { SchemaCSVPopUp } from './nodes/DataVizBox/SchemaCSVPopUp'; -import { DocButtonState } from './nodes/DocumentLinksButton'; -import { DocumentView, DocumentViewInternal } from './nodes/DocumentView'; -import { ImageEditorData as ImageEditor } from './nodes/ImageBox'; -import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup'; -import { LinkDocPreview, LinkInfo } from './nodes/LinkDocPreview'; -import { DirectionsAnchorMenu } from './nodes/MapBox/DirectionsAnchorMenu'; -import { MapAnchorMenu } from './nodes/MapBox/MapAnchorMenu'; -import { OpenWhere, OpenWhereMod } from './nodes/OpenWhere'; -import { TaskCompletionBox } from './nodes/TaskCompletedBox'; -import { DashFieldViewMenu } from './nodes/formattedText/DashFieldView'; -import { RichTextMenu } from './nodes/formattedText/RichTextMenu'; -import GenerativeFill from './nodes/generativeFill/GenerativeFill'; -import { PresBox } from './nodes/trails'; -import { AnchorMenu } from './pdf/AnchorMenu'; -import { GPTPopup } from './pdf/GPTPopup/GPTPopup'; -import { TopBar } from './topbar/TopBar'; -import { SmartDrawHandler } from './collections/collectionFreeForm/SmartDrawHandler'; +import { NumListCast } from '../../../../fields/Doc'; +import { List } from '../../../../fields/List'; +import { BoolCast, NumCast, StrCast } from '../../../../fields/Types'; +import { ViewBoxAnnotatableComponent } from '../../DocComponent'; +import { FieldView, FieldViewProps } from '../FieldView'; +import './PhysicsSimulationBox.scss'; +import InputField from './PhysicsSimulationInputField'; +import questions from './PhysicsSimulationQuestions.json'; +import tutorials from './PhysicsSimulationTutorial.json'; +import Wall from './PhysicsSimulationWall'; +import Weight from './PhysicsSimulationWeight'; +import { Docs } from '../../../documents/Documents'; +import { DocumentType } from '../../../documents/DocumentTypes'; -const { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } = require('./global/globalCssVariables.module.scss'); // prettier-ignore -const _global = (window /* browser */ || global) /* node */ as any; +interface IWallProps { + length: number; + xPos: number; + yPos: number; + angleInDegrees: number; +} +interface IForce { + description: string; + magnitude: number; + directionInDegrees: number; +} +interface VectorTemplate { + top: number; + left: number; + width: number; + height: number; + x1: number; + y1: number; + x2: number; + y2: number; + weightX: number; + weightY: number; +} +interface QuestionTemplate { + questionSetup: string[]; + variablesForQuestionSetup: string[]; + question: string; + answerParts: string[]; + answerSolutionDescriptions: string[]; + goal: string; + hints: { description: string; content: string }[]; +} + +interface TutorialTemplate { + question: string; + steps: { + description: string; + content: string; + forces: { + description: string; + magnitude: number; + directionInDegrees: number; + component: boolean; + }[]; + showMagnitude: boolean; + }[]; +} @observer -export class MainView extends ObservableReactComponent<{}> { - // eslint-disable-next-line no-use-before-define - public static Instance: MainView; - public static Live: boolean = false; - private _docBtnRef = React.createRef(); +export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent() { + public static LayoutString(fieldKey: string) { + return FieldView.LayoutString(PhysicsSimulationBox, fieldKey); + } + + _widthDisposer: IReactionDisposer | undefined; + @observable _simReset = 0; + + // semi-Constants + xMin = 0; + yMin = 0; + xMax = this._props.PanelWidth() * 0.6; + yMax = this._props.PanelHeight(); + color = `rgba(0,0,0,0.5)`; + radius = 50; + wallPositions: IWallProps[] = []; + + @computed get circularMotionRadius() { + return (NumCast(this.dataDoc.circularMotionRadius, 150) * this._props.PanelWidth()) / 1000; + } + @computed get gravity() { + return NumCast(this.dataDoc.simulation_gravity, -9.81); + } + @computed get simulationType() { + return StrCast(this.dataDoc.simulation_type, 'Inclined Plane'); + } + @computed get simulationMode() { + return StrCast(this.dataDoc.simulation_mode, 'Freeform'); + } + // Used for spring simulation + @computed get springConstant() { + return NumCast(this.dataDoc.spring_constant, 0.5); + } + @computed get springLengthRest() { + return NumCast(this.dataDoc.spring_lengthRest, 200); + } + @computed get springLengthStart() { + return NumCast(this.dataDoc.spring_lengthStart, 200); + } - @observable private _windowWidth: number = 0; - @observable private _windowHeight: number = 0; - @observable private _dashUIWidth: number = 0; // width of entire main dashboard region including left menu buttons and properties panel (but not including the dashboard selector button row) - @observable private _dashUIHeight: number = 0; // height of entire main dashboard region including top menu buttons - @observable private _panelContent: string = 'none'; - @observable private _sidebarContent: any = Doc.MyLeftSidebarPanel; - @observable private _leftMenuFlyoutWidth: number = 0; - @computed get _hideUI() { - return this.mainDoc && this.mainDoc._type_collection !== CollectionViewType.Docking; + @computed get pendulumAngle() { + return NumCast(this.dataDoc.pendulum_angle); + } + @computed get pendulumAngleStart() { + return NumCast(this.dataDoc.pendulum_angleStart); + } + @computed get pendulumLength() { + return NumCast(this.dataDoc.pendulum_length); + } + @computed get pendulumLengthStart() { + return NumCast(this.dataDoc.pendulum_lengthStart); } - @computed private get dashboardTabHeight() { - return this._hideUI ? 0 : 27; - } // 27 comes form lm.config.defaultConfig.dimensions.headerHeight in goldenlayout.js - @computed private get topOfDashUI() { - return this._hideUI || DocumentView.LightboxDoc() ? 0 : Number(TOPBAR_HEIGHT.replace('px', '')); + // Used for wedge simulation + @computed get wedgeAngle() { + return NumCast(this.dataDoc.wedge_angle, 26); } - @computed private get topOfHeaderBarDoc() { - return this.topOfDashUI; + @computed get wedgeHeight() { + return NumCast(this.dataDoc.wedge_height, Math.tan((26 * Math.PI) / 180) * this.xMax * 0.5); } - @computed private get topOfSidebarDoc() { - return this.topOfDashUI + this.topMenuHeight(); + @computed get wedgeWidth() { + return NumCast(this.dataDoc.wedge_width, this.xMax * 0.5); } - @computed private get topOfMainDoc() { - return this.topOfDashUI + this.topMenuHeight() + this.headerBarDocHeight(); + @computed get mass1() { + return NumCast(this.dataDoc.mass1, 1); } - @computed private get topOfMainDocContent() { - return this.topOfMainDoc + this.dashboardTabHeight; + @computed get mass2() { + return NumCast(this.dataDoc.mass2, 1); } - @computed private get leftScreenOffsetOfMainDocView() { - return this.leftMenuWidth() - 2; + + @computed get mass1Radius() { + return NumCast(this.dataDoc.mass1_radius, 30); } - @computed private get userDoc() { - return Doc.UserDoc(); + @computed get mass1PosXStart() { + return NumCast(this.dataDoc.mass1_positionXstart); } - @observable mainDoc: Opt = undefined; - @computed private get mainContainer() { - if (window.location.pathname.startsWith('/doc/') && ClientUtils.CurrentUserEmail() === 'guest') { - DocServer.GetRefField(window.location.pathname.substring('/doc/'.length)).then(main => - runInAction(() => { - this.mainDoc = main as Doc; - }) - ); - return this.mainDoc; - } - return this.userDoc ? Doc.ActiveDashboard : Doc.GuestDashboard; + @computed get mass1PosYStart() { + return NumCast(this.dataDoc.mass1_positionYstart); } - @computed private get headerBarDoc() { - return Doc.MyHeaderBar; + @computed get mass1VelXStart() { + return NumCast(this.dataDoc.mass1_velocityXstart); } - @computed public get mainFreeform(): Opt { - return (docs => (docs?.length > 1 ? docs[1] : undefined))(DocListCast(this.mainContainer!.data)); + @computed get mass1VelYStart() { + return NumCast(this.dataDoc.mass1_velocityYstart); } - @observable public headerBarHeight: number = 0; - headerBarHeightFunc = () => this.headerBarHeight; - @action - toggleTopBar = () => { - if (this.headerBarHeight > 0) { - this.headerBarHeight = 0; - } else { - this.headerBarHeight = 60; - } - }; - headerBarDocWidth = () => this.mainDocViewWidth(); - headerBarDocHeight = () => (this._hideUI ? 0 : this.headerBarHeight ?? 0); - topMenuHeight = () => (this._hideUI ? 0 : 35); - topMenuWidth = returnZero; // value is ignored ... - leftMenuWidth = () => (this._hideUI ? 0 : Number(LEFT_MENU_WIDTH.replace('px', ''))); - leftMenuHeight = () => this._dashUIHeight; - leftMenuFlyoutWidth = () => this._leftMenuFlyoutWidth; - leftMenuFlyoutHeight = () => this._dashUIHeight; - propertiesWidth = () => Math.max(0, Math.min(this._dashUIWidth - 50, SnappingManager.PropertiesWidth || 0)); - propertiesHeight = () => this._dashUIHeight; - mainDocViewWidth = () => this._dashUIWidth - this.propertiesWidth() - this.leftMenuWidth() - this.leftMenuFlyoutWidth(); - mainDocViewHeight = () => this._dashUIHeight - this.headerBarDocHeight(); + @computed get mass2PosXStart() { + return NumCast(this.dataDoc.mass2_positionXstart); + } + @computed get mass2PosYStart() { + return NumCast(this.dataDoc.mass2_positionYstart); + } + @computed get mass2VelXStart() { + return NumCast(this.dataDoc.mass2_velocityXstart); + } + @computed get mass2VelYStart() { + return NumCast(this.dataDoc.mass2_velocityYstart); + } + + @computed get selectedQuestion() { + return this.dataDoc.selectedQuestion ? (JSON.parse(StrCast(this.dataDoc.selectedQuestion)) as QuestionTemplate) : questions.inclinePlane[0]; + } + @computed get tutorial() { + return this.dataDoc.tutorial ? (JSON.parse(StrCast(this.dataDoc.tutorial)) as TutorialTemplate) : tutorials.inclinePlane; + } + @computed get selectedSolutions() { + return NumListCast(this.dataDoc.selectedSolutions); + } + @computed get questionPartOne() { + return StrCast(this.dataDoc.questionPartOne); + } + @computed get questionPartTwo() { + return StrCast(this.dataDoc.questionPartTwo); + } + + componentWillUnmount() { + this._widthDisposer?.(); + } componentDidMount() { - // Utils.TraceConsoleLog(); - reaction( - // when a multi-selection occurs, remove focus from all active elements to allow keyboad input to go only to global key manager to act upon selection - () => DocumentView.Selected().slice(), - views => views.length > 1 && (document.activeElement as any)?.blur !== undefined && (document.activeElement as any)!.blur() - ); - reaction( - () => Doc.MyDockedBtns.linearView_IsOpen, - open => SnappingManager.SetPrintToConsole(!!open) - ); - const scriptTag = document.createElement('script'); - scriptTag.setAttribute('type', 'text/javascript'); - scriptTag.setAttribute('src', 'https://www.bing.com/api/maps/mapcontrol?callback=makeMap'); - scriptTag.async = true; - scriptTag.defer = true; - document.body.appendChild(scriptTag); - document.getElementById('root')?.addEventListener('scroll', () => - (ele => { - ele.scrollLeft = ele.scrollTop = 0; - })(document.getElementById('root')!) - ); - const ele = document.getElementById('loader'); - const prog = document.getElementById('dash-progress'); - if (ele && prog) { - // remove from DOM - setTimeout(() => { - prog.style.transition = '1s'; - prog.style.width = '100%'; - }, 0); - setTimeout(() => { - ele.outerHTML = ''; - }, 1000); - } - this._sidebarContent.proto = undefined; - if (!MainView.Live) { - DocServer.setLivePlaygroundFields([ - 'dataTransition', - 'viewTransition', - 'treeView_Open', - 'treeView_ExpandedView', - 'carousel_index', - 'itemIndex', // for changing slides in presentations - 'layout_sidebarWidthPercent', - 'layout_currentTimecode', - 'layout_timelineHeightPercent', - 'layout_hideMinimap', - 'layout_showSidebar', - 'layout_scrollTop', - 'layout_fitWidth', - 'layout_curPage', - 'presStatus', - 'freeform_panX', - 'freeform_panY', - 'freeform_scale', - 'overlayX', - 'overlayY', - 'text_scrollHeight', - 'text_height', - 'hidden', - // 'type_collection', - 'chromeHidden', - 'currentFrame', - ]); // can play with these fields on someone else's - } + // Setup and update simulation + this._widthDisposer = reaction(() => [this._props.PanelWidth(), this._props.PanelHeight()], this.setupSimulation, { fireImmediately: true }); - const tag = document.createElement('script'); - tag.src = 'https://www.youtube.com/iframe_api'; - const firstScriptTag = document.getElementsByTagName('script')[0]; - firstScriptTag.parentNode!.insertBefore(tag, firstScriptTag); - document.addEventListener('dash', (e: any) => { - // event used by chrome plugin to tell Dash which document to focus on - const id = GetDocFromUrl(e.detail); - DocServer.GetRefField(id).then(doc => (doc instanceof Doc ? DocumentView.showDocument(doc, { willPan: false }) : null)); - }); - document.addEventListener('linkAnnotationToDash', Hypothesis.linkListener); - this.initEventListeners(); + // Create walls + this.wallPositions = [ + { length: 100, xPos: 0, yPos: 0, angleInDegrees: 0 }, + { length: 100, xPos: 0, yPos: 100, angleInDegrees: 0 }, + { length: 100, xPos: 0, yPos: 0, angleInDegrees: 90 }, + { length: 100, xPos: (this.xMax / this._props.PanelWidth()) * 100, yPos: 0, angleInDegrees: 90 }, + ]; } - componentWillUnMount() { - // window.removeEventListener('keyup', KeyManager.Instance.unhandle); - // window.removeEventListener('keydown', KeyManager.Instance.handle); - // window.removeEventListener('pointerdown', this.globalPointerDown, true); - // window.removeEventListener('pointermove', this.globalPointerMove, true); - // window.removeEventListener('pointerup', this.globalPointerClick, true); - // window.removeEventListener('paste', KeyManager.Instance.paste as any); - // document.removeEventListener('linkAnnotationToDash', Hypothesis.linkListener); + componentDidUpdate(prevProps: Readonly) { + super.componentDidUpdate(prevProps); + if (this.xMax !== this._props.PanelWidth() * 0.6 || this.yMax !== this._props.PanelHeight()) { + this.xMax = this._props.PanelWidth() * 0.6; + this.yMax = this._props.PanelHeight(); + this.setupSimulation(); + } } - constructor(props: any) { - super(props); - makeObservable(this); - DocumentViewInternal.addDocTabFunc = MainView.addDocTabFunc_impl; - MainView.Instance = this; - DashboardView._urlState = HistoryUtil.parseUrl(window.location) || ({} as any); + gravityForce = (mass: number): IForce => ({ + description: 'Gravity', + magnitude: mass * Math.abs(this.gravity), + directionInDegrees: 270, + }); - // causes errors to be generated when modifying an observable outside of an action - configure({ enforceActions: 'observed' }); + @action + setupSimulation = () => { + const { simulationType } = this; + const mode = this.simulationMode; + this.dataDoc.simulation_paused = true; + if (simulationType !== 'Circular Motion') { + this.dataDoc.mass1_velocityXstart = 0; + this.dataDoc.mass1_velocityYstart = 0; + this.dataDoc.mass1_velocityX = 0; + this.dataDoc.mass1_velocityY = 0; + } + if (mode === 'Freeform') { + this.dataDoc.simulation_showForceMagnitudes = true; + // prettier-ignore + switch (simulationType) { + case 'One Weight': + this.dataDoc.simulation_showComponentForces = false; + this.dataDoc.mass1_positionYstart = this.yMin + this.mass1Radius; + this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - this.mass1Radius; + this.dataDoc.mass1_positionY = this.getDisplayYPos(this.yMin + this.mass1Radius); + this.dataDoc.mass1_positionX = (this.xMax + this.xMin) / 2 - this.mass1Radius; + this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1)]); + this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1)]); + break; + case 'Inclined Plane': this.setupInclinedPlane(); break; + case 'Pendulum': this.setupPendulum(); break; + case 'Spring': this.setupSpring(); break; + case 'Circular Motion': this.setupCircular(20); break; + case 'Pulley': this.setupPulley(); break; + case 'Suspension': this.setupSuspension();break; + default: + } + this._simReset++; + } else if (mode === 'Review') { + this.dataDoc.simulation_showComponentForces = false; + this.dataDoc.simulation_showForceMagnitudes = true; + this.dataDoc.simulation_showAcceleration = false; + this.dataDoc.simulation_showVelocity = false; + this.dataDoc.simulation_showForces = true; + this.generateNewQuestion(); + // prettier-ignore + switch (simulationType) { + case 'One Weight' : break;// TODO - one weight review problems + case 'Spring': this.setupSpring(); break; // TODO - spring review problems + case 'Inclined Plane': this.dataDoc.mass1_forcesUpdated = this.dataDoc.mass1_forcesStart = ''; break; + case 'Pendulum': this.setupPendulum(); break; // TODO - pendulum review problems + case 'Circular Motion': this.setupCircular(0); break; // TODO - circular motion review problems + case 'Pulley': this.setupPulley(); break; // TODO - pulley tutorial review problems + case 'Suspension': this.setupSuspension(); break; // TODO - suspension tutorial review problems + default: + } + } else if (mode === 'Tutorial') { + this.dataDoc.simulation_showComponentForces = false; + this.dataDoc.tutorial_stepNumber = 0; + this.dataDoc.simulation_showAcceleration = false; + if (this.simulationType !== 'Circular Motion') { + this.dataDoc.mass1_velocityX = 0; + this.dataDoc.mass1_velocityY = 0; + this.dataDoc.simulation_showVelocity = false; + } else { + this.dataDoc.mass1_velocityX = 20; + this.dataDoc.mass1_velocityY = 0; + this.dataDoc.simulation_showVelocity = true; + } - if (window.location.pathname !== '/home') { - const pathname = window.location.pathname.substr(1).split('/'); - if (pathname.length > 1 && pathname[0] === 'doc') { - DocServer.GetRefField(pathname[1]).then( - action(field => { - if (field instanceof Doc && field._type_collection !== CollectionViewType.Docking) { - Doc.GuestTarget = field; - } - }) - ); + switch (this.simulationType) { + case 'One Weight': + this.dataDoc.simulation_showForces = true; + this.dataDoc.mass1_positionYstart = this.yMax - 100; + this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - this.mass1Radius; + this.dataDoc.tutorial = JSON.stringify(tutorials.freeWeight); + this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.freeWeight.steps[0].forces); + this.dataDoc.simulation_showForceMagnitudes = tutorials.freeWeight.steps[0].showMagnitude; + break; + case 'Spring': + this.dataDoc.simulation_showForces = true; + this.setupSpring(); + this.dataDoc.mass1_positionYstart = this.yMin + 200 + 19.62; + this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - this.mass1Radius; + this.dataDoc.tutorial = JSON.stringify(tutorials.spring); + this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.spring.steps[0].forces); + this.dataDoc.simulation_showForceMagnitudes = tutorials.spring.steps[0].showMagnitude; + break; + case 'Pendulum': + this.setupPendulum(); + this.dataDoc.tutorial = JSON.stringify(tutorials.pendulum); + this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.pendulum.steps[0].forces); + this.dataDoc.simulation_showForceMagnitudes = tutorials.pendulum.steps[0].showMagnitude; + break; + case 'Inclined Plane': + this.dataDoc.wedge_angle = 26; + this.setupInclinedPlane(); + this.dataDoc.simulation_showForces = true; + this.dataDoc.tutorial = JSON.stringify(tutorials.inclinePlane); + this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.inclinePlane.steps[0].forces); + this.dataDoc.simulation_showForceMagnitudes = tutorials.inclinePlane.steps[0].showMagnitude; + break; + case 'Circular Motion': + this.dataDoc.simulation_showForces = true; + this.setupCircular(40); + this.dataDoc.tutorial = JSON.stringify(tutorials.circular); + this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.circular.steps[0].forces); + this.dataDoc.simulation_showForceMagnitudes = tutorials.circular.steps[0].showMagnitude; + break; + case 'Pulley': + this.dataDoc.simulation_showForces = true; + this.setupPulley(); + this.dataDoc.tutorial = JSON.stringify(tutorials.pulley); + this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.pulley.steps[0].forces); + this.dataDoc.simulation_showForceMagnitudes = tutorials.pulley.steps[0].showMagnitude; + break; + case 'Suspension': + this.dataDoc.simulation_showForces = true; + this.setupSuspension(); + this.dataDoc.tutorial = JSON.stringify(tutorials.suspension); + this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.suspension.steps[0].forces); + this.dataDoc.simulation_showForceMagnitudes = tutorials.suspension.steps[0].showMagnitude; + break; + default: } + this._simReset++; } + }; - library.add( - ...[ - fa.faExclamationCircle, - fa.faEdit, - fa.faArrowDownShortWide, - fa.faTrash, - fa.faTrashAlt, - fa.faShare, - fa.faTaxi, - fa.faDownload, - fa.faPallet, - fa.faExpandArrowsAlt, - fa.faAmbulance, - fa.faLayerGroup, - fa.faExternalLinkAlt, - fa.faCalendar, - fa.faSquare, - far.faSquare as any, - fa.faConciergeBell, - fa.faWindowRestore, - fa.faFolder, - fa.faFolderOpen, - fa.faFolderPlus, - fa.faFolderClosed, - fa.faBook, - fa.faMapPin, - fa.faMapMarker, - fa.faFingerprint, - fa.faCrosshairs, - fa.faDesktop, - fa.faUnlock, - fa.faLock, - fa.faLaptopCode, - fa.faMale, - fa.faCopy, - fa.faHome, - fa.faHandPointLeft, - fa.faHandPointRight, - fa.faCompass, - fa.faSnowflake, - fa.faStar, - fa.faSplotch, - fa.faMicrophone, - fa.faCircleHalfStroke, - fa.faKeyboard, - fa.faQuestion, - fa.faTasks, - fa.faPalette, - fa.faAngleLeft, - fa.faAngleRight, - fa.faBell, - fa.faCamera, - fa.faExpand, - fa.faCaretDown, - fa.faCaretLeft, - fa.faCaretRight, - fa.faCaretSquareDown, - fa.faCaretSquareRight, - fa.faArrowsAltH, - fa.faPlus, - fa.faMinus, - fa.faTerminal, - fa.faToggleOn, - fa.faFile, - fa.faLocationArrow, - fa.faSearch, - fa.faFileDownload, - fa.faFileUpload, - fa.faStop, - fa.faCalculator, - fa.faWindowMaximize, - fa.faIdCard, - fa.faAddressCard, - fa.faQuestionCircle, - fa.faArrowLeft, - fa.faArrowRight, - fa.faArrowDown, - fa.faArrowUp, - fa.faBolt, - fa.faBullseye, - fa.faTurnUp, - fa.faTurnDown, - fa.faCaretUp, - fa.faCat, - fa.faCheck, - fa.faChevronRight, - fa.faChevronLeft, - fa.faChevronDown, - fa.faChevronUp, - fa.faClone, - fa.faCloudUploadAlt, - fa.faCommentAlt, - fa.faCommentDots, - fa.faCompressArrowsAlt, - fa.faCut, - fa.faEllipsisV, - fa.faEraser, - fa.faDeleteLeft, - fa.faXmarksLines, - fa.faCircleXmark, - fa.faXmark, - fa.faExclamation, - fa.faFileAlt, - fa.faFileAudio, - fa.faFileVideo, - fa.faFilePdf, - fa.faFilm, - fa.faFilter, - fa.faFont, - fa.faGlobeAmericas, - fa.faGlobeAsia, - fa.faHighlighter, - fa.faLongArrowAltRight, - fa.faMousePointer, - fa.faMusic, - fa.faObjectGroup, - fa.faArrowsLeftRight, - fa.faPause, - fa.faPen, - fa.faUserPen, - fa.faPenNib, - fa.faPhone, - fa.faPlay, - fa.faPortrait, - fa.faRedoAlt, - fa.faStamp, - fa.faStickyNote, - fa.faArrowsAltV, - fa.faTimesCircle, - fa.faThumbtack, - fa.faTree, - fa.faTv, - fa.faUndoAlt, - fa.faVideoSlash, - fa.faVideo, - fa.faAsterisk, - fa.faBrain, - fa.faImage, - fa.faPaintBrush, - fa.faTimes, - fa.faFlag, - fa.faScroll, - fa.faEye, - fa.faArrowsAlt, - fa.faQuoteLeft, - fa.faSortAmountDown, - fa.faAlignLeft, - fa.faAlignCenter, - fa.faAlignRight, - fa.faHeading, - fa.faRulerCombined, - fa.faFillDrip, - fa.faLink, - fa.faUnlink, - fa.faBold, - fa.faItalic, - fa.faClipboard, - fa.faUnderline, - fa.faStrikethrough, - fa.faSuperscript, - fa.faSubscript, - fa.faIndent, - fa.faEyeDropper, - fa.faPaintRoller, - fa.faBars, - fa.faBarsStaggered, - fa.faBrush, - fa.faShapes, - fa.faEllipsisH, - fa.faHandPaper, - fa.faMap, - fa.faUser, - faHireAHelper as any, - fa.faTrashRestore, - fa.faUsers, - fa.faWrench, - fa.faCog, - fa.faMap, - fa.faBellSlash, - fa.faExpandAlt, - fa.faArchive, - fa.faBezierCurve, - fa.faCircle, - far.faCircle as any, - fa.faLongArrowAltRight, - fa.faPenFancy, - fa.faAngleDoubleRight, - fa.faAngleDoubleDown, - fa.faAngleDoubleLeft, - fa.faAngleDoubleUp, - faBuffer as any, - fa.faExpand, - fa.faUndo, - fa.faSlidersH, - fa.faAngleUp, - fa.faAngleDown, - fa.faPlayCircle, - fa.faClock, - fa.faRoute, - fa.faRocket, - fa.faExchangeAlt, - fa.faHashtag, - fa.faAlignJustify, - fa.faCheckSquare, - fa.faListUl, - fa.faWindowMinimize, - fa.faWindowRestore, - fa.faTextWidth, - fa.faTextHeight, - fa.faClosedCaptioning, - fa.faInfoCircle, - fa.faTag, - fa.faSyncAlt, - fa.faPhotoVideo, - fa.faArrowAltCircleDown, - fa.faArrowAltCircleUp, - fa.faArrowAltCircleLeft, - fa.faArrowAltCircleRight, - fa.faStopCircle, - fa.faCheckCircle, - fa.faGripVertical, - fa.faSortUp, - fa.faSortDown, - fa.faTable, - fa.faTableCells, - fa.faTableColumns, - fa.faTh, - fa.faThList, - fa.faProjectDiagram, - fa.faSignature, - fa.faColumns, - fa.faChevronCircleUp, - fa.faUpload, - fa.faBorderAll, - fa.faBraille, - fa.faPersonChalkboard, - fa.faChalkboard, - fa.faPencilAlt, - fa.faEyeSlash, - fa.faSmile, - fa.faIndent, - fa.faOutdent, - fa.faChartBar, - fa.faBan, - fa.faPhoneSlash, - fa.faGripLines, - fa.faSave, - fa.faBook, - fa.faBookmark, - fa.faList, - fa.faListOl, - fa.faLightbulb, - fa.faBookOpen, - fa.faMapMarkerAlt, - fa.faSearchPlus, - fa.faSolarPanel, - fa.faVolumeUp, - fa.faVolumeDown, - fa.faSquareRootAlt, - fa.faVolumeMute, - fa.faUserCircle, - fa.faHeart, - fa.faHeartBroken, - fa.faHighlighter, - fa.faRemoveFormat, - fa.faHandPointUp, - fa.faXRay, - fa.faZ, - fa.faArrowsUpToLine, - fa.faArrowsDownToLine, - fa.faPalette, - fa.faHourglassHalf, - fa.faRobot, - fa.faSatellite, - fa.faStar, - ] - ); - } + // Helper function to go between display and real values + getDisplayYPos = (yPos: number) => this.yMax - yPos - 2 * this.mass1Radius + 5; + getYPosFromDisplay = (yDisplay: number) => this.yMax - yDisplay - 2 * this.mass1Radius + 5; - private longPressTimer: NodeJS.Timeout | undefined; - globalPointerClick = action(() => { - this.longPressTimer && clearTimeout(this.longPressTimer); - DocumentView.LongPress = false; - }); - globalPointerMove = action((e: PointerEvent) => { - if (e.movementX > 3 || e.movementY > 3) this.longPressTimer && clearTimeout(this.longPressTimer); - }); - globalPointerDown = action((e: PointerEvent) => { - DocumentView.LongPress = false; - this.longPressTimer = setTimeout( - action(() => { - DocumentView.LongPress = true; - }), - 1000 - ); - DocumentManager.removeOverlayViews(); - Doc.linkFollowUnhighlight(); - AudioBox.Enabled = true; - const targets = document.elementsFromPoint(e.x, e.y); - if (targets.length) { - let targClass = targets[0].className.toString(); - for (let i = 0; i < targets.length - 1; i++) { - if (typeof targets[i].className === 'object') targClass = targets[i + 1].className.toString(); - else break; - } - !targClass.includes('contextMenu') && ContextMenu.Instance.closeMenu(); - !['timeline-menu-desc', 'timeline-menu-item', 'timeline-menu-input'].includes(targClass) && TimelineMenu.Instance.closeMenu(); + // Update forces when coefficient of static friction changes in freeform mode + updateForcesWithFriction = (coefficient: number, width = this.wedgeWidth, height = this.wedgeHeight) => { + const normalForce: IForce = { + description: 'Normal Force', + magnitude: Math.abs(this.gravity) * Math.cos(Math.atan(height / width)) * this.mass1, + directionInDegrees: 180 - 90 - (Math.atan(height / width) * 180) / Math.PI, + }; + const frictionForce: IForce = { + description: 'Static Friction Force', + magnitude: coefficient * Math.abs(this.gravity) * Math.cos(Math.atan(height / width)) * this.mass1, + directionInDegrees: 180 - (Math.atan(height / width) * 180) / Math.PI, + }; + // reduce magnitude or friction force if necessary such that block cannot slide up plane + let yForce = -Math.abs(this.gravity) * this.mass1; + yForce += normalForce.magnitude * Math.sin((normalForce.directionInDegrees * Math.PI) / 180); + yForce += frictionForce.magnitude * Math.sin((frictionForce.directionInDegrees * Math.PI) / 180); + if (yForce > 0) { + frictionForce.magnitude = (-normalForce.magnitude * Math.sin((normalForce.directionInDegrees * Math.PI) / 180) + Math.abs(this.gravity) * this.mass1) / Math.sin((frictionForce.directionInDegrees * Math.PI) / 180); } - }); - initEventListeners = () => { - window.addEventListener('beforeunload', UPDATE_SERVER_CACHE); - window.addEventListener('drop', e => e.preventDefault(), false); // prevent default behavior of navigating to a new web page - window.addEventListener('dragover', e => e.preventDefault(), false); - document.addEventListener('pointerdown', this.globalPointerDown, true); - document.addEventListener('pointermove', this.globalPointerMove, true); - document.addEventListener('pointerup', this.globalPointerClick, true); - document.addEventListener( - 'click', - (e: MouseEvent) => { - if (!e.cancelBubble) { - const pathstr = (e as any)?.path?.map((p: any) => p.classList?.toString()).join(); - if (pathstr?.includes('libraryFlyout')) { - DocumentView.DeselectAll(); - } - } - }, - false - ); - document.oncontextmenu = () => false; + const normalForceComponent: IForce = { + description: 'Normal Force', + magnitude: this.mass1 * Math.abs(this.gravity) * Math.cos(Math.atan(height / width)), + directionInDegrees: 180 - 90 - (Math.atan(height / width) * 180) / Math.PI, + }; + const gravityParallel: IForce = { + description: 'Gravity Parallel Component', + magnitude: this.mass1 * Math.abs(this.gravity) * Math.sin(Math.PI / 2 - Math.atan(height / width)), + directionInDegrees: 180 - 90 - (Math.atan(height / width) * 180) / Math.PI + 180, + }; + const gravityPerpendicular: IForce = { + description: 'Gravity Perpendicular Component', + magnitude: this.mass1 * Math.abs(this.gravity) * Math.cos(Math.PI / 2 - Math.atan(height / width)), + directionInDegrees: 360 - (Math.atan(height / width) * 180) / Math.PI, + }; + const gravityForce = this.gravityForce(this.mass1); + if (coefficient !== 0) { + this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce, normalForce, frictionForce]); + this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce, normalForce, frictionForce]); + this.dataDoc.mass1_componentForces = JSON.stringify([frictionForce, normalForceComponent, gravityParallel, gravityPerpendicular]); + } else { + this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce, normalForce]); + this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce, normalForce]); + this.dataDoc.mass1_componentForces = JSON.stringify([normalForceComponent, gravityParallel, gravityPerpendicular]); + } }; - @action - createNewPresentation = () => { - const pres = Doc.MakeCopy(Doc.UserDoc().emptyTrail as Doc, true); - CollectionDockingView.AddSplit(pres, OpenWhereMod.right); - Doc.MyTrails && Doc.AddDocToList(Doc.MyTrails, 'data', pres); // Doc.MyTrails should be created in createDashboard - Doc.ActivePresentation = pres; + // Change wedge height and width and weight position to match new wedge angle + changeWedgeBasedOnNewAngle = (angle: number) => { + const radAng = (angle * Math.PI) / 180; + this.dataDoc.wedge_width = this.xMax * 0.5; + this.dataDoc.wedge_height = Math.tan(radAng) * this.dataDoc.wedge_width; + + // update weight position based on updated wedge width/height + const yPos = this.yMax - this.dataDoc.wedge_height - this.mass1Radius * Math.cos(radAng) - this.mass1Radius; + const xPos = this.xMax * 0.25 + this.mass1Radius * Math.sin(radAng) - this.mass1Radius; + + this.dataDoc.mass1_positionXstart = xPos; + this.dataDoc.mass1_positionYstart = yPos; + if (this.simulationMode === 'Freeform') { + this.updateForcesWithFriction(NumCast(this.dataDoc.coefficientOfStaticFriction), this.dataDoc.wedge_width, Math.tan(radAng) * this.dataDoc.wedge_width); + } }; - @action - openPresentation = (pres: Doc) => { - if (pres.type === DocumentType.PRES) { - CollectionDockingView.AddSplit(pres, OpenWhereMod.right, undefined, PresBox.PanelName); - Doc.MyTrails && (Doc.ActivePresentation = pres); - Doc.AddDocToList(Doc.MyTrails, 'data', pres); - this.closeFlyout(); + // In review mode, update forces when coefficient of static friction changed + updateReviewForcesBasedOnCoefficient = (coefficient: number) => { + let theta = this.wedgeAngle; + const index = this.selectedQuestion.variablesForQuestionSetup.indexOf('theta - max 45'); + if (index >= 0) { + theta = NumListCast(this.dataDoc.questionVariables)[index]; + } + if (isNaN(theta)) { + return; + } + this.dataDoc.review_GravityMagnitude = Math.abs(this.gravity); + this.dataDoc.review_GravityAngle = 270; + this.dataDoc.review_NormalMagnitude = Math.abs(this.gravity) * Math.cos((theta * Math.PI) / 180); + this.dataDoc.review_NormalAngle = 90 - theta; + let yForce = -Math.abs(this.gravity); + yForce += Math.abs(this.gravity) * Math.cos((theta * Math.PI) / 180) * Math.sin(((90 - theta) * Math.PI) / 180); + yForce += coefficient * Math.abs(this.gravity) * Math.cos((theta * Math.PI) / 180) * Math.sin(((180 - theta) * Math.PI) / 180); + let friction = coefficient * Math.abs(this.gravity) * Math.cos((theta * Math.PI) / 180); + if (yForce > 0) { + friction = (-(Math.abs(this.gravity) * Math.cos((theta * Math.PI) / 180)) * Math.sin(((90 - theta) * Math.PI) / 180) + Math.abs(this.gravity)) / Math.sin(((180 - theta) * Math.PI) / 180); } + this.dataDoc.review_StaticMagnitude = friction; + this.dataDoc.review_StaticAngle = 180 - theta; }; - @action - createNewFolder = async () => { - const folder = Docs.Create.TreeDocument([], { title: 'Untitled folder', _dragOnlyWithinContainer: true, isFolder: true }); - Doc.AddDocToList(Doc.MyFilesystem, 'data', folder); + // In review mode, update forces when wedge angle changed + updateReviewForcesBasedOnAngle = (angle: number) => { + this.dataDoc.review_GravityMagnitude = Math.abs(this.gravity); + this.dataDoc.review_GravityAngle = 270; + this.dataDoc.review_NormalMagnitude = Math.abs(this.gravity) * Math.cos((angle * Math.PI) / 180); + this.dataDoc.review_NormalAngle = 90 - angle; + let yForce = -Math.abs(this.gravity); + yForce += Math.abs(this.gravity) * Math.cos((angle * Math.PI) / 180) * Math.sin(((90 - angle) * Math.PI) / 180); + yForce += NumCast(this.dataDoc.review_Coefficient) * Math.abs(this.gravity) * Math.cos((angle * Math.PI) / 180) * Math.sin(((180 - angle) * Math.PI) / 180); + let friction = NumCast(this.dataDoc.review_Coefficient) * Math.abs(this.gravity) * Math.cos((angle * Math.PI) / 180); + if (yForce > 0) { + friction = (-(Math.abs(this.gravity) * Math.cos((angle * Math.PI) / 180)) * Math.sin(((90 - angle) * Math.PI) / 180) + Math.abs(this.gravity)) / Math.sin(((180 - angle) * Math.PI) / 180); + } + this.dataDoc.review_StaticMagnitude = friction; + this.dataDoc.review_StaticAngle = 180 - angle; }; - waitForDoubleClick = () => (SnappingManager.ExploreMode ? 'never' : undefined); - headerBarScreenXf = () => new Transform(-this.leftScreenOffsetOfMainDocView - this.leftMenuFlyoutWidth(), -this.headerBarDocHeight(), 1); - mainScreenToLocalXf = () => new Transform(-this.leftScreenOffsetOfMainDocView - this.leftMenuFlyoutWidth(), -this.topOfMainDocContent, 1); - addHeaderDoc = (docs: Doc | Doc[]) => toList(docs).reduce((done, doc) => Doc.AddDocToList(this.headerBarDoc, 'data', doc), true); - removeHeaderDoc = (docs: Doc | Doc[]) => toList(docs).reduce((done, doc) => Doc.RemoveDocFromList(this.headerBarDoc, 'data', doc), true); - @computed get headerBarDocView() { - return ( -
- -
- ); - } - @computed get mainDocView() { - const headerBar = this._hideUI || !this.headerBarDocHeight?.() ? null : this.headerBarDocView; - return ( - <> - {headerBar} - - - ); - } + // Solve for the correct answers to the generated problem + getAnswersToQuestion = (question: QuestionTemplate, questionVars: number[]) => { + const solutions: number[] = []; - @computed get dockingContent() { - return ( - -
{ - e.stopPropagation(); - e.preventDefault(); - }} - style={{ - width: `calc(100% - ${this._leftMenuFlyoutWidth + this.leftMenuWidth() + this.propertiesWidth()}px)`, - minWidth: `calc(100% - ${this._leftMenuFlyoutWidth + this.leftMenuWidth() + this.propertiesWidth()}px)`, - transform: DocumentView.LightboxDoc() ? 'scale(0.0001)' : undefined, - }}> - {!this.mainContainer ? null : this.mainDocView} -
-
- ); - } + let theta = this.wedgeAngle; + let index = question.variablesForQuestionSetup.indexOf('theta - max 45'); + if (index >= 0) { + theta = questionVars[index]; + } + let muS: number = NumCast(this.dataDoc.coefficientOfStaticFriction); + index = question.variablesForQuestionSetup.indexOf('coefficient of static friction'); + if (index >= 0) { + muS = questionVars[index]; + } - @action - onPropertiesPointerDown = (e: React.PointerEvent) => { - setupMoveUpEvents( - this, - e, - action(() => { - SnappingManager.SetPropertiesWidth(Math.max(0, this._dashUIWidth - e.clientX)); - return !SnappingManager.PropertiesWidth; - }), - action(() => { - SnappingManager.PropertiesWidth < 5 && SnappingManager.SetPropertiesWidth(0); - }), - action(() => { - SnappingManager.SetPropertiesWidth(this.propertiesWidth() < 15 ? Math.min(this._dashUIWidth - 50, 250) : 0); - }), - false - ); + for (let i = 0; i < question.answerSolutionDescriptions.length; i++) { + const description = question.answerSolutionDescriptions[i]; + if (!isNaN(NumCast(description))) { + solutions.push(NumCast(description)); + } else if (description === 'solve normal force angle from wedge angle') { + solutions.push(90 - theta); + } else if (description === 'solve normal force magnitude from wedge angle') { + solutions.push(Math.abs(this.gravity) * Math.cos((theta / 180) * Math.PI)); + } else if (description === 'solve static force magnitude from wedge angle given equilibrium') { + const normalForceMagnitude = Math.abs(this.gravity) * Math.cos((theta / 180) * Math.PI); + const normalForceAngle = 90 - theta; + const frictionForceAngle = 180 - theta; + const frictionForceMagnitude = (-normalForceMagnitude * Math.sin((normalForceAngle * Math.PI) / 180) + Math.abs(this.gravity)) / Math.sin((frictionForceAngle * Math.PI) / 180); + solutions.push(frictionForceMagnitude); + } else if (description === 'solve static force angle from wedge angle given equilibrium') { + solutions.push(180 - theta); + } else if (description === 'solve minimum static coefficient from wedge angle given equilibrium') { + const normalForceMagnitude = Math.abs(this.gravity) * Math.cos((theta / 180) * Math.PI); + const normalForceAngle = 90 - theta; + const frictionForceAngle = 180 - theta; + const frictionForceMagnitude = (-normalForceMagnitude * Math.sin((normalForceAngle * Math.PI) / 180) + Math.abs(this.gravity)) / Math.sin((frictionForceAngle * Math.PI) / 180); + const frictionCoefficient = frictionForceMagnitude / normalForceMagnitude; + solutions.push(frictionCoefficient); + } else if (description === 'solve maximum wedge angle from coefficient of static friction given equilibrium') { + solutions.push((Math.atan(muS) * 180) / Math.PI); + } + } + this.dataDoc.selectedSolutions = new List(solutions); + return solutions; }; - @action - onFlyoutPointerDown = (e: React.PointerEvent) => { - setupMoveUpEvents( - this, - e, - action(ev => { - this._leftMenuFlyoutWidth = Math.max(ev.clientX - 58, 0); - return false; - }), - () => this._leftMenuFlyoutWidth < 5 && this.closeFlyout(), - this.closeFlyout - ); + // In review mode, check if input answers match correct answers and optionally generate alert + checkAnswers = (showAlert: boolean = true) => { + let error: boolean = false; + const epsilon: number = 0.01; + if (this.selectedQuestion) { + for (let i = 0; i < this.selectedQuestion.answerParts.length; i++) { + if (this.selectedQuestion.answerParts[i] === 'force of gravity') { + if (Math.abs(NumCast(this.dataDoc.review_GravityMagnitude) - this.selectedSolutions[i]) > epsilon) { + error = true; + } + } else if (this.selectedQuestion.answerParts[i] === 'angle of gravity') { + if (Math.abs(NumCast(this.dataDoc.review_GravityAngle) - this.selectedSolutions[i]) > epsilon) { + error = true; + } + } else if (this.selectedQuestion.answerParts[i] === 'normal force') { + if (Math.abs(NumCast(this.dataDoc.review_NormalMagnitude) - this.selectedSolutions[i]) > epsilon) { + error = true; + } + } else if (this.selectedQuestion.answerParts[i] === 'angle of normal force') { + if (Math.abs(NumCast(this.dataDoc.review_NormalAngle) - this.selectedSolutions[i]) > epsilon) { + error = true; + } + } else if (this.selectedQuestion.answerParts[i] === 'force of static friction') { + if (Math.abs(NumCast(this.dataDoc.review_StaticMagnitude) - this.selectedSolutions[i]) > epsilon) { + error = true; + } + } else if (this.selectedQuestion.answerParts[i] === 'angle of static friction') { + if (Math.abs(NumCast(this.dataDoc.review_StaticAngle) - this.selectedSolutions[i]) > epsilon) { + error = true; + } + } else if (this.selectedQuestion.answerParts[i] === 'coefficient of static friction') { + if (Math.abs(NumCast(this.dataDoc.coefficientOfStaticFriction) - this.selectedSolutions[i]) > epsilon) { + error = true; + } + } else if (this.selectedQuestion.answerParts[i] === 'wedge angle') { + if (Math.abs(this.wedgeAngle - this.selectedSolutions[i]) > epsilon) { + error = true; + } + } + } + } + if (showAlert) { + this.dataDoc.simulation_paused = false; + setTimeout(() => (this.dataDoc.simulation_paused = true), 3000); + } + if (this.selectedQuestion.goal === 'noMovement') { + this.dataDoc.noMovement = !error; + } }; - sidebarScreenToLocal = () => new Transform(0, -this.topOfSidebarDoc, 1); - mainContainerXf = () => this.sidebarScreenToLocal().translate(-this.leftScreenOffsetOfMainDocView, 0); - static addDocTabFunc_impl = (docs: Doc | Doc[], location: OpenWhere): boolean => { - const doc = toList(docs).lastElement(); - const whereFields = location.split(':'); - const keyValue = whereFields.includes(OpenWhereMod.keyvalue); - const whereMods = whereFields.length > 1 ? (whereFields[1] as OpenWhereMod) : OpenWhereMod.none; - const panelName = whereFields.length > 1 ? whereFields.lastElement() : ''; - if (doc.dockingConfig && !keyValue) return DashboardView.openDashboard(doc); - switch (whereFields[0]) { - case OpenWhere.lightbox: return LightboxView.Instance.AddDocTab(doc, location); - case OpenWhere.close: return CollectionDockingView.CloseSplit(doc, whereMods); - case OpenWhere.toggle: return CollectionDockingView.ToggleSplit(doc, whereMods, undefined, TabDocView.DontSelectOnActivate); // bcz: hack! mark the toggle so that it won't be selected on activation- this is needed so that the backlinks menu can toggle views of targets on and off without selecting them - case OpenWhere.replace: return CollectionDockingView.ReplaceTab(doc, whereMods, undefined, panelName); - case OpenWhere.add:default:return CollectionDockingView.AddSplit(doc, whereMods, undefined, undefined, keyValue); - } // prettier-ignore + // Reset all review values to default + resetReviewValuesToDefault = () => { + this.dataDoc.review_GravityMagnitude = 0; + this.dataDoc.review_GravityAngle = 0; + this.dataDoc.review_NormalMagnitude = 0; + this.dataDoc.review_NormalAngle = 0; + this.dataDoc.review_StaticMagnitude = 0; + this.dataDoc.review_StaticAngle = 0; + this.dataDoc.coefficientOfKineticFriction = 0; + this.dataDoc.simulation_paused = true; }; - @computed get flyout() { - return !this._leftMenuFlyoutWidth ? ( -
- {this.docButtons} -
- ) : ( -
-
- -
- {this.docButtons} -
- ); - } + // In review mode, reset problem variables and generate a new question + generateNewQuestion = () => { + this.resetReviewValuesToDefault(); - @computed get leftMenuPanel() { - return ( -
- -
- ); - } + const vars: number[] = []; + let question: QuestionTemplate = questions.inclinePlane[0]; - @action - selectMenu = (button: Doc) => { - const title = StrCast(button[DocData].title); - const willOpen = !this._leftMenuFlyoutWidth || this._panelContent !== title; - this.closeFlyout(); - if (willOpen) { - switch ((this._panelContent = title)) { - case 'Settings': - SettingsManager.Instance.openMgr(); - break; - case 'Help': - break; - default: - this.expandFlyout(button); + if (this.simulationType === 'Inclined Plane') { + this.dataDoc.questionNumber = (NumCast(this.dataDoc.questionNumber) + 1) % questions.inclinePlane.length; + question = questions.inclinePlane[NumCast(this.dataDoc.questionNumber)]; + + let coefficient = 0; + let wedge_angle = 0; + + for (let i = 0; i < question.variablesForQuestionSetup.length; i++) { + if (question.variablesForQuestionSetup[i] === 'theta - max 45') { + const randValue = Math.floor(Math.random() * 44 + 1); + vars.push(randValue); + wedge_angle = randValue; + } else if (question.variablesForQuestionSetup[i] === 'coefficient of static friction') { + const randValue = Math.round(Math.random() * 1000) / 1000; + vars.push(randValue); + coefficient = randValue; + } } + this.dataDoc.wedge_angle = wedge_angle; + this.changeWedgeBasedOnNewAngle(wedge_angle); + this.dataDoc.coefficientOfStaticFriction = coefficient; + this.dataDoc.review_Coefficient = coefficient; } - return true; + let q = ''; + for (let i = 0; i < question.questionSetup.length; i++) { + q += question.questionSetup[i]; + if (i !== question.questionSetup.length - 1) { + q += vars[i]; + if (question.variablesForQuestionSetup[i].includes('theta')) { + q += ' degree (≈' + Math.round((1000 * (vars[i] * Math.PI)) / 180) / 1000 + ' rad)'; + } + } + } + this.dataDoc.questionVariables = new List(vars); + this.dataDoc.selectedQuestion = JSON.stringify(question); + this.dataDoc.questionPartOne = q; + this.dataDoc.questionPartTwo = question.question; + this.dataDoc.answers = new List(this.getAnswersToQuestion(question, vars)); + // this.dataDoc.simulation_reset = (!this.dataDoc.simulation_reset); }; - @computed get mainInnerContent() { - const leftMenuFlyoutWidth = this._leftMenuFlyoutWidth + this.leftMenuWidth(); - const width = this.propertiesWidth() + leftMenuFlyoutWidth; - return ( - <> - {this._hideUI ? null : this.leftMenuPanel} -
- {this.flyout} -
- -
-
- {this.dockingContent} + // Default setup for uniform circular motion simulation + @action + setupCircular = (value: number) => { + this.dataDoc.simulation_showComponentForces = false; + this.dataDoc.mass1_velocityYstart = 0; + this.dataDoc.mass1_velocityXstart = value; + const xPos = (this.xMax + this.xMin) / 2 - this.mass1Radius; + const yPos = (this.yMax + this.yMin) / 2 + this.circularMotionRadius - this.mass1Radius; + this.dataDoc.mass1_positionYstart = yPos; + this.dataDoc.mass1_positionXstart = xPos; + const tensionForce: IForce = { + description: 'Centripetal Force', + magnitude: (this.dataDoc.mass1_velocityXstart ** 2 * this.mass1) / this.circularMotionRadius, + directionInDegrees: 90, + }; + this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce]); + this.dataDoc.mass1_forcesStart = JSON.stringify([tensionForce]); + this._simReset++; + }; - {this._hideUI ? null : ( -
- -
- )} -
-
- -
-
-
-
- - ); - } + setupInclinedPlane = () => { + this.changeWedgeBasedOnNewAngle(this.wedgeAngle); + this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1)]); + this.updateForcesWithFriction(NumCast(this.dataDoc.coefficientOfStaticFriction)); + }; - @computed get mainDashboardArea() { - return !this.userDoc ? null : ( -
{ - r && - new _global.ResizeObserver( - action(() => { - this._dashUIWidth = r.getBoundingClientRect().width; - this._dashUIHeight = r.getBoundingClientRect().height; - }) - ).observe(r); - }} - style={{ - color: 'black', - height: `calc(100% - ${this.topOfDashUI + this.topMenuHeight()}px)`, - width: '100%', - }}> - {this.mainInnerContent} -
- ); - } + // Default setup for pendulum simulation + setupPendulum = () => { + const length = (300 * this._props.PanelWidth()) / 1000; + const angle = 30; + const x = length * Math.cos(((90 - angle) * Math.PI) / 180); + const y = length * Math.sin(((90 - angle) * Math.PI) / 180); + const xPos = this.xMax / 2 - x - this.mass1Radius; + const yPos = y - this.mass1Radius - 5; + this.dataDoc.mass1_positionXstart = xPos; + this.dataDoc.mass1_positionYstart = yPos; + const forceOfTension: IForce = { + description: 'Tension', + magnitude: this.mass1 * Math.abs(this.gravity) * Math.sin((60 * Math.PI) / 180), + directionInDegrees: 90 - angle, + }; + const gravityParallel: IForce = { + description: 'Gravity Parallel Component', + magnitude: this.mass1 * Math.abs(this.gravity) * Math.sin(((90 - angle) * Math.PI) / 180), + directionInDegrees: -angle - 90, + }; + const gravityPerpendicular: IForce = { + description: 'Gravity Perpendicular Component', + magnitude: this.mass1 * Math.abs(this.gravity) * Math.cos(((90 - angle) * Math.PI) / 180), + directionInDegrees: -angle, + }; - expandFlyout = action((button: Doc) => { - // bcz: What's going on here!? --- may be fixed now, so commenting out ... - // Chrome(not firefox) seems to have a bug when the flyout expands and there's a zoomed freeform tab. All of the div below the CollectionFreeFormView's main div - // generate the wrong value from getClientRectangle() -- specifically they return an 'x' that is the flyout's width greater than it should be. - // interactively adjusting the flyout fixes the problem. So does programmatically changing the value after a timeout to something *fractionally* different (ie, 1.5, not 1);) - this._leftMenuFlyoutWidth = this._leftMenuFlyoutWidth || 250; - // setTimeout(action(() => (this._leftMenuFlyoutWidth += 0.5))); + this.dataDoc.mass1_componentForces = JSON.stringify([forceOfTension, gravityParallel, gravityPerpendicular]); + this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1)]); + this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1), forceOfTension]); + this.dataDoc.pendulum_angle = this.dataDoc.pendulum_angleStart = 30; + this.dataDoc.pendulum_length = this.dataDoc.pendulum_lengthStart = 300; + }; - this._sidebarContent.proto = DocCast(button.target); - SnappingManager.SetLastPressedBtn(button[Id]); - }); + // Default setup for spring simulation + @action + setupSpring = () => { + this.dataDoc.simulation_showComponentForces = false; + this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1)]); + this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1)]); + this.dataDoc.mass1_positionXstart = this.xMax / 2 - this.mass1Radius; + this.dataDoc.mass1_positionYstart = 200; + this.dataDoc.spring_constant = 0.5; + this.dataDoc.spring_lengthRest = 200; + this.dataDoc.spring_lengthStart = 200; + this._simReset++; + }; - closeFlyout = action(() => { - SnappingManager.SetLastPressedBtn(''); - this._panelContent = 'none'; - this._sidebarContent.proto = undefined; - this._leftMenuFlyoutWidth = 0; - }); + // Default setup for suspension simulation + @action + setupSuspension = () => { + const xPos = (this.xMax + this.xMin) / 2 - this.mass1Radius; + const yPos = this.yMin + 200; + this.dataDoc.mass1_positionYstart = yPos; + this.dataDoc.mass1_positionXstart = xPos; + this.dataDoc.mass1_positionY = this.getDisplayYPos(yPos); + this.dataDoc.mass1_positionX = xPos; + const tensionMag = (this.mass1 * Math.abs(this.gravity)) / (2 * Math.sin(Math.PI / 4)); + const tensionForce1: IForce = { + description: 'Tension', + magnitude: tensionMag, + directionInDegrees: 45, + }; + const tensionForce2: IForce = { + description: 'Tension', + magnitude: tensionMag, + directionInDegrees: 135, + }; + const gravity = this.gravityForce(this.mass1); + this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, gravity]); + this.dataDoc.mass1_forcesStart = JSON.stringify([tensionForce1, tensionForce2, gravity]); + this._simReset++; + }; - remButtonDoc = (docs: Doc | Doc[]) => toList(docs).reduce((flg: boolean, doc) => flg && !doc.dragOnlyWithinContainer && Doc.RemoveDocFromList(Doc.MyDockedBtns, 'data', doc), true); - moveButtonDoc = (docs: Doc | Doc[], targetCol: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => this.remButtonDoc(docs) && addDocument(docs); - addButtonDoc = (docs: Doc | Doc[]) => toList(docs).reduce((flg: boolean, doc) => flg && Doc.AddDocToList(Doc.MyDockedBtns, 'data', doc), true); + // Default setup for pulley simulation + @action + setupPulley = () => { + this.dataDoc.simulation_showComponentForces = false; + this.dataDoc.mass1_positionYstart = (this.yMax + this.yMin) / 2; + this.dataDoc.mass1_positionXstart = (this.xMin + this.xMax) / 2 - 2 * this.mass1Radius - 5; + this.dataDoc.mass1_positionY = this.getDisplayYPos((this.yMax + this.yMin) / 2); + this.dataDoc.mass1_positionX = (this.xMin + this.xMax) / 2 - 2 * this.mass1Radius - 5; + const a = (-1 * ((this.mass1 - this.mass2) * Math.abs(this.gravity))) / (this.mass1 + this.mass2); + const gravityForce1 = this.gravityForce(this.mass1); + const tensionForce1: IForce = { + description: 'Tension', + magnitude: this.mass1 * a + this.mass1 * Math.abs(this.gravity), + directionInDegrees: 90, + }; + this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce1, tensionForce1]); + this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce1, tensionForce1]); - buttonBarXf = () => { - if (!this._docBtnRef.current) return Transform.Identity(); - const { scale, translateX, translateY } = ClientUtils.GetScreenTransform(this._docBtnRef.current); - return new Transform(-translateX, -translateY, 1 / scale); + const gravityForce2 = this.gravityForce(this.mass2); + const tensionForce2: IForce = { + description: 'Tension', + magnitude: -this.mass2 * a + this.mass2 * Math.abs(this.gravity), + directionInDegrees: 90, + }; + this.dataDoc.mass2_positionYstart = (this.yMax + this.yMin) / 2; + this.dataDoc.mass2_positionXstart = (this.xMin + this.xMax) / 2 + 5; + this.dataDoc.mass2_positionY = this.getDisplayYPos((this.yMax + this.yMin) / 2); + this.dataDoc.mass2_positionX = (this.xMin + this.xMax) / 2 + 5; + this.dataDoc.mass2_forcesUpdated = JSON.stringify([gravityForce2, tensionForce2]); + this.dataDoc.mass2_forcesStart = JSON.stringify([gravityForce2, tensionForce2]); + this._simReset++; }; - @computed get docButtons() { - return !Doc.MyDockedBtns ? null : ( -
- - {['watching', 'recording'].includes(StrCast(this.userDoc?.presentationMode)) ?
{StrCast(this.userDoc?.presentationMode)}
: null} -
- ); - } - @computed get snapLines() { - const dragged = DragManager.docsBeingDragged.lastElement() ?? DocumentView.SelectedDocs().lastElement(); - const dragPar = dragged ? CollectionFreeFormView.from(DocumentView.getViews(dragged).lastElement()) : undefined; - return !dragPar?.layoutDoc.freeform_snapLines ? null : ( -
- - {[ - ...SnappingManager.HorizSnapLines.map((l, i) => ( - // eslint-disable-next-line react/no-array-index-key - - )), - ...SnappingManager.VertSnapLines.map((l, i) => ( - // eslint-disable-next-line react/no-array-index-key - - )), - ]} - -
- ); - } - - @computed get inkResources() { - return ( - - - - - - - - - - - - - - - ); + public static parseJSON(json: string) { + return !json ? [] : (JSON.parse(json) as IForce[]); } - togglePropertiesFlyout = () => { - if (MainView.Instance.propertiesWidth() > 0) { - SnappingManager.SetPropertiesWidth(0); - } else { - SnappingManager.SetPropertiesWidth(300); - } + // Handle force change in review mode + updateReviewModeValues = () => { + const forceOfGravityReview: IForce = { + description: 'Gravity', + magnitude: NumCast(this.dataDoc.review_GravityMagnitude), + directionInDegrees: NumCast(this.dataDoc.review_GravityAngle), + }; + const normalForceReview: IForce = { + description: 'Normal Force', + magnitude: NumCast(this.dataDoc.review_NormalMagnitude), + directionInDegrees: NumCast(this.dataDoc.review_NormalAngle), + }; + const staticFrictionForceReview: IForce = { + description: 'Static Friction Force', + magnitude: NumCast(this.dataDoc.review_StaticMagnitude), + directionInDegrees: NumCast(this.dataDoc.review_StaticAngle), + }; + this.dataDoc.mass1_forcesStart = JSON.stringify([forceOfGravityReview, normalForceReview, staticFrictionForceReview]); + this.dataDoc.mass1_forcesUpdated = JSON.stringify([forceOfGravityReview, normalForceReview, staticFrictionForceReview]); }; - lightboxMaxBorder = [200, 50]; + pause = () => (this.dataDoc.simulation_paused = true); + componentForces1 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass1_componentForces)); + setComponentForces1 = (forces: IForce[]) => (this.dataDoc.mass1_componentForces = JSON.stringify(forces)); + componentForces2 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass2_componentForces)); + setComponentForces2 = (forces: IForce[]) => (this.dataDoc.mass2_componentForces = JSON.stringify(forces)); + startForces1 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass1_forcesStart)); + startForces2 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass2_forcesStart)); + forcesUpdated1 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass1_forcesUpdated)); + setForcesUpdated1 = (forces: IForce[]) => (this.dataDoc.mass1_forcesUpdated = JSON.stringify(forces)); + forcesUpdated2 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass2_forcesUpdated)); + setForcesUpdated2 = (forces: IForce[]) => (this.dataDoc.mass2_forcesUpdated = JSON.stringify(forces)); + setPosition1 = (xPos: number | undefined, yPos: number | undefined) => { + yPos !== undefined && (this.dataDoc.mass1_positionY = Math.round(yPos * 100) / 100); + xPos !== undefined && (this.dataDoc.mass1_positionX = Math.round(xPos * 100) / 100); + }; + setPosition2 = (xPos: number | undefined, yPos: number | undefined) => { + yPos !== undefined && (this.dataDoc.mass2_positionY = Math.round(yPos * 100) / 100); + xPos !== undefined && (this.dataDoc.mass2_positionX = Math.round(xPos * 100) / 100); + }; + setVelocity1 = (xVel: number | undefined, yVel: number | undefined) => { + yVel !== undefined && (this.dataDoc.mass1_velocityY = (-1 * Math.round(yVel * 100)) / 100); + xVel !== undefined && (this.dataDoc.mass1_velocityX = Math.round(xVel * 100) / 100); + }; + setVelocity2 = (xVel: number | undefined, yVel: number | undefined) => { + yVel !== undefined && (this.dataDoc.mass2_velocityY = (-1 * Math.round(yVel * 100)) / 100); + xVel !== undefined && (this.dataDoc.mass2_velocityX = Math.round(xVel * 100) / 100); + }; + setAcceleration1 = (xAccel: number, yAccel: number) => { + this.dataDoc.mass1_accelerationY = yAccel; + this.dataDoc.mass1_accelerationX = xAccel; + }; + setAcceleration2 = (xAccel: number, yAccel: number) => { + this.dataDoc.mass2_accelerationY = yAccel; + this.dataDoc.mass2_accelerationX = xAccel; + }; + setPendulumAngle = (angle: number | undefined, length: number | undefined) => { + angle !== undefined && (this.dataDoc.pendulum_angle = angle); + length !== undefined && (this.dataDoc.pendulum_length = length); + }; + setSpringLength = (length: number) => { + this.dataDoc.spring_lengthStart = length; + }; + resetRequest = () => this._simReset; render() { + const commonWeightProps = { + pause: this.pause, + paused: BoolCast(this.dataDoc.simulation_paused), + panelWidth: this._props.PanelWidth, + panelHeight: this._props.PanelHeight, + resetRequest: this.resetRequest, + xMax: this.xMax, + xMin: this.xMin, + yMax: this.yMax, + yMin: this.yMin, + wallPositions: this.wallPositions, + gravity: Math.abs(this.gravity), + timestepSize: 0.05, + showComponentForces: BoolCast(this.dataDoc.simulation_showComponentForces), + coefficientOfKineticFriction: NumCast(this.dataDoc.coefficientOfKineticFriction), + elasticCollisions: BoolCast(this.dataDoc.elasticCollisions), + simulationMode: this.simulationMode, + noMovement: BoolCast(this.dataDoc.noMovement), + circularMotionRadius: this.circularMotionRadius, + wedgeHeight: this.wedgeHeight, + wedgeWidth: this.wedgeWidth, + springConstant: this.springConstant, + springStartLength: this.springLengthStart, + springRestLength: this.springLengthRest, + setSpringLength: this.setSpringLength, + setPendulumAngle: this.setPendulumAngle, + pendulumAngle: this.pendulumAngle, + pendulumLength: this.pendulumLength, + startPendulumAngle: this.pendulumAngleStart, + startPendulumLength: this.pendulumLengthStart, + radius: this.mass1Radius, + simulationSpeed: NumCast(this.dataDoc.simulation_speed, 2), + showAcceleration: BoolCast(this.dataDoc.simulation_showAcceleration), + showForceMagnitudes: BoolCast(this.dataDoc.simulation_showForceMagnitudes), + showForces: BoolCast(this.dataDoc.simulation_showForces), + showVelocity: BoolCast(this.dataDoc.simulation_showVelocity), + simulationType: this.simulationType, + }; return ( -
- (ele => { - ele.scrollTop = ele.scrollLeft = 0; - })(document.getElementById('root')!) - } - ref={r => { - r && - new _global.ResizeObserver( - action(() => { - this._windowWidth = r.getBoundingClientRect().width; - this._windowHeight = r.getBoundingClientRect().height; - }) - ).observe(r); - }}> - {this.inkResources} - - - - - - - - - - - - - {this._hideUI ? null : } - - {DocButtonState.Instance.LinkEditorDocView ? ( - { - DocButtonState.Instance.LinkEditorDocView = undefined; - })} - docView={DocButtonState.Instance.LinkEditorDocView} - /> - ) : null} - {LinkInfo.Instance?.LinkInfo ? ( - // eslint-disable-next-line react/jsx-props-no-spreading - - ) : null} - {((page: string) => { - // prettier-ignore - switch (page) { - case 'home': return ; - case 'dashboard': - default: return (<> -
- -
- {this.mainDashboardArea} - ); - } - })(Doc.ActivePage)} - - - - - - - - - - - - - {this.snapLines} - - - - +
+
+
+
+
+ {!this.dataDoc.simulation_paused && ( +
+ +
+ )} +
+
+ + {this.simulationType === 'Pulley' && ( + + )} +
+
+ {(this.simulationType === 'One Weight' || this.simulationType === 'Inclined Plane') && + this.wallPositions?.map((element, index) => )} +
+
+
+
this._props.isContentActive() && e.stopPropagation()} + style={{ overflow: 'auto', height: `${Math.max(1, 800 / this._props.PanelWidth()) * 100}%`, transform: `scale(${Math.min(1, this._props.PanelWidth() / 850)})` }}> +
+ + {this.dataDoc.simulation_paused && this.simulationMode !== 'Tutorial' && ( + (this.dataDoc.simulation_paused = false)}> + + + )} + {!this.dataDoc.simulation_paused && this.simulationMode !== 'Tutorial' && ( + (this.dataDoc.simulation_paused = true)}> + + + )} + {this.dataDoc.simulation_paused && this.simulationMode !== 'Tutorial' && ( + this._simReset++)}> + + + )} + +
+ +
+
+ +
+
+ {this.simulationMode === 'Review' && this.simulationType !== 'Inclined Plane' && ( +
+

{this.simulationType} review problems in progress!

+
+
+ )} + {this.simulationMode === 'Review' && this.simulationType === 'Inclined Plane' && ( +
+ {!this.dataDoc.hintDialogueOpen && ( + (this.dataDoc.hintDialogueOpen = true)} + sx={{ + position: 'fixed', + left: this.xMax - 50 + 'px', + top: this.yMin + 14 + 'px', + }}> + + + )} + (this.dataDoc.hintDialogueOpen = false)}> + Hints + + {this.selectedQuestion.hints?.map((hint: any, index: number) => ( +
+ +
+ + + Hint {index + 1}: {hint.description} + + + {hint.content} +
+
+
+ ))} +
+ + + +
+
+
+

{this.questionPartOne}

+

{this.questionPartTwo}

+
+
+ {this.selectedQuestion.answerParts.includes('force of gravity') && ( + Gravity magnitude

} + lowerBound={0} + dataDoc={this.dataDoc} + prop="review_GravityMagnitude" + step={0.1} + unit="N" + upperBound={50} + value={NumCast(this.dataDoc.review_GravityMagnitude)} + showIcon={BoolCast(this.dataDoc.simulation_showIcon)} + correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('force of gravity')]} + labelWidth="7em" + /> + )} + {this.selectedQuestion.answerParts.includes('angle of gravity') && ( + Gravity angle

} + lowerBound={0} + dataDoc={this.dataDoc} + prop="review_GravityAngle" + step={1} + unit="°" + upperBound={360} + value={NumCast(this.dataDoc.review_GravityAngle)} + radianEquivalent + showIcon={BoolCast(this.dataDoc.simulation_showIcon)} + correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('angle of gravity')]} + labelWidth="7em" + /> + )} + {this.selectedQuestion.answerParts.includes('normal force') && ( + Normal force magnitude

} + lowerBound={0} + dataDoc={this.dataDoc} + prop="review_NormalMagnitude" + step={0.1} + unit="N" + upperBound={50} + value={NumCast(this.dataDoc.review_NormalMagnitude)} + showIcon={BoolCast(this.dataDoc.simulation_showIcon)} + correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('normal force')]} + labelWidth="7em" + /> + )} + {this.selectedQuestion.answerParts.includes('angle of normal force') && ( + Normal force angle

} + lowerBound={0} + dataDoc={this.dataDoc} + prop="review_NormalAngle" + step={1} + unit="°" + upperBound={360} + value={NumCast(this.dataDoc.review_NormalAngle)} + radianEquivalent + showIcon={BoolCast(this.dataDoc.simulation_showIcon)} + correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('angle of normal force')]} + labelWidth="7em" + /> + )} + {this.selectedQuestion.answerParts.includes('force of static friction') && ( + Static friction magnitude

} + lowerBound={0} + dataDoc={this.dataDoc} + prop="review_StaticMagnitude" + step={0.1} + unit="N" + upperBound={50} + value={NumCast(this.dataDoc.review_StaticMagnitude)} + showIcon={BoolCast(this.dataDoc.simulation_showIcon)} + correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('force of static friction')]} + labelWidth="7em" + /> + )} + {this.selectedQuestion.answerParts.includes('angle of static friction') && ( + Static friction angle

} + lowerBound={0} + dataDoc={this.dataDoc} + prop="review_StaticAngle" + step={1} + unit="°" + upperBound={360} + value={NumCast(this.dataDoc.review_StaticAngle)} + radianEquivalent + showIcon={BoolCast(this.dataDoc.simulation_showIcon)} + correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('angle of static friction')]} + labelWidth="7em" + /> + )} + {this.selectedQuestion.answerParts.includes('coefficient of static friction') && ( + + μs + + } + lowerBound={0} + dataDoc={this.dataDoc} + prop="coefficientOfStaticFriction" + step={0.1} + unit="" + upperBound={1} + value={NumCast(this.dataDoc.coefficientOfStaticFriction)} + effect={this.updateReviewForcesBasedOnCoefficient} + showIcon={BoolCast(this.dataDoc.simulation_showIcon)} + correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('coefficient of static friction')]} + /> + )} + {this.selectedQuestion.answerParts.includes('wedge angle') && ( + θ} + lowerBound={0} + dataDoc={this.dataDoc} + prop="wedge_angle" + step={1} + unit="°" + upperBound={49} + value={this.wedgeAngle} + effect={(val: number) => { + this.changeWedgeBasedOnNewAngle(val); + this.updateReviewForcesBasedOnAngle(val); + }} + radianEquivalent + showIcon={BoolCast(this.dataDoc.simulation_showIcon)} + correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('wedge angle')]} + /> + )} +
+
+
+ )} + {this.simulationMode === 'Tutorial' && ( +
+
+

Problem

+

{this.tutorial.question}

+
+
+ { + let step = NumCast(this.dataDoc.tutorial_stepNumber) - 1; + step = Math.max(step, 0); + step = Math.min(step, this.tutorial.steps.length - 1); + this.dataDoc.tutorial_stepNumber = step; + this.dataDoc.mass1_forcesStart = JSON.stringify(this.tutorial.steps[step].forces); + this.dataDoc.mass1_forcesUpdated = JSON.stringify(this.tutorial.steps[step].forces); + this.dataDoc.simulation_showForceMagnitudes = this.tutorial.steps[step].showMagnitude; + }} + disabled={this.dataDoc.tutorial_stepNumber === 0}> + + +
+

+ Step {NumCast(this.dataDoc.tutorial_stepNumber) + 1}: {this.tutorial.steps[NumCast(this.dataDoc.tutorial_stepNumber)].description} +

+

{this.tutorial.steps[NumCast(this.dataDoc.tutorial_stepNumber)].content}

+
+ { + let step = NumCast(this.dataDoc.tutorial_stepNumber) + 1; + step = Math.max(step, 0); + step = Math.min(step, this.tutorial.steps.length - 1); + this.dataDoc.tutorial_stepNumber = step; + this.dataDoc.mass1_forcesStart = JSON.stringify(this.tutorial.steps[step].forces); + this.dataDoc.mass1_forcesUpdated = JSON.stringify(this.tutorial.steps[step].forces); + this.dataDoc.simulation_showForceMagnitudes = this.tutorial.steps[step].showMagnitude; + }} + disabled={this.dataDoc.tutorial_stepNumber === this.tutorial.steps.length - 1}> + + +
+
+ {(this.simulationType === 'One Weight' || this.simulationType === 'Inclined Plane' || this.simulationType === 'Pendulum') &&

Resources

} + {this.simulationType === 'One Weight' && ( + + )} + {this.simulationType === 'Inclined Plane' && ( + + )} + {this.simulationType === 'Pendulum' && ( + + )} +
+
+ )} + {this.simulationMode === 'Review' && this.simulationType === 'Inclined Plane' && ( +
+

(this.dataDoc.simulation_mode = 'Tutorial')}> + {' '} + Go to walkthrough{' '} +

+
+ + +
+
+ )} + {this.simulationMode === 'Freeform' && ( +
+ + + {this.simulationType === 'One Weight' && ( + (this.dataDoc.elasticCollisions = !this.dataDoc.elasticCollisions)} />} + label="Make collisions elastic" + labelPlacement="start" + /> + )} + (this.dataDoc.simulation_showForces = !this.dataDoc.simulation_showForces)} />} + label="Show force vectors" + labelPlacement="start" + /> + {(this.simulationType === 'Inclined Plane' || this.simulationType === 'Pendulum') && ( + (this.dataDoc.simulation_showComponentForces = !this.dataDoc.simulation_showComponentForces)} />} + label="Show component force vectors" + labelPlacement="start" + /> + )} + (this.dataDoc.simulation_showAcceleration = !this.dataDoc.simulation_showAcceleration)} />} + label="Show acceleration vector" + labelPlacement="start" + /> + (this.dataDoc.simulation_showVelocity = !this.dataDoc.simulation_showVelocity)} />} + label="Show velocity vector" + labelPlacement="start" + /> + Speed} lowerBound={1} dataDoc={this.dataDoc} prop="simulation_speed" step={1} unit="x" upperBound={10} value={NumCast(this.dataDoc.simulation_speed, 2)} labelWidth="5em" /> + {this.dataDoc.simulation_paused && this.simulationType !== 'Circular Motion' && ( + Gravity} + lowerBound={-30} + dataDoc={this.dataDoc} + prop="gravity" + step={0.01} + unit="m/s2" + upperBound={0} + value={NumCast(this.dataDoc.simulation_gravity, -9.81)} + effect={(val: number) => this.setupSimulation()} + labelWidth="5em" + /> + )} + {this.dataDoc.simulation_paused && this.simulationType !== 'Pulley' && ( + Mass} + lowerBound={1} + dataDoc={this.dataDoc} + prop="mass1" + step={0.1} + unit="kg" + upperBound={5} + value={this.mass1 ?? 1} + effect={(val: number) => this.setupSimulation()} + labelWidth="5em" + /> + )} + {this.dataDoc.simulation_paused && this.simulationType === 'Pulley' && ( + Red mass} + lowerBound={1} + dataDoc={this.dataDoc} + prop="mass1" + step={0.1} + unit="kg" + upperBound={5} + value={this.mass1 ?? 1} + effect={(val: number) => this.setupSimulation()} + labelWidth="5em" + /> + )} + {this.dataDoc.simulation_paused && this.simulationType === 'Pulley' && ( + Blue mass} + lowerBound={1} + dataDoc={this.dataDoc} + prop="mass2" + step={0.1} + unit="kg" + upperBound={5} + value={this.mass2 ?? 1} + effect={(val: number) => this.setupSimulation()} + labelWidth="5em" + /> + )} + {this.dataDoc.simulation_paused && this.simulationType === 'Circular Motion' && ( + Rod length} + lowerBound={100} + dataDoc={this.dataDoc} + prop="circularMotionRadius" + step={5} + unit="m" + upperBound={250} + value={this.circularMotionRadius} + effect={(val: number) => this.setupSimulation()} + labelWidth="5em" + /> + )} + + + {this.simulationType === 'Spring' && this.dataDoc.simulation_paused && ( +
+ Spring stiffness} + lowerBound={0.1} + dataDoc={this.dataDoc} + prop="spring_constant" + step={1} + unit="N/m" + upperBound={500} + value={this.springConstant} + effect={action(() => this._simReset++)} + radianEquivalent={false} + mode="Freeform" + labelWidth="7em" + /> + Rest length} + lowerBound={10} + dataDoc={this.dataDoc} + prop="spring_lengthRest" + step={100} + unit="" + upperBound={500} + value={this.springLengthRest} + effect={action(() => this._simReset++)} + radianEquivalent={false} + mode="Freeform" + labelWidth="7em" + /> + Starting displacement} + lowerBound={-(this.springLengthRest - 10)} + dataDoc={this.dataDoc} + prop="" + step={10} + unit="" + upperBound={this.springLengthRest} + value={this.springLengthStart - this.springLengthRest} + effect={action((val: number) => { + this.dataDoc.mass1_positionYstart = this.springLengthRest + val; + this.dataDoc.spring_lengthStart = this.springLengthRest + val; + this._simReset++; + })} + radianEquivalent={false} + mode="Freeform" + labelWidth="7em" + /> +
+ )} + {this.simulationType === 'Inclined Plane' && this.dataDoc.simulation_paused && ( +
+ θ} + lowerBound={0} + dataDoc={this.dataDoc} + prop="wedge_angle" + step={1} + unit="°" + upperBound={49} + value={this.wedgeAngle} + effect={action((val: number) => { + this.changeWedgeBasedOnNewAngle(val); + this._simReset++; + })} + radianEquivalent + mode="Freeform" + labelWidth="2em" + /> + + μs + + } + lowerBound={0} + dataDoc={this.dataDoc} + prop="coefficientOfStaticFriction" + step={0.1} + unit="" + upperBound={1} + value={NumCast(this.dataDoc.coefficientOfStaticFriction) ?? 0} + effect={action((val: number) => { + this.updateForcesWithFriction(val); + if (val < NumCast(this.dataDoc.coefficientOfKineticFriction)) { + this.dataDoc.soefficientOfKineticFriction = val; + } + this._simReset++; + })} + mode="Freeform" + labelWidth="2em" + /> + + μk + + } + lowerBound={0} + dataDoc={this.dataDoc} + prop="coefficientOfKineticFriction" + step={0.1} + unit="" + upperBound={NumCast(this.dataDoc.coefficientOfStaticFriction)} + value={NumCast(this.dataDoc.coefficientOfKineticFriction) ?? 0} + effect={action(() => this._simReset++)} + mode="Freeform" + labelWidth="2em" + /> +
+ )} + {this.simulationType === 'Inclined Plane' && !this.dataDoc.simulation_paused && ( + + <> + θ: {Math.round(this.wedgeAngle * 100) / 100}° ≈ {Math.round(((this.wedgeAngle * Math.PI) / 180) * 100) / 100} rad +
+ μ s: {this.dataDoc.coefficientOfStaticFriction} +
+ μ k: {this.dataDoc.coefficientOfKineticFriction} + +
+ )} + {this.simulationType === 'Pendulum' && !this.dataDoc.simulation_paused && ( + + θ: {Math.round(this.pendulumAngle * 100) / 100}° ≈ {Math.round(((this.pendulumAngle * Math.PI) / 180) * 100) / 100} rad + + )} + {this.simulationType === 'Pendulum' && this.dataDoc.simulation_paused && ( +
+ Angle} + lowerBound={0} + dataDoc={this.dataDoc} + prop="pendulum_angle" + step={1} + unit="°" + upperBound={59} + value={NumCast(this.dataDoc.pendulum_angle, 30)} + effect={action(value => { + this.dataDoc.pendulum_angleStart = value; + this.dataDoc.pendulum_lengthStart = this.dataDoc.pendulum_length; + if (this.simulationType === 'Pendulum') { + const mag = this.mass1 * Math.abs(this.gravity) * Math.cos((value * Math.PI) / 180); + + const forceOfTension: IForce = { + description: 'Tension', + magnitude: mag, + directionInDegrees: 90 - value, + }; + const gravityParallel: IForce = { + description: 'Gravity Parallel Component', + magnitude: Math.abs(this.gravity) * Math.cos((value * Math.PI) / 180), + directionInDegrees: 270 - value, + }; + const gravityPerpendicular: IForce = { + description: 'Gravity Perpendicular Component', + magnitude: Math.abs(this.gravity) * Math.sin((value * Math.PI) / 180), + directionInDegrees: -value, + }; + + const length = this.pendulumLength; + const x = length * Math.cos(((90 - value) * Math.PI) / 180); + const y = length * Math.sin(((90 - value) * Math.PI) / 180); + const xPos = this.xMax / 2 - x - NumCast(this.dataDoc.radius); + const yPos = y - NumCast(this.dataDoc.radius) - 5; + this.dataDoc.mass1_positionXstart = xPos; + this.dataDoc.mass1_positionYstart = yPos; + + this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1), forceOfTension]); + this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1), forceOfTension]); + this.dataDoc.mass1_componentForces = JSON.stringify([forceOfTension, gravityParallel, gravityPerpendicular]); + this._simReset++; + } + })} + radianEquivalent + mode="Freeform" + labelWidth="5em" + /> + Rod length} + lowerBound={0} + dataDoc={this.dataDoc} + prop="pendulum_length" + step={1} + unit="m" + upperBound={400} + value={Math.round(this.pendulumLength)} + effect={action(value => { + if (this.simulationType === 'Pendulum') { + this.dataDoc.pendulum_angleStart = this.pendulumAngle; + this.dataDoc.pendulum_lengthStart = value; + this._simReset++; + } + })} + radianEquivalent={false} + mode="Freeform" + labelWidth="5em" + /> +
+ )} +
+ )} +
+ {this.simulationMode === 'Freeform' && ( + + + + + + + + + + {(!this.dataDoc.simulation_paused || this.simulationType === 'Inclined Plane' || this.simulationType === 'Circular Motion' || this.simulationType === 'Pulley') && ( + + )}{' '} + {this.dataDoc.simulation_paused && this.simulationType !== 'Inclined Plane' && this.simulationType !== 'Circular Motion' && this.simulationType !== 'Pulley' && ( + + )}{' '} + {(!this.dataDoc.simulation_paused || this.simulationType === 'Inclined Plane' || this.simulationType === 'Circular Motion' || this.simulationType === 'Pulley') && ( + + )}{' '} + {this.dataDoc.simulation_paused && this.simulationType !== 'Inclined Plane' && this.simulationType !== 'Circular Motion' && this.simulationType !== 'Pulley' && ( + + )}{' '} + + + + {(!this.dataDoc.simulation_paused || (this.simulationType !== 'One Weight' && this.simulationType !== 'Circular Motion')) && ( + + )}{' '} + {this.dataDoc.simulation_paused && (this.simulationType === 'One Weight' || this.simulationType === 'Circular Motion') && ( + + )}{' '} + {(!this.dataDoc.simulation_paused || this.simulationType !== 'One Weight') && }{' '} + {this.dataDoc.simulation_paused && this.simulationType === 'One Weight' && ( + + )}{' '} + + + + + + + + + + + + +
{this.simulationType === 'Pulley' ? 'Red Weight' : ''}XY
{ + // window.open( + // "https://www.khanacademy.org/science/physics/two-dimensional-motion" + // ); + // }} + > + Position + {this.dataDoc.mass1_positionX + ''} m + { + this.dataDoc.mass1_xChange = value; + if (this.simulationType === 'Suspension') { + const x1rod = (this.xMax + this.xMin) / 2 - this.radius - this.yMin - 200; + const x2rod = (this.xMax + this.xMin) / 2 + this.yMin + 200 + this.radius; + const deltaX1 = value + this.radius - x1rod; + const deltaX2 = x2rod - (value + this.radius); + const deltaY = this.getYPosFromDisplay(NumCast(this.dataDoc.mass1_positionY)) + this.radius; + let dir1T = Math.PI - Math.atan(deltaY / deltaX1); + let dir2T = Math.atan(deltaY / deltaX2); + const tensionMag2 = (this.mass1 * Math.abs(this.gravity)) / ((-Math.cos(dir2T) / Math.cos(dir1T)) * Math.sin(dir1T) + Math.sin(dir2T)); + const tensionMag1 = (-tensionMag2 * Math.cos(dir2T)) / Math.cos(dir1T); + dir1T = (dir1T * 180) / Math.PI; + dir2T = (dir2T * 180) / Math.PI; + const tensionForce1: IForce = { + description: 'Tension', + magnitude: tensionMag1, + directionInDegrees: dir1T, + }; + const tensionForce2: IForce = { + description: 'Tension', + magnitude: tensionMag2, + directionInDegrees: dir2T, + }; + const gravity = this.gravityForce(this.mass1); + this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, gravity]); + } + }} + small + mode="Freeform" + /> + {`${NumCast(this.dataDoc.mass1_positionY)} m`} + { + this.dataDoc.mass1_yChange = value; + if (this.simulationType === 'Suspension') { + const x1rod = (this.xMax + this.xMin) / 2 - this.radius - this.yMin - 200; + const x2rod = (this.xMax + this.xMin) / 2 + this.yMin + 200 + this.radius; + const deltaX1 = NumCast(this.dataDoc.mass1_positionX) + this.radius - x1rod; + const deltaX2 = x2rod - (NumCast(this.dataDoc.mass1_positionX) + this.radius); + const deltaY = this.getYPosFromDisplay(value) + this.radius; + let dir1T = Math.PI - Math.atan(deltaY / deltaX1); + let dir2T = Math.atan(deltaY / deltaX2); + const tensionMag2 = (this.mass1 * Math.abs(this.gravity)) / ((-Math.cos(dir2T) / Math.cos(dir1T)) * Math.sin(dir1T) + Math.sin(dir2T)); + const tensionMag1 = (-tensionMag2 * Math.cos(dir2T)) / Math.cos(dir1T); + dir1T = (dir1T * 180) / Math.PI; + dir2T = (dir2T * 180) / Math.PI; + const tensionForce1: IForce = { + description: 'Tension', + magnitude: tensionMag1, + directionInDegrees: dir1T, + }; + const tensionForce2: IForce = { + description: 'Tension', + magnitude: tensionMag2, + directionInDegrees: dir2T, + }; + const gravity = this.gravityForce(this.mass1); + this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, gravity]); + } + }} + small + mode="Freeform" + /> +
{ + // window.open( + // "https://www.khanacademy.org/science/physics/two-dimensional-motion" + // ); + // }} + > + Velocity + {`${NumCast(this.dataDoc.mass1_velocityX)} m/s`} + { + this.dataDoc.mass1_velocityXstart = value; + this._simReset++; + })} + small + mode="Freeform" + /> + {this.dataDoc.mass1_velocityY + ''} m/s + { + this.dataDoc.mass1_velocityYstart = -value; + }} + small + mode="Freeform" + /> +
{ + // window.open( + // "https://www.khanacademy.org/science/physics/two-dimensional-motion" + // ); + // }} + > + Acceleration + + {this.dataDoc.mass1_accelerationX + ''} m/s2 + + {this.dataDoc.mass1_accelerationY + ''} m/s2 +
+ Momentum + {Math.round(NumCast(this.dataDoc.mass1_velocityX) * this.mass1 * 10) / 10} kg*m/s{Math.round(NumCast(this.dataDoc.mass1_velocityY) * this.mass1 * 10) / 10} kg*m/s
+ )} + {this.simulationMode === 'Freeform' && this.simulationType === 'Pulley' && ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Blue WeightXY
+ Position + {`${this.dataDoc.mass2_positionX} m`}{`${this.dataDoc.mass2_positionY} m`}
+ Velocity + {`${this.dataDoc.mass2_positionX} m/s`}{`${this.dataDoc.mass2_positionY} m/s`}
+ Acceleration + + {this.dataDoc.mass2_accelerationX + ''} m/s2 + + {this.dataDoc.mass2_accelerationY + ''} m/s2 +
+ Momentum + {Math.round(NumCast(this.dataDoc.mass2_velocityX) * this.mass1 * 10) / 10} kg*m/s{Math.round(NumCast(this.dataDoc.mass2_velocityY) * this.mass1 * 10) / 10} kg*m/s
+ )} +
+ {this.simulationType !== 'Pendulum' && this.simulationType !== 'Spring' && ( +
+

Kinematic Equations

+
    +
  • + Position: x1=x0+v0t+ + 1⁄ + 2at + 2 +
  • +
  • + Velocity: v1=v0+at +
  • +
  • Acceleration: a = F/m
  • +
+
+ )} + {this.simulationType === 'Spring' && ( +
+

Harmonic Motion Equations: Spring

+
    +
  • + Spring force: Fs=kd +
  • +
  • + Spring period: Ts=2π√m⁄ + k +
  • +
  • Equilibrium displacement for vertical spring: d = mg/k
  • +
  • + Elastic potential energy: Us=1⁄ + 2kd2 +
  • +
      +
    • Maximum when system is at maximum displacement, 0 when system is at 0 displacement
    • +
    +
  • + Translational kinetic energy: K=1⁄ + 2mv2 +
  • +
      +
    • Maximum when system is at maximum/minimum velocity (at 0 displacement), 0 when velocity is 0 (at maximum displacement)
    • +
    +
+
+ )} + {this.simulationType === 'Pendulum' && ( +
+

Harmonic Motion Equations: Pendulum

+
    +
  • + Pendulum period: Tp=2π√l⁄ + g +
  • +
+
+ )} +
+
+
+ + + + + + + + + +

+ {this.simulationType === 'Circular Motion' ? 'Z' : 'Y'} +

+

+ X +

+
); } } -// eslint-disable-next-line prefer-arrow-callback -ScriptingGlobals.add(function selectMainMenu(doc: Doc) { - MainView.Instance.selectMenu(doc); +Docs.Prototypes.TemplateMap.set(DocumentType.SIMULATION, { + data: '', + layout: { view: PhysicsSimulationBox, dataField: 'data' }, + options: { acl: '', _width: 1000, _height: 800, mass1: '', mass2: '', layout_nativeDimEditable: true, position: '', acceleration: '', pendulum: '', spring: '', wedge: '', simulation: '', review: '', systemIcon: 'BsShareFill' }, }); -// eslint-disable-next-line prefer-arrow-callback -ScriptingGlobals.add(function createNewPresentation() { - return MainView.Instance.createNewPresentation(); -}, 'creates a new presentation when called'); -// eslint-disable-next-line prefer-arrow-callback -ScriptingGlobals.add(function openPresentation(pres: Doc) { - return MainView.Instance.openPresentation(pres); -}, 'creates a new presentation when called'); -// eslint-disable-next-line prefer-arrow-callback -ScriptingGlobals.add(function createNewFolder() { - return MainView.Instance.createNewFolder(); -}, 'creates a new folder in myFiles when called'); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index b8257ff31..467191735 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -7,7 +7,6 @@ import { action, computed, IReactionDisposer, makeObservable, observable, reacti import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; -import { TbAlpha } from 'react-icons/tb'; import { ClientUtils, DashColor, lightOrDark, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, UpdateIcon } from '../../../../ClientUtils'; import { DateField } from '../../../../fields/DateField'; import { ActiveEraserWidth, ActiveInkWidth, Doc, DocListCast, Field, FieldType, Opt, SetActiveInkColor, SetActiveInkWidth } from '../../../../fields/Doc'; @@ -56,7 +55,7 @@ import { CollectionFreeFormPannableContents } from './CollectionFreeFormPannable import { CollectionFreeFormRemoteCursors } from './CollectionFreeFormRemoteCursors'; import './CollectionFreeFormView.scss'; import { MarqueeView } from './MarqueeView'; -import { SmartDrawHandler } from './SmartDrawHandler'; +import { DrawingOptions, SmartDrawHandler } from '../../smartdraw/SmartDrawHandler'; @observer class CollectionFreeFormOverlayView extends React.Component<{ elements: () => ViewDefResult[] }> { @@ -120,6 +119,7 @@ export class CollectionFreeFormView extends CollectionSubView(); @observable _marqueeViewRef = React.createRef(); @@ -514,7 +514,7 @@ export class CollectionFreeFormView extends CollectionSubView { this._deleteList.lastElement()?._props.removeDocument?.(this._deleteList.map(ink => ink.Document)); @@ -607,12 +608,12 @@ export class CollectionFreeFormView extends CollectionSubView { + e.stopImmediatePropagation(); const currPoint = { X: e.clientX, Y: e.clientY }; this._eraserPts.push([currPoint.X, currPoint.Y]); this._eraserPts = this._eraserPts.slice(Math.max(0, this._eraserPts.length - 5)); if (Doc.ActiveTool === InkTool.RadiusEraser) { const strokeMap: Map = this.getRadiusEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint); - strokeMap.forEach((intersects, stroke) => { if (!this._deleteList.includes(stroke)) { this._deleteList.push(stroke); @@ -682,9 +683,9 @@ export class CollectionFreeFormView extends CollectionSubView { + e.preventDefault(); + e.stopImmediatePropagation(); this.erase(e, [0, 0]); - e.stopPropagation(); - return false; }; /** @@ -696,32 +697,32 @@ export class CollectionFreeFormView extends CollectionSubView { - const currPoint = { X: e.clientX, Y: e.clientY }; - this._eraserPts.push([currPoint.X, currPoint.Y]); - this._eraserPts = this._eraserPts.slice(Math.max(0, this._eraserPts.length - 5)); - const strokeMap: Map = this.getRadiusEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint); - - strokeMap.forEach((intersects, stroke) => { - if (!this._deleteList.includes(stroke)) { - this._deleteList.push(stroke); - SetActiveInkWidth(StrCast(stroke.Document.stroke_width?.toString()) || '1'); - SetActiveInkColor(StrCast(stroke.Document.color?.toString()) || 'black'); - const segments = this.radiusErase(stroke, intersects.sort()); - segments?.forEach(segment => - this.forceStrokeGesture( - e, - Gestures.Stroke, - segment.reduce((data, curve) => [...data, ...curve.points.map(p => stroke.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]) - ) - ); - } - stroke.layoutDoc.opacity = 0; - stroke.layoutDoc.dontIntersect = true; - }); - return false; - }; + // @action + // onRadiusEraserMove = (e: PointerEvent, down: number[], delta: number[]) => { + // const currPoint = { X: e.clientX, Y: e.clientY }; + // this._eraserPts.push([currPoint.X, currPoint.Y]); + // this._eraserPts = this._eraserPts.slice(Math.max(0, this._eraserPts.length - 5)); + // const strokeMap: Map = this.getRadiusEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint); + + // strokeMap.forEach((intersects, stroke) => { + // if (!this._deleteList.includes(stroke)) { + // this._deleteList.push(stroke); + // SetActiveInkWidth(StrCast(stroke.Document.stroke_width?.toString()) || '1'); + // SetActiveInkColor(StrCast(stroke.Document.color?.toString()) || 'black'); + // const segments = this.radiusErase(stroke, intersects.sort()); + // segments?.forEach(segment => + // this.forceStrokeGesture( + // e, + // Gestures.Stroke, + // segment.reduce((data, curve) => [...data, ...curve.points.map(p => stroke.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]) + // ) + // ); + // } + // stroke.layoutDoc.opacity = 0; + // stroke.layoutDoc.dontIntersect = true; + // }); + // return false; + // }; forceStrokeGesture = (e: PointerEvent, gesture: Gestures, points: InkData, text?: any) => { this.onGesture(e, new GestureUtils.GestureEvent(gesture, points, InkField.getBounds(points), text)); @@ -1263,15 +1264,14 @@ export class CollectionFreeFormView extends CollectionSubView { - SmartDrawHandler.Instance.displaySmartDrawHandler(e.pageX, e.pageY, this.createInkStrokes); + showSmartDraw = (e: PointerEvent, doubleTap?: boolean) => { + SmartDrawHandler.Instance.displaySmartDrawHandler(e.pageX, e.pageY, this.createDrawing, this.removeDrawing); }; + _drawing: Doc[] = []; @undoBatch - createInkStrokes = (strokeData: [InkData, string, string][]) => { + createDrawing = (e: React.PointerEvent, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string) => { strokeData.forEach((stroke: [InkData, string, string]) => { - // const points: InkData = FitCurve(inkData, 20) as InkData; - // const allPts = GenerateControlPoints(inkData, alpha); const bounds = InkField.getBounds(stroke[0]); const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; @@ -1288,8 +1288,33 @@ export class CollectionFreeFormView extends CollectionSubView { + this._batch = UndoManager.StartBatch('regenerateDrawing'); + if (doc) { + const docData: Doc = doc[DocData]; + const children = docData.data as unknown as Doc[]; + this._props.removeDocument?.(doc); + this._props.removeDocument?.(children); + } else { + this._props.removeDocument?.(this._drawing); + } + this._drawing = []; }; @action @@ -1995,6 +2020,14 @@ export class CollectionFreeFormView extends CollectionSubView { + this._showDrawingEditor = !this._showDrawingEditor; + this._showDrawingEditor ? SmartDrawHandler.Instance.displayRegenerate(this._downX, this._downY - 10, this.createDrawing, this.removeDrawing) : SmartDrawHandler.Instance.hideRegenerate(); + }), + icon: 'pen-to-square', + }); this._props.renderDepth && optionItems.push({ description: 'Use Background Color as Default', diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index dc15c83c5..23cf487ec 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -36,6 +36,7 @@ import { CollectionFreeFormView } from './CollectionFreeFormView'; import { ImageLabelHandler } from './ImageLabelHandler'; import { MarqueeOptionsMenu } from './MarqueeOptionsMenu'; import './MarqueeView.scss'; +import { collectionOf } from '@turf/turf'; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -426,6 +427,7 @@ export class MarqueeView extends ObservableReactComponent { - static Instance: SmartDrawHandler; - - @observable private _display: boolean = false; - @observable private _pageX: number = 0; - @observable private _pageY: number = 0; - @observable private _yRelativeToTop: boolean = true; - @observable private _isLoading: boolean = false; - @observable private _userInput: string = ''; - @observable private _showOptions: boolean = false; - @observable private _menuIcon: string = 'caret-right'; - @observable private _complexity: number = 5; - @observable private _size: number = 300; - @observable private _autoColor: boolean = true; - @observable private _showRegenerate: boolean = false; - private _addToDocFunc: (strokeList: [InkData, string, string][]) => void = () => {}; - private _lastX: number = 0; - private _lastY: number = 0; - - constructor(props: any) { - super(props); - makeObservable(this); - SmartDrawHandler.Instance = this; - } - - @action - setUserInput = (input: string) => { - this._userInput = input; - }; - - @action - displaySmartDrawHandler = (x: number, y: number, addToDoc: (strokeData: [InkData, string, string][]) => void) => { - this._pageX = x; - this._pageY = y; - this._display = true; - this._addToDocFunc = addToDoc; - }; - - hideSmartDrawHandler = () => { - this._showRegenerate = false; - this._display = false; - this._isLoading = false; - this._showOptions = false; - this._menuIcon = 'caret-right'; - }; - - hideRegenerate = () => { - this._showRegenerate = false; - this._userInput = ''; - this._complexity = 5; - this._size = 300; - this._autoColor = true; - this._isLoading = false; - }; - - toggleMenu = () => { - this._showOptions = !this._showOptions; - this._menuIcon === 'caret-right' ? (this._menuIcon = 'caret-down') : (this._menuIcon = 'caret-right'); - }; - - @action - drawWithGPT = async (e: React.MouseEvent, startPoint: { X: number; Y: number }, input: string, regenerate: boolean = false) => { - if (this._userInput === '') return; - e.stopPropagation(); - this._lastX = startPoint.X; - this._lastY = startPoint.Y; - this._isLoading = true; - this._showOptions = false; - try { - const res = await gptAPICall(`"${input}", "${this._complexity}", "${this._size}"`, GPTCallType.DRAW); - if (!res) { - console.error('GPT call failed'); - return; - } - const svg = res.match(/]*>([\s\S]*?)<\/svg>/g); - if (svg) { - const svgObject = await parse(svg[0]); - const svgStrokes: any = svgObject.children; - const strokeData: [InkData, string, string][] = []; - svgStrokes.forEach((child: any) => { - const convertedBezier: InkData = SVGToBezier(child.name, child.attributes); - strokeData.push([ - convertedBezier.map(point => { - return { X: point.X + startPoint.X - this._size / 1.5, Y: point.Y + startPoint.Y - this._size / 2 }; - }), - this._autoColor ? child.attributes.stroke : undefined, - this._autoColor ? child.attributes.fill : undefined, - ]); - }); - if (regenerate) UndoManager.Undo(); - this._addToDocFunc(strokeData); - } - } catch (err) { - console.error('GPT call failed', err); - } - this.hideSmartDrawHandler(); - this._showRegenerate = true; - }; - - regenerate = (e: React.MouseEvent) => { - this.drawWithGPT(e, { X: this._lastX, Y: this._lastY }, `Regenerate the item "${this._userInput}"`, true); - }; - - render() { - if (this._display) { - return ( -
-
- { - this.hideSmartDrawHandler(); - this.hideRegenerate(); - }} - icon={} - color={SettingsManager.userColor} - style={{ width: '19px' }} - /> - { - this.setUserInput(e.target.value); - }} - placeholder="Enter item to draw" - /> - } - color={SettingsManager.userColor} - style={{ width: '14px' }} - onClick={() => { - this._showOptions = !this._showOptions; - }} - /> -
- {this._showOptions && ( - <> -
-
- Auto color - (this._autoColor = !this._autoColor)} - /> -
-
- Complexity - { - this._complexity = val as number; - }} - valueLabelDisplay="auto" - /> -
-
- Size (in pixels) - { - this._size = val as number; - }} - valueLabelDisplay="auto" - /> -
-
- - )} -
- ); - } else if (this._showRegenerate) { - return ( -
-
- } color={SettingsManager.userColor} style={{ width: '19px' }} /> - : } - color={SettingsManager.userColor} - onClick={e => { - this.regenerate(e); - }} - /> -
-
- ); - } else { - return <>; - } - } -} diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index 7bca1230f..6e24b2931 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -20,15 +20,27 @@ top: 0; left: 0; + .pdfBox-sidebarBtn-container { + display: flex; + flex-direction: row; + position: absolute; + width: 53px; + height: 33px; + right: 5px; + align-items: center; + justify-content: space-between; + z-index: 1; + } + // glr: This should really be the same component as text and PDFs .pdfBox-sidebarBtn { background: $black; height: 25px; width: 25px; - right: 5px; + // right: 5px; color: $white; display: flex; - position: absolute; + // position: absolute; align-items: center; justify-content: center; border-radius: 3px; diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 7a89b143b..8dd48f10f 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -1,6 +1,8 @@ /* eslint-disable jsx-a11y/no-static-element-interactions */ /* eslint-disable jsx-a11y/control-has-associated-label */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { IconButton } from 'browndash-components'; +import { black } from 'colors'; import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as Pdfjs from 'pdfjs-dist'; @@ -503,17 +505,30 @@ export class PDFBox extends ViewBoxAnnotatableComponent() { } @computed get sidebarHandle() { return ( -
this.sidebarBtnDown(e, true)}> - +
+
+ {/* // onPointerDown={e => this.sidebarBtnDown(e, true)} */} + } onPointerDown={e => this.sidebarBtnDown(e, true)} /> +
+
+ } onPointerDown={e => this.sidebarBtnDown(e, true)} /> +
); } diff --git a/src/client/views/smartdraw/DrawingPalette.scss b/src/client/views/smartdraw/DrawingPalette.scss new file mode 100644 index 000000000..0f1152b71 --- /dev/null +++ b/src/client/views/smartdraw/DrawingPalette.scss @@ -0,0 +1,11 @@ +.drawing-palette { + display: grid; + grid-template-columns: auto; + position: absolute; + right: 14px; + width: 170px; + height: 170px; + top: 50px; + border-radius: 5px; + background-color: white; +} diff --git a/src/client/views/smartdraw/DrawingPalette.tsx b/src/client/views/smartdraw/DrawingPalette.tsx new file mode 100644 index 000000000..87a39bc85 --- /dev/null +++ b/src/client/views/smartdraw/DrawingPalette.tsx @@ -0,0 +1,89 @@ +import { computed, makeObservable, observable } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { returnAll, returnFalse, returnOne, returnZero } from '../../../ClientUtils'; +import { Doc, StrListCast } from '../../../fields/Doc'; +import { emptyFunction } from '../../../Utils'; +import { CollectionViewType } from '../../documents/DocumentTypes'; +import { MarqueeView } from '../collections/collectionFreeForm'; +import { CollectionGridView } from '../collections/collectionGrid'; +import { CollectionStackingView } from '../collections/CollectionStackingView'; +import { DocumentView } from '../nodes/DocumentView'; +import { FieldViewProps } from '../nodes/FieldView'; +import { ObservableReactComponent } from '../ObservableReactComponent'; +import './DrawingPalette.scss'; + +@observer +export class DrawingPalette extends ObservableReactComponent<{}> { + @observable private _savedDrawings: Doc[] = []; + @observable _marqueeViewRef = React.createRef(); + private _stackRef = React.createRef(); + + constructor(props: any) { + super(props); + makeObservable(this); + } + + panelWidth = () => 100; + panelHeight = () => 100; + + getCollection = () => { + return this._marqueeViewRef.current?.collection(undefined, false, this._savedDrawings) || new Doc(); + }; + + @computed get savedDrawingAnnos() { + // const savedAnnos = Doc.MyDrawingAnnos; + return ( +
+ {/* */} + {/* */} +
+ ); + } + + render() { + return ( +
+ {/* {this._savedDrawings.map(doc => { + return ; + })} */} + {/* */} + {} + {/* */} + {this.savedDrawingAnnos} +
+ ); + } +} diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx new file mode 100644 index 000000000..6d2cc0593 --- /dev/null +++ b/src/client/views/smartdraw/SmartDrawHandler.tsx @@ -0,0 +1,407 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { action, makeObservable, observable } from 'mobx'; +import { observer } from 'mobx-react'; +import React from 'react'; +import { SettingsManager } from '../../util/SettingsManager'; +import { ObservableReactComponent } from '../ObservableReactComponent'; +import { Button, IconButton } from 'browndash-components'; +import ReactLoading from 'react-loading'; +import { AiOutlineSend } from 'react-icons/ai'; +// import './ImageLabelHandler.scss'; +import { gptAPICall, GPTCallType } from '../../apis/gpt/GPT'; +import { InkData } from '../../../fields/InkField'; +import { SVGToBezier } from '../../util/bezierFit'; +const { parse } = require('svgson'); +import { Slider, Switch } from '@mui/material'; +import { Doc } from '../../../fields/Doc'; +import { DocData } from '../../../fields/DocSymbols'; +import { DocumentView } from '../nodes/DocumentView'; + +export interface DrawingOptions { + text: string; + complexity: number; + size: number; + autoColor: boolean; + x: number; + y: number; +} + +@observer +export class SmartDrawHandler extends ObservableReactComponent<{}> { + static Instance: SmartDrawHandler; + + @observable private _display: boolean = false; + @observable private _pageX: number = 0; + @observable private _pageY: number = 0; + @observable private _yRelativeToTop: boolean = true; + @observable private _isLoading: boolean = false; + @observable private _userInput: string = ''; + @observable private _showOptions: boolean = false; + @observable private _showEditBox: boolean = false; + @observable private _showRegenerate: boolean = false; + @observable private _complexity: number = 5; + @observable private _size: number = 200; + @observable private _autoColor: boolean = true; + @observable private _regenInput: string = ''; + private _addFunc: (e: React.PointerEvent, strokeList: [InkData, string, string][], opts: DrawingOptions, gptRes: string) => void = () => {}; + private _deleteFunc: (doc?: Doc) => void = () => {}; + private _lastInput: DrawingOptions = { text: '', complexity: 5, size: 300, autoColor: true, x: 0, y: 0 }; + private _lastResponse: string = ''; + private _selectedDoc: Doc | undefined = undefined; + + constructor(props: any) { + super(props); + makeObservable(this); + SmartDrawHandler.Instance = this; + } + + @action + setUserInput = (input: string) => { + this._userInput = input; + }; + + @action + setRegenInput = (input: string) => { + this._regenInput = input; + }; + + @action + setShowOptions = () => { + this._showOptions = !this._showOptions; + }; + + @action + setComplexity = (val: number) => { + this._complexity = val; + }; + + @action + setSize = (val: number) => { + this._size = val; + }; + + @action + setAutoColor = () => { + this._autoColor = !this._autoColor; + }; + + @action + displaySmartDrawHandler = (x: number, y: number, addFunc: (e: React.PointerEvent, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string) => void, deleteFunc: (doc?: Doc) => void) => { + this._pageX = x; + this._pageY = y; + this._display = true; + this._addFunc = addFunc; + this._deleteFunc = deleteFunc; + }; + + @action + displayRegenerate = (x: number, y: number, addFunc: (e: React.PointerEvent, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string) => void, deleteFunc: (doc?: Doc) => void) => { + const selectedDoc: Doc = DocumentView.SelectedDocs().lastElement(); + const docData = selectedDoc[DocData]; + this._addFunc = addFunc; + this._deleteFunc = deleteFunc; + this._pageX = x; + this._pageY = y; + this._showRegenerate = true; + this._lastResponse = docData.drawingData as string; + this._lastInput = { text: docData.drawingInput as string, complexity: docData.drawingComplexity as number, size: docData.drawingSize as number, autoColor: docData.drawingColored as boolean, x: this._pageX, y: this._pageY }; + }; + + @action + hideSmartDrawHandler = () => { + this._showRegenerate = false; + this._display = false; + this._isLoading = false; + this._showOptions = false; + this._userInput = ''; + this._complexity = 5; + this._size = 300; + this._autoColor = true; + // this._regenInput = '' + }; + + @action + hideRegenerate = () => { + this._showRegenerate = false; + this._isLoading = false; + this._regenInput = ''; + }; + + _errorOccurredOnce = false; + @action + drawWithGPT = async (e: React.PointerEvent, input: string) => { + if (input === '') return; + this._lastInput = { text: input, complexity: this._complexity, size: this._size, autoColor: this._autoColor, x: e.clientX, y: e.clientY }; + this._isLoading = true; + this._showOptions = false; + try { + const res = await gptAPICall(`"${input}", "${this._complexity}", "${this._size}"`, GPTCallType.DRAW, undefined, true); + if (!res) { + console.error('GPT call failed'); + return; + } + console.log(res); + await this.parseResponse(e, res, { X: e.clientX, Y: e.clientY }, false); + this.hideSmartDrawHandler(); + this._showRegenerate = true; + this._errorOccurredOnce = false; + } catch (err) { + if (this._errorOccurredOnce) { + console.error('GPT call failed', err); + this._errorOccurredOnce = false; + } else { + this._errorOccurredOnce = true; + this.drawWithGPT(e, input); + } + } + this._isLoading = false; + }; + + @action + edit = () => { + this._showEditBox = !this._showEditBox; + }; + + @action + regenerate = async (e: React.PointerEvent) => { + this._isLoading = true; + try { + let res; + if (this._regenInput !== '') { + const prompt: string = `This is your previously generated svg code: ${this._lastResponse} for the user input "${this._lastInput.text}". Please regenerate it with the provided specifications.`; + res = await gptAPICall(`"${this._regenInput}"`, GPTCallType.DRAW, prompt, true); + this._lastInput.text = `${this._lastInput.text} + ${this._regenInput}`; + } else { + res = await gptAPICall(`"${this._lastInput.text}", "${this._lastInput.complexity}", "${this._lastInput.size}"`, GPTCallType.DRAW, undefined, true); + } + if (!res) { + console.error('GPT call failed'); + return; + } + console.log(res); + this.parseResponse(e, res, { X: this._lastInput.x, Y: this._lastInput.y }, true); + } catch (err) { + console.error('GPT call failed', err); + } + this._isLoading = false; + this._regenInput = ''; + this._showEditBox = false; + }; + + @action + parseResponse = async (e: React.PointerEvent, res: string, startPoint: { X: number; Y: number }, regenerate: boolean) => { + const svg = res.match(/]*>([\s\S]*?)<\/svg>/g); + console.log('start point is', startPoint); + if (svg) { + this._lastResponse = svg[0]; + const svgObject = await parse(svg[0]); + const svgStrokes: any = svgObject.children; + const strokeData: [InkData, string, string][] = []; + console.log('autocolor is', this._autoColor); + svgStrokes.forEach((child: any) => { + const convertedBezier: InkData = SVGToBezier(child.name, child.attributes); + strokeData.push([ + convertedBezier.map(point => { + return { X: point.X + startPoint.X - this._size / 1.5, Y: point.Y + startPoint.Y - this._size / 2 }; + }), + (regenerate ? this._lastInput.autoColor : this._autoColor) ? child.attributes.stroke : undefined, + (regenerate ? this._lastInput.autoColor : this._autoColor) ? child.attributes.fill : undefined, + ]); + }); + if (regenerate) { + this._deleteFunc(this._selectedDoc); + } + this._addFunc(e, strokeData, this._lastInput, svg[0]); + } + }; + + render() { + if (this._display) { + return ( +
+
+ { + this.hideSmartDrawHandler(); + this.hideRegenerate(); + }} + icon={} + color={SettingsManager.userColor} + style={{ width: '19px' }} + /> + { + this.setUserInput(e.target.value); + }} + placeholder="Enter item to draw" + /> +
+ {this._showOptions && ( + <> +
+
+ Auto color + +
+
+ Complexity + { + this.setComplexity(val as number); + }} + valueLabelDisplay="auto" + /> +
+
+ Size (in pixels) + { + this.setSize(val as number); + }} + valueLabelDisplay="auto" + /> +
+
+ + )} +
+ ); + } else if (this._showRegenerate) { + return ( +
+
+ : } + color={SettingsManager.userColor} + onClick={e => { + this.regenerate(e as React.PointerEvent); + }} + /> + } color={SettingsManager.userColor} onClick={this.edit} /> + {this._showEditBox && ( +
+ { + this.setRegenInput(e.target.value); + }} + placeholder="Edit instructions" + /> +
+ )} +
+
+ ); + } else { + return <>; + } + } +} diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 4a469dfe2..bc1abd26e 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -276,6 +276,7 @@ export class Doc extends RefField { public static get MyPublishedDocs() { return DocListCast(Doc.ActiveDashboard?.myPublishedDocs).concat(DocListCast(DocCast(Doc.UserDoc().myPublishedDocs)?.data)); } // prettier-ignore public static get MyDashboards() { return DocCast(Doc.UserDoc().myDashboards); } // prettier-ignore public static get MyTemplates() { return DocCast(Doc.UserDoc().myTemplates); } // prettier-ignore + public static get MyDrawingAnnos() { return DocCast(Doc.UserDoc().myDrawingAnnos); } // prettier-ignore public static get MyImports() { return DocCast(Doc.UserDoc().myImports); } // prettier-ignore public static get MyFilesystem() { return DocCast(Doc.UserDoc().myFilesystem); } // prettier-ignore public static get MyTools() { return DocCast(Doc.UserDoc().myTools); } // prettier-ignore -- cgit v1.2.3-70-g09d2 From 3a269cb5120dbad1002c7cb4005776a25556b6e3 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 1 Jul 2024 14:06:34 -0400 Subject: moved active ink settings to DocumentView from Doc. Changed how ink fill color is set based on what is selected. --- src/client/documents/DocFromField.ts | 16 +++++-- src/client/documents/Documents.ts | 15 +------ src/client/views/GestureOverlay.tsx | 12 +++--- .../collectionFreeForm/CollectionFreeFormView.tsx | 23 ++++++++-- src/client/views/global/globalScripts.ts | 39 ++++++++--------- src/client/views/nodes/DocumentView.tsx | 50 ++++++++++++++++++++++ src/fields/Doc.ts | 47 -------------------- 7 files changed, 106 insertions(+), 96 deletions(-) diff --git a/src/client/documents/DocFromField.ts b/src/client/documents/DocFromField.ts index b65bbbdf5..9acb9c225 100644 --- a/src/client/documents/DocFromField.ts +++ b/src/client/documents/DocFromField.ts @@ -1,5 +1,4 @@ import { Doc, DocListCast } from '../../fields/Doc'; -import { InkField } from '../../fields/InkField'; import { List } from '../../fields/List'; import { StrCast } from '../../fields/Types'; import { AudioField, ImageField, PdfField, VideoField } from '../../fields/URLField'; @@ -12,7 +11,17 @@ export function ResetLayoutFieldKey(doc: Doc, fieldKey: string) { doc.layout = StrCast(doc.layout).replace(/={'.*'}/, `={'${fieldKey}'}`); return doc; } -export function DocumentFromField(target: Doc, fieldKey: string, proto?: Doc, options?: DocumentOptions): Doc | undefined { +/** + * Creates a new document based on the type of (and containing the) data in the specified field of an existing document. + * If the field contains a list, then it may be useful to specify a classProto to indicate the type of + * collection Doc that gets created. + * @param target document to retrive field from + * @param fieldKey field key to retrieve + * @param classProto optionally a class proto to set on the new document + * @param options metadata configuration for new document + * @returns + */ +export function DocumentFromField(target: Doc, fieldKey: string, classProto?: Doc, options?: DocumentOptions): Doc | undefined { const field = target[fieldKey]; const resolved = options ?? {}; const nonDocFieldToDoc = () => { @@ -20,12 +29,11 @@ export function DocumentFromField(target: Doc, fieldKey: string, proto?: Doc, op if (field instanceof VideoField) return Docs.Create.VideoDocument(field.url.href, resolved); if (field instanceof PdfField) return Docs.Create.PdfDocument(field.url.href, resolved); if (field instanceof AudioField) return Docs.Create.AudioDocument(field.url.href, resolved); - if (field instanceof InkField) return Docs.Create.InkDocument(field.inkData, resolved); if (field instanceof List && field[0] instanceof Doc) return Docs.Create.StackingDocument(DocListCast(field), resolved); return Docs.Create.TextDocument('', { ...{ _width: 200, _height: 25, _layout_autoHeight: true }, ...resolved }); }; const created = field instanceof Doc ? field : ResetLayoutFieldKey(nonDocFieldToDoc(), fieldKey); created.title = fieldKey; - proto && created.proto && (created.proto = Doc.GetProto(proto)); + classProto && created.proto && (created.proto = classProto); return created; } diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index a67e6b4f6..2dcf8a54c 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -5,7 +5,7 @@ import { reaction } from 'mobx'; import { basename } from 'path'; import { ClientUtils, OmitKeys } from '../../ClientUtils'; import { DateField } from '../../fields/DateField'; -import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, CreateLinkToActiveAudio, Doc, FieldType, Opt, updateCachedAcls } from '../../fields/Doc'; +import { CreateLinkToActiveAudio, Doc, FieldType, Opt, updateCachedAcls } from '../../fields/Doc'; import { Initializing } from '../../fields/DocSymbols'; import { HtmlField } from '../../fields/HtmlField'; import { InkField } from '../../fields/InkField'; @@ -833,18 +833,7 @@ export namespace Docs { return linkDoc; } - export function InkDocument( - points: PointData[], - options: DocumentOptions = {}, - strokeWidth = ActiveInkWidth(), - color = ActiveInkColor(), - strokeBezier = ActiveInkBezierApprox(), - fillColor = ActiveFillColor(), - arrowStart = ActiveArrowStart(), - arrowEnd = ActiveArrowEnd(), - dash = ActiveDash(), - isInkMask = ActiveIsInkMask() - ) { + 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 diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 2f26bdaef..e3e252593 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -4,25 +4,23 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, setupMoveUpEvents } from '../../ClientUtils'; import { emptyFunction } from '../../Utils'; +import { Doc, Opt } from '../../fields/Doc'; +import { InkData, InkField, InkTool } from '../../fields/InkField'; +import { NumCast } from '../../fields/Types'; import { ActiveArrowEnd, ActiveArrowScale, ActiveArrowStart, ActiveDash, - ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, - Doc, - Opt, SetActiveArrowStart, SetActiveDash, SetActiveFillColor, SetActiveInkColor, SetActiveInkWidth, -} from '../../fields/Doc'; -import { InkData, InkField, InkTool } from '../../fields/InkField'; -import { NumCast } from '../../fields/Types'; +} from './nodes/DocumentView'; // import MobileInkOverlay from '../../mobile/MobileInkOverlay'; import { Gestures } from '../../pen-gestures/GestureTypes'; import { GestureUtils } from '../../pen-gestures/GestureUtils'; @@ -32,7 +30,7 @@ import { ScriptingGlobals } from '../util/ScriptingGlobals'; import { Transform } from '../util/Transform'; import './GestureOverlay.scss'; import { ObservableReactComponent } from './ObservableReactComponent'; -import { DocumentView } from './nodes/DocumentView'; +import { ActiveFillColor, DocumentView } from './nodes/DocumentView'; export enum ToolglassTools { InkToText = 'inktotext', diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index b6e1fca77..d611db1f8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -9,7 +9,8 @@ import { computedFn } from 'mobx-utils'; import * as React from 'react'; import { ClientUtils, DashColor, lightOrDark, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, UpdateIcon } from '../../../../ClientUtils'; import { DateField } from '../../../../fields/DateField'; -import { ActiveEraserWidth, ActiveInkWidth, Doc, DocListCast, Field, FieldType, Opt, SetActiveInkColor, SetActiveInkWidth } from '../../../../fields/Doc'; +import { Doc, DocListCast, Field, FieldType, Opt } from '../../../../fields/Doc'; +import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveEraserWidth, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, SetActiveInkColor, SetActiveInkWidth } from '../../nodes/DocumentView'; import { DocData, Height, Width } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { InkData, InkField, InkTool, Segment } from '../../../../fields/InkField'; @@ -38,7 +39,7 @@ import { ContextMenu } from '../../ContextMenu'; import { InkingStroke } from '../../InkingStroke'; import { CollectionFreeFormDocumentView } from '../../nodes/CollectionFreeFormDocumentView'; import { SchemaCSVPopUp } from '../../nodes/DataVizBox/SchemaCSVPopUp'; -import { DocumentView } from '../../nodes/DocumentView'; +import { ActiveFillColor, DocumentView } from '../../nodes/DocumentView'; import { FieldViewProps } from '../../nodes/FieldView'; import { FocusViewOptions } from '../../nodes/FocusViewOptions'; import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; @@ -550,7 +551,14 @@ export class CollectionFreeFormView extends CollectionSubView() { } } +export function ActiveFillColor(): string { + const dv = DocumentView.Selected().lastElement() ?.Document._layout_isSvg ? DocumentView.Selected().lastElement() : undefined; + return StrCast(dv?.Document.fillColor, StrCast(ActiveInkPen()?.activeFillColor, "")); +} // prettier-ignore +export function ActiveInkPen(): Doc { return Doc.UserDoc(); } // prettier-ignore +export function ActiveInkColor(): string { return StrCast(ActiveInkPen()?.activeInkColor, 'black'); } // prettier-ignore +export function ActiveIsInkMask(): boolean { return BoolCast(ActiveInkPen()?.activeIsInkMask, false); } // prettier-ignore +export function ActiveInkHideTextLabels(): boolean { return BoolCast(ActiveInkPen().activeInkHideTextLabels, false); } // prettier-ignore +export function ActiveArrowStart(): string { return StrCast(ActiveInkPen()?.activeArrowStart, ''); } // prettier-ignore +export function ActiveArrowEnd(): string { return StrCast(ActiveInkPen()?.activeArrowEnd, ''); } // prettier-ignore +export function ActiveArrowScale(): number { return NumCast(ActiveInkPen()?.activeArrowScale, 1); } // prettier-ignore +export function ActiveDash(): string { return StrCast(ActiveInkPen()?.activeDash, '0'); } // prettier-ignore +export function ActiveInkWidth(): number { return Number(ActiveInkPen()?.activeInkWidth); } // prettier-ignore +export function ActiveInkBezierApprox(): string { return StrCast(ActiveInkPen()?.activeInkBezier); } // prettier-ignore +export function ActiveEraserWidth(): number { return Number(ActiveInkPen()?.eraserWidth); } // prettier-ignore + +export function SetActiveInkWidth(width: string): void { + !isNaN(parseInt(width)) && ActiveInkPen() && (ActiveInkPen().activeInkWidth = width); +} +export function SetActiveBezierApprox(bezier: string): void { + ActiveInkPen() && (ActiveInkPen().activeInkBezier = isNaN(parseInt(bezier)) ? '' : bezier); +} +export function SetActiveInkColor(value: string) { + ActiveInkPen() && (ActiveInkPen().activeInkColor = value); +} +export function SetActiveIsInkMask(value: boolean) { + ActiveInkPen() && (ActiveInkPen().activeIsInkMask = value); +} +export function SetActiveInkHideTextLabels(value: boolean) { + ActiveInkPen() && (ActiveInkPen().activeInkHideTextLabels = value); +} +export function SetActiveFillColor(value: string) { + ActiveInkPen() && (ActiveInkPen().activeFillColor = value); +} +export function SetActiveArrowStart(value: string) { + ActiveInkPen() && (ActiveInkPen().activeArrowStart = value); +} +export function SetActiveArrowEnd(value: string) { + ActiveInkPen() && (ActiveInkPen().activeArrowEnd = value); +} +export function SetActiveArrowScale(value: number) { + ActiveInkPen() && (ActiveInkPen().activeArrowScale = value); +} +export function SetActiveDash(dash: string): void { + !isNaN(parseInt(dash)) && ActiveInkPen() && (ActiveInkPen().activeDash = dash); +} +export function SetEraserWidth(width: number): void { + ActiveInkPen() && (ActiveInkPen().eraserWidth = width); +} + // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function DocFocusOrOpen(docIn: Doc, optionsIn?: FocusViewOptions, containingDoc?: Doc) { return DocumentView.FocusOrOpen(docIn, optionsIn, containingDoc); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 1b3d963e8..72ec16b42 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -174,53 +174,6 @@ export function updateCachedAcls(doc: Doc) { return undefined; } -export function ActiveInkPen(): Doc { return Doc.UserDoc(); } // prettier-ignore -export function ActiveInkColor(): string { return StrCast(ActiveInkPen()?.activeInkColor, 'black'); } // prettier-ignore -export function ActiveFillColor(): string { return StrCast(ActiveInkPen()?.activeFillColor, ''); } // prettier-ignore -export function ActiveIsInkMask(): boolean { return BoolCast(ActiveInkPen()?.activeIsInkMask, false); } // prettier-ignore -export function ActiveInkHideTextLabels(): boolean { return BoolCast(ActiveInkPen().activeInkHideTextLabels, false); } // prettier-ignore -export function ActiveArrowStart(): string { return StrCast(ActiveInkPen()?.activeArrowStart, ''); } // prettier-ignore -export function ActiveArrowEnd(): string { return StrCast(ActiveInkPen()?.activeArrowEnd, ''); } // prettier-ignore -export function ActiveArrowScale(): number { return NumCast(ActiveInkPen()?.activeArrowScale, 1); } // prettier-ignore -export function ActiveDash(): string { return StrCast(ActiveInkPen()?.activeDash, '0'); } // prettier-ignore -export function ActiveInkWidth(): number { return Number(ActiveInkPen()?.activeInkWidth); } // prettier-ignore -export function ActiveInkBezierApprox(): string { return StrCast(ActiveInkPen()?.activeInkBezier); } // prettier-ignore -export function ActiveEraserWidth(): number { return Number(ActiveInkPen()?.eraserWidth); } // prettier-ignore - -export function SetActiveInkWidth(width: string): void { - !isNaN(parseInt(width)) && ActiveInkPen() && (ActiveInkPen().activeInkWidth = width); -} -export function SetActiveBezierApprox(bezier: string): void { - ActiveInkPen() && (ActiveInkPen().activeInkBezier = isNaN(parseInt(bezier)) ? '' : bezier); -} -export function SetActiveInkColor(value: string) { - ActiveInkPen() && (ActiveInkPen().activeInkColor = value); -} -export function SetActiveIsInkMask(value: boolean) { - ActiveInkPen() && (ActiveInkPen().activeIsInkMask = value); -} -export function SetActiveInkHideTextLabels(value: boolean) { - ActiveInkPen() && (ActiveInkPen().activeInkHideTextLabels = value); -} -export function SetActiveFillColor(value: string) { - ActiveInkPen() && (ActiveInkPen().activeFillColor = value); -} -export function SetActiveArrowStart(value: string) { - ActiveInkPen() && (ActiveInkPen().activeArrowStart = value); -} -export function SetActiveArrowEnd(value: string) { - ActiveInkPen() && (ActiveInkPen().activeArrowEnd = value); -} -export function SetActiveArrowScale(value: number) { - ActiveInkPen() && (ActiveInkPen().activeArrowScale = value); -} -export function SetActiveDash(dash: string): void { - !isNaN(parseInt(dash)) && ActiveInkPen() && (ActiveInkPen().activeDash = dash); -} -export function SetEraserWidth(width: number): void { - ActiveInkPen() && (ActiveInkPen().eraserWidth = width); -} - @scriptingGlobal @Deserializable('Doc', updateCachedAcls, ['id']) export class Doc extends RefField { -- cgit v1.2.3-70-g09d2 From f84a8d79c07bdd55e48acc976227a2ceeb457e5f Mon Sep 17 00:00:00 2001 From: eleanor-park Date: Tue, 2 Jul 2024 14:35:58 -0400 Subject: bug creating drawing groups --- src/client/views/MainView.tsx | 2964 +++++++------------- .../collectionFreeForm/CollectionFreeFormView.tsx | 22 +- src/client/views/smartdraw/SmartDrawHandler.tsx | 14 +- 3 files changed, 1070 insertions(+), 1930 deletions(-) diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index f88eb3bca..dd11ac684 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,1991 +1,1129 @@ -/* eslint-disable camelcase */ -/* eslint-disable jsx-a11y/control-has-associated-label */ -/* eslint-disable @typescript-eslint/no-unused-vars */ -/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */ -/* eslint-disable jsx-a11y/click-events-have-key-events */ -/* eslint-disable react/no-array-index-key */ -/* eslint-disable react/jsx-props-no-spreading */ -/* eslint-disable no-return-assign */ -import ArrowLeftIcon from '@mui/icons-material/ArrowLeft'; -import ArrowRightIcon from '@mui/icons-material/ArrowRight'; -import PauseIcon from '@mui/icons-material/Pause'; -import PlayArrowIcon from '@mui/icons-material/PlayArrow'; -import QuestionMarkIcon from '@mui/icons-material/QuestionMark'; -import ReplayIcon from '@mui/icons-material/Replay'; -import { Box, Button, Checkbox, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, FormControl, FormControlLabel, FormGroup, IconButton, LinearProgress, Stack } from '@mui/material'; -import Typography from '@mui/material/Typography'; -import { IReactionDisposer, action, computed, observable, reaction } from 'mobx'; +/* eslint-disable node/no-unpublished-import */ +import { library } from '@fortawesome/fontawesome-svg-core'; +import { faBuffer, faHireAHelper } from '@fortawesome/free-brands-svg-icons'; +import * as far from '@fortawesome/free-regular-svg-icons'; +import * as fa from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { action, computed, configure, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { NumListCast } from '../../../../fields/Doc'; -import { List } from '../../../../fields/List'; -import { BoolCast, NumCast, StrCast } from '../../../../fields/Types'; -import { ViewBoxAnnotatableComponent } from '../../DocComponent'; -import { FieldView, FieldViewProps } from '../FieldView'; -import './PhysicsSimulationBox.scss'; -import InputField from './PhysicsSimulationInputField'; -import questions from './PhysicsSimulationQuestions.json'; -import tutorials from './PhysicsSimulationTutorial.json'; -import Wall from './PhysicsSimulationWall'; -import Weight from './PhysicsSimulationWeight'; -import { Docs } from '../../../documents/Documents'; -import { DocumentType } from '../../../documents/DocumentTypes'; +// eslint-disable-next-line import/no-relative-packages +import '../../../node_modules/browndash-components/dist/styles/global.min.css'; +import { ClientUtils, lightOrDark, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents } from '../../ClientUtils'; +import { emptyFunction } from '../../Utils'; +import { Doc, DocListCast, GetDocFromUrl, Opt } from '../../fields/Doc'; +import { DocData } from '../../fields/DocSymbols'; +import { Id } from '../../fields/FieldSymbols'; +import { DocCast, StrCast, toList } from '../../fields/Types'; +import { DocServer } from '../DocServer'; +import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; +import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; +import { Docs } from '../documents/Documents'; +import { CalendarManager } from '../util/CalendarManager'; +import { CaptureManager } from '../util/CaptureManager'; +import { DocumentManager } from '../util/DocumentManager'; +import { DragManager } from '../util/DragManager'; +import { dropActionType } from '../util/DropActionTypes'; +import { GroupManager } from '../util/GroupManager'; +import { HistoryUtil } from '../util/History'; +import { Hypothesis } from '../util/HypothesisUtils'; +import { UPDATE_SERVER_CACHE } from '../util/LinkManager'; +import { RTFMarkup } from '../util/RTFMarkup'; +import { ScriptingGlobals } from '../util/ScriptingGlobals'; +import { ServerStats } from '../util/ServerStats'; +import { SettingsManager } from '../util/SettingsManager'; +import { SharingManager } from '../util/SharingManager'; +import { SnappingManager } from '../util/SnappingManager'; +import { Transform } from '../util/Transform'; +import { ReportManager } from '../util/reportManager/ReportManager'; +import { ComponentDecorations } from './ComponentDecorations'; +import { ContextMenu } from './ContextMenu'; +import { DashboardView } from './DashboardView'; +import { DictationOverlay } from './DictationOverlay'; +import { DocumentDecorations } from './DocumentDecorations'; +import { GestureOverlay } from './GestureOverlay'; +import { LightboxView } from './LightboxView'; +import './MainView.scss'; +import { ObservableReactComponent } from './ObservableReactComponent'; +import { PreviewCursor } from './PreviewCursor'; +import { PropertiesView } from './PropertiesView'; +import { DashboardStyleProvider, DefaultStyleProvider, returnEmptyDocViewList } from './StyleProvider'; +import { TimelineMenu } from './animationtimeline/TimelineMenu'; +import { CollectionDockingView } from './collections/CollectionDockingView'; +import { CollectionMenu } from './collections/CollectionMenu'; +import { TabDocView } from './collections/TabDocView'; +import './collections/TreeView.scss'; +import { CollectionFreeFormView } from './collections/collectionFreeForm'; +import { ImageLabelHandler } from './collections/collectionFreeForm/ImageLabelHandler'; +import { MarqueeOptionsMenu } from './collections/collectionFreeForm/MarqueeOptionsMenu'; +import { CollectionLinearView } from './collections/collectionLinear'; +import { LinkMenu } from './linking/LinkMenu'; +import { AudioBox } from './nodes/AudioBox'; +import { SchemaCSVPopUp } from './nodes/DataVizBox/SchemaCSVPopUp'; +import { DocButtonState } from './nodes/DocumentLinksButton'; +import { DocumentView, DocumentViewInternal } from './nodes/DocumentView'; +import { ImageEditorData as ImageEditor } from './nodes/ImageBox'; +import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup'; +import { LinkDocPreview, LinkInfo } from './nodes/LinkDocPreview'; +import { DirectionsAnchorMenu } from './nodes/MapBox/DirectionsAnchorMenu'; +import { MapAnchorMenu } from './nodes/MapBox/MapAnchorMenu'; +import { OpenWhere, OpenWhereMod } from './nodes/OpenWhere'; +import { TaskCompletionBox } from './nodes/TaskCompletedBox'; +import { DashFieldViewMenu } from './nodes/formattedText/DashFieldView'; +import { RichTextMenu } from './nodes/formattedText/RichTextMenu'; +import GenerativeFill from './nodes/generativeFill/GenerativeFill'; +import { PresBox } from './nodes/trails'; +import { AnchorMenu } from './pdf/AnchorMenu'; +import { GPTPopup } from './pdf/GPTPopup/GPTPopup'; +import { TopBar } from './topbar/TopBar'; +import { SmartDrawHandler } from './smartdraw/SmartDrawHandler'; -interface IWallProps { - length: number; - xPos: number; - yPos: number; - angleInDegrees: number; -} -interface IForce { - description: string; - magnitude: number; - directionInDegrees: number; -} -interface VectorTemplate { - top: number; - left: number; - width: number; - height: number; - x1: number; - y1: number; - x2: number; - y2: number; - weightX: number; - weightY: number; -} -interface QuestionTemplate { - questionSetup: string[]; - variablesForQuestionSetup: string[]; - question: string; - answerParts: string[]; - answerSolutionDescriptions: string[]; - goal: string; - hints: { description: string; content: string }[]; -} - -interface TutorialTemplate { - question: string; - steps: { - description: string; - content: string; - forces: { - description: string; - magnitude: number; - directionInDegrees: number; - component: boolean; - }[]; - showMagnitude: boolean; - }[]; -} +const { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } = require('./global/globalCssVariables.module.scss'); // prettier-ignore +const _global = (window /* browser */ || global) /* node */ as any; @observer -export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent() { - public static LayoutString(fieldKey: string) { - return FieldView.LayoutString(PhysicsSimulationBox, fieldKey); - } - - _widthDisposer: IReactionDisposer | undefined; - @observable _simReset = 0; - - // semi-Constants - xMin = 0; - yMin = 0; - xMax = this._props.PanelWidth() * 0.6; - yMax = this._props.PanelHeight(); - color = `rgba(0,0,0,0.5)`; - radius = 50; - wallPositions: IWallProps[] = []; - - @computed get circularMotionRadius() { - return (NumCast(this.dataDoc.circularMotionRadius, 150) * this._props.PanelWidth()) / 1000; - } - @computed get gravity() { - return NumCast(this.dataDoc.simulation_gravity, -9.81); - } - @computed get simulationType() { - return StrCast(this.dataDoc.simulation_type, 'Inclined Plane'); - } - @computed get simulationMode() { - return StrCast(this.dataDoc.simulation_mode, 'Freeform'); - } - // Used for spring simulation - @computed get springConstant() { - return NumCast(this.dataDoc.spring_constant, 0.5); - } - @computed get springLengthRest() { - return NumCast(this.dataDoc.spring_lengthRest, 200); - } - @computed get springLengthStart() { - return NumCast(this.dataDoc.spring_lengthStart, 200); - } - - @computed get pendulumAngle() { - return NumCast(this.dataDoc.pendulum_angle); - } - @computed get pendulumAngleStart() { - return NumCast(this.dataDoc.pendulum_angleStart); - } - @computed get pendulumLength() { - return NumCast(this.dataDoc.pendulum_length); - } - @computed get pendulumLengthStart() { - return NumCast(this.dataDoc.pendulum_lengthStart); - } +export class MainView extends ObservableReactComponent<{}> { + // eslint-disable-next-line no-use-before-define + public static Instance: MainView; + public static Live: boolean = false; + private _docBtnRef = React.createRef(); - // Used for wedge simulation - @computed get wedgeAngle() { - return NumCast(this.dataDoc.wedge_angle, 26); - } - @computed get wedgeHeight() { - return NumCast(this.dataDoc.wedge_height, Math.tan((26 * Math.PI) / 180) * this.xMax * 0.5); - } - @computed get wedgeWidth() { - return NumCast(this.dataDoc.wedge_width, this.xMax * 0.5); - } - @computed get mass1() { - return NumCast(this.dataDoc.mass1, 1); - } - @computed get mass2() { - return NumCast(this.dataDoc.mass2, 1); + @observable private _windowWidth: number = 0; + @observable private _windowHeight: number = 0; + @observable private _dashUIWidth: number = 0; // width of entire main dashboard region including left menu buttons and properties panel (but not including the dashboard selector button row) + @observable private _dashUIHeight: number = 0; // height of entire main dashboard region including top menu buttons + @observable private _panelContent: string = 'none'; + @observable private _sidebarContent: any = Doc.MyLeftSidebarPanel; + @observable private _leftMenuFlyoutWidth: number = 0; + @computed get _hideUI() { + return this.mainDoc && this.mainDoc._type_collection !== CollectionViewType.Docking; } - @computed get mass1Radius() { - return NumCast(this.dataDoc.mass1_radius, 30); - } - @computed get mass1PosXStart() { - return NumCast(this.dataDoc.mass1_positionXstart); - } - @computed get mass1PosYStart() { - return NumCast(this.dataDoc.mass1_positionYstart); + @computed private get dashboardTabHeight() { + return this._hideUI ? 0 : 27; + } // 27 comes form lm.config.defaultConfig.dimensions.headerHeight in goldenlayout.js + @computed private get topOfDashUI() { + return this._hideUI || DocumentView.LightboxDoc() ? 0 : Number(TOPBAR_HEIGHT.replace('px', '')); } - @computed get mass1VelXStart() { - return NumCast(this.dataDoc.mass1_velocityXstart); + @computed private get topOfHeaderBarDoc() { + return this.topOfDashUI; } - @computed get mass1VelYStart() { - return NumCast(this.dataDoc.mass1_velocityYstart); + @computed private get topOfSidebarDoc() { + return this.topOfDashUI + this.topMenuHeight(); } - - @computed get mass2PosXStart() { - return NumCast(this.dataDoc.mass2_positionXstart); - } - @computed get mass2PosYStart() { - return NumCast(this.dataDoc.mass2_positionYstart); + @computed private get topOfMainDoc() { + return this.topOfDashUI + this.topMenuHeight() + this.headerBarDocHeight(); } - @computed get mass2VelXStart() { - return NumCast(this.dataDoc.mass2_velocityXstart); + @computed private get topOfMainDocContent() { + return this.topOfMainDoc + this.dashboardTabHeight; } - @computed get mass2VelYStart() { - return NumCast(this.dataDoc.mass2_velocityYstart); - } - - @computed get selectedQuestion() { - return this.dataDoc.selectedQuestion ? (JSON.parse(StrCast(this.dataDoc.selectedQuestion)) as QuestionTemplate) : questions.inclinePlane[0]; + @computed private get leftScreenOffsetOfMainDocView() { + return this.leftMenuWidth() - 2; } - @computed get tutorial() { - return this.dataDoc.tutorial ? (JSON.parse(StrCast(this.dataDoc.tutorial)) as TutorialTemplate) : tutorials.inclinePlane; + @computed private get userDoc() { + return Doc.UserDoc(); } - @computed get selectedSolutions() { - return NumListCast(this.dataDoc.selectedSolutions); + @observable mainDoc: Opt = undefined; + @computed private get mainContainer() { + if (window.location.pathname.startsWith('/doc/') && ClientUtils.CurrentUserEmail() === 'guest') { + DocServer.GetRefField(window.location.pathname.substring('/doc/'.length)).then(main => + runInAction(() => { + this.mainDoc = main as Doc; + }) + ); + return this.mainDoc; + } + return this.userDoc ? Doc.ActiveDashboard : Doc.GuestDashboard; } - @computed get questionPartOne() { - return StrCast(this.dataDoc.questionPartOne); + @computed private get headerBarDoc() { + return Doc.MyHeaderBar; } - @computed get questionPartTwo() { - return StrCast(this.dataDoc.questionPartTwo); + @computed public get mainFreeform(): Opt { + return (docs => (docs?.length > 1 ? docs[1] : undefined))(DocListCast(this.mainContainer!.data)); } + @observable public headerBarHeight: number = 0; + headerBarHeightFunc = () => this.headerBarHeight; - componentWillUnmount() { - this._widthDisposer?.(); - } + @action + toggleTopBar = () => { + if (this.headerBarHeight > 0) { + this.headerBarHeight = 0; + } else { + this.headerBarHeight = 60; + } + }; + headerBarDocWidth = () => this.mainDocViewWidth(); + headerBarDocHeight = () => (this._hideUI ? 0 : this.headerBarHeight ?? 0); + topMenuHeight = () => (this._hideUI ? 0 : 35); + topMenuWidth = returnZero; // value is ignored ... + leftMenuWidth = () => (this._hideUI ? 0 : Number(LEFT_MENU_WIDTH.replace('px', ''))); + leftMenuHeight = () => this._dashUIHeight; + leftMenuFlyoutWidth = () => this._leftMenuFlyoutWidth; + leftMenuFlyoutHeight = () => this._dashUIHeight; + propertiesWidth = () => Math.max(0, Math.min(this._dashUIWidth - 50, SnappingManager.PropertiesWidth || 0)); + propertiesHeight = () => this._dashUIHeight; + mainDocViewWidth = () => this._dashUIWidth - this.propertiesWidth() - this.leftMenuWidth() - this.leftMenuFlyoutWidth(); + mainDocViewHeight = () => this._dashUIHeight - this.headerBarDocHeight(); componentDidMount() { - // Setup and update simulation - this._widthDisposer = reaction(() => [this._props.PanelWidth(), this._props.PanelHeight()], this.setupSimulation, { fireImmediately: true }); + // Utils.TraceConsoleLog(); + reaction( + // when a multi-selection occurs, remove focus from all active elements to allow keyboad input to go only to global key manager to act upon selection + () => DocumentView.Selected().slice(), + views => views.length > 1 && (document.activeElement as any)?.blur !== undefined && (document.activeElement as any)!.blur() + ); + reaction( + () => Doc.MyDockedBtns.linearView_IsOpen, + open => SnappingManager.SetPrintToConsole(!!open) + ); + const scriptTag = document.createElement('script'); + scriptTag.setAttribute('type', 'text/javascript'); + scriptTag.setAttribute('src', 'https://www.bing.com/api/maps/mapcontrol?callback=makeMap'); + scriptTag.async = true; + scriptTag.defer = true; + document.body.appendChild(scriptTag); + document.getElementById('root')?.addEventListener('scroll', () => + (ele => { + ele.scrollLeft = ele.scrollTop = 0; + })(document.getElementById('root')!) + ); + const ele = document.getElementById('loader'); + const prog = document.getElementById('dash-progress'); + if (ele && prog) { + // remove from DOM + setTimeout(() => { + prog.style.transition = '1s'; + prog.style.width = '100%'; + }, 0); + setTimeout(() => { + ele.outerHTML = ''; + }, 1000); + } + this._sidebarContent.proto = undefined; + if (!MainView.Live) { + DocServer.setLivePlaygroundFields([ + 'dataTransition', + 'viewTransition', + 'treeView_Open', + 'treeView_ExpandedView', + 'carousel_index', + 'itemIndex', // for changing slides in presentations + 'layout_sidebarWidthPercent', + 'layout_currentTimecode', + 'layout_timelineHeightPercent', + 'layout_hideMinimap', + 'layout_showSidebar', + 'layout_scrollTop', + 'layout_fitWidth', + 'layout_curPage', + 'presStatus', + 'freeform_panX', + 'freeform_panY', + 'freeform_scale', + 'overlayX', + 'overlayY', + 'text_scrollHeight', + 'text_height', + 'hidden', + // 'type_collection', + 'chromeHidden', + 'currentFrame', + ]); // can play with these fields on someone else's + } - // Create walls - this.wallPositions = [ - { length: 100, xPos: 0, yPos: 0, angleInDegrees: 0 }, - { length: 100, xPos: 0, yPos: 100, angleInDegrees: 0 }, - { length: 100, xPos: 0, yPos: 0, angleInDegrees: 90 }, - { length: 100, xPos: (this.xMax / this._props.PanelWidth()) * 100, yPos: 0, angleInDegrees: 90 }, - ]; + const tag = document.createElement('script'); + tag.src = 'https://www.youtube.com/iframe_api'; + const firstScriptTag = document.getElementsByTagName('script')[0]; + firstScriptTag.parentNode!.insertBefore(tag, firstScriptTag); + document.addEventListener('dash', (e: any) => { + // event used by chrome plugin to tell Dash which document to focus on + const id = GetDocFromUrl(e.detail); + DocServer.GetRefField(id).then(doc => (doc instanceof Doc ? DocumentView.showDocument(doc, { willPan: false }) : null)); + }); + document.addEventListener('linkAnnotationToDash', Hypothesis.linkListener); + this.initEventListeners(); } - componentDidUpdate(prevProps: Readonly) { - super.componentDidUpdate(prevProps); - if (this.xMax !== this._props.PanelWidth() * 0.6 || this.yMax !== this._props.PanelHeight()) { - this.xMax = this._props.PanelWidth() * 0.6; - this.yMax = this._props.PanelHeight(); - this.setupSimulation(); - } + componentWillUnMount() { + // window.removeEventListener('keyup', KeyManager.Instance.unhandle); + // window.removeEventListener('keydown', KeyManager.Instance.handle); + // window.removeEventListener('pointerdown', this.globalPointerDown, true); + // window.removeEventListener('pointermove', this.globalPointerMove, true); + // window.removeEventListener('pointerup', this.globalPointerClick, true); + // window.removeEventListener('paste', KeyManager.Instance.paste as any); + // document.removeEventListener('linkAnnotationToDash', Hypothesis.linkListener); } - gravityForce = (mass: number): IForce => ({ - description: 'Gravity', - magnitude: mass * Math.abs(this.gravity), - directionInDegrees: 270, - }); + constructor(props: any) { + super(props); + makeObservable(this); + DocumentViewInternal.addDocTabFunc = MainView.addDocTabFunc_impl; + MainView.Instance = this; + DashboardView._urlState = HistoryUtil.parseUrl(window.location) || ({} as any); - @action - setupSimulation = () => { - const { simulationType } = this; - const mode = this.simulationMode; - this.dataDoc.simulation_paused = true; - if (simulationType !== 'Circular Motion') { - this.dataDoc.mass1_velocityXstart = 0; - this.dataDoc.mass1_velocityYstart = 0; - this.dataDoc.mass1_velocityX = 0; - this.dataDoc.mass1_velocityY = 0; - } - if (mode === 'Freeform') { - this.dataDoc.simulation_showForceMagnitudes = true; - // prettier-ignore - switch (simulationType) { - case 'One Weight': - this.dataDoc.simulation_showComponentForces = false; - this.dataDoc.mass1_positionYstart = this.yMin + this.mass1Radius; - this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - this.mass1Radius; - this.dataDoc.mass1_positionY = this.getDisplayYPos(this.yMin + this.mass1Radius); - this.dataDoc.mass1_positionX = (this.xMax + this.xMin) / 2 - this.mass1Radius; - this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1)]); - this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1)]); - break; - case 'Inclined Plane': this.setupInclinedPlane(); break; - case 'Pendulum': this.setupPendulum(); break; - case 'Spring': this.setupSpring(); break; - case 'Circular Motion': this.setupCircular(20); break; - case 'Pulley': this.setupPulley(); break; - case 'Suspension': this.setupSuspension();break; - default: - } - this._simReset++; - } else if (mode === 'Review') { - this.dataDoc.simulation_showComponentForces = false; - this.dataDoc.simulation_showForceMagnitudes = true; - this.dataDoc.simulation_showAcceleration = false; - this.dataDoc.simulation_showVelocity = false; - this.dataDoc.simulation_showForces = true; - this.generateNewQuestion(); - // prettier-ignore - switch (simulationType) { - case 'One Weight' : break;// TODO - one weight review problems - case 'Spring': this.setupSpring(); break; // TODO - spring review problems - case 'Inclined Plane': this.dataDoc.mass1_forcesUpdated = this.dataDoc.mass1_forcesStart = ''; break; - case 'Pendulum': this.setupPendulum(); break; // TODO - pendulum review problems - case 'Circular Motion': this.setupCircular(0); break; // TODO - circular motion review problems - case 'Pulley': this.setupPulley(); break; // TODO - pulley tutorial review problems - case 'Suspension': this.setupSuspension(); break; // TODO - suspension tutorial review problems - default: - } - } else if (mode === 'Tutorial') { - this.dataDoc.simulation_showComponentForces = false; - this.dataDoc.tutorial_stepNumber = 0; - this.dataDoc.simulation_showAcceleration = false; - if (this.simulationType !== 'Circular Motion') { - this.dataDoc.mass1_velocityX = 0; - this.dataDoc.mass1_velocityY = 0; - this.dataDoc.simulation_showVelocity = false; - } else { - this.dataDoc.mass1_velocityX = 20; - this.dataDoc.mass1_velocityY = 0; - this.dataDoc.simulation_showVelocity = true; - } + // causes errors to be generated when modifying an observable outside of an action + configure({ enforceActions: 'observed' }); - switch (this.simulationType) { - case 'One Weight': - this.dataDoc.simulation_showForces = true; - this.dataDoc.mass1_positionYstart = this.yMax - 100; - this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - this.mass1Radius; - this.dataDoc.tutorial = JSON.stringify(tutorials.freeWeight); - this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.freeWeight.steps[0].forces); - this.dataDoc.simulation_showForceMagnitudes = tutorials.freeWeight.steps[0].showMagnitude; - break; - case 'Spring': - this.dataDoc.simulation_showForces = true; - this.setupSpring(); - this.dataDoc.mass1_positionYstart = this.yMin + 200 + 19.62; - this.dataDoc.mass1_positionXstart = (this.xMax + this.xMin) / 2 - this.mass1Radius; - this.dataDoc.tutorial = JSON.stringify(tutorials.spring); - this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.spring.steps[0].forces); - this.dataDoc.simulation_showForceMagnitudes = tutorials.spring.steps[0].showMagnitude; - break; - case 'Pendulum': - this.setupPendulum(); - this.dataDoc.tutorial = JSON.stringify(tutorials.pendulum); - this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.pendulum.steps[0].forces); - this.dataDoc.simulation_showForceMagnitudes = tutorials.pendulum.steps[0].showMagnitude; - break; - case 'Inclined Plane': - this.dataDoc.wedge_angle = 26; - this.setupInclinedPlane(); - this.dataDoc.simulation_showForces = true; - this.dataDoc.tutorial = JSON.stringify(tutorials.inclinePlane); - this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.inclinePlane.steps[0].forces); - this.dataDoc.simulation_showForceMagnitudes = tutorials.inclinePlane.steps[0].showMagnitude; - break; - case 'Circular Motion': - this.dataDoc.simulation_showForces = true; - this.setupCircular(40); - this.dataDoc.tutorial = JSON.stringify(tutorials.circular); - this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.circular.steps[0].forces); - this.dataDoc.simulation_showForceMagnitudes = tutorials.circular.steps[0].showMagnitude; - break; - case 'Pulley': - this.dataDoc.simulation_showForces = true; - this.setupPulley(); - this.dataDoc.tutorial = JSON.stringify(tutorials.pulley); - this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.pulley.steps[0].forces); - this.dataDoc.simulation_showForceMagnitudes = tutorials.pulley.steps[0].showMagnitude; - break; - case 'Suspension': - this.dataDoc.simulation_showForces = true; - this.setupSuspension(); - this.dataDoc.tutorial = JSON.stringify(tutorials.suspension); - this.dataDoc.mass1_forcesStart = JSON.stringify(tutorials.suspension.steps[0].forces); - this.dataDoc.simulation_showForceMagnitudes = tutorials.suspension.steps[0].showMagnitude; - break; - default: + if (window.location.pathname !== '/home') { + const pathname = window.location.pathname.substr(1).split('/'); + if (pathname.length > 1 && pathname[0] === 'doc') { + DocServer.GetRefField(pathname[1]).then( + action(field => { + if (field instanceof Doc && field._type_collection !== CollectionViewType.Docking) { + Doc.GuestTarget = field; + } + }) + ); } - this._simReset++; } - }; - // Helper function to go between display and real values - getDisplayYPos = (yPos: number) => this.yMax - yPos - 2 * this.mass1Radius + 5; - getYPosFromDisplay = (yDisplay: number) => this.yMax - yDisplay - 2 * this.mass1Radius + 5; + library.add( + ...[ + fa.faExclamationCircle, + fa.faEdit, + fa.faArrowDownShortWide, + fa.faTrash, + fa.faTrashAlt, + fa.faShare, + fa.faTaxi, + fa.faDownload, + fa.faPallet, + fa.faExpandArrowsAlt, + fa.faAmbulance, + fa.faLayerGroup, + fa.faExternalLinkAlt, + fa.faCalendar, + fa.faSquare, + far.faSquare as any, + fa.faConciergeBell, + fa.faWindowRestore, + fa.faFolder, + fa.faFolderOpen, + fa.faFolderPlus, + fa.faFolderClosed, + fa.faBook, + fa.faMapPin, + fa.faMapMarker, + fa.faFingerprint, + fa.faCrosshairs, + fa.faDesktop, + fa.faUnlock, + fa.faLock, + fa.faLaptopCode, + fa.faMale, + fa.faCopy, + fa.faHome, + fa.faHandPointLeft, + fa.faHandPointRight, + fa.faCompass, + fa.faSnowflake, + fa.faStar, + fa.faSplotch, + fa.faMicrophone, + fa.faCircleHalfStroke, + fa.faKeyboard, + fa.faQuestion, + fa.faTasks, + fa.faPalette, + fa.faAngleLeft, + fa.faAngleRight, + fa.faBell, + fa.faCamera, + fa.faExpand, + fa.faCaretDown, + fa.faCaretLeft, + fa.faCaretRight, + fa.faCaretSquareDown, + fa.faCaretSquareRight, + fa.faArrowsAltH, + fa.faPlus, + fa.faMinus, + fa.faTerminal, + fa.faToggleOn, + fa.faFile, + fa.faLocationArrow, + fa.faSearch, + fa.faFileDownload, + fa.faFileUpload, + fa.faStop, + fa.faCalculator, + fa.faWindowMaximize, + fa.faIdCard, + fa.faAddressCard, + fa.faQuestionCircle, + fa.faArrowLeft, + fa.faArrowRight, + fa.faArrowDown, + fa.faArrowUp, + fa.faBolt, + fa.faBullseye, + fa.faTurnUp, + fa.faTurnDown, + fa.faCaretUp, + fa.faCat, + fa.faCheck, + fa.faChevronRight, + fa.faChevronLeft, + fa.faChevronDown, + fa.faChevronUp, + fa.faClone, + fa.faCloudUploadAlt, + fa.faCommentAlt, + fa.faCommentDots, + fa.faCompressArrowsAlt, + fa.faCut, + fa.faEllipsisV, + fa.faEraser, + fa.faDeleteLeft, + fa.faXmarksLines, + fa.faCircleXmark, + fa.faXmark, + fa.faExclamation, + fa.faFileAlt, + fa.faFileAudio, + fa.faFileVideo, + fa.faFilePdf, + fa.faFilm, + fa.faFilter, + fa.faFont, + fa.faGlobeAmericas, + fa.faGlobeAsia, + fa.faHighlighter, + fa.faLongArrowAltRight, + fa.faMousePointer, + fa.faMusic, + fa.faObjectGroup, + fa.faArrowsLeftRight, + fa.faPause, + fa.faPen, + fa.faUserPen, + fa.faPenNib, + fa.faPhone, + fa.faPlay, + fa.faPortrait, + fa.faRedoAlt, + fa.faStamp, + fa.faStickyNote, + fa.faArrowsAltV, + fa.faTimesCircle, + fa.faThumbtack, + fa.faTree, + fa.faTv, + fa.faUndoAlt, + fa.faVideoSlash, + fa.faVideo, + fa.faAsterisk, + fa.faBrain, + fa.faImage, + fa.faPaintBrush, + fa.faTimes, + fa.faFlag, + fa.faScroll, + fa.faEye, + fa.faArrowsAlt, + fa.faQuoteLeft, + fa.faSortAmountDown, + fa.faAlignLeft, + fa.faAlignCenter, + fa.faAlignRight, + fa.faHeading, + fa.faRulerCombined, + fa.faFillDrip, + fa.faLink, + fa.faUnlink, + fa.faBold, + fa.faItalic, + fa.faClipboard, + fa.faUnderline, + fa.faStrikethrough, + fa.faSuperscript, + fa.faSubscript, + fa.faIndent, + fa.faEyeDropper, + fa.faPaintRoller, + fa.faBars, + fa.faBarsStaggered, + fa.faBrush, + fa.faShapes, + fa.faEllipsisH, + fa.faHandPaper, + fa.faMap, + fa.faUser, + faHireAHelper as any, + fa.faTrashRestore, + fa.faUsers, + fa.faWrench, + fa.faCog, + fa.faMap, + fa.faBellSlash, + fa.faExpandAlt, + fa.faArchive, + fa.faBezierCurve, + fa.faCircle, + far.faCircle as any, + fa.faLongArrowAltRight, + fa.faPenFancy, + fa.faAngleDoubleRight, + fa.faAngleDoubleDown, + fa.faAngleDoubleLeft, + fa.faAngleDoubleUp, + faBuffer as any, + fa.faExpand, + fa.faUndo, + fa.faSlidersH, + fa.faAngleUp, + fa.faAngleDown, + fa.faPlayCircle, + fa.faClock, + fa.faRoute, + fa.faRocket, + fa.faExchangeAlt, + fa.faHashtag, + fa.faAlignJustify, + fa.faCheckSquare, + fa.faListUl, + fa.faWindowMinimize, + fa.faWindowRestore, + fa.faTextWidth, + fa.faTextHeight, + fa.faClosedCaptioning, + fa.faInfoCircle, + fa.faTag, + fa.faSyncAlt, + fa.faPhotoVideo, + fa.faArrowAltCircleDown, + fa.faArrowAltCircleUp, + fa.faArrowAltCircleLeft, + fa.faArrowAltCircleRight, + fa.faStopCircle, + fa.faCheckCircle, + fa.faGripVertical, + fa.faSortUp, + fa.faSortDown, + fa.faTable, + fa.faTableCells, + fa.faTableColumns, + fa.faTh, + fa.faThList, + fa.faProjectDiagram, + fa.faSignature, + fa.faColumns, + fa.faChevronCircleUp, + fa.faUpload, + fa.faBorderAll, + fa.faBraille, + fa.faPersonChalkboard, + fa.faChalkboard, + fa.faPencilAlt, + fa.faEyeSlash, + fa.faSmile, + fa.faIndent, + fa.faOutdent, + fa.faChartBar, + fa.faBan, + fa.faPhoneSlash, + fa.faGripLines, + fa.faSave, + fa.faBook, + fa.faBookmark, + fa.faList, + fa.faListOl, + fa.faLightbulb, + fa.faBookOpen, + fa.faMapMarkerAlt, + fa.faSearchPlus, + fa.faSolarPanel, + fa.faVolumeUp, + fa.faVolumeDown, + fa.faSquareRootAlt, + fa.faVolumeMute, + fa.faUserCircle, + fa.faHeart, + fa.faHeartBroken, + fa.faHighlighter, + fa.faRemoveFormat, + fa.faHandPointUp, + fa.faXRay, + fa.faZ, + fa.faArrowsUpToLine, + fa.faArrowsDownToLine, + fa.faPalette, + fa.faHourglassHalf, + fa.faRobot, + fa.faSatellite, + fa.faStar, + ] + ); + } - // Update forces when coefficient of static friction changes in freeform mode - updateForcesWithFriction = (coefficient: number, width = this.wedgeWidth, height = this.wedgeHeight) => { - const normalForce: IForce = { - description: 'Normal Force', - magnitude: Math.abs(this.gravity) * Math.cos(Math.atan(height / width)) * this.mass1, - directionInDegrees: 180 - 90 - (Math.atan(height / width) * 180) / Math.PI, - }; - const frictionForce: IForce = { - description: 'Static Friction Force', - magnitude: coefficient * Math.abs(this.gravity) * Math.cos(Math.atan(height / width)) * this.mass1, - directionInDegrees: 180 - (Math.atan(height / width) * 180) / Math.PI, - }; - // reduce magnitude or friction force if necessary such that block cannot slide up plane - let yForce = -Math.abs(this.gravity) * this.mass1; - yForce += normalForce.magnitude * Math.sin((normalForce.directionInDegrees * Math.PI) / 180); - yForce += frictionForce.magnitude * Math.sin((frictionForce.directionInDegrees * Math.PI) / 180); - if (yForce > 0) { - frictionForce.magnitude = (-normalForce.magnitude * Math.sin((normalForce.directionInDegrees * Math.PI) / 180) + Math.abs(this.gravity) * this.mass1) / Math.sin((frictionForce.directionInDegrees * Math.PI) / 180); + private longPressTimer: NodeJS.Timeout | undefined; + globalPointerClick = action(() => { + this.longPressTimer && clearTimeout(this.longPressTimer); + DocumentView.LongPress = false; + }); + globalPointerMove = action((e: PointerEvent) => { + if (e.movementX > 3 || e.movementY > 3) this.longPressTimer && clearTimeout(this.longPressTimer); + }); + globalPointerDown = action((e: PointerEvent) => { + DocumentView.LongPress = false; + this.longPressTimer = setTimeout( + action(() => { + DocumentView.LongPress = true; + }), + 1000 + ); + DocumentManager.removeOverlayViews(); + Doc.linkFollowUnhighlight(); + AudioBox.Enabled = true; + const targets = document.elementsFromPoint(e.x, e.y); + if (targets.length) { + let targClass = targets[0].className.toString(); + for (let i = 0; i < targets.length - 1; i++) { + if (typeof targets[i].className === 'object') targClass = targets[i + 1].className.toString(); + else break; + } + !targClass.includes('contextMenu') && ContextMenu.Instance.closeMenu(); + !['timeline-menu-desc', 'timeline-menu-item', 'timeline-menu-input'].includes(targClass) && TimelineMenu.Instance.closeMenu(); } + }); - const normalForceComponent: IForce = { - description: 'Normal Force', - magnitude: this.mass1 * Math.abs(this.gravity) * Math.cos(Math.atan(height / width)), - directionInDegrees: 180 - 90 - (Math.atan(height / width) * 180) / Math.PI, - }; - const gravityParallel: IForce = { - description: 'Gravity Parallel Component', - magnitude: this.mass1 * Math.abs(this.gravity) * Math.sin(Math.PI / 2 - Math.atan(height / width)), - directionInDegrees: 180 - 90 - (Math.atan(height / width) * 180) / Math.PI + 180, - }; - const gravityPerpendicular: IForce = { - description: 'Gravity Perpendicular Component', - magnitude: this.mass1 * Math.abs(this.gravity) * Math.cos(Math.PI / 2 - Math.atan(height / width)), - directionInDegrees: 360 - (Math.atan(height / width) * 180) / Math.PI, - }; - const gravityForce = this.gravityForce(this.mass1); - if (coefficient !== 0) { - this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce, normalForce, frictionForce]); - this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce, normalForce, frictionForce]); - this.dataDoc.mass1_componentForces = JSON.stringify([frictionForce, normalForceComponent, gravityParallel, gravityPerpendicular]); - } else { - this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce, normalForce]); - this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce, normalForce]); - this.dataDoc.mass1_componentForces = JSON.stringify([normalForceComponent, gravityParallel, gravityPerpendicular]); - } + initEventListeners = () => { + window.addEventListener('beforeunload', UPDATE_SERVER_CACHE); + window.addEventListener('drop', e => e.preventDefault(), false); // prevent default behavior of navigating to a new web page + window.addEventListener('dragover', e => e.preventDefault(), false); + document.addEventListener('pointerdown', this.globalPointerDown, true); + document.addEventListener('pointermove', this.globalPointerMove, true); + document.addEventListener('pointerup', this.globalPointerClick, true); + document.addEventListener( + 'click', + (e: MouseEvent) => { + if (!e.cancelBubble) { + const pathstr = (e as any)?.path?.map((p: any) => p.classList?.toString()).join(); + if (pathstr?.includes('libraryFlyout')) { + DocumentView.DeselectAll(); + } + } + }, + false + ); + document.oncontextmenu = () => false; }; - // Change wedge height and width and weight position to match new wedge angle - changeWedgeBasedOnNewAngle = (angle: number) => { - const radAng = (angle * Math.PI) / 180; - this.dataDoc.wedge_width = this.xMax * 0.5; - this.dataDoc.wedge_height = Math.tan(radAng) * this.dataDoc.wedge_width; - - // update weight position based on updated wedge width/height - const yPos = this.yMax - this.dataDoc.wedge_height - this.mass1Radius * Math.cos(radAng) - this.mass1Radius; - const xPos = this.xMax * 0.25 + this.mass1Radius * Math.sin(radAng) - this.mass1Radius; - - this.dataDoc.mass1_positionXstart = xPos; - this.dataDoc.mass1_positionYstart = yPos; - if (this.simulationMode === 'Freeform') { - this.updateForcesWithFriction(NumCast(this.dataDoc.coefficientOfStaticFriction), this.dataDoc.wedge_width, Math.tan(radAng) * this.dataDoc.wedge_width); - } + @action + createNewPresentation = () => { + const pres = Doc.MakeCopy(Doc.UserDoc().emptyTrail as Doc, true); + CollectionDockingView.AddSplit(pres, OpenWhereMod.right); + Doc.MyTrails && Doc.AddDocToList(Doc.MyTrails, 'data', pres); // Doc.MyTrails should be created in createDashboard + Doc.ActivePresentation = pres; }; - // In review mode, update forces when coefficient of static friction changed - updateReviewForcesBasedOnCoefficient = (coefficient: number) => { - let theta = this.wedgeAngle; - const index = this.selectedQuestion.variablesForQuestionSetup.indexOf('theta - max 45'); - if (index >= 0) { - theta = NumListCast(this.dataDoc.questionVariables)[index]; - } - if (isNaN(theta)) { - return; - } - this.dataDoc.review_GravityMagnitude = Math.abs(this.gravity); - this.dataDoc.review_GravityAngle = 270; - this.dataDoc.review_NormalMagnitude = Math.abs(this.gravity) * Math.cos((theta * Math.PI) / 180); - this.dataDoc.review_NormalAngle = 90 - theta; - let yForce = -Math.abs(this.gravity); - yForce += Math.abs(this.gravity) * Math.cos((theta * Math.PI) / 180) * Math.sin(((90 - theta) * Math.PI) / 180); - yForce += coefficient * Math.abs(this.gravity) * Math.cos((theta * Math.PI) / 180) * Math.sin(((180 - theta) * Math.PI) / 180); - let friction = coefficient * Math.abs(this.gravity) * Math.cos((theta * Math.PI) / 180); - if (yForce > 0) { - friction = (-(Math.abs(this.gravity) * Math.cos((theta * Math.PI) / 180)) * Math.sin(((90 - theta) * Math.PI) / 180) + Math.abs(this.gravity)) / Math.sin(((180 - theta) * Math.PI) / 180); + @action + openPresentation = (pres: Doc) => { + if (pres.type === DocumentType.PRES) { + CollectionDockingView.AddSplit(pres, OpenWhereMod.right, undefined, PresBox.PanelName); + Doc.MyTrails && (Doc.ActivePresentation = pres); + Doc.AddDocToList(Doc.MyTrails, 'data', pres); + this.closeFlyout(); } - this.dataDoc.review_StaticMagnitude = friction; - this.dataDoc.review_StaticAngle = 180 - theta; }; - // In review mode, update forces when wedge angle changed - updateReviewForcesBasedOnAngle = (angle: number) => { - this.dataDoc.review_GravityMagnitude = Math.abs(this.gravity); - this.dataDoc.review_GravityAngle = 270; - this.dataDoc.review_NormalMagnitude = Math.abs(this.gravity) * Math.cos((angle * Math.PI) / 180); - this.dataDoc.review_NormalAngle = 90 - angle; - let yForce = -Math.abs(this.gravity); - yForce += Math.abs(this.gravity) * Math.cos((angle * Math.PI) / 180) * Math.sin(((90 - angle) * Math.PI) / 180); - yForce += NumCast(this.dataDoc.review_Coefficient) * Math.abs(this.gravity) * Math.cos((angle * Math.PI) / 180) * Math.sin(((180 - angle) * Math.PI) / 180); - let friction = NumCast(this.dataDoc.review_Coefficient) * Math.abs(this.gravity) * Math.cos((angle * Math.PI) / 180); - if (yForce > 0) { - friction = (-(Math.abs(this.gravity) * Math.cos((angle * Math.PI) / 180)) * Math.sin(((90 - angle) * Math.PI) / 180) + Math.abs(this.gravity)) / Math.sin(((180 - angle) * Math.PI) / 180); - } - this.dataDoc.review_StaticMagnitude = friction; - this.dataDoc.review_StaticAngle = 180 - angle; + @action + createNewFolder = async () => { + const folder = Docs.Create.TreeDocument([], { title: 'Untitled folder', _dragOnlyWithinContainer: true, isFolder: true }); + Doc.AddDocToList(Doc.MyFilesystem, 'data', folder); }; - // Solve for the correct answers to the generated problem - getAnswersToQuestion = (question: QuestionTemplate, questionVars: number[]) => { - const solutions: number[] = []; + waitForDoubleClick = () => (SnappingManager.ExploreMode ? 'never' : undefined); + headerBarScreenXf = () => new Transform(-this.leftScreenOffsetOfMainDocView - this.leftMenuFlyoutWidth(), -this.headerBarDocHeight(), 1); + mainScreenToLocalXf = () => new Transform(-this.leftScreenOffsetOfMainDocView - this.leftMenuFlyoutWidth(), -this.topOfMainDocContent, 1); + addHeaderDoc = (docs: Doc | Doc[]) => toList(docs).reduce((done, doc) => Doc.AddDocToList(this.headerBarDoc, 'data', doc), true); + removeHeaderDoc = (docs: Doc | Doc[]) => toList(docs).reduce((done, doc) => Doc.RemoveDocFromList(this.headerBarDoc, 'data', doc), true); + @computed get headerBarDocView() { + return ( +
+ +
+ ); + } + @computed get mainDocView() { + const headerBar = this._hideUI || !this.headerBarDocHeight?.() ? null : this.headerBarDocView; + return ( + <> + {headerBar} + + + ); + } - let theta = this.wedgeAngle; - let index = question.variablesForQuestionSetup.indexOf('theta - max 45'); - if (index >= 0) { - theta = questionVars[index]; - } - let muS: number = NumCast(this.dataDoc.coefficientOfStaticFriction); - index = question.variablesForQuestionSetup.indexOf('coefficient of static friction'); - if (index >= 0) { - muS = questionVars[index]; - } + @computed get dockingContent() { + return ( + +
{ + e.stopPropagation(); + e.preventDefault(); + }} + style={{ + width: `calc(100% - ${this._leftMenuFlyoutWidth + this.leftMenuWidth() + this.propertiesWidth()}px)`, + minWidth: `calc(100% - ${this._leftMenuFlyoutWidth + this.leftMenuWidth() + this.propertiesWidth()}px)`, + transform: DocumentView.LightboxDoc() ? 'scale(0.0001)' : undefined, + }}> + {!this.mainContainer ? null : this.mainDocView} +
+
+ ); + } - for (let i = 0; i < question.answerSolutionDescriptions.length; i++) { - const description = question.answerSolutionDescriptions[i]; - if (!isNaN(NumCast(description))) { - solutions.push(NumCast(description)); - } else if (description === 'solve normal force angle from wedge angle') { - solutions.push(90 - theta); - } else if (description === 'solve normal force magnitude from wedge angle') { - solutions.push(Math.abs(this.gravity) * Math.cos((theta / 180) * Math.PI)); - } else if (description === 'solve static force magnitude from wedge angle given equilibrium') { - const normalForceMagnitude = Math.abs(this.gravity) * Math.cos((theta / 180) * Math.PI); - const normalForceAngle = 90 - theta; - const frictionForceAngle = 180 - theta; - const frictionForceMagnitude = (-normalForceMagnitude * Math.sin((normalForceAngle * Math.PI) / 180) + Math.abs(this.gravity)) / Math.sin((frictionForceAngle * Math.PI) / 180); - solutions.push(frictionForceMagnitude); - } else if (description === 'solve static force angle from wedge angle given equilibrium') { - solutions.push(180 - theta); - } else if (description === 'solve minimum static coefficient from wedge angle given equilibrium') { - const normalForceMagnitude = Math.abs(this.gravity) * Math.cos((theta / 180) * Math.PI); - const normalForceAngle = 90 - theta; - const frictionForceAngle = 180 - theta; - const frictionForceMagnitude = (-normalForceMagnitude * Math.sin((normalForceAngle * Math.PI) / 180) + Math.abs(this.gravity)) / Math.sin((frictionForceAngle * Math.PI) / 180); - const frictionCoefficient = frictionForceMagnitude / normalForceMagnitude; - solutions.push(frictionCoefficient); - } else if (description === 'solve maximum wedge angle from coefficient of static friction given equilibrium') { - solutions.push((Math.atan(muS) * 180) / Math.PI); - } - } - this.dataDoc.selectedSolutions = new List(solutions); - return solutions; + @action + onPropertiesPointerDown = (e: React.PointerEvent) => { + setupMoveUpEvents( + this, + e, + action(() => { + SnappingManager.SetPropertiesWidth(Math.max(0, this._dashUIWidth - e.clientX)); + return !SnappingManager.PropertiesWidth; + }), + action(() => { + SnappingManager.PropertiesWidth < 5 && SnappingManager.SetPropertiesWidth(0); + }), + action(() => { + SnappingManager.SetPropertiesWidth(this.propertiesWidth() < 15 ? Math.min(this._dashUIWidth - 50, 250) : 0); + }), + false + ); }; - // In review mode, check if input answers match correct answers and optionally generate alert - checkAnswers = (showAlert: boolean = true) => { - let error: boolean = false; - const epsilon: number = 0.01; - if (this.selectedQuestion) { - for (let i = 0; i < this.selectedQuestion.answerParts.length; i++) { - if (this.selectedQuestion.answerParts[i] === 'force of gravity') { - if (Math.abs(NumCast(this.dataDoc.review_GravityMagnitude) - this.selectedSolutions[i]) > epsilon) { - error = true; - } - } else if (this.selectedQuestion.answerParts[i] === 'angle of gravity') { - if (Math.abs(NumCast(this.dataDoc.review_GravityAngle) - this.selectedSolutions[i]) > epsilon) { - error = true; - } - } else if (this.selectedQuestion.answerParts[i] === 'normal force') { - if (Math.abs(NumCast(this.dataDoc.review_NormalMagnitude) - this.selectedSolutions[i]) > epsilon) { - error = true; - } - } else if (this.selectedQuestion.answerParts[i] === 'angle of normal force') { - if (Math.abs(NumCast(this.dataDoc.review_NormalAngle) - this.selectedSolutions[i]) > epsilon) { - error = true; - } - } else if (this.selectedQuestion.answerParts[i] === 'force of static friction') { - if (Math.abs(NumCast(this.dataDoc.review_StaticMagnitude) - this.selectedSolutions[i]) > epsilon) { - error = true; - } - } else if (this.selectedQuestion.answerParts[i] === 'angle of static friction') { - if (Math.abs(NumCast(this.dataDoc.review_StaticAngle) - this.selectedSolutions[i]) > epsilon) { - error = true; - } - } else if (this.selectedQuestion.answerParts[i] === 'coefficient of static friction') { - if (Math.abs(NumCast(this.dataDoc.coefficientOfStaticFriction) - this.selectedSolutions[i]) > epsilon) { - error = true; - } - } else if (this.selectedQuestion.answerParts[i] === 'wedge angle') { - if (Math.abs(this.wedgeAngle - this.selectedSolutions[i]) > epsilon) { - error = true; - } - } - } - } - if (showAlert) { - this.dataDoc.simulation_paused = false; - setTimeout(() => (this.dataDoc.simulation_paused = true), 3000); - } - if (this.selectedQuestion.goal === 'noMovement') { - this.dataDoc.noMovement = !error; - } + @action + onFlyoutPointerDown = (e: React.PointerEvent) => { + setupMoveUpEvents( + this, + e, + action(ev => { + this._leftMenuFlyoutWidth = Math.max(ev.clientX - 58, 0); + return false; + }), + () => this._leftMenuFlyoutWidth < 5 && this.closeFlyout(), + this.closeFlyout + ); }; - // Reset all review values to default - resetReviewValuesToDefault = () => { - this.dataDoc.review_GravityMagnitude = 0; - this.dataDoc.review_GravityAngle = 0; - this.dataDoc.review_NormalMagnitude = 0; - this.dataDoc.review_NormalAngle = 0; - this.dataDoc.review_StaticMagnitude = 0; - this.dataDoc.review_StaticAngle = 0; - this.dataDoc.coefficientOfKineticFriction = 0; - this.dataDoc.simulation_paused = true; + sidebarScreenToLocal = () => new Transform(0, -this.topOfSidebarDoc, 1); + mainContainerXf = () => this.sidebarScreenToLocal().translate(-this.leftScreenOffsetOfMainDocView, 0); + static addDocTabFunc_impl = (docs: Doc | Doc[], location: OpenWhere): boolean => { + const doc = toList(docs).lastElement(); + const whereFields = location.split(':'); + const keyValue = whereFields.includes(OpenWhereMod.keyvalue); + const whereMods = whereFields.length > 1 ? (whereFields[1] as OpenWhereMod) : OpenWhereMod.none; + const panelName = whereFields.length > 1 ? whereFields.lastElement() : ''; + if (doc.dockingConfig && !keyValue) return DashboardView.openDashboard(doc); + switch (whereFields[0]) { + case OpenWhere.lightbox: return LightboxView.Instance.AddDocTab(doc, location); + case OpenWhere.close: return CollectionDockingView.CloseSplit(doc, whereMods); + case OpenWhere.toggle: return CollectionDockingView.ToggleSplit(doc, whereMods, undefined, TabDocView.DontSelectOnActivate); // bcz: hack! mark the toggle so that it won't be selected on activation- this is needed so that the backlinks menu can toggle views of targets on and off without selecting them + case OpenWhere.replace: return CollectionDockingView.ReplaceTab(doc, whereMods, undefined, panelName); + case OpenWhere.add:default:return CollectionDockingView.AddSplit(doc, whereMods, undefined, undefined, keyValue); + } // prettier-ignore }; - // In review mode, reset problem variables and generate a new question - generateNewQuestion = () => { - this.resetReviewValuesToDefault(); - - const vars: number[] = []; - let question: QuestionTemplate = questions.inclinePlane[0]; - - if (this.simulationType === 'Inclined Plane') { - this.dataDoc.questionNumber = (NumCast(this.dataDoc.questionNumber) + 1) % questions.inclinePlane.length; - question = questions.inclinePlane[NumCast(this.dataDoc.questionNumber)]; + @computed get flyout() { + return !this._leftMenuFlyoutWidth ? ( +
+ {this.docButtons} +
+ ) : ( +
+
+ +
+ {this.docButtons} +
+ ); + } - let coefficient = 0; - let wedge_angle = 0; + @computed get leftMenuPanel() { + return ( +
+ +
+ ); + } - for (let i = 0; i < question.variablesForQuestionSetup.length; i++) { - if (question.variablesForQuestionSetup[i] === 'theta - max 45') { - const randValue = Math.floor(Math.random() * 44 + 1); - vars.push(randValue); - wedge_angle = randValue; - } else if (question.variablesForQuestionSetup[i] === 'coefficient of static friction') { - const randValue = Math.round(Math.random() * 1000) / 1000; - vars.push(randValue); - coefficient = randValue; - } - } - this.dataDoc.wedge_angle = wedge_angle; - this.changeWedgeBasedOnNewAngle(wedge_angle); - this.dataDoc.coefficientOfStaticFriction = coefficient; - this.dataDoc.review_Coefficient = coefficient; - } - let q = ''; - for (let i = 0; i < question.questionSetup.length; i++) { - q += question.questionSetup[i]; - if (i !== question.questionSetup.length - 1) { - q += vars[i]; - if (question.variablesForQuestionSetup[i].includes('theta')) { - q += ' degree (≈' + Math.round((1000 * (vars[i] * Math.PI)) / 180) / 1000 + ' rad)'; - } + @action + selectMenu = (button: Doc) => { + const title = StrCast(button[DocData].title); + const willOpen = !this._leftMenuFlyoutWidth || this._panelContent !== title; + this.closeFlyout(); + if (willOpen) { + switch ((this._panelContent = title)) { + case 'Settings': + SettingsManager.Instance.openMgr(); + break; + case 'Help': + break; + default: + this.expandFlyout(button); } } - this.dataDoc.questionVariables = new List(vars); - this.dataDoc.selectedQuestion = JSON.stringify(question); - this.dataDoc.questionPartOne = q; - this.dataDoc.questionPartTwo = question.question; - this.dataDoc.answers = new List(this.getAnswersToQuestion(question, vars)); - // this.dataDoc.simulation_reset = (!this.dataDoc.simulation_reset); + return true; }; - // Default setup for uniform circular motion simulation - @action - setupCircular = (value: number) => { - this.dataDoc.simulation_showComponentForces = false; - this.dataDoc.mass1_velocityYstart = 0; - this.dataDoc.mass1_velocityXstart = value; - const xPos = (this.xMax + this.xMin) / 2 - this.mass1Radius; - const yPos = (this.yMax + this.yMin) / 2 + this.circularMotionRadius - this.mass1Radius; - this.dataDoc.mass1_positionYstart = yPos; - this.dataDoc.mass1_positionXstart = xPos; - const tensionForce: IForce = { - description: 'Centripetal Force', - magnitude: (this.dataDoc.mass1_velocityXstart ** 2 * this.mass1) / this.circularMotionRadius, - directionInDegrees: 90, - }; - this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce]); - this.dataDoc.mass1_forcesStart = JSON.stringify([tensionForce]); - this._simReset++; - }; + @computed get mainInnerContent() { + const leftMenuFlyoutWidth = this._leftMenuFlyoutWidth + this.leftMenuWidth(); + const width = this.propertiesWidth() + leftMenuFlyoutWidth; + return ( + <> + {this._hideUI ? null : this.leftMenuPanel} +
+ {this.flyout} +
+ +
+
+ {this.dockingContent} - setupInclinedPlane = () => { - this.changeWedgeBasedOnNewAngle(this.wedgeAngle); - this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1)]); - this.updateForcesWithFriction(NumCast(this.dataDoc.coefficientOfStaticFriction)); - }; + {this._hideUI ? null : ( +
+ +
+ )} +
+
+ +
+
+
+
+ + ); + } - // Default setup for pendulum simulation - setupPendulum = () => { - const length = (300 * this._props.PanelWidth()) / 1000; - const angle = 30; - const x = length * Math.cos(((90 - angle) * Math.PI) / 180); - const y = length * Math.sin(((90 - angle) * Math.PI) / 180); - const xPos = this.xMax / 2 - x - this.mass1Radius; - const yPos = y - this.mass1Radius - 5; - this.dataDoc.mass1_positionXstart = xPos; - this.dataDoc.mass1_positionYstart = yPos; - const forceOfTension: IForce = { - description: 'Tension', - magnitude: this.mass1 * Math.abs(this.gravity) * Math.sin((60 * Math.PI) / 180), - directionInDegrees: 90 - angle, - }; - const gravityParallel: IForce = { - description: 'Gravity Parallel Component', - magnitude: this.mass1 * Math.abs(this.gravity) * Math.sin(((90 - angle) * Math.PI) / 180), - directionInDegrees: -angle - 90, - }; - const gravityPerpendicular: IForce = { - description: 'Gravity Perpendicular Component', - magnitude: this.mass1 * Math.abs(this.gravity) * Math.cos(((90 - angle) * Math.PI) / 180), - directionInDegrees: -angle, - }; + @computed get mainDashboardArea() { + return !this.userDoc ? null : ( +
{ + r && + new _global.ResizeObserver( + action(() => { + this._dashUIWidth = r.getBoundingClientRect().width; + this._dashUIHeight = r.getBoundingClientRect().height; + }) + ).observe(r); + }} + style={{ + color: 'black', + height: `calc(100% - ${this.topOfDashUI + this.topMenuHeight()}px)`, + width: '100%', + }}> + {this.mainInnerContent} +
+ ); + } - this.dataDoc.mass1_componentForces = JSON.stringify([forceOfTension, gravityParallel, gravityPerpendicular]); - this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1)]); - this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1), forceOfTension]); - this.dataDoc.pendulum_angle = this.dataDoc.pendulum_angleStart = 30; - this.dataDoc.pendulum_length = this.dataDoc.pendulum_lengthStart = 300; - }; + expandFlyout = action((button: Doc) => { + // bcz: What's going on here!? --- may be fixed now, so commenting out ... + // Chrome(not firefox) seems to have a bug when the flyout expands and there's a zoomed freeform tab. All of the div below the CollectionFreeFormView's main div + // generate the wrong value from getClientRectangle() -- specifically they return an 'x' that is the flyout's width greater than it should be. + // interactively adjusting the flyout fixes the problem. So does programmatically changing the value after a timeout to something *fractionally* different (ie, 1.5, not 1);) + this._leftMenuFlyoutWidth = this._leftMenuFlyoutWidth || 250; + // setTimeout(action(() => (this._leftMenuFlyoutWidth += 0.5))); - // Default setup for spring simulation - @action - setupSpring = () => { - this.dataDoc.simulation_showComponentForces = false; - this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1)]); - this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1)]); - this.dataDoc.mass1_positionXstart = this.xMax / 2 - this.mass1Radius; - this.dataDoc.mass1_positionYstart = 200; - this.dataDoc.spring_constant = 0.5; - this.dataDoc.spring_lengthRest = 200; - this.dataDoc.spring_lengthStart = 200; - this._simReset++; - }; + this._sidebarContent.proto = DocCast(button.target); + SnappingManager.SetLastPressedBtn(button[Id]); + }); - // Default setup for suspension simulation - @action - setupSuspension = () => { - const xPos = (this.xMax + this.xMin) / 2 - this.mass1Radius; - const yPos = this.yMin + 200; - this.dataDoc.mass1_positionYstart = yPos; - this.dataDoc.mass1_positionXstart = xPos; - this.dataDoc.mass1_positionY = this.getDisplayYPos(yPos); - this.dataDoc.mass1_positionX = xPos; - const tensionMag = (this.mass1 * Math.abs(this.gravity)) / (2 * Math.sin(Math.PI / 4)); - const tensionForce1: IForce = { - description: 'Tension', - magnitude: tensionMag, - directionInDegrees: 45, - }; - const tensionForce2: IForce = { - description: 'Tension', - magnitude: tensionMag, - directionInDegrees: 135, - }; - const gravity = this.gravityForce(this.mass1); - this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, gravity]); - this.dataDoc.mass1_forcesStart = JSON.stringify([tensionForce1, tensionForce2, gravity]); - this._simReset++; - }; + closeFlyout = action(() => { + SnappingManager.SetLastPressedBtn(''); + this._panelContent = 'none'; + this._sidebarContent.proto = undefined; + this._leftMenuFlyoutWidth = 0; + }); - // Default setup for pulley simulation - @action - setupPulley = () => { - this.dataDoc.simulation_showComponentForces = false; - this.dataDoc.mass1_positionYstart = (this.yMax + this.yMin) / 2; - this.dataDoc.mass1_positionXstart = (this.xMin + this.xMax) / 2 - 2 * this.mass1Radius - 5; - this.dataDoc.mass1_positionY = this.getDisplayYPos((this.yMax + this.yMin) / 2); - this.dataDoc.mass1_positionX = (this.xMin + this.xMax) / 2 - 2 * this.mass1Radius - 5; - const a = (-1 * ((this.mass1 - this.mass2) * Math.abs(this.gravity))) / (this.mass1 + this.mass2); - const gravityForce1 = this.gravityForce(this.mass1); - const tensionForce1: IForce = { - description: 'Tension', - magnitude: this.mass1 * a + this.mass1 * Math.abs(this.gravity), - directionInDegrees: 90, - }; - this.dataDoc.mass1_forcesUpdated = JSON.stringify([gravityForce1, tensionForce1]); - this.dataDoc.mass1_forcesStart = JSON.stringify([gravityForce1, tensionForce1]); + remButtonDoc = (docs: Doc | Doc[]) => toList(docs).reduce((flg: boolean, doc) => flg && !doc.dragOnlyWithinContainer && Doc.RemoveDocFromList(Doc.MyDockedBtns, 'data', doc), true); + moveButtonDoc = (docs: Doc | Doc[], targetCol: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => this.remButtonDoc(docs) && addDocument(docs); + addButtonDoc = (docs: Doc | Doc[]) => toList(docs).reduce((flg: boolean, doc) => flg && Doc.AddDocToList(Doc.MyDockedBtns, 'data', doc), true); - const gravityForce2 = this.gravityForce(this.mass2); - const tensionForce2: IForce = { - description: 'Tension', - magnitude: -this.mass2 * a + this.mass2 * Math.abs(this.gravity), - directionInDegrees: 90, - }; - this.dataDoc.mass2_positionYstart = (this.yMax + this.yMin) / 2; - this.dataDoc.mass2_positionXstart = (this.xMin + this.xMax) / 2 + 5; - this.dataDoc.mass2_positionY = this.getDisplayYPos((this.yMax + this.yMin) / 2); - this.dataDoc.mass2_positionX = (this.xMin + this.xMax) / 2 + 5; - this.dataDoc.mass2_forcesUpdated = JSON.stringify([gravityForce2, tensionForce2]); - this.dataDoc.mass2_forcesStart = JSON.stringify([gravityForce2, tensionForce2]); - this._simReset++; + buttonBarXf = () => { + if (!this._docBtnRef.current) return Transform.Identity(); + const { scale, translateX, translateY } = ClientUtils.GetScreenTransform(this._docBtnRef.current); + return new Transform(-translateX, -translateY, 1 / scale); }; - public static parseJSON(json: string) { - return !json ? [] : (JSON.parse(json) as IForce[]); + @computed get docButtons() { + return !Doc.MyDockedBtns ? null : ( +
+ + {['watching', 'recording'].includes(StrCast(this.userDoc?.presentationMode)) ?
{StrCast(this.userDoc?.presentationMode)}
: null} +
+ ); + } + @computed get snapLines() { + const dragged = DragManager.docsBeingDragged.lastElement() ?? DocumentView.SelectedDocs().lastElement(); + const dragPar = dragged ? CollectionFreeFormView.from(DocumentView.getViews(dragged).lastElement()) : undefined; + return !dragPar?.layoutDoc.freeform_snapLines ? null : ( +
+ + {[ + ...SnappingManager.HorizSnapLines.map((l, i) => ( + // eslint-disable-next-line react/no-array-index-key + + )), + ...SnappingManager.VertSnapLines.map((l, i) => ( + // eslint-disable-next-line react/no-array-index-key + + )), + ]} + +
+ ); + } + + @computed get inkResources() { + return ( + + + + + + + + + + + + + + + ); } - // Handle force change in review mode - updateReviewModeValues = () => { - const forceOfGravityReview: IForce = { - description: 'Gravity', - magnitude: NumCast(this.dataDoc.review_GravityMagnitude), - directionInDegrees: NumCast(this.dataDoc.review_GravityAngle), - }; - const normalForceReview: IForce = { - description: 'Normal Force', - magnitude: NumCast(this.dataDoc.review_NormalMagnitude), - directionInDegrees: NumCast(this.dataDoc.review_NormalAngle), - }; - const staticFrictionForceReview: IForce = { - description: 'Static Friction Force', - magnitude: NumCast(this.dataDoc.review_StaticMagnitude), - directionInDegrees: NumCast(this.dataDoc.review_StaticAngle), - }; - this.dataDoc.mass1_forcesStart = JSON.stringify([forceOfGravityReview, normalForceReview, staticFrictionForceReview]); - this.dataDoc.mass1_forcesUpdated = JSON.stringify([forceOfGravityReview, normalForceReview, staticFrictionForceReview]); + togglePropertiesFlyout = () => { + if (MainView.Instance.propertiesWidth() > 0) { + SnappingManager.SetPropertiesWidth(0); + } else { + SnappingManager.SetPropertiesWidth(300); + } }; - pause = () => (this.dataDoc.simulation_paused = true); - componentForces1 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass1_componentForces)); - setComponentForces1 = (forces: IForce[]) => (this.dataDoc.mass1_componentForces = JSON.stringify(forces)); - componentForces2 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass2_componentForces)); - setComponentForces2 = (forces: IForce[]) => (this.dataDoc.mass2_componentForces = JSON.stringify(forces)); - startForces1 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass1_forcesStart)); - startForces2 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass2_forcesStart)); - forcesUpdated1 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass1_forcesUpdated)); - setForcesUpdated1 = (forces: IForce[]) => (this.dataDoc.mass1_forcesUpdated = JSON.stringify(forces)); - forcesUpdated2 = () => PhysicsSimulationBox.parseJSON(StrCast(this.dataDoc.mass2_forcesUpdated)); - setForcesUpdated2 = (forces: IForce[]) => (this.dataDoc.mass2_forcesUpdated = JSON.stringify(forces)); - setPosition1 = (xPos: number | undefined, yPos: number | undefined) => { - yPos !== undefined && (this.dataDoc.mass1_positionY = Math.round(yPos * 100) / 100); - xPos !== undefined && (this.dataDoc.mass1_positionX = Math.round(xPos * 100) / 100); - }; - setPosition2 = (xPos: number | undefined, yPos: number | undefined) => { - yPos !== undefined && (this.dataDoc.mass2_positionY = Math.round(yPos * 100) / 100); - xPos !== undefined && (this.dataDoc.mass2_positionX = Math.round(xPos * 100) / 100); - }; - setVelocity1 = (xVel: number | undefined, yVel: number | undefined) => { - yVel !== undefined && (this.dataDoc.mass1_velocityY = (-1 * Math.round(yVel * 100)) / 100); - xVel !== undefined && (this.dataDoc.mass1_velocityX = Math.round(xVel * 100) / 100); - }; - setVelocity2 = (xVel: number | undefined, yVel: number | undefined) => { - yVel !== undefined && (this.dataDoc.mass2_velocityY = (-1 * Math.round(yVel * 100)) / 100); - xVel !== undefined && (this.dataDoc.mass2_velocityX = Math.round(xVel * 100) / 100); - }; - setAcceleration1 = (xAccel: number, yAccel: number) => { - this.dataDoc.mass1_accelerationY = yAccel; - this.dataDoc.mass1_accelerationX = xAccel; - }; - setAcceleration2 = (xAccel: number, yAccel: number) => { - this.dataDoc.mass2_accelerationY = yAccel; - this.dataDoc.mass2_accelerationX = xAccel; - }; - setPendulumAngle = (angle: number | undefined, length: number | undefined) => { - angle !== undefined && (this.dataDoc.pendulum_angle = angle); - length !== undefined && (this.dataDoc.pendulum_length = length); - }; - setSpringLength = (length: number) => { - this.dataDoc.spring_lengthStart = length; - }; - resetRequest = () => this._simReset; + lightboxMaxBorder = [200, 50]; render() { - const commonWeightProps = { - pause: this.pause, - paused: BoolCast(this.dataDoc.simulation_paused), - panelWidth: this._props.PanelWidth, - panelHeight: this._props.PanelHeight, - resetRequest: this.resetRequest, - xMax: this.xMax, - xMin: this.xMin, - yMax: this.yMax, - yMin: this.yMin, - wallPositions: this.wallPositions, - gravity: Math.abs(this.gravity), - timestepSize: 0.05, - showComponentForces: BoolCast(this.dataDoc.simulation_showComponentForces), - coefficientOfKineticFriction: NumCast(this.dataDoc.coefficientOfKineticFriction), - elasticCollisions: BoolCast(this.dataDoc.elasticCollisions), - simulationMode: this.simulationMode, - noMovement: BoolCast(this.dataDoc.noMovement), - circularMotionRadius: this.circularMotionRadius, - wedgeHeight: this.wedgeHeight, - wedgeWidth: this.wedgeWidth, - springConstant: this.springConstant, - springStartLength: this.springLengthStart, - springRestLength: this.springLengthRest, - setSpringLength: this.setSpringLength, - setPendulumAngle: this.setPendulumAngle, - pendulumAngle: this.pendulumAngle, - pendulumLength: this.pendulumLength, - startPendulumAngle: this.pendulumAngleStart, - startPendulumLength: this.pendulumLengthStart, - radius: this.mass1Radius, - simulationSpeed: NumCast(this.dataDoc.simulation_speed, 2), - showAcceleration: BoolCast(this.dataDoc.simulation_showAcceleration), - showForceMagnitudes: BoolCast(this.dataDoc.simulation_showForceMagnitudes), - showForces: BoolCast(this.dataDoc.simulation_showForces), - showVelocity: BoolCast(this.dataDoc.simulation_showVelocity), - simulationType: this.simulationType, - }; return ( -
-
-
-
-
- {!this.dataDoc.simulation_paused && ( -
- -
- )} -
-
- - {this.simulationType === 'Pulley' && ( - - )} -
-
- {(this.simulationType === 'One Weight' || this.simulationType === 'Inclined Plane') && - this.wallPositions?.map((element, index) => )} -
-
-
-
this._props.isContentActive() && e.stopPropagation()} - style={{ overflow: 'auto', height: `${Math.max(1, 800 / this._props.PanelWidth()) * 100}%`, transform: `scale(${Math.min(1, this._props.PanelWidth() / 850)})` }}> -
- - {this.dataDoc.simulation_paused && this.simulationMode !== 'Tutorial' && ( - (this.dataDoc.simulation_paused = false)}> - - - )} - {!this.dataDoc.simulation_paused && this.simulationMode !== 'Tutorial' && ( - (this.dataDoc.simulation_paused = true)}> - - - )} - {this.dataDoc.simulation_paused && this.simulationMode !== 'Tutorial' && ( - this._simReset++)}> - - - )} - -
- -
-
- -
-
- {this.simulationMode === 'Review' && this.simulationType !== 'Inclined Plane' && ( -
-

{this.simulationType} review problems in progress!

-
-
- )} - {this.simulationMode === 'Review' && this.simulationType === 'Inclined Plane' && ( -
- {!this.dataDoc.hintDialogueOpen && ( - (this.dataDoc.hintDialogueOpen = true)} - sx={{ - position: 'fixed', - left: this.xMax - 50 + 'px', - top: this.yMin + 14 + 'px', - }}> - - - )} - (this.dataDoc.hintDialogueOpen = false)}> - Hints - - {this.selectedQuestion.hints?.map((hint: any, index: number) => ( -
- -
- - - Hint {index + 1}: {hint.description} - - - {hint.content} -
-
-
- ))} -
- - - -
-
-
-

{this.questionPartOne}

-

{this.questionPartTwo}

-
-
- {this.selectedQuestion.answerParts.includes('force of gravity') && ( - Gravity magnitude

} - lowerBound={0} - dataDoc={this.dataDoc} - prop="review_GravityMagnitude" - step={0.1} - unit="N" - upperBound={50} - value={NumCast(this.dataDoc.review_GravityMagnitude)} - showIcon={BoolCast(this.dataDoc.simulation_showIcon)} - correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('force of gravity')]} - labelWidth="7em" - /> - )} - {this.selectedQuestion.answerParts.includes('angle of gravity') && ( - Gravity angle

} - lowerBound={0} - dataDoc={this.dataDoc} - prop="review_GravityAngle" - step={1} - unit="°" - upperBound={360} - value={NumCast(this.dataDoc.review_GravityAngle)} - radianEquivalent - showIcon={BoolCast(this.dataDoc.simulation_showIcon)} - correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('angle of gravity')]} - labelWidth="7em" - /> - )} - {this.selectedQuestion.answerParts.includes('normal force') && ( - Normal force magnitude

} - lowerBound={0} - dataDoc={this.dataDoc} - prop="review_NormalMagnitude" - step={0.1} - unit="N" - upperBound={50} - value={NumCast(this.dataDoc.review_NormalMagnitude)} - showIcon={BoolCast(this.dataDoc.simulation_showIcon)} - correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('normal force')]} - labelWidth="7em" - /> - )} - {this.selectedQuestion.answerParts.includes('angle of normal force') && ( - Normal force angle

} - lowerBound={0} - dataDoc={this.dataDoc} - prop="review_NormalAngle" - step={1} - unit="°" - upperBound={360} - value={NumCast(this.dataDoc.review_NormalAngle)} - radianEquivalent - showIcon={BoolCast(this.dataDoc.simulation_showIcon)} - correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('angle of normal force')]} - labelWidth="7em" - /> - )} - {this.selectedQuestion.answerParts.includes('force of static friction') && ( - Static friction magnitude

} - lowerBound={0} - dataDoc={this.dataDoc} - prop="review_StaticMagnitude" - step={0.1} - unit="N" - upperBound={50} - value={NumCast(this.dataDoc.review_StaticMagnitude)} - showIcon={BoolCast(this.dataDoc.simulation_showIcon)} - correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('force of static friction')]} - labelWidth="7em" - /> - )} - {this.selectedQuestion.answerParts.includes('angle of static friction') && ( - Static friction angle

} - lowerBound={0} - dataDoc={this.dataDoc} - prop="review_StaticAngle" - step={1} - unit="°" - upperBound={360} - value={NumCast(this.dataDoc.review_StaticAngle)} - radianEquivalent - showIcon={BoolCast(this.dataDoc.simulation_showIcon)} - correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('angle of static friction')]} - labelWidth="7em" - /> - )} - {this.selectedQuestion.answerParts.includes('coefficient of static friction') && ( - - μs - - } - lowerBound={0} - dataDoc={this.dataDoc} - prop="coefficientOfStaticFriction" - step={0.1} - unit="" - upperBound={1} - value={NumCast(this.dataDoc.coefficientOfStaticFriction)} - effect={this.updateReviewForcesBasedOnCoefficient} - showIcon={BoolCast(this.dataDoc.simulation_showIcon)} - correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('coefficient of static friction')]} - /> - )} - {this.selectedQuestion.answerParts.includes('wedge angle') && ( - θ} - lowerBound={0} - dataDoc={this.dataDoc} - prop="wedge_angle" - step={1} - unit="°" - upperBound={49} - value={this.wedgeAngle} - effect={(val: number) => { - this.changeWedgeBasedOnNewAngle(val); - this.updateReviewForcesBasedOnAngle(val); - }} - radianEquivalent - showIcon={BoolCast(this.dataDoc.simulation_showIcon)} - correctValue={NumListCast(this.dataDoc.answers)[this.selectedQuestion.answerParts.indexOf('wedge angle')]} - /> - )} -
-
-
- )} - {this.simulationMode === 'Tutorial' && ( -
-
-

Problem

-

{this.tutorial.question}

-
-
- { - let step = NumCast(this.dataDoc.tutorial_stepNumber) - 1; - step = Math.max(step, 0); - step = Math.min(step, this.tutorial.steps.length - 1); - this.dataDoc.tutorial_stepNumber = step; - this.dataDoc.mass1_forcesStart = JSON.stringify(this.tutorial.steps[step].forces); - this.dataDoc.mass1_forcesUpdated = JSON.stringify(this.tutorial.steps[step].forces); - this.dataDoc.simulation_showForceMagnitudes = this.tutorial.steps[step].showMagnitude; - }} - disabled={this.dataDoc.tutorial_stepNumber === 0}> - - -
-

- Step {NumCast(this.dataDoc.tutorial_stepNumber) + 1}: {this.tutorial.steps[NumCast(this.dataDoc.tutorial_stepNumber)].description} -

-

{this.tutorial.steps[NumCast(this.dataDoc.tutorial_stepNumber)].content}

-
- { - let step = NumCast(this.dataDoc.tutorial_stepNumber) + 1; - step = Math.max(step, 0); - step = Math.min(step, this.tutorial.steps.length - 1); - this.dataDoc.tutorial_stepNumber = step; - this.dataDoc.mass1_forcesStart = JSON.stringify(this.tutorial.steps[step].forces); - this.dataDoc.mass1_forcesUpdated = JSON.stringify(this.tutorial.steps[step].forces); - this.dataDoc.simulation_showForceMagnitudes = this.tutorial.steps[step].showMagnitude; - }} - disabled={this.dataDoc.tutorial_stepNumber === this.tutorial.steps.length - 1}> - - -
-
- {(this.simulationType === 'One Weight' || this.simulationType === 'Inclined Plane' || this.simulationType === 'Pendulum') &&

Resources

} - {this.simulationType === 'One Weight' && ( - - )} - {this.simulationType === 'Inclined Plane' && ( - - )} - {this.simulationType === 'Pendulum' && ( - - )} -
-
- )} - {this.simulationMode === 'Review' && this.simulationType === 'Inclined Plane' && ( -
-

(this.dataDoc.simulation_mode = 'Tutorial')}> - {' '} - Go to walkthrough{' '} -

-
- - -
-
- )} - {this.simulationMode === 'Freeform' && ( -
- - - {this.simulationType === 'One Weight' && ( - (this.dataDoc.elasticCollisions = !this.dataDoc.elasticCollisions)} />} - label="Make collisions elastic" - labelPlacement="start" - /> - )} - (this.dataDoc.simulation_showForces = !this.dataDoc.simulation_showForces)} />} - label="Show force vectors" - labelPlacement="start" - /> - {(this.simulationType === 'Inclined Plane' || this.simulationType === 'Pendulum') && ( - (this.dataDoc.simulation_showComponentForces = !this.dataDoc.simulation_showComponentForces)} />} - label="Show component force vectors" - labelPlacement="start" - /> - )} - (this.dataDoc.simulation_showAcceleration = !this.dataDoc.simulation_showAcceleration)} />} - label="Show acceleration vector" - labelPlacement="start" - /> - (this.dataDoc.simulation_showVelocity = !this.dataDoc.simulation_showVelocity)} />} - label="Show velocity vector" - labelPlacement="start" - /> - Speed} lowerBound={1} dataDoc={this.dataDoc} prop="simulation_speed" step={1} unit="x" upperBound={10} value={NumCast(this.dataDoc.simulation_speed, 2)} labelWidth="5em" /> - {this.dataDoc.simulation_paused && this.simulationType !== 'Circular Motion' && ( - Gravity} - lowerBound={-30} - dataDoc={this.dataDoc} - prop="gravity" - step={0.01} - unit="m/s2" - upperBound={0} - value={NumCast(this.dataDoc.simulation_gravity, -9.81)} - effect={(val: number) => this.setupSimulation()} - labelWidth="5em" - /> - )} - {this.dataDoc.simulation_paused && this.simulationType !== 'Pulley' && ( - Mass} - lowerBound={1} - dataDoc={this.dataDoc} - prop="mass1" - step={0.1} - unit="kg" - upperBound={5} - value={this.mass1 ?? 1} - effect={(val: number) => this.setupSimulation()} - labelWidth="5em" - /> - )} - {this.dataDoc.simulation_paused && this.simulationType === 'Pulley' && ( - Red mass} - lowerBound={1} - dataDoc={this.dataDoc} - prop="mass1" - step={0.1} - unit="kg" - upperBound={5} - value={this.mass1 ?? 1} - effect={(val: number) => this.setupSimulation()} - labelWidth="5em" - /> - )} - {this.dataDoc.simulation_paused && this.simulationType === 'Pulley' && ( - Blue mass} - lowerBound={1} - dataDoc={this.dataDoc} - prop="mass2" - step={0.1} - unit="kg" - upperBound={5} - value={this.mass2 ?? 1} - effect={(val: number) => this.setupSimulation()} - labelWidth="5em" - /> - )} - {this.dataDoc.simulation_paused && this.simulationType === 'Circular Motion' && ( - Rod length} - lowerBound={100} - dataDoc={this.dataDoc} - prop="circularMotionRadius" - step={5} - unit="m" - upperBound={250} - value={this.circularMotionRadius} - effect={(val: number) => this.setupSimulation()} - labelWidth="5em" - /> - )} - - - {this.simulationType === 'Spring' && this.dataDoc.simulation_paused && ( -
- Spring stiffness} - lowerBound={0.1} - dataDoc={this.dataDoc} - prop="spring_constant" - step={1} - unit="N/m" - upperBound={500} - value={this.springConstant} - effect={action(() => this._simReset++)} - radianEquivalent={false} - mode="Freeform" - labelWidth="7em" - /> - Rest length} - lowerBound={10} - dataDoc={this.dataDoc} - prop="spring_lengthRest" - step={100} - unit="" - upperBound={500} - value={this.springLengthRest} - effect={action(() => this._simReset++)} - radianEquivalent={false} - mode="Freeform" - labelWidth="7em" - /> - Starting displacement} - lowerBound={-(this.springLengthRest - 10)} - dataDoc={this.dataDoc} - prop="" - step={10} - unit="" - upperBound={this.springLengthRest} - value={this.springLengthStart - this.springLengthRest} - effect={action((val: number) => { - this.dataDoc.mass1_positionYstart = this.springLengthRest + val; - this.dataDoc.spring_lengthStart = this.springLengthRest + val; - this._simReset++; - })} - radianEquivalent={false} - mode="Freeform" - labelWidth="7em" - /> -
- )} - {this.simulationType === 'Inclined Plane' && this.dataDoc.simulation_paused && ( -
- θ} - lowerBound={0} - dataDoc={this.dataDoc} - prop="wedge_angle" - step={1} - unit="°" - upperBound={49} - value={this.wedgeAngle} - effect={action((val: number) => { - this.changeWedgeBasedOnNewAngle(val); - this._simReset++; - })} - radianEquivalent - mode="Freeform" - labelWidth="2em" - /> - - μs - - } - lowerBound={0} - dataDoc={this.dataDoc} - prop="coefficientOfStaticFriction" - step={0.1} - unit="" - upperBound={1} - value={NumCast(this.dataDoc.coefficientOfStaticFriction) ?? 0} - effect={action((val: number) => { - this.updateForcesWithFriction(val); - if (val < NumCast(this.dataDoc.coefficientOfKineticFriction)) { - this.dataDoc.soefficientOfKineticFriction = val; - } - this._simReset++; - })} - mode="Freeform" - labelWidth="2em" - /> - - μk - - } - lowerBound={0} - dataDoc={this.dataDoc} - prop="coefficientOfKineticFriction" - step={0.1} - unit="" - upperBound={NumCast(this.dataDoc.coefficientOfStaticFriction)} - value={NumCast(this.dataDoc.coefficientOfKineticFriction) ?? 0} - effect={action(() => this._simReset++)} - mode="Freeform" - labelWidth="2em" - /> -
- )} - {this.simulationType === 'Inclined Plane' && !this.dataDoc.simulation_paused && ( - - <> - θ: {Math.round(this.wedgeAngle * 100) / 100}° ≈ {Math.round(((this.wedgeAngle * Math.PI) / 180) * 100) / 100} rad -
- μ s: {this.dataDoc.coefficientOfStaticFriction} -
- μ k: {this.dataDoc.coefficientOfKineticFriction} - -
- )} - {this.simulationType === 'Pendulum' && !this.dataDoc.simulation_paused && ( - - θ: {Math.round(this.pendulumAngle * 100) / 100}° ≈ {Math.round(((this.pendulumAngle * Math.PI) / 180) * 100) / 100} rad - - )} - {this.simulationType === 'Pendulum' && this.dataDoc.simulation_paused && ( -
- Angle} - lowerBound={0} - dataDoc={this.dataDoc} - prop="pendulum_angle" - step={1} - unit="°" - upperBound={59} - value={NumCast(this.dataDoc.pendulum_angle, 30)} - effect={action(value => { - this.dataDoc.pendulum_angleStart = value; - this.dataDoc.pendulum_lengthStart = this.dataDoc.pendulum_length; - if (this.simulationType === 'Pendulum') { - const mag = this.mass1 * Math.abs(this.gravity) * Math.cos((value * Math.PI) / 180); - - const forceOfTension: IForce = { - description: 'Tension', - magnitude: mag, - directionInDegrees: 90 - value, - }; - const gravityParallel: IForce = { - description: 'Gravity Parallel Component', - magnitude: Math.abs(this.gravity) * Math.cos((value * Math.PI) / 180), - directionInDegrees: 270 - value, - }; - const gravityPerpendicular: IForce = { - description: 'Gravity Perpendicular Component', - magnitude: Math.abs(this.gravity) * Math.sin((value * Math.PI) / 180), - directionInDegrees: -value, - }; - - const length = this.pendulumLength; - const x = length * Math.cos(((90 - value) * Math.PI) / 180); - const y = length * Math.sin(((90 - value) * Math.PI) / 180); - const xPos = this.xMax / 2 - x - NumCast(this.dataDoc.radius); - const yPos = y - NumCast(this.dataDoc.radius) - 5; - this.dataDoc.mass1_positionXstart = xPos; - this.dataDoc.mass1_positionYstart = yPos; - - this.dataDoc.mass1_forcesStart = JSON.stringify([this.gravityForce(this.mass1), forceOfTension]); - this.dataDoc.mass1_forcesUpdated = JSON.stringify([this.gravityForce(this.mass1), forceOfTension]); - this.dataDoc.mass1_componentForces = JSON.stringify([forceOfTension, gravityParallel, gravityPerpendicular]); - this._simReset++; - } - })} - radianEquivalent - mode="Freeform" - labelWidth="5em" - /> - Rod length} - lowerBound={0} - dataDoc={this.dataDoc} - prop="pendulum_length" - step={1} - unit="m" - upperBound={400} - value={Math.round(this.pendulumLength)} - effect={action(value => { - if (this.simulationType === 'Pendulum') { - this.dataDoc.pendulum_angleStart = this.pendulumAngle; - this.dataDoc.pendulum_lengthStart = value; - this._simReset++; - } - })} - radianEquivalent={false} - mode="Freeform" - labelWidth="5em" - /> -
- )} -
- )} -
- {this.simulationMode === 'Freeform' && ( - - - - - - - - - - {(!this.dataDoc.simulation_paused || this.simulationType === 'Inclined Plane' || this.simulationType === 'Circular Motion' || this.simulationType === 'Pulley') && ( - - )}{' '} - {this.dataDoc.simulation_paused && this.simulationType !== 'Inclined Plane' && this.simulationType !== 'Circular Motion' && this.simulationType !== 'Pulley' && ( - - )}{' '} - {(!this.dataDoc.simulation_paused || this.simulationType === 'Inclined Plane' || this.simulationType === 'Circular Motion' || this.simulationType === 'Pulley') && ( - - )}{' '} - {this.dataDoc.simulation_paused && this.simulationType !== 'Inclined Plane' && this.simulationType !== 'Circular Motion' && this.simulationType !== 'Pulley' && ( - - )}{' '} - - - - {(!this.dataDoc.simulation_paused || (this.simulationType !== 'One Weight' && this.simulationType !== 'Circular Motion')) && ( - - )}{' '} - {this.dataDoc.simulation_paused && (this.simulationType === 'One Weight' || this.simulationType === 'Circular Motion') && ( - - )}{' '} - {(!this.dataDoc.simulation_paused || this.simulationType !== 'One Weight') && }{' '} - {this.dataDoc.simulation_paused && this.simulationType === 'One Weight' && ( - - )}{' '} - - - - - - - - - - - - -
{this.simulationType === 'Pulley' ? 'Red Weight' : ''}XY
{ - // window.open( - // "https://www.khanacademy.org/science/physics/two-dimensional-motion" - // ); - // }} - > - Position - {this.dataDoc.mass1_positionX + ''} m - { - this.dataDoc.mass1_xChange = value; - if (this.simulationType === 'Suspension') { - const x1rod = (this.xMax + this.xMin) / 2 - this.radius - this.yMin - 200; - const x2rod = (this.xMax + this.xMin) / 2 + this.yMin + 200 + this.radius; - const deltaX1 = value + this.radius - x1rod; - const deltaX2 = x2rod - (value + this.radius); - const deltaY = this.getYPosFromDisplay(NumCast(this.dataDoc.mass1_positionY)) + this.radius; - let dir1T = Math.PI - Math.atan(deltaY / deltaX1); - let dir2T = Math.atan(deltaY / deltaX2); - const tensionMag2 = (this.mass1 * Math.abs(this.gravity)) / ((-Math.cos(dir2T) / Math.cos(dir1T)) * Math.sin(dir1T) + Math.sin(dir2T)); - const tensionMag1 = (-tensionMag2 * Math.cos(dir2T)) / Math.cos(dir1T); - dir1T = (dir1T * 180) / Math.PI; - dir2T = (dir2T * 180) / Math.PI; - const tensionForce1: IForce = { - description: 'Tension', - magnitude: tensionMag1, - directionInDegrees: dir1T, - }; - const tensionForce2: IForce = { - description: 'Tension', - magnitude: tensionMag2, - directionInDegrees: dir2T, - }; - const gravity = this.gravityForce(this.mass1); - this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, gravity]); - } - }} - small - mode="Freeform" - /> - {`${NumCast(this.dataDoc.mass1_positionY)} m`} - { - this.dataDoc.mass1_yChange = value; - if (this.simulationType === 'Suspension') { - const x1rod = (this.xMax + this.xMin) / 2 - this.radius - this.yMin - 200; - const x2rod = (this.xMax + this.xMin) / 2 + this.yMin + 200 + this.radius; - const deltaX1 = NumCast(this.dataDoc.mass1_positionX) + this.radius - x1rod; - const deltaX2 = x2rod - (NumCast(this.dataDoc.mass1_positionX) + this.radius); - const deltaY = this.getYPosFromDisplay(value) + this.radius; - let dir1T = Math.PI - Math.atan(deltaY / deltaX1); - let dir2T = Math.atan(deltaY / deltaX2); - const tensionMag2 = (this.mass1 * Math.abs(this.gravity)) / ((-Math.cos(dir2T) / Math.cos(dir1T)) * Math.sin(dir1T) + Math.sin(dir2T)); - const tensionMag1 = (-tensionMag2 * Math.cos(dir2T)) / Math.cos(dir1T); - dir1T = (dir1T * 180) / Math.PI; - dir2T = (dir2T * 180) / Math.PI; - const tensionForce1: IForce = { - description: 'Tension', - magnitude: tensionMag1, - directionInDegrees: dir1T, - }; - const tensionForce2: IForce = { - description: 'Tension', - magnitude: tensionMag2, - directionInDegrees: dir2T, - }; - const gravity = this.gravityForce(this.mass1); - this.dataDoc.mass1_forcesUpdated = JSON.stringify([tensionForce1, tensionForce2, gravity]); - } - }} - small - mode="Freeform" - /> -
{ - // window.open( - // "https://www.khanacademy.org/science/physics/two-dimensional-motion" - // ); - // }} - > - Velocity - {`${NumCast(this.dataDoc.mass1_velocityX)} m/s`} - { - this.dataDoc.mass1_velocityXstart = value; - this._simReset++; - })} - small - mode="Freeform" - /> - {this.dataDoc.mass1_velocityY + ''} m/s - { - this.dataDoc.mass1_velocityYstart = -value; - }} - small - mode="Freeform" - /> -
{ - // window.open( - // "https://www.khanacademy.org/science/physics/two-dimensional-motion" - // ); - // }} - > - Acceleration - - {this.dataDoc.mass1_accelerationX + ''} m/s2 - - {this.dataDoc.mass1_accelerationY + ''} m/s2 -
- Momentum - {Math.round(NumCast(this.dataDoc.mass1_velocityX) * this.mass1 * 10) / 10} kg*m/s{Math.round(NumCast(this.dataDoc.mass1_velocityY) * this.mass1 * 10) / 10} kg*m/s
- )} - {this.simulationMode === 'Freeform' && this.simulationType === 'Pulley' && ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Blue WeightXY
- Position - {`${this.dataDoc.mass2_positionX} m`}{`${this.dataDoc.mass2_positionY} m`}
- Velocity - {`${this.dataDoc.mass2_positionX} m/s`}{`${this.dataDoc.mass2_positionY} m/s`}
- Acceleration - - {this.dataDoc.mass2_accelerationX + ''} m/s2 - - {this.dataDoc.mass2_accelerationY + ''} m/s2 -
- Momentum - {Math.round(NumCast(this.dataDoc.mass2_velocityX) * this.mass1 * 10) / 10} kg*m/s{Math.round(NumCast(this.dataDoc.mass2_velocityY) * this.mass1 * 10) / 10} kg*m/s
- )} -
- {this.simulationType !== 'Pendulum' && this.simulationType !== 'Spring' && ( -
-

Kinematic Equations

-
    -
  • - Position: x1=x0+v0t+ - 1⁄ - 2at - 2 -
  • -
  • - Velocity: v1=v0+at -
  • -
  • Acceleration: a = F/m
  • -
-
- )} - {this.simulationType === 'Spring' && ( -
-

Harmonic Motion Equations: Spring

-
    -
  • - Spring force: Fs=kd -
  • -
  • - Spring period: Ts=2π√m⁄ - k -
  • -
  • Equilibrium displacement for vertical spring: d = mg/k
  • -
  • - Elastic potential energy: Us=1⁄ - 2kd2 -
  • -
      -
    • Maximum when system is at maximum displacement, 0 when system is at 0 displacement
    • -
    -
  • - Translational kinetic energy: K=1⁄ - 2mv2 -
  • -
      -
    • Maximum when system is at maximum/minimum velocity (at 0 displacement), 0 when velocity is 0 (at maximum displacement)
    • -
    -
-
- )} - {this.simulationType === 'Pendulum' && ( -
-

Harmonic Motion Equations: Pendulum

-
    -
  • - Pendulum period: Tp=2π√l⁄ - g -
  • -
-
- )} -
-
-
- - - - - - - - - -

- {this.simulationType === 'Circular Motion' ? 'Z' : 'Y'} -

-

- X -

-
+
+ (ele => { + ele.scrollTop = ele.scrollLeft = 0; + })(document.getElementById('root')!) + } + ref={r => { + r && + new _global.ResizeObserver( + action(() => { + this._windowWidth = r.getBoundingClientRect().width; + this._windowHeight = r.getBoundingClientRect().height; + }) + ).observe(r); + }}> + {this.inkResources} + + + + + + + + + + + + + {this._hideUI ? null : } + + {DocButtonState.Instance.LinkEditorDocView ? ( + { + DocButtonState.Instance.LinkEditorDocView = undefined; + })} + docView={DocButtonState.Instance.LinkEditorDocView} + /> + ) : null} + {LinkInfo.Instance?.LinkInfo ? ( + // eslint-disable-next-line react/jsx-props-no-spreading + + ) : null} + {((page: string) => { + // prettier-ignore + switch (page) { + case 'home': return ; + case 'dashboard': + default: return (<> +
+ +
+ {this.mainDashboardArea} + ); + } + })(Doc.ActivePage)} + + + + + + + + + + + + + {this.snapLines} + + + +
); } } -Docs.Prototypes.TemplateMap.set(DocumentType.SIMULATION, { - data: '', - layout: { view: PhysicsSimulationBox, dataField: 'data' }, - options: { acl: '', _width: 1000, _height: 800, mass1: '', mass2: '', layout_nativeDimEditable: true, position: '', acceleration: '', pendulum: '', spring: '', wedge: '', simulation: '', review: '', systemIcon: 'BsShareFill' }, +// eslint-disable-next-line prefer-arrow-callback +ScriptingGlobals.add(function selectMainMenu(doc: Doc) { + MainView.Instance.selectMenu(doc); }); +// eslint-disable-next-line prefer-arrow-callback +ScriptingGlobals.add(function createNewPresentation() { + return MainView.Instance.createNewPresentation(); +}, 'creates a new presentation when called'); +// eslint-disable-next-line prefer-arrow-callback +ScriptingGlobals.add(function openPresentation(pres: Doc) { + return MainView.Instance.openPresentation(pres); +}, 'creates a new presentation when called'); +// eslint-disable-next-line prefer-arrow-callback +ScriptingGlobals.add(function createNewFolder() { + return MainView.Instance.createNewFolder(); +}, 'creates a new folder in myFiles when called'); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 467191735..09bb3649d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1270,7 +1270,7 @@ export class CollectionFreeFormView extends CollectionSubView, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string) => { + createDrawing = (e: React.PointerEvent, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => { strokeData.forEach((stroke: [InkData, string, string]) => { const bounds = InkField.getBounds(stroke[0]); const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); @@ -1291,16 +1291,16 @@ export class CollectionFreeFormView extends CollectionSubView { @observable private _size: number = 200; @observable private _autoColor: boolean = true; @observable private _regenInput: string = ''; - private _addFunc: (e: React.PointerEvent, strokeList: [InkData, string, string][], opts: DrawingOptions, gptRes: string) => void = () => {}; + private _addFunc: (e: React.PointerEvent, strokeList: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void = () => {}; private _deleteFunc: (doc?: Doc) => void = () => {}; private _lastInput: DrawingOptions = { text: '', complexity: 5, size: 300, autoColor: true, x: 0, y: 0 }; private _lastResponse: string = ''; @@ -86,7 +86,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { }; @action - displaySmartDrawHandler = (x: number, y: number, addFunc: (e: React.PointerEvent, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string) => void, deleteFunc: (doc?: Doc) => void) => { + displaySmartDrawHandler = (x: number, y: number, addFunc: (e: React.PointerEvent, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void, deleteFunc: (doc?: Doc) => void) => { this._pageX = x; this._pageY = y; this._display = true; @@ -95,9 +95,9 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { }; @action - displayRegenerate = (x: number, y: number, addFunc: (e: React.PointerEvent, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string) => void, deleteFunc: (doc?: Doc) => void) => { - const selectedDoc: Doc = DocumentView.SelectedDocs().lastElement(); - const docData = selectedDoc[DocData]; + displayRegenerate = (x: number, y: number, addFunc: (e: React.PointerEvent, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void, deleteFunc: (doc?: Doc) => void) => { + this._selectedDoc = DocumentView.SelectedDocs().lastElement(); + const docData = this._selectedDoc[DocData]; this._addFunc = addFunc; this._deleteFunc = deleteFunc; this._pageX = x; @@ -210,8 +210,10 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> { }); if (regenerate) { this._deleteFunc(this._selectedDoc); + this._addFunc(e, strokeData, this._lastInput, svg[0], this._selectedDoc); + } else { + this._addFunc(e, strokeData, this._lastInput, svg[0]); } - this._addFunc(e, strokeData, this._lastInput, svg[0]); } }; -- cgit v1.2.3-70-g09d2 From 22ef5658b825281f5dd51e3c51a62c3d53756dc0 Mon Sep 17 00:00:00 2001 From: eleanor-park Date: Tue, 2 Jul 2024 14:49:54 -0400 Subject: fixed pointer event problem --- .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 09bb3649d..0bdcc8450 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -518,8 +518,8 @@ export class CollectionFreeFormView extends CollectionSubView Date: Tue, 2 Jul 2024 17:00:12 -0400 Subject: fixed displaying marquee groups when Bounds isn't set. --- src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 23cf487ec..5aff3ed6f 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -375,8 +375,8 @@ export class MarqueeView extends ObservableReactComponent Date: Wed, 10 Jul 2024 09:21:12 -0400 Subject: fixed undoing bringToFront selections - made longPress observable work. made ink strokes keep Z index by default when clicked. --- src/client/documents/Documents.ts | 1 + src/client/util/SnappingManager.ts | 3 + src/client/views/MainView.tsx | 6 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 9 ++- src/client/views/nodes/DocumentView.tsx | 65 ++++++++++------------ 5 files changed, 44 insertions(+), 40 deletions(-) diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 2dcf8a54c..b96fdb4bd 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -849,6 +849,7 @@ export namespace Docs { I.text_align = 'center'; I.rotation = 0; I.defaultDoubleClick = 'ignore'; + I.keepZWhenDragged = true; I.author_date = new DateField(); I.acl_Guest = Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.View; // I.acl_Override = SharingPermissions.Unset; diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts index 1337d271f..cc0366c5b 100644 --- a/src/client/util/SnappingManager.ts +++ b/src/client/util/SnappingManager.ts @@ -11,6 +11,7 @@ export class SnappingManager { return SnappingManager._manager ?? new SnappingManager(); } + @observable _longPress = false; @observable _shiftKey = false; @observable _ctrlKey = false; @observable _metaKey = false; @@ -43,6 +44,7 @@ export class SnappingManager { public static get HorizSnapLines() { return this.Instance._horizSnapLines; } // prettier-ignore public static get VertSnapLines() { return this.Instance._vertSnapLines; } // prettier-ignore + public static get LongPress() { return this.Instance._longPress; } // prettier-ignore public static get ShiftKey() { return this.Instance._shiftKey; } // prettier-ignore public static get CtrlKey() { return this.Instance._ctrlKey; } // prettier-ignore public static get MetaKey() { return this.Instance._metaKey; } // prettier-ignore @@ -58,6 +60,7 @@ export class SnappingManager { public static get PropertiesWidth(){ return this.Instance._propertyWid; } // prettier-ignore public static get PrintToConsole() { return this.Instance._printToConsole; } // prettier-ignore + public static SetLongPress = (press: boolean) => runInAction(() => {this.Instance._longPress = press}); // prettier-ignore public static SetShiftKey = (down: boolean) => runInAction(() => {this.Instance._shiftKey = down}); // prettier-ignore public static SetCtrlKey = (down: boolean) => runInAction(() => {this.Instance._ctrlKey = down}); // prettier-ignore public static SetMetaKey = (down: boolean) => runInAction(() => {this.Instance._metaKey = down}); // prettier-ignore diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 31d88fb87..ef1bcfb64 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -555,16 +555,16 @@ export class MainView extends ObservableReactComponent<{}> { private longPressTimer: NodeJS.Timeout | undefined; globalPointerClick = action(() => { this.longPressTimer && clearTimeout(this.longPressTimer); - DocumentView.LongPress = false; + SnappingManager.SetLongPress(false); }); globalPointerMove = action((e: PointerEvent) => { if (e.movementX > 3 || e.movementY > 3) this.longPressTimer && clearTimeout(this.longPressTimer); }); globalPointerDown = action((e: PointerEvent) => { - DocumentView.LongPress = false; + SnappingManager.SetLongPress(false); this.longPressTimer = setTimeout( action(() => { - DocumentView.LongPress = true; + SnappingManager.SetLongPress(true); }), 1000 ); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 034a38e9c..29a499035 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -20,6 +20,11 @@ import { DocumentView, DocumentViewProps } from './DocumentView'; import { FieldViewProps } from './FieldView'; import { OpenWhere } from './OpenWhere'; +export enum GroupActive { // flags for whether a view is activate because of its relationship to a group + group = 'group', // this is a group that is activated because it's on an active canvas, but is not part of some other group + child = 'child', // this is a group child that is activated because its containing group is activated + inactive = 'inactive', // this is a group child but it is not active +} /// Ugh, typescript has no run-time way of iterating through the keys of an interface. so we need /// manaully keep this list of keys in synch wih the fields of the freeFormProps interface const freeFormPropsKeys = ['x', 'y', 'z', 'zIndex', 'rotation', 'opacity', 'backgroundColor', 'color', 'highlight', 'width', 'height', 'autoDim', 'transition']; @@ -274,7 +279,9 @@ export class CollectionFreeFormDocumentView extends DocComponent this._props.rotation; render() { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 0ded01c80..3cf40c087 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -43,6 +43,7 @@ import { ObserverJsxParser } from '../ObservableReactComponent'; import { PinProps } from '../PinFuncs'; import { StyleProp } from '../StyleProp'; import { ViewBoxInterface } from '../ViewBoxInterface'; +import { GroupActive } from './CollectionFreeFormDocumentView'; import { DocumentContentsView } from './DocumentContentsView'; import { DocumentLinksButton } from './DocumentLinksButton'; import './DocumentView.scss'; @@ -153,7 +154,7 @@ export class DocumentViewInternal extends DocComponent { - if (this._props.isGroupActive?.() === 'child' && !this._props.isDocumentActive?.()) return; - const documentView = this._docView; - if (documentView && !this.Document.ignoreClick && this._props.renderDepth >= 0 && ClientUtils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) { + if (this._props.isGroupActive?.() === GroupActive.child && !this._props.isDocumentActive?.()) return; + if (this._docView && !this.Document.ignoreClick && this._props.renderDepth >= 0 && ClientUtils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) { let stopPropagate = true; let preventDefault = true; - !this.layoutDoc._keepZWhenDragged && this._props.bringToFront?.(this.Document); const scriptProps = { this: this.Document, _readOnly_: false, scriptContext: this._props.scriptContext, - documentView, + documentView: this._docView, clientX: e.clientX, clientY: e.clientY, shiftKey: e.shiftKey, @@ -317,44 +316,39 @@ export class DocumentViewInternal extends DocComponent this.onDoubleClickHdlr.script.run(scriptProps, console.log).result?.select && this._props.select(false), 'on double click: ' + this.Document.title); - } else if (!Doc.IsSystem(this.Document) && defaultDblclick !== 'ignore') { - UndoManager.RunInBatch(() => this._props.addDocTab(this.Document, OpenWhere.lightboxAlways), 'double tap'); - DocumentView.DeselectAll(); - Doc.UnBrushDoc(this.Document); - } else { - this._singleClickFunc?.(); - } + undoable(() => { + if (this.onDoubleClickHdlr?.script) { + this.onDoubleClickHdlr.script.run(scriptProps, console.log).result?.select && this._props.select(false); + } else if (!Doc.IsSystem(this.Document) && defaultDblclick !== 'ignore') { + this._props.addDocTab(this.Document, OpenWhere.lightboxAlways); + DocumentView.DeselectAll(); + Doc.UnBrushDoc(this.Document); + } else this._singleClickFunc?.(); + }, 'on double click: ' + this.Document.title)(); this._doubleClickTimeout && clearTimeout(this._doubleClickTimeout); this._doubleClickTimeout = undefined; this._singleClickFunc = undefined; } else { - let clickFunc: undefined | (() => any); - if (!this.disableClickScriptFunc && this.onClickHdlr?.script) { - clickFunc = undoable(() => { - this.onClickHdlr?.script.run(scriptProps, console.log).result?.select && this._props.select(false); - }, 'click ' + this.Document.title); - } else { - // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTemplateForField implies we're clicking on part of a template instance and we want to select the whole template, not the part - if (this.layoutDoc.onDragStart && !(e.ctrlKey || e.button > 0)) { - stopPropagate = false; - } - preventDefault = false; - } - const sendToBack = e.altKey ? () => documentView._props.bringToFront?.(this.Document, true) : undefined; + const sendToBack = e.altKey ? () => this._props.bringToFront?.(this.Document, true) : undefined; const selectFunc = () => { + !this.layoutDoc._keepZWhenDragged && this._props.bringToFront?.(this.Document); // selecting a view that is part of a template proxies the selection back to the root of the template const templateRoot = !(e.ctrlKey || e.button > 0) && this._props.docViewPath?.().reverse().find(dv => !dv._props.TemplateDataDocument); // prettier-ignore (templateRoot || this._docView)?.select(e.ctrlKey || e.shiftKey, e.metaKey); }; - this._singleClickFunc = clickFunc ?? sendToBack ?? selectFunc; - const waitFordblclick = this._props.waitForDoubleClickToClick?.() ?? this.Document.waitForDoubleClickToClick; - if ((clickFunc && waitFordblclick !== 'never') || waitFordblclick === 'always') { + const clickFunc = this.onClickFunc?.()?.script ? () => (this.onClickFunc?.()?.script.run(scriptProps, console.log).result as Opt<{ select: boolean }>)?.select && this._props.select(false) : undefined; + if (!clickFunc) { + // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTemplateForField implies we're clicking on part of a template instance and we want to select the whole template, not the part + if (this.layoutDoc.onDragStart && !(e.ctrlKey || e.button > 0)) stopPropagate = false; + preventDefault = false; + } + this._singleClickFunc = undoable(clickFunc ?? sendToBack ?? selectFunc, 'click: ' + this.Document.title); + const waitForDblClick = this._props.waitForDoubleClickToClick?.() ?? this.Document.waitForDoubleClickToClick; + if ((clickFunc && waitForDblClick !== 'never') || waitForDblClick === 'always') { this._doubleClickTimeout && clearTimeout(this._doubleClickTimeout); this._doubleClickTimeout = setTimeout(this._singleClickFunc, 300); // eslint-disable-next-line no-use-before-define - } else if (!DocumentView.LongPress) { + } else if (!SnappingManager.LongPress) { this._singleClickFunc(); this._singleClickFunc = undefined; } @@ -365,9 +359,9 @@ export class DocumentViewInternal extends DocComponent { - if (this._props.isGroupActive?.() === 'child' && !this._props.isDocumentActive?.()) return; + if (this._props.isGroupActive?.() === GroupActive.child && !this._props.isDocumentActive?.()) return; // eslint-disable-next-line no-use-before-define - this._longPressSelector = setTimeout(() => DocumentView.LongPress && this._props.select(false), 1000); + this._longPressSelector = setTimeout(() => SnappingManager.LongPress && this._props.select(false), 1000); if (!DocumentView.DownDocView) DocumentView.DownDocView = this._docView; this._downX = e.clientX; @@ -418,7 +412,7 @@ export class DocumentViewInternal extends DocComponent { @@ -1124,7 +1118,6 @@ export class DocumentView extends DocComponent() { @observable private _htmlOverlayText: Opt = undefined; @observable private _isHovering = false; @observable private _selected = false; - @observable public static LongPress = false; @computed private get shouldNotScale() { return (this.layout_fitWidth && !this.nativeWidth) || this.ComponentView?.isUnstyledView?.(); -- cgit v1.2.3-70-g09d2 From f23ea0cbde3c4193b8039f317fe71d965c8cbf40 Mon Sep 17 00:00:00 2001 From: geireann Date: Wed, 10 Jul 2024 12:00:47 -0400 Subject: some lint fixes and updating packages. --- package-lock.json | 2995 ++++++++++++----------- package.json | 16 +- src/client/views/collections/CollectionMenu.tsx | 23 +- 3 files changed, 1622 insertions(+), 1412 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7c531e3a6..f11d8a462 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,7 +49,7 @@ "@types/pdf-parse": "^1.1.4", "@types/reveal": "^4.2.0", "@types/supercluster": "^7.1.3", - "@types/web": "^0.0.148", + "@types/web": "^0.0.151", "@types/webpack-hot-middleware": "^2.25.9", "@typescript-eslint/parser": "^7.8.0", "@webscopeio/react-textarea-autocomplete": "^4.9.2", @@ -115,7 +115,7 @@ "function-plot": "^1.23.3", "golden-layout": "^2.6.0", "google-auth-library": "^9.4.1", - "googleapis": "^133.0.0", + "googleapis": "^140.0.1", "googlephotos": "^0.3.5", "got": "^14.0.0", "howler": "^2.2.4", @@ -154,7 +154,7 @@ "nodemon": "^3.0.2", "npm": "^10.2.5", "openai": "^4.26.0", - "p-limit": "^5.0.0", + "p-limit": "^6.1.0", "passport": "^0.7.0", "passport-google-oauth20": "^2.0.0", "passport-local": "^1.0.0", @@ -184,11 +184,11 @@ "react-awesome-reveal": "^4.2.7", "react-color": "^2.19.3", "react-compound-slider": "^3.4.0", - "react-datepicker": "^6.1.0", + "react-datepicker": "^7.3.0", "react-dom": "^18.2.0", "react-grid-layout": "^1.4.4", "react-icons": "^5.0.1", - "react-jsx-parser": "^1.29.0", + "react-jsx-parser": "^2.0.0", "react-latex-next": "^3.0.0", "react-loading": "^2.0.3", "react-map-gl": "^7.1.6", @@ -208,7 +208,7 @@ "request": "^2.88.2", "request-promise": "^4.2.6", "reveal.js": "^5.0.2", - "rimraf": "^5.0.5", + "rimraf": "^6.0.0", "sass": "^1.69.5", "sass-loader": "^14.2.0", "serializr": "^3.0.2", @@ -230,7 +230,7 @@ "url": "^0.11.3", "url-loader": "^4.1.1", "util": "^0.12.5", - "uuid": "^9.0.1", + "uuid": "^10.0.0", "valid-url": "^1.0.9", "web-request": "^1.0.7", "webpack": "^5.89.0", @@ -283,7 +283,7 @@ "@types/request": "^2.48.12", "@types/request-promise": "^4.1.51", "@types/shelljs": "^0.8.15", - "@types/uuid": "^9.0.7", + "@types/uuid": "^10.0.0", "@types/valid-url": "^1.0.7", "@types/webpack": "^5.28.5", "@types/youtube": "0.0.50", @@ -452,36 +452,56 @@ "node": ">=18.0.0" } }, - "node_modules/@azure/core-http": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@azure/core-http/-/core-http-3.0.4.tgz", - "integrity": "sha512-Fok9VVhMdxAFOtqiiAtg74fL0UJkt0z3D+ouUUxcRLzZNBioPRAMJFVxiWoJljYpXsRi4GDQHzQHDc9AiYaIUQ==", + "node_modules/@azure/core-client": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.9.2.tgz", + "integrity": "sha512-kRdry/rav3fUKHl/aDLd/pDLcB+4pOFwPPTVEExuMyaI5r+JBbMWqRbCY1pn5BniDaU3lRxO9eaQ1AmSMehl/w==", "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-tracing": "1.0.0-preview.13", - "@azure/core-util": "^1.1.1", + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.4.0", + "@azure/core-rest-pipeline": "^1.9.1", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.6.1", "@azure/logger": "^1.0.0", - "@types/node-fetch": "^2.5.0", - "@types/tunnel": "^0.0.3", - "form-data": "^4.0.0", - "node-fetch": "^2.6.7", - "process": "^0.11.10", - "tslib": "^2.2.0", - "tunnel": "^0.0.6", - "uuid": "^8.3.0", - "xml2js": "^0.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" } }, - "node_modules/@azure/core-http/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" + "node_modules/@azure/core-client/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-http-compat": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.1.2.tgz", + "integrity": "sha512-5MnV1yqzZwgNLLjlizsU3QqOeQChkIXw781Fwh1xdAqJR5AA32IUaq6xv1BICJvfbHoa+JYcaij2HFkhLbNTJQ==", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-client": "^1.3.0", + "@azure/core-rest-pipeline": "^1.3.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-http-compat/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@azure/core-lro": { @@ -520,16 +540,44 @@ "node": ">=18.0.0" } }, + "node_modules/@azure/core-rest-pipeline": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.16.1.tgz", + "integrity": "sha512-ExPSbgjwCoht6kB7B4MeZoBAxcQSIl29r/bPeazZJx50ej4JJCByimLOrZoIsurISNyJQQHf30b3JfqC3Hb88A==", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.4.0", + "@azure/core-tracing": "^1.0.1", + "@azure/core-util": "^1.9.0", + "@azure/logger": "^1.0.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@azure/core-tracing": { - "version": "1.0.0-preview.13", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.0-preview.13.tgz", - "integrity": "sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.1.2.tgz", + "integrity": "sha512-dawW9ifvWAWmUm9/h+/UQ2jrdvjCJ7VJEuCJ6XVNudzcOwm53BFZH4Q845vjfgoUAM8ZxokvVNxNxAITc502YA==", "dependencies": { - "@opentelemetry/api": "^1.0.1", - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=12.0.0" + "node": ">=18.0.0" } }, "node_modules/@azure/core-util": { @@ -555,6 +603,18 @@ "node": ">=18.0.0" } }, + "node_modules/@azure/core-xml": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@azure/core-xml/-/core-xml-1.4.2.tgz", + "integrity": "sha512-CW3MZhApe/S4iikbYKE7s83fjDBPIr2kpidX+hlGRwh7N4o1nIpQ/PfJTeioqhfqdMvRtheEl+ft64fyTaLNaA==", + "dependencies": { + "fast-xml-parser": "^4.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@azure/logger": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.1.2.tgz", @@ -567,29 +627,34 @@ } }, "node_modules/@azure/storage-blob": { - "version": "12.18.0", - "resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.18.0.tgz", - "integrity": "sha512-BzBZJobMoDyjJsPRMLNHvqHycTGrT8R/dtcTx9qUFcqwSRfGVK9A/cZ7Nx38UQydT9usZGbaDCN75QRNjezSAA==", + "version": "12.23.0", + "resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.23.0.tgz", + "integrity": "sha512-c1KJ5R5hqR/HtvmFtTn/Y1BNMq45NUBp0LZH7yF8WFMET+wmESgEr0FVTu/Z5NonmfUjbgJZG5Nh8xHc5RdWGQ==", "dependencies": { "@azure/abort-controller": "^1.0.0", - "@azure/core-http": "^3.0.0", + "@azure/core-auth": "^1.4.0", + "@azure/core-client": "^1.6.2", + "@azure/core-http-compat": "^2.0.0", "@azure/core-lro": "^2.2.0", "@azure/core-paging": "^1.1.1", - "@azure/core-tracing": "1.0.0-preview.13", + "@azure/core-rest-pipeline": "^1.10.1", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.6.1", + "@azure/core-xml": "^1.3.2", "@azure/logger": "^1.0.0", "events": "^3.0.0", "tslib": "^2.2.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" } }, "node_modules/@babel/code-frame": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz", - "integrity": "sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dependencies": { - "@babel/highlight": "^7.24.6", + "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" }, "engines": { @@ -597,29 +662,29 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.6.tgz", - "integrity": "sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", + "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.6.tgz", - "integrity": "sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", + "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.6", - "@babel/generator": "^7.24.6", - "@babel/helper-compilation-targets": "^7.24.6", - "@babel/helper-module-transforms": "^7.24.6", - "@babel/helpers": "^7.24.6", - "@babel/parser": "^7.24.6", - "@babel/template": "^7.24.6", - "@babel/traverse": "^7.24.6", - "@babel/types": "^7.24.6", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helpers": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -635,11 +700,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.6.tgz", - "integrity": "sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", + "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", "dependencies": { - "@babel/types": "^7.24.6", + "@babel/types": "^7.24.7", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -649,34 +714,35 @@ } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.6.tgz", - "integrity": "sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", "dependencies": { - "@babel/types": "^7.24.6" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.6.tgz", - "integrity": "sha512-+wnfqc5uHiMYtvRX7qu80Toef8BXeh4HHR1SPeonGb1SKPniNEd4a/nlaJJMv/OIEYvIVavvo0yR7u10Gqz0Iw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", "dependencies": { - "@babel/types": "^7.24.6" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz", - "integrity": "sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", + "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", "dependencies": { - "@babel/compat-data": "^7.24.6", - "@babel/helper-validator-option": "^7.24.6", + "@babel/compat-data": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", "browserslist": "^4.22.2", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -686,18 +752,18 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.6.tgz", - "integrity": "sha512-djsosdPJVZE6Vsw3kk7IPRWethP94WHGOhQTc67SNXE0ZzMhHgALw8iGmYS0TD1bbMM0VDROy43od7/hN6WYcA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.6", - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-function-name": "^7.24.6", - "@babel/helper-member-expression-to-functions": "^7.24.6", - "@babel/helper-optimise-call-expression": "^7.24.6", - "@babel/helper-replace-supers": "^7.24.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", - "@babel/helper-split-export-declaration": "^7.24.6", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.7.tgz", + "integrity": "sha512-kTkaDl7c9vO80zeX1rJxnuRpEsD5tA81yh11X1gQo+PhSti3JS+7qeZo9U4RHobKRiFPKaGK3svUAeb8D0Q7eg==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", "semver": "^6.3.1" }, "engines": { @@ -708,11 +774,11 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.6.tgz", - "integrity": "sha512-C875lFBIWWwyv6MHZUG9HmRrlTDgOsLWZfYR0nW69gaKJNe0/Mpxx5r0EID2ZdHQkdUmQo2t0uNckTL08/1BgA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz", + "integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-annotate-as-pure": "^7.24.7", "regexpu-core": "^5.3.1", "semver": "^6.3.1" }, @@ -739,68 +805,73 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz", - "integrity": "sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "dependencies": { + "@babel/types": "^7.24.7" + }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz", - "integrity": "sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", "dependencies": { - "@babel/template": "^7.24.6", - "@babel/types": "^7.24.6" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz", - "integrity": "sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", "dependencies": { - "@babel/types": "^7.24.6" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.6.tgz", - "integrity": "sha512-OTsCufZTxDUsv2/eDXanw/mUZHWOxSbEmC3pP8cgjcy5rgeVPWWMStnv274DV60JtHxTk0adT0QrCzC4M9NWGg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.7.tgz", + "integrity": "sha512-LGeMaf5JN4hAT471eJdBs/GK1DoYIJ5GCtZN/EsL6KUiiDZOvO/eKE11AMZJa2zP4zk4qe9V2O/hxAmkRc8p6w==", "dependencies": { - "@babel/types": "^7.24.6" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz", - "integrity": "sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "dependencies": { - "@babel/types": "^7.24.6" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz", - "integrity": "sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", + "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-module-imports": "^7.24.6", - "@babel/helper-simple-access": "^7.24.6", - "@babel/helper-split-export-declaration": "^7.24.6", - "@babel/helper-validator-identifier": "^7.24.6" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -810,32 +881,32 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.6.tgz", - "integrity": "sha512-3SFDJRbx7KuPRl8XDUr8O7GAEB8iGyWPjLKJh/ywP/Iy9WOmEfMrsWbaZpvBu2HSYn4KQygIsz0O7m8y10ncMA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", "dependencies": { - "@babel/types": "^7.24.6" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.6.tgz", - "integrity": "sha512-MZG/JcWfxybKwsA9N9PmtF2lOSFSEMVCpIRrbxccZFLJPrJciJdG/UhSh5W96GEteJI2ARqm5UAHxISwRDLSNg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", + "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.6.tgz", - "integrity": "sha512-1Qursq9ArRZPAMOZf/nuzVW8HgJLkTB9y9LfP4lW2MVp4e9WkLJDovfKBxoDcCk6VuzIxyqWHyBoaCtSRP10yg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz", + "integrity": "sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.6", - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-wrap-function": "^7.24.6" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-wrap-function": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -845,13 +916,13 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.6.tgz", - "integrity": "sha512-mRhfPwDqDpba8o1F8ESxsEkJMQkUF8ZIWrAc0FtWhxnjfextxMWxr22RtFizxxSYLjVHDeMgVsRq8BBZR2ikJQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", + "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-member-expression-to-functions": "^7.24.6", - "@babel/helper-optimise-call-expression": "^7.24.6" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -861,94 +932,97 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz", - "integrity": "sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "dependencies": { - "@babel/types": "^7.24.6" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.6.tgz", - "integrity": "sha512-jhbbkK3IUKc4T43WadP96a27oYti9gEf1LdyGSP2rHGH77kwLwfhO7TgwnWvxxQVmke0ImmCSS47vcuxEMGD3Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", "dependencies": { - "@babel/types": "^7.24.6" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz", - "integrity": "sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", "dependencies": { - "@babel/types": "^7.24.6" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz", - "integrity": "sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", + "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz", - "integrity": "sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz", - "integrity": "sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", + "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.6.tgz", - "integrity": "sha512-f1JLrlw/jbiNfxvdrfBgio/gRBk3yTAEJWirpAkiJG2Hb22E7cEYKHWo0dFPTv/niPovzIdPdEDetrv6tC6gPQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz", + "integrity": "sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==", "dependencies": { - "@babel/helper-function-name": "^7.24.6", - "@babel/template": "^7.24.6", - "@babel/types": "^7.24.6" + "@babel/helper-function-name": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.6.tgz", - "integrity": "sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", + "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", "peer": true, "dependencies": { - "@babel/template": "^7.24.6", - "@babel/types": "^7.24.6" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.6.tgz", - "integrity": "sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.6", + "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" @@ -958,9 +1032,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz", - "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", + "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", "bin": { "parser": "bin/babel-parser.js" }, @@ -969,12 +1043,12 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.6.tgz", - "integrity": "sha512-bYndrJ6Ph6Ar+GaB5VAc0JPoP80bQCm4qon6JEzXfRl5QZyQ8Ur1K6k7htxWmPA5z+k7JQvaMUrtXlqclWYzKw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz", + "integrity": "sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -984,11 +1058,11 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.6.tgz", - "integrity": "sha512-iVuhb6poq5ikqRq2XWU6OQ+R5o9wF+r/or9CeUyovgptz0UlnK4/seOQ1Istu/XybYjAhQv1FRSSfHHufIku5Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz", + "integrity": "sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -998,13 +1072,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.6.tgz", - "integrity": "sha512-c8TER5xMDYzzFcGqOEp9l4hvB7dcbhcGjcLVwxWfe4P5DOafdwjsBJZKsmv+o3aXh7NhopvayQIovHrh2zSRUQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", - "@babel/plugin-transform-optional-chaining": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1014,12 +1088,12 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.6.tgz", - "integrity": "sha512-z8zEjYmwBUHN/pCF3NuWBhHQjJCrd33qAi8MgANfMrAvn72k2cImT8VjK9LJFu4ysOLJqhfkYYb3MvwANRUNZQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz", + "integrity": "sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1098,11 +1172,11 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.6.tgz", - "integrity": "sha512-BE6o2BogJKJImTmGpkmOic4V0hlRRxVtzqxiSPa8TIFxyhi4EFjHm08nq1M4STK4RytuLMgnSz0/wfflvGFNOg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", + "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1112,11 +1186,11 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.6.tgz", - "integrity": "sha512-D+CfsVZousPXIdudSII7RGy52+dYRtbyKAZcvtQKq/NpsivyMVduepzcLqG5pMBugtMdedxdC8Ramdpcne9ZWQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", + "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1148,11 +1222,11 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.6.tgz", - "integrity": "sha512-lWfvAIFNWMlCsU0DRUun2GpFwZdGTukLaHJqRh1JRb80NdAP5Sb1HDHB5X9P9OtgZHQl089UzQkpYlBq2VTPRw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1271,11 +1345,11 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.6.tgz", - "integrity": "sha512-jSSSDt4ZidNMggcLx8SaKsbGNEfIl0PHx/4mFEulorE7bpYLbN0d3pDW3eJ7Y5Z3yPhy3L3NaPCYyTUY7TuugQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1285,13 +1359,13 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.6.tgz", - "integrity": "sha512-VEP2o4iR2DqQU6KPgizTW2mnMx6BG5b5O9iQdrW9HesLkv8GIA8x2daXBQxw1MrsIkFQGA/iJ204CKoQ8UcnAA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", + "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-remap-async-to-generator": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7", "@babel/plugin-syntax-async-generators": "^7.8.4" }, "engines": { @@ -1302,13 +1376,13 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.6.tgz", - "integrity": "sha512-NTBA2SioI3OsHeIn6sQmhvXleSl9T70YY/hostQLveWs0ic+qvbA3fa0kwAwQ0OA/XGaAerNZRQGJyRfhbJK4g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", "dependencies": { - "@babel/helper-module-imports": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-remap-async-to-generator": "^7.24.6" + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1318,11 +1392,11 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.6.tgz", - "integrity": "sha512-XNW7jolYHW9CwORrZgA/97tL/k05qe/HL0z/qqJq1mdWhwwCM6D4BJBV7wAz9HgFziN5dTOG31znkVIzwxv+vw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1332,11 +1406,11 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.6.tgz", - "integrity": "sha512-S/t1Xh4ehW7sGA7c1j/hiOBLnEYCp/c2sEG4ZkL8kI1xX9tW2pqJTCHKtdhe/jHKt8nG0pFCrDHUXd4DvjHS9w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", + "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1346,12 +1420,12 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.6.tgz", - "integrity": "sha512-j6dZ0Z2Z2slWLR3kt9aOmSIrBvnntWjMDN/TVcMPxhXMLmJVqX605CBRlcGI4b32GMbfifTEsdEjGjiE+j/c3A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", + "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1361,12 +1435,12 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.6.tgz", - "integrity": "sha512-1QSRfoPI9RoLRa8Mnakc6v3e0gJxiZQTYrMfLn+mD0sz5+ndSzwymp2hDcYJTyT0MOn0yuWzj8phlIvO72gTHA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { @@ -1377,17 +1451,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.6.tgz", - "integrity": "sha512-+fN+NO2gh8JtRmDSOB6gaCVo36ha8kfCW1nMq2Gc0DABln0VcHN4PrALDvF5/diLzIRKptC7z/d7Lp64zk92Fg==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.6", - "@babel/helper-compilation-targets": "^7.24.6", - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-function-name": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-replace-supers": "^7.24.6", - "@babel/helper-split-export-declaration": "^7.24.6", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.7.tgz", + "integrity": "sha512-CFbbBigp8ln4FU6Bpy6g7sE8B/WmCmzvivzUC6xDAdWVsjYTXijpuuGJmYkAaoWAzcItGKT3IOAbxRItZ5HTjw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", "globals": "^11.1.0" }, "engines": { @@ -1406,12 +1480,12 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.6.tgz", - "integrity": "sha512-cRzPobcfRP0ZtuIEkA8QzghoUpSB3X3qSH5W2+FzG+VjWbJXExtx0nbRqwumdBN1x/ot2SlTNQLfBCnPdzp6kg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/template": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1421,11 +1495,11 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.6.tgz", - "integrity": "sha512-YLW6AE5LQpk5npNXL7i/O+U9CE4XsBCuRPgyjl1EICZYKmcitV+ayuuUGMJm2lC1WWjXYszeTnIxF/dq/GhIZQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.7.tgz", + "integrity": "sha512-19eJO/8kdCQ9zISOf+SEUJM/bAUIsvY3YDnXZTupUCQ8LgrWnsG/gFB9dvXqdXnRXMAM8fvt7b0CBKQHNGy1mw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1435,12 +1509,12 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.6.tgz", - "integrity": "sha512-rCXPnSEKvkm/EjzOtLoGvKseK+dS4kZwx1HexO3BtRtgL0fQ34awHn34aeSHuXtZY2F8a1X8xqBBPRtOxDVmcA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1450,11 +1524,11 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.6.tgz", - "integrity": "sha512-/8Odwp/aVkZwPFJMllSbawhDAO3UJi65foB00HYnK/uXvvCPm0TAXSByjz1mpRmp0q6oX2SIxpkUOpPFHk7FLA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1464,11 +1538,11 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.6.tgz", - "integrity": "sha512-vpq8SSLRTBLOHUZHSnBqVo0AKX3PBaoPs2vVzYVWslXDTDIpwAcCDtfhUcHSQQoYoUvcFPTdC8TZYXu9ZnLT/w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" }, "engines": { @@ -1479,12 +1553,12 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.6.tgz", - "integrity": "sha512-EemYpHtmz0lHE7hxxxYEuTYOOBZ43WkDgZ4arQ4r+VX9QHuNZC+WH3wUWmRNvR8ECpTRne29aZV6XO22qpOtdA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1494,11 +1568,11 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.6.tgz", - "integrity": "sha512-inXaTM1SVrIxCkIJ5gqWiozHfFMStuGbGJAxZFBoHcRRdDP0ySLb3jH6JOwmfiinPwyMZqMBX+7NBDCO4z0NSA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { @@ -1509,12 +1583,12 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.6.tgz", - "integrity": "sha512-n3Sf72TnqK4nw/jziSqEl1qaWPbCRw2CziHH+jdRYvw4J6yeCzsj4jdw8hIntOEeDGTmHVe2w4MVL44PN0GMzg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1524,13 +1598,13 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.6.tgz", - "integrity": "sha512-sOajCu6V0P1KPljWHKiDq6ymgqB+vfo3isUS4McqW1DZtvSVU2v/wuMhmRmkg3sFoq6GMaUUf8W4WtoSLkOV/Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", + "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", "dependencies": { - "@babel/helper-compilation-targets": "^7.24.6", - "@babel/helper-function-name": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1540,11 +1614,11 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.6.tgz", - "integrity": "sha512-Uvgd9p2gUnzYJxVdBLcU0KurF8aVhkmVyMKW4MIY1/BByvs3EBpv45q01o7pRTVmTvtQq5zDlytP3dcUgm7v9w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { @@ -1555,11 +1629,11 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.6.tgz", - "integrity": "sha512-f2wHfR2HF6yMj+y+/y07+SLqnOSwRp8KYLpQKOzS58XLVlULhXbiYcygfXQxJlMbhII9+yXDwOUFLf60/TL5tw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", + "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1569,11 +1643,11 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.6.tgz", - "integrity": "sha512-EKaWvnezBCMkRIHxMJSIIylzhqK09YpiJtDbr2wsXTwnO0TxyjMUkaw4RlFIZMIS0iDj0KyIg7H7XCguHu/YDA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { @@ -1584,11 +1658,11 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.6.tgz", - "integrity": "sha512-9g8iV146szUo5GWgXpRbq/GALTnY+WnNuRTuRHWWFfWGbP9ukRL0aO/jpu9dmOPikclkxnNsjY8/gsWl6bmZJQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1598,12 +1672,12 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.6.tgz", - "integrity": "sha512-eAGogjZgcwqAxhyFgqghvoHRr+EYRQPFjUXrTYKBRb5qPnAVxOOglaxc4/byHqjvq/bqO2F3/CGwTHsgKJYHhQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", "dependencies": { - "@babel/helper-module-transforms": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1613,13 +1687,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.6.tgz", - "integrity": "sha512-JEV8l3MHdmmdb7S7Cmx6rbNEjRCgTQMZxllveHO0mx6uiclB0NflCawlQQ6+o5ZrwjUBYPzHm2XoK4wqGVUFuw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.7.tgz", + "integrity": "sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ==", "dependencies": { - "@babel/helper-module-transforms": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-simple-access": "^7.24.6" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1629,14 +1703,14 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.6.tgz", - "integrity": "sha512-xg1Z0J5JVYxtpX954XqaaAT6NpAY6LtZXvYFCJmGFJWwtlz2EmJoR8LycFRGNE8dBKizGWkGQZGegtkV8y8s+w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz", + "integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==", "dependencies": { - "@babel/helper-hoist-variables": "^7.24.6", - "@babel/helper-module-transforms": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-validator-identifier": "^7.24.6" + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1646,12 +1720,12 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.6.tgz", - "integrity": "sha512-esRCC/KsSEUvrSjv5rFYnjZI6qv4R1e/iHQrqwbZIoRJqk7xCvEUiN7L1XrmW5QSmQe3n1XD88wbgDTWLbVSyg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", "dependencies": { - "@babel/helper-module-transforms": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1661,12 +1735,12 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.6.tgz", - "integrity": "sha512-6DneiCiu91wm3YiNIGDWZsl6GfTTbspuj/toTEqLh9d4cx50UIzSdg+T96p8DuT7aJOBRhFyaE9ZvTHkXrXr6Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1676,11 +1750,11 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.6.tgz", - "integrity": "sha512-f8liz9JG2Va8A4J5ZBuaSdwfPqN6axfWRK+y66fjKYbwf9VBLuq4WxtinhJhvp1w6lamKUwLG0slK2RxqFgvHA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1690,11 +1764,11 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.6.tgz", - "integrity": "sha512-+QlAiZBMsBK5NqrBWFXCYeXyiU1y7BQ/OYaiPAcQJMomn5Tyg+r5WuVtyEuvTbpV7L25ZSLfE+2E9ywj4FD48A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { @@ -1705,11 +1779,11 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.6.tgz", - "integrity": "sha512-6voawq8T25Jvvnc4/rXcWZQKKxUNZcKMS8ZNrjxQqoRFernJJKjE3s18Qo6VFaatG5aiX5JV1oPD7DbJhn0a4Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-numeric-separator": "^7.10.4" }, "engines": { @@ -1720,14 +1794,14 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.6.tgz", - "integrity": "sha512-OKmi5wiMoRW5Smttne7BwHM8s/fb5JFs+bVGNSeHWzwZkWXWValR1M30jyXo1s/RaqgwwhEC62u4rFH/FBcBPg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", "dependencies": { - "@babel/helper-compilation-targets": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.24.6" + "@babel/plugin-transform-parameters": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1737,12 +1811,12 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.6.tgz", - "integrity": "sha512-N/C76ihFKlZgKfdkEYKtaRUtXZAgK7sOY4h2qrbVbVTXPrKGIi8aww5WGe/+Wmg8onn8sr2ut6FXlsbu/j6JHg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-replace-supers": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1752,11 +1826,11 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.6.tgz", - "integrity": "sha512-L5pZ+b3O1mSzJ71HmxSCmTVd03VOT2GXOigug6vDYJzE5awLI7P1g0wFcdmGuwSDSrQ0L2rDOe/hHws8J1rv3w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { @@ -1767,12 +1841,12 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.6.tgz", - "integrity": "sha512-cHbqF6l1QP11OkYTYQ+hhVx1E017O5ZcSPXk9oODpqhcAD1htsWG2NpHrrhthEO2qZomLK0FXS+u7NfrkF5aOQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.7.tgz", + "integrity": "sha512-tK+0N9yd4j+x/4hxF3F0e0fu/VdcxU18y5SevtyM/PCFlQvXbR0Zmlo2eBrKtVipGNFzpq56o8WsIIKcJFUCRQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { @@ -1783,11 +1857,11 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.6.tgz", - "integrity": "sha512-ST7guE8vLV+vI70wmAxuZpIKzVjvFX9Qs8bl5w6tN/6gOypPWUmMQL2p7LJz5E63vEGrDhAiYetniJFyBH1RkA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1797,12 +1871,12 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.6.tgz", - "integrity": "sha512-T9LtDI0BgwXOzyXrvgLTT8DFjCC/XgWLjflczTLXyvxbnSR/gpv0hbmzlHE/kmh9nOvlygbamLKRo6Op4yB6aw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", + "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1812,13 +1886,13 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.6.tgz", - "integrity": "sha512-Qu/ypFxCY5NkAnEhCF86Mvg3NSabKsh/TPpBVswEdkGl7+FbsYHy1ziRqJpwGH4thBdQHh8zx+z7vMYmcJ7iaQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.6", - "@babel/helper-create-class-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { @@ -1829,11 +1903,11 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.6.tgz", - "integrity": "sha512-oARaglxhRsN18OYsnPTpb8TcKQWDYNsPNmTnx5++WOAsUJ0cSC/FZVlIJCKvPbU4yn/UXsS0551CFKJhN0CaMw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1843,11 +1917,11 @@ } }, "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.6.tgz", - "integrity": "sha512-/3iiEEHDsJuj9QU09gbyWGSUxDboFcD7Nj6dnHIlboWSodxXAoaY/zlNMHeYAC0WsERMqgO9a7UaM77CsYgWcg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", + "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1857,15 +1931,15 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.6.tgz", - "integrity": "sha512-pCtPHhpRZHfwdA5G1Gpk5mIzMA99hv0R8S/Ket50Rw+S+8hkt3wBWqdqHaPw0CuUYxdshUgsPiLQ5fAs4ASMhw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz", + "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.6", - "@babel/helper-module-imports": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/plugin-syntax-jsx": "^7.24.6", - "@babel/types": "^7.24.6" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1875,11 +1949,11 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.6.tgz", - "integrity": "sha512-F7EsNp5StNDouSSdYyDSxh4J+xvj/JqG+Cb6s2fA+jCyHOzigG5vTwgH8tU2U8Voyiu5zCG9bAK49wTr/wPH0w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", + "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.24.6" + "@babel/plugin-transform-react-jsx": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1889,12 +1963,12 @@ } }, "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.6.tgz", - "integrity": "sha512-0HoDQlFJJkXRyV2N+xOpUETbKHcouSwijRQbKWVtxsPoq5bbB30qZag9/pSc5xcWVYjTHlLsBsY+hZDnzQTPNw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", + "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1904,11 +1978,11 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.6.tgz", - "integrity": "sha512-SMDxO95I8WXRtXhTAc8t/NFQUT7VYbIWwJCJgEli9ml4MhqUMh4S6hxgH6SmAC3eAQNWCDJFxcFeEt9w2sDdXg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.7", "regenerator-transform": "^0.15.2" }, "engines": { @@ -1919,11 +1993,11 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.6.tgz", - "integrity": "sha512-DcrgFXRRlK64dGE0ZFBPD5egM2uM8mgfrvTMOSB2yKzOtjpGegVYkzh3s1zZg1bBck3nkXiaOamJUqK3Syk+4A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1933,11 +2007,11 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.6.tgz", - "integrity": "sha512-xnEUvHSMr9eOWS5Al2YPfc32ten7CXdH7Zwyyk7IqITg4nX61oHj+GxpNvl+y5JHjfN3KXE2IV55wAWowBYMVw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1947,12 +2021,12 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.6.tgz", - "integrity": "sha512-h/2j7oIUDjS+ULsIrNZ6/TKG97FgmEk1PXryk/HQq6op4XUUUwif2f69fJrzK0wza2zjCS1xhXmouACaWV5uPA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1962,11 +2036,11 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.6.tgz", - "integrity": "sha512-fN8OcTLfGmYv7FnDrsjodYBo1DhPL3Pze/9mIIE2MGCT1KgADYIOD7rEglpLHZj8PZlC/JFX5WcD+85FLAQusw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1976,11 +2050,11 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.6.tgz", - "integrity": "sha512-BJbEqJIcKwrqUP+KfUIkxz3q8VzXe2R8Wv8TaNgO1cx+nNavxn/2+H8kp9tgFSOL6wYPPEgFvU6IKS4qoGqhmg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1990,11 +2064,11 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.6.tgz", - "integrity": "sha512-IshCXQ+G9JIFJI7bUpxTE/oA2lgVLAIK8q1KdJNoPXOpvRaNjMySGuvLfBw/Xi2/1lLo953uE8hyYSDW3TSYig==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.7.tgz", + "integrity": "sha512-VtR8hDy7YLB7+Pet9IarXjg/zgCMSF+1mNS/EQEiEaUPoFXCVsHG64SIxcaaI2zJgRiv+YmgaQESUfWAdbjzgg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2004,11 +2078,11 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.6.tgz", - "integrity": "sha512-bKl3xxcPbkQQo5eX9LjjDpU2xYHeEeNQbOhj0iPvetSzA+Tu9q/o5lujF4Sek60CM6MgYvOS/DJuwGbiEYAnLw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2018,12 +2092,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.6.tgz", - "integrity": "sha512-8EIgImzVUxy15cZiPii9GvLZwsy7Vxc+8meSlR3cXFmBIl5W5Tn9LGBf7CDKkHj4uVfNXCJB8RsVfnmY61iedA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2033,12 +2107,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.6.tgz", - "integrity": "sha512-pssN6ExsvxaKU638qcWb81RrvvgZom3jDgU/r5xFZ7TONkZGFf4MhI2ltMb8OcQWhHyxgIavEU+hgqtbKOmsPA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2048,12 +2122,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.6.tgz", - "integrity": "sha512-quiMsb28oXWIDK0gXLALOJRXLgICLiulqdZGOaPPd0vRT7fQp74NtdADAVu+D8s00C+0Xs0MxVP0VKF/sZEUgw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", + "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2063,26 +2137,26 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.6.tgz", - "integrity": "sha512-CrxEAvN7VxfjOG8JNF2Y/eMqMJbZPZ185amwGUBp8D9USK90xQmv7dLdFSa+VbD7fdIqcy/Mfv7WtzG8+/qxKg==", - "dependencies": { - "@babel/compat-data": "^7.24.6", - "@babel/helper-compilation-targets": "^7.24.6", - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-validator-option": "^7.24.6", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.6", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.6", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.6", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.7.tgz", + "integrity": "sha512-1YZNsc+y6cTvWlDHidMBsQZrZfEFjRIo/BZCT906PMdzOyXtSLTgqGdrpcuTDCXyd11Am5uQULtDIcCfnTc8fQ==", + "dependencies": { + "@babel/compat-data": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.7", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.24.6", - "@babel/plugin-syntax-import-attributes": "^7.24.6", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", @@ -2094,54 +2168,54 @@ "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.24.6", - "@babel/plugin-transform-async-generator-functions": "^7.24.6", - "@babel/plugin-transform-async-to-generator": "^7.24.6", - "@babel/plugin-transform-block-scoped-functions": "^7.24.6", - "@babel/plugin-transform-block-scoping": "^7.24.6", - "@babel/plugin-transform-class-properties": "^7.24.6", - "@babel/plugin-transform-class-static-block": "^7.24.6", - "@babel/plugin-transform-classes": "^7.24.6", - "@babel/plugin-transform-computed-properties": "^7.24.6", - "@babel/plugin-transform-destructuring": "^7.24.6", - "@babel/plugin-transform-dotall-regex": "^7.24.6", - "@babel/plugin-transform-duplicate-keys": "^7.24.6", - "@babel/plugin-transform-dynamic-import": "^7.24.6", - "@babel/plugin-transform-exponentiation-operator": "^7.24.6", - "@babel/plugin-transform-export-namespace-from": "^7.24.6", - "@babel/plugin-transform-for-of": "^7.24.6", - "@babel/plugin-transform-function-name": "^7.24.6", - "@babel/plugin-transform-json-strings": "^7.24.6", - "@babel/plugin-transform-literals": "^7.24.6", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.6", - "@babel/plugin-transform-member-expression-literals": "^7.24.6", - "@babel/plugin-transform-modules-amd": "^7.24.6", - "@babel/plugin-transform-modules-commonjs": "^7.24.6", - "@babel/plugin-transform-modules-systemjs": "^7.24.6", - "@babel/plugin-transform-modules-umd": "^7.24.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.6", - "@babel/plugin-transform-new-target": "^7.24.6", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.6", - "@babel/plugin-transform-numeric-separator": "^7.24.6", - "@babel/plugin-transform-object-rest-spread": "^7.24.6", - "@babel/plugin-transform-object-super": "^7.24.6", - "@babel/plugin-transform-optional-catch-binding": "^7.24.6", - "@babel/plugin-transform-optional-chaining": "^7.24.6", - "@babel/plugin-transform-parameters": "^7.24.6", - "@babel/plugin-transform-private-methods": "^7.24.6", - "@babel/plugin-transform-private-property-in-object": "^7.24.6", - "@babel/plugin-transform-property-literals": "^7.24.6", - "@babel/plugin-transform-regenerator": "^7.24.6", - "@babel/plugin-transform-reserved-words": "^7.24.6", - "@babel/plugin-transform-shorthand-properties": "^7.24.6", - "@babel/plugin-transform-spread": "^7.24.6", - "@babel/plugin-transform-sticky-regex": "^7.24.6", - "@babel/plugin-transform-template-literals": "^7.24.6", - "@babel/plugin-transform-typeof-symbol": "^7.24.6", - "@babel/plugin-transform-unicode-escapes": "^7.24.6", - "@babel/plugin-transform-unicode-property-regex": "^7.24.6", - "@babel/plugin-transform-unicode-regex": "^7.24.6", - "@babel/plugin-transform-unicode-sets-regex": "^7.24.6", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.24.7", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.24.7", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.24.7", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.7", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.24.7", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.24.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-modules-systemjs": "^7.24.7", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.7", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.10", "babel-plugin-polyfill-corejs3": "^0.10.4", @@ -2170,16 +2244,16 @@ } }, "node_modules/@babel/preset-react": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.6.tgz", - "integrity": "sha512-8mpzh1bWvmINmwM3xpz6ahu57mNaWavMm+wBNjQ4AFu1nghKBiIRET7l/Wmj4drXany/BBGjJZngICcD98F1iw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", + "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.6", - "@babel/helper-validator-option": "^7.24.6", - "@babel/plugin-transform-react-display-name": "^7.24.6", - "@babel/plugin-transform-react-jsx": "^7.24.6", - "@babel/plugin-transform-react-jsx-development": "^7.24.6", - "@babel/plugin-transform-react-pure-annotations": "^7.24.6" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.24.7", + "@babel/plugin-transform-react-jsx-development": "^7.24.7", + "@babel/plugin-transform-react-pure-annotations": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -2194,9 +2268,9 @@ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "node_modules/@babel/runtime": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.6.tgz", - "integrity": "sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz", + "integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -2205,9 +2279,9 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.24.6.tgz", - "integrity": "sha512-tbC3o8uHK9xMgMsvUm9qGqxVpbv6yborMBLbDteHIc7JDNHsTV0vDMQ5j1O1NXvO+BDELtL9KgoWYaUVIVGt8w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.24.7.tgz", + "integrity": "sha512-eytSX6JLBY6PVAeQa2bFlDx/7Mmln/gaEpsit5a3WEvjGfiIytEsgAwuIXCPM0xvw0v0cJn3ilq0/TvXrW0kgA==", "dependencies": { "core-js-pure": "^3.30.2", "regenerator-runtime": "^0.14.0" @@ -2217,31 +2291,31 @@ } }, "node_modules/@babel/template": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.6.tgz", - "integrity": "sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", "dependencies": { - "@babel/code-frame": "^7.24.6", - "@babel/parser": "^7.24.6", - "@babel/types": "^7.24.6" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.6.tgz", - "integrity": "sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==", - "dependencies": { - "@babel/code-frame": "^7.24.6", - "@babel/generator": "^7.24.6", - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-function-name": "^7.24.6", - "@babel/helper-hoist-variables": "^7.24.6", - "@babel/helper-split-export-declaration": "^7.24.6", - "@babel/parser": "^7.24.6", - "@babel/types": "^7.24.6", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", + "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2258,12 +2332,12 @@ } }, "node_modules/@babel/types": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.6.tgz", - "integrity": "sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", + "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", "dependencies": { - "@babel/helper-string-parser": "^7.24.6", - "@babel/helper-validator-identifier": "^7.24.6", + "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -2469,9 +2543,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", - "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -2548,10 +2622,21 @@ "node": "*" } }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@eslint/js": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.4.0.tgz", - "integrity": "sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.6.0.tgz", + "integrity": "sha512-D9B0/3vNg44ZeWbYMpBoXqNP4j6eQD5vNwIlGAuFRRzK/WtT/jvDQW3Bi9kkf3PMDMlM7Yi+73VLUsn5bJcl8A==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2585,29 +2670,29 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.2.tgz", - "integrity": "sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==", + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.4.tgz", + "integrity": "sha512-a4IowK4QkXl4SCWTGUR0INAfEOX3wtsYw3rKK5InQEHMGObkR8Xk44qYQD9P4r6HHw0iIfK6GUKECmY8sTkqRA==", "dependencies": { - "@floating-ui/utils": "^0.2.0" + "@floating-ui/utils": "^0.2.4" } }, "node_modules/@floating-ui/dom": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.5.tgz", - "integrity": "sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.7.tgz", + "integrity": "sha512-wmVfPG5o2xnKDU4jx/m4w5qva9FWHcnZ8BvzEe90D/RpwsJaTAVYPEPdQ8sbr/N8zZTAHlZUTQdqg8ZUbzHmng==", "dependencies": { - "@floating-ui/core": "^1.0.0", - "@floating-ui/utils": "^0.2.0" + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.4" } }, "node_modules/@floating-ui/react": { - "version": "0.26.16", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.16.tgz", - "integrity": "sha512-HEf43zxZNAI/E781QIVpYSF3K2VH4TTYZpqecjdsFkjsaU1EbaWcM++kw0HXFffj7gDUcBFevX8s0rQGQpxkow==", + "version": "0.26.19", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.19.tgz", + "integrity": "sha512-Jk6zITdjjIvjO/VdQFvpRaD3qPwOHH6AoDHxjhpy+oK4KFgaSP871HYWUAPdnLmx1gQ+w/pB312co3tVml+BXA==", "dependencies": { - "@floating-ui/react-dom": "^2.1.0", - "@floating-ui/utils": "^0.2.0", + "@floating-ui/react-dom": "^2.1.1", + "@floating-ui/utils": "^0.2.4", "tabbable": "^6.0.0" }, "peerDependencies": { @@ -2616,9 +2701,9 @@ } }, "node_modules/@floating-ui/react-dom": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.0.tgz", - "integrity": "sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz", + "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==", "dependencies": { "@floating-ui/dom": "^1.0.0" }, @@ -2628,9 +2713,9 @@ } }, "node_modules/@floating-ui/utils": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz", - "integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==" + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz", + "integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==" }, "node_modules/@formatjs/ecma402-abstract": { "version": "2.0.0", @@ -2746,30 +2831,30 @@ } }, "node_modules/@fullcalendar/core": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.13.tgz", - "integrity": "sha512-Cps/hMQan4kwnsBhFf2+m2mijbGoWs6r18ZzxBnAAOkkNHtPmHU8EdR6lF+ZLsiVvb7nsC4H/ZKqnxXWwgpoPw==", + "version": "6.1.14", + "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.14.tgz", + "integrity": "sha512-hIPRBevm0aMc2aHy1hRIJgXmI1QTvQM1neQa9oxtuqUmF1+ApYC3oAdwcQMTuI7lHHw3pKJDyJFkKLPPnL6HXA==", "dependencies": { "preact": "~10.12.1" } }, "node_modules/@fullcalendar/daygrid": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.13.tgz", - "integrity": "sha512-0I0hL1kgGjkZuc7Qt8mu4jjrqIL5PZzd58bEpTxoXRKI5UBZ9KbshGVMryQSXYANlrRtkPnXVt90VIDrxZbDrA==", + "version": "6.1.14", + "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.14.tgz", + "integrity": "sha512-DSyjiA1dEM8k3bOCrZpZOmAOZu71KGtH02ze+4QKuhxkmn/zQghmmLRdfzpOrcyJg6xGKkoB4pBcO+2lXar8XQ==", "peerDependencies": { - "@fullcalendar/core": "~6.1.13" + "@fullcalendar/core": "~6.1.14" } }, "node_modules/@fullcalendar/multimonth": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/@fullcalendar/multimonth/-/multimonth-6.1.13.tgz", - "integrity": "sha512-fn0BaLaMNkLmFzxijGZXYcO/fHQkuCcQV1R44mnu/01V4uSnFM1KPt2+V+6SgNiW1+ZNkUBHkkSLST1XdZjodw==", + "version": "6.1.14", + "resolved": "https://registry.npmjs.org/@fullcalendar/multimonth/-/multimonth-6.1.14.tgz", + "integrity": "sha512-el2vbZZgTkdufgOvRxqx61czjRMfEK50449g4SkqbagtS3ITNMAv84KHFcsbXVbd9Nh3UhbXDuYZuzJZpvY7mQ==", "dependencies": { - "@fullcalendar/daygrid": "~6.1.13" + "@fullcalendar/daygrid": "~6.1.14" }, "peerDependencies": { - "@fullcalendar/core": "~6.1.13" + "@fullcalendar/core": "~6.1.14" } }, "node_modules/@googlemaps/js-api-loader": { @@ -2793,6 +2878,7 @@ "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", "dependencies": { "@humanwhocodes/object-schema": "^2.0.2", "debug": "^4.3.1", @@ -2837,7 +2923,8 @@ "node_modules/@humanwhocodes/object-schema": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==" + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead" }, "node_modules/@icons/material": { "version": "0.2.4", @@ -3444,9 +3531,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", @@ -3494,9 +3581,9 @@ } }, "node_modules/@jsonjoy.com/util": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.1.3.tgz", - "integrity": "sha512-g//kkF4kOwUjemValCtOc/xiYzmwMRmWq3Bn+YnzOzuZLHq2PpMOxxIayN3cKbo7Ko2Np65t6D9H81IvXbXhqg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.2.0.tgz", + "integrity": "sha512-4B8B+3vFsY4eo33DMKyJPlQ3sBMpPFUZK2dr3O3rXrOGKKbYG44J0XSFkDo1VOQiri5HFEhIeVvItjR2xcazmg==", "engines": { "node": ">=10.0" }, @@ -3551,6 +3638,17 @@ "node-pre-gyp": "bin/node-pre-gyp" } }, + "node_modules/@mapbox/node-pre-gyp/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/@mapbox/node-pre-gyp/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3580,6 +3678,18 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@mapbox/node-pre-gyp/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@mapbox/node-pre-gyp/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3706,18 +3816,18 @@ } }, "node_modules/@mui/core-downloads-tracker": { - "version": "5.15.19", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.19.tgz", - "integrity": "sha512-tCHSi/Tomez9ERynFhZRvFO6n9ATyrPs+2N80DMDzp6xDVirbBjEwhPcE+x7Lj+nwYw0SqFkOxyvMP0irnm55w==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.0.tgz", + "integrity": "sha512-8SLffXYPRVpcZx5QzxNE8fytTqzp+IuU3deZbQWg/vSaTlDpR5YVrQ4qQtXTi5cRdhOufV5INylmwlKK+//nPw==", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" } }, "node_modules/@mui/icons-material": { - "version": "5.15.19", - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.19.tgz", - "integrity": "sha512-RsEiRxA5azN9b8gI7JRqekkgvxQUlitoBOtZglflb8cUDyP12/cP4gRwhb44Ea1/zwwGGjAj66ZJpGHhKfibNA==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.16.0.tgz", + "integrity": "sha512-6ISoOhkp9w5gD0PEW9JklrcbyARDkFWNTBdwXZ1Oy5IGlyu9B0zG0hnUIe4H17IaF1Vgj6C8VI+v4tkSdK0veg==", "dependencies": { "@babel/runtime": "^7.23.9" }, @@ -3740,16 +3850,16 @@ } }, "node_modules/@mui/material": { - "version": "5.15.19", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.19.tgz", - "integrity": "sha512-lp5xQBbcRuxNtjpWU0BWZgIrv2XLUz4RJ0RqFXBdESIsKoGCQZ6P3wwU5ZPuj5TjssNiKv9AlM+vHopRxZhvVQ==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.16.0.tgz", + "integrity": "sha512-DbR1NckTLpjt9Zut9EGQ70th86HfN0BYQgyYro6aXQrNfjzSwe3BJS1AyBQ5mJ7TdL6YVRqohfukxj9JlqZZUg==", "dependencies": { "@babel/runtime": "^7.23.9", "@mui/base": "5.0.0-beta.40", - "@mui/core-downloads-tracker": "^5.15.19", - "@mui/system": "^5.15.15", + "@mui/core-downloads-tracker": "^5.16.0", + "@mui/system": "^5.16.0", "@mui/types": "^7.2.14", - "@mui/utils": "^5.15.14", + "@mui/utils": "^5.16.0", "@types/react-transition-group": "^4.4.10", "clsx": "^2.1.0", "csstype": "^3.1.3", @@ -3784,12 +3894,12 @@ } }, "node_modules/@mui/private-theming": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.14.tgz", - "integrity": "sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.0.tgz", + "integrity": "sha512-sYpubkO1MZOnxNyVOClrPNOTs0MfuRVVnAvCeMaOaXt6GimgQbnUcshYv2pSr6PFj+Mqzdff/FYOBceK8u5QgA==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/utils": "^5.15.14", + "@mui/utils": "^5.16.0", "prop-types": "^15.8.1" }, "engines": { @@ -3841,15 +3951,15 @@ } }, "node_modules/@mui/system": { - "version": "5.15.15", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.15.tgz", - "integrity": "sha512-aulox6N1dnu5PABsfxVGOZffDVmlxPOVgj56HrUnJE8MCSh8lOvvkd47cebIVQQYAjpwieXQXiDPj5pwM40jTQ==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.0.tgz", + "integrity": "sha512-9YbkC2m3+pNumAvubYv+ijLtog6puJ0fJ6rYfzfLCM47pWrw3m+30nXNM8zMgDaKL6vpfWJcCXm+LPaWBpy7sw==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/private-theming": "^5.15.14", + "@mui/private-theming": "^5.16.0", "@mui/styled-engine": "^5.15.14", "@mui/types": "^7.2.14", - "@mui/utils": "^5.15.14", + "@mui/utils": "^5.16.0", "clsx": "^2.1.0", "csstype": "^3.1.3", "prop-types": "^15.8.1" @@ -3893,9 +4003,9 @@ } }, "node_modules/@mui/utils": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.14.tgz", - "integrity": "sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.0.tgz", + "integrity": "sha512-kLLi5J1xY+mwtUlMb8Ubdxf4qFAA1+U7WPBvjM/qQ4CIwLCohNb0sHo1oYPufjSIH/Z9+dhVxD7dJlfGjd1AVA==", "dependencies": { "@babel/runtime": "^7.23.9", "@types/prop-types": "^15.7.11", @@ -4039,14 +4149,6 @@ "@octokit/openapi-types": "^22.2.0" } }, - "node_modules/@opentelemetry/api": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.8.0.tgz", - "integrity": "sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==", - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -7923,6 +8025,25 @@ "url": "https://opencollective.com/turf" } }, + "node_modules/@turf/line-overlap/node_modules/deep-equal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz", + "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==", + "dependencies": { + "is-arguments": "^1.1.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.5.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/@turf/line-segment": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/@turf/line-segment/-/line-segment-6.5.0.tgz", @@ -8961,9 +9082,9 @@ } }, "node_modules/@types/d3-force": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.9.tgz", - "integrity": "sha512-IKtvyFdb4Q0LWna6ymywQsEYjK/94SGhPrMfEr1TIc5OBeziTi+1jcCvttts8e0UWZIxpasjnQk9MNk/3iS+kA==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", "dev": true }, "node_modules/@types/d3-format": { @@ -9145,9 +9266,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.3", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.3.tgz", - "integrity": "sha512-KOzM7MhcBFlmnlr/fzISFF5vGWVSvN6fTd4T+ExOt08bA/dA5kpSzY52nMsI1KDFmUREpJelPYyuslLRSjjgCg==", + "version": "4.19.5", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", + "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", "dev": true, "dependencies": { "@types/node": "*", @@ -9295,16 +9416,6 @@ "@types/sizzle": "*" } }, - "node_modules/@types/jsdom": { - "version": "16.2.15", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-16.2.15.tgz", - "integrity": "sha512-nwF87yjBKuX/roqGYerZZM0Nv1pZDMAT5YhOHYeM/72Fic+VEqJh4nyoqoapzJnW3pUlfxPY5FhgsJtM+dRnQQ==", - "dependencies": { - "@types/node": "*", - "@types/parse5": "^6.0.3", - "@types/tough-cookie": "*" - } - }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -9337,9 +9448,9 @@ } }, "node_modules/@types/lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ==", + "version": "4.17.6", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.6.tgz", + "integrity": "sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA==", "dev": true }, "node_modules/@types/mapbox-gl": { @@ -9371,9 +9482,9 @@ "dev": true }, "node_modules/@types/mocha": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", - "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", + "version": "10.0.7", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.7.tgz", + "integrity": "sha512-GN8yJ1mNTcFcah/wKEFIJckJx9iJLoMSzWcfRRuxz/Jk+U6KQNnml+etbtxFK8lPjzOw3zp4Ha/kjSst9fsHYw==", "dev": true }, "node_modules/@types/ms": { @@ -9382,9 +9493,9 @@ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" }, "node_modules/@types/node": { - "version": "20.14.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.1.tgz", - "integrity": "sha512-T2MzSGEu+ysB/FkWfqmhV3PLyQlowdptmmgD20C6QxsS8Fmv5SjpZ1ayXaEC0S21/h5UJ9iA6W/5vSNU5l00OA==", + "version": "20.14.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", + "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", "dependencies": { "undici-types": "~5.26.4" } @@ -9430,11 +9541,6 @@ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" }, - "node_modules/@types/parse5": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz", - "integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==" - }, "node_modules/@types/passport": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.16.tgz", @@ -9561,7 +9667,7 @@ "version": "18.3.0", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", - "dev": true, + "devOptional": true, "dependencies": { "@types/react": "*" } @@ -9666,12 +9772,6 @@ "resolved": "https://registry.npmjs.org/@types/reveal/-/reveal-4.2.0.tgz", "integrity": "sha512-lhTCUrk8pU/9SWcqbLwCy/AFjCp9S2hcDGoKAIycWGcHujUrDKMXWVkOvbSWk/gohZwwfuxQxucBaqvYAM5DTQ==" }, - "node_modules/@types/scheduler": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", - "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", - "optional": true - }, "node_modules/@types/send": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", @@ -9755,15 +9855,8 @@ "node_modules/@types/tough-cookie": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==" - }, - "node_modules/@types/tunnel": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@types/tunnel/-/tunnel-0.0.3.tgz", - "integrity": "sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA==", - "dependencies": { - "@types/node": "*" - } + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true }, "node_modules/@types/unist": { "version": "2.0.10", @@ -9771,9 +9864,9 @@ "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" }, "node_modules/@types/uuid": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", "dev": true }, "node_modules/@types/valid-url": { @@ -9783,9 +9876,9 @@ "dev": true }, "node_modules/@types/web": { - "version": "0.0.148", - "resolved": "https://registry.npmjs.org/@types/web/-/web-0.0.148.tgz", - "integrity": "sha512-HX2eARbn26tZuCOxZ25Ew6UUNhw8fgdGrOGcxX0/J6yTtlJm+nHlL9/h+2zgSzse13vlVe+c+W3LWqhnlAd5rg==" + "version": "0.0.151", + "resolved": "https://registry.npmjs.org/@types/web/-/web-0.0.151.tgz", + "integrity": "sha512-16wxPnfTZLPZdIjtNDmw1/BGxeV/gfhI9dfIhCIfg95nVkNchkoYxH3bywRo+R/UQYxPNzpZdDuTdiwlUfYEQA==" }, "node_modules/@types/webidl-conversions": { "version": "7.0.3", @@ -9850,16 +9943,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.12.0.tgz", - "integrity": "sha512-7F91fcbuDf/d3S8o21+r3ZncGIke/+eWk0EpO21LXhDfLahriZF9CGj4fbAetEjlaBdjdSm9a6VeXbpbT6Z40Q==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", + "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.12.0", - "@typescript-eslint/type-utils": "7.12.0", - "@typescript-eslint/utils": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/type-utils": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -9883,14 +9976,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.12.0.tgz", - "integrity": "sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ==", - "dependencies": { - "@typescript-eslint/scope-manager": "7.12.0", - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/typescript-estree": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", + "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", + "dependencies": { + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", "debug": "^4.3.4" }, "engines": { @@ -9910,12 +10003,12 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.12.0.tgz", - "integrity": "sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", + "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", "dependencies": { - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0" + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -9926,13 +10019,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.12.0.tgz", - "integrity": "sha512-lib96tyRtMhLxwauDWUp/uW3FMhLA6D0rJ8T7HmH7x23Gk1Gwwu8UZ94NMXBvOELn6flSPiBrCKlehkiXyaqwA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", + "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.12.0", - "@typescript-eslint/utils": "7.12.0", + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/utils": "7.16.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -9953,9 +10046,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.12.0.tgz", - "integrity": "sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", + "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", "engines": { "node": "^18.18.0 || >=20.0.0" }, @@ -9965,12 +10058,12 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.12.0.tgz", - "integrity": "sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", + "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", "dependencies": { - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -10003,15 +10096,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.12.0.tgz", - "integrity": "sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", + "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.12.0", - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/typescript-estree": "7.12.0" + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -10025,11 +10118,11 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.12.0.tgz", - "integrity": "sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", + "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", "dependencies": { - "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/types": "7.16.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -10046,36 +10139,36 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, "node_modules/@vue/compiler-core": { - "version": "3.4.27", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.27.tgz", - "integrity": "sha512-E+RyqY24KnyDXsCuQrI+mlcdW3ALND6U7Gqa/+bVwbcpcR3BRRIckFoz7Qyd4TTlnugtwuI7YgjbvsLmxb+yvg==", + "version": "3.4.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.31.tgz", + "integrity": "sha512-skOiodXWTV3DxfDhB4rOf3OGalpITLlgCeOwb+Y9GJpfQ8ErigdBUHomBzvG78JoVE8MJoQsb+qhZiHfKeNeEg==", "dependencies": { - "@babel/parser": "^7.24.4", - "@vue/shared": "3.4.27", + "@babel/parser": "^7.24.7", + "@vue/shared": "3.4.31", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "node_modules/@vue/compiler-dom": { - "version": "3.4.27", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.27.tgz", - "integrity": "sha512-kUTvochG/oVgE1w5ViSr3KUBh9X7CWirebA3bezTbB5ZKBQZwR2Mwj9uoSKRMFcz4gSMzzLXBPD6KpCLb9nvWw==", + "version": "3.4.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.31.tgz", + "integrity": "sha512-wK424WMXsG1IGMyDGyLqB+TbmEBFM78hIsOJ9QwUVLGrcSk0ak6zYty7Pj8ftm7nEtdU/DGQxAXp0/lM/2cEpQ==", "dependencies": { - "@vue/compiler-core": "3.4.27", - "@vue/shared": "3.4.27" + "@vue/compiler-core": "3.4.31", + "@vue/shared": "3.4.31" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.4.27", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.27.tgz", - "integrity": "sha512-nDwntUEADssW8e0rrmE0+OrONwmRlegDA1pD6QhVeXxjIytV03yDqTey9SBDiALsvAd5U4ZrEKbMyVXhX6mCGA==", - "dependencies": { - "@babel/parser": "^7.24.4", - "@vue/compiler-core": "3.4.27", - "@vue/compiler-dom": "3.4.27", - "@vue/compiler-ssr": "3.4.27", - "@vue/shared": "3.4.27", + "version": "3.4.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.31.tgz", + "integrity": "sha512-einJxqEw8IIJxzmnxmJBuK2usI+lJonl53foq+9etB2HAzlPjAS/wa7r0uUpXw5ByX3/0uswVSrjNb17vJm1kQ==", + "dependencies": { + "@babel/parser": "^7.24.7", + "@vue/compiler-core": "3.4.31", + "@vue/compiler-dom": "3.4.31", + "@vue/compiler-ssr": "3.4.31", + "@vue/shared": "3.4.31", "estree-walker": "^2.0.2", "magic-string": "^0.30.10", "postcss": "^8.4.38", @@ -10083,18 +10176,18 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.4.27", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.27.tgz", - "integrity": "sha512-CVRzSJIltzMG5FcidsW0jKNQnNRYC8bT21VegyMMtHmhW3UOI7knmUehzswXLrExDLE6lQCZdrhD4ogI7c+vuw==", + "version": "3.4.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.31.tgz", + "integrity": "sha512-RtefmITAje3fJ8FSg1gwgDhdKhZVntIVbwupdyZDSifZTRMiWxWehAOTCc8/KZDnBOcYQ4/9VWxsTbd3wT0hAA==", "dependencies": { - "@vue/compiler-dom": "3.4.27", - "@vue/shared": "3.4.27" + "@vue/compiler-dom": "3.4.31", + "@vue/shared": "3.4.31" } }, "node_modules/@vue/shared": { - "version": "3.4.27", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.27.tgz", - "integrity": "sha512-DL3NmY2OFlqmYYrzp39yi3LDkKxa5vZVwxWdQ3rG0ekuWscHraeIbnI8t+aZK7qhYqEqWKTUdijadunb9pnrgA==" + "version": "3.4.31", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.31.tgz", + "integrity": "sha512-Yp3wtJk//8cO4NItOPpi3QkLExAr/aLBGZMmTtW9WpdwBCJpRM6zj9WgWktXAl8IDIozwNMByT45JP3tO3ACWA==" }, "node_modules/@webassemblyjs/ast": { "version": "1.12.1", @@ -10326,9 +10419,9 @@ } }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "bin": { "acorn": "bin/acorn" }, @@ -10336,10 +10429,10 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", "peerDependencies": { "acorn": "^8" } @@ -10353,31 +10446,34 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", "dev": true, + "dependencies": { + "acorn": "^8.11.0" + }, "engines": { "node": ">=0.4.0" } }, "node_modules/adm-zip": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.13.tgz", - "integrity": "sha512-4U51tTl9J8UVEcuKGr6zRzY95tWoAa9l+ureGBNmsfleszjZblm5NyEEL/ZQxkhi86co5mZhSvL2T7gkZ6feYQ==", + "version": "0.5.14", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.14.tgz", + "integrity": "sha512-DnyqqifT4Jrcvb8USYjp6FHtBpEIz1mnXu6pTRHZ0RL69LbQYiO+0lDFg5+OKA7U29oWSs3a/i8fhn8ZcceIWg==", "engines": { "node": ">=12.0" } }, "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dependencies": { - "debug": "4" + "debug": "^4.3.4" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/agentkeepalive": { @@ -10423,14 +10519,14 @@ } }, "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.15.0.tgz", - "integrity": "sha512-15BTtQUOsSrmHCy+B4VnAiJAJxJ8IFgu6fcjFQF3jQYZ78nLSQthlFg4ehp+NLIyfvFgOlxNsjKIEhydtFPVHQ==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", "dependencies": { "fast-deep-equal": "^3.1.3", - "fast-uri": "^2.3.0", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" }, "funding": { "type": "github", @@ -10451,9 +10547,9 @@ } }, "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, "engines": { "node": ">=6" @@ -10632,12 +10728,12 @@ } }, "node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", "dev": true, "dependencies": { - "dequal": "^2.0.3" + "deep-equal": "^2.0.5" } }, "node_modules/arr-union": { @@ -10875,9 +10971,9 @@ } }, "node_modules/assert-never": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.2.1.tgz", - "integrity": "sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.3.0.tgz", + "integrity": "sha512-9Z3vxQ+berkL/JJo0dK+EY3Lp0s3NtSnP3VCLsh5HDcZPrh0M+KQRK5sWhUeyPPH+/RCxZqOxLMR+YC6vlviEQ==" }, "node_modules/assert-plus": { "version": "1.0.0", @@ -10957,9 +11053,9 @@ "integrity": "sha512-3AungXC4I8kKsS9PuS4JH2nc+0bVY/mjgrephHTIi8fpEeGsTHBUJeosp0Wc1myYMElmD0B3Oc4XL/HVJ4PV2g==" }, "node_modules/axe-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", - "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.9.1.tgz", + "integrity": "sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==", "dev": true, "engines": { "node": ">=4" @@ -10976,12 +11072,12 @@ } }, "node_modules/axobject-query": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", - "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", "dev": true, "dependencies": { - "dequal": "^2.0.3" + "deep-equal": "^2.0.5" } }, "node_modules/b4a": { @@ -11159,9 +11255,9 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/bare-events": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.3.1.tgz", - "integrity": "sha512-sJnSOTVESURZ61XgEleqmP255T6zTYwHPwE4r6SssIh0U9/uDvfpdoJYpVUerJJZH2fueO+CdT8ZT+OC/7aZDA==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz", + "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", "optional": true }, "node_modules/Base64": { @@ -13433,6 +13529,19 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/browndash-components/node_modules/npm/node_modules/node-gyp/node_modules/readable-stream": { + "version": "3.6.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/browndash-components/node_modules/npm/node_modules/node-gyp/node_modules/signal-exit": { "version": "3.0.7", "inBundle": true, @@ -13878,19 +13987,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/browndash-components/node_modules/npm/node_modules/readable-stream": { - "version": "3.6.2", - "inBundle": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/browndash-components/node_modules/npm/node_modules/retry": { "version": "0.12.0", "inBundle": true, @@ -14519,9 +14615,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", + "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", "funding": [ { "type": "opencollective", @@ -14537,10 +14633,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", + "caniuse-lite": "^1.0.30001640", + "electron-to-chromium": "^1.4.820", "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" @@ -14550,9 +14646,9 @@ } }, "node_modules/bson": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-6.7.0.tgz", - "integrity": "sha512-w2IquM5mYzYZv6rs3uN2DZTOBe2a0zXLj53TGDqwF4l6Sz/XsISrisXOJihArF9+BZ6Cq/GjVht7Sjfmri7ytQ==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.8.0.tgz", + "integrity": "sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==", "engines": { "node": ">=16.20.1" } @@ -14776,9 +14872,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001627", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001627.tgz", - "integrity": "sha512-4zgNiB8nTyV/tHhwZrFs88ryjls/lHiqFhrxCW4qSTeuRByBVnPYpDInchOIySWknznucaf31Z4KYqjfbrecVw==", + "version": "1.0.30001641", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001641.tgz", + "integrity": "sha512-Phv5thgl67bHYo1TtMY/MurjkHhV4EDaCosezRXgZ8jzA/Ub+wjxAvbGvjoFENStinwi5kCyOYV3mi5tOGykwA==", "funding": [ { "type": "opencollective", @@ -14822,6 +14918,14 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/centra": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/centra/-/centra-2.7.0.tgz", + "integrity": "sha512-PbFMgMSrmgx6uxCdm57RUos9Tc3fclMvhLSATYN39XsDV29B89zZ3KA89jmY0vwSGazyU+uerqwa6t+KaodPcg==", + "dependencies": { + "follow-redirects": "^1.15.6" + } + }, "node_modules/chai": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", @@ -14921,9 +15025,9 @@ } }, "node_modules/cheap-ruler": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/cheap-ruler/-/cheap-ruler-3.0.2.tgz", - "integrity": "sha512-02T332h1/HTN6cDSufLP8x4JzDs2+VC+8qZ/N0kWIVPyc2xUkWwWh3B2fJxR7raXkL4Mq7k554mfuM9ofv/vGg==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cheap-ruler/-/cheap-ruler-4.0.0.tgz", + "integrity": "sha512-0BJa8f4t141BYKQyn9NSQt1PguFQXMXwZiA5shfoaBYHAb2fFk2RAX+tiWMoQU+Agtzt3mdt0JtuyshAXqZ+Vw==" }, "node_modules/check-error": { "version": "2.1.1", @@ -15957,9 +16061,9 @@ "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==" }, "node_modules/cytoscape": { - "version": "3.29.2", - "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.29.2.tgz", - "integrity": "sha512-2G1ycU28Nh7OHT9rkXRLpCDP30MKH1dXJORZuBhtEhEW7pKwgPi77ImqlCWinouyE1PNepIOGZBOrE84DG7LyQ==", + "version": "3.30.0", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.30.0.tgz", + "integrity": "sha512-l590mjTHT6/Cbxp13dGPC2Y7VXdgc+rUeF8AnF/JPzhjNevbDJfObnJgaSjlldOgBQZbue+X6IUZ7r5GAgvauQ==", "engines": { "node": ">=0.10" } @@ -16621,16 +16725,29 @@ } }, "node_modules/deep-equal": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz", - "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dev": true, "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", "is-date-object": "^1.0.5", "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", "object-is": "^1.1.5", "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.5.1" + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -16918,9 +17035,9 @@ } }, "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "engines": { "node": ">=0.3.1" } @@ -17025,9 +17142,9 @@ } }, "node_modules/dompurify": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.5.tgz", - "integrity": "sha512-lwG+n5h8QNpxtyrJW/gJWckL+1/DQiYMX8f7t8Z2AZTPw1esVrqjI63i7Zc2Gz0aKzLVMYC1V1PL/ky+aY/NgA==" + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.6.tgz", + "integrity": "sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==" }, "node_modules/domutils": { "version": "3.1.0", @@ -17109,9 +17226,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.788", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.788.tgz", - "integrity": "sha512-ubp5+Ev/VV8KuRoWnfP2QF2Bg+O2ZFdb49DiiNbz2VmgkIqrnyYaqIOqj8A6K/3p1xV0QcU5hBQ1+BmB6ot1OA==" + "version": "1.4.823", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.823.tgz", + "integrity": "sha512-4h+oPeAiGQOHFyUJOqpoEcPj/xxlicxBzOErVeYVMMmAiXUXsGpsFd0QXBMaUUbnD8hhSfLf9uw+MlsoIA7j5w==" }, "node_modules/elkjs": { "version": "0.9.3", @@ -17140,9 +17257,9 @@ } }, "node_modules/engine.io": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", - "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz", + "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==", "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -17153,34 +17270,34 @@ "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", - "ws": "~8.11.0" + "ws": "~8.17.1" }, "engines": { "node": ">=10.2.0" } }, "node_modules/engine.io-client": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz", - "integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.4.tgz", + "integrity": "sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", - "ws": "~8.11.0", + "ws": "~8.17.1", "xmlhttprequest-ssl": "~2.0.0" } }, "node_modules/engine.io-client/node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -17200,15 +17317,15 @@ } }, "node_modules/engine.io/node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -17220,9 +17337,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.1.tgz", - "integrity": "sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==", + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", + "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -17340,6 +17457,26 @@ "node": ">= 0.4" } }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es-iterator-helpers": { "version": "1.0.19", "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", @@ -17366,9 +17503,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.3.tgz", - "integrity": "sha512-i1gCgmR9dCl6Vil6UKPI/trA69s08g/syhiDK9TG0Nf1RJjjFI+AzoWW7sPufzkgYAn861skuCwJa0pIIHYxvg==" + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==" }, "node_modules/es-object-atoms": { "version": "1.0.0", @@ -18597,27 +18734,27 @@ } }, "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", - "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", + "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", "dev": true, "dependencies": { - "@babel/runtime": "^7.23.2", - "aria-query": "^5.3.0", - "array-includes": "^3.1.7", + "aria-query": "~5.1.3", + "array-includes": "^3.1.8", "array.prototype.flatmap": "^1.3.2", "ast-types-flow": "^0.0.8", - "axe-core": "=4.7.0", - "axobject-query": "^3.2.1", + "axe-core": "^4.9.1", + "axobject-query": "~3.1.1", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.15", - "hasown": "^2.0.0", + "es-iterator-helpers": "^1.0.19", + "hasown": "^2.0.2", "jsx-ast-utils": "^3.3.5", "language-tags": "^1.0.9", "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7" + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.0" }, "engines": { "node": ">=4.0" @@ -18721,16 +18858,16 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.34.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.2.tgz", - "integrity": "sha512-2HCmrU+/JNigDN6tg55cRDKCQWicYAPB38JGSFDQt95jDm8rrvSUo7YPkOIm5l6ts1j1zCvysNcasvfTMQzUOw==", + "version": "7.34.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.3.tgz", + "integrity": "sha512-aoW4MV891jkUulwDApQbPYTVZmeuSyFrudpbTAQuj5Fv8VL+o6df2xIGpw8B0hPjAaih1/Fb0om9grCdyFYemA==", "dev": true, "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.2", "array.prototype.toreversed": "^1.1.2", - "array.prototype.tosorted": "^1.1.3", + "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.0.19", "estraverse": "^5.3.0", @@ -19019,6 +19156,17 @@ "node": ">=8" } }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/esm": { "version": "3.2.25", "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", @@ -19056,9 +19204,9 @@ } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dependencies": { "estraverse": "^5.1.0" }, @@ -19448,10 +19596,26 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, - "node_modules/fast-uri": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.3.0.tgz", - "integrity": "sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw==" + "node_modules/fast-xml-parser": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.0.tgz", + "integrity": "sha512-kLY3jFlwIYwBNDojclKsNAC12sfD6NwW74QB2CoNGPvtVxjliYehVunB3HYyNi+n4Tt1dAcgwYvmKF/Z18flqg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } }, "node_modules/fastest-levenshtein": { "version": "1.0.16", @@ -19881,9 +20045,9 @@ } }, "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -20225,9 +20389,9 @@ } }, "node_modules/function-plot": { - "version": "1.24.4", - "resolved": "https://registry.npmjs.org/function-plot/-/function-plot-1.24.4.tgz", - "integrity": "sha512-qlAfK6AENICh0HWiwx6h0aIAq/l/4YYNxConi89Bs7w4W+Jj5t548U6bPRbNR667N0hBLCSYOyYE2VsmRrflGg==", + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/function-plot/-/function-plot-1.25.0.tgz", + "integrity": "sha512-sp4jvtLxthE6mPuSrEWekACp49CG3MqhjgM9OLjoE69BtFIqwAJjs6Xl9lJX7E4q0YbQpEChTG4Wx25rpK5cxA==", "dependencies": { "built-in-math-eval": "^0.3.0", "d3-axis": "^3.0.0", @@ -20318,43 +20482,20 @@ } }, "node_modules/gaxios": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.6.0.tgz", - "integrity": "sha512-bpOZVQV5gthH/jVCSuYuokRo2bTKOcuBiVWpjmTn6C5Agl5zclGfTljuGsQZxwwDBkli+YhZhP4TdlqTnhOezQ==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.0.tgz", + "integrity": "sha512-DSrkyMTfAnAm4ks9Go20QGOcXEyW/NmZhvTYBU2rb4afBB393WIMQPWPEDMl/k8xqiNN9HYq2zao3oWXsdl2Tg==", "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "is-stream": "^2.0.0", "node-fetch": "^2.6.9", - "uuid": "^9.0.1" + "uuid": "^10.0.0" }, "engines": { "node": ">=14" } }, - "node_modules/gaxios/node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/gaxios/node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/gcp-metadata": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz", @@ -20369,6 +20510,19 @@ "node": ">=12" } }, + "node_modules/gcp-metadata/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, + "peer": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/gcp-metadata/node_modules/gaxios": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz", @@ -20385,6 +20539,20 @@ "node": ">=12" } }, + "node_modules/gcp-metadata/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "optional": true, + "peer": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -20402,6 +20570,25 @@ "deep-equal": "^1.0.0" } }, + "node_modules/geojson-equality/node_modules/deep-equal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz", + "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==", + "dependencies": { + "is-arguments": "^1.1.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.5.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/geojson-rbush": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/geojson-rbush/-/geojson-rbush-3.2.0.tgz", @@ -20428,9 +20615,9 @@ } }, "node_modules/geojson-vt": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-3.2.1.tgz", - "integrity": "sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-4.0.2.tgz", + "integrity": "sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A==" }, "node_modules/get-caller-file": { "version": "2.0.5", @@ -20559,22 +20746,20 @@ "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==" }, "node_modules/glob": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", - "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -20644,9 +20829,9 @@ } }, "node_modules/globals": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.3.0.tgz", - "integrity": "sha512-cCdyVjIUVTtX8ZsPkq1oCsOsLmGIswqnjZYMJJTGaNApj1yHtLSymKhwH51ttirREn75z3p4k051clwg7rvNKA==", + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.8.0.tgz", + "integrity": "sha512-VZAJ4cewHTExBWDHR6yptdIBlx9YSSZuwojj9Nt5mBRXQzrKakDsVKQ1J63sklLvzAJm0X5+RpO4i3Y2hcOnFw==", "dev": true, "engines": { "node": ">=18" @@ -20696,9 +20881,9 @@ "integrity": "sha512-sIVQCiRWOymHbVD1Aw/T9/ijbPYAVGBlgGYd1N9MRKfcyBNSpjr87Vg9nSHm+RCT8ELrvK8IJYJV0QRJuVUkCQ==" }, "node_modules/google-auth-library": { - "version": "9.10.0", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.10.0.tgz", - "integrity": "sha512-ol+oSa5NbcGdDqA+gZ3G3mev59OHBZksBTxY/tYwjtcp1H/scAFwJfSQU9/1RALoyZ7FslNbke8j4i3ipwlyuQ==", + "version": "9.11.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.11.0.tgz", + "integrity": "sha512-epX3ww/mNnhl6tL45EQ/oixsY8JLEgUFoT4A5E/5iAR4esld9Kqv6IJGk7EmGuOgDvaarwF95hU2+v7Irql9lw==", "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", @@ -20724,9 +20909,9 @@ } }, "node_modules/googleapis": { - "version": "133.0.0", - "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-133.0.0.tgz", - "integrity": "sha512-6xyc49j+x7N4smawJs/q1i7mbSkt6SYUWWd9RbsmmDW7gRv+mhwZ4xT+XkPihZcNyo/diF//543WZq4szdS74w==", + "version": "140.0.1", + "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-140.0.1.tgz", + "integrity": "sha512-ZGvBX4mQcFXO9ACnVNg6Aqy3KtBPB5zTuue43YVLxwn8HSv8jB7w+uDKoIPSoWuxGROgnj2kbng6acXncOQRNA==", "dependencies": { "google-auth-library": "^9.0.0", "googleapis-common": "^7.0.0" @@ -20751,6 +20936,18 @@ "node": ">=14.0.0" } }, + "node_modules/googleapis-common/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/googlephotos": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/googlephotos/-/googlephotos-0.3.5.tgz", @@ -20776,9 +20973,9 @@ } }, "node_modules/got": { - "version": "14.3.0", - "resolved": "https://registry.npmjs.org/got/-/got-14.3.0.tgz", - "integrity": "sha512-vZkrXdq5BtPWTXqvjXSpl6zky3zpHaOVfSug/RfFHu3YrtSsvYzopVMDqrh2do77WnGoCSSRCHW25zXOSAQ9zw==", + "version": "14.4.1", + "resolved": "https://registry.npmjs.org/got/-/got-14.4.1.tgz", + "integrity": "sha512-IvDJbJBUeexX74xNQuMIVgCRRuNOm5wuK+OC3Dc2pnSoh1AOmgc7JVj7WC+cJ4u0aPcO9KZ2frTXcqK4W/5qTQ==", "dependencies": { "@sindresorhus/is": "^6.3.1", "@szmarczak/http-timer": "^5.0.1", @@ -20790,7 +20987,8 @@ "http2-wrapper": "^2.2.1", "lowercase-keys": "^3.0.0", "p-cancelable": "^4.0.1", - "responselike": "^3.0.0" + "responselike": "^3.0.0", + "type-fest": "^4.19.0" }, "engines": { "node": ">=20" @@ -21028,9 +21226,9 @@ } }, "node_modules/hast-util-raw": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.3.tgz", - "integrity": "sha512-ICWvVOF2fq4+7CMmtCPD5CM4QKjPbHpPotE6+8tDooV0ZuyJVUzHsrNX+O5NaRbieTf0F7FfeBOMAwi6Td0+yQ==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.4.tgz", + "integrity": "sha512-LHE65TD2YiNsHD3YuXcKPHXPLuYh/gjp12mOfU8jxSrm1f/yJpsb0F/KKljS6U9LJoP0Ux+tCe8iJ2AsPzTdgA==", "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", @@ -21447,7 +21645,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -21456,18 +21653,6 @@ "node": ">= 14" } }, - "node_modules/http-proxy-agent/node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/http-proxy-middleware": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", @@ -21541,15 +21726,15 @@ "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==" }, "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dependencies": { - "agent-base": "6", + "agent-base": "^7.0.2", "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/human-signals": { @@ -21774,7 +21959,7 @@ "node_modules/image-size-stream/node_modules/image-size": { "version": "0.3.5", "resolved": "git+ssh://git@github.com/netroy/image-size.git#da2c863807a3e9602617bdd357b0de3ab4a064c1", - "integrity": "sha512-bOV/01RFEAMM7OJU4alHoipipEYAdVk1W9rto2aN1ZnEZsZ1A1OCVJJ2iMaaJIKidVXGZNbP9knmW/3wWTZ4/Q==", + "integrity": "sha512-nF4/PT7i5t72LJKRBAXfM8PCzUDQurOUzPsNUjQDpUhFpLNuCpSY0+XIHNcc/LtoU3GqSCK3wQDU+CCty3Bfcw==", "license": "MIT", "bin": { "image-size": "bin/image-size" @@ -22406,11 +22591,14 @@ } }, "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", + "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -22920,14 +23108,14 @@ } }, "node_modules/jackspeak": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.2.3.tgz", - "integrity": "sha512-htOzIMPbpLid/Gq9/zaz9SfExABxqRe1sSCdxntlO/aMD6u0issZQiY25n2GKQUtJ02j7z5sfptlAOMpWWOmvw==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.2.tgz", + "integrity": "sha512-qH3nOSj8q/8+Eg8LUPOq3C+6HWkpUioIjDsq1+D4zY91oZvpPttw8GwtF1nReRYKXl+1AORyFqtm2f5Q1SB6/Q==", "dependencies": { "@isaacs/cliui": "^8.0.2" }, "engines": { - "node": ">=14" + "node": "14 >=14.21 || 16 >=16.20 || >=18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -23207,31 +23395,6 @@ } } }, - "node_modules/jsdom/node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/jsdom/node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -23425,9 +23588,9 @@ } }, "node_modules/katex": { - "version": "0.16.10", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.10.tgz", - "integrity": "sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==", + "version": "0.16.11", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.11.tgz", + "integrity": "sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ==", "funding": [ "https://opencollective.com/katex", "https://github.com/sponsors/katex" @@ -23581,9 +23744,9 @@ } }, "node_modules/launch-editor": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", - "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.0.tgz", + "integrity": "sha512-vJranOAJrI/llyWGRQqiDM+adrw+k83fvmmx3+nV47g3+36xM15jE+zyZ6Ffel02+xSvuM0b2GDRosXZkbb6wA==", "dev": true, "dependencies": { "picocolors": "^1.0.0", @@ -23680,16 +23843,16 @@ } }, "node_modules/load-bmfont": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz", - "integrity": "sha512-8UyQoYmdRDy81Brz6aLAUhfZLwr5zV0L3taTQ4hju7m6biuwiWiJXjPhBJxbUQJA8PrkvJ/7Enqmwk2sM14soA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.2.tgz", + "integrity": "sha512-qElWkmjW9Oq1F9EI5Gt7aD9zcdHb9spJCW1L/dmPf7KzCCEJxq8nhHz5eCgI9aMf7vrG/wyaCqdsI+Iy9ZTlog==", "dependencies": { "buffer-equal": "0.0.1", "mime": "^1.3.4", "parse-bmfont-ascii": "^1.0.3", "parse-bmfont-binary": "^1.0.5", "parse-bmfont-xml": "^1.1.4", - "phin": "^2.9.1", + "phin": "^3.7.1", "xhr": "^2.0.1", "xtend": "^4.0.0" } @@ -24012,9 +24175,9 @@ "dev": true }, "node_modules/mapbox-gl": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-3.4.0.tgz", - "integrity": "sha512-QWgL28zg/zuIOHeF8DXPvHy1UHTgO5p4Oy6ifCAHwI9/hoI9/Fruya0yI4HkDtX1OgzTLO6SHO13A781BGJvyw==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-3.5.1.tgz", + "integrity": "sha512-sf4N18vl5FHS8lPRWZjTZShgIziDqSxan3MazHClvYYXezsAPn6hApRvAS2HEMTq7MXzRcvvt4sYgQWLubwnBw==", "dependencies": { "@mapbox/jsonlint-lines-primitives": "^2.0.2", "@mapbox/mapbox-gl-supported": "^3.0.0", @@ -24023,14 +24186,14 @@ "@mapbox/unitbezier": "^0.0.1", "@mapbox/vector-tile": "^1.3.1", "@mapbox/whoots-js": "^3.1.0", - "cheap-ruler": "^3.0.1", + "cheap-ruler": "^4.0.0", "csscolorparser": "~1.0.3", - "earcut": "^2.2.4", + "earcut": "^3.0.0", "fflate": "^0.8.1", - "geojson-vt": "^3.2.1", + "geojson-vt": "^4.0.2", "gl-matrix": "^3.4.3", "grid-index": "^1.1.0", - "kdbush": "^4.0.1", + "kdbush": "^4.0.2", "lodash.clonedeep": "^4.5.0", "murmurhash-js": "^1.0.0", "pbf": "^3.2.1", @@ -24038,13 +24201,18 @@ "quickselect": "^2.0.0", "rw": "^1.3.3", "serialize-to-js": "^3.1.2", - "supercluster": "^8.0.0", + "supercluster": "^8.0.1", "tiny-lru": "^11.2.6", "tinyqueue": "^2.0.3", - "tweakpane": "^4.0.3", + "tweakpane": "^4.0.4", "vt-pbf": "^3.1.3" } }, + "node_modules/mapbox-gl/node_modules/earcut": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.0.tgz", + "integrity": "sha512-41Fs7Q/PLq1SDbqjsgcY7GA42T0jvaCNGXgGtsNdvg+Yv8eIu06bxv4/PoREkZ9nMDNwnUSG9OFB9+yv8eKhDg==" + }, "node_modules/markdown-it": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", @@ -28760,9 +28928,9 @@ } }, "node_modules/mdast-util-to-hast": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.1.0.tgz", - "integrity": "sha512-/e2l/6+OdGp/FB+ctrJ9Avz71AN/GRH3oi/3KAx/kMnoUsD6q0woXlDT8lLEeViVKE7oZxE7RXzvO3T8kF2/sA==", + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", @@ -29102,6 +29270,18 @@ "web-worker": "^1.2.0" } }, + "node_modules/mermaid/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -29202,9 +29382,9 @@ } }, "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.0.0.tgz", - "integrity": "sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", @@ -29301,9 +29481,9 @@ ] }, "node_modules/micromark-extension-gfm-footnote": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.0.0.tgz", - "integrity": "sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", "dependencies": { "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", @@ -29649,9 +29829,9 @@ ] }, "node_modules/micromark-extension-gfm-strikethrough": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.0.0.tgz", - "integrity": "sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", @@ -29771,9 +29951,9 @@ ] }, "node_modules/micromark-extension-gfm-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.0.0.tgz", - "integrity": "sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", + "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", @@ -29882,9 +30062,9 @@ ] }, "node_modules/micromark-extension-gfm-task-list-item": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.0.1.tgz", - "integrity": "sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", @@ -30033,9 +30213,9 @@ ] }, "node_modules/micromark-extension-math": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.0.0.tgz", - "integrity": "sha512-iJ2Q28vBoEovLN5o3GO12CpqorQRYDPT+p4zW50tGwTfJB+iv/VnB6Ini+gqa24K97DwptMBBIvVX6Bjk49oyQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", + "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", "dependencies": { "@types/katex": "^0.16.0", "devlop": "^1.0.0", @@ -30548,9 +30728,9 @@ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" }, "node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -30627,9 +30807,9 @@ "integrity": "sha512-yc0LhH6tItlvfLBugVUEtgawwFU2sIe+cSdmRJJCTMZ5GEJyLxNyC/NIOAOGk67Fa8GNpOttO3Xz/1bHpXFD/g==" }, "node_modules/mobx": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/mobx/-/mobx-6.12.3.tgz", - "integrity": "sha512-c8NKkO4R2lShkSXZ2Ongj1ycjugjzFFo/UswHBnS62y07DMcTc9Rvo03/3nRyszIvwPNljlkd4S828zIBv/piw==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/mobx/-/mobx-6.13.0.tgz", + "integrity": "sha512-1laWODrBWmB7mDJ8EClCjUQTyLwJ0ydJgE4FtK7t9r3JnjXgc9OhmYs2P4RtHrY1co5+4T6cKP2UswX2SU29mA==", "funding": { "type": "opencollective", "url": "https://opencollective.com/mobx" @@ -30692,31 +30872,31 @@ } }, "node_modules/mocha": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", - "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "8.1.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.6.0.tgz", + "integrity": "sha512-hxjt4+EEB0SA0ZDygSS015t65lJw/I2yRCS3Ae+SJ5FrbzrXgfYwJr96f0OvIXdj7h4lv/vLCrH3rkiuizFSvw==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" }, "bin": { "_mocha": "bin/_mocha", @@ -30732,56 +30912,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/mocha/node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/mocha/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/mocha/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/mocha/node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", @@ -30802,18 +30932,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/mocha/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -30836,9 +30954,9 @@ } }, "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -30868,19 +30986,10 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/mongodb": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.7.0.tgz", - "integrity": "sha512-TMKyHdtMcO0fYBNORiYdmM25ijsHs+Njs963r4Tro4OQZzqYigAzYQouwWRg4OIaiLRUEGUh/1UAcH5lxdSLIA==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.8.0.tgz", + "integrity": "sha512-HGQ9NWDle5WvwMnrvUxsFYPd3JEbqD3RgABHBQRuoCEND0qzhsd0iH5ypHsf1eJ+sXmvmyKpP+FLOKY8Il7jMw==", "dependencies": { "@mongodb-js/saslprep": "^1.1.5", "bson": "^6.7.0", @@ -30955,13 +31064,13 @@ } }, "node_modules/mongoose": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.4.1.tgz", - "integrity": "sha512-odQ2WEWGL3hb0Qex+QMN4eH6D34WdMEw7F1If2MGABApSDmG9cMmqv/G1H6WsXmuaH9mkuuadW/WbLE5+tHJwA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.5.0.tgz", + "integrity": "sha512-iGgZvgO+fIgX1AQMehkG+Wj8qrWc9it8vUZrSKWjrebgfwHTqUcIdTgWK8mT1us1xd83NOQxiuGbg9ZJtLxs2Q==", "dependencies": { "bson": "^6.7.0", "kareem": "2.6.3", - "mongodb": "6.6.2", + "mongodb": "6.7.0", "mpath": "0.9.0", "mquery": "5.0.0", "ms": "2.1.3", @@ -30976,9 +31085,9 @@ } }, "node_modules/mongoose/node_modules/mongodb": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.6.2.tgz", - "integrity": "sha512-ZF9Ugo2JCG/GfR7DEb4ypfyJJyiKbg5qBYKRintebj8+DNS33CyGMkWbrS9lara+u+h+yEOGSRiLhFO/g1s1aw==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.7.0.tgz", + "integrity": "sha512-TMKyHdtMcO0fYBNORiYdmM25ijsHs+Njs963r4Tro4OQZzqYigAzYQouwWRg4OIaiLRUEGUh/1UAcH5lxdSLIA==", "dependencies": { "@mongodb-js/saslprep": "^1.1.5", "bson": "^6.7.0", @@ -31130,9 +31239,9 @@ "dev": true }, "node_modules/nan": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz", - "integrity": "sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==" + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz", + "integrity": "sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==" }, "node_modules/nanoid": { "version": "3.3.7", @@ -31309,17 +31418,17 @@ } }, "node_modules/nodemailer": { - "version": "6.9.13", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.13.tgz", - "integrity": "sha512-7o38Yogx6krdoBf3jCAqnIN4oSQFx+fMa0I7dK1D+me9kBxx12D+/33wSb+fhOCtIxvYJ+4x4IMEhmhCKfAiOA==", + "version": "6.9.14", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.14.tgz", + "integrity": "sha512-Dobp/ebDKBvz91sbtRKhcznLThrKxKt97GI2FAlAyy+fk19j73Uz3sBXolVtmcXjaorivqsbbbjDY+Jkt4/bQA==", "engines": { "node": ">=6.0.0" } }, "node_modules/nodemon": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.3.tgz", - "integrity": "sha512-m4Vqs+APdKzDFpuaL9F9EVOF85+h070FnkHVEoU4+rmT6Vw0bmNl7s61VEkY/cJkL7RCv1p4urnUDUMrS5rk2w==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz", + "integrity": "sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==", "dependencies": { "chokidar": "^3.5.2", "debug": "^4", @@ -33869,9 +33978,12 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -34128,9 +34240,9 @@ } }, "node_modules/openai": { - "version": "4.47.3", - "resolved": "https://registry.npmjs.org/openai/-/openai-4.47.3.tgz", - "integrity": "sha512-470d4ibH5kizXflCzgur22GpM4nOjrg7WQ9jTOa3dNKEn248oBy4+pjOyfcFR4V4YUn/YlDNjp6h83PbviCCKQ==", + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.52.5.tgz", + "integrity": "sha512-qqH8GsyPE3z06took/2uWOGqRcrZNlRoPAsihpg4jsl0+2Dfelnw6HDDMep0EI2Cfzw75nn3vHRZehep/IZzxg==", "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", @@ -34146,9 +34258,9 @@ } }, "node_modules/openai/node_modules/@types/node": { - "version": "18.19.34", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.34.tgz", - "integrity": "sha512-eXF4pfBNV5DAMKGbI02NnDtWrQ40hAN558/2vvS4gMpMIxaf6JmD7YjnZbq0Q9TDSSkKBamime8ewRoomHdt4g==", + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", "dependencies": { "undici-types": "~5.26.4" } @@ -34212,11 +34324,11 @@ } }, "node_modules/p-limit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", - "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.1.0.tgz", + "integrity": "sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==", "dependencies": { - "yocto-queue": "^1.0.0" + "yocto-queue": "^1.1.1" }, "engines": { "node": ">=18" @@ -34289,6 +34401,11 @@ "node": ">=6" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==" + }, "node_modules/pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -34538,12 +34655,9 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", - "engines": { - "node": "14 || >=16.14" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" }, "node_modules/path-to-regexp": { "version": "0.1.7", @@ -34559,9 +34673,9 @@ } }, "node_modules/path2d": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/path2d/-/path2d-0.2.0.tgz", - "integrity": "sha512-KdPAykQX6kmLSOO6Jpu2KNcCED7CKjmaBNGGNuctOsG0hgYO1OdYQaan6cYXJiG0WmXOwZZPILPBimu5QAIw3A==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/path2d/-/path2d-0.2.1.tgz", + "integrity": "sha512-Fl2z/BHvkTNvkuBzYTpTuirHZg6wW9z8+4SND/3mDTEcYbbNKWAy21dz9D3ePNNwrrK8pqZO5vLPZ1hLF6T7XA==", "optional": true, "engines": { "node": ">=6" @@ -34582,9 +34696,9 @@ "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, "node_modules/pbf": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz", - "integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.3.0.tgz", + "integrity": "sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==", "dependencies": { "ieee754": "^1.1.12", "resolve-protobuf-schema": "^2.1.0" @@ -34630,9 +34744,9 @@ } }, "node_modules/pdfjs-dist": { - "version": "4.3.136", - "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-4.3.136.tgz", - "integrity": "sha512-gzfnt1qc4yA+U46golPGYtU4WM2ssqP2MvFjKga8GEKOrEnzRPrA/9jogLLPYHiA3sGBPJ+p7BdAq+ytmw3jEg==", + "version": "4.4.168", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-4.4.168.tgz", + "integrity": "sha512-MbkAjpwka/dMHaCfQ75RY1FXX3IewBVu6NGZOcxerRFlaBiIkZmUoR0jotX5VUzYZEXAGzSFtknWs5xRKliXPA==", "engines": { "node": ">=18" }, @@ -34693,10 +34807,15 @@ "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" }, "node_modules/phin": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", - "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info." + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/phin/-/phin-3.7.1.tgz", + "integrity": "sha512-GEazpTWwTZaEQ9RhL7Nyz0WwqilbqgLahDM3D0hxWwmVDI52nXEybHqiN6/elwpkJBhcuj+WbBu+QfT0uhPGfQ==", + "dependencies": { + "centra": "^2.7.0" + }, + "engines": { + "node": ">= 8" + } }, "node_modules/picocolors": { "version": "1.0.1", @@ -34866,9 +34985,9 @@ } }, "node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "version": "8.4.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", + "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", "funding": [ { "type": "opencollective", @@ -34885,7 +35004,7 @@ ], "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", + "picocolors": "^1.0.1", "source-map-js": "^1.2.0" }, "engines": { @@ -34987,9 +35106,9 @@ } }, "node_modules/prettier": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.0.tgz", - "integrity": "sha512-J9odKxERhCQ10OC2yb93583f6UnYutOeiV5i0zEDS7UGTdUt0u+y8erxl3lBKvwo/JHyyoEdXjwp4dke9oyZ/g==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -35112,9 +35231,9 @@ } }, "node_modules/prosemirror-history": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.4.0.tgz", - "integrity": "sha512-UUiGzDVcqo1lovOPdi9YxxUps3oBFWAIYkXLu3Ot+JPv1qzVogRbcizxK3LhHmtaUxclohgiOVesRw5QSlMnbQ==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.4.1.tgz", + "integrity": "sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ==", "dependencies": { "prosemirror-state": "^1.2.2", "prosemirror-transform": "^1.0.0", @@ -35141,17 +35260,17 @@ } }, "node_modules/prosemirror-model": { - "version": "1.21.1", - "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.21.1.tgz", - "integrity": "sha512-IVBAuMqOfltTr7yPypwpfdGT+6rGAteVOw2FO6GEvCGGa1ZwxLseqC1Eax/EChDvG/xGquB2d/hLdgh3THpsYg==", + "version": "1.21.3", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.21.3.tgz", + "integrity": "sha512-nt2Xs/RNGepD9hrrkzXvtCm1mpGJoQfFSPktGa0BF/aav6XsnmVGZ9sTXNWRLupAz5SCLa3EyKlFeK7zJWROKg==", "dependencies": { "orderedmap": "^2.0.0" } }, "node_modules/prosemirror-schema-list": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.3.0.tgz", - "integrity": "sha512-Hz/7gM4skaaYfRPNgr421CU4GSwotmEwBVvJh5ltGiffUJwm7C8GfN/Bc6DR1EKEp5pDKhODmdXXyi9uIsZl5A==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.4.0.tgz", + "integrity": "sha512-nZOIq/AkBSzCENxUyLm5ltWE53e2PLk65ghMN8qLQptOmDVixZlPqtMeQdiNw0odL9vNpalEjl3upgRkuJ/Jyw==", "dependencies": { "prosemirror-model": "^1.0.0", "prosemirror-state": "^1.0.0", @@ -35177,9 +35296,9 @@ } }, "node_modules/prosemirror-view": { - "version": "1.33.7", - "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.33.7.tgz", - "integrity": "sha512-jo6eMQCtPRwcrA2jISBCnm0Dd2B+szS08BU1Ay+XGiozHo5EZMHfLQE8R5nO4vb1spTH2RW1woZIYXRiQsuP8g==", + "version": "1.33.8", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.33.8.tgz", + "integrity": "sha512-4PhMr/ufz2cdvFgpUAnZfs+0xij3RsFysreeG9V/utpwX7AJtYCDVyuRxzWoMJIEf4C7wVihuBNMPpFLPCiLQw==", "dependencies": { "prosemirror-model": "^1.20.0", "prosemirror-state": "^1.0.0", @@ -35350,6 +35469,7 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", "engines": { "node": ">=0.6.0", "teleport": ">=0.2.0" @@ -35549,9 +35669,9 @@ } }, "node_modules/rc-util": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.41.0.tgz", - "integrity": "sha512-xtlCim9RpmVv0Ar2Nnc3WfJCxjQkTf3xHPWoFdjp1fSs2NirQwqiQrfqdU9HUe0kdfb168M/T8Dq0IaX50xeKg==", + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.43.0.tgz", + "integrity": "sha512-AzC7KKOXFqAdIBqdGWepL9Xn7cm3vnAmjlHqUnoQaTMZYhM4VlXGLkkHHxj/BZ7Td0+SOPKB4RGPboBVKT9htw==", "dependencies": { "@babel/runtime": "^7.18.3", "react-is": "^18.2.0" @@ -35670,9 +35790,9 @@ } }, "node_modules/react-awesome-reveal": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/react-awesome-reveal/-/react-awesome-reveal-4.2.11.tgz", - "integrity": "sha512-BXdU3nzZkRYf6h2lIx4SCMEERhIQd7wKheHKRH8U9601m1U2W4LrwEpKbpUxIPWSjcUwci4w7EotdfF+9ZQHhQ==", + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/react-awesome-reveal/-/react-awesome-reveal-4.2.12.tgz", + "integrity": "sha512-cablqrGypakw34h+rMcn+CmDCMfS+n4MznL/0LBQpFksZ2FCRtKFWIYuKWWpY8lL2ttyBnWnMdlJJiuLHR99uA==", "funding": [ { "type": "github", @@ -35684,7 +35804,7 @@ } ], "dependencies": { - "react-intersection-observer": "^9.10.2", + "react-intersection-observer": "^9.10.3", "react-is": "^18.3.1" }, "peerDependencies": { @@ -35736,9 +35856,9 @@ "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==" }, "node_modules/react-datepicker": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-6.9.0.tgz", - "integrity": "sha512-QTxuzeem7BUfVFWv+g5WuvzT0c5BPo+XTCNbMTZKSZQLU+cMMwSUHwspaxuIcDlwNcOH0tiJ+bh1fJ2yxOGYWA==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-7.3.0.tgz", + "integrity": "sha512-EqRKLAtLZUTztiq6a+tjSjQX9ES0Xd229JPckAtyZZ4GoY3rtvNWAzkYZnQUf6zTWT50Ki0+t+W9VRQIkSJLfg==", "dependencies": { "@floating-ui/react": "^0.26.2", "clsx": "^2.1.0", @@ -35810,9 +35930,9 @@ } }, "node_modules/react-intersection-observer": { - "version": "9.10.2", - "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.10.2.tgz", - "integrity": "sha512-j2hGADK2hCbAlfaq6L3tVLb4iqngoN7B1fT16MwJ4J16YW/vWLcmAIinLsw0lgpZeMi4UDUWtHC9QDde0/P1yQ==", + "version": "9.10.3", + "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.10.3.tgz", + "integrity": "sha512-9NYfKwPZRovB6QJee7fDg0zz/SyYrqXtn5xTZU0vwLtLVBtfu9aZt1pVmr825REE49VPDZ7Lm5SNHjJBOTZHpA==", "peerDependencies": { "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -35829,44 +35949,23 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, "node_modules/react-jsx-parser": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/react-jsx-parser/-/react-jsx-parser-1.29.0.tgz", - "integrity": "sha512-u0svZd0UsPffRrIK0sTbox54jhEbTmg6ED9ob5FQahp1DeOpd2Rq+KiSTIFNYkZUL+WZi4Ntia/Oj5T4lDJafQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/react-jsx-parser/-/react-jsx-parser-2.0.0.tgz", + "integrity": "sha512-1siP+vM47gWE+x2VTF0ano5jJPRilOf7sRIoy4dzb1FmNoDpwe3htuzgcEfvzsc7YThzwmMQNUfy4vAv1ATs2g==", "hasInstallScript": true, "dependencies": { - "@types/jsdom": "^16.2.6", - "acorn": "^8.0.5", - "acorn-jsx": "^5.3.1", - "browserslist": "^4.14.5", - "core-js": "^3.8.3" + "acorn": "^8.12.1", + "acorn-jsx": "^5.3.2", + "browserslist": "^4.23.1", + "core-js": "^3.37.1" }, "optionalDependencies": { - "@types/react": "^17.0.1", - "@types/react-dom": "^17.0.0" + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0" }, "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" - } - }, - "node_modules/react-jsx-parser/node_modules/@types/react": { - "version": "17.0.80", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.80.tgz", - "integrity": "sha512-LrgHIu2lEtIo8M7d1FcI3BdwXWoRQwMoXOZ7+dPTW0lYREjmlHl3P0U1VD0i/9tppOuv8/sam7sOjx34TxSFbA==", - "optional": true, - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "^0.16", - "csstype": "^3.0.2" - } - }, - "node_modules/react-jsx-parser/node_modules/@types/react-dom": { - "version": "17.0.25", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.25.tgz", - "integrity": "sha512-urx7A7UxkZQmThYA4So0NelOVjx3V4rNFVJwp0WZlbIK5eM4rNJDiN3R/E9ix0MBh6kAEojk/9YL+Te6D9zHNA==", - "optional": true, - "dependencies": { - "@types/react": "^17" + "react": ">=18", + "react-dom": ">=18" } }, "node_modules/react-latex-next": { @@ -37393,17 +37492,93 @@ } }, "node_modules/rimraf": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", - "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.0.tgz", + "integrity": "sha512-u+yqhM92LW+89cxUQK0SRyvXYQmyuKHx0jkx4W7KfwLGLqJnQM5031Uv1trE4gB9XEXBM/s6MxKlfW95IidqaA==", "dependencies": { - "glob": "^10.3.7" + "glob": "^11.0.0" }, "bin": { "rimraf": "dist/esm/bin.mjs" }, "engines": { - "node": ">=14.18" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/jackspeak": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz", + "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/rimraf/node_modules/lru-cache": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz", + "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -37420,9 +37595,9 @@ "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==" }, "node_modules/rrweb-cssom": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.0.tgz", - "integrity": "sha512-KlSv0pm9kgQSRxXEMgtivPJ4h826YHsuob8pSHcfSZsSXGtvpEAie8S0AnXuObEJ7nhikOb4ahwxDm0H2yW17g==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", "dev": true }, "node_modules/run-applescript": { @@ -37562,9 +37737,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sass": { - "version": "1.77.4", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.4.tgz", - "integrity": "sha512-vcF3Ckow6g939GMA4PeU7b2K/9FALXk2KF9J87txdHzXbUF9XRQRwSxcAs/fGaTnJeBFd7UoV22j3lzMLdM0Pw==", + "version": "1.77.7", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.7.tgz", + "integrity": "sha512-9ywH75cO+rLjbrZ6en3Gp8qAMwPGBapFtlsMJoDTkcMU/bSe5a6cjKVUn5Jr4Gzg5GbP3HE8cm+02pLCgcoMow==", "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -37660,14 +37835,14 @@ } }, "node_modules/schema-utils/node_modules/ajv": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.15.0.tgz", - "integrity": "sha512-15BTtQUOsSrmHCy+B4VnAiJAJxJ8IFgu6fcjFQF3jQYZ78nLSQthlFg4ehp+NLIyfvFgOlxNsjKIEhydtFPVHQ==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", "dependencies": { "fast-deep-equal": "^3.1.3", - "fast-uri": "^2.3.0", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" }, "funding": { "type": "github", @@ -37786,10 +37961,9 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dependencies": { "randombytes": "^2.1.0" } @@ -38236,24 +38410,24 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", - "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", "dependencies": { "debug": "~4.3.4", - "ws": "~8.11.0" + "ws": "~8.17.1" } }, "node_modules/socket.io-adapter/node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -38310,24 +38484,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/sonic-forest": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sonic-forest/-/sonic-forest-1.0.3.tgz", - "integrity": "sha512-dtwajos6IWMEWXdEbW1IkEkyL2gztCAgDplRIX+OT5aRKnEd5e7r7YCxRgXZdhRP1FBdOBf8axeTPhzDv8T4wQ==", - "dependencies": { - "tree-dump": "^1.0.0" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, "node_modules/sort-asc": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.2.0.tgz", @@ -38585,6 +38741,18 @@ "node": ">=0.10.0" } }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/stream-browserify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", @@ -38722,6 +38890,16 @@ "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz", "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==" }, + "node_modules/string.prototype.includes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz", + "integrity": "sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, "node_modules/string.prototype.matchall": { "version": "4.0.11", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", @@ -38906,6 +39084,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, "node_modules/strtok3": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", @@ -38973,11 +39156,43 @@ "react-dom": ">= 16.8.0" } }, + "node_modules/styled-components/node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/styled-components/node_modules/stylis": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==" }, + "node_modules/styled-components/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", @@ -39168,9 +39383,9 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/terser": { - "version": "5.31.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz", - "integrity": "sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==", + "version": "5.31.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.2.tgz", + "integrity": "sha512-LGyRZVFm/QElZHy/CPr/O4eNZOZIzsrQ92y4v9UJe/pFJjypje2yI3C2FmPtvUEnhadlSbmG2nXtdcjHOjCfxw==", "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -39255,14 +39470,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/terser-webpack-plugin/node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/terser-webpack-plugin/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -39283,9 +39490,9 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "node_modules/text-decoder": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.0.tgz", - "integrity": "sha512-TmLJNj6UgX8xcUZo4UDStGQtDiTzF7BzWlzn9g7UWrjkpHr5uJTK1ld16wZ3LXb2vb6jH8qU89dW5whuMdXYdw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.1.tgz", + "integrity": "sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==", "dependencies": { "b4a": "^1.6.4" } @@ -39339,9 +39546,9 @@ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" }, "node_modules/tiny-lru": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-11.2.6.tgz", - "integrity": "sha512-0PU3c9PjMnltZaFo2sGYv/nnJsMjG0Cxx8X6FXHPPGjFyoo1SJDxvUXW1207rdiSxYizf31roo+GrkIByQeZoA==", + "version": "11.2.11", + "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-11.2.11.tgz", + "integrity": "sha512-27BIW0dIWTYYoWNnqSmoNMKe5WIbkXsc0xaCQHd3/3xT2XMuMJrzHdrO9QBFR14emBz1Bu0dOAs2sCBBrvgPQA==", "engines": { "node": ">=12" } @@ -39498,9 +39705,9 @@ "integrity": "sha512-up6Yvai4PYKhpNp5PkYtx50m3KbwQrqDwbuZP/ItyL64YEWHAvH6Md83LFLV/GRSk/BoUVwwgUzX6SOQSbsfAg==" }, "node_modules/tree-dump": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.1.tgz", - "integrity": "sha512-WCkcRBVPSlHHq1dc/px9iOfqklvzCbdRwvlNfxGZsrHqf6aZttfPrd7DJTt6oR10dwUfpFFQeVTkPbBIZxX/YA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", + "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", "engines": { "node": ">=10.0" }, @@ -39880,9 +40087,9 @@ } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/tslint": { "version": "6.1.3", @@ -40125,14 +40332,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -40150,9 +40349,9 @@ "integrity": "sha512-Ja03QIJlPuHt4IQ2FfGex4F4JAr8m3jpaHbFbQrgwr7s7L6U8ocrHiF3J1+wf9jzhGKxvDeaCAnGDot8OjGFyA==" }, "node_modules/tweakpane": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/tweakpane/-/tweakpane-4.0.3.tgz", - "integrity": "sha512-BlcWOAe8oe4c+k9pmLBARGdWB6MVZMszayekkixQXTgkxTaYoTUpHpwVEp+3HkoamZkomodpbBf0CkguIHTgLg==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/tweakpane/-/tweakpane-4.0.4.tgz", + "integrity": "sha512-RkWD54zDlEbnN01wQPk0ANHGbdCvlJx/E8A1QxhTfCbX+ROWos1Ws2MnhOm39aUGMOh+36TjUwpDmLfmwTr1Fg==", "funding": { "url": "https://github.com/sponsors/cocopon" } @@ -40174,11 +40373,11 @@ } }, "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.21.0.tgz", + "integrity": "sha512-ADn2w7hVPcK6w1I0uWnM//y1rLXZhzB9mr0a3OirzclKF1Wp6VzevUmzz/NRAWunOT6E8HrnpGY7xOfc6K57fA==", "engines": { - "node": ">=10" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -40270,9 +40469,9 @@ } }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", + "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -40287,14 +40486,14 @@ "integrity": "sha512-7sI4e/bZijOzyURng88oOFZCISQPTHozfE2sUu5AviFYk5QV7fYGb6YiDl+vKjF/pICA354JImBImL9XJWUvdQ==" }, "node_modules/typescript-eslint": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.12.0.tgz", - "integrity": "sha512-D6HKNbQcnNu3BaN4HkQCR16tgG8Q2AMUWPgvhrJksOXu+d6ys07yC06ONiV2kcsEfWC22voB6C3PvK2MqlBZ7w==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.16.0.tgz", + "integrity": "sha512-kaVRivQjOzuoCXU6+hLnjo3/baxyzWVO5GrnExkFzETRYJKVHYkrJglOu2OCm8Hi9RPDWX1PTNNTpU5KRV0+RA==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "7.12.0", - "@typescript-eslint/parser": "7.12.0", - "@typescript-eslint/utils": "7.12.0" + "@typescript-eslint/eslint-plugin": "7.16.0", + "@typescript-eslint/parser": "7.16.0", + "@typescript-eslint/utils": "7.16.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -40438,9 +40637,9 @@ "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" }, "node_modules/unified": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", - "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", @@ -40633,9 +40832,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", - "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "funding": [ { "type": "opencollective", @@ -40741,9 +40940,9 @@ "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" }, "node_modules/url/node_modules/qs": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz", - "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==", + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.3.tgz", + "integrity": "sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==", "dependencies": { "side-channel": "^1.0.6" }, @@ -40838,9 +41037,9 @@ } }, "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -41125,9 +41324,9 @@ } }, "node_modules/webpack": { - "version": "5.91.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.91.0.tgz", - "integrity": "sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==", + "version": "5.92.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.92.1.tgz", + "integrity": "sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA==", "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", @@ -41135,10 +41334,10 @@ "@webassemblyjs/wasm-edit": "^1.12.1", "@webassemblyjs/wasm-parser": "^1.12.1", "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", + "acorn-import-attributes": "^1.9.5", "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.16.0", + "enhanced-resolve": "^5.17.0", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", @@ -41270,13 +41469,13 @@ } }, "node_modules/webpack-dev-middleware/node_modules/memfs": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.9.2.tgz", - "integrity": "sha512-f16coDZlTG1jskq3mxarwB+fGRrd0uXWt+o1WIhRfOwbXQZqUDsTVxQBFK9JjRQHblg8eAG2JSbprDXKjc7ijQ==", + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.9.3.tgz", + "integrity": "sha512-bsYSSnirtYTWi1+OPMFb0M048evMKyUYe0EbtuGQgq6BVQM1g1W8/KIUJCCvjgI/El0j6Q4WsmMiBwLUBSw8LA==", "dependencies": { "@jsonjoy.com/json-pack": "^1.0.3", "@jsonjoy.com/util": "^1.1.2", - "sonic-forest": "^1.0.0", + "tree-dump": "^1.0.1", "tslib": "^2.0.0" }, "engines": { @@ -41355,6 +41554,24 @@ "node": ">= 10" } }, + "node_modules/webpack-dev-server/node_modules/rimraf": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.9.tgz", + "integrity": "sha512-3i7b8OcswU6CpU8Ej89quJD4O98id7TtVM5U4Mybh84zQXdrFmDLouWBEEaD/QfO3gDDfH+AGFCGsR7kngzQnA==", + "dev": true, + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "14 >=14.20 || 16 >=16.20 || >=18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/webpack-hot-middleware": { "version": "2.26.1", "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz", @@ -41692,9 +41909,9 @@ } }, "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", "dev": true }, "node_modules/wrap-ansi": { @@ -41844,9 +42061,9 @@ } }, "node_modules/ws": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", - "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "dev": true, "engines": { "node": ">=10.0.0" @@ -42050,9 +42267,9 @@ } }, "node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", "engines": { "node": ">=12.20" }, diff --git a/package.json b/package.json index cd5e34e86..a614d108e 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "@types/request": "^2.48.12", "@types/request-promise": "^4.1.51", "@types/shelljs": "^0.8.15", - "@types/uuid": "^9.0.7", + "@types/uuid": "^10.0.0", "@types/valid-url": "^1.0.7", "@types/webpack": "^5.28.5", "@types/youtube": "0.0.50", @@ -134,7 +134,7 @@ "@types/pdf-parse": "^1.1.4", "@types/reveal": "^4.2.0", "@types/supercluster": "^7.1.3", - "@types/web": "^0.0.148", + "@types/web": "^0.0.151", "@types/webpack-hot-middleware": "^2.25.9", "@typescript-eslint/parser": "^7.8.0", "@webscopeio/react-textarea-autocomplete": "^4.9.2", @@ -200,7 +200,7 @@ "function-plot": "^1.23.3", "golden-layout": "^2.6.0", "google-auth-library": "^9.4.1", - "googleapis": "^133.0.0", + "googleapis": "^140.0.1", "googlephotos": "^0.3.5", "got": "^14.0.0", "howler": "^2.2.4", @@ -239,7 +239,7 @@ "nodemon": "^3.0.2", "npm": "^10.2.5", "openai": "^4.26.0", - "p-limit": "^5.0.0", + "p-limit": "^6.1.0", "passport": "^0.7.0", "passport-google-oauth20": "^2.0.0", "passport-local": "^1.0.0", @@ -269,11 +269,11 @@ "react-awesome-reveal": "^4.2.7", "react-color": "^2.19.3", "react-compound-slider": "^3.4.0", - "react-datepicker": "^6.1.0", + "react-datepicker": "^7.3.0", "react-dom": "^18.2.0", "react-grid-layout": "^1.4.4", "react-icons": "^5.0.1", - "react-jsx-parser": "^1.29.0", + "react-jsx-parser": "^2.0.0", "react-latex-next": "^3.0.0", "react-loading": "^2.0.3", "react-map-gl": "^7.1.6", @@ -293,7 +293,7 @@ "request": "^2.88.2", "request-promise": "^4.2.6", "reveal.js": "^5.0.2", - "rimraf": "^5.0.5", + "rimraf": "^6.0.0", "sass": "^1.69.5", "sass-loader": "^14.2.0", "serializr": "^3.0.2", @@ -315,7 +315,7 @@ "url": "^0.11.3", "url-loader": "^4.1.1", "util": "^0.12.5", - "uuid": "^9.0.1", + "uuid": "^10.0.0", "valid-url": "^1.0.9", "web-request": "^1.0.7", "webpack": "^5.89.0", diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 3eb3008c4..b2f0280a5 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -17,7 +17,7 @@ import { DocData } from '../../../fields/DocSymbols'; import { List } from '../../../fields/List'; import { ObjectField } from '../../../fields/ObjectField'; import { RichTextField } from '../../../fields/RichTextField'; -import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types'; +import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; import { DragManager } from '../../util/DragManager'; import { dropActionType } from '../../util/DropActionTypes'; @@ -47,7 +47,7 @@ export class CollectionMenu extends AntimodeMenu { private _docBtnRef = React.createRef(); - constructor(props: any) { + constructor(props: CollectionMenuProps) { super(props); makeObservable(this); CollectionMenu.Instance = this; @@ -279,8 +279,8 @@ export class CollectionViewBaseChrome extends React.Component { const activeDash = Doc.ActiveDashboard; if (activeDash) { - button.target_childFilters = (Doc.MySearcher._childFilters || activeDash._childFilters) instanceof ObjectField ? ObjectField.MakeCopy((Doc.MySearcher._childFilters || activeDash._childFilters) as any as ObjectField) : undefined; - button.target_searchFilterDocs = activeDash._searchFilterDocs instanceof ObjectField ? ObjectField.MakeCopy(activeDash._searchFilterDocs as any as ObjectField) : undefined; + button.target_childFilters = (Doc.MySearcher._childFilters || activeDash._childFilters) instanceof ObjectField ? ObjectField.MakeCopy((Doc.MySearcher._childFilters || activeDash._childFilters) as ObjectField) : undefined; + button.target_searchFilterDocs = activeDash._searchFilterDocs instanceof ObjectField ? ObjectField.MakeCopy(activeDash._searchFilterDocs) : undefined; } }, }; @@ -338,15 +338,9 @@ export class CollectionViewBaseChrome extends React.Component { - const target = this.document !== Doc.MyLeftSidebarPanel ? this.document : DocCast(this.document.proto); - target._type_collection = (e.target as any).selectedOptions[0].value; - }; - - commandChanged = (e: React.ChangeEvent) => { + commandChanged = (e: React.ChangeEvent) => { runInAction(() => { - this._currentKey = (e.target as any).selectedOptions[0].value; + this._currentKey = e.target.selectedOptions[0].value; }); }; @@ -485,7 +479,7 @@ export class CollectionNoteTakingViewChrome extends React.Component { + onKeyChange = (e: React.FormEvent, { newValue }: { newValue: string }) => { this._currentKey = newValue; }; @@ -538,7 +532,6 @@ export class CollectionNoteTakingViewChrome extends React.Component {['vertical', 'horizontal', 'none'].map(type => ( - ))} -- cgit v1.2.3-70-g09d2 From 59ca918ea0918b41f1e2fa4b6acb8725ca9b44af Mon Sep 17 00:00:00 2001 From: geireann Date: Wed, 10 Jul 2024 13:44:39 -0400 Subject: fixed caption font color --- src/client/views/StyleProvider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index b7f8a3170..8c100f238 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -152,7 +152,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt Date: Thu, 11 Jul 2024 12:08:26 -0400 Subject: Revert "Merge branch 'eleanor-gptdraw' into master" This reverts commit 4438e7fe202ff4091b26f073122e7866ec9abb46, reversing changes made to 59ca918ea0918b41f1e2fa4b6acb8725ca9b44af. --- package-lock.json | 73 ---- package.json | 1 - src/client/apis/gpt/GPT.ts | 11 +- src/client/util/CurrentUserUtils.ts | 4 +- src/client/util/bezierFit.ts | 146 -------- src/client/views/GestureOverlay.tsx | 28 +- src/client/views/LightboxView.scss | 24 +- src/client/views/LightboxView.tsx | 7 - src/client/views/MainView.tsx | 5 - src/client/views/MarqueeAnnotator.tsx | 146 -------- src/client/views/collections/CollectionMenu.scss | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 242 ++++-------- .../collectionFreeForm/ImageLabelHandler.scss | 14 - .../collections/collectionFreeForm/MarqueeView.tsx | 6 +- src/client/views/global/globalScripts.ts | 4 +- src/client/views/nodes/PDFBox.scss | 16 +- src/client/views/nodes/PDFBox.tsx | 37 +- src/client/views/pdf/AnchorMenu.tsx | 14 - src/client/views/pdf/PDFViewer.tsx | 3 - src/client/views/smartdraw/DrawingPalette.scss | 11 - src/client/views/smartdraw/DrawingPalette.tsx | 89 ----- src/client/views/smartdraw/SmartDrawHandler.tsx | 409 --------------------- src/fields/Doc.ts | 48 --- src/fields/InkField.ts | 1 - 24 files changed, 110 insertions(+), 1231 deletions(-) delete mode 100644 src/client/views/smartdraw/DrawingPalette.scss delete mode 100644 src/client/views/smartdraw/DrawingPalette.tsx delete mode 100644 src/client/views/smartdraw/SmartDrawHandler.tsx diff --git a/package-lock.json b/package-lock.json index 922e2e4f0..f11d8a462 100644 --- a/package-lock.json +++ b/package-lock.json @@ -219,7 +219,6 @@ "stream-browserify": "^3.0.0", "styled-components": "^6.1.1", "supercluster": "^8.0.1", - "svgson": "^5.3.1", "textarea-caret": "^3.1.0", "tough-cookie": "^4.1.3", "tslint": "^6.1.3", @@ -16770,29 +16769,6 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, - "node_modules/deep-rename-keys": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/deep-rename-keys/-/deep-rename-keys-0.2.1.tgz", - "integrity": "sha512-RHd9ABw4Fvk+gYDWqwOftG849x0bYOySl/RgX0tLI9i27ZIeSO91mLZJEp7oPHOMFqHvpgu21YptmDt0FYD/0A==", - "dependencies": { - "kind-of": "^3.0.2", - "rename-keys": "^1.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deep-rename-keys/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -22603,11 +22579,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -37166,14 +37137,6 @@ "@types/unist": "*" } }, - "node_modules/rename-keys": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/rename-keys/-/rename-keys-1.2.0.tgz", - "integrity": "sha512-U7XpAktpbSgHTRSNRrjKSrjYkZKuhUukfoBlXWXUExCAqhzh1TU3BDRAfJmarcl5voKS+pbKU9MvyLWKZ4UEEg==", - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/renderkid": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", @@ -39265,15 +39228,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/svgson": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/svgson/-/svgson-5.3.1.tgz", - "integrity": "sha512-qdPgvUNWb40gWktBJnbJRelWcPzkLed/ShhnRsjbayXz8OtdPOzbil9jtiZdrYvSDumAz/VNQr6JaNfPx/gvPA==", - "dependencies": { - "deep-rename-keys": "^0.2.1", - "xml-reader": "2.4.3" - } - }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -42138,19 +42092,6 @@ "xtend": "^4.0.0" } }, - "node_modules/xml-lexer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/xml-lexer/-/xml-lexer-0.2.2.tgz", - "integrity": "sha512-G0i98epIwiUEiKmMcavmVdhtymW+pCAohMRgybyIME9ygfVu8QheIi+YoQh3ngiThsT0SQzJT4R0sKDEv8Ou0w==", - "dependencies": { - "eventemitter3": "^2.0.0" - } - }, - "node_modules/xml-lexer/node_modules/eventemitter3": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", - "integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==" - }, "node_modules/xml-name-validator": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", @@ -42165,20 +42106,6 @@ "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==" }, - "node_modules/xml-reader": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/xml-reader/-/xml-reader-2.4.3.tgz", - "integrity": "sha512-xWldrIxjeAMAu6+HSf9t50ot1uL5M+BtOidRCWHXIeewvSeIpscWCsp4Zxjk8kHHhdqFBrfK8U0EJeCcnyQ/gA==", - "dependencies": { - "eventemitter3": "^2.0.0", - "xml-lexer": "^0.2.2" - } - }, - "node_modules/xml-reader/node_modules/eventemitter3": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", - "integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==" - }, "node_modules/xml2js": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", diff --git a/package.json b/package.json index 895f5345a..a614d108e 100644 --- a/package.json +++ b/package.json @@ -304,7 +304,6 @@ "stream-browserify": "^3.0.0", "styled-components": "^6.1.1", "supercluster": "^8.0.1", - "svgson": "^5.3.1", "textarea-caret": "^3.1.0", "tough-cookie": "^4.1.3", "tslint": "^6.1.3", diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index a7bd05a21..05007960d 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -12,7 +12,6 @@ enum GPTCallType { DESCRIBE = 'describe', MERMAID = 'mermaid', DATA = 'data', - DRAW = 'draw', } type GPTCallOpts = { @@ -54,12 +53,6 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { temp: 0, prompt: 'List unique differences between the content of the UserAnswer and Rubric. Before each difference, label it and provide any additional information the UserAnswer missed and explain it in second person without separating it into UserAnswer and Rubric content and additional information. If there are no differences, say correct', }, - draw: { - model: 'gpt-4o', - maxTokens: 1024, - temp: 0.5, - prompt: 'Given an item, a level of complexity from 1-10, and a size in pixels, generate a detailed and colored line drawing representation of it. Make sure every element has the stroke field filled out. More complex drawings will have much more detail and strokes. The drawing should be in SVG format with no additional text or comments. For path coordinates, make sure you format with a comma between numbers, like M100,200 C150,250 etc. The only supported commands are line, ellipse, circle, rect, and path with M, Q, C, and L so only use those.', - }, }; let lastCall = ''; @@ -70,10 +63,10 @@ let lastResp = ''; * @param inputText Text to process * @returns AI Output */ -const gptAPICall = async (inputTextIn: string, callType: GPTCallType, prompt?: any, dontCache?: boolean) => { +const gptAPICall = async (inputTextIn: string, callType: GPTCallType, prompt?: any) => { const inputText = [GPTCallType.SUMMARY, GPTCallType.FLASHCARD, GPTCallType.QUIZ].includes(callType) ? inputTextIn + '.' : inputTextIn; const opts: GPTCallOpts = callTypeMap[callType]; - if (lastCall === inputText && dontCache !== true) return lastResp; + if (lastCall === inputText) return lastResp; try { lastCall = inputText; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 141695d86..e095bc659 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -730,7 +730,6 @@ pie title Minerals in my tap water static inkTools():Button[] { return [ { title: "Pen", toolTip: "Pen (Ctrl+P)", btnType: ButtonType.ToggleButton, icon: "pen-nib", toolType: "pen", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' }}, - { title: "Highlight", toolTip: "Highlight (Ctrl+H)", btnType: ButtonType.ToggleButton, icon: "highlighter",toolType: "highlighter", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' }}, { title: "Write", toolTip: "Write (Ctrl+Shift+P)", btnType: ButtonType.ToggleButton, icon: "pen", toolType: "write", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' }, funcs: {hidden:"IsNoviceMode()" }}, { title: "Eraser", toolTip: "Eraser (Ctrl+E)", btnType: ButtonType.MultiToggleButton, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'}, funcs: {toolType:"activeEraserTool()"}, subMenu: [ @@ -743,10 +742,9 @@ pie title Minerals in my tap water { title: "Square", toolTip: "Square (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "square", toolType: Gestures.Rectangle, scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} }, { title: "Line", toolTip: "Line (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "minus", toolType: Gestures.Line, scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} }, { title: "Mask", toolTip: "Mask", btnType: ButtonType.ToggleButton, icon: "user-circle",toolType: "inkMask", scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"IsNoviceMode()" } }, - { title: "Labels", toolTip: "Labels", btnType: ButtonType.ToggleButton, icon: "text-width", toolType: "labels", scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}, }, + { title: "Labels", toolTip: "Lab els", btnType: ButtonType.ToggleButton, icon: "text-width", toolType: "labels", scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}, }, { title: "Width", toolTip: "Stroke width", btnType: ButtonType.NumberSliderButton, toolType: "strokeWidth", ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, numBtnMin: 1}, { title: "Ink", toolTip: "Stroke color", btnType: ButtonType.ColorButton, icon: "pen", toolType: "strokeColor", ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'} }, - { title: "Smart Draw", toolTip: "Draw with GPT", btnType: ButtonType.ToggleButton, icon: "user-pen", toolType: "smartdraw", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}'}, funcs: {hidden: "IsNoviceMode()"}}, ]; } diff --git a/src/client/util/bezierFit.ts b/src/client/util/bezierFit.ts index f5696afaf..d6f3f2340 100644 --- a/src/client/util/bezierFit.ts +++ b/src/client/util/bezierFit.ts @@ -2,18 +2,8 @@ /* eslint-disable prefer-destructuring */ /* eslint-disable no-param-reassign */ /* eslint-disable camelcase */ -import e from 'cors'; import { Point } from '../../pen-gestures/ndollar'; -export enum SVGType { - Rect = 'rect', - Path = 'path', - Circle = 'circle', - Ellipse = 'ellipse', - Line = 'line', - Polygon = 'polygon', -} - class SmartRect { minx: number = 0; miny: number = 0; @@ -567,12 +557,6 @@ function FitCubic(d: Point[], first: number, last: number, tHat1: Point, tHat2: const negThatCenter = new Point(-tHatCenter.X, -tHatCenter.Y); FitCubic(d, splitPoint2D, last, negThatCenter, tHat2, error, result); } -/** - * Convert polyline coordinates to a (multi) segment bezier curve - * @param d - polyline coordinates - * @param error - how much error to allow in fitting (measured in pixels) - * @returns - */ export function FitCurve(d: Point[], error: number) { const tHat1 = ComputeLeftTangent(d, 0); // Unit tangent vectors at endpoints const tHat2 = ComputeRightTangent(d, d.length - 1); @@ -602,136 +586,6 @@ export function FitOneCurve(d: Point[], tHat1?: Point, tHat2?: Point) { return { finalCtrls, error }; } -// alpha determines how far away the tangents are, or the "tightness" of the bezier -export function GenerateControlPoints(coordinates: Point[], alpha = 0.1) { - const firstEnd = coordinates.length ? [coordinates[0], coordinates[0]] : []; - const lastEnd = coordinates.length ? [coordinates.lastElement(), coordinates.lastElement()] : []; - const points: Point[] = coordinates.slice(1, coordinates.length - 1).flatMap((pt, index, inkData) => { - const prevPt: Point = index === 0 ? firstEnd[0] : inkData[index - 1]; - const nextPt: Point = index === inkData.length - 1 ? lastEnd[0] : inkData[index + 1]; - if (prevPt.X === nextPt.X) { - const verticalDist = nextPt.Y - prevPt.Y; - return [{ X: pt.X, Y: pt.Y - alpha * verticalDist }, pt, pt, { X: pt.X, Y: pt.Y + alpha * verticalDist }]; - } else if (prevPt.Y === nextPt.Y) { - const horizDist = nextPt.X - prevPt.X; - return [{ X: pt.X - alpha * horizDist, Y: pt.Y }, pt, pt, { X: pt.X + alpha * horizDist, Y: pt.Y }]; - } - // tangent vectors between the adjacent points - const tanX = nextPt.X - prevPt.X; - const tanY = nextPt.Y - prevPt.Y; - const ctrlPt1: Point = { X: pt.X - alpha * tanX, Y: pt.Y - alpha * tanY }; - const ctrlPt2: Point = { X: pt.X + alpha * tanX, Y: pt.Y + alpha * tanY }; - return [ctrlPt1, pt, pt, ctrlPt2]; - }); - return [...firstEnd, ...points, ...lastEnd]; -} - -export function SVGToBezier(name: SVGType, attributes: any): Point[] { - console.log('in svg to bezier', name, attributes); - switch (name) { - case 'line': - const x1 = parseInt(attributes.x1); - const x2 = parseInt(attributes.x2); - const y1 = parseInt(attributes.y1); - const y2 = parseInt(attributes.y2); - return [ - { X: x1, Y: y1 }, - { X: x1, Y: y1 }, - { X: x2, Y: y2 }, - { X: x2, Y: y2 }, - ]; - case 'circle': - case 'ellipse': - const c = 0.551915024494; - const centerX = parseInt(attributes.cx); - const centerY = parseInt(attributes.cy); - const radiusX = parseInt(attributes.rx) || parseInt(attributes.r); - const radiusY = parseInt(attributes.ry) || parseInt(attributes.r); - return [ - { X: centerX, Y: centerY + radiusY }, - { X: centerX + c * radiusX, Y: centerY + radiusY }, - { X: centerX + radiusX, Y: centerY + c * radiusY }, - { X: centerX + radiusX, Y: centerY }, - { X: centerX + radiusX, Y: centerY }, - { X: centerX + radiusX, Y: centerY - c * radiusY }, - { X: centerX + c * radiusX, Y: centerY - radiusY }, - { X: centerX, Y: centerY - radiusY }, - { X: centerX, Y: centerY - radiusY }, - { X: centerX - c * radiusX, Y: centerY - radiusY }, - { X: centerX - radiusX, Y: centerY - c * radiusY }, - { X: centerX - radiusX, Y: centerY }, - { X: centerX - radiusX, Y: centerY }, - { X: centerX - radiusX, Y: centerY + c * radiusY }, - { X: centerX - c * radiusX, Y: centerY + radiusY }, - { X: centerX, Y: centerY + radiusY }, - ]; - case 'rect': - const x = parseInt(attributes.x); - const y = parseInt(attributes.y); - const width = parseInt(attributes.width); - const height = parseInt(attributes.height); - return [ - { X: x, Y: y }, - { X: x, Y: y }, - { X: x + width, Y: y }, - { X: x + width, Y: y }, - { X: x + width, Y: y }, - { X: x + width, Y: y }, - { X: x + width, Y: y + height }, - { X: x + width, Y: y + height }, - { X: x + width, Y: y + height }, - { X: x + width, Y: y + height }, - { X: x, Y: y + height }, - { X: x, Y: y + height }, - { X: x, Y: y + height }, - { X: x, Y: y + height }, - { X: x, Y: y }, - { X: x, Y: y }, - ]; - case 'path': - const coordList: Point[] = []; - const startPt = attributes.d.match(/M(-?\d+\.?\d*),(-?\d+\.?\d*)/); - coordList.push({ X: parseInt(startPt[1]), Y: parseInt(startPt[2]) }); - const matches: RegExpMatchArray[] = Array.from( - attributes.d.matchAll(/Q(-?\d+\.?\d*),(-?\d+\.?\d*) (-?\d+\.?\d*),(-?\d+\.?\d*)|C(-?\d+\.?\d*),(-?\d+\.?\d*) (-?\d+\.?\d*),(-?\d+\.?\d*) (-?\d+\.?\d*),(-?\d+\.?\d*)|L(-?\d+\.?\d*),(-?\d+\.?\d*)/g) - ); - let lastPt: Point; - matches.forEach(match => { - if (match[0].startsWith('Q')) { - coordList.push({ X: parseInt(match[1]), Y: parseInt(match[2]) }); - coordList.push({ X: parseInt(match[1]), Y: parseInt(match[2]) }); - coordList.push({ X: parseInt(match[3]), Y: parseInt(match[4]) }); - coordList.push({ X: parseInt(match[3]), Y: parseInt(match[4]) }); - lastPt = { X: parseInt(match[3]), Y: parseInt(match[4]) }; - } else if (match[0].startsWith('C')) { - coordList.push({ X: parseInt(match[5]), Y: parseInt(match[6]) }); - coordList.push({ X: parseInt(match[7]), Y: parseInt(match[8]) }); - coordList.push({ X: parseInt(match[9]), Y: parseInt(match[10]) }); - coordList.push({ X: parseInt(match[9]), Y: parseInt(match[10]) }); - lastPt = { X: parseInt(match[9]), Y: parseInt(match[10]) }; - } else { - coordList.push(lastPt || { X: parseInt(startPt[1]), Y: parseInt(startPt[2]) }); - coordList.push({ X: parseInt(match[11]), Y: parseInt(match[12]) }); - coordList.push({ X: parseInt(match[11]), Y: parseInt(match[12]) }); - coordList.push({ X: parseInt(match[11]), Y: parseInt(match[12]) }); - lastPt = { X: parseInt(match[11]), Y: parseInt(match[12]) }; - } - }); - const hasZ = attributes.d.match(/Z/); - if (hasZ) { - coordList.push(lastPt); - coordList.push({ X: parseInt(startPt[1]), Y: parseInt(startPt[2]) }); - coordList.push({ X: parseInt(startPt[1]), Y: parseInt(startPt[2]) }); - } else { - coordList.pop(); - } - return coordList; - case 'polygon': - default: - return []; - } -} - /* static double GetTValueFromSValue (const BezierRep &parent, double t, double endT, bool left, double influenceDistance, double &excess) { double dist = 0; diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index a1f7712c1..e3e252593 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -240,15 +240,15 @@ export class GestureOverlay extends ObservableReactComponent { @observable private _doc: Opt = undefined; @observable private _docTarget: Opt = undefined; @observable private _docView: Opt = undefined; - @observable private _showPalette: boolean = false; @computed get leftBorder() { return Math.min(this._props.PanelWidth / 4, this._props.maxBorder[0]); } // prettier-ignore @computed get topBorder() { return Math.min(this._props.PanelHeight / 4, this._props.maxBorder[1]); } // prettier-ignore @@ -204,9 +202,6 @@ export class LightboxView extends ObservableReactComponent { toggleFitWidth = () => { this._doc && (this._doc._layout_fitWidth = !this._doc._layout_fitWidth); }; - togglePalette = () => { - this._showPalette = !this._showPalette; - }; togglePen = () => { Doc.ActiveTool = Doc.ActiveTool === InkTool.Pen ? InkTool.None : InkTool.Pen; }; @@ -324,10 +319,8 @@ export class LightboxView extends ObservableReactComponent { {toggleBtn('lightboxView-navBtn', 'toggle reading view', this._doc?._layout_fitWidth, 'book-open', 'book', this.toggleFitWidth)} {toggleBtn('lightboxView-tabBtn', 'open document in a tab', false, 'file-download', '', this.downloadDoc)} - {toggleBtn('lightboxView-paletteBtn', 'toggle annotation palette', this._showPalette === true, 'palette', '', this.togglePalette)} {toggleBtn('lightboxView-penBtn', 'toggle pen annotation', Doc.ActiveTool === InkTool.Pen, 'pen', '', this.togglePen)} {toggleBtn('lightboxView-exploreBtn', 'toggle navigate only mode', SnappingManager.ExploreMode, 'globe-americas', '', this.toggleExplore)} - {this._showPalette && }
); } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 30720a3a2..ef1bcfb64 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -76,7 +76,6 @@ import { PresBox } from './nodes/trails'; import { AnchorMenu } from './pdf/AnchorMenu'; import { GPTPopup } from './pdf/GPTPopup/GPTPopup'; import { TopBar } from './topbar/TopBar'; -import { SmartDrawHandler } from './smartdraw/SmartDrawHandler'; const { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } = require('./global/globalCssVariables.module.scss'); // prettier-ignore const _global = (window /* browser */ || global) /* node */ as any; @@ -318,7 +317,6 @@ export class MainView extends ObservableReactComponent<{}> { fa.faCompass, fa.faSnowflake, fa.faStar, - fa.faSplotch, fa.faMicrophone, fa.faCircleHalfStroke, fa.faKeyboard, @@ -396,7 +394,6 @@ export class MainView extends ObservableReactComponent<{}> { fa.faArrowsLeftRight, fa.faPause, fa.faPen, - fa.faUserPen, fa.faPenNib, fa.faPhone, fa.faPlay, @@ -442,7 +439,6 @@ export class MainView extends ObservableReactComponent<{}> { fa.faEyeDropper, fa.faPaintRoller, fa.faBars, - fa.faBarsStaggered, fa.faBrush, fa.faShapes, fa.faEllipsisH, @@ -1093,7 +1089,6 @@ export class MainView extends ObservableReactComponent<{}> { - diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index f06f3efe0..c18ac6738 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -28,7 +28,6 @@ export interface MarqueeAnnotatorProps { marqueeContainer: HTMLDivElement; docView: () => DocumentView; savedAnnotations: () => ObservableMap; - savedTapes: () => ObservableMap; selectionText: () => string; annotationLayer: HTMLDivElement; addDocument: (doc: Doc) => boolean; @@ -75,7 +74,6 @@ export class MarqueeAnnotator extends ObservableReactComponent): Opt => { - // const savedTapeMap = savedTapes?.values() && Array.from(savedTapes?.values()).length ? savedTapes : this.props.savedTapes(); - // if (savedTapeMap.size === 0) return undefined; - // const tapes = Array.from(savedTapeMap.values())[0]; - // const doc = this.props.Document; - // const scale = (this.props.annotationLayerScaling?.() || 1) * NumCast(doc._freeform_scale, 1); - // if (tapes.length && (tapes[0] as any).marqueeing) { - // const anno = tapes[0]; - // const containerOffset = this.props.containerOffset?.() || [0, 0]; - // const tape = Docs.Create.FreeformDocument([], { - // onClick: isLinkButton ? FollowLinkScript() : undefined, - // backgroundColor: color, - // annotationOn: this.props.Document, - // title: 'Tape on ' + this.props.Document.title, - // }); - // tape.x = NumCast(doc.freeform_panX_min) + (parseInt(anno.style.left || '0') - containerOffset[0]) / scale; - // tape.y = NumCast(doc.freeform_panY_min) + (parseInt(anno.style.top || '0') - containerOffset[1]) / scale; - // tape._height = parseInt(anno.style.height || '0') / scale; - // tape._width = parseInt(anno.style.width || '0') / scale; - // anno.remove(); - // savedTapeMap.clear(); - // return tape; - // } - - // const textRegionAnno = Docs.Create.ConfigDocument({ - // annotationOn: this.props.Document, - // text: this.props.selectionText() as any, // text want an RTFfield, but strings are acceptable, too. - // text_html: this.props.selectionText() as any, - // backgroundColor: 'transparent', - // presentation_duration: 2100, - // presentation_transition: 500, - // presentation_zoomText: true, - // title: '>' + this.props.Document.title, - // }); - // const textRegionAnnoProto = textRegionAnno[DocData]; - // let minX = Number.MAX_VALUE; - // let maxX = -Number.MAX_VALUE; - // let minY = Number.MAX_VALUE; - // let maxY = -Number.MIN_VALUE; - // const annoRects: string[] = []; - // savedAnnoMap.forEach((value: HTMLDivElement[]) => - // value.forEach(anno => { - // const x = parseInt(anno.style.left ?? '0'); - // const y = parseInt(anno.style.top ?? '0'); - // const height = parseInt(anno.style.height ?? '0'); - // const width = parseInt(anno.style.width ?? '0'); - // annoRects.push(`${x}:${y}:${width}:${height}`); - // anno.remove(); - // minY = Math.min(NumCast(y), minY); - // minX = Math.min(NumCast(x), minX); - // maxY = Math.max(NumCast(y) + NumCast(height), maxY); - // maxX = Math.max(NumCast(x) + NumCast(width), maxX); - // }) - // ); - - // textRegionAnnoProto.y = Math.max(minY, 0); - // textRegionAnnoProto.x = Math.max(minX, 0); - // textRegionAnnoProto.height = Math.max(maxY, 0) - Math.max(minY, 0); - // textRegionAnnoProto.width = Math.max(maxX, 0) - Math.max(minX, 0); - // textRegionAnnoProto.backgroundColor = color; - // // mainAnnoDocProto.text = this._selectionText; - // textRegionAnnoProto.text_inlineAnnotations = new List(annoRects); - // textRegionAnnoProto.opacity = 0; - // textRegionAnnoProto.layout_unrendered = true; - // savedAnnoMap.clear(); - // return textRegionAnno; - // }; - - @undoBatch - makeTapeDocument = (color: string, isLinkButton?: boolean, savedTapes?: ObservableMap): Opt => { - // const savedAnnoMap = savedTapes?.values() && Array.from(savedTapes?.values()).length ? savedTapes : this.props.savedTapes(); - // if (savedAnnoMap.size === 0) return undefined; - // const savedAnnos = Array.from(savedAnnoMap.values())[0]; - const doc = this.props.Document; - const scale = (this.props.annotationLayerScaling?.() || 1) * NumCast(doc._freeform_scale, 1); - const marqueeAnno = Docs.Create.FreeformDocument([], { - onClick: isLinkButton ? FollowLinkScript() : undefined, - backgroundColor: color, - annotationOn: this.props.Document, - title: 'Annotation on ' + this.props.Document.title, - }); - marqueeAnno.x = NumCast(doc.freeform_panX_min) / scale; - marqueeAnno.y = NumCast(doc.freeform_panY_min) / scale; - marqueeAnno._height = parseInt('100') / scale; - marqueeAnno._width = parseInt('100') / scale; - return marqueeAnno; - // } - - // const textRegionAnno = Docs.Create.ConfigDocument({ - // annotationOn: this.props.Document, - // text: this.props.selectionText() as any, // text want an RTFfield, but strings are acceptable, too. - // text_html: this.props.selectionText() as any, - // backgroundColor: 'transparent', - // presentation_duration: 2100, - // presentation_transition: 500, - // presentation_zoomText: true, - // title: '>' + this.props.Document.title, - // }); - // const textRegionAnnoProto = textRegionAnno[DocData]; - // let minX = Number.MAX_VALUE; - // let maxX = -Number.MAX_VALUE; - // let minY = Number.MAX_VALUE; - // let maxY = -Number.MIN_VALUE; - // const annoRects: string[] = []; - // savedAnnoMap.forEach((value: HTMLDivElement[]) => - // value.forEach(anno => { - // const x = parseInt(anno.style.left ?? '0'); - // const y = parseInt(anno.style.top ?? '0'); - // const height = parseInt(anno.style.height ?? '0'); - // const width = parseInt(anno.style.width ?? '0'); - // annoRects.push(`${x}:${y}:${width}:${height}`); - // anno.remove(); - // minY = Math.min(NumCast(y), minY); - // minX = Math.min(NumCast(x), minX); - // maxY = Math.max(NumCast(y) + NumCast(height), maxY); - // maxX = Math.max(NumCast(x) + NumCast(width), maxX); - // }) - // ); - - // textRegionAnnoProto.y = Math.max(minY, 0); - // textRegionAnnoProto.x = Math.max(minX, 0); - // textRegionAnnoProto.height = Math.max(maxY, 0) - Math.max(minY, 0); - // textRegionAnnoProto.width = Math.max(maxX, 0) - Math.max(minX, 0); - // textRegionAnnoProto.backgroundColor = color; - // // mainAnnoDocProto.text = this._selectionText; - // textRegionAnnoProto.text_inlineAnnotations = new List(annoRects); - // textRegionAnnoProto.opacity = 0; - // textRegionAnnoProto.layout_unrendered = true; - // savedAnnoMap.clear(); - // return textRegionAnno; - }; - @action highlight = (color: string, isLinkButton: boolean, savedAnnotations?: ObservableMap, addAsAnnotation?: boolean) => { // creates annotation documents for current highlights @@ -272,15 +136,6 @@ export class MarqueeAnnotator extends ObservableReactComponent, addAsAnnotation?: boolean) => { - // creates annotation documents for current highlights - const effectiveAcl = GetEffectiveAcl(this.props.Document[DocData]); - const tape = [AclAugment, AclSelfEdit, AclEdit, AclAdmin].includes(effectiveAcl) && this.makeTapeDocument(color, isLinkButton, savedTapes); - addAsAnnotation && tape && this.props.addDocument(tape); - return tape as Doc; - }; - public static previewNewAnnotation = action((savedAnnotations: ObservableMap, annotationLayer: HTMLDivElement, div: HTMLDivElement, page: number) => { div.style.backgroundColor = '#ACCEF7'; div.style.opacity = '0.5'; @@ -327,7 +182,6 @@ export class MarqueeAnnotator extends ObservableReactComponent this.props.anchorMenuClick?.()?.(this.highlight(this.props.highlightDragSrcColor ?? 'rgba(173, 216, 230, 0.75)', true, undefined, true)), 'make sidebar annotation'); AnchorMenu.Instance.OnAudio = unimplementedFunction; AnchorMenu.Instance.Highlight = (color: string) => this.highlight(color, false, undefined, true); - AnchorMenu.Instance.Tape = (color: string) => this.tape(color, false, undefined, true); AnchorMenu.Instance.GetAnchor = (savedAnnotations?: ObservableMap /* , addAsAnnotation?: boolean */) => this.highlight('rgba(173, 216, 230, 0.75)', true, savedAnnotations, true); AnchorMenu.Instance.onMakeAnchor = () => AnchorMenu.Instance.GetAnchor(undefined, true); diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss index 45d9394ed..3ec875df4 100644 --- a/src/client/views/collections/CollectionMenu.scss +++ b/src/client/views/collections/CollectionMenu.scss @@ -6,7 +6,7 @@ align-content: center; justify-content: space-between; background-color: $dark-gray; - height: 40px; + height: 35px; border-bottom: $standard-border; padding: 0 10px; align-items: center; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 8f8cb9083..d611db1f8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,7 +1,7 @@ /* eslint-disable react/jsx-props-no-spreading */ /* eslint-disable jsx-a11y/click-events-have-key-events */ /* eslint-disable jsx-a11y/no-static-element-interactions */ -import { Bezier, Point } from 'bezier-js'; +import { Bezier } from 'bezier-js'; import { Colors } from 'browndash-components'; import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; @@ -27,7 +27,6 @@ import { aggregateBounds, clamp, emptyFunction, intersectRect, Utils } from '../ import { Docs } from '../../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; import { DocUtils } from '../../../documents/DocUtils'; -import { FitCurve, GenerateControlPoints } from '../../../util/bezierFit'; import { DragManager } from '../../../util/DragManager'; import { dropActionType } from '../../../util/DropActionTypes'; import { CompileScript } from '../../../util/Scripting'; @@ -56,7 +55,6 @@ import { CollectionFreeFormPannableContents } from './CollectionFreeFormPannable import { CollectionFreeFormRemoteCursors } from './CollectionFreeFormRemoteCursors'; import './CollectionFreeFormView.scss'; import { MarqueeView } from './MarqueeView'; -import { DrawingOptions, SmartDrawHandler } from '../../smartdraw/SmartDrawHandler'; @observer class CollectionFreeFormOverlayView extends React.Component<{ elements: () => ViewDefResult[] }> { @@ -120,7 +118,6 @@ export class CollectionFreeFormView extends CollectionSubView(); @observable _marqueeViewRef = React.createRef(); @@ -500,30 +497,28 @@ export class CollectionFreeFormView extends CollectionSubView { this._deleteList.lastElement()?._props.removeDocument?.(this._deleteList.map(ink => ink.Document)); @@ -615,48 +609,34 @@ export class CollectionFreeFormView extends CollectionSubView { - e.stopImmediatePropagation(); + /** + * Erases strokes by intersecting them with an invisible "eraser stroke". + * By default this iterates through all intersected ink strokes, determines their segmentation, draws back the non-intersected segments, + * and deletes the original stroke. + */ + @action + onEraserMove = (e: PointerEvent, down: number[], delta: number[]) => { const currPoint = { X: e.clientX, Y: e.clientY }; this._eraserPts.push([currPoint.X, currPoint.Y]); this._eraserPts = this._eraserPts.slice(Math.max(0, this._eraserPts.length - 5)); - if (Doc.ActiveTool === InkTool.RadiusEraser) { - const strokeMap: Map = this.getRadiusEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint); - strokeMap.forEach((intersects, stroke) => { - if (!this._deleteList.includes(stroke)) { - this._deleteList.push(stroke); - SetActiveInkWidth(StrCast(stroke.Document.stroke_width?.toString()) || '1'); - SetActiveInkColor(StrCast(stroke.Document.color?.toString()) || 'black'); - const segments = this.radiusErase(stroke, intersects.sort()); - segments?.forEach(segment => - this.forceStrokeGesture( - e, - Gestures.Stroke, - segment.reduce((data, curve) => [...data, ...curve.points.map(p => stroke.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]) - ) - ); - } - stroke.layoutDoc.opacity = 0; - stroke.layoutDoc.dontIntersect = true; - }); - } else { - this.getEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint).forEach(intersect => { - if (!this._deleteList.includes(intersect.inkView)) { - this._deleteList.push(intersect.inkView); - SetActiveInkWidth(StrCast(intersect.inkView.Document.stroke_width?.toString()) || '1'); - SetActiveInkColor(StrCast(intersect.inkView.Document.color?.toString()) || 'black'); - // create a new curve by appending all curves of the current segment together in order to render a single new stroke. - if (Doc.ActiveTool !== InkTool.StrokeEraser) { - // this._eraserLock++; - const segments = this.segmentErase(intersect.inkView, intersect.t); // intersect.t is where the eraser intersected the ink stroke - want to remove the segment that starts at the intersection just before this t value and goes to the one just after it - const newStrokes = segments?.map(segment => { - const points = segment.reduce((data, curve) => [...data, ...curve.points.map(p => intersect.inkView.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]); - const bounds = InkField.getBounds(points); - const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); - const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; - return Docs.Create.InkDocument( - points, - { title: 'stroke', + // if (this._eraserLock) return false; // leaving this commented out in case the idea is revisited in the future + this.getEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint).forEach(intersect => { + if (!this._deleteList.includes(intersect.inkView)) { + this._deleteList.push(intersect.inkView); + SetActiveInkWidth(StrCast(intersect.inkView.Document.stroke_width?.toString()) || '1'); + SetActiveInkColor(StrCast(intersect.inkView.Document.color?.toString()) || 'black'); + // create a new curve by appending all curves of the current segment together in order to render a single new stroke. + if (Doc.ActiveTool !== InkTool.StrokeEraser) { + // this._eraserLock++; + const segments = this.segmentErase(intersect.inkView, intersect.t); // intersect.t is where the eraser intersected the ink stroke - want to remove the segment that starts at the intersection just before this t value and goes to the one just after it + const newStrokes = segments?.map(segment => { + const points = segment.reduce((data, curve) => [...data, ...curve.points.map(p => intersect.inkView.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]); + const bounds = InkField.getBounds(points); + const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); + const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; + return Docs.Create.InkDocument( + points, + { title: 'stroke', x: B.x - inkWidth / 2, y: B.y - inkWidth / 2, _width: B.width + inkWidth, @@ -675,30 +655,14 @@ export class CollectionFreeFormView extends CollectionSubView this._eraserLock--); } - }); - } - return false; - }; - - /** - * Erases strokes by intersecting them with an invisible "eraser stroke". - * By default this iterates through all intersected ink strokes, determines their segmentation, draws back the non-intersected segments, - * and deletes the original stroke. - */ - @action - onEraserMove = (e: PointerEvent, down: number[], delta: number[]) => { - this.erase(e, delta); - // if (this._eraserLock) return false; // leaving this commented out in case the idea is revisited in the future + // Lower ink opacity to give the user a visual indicator of deletion. + intersect.inkView.layoutDoc.opacity = 0; + intersect.inkView.layoutDoc.dontIntersect = true; + } + }); return false; }; - @action - onEraserClick = (e: PointerEvent, doubleTap?: boolean) => { - e.preventDefault(); - e.stopImmediatePropagation(); - this.erase(e, [0, 0]); - }; - /** * Erases strokes by intersecting them with a circle of variable radius. Essentially creates an InkField for the * eraser circle, then determines its intersections with other ink strokes. Each stroke's DocumentView and its @@ -708,32 +672,32 @@ export class CollectionFreeFormView extends CollectionSubView { - // const currPoint = { X: e.clientX, Y: e.clientY }; - // this._eraserPts.push([currPoint.X, currPoint.Y]); - // this._eraserPts = this._eraserPts.slice(Math.max(0, this._eraserPts.length - 5)); - // const strokeMap: Map = this.getRadiusEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint); - - // strokeMap.forEach((intersects, stroke) => { - // if (!this._deleteList.includes(stroke)) { - // this._deleteList.push(stroke); - // SetActiveInkWidth(StrCast(stroke.Document.stroke_width?.toString()) || '1'); - // SetActiveInkColor(StrCast(stroke.Document.color?.toString()) || 'black'); - // const segments = this.radiusErase(stroke, intersects.sort()); - // segments?.forEach(segment => - // this.forceStrokeGesture( - // e, - // Gestures.Stroke, - // segment.reduce((data, curve) => [...data, ...curve.points.map(p => stroke.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]) - // ) - // ); - // } - // stroke.layoutDoc.opacity = 0; - // stroke.layoutDoc.dontIntersect = true; - // }); - // return false; - // }; + @action + onRadiusEraserMove = (e: PointerEvent, down: number[], delta: number[]) => { + const currPoint = { X: e.clientX, Y: e.clientY }; + this._eraserPts.push([currPoint.X, currPoint.Y]); + this._eraserPts = this._eraserPts.slice(Math.max(0, this._eraserPts.length - 5)); + const strokeMap: Map = this.getRadiusEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint); + + strokeMap.forEach((intersects, stroke) => { + if (!this._deleteList.includes(stroke)) { + this._deleteList.push(stroke); + SetActiveInkWidth(StrCast(stroke.Document.stroke_width?.toString()) || '1'); + SetActiveInkColor(StrCast(stroke.Document.color?.toString()) || 'black'); + const segments = this.radiusErase(stroke, intersects.sort()); + segments?.forEach(segment => + this.forceStrokeGesture( + e, + Gestures.Stroke, + segment.reduce((data, curve) => [...data, ...curve.points.map(p => stroke.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[]) + ) + ); + } + stroke.layoutDoc.opacity = 0; + stroke.layoutDoc.dontIntersect = true; + }); + return false; + }; forceStrokeGesture = (e: PointerEvent, gesture: Gestures, points: InkData, text?: any) => { this.onGesture(e, new GestureUtils.GestureEvent(gesture, points, InkField.getBounds(points), text)); @@ -764,7 +728,7 @@ export class CollectionFreeFormView extends CollectionSubView { - SmartDrawHandler.Instance.displaySmartDrawHandler(e.pageX, e.pageY, this.createDrawing, this.removeDrawing); - }; - - _drawing: Doc[] = []; - @undoBatch - createDrawing = (e: React.PointerEvent, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => { - strokeData.forEach((stroke: [InkData, string, string]) => { - const bounds = InkField.getBounds(stroke[0]); - const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height); - const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale; - const inkDoc = Docs.Create.InkDocument( - stroke[0], - { title: 'stroke', - x: B.x - inkWidth / 2, - y: B.y - inkWidth / 2, - _width: B.width + inkWidth, - _height: B.height + inkWidth, - stroke_showLabel: BoolCast(Doc.UserDoc().activeInkHideTextLabels)}, // prettier-ignore - inkWidth, - stroke[1], - undefined, - stroke[2] === 'none' ? undefined : stroke[2] - ); - this._drawing.push(inkDoc); - this.addDocument(inkDoc); - }); - const collection = this._marqueeViewRef.current?.collection(undefined, true, this._drawing); - if (collection) { - const docData = collection[DocData]; - docData.title = opts.text; - docData.drawingInput = opts.text; - docData.drawingComplexity = opts.complexity; - docData.drawingColored = opts.autoColor; - docData.drawingSize = opts.size; - docData.drawingData = gptRes; - } - this._batch?.end(); - }; - - removeDrawing = (doc?: Doc) => { - this._batch = UndoManager.StartBatch('regenerateDrawing'); - if (doc) { - const docData: Doc = doc[DocData]; - const children = docData.data as unknown as Doc[]; - this._props.removeDocument?.(doc); - this._props.removeDocument?.(children); - } else { - this._props.removeDocument?.(this._drawing); - } - this._drawing = []; - }; - @action zoom = (pointX: number, pointY: number, deltaY: number): void => { if (this.Document.isGroup || this.Document[(this._props.viewField ?? '_') + 'freeform_noZoom']) return; @@ -1921,10 +1831,8 @@ export class CollectionFreeFormView extends CollectionSubView { - const locPt = this.ScreenToLocalBoxXf().transformPoint(e.clientX, e.clientY); - this._eraserX = locPt[0]; - this._eraserY = locPt[1]; - // Doc.ActiveTool === InkTool.RadiusEraser ? this._childPointerEvents = 'none' : this._childPointerEvents = 'all' + this._eraserX = e.clientX; + this._eraserY = e.clientY; // super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY)); }; @@ -2031,14 +1939,6 @@ export class CollectionFreeFormView extends CollectionSubView { - this._showDrawingEditor = !this._showDrawingEditor; - this._showDrawingEditor ? SmartDrawHandler.Instance.displayRegenerate(this._downX, this._downY - 10, this.createDrawing, this.removeDrawing) : SmartDrawHandler.Instance.hideRegenerate(); - }), - icon: 'pen-to-square', - }); this._props.renderDepth && optionItems.push({ description: 'Use Background Color as Default', @@ -2243,8 +2143,8 @@ export class CollectionFreeFormView extends CollectionSubView Transform; @@ -375,8 +374,8 @@ export class MarqueeView extends ObservableReactComponent { SetActiveInkColor(StrCast(value)); selected?.type === DocumentType.INK && setActiveTool(GestureOverlay.Instance.InkShape ?? InkTool.Pen, true, false);}, }], [ 'eraserWidth', { - checkResult: () => ActiveEraserWidth() === 0 ? 1 : ActiveEraserWidth(), + checkResult: () => ActiveEraserWidth(), setInk: (doc: Doc) => { }, - setMode: () => { SetEraserWidth(value);}, + setMode: () => { SetEraserWidth(value.toString());}, }] ]); diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index 6e24b2931..7bca1230f 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -20,27 +20,15 @@ top: 0; left: 0; - .pdfBox-sidebarBtn-container { - display: flex; - flex-direction: row; - position: absolute; - width: 53px; - height: 33px; - right: 5px; - align-items: center; - justify-content: space-between; - z-index: 1; - } - // glr: This should really be the same component as text and PDFs .pdfBox-sidebarBtn { background: $black; height: 25px; width: 25px; - // right: 5px; + right: 5px; color: $white; display: flex; - // position: absolute; + position: absolute; align-items: center; justify-content: center; border-radius: 3px; diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 782df99f6..8db68ddfe 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -1,8 +1,6 @@ /* eslint-disable jsx-a11y/no-static-element-interactions */ /* eslint-disable jsx-a11y/control-has-associated-label */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { IconButton } from 'browndash-components'; -import { black } from 'colors'; import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as Pdfjs from 'pdfjs-dist'; @@ -505,30 +503,17 @@ export class PDFBox extends ViewBoxAnnotatableComponent() { } @computed get sidebarHandle() { return ( -
-
- {/* // onPointerDown={e => this.sidebarBtnDown(e, true)} */} - } onPointerDown={e => this.sidebarBtnDown(e, true)} /> -
-
- } onPointerDown={e => this.sidebarBtnDown(e, true)} /> -
+
this.sidebarBtnDown(e, true)}> +
); } diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index df990b0c0..2f6824466 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -51,7 +51,6 @@ export class AnchorMenu extends AntimodeMenu { public StartDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction; public StartCropDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction; public Highlight: (color: string) => Opt = (/* color: string */) => undefined; - public Tape: (color: string) => Opt = (/* color: string */) => undefined; public GetAnchor: (savedAnnotations: Opt>, addAsAnnotation: boolean) => Opt = emptyFunction; public Delete: () => void = unimplementedFunction; public PinToPres: () => void = unimplementedFunction; @@ -173,12 +172,6 @@ export class AnchorMenu extends AntimodeMenu { AnchorMenu.Instance.fadeOut(true); }; - @action - tapeClicked = () => { - this.Tape(this.highlightColor); - // AnchorMenu.Instance.fadeOut(true); - }; - @computed get highlighter() { return ( @@ -189,13 +182,6 @@ export class AnchorMenu extends AntimodeMenu { colorPicker={this.highlightColor} color={SettingsManager.userColor} /> - } - onClick={this.tapeClicked} - colorPicker={this.highlightColor} - color={SettingsManager.userColor} - /> ); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index fbe3518ec..db47a84e1 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -65,7 +65,6 @@ export class PDFViewer extends ObservableReactComponent { @observable _pageSizes: { width: number; height: number }[] = []; @observable _savedAnnotations = new ObservableMap(); - @observable _savedTapes = new ObservableMap(); @observable _textSelecting = true; @observable _showWaiting = true; @observable Index: number = -1; @@ -582,7 +581,6 @@ export class PDFViewer extends ObservableReactComponent { return
; } savedAnnotations = () => this._savedAnnotations; - savedTapes = () => this._savedTapes; addDocumentWrapper = (doc: Doc | Doc[]) => this._props.addDocument!(doc); render() { TraceMobx(); @@ -616,7 +614,6 @@ export class PDFViewer extends ObservableReactComponent { docView={this._props.pdfBox.DocumentView!} finishMarquee={this.finishMarquee} savedAnnotations={this.savedAnnotations} - savedTapes={this.savedTapes} selectionText={this.selectionText} annotationLayer={this._annotationLayer.current} marqueeContainer={this._mainCont.current} diff --git a/src/client/views/smartdraw/DrawingPalette.scss b/src/client/views/smartdraw/DrawingPalette.scss deleted file mode 100644 index 0f1152b71..000000000 --- a/src/client/views/smartdraw/DrawingPalette.scss +++ /dev/null @@ -1,11 +0,0 @@ -.drawing-palette { - display: grid; - grid-template-columns: auto; - position: absolute; - right: 14px; - width: 170px; - height: 170px; - top: 50px; - border-radius: 5px; - background-color: white; -} diff --git a/src/client/views/smartdraw/DrawingPalette.tsx b/src/client/views/smartdraw/DrawingPalette.tsx deleted file mode 100644 index 87a39bc85..000000000 --- a/src/client/views/smartdraw/DrawingPalette.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { computed, makeObservable, observable } from 'mobx'; -import { observer } from 'mobx-react'; -import * as React from 'react'; -import { returnAll, returnFalse, returnOne, returnZero } from '../../../ClientUtils'; -import { Doc, StrListCast } from '../../../fields/Doc'; -import { emptyFunction } from '../../../Utils'; -import { CollectionViewType } from '../../documents/DocumentTypes'; -import { MarqueeView } from '../collections/collectionFreeForm'; -import { CollectionGridView } from '../collections/collectionGrid'; -import { CollectionStackingView } from '../collections/CollectionStackingView'; -import { DocumentView } from '../nodes/DocumentView'; -import { FieldViewProps } from '../nodes/FieldView'; -import { ObservableReactComponent } from '../ObservableReactComponent'; -import './DrawingPalette.scss'; - -@observer -export class DrawingPalette extends ObservableReactComponent<{}> { - @observable private _savedDrawings: Doc[] = []; - @observable _marqueeViewRef = React.createRef(); - private _stackRef = React.createRef(); - - constructor(props: any) { - super(props); - makeObservable(this); - } - - panelWidth = () => 100; - panelHeight = () => 100; - - getCollection = () => { - return this._marqueeViewRef.current?.collection(undefined, false, this._savedDrawings) || new Doc(); - }; - - @computed get savedDrawingAnnos() { - // const savedAnnos = Doc.MyDrawingAnnos; - return ( -
- {/* */} - {/* */} -
- ); - } - - render() { - return ( -
- {/* {this._savedDrawings.map(doc => { - return ; - })} */} - {/* */} - {} - {/* */} - {this.savedDrawingAnnos} -
- ); - } -} diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx deleted file mode 100644 index d24cc9d50..000000000 --- a/src/client/views/smartdraw/SmartDrawHandler.tsx +++ /dev/null @@ -1,409 +0,0 @@ -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, makeObservable, observable } from 'mobx'; -import { observer } from 'mobx-react'; -import React from 'react'; -import { SettingsManager } from '../../util/SettingsManager'; -import { ObservableReactComponent } from '../ObservableReactComponent'; -import { Button, IconButton } from 'browndash-components'; -import ReactLoading from 'react-loading'; -import { AiOutlineSend } from 'react-icons/ai'; -// import './ImageLabelHandler.scss'; -import { gptAPICall, GPTCallType } from '../../apis/gpt/GPT'; -import { InkData } from '../../../fields/InkField'; -import { SVGToBezier } from '../../util/bezierFit'; -const { parse } = require('svgson'); -import { Slider, Switch } from '@mui/material'; -import { Doc } from '../../../fields/Doc'; -import { DocData } from '../../../fields/DocSymbols'; -import { DocumentView } from '../nodes/DocumentView'; - -export interface DrawingOptions { - text: string; - complexity: number; - size: number; - autoColor: boolean; - x: number; - y: number; -} - -@observer -export class SmartDrawHandler extends ObservableReactComponent<{}> { - static Instance: SmartDrawHandler; - - @observable private _display: boolean = false; - @observable private _pageX: number = 0; - @observable private _pageY: number = 0; - @observable private _yRelativeToTop: boolean = true; - @observable private _isLoading: boolean = false; - @observable private _userInput: string = ''; - @observable private _showOptions: boolean = false; - @observable private _showEditBox: boolean = false; - @observable private _showRegenerate: boolean = false; - @observable private _complexity: number = 5; - @observable private _size: number = 200; - @observable private _autoColor: boolean = true; - @observable private _regenInput: string = ''; - private _addFunc: (e: React.PointerEvent, strokeList: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void = () => {}; - private _deleteFunc: (doc?: Doc) => void = () => {}; - private _lastInput: DrawingOptions = { text: '', complexity: 5, size: 300, autoColor: true, x: 0, y: 0 }; - private _lastResponse: string = ''; - private _selectedDoc: Doc | undefined = undefined; - - constructor(props: any) { - super(props); - makeObservable(this); - SmartDrawHandler.Instance = this; - } - - @action - setUserInput = (input: string) => { - this._userInput = input; - }; - - @action - setRegenInput = (input: string) => { - this._regenInput = input; - }; - - @action - setShowOptions = () => { - this._showOptions = !this._showOptions; - }; - - @action - setComplexity = (val: number) => { - this._complexity = val; - }; - - @action - setSize = (val: number) => { - this._size = val; - }; - - @action - setAutoColor = () => { - this._autoColor = !this._autoColor; - }; - - @action - displaySmartDrawHandler = (x: number, y: number, addFunc: (e: React.PointerEvent, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void, deleteFunc: (doc?: Doc) => void) => { - this._pageX = x; - this._pageY = y; - this._display = true; - this._addFunc = addFunc; - this._deleteFunc = deleteFunc; - }; - - @action - displayRegenerate = (x: number, y: number, addFunc: (e: React.PointerEvent, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void, deleteFunc: (doc?: Doc) => void) => { - this._selectedDoc = DocumentView.SelectedDocs().lastElement(); - const docData = this._selectedDoc[DocData]; - this._addFunc = addFunc; - this._deleteFunc = deleteFunc; - this._pageX = x; - this._pageY = y; - this._showRegenerate = true; - this._lastResponse = docData.drawingData as string; - this._lastInput = { text: docData.drawingInput as string, complexity: docData.drawingComplexity as number, size: docData.drawingSize as number, autoColor: docData.drawingColored as boolean, x: this._pageX, y: this._pageY }; - }; - - @action - hideSmartDrawHandler = () => { - this._showRegenerate = false; - this._display = false; - this._isLoading = false; - this._showOptions = false; - this._userInput = ''; - this._complexity = 5; - this._size = 300; - this._autoColor = true; - // this._regenInput = '' - }; - - @action - hideRegenerate = () => { - this._showRegenerate = false; - this._isLoading = false; - this._regenInput = ''; - }; - - _errorOccurredOnce = false; - @action - drawWithGPT = async (e: React.PointerEvent, input: string) => { - if (input === '') return; - this._lastInput = { text: input, complexity: this._complexity, size: this._size, autoColor: this._autoColor, x: e.clientX, y: e.clientY }; - this._isLoading = true; - this._showOptions = false; - try { - const res = await gptAPICall(`"${input}", "${this._complexity}", "${this._size}"`, GPTCallType.DRAW, undefined, true); - if (!res) { - console.error('GPT call failed'); - return; - } - console.log(res); - await this.parseResponse(e, res, { X: e.clientX, Y: e.clientY }, false); - this.hideSmartDrawHandler(); - this._showRegenerate = true; - this._errorOccurredOnce = false; - } catch (err) { - if (this._errorOccurredOnce) { - console.error('GPT call failed', err); - this._errorOccurredOnce = false; - } else { - this._errorOccurredOnce = true; - this.drawWithGPT(e, input); - } - } - this._isLoading = false; - }; - - @action - edit = () => { - this._showEditBox = !this._showEditBox; - }; - - @action - regenerate = async (e: React.PointerEvent) => { - this._isLoading = true; - try { - let res; - if (this._regenInput !== '') { - const prompt: string = `This is your previously generated svg code: ${this._lastResponse} for the user input "${this._lastInput.text}". Please regenerate it with the provided specifications.`; - res = await gptAPICall(`"${this._regenInput}"`, GPTCallType.DRAW, prompt, true); - this._lastInput.text = `${this._lastInput.text} + ${this._regenInput}`; - } else { - res = await gptAPICall(`"${this._lastInput.text}", "${this._lastInput.complexity}", "${this._lastInput.size}"`, GPTCallType.DRAW, undefined, true); - } - if (!res) { - console.error('GPT call failed'); - return; - } - console.log(res); - this.parseResponse(e, res, { X: this._lastInput.x, Y: this._lastInput.y }, true); - } catch (err) { - console.error('GPT call failed', err); - } - this._isLoading = false; - this._regenInput = ''; - this._showEditBox = false; - }; - - @action - parseResponse = async (e: React.PointerEvent, res: string, startPoint: { X: number; Y: number }, regenerate: boolean) => { - const svg = res.match(/]*>([\s\S]*?)<\/svg>/g); - console.log('start point is', startPoint); - if (svg) { - this._lastResponse = svg[0]; - const svgObject = await parse(svg[0]); - const svgStrokes: any = svgObject.children; - const strokeData: [InkData, string, string][] = []; - console.log('autocolor is', this._autoColor); - svgStrokes.forEach((child: any) => { - const convertedBezier: InkData = SVGToBezier(child.name, child.attributes); - strokeData.push([ - convertedBezier.map(point => { - return { X: point.X + startPoint.X - this._size / 1.5, Y: point.Y + startPoint.Y - this._size / 2 }; - }), - (regenerate ? this._lastInput.autoColor : this._autoColor) ? child.attributes.stroke : undefined, - (regenerate ? this._lastInput.autoColor : this._autoColor) ? child.attributes.fill : undefined, - ]); - }); - if (regenerate) { - this._deleteFunc(this._selectedDoc); - this._addFunc(e, strokeData, this._lastInput, svg[0], this._selectedDoc); - } else { - this._addFunc(e, strokeData, this._lastInput, svg[0]); - } - } - }; - - render() { - if (this._display) { - return ( -
-
- { - this.hideSmartDrawHandler(); - this.hideRegenerate(); - }} - icon={} - color={SettingsManager.userColor} - style={{ width: '19px' }} - /> - { - this.setUserInput(e.target.value); - }} - placeholder="Enter item to draw" - /> -
- {this._showOptions && ( - <> -
-
- Auto color - -
-
- Complexity - { - this.setComplexity(val as number); - }} - valueLabelDisplay="auto" - /> -
-
- Size (in pixels) - { - this.setSize(val as number); - }} - valueLabelDisplay="auto" - /> -
-
- - )} -
- ); - } else if (this._showRegenerate) { - return ( -
-
- : } - color={SettingsManager.userColor} - onClick={e => { - this.regenerate(e as React.PointerEvent); - }} - /> - } color={SettingsManager.userColor} onClick={this.edit} /> - {this._showEditBox && ( -
- { - this.setRegenInput(e.target.value); - }} - placeholder="Edit instructions" - /> -
- )} -
-
- ); - } else { - return <>; - } - } -} diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index bc1abd26e..72ec16b42 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -174,53 +174,6 @@ export function updateCachedAcls(doc: Doc) { return undefined; } -export function ActiveInkPen(): Doc { return Doc.UserDoc(); } // prettier-ignore -export function ActiveInkColor(): string { return StrCast(ActiveInkPen()?.activeInkColor, 'black'); } // prettier-ignore -export function ActiveFillColor(): string { return StrCast(ActiveInkPen()?.activeFillColor, ''); } // prettier-ignore -export function ActiveIsInkMask(): boolean { return BoolCast(ActiveInkPen()?.activeIsInkMask, false); } // prettier-ignore -export function ActiveInkHideTextLabels(): boolean { return BoolCast(ActiveInkPen().activeInkHideTextLabels, false); } // prettier-ignore -export function ActiveArrowStart(): string { return StrCast(ActiveInkPen()?.activeArrowStart, ''); } // prettier-ignore -export function ActiveArrowEnd(): string { return StrCast(ActiveInkPen()?.activeArrowEnd, ''); } // prettier-ignore -export function ActiveArrowScale(): number { return NumCast(ActiveInkPen()?.activeArrowScale, 1); } // prettier-ignore -export function ActiveDash(): string { return StrCast(ActiveInkPen()?.activeDash, '0'); } // prettier-ignore -export function ActiveInkWidth(): number { return Number(ActiveInkPen()?.activeInkWidth); } // prettier-ignore -export function ActiveInkBezierApprox(): string { return StrCast(ActiveInkPen()?.activeInkBezier); } // prettier-ignore -export function ActiveEraserWidth(): number { return NumCast(ActiveInkPen()?.eraserWidth); } // prettier-ignore - -export function SetActiveInkWidth(width: string): void { - !isNaN(parseInt(width)) && ActiveInkPen() && (ActiveInkPen().activeInkWidth = width); -} -export function SetActiveBezierApprox(bezier: string): void { - ActiveInkPen() && (ActiveInkPen().activeInkBezier = isNaN(parseInt(bezier)) ? '' : bezier); -} -export function SetActiveInkColor(value: string) { - ActiveInkPen() && (ActiveInkPen().activeInkColor = value); -} -export function SetActiveIsInkMask(value: boolean) { - ActiveInkPen() && (ActiveInkPen().activeIsInkMask = value); -} -export function SetActiveInkHideTextLabels(value: boolean) { - ActiveInkPen() && (ActiveInkPen().activeInkHideTextLabels = value); -} -export function SetActiveFillColor(value: string) { - ActiveInkPen() && (ActiveInkPen().activeFillColor = value); -} -export function SetActiveArrowStart(value: string) { - ActiveInkPen() && (ActiveInkPen().activeArrowStart = value); -} -export function SetActiveArrowEnd(value: string) { - ActiveInkPen() && (ActiveInkPen().activeArrowEnd = value); -} -export function SetActiveArrowScale(value: number) { - ActiveInkPen() && (ActiveInkPen().activeArrowScale = value); -} -export function SetActiveDash(dash: string): void { - !isNaN(parseInt(dash)) && ActiveInkPen() && (ActiveInkPen().activeDash = dash); -} -export function SetEraserWidth(width: number): void { - !isNaN(width) && ActiveInkPen() && (ActiveInkPen().eraserWidth = width); -} - @scriptingGlobal @Deserializable('Doc', updateCachedAcls, ['id']) export class Doc extends RefField { @@ -276,7 +229,6 @@ export class Doc extends RefField { public static get MyPublishedDocs() { return DocListCast(Doc.ActiveDashboard?.myPublishedDocs).concat(DocListCast(DocCast(Doc.UserDoc().myPublishedDocs)?.data)); } // prettier-ignore public static get MyDashboards() { return DocCast(Doc.UserDoc().myDashboards); } // prettier-ignore public static get MyTemplates() { return DocCast(Doc.UserDoc().myTemplates); } // prettier-ignore - public static get MyDrawingAnnos() { return DocCast(Doc.UserDoc().myDrawingAnnos); } // prettier-ignore public static get MyImports() { return DocCast(Doc.UserDoc().myImports); } // prettier-ignore public static get MyFilesystem() { return DocCast(Doc.UserDoc().myFilesystem); } // prettier-ignore public static get MyTools() { return DocCast(Doc.UserDoc().myTools); } // prettier-ignore diff --git a/src/fields/InkField.ts b/src/fields/InkField.ts index 123d32301..32abf0076 100644 --- a/src/fields/InkField.ts +++ b/src/fields/InkField.ts @@ -17,7 +17,6 @@ export enum InkTool { Stamp = 'stamp', Write = 'write', PresentationPin = 'presentationpin', - SmartDraw = 'smartdraw', } export type Segment = Array; -- cgit v1.2.3-70-g09d2 From e7a69c89363b3bdeae713f509d4283cf69ac7484 Mon Sep 17 00:00:00 2001 From: geireann Date: Thu, 11 Jul 2024 14:25:56 -0400 Subject: fixed transforms for treeView. cleanedup/commented some code. --- src/ClientUtils.ts | 1 + .../views/collections/CollectionTreeView.tsx | 4 --- src/client/views/collections/TreeView.tsx | 10 +++--- src/client/views/nodes/DocumentView.tsx | 41 ++++++++-------------- 4 files changed, 20 insertions(+), 36 deletions(-) diff --git a/src/ClientUtils.ts b/src/ClientUtils.ts index d03ae1486..0ab8ca55b 100644 --- a/src/ClientUtils.ts +++ b/src/ClientUtils.ts @@ -86,6 +86,7 @@ export function returnEmptyDoclist() { return [] as any[]; } +// eslint-disable-next-line @typescript-eslint/no-namespace export namespace ClientUtils { export const CLICK_TIME = 300; export const DRAG_THRESHOLD = 4; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index c39df2c76..285598600 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -52,7 +52,6 @@ export type collectionTreeViewProps = { export class CollectionTreeView extends CollectionSubView>() { public static AddTreeFunc = 'addTreeFolder(this.embedContainer)'; private _treedropDisposer?: DragManager.DragDropDisposer; - private _mainEle?: HTMLDivElement; private _titleRef?: HTMLDivElement | HTMLInputElement | null; private _disposers: { [name: string]: IReactionDisposer } = {}; private _isDisposing = false; // notes that instance is in process of being disposed @@ -83,8 +82,6 @@ export class CollectionTreeView extends CollectionSubView this._mainEle; - // these should stay in synch with counterparts in DocComponent.ts ViewBoxAnnotatableComponent @observable _isAnyChildContentActive = false; whenChildContentsActiveChanged = action((isActive: boolean) => { @@ -134,7 +131,6 @@ export class CollectionTreeView extends CollectionSubView { this._treedropDisposer?.(); - this._mainEle = ele; if (ele) this._treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.Document, this.onInternalPreDrop.bind(this)); }; diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index b82421e6b..f69aea2a7 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -469,14 +469,12 @@ export class TreeView extends ObservableReactComponent { return false; } - refTransform = (ref: HTMLDivElement | undefined | null) => { + refTransform = (ref: HTMLElement | undefined | null) => { if (!ref) return this.ScreenToLocalTransform(); - const { translateX, translateY } = ClientUtils.GetScreenTransform(ref); - const outerXf = ClientUtils.GetScreenTransform(this.treeView.MainEle()); - const offset = this.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); - return this.ScreenToLocalTransform().translate(offset[0], offset[1]); + const { translateX, translateY, scale } = ClientUtils.GetScreenTransform(ref); + return new Transform(-translateX, -translateY, 1).scale(1/scale); }; - docTransform = () => this.refTransform(this._dref?.ContentRef?.current); + docTransform = () => this.refTransform(this._dref?.ContentDiv); getTransform = () => this.refTransform(this._tref.current); embeddedPanelWidth = () => this._props.panelWidth() / (this.treeView._props.NativeDimScaling?.() || 1); embeddedPanelHeight = () => { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 3cf40c087..cd003f1a6 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -969,8 +969,8 @@ export class DocumentViewInternal extends DocComponent, root: Doc) { - let dir = (presEffectDoc?.presentation_effectDirection ?? presEffectDoc?.followLinkAnimDirection) as PresEffectDirection; - const transitionTime = presEffectDoc?.presentation_transition ? NumCast(presEffectDoc?.presentation_transition) : 500; + const dir = ((presEffectDoc?.presentation_effectDirection ?? presEffectDoc?.followLinkAnimDirection) || PresEffectDirection.Center) as PresEffectDirection; + const duration = Cast(presEffectDoc?.presentation_transition, 'number', Cast(presEffectDoc?.followLinkTransitionTime, 'number', null)); const effectProps = { left: dir === PresEffectDirection.Left, right: dir === PresEffectDirection.Right, @@ -978,26 +978,14 @@ export class DocumentViewInternal extends DocComponent{renderDoc} case PresEffect.Flip: return {renderDoc} @@ -1079,15 +1067,16 @@ export class DocumentView extends DocComponent() { finished?: (changed: boolean) => void // func called after focusing on target with flag indicating whether anything needed to be done. ) => Promise; public static linkCommonAncestor: (link: Doc) => DocumentView | undefined; - // pin func + /** + * Pins a Doc to the current presentation trail. (see TabDocView for implementation) + */ public static PinDoc: (docIn: Doc | Doc[], pinProps: PinProps) => void; - // gesture - public static DownDocView: DocumentView | undefined; // the first DocView that receives a pointerdown event. used by GestureOverlay to determine the doc a gesture should apply to. - // media playing - @observable public static CurrentlyPlaying: DocumentView[] = []; + /** + * The DocumentView below the cursor at the start of a gesture (that receives the pointerDown event). Used by GestureOverlay to determine the doc a gesture should apply to. + */ + public static DownDocView: DocumentView | undefined; public get displayName() { return 'DocumentView(' + (this.Document?.title??"") + ')'; } // prettier-ignore - public ContentRef = React.createRef(); private _htmlOverlayEffect: Opt; private _disposers: { [name: string]: IReactionDisposer } = {}; private _viewTimer: NodeJS.Timeout | undefined; @@ -1118,6 +1107,7 @@ export class DocumentView extends DocComponent() { @observable private _htmlOverlayText: Opt = undefined; @observable private _isHovering = false; @observable private _selected = false; + @observable public static CurrentlyPlaying: DocumentView[] = []; // audio or video media views that are currently playing @computed private get shouldNotScale() { return (this.layout_fitWidth && !this.nativeWidth) || this.ComponentView?.isUnstyledView?.(); @@ -1464,7 +1454,6 @@ export class DocumentView extends DocComponent() { {!this.Document || !this._props.PanelWidth() ? null : (
Date: Fri, 12 Jul 2024 09:34:51 -0400 Subject: Fixed nested collections in templates. cleaned up some cod.e --- .../views/collections/CollectionCarousel3DView.tsx | 1 + .../collectionFreeForm/CollectionFreeFormView.tsx | 28 ++++++++++++---------- .../collectionSchema/CollectionSchemaView.tsx | 1 + .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- .../views/nodes/DataVizBox/components/TableBox.tsx | 1 + src/client/views/nodes/DocumentView.tsx | 2 +- 6 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index 27c85533f..38f681e87 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -17,6 +17,7 @@ import { FocusViewOptions } from '../nodes/FocusViewOptions'; import './CollectionCarousel3DView.scss'; import { CollectionSubView } from './CollectionSubView'; +// eslint-disable-next-line @typescript-eslint/no-var-requires const { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } = require('../global/globalCssVariables.module.scss'); @observer diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index d611db1f8..5b7f09be3 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -88,8 +88,10 @@ export class CollectionFreeFormView extends CollectionSubView(); private _batch: UndoManager.Batch | undefined = undefined; - private _brushtimer: any; - private _brushtimer1: any; private _keyTimer: NodeJS.Timeout | undefined; // timer for turning off transition flag when key frame change has completed. Need to clear this if you do a second navigation before first finishes, or else first timer can go off during second naviation. private _presEaseFunc: string = 'ease'; @@ -130,7 +130,7 @@ export class CollectionFreeFormView extends CollectionSubView { - this.onGesture(e, new GestureUtils.GestureEvent(gesture, points, InkField.getBounds(points), text)); + forceStrokeGesture = (e: PointerEvent, gesture: Gestures, points: InkData) => { + this.onGesture(e, new GestureUtils.GestureEvent(gesture, points, InkField.getBounds(points))); }; onPointerMove = (e: PointerEvent) => { @@ -1654,7 +1654,7 @@ export class CollectionFreeFormView extends CollectionSubView (this.Document.isTemplateDoc ? false : !this._renderCutoffData.get(doc[Id] + ''))); + renderCutoffProvider = computedFn((doc: Doc) => (this.Document.isTemplateDoc || this.Document.isTemplateForField ? false : !this._renderCutoffData.get(doc[Id] + ''))); doEngineLayout( poolData: Map, @@ -1688,7 +1688,7 @@ export class CollectionFreeFormView extends CollectionSubView elements.push({ ele: this.getChildDocView(entry[1]), - bounds: (entry[1].opacity === 0 ? { ...entry[1], width: 0, height: 0 } : { ...entry[1] }) as any, + 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, }) ); @@ -1810,10 +1810,11 @@ export class CollectionFreeFormView extends CollectionSubView disposer?.()); } - updateIcon = () => - UpdateIcon( + updateIcon = () => { + const contentDiv = this.DocumentView?.().ContentDiv; + contentDiv && UpdateIcon( this.layoutDoc[Id] + '-icon' + new Date().getTime(), - this.DocumentView?.().ContentDiv!, + contentDiv, NumCast(this.layoutDoc._width), NumCast(this.layoutDoc._height), this._props.PanelWidth(), @@ -1828,6 +1829,7 @@ export class CollectionFreeFormView extends CollectionSubView { @@ -2008,7 +2010,7 @@ export class CollectionFreeFormView extends CollectionSubView { if (!DocumentView.LightboxDoc() || DocumentView.LightboxContains(this.DocumentView?.())) { const layoutUnrendered = this.childDocs.filter(doc => !this._renderCutoffData.get(doc[Id])); - const loadIncrement = this.Document.isTemplateDoc ? Number.MAX_VALUE : 5; + const loadIncrement = this.Document.isTemplateDoc || this.Document.isTemplateForField ? Number.MAX_VALUE : 5; for (let i = 0; i < Math.min(layoutUnrendered.length, loadIncrement); i++) { this._renderCutoffData.set(layoutUnrendered[i][Id] + '', true); } diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 7c2cfd15f..6bea53355 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -32,6 +32,7 @@ import './CollectionSchemaView.scss'; import { SchemaColumnHeader } from './SchemaColumnHeader'; import { SchemaRowBox } from './SchemaRowBox'; +// eslint-disable-next-line @typescript-eslint/no-var-requires const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore export const FInfotoColType: { [key: string]: ColumnType } = { diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 29a499035..ee67dd305 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -320,6 +320,6 @@ export class CollectionFreeFormDocumentView extends DocComponent Date: Fri, 12 Jul 2024 09:47:08 -0400 Subject: some code type cleanup --- src/ClientUtils.ts | 17 ++++++++--------- src/client/util/SettingsManager.tsx | 4 ++-- src/client/views/collections/CollectionDockingView.tsx | 2 +- src/client/views/nodes/WebBox.tsx | 1 + .../views/nodes/formattedText/FormattedTextBox.tsx | 12 ++++++------ src/client/views/pdf/PDFViewer.tsx | 2 +- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/ClientUtils.ts b/src/ClientUtils.ts index 0ab8ca55b..630d7edbc 100644 --- a/src/ClientUtils.ts +++ b/src/ClientUtils.ts @@ -450,30 +450,29 @@ export function smoothScrollHorizontal(duration: number, element: HTMLElement | animateScroll(); } -export function addStyleSheet(styleType: string = 'text/css') { +export function addStyleSheet() { const style = document.createElement('style'); - style.type = styleType; const sheets = document.head.appendChild(style); - return (sheets as any).sheet; + return sheets.sheet; } -export function addStyleSheetRule(sheet: any, selector: any, css: any, selectorPrefix = '.') { +export function addStyleSheetRule(sheet: CSSStyleSheet | null, selector: string, css: string | {[key:string]: string}, selectorPrefix = '.') { const propText = typeof css === 'string' ? css : Object.keys(css) .map(p => p + ':' + (p === 'content' ? "'" + css[p] + "'" : css[p])) .join(';'); - return sheet.insertRule(selectorPrefix + selector + '{' + propText + '}', sheet.cssRules.length); + return sheet?.insertRule(selectorPrefix + selector + '{' + propText + '}', sheet.cssRules.length); } -export function removeStyleSheetRule(sheet: any, rule: number) { - if (sheet.rules.length) { +export function removeStyleSheetRule(sheet: CSSStyleSheet|null, rule: number) { + if (sheet?.rules.length) { sheet.removeRule(rule); return true; } return false; } -export function clearStyleSheetRules(sheet: any) { - if (sheet.rules.length) { +export function clearStyleSheetRules(sheet: CSSStyleSheet|null) { + if (sheet?.rules.length) { numberRange(sheet.rules.length).map(() => sheet.removeRule(0)); return true; } diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index d3c10f9f4..278931cdd 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -29,7 +29,7 @@ export enum ColorScheme { } @observer -export class SettingsManager extends React.Component<{}> { +export class SettingsManager extends React.Component { // eslint-disable-next-line no-use-before-define public static Instance: SettingsManager; static _settingsStyle = addStyleSheet(); @@ -123,7 +123,7 @@ export class SettingsManager extends React.Component<{}> { 'change color scheme' ); - constructor(props: {}) { + constructor(props: object) { super(props); makeObservable(this); SettingsManager.Instance = this; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 73179a266..2a36e96bf 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -58,7 +58,7 @@ export class CollectionDockingView extends CollectionSubView() { return this._goldenLayout._maximisedItem !== null; } private _goldenLayout: any = null; - static _highlightStyleSheet: any = addStyleSheet(); + static _highlightStyleSheet = addStyleSheet(); constructor(props: any) { super(props); diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 8835ea5e7..da947face 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -45,6 +45,7 @@ import { LinkInfo } from './LinkDocPreview'; import { OpenWhere } from './OpenWhere'; import './WebBox.scss'; +// eslint-disable-next-line @typescript-eslint/no-var-requires const { CreateImage } = require('./WebBoxRenderer'); @observer diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 9f2a9b8e1..5b435e44a 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -87,9 +87,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent(['Audio Tags', 'Text from Others', 'Todo Items', 'Important Items', 'Disagree Items', 'Ignore Items']); - static _highlightStyleSheet: any = addStyleSheet(); - static _bulletStyleSheet: any = addStyleSheet(); - static _userStyleSheet: any = addStyleSheet(); + static _highlightStyleSheet = addStyleSheet(); + static _bulletStyleSheet = addStyleSheet(); + static _userStyleSheet = addStyleSheet(); static _hadSelection: boolean = false; private _selectionHTML: string | undefined; private _sidebarRef = React.createRef(); @@ -384,7 +384,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent ) : ( -
setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => DocumentView.SelectView(this.DocumentView?.()!, false), true)}> +
setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => DocumentView.SelectView(this.DocumentView?.(), false), true)}> { - static _annotationStyle: any = addStyleSheet(); + static _annotationStyle = addStyleSheet(); constructor(props: IViewerProps) { super(props); -- cgit v1.2.3-70-g09d2