@ndla/ui 56.0.122-alpha.0 → 56.0.124-alpha.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 +1 -1
- package/es/Article/Article.js +127 -0
- package/es/Article/Article.js.map +1 -0
- package/es/Article/ArticleByline.js +133 -0
- package/es/Article/ArticleByline.js.map +1 -0
- package/es/Article/ArticleFootNotes.js +40 -0
- package/es/Article/ArticleFootNotes.js.map +1 -0
- package/es/AudioPlayer/AudioPlayer.js +157 -0
- package/es/AudioPlayer/AudioPlayer.js.map +1 -0
- package/es/AudioPlayer/Controls.js +254 -0
- package/es/AudioPlayer/Controls.js.map +1 -0
- package/es/AudioPlayer/SpeechControl.js +40 -0
- package/es/AudioPlayer/SpeechControl.js.map +1 -0
- package/es/AudioPlayer/index.js +8 -0
- package/es/AudioPlayer/index.js.map +1 -0
- package/es/Breadcrumb/Breadcrumb.js +44 -0
- package/es/Breadcrumb/Breadcrumb.js.map +1 -0
- package/es/Breadcrumb/BreadcrumbItem.js +36 -0
- package/es/Breadcrumb/BreadcrumbItem.js.map +1 -0
- package/es/Breadcrumb/HomeBreadcrumb.js +44 -0
- package/es/Breadcrumb/HomeBreadcrumb.js.map +1 -0
- package/es/Breadcrumb/index.js +9 -0
- package/es/Breadcrumb/index.js.map +1 -0
- package/es/CampaignBlock/CampaignBlock.js +131 -0
- package/es/CampaignBlock/CampaignBlock.js.map +1 -0
- package/es/CodeBlock/CodeBlock.js +25 -0
- package/es/CodeBlock/CodeBlock.js.map +1 -0
- package/es/CodeBlock/codeLanguageOptions.js +114 -0
- package/es/CodeBlock/codeLanguageOptions.js.map +1 -0
- package/es/Concept/Concept.js +50 -0
- package/es/Concept/Concept.js.map +1 -0
- package/es/ContactBlock/ContactBlock.js +145 -0
- package/es/ContactBlock/ContactBlock.js.map +1 -0
- package/es/ContentTypeBadge/ContentTypeBadge.js +41 -0
- package/es/ContentTypeBadge/ContentTypeBadge.js.map +1 -0
- package/es/ContentTypeBlockQuote/ContentTypeBlockQuote.js +25 -0
- package/es/ContentTypeBlockQuote/ContentTypeBlockQuote.js.map +1 -0
- package/es/ContentTypeFramedContent/ContentTypeFramedContent.js +25 -0
- package/es/ContentTypeFramedContent/ContentTypeFramedContent.js.map +1 -0
- package/es/ContentTypeHero/ContentTypeHero.js +39 -0
- package/es/ContentTypeHero/ContentTypeHero.js.map +1 -0
- package/es/CopyParagraphButton/CopyParagraphButton.js +62 -0
- package/es/CopyParagraphButton/CopyParagraphButton.js.map +1 -0
- package/es/CopyParagraphButton/index.js +8 -0
- package/es/CopyParagraphButton/index.js.map +1 -0
- package/es/Embed/AudioEmbed.js +52 -0
- package/es/Embed/AudioEmbed.js.map +1 -0
- package/es/Embed/BrightcoveEmbed.js +96 -0
- package/es/Embed/BrightcoveEmbed.js.map +1 -0
- package/es/Embed/CodeEmbed.js +61 -0
- package/es/Embed/CodeEmbed.js.map +1 -0
- package/es/Embed/ConceptEmbed.js +78 -0
- package/es/Embed/ConceptEmbed.js.map +1 -0
- package/es/Embed/ConceptInlineTriggerButton.js +40 -0
- package/es/Embed/ConceptInlineTriggerButton.js.map +1 -0
- package/es/Embed/ContentLinkEmbed.js +31 -0
- package/es/Embed/ContentLinkEmbed.js.map +1 -0
- package/es/Embed/CopyrightEmbed.js +23 -0
- package/es/Embed/CopyrightEmbed.js.map +1 -0
- package/es/Embed/EmbedErrorPlaceholder.js +43 -0
- package/es/Embed/EmbedErrorPlaceholder.js.map +1 -0
- package/es/Embed/EmbedWrapper.js +26 -0
- package/es/Embed/EmbedWrapper.js.map +1 -0
- package/es/Embed/ExternalEmbed.js +54 -0
- package/es/Embed/ExternalEmbed.js.map +1 -0
- package/es/Embed/FootnoteEmbed.js +27 -0
- package/es/Embed/FootnoteEmbed.js.map +1 -0
- package/es/Embed/GlossEmbed.js +52 -0
- package/es/Embed/GlossEmbed.js.map +1 -0
- package/es/Embed/H5pEmbed.js +38 -0
- package/es/Embed/H5pEmbed.js.map +1 -0
- package/es/Embed/IframeEmbed.js +69 -0
- package/es/Embed/IframeEmbed.js.map +1 -0
- package/es/Embed/ImageEmbed.js +180 -0
- package/es/Embed/ImageEmbed.js.map +1 -0
- package/es/Embed/InlineTriggerButton.js +25 -0
- package/es/Embed/InlineTriggerButton.js.map +1 -0
- package/es/Embed/RelatedContentEmbed.js +38 -0
- package/es/Embed/RelatedContentEmbed.js.map +1 -0
- package/es/Embed/UnknownEmbed.js +20 -0
- package/es/Embed/UnknownEmbed.js.map +1 -0
- package/es/Embed/UuDisclaimerEmbed.js +54 -0
- package/es/Embed/UuDisclaimerEmbed.js.map +1 -0
- package/es/ErrorMessage/ErrorMessage.js +54 -0
- package/es/ErrorMessage/ErrorMessage.js.map +1 -0
- package/es/ErrorMessage/index.js +8 -0
- package/es/ErrorMessage/index.js.map +1 -0
- package/es/FactBox/FactBox.js +121 -0
- package/es/FactBox/FactBox.js.map +1 -0
- package/es/FactBox/index.js +8 -0
- package/es/FactBox/index.js.map +1 -0
- package/es/FileList/File.js +76 -0
- package/es/FileList/File.js.map +1 -0
- package/es/FileList/FileList.js +32 -0
- package/es/FileList/FileList.js.map +1 -0
- package/es/FileList/PdfFile.js +28 -0
- package/es/FileList/PdfFile.js.map +1 -0
- package/es/Gloss/Gloss.js +142 -0
- package/es/Gloss/Gloss.js.map +1 -0
- package/es/Gloss/GlossExample.js +46 -0
- package/es/Gloss/GlossExample.js.map +1 -0
- package/es/Grid/Grid.js +66 -0
- package/es/Grid/Grid.js.map +1 -0
- package/es/Grid/GridParallaxItem.js +21 -0
- package/es/Grid/GridParallaxItem.js.map +1 -0
- package/es/KeyFigure/KeyFigure.js +46 -0
- package/es/KeyFigure/KeyFigure.js.map +1 -0
- package/es/LicenseByline/EmbedByline.js +132 -0
- package/es/LicenseByline/EmbedByline.js.map +1 -0
- package/es/LicenseByline/LicenseLink.js +31 -0
- package/es/LicenseByline/LicenseLink.js.map +1 -0
- package/es/LinkBlock/LinkBlock.js +74 -0
- package/es/LinkBlock/LinkBlock.js.map +1 -0
- package/es/LinkBlock/LinkBlockSection.js +23 -0
- package/es/LinkBlock/LinkBlockSection.js.map +1 -0
- package/es/Pitch/Pitch.js +62 -0
- package/es/Pitch/Pitch.js.map +1 -0
- package/es/RelatedArticleList/RelatedArticleList.js +97 -0
- package/es/RelatedArticleList/RelatedArticleList.js.map +1 -0
- package/es/RelatedArticleList/index.js +8 -0
- package/es/RelatedArticleList/index.js.map +1 -0
- package/es/ResourceBox/ResourceBox.js +74 -0
- package/es/ResourceBox/ResourceBox.js.map +1 -0
- package/es/TagSelector/TagSelector.js +100 -0
- package/es/TagSelector/TagSelector.js.map +1 -0
- package/es/ZendeskButton/ZendeskButton.js +41 -0
- package/es/ZendeskButton/ZendeskButton.js.map +1 -0
- package/es/_virtual/rolldown_runtime.js +11 -0
- package/es/i18n/formatNestedMessages.js +17 -0
- package/es/i18n/formatNestedMessages.js.map +1 -0
- package/es/i18n/i18n.js +29 -0
- package/es/i18n/i18n.js.map +1 -0
- package/es/i18n/useComponentTranslations.js +155 -0
- package/es/i18n/useComponentTranslations.js.map +1 -0
- package/es/index.js +65 -0
- package/es/locale/messages-en.js +438 -0
- package/es/locale/messages-en.js.map +1 -0
- package/es/locale/messages-nb.js +438 -0
- package/es/locale/messages-nb.js.map +1 -0
- package/es/locale/messages-nn.js +438 -0
- package/es/locale/messages-nn.js.map +1 -0
- package/es/locale/messages-se.js +438 -0
- package/es/locale/messages-se.js.map +1 -0
- package/es/model/ContentType.js +72 -0
- package/es/model/ContentType.js.map +1 -0
- package/es/model/SubjectCategories.js +25 -0
- package/es/model/SubjectCategories.js.map +1 -0
- package/es/model/SubjectTypes.js +23 -0
- package/es/model/SubjectTypes.js.map +1 -0
- package/es/model/WordClass.js +53 -0
- package/es/model/WordClass.js.map +1 -0
- package/es/model/index.js +19 -0
- package/es/model/index.js.map +1 -0
- package/es/utils/licenseAttributes.js +16 -0
- package/es/utils/licenseAttributes.js.map +1 -0
- package/es/utils/relativeUrl.js +26 -0
- package/es/utils/relativeUrl.js.map +1 -0
- package/lib/Article/Article.js +134 -0
- package/lib/Article/Article.js.map +1 -0
- package/lib/Article/ArticleByline.js +135 -0
- package/lib/Article/ArticleByline.js.map +1 -0
- package/lib/Article/ArticleFootNotes.js +41 -0
- package/lib/Article/ArticleFootNotes.js.map +1 -0
- package/lib/AudioPlayer/AudioPlayer.js +158 -0
- package/lib/AudioPlayer/AudioPlayer.js.map +1 -0
- package/lib/AudioPlayer/Controls.js +255 -0
- package/lib/AudioPlayer/Controls.js.map +1 -0
- package/lib/AudioPlayer/SpeechControl.js +41 -0
- package/lib/AudioPlayer/SpeechControl.js.map +1 -0
- package/lib/AudioPlayer/index.js +8 -0
- package/lib/AudioPlayer/index.js.map +1 -0
- package/lib/Breadcrumb/Breadcrumb.js +45 -0
- package/lib/Breadcrumb/Breadcrumb.js.map +1 -0
- package/lib/Breadcrumb/BreadcrumbItem.js +37 -0
- package/lib/Breadcrumb/BreadcrumbItem.js.map +1 -0
- package/lib/Breadcrumb/HomeBreadcrumb.js +45 -0
- package/lib/Breadcrumb/HomeBreadcrumb.js.map +1 -0
- package/lib/Breadcrumb/index.js +9 -0
- package/lib/Breadcrumb/index.js.map +1 -0
- package/lib/CampaignBlock/CampaignBlock.js +132 -0
- package/lib/CampaignBlock/CampaignBlock.js.map +1 -0
- package/lib/CodeBlock/CodeBlock.js +26 -0
- package/lib/CodeBlock/CodeBlock.js.map +1 -0
- package/lib/CodeBlock/codeLanguageOptions.js +115 -0
- package/lib/CodeBlock/codeLanguageOptions.js.map +1 -0
- package/lib/Concept/Concept.js +51 -0
- package/lib/Concept/Concept.js.map +1 -0
- package/lib/ContactBlock/ContactBlock.js +147 -0
- package/lib/ContactBlock/ContactBlock.js.map +1 -0
- package/lib/ContentTypeBadge/ContentTypeBadge.js +43 -0
- package/lib/ContentTypeBadge/ContentTypeBadge.js.map +1 -0
- package/lib/ContentTypeBlockQuote/ContentTypeBlockQuote.js +26 -0
- package/lib/ContentTypeBlockQuote/ContentTypeBlockQuote.js.map +1 -0
- package/lib/ContentTypeFramedContent/ContentTypeFramedContent.js +26 -0
- package/lib/ContentTypeFramedContent/ContentTypeFramedContent.js.map +1 -0
- package/lib/ContentTypeHero/ContentTypeHero.js +40 -0
- package/lib/ContentTypeHero/ContentTypeHero.js.map +1 -0
- package/lib/CopyParagraphButton/CopyParagraphButton.js +63 -0
- package/lib/CopyParagraphButton/CopyParagraphButton.js.map +1 -0
- package/lib/CopyParagraphButton/index.js +8 -0
- package/lib/CopyParagraphButton/index.js.map +1 -0
- package/lib/Embed/AudioEmbed.js +53 -0
- package/lib/Embed/AudioEmbed.js.map +1 -0
- package/lib/Embed/BrightcoveEmbed.js +97 -0
- package/lib/Embed/BrightcoveEmbed.js.map +1 -0
- package/lib/Embed/CodeEmbed.js +62 -0
- package/lib/Embed/CodeEmbed.js.map +1 -0
- package/lib/Embed/ConceptEmbed.js +81 -0
- package/lib/Embed/ConceptEmbed.js.map +1 -0
- package/lib/Embed/ConceptInlineTriggerButton.js +41 -0
- package/lib/Embed/ConceptInlineTriggerButton.js.map +1 -0
- package/lib/Embed/ContentLinkEmbed.js +32 -0
- package/lib/Embed/ContentLinkEmbed.js.map +1 -0
- package/lib/Embed/CopyrightEmbed.js +24 -0
- package/lib/Embed/CopyrightEmbed.js.map +1 -0
- package/lib/Embed/EmbedErrorPlaceholder.js +44 -0
- package/lib/Embed/EmbedErrorPlaceholder.js.map +1 -0
- package/lib/Embed/EmbedWrapper.js +27 -0
- package/lib/Embed/EmbedWrapper.js.map +1 -0
- package/lib/Embed/ExternalEmbed.js +55 -0
- package/lib/Embed/ExternalEmbed.js.map +1 -0
- package/lib/Embed/FootnoteEmbed.js +28 -0
- package/lib/Embed/FootnoteEmbed.js.map +1 -0
- package/lib/Embed/GlossEmbed.js +53 -0
- package/lib/Embed/GlossEmbed.js.map +1 -0
- package/lib/Embed/H5pEmbed.js +39 -0
- package/lib/Embed/H5pEmbed.js.map +1 -0
- package/lib/Embed/IframeEmbed.js +70 -0
- package/lib/Embed/IframeEmbed.js.map +1 -0
- package/lib/Embed/ImageEmbed.js +183 -0
- package/lib/Embed/ImageEmbed.js.map +1 -0
- package/lib/Embed/InlineTriggerButton.js +26 -0
- package/lib/Embed/InlineTriggerButton.js.map +1 -0
- package/lib/Embed/RelatedContentEmbed.js +39 -0
- package/lib/Embed/RelatedContentEmbed.js.map +1 -0
- package/lib/Embed/UnknownEmbed.js +21 -0
- package/lib/Embed/UnknownEmbed.js.map +1 -0
- package/lib/Embed/UuDisclaimerEmbed.js +55 -0
- package/lib/Embed/UuDisclaimerEmbed.js.map +1 -0
- package/lib/ErrorMessage/ErrorMessage.js +55 -0
- package/lib/ErrorMessage/ErrorMessage.js.map +1 -0
- package/lib/ErrorMessage/index.js +8 -0
- package/lib/ErrorMessage/index.js.map +1 -0
- package/lib/FactBox/FactBox.js +122 -0
- package/lib/FactBox/FactBox.js.map +1 -0
- package/lib/FactBox/index.js +8 -0
- package/lib/FactBox/index.js.map +1 -0
- package/lib/FileList/File.js +78 -0
- package/lib/FileList/File.js.map +1 -0
- package/lib/FileList/FileList.js +35 -0
- package/lib/FileList/FileList.js.map +1 -0
- package/lib/FileList/PdfFile.js +29 -0
- package/lib/FileList/PdfFile.js.map +1 -0
- package/lib/Gloss/Gloss.js +143 -0
- package/lib/Gloss/Gloss.js.map +1 -0
- package/lib/Gloss/GlossExample.js +47 -0
- package/lib/Gloss/GlossExample.js.map +1 -0
- package/lib/Grid/Grid.js +67 -0
- package/lib/Grid/Grid.js.map +1 -0
- package/lib/Grid/GridParallaxItem.js +22 -0
- package/lib/Grid/GridParallaxItem.js.map +1 -0
- package/lib/KeyFigure/KeyFigure.js +47 -0
- package/lib/KeyFigure/KeyFigure.js.map +1 -0
- package/lib/LicenseByline/EmbedByline.js +134 -0
- package/lib/LicenseByline/EmbedByline.js.map +1 -0
- package/lib/LicenseByline/LicenseLink.js +32 -0
- package/lib/LicenseByline/LicenseLink.js.map +1 -0
- package/lib/LinkBlock/LinkBlock.js +75 -0
- package/lib/LinkBlock/LinkBlock.js.map +1 -0
- package/lib/LinkBlock/LinkBlockSection.js +24 -0
- package/lib/LinkBlock/LinkBlockSection.js.map +1 -0
- package/lib/Pitch/Pitch.js +63 -0
- package/lib/Pitch/Pitch.js.map +1 -0
- package/lib/RelatedArticleList/RelatedArticleList.js +99 -0
- package/lib/RelatedArticleList/RelatedArticleList.js.map +1 -0
- package/lib/RelatedArticleList/index.js +8 -0
- package/lib/RelatedArticleList/index.js.map +1 -0
- package/lib/ResourceBox/ResourceBox.js +75 -0
- package/lib/ResourceBox/ResourceBox.js.map +1 -0
- package/lib/TagSelector/TagSelector.js +108 -0
- package/lib/TagSelector/TagSelector.js.map +1 -0
- package/lib/ZendeskButton/ZendeskButton.js +42 -0
- package/lib/ZendeskButton/ZendeskButton.js.map +1 -0
- package/lib/_virtual/rolldown_runtime.js +42 -0
- package/lib/i18n/formatNestedMessages.js +18 -0
- package/lib/i18n/formatNestedMessages.js.map +1 -0
- package/lib/i18n/i18n.js +31 -0
- package/lib/i18n/i18n.js.map +1 -0
- package/lib/i18n/useComponentTranslations.js +163 -0
- package/lib/i18n/useComponentTranslations.js.map +1 -0
- package/lib/index.js +157 -0
- package/lib/locale/messages-en.js +439 -0
- package/lib/locale/messages-en.js.map +1 -0
- package/lib/locale/messages-nb.js +439 -0
- package/lib/locale/messages-nb.js.map +1 -0
- package/lib/locale/messages-nn.js +439 -0
- package/lib/locale/messages-nn.js.map +1 -0
- package/lib/locale/messages-se.js +439 -0
- package/lib/locale/messages-se.js.map +1 -0
- package/lib/model/ContentType.js +94 -0
- package/lib/model/ContentType.js.map +1 -0
- package/lib/model/SubjectCategories.js +30 -0
- package/lib/model/SubjectCategories.js.map +1 -0
- package/lib/model/SubjectTypes.js +28 -0
- package/lib/model/SubjectTypes.js.map +1 -0
- package/lib/model/WordClass.js +58 -0
- package/lib/model/WordClass.js.map +1 -0
- package/lib/model/index.js +19 -0
- package/lib/model/index.js.map +1 -0
- package/lib/utils/licenseAttributes.js +17 -0
- package/lib/utils/licenseAttributes.js.map +1 -0
- package/lib/utils/relativeUrl.js +26 -0
- package/lib/utils/relativeUrl.js.map +1 -0
- package/package.json +12 -11
package/README.md
CHANGED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { ContentTypeBadge } from "../ContentTypeBadge/ContentTypeBadge.js";
|
|
2
|
+
import { ArticleByline } from "./ArticleByline.js";
|
|
3
|
+
import { forwardRef } from "react";
|
|
4
|
+
import { Heading, Text } from "@ndla/primitives";
|
|
5
|
+
import { Stack, styled } from "@ndla/styled-system/jsx";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { ark } from "@ark-ui/react";
|
|
8
|
+
import { cx } from "@ndla/styled-system/css";
|
|
9
|
+
|
|
10
|
+
//#region src/Article/Article.tsx
|
|
11
|
+
const StyledArticleContent = styled(ark.section, {}, { baseComponent: true });
|
|
12
|
+
const ArticleContent = forwardRef(({ className,...props }, ref) => /* @__PURE__ */ jsx(StyledArticleContent, {
|
|
13
|
+
className: cx("ndla-article", className),
|
|
14
|
+
...props,
|
|
15
|
+
ref
|
|
16
|
+
}));
|
|
17
|
+
const StyledArticleWrapper = styled(ark.article, { base: {
|
|
18
|
+
background: "background.default",
|
|
19
|
+
display: "flex",
|
|
20
|
+
flexDirection: "column",
|
|
21
|
+
color: "text.default",
|
|
22
|
+
alignItems: "center",
|
|
23
|
+
width: "100%",
|
|
24
|
+
overflowWrap: "break-word",
|
|
25
|
+
position: "relative",
|
|
26
|
+
"& mjx-stretchy-v > mjx-ext > mjx-c": { transform: "scaleY(100) translateY(0.075em)" },
|
|
27
|
+
_after: {
|
|
28
|
+
content: "",
|
|
29
|
+
display: "table",
|
|
30
|
+
clear: "both"
|
|
31
|
+
}
|
|
32
|
+
} }, { baseComponent: true });
|
|
33
|
+
const ArticleWrapper = forwardRef((props, ref) => /* @__PURE__ */ jsx(StyledArticleWrapper, {
|
|
34
|
+
"data-ndla-article": "",
|
|
35
|
+
ref,
|
|
36
|
+
...props
|
|
37
|
+
}));
|
|
38
|
+
const ArticleHGroup = styled(ark.hgroup, { base: {
|
|
39
|
+
display: "flex",
|
|
40
|
+
width: "100%",
|
|
41
|
+
flexDirection: "column",
|
|
42
|
+
alignItems: "flex-start",
|
|
43
|
+
"& h1": { overflowWrap: "anywhere" }
|
|
44
|
+
} }, { baseComponent: true });
|
|
45
|
+
const ArticleHeader = styled(ark.header, { base: {
|
|
46
|
+
display: "flex",
|
|
47
|
+
flexDirection: "column",
|
|
48
|
+
gap: "medium",
|
|
49
|
+
alignItems: "flex-start",
|
|
50
|
+
width: "100%",
|
|
51
|
+
paddingBlockStart: "xxlarge",
|
|
52
|
+
overflowWrap: "anywhere"
|
|
53
|
+
} }, { baseComponent: true });
|
|
54
|
+
const ArticleFooter = styled(ark.footer, { base: {
|
|
55
|
+
display: "flex",
|
|
56
|
+
flexDirection: "column",
|
|
57
|
+
gap: "xxlarge",
|
|
58
|
+
width: "100%",
|
|
59
|
+
"& > :is(:last-child)": { paddingBlockEnd: "5xlarge" }
|
|
60
|
+
} }, { baseComponent: true });
|
|
61
|
+
const StyledStack = styled(Stack, { base: {
|
|
62
|
+
width: "100%",
|
|
63
|
+
minHeight: "xxlarge"
|
|
64
|
+
} });
|
|
65
|
+
const StyledWrapper = styled("div", { base: {
|
|
66
|
+
display: "flex",
|
|
67
|
+
gap: "small",
|
|
68
|
+
flexWrap: "wrap",
|
|
69
|
+
alignItems: "center"
|
|
70
|
+
} });
|
|
71
|
+
const ArticleTitle = ({ contentType, heartButton, title, lang, id, introduction, contentTypeLabel, competenceGoals, disclaimer }) => {
|
|
72
|
+
return /* @__PURE__ */ jsxs(ArticleHeader, { children: [
|
|
73
|
+
/* @__PURE__ */ jsxs(ArticleHGroup, { children: [(!!contentType || !!heartButton) && /* @__PURE__ */ jsxs(StyledStack, {
|
|
74
|
+
justify: "space-between",
|
|
75
|
+
align: "center",
|
|
76
|
+
direction: "row",
|
|
77
|
+
gap: "small",
|
|
78
|
+
children: [!!contentType && /* @__PURE__ */ jsx(ContentTypeBadge, {
|
|
79
|
+
contentType,
|
|
80
|
+
children: contentTypeLabel
|
|
81
|
+
}), heartButton]
|
|
82
|
+
}), /* @__PURE__ */ jsx(Heading, {
|
|
83
|
+
textStyle: "heading.medium",
|
|
84
|
+
id,
|
|
85
|
+
lang,
|
|
86
|
+
property: "dct:title",
|
|
87
|
+
children: title
|
|
88
|
+
})] }),
|
|
89
|
+
!!introduction && /* @__PURE__ */ jsx(Text, {
|
|
90
|
+
lang,
|
|
91
|
+
textStyle: "body.xlarge",
|
|
92
|
+
asChild: true,
|
|
93
|
+
consumeCss: true,
|
|
94
|
+
children: /* @__PURE__ */ jsx("div", { children: introduction })
|
|
95
|
+
}),
|
|
96
|
+
/* @__PURE__ */ jsxs(StyledWrapper, { children: [competenceGoals, disclaimer] })
|
|
97
|
+
] });
|
|
98
|
+
};
|
|
99
|
+
const Article = ({ article, contentType, licenseBox, children, competenceGoals, contentTypeLabel, id, heartButton, lang, disclaimer }) => {
|
|
100
|
+
const { title, introduction, published, content, footNotes, copyright } = article;
|
|
101
|
+
const authors = copyright?.creators.length || copyright?.rightsholders.length ? copyright.creators : copyright?.processors;
|
|
102
|
+
return /* @__PURE__ */ jsxs(ArticleWrapper, { children: [
|
|
103
|
+
/* @__PURE__ */ jsx(ArticleTitle, {
|
|
104
|
+
id,
|
|
105
|
+
contentType,
|
|
106
|
+
heartButton,
|
|
107
|
+
title,
|
|
108
|
+
introduction,
|
|
109
|
+
competenceGoals,
|
|
110
|
+
lang,
|
|
111
|
+
contentTypeLabel,
|
|
112
|
+
disclaimer
|
|
113
|
+
}),
|
|
114
|
+
/* @__PURE__ */ jsx(ArticleContent, { children: content }),
|
|
115
|
+
/* @__PURE__ */ jsxs(ArticleFooter, { children: [/* @__PURE__ */ jsx(ArticleByline, {
|
|
116
|
+
footnotes: footNotes,
|
|
117
|
+
authors,
|
|
118
|
+
suppliers: copyright?.rightsholders,
|
|
119
|
+
published,
|
|
120
|
+
licenseBox
|
|
121
|
+
}), children] })
|
|
122
|
+
] });
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
//#endregion
|
|
126
|
+
export { Article, ArticleContent, ArticleFooter, ArticleHGroup, ArticleHeader, ArticleTitle, ArticleWrapper };
|
|
127
|
+
//# sourceMappingURL=Article.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Article.js","names":[],"sources":["../../src/Article/Article.tsx"],"sourcesContent":["/**\n * Copyright (c) 2016-present, NDLA.\n *\n * This source code is licensed under the GPLv3 license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport { type ComponentPropsWithRef, type ReactNode, forwardRef } from \"react\";\nimport { ark, type HTMLArkProps } from \"@ark-ui/react\";\nimport { Heading, Text } from \"@ndla/primitives\";\nimport { cx } from \"@ndla/styled-system/css\";\nimport { Stack, styled } from \"@ndla/styled-system/jsx\";\nimport type { JsxStyleProps } from \"@ndla/styled-system/types\";\nimport { ArticleByline } from \"./ArticleByline\";\nimport { ContentTypeBadge, type ContentType } from \"../ContentTypeBadge/ContentTypeBadge\";\nimport type { Article as ArticleType } from \"../types\";\n\nconst StyledArticleContent = styled(ark.section, {}, { baseComponent: true });\n\nexport const ArticleContent = forwardRef<HTMLElement, HTMLArkProps<\"div\"> & JsxStyleProps>(\n ({ className, ...props }, ref) => (\n <StyledArticleContent className={cx(\"ndla-article\", className)} {...props} ref={ref} />\n ),\n);\n\nconst StyledArticleWrapper = styled(\n ark.article,\n {\n base: {\n background: \"background.default\",\n display: \"flex\",\n flexDirection: \"column\",\n color: \"text.default\",\n alignItems: \"center\",\n width: \"100%\",\n overflowWrap: \"break-word\",\n position: \"relative\",\n \"& mjx-stretchy-v > mjx-ext > mjx-c\": {\n transform: \"scaleY(100) translateY(0.075em)\",\n },\n _after: {\n content: \"\",\n display: \"table\",\n clear: \"both\",\n },\n },\n },\n { baseComponent: true },\n);\n\nexport const ArticleWrapper = forwardRef<HTMLElement, ComponentPropsWithRef<\"article\"> & JsxStyleProps>(\n (props, ref) => <StyledArticleWrapper data-ndla-article=\"\" ref={ref} {...props} />,\n);\n\nexport const ArticleHGroup = styled(\n ark.hgroup,\n {\n base: {\n display: \"flex\",\n width: \"100%\",\n flexDirection: \"column\",\n alignItems: \"flex-start\",\n \"& h1\": {\n overflowWrap: \"anywhere\",\n },\n },\n },\n { baseComponent: true },\n);\n\nexport const ArticleHeader = styled(\n ark.header,\n {\n base: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"medium\",\n alignItems: \"flex-start\",\n width: \"100%\",\n paddingBlockStart: \"xxlarge\",\n overflowWrap: \"anywhere\",\n },\n },\n { baseComponent: true },\n);\n\nexport const ArticleFooter = styled(\n ark.footer,\n {\n base: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"xxlarge\",\n width: \"100%\",\n \"& > :is(:last-child)\": {\n paddingBlockEnd: \"5xlarge\",\n },\n },\n },\n { baseComponent: true },\n);\n\nconst StyledStack = styled(Stack, {\n base: {\n width: \"100%\",\n minHeight: \"xxlarge\",\n },\n});\n\nconst StyledWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n gap: \"small\",\n flexWrap: \"wrap\",\n alignItems: \"center\",\n },\n});\n\ninterface ArticleTitleProps {\n heartButton?: ReactNode;\n contentType?: ContentType;\n contentTypeLabel?: ReactNode;\n competenceGoals?: ReactNode;\n id: string;\n lang?: string;\n title?: ReactNode;\n introduction?: ReactNode;\n disclaimer?: ReactNode;\n}\n\nexport const ArticleTitle = ({\n contentType,\n heartButton,\n title,\n lang,\n id,\n introduction,\n contentTypeLabel,\n competenceGoals,\n disclaimer,\n}: ArticleTitleProps) => {\n return (\n <ArticleHeader>\n <ArticleHGroup>\n {(!!contentType || !!heartButton) && (\n <StyledStack justify=\"space-between\" align=\"center\" direction=\"row\" gap=\"small\">\n {!!contentType && <ContentTypeBadge contentType={contentType}>{contentTypeLabel}</ContentTypeBadge>}\n {heartButton}\n </StyledStack>\n )}\n <Heading textStyle=\"heading.medium\" id={id} lang={lang} property=\"dct:title\">\n {title}\n </Heading>\n </ArticleHGroup>\n {!!introduction && (\n <Text lang={lang} textStyle=\"body.xlarge\" asChild consumeCss>\n <div>{introduction}</div>\n </Text>\n )}\n <StyledWrapper>\n {competenceGoals}\n {disclaimer}\n </StyledWrapper>\n </ArticleHeader>\n );\n};\n\ninterface Props {\n heartButton?: ReactNode;\n article: ArticleType;\n licenseBox?: ReactNode;\n contentType?: ContentType;\n contentTypeLabel?: ReactNode;\n children?: ReactNode;\n competenceGoals?: ReactNode;\n id: string;\n lang?: string;\n disclaimer?: ReactNode;\n}\n\nexport const Article = ({\n article,\n contentType,\n licenseBox,\n children,\n competenceGoals,\n contentTypeLabel,\n id,\n heartButton,\n lang,\n disclaimer,\n}: Props) => {\n const { title, introduction, published, content, footNotes, copyright } = article;\n\n const authors =\n copyright?.creators.length || copyright?.rightsholders.length ? copyright.creators : copyright?.processors;\n\n return (\n <ArticleWrapper>\n <ArticleTitle\n id={id}\n contentType={contentType}\n heartButton={heartButton}\n title={title}\n introduction={introduction}\n competenceGoals={competenceGoals}\n lang={lang}\n contentTypeLabel={contentTypeLabel}\n disclaimer={disclaimer}\n />\n <ArticleContent>{content}</ArticleContent>\n <ArticleFooter>\n <ArticleByline\n footnotes={footNotes}\n authors={authors}\n suppliers={copyright?.rightsholders}\n published={published}\n licenseBox={licenseBox}\n />\n {children}\n </ArticleFooter>\n </ArticleWrapper>\n );\n};\n"],"mappings":";;;;;;;;;;AAkBA,MAAM,uBAAuB,OAAO,IAAI,SAAS,CAAE,GAAE,EAAE,eAAe,KAAM,EAAC;AAE7E,MAAa,iBAAiB,WAC5B,CAAC,EAAE,UAAW,GAAG,OAAO,EAAE,wBACxB,IAAC;CAAqB,WAAW,GAAG,gBAAgB,UAAU;CAAE,GAAI;CAAY;EAAO,CAE1F;AAED,MAAM,uBAAuB,OAC3B,IAAI,SACJ,EACE,MAAM;CACJ,YAAY;CACZ,SAAS;CACT,eAAe;CACf,OAAO;CACP,YAAY;CACZ,OAAO;CACP,cAAc;CACd,UAAU;CACV,sCAAsC,EACpC,WAAW,kCACZ;CACD,QAAQ;EACN,SAAS;EACT,SAAS;EACT,OAAO;CACR;AACF,EACF,GACD,EAAE,eAAe,KAAM,EACxB;AAED,MAAa,iBAAiB,WAC5B,CAAC,OAAO,wBAAQ,IAAC;CAAqB,qBAAkB;CAAQ;CAAK,GAAI;EAAS,CACnF;AAED,MAAa,gBAAgB,OAC3B,IAAI,QACJ,EACE,MAAM;CACJ,SAAS;CACT,OAAO;CACP,eAAe;CACf,YAAY;CACZ,QAAQ,EACN,cAAc,WACf;AACF,EACF,GACD,EAAE,eAAe,KAAM,EACxB;AAED,MAAa,gBAAgB,OAC3B,IAAI,QACJ,EACE,MAAM;CACJ,SAAS;CACT,eAAe;CACf,KAAK;CACL,YAAY;CACZ,OAAO;CACP,mBAAmB;CACnB,cAAc;AACf,EACF,GACD,EAAE,eAAe,KAAM,EACxB;AAED,MAAa,gBAAgB,OAC3B,IAAI,QACJ,EACE,MAAM;CACJ,SAAS;CACT,eAAe;CACf,KAAK;CACL,OAAO;CACP,wBAAwB,EACtB,iBAAiB,UAClB;AACF,EACF,GACD,EAAE,eAAe,KAAM,EACxB;AAED,MAAM,cAAc,OAAO,OAAO,EAChC,MAAM;CACJ,OAAO;CACP,WAAW;AACZ,EACF,EAAC;AAEF,MAAM,gBAAgB,OAAO,OAAO,EAClC,MAAM;CACJ,SAAS;CACT,KAAK;CACL,UAAU;CACV,YAAY;AACb,EACF,EAAC;AAcF,MAAa,eAAe,CAAC,EAC3B,aACA,aACA,OACA,MACA,IACA,cACA,kBACA,iBACA,YACkB,KAAK;AACvB,wBACE,KAAC;kBACC,KAAC,+BACK,iBAAiB,gCACnB,KAAC;GAAY,SAAQ;GAAgB,OAAM;GAAS,WAAU;GAAM,KAAI;gBACnE,+BAAe,IAAC;IAA8B;cAAc;KAAoC,EAClG;IACW,kBAEhB,IAAC;GAAQ,WAAU;GAAqB;GAAU;GAAM,UAAS;aAC9D;IACO,IACI;IACb,gCACD,IAAC;GAAW;GAAM,WAAU;GAAc;GAAQ;6BAChD,IAAC,mBAAK,eAAmB;IACpB;kBAET,KAAC,4BACE,iBACA,cACa;KACF;AAEnB;AAeD,MAAa,UAAU,CAAC,EACtB,SACA,aACA,YACA,UACA,iBACA,kBACA,IACA,aACA,MACA,YACM,KAAK;CACX,MAAM,EAAE,OAAO,cAAc,WAAW,SAAS,WAAW,WAAW,GAAG;CAE1E,MAAM,UACJ,WAAW,SAAS,UAAU,WAAW,cAAc,SAAS,UAAU,WAAW,WAAW;AAElG,wBACE,KAAC;kBACC,IAAC;GACK;GACS;GACA;GACN;GACO;GACG;GACX;GACY;GACN;IACZ;kBACF,IAAC,4BAAgB,UAAyB;kBAC1C,KAAC,4CACC,IAAC;GACC,WAAW;GACF;GACT,WAAW,WAAW;GACX;GACC;IACZ,EACD,YACa;KACD;AAEpB"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { ArticleFootNotes } from "./ArticleFootNotes.js";
|
|
2
|
+
import { forwardRef, useCallback, useEffect, useState } from "react";
|
|
3
|
+
import { AccordionItem, AccordionItemContent, AccordionItemIndicator, AccordionItemTrigger, AccordionRoot, Heading } from "@ndla/primitives";
|
|
4
|
+
import { styled } from "@ndla/styled-system/jsx";
|
|
5
|
+
import { useTranslation } from "react-i18next";
|
|
6
|
+
import { ArrowDownShortLine } from "@ndla/icons";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { useLocation } from "react-router-dom";
|
|
9
|
+
|
|
10
|
+
//#region src/Article/ArticleByline.tsx
|
|
11
|
+
const Wrapper = styled("div", { base: {
|
|
12
|
+
marginBlockStart: "medium",
|
|
13
|
+
paddingBlockStart: "xsmall",
|
|
14
|
+
borderTop: "1px solid",
|
|
15
|
+
borderColor: "stroke.subtle"
|
|
16
|
+
} });
|
|
17
|
+
const TextWrapper = styled("div", {
|
|
18
|
+
base: {
|
|
19
|
+
display: "flex",
|
|
20
|
+
flexDirection: "column",
|
|
21
|
+
gap: "3xsmall",
|
|
22
|
+
width: "100%",
|
|
23
|
+
justifyContent: "space-between",
|
|
24
|
+
paddingBlock: "xsmall",
|
|
25
|
+
textStyle: "body.medium",
|
|
26
|
+
"& [data-contributors=\"false\"]": { marginInlineStart: "auto" }
|
|
27
|
+
},
|
|
28
|
+
variants: { learningpath: {
|
|
29
|
+
true: {},
|
|
30
|
+
false: { tabletWide: { flexDirection: "row" } }
|
|
31
|
+
} }
|
|
32
|
+
});
|
|
33
|
+
const renderContributors = (contributors, t) => {
|
|
34
|
+
const contributorsArray = contributors.map((contributor, index) => {
|
|
35
|
+
if (index < 1) return contributor.name;
|
|
36
|
+
const sep = index === contributors.length - 1 ? ` ${t("article.conjunction")} ` : ", ";
|
|
37
|
+
return `${sep}${contributor.name}`;
|
|
38
|
+
});
|
|
39
|
+
return contributorsArray.join("");
|
|
40
|
+
};
|
|
41
|
+
const getSuppliersText = (suppliers, t) => {
|
|
42
|
+
if (suppliers.length === 0) return "";
|
|
43
|
+
return suppliers.length > 1 ? t("article.multipleSuppliersLabel", {
|
|
44
|
+
names: renderContributors(suppliers, t),
|
|
45
|
+
interpolation: { escapeValue: false }
|
|
46
|
+
}) : t("article.supplierLabel", {
|
|
47
|
+
name: renderContributors(suppliers, t),
|
|
48
|
+
interpolation: { escapeValue: false }
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
const StyledAccordionRoot = styled(AccordionRoot, { base: { paddingBlockStart: "xxlarge" } });
|
|
52
|
+
const refRegexp = /note\d/;
|
|
53
|
+
const footnotesAccordionId = "footnotes";
|
|
54
|
+
const ArticleByline = ({ authors = [], suppliers = [], footnotes, licenseBox, published, displayByline = true, bylineType = "article", bylineSuffix }) => {
|
|
55
|
+
const { t } = useTranslation();
|
|
56
|
+
const { pathname } = useLocation();
|
|
57
|
+
const [openAccordions, setOpenAccordions] = useState([]);
|
|
58
|
+
const accordionItemValue = "rulesForUse";
|
|
59
|
+
const onHashChange = useCallback((e) => {
|
|
60
|
+
const hash = e.newURL.split("#")[1];
|
|
61
|
+
if (hash?.match(refRegexp) && !openAccordions.includes(footnotesAccordionId)) {
|
|
62
|
+
setOpenAccordions([...openAccordions, footnotesAccordionId]);
|
|
63
|
+
const el = document.getElementById(`#${hash}`);
|
|
64
|
+
el?.click();
|
|
65
|
+
el?.focus();
|
|
66
|
+
}
|
|
67
|
+
}, [openAccordions]);
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
setOpenAccordions((prev) => prev.filter((state) => state !== accordionItemValue));
|
|
70
|
+
}, [pathname]);
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
window.addEventListener("hashchange", onHashChange);
|
|
73
|
+
return () => window.removeEventListener("hashchange", onHashChange);
|
|
74
|
+
}, [onHashChange]);
|
|
75
|
+
const showPrimaryContributors = suppliers.length > 0 || authors.length > 0;
|
|
76
|
+
const authorLabel = {
|
|
77
|
+
article: "article.authorsLabel",
|
|
78
|
+
learningPath: "article.authorsLabelLearningpath",
|
|
79
|
+
external: "article.authorsLabelExternal"
|
|
80
|
+
};
|
|
81
|
+
return /* @__PURE__ */ jsxs(Wrapper, { children: [!!displayByline && /* @__PURE__ */ jsxs(TextWrapper, {
|
|
82
|
+
learningpath: bylineType === "learningPath",
|
|
83
|
+
children: [
|
|
84
|
+
!!showPrimaryContributors && /* @__PURE__ */ jsxs("span", { children: [authors.length > 0 && `${t(authorLabel[bylineType], {
|
|
85
|
+
names: renderContributors(authors, t),
|
|
86
|
+
interpolation: { escapeValue: false }
|
|
87
|
+
})}. `, getSuppliersText(suppliers, t)] }),
|
|
88
|
+
published ? /* @__PURE__ */ jsxs("div", {
|
|
89
|
+
"data-contributors": showPrimaryContributors,
|
|
90
|
+
children: [
|
|
91
|
+
t(`${bylineType}.lastUpdated`),
|
|
92
|
+
" ",
|
|
93
|
+
published
|
|
94
|
+
]
|
|
95
|
+
}) : null,
|
|
96
|
+
bylineSuffix
|
|
97
|
+
]
|
|
98
|
+
}), (!!licenseBox || !!footnotes?.length) && /* @__PURE__ */ jsxs(StyledAccordionRoot, {
|
|
99
|
+
multiple: true,
|
|
100
|
+
value: openAccordions,
|
|
101
|
+
onValueChange: (details) => setOpenAccordions(details.value),
|
|
102
|
+
children: [!!licenseBox && /* @__PURE__ */ jsx(ArticleBylineAccordionItem, {
|
|
103
|
+
value: accordionItemValue,
|
|
104
|
+
accordionTitle: t("article.useContent"),
|
|
105
|
+
children: licenseBox
|
|
106
|
+
}), !!footnotes?.length && /* @__PURE__ */ jsx(ArticleBylineAccordionItem, {
|
|
107
|
+
value: footnotesAccordionId,
|
|
108
|
+
accordionTitle: t("article.footnotes"),
|
|
109
|
+
children: /* @__PURE__ */ jsx(ArticleFootNotes, { footNotes: footnotes })
|
|
110
|
+
})]
|
|
111
|
+
})] });
|
|
112
|
+
};
|
|
113
|
+
const ArticleBylineAccordionItem = forwardRef(({ value, accordionTitle, children,...props }, ref) => {
|
|
114
|
+
return /* @__PURE__ */ jsxs(AccordionItem, {
|
|
115
|
+
value,
|
|
116
|
+
ref,
|
|
117
|
+
...props,
|
|
118
|
+
children: [/* @__PURE__ */ jsx(Heading, {
|
|
119
|
+
asChild: true,
|
|
120
|
+
consumeCss: true,
|
|
121
|
+
textStyle: "label.medium",
|
|
122
|
+
fontWeight: "bold",
|
|
123
|
+
children: /* @__PURE__ */ jsx("h2", { children: /* @__PURE__ */ jsxs(AccordionItemTrigger, { children: [accordionTitle, /* @__PURE__ */ jsx(AccordionItemIndicator, {
|
|
124
|
+
asChild: true,
|
|
125
|
+
children: /* @__PURE__ */ jsx(ArrowDownShortLine, {})
|
|
126
|
+
})] }) })
|
|
127
|
+
}), /* @__PURE__ */ jsx(AccordionItemContent, { children })]
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
//#endregion
|
|
132
|
+
export { ArticleByline, ArticleBylineAccordionItem };
|
|
133
|
+
//# sourceMappingURL=ArticleByline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ArticleByline.js","names":["contributors: SupplierProps[] | AuthorProps[]","t: TFunction","suppliers: SupplierProps[]","e: HashChangeEvent","authorLabel: Record<string, string>"],"sources":["../../src/Article/ArticleByline.tsx"],"sourcesContent":["/**\n * Copyright (c) 2020-present, NDLA.\n *\n * This source code is licensed under the GPLv3 license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport type { TFunction } from \"i18next\";\nimport { type ReactNode, forwardRef, useCallback, useEffect, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useLocation } from \"react-router-dom\";\nimport { ArrowDownShortLine } from \"@ndla/icons\";\nimport {\n AccordionItem,\n AccordionItemContent,\n AccordionItemIndicator,\n type AccordionItemProps,\n AccordionItemTrigger,\n AccordionRoot,\n Heading,\n} from \"@ndla/primitives\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport { ArticleFootNotes } from \"./ArticleFootNotes\";\nimport type { FootNote } from \"../types\";\n\nconst Wrapper = styled(\"div\", {\n base: {\n // TODO: Figure out if we want to remove this margin. It's only here to add some gap between the article content and the byline.\n marginBlockStart: \"medium\",\n paddingBlockStart: \"xsmall\",\n borderTop: \"1px solid\",\n borderColor: \"stroke.subtle\",\n },\n});\n\nconst TextWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"3xsmall\",\n width: \"100%\",\n justifyContent: \"space-between\",\n paddingBlock: \"xsmall\",\n textStyle: \"body.medium\",\n '& [data-contributors=\"false\"]': {\n marginInlineStart: \"auto\",\n },\n },\n variants: {\n learningpath: {\n true: {},\n false: {\n tabletWide: {\n flexDirection: \"row\",\n },\n },\n },\n },\n});\n\ntype AuthorProps = {\n name: string;\n};\n\ntype SupplierProps = {\n name: string;\n};\n\ntype Props = {\n authors?: AuthorProps[];\n suppliers?: SupplierProps[];\n published?: string;\n licenseBox?: ReactNode;\n footnotes?: FootNote[];\n displayByline?: boolean;\n bylineType?: \"article\" | \"learningPath\" | \"external\";\n bylineSuffix?: ReactNode;\n};\n\nconst renderContributors = (contributors: SupplierProps[] | AuthorProps[], t: TFunction) => {\n const contributorsArray = contributors.map((contributor, index) => {\n if (index < 1) return contributor.name;\n const sep = index === contributors.length - 1 ? ` ${t(\"article.conjunction\")} ` : \", \";\n return `${sep}${contributor.name}`;\n });\n return contributorsArray.join(\"\");\n};\n\nconst getSuppliersText = (suppliers: SupplierProps[], t: TFunction) => {\n if (suppliers.length === 0) {\n return \"\";\n }\n return suppliers.length > 1\n ? t(\"article.multipleSuppliersLabel\", {\n names: renderContributors(suppliers, t),\n interpolation: { escapeValue: false },\n })\n : t(\"article.supplierLabel\", {\n name: renderContributors(suppliers, t),\n interpolation: { escapeValue: false },\n });\n};\n\nconst StyledAccordionRoot = styled(AccordionRoot, {\n base: {\n paddingBlockStart: \"xxlarge\",\n },\n});\n\nconst refRegexp = /note\\d/;\nconst footnotesAccordionId = \"footnotes\";\n\nexport const ArticleByline = ({\n authors = [],\n suppliers = [],\n footnotes,\n licenseBox,\n published,\n displayByline = true,\n bylineType = \"article\",\n bylineSuffix,\n}: Props) => {\n const { t } = useTranslation();\n const { pathname } = useLocation();\n const [openAccordions, setOpenAccordions] = useState<string[]>([]);\n const accordionItemValue = \"rulesForUse\";\n\n const onHashChange = useCallback(\n (e: HashChangeEvent) => {\n const hash = e.newURL.split(\"#\")[1];\n if (hash?.match(refRegexp) && !openAccordions.includes(footnotesAccordionId)) {\n setOpenAccordions([...openAccordions, footnotesAccordionId]);\n const el = document.getElementById(`#${hash}`);\n el?.click();\n el?.focus();\n }\n },\n [openAccordions],\n );\n\n useEffect(() => {\n setOpenAccordions((prev) => prev.filter((state) => state !== accordionItemValue));\n }, [pathname]);\n\n useEffect(() => {\n window.addEventListener(\"hashchange\", onHashChange);\n return () => window.removeEventListener(\"hashchange\", onHashChange);\n }, [onHashChange]);\n\n const showPrimaryContributors = suppliers.length > 0 || authors.length > 0;\n\n const authorLabel: Record<string, string> = {\n article: \"article.authorsLabel\",\n learningPath: \"article.authorsLabelLearningpath\",\n external: \"article.authorsLabelExternal\",\n };\n\n return (\n <Wrapper>\n {!!displayByline && (\n <TextWrapper learningpath={bylineType === \"learningPath\"}>\n {!!showPrimaryContributors && (\n <span>\n {authors.length > 0 &&\n `${t(authorLabel[bylineType], {\n names: renderContributors(authors, t),\n interpolation: { escapeValue: false },\n })}. `}\n {getSuppliersText(suppliers, t)}\n </span>\n )}\n {published ? (\n <div data-contributors={showPrimaryContributors}>\n {t(`${bylineType}.lastUpdated`)} {published}\n </div>\n ) : null}\n {bylineSuffix}\n </TextWrapper>\n )}\n {(!!licenseBox || !!footnotes?.length) && (\n <StyledAccordionRoot\n multiple\n value={openAccordions}\n onValueChange={(details) => setOpenAccordions(details.value)}\n >\n {!!licenseBox && (\n <ArticleBylineAccordionItem value={accordionItemValue} accordionTitle={t(\"article.useContent\")}>\n {licenseBox}\n </ArticleBylineAccordionItem>\n )}\n {!!footnotes?.length && (\n <ArticleBylineAccordionItem value={footnotesAccordionId} accordionTitle={t(\"article.footnotes\")}>\n <ArticleFootNotes footNotes={footnotes} />\n </ArticleBylineAccordionItem>\n )}\n </StyledAccordionRoot>\n )}\n </Wrapper>\n );\n};\n\ninterface ArticleBylineAccordionprops extends AccordionItemProps {\n accordionTitle: ReactNode;\n}\n\nexport const ArticleBylineAccordionItem = forwardRef<HTMLDivElement, ArticleBylineAccordionprops>(\n ({ value, accordionTitle, children, ...props }, ref) => {\n return (\n <AccordionItem value={value} ref={ref} {...props}>\n <Heading asChild consumeCss textStyle=\"label.medium\" fontWeight=\"bold\">\n <h2>\n <AccordionItemTrigger>\n {accordionTitle}\n <AccordionItemIndicator asChild>\n <ArrowDownShortLine />\n </AccordionItemIndicator>\n </AccordionItemTrigger>\n </h2>\n </Heading>\n <AccordionItemContent>{children}</AccordionItemContent>\n </AccordionItem>\n );\n },\n);\n"],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Text } from "@ndla/primitives";
|
|
2
|
+
import { styled } from "@ndla/styled-system/jsx";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
|
|
5
|
+
//#region src/Article/ArticleFootNotes.tsx
|
|
6
|
+
const citeDetailString = (description) => description ? `${description}. ` : "";
|
|
7
|
+
const StyledCite = styled("cite", { base: {
|
|
8
|
+
display: "flex",
|
|
9
|
+
alignItems: "center",
|
|
10
|
+
gap: "xsmall"
|
|
11
|
+
} });
|
|
12
|
+
const FootNote = ({ footNote }) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(Text, {
|
|
13
|
+
id: `note${footNote.ref}`,
|
|
14
|
+
asChild: true,
|
|
15
|
+
consumeCss: true,
|
|
16
|
+
textStyle: "body.medium",
|
|
17
|
+
children: /* @__PURE__ */ jsxs(StyledCite, { children: [
|
|
18
|
+
/* @__PURE__ */ jsx("a", {
|
|
19
|
+
href: `#ref${footNote.ref}`,
|
|
20
|
+
target: "_self",
|
|
21
|
+
children: footNote.ref
|
|
22
|
+
}),
|
|
23
|
+
`«${footNote.title}». ${footNote.authors.join(" ")}. ${citeDetailString(footNote.edition)}${citeDetailString(footNote.publisher)}${footNote.year}. `,
|
|
24
|
+
footNote.url ? /* @__PURE__ */ jsxs("a", {
|
|
25
|
+
href: footNote.url,
|
|
26
|
+
children: [footNote.url, "."]
|
|
27
|
+
}) : null
|
|
28
|
+
] })
|
|
29
|
+
}) });
|
|
30
|
+
const FootnoteList = styled("ol", { base: {
|
|
31
|
+
display: "flex",
|
|
32
|
+
flexDirection: "column",
|
|
33
|
+
gap: "medium",
|
|
34
|
+
listStyle: "none"
|
|
35
|
+
} });
|
|
36
|
+
const ArticleFootNotes = ({ footNotes }) => /* @__PURE__ */ jsx(FootnoteList, { children: footNotes.map((footNote) => /* @__PURE__ */ jsx(FootNote, { footNote }, footNote.ref)) });
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
export { ArticleFootNotes };
|
|
40
|
+
//# sourceMappingURL=ArticleFootNotes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ArticleFootNotes.js","names":["description: string | undefined"],"sources":["../../src/Article/ArticleFootNotes.tsx"],"sourcesContent":["/**\n * Copyright (c) 2017-present, NDLA.\n *\n * This source code is licensed under the GPLv3 license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport { Text } from \"@ndla/primitives\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport type { FootNote as FootNoteType } from \"../types\";\n\nconst citeDetailString = (description: string | undefined) => (description ? `${description}. ` : \"\");\n\ntype FootNoteProps = {\n footNote: FootNoteType;\n};\n\nconst StyledCite = styled(\"cite\", {\n base: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"xsmall\",\n },\n});\n\nconst FootNote = ({ footNote }: FootNoteProps) => (\n <li>\n <Text id={`note${footNote.ref}`} asChild consumeCss textStyle=\"body.medium\">\n <StyledCite>\n <a href={`#ref${footNote.ref}`} target=\"_self\">\n {footNote.ref}\n </a>\n {`«${footNote.title}». ${footNote.authors.join(\" \")}. ${citeDetailString(footNote.edition)}${citeDetailString(\n footNote.publisher,\n )}${footNote.year}. `}\n {footNote.url ? (\n <a href={footNote.url}>\n {footNote.url}\n {\".\"}\n </a>\n ) : null}\n </StyledCite>\n </Text>\n </li>\n);\n\ntype ArticleFootNotesProps = {\n footNotes: Array<FootNoteType>;\n};\n\nconst FootnoteList = styled(\"ol\", {\n base: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"medium\",\n listStyle: \"none\",\n },\n});\n\nexport const ArticleFootNotes = ({ footNotes }: ArticleFootNotesProps) => (\n <FootnoteList>\n {footNotes.map((footNote) => (\n <FootNote key={footNote.ref} footNote={footNote} />\n ))}\n </FootnoteList>\n);\n"],"mappings":";;;;;AAYA,MAAM,mBAAmB,CAACA,gBAAqC,eAAe,EAAE,YAAY,MAAM;AAMlG,MAAM,aAAa,OAAO,QAAQ,EAChC,MAAM;CACJ,SAAS;CACT,YAAY;CACZ,KAAK;AACN,EACF,EAAC;AAEF,MAAM,WAAW,CAAC,EAAE,UAAyB,qBAC3C,IAAC,kCACC,IAAC;CAAK,KAAK,MAAM,SAAS,IAAI;CAAG;CAAQ;CAAW,WAAU;2BAC5D,KAAC;kBACC,IAAC;GAAE,OAAO,MAAM,SAAS,IAAI;GAAG,QAAO;aACpC,SAAS;IACR;GACF,GAAG,SAAS,MAAM,KAAK,SAAS,QAAQ,KAAK,IAAI,CAAC,IAAI,iBAAiB,SAAS,QAAQ,CAAC,EAAE,iBAC3F,SAAS,UACV,CAAC,EAAE,SAAS,KAAK;EACjB,SAAS,sBACR,KAAC;GAAE,MAAM,SAAS;cACf,SAAS,KACT;IACC,GACF;KACO;EACR,GACJ;AAOP,MAAM,eAAe,OAAO,MAAM,EAChC,MAAM;CACJ,SAAS;CACT,eAAe;CACf,KAAK;CACL,WAAW;AACZ,EACF,EAAC;AAEF,MAAa,mBAAmB,CAAC,EAAE,WAAkC,qBACnE,IAAC,0BACE,UAAU,IAAI,CAAC,6BACd,IAAC,YAAsC,YAAxB,SAAS,IAA2B,CACnD,GACW"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { Controls_default } from "./Controls.js";
|
|
2
|
+
import { SpeechControl_default } from "./SpeechControl.js";
|
|
3
|
+
import { useId, useMemo, useState } from "react";
|
|
4
|
+
import { Button, Heading, Text } from "@ndla/primitives";
|
|
5
|
+
import { styled } from "@ndla/styled-system/jsx";
|
|
6
|
+
import { useTranslation } from "react-i18next";
|
|
7
|
+
import { SafeLink } from "@ndla/safelink";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
|
|
10
|
+
//#region src/AudioPlayer/AudioPlayer.tsx
|
|
11
|
+
const AudioPlayerWrapper = styled("div", { base: {
|
|
12
|
+
border: "1px solid",
|
|
13
|
+
borderColor: "stroke.default",
|
|
14
|
+
borderRadius: "xsmall",
|
|
15
|
+
boxShadow: "full",
|
|
16
|
+
marginBlockEnd: "4xsmall",
|
|
17
|
+
overflow: "hidden"
|
|
18
|
+
} });
|
|
19
|
+
const InfoWrapper = styled("div", { base: {
|
|
20
|
+
display: "flex",
|
|
21
|
+
tabletWideDown: { display: "block" }
|
|
22
|
+
} });
|
|
23
|
+
const ImageWrapper = styled("div", { base: {
|
|
24
|
+
display: "flex",
|
|
25
|
+
alignItems: "center",
|
|
26
|
+
flex: "1 0 auto",
|
|
27
|
+
width: "surface.4xsmall",
|
|
28
|
+
height: "surface.4xsmall",
|
|
29
|
+
overflow: "hidden",
|
|
30
|
+
"& img": {
|
|
31
|
+
width: "100%",
|
|
32
|
+
height: "100%",
|
|
33
|
+
objectFit: "cover"
|
|
34
|
+
},
|
|
35
|
+
desktop: {
|
|
36
|
+
width: "260px",
|
|
37
|
+
height: "260px"
|
|
38
|
+
},
|
|
39
|
+
tabletWideDown: {
|
|
40
|
+
maxHeight: "surface.small",
|
|
41
|
+
maxWidth: "100%",
|
|
42
|
+
width: "100%",
|
|
43
|
+
height: "auto"
|
|
44
|
+
}
|
|
45
|
+
} });
|
|
46
|
+
const TextWrapper = styled("div", { base: {
|
|
47
|
+
display: "flex",
|
|
48
|
+
alignItems: "flex-start",
|
|
49
|
+
flexDirection: "column",
|
|
50
|
+
gap: "xsmall",
|
|
51
|
+
padding: "xsmall",
|
|
52
|
+
width: "100%",
|
|
53
|
+
"&[data-has-image='true']": { tablet: {
|
|
54
|
+
paddingBlock: "xsmall",
|
|
55
|
+
paddingInline: "medium"
|
|
56
|
+
} }
|
|
57
|
+
} });
|
|
58
|
+
const TitleWrapper = styled("div", { base: {
|
|
59
|
+
display: "flex",
|
|
60
|
+
flexDirection: "column",
|
|
61
|
+
gap: "xsmall",
|
|
62
|
+
fontFamily: "sans",
|
|
63
|
+
tabletWide: {
|
|
64
|
+
width: "100%",
|
|
65
|
+
flexDirection: "row",
|
|
66
|
+
justifyContent: "space-between"
|
|
67
|
+
}
|
|
68
|
+
} });
|
|
69
|
+
const TextVersionWrapper = styled("div", { base: {
|
|
70
|
+
display: "flex",
|
|
71
|
+
flexDirection: "column",
|
|
72
|
+
gap: "xsmall",
|
|
73
|
+
borderBlockStart: "1px solid",
|
|
74
|
+
borderColor: "stroke.default",
|
|
75
|
+
paddingBlock: "medium",
|
|
76
|
+
paddingInline: "xsmall",
|
|
77
|
+
tablet: { paddingInline: "medium" }
|
|
78
|
+
} });
|
|
79
|
+
const TextVersionText = styled("div", { base: {
|
|
80
|
+
maxWidth: "surface.xlarge",
|
|
81
|
+
"& span > *": { whiteSpace: "pre-wrap" },
|
|
82
|
+
"& p:not(:first-child):not(:last-child)": { marginBlock: "small" },
|
|
83
|
+
"& p[data-align=\"center\"]": { textAlign: "center" },
|
|
84
|
+
"& p:has(span[dir=\"rtl\"])": { direction: "rtl" }
|
|
85
|
+
} });
|
|
86
|
+
const TextVersionButton = styled(Button, { base: { alignSelf: "flex-start" } });
|
|
87
|
+
const ShowMoreButton = styled(Button, { base: { marginInlineStart: "3xsmall" } });
|
|
88
|
+
const DESCRIPTION_MAX_LENGTH = 200;
|
|
89
|
+
const AudioPlayer = ({ src, title, subtitle, speech, description, img, textVersion }) => {
|
|
90
|
+
const { t } = useTranslation();
|
|
91
|
+
const [showTextVersion, setShowTextVersion] = useState(false);
|
|
92
|
+
const [showFullDescription, setShowFullDescription] = useState(false);
|
|
93
|
+
const truncatedDescription = useMemo(() => description?.slice(0, DESCRIPTION_MAX_LENGTH), [description]);
|
|
94
|
+
const textDescriptionId = useId();
|
|
95
|
+
if (speech) return /* @__PURE__ */ jsx(SpeechControl_default, {
|
|
96
|
+
src,
|
|
97
|
+
title
|
|
98
|
+
});
|
|
99
|
+
const toggleTextVersion = () => {
|
|
100
|
+
setShowTextVersion((curr) => !curr);
|
|
101
|
+
};
|
|
102
|
+
const textVersionButton = /* @__PURE__ */ jsx(TextVersionButton, {
|
|
103
|
+
variant: "secondary",
|
|
104
|
+
"aria-expanded": showTextVersion,
|
|
105
|
+
"aria-controls": textDescriptionId,
|
|
106
|
+
size: "small",
|
|
107
|
+
onClick: toggleTextVersion,
|
|
108
|
+
children: t(showTextVersion ? "audio.textVersion.close" : "audio.textVersion.heading")
|
|
109
|
+
});
|
|
110
|
+
return /* @__PURE__ */ jsxs(AudioPlayerWrapper, { children: [
|
|
111
|
+
/* @__PURE__ */ jsxs(InfoWrapper, { children: [!!img && /* @__PURE__ */ jsx(ImageWrapper, { children: /* @__PURE__ */ jsx("img", {
|
|
112
|
+
src: img.url,
|
|
113
|
+
alt: img.alt
|
|
114
|
+
}) }), /* @__PURE__ */ jsxs(TextWrapper, {
|
|
115
|
+
"data-has-image": !!img,
|
|
116
|
+
children: [
|
|
117
|
+
/* @__PURE__ */ jsxs(TitleWrapper, { children: [/* @__PURE__ */ jsxs("div", { children: [subtitle?.url ? /* @__PURE__ */ jsx(SafeLink, {
|
|
118
|
+
to: subtitle.url,
|
|
119
|
+
children: subtitle.title
|
|
120
|
+
}) : subtitle?.title, /* @__PURE__ */ jsx(Heading, {
|
|
121
|
+
asChild: true,
|
|
122
|
+
consumeCss: true,
|
|
123
|
+
textStyle: "title.large",
|
|
124
|
+
children: /* @__PURE__ */ jsx("h3", { children: title })
|
|
125
|
+
})] }), !!textVersion && !img && textVersionButton] }),
|
|
126
|
+
!!description && /* @__PURE__ */ jsxs(Text, {
|
|
127
|
+
textStyle: "body.medium",
|
|
128
|
+
children: [showFullDescription || description.length < DESCRIPTION_MAX_LENGTH ? description : `${truncatedDescription}...`, description.length > DESCRIPTION_MAX_LENGTH && /* @__PURE__ */ jsx(ShowMoreButton, {
|
|
129
|
+
variant: "link",
|
|
130
|
+
onClick: () => setShowFullDescription((p) => !p),
|
|
131
|
+
children: t(`audio.${showFullDescription ? "readLessDescriptionLabel" : "readMoreDescriptionLabel"}`)
|
|
132
|
+
})]
|
|
133
|
+
}),
|
|
134
|
+
!!textVersion && !!img && textVersionButton
|
|
135
|
+
]
|
|
136
|
+
})] }),
|
|
137
|
+
/* @__PURE__ */ jsx(Controls_default, {
|
|
138
|
+
src,
|
|
139
|
+
title
|
|
140
|
+
}),
|
|
141
|
+
!!textVersion && /* @__PURE__ */ jsxs(TextVersionWrapper, {
|
|
142
|
+
id: textDescriptionId,
|
|
143
|
+
hidden: !showTextVersion,
|
|
144
|
+
children: [/* @__PURE__ */ jsx(Heading, {
|
|
145
|
+
asChild: true,
|
|
146
|
+
textStyle: "title.medium",
|
|
147
|
+
consumeCss: true,
|
|
148
|
+
children: /* @__PURE__ */ jsx("h4", { children: t("audio.textVersion.heading") })
|
|
149
|
+
}), /* @__PURE__ */ jsx(TextVersionText, { children: textVersion })]
|
|
150
|
+
})
|
|
151
|
+
] });
|
|
152
|
+
};
|
|
153
|
+
var AudioPlayer_default = AudioPlayer;
|
|
154
|
+
|
|
155
|
+
//#endregion
|
|
156
|
+
export { AudioPlayer_default };
|
|
157
|
+
//# sourceMappingURL=AudioPlayer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AudioPlayer.js","names":["SpeechControl","Controls"],"sources":["../../src/AudioPlayer/AudioPlayer.tsx"],"sourcesContent":["/**\n * Copyright (c) 2017-present, NDLA.\n *\n * This source code is licensed under the GPLv3 license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport { type ReactNode, useId, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Heading, Text, Button } from \"@ndla/primitives\";\nimport { SafeLink } from \"@ndla/safelink\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport Controls from \"./Controls\";\nimport SpeechControl from \"./SpeechControl\";\n\n// TODO: Could the audio metadata be more tightly coupled to the audio player?\n\nconst AudioPlayerWrapper = styled(\"div\", {\n base: {\n border: \"1px solid\",\n borderColor: \"stroke.default\",\n borderRadius: \"xsmall\",\n boxShadow: \"full\",\n marginBlockEnd: \"4xsmall\",\n overflow: \"hidden\",\n },\n});\n\nconst InfoWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n tabletWideDown: {\n display: \"block\",\n },\n },\n});\n\nconst ImageWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n alignItems: \"center\",\n flex: \"1 0 auto\",\n width: \"surface.4xsmall\",\n height: \"surface.4xsmall\",\n overflow: \"hidden\",\n \"& img\": {\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n },\n desktop: {\n width: \"260px\",\n height: \"260px\",\n },\n tabletWideDown: {\n maxHeight: \"surface.small\",\n maxWidth: \"100%\",\n width: \"100%\",\n height: \"auto\",\n },\n },\n});\n\nconst TextWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n alignItems: \"flex-start\",\n flexDirection: \"column\",\n gap: \"xsmall\",\n padding: \"xsmall\",\n width: \"100%\",\n \"&[data-has-image='true']\": {\n tablet: {\n paddingBlock: \"xsmall\",\n paddingInline: \"medium\",\n },\n },\n },\n});\n\nconst TitleWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"xsmall\",\n fontFamily: \"sans\",\n tabletWide: {\n width: \"100%\",\n flexDirection: \"row\",\n justifyContent: \"space-between\",\n },\n },\n});\n\nconst TextVersionWrapper = styled(\"div\", {\n base: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"xsmall\",\n borderBlockStart: \"1px solid\",\n borderColor: \"stroke.default\",\n paddingBlock: \"medium\",\n paddingInline: \"xsmall\",\n tablet: {\n paddingInline: \"medium\",\n },\n },\n});\n\nconst TextVersionText = styled(\"div\", {\n base: {\n maxWidth: \"surface.xlarge\",\n \"& span > *\": {\n whiteSpace: \"pre-wrap\",\n },\n \"& p:not(:first-child):not(:last-child)\": {\n marginBlock: \"small\",\n },\n '& p[data-align=\"center\"]': {\n textAlign: \"center\",\n },\n '& p:has(span[dir=\"rtl\"])': {\n direction: \"rtl\",\n },\n },\n});\n\nconst TextVersionButton = styled(Button, {\n base: {\n alignSelf: \"flex-start\",\n },\n});\n\nconst ShowMoreButton = styled(Button, {\n base: {\n marginInlineStart: \"3xsmall\",\n },\n});\n\nconst DESCRIPTION_MAX_LENGTH = 200;\n\ntype Props = {\n src: string;\n title: string;\n subtitle?: {\n title: string;\n url?: string;\n };\n speech?: boolean;\n description?: string;\n textVersion?: ReactNode;\n img?: {\n url: string;\n alt: string;\n };\n};\n\nconst AudioPlayer = ({ src, title, subtitle, speech, description, img, textVersion }: Props) => {\n const { t } = useTranslation();\n const [showTextVersion, setShowTextVersion] = useState(false);\n const [showFullDescription, setShowFullDescription] = useState(false);\n const truncatedDescription = useMemo(() => description?.slice(0, DESCRIPTION_MAX_LENGTH), [description]);\n const textDescriptionId = useId();\n\n if (speech) {\n return <SpeechControl src={src} title={title} />;\n }\n\n const toggleTextVersion = () => {\n setShowTextVersion((curr) => !curr);\n };\n\n const textVersionButton = (\n <TextVersionButton\n variant=\"secondary\"\n aria-expanded={showTextVersion}\n aria-controls={textDescriptionId}\n size=\"small\"\n onClick={toggleTextVersion}\n >\n {t(showTextVersion ? \"audio.textVersion.close\" : \"audio.textVersion.heading\")}\n </TextVersionButton>\n );\n\n return (\n <AudioPlayerWrapper>\n <InfoWrapper>\n {!!img && (\n <ImageWrapper>\n <img src={img.url} alt={img.alt} />\n </ImageWrapper>\n )}\n <TextWrapper data-has-image={!!img}>\n <TitleWrapper>\n <div>\n {subtitle?.url ? <SafeLink to={subtitle.url}>{subtitle.title}</SafeLink> : subtitle?.title}\n <Heading asChild consumeCss textStyle=\"title.large\">\n <h3>{title}</h3>\n </Heading>\n </div>\n {!!textVersion && !img && textVersionButton}\n </TitleWrapper>\n {!!description && (\n <Text textStyle=\"body.medium\">\n {showFullDescription || description.length < DESCRIPTION_MAX_LENGTH\n ? description\n : `${truncatedDescription}...`}\n {description.length > DESCRIPTION_MAX_LENGTH && (\n <ShowMoreButton variant=\"link\" onClick={() => setShowFullDescription((p) => !p)}>\n {t(`audio.${showFullDescription ? \"readLessDescriptionLabel\" : \"readMoreDescriptionLabel\"}`)}\n </ShowMoreButton>\n )}\n </Text>\n )}\n {!!textVersion && !!img && textVersionButton}\n </TextWrapper>\n </InfoWrapper>\n <Controls src={src} title={title} />\n {!!textVersion && (\n <TextVersionWrapper id={textDescriptionId} hidden={!showTextVersion}>\n <Heading asChild textStyle=\"title.medium\" consumeCss>\n <h4>{t(\"audio.textVersion.heading\")}</h4>\n </Heading>\n <TextVersionText>{textVersion}</TextVersionText>\n </TextVersionWrapper>\n )}\n </AudioPlayerWrapper>\n );\n};\n\nexport default AudioPlayer;\n"],"mappings":"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"}
|