react-cheminfo 0.25.0 → 0.27.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 +73 -2
- package/bin/check-deploy.mjs +14 -4
- package/bin/check-messages.mjs +229 -0
- package/lib/about/ui/AboutBuild.d.ts.map +1 -1
- package/lib/about/ui/AboutBuild.js +15 -4
- package/lib/about/ui/AboutBuild.js.map +1 -1
- package/lib/about/ui/AboutCitations.d.ts.map +1 -1
- package/lib/about/ui/AboutCitations.js +3 -1
- package/lib/about/ui/AboutCitations.js.map +1 -1
- package/lib/about/ui/AboutPage.d.ts.map +1 -1
- package/lib/about/ui/AboutPage.js +9 -1
- package/lib/about/ui/AboutPage.js.map +1 -1
- package/lib/about/ui/AboutProvidedBy.d.ts.map +1 -1
- package/lib/about/ui/AboutProvidedBy.js +8 -3
- package/lib/about/ui/AboutProvidedBy.js.map +1 -1
- package/lib/capsule/ui/Capsule.d.ts +30 -0
- package/lib/capsule/ui/Capsule.d.ts.map +1 -0
- package/lib/capsule/ui/Capsule.js +12 -0
- package/lib/capsule/ui/Capsule.js.map +1 -0
- package/lib/capsule/ui/CapsuleFilter.d.ts +19 -3
- package/lib/capsule/ui/CapsuleFilter.d.ts.map +1 -1
- package/lib/capsule/ui/CapsuleFilter.js +14 -44
- package/lib/capsule/ui/CapsuleFilter.js.map +1 -1
- package/lib/capsule/ui/capsuleFilterCapsules.d.ts +15 -0
- package/lib/capsule/ui/capsuleFilterCapsules.d.ts.map +1 -0
- package/lib/capsule/ui/capsuleFilterCapsules.js +47 -0
- package/lib/capsule/ui/capsuleFilterCapsules.js.map +1 -0
- package/lib/chart/ui/ChartTrackingLayer.d.ts.map +1 -1
- package/lib/chart/ui/ChartTrackingLayer.js +4 -2
- package/lib/chart/ui/ChartTrackingLayer.js.map +1 -1
- package/lib/chrome/ui/SiteHeader.d.ts +1 -1
- package/lib/chrome/ui/SiteHeader.d.ts.map +1 -1
- package/lib/chrome/ui/SiteHeader.js +4 -2
- package/lib/chrome/ui/SiteHeader.js.map +1 -1
- package/lib/citation/ui/CitationMenu.d.ts +1 -1
- package/lib/citation/ui/CitationMenu.d.ts.map +1 -1
- package/lib/citation/ui/CitationMenu.js +7 -3
- package/lib/citation/ui/CitationMenu.js.map +1 -1
- package/lib/citation/ui/CiteButton.d.ts +1 -1
- package/lib/citation/ui/CiteButton.d.ts.map +1 -1
- package/lib/citation/ui/CiteButton.js +3 -1
- package/lib/citation/ui/CiteButton.js.map +1 -1
- package/lib/citation/ui/CopyFormatEntries.d.ts.map +1 -1
- package/lib/citation/ui/CopyFormatEntries.js +3 -1
- package/lib/citation/ui/CopyFormatEntries.js.map +1 -1
- package/lib/citation/ui/WorkEntry.d.ts.map +1 -1
- package/lib/citation/ui/WorkEntry.js +3 -1
- package/lib/citation/ui/WorkEntry.js.map +1 -1
- package/lib/citation/ui/entries.d.ts.map +1 -1
- package/lib/citation/ui/entries.js +8 -2
- package/lib/citation/ui/entries.js.map +1 -1
- package/lib/citation/ui/useCopyFeedback.d.ts.map +1 -1
- package/lib/citation/ui/useCopyFeedback.js +9 -4
- package/lib/citation/ui/useCopyFeedback.js.map +1 -1
- package/lib/clipboard/ui/ClickToCopy.d.ts.map +1 -1
- package/lib/clipboard/ui/ClickToCopy.js +12 -6
- package/lib/clipboard/ui/ClickToCopy.js.map +1 -1
- package/lib/clipboard/ui/CopyButton.d.ts +3 -3
- package/lib/clipboard/ui/CopyButton.d.ts.map +1 -1
- package/lib/clipboard/ui/CopyButton.js +7 -4
- package/lib/clipboard/ui/CopyButton.js.map +1 -1
- package/lib/color/ui/ColorScaleEditor.d.ts.map +1 -1
- package/lib/color/ui/ColorScaleEditor.js +15 -10
- package/lib/color/ui/ColorScaleEditor.js.map +1 -1
- package/lib/color/ui/ColorScaleEntry.d.ts.map +1 -1
- package/lib/color/ui/ColorScaleEntry.js +4 -2
- package/lib/color/ui/ColorScaleEntry.js.map +1 -1
- package/lib/color/ui/ColorScaleLegend.d.ts.map +1 -1
- package/lib/color/ui/ColorScaleLegend.js +7 -1
- package/lib/color/ui/ColorScaleLegend.js.map +1 -1
- package/lib/color/ui/ColorScaleSelect.d.ts.map +1 -1
- package/lib/color/ui/ColorScaleSelect.js +8 -4
- package/lib/color/ui/ColorScaleSelect.js.map +1 -1
- package/lib/confirm/ui/ConfirmButton.d.ts +2 -2
- package/lib/confirm/ui/ConfirmButton.d.ts.map +1 -1
- package/lib/confirm/ui/ConfirmButton.js +4 -2
- package/lib/confirm/ui/ConfirmButton.js.map +1 -1
- package/lib/core.d.ts +1 -0
- package/lib/core.d.ts.map +1 -1
- package/lib/core.js +1 -0
- package/lib/core.js.map +1 -1
- package/lib/credits/ui/CreditsList.d.ts.map +1 -1
- package/lib/credits/ui/CreditsList.js +3 -1
- package/lib/credits/ui/CreditsList.js.map +1 -1
- package/lib/delimited/ui/DelimitedTextDialog.d.ts.map +1 -1
- package/lib/delimited/ui/DelimitedTextDialog.js +5 -2
- package/lib/delimited/ui/DelimitedTextDialog.js.map +1 -1
- package/lib/delimited/ui/DelimitedTextPanel.d.ts.map +1 -1
- package/lib/delimited/ui/DelimitedTextPanel.js +8 -8
- package/lib/delimited/ui/DelimitedTextPanel.js.map +1 -1
- package/lib/deploy/core/checkDeploy.d.ts +3 -1
- package/lib/deploy/core/checkDeploy.d.ts.map +1 -1
- package/lib/deploy/core/checkDeploy.js +7 -1
- package/lib/deploy/core/checkDeploy.js.map +1 -1
- package/lib/deploy/core/index.d.ts +1 -0
- package/lib/deploy/core/index.d.ts.map +1 -1
- package/lib/deploy/core/index.js +1 -0
- package/lib/deploy/core/index.js.map +1 -1
- package/lib/deploy/core/pageCache.d.ts +24 -0
- package/lib/deploy/core/pageCache.d.ts.map +1 -0
- package/lib/deploy/core/pageCache.js +91 -0
- package/lib/deploy/core/pageCache.js.map +1 -0
- package/lib/deploy/core/types.d.ts +1 -1
- package/lib/deploy/core/types.d.ts.map +1 -1
- package/lib/deploy/core/types.js.map +1 -1
- package/lib/download/ui/FigureDownload.d.ts +2 -2
- package/lib/download/ui/FigureDownload.d.ts.map +1 -1
- package/lib/download/ui/FigureDownload.js +4 -2
- package/lib/download/ui/FigureDownload.js.map +1 -1
- package/lib/download/ui/FigureDownloadPanel.d.ts.map +1 -1
- package/lib/download/ui/FigureDownloadPanel.js +24 -18
- package/lib/download/ui/FigureDownloadPanel.js.map +1 -1
- package/lib/ecosystem/ui/EcosystemButton.d.ts +1 -1
- package/lib/ecosystem/ui/EcosystemButton.d.ts.map +1 -1
- package/lib/ecosystem/ui/EcosystemButton.js +4 -2
- package/lib/ecosystem/ui/EcosystemButton.js.map +1 -1
- package/lib/ecosystem/ui/EcosystemLinks.d.ts +1 -1
- package/lib/ecosystem/ui/EcosystemLinks.d.ts.map +1 -1
- package/lib/ecosystem/ui/EcosystemLinks.js +5 -2
- package/lib/ecosystem/ui/EcosystemLinks.js.map +1 -1
- package/lib/ecosystem/ui/EcosystemMenu.d.ts.map +1 -1
- package/lib/ecosystem/ui/EcosystemMenu.js +3 -1
- package/lib/ecosystem/ui/EcosystemMenu.js.map +1 -1
- package/lib/ecosystem/ui/SiteGroupSection.d.ts.map +1 -1
- package/lib/ecosystem/ui/SiteGroupSection.js +3 -1
- package/lib/ecosystem/ui/SiteGroupSection.js.map +1 -1
- package/lib/ecosystem/ui/SiteTile.d.ts.map +1 -1
- package/lib/ecosystem/ui/SiteTile.js +3 -1
- package/lib/ecosystem/ui/SiteTile.js.map +1 -1
- package/lib/error/ui/ErrorFallback.d.ts +2 -2
- package/lib/error/ui/ErrorFallback.d.ts.map +1 -1
- package/lib/error/ui/ErrorFallback.js +4 -2
- package/lib/error/ui/ErrorFallback.js.map +1 -1
- package/lib/help/ui/HelpBody.d.ts.map +1 -1
- package/lib/help/ui/HelpBody.js +3 -1
- package/lib/help/ui/HelpBody.js.map +1 -1
- package/lib/help/ui/HelpIcon.d.ts +2 -1
- package/lib/help/ui/HelpIcon.d.ts.map +1 -1
- package/lib/help/ui/HelpIcon.js +4 -2
- package/lib/help/ui/HelpIcon.js.map +1 -1
- package/lib/help/ui/HelpToolbarButton.d.ts.map +1 -1
- package/lib/help/ui/HelpToolbarButton.js +3 -1
- package/lib/help/ui/HelpToolbarButton.js.map +1 -1
- package/lib/help/ui/helpName.d.ts +5 -1
- package/lib/help/ui/helpName.d.ts.map +1 -1
- package/lib/help/ui/helpName.js +4 -2
- package/lib/help/ui/helpName.js.map +1 -1
- package/lib/i18n/core/chromeCatalog.d.ts +21 -0
- package/lib/i18n/core/chromeCatalog.d.ts.map +1 -0
- package/lib/i18n/core/chromeCatalog.js +29 -0
- package/lib/i18n/core/chromeCatalog.js.map +1 -0
- package/lib/i18n/core/index.d.ts +12 -0
- package/lib/i18n/core/index.d.ts.map +1 -0
- package/lib/i18n/core/index.js +6 -0
- package/lib/i18n/core/index.js.map +1 -0
- package/lib/i18n/core/languages.d.ts +32 -0
- package/lib/i18n/core/languages.d.ts.map +1 -0
- package/lib/i18n/core/languages.js +41 -0
- package/lib/i18n/core/languages.js.map +1 -0
- package/lib/i18n/core/messageCatalog.d.ts +113 -0
- package/lib/i18n/core/messageCatalog.d.ts.map +1 -0
- package/lib/i18n/core/messageCatalog.js +135 -0
- package/lib/i18n/core/messageCatalog.js.map +1 -0
- package/lib/i18n/core/messageValues.d.ts +3 -0
- package/lib/i18n/core/messageValues.d.ts.map +1 -0
- package/lib/i18n/core/messageValues.js +2 -0
- package/lib/i18n/core/messageValues.js.map +1 -0
- package/lib/i18n/core/session.d.ts +51 -0
- package/lib/i18n/core/session.d.ts.map +1 -0
- package/lib/i18n/core/session.js +64 -0
- package/lib/i18n/core/session.js.map +1 -0
- package/lib/i18n/core/translateSetup.d.ts +28 -0
- package/lib/i18n/core/translateSetup.d.ts.map +1 -0
- package/lib/i18n/core/translateSetup.js +30 -0
- package/lib/i18n/core/translateSetup.js.map +1 -0
- package/lib/i18n/ui/LanguageSelect.d.ts +37 -0
- package/lib/i18n/ui/LanguageSelect.d.ts.map +1 -0
- package/lib/i18n/ui/LanguageSelect.js +27 -0
- package/lib/i18n/ui/LanguageSelect.js.map +1 -0
- package/lib/i18n/ui/index.d.ts +6 -0
- package/lib/i18n/ui/index.d.ts.map +1 -0
- package/lib/i18n/ui/index.js +4 -0
- package/lib/i18n/ui/index.js.map +1 -0
- package/lib/i18n/ui/useLanguage.d.ts +23 -0
- package/lib/i18n/ui/useLanguage.d.ts.map +1 -0
- package/lib/i18n/ui/useLanguage.js +36 -0
- package/lib/i18n/ui/useLanguage.js.map +1 -0
- package/lib/i18n/ui/useT.d.ts +47 -0
- package/lib/i18n/ui/useT.d.ts.map +1 -0
- package/lib/i18n/ui/useT.js +51 -0
- package/lib/i18n/ui/useT.js.map +1 -0
- package/lib/locales/de.json +442 -0
- package/lib/locales/en.json +442 -0
- package/lib/locales/es.json +442 -0
- package/lib/locales/fr.json +442 -0
- package/lib/molecule3d/core/gestures.d.ts +10 -0
- package/lib/molecule3d/core/gestures.d.ts.map +1 -1
- package/lib/molecule3d/core/gestures.js +39 -7
- package/lib/molecule3d/core/gestures.js.map +1 -1
- package/lib/molecule3d/ui/Molecule3DExport.d.ts.map +1 -1
- package/lib/molecule3d/ui/Molecule3DExport.js +3 -1
- package/lib/molecule3d/ui/Molecule3DExport.js.map +1 -1
- package/lib/molecule3d/ui/Molecule3DHelp.d.ts.map +1 -1
- package/lib/molecule3d/ui/Molecule3DHelp.js +7 -2
- package/lib/molecule3d/ui/Molecule3DHelp.js.map +1 -1
- package/lib/molecule3d/ui/Molecule3DOptions.d.ts.map +1 -1
- package/lib/molecule3d/ui/Molecule3DOptions.js +9 -9
- package/lib/molecule3d/ui/Molecule3DOptions.js.map +1 -1
- package/lib/molecule3d/ui/Molecule3DSurfaceColors.d.ts.map +1 -1
- package/lib/molecule3d/ui/Molecule3DSurfaceColors.js +8 -8
- package/lib/molecule3d/ui/Molecule3DSurfaceColors.js.map +1 -1
- package/lib/molecule3d/ui/Molecule3DToolbar.d.ts.map +1 -1
- package/lib/molecule3d/ui/Molecule3DToolbar.js +15 -10
- package/lib/molecule3d/ui/Molecule3DToolbar.js.map +1 -1
- package/lib/molecule3d/ui/MoleculeViewer3D.d.ts.map +1 -1
- package/lib/molecule3d/ui/MoleculeViewer3D.js +6 -3
- package/lib/molecule3d/ui/MoleculeViewer3D.js.map +1 -1
- package/lib/orbital/ui/AtomicOrbitalCanvas.d.ts.map +1 -1
- package/lib/orbital/ui/AtomicOrbitalCanvas.js +3 -1
- package/lib/orbital/ui/AtomicOrbitalCanvas.js.map +1 -1
- package/lib/orbital/ui/AtomicOrbitalControls.d.ts.map +1 -1
- package/lib/orbital/ui/AtomicOrbitalControls.js +12 -15
- package/lib/orbital/ui/AtomicOrbitalControls.js.map +1 -1
- package/lib/orbital/ui/AtomicOrbitalViewer.d.ts.map +1 -1
- package/lib/orbital/ui/AtomicOrbitalViewer.js +6 -3
- package/lib/orbital/ui/AtomicOrbitalViewer.js.map +1 -1
- package/lib/orbital/ui/capability.d.ts +4 -0
- package/lib/orbital/ui/capability.d.ts.map +1 -1
- package/lib/orbital/ui/capability.js +4 -0
- package/lib/orbital/ui/capability.js.map +1 -1
- package/lib/overlay/ui/OverlayBar.d.ts +1 -1
- package/lib/overlay/ui/OverlayBar.d.ts.map +1 -1
- package/lib/overlay/ui/OverlayBar.js +6 -3
- package/lib/overlay/ui/OverlayBar.js.map +1 -1
- package/lib/overlay/ui/OverlayInfo.d.ts +1 -1
- package/lib/overlay/ui/OverlayInfo.d.ts.map +1 -1
- package/lib/overlay/ui/OverlayInfo.js +5 -2
- package/lib/overlay/ui/OverlayInfo.js.map +1 -1
- package/lib/overlay/ui/OverlayPanel.d.ts +9 -2
- package/lib/overlay/ui/OverlayPanel.d.ts.map +1 -1
- package/lib/overlay/ui/OverlayPanel.js +5 -11
- package/lib/overlay/ui/OverlayPanel.js.map +1 -1
- package/lib/overlay/ui/OverlayReadout.d.ts.map +1 -1
- package/lib/overlay/ui/OverlayReadout.js +3 -1
- package/lib/overlay/ui/OverlayReadout.js.map +1 -1
- package/lib/pedagogy/ui/ExerciseActions.d.ts +1 -1
- package/lib/pedagogy/ui/ExerciseActions.d.ts.map +1 -1
- package/lib/pedagogy/ui/ExerciseActions.js +9 -2
- package/lib/pedagogy/ui/ExerciseActions.js.map +1 -1
- package/lib/pedagogy/ui/ExerciseProgressHeader.d.ts +1 -1
- package/lib/pedagogy/ui/ExerciseProgressHeader.d.ts.map +1 -1
- package/lib/pedagogy/ui/ExerciseProgressHeader.js +9 -5
- package/lib/pedagogy/ui/ExerciseProgressHeader.js.map +1 -1
- package/lib/pedagogy/ui/GlossaryIndex.d.ts +1 -1
- package/lib/pedagogy/ui/GlossaryIndex.d.ts.map +1 -1
- package/lib/pedagogy/ui/GlossaryIndex.js +6 -8
- package/lib/pedagogy/ui/GlossaryIndex.js.map +1 -1
- package/lib/pedagogy/ui/HintLadder.d.ts +2 -2
- package/lib/pedagogy/ui/HintLadder.d.ts.map +1 -1
- package/lib/pedagogy/ui/HintLadder.js +8 -2
- package/lib/pedagogy/ui/HintLadder.js.map +1 -1
- package/lib/pedagogy/ui/SyntaxTooltip.d.ts +4 -4
- package/lib/pedagogy/ui/SyntaxTooltip.d.ts.map +1 -1
- package/lib/pedagogy/ui/SyntaxTooltip.js +4 -2
- package/lib/pedagogy/ui/SyntaxTooltip.js.map +1 -1
- package/lib/pedagogy/ui/TutorialStepStrip.d.ts.map +1 -1
- package/lib/pedagogy/ui/TutorialStepStrip.js +7 -2
- package/lib/pedagogy/ui/TutorialStepStrip.js.map +1 -1
- package/lib/periodic/ui/CategoryLegend.d.ts.map +1 -1
- package/lib/periodic/ui/CategoryLegend.js +3 -1
- package/lib/periodic/ui/CategoryLegend.js.map +1 -1
- package/lib/periodic/ui/ElementCell.d.ts.map +1 -1
- package/lib/periodic/ui/ElementCell.js +7 -1
- package/lib/periodic/ui/ElementCell.js.map +1 -1
- package/lib/periodic/ui/PeriodicTable.d.ts.map +1 -1
- package/lib/periodic/ui/PeriodicTable.js +3 -1
- package/lib/periodic/ui/PeriodicTable.js.map +1 -1
- package/lib/periodic/ui/PeriodicTableChrome.d.ts.map +1 -1
- package/lib/periodic/ui/PeriodicTableChrome.js +4 -2
- package/lib/periodic/ui/PeriodicTableChrome.js.map +1 -1
- package/lib/share/ui/ShareButton.d.ts +2 -2
- package/lib/share/ui/ShareButton.d.ts.map +1 -1
- package/lib/share/ui/ShareButton.js +5 -2
- package/lib/share/ui/ShareButton.js.map +1 -1
- package/lib/share/ui/ShareConfigOptions.d.ts.map +1 -1
- package/lib/share/ui/ShareConfigOptions.js +4 -2
- package/lib/share/ui/ShareConfigOptions.js.map +1 -1
- package/lib/share/ui/ShareDialog.d.ts.map +1 -1
- package/lib/share/ui/ShareDialog.js +3 -1
- package/lib/share/ui/ShareDialog.js.map +1 -1
- package/lib/share/ui/ShareDialogContent.d.ts.map +1 -1
- package/lib/share/ui/ShareDialogContent.js +10 -1
- package/lib/share/ui/ShareDialogContent.js.map +1 -1
- package/lib/share/ui/SharePresetTabs.d.ts.map +1 -1
- package/lib/share/ui/SharePresetTabs.js +3 -1
- package/lib/share/ui/SharePresetTabs.js.map +1 -1
- package/lib/slides/ui/BackToSlides.d.ts.map +1 -1
- package/lib/slides/ui/BackToSlides.js +4 -2
- package/lib/slides/ui/BackToSlides.js.map +1 -1
- package/lib/slides/ui/EmbedSlide.d.ts.map +1 -1
- package/lib/slides/ui/EmbedSlide.js +3 -1
- package/lib/slides/ui/EmbedSlide.js.map +1 -1
- package/lib/slides/ui/Slide.d.ts.map +1 -1
- package/lib/slides/ui/Slide.js +3 -1
- package/lib/slides/ui/Slide.js.map +1 -1
- package/lib/slides/ui/SlideshowBar.d.ts.map +1 -1
- package/lib/slides/ui/SlideshowBar.js +5 -3
- package/lib/slides/ui/SlideshowBar.js.map +1 -1
- package/lib/slides/ui/TalkList.d.ts +1 -1
- package/lib/slides/ui/TalkList.d.ts.map +1 -1
- package/lib/slides/ui/TalkList.js +4 -2
- package/lib/slides/ui/TalkList.js.map +1 -1
- package/lib/structure/core/editorGuide.d.ts +14 -0
- package/lib/structure/core/editorGuide.d.ts.map +1 -1
- package/lib/structure/core/editorGuide.js +117 -19
- package/lib/structure/core/editorGuide.js.map +1 -1
- package/lib/structure/core/editorToolbar.d.ts +3 -1
- package/lib/structure/core/editorToolbar.d.ts.map +1 -1
- package/lib/structure/core/editorToolbar.js +44 -23
- package/lib/structure/core/editorToolbar.js.map +1 -1
- package/lib/structure/ui/EditorHelpButton.d.ts.map +1 -1
- package/lib/structure/ui/EditorHelpButton.js +3 -2
- package/lib/structure/ui/EditorHelpButton.js.map +1 -1
- package/lib/structure/ui/StructureEditor.d.ts.map +1 -1
- package/lib/structure/ui/StructureEditor.js +3 -1
- package/lib/structure/ui/StructureEditor.js.map +1 -1
- package/lib/structure/ui/StructureEditorHelp.d.ts.map +1 -1
- package/lib/structure/ui/StructureEditorHelp.js +12 -3
- package/lib/structure/ui/StructureEditorHelp.js.map +1 -1
- package/lib/structure/ui/ToolbarTooltip.d.ts.map +1 -1
- package/lib/structure/ui/ToolbarTooltip.js +5 -3
- package/lib/structure/ui/ToolbarTooltip.js.map +1 -1
- package/lib/ui.d.ts +1 -0
- package/lib/ui.d.ts.map +1 -1
- package/lib/ui.js +1 -0
- package/lib/ui.js.map +1 -1
- package/package.json +4 -2
- package/src/about/ui/AboutBuild.tsx +23 -16
- package/src/about/ui/AboutCitations.tsx +3 -1
- package/src/about/ui/AboutPage.tsx +38 -12
- package/src/about/ui/AboutProvidedBy.tsx +13 -3
- package/src/capsule/ui/Capsule.tsx +48 -0
- package/src/capsule/ui/CapsuleFilter.tsx +38 -114
- package/src/capsule/ui/capsuleFilterCapsules.tsx +110 -0
- package/src/chart/ui/ChartTrackingLayer.tsx +4 -2
- package/src/chrome/ui/SiteHeader.tsx +5 -3
- package/src/citation/ui/CitationMenu.tsx +9 -5
- package/src/citation/ui/CiteButton.tsx +4 -2
- package/src/citation/ui/CopyFormatEntries.tsx +3 -1
- package/src/citation/ui/WorkEntry.tsx +5 -3
- package/src/citation/ui/entries.tsx +9 -2
- package/src/citation/ui/useCopyFeedback.ts +11 -4
- package/src/clipboard/ui/ClickToCopy.tsx +15 -5
- package/src/clipboard/ui/CopyButton.tsx +14 -10
- package/src/color/ui/ColorScaleEditor.tsx +17 -15
- package/src/color/ui/ColorScaleEntry.tsx +7 -3
- package/src/color/ui/ColorScaleLegend.tsx +7 -1
- package/src/color/ui/ColorScaleSelect.tsx +12 -6
- package/src/confirm/ui/ConfirmButton.tsx +9 -11
- package/src/core.ts +1 -0
- package/src/credits/ui/CreditsList.tsx +5 -1
- package/src/delimited/ui/DelimitedTextDialog.tsx +10 -10
- package/src/delimited/ui/DelimitedTextPanel.tsx +19 -12
- package/src/deploy/core/checkDeploy.ts +7 -1
- package/src/deploy/core/index.ts +1 -0
- package/src/deploy/core/pageCache.ts +120 -0
- package/src/deploy/core/types.ts +2 -1
- package/src/download/ui/FigureDownload.tsx +7 -5
- package/src/download/ui/FigureDownloadPanel.tsx +31 -25
- package/src/ecosystem/ui/EcosystemButton.tsx +5 -3
- package/src/ecosystem/ui/EcosystemLinks.tsx +10 -10
- package/src/ecosystem/ui/EcosystemMenu.tsx +3 -1
- package/src/ecosystem/ui/SiteGroupSection.tsx +6 -2
- package/src/ecosystem/ui/SiteTile.tsx +6 -2
- package/src/error/ui/ErrorFallback.tsx +13 -12
- package/src/help/ui/HelpBody.tsx +4 -2
- package/src/help/ui/HelpIcon.tsx +6 -3
- package/src/help/ui/HelpToolbarButton.tsx +4 -1
- package/src/help/ui/helpName.ts +10 -2
- package/src/i18n/core/chromeCatalog.ts +35 -0
- package/src/i18n/core/index.ts +26 -0
- package/src/i18n/core/languages.ts +46 -0
- package/src/i18n/core/messageCatalog.ts +202 -0
- package/src/i18n/core/messageValues.ts +2 -0
- package/src/i18n/core/session.ts +82 -0
- package/src/i18n/core/translateSetup.ts +47 -0
- package/src/i18n/ui/LanguageSelect.tsx +72 -0
- package/src/i18n/ui/index.ts +9 -0
- package/src/i18n/ui/useLanguage.ts +48 -0
- package/src/i18n/ui/useT.ts +90 -0
- package/src/locales/de.json +442 -0
- package/src/locales/en.json +442 -0
- package/src/locales/es.json +442 -0
- package/src/locales/fr.json +442 -0
- package/src/molecule3d/core/gestures.ts +44 -7
- package/src/molecule3d/ui/Molecule3DExport.tsx +3 -1
- package/src/molecule3d/ui/Molecule3DHelp.tsx +17 -6
- package/src/molecule3d/ui/Molecule3DOptions.tsx +13 -13
- package/src/molecule3d/ui/Molecule3DSurfaceColors.tsx +16 -13
- package/src/molecule3d/ui/Molecule3DToolbar.tsx +29 -18
- package/src/molecule3d/ui/MoleculeViewer3D.tsx +13 -8
- package/src/orbital/ui/AtomicOrbitalCanvas.tsx +3 -1
- package/src/orbital/ui/AtomicOrbitalControls.tsx +15 -20
- package/src/orbital/ui/AtomicOrbitalViewer.tsx +13 -13
- package/src/orbital/ui/capability.ts +10 -0
- package/src/overlay/ui/OverlayBar.tsx +7 -4
- package/src/overlay/ui/OverlayInfo.tsx +6 -3
- package/src/overlay/ui/OverlayPanel.tsx +10 -7
- package/src/overlay/ui/OverlayReadout.tsx +3 -1
- package/src/pedagogy/ui/ExerciseActions.tsx +16 -6
- package/src/pedagogy/ui/ExerciseProgressHeader.tsx +13 -11
- package/src/pedagogy/ui/GlossaryIndex.tsx +11 -12
- package/src/pedagogy/ui/HintLadder.tsx +15 -12
- package/src/pedagogy/ui/SyntaxTooltip.tsx +9 -7
- package/src/pedagogy/ui/TutorialStepStrip.tsx +8 -3
- package/src/periodic/ui/CategoryLegend.tsx +6 -1
- package/src/periodic/ui/ElementCell.tsx +7 -1
- package/src/periodic/ui/PeriodicTable.tsx +3 -1
- package/src/periodic/ui/PeriodicTableChrome.tsx +4 -2
- package/src/share/ui/ShareButton.tsx +8 -5
- package/src/share/ui/ShareConfigOptions.tsx +6 -7
- package/src/share/ui/ShareDialog.tsx +3 -1
- package/src/share/ui/ShareDialogContent.tsx +20 -10
- package/src/share/ui/SharePresetTabs.tsx +3 -1
- package/src/slides/ui/BackToSlides.tsx +4 -2
- package/src/slides/ui/EmbedSlide.tsx +3 -3
- package/src/slides/ui/Slide.tsx +3 -1
- package/src/slides/ui/SlideshowBar.tsx +12 -4
- package/src/slides/ui/TalkList.tsx +8 -10
- package/src/structure/core/editorGuide.ts +126 -19
- package/src/structure/core/editorToolbar.ts +52 -24
- package/src/structure/ui/EditorHelpButton.tsx +9 -4
- package/src/structure/ui/StructureEditor.tsx +7 -1
- package/src/structure/ui/StructureEditorHelp.tsx +34 -11
- package/src/structure/ui/ToolbarTooltip.tsx +8 -4
- package/src/ui.ts +1 -0
|
@@ -2,6 +2,8 @@ import type { IconName, Intent } from '@blueprintjs/core';
|
|
|
2
2
|
import { Button } from '@blueprintjs/core';
|
|
3
3
|
import type { ReactElement } from 'react';
|
|
4
4
|
|
|
5
|
+
import { useChromeT } from '../../i18n/ui/useT.ts';
|
|
6
|
+
|
|
5
7
|
import {
|
|
6
8
|
DEFAULT_COPY_RESET_AFTER,
|
|
7
9
|
useCopyToClipboard,
|
|
@@ -24,12 +26,12 @@ export interface CopyButtonProps {
|
|
|
24
26
|
label?: string;
|
|
25
27
|
/**
|
|
26
28
|
* Text shown while the copy is being confirmed, when there is a label.
|
|
27
|
-
* @default '
|
|
29
|
+
* @default the chrome's own word for it, in the language of the page
|
|
28
30
|
*/
|
|
29
31
|
copiedLabel?: string;
|
|
30
32
|
/**
|
|
31
33
|
* Text shown while a refused copy is being reported, when there is a label.
|
|
32
|
-
* @default '
|
|
34
|
+
* @default the chrome's own line, in the language of the page
|
|
33
35
|
*/
|
|
34
36
|
failedLabel?: string;
|
|
35
37
|
/**
|
|
@@ -59,7 +61,7 @@ export interface CopyButtonProps {
|
|
|
59
61
|
resetAfter?: number;
|
|
60
62
|
/**
|
|
61
63
|
* What the pointer and a screen reader are told.
|
|
62
|
-
* @default '
|
|
64
|
+
* @default the chrome's own line, in the language of the page
|
|
63
65
|
*/
|
|
64
66
|
title?: string;
|
|
65
67
|
/**
|
|
@@ -79,24 +81,26 @@ export function CopyButton(props: CopyButtonProps): ReactElement {
|
|
|
79
81
|
const {
|
|
80
82
|
content,
|
|
81
83
|
label,
|
|
82
|
-
copiedLabel
|
|
83
|
-
failedLabel
|
|
84
|
+
copiedLabel,
|
|
85
|
+
failedLabel,
|
|
84
86
|
minimal = false,
|
|
85
87
|
small = false,
|
|
86
88
|
icon = 'clipboard',
|
|
87
89
|
disabled = false,
|
|
88
90
|
resetAfter = DEFAULT_COPY_RESET_AFTER,
|
|
89
|
-
title
|
|
91
|
+
title,
|
|
90
92
|
className,
|
|
91
93
|
} = props;
|
|
94
|
+
const t = useChromeT();
|
|
92
95
|
const { copied, failed, copy } = useCopyToClipboard(resetAfter);
|
|
96
|
+
const hoverTitle = title ?? t('clipboard.copyToClipboard');
|
|
93
97
|
const look = buttonLook({
|
|
94
98
|
copied,
|
|
95
99
|
failed,
|
|
96
100
|
icon,
|
|
97
101
|
label,
|
|
98
|
-
copiedLabel,
|
|
99
|
-
failedLabel,
|
|
102
|
+
copiedLabel: copiedLabel ?? t('clipboard.copied'),
|
|
103
|
+
failedLabel: failedLabel ?? t('clipboard.failed'),
|
|
100
104
|
});
|
|
101
105
|
|
|
102
106
|
return (
|
|
@@ -108,8 +112,8 @@ export function CopyButton(props: CopyButtonProps): ReactElement {
|
|
|
108
112
|
intent={look.intent}
|
|
109
113
|
text={look.text}
|
|
110
114
|
disabled={disabled}
|
|
111
|
-
title={
|
|
112
|
-
aria-label={label ??
|
|
115
|
+
title={hoverTitle}
|
|
116
|
+
aria-label={label ?? hoverTitle}
|
|
113
117
|
onClick={() => {
|
|
114
118
|
void copy(typeof content === 'function' ? content() : content);
|
|
115
119
|
}}
|
|
@@ -2,6 +2,7 @@ import { Button, HTMLSelect } from '@blueprintjs/core';
|
|
|
2
2
|
import type { CSSProperties, ReactElement } from 'react';
|
|
3
3
|
|
|
4
4
|
import { formatDecimal } from '../../format/core/numbers.ts';
|
|
5
|
+
import { useChromeT } from '../../i18n/ui/useT.ts';
|
|
5
6
|
import { normalizeHexColor } from '../core/hex.ts';
|
|
6
7
|
import type {
|
|
7
8
|
ColorInterpolation,
|
|
@@ -22,14 +23,11 @@ const POSITION_DECIMALS = 2;
|
|
|
22
23
|
// hex colour is shown as black until it is picked again.
|
|
23
24
|
const UNREADABLE_COLOR = '#000000';
|
|
24
25
|
|
|
25
|
-
/**
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
{ value: 'rgb', label: 'RGB — mix the channels' },
|
|
31
|
-
{ value: 'hsv', label: 'HSV — turn the short way' },
|
|
32
|
-
{ value: 'hsv-long', label: 'HSV — turn the long way' },
|
|
26
|
+
/** The paths between two anchors, in the order the picker lists them. */
|
|
27
|
+
const INTERPOLATIONS: readonly ColorInterpolation[] = [
|
|
28
|
+
'rgb',
|
|
29
|
+
'hsv',
|
|
30
|
+
'hsv-long',
|
|
33
31
|
];
|
|
34
32
|
|
|
35
33
|
/** What {@link ColorScaleEditor} edits. */
|
|
@@ -57,6 +55,7 @@ export interface ColorScaleEditorProps {
|
|
|
57
55
|
*/
|
|
58
56
|
export function ColorScaleEditor(props: ColorScaleEditorProps): ReactElement {
|
|
59
57
|
const { className, value, onChange } = props;
|
|
58
|
+
const t = useChromeT();
|
|
60
59
|
const stops = value.stops;
|
|
61
60
|
|
|
62
61
|
function write(next: readonly ColorStop[]): void {
|
|
@@ -69,7 +68,7 @@ export function ColorScaleEditor(props: ColorScaleEditorProps): ReactElement {
|
|
|
69
68
|
scale={value}
|
|
70
69
|
height={PREVIEW_HEIGHT}
|
|
71
70
|
samples={PREVIEW_SAMPLES}
|
|
72
|
-
label=
|
|
71
|
+
label={t('color.scaleBeingEdited')}
|
|
73
72
|
/>
|
|
74
73
|
|
|
75
74
|
<div style={ROWS_STYLE}>
|
|
@@ -77,7 +76,7 @@ export function ColorScaleEditor(props: ColorScaleEditorProps): ReactElement {
|
|
|
77
76
|
<div key={`${String(index)}-${stop.color}`} style={ROW_STYLE}>
|
|
78
77
|
<input
|
|
79
78
|
type="color"
|
|
80
|
-
aria-label={
|
|
79
|
+
aria-label={t('color.anchorColour', { index: index + 1 })}
|
|
81
80
|
value={normalizeHexColor(stop.color) ?? UNREADABLE_COLOR}
|
|
82
81
|
style={SWATCH_STYLE}
|
|
83
82
|
onChange={(event) => {
|
|
@@ -86,7 +85,7 @@ export function ColorScaleEditor(props: ColorScaleEditorProps): ReactElement {
|
|
|
86
85
|
/>
|
|
87
86
|
<input
|
|
88
87
|
type="range"
|
|
89
|
-
aria-label={
|
|
88
|
+
aria-label={t('color.anchorPosition', { index: index + 1 })}
|
|
90
89
|
min={0}
|
|
91
90
|
max={1}
|
|
92
91
|
step={POSITION_STEP}
|
|
@@ -107,7 +106,7 @@ export function ColorScaleEditor(props: ColorScaleEditorProps): ReactElement {
|
|
|
107
106
|
icon="cross"
|
|
108
107
|
variant="minimal"
|
|
109
108
|
size="small"
|
|
110
|
-
aria-label={
|
|
109
|
+
aria-label={t('color.removeAnchor', { index: index + 1 })}
|
|
111
110
|
disabled={stops.length <= MINIMUM_STOPS}
|
|
112
111
|
onClick={() => {
|
|
113
112
|
write(stops.filter((_, at) => at !== index));
|
|
@@ -121,16 +120,19 @@ export function ColorScaleEditor(props: ColorScaleEditorProps): ReactElement {
|
|
|
121
120
|
<Button
|
|
122
121
|
icon="plus"
|
|
123
122
|
size="small"
|
|
124
|
-
text=
|
|
123
|
+
text={t('color.addColour')}
|
|
125
124
|
disabled={stops.length >= MAXIMUM_CUSTOM_STOPS}
|
|
126
125
|
onClick={() => {
|
|
127
126
|
write(withAddedStop(value));
|
|
128
127
|
}}
|
|
129
128
|
/>
|
|
130
129
|
<HTMLSelect
|
|
131
|
-
aria-label=
|
|
130
|
+
aria-label={t('color.path')}
|
|
132
131
|
value={value.interpolation}
|
|
133
|
-
options={
|
|
132
|
+
options={INTERPOLATIONS.map((interpolation) => ({
|
|
133
|
+
value: interpolation,
|
|
134
|
+
label: t(`color.interpolation.${interpolation}`),
|
|
135
|
+
}))}
|
|
134
136
|
onChange={(event) => {
|
|
135
137
|
onChange({
|
|
136
138
|
stops,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { MenuDivider, MenuItem } from '@blueprintjs/core';
|
|
2
2
|
import type { CSSProperties, ReactElement } from 'react';
|
|
3
3
|
|
|
4
|
+
import { useChromeT } from '../../i18n/ui/useT.ts';
|
|
4
5
|
import { resolveColorScale } from '../core/scaleText.ts';
|
|
5
6
|
import type { ColorScaleKind } from '../core/scales.ts';
|
|
6
7
|
import { COLOR_SCALE_KIND_LABELS } from '../core/scales.ts';
|
|
@@ -33,14 +34,15 @@ interface ColorScaleEntryProps {
|
|
|
33
34
|
*/
|
|
34
35
|
export function ColorScaleEntry(props: ColorScaleEntryProps): ReactElement {
|
|
35
36
|
const { id, label, kind, description, previous, selected, onChange } = props;
|
|
37
|
+
const t = useChromeT();
|
|
36
38
|
const entry = (
|
|
37
39
|
<MenuItem
|
|
38
40
|
roleStructure="listoption"
|
|
39
41
|
selected={selected}
|
|
40
|
-
htmlTitle={description}
|
|
42
|
+
htmlTitle={t.or(`color.scale.${id}.description`, description)}
|
|
41
43
|
text={
|
|
42
44
|
<span style={ITEM_STYLE}>
|
|
43
|
-
<span>{label}</span>
|
|
45
|
+
<span>{t.or(`color.scale.${id}.label`, label)}</span>
|
|
44
46
|
<ColorScaleBar scale={resolveColorScale(id).scale} />
|
|
45
47
|
</span>
|
|
46
48
|
}
|
|
@@ -52,7 +54,9 @@ export function ColorScaleEntry(props: ColorScaleEntryProps): ReactElement {
|
|
|
52
54
|
if (previous === kind) return entry;
|
|
53
55
|
return (
|
|
54
56
|
<>
|
|
55
|
-
<MenuDivider
|
|
57
|
+
<MenuDivider
|
|
58
|
+
title={t.or(`color.kind.${kind}`, COLOR_SCALE_KIND_LABELS[kind])}
|
|
59
|
+
/>
|
|
56
60
|
{entry}
|
|
57
61
|
</>
|
|
58
62
|
);
|
|
@@ -2,6 +2,7 @@ import type { CSSProperties, ReactElement } from 'react';
|
|
|
2
2
|
import { useId } from 'react';
|
|
3
3
|
|
|
4
4
|
import { formatTrimmed } from '../../format/core/numbers.ts';
|
|
5
|
+
import { useChromeT } from '../../i18n/ui/useT.ts';
|
|
5
6
|
import { TOKEN } from '../../tokens/core/familyTokens.ts';
|
|
6
7
|
import type { ColorScale } from '../core/interpolate.ts';
|
|
7
8
|
import { evenScale, sampleScale } from '../core/interpolate.ts';
|
|
@@ -66,6 +67,7 @@ export function ColorScaleLegend(props: ColorScaleLegendProps): ReactElement {
|
|
|
66
67
|
label = '',
|
|
67
68
|
formatValue = defaultFormatValue,
|
|
68
69
|
} = props;
|
|
70
|
+
const t = useChromeT();
|
|
69
71
|
const gradientId = useId();
|
|
70
72
|
|
|
71
73
|
const stops = gradientStops('stops' in scale ? scale : evenScale(scale));
|
|
@@ -81,7 +83,11 @@ export function ColorScaleLegend(props: ColorScaleLegendProps): ReactElement {
|
|
|
81
83
|
viewBox={`0 0 ${BAR_WIDTH} ${BAR_HEIGHT}`}
|
|
82
84
|
preserveAspectRatio="none"
|
|
83
85
|
role="img"
|
|
84
|
-
aria-label={
|
|
86
|
+
aria-label={t('color.legendLabel', {
|
|
87
|
+
what: label === '' ? t('color.colourScale') : label,
|
|
88
|
+
low,
|
|
89
|
+
high,
|
|
90
|
+
})}
|
|
85
91
|
>
|
|
86
92
|
{stops.length === 0 ? null : (
|
|
87
93
|
<defs>
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
import type { CSSProperties, ReactElement } from 'react';
|
|
9
9
|
import { useState } from 'react';
|
|
10
10
|
|
|
11
|
+
import { useChromeT } from '../../i18n/ui/useT.ts';
|
|
11
12
|
import { TOKEN } from '../../tokens/core/familyTokens.ts';
|
|
12
13
|
import { formatColorScale, resolveColorScale } from '../core/scaleText.ts';
|
|
13
14
|
import { COLOR_SCALES } from '../core/scales.ts';
|
|
@@ -68,6 +69,7 @@ export function ColorScaleSelect(props: ColorScaleSelectProps): ReactElement {
|
|
|
68
69
|
allowCustom = true,
|
|
69
70
|
testId,
|
|
70
71
|
} = props;
|
|
72
|
+
const t = useChromeT();
|
|
71
73
|
const [isOpen, setOpen] = useState(false);
|
|
72
74
|
const [isEditing, setEditing] = useState(false);
|
|
73
75
|
const resolved = resolveColorScale(value);
|
|
@@ -79,14 +81,14 @@ export function ColorScaleSelect(props: ColorScaleSelectProps): ReactElement {
|
|
|
79
81
|
icon="chevron-left"
|
|
80
82
|
variant="minimal"
|
|
81
83
|
size="small"
|
|
82
|
-
text=
|
|
84
|
+
text={t('color.scales')}
|
|
83
85
|
onClick={() => {
|
|
84
86
|
setEditing(false);
|
|
85
87
|
}}
|
|
86
88
|
/>
|
|
87
89
|
<Button
|
|
88
90
|
size="small"
|
|
89
|
-
text=
|
|
91
|
+
text={t('color.done')}
|
|
90
92
|
onClick={() => {
|
|
91
93
|
setEditing(false);
|
|
92
94
|
setOpen(false);
|
|
@@ -119,8 +121,8 @@ export function ColorScaleSelect(props: ColorScaleSelectProps): ReactElement {
|
|
|
119
121
|
<MenuDivider />
|
|
120
122
|
<MenuItem
|
|
121
123
|
icon="edit"
|
|
122
|
-
text=
|
|
123
|
-
label={resolved.id === null ? '
|
|
124
|
+
text={t('color.customEllipsis')}
|
|
125
|
+
label={resolved.id === null ? t('color.inUse') : undefined}
|
|
124
126
|
shouldDismissPopover={false}
|
|
125
127
|
onClick={() => {
|
|
126
128
|
setEditing(true);
|
|
@@ -150,13 +152,17 @@ export function ColorScaleSelect(props: ColorScaleSelectProps): ReactElement {
|
|
|
150
152
|
>
|
|
151
153
|
<Button
|
|
152
154
|
alignText="start"
|
|
153
|
-
aria-label={label === '' ? '
|
|
155
|
+
aria-label={label === '' ? t('color.colourScale') : label}
|
|
154
156
|
data-testid={testId}
|
|
155
157
|
endIcon="caret-down"
|
|
156
158
|
fill
|
|
157
159
|
text={
|
|
158
160
|
<span style={BUTTON_TEXT_STYLE}>
|
|
159
|
-
<span>
|
|
161
|
+
<span>
|
|
162
|
+
{resolved.id === null
|
|
163
|
+
? t('color.custom')
|
|
164
|
+
: t.or(`color.scale.${resolved.id}.label`, resolved.label)}
|
|
165
|
+
</span>
|
|
160
166
|
<ColorScaleBar
|
|
161
167
|
scale={resolved.scale}
|
|
162
168
|
style={{ width: BUTTON_BAR_WIDTH }}
|
|
@@ -3,6 +3,8 @@ import { Alert, Button } from '@blueprintjs/core';
|
|
|
3
3
|
import type { ReactElement, ReactNode } from 'react';
|
|
4
4
|
import { useState } from 'react';
|
|
5
5
|
|
|
6
|
+
import { useChromeT } from '../../i18n/ui/useT.ts';
|
|
7
|
+
|
|
6
8
|
/** Props of {@link ConfirmButton}: a Blueprint button, and what it asks. */
|
|
7
9
|
export interface ConfirmButtonProps extends Omit<ButtonProps, 'onClick'> {
|
|
8
10
|
/**
|
|
@@ -14,12 +16,12 @@ export interface ConfirmButtonProps extends Omit<ButtonProps, 'onClick'> {
|
|
|
14
16
|
onConfirm: () => void;
|
|
15
17
|
/**
|
|
16
18
|
* Text of the button that goes ahead: the verb of what happens, never `OK`.
|
|
17
|
-
* @default '
|
|
19
|
+
* @default the chrome's own word for it, in the language of the page
|
|
18
20
|
*/
|
|
19
21
|
confirmLabel?: string;
|
|
20
22
|
/**
|
|
21
23
|
* Text of the button that backs out.
|
|
22
|
-
* @default '
|
|
24
|
+
* @default the chrome's own word for it, in the language of the page
|
|
23
25
|
*/
|
|
24
26
|
cancelLabel?: string;
|
|
25
27
|
}
|
|
@@ -35,13 +37,9 @@ export interface ConfirmButtonProps extends Omit<ButtonProps, 'onClick'> {
|
|
|
35
37
|
* @returns The button, and the alert it opens.
|
|
36
38
|
*/
|
|
37
39
|
export function ConfirmButton(props: ConfirmButtonProps): ReactElement {
|
|
38
|
-
const {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
confirmLabel = 'Delete',
|
|
42
|
-
cancelLabel = 'Cancel',
|
|
43
|
-
...buttonProps
|
|
44
|
-
} = props;
|
|
40
|
+
const { question, onConfirm, confirmLabel, cancelLabel, ...buttonProps } =
|
|
41
|
+
props;
|
|
42
|
+
const t = useChromeT();
|
|
45
43
|
const [asking, setAsking] = useState(false);
|
|
46
44
|
|
|
47
45
|
return (
|
|
@@ -58,8 +56,8 @@ export function ConfirmButton(props: ConfirmButtonProps): ReactElement {
|
|
|
58
56
|
icon={alertIcon(buttonProps.icon)}
|
|
59
57
|
canEscapeKeyCancel
|
|
60
58
|
canOutsideClickCancel
|
|
61
|
-
cancelButtonText={cancelLabel}
|
|
62
|
-
confirmButtonText={confirmLabel}
|
|
59
|
+
cancelButtonText={cancelLabel ?? t('confirm.cancel')}
|
|
60
|
+
confirmButtonText={confirmLabel ?? t('confirm.delete')}
|
|
63
61
|
onCancel={() => {
|
|
64
62
|
setAsking(false);
|
|
65
63
|
}}
|
package/src/core.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * from './download/core/index.ts';
|
|
|
10
10
|
export * from './ecosystem/core/index.ts';
|
|
11
11
|
export * from './error/core/index.ts';
|
|
12
12
|
export * from './format/core/index.ts';
|
|
13
|
+
export * from './i18n/core/index.ts';
|
|
13
14
|
export * from './language/core/index.ts';
|
|
14
15
|
export * from './orbital/core/index.ts';
|
|
15
16
|
export * from './overlay/core/index.ts';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CSSProperties, ReactElement } from 'react';
|
|
2
2
|
|
|
3
|
+
import { useChromeT } from '../../i18n/ui/useT.ts';
|
|
3
4
|
import { joinClassNames } from '../../shared/ui/joinClassNames.ts';
|
|
4
5
|
import { TOKEN } from '../../tokens/core/familyTokens.ts';
|
|
5
6
|
import type { CreditEntry } from '../core/credits.ts';
|
|
@@ -32,6 +33,7 @@ export interface CreditsListProps {
|
|
|
32
33
|
*/
|
|
33
34
|
export function CreditsList(props: CreditsListProps): ReactElement {
|
|
34
35
|
const { entries, showLicense = true, className } = props;
|
|
36
|
+
const t = useChromeT();
|
|
35
37
|
|
|
36
38
|
return (
|
|
37
39
|
<ul
|
|
@@ -53,7 +55,9 @@ export function CreditsList(props: CreditsListProps): ReactElement {
|
|
|
53
55
|
) : (
|
|
54
56
|
' '
|
|
55
57
|
)}
|
|
56
|
-
<span>
|
|
58
|
+
<span>
|
|
59
|
+
{t.or(`credits.${entry.id}.description`, entry.description)}
|
|
60
|
+
</span>
|
|
57
61
|
</li>
|
|
58
62
|
))}
|
|
59
63
|
</ul>
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Button, Dialog, DialogBody, DialogFooter } from '@blueprintjs/core';
|
|
2
2
|
import type { CSSProperties, ReactElement } from 'react';
|
|
3
3
|
|
|
4
|
+
import { useChromeT } from '../../i18n/ui/useT.ts';
|
|
5
|
+
|
|
4
6
|
import type { DelimitedTextPanelProps } from './DelimitedTextPanel.tsx';
|
|
5
7
|
import { DelimitedTextPanel } from './DelimitedTextPanel.tsx';
|
|
6
8
|
|
|
@@ -26,27 +28,25 @@ export interface DelimitedTextDialogProps extends DelimitedTextPanelProps {
|
|
|
26
28
|
export function DelimitedTextDialog(
|
|
27
29
|
props: DelimitedTextDialogProps,
|
|
28
30
|
): ReactElement {
|
|
29
|
-
const {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
title = 'Copy the table',
|
|
33
|
-
className,
|
|
34
|
-
...panel
|
|
35
|
-
} = props;
|
|
31
|
+
const { isOpen, onClose, title, className, ...panel } = props;
|
|
32
|
+
const t = useChromeT();
|
|
33
|
+
const heading = title ?? t('delimited.copyTable');
|
|
36
34
|
|
|
37
35
|
return (
|
|
38
36
|
<Dialog
|
|
39
37
|
isOpen={isOpen}
|
|
40
38
|
onClose={onClose}
|
|
41
|
-
title={
|
|
39
|
+
title={heading}
|
|
42
40
|
icon="th"
|
|
43
41
|
className={className}
|
|
44
42
|
style={DIALOG_STYLE}
|
|
45
43
|
>
|
|
46
44
|
<DialogBody>
|
|
47
|
-
<DelimitedTextPanel {...panel} label={panel.label ??
|
|
45
|
+
<DelimitedTextPanel {...panel} label={panel.label ?? heading} />
|
|
48
46
|
</DialogBody>
|
|
49
|
-
<DialogFooter
|
|
47
|
+
<DialogFooter
|
|
48
|
+
actions={<Button text={t('delimited.close')} onClick={onClose} />}
|
|
49
|
+
/>
|
|
50
50
|
</Dialog>
|
|
51
51
|
);
|
|
52
52
|
}
|
|
@@ -6,7 +6,7 @@ import { CopyButton } from '../../clipboard/ui/CopyButton.tsx';
|
|
|
6
6
|
import { downloadText } from '../../download/core/downloadText.ts';
|
|
7
7
|
import { sanitizeFileName } from '../../download/core/sanitizeFileName.ts';
|
|
8
8
|
import { formatInteger } from '../../format/core/numbers.ts';
|
|
9
|
-
import {
|
|
9
|
+
import { useChromeT } from '../../i18n/ui/useT.ts';
|
|
10
10
|
import { joinClassNames } from '../../shared/ui/joinClassNames.ts';
|
|
11
11
|
import { TOKEN } from '../../tokens/core/familyTokens.ts';
|
|
12
12
|
import type { DelimiterId } from '../core/delimiters.ts';
|
|
@@ -82,9 +82,10 @@ export function DelimitedTextPanel(
|
|
|
82
82
|
fileName = 'table',
|
|
83
83
|
defaultDelimiter = 'tab',
|
|
84
84
|
downloadable = true,
|
|
85
|
-
label
|
|
85
|
+
label,
|
|
86
86
|
height = 320,
|
|
87
87
|
} = props;
|
|
88
|
+
const t = useChromeT();
|
|
88
89
|
const [delimiterId, setDelimiterId] = useState<string>(defaultDelimiter);
|
|
89
90
|
|
|
90
91
|
const choice = delimiterChoice(delimiterId);
|
|
@@ -96,10 +97,16 @@ export function DelimitedTextPanel(
|
|
|
96
97
|
return (
|
|
97
98
|
<div className={joinClassNames('delimited-text', className)}>
|
|
98
99
|
<Callout intent="primary" compact icon="info-sign">
|
|
99
|
-
{description ??
|
|
100
|
+
{description ??
|
|
101
|
+
t(
|
|
102
|
+
rows.length === 1
|
|
103
|
+
? 'delimited.descriptionOne'
|
|
104
|
+
: 'delimited.descriptionMany',
|
|
105
|
+
{ count: formatInteger(rows.length) },
|
|
106
|
+
)}
|
|
100
107
|
</Callout>
|
|
101
108
|
<div style={CONTROLS_STYLE}>
|
|
102
|
-
<span style={LABEL_STYLE}>
|
|
109
|
+
<span style={LABEL_STYLE}>{t('delimited.separator')}</span>
|
|
103
110
|
<SegmentedControl
|
|
104
111
|
size="small"
|
|
105
112
|
options={DELIMITER_CHOICES.map((option) => ({
|
|
@@ -113,7 +120,7 @@ export function DelimitedTextPanel(
|
|
|
113
120
|
{downloadable ? (
|
|
114
121
|
<Button
|
|
115
122
|
icon="download"
|
|
116
|
-
text=
|
|
123
|
+
text={t('delimited.save')}
|
|
117
124
|
size="small"
|
|
118
125
|
onClick={() =>
|
|
119
126
|
downloadText(
|
|
@@ -124,13 +131,18 @@ export function DelimitedTextPanel(
|
|
|
124
131
|
}
|
|
125
132
|
/>
|
|
126
133
|
) : null}
|
|
127
|
-
<CopyButton
|
|
134
|
+
<CopyButton
|
|
135
|
+
content={text}
|
|
136
|
+
label={t('delimited.copy')}
|
|
137
|
+
icon="clipboard"
|
|
138
|
+
small
|
|
139
|
+
/>
|
|
128
140
|
</div>
|
|
129
141
|
<textarea
|
|
130
142
|
readOnly
|
|
131
143
|
value={text}
|
|
132
144
|
spellCheck={false}
|
|
133
|
-
aria-label={label}
|
|
145
|
+
aria-label={label ?? t('delimited.tableAsText')}
|
|
134
146
|
className={Classes.INPUT}
|
|
135
147
|
style={{ ...TEXT_STYLE, height }}
|
|
136
148
|
onFocus={(event) => event.currentTarget.select()}
|
|
@@ -139,11 +151,6 @@ export function DelimitedTextPanel(
|
|
|
139
151
|
);
|
|
140
152
|
}
|
|
141
153
|
|
|
142
|
-
function defaultDescription(rowCount: number): string {
|
|
143
|
-
const rows = `${formatInteger(rowCount)} ${pluralize(rowCount, 'row')}`;
|
|
144
|
-
return `${rows}, one per line. Copy them, then paste into a spreadsheet.`;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
154
|
const CONTROLS_STYLE = {
|
|
148
155
|
display: 'flex',
|
|
149
156
|
flexWrap: 'wrap',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readComposeFile } from './composeFile.ts';
|
|
2
2
|
import { readEnvExample } from './envExample.ts';
|
|
3
|
+
import { readPageCache } from './pageCache.ts';
|
|
3
4
|
import type { CheckDeployOptions, DeployFile, DeployProblem } from './types.ts';
|
|
4
5
|
import { DEPLOY_COMPOSE_FILES } from './types.ts';
|
|
5
6
|
|
|
@@ -12,7 +13,9 @@ import { DEPLOY_COMPOSE_FILES } from './types.ts';
|
|
|
12
13
|
* reports it healthy. So a repository has to hand it a selectable tag on every
|
|
13
14
|
* image we build, an `IMAGE_NAME` that names the package our own workflow
|
|
14
15
|
* publishes, a compose file that parses on a checkout with no `.env` yet, and a
|
|
15
|
-
* health probe to read.
|
|
16
|
+
* health probe to read. It also has to hand the browser a page the browser will
|
|
17
|
+
* not keep, or the next deploy leaves returning visitors on a blank one. Each
|
|
18
|
+
* of those is invisible until a deploy, which is the
|
|
16
19
|
* worst moment to discover it — an `env_file` without `required: false` fails
|
|
17
20
|
* before a container starts, and an `IMAGE_NAME` off by a suffix pulls a
|
|
18
21
|
* package that was never published.
|
|
@@ -68,6 +71,9 @@ export function findDeployProblems(
|
|
|
68
71
|
readEnvExample(envExample, expected, problems);
|
|
69
72
|
}
|
|
70
73
|
|
|
74
|
+
const dockerfile = byPath.get('Dockerfile');
|
|
75
|
+
if (dockerfile !== undefined) readPageCache(dockerfile, byPath, problems);
|
|
76
|
+
|
|
71
77
|
const gitignore = byPath.get('.gitignore');
|
|
72
78
|
if (gitignore === undefined || !/^\s*\/?\.deploy\/?\s*$/m.test(gitignore)) {
|
|
73
79
|
problems.push({
|
package/src/deploy/core/index.ts
CHANGED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { DeployProblem } from './types.ts';
|
|
2
|
+
|
|
3
|
+
/** The page cache policy of a static-web-server site, at the repository root. */
|
|
4
|
+
export const PAGE_CACHE_CONFIG = 'sws.toml';
|
|
5
|
+
|
|
6
|
+
/** The nginx configuration of a site served by nginx. */
|
|
7
|
+
export const NGINX_CONFIG = 'nginx.conf';
|
|
8
|
+
|
|
9
|
+
const NO_CACHE =
|
|
10
|
+
/cache-control[\s:=]+["']?[^"'\n]*(?:no-cache|no-store|max-age=0)/i;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Report a server that lets a browser keep the page itself.
|
|
14
|
+
*
|
|
15
|
+
* A page names the hashed bundles of the build that wrote it, so a browser
|
|
16
|
+
* still holding a copy from an earlier deploy asks the new image for files it
|
|
17
|
+
* does not have; the request falls through to the page, the browser refuses to
|
|
18
|
+
* run HTML as a module, and the site comes up blank until the copy expires.
|
|
19
|
+
* Nothing on the server can see it and no test can either, because a test
|
|
20
|
+
* always loads a page and its bundles from the same build. So it is read off
|
|
21
|
+
* the server's configuration instead: static-web-server hands pages out with
|
|
22
|
+
* `max-age=86400` of its own, and nginx says nothing and lets the browser
|
|
23
|
+
* guess, so both have to be told. The bundles, named by their content, are the
|
|
24
|
+
* one thing worth keeping.
|
|
25
|
+
* @param dockerfile - The Dockerfile, which says what serves the build.
|
|
26
|
+
* @param byPath - Every file that was read, by repository path.
|
|
27
|
+
* @param problems - Where each problem found is appended.
|
|
28
|
+
*/
|
|
29
|
+
export function readPageCache(
|
|
30
|
+
dockerfile: string,
|
|
31
|
+
byPath: ReadonlyMap<string, string>,
|
|
32
|
+
problems: DeployProblem[],
|
|
33
|
+
): void {
|
|
34
|
+
if (dockerfile.includes('static-web-server')) {
|
|
35
|
+
readStaticWebServer(dockerfile, byPath, problems);
|
|
36
|
+
} else if (/^FROM\s+\S*nginx/im.test(dockerfile)) {
|
|
37
|
+
readNginx(byPath, problems);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function readStaticWebServer(
|
|
42
|
+
dockerfile: string,
|
|
43
|
+
byPath: ReadonlyMap<string, string>,
|
|
44
|
+
problems: DeployProblem[],
|
|
45
|
+
): void {
|
|
46
|
+
const named = /^\s*ENV\s+SERVER_CONFIG_FILE=(?<path>\S+)/m.exec(dockerfile);
|
|
47
|
+
const destination = named?.groups?.path;
|
|
48
|
+
if (destination === undefined) {
|
|
49
|
+
problems.push({
|
|
50
|
+
file: 'Dockerfile',
|
|
51
|
+
line: lineOf(dockerfile, /static-web-server/),
|
|
52
|
+
kind: 'cacheable-page',
|
|
53
|
+
message:
|
|
54
|
+
'static-web-server keeps every page in the browser for a day, so each deploy blanks the site for anyone who came by before it',
|
|
55
|
+
hint: `COPY ${PAGE_CACHE_CONFIG} /etc/sws.toml and set SERVER_CONFIG_FILE to it`,
|
|
56
|
+
});
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const copied = new RegExp(
|
|
61
|
+
String.raw`^\s*COPY\s+(?:--\S+\s+)*${escapeRegExp(PAGE_CACHE_CONFIG)}\s+${escapeRegExp(destination)}\s*$`,
|
|
62
|
+
'm',
|
|
63
|
+
);
|
|
64
|
+
if (!copied.test(dockerfile)) {
|
|
65
|
+
problems.push({
|
|
66
|
+
file: 'Dockerfile',
|
|
67
|
+
line: lineOf(dockerfile, /^\s*ENV\s+SERVER_CONFIG_FILE=/m),
|
|
68
|
+
kind: 'cacheable-page',
|
|
69
|
+
message: `SERVER_CONFIG_FILE names ${destination}, which nothing puts there`,
|
|
70
|
+
hint: `COPY ${PAGE_CACHE_CONFIG} ${destination}`,
|
|
71
|
+
});
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
readNoCacheRule(PAGE_CACHE_CONFIG, byPath, problems);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function readNginx(
|
|
79
|
+
byPath: ReadonlyMap<string, string>,
|
|
80
|
+
problems: DeployProblem[],
|
|
81
|
+
): void {
|
|
82
|
+
readNoCacheRule(NGINX_CONFIG, byPath, problems);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function readNoCacheRule(
|
|
86
|
+
path: string,
|
|
87
|
+
byPath: ReadonlyMap<string, string>,
|
|
88
|
+
problems: DeployProblem[],
|
|
89
|
+
): void {
|
|
90
|
+
const text = byPath.get(path);
|
|
91
|
+
if (text === undefined) {
|
|
92
|
+
problems.push({
|
|
93
|
+
file: path,
|
|
94
|
+
line: 0,
|
|
95
|
+
kind: 'cacheable-page',
|
|
96
|
+
message: 'the server has no page cache policy to read',
|
|
97
|
+
hint: `commit ${path} at the repository root, telling the browser to check the page on every visit`,
|
|
98
|
+
});
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (!NO_CACHE.test(text)) {
|
|
102
|
+
problems.push({
|
|
103
|
+
file: path,
|
|
104
|
+
line: 0,
|
|
105
|
+
kind: 'cacheable-page',
|
|
106
|
+
message: 'no rule stops a browser from keeping the page between deploys',
|
|
107
|
+
hint: 'give the page Cache-Control: no-cache, and keep the long life for the hashed bundles alone',
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function lineOf(text: string, pattern: RegExp): number {
|
|
113
|
+
const match = pattern.exec(text);
|
|
114
|
+
if (match === null) return 0;
|
|
115
|
+
return text.slice(0, match.index).split('\n').length;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function escapeRegExp(value: string): string {
|
|
119
|
+
return value.replaceAll(/[$()*+.?[\\\]^{|}]/g, String.raw`\$&`);
|
|
120
|
+
}
|