richie-education 2.34.1-dev2 → 2.34.1-dev22

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "richie-education",
3
- "version": "2.34.1-dev2",
3
+ "version": "2.34.1-dev22",
4
4
  "description": "A CMS to build learning portals for Open Education",
5
5
  "main": "sandbox/manage.py",
6
6
  "scripts": {
@@ -38,75 +38,75 @@
38
38
  "not dead"
39
39
  ],
40
40
  "dependencies": {
41
- "@babel/core": "7.26.0",
41
+ "@babel/core": "7.26.9",
42
42
  "@babel/plugin-syntax-dynamic-import": "7.8.3",
43
43
  "@babel/plugin-transform-modules-commonjs": "7.26.3",
44
- "@babel/preset-env": "7.26.0",
44
+ "@babel/preset-env": "7.26.9",
45
45
  "@babel/preset-react": "7.26.3",
46
46
  "@babel/preset-typescript": "7.26.0",
47
- "@faker-js/faker": "9.3.0",
48
- "@formatjs/cli": "6.3.14",
49
- "@formatjs/intl-relativetimeformat": "11.4.8",
50
- "@hookform/resolvers": "3.9.1",
47
+ "@faker-js/faker": "9.6.0",
48
+ "@formatjs/cli": "6.6.1",
49
+ "@formatjs/intl-relativetimeformat": "11.4.10",
50
+ "@hookform/resolvers": "4.1.3",
51
51
  "@lyracom/embedded-form-glue": "1.4.2",
52
52
  "@openfun/cunningham-react": "3.0.0",
53
53
  "@openfun/cunningham-tokens": "2.2.0",
54
- "@sentry/browser": "8.42.0",
55
- "@sentry/types": "8.42.0",
56
- "@storybook/addon-actions": "8.4.7",
57
- "@storybook/addon-essentials": "8.4.7",
58
- "@storybook/addon-interactions": "8.4.7",
59
- "@storybook/addon-links": "8.4.7",
60
- "@storybook/react": "8.4.7",
61
- "@storybook/react-webpack5": "8.4.7",
62
- "@storybook/test": "8.4.7",
63
- "@tanstack/query-core": "5.62.3",
64
- "@tanstack/query-sync-storage-persister": "5.62.3",
65
- "@tanstack/react-query": "5.62.3",
66
- "@tanstack/react-query-devtools": "5.62.3",
67
- "@tanstack/react-query-persist-client": "5.62.3",
54
+ "@sentry/browser": "9.5.0",
55
+ "@sentry/types": "9.5.0",
56
+ "@storybook/addon-actions": "8.6.4",
57
+ "@storybook/addon-essentials": "8.6.4",
58
+ "@storybook/addon-interactions": "8.6.4",
59
+ "@storybook/addon-links": "8.6.4",
60
+ "@storybook/react": "8.6.4",
61
+ "@storybook/react-webpack5": "8.6.4",
62
+ "@storybook/test": "8.6.4",
63
+ "@tanstack/query-core": "5.67.2",
64
+ "@tanstack/query-sync-storage-persister": "5.67.2",
65
+ "@tanstack/react-query": "5.67.2",
66
+ "@tanstack/react-query-devtools": "5.67.2",
67
+ "@tanstack/react-query-persist-client": "5.67.2",
68
68
  "@testing-library/dom": "10.4.0",
69
69
  "@testing-library/jest-dom": "6.6.3",
70
- "@testing-library/react": "16.1.0",
71
- "@testing-library/user-event": "14.5.2",
72
- "@types/fetch-mock": "7.3.8",
73
- "@types/iframe-resizer": "3.5.13",
70
+ "@testing-library/react": "16.2.0",
71
+ "@testing-library/user-event": "14.6.1",
72
+ "@types/fetch-mock": "9.2.2",
73
+ "@types/iframe-resizer": "4.0.0",
74
74
  "@types/jest": "29.5.14",
75
75
  "@types/js-cookie": "3.0.6",
76
76
  "@types/lodash-es": "4.17.12",
77
77
  "@types/node-fetch": "2.6.12",
78
78
  "@types/query-string": "6.3.0",
79
- "@types/react": "19.0.1",
79
+ "@types/react": "19.0.10",
80
80
  "@types/react-autosuggest": "10.1.11",
81
- "@types/react-dom": "19.0.1",
81
+ "@types/react-dom": "19.0.4",
82
82
  "@types/react-modal": "3.16.3",
83
- "@typescript-eslint/eslint-plugin": "8.17.0",
84
- "@typescript-eslint/parser": "8.17.0",
83
+ "@typescript-eslint/eslint-plugin": "8.26.0",
84
+ "@typescript-eslint/parser": "8.26.0",
85
85
  "babel-jest": "29.7.0",
86
- "babel-loader": "9.2.1",
86
+ "babel-loader": "10.0.0",
87
87
  "babel-plugin-react-intl": "8.2.25",
88
88
  "bootstrap": ">=4.6.0 <5",
89
89
  "classnames": "2.5.1",
90
90
  "cljs-merge": "1.1.1",
91
- "core-js": "3.39.0",
91
+ "core-js": "3.41.0",
92
92
  "downshift": "9.0.8",
93
93
  "eslint": ">=8.57.0 <9",
94
94
  "eslint-config-airbnb": "19.0.4",
95
95
  "eslint-config-airbnb-typescript": "18.0.0",
96
- "eslint-config-prettier": "9.1.0",
97
- "eslint-import-resolver-webpack": "0.13.9",
98
- "eslint-plugin-compat": "6.0.1",
99
- "eslint-plugin-formatjs": "5.2.8",
96
+ "eslint-config-prettier": "10.1.1",
97
+ "eslint-import-resolver-webpack": "0.13.10",
98
+ "eslint-plugin-compat": "6.0.2",
99
+ "eslint-plugin-formatjs": "5.2.14",
100
100
  "eslint-plugin-import": "2.31.0",
101
101
  "eslint-plugin-jsx-a11y": "6.10.2",
102
- "eslint-plugin-prettier": "5.2.1",
103
- "eslint-plugin-react": "7.37.2",
104
- "eslint-plugin-react-hooks": "5.1.0",
105
- "eslint-plugin-storybook": "0.11.1",
102
+ "eslint-plugin-prettier": "5.2.3",
103
+ "eslint-plugin-react": "7.37.4",
104
+ "eslint-plugin-react-hooks": "5.2.0",
105
+ "eslint-plugin-storybook": "0.11.4",
106
106
  "fetch-mock": "<10",
107
107
  "file-loader": "6.2.0",
108
- "glob": "11.0.0",
109
- "i18n-iso-countries": "7.13.0",
108
+ "glob": "11.0.1",
109
+ "i18n-iso-countries": "7.14.0",
110
110
  "iframe-resizer": "<5",
111
111
  "intl-pluralrules": "2.0.1",
112
112
  "jest": "29.7.0",
@@ -114,35 +114,35 @@
114
114
  "js-cookie": "3.0.5",
115
115
  "lodash-es": "4.17.21",
116
116
  "mdn-polyfills": "5.20.0",
117
- "msw": "2.6.8",
117
+ "msw": "2.7.3",
118
118
  "node-fetch": ">2.6.6 <3",
119
- "nodemon": "3.1.7",
120
- "prettier": "3.4.2",
119
+ "nodemon": "3.1.9",
120
+ "prettier": "3.5.3",
121
121
  "query-string": "9.1.1",
122
122
  "react": "19.0.0",
123
123
  "react-autosuggest": "10.1.0",
124
124
  "react-dom": "19.0.0",
125
- "react-hook-form": "7.54.0",
126
- "react-intl": "7.0.4",
127
- "react-modal": "3.16.1",
128
- "react-router": "7.0.2",
129
- "sass": "1.82.0",
125
+ "react-hook-form": "7.54.2",
126
+ "react-intl": "7.1.6",
127
+ "react-modal": "3.16.3",
128
+ "react-router": "7.3.0",
129
+ "sass": "1.85.1",
130
130
  "source-map-loader": "5.0.0",
131
- "storybook": "8.4.7",
131
+ "storybook": "8.6.4",
132
132
  "tsconfig-paths-webpack-plugin": "4.2.0",
133
- "typescript": "5.7.2",
134
- "uuid": "11.0.3",
135
- "webpack": "5.97.1",
136
- "webpack-cli": "5.1.4",
133
+ "typescript": "5.8.2",
134
+ "uuid": "11.1.0",
135
+ "webpack": "5.98.0",
136
+ "webpack-cli": "6.0.1",
137
137
  "whatwg-fetch": "3.6.20",
138
138
  "xhr-mock": "2.5.1",
139
139
  "yargs": "17.7.2",
140
- "yup": "1.5.0"
140
+ "yup": "1.6.1"
141
141
  },
142
142
  "resolutions": {
143
143
  "@testing-library/dom": "10.4.0",
144
- "@types/react": "19.0.1",
145
- "@types/react-dom": "19.0.1",
144
+ "@types/react": "19.0.10",
145
+ "@types/react-dom": "19.0.4",
146
146
  "react": "19.0.0",
147
147
  "react-dom": "19.0.0"
148
148
  },
@@ -154,7 +154,7 @@
154
154
  "yarn": "1.22.22"
155
155
  },
156
156
  "devDependencies": {
157
- "@storybook/addon-mdx-gfm": "8.4.7",
158
- "@storybook/addon-webpack5-compiler-babel": "3.0.3"
157
+ "@storybook/addon-mdx-gfm": "8.6.4",
158
+ "@storybook/addon-webpack5-compiler-babel": "3.0.5"
159
159
  }
160
160
  }
@@ -47,6 +47,14 @@ $r-theme: (
47
47
  item-cta-hollow-background: transparent,
48
48
  item-cta-hollow-border: transparent,
49
49
  item-divider-border: r-color('light-grey'),
50
+ dropdown-border-radius: 8px,
51
+ dropdown-padding: 0.5rem,
52
+ dropdown-gap: 0.5rem,
53
+ dropdown-background-color: r-color('azure2'),
54
+ dropdown-item-background-color: r-color('indianred3'),
55
+ dropdown-item-text-color: r-color('white'),
56
+ dropdown-item-border-radius: 4px,
57
+ dropdown-item-padding: 0.5rem 1rem,
50
58
  ),
51
59
  body-content: (
52
60
  base-color: r-color('black'),
@@ -483,6 +491,8 @@ $r-theme: (
483
491
  ),
484
492
  program-detail: (
485
493
  cover-empty-background: r-color('smoke'),
494
+ checkmark-list-decoration: url('../../richie/images/components/checkmark.svg'),
495
+ checkmark-list-decoration-color: r-color('indianred3'),
486
496
  ),
487
497
  registered-credit-card: (
488
498
  title-color: r-color('charcoal'),
@@ -168,6 +168,10 @@
168
168
  flex-wrap: nowrap;
169
169
  }
170
170
 
171
+ & > .topbar__list {
172
+ position: relative;
173
+ }
174
+
171
175
  // Aside menu variation
172
176
  &--aside {
173
177
  @include sv-flex(1, 0, auto);
@@ -197,6 +201,76 @@
197
201
  // Menu item element
198
202
  &__item {
199
203
  $item-selector: &;
204
+ &.dropdown {
205
+ display: block;
206
+ position: static;
207
+
208
+ & > button {
209
+ width: 100%;
210
+
211
+ & > .icon {
212
+ height: 1rem;
213
+ margin-left: 0.5rem;
214
+ width: 1rem;
215
+ }
216
+ }
217
+
218
+ & ul[role='menu'] {
219
+ padding-left: 0.5rem;
220
+ }
221
+ }
222
+
223
+ @include media-breakpoint-up($r-topbar-breakpoint) {
224
+ &.dropdown {
225
+ // See header_menu.html for the definition of the variables
226
+ --active-background-color: #{r-theme-val(topbar, dropdown-item-background-color)};
227
+ --active-text-color: #{r-theme-val(topbar, dropdown-item-text-color)};
228
+
229
+ & > button[aria-expanded='true'] {
230
+ background-color: r-theme-val(topbar, dropdown-background-color);
231
+ }
232
+
233
+ & > button[aria-expanded='true'] + .topbar__sublist {
234
+ display: block;
235
+ }
236
+
237
+ & > .topbar__sublist {
238
+ background: r-theme-val(topbar, dropdown-background-color);
239
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
240
+ border-radius: r-theme-val(topbar, dropdown-border-radius);
241
+ display: none;
242
+ position: absolute;
243
+ transform: translateX(-8px);
244
+ max-width: 100%;
245
+
246
+ &--full-width {
247
+ left: 0;
248
+ transform: inherit;
249
+ }
250
+
251
+ & > ul[role='menu'] {
252
+ display: flex;
253
+ flex-wrap: wrap;
254
+ gap: r-theme-val(topbar, dropdown-gap);
255
+ padding: r-theme-val(topbar, dropdown-padding);
256
+ }
257
+
258
+ & .topbar__item > a {
259
+ background-color: #fff;
260
+ border-radius: r-theme-val(topbar, dropdown-item-border-radius);
261
+ padding: r-theme-val(topbar, dropdown-item-padding);
262
+ &::after {
263
+ display: none;
264
+ }
265
+
266
+ &:is(:focus, :hover) {
267
+ background-color: var(--active-background-color);
268
+ color: var(--active-text-color);
269
+ }
270
+ }
271
+ }
272
+ }
273
+ }
200
274
 
201
275
  @include sv-flex(1, 0, auto);
202
276
  display: flex;
@@ -213,15 +287,23 @@
213
287
  --r--menu--item--hover--color: #{r-theme-val(topbar, item-hover-color)};
214
288
  }
215
289
 
216
- & > a {
290
+ & > button {
291
+ @include button-reset-style();
292
+ --radius: #{r-theme-val(topbar, dropdown-border-radius)};
293
+ border-radius: var(--radius) var(--radius) 0 0;
294
+ }
295
+
296
+ & > a,
297
+ & > button {
217
298
  @include sv-flex(1, 0, 100%);
299
+ align-items: center;
300
+ color: inherit;
218
301
  display: flex;
219
- padding: 1rem 0.2rem 1rem 1rem;
220
302
  flex-direction: row;
221
- align-items: center;
222
303
  font-family: inherit;
223
304
  font-weight: inherit;
224
- color: inherit;
305
+ justify-content: space-between;
306
+ padding: 1rem 0.2rem 1rem 1rem;
225
307
 
226
308
  @include media-breakpoint-up($r-topbar-breakpoint) {
227
309
  padding: 1rem 1rem;
@@ -235,18 +317,22 @@
235
317
 
236
318
  // If there is no default hover color we assume there is also no variant
237
319
  @if r-theme-val(topbar, item-hover-color) {
238
- &::after {
239
- content: '';
240
- position: absolute;
241
- bottom: 0;
242
- left: 0;
243
- right: 0;
244
- height: 8px;
320
+ &:is(a)::after {
245
321
  background-color: var(--r--menu--item--hover--color);
246
322
  border-top-left-radius: 0.2rem;
247
323
  border-top-right-radius: 0.2rem;
324
+ bottom: 0;
325
+ content: '';
326
+ height: 8px;
327
+ left: 0;
328
+ position: absolute;
329
+ right: 0;
248
330
  }
249
331
  }
332
+
333
+ &:is(button) {
334
+ background-color: r-theme-val(topbar, dropdown-background-color);
335
+ }
250
336
  }
251
337
  }
252
338
  }
@@ -257,8 +343,10 @@
257
343
 
258
344
  // Current page item or current ancestor
259
345
  &--selected,
260
- &--ancestor {
261
- & > a {
346
+ &--ancestor,
347
+ &:has(.topbar__sublist .topbar__item.topbar__item--selected) {
348
+ & > a,
349
+ & > button {
262
350
  position: relative;
263
351
  color: r-theme-val(topbar, item-active-color);
264
352
 
@@ -328,7 +416,8 @@
328
416
  }
329
417
 
330
418
  // Item divider
331
- & + #{$item-selector} {
419
+ & + #{$item-selector},
420
+ & > .topbar__list #{$item-selector} {
332
421
  @if r-theme-val(topbar, item-divider-border) {
333
422
  border-top: $onepixel solid r-theme-val(topbar, item-divider-border);
334
423
  }
@@ -5,7 +5,8 @@
5
5
  // Draw a background grid in pure CSS
6
6
  @mixin draw-grid($line-color: null, $border-color: null) {
7
7
  @if $line-color {
8
- background: linear-gradient(-90deg, $line-color $onepixel, transparent $onepixel),
8
+ background:
9
+ linear-gradient(-90deg, $line-color $onepixel, transparent $onepixel),
9
10
  linear-gradient($line-color $onepixel, transparent $onepixel),
10
11
  linear-gradient(-90deg, $line-color $onepixel, transparent $onepixel),
11
12
  linear-gradient($line-color $onepixel, transparent $onepixel),
@@ -2,11 +2,13 @@
2
2
  //
3
3
 
4
4
  .program-detail {
5
+ $detail-selector: &;
5
6
  margin: 0 auto;
6
7
  padding: 0;
7
8
 
8
9
  &__block {
9
10
  @include detail-block;
11
+
10
12
  @if $body-padding-fix {
11
13
  @include content-padding-fix($target: '&:last-child');
12
14
  }
@@ -54,6 +56,75 @@
54
56
  padding-right: $grid-gutter-width;
55
57
  }
56
58
 
59
+ &__objectives {
60
+ ul {
61
+ padding-left: 0.3rem;
62
+ list-style-type: none;
63
+
64
+ li {
65
+ position: relative;
66
+ margin-top: 0.5rem;
67
+ font-size: 1rem;
68
+ padding-left: 1.5rem;
69
+
70
+ &::before {
71
+ content: '';
72
+ display: block;
73
+ position: absolute;
74
+ top: 0.2rem;
75
+ left: 0;
76
+ width: 0.8rem;
77
+ height: 0.8rem;
78
+ background-repeat: no-repeat;
79
+ background-color: r-theme-val(program-detail, checkmark-list-decoration-color);
80
+ -webkit-mask: r-theme-val(program-detail, checkmark-list-decoration);
81
+ mask: r-theme-val(program-detail, checkmark-list-decoration);
82
+ -webkit-mask-size: cover;
83
+ mask-size: cover;
84
+ }
85
+ }
86
+ }
87
+ }
88
+
89
+ &__content {
90
+ @include media-breakpoint-up(lg) {
91
+ padding-right: 3rem;
92
+ }
93
+ }
94
+
95
+ &__aside {
96
+ padding: 1rem 0;
97
+
98
+ @include media-breakpoint-up(lg) {
99
+ @include sv-flex(1, 0, $r-program-aside);
100
+ padding: 3rem 1rem;
101
+ }
102
+
103
+ #{$detail-selector}__row {
104
+ margin-bottom: 1.5rem;
105
+ }
106
+
107
+ #{$detail-selector}__title {
108
+ @include font-size($h3-font-size);
109
+ padding-bottom: 1rem;
110
+
111
+ @if r-theme-val(course-detail, aside-title-border) {
112
+ border-bottom: $onepixel solid r-theme-val(course-detail, aside-title-border);
113
+ }
114
+ }
115
+ }
116
+
117
+ &__main {
118
+ @include media-breakpoint-up(lg) {
119
+ @include sv-flex(1, 0, calc(100% - #{$r-program-subheader-aside}));
120
+ display: flex;
121
+ justify-content: flex-start;
122
+ align-content: flex-start;
123
+ align-items: flex-start;
124
+ flex-wrap: wrap;
125
+ }
126
+ }
127
+
57
128
  &__courses {
58
129
  @include make-col-ready();
59
130
  @include make-col(12);
@@ -1,5 +1,6 @@
1
1
  .selector {
2
2
  position: relative;
3
+ z-index: 200;
3
4
 
4
5
  &__button {
5
6
  appearance: none;
@@ -152,11 +152,13 @@ $r-footer-logo-width-lg: 11.875rem !default;
152
152
  // full width like common blocks. Usefull if you plan to remove course run from
153
153
  // template
154
154
  $r-course-aside: 35% !default;
155
+ $r-program-aside: 25% !default;
155
156
 
156
157
  // Subheader aside column width in course detail. Unlike, $r-course-aside this
157
158
  // variable cannot be null. Otherwise to homegenize layout, it should have the
158
159
  // same value than $r-course-aside.
159
160
  $r-course-subheader-aside: 35% !default;
161
+ $r-program-subheader-aside: 25% !default;
160
162
 
161
163
  // Course search page shared variables
162
164
  $r-search-filters-gutter: 0.2rem !default;