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
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The body of `SiteShell`, once the route has been read: the theme, the bar,
|
|
3
|
+
* the page and the footer.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
7
|
+
import { isValidElement } from 'react';
|
|
8
|
+
|
|
9
|
+
import { AboutPage } from '../../about/ui/AboutPage.tsx';
|
|
10
|
+
import { AboutButton } from '../../chrome/ui/AboutButton.tsx';
|
|
11
|
+
import { SiteFooter } from '../../chrome/ui/SiteFooter.tsx';
|
|
12
|
+
import { SiteHeader } from '../../chrome/ui/SiteHeader.tsx';
|
|
13
|
+
import { useCompactHeader } from '../../chrome/ui/useCompactHeader.ts';
|
|
14
|
+
import { CiteButton } from '../../citation/ui/CiteButton.tsx';
|
|
15
|
+
import { EcosystemButton } from '../../ecosystem/ui/EcosystemButton.tsx';
|
|
16
|
+
import { SiteTheme } from '../../ecosystem/ui/SiteTheme.tsx';
|
|
17
|
+
import type { ShareParamCodecs } from '../../share/core/index.ts';
|
|
18
|
+
import { HiddenPartsProvider } from '../../share/ui/HiddenPartsProvider.tsx';
|
|
19
|
+
import { joinClassNames } from '../../shared/ui/joinClassNames.ts';
|
|
20
|
+
|
|
21
|
+
import { ShareControl } from './ShareControl.tsx';
|
|
22
|
+
import type { ShellSlot, SiteShellProps } from './SiteShell.tsx';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Draw the shell.
|
|
26
|
+
* @param props - The shell's props, the route already read.
|
|
27
|
+
* @returns The page in its chrome.
|
|
28
|
+
*/
|
|
29
|
+
export function ShellFrame<Codecs extends ShareParamCodecs, Tab extends string>(
|
|
30
|
+
props: SiteShellProps<Codecs, Tab>,
|
|
31
|
+
): ReactElement {
|
|
32
|
+
const {
|
|
33
|
+
siteId,
|
|
34
|
+
site,
|
|
35
|
+
mark,
|
|
36
|
+
markSize,
|
|
37
|
+
nav,
|
|
38
|
+
activeId,
|
|
39
|
+
homeHref,
|
|
40
|
+
onHome,
|
|
41
|
+
renderNavItem,
|
|
42
|
+
navPart = 'tabs',
|
|
43
|
+
width = 'page',
|
|
44
|
+
embedded = false,
|
|
45
|
+
hidden,
|
|
46
|
+
about = false,
|
|
47
|
+
contact,
|
|
48
|
+
belowHeader,
|
|
49
|
+
mainClassName,
|
|
50
|
+
mainTestId,
|
|
51
|
+
footer = {},
|
|
52
|
+
account,
|
|
53
|
+
children,
|
|
54
|
+
} = props;
|
|
55
|
+
const compact = useCompactHeader();
|
|
56
|
+
const footerSiteId = footer === false ? undefined : (footer.siteId ?? siteId);
|
|
57
|
+
const aboutOnShow = about !== false && about.active === true;
|
|
58
|
+
|
|
59
|
+
const page = (
|
|
60
|
+
<>
|
|
61
|
+
{siteId === undefined ? (
|
|
62
|
+
<SiteTheme site={site} />
|
|
63
|
+
) : (
|
|
64
|
+
<SiteTheme siteId={siteId} />
|
|
65
|
+
)}
|
|
66
|
+
<div className="site-shell">
|
|
67
|
+
<SiteHeader
|
|
68
|
+
siteId={siteId}
|
|
69
|
+
site={site}
|
|
70
|
+
mark={mark}
|
|
71
|
+
markSize={markSize}
|
|
72
|
+
embedded={embedded}
|
|
73
|
+
width={width}
|
|
74
|
+
nav={hidden?.includes(navPart) ? [] : nav}
|
|
75
|
+
activeId={aboutOnShow ? (about.id ?? 'about') : activeId}
|
|
76
|
+
homeHref={homeHref}
|
|
77
|
+
onHome={onHome}
|
|
78
|
+
renderNavItem={renderNavItem}
|
|
79
|
+
contact={contact}
|
|
80
|
+
actions={<ShellActions {...props} compact={compact} />}
|
|
81
|
+
share={<ShellShare {...props} compact={compact} />}
|
|
82
|
+
account={account}
|
|
83
|
+
/>
|
|
84
|
+
{embedded ? null : belowHeader}
|
|
85
|
+
<main
|
|
86
|
+
className={joinClassNames(
|
|
87
|
+
'site-shell__main',
|
|
88
|
+
width === 'full' ? 'site-shell__main--full' : undefined,
|
|
89
|
+
embedded ? 'site-shell__main--embedded' : undefined,
|
|
90
|
+
mainClassName,
|
|
91
|
+
)}
|
|
92
|
+
data-testid={mainTestId}
|
|
93
|
+
>
|
|
94
|
+
{aboutOnShow
|
|
95
|
+
? (about.page ?? <AboutPage content={about.content} />)
|
|
96
|
+
: children}
|
|
97
|
+
</main>
|
|
98
|
+
</div>
|
|
99
|
+
{footer === false || footerSiteId === undefined ? null : (
|
|
100
|
+
<SiteFooter
|
|
101
|
+
siteId={footerSiteId}
|
|
102
|
+
embedded={embedded}
|
|
103
|
+
width={width}
|
|
104
|
+
heading={footer.heading}
|
|
105
|
+
layout={footer.layout}
|
|
106
|
+
>
|
|
107
|
+
{footer.note === undefined ? null : (
|
|
108
|
+
<p className="app-footer__note">{footer.note}</p>
|
|
109
|
+
)}
|
|
110
|
+
{footer.children}
|
|
111
|
+
</SiteFooter>
|
|
112
|
+
)}
|
|
113
|
+
</>
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
return hidden === undefined ? (
|
|
117
|
+
page
|
|
118
|
+
) : (
|
|
119
|
+
<HiddenPartsProvider hidden={hidden}>{page}</HiddenPartsProvider>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
type ActionProps<
|
|
124
|
+
Codecs extends ShareParamCodecs,
|
|
125
|
+
Tab extends string,
|
|
126
|
+
> = SiteShellProps<Codecs, Tab> & { compact: boolean };
|
|
127
|
+
|
|
128
|
+
function ShellActions<Codecs extends ShareParamCodecs, Tab extends string>(
|
|
129
|
+
props: ActionProps<Codecs, Tab>,
|
|
130
|
+
): ReactNode {
|
|
131
|
+
const {
|
|
132
|
+
siteId,
|
|
133
|
+
about = false,
|
|
134
|
+
cite,
|
|
135
|
+
ecosystem = true,
|
|
136
|
+
actionsAfterAbout,
|
|
137
|
+
actionsAfterCite,
|
|
138
|
+
actions,
|
|
139
|
+
language,
|
|
140
|
+
compact,
|
|
141
|
+
} = props;
|
|
142
|
+
const works = cite ?? (about === false ? [] : (about.content.cite ?? []));
|
|
143
|
+
return (
|
|
144
|
+
<>
|
|
145
|
+
{about === false ? null : (
|
|
146
|
+
<AboutButton
|
|
147
|
+
id={about.id}
|
|
148
|
+
href={about.href ?? '/about'}
|
|
149
|
+
active={about.active}
|
|
150
|
+
onSelect={about.onSelect}
|
|
151
|
+
label={about.label}
|
|
152
|
+
title={about.title}
|
|
153
|
+
/>
|
|
154
|
+
)}
|
|
155
|
+
{fill(actionsAfterAbout, compact)}
|
|
156
|
+
{works === false || works.length === 0 ? null : (
|
|
157
|
+
<CiteButton works={works} compact={compact} />
|
|
158
|
+
)}
|
|
159
|
+
{fill(actionsAfterCite, compact)}
|
|
160
|
+
{ecosystem ? (
|
|
161
|
+
<EcosystemButton currentSiteId={siteId} compact={compact} />
|
|
162
|
+
) : null}
|
|
163
|
+
{fill(actions, compact)}
|
|
164
|
+
{fill(language, compact)}
|
|
165
|
+
</>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function ShellShare<Codecs extends ShareParamCodecs, Tab extends string>(
|
|
170
|
+
props: ActionProps<Codecs, Tab>,
|
|
171
|
+
): ReactNode {
|
|
172
|
+
const { share, siteId, compact } = props;
|
|
173
|
+
if (share === undefined) return null;
|
|
174
|
+
if (isValidElement(share)) return share;
|
|
175
|
+
return <ShareControl<Codecs> siteId={siteId} compact={compact} {...share} />;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function fill(slot: ShellSlot, compact: boolean): ReactNode {
|
|
179
|
+
return typeof slot === 'function' ? slot(compact) : slot;
|
|
180
|
+
}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
import type { AboutContent } from '../../about/core/about.ts';
|
|
4
|
+
import type { NavItem } from '../../chrome/ui/navItem.ts';
|
|
5
|
+
import type { CitedWork } from '../../citation/core/works.ts';
|
|
6
|
+
import type { SiteId, SiteRecord } from '../../ecosystem/core/sites.ts';
|
|
7
|
+
import { writeRoute } from '../../router/core/history.ts';
|
|
8
|
+
import type { TabRouter } from '../../router/core/tabRouter.ts';
|
|
9
|
+
import { useTabRoute } from '../../router/ui/useTabRoute.ts';
|
|
10
|
+
import type { ShareParamCodecs } from '../../share/core/index.ts';
|
|
11
|
+
|
|
12
|
+
import type { ShareControlProps } from './ShareControl.tsx';
|
|
13
|
+
import { ShellFrame } from './ShellFrame.tsx';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A slot of the bar: an element, or a function handed whether the bar has run
|
|
17
|
+
* out of room, so a site's own entries fold with the shared ones.
|
|
18
|
+
*/
|
|
19
|
+
export type ShellSlot = ReactNode | ((compact: boolean) => ReactNode);
|
|
20
|
+
|
|
21
|
+
/** The site's About: the record, and where it is served. */
|
|
22
|
+
export interface ShellAbout {
|
|
23
|
+
/** What the site says about itself; its works also feed the Cite button. */
|
|
24
|
+
content: AboutContent;
|
|
25
|
+
/**
|
|
26
|
+
* The About address.
|
|
27
|
+
* @default the router's address of the About tab, or `/about` without one
|
|
28
|
+
*/
|
|
29
|
+
href?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Whether the About is the page on show, in which case it is what the main
|
|
32
|
+
* area draws.
|
|
33
|
+
* @default whether the router's tab is the About tab, `false` without one
|
|
34
|
+
*/
|
|
35
|
+
active?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* What the site does when the entry is picked, for a page that routes in
|
|
38
|
+
* place.
|
|
39
|
+
* @default a move to the About tab with a router, the plain link without
|
|
40
|
+
*/
|
|
41
|
+
onSelect?: () => void;
|
|
42
|
+
/**
|
|
43
|
+
* What the active entry is named by.
|
|
44
|
+
* @default 'about'
|
|
45
|
+
*/
|
|
46
|
+
id?: string;
|
|
47
|
+
/**
|
|
48
|
+
* What the entry reads.
|
|
49
|
+
* @default the chrome's own word for it
|
|
50
|
+
*/
|
|
51
|
+
label?: string;
|
|
52
|
+
/**
|
|
53
|
+
* What the pointer is told.
|
|
54
|
+
* @default the chrome's own sentence
|
|
55
|
+
*/
|
|
56
|
+
title?: string;
|
|
57
|
+
/**
|
|
58
|
+
* The page itself, for a site whose About carries more than its record — a
|
|
59
|
+
* section of its own, a sign-in, a mark.
|
|
60
|
+
* @default `<AboutPage content={content} />`
|
|
61
|
+
*/
|
|
62
|
+
page?: ReactNode;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** The strip under the page. */
|
|
66
|
+
export interface ShellFooter {
|
|
67
|
+
/**
|
|
68
|
+
* The site the footer sits on, for a shell given a `site` record rather
|
|
69
|
+
* than a `siteId`.
|
|
70
|
+
* @default the shell's `siteId`, and no footer without one
|
|
71
|
+
*/
|
|
72
|
+
siteId?: SiteId;
|
|
73
|
+
/**
|
|
74
|
+
* What introduces the family.
|
|
75
|
+
* @default undefined
|
|
76
|
+
*/
|
|
77
|
+
heading?: string;
|
|
78
|
+
/**
|
|
79
|
+
* How much of each sibling is written.
|
|
80
|
+
* @default 'grid'
|
|
81
|
+
*/
|
|
82
|
+
layout?: 'grid' | 'row';
|
|
83
|
+
/**
|
|
84
|
+
* One line under the family, set as the footer's note.
|
|
85
|
+
* @default undefined
|
|
86
|
+
*/
|
|
87
|
+
note?: ReactNode;
|
|
88
|
+
/**
|
|
89
|
+
* Anything else under the family.
|
|
90
|
+
* @default undefined
|
|
91
|
+
*/
|
|
92
|
+
children?: ReactNode;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** What {@link SiteShell} needs. */
|
|
96
|
+
export interface SiteShellProps<
|
|
97
|
+
Codecs extends ShareParamCodecs = Record<string, never>,
|
|
98
|
+
Tab extends string = string,
|
|
99
|
+
> {
|
|
100
|
+
/**
|
|
101
|
+
* The site, named. One of `site` and `siteId` is required.
|
|
102
|
+
* @default undefined
|
|
103
|
+
*/
|
|
104
|
+
siteId?: SiteId;
|
|
105
|
+
/**
|
|
106
|
+
* The site, passed rather than named, for one outside the family's registry.
|
|
107
|
+
* @default undefined
|
|
108
|
+
*/
|
|
109
|
+
site?: SiteRecord;
|
|
110
|
+
/**
|
|
111
|
+
* The site's own mark, for a site the shared glyphs do not hold.
|
|
112
|
+
* @default the family's mark for the site
|
|
113
|
+
*/
|
|
114
|
+
mark?: ReactNode;
|
|
115
|
+
/**
|
|
116
|
+
* Edge of the mark, in pixels.
|
|
117
|
+
* @default 28
|
|
118
|
+
*/
|
|
119
|
+
markSize?: number;
|
|
120
|
+
/**
|
|
121
|
+
* The site's router. With it the shell follows the address itself: the
|
|
122
|
+
* page on show is the tab it names, and the About tab is served as the About
|
|
123
|
+
* page.
|
|
124
|
+
* @default undefined — the page says which entry is active
|
|
125
|
+
*/
|
|
126
|
+
router?: TabRouter<Tab>;
|
|
127
|
+
/**
|
|
128
|
+
* The tab the About is served at.
|
|
129
|
+
* @default 'about'
|
|
130
|
+
*/
|
|
131
|
+
aboutTab?: Tab;
|
|
132
|
+
/** The pages, in the order the bar lists them; About is not one of them. */
|
|
133
|
+
nav: readonly NavItem[];
|
|
134
|
+
/**
|
|
135
|
+
* Which of the pages is on show.
|
|
136
|
+
* @default the router's tab, or none without a router
|
|
137
|
+
*/
|
|
138
|
+
activeId?: string;
|
|
139
|
+
/**
|
|
140
|
+
* Where the brand leads.
|
|
141
|
+
* @default '/'
|
|
142
|
+
*/
|
|
143
|
+
homeHref?: string;
|
|
144
|
+
/**
|
|
145
|
+
* What the site does when the brand is picked.
|
|
146
|
+
* @default undefined
|
|
147
|
+
*/
|
|
148
|
+
onHome?: () => void;
|
|
149
|
+
/**
|
|
150
|
+
* Draws one page the site's own way.
|
|
151
|
+
* @default undefined
|
|
152
|
+
*/
|
|
153
|
+
renderNavItem?: (item: NavItem, isActive: boolean) => ReactNode;
|
|
154
|
+
/**
|
|
155
|
+
* The part a link hides the pages with; the bar then lists none.
|
|
156
|
+
* @default 'tabs'
|
|
157
|
+
*/
|
|
158
|
+
navPart?: string;
|
|
159
|
+
/**
|
|
160
|
+
* How wide the bar, the page and the footer run, all three alike.
|
|
161
|
+
* @default 'page'
|
|
162
|
+
*/
|
|
163
|
+
width?: 'page' | 'full';
|
|
164
|
+
/**
|
|
165
|
+
* Whether the page is framed in another site: no bar, no footer, and the
|
|
166
|
+
* frame as the margin.
|
|
167
|
+
* @default false
|
|
168
|
+
*/
|
|
169
|
+
embedded?: boolean;
|
|
170
|
+
/**
|
|
171
|
+
* The parts the link switches off, provided to every `PagePart` below.
|
|
172
|
+
* @default undefined — no provider; the page brings its own
|
|
173
|
+
*/
|
|
174
|
+
hidden?: readonly string[];
|
|
175
|
+
/**
|
|
176
|
+
* The About entry and page; `false` leaves both out.
|
|
177
|
+
* @default false
|
|
178
|
+
*/
|
|
179
|
+
about?: ShellAbout | false;
|
|
180
|
+
/**
|
|
181
|
+
* The works the Cite button offers; `false` leaves it out.
|
|
182
|
+
* @default the About's works, and no button when it has none
|
|
183
|
+
*/
|
|
184
|
+
cite?: readonly CitedWork[] | false;
|
|
185
|
+
/**
|
|
186
|
+
* Whether the Tools menu of the family is in the bar.
|
|
187
|
+
* @default true
|
|
188
|
+
*/
|
|
189
|
+
ecosystem?: boolean;
|
|
190
|
+
/**
|
|
191
|
+
* Entries between About and Cite — an API link, a version.
|
|
192
|
+
* @default undefined
|
|
193
|
+
*/
|
|
194
|
+
actionsAfterAbout?: ShellSlot;
|
|
195
|
+
/**
|
|
196
|
+
* Entries between Cite and Tools — a feedback form, a specification.
|
|
197
|
+
* @default undefined
|
|
198
|
+
*/
|
|
199
|
+
actionsAfterCite?: ShellSlot;
|
|
200
|
+
/**
|
|
201
|
+
* Entries after Tools — a unit picker, an admin action.
|
|
202
|
+
* @default undefined
|
|
203
|
+
*/
|
|
204
|
+
actions?: ShellSlot;
|
|
205
|
+
/**
|
|
206
|
+
* The language switcher, after the site's own entries.
|
|
207
|
+
* @default undefined
|
|
208
|
+
*/
|
|
209
|
+
language?: ShellSlot;
|
|
210
|
+
/**
|
|
211
|
+
* Who is signed in, at the right end.
|
|
212
|
+
* @default undefined
|
|
213
|
+
*/
|
|
214
|
+
account?: ReactNode;
|
|
215
|
+
/**
|
|
216
|
+
* The Share entry: what `ShareControl` is given, the shell passing it the
|
|
217
|
+
* site and the compact state, or a control of the site's own.
|
|
218
|
+
* @default undefined — no Share entry
|
|
219
|
+
*/
|
|
220
|
+
share?: ShareControlProps<Codecs> | ReactElement;
|
|
221
|
+
/**
|
|
222
|
+
* The contact form of the Contact entry, or `false` to leave it out.
|
|
223
|
+
* @default the family's form
|
|
224
|
+
*/
|
|
225
|
+
contact?: string | false;
|
|
226
|
+
/**
|
|
227
|
+
* What sits between the bar and the page — a tagline, a banner — dropped
|
|
228
|
+
* with the bar when the page is framed.
|
|
229
|
+
* @default undefined
|
|
230
|
+
*/
|
|
231
|
+
belowHeader?: ReactNode;
|
|
232
|
+
/**
|
|
233
|
+
* Classes the main area carries beside the shell's own.
|
|
234
|
+
* @default undefined
|
|
235
|
+
*/
|
|
236
|
+
mainClassName?: string;
|
|
237
|
+
/**
|
|
238
|
+
* `data-testid` of the main area.
|
|
239
|
+
* @default undefined
|
|
240
|
+
*/
|
|
241
|
+
mainTestId?: string;
|
|
242
|
+
/**
|
|
243
|
+
* The strip under the page, or `false` for none on this page.
|
|
244
|
+
* @default the family's links alone
|
|
245
|
+
*/
|
|
246
|
+
footer?: ShellFooter | false;
|
|
247
|
+
/** The page the address names. */
|
|
248
|
+
children: ReactNode;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* The chrome every site of the family carries, around its page: the theme,
|
|
253
|
+
* the bar with About · Cite · Tools · Contact · Share at its right, the page,
|
|
254
|
+
* and the footer linking every sibling. A framed page gets the page alone.
|
|
255
|
+
*
|
|
256
|
+
* Everything the bar holds is the shared components, in the family's order; a
|
|
257
|
+
* site fills the slots between them and never re-orders them. With a router,
|
|
258
|
+
* the shell also follows the address: it marks the tab on show and serves the
|
|
259
|
+
* About tab as the shared About page.
|
|
260
|
+
* @param props - See {@link SiteShellProps}.
|
|
261
|
+
* @returns The page in its chrome.
|
|
262
|
+
*/
|
|
263
|
+
export function SiteShell<
|
|
264
|
+
Codecs extends ShareParamCodecs = Record<string, never>,
|
|
265
|
+
Tab extends string = string,
|
|
266
|
+
>(props: SiteShellProps<Codecs, Tab>): ReactElement {
|
|
267
|
+
const { router } = props;
|
|
268
|
+
if (router === undefined) return <ShellFrame {...props} />;
|
|
269
|
+
return <RoutedShell {...props} router={router} />;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function RoutedShell<Codecs extends ShareParamCodecs, Tab extends string>(
|
|
273
|
+
props: SiteShellProps<Codecs, Tab> & { router: TabRouter<Tab> },
|
|
274
|
+
): ReactElement {
|
|
275
|
+
const { router, aboutTab = 'about' as Tab, about, activeId } = props;
|
|
276
|
+
const route = useTabRoute(router);
|
|
277
|
+
const routedAbout: ShellAbout | false =
|
|
278
|
+
about === undefined || about === false
|
|
279
|
+
? false
|
|
280
|
+
: {
|
|
281
|
+
...about,
|
|
282
|
+
href: about.href ?? router.format({ tab: aboutTab }),
|
|
283
|
+
active: about.active ?? route.tab === aboutTab,
|
|
284
|
+
onSelect:
|
|
285
|
+
about.onSelect ??
|
|
286
|
+
(() => {
|
|
287
|
+
writeRoute(router, { tab: aboutTab });
|
|
288
|
+
}),
|
|
289
|
+
};
|
|
290
|
+
return (
|
|
291
|
+
<ShellFrame
|
|
292
|
+
{...props}
|
|
293
|
+
about={routedAbout}
|
|
294
|
+
activeId={activeId ?? route.tab}
|
|
295
|
+
/>
|
|
296
|
+
);
|
|
297
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type { ShareControlProps } from './ShareControl.tsx';
|
|
2
|
+
export { ShareControl } from './ShareControl.tsx';
|
|
3
|
+
export type {
|
|
4
|
+
ShellAbout,
|
|
5
|
+
ShellFooter,
|
|
6
|
+
ShellSlot,
|
|
7
|
+
SiteShellProps,
|
|
8
|
+
} from './SiteShell.tsx';
|
|
9
|
+
export { SiteShell } from './SiteShell.tsx';
|
package/src/state/core/index.ts
CHANGED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {
|
|
2
|
+
readStorageText,
|
|
3
|
+
removeStorageEntry,
|
|
4
|
+
writeStorageEntry,
|
|
5
|
+
writeStorageText,
|
|
6
|
+
} from './storageEntry.ts';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* An entry a bucket was kept under before it took its versioned key: the full
|
|
10
|
+
* storage key, as written, or the key with a function turning its payload into
|
|
11
|
+
* the bucket's current shape.
|
|
12
|
+
*/
|
|
13
|
+
export type LegacyStorageKey =
|
|
14
|
+
| string
|
|
15
|
+
| {
|
|
16
|
+
/** The full storage key, e.g. `storage` or `mixonat:preferences`. */
|
|
17
|
+
key: string;
|
|
18
|
+
/**
|
|
19
|
+
* Turn the old payload, as `JSON.parse` read it, into what the bucket
|
|
20
|
+
* stores now. Answering `undefined`, or throwing, adopts nothing.
|
|
21
|
+
*/
|
|
22
|
+
migrate: (stored: unknown) => unknown;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Carry a returning visitor's entry over to the versioned key a bucket now
|
|
27
|
+
* uses, once.
|
|
28
|
+
*
|
|
29
|
+
* The first legacy key holding something is copied — as it is, or through its
|
|
30
|
+
* `migrate` — and only while the versioned entry does not exist, so it never
|
|
31
|
+
* overwrites what the bucket has written since. With `forget`, every legacy
|
|
32
|
+
* entry found is removed afterwards, adopted or not, so a bucket cleared later
|
|
33
|
+
* is not filled again from the old key on the next visit. Best effort, like
|
|
34
|
+
* every access to the store: one that cannot be reached adopts nothing.
|
|
35
|
+
* @param storageKey - The versioned key the bucket occupies.
|
|
36
|
+
* @param legacyKeys - The older entries, the preferred one first.
|
|
37
|
+
* @param forget - Whether to remove the legacy entries once read.
|
|
38
|
+
*/
|
|
39
|
+
export function adoptLegacyEntries(
|
|
40
|
+
storageKey: string,
|
|
41
|
+
legacyKeys: readonly LegacyStorageKey[],
|
|
42
|
+
forget: boolean,
|
|
43
|
+
): void {
|
|
44
|
+
if (legacyKeys.length === 0) return;
|
|
45
|
+
let adopted = readStorageText(storageKey) !== null;
|
|
46
|
+
for (const legacy of legacyKeys) {
|
|
47
|
+
const key = typeof legacy === 'string' ? legacy : legacy.key;
|
|
48
|
+
if (key === storageKey) continue;
|
|
49
|
+
const text = readStorageText(key);
|
|
50
|
+
if (text === null) continue;
|
|
51
|
+
if (!adopted) {
|
|
52
|
+
adopted =
|
|
53
|
+
typeof legacy === 'string'
|
|
54
|
+
? writeStorageText(storageKey, text)
|
|
55
|
+
: writeMigrated(storageKey, text, legacy.migrate);
|
|
56
|
+
}
|
|
57
|
+
if (forget) removeStorageEntry(key);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function writeMigrated(
|
|
62
|
+
storageKey: string,
|
|
63
|
+
text: string,
|
|
64
|
+
migrate: (stored: unknown) => unknown,
|
|
65
|
+
): boolean {
|
|
66
|
+
let value: unknown;
|
|
67
|
+
try {
|
|
68
|
+
value = migrate(JSON.parse(text));
|
|
69
|
+
} catch {
|
|
70
|
+
// A payload nobody can read any more is left to the defaults.
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
if (value === undefined) return false;
|
|
74
|
+
writeStorageEntry(storageKey, value);
|
|
75
|
+
return readStorageText(storageKey) !== null;
|
|
76
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { LegacyStorageKey } from './legacyEntries.ts';
|
|
2
|
+
import { adoptLegacyEntries } from './legacyEntries.ts';
|
|
1
3
|
import { isPlainRecord, mergeStored } from './mergeStored.ts';
|
|
2
4
|
import {
|
|
3
5
|
readStorageEntry,
|
|
@@ -16,30 +18,46 @@ import {
|
|
|
16
18
|
* quota is full still gets a working site, with their preferences lasting only
|
|
17
19
|
* as long as the tab.
|
|
18
20
|
* @param options - See {@link PersistBucketOptions}.
|
|
19
|
-
* @returns The
|
|
21
|
+
* @returns The ways to use the bucket: read it, write it, forget it, and
|
|
22
|
+
* hear another tab write it.
|
|
20
23
|
*/
|
|
21
24
|
export function persistBucket<T extends object>(
|
|
22
25
|
options: PersistBucketOptions<T>,
|
|
23
26
|
): PersistedBucket<T> {
|
|
24
27
|
const { key, version = 1, defaults, onQuotaExceeded } = options;
|
|
28
|
+
const { legacyKeys = [], forgetLegacyKeys = false } = options;
|
|
25
29
|
const storageKey = versionedStorageKey(key, version);
|
|
30
|
+
adoptLegacyEntries(storageKey, legacyKeys, forgetLegacyKeys);
|
|
31
|
+
|
|
32
|
+
function read(): BucketRead<T> {
|
|
33
|
+
const stored = readStorageEntry(storageKey);
|
|
34
|
+
const usable = isPlainRecord(stored) ? stored : undefined;
|
|
35
|
+
return {
|
|
36
|
+
value: mergeStored(defaults, usable),
|
|
37
|
+
firstRun: usable === undefined,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
26
40
|
|
|
27
41
|
return {
|
|
28
42
|
storageKey,
|
|
29
|
-
read
|
|
30
|
-
const stored = readStorageEntry(storageKey);
|
|
31
|
-
const usable = isPlainRecord(stored) ? stored : undefined;
|
|
32
|
-
return {
|
|
33
|
-
value: mergeStored(defaults, usable),
|
|
34
|
-
firstRun: usable === undefined,
|
|
35
|
-
};
|
|
36
|
-
},
|
|
43
|
+
read,
|
|
37
44
|
write: (value: T) => {
|
|
38
45
|
writeStorageEntry(storageKey, value, onQuotaExceeded);
|
|
39
46
|
},
|
|
40
47
|
clear: () => {
|
|
41
48
|
removeStorageEntry(storageKey);
|
|
42
49
|
},
|
|
50
|
+
subscribe: (listener) => {
|
|
51
|
+
function handleStorage(event: Event): void {
|
|
52
|
+
const change = event as { key?: unknown; newValue?: unknown };
|
|
53
|
+
if (change.key !== storageKey || change.newValue === null) return;
|
|
54
|
+
listener(read());
|
|
55
|
+
}
|
|
56
|
+
globalThis.addEventListener?.('storage', handleStorage);
|
|
57
|
+
return () => {
|
|
58
|
+
globalThis.removeEventListener?.('storage', handleStorage);
|
|
59
|
+
};
|
|
60
|
+
},
|
|
43
61
|
};
|
|
44
62
|
}
|
|
45
63
|
|
|
@@ -70,9 +88,23 @@ export interface PersistBucketOptions<T extends object> {
|
|
|
70
88
|
* @default undefined
|
|
71
89
|
*/
|
|
72
90
|
onQuotaExceeded?: (error: unknown) => void;
|
|
91
|
+
/**
|
|
92
|
+
* The entries the bucket was kept under before this key: an unversioned
|
|
93
|
+
* one, another site's, or a shape that needs a `migrate`. The first holding
|
|
94
|
+
* something is copied over once, while the versioned entry does not exist.
|
|
95
|
+
* @default []
|
|
96
|
+
*/
|
|
97
|
+
legacyKeys?: readonly LegacyStorageKey[];
|
|
98
|
+
/**
|
|
99
|
+
* Remove every legacy entry found once it has been read, so a bucket
|
|
100
|
+
* cleared later is not filled again from the old key. Left off, the old
|
|
101
|
+
* entries stay where they are.
|
|
102
|
+
* @default false
|
|
103
|
+
*/
|
|
104
|
+
forgetLegacyKeys?: boolean;
|
|
73
105
|
}
|
|
74
106
|
|
|
75
|
-
/** The
|
|
107
|
+
/** The ways a page uses its bucket. */
|
|
76
108
|
export interface PersistedBucket<T extends object> {
|
|
77
109
|
/** The versioned key the bucket occupies, e.g. `smiles:exercises:v1`. */
|
|
78
110
|
readonly storageKey: string;
|
|
@@ -82,6 +114,14 @@ export interface PersistedBucket<T extends object> {
|
|
|
82
114
|
write: (value: T) => void;
|
|
83
115
|
/** Forget the bucket, leaving whatever the page holds in memory untouched. */
|
|
84
116
|
clear: () => void;
|
|
117
|
+
/**
|
|
118
|
+
* Hear another tab of the same site store the bucket. The tab writing never
|
|
119
|
+
* hears its own write, and a removal is not news: the listener is handed
|
|
120
|
+
* what is stored now, merged over the defaults.
|
|
121
|
+
* @param listener - Called with the fresh read after each write elsewhere.
|
|
122
|
+
* @returns The function that stops listening.
|
|
123
|
+
*/
|
|
124
|
+
subscribe: (listener: (read: BucketRead<T>) => void) => () => void;
|
|
85
125
|
}
|
|
86
126
|
|
|
87
127
|
/** What one read of a bucket found. */
|