fcad-core-dragon 2.1.0 → 2.1.2

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.
Files changed (160) hide show
  1. package/.editorconfig +7 -7
  2. package/.gitlab-ci.yml +124 -0
  3. package/.prettierrc +11 -11
  4. package/.vscode/extensions.json +8 -8
  5. package/.vscode/settings.json +46 -16
  6. package/CHANGELOG +520 -520
  7. package/README.md +57 -57
  8. package/documentation/.vitepress/config.js +114 -114
  9. package/documentation/api-examples.md +49 -49
  10. package/documentation/composants/app-base-button.md +58 -58
  11. package/documentation/composants/app-base-error-display.md +59 -59
  12. package/documentation/composants/app-base-popover.md +68 -68
  13. package/documentation/composants/app-comp-audio.md +75 -75
  14. package/documentation/composants/app-comp-branch-buttons.md +111 -111
  15. package/documentation/composants/app-comp-button-progress.md +53 -53
  16. package/documentation/composants/app-comp-carousel.md +53 -53
  17. package/documentation/composants/app-comp-container.md +53 -53
  18. package/documentation/composants/app-comp-input-checkbox-next.md +42 -42
  19. package/documentation/composants/app-comp-input-dropdown-next.md +34 -34
  20. package/documentation/composants/app-comp-input-radio-next.md +39 -39
  21. package/documentation/composants/app-comp-input-text-next.md +35 -35
  22. package/documentation/composants/app-comp-input-text-table-next.md +34 -34
  23. package/documentation/composants/app-comp-input-text-to-fill-dropdown-next.md +53 -53
  24. package/documentation/composants/app-comp-input-text-to-fill-next.md +31 -31
  25. package/documentation/composants/app-comp-jauge.md +31 -31
  26. package/documentation/composants/app-comp-menu-item.md +55 -55
  27. package/documentation/composants/app-comp-menu.md +29 -29
  28. package/documentation/composants/app-comp-navigation.md +41 -41
  29. package/documentation/composants/app-comp-note-call.md +53 -53
  30. package/documentation/composants/app-comp-note-credit.md +53 -53
  31. package/documentation/composants/app-comp-play-bar-next.md +53 -53
  32. package/documentation/composants/app-comp-pop-up-next.md +93 -93
  33. package/documentation/composants/app-comp-quiz-next.md +235 -235
  34. package/documentation/composants/app-comp-quiz-recall.md +53 -53
  35. package/documentation/composants/app-comp-svg-next.md +53 -53
  36. package/documentation/composants/app-comp-table-of-content.md +50 -50
  37. package/documentation/composants/app-comp-video-player.md +82 -82
  38. package/documentation/composants.md +46 -46
  39. package/documentation/composants_critiques/ModelPageComposant.md +53 -53
  40. package/documentation/composants_critiques/app-base-module.md +43 -43
  41. package/documentation/composants_critiques/app-base-page.md +48 -48
  42. package/documentation/composants_critiques/app-base.md +311 -311
  43. package/documentation/composants_critiques/main.md +15 -15
  44. package/documentation/demarrage.md +50 -50
  45. package/documentation/deploiement.md +57 -57
  46. package/documentation/index.md +33 -33
  47. package/documentation/markdown-examples.md +85 -85
  48. package/documentation/public/vite.svg +14 -14
  49. package/documentation/public/vuejs.svg +1 -1
  50. package/documentation/public/vuetify.svg +5 -5
  51. package/eslint.config.js +60 -60
  52. package/junit-report.xml +182 -0
  53. package/package.json +66 -59
  54. package/playwright/index.html +12 -0
  55. package/playwright/index.js +21 -0
  56. package/playwright-ct.config.js +95 -0
  57. package/src/$locales/en.json +157 -157
  58. package/src/$locales/fr.json +120 -120
  59. package/src/assets/data/onboardingMessages.json +47 -47
  60. package/src/components/AppBase.vue +1171 -1169
  61. package/src/components/AppBaseButton.vue +90 -95
  62. package/src/components/AppBaseErrorDisplay.vue +438 -438
  63. package/src/components/AppBaseFlipCard.vue +84 -84
  64. package/src/components/AppBaseModule.vue +1639 -1634
  65. package/src/components/AppBasePage.vue +3 -2
  66. package/src/components/AppBasePopover.vue +41 -41
  67. package/src/components/AppBaseSkeleton.vue +66 -66
  68. package/src/components/AppCompAudio.vue +261 -256
  69. package/src/components/AppCompBranchButtons.vue +508 -508
  70. package/src/components/AppCompButtonProgress.vue +137 -132
  71. package/src/components/AppCompCarousel.vue +342 -336
  72. package/src/components/AppCompContainer.vue +29 -29
  73. package/src/components/AppCompInputCheckBoxNx.vue +325 -323
  74. package/src/components/AppCompInputDropdownNx.vue +302 -299
  75. package/src/components/AppCompInputRadioNx.vue +287 -284
  76. package/src/components/AppCompInputTextNx.vue +156 -153
  77. package/src/components/AppCompInputTextTableNx.vue +205 -202
  78. package/src/components/AppCompInputTextToFillDropdownNx.vue +343 -340
  79. package/src/components/AppCompInputTextToFillNx.vue +316 -313
  80. package/src/components/AppCompJauge.vue +81 -81
  81. package/src/components/AppCompMenu.vue +6 -2
  82. package/src/components/AppCompMenuItem.vue +246 -240
  83. package/src/components/AppCompNavigation.vue +977 -972
  84. package/src/components/AppCompNoteCall.vue +167 -161
  85. package/src/components/AppCompNoteCredit.vue +496 -491
  86. package/src/components/AppCompPlayBarNext.vue +2290 -2288
  87. package/src/components/AppCompPopUpNext.vue +508 -504
  88. package/src/components/AppCompQuizNext.vue +515 -510
  89. package/src/components/AppCompQuizRecall.vue +355 -350
  90. package/src/components/AppCompSVGNext.vue +346 -346
  91. package/src/components/AppCompSettingsMenu.vue +177 -172
  92. package/src/components/AppCompTableOfContent.vue +433 -427
  93. package/src/components/AppCompVideoPlayer.vue +377 -377
  94. package/src/components/AppCompViewDisplay.vue +6 -6
  95. package/src/components/BaseModule.vue +55 -55
  96. package/src/composables/useIdleDetector.js +56 -56
  97. package/src/composables/useQuiz.js +89 -89
  98. package/src/composables/useTimer.js +172 -172
  99. package/src/directives/nvdaFix.js +53 -53
  100. package/src/externalComps/ModuleView.vue +22 -22
  101. package/src/externalComps/SummaryView.vue +91 -91
  102. package/src/main.js +493 -476
  103. package/src/module/stores/appStore.js +960 -947
  104. package/src/module/xapi/ADL.js +520 -520
  105. package/src/module/xapi/Crypto/Hasher.js +241 -241
  106. package/src/module/xapi/Crypto/WordArray.js +278 -278
  107. package/src/module/xapi/Crypto/algorithms/BufferedBlockAlgorithm.js +103 -103
  108. package/src/module/xapi/Crypto/algorithms/C_algo.js +315 -315
  109. package/src/module/xapi/Crypto/algorithms/HMAC.js +9 -9
  110. package/src/module/xapi/Crypto/algorithms/SHA1.js +9 -9
  111. package/src/module/xapi/Crypto/encoders/Base.js +105 -105
  112. package/src/module/xapi/Crypto/encoders/Base64.js +99 -99
  113. package/src/module/xapi/Crypto/encoders/Hex.js +61 -61
  114. package/src/module/xapi/Crypto/encoders/Latin1.js +61 -61
  115. package/src/module/xapi/Crypto/encoders/Utf8.js +45 -45
  116. package/src/module/xapi/Crypto/index.js +53 -53
  117. package/src/module/xapi/Statement/activity.js +47 -47
  118. package/src/module/xapi/Statement/agent.js +55 -55
  119. package/src/module/xapi/Statement/group.js +26 -26
  120. package/src/module/xapi/Statement/index.js +259 -259
  121. package/src/module/xapi/Statement/statement.js +253 -253
  122. package/src/module/xapi/Statement/statementRef.js +23 -23
  123. package/src/module/xapi/Statement/substatement.js +22 -22
  124. package/src/module/xapi/Statement/verb.js +36 -36
  125. package/src/module/xapi/activitytypes.js +17 -17
  126. package/src/module/xapi/launch.js +157 -157
  127. package/src/module/xapi/utils.js +167 -167
  128. package/src/module/xapi/verbs.js +294 -294
  129. package/src/module/xapi/wrapper.js +1895 -1895
  130. package/src/module/xapi/xapiStatement.js +444 -444
  131. package/src/plugins/analytics.js +34 -34
  132. package/src/plugins/bus.js +12 -8
  133. package/src/plugins/gsap.js +17 -15
  134. package/src/plugins/helper.js +355 -358
  135. package/src/plugins/i18n.js +27 -26
  136. package/src/plugins/idb.js +227 -227
  137. package/src/plugins/save.js +37 -37
  138. package/src/plugins/scorm.js +287 -287
  139. package/src/plugins/xapi.js +11 -11
  140. package/src/public/index.html +33 -33
  141. package/src/router/index.js +57 -57
  142. package/src/router/routes.js +312 -312
  143. package/src/shared/generalfuncs.js +344 -344
  144. package/src/shared/validators.js +1018 -1018
  145. package/tests/component/AppBaseButton.spec.js +53 -0
  146. package/tests/component/pinia.spec.js +24 -0
  147. package/{src/components/tests__ → tests/unit}/AppBaseButton.spec.js +53 -53
  148. package/tests/unit/AppCompInputCheckBoxNx.spec.js +59 -0
  149. package/tests/unit/AppCompInputDropdownNx.spec.js +51 -0
  150. package/tests/unit/AppCompInputRadioNx.spec.js +59 -0
  151. package/tests/unit/AppCompInputTextNx.spec.js +44 -0
  152. package/tests/unit/AppCompInputTextTableNx.spec.js +77 -0
  153. package/tests/unit/AppCompInputTextToFillDropdownNx.spec.js +60 -0
  154. package/tests/unit/AppCompInputTextToFillNx.spec.js +45 -0
  155. package/tests/unit/AppCompQuizNext.spec.js +114 -0
  156. package/tests/unit/AppCompVideoPlayer.spec.js +177 -0
  157. package/{src/components/tests__ → tests/unit}/useTimer.spec.js +91 -91
  158. package/vitest.config.js +28 -19
  159. package/vitest.setup.js +28 -0
  160. package/src/components/AppBaseButton.test.js +0 -21
@@ -1,256 +1,261 @@
1
- <template>
2
- <section
3
- :id="'audio_' + id"
4
- ref="$media-container"
5
- class="__media-container"
6
- aria-label="Audio"
7
- >
8
- <!--Integration error display-->
9
- <app-base-error-display
10
- v-if="hasErr.length"
11
- :error-group="'component'"
12
- :error-title="`ERREUR: COMPOSANT D'AUDIO`"
13
- :errors-list="hasErr"
14
- />
15
-
16
- <div v-else class="audio-card">
17
- <!--Waiting and loading error -- skeleton-->
18
- <div
19
- v-if="isLoading || hasSourceLoadingError"
20
- class="skeleton audio"
21
- :class="{ isloading: isLoading, error: hasSourceLoadingError }"
22
- >
23
- <p v-if="hasSourceLoadingError">
24
- Une erreur s'est produite lors du chargement du média, veuillez
25
- réessayer
26
- </p>
27
- </div>
28
- <!--Audio content-->
29
- <div v-show="!isLoading && !hasSourceLoadingError" class="audio-content">
30
- <img
31
- v-if="mPoster"
32
- class="audio-img"
33
- :src="mPoster"
34
- aria-hidden="true"
35
- />
36
- <div class="audio-media">
37
- <span>{{ mTitle }}</span>
38
- <div class="audio-media-player">
39
- <audio
40
- :id="id"
41
- ref="m-audio"
42
- @loadedmetadata="updateMediaDataAudio($event.target)"
43
- >
44
- <source
45
- v-for="(aSource, index) in mSources"
46
- :key="index"
47
- :src="aSource.src"
48
- :type="aSource.type ? `audio/${aSource.type}` : 'audio/mp3'"
49
- @error="errorHandling($event)"
50
- />
51
- </audio>
52
- <app-comp-play-bar-next
53
- v-if="$audElement"
54
- :ref="`plyr_${id}`"
55
- :media-to-play="$audElement"
56
- />
57
- </div>
58
- </div>
59
- </div>
60
- <div class="audio-transcript">
61
- <v-expansion-panels class="audio">
62
- <v-expansion-panel>
63
- <v-expansion-panel-title>
64
- {{ $t('text.transcript') }}
65
- </v-expansion-panel-title>
66
- <v-expansion-panel-text>
67
- <div v-html="mTranscript"></div>
68
- </v-expansion-panel-text>
69
- </v-expansion-panel>
70
- </v-expansion-panels>
71
- </div>
72
- </div>
73
- </section>
74
- </template>
75
- <script>
76
- import { mapState, mapActions } from 'pinia'
77
- import { useAppStore } from '../module/stores/appStore'
78
- import { validateAudioData } from '../shared/validators'
79
- import AppCompPlayBarNext from './AppCompPlayBarNext.vue'
80
-
81
- export default {
82
- components: { AppCompPlayBarNext },
83
- props: {
84
- audData: {
85
- type: Object,
86
- required: true
87
- }
88
- },
89
- data() {
90
- return {
91
- id: this.audData.id,
92
- mTitle: this.audData.mTitle,
93
- mSources: this.audData.mSources,
94
- mTranscript: this.audData.mTranscript,
95
- mPoster: this.audData.mPoster,
96
- isSet: false,
97
- hasSourceLoadingError: false,
98
- hasErr: validateAudioData(this.audData)
99
- }
100
- },
101
- computed: {
102
- ...mapState(useAppStore, ['getCurrentBrowser', 'getCurrentPage']),
103
- $audElement() {
104
- if (!this.isSet) return null
105
- return {
106
- id: this.id,
107
- mTranscript: null,
108
- mType: 'audio',
109
- mSubtitles: null,
110
- mElement: this.$refs['m-audio']
111
- }
112
- },
113
- //MediaElement
114
- mediaElement() {
115
- if (!this.$audElement) return null
116
- const { mElement } = this.$audElement
117
- let thisElement = null
118
-
119
- if (!mElement) return null
120
- thisElement = mElement
121
-
122
- return thisElement
123
- },
124
- //Loading display
125
- isLoading() {
126
- if (!this.isSet && !this.hasSourceLoadingError) return true
127
- else return false
128
- }
129
- },
130
- mounted() {},
131
- beforeUnmount() {},
132
-
133
- methods: {
134
- ...mapActions(useAppStore, ['updateCurrentMediaElements']),
135
- /**
136
- * @description search the DOM for medias with duplicated ID declaration in the page
137
- * @return return Array of all DOM MediaElement with same id
138
- */
139
- checkDuplicatedID() {
140
- const mediaList = document.querySelectorAll('.__media-container')
141
- const duplicate = Array.from(mediaList).filter((media) =>
142
- media.id.includes(this.id)
143
- )
144
- return duplicate
145
- },
146
- /**
147
- * @description update the information for the mediaElement in the store
148
- * @param {htmlElement} e
149
- * @fires update-page to AppBaseModule.vue
150
- */
151
- updateMediaDataAudio(e) {
152
- //dispatch loading status of for this component
153
- this.$bus.$emit('set-comp-status', 'AppCompAudioPlayer', 'loading')
154
- this.$bus.$emit('update-media-duration')
155
-
156
- if (this.checkDuplicatedID().length > 1) {
157
- const errmsg = `Cet élément a le même ID <b>${this.id}</b>q'un autre media. Vous ne devez pas avoir de médias avec le même ID dans une page.`
158
-
159
- console.warn(
160
- `%c WARNING!>>> You cannot use the same ID (${this.id}) in your media elements for your page.`,
161
- 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
162
- )
163
-
164
- this.$bus.$emit('set-comp-status', 'AppCompAudioPlayer', 'ready')
165
- return this.hasErr.push(errmsg)
166
- }
167
-
168
- this.updateCurrentMediaElements(e).then(() => {
169
- this.isSet = true
170
- this.$bus.$emit('set-comp-status', 'AppCompAudioPlayer', 'ready')
171
- })
172
- },
173
- errorHandling(e) {
174
- this.hasSourceLoadingError = true
175
- }
176
- }
177
- }
178
- </script>
179
- <style scoped lang="scss">
180
- .audio-card {
181
- position: relative;
182
- border-radius: 4px;
183
- padding: 24px;
184
- min-width: 425px;
185
- max-width: 600px;
186
- box-shadow: 0px 3px 6px rgb(26 25 25 / 0.16);
187
-
188
- @media screen and (max-width: 1000px) {
189
- display: flex;
190
- flex-direction: column;
191
- }
192
- .audio-img {
193
- width: 128px;
194
- margin-right: 24px;
195
- }
196
- .audio-content {
197
- display: flex;
198
- flex-direction: row;
199
- align-items: center;
200
- padding-bottom: 24px;
201
-
202
- @media screen and (max-width: 1000px) {
203
- display: flex;
204
- flex-direction: column;
205
- }
206
- .audio-media {
207
- width: 100%;
208
- h5 {
209
- margin-bottom: 16px;
210
- }
211
- }
212
- }
213
- .audio-transcript {
214
- padding-top: 24px;
215
- }
216
- .audio-transcript-header {
217
- display: flex;
218
- justify-content: space-between;
219
- align-items: center;
220
- }
221
-
222
- .audio-transcript-button {
223
- height: 52px;
224
- width: 52px;
225
- display: flex;
226
- justify-content: center;
227
- align-items: center;
228
- svg {
229
- max-width: 18px;
230
- height: 10.25px;
231
- }
232
- &.rotate svg {
233
- transition: transform 0.5s;
234
- transform-origin: center;
235
- }
236
- &.rotate.click svg {
237
- transform: rotate(180deg);
238
- }
239
- }
240
- }
241
-
242
- .skeleton {
243
- &.audio {
244
- height: 100%;
245
- width: 100%;
246
- left: 0;
247
- top: 0;
248
- }
249
- }
250
-
251
- .debug {
252
- &:focus {
253
- border: 5px solid rgba(#fff, 0.05);
254
- }
255
- }
256
- </style>
1
+ <template>
2
+ <section
3
+ :id="'audio_' + id"
4
+ ref="$media-container"
5
+ class="__media-container"
6
+ aria-label="Audio"
7
+ >
8
+ <!--Integration error display-->
9
+ <app-base-error-display
10
+ v-if="hasErr.length"
11
+ :error-group="'component'"
12
+ :error-title="`ERREUR: COMPOSANT D'AUDIO`"
13
+ :errors-list="hasErr"
14
+ />
15
+
16
+ <div v-else class="audio-card">
17
+ <!--Waiting and loading error -- skeleton-->
18
+ <div
19
+ v-if="isLoading || hasSourceLoadingError"
20
+ class="skeleton audio"
21
+ :class="{ isloading: isLoading, error: hasSourceLoadingError }"
22
+ >
23
+ <p v-if="hasSourceLoadingError">
24
+ Une erreur s'est produite lors du chargement du média, veuillez
25
+ réessayer
26
+ </p>
27
+ </div>
28
+ <!--Audio content-->
29
+ <div v-show="!isLoading && !hasSourceLoadingError" class="audio-content">
30
+ <img
31
+ v-if="mPoster"
32
+ class="audio-img"
33
+ :src="mPoster"
34
+ aria-hidden="true"
35
+ />
36
+ <div class="audio-media">
37
+ <span>{{ mTitle }}</span>
38
+ <div class="audio-media-player">
39
+ <audio
40
+ :id="id"
41
+ ref="m-audio"
42
+ @loadedmetadata="updateMediaDataAudio($event.target)"
43
+ >
44
+ <source
45
+ v-for="(aSource, index) in mSources"
46
+ :key="index"
47
+ :src="aSource.src"
48
+ :type="aSource.type ? `audio/${aSource.type}` : 'audio/mp3'"
49
+ @error="errorHandling($event)"
50
+ />
51
+ </audio>
52
+ <app-comp-play-bar-next
53
+ v-if="$audElement"
54
+ :ref="`plyr_${id}`"
55
+ :media-to-play="$audElement"
56
+ />
57
+ </div>
58
+ </div>
59
+ </div>
60
+ <div class="audio-transcript">
61
+ <v-expansion-panels class="audio">
62
+ <v-expansion-panel>
63
+ <v-expansion-panel-title>
64
+ {{ $t('text.transcript') }}
65
+ </v-expansion-panel-title>
66
+ <v-expansion-panel-text>
67
+ <div v-html="mTranscript"></div>
68
+ </v-expansion-panel-text>
69
+ </v-expansion-panel>
70
+ </v-expansion-panels>
71
+ </div>
72
+ </div>
73
+ </section>
74
+ </template>
75
+ <script>
76
+ import { mapState, mapActions } from 'pinia'
77
+ import { useAppStore } from '../module/stores/appStore'
78
+ import { validateAudioData } from '../shared/validators'
79
+ import AppCompPlayBarNext from './AppCompPlayBarNext.vue'
80
+ import { useI18n } from 'vue-i18n'
81
+
82
+ export default {
83
+ components: { AppCompPlayBarNext },
84
+ props: {
85
+ audData: {
86
+ type: Object,
87
+ required: true
88
+ }
89
+ },
90
+ setup() {
91
+ const { t } = useI18n()
92
+ return { t }
93
+ },
94
+ data() {
95
+ return {
96
+ id: this.audData.id,
97
+ mTitle: this.audData.mTitle,
98
+ mSources: this.audData.mSources,
99
+ mTranscript: this.audData.mTranscript,
100
+ mPoster: this.audData.mPoster,
101
+ isSet: false,
102
+ hasSourceLoadingError: false,
103
+ hasErr: validateAudioData(this.audData)
104
+ }
105
+ },
106
+ computed: {
107
+ ...mapState(useAppStore, ['getCurrentBrowser', 'getCurrentPage']),
108
+ $audElement() {
109
+ if (!this.isSet) return null
110
+ return {
111
+ id: this.id,
112
+ mTranscript: null,
113
+ mType: 'audio',
114
+ mSubtitles: null,
115
+ mElement: this.$refs['m-audio']
116
+ }
117
+ },
118
+ //MediaElement
119
+ mediaElement() {
120
+ if (!this.$audElement) return null
121
+ const { mElement } = this.$audElement
122
+ let thisElement = null
123
+
124
+ if (!mElement) return null
125
+ thisElement = mElement
126
+
127
+ return thisElement
128
+ },
129
+ //Loading display
130
+ isLoading() {
131
+ if (!this.isSet && !this.hasSourceLoadingError) return true
132
+ else return false
133
+ }
134
+ },
135
+ mounted() {},
136
+ beforeUnmount() {},
137
+
138
+ methods: {
139
+ ...mapActions(useAppStore, ['updateCurrentMediaElements']),
140
+ /**
141
+ * @description search the DOM for medias with duplicated ID declaration in the page
142
+ * @return return Array of all DOM MediaElement with same id
143
+ */
144
+ checkDuplicatedID() {
145
+ const mediaList = document.querySelectorAll('.__media-container')
146
+ const duplicate = Array.from(mediaList).filter((media) =>
147
+ media.id.includes(this.id)
148
+ )
149
+ return duplicate
150
+ },
151
+ /**
152
+ * @description update the information for the mediaElement in the store
153
+ * @param {htmlElement} e
154
+ * @fires update-page to AppBaseModule.vue
155
+ */
156
+ updateMediaDataAudio(e) {
157
+ //dispatch loading status of for this component
158
+ this.$bus.$emit('set-comp-status', 'AppCompAudioPlayer', 'loading')
159
+ this.$bus.$emit('update-media-duration')
160
+
161
+ if (this.checkDuplicatedID().length > 1) {
162
+ const errmsg = `Cet élément a le même ID <b>${this.id}</b>q'un autre media. Vous ne devez pas avoir de médias avec le même ID dans une page.`
163
+
164
+ console.warn(
165
+ `%c WARNING!>>> You cannot use the same ID (${this.id}) in your media elements for your page.`,
166
+ 'background: orange; color: white; display: block; border-radius:5px; margin:5px;'
167
+ )
168
+
169
+ this.$bus.$emit('set-comp-status', 'AppCompAudioPlayer', 'ready')
170
+ return this.hasErr.push(errmsg)
171
+ }
172
+
173
+ this.updateCurrentMediaElements(e).then(() => {
174
+ this.isSet = true
175
+ this.$bus.$emit('set-comp-status', 'AppCompAudioPlayer', 'ready')
176
+ })
177
+ },
178
+ errorHandling(e) {
179
+ this.hasSourceLoadingError = true
180
+ }
181
+ }
182
+ }
183
+ </script>
184
+ <style scoped lang="scss">
185
+ .audio-card {
186
+ position: relative;
187
+ border-radius: 4px;
188
+ padding: 24px;
189
+ min-width: 425px;
190
+ max-width: 600px;
191
+ box-shadow: 0px 3px 6px rgb(26 25 25 / 0.16);
192
+
193
+ @media screen and (max-width: 1000px) {
194
+ display: flex;
195
+ flex-direction: column;
196
+ }
197
+ .audio-img {
198
+ width: 128px;
199
+ margin-right: 24px;
200
+ }
201
+ .audio-content {
202
+ display: flex;
203
+ flex-direction: row;
204
+ align-items: center;
205
+ padding-bottom: 24px;
206
+
207
+ @media screen and (max-width: 1000px) {
208
+ display: flex;
209
+ flex-direction: column;
210
+ }
211
+ .audio-media {
212
+ width: 100%;
213
+ h5 {
214
+ margin-bottom: 16px;
215
+ }
216
+ }
217
+ }
218
+ .audio-transcript {
219
+ padding-top: 24px;
220
+ }
221
+ .audio-transcript-header {
222
+ display: flex;
223
+ justify-content: space-between;
224
+ align-items: center;
225
+ }
226
+
227
+ .audio-transcript-button {
228
+ height: 52px;
229
+ width: 52px;
230
+ display: flex;
231
+ justify-content: center;
232
+ align-items: center;
233
+ svg {
234
+ max-width: 18px;
235
+ height: 10.25px;
236
+ }
237
+ &.rotate svg {
238
+ transition: transform 0.5s;
239
+ transform-origin: center;
240
+ }
241
+ &.rotate.click svg {
242
+ transform: rotate(180deg);
243
+ }
244
+ }
245
+ }
246
+
247
+ .skeleton {
248
+ &.audio {
249
+ height: 100%;
250
+ width: 100%;
251
+ left: 0;
252
+ top: 0;
253
+ }
254
+ }
255
+
256
+ .debug {
257
+ &:focus {
258
+ border: 5px solid rgba(#fff, 0.05);
259
+ }
260
+ }
261
+ </style>