From b05c44385cc81889ee94a4bbb034237142438bdc Mon Sep 17 00:00:00 2001 From: eleanor-park Date: Wed, 21 Feb 2024 17:44:25 -0500 Subject: branch --- src/.DS_Store | Bin 10244 -> 10244 bytes 1 file changed, 0 insertions(+), 0 deletions(-) (limited to 'src') diff --git a/src/.DS_Store b/src/.DS_Store index c363efb13..9b5118d8a 100644 Binary files a/src/.DS_Store and b/src/.DS_Store differ -- cgit v1.2.3-70-g09d2 From 7f4f5d5d4779a3ff8efd5a64e2cef9f6758e29ae Mon Sep 17 00:00:00 2001 From: "A.J. Shulman" Date: Wed, 21 Feb 2024 17:45:49 -0500 Subject: changed logo for Notes and PPT Slide in tool menu --- src/client/util/CurrentUserUtils.ts | 4 ++-- src/client/views/MainView.tsx | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 714e33d25..b0890b674 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -273,7 +273,7 @@ export class CurrentUserUtils { { toolTip: "Tap or drag to create a flashcard", title: "Flashcard", icon: "id-card", dragFactory: doc.emptyFlashcard as Doc, clickFactory: DocCast(doc.emptyFlashcard)}, { toolTip: "Tap or drag to create an equation", title: "Math", icon: "calculator", dragFactory: doc.emptyEquation as Doc, clickFactory: DocCast(doc.emptyEquation)}, { toolTip: "Tap or drag to create a physics simulation",title: "Simulation", icon: "rocket",dragFactory: doc.emptySimulation as Doc, clickFactory: DocCast(doc.emptySimulation), funcs: { hidden: "IsNoviceMode()"}}, - { toolTip: "Tap or drag to create a note board", title: "Notes", icon: "folder", dragFactory: doc.emptyNoteboard as Doc, clickFactory: DocCast(doc.emptyNoteboard)}, + { toolTip: "Tap or drag to create a note board", title: "Notes", icon: "book", dragFactory: doc.emptyNoteboard as Doc, clickFactory: DocCast(doc.emptyNoteboard)}, { toolTip: "Tap or drag to create a collection", title: "Col", icon: "folder", dragFactory: doc.emptyCollection as Doc, clickFactory: DocCast(doc.emptyTab)}, { toolTip: "Tap or drag to create a webpage", title: "Web", icon: "globe-asia", dragFactory: doc.emptyWebpage as Doc, clickFactory: DocCast(doc.emptyWebpage)}, { toolTip: "Tap or drag to create a comparison box", title: "Compare", icon: "columns", dragFactory: doc.emptyComparison as Doc, clickFactory: DocCast(doc.emptyComparison)}, @@ -284,7 +284,7 @@ export class CurrentUserUtils { { toolTip: "Tap or drag to create a button", title: "Button", icon: "bolt", dragFactory: doc.emptyButton as Doc, clickFactory: DocCast(doc.emptyButton)}, { toolTip: "Tap or drag to create a scripting box", title: "Script", icon: "terminal", dragFactory: doc.emptyScript as Doc, clickFactory: DocCast(doc.emptyScript), funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a data viz node", title: "DataViz", icon: "chart-bar", dragFactory: doc.emptyDataViz as Doc, clickFactory: DocCast(doc.emptyDataViz)}, - { toolTip: "Tap or drag to create a bullet slide", title: "PPT Slide", icon: "file", dragFactory: doc.emptySlide as Doc, clickFactory: DocCast(doc.emptySlide), openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}}, + { toolTip: "Tap or drag to create a bullet slide", title: "PPT Slide", icon: "person-chalkboard", dragFactory: doc.emptySlide as Doc, clickFactory: DocCast(doc.emptySlide), openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a view slide", title: "View Slide", icon: "address-card", dragFactory: doc.emptyViewSlide as Doc,clickFactory: DocCast(doc.emptyViewSlide),openFactoryLocation: OpenWhere.overlay,funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a data note", title: "DataNote", icon: "window-maximize",dragFactory: doc.emptyHeader as Doc,clickFactory: DocCast(doc.emptyHeader), openFactoryAsDelegate: true, funcs: { hidden: "IsNoviceMode()"} }, { toolTip: "Toggle a Calculator REPL", title: "replviewer", icon: "calculator", clickFactory: '' as any, openFactoryLocation: OpenWhere.overlay}, // hack: clickFactory is not a Doc but will get interpreted as a custom UI by the openDoc() onClick script diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index b6cb845a6..fe0e1d1ab 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -288,6 +288,7 @@ export class MainView extends ObservableReactComponent<{}> { fa.faFolderOpen, fa.faFolderPlus, fa.faFolderClosed, + fa.faBook, fa.faMapPin, fa.faMapMarker, fa.faFingerprint, @@ -488,6 +489,7 @@ export class MainView extends ObservableReactComponent<{}> { fa.faUpload, fa.faBorderAll, fa.faBraille, + fa.faPersonChalkboard, fa.faChalkboard, fa.faPencilAlt, fa.faEyeSlash, -- cgit v1.2.3-70-g09d2 From 3735fd5e8c0f5315d73a28ef59dcff4bc6158c88 Mon Sep 17 00:00:00 2001 From: Zachary Zhang Date: Wed, 21 Feb 2024 17:45:56 -0500 Subject: replace button icon with circle instead of bold --- src/.DS_Store | Bin 10244 -> 10244 bytes src/client/util/CurrentUserUtils.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/.DS_Store b/src/.DS_Store index c363efb13..bb607fbc3 100644 Binary files a/src/.DS_Store and b/src/.DS_Store differ diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 714e33d25..d61a40ffa 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -281,7 +281,7 @@ export class CurrentUserUtils { { toolTip: "Tap or drag to create a map", title: "Map", icon: "map-marker-alt", dragFactory: doc.emptyMap as Doc, clickFactory: DocCast(doc.emptyMap)}, { toolTip: "Tap or drag to create a screen grabber", title: "Grab", icon: "photo-video", dragFactory: doc.emptyScreengrab as Doc, clickFactory: DocCast(doc.emptyScreengrab), openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a WebCam recorder", title: "WebCam", icon: "photo-video", dragFactory: doc.emptyWebCam as Doc, clickFactory: DocCast(doc.emptyWebCam), openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}}, - { toolTip: "Tap or drag to create a button", title: "Button", icon: "bolt", dragFactory: doc.emptyButton as Doc, clickFactory: DocCast(doc.emptyButton)}, + { toolTip: "Tap or drag to create a button", title: "Button", icon: "circle", dragFactory: doc.emptyButton as Doc, clickFactory: DocCast(doc.emptyButton)}, { toolTip: "Tap or drag to create a scripting box", title: "Script", icon: "terminal", dragFactory: doc.emptyScript as Doc, clickFactory: DocCast(doc.emptyScript), funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a data viz node", title: "DataViz", icon: "chart-bar", dragFactory: doc.emptyDataViz as Doc, clickFactory: DocCast(doc.emptyDataViz)}, { toolTip: "Tap or drag to create a bullet slide", title: "PPT Slide", icon: "file", dragFactory: doc.emptySlide as Doc, clickFactory: DocCast(doc.emptySlide), openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}}, -- cgit v1.2.3-70-g09d2 From 2279f029ce19c9f7f886a6966ea5f23be9468890 Mon Sep 17 00:00:00 2001 From: eleanor-park Date: Wed, 21 Feb 2024 20:00:11 -0500 Subject: presentation trail tab icon changed --- src/client/views/MainView.tsx | 1 + src/fields/Doc.ts | 2 +- src/mobile/MobileInterface.tsx | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index b6cb845a6..496cb0bdd 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -452,6 +452,7 @@ export class MainView extends ObservableReactComponent<{}> { fa.faAngleDown, fa.faPlayCircle, fa.faClock, + fa.faRoute, fa.faRocket, fa.faExchangeAlt, fa.faHashtag, diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 56d50846a..17cc5ce97 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1432,7 +1432,7 @@ export namespace Doc { case DocumentType.WEBCAM: return 'video'; case DocumentType.AUDIO: return 'microphone'; case DocumentType.BUTTON: return 'bolt'; - case DocumentType.PRES: return 'tv'; + case DocumentType.PRES: return 'route'; case DocumentType.SCRIPTING: return 'terminal'; case DocumentType.IMPORT: return 'cloud-upload-alt'; case DocumentType.VID: return 'video'; diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index c31e73b42..dc4af8303 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -92,6 +92,7 @@ import { faTrash, faTrashAlt, faTree, + faRoute, faTv, faUndoAlt, faVideo, -- cgit v1.2.3-70-g09d2 From 788640ddf95f40194478660c229aea4b7b5679c9 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 22 Feb 2024 14:45:47 -0500 Subject: dont update server cache when tabs change. --- src/client/views/collections/CollectionDockingView.tsx | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 31ca86f0f..68de62d93 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -421,7 +421,6 @@ export class CollectionDockingView extends CollectionSubView() { if (map?.DashDoc && DocumentManager.Instance.getFirstDocumentView(map.DashDoc)) { SelectionManager.SelectView(DocumentManager.Instance.getFirstDocumentView(map.DashDoc), false); } - if (!className.includes('lm_close')) DocServer.UPDATE_SERVER_CACHE(); } } } -- cgit v1.2.3-70-g09d2 From b33ff1abdeab12d977c86f18c567ba3e84a49297 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 22 Feb 2024 16:34:32 -0500 Subject: replaced freeform document view wrapper with more direct caching of props. --- package-lock.json | 3625 ++++++++++---------- .../collectionFreeForm/CollectionFreeFormView.tsx | 4 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 175 +- 3 files changed, 1835 insertions(+), 1969 deletions(-) (limited to 'src') diff --git a/package-lock.json b/package-lock.json index 1f1c994c3..cf8e8ce29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -304,66 +304,66 @@ } }, "node_modules/@adobe/react-spectrum": { - "version": "3.34.0", - "resolved": "https://registry.npmjs.org/@adobe/react-spectrum/-/react-spectrum-3.34.0.tgz", - "integrity": "sha512-FI+kUI/SefYXCBdmKTwASijMuyaXONgU6uuBt0rddaasiHWytTVzxWHMRAZlxixQHks9nfvD11+DXvI58rNZNw==", - "dependencies": { - "@internationalized/string": "^3.2.0", - "@react-aria/i18n": "^3.10.1", - "@react-aria/ssr": "^3.9.1", - "@react-aria/utils": "^3.23.1", - "@react-aria/visually-hidden": "^3.8.9", - "@react-spectrum/actionbar": "^3.4.2", - "@react-spectrum/actiongroup": "^3.10.2", - "@react-spectrum/avatar": "^3.0.9", - "@react-spectrum/badge": "^3.1.10", - "@react-spectrum/breadcrumbs": "^3.9.4", - "@react-spectrum/button": "^3.16.1", - "@react-spectrum/buttongroup": "^3.6.10", - "@react-spectrum/calendar": "^3.4.6", - "@react-spectrum/checkbox": "^3.9.3", - "@react-spectrum/combobox": "^3.12.2", - "@react-spectrum/contextualhelp": "^3.6.8", - "@react-spectrum/datepicker": "^3.9.3", - "@react-spectrum/dialog": "^3.8.8", - "@react-spectrum/divider": "^3.5.10", - "@react-spectrum/dnd": "^3.3.7", - "@react-spectrum/form": "^3.7.3", - "@react-spectrum/icon": "^3.7.10", - "@react-spectrum/illustratedmessage": "^3.4.10", - "@react-spectrum/image": "^3.4.10", - "@react-spectrum/inlinealert": "^3.2.2", - "@react-spectrum/labeledvalue": "^3.1.11", - "@react-spectrum/layout": "^3.6.2", - "@react-spectrum/link": "^3.6.4", - "@react-spectrum/list": "^3.7.7", - "@react-spectrum/listbox": "^3.12.6", - "@react-spectrum/menu": "^3.18.0", - "@react-spectrum/meter": "^3.4.10", - "@react-spectrum/numberfield": "^3.9.0", - "@react-spectrum/overlays": "^5.5.4", - "@react-spectrum/picker": "^3.14.2", - "@react-spectrum/progress": "^3.7.4", - "@react-spectrum/provider": "^3.9.4", - "@react-spectrum/radio": "^3.7.3", - "@react-spectrum/searchfield": "^3.8.3", - "@react-spectrum/slider": "^3.6.6", - "@react-spectrum/statuslight": "^3.5.10", - "@react-spectrum/switch": "^3.5.2", - "@react-spectrum/table": "^3.12.7", - "@react-spectrum/tabs": "^3.8.7", - "@react-spectrum/tag": "^3.2.3", - "@react-spectrum/text": "^3.5.2", - "@react-spectrum/textfield": "^3.11.3", - "@react-spectrum/theme-dark": "^3.5.7", - "@react-spectrum/theme-default": "^3.5.7", - "@react-spectrum/theme-light": "^3.4.7", - "@react-spectrum/tooltip": "^3.6.4", - "@react-spectrum/view": "^3.6.7", - "@react-spectrum/well": "^3.4.10", - "@react-stately/collections": "^3.10.4", - "@react-stately/data": "^3.11.1", - "@react-types/shared": "^3.22.0", + "version": "3.34.1", + "resolved": "https://registry.npmjs.org/@adobe/react-spectrum/-/react-spectrum-3.34.1.tgz", + "integrity": "sha512-J1HOjntW+H8xusfc5xLnIlUXNOzllp4f7qzh3LlDOsZuH8oBH8sIYmBVp4ijVhRFUKa10qg088role1On3UGbg==", + "dependencies": { + "@internationalized/string": "^3.2.1", + "@react-aria/i18n": "^3.10.2", + "@react-aria/ssr": "^3.9.2", + "@react-aria/utils": "^3.23.2", + "@react-aria/visually-hidden": "^3.8.10", + "@react-spectrum/actionbar": "^3.4.3", + "@react-spectrum/actiongroup": "^3.10.3", + "@react-spectrum/avatar": "^3.0.10", + "@react-spectrum/badge": "^3.1.11", + "@react-spectrum/breadcrumbs": "^3.9.5", + "@react-spectrum/button": "^3.16.2", + "@react-spectrum/buttongroup": "^3.6.11", + "@react-spectrum/calendar": "^3.4.7", + "@react-spectrum/checkbox": "^3.9.4", + "@react-spectrum/combobox": "^3.12.3", + "@react-spectrum/contextualhelp": "^3.6.9", + "@react-spectrum/datepicker": "^3.9.4", + "@react-spectrum/dialog": "^3.8.9", + "@react-spectrum/divider": "^3.5.11", + "@react-spectrum/dnd": "^3.3.8", + "@react-spectrum/form": "^3.7.4", + "@react-spectrum/icon": "^3.7.11", + "@react-spectrum/illustratedmessage": "^3.4.11", + "@react-spectrum/image": "^3.4.11", + "@react-spectrum/inlinealert": "^3.2.3", + "@react-spectrum/labeledvalue": "^3.1.12", + "@react-spectrum/layout": "^3.6.3", + "@react-spectrum/link": "^3.6.5", + "@react-spectrum/list": "^3.7.8", + "@react-spectrum/listbox": "^3.12.7", + "@react-spectrum/menu": "^3.18.1", + "@react-spectrum/meter": "^3.4.11", + "@react-spectrum/numberfield": "^3.9.1", + "@react-spectrum/overlays": "^5.5.5", + "@react-spectrum/picker": "^3.14.3", + "@react-spectrum/progress": "^3.7.5", + "@react-spectrum/provider": "^3.9.5", + "@react-spectrum/radio": "^3.7.4", + "@react-spectrum/searchfield": "^3.8.4", + "@react-spectrum/slider": "^3.6.7", + "@react-spectrum/statuslight": "^3.5.11", + "@react-spectrum/switch": "^3.5.3", + "@react-spectrum/table": "^3.12.8", + "@react-spectrum/tabs": "^3.8.8", + "@react-spectrum/tag": "^3.2.4", + "@react-spectrum/text": "^3.5.3", + "@react-spectrum/textfield": "^3.11.4", + "@react-spectrum/theme-dark": "^3.5.8", + "@react-spectrum/theme-default": "^3.5.8", + "@react-spectrum/theme-light": "^3.4.8", + "@react-spectrum/tooltip": "^3.6.5", + "@react-spectrum/view": "^3.6.8", + "@react-spectrum/well": "^3.4.11", + "@react-stately/collections": "^3.10.5", + "@react-stately/data": "^3.11.2", + "@react-types/shared": "^3.22.1", "client-only": "^0.0.1" }, "peerDependencies": { @@ -2499,18 +2499,6 @@ "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==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@eslint/js": { "version": "8.56.0", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", @@ -2709,30 +2697,30 @@ } }, "node_modules/@fullcalendar/core": { - "version": "6.1.10", - "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.10.tgz", - "integrity": "sha512-oTXGJSAGpCf1oY+CKp5qYjMHkJCPBkJ3SHitl63n8Q6xKeiwQ4EF6Au451euUovREwJpLmD1AyZrCnWmtB9AVg==", + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.11.tgz", + "integrity": "sha512-TjG7c8sUz+Vkui2FyCNJ+xqyu0nq653Ibe99A66LoW95oBo6tVhhKIaG1Wh0GVKymYiqAQN/OEdYTuj4ay27kA==", "dependencies": { "preact": "~10.12.1" } }, "node_modules/@fullcalendar/daygrid": { - "version": "6.1.10", - "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.10.tgz", - "integrity": "sha512-Z4GRm1IyHKgxXFTWGcEI0nTsvYOIkpE0aMt3/o3ER2SZkF+hfwcDFhtj0c9+WhMjXFIWYeoTnA9rUOY7Zl/nxA==", + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.11.tgz", + "integrity": "sha512-hF5jJB7cgUIxWD5MVjj8IU407HISyLu7BWXcEIuTytkfr8oolOXeCazqnnjmRbnFOncoJQVstTtq6SIhaT32Xg==", "peerDependencies": { - "@fullcalendar/core": "~6.1.10" + "@fullcalendar/core": "~6.1.11" } }, "node_modules/@fullcalendar/multimonth": { - "version": "6.1.10", - "resolved": "https://registry.npmjs.org/@fullcalendar/multimonth/-/multimonth-6.1.10.tgz", - "integrity": "sha512-mLGEgD+sv8rNfKphyOCWRQapX7/nAvHgQmDTjuy4STlhHsddCYVmFlsSgF373ph1tXh41wAJUVdNO/pDmCvUfA==", + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/@fullcalendar/multimonth/-/multimonth-6.1.11.tgz", + "integrity": "sha512-7DbPC+AAlaKnquGVdw1Z85Q3nSZ4GZ1NcVIk4k7bLnqDlntwHPPsrDlSIzUWKcN0q5/u7jQHm4PU1m3LAl70Sg==", "dependencies": { - "@fullcalendar/daygrid": "~6.1.10" + "@fullcalendar/daygrid": "~6.1.11" }, "peerDependencies": { - "@fullcalendar/core": "~6.1.10" + "@fullcalendar/core": "~6.1.11" } }, "node_modules/@googlemaps/js-api-loader": { @@ -2816,34 +2804,34 @@ } }, "node_modules/@internationalized/date": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.5.1.tgz", - "integrity": "sha512-LUQIfwU9e+Fmutc/DpRTGXSdgYZLBegi4wygCWDSVmUdLTaMHsQyASDiJtREwanwKuQLq0hY76fCJ9J/9I2xOQ==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.5.2.tgz", + "integrity": "sha512-vo1yOMUt2hzp63IutEaTUxROdvQg1qlMRsbCvbay2AK2Gai7wIgCyK5weEX3nHkiLgo4qCXHijFNC/ILhlRpOQ==", "dependencies": { "@swc/helpers": "^0.5.0" } }, "node_modules/@internationalized/message": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@internationalized/message/-/message-3.1.1.tgz", - "integrity": "sha512-ZgHxf5HAPIaR0th+w0RUD62yF6vxitjlprSxmLJ1tam7FOekqRSDELMg4Cr/DdszG5YLsp5BG3FgHgqquQZbqw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@internationalized/message/-/message-3.1.2.tgz", + "integrity": "sha512-MHAWsZWz8jf6jFPZqpTudcCM361YMtPIRu9CXkYmKjJ/0R3pQRScV5C0zS+Qi50O5UAm8ecKhkXx6mWDDcF6/g==", "dependencies": { "@swc/helpers": "^0.5.0", "intl-messageformat": "^10.1.0" } }, "node_modules/@internationalized/number": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.5.0.tgz", - "integrity": "sha512-ZY1BW8HT9WKYvaubbuqXbbDdHhOUMfE2zHHFJeTppid0S+pc8HtdIxFxaYMsGjCb4UsF+MEJ4n2TfU7iHnUK8w==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.5.1.tgz", + "integrity": "sha512-N0fPU/nz15SwR9IbfJ5xaS9Ss/O5h1sVXMZf43vc9mxEG48ovglvvzBjF53aHlq20uoR6c+88CrIXipU/LSzwg==", "dependencies": { "@swc/helpers": "^0.5.0" } }, "node_modules/@internationalized/string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@internationalized/string/-/string-3.2.0.tgz", - "integrity": "sha512-Xx3Sy3f2c9ctT+vh8c7euEaEHQZltp0euZ3Hy4UfT3E13r6lxpUS3kgKyumEjboJZSnaZv7JhqWz3D75v+IxQg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@internationalized/string/-/string-3.2.1.tgz", + "integrity": "sha512-vWQOvRIauvFMzOO+h7QrdsJmtN1AXAFVcaLWP9AseRN2o7iHceZ6bIXhBD4teZl8i91A3gxKnWBlGgjCwU6MFQ==", "dependencies": { "@swc/helpers": "^0.5.0" } @@ -3615,9 +3603,9 @@ } }, "node_modules/@mui/core-downloads-tracker": { - "version": "5.15.10", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.10.tgz", - "integrity": "sha512-qPv7B+LeMatYuzRjB3hlZUHqinHx/fX4YFBiaS19oC02A1e9JFuDKDvlyRQQ5oRSbJJt0QlaLTlr0IcauVcJRQ==", + "version": "5.15.11", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.11.tgz", + "integrity": "sha512-JVrJ9Jo4gyU707ujnRzmE8ABBWpXd6FwL9GYULmwZRtfPg89ggXs/S3MStQkpJ1JRWfdLL6S5syXmgQGq5EDAw==", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" @@ -3693,12 +3681,12 @@ } }, "node_modules/@mui/private-theming": { - "version": "5.15.9", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.9.tgz", - "integrity": "sha512-/aMJlDOxOTAXyp4F2rIukW1O0anodAMCkv1DfBh/z9vaKHY3bd5fFf42wmP+0GRmwMinC5aWPpNfHXOED1fEtg==", + "version": "5.15.11", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.11.tgz", + "integrity": "sha512-jY/696SnSxSzO1u86Thym7ky5T9CgfidU3NFJjguldqK4f3Z5S97amZ6nffg8gTD0HBjY9scB+4ekqDEUmxZOA==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/utils": "^5.15.9", + "@mui/utils": "^5.15.11", "prop-types": "^15.8.1" }, "engines": { @@ -3719,9 +3707,9 @@ } }, "node_modules/@mui/styled-engine": { - "version": "5.15.9", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.9.tgz", - "integrity": "sha512-NRKtYkL5PZDH7dEmaLEIiipd3mxNnQSO+Yo8rFNBNptY8wzQnQ+VjayTq39qH7Sast5cwHKYFusUrQyD+SS4Og==", + "version": "5.15.11", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.11.tgz", + "integrity": "sha512-So21AhAngqo07ces4S/JpX5UaMU2RHXpEA6hNzI6IQjd/1usMPxpgK8wkGgTe3JKmC2KDmH8cvoycq5H3Ii7/w==", "dependencies": { "@babel/runtime": "^7.23.9", "@emotion/cache": "^11.11.0", @@ -3828,9 +3816,9 @@ } }, "node_modules/@mui/utils": { - "version": "5.15.9", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.9.tgz", - "integrity": "sha512-yDYfr61bCYUz1QtwvpqYy/3687Z8/nS4zv7lv/ih/6ZFGMl1iolEvxRmR84v2lOYxlds+kq1IVYbXxDKh8Z9sg==", + "version": "5.15.11", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.11.tgz", + "integrity": "sha512-D6bwqprUa9Stf8ft0dcMqWyWDKEo7D+6pB1k8WajbqlYIRA8J8Kw9Ra7PSZKKePGBGWO+/xxrX1U8HpG/aXQCw==", "dependencies": { "@babel/runtime": "^7.23.9", "@types/prop-types": "^15.7.11", @@ -3972,9 +3960,9 @@ } }, "node_modules/@octokit/types": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.4.0.tgz", - "integrity": "sha512-FLWs/AvZllw/AGVs+nJ+ELCDZZJk+kY0zMen118xhL2zD0s1etIUHm1odgjP7epxYU1ln7SZxEUWYop5bhsdgQ==", + "version": "12.5.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.5.0.tgz", + "integrity": "sha512-YJEKcb0KkJlIUNU/zjnZwHEP8AoVh/OoIcP/1IyR4UHxExz7fzpe/a8IG4wBtQi7QDEqiomVLX88S6FpxxAJtg==", "dependencies": { "@octokit/openapi-types": "^19.1.0" } @@ -4018,17 +4006,17 @@ } }, "node_modules/@react-aria/actiongroup": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@react-aria/actiongroup/-/actiongroup-3.7.2.tgz", - "integrity": "sha512-H8VLxkelhppaFGuPCOuZVryKBUeKVhCtkRIlR3ZnVcNR5jV9Qlc1J3rWOmMNJxcVTszXEbOcJL+/xX1fpBhA5g==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-stately/list": "^3.10.2", - "@react-types/actiongroup": "^3.4.6", - "@react-types/shared": "^3.22.0", + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@react-aria/actiongroup/-/actiongroup-3.7.3.tgz", + "integrity": "sha512-o1qw7w7GdL8vsOuzBc2mil+MM1CWWDDZ1+VhWnVwoDVt5Pxj36981leTh/WTS58IQ34N7p/jVdQMraQ25EJJyA==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-stately/list": "^3.10.3", + "@react-types/actiongroup": "^3.4.7", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4037,15 +4025,15 @@ } }, "node_modules/@react-aria/breadcrumbs": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@react-aria/breadcrumbs/-/breadcrumbs-3.5.10.tgz", - "integrity": "sha512-Z6UMVvobmBg4uLewAXkp9/X6AFN+S/4uHk3IShHCaI8ONNZrIewbPYR1B9qNsgMMnYWmDfaOp40krdJSgYdGUw==", - "dependencies": { - "@react-aria/i18n": "^3.10.1", - "@react-aria/link": "^3.6.4", - "@react-aria/utils": "^3.23.1", - "@react-types/breadcrumbs": "^3.7.2", - "@react-types/shared": "^3.22.0", + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@react-aria/breadcrumbs/-/breadcrumbs-3.5.11.tgz", + "integrity": "sha512-bQz4g2tKvcWxeqPGj9O0RQf++Ka8f2o/pJMJB+QQ27DVQWhxpQpND//oFku2aFYkxHB/fyD9qVoiqpQR25bidw==", + "dependencies": { + "@react-aria/i18n": "^3.10.2", + "@react-aria/link": "^3.6.5", + "@react-aria/utils": "^3.23.2", + "@react-types/breadcrumbs": "^3.7.3", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4053,16 +4041,16 @@ } }, "node_modules/@react-aria/button": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@react-aria/button/-/button-3.9.2.tgz", - "integrity": "sha512-7ZVUASmdOdi1FNP528oDggxO1SNoAhyuMutaJd7nNBjAJ4Zagi/T9qaAFoVha1hyejfLY/ZzXRdWhnkUYljSbA==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-stately/toggle": "^3.7.1", - "@react-types/button": "^3.9.1", - "@react-types/shared": "^3.22.0", + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@react-aria/button/-/button-3.9.3.tgz", + "integrity": "sha512-ZXo2VGTxfbaTEnfeIlm5ym4vYpGAy8sGrad8Scv+EyDAJWLMKokqctfaN6YSWbqUApC3FN63IvMqASflbmnYig==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-stately/toggle": "^3.7.2", + "@react-types/button": "^3.9.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4070,19 +4058,19 @@ } }, "node_modules/@react-aria/calendar": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/@react-aria/calendar/-/calendar-3.5.5.tgz", - "integrity": "sha512-9CmW7mwIJwuM8wsw4W8ads3mxUftaSSfYaWH1h+m0C9ycNJ1FP2QO+re4I821+LhuuyJTj1GOUJ7Tzk+c9yWJA==", - "dependencies": { - "@internationalized/date": "^3.5.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/live-announcer": "^3.3.1", - "@react-aria/utils": "^3.23.1", - "@react-stately/calendar": "^3.4.3", - "@react-types/button": "^3.9.1", - "@react-types/calendar": "^3.4.3", - "@react-types/shared": "^3.22.0", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@react-aria/calendar/-/calendar-3.5.6.tgz", + "integrity": "sha512-PA0Ur5WcODMn7t2gCUvq61YktkB+WlSZjzDr5kcY3sdl53ZjiyqCa2hYgrb6R0J859LVJXAp+5Qaproz8g1oLA==", + "dependencies": { + "@internationalized/date": "^3.5.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/live-announcer": "^3.3.2", + "@react-aria/utils": "^3.23.2", + "@react-stately/calendar": "^3.4.4", + "@react-types/button": "^3.9.2", + "@react-types/calendar": "^3.4.4", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4091,20 +4079,20 @@ } }, "node_modules/@react-aria/checkbox": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@react-aria/checkbox/-/checkbox-3.14.0.tgz", - "integrity": "sha512-eOIeIIhnoQkin+1kmz+pv/YjRSkMWAF4uyi1THwkTlLZmpJvxUqEbSzQhfBEH30tKAlFLAcpY3+XOUCm74tHng==", - "dependencies": { - "@react-aria/form": "^3.0.2", - "@react-aria/interactions": "^3.21.0", - "@react-aria/label": "^3.7.5", - "@react-aria/toggle": "^3.10.1", - "@react-aria/utils": "^3.23.1", - "@react-stately/checkbox": "^3.6.2", - "@react-stately/form": "^3.0.0", - "@react-stately/toggle": "^3.7.1", - "@react-types/checkbox": "^3.7.0", - "@react-types/shared": "^3.22.0", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/@react-aria/checkbox/-/checkbox-3.14.1.tgz", + "integrity": "sha512-b4rtrg5SpRSa9jBOqzJMmprJ+jDi3KyVvUh+DsvISe5Ti7gVAhMBgnca1D0xBp22w2jhk/o4gyu1bYxGLum0GA==", + "dependencies": { + "@react-aria/form": "^3.0.3", + "@react-aria/interactions": "^3.21.1", + "@react-aria/label": "^3.7.6", + "@react-aria/toggle": "^3.10.2", + "@react-aria/utils": "^3.23.2", + "@react-stately/checkbox": "^3.6.3", + "@react-stately/form": "^3.0.1", + "@react-stately/toggle": "^3.7.2", + "@react-types/checkbox": "^3.7.1", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4112,24 +4100,24 @@ } }, "node_modules/@react-aria/combobox": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/@react-aria/combobox/-/combobox-3.8.3.tgz", - "integrity": "sha512-7SteX1MjDV0077IZVMuaXAuIiSaQeGYh1sT5Y6eDOCiOArkPaEmXWzCjBDkLYex0jl6z51gl0gLU3dwq9kB6Gw==", - "dependencies": { - "@react-aria/i18n": "^3.10.1", - "@react-aria/listbox": "^3.11.4", - "@react-aria/live-announcer": "^3.3.1", - "@react-aria/menu": "^3.13.0", - "@react-aria/overlays": "^3.21.0", - "@react-aria/selection": "^3.17.4", - "@react-aria/textfield": "^3.14.2", - "@react-aria/utils": "^3.23.1", - "@react-stately/collections": "^3.10.4", - "@react-stately/combobox": "^3.8.1", - "@react-stately/form": "^3.0.0", - "@react-types/button": "^3.9.1", - "@react-types/combobox": "^3.10.0", - "@react-types/shared": "^3.22.0", + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/@react-aria/combobox/-/combobox-3.8.4.tgz", + "integrity": "sha512-HyTWIo2B/0xq0Of+sDEZCfJyf4BvCvDYIWG4UhjqL1kHIHIGQyyr+SldbVUjXVYnk8pP1eGB3ttiREujjjALPQ==", + "dependencies": { + "@react-aria/i18n": "^3.10.2", + "@react-aria/listbox": "^3.11.5", + "@react-aria/live-announcer": "^3.3.2", + "@react-aria/menu": "^3.13.1", + "@react-aria/overlays": "^3.21.1", + "@react-aria/selection": "^3.17.5", + "@react-aria/textfield": "^3.14.3", + "@react-aria/utils": "^3.23.2", + "@react-stately/collections": "^3.10.5", + "@react-stately/combobox": "^3.8.2", + "@react-stately/form": "^3.0.1", + "@react-types/button": "^3.9.2", + "@react-types/combobox": "^3.10.1", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4138,27 +4126,27 @@ } }, "node_modules/@react-aria/datepicker": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@react-aria/datepicker/-/datepicker-3.9.2.tgz", - "integrity": "sha512-8iTfhHEfPPmf7DmqnzCttvzZms15CstAVdvbOVqUuBqH8Ai693aIuVfOEkyqL5Vqohy4/+ViA5LZ3WM4m7QLiQ==", - "dependencies": { - "@internationalized/date": "^3.5.1", - "@internationalized/number": "^3.5.0", - "@internationalized/string": "^3.2.0", - "@react-aria/focus": "^3.16.1", - "@react-aria/form": "^3.0.2", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/label": "^3.7.5", - "@react-aria/spinbutton": "^3.6.2", - "@react-aria/utils": "^3.23.1", - "@react-stately/datepicker": "^3.9.1", - "@react-stately/form": "^3.0.0", - "@react-types/button": "^3.9.1", - "@react-types/calendar": "^3.4.3", - "@react-types/datepicker": "^3.7.1", - "@react-types/dialog": "^3.5.7", - "@react-types/shared": "^3.22.0", + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@react-aria/datepicker/-/datepicker-3.9.3.tgz", + "integrity": "sha512-1AjCAizd88ACKjVNhFazX4HZZFwWi2rsSlGCTm66Nx6wm5N/Cpbm466dpYEFyQUsKSOG4CC65G1zfYoMPe48MQ==", + "dependencies": { + "@internationalized/date": "^3.5.2", + "@internationalized/number": "^3.5.1", + "@internationalized/string": "^3.2.1", + "@react-aria/focus": "^3.16.2", + "@react-aria/form": "^3.0.3", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/label": "^3.7.6", + "@react-aria/spinbutton": "^3.6.3", + "@react-aria/utils": "^3.23.2", + "@react-stately/datepicker": "^3.9.2", + "@react-stately/form": "^3.0.1", + "@react-types/button": "^3.9.2", + "@react-types/calendar": "^3.4.4", + "@react-types/datepicker": "^3.7.2", + "@react-types/dialog": "^3.5.8", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4167,15 +4155,15 @@ } }, "node_modules/@react-aria/dialog": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/@react-aria/dialog/-/dialog-3.5.11.tgz", - "integrity": "sha512-oT+FBOtPZRWVBxPt1K8F5XaKGYpi+ZV3oFFzub8w+D6m+9WN4pktUx7YBz95Kunw7M1HcAsyQZX0fsAuDPL7Rw==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/overlays": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-types/dialog": "^3.5.7", - "@react-types/shared": "^3.22.0", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@react-aria/dialog/-/dialog-3.5.12.tgz", + "integrity": "sha512-7UJR/h/Y364u6Ltpw0bT51B48FybTuIBacGpEJN5IxZlpxvQt0KQcBDiOWfAa/GQogw4B5hH6agaOO0nJcP49Q==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/overlays": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-types/dialog": "^3.5.8", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4184,19 +4172,19 @@ } }, "node_modules/@react-aria/dnd": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@react-aria/dnd/-/dnd-3.5.2.tgz", - "integrity": "sha512-isEYONbkZMvx1DUmeAo/NwazFz9ZEKdosszWDhzxSk6a38C5kAHBIV2GBntwsL3W9EQn1fzUY/X13ykcHvjJAA==", - "dependencies": { - "@internationalized/string": "^3.2.0", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/live-announcer": "^3.3.1", - "@react-aria/overlays": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-stately/dnd": "^3.2.7", - "@react-types/button": "^3.9.1", - "@react-types/shared": "^3.22.0", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/@react-aria/dnd/-/dnd-3.5.3.tgz", + "integrity": "sha512-0gi6sRnr97fSQnGy+CMt+99/+vVqr+qv2T9Ts8X9TAzxHNokz5QfSL88QSlTU36EnAVLxPY18iZQWCExSjKpEQ==", + "dependencies": { + "@internationalized/string": "^3.2.1", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/live-announcer": "^3.3.2", + "@react-aria/overlays": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-stately/dnd": "^3.2.8", + "@react-types/button": "^3.9.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4205,13 +4193,13 @@ } }, "node_modules/@react-aria/focus": { - "version": "3.16.1", - "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.16.1.tgz", - "integrity": "sha512-3ZEYc+hWqDQX7fA54ZOTkED8OGXs9+K9fYmjD1IdjZJAJS/2/AJ95PgIQ29zBkl9D9TAi4Nb3tJ/3+H/02UzoA==", + "version": "3.16.2", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.16.2.tgz", + "integrity": "sha512-Rqo9ummmgotESfypzFjI3uh58yMpL+E+lJBbQuXkBM0u0cU2YYzu0uOrFrq3zcHk997udZvq1pGK/R+2xk9B7g==", "dependencies": { - "@react-aria/interactions": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-types/shared": "^3.22.0", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -4220,14 +4208,14 @@ } }, "node_modules/@react-aria/form": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@react-aria/form/-/form-3.0.2.tgz", - "integrity": "sha512-iQBbol9vSPd+s2rNlkmu646wGlrDNr/u+Uf/NRXNl5MNvDIWAQ3mliGL1ERGtT5GGq0WzSka4hjbzwf67BdQKw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@react-aria/form/-/form-3.0.3.tgz", + "integrity": "sha512-5Q2BHE4TTPDzGY2npCzpRRYshwWUb3SMUA/Cbz7QfEtBk+NYuVaq3KjvqLqgUUdyKtqLZ9Far0kIAexloOC4jw==", "dependencies": { - "@react-aria/interactions": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-stately/form": "^3.0.0", - "@react-types/shared": "^3.22.0", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-stately/form": "^3.0.1", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4235,23 +4223,23 @@ } }, "node_modules/@react-aria/grid": { - "version": "3.8.7", - "resolved": "https://registry.npmjs.org/@react-aria/grid/-/grid-3.8.7.tgz", - "integrity": "sha512-gpWiZptCA+65jVbCu9vzkfBfzfgLucSOZFy9P+fVrGB6fE6pDGj13oyyr+Nmr6jihQmOv+y9eJsU7u9Xlyl2Xg==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/live-announcer": "^3.3.1", - "@react-aria/selection": "^3.17.4", - "@react-aria/utils": "^3.23.1", - "@react-stately/collections": "^3.10.4", - "@react-stately/grid": "^3.8.4", - "@react-stately/selection": "^3.14.2", - "@react-stately/virtualizer": "^3.6.7", - "@react-types/checkbox": "^3.7.0", - "@react-types/grid": "^3.2.3", - "@react-types/shared": "^3.22.0", + "version": "3.8.8", + "resolved": "https://registry.npmjs.org/@react-aria/grid/-/grid-3.8.8.tgz", + "integrity": "sha512-7Bzbya4tO0oIgqexwRb8D6ZdC0GASYq9f/pnkrqocgvG9e1SCld4zOioKbYQDvAK/NnbCgXmmdqFAcLM/iazaA==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/live-announcer": "^3.3.2", + "@react-aria/selection": "^3.17.5", + "@react-aria/utils": "^3.23.2", + "@react-stately/collections": "^3.10.5", + "@react-stately/grid": "^3.8.5", + "@react-stately/selection": "^3.14.3", + "@react-stately/virtualizer": "^3.6.8", + "@react-types/checkbox": "^3.7.1", + "@react-types/grid": "^3.2.4", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4260,18 +4248,18 @@ } }, "node_modules/@react-aria/gridlist": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@react-aria/gridlist/-/gridlist-3.7.4.tgz", - "integrity": "sha512-9GeKXfMd4WqyaRs7PMvuL9ryLND0EBkgf14dycbZCb/QKxgNYRLPFZN6fV3LiMh2CiqAXEpmDOo60PxSxh618A==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/grid": "^3.8.7", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/selection": "^3.17.4", - "@react-aria/utils": "^3.23.1", - "@react-stately/list": "^3.10.2", - "@react-types/shared": "^3.22.0", + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/@react-aria/gridlist/-/gridlist-3.7.5.tgz", + "integrity": "sha512-RmHEJ++vngHYEWbUCtLLmGh7H3vNd2Y9S0q/9SgHFPbqPZycT5mxDZ2arqpOXeHRVRvPBaW9ZlMxI2bPOePrYw==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/grid": "^3.8.8", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/selection": "^3.17.5", + "@react-aria/utils": "^3.23.2", + "@react-stately/list": "^3.10.3", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4280,17 +4268,17 @@ } }, "node_modules/@react-aria/i18n": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.10.1.tgz", - "integrity": "sha512-o05AozIXhropvN8vg0YD0Z0vajYuaALxB1+Km00FE5uGim4u2UKeBXqAk+8QsOs4CHg91paa3C15DcTDDEMJSg==", - "dependencies": { - "@internationalized/date": "^3.5.1", - "@internationalized/message": "^3.1.1", - "@internationalized/number": "^3.5.0", - "@internationalized/string": "^3.2.0", - "@react-aria/ssr": "^3.9.1", - "@react-aria/utils": "^3.23.1", - "@react-types/shared": "^3.22.0", + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.10.2.tgz", + "integrity": "sha512-Z1ormoIvMOI4mEdcFLYsoJy9w/EzBdBmgfLP+S/Ah+1xwQOXpgwZxiKOhYHpWa0lf6hkKJL34N9MHJvCJ5Crvw==", + "dependencies": { + "@internationalized/date": "^3.5.2", + "@internationalized/message": "^3.1.2", + "@internationalized/number": "^3.5.1", + "@internationalized/string": "^3.2.1", + "@react-aria/ssr": "^3.9.2", + "@react-aria/utils": "^3.23.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4298,13 +4286,13 @@ } }, "node_modules/@react-aria/interactions": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.21.0.tgz", - "integrity": "sha512-sPuzEl4Xq/BR5gbYr2R/sDzwlX9NdJ02i8Ew2rEy2hLMlf1jAeUAdTg/G+K9baWJ8acV9fZv6h/mdV3dXGLPSg==", + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.21.1.tgz", + "integrity": "sha512-AlHf5SOzsShkHfV8GLLk3v9lEmYqYHURKcXWue0JdYbmquMRkUsf/+Tjl1+zHVAQ8lKqRnPYbTmc4AcZbqxltw==", "dependencies": { - "@react-aria/ssr": "^3.9.1", - "@react-aria/utils": "^3.23.1", - "@react-types/shared": "^3.22.0", + "@react-aria/ssr": "^3.9.2", + "@react-aria/utils": "^3.23.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4312,12 +4300,12 @@ } }, "node_modules/@react-aria/label": { - "version": "3.7.5", - "resolved": "https://registry.npmjs.org/@react-aria/label/-/label-3.7.5.tgz", - "integrity": "sha512-1hlTer4X9zlzC2PHC9SlAeY/E55dYyzxxpM75kqhtma8XFgDUB0Rztvi+R/Uenl0VDuy1Ny95OdhBM0j70qBnA==", + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/@react-aria/label/-/label-3.7.6.tgz", + "integrity": "sha512-ap9iFS+6RUOqeW/F2JoNpERqMn1PvVIo3tTMrJ1TY1tIwyJOxdCBRgx9yjnPBnr+Ywguep+fkPNNi/m74+tXVQ==", "dependencies": { - "@react-aria/utils": "^3.23.1", - "@react-types/shared": "^3.22.0", + "@react-aria/utils": "^3.23.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4325,15 +4313,15 @@ } }, "node_modules/@react-aria/link": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/@react-aria/link/-/link-3.6.4.tgz", - "integrity": "sha512-oCUWAvnJYD7IUR6ujQJqCChiSFJMsBncoInMvfbnlD3ZX5AqLWEPkJUZ7aM8XB6fGEapiYoY1IUHzOM63XsmjQ==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-types/link": "^3.5.2", - "@react-types/shared": "^3.22.0", + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/@react-aria/link/-/link-3.6.5.tgz", + "integrity": "sha512-kg8CxKqkciQFzODvLAfxEs8gbqNXFZCW/ISOE2LHYKbh9pA144LVo71qO3SPeYVVzIjmZeW4vEMdZwqkNozecw==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-types/link": "^3.5.3", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4341,18 +4329,18 @@ } }, "node_modules/@react-aria/listbox": { - "version": "3.11.4", - "resolved": "https://registry.npmjs.org/@react-aria/listbox/-/listbox-3.11.4.tgz", - "integrity": "sha512-ml2dUy1R0kSuDmFrW0xtAnI04nZBfzLLmINSl1k9N5Tr/PVZ/TVGjFimHfpG7g3uvTxGXpjFfA9DR+2Nyuj/SA==", - "dependencies": { - "@react-aria/interactions": "^3.21.0", - "@react-aria/label": "^3.7.5", - "@react-aria/selection": "^3.17.4", - "@react-aria/utils": "^3.23.1", - "@react-stately/collections": "^3.10.4", - "@react-stately/list": "^3.10.2", - "@react-types/listbox": "^3.4.6", - "@react-types/shared": "^3.22.0", + "version": "3.11.5", + "resolved": "https://registry.npmjs.org/@react-aria/listbox/-/listbox-3.11.5.tgz", + "integrity": "sha512-y3a3zQYjT+JKgugCMMKS7K9sRoCoP1Z6Fiiyfd77OHXWzh9RlnvWGsseljynmbxLzSuPwFtCYkU1Jz4QwsPUIg==", + "dependencies": { + "@react-aria/interactions": "^3.21.1", + "@react-aria/label": "^3.7.6", + "@react-aria/selection": "^3.17.5", + "@react-aria/utils": "^3.23.2", + "@react-stately/collections": "^3.10.5", + "@react-stately/list": "^3.10.3", + "@react-types/listbox": "^3.4.7", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4361,30 +4349,30 @@ } }, "node_modules/@react-aria/live-announcer": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@react-aria/live-announcer/-/live-announcer-3.3.1.tgz", - "integrity": "sha512-hsc77U7S16trM86d+peqJCOCQ7/smO1cybgdpOuzXyiwcHQw8RQ4GrXrS37P4Ux/44E9nMZkOwATQRT2aK8+Ew==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@react-aria/live-announcer/-/live-announcer-3.3.2.tgz", + "integrity": "sha512-aOyPcsfyY9tLCBhuUaYCruwcd1IrYLc47Ou+J7wMzjeN9v4lsaEfiN12WFl8pDqOwfy6/7It2wmlm5hOuZY8wQ==", "dependencies": { "@swc/helpers": "^0.5.0" } }, "node_modules/@react-aria/menu": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@react-aria/menu/-/menu-3.13.0.tgz", - "integrity": "sha512-2vNZV77I36sbAINj3QVbq4yxOfytzQpdQAhHy7QFr7WjvTYqPAVNuD4LgiGn97I5skLRakCs+tGiLgIQGY/0Ig==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/overlays": "^3.21.0", - "@react-aria/selection": "^3.17.4", - "@react-aria/utils": "^3.23.1", - "@react-stately/collections": "^3.10.4", - "@react-stately/menu": "^3.6.0", - "@react-stately/tree": "^3.7.5", - "@react-types/button": "^3.9.1", - "@react-types/menu": "^3.9.6", - "@react-types/shared": "^3.22.0", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/@react-aria/menu/-/menu-3.13.1.tgz", + "integrity": "sha512-jF80YIcvD16Fgwm5pj7ViUE3Dj7z5iewQixLaFVdvpgfyE58SD/ZVU9/JkK5g/03DYM0sjpUKZGkdFxxw8eKnw==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/overlays": "^3.21.1", + "@react-aria/selection": "^3.17.5", + "@react-aria/utils": "^3.23.2", + "@react-stately/collections": "^3.10.5", + "@react-stately/menu": "^3.6.1", + "@react-stately/tree": "^3.7.6", + "@react-types/button": "^3.9.2", + "@react-types/menu": "^3.9.7", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4393,13 +4381,13 @@ } }, "node_modules/@react-aria/meter": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/@react-aria/meter/-/meter-3.4.10.tgz", - "integrity": "sha512-8x4Y9NKRzJNPlcU9kn0kflYSLCyMwaIAx0JJFL576+HdZhyIbEPFk/vaaYWbyJgo5xYsicaeynwJ7j6lCyxF8w==", + "version": "3.4.11", + "resolved": "https://registry.npmjs.org/@react-aria/meter/-/meter-3.4.11.tgz", + "integrity": "sha512-P1G3Jdh0f/uieUDqvc3Ee4wzqBJa7H077BVSC3KPRqEp6YY7JimZGWjOwbFlO2PXhryXm/dI8EzUmh+4ZXjq/g==", "dependencies": { - "@react-aria/progress": "^3.4.10", - "@react-types/meter": "^3.3.6", - "@react-types/shared": "^3.22.0", + "@react-aria/progress": "^3.4.11", + "@react-types/meter": "^3.3.7", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4407,20 +4395,20 @@ } }, "node_modules/@react-aria/numberfield": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/@react-aria/numberfield/-/numberfield-3.11.0.tgz", - "integrity": "sha512-fdl+d6sIwHRMiraXMQ5JyPlrmsQ3YECh9W7fzbY3CBcsG9mXVQjoQ50cV7u5VeakLXaBsgL4EmVe/zmTk2G0Aw==", - "dependencies": { - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/spinbutton": "^3.6.2", - "@react-aria/textfield": "^3.14.2", - "@react-aria/utils": "^3.23.1", - "@react-stately/form": "^3.0.0", - "@react-stately/numberfield": "^3.9.0", - "@react-types/button": "^3.9.1", - "@react-types/numberfield": "^3.8.0", - "@react-types/shared": "^3.22.0", + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/@react-aria/numberfield/-/numberfield-3.11.1.tgz", + "integrity": "sha512-JQ1Z+Ho5H+jeav7jt9A4vBsIQR/Dd2CFbObrULjGkqSrnWjARFZBv3gZwmfGCtplEPeAv9buYKHAqebPtJNUww==", + "dependencies": { + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/spinbutton": "^3.6.3", + "@react-aria/textfield": "^3.14.3", + "@react-aria/utils": "^3.23.2", + "@react-stately/form": "^3.0.1", + "@react-stately/numberfield": "^3.9.1", + "@react-types/button": "^3.9.2", + "@react-types/numberfield": "^3.8.1", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4429,20 +4417,20 @@ } }, "node_modules/@react-aria/overlays": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@react-aria/overlays/-/overlays-3.21.0.tgz", - "integrity": "sha512-ulE5RQP3ZUFqY6Zok4L/CCZW5HCPZeuyDEezPw4/4Y/WD6TjGZ1ChbPuGsAl+X+fo/iKTpe7joN4kYrKmTb5WA==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/ssr": "^3.9.1", - "@react-aria/utils": "^3.23.1", - "@react-aria/visually-hidden": "^3.8.9", - "@react-stately/overlays": "^3.6.4", - "@react-types/button": "^3.9.1", - "@react-types/overlays": "^3.8.4", - "@react-types/shared": "^3.22.0", + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/@react-aria/overlays/-/overlays-3.21.1.tgz", + "integrity": "sha512-djEBDF+TbIIOHWWNpdm19+z8xtY8U+T+wKVQg/UZ6oWnclSqSWeGl70vu73Cg4HVBJ4hKf1SRx4Z/RN6VvH4Yw==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/ssr": "^3.9.2", + "@react-aria/utils": "^3.23.2", + "@react-aria/visually-hidden": "^3.8.10", + "@react-stately/overlays": "^3.6.5", + "@react-types/button": "^3.9.2", + "@react-types/overlays": "^3.8.5", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4451,15 +4439,15 @@ } }, "node_modules/@react-aria/progress": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/@react-aria/progress/-/progress-3.4.10.tgz", - "integrity": "sha512-q82LbDjimIo5a21Kg9aUYG94oFsDtpAwaQDj2YPVDt9kNie4BHOLHnHZWYk8jPoZDHMEk80jZBKWcDnk8+wWtw==", - "dependencies": { - "@react-aria/i18n": "^3.10.1", - "@react-aria/label": "^3.7.5", - "@react-aria/utils": "^3.23.1", - "@react-types/progress": "^3.5.1", - "@react-types/shared": "^3.22.0", + "version": "3.4.11", + "resolved": "https://registry.npmjs.org/@react-aria/progress/-/progress-3.4.11.tgz", + "integrity": "sha512-RePHbS15/KYFiApYLdwazwvWKsB9q0Kn5DGCSb0hqCC+k2Eui8iVVOsegswiP+xqkk/TiUCIkBEw22W3Az4kTg==", + "dependencies": { + "@react-aria/i18n": "^3.10.2", + "@react-aria/label": "^3.7.6", + "@react-aria/utils": "^3.23.2", + "@react-types/progress": "^3.5.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4467,19 +4455,19 @@ } }, "node_modules/@react-aria/radio": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@react-aria/radio/-/radio-3.10.1.tgz", - "integrity": "sha512-UEeQncLloHz/H4iwHbiBXiYLCDsMmRDkL/GMcpUCx0OaQSuKB/kJTOR0rFEMVyCiDVXx7hJ16fcSh1lXpLL9gA==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/form": "^3.0.2", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/label": "^3.7.5", - "@react-aria/utils": "^3.23.1", - "@react-stately/radio": "^3.10.1", - "@react-types/radio": "^3.7.0", - "@react-types/shared": "^3.22.0", + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/@react-aria/radio/-/radio-3.10.2.tgz", + "integrity": "sha512-CTUTR+qt3BLjmyQvKHZuVm+1kyvT72ZptOty++sowKXgJApTLdjq8so1IpaLAr8JIfzqD5I4tovsYwIQOX8log==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/form": "^3.0.3", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/label": "^3.7.6", + "@react-aria/utils": "^3.23.2", + "@react-stately/radio": "^3.10.2", + "@react-types/radio": "^3.7.1", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4487,17 +4475,17 @@ } }, "node_modules/@react-aria/searchfield": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@react-aria/searchfield/-/searchfield-3.7.2.tgz", - "integrity": "sha512-YpmvbWOgECTK9KjMYqWwSFPi57b7m0rdAQPMjB3Call0CE7tQiSP5TbwkpOa4Id8Kghm8ySV5fNkBKP2xhHxdg==", - "dependencies": { - "@react-aria/i18n": "^3.10.1", - "@react-aria/textfield": "^3.14.2", - "@react-aria/utils": "^3.23.1", - "@react-stately/searchfield": "^3.5.0", - "@react-types/button": "^3.9.1", - "@react-types/searchfield": "^3.5.2", - "@react-types/shared": "^3.22.0", + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@react-aria/searchfield/-/searchfield-3.7.3.tgz", + "integrity": "sha512-mnYI969R7tU3yMRIGmY1+peq7tmEW0W3MB/J2ImK36Obz/91tTtspHHEeFtPlQDLIyvVPB0Ucam4LIxCKPJm/Q==", + "dependencies": { + "@react-aria/i18n": "^3.10.2", + "@react-aria/textfield": "^3.14.3", + "@react-aria/utils": "^3.23.2", + "@react-stately/searchfield": "^3.5.1", + "@react-types/button": "^3.9.2", + "@react-types/searchfield": "^3.5.3", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4505,23 +4493,23 @@ } }, "node_modules/@react-aria/select": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/@react-aria/select/-/select-3.14.2.tgz", - "integrity": "sha512-8kwqzNwJI+oC8PqotElEeWF24Ae58nnyeujcM0yCnuglTGqacGqCHmAOFHb99SxxSXmNC6OppAZNmRV3kUxdLA==", - "dependencies": { - "@react-aria/form": "^3.0.2", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/label": "^3.7.5", - "@react-aria/listbox": "^3.11.4", - "@react-aria/menu": "^3.13.0", - "@react-aria/selection": "^3.17.4", - "@react-aria/utils": "^3.23.1", - "@react-aria/visually-hidden": "^3.8.9", - "@react-stately/select": "^3.6.1", - "@react-types/button": "^3.9.1", - "@react-types/select": "^3.9.1", - "@react-types/shared": "^3.22.0", + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/@react-aria/select/-/select-3.14.3.tgz", + "integrity": "sha512-9KCxI41FI+jTxEfUzRsMdJsZvjkCuuhL4UHig8MZXtXs0nsi7Ir3ezUDQ9m5MSG+ooBYM/CA9DyLDvo5Ioef+g==", + "dependencies": { + "@react-aria/form": "^3.0.3", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/label": "^3.7.6", + "@react-aria/listbox": "^3.11.5", + "@react-aria/menu": "^3.13.1", + "@react-aria/selection": "^3.17.5", + "@react-aria/utils": "^3.23.2", + "@react-aria/visually-hidden": "^3.8.10", + "@react-stately/select": "^3.6.2", + "@react-types/button": "^3.9.2", + "@react-types/select": "^3.9.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4530,16 +4518,16 @@ } }, "node_modules/@react-aria/selection": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/@react-aria/selection/-/selection-3.17.4.tgz", - "integrity": "sha512-COq5qGbJebn9Wbo/3UGluhYLK4uUijuacew/7PgLArHIjiqPvK7kqcQA5Kdwrxzv4Z94f2x9fVf8Uf65zB543Q==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-stately/selection": "^3.14.2", - "@react-types/shared": "^3.22.0", + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/@react-aria/selection/-/selection-3.17.5.tgz", + "integrity": "sha512-gO5jBUkc7WdkiFMlWt3x9pTSuj3Yeegsxfo44qU5NPlKrnGtPRZDWrlACNgkDHu645RNNPhlyoX0C+G8mUg1xA==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-stately/selection": "^3.14.3", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4548,12 +4536,12 @@ } }, "node_modules/@react-aria/separator": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/@react-aria/separator/-/separator-3.3.10.tgz", - "integrity": "sha512-/wM8yOY0XPWDJXbyiKo9lgDTePDCa0ZDoXAn+Hg4dwh6lQLBmEQBugN5sVJJ4BBdbyQbcRZcI2+eM4DfcU2kNg==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/@react-aria/separator/-/separator-3.3.11.tgz", + "integrity": "sha512-UTla+3P2pELpP73WSfbwZgP1y1wODFBQbEOHnUxxO8ocyaUyQLJdvc07bBLLpPoyutlggRG0v9ACo0Rui7AjOg==", "dependencies": { - "@react-aria/utils": "^3.23.1", - "@react-types/shared": "^3.22.0", + "@react-aria/utils": "^3.23.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4561,18 +4549,18 @@ } }, "node_modules/@react-aria/slider": { - "version": "3.7.5", - "resolved": "https://registry.npmjs.org/@react-aria/slider/-/slider-3.7.5.tgz", - "integrity": "sha512-AV0ZDWmdO8mvh3wS09uOAoenRCxkqaN7ZYb0rQLRvP2vhZJzaJPaN7/0f9/TLnvrZmmUspm4IqXD+Ci9q49lWA==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/label": "^3.7.5", - "@react-aria/utils": "^3.23.1", - "@react-stately/slider": "^3.5.1", - "@react-types/shared": "^3.22.0", - "@react-types/slider": "^3.7.0", + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/@react-aria/slider/-/slider-3.7.6.tgz", + "integrity": "sha512-ZeZhyHzhk9gxGuThPKgX2K3RKsxPxsFig1iYoJvqP8485NtHYQIPht2YcpEKA9siLxGF0DR9VCfouVhSoW0AEA==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/label": "^3.7.6", + "@react-aria/utils": "^3.23.2", + "@react-stately/slider": "^3.5.2", + "@react-types/shared": "^3.22.1", + "@react-types/slider": "^3.7.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4580,15 +4568,15 @@ } }, "node_modules/@react-aria/spinbutton": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/@react-aria/spinbutton/-/spinbutton-3.6.2.tgz", - "integrity": "sha512-ivrSmyjm/FSEBBD/Io3cwad88Kx8CiulLXZNJPvvEsTrsowDIyaLZ55oTrNIXXQZJY4Ns9ccaQUwD+QGBX/eIQ==", - "dependencies": { - "@react-aria/i18n": "^3.10.1", - "@react-aria/live-announcer": "^3.3.1", - "@react-aria/utils": "^3.23.1", - "@react-types/button": "^3.9.1", - "@react-types/shared": "^3.22.0", + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@react-aria/spinbutton/-/spinbutton-3.6.3.tgz", + "integrity": "sha512-IlfhRu/pc9zOt2C5zSEB7NmmzddvWisGx2iGzw8BwIKMD+cN3uy+Qwp+sG6Z/JzFEBN0F6Mxm3l5lhbiqjpICQ==", + "dependencies": { + "@react-aria/i18n": "^3.10.2", + "@react-aria/live-announcer": "^3.3.2", + "@react-aria/utils": "^3.23.2", + "@react-types/button": "^3.9.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4597,9 +4585,9 @@ } }, "node_modules/@react-aria/ssr": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.1.tgz", - "integrity": "sha512-NqzkLFP8ZVI4GSorS0AYljC13QW2sc8bDqJOkBvkAt3M8gbcAXJWVRGtZBCRscki9RZF+rNlnPdg0G0jYkhJcg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.2.tgz", + "integrity": "sha512-0gKkgDYdnq1w+ey8KzG9l+H5Z821qh9vVjztk55rUg71vTk/Eaebeir+WtzcLLwTjw3m/asIjx8Y59y1lJZhBw==", "dependencies": { "@swc/helpers": "^0.5.0" }, @@ -4611,13 +4599,13 @@ } }, "node_modules/@react-aria/switch": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@react-aria/switch/-/switch-3.6.1.tgz", - "integrity": "sha512-WaDJ4KJlrYvkLK4h3/KRGRfHlYjPmqDEh83ya0wtkZbKZte7/2+a1bnpwcrQeTmuDVSPthiieL1dQggg8sOuxA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@react-aria/switch/-/switch-3.6.2.tgz", + "integrity": "sha512-X5m/omyhXK+V/vhJFsHuRs2zmt9Asa/RuzlldbXnWohLdeuHMPgQnV8C9hg3f+sRi3sh9UUZ64H61pCtRoZNwg==", "dependencies": { - "@react-aria/toggle": "^3.10.1", - "@react-stately/toggle": "^3.7.1", - "@react-types/switch": "^3.5.0", + "@react-aria/toggle": "^3.10.2", + "@react-stately/toggle": "^3.7.2", + "@react-types/switch": "^3.5.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4625,25 +4613,25 @@ } }, "node_modules/@react-aria/table": { - "version": "3.13.4", - "resolved": "https://registry.npmjs.org/@react-aria/table/-/table-3.13.4.tgz", - "integrity": "sha512-dhYumqv2kCH3LOtmXJlq0Qc3VVFwaDaHaTV6xgen2EZxUZQa3mZDoCoxSu8/w3LvKwQAk+NAOqmrOHzMMyOlOQ==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/grid": "^3.8.7", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/live-announcer": "^3.3.1", - "@react-aria/utils": "^3.23.1", - "@react-aria/visually-hidden": "^3.8.9", - "@react-stately/collections": "^3.10.4", - "@react-stately/flags": "^3.0.0", - "@react-stately/table": "^3.11.5", - "@react-stately/virtualizer": "^3.6.7", - "@react-types/checkbox": "^3.7.0", - "@react-types/grid": "^3.2.3", - "@react-types/shared": "^3.22.0", - "@react-types/table": "^3.9.2", + "version": "3.13.5", + "resolved": "https://registry.npmjs.org/@react-aria/table/-/table-3.13.5.tgz", + "integrity": "sha512-P2nHEDk2CCoEbMFKNCyBC9qvmv7F/IXARDt/7z/J4mKFgU2iNSK+/zw6yrb38q33Zlk8hDaqSYNxHlMrh+/1MQ==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/grid": "^3.8.8", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/live-announcer": "^3.3.2", + "@react-aria/utils": "^3.23.2", + "@react-aria/visually-hidden": "^3.8.10", + "@react-stately/collections": "^3.10.5", + "@react-stately/flags": "^3.0.1", + "@react-stately/table": "^3.11.6", + "@react-stately/virtualizer": "^3.6.8", + "@react-types/checkbox": "^3.7.1", + "@react-types/grid": "^3.2.4", + "@react-types/shared": "^3.22.1", + "@react-types/table": "^3.9.3", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4652,17 +4640,17 @@ } }, "node_modules/@react-aria/tabs": { - "version": "3.8.4", - "resolved": "https://registry.npmjs.org/@react-aria/tabs/-/tabs-3.8.4.tgz", - "integrity": "sha512-q8c3QorgVqi9hxa1FisWuZ5rRkS0EyzynmJ2hNhyznIlGuMP30HsnsTIf1Y+hNNj3ofL04Xc5BkJpLrQvsBPAQ==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/selection": "^3.17.4", - "@react-aria/utils": "^3.23.1", - "@react-stately/tabs": "^3.6.3", - "@react-types/shared": "^3.22.0", - "@react-types/tabs": "^3.3.4", + "version": "3.8.5", + "resolved": "https://registry.npmjs.org/@react-aria/tabs/-/tabs-3.8.5.tgz", + "integrity": "sha512-Jvt33/W+66n5oCxVwHAYarJ3Fit61vULiPcG7uTez0Mf11cq/C72wOrj+ZuNz6PTLTi2veBNQ7MauY72SnOjRg==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/selection": "^3.17.5", + "@react-aria/utils": "^3.23.2", + "@react-stately/tabs": "^3.6.4", + "@react-types/shared": "^3.22.1", + "@react-types/tabs": "^3.3.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4671,19 +4659,19 @@ } }, "node_modules/@react-aria/tag": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/@react-aria/tag/-/tag-3.3.2.tgz", - "integrity": "sha512-AWgwRBwhhrmfdvvV7cSp3VTsLkw1e04IKQCKss3hF7zd75T+LfwvCa8g4CUDsFXx3lvIh0rB/6evhBfn3D0rDw==", - "dependencies": { - "@react-aria/gridlist": "^3.7.4", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/label": "^3.7.5", - "@react-aria/selection": "^3.17.4", - "@react-aria/utils": "^3.23.1", - "@react-stately/list": "^3.10.2", - "@react-types/button": "^3.9.1", - "@react-types/shared": "^3.22.0", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@react-aria/tag/-/tag-3.3.3.tgz", + "integrity": "sha512-tlJD9qj1XcsPIZD7DVJ6tWv8t7Z87/8qkbRDx7ugNqeHso9z0WqH9ZkSt17OFUWE2IQIk3V8D3iBSOtmhXcZGQ==", + "dependencies": { + "@react-aria/gridlist": "^3.7.5", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/label": "^3.7.6", + "@react-aria/selection": "^3.17.5", + "@react-aria/utils": "^3.23.2", + "@react-stately/list": "^3.10.3", + "@react-types/button": "^3.9.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4692,18 +4680,18 @@ } }, "node_modules/@react-aria/textfield": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/@react-aria/textfield/-/textfield-3.14.2.tgz", - "integrity": "sha512-l9FulRr7Kpchy+dt0hIZ7rMwMReJrZnjeWT7iwmZWFMleEYjSuRUnmM+L82oZBY9BSwftJ5kk6vG4AP7MLBulg==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/form": "^3.0.2", - "@react-aria/label": "^3.7.5", - "@react-aria/utils": "^3.23.1", - "@react-stately/form": "^3.0.0", - "@react-stately/utils": "^3.9.0", - "@react-types/shared": "^3.22.0", - "@react-types/textfield": "^3.9.0", + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/@react-aria/textfield/-/textfield-3.14.3.tgz", + "integrity": "sha512-wPSjj/mTABspYQdahg+l5YMtEQ3m5iPCTtb5g6nR1U1rzJkvS4i5Pug6PUXeLeMz2H3ToflPWGlNOqBioAFaOQ==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/form": "^3.0.3", + "@react-aria/label": "^3.7.6", + "@react-aria/utils": "^3.23.2", + "@react-stately/form": "^3.0.1", + "@react-stately/utils": "^3.9.1", + "@react-types/shared": "^3.22.1", + "@react-types/textfield": "^3.9.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4711,15 +4699,15 @@ } }, "node_modules/@react-aria/toggle": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@react-aria/toggle/-/toggle-3.10.1.tgz", - "integrity": "sha512-Z+T/fyWvglLDMsNDCee/OF3Josntzlfq1/Iez+ShqIaSI/FgZIjglQbEFqXvM9gSGOX1fYfv9n4Ztj6DDT6J2Q==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-stately/toggle": "^3.7.1", - "@react-types/checkbox": "^3.7.0", + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/@react-aria/toggle/-/toggle-3.10.2.tgz", + "integrity": "sha512-DgitscHWgI6IFgnvp2HcMpLGX/cAn+XX9kF5RJQbRQ9NqUgruU5cEEGSOLMrEJ6zXDa2xmOiQ+kINcyNhA+JLg==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-stately/toggle": "^3.7.2", + "@react-types/checkbox": "^3.7.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4727,16 +4715,16 @@ } }, "node_modules/@react-aria/tooltip": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@react-aria/tooltip/-/tooltip-3.7.1.tgz", - "integrity": "sha512-2lf72hIw3gfQLvKU9SHkh3a/CP8GJ3MbKlPq8x0gX7444zaYII/UDqIkde1TiR2fB71I/MqKSOx6mg28B9lj4w==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-stately/tooltip": "^3.4.6", - "@react-types/shared": "^3.22.0", - "@react-types/tooltip": "^3.4.6", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@react-aria/tooltip/-/tooltip-3.7.2.tgz", + "integrity": "sha512-6jXOSGPao3gPgUQWLbH2r/jxGMqIaIKrJgfwu9TQrh+UkwwiTYW20EpEDCYY2nRFlcoi7EYAiPDSEbHCwXS7Lg==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-stately/tooltip": "^3.4.7", + "@react-types/shared": "^3.22.1", + "@react-types/tooltip": "^3.4.7", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4744,13 +4732,13 @@ } }, "node_modules/@react-aria/utils": { - "version": "3.23.1", - "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.23.1.tgz", - "integrity": "sha512-iXibf9ojqdoygbvy/++v5cKLKgjc/5ZmKV8/9u/2Hkpha1cf5Td/Z+Vl42B6giUBAsuDio5kuZYfYC7Uk+t8ag==", + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.23.2.tgz", + "integrity": "sha512-yznR9jJ0GG+YJvTMZxijQwVp+ahP66DY0apZf7X+dllyN+ByEDW+yaL1ewYPIpugxVzH5P8jhnBXsIyHKN411g==", "dependencies": { - "@react-aria/ssr": "^3.9.1", - "@react-stately/utils": "^3.9.0", - "@react-types/shared": "^3.22.0", + "@react-aria/ssr": "^3.9.2", + "@react-stately/utils": "^3.9.1", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -4759,15 +4747,15 @@ } }, "node_modules/@react-aria/virtualizer": { - "version": "3.9.9", - "resolved": "https://registry.npmjs.org/@react-aria/virtualizer/-/virtualizer-3.9.9.tgz", - "integrity": "sha512-nso567w/vEd5wRLqF2tJF24XYx9wnf0NxrJZW/26xUVSUBgIy4QkYjxb2ylWQCLiRe8iA6xfC27dyvJVeQXwUg==", - "dependencies": { - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-stately/virtualizer": "^3.6.7", - "@react-types/shared": "^3.22.0", + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/@react-aria/virtualizer/-/virtualizer-3.9.10.tgz", + "integrity": "sha512-oDvGgexK6phB9XECWvAaKTq/nRKxHjmJSiZ2gv9j72JFoky4iVEHKAV6Qnar0VBcEpk16JcJVI/wf1xr9F+sjQ==", + "dependencies": { + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-stately/virtualizer": "^3.6.8", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4776,13 +4764,13 @@ } }, "node_modules/@react-aria/visually-hidden": { - "version": "3.8.9", - "resolved": "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.8.9.tgz", - "integrity": "sha512-yUUj4M8YjtwzS45n0nB4bCKCYd3Dl6wmCZKAcAqZG9hMh6DUAcSp2xqYKOAzvNrtZZmAoopgMP4UC9hKlY6swQ==", + "version": "3.8.10", + "resolved": "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.8.10.tgz", + "integrity": "sha512-np8c4wxdbE7ZrMv/bnjwEfpX0/nkWy9sELEb0sK8n4+HJ+WycoXXrVxBUb9tXgL/GCx5ReeDQChjQWwajm/z3A==", "dependencies": { - "@react-aria/interactions": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-types/shared": "^3.22.0", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4817,24 +4805,24 @@ "integrity": "sha512-x9ibmsP0ZVqzyCo1Pitbw+4b6iEXRw/r1TCy3vOUR3eKrzWLnHYZMR325BkZW2r8fnuWE/V3Fp4QZOP9qYORCw==" }, "node_modules/@react-spectrum/actionbar": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/@react-spectrum/actionbar/-/actionbar-3.4.2.tgz", - "integrity": "sha512-7vgDP/Q+GbkZN5bMspqUnpVBXDysaznN15s0ZtShOwfWSqbBFHFzMSKcH7IzQoF1C49TWOKwy6LEOGAsfG0RnA==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/live-announcer": "^3.3.1", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/actiongroup": "^3.10.2", - "@react-spectrum/button": "^3.16.1", - "@react-spectrum/overlays": "^5.5.4", - "@react-spectrum/text": "^3.5.2", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/collections": "^3.10.4", - "@react-types/actionbar": "^3.1.4", - "@react-types/shared": "^3.22.0", - "@spectrum-icons/ui": "^3.6.4", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@react-spectrum/actionbar/-/actionbar-3.4.3.tgz", + "integrity": "sha512-LIg3a5z0bnFIkA1teaGUo/RdT4ZKPpUUF0RxPSm0nHWEzolSgD7BN4ijK5UxsDLA2cfNxv78s+vwHHKkKnsjSA==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/live-announcer": "^3.3.2", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/actiongroup": "^3.10.3", + "@react-spectrum/button": "^3.16.2", + "@react-spectrum/overlays": "^5.5.5", + "@react-spectrum/text": "^3.5.3", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/collections": "^3.10.5", + "@react-types/actionbar": "^3.1.5", + "@react-types/shared": "^3.22.1", + "@spectrum-icons/ui": "^3.6.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4844,25 +4832,25 @@ } }, "node_modules/@react-spectrum/actiongroup": { - "version": "3.10.2", - "resolved": "https://registry.npmjs.org/@react-spectrum/actiongroup/-/actiongroup-3.10.2.tgz", - "integrity": "sha512-8IslvMwN0c0+PaZfn6zdQokefpUynyQjUPOJMrDcP6CFUKrNkjEexxwipSmgw0OGb1AdGCzCAXpqNXGS0OwBVw==", - "dependencies": { - "@react-aria/actiongroup": "^3.7.2", - "@react-aria/focus": "^3.16.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/button": "^3.16.1", - "@react-spectrum/menu": "^3.18.0", - "@react-spectrum/text": "^3.5.2", - "@react-spectrum/tooltip": "^3.6.4", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/collections": "^3.10.4", - "@react-stately/list": "^3.10.2", - "@react-types/actiongroup": "^3.4.6", - "@react-types/shared": "^3.22.0", - "@spectrum-icons/ui": "^3.6.4", - "@spectrum-icons/workflow": "^4.2.9", + "version": "3.10.3", + "resolved": "https://registry.npmjs.org/@react-spectrum/actiongroup/-/actiongroup-3.10.3.tgz", + "integrity": "sha512-VJASE+Y75Q885z9mx7CVELrX8PuZPbRnGFQnkoRnwZOTpMVZM6wQxA4IcAfsFVvaVIpHgBwtQTI1Ib+gAdtqgw==", + "dependencies": { + "@react-aria/actiongroup": "^3.7.3", + "@react-aria/focus": "^3.16.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/button": "^3.16.2", + "@react-spectrum/menu": "^3.18.1", + "@react-spectrum/text": "^3.5.3", + "@react-spectrum/tooltip": "^3.6.5", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/collections": "^3.10.5", + "@react-stately/list": "^3.10.3", + "@react-types/actiongroup": "^3.4.7", + "@react-types/shared": "^3.22.1", + "@spectrum-icons/ui": "^3.6.5", + "@spectrum-icons/workflow": "^4.2.10", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4872,14 +4860,14 @@ } }, "node_modules/@react-spectrum/avatar": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@react-spectrum/avatar/-/avatar-3.0.9.tgz", - "integrity": "sha512-zGgfK7tAFOJ9FvJdlvpi++L6YF/RFBONlfJ/acCcls/ki+spzzlmmtml/RFzzO//4vsw/5iayfknWsYdSAl/2g==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@react-spectrum/avatar/-/avatar-3.0.10.tgz", + "integrity": "sha512-PvsCTTcjNN7QSsa3iCc2UF5LeQCwFNaiR0/xvpk+/ViP1wVq+xFR1tfSrbAq7TAF1B3NQNfI+wepy2ol5l8X2g==", "dependencies": { - "@react-aria/utils": "^3.23.1", - "@react-spectrum/utils": "^3.11.4", - "@react-types/avatar": "^3.0.4", - "@react-types/shared": "^3.22.0", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/utils": "^3.11.5", + "@react-types/avatar": "^3.0.5", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4888,15 +4876,15 @@ } }, "node_modules/@react-spectrum/badge": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/@react-spectrum/badge/-/badge-3.1.10.tgz", - "integrity": "sha512-XsdwwbtIP0rxI2tRGrA3Nf46GSsekoO0tt1A/69P7dU230LkxTdILMLABCblP/lb6gxa1ksXkbWvB93L9ScDzw==", - "dependencies": { - "@react-aria/utils": "^3.23.1", - "@react-spectrum/text": "^3.5.2", - "@react-spectrum/utils": "^3.11.4", - "@react-types/badge": "^3.1.6", - "@react-types/shared": "^3.22.0", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@react-spectrum/badge/-/badge-3.1.11.tgz", + "integrity": "sha512-YOuUBdWmqDQQrNI0uUpazWv/qYmFeDCsJVfQnl/K4J0A6/x7wuvz3iLPJKYuvmqG45/I+WXYFFaNuWOm4jCMzA==", + "dependencies": { + "@react-aria/utils": "^3.23.2", + "@react-spectrum/text": "^3.5.3", + "@react-spectrum/utils": "^3.11.5", + "@react-types/badge": "^3.1.7", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4905,22 +4893,22 @@ } }, "node_modules/@react-spectrum/breadcrumbs": { - "version": "3.9.4", - "resolved": "https://registry.npmjs.org/@react-spectrum/breadcrumbs/-/breadcrumbs-3.9.4.tgz", - "integrity": "sha512-IYo+N6hp6FjZFYZu3eD2tiGDNX+XXluxVKRVX0wCKo7jjylRrEUhaDe0vJ9OZjtmU3RRUzczUHmsnn4maSuAqw==", - "dependencies": { - "@react-aria/breadcrumbs": "^3.5.10", - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/button": "^3.16.1", - "@react-spectrum/menu": "^3.18.0", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/collections": "^3.10.4", - "@react-types/breadcrumbs": "^3.7.2", - "@react-types/shared": "^3.22.0", - "@spectrum-icons/ui": "^3.6.4", + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/@react-spectrum/breadcrumbs/-/breadcrumbs-3.9.5.tgz", + "integrity": "sha512-MV1b077f189biweuI8H1/D6F7Nwrao0phYzAKqjaTa8bhXf180ej3VhtEEhrSyEhhMrHG3pPzCCbNUn2VMXDlg==", + "dependencies": { + "@react-aria/breadcrumbs": "^3.5.11", + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/button": "^3.16.2", + "@react-spectrum/menu": "^3.18.1", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/collections": "^3.10.5", + "@react-types/breadcrumbs": "^3.7.3", + "@react-types/shared": "^3.22.1", + "@spectrum-icons/ui": "^3.6.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4930,22 +4918,22 @@ } }, "node_modules/@react-spectrum/button": { - "version": "3.16.1", - "resolved": "https://registry.npmjs.org/@react-spectrum/button/-/button-3.16.1.tgz", - "integrity": "sha512-B1U4Mwq1BMId4pWJdDG0sgHDC05Ccu2ofoe3iR2444A4yzKpKC5OFr4lZXlevkxrwSLPwCmIBvpkGHxZswvJSA==", - "dependencies": { - "@react-aria/button": "^3.9.2", - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/progress": "^3.7.4", - "@react-spectrum/text": "^3.5.2", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/toggle": "^3.7.1", - "@react-types/button": "^3.9.1", - "@react-types/shared": "^3.22.0", - "@spectrum-icons/ui": "^3.6.4", + "version": "3.16.2", + "resolved": "https://registry.npmjs.org/@react-spectrum/button/-/button-3.16.2.tgz", + "integrity": "sha512-T0B4EUeAAfsocTMZpfKYIsPMIbuwjB1+hfbZyBBvWt8gerLiEiPAwt6+ga1YzV7C6aAz2FPeTT+zd/RxouDTPw==", + "dependencies": { + "@react-aria/button": "^3.9.3", + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/progress": "^3.7.5", + "@react-spectrum/text": "^3.5.3", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/toggle": "^3.7.2", + "@react-types/button": "^3.9.2", + "@react-types/shared": "^3.22.1", + "@spectrum-icons/ui": "^3.6.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4954,14 +4942,14 @@ } }, "node_modules/@react-spectrum/buttongroup": { - "version": "3.6.10", - "resolved": "https://registry.npmjs.org/@react-spectrum/buttongroup/-/buttongroup-3.6.10.tgz", - "integrity": "sha512-UunM+1u8Fwc5K6Th07ld2JbbP5PEpwt8ezQ+imA2YIeGXS+uKDi36ZCO0BM0VqZ92bd9k2UarZQwza4oRuIWYw==", - "dependencies": { - "@react-aria/utils": "^3.23.1", - "@react-spectrum/utils": "^3.11.4", - "@react-types/buttongroup": "^3.3.6", - "@react-types/shared": "^3.22.0", + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/@react-spectrum/buttongroup/-/buttongroup-3.6.11.tgz", + "integrity": "sha512-yJv6yBZRLIPYdOAch4FVhdrI0xZz5PPuLiSA6HF/9LlIimALj0qBgCsbQPPThz/UV8+8Y1F76wQUsDcj+iub/A==", + "dependencies": { + "@react-aria/utils": "^3.23.2", + "@react-spectrum/utils": "^3.11.5", + "@react-types/buttongroup": "^3.3.7", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4970,25 +4958,25 @@ } }, "node_modules/@react-spectrum/calendar": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/@react-spectrum/calendar/-/calendar-3.4.6.tgz", - "integrity": "sha512-uwBOyctISMNgZwpC33tvi5ResoKkcwRmUt8ifQwaYPxUHfUJCja30IQbsIbQ3EcWFkIJsdWgyqOGIhD04XNlPg==", - "dependencies": { - "@internationalized/date": "^3.5.1", - "@react-aria/calendar": "^3.5.5", - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-aria/visually-hidden": "^3.8.9", - "@react-spectrum/button": "^3.16.1", - "@react-spectrum/label": "^3.16.3", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/calendar": "^3.4.3", - "@react-types/button": "^3.9.1", - "@react-types/calendar": "^3.4.3", - "@react-types/shared": "^3.22.0", - "@spectrum-icons/ui": "^3.6.4", + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/@react-spectrum/calendar/-/calendar-3.4.7.tgz", + "integrity": "sha512-eBH8SAHHbhprbzk445wnNrW80bnm7Kv5rwmcDBd7/FGb5EhWnQgcQtBo3z79dpCXCl8UtpLsih3eDV9QQSjIDA==", + "dependencies": { + "@internationalized/date": "^3.5.2", + "@react-aria/calendar": "^3.5.6", + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-aria/visually-hidden": "^3.8.10", + "@react-spectrum/button": "^3.16.2", + "@react-spectrum/label": "^3.16.4", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/calendar": "^3.4.4", + "@react-types/button": "^3.9.2", + "@react-types/calendar": "^3.4.4", + "@react-types/shared": "^3.22.1", + "@spectrum-icons/ui": "^3.6.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4998,21 +4986,21 @@ } }, "node_modules/@react-spectrum/checkbox": { - "version": "3.9.3", - "resolved": "https://registry.npmjs.org/@react-spectrum/checkbox/-/checkbox-3.9.3.tgz", - "integrity": "sha512-cho26UkAaIldsmHxueLUyjI6LJVAW+8n+M+wibZTW2QAI456G/NS9+bUC1ZRbK+d49meHOk9y6rcKUnzcTq5jg==", - "dependencies": { - "@react-aria/checkbox": "^3.14.0", - "@react-aria/focus": "^3.16.1", - "@react-aria/interactions": "^3.21.0", - "@react-spectrum/form": "^3.7.3", - "@react-spectrum/label": "^3.16.3", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/checkbox": "^3.6.2", - "@react-stately/toggle": "^3.7.1", - "@react-types/checkbox": "^3.7.0", - "@react-types/shared": "^3.22.0", - "@spectrum-icons/ui": "^3.6.4", + "version": "3.9.4", + "resolved": "https://registry.npmjs.org/@react-spectrum/checkbox/-/checkbox-3.9.4.tgz", + "integrity": "sha512-PzUaSza13wh7YipWJLd/0q/nkAnEnxso7hdvMzDLYcw0iKhXNTM2fUoouUuY1SsbithlF2GS5REYyMpQ4FNO3g==", + "dependencies": { + "@react-aria/checkbox": "^3.14.1", + "@react-aria/focus": "^3.16.2", + "@react-aria/interactions": "^3.21.1", + "@react-spectrum/form": "^3.7.4", + "@react-spectrum/label": "^3.16.4", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/checkbox": "^3.6.3", + "@react-stately/toggle": "^3.7.2", + "@react-types/checkbox": "^3.7.1", + "@react-types/shared": "^3.22.1", + "@spectrum-icons/ui": "^3.6.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5021,34 +5009,34 @@ } }, "node_modules/@react-spectrum/combobox": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@react-spectrum/combobox/-/combobox-3.12.2.tgz", - "integrity": "sha512-w3z9myQ/NYpxh0UQoVhWB9b1QV3wguR+bb3KdBBp3ECgGAOsN7eSe5A+pIWFAjgbBxHWK/JuY0agFs9IWkauOA==", - "dependencies": { - "@react-aria/button": "^3.9.2", - "@react-aria/combobox": "^3.8.3", - "@react-aria/dialog": "^3.5.11", - "@react-aria/focus": "^3.16.1", - "@react-aria/form": "^3.0.2", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/label": "^3.7.5", - "@react-aria/overlays": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/button": "^3.16.1", - "@react-spectrum/form": "^3.7.3", - "@react-spectrum/label": "^3.16.3", - "@react-spectrum/listbox": "^3.12.6", - "@react-spectrum/overlays": "^5.5.4", - "@react-spectrum/progress": "^3.7.4", - "@react-spectrum/textfield": "^3.11.3", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/collections": "^3.10.4", - "@react-stately/combobox": "^3.8.1", - "@react-types/button": "^3.9.1", - "@react-types/combobox": "^3.10.0", - "@react-types/shared": "^3.22.0", - "@spectrum-icons/ui": "^3.6.4", + "version": "3.12.3", + "resolved": "https://registry.npmjs.org/@react-spectrum/combobox/-/combobox-3.12.3.tgz", + "integrity": "sha512-hskwbdqXSSNEBRYTn3XESSnLGjELU4Lfht3GkZCvcQt02TVvu9NMETSkVe4lwCYV2hwXtPFGyl3jXvmA3MQurQ==", + "dependencies": { + "@react-aria/button": "^3.9.3", + "@react-aria/combobox": "^3.8.4", + "@react-aria/dialog": "^3.5.12", + "@react-aria/focus": "^3.16.2", + "@react-aria/form": "^3.0.3", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/label": "^3.7.6", + "@react-aria/overlays": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/button": "^3.16.2", + "@react-spectrum/form": "^3.7.4", + "@react-spectrum/label": "^3.16.4", + "@react-spectrum/listbox": "^3.12.7", + "@react-spectrum/overlays": "^5.5.5", + "@react-spectrum/progress": "^3.7.5", + "@react-spectrum/textfield": "^3.11.4", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/collections": "^3.10.5", + "@react-stately/combobox": "^3.8.2", + "@react-types/button": "^3.9.2", + "@react-types/combobox": "^3.10.1", + "@react-types/shared": "^3.22.1", + "@spectrum-icons/ui": "^3.6.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5058,18 +5046,18 @@ } }, "node_modules/@react-spectrum/contextualhelp": { - "version": "3.6.8", - "resolved": "https://registry.npmjs.org/@react-spectrum/contextualhelp/-/contextualhelp-3.6.8.tgz", - "integrity": "sha512-3o1zCtDeDd3KGoKDS8uAdKcbUke1FPMErjPjhU/viKR/RY2uA2pjpPBpLSLKG3jV2IWOojAnCPvdOk3FVB7dKQ==", - "dependencies": { - "@react-aria/i18n": "^3.10.1", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/button": "^3.16.1", - "@react-spectrum/dialog": "^3.8.8", - "@react-spectrum/utils": "^3.11.4", - "@react-types/contextualhelp": "^3.2.7", - "@react-types/shared": "^3.22.0", - "@spectrum-icons/workflow": "^4.2.9", + "version": "3.6.9", + "resolved": "https://registry.npmjs.org/@react-spectrum/contextualhelp/-/contextualhelp-3.6.9.tgz", + "integrity": "sha512-M0GUmZSLWm6pBAqy0Wwv1srlUPxBSvhQxTxvxtBcRSQwCIE1BcnQ6VaJxlx6n+Ocr14GwYH6MTpD1ZLMUvWeiA==", + "dependencies": { + "@react-aria/i18n": "^3.10.2", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/button": "^3.16.2", + "@react-spectrum/dialog": "^3.8.9", + "@react-spectrum/utils": "^3.11.5", + "@react-types/contextualhelp": "^3.2.8", + "@react-types/shared": "^3.22.1", + "@spectrum-icons/workflow": "^4.2.10", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5079,29 +5067,29 @@ } }, "node_modules/@react-spectrum/datepicker": { - "version": "3.9.3", - "resolved": "https://registry.npmjs.org/@react-spectrum/datepicker/-/datepicker-3.9.3.tgz", - "integrity": "sha512-d8JCrgF7UyET+7tfaNKO+7/vTZ6LDgUqQ7yfMorh/IdM9o8PH1IpRLQlYY3E2o9PFGiP90raI37JEoeoLd0Rwg==", - "dependencies": { - "@internationalized/date": "^3.5.1", - "@react-aria/datepicker": "^3.9.2", - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/button": "^3.16.1", - "@react-spectrum/calendar": "^3.4.6", - "@react-spectrum/dialog": "^3.8.8", - "@react-spectrum/form": "^3.7.3", - "@react-spectrum/label": "^3.16.3", - "@react-spectrum/layout": "^3.6.2", - "@react-spectrum/utils": "^3.11.4", - "@react-spectrum/view": "^3.6.7", - "@react-stately/datepicker": "^3.9.1", - "@react-types/datepicker": "^3.7.1", - "@react-types/shared": "^3.22.0", - "@spectrum-icons/ui": "^3.6.4", - "@spectrum-icons/workflow": "^4.2.9", + "version": "3.9.4", + "resolved": "https://registry.npmjs.org/@react-spectrum/datepicker/-/datepicker-3.9.4.tgz", + "integrity": "sha512-NyFIH68WqbGajBMe/UMxZDwNwaPL/AKJeLC9CY+GcLp4uncWjI42LdcoBPSQFoEJHLtJlLhx+r7qWO/PMOhg3Q==", + "dependencies": { + "@internationalized/date": "^3.5.2", + "@react-aria/datepicker": "^3.9.3", + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/button": "^3.16.2", + "@react-spectrum/calendar": "^3.4.7", + "@react-spectrum/dialog": "^3.8.9", + "@react-spectrum/form": "^3.7.4", + "@react-spectrum/label": "^3.16.4", + "@react-spectrum/layout": "^3.6.3", + "@react-spectrum/utils": "^3.11.5", + "@react-spectrum/view": "^3.6.8", + "@react-stately/datepicker": "^3.9.2", + "@react-types/datepicker": "^3.7.2", + "@react-types/shared": "^3.22.1", + "@spectrum-icons/ui": "^3.6.5", + "@spectrum-icons/workflow": "^4.2.10", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5111,28 +5099,28 @@ } }, "node_modules/@react-spectrum/dialog": { - "version": "3.8.8", - "resolved": "https://registry.npmjs.org/@react-spectrum/dialog/-/dialog-3.8.8.tgz", - "integrity": "sha512-4FJG/B287UKh67+3QQfJ6ZoTS0PSZ+H7DTbtRgS0+t47EL8R1z09LsPSLysB7s9ZUUTvYgYfUqCJwADHipe/ng==", - "dependencies": { - "@react-aria/dialog": "^3.5.11", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/overlays": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/button": "^3.16.1", - "@react-spectrum/buttongroup": "^3.6.10", - "@react-spectrum/divider": "^3.5.10", - "@react-spectrum/layout": "^3.6.2", - "@react-spectrum/overlays": "^5.5.4", - "@react-spectrum/text": "^3.5.2", - "@react-spectrum/utils": "^3.11.4", - "@react-spectrum/view": "^3.6.7", - "@react-stately/overlays": "^3.6.4", - "@react-types/button": "^3.9.1", - "@react-types/dialog": "^3.5.7", - "@react-types/shared": "^3.22.0", - "@spectrum-icons/ui": "^3.6.4", + "version": "3.8.9", + "resolved": "https://registry.npmjs.org/@react-spectrum/dialog/-/dialog-3.8.9.tgz", + "integrity": "sha512-CxyARi0qYOJi24YVqXZp7tHVreYQoYc7+VBZzcn8dTbIL1CSxcSGbRGXOpHiaAejZ9/3lPm/PTbrWrKUBLbckA==", + "dependencies": { + "@react-aria/dialog": "^3.5.12", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/overlays": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/button": "^3.16.2", + "@react-spectrum/buttongroup": "^3.6.11", + "@react-spectrum/divider": "^3.5.11", + "@react-spectrum/layout": "^3.6.3", + "@react-spectrum/overlays": "^5.5.5", + "@react-spectrum/text": "^3.5.3", + "@react-spectrum/utils": "^3.11.5", + "@react-spectrum/view": "^3.6.8", + "@react-stately/overlays": "^3.6.5", + "@react-types/button": "^3.9.2", + "@react-types/dialog": "^3.5.8", + "@react-types/shared": "^3.22.1", + "@spectrum-icons/ui": "^3.6.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5142,14 +5130,14 @@ } }, "node_modules/@react-spectrum/divider": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@react-spectrum/divider/-/divider-3.5.10.tgz", - "integrity": "sha512-KcvVGd0fKwsveD7JPtz6DY/VBzI/kRWqr9kX7tC5dhSB/ob5C9EPABePQk1ei2C02/VX7GUF5zpL1PxpRZlxOg==", - "dependencies": { - "@react-aria/separator": "^3.3.10", - "@react-spectrum/utils": "^3.11.4", - "@react-types/divider": "^3.3.6", - "@react-types/shared": "^3.22.0", + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@react-spectrum/divider/-/divider-3.5.11.tgz", + "integrity": "sha512-u6pyqBEc4JRpntF+KGuzmkzn+rJh04kfvjJ3Tx4F9IucaY8xCfglhunf6/yvRqQB0VaMdlxKy5BGhHgBJzUBiA==", + "dependencies": { + "@react-aria/separator": "^3.3.11", + "@react-spectrum/utils": "^3.11.5", + "@react-types/divider": "^3.3.7", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5157,13 +5145,13 @@ } }, "node_modules/@react-spectrum/dnd": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/@react-spectrum/dnd/-/dnd-3.3.7.tgz", - "integrity": "sha512-PxODjyRbBLvHmE8ivsvm8BL+pkmyyG1HhlqvxFdlYq6wkWNwINuMBvn531B5AgJb2wwz6jKZ2PSAxegTxaxFrw==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/@react-spectrum/dnd/-/dnd-3.3.8.tgz", + "integrity": "sha512-GfLqduIBpH2LArBsFpNa4i9cYeFg7lJpqwrLVJRl96DbhdXEcwt9a4tqvsegkqKn6KPHDPG7uTX0OqPoQJluXQ==", "dependencies": { - "@react-aria/dnd": "^3.5.2", - "@react-stately/dnd": "^3.2.7", - "@react-types/shared": "^3.22.0", + "@react-aria/dnd": "^3.5.3", + "@react-stately/dnd": "^3.2.8", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5173,15 +5161,15 @@ } }, "node_modules/@react-spectrum/form": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/@react-spectrum/form/-/form-3.7.3.tgz", - "integrity": "sha512-KYnRXwYPpEnFLxLMm2GQwXwA3RvNNilLdLykksH2N0x30YYKU+QCU+6RMVKv1jpTSTXdFK8q+pjXMpmbEDib3g==", - "dependencies": { - "@react-aria/utils": "^3.23.1", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/form": "^3.0.0", - "@react-types/form": "^3.7.1", - "@react-types/shared": "^3.22.0", + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@react-spectrum/form/-/form-3.7.4.tgz", + "integrity": "sha512-xAS6vFM6dzKJc7gkC8Qy76VXLxZ9VqPZq4xxQeySvsO8pOujTFCL97QkS0mDjMOdpu72VDIF5JegK1Edlewr7g==", + "dependencies": { + "@react-aria/utils": "^3.23.2", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/form": "^3.0.1", + "@react-types/form": "^3.7.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5190,13 +5178,13 @@ } }, "node_modules/@react-spectrum/icon": { - "version": "3.7.10", - "resolved": "https://registry.npmjs.org/@react-spectrum/icon/-/icon-3.7.10.tgz", - "integrity": "sha512-vz5vaFeJK9trnzKCzCusHZbk62c0x7CYznBthxXUj+8vLr5VBfwHxsdJe20dcOyjEj3klA/nUTtUf2GZ6jPWEg==", + "version": "3.7.11", + "resolved": "https://registry.npmjs.org/@react-spectrum/icon/-/icon-3.7.11.tgz", + "integrity": "sha512-CTvbukq0g2oEjMqwMDx2qjfmFAv6u7/KwHRn9pGf6BUiU53Zlnl6Fjtm+c9cw8d9GcwlXyIWYBMIKyMm4+7g5A==", "dependencies": { - "@react-aria/utils": "^3.23.1", - "@react-spectrum/utils": "^3.11.4", - "@react-types/shared": "^3.22.0", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/utils": "^3.11.5", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5205,15 +5193,15 @@ } }, "node_modules/@react-spectrum/illustratedmessage": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/@react-spectrum/illustratedmessage/-/illustratedmessage-3.4.10.tgz", - "integrity": "sha512-Kl6MYZ2FYsXT9/G+VZ2fwZIENhWtVEGiXLqBww7oeSUw1S9HuCQU4xhvp1Jln3/4RUihEiaKbCukJtzwSIohBA==", - "dependencies": { - "@react-aria/utils": "^3.23.1", - "@react-spectrum/layout": "^3.6.2", - "@react-spectrum/utils": "^3.11.4", - "@react-types/illustratedmessage": "^3.3.6", - "@react-types/shared": "^3.22.0", + "version": "3.4.11", + "resolved": "https://registry.npmjs.org/@react-spectrum/illustratedmessage/-/illustratedmessage-3.4.11.tgz", + "integrity": "sha512-KJdcF+YY2rPZBTP5P38MEQBoNLglP1QUaCmbPH8a5dSZ+wj5EsOgseFa0fxAEZ23q9Wo9Fv9P9niRq0/479KTQ==", + "dependencies": { + "@react-aria/utils": "^3.23.2", + "@react-spectrum/layout": "^3.6.3", + "@react-spectrum/utils": "^3.11.5", + "@react-types/illustratedmessage": "^3.3.7", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5222,14 +5210,14 @@ } }, "node_modules/@react-spectrum/image": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/@react-spectrum/image/-/image-3.4.10.tgz", - "integrity": "sha512-r7guBwH6sjx/GlGwT/qGYO3T+IZHczrkMKleWS1mxB/8lc75R9+4lxD7AY/DZzgyvKMvX+hJltakPMFN/eCdJA==", - "dependencies": { - "@react-aria/utils": "^3.23.1", - "@react-spectrum/utils": "^3.11.4", - "@react-types/image": "^3.3.6", - "@react-types/shared": "^3.22.0", + "version": "3.4.11", + "resolved": "https://registry.npmjs.org/@react-spectrum/image/-/image-3.4.11.tgz", + "integrity": "sha512-pzYubgkkC5Ic3eKrNlPUFPbVUTUvZ7DObmGpQvmgmG0xipmUAscYKFEBr4LhCsy/29Sm7Tz4zsGUdA2vM5eA8g==", + "dependencies": { + "@react-aria/utils": "^3.23.2", + "@react-spectrum/utils": "^3.11.5", + "@react-types/image": "^3.3.7", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5238,17 +5226,17 @@ } }, "node_modules/@react-spectrum/inlinealert": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@react-spectrum/inlinealert/-/inlinealert-3.2.2.tgz", - "integrity": "sha512-PZsHIeMsrZy66WyXmYlWd1RCISulz4Afloslg3mHHsJC6nsafbqXxDLoDZM+8BvH8eXRV0zroBG22nbY3V+5Og==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/layout": "^3.6.2", - "@react-spectrum/utils": "^3.11.4", - "@react-types/shared": "^3.22.0", - "@spectrum-icons/ui": "^3.6.4", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@react-spectrum/inlinealert/-/inlinealert-3.2.3.tgz", + "integrity": "sha512-NX1bZvmI3EOBTRWaT4dzVyFxAuePPbXASZeJ4/wAnhvWDN65rKrctn+VZW3x6ZQoZ/WkQl4qW1txjVcLHkRBWg==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/layout": "^3.6.3", + "@react-spectrum/utils": "^3.11.5", + "@react-types/shared": "^3.22.1", + "@spectrum-icons/ui": "^3.6.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5257,18 +5245,18 @@ } }, "node_modules/@react-spectrum/label": { - "version": "3.16.3", - "resolved": "https://registry.npmjs.org/@react-spectrum/label/-/label-3.16.3.tgz", - "integrity": "sha512-RR/oEICzx2GeEC2w4CV5hoodv2Iz8bmb5z8yF98190yOBGWq8ai+gq0JXYOwqBj2McRmp5AaWgecj8HhGmdV2Q==", - "dependencies": { - "@react-aria/i18n": "^3.10.1", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/form": "^3.7.3", - "@react-spectrum/layout": "^3.6.2", - "@react-spectrum/utils": "^3.11.4", - "@react-types/label": "^3.9.0", - "@react-types/shared": "^3.22.0", - "@spectrum-icons/ui": "^3.6.4", + "version": "3.16.4", + "resolved": "https://registry.npmjs.org/@react-spectrum/label/-/label-3.16.4.tgz", + "integrity": "sha512-38hk6wqUwDCyYeScF1NIaxlPaltkTRTv6/XtIkm528eilLyOMxtMGXcP0Bl7nv0oDLxDZSm9TkgXjN24SyY0KQ==", + "dependencies": { + "@react-aria/i18n": "^3.10.2", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/form": "^3.7.4", + "@react-spectrum/layout": "^3.6.3", + "@react-spectrum/utils": "^3.11.5", + "@react-types/label": "^3.9.1", + "@react-types/shared": "^3.22.1", + "@spectrum-icons/ui": "^3.6.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5277,16 +5265,16 @@ } }, "node_modules/@react-spectrum/labeledvalue": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/@react-spectrum/labeledvalue/-/labeledvalue-3.1.11.tgz", - "integrity": "sha512-OW4fHEVoVhp/A/urNSns9mvrBYmBNDgvR4R4fCpfio5AXevYUqgIzYmTSMY8LUWa9+EkbtCnp5JSmD3KM25wrA==", - "dependencies": { - "@internationalized/date": "^3.5.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/label": "^3.16.3", - "@react-spectrum/utils": "^3.11.4", - "@react-types/shared": "^3.22.0", + "version": "3.1.12", + "resolved": "https://registry.npmjs.org/@react-spectrum/labeledvalue/-/labeledvalue-3.1.12.tgz", + "integrity": "sha512-Pa/eYf9FKr8QF7xKLoCv6a+Ezudfi7N1jFJLZ71zaVcDOcNByYKiy1lAquwLB+36PpsWt/EwKLE2/U7OuiWyfQ==", + "dependencies": { + "@internationalized/date": "^3.5.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/label": "^3.16.4", + "@react-spectrum/utils": "^3.11.5", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5295,14 +5283,14 @@ } }, "node_modules/@react-spectrum/layout": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/@react-spectrum/layout/-/layout-3.6.2.tgz", - "integrity": "sha512-B5asGN+uFlfThTms4KraAU4OapMmN9Ryr1uj5uhHLtCwyQcLphg1Q+LMX8LfrNr7vPLxgoZ4L3em7ohkSb8Okg==", + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@react-spectrum/layout/-/layout-3.6.3.tgz", + "integrity": "sha512-JsG4KclsgzKfRbe+PyMo8QryG5SmwYlym8JRuSLmZ+nfIKhESVbqSJE3IXblmDDWUb0rabQhSvW4p5h5nOil4w==", "dependencies": { - "@react-aria/utils": "^3.23.1", - "@react-spectrum/utils": "^3.11.4", - "@react-types/layout": "^3.3.12", - "@react-types/shared": "^3.22.0", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/utils": "^3.11.5", + "@react-types/layout": "^3.3.13", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5311,16 +5299,16 @@ } }, "node_modules/@react-spectrum/link": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/@react-spectrum/link/-/link-3.6.4.tgz", - "integrity": "sha512-qxTCuGJuQd88j/Cq9yRTu3h48QV1h8Y9GVBoEVHnNQ4HGQjpDLkQkAFQwIZHku87RKhVY9LgA3YmBuo/1AJbsg==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/link": "^3.6.4", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/utils": "^3.11.4", - "@react-types/link": "^3.5.2", + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/@react-spectrum/link/-/link-3.6.5.tgz", + "integrity": "sha512-pnPIzkM0/Nxm460dHuR195bD0BAaIvasqW8TqUFT0Igxfw0NFYyWZr5d4OkHKyypyUoQKaobpOgeAJHXxPtzTg==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/link": "^3.6.5", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/utils": "^3.11.5", + "@react-types/link": "^3.5.3", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5329,30 +5317,30 @@ } }, "node_modules/@react-spectrum/list": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@react-spectrum/list/-/list-3.7.7.tgz", - "integrity": "sha512-qL3lKLUauZ8fZsujPWa8K/Rz+zsY5eRktdqckQGVKBRLGOTc/WQcn9csb2hNOBSlYX5rYUabU5Ia7yGfMMauuA==", - "dependencies": { - "@react-aria/button": "^3.9.2", - "@react-aria/focus": "^3.16.1", - "@react-aria/gridlist": "^3.7.4", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-aria/virtualizer": "^3.9.9", - "@react-aria/visually-hidden": "^3.8.9", - "@react-spectrum/checkbox": "^3.9.3", - "@react-spectrum/dnd": "^3.3.7", - "@react-spectrum/layout": "^3.6.2", - "@react-spectrum/progress": "^3.7.4", - "@react-spectrum/text": "^3.5.2", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/collections": "^3.10.4", - "@react-stately/layout": "^3.13.6", - "@react-stately/list": "^3.10.2", - "@react-types/grid": "^3.2.3", - "@react-types/shared": "^3.22.0", - "@spectrum-icons/ui": "^3.6.4", + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/@react-spectrum/list/-/list-3.7.8.tgz", + "integrity": "sha512-w+fxiX+wz8X0bASAtKsf/myMrFI1Z0OXamttPRAJS5Ene6x09kf+K2djpZO1t9nT70IPnCcthhkMaCHk6eyUIw==", + "dependencies": { + "@react-aria/button": "^3.9.3", + "@react-aria/focus": "^3.16.2", + "@react-aria/gridlist": "^3.7.5", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-aria/virtualizer": "^3.9.10", + "@react-aria/visually-hidden": "^3.8.10", + "@react-spectrum/checkbox": "^3.9.4", + "@react-spectrum/dnd": "^3.3.8", + "@react-spectrum/layout": "^3.6.3", + "@react-spectrum/progress": "^3.7.5", + "@react-spectrum/text": "^3.5.3", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/collections": "^3.10.5", + "@react-stately/layout": "^3.13.7", + "@react-stately/list": "^3.10.3", + "@react-types/grid": "^3.2.4", + "@react-types/shared": "^3.22.1", + "@spectrum-icons/ui": "^3.6.5", "@swc/helpers": "^0.5.0", "react-transition-group": "^4.4.5" }, @@ -5363,27 +5351,27 @@ } }, "node_modules/@react-spectrum/listbox": { - "version": "3.12.6", - "resolved": "https://registry.npmjs.org/@react-spectrum/listbox/-/listbox-3.12.6.tgz", - "integrity": "sha512-PXGxWtPIbWjFxAnBOkUHlcoqy6QfvHYPwoGnS0cObEwPP6J4Int9MynMVg1S3wwxKl8quYPojoidsrp04CGmIA==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/listbox": "^3.11.4", - "@react-aria/utils": "^3.23.1", - "@react-aria/virtualizer": "^3.9.9", - "@react-spectrum/layout": "^3.6.2", - "@react-spectrum/progress": "^3.7.4", - "@react-spectrum/text": "^3.5.2", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/collections": "^3.10.4", - "@react-stately/layout": "^3.13.6", - "@react-stately/list": "^3.10.2", - "@react-stately/virtualizer": "^3.6.7", - "@react-types/listbox": "^3.4.6", - "@react-types/shared": "^3.22.0", - "@spectrum-icons/ui": "^3.6.4", + "version": "3.12.7", + "resolved": "https://registry.npmjs.org/@react-spectrum/listbox/-/listbox-3.12.7.tgz", + "integrity": "sha512-cFUIKPRtz5ViQYS0vO+oQmiFmbJjA04GCpyZKnBJAEonNDiY1RIHfFg/53Mr8IwstwNvGbxHVjMilPy6DtWDjA==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/listbox": "^3.11.5", + "@react-aria/utils": "^3.23.2", + "@react-aria/virtualizer": "^3.9.10", + "@react-spectrum/layout": "^3.6.3", + "@react-spectrum/progress": "^3.7.5", + "@react-spectrum/text": "^3.5.3", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/collections": "^3.10.5", + "@react-stately/layout": "^3.13.7", + "@react-stately/list": "^3.10.3", + "@react-stately/virtualizer": "^3.6.8", + "@react-types/listbox": "^3.4.7", + "@react-types/shared": "^3.22.1", + "@spectrum-icons/ui": "^3.6.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5393,31 +5381,31 @@ } }, "node_modules/@react-spectrum/menu": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@react-spectrum/menu/-/menu-3.18.0.tgz", - "integrity": "sha512-LSCvhs1IoEYZs798VzOPJia4V1/xGMbKIF0Ai7xqi+9DU+M/PSzWlhIRa1Ya/nTRxdUNOygG13CaY+WYnjYzEA==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/menu": "^3.13.0", - "@react-aria/overlays": "^3.21.0", - "@react-aria/separator": "^3.3.10", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/button": "^3.16.1", - "@react-spectrum/layout": "^3.6.2", - "@react-spectrum/overlays": "^5.5.4", - "@react-spectrum/text": "^3.5.2", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/collections": "^3.10.4", - "@react-stately/menu": "^3.6.0", - "@react-stately/overlays": "^3.6.4", - "@react-stately/tree": "^3.7.5", - "@react-types/menu": "^3.9.6", - "@react-types/overlays": "^3.8.4", - "@react-types/shared": "^3.22.0", - "@spectrum-icons/ui": "^3.6.4", - "@spectrum-icons/workflow": "^4.2.9", + "version": "3.18.1", + "resolved": "https://registry.npmjs.org/@react-spectrum/menu/-/menu-3.18.1.tgz", + "integrity": "sha512-3KutRgn9/uYcRH2IzUT6qiPlS9SK9+4R2W4Z1Ox27lQ30ZgC68kE37uOwZX10bDgTOWV/COYvm6qBBScZ+VFUg==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/menu": "^3.13.1", + "@react-aria/overlays": "^3.21.1", + "@react-aria/separator": "^3.3.11", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/button": "^3.16.2", + "@react-spectrum/layout": "^3.6.3", + "@react-spectrum/overlays": "^5.5.5", + "@react-spectrum/text": "^3.5.3", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/collections": "^3.10.5", + "@react-stately/menu": "^3.6.1", + "@react-stately/overlays": "^3.6.5", + "@react-stately/tree": "^3.7.6", + "@react-types/menu": "^3.9.7", + "@react-types/overlays": "^3.8.5", + "@react-types/shared": "^3.22.1", + "@spectrum-icons/ui": "^3.6.5", + "@spectrum-icons/workflow": "^4.2.10", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5427,15 +5415,15 @@ } }, "node_modules/@react-spectrum/meter": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/@react-spectrum/meter/-/meter-3.4.10.tgz", - "integrity": "sha512-cC4WnAoUSTD7ikGN4KSS92Dd3XRFxkzYlSQYt/ijBg3RR8k2sIerqbv6eEbYqMoErt6a0VXgBqSdon9Qj1jkuQ==", - "dependencies": { - "@react-aria/meter": "^3.4.10", - "@react-spectrum/progress": "^3.7.4", - "@react-spectrum/utils": "^3.11.4", - "@react-types/meter": "^3.3.6", - "@react-types/shared": "^3.22.0", + "version": "3.4.11", + "resolved": "https://registry.npmjs.org/@react-spectrum/meter/-/meter-3.4.11.tgz", + "integrity": "sha512-OBYIHnumb2cfeT48py6Qtsfs7m9DmddaHSCVB8MXNnn3fzrpPr5t4Wz2dYUWXnkPPC11D8WarjJ+6EgrNwNvdQ==", + "dependencies": { + "@react-aria/meter": "^3.4.11", + "@react-spectrum/progress": "^3.7.5", + "@react-spectrum/utils": "^3.11.5", + "@react-types/meter": "^3.3.7", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5444,26 +5432,26 @@ } }, "node_modules/@react-spectrum/numberfield": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@react-spectrum/numberfield/-/numberfield-3.9.0.tgz", - "integrity": "sha512-Zj51Q3mm7LSCClaN6StYAj11hXf23RD/KiBiKRb+0q2OfJAszAgxVzx71BWOHj0OnK5INlF5INp7GWhiVZ7rJQ==", - "dependencies": { - "@react-aria/button": "^3.9.2", - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/numberfield": "^3.11.0", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/form": "^3.7.3", - "@react-spectrum/label": "^3.16.3", - "@react-spectrum/textfield": "^3.11.3", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/numberfield": "^3.9.0", - "@react-types/button": "^3.9.1", - "@react-types/numberfield": "^3.8.0", - "@react-types/shared": "^3.22.0", - "@spectrum-icons/ui": "^3.6.4", - "@spectrum-icons/workflow": "^4.2.9", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@react-spectrum/numberfield/-/numberfield-3.9.1.tgz", + "integrity": "sha512-s6QNRncVrVjOYihKeyQ8fkdD1YJTqYttog/Rj96rD66vfUlI0bTr3q6mK6hZpU1YM29SL24BUCn6NdqOxqVeiQ==", + "dependencies": { + "@react-aria/button": "^3.9.3", + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/numberfield": "^3.11.1", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/form": "^3.7.4", + "@react-spectrum/label": "^3.16.4", + "@react-spectrum/textfield": "^3.11.4", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/numberfield": "^3.9.1", + "@react-types/button": "^3.9.2", + "@react-types/numberfield": "^3.8.1", + "@react-types/shared": "^3.22.1", + "@spectrum-icons/ui": "^3.6.5", + "@spectrum-icons/workflow": "^4.2.10", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5473,17 +5461,17 @@ } }, "node_modules/@react-spectrum/overlays": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/@react-spectrum/overlays/-/overlays-5.5.4.tgz", - "integrity": "sha512-xiIm84B1YbUOh8LxdpLMQN220/E6dyqTqB4KCTZ89YiKygJiEH9YPqM1GBsOEcpVUT+MEDPASixh2ADjY/YeIA==", - "dependencies": { - "@react-aria/interactions": "^3.21.0", - "@react-aria/overlays": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/overlays": "^3.6.4", - "@react-types/overlays": "^3.8.4", - "@react-types/shared": "^3.22.0", + "version": "5.5.5", + "resolved": "https://registry.npmjs.org/@react-spectrum/overlays/-/overlays-5.5.5.tgz", + "integrity": "sha512-rFwbWuagFo/Tuo45UE8KHUMz1Li1j5CNzsZdIfKZydHd0u4t69yR8bCn3pDUNIYEwclrLGUD2XFJaN9jYq1H4A==", + "dependencies": { + "@react-aria/interactions": "^3.21.1", + "@react-aria/overlays": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/overlays": "^3.6.5", + "@react-types/overlays": "^3.8.5", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0", "react-transition-group": "^4.4.5" }, @@ -5494,27 +5482,27 @@ } }, "node_modules/@react-spectrum/picker": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/@react-spectrum/picker/-/picker-3.14.2.tgz", - "integrity": "sha512-ZswvbG+2u6+c6qdy6wjh9IinT/Bkt1+Q7tuLGSTsPPAtWJoFEKQ9tntuvtYJx23vBZ2lrtGOWidJOeqKlOfshQ==", - "dependencies": { - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/select": "^3.14.2", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/button": "^3.16.1", - "@react-spectrum/form": "^3.7.3", - "@react-spectrum/label": "^3.16.3", - "@react-spectrum/listbox": "^3.12.6", - "@react-spectrum/overlays": "^5.5.4", - "@react-spectrum/progress": "^3.7.4", - "@react-spectrum/text": "^3.5.2", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/collections": "^3.10.4", - "@react-stately/select": "^3.6.1", - "@react-types/select": "^3.9.1", - "@react-types/shared": "^3.22.0", - "@spectrum-icons/ui": "^3.6.4", + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/@react-spectrum/picker/-/picker-3.14.3.tgz", + "integrity": "sha512-xaewWrOtGt/dQbiSwZe9UYH58berRlxyqIeAZQ7+FCRGoG/gl1p+l+7rfNKFS5OjVy6Adh6BZrrY6A99j4PbQA==", + "dependencies": { + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/select": "^3.14.3", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/button": "^3.16.2", + "@react-spectrum/form": "^3.7.4", + "@react-spectrum/label": "^3.16.4", + "@react-spectrum/listbox": "^3.12.7", + "@react-spectrum/overlays": "^5.5.5", + "@react-spectrum/progress": "^3.7.5", + "@react-spectrum/text": "^3.5.3", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/collections": "^3.10.5", + "@react-stately/select": "^3.6.2", + "@react-types/select": "^3.9.2", + "@react-types/shared": "^3.22.1", + "@spectrum-icons/ui": "^3.6.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5524,15 +5512,15 @@ } }, "node_modules/@react-spectrum/progress": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@react-spectrum/progress/-/progress-3.7.4.tgz", - "integrity": "sha512-xEz8RX54rPPw/WS6bgBpop2C3s7wjakwOT42KIZz0vVQrRCa596Mtmy7IrLLtyfHuIgNgNHs/BVaH46Nzrr9Uw==", - "dependencies": { - "@react-aria/progress": "^3.4.10", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/utils": "^3.11.4", - "@react-types/progress": "^3.5.1", - "@react-types/shared": "^3.22.0", + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/@react-spectrum/progress/-/progress-3.7.5.tgz", + "integrity": "sha512-ku+RTtgXWaxUwjopzWpvgNxJsn/gohMWO4len2K2yDQp6b4SY67ojRFBwyIDZ9Oi9RPTAvZOc3wJu5QPftfVcg==", + "dependencies": { + "@react-aria/progress": "^3.4.11", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/utils": "^3.11.5", + "@react-types/progress": "^3.5.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5541,16 +5529,16 @@ } }, "node_modules/@react-spectrum/provider": { - "version": "3.9.4", - "resolved": "https://registry.npmjs.org/@react-spectrum/provider/-/provider-3.9.4.tgz", - "integrity": "sha512-GEfmQCC/s0JRxMR7WA41vyGnSPssJTA1+ijTkDLGbhCyKmUq6pmNFaCj3WRW/ki+Gg42eWaNXth5sPexbxr9qA==", - "dependencies": { - "@react-aria/i18n": "^3.10.1", - "@react-aria/overlays": "^3.21.0", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/utils": "^3.11.4", - "@react-types/provider": "^3.7.1", - "@react-types/shared": "^3.22.0", + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/@react-spectrum/provider/-/provider-3.9.5.tgz", + "integrity": "sha512-FE5RQC1EwMMXUAtslekheyA0IrXSev4flaY4CT3exC/ohB1PuiXUDg4qqaHos2vVhsdUPNq5SeathtHEr8ryJA==", + "dependencies": { + "@react-aria/i18n": "^3.10.2", + "@react-aria/overlays": "^3.21.1", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/utils": "^3.11.5", + "@react-types/provider": "^3.7.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -5560,19 +5548,19 @@ } }, "node_modules/@react-spectrum/radio": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/@react-spectrum/radio/-/radio-3.7.3.tgz", - "integrity": "sha512-wi0ielcjBbsDm3kgDXutWyJVQa31+8r2++1N+omj0zkffOiHqK5m+9faUikX7DKwQ4d/CkbAegrkN6q4yxkwbw==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/radio": "^3.10.1", - "@react-spectrum/form": "^3.7.3", - "@react-spectrum/label": "^3.16.3", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/radio": "^3.10.1", - "@react-types/radio": "^3.7.0", - "@react-types/shared": "^3.22.0", + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@react-spectrum/radio/-/radio-3.7.4.tgz", + "integrity": "sha512-FmWcJlOeo5KsbWYpnEtoB9oC+haUeowfRda8dq0kBptR5WlagWD4Arez55/hjXCHLqQZ4r6vY6rYgMya2xiddQ==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/radio": "^3.10.2", + "@react-spectrum/form": "^3.7.4", + "@react-spectrum/label": "^3.16.4", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/radio": "^3.10.2", + "@react-types/radio": "^3.7.1", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5581,19 +5569,19 @@ } }, "node_modules/@react-spectrum/searchfield": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/@react-spectrum/searchfield/-/searchfield-3.8.3.tgz", - "integrity": "sha512-eHdfbQn2Jp2/USsKHOjLlVTqcnPHKUYa9f4bW9cXO0y08gfI1CSOhNlK3TYs625lvsRGCraCpsi6X2oStRWb8w==", - "dependencies": { - "@react-aria/searchfield": "^3.7.2", - "@react-spectrum/button": "^3.16.1", - "@react-spectrum/form": "^3.7.3", - "@react-spectrum/textfield": "^3.11.3", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/searchfield": "^3.5.0", - "@react-types/searchfield": "^3.5.2", - "@react-types/textfield": "^3.9.0", - "@spectrum-icons/ui": "^3.6.4", + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/@react-spectrum/searchfield/-/searchfield-3.8.4.tgz", + "integrity": "sha512-O8pM9dGlRZoFhNtZLVFpIOHM2+sy5/t23Lv0z0jXvVYmzHOaib8wPPJELnPRsDUIylqpnVxfiYSz051Gx5Zq8g==", + "dependencies": { + "@react-aria/searchfield": "^3.7.3", + "@react-spectrum/button": "^3.16.2", + "@react-spectrum/form": "^3.7.4", + "@react-spectrum/textfield": "^3.11.4", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/searchfield": "^3.5.1", + "@react-types/searchfield": "^3.5.3", + "@react-types/textfield": "^3.9.1", + "@spectrum-icons/ui": "^3.6.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5602,20 +5590,20 @@ } }, "node_modules/@react-spectrum/slider": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/@react-spectrum/slider/-/slider-3.6.6.tgz", - "integrity": "sha512-Meav6BLiTuuGxk+qFM3MJJubSIdBytb+Cfa3SIsZ8zx1X0O3eY517byJYjOVLo/FhzloWWNupr7aMPAGfOKb2A==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/slider": "^3.7.5", - "@react-aria/utils": "^3.23.1", - "@react-aria/visually-hidden": "^3.8.9", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/slider": "^3.5.1", - "@react-types/shared": "^3.22.0", - "@react-types/slider": "^3.7.0", + "version": "3.6.7", + "resolved": "https://registry.npmjs.org/@react-spectrum/slider/-/slider-3.6.7.tgz", + "integrity": "sha512-mhTG+sGZwQfNW9z+uzvmTQzzV2Qzcack3qYSw8HXEfd4BOjkgwTinS9aN8MLv147TF5RMvI0y3dmNirAoDi+yQ==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/slider": "^3.7.6", + "@react-aria/utils": "^3.23.2", + "@react-aria/visually-hidden": "^3.8.10", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/slider": "^3.5.2", + "@react-types/shared": "^3.22.1", + "@react-types/slider": "^3.7.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5624,14 +5612,14 @@ } }, "node_modules/@react-spectrum/statuslight": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@react-spectrum/statuslight/-/statuslight-3.5.10.tgz", - "integrity": "sha512-s697KmFlwF1dbM0nTNDanL6jqqC6da86tu8sqU7IWqowymbpkIdorFFHuFDiOUg+rKa+QXKzeLicaxH75o6oyw==", - "dependencies": { - "@react-aria/utils": "^3.23.1", - "@react-spectrum/utils": "^3.11.4", - "@react-types/shared": "^3.22.0", - "@react-types/statuslight": "^3.3.6", + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@react-spectrum/statuslight/-/statuslight-3.5.11.tgz", + "integrity": "sha512-zbIrI8rPLmMu3Jnl2fpA/kb0V3azdRBsv1KfhGNQkHM17Gy6ufrzzzh6cmnvQh8FREllMcIjC4eaBkYHFArtyg==", + "dependencies": { + "@react-aria/utils": "^3.23.2", + "@react-spectrum/utils": "^3.11.5", + "@react-types/shared": "^3.22.1", + "@react-types/statuslight": "^3.3.7", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5640,17 +5628,17 @@ } }, "node_modules/@react-spectrum/switch": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@react-spectrum/switch/-/switch-3.5.2.tgz", - "integrity": "sha512-gpxgU5z0BlaorNjCw6J9c2kSQA9ZR7tjg3hF3491i+h2+xc2NuTQe18WYEHTXFTmlXVEEXE97BEtoX4KY7YU0g==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/switch": "^3.6.1", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/toggle": "^3.7.1", - "@react-types/shared": "^3.22.0", - "@react-types/switch": "^3.5.0", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/@react-spectrum/switch/-/switch-3.5.3.tgz", + "integrity": "sha512-NJMk/b/Lrmgl0RB9QPF0wSuD5CgTPODaLuZD1uxXAcESKFVdN58eW8CU99e+ZC0tHgFofroTpEF073Yiz2LnkQ==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/switch": "^3.6.2", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/toggle": "^3.7.2", + "@react-types/shared": "^3.22.1", + "@react-types/switch": "^3.5.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5659,33 +5647,33 @@ } }, "node_modules/@react-spectrum/table": { - "version": "3.12.7", - "resolved": "https://registry.npmjs.org/@react-spectrum/table/-/table-3.12.7.tgz", - "integrity": "sha512-A+jirOXULysnKvrN0Q8hS4t64I8fFoyyXYAlfSTnza3n2hXKxYnYenKP/VjB7PvdFwZiBAY4+VVg37E0JfFUWw==", - "dependencies": { - "@react-aria/button": "^3.9.2", - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/table": "^3.13.4", - "@react-aria/utils": "^3.23.1", - "@react-aria/virtualizer": "^3.9.9", - "@react-aria/visually-hidden": "^3.8.9", - "@react-spectrum/checkbox": "^3.9.3", - "@react-spectrum/dnd": "^3.3.7", - "@react-spectrum/layout": "^3.6.2", - "@react-spectrum/menu": "^3.18.0", - "@react-spectrum/progress": "^3.7.4", - "@react-spectrum/tooltip": "^3.6.4", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/flags": "^3.0.0", - "@react-stately/layout": "^3.13.6", - "@react-stately/table": "^3.11.5", - "@react-stately/virtualizer": "^3.6.7", - "@react-types/grid": "^3.2.3", - "@react-types/shared": "^3.22.0", - "@react-types/table": "^3.9.2", - "@spectrum-icons/ui": "^3.6.4", + "version": "3.12.8", + "resolved": "https://registry.npmjs.org/@react-spectrum/table/-/table-3.12.8.tgz", + "integrity": "sha512-4JyDlvKljhvqqUHYk6X5JjmxXy03IZergKTu//MbELW4v9bwiwf94Ap8zTcUZPh/pcw7IQhpUDLPAi6RFBAUpA==", + "dependencies": { + "@react-aria/button": "^3.9.3", + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/table": "^3.13.5", + "@react-aria/utils": "^3.23.2", + "@react-aria/virtualizer": "^3.9.10", + "@react-aria/visually-hidden": "^3.8.10", + "@react-spectrum/checkbox": "^3.9.4", + "@react-spectrum/dnd": "^3.3.8", + "@react-spectrum/layout": "^3.6.3", + "@react-spectrum/menu": "^3.18.1", + "@react-spectrum/progress": "^3.7.5", + "@react-spectrum/tooltip": "^3.6.5", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/flags": "^3.0.1", + "@react-stately/layout": "^3.13.7", + "@react-stately/table": "^3.11.6", + "@react-stately/virtualizer": "^3.6.8", + "@react-types/grid": "^3.2.4", + "@react-types/shared": "^3.22.1", + "@react-types/table": "^3.9.3", + "@spectrum-icons/ui": "^3.6.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5695,24 +5683,24 @@ } }, "node_modules/@react-spectrum/tabs": { - "version": "3.8.7", - "resolved": "https://registry.npmjs.org/@react-spectrum/tabs/-/tabs-3.8.7.tgz", - "integrity": "sha512-DcPn/pcYuXiS6cwuMT4k3tusDoMuUTjWUYpAcHwDue9xcUGsb6BrNmMxrQ6J08nQN6DhUizqtGA9CCTS9NwcnA==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/tabs": "^3.8.4", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/picker": "^3.14.2", - "@react-spectrum/text": "^3.5.2", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/collections": "^3.10.4", - "@react-stately/list": "^3.10.2", - "@react-stately/tabs": "^3.6.3", - "@react-types/select": "^3.9.1", - "@react-types/shared": "^3.22.0", - "@react-types/tabs": "^3.3.4", + "version": "3.8.8", + "resolved": "https://registry.npmjs.org/@react-spectrum/tabs/-/tabs-3.8.8.tgz", + "integrity": "sha512-oBXKLD7cyCLQV3SUXIjEn9ttdyoGwpiTUfM3DNY3ki097pRdoBgMxPk1Sp7jKQs6tRUg4osK53iOG4LvEs6eTg==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/tabs": "^3.8.5", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/picker": "^3.14.3", + "@react-spectrum/text": "^3.5.3", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/collections": "^3.10.5", + "@react-stately/list": "^3.10.3", + "@react-stately/tabs": "^3.6.4", + "@react-types/select": "^3.9.2", + "@react-types/shared": "^3.22.1", + "@react-types/tabs": "^3.3.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5722,24 +5710,24 @@ } }, "node_modules/@react-spectrum/tag": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@react-spectrum/tag/-/tag-3.2.3.tgz", - "integrity": "sha512-9LZ6SplsNUtvH3VjWZEMpDxbcQSNLNUuoYp9mISzeD8Zf2aNhHLIzm5kyB29hZcZO7lZzZY8GdX44a5awmKLZw==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/i18n": "^3.10.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/selection": "^3.17.4", - "@react-aria/tag": "^3.3.2", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/button": "^3.16.1", - "@react-spectrum/form": "^3.7.3", - "@react-spectrum/label": "^3.16.3", - "@react-spectrum/text": "^3.5.2", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/collections": "^3.10.4", - "@react-stately/list": "^3.10.2", - "@react-types/shared": "^3.22.0", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@react-spectrum/tag/-/tag-3.2.4.tgz", + "integrity": "sha512-d6cqX+n10pokLsBGEC/ksLLHM3vBoR7zc0AAlBAUrBN6VMBWUQRyazDHeXPLLZs/S4+ICL80UXRf8NwWfA7Efg==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/i18n": "^3.10.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/selection": "^3.17.5", + "@react-aria/tag": "^3.3.3", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/button": "^3.16.2", + "@react-spectrum/form": "^3.7.4", + "@react-spectrum/label": "^3.16.4", + "@react-spectrum/text": "^3.5.3", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/collections": "^3.10.5", + "@react-stately/list": "^3.10.3", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5749,14 +5737,14 @@ } }, "node_modules/@react-spectrum/text": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@react-spectrum/text/-/text-3.5.2.tgz", - "integrity": "sha512-cv2WrZrM24btD2zRDs/Qg5n/1+EE2D69RbGySQrJWerohPRJzYoID/ZXPsn0W6gKVivbn6lRQ1+c9ptoXA7b8Q==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/@react-spectrum/text/-/text-3.5.3.tgz", + "integrity": "sha512-28WiSnIPm8WC4JOsHPLudCGjPc3tk7zKm3L+8xqzr374j1+HdMGivrhVOf1t4jbUMcT5dOxR7huuDe7E97qe5A==", "dependencies": { - "@react-aria/utils": "^3.23.1", - "@react-spectrum/utils": "^3.11.4", - "@react-types/shared": "^3.22.0", - "@react-types/text": "^3.3.6", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/utils": "^3.11.5", + "@react-types/shared": "^3.22.1", + "@react-types/text": "^3.3.7", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5765,21 +5753,21 @@ } }, "node_modules/@react-spectrum/textfield": { - "version": "3.11.3", - "resolved": "https://registry.npmjs.org/@react-spectrum/textfield/-/textfield-3.11.3.tgz", - "integrity": "sha512-859j6VUgXYdF/LoYnindXTirZHfyhX22/6BreQl7mxJT0JDqYn8G/k7pauRSGyw+Di3zuvujEKu8ZdJAMm/0JA==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/interactions": "^3.21.0", - "@react-aria/textfield": "^3.14.2", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/form": "^3.7.3", - "@react-spectrum/label": "^3.16.3", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/utils": "^3.9.0", - "@react-types/shared": "^3.22.0", - "@react-types/textfield": "^3.9.0", - "@spectrum-icons/ui": "^3.6.4", + "version": "3.11.4", + "resolved": "https://registry.npmjs.org/@react-spectrum/textfield/-/textfield-3.11.4.tgz", + "integrity": "sha512-J70Q1ddpX0v+R7x8w5DaJLixnp5mBWm39lUnekiahEUuA420U1eZCW80GiHXFS/GO6wpwjIZpWHcpBQuF/EDCQ==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/interactions": "^3.21.1", + "@react-aria/textfield": "^3.14.3", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/form": "^3.7.4", + "@react-spectrum/label": "^3.16.4", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/utils": "^3.9.1", + "@react-types/shared": "^3.22.1", + "@react-types/textfield": "^3.9.1", + "@spectrum-icons/ui": "^3.6.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5788,11 +5776,11 @@ } }, "node_modules/@react-spectrum/theme-dark": { - "version": "3.5.7", - "resolved": "https://registry.npmjs.org/@react-spectrum/theme-dark/-/theme-dark-3.5.7.tgz", - "integrity": "sha512-WaBVkhJKsZNcsHCcm6HQOSV934KLxZK6cbTt/FjUZtNTHcQTb5s2xf2jPeMwcRbRJfzagfTuTr5BkM38B9Zi1Q==", + "version": "3.5.8", + "resolved": "https://registry.npmjs.org/@react-spectrum/theme-dark/-/theme-dark-3.5.8.tgz", + "integrity": "sha512-ep78rIrgrXu5MHe6LQAiK8+Us/4PoeHcixm+xFJk8I7AP+6wrh+9+QSWdIi3/NJY9fIjXsMm+VyehFVtEq8PAg==", "dependencies": { - "@react-types/provider": "^3.7.1", + "@react-types/provider": "^3.7.2", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5800,11 +5788,11 @@ } }, "node_modules/@react-spectrum/theme-default": { - "version": "3.5.7", - "resolved": "https://registry.npmjs.org/@react-spectrum/theme-default/-/theme-default-3.5.7.tgz", - "integrity": "sha512-5GgCKfzA1be3pE5XtQ+5hk39I4BhU1qY+fHCDxvE/tndm2I7pCk26d6ifxA0H2RVKH8V3eiH0WG1TNXHcHIO1g==", + "version": "3.5.8", + "resolved": "https://registry.npmjs.org/@react-spectrum/theme-default/-/theme-default-3.5.8.tgz", + "integrity": "sha512-vZ9GH4l6H2Ks/PD15k2mx6XgA1EYKxQbB+ai9UZ3ALXf0KYlVIFSoHk4Vp3hP16D12KsuB7V0Gk8SvHlsRNo+Q==", "dependencies": { - "@react-types/provider": "^3.7.1", + "@react-types/provider": "^3.7.2", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5812,11 +5800,11 @@ } }, "node_modules/@react-spectrum/theme-light": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/@react-spectrum/theme-light/-/theme-light-3.4.7.tgz", - "integrity": "sha512-3NeIDN9QU8c40rqRSzurTdJRTZ5Uag4c2fLlF9Bve/yF7N6KlzK29H3EWNLBizAfozhPe5/HDEYqdArz7bxhlQ==", + "version": "3.4.8", + "resolved": "https://registry.npmjs.org/@react-spectrum/theme-light/-/theme-light-3.4.8.tgz", + "integrity": "sha512-6kjtQ6IGrh2E0WJKQ9eAR5yhcWFI2mNvd+wi8Uy3rtRdBB1L3iSfr2RmgxgcTCl50DnKqmcFsHbHaKMMKqhkaQ==", "dependencies": { - "@react-types/provider": "^3.7.1", + "@react-types/provider": "^3.7.2", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5824,21 +5812,21 @@ } }, "node_modules/@react-spectrum/tooltip": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/@react-spectrum/tooltip/-/tooltip-3.6.4.tgz", - "integrity": "sha512-z8RGtQjUHRT2haI1tz7lB9STuv6kj8GBGr++Zo5xE8nhY2QASRXE4gZ16YnGI8l2c7EFyLFstAEtbrxt835GWQ==", - "dependencies": { - "@react-aria/focus": "^3.16.1", - "@react-aria/overlays": "^3.21.0", - "@react-aria/tooltip": "^3.7.1", - "@react-aria/utils": "^3.23.1", - "@react-spectrum/overlays": "^5.5.4", - "@react-spectrum/utils": "^3.11.4", - "@react-stately/tooltip": "^3.4.6", - "@react-types/overlays": "^3.8.4", - "@react-types/shared": "^3.22.0", - "@react-types/tooltip": "^3.4.6", - "@spectrum-icons/ui": "^3.6.4", + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/@react-spectrum/tooltip/-/tooltip-3.6.5.tgz", + "integrity": "sha512-TnVUX8gNx65wOfHE5UIzuzpC4kUd6RuFeDykcu+3OM+fsK6qvDYg2MQq/3UiZHFI0ZHhX89yPf4uLaP0hcT8sg==", + "dependencies": { + "@react-aria/focus": "^3.16.2", + "@react-aria/overlays": "^3.21.1", + "@react-aria/tooltip": "^3.7.2", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/overlays": "^5.5.5", + "@react-spectrum/utils": "^3.11.5", + "@react-stately/tooltip": "^3.4.7", + "@react-types/overlays": "^3.8.5", + "@react-types/shared": "^3.22.1", + "@react-types/tooltip": "^3.4.7", + "@spectrum-icons/ui": "^3.6.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5848,14 +5836,14 @@ } }, "node_modules/@react-spectrum/utils": { - "version": "3.11.4", - "resolved": "https://registry.npmjs.org/@react-spectrum/utils/-/utils-3.11.4.tgz", - "integrity": "sha512-x1GfD25riFzbkscmLR7EUVDJolwjz7QSn8udtAW09kCcpCBjyA+SMmjt+rCpzYM4mtGfPlcJJrYDGDarGjNWxQ==", + "version": "3.11.5", + "resolved": "https://registry.npmjs.org/@react-spectrum/utils/-/utils-3.11.5.tgz", + "integrity": "sha512-V4heIuCBXhYOP3om5B0KNs2+RK6RKwAhHVjjJZ3RBeNqsF9UDxv+D/+dk3sAM2dsM1F8l38BNXQMMWXWW/BZYA==", "dependencies": { - "@react-aria/i18n": "^3.10.1", - "@react-aria/ssr": "^3.9.1", - "@react-aria/utils": "^3.23.1", - "@react-types/shared": "^3.22.0", + "@react-aria/i18n": "^3.10.2", + "@react-aria/ssr": "^3.9.2", + "@react-aria/utils": "^3.23.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -5864,14 +5852,14 @@ } }, "node_modules/@react-spectrum/view": { - "version": "3.6.7", - "resolved": "https://registry.npmjs.org/@react-spectrum/view/-/view-3.6.7.tgz", - "integrity": "sha512-eCwFfoMN7j4G44GZfGmFM+jWsD4zBxbmLsbrm6H1kEmxeeJkCM1jwF2H3Vc4WJxaBuOBY7tce8IHBRwQ3l0Wng==", + "version": "3.6.8", + "resolved": "https://registry.npmjs.org/@react-spectrum/view/-/view-3.6.8.tgz", + "integrity": "sha512-jAKh22xUjFY5sxPTtLc53fw3C+dki+DEDxArFK06/tF+ntV6lDat91j+YedcOtDT2p7C2PSfaToX5moyEAQ+NA==", "dependencies": { - "@react-aria/utils": "^3.23.1", - "@react-spectrum/utils": "^3.11.4", - "@react-types/shared": "^3.22.0", - "@react-types/view": "^3.4.6", + "@react-aria/utils": "^3.23.2", + "@react-spectrum/utils": "^3.11.5", + "@react-types/shared": "^3.22.1", + "@react-types/view": "^3.4.7", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5880,14 +5868,14 @@ } }, "node_modules/@react-spectrum/well": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/@react-spectrum/well/-/well-3.4.10.tgz", - "integrity": "sha512-k1xnXk75R7V2DEbI8+rejT3d2pQR5j6DHZt/JzBbpmuGxvKqlkMgr364vBmusOEu8lvUE5/Q6O+qdnNTZeirWw==", - "dependencies": { - "@react-aria/utils": "^3.23.1", - "@react-spectrum/utils": "^3.11.4", - "@react-types/shared": "^3.22.0", - "@react-types/well": "^3.3.6", + "version": "3.4.11", + "resolved": "https://registry.npmjs.org/@react-spectrum/well/-/well-3.4.11.tgz", + "integrity": "sha512-oCQqKKcKXNoF18dNz5GHBdSXrNPsVH5jsH17suqQevzDQkMN2X02Ov0oyOYMAUQM0xSE3ensLdjvLzUL0yl36g==", + "dependencies": { + "@react-aria/utils": "^3.23.2", + "@react-spectrum/utils": "^3.11.5", + "@react-types/shared": "^3.22.1", + "@react-types/well": "^3.3.7", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5895,14 +5883,14 @@ } }, "node_modules/@react-stately/calendar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/@react-stately/calendar/-/calendar-3.4.3.tgz", - "integrity": "sha512-OrEcdskszDjnjVnFuSiDC2PVBJ6lWMCJROD5s6W1LUehUtBp8LX9wPavAGHV43LbhN9ldj560sxaQ4WCddrRCA==", - "dependencies": { - "@internationalized/date": "^3.5.1", - "@react-stately/utils": "^3.9.0", - "@react-types/calendar": "^3.4.3", - "@react-types/shared": "^3.22.0", + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/@react-stately/calendar/-/calendar-3.4.4.tgz", + "integrity": "sha512-f9ZOd096gGGD+3LmU1gkmfqytGyQtrgi+Qjn+70GbM2Jy65pwOR4I9YrobbmeAFov5Tff13mQEa0yqWvbcDLZQ==", + "dependencies": { + "@internationalized/date": "^3.5.2", + "@react-stately/utils": "^3.9.1", + "@react-types/calendar": "^3.4.4", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5910,14 +5898,14 @@ } }, "node_modules/@react-stately/checkbox": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/@react-stately/checkbox/-/checkbox-3.6.2.tgz", - "integrity": "sha512-IzeyGd3MKoOAzvgbmds8wnCWRFUmQUznXEMxl1DbpqYpB+OH4nMS81D7yLSVeQPRtxcqKCSx+/98oycMThCilw==", + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/@react-stately/checkbox/-/checkbox-3.6.3.tgz", + "integrity": "sha512-hWp0GXVbMI4sS2NbBjWgOnHNrRqSV4jeftP8zc5JsIYRmrWBUZitxluB34QuVPzrBO29bGsF0GTArSiQZt6BWw==", "dependencies": { - "@react-stately/form": "^3.0.0", - "@react-stately/utils": "^3.9.0", - "@react-types/checkbox": "^3.7.0", - "@react-types/shared": "^3.22.0", + "@react-stately/form": "^3.0.1", + "@react-stately/utils": "^3.9.1", + "@react-types/checkbox": "^3.7.1", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5925,11 +5913,11 @@ } }, "node_modules/@react-stately/collections": { - "version": "3.10.4", - "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.10.4.tgz", - "integrity": "sha512-OHhCrItGt4zB2bSrgObRo0H2SC7QlkH8ReGxo+NVIWchXRLRoiWBP7S+IwleewEo5gOqDVPY3hqA9n4iiI8twg==", + "version": "3.10.5", + "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.10.5.tgz", + "integrity": "sha512-k8Q29Nnvb7iAia1QvTanZsrWP2aqVNBy/1SlE6kLL6vDqtKZC+Esd1SDLHRmIcYIp5aTdfwIGd0NuiRQA7a81Q==", "dependencies": { - "@react-types/shared": "^3.22.0", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5937,18 +5925,18 @@ } }, "node_modules/@react-stately/combobox": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@react-stately/combobox/-/combobox-3.8.1.tgz", - "integrity": "sha512-FaWkqTXQdWg7ptaeU4iPcqF/kxbRg2ZNUcvW/hiL/enciV5tRCsddvfNqvDvy1L30z9AUwlp9MWqzm/DhBITCw==", - "dependencies": { - "@react-stately/collections": "^3.10.4", - "@react-stately/form": "^3.0.0", - "@react-stately/list": "^3.10.2", - "@react-stately/overlays": "^3.6.4", - "@react-stately/select": "^3.6.1", - "@react-stately/utils": "^3.9.0", - "@react-types/combobox": "^3.10.0", - "@react-types/shared": "^3.22.0", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@react-stately/combobox/-/combobox-3.8.2.tgz", + "integrity": "sha512-f+IHuFW848VoMbvTfSakn2WIh2urDxO355LrKxnisXPCkpQHpq3lvT2mJtKJwkPxjAy7xPjpV8ejgga2R6p53Q==", + "dependencies": { + "@react-stately/collections": "^3.10.5", + "@react-stately/form": "^3.0.1", + "@react-stately/list": "^3.10.3", + "@react-stately/overlays": "^3.6.5", + "@react-stately/select": "^3.6.2", + "@react-stately/utils": "^3.9.1", + "@react-types/combobox": "^3.10.1", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5956,11 +5944,11 @@ } }, "node_modules/@react-stately/data": { - "version": "3.11.1", - "resolved": "https://registry.npmjs.org/@react-stately/data/-/data-3.11.1.tgz", - "integrity": "sha512-JedDhZ5e6Qetf+TGXKBdVVEvB50BymNJHKRFRQ9E3mmh/KFeY4V8THHKrNE/BhzB6Z3onsp5r14Z66Nku+klTg==", + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/@react-stately/data/-/data-3.11.2.tgz", + "integrity": "sha512-yhK2upk2WbJeiLBRWHrh/4G2CvmmozCzoivLaRAPYu53m1J3MyzVGCLJgnZMbMZvAbNcYWZK6IzO6VqZ2y1fOw==", "dependencies": { - "@react-types/shared": "^3.22.0", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5968,17 +5956,17 @@ } }, "node_modules/@react-stately/datepicker": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@react-stately/datepicker/-/datepicker-3.9.1.tgz", - "integrity": "sha512-o5xLvlZGJyAbTev2yruGlV2fzQyIDuYTgL19TTt0W0WCfjGGr/AAA9GjGXXmyoRA7sZMxqIPnnv7lNrdA38ofA==", - "dependencies": { - "@internationalized/date": "^3.5.1", - "@internationalized/string": "^3.2.0", - "@react-stately/form": "^3.0.0", - "@react-stately/overlays": "^3.6.4", - "@react-stately/utils": "^3.9.0", - "@react-types/datepicker": "^3.7.1", - "@react-types/shared": "^3.22.0", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@react-stately/datepicker/-/datepicker-3.9.2.tgz", + "integrity": "sha512-Z6FrK6Af7R5BizqHhJFCj3Hn32mg5iLSDdEgFQAuO043guOXUKFUAnbxfbQUjL6PGE6QwWMfQD7PPGebHn9Ifw==", + "dependencies": { + "@internationalized/date": "^3.5.2", + "@internationalized/string": "^3.2.1", + "@react-stately/form": "^3.0.1", + "@react-stately/overlays": "^3.6.5", + "@react-stately/utils": "^3.9.1", + "@react-types/datepicker": "^3.7.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5986,12 +5974,12 @@ } }, "node_modules/@react-stately/dnd": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/@react-stately/dnd/-/dnd-3.2.7.tgz", - "integrity": "sha512-QqSCvE9Rhp+Mr8Mt/SrByze24BFX1cy7gmXbwoqAYgHNIx3gWCVdBLqxfpfgYIhZdF9H72EWS8lQkfkZla06Ng==", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/@react-stately/dnd/-/dnd-3.2.8.tgz", + "integrity": "sha512-oSo+2Bzum3Q1/d+3FuaDmpVHqqBB004tycuQDDFtad3N1BKm+fNfmslRK1ioLkPLK4sm1130V+BZBY3JXLe80A==", "dependencies": { - "@react-stately/selection": "^3.14.2", - "@react-types/shared": "^3.22.0", + "@react-stately/selection": "^3.14.3", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5999,9 +5987,9 @@ } }, "node_modules/@react-stately/flags": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.0.0.tgz", - "integrity": "sha512-e3i2ItHbIa0eEwmSXAnPdD7K8syW76JjGe8ENxwFJPW/H1Pu9RJfjkCb/Mq0WSPN/TpxBb54+I9TgrGhbCoZ9w==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.0.1.tgz", + "integrity": "sha512-h5PcDMj54aipQNO18ig/IMI1kzPwcvSwVq5M6Ib6XE1WIkOH0dIuW2eADdAOhcGi3KXJtXVdD29zh0Eox1TKgQ==", "dependencies": { "@swc/helpers": "^0.4.14" } @@ -6016,11 +6004,11 @@ } }, "node_modules/@react-stately/form": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@react-stately/form/-/form-3.0.0.tgz", - "integrity": "sha512-C8wkfFmtx1escizibhdka5JvTy9/Vp173CS9cakjvWTmnjYYC1nOlzwp7BsYWTgerCFbRY/BU/Cf/bJDxPiUKQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@react-stately/form/-/form-3.0.1.tgz", + "integrity": "sha512-T1Ul2Ou0uE/S4ECLcGKa0OfXjffdjEHfUFZAk7OZl0Mqq/F7dl5WpoLWJ4d4IyvZzGO6anFNenP+vODWbrF3NA==", "dependencies": { - "@react-types/shared": "^3.22.0", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6028,14 +6016,14 @@ } }, "node_modules/@react-stately/grid": { - "version": "3.8.4", - "resolved": "https://registry.npmjs.org/@react-stately/grid/-/grid-3.8.4.tgz", - "integrity": "sha512-rwqV1K4lVhaiaqJkt4TfYqdJoVIyqvSm98rKAYfCNzrKcivVpoiCMJ2EMt6WlYCjDVBdEOQ7fMV1I60IV0pntA==", - "dependencies": { - "@react-stately/collections": "^3.10.4", - "@react-stately/selection": "^3.14.2", - "@react-types/grid": "^3.2.3", - "@react-types/shared": "^3.22.0", + "version": "3.8.5", + "resolved": "https://registry.npmjs.org/@react-stately/grid/-/grid-3.8.5.tgz", + "integrity": "sha512-KCzi0x0p1ZKK+OptonvJqMbn6Vlgo6GfOIlgcDd0dNYDP8TJ+3QFJAFre5mCr7Fubx7LcAOio4Rij0l/R8fkXQ==", + "dependencies": { + "@react-stately/collections": "^3.10.5", + "@react-stately/selection": "^3.14.3", + "@react-types/grid": "^3.2.4", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6043,16 +6031,16 @@ } }, "node_modules/@react-stately/layout": { - "version": "3.13.6", - "resolved": "https://registry.npmjs.org/@react-stately/layout/-/layout-3.13.6.tgz", - "integrity": "sha512-lfkLbPjwsvmA/Rk4OodtrBfFNiApvk5t2cehYHtUU5OFvHGaqt/n//dZ85XI2ooUq1FwfBZZ0ZXAAvJeaWR1QA==", - "dependencies": { - "@react-stately/collections": "^3.10.4", - "@react-stately/table": "^3.11.5", - "@react-stately/virtualizer": "^3.6.7", - "@react-types/grid": "^3.2.3", - "@react-types/shared": "^3.22.0", - "@react-types/table": "^3.9.2", + "version": "3.13.7", + "resolved": "https://registry.npmjs.org/@react-stately/layout/-/layout-3.13.7.tgz", + "integrity": "sha512-9HH/aSxpEHwUW1T1vGN3+iznkAXQUzoMrsoEepNzesOsUGSm/MFZmEk4+9cdPA7y3ou2eHpGNUB1YIDDVptElg==", + "dependencies": { + "@react-stately/collections": "^3.10.5", + "@react-stately/table": "^3.11.6", + "@react-stately/virtualizer": "^3.6.8", + "@react-types/grid": "^3.2.4", + "@react-types/shared": "^3.22.1", + "@react-types/table": "^3.9.3", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6060,14 +6048,14 @@ } }, "node_modules/@react-stately/list": { - "version": "3.10.2", - "resolved": "https://registry.npmjs.org/@react-stately/list/-/list-3.10.2.tgz", - "integrity": "sha512-INt+zofkIg2KN8B95xPi9pJG7ZFWAm30oIm/lCPBqM3K1Nm03/QaAbiQj2QeJcOsG3lb7oqI6D6iwTolwJkjIQ==", - "dependencies": { - "@react-stately/collections": "^3.10.4", - "@react-stately/selection": "^3.14.2", - "@react-stately/utils": "^3.9.0", - "@react-types/shared": "^3.22.0", + "version": "3.10.3", + "resolved": "https://registry.npmjs.org/@react-stately/list/-/list-3.10.3.tgz", + "integrity": "sha512-Ul8el0tQy2Ucl3qMQ0fiqdJ874W1ZNjURVSgSxN+pGwVLNBVRjd6Fl7YwZFCXER2YOlzkwg+Zqozf/ZlS0EdXA==", + "dependencies": { + "@react-stately/collections": "^3.10.5", + "@react-stately/selection": "^3.14.3", + "@react-stately/utils": "^3.9.1", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6075,13 +6063,13 @@ } }, "node_modules/@react-stately/menu": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@react-stately/menu/-/menu-3.6.0.tgz", - "integrity": "sha512-OB6CjNyfOkAuirqx1oTL8z8epS9WDzLyrXjmRnxdiCU9EgRXLGAQNECuO7VIpl58oDry8tgRJiJ8fn8FivWSQA==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@react-stately/menu/-/menu-3.6.1.tgz", + "integrity": "sha512-3v0vkTm/kInuuG8jG7jbxXDBnMQcoDZKWvYsBQq7+POt0LmijbLdbdZPBoz9TkZ3eo/OoP194LLHOaFTQyHhlw==", "dependencies": { - "@react-stately/overlays": "^3.6.4", - "@react-types/menu": "^3.9.6", - "@react-types/shared": "^3.22.0", + "@react-stately/overlays": "^3.6.5", + "@react-types/menu": "^3.9.7", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6089,14 +6077,14 @@ } }, "node_modules/@react-stately/numberfield": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@react-stately/numberfield/-/numberfield-3.9.0.tgz", - "integrity": "sha512-8O802S38e1htZbSzpPjbbIGAGxGC/DIzcW8H03UmBXiIFosEjpdmm8qRrJbhGfJGpwnehtzJQ6EaOLgLZMCFKg==", - "dependencies": { - "@internationalized/number": "^3.5.0", - "@react-stately/form": "^3.0.0", - "@react-stately/utils": "^3.9.0", - "@react-types/numberfield": "^3.8.0", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@react-stately/numberfield/-/numberfield-3.9.1.tgz", + "integrity": "sha512-btBIcBEfSVCUm6NwJrMrMygoIu/fQGazzD0RhF7PNsfvkFiWn+TSOyQqSXcsUJVOnBfoS/dVWj6r57KA7zl3FA==", + "dependencies": { + "@internationalized/number": "^3.5.1", + "@react-stately/form": "^3.0.1", + "@react-stately/utils": "^3.9.1", + "@react-types/numberfield": "^3.8.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6104,12 +6092,12 @@ } }, "node_modules/@react-stately/overlays": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.6.4.tgz", - "integrity": "sha512-tHEaoAGpE9dSnsskqLPVKum59yGteoSqsniTopodM+miQozbpPlSjdiQnzGLroy5Afx5OZYClE616muNHUILXA==", + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.6.5.tgz", + "integrity": "sha512-U4rCFj6TPJPXLUvYXAcvh+yP/CO2W+7f0IuqP7ZZGE+Osk9qFkT+zRK5/6ayhBDFpmueNfjIEAzT9gYPQwNHFw==", "dependencies": { - "@react-stately/utils": "^3.9.0", - "@react-types/overlays": "^3.8.4", + "@react-stately/utils": "^3.9.1", + "@react-types/overlays": "^3.8.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6117,14 +6105,14 @@ } }, "node_modules/@react-stately/radio": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@react-stately/radio/-/radio-3.10.1.tgz", - "integrity": "sha512-MsBYbcLCvjKsqTAKe43T681F2XwKMsS7PLG0eplZgWP9210AMY78GeY1XPYZKHPAau8XkbYiuJqbqTerIJ3DBw==", + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/@react-stately/radio/-/radio-3.10.2.tgz", + "integrity": "sha512-JW5ZWiNMKcZvMTsuPeWJQLHXD5rlqy7Qk6fwUx/ZgeibvMBW/NnW19mm2+IMinzmbtERXvR6nsiA837qI+4dew==", "dependencies": { - "@react-stately/form": "^3.0.0", - "@react-stately/utils": "^3.9.0", - "@react-types/radio": "^3.7.0", - "@react-types/shared": "^3.22.0", + "@react-stately/form": "^3.0.1", + "@react-stately/utils": "^3.9.1", + "@react-types/radio": "^3.7.1", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6132,12 +6120,12 @@ } }, "node_modules/@react-stately/searchfield": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/@react-stately/searchfield/-/searchfield-3.5.0.tgz", - "integrity": "sha512-SStjChkn/33pEn40slKQPnBnmQYyxVazVwPjiBkdeVejC42lUVairUTrGJgF0PNoZTbxn0so2/XzjqTC9T8iCw==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@react-stately/searchfield/-/searchfield-3.5.1.tgz", + "integrity": "sha512-9A8Wghx1avRHhMpNH1Nj+jFfiF1bhsff2GEC5PZgWYzhCykw3G5bywn3JAuUS4kh7Vpqhbu4KpHAhmWPSv4B/Q==", "dependencies": { - "@react-stately/utils": "^3.9.0", - "@react-types/searchfield": "^3.5.2", + "@react-stately/utils": "^3.9.1", + "@react-types/searchfield": "^3.5.3", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6145,15 +6133,15 @@ } }, "node_modules/@react-stately/select": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@react-stately/select/-/select-3.6.1.tgz", - "integrity": "sha512-e5ixtLiYLlFWM8z1msDqXWhflF9esIRfroptZsltMn1lt2iImUlDRlOTZlMtPQzUrDWoiHXRX88sSKUM/jXjQQ==", - "dependencies": { - "@react-stately/form": "^3.0.0", - "@react-stately/list": "^3.10.2", - "@react-stately/overlays": "^3.6.4", - "@react-types/select": "^3.9.1", - "@react-types/shared": "^3.22.0", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@react-stately/select/-/select-3.6.2.tgz", + "integrity": "sha512-duOxdHKol93h6Ew6fap6Amz+zngoERKZLSKVm/8I8uaBgkoBhEeTFv7mlpHTgINxymMw3mMrvy6GL/gfKFwkqg==", + "dependencies": { + "@react-stately/form": "^3.0.1", + "@react-stately/list": "^3.10.3", + "@react-stately/overlays": "^3.6.5", + "@react-types/select": "^3.9.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6161,13 +6149,13 @@ } }, "node_modules/@react-stately/selection": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/@react-stately/selection/-/selection-3.14.2.tgz", - "integrity": "sha512-mL7OoiUgVWaaF7ks5XSxgbXeShijYmD4G3bkBHhqkpugU600QH6BM2hloCq8KOUupk1y8oTljPtF9EmCv375DA==", + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/@react-stately/selection/-/selection-3.14.3.tgz", + "integrity": "sha512-d/t0rIWieqQ7wjLoMoWnuHEUSMoVXxkPBFuSlJF3F16289FiQ+b8aeKFDzFTYN7fFD8rkZTnpuE4Tcxg3TmA+w==", "dependencies": { - "@react-stately/collections": "^3.10.4", - "@react-stately/utils": "^3.9.0", - "@react-types/shared": "^3.22.0", + "@react-stately/collections": "^3.10.5", + "@react-stately/utils": "^3.9.1", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6175,13 +6163,13 @@ } }, "node_modules/@react-stately/slider": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@react-stately/slider/-/slider-3.5.1.tgz", - "integrity": "sha512-NRZ5m1wOVxGZF1CQC6hOzt/LmHNUF2xpFSkzN29fW/InPH4jb3BuOkRbbWv76QaVe0Kdg2ZLWcMl2+Qt6adIeQ==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@react-stately/slider/-/slider-3.5.2.tgz", + "integrity": "sha512-ntH3NLRG+AwVC7q4Dx9DcmMkMh9vmHjHNXAgaoqNjhvwfSIae7sQ69CkVe6XeJjIBy6LlH81Kgapz+ABe5a1ZA==", "dependencies": { - "@react-stately/utils": "^3.9.0", - "@react-types/shared": "^3.22.0", - "@react-types/slider": "^3.7.0", + "@react-stately/utils": "^3.9.1", + "@react-types/shared": "^3.22.1", + "@react-types/slider": "^3.7.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6189,18 +6177,18 @@ } }, "node_modules/@react-stately/table": { - "version": "3.11.5", - "resolved": "https://registry.npmjs.org/@react-stately/table/-/table-3.11.5.tgz", - "integrity": "sha512-l84iZJxpR0vlprHNEeGCVZTjOivP5fLpllmG+GswGxN4JXDqCEZ6gCQzpXxLyQTyBZ8lTRmmmmW20V2nCmDO4w==", - "dependencies": { - "@react-stately/collections": "^3.10.4", - "@react-stately/flags": "^3.0.0", - "@react-stately/grid": "^3.8.4", - "@react-stately/selection": "^3.14.2", - "@react-stately/utils": "^3.9.0", - "@react-types/grid": "^3.2.3", - "@react-types/shared": "^3.22.0", - "@react-types/table": "^3.9.2", + "version": "3.11.6", + "resolved": "https://registry.npmjs.org/@react-stately/table/-/table-3.11.6.tgz", + "integrity": "sha512-34YsfOILXusj3p6QNcKEaDWVORhM6WEhwPSLCZlkwAJvkxuRQFdih5rQKoIDc0uV5aZsB6bYBqiFhnjY0VERhw==", + "dependencies": { + "@react-stately/collections": "^3.10.5", + "@react-stately/flags": "^3.0.1", + "@react-stately/grid": "^3.8.5", + "@react-stately/selection": "^3.14.3", + "@react-stately/utils": "^3.9.1", + "@react-types/grid": "^3.2.4", + "@react-types/shared": "^3.22.1", + "@react-types/table": "^3.9.3", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6208,13 +6196,13 @@ } }, "node_modules/@react-stately/tabs": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/@react-stately/tabs/-/tabs-3.6.3.tgz", - "integrity": "sha512-Nj+Gacwa2SIzYIvHW40GsyX4Q6c8kF7GOuXESeQswbCjnwqhrSbDBp+ngPcUPUJxqFh6JhDCVwAS3wMhUoyUwA==", + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/@react-stately/tabs/-/tabs-3.6.4.tgz", + "integrity": "sha512-WZJgMBqzLgN88RN8AxhY4aH1+I+4w1qQA0Lh3LRSDegaytd+NHixCWaP3IPjePgCB5N1UsPe96Xglw75zjHmDg==", "dependencies": { - "@react-stately/list": "^3.10.2", - "@react-types/shared": "^3.22.0", - "@react-types/tabs": "^3.3.4", + "@react-stately/list": "^3.10.3", + "@react-types/shared": "^3.22.1", + "@react-types/tabs": "^3.3.5", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6222,12 +6210,12 @@ } }, "node_modules/@react-stately/toggle": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@react-stately/toggle/-/toggle-3.7.1.tgz", - "integrity": "sha512-pZyhPJNdhidm/Uq/Pt58H0I6CUNyfnhfGAAn9Et6T3/SymcX1Zti5mZg5gXgICFlwGbucfLBe+Jt691Rnt2vaA==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@react-stately/toggle/-/toggle-3.7.2.tgz", + "integrity": "sha512-SHCF2btcoK57c4lyhucRbyPBAFpp0Pdp0vcPdn3hUgqbu6e5gE0CwG/mgFmZRAQoc7PRc7XifL0uNw8diJJI0Q==", "dependencies": { - "@react-stately/utils": "^3.9.0", - "@react-types/checkbox": "^3.7.0", + "@react-stately/utils": "^3.9.1", + "@react-types/checkbox": "^3.7.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6235,12 +6223,12 @@ } }, "node_modules/@react-stately/tooltip": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/@react-stately/tooltip/-/tooltip-3.4.6.tgz", - "integrity": "sha512-uL93bmsXf+OOgpKLPEKfpDH4z+MK2CuqlqVxx7rshN0vjWOSoezE5nzwgee90+RpDrLNNNWTNa7n+NkDRpI1jA==", + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/@react-stately/tooltip/-/tooltip-3.4.7.tgz", + "integrity": "sha512-ACtRgBQ8rphBtsUaaxvEAM0HHN9PvMuyvL0vUHd7jvBDCVZJ6it1BKu9SBKjekBkoBOw9nemtkplh9R2CA6V8Q==", "dependencies": { - "@react-stately/overlays": "^3.6.4", - "@react-types/tooltip": "^3.4.6", + "@react-stately/overlays": "^3.6.5", + "@react-types/tooltip": "^3.4.7", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6248,14 +6236,14 @@ } }, "node_modules/@react-stately/tree": { - "version": "3.7.5", - "resolved": "https://registry.npmjs.org/@react-stately/tree/-/tree-3.7.5.tgz", - "integrity": "sha512-xTJVwvhAeY0N5rui4N/TxN7f8hjXdqApDuGDxMZeFAWoQz8Abf7LFKBVQ3OkT6qVr7P+23dgoisUDBhD5a45Hg==", - "dependencies": { - "@react-stately/collections": "^3.10.4", - "@react-stately/selection": "^3.14.2", - "@react-stately/utils": "^3.9.0", - "@react-types/shared": "^3.22.0", + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/@react-stately/tree/-/tree-3.7.6.tgz", + "integrity": "sha512-y8KvEoZX6+YvqjNCVGS3zA/BKw4D3XrUtUKIDme3gu5Mn6z97u+hUXKdXVCniZR7yvV3fHAIXwE5V2K8Oit4aw==", + "dependencies": { + "@react-stately/collections": "^3.10.5", + "@react-stately/selection": "^3.14.3", + "@react-stately/utils": "^3.9.1", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6263,9 +6251,9 @@ } }, "node_modules/@react-stately/utils": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.9.0.tgz", - "integrity": "sha512-yPKFY1F88HxuZ15BG2qwAYxtpE4HnIU0Ofi4CuBE0xC6I8mwo4OQjDzi+DZjxQngM9D6AeTTD6F1V8gkozA0Gw==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.9.1.tgz", + "integrity": "sha512-yzw75GE0iUWiyps02BOAPTrybcsMIxEJlzXqtvllAb01O9uX5n0i3X+u2eCpj2UoDF4zS08Ps0jPgWxg8xEYtA==", "dependencies": { "@swc/helpers": "^0.5.0" }, @@ -6274,12 +6262,12 @@ } }, "node_modules/@react-stately/virtualizer": { - "version": "3.6.7", - "resolved": "https://registry.npmjs.org/@react-stately/virtualizer/-/virtualizer-3.6.7.tgz", - "integrity": "sha512-huhQSrfwiUq2idceSE2aQ54d9gttAovKDtw7uERWFt+UAxiprWq8hr6sl7rTdN2NB7fz/t+MAJJuwWMkzLUlOw==", + "version": "3.6.8", + "resolved": "https://registry.npmjs.org/@react-stately/virtualizer/-/virtualizer-3.6.8.tgz", + "integrity": "sha512-Pf06ihTwExRJltGhi72tmLIo0pcjkL55nu7ifMafAAdxZK4ONxRLSuUjjpvYf/0Rs92xRZy2t/XmHREnfirdkQ==", "dependencies": { - "@react-aria/utils": "^3.23.1", - "@react-types/shared": "^3.22.0", + "@react-aria/utils": "^3.23.2", + "@react-types/shared": "^3.22.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6287,470 +6275,470 @@ } }, "node_modules/@react-types/actionbar": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@react-types/actionbar/-/actionbar-3.1.4.tgz", - "integrity": "sha512-/z9N7ztd/MOdEDQNHTCNviYe0+rqy1s19Xg3tv/PV1oUCOsjrnja85VVxoa+AWR8IbwgDNIfpXg2Wa66b1FDbw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@react-types/actionbar/-/actionbar-3.1.5.tgz", + "integrity": "sha512-Z3hfIoaOaW8wJxQm1NyWVvSftpNDYv9iWqpEWBEdhxuqsUkOVszZ7KcNaF4qsm4bJIcJWn3FNKhaTKGwISZcdQ==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/actiongroup": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/@react-types/actiongroup/-/actiongroup-3.4.6.tgz", - "integrity": "sha512-Dho2mEDCU9ZAW+QX2HZkZhyxHK/EGfTvSWdHBFaCYsh4CPI/6PcvtirpSKMrzNNaZ97Exthv3GcLpAnLwM9jZw==", + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/@react-types/actiongroup/-/actiongroup-3.4.7.tgz", + "integrity": "sha512-VsyHn6mGqEHKEIGFiHTq7rSuzuQjGVZGtnhh/9jQXW6zoSJyoM4fAnHEt+RE92NdiRv5e3+OzzrwG0TZsi87cQ==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/avatar": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@react-types/avatar/-/avatar-3.0.4.tgz", - "integrity": "sha512-fQ+qGce0EqcX0s2glnFjfvxSq42GHaqvl+eL8TnsDz0OIvB8KKzTO/rV/q1CIy/LtMP8fjCb6oqVFQcLfuODfw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@react-types/avatar/-/avatar-3.0.5.tgz", + "integrity": "sha512-/hM/BnRoUhusT16G4hf2hfe4FocxaM5H/a7aetUrmlr9e5ppX3n0VsU0btIwxdh+aJL8u2BBt2scoiJaujQPNg==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/badge": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@react-types/badge/-/badge-3.1.6.tgz", - "integrity": "sha512-6xjgfRnCVSBI6l/RQkI4u3tXiXw1aeFKRqXPcyIyt/kuu7rP0nKeYcM2XYyXXQp7vHfBdOEL2f6LwIHR/lx4uQ==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@react-types/badge/-/badge-3.1.7.tgz", + "integrity": "sha512-2Q5W9gleI83WpL1i6qPdcPC8l1V7364dpkNLcMi9DFmM2l69+QcPvSWVQMQLevmRo4cnaQ+TYsOgYv8I4rRJCg==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/breadcrumbs": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@react-types/breadcrumbs/-/breadcrumbs-3.7.2.tgz", - "integrity": "sha512-esl6RucDW2CNMsApJxNYfMtDaUcfLlwKMPH/loYsOBbKxGl2HsgVLMcdpjEkTRs2HCTNCbBXWpeU8AY77t+bsw==", + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@react-types/breadcrumbs/-/breadcrumbs-3.7.3.tgz", + "integrity": "sha512-eFto/+6J+JR58vThNcALZRA1OlqlG3GzQ/bq3q8IrrkOZcrfbEJJCWit/+53Ia98siJKuF4OJHnotxIVIz5I3w==", "dependencies": { - "@react-types/link": "^3.5.2", - "@react-types/shared": "^3.22.0" + "@react-types/link": "^3.5.3", + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/button": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.9.1.tgz", - "integrity": "sha512-bf9iTar3PtqnyV9rA+wyFyrskZKhwmOuOd/ifYIjPs56YNVXWH5Wfqj6Dx3xdFBgtKx8mEVQxVhoX+WkHX+rtw==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.9.2.tgz", + "integrity": "sha512-EnPTkGHZRtiwAoJy5q9lDjoG30bEzA/qnvKG29VVXKYAGeqY2IlFs1ypmU+z1X/CpJgPcG3I5cakM7yTVm3pSg==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/buttongroup": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/@react-types/buttongroup/-/buttongroup-3.3.6.tgz", - "integrity": "sha512-aKFDzAWM6bk2+EBDSZe3zq4NMuguXsPyZ9OexN0YLleK4IkRKE2S51PdChY/GAFhfs7VsOKgjHrYWUnrmCCYvw==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@react-types/buttongroup/-/buttongroup-3.3.7.tgz", + "integrity": "sha512-EZ/1k66GtDtWfE/udNRz2UBbt4YJumeyW1SGcZEO3jketvpms58WapLsMkCezlLz7WYaa5ADV0kU8v88APjI6g==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/calendar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/@react-types/calendar/-/calendar-3.4.3.tgz", - "integrity": "sha512-96x57ctX5wNEl+8et3sc2NQm8neOJayEeqOQQpyPtI7jyvst/xBrKCwysf9W/dhgPlUC+KeBAYFWfjd5hFVHYA==", + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/@react-types/calendar/-/calendar-3.4.4.tgz", + "integrity": "sha512-hV1Thmb/AES5OmfPvvmyjSkmsEULjiDfA7Yyy70L/YKuSNKb7Su+Bf2VnZuDW3ec+GxO4JJNlpJ0AkbphWBvcg==", "dependencies": { - "@internationalized/date": "^3.5.1", - "@react-types/shared": "^3.22.0" + "@internationalized/date": "^3.5.2", + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/checkbox": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.7.0.tgz", - "integrity": "sha512-3ZW/+Fh5GkL7mQhayyESB9+YQ6y7nImLQ8jB2lg42esaK5UF7IpG3xlrYm2z4KWLvQFXncX7SJsnwzYiBMLY+g==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.7.1.tgz", + "integrity": "sha512-kuGqjQFex0As/3gfWyk+e9njCcad/ZdnYLLiNvhlk15730xfa0MmnOdpqo9jfuFSXBjOcpxoofvEhvrRMtEdUA==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/combobox": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/@react-types/combobox/-/combobox-3.10.0.tgz", - "integrity": "sha512-1IXSNS02TPbguyYopaW2snU6sZusbClHrEyVr4zPeexTV4kpUUBNXOzFQ+eSQRR0r2XW57Z0yRW4GJ6FGU0yCA==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@react-types/combobox/-/combobox-3.10.1.tgz", + "integrity": "sha512-XMno1rgVRNta49vf5nV7VJpVSVAV20tt79t618gG1qRKH5Kt2Cy8lz2fQ5vHG6UTv/6jUOvU8g5Pc93sLaTmoA==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/contextualhelp": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/@react-types/contextualhelp/-/contextualhelp-3.2.7.tgz", - "integrity": "sha512-BHwBSBhPekKc/PxDpnkvfcEgpaYLMrV6WYgMfUz2/BMYOjdm+pb1y80vpNkWtrJKytyqp1zeZ+Ca+xzX1HdazA==", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/@react-types/contextualhelp/-/contextualhelp-3.2.8.tgz", + "integrity": "sha512-Yb0zOqkWfjKCO+gpfVj69CfWPhVq6RTgwLBV47ntIlHitpbh7RDYwDVulPyaVoopPbNSFUoV4YIJZPlOgpbKjg==", "dependencies": { - "@react-types/overlays": "^3.8.4", - "@react-types/shared": "^3.22.0" + "@react-types/overlays": "^3.8.5", + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/datepicker": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@react-types/datepicker/-/datepicker-3.7.1.tgz", - "integrity": "sha512-5juVDULOytNzkotqX8j5mYKJckeIpkgbHqVSGkPgLw0++FceIaSZ6RH56cqLup0pO45paqIt9zHh+QXBYX+syg==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@react-types/datepicker/-/datepicker-3.7.2.tgz", + "integrity": "sha512-zThqFAdhQL1dqyVDsDSSTdfCjoD6634eyg/B0ZJfQxcLUR/5pch3v/gxBhbyCVDGMNHRWUWIJvY9DVOepuoSug==", "dependencies": { - "@internationalized/date": "^3.5.1", - "@react-types/calendar": "^3.4.3", - "@react-types/overlays": "^3.8.4", - "@react-types/shared": "^3.22.0" + "@internationalized/date": "^3.5.2", + "@react-types/calendar": "^3.4.4", + "@react-types/overlays": "^3.8.5", + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/dialog": { - "version": "3.5.7", - "resolved": "https://registry.npmjs.org/@react-types/dialog/-/dialog-3.5.7.tgz", - "integrity": "sha512-geYoqAyQaTLG43AaXdMUVqZXYgkSifrD9cF7lR2kPAT0uGFv0YREi6ieU+aui8XJ83EW0xcxP+EPWd2YkN4D4w==", + "version": "3.5.8", + "resolved": "https://registry.npmjs.org/@react-types/dialog/-/dialog-3.5.8.tgz", + "integrity": "sha512-RX8JsMvty8ADHRqVEkppoynXLtN4IzUh8d5z88UEBbcvWKlHfd6bOBQjQcBH3AUue5wjfpPIt6brw2VzgBY/3Q==", "dependencies": { - "@react-types/overlays": "^3.8.4", - "@react-types/shared": "^3.22.0" + "@react-types/overlays": "^3.8.5", + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/divider": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/@react-types/divider/-/divider-3.3.6.tgz", - "integrity": "sha512-Iwwe349IiCX7ZQK1Oz4AN5kWwiXG0DECSN4qB3h+14n97JKy3chWJC7UA+V6+2p5DbxmLVZm4XxDRgx7y0lVTg==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@react-types/divider/-/divider-3.3.7.tgz", + "integrity": "sha512-enAlzHVwzqBPpmE+/VAO5IGVPxPrscHkdbnEkTqW9JQeMUGXd4L0TdHOGd+vtcA+gILJMnhUfT3XE4wQ4HlpVw==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/form": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@react-types/form/-/form-3.7.1.tgz", - "integrity": "sha512-Wr44McYcB5Od3SwMzLhe1qaaZIy+YUe16jYRc/0io1gyCELXmplpIw8VQmf9/x62ze9CC/aZVdEJ/V9CogXmOA==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@react-types/form/-/form-3.7.2.tgz", + "integrity": "sha512-6/isEJY4PsYoHdMaGQtqQyquXGTwB1FqCBOPKQjI/vBGWG3fL7FGfWm4Z62eTbCH4Xyv3FZuNywlT8UjPMQyKA==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/grid": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@react-types/grid/-/grid-3.2.3.tgz", - "integrity": "sha512-GQM4RDmYhstcYZ0Odjq+xUwh1fhLmRebG6qMM8OXHTPQ77nhl3wc1UTGRhZm6mzEionplSRx4GCpEMEHMJIU0w==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@react-types/grid/-/grid-3.2.4.tgz", + "integrity": "sha512-sDVoyQcH7MoGdx5nBi5ZOU/mVFBt9YTxhvr0PZ97dMdEHZtJC1w9SuezwWS34f50yb8YAXQRTICbZYcK4bAlDA==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/illustratedmessage": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/@react-types/illustratedmessage/-/illustratedmessage-3.3.6.tgz", - "integrity": "sha512-1FdJl1tR6mirmXT8yaTFeHNWdLXV6Dll66Mv1liEtTYsmCgn2anxwM73jK63t3jdT6ez/M1wGiwMlMtyiqo+ZQ==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@react-types/illustratedmessage/-/illustratedmessage-3.3.7.tgz", + "integrity": "sha512-r8WAv+w0WQSDRmDmG6jL0dXK8MjMr/lr2gBpVYVvC45Gu+fqf4VL+4zphgwASRysWclFbjQhgkgC7OEXk3GUKg==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/image": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/@react-types/image/-/image-3.3.6.tgz", - "integrity": "sha512-GSb0deyquS3kFt0e9SfPP9I/YaYYUToYYPzx9As0R0mzuVn6qTHhUtpKhBqQAOpE1Cd8XdEQeYsDB3sdOurI+A==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@react-types/image/-/image-3.3.7.tgz", + "integrity": "sha512-ty6wuan6p3Z8OzSrbjtL2k8yXHW+n0qiYKyqKpSA8TcRLDLhtvRceI7X12RuDfbAiEN6/zfLCuF47O3y7OeKug==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/label": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@react-types/label/-/label-3.9.0.tgz", - "integrity": "sha512-nTmPf5ED8aLGqvFsZHIHwMPrRX0cfbOyayva//Rdis41KWQoKUB80DIQjE+iUDOgTivIxGBkpqdIZVqRuehTnw==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@react-types/label/-/label-3.9.1.tgz", + "integrity": "sha512-0N/UOhwrKjE9VjVbUoJCsH5UwTzSu3d5B3xtvhH8YFqSbJCI+HMKILby8i8ys55RA9fQDMScIjCJafEFWW7UWA==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/layout": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/@react-types/layout/-/layout-3.3.12.tgz", - "integrity": "sha512-Ai6limgTVYQoGiXUvsXg8MHik+YAtRWEVLQhT5E1nQkDkNkQyccB+waUSfORhRkjJcnp+KMcbmPZ8V5ZO42rvQ==", + "version": "3.3.13", + "resolved": "https://registry.npmjs.org/@react-types/layout/-/layout-3.3.13.tgz", + "integrity": "sha512-Y3pmSsfDB+bV299F5SJannR6m/XM5IyfdqjPS0/Qx8KBBf0A3UWfL6qUr4BMEAKsEJuIXA7zT3RSo/AbGSbSyg==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/link": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@react-types/link/-/link-3.5.2.tgz", - "integrity": "sha512-/s51/WejmpLiyxOgP89s4txgxYoGaPe8pVDItVo1h4+BhU1Puyvgv/Jx8t9dPvo6LUXbraaN+SgKk/QDxaiirw==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/@react-types/link/-/link-3.5.3.tgz", + "integrity": "sha512-yVafjW3IejyVnK3oMBNjFABCGG6J27EUG8rvkaGaI1uB6srGUEhpJ97XLv11aj1QkXHBy3VGXqxEV3S7wn4HTw==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/listbox": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/@react-types/listbox/-/listbox-3.4.6.tgz", - "integrity": "sha512-XOQvrTqNh5WIPDvKiWiep8T07RAsMfjAXTjDbnjxVlKACUXkcwpts9kFaLnJ9LJRFt6DwItfP+WMkzvmx63/NQ==", + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/@react-types/listbox/-/listbox-3.4.7.tgz", + "integrity": "sha512-68y5H9CVSPFiwO6MOFxTbry9JQMK/Lb1M9i3M8TDyq1AbJxBPpgAvJ9RaqIMCucsnqCzpY/zA3D/X417zByL1w==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/menu": { - "version": "3.9.6", - "resolved": "https://registry.npmjs.org/@react-types/menu/-/menu-3.9.6.tgz", - "integrity": "sha512-w/RbFInOf4nNayQDv5c2L8IMJbcFOkBhsT3xvvpTy+CHvJcQdjggwaV1sRiw7eF/PwB81k2CwigmidUzHJhKDg==", + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/@react-types/menu/-/menu-3.9.7.tgz", + "integrity": "sha512-K6KhloJVoGsqwkdeez72fkNI9dfrmLI/sNrB4XuOKo2crDQ/eyZYWyJmzz8giz/tHME9w774k487rVoefoFh5w==", "dependencies": { - "@react-types/overlays": "^3.8.4", - "@react-types/shared": "^3.22.0" + "@react-types/overlays": "^3.8.5", + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/meter": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/@react-types/meter/-/meter-3.3.6.tgz", - "integrity": "sha512-1XYp1fA9UU0lO6kjf3TwVE8mppOJa64mBKAcLWtTyq1e/cYIAbx5o6CsuUx0YDpXKF6gdtvIWvfmxeWsmqJ1jQ==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@react-types/meter/-/meter-3.3.7.tgz", + "integrity": "sha512-p+YJ0+Lpn5MLmlbFZbDH1P0ILv1+AuMcUbxLcXMIVMGn7o0FO7eVZnFuq76D+qTDm9all+TRLJix7bctOrP+5Q==", "dependencies": { - "@react-types/progress": "^3.5.1" + "@react-types/progress": "^3.5.2" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/numberfield": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@react-types/numberfield/-/numberfield-3.8.0.tgz", - "integrity": "sha512-2xnVvOVVSnvzT5JxldJdVRh/IMry9//PyQ5VcK3ze0m+bcD6zZspIdspzu8jiYyUPmZLHN1cZzx5GZSak1V6ig==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@react-types/numberfield/-/numberfield-3.8.1.tgz", + "integrity": "sha512-GaCjLQgXUGCt40SLjKk3/COMWFlN2vV/3Xs3VSLAEdFZpk99b+Ik1oR21+7ZP5/iMHuQDc1MJRWdFfIjxCvVDQ==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/overlays": { - "version": "3.8.4", - "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.8.4.tgz", - "integrity": "sha512-pfgNlQnbF6RB/R2oSxyqAP3Uzz0xE/k5q4n5gUeCDNLjY5qxFHGE8xniZZ503nZYw6VBa9XMN1efDOKQyeiO0w==", + "version": "3.8.5", + "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.8.5.tgz", + "integrity": "sha512-4D7EEBQigD/m8hE68Ys8eloyyZFHHduqykSIgINJ0edmo0jygRbWlTwuhWFR9USgSP4dK54duN0Mvq0m4HEVEw==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/progress": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@react-types/progress/-/progress-3.5.1.tgz", - "integrity": "sha512-CqsUjczUK/SfuFzDcajBBaXRTW0D3G9S/yqLDj9e8E0ii+lGDLt1PHj24t1J7E88U2rVYqmM9VL4NHTt8o3IYA==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@react-types/progress/-/progress-3.5.2.tgz", + "integrity": "sha512-aQql22kusEudsHwDEzq6y/Mh29AM+ftRDKdS5E5g4MkCY5J4FMbOYco1T5So83NIvvG9+eKcxPoJUMjQQACAyA==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/provider": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@react-types/provider/-/provider-3.7.1.tgz", - "integrity": "sha512-WKwHwG5b0LkI570tbHCy4hBhT/E+OrdgIybScDxM713B2OwmMKKyaPKdV05SeoomP8oiPvkaAeXhLZa1ah7CYg==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@react-types/provider/-/provider-3.7.2.tgz", + "integrity": "sha512-nzxbfuh/ZJXt/blGAiRPkxi9jAUnnBkHcvljqdfizfLJlN5epaYYaTWNUSde27Oe1tAnpm2WDlLQo5+0C6C0FA==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/radio": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@react-types/radio/-/radio-3.7.0.tgz", - "integrity": "sha512-EcwGAXzSHjSqpFZha7xn3IUrhPiJLj+0yb1Ip0qPmhWz0VVw2DwrkY7q/jfaKroVvQhTo2TbfGhcsAQrt0fRqg==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@react-types/radio/-/radio-3.7.1.tgz", + "integrity": "sha512-Zut3rN1odIUBLZdijeyou+UqsLeRE76d9A+npykYGu29ndqmo3w4sLn8QeQcdj1IR71ZnG0pW2Y2BazhK5XrrQ==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/searchfield": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@react-types/searchfield/-/searchfield-3.5.2.tgz", - "integrity": "sha512-JAK2/Kg4Dr393FYfbRw0TlXKnJPX77sq1x/ZBxtO6p64+MuuIYKqw0i9PwDlo1PViw2QI5u8GFhKA2TgemY9uA==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/@react-types/searchfield/-/searchfield-3.5.3.tgz", + "integrity": "sha512-gBfsT1WpY8UIb74yyYmnjiHpVasph2mdmGj9i8cGF2HUYwx5p+Fr85mtCGDph0uirvRoM5ExMp4snD+ueNAVCg==", "dependencies": { - "@react-types/shared": "^3.22.0", - "@react-types/textfield": "^3.9.0" + "@react-types/shared": "^3.22.1", + "@react-types/textfield": "^3.9.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/select": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@react-types/select/-/select-3.9.1.tgz", - "integrity": "sha512-EpKSxrnh8HdZvOF9dHQkjivAcdIp1K81FaxmvosH8Lygqh0iYXxAdZGtKLMyBoPI8YFhA+rotIzTcOqgCCnqWA==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@react-types/select/-/select-3.9.2.tgz", + "integrity": "sha512-fGFrunednY3Pq/BBwVOf87Fsuyo/SlevL0wFIE9OOl2V5NXVaTY7/7RYA8hIOHPzmvsMbndy419BEudiNGhv4A==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/shared": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.22.0.tgz", - "integrity": "sha512-yVOekZWbtSmmiThGEIARbBpnmUIuePFlLyctjvCbgJgGhz8JnEJOipLQ/a4anaWfzAgzSceQP8j/K+VOOePleA==", + "version": "3.22.1", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.22.1.tgz", + "integrity": "sha512-PCpa+Vo6BKnRMuOEzy5zAZ3/H5tnQg1e80khMhK2xys0j6ZqzkgQC+fHMNZ7VDFNLqqNMj/o0eVeSBDh2POjkw==", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/slider": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@react-types/slider/-/slider-3.7.0.tgz", - "integrity": "sha512-uyQXUVFfqc9SPUW0LZLMan2n232F/OflRafiHXz9viLFa9tVOupVa7GhASRAoHojwkjoJ1LjFlPih7g5dOZ0/Q==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@react-types/slider/-/slider-3.7.1.tgz", + "integrity": "sha512-FKO3YZYdrBs00XbBW5acP+0L1cCdevl/uRJiXbnLpGysO5PrSFIRS7Wlv4M7ztf6gT7b1Ao4FNC9crbxBr6BzA==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/statuslight": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/@react-types/statuslight/-/statuslight-3.3.6.tgz", - "integrity": "sha512-MB/CnsbaE6reOrnpowJfgkpeSNY0ZuqA6g/k8331a+TP2yIO6X0cUYyEGG8S/k9hFyFCMKlcmmm4pwMrX4sZtQ==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@react-types/statuslight/-/statuslight-3.3.7.tgz", + "integrity": "sha512-PFctvM8NJFENNWHydEK4pCMXKmjrHB2PJ/fdJ2Bi6ABRcTBXzi/qgUUdbeTG7STXlA+P2/xNgKtHheus8K+K3g==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/switch": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/@react-types/switch/-/switch-3.5.0.tgz", - "integrity": "sha512-/wNmUGjk69bP6t5k2QkAdrNN5Eb9Rz4dOyp0pCPmoeE+5haW6sV5NmtkvWX1NSc4DQz1xL/a5b+A0vxPCP22Jw==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@react-types/switch/-/switch-3.5.1.tgz", + "integrity": "sha512-2LFEKMGeufqyYmeN/5dtkDkCPG6x9O4eu6aaBaJmPGon7C/l3yiFEgRue6oCUYc1HixR7Qlp0sPxk0tQeWzrSg==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/table": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@react-types/table/-/table-3.9.2.tgz", - "integrity": "sha512-brw5JUANOzBa2rYNpN8AIl9nDZ9RwRZC6G/wTM/JhtirjC1S42oCtf8Ap5rWJBdmMG/5KOfcGNcAl/huyqb3gg==", + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@react-types/table/-/table-3.9.3.tgz", + "integrity": "sha512-Hs/pMbxJdga2zBol4H5pV1FVIiRjCuSTXst6idJjkctanTexR4xkyrtBwl+rdLNoGwQ2pGii49vgklc5bFK7zA==", "dependencies": { - "@react-types/grid": "^3.2.3", - "@react-types/shared": "^3.22.0" + "@react-types/grid": "^3.2.4", + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/tabs": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@react-types/tabs/-/tabs-3.3.4.tgz", - "integrity": "sha512-4mCTtFrwMRypyGTZCvNYVT9CkknexO/UYvqwDm2jMYb8JgjRvxnomu776Yh7uyiYKWyql2upm20jqasEOm620w==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@react-types/tabs/-/tabs-3.3.5.tgz", + "integrity": "sha512-6NTSZBOWekCtApdZrhu5tHhE/8q52oVohQN+J5T7shAXd6ZAtu8PABVR/nH4BWucc8FL0OUajRqunqzQMU13gA==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/text": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/@react-types/text/-/text-3.3.6.tgz", - "integrity": "sha512-cO3IQ/DQ/xUGGskJ8/zCLkbzvrjlQbRnrJl95BEGs97CmiN+zqGoCqvDhjWEbuPRtfGXJ27CYZDC2oVZetUG4w==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@react-types/text/-/text-3.3.7.tgz", + "integrity": "sha512-URkJHS314ppyq6JjMPZbg/P4j9vey0H/Lc2+YB96qIcebBKy8iNN0IlwRsLFXimlGDp7dgn6tv+51bdJh+CRCQ==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/textfield": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@react-types/textfield/-/textfield-3.9.0.tgz", - "integrity": "sha512-D/DiwzsfkwlAg3uv8hoIfwju+zhB/hWDEdTvxQbPkntDr0kmN/QfI17NMSzbOBCInC4ABX87ViXLGxr940ykGA==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@react-types/textfield/-/textfield-3.9.1.tgz", + "integrity": "sha512-JBHY9M2CkL6xFaGSfWmUJVu3tEK09FaeB1dU3IEh6P41xxbFnPakYHSSAdnwMXBtXPoSHIVsUBickW/pjgfe5g==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/tooltip": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/@react-types/tooltip/-/tooltip-3.4.6.tgz", - "integrity": "sha512-RaZewdER7ZcsNL99RhVHs8kSLyzIBkwc0W6eFZrxST2MD9J5GzkVWRhIiqtFOd5U1aYnxdJ6woq72Ef+le6Vfw==", + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/@react-types/tooltip/-/tooltip-3.4.7.tgz", + "integrity": "sha512-rV4HZRQxLRNhe24yATOxnFQtGRUmsR7mqxMupXCmd1vrw8h+rdKlQv1zW2q8nALAKNmnRXZJHxYQ1SFzb98fgg==", "dependencies": { - "@react-types/overlays": "^3.8.4", - "@react-types/shared": "^3.22.0" + "@react-types/overlays": "^3.8.5", + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/view": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/@react-types/view/-/view-3.4.6.tgz", - "integrity": "sha512-GAdvvabJAYrVCgOUsZp8KkmNLfkKnDmoMNmwCN9I2OnSS+5JyjTrgNIOiznMjDEqhXTbaefcsVofoUfTYXjtyQ==", + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/@react-types/view/-/view-3.4.7.tgz", + "integrity": "sha512-AcgLrlaZkCXH+pD4I7pTPB52Rstg1M+V2yKPP29lnqg/rOjsqLjN/gLLy/EBi97cQ+TbDbg0854vcxAKs6qclg==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" } }, "node_modules/@react-types/well": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/@react-types/well/-/well-3.3.6.tgz", - "integrity": "sha512-NX4+bMmNYrbjllKR9Xxg0YHNWrscHzZQmcdYiM/Z8qZ1TNVPhXeLmKxCDamlmUSZudCqwui4q5xwzuUyrRRA6w==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@react-types/well/-/well-3.3.7.tgz", + "integrity": "sha512-BaZ4utlEeweD8+mAYdqwq2bS8aDrXqi4xFPdfqZpHcpbSJjmGBCCS+GU2y/N2Yl1aODu5l0+gcrvxxr63bV+GA==", "dependencies": { - "@react-types/shared": "^3.22.0" + "@react-types/shared": "^3.22.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" @@ -6793,12 +6781,12 @@ "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "node_modules/@spectrum-icons/ui": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/@spectrum-icons/ui/-/ui-3.6.4.tgz", - "integrity": "sha512-ojjICGgVaBeMKbeMB9/KCAs7l2ToJlNrJUVljkLv2Os6fukGHsAgVgO6wyw9diUIZGgentpx441+CQLooi9J6w==", + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/@spectrum-icons/ui/-/ui-3.6.5.tgz", + "integrity": "sha512-L1QISmlzoA4xuBdMpWT2vkR7NDxuROjSwC5BxS8R2SAZR4oKs0dPfODaw2uju6D/xqJIqVrSM6yQDhV51lPKyA==", "dependencies": { "@adobe/react-spectrum-ui": "1.2.0", - "@react-spectrum/icon": "^3.7.10", + "@react-spectrum/icon": "^3.7.11", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -6807,12 +6795,12 @@ } }, "node_modules/@spectrum-icons/workflow": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/@spectrum-icons/workflow/-/workflow-4.2.9.tgz", - "integrity": "sha512-JdDzhnI7ASToodB1V5iy/CZNNHXxE7fwaPCS4+BpdwoibowgK5c1tnu1nHhzMHilw94UosYQjPbf3zzjSSYbjw==", + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/@spectrum-icons/workflow/-/workflow-4.2.10.tgz", + "integrity": "sha512-CaDYaGMe2bYDozzHztrgEy0tljQWn4OBE9hJC2fAM5cMTve4viiWhcmHYYWFv3MZQyavHy1UwCL1jlXg7bK3PA==", "dependencies": { "@adobe/react-spectrum-workflow": "2.3.4", - "@react-spectrum/icon": "^3.7.10", + "@react-spectrum/icon": "^3.7.11", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -9112,9 +9100,9 @@ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" }, "node_modules/@types/node": { - "version": "20.11.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.18.tgz", - "integrity": "sha512-ABT5VWnnYneSBcNWYSCuR05M826RoMyMSGiFivXGx6ZUIsXb9vn4643IEwkg2zbEOSgAiSogtapN2fgc4mAPlw==", + "version": "20.11.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.20.tgz", + "integrity": "sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==", "dependencies": { "undici-types": "~5.26.4" } @@ -9249,9 +9237,9 @@ } }, "node_modules/@types/react": { - "version": "18.2.55", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.55.tgz", - "integrity": "sha512-Y2Tz5P4yz23brwm2d7jNon39qoAtMMmalOQv6+fEFt1mT+FcM3D841wDpoUvFXhaYenuROCy3FZYqdTjM7qVyA==", + "version": "18.2.57", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.57.tgz", + "integrity": "sha512-ZvQsktJgSYrQiMirAN60y4O/LRevIV8hUzSOSNB6gfR3/o3wCBFQx3sPwIYtuDMeiVgsSS3UzCV26tEzgnfvQw==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -10338,6 +10326,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "engines": { + "node": ">=8" + } + }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -10427,9 +10423,12 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/available-typed-arrays": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz", - "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -10825,9 +10824,9 @@ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, "node_modules/bootstrap": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.2.tgz", - "integrity": "sha512-D32nmNWiQHo94BKHLmOrdjlL05q1c8oxbtBphQFb9Z5to6eGRDCm0QgeaZ4zFBHzfg2++rqa2JkqCcxDy0sH0g==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", + "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", "funding": [ { "type": "github", @@ -14030,9 +14029,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001587", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz", - "integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==", + "version": "1.0.30001589", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001589.tgz", + "integrity": "sha512-vNQWS6kI+q6sBlHbh71IIeC+sRwK2N3EDySc/updIGhIee2x5z00J4c1242/5/d6EpEMdOnk/m+6tuk4/tcsqg==", "funding": [ { "type": "opencollective", @@ -15582,6 +15581,18 @@ } } }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/decimal.js": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", @@ -16054,9 +16065,9 @@ } }, "node_modules/dotenv": { - "version": "16.4.4", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.4.tgz", - "integrity": "sha512-XvPXc8XAQThSjAbY6cQ/9PcBXmFoWuw1sQ3b8HqUCR6ziGXjkTi//kB9SWa2UwqlgdAIuRqAa/9hVljzPehbYg==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", "dev": true, "engines": { "node": ">=12" @@ -16112,9 +16123,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.670", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.670.tgz", - "integrity": "sha512-hcijYOWjOtjKrKPtNA6tuLlA/bTLO3heFG8pQA6mLpq7dRydSWicXova5lyxDzp1iVJaYhK7J2OQlGE52KYn7A==" + "version": "1.4.680", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.680.tgz", + "integrity": "sha512-4nToZ5jlPO14W82NkF32wyjhYqQByVaDmLy4J2/tYcAbJfgO2TKJC780Az1V13gzq4l73CJ0yuyalpXvxXXD9A==" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -16371,14 +16382,14 @@ "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" }, "node_modules/es-set-tostringtag": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", - "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2", - "has-tostringtag": "^1.0.0", - "hasown": "^2.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -17959,18 +17970,6 @@ "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==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -18069,6 +18068,11 @@ "node": ">=6" } }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -18366,7 +18370,8 @@ "node_modules/fast-diff": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==" + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true }, "node_modules/fast-equals": { "version": "4.0.3", @@ -18733,9 +18738,9 @@ } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "node_modules/flexlayout-react": { @@ -19257,9 +19262,9 @@ } }, "node_modules/gaxios": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.2.0.tgz", - "integrity": "sha512-H6+bHeoEAU5D6XNc6mPKeN5dLZqEDs9Gpk6I+SZBEzK5So58JVrHPmevNi35fRl1J9Y5TaeLW0kYx3pCJ1U2mQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.3.0.tgz", + "integrity": "sha512-p+ggrQw3fBwH2F5N/PAI4k/G/y1art5OxKpb2J2chwNNHM4hHuAOtivjPuirMF4KNKwTTUal/lPfL2+7h2mEcg==", "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", @@ -19282,9 +19287,9 @@ } }, "node_modules/gaxios/node_modules/https-proxy-agent": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.3.tgz", - "integrity": "sha512-kCnwztfX0KZJSLOBrcL0emLeFako55NWMovvyPP2AjsghNk9RB1yjSI+jVumPHYZsNXegNoqupSW9IY3afSH8w==", + "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" @@ -19794,9 +19799,9 @@ } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -20264,9 +20269,9 @@ } }, "node_modules/http-proxy-agent": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.1.tgz", - "integrity": "sha512-My1KCEPs6A0hb4qCVzYp8iEvA8j8YqcvXLZZH8C9OFuTYpYjHE7N2dtG3mRl1HMD4+VGXpF3XcDVcxGBT7yDZQ==", + "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", @@ -20324,12 +20329,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/http-proxy/node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, "node_modules/http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -20404,14 +20403,6 @@ "npm": ">=5.3.0" } }, - "node_modules/hyperdyperid": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", - "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", - "engines": { - "node": ">=10.18" - } - }, "node_modules/i": { "version": "0.3.7", "resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz", @@ -21368,9 +21359,9 @@ } }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "engines": { "node": ">= 0.4" @@ -21411,6 +21402,17 @@ "node": ">=8" } }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -21458,12 +21460,15 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -21869,9 +21874,9 @@ } }, "node_modules/jsdom/node_modules/https-proxy-agent": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.3.tgz", - "integrity": "sha512-kCnwztfX0KZJSLOBrcL0emLeFako55NWMovvyPP2AjsghNk9RB1yjSI+jVumPHYZsNXegNoqupSW9IY3afSH8w==", + "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", @@ -22356,12 +22361,6 @@ "resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz", "integrity": "sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w==" }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", - "peer": true - }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -22372,12 +22371,6 @@ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "peer": true - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -24011,9 +24004,9 @@ } }, "node_modules/mongoose": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.1.2.tgz", - "integrity": "sha512-5KMq7k6KmFCIB8/YMKMFsWdsdNkBwuARDRHDRpp5GKC78eT0LwHIaMEKo6gDUg3zBuMoy9OdcM/6f4dkW06C/A==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.2.0.tgz", + "integrity": "sha512-la93n6zCYRbPS+c5N9oTDAktvREy5OT9OCljp1Tah0y3+p8UPMTAoabWaLZMdzYruOtF9/9GRf6MasaZjiZP1A==", "dependencies": { "bson": "^6.2.0", "kareem": "2.5.1", @@ -24101,14 +24094,6 @@ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==" }, - "node_modules/multimatch/node_modules/arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "engines": { - "node": ">=8" - } - }, "node_modules/multimatch/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -24321,17 +24306,17 @@ } }, "node_modules/nodemailer": { - "version": "6.9.9", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.9.tgz", - "integrity": "sha512-dexTll8zqQoVJEZPwQAKzxxtFn0qTnjdQTchoU6Re9BUUGBJiOy3YMn/0ShTW6J5M0dfQ1NeDeRTTl4oIWgQMA==", + "version": "6.9.10", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.10.tgz", + "integrity": "sha512-qtoKfGFhvIFW5kLfrkw2R6Nm6Ur4LNUMykyqu6n9BRKJuyQrqEGwdXXUAbwWEKt33dlWUGXb7rzmJP/p4+O+CA==", "engines": { "node": ">=6.0.0" } }, "node_modules/nodemon": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.3.tgz", - "integrity": "sha512-7jH/NXbFPxVaMwmBCC2B9F/V6X1VkEdNgx3iu9jji8WxWcvhMWkmhNWhI5077zknOnZnBzba9hZP6bCPJLSReQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", + "integrity": "sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==", "dependencies": { "chokidar": "^3.5.2", "debug": "^4", @@ -27304,9 +27289,9 @@ } }, "node_modules/openai/node_modules/@types/node": { - "version": "18.19.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.16.tgz", - "integrity": "sha512-mjtrR7Wco9ZwcGBc1zre6fENlj9z42/+0W26lBGtGBTPiR3Zm9iZAaiPhxreG6magwGCILLVYwlQ48GjAaqM6w==", + "version": "18.19.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.18.tgz", + "integrity": "sha512-80CP7B8y4PzZF0GWx15/gVWRrB5y/bIjNI84NK3cmQJu0WZwvmj2WMA5LcofQFVfLqqCSp545+U2LsrVzX36Zg==", "dependencies": { "undici-types": "~5.26.4" } @@ -27483,9 +27468,9 @@ "integrity": "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==" }, "node_modules/parse-bmfont-xml": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.5.tgz", - "integrity": "sha512-wgM+ANC5G5Yu08/IEFMxr9x+PpHg+R8jf8U8q0P91TBDaTdjcf4IwupUiPwEcJJKNqSshC2tOkDQW3Q30s1efQ==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.6.tgz", + "integrity": "sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==", "dependencies": { "xml-parse-from-string": "^1.0.0", "xml2js": "^0.5.0" @@ -27845,7 +27830,8 @@ "node_modules/phin": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", - "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==" + "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info." }, "node_modules/picocolors": { "version": "1.0.0", @@ -28006,6 +27992,14 @@ "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.4.35", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", @@ -28319,9 +28313,9 @@ } }, "node_modules/prosemirror-view": { - "version": "1.32.7", - "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.32.7.tgz", - "integrity": "sha512-pvxiOoD4shW41X5bYDjRQk3DSG4fMqxh36yPMt7VYgU3dWRmqFzWJM/R6zeo1KtC8nyk717ZbQND3CC9VNeptw==", + "version": "1.33.1", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.33.1.tgz", + "integrity": "sha512-62qkYgSJIkwIMMCpuGuPzc52DiK1Iod6TWoIMxP4ja6BTD4yO8kCUL64PZ/WhH/dJ9fW0CDO39FhH1EMyhUFEg==", "dependencies": { "prosemirror-model": "^1.16.0", "prosemirror-state": "^1.0.0", @@ -28582,20 +28576,6 @@ "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" }, - "node_modules/quill-delta": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz", - "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==", - "peer": true, - "dependencies": { - "fast-diff": "^1.3.0", - "lodash.clonedeep": "^4.5.0", - "lodash.isequal": "^4.5.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, "node_modules/random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", @@ -28698,9 +28678,9 @@ } }, "node_modules/rc-util": { - "version": "5.38.1", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.38.1.tgz", - "integrity": "sha512-e4ZMs7q9XqwTuhIK7zBIVFltUtMSjphuPPQXHoHlzRzNdOwUxDejo0Zls5HYaJfRKNURcsS/ceKVULlhjBrxng==", + "version": "5.38.2", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.38.2.tgz", + "integrity": "sha512-yRGRPKyi84H7NkRSP6FzEIYBdUt4ufdsmXUZ7qM2H5qoByPax70NnGPkfo36N+UKUnUBj2f2Q2eUbwYMuAsIOQ==", "dependencies": { "@babel/runtime": "^7.18.3", "react-is": "^18.2.0" @@ -28892,9 +28872,9 @@ } }, "node_modules/react-intersection-observer": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.8.0.tgz", - "integrity": "sha512-wXHvMQUsTagh3X0Z6jDtGkIXc3VVCd2tjDRYR9kII3GKrZr0XF0xtpfdamo2n8BSF+zzfeeBVOTjxZWpBp9X0g==", + "version": "9.8.1", + "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.8.1.tgz", + "integrity": "sha512-QzOFdROX8D8MH3wE3OVKH0f3mLjKTtEN1VX/rkNuECCff+aKky0pIjulDhr3Ewqj5el/L+MhBkM3ef0Tbt+qUQ==", "peerDependencies": { "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" @@ -29236,13 +29216,13 @@ "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==" }, "node_modules/recharts": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.12.0.tgz", - "integrity": "sha512-rVNcdNQ5b7+40Ue7mcEKZJyEv+3SUk2bDEVvOyXPDXXVE7TU3lrvnJUgAvO36hSzhRP2DnAamKXvHLFIFOU0Ww==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.12.1.tgz", + "integrity": "sha512-35vUCEBPf+pM+iVgSgVTn86faKya5pc4JO6cYJL63qOK2zDEyzDn20Tdj+CDI/3z+VcpKyQ8ZBQ9OiQ+vuAbjg==", "dependencies": { "clsx": "^2.0.0", "eventemitter3": "^4.0.1", - "lodash": "^4.17.19", + "lodash": "^4.17.21", "react-is": "^16.10.2", "react-smooth": "^4.0.0", "recharts-scale": "^0.4.4", @@ -29265,11 +29245,6 @@ "decimal.js-light": "^2.4.1" } }, - "node_modules/recharts/node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, "node_modules/recharts/node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -30015,9 +29990,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sass": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.70.0.tgz", - "integrity": "sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==", + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.71.1.tgz", + "integrity": "sha512-wovtnV2PxzteLlfNzbgm1tFXPLoZILYAMJtvoXXkD7/+1uP41eKkIt1ypWq5/q2uT94qHjXehEYfmjKOvjL9sg==", "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -30368,13 +30343,14 @@ } }, "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dependencies": { - "define-data-property": "^1.0.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -30686,10 +30662,11 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", - "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "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==", "dependencies": { + "debug": "~4.3.4", "ws": "~8.11.0" } }, @@ -31012,9 +30989,9 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/streamx": { - "version": "2.15.8", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.8.tgz", - "integrity": "sha512-6pwMeMY/SuISiRsuS8TeIrAzyFbG5gGPHFQsYjUr/pbBadaL1PCWmzKw+CHZSwainfvcF6Si6cVLq4XTEwswFQ==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.16.1.tgz", + "integrity": "sha512-m9QYj6WygWyWa3H1YY69amr4nVgy61xfjys7xO7kviL5rfIEc2naf+ewFiOA+aEJD7y0JO3h2GoiUv4TDwEGzQ==", "dependencies": { "fast-fifo": "^1.1.0", "queue-tick": "^1.0.1" @@ -31550,9 +31527,9 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/terser": { - "version": "5.27.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.1.tgz", - "integrity": "sha512-29wAr6UU/oQpnTw5HoadwjUZnFQXGdOfj0LjZ4sVxzqwHh/QVkvr7m8y9WoR4iN3FRitVduTc6KdjcW38Npsug==", + "version": "5.27.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.2.tgz", + "integrity": "sha512-sHXmLSkImesJ4p5apTeT63DsV4Obe1s37qT8qvwHRmVxKTBH7Rv9Wr26VcAMmLbmk9UliiwK8z+657NyJHHy/w==", "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -31632,25 +31609,13 @@ "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" }, "node_modules/textarea-caret": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/textarea-caret/-/textarea-caret-3.1.0.tgz", "integrity": "sha512-cXAvzO9pP5CGa6NKx0WYHl+8CHKZs8byMkt3PCJBCmq2a34YA9pO1NrQET5pzeqnBjBdToF5No4rrmkDUgQC2Q==" }, - "node_modules/thingies": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.16.0.tgz", - "integrity": "sha512-J23AVs11hSQxuJxvfQyMIaS9z1QpDxOCvMkL3ZxZl8/jmkgmnNGWrlyNxVz6Jbh0U6DuGmHqq6f7zUROfg/ncg==", - "engines": { - "node": ">=10.18" - }, - "peerDependencies": { - "tslib": "^2" - } - }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -32479,6 +32444,18 @@ "node": ">= 0.8.0" } }, + "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==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -32492,12 +32469,12 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.1.tgz", - "integrity": "sha512-RSqu1UEuSlrBhHTWC8O9FnPjOduNs4M7rJ4pRKoEjtx1zUNOPN2sSXHLDX+Y2WPbHIxbvg4JFo2DNAEfPIKWoQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", "is-typed-array": "^1.1.13" }, @@ -32506,15 +32483,16 @@ } }, "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -32524,16 +32502,17 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -32543,14 +32522,20 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", + "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -32711,17 +32696,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unified/node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/uninstall": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/uninstall/-/uninstall-0.0.0.tgz", @@ -33233,9 +33207,9 @@ } }, "node_modules/web-streams-polyfill": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.2.tgz", - "integrity": "sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", "engines": { "node": ">= 8" } @@ -33249,9 +33223,9 @@ } }, "node_modules/webpack": { - "version": "5.90.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.1.tgz", - "integrity": "sha512-SstPdlAC5IvgFnhiRok8hqJo/+ArAbNv7rhU4fnWGHNVfN59HSQFaxZDSAL3IFG2YmqxuRs+IU33milSxbPlog==", + "version": "5.90.3", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.3.tgz", + "integrity": "sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==", "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", @@ -33392,49 +33366,12 @@ } } }, - "node_modules/webpack-dev-middleware/node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" - }, - "node_modules/webpack-dev-middleware/node_modules/json-joy": { - "version": "11.28.0", - "resolved": "https://registry.npmjs.org/json-joy/-/json-joy-11.28.0.tgz", - "integrity": "sha512-WTq2tYD2r+0rUFId4gtUjwejV20pArh4q2WRJKxJdwLlPFHyW94HwwB2vUr5lUJTVkehhhWEVLwOUI0MSacNIw==", - "dependencies": { - "arg": "^5.0.2", - "hyperdyperid": "^1.2.0", - "thingies": "^1.14.1" - }, - "bin": { - "jj": "bin/jj.js", - "json-pack": "bin/json-pack.js", - "json-pack-test": "bin/json-pack-test.js", - "json-patch": "bin/json-patch.js", - "json-patch-test": "bin/json-patch-test.js", - "json-pointer": "bin/json-pointer.js", - "json-pointer-test": "bin/json-pointer-test.js", - "json-unpack": "bin/json-unpack.js" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "quill-delta": "^5", - "rxjs": "7", - "tslib": "2" - } - }, "node_modules/webpack-dev-middleware/node_modules/memfs": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.7.0.tgz", - "integrity": "sha512-FGbf9Yz2gzXCUmpymkKnzAQOitriZQlIMtmnzb2LOcT0FTUdzL6AAwNGQrSOACx/UiW7XQsG65vrIA9+L01Edw==", + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.7.7.tgz", + "integrity": "sha512-x9qc6k88J/VVwnfTkJV8pRRswJ2156Rc4w5rciRqKceFDZ0y1MqsNL9pkg5sE0GOcDzZYbonreALhaHzg1siFw==", "dependencies": { - "json-joy": "^11.0.0", - "thingies": "^1.11.1" + "tslib": "^2.0.0" }, "engines": { "node": ">= 4.0.0" @@ -33442,18 +33379,6 @@ "funding": { "type": "github", "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/webpack-dev-middleware/node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "peer": true, - "dependencies": { - "tslib": "^2.1.0" } }, "node_modules/webpack-dev-server": { @@ -34218,18 +34143,6 @@ "node": ">=10" } }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/yargs-unparser/node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index a69030019..3670382c5 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -37,7 +37,7 @@ import { GestureOverlay } from '../../GestureOverlay'; import { CtrlKey } from '../../GlobalKeyHandler'; import { ActiveInkWidth, InkingStroke, SetActiveInkColor, SetActiveInkWidth } from '../../InkingStroke'; import { LightboxView } from '../../LightboxView'; -import { CollectionFreeFormDocumentView, CollectionFreeFormDocumentViewWrapper } from '../../nodes/CollectionFreeFormDocumentView'; +import { CollectionFreeFormDocumentView } from '../../nodes/CollectionFreeFormDocumentView'; import { SchemaCSVPopUp } from '../../nodes/DataVizBox/SchemaCSVPopUp'; import { DocumentView, OpenWhere } from '../../nodes/DocumentView'; import { FieldViewProps, FocusViewOptions } from '../../nodes/FieldView'; @@ -1181,7 +1181,7 @@ export class CollectionFreeFormView extends CollectionSubView boolean; - CollectionFreeFormView: CollectionFreeFormView; -} -@observer -export class CollectionFreeFormDocumentViewWrapper extends ObservableReactComponent { - constructor(props: CollectionFreeFormDocumentViewWrapperProps) { - super(props); - makeObservable(this); - } - @observable X = this.props.x; - @observable Y = this.props.y; - @observable Z = this.props.z; - @observable ZIndex = this.props.zIndex; - @observable Rotation = this.props.rotation; - @observable Opacity = this.props.opacity; - @observable BackgroundColor = this.props.backgroundColor; - @observable Color = this.props.color; - @observable Highlight = this.props.highlight; - @observable Width = this.props.width; - @observable Height = this.props.height; - @observable AutoDim = this.props.autoDim; - @observable Transition = this.props.transition; - CollectionFreeFormView = this.props.CollectionFreeFormView; // needed for type checking - RenderCutoffProvider = this.props.RenderCutoffProvider; // needed for type checking - - get Document() { - return this._props.Document; - } - @computed get WrapperKeys() { - return Object.keys(this).filter(key => key.startsWith('w_')).map(key => key.replace('w_', '')) - .map(key => ({upper:key, lower:key[0].toLowerCase() + key.substring(1)})); // prettier-ignore - } - - // wrapper functions around prop fields that have been converted to observables to keep 'props' from ever changing. - // this way, downstream code only invalidates when it uses a specific prop, not when any prop changes - w_X = () => this.X; // prettier-ignore - w_Y = () => this.Y; // prettier-ignore - w_Z = () => this.Z; // prettier-ignore - w_ZIndex = () => this.ZIndex ?? NumCast(this.Document.zIndex); // prettier-ignore - w_Rotation = () => this.Rotation ?? NumCast(this.Document._rotation); // prettier-ignore - w_Opacity = () => this.Opacity; // prettier-ignore - w_BackgroundColor = () => this.BackgroundColor ?? Cast(this.Document._backgroundColor, 'string', null); // prettier-ignore - w_Color = () => this.Color ?? Cast(this.Document._color, 'string', null); // prettier-ignore - w_Highlight = () => this.Highlight; // prettier-ignore - w_Width = () => this.Width; // prettier-ignore - w_Height = () => this.Height; // prettier-ignore - w_AutoDim = () => this.AutoDim; // prettier-ignore - w_Transition = () => this.Transition; // prettier-ignore - - PanelWidth = () => this._props.autoDim ? this._props.PanelWidth?.() : this.Width; // prettier-ignore - PanelHeight = () => this._props.autoDim ? this._props.PanelHeight?.() : this.Height; // prettier-ignore - - componentDidUpdate(prevProps: Readonly>) { - super.componentDidUpdate(prevProps); - this.WrapperKeys.forEach(action(keys => ((this as any)[keys.upper] = (this.props as any)[keys.lower]))); - } - render() { - const layoutProps = this.WrapperKeys.reduce((val, keys) => [(val['w_' + keys.upper] = (this as any)['w_' + keys.upper]), val][1], {} as { [key: string]: Function }); - return ( - keys.lower) ).omit} // prettier-ignore - {...layoutProps} - PanelWidth={this.PanelWidth} - PanelHeight={this.PanelHeight} - /> - ); - } } export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { - w_X: () => number; - w_Y: () => number; - w_Z: () => number; - w_ZIndex?: () => number; - w_Rotation?: () => number; - w_Color: () => string; - w_BackgroundColor: () => string; - w_Opacity: () => number | undefined; - w_Highlight: () => boolean | undefined; - w_Transition: () => string | undefined; - w_Width: () => number; - w_Height: () => number; - PanelWidth: () => number; - PanelHeight: () => number; RenderCutoffProvider: (doc: Doc) => boolean; CollectionFreeFormView: CollectionFreeFormView; } - @observer -export class CollectionFreeFormDocumentView extends DocComponent() { - constructor(props: CollectionFreeFormDocumentViewProps) { - super(props); - makeObservable(this); - } +export class CollectionFreeFormDocumentView extends DocComponent() { get displayName() { // this makes mobx trace() statements more descriptive return 'CollectionFreeFormDocumentView(' + this.Document.title + ')'; } // prettier-ignore + public static CollectionFreeFormDocViewClassName = 'collectionFreeFormDocumentView-container'; public static animFields: { key: string; val?: number }[] = [ { key: 'x' }, { key: 'y' }, @@ -145,16 +62,53 @@ export class CollectionFreeFormDocumentView extends DocComponent (Doc.LayoutFieldKey(doc) ? [Doc.LayoutFieldKey(doc)] : []); // fields that are configured to be animatable using animation frames - get CollectionFreeFormView() { - return this._props.CollectionFreeFormView; + constructor(props: CollectionFreeFormDocumentViewProps & freeFormProps) { + super(props); + makeObservable(this); + } + + get WrapperKeys() { + // each of these keys is set by the CollectionView and passed via props. however, if any one of these props changes + // (or any other prop), then it's as if they all change. + // Anything that accesses these props will then invalidate unncessarily. + // To avoid this, we copy these prop values into local observables. Now when 'props' changes, nothing invalidates. + // Instead, we copy each values into its observable which ohnly triggers invalidations if the new value is different + // than the old value, and then only things that access that observable will invalidate. + return freeFormPropsKeys + .map(key => ({upper:key[0].toUpperCase() + key.substring(1), lower:key})); // prettier-ignore + } + @observable X = this.props.x; + @observable Y = this.props.y; + @observable Z = this.props.z; + @observable ZIndex = this.props.zIndex; + @observable Rotation = this.props.rotation; + @observable Opacity = this.props.opacity; + @observable BackgroundColor = this.props.backgroundColor; + @observable Color = this.props.color; + @observable Highlight = this.props.highlight; + @observable Width = this.props.width; + @observable Height = this.props.height; + @observable AutoDim = this.props.autoDim; + @observable Transition = this.props.transition; + + componentDidUpdate(prevProps: Readonly>) { + super.componentDidUpdate(prevProps); + this.WrapperKeys.forEach(action(keys => ((this as any)[keys.upper] = (this.props as any)[keys.lower]))); } + CollectionFreeFormView = this.props.CollectionFreeFormView; // needed for type checking + // this way, downstream code only invalidates when it uses a specific prop, not when any prop changes + DataTransition = () => this._props.transition; // prettier-ignore + RenderCutoffProvider = this.props.RenderCutoffProvider; // needed for type checking + PanelWidth = () => this._props.autoDim ? this._props.PanelWidth?.() : this.Width; // prettier-ignore + PanelHeight = () => this._props.autoDim ? this._props.PanelHeight?.() : this.Height; // prettier-ignore + styleProvider = (doc: Doc | undefined, props: Opt, property: string) => { if (doc === this.layoutDoc) { switch (property) { - case StyleProp.Opacity: return this._props.w_Opacity(); // only change the opacity for this specific document, not its children - case StyleProp.BackgroundColor: return this._props.w_BackgroundColor(); - case StyleProp.Color: return this._props.w_Color(); + case StyleProp.Opacity: return this.Opacity; // only change the opacity for this specific document, not its children + case StyleProp.BackgroundColor: return this.BackgroundColor; + case StyleProp.Color: return this.Color; } // prettier-ignore } return this._props.styleProvider?.(doc, props, property); @@ -253,14 +207,14 @@ export class CollectionFreeFormDocumentView extends DocComponent { const [locX, locY] = this._props.ScreenToLocalTransform().transformDirection(x, y); - this.Document.x = this._props.w_X() + locX; - this.Document.y = this._props.w_Y() + locY; + this.Document.x = this.X + locX; + this.Document.y = this.Y + locY; }; screenToLocalTransform = () => this._props .ScreenToLocalTransform() - .translate(-this._props.w_X(), -this._props.w_Y()) - .rotateDeg(-(this._props.w_Rotation?.() || 0)); + .translate(-this.X, -this.Y) + .rotateDeg(-(this.Rotation || 0)); returnThis = () => this; /// this indicates whether the doc view is activated because of its relationshop to a group @@ -273,27 +227,26 @@ export class CollectionFreeFormDocumentView extends DocComponent key.startsWith('w_'))).omit; // prettier-ignore + return (
- {this._props.RenderCutoffProvider(this.Document) ? ( -
+ {this.RenderCutoffProvider(this.Document) ? ( +
) : ( val.lower)).omit} // prettier-ignore + DataTransition={this.DataTransition} CollectionFreeFormDocumentView={this.returnThis} styleProvider={this.styleProvider} ScreenToLocalTransform={this.screenToLocalTransform} -- cgit v1.2.3-70-g09d2 From 27306bd0ae259241182d90cc62225609dfc8da74 Mon Sep 17 00:00:00 2001 From: geireann Date: Sun, 25 Feb 2024 12:51:26 -0500 Subject: fixed conversion of doc to schema cells to allow number 0 to be converted to a string. --- .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 3670382c5..50a9feff8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1962,8 +1962,8 @@ ScriptingGlobals.add(function datavizFromSchema(doc: Doc) { for (let i = 0; i < children.length; i++) { let eachRow = []; for (let j = 0; j < keys.length; j++) { - var cell = children[i][keys[j]]; - if (cell && (cell as string)) cell = cell.toString().replace(/\,/g, ''); + var cell = children[i][keys[j]]?.toString(); + if (cell) cell = cell.toString().replace(/\,/g, ''); eachRow.push(cell); } csvRows.push(eachRow); -- cgit v1.2.3-70-g09d2 From d99f64efe9e69f2159f1ad8f851b24533a996ba5 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 26 Feb 2024 12:57:48 -0500 Subject: fixed some string types to be enumerations for dropAction. fixed bug in golden layout dragging where a stack's tabs could disappear. --- src/client/documents/Documents.ts | 40 ++++++++++------ src/client/goldenLayout.js | 2 +- src/client/util/CurrentUserUtils.ts | 44 +++++++++--------- src/client/util/DragManager.ts | 54 +++++++++++++++------- src/client/views/MainView.tsx | 6 +-- src/client/views/collections/CollectionMenu.tsx | 4 +- .../views/collections/CollectionPileView.tsx | 3 +- .../views/collections/CollectionTreeView.tsx | 16 +++++-- src/client/views/collections/TreeView.tsx | 4 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- .../collections/collectionFreeForm/MarqueeView.tsx | 9 +++- .../collectionSchema/CollectionSchemaView.tsx | 4 +- .../collectionSchema/SchemaTableCell.tsx | 7 +-- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/trails/PresBox.tsx | 5 +- src/client/views/topbar/TopBar.tsx | 3 +- src/fields/documentSchemas.ts | 6 +-- 17 files changed, 129 insertions(+), 82 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 2d2f5fe4a..8a13395c3 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -68,10 +68,20 @@ class EmptyBox { return ''; } } + +export enum FInfoFieldType { + string, + boolean, + number, + Doc, + enumeration, + date, + list, +} export class FInfo { description: string = ''; readOnly: boolean = false; - fieldType?: string = ''; + fieldType?: FInfoFieldType; values?: Field[]; filterable?: boolean = true; @@ -84,7 +94,7 @@ export class FInfo { searchable = () => true; } class BoolInfo extends FInfo { - fieldType? = 'boolean'; + fieldType? = FInfoFieldType.boolean; values?: boolean[] = [true, false]; constructor(d: string, filterable?: boolean) { super(d); @@ -93,7 +103,7 @@ class BoolInfo extends FInfo { override searchable = () => false; } class NumInfo extends FInfo { - fieldType? = 'number'; + fieldType? = FInfoFieldType.number; values?: number[] = []; constructor(d: string, filterable?: boolean, readOnly?: boolean, values?: number[]) { super(d, readOnly); @@ -103,7 +113,7 @@ class NumInfo extends FInfo { override searchable = () => false; } class StrInfo extends FInfo { - fieldType? = 'string'; + fieldType? = FInfoFieldType.string; values?: string[] = []; constructor(d: string, filterable?: boolean, readOnly?: boolean, values?: string[]) { super(d, readOnly); @@ -112,7 +122,7 @@ class StrInfo extends FInfo { } } class DocInfo extends FInfo { - fieldType? = 'Doc'; + fieldType? = FInfoFieldType.Doc; values?: Doc[] = []; constructor(d: string, filterable?: boolean, values?: Doc[]) { super(d, true); @@ -122,45 +132,45 @@ class DocInfo extends FInfo { override searchable = () => false; } class DimInfo extends FInfo { - fieldType? = 'enumeration'; + fieldType? = FInfoFieldType.enumeration; values? = [DimUnit.Pixel, DimUnit.Ratio]; readOnly = false; filterable = false; override searchable = () => false; } class PEInfo extends FInfo { - fieldType? = 'enumeration'; + fieldType? = FInfoFieldType.enumeration; values? = ['all', 'none']; readOnly = false; filterable = false; override searchable = () => false; } class DAInfo extends FInfo { - fieldType? = 'enumeration'; - values? = ['embed', 'copy', 'move', 'same', 'proto', 'none']; + fieldType? = FInfoFieldType.enumeration; + values? = ['embed', 'copy', 'move', 'same', 'add', 'inSame', 'proto']; readOnly = false; filterable = false; override searchable = () => false; } class CTypeInfo extends FInfo { - fieldType? = 'enumeration'; + fieldType? = FInfoFieldType.enumeration; values? = Array.from(Object.keys(CollectionViewType)); readOnly = false; filterable = false; override searchable = () => false; } class DTypeInfo extends FInfo { - fieldType? = 'enumeration'; + fieldType? = FInfoFieldType.enumeration; values? = Array.from(Object.keys(DocumentType)); override searchable = () => false; } class DateInfo extends FInfo { - fieldType? = 'date'; + fieldType? = FInfoFieldType.date; values?: DateField[] = []; filterable = true; } class ListInfo extends FInfo { - fieldType? = 'list'; + fieldType? = FInfoFieldType.list; values?: List[] = []; } type BOOLt = BoolInfo | boolean; @@ -728,7 +738,7 @@ export namespace Docs { { data: '', layout: { view: ComparisonBox, dataField: defaultDataKey }, - options: { backgroundColor: 'gray', dropAction: 'move', waitForDoubleClickToClick: 'always', layout_reflowHorizontal: true, layout_reflowVertical: true, layout_nativeDimEditable: true, systemIcon: 'BsLayoutSplit' }, + options: { backgroundColor: 'gray', dropAction: dropActionType.move, waitForDoubleClickToClick: 'always', layout_reflowHorizontal: true, layout_reflowVertical: true, layout_nativeDimEditable: true, systemIcon: 'BsLayoutSplit' }, }, ], [ @@ -1182,7 +1192,7 @@ export namespace Docs { return InstanceFromProto( Prototypes.get(DocumentType.COL), new List(documents), - { backgroundColor: 'transparent', dropAction: 'move', _forceActive: true, _freeform_noZoom: true, _freeform_noAutoPan: true, ...options, _type_collection: CollectionViewType.Pile }, + { backgroundColor: 'transparent', dropAction: dropActionType.move, _forceActive: true, _freeform_noZoom: true, _freeform_noAutoPan: true, ...options, _type_collection: CollectionViewType.Pile }, id ); } diff --git a/src/client/goldenLayout.js b/src/client/goldenLayout.js index 2b94d35ee..cb1dfd76a 100644 --- a/src/client/goldenLayout.js +++ b/src/client/goldenLayout.js @@ -4727,7 +4727,7 @@ */ } else { type = isVertical ? 'column' : 'row'; - if (this.parent.contentItems.length === 1) { + if (this.parent.contentItems.length === 1 && this.contentItems.length === 1) { let grandparent = this.parent.parent; let correctRowOrCol = this.layoutManager.createContentItem({ type: type }, this); grandparent.replaceChild(this.parent, correctRowOrCol); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 714e33d25..d396ba815 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -14,7 +14,7 @@ import { SetCachedGroups, SharingPermissions } from "../../fields/util"; import { GestureUtils } from "../../pen-gestures/GestureUtils"; import { DocServer } from "../DocServer"; import { CollectionViewType, DocumentType } from "../documents/DocumentTypes"; -import { DocUtils, Docs, DocumentOptions, FInfo } from "../documents/Documents"; +import { DocUtils, Docs, DocumentOptions, FInfo, FInfoFieldType } from "../documents/Documents"; import { DashboardView } from "../views/DashboardView"; import { OverlayView } from "../views/OverlayView"; import { CollectionTreeView, TreeViewType } from "../views/collections/CollectionTreeView"; @@ -257,11 +257,11 @@ export class CurrentUserUtils { {key: "DataViz", creator: opts => Docs.Create.DataVizDocument("/users/rz/Downloads/addresses.csv", opts), opts: { _width: 300, _height: 300 }}, {key: "Header", creator: headerTemplate, opts: { _width: 300, _height: 70, _headerPointerEvents: "all", _headerHeight: 12, _headerFontSize: 9, _layout_autoHeight: true, treeView_HideUnrendered: true}}, {key: "ViewSlide", creator: slideView, opts: { _width: 400, _height: 300, _xMargin: 3, _yMargin: 3,}}, - {key: "Trail", creator: Docs.Create.PresDocument, opts: { _width: 400, _height: 30, _type_collection: CollectionViewType.Stacking, dropAction: "embed" as dropActionType, treeView_HideTitle: true, _layout_fitWidth:true, layout_boxShadow: "0 0" }}, + {key: "Trail", creator: Docs.Create.PresDocument, opts: { _width: 400, _height: 30, _type_collection: CollectionViewType.Stacking, dropAction: dropActionType.embed, treeView_HideTitle: true, _layout_fitWidth:true, layout_boxShadow: "0 0" }}, {key: "Tab", creator: opts => Docs.Create.FreeformDocument([], opts), opts: { _width: 500, _height: 800, _layout_fitWidth: true, _freeform_backgroundGrid: true, }}, {key: "Slide", creator: opts => Docs.Create.TreeDocument([], opts), opts: { _width: 300, _height: 200, _type_collection: CollectionViewType.Tree, treeView_HasOverlay: true, _text_fontSize: "20px", _layout_autoHeight: true, - dropAction:'move', treeView_Type: TreeViewType.outline, + dropAction:dropActionType.move, treeView_Type: TreeViewType.outline, backgroundColor: "white", _xMargin: 0, _yMargin: 0, _createDocOnCR: true }, funcs: {title: 'this.text?.Text'}}, ]; @@ -311,7 +311,7 @@ export class CurrentUserUtils { const reqdOpts:DocumentOptions = { title: "Document Creators", _layout_showTitle: "title", _xMargin: 0, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, _chromeHidden: true, isSystem: true, _layout_autoHeight: true, _width: 500, _height: 300, _layout_fitWidth: true, _columnWidth: 40, ignoreClick: true, _lockedPosition: true, _forceActive: true, - childDragAction: 'embed' + childDragAction: dropActionType.embed }; const reqdScripts = { dropConverter: "convertToButtons(dragData)" }; return DocUtils.AssignScripts(DocUtils.AssignOpts(dragCreatorDoc, reqdOpts, creatorBtns) ?? Docs.Create.MasonryDocument(creatorBtns, reqdOpts), reqdScripts); @@ -353,7 +353,7 @@ export class CurrentUserUtils { }); const reqdStackOpts:DocumentOptions ={ - title: "menuItemPanel", childDragAction: "same", layout_boxShadow: "rgba(0,0,0,0)", dontRegisterView: true, ignoreClick: true, + title: "menuItemPanel", childDragAction: dropActionType.same, layout_boxShadow: "rgba(0,0,0,0)", dontRegisterView: true, ignoreClick: true, _chromeHidden: true, _gridGap: 0, _yMargin: 0, _xMargin: 0, _layout_autoHeight: false, _width: 60, _columnWidth: 60, _lockedPosition: true, isSystem: true, }; return DocUtils.AssignDocField(doc, field, (opts, items) => Docs.Create.StackingDocument(items??[], opts), reqdStackOpts, menuBtns, { dropConverter: "convertToButtons(dragData)" }); @@ -436,7 +436,7 @@ export class CurrentUserUtils { /// Search option on the left side button panel static setupSearcher(doc: Doc, field:string) { return DocUtils.AssignDocField(doc, field, (opts, items) => Docs.Create.SearchDocument(opts), { - dontRegisterView: true, backgroundColor: "dimgray", ignoreClick: true, title: "Search Panel", isSystem: true, childDragAction: "embed", + dontRegisterView: true, backgroundColor: "dimgray", ignoreClick: true, title: "Search Panel", isSystem: true, childDragAction: dropActionType.embed, _lockedPosition: true, _type_collection: CollectionViewType.Schema }); } @@ -476,8 +476,8 @@ export class CurrentUserUtils { const childContextMenuIcons = ["tv", "camera", "users", "times", "trash"]; // entries must be kept in synch with childContextMenuScripts, childContextMenuLabels, and childContextMenuFilters const reqdOpts:DocumentOptions = { title: "My Dashboards", childHideLinkButton: true, treeView_FreezeChildren: "remove|add", treeView_HideTitle: true, layout_boxShadow: "0 0", childDontRegisterViews: true, - dropAction: "inSame", treeView_Type: TreeViewType.fileSystem, isFolder: true, isSystem: true, treeView_TruncateTitleWidth: 350, ignoreClick: true, - layout_headerButton: newDashboardButton, childDragAction: "inSame", + dropAction: dropActionType.inPlace, treeView_Type: TreeViewType.fileSystem, isFolder: true, isSystem: true, treeView_TruncateTitleWidth: 350, ignoreClick: true, + layout_headerButton: newDashboardButton, childDragAction: dropActionType.inPlace, _layout_showTitle: "title", _height: 400, _gridGap: 5, _forceActive: true, _lockedPosition: true, contextMenuLabels:new List(contextMenuLabels), contextMenuIcons:new List(contextMenuIcons), @@ -510,9 +510,9 @@ export class CurrentUserUtils { const newFolderButton = DocUtils.AssignScripts(DocUtils.AssignOpts(DocCast(myFilesystem?.layout_headerButton), newFolderOpts) ?? Docs.Create.FontIconDocument(newFolderOpts), newFolderScript); const reqdOpts:DocumentOptions = { _layout_showTitle: "title", _height: 100, _forceActive: true, - title: "My Documents", layout_headerButton: newFolderButton, treeView_HideTitle: true, dropAction: 'add', isSystem: true, + title: "My Documents", layout_headerButton: newFolderButton, treeView_HideTitle: true, dropAction: dropActionType.add, isSystem: true, isFolder: true, treeView_Type: TreeViewType.fileSystem, childHideLinkButton: true, layout_boxShadow: "0 0", childDontRegisterViews: true, - treeView_TruncateTitleWidth: 350, ignoreClick: true, childDragAction: "embed", + treeView_TruncateTitleWidth: 350, ignoreClick: true, childDragAction: dropActionType.embed, layout_explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard." }; const fileFolders = new Set(DocListCast(DocCast(doc[field])?.data)); @@ -522,8 +522,8 @@ export class CurrentUserUtils { /// initializes the panel displaying docs that have been recently closed static setupRecentlyClosed(doc: Doc, field:string) { const reqdOpts:DocumentOptions = { _layout_showTitle: "title", _lockedPosition: true, _gridGap: 5, _forceActive: true, isFolder: true, - title: "My Recently Closed", childHideLinkButton: true, treeView_HideTitle: true, childDragAction: "move", isSystem: true, - treeView_TruncateTitleWidth: 350, ignoreClick: true, layout_boxShadow: "0 0", childDontRegisterViews: true, dropAction: "same", + title: "My Recently Closed", childHideLinkButton: true, treeView_HideTitle: true, childDragAction: dropActionType.move, isSystem: true, + treeView_TruncateTitleWidth: 350, ignoreClick: true, layout_boxShadow: "0 0", childDontRegisterViews: true, dropAction: dropActionType.same, contextMenuLabels: new List(["Empty recently closed"]), contextMenuIcons:new List(["trash"]), layout_explainer: "Recently closed documents appear in this menu. They will only be deleted if you explicity empty this list." @@ -546,7 +546,7 @@ export class CurrentUserUtils { static setupUserDocView(doc: Doc, field:string) { const reqdOpts:DocumentOptions = { _lockedPosition: true, _gridGap: 5, _forceActive: true, title: Doc.CurrentUserEmail +"-view", - layout_boxShadow: "0 0", childDontRegisterViews: true, dropAction: "same", ignoreClick: true, isSystem: true, + layout_boxShadow: "0 0", childDontRegisterViews: true, dropAction: dropActionType.same, ignoreClick: true, isSystem: true, treeView_HideTitle: true, treeView_TruncateTitleWidth: 350 }; if (!doc[field]) DocUtils.AssignOpts(doc, {treeView_Open: true, treeView_ExpandedView: "fields" }); @@ -587,7 +587,7 @@ export class CurrentUserUtils { ]; const btns = btnDescs.map(desc => dockBtn({_width: 30, _height: 30, defaultDoubleClick: 'ignore', undoIgnoreFields: new List(['opacity']), _dragOnlyWithinContainer: true, ...desc.opts}, desc.scripts)); const dockBtnsReqdOpts:DocumentOptions = { - title: "docked buttons", _height: 40, flexGap: 0, layout_boxShadow: "standard", childDragAction: 'move', + title: "docked buttons", _height: 40, flexGap: 0, layout_boxShadow: "standard", childDragAction: dropActionType.move, childDontRegisterViews: true, linearView_IsOpen: true, linearView_Expandable: true, ignoreClick: true }; reaction(() => UndoManager.redoStack.slice(), () => Doc.GetProto(btns.find(btn => btn.title === "Redo")!).opacity = UndoManager.CanRedo() ? 1 : 0.4, { fireImmediately: true }); @@ -743,7 +743,7 @@ export class CurrentUserUtils { /// Initializes all the default buttons for the top bar context menu static setupContextMenuButtons(doc: Doc, field="myContextMenuBtns") { - const reqdCtxtOpts:DocumentOptions = { title: "context menu buttons", undoIgnoreFields:new List(['width', "linearView_IsOpen"]), flexGap: 0, childDragAction: 'embed', childDontRegisterViews: true, linearView_IsOpen: true, ignoreClick: true, linearView_Expandable: false, _height: 35 }; + const reqdCtxtOpts:DocumentOptions = { title: "context menu buttons", undoIgnoreFields:new List(['width', "linearView_IsOpen"]), flexGap: 0, childDragAction: dropActionType.embed, childDontRegisterViews: true, linearView_IsOpen: true, ignoreClick: true, linearView_Expandable: false, _height: 35 }; const ctxtMenuBtnsDoc = DocUtils.AssignDocField(doc, field, (opts, items) => this.linearButtonList(opts, items??[]), reqdCtxtOpts, undefined); const ctxtMenuBtns = CurrentUserUtils.contextMenuTools().map(params => this.setupContextMenuBtn(params, ctxtMenuBtnsDoc) ); return DocUtils.AssignOpts(ctxtMenuBtnsDoc, reqdCtxtOpts, ctxtMenuBtns); @@ -769,7 +769,7 @@ export class CurrentUserUtils { ]; const btns = btnDescs.map(desc => dockBtn({_width: desc.opts.width??30, _height: 30, defaultDoubleClick: 'ignore', undoIgnoreFields: new List(['opacity']), _dragOnlyWithinContainer: true, ...desc.opts}, desc.scripts, desc.funcs)); const dockBtnsReqdOpts:DocumentOptions = { - title: "docked buttons", _height: 40, flexGap: 0, layout_boxShadow: "standard", childDragAction: 'move', + title: "docked buttons", _height: 40, flexGap: 0, layout_boxShadow: "standard", childDragAction: dropActionType.move, childDontRegisterViews: true, linearView_IsOpen: true, linearView_Expandable: false, ignoreClick: true }; return DocUtils.AssignDocField(doc, field, (opts, items) => this.linearButtonList(opts, items??[]), dockBtnsReqdOpts, btns); @@ -809,7 +809,7 @@ export class CurrentUserUtils { // childContextMenuLabels: new List(["Add to Dashboards",]), // childContextMenuIcons: new List(["user-plus",]), "acl-Guest": SharingPermissions.Augment, "_acl-Guest": SharingPermissions.Augment, - childDragAction: "embed", isSystem: true, childContentPointerEvents: "none", childLimitHeight: 0, _yMargin: 0, _gridGap: 15, childDontRegisterViews:true, + childDragAction: dropActionType.embed, isSystem: true, childContentPointerEvents: "none", childLimitHeight: 0, _yMargin: 0, _gridGap: 15, childDontRegisterViews:true, // NOTE: treeView_HideTitle & _layout_showTitle is for a TreeView's editable title, _layout_showTitle is for DocumentViews title bar _layout_showTitle: "title", treeView_HideTitle: true, ignoreClick: true, _lockedPosition: true, layout_boxShadow: "0 0", _chromeHidden: true, dontRegisterView: true, layout_explainer: "This is where documents or dashboards that other users have shared with you will appear. To share a document or dashboard right click and select 'Share'" @@ -824,7 +824,7 @@ export class CurrentUserUtils { const reqdOpts:DocumentOptions = { title: "My Imports", _forceActive: true, _layout_showTitle: "title", childLayoutString: ImportElementBox.LayoutString('data'), _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, childLimitHeight: 0, onClickScriptDisable:"never", - childDragAction: "copy", _layout_autoHeight: true, _yMargin: 50, _gridGap: 15, layout_boxShadow: "0 0", _lockedPosition: true, isSystem: true, _chromeHidden: true, + childDragAction: dropActionType.copy, _layout_autoHeight: true, _yMargin: 50, _gridGap: 15, layout_boxShadow: "0 0", _lockedPosition: true, isSystem: true, _chromeHidden: true, dontRegisterView: true, layout_explainer: "This is where documents that are Imported into Dash will go." }; const myImports = DocUtils.AssignDocField(doc, field, (opts) => Docs.Create.MasonryDocument([], opts), reqdOpts, undefined, {onClick: "deselectAll()"}); @@ -886,7 +886,7 @@ export class CurrentUserUtils { this.setupDocTemplates(doc); // sets up the template menu of templates //this.setupFieldInfos(doc); // sets up the collection of field info descriptions for each possible DocumentOption DocUtils.AssignDocField(doc, "globalScriptDatabase", (opts) => Docs.Prototypes.MainScriptDocument(), {}); - DocUtils.AssignDocField(doc, "myHeaderBar", (opts) => Docs.Create.MulticolumnDocument([], opts), { title: "My Header Bar", isSystem: true, _chromeHidden:true, childLayoutFitWidth:false, childDocumentsActive:false, dropAction: 'move'}); // drop down panel at top of dashboard for stashing documents + DocUtils.AssignDocField(doc, "myHeaderBar", (opts) => Docs.Create.MulticolumnDocument([], opts), { title: "My Header Bar", isSystem: true, _chromeHidden:true, childLayoutFitWidth:false, childDocumentsActive:false, dropAction: dropActionType.move}); // drop down panel at top of dashboard for stashing documents Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MyDashboards) Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MySharedDocs) @@ -909,9 +909,9 @@ export class CurrentUserUtils { const options = pair[1] as FInfo; const opts:DocumentOptions = { isSystem: true, title: pair[0], ...OmitKeys(options, ["values"]).omit, fieldIsLayout: pair[0].startsWith("_")}; switch (options.fieldType) { - case "boolean": opts.fieldValues = new List(options.values as any); break; - case "number": opts.fieldValues = new List(options.values as any); break; - case Doc.name: opts.fieldValues = new List(options.values as any); break; + case FInfoFieldType.boolean: opts.fieldValues = new List(options.values as any); break; + case FInfoFieldType.number: opts.fieldValues = new List(options.values as any); break; + case FInfoFieldType.Doc: opts.fieldValues = new List(options.values as any); break; default: opts.fieldValues = new List(options.values as any); break;// string, pointerEvents, dimUnit, dropActionType } DocUtils.AssignDocField(infos, pair[0], opts => Doc.assign(new Doc(), OmitKeys(opts,["values"]).omit), opts); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 1f093a33c..f6af6196f 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,10 +1,24 @@ +/** + * The DragManager handles all dragging interactions that occur entirely within Dash (as opposed to external drag operations from the file system, etc) + * + * Events are generated for + * a pause in the drag movement (dashDragMovePause) as a Doc(s) is dragged, + * just before (dashPreDrop) a Doc(s) is dropped, + * and just after (dashDropEvent) a Doc(s) is dropped + * If the document is dragged and paused over the golden layout header tabs, the + * drag interaction will switch to a golden layout tab drag. + * + * All drag operations can be aborted by hitting the Esc key + * + */ + import { action, observable, runInAction } from 'mobx'; import { DateField } from '../../fields/DateField'; import { Doc, Field, Opt, StrListCast } from '../../fields/Doc'; import { List } from '../../fields/List'; import { PrefetchProxy } from '../../fields/Proxy'; import { ScriptField } from '../../fields/ScriptField'; -import { ScriptCast, StrCast } from '../../fields/Types'; +import { ScriptCast } from '../../fields/Types'; import { emptyFunction, Utils } from '../../Utils'; import { Docs, DocUtils } from '../documents/Documents'; import { CollectionFreeFormDocumentView } from '../views/nodes/CollectionFreeFormDocumentView'; @@ -16,7 +30,15 @@ import { UndoManager } from './UndoManager'; import { DocData } from '../../fields/DocSymbols'; const { default : { contextMenuZindex } } = require('../views/global/globalCssVariables.module.scss'); // prettier-ignore -export type dropActionType = 'embed' | 'copy' | 'move' | 'add' | 'same' | 'inSame' | 'proto' | 'none' | undefined; // undefined = move, "same" = move but don't call dropPropertiesToRemove +export enum dropActionType { + embed = 'embed', // create a new embedding of the dragged document for the new location + copy = 'copy', // copy the dragged document + move = 'move', // move the dragged document to the drop location after removing it from where it was + add = 'add', // add the dragged document to the drop location without removing it from where it was + same = 'same', // only allow drop within same collection (or same hierarchical tree collection) + inPlace = 'inSame', // keep document in place (unless overridden by a drag modifier) + proto = 'proto', +} // undefined = move, same = move but doesn't call dropPropertiesToRemove /** * Initialize drag @@ -129,9 +151,9 @@ export namespace DragManager { treeViewDoc?: Doc; offset: number[]; canEmbed?: boolean; - userDropAction: dropActionType; // the user requested drop action -- this will be honored as specified by modifier keys + userDropAction?: dropActionType; // the user requested drop action -- this will be honored as specified by modifier keys defaultDropAction?: dropActionType; // an optionally specified default drop action when there is no user drop actionl - this will be honored if there is no user drop action - dropAction: dropActionType; // a drop action request by the initiating code. the actual drop action may be different -- eg, if the request is 'embed', but the document is dropped within the same collection, the drop action will be switched to 'move' + dropAction?: dropActionType; // a drop action request by the initiating code. the actual drop action may be different -- eg, if the request is 'embed', but the document is dropped within the same collection, the drop action will be switched to 'move' dropPropertiesToRemove?: string[]; moveDocument?: MoveFunction; removeDocument?: RemoveFunction; @@ -170,8 +192,8 @@ export namespace DragManager { dropDocCreator: (annotationOn: Doc | undefined) => Doc; dropDocument?: Doc; offset: number[]; - dropAction: dropActionType; - userDropAction: dropActionType; + dropAction?: dropActionType; + userDropAction?: dropActionType; } let defaultPreDropFunc = (e: Event, de: DragManager.DropEvent, targetAction: dropActionType) => { @@ -189,7 +211,7 @@ export namespace DragManager { const handler = (e: Event) => dropFunc(e, (e as CustomEvent).detail); const preDropHandler = (e: Event) => { const de = (e as CustomEvent).detail; - (preDropFunc ?? defaultPreDropFunc)(e, de, StrCast(doc.dropAction) as dropActionType); + (preDropFunc ?? defaultPreDropFunc)(e, de, doc.dropAction as any as dropActionType); }; element.addEventListener('dashOnDrop', handler); element.addEventListener('dashPreDrop', preDropHandler); @@ -218,19 +240,19 @@ export namespace DragManager { dragData.draggedDocuments.map(async d => !dragData.isDocDecorationMove && !dragData.userDropAction && ScriptCast(d.onDragStart) ? addAudioTag(ScriptCast(d.onDragStart).script.run({ this: d }).result) - : docDragData.dropAction === 'embed' + : docDragData.dropAction === dropActionType.embed ? Doc.BestEmbedding(d) - : docDragData.dropAction === 'add' + : docDragData.dropAction === dropActionType.add ? d - : docDragData.dropAction === 'proto' + : docDragData.dropAction === dropActionType.proto ? d[DocData] - : docDragData.dropAction === 'copy' + : docDragData.dropAction === dropActionType.copy ? (await Doc.MakeClone(d)).clone : d ) ) ).filter(d => d); - !['same', 'proto'].includes(docDragData.dropAction as any) && + ![dropActionType.same, dropActionType.proto].includes(docDragData.dropAction as any) && docDragData.droppedDocuments // .filter(drop => !drop.dragOnlyWithinContainer || ['embed', 'copy'].includes(docDragData.dropAction as any)) .forEach((drop: Doc, i: number) => { @@ -504,7 +526,7 @@ export namespace DragManager { const moveHandler = (e: PointerEvent) => { e.preventDefault(); // required or dragging text menu link item ends up dragging the link button as native drag/drop if (dragData instanceof DocumentDragData) { - dragData.userDropAction = e.ctrlKey && e.altKey ? 'copy' : e.shiftKey ? 'move' : e.ctrlKey ? 'embed' : dragData.defaultDropAction; + dragData.userDropAction = e.ctrlKey && e.altKey ? dropActionType.copy : e.shiftKey ? dropActionType.move : e.ctrlKey ? dropActionType.embed : dragData.defaultDropAction; } if (['lm_tab', 'lm_title_wrap', 'lm_tabs', 'lm_header'].includes(typeof (e.target as any).className === 'string' ? (e.target as any)?.className : '') && dragData.draggedDocuments.length === 1) { if (!startWindowDragTimer) { @@ -530,7 +552,7 @@ export namespace DragManager { if (target && !Doc.UserDoc()._noAutoscroll && !options?.noAutoscroll && !dragData.draggedDocuments?.some((d: any) => d._freeform_noAutoPan)) { const autoScrollHandler = () => { target.dispatchEvent( - new CustomEvent('dashDragAutoScroll', { + new CustomEvent('dashDragMovePause', { bubbles: true, detail: { shiftKey: e.shiftKey, @@ -552,7 +574,7 @@ export namespace DragManager { screenY: e.screenY, detail: e.detail, view: e.view ? e.view : (new Window() as any), - nativeEvent: new DragEvent('dashDragAutoScroll'), + nativeEvent: new DragEvent('dashDragMovePause'), currentTarget: target, target: target, bubbles: true, @@ -566,7 +588,7 @@ export namespace DragManager { isPropagationStopped: () => ('not implemented for this event' ? false : false), persist: emptyFunction, timeStamp: e.timeStamp, - type: 'dashDragAutoScroll', + type: 'dashDragMovePause', }, }) ); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index b6cb845a6..3be52597a 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -19,7 +19,7 @@ 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 { DragManager, dropActionType } from '../util/DragManager'; import { GroupManager } from '../util/GroupManager'; import { HistoryUtil } from '../util/History'; import { Hypothesis } from '../util/HypothesisUtils'; @@ -623,7 +623,7 @@ export class MainView extends ObservableReactComponent<{}> { isContentActive={returnTrue} // headerBar is awlays contentActive which means its items are always documentActive ScreenToLocalTransform={this.headerBarScreenXf} childHideResizeHandles={true} - childDragAction="move" + childDragAction={dropActionType.move} dontRegisterView={true} hideResizeHandles={true} PanelWidth={this.headerBarDocWidth} @@ -905,7 +905,7 @@ export class MainView extends ObservableReactComponent<{}> { Document={Doc.MyDockedBtns} docViewPath={returnEmptyDocViewList} fieldKey="data" - dropAction="embed" + dropAction={dropActionType.embed} styleProvider={DefaultStyleProvider} select={emptyFunction} isAnyChildContentActive={returnFalse} diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 0f90818ef..8729ef549 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -11,7 +11,7 @@ import { RichTextField } from '../../../fields/RichTextField'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../../Utils'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; -import { DragManager } from '../../util/DragManager'; +import { DragManager, dropActionType } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; import { SettingsManager } from '../../util/SettingsManager'; import { Transform } from '../../util/Transform'; @@ -91,7 +91,7 @@ export class CollectionMenu extends AntimodeMenu { Document={selDoc} docViewPath={returnEmptyDocViewList} fieldKey="data" - dropAction="embed" + dropAction={dropActionType.embed} styleProvider={DefaultStyleProvider} select={emptyFunction} isContentActive={returnTrue} diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx index d0df77cbe..7d7f0bb61 100644 --- a/src/client/views/collections/CollectionPileView.tsx +++ b/src/client/views/collections/CollectionPileView.tsx @@ -13,6 +13,7 @@ import { computePassLayout, computeStarburstLayout } from './collectionFreeForm' import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; import './CollectionPileView.scss'; import { CollectionSubView } from './CollectionSubView'; +import { dropActionType } from '../../util/DragManager'; @observer export class CollectionPileView extends CollectionSubView() { @@ -72,7 +73,7 @@ export class CollectionPileView extends CollectionSubView() { // pile children never have their contents active, but will be document active whenever the entire pile is. childContentsActive={returnFalse} childDocumentsActive={this._props.isDocumentActive} - childDragAction="move" + childDragAction={dropActionType.move} childClickScript={this.toggleIcon} />
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 786301136..4d60cbefc 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -153,12 +153,18 @@ export class CollectionTreeView extends CollectionSubView { + protected onInternalPreDrop = (e: Event, de: DragManager.DropEvent, targetDropAction: dropActionType) => { const dragData = de.complete.docDragData; if (dragData) { - const sameTree = Doc.AreProtosEqual(dragData.treeViewDoc, this.Document) ? true : false; + const sourceDragAction = dragData.dropAction; + const sameTree = () => Doc.AreProtosEqual(dragData.treeViewDoc, this.Document); const isAlreadyInTree = () => sameTree || dragData.draggedDocuments.some(d => d.embedContainer === this.Document && this.childDocs.includes(d)); - dragData.dropAction = dropAction && !isAlreadyInTree() ? dropAction : sameTree && dragData.dropAction !== 'inSame' ? 'same' : dragData.dropAction; + dragData.dropAction = + targetDropAction && !isAlreadyInTree() // if dropped document is not in the tree + ? targetDropAction // then use the target's drop action if it's specified + : !sameTree() || sourceDragAction === dropActionType.inPlace // if doc from another tree, or a non inPlace source drag action is specified + ? sourceDragAction // use the source dragAction + : dropActionType.same; // otherwise use same tree semantics to move within tree e.stopPropagation(); } }; @@ -287,7 +293,7 @@ export class CollectionTreeView extends CollectionSubView this.addDoc(doc, relativeTo, before); const moveDoc = (d: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this._props.moveDocument?.(d, target, addDoc) || false; if (this._renderCount < this.treeChildren.length) setTimeout(action(() => (this._renderCount = Math.min(this.treeChildren.length, this._renderCount + 20)))); @@ -473,7 +479,7 @@ export class CollectionTreeView extends CollectionSubView { droppedDocuments: Doc[], before: boolean, inside: number | boolean, - dropAction: dropActionType, + dropAction: dropActionType | undefined, removeDocument: DragManager.RemoveFunction | undefined, moveDocument: DragManager.MoveFunction | undefined, forceAdd: boolean, @@ -1161,7 +1161,7 @@ export class TreeView extends ObservableReactComponent { const before = pt[1] < rect.top + rect.height / 2; const inside = this.treeView.fileSysMode && !this.Document.isFolder ? false : pt[0] > rect.left + rect.width * 0.33 || (!before && this.treeViewOpen && this.childDocs?.length ? true : false); - const docs = this.treeView.onTreeDrop(de, (docs: Doc[]) => this.dropDocuments(docs, before, inside, 'copy', undefined, undefined, false, false)); + this.treeView.onTreeDrop(de, (docs: Doc[]) => this.dropDocuments(docs, before, inside, dropActionType.copy, undefined, undefined, false, false)); }; render() { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 50a9feff8..50b3dbd70 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -462,7 +462,7 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout).filter(cd => (this.Document._freeform_useClusters ? NumCast(cd.layout_cluster) : NumCast(cd.group, -1)) === cluster); const clusterDocs = eles.map(ele => DocumentManager.Instance.getDocumentView(ele, this.DocumentView?.())!); const { left, top } = clusterDocs[0].getBounds || { left: 0, top: 0 }; - const de = new DragManager.DocumentDragData(eles, e.ctrlKey || e.altKey ? 'embed' : undefined); + const de = new DragManager.DocumentDragData(eles, e.ctrlKey || e.altKey ? dropActionType.embed : undefined); de.moveDocument = this._props.moveDocument; de.offset = this.screenToFreeformContentsXf.transformDirection(ptsParent.clientX - left, ptsParent.clientY - top); DragManager.StartDocumentDrag( diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index a417d777a..d0e59180d 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -635,8 +635,13 @@ export class MarqueeView extends ObservableReactComponent) => { + onDragMovePause = (e: CustomEvent) => { if ((e as any).handlePan || this._props.isAnnotationOverlay) return; (e as any).handlePan = true; @@ -659,7 +664,7 @@ export class MarqueeView extends ObservableReactComponent { - r?.addEventListener('dashDragAutoScroll', this.onDragAutoScroll as any); + r?.addEventListener('dashDragMovePause', this.onDragMovePause as any); this.MarqueeRef = r; }} style={{ diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 31b4a2dd4..eee3836d2 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -10,7 +10,7 @@ import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Ty import { emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils'; import { Docs, DocumentOptions, DocUtils, FInfo } from '../../../documents/Documents'; import { DocumentManager } from '../../../util/DocumentManager'; -import { DragManager } from '../../../util/DragManager'; +import { DragManager, dropActionType } from '../../../util/DragManager'; import { SelectionManager } from '../../../util/SelectionManager'; import { undoable, undoBatch } from '../../../util/UndoManager'; import { ContextMenu } from '../../ContextMenu'; @@ -981,7 +981,7 @@ class CollectionSchemaViewDoc extends ObservableReactComponent() { }; childLayoutTemplate = () => Docs.Create.PresElementBoxDocument(); - removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.Document, this.fieldKey, doc); + removeDocument = (doc: Doc | Doc[]) => !(doc instanceof Doc ? [doc] : doc).map(d => Doc.RemoveDocFromList(this.Document, this.fieldKey, d)).some(p => !p); getTransform = () => this.ScreenToLocalBoxXf().translate(-5, -65); // listBox padding-left and pres-box-cont minHeight panelHeight = () => this._props.PanelHeight() - 40; /** @@ -2607,7 +2608,7 @@ export class PresBox extends ViewBoxBaseComponent() { childIgnoreNativeSize={true} moveDocument={returnFalse} ignoreUnrendered={true} - childDragAction="move" + childDragAction={dropActionType.move} setContentViewBox={emptyFunction} //childLayoutFitWidth={returnTrue} childOpacity={returnOne} diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx index 4155800b8..0952dda20 100644 --- a/src/client/views/topbar/TopBar.tsx +++ b/src/client/views/topbar/TopBar.tsx @@ -25,6 +25,7 @@ import { Colors } from '../global/globalEnums'; import { DocumentViewInternal, returnEmptyDocViewList } from '../nodes/DocumentView'; import { DefaultStyleProvider } from '../StyleProvider'; import './TopBar.scss'; +import { dropActionType } from '../../util/DragManager'; /** * ABOUT: This is the topbar in Dash, which included the current Dashboard as well as access to information on the user @@ -102,7 +103,7 @@ export class TopBar extends React.Component { Document={selDoc} docViewPath={returnEmptyDocViewList} fieldKey="data" - dropAction="embed" + dropAction={dropActionType.embed} styleProvider={DefaultStyleProvider} select={emptyFunction} isContentActive={returnTrue} diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts index 8eeb52709..1cacfe30c 100644 --- a/src/fields/documentSchemas.ts +++ b/src/fields/documentSchemas.ts @@ -96,9 +96,9 @@ export const documentSchema = createSchema({ // drag drop properties _dragOnlyWithinContainer: 'boolean', // whether document can be dropped into a different collection dragFactory: Doc, // the document that serves as the "template" for the onDragStart script. ie, to drag out copies of the dragFactory document. - dropAction: 'string', // override specifying what should happen when something is dropped on this document (can be "embed", "copy", "move") - dragAction: 'string', // override specifying what should happen when this document s dragged (can be "embed", "copy", "move") - childDragAction: 'string', // specify the override for what should happen when the child of a collection is dragged from it and dropped (can be "embed" or "copy") + dropAction: 'string', // override specifying what should happen when something is dropped on this document (dropActionType) + dragAction: 'string', // override specifying what should happen when this document s dragged (dropActionType) + childDragAction: 'string', // specify the override for what should happen when the child of a collection is dragged from it and dropped (dropActionType) dropPropertiesToRemove: listSpec('string'), // properties that should be removed from the embed/copy/etc of this document when it is dropped }); -- cgit v1.2.3-70-g09d2 From ab658feb8d5a0a2c7eb2bd213bff227b7accb23a Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 26 Feb 2024 14:45:02 -0500 Subject: fixed tooltips to not grab events - this made moving down a menu a problem since the tooltip blocked the next menu item and wouldn't give the hover event to the next menu item. fixed proto_embeddings to update when lassoing a collection in marqueeView which made showContexts in property view do the right thing. --- src/client/views/DocComponent.tsx | 8 ++++---- src/client/views/PropertiesDocContextSelector.tsx | 4 ++-- src/client/views/collections/CollectionDockingView.tsx | 6 ++++-- src/client/views/linking/LinkMenuItem.tsx | 14 +++++++------- src/fields/Doc.ts | 11 ++++++----- 5 files changed, 23 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 3d5a5b945..2a527eca1 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -187,14 +187,14 @@ export function ViewBoxAnnotatableComponent

() { const toRemove = value.filter(v => docs.includes(v)); if (toRemove.length !== 0) { - const recent = this.Document !== Doc.MyRecentlyClosed ? Doc.MyRecentlyClosed : undefined; + const recentlyClosed = this.Document !== Doc.MyRecentlyClosed ? Doc.MyRecentlyClosed : undefined; toRemove.forEach(doc => { leavePushpin && DocUtils.LeavePushpin(doc, annotationKey ?? this.annotationKey); Doc.RemoveDocFromList(targetDataDoc, annotationKey ?? this.annotationKey, doc, true); - Doc.RemoveEmbedding(doc, doc); doc.embedContainer = undefined; - if (recent && !dontAddToRemoved) { - doc.type !== DocumentType.LOADING && Doc.AddDocToList(recent, 'data', doc, undefined, true, true); + if (recentlyClosed && !dontAddToRemoved && doc.type !== DocumentType.LOADING) { + Doc.AddDocToList(recentlyClosed, 'data', doc, undefined, true, true); + Doc.RemoveEmbedding(doc, doc); } }); if (targetDataDoc.isGroup && DocListCast(targetDataDoc[annotationKey ?? this.annotationKey]).length < 2) { diff --git a/src/client/views/PropertiesDocContextSelector.tsx b/src/client/views/PropertiesDocContextSelector.tsx index 361451c4d..b8bbde9de 100644 --- a/src/client/views/PropertiesDocContextSelector.tsx +++ b/src/client/views/PropertiesDocContextSelector.tsx @@ -30,12 +30,12 @@ export class PropertiesDocContextSelector extends ObservableReactComponent embedding.embedContainer && embedding.embedContainer instanceof Doc).reduce((set, embedding) => set.add(Cast(embedding.embedContainer, Doc, null)), new Set()); - const containerSets = Array.from(containerProtos.keys()).map(container => Doc.GetEmbeddings(container)); + const containerSets = Array.from(containerProtos.keys()).map(container => (Doc.GetEmbeddings(container).length ? Doc.GetEmbeddings(container) : [container])); const containers = containerSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set()); - const doclayoutSets = Array.from(containers.keys()).map(dp => Doc.GetEmbeddings(dp)); + const doclayoutSets = Array.from(containers.keys()).map(dp => (Doc.GetEmbeddings(dp).length ? Doc.GetEmbeddings(dp) : [dp])); const doclayouts = Array.from( doclayoutSets .reduce((p, set) => { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 68de62d93..d9d6a5eb5 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -488,8 +488,10 @@ export class CollectionDockingView extends CollectionSubView() { Doc.AddDocToList(Doc.MyHeaderBar, 'data', tab.DashDoc, undefined, undefined, true); // if you close a tab that is not embedded somewhere else (an embedded Doc can be opened simultaneously in a tab), then add the tab to recently closed if (tab.DashDoc.embedContainer === this.Document) tab.DashDoc.embedContainer = undefined; - if (!tab.DashDoc.embedContainer) Doc.AddDocToList(Doc.MyRecentlyClosed, 'data', tab.DashDoc, undefined, true, true); - Doc.RemoveEmbedding(tab.DashDoc, tab.DashDoc); + if (!tab.DashDoc.embedContainer) { + Doc.AddDocToList(Doc.MyRecentlyClosed, 'data', tab.DashDoc, undefined, true, true); + Doc.RemoveEmbedding(tab.DashDoc, tab.DashDoc); + } } if (CollectionDockingView.Instance) { const dview = CollectionDockingView.Instance.Document; diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index e694806a5..81dd0eb98 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -10,7 +10,7 @@ import { Cast, DocCast, StrCast } from '../../../fields/Types'; import { WebField } from '../../../fields/URLField'; import { DocumentType } from '../../documents/DocumentTypes'; import { DocumentManager } from '../../util/DocumentManager'; -import { DragManager } from '../../util/DragManager'; +import { DragManager, dropActionType } from '../../util/DragManager'; import { LinkFollower } from '../../util/LinkFollower'; import { LinkManager } from '../../util/LinkManager'; import { SelectionManager } from '../../util/SelectionManager'; @@ -45,7 +45,7 @@ export async function StartLinkTargetsDrag(dragEle: HTMLElement, docView: Docume const dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs); dragData.canEmbed = true; - dragData.dropAction = 'embed'; + dragData.dropAction = dropActionType.embed; DragManager.StartDocumentDrag([dragEle], dragData, downX, downY, undefined); } @@ -89,7 +89,7 @@ export class LinkMenuItem extends ObservableReactComponent { this, e, e => { - const dragData = new DragManager.DocumentDragData([this._props.linkDoc], 'embed'); + const dragData = new DragManager.DocumentDragData([this._props.linkDoc], dropActionType.embed); dragData.dropPropertiesToRemove = ['hidden']; DragManager.StartDocumentDrag([this._editRef.current!], dragData, e.x, e.y); return true; @@ -177,12 +177,12 @@ export class LinkMenuItem extends ObservableReactComponent { className="linkMenu-name" //title="drag to view target. click to customize." onPointerDown={this.onLinkButtonDown}>

- Edit Link
}> + Edit Link
}>
e.stopPropagation()}>
- Show/Hide Link
}> + Show/Hide Link}>
@@ -211,7 +211,7 @@ export class LinkMenuItem extends ObservableReactComponent {

) : null}
- Follow Link
}> + Follow Link}>

{this._props.linkDoc.linksToAnnotation && Cast(this._props.destinationDoc.data, WebField)?.url.href === this._props.linkDoc.annotationUri ? 'Annotation in' : ''} {StrCast(title)}

@@ -221,7 +221,7 @@ export class LinkMenuItem extends ObservableReactComponent {
- Delete Link
}> + Delete Link}>
e.stopPropagation()}>
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 56d50846a..b1bdd50a7 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -391,7 +391,10 @@ export class Doc extends RefField { export namespace Doc { export function SetContainer(doc: Doc, container: Doc) { - container !== Doc.MyRecentlyClosed && (doc.embedContainer = container); + if (container !== Doc.MyRecentlyClosed) { + doc.embedContainer = container; + Doc.AddEmbedding(doc, doc); + } } export function RunCachedUpdate(doc: Doc, field: string) { const update = doc[CachedUpdates][field]; @@ -604,7 +607,7 @@ export namespace Doc { const dataDoc = doc[DocData]; const availableEmbeddings = Doc.GetEmbeddings(dataDoc); const bestEmbedding = [...(dataDoc !== doc ? [doc] : []), ...availableEmbeddings].find(doc => !doc.embedContainer && doc.author === Doc.CurrentUserEmail); - bestEmbedding && Doc.AddDocToList(dataDoc, 'protoEmbeddings', doc, undefined, undefined, undefined, undefined, undefined, true); + bestEmbedding && Doc.AddDocToList(dataDoc, 'proto_embeddings', doc, undefined, undefined, undefined, undefined, undefined, true); return bestEmbedding ?? Doc.MakeEmbedding(doc); } @@ -984,10 +987,9 @@ export namespace Doc { Object.keys(doc) .filter(key => key.startsWith('acl')) .forEach(key => (delegate[key] = doc[key])); - if (!Doc.IsSystem(doc)) Doc.AddEmbedding(doc, delegate); title && (delegate.title = title); delegate[Initializing] = false; - Doc.AddEmbedding(doc, delegate); + if (!Doc.IsSystem(doc)) Doc.AddEmbedding(doc, delegate); return delegate; } return undefined; @@ -1008,7 +1010,6 @@ export namespace Doc { delegate[Initializing] = true; delegate.proto = delegateProto; delegate.author = Doc.CurrentUserEmail; - Doc.AddEmbedding(delegateProto, delegate); delegate[Initializing] = false; delegateProto[Initializing] = false; return delegate; -- cgit v1.2.3-70-g09d2 From 86726ad1b7ef40ac374b53f9d5902441537df7bd Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 28 Feb 2024 10:38:54 -0500 Subject: changed multirow view to support a maxShown flag so that headerBar doesn't take forever to load with a lot of closed tabs. --- src/client/documents/Documents.ts | 1 + src/client/util/CurrentUserUtils.ts | 2 +- src/client/util/DragManager.ts | 2 - src/client/views/FilterPanel.tsx | 4 +- src/client/views/OverlayView.tsx | 4 +- .../CollectionMulticolumnView.tsx | 58 +++++++++++++++------- .../CollectionMultirowView.tsx | 1 - 7 files changed, 48 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 8a13395c3..9b17901ca 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -267,6 +267,7 @@ export class DocumentOptions { _layout_reflowVertical?: BOOLt = new BoolInfo('native height can be changed independent of width by dragging decoration resizers'); _layout_reflowHorizontal?: BOOLt = new BoolInfo('whether a doc with a native size can be horizonally resized, causing some form of reflow'); layout_boxShadow?: string; // box-shadow css string OR "standard" to use dash standard box shadow + layout_maxShown?: NUMt = new NumInfo('maximum number of children to display at one time (see multicolumnview)'); _layout_autoHeight?: BOOLt = new BoolInfo('whether document automatically resizes vertically to display contents'); _layout_curPage?: NUMt = new NumInfo('current page of a PDF or other? paginated document', false); _layout_currentTimecode?: NUMt = new NumInfo('the current timecode of a time-based document (e.g., current time of a video) value is in seconds', false); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index d396ba815..289384be0 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -886,7 +886,7 @@ export class CurrentUserUtils { this.setupDocTemplates(doc); // sets up the template menu of templates //this.setupFieldInfos(doc); // sets up the collection of field info descriptions for each possible DocumentOption DocUtils.AssignDocField(doc, "globalScriptDatabase", (opts) => Docs.Prototypes.MainScriptDocument(), {}); - DocUtils.AssignDocField(doc, "myHeaderBar", (opts) => Docs.Create.MulticolumnDocument([], opts), { title: "My Header Bar", isSystem: true, _chromeHidden:true, childLayoutFitWidth:false, childDocumentsActive:false, dropAction: dropActionType.move}); // drop down panel at top of dashboard for stashing documents + DocUtils.AssignDocField(doc, "myHeaderBar", (opts) => Docs.Create.MulticolumnDocument([], opts), { title: "My Header Bar", isSystem: true, _chromeHidden:true, layout_maxShown: 10, childLayoutFitWidth:false, childDocumentsActive:false, dropAction: dropActionType.move}); // drop down panel at top of dashboard for stashing documents Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MyDashboards) Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MySharedDocs) diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index f6af6196f..aa0f77c72 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -101,8 +101,6 @@ export namespace DragManager { export interface DragOptions { dragComplete?: (e: DragCompleteEvent) => void; // function to invoke when drag has completed hideSource?: boolean; // hide source document during drag - offsetX?: number; // offset of top left of source drag visual from cursor - offsetY?: number; noAutoscroll?: boolean; } diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 818c81c9a..455801422 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -121,11 +121,13 @@ export class FilterPanel extends ObservableReactComponent { const valueSet = new Set(childFilters.map(filter => filter.split(Doc.FilterSep)[1])); let rtFields = 0; let subDocs = childDocs; + let gatheredDocs = [] as Doc[]; if (subDocs.length > 0) { let newarray: Doc[] = []; while (subDocs.length > 0) { newarray = []; subDocs.forEach(t => { + gatheredDocs.push(t); const facetVal = t[facetKey]; if (facetVal instanceof RichTextField || typeof facetVal === 'string') rtFields++; facetVal !== undefined && valueSet.add(Field.toString(facetVal as Field)); @@ -135,7 +137,7 @@ export class FilterPanel extends ObservableReactComponent { DocListCast(t[annos ? fieldKey + '_annotations' : fieldKey]).forEach(newdoc => newarray.push(newdoc)); annos && DocListCast(t[fieldKey + '_sidebar']).forEach(newdoc => newarray.push(newdoc)); }); - subDocs = newarray; + subDocs = newarray.filter(d => !gatheredDocs.includes(d)); } } // } diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 20dc6c9fa..15b1f0275 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -9,7 +9,7 @@ import { Height, Width } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; import { NumCast } from '../../fields/Types'; import { DocumentType } from '../documents/DocumentTypes'; -import { DragManager } from '../util/DragManager'; +import { DragManager, dropActionType } from '../util/DragManager'; import { Transform } from '../util/Transform'; import { LightboxView } from './LightboxView'; import { ObservableReactComponent } from './ObservableReactComponent'; @@ -196,7 +196,7 @@ export class OverlayView extends ObservableReactComponent<{}> { if (e.metaKey) { const dragData = new DragManager.DocumentDragData([d]); dragData.offset = [-offsetx, -offsety]; - dragData.dropAction = 'move'; + dragData.dropAction = dropActionType.move; dragData.removeDocument = this.removeOverlayDoc; dragData.moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => { return dragData.removeDocument!(doc) ? addDocument(doc) : false; diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index b181b59ce..85fe7c896 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -1,10 +1,10 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; -import { Button } from 'browndash-components'; -import { action, computed, makeObservable } from 'mobx'; +import { Button, IconButton } from 'browndash-components'; +import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { emptyFunction, returnFalse } from '../../../../Utils'; +import { FaChevronRight } from 'react-icons/fa'; import { Doc, DocListCast } from '../../../../fields/Doc'; import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { DragManager, dropActionType } from '../../../util/DragManager'; @@ -37,6 +37,8 @@ const resizerWidth = 8; @observer export class CollectionMulticolumnView extends CollectionSubView() { + @observable _startIndex = 0; + constructor(props: any) { super(props); makeObservable(this); @@ -48,7 +50,7 @@ export class CollectionMulticolumnView extends CollectionSubView() { */ @computed private get ratioDefinedDocs() { - return this.childLayoutPairs.map(pair => pair.layout).filter(layout => StrCast(layout._dimUnit, '*') === DimUnit.Ratio); + return this.childLayouts.filter(layout => StrCast(layout._dimUnit, '*') === DimUnit.Ratio); } @computed @@ -57,6 +59,15 @@ export class CollectionMulticolumnView extends CollectionSubView() { return ratioDocs.length ? Math.min(...ratioDocs.map(layout => NumCast(layout._dimMagnitude))) : 1; } + @computed get maxShown() { + return NumCast(this.layoutDoc.layout_maxShown); + } + + @computed + private get childLayouts() { + return (this.maxShown ? this.childLayoutPairs.slice(this._startIndex, this._startIndex + this.maxShown) : this.childLayoutPairs).map(pair => pair.layout); + } + /** * This loops through all childLayoutPairs and extracts the values for _dimUnit * and _dimMagnitude, ignoring any that are malformed. Additionally, it then @@ -69,9 +80,9 @@ export class CollectionMulticolumnView extends CollectionSubView() { private get resolvedLayoutInformation(): LayoutData { let starSum = 0; const widthSpecifiers: WidthSpecifier[] = []; - this.childLayoutPairs.map(pair => { - const unit = StrCast(pair.layout._dimUnit, '*'); - const magnitude = NumCast(pair.layout._dimMagnitude, this.minimumDim); + this.childLayouts.map(layout => { + const unit = StrCast(layout._dimUnit, '*'); + const magnitude = NumCast(layout._dimMagnitude, this.minimumDim); if (unit && magnitude && magnitude > 0 && resolvedUnits.includes(unit)) { unit === DimUnit.Ratio && (starSum += magnitude); widthSpecifiers.push({ magnitude, unit }); @@ -90,7 +101,7 @@ export class CollectionMulticolumnView extends CollectionSubView() { */ // setTimeout(() => { // const { ratioDefinedDocs } = this; - // if (this.childLayoutPairs.length) { + // if (this.childPairs.length) { // const minimum = this.minimumDim; // if (minimum !== 0) { // ratioDefinedDocs.forEach(layout => layout._dimMagnitude = NumCast(layout._dimMagnitude, 1) / minimum, 1); @@ -187,13 +198,14 @@ export class CollectionMulticolumnView extends CollectionSubView() { return Transform.Identity(); // we're still waiting on promises to resolve } let offset = 0; - for (const { layout: candidate } of this.childLayoutPairs) { + var xf = Transform.Identity(); + this.childLayouts.map(candidate => { if (candidate === layout) { - return this.ScreenToLocalBoxXf().translate(-offset / (this._props.NativeDimScaling?.() || 1), 0); + return (xf = this.ScreenToLocalBoxXf().translate(-offset / (this._props.NativeDimScaling?.() || 1), 0)); } offset += this.lookupPixels(candidate) + resizerWidth; - } - return Transform.Identity(); // type coersion, this case should never be hit + }); + return xf; }; @undoBatch @@ -297,10 +309,8 @@ export class CollectionMulticolumnView extends CollectionSubView() { */ @computed private get contents(): JSX.Element[] | null { - const { childLayoutPairs } = this; const collector: JSX.Element[] = []; - for (let i = 0; i < childLayoutPairs.length; i++) { - const { layout } = childLayoutPairs[i]; + this.childLayouts.forEach((layout, i) => { collector.push(
@@ -317,10 +327,10 @@ export class CollectionMulticolumnView extends CollectionSubView() { select={this._props.select} columnUnitLength={this.getColumnUnitLength} toLeft={layout} - toRight={childLayoutPairs[i + 1]?.layout} + toRight={this.childLayouts[i + 1]} /> ); - } + }); collector.pop(); // removes the final extraneous resize bar return collector; } @@ -339,6 +349,20 @@ export class CollectionMulticolumnView extends CollectionSubView() { marginBottom: NumCast(this.Document._yMargin), }}> {this.contents} + {!this._startIndex ? null : ( + +
(this._startIndex = Math.min(this.childLayoutPairs.length - 1, this._startIndex + this.maxShown)))}> +
+
+ )} + {this._startIndex > this.childLayoutPairs.length - 1 ? null : ( + +
(this._startIndex = Math.min(this.childLayoutPairs.length - 1, this._startIndex + this.maxShown)))}> + } color={SettingsManager.userColor} /> +
+
+ )}
); } diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index 659f7ccdc..17bf3e50c 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -1,7 +1,6 @@ import { action, computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { emptyFunction, returnFalse } from '../../../../Utils'; import { Doc, DocListCast } from '../../../../fields/Doc'; import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { DragManager, dropActionType } from '../../../util/DragManager'; -- cgit v1.2.3-70-g09d2 From 4548ec81efc434c8ee5d89b896b2088e4e61d7a0 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 28 Feb 2024 22:22:20 -0500 Subject: extracted field dropdown menu to a components and then cleaned up collectionTimeView, Documentview titles, and FilterPanel to share it --- src/client/documents/Documents.ts | 18 +- src/client/views/FieldsDropdown.tsx | 120 +++++++++++ src/client/views/FilterPanel.tsx | 239 ++++++--------------- .../views/collections/CollectionTimeView.tsx | 55 +---- src/client/views/global/globalScripts.ts | 2 +- src/client/views/nodes/DocumentView.scss | 1 - src/client/views/nodes/DocumentView.tsx | 67 +++--- 7 files changed, 236 insertions(+), 266 deletions(-) create mode 100644 src/client/views/FieldsDropdown.tsx (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 9b17901ca..031560886 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -77,6 +77,7 @@ export enum FInfoFieldType { enumeration, date, list, + rtf, } export class FInfo { description: string = ''; @@ -84,7 +85,7 @@ export class FInfo { fieldType?: FInfoFieldType; values?: Field[]; - filterable?: boolean = true; + filterable?: boolean = true; // can be used as a Filter in FilterPanel // format?: string; // format to display values (e.g, decimal places, $, etc) // parse?: ScriptField; // parse a value from a string constructor(d: string, readOnly?: boolean) { @@ -165,9 +166,19 @@ class DTypeInfo extends FInfo { override searchable = () => false; } class DateInfo extends FInfo { + constructor(d: string, filterable?: boolean) { + super(d, true); + this.filterable = filterable; + } fieldType? = FInfoFieldType.date; values?: DateField[] = []; - filterable = true; +} +class RtfInfo extends FInfo { + constructor(d: string, filterable?: boolean) { + super(d, true); + this.filterable = filterable; + } + fieldType? = FInfoFieldType.rtf; } class ListInfo extends FInfo { fieldType? = FInfoFieldType.list; @@ -178,6 +189,7 @@ type NUMt = NumInfo | number; type STRt = StrInfo | string; type LISTt = ListInfo | List; type DOCt = DocInfo | Doc; +type RTFt = RtfInfo | RichTextField; type DIMt = DimInfo | typeof DimUnit.Pixel | typeof DimUnit.Ratio; type PEVt = PEInfo | 'none' | 'all'; type COLLt = CTypeInfo | CollectionViewType; @@ -191,6 +203,7 @@ export class DocumentOptions { z?: NUMt = new NumInfo('whether document is in overlay (1) or not (0)', false, false, [1, 0]); overlayX?: NUMt = new NumInfo('x coordinate of document in a overlay view', false); overlayY?: NUMt = new NumInfo('y coordinate of document in a overlay view', false); + text?: RTFt = new RtfInfo('rich text of a text doc', true); _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height", false); _dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units"); latitude?: NUMt = new NumInfo('latitude coordinate for map views', false); @@ -470,7 +483,6 @@ export class DocumentOptions { sidebar_type_collection?: string; // collection type of text sidebar data_dashboards?: List; // list of dashboards used in shareddocs; - text?: string; textTransform?: string; letterSpacing?: string; iconTemplate?: string; // name of icon template style diff --git a/src/client/views/FieldsDropdown.tsx b/src/client/views/FieldsDropdown.tsx new file mode 100644 index 000000000..5638d34c6 --- /dev/null +++ b/src/client/views/FieldsDropdown.tsx @@ -0,0 +1,120 @@ +/** + * This creates a dropdown menu that's populated with possible field key names (e.g., author, tags) + * + * The set of field names actually displayed is based on searching the prop 'Document' and its descendants : + * The field list will contain all of the fields within the prop Document and all of its children; + * this list is then pruned down to only include fields that are not marked in Documents.ts to be non-filterable + */ + +import { computed, makeObservable, observable, runInAction } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import Select from 'react-select'; +import { Doc } from '../../fields/Doc'; +import { DocOptions, FInfo } from '../documents/Documents'; +import { SearchUtil } from '../util/SearchUtil'; +import { SettingsManager } from '../util/SettingsManager'; +import './FilterPanel.scss'; +import { ObservableReactComponent } from './ObservableReactComponent'; + +interface fieldsDropdownProps { + Document: Doc; // show fields for this Doc if set, otherwise for all docs in dashboard + selectFunc: (value: string) => void; + menuClose?: () => void; + placeholder?: string | (() => string); + showPlaceholder?: true; // if true, then input field always shows the placeholder value; otherwise, it shows the current selection + addedFields?: string[]; +} + +@observer +export class FieldsDropdown extends ObservableReactComponent { + @observable _newField = ''; + constructor(props: any) { + super(props); + makeObservable(this); + } + + @computed get allDescendantDocs() { + const allDocs = new Set(); + SearchUtil.foreachRecursiveDoc([this._props.Document], (depth, doc) => allDocs.add(doc)); + return Array.from(allDocs); + } + + @computed get fieldsOfDocuments() { + const keys = new Set(); + this.allDescendantDocs.forEach(doc => SearchUtil.documentKeys(doc).filter(key => keys.add(key))); + const sortedKeys = Array.from(keys.keys()) + .filter(key => key[0]) + .filter(key => key.indexOf('modificationDate') !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith('_')) || !Doc.noviceMode) + .sort(); + + Array.from(keys).forEach(key => sortedKeys.splice(sortedKeys.indexOf(key), 1)); + + return [...Array.from(keys), ...sortedKeys]; + } + + render() { + const filteredOptions = ['author', ...(this._newField ? [this._newField] : []), ...(this._props.addedFields ?? []), ...this.fieldsOfDocuments.filter(facet => facet[0] === facet.charAt(0).toUpperCase())]; + + Object.entries(DocOptions) + .filter(opts => opts[1].filterable) + .forEach((pair: [string, FInfo]) => filteredOptions.push(pair[0])); + const options = filteredOptions.sort().map(facet => ({ value: facet, label: facet })); + + console.log(options); + return ( + ({ - ...baseStyles, - color: SettingsManager.userColor, - background: SettingsManager.userBackgroundColor, - }), - placeholder: (baseStyles, state) => ({ - ...baseStyles, - color: SettingsManager.userColor, - background: SettingsManager.userBackgroundColor, - }), - input: (baseStyles, state) => ({ - ...baseStyles, - color: SettingsManager.userColor, - background: SettingsManager.userBackgroundColor, - }), - option: (baseStyles, state) => ({ - ...baseStyles, - color: SettingsManager.userColor, - background: !state.isFocused ? SettingsManager.userBackgroundColor : SettingsManager.userVariantColor, - }), - menuList: (baseStyles, state) => ({ - ...baseStyles, - backgroundColor: SettingsManager.userBackgroundColor, - }), - }} - placeholder={'add a filter'} - options={options} - isMulti={false} - onChange={val => this.facetClick((val as UserOptions).value)} - onKeyDown={e => e.stopPropagation()} - //onMenuClose={onClose} - value={null} - closeMenuOnSelect={true} - /> - ); - } - render() { return (
-
{this.fieldsDropdown}
+
+ +
{/* THE FOLLOWING CODE SHOULD BE DEVELOPER FOR BOOLEAN EXPRESSION (AND / OR) */} {/*
filter.split(Doc.FilterSep)[0] === facetHeader) ?.split(Doc.FilterSep)[1] } style={{ color: SettingsManager.userColor, background: SettingsManager.userBackgroundColor }} - onBlur={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, e.currentTarget.value, !e.currentTarget.value ? 'remove' : 'match'), 'set text filter')} - onKeyDown={e => e.key === 'Enter' && undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, e.currentTarget.value, !e.currentTarget.value ? 'remove' : 'match'), 'set text filter')(e)} + onBlur={undoable(e => Doc.setDocFilter(this.Document, facetHeader, e.currentTarget.value, !e.currentTarget.value ? 'remove' : 'match'), 'set text filter')} + onKeyDown={e => e.key === 'Enter' && undoable(e => Doc.setDocFilter(this.Document, facetHeader, e.currentTarget.value, !e.currentTarget.value ? 'remove' : 'match'), 'set text filter')(e)} /> ); case 'checkbox': @@ -399,12 +311,12 @@ export class FilterPanel extends ObservableReactComponent { filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue) ?.split(Doc.FilterSep)[2] ?? '' )} type={type} - onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} + onChange={undoable(e => Doc.setDocFilter(this.Document, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} /> {facetValue}
@@ -414,64 +326,51 @@ export class FilterPanel extends ObservableReactComponent { case 'range': const domain = renderInfoDomain; const range = renderInfoRange; - - if (range) { - console.log('this is info range ' + range[0] + ' , ' + range[1]); - } - if (domain) { - console.log('this is info domain ' + domain[0] + ', ' + domain[1]); - return ( - <> - {/*
- console.log('on change'))} /> -
*/} - -
- Doc.setDocRangeFilter(this.targetDoc, facetHeader, values)} - values={renderInfoRange!}> - {railProps => } - - {({ handles, activeHandleID, getHandleProps }) => ( -
- {handles.map((handle, i) => { - // const value = i === 0 ? defaultValues[0] : defaultValues[1]; - return ( -
- -
- ); - })} -
- )} -
- - {({ tracks, getTrackProps }) => ( -
- {tracks.map(({ id, source, target }) => ( - - ))} -
- )} -
- - {({ ticks }) => ( -
- {ticks.map(tick => ( - val.toString()} /> - ))} -
- )} -
-
-
- +
+ Doc.setDocRangeFilter(this.Document, facetHeader, values)} + values={renderInfoRange!}> + {railProps => } + + {({ handles, activeHandleID, getHandleProps }) => ( +
+ {handles.map((handle, i) => { + // const value = i === 0 ? defaultValues[0] : defaultValues[1]; + return ( +
+ +
+ ); + })} +
+ )} +
+ + {({ tracks, getTrackProps }) => ( +
+ {tracks.map(({ id, source, target }) => ( + + ))} +
+ )} +
+ + {({ ticks }) => ( +
+ {ticks.map(tick => ( + val.toString()} /> + ))} +
+ )} +
+
+
); } diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index 38f6aa3e7..b92edd165 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -1,12 +1,10 @@ -import { toUpper } from 'lodash'; import { action, computed, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { emptyFunction, returnEmptyString, returnFalse, returnTrue, setupMoveUpEvents } from '../../../Utils'; +import { emptyFunction, returnFalse, returnTrue, setupMoveUpEvents } from '../../../Utils'; import { Doc, Opt, StrListCast } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { ObjectField } from '../../../fields/ObjectField'; -import { RichTextField } from '../../../fields/RichTextField'; import { listSpec } from '../../../fields/Schema'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; @@ -15,7 +13,7 @@ import { DocumentManager } from '../../util/DocumentManager'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; -import { EditableView } from '../EditableView'; +import { FieldsDropdown } from '../FieldsDropdown'; import { DocumentView } from '../nodes/DocumentView'; import { FocusViewOptions } from '../nodes/FieldView'; import { PresBox } from '../nodes/trails'; @@ -192,51 +190,6 @@ export class CollectionTimeView extends CollectionSubView() { ContextMenu.Instance.addItem({ description: 'Options...', subitems: layoutItems, icon: 'eye' }); }; - @computed get _allFacets() { - const facets = new Set(); - this.childDocs.forEach(child => Object.keys(Doc.GetProto(child)).forEach(key => facets.add(key))); - Doc.AreProtosEqual(this.dataDoc, this.Document) && this.childDocs.forEach(child => Object.keys(child).forEach(key => facets.add(key))); - return Array.from(facets); - } - menuCallback = (x: number, y: number) => { - ContextMenu.Instance.clearItems(); - const keySet: Set = new Set(['tags']); - - this.childLayoutPairs.map(pair => - this._allFacets - .filter(fieldKey => pair.layout[fieldKey] instanceof RichTextField || typeof pair.layout[fieldKey] === 'number' || typeof pair.layout[fieldKey] === 'boolean' || typeof pair.layout[fieldKey] === 'string') - .filter(fieldKey => fieldKey[0] !== '_' && (fieldKey === 'tags' || fieldKey[0] === toUpper(fieldKey)[0])) - .map(fieldKey => keySet.add(fieldKey)) - ); - - const docItems: ContextMenuProps[] = Array.from(keySet).map(fieldKey => - ({ description: ':' + fieldKey, event: () => (this.layoutDoc._pivotField = fieldKey), icon: 'compress-arrows-alt' })); // prettier-ignore - docItems.push({ description: ':default', event: () => (this.layoutDoc._pivotField = undefined), icon: 'compress-arrows-alt' }); - ContextMenu.Instance.addItem({ description: 'Pivot Fields ...', subitems: docItems, icon: 'eye' }); - ContextMenu.Instance.displayMenu(x, y, ':'); - }; - - @computed get pivotKeyUI() { - return ( -
- { - if (value?.length) { - this.layoutDoc._pivotField = value; - return true; - } - return false; - }} - background={'#f1efeb'} // this._props.headingObject ? this._props.headingObject.color : "#f1efeb"; - contents={':' + StrCast(this.layoutDoc._pivotField)} - showMenuOnLoad={true} - display={'inline'} - menuCallback={this.menuCallback} - /> -
- ); - } render() { let nonNumbers = 0; @@ -263,7 +216,6 @@ export class CollectionTimeView extends CollectionSubView() { return (
- {this.pivotKeyUI} {this.contents} {!this._props.isSelected() || !doTimeline ? null : ( <> @@ -272,6 +224,9 @@ export class CollectionTimeView extends CollectionSubView() {
)} +
+ (this.layoutDoc._pivotField = fieldKey)} placeholder={StrCast(this.layoutDoc._pivotField)} /> +
); } diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 51672513b..e73ab25b5 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -78,7 +78,7 @@ ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boole } if (SelectionManager.Views.length) { SelectionManager.Docs.forEach(doc => { - Doc.GetProto(doc).layout_headingColor = color; + doc[DocData].layout_headingColor = color === 'transparent' ? undefined : color; doc.layout_showTitle = color === 'transparent' ? undefined : StrCast(doc.layout_showTitle, 'title'); }); } else { diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index c4dab16fb..5421c1b50 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -180,7 +180,6 @@ .documentView-titleWrapper, .documentView-titleWrapper-hover { - overflow: hidden; color: $black; transform-origin: top left; top: 0; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index abb1aa59f..b0e8cf6ff 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -48,6 +48,7 @@ import { KeyValueBox } from './KeyValueBox'; import { LinkAnchorBox } from './LinkAnchorBox'; import { FormattedTextBox } from './formattedText/FormattedTextBox'; import { PresEffect, PresEffectDirection } from './trails'; +import { FieldsDropdown } from '../FieldsDropdown'; interface Window { MediaRecorder: MediaRecorder; } @@ -784,28 +785,25 @@ export class DocumentViewInternal extends DocComponent, props: Opt, property: string) => this._props?.styleProvider?.(doc, props, property + ':caption'); - fieldsDropdown = (reqdFields: string[], dropdownWidth: number, placeholder: string, onChange: (val: string | number) => void, onClose: () => void) => { - const filteredFields = Object.entries(DocOptions).reduce((set, [field, opts]) => (opts.filterable ? set.add(field) : set), new Set(reqdFields)); + fieldsDropdown = (placeholder: string) => { return ( -
-
r && (this._titleDropDownInnerWidth = Number(getComputedStyle(r).width.replace('px', ''))))} - onPointerDown={action(e => (this._changingTitleField = true))} - style={{ width: 'max-content', transformOrigin: 'left', transform: `scale(${this.titleHeight / 30 /* height of Dropdown */})` }}> - !isOpen && (this._changingTitleField = false))} - selectedVal={placeholder} - setSelectedVal={onChange} - color={SettingsManager.userColor} - background={SettingsManager.userVariantColor} - type={Type.TERT} - closeOnSelect={true} - dropdownType={DropdownType.SELECT} - items={Array.from(filteredFields).map(facet => ({ val: facet, text: facet }))} - width={100} - fillWidth - /> -
+
r && (this._titleDropDownInnerWidth = Number(getComputedStyle(r).width.replace('px', ''))))} + onPointerDown={action(e => (this._changingTitleField = true))} + style={{ width: 'max-content', background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor, transformOrigin: 'left', transform: `scale(${this.titleHeight / 30 /* height of Dropdown */})` }}> + { + if (this.layoutDoc.layout_showTitle) { + this.layoutDoc._layout_showTitle = field; + } else if (!this._props.layout_showTitle) { + Doc.UserDoc().layout_showTitle = field; + } + this._changingTitleField = false; + })} + menuClose={action(() => (this._changingTitleField = false))} + />
); }; @@ -839,22 +837,7 @@ export class DocumentViewInternal extends DocComponent - {!dropdownWidth - ? null - : this.fieldsDropdown( - [StrCast(this.layoutDoc.layout_showTitle)], - dropdownWidth, - StrCast(this.layoutDoc.layout_showTitle).split(':')[0], - action((field: string | number) => { - if (this.layoutDoc.layout_showTitle) { - this.layoutDoc._layout_showTitle = field; - } else if (!this._props.layout_showTitle) { - Doc.UserDoc().layout_showTitle = field; - } - this._changingTitleField = false; - }), - action(() => (this._changingTitleField = false)) - )} + {!dropdownWidth ? null :
{this.fieldsDropdown(showTitle)}
}
targetDoc[field.trim()]?.toString()) - .join(' \\ ')} + contents={ + showTitle + .split(';') + .map(field => targetDoc[field.trim()]?.toString()) + .join(' \\ ') || '-unset-' + } display="block" oneLine={true} fontSize={(this.titleHeight / 15) * 10} -- cgit v1.2.3-70-g09d2 From 4cce99ec8d0bb2a45e19dd967dbbb8348c68abe8 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 28 Feb 2024 22:46:23 -0500 Subject: fixed double click of some icons to make them persist (circle, rectangle, fitall). --- src/client/util/CurrentUserUtils.ts | 4 +--- src/client/views/global/globalScripts.ts | 12 ++++++------ src/client/views/nodes/FontIconBox/FontIconBox.tsx | 10 ++++++++-- 3 files changed, 15 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 289384be0..84bed08fa 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -611,9 +611,7 @@ export class CurrentUserUtils { return [ { title: "Snap", icon: "th", toolTip: "Show Snap Lines", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"snaplines", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform { title: "Grid", icon: "border-all", toolTip: "Show Grid", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"grid", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform - { title: "View All", icon: "object-group", toolTip: "Keep all Docs in View",btnType: ButtonType.ToggleButton, ignoreClick:true, expertMode: false, toolType:"viewAll", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform - // want the same style as toggle button, but don't want it to act as an actual toggle, so set disableToggle to true, - { title: "Fit All", icon: "arrows-left-right", toolTip: "Fit Docs to View (once)",btnType: ButtonType.ClickButton,ignoreClick:false,expertMode: false, toolType:"fitOnce", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform + { title: "Fit All", icon: "object-group", toolTip: "Fit Docs to View (double click to make sticky)",btnType: ButtonType.ToggleButton, ignoreClick:true, expertMode: false, toolType:"viewAll", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}', onDoubleClick: '{ return showFreeform(this.toolType, _readOnly_, true);}'}}, // Only when floating document is selected in freeform { title: "Clusters", icon: "braille", toolTip: "Show Doc Clusters", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"clusters", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform { title: "Cards", icon: "brain", toolTip: "Flashcards", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"flashcards", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform { title: "Arrange", icon:"arrow-down-short-wide",toolTip:"Toggle Auto Arrange", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"arrange", funcs: {hidden: 'IsNoviceMode()'}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index e73ab25b5..33704e8fe 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -98,7 +98,7 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { selected ? selected.CollectionFreeFormDocumentView?.float() : console.log('[FontIconBox.tsx] toggleOverlay failed'); }); -ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce', checkResult?: boolean) { +ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce', checkResult?: boolean, persist?: boolean) { const selected = SelectionManager.Docs.lastElement(); // prettier-ignore const map: Map<'flashcards' | 'center' |'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll' | 'fitOnce', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc, dv:DocumentView) => void;}> = new Map([ @@ -112,16 +112,16 @@ ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid }], ['viewAll', { checkResult: (doc:Doc) => BoolCast(doc?._freeform_fitContentsToBox, false), - setDoc: (doc:Doc,dv:DocumentView) => doc._freeform_fitContentsToBox = !doc._freeform_fitContentsToBox, + setDoc: (doc:Doc,dv:DocumentView) => { + if (persist) doc._freeform_fitContentsToBox = !doc._freeform_fitContentsToBox; + else if (doc._freeform_fitContentsToBox) doc._freeform_fitContentsToBox = undefined; + else (dv.ComponentView as CollectionFreeFormView)?.fitContentOnce(); + }, }], ['center', { checkResult: (doc:Doc) => BoolCast(doc?._stacking_alignCenter, false), setDoc: (doc:Doc,dv:DocumentView) => doc._stacking_alignCenter = !doc._stacking_alignCenter, }], - ['fitOnce', { - checkResult: (doc:Doc) => false, - setDoc: (doc:Doc, dv:DocumentView) => (dv.ComponentView as CollectionFreeFormView)?.fitContentOnce() - }], ['clusters', { waitForRender: true, // flags that undo batch should terminate after a re-render giving the script the chance to fire checkResult: (doc:Doc) => BoolCast(doc?._freeform_useClusters, false), diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index 3577cc8d9..91b6de80b 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -7,7 +7,7 @@ import * as React from 'react'; import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc'; import { ScriptField } from '../../../../fields/ScriptField'; import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; -import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; +import { emptyFunction, returnTrue, setupMoveUpEvents, Utils } from '../../../../Utils'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; import { SelectionManager } from '../../../util/SelectionManager'; import { SettingsManager } from '../../../util/SettingsManager'; @@ -314,6 +314,7 @@ export class FontIconBox extends ViewBoxBaseComponent() { const tooltip = StrCast(this.Document.toolTip); const script = ScriptCast(this.Document.onClick); + const double = ScriptCast(this.Document.onDoubleClick); const toggleStatus = script ? script.script.run({ this: this.Document, self: this.Document, value: undefined, _readOnly_: true }).result : false; // Colors const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color); @@ -330,7 +331,12 @@ export class FontIconBox extends ViewBoxBaseComponent() { //background={SettingsManager.userBackgroundColor} icon={this.Icon(color)!} label={this.label} - onPointerDown={() => script.script.run({ this: this.Document, self: this.Document, value: !toggleStatus, _readOnly_: false })} + onPointerDown={e => + setupMoveUpEvents(this, e, returnTrue, emptyFunction, (e, doubleTap) => { + !doubleTap && script.script.run({ this: this.Document, self: this.Document, value: !toggleStatus, _readOnly_: false }); + doubleTap && double.script.run({ this: this.Document, self: this.Document, value: !toggleStatus, _readOnly_: false }); + }) + } /> ); } -- cgit v1.2.3-70-g09d2 From e973de1476194fe68a2f218e458e4619fb71c75e Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 29 Feb 2024 09:34:56 -0500 Subject: fixed minimap to show at least as much as the freeformview is showing (was a problem for example when there was just a single document) --- src/client/views/collections/TabDocView.tsx | 8 ++++++++ .../collections/collectionFreeForm/CollectionFreeFormView.tsx | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 02aa76d82..b52f2e7b6 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -564,6 +564,12 @@ export class TabMinimapView extends ObservableReactComponent Cast(this._props.document.childLayoutTemplate, Doc, null); returnMiniSize = () => NumCast(this._props.document._miniMapSize, 150); miniDown = (e: React.PointerEvent) => { @@ -620,6 +626,8 @@ export class TabMinimapView extends ObservableReactComponent
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 50b3dbd70..e48656f5e 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -159,8 +159,8 @@ export class CollectionFreeFormView extends CollectionSubView e.bounds?.width && !e.bounds.z).map(e => e.bounds!), - NumCast(this.layoutDoc._xPadding, 10), - NumCast(this.layoutDoc._yPadding, 10) + NumCast(this.layoutDoc._xPadding, this._props.xPadding ?? 10), + NumCast(this.layoutDoc._yPadding, this._props.yPadding ?? 10) ); } @computed get nativeWidth() { -- cgit v1.2.3-70-g09d2 From ee48402ef2aa336e28497e308877d4bde3cf118b Mon Sep 17 00:00:00 2001 From: geireann Date: Thu, 29 Feb 2024 14:28:07 -0500 Subject: fixed enum --- src/client/views/nodes/VideoBox.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 40647feff..b2ae7201c 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -31,6 +31,7 @@ import { FocusViewOptions, FieldView, FieldViewProps } from './FieldView'; import { RecordingBox } from './RecordingBox'; import { PinProps, PresBox } from './trails'; import './VideoBox.scss'; +import { dropActionType } from '../../util/DragManager'; /** * VideoBox @@ -335,7 +336,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent() impl this._props.addDocument?.(imageSnapshot); const link = DocUtils.MakeLink(imageSnapshot, this.getAnchor(true), { link_relationship: 'video snapshot' }); link && (DocCast(link.link_anchor_2)[DocData].timecodeToHide = NumCast(DocCast(link.link_anchor_2).timecodeToShow) + 3); - setTimeout(() => downX !== undefined && downY !== undefined && DocumentManager.Instance.getFirstDocumentView(imageSnapshot)?.startDragging(downX, downY, 'move', true)); + setTimeout(() => downX !== undefined && downY !== undefined && DocumentManager.Instance.getFirstDocumentView(imageSnapshot)?.startDragging(downX, downY, dropActionType.move, true)); }; getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => { -- cgit v1.2.3-70-g09d2 From 4e837a73f5fae06368416f99c047d78f6b94565b Mon Sep 17 00:00:00 2001 From: newalina <157907056+newalina@users.noreply.github.com> Date: Thu, 29 Feb 2024 23:16:33 -0500 Subject: add state message gifs --- .../CollectionFreeFormInfoState.tsx | 20 ++-- .../CollectionFreeFormInfoUI.tsx | 117 +++++++++++++-------- src/server/public/assets/dash-colon-menu.gif | Bin 0 -> 348794 bytes .../public/assets/dash-create-link-board.gif | Bin 0 -> 167854 bytes src/server/public/assets/dash-following-link.gif | Bin 0 -> 181851 bytes 5 files changed, 83 insertions(+), 54 deletions(-) create mode 100644 src/server/public/assets/dash-colon-menu.gif create mode 100644 src/server/public/assets/dash-create-link-board.gif create mode 100644 src/server/public/assets/dash-following-link.gif (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx index 58f6b1593..688f84cd5 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx @@ -5,7 +5,6 @@ import * as React from 'react'; import { SettingsManager } from '../../../util/SettingsManager'; import { ObservableReactComponent } from '../../ObservableReactComponent'; import './CollectionFreeFormView.scss'; -// import assets from './assets/link.png'; /** * An Fsa Arc. The first array element is a test condition function that will be observed. @@ -15,18 +14,18 @@ import './CollectionFreeFormView.scss'; export type infoArc = [() => any, (res?: any) => infoState]; export const StateMessage = Symbol('StateMessage'); -export const StateEntryFunc = Symbol('StateEntryFunc'); export const StateMessageGIF = Symbol('StateMessageGIF'); +export const StateEntryFunc = Symbol('StateEntryFunc'); export class infoState { [StateMessage]: string = ''; - [StateEntryFunc]?: () => any; - [StateMessageGIF]?: string = ''; [key: string]: infoArc; - constructor(message: string, arcs: { [key: string]: infoArc }, entryFunc?: () => any, messageGif?: string) { + [StateMessageGIF]?: string = ''; + [StateEntryFunc]?: () => any; + constructor(message: string, arcs: { [key: string]: infoArc }, messageGif?: string, entryFunc?: () => any) { this[StateMessage] = message; Object.assign(this, arcs); - this[StateEntryFunc] = entryFunc; this[StateMessageGIF] = messageGif; + this[StateEntryFunc] = entryFunc; } } @@ -36,16 +35,17 @@ export class infoState { * @param arcs an object with fields containing @infoArcs (an object with field names indicating the arc transition and * field values being a tuple of an arc transition trigger function (that returns a truthy value when the arc should fire), * and an arc transition action function (that sets the next state) + * @param gif the gif displayed when in this state * @param entryFunc a function to call when entering the state * @returns an FSA state */ export function InfoState( msg: string, // arcs: { [key: string]: infoArc }, - entryFunc?: () => any, - gif?: string + gif?: string, + entryFunc?: () => any ) { - return new infoState(msg, arcs, entryFunc, gif); + return new infoState(msg, arcs, gif, entryFunc); } export interface CollectionFreeFormInfoStateProps { @@ -103,7 +103,7 @@ export class CollectionFreeFormInfoState extends ObservableReactComponent
{this.State?.[StateMessage]}
- state message gif + state message gif
this.props.close())} /> diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx index 8628ca3c3..cd76003c4 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx @@ -11,6 +11,7 @@ import { DocButtonState, DocumentLinksButton } from '../../nodes/DocumentLinksBu import { CollectionFreeFormInfoState, InfoState, StateEntryFunc, infoState } from './CollectionFreeFormInfoState'; import { CollectionFreeFormView } from './CollectionFreeFormView'; import './CollectionFreeFormView.scss'; +import { TopBar } from '../../topbar/TopBar'; export interface CollectionFreeFormInfoUIProps { Document: Doc; @@ -75,72 +76,98 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent numDocs(), () => { - docX = firstDoc()?.x; - docY = firstDoc()?.y; - return oneDoc; - }], - }, setBackground("blue")); // prettier-ignore + docCreated: [() => numDocs(), () => { + docX = firstDoc()?.x; + docY = firstDoc()?.y; + return oneDoc; + }], + }); // prettier-ignore const oneDoc = InfoState('Hello world! You can drag and drop to move your document around.', { - // docCreated: [() => numDocs() > 1, () => multipleDocs], - docDeleted: [() => numDocs() < 1, () => start], - docMoved: [() => (docX && docX != docNewX()) || (docY && docY != docNewY()), () => { - docX = firstDoc()?.x; - docY = firstDoc()?.y; - return movedDoc1; - }], - }, setBackground("red")); // prettier-ignore + // docCreated: [() => numDocs() > 1, () => multipleDocs], + docDeleted: [() => numDocs() < 1, () => start], + docMoved: [() => (docX && docX != docNewX()) || (docY && docY != docNewY()), () => { + docX = firstDoc()?.x; + docY = firstDoc()?.y; + return movedDoc1; + }], + }); // prettier-ignore - const movedDoc1 = InfoState('Great moves. Try creating a second document.', { + const movedDoc1 = InfoState( + 'Great moves. Try creating a second document. You can see the list of supported document types by typing \":\".', + { docCreated: [() => numDocs() == 2, () => multipleDocs], docDeleted: [() => numDocs() < 1, () => start], docMoved: [() => (docX && docX != docNewX()) || (docY && docY != docNewY()), () => { - docX = firstDoc()?.x; - docY = firstDoc()?.y; - return movedDoc2; - }], - }, setBackground("yellow")); // prettier-ignore + docX = firstDoc()?.x; + docY = firstDoc()?.y; + return movedDoc2; + }], + }, + 'dash-colon-menu.gif' + ); // prettier-ignore - const movedDoc2 = InfoState('Slick moves. Try creating a second document.', { + const movedDoc2 = InfoState( + 'Slick moves. Try creating a second document. You can see the list of supported document types by typing \":\".', + { docCreated: [() => numDocs() == 2, () => multipleDocs], docDeleted: [() => numDocs() < 1, () => start], docMoved: [() => (docX && docX != docNewX()) || (docY && docY != docNewY()), () => { - docX = firstDoc()?.x; - docY = firstDoc()?.y; - return movedDoc3; - }], - }, setBackground("pink")); // prettier-ignore + docX = firstDoc()?.x; + docY = firstDoc()?.y; + return movedDoc3; + }], + }, + 'dash-colon-menu.gif' + ); // prettier-ignore - const movedDoc3 = InfoState('Groovy moves. Try creating a second document.', { + const movedDoc3 = InfoState( + 'Groovy moves. Try creating a second document. You can see the list of supported document types by typing \":\".', + { docCreated: [() => numDocs() == 2, () => multipleDocs], docDeleted: [() => numDocs() < 1, () => start], docMoved: [() => (docX && docX != docNewX()) || (docY && docY != docNewY()), () => { - docX = firstDoc()?.x; - docY = firstDoc()?.y; - return movedDoc1; - }], - }, setBackground("green")); // prettier-ignore + docX = firstDoc()?.x; + docY = firstDoc()?.y; + return movedDoc1; + }], + }, + 'dash-colon-menu.gif' + ); // prettier-ignore - const multipleDocs = InfoState('Let\'s create a new link. Click the link icon on one of your documents.', { + const multipleDocs = InfoState( + 'Let\'s create a new link. Click the link icon on one of your documents.', + { linkStarted: [() => linkStart(), () => startedLink], docRemoved: [() => numDocs() < 2, () => oneDoc], - }, setBackground("purple")); // prettier-ignore + }, + 'dash-create-link-board.gif' + ); // prettier-ignore - const startedLink = InfoState('Now click the highlighted link icon on your other document.', { + const startedLink = InfoState( + 'Now click the highlighted link icon on your other document.', + { linkCreated: [() => numDocLinks(), () => madeLink], docRemoved: [() => numDocs() < 2, () => oneDoc], - }, setBackground("orange")); // prettier-ignore + }, + 'dash-create-link-board.gif' + ); // prettier-ignore - const madeLink = InfoState('You made your first link! You can view your links by selecting the blue dot.', { + const madeLink = InfoState( + 'You made your first link! You can view your links by selecting the blue dot.', + { linkCreated: [() => !numDocLinks(), () => multipleDocs], linkViewed: [() => linkMenuOpen(), () => { - alert(numDocLinks() + " cheer for " + numDocLinks() + " link!"); - return viewedLink; + alert(numDocLinks() + " cheer for " + numDocLinks() + " link!"); + return viewedLink; }], - }, setBackground("blue")); // prettier-ignore + }, + 'dash-following-link.gif' + ); // prettier-ignore - const viewedLink = InfoState('Great work. You are now ready to create your own hypermedia world.', { + const viewedLink = InfoState( + 'Great work. You are now ready to create your own hypermedia world. Click the blinking question mark to learn more.', + { linkDeleted: [() => !numDocLinks(), () => multipleDocs], docRemoved: [() => numDocs() < 2, () => oneDoc], docCreated: [() => numDocs() == 3, () => { @@ -148,7 +175,10 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent activeTool() === InkTool.Pen, () => penMode], - }, setBackground("black")); // prettier-ignore + }, + 'documentation.png', + + ); // prettier-ignore const presentDocs = InfoState( 'Another document! You could make a presentation. Click the pin icon in the top left corner.', @@ -162,7 +192,6 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent numDocs() < 3, () => viewedLink], }, - setBackground('black'), '/assets/dash-pin-with-view.gif' ); @@ -244,7 +273,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent numDocs() == 1, () => oneDoc], - }, setBackground("white")); // prettier-ignore + }); // prettier-ignore return start; }; diff --git a/src/server/public/assets/dash-colon-menu.gif b/src/server/public/assets/dash-colon-menu.gif new file mode 100644 index 000000000..b5512afb1 Binary files /dev/null and b/src/server/public/assets/dash-colon-menu.gif differ diff --git a/src/server/public/assets/dash-create-link-board.gif b/src/server/public/assets/dash-create-link-board.gif new file mode 100644 index 000000000..354188fd9 Binary files /dev/null and b/src/server/public/assets/dash-create-link-board.gif differ diff --git a/src/server/public/assets/dash-following-link.gif b/src/server/public/assets/dash-following-link.gif new file mode 100644 index 000000000..9e3e6df82 Binary files /dev/null and b/src/server/public/assets/dash-following-link.gif differ -- cgit v1.2.3-70-g09d2 From 3179048be75fb7662fc472249798b2d103dc5544 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 1 Mar 2024 08:22:30 -0500 Subject: added function to make documentation icon flip around. --- src/client/views/topbar/TopBar.tsx | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx index 0952dda20..230a85d32 100644 --- a/src/client/views/topbar/TopBar.tsx +++ b/src/client/views/topbar/TopBar.tsx @@ -1,6 +1,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Button, IconButton, isDark, Size, Type } from 'browndash-components'; -import { action, computed, observable, reaction } from 'mobx'; +import { action, computed, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { FaBug } from 'react-icons/fa'; @@ -26,13 +26,23 @@ import { DocumentViewInternal, returnEmptyDocViewList } from '../nodes/DocumentV import { DefaultStyleProvider } from '../StyleProvider'; import './TopBar.scss'; import { dropActionType } from '../../util/DragManager'; +import { Flip } from 'react-awesome-reveal'; +import { ObservableReactComponent } from '../ObservableReactComponent'; /** * ABOUT: This is the topbar in Dash, which included the current Dashboard as well as access to information on the user * and settings and help buttons. Future scope for this bar is to include the collaborators that are on the same Dashboard. */ @observer -export class TopBar extends React.Component { +export class TopBar extends ObservableReactComponent<{}> { + static Instance: TopBar; + @observable private _flipDocumentation = 0; + constructor(props: any) { + super(props); + makeObservable(this); + TopBar.Instance = this; + } + navigateToHome = () => { (CollectionDockingView.Instance?.CaptureThumbnail() ?? new Promise(res => res())).then(() => { Doc.ActivePage = 'home'; @@ -162,7 +172,6 @@ export class TopBar extends React.Component {
) : null; } - /** * Returns the right hand side of the topbar. * This part of the topbar includes information about the current user, @@ -184,6 +193,9 @@ export class TopBar extends React.Component { /> ) : null} } /> + + window.open('https://brown-dash.github.io/Dash-Documentation/', '_blank')} icon={} /> + window.open('https://brown-dash.github.io/Dash-Documentation/', '_blank')} icon={} /> } /> (this._flipDocumentation = this._flipDocumentation + 1)); + render() { return ( //TODO:glr Add support for light / dark mode -- cgit v1.2.3-70-g09d2 From 1a4a5d56a5a9962d75b625bf784420d9f8aedb4e Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 1 Mar 2024 08:31:25 -0500 Subject: added flipping of documentation icon --- .../views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx index cd76003c4..a81195c95 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx @@ -42,6 +42,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent Date: Fri, 1 Mar 2024 08:41:32 -0500 Subject: from last --- src/client/views/topbar/TopBar.tsx | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx index 230a85d32..addad2bbc 100644 --- a/src/client/views/topbar/TopBar.tsx +++ b/src/client/views/topbar/TopBar.tsx @@ -196,7 +196,6 @@ export class TopBar extends ObservableReactComponent<{}> { window.open('https://brown-dash.github.io/Dash-Documentation/', '_blank')} icon={} /> - window.open('https://brown-dash.github.io/Dash-Documentation/', '_blank')} icon={} /> } /> Date: Fri, 1 Mar 2024 08:41:58 -0500 Subject: from last --- src/client/views/topbar/TopBar.tsx | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx index 230a85d32..addad2bbc 100644 --- a/src/client/views/topbar/TopBar.tsx +++ b/src/client/views/topbar/TopBar.tsx @@ -196,7 +196,6 @@ export class TopBar extends ObservableReactComponent<{}> { window.open('https://brown-dash.github.io/Dash-Documentation/', '_blank')} icon={} /> - window.open('https://brown-dash.github.io/Dash-Documentation/', '_blank')} icon={} /> } /> Date: Mon, 4 Mar 2024 12:55:05 -0500 Subject: changes to restore template menu and fix freeform templates to always show contents. Fix for alt-dropping an image to replace another image. --- src/client/views/DocumentButtonBar.tsx | 48 +++++++++------------- src/client/views/DocumentDecorations.tsx | 4 +- src/client/views/InkingStroke.tsx | 2 +- src/client/views/TemplateMenu.tsx | 2 +- src/client/views/collections/TabDocView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 9 ++-- src/client/views/nodes/ImageBox.tsx | 1 + 7 files changed, 30 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 8a4b42ae0..d65e0b406 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -4,12 +4,12 @@ import { Tooltip } from '@mui/material'; import { action, computed, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { emptyFunction, returnFalse, setupMoveUpEvents, simulateMouseClick } from '../../Utils'; +import { emptyFunction, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick } from '../../Utils'; import { Doc } from '../../fields/Doc'; import { Cast, DocCast } from '../../fields/Types'; import { DocUtils } from '../documents/Documents'; import { CalendarManager } from '../util/CalendarManager'; -import { DragManager } from '../util/DragManager'; +import { DragManager, dropActionType } from '../util/DragManager'; import { IsFollowLinkScript } from '../util/LinkFollower'; import { SelectionManager } from '../util/SelectionManager'; import { SharingManager } from '../util/SharingManager'; @@ -24,6 +24,9 @@ import { DocumentView, DocumentViewInternal, OpenWhere } from './nodes/DocumentV import { DashFieldView } from './nodes/formattedText/DashFieldView'; import { PinProps } from './nodes/trails'; import { faCalendarDays } from '@fortawesome/free-solid-svg-icons'; +import { Popup } from 'browndash-components'; +import { TemplateMenu } from './TemplateMenu'; +import { FaEdit } from 'react-icons/fa'; @observer export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (DocumentView | undefined)[]; stack?: any }> { @@ -306,7 +309,7 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => ( const dragDocView = this.view0!; const dragData = new DragManager.DocumentDragData([dragDocView.Document]); const [left, top] = dragDocView.screenToContentsTransform().inverse().transformPoint(0, 0); - dragData.defaultDropAction = 'embed'; + dragData.defaultDropAction = dropActionType.embed; dragData.canEmbed = true; DragManager.StartDocumentDrag([dragDocView.ContentDiv!], dragData, left, top, { hideSource: false }); return true; @@ -316,35 +319,24 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => ( _ref = React.createRef(); @observable _tooltipOpen: boolean = false; + @computed get templateMenu() { + return ( +
+ v) + .map(v => v as DocumentView)} + /> +
+ ); + } @computed get templateButton() { - const view0 = this.view0; - const views = this._props.views(); - return !view0 ? null : ( + return !this.view0 ? null : ( Tap to Customize Layout. Drag an embedding
} open={this._tooltipOpen} onClose={action(() => (this._tooltipOpen = false))} placement="bottom">
!this._ref.current?.getBoundingClientRect().width && (this._tooltipOpen = true))}> - { - /* (this._embedDown = true))} - onClose={action(() => (this._embedDown = false))} - content={ - !this._embedDown ? null : ( -
- {' '} - v).map(v => v as DocumentView)} /> -
- ) - }> -
- -
-
*/ - -
- -
- } + } popup={this.templateMenu} popupContainsPt={returnTrue} />
); diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index e9c4d9cc5..9d53c58c0 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -77,7 +77,7 @@ export class DocumentDecorations extends ObservableReactComponent center.x+x || this.Bounds.r < center.x+x || this.Bounds.y > center.y+y || this.Bounds.b < center.y+y ))); })); // prettier-ignore @@ -514,7 +514,7 @@ export class DocumentDecorations extends ObservableReactComponent (doc.isGroup ? DocListCast(doc.data).some(this.hasFixedAspect) : !BoolCast(doc.layout_nativeDimEditable)); + hasFixedAspect = (doc: Doc): boolean => (doc.isGroup ? DocListCast(doc.data).some(this.hasFixedAspect) : !BoolCast(doc._layout_nativeDimEditable)); // // resize a single DocumentView about the specified reference point, possibly setting/updating the native dimensions of the Doc diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 92644d3c5..122e5c4c3 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -438,7 +438,7 @@ export class InkingStroke extends ViewBoxBaseComponent() impleme { componentDidMount() { !this._addedKeys && (this._addedKeys = new ObservableSet()); [...Array.from(Object.keys(this.props.docViews[0].Document[DocData])), ...Array.from(Object.keys(this.props.docViews[0].Document))] - .filter(key => key.startsWith('layout_')) + .filter(key => key.startsWith('layout_') && key !== 'layout_fieldKey') .map(key => runInAction(() => this._addedKeys.add(key.replace('layout_', '')))); } diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index b52f2e7b6..699ec3b95 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -638,7 +638,7 @@ export class TabMinimapView extends ObservableReactComponent - } color={SettingsManager.userVariantColor} type={Type.TERT} onPointerDown={e => e.stopPropagation()} placement={'top-end'} popup={this.popup} /> + } color={SettingsManager.userVariantColor} type={Type.TERT} onPointerDown={e => e.stopPropagation()} placement="top-end" popup={this.popup} />
); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index e48656f5e..877569ab3 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -17,7 +17,7 @@ import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../ import { ImageField } from '../../../../fields/URLField'; import { TraceMobx } from '../../../../fields/util'; import { GestureUtils } from '../../../../pen-gestures/GestureUtils'; -import { aggregateBounds, DashColor, emptyFunction, intersectRect, lightOrDark, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, Utils } from '../../../../Utils'; +import { aggregateBounds, DashColor, emptyFunction, intersectRect, lightOrDark, numberValue, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, Utils } from '../../../../Utils'; import { CognitiveServices } from '../../../cognitive_services/CognitiveServices'; import { Docs, DocUtils } from '../../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; @@ -760,7 +760,6 @@ export class CollectionFreeFormView extends CollectionSubView { if (this.tryDragCluster(e, this._hitCluster)) { e.stopPropagation(); // we're moving a cluster, so stop propagation and return true to end panning and let the document drag take over @@ -1344,7 +1343,7 @@ export class CollectionFreeFormView extends CollectionSubView { if (!LightboxView.LightboxDoc || LightboxView.Contains(this.DocumentView?.())) { const layout_unrendered = this.childDocs.filter(doc => !this._renderCutoffData.get(doc[Id])); - const loadIncrement = 5; + const loadIncrement = this.Document.isTemplateDoc ? Number.MAX_VALUE : 5; for (var i = 0; i < Math.min(layout_unrendered.length, loadIncrement); i++) { this._renderCutoffData.set(layout_unrendered[i][Id] + '', true); } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 923aead64..251235b93 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -141,6 +141,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent() impl const targetField = Doc.LayoutFieldKey(layoutDoc); const targetDoc = layoutDoc[DocData]; if (targetDoc[targetField] instanceof ImageField) { + added = true; this.dataDoc[this.fieldKey] = ObjectField.MakeCopy(targetDoc[targetField] as ImageField); Doc.SetNativeWidth(this.dataDoc, Doc.NativeWidth(targetDoc), this.fieldKey); Doc.SetNativeHeight(this.dataDoc, Doc.NativeHeight(targetDoc), this.fieldKey); -- cgit v1.2.3-70-g09d2 From 2e99ef0512b8f1b5c089637643ff6addf5afd943 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 4 Mar 2024 16:07:52 -0500 Subject: cleaned up a number of things related to autoHeight and stacking/masonry/notetaking views --- src/Utils.ts | 7 ++ src/client/views/ContextMenu.tsx | 5 +- src/client/views/DocumentDecorations.tsx | 10 +- src/client/views/PropertiesButtons.tsx | 3 +- .../views/collections/CollectionDockingView.tsx | 6 +- .../collections/CollectionMasonryViewFieldRow.tsx | 15 ++- .../collections/CollectionNoteTakingView.scss | 1 + .../views/collections/CollectionNoteTakingView.tsx | 107 +++++++++------------ .../collections/CollectionNoteTakingViewColumn.tsx | 22 ++--- .../views/collections/CollectionStackingView.tsx | 73 ++++---------- .../CollectionStackingViewFieldColumn.tsx | 23 +++-- .../views/collections/CollectionTreeView.tsx | 8 +- src/client/views/nodes/DocumentView.tsx | 7 +- src/client/views/nodes/EquationBox.tsx | 5 +- src/client/views/nodes/WebBox.tsx | 6 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 4 +- 16 files changed, 136 insertions(+), 166 deletions(-) (limited to 'src') diff --git a/src/Utils.ts b/src/Utils.ts index e8bd35ac4..38325a463 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -902,6 +902,13 @@ export function setupMoveUpEvents( document.addEventListener('click', _clickEvent, true); } +export function DivHeight(ele: HTMLElement): number { + return Number(getComputedStyle(ele).height.replace('px', '')); +} +export function DivWidth(ele: HTMLElement): number { + return Number(getComputedStyle(ele).width.replace('px', '')); +} + export function dateRangeStrToDates(dateStr: string) { // dateStr in yyyy-mm-dd format const dateRangeParts = dateStr.split('|'); // splits into from and to date diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 8c3c9df2e..8f4e43978 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -7,6 +7,7 @@ import { SettingsManager } from '../util/SettingsManager'; import './ContextMenu.scss'; import { ContextMenuItem, ContextMenuProps, OriginalMenuProps } from './ContextMenuItem'; import { ObservableReactComponent } from './ObservableReactComponent'; +import { DivHeight, DivWidth } from '../../Utils'; @observer export class ContextMenu extends ObservableReactComponent<{}> { @@ -214,8 +215,8 @@ export class ContextMenu extends ObservableReactComponent<{}> { className="contextMenu-cont" ref={action((r: any) => { if (r) { - this._width = Number(getComputedStyle(r).width.replace('px', '')); - this._height = Number(getComputedStyle(r).height.replace('px', '')); + this._width = DivWidth(r); + this._height = DivHeight(r); } })} style={{ diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 9d53c58c0..87ee962a0 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -562,7 +562,13 @@ export class DocumentDecorations extends ObservableReactComponent NumCast(doc._height) < 20 && (doc._layout_autoHeight = true)); + SelectionManager.Views.forEach(view => NumCast(view.Document._height) < 20 && (view.layoutDoc._layout_autoHeight = true)); //need to change points for resize, or else rotation/control points will fail. this._inkDragDocs .map(oldbds => ({ oldbds, inkPts: Cast(oldbds.doc.data, InkField)?.inkData || [] })) diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index cb38ab602..3cb835e39 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -486,8 +486,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { const isImage = layoutField instanceof ImageField; const isMap = this.selectedDoc?.type === DocumentType.MAP; const isCollection = this.selectedDoc?.type === DocumentType.COL; - //TODO: will likely need to create separate note-taking view type here - const isStacking = this.selectedDoc?._type_collection === CollectionViewType.Stacking || this.selectedDoc?._type_collection === CollectionViewType.NoteTaking; + const isStacking = [CollectionViewType.Stacking, CollectionViewType.Masonry, CollectionViewType.NoteTaking].includes(this.selectedDoc?._type_collection as any); const isFreeForm = this.selectedDoc?._type_collection === CollectionViewType.Freeform; const isTree = this.selectedDoc?._type_collection === CollectionViewType.Tree; const isTabView = this.selectedTabView; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index d9d6a5eb5..8f1633122 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -11,7 +11,7 @@ import { List } from '../../../fields/List'; import { ImageCast, NumCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { GetEffectiveAcl, inheritParentAcls } from '../../../fields/util'; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, incrementTitleCopy } from '../../../Utils'; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, DivHeight, DivWidth, emptyFunction, incrementTitleCopy } from '../../../Utils'; import { DocServer } from '../../DocServer'; import { Docs } from '../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; @@ -432,8 +432,8 @@ export class CollectionDockingView extends CollectionSubView() { public CaptureThumbnail() { const content = this.DocumentView?.()?.ContentDiv; if (content) { - const _width = Number(getComputedStyle(content).width.replace('px', '')); - const _height = Number(getComputedStyle(content).height.replace('px', '')); + const _width = DivWidth(content); + const _height = DivHeight(content); return CollectionFreeFormView.UpdateIcon(this.layoutDoc[Id] + '-icon' + new Date().getTime(), content, _width, _height, _width, _height, 0, 1, true, this.layoutDoc[Id] + '-icon', (iconFile, _nativeWidth, _nativeHeight) => { const proto = this.dataDoc; // Cast(img.proto, Doc, null)!; proto['thumb_nativeWidth'] = _width; diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index 41c5d5b42..763d2e3a6 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -33,8 +33,7 @@ interface CMVFieldRowProps { createDropTarget: (ele: HTMLDivElement) => void; screenToLocalTransform: () => Transform; setDocHeight: (key: string, thisHeight: number) => void; - observeHeight: (myref: any) => void; - unobserveHeight: (myref: any) => void; + refList: any[]; showHandle: boolean; } @@ -68,20 +67,20 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent { this._dropDisposer?.(); - if (ele) { - this._ele = ele; - this._props.observeHeight(ele); - this._dropDisposer = DragManager.MakeDropTarget(ele, this.rowDrop.bind(this), this._props.Document); - } + if (ele) this._dropDisposer = DragManager.MakeDropTarget(ele, this.rowDrop.bind(this), this._props.Document); + else if (this._ele) this.props.refList.splice(this.props.refList.indexOf(this._ele), 1); + this._ele = ele; }; @action componentDidMount() { this.heading = this._props.headingObject?.heading || ''; this.color = this._props.headingObject?.color || '#f1efeb'; this.collapsed = this._props.headingObject?.collapsed || false; + this._ele && this.props.refList.push(this._ele); } componentWillUnmount() { - this._props.unobserveHeight(this._ele); + this._ele && this.props.refList.splice(this.props.refList.indexOf(this._ele), 1); + this._ele = null; } getTrueHeight = () => { diff --git a/src/client/views/collections/CollectionNoteTakingView.scss b/src/client/views/collections/CollectionNoteTakingView.scss index 91a82d40f..4c2dcf9ab 100644 --- a/src/client/views/collections/CollectionNoteTakingView.scss +++ b/src/client/views/collections/CollectionNoteTakingView.scss @@ -98,6 +98,7 @@ overflow: auto; display: flex; flex-direction: column; + height: max-content; } .collectionSchemaView-previewDoc { diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index b8133806f..6318620e0 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -1,4 +1,4 @@ -import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, observe, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, Field, Opt } from '../../../fields/Doc'; @@ -9,7 +9,7 @@ import { listSpec } from '../../../fields/Schema'; import { SchemaHeaderField } from '../../../fields/SchemaHeaderField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, returnFalse, returnZero, smoothScroll, Utils } from '../../../Utils'; +import { DivHeight, emptyFunction, returnFalse, returnZero, smoothScroll, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DragManager, dropActionType } from '../../util/DragManager'; import { SnappingManager } from '../../util/SnappingManager'; @@ -45,6 +45,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { public DividerWidth = 16; @observable docsDraggedRowCol: number[] = []; @observable _scroll = 0; + @observable _refList: any[] = []; constructor(props: any) { super(props); @@ -157,8 +158,16 @@ export class CollectionNoteTakingView extends CollectionSubView() { document.addEventListener('pointerup', this.removeDocDragHighlight, true); this._disposers.layout_autoHeight = reaction( () => this.layoutDoc._layout_autoHeight, - layout_autoHeight => - layout_autoHeight && this._props.setHeight?.(Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), this.headerMargin + Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', '')))))) + layout_autoHeight => layout_autoHeight && this._props.setHeight?.(this.headerMargin + Math.max(...this._refList.map(DivHeight))) + ); + + this._disposers.refList = reaction( + () => ({ refList: this._refList.slice(), autoHeight: this.layoutDoc._layout_autoHeight && !LightboxView.Contains(this.DocumentView?.()) }), + ({ refList, autoHeight }) => { + if (autoHeight) refList.forEach(r => this.observer.observe(r)); + else this.observer.disconnect(); + }, + { fireImmediately: true } ); } @@ -345,7 +354,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { // get the index for where you need to insert the doc you are currently dragging const clientY = this.ScreenToLocalBoxXf().transformPoint(ex, ey)[1]; let dropInd = -1; - let pos0 = (this.refList.lastElement() as HTMLDivElement).children[0].getBoundingClientRect().height + this.yMargin * 2; + let pos0 = (this._refList.lastElement() as HTMLDivElement).children[0].getBoundingClientRect().height + this.yMargin * 2; colDocs.forEach((doc, i) => { let pos1 = this.getDocHeight(doc) + 2 * this.gridGap; pos1 += pos0; @@ -424,7 +433,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { if (super.onInternalDrop(e, de)) { // filter out the currently dragged docs from the child docs, since we will insert them later const rowCol = this.docsDraggedRowCol; - const droppedDocs = this.childDocs.slice().filter((d: Doc, ind: number) => ind >= this.childDocs.length); // if the drop operation adds something to the end of the list, then use that as the new document (may be different than what was dropped e.g., in the case of a button which is dropped but which creates say, a note). + const droppedDocs = this.childDocs.filter((d: Doc, ind: number) => ind >= this.childDocs.length); // if the drop operation adds something to the end of the list, then use that as the new document (may be different than what was dropped e.g., in the case of a button which is dropped but which creates say, a note). const newDocs = droppedDocs.length ? droppedDocs : de.complete.docDragData.droppedDocuments; const docs = this.childDocList; if (docs && newDocs.length) { @@ -489,65 +498,45 @@ export class CollectionNoteTakingView extends CollectionSubView() { headings = () => Array.from(this.Sections); - refList: any[] = []; - editableViewProps = () => ({ GetValue: () => '', SetValue: this.addGroup, contents: '+ New Column', }); + refList = () => this._refList; + // sectionNoteTaking returns a CollectionNoteTakingViewColumn (which is an individual column) - sectionNoteTaking = (heading: SchemaHeaderField | undefined, docList: Doc[]) => { - const type = 'number'; - return ( - this.refList.splice(this.refList.indexOf(ref), 1)} - observeHeight={ref => { - if (ref) { - this.refList.push(ref); - this.observer = new _global.ResizeObserver( - action((entries: any) => { - if (this.layoutDoc._layout_autoHeight && ref && this.refList.length && !SnappingManager.IsDragging) { - const height = this.headerMargin + Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', ''))))); - if (!LightboxView.Contains(this.DocumentView?.())) { - this._props.setHeight?.(height); - } - } - }) - ); - this.observer.observe(ref); - } - }} - PanelWidth={this._props.PanelWidth} - select={this._props.select} - addDocument={this.addDocument} - chromeHidden={this.chromeHidden} - colHeaderData={this.colHeaderData} - Document={this.Document} - TemplateDataDocument={this._props.TemplateDataDocument} - resizeColumns={this.resizeColumns} - renderChildren={this.children} - numGroupColumns={this.numGroupColumns} - gridGap={this.gridGap} - pivotField={this.notetakingCategoryField} - fieldKey={this.fieldKey} - dividerWidth={this.DividerWidth} - maxColWidth={this.maxColWidth} - availableWidth={this.availableWidth} - headings={this.headings} - heading={heading?.heading ?? 'unset'} - headingObject={heading} - docList={docList} - yMargin={this.yMargin} - type={type} - createDropTarget={this.createDashEventsTarget} - screenToLocalTransform={this.ScreenToLocalBoxXf} - editableViewProps={this.editableViewProps} - /> - ); - }; + sectionNoteTaking = (heading: SchemaHeaderField | undefined, docList: Doc[]) => ( + + ); // addGroup is called when adding a new columnHeader, adding a SchemaHeaderField to our list of // columnHeaders and resizing the existing columns to make room for our new one. @@ -619,7 +608,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { return this.isContentActive() === false ? 'none' : undefined; } - observer: any; + observer = new _global.ResizeObserver(() => this._props.setHeight?.(this.headerMargin + Math.max(...this._refList.map(DivHeight)))); render() { TraceMobx(); diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx index 38846c79d..db178d500 100644 --- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx +++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx @@ -36,15 +36,13 @@ interface CSVFieldColumnProps { yMargin: number; numGroupColumns: number; gridGap: number; - type: 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | undefined; headings: () => object[]; select: (ctrlPressed: boolean) => void; renderChildren: (docs: Doc[]) => JSX.Element[]; addDocument: (doc: Doc | Doc[]) => boolean; createDropTarget: (ele: HTMLDivElement) => void; screenToLocalTransform: () => Transform; - observeHeight: (myref: any) => void; - unobserveHeight: (myref: any) => void; + refList: any[]; editableViewProps: () => any; resizeColumns: (headers: SchemaHeaderField[]) => boolean; maxColWidth: number; @@ -78,15 +76,18 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent { this.dropDisposer?.(); - if (ele) { - this._ele = ele; - this._props.observeHeight(ele); - this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this), this._props.Document); - } + if (ele) this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this), this._props.Document); + else if (this._ele) this.props.refList.slice(this.props.refList.indexOf(this._ele), 1); + this._ele = ele; }; + componentDidMount(): void { + this._ele && this.props.refList.push(this._ele); + } + componentWillUnmount() { - this._props.unobserveHeight(this._ele); + this._ele && this.props.refList.splice(this._props.refList.indexOf(this._ele), 1); + this._ele = null; } @undoBatch @@ -289,11 +290,10 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent>() { + _disposers: { [key: string]: IReactionDisposer } = {}; _masonryGridRef: HTMLDivElement | null = null; // used in a column dragger, likely due for the masonry grid view. We want to use this _draggerRef = React.createRef(); - // Not sure what a pivot field is. Seems like we cause reaction in MobX get rid of it once we exit this view - _pivotFieldDisposer?: IReactionDisposer; - // Seems like we cause reaction in MobX get rid of our height once we exit this view - _layout_autoHeightDisposer?: IReactionDisposer; // keeping track of documents. Updated on internal and external drops. What's the difference? _docXfs: { height: () => number; width: () => number; stackedDocTransform: () => Transform }[] = []; // Doesn't look like this field is being used anywhere. Obsolete? _columnStart: number = 0; + + @observable _refList: any[] = []; // map of node headers to their heights. Used in Masonry @observable _heightMap = new Map(); // Assuming that this is the current css cursor style @@ -207,27 +205,27 @@ export class CollectionStackingView extends CollectionSubView this.pivotField, () => (this.dataDoc['_' + this.fieldKey + '_columnHeaders'] = new List()) ); - this._layout_autoHeightDisposer = reaction( + this._disposers.autoHeight = reaction( () => this.layoutDoc._layout_autoHeight, - layout_autoHeight => - layout_autoHeight && - this._props.setHeight?.( - Math.min( - NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), - this.headerMargin + (this.isStackingView ? Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', '')))) : this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace('px', '')), 0)) - ) - ) + layout_autoHeight => layout_autoHeight && this._props.setHeight?.(this.headerMargin + (this.isStackingView ? Math.max(...this._refList.map(DivHeight)) : this._refList.reduce((p, r) => p + DivHeight(r), 0))) + ); + this._disposers.refList = reaction( + () => ({ refList: this._refList.slice(), autoHeight: this.layoutDoc._layout_autoHeight && !LightboxView.Contains(this.DocumentView?.()) }), + ({ refList, autoHeight }) => { + this.observer.disconnect(); + if (autoHeight) refList.forEach(r => this.observer.observe(r)); + }, + { fireImmediately: true } ); } componentWillUnmount() { super.componentWillUnmount(); - this._pivotFieldDisposer?.(); - this._layout_autoHeightDisposer?.(); + Object.keys(this._disposers).forEach(key => this._disposers[key]()); } isAnyChildContentActive = () => this._props.isAnyChildContentActive(); @@ -523,7 +521,6 @@ export class CollectionStackingView extends CollectionSubView Array.from(this.Sections); - refList: any[] = []; // what a section looks like if we're in stacking view sectionStacking = (heading: SchemaHeaderField | undefined, docList: Doc[]) => { const key = this.pivotField; @@ -536,23 +533,7 @@ export class CollectionStackingView extends CollectionSubView this.refList.splice(this.refList.indexOf(ref), 1)} - observeHeight={ref => { - if (ref) { - this.refList.push(ref); - this.observer = new _global.ResizeObserver( - action((entries: any) => { - if (this.layoutDoc._layout_autoHeight && ref && this.refList.length && !SnappingManager.IsDragging) { - const height = this.headerMargin + Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', ''))))); - if (!LightboxView.Contains(this.DocumentView?.())) { - this._props.setHeight?.(height); - } - } - }) - ); - this.observer.observe(ref); - } - }} + refList={this._refList} addDocument={this.addDocument} chromeHidden={this.chromeHidden} colHeaderData={this.colHeaderData} @@ -591,21 +572,7 @@ export class CollectionStackingView extends CollectionSubView this.refList.splice(this.refList.indexOf(ref), 1)} - observeHeight={ref => { - if (ref) { - this.refList.push(ref); - this.observer = new _global.ResizeObserver( - action((entries: any) => { - if (this.layoutDoc._layout_autoHeight && ref && this.refList.length && !SnappingManager.IsDragging) { - const height = this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace('px', '')), 0); - this._props.setHeight?.(2 * this.headerMargin + height); // bcz: added 2x for header to fix problem with scrollbars appearing in Tools panel - } - }) - ); - this.observer.observe(ref); - } - }} + refList={this._refList} key={heading ? heading.heading : ''} rows={rows} headings={this.headings} @@ -709,7 +676,9 @@ export class CollectionStackingView extends CollectionSubView this._props.setHeight?.(this.headerMargin + (this.isStackingView ? Math.max(...this._refList.map(DivHeight)) : this._refList.reduce((p, r) => p + DivHeight(r), 0)))); + render() { TraceMobx(); const editableViewProps = { diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index c455f20d8..6a3cb759e 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -9,7 +9,7 @@ import { ScriptField } from '../../../fields/ScriptField'; import { BoolCast, NumCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, returnEmptyString, setupMoveUpEvents } from '../../../Utils'; +import { DivHeight, DivWidth, emptyFunction, returnEmptyString, setupMoveUpEvents } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; import { DragManager } from '../../util/DragManager'; @@ -44,8 +44,7 @@ interface CSVFieldColumnProps { addDocument: (doc: Doc | Doc[]) => boolean; createDropTarget: (ele: HTMLDivElement) => void; screenToLocalTransform: () => Transform; - observeHeight: (myref: any) => void; - unobserveHeight: (myref: any) => void; + refList: any[]; } @observer @@ -53,7 +52,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent< private dropDisposer?: DragManager.DragDropDisposer; private _disposers: { [name: string]: IReactionDisposer } = {}; private _headerRef: React.RefObject = React.createRef(); - @observable private _background = 'inherit'; + @observable _background = 'inherit'; @observable _paletteOn = false; @observable _heading = ''; @observable _color = ''; @@ -71,15 +70,14 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent< // is that the only way to have drop targets? createColumnDropRef = (ele: HTMLDivElement | null) => { this.dropDisposer?.(); - if (ele) { - this._ele = ele; - this._props.observeHeight(ele); - this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this), this._props.Document); - } + if (ele) this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this), this._props.Document); + else if (this._ele) this.props.refList.splice(this.props.refList.indexOf(this._ele), 1); + this._ele = ele; }; @action componentDidMount() { + this._ele && this.props.refList.push(this._ele); this._disposers.collapser = reaction( () => this._props.headingObject?.collapsed, collapsed => (this.collapsed = collapsed !== undefined ? BoolCast(collapsed) : false), @@ -88,7 +86,8 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent< } componentWillUnmount() { this._disposers.collapser?.(); - this._props.unobserveHeight(this._ele); + this._ele && this.props.refList.splice(this.props.refList.indexOf(this._ele), 1); + this._ele = null; } //TODO: what is scripting? I found it in SetInPlace def but don't know what that is @@ -217,8 +216,8 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent< const layoutItems: ContextMenuProps[] = []; const docItems: ContextMenuProps[] = []; const dataDoc = this._props.TemplateDataDocument || this._props.Document; - const width = this._ele ? Number(getComputedStyle(this._ele).width.replace('px', '')) : 0; - const height = this._ele ? Number(getComputedStyle(this._ele).height.replace('px', '')) : 0; + const width = this._ele ? DivWidth(this._ele) : 0; + const height = this._ele ? DivHeight(this._ele) : 0; DocUtils.addDocumentCreatorMenuItems( doc => { FormattedTextBox.SetSelectOnLoad(doc); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 4d60cbefc..3b37bdcfa 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -8,7 +8,7 @@ import { listSpec } from '../../../fields/Schema'; import { ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, returnAll, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnOne, returnTrue, returnZero, Utils } from '../../../Utils'; +import { DivHeight, emptyFunction, returnAll, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnOne, returnTrue, returnZero, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType } from '../../util/DragManager'; @@ -113,8 +113,8 @@ export class CollectionTreeView extends CollectionSubView { if (!this._isDisposing) { - const titleHeight = !this._titleRef ? this.marginTop() : Number(getComputedStyle(this._titleRef).height.replace('px', '')); - const bodyHeight = Array.from(this.refList).reduce((p, r) => p + Number(getComputedStyle(r).height.replace('px', '')), this.marginBot()) + 6; + const titleHeight = !this._titleRef ? this.marginTop() : DivHeight(this._titleRef); + const bodyHeight = Array.from(this.refList).reduce((p, r) => p + DivHeight(r), this.marginBot()) + 6; this.layoutDoc._layout_autoHeightMargins = bodyHeight; !this._props.dontRegisterView && this._props.setHeight?.(bodyHeight + titleHeight); } @@ -420,7 +420,7 @@ export class CollectionTreeView extends CollectionSubView {!this.buttonMenu && !this.noviceExplainer ? null : ( -
r && (this._headerHeight = Number(getComputedStyle(r).height.replace(/px/, ''))))}> +
r && (this._headerHeight = DivHeight(r)))}> {this.buttonMenu} {this.noviceExplainer}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index b0e8cf6ff..ee058c085 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,11 +1,10 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; -import { Dropdown, DropdownType, Type } from 'browndash-components'; import { Howl } from 'howler'; import { IReactionDisposer, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Bounce, Fade, Flip, JackInTheBox, Roll, Rotate, Zoom } from 'react-awesome-reveal'; -import { Utils, emptyFunction, isTargetChildOf as isParentOf, lightOrDark, returnEmptyString, returnFalse, returnTrue, returnVal, simulateMouseClick } from '../../../Utils'; +import { DivWidth, Utils, emptyFunction, isTargetChildOf as isParentOf, lightOrDark, returnEmptyString, returnFalse, returnTrue, returnVal, simulateMouseClick } from '../../../Utils'; import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../fields/Doc'; import { AclPrivate, Animation, AudioPlay, DocData, DocViews } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; @@ -703,7 +702,7 @@ export class DocumentViewInternal extends DocComponent this._props.PanelHeight() - this.headerMargin; screenToLocalContent = () => this._props.ScreenToLocalTransform().translate(0, -this.headerMargin); onClickFunc = this.disableClickScriptFunc ? undefined : () => this.onClickHandler; - setHeight = (height: number) => !this._props.suppressSetHeight && (this.layoutDoc._height = height); + setHeight = (height: number) => !this._props.suppressSetHeight && (this.layoutDoc._height = Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), height)); setContentView = action((view: ViewBoxInterface) => (this._componentView = view)); isContentActive = (): boolean | undefined => this._isContentActive; childFilters = () => [...this._props.childFilters(), ...StrListCast(this.layoutDoc.childFilters)]; @@ -788,7 +787,7 @@ export class DocumentViewInternal extends DocComponent { return (
r && (this._titleDropDownInnerWidth = Number(getComputedStyle(r).width.replace('px', ''))))} + ref={action((r: any) => r && (this._titleDropDownInnerWidth = DivWidth(r)))} onPointerDown={action(e => (this._changingTitleField = true))} style={{ width: 'max-content', background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor, transformOrigin: 'left', transform: `scale(${this.titleHeight / 30 /* height of Dropdown */})` }}> () { @@ -57,8 +58,8 @@ export class EquationBox extends ViewBoxBaseComponent() { @action keyPressed = (e: KeyboardEvent) => { - const _height = Number(getComputedStyle(this._ref.current!.element.current).height.replace('px', '')); - const _width = Number(getComputedStyle(this._ref.current!.element.current).width.replace('px', '')); + const _height = DivHeight(this._ref.current!.element.current); + const _width = DivWidth(this._ref.current!.element.current); if (e.key === 'Enter') { const nextEq = Docs.Create.EquationDocument(e.shiftKey ? StrCast(this.dataDoc.text) : 'x', { title: '# math', diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 2c5398e40..c9340edc0 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -14,7 +14,7 @@ import { listSpec } from '../../../fields/Schema'; import { Cast, NumCast, StrCast, WebCast } from '../../../fields/Types'; import { ImageField, WebField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, getWordAtPoint, lightOrDark, returnFalse, returnOne, returnZero, setupMoveUpEvents, smoothScroll, stringHash, Utils } from '../../../Utils'; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, DivHeight, emptyFunction, getWordAtPoint, lightOrDark, returnFalse, returnOne, returnZero, setupMoveUpEvents, smoothScroll, stringHash, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; @@ -83,7 +83,7 @@ export class WebBox extends ViewBoxAnnotatableComponent() implem return this.webField?.toString() || ''; } @computed get _urlHash() { - return ""+ (stringHash(this._url)??''); + return '' + (stringHash(this._url) ?? ''); } @computed get scrollHeight() { return Math.max(NumCast(this.layoutDoc._height), this._scrollHeight); @@ -782,7 +782,7 @@ export class WebBox extends ViewBoxAnnotatableComponent() implem className="webBox-htmlSpan" ref={action((r: any) => { if (r) { - this._scrollHeight = Number(getComputedStyle(r).height.replace('px', '')); + this._scrollHeight = DivHeight(r); this.lighttext = Array.from(r.children).some((c: any) => c instanceof HTMLElement && lightOrDark(getComputedStyle(c).color) !== Colors.WHITE); } })} diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 56008de8e..266a2442f 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -23,7 +23,7 @@ import { RichTextField } from '../../../../fields/RichTextField'; import { ComputedField } from '../../../../fields/ScriptField'; import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util'; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils'; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, DivWidth, emptyFunction, numberRange, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils'; import { gptAPICall, GPTCallType } from '../../../apis/gpt/GPT'; import { DocServer } from '../../../DocServer'; import { Docs, DocUtils } from '../../../documents/Documents'; @@ -758,7 +758,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { const defaultSidebar = 250; - const prevWidth = 1 - this.sidebarWidth() / Number(getComputedStyle(this._ref.current!).width.replace('px', '')); + const prevWidth = 1 - this.sidebarWidth() / DivWidth(this._ref.current!); if (preview) this._showSidebar = true; else { this.layoutDoc[this.SidebarKey + '_freeform_scale_max'] = 1; -- cgit v1.2.3-70-g09d2 From 26cd21b5148d07e0be39cd6997723b34a70ebab6 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 5 Mar 2024 12:16:53 -0500 Subject: added mermaid and poltly to tools list --- src/client/util/CurrentUserUtils.ts | 99 +++++++++++++++++++++++++++++++- src/client/views/nodes/ComparisonBox.tsx | 4 +- 2 files changed, 98 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 84bed08fa..3a928d0af 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -2,6 +2,7 @@ import { observable, reaction, runInAction } from "mobx"; import * as rp from 'request-promise'; import { OmitKeys, Utils } from "../../Utils"; import { Doc, DocListCast, DocListCastAsync, Opt } from "../../fields/Doc"; +import { DocData } from "../../fields/DocSymbols"; import { InkTool } from "../../fields/InkField"; import { List } from "../../fields/List"; import { PrefetchProxy } from "../../fields/Proxy"; @@ -234,6 +235,95 @@ export class CurrentUserUtils { MakeTemplate(Doc.GetProto(slide), true, "Untitled Slide View"); return slide; } + const plotlyView = (opts:DocumentOptions) => { + var plotly = Doc.MyPublishedDocs.find(doc => doc.title === "@plotly"); + if (!plotly) { + const plotly = Docs.Create.TextDocument( + `await import("https://cdn.plot.ly/plotly-2.27.0.min.js"); + Plotly.newPlot(dashDiv.id, [ --DOCDATA-- ])` + , {title: "@plotly", title_custom: true, _width:300,_height:400}); + Doc.AddToMyPublished(plotly); + } + const rtfield = new RichTextField(JSON.stringify( + {doc: {type:"doc",content:[ + {type:"code_block",content:[ + {type:"text",text:"^@plotly"}, + {type:"text",text:"\n"}, + {type:"text",text:"\n{"}, + {type:"text",text:"\n x: [1,2,3,5,19],"}, + {type:"text",text:"\n y: [1, 9, 15, 12,3],"}, + {type:"text",text:"\n mode: 'lines+markers', "}, + {type:"text",text:"\n type: 'scatter'"}, + {type:"text",text:"\n}"} + ]} + ]}, + selection:{type:"text",anchor:2,head:2}}), + `^@plotly + { + x: [1,2,3,5,19], + y: [1, 9, 15, 12,3], + mode: 'lines+markers', + type: 'scatter' + }`); + const slide = Docs.Create.TextDocument("", opts); + slide[DocData].text = rtfield; + slide[DocData].layout_textPainted = ``; + slide[DocData]._type_collection = CollectionViewType.Freeform; + slide.onPaint = ScriptField.MakeScript(`toggleDetail(documentView, "textPainted", "")`); + return slide; + } + const mermaidsView = (opts:DocumentOptions) => { + var mermaids = Doc.MyPublishedDocs.find(doc => doc.title === "@mermaids"); + if (!mermaids) { + const mermaids = Docs.Create.TextDocument( + `const mdef = (await import("https://cdn.jsdelivr.net/npm/mermaid\@10.8.0/dist/mermaid.esm.min.mjs")).default; + window["callb"] = (x) => { + alert(x); + } + mdef.initialize({ + securityLevel : "loose", + startOnLoad: true, + flowchart: { useMaxWidth: true, htmlLabels: true, curve: 'cardinal' }, + }); + const mermaid = async (str) => (await mdef.render("graph"+Date.now(),str)); + const {svg, bindFunctions} = await mermaid(\`--DOCDATA--\`); + dashDiv.innerHTML = svg; + if (bindFunctions) { + bindFunctions(dashDiv); + }` + , {title: "@mermaids", title_custom: true, _width:300,_height:400}); + Doc.AddToMyPublished(mermaids); + } + const rtfield = new RichTextField(JSON.stringify( + {doc: {type:"doc",content:[ + {type:"code_block",content:[ + {type:"text",text:"^@mermaids"}, + {type:"text",text:"\n\n"}, + {type:"text",text:"pie "}, + {type:"text",text:"title"}, + {type:"text",text:" "}, + {type:"text",text:"Minerals in my tap water"}, + {type:"text",text:"\n \"Calcium\" : "}, + {type:"dashField",attrs:{fieldKey:"calcium",docId:"","hideKey":false,editable:true}}, + {type:"text",text:"\n \"Potassium\" : "}, + {type:"dashField",attrs:{fieldKey:"pot",docId:"",hideKey:false,editable:true}}, + {type:"text",text:"\n \"Magnesium\" : 10.01"} + ]} + ]}, + selection:{type:"text",anchor:109,head:109} + }), + `^@mermaids +pie title Minerals in my tap water + "Calcium" : 42.96 + "Potassium" : 50 + "Magnesium" : 10.01`); + const slide = Docs.Create.TextDocument("", opts); + slide[DocData].text = rtfield; + slide[DocData].layout_textPainted = ``; + slide[DocData]._type_collection = CollectionViewType.Freeform; + slide.onPaint = ScriptField.MakeScript(`toggleDetail(documentView, "textPainted", "")`); + return slide; + } const emptyThings:{key:string, // the field name where the empty thing will be stored opts:DocumentOptions, // the document options that are required for the empty thing funcs?:{[key:string]: any}, // computed fields that are rquired for the empth thing @@ -264,7 +354,9 @@ export class CurrentUserUtils { dropAction:dropActionType.move, treeView_Type: TreeViewType.outline, backgroundColor: "white", _xMargin: 0, _yMargin: 0, _createDocOnCR: true }, funcs: {title: 'this.text?.Text'}}, - ]; + {key: "Mermaids", creator: mermaidsView, opts: { _width: 300, _height: 300, }}, + {key: "Plotly", creator: plotlyView, opts: { _width: 300, _height: 300, }}, + ]; emptyThings.forEach(thing => DocUtils.AssignDocField(doc, "empty"+thing.key, (opts) => thing.creator(opts), {...standardOps(thing.key), ...thing.opts}, undefined, thing.scripts, thing.funcs)); @@ -272,6 +364,8 @@ export class CurrentUserUtils { { toolTip: "Tap or drag to create a note", title: "Note", icon: "sticky-note", dragFactory: doc.emptyNote as Doc, clickFactory: DocCast(doc.emptyNote)}, { toolTip: "Tap or drag to create a flashcard", title: "Flashcard", icon: "id-card", dragFactory: doc.emptyFlashcard as Doc, clickFactory: DocCast(doc.emptyFlashcard)}, { toolTip: "Tap or drag to create an equation", title: "Math", icon: "calculator", dragFactory: doc.emptyEquation as Doc, clickFactory: DocCast(doc.emptyEquation)}, + { toolTip: "Tap or drag to create a mermaid node", title: "Mermaids", icon: "rocket", dragFactory: doc.emptyMermaids as Doc, clickFactory: DocCast(doc.emptyMermaids)}, + { toolTip: "Tap or drag to create a plotly node", title: "Plotly", icon: "rocket", dragFactory: doc.emptyPlotly as Doc, clickFactory: DocCast(doc.emptyMermaids)}, { toolTip: "Tap or drag to create a physics simulation",title: "Simulation", icon: "rocket",dragFactory: doc.emptySimulation as Doc, clickFactory: DocCast(doc.emptySimulation), funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a note board", title: "Notes", icon: "folder", dragFactory: doc.emptyNoteboard as Doc, clickFactory: DocCast(doc.emptyNoteboard)}, { toolTip: "Tap or drag to create a collection", title: "Col", icon: "folder", dragFactory: doc.emptyCollection as Doc, clickFactory: DocCast(doc.emptyTab)}, @@ -442,8 +536,7 @@ export class CurrentUserUtils { /// Initializes the panel of draggable tools that is opened from the left sidebar. static setupToolsBtnPanel(doc: Doc, field:string) { - const myTools = DocCast(doc[field]); - const allTools = DocListCast(myTools?.data); + const allTools = DocListCast(DocCast(doc[field])?.data); const creatorBtns = CurrentUserUtils.setupCreatorButtons(doc, allTools?.length ? allTools[0]:undefined); const userTools = allTools && allTools?.length > 1 ? allTools[1]:undefined; const userBtns = CurrentUserUtils.setupUserDocumentCreatorButtons(doc, userTools); diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index 116dc48a6..ef8c045cc 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -6,7 +6,7 @@ import { emptyFunction, returnFalse, returnNone, returnZero, setupMoveUpEvents } import { Doc, Opt } from '../../../fields/Doc'; import { DocCast, NumCast, StrCast } from '../../../fields/Types'; import { DocUtils, Docs } from '../../documents/Documents'; -import { DragManager } from '../../util/DragManager'; +import { DragManager, dropActionType } from '../../util/DragManager'; import { undoBatch } from '../../util/UndoManager'; import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent'; import { StyleProp } from '../StyleProvider'; @@ -135,7 +135,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() this, e, e => { - const de = new DragManager.DocumentDragData([DocCast(this.dataDoc[which])], 'move'); + const de = new DragManager.DocumentDragData([DocCast(this.dataDoc[which])], dropActionType.move); de.moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => { this.clearDoc(which); return addDocument(doc); -- cgit v1.2.3-70-g09d2 From 1dd5944ab430a57d105e649a218ca0d9f2f0a060 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 5 Mar 2024 12:26:23 -0500 Subject: from last --- src/client/util/CurrentUserUtils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 3a928d0af..d75c717c9 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -241,7 +241,7 @@ export class CurrentUserUtils { const plotly = Docs.Create.TextDocument( `await import("https://cdn.plot.ly/plotly-2.27.0.min.js"); Plotly.newPlot(dashDiv.id, [ --DOCDATA-- ])` - , {title: "@plotly", title_custom: true, _width:300,_height:400}); + , {title: "@plotly", title_custom: true, _layout_showTitle:"title", _width:300,_height:400}); Doc.AddToMyPublished(plotly); } const rtfield = new RichTextField(JSON.stringify( @@ -291,7 +291,7 @@ export class CurrentUserUtils { if (bindFunctions) { bindFunctions(dashDiv); }` - , {title: "@mermaids", title_custom: true, _width:300,_height:400}); + , {title: "@mermaids", title_custom: true, _layout_showTitle:"title", _width:300,_height:400}); Doc.AddToMyPublished(mermaids); } const rtfield = new RichTextField(JSON.stringify( -- cgit v1.2.3-70-g09d2 From 11b6cb8344f26e5895bebc3dedef491675717e30 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 5 Mar 2024 15:11:29 -0500 Subject: fixed text in templates to revert to template value when noTemplate is set. made dashFieldView read from datadoc. added margins for multicolumn/row, enabled chromHidden for multicolumn/row --- src/client/views/PropertiesView.tsx | 3 ++- .../collectionMulticolumn/CollectionMulticolumnView.tsx | 10 ++++++---- src/client/views/nodes/formattedText/DashFieldView.tsx | 15 +++++++-------- src/client/views/nodes/formattedText/FormattedTextBox.tsx | 5 +++-- 4 files changed, 18 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index e4e7bec32..cbd3ff358 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -135,7 +135,7 @@ export class PropertiesView extends ObservableReactComponent (!this.selectedLayoutDoc ? 0 : Math.min(NumCast(this.selectedLayoutDoc?._width), this._props.width - 20)); @@ -1076,6 +1076,7 @@ export class PropertiesView extends ObservableReactComponent {!this.isStack ? null : this.getNumber('Gap', ' px', 0, 200, NumCast(this.selectedDoc!.gridGap), (val: number) => !isNaN(val) && (this.selectedDoc!.gridGap = val))} {!this.isStack ? null : this.getNumber('xMargin', ' px', 0, 500, NumCast(this.selectedDoc!.xMargin), (val: number) => !isNaN(val) && (this.selectedDoc!.xMargin = val))} + {!this.isStack ? null : this.getNumber('yMargin', ' px', 0, 500, NumCast(this.selectedDoc!.yMargin), (val: number) => !isNaN(val) && (this.selectedDoc!.yMargin = val))} {!this.isGroup ? null : this.getNumber('Padding', ' px', 0, 500, NumCast(this.selectedDoc!.xPadding), (val: number) => !isNaN(val) && (this.selectedDoc!.xPadding = this.selectedDoc!.yPadding = val))} {this.isInk ? this.controlPointsButton : null} {this.getNumber('Width', ' px', 0, Math.max(1000, this.shapeWid), this.shapeWid, (val: number) => !isNaN(val) && (this.shapeWid = val), 1000, 1)} diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index 85fe7c896..125dd2781 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -315,7 +315,9 @@ export class CollectionMulticolumnView extends CollectionSubView() {
{this.getDisplayDoc(layout)} -
, @@ -350,14 +352,14 @@ export class CollectionMulticolumnView extends CollectionSubView() { }}> {this.contents} {!this._startIndex ? null : ( - +
(this._startIndex = Math.min(this.childLayoutPairs.length - 1, this._startIndex + this.maxShown)))}>
)} - {this._startIndex > this.childLayoutPairs.length - 1 ? null : ( - + {this._startIndex > this.childLayoutPairs.length - 1 || !this.maxShown ? null : ( +
(this._startIndex = Math.min(this.childLayoutPairs.length - 1, this._startIndex + this.maxShown)))}> } color={SettingsManager.userColor} />
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index b49e7dcf0..5c4d850ad 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -4,24 +4,23 @@ import { action, computed, IReactionDisposer, makeObservable, observable, reacti import { observer } from 'mobx-react'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; -import Select from 'react-select'; import { Doc, DocListCast, Field } from '../../../../fields/Doc'; import { List } from '../../../../fields/List'; import { listSpec } from '../../../../fields/Schema'; import { SchemaHeaderField } from '../../../../fields/SchemaHeaderField'; -import { Cast, StrCast } from '../../../../fields/Types'; +import { Cast } from '../../../../fields/Types'; import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents } from '../../../../Utils'; import { DocServer } from '../../../DocServer'; import { CollectionViewType } from '../../../documents/DocumentTypes'; import { Transform } from '../../../util/Transform'; -import { undoable, undoBatch } from '../../../util/UndoManager'; +import { undoBatch } from '../../../util/UndoManager'; import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu'; import { SchemaTableCell } from '../../collections/collectionSchema/SchemaTableCell'; +import { FilterPanel } from '../../FilterPanel'; import { ObservableReactComponent } from '../../ObservableReactComponent'; import { OpenWhere } from '../DocumentView'; import './DashFieldView.scss'; import { FormattedTextBox } from './FormattedTextBox'; -import { FilterPanel } from '../../FilterPanel'; export class DashFieldView { dom: HTMLDivElement; // container for label and value @@ -29,7 +28,7 @@ export class DashFieldView { node: any; tbox: FormattedTextBox; - unclickable = () => !this.tbox._props.isSelected() && this.node.marks.some((m: any) => m.type === this.tbox.EditorView?.state.schema.marks.linkAnchor && m.attrs.noPreview); + unclickable = () => !this.tbox._props.rootSelected?.() && this.node.marks.some((m: any) => m.type === this.tbox.EditorView?.state.schema.marks.linkAnchor && m.attrs.noPreview); constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) { this.node = node; this.tbox = tbox; @@ -108,12 +107,12 @@ export class DashFieldViewInternal extends ObservableReactComponent dashDoc instanceof Doc && (this._dashDoc = dashDoc))); } else { - this._dashDoc = this._props.tbox.Document; + this._dashDoc = this._fieldKey.startsWith('_') ? this._props.tbox.Document : this._props.tbox.dataDoc; } } @@ -202,7 +201,7 @@ export class DashFieldViewInternal extends ObservableReactComponent {this._props.hideKey ? null : ( diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 266a2442f..2d5239f06 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -374,9 +374,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent Date: Wed, 6 Mar 2024 09:44:38 -0500 Subject: enabled copy and paste to work with template docs (and not copy template). Fixed tempaltes of collections to allow new nodes to be added/removed. --- src/client/views/DocComponent.tsx | 8 ++--- src/client/views/TemplateMenu.tsx | 9 ++++-- src/client/views/nodes/ScriptingBox.tsx | 32 ++++++++++---------- src/fields/Doc.ts | 52 ++++++++++++++++++++++----------- 4 files changed, 60 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 2a527eca1..a25a8f77a 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -182,7 +182,7 @@ export function ViewBoxAnnotatableComponent

() { const docs = indocs.filter(doc => [AclEdit, AclAdmin].includes(effectiveAcl) || GetEffectiveAcl(doc) === AclAdmin); // docs.forEach(doc => doc.annotationOn === this.Document && Doc.SetInPlace(doc, 'annotationOn', undefined, true)); - const targetDataDoc = this.dataDoc; + const targetDataDoc = this.Document[DocData]; // this.dataDoc; // we want to write to the template, not the actual data doc const value = DocListCast(targetDataDoc[annotationKey ?? this.annotationKey]); const toRemove = value.filter(v => docs.includes(v)); @@ -228,7 +228,7 @@ export function ViewBoxAnnotatableComponent

() { if (this._props.filterAddDocument?.(docs) === false || docs.find(doc => Doc.AreProtosEqual(doc, this.Document) && Doc.LayoutField(doc) === Doc.LayoutField(this.Document))) { return false; } - const targetDataDoc = this.dataDoc; + const targetDataDoc = this.Document[DocData]; // this.dataDoc; // we want to write to the template, not the actual data doc const effectiveAcl = GetEffectiveAcl(targetDataDoc); if (effectiveAcl === AclPrivate || effectiveAcl === AclReadonly) { @@ -245,9 +245,9 @@ export function ViewBoxAnnotatableComponent

() { inheritParentAcls(targetDataDoc, doc, true); }); - const annoDocs = Doc.Get(targetDataDoc, annotationKey ?? this.annotationKey, true) as List; // get the dataDoc directly ... when using templates there may be some default items already there, but we can't change them. maybe we should copy them over, though... + const annoDocs = Doc.Get(targetDataDoc, annotationKey ?? this.annotationKey, true) as List; // get the dataDoc directly ... when using templates there may be some default items already there, but we can't change them, so we copy them below (should really be some kind of inheritance since the template contents could change) if (annoDocs instanceof List) annoDocs.push(...added.filter(add => !annoDocs.includes(add))); - else targetDataDoc[annotationKey ?? this.annotationKey] = new List(added); + else targetDataDoc[annotationKey ?? this.annotationKey] = new List([...added, ...(annoDocs === undefined ? DocListCast(targetDataDoc[annotationKey ?? this.annotationKey]) : [])]); targetDataDoc[(annotationKey ?? this.annotationKey) + '_modificationDate'] = new DateField(); } } diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index f7729dbc7..5d9abb460 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -3,7 +3,7 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast } from '../../fields/Doc'; import { ScriptField } from '../../fields/ScriptField'; -import { Cast, StrCast } from '../../fields/Types'; +import { Cast, DocCast, StrCast } from '../../fields/Types'; import { TraceMobx } from '../../fields/util'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../Utils'; import { Docs, DocUtils } from '../documents/Documents'; @@ -81,8 +81,11 @@ export class TemplateMenu extends React.Component { componentDidMount() { !this._addedKeys && (this._addedKeys = new ObservableSet()); [...Array.from(Object.keys(this.props.docViews[0].Document[DocData])), ...Array.from(Object.keys(this.props.docViews[0].Document))] - .filter(key => key.startsWith('layout_') && key !== 'layout_fieldKey') - .map(key => runInAction(() => this._addedKeys.add(key.replace('layout_', '')))); + .filter(key => key.startsWith('layout_') && ( + StrCast(this.props.docViews[0].Document[key]).startsWith("<") || + DocCast(this.props.docViews[0].Document[key])?.isTemplateDoc + )) + .map(key => runInAction(() => this._addedKeys.add(key.replace('layout_', '')))); // prettier-ignore } return100 = () => 300; diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx index 89650889d..d9d0dbe3e 100644 --- a/src/client/views/nodes/ScriptingBox.tsx +++ b/src/client/views/nodes/ScriptingBox.tsx @@ -130,7 +130,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent() } }) ); - observer.observe(document.getElementsByClassName('scriptingBox')[0]); + observer.observe(document.getElementsByClassName('scriptingBox-outerDiv')[0]); } @action @@ -811,22 +811,20 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent() render() { TraceMobx(); return ( -

-
this._props.isSelected() && e.stopPropagation()}> - {this._paramSuggestion ? ( -
- {' '} - {this._scriptSuggestedParams}{' '} -
- ) : null} - {!this._applied && !this._function ? this.renderScriptingInputs : null} - {this._applied && !this._function ? this.renderParamsInputs() : null} - {!this._applied && this._function ? this.renderFunctionInputs() : null} - - {!this._applied && !this._function ? this.renderScriptingTools() : null} - {this._applied && !this._function ? this.renderTools('Run', () => this.onRun()) : null} - {!this._applied && this._function ? this.renderTools('Create Function', () => this.onCreate()) : null} -
+
this._props.isSelected() && e.stopPropagation()}> + {this._paramSuggestion ? ( +
+ {' '} + {this._scriptSuggestedParams}{' '} +
+ ) : null} + {!this._applied && !this._function ? this.renderScriptingInputs : null} + {this._applied && !this._function ? this.renderParamsInputs() : null} + {!this._applied && this._function ? this.renderFunctionInputs() : null} + + {!this._applied && !this._function ? this.renderScriptingTools() : null} + {this._applied && !this._function ? this.renderTools('Run', () => this.onRun()) : null} + {!this._applied && this._function ? this.renderTools('Create Function', () => this.onCreate()) : null}
); } diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index b1bdd50a7..1df9d80a1 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -614,8 +614,19 @@ export namespace Doc { // this lists out all the tag ids that can be in a RichTextField that might contain document ids. // if a document is cloned, we need to make sure to clone all of these referenced documents as well; export const DocsInTextFieldIds = ['audioId', 'textId', 'anchorId', 'docId']; - export async function makeClone(doc: Doc, cloneMap: Map, linkMap: Map, rtfs: { copy: Doc; key: string; field: RichTextField }[], exclusions: string[], pruneDocs: Doc[], cloneLinks: boolean): Promise { - if (Doc.IsBaseProto(doc)) return doc; + export async function makeClone( + doc: Doc, + cloneMap: Map, + linkMap: Map, + rtfs: { copy: Doc; key: string; field: RichTextField }[], + exclusions: string[], + pruneDocs: Doc[], + cloneLinks: boolean, + cloneTemplates: boolean + ): Promise { + if (Doc.IsBaseProto(doc) || ((Doc.Get(doc, 'isTemplateDoc', true) || Doc.Get(doc, 'isTemplateForField', true)) && !cloneTemplates)) { + return doc; + } if (cloneMap.get(doc[Id])) return cloneMap.get(doc[Id])!; const copy = new Doc(undefined, true); cloneMap.set(doc[Id], copy); @@ -630,7 +641,7 @@ export namespace Doc { const list = await Cast(doc[key], listSpec(Doc)); const docs = list && (await DocListCastAsync(list))?.filter(d => d instanceof Doc); if (docs !== undefined && docs.length) { - const clones = await Promise.all(docs.map(async d => Doc.makeClone(d, cloneMap, linkMap, rtfs, exclusions, pruneDocs, cloneLinks))); + const clones = await Promise.all(docs.map(async d => Doc.makeClone(d, cloneMap, linkMap, rtfs, exclusions, pruneDocs, cloneLinks, cloneTemplates))); assignKey(new List(clones)); } else { assignKey(ObjectField.MakeCopy(field)); @@ -645,7 +656,7 @@ export namespace Doc { ); const results = docids && (await DocServer.GetRefFields(docids)); const docs = results && Array.from(Object.keys(results)).map(key => DocCast(results[key])); - docs?.map(doc => doc && Doc.makeClone(doc, cloneMap, linkMap, rtfs, exclusions, pruneDocs, cloneLinks)); + docs?.map(doc => doc && Doc.makeClone(doc, cloneMap, linkMap, rtfs, exclusions, pruneDocs, cloneLinks, cloneTemplates)); rtfs.push({ copy, key, field }); } } @@ -657,8 +668,14 @@ export namespace Doc { } else if (docAtKey instanceof Doc) { if (pruneDocs.includes(docAtKey)) { // prune doc and do nothing - } else if (!Doc.IsSystem(docAtKey) && (key.startsWith('layout') || ['embedContainer', 'annotationOn', 'proto'].includes(key) || ((key === 'link_anchor_1' || key === 'link_anchor_2') && doc.author === Doc.CurrentUserEmail))) { - assignKey(await Doc.makeClone(docAtKey, cloneMap, linkMap, rtfs, exclusions, pruneDocs, cloneLinks)); + } else if ( + !Doc.IsSystem(docAtKey) && + (key.includes('layout[') || + key.startsWith('layout') || // + ['embedContainer', 'annotationOn', 'proto'].includes(key) || + (['link_anchor_1', 'link_anchor_2'].includes(key) && doc.author === Doc.CurrentUserEmail)) + ) { + assignKey(await Doc.makeClone(docAtKey, cloneMap, linkMap, rtfs, exclusions, pruneDocs, cloneLinks, cloneTemplates)); } else { assignKey(docAtKey); } @@ -681,16 +698,17 @@ export namespace Doc { ((cloneMap.has(DocCast(link.link_anchor_1)?.[Id]) || cloneMap.has(DocCast(DocCast(link.link_anchor_1)?.annotationOn)?.[Id])) && (cloneMap.has(DocCast(link.link_anchor_2)?.[Id]) || cloneMap.has(DocCast(DocCast(link.link_anchor_2)?.annotationOn)?.[Id]))) ) { - linkMap.set(link[Id], await Doc.makeClone(link, cloneMap, linkMap, rtfs, exclusions, pruneDocs, cloneLinks)); + linkMap.set(link[Id], await Doc.makeClone(link, cloneMap, linkMap, rtfs, exclusions, pruneDocs, cloneLinks, cloneTemplates)); } }); - Doc.SetInPlace(copy, 'title', '>:' + doc.title, true); + if (Doc.Get(copy, 'title', true)) copy.title = '>:' + doc.title; + // Doc.SetInPlace(copy, 'title', '>:' + doc.title, true); copy.cloneOf = doc; cloneMap.set(doc[Id], copy); return copy; } - export function repairClone(clone: Doc, cloneMap: Map, visited: Set) { + export function repairClone(clone: Doc, cloneMap: Map, cloneTemplates: boolean, visited: Set) { if (visited.has(clone)) return; visited.add(clone); Object.keys(clone) @@ -699,22 +717,22 @@ export namespace Doc { const docAtKey = DocCast(clone[key]); if (docAtKey && !Doc.IsSystem(docAtKey)) { if (!Array.from(cloneMap.values()).includes(docAtKey)) { - clone[key] = cloneMap.get(docAtKey[Id]); + clone[key] = !cloneTemplates && (Doc.Get(docAtKey, 'isTemplateDoc', true) || Doc.Get(docAtKey, 'isTemplateForField', true)) ? docAtKey : cloneMap.get(docAtKey[Id]); } else { - repairClone(docAtKey, cloneMap, visited); + repairClone(docAtKey, cloneMap, cloneTemplates, visited); } } }); } - export function MakeClones(docs: Doc[], cloneLinks: boolean) { + export function MakeClones(docs: Doc[], cloneLinks: boolean, cloneTemplates: boolean) { const cloneMap = new Map(); - return docs.map(doc => Doc.MakeClone(doc, cloneLinks, cloneMap)); + return docs.map(doc => Doc.MakeClone(doc, cloneLinks, cloneTemplates, cloneMap)); } - export async function MakeClone(doc: Doc, cloneLinks = true, cloneMap: Map = new Map()) { + export async function MakeClone(doc: Doc, cloneLinks = true, cloneTemplates = true, cloneMap: Map = new Map()) { const linkMap = new Map(); const rtfMap: { copy: Doc; key: string; field: RichTextField }[] = []; - const copy = await Doc.makeClone(doc, cloneMap, linkMap, rtfMap, ['cloneOf'], doc.embedContainer ? [DocCast(doc.embedContainer)] : [], cloneLinks); + const copy = await Doc.makeClone(doc, cloneMap, linkMap, rtfMap, ['cloneOf'], doc.embedContainer ? [DocCast(doc.embedContainer)] : [], cloneLinks, cloneTemplates); const repaired = new Set(); const linkedDocs = Array.from(linkMap.values()); linkedDocs.map((link: Doc) => LinkManager.Instance.addLink(link, true)); @@ -732,7 +750,7 @@ export namespace Doc { copy[key] = new RichTextField(field.Data.replace(docidsearch, replacer).replace(re, replacer2), field.Text); }); const clonedDocs = [...Array.from(cloneMap.values()), ...linkedDocs]; - clonedDocs.map(clone => Doc.repairClone(clone, cloneMap, repaired)); + clonedDocs.map(clone => Doc.repairClone(clone, cloneMap, cloneTemplates, repaired)); return { clone: copy, map: cloneMap, linkMap }; } @@ -1395,7 +1413,7 @@ export namespace Doc { const list = Array.from(Object.values(fieldlist)) .map(d => DocCast(d)) .filter(d => d); - const docs = clone ? (await Promise.all(Doc.MakeClones(list, false))).map(res => res.clone) : list; + const docs = clone ? (await Promise.all(Doc.MakeClones(list, false, false))).map(res => res.clone) : list; if (ptx !== undefined && pty !== undefined && newPoint !== undefined) { const firstx = list.length ? NumCast(list[0].x) + ptx - newPoint[0] : 0; const firsty = list.length ? NumCast(list[0].y) + pty - newPoint[1] : 0; -- cgit v1.2.3-70-g09d2 From bd9170eaa21a2fbccd0912f50d40cefaf0bbe47f Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 6 Mar 2024 12:28:24 -0500 Subject: cleaned up some dropActionType strings. fixed stackingview scrolling when always active. fixed schemaView keys dropdown menu to be a popup. cleaned up display of key Finfo's --- src/client/documents/Documents.ts | 46 +++---- src/client/views/DashboardView.tsx | 9 +- src/client/views/TemplateMenu.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 15 ++- src/client/views/collections/CollectionSubView.tsx | 5 +- src/client/views/collections/TreeView.tsx | 6 +- .../collectionSchema/CollectionSchemaView.scss | 149 +++++++++++---------- .../collectionSchema/CollectionSchemaView.tsx | 68 ++++++---- src/client/views/nodes/LinkAnchorBox.tsx | 4 +- .../views/nodes/RecordingBox/RecordingBox.tsx | 4 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 4 +- 11 files changed, 170 insertions(+), 142 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 031560886..c9b5cb915 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -70,14 +70,14 @@ class EmptyBox { } export enum FInfoFieldType { - string, - boolean, - number, - Doc, - enumeration, - date, - list, - rtf, + string = 'string', + boolean = 'boolean', + number = 'number', + Doc = 'Doc', + enumeration = 'enum', + date = 'date', + list = 'list', + rtf = 'rich text', } export class FInfo { description: string = ''; @@ -198,20 +198,20 @@ type DATEt = DateInfo | number; type DTYPEt = DTypeInfo | string; export class DocumentOptions { // coordinate and dimensions depending on view - x?: NUMt = new NumInfo('x coordinate of document in a freeform view', false); - y?: NUMt = new NumInfo('y coordinate of document in a freeform view', false); + x?: NUMt = new NumInfo('horizontal coordinate in freeform view', false); + y?: NUMt = new NumInfo('vertical coordinate in freeform view', false); z?: NUMt = new NumInfo('whether document is in overlay (1) or not (0)', false, false, [1, 0]); - overlayX?: NUMt = new NumInfo('x coordinate of document in a overlay view', false); - overlayY?: NUMt = new NumInfo('y coordinate of document in a overlay view', false); - text?: RTFt = new RtfInfo('rich text of a text doc', true); + overlayX?: NUMt = new NumInfo('horizontal coordinate in overlay view', false); + overlayY?: NUMt = new NumInfo('vertical coordinate in overlay view', false); + text?: RTFt = new RtfInfo('plain or rich text', true); _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height", false); _dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units"); - latitude?: NUMt = new NumInfo('latitude coordinate for map views', false); - longitude?: NUMt = new NumInfo('longitude coordinate for map views', false); + latitude?: NUMt = new NumInfo('latitude coordinate', false); + longitude?: NUMt = new NumInfo('longitude coordinate', false); routeCoordinates?: STRt = new StrInfo("stores a route's/direction's coordinates (stringified version)"); // for a route document, this stores the route's coordinates - markerType?: STRt = new StrInfo('Defines the marker type for a pushpin document'); - markerColor?: STRt = new StrInfo('Defines the marker color for a pushpin document'); - map?: STRt = new StrInfo('text location of map'); + markerType?: STRt = new StrInfo('marker type for a pushpin document'); + markerColor?: STRt = new StrInfo('marker color for a pushpin document'); + map?: STRt = new StrInfo('map location name'); map_type?: STRt = new StrInfo('type of map view', false); map_zoom?: NUMt = new NumInfo('zoom of a map view', false); map_pitch?: NUMt = new NumInfo('pitch of a map view', false); @@ -221,11 +221,11 @@ export class DocumentOptions { date_range?: STRt = new StrInfo('date range for calendar', false); wikiData?: STRt = new StrInfo('WikiData ID related to map location'); - description?: STRt = new StrInfo('A description of the document'); - _timecodeToShow?: NUMt = new NumInfo('the time that a document should be displayed (e.g., when an annotation shows up as a video plays)', false); - _timecodeToHide?: NUMt = new NumInfo('the time that a document should be hidden', false); - _width?: NUMt = new NumInfo('displayed width of a document'); - _height?: NUMt = new NumInfo('displayed height of document'); + description?: STRt = new StrInfo('description of document'); + _timecodeToShow?: NUMt = new NumInfo('media timecode when document should appear (e.g., when an annotation shows up as a video plays)', false); + _timecodeToHide?: NUMt = new NumInfo('media timecode when document should disappear', false); + _width?: NUMt = new NumInfo("width of document in container's coordinates"); + _height?: NUMt = new NumInfo("height of document in container's coordiantes"); data_nativeWidth?: NUMt = new NumInfo('native width of data field contents (e.g., the pixel width of an image)', false); data_nativeHeight?: NUMt = new NumInfo('native height of data field contents (e.g., the pixel height of an image)', false); linearBtnWidth?: NUMt = new NumInfo('unexpanded width of a linear menu button (button "width" changes when it expands)', false); diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx index 472d419fc..439d250de 100644 --- a/src/client/views/DashboardView.tsx +++ b/src/client/views/DashboardView.tsx @@ -28,6 +28,7 @@ import { Colors } from './global/globalEnums'; import { MainViewModal } from './MainViewModal'; import { ButtonType } from './nodes/FontIconBox/FontIconBox'; import { ObservableReactComponent } from './ObservableReactComponent'; +import { dropActionType } from '../util/DragManager'; enum DashboardGroup { MyDashboards, @@ -403,7 +404,7 @@ export class DashboardView extends ObservableReactComponent<{}> { _layout_fitWidth: true, _gridGap: 5, _forceActive: true, - childDragAction: 'embed', + childDragAction: dropActionType.embed, treeView_TruncateTitleWidth: 150, ignoreClick: true, contextMenuIcons: new List(['plus']), @@ -411,7 +412,7 @@ export class DashboardView extends ObservableReactComponent<{}> { _lockedPosition: true, layout_boxShadow: '0 0', childDontRegisterViews: true, - dropAction: 'same', + dropAction: dropActionType.same, isSystem: true, layout_explainer: 'All of the calendars that you have created will appear here.', }; @@ -450,7 +451,7 @@ export class DashboardView extends ObservableReactComponent<{}> { _layout_fitWidth: true, _gridGap: 5, _forceActive: true, - childDragAction: 'embed', + childDragAction: dropActionType.embed, treeView_TruncateTitleWidth: 150, ignoreClick: true, layout_headerButton: myTrailsBtn, @@ -459,7 +460,7 @@ export class DashboardView extends ObservableReactComponent<{}> { _lockedPosition: true, layout_boxShadow: '0 0', childDontRegisterViews: true, - dropAction: 'same', + dropAction: dropActionType.same, isSystem: true, layout_explainer: 'All of the trails that you have created will appear here.', }; diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 5d9abb460..00195f7d7 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -105,7 +105,7 @@ export class TemplateMenu extends React.Component { const addedTypes = DocListCast(Cast(Doc.UserDoc()['template_clickFuncs'], Doc, null)?.data); const templateMenu: Array = []; this.props.templates?.forEach((checked, template) => templateMenu.push()); - templateMenu.push(); + templateMenu.push(); addedTypes.concat(noteTypes).map(template => (template.treeView_Checked = this.templateIsUsed(firstDoc, template))); this._addedKeys && Array.from(this._addedKeys) diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index dc391631a..ea1caf58f 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -233,10 +233,6 @@ export class CollectionStackingView extends CollectionSubView boolean): boolean => { return this._props.removeDocument?.(doc) && addDocument?.(doc) ? true : false; }; - createRef = (ele: HTMLDivElement | null) => { - this._masonryGridRef = ele; - this.createDashEventsTarget(ele!); //so the whole grid is the drop target? - }; onChildClickHandler = () => this._props.childClickScript || ScriptCast(this.Document.onChildClick); @computed get onChildDoubleClickHandler() { @@ -679,6 +675,8 @@ export class CollectionStackingView extends CollectionSubView this._props.setHeight?.(this.headerMargin + (this.isStackingView ? Math.max(...this._refList.map(DivHeight)) : this._refList.reduce((p, r) => p + DivHeight(r), 0)))); + onPassiveWheel = (e: WheelEvent) => e.stopPropagation(); + _oldWheel: any; render() { TraceMobx(); const editableViewProps = { @@ -699,7 +697,14 @@ export class CollectionStackingView extends CollectionSubView
{ + this._masonryGridRef = ele; + this.createDashEventsTarget(ele); //so the whole grid is the drop target? + this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel); + this._oldWheel = ele; + // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling + ele?.addEventListener('wheel', this.onPassiveWheel, { passive: false }); + }} style={{ overflowY: this.isContentActive() ? 'auto' : 'hidden', background: this._props.styleProvider?.(this.Document, this._props, StyleProp.BackgroundColor), diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index fdbd1cc90..59a695a3d 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -219,12 +219,13 @@ export function CollectionSubView(moreProps?: X) { const targetDocments = DocListCast(this.dataDoc[this._props.fieldKey]); const someMoved = !dropAction && docDragData.draggedDocuments.some(drag => targetDocments.includes(drag)); if (someMoved) docDragData.droppedDocuments = docDragData.droppedDocuments.map((drop, i) => (targetDocments.includes(docDragData.draggedDocuments[i]) ? docDragData.draggedDocuments[i] : drop)); - if ((!dropAction || dropAction === 'inSame' || dropAction === 'same' || dropAction === 'move' || someMoved) && docDragData.moveDocument) { + if ((!dropAction || dropAction === dropActionType.inPlace || dropAction === dropActionType.same || dropAction === dropActionType.move || someMoved) && docDragData.moveDocument) { const movedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] === d); const addedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] !== d); if (movedDocs.length) { const canAdd = - (de.embedKey || dropAction || Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.Document)) && (dropAction !== 'inSame' || docDragData.draggedDocuments.every(d => d.embedContainer === this.Document)); + (de.embedKey || dropAction || Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.Document)) && + (dropAction !== dropActionType.inPlace || docDragData.draggedDocuments.every(d => d.embedContainer === this.Document)); const moved = docDragData.moveDocument(movedDocs, this.Document, canAdd ? this.addDocument : returnFalse); added = canAdd || moved ? moved : undefined; } else if (addedDocs.length) { diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 4f2d8b9c0..285a789e6 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -449,10 +449,10 @@ export class TreeView extends ObservableReactComponent { const addDoc = inside ? this.localAdd : parentAddDoc; const canAdd = !StrCast((inside ? this.Document : this._props.treeViewParent)?.treeView_FreezeChildren).includes('add') || forceAdd; - if (canAdd && (dropAction !== 'inSame' || droppedDocuments.every(d => d.embedContainer === this._props.parentTreeView?.Document))) { - const move = (!dropAction || canEmbed || dropAction === 'proto' || dropAction === 'move' || dropAction === 'same' || dropAction === 'inSame') && moveDocument; + if (canAdd && (dropAction !== dropActionType.inPlace || droppedDocuments.every(d => d.embedContainer === this._props.parentTreeView?.Document))) { + const move = (!dropAction || canEmbed || dropAction === dropActionType.proto || dropAction === dropActionType.move || dropAction === dropActionType.same || dropAction === dropActionType.inPlace) && moveDocument; this._props.parentTreeView instanceof TreeView && (this._props.parentTreeView.dropping = true); - const res = droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === 'proto' ? addDoc(d) : false) : addDoc(d)) || added, false); + const res = droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === dropActionType.proto ? addDoc(d) : false) : addDoc(d)) || added, false); this._props.parentTreeView instanceof TreeView && (this._props.parentTreeView.dropping = false); return res; } diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index fed4e89cf..ac0bd2378 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -38,91 +38,97 @@ background: yellow; } } + } - .schema-column-menu, - .schema-filter-menu { - background: $light-gray; - position: absolute; - min-width: 200px; - max-width: 400px; - display: flex; - flex-direction: column; - align-items: flex-start; - z-index: 1; - - .schema-key-search-input { - width: calc(100% - 20px); - margin: 10px; - } + .schema-preview-divider { + height: 100%; + background: black; + cursor: ew-resize; + } +} - .schema-search-result { - cursor: pointer; - padding: 5px 10px; - width: 100%; +.schema-column-menu, +.schema-filter-menu { + background: $light-gray; + position: relative; + min-width: 200px; + max-width: 400px; + display: flex; + flex-direction: column; + align-items: flex-start; + z-index: 1; - &:hover { - background-color: $medium-gray; - } + .schema-key-search-input { + width: calc(100% - 20px); + margin: 10px; + } - .schema-search-result-type, - .schema-search-result-desc { - color: $dark-gray; - font-size: $body-text; - } - } + .schema-search-result { + cursor: pointer; + padding: 5px 10px; + width: 100%; - .schema-key-search, - .schema-new-key-options { - width: 100%; - display: flex; - flex-direction: column; - align-items: flex-start; - } + &:hover { + background-color: $medium-gray; + } + .schema-search-result-type { + font-family: 'Courier New', Courier, monospace; + } - .schema-new-key-options { - margin: 10px; - .schema-key-warning { - color: red; - font-weight: normal; - align-self: center; - } - } + .schema-search-result-type, + .schema-search-result-desc { + color: $dark-gray; + font-size: $body-text; + } + .schema-search-result-desc { + font-style: italic; + } + } - .schema-key-list { - width: 100%; - max-height: 300px; - overflow-y: auto; - } + .schema-key-search, + .schema-new-key-options { + width: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + } - .schema-key-type-option { - margin: 2px 0px; + .schema-new-key-options { + margin: 10px; + .schema-key-warning { + color: red; + font-weight: normal; + align-self: center; + } + } - input { - margin-right: 5px; - } - } + .schema-key-list { + width: 100%; + max-height: 300px; + overflow-y: auto; + } - .schema-key-default-val { - margin: 5px 0; - } + .schema-key-type-option { + margin: 2px 0px; - .schema-column-menu-button { - cursor: pointer; - padding: 2px 5px; - background: $medium-blue; - border-radius: 9999px; - color: $white; - width: fit-content; - margin: 5px; - align-self: center; - } + input { + margin-right: 5px; } } - .schema-preview-divider { - height: 100%; - background: black; - cursor: ew-resize; + .schema-key-default-val { + margin: 5px 0; + } + + .schema-column-menu-button { + cursor: pointer; + padding: 2px 5px; + background: $medium-blue; + border-radius: 9999px; + color: $white; + width: fit-content; + margin: 5px; + align-self: center; } } @@ -133,6 +139,7 @@ .row-menu { display: flex; justify-content: center; + cursor: pointer; } } diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index eee3836d2..12f0ad5e9 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, makeObservable, observable, ObservableMap, observe } from 'mobx'; +import { action, computed, makeObservable, observable, ObservableMap, observe, trace } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast, Field, NumListCast, Opt, StrListCast } from '../../../../fields/Doc'; @@ -25,6 +25,8 @@ import { CollectionSubView } from '../CollectionSubView'; import './CollectionSchemaView.scss'; import { SchemaColumnHeader } from './SchemaColumnHeader'; import { SchemaRowBox } from './SchemaRowBox'; +import { Popup, PopupTrigger, Type } from 'browndash-components'; +import { SettingsManager } from '../../../util/SettingsManager'; const { default: { SCHEMA_NEW_NODE_HEIGHT } } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore export enum ColumnType { @@ -161,7 +163,7 @@ export class CollectionSchemaView extends CollectionSubView() { (change as any).added.forEach((doc: Doc) => // for each document added Doc.GetAllPrototypes(doc.value as Doc).forEach(proto => // for all of its prototypes (and itself) Object.keys(proto).forEach(action(key => // check if any of its keys are new, and add them - !this.fieldInfos.get(key) && this.fieldInfos.set(key, new FInfo(key, key === 'author')))))); + !this.fieldInfos.get(key) && this.fieldInfos.set(key, new FInfo("-no description-", key === 'author')))))); break; case 'update': //let oldValue = change.oldValue; // fill this in if the entire child list will ever be reassigned with a new list } @@ -681,6 +683,7 @@ export class CollectionSchemaView extends CollectionSubView() { } else { this.setKey(this._menuValue, this._newFieldDefault); } + this._columnMenuIndex = undefined; })}> done
@@ -688,12 +691,12 @@ export class CollectionSchemaView extends CollectionSubView() { ); } - onPassiveWheel = (e: WheelEvent) => { + onKeysPassiveWheel = (e: WheelEvent) => { // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this) - if (!this._oldWheel.scrollTop && e.deltaY <= 0) e.preventDefault(); + if (!this._oldKeysWheel.scrollTop && e.deltaY <= 0) e.preventDefault(); e.stopPropagation(); }; - _oldWheel: any; + _oldKeysWheel: any; @computed get keysDropdown() { return (
@@ -708,9 +711,9 @@ export class CollectionSchemaView extends CollectionSubView() {
{ - this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel); - this._oldWheel = r; - r?.addEventListener('wheel', this.onPassiveWheel, { passive: false }); + this._oldKeysWheel?.removeEventListener('wheel', this.onKeysPassiveWheel); + this._oldKeysWheel = r; + r?.addEventListener('wheel', this.onKeysPassiveWheel, { passive: false }); }}> {this._menuKeys.map(key => (

- {key} - {this.fieldInfos.get(key)!.fieldType ? ', ' : ''} + {key} + {this.fieldInfos.get(key)!.fieldType ? ':' : ''} {this.fieldInfos.get(key)!.fieldType} +   {this.fieldInfos.get(key)!.description}

-

{this.fieldInfos.get(key)!.description}

))}
@@ -740,16 +743,17 @@ export class CollectionSchemaView extends CollectionSubView() { const x = this._columnMenuIndex! == -1 ? 0 : this.displayColumnWidths.reduce((total, curr, index) => total + (index < this._columnMenuIndex! ? curr : 0), CollectionSchemaView._rowMenuWidth); return (
- e.stopPropagation()} /> + e.stopPropagation()} /> + {this._makeNewField ? this.newFieldMenu : this.keysDropdown} +
+ ); + } + get renderKeysMenu() { + console.log('RNDERMENUT:' + this._columnMenuIndex); + return ( +
+ e.stopPropagation()} /> {this._makeNewField ? this.newFieldMenu : this.keysDropdown} -
{ - e.stopPropagation(); - this.closeColumnMenu(); - })}> - cancel -
); } @@ -833,6 +837,8 @@ export class CollectionSchemaView extends CollectionSubView() { isContentActive = () => this._props.isSelected() || this._props.isContentActive(); screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0); previewWidthFunc = () => this.previewWidth; + onPassiveWheel = (e: WheelEvent) => e.stopPropagation(); + _oldWheel: any; render() { return (
this.createDashEventsTarget(ele)} onDrop={this.onExternalDrop.bind(this)}> @@ -841,15 +847,23 @@ export class CollectionSchemaView extends CollectionSubView() { className="schema-table" style={{ width: `calc(100% - ${this.previewWidth}px)` }} onWheel={e => this._props.isContentActive() && e.stopPropagation()} - ref={r => { - // prevent wheel events from passively propagating up through containers - r?.addEventListener('wheel', (e: WheelEvent) => {}, { passive: false }); + ref={ele => { + // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling + this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel); + (this._oldWheel = ele)?.addEventListener('wheel', this.onPassiveWheel, { passive: false }); }}>
-
(this._columnMenuIndex === -1 ? this.closeColumnMenu() : this.openColumnMenu(-1, true))}> - -
+ this.openColumnMenu(-1, true)} icon="plus" />} + trigger={PopupTrigger.CLICK} + type={Type.TERT} + isOpen={this._columnMenuIndex !== -1 ? false : undefined} + popup={this.renderKeysMenu} + />
{this.columnKeys.map((key, index) => ( ))}
- {this._columnMenuIndex !== undefined && this.renderColumnMenu} + {this._columnMenuIndex !== undefined && this._columnMenuIndex !== -1 && this.renderColumnMenu} {this._filterColumnIndex !== undefined && this.renderFilterMenu} (this._tableContentRef = ref)} /> {this.layoutDoc.chromeHidden ? null : ( diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index 00e1f04c5..0a4325d8c 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -5,7 +5,7 @@ import { Utils, emptyFunction, setupMoveUpEvents } from '../../../Utils'; import { Doc } from '../../../fields/Doc'; import { NumCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { DragManager } from '../../util/DragManager'; +import { DragManager, dropActionType } from '../../util/DragManager'; import { LinkFollower } from '../../util/LinkFollower'; import { SelectionManager } from '../../util/SelectionManager'; import { ViewBoxBaseComponent } from '../DocComponent'; @@ -54,7 +54,7 @@ export class LinkAnchorBox extends ViewBoxBaseComponent() { const separation = Math.sqrt((pt[0] - e.clientX) * (pt[0] - e.clientX) + (pt[1] - e.clientY) * (pt[1] - e.clientY)); if (separation > 100) { const dragData = new DragManager.DocumentDragData([this.Document]); - dragData.dropAction = 'embed'; + dragData.dropAction = dropActionType.embed; dragData.dropPropertiesToRemove = ['link_anchor_1_x', 'link_anchor_1_y', 'link_anchor_2_x', 'link_anchor_2_y', 'onClick']; DragManager.StartDocumentDrag([this._ref.current!], dragData, pt[0], pt[1]); return true; diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx index f6d94ce05..e38a42b29 100644 --- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx +++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx @@ -11,7 +11,7 @@ import { Upload } from '../../../../server/SharedMediaTypes'; import { DocumentType } from '../../../documents/DocumentTypes'; import { Docs } from '../../../documents/Documents'; import { DocumentManager } from '../../../util/DocumentManager'; -import { DragManager } from '../../../util/DragManager'; +import { DragManager, dropActionType } from '../../../util/DragManager'; import { ScriptingGlobals } from '../../../util/ScriptingGlobals'; import { Presentation } from '../../../util/TrackMovements'; import { undoBatch } from '../../../util/UndoManager'; @@ -251,7 +251,7 @@ ScriptingGlobals.add(function resumeWorkspaceReplaying(value: Doc, _readOnly_: b ScriptingGlobals.add(function startRecordingDrag(value: { doc: Doc | string; e: React.PointerEvent }) { if (DocCast(value.doc)) { - DragManager.StartDocumentDrag([value.e.target as HTMLElement], new DragManager.DocumentDragData([DocCast(value.doc)], 'embed'), value.e.clientX, value.e.clientY); + DragManager.StartDocumentDrag([value.e.target as HTMLElement], new DragManager.DocumentDragData([DocCast(value.doc)], dropActionType.embed), value.e.clientX, value.e.clientY); value.e.preventDefault(); return true; } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 2d5239f06..4a1a51558 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -30,7 +30,7 @@ import { Docs, DocUtils } from '../../../documents/Documents'; import { CollectionViewType } from '../../../documents/DocumentTypes'; import { DictationManager } from '../../../util/DictationManager'; import { DocumentManager } from '../../../util/DocumentManager'; -import { DragManager } from '../../../util/DragManager'; +import { DragManager, dropActionType } from '../../../util/DragManager'; import { MakeTemplate } from '../../../util/DropConverter'; import { LinkManager } from '../../../util/LinkManager'; import { RTFMarkup } from '../../../util/RTFMarkup'; @@ -624,7 +624,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent Date: Wed, 6 Mar 2024 13:29:30 -0500 Subject: fixed plotly/mermaids loading from a new account --- src/client/documents/Documents.ts | 6 ++-- src/client/util/CurrentUserUtils.ts | 38 ++++++++++++---------- src/client/util/DropConverter.ts | 1 - src/client/views/DashboardView.tsx | 1 - .../collections/collectionFreeForm/MarqueeView.tsx | 1 - src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FontIconBox/FontIconBox.tsx | 4 +-- src/client/views/nodes/trails/PresBox.tsx | 8 ++--- src/fields/Doc.ts | 7 ++-- 9 files changed, 36 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index c9b5cb915..d41cd24d4 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -273,7 +273,7 @@ export class DocumentOptions { layout_hideResizeHandles?: BOOLt = new BoolInfo('whether to hide the resize handles when selected'); layout_hideLinkButton?: BOOLt = new BoolInfo('whether the blue link counter button should be hidden'); layout_hideDecorationTitle?: BOOLt = new BoolInfo('whether to suppress the document decortations title when selected'); - _layout_hideContextMenu?: BOOLt = new BoolInfo('whether the context menu can be shown'); + layout_hideContextMenu?: BOOLt = new BoolInfo('whether the context menu can be shown'); layout_borderRounding?: string; _layout_modificationDate?: DATEt = new DateInfo('last modification date of doc layout', false); _layout_nativeDimEditable?: BOOLt = new BoolInfo('native dimensions can be modified using document decoration reizers', false); @@ -286,7 +286,6 @@ export class DocumentOptions { _layout_currentTimecode?: NUMt = new NumInfo('the current timecode of a time-based document (e.g., current time of a video) value is in seconds', false); _layout_centered?: BOOLt = new BoolInfo('whether text should be vertically centered in Doc'); _layout_fitWidth?: BOOLt = new BoolInfo('whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)'); - _layout_fitContentsToBox?: BOOLt = new BoolInfo('whether a freeformview should zoom/scale to create a shrinkwrapped view of its content'); _layout_fieldKey?: STRt = new StrInfo('the field key containing the current layout definition', false); _layout_enableAltContentUI?: BOOLt = new BoolInfo('whether to show alternate content button'); _layout_showTitle?: string; // field name to display in header (:hover is an optional suffix) @@ -397,6 +396,7 @@ export class DocumentOptions { _freeform_panY?: NUMt = new NumInfo('vertical pan location of a freeform view'); _freeform_noAutoPan?: BOOLt = new BoolInfo('disables autopanning when this item is dragged'); _freeform_noZoom?: BOOLt = new BoolInfo('disables zooming (used by Pile docs)'); + _freeform_fitContentsToBox?: BOOLt = new BoolInfo('whether a freeformview should zoom/scale to create a shrinkwrapped view of its content'); //BUTTONS buttonText?: string; @@ -699,7 +699,7 @@ export namespace Docs { DocumentType.FONTICON, { layout: { view: FontIconBox, dataField: 'icon' }, - options: { defaultDoubleClick: 'ignore', waitForDoubleClickToClick: 'never', layout_hideLinkButton: true, _width: 40, _height: 40 }, + options: { defaultDoubleClick: 'ignore', waitForDoubleClickToClick: 'never', layout_hideContextMenu: true, layout_hideLinkButton: true, _width: 40, _height: 40 }, }, ], [ diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index d75c717c9..310613bc9 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -66,7 +66,7 @@ export class CurrentUserUtils { const userTemplates = DocListCast(userDocTemplates?.data).filter(doc => !Doc.IsSystem(doc)); const reqdOpts:DocumentOptions = { title: "User Tools", _xMargin: 0, _layout_showTitle: "title", _chromeHidden: true, hidden: false, - _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, isSystem: true, _forceActive: true, + _dragOnlyWithinContainer: true, layout_hideContextMenu: true, isSystem: true, _forceActive: true, _layout_autoHeight: true, _width: 500, _height: 300, _layout_fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true, }; const reqdScripts = { dropConverter : "convertToButtons(dragData)" }; @@ -235,7 +235,7 @@ export class CurrentUserUtils { MakeTemplate(Doc.GetProto(slide), true, "Untitled Slide View"); return slide; } - const plotlyView = (opts:DocumentOptions) => { + const plotlyApi = () => { var plotly = Doc.MyPublishedDocs.find(doc => doc.title === "@plotly"); if (!plotly) { const plotly = Docs.Create.TextDocument( @@ -244,6 +244,8 @@ export class CurrentUserUtils { , {title: "@plotly", title_custom: true, _layout_showTitle:"title", _width:300,_height:400}); Doc.AddToMyPublished(plotly); } + } + const plotlyView = (opts:DocumentOptions) => { const rtfield = new RichTextField(JSON.stringify( {doc: {type:"doc",content:[ {type:"code_block",content:[ @@ -269,10 +271,10 @@ export class CurrentUserUtils { slide[DocData].text = rtfield; slide[DocData].layout_textPainted = ``; slide[DocData]._type_collection = CollectionViewType.Freeform; - slide.onPaint = ScriptField.MakeScript(`toggleDetail(documentView, "textPainted", "")`); + slide.onPaint = ScriptField.MakeScript(`toggleDetail(documentView, "textPainted", "")`, {documentView:"any"}); return slide; } - const mermaidsView = (opts:DocumentOptions) => { + const mermaidsApi = () => { var mermaids = Doc.MyPublishedDocs.find(doc => doc.title === "@mermaids"); if (!mermaids) { const mermaids = Docs.Create.TextDocument( @@ -294,6 +296,8 @@ export class CurrentUserUtils { , {title: "@mermaids", title_custom: true, _layout_showTitle:"title", _width:300,_height:400}); Doc.AddToMyPublished(mermaids); } + } + const mermaidsView = (opts:DocumentOptions) => { const rtfield = new RichTextField(JSON.stringify( {doc: {type:"doc",content:[ {type:"code_block",content:[ @@ -321,9 +325,10 @@ pie title Minerals in my tap water slide[DocData].text = rtfield; slide[DocData].layout_textPainted = ``; slide[DocData]._type_collection = CollectionViewType.Freeform; - slide.onPaint = ScriptField.MakeScript(`toggleDetail(documentView, "textPainted", "")`); + slide.onPaint = ScriptField.MakeScript(`toggleDetail(documentView, "textPainted", "")`, {documentView:"any"}); return slide; } + const apis = [plotlyApi(), mermaidsApi()] const emptyThings:{key:string, // the field name where the empty thing will be stored opts:DocumentOptions, // the document options that are required for the empty thing funcs?:{[key:string]: any}, // computed fields that are rquired for the empth thing @@ -396,14 +401,14 @@ pie title Minerals in my tap water const creatorBtns = CurrentUserUtils.creatorBtnDescriptors(doc).map((reqdOpts) => { const btn = dragCreatorDoc ? DocListCast(dragCreatorDoc.data).find(doc => doc.title === reqdOpts.title): undefined; const opts:DocumentOptions = {...OmitKeys(reqdOpts, ["funcs", "scripts", "backgroundColor"]).omit, - _width: 60, _height: 60, _layout_hideContextMenu: true, _dragOnlyWithinContainer: true, + _width: 60, _height: 60, _dragOnlyWithinContainer: true, btnType: ButtonType.ToolButton, backgroundColor: reqdOpts.backgroundColor ?? Colors.DARK_GRAY, color: Colors.WHITE, isSystem: true, }; return DocUtils.AssignScripts(DocUtils.AssignOpts(btn, opts) ?? Docs.Create.FontIconDocument(opts), reqdOpts.scripts, reqdOpts.funcs); }); const reqdOpts:DocumentOptions = { - title: "Document Creators", _layout_showTitle: "title", _xMargin: 0, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, _chromeHidden: true, isSystem: true, + title: "Document Creators", _layout_showTitle: "title", _xMargin: 0, _dragOnlyWithinContainer: true, layout_hideContextMenu: true, _chromeHidden: true, isSystem: true, _layout_autoHeight: true, _width: 500, _height: 300, _layout_fitWidth: true, _columnWidth: 40, ignoreClick: true, _lockedPosition: true, _forceActive: true, childDragAction: dropActionType.embed }; @@ -441,7 +446,7 @@ pie title Minerals in my tap water const btnDoc = myLeftSidebarMenu ? DocListCast(myLeftSidebarMenu.data).find(doc => doc.title === title) : undefined; const reqdBtnOpts:DocumentOptions = { title, icon, target, toolTip, hidden, btnType: ButtonType.MenuButton, isSystem: true, undoIgnoreFields: new List(['height', 'data_columnHeaders']), dontRegisterView: true, - _width: 60, _height: 60, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, + _width: 60, _height: 60, _dragOnlyWithinContainer: true, }; return DocUtils.AssignScripts(DocUtils.AssignOpts(btnDoc, reqdBtnOpts) ?? Docs.Create.FontIconDocument(reqdBtnOpts), scripts, funcs); }); @@ -544,7 +549,7 @@ pie title Minerals in my tap water const reqdToolOps:DocumentOptions = { title: "My Tools", isSystem: true, ignoreClick: true, layout_boxShadow: "0 0", layout_explainer: "This is a palette of documents that can be created.", - _layout_showTitle: "title", _width: 500, _yMargin: 20, _lockedPosition: true, _forceActive: true, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, _chromeHidden: true, + _layout_showTitle: "title", _width: 500, _yMargin: 20, _lockedPosition: true, _forceActive: true, _dragOnlyWithinContainer: true, layout_hideContextMenu: true, _chromeHidden: true, }; return DocUtils.AssignDocField(doc, field, (opts, items) => Docs.Create.StackingDocument(items??[], opts), reqdToolOps, [creatorBtns, userBtns]); } @@ -555,7 +560,7 @@ pie title Minerals in my tap water const newDashboard = `createNewDashboard()`; - const reqdBtnOpts:DocumentOptions = { _forceActive: true, _width: 30, _height: 30, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, + const reqdBtnOpts:DocumentOptions = { _forceActive: true, _width: 30, _height: 30, _dragOnlyWithinContainer: true, title: "new Dash", btnType: ButtonType.ClickButton, toolTip: "Create new dashboard", buttonText: "New trail", icon: "plus", isSystem: true }; const reqdBtnScript = {onClick: newDashboard,} const newDashboardButton = DocUtils.AssignScripts(DocUtils.AssignOpts(DocCast(myDashboards?.layout_headerButton), reqdBtnOpts) ?? Docs.Create.FontIconDocument(reqdBtnOpts), reqdBtnScript); @@ -596,7 +601,7 @@ pie title Minerals in my tap water var myFilesystem = DocCast(doc[field]); const newFolderOpts: DocumentOptions = { - _forceActive: true, _dragOnlyWithinContainer: true, _embedContainer: Doc.MyFilesystem, _layout_hideContextMenu: true, _width: 30, _height: 30, undoIgnoreFields:new List(['treeView_SortCriterion']), + _forceActive: true, _dragOnlyWithinContainer: true, _embedContainer: Doc.MyFilesystem, _width: 30, _height: 30, undoIgnoreFields:new List(['treeView_SortCriterion']), title: "New folder", color: Colors.BLACK, btnType: ButtonType.ClickButton, toolTip: "Create new folder", buttonText: "New folder", icon: "folder-plus", isSystem: true }; const newFolderScript = { onClick: CollectionTreeView.AddTreeFunc}; @@ -624,7 +629,7 @@ pie title Minerals in my tap water const recentlyClosed = DocUtils.AssignDocField(doc, field, (opts) => Docs.Create.TreeDocument([], opts), reqdOpts); const clearAll = (target:string) => `getProto(${target}).data = new List([])`; - const clearBtnsOpts:DocumentOptions = { _width: 30, _height: 30, _forceActive: true, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, + const clearBtnsOpts:DocumentOptions = { _width: 30, _height: 30, _forceActive: true, _dragOnlyWithinContainer: true, layout_hideContextMenu: true, title: "Empty", target: recentlyClosed, btnType: ButtonType.ClickButton, color: Colors.BLACK, buttonText: "Empty", icon: "trash", isSystem: true, toolTip: "Empty recently closed",}; DocUtils.AssignDocField(recentlyClosed, "layout_headerButton", (opts) => Docs.Create.FontIconDocument(opts), clearBtnsOpts, undefined, {onClick: clearAll("this.target")}); @@ -658,8 +663,7 @@ pie title Minerals in my tap water }) static createToolButton = (opts: DocumentOptions) => Docs.Create.FontIconDocument({ - btnType: ButtonType.ToolButton, _layout_hideContextMenu: true, - _dropPropertiesToRemove: new List([ "_layout_hideContextMenu"]), + btnType: ButtonType.ToolButton, _dropPropertiesToRemove: new List([ "layout_hideContextMenu"]), /*_nativeWidth: 40, _nativeHeight: 40, */ _width: 40, _height: 40, isSystem: true, ...opts, }) @@ -804,7 +808,7 @@ pie title Minerals in my tap water _nativeWidth: params.width ?? 30, _width: params.width ?? 30, _height: 30, _nativeHeight: 30, linearBtnWidth: params.linearBtnWidth, toolType: params.toolType, expertMode: params.expertMode, - _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, _lockedPosition: true, + _dragOnlyWithinContainer: true, _lockedPosition: true, }; const reqdFuncs:{[key:string]:any} = { ...params.funcs, @@ -914,14 +918,14 @@ pie title Minerals in my tap water static setupImportSidebar(doc: Doc, field:string) { const reqdOpts:DocumentOptions = { title: "My Imports", _forceActive: true, _layout_showTitle: "title", childLayoutString: ImportElementBox.LayoutString('data'), - _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, childLimitHeight: 0, onClickScriptDisable:"never", + _dragOnlyWithinContainer: true, layout_hideContextMenu: true, childLimitHeight: 0, onClickScriptDisable:"never", childDragAction: dropActionType.copy, _layout_autoHeight: true, _yMargin: 50, _gridGap: 15, layout_boxShadow: "0 0", _lockedPosition: true, isSystem: true, _chromeHidden: true, dontRegisterView: true, layout_explainer: "This is where documents that are Imported into Dash will go." }; const myImports = DocUtils.AssignDocField(doc, field, (opts) => Docs.Create.MasonryDocument([], opts), reqdOpts, undefined, {onClick: "deselectAll()"}); const reqdBtnOpts:DocumentOptions = { _forceActive: true, toolTip: "Import from computer", - _width: 30, _height: 30, color: Colors.BLACK, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true, title: "Import", btnType: ButtonType.ClickButton, + _width: 30, _height: 30, color: Colors.BLACK, _dragOnlyWithinContainer: true, title: "Import", btnType: ButtonType.ClickButton, buttonText: "Import", icon: "upload", isSystem: true }; DocUtils.AssignDocField(myImports, "layout_headerButton", (opts) => Docs.Create.FontIconDocument(opts), reqdBtnOpts, undefined, { onClick: "importDocument()" }); return myImports; diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts index 54066d267..ba981145d 100644 --- a/src/client/util/DropConverter.ts +++ b/src/client/util/DropConverter.ts @@ -73,7 +73,6 @@ export function convertDropDataToButtons(data: DragManager.DocumentDragData) { _nativeHeight: 100, _width: 100, _height: 100, - _layout_hideContextMenu: true, backgroundColor: StrCast(doc.backgroundColor), title: StrCast(layoutDoc.title), btnType: ButtonType.ClickButton, diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx index 439d250de..146ac5b01 100644 --- a/src/client/views/DashboardView.tsx +++ b/src/client/views/DashboardView.tsx @@ -428,7 +428,6 @@ export class DashboardView extends ObservableReactComponent<{}> { _width: 30, _height: 30, _dragOnlyWithinContainer: true, - _layout_hideContextMenu: true, title: 'New trail', toolTip: 'Create new trail', color: Colors.BLACK, diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index d0e59180d..e22b83307 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -494,7 +494,6 @@ export class MarqueeView extends ObservableReactComponent { - if (e && this.layoutDoc._layout_hideContextMenu && Doc.noviceMode) { + if (e && this.layoutDoc.layout_hideContextMenu && Doc.noviceMode) { e.preventDefault(); e.stopPropagation(); //!this._props.isSelected(true) && SelectionManager.SelectView(this.DocumentView(), false); diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index 91b6de80b..d24c79b10 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -333,8 +333,8 @@ export class FontIconBox extends ViewBoxBaseComponent() { label={this.label} onPointerDown={e => setupMoveUpEvents(this, e, returnTrue, emptyFunction, (e, doubleTap) => { - !doubleTap && script.script.run({ this: this.Document, self: this.Document, value: !toggleStatus, _readOnly_: false }); - doubleTap && double.script.run({ this: this.Document, self: this.Document, value: !toggleStatus, _readOnly_: false }); + (!doubleTap || !double) && script.script.run({ this: this.Document, self: this.Document, value: !toggleStatus, _readOnly_: false }); + doubleTap && double && double.script.run({ this: this.Document, self: this.Document, value: !toggleStatus, _readOnly_: false }); }) } /> diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 918987034..0d4f9ec78 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -2223,10 +2223,10 @@ export class PresBox extends ViewBoxBaseComponent() { // prettier-ignore switch (layout) { case 'blank': return Docs.Create.FreeformDocument([], { title: input ? input : 'Blank slide', _width: 400, _height: 225, x, y }); - case 'title': return Docs.Create.FreeformDocument([title(), subtitle()], { title: input ? input : 'Title slide', _width: 400, _height: 225, _layout_fitContentsToBox: true, x, y }); - case 'header': return Docs.Create.FreeformDocument([header()], { title: input ? input : 'Section header', _width: 400, _height: 225, _layout_fitContentsToBox: true, x, y }); - case 'content': return Docs.Create.FreeformDocument([contentTitle(), content()], { title: input ? input : 'Title and content', _width: 400, _height: 225, _layout_fitContentsToBox: true, x, y }); - case 'twoColumns': return Docs.Create.FreeformDocument([contentTitle(), content1(), content2()], { title: input ? input : 'Title and two columns', _width: 400, _height: 225, _layout_fitContentsToBox: true, x, y }) + case 'title': return Docs.Create.FreeformDocument([title(), subtitle()], { title: input ? input : 'Title slide', _width: 400, _height: 225, _freeform_fitContentsToBox: true, x, y }); + case 'header': return Docs.Create.FreeformDocument([header()], { title: input ? input : 'Section header', _width: 400, _height: 225, _freeform_fitContentsToBox: true, x, y }); + case 'content': return Docs.Create.FreeformDocument([contentTitle(), content()], { title: input ? input : 'Title and content', _width: 400, _height: 225, _freeform_fitContentsToBox: true, x, y }); + case 'twoColumns': return Docs.Create.FreeformDocument([contentTitle(), content1(), content2()], { title: input ? input : 'Title and two columns', _width: 400, _height: 225, _freeform_fitContentsToBox: true, x, y }) } }; diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 1df9d80a1..be1af3e6c 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -172,7 +172,7 @@ export class Doc extends RefField { public static get MyTrails() { return DocCast(Doc.ActiveDashboard?.myTrails); } // prettier-ignore public static get MyCalendars() { return DocCast(Doc.ActiveDashboard?.myCalendars); } // prettier-ignore public static get MyOverlayDocs() { return DocListCast(Doc.ActiveDashboard?.myOverlayDocs ?? DocCast(Doc.UserDoc().myOverlayDocs)?.data); } // prettier-ignore - public static get MyPublishedDocs() { return DocListCast(Doc.ActiveDashboard?.myPublishedDocs ?? DocCast(Doc.UserDoc().myPublishedDocs)?.data); } // prettier-ignore + 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 MyImports() { return DocCast(Doc.UserDoc().myImports); } // prettier-ignore @@ -583,6 +583,9 @@ export namespace Doc { Doc.RemoveDocFromList(doc[DocData], 'proto_embeddings', embedding); } export function AddEmbedding(doc: Doc, embedding: Doc) { + if (embedding === null) { + console.log('WHAT?'); + } Doc.AddDocToList(doc[DocData], 'proto_embeddings', embedding, undefined, undefined, undefined, undefined, undefined, true); } export function GetEmbeddings(doc: Doc) { @@ -607,7 +610,7 @@ export namespace Doc { const dataDoc = doc[DocData]; const availableEmbeddings = Doc.GetEmbeddings(dataDoc); const bestEmbedding = [...(dataDoc !== doc ? [doc] : []), ...availableEmbeddings].find(doc => !doc.embedContainer && doc.author === Doc.CurrentUserEmail); - bestEmbedding && Doc.AddDocToList(dataDoc, 'proto_embeddings', doc, undefined, undefined, undefined, undefined, undefined, true); + bestEmbedding && Doc.AddEmbedding(doc, doc); return bestEmbedding ?? Doc.MakeEmbedding(doc); } -- cgit v1.2.3-70-g09d2 From ecf3bf771156b3935d8c87f1fbaf5c4e294c6aee Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 6 Mar 2024 13:36:45 -0500 Subject: fixed backgroundColors to be set on dataDoc in infoUI --- .../collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx index 8628ca3c3..43b877705 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx @@ -34,7 +34,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent (this._currState = val)); } // prettier-ignore componentWillUnmount(): void { - this._props.Freeform.layoutDoc.backgroundColor = this._originalbackground; + this._props.Freeform.dataDoc.backgroundColor = this._originalbackground; } setCurrState = (state: infoState) => { @@ -45,9 +45,9 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent { - this._originalbackground = StrCast(this._props.Freeform.layoutDoc.backgroundColor); + this._originalbackground = StrCast(this._props.Freeform.dataDoc.backgroundColor); // state entry functions - const setBackground = (colour: string) => () => (this._props.Freeform.layoutDoc.backgroundColor = colour); + const setBackground = (colour: string) => () => (this._props.Freeform.dataDoc.backgroundColor = colour); const setOpacity = (opacity: number) => () => (this._props.Freeform.layoutDoc.opacity = opacity); // arc transition trigger conditions const firstDoc = () => (this._props.Freeform.childDocs.length ? this._props.Freeform.childDocs[0] : undefined); -- cgit v1.2.3-70-g09d2 From b938ac2909290bd5dd11eeb0a0056f4679dbb25e Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 7 Mar 2024 10:24:56 -0500 Subject: fixed several things related to templates for labels (used as icons) and FontIconboxes. Also made labels non uniformly resizable . --- src/client/documents/Documents.ts | 16 +++++++--------- src/client/util/CurrentUserUtils.ts | 16 +++++++++------- src/client/views/DocumentDecorations.tsx | 10 +++++----- .../collectionFreeForm/CollectionFreeFormView.tsx | 12 ++++++++---- src/client/views/nodes/FontIconBox/FontIconBox.tsx | 8 ++++++-- src/client/views/nodes/LabelBox.tsx | 10 +++------- 6 files changed, 38 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index d41cd24d4..b7d8222b9 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -277,8 +277,8 @@ export class DocumentOptions { layout_borderRounding?: string; _layout_modificationDate?: DATEt = new DateInfo('last modification date of doc layout', false); _layout_nativeDimEditable?: BOOLt = new BoolInfo('native dimensions can be modified using document decoration reizers', false); - _layout_reflowVertical?: BOOLt = new BoolInfo('native height can be changed independent of width by dragging decoration resizers'); - _layout_reflowHorizontal?: BOOLt = new BoolInfo('whether a doc with a native size can be horizonally resized, causing some form of reflow'); + _layout_reflowVertical?: BOOLt = new BoolInfo('permit vertical resizing with content "reflow"'); + _layout_reflowHorizontal?: BOOLt = new BoolInfo('permit horizontal resizing with content reflow'); layout_boxShadow?: string; // box-shadow css string OR "standard" to use dash standard box shadow layout_maxShown?: NUMt = new NumInfo('maximum number of children to display at one time (see multicolumnview)'); _layout_autoHeight?: BOOLt = new BoolInfo('whether document automatically resizes vertically to display contents'); @@ -317,7 +317,6 @@ export class DocumentOptions { _label_minFontSize?: NUMt = new NumInfo('minimum font size for labelBoxes', false); _label_maxFontSize?: NUMt = new NumInfo('maximum font size for labelBoxes', false); stroke_width?: NUMt = new NumInfo('width of an ink stroke', false); - icon_label?: STRt = new StrInfo('label to use for a fontIcon doc (otherwise, the title is used)', false); mediaState?: STRt = new StrInfo(`status of audio/video media document: ${media_state.PendingRecording}, ${media_state.Recording}, ${media_state.Paused}, ${media_state.Playing}`, false); recording?: BOOLt = new BoolInfo('whether WebCam is recording or not'); slides?: DOCt = new DocInfo('presentation slide associated with video recording (bcz: should be renamed!!)'); @@ -652,8 +651,8 @@ export namespace Docs { [ DocumentType.LABEL, { - layout: { view: LabelBox, dataField: defaultDataKey }, - options: { _singleLine: true }, + layout: { view: LabelBox, dataField: 'title' }, + options: { _singleLine: true, layout_nativeDimEditable: true, layout_reflowHorizontal: true, layout_reflowVertical: true }, }, ], [ @@ -684,8 +683,8 @@ export namespace Docs { [ DocumentType.BUTTON, { - layout: { view: LabelBox, dataField: 'onClick' }, - options: {}, + layout: { view: LabelBox, dataField: 'title' }, + options: { layout_nativeDimEditable: true, layout_reflowHorizontal: true, layout_reflowVertical: true }, }, ], [ @@ -1881,8 +1880,7 @@ export namespace DocUtils { const hasContextAnchor = LinkManager.Links(doc).some(l => (l.link_anchor_2 === doc && Cast(l.link_anchor_1, Doc, null)?.annotationOn === context) || (l.link_anchor_1 === doc && Cast(l.link_anchor_2, Doc, null)?.annotationOn === context)); if (context && !hasContextAnchor && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) { const pushpin = Docs.Create.FontIconDocument({ - title: 'pushpin', - icon_label: '', + title: '', annotationOn: Cast(doc.annotationOn, Doc, null), followLinkToggle: true, icon: 'map-pin', diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 310613bc9..cfba003fc 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -22,7 +22,7 @@ import { CollectionTreeView, TreeViewType } from "../views/collections/Collectio import { Colors } from "../views/global/globalEnums"; import { media_state } from "../views/nodes/AudioBox"; import { OpenWhere } from "../views/nodes/DocumentView"; -import { ButtonType } from "../views/nodes/FontIconBox/FontIconBox"; +import { ButtonType, FontIconBox } from "../views/nodes/FontIconBox/FontIconBox"; import { ImportElementBox } from "../views/nodes/importBox/ImportElementBox"; import { DragManager, dropActionType } from "./DragManager"; import { MakeTemplate } from "./DropConverter"; @@ -32,6 +32,8 @@ import { ScriptingGlobals } from "./ScriptingGlobals"; import { ColorScheme } from "./SettingsManager"; import { SnappingManager } from "./SnappingManager"; import { UndoManager } from "./UndoManager"; +import { LabelBox } from "../views/nodes/LabelBox"; +import { ImageBox } from "../views/nodes/ImageBox"; interface Button { // DocumentOptions fields a button can set @@ -156,14 +158,14 @@ export class CurrentUserUtils { } const allopts = {isSystem: true, onClickScriptDisable: "never", ...opts}; return DocUtils.AssignScripts( (curIcon?.iconTemplate === opts.iconTemplate ? - DocUtils.AssignOpts(curIcon, allopts):undefined) ?? ((templateIconsDoc[iconFieldName] = MakeTemplate(creator(allopts), true, iconFieldName, templateField))), + DocUtils.AssignOpts(curIcon, allopts):undefined) ?? ((templateIconsDoc[iconFieldName] = MakeTemplate(creator(allopts, templateField), true, iconFieldName, templateField))), {onClick:"deiconifyView(documentView)", onDoubleClick: "deiconifyViewToLightbox(documentView)", }); }; - const labelBox = (opts: DocumentOptions, data?:string) => Docs.Create.LabelDocument({ - textTransform: "unset", letterSpacing: "unset", _singleLine: false, _label_minFontSize: 14, _label_maxFontSize: 14, layout_borderRounding: "5px", _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, ...opts + const labelBox = (opts: DocumentOptions, fieldKey:string) => Docs.Create.LabelDocument({ + layout: LabelBox.LayoutString(fieldKey), textTransform: "unset", letterSpacing: "unset", _singleLine: false, _label_minFontSize: 14, _label_maxFontSize: 14, layout_borderRounding: "5px", _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, ...opts }); - const imageBox = (opts: DocumentOptions, url?:string) => Docs.Create.ImageDocument(url ?? "http://www.cs.brown.edu/~bcz/noImage.png", { "icon_nativeWidth": 360 / 4, "icon_nativeHeight": 270 / 4, iconTemplate:DocumentType.IMG, _width: 360 / 4, _height: 270 / 4, _layout_showTitle: "title", ...opts }); - const fontBox = (opts:DocumentOptions, data?:string) => Docs.Create.FontIconDocument({ _nativeHeight: 30, _nativeWidth: 30, _width: 30, _height: 30, ...opts }); + const imageBox = (opts: DocumentOptions, fieldKey:string) => Docs.Create.ImageDocument( "http://www.cs.brown.edu/~bcz/noImage.png", { layout:ImageBox.LayoutString(fieldKey), "icon_nativeWidth": 360 / 4, "icon_nativeHeight": 270 / 4, iconTemplate:DocumentType.IMG, _width: 360 / 4, _height: 270 / 4, _layout_showTitle: "title", ...opts }); + const fontBox = (opts:DocumentOptions, fieldKey:string) => Docs.Create.FontIconDocument({ layout:FontIconBox.LayoutString(fieldKey), _nativeHeight: 30, _nativeWidth: 30, _width: 30, _height: 30, ...opts }); const iconTemplates = [ makeIconTemplate(undefined, "title", { iconTemplate:DocumentType.LABEL, backgroundColor: "dimgray"}), makeIconTemplate(DocumentType.AUDIO, "title", { iconTemplate:DocumentType.LABEL, backgroundColor: "lightgreen"}), @@ -174,7 +176,7 @@ export class CurrentUserUtils { makeIconTemplate(DocumentType.COL, "icon", { iconTemplate:DocumentType.IMG}), makeIconTemplate(DocumentType.COL, "icon", { iconTemplate:DocumentType.IMG}), makeIconTemplate(DocumentType.VID, "icon", { iconTemplate:DocumentType.IMG}), - makeIconTemplate(DocumentType.BUTTON,"data", { iconTemplate:DocumentType.FONTICON}), + makeIconTemplate(DocumentType.BUTTON,"title", { iconTemplate:DocumentType.FONTICON}), //nasty hack .. templates are looked up exclusively by type -- but we want a template for a document with a certain field (transcription) .. so this hack and the companion hack in createCustomView does this for now makeIconTemplate("transcription" as any, "transcription", { iconTemplate:DocumentType.LABEL, backgroundColor: "orange" }), //makeIconTemplate(DocumentType.PDF, "icon", {iconTemplate:DocumentType.IMG}, (opts) => imageBox("http://www.cs.brown.edu/~bcz/noImage.png", opts)) diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 87ee962a0..2fb9f0fc1 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -323,7 +323,7 @@ export class DocumentDecorations extends ObservableReactComponent { const docMax = Math.min(NumCast(doc.width) / 2, NumCast(doc.height) / 2); const radius = Math.min(1, dist / maxDist) * docMax; // set radius based on ratio of drag distance to half diagonal distance of bounding box - doc.layout_borderRounding = `${radius}px`; + doc._layout_borderRounding = `${radius}px`; }); return false; }, @@ -533,9 +533,9 @@ export class DocumentDecorations extends ObservableReactComponent docCurveTVal) { const localStartTVal = startSegmentT - Math.floor(i / 4); t !== (localStartTVal < 0 ? 0 : localStartTVal) && segment.push(inkSegment.split(localStartTVal < 0 ? 0 : localStartTVal, t)); - segment.length && segments.push(segment); + if (segment.length && (Math.abs(segment[0].points[0].x - segment[0].points.lastElement().x) > 0.5 || Math.abs(segment[0].points[0].y - segment[0].points.lastElement().y) > 0.5)) segments.push(segment); } // start a new segment from the intersection t value - segment = tVals.length - 1 === index ? [inkSegment.split(t).right] : []; + if (tVals.length - 1 === index) { + const split = inkSegment.split(t).right; + if (split && (Math.abs(split.points[0].x - split.points.lastElement().x) > 0.5 || Math.abs(split.points[0].y - split.points.lastElement().y) > 0.5)) segment = [split]; + else segment = []; + } else segment = []; startSegmentT = docCurveTVal; }); } else { @@ -1647,7 +1651,7 @@ export class CollectionFreeFormView extends CollectionSubView (this._showAnimTimeline = !this._showAnimTimeline)), icon: 'eye' }); - this._props.renderDepth && optionItems.push({ description: 'Use Background Color as Default', event: () => (Cast(Doc.UserDoc().emptyCollection, Doc, null)._backgroundColor = StrCast(this.layoutDoc._backgroundColor)), icon: 'palette' }); + this._props.renderDepth && optionItems.push({ description: 'Use Background Color as Default', event: () => (Cast(Doc.UserDoc().emptyCollection, Doc, null).backgroundColor = StrCast(this.layoutDoc.backgroundColor)), icon: 'palette' }); this._props.renderDepth && optionItems.push({ description: 'Fit Content Once', event: this.fitContentOnce, icon: 'object-group' }); if (!Doc.noviceMode) { optionItems.push({ description: (!Doc.NativeWidth(this.layoutDoc) || !Doc.NativeHeight(this.layoutDoc) ? 'Freeze' : 'Unfreeze') + ' Aspect', event: this.toggleNativeDimensions, icon: 'snowflake' }); diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index d24c79b10..46043eefb 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -81,9 +81,13 @@ export class FontIconBox extends ViewBoxBaseComponent() { } }; - // Determining UI Specs + /** + * this chooses the appropriate title for the label + * if the Document is a template, then we use the title of the data doc that it renders + * otherwise, we use the Document's title itself. + */ @computed get label() { - return StrCast(this.dataDoc.icon_label, StrCast(this.Document.title)); + return StrCast(this.Document.isTemplateDoc ? this.dataDoc.title : this.Document.title); } Icon = (color: string, iconFalse?: boolean) => { let icon; diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx index fd3074a88..be20b5934 100644 --- a/src/client/views/nodes/LabelBox.tsx +++ b/src/client/views/nodes/LabelBox.tsx @@ -17,12 +17,8 @@ import './LabelBox.scss'; import { PinProps, PresBox } from './trails'; import { Docs } from '../../documents/Documents'; -export interface LabelBoxProps extends FieldViewProps { - label?: string; -} - @observer -export class LabelBox extends ViewBoxBaseComponent() { +export class LabelBox extends ViewBoxBaseComponent() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LabelBox, fieldKey); } @@ -32,7 +28,7 @@ export class LabelBox extends ViewBoxBaseComponent() { private dropDisposer?: DragManager.DragDropDisposer; private _timeout: any; - constructor(props: LabelBoxProps) { + constructor(props: FieldViewProps) { super(props); makeObservable(this); } @@ -45,7 +41,7 @@ export class LabelBox extends ViewBoxBaseComponent() { } @computed get Title() { - return this.dataDoc.title_custom ? StrCast(this.Document.title) : this._props.label ? this._props.label : Field.toString(this.dataDoc[this.fieldKey] as Field); + return Field.toString(this.dataDoc[this.fieldKey] as Field); } protected createDropTarget = (ele: HTMLDivElement) => { -- cgit v1.2.3-70-g09d2 From 7164179264d057986bfd5f303c61248f1c189406 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 8 Mar 2024 16:17:02 -0500 Subject: cleaned up MakeTemplate api and currentUserUtils templates for clicks etc. --- src/client/documents/Documents.ts | 9 ++++ src/client/util/CurrentUserUtils.ts | 35 ++++++++-------- src/client/util/DropConverter.ts | 48 ++++++++++++++-------- src/client/views/collections/TreeView.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 4 +- 5 files changed, 60 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index b7d8222b9..e6969d1f3 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1024,6 +1024,15 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.PRES), new List(), options); } + /** + * Creates a Doc to edit a script and write the compiled script into the specified field. + * Typically, this would be used to create a template that can then be applied to some other Doc + * in order to customize a behavior, such as onClick. + * @param script + * @param options + * @param fieldKey the field that the compiled script is written into. + * @returns the Scripting Doc + */ export function ScriptingDocument(script: Opt | null, options: DocumentOptions = {}, fieldKey?: string) { return InstanceFromProto(Prototypes.get(DocumentType.SCRIPTING), script ? script : undefined, { ...options, layout: fieldKey ? ScriptingBox.LayoutString(fieldKey) : undefined }); } diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index cfba003fc..564a46514 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -105,9 +105,12 @@ export class CurrentUserUtils { { opts: { title: "onCheckedClick"}, script: "console.log(heading, checked, containingTreeView)"}, ]; const reqdClickList = reqdTempOpts.map(opts => { + const title = opts.opts.title?.toString(); const allOpts = {...reqdClickOpts, ...opts.opts}; - const clickDoc = tempClicks ? DocListCast(tempClicks.data).find(doc => doc.title === opts.opts.title): undefined; - return DocUtils.AssignOpts(clickDoc, allOpts) ?? MakeTemplate(Docs.Create.ScriptingDocument(ScriptField.MakeScript(opts.script, {heading:Doc.name, checked:"boolean", containingTreeView:Doc.name}), allOpts), true, opts.opts.title?.toString()); + const clickDoc = tempClicks ? DocListCast(tempClicks.data).find(doc => doc.title === title): undefined; + const script = ScriptField.MakeScript(opts.script, {heading:Doc.name, checked:"boolean", containingTreeView:Doc.name}); + const scriptDoc = Docs.Create.ScriptingDocument(script, allOpts, title) + return DocUtils.AssignOpts(clickDoc, allOpts) ?? MakeTemplate(scriptDoc); }); const reqdOpts:DocumentOptions = {title: "click editor templates", _height:75, isSystem: true}; @@ -118,13 +121,13 @@ export class CurrentUserUtils { static setupNoteTemplates(doc: Doc, field="template_notes") { const tempNotes = DocCast(doc[field]); const reqdTempOpts:DocumentOptions[] = [ - { noteType: "Postit", backgroundColor: "yellow", icon: "sticky-note"}, - { noteType: "Idea", backgroundColor: "pink", icon: "lightbulb" }, - { noteType: "Topic", backgroundColor: "lightblue", icon: "book-open" }]; + { title: "Postit", backgroundColor: "yellow", icon: "sticky-note"}, + { title: "Idea", backgroundColor: "pink", icon: "lightbulb" }, + { title: "Topic", backgroundColor: "lightblue", icon: "book-open" }]; const reqdNoteList = reqdTempOpts.map(opts => { - const reqdOpts = {...opts, isSystem:true, title: "text", width:200, layout_autoHeight: true, layout_fitWidth: true}; - const noteType = tempNotes ? DocListCast(tempNotes.data).find(doc => doc.noteType === opts.noteType): undefined; - return DocUtils.AssignOpts(noteType, reqdOpts) ?? MakeTemplate(Docs.Create.TextDocument("",reqdOpts), true, opts.noteType??"Note"); + const reqdOpts = {...opts, isSystem:true, width:200, layout_autoHeight: true, layout_fitWidth: true}; + const noteTemp = tempNotes ? DocListCast(tempNotes.data).find(doc => doc.title === opts.title): undefined; + return DocUtils.AssignOpts(noteTemp, reqdOpts) ?? MakeTemplate(Docs.Create.TextDocument("",reqdOpts)); }); const reqdOpts:DocumentOptions = { title: "Note Layouts", _height: 75, isSystem: true }; @@ -149,16 +152,16 @@ export class CurrentUserUtils { const templateIconsDoc = DocUtils.AssignOpts(DocCast(doc[field]), reqdOpts) ?? (doc[field] = Docs.Create.TreeDocument([], reqdOpts)); const makeIconTemplate = (type: DocumentType | undefined, templateField: string, opts:DocumentOptions) => { - const iconFieldName = "icon" + (type ? "_" + type : ""); - const curIcon = DocCast(templateIconsDoc[iconFieldName]); + const title = "icon" + (type ? "_" + type : ""); + const curIcon = DocCast(templateIconsDoc[title]); let creator = labelBox; switch (opts.iconTemplate) { case DocumentType.IMG : creator = imageBox; break; case DocumentType.FONTICON: creator = fontBox; break; } - const allopts = {isSystem: true, onClickScriptDisable: "never", ...opts}; + const allopts = {isSystem: true, onClickScriptDisable: "never", ...opts, title}; return DocUtils.AssignScripts( (curIcon?.iconTemplate === opts.iconTemplate ? - DocUtils.AssignOpts(curIcon, allopts):undefined) ?? ((templateIconsDoc[iconFieldName] = MakeTemplate(creator(allopts, templateField), true, iconFieldName, templateField))), + DocUtils.AssignOpts(curIcon, allopts):undefined) ?? ((templateIconsDoc[title] = MakeTemplate(creator(allopts, templateField)))), {onClick:"deiconifyView(documentView)", onDoubleClick: "deiconifyViewToLightbox(documentView)", }); }; const labelBox = (opts: DocumentOptions, fieldKey:string) => Docs.Create.LabelDocument({ @@ -211,7 +214,7 @@ export class CurrentUserUtils { }; const headerBtnHgt = 10; const headerTemplate = (opts:DocumentOptions) => { - const header = Docs.Create.RTFDocument(new RichTextField(JSON.stringify(json), ""), { ...opts, title: "text", + const header = Docs.Create.RTFDocument(new RichTextField(JSON.stringify(json), ""), { ...opts, title: "Untitled Header", layout: "" + ` ` + @@ -224,7 +227,7 @@ export class CurrentUserUtils { // " " + // " " + // "
"; - MakeTemplate(Doc.GetProto(header), true, "Untitled Header"); + MakeTemplate(Doc.GetProto(header)); return header; } const slideView = (opts:DocumentOptions) => { @@ -232,9 +235,9 @@ export class CurrentUserUtils { [ Docs.Create.MulticolumnDocument([], { title: "hero", _height: 200, isSystem: true }), Docs.Create.TextDocument("", { title: "text", _layout_fitWidth:true, _height: 100, isSystem: true, _text_fontFamily: StrCast(Doc.UserDoc().fontFamily), _text_fontSize: StrCast(Doc.UserDoc().fontSize) }) - ], opts); + ], {...opts, title: "Untitled Slide View"}); - MakeTemplate(Doc.GetProto(slide), true, "Untitled Slide View"); + MakeTemplate(Doc.GetProto(slide)); return slide; } const plotlyApi = () => { diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts index ba981145d..3df3e36c6 100644 --- a/src/client/util/DropConverter.ts +++ b/src/client/util/DropConverter.ts @@ -12,43 +12,55 @@ import { ButtonType, FontIconBox } from '../views/nodes/FontIconBox/FontIconBox' import { DragManager } from './DragManager'; import { ScriptingGlobals } from './ScriptingGlobals'; -export function MakeTemplate(doc: Doc, first: boolean = true, rename: Opt = undefined, templateField: string = '') { - if (templateField) doc[DocData].title = templateField; /// the title determines which field is being templated - doc.isTemplateDoc = makeTemplate(doc, first, rename); +/** + * Converts a Doc to a render template that can be applied to other Docs to customize how they render while + * still using the other Doc as the backing data store (ie, dataDoc). During rendering, if a layout Doc is provided + * with 'isTemplateDoc' set, then the layout Doc is treated as a template for the rendered Doc. The template Doc is + * "expanded" to create an template instance for the rendered Doc. + * + * + * @param doc the doc to convert to a template + * @returns 'doc' + */ +export function MakeTemplate(doc: Doc) { + doc.isTemplateDoc = makeTemplate(doc, true); return doc; } -// -// converts 'doc' into a template that can be used to render other documents. -// the title of doc is used to determine which field is being templated, so -// passing a value for 'rename' allows the doc to be given a meangingful name -// after it has been converted to -function makeTemplate(doc: Doc, first: boolean = true, rename: Opt = undefined): boolean { + +/** + * Recursively converts 'doc' into a template that can be used to render other documents. + * + * For recurive Docs in the template, their target fieldKey is defined by their title, + * not by whatever fieldKey they used in their layout. + * @param doc + * @param first whether this is the topmost root of the recursive template + * @returns whether a template was successfully created + */ +function makeTemplate(doc: Doc, first: boolean = true): boolean { const layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateForField ? doc.layout : doc; if (layoutDoc.layout instanceof Doc) { - // its already a template - return true; + return true; // its already a template } const layout = StrCast(layoutDoc.layout).match(/fieldKey={'[^']*'}/)![0]; const fieldKey = layout.replace("fieldKey={'", '').replace(/'}$/, ''); const docs = DocListCast(layoutDoc[fieldKey]); - let any = false; + let isTemplate = false; docs.forEach(d => { if (!StrCast(d.title).startsWith('-')) { - any = Doc.MakeMetadataFieldTemplate(d, layoutDoc[DocData]) || any; + isTemplate = Doc.MakeMetadataFieldTemplate(d, layoutDoc[DocData]) || isTemplate; } else if (d.type === DocumentType.COL || d.data instanceof RichTextField) { - any = makeTemplate(d, false) || any; + isTemplate = makeTemplate(d, false) || isTemplate; } }); if (first && !docs.length) { // bcz: feels hacky : if the root level document has items, it's not a field template - any = Doc.MakeMetadataFieldTemplate(doc, layoutDoc[DocData], true) || any; + isTemplate = Doc.MakeMetadataFieldTemplate(doc, layoutDoc[DocData], true) || isTemplate; } else if (layoutDoc[fieldKey] instanceof RichTextField || layoutDoc[fieldKey] instanceof ImageField) { if (!StrCast(layoutDoc.title).startsWith('-')) { - any = Doc.MakeMetadataFieldTemplate(layoutDoc, layoutDoc[DocData], true); + isTemplate = Doc.MakeMetadataFieldTemplate(layoutDoc, layoutDoc[DocData], true); } } - rename && (doc.title = rename); - return any; + return isTemplate; } export function convertDropDataToButtons(data: DragManager.DocumentDragData) { data?.draggedDocuments.map((doc, i) => { diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 285a789e6..0c0e49411 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -631,7 +631,7 @@ export class TreeView extends ObservableReactComponent { } return (
- {!docs?.length || this._props.AddToMap /* hack to identify pres box trees */ ? null : ( + {!docs?.length || this.treeView.outlineMode || this._props.AddToMap /* hack to identify pres box trees */ ? null : (
{ if (!this.layoutDoc.isTemplateDoc) { - const title = StrCast(this.Document.title); - this.Document.title = 'text'; - MakeTemplate(this.Document, true, title); + MakeTemplate(this.Document); } Doc.UserDoc().defaultTextLayout = new PrefetchProxy(this.Document); Doc.AddDocToList(Cast(Doc.UserDoc().template_notes, Doc, null), 'data', this.Document); -- cgit v1.2.3-70-g09d2 From f1ed1cff137c06afc4d4db8a8778f7827404889b Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 9 Mar 2024 19:05:30 -0500 Subject: fixed up default text that uses a template to process an initial carriage return properly. fixed text with inherited templates to be able to show fields with a default dashField value from template that can be overidden on instance. --- src/client/documents/Documents.ts | 11 +++--- src/client/views/MarqueeAnnotator.tsx | 4 +-- src/client/views/PreviewCursor.tsx | 2 +- src/client/views/collections/TreeView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 36 +++++++++++-------- .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- .../collectionSchema/SchemaTableCell.tsx | 2 +- src/client/views/nodes/MapBox/MapBox.tsx | 4 +-- .../views/nodes/MapboxMapBox/MapboxContainer.tsx | 4 +-- .../views/nodes/formattedText/FormattedTextBox.tsx | 40 ++++++++++------------ 10 files changed, 55 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e6969d1f3..7a3b965fe 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -3,7 +3,7 @@ import { action, reaction, runInAction } from 'mobx'; import { basename } from 'path'; import { DateField } from '../../fields/DateField'; import { Doc, DocListCast, Field, LinkedTo, Opt, StrListCast, updateCachedAcls } from '../../fields/Doc'; -import { Initializing } from '../../fields/DocSymbols'; +import { DocData, Initializing } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; import { HtmlField } from '../../fields/HtmlField'; import { InkField, PointData } from '../../fields/InkField'; @@ -1981,10 +1981,8 @@ export namespace DocUtils { } } - export function GetNewTextDoc(title: string, x: number, y: number, width?: number, height?: number, noMargins?: boolean, annotationOn?: Doc, backgroundColor?: string) { + export function GetNewTextDoc(title: string, x: number, y: number, width?: number, height?: number, annotationOn?: Doc, backgroundColor?: string) { const tbox = Docs.Create.TextDocument('', { - _xMargin: noMargins ? 0 : undefined, - _yMargin: noMargins ? 0 : undefined, annotationOn, backgroundColor, _width: width || 200, @@ -1997,11 +1995,14 @@ export namespace DocUtils { _layout_enableAltContentUI: BoolCast(Doc.UserDoc().defaultToFlashcards), title, }); + const template = Doc.UserDoc().defaultTextLayout; if (template instanceof Doc) { + // if a default text template is specified tbox._width = NumCast(template._width); tbox.layout_fieldKey = 'layout_' + StrCast(template.title); - Doc.GetProto(tbox)[StrCast(tbox.layout_fieldKey)] = template; + Doc.GetProto(tbox)[StrCast(tbox.layout_fieldKey)] = template; // set the text doc's layout to render with the text template + tbox[DocData].proto = template; // and also set the text doc to inherit from the template (this allows the template to specify default field values) } return tbox; } diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index a4303c3aa..f59042b04 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -88,7 +88,7 @@ export class MarqueeAnnotator extends ObservableReactComponent this.highlight(this.props.highlightDragSrcColor ?? 'rgba(173, 216, 230, 0.75)', true, undefined, true); // hyperlink color const targetCreator = (annotationOn: Doc | undefined) => { - const target = DocUtils.GetNewTextDoc('Note linked to ' + this.props.Document.title, 0, 0, 100, 100, undefined, annotationOn, 'yellow'); + const target = DocUtils.GetNewTextDoc('Note linked to ' + this.props.Document.title, 0, 0, 100, 100, annotationOn, 'yellow'); FormattedTextBox.SetSelectOnLoad(target); return target; }; diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 456b753b4..a94c18295 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -85,7 +85,7 @@ export class PreviewCursor extends ObservableReactComponent<{}> { } else { FormattedTextBox.PasteOnLoad = e; if (e.clipboardData.getData('dash/pdfAnchor')) e.preventDefault(); - UndoManager.RunInBatch(() => this._addLiveTextDoc?.(DocUtils.GetNewTextDoc('', newPoint[0], newPoint[1], 500, undefined, undefined, undefined)), 'paste'); + UndoManager.RunInBatch(() => this._addLiveTextDoc?.(DocUtils.GetNewTextDoc('', newPoint[0], newPoint[1], 500, undefined, undefined)), 'paste'); } } //pasting in images diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 0c0e49411..c6bbcb0a5 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -884,7 +884,7 @@ export class TreeView extends ObservableReactComponent { // prettier-ignore switch (property.split(':')[0]) { case StyleProp.Opacity: return this.treeView.outlineMode ? undefined : 1; - case StyleProp.BackgroundColor: return this.selected ? '#7089bb' : StrCast(doc._backgroundColor, StrCast(doc.backgroundColor)); + case StyleProp.BackgroundColor: return this.selected ? '#7089bb' : undefined;//StrCast(doc._backgroundColor, StrCast(doc.backgroundColor)); case StyleProp.Highlighting: if (this.treeView.outlineMode) return undefined; case StyleProp.BoxShadow: return undefined; case StyleProp.DocContents: diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 4eb946939..9500b918a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -30,7 +30,7 @@ import { SelectionManager } from '../../../util/SelectionManager'; import { freeformScrollMode } from '../../../util/SettingsManager'; import { SnappingManager } from '../../../util/SnappingManager'; import { Transform } from '../../../util/Transform'; -import { undoBatch, UndoManager } from '../../../util/UndoManager'; +import { undoable, undoBatch, UndoManager } from '../../../util/UndoManager'; import { Timeline } from '../../animationtimeline/Timeline'; import { ContextMenu } from '../../ContextMenu'; import { GestureOverlay } from '../../GestureOverlay'; @@ -1146,23 +1146,29 @@ export class CollectionFreeFormView extends CollectionSubView this._props.isContentActive(); - @undoBatch + /** + * Create a new text note of the same style as the one being typed into. + * If the text doc is be part of a larger templated doc, the new Doc will be a copy of the templated Doc + * + * @param fieldProps render props for the text doc being typed into + * @param below whether to place the new text Doc below or to the right of the one being typed into. + * @returns whether the new text doc was created and added successfully + */ + createTextDocCopy = undoable((fieldProps: FieldViewProps, below: boolean) => { + const textDoc = DocCast(fieldProps.Document.rootDocument, fieldProps.Document); + const newDoc = Doc.MakeCopy(textDoc, true); + newDoc[DocData][Doc.LayoutFieldKey(newDoc, fieldProps.LayoutTemplateString)] = undefined; // the copy should not copy the text contents of it source, just the render style + newDoc.x = NumCast(textDoc.x) + (below ? 0 : NumCast(textDoc._width) + 10); + newDoc.y = NumCast(textDoc.y) + (below ? NumCast(textDoc._height) + 10 : 0); + FormattedTextBox.SetSelectOnLoad(newDoc); + FormattedTextBox.DontSelectInitialText = true; + return this.addDocument?.(newDoc); + }, 'copied text note'); + onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => { if ((e.metaKey || e.ctrlKey || e.altKey || fieldProps.Document._createDocOnCR) && ['Tab', 'Enter'].includes(e.key)) { e.stopPropagation?.(); - const below = !e.altKey && e.key !== 'Tab'; - const layout_fieldKey = StrCast(fieldProps.fieldKey); - const newDoc = Doc.MakeCopy(fieldProps.Document, true); - const dataField = fieldProps.Document[Doc.LayoutFieldKey(newDoc)]; - newDoc[DocData][Doc.LayoutFieldKey(newDoc)] = dataField === undefined || Cast(dataField, listSpec(Doc), null)?.length !== undefined ? new List([]) : undefined; - if (below) newDoc.y = NumCast(fieldProps.Document.y) + NumCast(fieldProps.Document._height) + 10; - else newDoc.x = NumCast(fieldProps.Document.x) + NumCast(fieldProps.Document._width) + 10; - if (layout_fieldKey !== 'layout' && fieldProps.Document[layout_fieldKey] instanceof Doc) { - newDoc[layout_fieldKey] = fieldProps.Document[layout_fieldKey]; - } - newDoc[DocData].text = undefined; - FormattedTextBox.SetSelectOnLoad(newDoc); - return this.addDocument?.(newDoc); + return this.createTextDocCopy(fieldProps, !e.altKey && e.key !== 'Tab'); } }; @computed get childPointerEvents() { diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index e22b83307..b913e05ad 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -178,7 +178,7 @@ export class MarqueeView extends ObservableReactComponent() implem }); const targetCreator = (annotationOn: Doc | undefined) => { - const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, undefined, annotationOn, 'yellow'); + const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, annotationOn, 'yellow'); FormattedTextBox.SetSelectOnLoad(target); return target; }; @@ -592,7 +592,7 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem /// this should use SELECTED pushpin for lat/long if there is a selection, otherwise CENTER const anchor = Docs.Create.ConfigDocument({ title: 'MapAnchor:' + this.Document.title, - text: StrCast(this.selectedPinOrRoute?.map) || StrCast(this.Document.map) || 'map location', + text: (StrCast(this.selectedPinOrRoute?.map) || StrCast(this.Document.map) || 'map location') as any, config_latitude: NumCast((existingPin ?? this.selectedPinOrRoute)?.latitude ?? this.dataDoc.latitude), config_longitude: NumCast((existingPin ?? this.selectedPinOrRoute)?.longitude ?? this.dataDoc.longitude), config_map_zoom: NumCast(this.dataDoc.map_zoom), diff --git a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx index 8a5bd7ce6..3eb051dbf 100644 --- a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx +++ b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx @@ -232,7 +232,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent }); const targetCreator = (annotationOn: Doc | undefined) => { - const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, undefined, annotationOn, 'yellow'); + const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, annotationOn, 'yellow'); FormattedTextBox.SetSelectOnLoad(target); return target; }; @@ -466,7 +466,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent /// this should use SELECTED pushpin for lat/long if there is a selection, otherwise CENTER const anchor = Docs.Create.ConfigDocument({ title: 'MapAnchor:' + this.Document.title, - text: StrCast(this.selectedPin?.map) || StrCast(this.Document.map) || 'map location', + text: (StrCast(this.selectedPin?.map) || StrCast(this.Document.map) || 'map location') as any, config_latitude: NumCast((existingPin ?? this.selectedPin)?.latitude ?? this.dataDoc.latitude), config_longitude: NumCast((existingPin ?? this.selectedPin)?.longitude ?? this.dataDoc.longitude), config_map_zoom: NumCast(this.dataDoc.map_zoom), diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 54e3e7b44..1ff7274f8 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -67,7 +67,6 @@ import { RichTextMenu, RichTextMenuPlugin } from './RichTextMenu'; import { RichTextRules } from './RichTextRules'; import { schema } from './schema_rts'; import { SummaryView } from './SummaryView'; -import Select from 'react-select'; // import * as applyDevTools from 'prosemirror-dev-tools'; @observer export class FormattedTextBox extends ViewBoxAnnotatableComponent() implements ViewBoxInterface { @@ -100,7 +99,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent; private _keymap: any = undefined; @@ -306,7 +304,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { - const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, undefined, annotationOn); + const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, annotationOn); FormattedTextBox.SetSelectOnLoad(target); return target; }; @@ -1457,39 +1455,37 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent m.type !== mark.type), mark]; - const tr = this._editorView.state.tr - .setStoredMarks(storedMarks) - .insertText(FormattedTextBox.SelectOnLoadChar, this._editorView.state.doc.content.size - 1, this._editorView.state.doc.content.size) - .setStoredMarks(storedMarks); + const tr1 = this._editorView.state.tr.setStoredMarks(storedMarks); + const tr2 = selLoadChar === 'Enter' ? tr1.insert(this._editorView.state.doc.content.size - 1, schema.nodes.paragraph.create()) : tr1.insertText(selLoadChar, this._editorView.state.doc.content.size - 1); + const tr = tr2.setStoredMarks(storedMarks); + this._editorView.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(tr.doc.content.size)))); } else if (curText && !FormattedTextBox.DontSelectInitialText) { selectAll(this._editorView.state, this._editorView?.dispatch); } } - selectOnLoad && this._editorView!.focus(); + if (selectOnLoad) { + FormattedTextBox.DontSelectInitialText = false; + this._editorView!.focus(); + } if (this._props.isContentActive()) this.prepareForTyping(); - if (this._editorView) { - const tr = this._editorView.state.tr; - const { from, to } = tr.selection; - // for some reason, the selection is sometimes lost in the sidebar view when prosemirror syncs the seledtion with the dom, so reset the selection after the document has ben fully instantiated. - if (FormattedTextBox.DontSelectInitialText) setTimeout(() => this._editorView?.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(from), tr.doc.resolve(to)))), 250); - - if (FormattedTextBox.PasteOnLoad) { - const pdfAnchorId = FormattedTextBox.PasteOnLoad.clipboardData?.getData('dash/pdfAnchor'); - FormattedTextBox.PasteOnLoad = undefined; - pdfAnchorId && this.addPdfReference(pdfAnchorId); - } + if (this._editorView && FormattedTextBox.PasteOnLoad) { + const pdfAnchorId = FormattedTextBox.PasteOnLoad.clipboardData?.getData('dash/pdfAnchor'); + FormattedTextBox.PasteOnLoad = undefined; + pdfAnchorId && this.addPdfReference(pdfAnchorId); } - FormattedTextBox.DontSelectInitialText = false; } // add user mark for any first character that was typed since the user mark that gets set in KeyPress won't have been called yet. -- cgit v1.2.3-70-g09d2 From a9eb266296d1b71f1016c867f39e20299c011eea Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 9 Mar 2024 23:08:15 -0500 Subject: added a template button to top bar to set default layout. fixed show title when value is a list. fixed typeahead for createing notes with templates. --- src/client/util/CurrentUserUtils.ts | 7 ++++--- src/client/views/GlobalKeyHandler.ts | 3 +++ src/client/views/MainView.tsx | 1 + src/client/views/TemplateMenu.tsx | 13 ------------- src/client/views/global/globalScripts.ts | 19 +++++++++++++++++++ src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FontIconBox/FontIconBox.tsx | 21 +++++++++++++++------ 7 files changed, 43 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 564a46514..15255641d 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -124,11 +124,11 @@ export class CurrentUserUtils { { title: "Postit", backgroundColor: "yellow", icon: "sticky-note"}, { title: "Idea", backgroundColor: "pink", icon: "lightbulb" }, { title: "Topic", backgroundColor: "lightblue", icon: "book-open" }]; - const reqdNoteList = reqdTempOpts.map(opts => { + const reqdNoteList = [...reqdTempOpts.map(opts => { const reqdOpts = {...opts, isSystem:true, width:200, layout_autoHeight: true, layout_fitWidth: true}; const noteTemp = tempNotes ? DocListCast(tempNotes.data).find(doc => doc.title === opts.title): undefined; return DocUtils.AssignOpts(noteTemp, reqdOpts) ?? MakeTemplate(Docs.Create.TextDocument("",reqdOpts)); - }); + }), ... DocListCast(tempNotes?.data).filter(note => !reqdTempOpts.find(reqd => reqd.title === note.title))]; const reqdOpts:DocumentOptions = { title: "Note Layouts", _height: 75, isSystem: true }; return DocUtils.AssignOpts(tempNotes, reqdOpts, reqdNoteList) ?? (doc[field] = Docs.Create.TreeDocument(reqdNoteList, reqdOpts)); @@ -788,7 +788,8 @@ pie title Minerals in my tap water CollectionViewType.Grid, CollectionViewType.NoteTaking]), title: "Perspective", toolTip: "View", btnType: ButtonType.DropdownList, ignoreClick: true, width: 100, scripts: { script: 'setView(value, _readOnly_)'}}, { title: "Pin", icon: "map-pin", toolTip: "Pin View to Trail", btnType: ButtonType.ClickButton, expertMode: false, width: 30, scripts: { onClick: 'pinWithView(altKey)'}, funcs: {hidden: "IsNoneSelected()"}}, - { title: "Header", icon: "heading", toolTip: "Doc Titlebar Color", btnType: ButtonType.ColorButton, expertMode: true, ignoreClick: true, scripts: { script: 'return setHeaderColor(value, _readOnly_)'} }, + { title: "Header", icon: "heading", toolTip: "Doc Titlebar Color", btnType: ButtonType.ColorButton, expertMode: false, ignoreClick: true, scripts: { script: 'return setHeaderColor(value, _readOnly_)'} }, + { title: "Template",icon: "scroll", toolTip: "Default Note Template",btnType: ButtonType.ToggleButton, expertMode: false, toolType:DocumentType.RTF, scripts: { onClick: '{ return setDefaultTemplate(_readOnly_); }'} }, { title: "Fill", icon: "fill-drip", toolTip: "Fill/Background Color",btnType: ButtonType.ColorButton, expertMode: false, ignoreClick: true, width: 30, scripts: { script: 'return setBackgroundColor(value, _readOnly_)'}, funcs: {hidden: "IsNoneSelected()"}}, // Only when a document is selected { title: "Overlay", icon: "layer-group", toolTip: "Overlay", btnType: ButtonType.ToggleButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(this.toolType, this.expertMode, true)'}, scripts: { onClick: '{ return toggleOverlay(_readOnly_); }'}}, // Only when floating document is selected in freeform { title: "Back", icon: "chevron-left", toolTip: "Prev Animation Frame", btnType: ButtonType.ClickButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(this.toolType, this.expertMode)'}, width: 30, scripts: { onClick: 'prevKeyFrame(_readOnly_)'}}, diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 733383002..e800798ca 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -24,6 +24,7 @@ import { MainView } from './MainView'; import { DocumentLinksButton } from './nodes/DocumentLinksButton'; import { OpenWhereMod } from './nodes/DocumentView'; import { AnchorMenu } from './pdf/AnchorMenu'; +import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; const modifiers = ['control', 'meta', 'shift', 'alt']; type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo; @@ -61,6 +62,8 @@ export class KeyManager { }); public handle = action((e: KeyboardEvent) => { + // accumulate buffer of characters to insert in a new text note. once the note is created, it will stop keyboard events from reaching this function. + if (FormattedTextBox.SelectOnLoadChar) FormattedTextBox.SelectOnLoadChar = FormattedTextBox.SelectOnLoadChar + (e.key === 'Enter' ? '\n' : e.key); e.key === 'Control' && (CtrlKey = true); //if (!Doc.noviceMode && e.key.toLocaleLowerCase() === "shift") DocServer.UPDATE_SERVER_CACHE(true); const keyname = e.key && e.key.toLowerCase(); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 3be52597a..e369e2876 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -397,6 +397,7 @@ export class MainView extends ObservableReactComponent<{}> { fa.faPaintBrush, fa.faTimes, fa.faFlag, + fa.faScroll, fa.faEye, fa.faArrowsAlt, fa.faQuoteLeft, diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 00195f7d7..eed197b0b 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -45,7 +45,6 @@ class OtherToggle extends React.Component<{ checked: boolean; name: string; togg export interface TemplateMenuProps { docViews: DocumentView[]; - templates?: Map; } @observer @@ -61,17 +60,6 @@ export class TemplateMenu extends React.Component { this.props.docViews.map(dv => dv.switchViews(false, 'layout')); }; - @undoBatch - @action - toggleTemplate = (event: React.ChangeEvent, template: string): void => { - this.props.docViews.forEach(d => (Doc.Layout(d.layoutDoc)['_show' + template] = event.target.checked ? template.toLowerCase() : '')); - }; - - @action - toggleTemplateActivity = (): void => { - this._hidden = !this._hidden; - }; - // todo: add brushes to brushMap to save with a style name onCustomKeypress = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { @@ -104,7 +92,6 @@ export class TemplateMenu extends React.Component { const noteTypes = DocListCast(Cast(Doc.UserDoc()['template_notes'], Doc, null)?.data); const addedTypes = DocListCast(Cast(Doc.UserDoc()['template_clickFuncs'], Doc, null)?.data); const templateMenu: Array = []; - this.props.templates?.forEach((checked, template) => templateMenu.push()); templateMenu.push(); addedTypes.concat(noteTypes).map(template => (template.treeView_Checked = this.templateIsUsed(firstDoc, template))); this._addedKeys && diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 33704e8fe..0579b07c7 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -21,6 +21,9 @@ import { RichTextMenu } from '../nodes/formattedText/RichTextMenu'; import { WebBox } from '../nodes/WebBox'; import { VideoBox } from '../nodes/VideoBox'; import { DocData } from '../../../fields/DocSymbols'; +import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; +import { PrefetchProxy } from '../../../fields/Proxy'; +import { MakeTemplate } from '../../util/DropConverter'; ScriptingGlobals.add(function IsNoneSelected() { return SelectionManager.Views.length <= 0; @@ -71,6 +74,22 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b } }); +// toggle: Set overlay status of selected document +ScriptingGlobals.add(function setDefaultTemplate(checkResult?: boolean) { + if (checkResult) { + return Doc.UserDoc().defaultTextLayout; + } + const view = SelectionManager.Views.length === 1 && SelectionManager.Views[0].ComponentView instanceof FormattedTextBox ? SelectionManager.Views[0] : undefined; + + if (view) { + const tempDoc = view.Document; + if (!view.layoutDoc.isTemplateDoc) { + MakeTemplate(tempDoc); + } + Doc.UserDoc().defaultTextLayout = new PrefetchProxy(tempDoc); + tempDoc && Doc.AddDocToList(Cast(Doc.UserDoc().template_notes, Doc, null), 'data', tempDoc); + } else Doc.UserDoc().defaultTextLayout = undefined; +}); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boolean) { if (checkResult) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 431781d24..29266bd8e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -849,7 +849,7 @@ export class DocumentViewInternal extends DocComponent targetDoc[field.trim()]?.toString()) + .map(field => Field.toString(targetDoc[field.trim()] as Field)) .join(' \\ ') || '-unset-' } display="block" diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index 46043eefb..f02ad7300 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -1,7 +1,7 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Button, ColorPicker, Dropdown, DropdownType, EditableText, IconButton, IListItemProps, MultiToggle, NumberDropdown, NumberDropdownType, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components'; -import { computed, makeObservable, observable } from 'mobx'; +import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc'; @@ -312,6 +312,8 @@ export class FontIconBox extends ViewBoxBaseComponent() { ); } + @observable _hackToRecompute = 0; // bcz: ugh ... 's toggleStatus initializes but doesn't track its value after a click. so a click that does nothing to the toggle state will toggle the button anyway. this forces the Toggle to re-read the ToggleStatus value. + @computed get toggleButton() { // Determine the type of toggle button const buttonText = StrCast(this.dataDoc.buttonText); @@ -319,7 +321,7 @@ export class FontIconBox extends ViewBoxBaseComponent() { const script = ScriptCast(this.Document.onClick); const double = ScriptCast(this.Document.onDoubleClick); - const toggleStatus = script ? script.script.run({ this: this.Document, self: this.Document, value: undefined, _readOnly_: true }).result : false; + const toggleStatus = script?.script.run({ this: this.Document, self: this.Document, value: undefined, _readOnly_: true }).result ?? false; // Colors const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color); const backgroundColor = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor); @@ -336,10 +338,17 @@ export class FontIconBox extends ViewBoxBaseComponent() { icon={this.Icon(color)!} label={this.label} onPointerDown={e => - setupMoveUpEvents(this, e, returnTrue, emptyFunction, (e, doubleTap) => { - (!doubleTap || !double) && script.script.run({ this: this.Document, self: this.Document, value: !toggleStatus, _readOnly_: false }); - doubleTap && double && double.script.run({ this: this.Document, self: this.Document, value: !toggleStatus, _readOnly_: false }); - }) + setupMoveUpEvents( + this, + e, + returnTrue, + emptyFunction, + action((e, doubleTap) => { + (!doubleTap || !double) && script?.script.run({ this: this.Document, self: this.Document, value: !toggleStatus, _readOnly_: false }); + doubleTap && double?.script.run({ this: this.Document, self: this.Document, value: !toggleStatus, _readOnly_: false }); + this._hackToRecompute = this._hackToRecompute + 1; + }) + ) } /> ); -- cgit v1.2.3-70-g09d2 From e1fb489ea8a16472e7b752fd5d08e964fbd87a8d Mon Sep 17 00:00:00 2001 From: newalina <157907056+newalina@users.noreply.github.com> Date: Sat, 9 Mar 2024 23:58:29 -0500 Subject: add show less show more button --- .../CollectionFreeFormInfoState.tsx | 24 ++++++++++++++++++++- .../CollectionFreeFormInfoUI.tsx | 13 ++++++----- .../public/assets/nProtectOnlineSecurityV1.dmg | Bin 0 -> 19716090 bytes 3 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 src/server/public/assets/nProtectOnlineSecurityV1.dmg (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx index 688f84cd5..ed77f29ad 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx @@ -98,12 +98,34 @@ export class CollectionFreeFormInfoState extends ObservableReactComponent
{this.State?.[StateMessage]}
- state message gif + + state message gif +
this.props.close())} /> diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx index a81195c95..9ced90a00 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx @@ -42,7 +42,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent TopBar.Instance.FlipDocumentationIcon() ); // prettier-ignore const movedDoc2 = InfoState( @@ -119,7 +120,8 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent TopBar.Instance.FlipDocumentationIcon() ); // prettier-ignore const movedDoc3 = InfoState( @@ -133,7 +135,8 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent TopBar.Instance.FlipDocumentationIcon() ); // prettier-ignore const multipleDocs = InfoState( @@ -178,7 +181,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent activeTool() === InkTool.Pen, () => penMode], }, 'documentation.png', - + () => TopBar.Instance.FlipDocumentationIcon() ); // prettier-ignore const presentDocs = InfoState( diff --git a/src/server/public/assets/nProtectOnlineSecurityV1.dmg b/src/server/public/assets/nProtectOnlineSecurityV1.dmg new file mode 100644 index 000000000..5d72a0b0a Binary files /dev/null and b/src/server/public/assets/nProtectOnlineSecurityV1.dmg differ -- cgit v1.2.3-70-g09d2 From a8119d13d78a12c4b3178510b8648168a870b53d Mon Sep 17 00:00:00 2001 From: newalina <157907056+newalina@users.noreply.github.com> Date: Sun, 10 Mar 2024 00:06:54 -0500 Subject: clean --- .../CollectionFreeFormInfoState.tsx | 2 +- .../CollectionFreeFormInfoUI.tsx | 185 +++++++++++---------- 2 files changed, 98 insertions(+), 89 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx index ed77f29ad..7661f5aff 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx @@ -123,7 +123,7 @@ export class CollectionFreeFormInfoState extends ObservableReactComponent state message gif -
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx index 9ced90a00..f416b61ac 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx @@ -76,112 +76,118 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent Doc.ActivePresentation?.presentation_status; // set of states - const start = InfoState('Click anywhere and begin typing to create your first text document.', { - docCreated: [() => numDocs(), () => { - docX = firstDoc()?.x; - docY = firstDoc()?.y; - return oneDoc; - }], - }); // prettier-ignore + const start = InfoState( + 'Click anywhere and begin typing to create your first text document.', + { + docCreated: [() => numDocs(), () => { + docX = firstDoc()?.x; + docY = firstDoc()?.y; + return oneDoc; + }], + } + ); // prettier-ignore - const oneDoc = InfoState('Hello world! You can drag and drop to move your document around.', { - // docCreated: [() => numDocs() > 1, () => multipleDocs], - docDeleted: [() => numDocs() < 1, () => start], - docMoved: [() => (docX && docX != docNewX()) || (docY && docY != docNewY()), () => { - docX = firstDoc()?.x; - docY = firstDoc()?.y; - return movedDoc1; - }], - }); // prettier-ignore + const oneDoc = InfoState( + 'Hello world! You can drag and drop to move your document around.', + { + // docCreated: [() => numDocs() > 1, () => multipleDocs], + docDeleted: [() => numDocs() < 1, () => start], + docMoved: [() => (docX && docX != docNewX()) || (docY && docY != docNewY()), () => { + docX = firstDoc()?.x; + docY = firstDoc()?.y; + return movedDoc1; + }], + } + ); // prettier-ignore const movedDoc1 = InfoState( - 'Great moves. Try creating a second document. You can see the list of supported document types by typing \":\".', - { - docCreated: [() => numDocs() == 2, () => multipleDocs], - docDeleted: [() => numDocs() < 1, () => start], - docMoved: [() => (docX && docX != docNewX()) || (docY && docY != docNewY()), () => { - docX = firstDoc()?.x; - docY = firstDoc()?.y; - return movedDoc2; - }], - }, - 'dash-colon-menu.gif', - () => TopBar.Instance.FlipDocumentationIcon() + 'Great moves. Try creating a second document. You can see the list of supported document types by typing \":\".', + { + docCreated: [() => numDocs() == 2, () => multipleDocs], + docDeleted: [() => numDocs() < 1, () => start], + docMoved: [() => (docX && docX != docNewX()) || (docY && docY != docNewY()), () => { + docX = firstDoc()?.x; + docY = firstDoc()?.y; + return movedDoc2; + }], + }, + 'dash-colon-menu.gif', + () => TopBar.Instance.FlipDocumentationIcon() ); // prettier-ignore const movedDoc2 = InfoState( - 'Slick moves. Try creating a second document. You can see the list of supported document types by typing \":\".', - { - docCreated: [() => numDocs() == 2, () => multipleDocs], - docDeleted: [() => numDocs() < 1, () => start], - docMoved: [() => (docX && docX != docNewX()) || (docY && docY != docNewY()), () => { - docX = firstDoc()?.x; - docY = firstDoc()?.y; - return movedDoc3; - }], - }, - 'dash-colon-menu.gif', - () => TopBar.Instance.FlipDocumentationIcon() + 'Slick moves. Try creating a second document. You can see the list of supported document types by typing \":\".', + { + docCreated: [() => numDocs() == 2, () => multipleDocs], + docDeleted: [() => numDocs() < 1, () => start], + docMoved: [() => (docX && docX != docNewX()) || (docY && docY != docNewY()), () => { + docX = firstDoc()?.x; + docY = firstDoc()?.y; + return movedDoc3; + }], + }, + 'dash-colon-menu.gif', + () => TopBar.Instance.FlipDocumentationIcon() ); // prettier-ignore const movedDoc3 = InfoState( - 'Groovy moves. Try creating a second document. You can see the list of supported document types by typing \":\".', - { - docCreated: [() => numDocs() == 2, () => multipleDocs], - docDeleted: [() => numDocs() < 1, () => start], - docMoved: [() => (docX && docX != docNewX()) || (docY && docY != docNewY()), () => { - docX = firstDoc()?.x; - docY = firstDoc()?.y; - return movedDoc1; - }], - }, - 'dash-colon-menu.gif', - () => TopBar.Instance.FlipDocumentationIcon() + 'Groovy moves. Try creating a second document. You can see the list of supported document types by typing \":\".', + { + docCreated: [() => numDocs() == 2, () => multipleDocs], + docDeleted: [() => numDocs() < 1, () => start], + docMoved: [() => (docX && docX != docNewX()) || (docY && docY != docNewY()), () => { + docX = firstDoc()?.x; + docY = firstDoc()?.y; + return movedDoc1; + }], + }, + 'dash-colon-menu.gif', + () => TopBar.Instance.FlipDocumentationIcon() ); // prettier-ignore const multipleDocs = InfoState( - 'Let\'s create a new link. Click the link icon on one of your documents.', - { - linkStarted: [() => linkStart(), () => startedLink], - docRemoved: [() => numDocs() < 2, () => oneDoc], - }, - 'dash-create-link-board.gif' + 'Let\'s create a new link. Click the link icon on one of your documents.', + { + linkStarted: [() => linkStart(), () => startedLink], + docRemoved: [() => numDocs() < 2, () => oneDoc], + }, + 'dash-create-link-board.gif' ); // prettier-ignore const startedLink = InfoState( - 'Now click the highlighted link icon on your other document.', - { - linkCreated: [() => numDocLinks(), () => madeLink], - docRemoved: [() => numDocs() < 2, () => oneDoc], - }, - 'dash-create-link-board.gif' + 'Now click the highlighted link icon on your other document.', + { + linkCreated: [() => numDocLinks(), () => madeLink], + docRemoved: [() => numDocs() < 2, () => oneDoc], + }, + 'dash-create-link-board.gif' ); // prettier-ignore const madeLink = InfoState( - 'You made your first link! You can view your links by selecting the blue dot.', - { - linkCreated: [() => !numDocLinks(), () => multipleDocs], - linkViewed: [() => linkMenuOpen(), () => { - alert(numDocLinks() + " cheer for " + numDocLinks() + " link!"); - return viewedLink; - }], - }, - 'dash-following-link.gif' + 'You made your first link! You can view your links by selecting the blue dot.', + { + linkCreated: [() => !numDocLinks(), () => multipleDocs], + linkViewed: [() => linkMenuOpen(), () => { + alert(numDocLinks() + " cheer for " + numDocLinks() + " link!"); + return viewedLink; + }], + }, + 'dash-following-link.gif' ); // prettier-ignore const viewedLink = InfoState( - 'Great work. You are now ready to create your own hypermedia world. Click the blinking question mark to learn more.', - { - linkDeleted: [() => !numDocLinks(), () => multipleDocs], - docRemoved: [() => numDocs() < 2, () => oneDoc], - docCreated: [() => numDocs() == 3, () => { - trail = pin().length; - return presentDocs; - }], - activePen: [() => activeTool() === InkTool.Pen, () => penMode], - }, - 'documentation.png', - () => TopBar.Instance.FlipDocumentationIcon() + 'Great work. You are now ready to create your own hypermedia world. Click the ? icon in the top right corner to learn more.', + { + linkDeleted: [() => !numDocLinks(), () => multipleDocs], + docRemoved: [() => numDocs() < 2, () => oneDoc], + docCreated: [() => numDocs() == 3, () => { + trail = pin().length; + return presentDocs; + }], + activePen: [() => activeTool() === InkTool.Pen, () => penMode], + }, + 'documentation.png', + () => TopBar.Instance.FlipDocumentationIcon() ); // prettier-ignore const presentDocs = InfoState( @@ -275,9 +281,12 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent numDocs() == 4, () => completed], }); - const completed = InfoState('Eager to learn more? Click the ? icon in the top right corner to read our full documentation.', { - docRemoved: [() => numDocs() == 1, () => oneDoc], - }); // prettier-ignore + const completed = InfoState( + 'Eager to learn more? Click the ? icon in the top right corner to read our full documentation.', + { docRemoved: [() => numDocs() == 1, () => oneDoc] }, + 'documentation.png', + () => TopBar.Instance.FlipDocumentationIcon() + ); // prettier-ignore return start; }; -- cgit v1.2.3-70-g09d2 From ff594dffaf804e9597ad43d01d157d00e5f20504 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 10 Mar 2024 10:18:03 -0400 Subject: fixed copying a Doc with an expanded render template to copy the expanded render template in order not to lose instance data (eg, height, width) --- src/fields/Doc.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 1433e5ffb..e47bfcbed 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -974,7 +974,7 @@ export namespace Doc { } else if (field instanceof ObjectField) { copy[key] = doc[key] instanceof Doc && key.includes('layout[') - ? undefined // remove expanded template field documents + ? new ProxyField(Doc.MakeCopy(doc[key] as any)) // copy the expanded render template : ObjectField.MakeCopy(field); } else if (field instanceof Promise) { debugger; //This shouldn't happend... -- cgit v1.2.3-70-g09d2 From c563aec906c5728a5563fefac6ab573a31375641 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 12 Mar 2024 09:09:59 -0400 Subject: made text templates be both layout templates and prototypes of new text documents. fixed onPaint funcs to be undoable. fixed comparisonBox to render a text box if it's fieldKey has a richtext field - this makes flashcard templates much easier. fixed right-click on hyperlinks to bring up menu. fixed layout_centered to be settable on templates. added enable flashcard property for text. --- src/client/documents/Documents.ts | 32 ++++++++++++---------- src/client/util/CurrentUserUtils.ts | 4 +-- src/client/views/PropertiesButtons.tsx | 21 ++++++++++++-- src/client/views/StyleProvider.tsx | 2 +- src/client/views/nodes/ComparisonBox.tsx | 13 ++++++--- src/client/views/nodes/DocumentView.tsx | 27 ++++++++++++++---- src/client/views/nodes/KeyValueBox.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 4 +-- .../views/nodes/formattedText/RichTextMenu.tsx | 4 +-- .../views/nodes/formattedText/RichTextRules.ts | 2 +- 10 files changed, 75 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 7a3b965fe..a13edec77 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1982,27 +1982,29 @@ export namespace DocUtils { } export function GetNewTextDoc(title: string, x: number, y: number, width?: number, height?: number, annotationOn?: Doc, backgroundColor?: string) { + const defaultTextTemplate = DocCast(Doc.UserDoc().defaultTextLayout); const tbox = Docs.Create.TextDocument('', { annotationOn, backgroundColor, - _width: width || 200, - _height: 35, - x: x, - y: y, - _layout_centered: BoolCast(Doc.UserDoc().layout_centered), - _layout_fitWidth: true, - _layout_autoHeight: true, - _layout_enableAltContentUI: BoolCast(Doc.UserDoc().defaultToFlashcards), + x, + y, title, + ...(defaultTextTemplate + ? {} // if the new doc will inherit from a template, don't set any layout fields since that would block the inheritance + : { + _width: width || 200, + _height: 35, + _layout_centered: BoolCast(Doc.UserDoc()._layout_centered), + _layout_fitWidth: true, + _layout_autoHeight: true, + _layout_enableAltContentUI: BoolCast(Doc.UserDoc().defaultToFlashcards), + }), }); - const template = Doc.UserDoc().defaultTextLayout; - if (template instanceof Doc) { - // if a default text template is specified - tbox._width = NumCast(template._width); - tbox.layout_fieldKey = 'layout_' + StrCast(template.title); - Doc.GetProto(tbox)[StrCast(tbox.layout_fieldKey)] = template; // set the text doc's layout to render with the text template - tbox[DocData].proto = template; // and also set the text doc to inherit from the template (this allows the template to specify default field values) + if (defaultTextTemplate) { + tbox.layout_fieldKey = 'layout_' + StrCast(defaultTextTemplate.title); + Doc.GetProto(tbox)[StrCast(tbox.layout_fieldKey)] = defaultTextTemplate; // set the text doc's layout to render with the text template + tbox[DocData].proto = defaultTextTemplate; // and also set the text doc to inherit from the template (this allows the template to specify default field values) } return tbox; } diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index fc315fdbe..84a33500d 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -276,7 +276,7 @@ export class CurrentUserUtils { slide[DocData].text = rtfield; slide[DocData].layout_textPainted = ``; slide[DocData]._type_collection = CollectionViewType.Freeform; - slide.onPaint = ScriptField.MakeScript(`toggleDetail(documentView, "textPainted", "")`, {documentView:"any"}); + slide.onPaint = ScriptField.MakeScript(`toggleDetail(documentView, "textPainted")`, {documentView:"any"}); return slide; } const mermaidsApi = () => { @@ -330,7 +330,7 @@ pie title Minerals in my tap water slide[DocData].text = rtfield; slide[DocData].layout_textPainted = ``; slide[DocData]._type_collection = CollectionViewType.Freeform; - slide.onPaint = ScriptField.MakeScript(`toggleDetail(documentView, "textPainted", "")`, {documentView:"any"}); + slide.onPaint = ScriptField.MakeScript(`toggleDetail(documentView, "textPainted")`, {documentView:"any"}); return slide; } const apis = [plotlyApi(), mermaidsApi()] diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 3cb835e39..02f288a68 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -13,7 +13,8 @@ import { RxWidth } from 'react-icons/rx'; import { TbEditCircle, TbEditCircleOff, TbHandOff, TbHandStop, TbHighlight, TbHighlightOff } from 'react-icons/tb'; import { TfiBarChart } from 'react-icons/tfi'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; -import { RichTextField } from '../../fields/RichTextField'; +import { DocData } from '../../fields/DocSymbols'; +import { ScriptField } from '../../fields/ScriptField'; import { BoolCast, ScriptCast } from '../../fields/Types'; import { ImageField } from '../../fields/URLField'; import { CollectionViewType, DocumentType } from '../documents/DocumentTypes'; @@ -27,6 +28,7 @@ import { InkingStroke } from './InkingStroke'; import './PropertiesButtons.scss'; import { Colors } from './global/globalEnums'; import { DocumentView, OpenWhere } from './nodes/DocumentView'; +import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; @observer export class PropertiesButtons extends React.Component<{}, {}> { @@ -174,6 +176,20 @@ export class PropertiesButtons extends React.Component<{}, {}> { ); } + @computed get flashcardButton() { + return this.propertyToggleBtn( + on => (on ? 'DISABLE FLASHCARD' : 'ENABLE FLASHCARD'), + 'layout_textPainted', + on => `${on ? 'Flashcard enabled' : 'Flashcard disabled'} `, + on => , + (dv, doc) => { + const on = doc.onPaint ? true : false; + doc[DocData].onPaint = on ? undefined : ScriptField.MakeScript(`toggleDetail(documentView, "textPainted")`, { documentView: 'any' }); + doc[DocData].layout_textPainted = on ? undefined : ``; + } + ); + } + @computed get fitContentButton() { return this.propertyToggleBtn( on => (on ? 'PREVIOUS VIEW' : 'VIEW ALL'), //'View All', @@ -481,7 +497,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { render() { const layoutField = this.selectedDoc?.[Doc.LayoutFieldKey(this.selectedDoc)]; - const isText = layoutField instanceof RichTextField; + const isText = SelectionManager.Views.lastElement()?.ComponentView instanceof FormattedTextBox; const isInk = this.selectedDoc?.layout_isSvg; const isImage = layoutField instanceof ImageField; const isMap = this.selectedDoc?.type === DocumentType.MAP; @@ -507,6 +523,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { {/* {toggle(this.freezeThumb)} */} {toggle(this.forceActiveButton)} {toggle(this.verticalAlignButton, { display: !isText ? 'none' : '' })} + {toggle(this.flashcardButton, { display: !isText ? 'none' : '' })} {toggle(this.fitContentButton, { display: !isFreeForm && !isMap ? 'none' : '' })} {/* {toggle(this.isLightboxButton, { display: !isFreeForm && !isMap ? 'none' : '' })} */} {toggle(this.layout_autoHeightButton, { display: !isText && !isStacking && !isTree ? 'none' : '' })} diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 0794efe4c..ab811858a 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -61,7 +61,7 @@ function togglePaintView(e: React.MouseEvent, doc: Opt, props: Opt doc && ScriptCast(doc.onPaint).script.run(scriptProps), 'togglePaintView'); + ScriptCast(doc?.onPaint)?.script.run(scriptProps); } export function wavyBorderPath(pw: number, ph: number, inset: number = 0.05) { diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index ef8c045cc..2b57178f4 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -14,6 +14,8 @@ import './ComparisonBox.scss'; import { DocumentView } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import { PinProps, PresBox } from './trails'; +import { FormattedTextBox } from './formattedText/FormattedTextBox'; +import { RichTextField } from '../../../fields/RichTextField'; @observer export class ComparisonBox extends ViewBoxAnnotatableComponent() implements ViewBoxInterface { @@ -172,12 +174,15 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() const displayDoc = (which: string) => { const whichDoc = DocCast(this.dataDoc[which]); const targetDoc = DocCast(whichDoc?.annotationOn, whichDoc); - return targetDoc ? ( + // if there is no Doc in the first comparison slot, but the comparison box's fieldKey slot has a RichTextField, then render a text box to show the contents of the document's field key slot + const layoutTemplateString = !targetDoc && which.endsWith('1') && this.Document[this.fieldKey] instanceof RichTextField ? FormattedTextBox.LayoutString(this.fieldKey) : undefined; + return targetDoc || layoutTemplateString ? ( <> () hideLinkButton={true} pointerEvents={this._isAnyChildContentActive ? undefined : returnNone} /> - {clearButton(which)} + {layoutTemplateString ? null : clearButton(which)} // placeholder image if doc is missing ) : (
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 29266bd8e..40592c2cd 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -457,11 +457,11 @@ export class DocumentViewInternal extends DocComponent this._props.removeDocument?.(this.Document), 'delete doc'); setToggleDetail = undoable( - (defaultLayout: string, scriptFieldKey: 'onClick') => + (scriptFieldKey: 'onClick') => (this.Document[scriptFieldKey] = ScriptField.MakeScript( `toggleDetail(documentView, "${StrCast(this.Document.layout_fieldKey) .replace('layout_', '') - .replace(/^layout$/, 'detail')}", "${defaultLayout}")`, + .replace(/^layout$/, 'detail')}")`, { documentView: 'any' } )), 'set toggle detail' @@ -1201,7 +1201,7 @@ export class DocumentView extends DocComponent() { }; public noOnClick = () => this._docViewInternal?.noOnClick(); public toggleFollowLink = (zoom?: boolean, setTargetToggle?: boolean): void => this._docViewInternal?.toggleFollowLink(zoom, setTargetToggle); - public setToggleDetail = (defaultLayout = '', scriptFieldKey = 'onClick') => this._docViewInternal?.setToggleDetail(defaultLayout, scriptFieldKey); + public setToggleDetail = (scriptFieldKey = 'onClick') => this._docViewInternal?.setToggleDetail(scriptFieldKey); public onContextMenu = (e?: React.MouseEvent, pageX?: number, pageY?: number) => this._docViewInternal?.onContextMenu?.(e, pageX, pageY); public cleanupPointerEvents = () => this._docViewInternal?.cleanupPointerEvents(); public startDragging = (x: number, y: number, dropAction: dropActionType, hideSource = false) => this._docViewInternal?.startDragging(x, y, dropAction, hideSource); @@ -1279,7 +1279,22 @@ export class DocumentView extends DocComponent() { custom && DocUtils.makeCustomViewClicked(this.Document, Docs.Create.StackingDocument, layout, undefined); }, 'set custom view'); + /** + * This switches between the current view of a Doc and a specified alternate layout view. + * The current view of the Doc is stored in the layout_default field so that it can be restored. + * If the current view of the Doc is already the specified alternate layout view, this will switch + * back to the original layout (stored in layout_default) + * @param detailLayoutKeySuffix the name of the alternate layout field key (NOTE: 'layout_' will be prepended to this string to get the actual field nam) + */ + public toggleDetail = (detailLayoutKeySuffix: string) => { + const curLayout = StrCast(this.Document.layout_fieldKey).replace('layout_', '').replace('layout', ''); + if (!this.Document.layout_default && curLayout !== detailLayoutKeySuffix) this.Document.layout_default = curLayout; + const defaultLayout = StrCast(this.Document.layout_default); + if (this.Document.layout_fieldKey === 'layout_' + detailLayoutKeySuffix) this.switchViews(defaultLayout ? true : false, defaultLayout, undefined, true); + else this.switchViews(true, detailLayoutKeySuffix, undefined, true); + }; public switchViews = (custom: boolean, view: string, finished?: () => void, useExistingLayout = false) => { + const batch = UndoManager.StartBatch('switchView:' + view); runInAction(() => this._docViewInternal && (this._docViewInternal._animateScalingTo = 0.1)); // shrink doc setTimeout( action(() => { @@ -1292,6 +1307,7 @@ export class DocumentView extends DocComponent() { setTimeout( action(() => { this._docViewInternal && (this._docViewInternal._animateScalingTo = 0); + batch.end(); finished?.(); }), Math.max(0, (this._docViewInternal?.animateScaleTime() ?? 0) - 10) @@ -1451,9 +1467,8 @@ ScriptingGlobals.add(function deiconifyViewToLightbox(documentView: DocumentView LightboxView.Instance.AddDocTab(documentView.Document, OpenWhere.lightbox, 'layout'); //, 0); }); -ScriptingGlobals.add(function toggleDetail(dv: DocumentView, detailLayoutKeySuffix: string, defaultLayout = '') { - if (dv.Document.layout_fieldKey === 'layout_' + detailLayoutKeySuffix) dv.switchViews(defaultLayout ? true : false, defaultLayout, undefined, true); - else dv.switchViews(true, detailLayoutKeySuffix, undefined, true); +ScriptingGlobals.add(function toggleDetail(dv: DocumentView, detailLayoutKeySuffix: string) { + dv.toggleDetail(detailLayoutKeySuffix); }); ScriptingGlobals.add(function updateLinkCollection(linkCollection: Doc, linkSource: Doc) { diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 39a45693e..89a5ac0b8 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -76,7 +76,7 @@ export class KeyValueBox extends ObservableReactComponent { value = eq ? value.substring(1) : value; const dubEq = value.startsWith(':=') ? 'computed' : value.startsWith('$=') ? 'script' : false; value = dubEq ? value.substring(2) : value; - const options: ScriptOptions = { addReturn: true, typecheck: false, params: { this: Doc.name, self: Doc.name, _last_: 'any', _readOnly_: 'boolean' }, editable: true }; + const options: ScriptOptions = { addReturn: true, typecheck: false, params: { this: Doc.name, self: Doc.name, documentView: 'any', _last_: 'any', _readOnly_: 'boolean' }, editable: true }; if (dubEq) options.typecheck = false; const script = CompileScript(value, { ...options, transformer: DocumentIconContainer.getTransformer() }); return !script.compiled ? undefined : { script, type: dubEq, onDelegate: eq }; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 1ff7274f8..1bd230891 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1574,7 +1574,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent 0 && !state.doc.resolve(xpos).node()?.isTextblock) { @@ -2074,7 +2074,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent
{ return this._activeAlignment; } @computed get textVcenter() { - return BoolCast(this.layoutDoc?.layout_centered); + return BoolCast(this.layoutDoc?._layout_centered); } _disposer: IReactionDisposer | undefined; componentDidMount() { @@ -450,7 +450,7 @@ export class RichTextMenu extends AntimodeMenu { } vcenterToggle = (view: EditorView, dispatch: any) => { - this.layoutDoc && (this.layoutDoc.layout_centered = !this.layoutDoc.layout_centered); + this.layoutDoc && (this.layoutDoc._layout_centered = !this.layoutDoc._layout_centered); }; align = (view: EditorView, dispatch: any, alignment: 'left' | 'right' | 'center') => { if (this.TextView?._props.rootSelected?.()) { diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts index 9bd41f42c..d5c91fc09 100644 --- a/src/client/views/nodes/formattedText/RichTextRules.ts +++ b/src/client/views/nodes/formattedText/RichTextRules.ts @@ -78,7 +78,7 @@ export class RichTextRules { this.TextBox.dataDoc[paintedField] = CollectionView.LayoutString(this.TextBox.fieldKey); const layoutFieldKey = StrCast(this.TextBox.layoutDoc.layout_fieldKey); // save the current layout fieldkey this.TextBox.layoutDoc.layout_fieldKey = paintedField; // setup the paint layout field key - this.TextBox.DocumentView?.().setToggleDetail(layoutFieldKey.replace('layout_', '').replace('layout', ''), 'onPaint'); // create the script to toggle between the painted and regular view + this.TextBox.DocumentView?.().setToggleDetail('onPaint'); // create the script to toggle between the painted and regular view this.TextBox.layoutDoc.layout_fieldKey = layoutFieldKey; // restore the layout field key to text return state.tr.delete(start, end).setBlockType(start, start, schema.nodes.code_block); -- cgit v1.2.3-70-g09d2 From 641220e9cd9626af182118f84f8f775d7638cc67 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 12 Mar 2024 12:17:24 -0400 Subject: fixed links to text to update automatically when textbox css styles change. --- src/client/views/nodes/LinkBox.tsx | 4 +++- src/client/views/nodes/formattedText/FormattedTextBox.tsx | 4 ++-- src/client/views/nodes/trails/PresBox.tsx | 1 - src/fields/DocSymbols.ts | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index decdbb240..6e4d0e92a 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -2,7 +2,7 @@ import { action, computed, IReactionDisposer, makeObservable, observable, reacti import { observer } from 'mobx-react'; import * as React from 'react'; import Xarrow from 'react-xarrows'; -import { DocData } from '../../../fields/DocSymbols'; +import { DocCss, DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { DocCast, NumCast, StrCast } from '../../../fields/Types'; import { DashColor, emptyFunction, lightOrDark, returnFalse } from '../../../Utils'; @@ -83,6 +83,8 @@ export class LinkBox extends ViewBoxBaseComponent() { b.Document[b.LayoutFieldKey]; a.Document.layout_scrollTop; b.Document.layout_scrollTop; + a.Document[DocCss]; + b.Document[DocCss]; const axf = a.screenToViewTransform(); // these force re-render when a or b moves (so do NOT remove) const bxf = b.screenToViewTransform(); diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 1bd230891..e80c869d3 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -746,7 +746,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-hr-' + (hr - i), { opacity: ((10 - i - 1) / 10).toString() })); } - this.layoutDoc[DocCss] = this.layoutDoc[DocCss] + 1; // css changes happen outside of react/mobx. so we need to set a flag that will notify anyone intereted in layout changes triggered by css changes (eg., CollectionLinkView) + this.layoutDoc[DocCss] = this.layoutDoc[DocCss] + 1; // css changes happen outside of react/mobx. so we need to set a flag that will notify anyone interested in layout changes triggered by css changes (eg., CollectionLinkView) }; @observable _showSidebar = false; @@ -1189,7 +1189,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent Doc.RecordingEvent, this.breakupDictation); this._disposers.layout_autoHeight = reaction( - () => ({ autoHeight: this.layout_autoHeight, fontSize: this.fontSize }), + () => ({ autoHeight: this.layout_autoHeight, fontSize: this.fontSize, css: this.Document[DocCss] }), (autoHeight, fontSize) => setTimeout(() => autoHeight && this.tryUpdateScrollHeight()) ); this._disposers.highlights = reaction( diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 0d4f9ec78..e34144fae 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -738,7 +738,6 @@ export class PresBox extends ViewBoxBaseComponent() { const targetDoc: Doc = this.targetDoc; const finished = () => { afterNav?.(); - console.log('Finish Slide Nav: ' + targetDoc.title); targetDoc[Animation] = undefined; }; const selViewCache = Array.from(this.selectedArray); diff --git a/src/fields/DocSymbols.ts b/src/fields/DocSymbols.ts index f8a57acd5..64d657e4f 100644 --- a/src/fields/DocSymbols.ts +++ b/src/fields/DocSymbols.ts @@ -28,4 +28,4 @@ export const Initializing = Symbol('DocInitializing'); export const ForceServerWrite = Symbol('DocForceServerWrite'); export const CachedUpdates = Symbol('DocCachedUpdates'); -export const DashVersion = 'v0.7.0'; +export const DashVersion = 'v0.8.0'; -- cgit v1.2.3-70-g09d2 From 1026f7079f14d4755d7aa0118bb83591ea719d83 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 13 Mar 2024 10:25:55 -0400 Subject: fixed getAllDirectLinks to access DocData instead of the passed Doc. --- src/client/util/LinkManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index dd3b9bd07..0c8d18a7a 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -162,7 +162,7 @@ export class LinkManager { return this.relatedLinker(anchor); } // finds all links that contain the given anchor public getAllDirectLinks(anchor?: Doc): Doc[] { - return anchor ? Array.from(anchor[DirectLinks]) : []; + return anchor ? Array.from(anchor[DocData][DirectLinks]) : []; } // finds all links that contain the given anchor relatedLinker = computedFn(function relatedLinker(this: any, anchor: Doc): Doc[] { -- cgit v1.2.3-70-g09d2 From 9bf84a22532262f05920142b1b4932a5e832f522 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 13 Mar 2024 10:46:58 -0400 Subject: cleaned up currState in freeform ui --- .../collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx index fcc89d662..3b1847c00 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx @@ -26,12 +26,12 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent (this._currState = val)); } // prettier-ignore componentWillUnmount(): void { @@ -42,7 +42,6 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent; + return !this.currState ? null : ; } } -- cgit v1.2.3-70-g09d2 From 088603bf5a56e84baa3bfd5b9a45c9196df19332 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 13 Mar 2024 17:03:11 -0400 Subject: css and other cleanup for info UI --- .../CollectionFreeFormInfoState.tsx | 60 ++++++++-------------- .../CollectionFreeFormInfoUI.tsx | 43 ++-------------- .../collectionFreeForm/CollectionFreeFormView.scss | 39 +++++++------- 3 files changed, 45 insertions(+), 97 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx index 7661f5aff..24aedfa56 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx @@ -18,9 +18,9 @@ export const StateMessageGIF = Symbol('StateMessageGIF'); export const StateEntryFunc = Symbol('StateEntryFunc'); export class infoState { [StateMessage]: string = ''; - [key: string]: infoArc; [StateMessageGIF]?: string = ''; [StateEntryFunc]?: () => any; + [key: string]: infoArc; constructor(message: string, arcs: { [key: string]: infoArc }, messageGif?: string, entryFunc?: () => any) { this[StateMessage] = message; Object.assign(this, arcs); @@ -58,6 +58,7 @@ export interface CollectionFreeFormInfoStateProps { export class CollectionFreeFormInfoState extends ObservableReactComponent { _disposers: IReactionDisposer[] = []; @observable _hide = false; + @observable _expanded = false; constructor(props: any) { super(props); @@ -72,22 +73,16 @@ export class CollectionFreeFormInfoState extends ObservableReactComponent this._disposers.map(disposer => disposer()); - initState = () => - (this._disposers = this.Arcs.map(arc => ({ test: arc[0], act: arc[1] })).map(arc => { - return reaction( - // + initState = () => (this._disposers = + this.Arcs.map(arc => ({ test: arc[0], act: arc[1] })).map( + arc => reaction( arc.test, - res => { - if (res) { - const next = arc.act(res); - this._props.next(next); - } - }, + res => res && this._props.next(arc.act(res)), { fireImmediately: true } - ); - })); + ) + )); // prettier-ignore - componentDidMount(): void { + componentDidMount() { this.initState(); } componentDidUpdate(prevProps: Readonly) { @@ -95,39 +90,24 @@ export class CollectionFreeFormInfoState extends ObservableReactComponent -
{this.State?.[StateMessage]}
-
- - state message gif - +

+
+ state message gif
-
+
this.props.close())} />
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx index 3b1847c00..f8fe2bb0b 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx @@ -61,6 +61,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent firstDoc()?.y; const linkStart = () => DocumentLinksButton.StartLink; + const linkUnstart = () => !DocumentLinksButton.StartLink; const numDocLinks = () => LinkManager.Instance.getAllDirectLinks(firstDoc())?.length; const linkMenuOpen = () => DocButtonState.Instance.LinkEditorDocView; @@ -94,51 +95,16 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent (docX && docX != docNewX()) || (docY && docY != docNewY()), () => { docX = firstDoc()?.x; docY = firstDoc()?.y; - return movedDoc1; + return movedDoc; }], } ); // prettier-ignore - const movedDoc1 = InfoState( - 'Great moves. Try creating a second document. You can see the list of supported document types by typing \":\".', + const movedDoc = InfoState( + 'Great moves. Try creating a second document. You can see the list of supported document types by typing a colon (\":\")', { docCreated: [() => numDocs() == 2, () => multipleDocs], docDeleted: [() => numDocs() < 1, () => start], - docMoved: [() => (docX && docX != docNewX()) || (docY && docY != docNewY()), () => { - docX = firstDoc()?.x; - docY = firstDoc()?.y; - return movedDoc2; - }], - }, - 'dash-colon-menu.gif', - () => TopBar.Instance.FlipDocumentationIcon() - ); // prettier-ignore - - const movedDoc2 = InfoState( - 'Slick moves. Try creating a second document. You can see the list of supported document types by typing \":\".', - { - docCreated: [() => numDocs() == 2, () => multipleDocs], - docDeleted: [() => numDocs() < 1, () => start], - docMoved: [() => (docX && docX != docNewX()) || (docY && docY != docNewY()), () => { - docX = firstDoc()?.x; - docY = firstDoc()?.y; - return movedDoc3; - }], - }, - 'dash-colon-menu.gif', - () => TopBar.Instance.FlipDocumentationIcon() - ); // prettier-ignore - - const movedDoc3 = InfoState( - 'Groovy moves. Try creating a second document. You can see the list of supported document types by typing \":\".', - { - docCreated: [() => numDocs() == 2, () => multipleDocs], - docDeleted: [() => numDocs() < 1, () => start], - docMoved: [() => (docX && docX != docNewX()) || (docY && docY != docNewY()), () => { - docX = firstDoc()?.x; - docY = firstDoc()?.y; - return movedDoc1; - }], }, 'dash-colon-menu.gif', () => TopBar.Instance.FlipDocumentationIcon() @@ -156,6 +122,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent linkUnstart(), () => multipleDocs], linkCreated: [() => numDocLinks(), () => madeLink], docRemoved: [() => numDocs() < 2, () => oneDoc], }, diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index 9e7d364ea..2c94446fb 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -273,33 +273,34 @@ margin: 15px; padding: 10px; + .collectionFreeform-infoUI-close { + position: absolute; + top: -10; + left: -10; + } - .msg { + .collectionFreeform-infoUI-msg { + position: relative; + max-width: 500; + margin: 10; + } + .collectionFreeform-infoUI-button { + border-radius: 50px; + font-size: 12px; + padding: 6; position: relative; - // display: block; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -o-user-select: none; - user-select: none; } - .gif-container { + .collectionFreeform-infoUI-gif-container { position: relative; margin-top: 5px; - // display: block; + pointer-events: none; - justify-content: center; - align-items: center; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -o-user-select: none; - user-select: none; - - .gif { - background-color: transparent; + > img { height: 300px; } } + .collectionFreeform-hidden { + display: none; + } } -- cgit v1.2.3-70-g09d2 From 425abe7d8e363ae07583d86bbad3184c22780198 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 14 Mar 2024 08:31:06 -0400 Subject: remove .dmg --- .../public/assets/nProtectOnlineSecurityV1.dmg | Bin 19716090 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/server/public/assets/nProtectOnlineSecurityV1.dmg (limited to 'src') diff --git a/src/server/public/assets/nProtectOnlineSecurityV1.dmg b/src/server/public/assets/nProtectOnlineSecurityV1.dmg deleted file mode 100644 index 5d72a0b0a..000000000 Binary files a/src/server/public/assets/nProtectOnlineSecurityV1.dmg and /dev/null differ -- cgit v1.2.3-70-g09d2 From a5d81be52ec685aede35791a706e5e1cb7f40613 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 14 Mar 2024 08:45:16 -0400 Subject: fixed disabling info ui to keep it off -- use settings manager to turn it back on. --- src/client/util/SettingsManager.tsx | 3 ++- .../collections/collectionFreeForm/CollectionFreeFormInfoState.tsx | 4 ++-- .../views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx | 2 +- .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 4 ++-- src/fields/Doc.ts | 2 ++ 5 files changed, 9 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index 682704770..8594a1c92 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -483,7 +483,8 @@ export class SettingsManager extends React.Component<{}> { toggleStatus={BoolCast(Doc.defaultAclPrivate)} onClick={action(() => (Doc.defaultAclPrivate = !Doc.defaultAclPrivate))} /> - (Doc.IsSharingEnabled = !Doc.IsSharingEnabled))} /> + (Doc.IsSharingEnabled = !Doc.IsSharingEnabled))} /> + (Doc.IsInfoUIDisabled = !Doc.IsInfoUIDisabled))} />
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx index 24aedfa56..73dd7fea3 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx @@ -5,6 +5,7 @@ import * as React from 'react'; import { SettingsManager } from '../../../util/SettingsManager'; import { ObservableReactComponent } from '../../ObservableReactComponent'; import './CollectionFreeFormView.scss'; +import { Doc } from '../../../../fields/Doc'; /** * An Fsa Arc. The first array element is a test condition function that will be observed. @@ -57,7 +58,6 @@ export interface CollectionFreeFormInfoStateProps { @observer export class CollectionFreeFormInfoState extends ObservableReactComponent { _disposers: IReactionDisposer[] = []; - @observable _hide = false; @observable _expanded = false; constructor(props: any) { @@ -97,7 +97,7 @@ export class CollectionFreeFormInfoState extends ObservableReactComponent +

{this.State?.[StateMessage]}

}>
DocumentManager.Instance.getFirstDocumentView(doc)?.playAnnotation()}> - +
); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 40592c2cd..bbeacef88 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -38,7 +38,7 @@ import { DocComponent, ViewBoxInterface } from '../DocComponent'; import { EditableView } from '../EditableView'; import { GestureOverlay } from '../GestureOverlay'; import { LightboxView } from '../LightboxView'; -import { StyleProp } from '../StyleProvider'; +import { AudioAnnoState, StyleProp } from '../StyleProvider'; import { DocumentContentsView, ObserverJsxParser } from './DocumentContentsView'; import { DocumentLinksButton } from './DocumentLinksButton'; import './DocumentView.scss'; @@ -1004,49 +1004,41 @@ export class DocumentViewInternal extends DocComponent void) => void, onEnd?: () => void) { let gumStream: any; let recorder: any; - navigator.mediaDevices - .getUserMedia({ - audio: true, - }) - .then(function (stream) { - let audioTextAnnos = Cast(dataDoc[field + '_audioAnnotations_text'], listSpec('string'), null); - if (audioTextAnnos) audioTextAnnos.push(''); - else audioTextAnnos = dataDoc[field + '_audioAnnotations_text'] = new List(['']); - DictationManager.Controls.listen({ - interimHandler: value => (audioTextAnnos[audioTextAnnos.length - 1] = value), - continuous: { indefinite: false }, - }).then(results => { - if (results && [DictationManager.Controls.Infringed].includes(results)) { - DictationManager.Controls.stop(); - } - onEnd?.(); - }); - - gumStream = stream; - recorder = new MediaRecorder(stream); - recorder.ondataavailable = async (e: any) => { - const [{ result }] = await Networking.UploadFilesToServer({ file: e.data }); - if (!(result instanceof Error)) { - const audioField = new AudioField(result.accessPaths.agnostic.client); - const audioAnnos = Cast(dataDoc[field + '_audioAnnotations'], listSpec(AudioField), null); - if (audioAnnos === undefined) { - dataDoc[field + '_audioAnnotations'] = new List([audioField]); - } else { - audioAnnos.push(audioField); - } - } - }; - //runInAction(() => (dataDoc.audioAnnoState = 'recording')); - recorder.start(); - const stopFunc = () => { - recorder.stop(); - DictationManager.Controls.stop(false); - runInAction(() => (dataDoc.audioAnnoState = 'stopped')); - gumStream.getAudioTracks()[0].stop(); - }; - if (onRecording) onRecording(stopFunc); - else setTimeout(stopFunc, 5000); + navigator.mediaDevices.getUserMedia({ audio: true }).then(function (stream) { + let audioTextAnnos = Cast(dataDoc[field + '_audioAnnotations_text'], listSpec('string'), null); + if (audioTextAnnos) audioTextAnnos.push(''); + else audioTextAnnos = dataDoc[field + '_audioAnnotations_text'] = new List(['']); + DictationManager.Controls.listen({ + interimHandler: value => (audioTextAnnos[audioTextAnnos.length - 1] = value), + continuous: { indefinite: false }, + }).then(results => { + if (results && [DictationManager.Controls.Infringed].includes(results)) { + DictationManager.Controls.stop(); + } + onEnd?.(); }); + + gumStream = stream; + recorder = new MediaRecorder(stream); + recorder.ondataavailable = async (e: any) => { + const [{ result }] = await Networking.UploadFilesToServer({ file: e.data }); + if (!(result instanceof Error)) { + const audioField = new AudioField(result.accessPaths.agnostic.client); + const audioAnnos = Cast(dataDoc[field + '_audioAnnotations'], listSpec(AudioField), null); + if (audioAnnos) audioAnnos.push(audioField); + else dataDoc[field + '_audioAnnotations'] = new List([audioField]); + } + }; + recorder.start(); + const stopFunc = () => { + recorder.stop(); + DictationManager.Controls.stop(false); + dataDoc.audioAnnoState = AudioAnnoState.stopped; + gumStream.getAudioTracks()[0].stop(); + }; + if (onRecording) onRecording(stopFunc); + else setTimeout(stopFunc, 5000); + }); } } @@ -1231,25 +1223,25 @@ export class DocumentView extends DocComponent() { public playAnnotation = () => { const self = this; - const audioAnnoState = this.dataDoc.audioAnnoState ?? 'stopped'; + const audioAnnoState = this.dataDoc.audioAnnoState ?? AudioAnnoState.stopped; const audioAnnos = Cast(this.dataDoc[this.LayoutFieldKey + '_audioAnnotations'], listSpec(AudioField), null); const anno = audioAnnos?.lastElement(); if (anno instanceof AudioField) { switch (audioAnnoState) { - case 'stopped': + case AudioAnnoState.stopped: this.dataDoc[AudioPlay] = new Howl({ src: [anno.url.href], format: ['mp3'], autoplay: true, loop: false, volume: 0.5, - onend: action(() => (self.dataDoc.audioAnnoState = 'stopped')), + onend: action(() => (self.dataDoc.audioAnnoState = AudioAnnoState.stopped)), }); - this.dataDoc.audioAnnoState = 'playing'; + this.dataDoc.audioAnnoState = AudioAnnoState.playing; break; - case 'playing': + case AudioAnnoState.playing: this.dataDoc[AudioPlay]?.stop(); - this.dataDoc.audioAnnoState = 'stopped'; + this.dataDoc.audioAnnoState = AudioAnnoState.stopped; break; } } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index e80c869d3..fb709818c 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -51,7 +51,7 @@ import { SidebarAnnos } from '../../SidebarAnnos'; import { StyleProp } from '../../StyleProvider'; import { media_state } from '../AudioBox'; import { DocumentView, DocumentViewInternal, OpenWhere } from '../DocumentView'; -import { FocusViewOptions, FieldView, FieldViewProps } from '../FieldView'; +import { FieldView, FieldViewProps, FocusViewOptions } from '../FieldView'; import { LinkInfo } from '../LinkDocPreview'; import { PinProps, PresBox } from '../trails'; import { DashDocCommentView } from './DashDocCommentView'; @@ -271,29 +271,24 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent (stopFunc = stop)); - let reactionDisposer = reaction( + const reactionDisposer = reaction( () => target.mediaState, - action(dictation => { + dictation => { if (!dictation) { - targetData.audioAnnoState = 'stopped'; stopFunc(); reactionDisposer(); } - }) + } ); target.title = ComputedField.MakeFunction(`self["text_audioAnnotations_text"].lastElement()`); } }); }; - AnchorMenu.Instance.Highlight = undoable( - action((color: string, isLinkButton: boolean) => { - this._editorView?.state && RichTextMenu.Instance.setHighlight(color); - return undefined; - }), - 'highlght text' - ); + AnchorMenu.Instance.Highlight = undoable((color: string) => { + this._editorView?.state && RichTextMenu.Instance.setHighlight(color); + return undefined; + }, 'highlght text'); AnchorMenu.Instance.onMakeAnchor = () => this.getAnchor(true); AnchorMenu.Instance.StartCropDrag = unimplementedFunction; /** diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index d0688c338..59f191af0 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -46,7 +46,7 @@ export class AnchorMenu extends AntimodeMenu { public OnAudio: (e: PointerEvent) => void = unimplementedFunction; public StartDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction; public StartCropDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction; - public Highlight: (color: string, isTargetToggler: boolean, savedAnnotations?: ObservableMap, addAsAnnotation?: boolean) => Opt = (color: string, isTargetToggler: boolean) => undefined; + public Highlight: (color: string) => Opt = (color: string) => undefined; public GetAnchor: (savedAnnotations: Opt>, addAsAnnotation: boolean) => Opt = (savedAnnotations: Opt>, addAsAnnotation: boolean) => undefined; public Delete: () => void = unimplementedFunction; public PinToPres: () => void = unimplementedFunction; @@ -118,8 +118,8 @@ export class AnchorMenu extends AntimodeMenu { }; @action - highlightClicked = (e: React.MouseEvent) => { - this.Highlight(this.highlightColor, false, undefined, true); + highlightClicked = () => { + this.Highlight(this.highlightColor); AnchorMenu.Instance.fadeOut(true); }; diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index ea5411740..921d7aa5d 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -15,7 +15,7 @@ import { incrementTitleCopy, Utils } from '../Utils'; import { DateField } from './DateField'; import { AclAdmin, AclAugment, AclEdit, AclPrivate, AclReadonly, Animation, AudioPlay, Brushed, CachedUpdates, DirectLinks, - DocAcl, DocCss, DocData, DocFields, DocLayout, DocViews, FieldKeys, FieldTuples, ForceServerWrite, Height, Highlight, + DocAcl, DocCss, DocData, DocLayout, DocViews, FieldKeys, FieldTuples, ForceServerWrite, Height, Highlight, Initializing, Self, SelfProxy, TransitionTimer, UpdatingFromServer, Width } from './DocSymbols'; // prettier-ignore import { Copy, FieldChanged, HandleUpdate, Id, Parent, ToJavascriptString, ToScriptString, ToString } from './FieldSymbols'; @@ -227,7 +227,6 @@ export class Doc extends RefField { DocAcl, DocCss, DocData, - DocFields, DocLayout, DocViews, FieldKeys, @@ -308,7 +307,6 @@ export class Doc extends RefField { DocServer.UpdateField(this[Id], serverOp); } }; - public [DocFields] = () => this[Self][FieldTuples]; // Object.keys(this).reduce((fields, key) => { fields[key] = this[key]; return fields; }, {} as any); public [Width] = () => NumCast(this[SelfProxy]._width); public [Height] = () => NumCast(this[SelfProxy]._height); public [TransitionTimer]: any = undefined; diff --git a/src/fields/DocSymbols.ts b/src/fields/DocSymbols.ts index 64d657e4f..837fcc90e 100644 --- a/src/fields/DocSymbols.ts +++ b/src/fields/DocSymbols.ts @@ -1,8 +1,26 @@ -export const DocUpdated = Symbol('DocUpdated'); +// Symbols for fundamental Doc operations such as: permissions, field and proxy access and server interactions +export const AclPrivate = Symbol('DocAclOwnerOnly'); +export const AclReadonly = Symbol('DocAclReadOnly'); +export const AclAugment = Symbol('DocAclAugment'); +export const AclSelfEdit = Symbol('DocAclSelfEdit'); +export const AclEdit = Symbol('DocAclEdit'); +export const AclAdmin = Symbol('DocAclAdmin'); +export const DocAcl = Symbol('DocAcl'); +export const CachedUpdates = Symbol('DocCachedUpdates'); +export const UpdatingFromServer = Symbol('DocUpdatingFromServer'); +export const ForceServerWrite = Symbol('DocForceServerWrite'); export const Self = Symbol('DocSelf'); export const SelfProxy = Symbol('DocSelfProxy'); export const FieldKeys = Symbol('DocFieldKeys'); export const FieldTuples = Symbol('DocFieldTuples'); +export const Initializing = Symbol('DocInitializing'); + +// Symbols for core Dash document model including data docs, layout docs, and links +export const DocData = Symbol('DocData'); +export const DocLayout = Symbol('DocLayout'); +export const DirectLinks = Symbol('DocDirectLinks'); + +// Symbols for view related operations for Documents export const AudioPlay = Symbol('DocAudioPlay'); export const Width = Symbol('DocWidth'); export const Height = Symbol('DocHeight'); @@ -10,22 +28,7 @@ export const Animation = Symbol('DocAnimation'); export const Highlight = Symbol('DocHighlight'); export const DocViews = Symbol('DocViews'); export const Brushed = Symbol('DocBrushed'); -export const DocData = Symbol('DocData'); -export const DocLayout = Symbol('DocLayout'); -export const DocFields = Symbol('DocFields'); export const DocCss = Symbol('DocCss'); -export const DocAcl = Symbol('DocAcl'); export const TransitionTimer = Symbol('DocTransitionTimer'); -export const DirectLinks = Symbol('DocDirectLinks'); -export const AclPrivate = Symbol('DocAclOwnerOnly'); -export const AclReadonly = Symbol('DocAclReadOnly'); -export const AclAugment = Symbol('DocAclAugment'); -export const AclSelfEdit = Symbol('DocAclSelfEdit'); -export const AclEdit = Symbol('DocAclEdit'); -export const AclAdmin = Symbol('DocAclAdmin'); -export const UpdatingFromServer = Symbol('DocUpdatingFromServer'); -export const Initializing = Symbol('DocInitializing'); -export const ForceServerWrite = Symbol('DocForceServerWrite'); -export const CachedUpdates = Symbol('DocCachedUpdates'); export const DashVersion = 'v0.8.0'; -- cgit v1.2.3-70-g09d2 From 0fcfcdf78a7736b4ecb414f6127020bbcceee267 Mon Sep 17 00:00:00 2001 From: geireann Date: Thu, 14 Mar 2024 11:57:33 -0400 Subject: fixed dragging system documents in files sidebar --- src/client/views/collections/TreeView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index c6bbcb0a5..08c00d696 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -1055,7 +1055,7 @@ export class TreeView extends ObservableReactComponent { this, e, () => { - this._dref?.startDragging(e.clientX, e.clientY, '' as any); + (this._dref ?? this._docRef)?.startDragging(e.clientX, e.clientY, '' as any); return true; }, returnFalse, -- cgit v1.2.3-70-g09d2 From 92879a2f211f5e5c3c5fe5b28bd25a6f22d274ee Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 14 Mar 2024 16:34:21 -0400 Subject: Added a GPT capability to comparison boxes .. --- src/client/apis/gpt/GPT.ts | 6 +++--- src/client/views/nodes/ComparisonBox.tsx | 27 +++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index cea862330..fb51278ae 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -14,9 +14,9 @@ type GPTCallOpts = { }; const callTypeMap: { [type: string]: GPTCallOpts } = { - summary: { model: 'text-davinci-003', maxTokens: 256, temp: 0.5, prompt: 'Summarize this text in simpler terms: ' }, - edit: { model: 'text-davinci-003', maxTokens: 256, temp: 0.5, prompt: 'Reword this: ' }, - completion: { model: 'text-davinci-003', maxTokens: 256, temp: 0.5, prompt: '' }, + summary: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: 'Summarize this text in simpler terms: ' }, + edit: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: 'Reword this: ' }, + completion: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: '' }, }; /** diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index 2b57178f4..e759030f5 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -4,7 +4,7 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { emptyFunction, returnFalse, returnNone, returnZero, setupMoveUpEvents } from '../../../Utils'; import { Doc, Opt } from '../../../fields/Doc'; -import { DocCast, NumCast, StrCast } from '../../../fields/Types'; +import { DocCast, NumCast, RTFCast, StrCast } from '../../../fields/Types'; import { DocUtils, Docs } from '../../documents/Documents'; import { DragManager, dropActionType } from '../../util/DragManager'; import { undoBatch } from '../../util/UndoManager'; @@ -16,6 +16,8 @@ import { FieldView, FieldViewProps } from './FieldView'; import { PinProps, PresBox } from './trails'; import { FormattedTextBox } from './formattedText/FormattedTextBox'; import { RichTextField } from '../../../fields/RichTextField'; +import { GPTCallType, gptAPICall } from '../../apis/gpt/GPT'; +import { DocData } from '../../../fields/DocSymbols'; @observer export class ComparisonBox extends ViewBoxAnnotatableComponent() implements ViewBoxInterface { @@ -174,8 +176,29 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() const displayDoc = (which: string) => { const whichDoc = DocCast(this.dataDoc[which]); const targetDoc = DocCast(whichDoc?.annotationOn, whichDoc); + const subjectText = RTFCast(this.Document[this.fieldKey])?.Text; // if there is no Doc in the first comparison slot, but the comparison box's fieldKey slot has a RichTextField, then render a text box to show the contents of the document's field key slot - const layoutTemplateString = !targetDoc && which.endsWith('1') && this.Document[this.fieldKey] instanceof RichTextField ? FormattedTextBox.LayoutString(this.fieldKey) : undefined; + // of if there is no Doc in the second comparison slot, but the second slot has a RichTextField, then render a text box to show the contents of the document's field key slot + const layoutTemplateString = !targetDoc + ? which.endsWith('1') && subjectText !== undefined + ? FormattedTextBox.LayoutString(this.fieldKey) + : which.endsWith('2') && (this.Document[which] instanceof RichTextField || typeof this.Document[which] === 'string') + ? FormattedTextBox.LayoutString(which) + : undefined + : undefined; + + // A bit hacky to try out the concept of using GPT to fill in flashcards -- this whole process should probably be packaged into a script to be more generic. + // If the second slot doesn't have anything in it, but the fieldKey slot has text + // and the fieldKey + "_alternate" has a text that incldues "--TEXT--", then + // treat the fieldKey + "_altenrate" text as a GPT query parameterized by the fieldKey text + // Call GPT to fill in an "answer" value in the second slot. + if (which.endsWith('2') && !layoutTemplateString && !targetDoc) { + const queryText = RTFCast(this.Document[this.fieldKey + '_alternate'])?.Text; + if (queryText?.includes('--TEXT--') && subjectText) { + this.Document[DocData][this.fieldKey + '_2'] = ''; + gptAPICall(queryText?.replace('--TEXT--', subjectText), GPTCallType.COMPLETION).then(value => (this.Document[DocData][this.fieldKey + '_2'] = value.trim())); + } + } return targetDoc || layoutTemplateString ? ( <> Date: Sun, 17 Mar 2024 11:50:15 -0400 Subject: use metakey to edit computedfield result instead of expression in schema cell, set default new field values on data doc. fixed stacking view from autoresizing when switching to a different collection view. changed syntax for setting fields in text docs to use ':=' for computed fields. Added call to Chat in computed functions when (( )) is used. Added caching of computed function result when a function called by ComputedField uses the _setCacheResult_ method (currently only gptCallChat). --- src/client/documents/Documents.ts | 2 +- src/client/util/SnappingManager.ts | 5 +- src/client/views/GlobalKeyHandler.ts | 2 + .../views/collections/CollectionStackingView.tsx | 1 + .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- .../collectionSchema/CollectionSchemaView.tsx | 11 ++- .../collectionSchema/SchemaTableCell.tsx | 23 +++-- src/client/views/nodes/ComparisonBox.tsx | 35 ++++--- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FieldView.tsx | 6 +- src/client/views/nodes/KeyValueBox.tsx | 65 ++++++++----- src/client/views/nodes/KeyValuePair.tsx | 2 +- .../views/nodes/formattedText/DashFieldView.tsx | 2 +- .../views/nodes/formattedText/RichTextRules.ts | 36 +++++--- src/client/views/nodes/formattedText/nodes_rts.ts | 1 - src/fields/Doc.ts | 21 ++++- src/fields/ScriptField.ts | 102 +++++++++++++-------- src/server/public/assets/documentation.png | Bin 0 -> 4526 bytes 18 files changed, 203 insertions(+), 115 deletions(-) create mode 100644 src/server/public/assets/documentation.png (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index a13edec77..1d7c73306 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -175,7 +175,7 @@ class DateInfo extends FInfo { } class RtfInfo extends FInfo { constructor(d: string, filterable?: boolean) { - super(d, true); + super(d); this.filterable = filterable; } fieldType? = FInfoFieldType.rtf; diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts index 40c3f76fb..359140732 100644 --- a/src/client/util/SnappingManager.ts +++ b/src/client/util/SnappingManager.ts @@ -9,6 +9,7 @@ export class SnappingManager { @observable _shiftKey = false; @observable _ctrlKey = false; + @observable _metaKey = false; @observable _isLinkFollowing = false; @observable _isDragging: boolean = false; @observable _isResizing: Doc | undefined = undefined; @@ -32,6 +33,7 @@ export class SnappingManager { public static get VertSnapLines() { return this.Instance._vertSnapLines; } // 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 public static get IsLinkFollowing(){ return this.Instance._isLinkFollowing; } // prettier-ignore public static get IsDragging() { return this.Instance._isDragging; } // prettier-ignore public static get IsResizing() { return this.Instance._isResizing; } // prettier-ignore @@ -39,7 +41,8 @@ export class SnappingManager { public static get ExploreMode() { return this.Instance._exploreMode; } // 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 SetIsLinkFollowing= (follow: boolean) => runInAction(() => (this.Instance._isLinkFollowing = follow)); // prettier-ignore + public static SetMetaKey = (down: boolean) => runInAction(() => (this.Instance._metaKey = down)); // prettier-ignore + public static SetIsLinkFollowing= (follow:boolean)=> runInAction(() => (this.Instance._isLinkFollowing = follow)); // prettier-ignore public static SetIsDragging = (drag: boolean) => runInAction(() => (this.Instance._isDragging = drag)); // prettier-ignore public static SetIsResizing = (doc: Opt) => runInAction(() => (this.Instance._isResizing = doc)); // prettier-ignore public static SetCanEmbed = (embed:boolean) => runInAction(() => (this.Instance._canEmbed = embed)); // prettier-ignore diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index e800798ca..667d8dbb0 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -55,10 +55,12 @@ export class KeyManager { public handleModifiers = action((e: KeyboardEvent) => { if (e.shiftKey) SnappingManager.SetShiftKey(true); if (e.ctrlKey) SnappingManager.SetCtrlKey(true); + if (e.metaKey) SnappingManager.SetMetaKey(true); }); public unhandleModifiers = action((e: KeyboardEvent) => { if (!e.shiftKey) SnappingManager.SetShiftKey(false); if (!e.ctrlKey) SnappingManager.SetCtrlKey(false); + if (!e.metaKey) SnappingManager.SetMetaKey(false); }); public handle = action((e: KeyboardEvent) => { diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index ea1caf58f..2b23935eb 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -225,6 +225,7 @@ export class CollectionStackingView extends CollectionSubView this._disposers[key]()); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 7bfbbf3f9..b2fb5848e 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -249,7 +249,7 @@ export class CollectionFreeFormView extends CollectionSubView this.freeformData()?.bounds.cx ?? NumCast(this.Document[this.panXFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.freeform_panX, 1)); panY = () => this.freeformData()?.bounds.cy ?? NumCast(this.Document[this.panYFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.freeform_panY, 1)); - zoomScaling = () => this.freeformData()?.scale ?? NumCast(Doc.Layout(this.Document)[this.scaleFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.[this.scaleFieldKey], 1)); + zoomScaling = () => this.freeformData()?.scale ?? NumCast(Doc.Layout(this.Document)[this.scaleFieldKey], 1); //, NumCast(DocCast(this.Document.resolvedDataDoc)?.[this.scaleFieldKey], 1)); PanZoomCenterXf = () => this._props.isAnnotationOverlay && this.zoomScaling() === 1 ? `` : `translate(${this.cachedCenteringShiftX}px, ${this.cachedCenteringShiftY}px) scale(${this.zoomScaling()}) translate(${-this.panX()}px, ${-this.panY()}px)`; ScreenToContentsXf = () => this.screenToFreeformContentsXf.copy(); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 12f0ad5e9..4a0ca8fe5 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -1,5 +1,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, makeObservable, observable, ObservableMap, observe, trace } from 'mobx'; +import { Popup, PopupTrigger, Type } from 'browndash-components'; +import { action, computed, makeObservable, observable, ObservableMap, observe } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast, Field, NumListCast, Opt, StrListCast } from '../../../../fields/Doc'; @@ -12,12 +13,13 @@ import { Docs, DocumentOptions, DocUtils, FInfo } from '../../../documents/Docum import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager, dropActionType } from '../../../util/DragManager'; import { SelectionManager } from '../../../util/SelectionManager'; +import { SettingsManager } from '../../../util/SettingsManager'; import { undoable, undoBatch } from '../../../util/UndoManager'; import { ContextMenu } from '../../ContextMenu'; import { EditableView } from '../../EditableView'; import { Colors } from '../../global/globalEnums'; import { DocumentView } from '../../nodes/DocumentView'; -import { FocusViewOptions, FieldViewProps } from '../../nodes/FieldView'; +import { FieldViewProps, FocusViewOptions } from '../../nodes/FieldView'; import { KeyValueBox } from '../../nodes/KeyValueBox'; import { ObservableReactComponent } from '../../ObservableReactComponent'; import { DefaultStyleProvider, StyleProp } from '../../StyleProvider'; @@ -25,8 +27,7 @@ import { CollectionSubView } from '../CollectionSubView'; import './CollectionSchemaView.scss'; import { SchemaColumnHeader } from './SchemaColumnHeader'; import { SchemaRowBox } from './SchemaRowBox'; -import { Popup, PopupTrigger, Type } from 'browndash-components'; -import { SettingsManager } from '../../../util/SettingsManager'; +import { DocData } from '../../../../fields/DocSymbols'; const { default: { SCHEMA_NEW_NODE_HEIGHT } } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore export enum ColumnType { @@ -284,7 +285,7 @@ export class CollectionSchemaView extends CollectionSubView() { }; @action - addNewKey = (key: string, defaultVal: any) => this.childDocs.forEach(doc => (doc[key] = defaultVal)); + addNewKey = (key: string, defaultVal: any) => this.childDocs.forEach(doc => (doc[DocData][key] = defaultVal)); @undoBatch removeColumn = (index: number) => { diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index ed1b519b4..711ef507c 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -1,8 +1,11 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Popup, Size, Type } from 'browndash-components'; import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import { extname } from 'path'; import * as React from 'react'; import DatePicker from 'react-datepicker'; +import 'react-datepicker/dist/react-datepicker.css'; import Select from 'react-select'; import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero } from '../../../../Utils'; import { DateField } from '../../../../fields/DateField'; @@ -12,6 +15,8 @@ import { BoolCast, Cast, DateCast, DocCast, FieldValue, StrCast } from '../../.. import { ImageField } from '../../../../fields/URLField'; import { FInfo, FInfoFieldType } from '../../../documents/Documents'; import { DocFocusOrOpen } from '../../../util/DocumentManager'; +import { dropActionType } from '../../../util/DragManager'; +import { SettingsManager } from '../../../util/SettingsManager'; import { Transform } from '../../../util/Transform'; import { undoBatch, undoable } from '../../../util/UndoManager'; import { EditableView } from '../../EditableView'; @@ -24,12 +29,7 @@ import { KeyValueBox } from '../../nodes/KeyValueBox'; import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { ColumnType, FInfotoColType } from './CollectionSchemaView'; import './CollectionSchemaView.scss'; -import 'react-datepicker/dist/react-datepicker.css'; -import { Popup, Size, Type } from 'browndash-components'; -import { IconLookup, faCaretDown } from '@fortawesome/free-solid-svg-icons'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { SettingsManager } from '../../../util/SettingsManager'; -import { dropActionType } from '../../../util/DragManager'; +import { SnappingManager } from '../../../util/SnappingManager'; export interface SchemaTableCellProps { Document: Doc; @@ -129,10 +129,12 @@ export class SchemaTableCell extends ObservableReactComponent Field.toKeyValueString(this._props.Document, this._props.fieldKey)} + GetValue={() => Field.toKeyValueString(this._props.Document, this._props.fieldKey, SnappingManager.MetaKey)} SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => { if (shiftDown && enterKey) { this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value); + this._props.finishEdit?.(); + return true; } const ret = KeyValueBox.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), value, Doc.IsDataProto(this._props.Document) ? true : undefined); this._props.finishEdit?.(); @@ -345,8 +347,7 @@ export class SchemaBoolCell extends ObservableReactComponent | undefined) => { if ((value?.nativeEvent as any).shiftKey) { this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + value?.target?.checked.toString()); - } - KeyValueBox.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + value?.target?.checked.toString()); + } else KeyValueBox.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + value?.target?.checked.toString()); })} /> { if (shiftDown && enterKey) { this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value); + this._props.finishEdit?.(); + return true; } - const set = KeyValueBox.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), value); + const set = KeyValueBox.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), value, Doc.IsDataProto(this._props.Document) ? true : undefined); this._props.finishEdit?.(); return set; })} diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index e759030f5..715b23fb6 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -4,6 +4,7 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { emptyFunction, returnFalse, returnNone, returnZero, setupMoveUpEvents } from '../../../Utils'; import { Doc, Opt } from '../../../fields/Doc'; +import { RichTextField } from '../../../fields/RichTextField'; import { DocCast, NumCast, RTFCast, StrCast } from '../../../fields/Types'; import { DocUtils, Docs } from '../../documents/Documents'; import { DragManager, dropActionType } from '../../util/DragManager'; @@ -13,11 +14,9 @@ import { StyleProp } from '../StyleProvider'; import './ComparisonBox.scss'; import { DocumentView } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; -import { PinProps, PresBox } from './trails'; +import { KeyValueBox } from './KeyValueBox'; import { FormattedTextBox } from './formattedText/FormattedTextBox'; -import { RichTextField } from '../../../fields/RichTextField'; -import { GPTCallType, gptAPICall } from '../../apis/gpt/GPT'; -import { DocData } from '../../../fields/DocSymbols'; +import { PinProps, PresBox } from './trails'; @observer export class ComparisonBox extends ViewBoxAnnotatableComponent() implements ViewBoxInterface { @@ -173,10 +172,17 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent()
); }; + + /** + * Display the Docs in the before/after fields of the comparison. This also supports a GPT flash card use case + * where if there are no Docs in the slots, but the main fieldKey contains text, then + * @param which + * @returns + */ const displayDoc = (which: string) => { const whichDoc = DocCast(this.dataDoc[which]); const targetDoc = DocCast(whichDoc?.annotationOn, whichDoc); - const subjectText = RTFCast(this.Document[this.fieldKey])?.Text; + const subjectText = RTFCast(this.Document[this.fieldKey])?.Text.trim(); // if there is no Doc in the first comparison slot, but the comparison box's fieldKey slot has a RichTextField, then render a text box to show the contents of the document's field key slot // of if there is no Doc in the second comparison slot, but the second slot has a RichTextField, then render a text box to show the contents of the document's field key slot const layoutTemplateString = !targetDoc @@ -188,15 +194,18 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() : undefined; // A bit hacky to try out the concept of using GPT to fill in flashcards -- this whole process should probably be packaged into a script to be more generic. - // If the second slot doesn't have anything in it, but the fieldKey slot has text - // and the fieldKey + "_alternate" has a text that incldues "--TEXT--", then - // treat the fieldKey + "_altenrate" text as a GPT query parameterized by the fieldKey text - // Call GPT to fill in an "answer" value in the second slot. + // If the second slot doesn't have anything in it, but the fieldKey slot has text (e.g., this.text is a string) + // and the fieldKey + "_alternate" has text, then treat the _alternate's text as a GPT query (indicated by (( && )) ) that is parameterized (optionally) + // by the field references in the text (eg., this.text_alternate is + // "((Provide a one sentence definition for (this) that doesn't use any word in (this.excludeWords) ))" + // where (this) is replaced by the text in the fieldKey slot abd this.excludeWords is repalced by the conetnts of the excludeWords field + // A GPT call will put the "answer" in the second slot of the comparison (eg., text_2) if (which.endsWith('2') && !layoutTemplateString && !targetDoc) { - const queryText = RTFCast(this.Document[this.fieldKey + '_alternate'])?.Text; - if (queryText?.includes('--TEXT--') && subjectText) { - this.Document[DocData][this.fieldKey + '_2'] = ''; - gptAPICall(queryText?.replace('--TEXT--', subjectText), GPTCallType.COMPLETION).then(value => (this.Document[DocData][this.fieldKey + '_2'] = value.trim())); + var queryText = RTFCast(this.Document[this.fieldKey + '_alternate']) + ?.Text.replace('(this)', subjectText) // TODO: this should be done in KeyValueBox.setField but it doesn't know about the fieldKey ... + .trim(); + if (subjectText && queryText.match(/\(\(.*\)\)/)) { + KeyValueBox.SetField(this.Document, which, ':=' + queryText, false); // make the second slot be a computed field on the data doc that calls ChatGpt } } return targetDoc || layoutTemplateString ? ( diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index bbeacef88..9848f18e0 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1215,7 +1215,7 @@ export class DocumentView extends DocComponent() { if (layout_fieldKey && layout_fieldKey !== 'layout' && layout_fieldKey !== 'layout_icon') this.Document.deiconifyLayout = layout_fieldKey.replace('layout_', ''); } else { const deiconifyLayout = Cast(this.Document.deiconifyLayout, 'string', null); - this.switchViews(deiconifyLayout ? true : false, deiconifyLayout, finalFinished); + this.switchViews(deiconifyLayout ? true : false, deiconifyLayout, finalFinished, true); this.Document.deiconifyLayout = undefined; this._props.bringToFront?.(this.Document); } diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 8a49b4757..4ecaaa283 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -11,6 +11,7 @@ import { ViewBoxInterface } from '../DocComponent'; import { CollectionFreeFormDocumentView } from './CollectionFreeFormDocumentView'; import { DocumentView, OpenWhere } from './DocumentView'; import { PinProps } from './trails'; +import { computed } from 'mobx'; export interface FocusViewOptions { willPan?: boolean; // determines whether to pan to target document @@ -121,9 +122,12 @@ export class FieldView extends React.Component { public static LayoutString(fieldType: { name: string }, fieldStr: string) { return `<${fieldType.name} {...props} fieldKey={'${fieldStr}'}/>`; //e.g., "" } + @computed get fieldval() { + return this.props.Document[this.props.fieldKey]; + } render() { - const field = this.props.Document[this.props.fieldKey]; + const field = this.fieldval; // prettier-ignore if (field instanceof Doc) return

{field.title?.toString()}

; if (field === undefined) return

{''}

; diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 89a5ac0b8..2257e6455 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -6,7 +6,7 @@ import { Doc, Field, FieldResult } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { RichTextField } from '../../../fields/RichTextField'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; -import { DocCast } from '../../../fields/Types'; +import { DocCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { Docs } from '../../documents/Documents'; import { SetupDrag } from '../../util/DragManager'; @@ -71,34 +71,51 @@ export class KeyValueBox extends ObservableReactComponent { } } }; - public static CompileKVPScript(value: string): KVPScript | undefined { - const eq = value.startsWith('='); - value = eq ? value.substring(1) : value; - const dubEq = value.startsWith(':=') ? 'computed' : value.startsWith('$=') ? 'script' : false; - value = dubEq ? value.substring(2) : value; - const options: ScriptOptions = { addReturn: true, typecheck: false, params: { this: Doc.name, self: Doc.name, documentView: 'any', _last_: 'any', _readOnly_: 'boolean' }, editable: true }; - if (dubEq) options.typecheck = false; - const script = CompileScript(value, { ...options, transformer: DocumentIconContainer.getTransformer() }); - return !script.compiled ? undefined : { script, type: dubEq, onDelegate: eq }; + /** + * this compiles a string as a script after parsing off initial characters that determine script parameters + * if the script starts with '=', then it will be stored on the delegate of the Doc, otherise on the data doc + * if the script then starts with a ':=', then it will be treated as ComputedField, + * '$=', then it will just be a Script + * @param value + * @returns + */ + public static CompileKVPScript(rawvalue: string): KVPScript | undefined { + const onDelegate = rawvalue.startsWith('='); + rawvalue = onDelegate ? rawvalue.substring(1) : rawvalue; + const type: 'computed' | 'script' | false = rawvalue.startsWith(':=') ? 'computed' : rawvalue.startsWith('$=') ? 'script' : false; + rawvalue = type ? rawvalue.substring(2) : rawvalue; + rawvalue = rawvalue.replace(/.*\(\((.*)\)\)/, 'dashCallChat(_setCacheResult_, this, "$1")'); + const value = ["'", '"', '`'].includes(rawvalue.length ? rawvalue[0] : '') || !isNaN(rawvalue as any) ? rawvalue : '`' + rawvalue + '`'; + + var script = ScriptField.CompileScript(rawvalue, {}, true, undefined, DocumentIconContainer.getTransformer()); + if (!script.compiled) { + script = ScriptField.CompileScript(value, {}, true, undefined, DocumentIconContainer.getTransformer()); + } + return !script.compiled ? undefined : { script, type, onDelegate }; } - public static ApplyKVPScript(doc: Doc, key: string, kvpScript: KVPScript, forceOnDelegate?: boolean): boolean { + public static ApplyKVPScript(doc: Doc, key: string, kvpScript: KVPScript, forceOnDelegate?: boolean, setResult?: (value: FieldResult) => void) { const { script, type, onDelegate } = kvpScript; //const target = onDelegate ? Doc.Layout(doc.layout) : Doc.GetProto(doc); // bcz: TODO need to be able to set fields on layout templates const target = forceOnDelegate || onDelegate || key.startsWith('_') ? doc : DocCast(doc.proto, doc); - let field: Field; - if (type === 'computed') { - field = new ComputedField(script); - } else if (type === 'script') { - field = new ScriptField(script); - } else { - const res = script.run({ this: Doc.Layout(doc), self: doc }, console.log); - if (!res.success) { - target[key] = script.originalScript; - return true; + let field: Field | undefined; + switch (type) { + case 'computed': field = new ComputedField(script); break; // prettier-ignore + case 'script': field = new ScriptField(script); break; // prettier-ignore + default: { + const _setCacheResult_ = (value: FieldResult) => { + field = value as Field; + setResult?.(value); + }; + const res = script.run({ this: Doc.Layout(doc), self: doc, _setCacheResult_ }, console.log); + if (!res.success) { + if (key) target[key] = script.originalScript; + return false; + } + field === undefined && (field = res.result); } - field = res.result; } + if (!key) return field; if (Field.IsField(field, true) && (key !== 'proto' || field !== target)) { target[key] = field; return true; @@ -107,10 +124,10 @@ export class KeyValueBox extends ObservableReactComponent { } @undoBatch - public static SetField(doc: Doc, key: string, value: string, forceOnDelegate?: boolean) { + public static SetField(doc: Doc, key: string, value: string, forceOnDelegate?: boolean, setResult?: (value: FieldResult) => void) { const script = this.CompileKVPScript(value); if (!script) return false; - return this.ApplyKVPScript(doc, key, script, forceOnDelegate); + return this.ApplyKVPScript(doc, key, script, forceOnDelegate, setResult); } onPointerDown = (e: React.PointerEvent): void => { diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index f9e8ce4f3..d59489a78 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -125,7 +125,7 @@ export class KeyValuePair extends ObservableReactComponent { pinToPres: returnZero, }} GetValue={() => Field.toKeyValueString(this._props.doc, this._props.keyName)} - SetValue={(value: string) => KeyValueBox.SetField(this._props.doc, this._props.keyName, value)} + SetValue={(value: string) => (KeyValueBox.SetField(this._props.doc, this._props.keyName, value) ? true : false)} />
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index 5c4d850ad..62cb460c2 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -137,7 +137,7 @@ export class DashFieldViewInternal extends ObservableReactComponent this._props.tbox._props.PanelWidth() - 20 : returnZero} selectedCell={() => [this._dashDoc!, 0]} fieldKey={this._fieldKey} diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts index d5c91fc09..c798ae4b3 100644 --- a/src/client/views/nodes/formattedText/RichTextRules.ts +++ b/src/client/views/nodes/formattedText/RichTextRules.ts @@ -1,6 +1,6 @@ import { ellipsis, emDash, InputRule, smartQuotes, textblockTypeInputRule } from 'prosemirror-inputrules'; import { NodeSelection, TextSelection } from 'prosemirror-state'; -import { Doc, StrListCast } from '../../../../fields/Doc'; +import { Doc, FieldResult, StrListCast } from '../../../../fields/Doc'; import { DocData } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { List } from '../../../../fields/List'; @@ -8,13 +8,14 @@ import { NumCast, StrCast } from '../../../../fields/Types'; import { Utils } from '../../../../Utils'; import { DocServer } from '../../../DocServer'; import { Docs, DocUtils } from '../../../documents/Documents'; +import { CollectionViewType } from '../../../documents/DocumentTypes'; +import { CollectionView } from '../../collections/CollectionView'; +import { ContextMenu } from '../../ContextMenu'; +import { KeyValueBox } from '../KeyValueBox'; import { FormattedTextBox } from './FormattedTextBox'; import { wrappingInputRule } from './prosemirrorPatches'; import { RichTextMenu } from './RichTextMenu'; import { schema } from './schema_rts'; -import { CollectionView } from '../../collections/CollectionView'; -import { CollectionViewType } from '../../../documents/DocumentTypes'; -import { ContextMenu } from '../../ContextMenu'; export class RichTextRules { public Document: Doc; @@ -282,18 +283,28 @@ export class RichTextRules { : tr; }), + new InputRule(new RegExp(/(^|[^=])(\(\(.*\)\))/), (state, match, start, end) => { + var count = 0; // ignore first return value which will be the notation that chat is pending a result + KeyValueBox.SetField(this.Document, '', match[2], false, (gptval: FieldResult) => { + count && this.TextBox.EditorView?.dispatch(this.TextBox.EditorView!.state.tr.insertText(' ' + (gptval as string))); + count++; + }); + return null; + }), + // create a text display of a metadata field on this or another document, or create a hyperlink portal to another document // [[ : ]] // [[:docTitle]] => hyperlink // [[fieldKey]] => show field - // [[fieldKey=value]] => show field and also set its value + // [[fieldKey{:,=:}=value]] => show field and also set its value // [[fieldKey:docTitle]] => show field of doc new InputRule( - new RegExp(/\[\[([a-zA-Z_\? \-0-9]*)(=[a-z,A-Z_@\? /\-0-9]*)?(:[a-zA-Z_@:\.\? \-0-9]+)?\]\]$/), + new RegExp(/\[\[([a-zA-Z_\? \-0-9]*)((=:|:)?=)([a-z,A-Z_@\?+\-*/\ 0-9\(\)]*)?(:[a-zA-Z_@:\.\? \-0-9]+)?\]\]$/), (state, match, start, end) => { const fieldKey = match[1]; - const docTitle = match[3]?.replace(':', ''); - const value = match[2]?.substring(1); + const assign = match[2] === '=' ? '' : match[2]; + const value = match[4]; + const docTitle = match[5]?.replace(':', ''); const linkToDoc = (target: Doc) => { const rstate = this.TextBox.EditorView?.state; const selection = rstate?.selection.$from.pos; @@ -325,13 +336,14 @@ export class RichTextRules { } return state.tr; } - if (value?.includes(',')) { + // if the value has commas assume its an array (unless it's part of a chat gpt call indicated by '((' ) + if (value?.includes(',') && !value.startsWith('((')) { const values = value.split(','); const strs = values.some(v => !v.match(/^[-]?[0-9.]$/)); this.Document[DocData][fieldKey] = strs ? new List(values) : new List(values.map(v => Number(v))); - } else if (value !== '' && value !== undefined) { - const num = value.match(/^[0-9.]$/); - this.Document[DocData][fieldKey] = value === 'true' ? true : value === 'false' ? false : num ? Number(value) : value; + } else if (value) { + KeyValueBox.SetField(this.Document, fieldKey, assign + value, Doc.IsDataProto(this.Document) ? true : undefined, assign ? undefined: + (gptval: FieldResult) => this.Document[DocData][fieldKey] = gptval as string ); // prettier-ignore } const target = getTitledDoc(docTitle); const fieldView = state.schema.nodes.dashField.create({ fieldKey, docId: target?.[Id], hideKey: false }); diff --git a/src/client/views/nodes/formattedText/nodes_rts.ts b/src/client/views/nodes/formattedText/nodes_rts.ts index 4706a97fa..c9115be90 100644 --- a/src/client/views/nodes/formattedText/nodes_rts.ts +++ b/src/client/views/nodes/formattedText/nodes_rts.ts @@ -1,4 +1,3 @@ -import * as React from 'react'; import { DOMOutputSpec, Node, NodeSpec } from 'prosemirror-model'; import { listItem, orderedList } from 'prosemirror-schema-list'; import { ParagraphNodeSpec, toParagraphDOM, getParagraphNodeAttrs } from './ParagraphNodeSpec'; diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 921d7aa5d..30f5f716c 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -34,14 +34,29 @@ import * as JSZip from 'jszip'; import { FieldViewProps } from '../client/views/nodes/FieldView'; export const LinkedTo = '-linkedTo'; export namespace Field { - export function toKeyValueString(doc: Doc, key: string): string { - const onDelegate = Object.keys(doc).includes(key.replace(/^_/, '')); + /** + * Converts a field to its equivalent input string in the key value box such that if the string + * is entered into a keyValueBox it will create an equivalent field (except if showComputedValue is set). + * @param doc doc containing key + * @param key field key to display + * @param showComputedValue whether copmuted function should display its value instead of its function + * @returns string representation of the field + */ + export function toKeyValueString(doc: Doc, key: string, showComputedValue?: boolean): string { + const onDelegate = !Doc.IsDataProto(doc) && Object.keys(doc).includes(key.replace(/^_/, '')); const field = ComputedField.WithoutComputed(() => FieldValue(doc[key])); return !Field.IsField(field) ? key.startsWith('_') ? '=' : '' - : (onDelegate ? '=' : '') + (field instanceof ComputedField ? `:=${field.script.originalScript}` : field instanceof ScriptField ? `$=${field.script.originalScript}` : Field.toScriptString(field)); + : (onDelegate ? '=' : '') + + (field instanceof ComputedField && showComputedValue + ? field._lastComputedResult + : field instanceof ComputedField + ? `:=${field.script.originalScript}` + : field instanceof ScriptField + ? `$=${field.script.originalScript}` + : Field.toScriptString(field)); } export function toScriptString(field: Field) { switch (typeof field) { diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts index c7fe72ca6..9021c8896 100644 --- a/src/fields/ScriptField.ts +++ b/src/fields/ScriptField.ts @@ -1,15 +1,17 @@ +import { action, makeObservable, observable } from 'mobx'; import { computedFn } from 'mobx-utils'; import { createSimpleSchema, custom, map, object, primitive, PropSchema, serializable, SKIP } from 'serializr'; import { DocServer } from '../client/DocServer'; -import { CompiledScript, CompileScript, ScriptOptions } from '../client/util/Scripting'; +import { CompiledScript, CompileScript, ScriptOptions, Transformer } from '../client/util/Scripting'; import { scriptingGlobal, ScriptingGlobals } from '../client/util/ScriptingGlobals'; import { autoObject, Deserializable } from '../client/util/SerializationHelper'; import { numberRange } from '../Utils'; -import { Doc, Field, Opt } from './Doc'; -import { Copy, Id, ToJavascriptString, ToScriptString, ToString, ToValue } from './FieldSymbols'; +import { Doc, Field, FieldResult, Opt } from './Doc'; +import { Copy, FieldChanged, Id, ToJavascriptString, ToScriptString, ToString, ToValue } from './FieldSymbols'; import { List } from './List'; import { ObjectField } from './ObjectField'; import { Cast, StrCast } from './Types'; +import { GPTCallType, gptAPICall } from '../client/apis/gpt/GPT'; function optional(propSchema: PropSchema) { return custom( @@ -85,6 +87,13 @@ export class ScriptField extends ObjectField { readonly script: CompiledScript; @serializable(object(scriptSchema)) readonly setterscript: CompiledScript | undefined; + @serializable + @observable + _cachedResult: FieldResult = undefined; + setCacheResult = action((value: FieldResult) => { + this._cachedResult = value; + this[FieldChanged]?.(); + }); @serializable(autoObject()) captures?: List; @@ -122,21 +131,25 @@ export class ScriptField extends ObjectField { [ToString]() { return this.script.originalScript; } - public static CompileScript(script: string, params: object = {}, addReturn = false, capturedVariables?: { [name: string]: Doc | string | number | boolean }) { + public static CompileScript(script: string, params: object = {}, addReturn = false, capturedVariables?: { [name: string]: Doc | string | number | boolean }, transformer?: Transformer) { return CompileScript(script, { params: { this: Doc?.name || 'Doc', // this is the doc that executes the script self: Doc?.name || 'Doc', // self is the root doc of the doc that executes the script + documentView: 'any', _last_: 'any', // _last_ is the previous value of a computed field when it is being triggered to re-run. + _setCacheResult_: 'any', // set the cached value of the function _readOnly_: 'boolean', // _readOnly_ is set when a computed field is executed to indicate that it should not have mobx side-effects. used for checking the value of a set function (see FontIconBox) ...params, }, + transformer, typecheck: false, editable: true, addReturn: addReturn, capturedVariables, }); } + public static MakeFunction(script: string, params: object = {}, capturedVariables?: { [name: string]: Doc | string | number | boolean }) { const compiled = ScriptField.CompileScript(script, params, true, capturedVariables); return compiled.compiled ? new ScriptField(compiled) : undefined; @@ -146,29 +159,62 @@ export class ScriptField extends ObjectField { const compiled = ScriptField.CompileScript(script, params, false, capturedVariables); return compiled.compiled ? new ScriptField(compiled) : undefined; } + public static CallGpt(queryText: string, setVal: (val: FieldResult) => void, target: Doc) { + if (typeof queryText === 'string' && setVal) { + while (queryText.match(/\(this\.[a-zA-Z_]*\)/)?.length) { + const fieldRef = queryText.split('(this.')[1].replace(/\).*/, ''); + queryText = queryText.replace(/\(this\.[a-zA-Z_]*\)/, Field.toString(target[fieldRef] as Field)); + } + setVal(`Chat Pending: ${queryText}`); + gptAPICall(queryText, GPTCallType.COMPLETION).then(result => { + if (queryText.includes('#')) { + const matches = result.match(/-?[0-9][0-9,]+[.]?[0-9]*/); + if (matches?.length) setVal(Number(matches[0].replace(/,/g, ''))); + } else setVal(result.trim()); + }); + } + } } @scriptingGlobal @Deserializable('computed', deserializeScript) export class ComputedField extends ScriptField { - _lastComputedResult: any; - //TODO maybe add an observable cache based on what is passed in for doc, considering there shouldn't really be that many possible values for doc - value = computedFn((doc: Doc) => this._valueOutsideReaction(doc)); - _valueOutsideReaction = (doc: Doc) => (this._lastComputedResult = this.script.compiled && this.script.run({ this: doc, self: doc, value: '', _last_: this._lastComputedResult, _readOnly_: true }, console.log).result); - - [ToValue](doc: Doc) { - return ComputedField.toValue(doc, this); + static undefined = '__undefined'; + static useComputed = true; + static DisableComputedFields() { this.useComputed = false; } // prettier-ignore + static EnableComputedFields() { this.useComputed = true; } // prettier-ignore + static WithoutComputed(fn: () => T) { + this.DisableComputedFields(); + try { + return fn(); + } finally { + this.EnableComputedFields(); + } } - [Copy](): ObjectField { - return new ComputedField(this.script, this.setterscript, this.rawscript); + + constructor(script: CompiledScript | undefined, setterscript?: CompiledScript, rawscript?: string) { + super(script, setterscript, rawscript); + makeObservable(this); } + _lastComputedResult: FieldResult; + value = computedFn((doc: Doc) => this._valueOutsideReaction(doc)); + _valueOutsideReaction = (doc: Doc) => { + this._lastComputedResult = + this._cachedResult ?? (this.script.compiled && this.script.run({ this: doc, self: doc, value: '', _setCacheResult_: this.setCacheResult, _last_: this._lastComputedResult, _readOnly_: true }, console.log).result); + return this._lastComputedResult; + }; + + [ToValue](doc: Doc) { if (ComputedField.useComputed) return { value: this._valueOutsideReaction(doc) }; } // prettier-ignore + [Copy](): ObjectField { return new ComputedField(this.script, this.setterscript, this.rawscript); } // prettier-ignore + public static MakeFunction(script: string, params: object = {}, capturedVariables?: { [name: string]: Doc | string | number | boolean }, setterscript?: string) { const compiled = ScriptField.CompileScript(script, params, true, { value: '', ...capturedVariables }); const compiledsetter = setterscript ? ScriptField.CompileScript(setterscript, { ...params, value: 'any' }, false, capturedVariables) : undefined; const compiledsetscript = compiledsetter?.compiled ? compiledsetter : undefined; return compiled.compiled ? new ComputedField(compiled, compiledsetscript) : undefined; } + public static MakeInterpolatedNumber(fieldKey: string, interpolatorKey: string, doc: Doc, curTimecode: number, defaultVal: Opt) { if (!doc[`${fieldKey}_indexed`]) { const flist = new List(numberRange(curTimecode + 1).map(i => undefined) as any as number[]); @@ -206,33 +252,6 @@ export class ComputedField extends ScriptField { return (doc[`${fieldKey}`] = getField.compiled ? new ComputedField(getField, setField?.compiled ? setField : undefined) : undefined); } } -export namespace ComputedField { - let useComputed = true; - export function DisableComputedFields() { - useComputed = false; - } - - export function EnableComputedFields() { - useComputed = true; - } - - export const undefined = '__undefined'; - - export function WithoutComputed(fn: () => T) { - DisableComputedFields(); - try { - return fn(); - } finally { - EnableComputedFields(); - } - } - - export function toValue(doc: any, value: any) { - if (useComputed) { - return { value: value._valueOutsideReaction(doc) }; - } - } -} ScriptingGlobals.add( function setIndexVal(list: any[], index: number, value: any) { @@ -258,3 +277,6 @@ ScriptingGlobals.add( 'returns the value at a given index of a list', '(list: any[], index: number)' ); +ScriptingGlobals.add(function dashCallChat(setVal: (val: FieldResult) => void, target: Doc, queryText: string) { + ScriptField.CallGpt(queryText, setVal, target); +}, 'calls chat gpt for the query string and then calls setVal with the result'); diff --git a/src/server/public/assets/documentation.png b/src/server/public/assets/documentation.png new file mode 100644 index 000000000..95c76b198 Binary files /dev/null and b/src/server/public/assets/documentation.png differ -- cgit v1.2.3-70-g09d2 From 625c3a67fbcbfc93f1f1b35aed10b9fe7f33dfa9 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 17 Mar 2024 13:50:45 -0400 Subject: fixed displaying of chat gpt query to use (( )) notation. allow '"'s in chat gpt calls by escaping with "`" intead. --- src/client/views/nodes/KeyValueBox.tsx | 6 +++--- src/fields/Doc.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 2257e6455..2bcad806f 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -6,11 +6,11 @@ import { Doc, Field, FieldResult } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { RichTextField } from '../../../fields/RichTextField'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; -import { DocCast, StrCast } from '../../../fields/Types'; +import { DocCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { Docs } from '../../documents/Documents'; import { SetupDrag } from '../../util/DragManager'; -import { CompileScript, CompiledScript, ScriptOptions } from '../../util/Scripting'; +import { CompiledScript } from '../../util/Scripting'; import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; @@ -84,7 +84,7 @@ export class KeyValueBox extends ObservableReactComponent { rawvalue = onDelegate ? rawvalue.substring(1) : rawvalue; const type: 'computed' | 'script' | false = rawvalue.startsWith(':=') ? 'computed' : rawvalue.startsWith('$=') ? 'script' : false; rawvalue = type ? rawvalue.substring(2) : rawvalue; - rawvalue = rawvalue.replace(/.*\(\((.*)\)\)/, 'dashCallChat(_setCacheResult_, this, "$1")'); + rawvalue = rawvalue.replace(/.*\(\((.*)\)\)/, 'dashCallChat(_setCacheResult_, this, `$1`)'); const value = ["'", '"', '`'].includes(rawvalue.length ? rawvalue[0] : '') || !isNaN(rawvalue as any) ? rawvalue : '`' + rawvalue + '`'; var script = ScriptField.CompileScript(rawvalue, {}, true, undefined, DocumentIconContainer.getTransformer()); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 30f5f716c..daae32e9f 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -53,7 +53,7 @@ export namespace Field { (field instanceof ComputedField && showComputedValue ? field._lastComputedResult : field instanceof ComputedField - ? `:=${field.script.originalScript}` + ? `:=${field.script.originalScript.replace(/dashCallChat\(_setCacheResult_, this, `(.*)`\)/, '(($1))')}` : field instanceof ScriptField ? `$=${field.script.originalScript}` : Field.toScriptString(field)); -- cgit v1.2.3-70-g09d2 From fa0f4d5b4ce9ad3a891b719ca099f4bbc12f1096 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 18 Mar 2024 10:28:43 -0400 Subject: comments --- src/client/views/DocComponent.tsx | 61 ++++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index a25a8f77a..18e7ab12a 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -75,15 +75,25 @@ export function DocComponent

() { makeObservable(this); } - //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then + /** + * This is the document being rendered. In the case of a compound template, it + * may not be the actual document rendered and it also may not be the 'real' root document. + * Rather, it specifies the shared properties of all layouts of the document (eg, x,y,) + */ get Document() { return this._props.Document; } - // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info + + /** + * This is the document being rendered. It may be a template so it may or may no inherit from the data doc. + */ @computed get layoutDoc() { return this._props.LayoutTemplateString ? this.Document : Doc.Layout(this.Document, this._props.LayoutTemplate?.()); } - // This is the data part of a document -- ie, the data that is constant across all views of the document + + /** + * This is the unique data repository for a dcoument that stores the intrinsic document data + */ @computed get dataDoc() { return this.Document[DocData]; } @@ -109,19 +119,32 @@ export function ViewBoxBaseComponent

() { get DocumentView() { return this._props.DocumentView; } - //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then + + /** + * This is the document being rendered. In the case of a compound template, it + * may not be the actual document rendered and it also may not be the 'real' root document. + * Rather, it specifies the shared properties of all layouts of the document (eg, x,y,) + */ get Document() { return this._props.Document; } - // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info + /** + * This is the document being rendered. It may be a template so it may or may no inherit from the data doc. + */ @computed get layoutDoc() { return Doc.Layout(this.Document); } - // This is the data part of a document -- ie, the data that is constant across all views of the document + + /** + * This is the unique data repository for a dcoument that stores the intrinsic document data + */ @computed get dataDoc() { return this.Document.isTemplateForField || this.Document.isTemplateDoc ? this._props.TemplateDataDocument ?? this.Document[DocData] : this.Document[DocData]; } - // key where data is stored + + /** + * this is the field key where the primary rendering data is stored for the layout doc (e.g., it's often the 'data' field for a collection, or the 'text' field for rich text) + */ get fieldKey() { return this._props.fieldKey; } @@ -154,23 +177,39 @@ export function ViewBoxAnnotatableComponent

() { get DocumentView() { return this._props.DocumentView; } - //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then + + /** + * This is the document being rendered. In the case of a compound template, it + * may not be the actual document rendered and it also may not be the 'real' root document. + * Rather, it specifies the shared properties of all layouts of the document (eg, x,y,) + */ @computed get Document() { return this._props.Document; } - // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info + /** + * This is the document being rendered. It may be a template so it may or may no inherit from the data doc. + */ @computed get layoutDoc() { return Doc.Layout(this.Document); } - // This is the data part of a document -- ie, the data that is constant across all views of the document + + /** + * This is the unique data repository for a dcoument that stores the intrinsic document data + */ @computed get dataDoc() { return this.Document.isTemplateForField || this.Document.isTemplateDoc ? this._props.TemplateDataDocument ?? this.Document[DocData] : this.Document[DocData]; } - // key where data is stored + /** + * this is the field key where the primary rendering data is stored for the layout doc (e.g., it's often the 'data' field for a collection, or the 'text' field for rich text) + */ @computed get fieldKey() { return this._props.fieldKey; } + + /** + * this is field key where the list of annotations is stored + */ @computed public get annotationKey() { return this.fieldKey + (this._annotationKeySuffix() ? '_' + this._annotationKeySuffix() : ''); } -- cgit v1.2.3-70-g09d2 From 38be41b6ae73e0b295245d96636db74cb6848d6c Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 18 Mar 2024 10:29:17 -0400 Subject: changed pdf paste ref title --- src/client/views/MarqueeAnnotator.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 3c35b441b..bd6be2519 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -93,7 +93,7 @@ export class MarqueeAnnotator extends ObservableReactComponent' + this.props.Document.title, }); let minX = Number.MAX_VALUE; let maxX = -Number.MAX_VALUE; -- cgit v1.2.3-70-g09d2 From e576f88501da55a1e1abbcbc3260733da94bff8a Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 18 Mar 2024 10:29:47 -0400 Subject: link to pdf's data doc on paste --- src/client/views/pdf/PDFViewer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 0d4cfda88..a582f8004 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -5,7 +5,7 @@ import 'pdfjs-dist/web/pdf_viewer.css'; import * as PDFJSViewer from 'pdfjs-dist/web/pdf_viewer.mjs'; import * as React from 'react'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; -import { Height } from '../../../fields/DocSymbols'; +import { DocData, Height } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; @@ -135,7 +135,7 @@ export class PDFViewer extends ObservableReactComponent { const anchor = this._getAnchor(undefined, false); if (anchor) { anchor.textCopied = true; - e.clipboardData.setData('dash/pdfAnchor', anchor[Id]); + e.clipboardData.setData('dash/pdfAnchor', anchor[DocData][Id]); } e.preventDefault(); } -- cgit v1.2.3-70-g09d2 From 7d31c773ab85697b8a5eeecc752b567c8235efec Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 18 Mar 2024 10:30:23 -0400 Subject: cleanup --- src/client/views/nodes/DocumentContentsView.tsx | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 07e179246..5a326ecb0 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -135,8 +135,6 @@ export class DocumentContentsView extends ObservableReactComponent Date: Tue, 19 Mar 2024 17:08:46 -0400 Subject: cleaned up user templates to not get changed on reload. made setting a template add it to the template tools list and as a tools button. fixed linking to parts of a template. fixed disappearing templates caused by stacking view set a field with an empty key. updated field assignment syntax in trees, dash field views, and key value box to all use :,:=,=,=:= syntax. added text elide button. added @(title) syntax for hyperlinking. made using a template both inherit from the template to get default values and use the template to render. fixed submenu placement of context menu. updated RTF markdown doc. --- src/client/util/CurrentUserUtils.ts | 19 +++-- src/client/util/DropConverter.ts | 45 +++++----- src/client/util/LinkManager.ts | 13 +-- src/client/util/RTFMarkup.tsx | 30 +++---- src/client/views/ContextMenuItem.tsx | 2 +- src/client/views/TemplateMenu.scss | 1 + src/client/views/TemplateMenu.tsx | 7 +- .../collections/CollectionMasonryViewFieldRow.tsx | 10 +-- .../CollectionStackingViewFieldColumn.tsx | 6 +- src/client/views/collections/TreeView.tsx | 14 +++- src/client/views/global/globalScripts.ts | 33 +++----- src/client/views/nodes/ComparisonBox.tsx | 71 +++++++++------- src/client/views/nodes/DocumentView.tsx | 32 ++++++- src/client/views/nodes/FieldView.tsx | 1 + src/client/views/nodes/FontIconBox/FontIconBox.tsx | 22 ++--- src/client/views/nodes/KeyValueBox.tsx | 2 +- src/client/views/nodes/KeyValuePair.tsx | 2 +- .../views/nodes/formattedText/DashFieldView.tsx | 57 +++++++++---- .../views/nodes/formattedText/FormattedTextBox.tsx | 34 ++++---- .../views/nodes/formattedText/RichTextMenu.tsx | 13 +++ .../views/nodes/formattedText/RichTextRules.ts | 97 ++++++++++++---------- src/client/views/nodes/formattedText/marks_rts.ts | 5 +- src/client/views/nodes/formattedText/nodes_rts.ts | 2 + src/fields/Doc.ts | 42 +++++----- src/fields/util.ts | 4 + 25 files changed, 328 insertions(+), 236 deletions(-) (limited to 'src') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 84a33500d..bbee18707 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -73,7 +73,7 @@ export class CurrentUserUtils { }; const reqdScripts = { dropConverter : "convertToButtons(dragData)" }; const reqdFuncs = { /* hidden: "IsNoviceMode()" */ }; - return DocUtils.AssignScripts(DocUtils.AssignOpts(userDocTemplates, reqdOpts, userTemplates) ?? Docs.Create.MasonryDocument(userTemplates, reqdOpts), reqdScripts, reqdFuncs); + return DocUtils.AssignScripts(userDocTemplates ?? Docs.Create.MasonryDocument(userTemplates, reqdOpts), reqdScripts, reqdFuncs); } /// Initializes templates for editing click funcs of a document @@ -133,11 +133,19 @@ export class CurrentUserUtils { const reqdOpts:DocumentOptions = { title: "Note Layouts", _height: 75, isSystem: true }; return DocUtils.AssignOpts(tempNotes, reqdOpts, reqdNoteList) ?? (doc[field] = Docs.Create.TreeDocument(reqdNoteList, reqdOpts)); } + static setupUserTemplates(doc: Doc, field="template_user") { + const tempUsers = DocCast(doc[field]); + const reqdUserList = DocListCast(tempUsers?.data); + + const reqdOpts:DocumentOptions = { title: "User Layouts", _height: 75, isSystem: true }; + return DocUtils.AssignOpts(tempUsers, reqdOpts, reqdUserList) ?? (doc[field] = Docs.Create.TreeDocument(reqdUserList, reqdOpts)); + } /// Initializes collection of templates for notes and click functions static setupDocTemplates(doc: Doc, field="myTemplates") { const templates = [ CurrentUserUtils.setupNoteTemplates(doc), + CurrentUserUtils.setupUserTemplates(doc), CurrentUserUtils.setupClickEditorTemplates(doc) ]; CurrentUserUtils.setupChildClickEditors(doc) @@ -375,9 +383,9 @@ pie title Minerals in my tap water { toolTip: "Tap or drag to create a flashcard", title: "Flashcard", icon: "id-card", dragFactory: doc.emptyFlashcard as Doc, clickFactory: DocCast(doc.emptyFlashcard)}, { toolTip: "Tap or drag to create an equation", title: "Math", icon: "calculator", dragFactory: doc.emptyEquation as Doc, clickFactory: DocCast(doc.emptyEquation)}, { toolTip: "Tap or drag to create a mermaid node", title: "Mermaids", icon: "rocket", dragFactory: doc.emptyMermaids as Doc, clickFactory: DocCast(doc.emptyMermaids)}, - { toolTip: "Tap or drag to create a plotly node", title: "Plotly", icon: "rocket", dragFactory: doc.emptyPlotly as Doc, clickFactory: DocCast(doc.emptyMermaids)}, + { toolTip: "Tap or drag to create a plotly node", title: "Plotly", icon: "rocket", dragFactory: doc.emptyPlotly as Doc, clickFactory: DocCast(doc.emptyMermaids)}, { toolTip: "Tap or drag to create a physics simulation",title: "Simulation", icon: "rocket",dragFactory: doc.emptySimulation as Doc, clickFactory: DocCast(doc.emptySimulation), funcs: { hidden: "IsNoviceMode()"}}, - { toolTip: "Tap or drag to create a note board", title: "Notes", icon: "book", dragFactory: doc.emptyNoteboard as Doc, clickFactory: DocCast(doc.emptyNoteboard)}, + { toolTip: "Tap or drag to create a note board", title: "Notes", icon: "book", dragFactory: doc.emptyNoteboard as Doc, clickFactory: DocCast(doc.emptyNoteboard)}, { toolTip: "Tap or drag to create a collection", title: "Col", icon: "folder", dragFactory: doc.emptyCollection as Doc, clickFactory: DocCast(doc.emptyTab)}, { toolTip: "Tap or drag to create a webpage", title: "Web", icon: "globe-asia", dragFactory: doc.emptyWebpage as Doc, clickFactory: DocCast(doc.emptyWebpage)}, { toolTip: "Tap or drag to create a comparison box", title: "Compare", icon: "columns", dragFactory: doc.emptyComparison as Doc, clickFactory: DocCast(doc.emptyComparison)}, @@ -385,10 +393,10 @@ pie title Minerals in my tap water { toolTip: "Tap or drag to create a map", title: "Map", icon: "map-marker-alt", dragFactory: doc.emptyMap as Doc, clickFactory: DocCast(doc.emptyMap)}, { toolTip: "Tap or drag to create a screen grabber", title: "Grab", icon: "photo-video", dragFactory: doc.emptyScreengrab as Doc, clickFactory: DocCast(doc.emptyScreengrab), openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a WebCam recorder", title: "WebCam", icon: "photo-video", dragFactory: doc.emptyWebCam as Doc, clickFactory: DocCast(doc.emptyWebCam), openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}}, - { toolTip: "Tap or drag to create a button", title: "Button", icon: "circle", dragFactory: doc.emptyButton as Doc, clickFactory: DocCast(doc.emptyButton)}, + { toolTip: "Tap or drag to create a button", title: "Button", icon: "circle", dragFactory: doc.emptyButton as Doc, clickFactory: DocCast(doc.emptyButton)}, { toolTip: "Tap or drag to create a scripting box", title: "Script", icon: "terminal", dragFactory: doc.emptyScript as Doc, clickFactory: DocCast(doc.emptyScript), funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a data viz node", title: "DataViz", icon: "chart-bar", dragFactory: doc.emptyDataViz as Doc, clickFactory: DocCast(doc.emptyDataViz)}, - { toolTip: "Tap or drag to create a bullet slide", title: "PPT Slide", icon: "person-chalkboard", dragFactory: doc.emptySlide as Doc, clickFactory: DocCast(doc.emptySlide), openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}}, + { toolTip: "Tap or drag to create a bullet slide", title: "PPT Slide", icon: "person-chalkboard", dragFactory: doc.emptySlide as Doc, clickFactory: DocCast(doc.emptySlide), openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a view slide", title: "View Slide", icon: "address-card", dragFactory: doc.emptyViewSlide as Doc,clickFactory: DocCast(doc.emptyViewSlide),openFactoryLocation: OpenWhere.overlay,funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a data note", title: "DataNote", icon: "window-maximize",dragFactory: doc.emptyHeader as Doc,clickFactory: DocCast(doc.emptyHeader), openFactoryAsDelegate: true, funcs: { hidden: "IsNoviceMode()"} }, { toolTip: "Toggle a Calculator REPL", title: "replviewer", icon: "calculator", clickFactory: '' as any, openFactoryLocation: OpenWhere.overlay}, // hack: clickFactory is not a Doc but will get interpreted as a custom UI by the openDoc() onClick script @@ -738,6 +746,7 @@ pie title Minerals in my tap water { title: "Center", toolTip: "Center align (Cmd-\\)",btnType: ButtonType.ToggleButton, icon: "align-center",toolType:"center",ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} }, { title: "Right", toolTip: "Right align (Cmd-])", btnType: ButtonType.ToggleButton, icon: "align-right", toolType:"right", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} }, ]}, + { title: "Elide", toolTip: "Elide selection", btnType: ButtonType.ToggleButton, icon: "eye", toolType:"elide", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'}}, { title: "Dictate", toolTip: "Dictate", btnType: ButtonType.ToggleButton, icon: "microphone", toolType:"dictation", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'}}, { title: "NoLink", toolTip: "Auto Link", btnType: ButtonType.ToggleButton, icon: "link", toolType:"noAutoLink", expertMode:true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'}, funcs: {hidden: 'IsNoviceMode()'}}, // { title: "Strikethrough", tooltip: "Strikethrough", btnType: ButtonType.ToggleButton, icon: "strikethrough", scripts: {onClick:: 'toggleStrikethrough()'}}, diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts index 3df3e36c6..ed5749d06 100644 --- a/src/client/util/DropConverter.ts +++ b/src/client/util/DropConverter.ts @@ -28,6 +28,7 @@ export function MakeTemplate(doc: Doc) { } /** + * * Recursively converts 'doc' into a template that can be used to render other documents. * * For recurive Docs in the template, their target fieldKey is defined by their title, @@ -75,32 +76,36 @@ export function convertDropDataToButtons(data: DragManager.DocumentDragData) { remProps.map(prop => (dbox[prop] = undefined)); } } else if (!doc.onDragStart && !doc.isButtonBar) { - const layoutDoc = doc; // doc.layout instanceof Doc && doc.layout.isTemplateForField ? doc.layout : doc; - if (layoutDoc.type !== DocumentType.FONTICON) { - !layoutDoc.isTemplateDoc && makeTemplate(layoutDoc); - } - layoutDoc.isTemplateDoc = true; - dbox = Docs.Create.FontIconDocument({ - _nativeWidth: 100, - _nativeHeight: 100, - _width: 100, - _height: 100, - backgroundColor: StrCast(doc.backgroundColor), - title: StrCast(layoutDoc.title), - btnType: ButtonType.ClickButton, - icon: 'bolt', - isSystem: false, - }); - dbox.title = ComputedField.MakeFunction('this.dragFactory.title'); - dbox.dragFactory = layoutDoc; - dbox.dropPropertiesToRemove = doc.dropPropertiesToRemove instanceof ObjectField ? ObjectField.MakeCopy(doc.dropPropertiesToRemove) : undefined; - dbox.onDragStart = ScriptField.MakeFunction('makeDelegate(this.dragFactory)'); + dbox = makeUserTemplateButton(doc); } else if (doc.isButtonBar) { dbox.ignoreClick = true; } data.droppedDocuments[i] = dbox; }); } +export function makeUserTemplateButton(doc: Doc) { + const layoutDoc = doc; // doc.layout instanceof Doc && doc.layout.isTemplateForField ? doc.layout : doc; + if (layoutDoc.type !== DocumentType.FONTICON) { + !layoutDoc.isTemplateDoc && makeTemplate(layoutDoc); + } + layoutDoc.isTemplateDoc = true; + const dbox = Docs.Create.FontIconDocument({ + _nativeWidth: 100, + _nativeHeight: 100, + _width: 100, + _height: 100, + backgroundColor: StrCast(doc.backgroundColor), + title: StrCast(layoutDoc.title), + btnType: ButtonType.ClickButton, + icon: 'bolt', + isSystem: false, + }); + dbox.title = ComputedField.MakeFunction('this.dragFactory.title'); + dbox.dragFactory = layoutDoc; + dbox.dropPropertiesToRemove = doc.dropPropertiesToRemove instanceof ObjectField ? ObjectField.MakeCopy(doc.dropPropertiesToRemove) : undefined; + dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory)'); + return dbox; +} ScriptingGlobals.add( function convertToButtons(dragData: any) { convertDropDataToButtons(dragData as DragManager.DocumentDragData); diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 0c8d18a7a..cf16c4d6d 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -58,8 +58,8 @@ export class LinkManager { link && action(lAnchProtoProtos => { Doc.AddDocToList(Doc.UserDoc(), 'links', link); - lAnchs[0] && lAnchs[0][DocData][DirectLinks].add(link); - lAnchs[1] && lAnchs[1][DocData][DirectLinks].add(link); + lAnchs[0]?.[DocData][DirectLinks].add(link); + lAnchs[1]?.[DocData][DirectLinks].add(link); }) ) ) @@ -170,10 +170,11 @@ export class LinkManager { console.log('WAITING FOR DOC/PROTO IN LINKMANAGER'); return []; } - const dirLinks = Doc.GetProto(anchor)[DirectLinks]; - const annos = DocListCast(anchor[Doc.LayoutFieldKey(anchor) + '_annotations']); - if (!annos) debugger; - return annos.reduce((list, anno) => [...list, ...LinkManager.Instance.relatedLinker(anno)], Array.from(dirLinks).slice()); + + const dirLinks = Array.from(anchor[DocData][DirectLinks]).filter(l => Doc.GetProto(anchor) === anchor[DocData] || ['1', '2'].includes(LinkManager.anchorIndex(l, anchor) as any)); + const anchorRoot = DocCast(anchor.rootDocument, anchor); // template Doc fields store annotations on the topmost root of a template (not on themselves since the template layout items are only for layout) + const annos = DocListCast(anchorRoot[Doc.LayoutFieldKey(anchor) + '_annotations']); + return annos.reduce((list, anno) => [...list, ...LinkManager.Instance.relatedLinker(anno)], Array.from(dirLinks)); }, true); // returns map of group type to anchor's links in that group type diff --git a/src/client/util/RTFMarkup.tsx b/src/client/util/RTFMarkup.tsx index f96d8a5df..315daad42 100644 --- a/src/client/util/RTFMarkup.tsx +++ b/src/client/util/RTFMarkup.tsx @@ -3,18 +3,12 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { MainViewModal } from '../views/MainViewModal'; import { SettingsManager } from './SettingsManager'; -import { Doc } from '../../fields/Doc'; -import { StrCast } from '../../fields/Types'; @observer export class RTFMarkup extends React.Component<{}> { static Instance: RTFMarkup; @observable private isOpen = false; // whether the SharingManager modal is open or not - // private get linkVisible() { - // return this.targetDoc ? this.targetDoc["acl-" + PublicKey] !== SharingPermissions.None : false; - // } - @action public open = () => (this.isOpen = true); @@ -39,6 +33,10 @@ export class RTFMarkup extends React.Component<{}> { {`wiki:phrase`} {` display wikipedia page for entered text (terminate with carriage return)`}

+

+ {`(( any text ))`} + {` submit text to Chat GPT to have results appended afterward`} +

{`#tag `} {` add hashtag metadata to document. e.g, #idea`} @@ -47,10 +45,6 @@ export class RTFMarkup extends React.Component<{}> { {`#, ## ... ###### `} {` set heading style based on number of '#'s between 1 and 6`}

-

- {`#tag `} - {` add hashtag metadata to document. e.g, #idea`} -

{`>> `} {` add a sidebar text document inline`} @@ -61,7 +55,7 @@ export class RTFMarkup extends React.Component<{}> {

{`cmd-f `} - {` collapse to an inline footnote)`} + {` collapse to an inline footnote`}

{`cmd-e `} @@ -116,20 +110,20 @@ export class RTFMarkup extends React.Component<{}> { {` start a block of text that begins with a hanging indent`}

- {`[:doctitle]] `} + {`@(doctitle) `} {` hyperlink to document specified by it’s title`}

- {`[[fieldname]] `} - {` display value of fieldname`} + {`[@(doctitle.)fieldname] `} + {` display value of fieldname of text document (unless (doctitle.) is used to indicate another document by it's title)`}

- {`[[fieldname=value]] `} - {` assign value to fieldname of document and display it`} + {`[@fieldname:value] `} + {` assign value to fieldname to data document and display it (if '=' is used instead of ':' the value is set on the layout Doc. if value is wrapped in (()) then it will be sent to ChatGPT and the response will replace the value)`}

- {`[[fieldname:doctitle]] `} - {` show value of fieldname from doc specified by it’s title`} + {`[@fieldname:=expression] `} + {` assign a computed expression to fieldname to data document and display it (if '=:=' is used instead of ':=' the expression is set on the layout Doc. if value is wrapped in (()) then it will be sent to ChatGPT and the prompt/response will replace the value)`}

); diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index b2076e1a5..d15ab749c 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -113,7 +113,7 @@ export class ContextMenuItem extends ObservableReactComponent 0 ? '90%' : '20%', + marginLeft: window.innerWidth - this._overPosX - 50 > 0 ? '90%' : '20%', marginTop, background: SettingsManager.userBackgroundColor, }}> diff --git a/src/client/views/TemplateMenu.scss b/src/client/views/TemplateMenu.scss index 4d0f1bf00..36a9ce6d0 100644 --- a/src/client/views/TemplateMenu.scss +++ b/src/client/views/TemplateMenu.scss @@ -39,6 +39,7 @@ display: inline-block; height: 100%; width: 100%; + max-height: 250px; .templateToggle, .chromeToggle { diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index eed197b0b..e7269df98 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -1,7 +1,8 @@ -import { action, computed, observable, ObservableSet, runInAction } from 'mobx'; +import { computed, observable, ObservableSet, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast } from '../../fields/Doc'; +import { DocData } from '../../fields/DocSymbols'; import { ScriptField } from '../../fields/ScriptField'; import { Cast, DocCast, StrCast } from '../../fields/Types'; import { TraceMobx } from '../../fields/util'; @@ -9,12 +10,10 @@ import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, retu import { Docs, DocUtils } from '../documents/Documents'; import { ScriptingGlobals } from '../util/ScriptingGlobals'; import { Transform } from '../util/Transform'; -import { undoBatch } from '../util/UndoManager'; import { CollectionTreeView } from './collections/CollectionTreeView'; import { DocumentView, returnEmptyDocViewList } from './nodes/DocumentView'; import { DefaultStyleProvider } from './StyleProvider'; import './TemplateMenu.scss'; -import { DocData } from '../../fields/DocSymbols'; @observer class TemplateToggle extends React.Component<{ template: string; checked: boolean; toggle: (event: React.ChangeEvent, template: string) => void }> { @@ -99,7 +98,7 @@ export class TemplateMenu extends React.Component { .filter(key => !noteTypes.some(nt => nt.title === key)) .forEach(template => templateMenu.push( this.toggleLayout(e, template)} />)); return ( -
    +
      {Doc.noviceMode ? null : } {templateMenu} Doc.SetInPlace(d, key, castedValue, !onLayoutDoc)); + key && de.complete.docDragData.droppedDocuments.forEach(d => Doc.SetInPlace(d, key, castedValue, !this.onLayoutDoc(key))); } return true; } @@ -128,7 +127,7 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent Doc.SetInPlace(d, key, castedValue, true)); + key && this._props.docList.forEach(d => Doc.SetInPlace(d, key, castedValue, true)); this._heading = castedValue.toString(); return true; } @@ -155,10 +154,9 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent { this._createEmbeddingSelected = false; const key = this._props.pivotField; - this._props.docList.forEach(d => Doc.SetInPlace(d, key, undefined, true)); + key && this._props.docList.forEach(d => Doc.SetInPlace(d, key, undefined, true)); if (this._props.parent.colHeaderData && this._props.headingObject) { const index = this._props.parent.colHeaderData.indexOf(this._props.headingObject); this._props.parent.colHeaderData.splice(index, 1); diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 6a3cb759e..641e01b81 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -112,7 +112,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent< if (this._props.colHeaderData?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) { return false; } - this._props.docList.forEach(d => (d[this._props.pivotField] = castedValue)); + this._props.pivotField && this._props.docList.forEach(d => (d[this._props.pivotField] = castedValue)); if (this._props.headingObject) { this._props.headingObject.setHeading(castedValue.toString()); this._heading = this._props.headingObject.heading; @@ -137,7 +137,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent< if (!value && !forceEmptyNote) return false; const key = this._props.pivotField; const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, _layout_fitWidth: true, title: value, _layout_autoHeight: true }); - newDoc[key] = this.getValue(this._props.heading); + key && (newDoc[key] = this.getValue(this._props.heading)); const maxHeading = this._props.docList.reduce((maxHeading, doc) => (NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading), 0); const heading = maxHeading === 0 || this._props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3; newDoc.heading = heading; @@ -148,7 +148,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent< @action deleteColumn = () => { - this._props.docList.forEach(d => (d[this._props.pivotField] = undefined)); + this._props.pivotField && this._props.docList.forEach(d => (d[this._props.pivotField] = undefined)); if (this._props.colHeaderData && this._props.headingObject) { const index = this._props.colHeaderData.indexOf(this._props.headingObject); this._props.colHeaderData.splice(index, 1); diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 08c00d696..1b4349f44 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -574,11 +574,21 @@ export class TreeView extends ObservableReactComponent {
      value.indexOf(':') !== -1 && KeyValueBox.SetField(doc, value.substring(0, value.indexOf(':')), value.substring(value.indexOf(':') + 1, value.length), true)} + SetValue={input => { + const match = input.match(/([a-zA-Z0-9_-]+)(=|=:=)([a-zA-Z,_@\?\+\-\*\/\ 0-9\(\)]+)/); + if (match) { + const key = match[1]; + const assign = match[2]; + const val = match[3]; + KeyValueBox.SetField(doc, key, assign + val, false); + return true; + } + return false; + }} />
      ); diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 0579b07c7..3fdc9a488 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -1,29 +1,26 @@ import { Colors } from 'browndash-components'; import { action, runInAction } from 'mobx'; +import { aggregateBounds } from '../../../Utils'; import { Doc, Opt } from '../../../fields/Doc'; import { InkTool } from '../../../fields/InkField'; import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types'; import { WebField } from '../../../fields/URLField'; import { GestureUtils } from '../../../pen-gestures/GestureUtils'; -import { aggregateBounds } from '../../../Utils'; import { DocumentType } from '../../documents/DocumentTypes'; import { LinkManager } from '../../util/LinkManager'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { SelectionManager } from '../../util/SelectionManager'; -import { undoable, UndoManager } from '../../util/UndoManager'; -import { CollectionFreeFormView } from '../collections/collectionFreeForm'; +import { UndoManager, undoable } from '../../util/UndoManager'; import { GestureOverlay } from '../GestureOverlay'; import { ActiveFillColor, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, InkingStroke, SetActiveFillColor, SetActiveInkColor, SetActiveInkWidth, SetActiveIsInkMask } from '../InkingStroke'; +import { CollectionFreeFormView } from '../collections/collectionFreeForm'; // import { InkTranscription } from '../InkTranscription'; +import { DocData } from '../../../fields/DocSymbols'; import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocumentView'; import { DocumentView } from '../nodes/DocumentView'; -import { RichTextMenu } from '../nodes/formattedText/RichTextMenu'; -import { WebBox } from '../nodes/WebBox'; import { VideoBox } from '../nodes/VideoBox'; -import { DocData } from '../../../fields/DocSymbols'; -import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; -import { PrefetchProxy } from '../../../fields/Proxy'; -import { MakeTemplate } from '../../util/DropConverter'; +import { WebBox } from '../nodes/WebBox'; +import { RichTextMenu } from '../nodes/formattedText/RichTextMenu'; ScriptingGlobals.add(function IsNoneSelected() { return SelectionManager.Views.length <= 0; @@ -76,19 +73,7 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b // toggle: Set overlay status of selected document ScriptingGlobals.add(function setDefaultTemplate(checkResult?: boolean) { - if (checkResult) { - return Doc.UserDoc().defaultTextLayout; - } - const view = SelectionManager.Views.length === 1 && SelectionManager.Views[0].ComponentView instanceof FormattedTextBox ? SelectionManager.Views[0] : undefined; - - if (view) { - const tempDoc = view.Document; - if (!view.layoutDoc.isTemplateDoc) { - MakeTemplate(tempDoc); - } - Doc.UserDoc().defaultTextLayout = new PrefetchProxy(tempDoc); - tempDoc && Doc.AddDocToList(Cast(Doc.UserDoc().template_notes, Doc, null), 'data', tempDoc); - } else Doc.UserDoc().defaultTextLayout = undefined; + return DocumentView.setDefaultTemplate(checkResult); }); // toggle: Set overlay status of selected document ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boolean) { @@ -197,7 +182,7 @@ ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highligh map.get(attr)?.setDoc?.(); }); -type attrname = 'noAutoLink' | 'dictation' | 'bold' | 'italics' | 'underline' | 'left' | 'center' | 'right' | 'vcent' | 'bullet' | 'decimal'; +type attrname = 'noAutoLink' | 'dictation' | 'bold' | 'italics' | 'elide' | 'underline' | 'left' | 'center' | 'right' | 'vcent' | 'bullet' | 'decimal'; type attrfuncs = [attrname, { checkResult: () => boolean; toggle: () => any }]; ScriptingGlobals.add(function toggleCharStyle(charStyle: attrname, checkResult?: boolean) { @@ -221,6 +206,8 @@ ScriptingGlobals.add(function toggleCharStyle(charStyle: attrname, checkResult?: const attrs:attrfuncs[] = [ ['dictation', { checkResult: () => textView?._recordingDictation ? true:false, toggle: () => textView && runInAction(() => (textView._recordingDictation = !textView._recordingDictation)) }], + ['elide', { checkResult: () => false, + toggle: () => editorView ? RichTextMenu.Instance?.elideSelection(): 0}], ['noAutoLink',{ checkResult: () => (editorView ? RichTextMenu.Instance.noAutoLink : false), toggle: () => editorView && RichTextMenu.Instance?.toggleNoAutoLinkAnchor()}], ['bold', { checkResult: () => (editorView ? RichTextMenu.Instance.bold : (Doc.UserDoc().fontWeight === 'bold') ? true:false), diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index 715b23fb6..62f630c6c 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -159,6 +159,37 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() moveDoc2 = (doc: Doc | Doc[], targetCol: Doc | undefined, addDoc: any) => (doc instanceof Doc ? [doc] : doc).reduce((res, doc: Doc) => res && this.moveDoc(doc, addDoc, this.fieldKey + '_2'), true); remDoc1 = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((res, doc) => res && this.remDoc(doc, this.fieldKey + '_1'), true); remDoc2 = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((res, doc) => res && this.remDoc(doc, this.fieldKey + '_2'), true); + + /** + * Tests for whether a comparison box slot (ie, before or after) has renderable text content + * @param whichSlot field key for start or end slot + * @returns a JSX layout string if a text field is found, othwerise undefined + */ + testForTextFields = (whichSlot: string) => { + const slotHasText = Doc.Get(this.dataDoc, whichSlot, true) instanceof RichTextField || typeof Doc.Get(this.dataDoc, whichSlot, true) === 'string'; + const subjectText = RTFCast(this.Document[this.fieldKey])?.Text.trim(); + const altText = RTFCast(this.Document[this.fieldKey + '_alternate'])?.Text.trim(); + const layoutTemplateString = + slotHasText ? FormattedTextBox.LayoutString(whichSlot): + whichSlot.endsWith('1') ? (subjectText !== undefined ? FormattedTextBox.LayoutString(this.fieldKey) : undefined) : + altText !== undefined ? FormattedTextBox.LayoutString(this.fieldKey + '_alternate'): undefined; // prettier-ignore + + // A bit hacky to try out the concept of using GPT to fill in flashcards + // If the second slot doesn't have anything in it, but the fieldKey slot has text (e.g., this.text is a string) + // and the fieldKey + "_alternate" has text that includes a GPT query (indicated by (( && )) ) that is parameterized (optionally) by the fieldKey text (this) or other metadata (this.). + // eg., this.text_alternate is + // "((Provide a one sentence definition for (this) that doesn't use any word in (this.excludeWords) ))" + // where (this) is replaced by the text in the fieldKey slot abd this.excludeWords is repalced by the conetnts of the excludeWords field + // The GPT call will put the "answer" in the second slot of the comparison (eg., text_2) + if (whichSlot.endsWith('2') && !layoutTemplateString?.includes(whichSlot)) { + var queryText = altText.replace('(this)', subjectText); // TODO: this should be done in KeyValueBox.setField but it doesn't know about the fieldKey ... + if (queryText && queryText.match(/\(\(.*\)\)/)) { + KeyValueBox.SetField(this.Document, whichSlot, ':=' + queryText, false); // make the second slot be a computed field on the data doc that calls ChatGpt + } + } + return layoutTemplateString; + }; + _closeRef = React.createRef(); render() { const clearButton = (which: string) => { @@ -176,48 +207,24 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() /** * Display the Docs in the before/after fields of the comparison. This also supports a GPT flash card use case * where if there are no Docs in the slots, but the main fieldKey contains text, then - * @param which + * @param whichSlot * @returns */ - const displayDoc = (which: string) => { - const whichDoc = DocCast(this.dataDoc[which]); + const displayDoc = (whichSlot: string) => { + const whichDoc = DocCast(this.dataDoc[whichSlot]); const targetDoc = DocCast(whichDoc?.annotationOn, whichDoc); - const subjectText = RTFCast(this.Document[this.fieldKey])?.Text.trim(); - // if there is no Doc in the first comparison slot, but the comparison box's fieldKey slot has a RichTextField, then render a text box to show the contents of the document's field key slot - // of if there is no Doc in the second comparison slot, but the second slot has a RichTextField, then render a text box to show the contents of the document's field key slot - const layoutTemplateString = !targetDoc - ? which.endsWith('1') && subjectText !== undefined - ? FormattedTextBox.LayoutString(this.fieldKey) - : which.endsWith('2') && (this.Document[which] instanceof RichTextField || typeof this.Document[which] === 'string') - ? FormattedTextBox.LayoutString(which) - : undefined - : undefined; - - // A bit hacky to try out the concept of using GPT to fill in flashcards -- this whole process should probably be packaged into a script to be more generic. - // If the second slot doesn't have anything in it, but the fieldKey slot has text (e.g., this.text is a string) - // and the fieldKey + "_alternate" has text, then treat the _alternate's text as a GPT query (indicated by (( && )) ) that is parameterized (optionally) - // by the field references in the text (eg., this.text_alternate is - // "((Provide a one sentence definition for (this) that doesn't use any word in (this.excludeWords) ))" - // where (this) is replaced by the text in the fieldKey slot abd this.excludeWords is repalced by the conetnts of the excludeWords field - // A GPT call will put the "answer" in the second slot of the comparison (eg., text_2) - if (which.endsWith('2') && !layoutTemplateString && !targetDoc) { - var queryText = RTFCast(this.Document[this.fieldKey + '_alternate']) - ?.Text.replace('(this)', subjectText) // TODO: this should be done in KeyValueBox.setField but it doesn't know about the fieldKey ... - .trim(); - if (subjectText && queryText.match(/\(\(.*\)\)/)) { - KeyValueBox.SetField(this.Document, which, ':=' + queryText, false); // make the second slot be a computed field on the data doc that calls ChatGpt - } - } + const layoutTemplateString = targetDoc ? '' : this.testForTextFields(whichSlot); return targetDoc || layoutTemplateString ? ( <> () hideLinkButton={true} pointerEvents={this._isAnyChildContentActive ? undefined : returnNone} /> - {layoutTemplateString ? null : clearButton(which)} + {layoutTemplateString ? null : clearButton(whichSlot)} // placeholder image if doc is missing ) : (
      diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 9848f18e0..e9ce98583 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -10,6 +10,7 @@ import { AclPrivate, Animation, AudioPlay, DocData, DocViews } from '../../../fi import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; +import { PrefetchProxy } from '../../../fields/Proxy'; import { listSpec } from '../../../fields/Schema'; import { ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; @@ -19,10 +20,11 @@ import { DocServer } from '../../DocServer'; import { Networking } from '../../Network'; import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; -import { DocOptions, DocUtils, Docs } from '../../documents/Documents'; +import { DocUtils, Docs } from '../../documents/Documents'; import { DictationManager } from '../../util/DictationManager'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType } from '../../util/DragManager'; +import { MakeTemplate, makeUserTemplateButton } from '../../util/DropConverter'; import { FollowLinkScript } from '../../util/LinkFollower'; import { LinkManager } from '../../util/LinkManager'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; @@ -36,6 +38,7 @@ import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { DocComponent, ViewBoxInterface } from '../DocComponent'; import { EditableView } from '../EditableView'; +import { FieldsDropdown } from '../FieldsDropdown'; import { GestureOverlay } from '../GestureOverlay'; import { LightboxView } from '../LightboxView'; import { AudioAnnoState, StyleProp } from '../StyleProvider'; @@ -47,7 +50,6 @@ import { KeyValueBox } from './KeyValueBox'; import { LinkAnchorBox } from './LinkAnchorBox'; import { FormattedTextBox } from './formattedText/FormattedTextBox'; import { PresEffect, PresEffectDirection } from './trails'; -import { FieldsDropdown } from '../FieldsDropdown'; interface Window { MediaRecorder: MediaRecorder; } @@ -1271,6 +1273,32 @@ export class DocumentView extends DocComponent() { custom && DocUtils.makeCustomViewClicked(this.Document, Docs.Create.StackingDocument, layout, undefined); }, 'set custom view'); + public static setDefaultTemplate(checkResult?: boolean) { + if (checkResult) { + return Doc.UserDoc().defaultTextLayout; + } + const view = SelectionManager.Views[0]?._props.renderDepth > 0 ? SelectionManager.Views[0] : undefined; + undoable(() => { + var tempDoc: Opt; + if (view) { + if (!view.layoutDoc.isTemplateDoc) { + tempDoc = view.Document; + MakeTemplate(tempDoc); + Doc.AddDocToList(Doc.UserDoc(), 'template_user', tempDoc); + Doc.AddDocToList(DocListCast(Doc.MyTools.data)[1], 'data', makeUserTemplateButton(tempDoc)); + tempDoc && Doc.AddDocToList(Cast(Doc.UserDoc().template_user, Doc, null), 'data', tempDoc); + } else { + tempDoc = DocCast(view.Document[StrCast(view.Document.layout_fieldKey)]); + if (!tempDoc) { + tempDoc = view.Document; + while (tempDoc && !Doc.isTemplateDoc(tempDoc)) tempDoc = DocCast(tempDoc.proto); + } + } + } + Doc.UserDoc().defaultTextLayout = tempDoc ? new PrefetchProxy(tempDoc) : undefined; + }, 'set default template')(); + } + /** * This switches between the current view of a Doc and a specified alternate layout view. * The current view of the Doc is stored in the layout_default field so that it can be restored. diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 4ecaaa283..5b47dd91d 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -55,6 +55,7 @@ export interface FieldViewSharedProps { ignoreAutoHeight?: boolean; disableBrushing?: boolean; // should highlighting for this view be disabled when same document in another view is hovered over. hideClickBehaviors?: boolean; // whether to suppress menu item options for changing click behaviors + ignoreUsePath?: boolean; // ignore the usePath field for selecting the fieldKey (eg., on text docs) CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView; containerViewPath?: () => DocumentView[]; fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _freeform_fitContentsToBox property on a Document diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index f02ad7300..57ae92359 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -5,8 +5,7 @@ import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc'; -import { ScriptField } from '../../../../fields/ScriptField'; -import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; +import { BoolCast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { emptyFunction, returnTrue, setupMoveUpEvents, Utils } from '../../../../Utils'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; import { SelectionManager } from '../../../util/SelectionManager'; @@ -61,23 +60,12 @@ export class FontIconBox extends ViewBoxBaseComponent() { } @observable noTooltip = false; - showTemplate = (): void => { - const dragFactory = Cast(this.layoutDoc.dragFactory, Doc, null); - dragFactory && this._props.addDocTab(dragFactory, OpenWhere.addRight); - }; - dragAsTemplate = (): void => { - this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); - }; - useAsPrototype = (): void => { - this.layoutDoc.onDragStart = ScriptField.MakeFunction('makeDelegate(this.dragFactory, true)'); - }; + showTemplate = (dragFactory: Doc) => this._props.addDocTab(dragFactory, OpenWhere.addRight); specificContextMenu = (): void => { - if (!Doc.noviceMode && Cast(this.layoutDoc.dragFactory, Doc, null)) { - const cm = ContextMenu.Instance; - cm.addItem({ description: 'Show Template', event: this.showTemplate, icon: 'tag' }); - cm.addItem({ description: 'Use as Render Template', event: this.dragAsTemplate, icon: 'tag' }); - cm.addItem({ description: 'Use as Prototype', event: this.useAsPrototype, icon: 'tag' }); + const dragFactory = DocCast(this.layoutDoc.dragFactory); + if (!Doc.noviceMode && dragFactory) { + ContextMenu.Instance.addItem({ description: 'Show Template', event: () => this.showTemplate(dragFactory), icon: 'tag' }); } }; diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 2bcad806f..d85432631 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -115,7 +115,7 @@ export class KeyValueBox extends ObservableReactComponent { field === undefined && (field = res.result); } } - if (!key) return field; + if (!key) return false; if (Field.IsField(field, true) && (key !== 'proto' || field !== target)) { target[key] = field; return true; diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index d59489a78..f9e8ce4f3 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -125,7 +125,7 @@ export class KeyValuePair extends ObservableReactComponent { pinToPres: returnZero, }} GetValue={() => Field.toKeyValueString(this._props.doc, this._props.keyName)} - SetValue={(value: string) => (KeyValueBox.SetField(this._props.doc, this._props.keyName, value) ? true : false)} + SetValue={(value: string) => KeyValueBox.SetField(this._props.doc, this._props.keyName, value)} />
      diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index 62cb460c2..6b66d829c 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -1,6 +1,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; -import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction, trace } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; @@ -8,12 +8,12 @@ import { Doc, DocListCast, Field } from '../../../../fields/Doc'; import { List } from '../../../../fields/List'; import { listSpec } from '../../../../fields/Schema'; import { SchemaHeaderField } from '../../../../fields/SchemaHeaderField'; -import { Cast } from '../../../../fields/Types'; +import { Cast, DocCast } from '../../../../fields/Types'; import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents } from '../../../../Utils'; import { DocServer } from '../../../DocServer'; import { CollectionViewType } from '../../../documents/DocumentTypes'; import { Transform } from '../../../util/Transform'; -import { undoBatch } from '../../../util/UndoManager'; +import { undoable, undoBatch } from '../../../util/UndoManager'; import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu'; import { SchemaTableCell } from '../../collections/collectionSchema/SchemaTableCell'; import { FilterPanel } from '../../FilterPanel'; @@ -21,6 +21,7 @@ import { ObservableReactComponent } from '../../ObservableReactComponent'; import { OpenWhere } from '../DocumentView'; import './DashFieldView.scss'; import { FormattedTextBox } from './FormattedTextBox'; +import { DocData } from '../../../../fields/DocSymbols'; export class DashFieldView { dom: HTMLDivElement; // container for label and value @@ -62,6 +63,8 @@ export class DashFieldView { height={node.attrs.height} hideKey={node.attrs.hideKey} editable={node.attrs.editable} + expanded={node.attrs.expanded} + dataDoc={node.attrs.dataDoc} tbox={tbox} /> ); @@ -89,6 +92,8 @@ interface IDashFieldViewInternal { width: number; height: number; editable: boolean; + expanded: boolean; + dataDoc: boolean; node: any; getPos: any; unclickable: () => boolean; @@ -101,18 +106,19 @@ export class DashFieldViewInternal extends ObservableReactComponent(); @observable _dashDoc: Doc | undefined = undefined; - @observable _expanded = false; + @observable _expanded = this._props.expanded; constructor(props: IDashFieldViewInternal) { super(props); makeObservable(this); this._fieldKey = this._props.fieldKey; - this._textBoxDoc = this._fieldKey.startsWith('_') ? this._props.tbox.Document : this._props.tbox.dataDoc; + this._textBoxDoc = this._props.tbox.Document; + const setDoc = (doc: Doc) => (this._dashDoc = this._props.dataDoc ? doc[DocData] : doc); if (this._props.docId) { - DocServer.GetRefField(this._props.docId).then(action(dashDoc => dashDoc instanceof Doc && (this._dashDoc = dashDoc))); + DocServer.GetRefField(this._props.docId).then(dashDoc => dashDoc instanceof Doc && setDoc(dashDoc)); } else { - this._dashDoc = this._fieldKey.startsWith('_') ? this._props.tbox.Document : this._props.tbox.dataDoc; + setDoc(this._props.tbox.Document); } } @@ -126,7 +132,9 @@ export class DashFieldViewInternal extends ObservableReactComponent 100; + isRowActive = () => this._expanded && this._props.editable; + finishEdit = action(() => (this._expanded = false)); + selectedCell = (): [Doc, number] => [this._dashDoc!, 0]; // set the display of the field's value (checkbox for booleans, span of text for strings) @computed get fieldValueContent() { @@ -137,18 +145,18 @@ export class DashFieldViewInternal extends ObservableReactComponent this._props.tbox._props.PanelWidth() - 20 : returnZero} - selectedCell={() => [this._dashDoc!, 0]} + maxWidth={this._props.hideKey || this._hideKey ? undefined : this._props.tbox._props.PanelWidth} + columnWidth={returnZero} + selectedCell={this.selectedCell} fieldKey={this._fieldKey} rowHeight={returnZero} - isRowActive={() => this._expanded && this._props.editable} + isRowActive={this.isRowActive} padding={0} getFinfo={emptyFunction} setColumnValues={returnFalse} allowCRs={true} oneLine={!this._expanded} - finishEdit={action(() => (this._expanded = false))} + finishEdit={this.finishEdit} transform={Transform.Identity} menuTarget={null} /> @@ -173,11 +181,21 @@ export class DashFieldViewInternal extends ObservableReactComponent this._dashDoc && (this._dashDoc[this._fieldKey + '_hideKey'] = !this._dashDoc[this._fieldKey + '_hideKey'])), + 'hideKey' + ); + + @computed get _hideKey() { + return this._dashDoc && this._dashDoc[this._fieldKey + '_hideKey']; + } + // clicking on the label creates a pivot view collection of all documents // in the same collection. The pivot field is the fieldKey of this label onPointerDownLabelSpan = (e: any) => { setupMoveUpEvents(this, e, returnFalse, returnFalse, e => { DashFieldViewMenu.createFieldView = this.createPivotForField; + DashFieldViewMenu.toggleFieldHide = this.toggleFieldHide; DashFieldViewMenu.Instance.show(e.clientX, e.clientY + 16, this._fieldKey); }); }; @@ -188,6 +206,7 @@ export class DashFieldViewInternal extends ObservableReactComponent ({ value: facet, label: facet })); @@ -203,9 +222,9 @@ export class DashFieldViewInternal extends ObservableReactComponent - {this._props.hideKey ? null : ( + {this._props.hideKey || this._hideKey ? null : ( - {(this._textBoxDoc === this._dashDoc ? '' : this._dashDoc?.title + ':') + this._fieldKey} + {(Doc.AreProtosEqual(DocCast(this._textBoxDoc.rootDocument) ?? this._textBoxDoc, DocCast(this._dashDoc?.rootDocument) ?? this._dashDoc) ? '' : this._dashDoc?.title + ':') + this._fieldKey} )} {this._props.fieldKey.startsWith('#') ? null : this.fieldValueContent} @@ -224,6 +243,7 @@ export class DashFieldViewInternal extends ObservableReactComponent { static Instance: DashFieldViewMenu; static createFieldView: (e: React.MouseEvent) => void = emptyFunction; + static toggleFieldHide: () => void = emptyFunction; constructor(props: any) { super(props); DashFieldViewMenu.Instance = this; @@ -233,6 +253,10 @@ export class DashFieldViewMenu extends AntimodeMenu { DashFieldViewMenu.createFieldView(e); DashFieldViewMenu.Instance.fadeOut(true); }; + toggleFieldHide = (e: React.MouseEvent) => { + DashFieldViewMenu.toggleFieldHide(); + DashFieldViewMenu.Instance.fadeOut(true); + }; @observable _fieldKey = ''; @@ -252,6 +276,9 @@ export class DashFieldViewMenu extends AntimodeMenu { + ); } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index fb709818c..2b48494f2 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -451,7 +451,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent (tr = this.hyperlinkTerm(tr, term, newAutoLinks))); + Doc.MyPublishedDocs.filter(term => term.title).forEach(term => (tr = this.hyperlinkTerm(tr, term, newAutoLinks))); tr = tr.setSelection(isNodeSel && false ? new NodeSelection(tr.doc.resolve(f)) : new TextSelection(tr.doc.resolve(f), tr.doc.resolve(t))); this._editorView?.dispatch(tr); } @@ -958,8 +958,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent (this.layoutDoc._layout_autoHeight = !this.layoutDoc._layout_autoHeight), icon: this.Document._layout_autoHeight ? 'lock' : 'unlock', }); - optionItems.push({ description: `show markdown options`, event: RTFMarkup.Instance.open, icon: }); !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'eye' }); + const help = cm.findByDescription('Help...'); + const helpItems = help && 'subitems' in help ? help.subitems : []; + helpItems.push({ description: `show markdown options`, event: RTFMarkup.Instance.open, icon: }); + !help && cm.addItem({ description: 'Help...', subitems: helpItems, icon: 'eye' }); this._downX = this._downY = Number.NaN; }; @@ -1239,8 +1242,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent this._editorView?.dispatch(tx.insertText(incomingValue.str))); + } else { + selectAll(this._editorView.state, tx => this._editorView?.dispatch(tx.insertText(incomingValue?.str ?? ''))); } } } @@ -1339,15 +1342,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { if (pdfAnchor instanceof Doc) { const dashField = view.state.schema.nodes.paragraph.create({}, [ - view.state.schema.nodes.dashField.create({ fieldKey: 'text', docId: pdfAnchor[Id], hideKey: true, editable: false }, undefined, [ + view.state.schema.nodes.dashField.create({ fieldKey: 'text', docId: pdfAnchor[Id], hideKey: true, editable: false, expanded: true }, undefined, [ view.state.schema.marks.linkAnchor.create({ allAnchors: [{ href: `/doc/${this.Document[Id]}`, title: this.Document.title, anchorId: `${this.Document[Id]}` }], - title: `from: ${DocCast(pdfAnchor.embedContainer).title}`, + title: StrCast(pdfAnchor.title), noPreview: true, - docref: false, + docref: true, + fontSize: '8px', }), - view.state.schema.marks.pFontSize.create({ fontSize: '8px' }), - view.state.schema.marks.em.create({}), ]), ]); @@ -1926,11 +1928,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent ); } - cycleAlternateText = () => { - if (this.layoutDoc._layout_enableAltContentUI) { - const usePath = this.layoutDoc[`_${this._props.fieldKey}_usePath`]; - this.layoutDoc[`_${this._props.fieldKey}_usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' ? 'alternate:hover' : undefined; - } + cycleAlternateText = (skipHover?: boolean) => { + this.layoutDoc._layout_enableAltContentUI = true; + const usePath = this.layoutDoc[`_${this._props.fieldKey}_usePath`]; + this.layoutDoc[`_${this._props.fieldKey}_usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' && !skipHover ? 'alternate:hover' : undefined; }; @computed get overlayAlternateIcon() { const usePath = this.layoutDoc[`_${this._props.fieldKey}_usePath`]; @@ -1965,7 +1966,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { }); } + elideSelection = () => { + const state = this.view?.state; + if (!state) return; + if (state.selection.empty) return false; + const mark = state.schema.marks.summarize.create(); + const tr = state.tr; + tr.addMark(state.selection.from, state.selection.to, mark); + const content = tr.selection.content(); + const newNode = state.schema.nodes.summary.create({ visibility: false, text: content, textslice: content.toJSON() }); + this.view?.dispatch?.(tr.replaceSelectionWith(newNode).removeMark(tr.selection.from - 1, tr.selection.from, mark)); + return true; + }; + toggleNoAutoLinkAnchor = () => { if (this.view) { const mark = this.view.state.schema.mark(this.view.state.schema.marks.noAutoLinkAnchor); diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts index c798ae4b3..b97141e92 100644 --- a/src/client/views/nodes/formattedText/RichTextRules.ts +++ b/src/client/views/nodes/formattedText/RichTextRules.ts @@ -267,7 +267,7 @@ export class RichTextRules { // toggle alternate text UI %/ new InputRule(new RegExp(/%\//), (state, match, start, end) => { - setTimeout(this.TextBox.cycleAlternateText); + setTimeout(() => this.TextBox.cycleAlternateText(true)); return state.tr.deleteRange(start, end); }), @@ -283,40 +283,26 @@ export class RichTextRules { : tr; }), - new InputRule(new RegExp(/(^|[^=])(\(\(.*\)\))/), (state, match, start, end) => { - var count = 0; // ignore first return value which will be the notation that chat is pending a result - KeyValueBox.SetField(this.Document, '', match[2], false, (gptval: FieldResult) => { - count && this.TextBox.EditorView?.dispatch(this.TextBox.EditorView!.state.tr.insertText(' ' + (gptval as string))); - count++; - }); - return null; - }), - - // create a text display of a metadata field on this or another document, or create a hyperlink portal to another document - // [[ : ]] - // [[:docTitle]] => hyperlink - // [[fieldKey]] => show field - // [[fieldKey{:,=:}=value]] => show field and also set its value - // [[fieldKey:docTitle]] => show field of doc - new InputRule( - new RegExp(/\[\[([a-zA-Z_\? \-0-9]*)((=:|:)?=)([a-z,A-Z_@\?+\-*/\ 0-9\(\)]*)?(:[a-zA-Z_@:\.\? \-0-9]+)?\]\]$/), - (state, match, start, end) => { - const fieldKey = match[1]; - const assign = match[2] === '=' ? '' : match[2]; - const value = match[4]; - const docTitle = match[5]?.replace(':', ''); + // create a hyperlink to a titled document + // @() + new InputRule(new RegExp(/(^|\s)@\(([a-zA-Z_@:\.\? \-0-9]+)\)/), (state, match, start, end) => { + const docTitle = match[2]; + const prefixLength = '@('.length; + if (docTitle) { const linkToDoc = (target: Doc) => { - const rstate = this.TextBox.EditorView?.state; - const selection = rstate?.selection.$from.pos; - if (rstate) { - this.TextBox.EditorView?.dispatch(rstate.tr.setSelection(new TextSelection(rstate.doc.resolve(start), rstate.doc.resolve(end - 3)))); + const editor = this.TextBox.EditorView; + const selection = editor?.state?.selection.$from.pos; + if (editor) { + const estate = editor.state; + editor.dispatch(estate.tr.setSelection(new TextSelection(estate.doc.resolve(start), estate.doc.resolve(end - prefixLength)))); } DocUtils.MakeLink(this.TextBox.getAnchor(true), target, { link_relationship: 'portal to:portal from' }); - const fstate = this.TextBox.EditorView?.state; - if (fstate && selection) { - this.TextBox.EditorView?.dispatch(fstate.tr.setSelection(new TextSelection(fstate.doc.resolve(selection)))); + const teditor = this.TextBox.EditorView; + if (teditor && selection) { + const tstate = teditor.state; + teditor.dispatch(tstate.tr.setSelection(new TextSelection(tstate.doc.resolve(selection)))); } }; const getTitledDoc = (docTitle: string) => { @@ -326,32 +312,57 @@ export class RichTextRules { const titledDoc = DocServer.FindDocByTitle(docTitle); return titledDoc ? Doc.BestEmbedding(titledDoc) : titledDoc; }; - if (!fieldKey) { - if (docTitle) { - const target = getTitledDoc(docTitle); - if (target) { - setTimeout(() => linkToDoc(target)); - return state.tr.deleteRange(end - 1, end).deleteRange(start, start + 3); - } - } - return state.tr; + const target = getTitledDoc(docTitle); + if (target) { + setTimeout(() => linkToDoc(target)); + return state.tr.insertText(' ').deleteRange(start, start + prefixLength); } + } + return state.tr; + }), + + // create a text display of a metadata field on this or another document, or create a hyperlink portal to another document + // [@{this,doctitle,}.fieldKey{:,=,:=,=:=}value] + // [@{this,doctitle,}.fieldKey] + new InputRule( + new RegExp(/\[(@|@this\.|@[a-zA-Z_\? \-0-9]+\.)([a-zA-Z_\?\-0-9]+)((:|=|:=|=:=)([a-zA-Z,_@\?\+\-\*\/\ 0-9\(\)]*))?\]/), + (state, match, start, end) => { + const docTitle = match[1].substring(1).replace(/\.$/, ''); + const fieldKey = match[2]; + const assign = match[4] === ':' ? (match[4] = '') : match[4]; + const value = match[5]; + const dataDoc = value === undefined ? !fieldKey.startsWith('_') : !assign?.startsWith('='); + const getTitledDoc = (docTitle: string) => { + if (!DocServer.FindDocByTitle(docTitle)) { + Doc.AddToMyPublished(Docs.Create.TextDocument('', { title: docTitle, _width: 400, _layout_autoHeight: true })); + } + return DocServer.FindDocByTitle(docTitle); + }; // if the value has commas assume its an array (unless it's part of a chat gpt call indicated by '((' ) if (value?.includes(',') && !value.startsWith('((')) { const values = value.split(','); const strs = values.some(v => !v.match(/^[-]?[0-9.]$/)); this.Document[DocData][fieldKey] = strs ? new List(values) : new List(values.map(v => Number(v))); } else if (value) { - KeyValueBox.SetField(this.Document, fieldKey, assign + value, Doc.IsDataProto(this.Document) ? true : undefined, assign ? undefined: - (gptval: FieldResult) => this.Document[DocData][fieldKey] = gptval as string ); // prettier-ignore + KeyValueBox.SetField(this.Document, fieldKey, assign + value, Doc.IsDataProto(this.Document) ? true : undefined, assign.includes(":=") ? undefined: + (gptval: FieldResult) => (dataDoc ? this.Document[DocData]:this.Document)[fieldKey] = gptval as string ); // prettier-ignore } - const target = getTitledDoc(docTitle); - const fieldView = state.schema.nodes.dashField.create({ fieldKey, docId: target?.[Id], hideKey: false }); + const target = docTitle ? getTitledDoc(docTitle) : undefined; + const fieldView = state.schema.nodes.dashField.create({ fieldKey, docId: target?.[Id], hideKey: false, dataDoc }); return state.tr.setSelection(new TextSelection(state.doc.resolve(start), state.doc.resolve(end))).replaceSelectionWith(fieldView, true); }, { inCode: true } ), + new InputRule(new RegExp(/(^|[^=])(\(\(.*\)\))/), (state, match, start, end) => { + var count = 0; // ignore first return value which will be the notation that chat is pending a result + KeyValueBox.SetField(this.Document, '', match[2], false, (gptval: FieldResult) => { + count && this.TextBox.EditorView?.dispatch(this.TextBox.EditorView!.state.tr.insertText(' ' + (gptval as string))); + count++; + }); + return null; + }), + // create a text display of a metadata field on this or another document, or create a hyperlink portal to another document // wiki:title new InputRule(new RegExp(/wiki:([a-zA-Z_@:\.\?\-0-9]+ )$/), (state, match, start, end) => { diff --git a/src/client/views/nodes/formattedText/marks_rts.ts b/src/client/views/nodes/formattedText/marks_rts.ts index a141ef041..b68acc8f8 100644 --- a/src/client/views/nodes/formattedText/marks_rts.ts +++ b/src/client/views/nodes/formattedText/marks_rts.ts @@ -74,6 +74,7 @@ export const marks: { [index: string]: MarkSpec } = { allAnchors: { default: [] as { href: string; title: string; anchorId: string }[] }, title: { default: null }, noPreview: { default: false }, + fontSize: { default: null }, docref: { default: false }, // flags whether the linked text comes from a document within Dash. If so, an attribution label is appended after the text }, inclusive: false, @@ -93,14 +94,16 @@ export const marks: { [index: string]: MarkSpec } = { const anchorids = node.attrs.allAnchors.reduce((p: string, item: { href: string; title: string; anchorId: string }) => (p ? p + ' ' + item.anchorId : item.anchorId), ''); return node.attrs.docref && node.attrs.title ? [ - 'div', + 'a', ['span', 0], [ 'span', { ...node.attrs, class: 'prosemirror-attribution', + 'data-targethrefs': targethrefs, href: node.attrs.allAnchors[0].href, + style: `font-size: ${node.attrs.fontSize}`, }, node.attrs.title, ], diff --git a/src/client/views/nodes/formattedText/nodes_rts.ts b/src/client/views/nodes/formattedText/nodes_rts.ts index c9115be90..905146ee2 100644 --- a/src/client/views/nodes/formattedText/nodes_rts.ts +++ b/src/client/views/nodes/formattedText/nodes_rts.ts @@ -265,6 +265,8 @@ export const nodes: { [index: string]: NodeSpec } = { docId: { default: '' }, hideKey: { default: false }, editable: { default: true }, + expanded: { default: null }, + dataDoc: { default: false }, }, leafText: node => Field.toString((DocServer.GetCachedRefField(node.attrs.docId as string) as Doc)?.[node.attrs.fieldKey as string] as Field), group: 'inline', diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index daae32e9f..4b40d11b9 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -445,6 +445,12 @@ export namespace Doc { export function GetT(doc: Doc, key: string, ctor: ToConstructor, ignoreProto: boolean = false): FieldResult { return Cast(Get(doc, key, ignoreProto), ctor) as FieldResult; } + export function isTemplateDoc(doc: Doc) { + return GetT(doc, 'isTemplateDoc', 'boolean', true); + } + export function isTemplateForField(doc: Doc) { + return GetT(doc, 'isTemplateForField', 'string', true); + } export function IsDataProto(doc: Doc) { return GetT(doc, 'isDataDoc', 'boolean', true); } @@ -642,7 +648,7 @@ export namespace Doc { cloneLinks: boolean, cloneTemplates: boolean ): Promise { - if (Doc.IsBaseProto(doc) || ((Doc.Get(doc, 'isTemplateDoc', true) || Doc.Get(doc, 'isTemplateForField', true)) && !cloneTemplates)) { + if (Doc.IsBaseProto(doc) || ((Doc.isTemplateDoc(doc) || Doc.isTemplateForField(doc)) && !cloneTemplates)) { return doc; } if (cloneMap.get(doc[Id])) return cloneMap.get(doc[Id])!; @@ -735,7 +741,7 @@ export namespace Doc { const docAtKey = DocCast(clone[key]); if (docAtKey && !Doc.IsSystem(docAtKey)) { if (!Array.from(cloneMap.values()).includes(docAtKey)) { - clone[key] = !cloneTemplates && (Doc.Get(docAtKey, 'isTemplateDoc', true) || Doc.Get(docAtKey, 'isTemplateForField', true)) ? docAtKey : cloneMap.get(docAtKey[Id]); + clone[key] = !cloneTemplates && (Doc.isTemplateDoc(docAtKey) || Doc.isTemplateForField(docAtKey)) ? docAtKey : cloneMap.get(docAtKey[Id]); } else { repairClone(docAtKey, cloneMap, cloneTemplates, visited); } @@ -857,7 +863,7 @@ export namespace Doc { // of the original layout while allowing for individual layout properties to be overridden in the expanded layout. export function expandTemplateLayout(templateLayoutDoc: Doc, targetDoc?: Doc) { // nothing to do if the layout isn't a template or we don't have a target that's different than the template - if (!targetDoc || templateLayoutDoc === targetDoc || (!templateLayoutDoc.isTemplateForField && !templateLayoutDoc.isTemplateDoc)) { + if (!targetDoc || templateLayoutDoc === targetDoc || (!Doc.isTemplateForField(templateLayoutDoc) && !Doc.isTemplateDoc(templateLayoutDoc))) { return templateLayoutDoc; } @@ -874,7 +880,7 @@ export namespace Doc { expandedTemplateLayout = undefined; _pendingMap.add(targetDoc[Id] + expandedLayoutFieldKey); } else if (expandedTemplateLayout === undefined && !_pendingMap.has(targetDoc[Id] + expandedLayoutFieldKey)) { - if (templateLayoutDoc.resolvedDataDoc === (targetDoc.rootDocument ?? Doc.GetProto(targetDoc))) { + if (templateLayoutDoc.resolvedDataDoc === targetDoc[DocData]) { expandedTemplateLayout = templateLayoutDoc; // reuse an existing template layout if its for the same document with the same params } else { templateLayoutDoc.resolvedDataDoc && (templateLayoutDoc = DocCast(templateLayoutDoc.proto, templateLayoutDoc)); // if the template has already been applied (ie, a nested template), then use the template's prototype @@ -910,8 +916,9 @@ export namespace Doc { console.log('Warning: GetLayoutDataDocPair childDoc not defined'); return { layout: childDoc, data: childDoc }; } - const resolvedDataDoc = Doc.AreProtosEqual(containerDataDoc, containerDoc) || (!childDoc.isTemplateDoc && !childDoc.isTemplateForField) ? undefined : containerDataDoc; - return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc), data: resolvedDataDoc }; + const resolvedDataDoc = Doc.AreProtosEqual(containerDataDoc, containerDoc) || (!Doc.isTemplateDoc(childDoc) && !Doc.isTemplateForField(childDoc)) ? undefined : containerDataDoc; + const templateRoot = DocCast(containerDoc?.rootDocument); + return { layout: Doc.expandTemplateLayout(childDoc, templateRoot), data: resolvedDataDoc }; } export function FindReferences(infield: Doc | List, references: Set, system: boolean | undefined) { @@ -1035,20 +1042,13 @@ export namespace Doc { // (ie, the 'data' doc), and then creates another delegate of that (ie, the 'layout' doc). // This is appropriate if you're trying to create a document that behaves like all // regularly created documents (e.g, text docs, pdfs, etc which all have data/layout docs) - export function MakeDelegateWithProto(doc: Doc, id?: string, title?: string): Doc { - const delegateProto = new Doc(); - delegateProto[Initializing] = true; - delegateProto.proto = doc; - delegateProto.author = Doc.CurrentUserEmail; - delegateProto.isDataDoc = true; - title && (delegateProto.title = title); - const delegate = new Doc(id, true); - delegate[Initializing] = true; - delegate.proto = delegateProto; - delegate.author = Doc.CurrentUserEmail; - delegate[Initializing] = false; - delegateProto[Initializing] = false; - return delegate; + export function MakeDelegateWithProto(doc: Doc, id?: string, title?: string) { + const ndoc = Doc.ApplyTemplate(doc); + if (ndoc) { + Doc.GetProto(ndoc).isDataDoc = true; + ndoc && (Doc.GetProto(ndoc).proto = doc); + } + return ndoc; } let _applyCount: number = 0; @@ -1671,7 +1671,7 @@ ScriptingGlobals.add(function getEmbedding(doc: any) { return Doc.MakeEmbedding(doc); }); ScriptingGlobals.add(function getCopy(doc: any, copyProto: any) { - return doc.isTemplateDoc ? Doc.ApplyTemplate(doc) : Doc.MakeCopy(doc, copyProto); + return doc.isTemplateDoc ? Doc.MakeDelegateWithProto(doc) : Doc.MakeCopy(doc, copyProto); }); ScriptingGlobals.add(function copyField(field: any) { return Field.Copy(field); diff --git a/src/fields/util.ts b/src/fields/util.ts index b73520999..c2ec3f13a 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -286,6 +286,10 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc // target should be either a Doc or ListImpl. receiver should be a Proxy Or List. // export function setter(target: any, in_prop: string | symbol | number, value: any, receiver: any): boolean { + if (!in_prop) { + console.log('WARNING: trying to set an empty property. This should be fixed. '); + return false; + } let prop = in_prop; const effectiveAcl = in_prop === 'constructor' || typeof in_prop === 'symbol' ? AclAdmin : GetPropAcl(target, prop); if (effectiveAcl !== AclEdit && effectiveAcl !== AclAugment && effectiveAcl !== AclAdmin) return true; -- cgit v1.2.3-70-g09d2 From 2b9c89e54c19a53f0e1978850e8d05ac31186e21 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 21 Mar 2024 17:34:23 -0400 Subject: changed gpt calls from text box to package result into an elision node. --- .../views/nodes/formattedText/RichTextMenu.tsx | 22 +++++++++++++--------- .../views/nodes/formattedText/RichTextRules.ts | 9 +++++++-- 2 files changed, 20 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index bee0d72e3..b5d0f28d8 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -318,16 +318,20 @@ export class RichTextMenu extends AntimodeMenu { }); } - elideSelection = () => { - const state = this.view?.state; - if (!state) return; - if (state.selection.empty) return false; + elideSelection = (txstate: EditorState | undefined = undefined, visibility = false) => { + const state = txstate ?? this.view?.state; + if (!state || state.selection.empty) return false; const mark = state.schema.marks.summarize.create(); - const tr = state.tr; - tr.addMark(state.selection.from, state.selection.to, mark); - const content = tr.selection.content(); - const newNode = state.schema.nodes.summary.create({ visibility: false, text: content, textslice: content.toJSON() }); - this.view?.dispatch?.(tr.replaceSelectionWith(newNode).removeMark(tr.selection.from - 1, tr.selection.from, mark)); + const tr = state.tr.addMark(state.tr.selection.from, state.selection.to, mark); + const text = tr.selection.content(); + const elideNode = state.schema.nodes.summary.create({ visibility, text, textslice: text.toJSON() }); + const summary = tr.replaceSelectionWith(elideNode).removeMark(tr.selection.from - 1, tr.selection.from, mark); + const expanded = () => { + const endOfElidableText = summary.selection.to + text.content.size; + const res = summary.insert(summary.selection.to, text.content).insert(endOfElidableText, state.schema.nodes.paragraph.create({})); + return res.setSelection(new TextSelection(res.doc.resolve(endOfElidableText + 1))); + }; + this.view?.dispatch?.(visibility ? expanded() : summary); return true; }; diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts index b97141e92..adc031636 100644 --- a/src/client/views/nodes/formattedText/RichTextRules.ts +++ b/src/client/views/nodes/formattedText/RichTextRules.ts @@ -354,10 +354,15 @@ export class RichTextRules { { inCode: true } ), - new InputRule(new RegExp(/(^|[^=])(\(\(.*\)\))/), (state, match, start, end) => { + // pass the contents between '((' and '))' to chatGPT and append the result + new InputRule(new RegExp(/(^|[^=])(\(\(.*\)\))$/), (state, match, start, end) => { var count = 0; // ignore first return value which will be the notation that chat is pending a result KeyValueBox.SetField(this.Document, '', match[2], false, (gptval: FieldResult) => { - count && this.TextBox.EditorView?.dispatch(this.TextBox.EditorView!.state.tr.insertText(' ' + (gptval as string))); + if (count) { + const tr = this.TextBox.EditorView?.state.tr.insertText(' ' + (gptval as string)); + tr && this.TextBox.EditorView?.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(end + 2), tr.doc.resolve(end + 2 + (gptval as string).length)))); + RichTextMenu.Instance.elideSelection(this.TextBox.EditorView?.state, true); + } count++; }); return null; -- cgit v1.2.3-70-g09d2 From 462580bf70ff563dbfe33a84b8cd015e637cdf7e Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 22 Mar 2024 11:41:22 -0400 Subject: make ink stroke labels visible always for closed gesture strokes. --- src/client/documents/Documents.ts | 1 + src/client/views/InkingStroke.tsx | 2 +- .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 1d7c73306..37db23bdc 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -317,6 +317,7 @@ export class DocumentOptions { _label_minFontSize?: NUMt = new NumInfo('minimum font size for labelBoxes', false); _label_maxFontSize?: NUMt = new NumInfo('maximum font size for labelBoxes', false); stroke_width?: NUMt = new NumInfo('width of an ink stroke', false); + stroke_showLabel?: BOOLt = new BoolInfo('show label inside of stroke'); mediaState?: STRt = new StrInfo(`status of audio/video media document: ${media_state.PendingRecording}, ${media_state.Recording}, ${media_state.Paused}, ${media_state.Playing}`, false); recording?: BOOLt = new BoolInfo('whether WebCam is recording or not'); slides?: DOCt = new DocInfo('presentation slide associated with video recording (bcz: should be renamed!!)'); diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 122e5c4c3..ce70b5052 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -446,7 +446,7 @@ export class InkingStroke extends ViewBoxBaseComponent() impleme {clickableLine(this.onPointerDown, isInkMask)} {isInkMask ? null : inkLine} - {!closed || (!RTFCast(this.dataDoc.text)?.Text && (!this._props.isSelected() || Doc.UserDoc().activeInkHideTextLabels)) ? null : ( + {!closed || (!RTFCast(this.dataDoc.text)?.Text && !this.dataDoc[this.fieldKey + '_showLabel'] && (!this._props.isSelected() || Doc.UserDoc().activeInkHideTextLabels)) ? null : (
      Date: Sat, 23 Mar 2024 14:55:20 -0400 Subject: added empty image tool and fixed createCustomView api --- src/client/documents/Documents.ts | 6 ++---- src/client/util/CurrentUserUtils.ts | 2 ++ 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 37db23bdc..d68021062 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1780,10 +1780,7 @@ export namespace DocUtils { } // applies a custom template to a document. the template is identified by it's short name (e.g, slideView not layout_slideView) export function makeCustomViewClicked(doc: Doc, creator: Opt<(documents: Array, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = 'custom', docLayoutTemplate?: Doc) { const batch = UndoManager.StartBatch('makeCustomViewClicked'); - runInAction(() => { - doc.layout_fieldKey = 'layout_' + templateSignature; - createCustomView(doc, creator, templateSignature, docLayoutTemplate); - }); + createCustomView(doc, creator, templateSignature, docLayoutTemplate); batch.end(); return doc; } @@ -1807,6 +1804,7 @@ export namespace DocUtils { } export function createCustomView(doc: Doc, creator: Opt<(documents: Array, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = 'custom', docLayoutTemplate?: Doc) { const templateName = templateSignature.replace(/\(.*\)/, ''); + doc.layout_fieldKey = 'layout_' + (templateSignature || docLayoutTemplate?.title); docLayoutTemplate = docLayoutTemplate || findTemplate(templateName, StrCast(doc.isGroup && doc.transcription ? 'transcription' : doc.type), templateSignature); const customName = 'layout_' + templateSignature; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index bbee18707..11f6c82ec 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -349,6 +349,7 @@ pie title Minerals in my tap water creator:(opts:DocumentOptions)=> any // how to create the empty thing if it doesn't exist }[] = [ {key: "Note", creator: opts => Docs.Create.TextDocument("", opts), opts: { _width: 200, _layout_autoHeight: true }}, + {key: "Image", creator: opts => Docs.Create.ImageDocument("", opts), opts: { _width: 400, _height:400 }}, {key: "Flashcard", creator: opts => Docs.Create.TextDocument("", opts), opts: { _width: 200, _layout_autoHeight: true, _layout_enableAltContentUI: true}}, {key: "Equation", creator: opts => Docs.Create.EquationDocument("",opts), opts: { _width: 300, _height: 35, }}, {key: "Noteboard", creator: opts => Docs.Create.NoteTakingDocument([], opts), opts: { _width: 250, _height: 200, _layout_fitWidth: true}}, @@ -386,6 +387,7 @@ pie title Minerals in my tap water { toolTip: "Tap or drag to create a plotly node", title: "Plotly", icon: "rocket", dragFactory: doc.emptyPlotly as Doc, clickFactory: DocCast(doc.emptyMermaids)}, { toolTip: "Tap or drag to create a physics simulation",title: "Simulation", icon: "rocket",dragFactory: doc.emptySimulation as Doc, clickFactory: DocCast(doc.emptySimulation), funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a note board", title: "Notes", icon: "book", dragFactory: doc.emptyNoteboard as Doc, clickFactory: DocCast(doc.emptyNoteboard)}, + { toolTip: "Tap or drag to create an iamge", title: "Image", icon: "image", dragFactory: doc.emptyImage as Doc, clickFactory: DocCast(doc.emptyImage)}, { toolTip: "Tap or drag to create a collection", title: "Col", icon: "folder", dragFactory: doc.emptyCollection as Doc, clickFactory: DocCast(doc.emptyTab)}, { toolTip: "Tap or drag to create a webpage", title: "Web", icon: "globe-asia", dragFactory: doc.emptyWebpage as Doc, clickFactory: DocCast(doc.emptyWebpage)}, { toolTip: "Tap or drag to create a comparison box", title: "Compare", icon: "columns", dragFactory: doc.emptyComparison as Doc, clickFactory: DocCast(doc.emptyComparison)}, -- cgit v1.2.3-70-g09d2 From 1606b9cfd1bf48890d2cc0b39595982cafeb990e Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 23 Mar 2024 15:03:29 -0400 Subject: from last --- src/client/documents/Documents.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index d68021062..17cb6fef8 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1777,10 +1777,23 @@ export namespace DocUtils { subitems: userDocList, icon: 'file', }); - } // applies a custom template to a document. the template is identified by it's short name (e.g, slideView not layout_slideView) - export function makeCustomViewClicked(doc: Doc, creator: Opt<(documents: Array, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = 'custom', docLayoutTemplate?: Doc) { + } + + // applies a custom template to a document. the template is identified by it's short name (e.g, slideView not layout_slideView) + + /** + * Applies a template to a Doc and logs the action with the UndoManager + * If the template already exists and has been registered, it can be specified by it's signature name (e.g., 'icon' not 'layout_icon'). + * Alternatively, the signature can be omitted and the template can be provided. + * @param doc the Doc to apply the template to. + * @param creator a function that will create the template if it doesn't exist + * @param templateSignature the signature name for a template that has already been created and registered on the userDoc. (can be "" if template is provide) + * @param template the template to use (optional if templateSignature is provided) + * @returns doc + */ + export function makeCustomViewClicked(doc: Doc, creator: Opt<(documents: Array, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = 'custom', template?: Doc) { const batch = UndoManager.StartBatch('makeCustomViewClicked'); - createCustomView(doc, creator, templateSignature, docLayoutTemplate); + createCustomView(doc, creator, templateSignature || StrCast(template?.title), template); batch.end(); return doc; } -- cgit v1.2.3-70-g09d2 From 4ea0ea97359cf2f3e97367dafbfaf9157ecc987b Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 23 Mar 2024 15:30:49 -0400 Subject: made backspace deleting a schema row undoable. fixed calling chat on string fields --- src/client/views/collections/collectionSchema/CollectionSchemaView.tsx | 2 +- src/client/views/nodes/KeyValueBox.tsx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 4a0ca8fe5..5f4948808 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -238,7 +238,7 @@ export class CollectionSchemaView extends CollectionSubView() { } break; case 'Backspace': { - this.removeDocument(this._selectedDocs); + undoable(() => this.removeDocument(this._selectedDocs), 'delete schema row'); break; } case 'Escape': { diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index d85432631..5394c7dbb 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -105,7 +105,8 @@ export class KeyValueBox extends ObservableReactComponent { default: { const _setCacheResult_ = (value: FieldResult) => { field = value as Field; - setResult?.(value); + if (setResult) setResult?.(value); + else target[key] = field; }; const res = script.run({ this: Doc.Layout(doc), self: doc, _setCacheResult_ }, console.log); if (!res.success) { -- cgit v1.2.3-70-g09d2 From b949608ff69fb66c30bbed439b1c37f8fffd2333 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 23 Mar 2024 21:13:38 -0400 Subject: fixed linking to parts of a template. fixed highlting part of a template when following a link to it. --- .../collectionFreeForm/CollectionFreeFormView.tsx | 12 +++++++++--- src/fields/Doc.ts | 3 ++- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 01d379b96..1fd453e96 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -314,7 +314,7 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout).includes(anchor)) return; const xfToCollection = options?.docTransform ?? Transform.Identity(); const savedState = { panX: NumCast(this.Document[this.panXFieldKey]), panY: NumCast(this.Document[this.panYFieldKey]), scale: options?.willZoomCentered ? this.Document[this.scaleFieldKey] : undefined }; const cantTransform = this.fitContentsToBox || ((this.Document.isGroup || this.layoutDoc._lockedTransform) && !LightboxView.LightboxDoc); @@ -335,6 +335,7 @@ export class CollectionFreeFormView extends CollectionSubView> => new Promise>(res => { if (doc.hidden && this._lightboxDoc !== doc) options.didMove = !(doc.hidden = false); + if (doc === this.Document) return res(this.DocumentView?.()); const findDoc = (finish: (dv: DocumentView) => void) => DocumentManager.Instance.AddViewRenderedCb(doc, dv => finish(dv)); findDoc(dv => res(dv)); }); @@ -1262,7 +1263,7 @@ export class CollectionFreeFormView extends CollectionSubView pair.layout)?.includes(doc)) { if (doc.hidden) doc.hidden = false; return true; } @@ -1405,7 +1406,12 @@ export class CollectionFreeFormView extends CollectionSubView { // create an anchor that saves information about the current state of the freeform view (pan, zoom, view type) - const anchor = Docs.Create.ConfigDocument({ title: 'ViewSpec - ' + StrCast(this.layoutDoc._type_collection), layout_unrendered: true, presentation_transition: 500, annotationOn: this.Document }); + const anchor = Docs.Create.ConfigDocument({ + title: 'ViewSpec - ' + StrCast(this.layoutDoc._type_collection), + layout_unrendered: true, + presentation_transition: 500, + annotationOn: this.Document, + }); PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), pannable: !this.Document.isGroup, type_collection: true, filters: true } }, this.Document); if (addAsAnnotation) { diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 4b40d11b9..246828709 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1279,7 +1279,8 @@ export namespace Doc { highlightedDocs.add(doc); doc[Highlight] = true; doc[Animation] = presentation_effect; - if (dataAndDisplayDocs) { + if (dataAndDisplayDocs && !doc.resolvedDataDoc) { + // if doc is a layout template then we don't want to highlight the proto since that will be the entire template, not just the specific layout field highlightedDocs.add(doc[DocData]); doc[DocData][Highlight] = true; } -- cgit v1.2.3-70-g09d2 From 2e0cb3e0a470994eecbb7f6b2ec87296baf517b9 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 24 Mar 2024 19:04:42 -0400 Subject: fixed linkdocpreviews to sequence through multiple links. fixed text boxes to update text when dashfieldView text changes (but the fieldview doesn't), fixed dashFieldViews to be editable cleanly, and to allow sub-dashFieldViews to be editbale. allowed toggle on/off of dashFieldView fieldKey. got rid of sidebars in scemaCells. fied editing dashFieldViews in captions and as childrend of dashFieldViews by passing rootSelected --- .../collectionSchema/SchemaTableCell.tsx | 9 ++++- src/client/views/nodes/DocumentView.tsx | 1 + src/client/views/nodes/LinkDocPreview.tsx | 1 + .../views/nodes/formattedText/DashFieldView.scss | 32 ++++++++++----- .../views/nodes/formattedText/DashFieldView.tsx | 45 ++++++++++++++-------- .../views/nodes/formattedText/FormattedTextBox.tsx | 26 +++++++++---- 6 files changed, 80 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 711ef507c..ce73ff8a4 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -51,6 +51,8 @@ export interface SchemaTableCellProps { options?: string[]; menuTarget: HTMLDivElement | null; transform: () => Transform; + autoFocus?: boolean; // whether to set focus on creation, othwerise wait for a click + rootSelected?: () => boolean; } @observer @@ -89,6 +91,7 @@ export class SchemaTableCell extends ObservableReactComponent this._props.autoFocus && r?.setIsFocused(true)} oneLine={this._props.oneLine} allowCRs={this._props.allowCRs} contents={undefined} @@ -314,13 +319,15 @@ export class SchemaRTFCell extends ObservableReactComponent this.selected; render() { const { color, textDecoration, fieldProps, cursor, pointerEvents } = SchemaTableCell.renderProps(this._props); fieldProps.isContentActive = this.selectedFunc; return (
      - {this.selected ? : (field => (field ? Field.toString(field) : ''))(FieldValue(fieldProps.Document[fieldProps.fieldKey]))} + {this.selected ? this._props.finishEdit?.()} /> : (field => (field ? Field.toString(field) : ''))(FieldValue(fieldProps.Document[fieldProps.fieldKey]))}
      ); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index e9ce98583..1044d6609 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -892,6 +892,7 @@ export class DocumentViewInternal extends DocComponent this._expanded && this._props.editable; - finishEdit = action(() => (this._expanded = false)); + + finishEdit = action(() => { + if (this._expanded) { + this._expanded = false; + // if the edit finishes, then we want to lose focus on the textBox unless something else in the textBox got focus + // the timeout allows switching focus from one dashFieldView to another in the same text box + setTimeout(() => !this._props.tbox.ProseRef?.contains(document.activeElement) && this._props.tbox._props.onBlur?.()); + } + }); selectedCell = (): [Doc, number] => [this._dashDoc!, 0]; + columnWidth = () => Math.min(this._props.tbox._props.PanelWidth(), Math.max(50, this._props.tbox._props.PanelWidth() - 100)); // try to leave room for the fieldKey // set the display of the field's value (checkbox for booleans, span of text for strings) @computed get fieldValueContent() { return !this._dashDoc ? null : ( -
      (this._expanded = !this._props.editable ? !this._expanded : true))} style={{ fontSize: 'smaller', width: this._props.hideKey ? this._props.tbox._props.PanelWidth() - 20 : undefined }}> +
      (this._expanded = !this._props.editable ? !this._expanded : true))} style={{ fontSize: 'smaller', width: !this._hideKey && this._expanded ? this.columnWidth() : undefined }}>
      ); @@ -187,12 +198,12 @@ export class DashFieldViewInternal extends ObservableReactComponent { + onPointerDownLabelSpan = (e: React.PointerEvent) => { setupMoveUpEvents(this, e, returnFalse, returnFalse, e => { DashFieldViewMenu.createFieldView = this.createPivotForField; DashFieldViewMenu.toggleFieldHide = this.toggleFieldHide; @@ -215,7 +226,7 @@ export class DashFieldViewInternal extends ObservableReactComponent + { + this._editingTitle = false; + !hideTitle && this.titleBlur(); + })} + onChange={action(e => !hideTitle && (this._accumulatedTitle = e.target.value))} + onKeyDown={hideTitle ? emptyFunction : this.titleEntered} + onPointerDown={e => e.stopPropagation()} + /> + ) : (
      {hideTitle ? null : ( diff --git a/src/client/views/FieldsDropdown.tsx b/src/client/views/FieldsDropdown.tsx index 5638d34c6..6a5c2cb4c 100644 --- a/src/client/views/FieldsDropdown.tsx +++ b/src/client/views/FieldsDropdown.tsx @@ -61,7 +61,6 @@ export class FieldsDropdown extends ObservableReactComponent filteredOptions.push(pair[0])); const options = filteredOptions.sort().map(facet => ({ value: facet, label: facet })); - console.log(options); return ( } + {Doc.noviceMode ? null : } {templateMenu} { + onKeyDown = (e: KeyboardEvent) => { //make textbox and add it to this collection // tslint:disable-next-line:prefer-const const cm = ContextMenu.Instance; @@ -311,7 +311,7 @@ export class MarqueeView extends ObservableReactComponent { ? DocCast(linkDoc.link_anchor_2) : DocCast(linkDoc.link_anchor_1) : LinkManager.getOppositeAnchor(linkDoc, sourceDoc) || - LinkManager.getOppositeAnchor(linkDoc, Cast(linkDoc.link_anchor_2, Doc, null).annotationOn === sourceDoc ? Cast(linkDoc.link_anchor_2, Doc, null) : Cast(linkDoc.link_anchor_1, Doc, null)); + LinkManager.getOppositeAnchor(linkDoc, Cast(linkDoc.link_anchor_2, Doc, null)?.annotationOn === sourceDoc ? Cast(linkDoc.link_anchor_2, Doc, null) : Cast(linkDoc.link_anchor_1, Doc, null)); return !destDoc || !sourceDoc ? null : ( () { _height: 300, backgroundColor: 'white', }); - this._props.addDocument?.(graph); + const link = DocUtils.MakeLink(this.Document, graph, { link_relationship: 'function', link_description: 'input' }); + //this._props.addDocument?.(graph); + link && this._props.addDocument?.(link); e.stopPropagation(); } if (e.key === 'Backspace' && !this.dataDoc.text) this._props.removeDocument?.(this.Document); diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx index 2e7a2120e..67445e552 100644 --- a/src/client/views/nodes/FunctionPlotBox.tsx +++ b/src/client/views/nodes/FunctionPlotBox.tsx @@ -7,12 +7,13 @@ import { List } from '../../../fields/List'; import { listSpec } from '../../../fields/Schema'; import { Cast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { Docs } from '../../documents/Documents'; +import { DocUtils, Docs } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; import { undoBatch } from '../../util/UndoManager'; import { ViewBoxAnnotatableComponent } from '../DocComponent'; import { FieldView, FieldViewProps } from './FieldView'; import { PinProps, PresBox } from './trails'; +import { LinkManager } from '../../util/LinkManager'; @observer export class FunctionPlotBox extends ViewBoxAnnotatableComponent() { @@ -33,7 +34,7 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent componentDidMount() { this._props.setContentViewBox?.(this); reaction( - () => [DocListCast(this.dataDoc[this.fieldKey]).map(doc => doc?.text), this.layoutDoc.width, this.layoutDoc.height, this.layoutDoc.xRange, this.layoutDoc.yRange], + () => [this.graphFuncs, this.layoutDoc.width, this.layoutDoc.height, this.layoutDoc.xRange, this.layoutDoc.yRange], () => this.createGraph() ); } @@ -45,11 +46,17 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent if (addAsAnnotation) this.addDocument(anchor); return anchor; }; + @computed get graphFuncs() { + const links = LinkManager.Instance.getAllRelatedLinks(this.Document) + .map(d => LinkManager.getOppositeAnchor(d, this.Document)) + .filter(d => d) + .map(d => d!); + return links.concat(DocListCast(this.dataDoc[this.fieldKey])).map(doc => StrCast(doc.text, 'x^2').replace(/\\frac\{(.*)\}\{(.*)\}/, '($1/$2)')); + } createGraph = (ele?: HTMLDivElement) => { this._plotEle = ele || this._plotEle; const width = this._props.PanelWidth(); const height = this._props.PanelHeight(); - const fns = DocListCast(this.dataDoc.data).map(doc => StrCast(doc.text, 'x^2').replace(/\\frac\{(.*)\}\{(.*)\}/, '($1/$2)')); try { this._plotEle.children.length && this._plotEle.removeChild(this._plotEle.children[0]); this._plot = functionPlot({ @@ -59,7 +66,7 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent xAxis: { domain: Cast(this.layoutDoc.xRange, listSpec('number'), [-10, 10]) }, yAxis: { domain: Cast(this.layoutDoc.yRange, listSpec('number'), [-1, 9]) }, grid: true, - data: fns.map(fn => ({ + data: this.graphFuncs.map(fn => ({ fn, // derivative: { fn: "2 * x", updateOnMouseMove: true } })), @@ -72,7 +79,14 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent @undoBatch drop = (e: Event, de: DragManager.DropEvent) => { if (de.complete.docDragData?.droppedDocuments.length) { - const added = de.complete.docDragData.droppedDocuments.reduce((res, doc) => res && Doc.AddDocToList(this.dataDoc, this._props.fieldKey, doc), true); + const added = de.complete.docDragData.droppedDocuments.reduce((res, doc) => { + ///const ret = res && Doc.AddDocToList(this.dataDoc, this._props.fieldKey, doc); + if (res) { + const link = DocUtils.MakeLink(doc, this.Document, { link_relationship: 'function', link_description: 'input' }); + link && this._props.addDocument?.(link); + } + return res; + }, true); !added && e.preventDefault(); e.stopPropagation(); // prevent parent Doc from registering new position so that it snaps back into place return added; @@ -104,7 +118,7 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent {this.theGraph}
      () { public static LayoutString(fieldKey: string = 'link') { return FieldView.LayoutString(LinkBox, fieldKey); } - _disposer: IReactionDisposer | undefined; + _disposers: { [name: string]: IReactionDisposer } = {}; @observable _forceAnimate: number = 0; // forces xArrow to animate when a transition animation is detected on something that affects an anchor @observable _hide = false; // don't render if anchor is not visible since that breaks xAnchor @@ -40,11 +40,15 @@ export class LinkBox extends ViewBoxBaseComponent() { return DocumentManager.Instance.getDocumentView(anchor, this.DocumentView?.().containerViewPath?.().lastElement()); }; componentWillUnmount() { - this._disposer?.(); + Object.keys(this._disposers).forEach(key => this._disposers[key]()); } componentDidMount() { this._props.setContentViewBox?.(this); - this._disposer = reaction( + this._disposers.deleting = reaction( + () => !this.anchor1 || !this.anchor2, + empty => empty && this._props.removeDocument?.(this.Document) + ); + this._disposers.dragging = reaction( () => ({ drag: SnappingManager.IsDragging }), ({ drag }) => { !LightboxView.Contains(this.DocumentView?.()) && diff --git a/src/client/views/nodes/LinkDescriptionPopup.tsx b/src/client/views/nodes/LinkDescriptionPopup.tsx index 1645d0813..2a96ce458 100644 --- a/src/client/views/nodes/LinkDescriptionPopup.tsx +++ b/src/client/views/nodes/LinkDescriptionPopup.tsx @@ -69,8 +69,10 @@ export class LinkDescriptionPopup extends React.Component<{}> { }}> e.stopPropagation()} - onKeyPress={e => e.key === 'Enter' && this.onDismiss(true)} + onKeyDown={e => { + e.key === 'Enter' && this.onDismiss(true); + e.stopPropagation(); + }} value={this.description} placeholder={this.description || '(Optional) Enter link description...'} onChange={e => this.descriptionChanged(e)} diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx index d9d0dbe3e..8c65fd34e 100644 --- a/src/client/views/nodes/ScriptingBox.tsx +++ b/src/client/views/nodes/ScriptingBox.tsx @@ -670,7 +670,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent() const definedParameters = !this.compileParams.length ? null : (
      {this.compileParams.map((parameter, i) => ( -
      e.key === 'Enter' && this._overlayDisposer?.()}> +
      e.key === 'Enter' && this._overlayDisposer?.()}> () {!this.compileParams.length || !this.paramsNames ? null : (
      {this.paramsNames.map((parameter: string, i: number) => ( -
      e.key === 'Enter' && this._overlayDisposer?.()}> +
      e.key === 'Enter' && this._overlayDisposer?.()}>
      {`${parameter}:${this.paramsTypes[i]} = `}
      {this.paramsTypes[i] === 'boolean' ? this.renderEnum(parameter, [true, false]) : null} diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index 5b03e2236..8802a032f 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -1,6 +1,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; -import { action, computed, IReactionDisposer, makeObservable, observable, reaction, trace } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction, trace } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; @@ -22,15 +22,20 @@ import { OpenWhere } from '../DocumentView'; import './DashFieldView.scss'; import { FormattedTextBox } from './FormattedTextBox'; import { DocData } from '../../../../fields/DocSymbols'; +import { NodeSelection, TextSelection } from 'prosemirror-state'; export class DashFieldView { dom: HTMLDivElement; // container for label and value root: any; node: any; tbox: FormattedTextBox; + @observable expanded = false; + Expanded = () => this.expanded; unclickable = () => !this.tbox._props.rootSelected?.() && this.node.marks.some((m: any) => m.type === this.tbox.EditorView?.state.schema.marks.linkAnchor && m.attrs.noPreview); constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) { + makeObservable(this); + const self = this; this.node = node; this.tbox = tbox; this.dom = document.createElement('div'); @@ -38,11 +43,26 @@ export class DashFieldView { this.dom.style.height = node.attrs.height; this.dom.style.position = 'relative'; this.dom.style.display = 'inline-block'; - this.dom.onkeypress = function (e: any) { + const tBox = this.tbox; + this.dom.onkeypress = function (e: KeyboardEvent) { e.stopPropagation(); }; - this.dom.onkeydown = function (e: any) { + this.dom.onkeydown = function (e: KeyboardEvent) { e.stopPropagation(); + if (e.key === 'Tab') { + e.preventDefault(); + const editor = tbox.EditorView; + if (editor) { + const state = editor.state; + for (var i = state.selection.to; i < state.doc.content.size; i++) { + if (state.doc.nodeAt(i)?.type.name === state.schema.nodes.dashField.name) { + editor.dispatch(state.tr.setSelection(new NodeSelection(state.doc.resolve(i)))); + return; + } + } + tBox.setFocus(state.selection.to + 1); + } + } }; this.dom.onkeyup = function (e: any) { e.stopPropagation(); @@ -51,6 +71,8 @@ export class DashFieldView { e.stopPropagation(); }; + this.expanded = node.attrs.expanded; + this.root = ReactDOM.createRoot(this.dom); this.root.render( @@ -77,9 +99,11 @@ export class DashFieldView { }); } deselectNode() { + runInAction(() => (this.expanded = false)); this.dom.classList.remove('ProseMirror-selectednode'); } selectNode() { + setTimeout(() => runInAction(() => (this.expanded = true)), 100); this.dom.classList.add('ProseMirror-selectednode'); } } @@ -92,7 +116,7 @@ interface IDashFieldViewInternal { width: number; height: number; editable: boolean; - expanded: boolean; + expanded: () => boolean; dataDoc: boolean; node: any; getPos: any; @@ -106,7 +130,7 @@ export class DashFieldViewInternal extends ObservableReactComponent(); @observable _dashDoc: Doc | undefined = undefined; - @observable _expanded = this._props.expanded; + @observable _expanded = this._props.expanded(); constructor(props: IDashFieldViewInternal) { super(props); @@ -132,7 +156,7 @@ export class DashFieldViewInternal extends ObservableReactComponent this._expanded && this._props.editable; + isRowActive = () => (this._props.expanded() || this._expanded) && this._props.editable; finishEdit = action(() => { if (this._expanded) { @@ -155,7 +179,7 @@ export class DashFieldViewInternal extends ObservableReactComponent ({ value: facet, label: facet })); @@ -239,13 +263,13 @@ export class DashFieldViewInternal extends ObservableReactComponent )} {this._props.fieldKey.startsWith('#') ? null : this.fieldValueContent} - {!this.values.length ? null : ( - {this.values.map(val => ( ))} - )} + )} */}
      ); } diff --git a/src/client/views/nodes/formattedText/EquationView.tsx b/src/client/views/nodes/formattedText/EquationView.tsx index b786c5ffb..b90653acc 100644 --- a/src/client/views/nodes/formattedText/EquationView.tsx +++ b/src/client/views/nodes/formattedText/EquationView.tsx @@ -8,6 +8,7 @@ import { StrCast } from '../../../../fields/Types'; import './DashFieldView.scss'; import EquationEditor from './EquationEditor'; import { FormattedTextBox } from './FormattedTextBox'; +import { DocData } from '../../../../fields/DocSymbols'; export class EquationView { dom: HTMLDivElement; // container for label and value @@ -88,7 +89,6 @@ export class EquationViewInternal extends React.Component } e.stopPropagation(); }} - onKeyPress={e => e.stopPropagation()} style={{ position: 'relative', display: 'inline-block', @@ -96,12 +96,11 @@ export class EquationViewInternal extends React.Component height: this.props.height, background: 'white', borderRadius: '10%', - bottom: 3, }}> ) => { + onKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { DocServer.GetRefField(this.idToAdd).then( action((field: any) => { @@ -168,7 +168,7 @@ class Viewer extends React.Component { render() { return ( <> - +
      {this.fields.map((field, index) => ( false}> -- cgit v1.2.3-70-g09d2 From 397e152d6450b4904645ebb271691fb01b267c4e Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 27 Mar 2024 13:29:55 -0400 Subject: fixed collapsible text box outlines. fixed ending lists with enter. --- .../views/nodes/formattedText/FormattedTextBox.tsx | 18 +++++++----- .../formattedText/ProsemirrorExampleTransfer.ts | 34 ++++++++++------------ src/client/views/nodes/formattedText/marks_rts.ts | 16 ---------- 3 files changed, 26 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 70b3b52fd..1a5e1febf 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1671,10 +1671,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent>(schema: S, props: any, mapKey const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks()); if ( - !liftListItem(schema.nodes.list_item)(state.tr, (tx2: Transaction) => { + !liftListItem(schema.nodes.list_item)(state, (tx2: Transaction) => { const tx3 = updateBullets(tx2, schema); marks && tx3.ensureMarks([...marks]); marks && tx3.setStoredMarks([...marks]); @@ -164,12 +165,6 @@ export function buildKeymap>(schema: S, props: any, mapKey SelectionManager.DeselectAll(); }); - const splitMetadata = (marks: any, tx: Transaction) => { - marks && tx.ensureMarks(marks.filter((val: any) => val.type !== schema.marks.metadata && val.type !== schema.marks.metadataKey && val.type !== schema.marks.metadataVal)); - marks && tx.setStoredMarks(marks.filter((val: any) => val.type !== schema.marks.metadata && val.type !== schema.marks.metadataKey && val.type !== schema.marks.metadataVal)); - return tx; - }; - bind('Alt-Enter', () => (props.onKey?.(event, props) ? true : true)); bind('Ctrl-Enter', () => (props.onKey?.(event, props) ? true : true)); bind('Cmd-a', (state: EditorState, dispatch: (tx: Transaction) => void) => { @@ -288,7 +283,8 @@ export function buildKeymap>(schema: S, props: any, mapKey //newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock //command to break line - bind('Enter', (state: EditorState, dispatch: (tx: Transaction) => void) => { + + const enter = (state: EditorState, dispatch: (tx: Transaction) => void, view: EditorView) => { if (props.onKey?.(event, props)) return true; if (!canEdit(state)) return true; @@ -304,7 +300,11 @@ export function buildKeymap>(schema: S, props: any, mapKey const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks()); const cr = state.selection.$from.node().textContent.endsWith('\n'); if (/*cr ||*/ !newlineInCode(state, dispatch as any)) { - if ( + if (!view.state.selection.$from.nodeBefore && !view.state.selection.$from.nodeBefore) { + do { + liftListItem(schema.nodes.list_item)(view.state, view.dispatch); + } while (view.state.selection.$from.depth > 1); + } else if ( !splitListItem(schema.nodes.list_item)(state as any, (tx2: Transaction) => { const tx3 = updateBullets(tx2, schema); marks && tx3.ensureMarks([...marks]); @@ -318,10 +318,9 @@ export function buildKeymap>(schema: S, props: any, mapKey const tonode = tx3.selection.$to.node(); if (tx3.selection.to && tx3.doc.nodeAt(tx3.selection.to - 1)) { const tx4 = tx3.setNodeMarkup(tx3.selection.to - 1, tonode.type, fromattrs, tonode.marks); - splitMetadata(marks, tx4); - if (!liftListItem(schema.nodes.list_item)(tx4, dispatch as (tx: Transaction) => void)) { - dispatch(tx4); - } + dispatch(tx4); + if (!view.state.selection.$from.node().content.size) liftListItem(schema.nodes.list_item)(view.state, view.dispatch); + else enter(view.state, view.dispatch, view); // view.dispatch(view.state.tr.insertText('\r\n')); } else dispatch(tx3.insertText('\r\n')); }) ) { @@ -330,13 +329,12 @@ export function buildKeymap>(schema: S, props: any, mapKey } } return true; - }); + }; + bind('Enter', enter); //Command to create a blank space bind('Space', (state: EditorState, dispatch: (tx: Transaction) => void) => { if (props.TemplateDataDocument && GetEffectiveAcl(props.TemplateDataDocument) != AclEdit && GetEffectiveAcl(props.TemplateDataDocument) != AclAugment && GetEffectiveAcl(props.TemplateDataDocument) != AclAdmin) return true; - const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks()); - dispatch(splitMetadata(marks, state.tr)); return false; }); diff --git a/src/client/views/nodes/formattedText/marks_rts.ts b/src/client/views/nodes/formattedText/marks_rts.ts index b68acc8f8..ccf7de4a1 100644 --- a/src/client/views/nodes/formattedText/marks_rts.ts +++ b/src/client/views/nodes/formattedText/marks_rts.ts @@ -235,22 +235,6 @@ export const marks: { [index: string]: MarkSpec } = { }, }, - metadata: { - toDOM() { - return ['span', { style: 'font-size:75%; background:rgba(100, 100, 100, 0.2); ' }]; - }, - }, - metadataKey: { - toDOM() { - return ['span', { style: 'font-style:italic; ' }]; - }, - }, - metadataVal: { - toDOM() { - return ['span']; - }, - }, - summarizeInclusive: { parseDOM: [ { -- cgit v1.2.3-70-g09d2 From 3bf4c1e7e9e34b2f4730e3df504ef06c36d05a9e Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 27 Mar 2024 13:39:36 -0400 Subject: fixed backspacing to delete list items. --- src/client/views/nodes/formattedText/FormattedTextBox.tsx | 2 +- src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 1a5e1febf..729c4d534 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1671,7 +1671,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent>(schema: S, props: any, mapKey }); // backspace = chainCommands(deleteSelection, joinBackward, selectNodeBackward); - bind('Backspace', (state: EditorState, dispatch: (tx: Transaction) => void) => { + const backspace = (state: EditorState, dispatch: (tx: Transaction) => void, view: EditorView) => { if (props.onKey?.(event, props)) return true; if (!canEdit(state)) return true; @@ -267,6 +267,7 @@ export function buildKeymap>(schema: S, props: any, mapKey if ( !joinBackward(state, (tx: Transaction) => { dispatch(updateBullets(tx, schema)); + if (!view.state.selection.$from.node().content.size) backspace(view.state, view.dispatch, view); }) ) { if ( @@ -279,7 +280,8 @@ export function buildKeymap>(schema: S, props: any, mapKey } } return true; - }); + }; + bind('Backspace', backspace); //newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock //command to break line -- cgit v1.2.3-70-g09d2 From 1d47f6cc8be84ab368ad91f287909ee162d1f2e2 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 27 Mar 2024 15:42:12 -0400 Subject: fixed toggling footnotes. fixed error in bullet hit test. fixed problems with backspace and enter in prosemirror transfer. fixed display of markdown options to start at top. --- src/client/util/RTFMarkup.tsx | 2 +- .../views/nodes/formattedText/FootnoteView.tsx | 4 ++- .../views/nodes/formattedText/FormattedTextBox.tsx | 3 +- .../formattedText/ProsemirrorExampleTransfer.ts | 41 ++++++++++++++-------- 4 files changed, 32 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/client/util/RTFMarkup.tsx b/src/client/util/RTFMarkup.tsx index 315daad42..57485d893 100644 --- a/src/client/util/RTFMarkup.tsx +++ b/src/client/util/RTFMarkup.tsx @@ -132,7 +132,7 @@ export class RTFMarkup extends React.Component<{}> { render() { return ( e.stopPropagation(), true); // These are used when the footnote is selected this.innerView = null; } @@ -82,9 +83,10 @@ export class FootnoteView { document.removeEventListener('pointerup', this.ignore, true); }; - toggle = () => { + toggle = (e: PointerEvent) => { if (this.innerView) this.close(); else this.open(); + e.stopPropagation(); }; close() { diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 729c4d534..9882a9be9 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1685,7 +1685,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent>(schema: S, props: any, mapKey }); // backspace = chainCommands(deleteSelection, joinBackward, selectNodeBackward); - const backspace = (state: EditorState, dispatch: (tx: Transaction) => void, view: EditorView) => { + const backspace = (state: EditorState, dispatch: (tx: Transaction) => void, view: EditorView, once = true) => { if (props.onKey?.(event, props)) return true; if (!canEdit(state)) return true; @@ -267,7 +267,7 @@ export function buildKeymap>(schema: S, props: any, mapKey if ( !joinBackward(state, (tx: Transaction) => { dispatch(updateBullets(tx, schema)); - if (!view.state.selection.$from.node().content.size) backspace(view.state, view.dispatch, view); + if (once && view.state.selection.$from.depth > 1 && view.state.selection.$from.node(view.state.selection.$from.depth - 1).type === view.state.schema.nodes.list_item) backspace(view.state, view.dispatch, view, false); }) ) { if ( @@ -286,26 +286,26 @@ export function buildKeymap>(schema: S, props: any, mapKey //newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock //command to break line - const enter = (state: EditorState, dispatch: (tx: Transaction) => void, view: EditorView) => { + const enter = (state: EditorState, dispatch: (tx: Transaction) => void, view: EditorView, once = true) => { if (props.onKey?.(event, props)) return true; if (!canEdit(state)) return true; const trange = state.selection.$from.blockRange(state.selection.$to); - const path = (state.selection.$from as any).path; - const depth = trange ? liftTarget(trange) : undefined; - const split = path.length > 5 && !path[path.length - 3].textContent && path[path.length - 6].type !== schema.nodes.list_item; - if (split && trange && depth !== undefined && depth !== null) { + const depth = trange ? liftTarget(trange) : null; + if ( + depth !== null && + state.selection.$from.node(state.selection.$from.depth - 1)?.type === state.schema.nodes.blockquote && // + !state.selection.$from.node().content.size && + trange + ) { dispatch(state.tr.lift(trange, depth) as any); return true; } const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks()); - const cr = state.selection.$from.node().textContent.endsWith('\n'); - if (/*cr ||*/ !newlineInCode(state, dispatch as any)) { - if (!view.state.selection.$from.nodeBefore && !view.state.selection.$from.nodeBefore) { - do { - liftListItem(schema.nodes.list_item)(view.state, view.dispatch); - } while (view.state.selection.$from.depth > 1); + if (!newlineInCode(state, dispatch as any)) { + if (once && view.state.selection.$from.depth > 1 && !view.state.selection.$from.nodeBefore && !view.state.selection.$from.nodeBefore) { + for (let i = 0; i < 10 && view.state.selection.$from.depth > 1 && liftListItem(schema.nodes.list_item)(view.state, view.dispatch); i++); } else if ( !splitListItem(schema.nodes.list_item)(state as any, (tx2: Transaction) => { const tx3 = updateBullets(tx2, schema); @@ -321,8 +321,19 @@ export function buildKeymap>(schema: S, props: any, mapKey if (tx3.selection.to && tx3.doc.nodeAt(tx3.selection.to - 1)) { const tx4 = tx3.setNodeMarkup(tx3.selection.to - 1, tonode.type, fromattrs, tonode.marks); dispatch(tx4); - if (!view.state.selection.$from.node().content.size) liftListItem(schema.nodes.list_item)(view.state, view.dispatch); - else enter(view.state, view.dispatch, view); // view.dispatch(view.state.tr.insertText('\r\n')); + if ( + view.state.selection.$from.parentOffset && // + !view.state.selection.$from.node().content.size + ) + liftListItem(schema.nodes.list_item)(view.state, view.dispatch); + else if ( + once && + view.state.selection.$from.parentOffset && + view.state.selection.$from.depth > 1 && // + view.state.selection.$from.node(view.state.selection.$from.depth - 1).type === schema.nodes.list_item + ) + enter(view.state, view.dispatch, view, false); + else if (once && depth && !view.state.selection.$from.parentOffset) backspace(view.state, view.dispatch, view, false); } else dispatch(tx3.insertText('\r\n')); }) ) { -- cgit v1.2.3-70-g09d2 From 6eff9b8943a74c8f1c80741efac20fbe8c50cece Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 27 Mar 2024 15:49:09 -0400 Subject: fixed forward hyperlink reference to not publish. --- src/client/views/nodes/formattedText/RichTextRules.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts index c3eaf4dd2..c59a94394 100644 --- a/src/client/views/nodes/formattedText/RichTextRules.ts +++ b/src/client/views/nodes/formattedText/RichTextRules.ts @@ -307,7 +307,7 @@ export class RichTextRules { }; const getTitledDoc = (docTitle: string) => { if (!DocServer.FindDocByTitle(docTitle)) { - Doc.AddToMyPublished(Docs.Create.TextDocument('', { title: docTitle, _width: 400, _layout_autoHeight: true })); + Docs.Create.TextDocument('', { title: docTitle, _width: 400, _layout_fitWidth: true, _layout_autoHeight: true }); } const titledDoc = DocServer.FindDocByTitle(docTitle); return titledDoc ? Doc.BestEmbedding(titledDoc) : titledDoc; -- cgit v1.2.3-70-g09d2 From 00367534e4a61eea788beffedaa0bc266ea3aa16 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 27 Mar 2024 17:23:55 -0400 Subject: fixed lightbox views to suppressheight for docs with layout_fitWidth set --- src/client/views/LightboxView.tsx | 1 + src/client/views/nodes/DocumentView.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index b9d805145..1f0b8e387 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -259,6 +259,7 @@ export class LightboxView extends ObservableReactComponent { styleProvider={DefaultStyleProvider} ScreenToLocalTransform={this.lightboxScreenToLocal} renderDepth={0} + suppressSetHeight={this._doc._layout_fitWidth ? true : false} containerViewPath={returnEmptyDoclist} childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 3154ee434..6d8656888 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -222,7 +222,7 @@ export class DocumentViewInternal extends DocComponent !link.link_matchEmbeddings || link.link_anchor_1 === this.Document || link.link_anchor_2 === this.Document); } -- cgit v1.2.3-70-g09d2 From 9b2cfea0c13fef048ba6ae3d5281d1eea836e9b3 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 27 Mar 2024 19:22:26 -0400 Subject: preserve nodeSelections after onBlur by not calling autoLink. fix promoting text to list cursor locatoin --- .../views/nodes/formattedText/FormattedTextBox.tsx | 22 +++++++++++++--------- .../formattedText/ProsemirrorExampleTransfer.ts | 3 ++- 2 files changed, 15 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 9882a9be9..d25101844 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1694,8 +1694,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { - tr.addStoredMark(m); - return tr; - }, this._editorView.state.tr); - tr && this._editorView.dispatch(tr); + if (!(this.EditorView?.state.selection instanceof NodeSelection)) { + this.autoLink(); + if (this._editorView?.state.tr) { + const tr = stordMarks?.reduce((tr, m) => { + tr.addStoredMark(m); + return tr; + }, this._editorView.state.tr); + tr && this._editorView.dispatch(tr); + } } } if (RichTextMenu.Instance?.view === this._editorView && !this._props.rootSelected?.()) { diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts index 87eee1b2f..ab49a53ea 100644 --- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts +++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts @@ -107,7 +107,8 @@ export function buildKeymap>(schema: S, props: any, mapKey // when promoting to a list, assume list will format things so don't copy the stored marks. marks && tx3.ensureMarks([...marks]); marks && tx3.setStoredMarks([...marks]); - dispatch(tx3); + const tx4 = tx3.setSelection(TextSelection.near(tx3.doc.resolve(state.selection.to + 2))); + dispatch(tx4); }) ) { console.log('bullet promote fail'); -- cgit v1.2.3-70-g09d2 From 52bd492747cf169df7bcdecdbdbb353d45b19734 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 28 Mar 2024 00:05:05 -0400 Subject: fixed tabbing between items in nested dashFieldViews --- src/client/views/EditableView.tsx | 1 + .../views/collections/collectionSchema/CollectionSchemaView.scss | 9 +++++++++ .../views/collections/collectionSchema/SchemaTableCell.tsx | 8 ++++---- src/fields/Doc.ts | 3 +++ src/fields/RichTextField.ts | 7 +++++++ 5 files changed, 24 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 44c8e4e1f..85e893e19 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -121,6 +121,7 @@ export class EditableView extends ObservableReactComponent { @action onKeyDown = (e: React.KeyboardEvent) => { + if (e.nativeEvent.defaultPrevented) return; // hack .. DashFieldView grabs native events, but react ignores stoppedPropagation and preventDefault, so we need to check it here switch (e.key) { case 'Tab': e.stopPropagation(); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index ac0bd2378..9768877ff 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -226,6 +226,15 @@ align-items: center; } +.schemaRTFCell { + display: flex; + width: 100%; + height: 100%; + position: relative; + min-width: 10px; + min-height: 10px; +} + .schema-row { cursor: grab; justify-content: flex-end; diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index bda8afa41..ab05a62d3 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -17,6 +17,7 @@ import { FInfo, FInfoFieldType } from '../../../documents/Documents'; import { DocFocusOrOpen } from '../../../util/DocumentManager'; import { dropActionType } from '../../../util/DragManager'; import { SettingsManager } from '../../../util/SettingsManager'; +import { SnappingManager } from '../../../util/SnappingManager'; import { Transform } from '../../../util/Transform'; import { undoBatch, undoable } from '../../../util/UndoManager'; import { EditableView } from '../../EditableView'; @@ -29,7 +30,6 @@ import { KeyValueBox } from '../../nodes/KeyValueBox'; import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { ColumnType, FInfotoColType } from './CollectionSchemaView'; import './CollectionSchemaView.scss'; -import { SnappingManager } from '../../../util/SnappingManager'; export interface SchemaTableCellProps { Document: Doc; @@ -128,7 +128,7 @@ export class SchemaTableCell extends ObservableReactComponent this._props.autoFocus && r?.setIsFocused(true)} + ref={r => this.selected && this._props.autoFocus && r?.setIsFocused(true)} oneLine={this._props.oneLine} allowCRs={this._props.allowCRs} contents={undefined} @@ -141,7 +141,7 @@ export class SchemaTableCell extends ObservableReactComponent +
      {this.selected ? this._props.finishEdit?.()} /> : (field => (field ? Field.toString(field) : ''))(FieldValue(fieldProps.Document[fieldProps.fieldKey]))}
      ); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 1bd49cf3f..bdf600475 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1713,3 +1713,6 @@ ScriptingGlobals.add(function setDocRangeFilter(container: Doc, key: string, ran ScriptingGlobals.add(function toJavascriptString(str: string) { return Field.toJavascriptString(str as Field); }); +ScriptingGlobals.add(function RtfField() { + return RichTextField.RTFfield(); +}); diff --git a/src/fields/RichTextField.ts b/src/fields/RichTextField.ts index d0a149506..3f13f7e6d 100644 --- a/src/fields/RichTextField.ts +++ b/src/fields/RichTextField.ts @@ -36,4 +36,11 @@ export class RichTextField extends ObjectField { [ToString]() { return this.Text; } + + public static RTFfield() { + return new RichTextField( + `{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}`, + '' + ); + } } -- cgit v1.2.3-70-g09d2 From 1b592f74a7df8f6dd7b2881032725f26aedff403 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 28 Mar 2024 11:38:56 -0400 Subject: fixed keyvaluebox to show props document, never the doc in the fieldKey slot. changed computedFIelds to do mobx caching. changed text boxes to do updating from templates based on a fieldKey_autoUpdate flag combined with modification timestamps. enabled comparison box to work with text fields in addition to docs. --- src/client/util/Scripting.ts | 9 +-- src/client/views/InkControlPtHandles.tsx | 85 ++++++++++++---------- src/client/views/PropertiesButtons.tsx | 4 +- src/client/views/nodes/ComparisonBox.tsx | 6 +- src/client/views/nodes/KeyValueBox.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 31 +++++--- src/fields/Doc.ts | 2 +- src/fields/ScriptField.ts | 22 ++++-- 8 files changed, 90 insertions(+), 71 deletions(-) (limited to 'src') diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index f5e162d16..31222aa50 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -88,15 +88,10 @@ function Run(script: string | undefined, customParams: string[], diagnostics: an } const result = compiledFunction.apply(thisParam, params).apply(thisParam, argsArray); - if (batch) { - batch.end(); - } - + batch?.end(); return { success: true, result }; } catch (error) { - if (batch) { - batch.end(); - } + batch?.end(); onError?.(script + ' ' + error); return { success: false, error, result: errorVal }; } diff --git a/src/client/views/InkControlPtHandles.tsx b/src/client/views/InkControlPtHandles.tsx index 31b13d2c8..01d52135a 100644 --- a/src/client/views/InkControlPtHandles.tsx +++ b/src/client/views/InkControlPtHandles.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { action, observable } from 'mobx'; +import { action, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import { Doc } from '../../fields/Doc'; import { ControlPoint, InkData, PointData } from '../../fields/InkField'; @@ -13,6 +13,7 @@ import { Colors } from './global/globalEnums'; import { InkingStroke } from './InkingStroke'; import { InkStrokeProperties } from './InkStrokeProperties'; import { SnappingManager } from '../util/SnappingManager'; +import { ObservableReactComponent } from './ObservableReactComponent'; export interface InkControlProps { inkDoc: Doc; @@ -24,10 +25,15 @@ export interface InkControlProps { } @observer -export class InkControlPtHandles extends React.Component { +export class InkControlPtHandles extends ObservableReactComponent { @observable private _overControl = -1; get docView() { - return this.props.inkView.DocumentView?.(); + return this._props.inkView.DocumentView?.(); + } + + constructor(props: InkControlProps) { + super(props); + makeObservable(this); } componentDidMount() { @@ -42,51 +48,51 @@ export class InkControlPtHandles extends React.Component { */ @action onControlDown = (e: React.PointerEvent, controlIndex: number): void => { - const ptFromScreen = this.props.inkView.ptFromScreen; + const ptFromScreen = this._props.inkView.ptFromScreen; if (ptFromScreen) { const order = controlIndex % 4; - const handleIndexA = ((order === 3 ? controlIndex - 1 : controlIndex - 2) + this.props.inkCtrlPoints.length) % this.props.inkCtrlPoints.length; - const handleIndexB = (order === 3 ? controlIndex + 2 : controlIndex + 1) % this.props.inkCtrlPoints.length; - const brokenIndices = Cast(this.props.inkDoc.brokenInkIndices, listSpec('number')); + const handleIndexA = ((order === 3 ? controlIndex - 1 : controlIndex - 2) + this._props.inkCtrlPoints.length) % this._props.inkCtrlPoints.length; + const handleIndexB = (order === 3 ? controlIndex + 2 : controlIndex + 1) % this._props.inkCtrlPoints.length; + const brokenIndices = Cast(this._props.inkDoc.brokenInkIndices, listSpec('number')); const wasSelected = InkStrokeProperties.Instance._currentPoint === controlIndex; if (!wasSelected) InkStrokeProperties.Instance._currentPoint = -1; - const origInk = this.props.inkCtrlPoints.slice(); + const origInk = this._props.inkCtrlPoints.slice(); setupMoveUpEvents( this, e, action((e: PointerEvent, down: number[], delta: number[]) => { - if (!this.props.inkView.controlUndo) this.props.inkView.controlUndo = UndoManager.StartBatch('drag ink ctrl pt'); + if (!this._props.inkView.controlUndo) this._props.inkView.controlUndo = UndoManager.StartBatch('drag ink ctrl pt'); const inkMoveEnd = ptFromScreen({ X: delta[0], Y: delta[1] }); const inkMoveStart = ptFromScreen({ X: 0, Y: 0 }); this.docView && InkStrokeProperties.Instance.moveControlPtHandle(this.docView, inkMoveEnd.X - inkMoveStart.X, inkMoveEnd.Y - inkMoveStart.Y, controlIndex, origInk); return false; }), action(() => { - if (this.props.inkView.controlUndo && this.docView) { + if (this._props.inkView.controlUndo && this.docView) { InkStrokeProperties.Instance.snapControl(this.docView, controlIndex); } - this.props.inkView.controlUndo?.end(); - this.props.inkView.controlUndo = undefined; + this._props.inkView.controlUndo?.end(); + this._props.inkView.controlUndo = undefined; UndoManager.FilterBatches(['data', 'x', 'y', 'width', 'height']); }), action((e: PointerEvent, doubleTap: boolean | undefined) => { - const equivIndex = controlIndex === 0 ? this.props.inkCtrlPoints.length - 1 : controlIndex === this.props.inkCtrlPoints.length - 1 ? 0 : controlIndex; + const equivIndex = controlIndex === 0 ? this._props.inkCtrlPoints.length - 1 : controlIndex === this._props.inkCtrlPoints.length - 1 ? 0 : controlIndex; if (doubleTap || e.button === 2) { if (!brokenIndices?.includes(equivIndex) && !brokenIndices?.includes(controlIndex)) { if (brokenIndices) brokenIndices.push(controlIndex); - else this.props.inkDoc.brokenInkIndices = new List([controlIndex]); + else this._props.inkDoc.brokenInkIndices = new List([controlIndex]); } else { if (brokenIndices?.includes(equivIndex)) { - if (!this.props.inkView.controlUndo) this.props.inkView.controlUndo = UndoManager.StartBatch('make smooth'); + if (!this._props.inkView.controlUndo) this._props.inkView.controlUndo = UndoManager.StartBatch('make smooth'); this.docView && InkStrokeProperties.Instance.snapHandleTangent(this.docView, equivIndex, handleIndexA, handleIndexB); } if (equivIndex !== controlIndex && brokenIndices?.includes(controlIndex)) { - if (!this.props.inkView.controlUndo) this.props.inkView.controlUndo = UndoManager.StartBatch('make smooth'); + if (!this._props.inkView.controlUndo) this._props.inkView.controlUndo = UndoManager.StartBatch('make smooth'); this.docView && InkStrokeProperties.Instance.snapHandleTangent(this.docView, controlIndex, handleIndexA, handleIndexB); } } - this.props.inkView.controlUndo?.end(); - this.props.inkView.controlUndo = undefined; + this._props.inkView.controlUndo?.end(); + this._props.inkView.controlUndo = undefined; } this.changeCurrPoint(controlIndex); }), @@ -126,14 +132,14 @@ export class InkControlPtHandles extends React.Component { render() { // Accessing the current ink's data and extracting all control points. - const scrData = this.props.screenCtrlPoints; + const scrData = this._props.screenCtrlPoints; const sreenCtrlPoints: ControlPoint[] = []; for (let i = 0; i <= scrData.length - 4; i += 4) { sreenCtrlPoints.push({ ...scrData[i], I: i }); sreenCtrlPoints.push({ ...scrData[i + 3], I: i + 3 }); } - const inkData = this.props.inkCtrlPoints; + const inkData = this._props.inkCtrlPoints; const inkCtrlPts: ControlPoint[] = []; for (let i = 0; i <= inkData.length - 4; i += 4) { inkCtrlPts.push({ ...inkData[i], I: i }); @@ -141,23 +147,23 @@ export class InkControlPtHandles extends React.Component { } const closed = InkingStroke.IsClosed(inkData); - const nearestScreenPt = this.props.nearestScreenPt(); + const nearestScreenPt = this._props.nearestScreenPt(); const TagType = (broken?: boolean) => (broken ? 'rect' : 'circle'); const hdl = (control: { X: number; Y: number; I: number }, scale: number, color: string) => { - const broken = Cast(this.props.inkDoc.brokenInkIndices, listSpec('number'))?.includes(control.I); + const broken = Cast(this._props.inkDoc.brokenInkIndices, listSpec('number'))?.includes(control.I); const Tag = TagType((control.I === 0 || control.I === inkData.length - 1) && !closed) as keyof JSX.IntrinsicElements; return ( this.onControlDown(e, control.I)} @@ -170,7 +176,7 @@ export class InkControlPtHandles extends React.Component { }; return ( - {!nearestScreenPt ? null : } + {!nearestScreenPt ? null : } {sreenCtrlPoints.map(control => hdl(control, this._overControl !== control.I ? 1 : 3 / 2, Colors.WHITE))} ); @@ -185,10 +191,15 @@ export interface InkEndProps { endPt: () => PointData; } @observer -export class InkEndPtHandles extends React.Component { +export class InkEndPtHandles extends ObservableReactComponent { @observable _overStart: boolean = false; @observable _overEnd: boolean = false; + constructor(props: InkEndProps) { + super(props); + makeObservable(this); + } + _throttle = 0; // need to throttle dragging since the position may change when the control points change. this allows the stroke to settle so that we don't get increasingly bad jitter @action dragRotate = (e: React.PointerEvent, pt1: () => { X: number; Y: number }, pt2: () => { X: number; Y: number }) => { @@ -198,7 +209,7 @@ export class InkEndPtHandles extends React.Component { e, action(e => { if (this._throttle++ % 2 !== 0) return false; - if (!this.props.inkView.controlUndo) this.props.inkView.controlUndo = UndoManager.StartBatch('stretch ink'); + if (!this._props.inkView.controlUndo) this._props.inkView.controlUndo = UndoManager.StartBatch('stretch ink'); // compute stretch factor by finding scaling along axis between start and end points const p1 = pt1(); const p2 = pt2(); @@ -216,8 +227,8 @@ export class InkEndPtHandles extends React.Component { }), action(() => { SnappingManager.SetIsDragging(false); - this.props.inkView.controlUndo?.end(); - this.props.inkView.controlUndo = undefined; + this._props.inkView.controlUndo?.end(); + this._props.inkView.controlUndo = undefined; UndoManager.FilterBatches(['stroke', 'x', 'y', 'width', 'height']); }), returnFalse @@ -230,7 +241,7 @@ export class InkEndPtHandles extends React.Component { key={key} cx={pt.X} cy={pt.Y} - r={this.props.screenSpaceLineWidth * 2} + r={this._props.screenSpaceLineWidth * 2} fill={this._overStart ? '#aaaaaa' : '#99999977'} stroke={'#00007777'} strokeWidth={0} @@ -242,8 +253,8 @@ export class InkEndPtHandles extends React.Component { ); return ( - {hdl('start', this.props.startPt(), e => this.dragRotate(e, this.props.startPt, this.props.endPt))} - {hdl('end', this.props.endPt(), e => this.dragRotate(e, this.props.endPt, this.props.startPt))} + {hdl('start', this._props.startPt(), e => this.dragRotate(e, this._props.startPt, this._props.endPt))} + {hdl('end', this._props.endPt(), e => this.dragRotate(e, this._props.endPt, this._props.startPt))} ); } diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 02f288a68..517a80d63 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -87,7 +87,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { containerDoc._isLightbox = !containerDoc._isLightbox; //containerDoc._xPadding = containerDoc._yPadding = containerDoc._isLightbox ? 10 : undefined; const containerContents = DocListCast(dv.dataDoc[Doc.LayoutFieldKey(containerDoc)]); - //dv.Docuemnt.onClick = ScriptField.MakeScript('{self.data = undefined; documentView.select(false)}', { documentView: 'any' }); + //dv.Docuemnt.onClick = ScriptField.MakeScript('{this.data = undefined; documentView.select(false)}', { documentView: 'any' }); containerContents.forEach(doc => LinkManager.Links(doc).forEach(link => (link.link_displayLine = false))); }); } @@ -219,7 +219,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { // containerDoc._isLightbox = !containerDoc._isLightbox; // //containerDoc._xPadding = containerDoc._yPadding = containerDoc._isLightbox ? 10 : undefined; // const containerContents = DocListCast(dv.dataDoc[dv.props.fieldKey ?? Doc.LayoutFieldKey(containerDoc)]); - // //dv.Document.onClick = ScriptField.MakeScript('{self.data = undefined; documentView.select(false)}', { documentView: 'any' }); + // //dv.Document.onClick = ScriptField.MakeScript('{this.data = undefined; documentView.select(false)}', { documentView: 'any' }); // containerContents.forEach(doc => LinkManager.Links(doc).forEach(link => (link.layout_linkDisplay = false))); // }); // } diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index 59d99b371..9ffdc350d 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -69,8 +69,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() action((e, doubleTap) => { if (doubleTap) { this._isAnyChildContentActive = true; - if (!this.dataDoc[this.fieldKey + '_1']) this.dataDoc[this.fieldKey + '_1'] = DocUtils.copyDragFactory(Doc.UserDoc().emptyNote as Doc); - if (!this.dataDoc[this.fieldKey + '_2']) this.dataDoc[this.fieldKey + '_2'] = DocUtils.copyDragFactory(Doc.UserDoc().emptyNote as Doc); + if (!this.dataDoc[this.fieldKey + '_1'] && !this.dataDoc[this.fieldKey]) this.dataDoc[this.fieldKey + '_1'] = DocUtils.copyDragFactory(Doc.UserDoc().emptyNote as Doc); + if (!this.dataDoc[this.fieldKey + '_2'] && !this.dataDoc[this.fieldKey + '_alternate']) this.dataDoc[this.fieldKey + '_2'] = DocUtils.copyDragFactory(Doc.UserDoc().emptyNote as Doc); } }), false, @@ -131,8 +131,6 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() return false; }; - whenChildContentsActiveChanged = action((isActive: boolean) => (this._isAnyChildContentActive = isActive)); - closeDown = (e: React.PointerEvent, which: string) => { setupMoveUpEvents( this, diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 78e4435ce..31a2367fc 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -55,7 +55,7 @@ export class KeyValueBox extends ObservableReactComponent { @observable _splitPercentage = 50; get fieldDocToLayout() { - return this._props.fieldKey ? DocCast(this._props.Document[this._props.fieldKey], DocCast(this._props.Document)) : this._props.Document; + return DocCast(this._props.Document); } @action diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index d25101844..f06e5fad0 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -21,7 +21,7 @@ import { List } from '../../../../fields/List'; import { PrefetchProxy } from '../../../../fields/Proxy'; import { RichTextField } from '../../../../fields/RichTextField'; import { ComputedField } from '../../../../fields/ScriptField'; -import { BoolCast, Cast, DocCast, FieldValue, NumCast, RTFCast, ScriptCast, StrCast } from '../../../../fields/Types'; +import { BoolCast, Cast, DateCast, DocCast, FieldValue, NumCast, RTFCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util'; import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, DivWidth, emptyFunction, numberRange, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils'; import { gptAPICall, GPTCallType } from '../../../apis/gpt/GPT'; @@ -349,6 +349,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent json?.replace(/"selection":.*/, ''); @@ -369,22 +370,20 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent (this.dataDoc[this.fieldKey + '_autoUpdate'] = !this.dataDoc[this.fieldKey + '_autoUpdate']), icon: 'star' }); optionItems.push({ description: `Generate Dall-E Image`, event: () => this.generateImage(), icon: 'star' }); optionItems.push({ description: `Ask GPT-3`, event: () => this.askGPT(), icon: 'lightbulb' }); this._props.renderDepth && @@ -1244,9 +1244,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { - const dataDoc = Doc.IsDelegateField(DocCast(this.layoutDoc?.proto), this.fieldKey) ? DocCast(this.layoutDoc?.proto) : this?.dataDoc; - const whichDoc = !this.dataDoc || !this.layoutDoc ? undefined : dataDoc?.[this.fieldKey + '_noTemplate'] || !this.layoutDoc[this.fieldKey] ? dataDoc : this.layoutDoc; - return !whichDoc ? undefined : { data: Cast(whichDoc[this.fieldKey], RichTextField, null), str: Field.toString(DocCast(whichDoc[this.fieldKey]) ?? StrCast(whichDoc[this.fieldKey])) }; + const protoData = DocCast(this.dataDoc.proto)?.[this.fieldKey]; + const dataData = this.dataDoc[this.fieldKey]; + const layoutData = Doc.AreProtosEqual(this.layoutDoc, this.dataDoc) ? undefined : this.layoutDoc[this.fieldKey]; + const dataTime = dataData ? DateCast(this.dataDoc[this.fieldKey + '_modificationDate'])?.date.getTime() ?? 0 : 0; + const layoutTime = layoutData && this.dataDoc[this.fieldKey + '_autoUpdate'] ? DateCast(DocCast(this.layoutDoc)[this.fieldKey + '_modificationDate'])?.date.getTime() ?? 0 : 0; + const protoTime = protoData && this.dataDoc[this.fieldKey + '_autoUpdate'] ? DateCast(DocCast(this.dataDoc.proto)[this.fieldKey + '_modificationDate'])?.date.getTime() ?? 0 : 0; + const recentData = dataTime >= layoutTime ? (protoTime >= dataTime ? protoData : dataData) : layoutTime >= protoTime ? layoutData : protoData; + const whichData = recentData ?? (this.layoutDoc.isTemplateDoc ? layoutData : protoData) ?? protoData; + return !whichData ? undefined : { data: RTFCast(whichData), str: Field.toString(DocCast(whichData) ?? StrCast(whichData)) }; }, incomingValue => { if (this._editorView && this._applyingChange !== this.fieldKey) { @@ -1256,11 +1262,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent this._editorView?.dispatch(tx.insertText(incomingValue?.str ?? ''))); } } - } + }, + { fireImmediately: true } ); this._disposers.search = reaction( diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index bdf600475..200896e25 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -48,7 +48,7 @@ export namespace Field { const valFunc = (field: Field): string => { const res = field instanceof ComputedField && showComputedValue - ? field._lastComputedResult + ? field.value(doc) : field instanceof ComputedField ? `:=${field.script.originalScript.replace(/dashCallChat\(_setCacheResult_, this, `(.*)`\)/, '(($1))')}` : field instanceof ScriptField diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts index 9021c8896..8b51088b2 100644 --- a/src/fields/ScriptField.ts +++ b/src/fields/ScriptField.ts @@ -198,14 +198,22 @@ export class ComputedField extends ScriptField { } _lastComputedResult: FieldResult; - value = computedFn((doc: Doc) => this._valueOutsideReaction(doc)); - _valueOutsideReaction = (doc: Doc) => { - this._lastComputedResult = - this._cachedResult ?? (this.script.compiled && this.script.run({ this: doc, self: doc, value: '', _setCacheResult_: this.setCacheResult, _last_: this._lastComputedResult, _readOnly_: true }, console.log).result); - return this._lastComputedResult; - }; + value = (doc:Doc) => (this._lastComputedResult = this._cachedResult ?? + computedFn((doc: Doc) => + this.script.compiled && + this.script.run( { + this: doc, + //value: '', + _setCacheResult_: this.setCacheResult, + _last_: this._lastComputedResult, + _readOnly_: true, + }, + console.log + ).result + )(doc) + ); // prettier-ignore - [ToValue](doc: Doc) { if (ComputedField.useComputed) return { value: this._valueOutsideReaction(doc) }; } // prettier-ignore + [ToValue](doc: Doc) { if (ComputedField.useComputed) return { value: this.value(doc) }; } // prettier-ignore [Copy](): ObjectField { return new ComputedField(this.script, this.setterscript, this.rawscript); } // prettier-ignore public static MakeFunction(script: string, params: object = {}, capturedVariables?: { [name: string]: Doc | string | number | boolean }, setterscript?: string) { -- cgit v1.2.3-70-g09d2 From 75a520e2cbdd611fcd1846540c42c25df9f70241 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 28 Mar 2024 15:22:15 -0400 Subject: enabled functions to be entered in dashFieldViews on creation. --- src/client/views/nodes/formattedText/RichTextRules.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts index c59a94394..7afe91e94 100644 --- a/src/client/views/nodes/formattedText/RichTextRules.ts +++ b/src/client/views/nodes/formattedText/RichTextRules.ts @@ -325,7 +325,7 @@ export class RichTextRules { // [@{this,doctitle,}.fieldKey{:,=,:=,=:=}value] // [@{this,doctitle,}.fieldKey] new InputRule( - new RegExp(/\[(@|@this\.|@[a-zA-Z_\? \-0-9]+\.)([a-zA-Z_\?\-0-9]+)((:|=|:=|=:=)([a-zA-Z,_@\?\+\-\*\/\ 0-9\(\)]*))?\]/), + new RegExp(/\[(@|@this\.|@[a-zA-Z_\? \-0-9]+\.)([a-zA-Z_\?\-0-9]+)((:|=|:=|=:=)([a-zA-Z,_\(\)\.@\?\+\-\*\/\ 0-9\(\)]*))?\]/), (state, match, start, end) => { const docTitle = match[1].substring(1).replace(/\.$/, ''); const fieldKey = match[2]; @@ -346,6 +346,7 @@ export class RichTextRules { } else if (value) { KeyValueBox.SetField(this.Document, fieldKey, assign + value, Doc.IsDataProto(this.Document) ? true : undefined, assign.includes(":=") ? undefined: (gptval: FieldResult) => (dataDoc ? this.Document[DocData]:this.Document)[fieldKey] = gptval as string ); // prettier-ignore + if (fieldKey === this.TextBox.fieldKey) return this.TextBox.EditorView!.state.tr; } const target = docTitle ? getTitledDoc(docTitle) : undefined; const fieldView = state.schema.nodes.dashField.create({ fieldKey, docId: target?.[Id], hideKey: false, dataDoc }); -- cgit v1.2.3-70-g09d2 From 82a74549a6b1c942fabaf8396c450b70d65e81dd Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 28 Mar 2024 23:28:11 -0400 Subject: fixed following link to pdf text selection with highlights. fixed hide key/value in dashfieldView. fixed selecting dashFieldView nodes. --- src/client/documents/Documents.ts | 25 +- src/client/util/CurrentUserUtils.ts | 4 +- src/client/views/MarqueeAnnotator.tsx | 1 + src/client/views/SidebarAnnos.tsx | 4 +- .../CollectionFreeFormLayoutEngines.tsx | 2 +- src/client/views/nodes/MapBox/MapBox.tsx | 791 +++++---------------- src/client/views/nodes/MapBox/MapPushpinBox.tsx | 4 +- .../views/nodes/RecordingBox/RecordingView.scss | 322 ++++----- .../views/nodes/formattedText/DashFieldView.tsx | 70 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 32 +- .../views/nodes/formattedText/RichTextRules.ts | 3 +- src/client/views/nodes/formattedText/nodes_rts.ts | 1 + 12 files changed, 445 insertions(+), 814 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index b63c5e429..b3d14bc22 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1,6 +1,7 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { action, reaction, runInAction } from 'mobx'; import { basename } from 'path'; +import { OmitKeys, Utils } from '../../Utils'; import { DateField } from '../../fields/DateField'; import { Doc, DocListCast, Field, LinkedTo, Opt, StrListCast, updateCachedAcls } from '../../fields/Doc'; import { DocData, Initializing } from '../../fields/DocSymbols'; @@ -13,30 +14,29 @@ import { SchemaHeaderField } from '../../fields/SchemaHeaderField'; import { ComputedField, ScriptField } from '../../fields/ScriptField'; import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } from '../../fields/Types'; import { AudioField, CsvField, ImageField, PdfField, VideoField, WebField, YoutubeField } from '../../fields/URLField'; -import { inheritParentAcls, SharingPermissions } from '../../fields/util'; +import { SharingPermissions, inheritParentAcls } from '../../fields/util'; import { Upload } from '../../server/SharedMediaTypes'; -import { OmitKeys, Utils } from '../../Utils'; -import { YoutubeBox } from '../apis/youtube/YoutubeBox'; import { DocServer } from '../DocServer'; import { Networking } from '../Network'; +import { YoutubeBox } from '../apis/youtube/YoutubeBox'; import { DragManager, dropActionType } from '../util/DragManager'; import { FollowLinkScript } from '../util/LinkFollower'; import { LinkManager } from '../util/LinkManager'; import { ScriptingGlobals } from '../util/ScriptingGlobals'; -import { undoable, UndoManager } from '../util/UndoManager'; -import { CollectionDockingView } from '../views/collections/CollectionDockingView'; -import { DimUnit } from '../views/collections/collectionMulticolumn/CollectionMulticolumnView'; -import { CollectionView } from '../views/collections/CollectionView'; +import { UndoManager, undoable } from '../util/UndoManager'; import { ContextMenu } from '../views/ContextMenu'; import { ContextMenuProps } from '../views/ContextMenuItem'; import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, InkingStroke } from '../views/InkingStroke'; +import { CollectionDockingView } from '../views/collections/CollectionDockingView'; +import { CollectionView } from '../views/collections/CollectionView'; +import { DimUnit } from '../views/collections/collectionMulticolumn/CollectionMulticolumnView'; import { AudioBox, media_state } from '../views/nodes/AudioBox'; import { ComparisonBox } from '../views/nodes/ComparisonBox'; import { DataVizBox } from '../views/nodes/DataVizBox/DataVizBox'; +import { OpenWhere } from '../views/nodes/DocumentView'; import { EquationBox } from '../views/nodes/EquationBox'; import { FieldViewProps } from '../views/nodes/FieldView'; import { FontIconBox } from '../views/nodes/FontIconBox/FontIconBox'; -import { FormattedTextBox } from '../views/nodes/formattedText/FormattedTextBox'; import { FunctionPlotBox } from '../views/nodes/FunctionPlotBox'; import { ImageBox } from '../views/nodes/ImageBox'; import { KeyValueBox } from '../views/nodes/KeyValueBox'; @@ -52,14 +52,14 @@ import { RecordingBox } from '../views/nodes/RecordingBox/RecordingBox'; import { ScreenshotBox } from '../views/nodes/ScreenshotBox'; import { ScriptingBox } from '../views/nodes/ScriptingBox'; import { TaskCompletionBox } from '../views/nodes/TaskCompletedBox'; -import { PresBox } from '../views/nodes/trails/PresBox'; -import { PresElementBox } from '../views/nodes/trails/PresElementBox'; import { VideoBox } from '../views/nodes/VideoBox'; import { WebBox } from '../views/nodes/WebBox'; +import { CalendarBox } from '../views/nodes/calendarBox/CalendarBox'; +import { FormattedTextBox } from '../views/nodes/formattedText/FormattedTextBox'; +import { PresBox } from '../views/nodes/trails/PresBox'; +import { PresElementBox } from '../views/nodes/trails/PresElementBox'; import { SearchBox } from '../views/search/SearchBox'; import { CollectionViewType, DocumentType } from './DocumentTypes'; -import { CalendarBox } from '../views/nodes/calendarBox/CalendarBox'; -import { OpenWhere } from '../views/nodes/DocumentView'; const { default: { DFLT_IMAGE_NATIVE_DIM } } = require('../views/global/globalCssVariables.module.scss'); // prettier-ignore const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace('px', '')); @@ -204,6 +204,7 @@ export class DocumentOptions { overlayX?: NUMt = new NumInfo('horizontal coordinate in overlay view', false); overlayY?: NUMt = new NumInfo('vertical coordinate in overlay view', false); text?: RTFt = new RtfInfo('plain or rich text', true); + text_html?: STRt = new StrInfo('plain text or html', true); _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height", false); _dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units"); latitude?: NUMt = new NumInfo('latitude coordinate', false); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 11f6c82ec..f4599f04a 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -321,9 +321,9 @@ export class CurrentUserUtils { {type:"text",text:" "}, {type:"text",text:"Minerals in my tap water"}, {type:"text",text:"\n \"Calcium\" : "}, - {type:"dashField",attrs:{fieldKey:"calcium",docId:"","hideKey":false,editable:true}}, + {type:"dashField",attrs:{fieldKey:"calcium",docId:"",hideKey:false,hideValue:false,editable:true}}, {type:"text",text:"\n \"Potassium\" : "}, - {type:"dashField",attrs:{fieldKey:"pot",docId:"",hideKey:false,editable:true}}, + {type:"dashField",attrs:{fieldKey:"pot",docId:"",hideKey:false,hideValue:false,editable:true}}, {type:"text",text:"\n \"Magnesium\" : 10.01"} ]} ]}, diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index c29474fcd..0b68fd59e 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -89,6 +89,7 @@ export class MarqueeAnnotator extends ObservableReactComponent, pivotDoc: Do y: -y + (pivotAxisWidth - hgt) / 2, width: wid, height: hgt, + backgroundColor: StrCast(layoutDoc.backgroundColor), pair: { layout: doc }, replica: val.replicas[i], }); diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 927e6fad4..36dad2747 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -6,7 +6,7 @@ import { IconButton, Size, Type } from 'browndash-components'; import * as d3 from 'd3'; import { Feature, FeatureCollection, GeoJsonProperties, Geometry, LineString, Position } from 'geojson'; import mapboxgl, { LngLat, LngLatBoundsLike, MapLayerMouseEvent } from 'mapbox-gl'; -import { IReactionDisposer, ObservableMap, action, autorun, computed, makeObservable, observable, reaction, runInAction } from 'mobx'; +import { IReactionDisposer, ObservableMap, action, autorun, computed, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { CirclePicker, ColorResult } from 'react-color'; @@ -14,7 +14,6 @@ import { Layer, MapProvider, MapRef, Map as MapboxMap, Marker, Source, ViewState import { MarkerEvent } from 'react-map-gl/dist/esm/types'; import { Utils, emptyFunction, setupMoveUpEvents } from '../../../../Utils'; import { Doc, DocListCast, Field, LinkedTo, Opt } from '../../../../fields/Doc'; -import { DocCss, Highlight } from '../../../../fields/DocSymbols'; import { DocCast, NumCast, StrCast } from '../../../../fields/Types'; import { DocumentType } from '../../../documents/DocumentTypes'; import { DocUtils, Docs } from '../../../documents/Documents'; @@ -28,7 +27,7 @@ import { SidebarAnnos } from '../../SidebarAnnos'; import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm'; import { Colors } from '../../global/globalEnums'; import { DocumentView } from '../DocumentView'; -import { FocusViewOptions, FieldView, FieldViewProps } from '../FieldView'; +import { FieldView, FieldViewProps, FocusViewOptions } from '../FieldView'; import { FormattedTextBox } from '../formattedText/FormattedTextBox'; import { PinProps, PresBox } from '../trails'; import { fastSpeedIcon, mediumSpeedIcon, slowSpeedIcon } from './AnimationSpeedIcons'; @@ -53,7 +52,6 @@ import { MarkerIcons } from './MarkerIcons'; * A map marker is considered a document that contains a collection with stacking view of documents, it has a lat, lng location, which is passed to Maps API's custom marker (red pin) to be rendered on the google maps */ -const bingApiKey = process.env.BING_MAPS; // if you're running local, get a Bing Maps api key here: https://www.bingmapsportal.com/ and then add it to the .env file in the Dash-Web root directory as: _CLIENT_BING_MAPS= const MAPBOX_ACCESS_TOKEN = 'pk.eyJ1IjoiemF1bHRhdmFuZ2FyIiwiYSI6ImNscHgwNDd1MDA3MXIydm92ODdianp6cGYifQ.WFAqbhwxtMHOWSPtu0l2uQ'; const MAPBOX_FORWARD_GEOCODE_BASE_URL = 'https://api.mapbox.com/geocoding/v5/mapbox.places/'; @@ -66,72 +64,69 @@ type PopupInfo = { description: string; }; -// export type GeocoderControlProps = Omit & { -// mapboxAccessToken: string; -// marker?: Omit; -// position: ControlPosition; - -// onResult: (...args: any[]) => void; -// }; - -type MapMarker = { - longitude: number; - latitude: number; -}; - -/** - * Consider integrating later: allows for drawing, circling, making shapes on map - */ -// const drawingManager = new window.google.maps.drawing.DrawingManager({ -// drawingControl: true, -// drawingControlOptions: { -// position: google.maps.ControlPosition.TOP_RIGHT, -// drawingModes: [ -// google.maps.drawing.OverlayType.MARKER, -// // currently we are not supporting the following drawing mode on map, a thought for future development -// google.maps.drawing.OverlayType.CIRCLE, -// google.maps.drawing.OverlayType.POLYLINE, -// ], -// }, -// }); - @observer export class MapBox extends ViewBoxAnnotatableComponent() implements ViewBoxInterface { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(MapBox, fieldKey); } - private _dragRef = React.createRef(); + private _unmounting = false; private _sidebarRef = React.createRef(); private _ref: React.RefObject = React.createRef(); private _mapRef: React.RefObject = React.createRef(); private _disposers: { [key: string]: IReactionDisposer } = {}; - private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean, doc: Opt) => void); constructor(props: FieldViewProps) { super(props); makeObservable(this); } - @observable private _savedAnnotations = new ObservableMap(); - @computed get allSidebarDocs() { - return DocListCast(this.dataDoc[this.SidebarKey]); - } + @observable _featuresFromGeocodeResults: any[] = []; + @observable _savedAnnotations = new ObservableMap(); + @observable _selectedPinOrRoute: Doc | undefined = undefined; // The pin that is selected + @observable _mapReady = false; + @observable _isAnimating: boolean = false; + @observable _routeToAnimate: Doc | undefined = undefined; + @observable _animationPhase: number = 0; + @observable _finishedFlyTo: boolean = false; + @observable _frameId: number | null = null; + @observable _animationUtility: AnimationUtility | null = null; + @observable _settingsOpen: boolean = false; + @observable _mapStyle: string = 'mapbox://styles/mapbox/standard'; + @observable _showTerrain: boolean = true; + @observable _currentPopup: PopupInfo | undefined = undefined; + @observable _isStreetViewAnimation: boolean = false; + @observable _animationSpeed: AnimationSpeed = AnimationSpeed.MEDIUM; + @observable _animationLineColor: string = '#ffff00'; + @observable _temporaryRouteSource: FeatureCollection = { type: 'FeatureCollection', features: [] }; + @observable _dynamicRouteFeature: Feature = { + type: 'Feature', + properties: {}, + geometry: { type: 'LineString', coordinates: [] }, + }; + + @observable path: turf.helpers.Feature = { + type: 'Feature', + geometry: { type: 'LineString', coordinates: [] }, + properties: {}, + }; + // this list contains pushpins and configs - @computed get allAnnotations() { - return DocListCast(this.dataDoc[this.annotationKey]); - } - @computed get allPushpins() { - return this.allAnnotations.filter(anno => anno.type === DocumentType.PUSHPIN); - } - @computed get allRoutes() { - return this.allAnnotations.filter(anno => anno.type === DocumentType.MAPROUTE); + @computed get allAnnotations() { return DocListCast(this.dataDoc[this.annotationKey]); } //prettier-ignore + @computed get allSidebarDocs() { return DocListCast(this.dataDoc[this.SidebarKey]); } //prettier-ignore + @computed get allPushpins() { return this.allAnnotations.filter(anno => anno.type === DocumentType.PUSHPIN); } //prettier-ignore + @computed get allRoutes() { return this.allAnnotations.filter(anno => anno.type === DocumentType.MAPROUTE); } //prettier-ignore + @computed get SidebarShown() { return this.layoutDoc._layout_showSidebar ? true : false; } //prettier-ignore + @computed get sidebarWidthPercent() { return StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%'); } //prettier-ignore + @computed get SidebarKey() { return this.fieldKey + '_sidebar'; } //prettier-ignore + @computed get sidebarColor() { + return StrCast(this.layoutDoc.sidebar_color, StrCast(this.layoutDoc[this._props.fieldKey + '_backgroundColor'], '#e4e4e4')); } @computed get updatedRouteCoordinates(): Feature { - if (this.routeToAnimate?.routeCoordinates) { - const originalCoordinates: Position[] = JSON.parse(StrCast(this.routeToAnimate.routeCoordinates)); + if (this._routeToAnimate?.routeCoordinates) { + const originalCoordinates: Position[] = JSON.parse(StrCast(this._routeToAnimate.routeCoordinates)); // const index = Math.floor(this.animationPhase * originalCoordinates.length); - const index = this.animationPhase * (originalCoordinates.length - 1); // Calculate the fractional index - console.log('Animation phase', this.animationPhase); + const index = this._animationPhase * (originalCoordinates.length - 1); // Calculate the fractional index + console.log('Animation phase', this._animationPhase); const startIndex = Math.floor(index); const endIndex = Math.ceil(index); let feature: Feature; @@ -147,7 +142,7 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem feature = { type: 'Feature', properties: { - routeTitle: StrCast(this.routeToAnimate.title), + routeTitle: StrCast(this._routeToAnimate.title), }, geometry: geometry, }; @@ -158,9 +153,7 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem const fraction = index - startIndex; const interpolator = d3.interpolateArray(startCoord, endCoord); - const interpolatedCoord = interpolator(fraction); - const coordinates = originalCoordinates.slice(0, startIndex + 1).concat([interpolatedCoord]); geometry = { @@ -170,14 +163,14 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem feature = { type: 'Feature', properties: { - routeTitle: StrCast(this.routeToAnimate.title), + routeTitle: StrCast(this._routeToAnimate.title), }, geometry: geometry, }; } autorun(() => { - const animationUtil = this.animationUtility; + const animationUtil = this._animationUtility; const concattedCoordinates = geometry.coordinates.concat(originalCoordinates.slice(endIndex)); const newFeature: Feature = { type: 'Feature', @@ -204,11 +197,7 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem }; } @computed get selectedRouteCoordinates(): Position[] { - let coordinates: Position[] = []; - if (this.routeToAnimate?.routeCoordinates) { - coordinates = JSON.parse(StrCast(this.routeToAnimate.routeCoordinates)); - } - return coordinates; + return !this._routeToAnimate?.routeCoordinates ? [] : JSON.parse(StrCast(this._routeToAnimate.routeCoordinates)); } @computed get allRoutesGeoJson(): FeatureCollection { @@ -233,29 +222,14 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem }; } - @computed get SidebarShown() { - return this.layoutDoc._layout_showSidebar ? true : false; - } - @computed get sidebarWidthPercent() { - return StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%'); - } - @computed get sidebarColor() { - return StrCast(this.layoutDoc.sidebar_color, StrCast(this.layoutDoc[this._props.fieldKey + '_backgroundColor'], '#e4e4e4')); - } - @computed get SidebarKey() { - return this.fieldKey + '_sidebar'; - } - componentDidMount() { this._unmounting = false; this._props.setContentViewBox?.(this); } - _unmounting = false; - componentWillUnmount(): void { + componentWillUnmount() { this._unmounting = true; this.deselectPinOrRoute(); - this._rerenderTimeout && clearTimeout(this._rerenderTimeout); Object.keys(this._disposers).forEach(key => this._disposers[key]?.()); } @@ -269,7 +243,7 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem if (!this.layoutDoc._layout_showSidebar) this.toggleSidebar(); const docs = doc instanceof Doc ? [doc] : doc; docs.forEach(doc => { - let existingPin = this.allPushpins.find(pin => pin.latitude === doc.latitude && pin.longitude === doc.longitude) ?? this.selectedPinOrRoute; + let existingPin = this.allPushpins.find(pin => pin.latitude === doc.latitude && pin.longitude === doc.longitude) ?? this._selectedPinOrRoute; if (doc.latitude !== undefined && doc.longitude !== undefined && !existingPin) { existingPin = this.createPushpin(NumCast(doc.latitude), NumCast(doc.longitude), StrCast(doc.map)); } @@ -370,10 +344,10 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem const sourceAnchorCreator = action(() => { const note = this.getAnchor(true); - if (note && this.selectedPinOrRoute) { - note.latitude = this.selectedPinOrRoute.latitude; - note.longitude = this.selectedPinOrRoute.longitude; - note.map = this.selectedPinOrRoute.map; + if (note && this._selectedPinOrRoute) { + note.latitude = this._selectedPinOrRoute.latitude; + note.longitude = this._selectedPinOrRoute.longitude; + note.map = this._selectedPinOrRoute.map; } return note as Doc; }); @@ -399,10 +373,10 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem const createFunc = undoable( action(() => { const note = this._sidebarRef.current?.anchorMenuClick(this.getAnchor(true), ['latitude', 'longitude', LinkedTo]); - if (note && this.selectedPinOrRoute) { - note.latitude = this.selectedPinOrRoute.latitude; - note.longitude = this.selectedPinOrRoute.longitude; - note.map = this.selectedPinOrRoute.map; + if (note && this._selectedPinOrRoute) { + note.latitude = this._selectedPinOrRoute.latitude; + note.longitude = this._selectedPinOrRoute.longitude; + note.map = this._selectedPinOrRoute.map; } }), 'create note annotation' @@ -423,12 +397,7 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem return false; }; - setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean, doc: Opt) => void) => (this._setPreviewCursor = func); - - addDocumentWrapper = (doc: Doc | Doc[], annotationKey?: string) => this.addDocument(doc, annotationKey); - pointerEvents = () => (this._props.isContentActive() && !MarqueeOptionsMenu.Instance.isShown() ? 'all' : 'none'); - panelWidth = () => this._props.PanelWidth() / (this._props.NativeDimScaling?.() || 1) - this.sidebarWidth(); panelHeight = () => this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1); scrollXf = () => this.ScreenToLocalBoxXf().translate(0, NumCast(this.layoutDoc._layout_scrollTop)); @@ -439,52 +408,9 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick; savedAnnotations = () => this._savedAnnotations; - _bingSearchManager: any; - _bingMap: any; - get MicrosoftMaps() { - return (window as any).Microsoft.Maps; - } - // uses Bing Search to retrieve lat/lng for a location. eg., - // const results = this.geocodeQuery(map.map, 'Philadelphia, PA'); - // to move the map to that location: - // const location = await this.geocodeQuery(this._bingMap, 'Philadelphia, PA'); - // this._bingMap.current.setView({ - // mapTypeId: this.MicrosoftMaps.MapTypeId.aerial, - // center: new this.MicrosoftMaps.Location(loc.latitude, loc.longitude), - // }); - // - bingGeocode = (map: any, query: string) => { - return new Promise<{ latitude: number; longitude: number }>((res, reject) => { - //If search manager is not defined, load the search module. - if (!this._bingSearchManager) { - //Create an instance of the search manager and call the geocodeQuery function again. - this.MicrosoftMaps.loadModule('Microsoft.Maps.Search', () => { - this._bingSearchManager = new this.MicrosoftMaps.Search.SearchManager(map.current); - res(this.bingGeocode(map, query)); - }); - } else { - this._bingSearchManager.geocode({ - where: query, - callback: action((r: any) => res(r.results[0].location)), - errorCallback: (e: any) => reject(), - }); - } - }); - }; - - @observable - bingSearchBarContents: any = this.Document.map; // For Bing Maps: The contents of the Bing search bar (string) - - geoDataRequestOptions = { - entityType: 'PopulatedPlace', - }; - - // The pin that is selected - @observable selectedPinOrRoute: Doc | undefined = undefined; - @action deselectPinOrRoute = () => { - if (this.selectedPinOrRoute) { + if (this._selectedPinOrRoute) { // // Removes filter // Doc.setDocFilter(this.Document, 'latitude', this.selectedPin.latitude, 'remove'); // Doc.setDocFilter(this.Document, 'longitude', this.selectedPin.longitude, 'remove'); @@ -511,79 +437,6 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem } return new Promise>(res => DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv))); }; - /* - * Pushpin onclick - */ - @action - pushpinClicked = (pinDoc: Doc) => { - this.deselectPinOrRoute(); - this.selectedPinOrRoute = pinDoc; - this.bingSearchBarContents = pinDoc.map; - - // Doc.setDocFilter(this.Document, 'latitude', this.selectedPin.latitude, 'match'); - // Doc.setDocFilter(this.Document, 'longitude', this.selectedPin.longitude, 'match'); - Doc.setDocFilter(this.Document, LinkedTo, `mapPin=${Field.toScriptString(this.selectedPinOrRoute)}`, 'check'); - - this.recolorPin(this.selectedPinOrRoute, 'green'); - - MapAnchorMenu.Instance.Delete = this.deleteSelectedPinOrRoute; - MapAnchorMenu.Instance.Center = this.centerOnSelectedPin; - MapAnchorMenu.Instance.OnClick = this.createNoteAnnotation; - MapAnchorMenu.Instance.StartDrag = this.startAnchorDrag; - - const point = this._bingMap.current.tryLocationToPixel(new this.MicrosoftMaps.Location(this.selectedPinOrRoute.latitude, this.selectedPinOrRoute.longitude)); - const x = point.x + (this._props.PanelWidth() - this.sidebarWidth()) / 2; - const y = point.y + this._props.PanelHeight() / 2 + 32; - const cpt = this.ScreenToLocalBoxXf().inverse().transformPoint(x, y); - MapAnchorMenu.Instance.jumpTo(cpt[0], cpt[1], true); - - document.addEventListener('pointerdown', this.tryHideMapAnchorMenu, true); - }; - - /** - * Map OnClick - */ - @action - mapOnClick = (e: { location: { latitude: any; longitude: any } }) => { - this._props.select(false); - this.deselectPinOrRoute(); - }; - /* - * Updates values of layout doc to match the current map - */ - @action - mapRecentered = () => { - if ( - Math.abs(NumCast(this.dataDoc.latitude) - this._bingMap.current.getCenter().latitude) > 1e-7 || // - Math.abs(NumCast(this.dataDoc.longitude) - this._bingMap.current.getCenter().longitude) > 1e-7 - ) { - this.dataDoc.latitude = this._bingMap.current.getCenter().latitude; - this.dataDoc.longitude = this._bingMap.current.getCenter().longitude; - this.dataDoc.map = ''; - this.bingSearchBarContents = ''; - } - this.dataDoc.map_zoom = this._bingMap.current.getZoom(); - }; - /* - * Updates maptype - */ - @action - updateMapType = () => (this.dataDoc.map_type = this._bingMap.current.getMapTypeId()); - - /* - * For Bing Maps - * Called by search button's onClick - * Finds the geocode of the searched contents and sets location to that location - **/ - @action - bingSearch = () => { - return this.bingGeocode(this._bingMap, this.bingSearchBarContents).then(location => { - this.dataDoc.latitude = location.latitude; - this.dataDoc.longitude = location.longitude; - this.dataDoc.map_zoom = this._bingMap.current.getZoom(); - this.dataDoc.map = this.bingSearchBarContents; - }); - }; /* * Returns doc w/ relevant info @@ -592,14 +445,14 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem /// this should use SELECTED pushpin for lat/long if there is a selection, otherwise CENTER const anchor = Docs.Create.ConfigDocument({ title: 'MapAnchor:' + this.Document.title, - text: (StrCast(this.selectedPinOrRoute?.map) || StrCast(this.Document.map) || 'map location') as any, - config_latitude: NumCast((existingPin ?? this.selectedPinOrRoute)?.latitude ?? this.dataDoc.latitude), - config_longitude: NumCast((existingPin ?? this.selectedPinOrRoute)?.longitude ?? this.dataDoc.longitude), + text: (StrCast(this._selectedPinOrRoute?.map) || StrCast(this.Document.map) || 'map location') as any, + config_latitude: NumCast((existingPin ?? this._selectedPinOrRoute)?.latitude ?? this.dataDoc.latitude), + config_longitude: NumCast((existingPin ?? this._selectedPinOrRoute)?.longitude ?? this.dataDoc.longitude), config_map_zoom: NumCast(this.dataDoc.map_zoom), // config_map_type: StrCast(this.dataDoc.map_type), - config_map: StrCast((existingPin ?? this.selectedPinOrRoute)?.map) || StrCast(this.dataDoc.map), + config_map: StrCast((existingPin ?? this._selectedPinOrRoute)?.map) || StrCast(this.dataDoc.map), layout_unrendered: true, - mapPin: existingPin ?? this.selectedPinOrRoute, + mapPin: existingPin ?? this._selectedPinOrRoute, annotationOn: this.Document, }); if (anchor) { @@ -613,25 +466,6 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem map_docToPinMap = new Map(); map_pinHighlighted = new Map(); - /* - * Input: pin doc - * Adds MicrosoftMaps Pushpin to the map (render) - */ - @action - addPushpin = (pin: Doc) => { - const pushPin = pin.infoWindowOpen - ? new this.MicrosoftMaps.Pushpin(new this.MicrosoftMaps.Location(pin.latitude, pin.longitude), {}) - : new this.MicrosoftMaps.Pushpin( - new this.MicrosoftMaps.Location(pin.latitude, pin.longitude) - // {icon: 'http://icons.iconarchive.com/icons/icons-land/vista-map-markers/24/Map-Marker-Marker-Outside-Chartreuse-icon.png'} - ); - - this._bingMap.current.entities.push(pushPin); - - this.MicrosoftMaps.Events.addHandler(pushPin, 'click', (e: any) => this.pushpinClicked(pin)); - // this.MicrosoftMaps.Events.addHandler(pushPin, 'dblclick', (e: any) => this.pushpinDblClicked(pushPin, pin)); - this.map_docToPinMap.set(pin, pushPin); - }; /* * Input: pin doc @@ -640,27 +474,16 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem @action removePushpinOrRoute = (pinOrRouteDoc: Doc) => this.removeMapDocument(pinOrRouteDoc, this.annotationKey); - /* - * Removes pushpin from map render - */ - deletePushpin = (pinDoc: Doc) => { - if (!this._unmounting) { - this._bingMap.current.entities.remove(this.map_docToPinMap.get(pinDoc)); - } - this.map_docToPinMap.delete(pinDoc); - this.selectedPinOrRoute = undefined; - }; - @action deleteSelectedPinOrRoute = undoable(() => { console.log('deleting'); - if (this.selectedPinOrRoute) { + if (this._selectedPinOrRoute) { // Removes filter - Doc.setDocFilter(this.Document, 'latitude', this.selectedPinOrRoute.latitude, 'remove'); - Doc.setDocFilter(this.Document, 'longitude', this.selectedPinOrRoute.longitude, 'remove'); - Doc.setDocFilter(this.Document, LinkedTo, `mapPin=${Field.toScriptString(DocCast(this.selectedPinOrRoute))}`, 'remove'); + Doc.setDocFilter(this.Document, 'latitude', this._selectedPinOrRoute.latitude, 'remove'); + Doc.setDocFilter(this.Document, 'longitude', this._selectedPinOrRoute.longitude, 'remove'); + Doc.setDocFilter(this.Document, LinkedTo, `mapPin=${Field.toScriptString(DocCast(this._selectedPinOrRoute))}`, 'remove'); - this.removePushpinOrRoute(this.selectedPinOrRoute); + this.removePushpinOrRoute(this._selectedPinOrRoute); } MapAnchorMenu.Instance.fadeOut(true); document.removeEventListener('pointerdown', this.tryHideMapAnchorMenu, true); @@ -677,7 +500,7 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem e.preventDefault(); MapAnchorMenu.Instance.fadeOut(true); runInAction(() => { - this.temporaryRouteSource = { + this._temporaryRouteSource = { type: 'FeatureCollection', features: [], }; @@ -688,9 +511,9 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem @action centerOnSelectedPin = () => { - if (this.selectedPinOrRoute) { + if (this._selectedPinOrRoute) { this._mapRef.current?.flyTo({ - center: [NumCast(this.selectedPinOrRoute.longitude), NumCast(this.selectedPinOrRoute.latitude)], + center: [NumCast(this._selectedPinOrRoute.longitude), NumCast(this._selectedPinOrRoute.latitude)], }); } // if (this.selectedPin) { @@ -703,33 +526,6 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem document.removeEventListener('pointerdown', this.tryHideMapAnchorMenu); }; - /** - * View options for bing maps - */ - bingViewOptions = { - // center: { latitude: this.dataDoc.latitude ?? defaultCenter.lat, longitude: this.dataDoc.longitude ?? defaultCenter.lng }, - zoom: this.dataDoc.latitude ?? 10, - mapTypeId: 'grayscale', - }; - - /** - * Map options - */ - bingMapOptions = { - navigationBarMode: 'square', - backgroundColor: '#f1f3f4', - enableInertia: true, - supportedMapTypes: ['grayscale', 'canvasLight'], - disableMapTypeSelectorMouseOver: true, - // showScalebar:true - // disableRoadView:true, - // disableBirdseye:true - streetsideOptions: { - showProblemReporting: false, - showCurrentAddress: false, - }, - }; - recolorPin = (pin: Doc, color?: string) => { // this._bingMap.current.entities.remove(this.map_docToPinMap.get(pin)); // this.map_docToPinMap.delete(pin); @@ -739,109 +535,6 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem // this.map_docToPinMap.set(pin, newpin); }; - /* - * Called when BingMap is first rendered - * Initializes starting values - */ - @observable _mapReady = false; - @action - bingMapReady = (map: any) => { - this._mapReady = true; - this._bingMap = map.map; - if (!this._bingMap.current) { - alert('NO Map!?'); - } - this.MicrosoftMaps.Events.addHandler(this._bingMap.current, 'click', this.mapOnClick); - this.MicrosoftMaps.Events.addHandler(this._bingMap.current, 'viewchangeend', undoable(this.mapRecentered, 'Map Layout Change')); - this.MicrosoftMaps.Events.addHandler(this._bingMap.current, 'maptypechanged', undoable(this.updateMapType, 'Map ViewType Change')); - - this._disposers.mapLocation = reaction( - () => this.Document.map, - mapLoc => (this.bingSearchBarContents = mapLoc), - { fireImmediately: true } - ); - this._disposers.highlight = reaction( - () => this.allAnnotations.map(doc => doc[Highlight]), - () => { - const allConfigPins = this.allAnnotations.map(doc => ({ doc, pushpin: DocCast(doc.mapPin) })).filter(pair => pair.pushpin); - allConfigPins.forEach(({ doc, pushpin }) => { - if (!pushpin[Highlight] && this.map_pinHighlighted.get(pushpin)) { - this.recolorPin(pushpin); - this.map_pinHighlighted.delete(pushpin); - } - }); - allConfigPins.forEach(({ doc, pushpin }) => { - if (doc[Highlight] && !this.map_pinHighlighted.get(pushpin)) { - this.recolorPin(pushpin, 'orange'); - this.map_pinHighlighted.set(pushpin, true); - } - }); - }, - { fireImmediately: true } - ); - - this._disposers.location = reaction( - () => ({ lat: this.Document.latitude, lng: this.Document.longitude, zoom: this.Document.map_zoom, mapType: this.Document.map_type }), - locationObject => { - // if (this._bingMap.current) - try { - locationObject?.zoom && - this._bingMap.current?.setView({ - mapTypeId: locationObject.mapType, - zoom: locationObject.zoom, - center: new this.MicrosoftMaps.Location(locationObject.lat, locationObject.lng), - }); - } catch (e) { - console.log(e); - } - }, - { fireImmediately: true } - ); - }; - - dragToggle = (e: React.PointerEvent) => { - let dragClone: HTMLDivElement | undefined; - - setupMoveUpEvents( - e, - e, - e => { - // move event - if (!dragClone) { - dragClone = this._dragRef.current?.cloneNode(true) as HTMLDivElement; // copy draggable pin - dragClone.style.position = 'absolute'; - dragClone.style.zIndex = '10000'; - DragManager.Root().appendChild(dragClone); // add clone to root - } - dragClone.style.transform = `translate(${e.clientX - 15}px, ${e.clientY - 15}px)`; - return false; - }, - e => { - // up event - if (!dragClone) return; - DragManager.Root().removeChild(dragClone); - let target = document.elementFromPoint(e.x, e.y); // element for specified x and y coordinates - while (target) { - if (target === this._ref.current) { - const cpt = this.ScreenToLocalBoxXf().transformPoint(e.clientX, e.clientY); - const x = cpt[0] - (this._props.PanelWidth() - this.sidebarWidth()) / 2; - const y = cpt[1] - 20 /* height of search bar */ - this._props.PanelHeight() / 2; - const location = this._bingMap.current.tryPixelToLocation(new this.MicrosoftMaps.Point(x, y)); - this.createPushpin(location.latitude, location.longitude); - break; - } - target = target.parentElement; - } - }, - e => { - const createPin = () => this.createPushpin(this.Document.latitude, this.Document.longitude, this.Document.map); - if (this.bingSearchBarContents) { - this.bingSearch().then(createPin); - } else createPin(); - } - ); - }; - // incrementer: number = 0; /* * Creates Pushpin doc and adds it to the list of annotations @@ -880,7 +573,7 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem if (createPinForDestination) { this.createPushpin(destination.center[1], destination.center[0], destination.place_name); } - this.temporaryRouteSource = { + this._temporaryRouteSource = { type: 'FeatureCollection', features: [], }; @@ -890,10 +583,14 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem // TODO: Display error that can't create route to same location }, 'createmaproute'); - searchbarKeyDown = (e: any) => e.key === 'Enter' && this.bingSearch(); - - @observable - featuresFromGeocodeResults: any[] = []; + @action + searchbarKeyDown = (e: any) => { + if (e.key === 'Enter' && this._featuresFromGeocodeResults) { + const center = this._featuresFromGeocodeResults[0]?.center; + this._featuresFromGeocodeResults = []; + setTimeout(() => center && this._mapRef.current?.flyTo({ center })); + } + }; @action addMarkerForFeature = (feature: any) => { @@ -910,7 +607,7 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem center: feature.center, }); } - this.featuresFromGeocodeResults = []; + this._featuresFromGeocodeResults = []; } else { // TODO: handle error } @@ -922,11 +619,11 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem */ handleSearchChange = async (searchText: string) => { const features = await MapboxApiUtility.forwardGeocodeForFeatures(searchText); - if (features && !this.isAnimating) { + if (features && !this._isAnimating) { runInAction(() => { - this.settingsOpen = false; - this.featuresFromGeocodeResults = features; - this.routeToAnimate = undefined; + this._settingsOpen = false; + this._featuresFromGeocodeResults = features; + this._routeToAnimate = undefined; }); } // try { @@ -946,8 +643,8 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem @action handleMapClick = (e: MapLayerMouseEvent) => { - this.featuresFromGeocodeResults = []; - this.settingsOpen = false; + this._featuresFromGeocodeResults = []; + this._settingsOpen = false; if (this._mapRef.current) { const features = this._mapRef.current.queryRenderedFeatures(e.point, { layers: ['map-routes-layer'], @@ -960,8 +657,8 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem const routeDoc: Doc | undefined = this.allRoutes.find(routeDoc => routeDoc.title === routeTitle); this.deselectPinOrRoute(); // TODO: Also deselect route if selected if (routeDoc) { - this.selectedPinOrRoute = routeDoc; - Doc.setDocFilter(this.Document, LinkedTo, `mapRoute=${Field.toScriptString(this.selectedPinOrRoute)}`, 'check'); + this._selectedPinOrRoute = routeDoc; + Doc.setDocFilter(this.Document, LinkedTo, `mapRoute=${Field.toScriptString(this._selectedPinOrRoute)}`, 'check'); // TODO: Recolor route @@ -1008,7 +705,7 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem const features = await MapboxApiUtility.reverseGeocodeForFeatures(longitude, latitude); if (features) { runInAction(() => { - this.featuresFromGeocodeResults = features; + this._featuresFromGeocodeResults = features; }); } @@ -1028,21 +725,18 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem // } }; - @observable - currentPopup: PopupInfo | undefined = undefined; - @action handleMarkerClick = (e: MarkerEvent, pinDoc: Doc) => { - this.featuresFromGeocodeResults = []; + this._featuresFromGeocodeResults = []; this.deselectPinOrRoute(); // TODO: check this method - this.selectedPinOrRoute = pinDoc; + this._selectedPinOrRoute = pinDoc; // this.bingSearchBarContents = pinDoc.map; // Doc.setDocFilter(this.Document, 'latitude', this.selectedPin.latitude, 'match'); // Doc.setDocFilter(this.Document, 'longitude', this.selectedPin.longitude, 'match'); - Doc.setDocFilter(this.Document, LinkedTo, `mapPin=${Field.toScriptString(this.selectedPinOrRoute)}`, 'check'); + Doc.setDocFilter(this.Document, LinkedTo, `mapPin=${Field.toScriptString(this._selectedPinOrRoute)}`, 'check'); - this.recolorPin(this.selectedPinOrRoute, 'green'); // TODO: check this method + this.recolorPin(this._selectedPinOrRoute, 'green'); // TODO: check this method MapAnchorMenu.Instance.Delete = this.deleteSelectedPinOrRoute; MapAnchorMenu.Instance.Center = this.centerOnSelectedPin; @@ -1072,12 +766,6 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem // }) }; - @observable - temporaryRouteSource: FeatureCollection = { - type: 'FeatureCollection', - features: [], - }; - @action displayRoute = (routeInfoMap: Record | undefined, type: TransportationType) => { if (routeInfoMap) { @@ -1096,41 +784,23 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem }; // TODO: Create pin for destination // TODO: Fly to point where full route will be shown - this.temporaryRouteSource = newTempRouteSource; + this._temporaryRouteSource = newTempRouteSource; } }; - @observable - isAnimating: boolean = false; - - @observable - routeToAnimate: Doc | undefined = undefined; - - @observable - animationPhase: number = 0; - - @observable - finishedFlyTo: boolean = false; - @action setAnimationPhase = (newValue: number) => { - this.animationPhase = newValue; + this._animationPhase = newValue; }; - @observable - frameId: number | null = null; - @action setFrameId = (frameId: number) => { - this.frameId = frameId; + this._frameId = frameId; }; - @observable - animationUtility: AnimationUtility | null = null; - @action setAnimationUtility = (util: AnimationUtility) => { - this.animationUtility = util; + this._animationUtility = util; }; @action @@ -1138,8 +808,8 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem if (routeDoc) { MapAnchorMenu.Instance.fadeOut(true); document.removeEventListener('pointerdown', this.tryHideMapAnchorMenu, true); - this.featuresFromGeocodeResults = []; - this.routeToAnimate = routeDoc; + this._featuresFromGeocodeResults = []; + this._routeToAnimate = routeDoc; } }; @@ -1161,29 +831,20 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem @computed get preAnimationViewState() { - if (!this.isAnimating) { + if (!this._isAnimating) { return this.mapboxMapViewState; } } - @observable - isStreetViewAnimation: boolean = false; - - @observable - animationSpeed: AnimationSpeed = AnimationSpeed.MEDIUM; - - @observable - animationLineColor: string = '#ffff00'; - @action setAnimationLineColor = (color: ColorResult) => { - this.animationLineColor = color.hex; + this._animationLineColor = color.hex; }; @action updateAnimationSpeed = () => { let newAnimationSpeed: AnimationSpeed; - switch (this.animationSpeed) { + switch (this._animationSpeed) { case AnimationSpeed.SLOW: newAnimationSpeed = AnimationSpeed.MEDIUM; break; @@ -1197,63 +858,33 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem newAnimationSpeed = AnimationSpeed.MEDIUM; break; } - this.animationSpeed = newAnimationSpeed; - if (this.animationUtility) { - this.animationUtility.updateAnimationSpeed(newAnimationSpeed); + this._animationSpeed = newAnimationSpeed; + if (this._animationUtility) { + this._animationUtility.updateAnimationSpeed(newAnimationSpeed); } }; @computed get animationSpeedTooltipText(): string { - switch (this.animationSpeed) { - case AnimationSpeed.SLOW: - return '1x speed'; - case AnimationSpeed.MEDIUM: - return '2x speed'; - case AnimationSpeed.FAST: - return '3x speed'; - default: - return '2x speed'; - } + switch (this._animationSpeed) { + case AnimationSpeed.SLOW: return '1x speed'; + case AnimationSpeed.MEDIUM: return '2x speed'; + case AnimationSpeed.FAST: return '3x speed'; + default: return '2x speed'; + } // prettier-ignore } @computed get animationSpeedIcon(): JSX.Element { - switch (this.animationSpeed) { - case AnimationSpeed.SLOW: - return slowSpeedIcon; - case AnimationSpeed.MEDIUM: - return mediumSpeedIcon; - case AnimationSpeed.FAST: - return fastSpeedIcon; - default: - return mediumSpeedIcon; - } + switch (this._animationSpeed) { + case AnimationSpeed.SLOW: return slowSpeedIcon; + case AnimationSpeed.MEDIUM: return mediumSpeedIcon; + case AnimationSpeed.FAST: return fastSpeedIcon; + default: return mediumSpeedIcon; + } // prettier-ignore } @action toggleIsStreetViewAnimation = () => { - const newVal = !this.isStreetViewAnimation; - this.isStreetViewAnimation = newVal; - if (this.animationUtility) { - this.animationUtility.updateIsStreetViewAnimation(newVal); - } - }; - - @observable - dynamicRouteFeature: Feature = { - type: 'Feature', - properties: {}, - geometry: { - type: 'LineString', - coordinates: [], - }, - }; - - @observable - path: turf.helpers.Feature = { - type: 'Feature', - geometry: { - type: 'LineString', - coordinates: [], - }, - properties: {}, + const newVal = !this._isStreetViewAnimation; + this._isStreetViewAnimation = newVal; + this._animationUtility?.updateIsStreetViewAnimation(newVal); }; getFeatureFromRouteDoc = (routeDoc: Doc): Feature => { @@ -1272,19 +903,19 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem @action playAnimation = (status: AnimationStatus) => { - if (!this._mapRef.current || !this.routeToAnimate) { + if (!this._mapRef.current || !this._routeToAnimate) { return; } - this.animationPhase = status === AnimationStatus.RESUME ? this.animationPhase : 0; - this.frameId = AnimationStatus.RESUME ? this.frameId : null; - this.finishedFlyTo = AnimationStatus.RESUME ? this.finishedFlyTo : false; + this._animationPhase = status === AnimationStatus.RESUME ? this._animationPhase : 0; + this._frameId = AnimationStatus.RESUME ? this._frameId : null; + this._finishedFlyTo = AnimationStatus.RESUME ? this._finishedFlyTo : false; const path = turf.lineString(this.selectedRouteCoordinates); - this.settingsOpen = false; + this._settingsOpen = false; this.path = path; - this.isAnimating = true; + this._isAnimating = true; runInAction(() => { return new Promise(async resolve => { @@ -1293,18 +924,11 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem lat: this.selectedRouteCoordinates[0][1], }; - const animationUtil = new AnimationUtility(targetLngLat, this.selectedRouteCoordinates, this.isStreetViewAnimation, this.animationSpeed, this.showTerrain, this._mapRef.current); - runInAction(() => { - this.setAnimationUtility(animationUtil); - }); - - const updateFrameId = (newFrameId: number) => { - this.setFrameId(newFrameId); - }; + const animationUtil = new AnimationUtility(targetLngLat, this.selectedRouteCoordinates, this._isStreetViewAnimation, this._animationSpeed, this._showTerrain, this._mapRef.current); + runInAction(() => this.setAnimationUtility(animationUtil)); - const updateAnimationPhase = (newAnimationPhase: number) => { - this.setAnimationPhase(newAnimationPhase); - }; + const updateFrameId = (newFrameId: number) => this.setFrameId(newFrameId); + const updateAnimationPhase = (newAnimationPhase: number) => this.setAnimationPhase(newAnimationPhase); if (status !== AnimationStatus.RESUME) { const result = await animationUtil.flyInAndRotate({ @@ -1324,9 +948,7 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem console.log('Altitude: ', result.altitude); } - runInAction(() => { - this.finishedFlyTo = true; - }); + runInAction(() => (this._finishedFlyTo = true)); // follow the path while slowly rotating the camera, passing in the camera bearing and altitude from the previous animation await animationUtil.animatePath({ @@ -1335,7 +957,7 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem // startBearing: -20, // startAltitude: this.isStreetViewAnimation ? 80 : 12000, // pitch: this.isStreetViewAnimation ? 80: 50, - currentAnimationPhase: this.animationPhase, + currentAnimationPhase: this._animationPhase, updateAnimationPhase, updateFrameId, }); @@ -1353,7 +975,7 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem }); setTimeout(() => { - this.isStreetViewAnimation = false; + this._isStreetViewAnimation = false; resolve(); }, 10000); }); @@ -1362,27 +984,27 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem @action pauseAnimation = () => { - if (this.frameId && this.animationPhase > 0) { - window.cancelAnimationFrame(this.frameId); - this.frameId = null; - this.isAnimating = false; + if (this._frameId && this._animationPhase > 0) { + window.cancelAnimationFrame(this._frameId); + this._frameId = null; + this._isAnimating = false; } }; @action stopAnimation = (close: boolean) => { - if (this.frameId) { - window.cancelAnimationFrame(this.frameId); + if (this._frameId) { + window.cancelAnimationFrame(this._frameId); } - this.animationPhase = 0; - this.frameId = null; - this.finishedFlyTo = false; - this.isAnimating = false; + this._animationPhase = 0; + this._frameId = null; + this._finishedFlyTo = false; + this._isAnimating = false; if (close) { - this.animationSpeed = AnimationSpeed.MEDIUM; - this.isStreetViewAnimation = false; - this.routeToAnimate = undefined; - this.animationUtility = null; + this._animationSpeed = AnimationSpeed.MEDIUM; + this._isStreetViewAnimation = false; + this._routeToAnimate = undefined; + this._animationUtility = null; } }; @@ -1390,21 +1012,21 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem return ( <> { - if (this.isAnimating && this.finishedFlyTo) { + if (this._isAnimating && this._finishedFlyTo) { this.pauseAnimation(); - } else if (this.animationPhase > 0) { + } else if (this._animationPhase > 0) { this.playAnimation(AnimationStatus.RESUME); // Resume from the current phase } else { this.playAnimation(AnimationStatus.START); // Play from the beginning } }} - icon={this.isAnimating && this.finishedFlyTo ? : } + icon={this._isAnimating && this._finishedFlyTo ? : } color="black" size={Size.MEDIUM} /> - {this.isAnimating && this.finishedFlyTo && ( + {this._isAnimating && this._finishedFlyTo && ( { @@ -1420,7 +1042,7 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem <>
      |
      - } /> + } />
      |
      |
      @@ -1436,26 +1058,17 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem @action hideRoute = () => { - this.temporaryRouteSource = { + this._temporaryRouteSource = { type: 'FeatureCollection', features: [], }; }; - @observable - settingsOpen: boolean = false; - - @observable - mapStyle: string = 'mapbox://styles/mapbox/standard'; - - @observable - showTerrain: boolean = true; - @action toggleSettings = () => { - if (!this.isAnimating && this.animationPhase == 0) { - this.featuresFromGeocodeResults = []; - this.settingsOpen = !this.settingsOpen; + if (!this._isAnimating && this._animationPhase == 0) { + this._featuresFromGeocodeResults = []; + this._settingsOpen = !this._settingsOpen; } }; @@ -1500,14 +1113,10 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem @action onStepZoomChange = (increment: boolean) => { if (this._mapRef.current) { - let newZoom: number; - if (increment) { - console.log('inc'); - newZoom = Math.min(16, this.mapboxMapViewState.zoom + 1); - } else { - console.log('dec'); - newZoom = Math.max(0, this.mapboxMapViewState.zoom - 1); - } + const newZoom = increment // + ? Math.min(16, this.mapboxMapViewState.zoom + 1) + : Math.max(0, this.mapboxMapViewState.zoom - 1); + this._mapRef.current.setZoom(newZoom); this.dataDoc.map_zoom = newZoom; } @@ -1523,7 +1132,7 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem }; @action - toggleShowTerrain = () => (this.showTerrain = !this.showTerrain); + toggleShowTerrain = () => (this._showTerrain = !this._showTerrain); getMarkerIcon = (pinDoc: Doc): JSX.Element | null => { const markerType = StrCast(pinDoc.markerType); @@ -1532,25 +1141,8 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem return MarkerIcons.getFontAwesomeIcon(markerType, '2x', markerColor) ?? null; }; - static _firstRender = true; - static _rerenderDelay = 500; - _rerenderTimeout: any; + _textRef = React.createRef(); render() { - // bcz: no idea what's going on here, but bings maps have some kind of bug - // such that we need to delay rendering a second map on startup until the first map is rendered. - this.Document[DocCss]; - if (MapBox._rerenderDelay) { - // prettier-ignore - this._rerenderTimeout = this._rerenderTimeout ?? - setTimeout(action(() => { - if ((window as any).Microsoft?.Maps?.Internal._WorkDispatcher) { - MapBox._rerenderDelay = 0; - } - this._rerenderTimeout = undefined; - this.Document[DocCss] = this.Document[DocCss] + 1; - }), MapBox._rerenderDelay); - return null; - } const scale = this._props.NativeDimScaling?.() || 1; const parscale = scale === 1 ? 1 : this.ScreenToLocalBoxXf().Scale ?? 1; @@ -1560,20 +1152,18 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem
      e.stopPropagation()} - onPointerDown={async e => { - e.button === 0 && !e.ctrlKey && e.stopPropagation(); - }} + onPointerDown={e => e.button === 0 && !e.ctrlKey && e.stopPropagation()} style={{ transformOrigin: 'top left', transform: `scale(${scale})`, width: `calc(100% - ${this.sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}>
      {renderAnnotations(this.transparentFilter)}
      {renderAnnotations(this.opaqueFilter)} {SnappingManager.IsDragging ? null : renderAnnotations()} - {!this.routeToAnimate && ( + {!this._routeToAnimate && (
      - this.handleSearchChange(e.target.value)} /> + this.handleSearchChange(e.target.value)} /> } type={Type.TERT} onClick={e => this.toggleSettings()} />
      )} - {this.settingsOpen && !this.routeToAnimate && ( + {this._settingsOpen && !this._routeToAnimate && (
      Map Style:
      @@ -1605,21 +1195,21 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem
      Show terrain:
      - +
      )} - {this.routeToAnimate && ( + {this._routeToAnimate && (
      -
      {StrCast(this.routeToAnimate.title)}
      +
      {StrCast(this._routeToAnimate.title)}
      {this.getRouteAnimationOptions()}
      )} - {this.featuresFromGeocodeResults.length > 0 && ( + {this._featuresFromGeocodeResults.length > 0 && (
      - + <>

      Choose a location for your pin:

      - {this.featuresFromGeocodeResults + {this._featuresFromGeocodeResults .filter(feature => feature.place_name) .map((feature, idx) => (
      () implem
      {feature.place_name}
      ))} -
      +
      )} () implem width: NumCast(this.layoutDoc._width) * parscale, height: NumCast(this.layoutDoc._height) * parscale, }} - initialViewState={this.isAnimating ? undefined : this.mapboxMapViewState} + initialViewState={this._isAnimating ? undefined : this.mapboxMapViewState} onZoom={this.onMapZoom} onMove={this.onMapMove} onClick={this.handleMapClick} onDblClick={this.handleMapDblClick} - terrain={this.showTerrain ? { source: 'mapbox-dem', exaggeration: 2.0 } : undefined}> + terrain={this._showTerrain ? { source: 'mapbox-dem', exaggeration: 2.0 } : undefined}> - + - {!this.isAnimating && this.animationPhase == 0 && } - {this.routeToAnimate && (this.isAnimating || this.animationPhase > 0) && ( + {!this._isAnimating && this._animationPhase == 0 && ( + + )} + {this._routeToAnimate && (this._isAnimating || this._animationPhase > 0) && ( <> - {!this.isStreetViewAnimation && ( + {!this._isStreetViewAnimation && ( <> () implem type="line" source="animated-route" paint={{ - 'line-color': this.animationLineColor, + 'line-color': this._animationLineColor, 'line-width': 5, }} /> @@ -1722,10 +1314,9 @@ export class MapBox extends ViewBoxAnnotatableComponent() implem )} <> - {!this.isAnimating && - this.animationPhase == 0 && - this.allPushpins - // .filter(anno => !anno.layout_unrendered) + {!this._isAnimating && + this._animationPhase == 0 && + this.allPushpins // .filter(anno => !anno.layout_unrendered) .map((pushpin, idx) => ( ) => this.handleMarkerClick(e, pushpin)}> {this.getMarkerIcon(pushpin)} diff --git a/src/client/views/nodes/MapBox/MapPushpinBox.tsx b/src/client/views/nodes/MapBox/MapPushpinBox.tsx index fc5b4dd18..8ebc90157 100644 --- a/src/client/views/nodes/MapBox/MapPushpinBox.tsx +++ b/src/client/views/nodes/MapBox/MapPushpinBox.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { ViewBoxBaseComponent } from '../../DocComponent'; import { FieldView, FieldViewProps } from '../FieldView'; -import { MapBox } from './MapBox'; +import { MapBoxContainer } from '../MapboxMapBox/MapboxContainer'; /** * Map Pushpin doc class @@ -18,7 +18,7 @@ export class MapPushpinBox extends ViewBoxBaseComponent() { } get mapBoxView() { - return this.DocumentView?.()?.containerViewPath?.().lastElement()?.ComponentView as MapBox; + return this.DocumentView?.()?.containerViewPath?.().lastElement()?.ComponentView as MapBoxContainer; } get mapBox() { return this.DocumentView?.().containerViewPath?.().lastElement()?.Document; diff --git a/src/client/views/nodes/RecordingBox/RecordingView.scss b/src/client/views/nodes/RecordingBox/RecordingView.scss index 287cccd8f..f2d5a980d 100644 --- a/src/client/views/nodes/RecordingBox/RecordingView.scss +++ b/src/client/views/nodes/RecordingBox/RecordingView.scss @@ -1,208 +1,200 @@ video { - // flex: 100%; - width: 100%; - // min-height: 400px; - //height: auto; - height: 100%; - //display: block; - object-fit: cover; - background-color: black; -} - -button { - margin: 0 .5rem + // flex: 100%; + width: 100%; + // min-height: 400px; + //height: auto; + height: 100%; + //display: block; + object-fit: cover; + background-color: black; } .recording-container { - height: 100%; - width: 100%; - // display: flex; - pointer-events: all; - background-color: black; + height: 100%; + width: 100%; + // display: flex; + pointer-events: all; + background-color: black; + button { + margin: 0 0.5rem; + } } .video-wrapper { - // max-width: 600px; - // max-width: 700px; - // position: relative; - display: flex; - justify-content: center; - // overflow: hidden; - border-radius: 10px; - margin: 0; + // max-width: 600px; + // max-width: 700px; + // position: relative; + display: flex; + justify-content: center; + // overflow: hidden; + border-radius: 10px; + margin: 0; } .video-wrapper:hover .controls { - bottom: 34.5px; - transform: translateY(0%); - opacity: 100%; + bottom: 34.5px; + transform: translateY(0%); + opacity: 100%; } .controls { - display: flex; - align-items: center; - justify-content: center; - position: absolute; - width: 100%; - flex-wrap: wrap; - background: rgba(255, 255, 255, 0.25); - box-shadow: 0 8px 32px 0 rgba(255, 255, 255, 0.1); - // backdrop-filter: blur(4px); - border-radius: 10px; - border: 1px solid rgba(255, 255, 255, 0.18); - transition: all 0.3s ease-in-out; - bottom: 34.5px; - height: 60px; + display: flex; + align-items: center; + justify-content: center; + position: absolute; + width: 100%; + flex-wrap: wrap; + background: rgba(255, 255, 255, 0.25); + box-shadow: 0 8px 32px 0 rgba(255, 255, 255, 0.1); + // backdrop-filter: blur(4px); + border-radius: 10px; + border: 1px solid rgba(255, 255, 255, 0.18); + transition: all 0.3s ease-in-out; + bottom: 34.5px; + height: 60px; } .controls:active { - bottom: 40px; + bottom: 40px; } .actions button { - background: none; - border: none; - outline: none; - cursor: pointer; + background: none; + border: none; + outline: none; + cursor: pointer; } .actions button i { - background-color: none; - color: white; - font-size: 30px; + background-color: none; + color: white; + font-size: 30px; } - .velocity { - appearance: none; - background: none; - color: white; - outline: none; - border: none; - text-align: center; - font-size: 16px; + appearance: none; + background: none; + color: white; + outline: none; + border: none; + text-align: center; + font-size: 16px; } .mute-btn { - background: none; - border: none; - outline: none; - cursor: pointer; + background: none; + border: none; + outline: none; + cursor: pointer; } .mute-btn i { - background-color: none; - color: white; - font-size: 20px; + background-color: none; + color: white; + font-size: 20px; } .recording-sign { - height: 20px; - width: auto; - display: flex; - flex-direction: row; - position: absolute; - top: 10px; - right: 15px; - align-items: center; - justify-content: center; - - .timer { - font-size: 15px; - color: white; - margin: 0; - } - - .dot { - height: 15px; - width: 15px; - margin: 5px; - background-color: red; - border-radius: 50%; - display: inline-block; - } + height: 20px; + width: auto; + display: flex; + flex-direction: row; + position: absolute; + top: 10px; + right: 15px; + align-items: center; + justify-content: center; + + .timer { + font-size: 15px; + color: white; + margin: 0; + } + + .dot { + height: 15px; + width: 15px; + margin: 5px; + background-color: red; + border-radius: 50%; + display: inline-block; + } } .controls-inner-container { - display: flex; - flex-direction: row; - position: relative; - width: 100%; - align-items: center; - justify-content: center; + display: flex; + flex-direction: row; + position: relative; + width: 100%; + align-items: center; + justify-content: center; } .record-button-wrapper { - width: 35px; - height: 35px; - font-size: 0; - background-color: grey; - border: 0px; - border-radius: 35px; - margin: 10px; - display: flex; - justify-content: center; - - .record-button { - background-color: red; - border: 0px; - border-radius: 50%; - height: 80%; - width: 80%; - align-self: center; - margin: 0; - - &:hover { - height: 85%; - width: 85%; - } - } - - .stop-button { - background-color: red; - border: 0px; - border-radius: 10%; - height: 70%; - width: 70%; - align-self: center; - margin: 0; - - - // &:hover { - // width: 40px; - // height: 40px - // } - } - + width: 35px; + height: 35px; + font-size: 0; + background-color: grey; + border: 0px; + border-radius: 35px; + margin: 10px; + display: flex; + justify-content: center; + + .record-button { + background-color: red; + border: 0px; + border-radius: 50%; + height: 80%; + width: 80%; + align-self: center; + margin: 0; + + &:hover { + height: 85%; + width: 85%; + } + } + + .stop-button { + background-color: red; + border: 0px; + border-radius: 10%; + height: 70%; + width: 70%; + align-self: center; + margin: 0; + + // &:hover { + // width: 40px; + // height: 40px + // } + } } .options-wrapper { - height: 100%; - display: flex; - flex-direction: row; - align-content: center; - position: relative; - top: 0; - bottom: 0; - - &.video-edit-wrapper { - - // right: 50% - 15; - - .track-screen { - font-weight: 200; - } - - } - - &.track-screen-wrapper { - - // right: 50% - 30; - - .track-screen { - font-weight: 200; - color: aqua; - } - - } -} \ No newline at end of file + height: 100%; + display: flex; + flex-direction: row; + align-content: center; + position: relative; + top: 0; + bottom: 0; + + &.video-edit-wrapper { + // right: 50% - 15; + + .track-screen { + font-weight: 200; + } + } + + &.track-screen-wrapper { + // right: 50% - 30; + + .track-screen { + font-weight: 200; + color: aqua; + } + } +} diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index 8802a032f..cdfeebe66 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -22,7 +22,7 @@ import { OpenWhere } from '../DocumentView'; import './DashFieldView.scss'; import { FormattedTextBox } from './FormattedTextBox'; import { DocData } from '../../../../fields/DocSymbols'; -import { NodeSelection, TextSelection } from 'prosemirror-state'; +import { NodeSelection } from 'prosemirror-state'; export class DashFieldView { dom: HTMLDivElement; // container for label and value @@ -60,7 +60,7 @@ export class DashFieldView { return; } } - tBox.setFocus(state.selection.to + 1); + tBox.setFocus(state.selection.to); } } }; @@ -84,6 +84,7 @@ export class DashFieldView { width={node.attrs.width} height={node.attrs.height} hideKey={node.attrs.hideKey} + hideValue={node.attrs.hideValue} editable={node.attrs.editable} expanded={this.Expanded} dataDoc={node.attrs.dataDoc} @@ -112,6 +113,7 @@ interface IDashFieldViewInternal { fieldKey: string; docId: string; hideKey: boolean; + hideValue: boolean; tbox: FormattedTextBox; width: number; height: number; @@ -217,12 +219,28 @@ export class DashFieldViewInternal extends ObservableReactComponent this._dashDoc && (this._dashDoc[this._fieldKey + '_hideKey'] = !this._dashDoc[this._fieldKey + '_hideKey'])), + action(() => { + const editor = this._props.tbox.EditorView!; + editor.dispatch(editor.state.tr.setNodeMarkup(this._props.getPos(), this._props.node.type, { ...this._props.node.attrs, hideKey: !this._props.node.attrs.hideKey ? true : false })); + }), 'hideKey' ); + toggleValueHide = undoable( + action(() => { + const editor = this._props.tbox.EditorView!; + editor.dispatch(editor.state.tr.setNodeMarkup(this._props.getPos(), this._props.node.type, { ...this._props.node.attrs, hideValue: !this._props.node.attrs.hideValue ? true : false })); + }), + 'hideValue' + ); + + @observable _showValue = false; @computed get _hideKey() { - return this._dashDoc?.[this._fieldKey + '_hideKey'] && !this._expanded; + return this._props.hideKey && !this._expanded; + } + + @computed get _hideValue() { + return !this._showValue && this._props.hideValue && !this._expanded; } // clicking on the label creates a pivot view collection of all documents @@ -231,7 +249,11 @@ export class DashFieldViewInternal extends ObservableReactComponent { DashFieldViewMenu.createFieldView = this.createPivotForField; DashFieldViewMenu.toggleFieldHide = this.toggleFieldHide; + DashFieldViewMenu.toggleValueHide = this.toggleValueHide; DashFieldViewMenu.Instance.show(e.clientX, e.clientY + 16, this._fieldKey); + this._dashDoc?.[this._fieldKey + '_hideValue'] && runInAction(() => (this._showValue = !this._showValue)); + const editor = this._props.tbox.EditorView!; + setTimeout(() => editor.dispatch(editor.state.tr.setSelection(new NodeSelection(editor.state.doc.resolve(this._props.getPos())))), 100); }); }; @@ -257,12 +279,12 @@ export class DashFieldViewInternal extends ObservableReactComponent - {this._props.hideKey || this._hideKey ? null : ( + {this._hideKey ? null : ( {(Doc.AreProtosEqual(DocCast(this._textBoxDoc.rootDocument) ?? this._textBoxDoc, DocCast(this._dashDoc?.rootDocument) ?? this._dashDoc) ? '' : this._dashDoc?.title + ':') + this._fieldKey} )} - {this._props.fieldKey.startsWith('#') ? null : this.fieldValueContent} + {this._props.fieldKey.startsWith('#') || this._hideValue ? null : this.fieldValueContent} {/* {!this.values.length ? null : ( + {!this.values.length ? null : ( + - )} */} + )}
      ); } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 66df1eaf2..3700b08d6 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -2064,8 +2064,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent (this._isHovering = true))} - onPointerLeave={action(() => (this._isHovering = false))} + onPointerEnter={action(() => { + this._isHovering = true; + this.layoutDoc[`_${this._props.fieldKey}_usePath`] && (this.Document.isHovering = true); + })} + onPointerLeave={action(() => (this.Document.isHovering = this._isHovering = false))} ref={r => { this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel); this._oldWheel = r; -- cgit v1.2.3-70-g09d2 From 1e37adacfe5b44a71ed7d7dfd785c6c2d0808eae Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 31 Mar 2024 08:43:38 -0400 Subject: fixed divider column for notetaking view. fixed scrolling of text docs. fixed keeping user docs in system button bars. --- src/client/documents/Documents.ts | 2 +- .../views/collections/CollectionNoteTakingViewDivider.tsx | 12 ++++++++++++ src/client/views/nodes/formattedText/FormattedTextBox.scss | 1 + src/client/views/nodes/formattedText/FormattedTextBox.tsx | 1 + 4 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 8dccdeba9..6a0d45543 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1591,7 +1591,7 @@ export namespace DocUtils { } }); items?.forEach(item => !DocListCast(doc.data).includes(item) && Doc.AddDocToList(Doc.GetProto(doc), 'data', item)); - items && DocListCast(doc.data).forEach(item => !items.includes(item) && Doc.RemoveDocFromList(Doc.GetProto(doc), 'data', item)); + items && DocListCast(doc.data).forEach(item => Doc.IsSystem(item) && !items.includes(item) && Doc.RemoveDocFromList(Doc.GetProto(doc), 'data', item)); } return doc; } diff --git a/src/client/views/collections/CollectionNoteTakingViewDivider.tsx b/src/client/views/collections/CollectionNoteTakingViewDivider.tsx index 5e4bce19d..50a97b978 100644 --- a/src/client/views/collections/CollectionNoteTakingViewDivider.tsx +++ b/src/client/views/collections/CollectionNoteTakingViewDivider.tsx @@ -51,6 +51,18 @@ export class CollectionNoteTakingViewDivider extends ObservableReactComponent +
      this.registerResizing(e)} + style={{ + height: '95%', + width: 12, + borderRight: '4px solid #282828', + borderLeft: '4px solid #282828', + position: 'fixed', + pointerEvents: 'none', + }} + />
      this.registerResizing(e)} diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss index 03ff0436b..00d890860 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.scss +++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss @@ -156,6 +156,7 @@ audiotag:hover { .formattedTextBox-inner, .formattedTextBox-inner-minimal { height: 100%; + overflow: auto; white-space: pre-wrap; .ProseMirror:hover { background: rgba(200, 200, 200, 0.2); diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 3700b08d6..2deecb6ad 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -2032,6 +2032,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent Date: Sun, 31 Mar 2024 23:09:53 -0400 Subject: fixed scrolling to targets in text views. fixed referencing fields on another doc from text box. fixed '@name' technique for publishing documents to also remove documents and work anywhere a title is set. --- src/client/documents/Documents.ts | 5 ++++ src/client/util/Scripting.ts | 2 +- src/client/views/DocumentButtonBar.tsx | 2 +- src/client/views/DocumentDecorations.tsx | 6 ---- .../views/collections/CollectionDockingView.tsx | 25 ++++++++++++++-- .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- .../views/nodes/formattedText/DashFieldView.tsx | 8 ++--- .../views/nodes/formattedText/FormattedTextBox.tsx | 34 ++++++++++------------ .../views/nodes/formattedText/RichTextRules.ts | 13 +++------ src/client/views/nodes/formattedText/nodes_rts.ts | 1 - src/fields/Doc.ts | 13 +++++++-- src/fields/util.ts | 16 +++++++++- 12 files changed, 78 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 6a0d45543..eb15c332f 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1516,6 +1516,9 @@ export namespace DocUtils { return linkDoc; }); + const a = source.layout_unrendered ? 'link_anchor_1.annotationOn' : 'link_anchor_1'; + const b = target.layout_unrendered ? 'link_anchor_2.annotationOn' : 'link_anchor_2'; + return makeLink( Docs.Create.LinkDocument( source, @@ -1529,6 +1532,8 @@ export namespace DocUtils { link_displayLine: linkSettings.link_displayLine, link_relationship: linkSettings.link_relationship, link_description: linkSettings.link_description, + x: ComputedField.MakeFunction(`(this.${a}.x+this.${b}.x)/2`) as any, + y: ComputedField.MakeFunction(`(this.${a}.y+this.${b}.y)/2`) as any, link_autoMoveAnchors: true, _lockedPosition: true, _layout_showCaption: '', // removed since they conflict with showing a link with a LinkBox (ie, line, not comparison box) diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index 31222aa50..422e708bc 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -250,7 +250,7 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp const outputText = host.readFile('file.js'); const diagnostics = ts.getPreEmitDiagnostics(program).concat(testResult.diagnostics); - + if (script.startsWith('@')) options.typecheck = true; // need the compilation to fail so that the script will return itself as a string (instead of nothing) const result = Run(outputText, paramNames, diagnostics, script, options); if (options.globals) { diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index d65e0b406..15ce4c15f 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -416,7 +416,7 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => ( )} {DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== doc ?
      {this.endLinkButton}
      : null} - {Doc.noviceMode ? null :
      {this.templateButton}
      } +
      {this.templateButton}
      {!SelectionManager.Views?.some(v => v.allLinks.length) ? null :
      {this.followLinkButton}
      }
      {this.pinButton}
      {this.recordButton}
      diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 951e0912c..9e469ed1f 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -131,12 +131,6 @@ export class DocumentDecorations extends ObservableReactComponent { if (titleFieldKey === 'title') { d.dataDoc.title_custom = !this._accumulatedTitle.startsWith('-'); - if (StrCast(d.Document.title).startsWith('@') && !this._accumulatedTitle.startsWith('@')) { - Doc.RemFromMyPublished(d.Document); - } - if (!StrCast(d.Document.title).startsWith('@') && this._accumulatedTitle.startsWith('@')) { - Doc.AddToMyPublished(d.Document); - } } KeyValueBox.SetField(d.Document, titleFieldKey, this._accumulatedTitle); }), diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 25bfdb588..b2897a9b7 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -3,14 +3,14 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import * as GoldenLayout from '../../../client/goldenLayout'; -import { Doc, DocListCast, Opt } from '../../../fields/Doc'; +import { Doc, DocListCast, Field, Opt } from '../../../fields/Doc'; import { AclAdmin, AclEdit, DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; -import { ImageCast, NumCast, StrCast } from '../../../fields/Types'; +import { FieldValue, ImageCast, NumCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; -import { GetEffectiveAcl, inheritParentAcls } from '../../../fields/util'; +import { GetEffectiveAcl, inheritParentAcls, SetPropSetterCb } from '../../../fields/util'; import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, DivHeight, DivWidth, emptyFunction, incrementTitleCopy } from '../../../Utils'; import { DocServer } from '../../DocServer'; import { Docs } from '../../documents/Documents'; @@ -32,6 +32,7 @@ import './CollectionDockingView.scss'; import { CollectionFreeFormView } from './collectionFreeForm'; import { CollectionSubView } from './CollectionSubView'; import { TabDocView } from './TabDocView'; +import { ComputedField } from '../../../fields/ScriptField'; const _global = (window /* browser */ || global) /* node */ as any; @observer @@ -313,8 +314,26 @@ export class CollectionDockingView extends CollectionSubView() { } }; + /** + * This publishes Docs having titles starting with '@' to Doc.myPublishedDocs + * Once published, any text that uses the 'title' in its body will automatically + * be linked to this published document. + * @param target + * @param title + */ + titleChanged = (target: any, value: any) => { + const title = Field.toString(value); + if (title.startsWith('@') && !title.substring(1).match(/[\(\)\[\]@]/) && title.length > 1) { + const embedding = DocListCast(target.proto_embeddings).lastElement(); + embedding && Doc.AddToMyPublished(embedding); + } else if (!title.startsWith('@')) { + DocListCast(target.proto_embeddings).forEach(doc => Doc.RemFromMyPublished(doc)); + } + }; + componentDidMount: () => void = async () => { this._unmounting = false; + SetPropSetterCb('title', this.titleChanged); // this overrides any previously assigned callback for the property if (this._containerRef.current) { this._lightboxReactionDisposer = reaction( () => LightboxView.LightboxDoc, diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 6b3a56b0b..6eca91e9d 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -499,7 +499,7 @@ export class MarqueeView extends ObservableReactComponent ); @@ -119,7 +118,6 @@ interface IDashFieldViewInternal { height: number; editable: boolean; nodeSelected: () => boolean; - dataDoc: boolean; node: any; getPos: any; unclickable: () => boolean; @@ -139,7 +137,7 @@ export class DashFieldViewInternal extends ObservableReactComponent (this._dashDoc = this._props.dataDoc ? doc[DocData] : doc)); + const setDoc = action((doc: Doc) => (this._dashDoc = doc)); if (this._props.docId) { DocServer.GetRefField(this._props.docId).then(dashDoc => dashDoc instanceof Doc && setDoc(dashDoc)); @@ -168,7 +166,7 @@ export class DashFieldViewInternal extends ObservableReactComponent !this._props.tbox.ProseRef?.contains(document.activeElement) && this._props.tbox._props.onBlur?.()); } }); - selectedCell = (): [Doc, number] => [this._dashDoc!, 0]; + selectedCell = (): [Doc, number] | undefined => (this._dashDoc ? [this._dashDoc, 0] : undefined); columnWidth = () => Math.min(this._props.tbox._props.PanelWidth(), Math.max(50, this._props.tbox._props.PanelWidth() - 100)); // try to leave room for the fieldKey // set the display of the field's value (checkbox for booleans, span of text for strings) @@ -284,7 +282,7 @@ export class DashFieldViewInternal extends ObservableReactComponent +