react-cheminfo 0.64.1 → 0.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +282 -0
- package/lib/card/core/cardAddress.d.ts +70 -0
- package/lib/card/core/cardAddress.d.ts.map +1 -0
- package/lib/card/core/cardAddress.js +59 -0
- package/lib/card/core/cardAddress.js.map +1 -0
- package/lib/card/core/cardPageUrl.d.ts +49 -0
- package/lib/card/core/cardPageUrl.d.ts.map +1 -0
- package/lib/card/core/cardPageUrl.js +59 -0
- package/lib/card/core/cardPageUrl.js.map +1 -0
- package/lib/card/core/index.d.ts +7 -0
- package/lib/card/core/index.d.ts.map +1 -0
- package/lib/card/core/index.js +4 -0
- package/lib/card/core/index.js.map +1 -0
- package/lib/card/core/panelRoom.d.ts +40 -0
- package/lib/card/core/panelRoom.d.ts.map +1 -0
- package/lib/card/core/panelRoom.js +40 -0
- package/lib/card/core/panelRoom.js.map +1 -0
- package/lib/card/ui/CardDetailsButton.d.ts +38 -0
- package/lib/card/ui/CardDetailsButton.d.ts.map +1 -0
- package/lib/card/ui/CardDetailsButton.js +50 -0
- package/lib/card/ui/CardDetailsButton.js.map +1 -0
- package/lib/card/ui/CardFigure.d.ts +51 -0
- package/lib/card/ui/CardFigure.d.ts.map +1 -0
- package/lib/card/ui/CardFigure.js +27 -0
- package/lib/card/ui/CardFigure.js.map +1 -0
- package/lib/card/ui/CardFrame.d.ts +30 -0
- package/lib/card/ui/CardFrame.d.ts.map +1 -0
- package/lib/card/ui/CardFrame.js +20 -0
- package/lib/card/ui/CardFrame.js.map +1 -0
- package/lib/card/ui/CopyTableButton.d.ts +37 -0
- package/lib/card/ui/CopyTableButton.d.ts.map +1 -0
- package/lib/card/ui/CopyTableButton.js +19 -0
- package/lib/card/ui/CopyTableButton.js.map +1 -0
- package/lib/card/ui/cardTooltip.d.ts +14 -0
- package/lib/card/ui/cardTooltip.d.ts.map +1 -0
- package/lib/card/ui/cardTooltip.js +15 -0
- package/lib/card/ui/cardTooltip.js.map +1 -0
- package/lib/card/ui/embed.d.ts +15 -0
- package/lib/card/ui/embed.d.ts.map +1 -0
- package/lib/card/ui/embed.js +24 -0
- package/lib/card/ui/embed.js.map +1 -0
- package/lib/card/ui/fitCardToFrame.d.ts +31 -0
- package/lib/card/ui/fitCardToFrame.d.ts.map +1 -0
- package/lib/card/ui/fitCardToFrame.js +66 -0
- package/lib/card/ui/fitCardToFrame.js.map +1 -0
- package/lib/card/ui/holdRoomForPanels.d.ts +16 -0
- package/lib/card/ui/holdRoomForPanels.d.ts.map +1 -0
- package/lib/card/ui/holdRoomForPanels.js +76 -0
- package/lib/card/ui/holdRoomForPanels.js.map +1 -0
- package/lib/card/ui/index.d.ts +11 -0
- package/lib/card/ui/index.d.ts.map +1 -0
- package/lib/card/ui/index.js +7 -0
- package/lib/card/ui/index.js.map +1 -0
- package/lib/card/ui/openPanels.d.ts +25 -0
- package/lib/card/ui/openPanels.d.ts.map +1 -0
- package/lib/card/ui/openPanels.js +85 -0
- package/lib/card/ui/openPanels.js.map +1 -0
- package/lib/card.d.ts +13 -0
- package/lib/card.d.ts.map +1 -0
- package/lib/card.js +13 -0
- package/lib/card.js.map +1 -0
- package/lib/conformers.d.ts +1 -0
- package/lib/conformers.d.ts.map +1 -1
- package/lib/conformers.js +1 -0
- package/lib/conformers.js.map +1 -1
- package/lib/core.d.ts +4 -0
- package/lib/core.d.ts.map +1 -1
- package/lib/core.js +5 -0
- package/lib/core.js.map +1 -1
- package/lib/fetch/core/apiError.d.ts +56 -0
- package/lib/fetch/core/apiError.d.ts.map +1 -0
- package/lib/fetch/core/apiError.js +43 -0
- package/lib/fetch/core/apiError.js.map +1 -0
- package/lib/fetch/core/fetchJson.d.ts +47 -0
- package/lib/fetch/core/fetchJson.d.ts.map +1 -0
- package/lib/fetch/core/fetchJson.js +109 -0
- package/lib/fetch/core/fetchJson.js.map +1 -0
- package/lib/fetch/core/index.d.ts +5 -0
- package/lib/fetch/core/index.d.ts.map +1 -0
- package/lib/fetch/core/index.js +3 -0
- package/lib/fetch/core/index.js.map +1 -0
- package/lib/formula/core/formulaText.d.ts +46 -0
- package/lib/formula/core/formulaText.d.ts.map +1 -0
- package/lib/formula/core/formulaText.js +74 -0
- package/lib/formula/core/formulaText.js.map +1 -0
- package/lib/formula/core/index.d.ts +6 -0
- package/lib/formula/core/index.d.ts.map +1 -0
- package/lib/formula/core/index.js +4 -0
- package/lib/formula/core/index.js.map +1 -0
- package/lib/formula/core/normalizeFormula.d.ts +22 -0
- package/lib/formula/core/normalizeFormula.d.ts.map +1 -0
- package/lib/formula/core/normalizeFormula.js +46 -0
- package/lib/formula/core/normalizeFormula.js.map +1 -0
- package/lib/formula/core/readFormula.d.ts +73 -0
- package/lib/formula/core/readFormula.d.ts.map +1 -0
- package/lib/formula/core/readFormula.js +132 -0
- package/lib/formula/core/readFormula.js.map +1 -0
- package/lib/formula/ui/CopyableFormula.d.ts +31 -0
- package/lib/formula/ui/CopyableFormula.d.ts.map +1 -0
- package/lib/formula/ui/CopyableFormula.js +19 -0
- package/lib/formula/ui/CopyableFormula.js.map +1 -0
- package/lib/formula/ui/FormulaInput.d.ts +29 -0
- package/lib/formula/ui/FormulaInput.d.ts.map +1 -0
- package/lib/formula/ui/FormulaInput.js +16 -0
- package/lib/formula/ui/FormulaInput.js.map +1 -0
- package/lib/formula/ui/QuestionFormula.d.ts +14 -0
- package/lib/formula/ui/QuestionFormula.d.ts.map +1 -0
- package/lib/formula/ui/QuestionFormula.js +13 -0
- package/lib/formula/ui/QuestionFormula.js.map +1 -0
- package/lib/formula/ui/index.d.ts +7 -0
- package/lib/formula/ui/index.d.ts.map +1 -0
- package/lib/formula/ui/index.js +4 -0
- package/lib/formula/ui/index.js.map +1 -0
- package/lib/formula.d.ts +11 -0
- package/lib/formula.d.ts.map +1 -0
- package/lib/formula.js +11 -0
- package/lib/formula.js.map +1 -0
- package/lib/hooks/ui/index.d.ts +1 -0
- package/lib/hooks/ui/index.d.ts.map +1 -1
- package/lib/hooks/ui/index.js.map +1 -1
- package/lib/hooks/ui/keyTargets.d.ts +4 -2
- package/lib/hooks/ui/keyTargets.d.ts.map +1 -1
- package/lib/hooks/ui/keyTargets.js +5 -3
- package/lib/hooks/ui/keyTargets.js.map +1 -1
- package/lib/hooks/ui/useAsync.d.ts +20 -5
- package/lib/hooks/ui/useAsync.d.ts.map +1 -1
- package/lib/hooks/ui/useAsync.js +29 -14
- package/lib/hooks/ui/useAsync.js.map +1 -1
- package/lib/i18n/core/chromeCatalog.d.ts +1 -1
- package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
- package/lib/locales/de.json +37 -0
- package/lib/locales/en.json +37 -0
- package/lib/locales/es.json +37 -0
- package/lib/locales/fr.json +37 -0
- package/lib/locales/it.json +37 -0
- package/lib/moleculesClient/core/index.d.ts +5 -0
- package/lib/moleculesClient/core/index.d.ts.map +1 -0
- package/lib/moleculesClient/core/index.js +3 -0
- package/lib/moleculesClient/core/index.js.map +1 -0
- package/lib/moleculesClient/core/moleculesClient.d.ts +12 -0
- package/lib/moleculesClient/core/moleculesClient.d.ts.map +1 -0
- package/lib/moleculesClient/core/moleculesClient.js +105 -0
- package/lib/moleculesClient/core/moleculesClient.js.map +1 -0
- package/lib/moleculesClient/core/moleculesClientApi.d.ts +100 -0
- package/lib/moleculesClient/core/moleculesClientApi.d.ts.map +1 -0
- package/lib/moleculesClient/core/moleculesClientApi.js +20 -0
- package/lib/moleculesClient/core/moleculesClientApi.js.map +1 -0
- package/lib/moleculesClient/core/moleculesTypes.d.ts +154 -0
- package/lib/moleculesClient/core/moleculesTypes.d.ts.map +1 -0
- package/lib/moleculesClient/core/moleculesTypes.js +2 -0
- package/lib/moleculesClient/core/moleculesTypes.js.map +1 -0
- package/lib/moleculesClient/core/requestRetry.d.ts +50 -0
- package/lib/moleculesClient/core/requestRetry.d.ts.map +1 -0
- package/lib/moleculesClient/core/requestRetry.js +108 -0
- package/lib/moleculesClient/core/requestRetry.js.map +1 -0
- package/lib/molstar/core/camera.d.ts +2 -1
- package/lib/molstar/core/camera.d.ts.map +1 -1
- package/lib/molstar/core/camera.js +3 -2
- package/lib/molstar/core/camera.js.map +1 -1
- package/lib/molstar/core/framing.d.ts +102 -0
- package/lib/molstar/core/framing.d.ts.map +1 -0
- package/lib/molstar/core/framing.js +120 -0
- package/lib/molstar/core/framing.js.map +1 -0
- package/lib/molstar/core/hover.d.ts +16 -0
- package/lib/molstar/core/hover.d.ts.map +1 -1
- package/lib/molstar/core/hover.js +14 -0
- package/lib/molstar/core/hover.js.map +1 -1
- package/lib/molstar/core/index.d.ts +4 -1
- package/lib/molstar/core/index.d.ts.map +1 -1
- package/lib/molstar/core/index.js +2 -1
- package/lib/molstar/core/index.js.map +1 -1
- package/lib/pedagogy/core/answers.d.ts +46 -0
- package/lib/pedagogy/core/answers.d.ts.map +1 -0
- package/lib/pedagogy/core/answers.js +77 -0
- package/lib/pedagogy/core/answers.js.map +1 -0
- package/lib/pedagogy/core/attempts.d.ts +86 -0
- package/lib/pedagogy/core/attempts.d.ts.map +1 -0
- package/lib/pedagogy/core/attempts.js +117 -0
- package/lib/pedagogy/core/attempts.js.map +1 -0
- package/lib/pedagogy/core/index.d.ts +8 -0
- package/lib/pedagogy/core/index.d.ts.map +1 -1
- package/lib/pedagogy/core/index.js +4 -0
- package/lib/pedagogy/core/index.js.map +1 -1
- package/lib/pedagogy/core/progressController.d.ts +64 -0
- package/lib/pedagogy/core/progressController.d.ts.map +1 -0
- package/lib/pedagogy/core/progressController.js +56 -0
- package/lib/pedagogy/core/progressController.js.map +1 -0
- package/lib/pedagogy/core/seed.d.ts +96 -0
- package/lib/pedagogy/core/seed.d.ts.map +1 -0
- package/lib/pedagogy/core/seed.js +128 -0
- package/lib/pedagogy/core/seed.js.map +1 -0
- package/lib/pedagogy/core/series.d.ts +77 -0
- package/lib/pedagogy/core/series.d.ts.map +1 -0
- package/lib/pedagogy/core/series.js +10 -0
- package/lib/pedagogy/core/series.js.map +1 -0
- package/lib/pedagogy/ui/AnswerFields.d.ts +21 -0
- package/lib/pedagogy/ui/AnswerFields.d.ts.map +1 -0
- package/lib/pedagogy/ui/AnswerFields.js +24 -0
- package/lib/pedagogy/ui/AnswerFields.js.map +1 -0
- package/lib/pedagogy/ui/ExerciseList.d.ts +82 -0
- package/lib/pedagogy/ui/ExerciseList.d.ts.map +1 -0
- package/lib/pedagogy/ui/ExerciseList.js +53 -0
- package/lib/pedagogy/ui/ExerciseList.js.map +1 -0
- package/lib/pedagogy/ui/ExerciseSeries.d.ts +95 -0
- package/lib/pedagogy/ui/ExerciseSeries.d.ts.map +1 -0
- package/lib/pedagogy/ui/ExerciseSeries.js +74 -0
- package/lib/pedagogy/ui/ExerciseSeries.js.map +1 -0
- package/lib/pedagogy/ui/QuestionCard.d.ts +64 -0
- package/lib/pedagogy/ui/QuestionCard.d.ts.map +1 -0
- package/lib/pedagogy/ui/QuestionCard.js +73 -0
- package/lib/pedagogy/ui/QuestionCard.js.map +1 -0
- package/lib/pedagogy/ui/index.d.ts +10 -0
- package/lib/pedagogy/ui/index.d.ts.map +1 -1
- package/lib/pedagogy/ui/index.js +6 -0
- package/lib/pedagogy/ui/index.js.map +1 -1
- package/lib/pedagogy/ui/seriesCounts.d.ts +17 -0
- package/lib/pedagogy/ui/seriesCounts.d.ts.map +1 -0
- package/lib/pedagogy/ui/seriesCounts.js +27 -0
- package/lib/pedagogy/ui/seriesCounts.js.map +1 -0
- package/lib/pedagogy/ui/seriesParts.d.ts +55 -0
- package/lib/pedagogy/ui/seriesParts.d.ts.map +1 -0
- package/lib/pedagogy/ui/seriesParts.js +38 -0
- package/lib/pedagogy/ui/seriesParts.js.map +1 -0
- package/lib/pedagogy/ui/useAttemptRecords.d.ts +10 -0
- package/lib/pedagogy/ui/useAttemptRecords.d.ts.map +1 -0
- package/lib/pedagogy/ui/useAttemptRecords.js +11 -0
- package/lib/pedagogy/ui/useAttemptRecords.js.map +1 -0
- package/lib/periodic/ui/PeriodicTable.d.ts.map +1 -1
- package/lib/periodic/ui/PeriodicTable.js +6 -3
- package/lib/periodic/ui/PeriodicTable.js.map +1 -1
- package/lib/property/core/copyableText.d.ts +14 -0
- package/lib/property/core/copyableText.d.ts.map +1 -0
- package/lib/property/core/copyableText.js +21 -0
- package/lib/property/core/copyableText.js.map +1 -0
- package/lib/property/core/index.d.ts +2 -0
- package/lib/property/core/index.d.ts.map +1 -0
- package/lib/property/core/index.js +2 -0
- package/lib/property/core/index.js.map +1 -0
- package/lib/property/ui/PropertyTable.d.ts +43 -0
- package/lib/property/ui/PropertyTable.d.ts.map +1 -0
- package/lib/property/ui/PropertyTable.js +19 -0
- package/lib/property/ui/PropertyTable.js.map +1 -0
- package/lib/property/ui/index.d.ts +3 -0
- package/lib/property/ui/index.d.ts.map +1 -0
- package/lib/property/ui/index.js +2 -0
- package/lib/property/ui/index.js.map +1 -0
- package/lib/router/core/history.d.ts +24 -3
- package/lib/router/core/history.d.ts.map +1 -1
- package/lib/router/core/history.js +55 -7
- package/lib/router/core/history.js.map +1 -1
- package/lib/router/core/index.d.ts +3 -3
- package/lib/router/core/index.d.ts.map +1 -1
- package/lib/router/core/index.js +2 -2
- package/lib/router/core/index.js.map +1 -1
- package/lib/router/core/languageRoute.d.ts +61 -0
- package/lib/router/core/languageRoute.d.ts.map +1 -0
- package/lib/router/core/languageRoute.js +96 -0
- package/lib/router/core/languageRoute.js.map +1 -0
- package/lib/router/core/siteAddresses.d.ts +23 -0
- package/lib/router/core/siteAddresses.d.ts.map +1 -1
- package/lib/router/core/siteAddresses.js +26 -0
- package/lib/router/core/siteAddresses.js.map +1 -1
- package/lib/router/core/tabRouter.d.ts +2 -108
- package/lib/router/core/tabRouter.d.ts.map +1 -1
- package/lib/router/core/tabRouter.js +38 -5
- package/lib/router/core/tabRouter.js.map +1 -1
- package/lib/router/core/tabRouterTypes.d.ts +154 -0
- package/lib/router/core/tabRouterTypes.d.ts.map +1 -0
- package/lib/router/core/tabRouterTypes.js +2 -0
- package/lib/router/core/tabRouterTypes.js.map +1 -0
- package/lib/seo/core/fitDescription.d.ts +40 -0
- package/lib/seo/core/fitDescription.d.ts.map +1 -0
- package/lib/seo/core/fitDescription.js +45 -0
- package/lib/seo/core/fitDescription.js.map +1 -0
- package/lib/seo/core/index.d.ts +7 -0
- package/lib/seo/core/index.d.ts.map +1 -1
- package/lib/seo/core/index.js +4 -0
- package/lib/seo/core/index.js.map +1 -1
- package/lib/seo/core/limits.d.ts +24 -0
- package/lib/seo/core/limits.d.ts.map +1 -0
- package/lib/seo/core/limits.js +24 -0
- package/lib/seo/core/limits.js.map +1 -0
- package/lib/seo/core/pageContent.d.ts +25 -0
- package/lib/seo/core/pageContent.d.ts.map +1 -0
- package/lib/seo/core/pageContent.js +25 -0
- package/lib/seo/core/pageContent.js.map +1 -0
- package/lib/seo/core/plainDescription.d.ts.map +1 -1
- package/lib/seo/core/plainDescription.js +3 -2
- package/lib/seo/core/plainDescription.js.map +1 -1
- package/lib/seo/core/routeProblems.d.ts.map +1 -1
- package/lib/seo/core/routeProblems.js +1 -6
- package/lib/seo/core/routeProblems.js.map +1 -1
- package/lib/seo/core/routeTable.d.ts +31 -0
- package/lib/seo/core/routeTable.d.ts.map +1 -0
- package/lib/seo/core/routeTable.js +96 -0
- package/lib/seo/core/routeTable.js.map +1 -0
- package/lib/seo/vite/index.d.ts +2 -0
- package/lib/seo/vite/index.d.ts.map +1 -1
- package/lib/seo/vite/index.js +1 -0
- package/lib/seo/vite/index.js.map +1 -1
- package/lib/seo/vite/prerender.d.ts +10 -0
- package/lib/seo/vite/prerender.d.ts.map +1 -1
- package/lib/seo/vite/prerender.js +12 -1
- package/lib/seo/vite/prerender.js.map +1 -1
- package/lib/seo/vite/routeTable.d.ts +40 -0
- package/lib/seo/vite/routeTable.d.ts.map +1 -0
- package/lib/seo/vite/routeTable.js +44 -0
- package/lib/seo/vite/routeTable.js.map +1 -0
- package/lib/server/answerAddresses.d.ts +51 -0
- package/lib/server/answerAddresses.d.ts.map +1 -0
- package/lib/server/answerAddresses.js +72 -0
- package/lib/server/answerAddresses.js.map +1 -0
- package/lib/server/cardMeta.d.ts +57 -0
- package/lib/server/cardMeta.d.ts.map +1 -0
- package/lib/server/cardMeta.js +52 -0
- package/lib/server/cardMeta.js.map +1 -0
- package/lib/server/config.d.ts +72 -0
- package/lib/server/config.d.ts.map +1 -0
- package/lib/server/config.js +67 -0
- package/lib/server/config.js.map +1 -0
- package/lib/server/envNumber.d.ts +35 -0
- package/lib/server/envNumber.d.ts.map +1 -0
- package/lib/server/envNumber.js +42 -0
- package/lib/server/envNumber.js.map +1 -0
- package/lib/server/healthRoute.d.ts +26 -0
- package/lib/server/healthRoute.d.ts.map +1 -0
- package/lib/server/healthRoute.js +22 -0
- package/lib/server/healthRoute.js.map +1 -0
- package/lib/server/listenSite.d.ts +38 -0
- package/lib/server/listenSite.d.ts.map +1 -0
- package/lib/server/listenSite.js +60 -0
- package/lib/server/listenSite.js.map +1 -0
- package/lib/server/mcpServer.d.ts +8 -0
- package/lib/server/mcpServer.d.ts.map +1 -0
- package/lib/server/mcpServer.js +11 -0
- package/lib/server/mcpServer.js.map +1 -0
- package/lib/server/repositoryVersion.d.ts +16 -0
- package/lib/server/repositoryVersion.d.ts.map +1 -0
- package/lib/server/repositoryVersion.js +33 -0
- package/lib/server/repositoryVersion.js.map +1 -0
- package/lib/server/routeOptions.d.ts +23 -0
- package/lib/server/routeOptions.d.ts.map +1 -0
- package/lib/server/routeOptions.js +20 -0
- package/lib/server/routeOptions.js.map +1 -0
- package/lib/server/routeTable.d.ts +14 -0
- package/lib/server/routeTable.d.ts.map +1 -0
- package/lib/server/routeTable.js +32 -0
- package/lib/server/routeTable.js.map +1 -0
- package/lib/server/siteView.d.ts +29 -0
- package/lib/server/siteView.d.ts.map +1 -0
- package/lib/server/siteView.js +21 -0
- package/lib/server/siteView.js.map +1 -0
- package/lib/server/spaPages.d.ts +32 -0
- package/lib/server/spaPages.d.ts.map +1 -0
- package/lib/server/spaPages.js +126 -0
- package/lib/server/spaPages.js.map +1 -0
- package/lib/server/spaSite.d.ts +30 -0
- package/lib/server/spaSite.d.ts.map +1 -0
- package/lib/server/spaSite.js +170 -0
- package/lib/server/spaSite.js.map +1 -0
- package/lib/server/spaSiteOptions.d.ts +126 -0
- package/lib/server/spaSiteOptions.d.ts.map +1 -0
- package/lib/server/spaSiteOptions.js +2 -0
- package/lib/server/spaSiteOptions.js.map +1 -0
- package/lib/server/staticSite.d.ts +9 -0
- package/lib/server/staticSite.d.ts.map +1 -1
- package/lib/server/staticSite.js +41 -19
- package/lib/server/staticSite.js.map +1 -1
- package/lib/server/toolSiteServer.d.ts +77 -0
- package/lib/server/toolSiteServer.d.ts.map +1 -0
- package/lib/server/toolSiteServer.js +58 -0
- package/lib/server/toolSiteServer.js.map +1 -0
- package/lib/server/trustProxy.d.ts +20 -0
- package/lib/server/trustProxy.d.ts.map +1 -0
- package/lib/server/trustProxy.js +32 -0
- package/lib/server/trustProxy.js.map +1 -0
- package/lib/server/types.d.ts +13 -0
- package/lib/server/types.d.ts.map +1 -0
- package/lib/server/types.js +2 -0
- package/lib/server/types.js.map +1 -0
- package/lib/server.d.ts +22 -0
- package/lib/server.d.ts.map +1 -1
- package/lib/server.js +12 -0
- package/lib/server.js.map +1 -1
- package/lib/share/core/config.d.ts +18 -0
- package/lib/share/core/config.d.ts.map +1 -1
- package/lib/share/core/config.js +33 -2
- package/lib/share/core/config.js.map +1 -1
- package/lib/share/core/index.d.ts +3 -1
- package/lib/share/core/index.d.ts.map +1 -1
- package/lib/share/core/index.js +2 -1
- package/lib/share/core/index.js.map +1 -1
- package/lib/share/core/keySetParam.d.ts +40 -0
- package/lib/share/core/keySetParam.d.ts.map +1 -0
- package/lib/share/core/keySetParam.js +60 -0
- package/lib/share/core/keySetParam.js.map +1 -0
- package/lib/share/core/vocabulary.d.ts +8 -0
- package/lib/share/core/vocabulary.d.ts.map +1 -1
- package/lib/shell/ui/ShareControl.d.ts +75 -0
- package/lib/shell/ui/ShareControl.d.ts.map +1 -0
- package/lib/shell/ui/ShareControl.js +40 -0
- package/lib/shell/ui/ShareControl.js.map +1 -0
- package/lib/shell/ui/ShellFrame.d.ts +14 -0
- package/lib/shell/ui/ShellFrame.d.ts.map +1 -0
- package/lib/shell/ui/ShellFrame.js +45 -0
- package/lib/shell/ui/ShellFrame.js.map +1 -0
- package/lib/shell/ui/SiteShell.d.ts +251 -0
- package/lib/shell/ui/SiteShell.d.ts.map +1 -0
- package/lib/shell/ui/SiteShell.js +39 -0
- package/lib/shell/ui/SiteShell.js.map +1 -0
- package/lib/shell/ui/index.d.ts +5 -0
- package/lib/shell/ui/index.d.ts.map +1 -0
- package/lib/shell/ui/index.js +3 -0
- package/lib/shell/ui/index.js.map +1 -0
- package/lib/state/core/index.d.ts +1 -0
- package/lib/state/core/index.d.ts.map +1 -1
- package/lib/state/core/index.js.map +1 -1
- package/lib/state/core/legacyEntries.d.ts +30 -0
- package/lib/state/core/legacyEntries.d.ts.map +1 -0
- package/lib/state/core/legacyEntries.js +51 -0
- package/lib/state/core/legacyEntries.js.map +1 -0
- package/lib/state/core/persistBucket.d.ts +26 -2
- package/lib/state/core/persistBucket.d.ts.map +1 -1
- package/lib/state/core/persistBucket.js +26 -9
- package/lib/state/core/persistBucket.js.map +1 -1
- package/lib/state/core/persistSignalBucket.d.ts +26 -0
- package/lib/state/core/persistSignalBucket.d.ts.map +1 -1
- package/lib/state/core/persistSignalBucket.js +31 -0
- package/lib/state/core/persistSignalBucket.js.map +1 -1
- package/lib/state/core/storageEntry.d.ts +15 -0
- package/lib/state/core/storageEntry.d.ts.map +1 -1
- package/lib/state/core/storageEntry.js +33 -0
- package/lib/state/core/storageEntry.js.map +1 -1
- package/lib/structure/ui/StructureExportButton.d.ts +27 -0
- package/lib/structure/ui/StructureExportButton.d.ts.map +1 -0
- package/lib/structure/ui/StructureExportButton.js +21 -0
- package/lib/structure/ui/StructureExportButton.js.map +1 -0
- package/lib/structure/ui/index.d.ts +4 -0
- package/lib/structure/ui/index.d.ts.map +1 -1
- package/lib/structure/ui/index.js +2 -0
- package/lib/structure/ui/index.js.map +1 -1
- package/lib/structure/ui/useStructureDraft.d.ts +32 -0
- package/lib/structure/ui/useStructureDraft.d.ts.map +1 -0
- package/lib/structure/ui/useStructureDraft.js +20 -0
- package/lib/structure/ui/useStructureDraft.js.map +1 -0
- package/lib/ui.d.ts +2 -0
- package/lib/ui.d.ts.map +1 -1
- package/lib/ui.js +2 -0
- package/lib/ui.js.map +1 -1
- package/lib/worker/core/index.d.ts +1 -1
- package/lib/worker/core/index.d.ts.map +1 -1
- package/lib/worker/core/messages.d.ts +4 -2
- package/lib/worker/core/messages.d.ts.map +1 -1
- package/lib/worker/core/messages.js.map +1 -1
- package/lib/worker/core/oclResourcesUrl.d.ts +16 -0
- package/lib/worker/core/oclResourcesUrl.d.ts.map +1 -0
- package/lib/worker/core/oclResourcesUrl.js +19 -0
- package/lib/worker/core/oclResourcesUrl.js.map +1 -0
- package/lib/worker/core/serveWorkerRequests.d.ts +8 -0
- package/lib/worker/core/serveWorkerRequests.d.ts.map +1 -1
- package/lib/worker/core/serveWorkerRequests.js +15 -2
- package/lib/worker/core/serveWorkerRequests.js.map +1 -1
- package/lib/worker/core/workerChannel.d.ts +3 -4
- package/lib/worker/core/workerChannel.d.ts.map +1 -1
- package/lib/worker/core/workerChannel.js +72 -67
- package/lib/worker/core/workerChannel.js.map +1 -1
- package/lib/worker/core/workerChannelParts.d.ts +17 -6
- package/lib/worker/core/workerChannelParts.d.ts.map +1 -1
- package/lib/worker/core/workerChannelParts.js +20 -4
- package/lib/worker/core/workerChannelParts.js.map +1 -1
- package/lib/worker/core/workerChannelTypes.d.ts +46 -2
- package/lib/worker/core/workerChannelTypes.d.ts.map +1 -1
- package/lib/worker/core/workerSlot.d.ts +66 -0
- package/lib/worker/core/workerSlot.d.ts.map +1 -0
- package/lib/worker/core/workerSlot.js +107 -0
- package/lib/worker/core/workerSlot.js.map +1 -0
- package/package.json +16 -1
- package/src/card/core/cardAddress.ts +100 -0
- package/src/card/core/cardPageUrl.ts +97 -0
- package/src/card/core/index.ts +6 -0
- package/src/card/core/panelRoom.ts +66 -0
- package/src/card/ui/CardDetailsButton.tsx +104 -0
- package/src/card/ui/CardFigure.tsx +86 -0
- package/src/card/ui/CardFrame.tsx +46 -0
- package/src/card/ui/CopyTableButton.tsx +81 -0
- package/src/card/ui/cardTooltip.ts +18 -0
- package/src/card/ui/embed.ts +27 -0
- package/src/card/ui/fitCardToFrame.ts +76 -0
- package/src/card/ui/holdRoomForPanels.ts +83 -0
- package/src/card/ui/index.ts +14 -0
- package/src/card/ui/openPanels.ts +106 -0
- package/src/card.ts +13 -0
- package/src/conformers.ts +4 -0
- package/src/core.ts +5 -0
- package/src/fetch/core/apiError.ts +65 -0
- package/src/fetch/core/fetchJson.ts +129 -0
- package/src/fetch/core/index.ts +4 -0
- package/src/formula/core/formulaText.ts +96 -0
- package/src/formula/core/index.ts +20 -0
- package/src/formula/core/normalizeFormula.ts +50 -0
- package/src/formula/core/readFormula.ts +211 -0
- package/src/formula/ui/CopyableFormula.tsx +51 -0
- package/src/formula/ui/FormulaInput.tsx +50 -0
- package/src/formula/ui/QuestionFormula.tsx +20 -0
- package/src/formula/ui/index.ts +6 -0
- package/src/formula.ts +11 -0
- package/src/hooks/ui/index.ts +1 -0
- package/src/hooks/ui/keyTargets.ts +5 -3
- package/src/hooks/ui/useAsync.ts +50 -14
- package/src/locales/de.json +37 -0
- package/src/locales/en.json +37 -0
- package/src/locales/es.json +37 -0
- package/src/locales/fr.json +37 -0
- package/src/locales/it.json +37 -0
- package/src/moleculesClient/core/index.ts +19 -0
- package/src/moleculesClient/core/moleculesClient.ts +175 -0
- package/src/moleculesClient/core/moleculesClientApi.ts +120 -0
- package/src/moleculesClient/core/moleculesTypes.ts +163 -0
- package/src/moleculesClient/core/requestRetry.ts +118 -0
- package/src/molstar/core/camera.ts +3 -2
- package/src/molstar/core/framing.ts +200 -0
- package/src/molstar/core/hover.ts +26 -0
- package/src/molstar/core/index.ts +21 -1
- package/src/pedagogy/core/answers.ts +94 -0
- package/src/pedagogy/core/attempts.ts +205 -0
- package/src/pedagogy/core/index.ts +36 -0
- package/src/pedagogy/core/progressController.ts +116 -0
- package/src/pedagogy/core/seed.ts +177 -0
- package/src/pedagogy/core/series.ts +82 -0
- package/src/pedagogy/ui/AnswerFields.tsx +63 -0
- package/src/pedagogy/ui/ExerciseList.tsx +202 -0
- package/src/pedagogy/ui/ExerciseSeries.tsx +250 -0
- package/src/pedagogy/ui/QuestionCard.tsx +231 -0
- package/src/pedagogy/ui/index.ts +18 -0
- package/src/pedagogy/ui/seriesCounts.ts +34 -0
- package/src/pedagogy/ui/seriesParts.tsx +127 -0
- package/src/pedagogy/ui/useAttemptRecords.ts +16 -0
- package/src/periodic/ui/PeriodicTable.tsx +6 -3
- package/src/property/core/copyableText.ts +20 -0
- package/src/property/core/index.ts +1 -0
- package/src/property/ui/PropertyTable.tsx +83 -0
- package/src/property/ui/index.ts +2 -0
- package/src/router/core/history.ts +61 -7
- package/src/router/core/index.ts +3 -2
- package/src/router/core/languageRoute.ts +136 -0
- package/src/router/core/siteAddresses.ts +38 -0
- package/src/router/core/tabRouter.ts +59 -117
- package/src/router/core/tabRouterTypes.ts +158 -0
- package/src/seo/core/fitDescription.ts +74 -0
- package/src/seo/core/index.ts +17 -0
- package/src/seo/core/limits.ts +27 -0
- package/src/seo/core/pageContent.ts +42 -0
- package/src/seo/core/plainDescription.ts +4 -2
- package/src/seo/core/routeProblems.ts +1 -7
- package/src/seo/core/routeTable.ts +103 -0
- package/src/seo/vite/index.ts +2 -0
- package/src/seo/vite/prerender.ts +26 -1
- package/src/seo/vite/routeTable.ts +79 -0
- package/src/server/answerAddresses.ts +92 -0
- package/src/server/cardMeta.ts +88 -0
- package/src/server/config.ts +125 -0
- package/src/server/envNumber.ts +65 -0
- package/src/server/healthRoute.ts +42 -0
- package/src/server/listenSite.ts +90 -0
- package/src/server/mcpServer.ts +14 -0
- package/src/server/repositoryVersion.ts +33 -0
- package/src/server/routeOptions.ts +26 -0
- package/src/server/routeTable.ts +35 -0
- package/src/server/siteView.ts +42 -0
- package/src/server/spaPages.ts +179 -0
- package/src/server/spaSite.ts +216 -0
- package/src/server/spaSiteOptions.ts +133 -0
- package/src/server/staticSite.ts +65 -35
- package/src/server/toolSiteServer.ts +127 -0
- package/src/server/trustProxy.ts +32 -0
- package/src/server/types.ts +25 -0
- package/src/server.ts +40 -0
- package/src/share/core/config.ts +45 -2
- package/src/share/core/index.ts +4 -0
- package/src/share/core/keySetParam.ts +92 -0
- package/src/share/core/vocabulary.ts +8 -0
- package/src/shell/ui/ShareControl.tsx +150 -0
- package/src/shell/ui/ShellFrame.tsx +180 -0
- package/src/shell/ui/SiteShell.tsx +297 -0
- package/src/shell/ui/index.ts +9 -0
- package/src/state/core/index.ts +1 -0
- package/src/state/core/legacyEntries.ts +76 -0
- package/src/state/core/persistBucket.ts +50 -10
- package/src/state/core/persistSignalBucket.ts +52 -0
- package/src/state/core/storageEntry.ts +32 -0
- package/src/structure/ui/StructureExportButton.tsx +57 -0
- package/src/structure/ui/index.ts +4 -0
- package/src/structure/ui/useStructureDraft.ts +47 -0
- package/src/ui.ts +2 -0
- package/src/worker/core/index.ts +1 -0
- package/src/worker/core/messages.ts +4 -3
- package/src/worker/core/oclResourcesUrl.ts +21 -0
- package/src/worker/core/serveWorkerRequests.ts +30 -2
- package/src/worker/core/workerChannel.ts +74 -74
- package/src/worker/core/workerChannelParts.ts +33 -13
- package/src/worker/core/workerChannelTypes.ts +47 -2
- package/src/worker/core/workerSlot.ts +181 -0
- package/styles/card.css +145 -0
- package/styles/chrome.css +248 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import type { LegacyStorageKey } from './legacyEntries.ts';
|
|
1
2
|
import { isPlainRecord } from './mergeStored.ts';
|
|
2
3
|
import { persistBucket } from './persistBucket.ts';
|
|
4
|
+
import { readStorageText } from './storageEntry.ts';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Keep a tree of signals in `localStorage`, under one versioned key.
|
|
@@ -19,6 +21,12 @@ import { persistBucket } from './persistBucket.ts';
|
|
|
19
21
|
* the tracking is always done by the copy of the library that made the
|
|
20
22
|
* signals. A member that is neither a signal nor a plain object is ignored.
|
|
21
23
|
* Never put a `computed()` in a bucket: it cannot be written back.
|
|
24
|
+
*
|
|
25
|
+
* With `syncAcrossTabs`, every tab follows the entry: a tab opened before
|
|
26
|
+
* another one stored its work would otherwise write its stale copy over it. A
|
|
27
|
+
* write that would store what is already there is skipped, so two tabs cannot
|
|
28
|
+
* echo each other, and nothing is written while another tab's copy is being
|
|
29
|
+
* taken on.
|
|
22
30
|
* @param options - See {@link PersistSignalBucketOptions}.
|
|
23
31
|
* @returns The same bucket, rehydrated, so it can be exported directly.
|
|
24
32
|
*/
|
|
@@ -26,26 +34,51 @@ export function persistSignalBucket<TBucket extends object>(
|
|
|
26
34
|
options: PersistSignalBucketOptions<TBucket>,
|
|
27
35
|
): TBucket {
|
|
28
36
|
const { key, version, bucket, effect, onQuotaExceeded } = options;
|
|
37
|
+
const { legacyKeys, forgetLegacyKeys, syncAcrossTabs = false } = options;
|
|
29
38
|
const stored = persistBucket({
|
|
30
39
|
key,
|
|
31
40
|
version,
|
|
32
41
|
defaults: snapshotBucket(bucket),
|
|
33
42
|
onQuotaExceeded,
|
|
43
|
+
legacyKeys,
|
|
44
|
+
forgetLegacyKeys,
|
|
34
45
|
});
|
|
35
46
|
|
|
36
47
|
const { value, firstRun } = stored.read();
|
|
37
48
|
if (!firstRun) hydrateBucket(bucket, value);
|
|
38
49
|
|
|
39
50
|
let subscribed = false;
|
|
51
|
+
let adopting = false;
|
|
40
52
|
effect(() => {
|
|
41
53
|
const snapshot = snapshotBucket(bucket);
|
|
42
54
|
if (!subscribed) {
|
|
43
55
|
subscribed = true;
|
|
44
56
|
return;
|
|
45
57
|
}
|
|
58
|
+
if (adopting) return;
|
|
59
|
+
if (
|
|
60
|
+
syncAcrossTabs !== false &&
|
|
61
|
+
readStorageText(stored.storageKey) === JSON.stringify(snapshot)
|
|
62
|
+
) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
46
65
|
stored.write(snapshot);
|
|
47
66
|
});
|
|
48
67
|
|
|
68
|
+
if (syncAcrossTabs !== false) {
|
|
69
|
+
stored.subscribe((read) => {
|
|
70
|
+
if (typeof syncAcrossTabs === 'function' && !syncAcrossTabs(bucket)) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
adopting = true;
|
|
74
|
+
try {
|
|
75
|
+
hydrateBucket(bucket, read.value);
|
|
76
|
+
} finally {
|
|
77
|
+
adopting = false;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
49
82
|
return bucket;
|
|
50
83
|
}
|
|
51
84
|
|
|
@@ -77,6 +110,25 @@ export interface PersistSignalBucketOptions<TBucket extends object> {
|
|
|
77
110
|
* @default undefined
|
|
78
111
|
*/
|
|
79
112
|
onQuotaExceeded?: (error: unknown) => void;
|
|
113
|
+
/**
|
|
114
|
+
* The entries the bucket was kept under before this key, the preferred one
|
|
115
|
+
* first; see `persistBucket`.
|
|
116
|
+
* @default []
|
|
117
|
+
*/
|
|
118
|
+
legacyKeys?: readonly LegacyStorageKey[];
|
|
119
|
+
/**
|
|
120
|
+
* Remove every legacy entry found once it has been read.
|
|
121
|
+
* @default false
|
|
122
|
+
*/
|
|
123
|
+
forgetLegacyKeys?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Take on what another tab stores, and skip a write that would store what is
|
|
126
|
+
* already there. A function decides each time, handed the bucket as this tab
|
|
127
|
+
* holds it: a bucket of work in progress keeps its own while it has some,
|
|
128
|
+
* rather than two tabs overwriting each other in turn.
|
|
129
|
+
* @default false
|
|
130
|
+
*/
|
|
131
|
+
syncAcrossTabs?: boolean | ((bucket: TBucket) => boolean);
|
|
80
132
|
}
|
|
81
133
|
|
|
82
134
|
interface SignalLeaf {
|
|
@@ -81,6 +81,38 @@ export function removeStorageEntry(storageKey: string): void {
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Read one `localStorage` entry as the text it was stored as, so two copies of
|
|
86
|
+
* a payload can be compared without parsing either.
|
|
87
|
+
* @param storageKey - The full key.
|
|
88
|
+
* @returns The stored text, or `null` when there is none or the store cannot
|
|
89
|
+
* be reached.
|
|
90
|
+
*/
|
|
91
|
+
export function readStorageText(storageKey: string): string | null {
|
|
92
|
+
try {
|
|
93
|
+
return globalThis.localStorage?.getItem(storageKey) ?? null;
|
|
94
|
+
} catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Write one `localStorage` entry as text, exactly as given. Best effort.
|
|
101
|
+
* @param storageKey - The full key.
|
|
102
|
+
* @param text - What to store.
|
|
103
|
+
* @returns Whether the store took it.
|
|
104
|
+
*/
|
|
105
|
+
export function writeStorageText(storageKey: string, text: string): boolean {
|
|
106
|
+
try {
|
|
107
|
+
const storage = globalThis.localStorage as Storage | undefined;
|
|
108
|
+
if (storage === undefined) return false;
|
|
109
|
+
storage.setItem(storageKey, text);
|
|
110
|
+
return true;
|
|
111
|
+
} catch {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
84
116
|
function isQuotaExceeded(error: unknown): boolean {
|
|
85
117
|
if (typeof error !== 'object' || error === null) return false;
|
|
86
118
|
const { name, code } = error as { name?: unknown; code?: unknown };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
|
|
4
|
+
import { useChromeT } from '../../i18n/ui/useT.ts';
|
|
5
|
+
import { OverlayIconButton } from '../../overlay/ui/OverlayIconButton.tsx';
|
|
6
|
+
|
|
7
|
+
import { StructureExportDialog } from './StructureExportDialog.tsx';
|
|
8
|
+
import type { StructureExportPanelProps } from './StructureExportPanel.tsx';
|
|
9
|
+
|
|
10
|
+
/** What {@link StructureExportButton} hands over. */
|
|
11
|
+
export interface StructureExportButtonProps extends StructureExportPanelProps {
|
|
12
|
+
/**
|
|
13
|
+
* What the glyph is called, for the pointer and for a screen reader.
|
|
14
|
+
* @default the chrome's own line, `Copy or save the structure: SMILES,
|
|
15
|
+
* molfile`
|
|
16
|
+
*/
|
|
17
|
+
label?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Value of the `data-testid` attribute of the glyph.
|
|
20
|
+
* @default 'card-structure'
|
|
21
|
+
*/
|
|
22
|
+
testId?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The glyph beside a figure that hands its one structure over: as a SMILES,
|
|
27
|
+
* a molfile or an idCode, each copied with a click, or as a picture — the
|
|
28
|
+
* export dialog, the one the chat opens on its own molecule cards. It is drawn
|
|
29
|
+
* like the figure's other glyphs, so it sits in the `tools` of a `CardFigure`
|
|
30
|
+
* or of any overlay bar.
|
|
31
|
+
* @param props - The structure, the name of its files, and the glyph's name.
|
|
32
|
+
* @returns The glyph; the dialog is drawn over the page while it is open.
|
|
33
|
+
*/
|
|
34
|
+
export function StructureExportButton(
|
|
35
|
+
props: StructureExportButtonProps,
|
|
36
|
+
): ReactElement {
|
|
37
|
+
const { label, testId = 'card-structure', ...structure } = props;
|
|
38
|
+
const t = useChromeT();
|
|
39
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
40
|
+
return (
|
|
41
|
+
<>
|
|
42
|
+
<OverlayIconButton
|
|
43
|
+
icon="export"
|
|
44
|
+
label={label ?? t('structure.export.glyph')}
|
|
45
|
+
active={isOpen}
|
|
46
|
+
opensMenu
|
|
47
|
+
testId={testId}
|
|
48
|
+
onClick={() => setIsOpen(true)}
|
|
49
|
+
/>
|
|
50
|
+
<StructureExportDialog
|
|
51
|
+
{...structure}
|
|
52
|
+
isOpen={isOpen}
|
|
53
|
+
onClose={() => setIsOpen(false)}
|
|
54
|
+
/>
|
|
55
|
+
</>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
@@ -25,6 +25,10 @@ export type { StructureEditorHelpProps } from './StructureEditorHelp.tsx';
|
|
|
25
25
|
export { StructureEditorHelp } from './StructureEditorHelp.tsx';
|
|
26
26
|
export type { StructureExportDialogProps } from './StructureExportDialog.tsx';
|
|
27
27
|
export { StructureExportDialog } from './StructureExportDialog.tsx';
|
|
28
|
+
export type { StructureExportButtonProps } from './StructureExportButton.tsx';
|
|
29
|
+
export { StructureExportButton } from './StructureExportButton.tsx';
|
|
28
30
|
export type { StructureExportPanelProps } from './StructureExportPanel.tsx';
|
|
29
31
|
export type { ToolbarFloorOptions } from './useToolbarFloor.ts';
|
|
30
32
|
export { useToolbarFloor } from './useToolbarFloor.ts';
|
|
33
|
+
export type { StructureDraft } from './useStructureDraft.ts';
|
|
34
|
+
export { useStructureDraft } from './useStructureDraft.ts';
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useCallback, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
/** What a structure editor is drawing, and how a page reloads it. */
|
|
4
|
+
export interface StructureDraft<TValue> {
|
|
5
|
+
/** What the canvas holds: the structure last loaded or last drawn. */
|
|
6
|
+
value: TValue;
|
|
7
|
+
/**
|
|
8
|
+
* What `StructureEditor` takes as `revision`: it reloads `value` into the
|
|
9
|
+
* canvas each time this changes, and only then.
|
|
10
|
+
*/
|
|
11
|
+
revision: number;
|
|
12
|
+
/**
|
|
13
|
+
* Put a structure in the canvas, replacing what is drawn: an example, the
|
|
14
|
+
* query a dialog is opened on, a Clear button loading the empty string.
|
|
15
|
+
* @param value - The structure, as the editor's `inputFormat` reads it.
|
|
16
|
+
*/
|
|
17
|
+
load: (value: TValue) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Keep what the editor drew, without reloading the canvas: what its
|
|
20
|
+
* `onChange` hands over. The same value twice changes nothing.
|
|
21
|
+
* @param value - The structure the editor reports.
|
|
22
|
+
*/
|
|
23
|
+
update: (value: TValue) => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The draft a `StructureEditor` is fed: what it draws, and the revision that
|
|
28
|
+
* makes it reload. The editor is uncontrolled, so feeding every stroke back
|
|
29
|
+
* into it would replace the structure under the pen; this keeps the drawing
|
|
30
|
+
* out of the canvas until the page means to load one.
|
|
31
|
+
* @param initial - What the canvas opens on.
|
|
32
|
+
* @returns The draft, and the two ways to change it.
|
|
33
|
+
*/
|
|
34
|
+
export function useStructureDraft<TValue = string>(
|
|
35
|
+
initial: TValue,
|
|
36
|
+
): StructureDraft<TValue> {
|
|
37
|
+
const [draft, setDraft] = useState({ value: initial, revision: 0 });
|
|
38
|
+
const load = useCallback((value: TValue) => {
|
|
39
|
+
setDraft((previous) => ({ value, revision: previous.revision + 1 }));
|
|
40
|
+
}, []);
|
|
41
|
+
const update = useCallback((value: TValue) => {
|
|
42
|
+
setDraft((previous) =>
|
|
43
|
+
Object.is(previous.value, value) ? previous : { ...previous, value },
|
|
44
|
+
);
|
|
45
|
+
}, []);
|
|
46
|
+
return { value: draft.value, revision: draft.revision, load, update };
|
|
47
|
+
}
|
package/src/ui.ts
CHANGED
|
@@ -27,12 +27,14 @@ export * from './parallel/ui/index.ts';
|
|
|
27
27
|
export * from './pedagogy/ui/index.ts';
|
|
28
28
|
export * from './periodic/ui/index.ts';
|
|
29
29
|
export * from './projection/ui/index.ts';
|
|
30
|
+
export * from './property/ui/index.ts';
|
|
30
31
|
export * from './range/ui/index.ts';
|
|
31
32
|
export * from './router/ui/index.ts';
|
|
32
33
|
export * from './scatter/ui/index.ts';
|
|
33
34
|
export * from './scatter3d/ui/index.ts';
|
|
34
35
|
export * from './share/ui/index.ts';
|
|
35
36
|
export * from './shared/ui/index.ts';
|
|
37
|
+
export * from './shell/ui/index.ts';
|
|
36
38
|
export * from './split/ui/index.ts';
|
|
37
39
|
export * from './taxonomy/ui/index.ts';
|
|
38
40
|
// The conformer table, from the structure module's file rather than its
|
package/src/worker/core/index.ts
CHANGED
|
@@ -27,12 +27,13 @@ export interface WorkerProgressMessage<TProgress> {
|
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* What a worker posts once a job is over. An `Error` does not survive the
|
|
30
|
-
* boundary, so a failure travels as its message
|
|
31
|
-
*
|
|
30
|
+
* boundary, so a failure travels as its message — plus, when the worker was
|
|
31
|
+
* told how, a `detail` the page reads to say it in its own words — and becomes
|
|
32
|
+
* an `Error` again on this side.
|
|
32
33
|
*/
|
|
33
34
|
export type WorkerResponseMessage<TResponse> =
|
|
34
35
|
| { id: number; ok: true; response: TResponse }
|
|
35
|
-
| { id: number; ok: false; message: string };
|
|
36
|
+
| { id: number; ok: false; message: string; detail?: unknown };
|
|
36
37
|
|
|
37
38
|
/**
|
|
38
39
|
* As much of a `Worker` as a channel uses. A real `Worker` satisfies it, and so
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** The file OpenChemLib's static resources are served as, at the site's root. */
|
|
2
|
+
export const OCL_RESOURCES_FILE = 'openchemlib-resources.json';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Where OpenChemLib's static resources sit, as this page is mounted.
|
|
6
|
+
*
|
|
7
|
+
* A worker fetches them, but a worker has no `document` and so cannot read the
|
|
8
|
+
* `<base>` the page carries, and its own script address is no help either: it
|
|
9
|
+
* sits under `assets/` in the build and under `src/` in development. So the
|
|
10
|
+
* page resolves the address and posts it with the job — the argument
|
|
11
|
+
* `registerResources` needs in a worker.
|
|
12
|
+
* @param file - The file, relative to the site's own root.
|
|
13
|
+
* @returns The absolute address, or `undefined` outside a page, where
|
|
14
|
+
* `registerResources` reads the file from the installed package instead.
|
|
15
|
+
*/
|
|
16
|
+
export function oclResourcesUrl(
|
|
17
|
+
file: string = OCL_RESOURCES_FILE,
|
|
18
|
+
): string | undefined {
|
|
19
|
+
const baseUri = globalThis.document?.baseURI;
|
|
20
|
+
return baseUri ? new URL(file, baseUri).href : undefined;
|
|
21
|
+
}
|
|
@@ -37,6 +37,14 @@ export interface ServeWorkerRequestsOptions<TRequest, TResponse> {
|
|
|
37
37
|
* @default undefined — every answer is copied
|
|
38
38
|
*/
|
|
39
39
|
transfer?: (response: TResponse) => Transferable[];
|
|
40
|
+
/**
|
|
41
|
+
* What a failed answer carries besides its message, for the page's channel
|
|
42
|
+
* to word the failure in its own language — the key of a translatable
|
|
43
|
+
* message and its values, say. It must survive being posted; answering
|
|
44
|
+
* `undefined` adds nothing.
|
|
45
|
+
* @default undefined — a failure carries its message alone
|
|
46
|
+
*/
|
|
47
|
+
detail?: (error: unknown) => unknown;
|
|
40
48
|
}
|
|
41
49
|
|
|
42
50
|
/**
|
|
@@ -59,7 +67,7 @@ export function serveWorkerRequests<TRequest, TResponse, TProgress = never>(
|
|
|
59
67
|
) => TResponse | Promise<TResponse>,
|
|
60
68
|
options: ServeWorkerRequestsOptions<TRequest, TResponse> = {},
|
|
61
69
|
): boolean {
|
|
62
|
-
const { accepts, transfer } = options;
|
|
70
|
+
const { accepts, transfer, detail } = options;
|
|
63
71
|
const scope = options.scope ?? dedicatedWorkerScope();
|
|
64
72
|
if (scope === undefined) return false;
|
|
65
73
|
const running = new Map<number, AbortController>();
|
|
@@ -99,7 +107,15 @@ export function serveWorkerRequests<TRequest, TResponse, TProgress = never>(
|
|
|
99
107
|
answer(scope, { id, ok: true, response }, transfer);
|
|
100
108
|
},
|
|
101
109
|
(error: unknown) => {
|
|
102
|
-
|
|
110
|
+
const message = errorMessage(error);
|
|
111
|
+
const extra =
|
|
112
|
+
detail === undefined ? undefined : describe(detail, error);
|
|
113
|
+
answer(
|
|
114
|
+
scope,
|
|
115
|
+
extra === undefined
|
|
116
|
+
? { id, ok: false, message }
|
|
117
|
+
: { id, ok: false, message, detail: extra },
|
|
118
|
+
);
|
|
103
119
|
},
|
|
104
120
|
)
|
|
105
121
|
.finally(() => {
|
|
@@ -127,6 +143,18 @@ function answer<TResponse>(
|
|
|
127
143
|
}
|
|
128
144
|
}
|
|
129
145
|
|
|
146
|
+
function describe(
|
|
147
|
+
detail: (error: unknown) => unknown,
|
|
148
|
+
error: unknown,
|
|
149
|
+
): unknown {
|
|
150
|
+
try {
|
|
151
|
+
return detail(error);
|
|
152
|
+
} catch {
|
|
153
|
+
// A detail that cannot be worked out leaves the message to say it all.
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
130
158
|
function dedicatedWorkerScope(): WorkerScopeLike | undefined {
|
|
131
159
|
const candidate = globalThis as {
|
|
132
160
|
postMessage?: unknown;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { toError } from '../../error/core/toError.ts';
|
|
2
2
|
|
|
3
3
|
import { CancelledRequestError, RequestTimeoutError } from './errors.ts';
|
|
4
|
-
import type {
|
|
4
|
+
import type { WorkerRequestMessage } from './messages.ts';
|
|
5
5
|
import type {
|
|
6
6
|
Outcome,
|
|
7
7
|
PendingRequest,
|
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
positiveMilliseconds,
|
|
13
13
|
postCancel,
|
|
14
14
|
runJobInProcess,
|
|
15
|
-
subscribeToWorker,
|
|
16
15
|
watchRequest,
|
|
17
16
|
} from './workerChannelParts.ts';
|
|
18
17
|
import type {
|
|
@@ -21,6 +20,7 @@ import type {
|
|
|
21
20
|
WorkerRequestOptions,
|
|
22
21
|
WorkerSource,
|
|
23
22
|
} from './workerChannelTypes.ts';
|
|
23
|
+
import { createWorkerSlot } from './workerSlot.ts';
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Turn a worker into something a page can await.
|
|
@@ -30,10 +30,9 @@ import type {
|
|
|
30
30
|
* — cancelled, superseded, timed out, or failed — drops out of the pending map
|
|
31
31
|
* at that moment. The worker may post progress about a job while it runs.
|
|
32
32
|
*
|
|
33
|
-
* Handed a worker, the channel posts to it and terminates it when asked
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* in-process run where there is no `Worker`.
|
|
33
|
+
* Handed a worker, the channel posts to it and terminates it when asked. Handed
|
|
34
|
+
* a function, it creates the worker when needed and can run the job in-process
|
|
35
|
+
* instead; see `createWorkerSlot`.
|
|
37
36
|
* @param source - The worker, or the function that creates it.
|
|
38
37
|
* @param options - See {@link WorkerChannelOptions}.
|
|
39
38
|
* @returns The channel.
|
|
@@ -43,38 +42,44 @@ export function createWorkerChannel<TRequest, TResponse, TProgress = never>(
|
|
|
43
42
|
source: WorkerSource,
|
|
44
43
|
options: WorkerChannelOptions<TRequest, TResponse, TProgress> = {},
|
|
45
44
|
): WorkerChannel<TRequest, TResponse, TProgress> {
|
|
46
|
-
const {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
cooperativeCancel = false,
|
|
50
|
-
defaultTimeoutMs,
|
|
51
|
-
runInProcess,
|
|
52
|
-
} = options;
|
|
45
|
+
const { name = 'worker', schedule = 'parallel' } = options;
|
|
46
|
+
const { cooperativeCancel = false, retryAfterWorkerFailure } = options;
|
|
47
|
+
const { defaultTimeoutMs, runInProcess, failure } = options;
|
|
53
48
|
const fallbackTimeoutMs = positiveMilliseconds(
|
|
54
49
|
defaultTimeoutMs,
|
|
55
50
|
DEFAULT_TIMEOUT_MS,
|
|
56
51
|
);
|
|
57
|
-
|
|
58
|
-
if (schedule === 'restart' && factory === undefined) {
|
|
52
|
+
if (schedule === 'restart' && typeof source !== 'function') {
|
|
59
53
|
throw new Error(`${name}: the restart schedule needs a worker factory`);
|
|
60
54
|
}
|
|
61
|
-
const
|
|
62
|
-
const runLocally = factory && hasNoWorker ? runInProcess : undefined;
|
|
55
|
+
const retries = typeof source === 'function' && retryAfterWorkerFailure;
|
|
63
56
|
|
|
64
57
|
const pending = new Map<number, PendingRequest<TResponse, TProgress>>();
|
|
65
|
-
|
|
58
|
+
const posted = new Map<number, QueuedRequest<TRequest>>();
|
|
59
|
+
const retried = new Set<number>();
|
|
66
60
|
let closed = false;
|
|
67
61
|
let nextId = 0;
|
|
68
62
|
let activeId: number | null = null;
|
|
69
63
|
let queued: QueuedRequest<TRequest> | null = null;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
64
|
+
const slot = createWorkerSlot<TRequest, TResponse, TProgress>(source, {
|
|
65
|
+
name,
|
|
66
|
+
runInProcess,
|
|
67
|
+
failure,
|
|
68
|
+
isWaited: (id) => pending.has(id),
|
|
69
|
+
report: {
|
|
70
|
+
progress: (id, progress) => {
|
|
71
|
+
pending.get(id)?.onProgress?.(progress as TProgress);
|
|
72
|
+
},
|
|
73
|
+
answer: (id, outcome) => complete(id, outcome),
|
|
74
|
+
failure: (error) => workerFailed(error),
|
|
75
|
+
},
|
|
76
|
+
});
|
|
74
77
|
|
|
75
78
|
function take(id: number): PendingRequest<TResponse, TProgress> | undefined {
|
|
76
79
|
const entry = pending.get(id);
|
|
77
80
|
pending.delete(id);
|
|
81
|
+
posted.delete(id);
|
|
82
|
+
retried.delete(id);
|
|
78
83
|
entry?.dispose();
|
|
79
84
|
return entry;
|
|
80
85
|
}
|
|
@@ -93,7 +98,7 @@ export function createWorkerChannel<TRequest, TResponse, TProgress = never>(
|
|
|
93
98
|
const entry = take(id);
|
|
94
99
|
if (entry === undefined) return false;
|
|
95
100
|
entry.controller?.abort();
|
|
96
|
-
if (cooperativeCancel && entry.dispatched) postCancel(
|
|
101
|
+
if (cooperativeCancel && entry.dispatched) postCancel(slot.current, id);
|
|
97
102
|
entry.reject(error);
|
|
98
103
|
return true;
|
|
99
104
|
}
|
|
@@ -106,22 +111,18 @@ export function createWorkerChannel<TRequest, TResponse, TProgress = never>(
|
|
|
106
111
|
}
|
|
107
112
|
|
|
108
113
|
function rejectAll(error: Error): void {
|
|
109
|
-
for (const entry of pending
|
|
110
|
-
|
|
114
|
+
for (const [id, entry] of pending) {
|
|
115
|
+
take(id);
|
|
111
116
|
entry.controller?.abort();
|
|
112
117
|
entry.reject(error);
|
|
113
118
|
}
|
|
114
|
-
pending.clear();
|
|
115
119
|
activeId = null;
|
|
116
120
|
queued = null;
|
|
117
121
|
}
|
|
118
122
|
|
|
119
123
|
function abandonActive(): void {
|
|
120
124
|
activeId = null;
|
|
121
|
-
|
|
122
|
-
worker.terminate();
|
|
123
|
-
worker = null;
|
|
124
|
-
}
|
|
125
|
+
slot.abandon();
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
function startQueued(): void {
|
|
@@ -135,55 +136,55 @@ export function createWorkerChannel<TRequest, TResponse, TProgress = never>(
|
|
|
135
136
|
if (entry === undefined) return;
|
|
136
137
|
entry.dispatched = true;
|
|
137
138
|
if (schedule !== 'parallel') activeId = id;
|
|
138
|
-
if (runLocally !== undefined) {
|
|
139
|
-
entry.controller = runJobInProcess(
|
|
140
|
-
runLocally,
|
|
141
|
-
payload,
|
|
142
|
-
(progress) => pending.get(id)?.onProgress?.(progress),
|
|
143
|
-
(outcome) => complete(id, outcome),
|
|
144
|
-
);
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
const message: WorkerRequestMessage<TRequest> = { id, request: payload };
|
|
148
139
|
try {
|
|
149
|
-
const target =
|
|
150
|
-
if (
|
|
151
|
-
|
|
140
|
+
const target = slot.acquire();
|
|
141
|
+
if (target !== null) {
|
|
142
|
+
if (retries && transfer === undefined) {
|
|
143
|
+
posted.set(id, { id, payload, transfer });
|
|
144
|
+
}
|
|
145
|
+
const message: WorkerRequestMessage<TRequest> = {
|
|
146
|
+
id,
|
|
147
|
+
request: payload,
|
|
148
|
+
};
|
|
149
|
+
if (transfer === undefined) target.postMessage(message);
|
|
150
|
+
else target.postMessage(message, transfer);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
152
153
|
} catch (error) {
|
|
153
154
|
complete(id, { ok: false, error: toError(error) });
|
|
155
|
+
return;
|
|
154
156
|
}
|
|
157
|
+
entry.controller = runJobInProcess(
|
|
158
|
+
slot.runLocally,
|
|
159
|
+
payload,
|
|
160
|
+
(progress) => pending.get(id)?.onProgress?.(progress),
|
|
161
|
+
(outcome) => complete(id, outcomeOf(outcome)),
|
|
162
|
+
);
|
|
155
163
|
}
|
|
156
164
|
|
|
157
|
-
function
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
worker = factory();
|
|
163
|
-
listen(worker);
|
|
164
|
-
}
|
|
165
|
-
return worker;
|
|
165
|
+
function outcomeOf(outcome: Outcome<TResponse>): Outcome<TResponse> {
|
|
166
|
+
return outcome.ok
|
|
167
|
+
? outcome
|
|
168
|
+
: { ok: false, error: slot.jobFailed(outcome.error) };
|
|
166
169
|
}
|
|
167
170
|
|
|
168
|
-
function
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
},
|
|
186
|
-
});
|
|
171
|
+
function workerFailed(error: Error): void {
|
|
172
|
+
if (!retries) {
|
|
173
|
+
rejectAll(error);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
activeId = null;
|
|
177
|
+
for (const [id, entry] of pending) {
|
|
178
|
+
if (!entry.dispatched) continue;
|
|
179
|
+
const job = posted.get(id);
|
|
180
|
+
if (job === undefined || retried.has(id)) {
|
|
181
|
+
drop(id, error);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
retried.add(id);
|
|
185
|
+
dispatch(id, job.payload);
|
|
186
|
+
}
|
|
187
|
+
if (activeId === null) startQueued();
|
|
187
188
|
}
|
|
188
189
|
|
|
189
190
|
function expire(id: number, budget: number): void {
|
|
@@ -242,9 +243,8 @@ export function createWorkerChannel<TRequest, TResponse, TProgress = never>(
|
|
|
242
243
|
cancel: () => dropAll('was cancelled'),
|
|
243
244
|
terminate: () => {
|
|
244
245
|
rejectAll(new CancelledRequestError(`${name} was terminated`));
|
|
245
|
-
|
|
246
|
-
if (
|
|
247
|
-
else worker = null;
|
|
246
|
+
slot.terminate();
|
|
247
|
+
if (!slot.hasFactory) closed = true;
|
|
248
248
|
},
|
|
249
249
|
};
|
|
250
250
|
}
|