@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["CopyParagraphButton"],"sources":["../../src/CopyParagraphButton/index.tsx"],"sourcesContent":["/**\n * Copyright (c) 2021-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 CopyParagraphButton from \"./CopyParagraphButton\";\n\nexport { CopyParagraphButton };\nexport default CopyParagraphButton;\n"],"mappings":";;;AAWA,oCAAeA"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { EmbedByline } from "../LicenseByline/EmbedByline.js";
|
|
2
|
+
import { EmbedErrorPlaceholder_default } from "./EmbedErrorPlaceholder.js";
|
|
3
|
+
import { licenseAttributes } from "../utils/licenseAttributes.js";
|
|
4
|
+
import { AudioPlayer_default } from "../AudioPlayer/index.js";
|
|
5
|
+
import { Figure } from "@ndla/primitives";
|
|
6
|
+
import { styled } from "@ndla/styled-system/jsx";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
|
|
9
|
+
//#region src/Embed/AudioEmbed.tsx
|
|
10
|
+
const StyledFigure = styled(Figure, { base: { clear: "both" } });
|
|
11
|
+
const AudioEmbed = ({ embed, lang }) => {
|
|
12
|
+
const type = embed.embedData.type === "standard" ? "audio" : "podcast";
|
|
13
|
+
if (embed.status === "error") return /* @__PURE__ */ jsx(EmbedErrorPlaceholder_default, { type });
|
|
14
|
+
const { data, embedData } = embed;
|
|
15
|
+
if (embedData.type === "minimal") return /* @__PURE__ */ jsx(AudioPlayer_default, {
|
|
16
|
+
speech: true,
|
|
17
|
+
src: data.audioFile.url,
|
|
18
|
+
title: data.title.title
|
|
19
|
+
});
|
|
20
|
+
const subtitle = data.series ? {
|
|
21
|
+
title: data.series.title.title,
|
|
22
|
+
url: `/podkast/${data.series.id}`
|
|
23
|
+
} : void 0;
|
|
24
|
+
const coverPhoto = data.podcastMeta?.coverPhoto;
|
|
25
|
+
const img = coverPhoto && {
|
|
26
|
+
url: coverPhoto.url,
|
|
27
|
+
alt: coverPhoto.altText
|
|
28
|
+
};
|
|
29
|
+
const licenseProps = licenseAttributes(data.copyright.license.license, lang, embedData.url);
|
|
30
|
+
return /* @__PURE__ */ jsxs(StyledFigure, {
|
|
31
|
+
lang,
|
|
32
|
+
"data-embed-type": type,
|
|
33
|
+
...licenseProps,
|
|
34
|
+
children: [/* @__PURE__ */ jsx(AudioPlayer_default, {
|
|
35
|
+
description: data.podcastMeta?.introduction ?? "",
|
|
36
|
+
img,
|
|
37
|
+
src: data.audioFile.url,
|
|
38
|
+
textVersion: data.manuscript?.manuscript.length ? /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: data.manuscript.manuscript } }) : void 0,
|
|
39
|
+
title: data.title.title,
|
|
40
|
+
subtitle
|
|
41
|
+
}), /* @__PURE__ */ jsx(EmbedByline, {
|
|
42
|
+
error: false,
|
|
43
|
+
type: data.audioType === "standard" ? "audio" : "podcast",
|
|
44
|
+
copyright: embed.data.copyright
|
|
45
|
+
})]
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
var AudioEmbed_default = AudioEmbed;
|
|
49
|
+
|
|
50
|
+
//#endregion
|
|
51
|
+
export { AudioEmbed_default };
|
|
52
|
+
//# sourceMappingURL=AudioEmbed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AudioEmbed.js","names":["EmbedErrorPlaceholder","AudioPlayer"],"sources":["../../src/Embed/AudioEmbed.tsx"],"sourcesContent":["/**\n * Copyright (c) 2023-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 { Figure } from \"@ndla/primitives\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport type { AudioMetaData } from \"@ndla/types-embed\";\nimport EmbedErrorPlaceholder from \"./EmbedErrorPlaceholder\";\nimport type { Author } from \"./ImageEmbed\";\nimport AudioPlayer from \"../AudioPlayer\";\nimport { EmbedByline } from \"../LicenseByline\";\nimport { licenseAttributes } from \"../utils/licenseAttributes\";\n\nconst StyledFigure = styled(Figure, {\n base: {\n clear: \"both\",\n },\n});\n\ninterface Props {\n embed: AudioMetaData;\n lang?: string;\n}\n\nexport const getFirstNonEmptyLicenseCredits = (authors: {\n creators: Author[];\n rightsholders: Author[];\n processors: Author[];\n}) => Object.values(authors).find((i) => i.length > 0) ?? [];\n\nconst AudioEmbed = ({ embed, lang }: Props) => {\n const type = embed.embedData.type === \"standard\" ? \"audio\" : \"podcast\";\n if (embed.status === \"error\") {\n return <EmbedErrorPlaceholder type={type} />;\n }\n\n const { data, embedData } = embed;\n\n if (embedData.type === \"minimal\") {\n return <AudioPlayer speech src={data.audioFile.url} title={data.title.title} />;\n }\n\n const subtitle = data.series ? { title: data.series.title.title, url: `/podkast/${data.series.id}` } : undefined;\n\n const coverPhoto = data.podcastMeta?.coverPhoto;\n\n const img = coverPhoto && { url: coverPhoto.url, alt: coverPhoto.altText };\n\n const licenseProps = licenseAttributes(data.copyright.license.license, lang, embedData.url);\n\n return (\n <StyledFigure lang={lang} data-embed-type={type} {...licenseProps}>\n <AudioPlayer\n description={data.podcastMeta?.introduction ?? \"\"}\n img={img}\n src={data.audioFile.url}\n textVersion={\n data.manuscript?.manuscript.length ? (\n <div dangerouslySetInnerHTML={{ __html: data.manuscript.manuscript }} />\n ) : undefined\n }\n title={data.title.title}\n subtitle={subtitle}\n />\n <EmbedByline\n error={false}\n type={data.audioType === \"standard\" ? \"audio\" : \"podcast\"}\n copyright={embed.data.copyright}\n />\n </StyledFigure>\n );\n};\n\nexport default AudioEmbed;\n"],"mappings":";;;;;;;;;AAiBA,MAAM,eAAe,OAAO,QAAQ,EAClC,MAAM,EACJ,OAAO,OACR,EACF,EAAC;AAaF,MAAM,aAAa,CAAC,EAAE,OAAO,MAAa,KAAK;CAC7C,MAAM,OAAO,MAAM,UAAU,SAAS,aAAa,UAAU;AAC7D,KAAI,MAAM,WAAW,QACnB,wBAAO,IAACA,iCAA4B,OAAQ;CAG9C,MAAM,EAAE,MAAM,WAAW,GAAG;AAE5B,KAAI,UAAU,SAAS,UACrB,wBAAO,IAACC;EAAY;EAAO,KAAK,KAAK,UAAU;EAAK,OAAO,KAAK,MAAM;GAAS;CAGjF,MAAM,WAAW,KAAK,SAAS;EAAE,OAAO,KAAK,OAAO,MAAM;EAAO,MAAM,WAAW,KAAK,OAAO,GAAG;CAAG;CAEpG,MAAM,aAAa,KAAK,aAAa;CAErC,MAAM,MAAM,cAAc;EAAE,KAAK,WAAW;EAAK,KAAK,WAAW;CAAS;CAE1E,MAAM,eAAe,kBAAkB,KAAK,UAAU,QAAQ,SAAS,MAAM,UAAU,IAAI;AAE3F,wBACE,KAAC;EAAmB;EAAM,mBAAiB;EAAM,GAAI;6BACnD,IAACA;GACC,aAAa,KAAK,aAAa,gBAAgB;GAC1C;GACL,KAAK,KAAK,UAAU;GACpB,aACE,KAAK,YAAY,WAAW,yBAC1B,IAAC,SAAI,yBAAyB,EAAE,QAAQ,KAAK,WAAW,WAAY,IAAI;GAG5E,OAAO,KAAK,MAAM;GACR;IACV,kBACF,IAAC;GACC,OAAO;GACP,MAAM,KAAK,cAAc,aAAa,UAAU;GAChD,WAAW,MAAM,KAAK;IACtB;GACW;AAElB;AAED,yBAAe"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { EmbedByline } from "../LicenseByline/EmbedByline.js";
|
|
2
|
+
import { EmbedErrorPlaceholder_default } from "./EmbedErrorPlaceholder.js";
|
|
3
|
+
import { licenseAttributes } from "../utils/licenseAttributes.js";
|
|
4
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { Button, Figure } from "@ndla/primitives";
|
|
6
|
+
import { styled } from "@ndla/styled-system/jsx";
|
|
7
|
+
import parse from "html-react-parser";
|
|
8
|
+
import { useTranslation } from "react-i18next";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
|
|
11
|
+
//#region src/Embed/BrightcoveEmbed.tsx
|
|
12
|
+
const LinkedVideoButton = styled(Button, { base: { marginBlockStart: "3xsmall" } });
|
|
13
|
+
const BrightcoveIframe = styled("iframe", { base: {
|
|
14
|
+
border: 0,
|
|
15
|
+
height: "auto",
|
|
16
|
+
width: "100%"
|
|
17
|
+
} });
|
|
18
|
+
const isNumeric = (value) => !Number.isNaN(value - Number.parseFloat(value));
|
|
19
|
+
const getIframeProps = (data, sources) => {
|
|
20
|
+
const { account, videoid, player = "default" } = data;
|
|
21
|
+
const source = sources.filter((s) => s.width && s.height).toSorted((a, b) => a.height - b.height)[0];
|
|
22
|
+
return {
|
|
23
|
+
src: `https://players.brightcove.net/${account}/${player}_default/index.html?videoId=${videoid}`,
|
|
24
|
+
height: source?.height ?? "480",
|
|
25
|
+
width: source?.width ?? "640"
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
const BrightcoveEmbed = ({ embed, renderContext = "article", lang }) => {
|
|
29
|
+
const [showOriginalVideo, setShowOriginalVideo] = useState(true);
|
|
30
|
+
const { t } = useTranslation();
|
|
31
|
+
const iframeRef = useRef(null);
|
|
32
|
+
const { embedData } = embed;
|
|
33
|
+
const fallbackTitle = `${t("embed.type.video")}: ${embedData.videoid}`;
|
|
34
|
+
const parsedDescription = useMemo(() => {
|
|
35
|
+
if (embed.embedData.caption || renderContext === "article") return embed.embedData.caption ? parse(embed.embedData.caption) : void 0;
|
|
36
|
+
else if (embed.status === "success" && embed.data.description) return parse(embed.data.description);
|
|
37
|
+
}, [embed, renderContext]);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
const iframe = iframeRef.current;
|
|
40
|
+
if (iframe) {
|
|
41
|
+
const [width, height] = [parseInt(iframe.width), parseInt(iframe.height)];
|
|
42
|
+
iframe.style.aspectRatio = `${width}/${height}`;
|
|
43
|
+
iframe.width = "";
|
|
44
|
+
iframe.height = "";
|
|
45
|
+
}
|
|
46
|
+
}, []);
|
|
47
|
+
if (embed.status === "error") return /* @__PURE__ */ jsx(EmbedErrorPlaceholder_default, {
|
|
48
|
+
type: "video",
|
|
49
|
+
children: /* @__PURE__ */ jsx(BrightcoveIframe, {
|
|
50
|
+
ref: iframeRef,
|
|
51
|
+
title: embedData.alt || fallbackTitle,
|
|
52
|
+
"aria-label": embedData.alt || fallbackTitle,
|
|
53
|
+
...getIframeProps(embedData, []),
|
|
54
|
+
allow: "fullscreen; encrypted-media"
|
|
55
|
+
})
|
|
56
|
+
});
|
|
57
|
+
const { data } = embed;
|
|
58
|
+
const linkedVideoId = isNumeric(data.link?.text) ? data.link?.text : void 0;
|
|
59
|
+
const originalVideoProps = getIframeProps(embedData, data.sources);
|
|
60
|
+
const alternativeVideoProps = linkedVideoId ? getIframeProps({
|
|
61
|
+
...embedData,
|
|
62
|
+
videoid: linkedVideoId
|
|
63
|
+
}, data.sources) : void 0;
|
|
64
|
+
const licenseProps = licenseAttributes(data?.copyright?.license.license, lang, embedData.pageUrl);
|
|
65
|
+
const title = data.name?.trim() ? `${t("embed.type.video")}: ${data.name}` : fallbackTitle;
|
|
66
|
+
return /* @__PURE__ */ jsxs(Figure, {
|
|
67
|
+
"data-embed-type": "brightcove",
|
|
68
|
+
...licenseProps,
|
|
69
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
70
|
+
className: "brightcove-video",
|
|
71
|
+
children: /* @__PURE__ */ jsx(BrightcoveIframe, {
|
|
72
|
+
ref: iframeRef,
|
|
73
|
+
className: "original",
|
|
74
|
+
title,
|
|
75
|
+
"aria-label": title,
|
|
76
|
+
...alternativeVideoProps && !showOriginalVideo ? alternativeVideoProps : originalVideoProps,
|
|
77
|
+
allow: "fullscreen; encrypted-media"
|
|
78
|
+
})
|
|
79
|
+
}), /* @__PURE__ */ jsx(EmbedByline, {
|
|
80
|
+
type: "video",
|
|
81
|
+
copyright: data.copyright,
|
|
82
|
+
description: parsedDescription,
|
|
83
|
+
children: /* @__PURE__ */ jsx("div", { children: !!linkedVideoId && /* @__PURE__ */ jsx(LinkedVideoButton, {
|
|
84
|
+
size: "small",
|
|
85
|
+
variant: "secondary",
|
|
86
|
+
onClick: () => setShowOriginalVideo((p) => !p),
|
|
87
|
+
children: t(`figure.button.${!showOriginalVideo ? "original" : "alternative"}`)
|
|
88
|
+
}) })
|
|
89
|
+
})]
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
var BrightcoveEmbed_default = BrightcoveEmbed;
|
|
93
|
+
|
|
94
|
+
//#endregion
|
|
95
|
+
export { BrightcoveEmbed_default };
|
|
96
|
+
//# sourceMappingURL=BrightcoveEmbed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BrightcoveEmbed.js","names":["value: any","data: BrightcoveEmbedData","sources: BrightcoveVideoSource[]","EmbedErrorPlaceholder"],"sources":["../../src/Embed/BrightcoveEmbed.tsx"],"sourcesContent":["/**\n * Copyright (c) 2023-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 parse from \"html-react-parser\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Button, Figure } from \"@ndla/primitives\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport type { BrightcoveEmbedData, BrightcoveMetaData, BrightcoveVideoSource } from \"@ndla/types-embed\";\nimport EmbedErrorPlaceholder from \"./EmbedErrorPlaceholder\";\nimport type { RenderContext } from \"./types\";\nimport { EmbedByline } from \"../LicenseByline\";\nimport { licenseAttributes } from \"../utils/licenseAttributes\";\n\ninterface Props {\n embed: BrightcoveMetaData;\n renderContext?: RenderContext;\n lang?: string;\n}\n\nconst LinkedVideoButton = styled(Button, {\n base: {\n marginBlockStart: \"3xsmall\",\n },\n});\n\nconst BrightcoveIframe = styled(\"iframe\", {\n base: {\n border: 0,\n height: \"auto\",\n width: \"100%\",\n },\n});\n\nexport const makeIframeString = (url: string, width: string | number, height: string | number, title = \"\") => {\n const strippedWidth = typeof width === \"number\" ? width : width.replace(/\\s*px/, \"\");\n const strippedHeight = typeof height === \"number\" ? height : height.replace(/\\s*px/, \"\");\n const urlOrTitle = title || url;\n return `<iframe title=\"${urlOrTitle}\" aria-label=\"${urlOrTitle}\" src=\"${url}\" width=\"${strippedWidth}\" height=\"${strippedHeight}\" allowfullscreen scrolling=\"no\" frameborder=\"0\" loading=\"lazy\"></iframe>`;\n};\n\nexport const isNumeric = (value: any) => !Number.isNaN(value - Number.parseFloat(value));\n\nconst getIframeProps = (data: BrightcoveEmbedData, sources: BrightcoveVideoSource[]) => {\n const { account, videoid, player = \"default\" } = data;\n\n const source = sources.filter((s) => s.width && s.height).toSorted((a, b) => a!.height! - b.height!)[0];\n\n return {\n src: `https://players.brightcove.net/${account}/${player}_default/index.html?videoId=${videoid}`,\n height: source?.height ?? \"480\",\n width: source?.width ?? \"640\",\n };\n};\nconst BrightcoveEmbed = ({ embed, renderContext = \"article\", lang }: Props) => {\n const [showOriginalVideo, setShowOriginalVideo] = useState(true);\n const { t } = useTranslation();\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const { embedData } = embed;\n const fallbackTitle = `${t(\"embed.type.video\")}: ${embedData.videoid}`;\n const parsedDescription = useMemo(() => {\n if (embed.embedData.caption || renderContext === \"article\") {\n return embed.embedData.caption ? parse(embed.embedData.caption) : undefined;\n } else if (embed.status === \"success\" && embed.data.description) {\n return parse(embed.data.description);\n }\n }, [embed, renderContext]);\n\n useEffect(() => {\n const iframe = iframeRef.current;\n if (iframe) {\n const [width, height] = [parseInt(iframe.width), parseInt(iframe.height)];\n iframe.style.aspectRatio = `${width}/${height}`;\n iframe.width = \"\";\n iframe.height = \"\";\n }\n }, []);\n if (embed.status === \"error\") {\n return (\n <EmbedErrorPlaceholder type=\"video\">\n <BrightcoveIframe\n ref={iframeRef}\n title={embedData.alt || fallbackTitle}\n aria-label={embedData.alt || fallbackTitle}\n {...getIframeProps(embedData, [])}\n allow=\"fullscreen; encrypted-media\"\n />\n </EmbedErrorPlaceholder>\n );\n }\n const { data } = embed;\n\n const linkedVideoId = isNumeric(data.link?.text) ? data.link?.text : undefined;\n\n const originalVideoProps = getIframeProps(embedData, data.sources);\n const alternativeVideoProps = linkedVideoId\n ? getIframeProps({ ...embedData, videoid: linkedVideoId }, data.sources)\n : undefined;\n\n const licenseProps = licenseAttributes(data?.copyright?.license.license, lang, embedData.pageUrl);\n\n const title = data.name?.trim() ? `${t(\"embed.type.video\")}: ${data.name}` : fallbackTitle;\n\n return (\n <Figure data-embed-type=\"brightcove\" {...licenseProps}>\n <div className=\"brightcove-video\">\n <BrightcoveIframe\n ref={iframeRef}\n className=\"original\"\n title={title}\n aria-label={title}\n {...(alternativeVideoProps && !showOriginalVideo ? alternativeVideoProps : originalVideoProps)}\n allow=\"fullscreen; encrypted-media\"\n />\n </div>\n <EmbedByline type=\"video\" copyright={data.copyright!} description={parsedDescription}>\n <div>\n {!!linkedVideoId && (\n <LinkedVideoButton size=\"small\" variant=\"secondary\" onClick={() => setShowOriginalVideo((p) => !p)}>\n {t(`figure.button.${!showOriginalVideo ? \"original\" : \"alternative\"}`)}\n </LinkedVideoButton>\n )}\n </div>\n </EmbedByline>\n </Figure>\n );\n};\n\nexport default BrightcoveEmbed;\n"],"mappings":";;;;;;;;;;;AAyBA,MAAM,oBAAoB,OAAO,QAAQ,EACvC,MAAM,EACJ,kBAAkB,UACnB,EACF,EAAC;AAEF,MAAM,mBAAmB,OAAO,UAAU,EACxC,MAAM;CACJ,QAAQ;CACR,QAAQ;CACR,OAAO;AACR,EACF,EAAC;AASF,MAAa,YAAY,CAACA,WAAgB,OAAO,MAAM,QAAQ,OAAO,WAAW,MAAM,CAAC;AAExF,MAAM,iBAAiB,CAACC,MAA2BC,YAAqC;CACtF,MAAM,EAAE,SAAS,SAAS,SAAS,WAAW,GAAG;CAEjD,MAAM,SAAS,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,EAAG,SAAU,EAAE,OAAQ,CAAC;AAErG,QAAO;EACL,MAAM,iCAAiC,QAAQ,GAAG,OAAO,8BAA8B,QAAQ;EAC/F,QAAQ,QAAQ,UAAU;EAC1B,OAAO,QAAQ,SAAS;CACzB;AACF;AACD,MAAM,kBAAkB,CAAC,EAAE,OAAO,gBAAgB,WAAW,MAAa,KAAK;CAC7E,MAAM,CAAC,mBAAmB,qBAAqB,GAAG,SAAS,KAAK;CAChE,MAAM,EAAE,GAAG,GAAG,gBAAgB;CAC9B,MAAM,YAAY,OAA0B,KAAK;CACjD,MAAM,EAAE,WAAW,GAAG;CACtB,MAAM,iBAAiB,EAAE,EAAE,mBAAmB,CAAC,IAAI,UAAU,QAAQ;CACrE,MAAM,oBAAoB,QAAQ,MAAM;AACtC,MAAI,MAAM,UAAU,WAAW,kBAAkB,UAC/C,QAAO,MAAM,UAAU,UAAU,MAAM,MAAM,UAAU,QAAQ;WACtD,MAAM,WAAW,aAAa,MAAM,KAAK,YAClD,QAAO,MAAM,MAAM,KAAK,YAAY;CAEvC,GAAE,CAAC,OAAO,aAAc,EAAC;AAE1B,WAAU,MAAM;EACd,MAAM,SAAS,UAAU;AACzB,MAAI,QAAQ;GACV,MAAM,CAAC,OAAO,OAAO,GAAG,CAAC,SAAS,OAAO,MAAM,EAAE,SAAS,OAAO,OAAO,AAAC;AACzE,UAAO,MAAM,eAAe,EAAE,MAAM,GAAG,OAAO;AAC9C,UAAO,QAAQ;AACf,UAAO,SAAS;EACjB;CACF,GAAE,CAAE,EAAC;AACN,KAAI,MAAM,WAAW,QACnB,wBACE,IAACC;EAAsB,MAAK;4BAC1B,IAAC;GACC,KAAK;GACL,OAAO,UAAU,OAAO;GACxB,cAAY,UAAU,OAAO;GAC7B,GAAI,eAAe,WAAW,CAAE,EAAC;GACjC,OAAM;IACN;GACoB;CAG5B,MAAM,EAAE,MAAM,GAAG;CAEjB,MAAM,gBAAgB,UAAU,KAAK,MAAM,KAAK,GAAG,KAAK,MAAM;CAE9D,MAAM,qBAAqB,eAAe,WAAW,KAAK,QAAQ;CAClE,MAAM,wBAAwB,gBAC1B,eAAe;EAAE,GAAG;EAAW,SAAS;CAAe,GAAE,KAAK,QAAQ;CAG1E,MAAM,eAAe,kBAAkB,MAAM,WAAW,QAAQ,SAAS,MAAM,UAAU,QAAQ;CAEjG,MAAM,QAAQ,KAAK,MAAM,MAAM,IAAI,EAAE,EAAE,mBAAmB,CAAC,IAAI,KAAK,KAAK,IAAI;AAE7E,wBACE,KAAC;EAAO,mBAAgB;EAAa,GAAI;6BACvC,IAAC;GAAI,WAAU;6BACb,IAAC;IACC,KAAK;IACL,WAAU;IACH;IACP,cAAY;IACZ,GAAK,0BAA0B,oBAAoB,wBAAwB;IAC3E,OAAM;KACN;IACE,kBACN,IAAC;GAAY,MAAK;GAAQ,WAAW,KAAK;GAAY,aAAa;6BACjE,IAAC,qBACI,iCACD,IAAC;IAAkB,MAAK;IAAQ,SAAQ;IAAY,SAAS,MAAM,qBAAqB,CAAC,OAAO,EAAE;cAC/F,GAAG,iBAAiB,oBAAoB,aAAa,cAAc,EAAE;KACpD,GAElB;IACM;GACP;AAEZ;AAED,8BAAe"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { EmbedErrorPlaceholder_default } from "./EmbedErrorPlaceholder.js";
|
|
2
|
+
import { CodeBlock_default } from "../CodeBlock/CodeBlock.js";
|
|
3
|
+
import { codeLanguageOptions } from "../CodeBlock/codeLanguageOptions.js";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
import { Button, Figure } from "@ndla/primitives";
|
|
6
|
+
import { styled } from "@ndla/styled-system/jsx";
|
|
7
|
+
import { useTranslation } from "react-i18next";
|
|
8
|
+
import { CheckLine, FileCopyLine } from "@ndla/icons";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
import { copyTextToClipboard } from "@ndla/util";
|
|
11
|
+
|
|
12
|
+
//#region src/Embed/CodeEmbed.tsx
|
|
13
|
+
const StyledFigCaption = styled("figcaption", { base: {
|
|
14
|
+
textStyle: "label.large",
|
|
15
|
+
fontWeight: "bold"
|
|
16
|
+
} });
|
|
17
|
+
const StyledFigure = styled(Figure, { base: {
|
|
18
|
+
clear: "both",
|
|
19
|
+
"& > *:not(:where(:first-child))": { marginBlockStart: "xsmall" }
|
|
20
|
+
} });
|
|
21
|
+
const getTitleFromFormat = (format) => {
|
|
22
|
+
const selectedLanguage = codeLanguageOptions.find((item) => item.format === format);
|
|
23
|
+
if (selectedLanguage) return selectedLanguage.title;
|
|
24
|
+
return;
|
|
25
|
+
};
|
|
26
|
+
const CodeEmbed = ({ embed }) => {
|
|
27
|
+
const [isCopied, setIsCopied] = useState(false);
|
|
28
|
+
const { t } = useTranslation();
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (isCopied) {
|
|
31
|
+
const timer = setInterval(() => setIsCopied(false), 3e3);
|
|
32
|
+
return () => {
|
|
33
|
+
clearTimeout(timer);
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}, [isCopied]);
|
|
37
|
+
if (embed.status === "error") return /* @__PURE__ */ jsx(EmbedErrorPlaceholder_default, { type: "code" });
|
|
38
|
+
return /* @__PURE__ */ jsxs(StyledFigure, {
|
|
39
|
+
"data-embed-type": "code-block",
|
|
40
|
+
children: [
|
|
41
|
+
/* @__PURE__ */ jsx(StyledFigCaption, { children: embed.embedData.title || getTitleFromFormat(embed.embedData.codeFormat) }),
|
|
42
|
+
/* @__PURE__ */ jsx(CodeBlock_default, {
|
|
43
|
+
highlightedCode: embed.status === "success" ? embed.data.highlightedCode : "",
|
|
44
|
+
format: embed.embedData.codeFormat
|
|
45
|
+
}),
|
|
46
|
+
/* @__PURE__ */ jsxs(Button, {
|
|
47
|
+
variant: "secondary",
|
|
48
|
+
onClick: () => {
|
|
49
|
+
copyTextToClipboard(embed.status === "success" ? embed.data.decodedContent : "");
|
|
50
|
+
setIsCopied(true);
|
|
51
|
+
},
|
|
52
|
+
children: [isCopied ? /* @__PURE__ */ jsx(CheckLine, {}) : /* @__PURE__ */ jsx(FileCopyLine, {}), isCopied ? t("codeBlock.copiedCode") : t("codeBlock.copyCode")]
|
|
53
|
+
})
|
|
54
|
+
]
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
var CodeEmbed_default = CodeEmbed;
|
|
58
|
+
|
|
59
|
+
//#endregion
|
|
60
|
+
export { CodeEmbed_default };
|
|
61
|
+
//# sourceMappingURL=CodeEmbed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodeEmbed.js","names":["format: string","item: ICodeLangugeOption","EmbedErrorPlaceholder","CodeBlock"],"sources":["../../src/Embed/CodeEmbed.tsx"],"sourcesContent":["/**\n * Copyright (c) 2023-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 { useEffect, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { FileCopyLine, CheckLine } from \"@ndla/icons\";\nimport { Button, Figure } from \"@ndla/primitives\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport type { CodeMetaData } from \"@ndla/types-embed\";\nimport { copyTextToClipboard } from \"@ndla/util\";\nimport EmbedErrorPlaceholder from \"./EmbedErrorPlaceholder\";\nimport { CodeBlock, codeLanguageOptions } from \"../CodeBlock\";\nimport type { ICodeLangugeOption } from \"../CodeBlock/codeLanguageOptions\";\n\ninterface Props {\n embed: CodeMetaData;\n}\n\nconst StyledFigCaption = styled(\"figcaption\", {\n base: {\n textStyle: \"label.large\",\n fontWeight: \"bold\",\n },\n});\n\nconst StyledFigure = styled(Figure, {\n base: {\n clear: \"both\",\n // We apply margin here to allow for the float and size props on figure to work as intended.\n \"& > *:not(:where(:first-child))\": {\n marginBlockStart: \"xsmall\",\n },\n },\n});\n\nconst getTitleFromFormat = (format: string) => {\n const selectedLanguage = codeLanguageOptions.find((item: ICodeLangugeOption) => item.format === format);\n if (selectedLanguage) {\n return selectedLanguage.title;\n }\n return;\n};\n\nconst CodeEmbed = ({ embed }: Props) => {\n const [isCopied, setIsCopied] = useState(false);\n const { t } = useTranslation();\n\n useEffect(() => {\n if (isCopied) {\n const timer = setInterval(() => setIsCopied(false), 3000);\n // ensure interval is cleared - also if unmounted\n return () => {\n clearTimeout(timer);\n };\n }\n }, [isCopied]);\n\n if (embed.status === \"error\") {\n return <EmbedErrorPlaceholder type=\"code\" />;\n }\n\n return (\n <StyledFigure data-embed-type=\"code-block\">\n <StyledFigCaption>{embed.embedData.title || getTitleFromFormat(embed.embedData.codeFormat)}</StyledFigCaption>\n <CodeBlock\n highlightedCode={embed.status === \"success\" ? embed.data.highlightedCode : \"\"}\n format={embed.embedData.codeFormat}\n />\n <Button\n variant=\"secondary\"\n onClick={() => {\n copyTextToClipboard(embed.status === \"success\" ? embed.data.decodedContent : \"\");\n setIsCopied(true);\n }}\n >\n {isCopied ? <CheckLine /> : <FileCopyLine />}\n {isCopied ? t(\"codeBlock.copiedCode\") : t(\"codeBlock.copyCode\")}\n </Button>\n </StyledFigure>\n );\n};\n\nexport default CodeEmbed;\n"],"mappings":";;;;;;;;;;;;AAuBA,MAAM,mBAAmB,OAAO,cAAc,EAC5C,MAAM;CACJ,WAAW;CACX,YAAY;AACb,EACF,EAAC;AAEF,MAAM,eAAe,OAAO,QAAQ,EAClC,MAAM;CACJ,OAAO;CAEP,mCAAmC,EACjC,kBAAkB,SACnB;AACF,EACF,EAAC;AAEF,MAAM,qBAAqB,CAACA,WAAmB;CAC7C,MAAM,mBAAmB,oBAAoB,KAAK,CAACC,SAA6B,KAAK,WAAW,OAAO;AACvG,KAAI,iBACF,QAAO,iBAAiB;AAE1B;AACD;AAED,MAAM,YAAY,CAAC,EAAE,OAAc,KAAK;CACtC,MAAM,CAAC,UAAU,YAAY,GAAG,SAAS,MAAM;CAC/C,MAAM,EAAE,GAAG,GAAG,gBAAgB;AAE9B,WAAU,MAAM;AACd,MAAI,UAAU;GACZ,MAAM,QAAQ,YAAY,MAAM,YAAY,MAAM,EAAE,IAAK;AAEzD,UAAO,MAAM;AACX,iBAAa,MAAM;GACpB;EACF;CACF,GAAE,CAAC,QAAS,EAAC;AAEd,KAAI,MAAM,WAAW,QACnB,wBAAO,IAACC,iCAAsB,MAAK,SAAS;AAG9C,wBACE,KAAC;EAAa,mBAAgB;;mBAC5B,IAAC,8BAAkB,MAAM,UAAU,SAAS,mBAAmB,MAAM,UAAU,WAAW,GAAoB;mBAC9G,IAACC;IACC,iBAAiB,MAAM,WAAW,YAAY,MAAM,KAAK,kBAAkB;IAC3E,QAAQ,MAAM,UAAU;KACxB;mBACF,KAAC;IACC,SAAQ;IACR,SAAS,MAAM;AACb,yBAAoB,MAAM,WAAW,YAAY,MAAM,KAAK,iBAAiB,GAAG;AAChF,iBAAY,KAAK;IAClB;eAEA,2BAAW,IAAC,cAAY,mBAAG,IAAC,iBAAe,EAC3C,WAAW,EAAE,uBAAuB,GAAG,EAAE,qBAAqB;KACxD;;GACI;AAElB;AAED,wBAAe"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { EmbedErrorPlaceholder_default } from "./EmbedErrorPlaceholder.js";
|
|
2
|
+
import { ConceptInlineTriggerButton } from "./ConceptInlineTriggerButton.js";
|
|
3
|
+
import { GlossEmbed } from "./GlossEmbed.js";
|
|
4
|
+
import { Concept } from "../Concept/Concept.js";
|
|
5
|
+
import { forwardRef, useMemo, useRef } from "react";
|
|
6
|
+
import { PopoverContent, PopoverRoot, PopoverTrigger } from "@ndla/primitives";
|
|
7
|
+
import { styled } from "@ndla/styled-system/jsx";
|
|
8
|
+
import parse from "html-react-parser";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
import { Portal } from "@ark-ui/react";
|
|
11
|
+
|
|
12
|
+
//#region src/Embed/ConceptEmbed.tsx
|
|
13
|
+
const StyledPopoverContent = styled(PopoverContent, { base: {
|
|
14
|
+
width: "surface.xlarge",
|
|
15
|
+
maxHeight: "50vh",
|
|
16
|
+
overflowY: "auto"
|
|
17
|
+
} });
|
|
18
|
+
const ConceptEmbed = ({ embed, renderContext, lang, previewAlt }) => {
|
|
19
|
+
const parsedContent = useMemo(() => {
|
|
20
|
+
if (embed.status === "error" || !embed.data.concept.content) return void 0;
|
|
21
|
+
return parse(embed.data.concept.content.htmlContent);
|
|
22
|
+
}, [embed]);
|
|
23
|
+
if (embed.status === "error" && embed.embedData.type === "inline") return /* @__PURE__ */ jsx("span", { children: embed.embedData.linkText });
|
|
24
|
+
if (embed.status === "error") return /* @__PURE__ */ jsx(EmbedErrorPlaceholder_default, { type: "gloss" });
|
|
25
|
+
const { concept, visualElement } = embed.data;
|
|
26
|
+
if (embed.data.concept.glossData) return /* @__PURE__ */ jsx(GlossEmbed, { embed });
|
|
27
|
+
if (embed.embedData.type === "inline") return /* @__PURE__ */ jsx(InlineConcept, {
|
|
28
|
+
previewAlt,
|
|
29
|
+
linkText: embed.embedData.linkText,
|
|
30
|
+
copyright: concept.copyright,
|
|
31
|
+
visualElement,
|
|
32
|
+
lang,
|
|
33
|
+
title: concept.title.title,
|
|
34
|
+
source: concept.source,
|
|
35
|
+
children: parsedContent
|
|
36
|
+
});
|
|
37
|
+
return /* @__PURE__ */ jsx(BlockConcept, {
|
|
38
|
+
previewAlt,
|
|
39
|
+
copyright: concept.copyright,
|
|
40
|
+
visualElement,
|
|
41
|
+
lang,
|
|
42
|
+
title: renderContext === "embed" ? void 0 : concept.title.title,
|
|
43
|
+
source: concept.source,
|
|
44
|
+
children: parsedContent
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
const InlineConcept = forwardRef(({ linkText, copyright, visualElement, previewAlt, lang, children, title, source,...rest }, ref) => {
|
|
48
|
+
const contentRef = useRef(null);
|
|
49
|
+
return /* @__PURE__ */ jsxs(PopoverRoot, {
|
|
50
|
+
initialFocusEl: () => contentRef.current,
|
|
51
|
+
children: [/* @__PURE__ */ jsx(PopoverTrigger, {
|
|
52
|
+
asChild: true,
|
|
53
|
+
ref,
|
|
54
|
+
...rest,
|
|
55
|
+
children: /* @__PURE__ */ jsx(ConceptInlineTriggerButton, { children: linkText })
|
|
56
|
+
}), /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(StyledPopoverContent, {
|
|
57
|
+
ref: contentRef,
|
|
58
|
+
children: /* @__PURE__ */ jsx(Concept, {
|
|
59
|
+
copyright,
|
|
60
|
+
visualElement,
|
|
61
|
+
title,
|
|
62
|
+
lang,
|
|
63
|
+
source,
|
|
64
|
+
previewAlt,
|
|
65
|
+
children
|
|
66
|
+
})
|
|
67
|
+
}) })]
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
const BlockConcept = forwardRef((props, ref) => /* @__PURE__ */ jsx(Concept, {
|
|
71
|
+
...props,
|
|
72
|
+
"data-embed-type": "concept",
|
|
73
|
+
ref
|
|
74
|
+
}));
|
|
75
|
+
|
|
76
|
+
//#endregion
|
|
77
|
+
export { BlockConcept, ConceptEmbed, InlineConcept };
|
|
78
|
+
//# sourceMappingURL=ConceptEmbed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConceptEmbed.js","names":["EmbedErrorPlaceholder"],"sources":["../../src/Embed/ConceptEmbed.tsx"],"sourcesContent":["/**\n * Copyright (c) 2024-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 parse from \"html-react-parser\";\nimport { forwardRef, useMemo, useRef } from \"react\";\nimport { Portal } from \"@ark-ui/react\";\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from \"@ndla/primitives\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport type { ConceptMetaData } from \"@ndla/types-embed\";\nimport { ConceptInlineTriggerButton } from \"./ConceptInlineTriggerButton\";\nimport EmbedErrorPlaceholder from \"./EmbedErrorPlaceholder\";\nimport { GlossEmbed } from \"./GlossEmbed\";\nimport type { RenderContext } from \"./types\";\nimport { Concept, type ConceptProps } from \"../Concept/Concept\";\n\ninterface BaseProps {\n renderContext?: RenderContext;\n lang?: string;\n previewAlt?: boolean;\n}\n\ninterface Props extends BaseProps {\n embed: ConceptMetaData;\n}\n\nconst StyledPopoverContent = styled(PopoverContent, {\n base: {\n width: \"surface.xlarge\",\n maxHeight: \"50vh\",\n overflowY: \"auto\",\n },\n});\n\nexport const ConceptEmbed = ({ embed, renderContext, lang, previewAlt }: Props) => {\n const parsedContent = useMemo(() => {\n if (embed.status === \"error\" || !embed.data.concept.content) return undefined;\n return parse(embed.data.concept.content.htmlContent);\n }, [embed]);\n\n if (embed.status === \"error\" && embed.embedData.type === \"inline\") {\n return <span>{embed.embedData.linkText}</span>;\n }\n if (embed.status === \"error\") {\n // TODO: This could be either concept or gloss. We don't know if it errors out. :)\n return <EmbedErrorPlaceholder type=\"gloss\" />;\n }\n\n const { concept, visualElement } = embed.data;\n\n // TODO: Consider whether we should do this in article-converter instead.\n if (embed.data.concept.glossData) {\n return <GlossEmbed embed={embed} />;\n }\n\n if (embed.embedData.type === \"inline\") {\n return (\n <InlineConcept\n previewAlt={previewAlt}\n linkText={embed.embedData.linkText}\n copyright={concept.copyright}\n visualElement={visualElement}\n lang={lang}\n title={concept.title.title}\n source={concept.source}\n >\n {parsedContent}\n </InlineConcept>\n );\n }\n\n return (\n <BlockConcept\n previewAlt={previewAlt}\n copyright={concept.copyright}\n visualElement={visualElement}\n lang={lang}\n title={renderContext === \"embed\" ? undefined : concept.title.title}\n source={concept.source}\n >\n {parsedContent}\n </BlockConcept>\n );\n};\n\nexport interface InlineConceptProps extends ConceptProps, BaseProps {\n linkText?: string;\n source?: string;\n}\n\nexport const InlineConcept = forwardRef<HTMLSpanElement, InlineConceptProps>(\n ({ linkText, copyright, visualElement, previewAlt, lang, children, title, source, ...rest }, ref) => {\n const contentRef = useRef<HTMLDivElement>(null);\n return (\n <PopoverRoot initialFocusEl={() => contentRef.current}>\n {/* @ts-expect-error placing ref and rest on popover trigger somehow removes a bug where the popover target becomes a bit bigger */}\n <PopoverTrigger asChild ref={ref} {...rest}>\n <ConceptInlineTriggerButton>{linkText}</ConceptInlineTriggerButton>\n </PopoverTrigger>\n <Portal>\n <StyledPopoverContent ref={contentRef}>\n <Concept\n copyright={copyright}\n visualElement={visualElement}\n title={title}\n lang={lang}\n source={source}\n previewAlt={previewAlt}\n >\n {children}\n </Concept>\n </StyledPopoverContent>\n </Portal>\n </PopoverRoot>\n );\n },\n);\n\nexport interface BlockConceptProps extends ConceptProps {}\n\nexport const BlockConcept = forwardRef<HTMLElement, BlockConceptProps>((props, ref) => (\n <Concept {...props} data-embed-type=\"concept\" ref={ref} />\n));\n"],"mappings":";;;;;;;;;;;;AA8BA,MAAM,uBAAuB,OAAO,gBAAgB,EAClD,MAAM;CACJ,OAAO;CACP,WAAW;CACX,WAAW;AACZ,EACF,EAAC;AAEF,MAAa,eAAe,CAAC,EAAE,OAAO,eAAe,MAAM,YAAmB,KAAK;CACjF,MAAM,gBAAgB,QAAQ,MAAM;AAClC,MAAI,MAAM,WAAW,YAAY,MAAM,KAAK,QAAQ,QAAS;AAC7D,SAAO,MAAM,MAAM,KAAK,QAAQ,QAAQ,YAAY;CACrD,GAAE,CAAC,KAAM,EAAC;AAEX,KAAI,MAAM,WAAW,WAAW,MAAM,UAAU,SAAS,SACvD,wBAAO,IAAC,oBAAM,MAAM,UAAU,WAAgB;AAEhD,KAAI,MAAM,WAAW,QAEnB,wBAAO,IAACA,iCAAsB,MAAK,UAAU;CAG/C,MAAM,EAAE,SAAS,eAAe,GAAG,MAAM;AAGzC,KAAI,MAAM,KAAK,QAAQ,UACrB,wBAAO,IAAC,cAAkB,QAAS;AAGrC,KAAI,MAAM,UAAU,SAAS,SAC3B,wBACE,IAAC;EACa;EACZ,UAAU,MAAM,UAAU;EAC1B,WAAW,QAAQ;EACJ;EACT;EACN,OAAO,QAAQ,MAAM;EACrB,QAAQ,QAAQ;YAEf;GACa;AAIpB,wBACE,IAAC;EACa;EACZ,WAAW,QAAQ;EACJ;EACT;EACN,OAAO,kBAAkB,mBAAsB,QAAQ,MAAM;EAC7D,QAAQ,QAAQ;YAEf;GACY;AAElB;AAOD,MAAa,gBAAgB,WAC3B,CAAC,EAAE,UAAU,WAAW,eAAe,YAAY,MAAM,UAAU,OAAO,OAAQ,GAAG,MAAM,EAAE,QAAQ;CACnG,MAAM,aAAa,OAAuB,KAAK;AAC/C,wBACE,KAAC;EAAY,gBAAgB,MAAM,WAAW;6BAE5C,IAAC;GAAe;GAAa;GAAK,GAAI;6BACpC,IAAC,wCAA4B,WAAsC;IACpD,kBACjB,IAAC,oCACC,IAAC;GAAqB,KAAK;6BACzB,IAAC;IACY;IACI;IACR;IACD;IACE;IACI;IAEX;KACO;IACW,GAChB;GACG;AAEjB,EACF;AAID,MAAa,eAAe,WAA2C,CAAC,OAAO,wBAC7E,IAAC;CAAQ,GAAI;CAAO,mBAAgB;CAAe;EAAO,CAC1D"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { InlineTriggerButton } from "./InlineTriggerButton.js";
|
|
2
|
+
import { styled } from "@ndla/styled-system/jsx";
|
|
3
|
+
|
|
4
|
+
//#region src/Embed/ConceptInlineTriggerButton.tsx
|
|
5
|
+
const ConceptInlineTriggerButton = styled(InlineTriggerButton, { base: {
|
|
6
|
+
position: "relative",
|
|
7
|
+
overflow: "visible",
|
|
8
|
+
borderBottom: "1px solid",
|
|
9
|
+
borderStyle: "dashed",
|
|
10
|
+
borderColor: "stroke.hover",
|
|
11
|
+
paddingBlockStart: "5xsmall",
|
|
12
|
+
width: "fit-content",
|
|
13
|
+
cursor: "pointer",
|
|
14
|
+
_hover: {
|
|
15
|
+
borderColor: "text.link",
|
|
16
|
+
background: "surface.actionSubtle.hover"
|
|
17
|
+
},
|
|
18
|
+
_active: {
|
|
19
|
+
borderColor: "text.link",
|
|
20
|
+
background: "surface.actionSubtle.active"
|
|
21
|
+
},
|
|
22
|
+
_focusVisible: {
|
|
23
|
+
outline: "none",
|
|
24
|
+
borderRadius: "0",
|
|
25
|
+
_after: {
|
|
26
|
+
content: "\"\"",
|
|
27
|
+
position: "absolute",
|
|
28
|
+
inset: "0",
|
|
29
|
+
outline: "3px",
|
|
30
|
+
borderRadius: "xsmall",
|
|
31
|
+
outlineColor: "stroke.default",
|
|
32
|
+
outlineOffset: "3px",
|
|
33
|
+
outlineStyle: "solid"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
} });
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
export { ConceptInlineTriggerButton };
|
|
40
|
+
//# sourceMappingURL=ConceptInlineTriggerButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConceptInlineTriggerButton.js","names":[],"sources":["../../src/Embed/ConceptInlineTriggerButton.tsx"],"sourcesContent":["/**\n * Copyright (c) 2024-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 { styled } from \"@ndla/styled-system/jsx\";\nimport { InlineTriggerButton } from \"./InlineTriggerButton\";\n\nexport const ConceptInlineTriggerButton = styled(InlineTriggerButton, {\n base: {\n position: \"relative\",\n overflow: \"visible\",\n borderBottom: \"1px solid\",\n borderStyle: \"dashed\",\n borderColor: \"stroke.hover\",\n paddingBlockStart: \"5xsmall\",\n width: \"fit-content\",\n cursor: \"pointer\",\n _hover: {\n borderColor: \"text.link\",\n background: \"surface.actionSubtle.hover\",\n },\n _active: {\n borderColor: \"text.link\",\n background: \"surface.actionSubtle.active\",\n },\n // The global focus ring forces the border-radius to be xsmall, causing the dashed border to be cut off. This is a workaround.\n _focusVisible: {\n outline: \"none\",\n borderRadius: \"0\",\n _after: {\n content: '\"\"',\n position: \"absolute\",\n inset: \"0\",\n outline: \"3px\",\n borderRadius: \"xsmall\",\n outlineColor: \"stroke.default\",\n outlineOffset: \"3px\",\n outlineStyle: \"solid\",\n },\n },\n },\n});\n"],"mappings":";;;;AAWA,MAAa,6BAA6B,OAAO,qBAAqB,EACpE,MAAM;CACJ,UAAU;CACV,UAAU;CACV,cAAc;CACd,aAAa;CACb,aAAa;CACb,mBAAmB;CACnB,OAAO;CACP,QAAQ;CACR,QAAQ;EACN,aAAa;EACb,YAAY;CACb;CACD,SAAS;EACP,aAAa;EACb,YAAY;CACb;CAED,eAAe;EACb,SAAS;EACT,cAAc;EACd,QAAQ;GACN,SAAS;GACT,UAAU;GACV,OAAO;GACP,SAAS;GACT,cAAc;GACd,cAAc;GACd,eAAe;GACf,cAAc;EACf;CACF;AACF,EACF,EAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Text } from "@ndla/primitives";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
|
|
5
|
+
//#region src/Embed/ContentLinkEmbed.tsx
|
|
6
|
+
const ContentLinkEmbed = ({ embed, isOembed, children }) => {
|
|
7
|
+
const { t } = useTranslation();
|
|
8
|
+
if (embed.status === "error") return /* @__PURE__ */ jsx(Text, {
|
|
9
|
+
color: "text.error",
|
|
10
|
+
asChild: true,
|
|
11
|
+
consumeCss: true,
|
|
12
|
+
children: /* @__PURE__ */ jsxs("span", { children: [/* @__PURE__ */ jsx("span", { children: `${t("embed.linkError")}: ` }), children] })
|
|
13
|
+
});
|
|
14
|
+
const { embedData, data } = embed;
|
|
15
|
+
if (embedData.openIn === "new-context" || isOembed) return /* @__PURE__ */ jsx("a", {
|
|
16
|
+
href: data.path,
|
|
17
|
+
"data-embed-type": "content-link",
|
|
18
|
+
target: "_blank",
|
|
19
|
+
rel: "noopener noreferrer",
|
|
20
|
+
children
|
|
21
|
+
});
|
|
22
|
+
return /* @__PURE__ */ jsx("a", {
|
|
23
|
+
href: data.path,
|
|
24
|
+
children
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
var ContentLinkEmbed_default = ContentLinkEmbed;
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
export { ContentLinkEmbed_default };
|
|
31
|
+
//# sourceMappingURL=ContentLinkEmbed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContentLinkEmbed.js","names":[],"sources":["../../src/Embed/ContentLinkEmbed.tsx"],"sourcesContent":["/**\n * Copyright (c) 2023-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 } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Text } from \"@ndla/primitives\";\nimport type { ContentLinkMetaData } from \"@ndla/types-embed\";\n\ninterface Props {\n embed: ContentLinkMetaData;\n isOembed?: boolean;\n children?: ReactNode;\n}\n\nconst ContentLinkEmbed = ({ embed, isOembed, children }: Props) => {\n const { t } = useTranslation();\n if (embed.status === \"error\") {\n return (\n <Text color=\"text.error\" asChild consumeCss>\n <span>\n <span>{`${t(\"embed.linkError\")}: `}</span>\n {children}\n </span>\n </Text>\n );\n }\n\n const { embedData, data } = embed;\n\n if (embedData.openIn === \"new-context\" || isOembed) {\n return (\n <a href={data.path} data-embed-type=\"content-link\" target=\"_blank\" rel=\"noopener noreferrer\">\n {children}\n </a>\n );\n }\n\n return <a href={data.path}>{children}</a>;\n};\n\nexport default ContentLinkEmbed;\n"],"mappings":";;;;;AAmBA,MAAM,mBAAmB,CAAC,EAAE,OAAO,UAAU,UAAiB,KAAK;CACjE,MAAM,EAAE,GAAG,GAAG,gBAAgB;AAC9B,KAAI,MAAM,WAAW,QACnB,wBACE,IAAC;EAAK,OAAM;EAAa;EAAQ;4BAC/B,KAAC,qCACC,IAAC,qBAAO,EAAE,EAAE,kBAAkB,CAAC,MAAW,EACzC,YACI;GACF;CAIX,MAAM,EAAE,WAAW,MAAM,GAAG;AAE5B,KAAI,UAAU,WAAW,iBAAiB,SACxC,wBACE,IAAC;EAAE,MAAM,KAAK;EAAM,mBAAgB;EAAe,QAAO;EAAS,KAAI;EACpE;GACC;AAIR,wBAAO,IAAC;EAAE,MAAM,KAAK;EAAO;GAAa;AAC1C;AAED,+BAAe"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { EmbedByline } from "../LicenseByline/EmbedByline.js";
|
|
2
|
+
import { styled } from "@ndla/styled-system/jsx";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
|
|
5
|
+
//#region src/Embed/CopyrightEmbed.tsx
|
|
6
|
+
const StyledCopyrightContent = styled("div", { base: { marginBlockEnd: "xsmall" } });
|
|
7
|
+
const CopyrightEmbed = ({ embed, children }) => {
|
|
8
|
+
return /* @__PURE__ */ jsxs("figure", {
|
|
9
|
+
"data-embed-type": "copyright",
|
|
10
|
+
children: [/* @__PURE__ */ jsx(StyledCopyrightContent, {
|
|
11
|
+
"data-copyright-content": "",
|
|
12
|
+
children
|
|
13
|
+
}), /* @__PURE__ */ jsx(EmbedByline, {
|
|
14
|
+
type: "copyright",
|
|
15
|
+
copyright: embed.embedData.copyright
|
|
16
|
+
})]
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
var CopyrightEmbed_default = CopyrightEmbed;
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { CopyrightEmbed_default };
|
|
23
|
+
//# sourceMappingURL=CopyrightEmbed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CopyrightEmbed.js","names":[],"sources":["../../src/Embed/CopyrightEmbed.tsx"],"sourcesContent":["/**\n * Copyright (c) 2024-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 } from \"react\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport type { CopyrightMetaData } from \"@ndla/types-embed\";\nimport { EmbedByline } from \"../LicenseByline\";\n\ninterface Props {\n embed: CopyrightMetaData;\n children?: ReactNode;\n}\n\nconst StyledCopyrightContent = styled(\"div\", {\n base: {\n marginBlockEnd: \"xsmall\",\n },\n});\n\nconst CopyrightEmbed = ({ embed, children }: Props) => {\n return (\n <figure data-embed-type=\"copyright\">\n <StyledCopyrightContent data-copyright-content=\"\">{children}</StyledCopyrightContent>\n <EmbedByline type=\"copyright\" copyright={embed.embedData.copyright} />\n </figure>\n );\n};\n\nexport default CopyrightEmbed;\n"],"mappings":";;;;;AAkBA,MAAM,yBAAyB,OAAO,OAAO,EAC3C,MAAM,EACJ,gBAAgB,SACjB,EACF,EAAC;AAEF,MAAM,iBAAiB,CAAC,EAAE,OAAO,UAAiB,KAAK;AACrD,wBACE,KAAC;EAAO,mBAAgB;6BACtB,IAAC;GAAuB,0BAAuB;GAAI;IAAkC,kBACrF,IAAC;GAAY,MAAK;GAAY,WAAW,MAAM,UAAU;IAAa;GAC/D;AAEZ;AAED,6BAAe"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { EmbedByline } from "../LicenseByline/EmbedByline.js";
|
|
2
|
+
import "react";
|
|
3
|
+
import { Figure } from "@ndla/primitives";
|
|
4
|
+
import { styled } from "@ndla/styled-system/jsx";
|
|
5
|
+
import { ErrorWarningLine } from "@ndla/icons";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
|
|
8
|
+
//#region src/Embed/EmbedErrorPlaceholder.tsx
|
|
9
|
+
const ErrorPlaceholder = styled("div", { base: {
|
|
10
|
+
display: "flex",
|
|
11
|
+
alignItems: "center",
|
|
12
|
+
justifyContent: "center",
|
|
13
|
+
background: "background.subtle",
|
|
14
|
+
height: "surface.xsmall",
|
|
15
|
+
border: "1px solid",
|
|
16
|
+
borderColor: "stroke.default",
|
|
17
|
+
borderRadius: "xsmall",
|
|
18
|
+
"& svg": {
|
|
19
|
+
height: "5xlarge",
|
|
20
|
+
width: "5xlarge",
|
|
21
|
+
fill: "stroke.default"
|
|
22
|
+
}
|
|
23
|
+
} });
|
|
24
|
+
const StyledFigure = styled(Figure, { base: { "& > *:not(:first-child)": { marginBlockStart: "3xsmall" } } });
|
|
25
|
+
const EmbedErrorPlaceholder = ({ type, children, figureType, float }) => {
|
|
26
|
+
return /* @__PURE__ */ jsxs(StyledFigure, {
|
|
27
|
+
size: figureType,
|
|
28
|
+
float,
|
|
29
|
+
"data-embed-type": type,
|
|
30
|
+
children: [children ?? /* @__PURE__ */ jsx(ErrorPlaceholder, {
|
|
31
|
+
"data-embed-type": type,
|
|
32
|
+
children: /* @__PURE__ */ jsx(ErrorWarningLine, {})
|
|
33
|
+
}), /* @__PURE__ */ jsx(EmbedByline, {
|
|
34
|
+
error: true,
|
|
35
|
+
type
|
|
36
|
+
})]
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
var EmbedErrorPlaceholder_default = EmbedErrorPlaceholder;
|
|
40
|
+
|
|
41
|
+
//#endregion
|
|
42
|
+
export { EmbedErrorPlaceholder_default };
|
|
43
|
+
//# sourceMappingURL=EmbedErrorPlaceholder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmbedErrorPlaceholder.js","names":[],"sources":["../../src/Embed/EmbedErrorPlaceholder.tsx"],"sourcesContent":["/**\n * Copyright (c) 2023-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 } from \"react\";\nimport { ErrorWarningLine } from \"@ndla/icons\";\nimport { Figure, type FigureFloat, type FigureSize } from \"@ndla/primitives\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport { EmbedByline } from \"../LicenseByline\";\nimport { type EmbedBylineErrorProps } from \"../LicenseByline/EmbedByline\";\n\ninterface Props {\n type: EmbedBylineErrorProps[\"type\"];\n figureType?: FigureSize;\n float?: FigureFloat;\n children?: ReactNode;\n}\n\nconst ErrorPlaceholder = styled(\"div\", {\n base: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: \"background.subtle\",\n height: \"surface.xsmall\",\n border: \"1px solid\",\n borderColor: \"stroke.default\",\n borderRadius: \"xsmall\",\n \"& svg\": {\n height: \"5xlarge\",\n width: \"5xlarge\",\n fill: \"stroke.default\",\n },\n },\n});\n\nconst StyledFigure = styled(Figure, {\n base: {\n \"& > *:not(:first-child)\": {\n marginBlockStart: \"3xsmall\",\n },\n },\n});\n\nconst EmbedErrorPlaceholder = ({ type, children, figureType, float }: Props) => {\n return (\n <StyledFigure size={figureType} float={float} data-embed-type={type}>\n {children ?? (\n <ErrorPlaceholder data-embed-type={type}>\n <ErrorWarningLine />\n </ErrorPlaceholder>\n )}\n <EmbedByline error type={type} />\n </StyledFigure>\n );\n};\n\nexport default EmbedErrorPlaceholder;\n"],"mappings":";;;;;;;;AAsBA,MAAM,mBAAmB,OAAO,OAAO,EACrC,MAAM;CACJ,SAAS;CACT,YAAY;CACZ,gBAAgB;CAChB,YAAY;CACZ,QAAQ;CACR,QAAQ;CACR,aAAa;CACb,cAAc;CACd,SAAS;EACP,QAAQ;EACR,OAAO;EACP,MAAM;CACP;AACF,EACF,EAAC;AAEF,MAAM,eAAe,OAAO,QAAQ,EAClC,MAAM,EACJ,2BAA2B,EACzB,kBAAkB,UACnB,EACF,EACF,EAAC;AAEF,MAAM,wBAAwB,CAAC,EAAE,MAAM,UAAU,YAAY,OAAc,KAAK;AAC9E,wBACE,KAAC;EAAa,MAAM;EAAmB;EAAO,mBAAiB;aAC5D,4BACC,IAAC;GAAiB,mBAAiB;6BACjC,IAAC,qBAAmB;IACH,kBAErB,IAAC;GAAY;GAAY;IAAQ;GACpB;AAElB;AAED,oCAAe"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { forwardRef } from "react";
|
|
2
|
+
import { styled } from "@ndla/styled-system/jsx";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import { ark } from "@ark-ui/react";
|
|
5
|
+
import { css, cva } from "@ndla/styled-system/css";
|
|
6
|
+
|
|
7
|
+
//#region src/Embed/EmbedWrapper.tsx
|
|
8
|
+
const embedWrapperRecipe = cva({
|
|
9
|
+
base: { position: "relative" },
|
|
10
|
+
defaultVariants: { noClear: false },
|
|
11
|
+
variants: { noClear: {
|
|
12
|
+
true: { "& + [data-embed-wrapper]": { clear: "both" } },
|
|
13
|
+
false: { clear: "both" }
|
|
14
|
+
} }
|
|
15
|
+
});
|
|
16
|
+
const StyledEmbedWrapper = styled(ark.div, {}, { baseComponent: true });
|
|
17
|
+
const EmbedWrapper = forwardRef(({ noClear, css: cssProp,...props }, ref) => /* @__PURE__ */ jsx(StyledEmbedWrapper, {
|
|
18
|
+
css: css.raw(embedWrapperRecipe.raw({ noClear }), cssProp),
|
|
19
|
+
"data-embed-wrapper": "",
|
|
20
|
+
...props,
|
|
21
|
+
ref
|
|
22
|
+
}));
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { EmbedWrapper };
|
|
26
|
+
//# sourceMappingURL=EmbedWrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmbedWrapper.js","names":[],"sources":["../../src/Embed/EmbedWrapper.tsx"],"sourcesContent":["/**\n * Copyright (c) 2024-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 { forwardRef } from \"react\";\nimport { ark, type HTMLArkProps } from \"@ark-ui/react\";\nimport { css, cva } from \"@ndla/styled-system/css\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport type { JsxStyleProps, RecipeVariantProps } from \"@ndla/styled-system/types\";\n\nconst embedWrapperRecipe = cva({\n base: {\n position: \"relative\",\n },\n defaultVariants: {\n noClear: false,\n },\n variants: {\n noClear: {\n true: {\n \"& + [data-embed-wrapper]\": {\n clear: \"both\",\n },\n },\n false: {\n clear: \"both\",\n },\n },\n },\n});\n\nexport type EmbedWrapperVariantProps = RecipeVariantProps<typeof embedWrapperRecipe>;\n\nexport type EmbedWrapperProps = HTMLArkProps<\"div\"> & JsxStyleProps & EmbedWrapperVariantProps;\n\nconst StyledEmbedWrapper = styled(ark.div, {}, { baseComponent: true });\n\nexport const EmbedWrapper = forwardRef<HTMLDivElement, EmbedWrapperProps>(\n ({ noClear, css: cssProp, ...props }, ref) => (\n <StyledEmbedWrapper\n css={css.raw(embedWrapperRecipe.raw({ noClear }), cssProp)}\n data-embed-wrapper=\"\"\n {...props}\n ref={ref}\n />\n ),\n);\n"],"mappings":";;;;;;;AAcA,MAAM,qBAAqB,IAAI;CAC7B,MAAM,EACJ,UAAU,WACX;CACD,iBAAiB,EACf,SAAS,MACV;CACD,UAAU,EACR,SAAS;EACP,MAAM,EACJ,4BAA4B,EAC1B,OAAO,OACR,EACF;EACD,OAAO,EACL,OAAO,OACR;CACF,EACF;AACF,EAAC;AAMF,MAAM,qBAAqB,OAAO,IAAI,KAAK,CAAE,GAAE,EAAE,eAAe,KAAM,EAAC;AAEvE,MAAa,eAAe,WAC1B,CAAC,EAAE,SAAS,KAAK,QAAS,GAAG,OAAO,EAAE,wBACpC,IAAC;CACC,KAAK,IAAI,IAAI,mBAAmB,IAAI,EAAE,QAAS,EAAC,EAAE,QAAQ;CAC1D,sBAAmB;CACnB,GAAI;CACC;EACL,CAEL"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { EmbedErrorPlaceholder_default } from "./EmbedErrorPlaceholder.js";
|
|
2
|
+
import { ResourceBox_default } from "../ResourceBox/ResourceBox.js";
|
|
3
|
+
import { useEffect, useRef } from "react";
|
|
4
|
+
import { Figure } from "@ndla/primitives";
|
|
5
|
+
import { styled } from "@ndla/styled-system/jsx";
|
|
6
|
+
import { useTranslation } from "react-i18next";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
|
|
9
|
+
//#region src/Embed/ExternalEmbed.tsx
|
|
10
|
+
const StyledFigure = styled(Figure, { base: { "& iframe": {
|
|
11
|
+
height: "auto",
|
|
12
|
+
width: "100%"
|
|
13
|
+
} } });
|
|
14
|
+
const ExternalEmbed = ({ embed }) => {
|
|
15
|
+
const { t } = useTranslation();
|
|
16
|
+
const figRef = useRef(null);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const iframe = figRef.current?.querySelector("iframe");
|
|
19
|
+
if (iframe) {
|
|
20
|
+
const [width, height] = [Number.parseInt(iframe.width), Number.parseInt(iframe.height)];
|
|
21
|
+
iframe.style.aspectRatio = `${width ? width : 16}/${height ? height : 9}`;
|
|
22
|
+
iframe.width = "";
|
|
23
|
+
iframe.height = "";
|
|
24
|
+
}
|
|
25
|
+
}, []);
|
|
26
|
+
if (embed.status === "error") return /* @__PURE__ */ jsx(EmbedErrorPlaceholder_default, { type: "external" });
|
|
27
|
+
const { embedData, data } = embed;
|
|
28
|
+
if (embedData.type === "fullscreen") {
|
|
29
|
+
const image = {
|
|
30
|
+
src: data.iframeImage?.image.imageUrl,
|
|
31
|
+
alt: embedData.alt !== void 0 ? embedData.alt : data.iframeImage?.alttext?.alttext ?? ""
|
|
32
|
+
};
|
|
33
|
+
return /* @__PURE__ */ jsx(Figure, {
|
|
34
|
+
"data-embed-type": "external",
|
|
35
|
+
children: /* @__PURE__ */ jsx(ResourceBox_default, {
|
|
36
|
+
image,
|
|
37
|
+
title: embedData.title ?? "",
|
|
38
|
+
url: embedData.url,
|
|
39
|
+
caption: embedData.caption ?? "",
|
|
40
|
+
buttonText: t("license.other.itemImage.ariaLabel")
|
|
41
|
+
})
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return /* @__PURE__ */ jsx(StyledFigure, {
|
|
45
|
+
"data-embed-type": "external",
|
|
46
|
+
ref: figRef,
|
|
47
|
+
dangerouslySetInnerHTML: { __html: data?.oembed?.html ?? "" }
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
var ExternalEmbed_default = ExternalEmbed;
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
export { ExternalEmbed_default };
|
|
54
|
+
//# sourceMappingURL=ExternalEmbed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExternalEmbed.js","names":["EmbedErrorPlaceholder","ResourceBox"],"sources":["../../src/Embed/ExternalEmbed.tsx"],"sourcesContent":["/**\n * Copyright (c) 2023-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 { useEffect, useRef } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Figure } from \"@ndla/primitives\";\nimport { styled } from \"@ndla/styled-system/jsx\";\nimport type { OembedMetaData } from \"@ndla/types-embed\";\nimport EmbedErrorPlaceholder from \"./EmbedErrorPlaceholder\";\nimport { ResourceBox } from \"../ResourceBox\";\n\ninterface Props {\n embed: OembedMetaData;\n}\n\nconst StyledFigure = styled(Figure, {\n base: {\n \"& iframe\": {\n height: \"auto\",\n width: \"100%\",\n },\n },\n});\n\nconst ExternalEmbed = ({ embed }: Props) => {\n const { t } = useTranslation();\n const figRef = useRef<HTMLElement>(null);\n\n useEffect(() => {\n const iframe = figRef.current?.querySelector(\"iframe\");\n if (iframe) {\n const [width, height] = [Number.parseInt(iframe.width), Number.parseInt(iframe.height)];\n iframe.style.aspectRatio = `${width ? width : 16}/${height ? height : 9}`;\n iframe.width = \"\";\n iframe.height = \"\";\n }\n }, []);\n\n if (embed.status === \"error\") {\n return <EmbedErrorPlaceholder type=\"external\" />;\n }\n\n const { embedData, data } = embed;\n\n if (embedData.type === \"fullscreen\") {\n const image = {\n src: data.iframeImage?.image.imageUrl,\n alt: embedData.alt !== undefined ? embedData.alt : (data.iframeImage?.alttext?.alttext ?? \"\"),\n };\n return (\n <Figure data-embed-type=\"external\">\n <ResourceBox\n image={image}\n title={embedData.title ?? \"\"}\n url={embedData.url}\n caption={embedData.caption ?? \"\"}\n buttonText={t(\"license.other.itemImage.ariaLabel\")}\n />\n </Figure>\n );\n }\n\n return (\n <StyledFigure\n data-embed-type=\"external\"\n ref={figRef}\n dangerouslySetInnerHTML={{ __html: data?.oembed?.html ?? \"\" }}\n />\n );\n};\nexport default ExternalEmbed;\n"],"mappings":";;;;;;;;;AAoBA,MAAM,eAAe,OAAO,QAAQ,EAClC,MAAM,EACJ,YAAY;CACV,QAAQ;CACR,OAAO;AACR,EACF,EACF,EAAC;AAEF,MAAM,gBAAgB,CAAC,EAAE,OAAc,KAAK;CAC1C,MAAM,EAAE,GAAG,GAAG,gBAAgB;CAC9B,MAAM,SAAS,OAAoB,KAAK;AAExC,WAAU,MAAM;EACd,MAAM,SAAS,OAAO,SAAS,cAAc,SAAS;AACtD,MAAI,QAAQ;GACV,MAAM,CAAC,OAAO,OAAO,GAAG,CAAC,OAAO,SAAS,OAAO,MAAM,EAAE,OAAO,SAAS,OAAO,OAAO,AAAC;AACvF,UAAO,MAAM,eAAe,EAAE,QAAQ,QAAQ,GAAG,GAAG,SAAS,SAAS,EAAE;AACxE,UAAO,QAAQ;AACf,UAAO,SAAS;EACjB;CACF,GAAE,CAAE,EAAC;AAEN,KAAI,MAAM,WAAW,QACnB,wBAAO,IAACA,iCAAsB,MAAK,aAAa;CAGlD,MAAM,EAAE,WAAW,MAAM,GAAG;AAE5B,KAAI,UAAU,SAAS,cAAc;EACnC,MAAM,QAAQ;GACZ,KAAK,KAAK,aAAa,MAAM;GAC7B,KAAK,UAAU,iBAAoB,UAAU,MAAO,KAAK,aAAa,SAAS,WAAW;EAC3F;AACD,yBACE,IAAC;GAAO,mBAAgB;6BACtB,IAACC;IACQ;IACP,OAAO,UAAU,SAAS;IAC1B,KAAK,UAAU;IACf,SAAS,UAAU,WAAW;IAC9B,YAAY,EAAE,oCAAoC;KAClD;IACK;CAEZ;AAED,wBACE,IAAC;EACC,mBAAgB;EAChB,KAAK;EACL,yBAAyB,EAAE,QAAQ,MAAM,QAAQ,QAAQ,GAAI;GAC7D;AAEL;AACD,4BAAe"}
|