@ndla/ui 37.1.4 → 39.0.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/Article/Article.js +2 -2
- package/es/Article/ArticleHeaderWrapper.js +4 -7
- package/es/Article/ArticleNotions.js +16 -17
- package/es/Article/ArticleSideBar.js +4 -5
- package/es/AudioPlayer/Controls.js +187 -237
- package/es/BlogPost/BlogPost.js +4 -4
- package/es/CompetenceGoals/CompetenceGoalsDialog.js +12 -25
- package/es/Filter/FilterButtons.js +12 -14
- package/es/Filter/FilterListPhone.js +2 -4
- package/es/Footer/index.js +1 -2
- package/es/Grid/Grid.js +41 -0
- package/es/Grid/index.js +9 -0
- package/es/LearningPaths/LearningPathMenuModalWrapper.js +10 -6
- package/es/Masthead/MastheadSearchModal.js +56 -47
- package/es/MyNdla/SettingsMenu.js +6 -6
- package/es/NDLAFilm/AboutNdlaFilm.js +3 -3
- package/es/ResourcesWrapper/ResourcesTopicTitle.js +19 -23
- package/es/SearchTypeResult/PopupFilter.js +14 -20
- package/es/SearchTypeResult/components/ItemContexts.js +10 -21
- package/es/Topic/Topic.js +23 -23
- package/es/User/index.js +1 -3
- package/es/index.js +2 -3
- package/es/locale/messages-en.js +1 -0
- package/es/locale/messages-nb.js +1 -0
- package/es/locale/messages-nn.js +1 -0
- package/es/locale/messages-se.js +1 -0
- package/es/locale/messages-sma.js +1 -0
- package/lib/Article/Article.d.ts +2 -2
- package/lib/Article/Article.js +2 -2
- package/lib/Article/ArticleHeaderWrapper.d.ts +3 -2
- package/lib/Article/ArticleHeaderWrapper.js +4 -7
- package/lib/Article/ArticleNotions.js +17 -21
- package/lib/Article/ArticleSideBar.js +5 -9
- package/lib/AudioPlayer/Controls.d.ts +2 -2
- package/lib/AudioPlayer/Controls.js +187 -237
- package/lib/BlogPost/BlogPost.d.ts +1 -1
- package/lib/BlogPost/BlogPost.js +4 -4
- package/lib/CompetenceGoals/CompetenceGoalsDialog.d.ts +3 -14
- package/lib/CompetenceGoals/CompetenceGoalsDialog.js +11 -26
- package/lib/Filter/FilterButtons.js +13 -15
- package/lib/Filter/FilterListPhone.js +3 -5
- package/lib/Footer/index.d.ts +1 -2
- package/lib/Footer/index.js +0 -7
- package/lib/Grid/Grid.d.ts +15 -0
- package/lib/Grid/Grid.js +48 -0
- package/lib/Grid/index.d.ts +9 -0
- package/lib/Grid/index.js +13 -0
- package/lib/LearningPaths/LearningPathMenuModalWrapper.js +9 -8
- package/lib/Masthead/MastheadSearchModal.d.ts +1 -1
- package/lib/Masthead/MastheadSearchModal.js +58 -46
- package/lib/MyNdla/SettingsMenu.js +5 -5
- package/lib/NDLAFilm/AboutNdlaFilm.js +2 -2
- package/lib/ResourcesWrapper/ResourcesTopicTitle.js +20 -27
- package/lib/SearchTypeResult/PopupFilter.js +14 -20
- package/lib/SearchTypeResult/components/ItemContexts.js +10 -21
- package/lib/Topic/Topic.js +22 -22
- package/lib/User/index.d.ts +0 -2
- package/lib/User/index.js +1 -13
- package/lib/index.d.ts +3 -3
- package/lib/index.js +8 -20
- package/lib/locale/messages-en.d.ts +1 -0
- package/lib/locale/messages-en.js +1 -0
- package/lib/locale/messages-nb.d.ts +1 -0
- package/lib/locale/messages-nb.js +1 -0
- package/lib/locale/messages-nn.d.ts +1 -0
- package/lib/locale/messages-nn.js +1 -0
- package/lib/locale/messages-se.d.ts +1 -0
- package/lib/locale/messages-se.js +1 -0
- package/lib/locale/messages-sma.d.ts +1 -0
- package/lib/locale/messages-sma.js +1 -0
- package/package.json +20 -22
- package/src/Article/Article.tsx +4 -4
- package/src/Article/ArticleHeaderWrapper.tsx +12 -18
- package/src/Article/ArticleNotions.tsx +7 -8
- package/src/Article/ArticleSideBar.tsx +3 -3
- package/src/AudioPlayer/Controls.tsx +150 -289
- package/src/BlogPost/BlogPost.stories.tsx +15 -12
- package/src/BlogPost/BlogPost.tsx +1 -1
- package/src/CompetenceGoals/CompetenceGoalsDialog.tsx +13 -38
- package/src/Filter/FilterButtons.tsx +4 -5
- package/src/Filter/FilterListPhone.tsx +3 -4
- package/src/Footer/index.ts +1 -2
- package/src/Grid/Grid.stories.tsx +68 -0
- package/src/Grid/Grid.tsx +63 -0
- package/src/Grid/index.ts +10 -0
- package/src/KeyFigure/KeyFigure.stories.tsx +10 -8
- package/src/LearningPaths/LearningPathMenuModalWrapper.tsx +10 -6
- package/src/Masthead/MastheadSearchModal.tsx +48 -74
- package/src/MyNdla/SettingsMenu.tsx +3 -3
- package/src/NDLAFilm/AboutNdlaFilm.tsx +3 -3
- package/src/ResourcesWrapper/ResourcesTopicTitle.tsx +4 -8
- package/src/SearchTypeResult/PopupFilter.tsx +6 -11
- package/src/SearchTypeResult/components/ItemContexts.tsx +4 -21
- package/src/Topic/Topic.tsx +7 -7
- package/src/User/index.ts +0 -2
- package/src/index.ts +3 -3
- package/src/locale/messages-en.ts +1 -0
- package/src/locale/messages-nb.ts +1 -0
- package/src/locale/messages-nn.ts +1 -0
- package/src/locale/messages-se.ts +1 -0
- package/src/locale/messages-sma.ts +1 -0
- package/es/Figure/FigureLicenseDialogContent.js +0 -75
- package/es/Footer/FooterAuth.js +0 -110
- package/es/Masthead/MastheadAuthModal.js +0 -50
- package/es/SearchTypeResult/SearchNotionItem.js +0 -208
- package/es/User/AuthModal.js +0 -116
- package/lib/Figure/FigureLicenseDialogContent.d.ts +0 -22
- package/lib/Figure/FigureLicenseDialogContent.js +0 -80
- package/lib/Footer/FooterAuth.d.ts +0 -10
- package/lib/Footer/FooterAuth.js +0 -114
- package/lib/Masthead/MastheadAuthModal.d.ts +0 -13
- package/lib/Masthead/MastheadAuthModal.js +0 -56
- package/lib/SearchTypeResult/SearchNotionItem.d.ts +0 -29
- package/lib/SearchTypeResult/SearchNotionItem.js +0 -215
- package/lib/User/AuthModal.d.ts +0 -22
- package/lib/User/AuthModal.js +0 -124
- package/src/Figure/FigureLicenseDialogContent.tsx +0 -80
- package/src/Footer/FooterAuth.tsx +0 -104
- package/src/Masthead/MastheadAuthModal.tsx +0 -62
- package/src/SearchTypeResult/SearchNotionItem.tsx +0 -228
- package/src/User/AuthModal.tsx +0 -123
|
@@ -8,179 +8,85 @@
|
|
|
8
8
|
|
|
9
9
|
import React, { useEffect, useRef, useState } from 'react';
|
|
10
10
|
import styled from '@emotion/styled';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
11
|
+
import { Root, Trigger, Item, Content, DropdownMenuPortal } from '@radix-ui/react-dropdown-menu';
|
|
12
|
+
import { Root as SliderRoot, Track, Range, SliderThumb } from '@radix-ui/react-slider';
|
|
13
|
+
import { Root as PopoverRoot, PopoverContent, PopoverTrigger, PopoverPortal } from '@radix-ui/react-popover';
|
|
14
14
|
import { Play, Pause, VolumeUp } from '@ndla/icons/common';
|
|
15
15
|
import { breakpoints, colors, fonts, misc, mq, spacing } from '@ndla/core';
|
|
16
16
|
import { useTranslation } from 'react-i18next';
|
|
17
17
|
import { Back15, Forward15 } from '@ndla/icons/action';
|
|
18
|
+
import { ButtonV2, IconButtonV2 } from '@ndla/button';
|
|
18
19
|
|
|
19
20
|
const ControlsWrapper = styled.div`
|
|
20
21
|
border: 1px solid ${colors.brand.lighter};
|
|
21
22
|
display: flex;
|
|
22
23
|
align-items: center;
|
|
23
24
|
justify-content: center;
|
|
24
|
-
background:
|
|
25
|
+
background: ${colors.white};
|
|
25
26
|
font-family: ${fonts.sans};
|
|
27
|
+
gap: ${spacing.xsmall};
|
|
28
|
+
padding: ${spacing.small} ${spacing.normal};
|
|
26
29
|
${mq.range({ until: breakpoints.tabletWide })} {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
display: grid;
|
|
31
|
+
padding: ${spacing.small};
|
|
32
|
+
grid-template-columns: 1fr repeat(5, auto) 1fr;
|
|
33
|
+
grid-template-areas:
|
|
34
|
+
'track track track track track track track'
|
|
35
|
+
'. speed backwards play forwards volume .';
|
|
32
36
|
}
|
|
33
37
|
`;
|
|
34
38
|
|
|
35
|
-
const PlayButton = styled
|
|
36
|
-
background: ${colors.brand.lighter};
|
|
37
|
-
border: none;
|
|
38
|
-
display: flex;
|
|
39
|
-
align-items: center;
|
|
40
|
-
justify-content: center;
|
|
41
|
-
padding: 0;
|
|
42
|
-
cursor: pointer;
|
|
43
|
-
color: ${colors.brand.primary};
|
|
44
|
-
width: 55px;
|
|
45
|
-
height: 55px;
|
|
46
|
-
border-radius: 50%;
|
|
47
|
-
transition: ${misc.transition.default};
|
|
48
|
-
margin-right: ${spacing.small};
|
|
39
|
+
const PlayButton = styled(IconButtonV2)`
|
|
49
40
|
${mq.range({ until: breakpoints.tabletWide })} {
|
|
50
|
-
|
|
51
|
-
margin-left: ${spacing.small};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
&:hover,
|
|
55
|
-
&:active,
|
|
56
|
-
&:focus {
|
|
57
|
-
background: ${colors.brand.primary};
|
|
58
|
-
color: #ffffff;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
.c-icon {
|
|
62
|
-
width: 24px;
|
|
63
|
-
height: 24px;
|
|
41
|
+
grid-area: play;
|
|
64
42
|
}
|
|
65
43
|
`;
|
|
66
44
|
|
|
67
|
-
const
|
|
68
|
-
background-color: inherit;
|
|
69
|
-
background-position: center;
|
|
70
|
-
background-repeat: no-repeat;
|
|
71
|
-
width: 42px;
|
|
72
|
-
height: 42px;
|
|
73
|
-
border: 0;
|
|
74
|
-
border-radius: 50%;
|
|
75
|
-
cursor: pointer;
|
|
76
|
-
font-weight: bold;
|
|
77
|
-
font-size: 9px;
|
|
78
|
-
line-height: 23px;
|
|
79
|
-
color: ${colors.brand.dark};
|
|
80
|
-
font-family: ${fonts.sans};
|
|
81
|
-
transition: ${misc.transition.default};
|
|
82
|
-
|
|
83
|
-
&:hover {
|
|
84
|
-
background-color: ${colors.brand.greyLighter};
|
|
85
|
-
}
|
|
86
|
-
`;
|
|
87
|
-
|
|
88
|
-
const Forward15SecButton = styled(ForwardRewindButton)`
|
|
89
|
-
svg {
|
|
90
|
-
fill: ${colors.brand.primary};
|
|
91
|
-
width: 24px;
|
|
92
|
-
height: 24px;
|
|
93
|
-
}
|
|
45
|
+
const Forward15SecButton = styled(IconButtonV2)`
|
|
94
46
|
${mq.range({ until: breakpoints.tabletWide })} {
|
|
95
|
-
|
|
47
|
+
grid-area: forwards;
|
|
96
48
|
}
|
|
97
49
|
`;
|
|
98
|
-
const Back15SecButton = styled(
|
|
99
|
-
svg {
|
|
100
|
-
fill: ${colors.brand.primary};
|
|
101
|
-
width: 24px;
|
|
102
|
-
height: 24px;
|
|
103
|
-
}
|
|
50
|
+
const Back15SecButton = styled(IconButtonV2)`
|
|
104
51
|
${mq.range({ until: breakpoints.tabletWide })} {
|
|
105
|
-
|
|
52
|
+
grid-area: backwards;
|
|
106
53
|
}
|
|
107
54
|
`;
|
|
108
55
|
|
|
109
|
-
const
|
|
110
|
-
position: relative;
|
|
111
|
-
display: flex;
|
|
112
|
-
justify-content: center;
|
|
56
|
+
const SpeedButton = styled(ButtonV2)`
|
|
113
57
|
${mq.range({ until: breakpoints.tabletWide })} {
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
`;
|
|
117
|
-
const SpeedButton = styled(MenuButton)`
|
|
118
|
-
height: 32px;
|
|
119
|
-
border: 0;
|
|
120
|
-
background: none;
|
|
121
|
-
cursor: pointer;
|
|
122
|
-
font-weight: 600;
|
|
123
|
-
font-size: 12px;
|
|
124
|
-
text-align: center;
|
|
125
|
-
width: 52px;
|
|
126
|
-
&:hover,
|
|
127
|
-
&:active,
|
|
128
|
-
&:focus,
|
|
129
|
-
&[aria-expanded='true'] {
|
|
130
|
-
background: ${colors.brand.greyLighter};
|
|
131
|
-
border-radius: 27px;
|
|
132
|
-
color: ${colors.text.primary};
|
|
58
|
+
grid-area: speed;
|
|
133
59
|
}
|
|
134
60
|
`;
|
|
135
61
|
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
bottom: 36px;
|
|
139
|
-
z-index: 99;
|
|
140
|
-
`;
|
|
141
|
-
|
|
142
|
-
const SpeedList = styled(MenuItems)`
|
|
143
|
-
background: #ffffff;
|
|
62
|
+
const SpeedList = styled(Content)`
|
|
63
|
+
background: ${colors.white};
|
|
144
64
|
border: 1px solid ${colors.brand.lighter};
|
|
145
|
-
border-radius:
|
|
65
|
+
border-radius: ${misc.borderRadius};
|
|
146
66
|
padding: 5px 10px;
|
|
147
67
|
display: flex;
|
|
148
68
|
flex-direction: column;
|
|
149
69
|
justify-content: center;
|
|
150
|
-
align-items: stretch;
|
|
151
70
|
`;
|
|
152
71
|
|
|
153
|
-
|
|
154
|
-
selected?: boolean;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const SpeedValueButton = styled(MenuItem)<SpeedValueButtonProps>`
|
|
72
|
+
const SpeedValueButton = styled(Item)`
|
|
158
73
|
height: 28px;
|
|
159
|
-
position: relative;
|
|
160
|
-
background: none;
|
|
161
|
-
border: 0;
|
|
162
74
|
padding: 0 14px;
|
|
163
75
|
cursor: pointer;
|
|
164
|
-
font-weight:
|
|
165
|
-
|
|
76
|
+
font-weight: ${fonts.weight.semibold};
|
|
77
|
+
${fonts.sizes('14px')};
|
|
166
78
|
color: ${colors.text.light};
|
|
167
79
|
display: flex;
|
|
168
80
|
justify-content: center;
|
|
169
|
-
align-items: center;
|
|
170
81
|
&:hover,
|
|
171
82
|
&:active,
|
|
172
83
|
&:focus,
|
|
173
|
-
&[data-
|
|
84
|
+
&[data-highlighted] {
|
|
174
85
|
background: ${colors.brand.greyLighter};
|
|
175
86
|
border-radius: 5px;
|
|
87
|
+
outline: none;
|
|
176
88
|
color: ${colors.text.primary};
|
|
177
89
|
}
|
|
178
|
-
${(props) =>
|
|
179
|
-
props.selected &&
|
|
180
|
-
`
|
|
181
|
-
color: ${colors.text.primary};
|
|
182
|
-
|
|
183
|
-
`}
|
|
184
90
|
`;
|
|
185
91
|
|
|
186
92
|
const SpeedSelectedMark = styled.span`
|
|
@@ -188,142 +94,108 @@ const SpeedSelectedMark = styled.span`
|
|
|
188
94
|
background: #d1372e;
|
|
189
95
|
width: 6px;
|
|
190
96
|
height: 6px;
|
|
191
|
-
display: inline-block;
|
|
192
|
-
align-self: flex-start;
|
|
193
97
|
margin: 6px 0 0 2px;
|
|
194
98
|
`;
|
|
195
99
|
|
|
196
100
|
const Time = styled.div`
|
|
197
|
-
|
|
101
|
+
${fonts.sizes('16px')};
|
|
198
102
|
`;
|
|
199
103
|
|
|
200
104
|
const ProgressWrapper = styled.div`
|
|
201
|
-
flex: 1
|
|
105
|
+
flex: 1;
|
|
202
106
|
display: flex;
|
|
203
107
|
align-items: center;
|
|
204
|
-
|
|
108
|
+
gap: ${spacing.small};
|
|
205
109
|
${mq.range({ until: breakpoints.tabletWide })} {
|
|
206
|
-
|
|
207
|
-
width: 100%;
|
|
208
|
-
margin: 0;
|
|
209
|
-
margin-bottom: ${spacing.normal};
|
|
110
|
+
grid-area: track;
|
|
210
111
|
}
|
|
211
112
|
`;
|
|
212
|
-
|
|
113
|
+
|
|
114
|
+
const SliderWrapper = styled(SliderRoot)`
|
|
213
115
|
cursor: pointer;
|
|
214
|
-
flex: 1
|
|
215
|
-
|
|
116
|
+
flex: 1;
|
|
117
|
+
position: relative;
|
|
118
|
+
display: flex;
|
|
119
|
+
align-items: center;
|
|
120
|
+
user-select: none;
|
|
121
|
+
touch-action: none;
|
|
216
122
|
`;
|
|
217
123
|
|
|
218
|
-
const
|
|
124
|
+
const StyledTrack = styled(Track)`
|
|
219
125
|
height: 4px;
|
|
220
126
|
width: 100%;
|
|
221
127
|
background: ${colors.brand.lighter};
|
|
222
128
|
border-radius: 7px;
|
|
223
129
|
`;
|
|
224
130
|
|
|
225
|
-
const
|
|
131
|
+
const StyledRange = styled(Range)`
|
|
132
|
+
position: absolute;
|
|
226
133
|
height: 4px;
|
|
227
134
|
background: #5cbc80;
|
|
228
135
|
border-radius: 7px;
|
|
229
136
|
`;
|
|
230
137
|
|
|
231
|
-
const
|
|
138
|
+
const StyledThumb = styled(SliderThumb)`
|
|
139
|
+
display: block;
|
|
232
140
|
width: 20px;
|
|
233
141
|
height: 20px;
|
|
234
142
|
background: #5cbc80;
|
|
235
143
|
border-radius: 50%;
|
|
236
|
-
|
|
144
|
+
outline: none;
|
|
237
145
|
`;
|
|
238
146
|
|
|
239
|
-
const VolumeWrapper = styled(
|
|
147
|
+
const VolumeWrapper = styled(PopoverRoot)`
|
|
240
148
|
position: relative;
|
|
241
149
|
display: flex;
|
|
242
150
|
justify-content: center;
|
|
243
|
-
${mq.range({ until: breakpoints.tabletWide })} {
|
|
244
|
-
order: 6;
|
|
245
|
-
}
|
|
246
|
-
`;
|
|
247
|
-
|
|
248
|
-
const WardButtonWrapper = styled.div<{ order: number }>`
|
|
249
|
-
position: relative;
|
|
250
|
-
display: flex;
|
|
251
|
-
justify-content: center;
|
|
252
|
-
${mq.range({ until: breakpoints.tabletWide })} {
|
|
253
|
-
${(props) =>
|
|
254
|
-
`
|
|
255
|
-
order: ${props.order};
|
|
256
|
-
`}
|
|
257
|
-
}
|
|
258
|
-
`;
|
|
259
|
-
|
|
260
|
-
const VolumeButton = styled(Popover.Button)`
|
|
261
|
-
background-color: inherit;
|
|
262
|
-
width: 48px;
|
|
263
|
-
height: 48px;
|
|
264
|
-
border-radius: 50%;
|
|
265
|
-
border: 0;
|
|
266
|
-
background-position: center;
|
|
267
|
-
background-repeat: no-repeat;
|
|
268
|
-
cursor: pointer;
|
|
269
|
-
|
|
270
|
-
svg {
|
|
271
|
-
fill: ${colors.brand.primary};
|
|
272
|
-
width: 32px;
|
|
273
|
-
height: 32px;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
&:hover,
|
|
277
|
-
&:active,
|
|
278
|
-
&:focus,
|
|
279
|
-
&[aria-expanded='true'] {
|
|
280
|
-
background-color: ${colors.brand.greyLighter};
|
|
281
|
-
}
|
|
282
151
|
`;
|
|
283
152
|
|
|
284
|
-
const VolumeList = styled(
|
|
285
|
-
position: absolute;
|
|
286
|
-
bottom: 52px;
|
|
287
|
-
z-index: 99;
|
|
153
|
+
const VolumeList = styled(PopoverContent)`
|
|
288
154
|
box-shadow: 0 14px 20px -5px rgba(32, 88, 143, 0.17);
|
|
289
155
|
border-radius: 60px;
|
|
290
|
-
background:
|
|
156
|
+
background: ${colors.white};
|
|
157
|
+
padding: ${spacing.small};
|
|
291
158
|
border: 1px solid ${colors.brand.lighter};
|
|
292
|
-
display: flex;
|
|
293
|
-
flex-direction: column;
|
|
294
|
-
justify-content: center;
|
|
295
|
-
width: 32px;
|
|
296
159
|
height: 128px;
|
|
297
160
|
`;
|
|
298
161
|
|
|
299
|
-
const VolumeSliderWrapper = styled
|
|
162
|
+
const VolumeSliderWrapper = styled(SliderRoot)`
|
|
300
163
|
cursor: pointer;
|
|
301
|
-
|
|
164
|
+
height: 100%;
|
|
165
|
+
position: relative;
|
|
302
166
|
display: flex;
|
|
303
|
-
|
|
304
|
-
|
|
167
|
+
flex-direction: column;
|
|
168
|
+
align-items: center;
|
|
169
|
+
user-select: none;
|
|
170
|
+
touch-action: none;
|
|
171
|
+
`;
|
|
172
|
+
|
|
173
|
+
const VolumeButton = styled(IconButtonV2)`
|
|
174
|
+
${mq.range({ until: breakpoints.tabletWide })} {
|
|
175
|
+
grid-area: volume;
|
|
176
|
+
}
|
|
305
177
|
`;
|
|
306
178
|
|
|
307
|
-
const VolumeSliderBackground = styled(
|
|
179
|
+
const VolumeSliderBackground = styled(Track)`
|
|
308
180
|
height: 100%;
|
|
309
181
|
width: 5px;
|
|
310
182
|
background: ${colors.brand.lighter};
|
|
311
183
|
border-radius: 7px;
|
|
312
184
|
`;
|
|
313
185
|
|
|
314
|
-
const VolumeSliderSelected = styled(
|
|
186
|
+
const VolumeSliderSelected = styled(Range)`
|
|
187
|
+
position: absolute;
|
|
315
188
|
width: 5px;
|
|
316
189
|
background: ${colors.brand.secondary};
|
|
317
190
|
border-radius: 7px;
|
|
318
|
-
bottom: 0;
|
|
319
191
|
`;
|
|
320
192
|
|
|
321
|
-
const VolumeSliderHandle = styled(
|
|
193
|
+
const VolumeSliderHandle = styled(SliderThumb)`
|
|
194
|
+
display: block;
|
|
322
195
|
width: 20px;
|
|
323
196
|
height: 20px;
|
|
324
197
|
background: ${colors.brand.primary};
|
|
325
198
|
border-radius: 50%;
|
|
326
|
-
left: -8px;
|
|
327
199
|
`;
|
|
328
200
|
|
|
329
201
|
const formatTime = (seconds: number) => {
|
|
@@ -336,16 +208,15 @@ const formatTime = (seconds: number) => {
|
|
|
336
208
|
|
|
337
209
|
const speedValues = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
|
|
338
210
|
|
|
339
|
-
|
|
211
|
+
interface Props {
|
|
340
212
|
src: string;
|
|
341
213
|
title: string;
|
|
342
|
-
}
|
|
214
|
+
}
|
|
343
215
|
|
|
344
216
|
const Controls = ({ src, title }: Props) => {
|
|
345
217
|
const { t } = useTranslation();
|
|
346
218
|
const [speedValue, setSpeedValue] = useState(1);
|
|
347
219
|
const [volumeValue, setVolumeValue] = useState(100);
|
|
348
|
-
const [sliderValue, setSliderValue] = useState(0);
|
|
349
220
|
const [currentTime, setCurrentTime] = useState(0);
|
|
350
221
|
const [remainingTime, setRemainingTime] = useState(0);
|
|
351
222
|
const [playing, setPlaying] = useState(false);
|
|
@@ -362,8 +233,6 @@ const Controls = ({ src, title }: Props) => {
|
|
|
362
233
|
const audioElement = audioRef.current;
|
|
363
234
|
const handleTimeUpdate = () => {
|
|
364
235
|
const { currentTime, duration } = audioElement;
|
|
365
|
-
const percent = Math.round((currentTime / duration) * 100);
|
|
366
|
-
setSliderValue(percent);
|
|
367
236
|
setCurrentTime(Math.round(currentTime));
|
|
368
237
|
setRemainingTime(Math.round(duration - currentTime));
|
|
369
238
|
};
|
|
@@ -372,7 +241,6 @@ const Controls = ({ src, title }: Props) => {
|
|
|
372
241
|
const { currentTime, duration } = audioElement;
|
|
373
242
|
setCurrentTime(Math.round(currentTime));
|
|
374
243
|
setRemainingTime(Math.round(duration - currentTime));
|
|
375
|
-
setRemainingTime(Math.round(duration - currentTime));
|
|
376
244
|
};
|
|
377
245
|
|
|
378
246
|
const handleTimeEnded = () => {
|
|
@@ -408,16 +276,16 @@ const Controls = ({ src, title }: Props) => {
|
|
|
408
276
|
}
|
|
409
277
|
};
|
|
410
278
|
|
|
411
|
-
const handleSliderChange = (value: number) => {
|
|
279
|
+
const handleSliderChange = (value: number[]) => {
|
|
412
280
|
if (audioRef.current) {
|
|
413
|
-
audioRef.current.currentTime =
|
|
281
|
+
audioRef.current.currentTime = value[0];
|
|
414
282
|
}
|
|
415
283
|
};
|
|
416
284
|
|
|
417
|
-
const handleVolumeSliderChange = (
|
|
285
|
+
const handleVolumeSliderChange = (values: number[]) => {
|
|
418
286
|
if (audioRef.current) {
|
|
419
|
-
audioRef.current.volume =
|
|
420
|
-
setVolumeValue(
|
|
287
|
+
audioRef.current.volume = values[0] / 100;
|
|
288
|
+
setVolumeValue(values[0]);
|
|
421
289
|
}
|
|
422
290
|
};
|
|
423
291
|
|
|
@@ -426,102 +294,95 @@ const Controls = ({ src, title }: Props) => {
|
|
|
426
294
|
{/* eslint-disable-next-line jsx-a11y/media-has-caption */}
|
|
427
295
|
<audio ref={audioRef} src={src} title={title} preload="metadata" />
|
|
428
296
|
<ControlsWrapper>
|
|
429
|
-
<PlayButton
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
</span>
|
|
297
|
+
<PlayButton
|
|
298
|
+
aria-label={t(playing ? t('audio.pause') : t('audio.play'))}
|
|
299
|
+
colorTheme="lighter"
|
|
300
|
+
size="normal"
|
|
301
|
+
onClick={togglePlay}
|
|
302
|
+
>
|
|
303
|
+
{playing ? <Pause /> : <Play />}
|
|
437
304
|
</PlayButton>
|
|
438
|
-
<
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
<SpeedWrapper>
|
|
452
|
-
<Menu>
|
|
305
|
+
<Back15SecButton
|
|
306
|
+
variant="ghost"
|
|
307
|
+
colorTheme="greyLighter"
|
|
308
|
+
title={t('audio.controls.rewind15sec')}
|
|
309
|
+
aria-label={t('audio.controls.rewind15sec')}
|
|
310
|
+
onClick={() => onSeekSeconds(-15)}
|
|
311
|
+
>
|
|
312
|
+
<Back15 />
|
|
313
|
+
</Back15SecButton>
|
|
314
|
+
|
|
315
|
+
<Root>
|
|
316
|
+
<Trigger asChild>
|
|
453
317
|
<SpeedButton
|
|
454
|
-
|
|
455
|
-
|
|
318
|
+
shape="pill"
|
|
319
|
+
variant="ghost"
|
|
320
|
+
size="normal"
|
|
321
|
+
colorTheme="greyLighter"
|
|
456
322
|
title={t('audio.controls.selectSpeed')}
|
|
457
323
|
aria-label={t('audio.controls.selectSpeed')}
|
|
458
324
|
>
|
|
459
325
|
{speedValue}x
|
|
460
326
|
</SpeedButton>
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
</Menu>
|
|
482
|
-
</SpeedWrapper>
|
|
483
|
-
<WardButtonWrapper order={5}>
|
|
484
|
-
<Forward15SecButton
|
|
485
|
-
type="button"
|
|
486
|
-
title={t('audio.controls.forward15sec')}
|
|
487
|
-
aria-label={t('audio.controls.forward15sec')}
|
|
488
|
-
onClick={() => {
|
|
489
|
-
onSeekSeconds(15);
|
|
490
|
-
}}
|
|
491
|
-
>
|
|
492
|
-
<Forward15 />
|
|
493
|
-
</Forward15SecButton>
|
|
494
|
-
</WardButtonWrapper>
|
|
327
|
+
</Trigger>
|
|
328
|
+
<DropdownMenuPortal>
|
|
329
|
+
<SpeedList side="top">
|
|
330
|
+
{speedValues.map((speed) => (
|
|
331
|
+
<SpeedValueButton key={speed} onSelect={() => setSpeedValue(speed)}>
|
|
332
|
+
{speed}x{speed === speedValue && <SpeedSelectedMark />}
|
|
333
|
+
</SpeedValueButton>
|
|
334
|
+
))}
|
|
335
|
+
</SpeedList>
|
|
336
|
+
</DropdownMenuPortal>
|
|
337
|
+
</Root>
|
|
338
|
+
<Forward15SecButton
|
|
339
|
+
colorTheme="greyLighter"
|
|
340
|
+
variant="ghost"
|
|
341
|
+
title={t('audio.controls.forward15sec')}
|
|
342
|
+
aria-label={t('audio.controls.forward15sec')}
|
|
343
|
+
onClick={() => onSeekSeconds(15)}
|
|
344
|
+
>
|
|
345
|
+
<Forward15 />
|
|
346
|
+
</Forward15SecButton>
|
|
495
347
|
<ProgressWrapper>
|
|
496
348
|
<Time>{formatTime(currentTime)}</Time>
|
|
497
|
-
<SliderWrapper
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
349
|
+
<SliderWrapper
|
|
350
|
+
value={[audioRef.current?.currentTime ?? 0]}
|
|
351
|
+
defaultValue={[0]}
|
|
352
|
+
step={1}
|
|
353
|
+
max={audioRef.current?.duration ?? 0}
|
|
354
|
+
onValueChange={handleSliderChange}
|
|
355
|
+
>
|
|
356
|
+
<StyledTrack>
|
|
357
|
+
<StyledRange />
|
|
358
|
+
</StyledTrack>
|
|
359
|
+
<StyledThumb />
|
|
504
360
|
</SliderWrapper>
|
|
505
361
|
<Time>-{formatTime(remainingTime)}</Time>
|
|
506
362
|
</ProgressWrapper>
|
|
507
363
|
<VolumeWrapper>
|
|
508
|
-
<
|
|
509
|
-
<
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
364
|
+
<PopoverTrigger asChild>
|
|
365
|
+
<VolumeButton variant="ghost" colorTheme="greyLighter" aria-label={t('audio.controls.adjustVolume')}>
|
|
366
|
+
<VolumeUp />
|
|
367
|
+
</VolumeButton>
|
|
368
|
+
</PopoverTrigger>
|
|
369
|
+
<PopoverPortal>
|
|
370
|
+
<VolumeList side="top">
|
|
371
|
+
<VolumeSliderWrapper
|
|
372
|
+
orientation="vertical"
|
|
373
|
+
value={[volumeValue]}
|
|
374
|
+
min={0}
|
|
375
|
+
defaultValue={[100]}
|
|
376
|
+
step={1}
|
|
377
|
+
onValueChange={handleVolumeSliderChange}
|
|
517
378
|
>
|
|
518
|
-
<VolumeSliderBackground
|
|
519
|
-
<VolumeSliderSelected
|
|
520
|
-
<VolumeSliderHandle as="div" />
|
|
379
|
+
<VolumeSliderBackground>
|
|
380
|
+
<VolumeSliderSelected />
|
|
521
381
|
</VolumeSliderBackground>
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
382
|
+
<VolumeSliderHandle />
|
|
383
|
+
</VolumeSliderWrapper>
|
|
384
|
+
</VolumeList>
|
|
385
|
+
</PopoverPortal>
|
|
525
386
|
</VolumeWrapper>
|
|
526
387
|
</ControlsWrapper>
|
|
527
388
|
</div>
|
|
@@ -8,9 +8,21 @@
|
|
|
8
8
|
|
|
9
9
|
import React from 'react';
|
|
10
10
|
import { Meta, StoryFn } from '@storybook/react';
|
|
11
|
-
import BlogPost from './BlogPost';
|
|
11
|
+
import BlogPost, { Props } from './BlogPost';
|
|
12
12
|
import { defaultParameters } from '../../../../stories/defaults';
|
|
13
13
|
|
|
14
|
+
const args: Props = {
|
|
15
|
+
title: { title: 'Min bloggpost', language: 'nb-no' },
|
|
16
|
+
author: 'Ola Nordmann',
|
|
17
|
+
url: '#',
|
|
18
|
+
headingLevel: 'h3',
|
|
19
|
+
size: 'large',
|
|
20
|
+
metaImage: {
|
|
21
|
+
alt: 'Yonghetempelet i Beijing. Foto.',
|
|
22
|
+
url: 'https://api.test.ndla.no/image-api/raw/id//62870',
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
14
26
|
export default {
|
|
15
27
|
title: 'Enkle komponenter/Blog Post',
|
|
16
28
|
component: BlogPost,
|
|
@@ -18,21 +30,12 @@ export default {
|
|
|
18
30
|
parameters: {
|
|
19
31
|
...defaultParameters,
|
|
20
32
|
},
|
|
21
|
-
args:
|
|
22
|
-
title: { title: 'Min bloggpost', language: 'nb-no' },
|
|
23
|
-
author: 'Ola Nordmann',
|
|
24
|
-
url: '#',
|
|
25
|
-
headingLevel: 'h3',
|
|
26
|
-
size: 'large',
|
|
27
|
-
metaImage: {
|
|
28
|
-
alt: 'Yonghetempelet i Beijing. Foto.',
|
|
29
|
-
url: 'https://api.test.ndla.no/image-api/raw/20080101-032119-ag.jpg',
|
|
30
|
-
},
|
|
31
|
-
},
|
|
33
|
+
args: args,
|
|
32
34
|
} as Meta<typeof BlogPost>;
|
|
33
35
|
|
|
34
36
|
export const BlogPostStory: StoryFn<typeof BlogPost> = ({ ...args }) => {
|
|
35
37
|
return <BlogPost {...args} />;
|
|
36
38
|
};
|
|
37
39
|
|
|
40
|
+
BlogPostStory.args = args;
|
|
38
41
|
BlogPostStory.storyName = 'BlogPost';
|