@ndla/ui 55.0.10-alpha.0 → 55.0.11-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/es/index.js +0 -2
- package/lib/index.d.ts +0 -3
- package/lib/index.js +0 -20
- package/package.json +8 -8
- package/src/index.ts +0 -3
- package/es/MyNdla/Resource/Folder.js +0 -135
- package/es/MyNdla/Resource/index.js +0 -10
- package/es/MyNdla/index.js +0 -10
- package/es/Resource/BlockResource.js +0 -204
- package/es/Resource/ListResource.js +0 -235
- package/es/Resource/index.js +0 -10
- package/es/Resource/resourceComponents.js +0 -179
- package/es/Resource/storyComponents.js +0 -64
- package/lib/MyNdla/Resource/Folder.d.ts +0 -24
- package/lib/MyNdla/Resource/Folder.js +0 -142
- package/lib/MyNdla/Resource/index.d.ts +0 -9
- package/lib/MyNdla/Resource/index.js +0 -13
- package/lib/MyNdla/index.d.ts +0 -9
- package/lib/MyNdla/index.js +0 -13
- package/lib/Resource/BlockResource.d.ts +0 -28
- package/lib/Resource/BlockResource.js +0 -208
- package/lib/Resource/ListResource.d.ts +0 -28
- package/lib/Resource/ListResource.js +0 -239
- package/lib/Resource/index.d.ts +0 -11
- package/lib/Resource/index.js +0 -20
- package/lib/Resource/resourceComponents.d.ts +0 -43
- package/lib/Resource/resourceComponents.js +0 -188
- package/lib/Resource/storyComponents.d.ts +0 -12
- package/lib/Resource/storyComponents.js +0 -71
- package/src/MyNdla/Resource/Folder.stories.tsx +0 -87
- package/src/MyNdla/Resource/Folder.tsx +0 -228
- package/src/MyNdla/Resource/index.ts +0 -10
- package/src/MyNdla/index.ts +0 -10
- package/src/Resource/BlockResource.stories.tsx +0 -98
- package/src/Resource/BlockResource.tsx +0 -212
- package/src/Resource/ListResource.stories.tsx +0 -99
- package/src/Resource/ListResource.tsx +0 -273
- package/src/Resource/index.ts +0 -12
- package/src/Resource/resourceComponents.tsx +0 -242
- package/src/Resource/storyComponents.tsx +0 -49
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2022-present, NDLA.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the GPLv3 license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { ReactNode } from "react";
|
|
10
|
-
import { useTranslation } from "react-i18next";
|
|
11
|
-
import styled from "@emotion/styled";
|
|
12
|
-
import { fonts, spacing, colors, mq, breakpoints, stackOrder } from "@ndla/core";
|
|
13
|
-
import { FileDocumentOutline, Share, Link } from "@ndla/icons/common";
|
|
14
|
-
import { FolderOutlined, FolderSharedOutlined } from "@ndla/icons/contentType";
|
|
15
|
-
import { ResourceTitleLink } from "../../Resource/resourceComponents";
|
|
16
|
-
|
|
17
|
-
export type LayoutType = "list" | "listLarger" | "block";
|
|
18
|
-
|
|
19
|
-
const FolderWrapper = styled.div`
|
|
20
|
-
display: flex;
|
|
21
|
-
position: relative;
|
|
22
|
-
align-items: center;
|
|
23
|
-
justify-content: space-between;
|
|
24
|
-
text-overflow: ellipsis;
|
|
25
|
-
overflow: hidden;
|
|
26
|
-
word-break: break-word;
|
|
27
|
-
|
|
28
|
-
${mq.range({ until: breakpoints.mobileWide })} {
|
|
29
|
-
&:not([data-type="list"]) {
|
|
30
|
-
flex-direction: column;
|
|
31
|
-
align-items: unset;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
&[data-type="block"] {
|
|
36
|
-
flex-direction: column;
|
|
37
|
-
align-items: unset;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
border: 1px solid ${colors.brand.neutral7};
|
|
41
|
-
cursor: pointer;
|
|
42
|
-
border-radius: 2px;
|
|
43
|
-
box-shadow: none;
|
|
44
|
-
text-decoration: none;
|
|
45
|
-
&:hover {
|
|
46
|
-
box-shadow: 1px 1px 6px 2px rgba(9, 55, 101, 0.08);
|
|
47
|
-
transition-duration: 0.2s;
|
|
48
|
-
[data-title] {
|
|
49
|
-
color: ${colors.brand.primary};
|
|
50
|
-
text-decoration: underline;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
`;
|
|
54
|
-
|
|
55
|
-
const TitleWrapper = styled.div`
|
|
56
|
-
display: flex;
|
|
57
|
-
margin: ${spacing.nsmall};
|
|
58
|
-
flex-direction: row;
|
|
59
|
-
align-items: center;
|
|
60
|
-
gap: ${spacing.xsmall};
|
|
61
|
-
justify-content: space-between;
|
|
62
|
-
&[data-type="block"] {
|
|
63
|
-
margin-bottom: 0;
|
|
64
|
-
}
|
|
65
|
-
`;
|
|
66
|
-
|
|
67
|
-
const IconWrapper = styled.div`
|
|
68
|
-
display: flex;
|
|
69
|
-
border-radius: 100%;
|
|
70
|
-
color: ${colors.brand.primary};
|
|
71
|
-
svg {
|
|
72
|
-
width: 20px;
|
|
73
|
-
height: 20px;
|
|
74
|
-
}
|
|
75
|
-
`;
|
|
76
|
-
|
|
77
|
-
const FolderTitle = styled.h2`
|
|
78
|
-
${fonts.sizes("16px", "20px")};
|
|
79
|
-
font-weight: ${fonts.weight.semibold};
|
|
80
|
-
margin: 0px !important;
|
|
81
|
-
flex: 1;
|
|
82
|
-
|
|
83
|
-
overflow: hidden;
|
|
84
|
-
text-overflow: ellipsis;
|
|
85
|
-
/* Unfortunate css needed for multi-line text overflow ellipsis. */
|
|
86
|
-
display: -webkit-box;
|
|
87
|
-
-webkit-line-clamp: 1;
|
|
88
|
-
line-clamp: 1;
|
|
89
|
-
-webkit-box-orient: vertical;
|
|
90
|
-
`;
|
|
91
|
-
|
|
92
|
-
const MenuWrapper = styled.div`
|
|
93
|
-
display: flex;
|
|
94
|
-
z-index: ${stackOrder.offsetSingle};
|
|
95
|
-
flex-direction: row;
|
|
96
|
-
align-items: center;
|
|
97
|
-
justify-content: space-between;
|
|
98
|
-
`;
|
|
99
|
-
|
|
100
|
-
const CountContainer = styled.div`
|
|
101
|
-
overflow: hidden;
|
|
102
|
-
display: flex;
|
|
103
|
-
flex-direction: row;
|
|
104
|
-
min-height: 44px;
|
|
105
|
-
gap: ${spacing.small};
|
|
106
|
-
margin: 0 ${spacing.small} 0 ${spacing.nsmall};
|
|
107
|
-
|
|
108
|
-
${mq.range({ until: breakpoints.tablet })} {
|
|
109
|
-
&[data-type="list"] {
|
|
110
|
-
display: none;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
`;
|
|
114
|
-
|
|
115
|
-
const IconTextWrapper = styled.div`
|
|
116
|
-
display: flex;
|
|
117
|
-
align-items: center;
|
|
118
|
-
gap: ${spacing.xxsmall};
|
|
119
|
-
color: ${colors.brand.grey};
|
|
120
|
-
white-space: nowrap;
|
|
121
|
-
svg {
|
|
122
|
-
width: 13px;
|
|
123
|
-
height: 13px;
|
|
124
|
-
}
|
|
125
|
-
${fonts.sizes(16)};
|
|
126
|
-
`;
|
|
127
|
-
|
|
128
|
-
interface IconCountProps {
|
|
129
|
-
type: "resource" | "folder";
|
|
130
|
-
count?: number;
|
|
131
|
-
layoutType: LayoutType;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const Count = ({ type, count, layoutType }: IconCountProps) => {
|
|
135
|
-
const Icon = type === "resource" ? FileDocumentOutline : FolderOutlined;
|
|
136
|
-
const { t } = useTranslation();
|
|
137
|
-
if (!count) return null;
|
|
138
|
-
|
|
139
|
-
return (
|
|
140
|
-
<IconTextWrapper data-type={layoutType}>
|
|
141
|
-
<Icon />
|
|
142
|
-
<span>{t(`myNdla.${type}s`, { count })}</span>
|
|
143
|
-
</IconTextWrapper>
|
|
144
|
-
);
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
interface Props {
|
|
148
|
-
id: string;
|
|
149
|
-
title: string;
|
|
150
|
-
author?: string;
|
|
151
|
-
subFolders?: number;
|
|
152
|
-
subResources?: number;
|
|
153
|
-
description?: string;
|
|
154
|
-
link: string;
|
|
155
|
-
type?: LayoutType;
|
|
156
|
-
menu?: ReactNode;
|
|
157
|
-
isShared?: boolean;
|
|
158
|
-
isOwner?: boolean;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const getIcon = (isOwner: boolean, isShared?: boolean) => {
|
|
162
|
-
if (!isOwner) {
|
|
163
|
-
return Link;
|
|
164
|
-
} else if (isShared) {
|
|
165
|
-
return FolderSharedOutlined;
|
|
166
|
-
} else {
|
|
167
|
-
return FolderOutlined;
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
const Folder = ({
|
|
172
|
-
id,
|
|
173
|
-
link,
|
|
174
|
-
title,
|
|
175
|
-
author,
|
|
176
|
-
subFolders,
|
|
177
|
-
subResources,
|
|
178
|
-
type = "list",
|
|
179
|
-
menu,
|
|
180
|
-
isShared,
|
|
181
|
-
isOwner = true,
|
|
182
|
-
}: Props) => {
|
|
183
|
-
const { t } = useTranslation();
|
|
184
|
-
const Icon = getIcon(isOwner, isShared);
|
|
185
|
-
|
|
186
|
-
return (
|
|
187
|
-
<FolderWrapper data-type={type} id={id}>
|
|
188
|
-
<TitleWrapper data-type={type}>
|
|
189
|
-
<IconWrapper
|
|
190
|
-
aria-label={`${isShared ? `${t("myNdla.folder.sharing.shared")} ` : ""}${t("myNdla.folder.folder")}`}
|
|
191
|
-
>
|
|
192
|
-
<Icon />
|
|
193
|
-
</IconWrapper>
|
|
194
|
-
<ResourceTitleLink to={link}>
|
|
195
|
-
<FolderTitle data-title="" title={title}>
|
|
196
|
-
{title}
|
|
197
|
-
</FolderTitle>
|
|
198
|
-
</ResourceTitleLink>
|
|
199
|
-
</TitleWrapper>
|
|
200
|
-
<MenuWrapper>
|
|
201
|
-
<CountContainer data-type={type}>
|
|
202
|
-
{isShared && (
|
|
203
|
-
<IconTextWrapper>
|
|
204
|
-
<Share />
|
|
205
|
-
{!isOwner ? (
|
|
206
|
-
<span>
|
|
207
|
-
{t("myNdla.folder.sharing.sharedBy")}
|
|
208
|
-
{author ? `${author}` : t("myNdla.folder.sharing.sharedByAnonymous")}
|
|
209
|
-
</span>
|
|
210
|
-
) : (
|
|
211
|
-
<span aria-hidden>{t("myNdla.folder.sharing.shared")}</span>
|
|
212
|
-
)}
|
|
213
|
-
</IconTextWrapper>
|
|
214
|
-
)}
|
|
215
|
-
{isOwner && (
|
|
216
|
-
<>
|
|
217
|
-
<Count layoutType={type} type={"folder"} count={subFolders} />
|
|
218
|
-
<Count layoutType={type} type={"resource"} count={subResources} />
|
|
219
|
-
</>
|
|
220
|
-
)}
|
|
221
|
-
</CountContainer>
|
|
222
|
-
{menu}
|
|
223
|
-
</MenuWrapper>
|
|
224
|
-
</FolderWrapper>
|
|
225
|
-
);
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
export default Folder;
|
package/src/MyNdla/index.ts
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2022-present, NDLA.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the GPLv3 license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import styled from "@emotion/styled";
|
|
10
|
-
import { Meta, StoryFn, StoryObj } from "@storybook/react";
|
|
11
|
-
import { spacing } from "@ndla/core";
|
|
12
|
-
import BlockResource from "./BlockResource";
|
|
13
|
-
import { StoryResourceMenu, resourceTypesArr } from "./storyComponents";
|
|
14
|
-
|
|
15
|
-
export default {
|
|
16
|
-
title: "My NDLA/BlockResource",
|
|
17
|
-
component: BlockResource,
|
|
18
|
-
tags: ["autodocs"],
|
|
19
|
-
argTypes: {
|
|
20
|
-
resourceImage: {
|
|
21
|
-
control: false,
|
|
22
|
-
},
|
|
23
|
-
resourceTypes: {
|
|
24
|
-
control: false,
|
|
25
|
-
},
|
|
26
|
-
menu: {
|
|
27
|
-
control: false,
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
args: {
|
|
31
|
-
id: "1234",
|
|
32
|
-
link: "",
|
|
33
|
-
title: "Tittel til ressurs",
|
|
34
|
-
description: "Dette er for eksempel en fagbeskrivelse! Dersom den er for lang vil den bli forkortet",
|
|
35
|
-
resourceImage: {
|
|
36
|
-
src: "https://cdn.pixabay.com/photo/2022/06/12/22/35/village-7258991_1280.jpg",
|
|
37
|
-
alt: "",
|
|
38
|
-
},
|
|
39
|
-
resourceTypes: [{ id: "urn:resourcetype:learningPath", name: "Læringssti" }],
|
|
40
|
-
tags: ["tag", "tag", "tag", "tag"],
|
|
41
|
-
},
|
|
42
|
-
} as Meta<typeof BlockResource>;
|
|
43
|
-
|
|
44
|
-
export const WithImage: StoryFn<typeof BlockResource> = (args) => {
|
|
45
|
-
return <BlockResource {...args} />;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
export const WithoutImage: StoryObj<typeof BlockResource> = {
|
|
49
|
-
args: { resourceImage: { src: "", alt: "" } },
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
export const WithoutTags: StoryObj<typeof BlockResource> = {
|
|
53
|
-
args: { tags: [] },
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
export const WithOverflowingDescription: StoryObj<typeof BlockResource> = {
|
|
57
|
-
args: {
|
|
58
|
-
description:
|
|
59
|
-
"Beskrivelser trenger ikke å være så veldig lange. Det er ganske vanskelig å få plass til en livshistorie. Det lærte jeg da jeg var ung",
|
|
60
|
-
},
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export const WithMenu: StoryObj<typeof BlockResource> = {
|
|
64
|
-
args: {
|
|
65
|
-
menu: <StoryResourceMenu />,
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
export const WithUnavailableResource: StoryObj<typeof BlockResource> = {
|
|
70
|
-
args: {
|
|
71
|
-
title: "Ressurs ikke tilgjengelig",
|
|
72
|
-
resourceTypes: [],
|
|
73
|
-
resourceImage: { src: "", alt: "" },
|
|
74
|
-
},
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
export const Loading: StoryObj<typeof BlockResource> = {
|
|
78
|
-
args: {
|
|
79
|
-
isLoading: true,
|
|
80
|
-
},
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
const BlockWrapper = styled.div`
|
|
84
|
-
display: flex;
|
|
85
|
-
gap: ${spacing.small};
|
|
86
|
-
flex-wrap: wrap;
|
|
87
|
-
`;
|
|
88
|
-
|
|
89
|
-
export const BlockView: StoryObj<typeof BlockResource> = {
|
|
90
|
-
args: { resourceImage: { src: "", alt: "" } },
|
|
91
|
-
render: ({ ...args }) => (
|
|
92
|
-
<BlockWrapper>
|
|
93
|
-
{resourceTypesArr.map((rt) => (
|
|
94
|
-
<BlockResource {...args} key={rt.id} resourceTypes={[rt]} />
|
|
95
|
-
))}
|
|
96
|
-
</BlockWrapper>
|
|
97
|
-
),
|
|
98
|
-
};
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2022-present, NDLA.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the GPLv3 license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/** @jsxImportSource @emotion/react */
|
|
10
|
-
import { ReactNode, useMemo } from "react";
|
|
11
|
-
import styled from "@emotion/styled";
|
|
12
|
-
import { colors, spacing, stackOrder } from "@ndla/core";
|
|
13
|
-
import { Text } from "@ndla/typography";
|
|
14
|
-
import {
|
|
15
|
-
CompressedTagList,
|
|
16
|
-
ResourceImageProps,
|
|
17
|
-
ResourceTypeList,
|
|
18
|
-
ResourceTitleLink,
|
|
19
|
-
LoaderProps,
|
|
20
|
-
ContentIconWrapper,
|
|
21
|
-
resourceHeadingStyle,
|
|
22
|
-
} from "./resourceComponents";
|
|
23
|
-
import ContentLoader from "../ContentLoader";
|
|
24
|
-
import ContentTypeBadge from "../ContentTypeBadge";
|
|
25
|
-
import Image from "../Image";
|
|
26
|
-
import { contentTypeMapping, MISSING, resourceEmbedTypeMapping } from "../model/ContentType";
|
|
27
|
-
|
|
28
|
-
const BlockElementWrapper = styled.div`
|
|
29
|
-
display: flex;
|
|
30
|
-
position: relative;
|
|
31
|
-
text-decoration: none;
|
|
32
|
-
box-shadow: none;
|
|
33
|
-
flex-direction: column;
|
|
34
|
-
max-width: 450px;
|
|
35
|
-
max-height: 240px;
|
|
36
|
-
border: 1px solid ${colors.brand.light};
|
|
37
|
-
border-radius: 2px;
|
|
38
|
-
color: ${colors.brand.greyDark};
|
|
39
|
-
cursor: pointer;
|
|
40
|
-
|
|
41
|
-
&:hover {
|
|
42
|
-
box-shadow: 1px 1px 6px 2px rgba(9, 55, 101, 0.08);
|
|
43
|
-
transition-duration: 0.2s;
|
|
44
|
-
[data-link] {
|
|
45
|
-
color: ${colors.brand.primary};
|
|
46
|
-
text-decoration: underline;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
&:hover,
|
|
51
|
-
&:focus,
|
|
52
|
-
&:focus-within {
|
|
53
|
-
[data-description] {
|
|
54
|
-
/* Unfortunate css needed for multi-line text overflow ellipsis. */
|
|
55
|
-
height: 3.1em;
|
|
56
|
-
-webkit-line-clamp: 2;
|
|
57
|
-
line-clamp: 2;
|
|
58
|
-
-webkit-box-orient: vertical;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
`;
|
|
62
|
-
|
|
63
|
-
const BlockDescription = styled(Text)`
|
|
64
|
-
display: -webkit-box;
|
|
65
|
-
line-clamp: 2;
|
|
66
|
-
height: 0em;
|
|
67
|
-
overflow: hidden;
|
|
68
|
-
text-overflow: ellipsis;
|
|
69
|
-
transition: height 0.2s ease-out;
|
|
70
|
-
`;
|
|
71
|
-
|
|
72
|
-
const TagsAndActionMenu = styled.div`
|
|
73
|
-
display: flex;
|
|
74
|
-
align-items: center;
|
|
75
|
-
justify-content: flex-end;
|
|
76
|
-
z-index: ${stackOrder.offsetSingle};
|
|
77
|
-
`;
|
|
78
|
-
|
|
79
|
-
const BlockInfoWrapper = styled.div`
|
|
80
|
-
display: flex;
|
|
81
|
-
flex-direction: column;
|
|
82
|
-
`;
|
|
83
|
-
|
|
84
|
-
const ContentWrapper = styled.div`
|
|
85
|
-
display: flex;
|
|
86
|
-
margin: ${spacing.small} ${spacing.small} 0 ${spacing.small};
|
|
87
|
-
flex-direction: column;
|
|
88
|
-
`;
|
|
89
|
-
|
|
90
|
-
const ImageWrapper = styled.div`
|
|
91
|
-
display: flex;
|
|
92
|
-
width: 100%;
|
|
93
|
-
justify-content: center;
|
|
94
|
-
overflow: hidden;
|
|
95
|
-
align-items: center;
|
|
96
|
-
img {
|
|
97
|
-
object-fit: cover;
|
|
98
|
-
aspect-ratio: 4/3;
|
|
99
|
-
min-width: 100%;
|
|
100
|
-
}
|
|
101
|
-
`;
|
|
102
|
-
|
|
103
|
-
interface BlockImageProps {
|
|
104
|
-
image: ResourceImageProps;
|
|
105
|
-
loading?: boolean;
|
|
106
|
-
contentType: string;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const BlockImage = ({ image, loading, contentType }: BlockImageProps) => {
|
|
110
|
-
if (loading) {
|
|
111
|
-
return (
|
|
112
|
-
<ContentLoader height={"100%"} width={"100%"} viewBox={null} preserveAspectRatio="none">
|
|
113
|
-
<rect x="0" y="0" rx="3" ry="3" width="100%" height="100%" />
|
|
114
|
-
</ContentLoader>
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
if (image.src === "") {
|
|
118
|
-
return (
|
|
119
|
-
<ContentIconWrapper contentType={contentType}>
|
|
120
|
-
<ContentTypeBadge type={contentType} size="large" />
|
|
121
|
-
</ContentIconWrapper>
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
return <Image alt={image.alt} src={image.src} fallbackWidth={300} />;
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
const ResourceTypeAndTitleLoader = ({ children, loading }: LoaderProps) => {
|
|
128
|
-
if (loading) {
|
|
129
|
-
return (
|
|
130
|
-
<ContentLoader height={"18px"} width={"100%"} viewBox={null} preserveAspectRatio="none">
|
|
131
|
-
<rect x="0" y="0" rx="3" ry="3" width="20%" height="18px" />
|
|
132
|
-
<rect x="25%" y="0" rx="3" ry="3" width="20%" height="18px" />
|
|
133
|
-
</ContentLoader>
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return <>{children}</>;
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
interface Props {
|
|
141
|
-
id: string;
|
|
142
|
-
link: string;
|
|
143
|
-
tagLinkPrefix?: string;
|
|
144
|
-
title: string;
|
|
145
|
-
resourceImage: ResourceImageProps;
|
|
146
|
-
tags?: string[];
|
|
147
|
-
description?: string;
|
|
148
|
-
menu?: ReactNode;
|
|
149
|
-
isLoading?: boolean;
|
|
150
|
-
targetBlank?: boolean;
|
|
151
|
-
resourceTypes?: { id: string; name: string }[];
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const BlockResource = ({
|
|
155
|
-
id,
|
|
156
|
-
link,
|
|
157
|
-
tagLinkPrefix,
|
|
158
|
-
title,
|
|
159
|
-
tags,
|
|
160
|
-
resourceImage,
|
|
161
|
-
description,
|
|
162
|
-
menu,
|
|
163
|
-
isLoading,
|
|
164
|
-
targetBlank,
|
|
165
|
-
resourceTypes,
|
|
166
|
-
}: Props) => {
|
|
167
|
-
const firstResourceType = resourceTypes?.[0]?.id ?? "";
|
|
168
|
-
|
|
169
|
-
const contentType = useMemo(() => {
|
|
170
|
-
if (!firstResourceType) {
|
|
171
|
-
return MISSING;
|
|
172
|
-
}
|
|
173
|
-
return (
|
|
174
|
-
contentTypeMapping[firstResourceType] ?? resourceEmbedTypeMapping[firstResourceType] ?? contentTypeMapping.default
|
|
175
|
-
);
|
|
176
|
-
}, [firstResourceType]);
|
|
177
|
-
|
|
178
|
-
return (
|
|
179
|
-
<BlockElementWrapper id={id}>
|
|
180
|
-
<ImageWrapper>
|
|
181
|
-
<BlockImage image={resourceImage} loading={isLoading} contentType={contentType} />
|
|
182
|
-
</ImageWrapper>
|
|
183
|
-
<BlockInfoWrapper>
|
|
184
|
-
<ContentWrapper>
|
|
185
|
-
<ResourceTypeAndTitleLoader loading={isLoading}>
|
|
186
|
-
<ResourceTitleLink
|
|
187
|
-
data-link=""
|
|
188
|
-
title={title}
|
|
189
|
-
target={targetBlank ? "_blank" : undefined}
|
|
190
|
-
to={link}
|
|
191
|
-
data-resource-available={contentType !== MISSING}
|
|
192
|
-
>
|
|
193
|
-
<Text element="span" textStyle="label-small" css={resourceHeadingStyle}>
|
|
194
|
-
{title}
|
|
195
|
-
</Text>
|
|
196
|
-
</ResourceTitleLink>
|
|
197
|
-
</ResourceTypeAndTitleLoader>
|
|
198
|
-
<ResourceTypeList resourceTypes={resourceTypes} />
|
|
199
|
-
<BlockDescription element="p" textStyle="meta-text-small" margin="none" data-description="">
|
|
200
|
-
{description}
|
|
201
|
-
</BlockDescription>
|
|
202
|
-
</ContentWrapper>
|
|
203
|
-
<TagsAndActionMenu>
|
|
204
|
-
{tags && tags.length > 0 && <CompressedTagList tagLinkPrefix={tagLinkPrefix} tags={tags} />}
|
|
205
|
-
{menu}
|
|
206
|
-
</TagsAndActionMenu>
|
|
207
|
-
</BlockInfoWrapper>
|
|
208
|
-
</BlockElementWrapper>
|
|
209
|
-
);
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
export default BlockResource;
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2022-present, NDLA.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the GPLv3 license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import styled from "@emotion/styled";
|
|
10
|
-
import { Meta, StoryFn, StoryObj } from "@storybook/react";
|
|
11
|
-
import ListResource from "./ListResource";
|
|
12
|
-
import { StoryResourceMenu, resourceTypesArr } from "./storyComponents";
|
|
13
|
-
import { spacing } from "../../../core/src";
|
|
14
|
-
|
|
15
|
-
export default {
|
|
16
|
-
title: "My NDLA/ListResource",
|
|
17
|
-
component: ListResource,
|
|
18
|
-
tags: ["autodocs"],
|
|
19
|
-
argTypes: {
|
|
20
|
-
resourceImage: {
|
|
21
|
-
control: false,
|
|
22
|
-
},
|
|
23
|
-
resourceTypes: {
|
|
24
|
-
control: false,
|
|
25
|
-
},
|
|
26
|
-
menu: {
|
|
27
|
-
control: false,
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
args: {
|
|
31
|
-
id: "1234",
|
|
32
|
-
link: "",
|
|
33
|
-
title: "Tittel til ressurs",
|
|
34
|
-
resourceImage: {
|
|
35
|
-
src: "https://cdn.pixabay.com/photo/2022/06/12/22/35/village-7258991_1280.jpg",
|
|
36
|
-
alt: "",
|
|
37
|
-
},
|
|
38
|
-
resourceTypes: [{ id: "urn:resourcetype:learningPath", name: "Læringssti" }],
|
|
39
|
-
tags: ["tag", "tag", "tag", "tag"],
|
|
40
|
-
},
|
|
41
|
-
} as Meta<typeof ListResource>;
|
|
42
|
-
|
|
43
|
-
export const WithImage: StoryFn<typeof ListResource> = (args) => {
|
|
44
|
-
return <ListResource {...args} />;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export const WithoutImage: StoryObj<typeof ListResource> = {
|
|
48
|
-
args: {
|
|
49
|
-
resourceImage: { src: "", alt: "" },
|
|
50
|
-
},
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export const WithoutTags: StoryObj<typeof ListResource> = {
|
|
54
|
-
args: { tags: [] },
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export const WithOverflowingDescription: StoryObj<typeof ListResource> = {
|
|
58
|
-
args: {
|
|
59
|
-
description:
|
|
60
|
-
"Beskrivelser trenger ikke å være så veldig lange. Det er ganske vanskelig å få plass til en livshistorie. Det lærte jeg da jeg var en ung utvikler og utviklet denne komponenten. Jeg husker det nærmest som om det var i går, men det var det egentlig ikke. Det var i det gode år 2022",
|
|
61
|
-
},
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
export const WithMenu: StoryObj<typeof ListResource> = {
|
|
65
|
-
args: {
|
|
66
|
-
menu: <StoryResourceMenu />,
|
|
67
|
-
},
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
export const WithUnavailableResource: StoryObj<typeof ListResource> = {
|
|
71
|
-
args: {
|
|
72
|
-
title: "Ressurs ikke tilgjengelig",
|
|
73
|
-
resourceTypes: [],
|
|
74
|
-
resourceImage: { src: "", alt: "" },
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
export const Loading: StoryObj<typeof ListResource> = {
|
|
79
|
-
args: {
|
|
80
|
-
isLoading: true,
|
|
81
|
-
},
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const Wrapper = styled.div`
|
|
85
|
-
display: flex;
|
|
86
|
-
flex-direction: column;
|
|
87
|
-
gap: ${spacing.small};
|
|
88
|
-
`;
|
|
89
|
-
|
|
90
|
-
export const BlockView: StoryObj<typeof ListResource> = {
|
|
91
|
-
args: { resourceImage: { src: "", alt: "" } },
|
|
92
|
-
render: ({ ...args }) => (
|
|
93
|
-
<Wrapper>
|
|
94
|
-
{resourceTypesArr.map((rt) => (
|
|
95
|
-
<ListResource {...args} key={rt.id} resourceTypes={[rt]} />
|
|
96
|
-
))}
|
|
97
|
-
</Wrapper>
|
|
98
|
-
),
|
|
99
|
-
};
|