@eui/ecl 22.0.0-alpha.52 → 22.0.0-alpha.53
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/assets/i18n-ecl/bg.json +6 -2
- package/assets/i18n-ecl/cs.json +6 -2
- package/assets/i18n-ecl/da.json +6 -2
- package/assets/i18n-ecl/de.json +6 -2
- package/assets/i18n-ecl/el.json +6 -2
- package/assets/i18n-ecl/en.json +6 -2
- package/assets/i18n-ecl/es.json +6 -2
- package/assets/i18n-ecl/et.json +6 -2
- package/assets/i18n-ecl/fi.json +6 -2
- package/assets/i18n-ecl/fr.json +6 -2
- package/assets/i18n-ecl/ga.json +6 -2
- package/assets/i18n-ecl/hr.json +6 -2
- package/assets/i18n-ecl/hu.json +6 -2
- package/assets/i18n-ecl/it.json +6 -2
- package/assets/i18n-ecl/lt.json +6 -2
- package/assets/i18n-ecl/lv.json +6 -2
- package/assets/i18n-ecl/mt.json +6 -2
- package/assets/i18n-ecl/nl.json +6 -2
- package/assets/i18n-ecl/pl.json +6 -2
- package/assets/i18n-ecl/pt.json +6 -2
- package/assets/i18n-ecl/ro.json +6 -2
- package/assets/i18n-ecl/sk.json +6 -2
- package/assets/i18n-ecl/sl.json +6 -2
- package/assets/i18n-ecl/sv.json +6 -2
- package/components/ecl-slider/package.json +4 -0
- package/docs/changelog.html +14 -0
- package/docs/components/EclAccordionSummaryComponent.html +1 -1
- package/docs/components/EclAddToCalendarComponent.html +1 -1
- package/docs/components/EclAnimatedNumbersComponent.html +1 -1
- package/docs/components/EclAnimatedNumbersItemComponent.html +1 -1
- package/docs/components/EclAppComponent.html +1 -1
- package/docs/components/EclBannerComponent.html +1 -1
- package/docs/components/EclBlockquoteComponent.html +1 -1
- package/docs/components/EclBreadcrumbComponent.html +1 -1
- package/docs/components/EclBreadcrumbSegmentComponent.html +1 -1
- package/docs/components/EclButtonComponent.html +1 -1
- package/docs/components/EclCardBodyComponent.html +1 -1
- package/docs/components/EclCardComponent.html +1 -1
- package/docs/components/EclCarouselComponent.html +182 -898
- package/docs/components/EclCarouselItemComponent.html +32 -1
- package/docs/components/EclCategoryFilterComponent.html +1 -1
- package/docs/components/EclCategoryFilterItemComponent.html +1 -1
- package/docs/components/EclCategoryFilterListComponent.html +1 -1
- package/docs/components/EclCheckboxHelpComponent.html +1 -1
- package/docs/components/EclCheckboxLabelComponent.html +1 -1
- package/docs/components/EclContentBlockComponent.html +1 -1
- package/docs/components/EclContentItemComponent.html +1 -1
- package/docs/components/EclDateBlockComponent.html +1 -1
- package/docs/components/EclDescriptionListDefinitionComponent.html +1 -1
- package/docs/components/EclExpandableComponent.html +1 -1
- package/docs/components/EclFactFiguresComponent.html +1 -1
- package/docs/components/EclFactFiguresItemComponent.html +1 -1
- package/docs/components/EclFactFiguresViewAllComponent.html +1 -1
- package/docs/components/EclFeaturedComponent.html +1 -1
- package/docs/components/EclFeaturedItemComponent.html +1 -1
- package/docs/components/EclFeaturedItemDescriptionComponent.html +1 -1
- package/docs/components/EclFileComponent.html +1 -1
- package/docs/components/EclFileItemComponent.html +1 -1
- package/docs/components/EclFileItemsComponent.html +1 -1
- package/docs/components/EclFileListsComponent.html +1 -1
- package/docs/components/EclFormGroupComponent.html +1 -1
- package/docs/components/EclFormLabelComponent.html +1 -1
- package/docs/components/EclGalleryComponent.html +1 -1
- package/docs/components/EclGalleryFooterComponent.html +1 -1
- package/docs/components/EclGalleryItemComponent.html +1 -1
- package/docs/components/EclHighlightBoxComponent.html +1 -1
- package/docs/components/EclHighlightedSearchComponent.html +1 -1
- package/docs/components/EclIconComponent.html +1 -10
- package/docs/components/EclIndicatorComponent.html +1 -1
- package/docs/components/EclInpageNavigationComponent.html +1 -1
- package/docs/components/EclInpageNavigationItemComponent.html +1 -1
- package/docs/components/EclLayoutWrapperComponent.html +1 -1
- package/docs/components/EclListIllustrationComponent.html +1 -1
- package/docs/components/EclListIllustrationItemComponent.html +1 -1
- package/docs/components/EclLoadingIndicatorComponent.html +1 -1
- package/docs/components/EclMediaContainerComponent.html +1 -1
- package/docs/components/EclMegaMenuComponent.html +1 -1
- package/docs/components/EclMegaMenuFeaturedComponent.html +1 -1
- package/docs/components/EclMegaMenuInfoComponent.html +1 -1
- package/docs/components/EclMegaMenuItemComponent.html +1 -1
- package/docs/components/EclMegaMenuSubitemComponent.html +1 -1
- package/docs/components/EclMenuComponent.html +1 -1
- package/docs/components/EclMenuItemComponent.html +1 -1
- package/docs/components/EclMenuMegaComponent.html +1 -1
- package/docs/components/EclMenuMegaItemComponent.html +1 -1
- package/docs/components/EclModalBodyComponent.html +1 -1
- package/docs/components/EclModalComponent.html +1 -1
- package/docs/components/EclModalFooterComponent.html +1 -1
- package/docs/components/EclModalHeaderComponent.html +1 -1
- package/docs/components/EclMultiselectComponent.html +1 -1
- package/docs/components/EclMultiselectDropdownComponent.html +1 -1
- package/docs/components/EclMultiselectInputComponent.html +1 -1
- package/docs/components/EclMultiselectOptgroupComponent.html +1 -1
- package/docs/components/EclMultiselectOptionComponent.html +1 -1
- package/docs/components/EclNavigationListComponent.html +1 -1
- package/docs/components/EclNavigationListItemComponent.html +1 -1
- package/docs/components/EclNewsTickerComponent.html +1 -1
- package/docs/components/EclNewsTickerItemComponent.html +1 -1
- package/docs/components/EclNotificationComponent.html +1 -1
- package/docs/components/EclPageHeaderComponent.html +1 -1
- package/docs/components/EclPageHeaderDescriptionContainerComponent.html +1 -1
- package/docs/components/EclPageHeaderExpandableComponent.html +1 -1
- package/docs/components/EclPageHeaderSectionComponent.html +1 -1
- package/docs/components/EclPageHeaderSectionInfoComponent.html +1 -1
- package/docs/components/EclPageSummaryComponent.html +1 -1
- package/docs/components/EclPaginationComponent.html +1 -1
- package/docs/components/EclPaginationItemComponent.html +1 -1
- package/docs/components/EclPopoverComponent.html +1 -1
- package/docs/components/EclQuizCardComponent.html +113 -44
- package/docs/components/EclQuizComponent.html +4 -9
- package/docs/components/EclRadioLabelComponent.html +1 -1
- package/docs/components/EclRangeBubbleComponent.html +1 -1
- package/docs/components/EclRangeValueComponent.html +1 -1
- package/docs/components/EclRatingFieldComponent.html +1 -1
- package/docs/components/EclSearchFormComponent.html +1 -1
- package/docs/components/EclSelectContainerComponent.html +1 -1
- package/docs/components/EclSiteFooterComponent.html +1 -1
- package/docs/components/EclSiteFooterCoownerComponent.html +1 -1
- package/docs/components/EclSiteFooterCoreComponent.html +1 -1
- package/docs/components/EclSiteFooterFeedbackComponent.html +1 -1
- package/docs/components/EclSiteFooterFixedContentEUComponent.html +1 -1
- package/docs/components/EclSiteFooterRowCommonComponent.html +1 -1
- package/docs/components/EclSiteHeaderActionComponent.html +1 -1
- package/docs/components/EclSiteHeaderBannerTopComponent.html +1 -1
- package/docs/components/EclSiteHeaderComponent.html +1 -1
- package/docs/components/EclSiteHeaderCustomActionComponent.html +1 -1
- package/docs/components/EclSiteHeaderEnvironmentComponent.html +1 -1
- package/docs/components/EclSiteHeaderLanguageComponent.html +1 -1
- package/docs/components/EclSiteHeaderLanguagePopoverComponent.html +1 -1
- package/docs/components/EclSiteHeaderLoginComponent.html +1 -1
- package/docs/components/EclSiteHeaderNotificationComponent.html +1 -1
- package/docs/components/EclSiteHeaderSearchComponent.html +1 -1
- package/docs/components/EclSliderPagerComponent.html +1159 -0
- package/docs/components/EclSloganTickerComponent.html +1 -1
- package/docs/components/EclSocialMediaFollowComponent.html +1 -1
- package/docs/components/EclSocialMediaFollowItemComponent.html +1 -1
- package/docs/components/EclSplashPageComponent.html +1 -1
- package/docs/components/EclSplashPageLanguageCategoryComponent.html +1 -1
- package/docs/components/EclSplashPageLanguageContainerComponent.html +1 -1
- package/docs/components/EclSplashPageLanguageLinkComponent.html +1 -1
- package/docs/components/EclSpotlightComponent.html +1 -1
- package/docs/components/EclSpotlightLinkComponent.html +1 -1
- package/docs/components/EclStickyContainerComponent.html +1 -1
- package/docs/components/EclStoryCardComponent.html +4 -4
- package/docs/components/EclStoryCardGridDetailsComponent.html +57 -2
- package/docs/components/EclStoryCardItemComponent.html +77 -2
- package/docs/components/EclTabComponent.html +1 -1
- package/docs/components/EclTabLabelComponent.html +1 -1
- package/docs/components/EclTableSortButtonComponent.html +1 -1
- package/docs/components/EclTabsComponent.html +1 -1
- package/docs/components/EclTagComponent.html +1 -1
- package/docs/components/EclTextMediaComponent.html +1 -1
- package/docs/components/EclTimelineComponent.html +1 -1
- package/docs/components/EclTimelineItemComponent.html +1 -1
- package/docs/components/EclTimelineItemTogglerComponent.html +1 -1
- package/docs/js/menu-wc.js +3 -0
- package/docs/js/search/search_index.js +2 -2
- package/docs/json/EclCarouselComponent.md +8 -4
- package/docs/json/EclCarouselItemComponent.md +1 -0
- package/docs/json/EclQuizCardComponent.md +6 -3
- package/docs/json/EclSliderPagerComponent.md +55 -0
- package/docs/json/EclStoryCardGridDetailsComponent.md +1 -0
- package/docs/json/EclStoryCardItemComponent.md +1 -0
- package/docs/json/documentation.json +1889 -565
- package/docs/llms.txt +69 -34
- package/docs/miscellaneous/variables.html +132 -20
- package/docs/overview.html +1 -1
- package/docs/properties.html +1 -1
- package/fesm2022/eui-ecl-components-ecl-carousel.mjs +405 -407
- package/fesm2022/eui-ecl-components-ecl-carousel.mjs.map +1 -1
- package/fesm2022/eui-ecl-components-ecl-menu.mjs +15 -15
- package/fesm2022/eui-ecl-components-ecl-menu.mjs.map +1 -1
- package/fesm2022/eui-ecl-components-ecl-quiz.mjs +93 -55
- package/fesm2022/eui-ecl-components-ecl-quiz.mjs.map +1 -1
- package/fesm2022/eui-ecl-components-ecl-slider.mjs +187 -0
- package/fesm2022/eui-ecl-components-ecl-slider.mjs.map +1 -0
- package/fesm2022/eui-ecl-components-ecl-story-card.mjs +96 -18
- package/fesm2022/eui-ecl-components-ecl-story-card.mjs.map +1 -1
- package/package.json +18 -12
- package/types/eui-ecl-components-ecl-carousel.d.ts +234 -202
- package/types/eui-ecl-components-ecl-carousel.d.ts.map +1 -1
- package/types/eui-ecl-components-ecl-menu.d.ts +0 -2
- package/types/eui-ecl-components-ecl-menu.d.ts.map +1 -1
- package/types/eui-ecl-components-ecl-quiz.d.ts +94 -57
- package/types/eui-ecl-components-ecl-quiz.d.ts.map +1 -1
- package/types/eui-ecl-components-ecl-slider.d.ts +118 -0
- package/types/eui-ecl-components-ecl-slider.d.ts.map +1 -0
- package/types/eui-ecl-components-ecl-story-card.d.ts +78 -48
- package/types/eui-ecl-components-ecl-story-card.d.ts.map +1 -1
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Directive, input, signal, output, computed, viewChild, ChangeDetectionStrategy, Component, booleanAttribute,
|
|
3
|
-
import
|
|
2
|
+
import { Directive, input, signal, output, computed, viewChild, ChangeDetectionStrategy, Component, booleanAttribute, inject, ChangeDetectorRef, ElementRef, ContentChildren, forwardRef } from '@angular/core';
|
|
3
|
+
import * as i1 from '@eui/ecl/components/ecl-slider';
|
|
4
|
+
import { EUI_ECL_SLIDER } from '@eui/ecl/components/ecl-slider';
|
|
4
5
|
import { ECLBaseDirective, EclRtlService } from '@eui/ecl/core';
|
|
5
|
-
import { TranslatePipe } from '@ngx-translate/core';
|
|
6
|
+
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
|
|
6
7
|
import { EmblaCarouselDirective } from 'embla-carousel-angular';
|
|
7
8
|
import { Subject, takeUntil } from 'rxjs';
|
|
8
9
|
import { outputToObservable } from '@angular/core/rxjs-interop';
|
|
10
|
+
import { EclIconComponent } from '@eui/ecl/components/ecl-icon';
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* Structural directive that marks an `<ol>` element as the ECL quiz option list.
|
|
@@ -59,19 +61,46 @@ class EclQuizCardComponent extends ECLBaseDirective {
|
|
|
59
61
|
...(ngDevMode ? [{ debugName: "answerTitle" }] : /* istanbul ignore next */ []));
|
|
60
62
|
/**
|
|
61
63
|
* Category label displayed in the card header (poll variant).
|
|
64
|
+
*
|
|
65
|
+
* @deprecated Since the port of ECL PR #4681. Upstream ECL removed the
|
|
66
|
+
* category label (it is no longer part of the markup or styled by
|
|
67
|
+
* `@eui/styles`); the back of the card now relies on the answer title and
|
|
68
|
+
* the success/error result icons. This input is kept only to preserve the
|
|
69
|
+
* public API and no longer renders anything. To be removed in v22.x.
|
|
62
70
|
*/
|
|
63
71
|
this.category = input('', /* @ts-ignore */
|
|
64
72
|
...(ngDevMode ? [{ debugName: "category" }] : /* istanbul ignore next */ []));
|
|
73
|
+
/**
|
|
74
|
+
* Image source for the card. When set together with a supported
|
|
75
|
+
* {@link imageDisplay} mode, a picture is rendered on the card.
|
|
76
|
+
*/
|
|
77
|
+
this.imageSrc = input('', /* @ts-ignore */
|
|
78
|
+
...(ngDevMode ? [{ debugName: "imageSrc" }] : /* istanbul ignore next */ []));
|
|
79
|
+
/**
|
|
80
|
+
* Alternative text for the card image.
|
|
81
|
+
*/
|
|
82
|
+
this.imageAlt = input('', /* @ts-ignore */
|
|
83
|
+
...(ngDevMode ? [{ debugName: "imageAlt" }] : /* istanbul ignore next */ []));
|
|
84
|
+
/**
|
|
85
|
+
* Controls where the image/illustration is displayed:
|
|
86
|
+
* - 'none': no image (default)
|
|
87
|
+
* - 'back': image only on the back; for poll variant an animated
|
|
88
|
+
* question-mark illustration is shown on the front
|
|
89
|
+
* - 'always': image on both front and back
|
|
90
|
+
*/
|
|
91
|
+
this.imageDisplay = input('none', /* @ts-ignore */
|
|
92
|
+
...(ngDevMode ? [{ debugName: "imageDisplay" }] : /* istanbul ignore next */ []));
|
|
65
93
|
/**
|
|
66
94
|
* Icon name for the card header.
|
|
67
|
-
* Defaults to 'sparkle' for reveal, 'question' for poll.
|
|
95
|
+
* Defaults to 'sparkle' for reveal, 'question-mark' for poll.
|
|
68
96
|
*/
|
|
69
97
|
this.icon = input('', /* @ts-ignore */
|
|
70
98
|
...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
71
99
|
/**
|
|
72
|
-
* Icon size for the card header.
|
|
100
|
+
* Icon size for the card header. When empty, a variant-based default is
|
|
101
|
+
* used ('xl' for poll, 'l' for reveal).
|
|
73
102
|
*/
|
|
74
|
-
this.iconSize = input('
|
|
103
|
+
this.iconSize = input('', /* @ts-ignore */
|
|
75
104
|
...(ngDevMode ? [{ debugName: "iconSize" }] : /* istanbul ignore next */ []));
|
|
76
105
|
/**
|
|
77
106
|
* The variant of the quiz, set by the parent EclQuizComponent.
|
|
@@ -89,12 +118,6 @@ class EclQuizCardComponent extends ECLBaseDirective {
|
|
|
89
118
|
*/
|
|
90
119
|
this.isFirstCard = signal(false, /* @ts-ignore */
|
|
91
120
|
...(ngDevMode ? [{ debugName: "isFirstCard" }] : /* istanbul ignore next */ []));
|
|
92
|
-
/**
|
|
93
|
-
* Whether all cards in the quiz have been flipped.
|
|
94
|
-
* Set by the parent EclQuizComponent to restore tabindex on category spans.
|
|
95
|
-
*/
|
|
96
|
-
this.allCardsFlipped = signal(false, /* @ts-ignore */
|
|
97
|
-
...(ngDevMode ? [{ debugName: "allCardsFlipped" }] : /* istanbul ignore next */ []));
|
|
98
121
|
/** Whether the card is currently flipped (showing back). */
|
|
99
122
|
this.isFlipped = signal(false, /* @ts-ignore */
|
|
100
123
|
...(ngDevMode ? [{ debugName: "isFlipped" }] : /* istanbul ignore next */ []));
|
|
@@ -106,9 +129,23 @@ class EclQuizCardComponent extends ECLBaseDirective {
|
|
|
106
129
|
...(ngDevMode ? [{ debugName: "questionId" }] : /* istanbul ignore next */ []));
|
|
107
130
|
this.answerId = computed(() => `${this.id()}-answer`, /* @ts-ignore */
|
|
108
131
|
...(ngDevMode ? [{ debugName: "answerId" }] : /* istanbul ignore next */ []));
|
|
109
|
-
/** Whether
|
|
110
|
-
this.
|
|
111
|
-
...(ngDevMode ? [{ debugName: "
|
|
132
|
+
/** Whether a picture is available to render. */
|
|
133
|
+
this.hasPicture = computed(() => !!this.imageSrc(), /* @ts-ignore */
|
|
134
|
+
...(ngDevMode ? [{ debugName: "hasPicture" }] : /* istanbul ignore next */ []));
|
|
135
|
+
/** Whether the picture should be rendered on the front face. */
|
|
136
|
+
this.showFrontPicture = computed(() => this.hasPicture() && this.imageDisplay() === 'always', /* @ts-ignore */
|
|
137
|
+
...(ngDevMode ? [{ debugName: "showFrontPicture" }] : /* istanbul ignore next */ []));
|
|
138
|
+
/** Whether the picture should be rendered on the back face. */
|
|
139
|
+
this.showBackPicture = computed(() => this.hasPicture() && (this.imageDisplay() === 'always' || this.imageDisplay() === 'back'), /* @ts-ignore */
|
|
140
|
+
...(ngDevMode ? [{ debugName: "showBackPicture" }] : /* istanbul ignore next */ []));
|
|
141
|
+
/**
|
|
142
|
+
* Whether the animated question-mark illustration should be shown on the
|
|
143
|
+
* front of a poll card (poll variant with 'back' image display).
|
|
144
|
+
*/
|
|
145
|
+
this.showIllustration = computed(() => this.variant() === 'poll' && this.imageDisplay() === 'back', /* @ts-ignore */
|
|
146
|
+
...(ngDevMode ? [{ debugName: "showIllustration" }] : /* istanbul ignore next */ []));
|
|
147
|
+
/** Indices used to render the illustration's repeated question-mark shapes. */
|
|
148
|
+
this.illustrationMarks = Array.from({ length: 18 }, (_unused, i) => i + 1);
|
|
112
149
|
/** Index of the selected option (poll variant). */
|
|
113
150
|
this.selectedOptionIndex = signal(null, /* @ts-ignore */
|
|
114
151
|
...(ngDevMode ? [{ debugName: "selectedOptionIndex" }] : /* istanbul ignore next */ []));
|
|
@@ -126,10 +163,8 @@ class EclQuizCardComponent extends ECLBaseDirective {
|
|
|
126
163
|
...(ngDevMode ? [{ debugName: "answerElementRef" }] : /* istanbul ignore next */ []));
|
|
127
164
|
this.contentElementRef = viewChild('contentElement', /* @ts-ignore */
|
|
128
165
|
...(ngDevMode ? [{ debugName: "contentElementRef" }] : /* istanbul ignore next */ []));
|
|
129
|
-
this.
|
|
130
|
-
...(ngDevMode ? [{ debugName: "
|
|
131
|
-
this.categoryErrorRef = viewChild('categoryError', /* @ts-ignore */
|
|
132
|
-
...(ngDevMode ? [{ debugName: "categoryErrorRef" }] : /* istanbul ignore next */ []));
|
|
166
|
+
this.answerTitleRef = viewChild('answerTitleEl', /* @ts-ignore */
|
|
167
|
+
...(ngDevMode ? [{ debugName: "answerTitleRef" }] : /* istanbul ignore next */ []));
|
|
133
168
|
this.cssClasses = computed(() => [
|
|
134
169
|
super.getCssClasses('ecl-quiz-card'),
|
|
135
170
|
this.isFlipped() ? 'ecl-quiz-card__flipped' : '',
|
|
@@ -182,11 +217,11 @@ class EclQuizCardComponent extends ECLBaseDirective {
|
|
|
182
217
|
if (this.icon()) {
|
|
183
218
|
return this.icon();
|
|
184
219
|
}
|
|
185
|
-
return this.variant() === 'poll' ? 'question' : 'sparkle';
|
|
220
|
+
return this.variant() === 'poll' ? 'question-mark' : 'sparkle';
|
|
186
221
|
}
|
|
187
222
|
/** Get the resolved icon size. */
|
|
188
223
|
getIconSize() {
|
|
189
|
-
return this.iconSize() || (this.variant() === 'poll' ? '
|
|
224
|
+
return this.iconSize() || (this.variant() === 'poll' ? 'xl' : 'l');
|
|
190
225
|
}
|
|
191
226
|
/**
|
|
192
227
|
* Handle click on the card itself (reveal variant).
|
|
@@ -216,7 +251,7 @@ class EclQuizCardComponent extends ECLBaseDirective {
|
|
|
216
251
|
this.selectedOptionIndex.set(optionIndex);
|
|
217
252
|
this.isCorrect.set(optionsList[optionIndex]?.match ?? false);
|
|
218
253
|
this.flipCard();
|
|
219
|
-
this.
|
|
254
|
+
this.focusAnswerTitleAfterFlip();
|
|
220
255
|
}
|
|
221
256
|
/**
|
|
222
257
|
* Handle keyboard on option (poll variant).
|
|
@@ -227,12 +262,6 @@ class EclQuizCardComponent extends ECLBaseDirective {
|
|
|
227
262
|
this.onOptionClick(optionIndex);
|
|
228
263
|
}
|
|
229
264
|
}
|
|
230
|
-
/**
|
|
231
|
-
* Handle blur on the category span. Sets tabindex to -1 so it leaves the tab order.
|
|
232
|
-
*/
|
|
233
|
-
onCategoryBlur() {
|
|
234
|
-
this.categoryHasFocus.set(false);
|
|
235
|
-
}
|
|
236
265
|
/**
|
|
237
266
|
* Flip the card between front and back.
|
|
238
267
|
*/
|
|
@@ -246,20 +275,19 @@ class EclQuizCardComponent extends ECLBaseDirective {
|
|
|
246
275
|
this.cardFlip.emit(event);
|
|
247
276
|
}
|
|
248
277
|
/**
|
|
249
|
-
* Focus the
|
|
278
|
+
* Focus the answer title after the card flips in poll variant.
|
|
250
279
|
* Uses requestAnimationFrame to ensure the DOM has updated (inert removed from back face).
|
|
251
280
|
*/
|
|
252
|
-
|
|
253
|
-
this.categoryHasFocus.set(true);
|
|
281
|
+
focusAnswerTitleAfterFlip() {
|
|
254
282
|
requestAnimationFrame(() => {
|
|
255
|
-
const ref = this.
|
|
283
|
+
const ref = this.answerTitleRef();
|
|
256
284
|
if (ref?.nativeElement) {
|
|
257
285
|
ref.nativeElement.focus();
|
|
258
286
|
}
|
|
259
287
|
});
|
|
260
288
|
}
|
|
261
289
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclQuizCardComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
262
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: EclQuizCardComponent, isStandalone: true, selector: "li[eclQuizCard]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, question: { classPropertyName: "question", publicName: "question", isSignal: true, isRequired: false, transformFunction: null }, answer: { classPropertyName: "answer", publicName: "answer", isSignal: true, isRequired: false, transformFunction: null }, answerTitle: { classPropertyName: "answerTitle", publicName: "answerTitle", isSignal: true, isRequired: false, transformFunction: null }, category: { classPropertyName: "category", publicName: "category", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, iconSize: { classPropertyName: "iconSize", publicName: "iconSize", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cardFlip: "cardFlip" }, host: { listeners: { "click": "onClick()", "keydown": "onKeydown($event)" }, properties: { "attr.id": "id()", "attr.aria-labelledby": "questionId()", "class": "cssClasses()", "attr.tabindex": "tabIndex()", "style.transform": "styleTransform" } }, viewQueries: [{ propertyName: "frontElementRef", first: true, predicate: ["frontElement"], descendants: true, isSignal: true }, { propertyName: "backElementRef", first: true, predicate: ["backElement"], descendants: true, isSignal: true }, { propertyName: "questionElementRef", first: true, predicate: ["questionElement"], descendants: true, isSignal: true }, { propertyName: "answerElementRef", first: true, predicate: ["answerElement"], descendants: true, isSignal: true }, { propertyName: "contentElementRef", first: true, predicate: ["contentElement"], descendants: true, isSignal: true }, { propertyName: "categorySuccessRef", first: true, predicate: ["categorySuccess"], descendants: true, isSignal: true }, { propertyName: "categoryErrorRef", first: true, predicate: ["categoryError"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<article class=\"ecl-quiz-card__content\" #contentElement>\n <!-- Front face -->\n <div class=\"ecl-quiz-card__front\" #frontElement [hidden]=\"isFlipped()\" [inert]=\"isFlipped()\">\n <div class=\"ecl-quiz-card__header\">\n <div class=\"ecl-quiz-card__icon\">\n <ecl-icon [icon]=\"getIconName()\" [size]=\"getIconSize()\" iconSet=\"phosphor\">\n </ecl-icon>\n </div>\n @if (category()) {\n <span class=\"ecl-quiz-card__category\">{{ category() }}</span>\n }\n </div>\n\n @if (variant() === 'reveal') {\n <div class=\"ecl-quiz-card__question\" [id]=\"questionId()\" #questionElement>{{ question() }}</div>\n <!-- Reveal variant: flip label -->\n <div class=\"ecl-quiz-card__flip\">\n {{ 'ecl.quiz.REVEAL-ANSWER' | translate }}\n <ecl-icon iconSet=\"phosphor\" icon=\"arrow-clockwise\" size=\"m\"></ecl-icon>\n </div>\n } @else {\n <!-- Poll variant: options -->\n <fieldset [attr.aria-describedby]=\"isFirstCard() ? id() + '-skip-instructions' : null\">\n <legend class=\"ecl-quiz-card__question\" [id]=\"questionId()\" #questionElement>{{ question() }}</legend>\n <ol class=\"ecl-quiz-card__options\" type=\"A\">\n @for (option of options(); let i = $index; track i) {\n <li class=\"ecl-quiz-card__option\" [attr.data-match]=\"option.match\" (mouseup)=\"onOptionClick(i)\">\n <label class=\"ecl-quiz-card__label\">\n <input type=\"radio\" [name]=\"id() + '-options'\" [attr.data-match]=\"option.match\"\n [attr.tabindex]=\"isFlipped() ? -1 : null\" (keydown)=\"onOptionKeydown($event, i)\">\n {{ option.text }}</label>\n @if (i === 0 && isFirstCard()) {\n <span class=\"ecl-quiz__skip\" [id]=\"id() + '-skip-instructions'\">{{ 'ecl.quiz.SKIP-INSTRUCTIONS' |\n translate }}</span>\n }\n </li>\n }\n </ol>\n </fieldset>\n }\n </div>\n\n <!-- Back face -->\n <div class=\"ecl-quiz-card__back\" #backElement [hidden]=\"!isFlipped()\" [inert]=\"!isFlipped()\" style\n [class.ecl-quiz-card--correct]=\"variant() === 'poll' && isCorrect() === true\">\n <div class=\"ecl-quiz-card__header\">\n @if (variant() === 'reveal') {\n <div class=\"ecl-quiz-card__icon\">\n <ecl-icon [icon]=\"getIconName()\" [size]=\"getIconSize()\" iconSet=\"phosphor\">\n </ecl-icon>\n </div>\n } @else {\n <!-- Poll variant: success/error icons and category labels -->\n <div class=\"ecl-quiz-card__icon\">\n <ecl-icon icon=\"check-circle\" iconSet=\"phosphor\" size=\"2xl\" class=\"ecl-quiz-card__icon--success\">\n </ecl-icon>\n <ecl-icon icon=\"x-circle\" size=\"2xl\" iconSet=\"phosphor\" class=\"ecl-quiz-card__icon--error\">\n </ecl-icon>\n </div>\n <span #categorySuccess class=\"ecl-quiz-card__category ecl-quiz-card__category--success\"\n [attr.tabindex]=\"(allCardsFlipped() || categoryHasFocus()) && isCorrect() === true ? 0 : -1\"\n (blur)=\"onCategoryBlur()\">{{\n 'ecl.quiz.CORRECT' | translate }}</span>\n <span #categoryError class=\"ecl-quiz-card__category ecl-quiz-card__category--error\"\n [attr.tabindex]=\"(allCardsFlipped() || categoryHasFocus()) && isCorrect() === false ? 0 : -1\"\n (blur)=\"onCategoryBlur()\">{{\n 'ecl.quiz.INCORRECT' | translate }}</span>\n <span class=\"ecl-quiz-card__sr-status\" role=\"status\" aria-atomic=\"true\">{{ isFlipped() ? (isCorrect() ===\n true ? ('ecl.quiz.CORRECT' | translate) : ('ecl.quiz.INCORRECT' | translate)) : '' }}</span>\n }\n </div>\n\n <div class=\"ecl-quiz-card__answer\" [id]=\"answerId()\" #answerElement>\n @if (answerTitle()) {\n <div class=\"ecl-quiz-card__answer-title\">{{ answerTitle() }}</div>\n }\n {{ answer() }}\n </div>\n\n @if (variant() === 'reveal') {\n <!-- Reveal variant: go back label -->\n <div class=\"ecl-quiz-card__flip\">\n {{ 'ecl.quiz.FLIP-BACK' | translate }}\n <ecl-icon icon=\"arrow-clockwise\" size=\"m\" iconSet=\"phosphor\"></ecl-icon>\n </div>\n } @else {\n <!-- Poll variant: options list on back (showing selected state) -->\n <ol class=\"ecl-quiz-card__options\" type=\"A\">\n @for (option of options(); let i = $index; track i) {\n <li class=\"ecl-quiz-card__option\" [class.ecl-quiz-card__option--selected]=\"selectedOptionIndex() === i\"\n [attr.data-match]=\"option.match\">\n @if (selectedOptionIndex() === i) {\n @if (!option.match) {\n <span class=\"ecl-quiz-card__option-assistive-label\">{{ 'ecl.quiz.YOUR-INCORRECT-ANSWER' | translate }}</span>\n }\n @if (option.match) {\n <span class=\"ecl-quiz-card__option-assistive-label\">{{ 'ecl.quiz.YOUR-CORRECT-ANSWER' | translate }}</span>\n }\n } @else if (option.match) {\n <span class=\"ecl-quiz-card__option-assistive-label\">{{ 'ecl.quiz.CORRECT-ANSWER' | translate }}</span>\n }\n {{ option.text }}\n @if (selectedOptionIndex() === i && !option.match) {\n <span class=\"ecl-quiz-card__option-icon\">\n <ecl-icon icon=\"x-circle\" size=\"s\" iconSet=\"phosphor\"\n class=\"ecl-quiz-card__option-icon--error\"></ecl-icon>\n </span>\n }\n @if (option.match) {\n <span class=\"ecl-quiz-card__option-icon\">\n <ecl-icon icon=\"check-circle\" size=\"s\" iconSet=\"phosphor\"\n class=\"ecl-quiz-card__option-icon--success\"></ecl-icon>\n </span>\n }\n </li>\n }\n </ol>\n }\n </div>\n</article>", dependencies: [{ kind: "component", type: EclIconComponent, selector: "ecl-icon", inputs: ["iconSet", "icon", "size", "color", "transform", "ariaLabelledby", "role", "title", "ariaHidden", "focusable", "isFlipHorizontal"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
290
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: EclQuizCardComponent, isStandalone: true, selector: "li[eclQuizCard]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, question: { classPropertyName: "question", publicName: "question", isSignal: true, isRequired: false, transformFunction: null }, answer: { classPropertyName: "answer", publicName: "answer", isSignal: true, isRequired: false, transformFunction: null }, answerTitle: { classPropertyName: "answerTitle", publicName: "answerTitle", isSignal: true, isRequired: false, transformFunction: null }, category: { classPropertyName: "category", publicName: "category", isSignal: true, isRequired: false, transformFunction: null }, imageSrc: { classPropertyName: "imageSrc", publicName: "imageSrc", isSignal: true, isRequired: false, transformFunction: null }, imageAlt: { classPropertyName: "imageAlt", publicName: "imageAlt", isSignal: true, isRequired: false, transformFunction: null }, imageDisplay: { classPropertyName: "imageDisplay", publicName: "imageDisplay", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, iconSize: { classPropertyName: "iconSize", publicName: "iconSize", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cardFlip: "cardFlip" }, host: { listeners: { "click": "onClick()", "keydown": "onKeydown($event)" }, properties: { "attr.id": "id()", "attr.aria-labelledby": "questionId()", "class": "cssClasses()", "attr.tabindex": "tabIndex()", "style.transform": "styleTransform" } }, viewQueries: [{ propertyName: "frontElementRef", first: true, predicate: ["frontElement"], descendants: true, isSignal: true }, { propertyName: "backElementRef", first: true, predicate: ["backElement"], descendants: true, isSignal: true }, { propertyName: "questionElementRef", first: true, predicate: ["questionElement"], descendants: true, isSignal: true }, { propertyName: "answerElementRef", first: true, predicate: ["answerElement"], descendants: true, isSignal: true }, { propertyName: "contentElementRef", first: true, predicate: ["contentElement"], descendants: true, isSignal: true }, { propertyName: "answerTitleRef", first: true, predicate: ["answerTitleEl"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<article class=\"ecl-quiz-card__content\" #contentElement>\n <!-- Front face -->\n <div class=\"ecl-quiz-card__front\" #frontElement [hidden]=\"isFlipped()\" [inert]=\"isFlipped()\">\n @if (showFrontPicture()) {\n <picture class=\"ecl-picture ecl-quiz-card__picture\">\n <img class=\"ecl-quiz-card__image\" [src]=\"imageSrc()\" [alt]=\"imageAlt()\">\n </picture>\n } @else if (showIllustration()) {\n <div class=\"ecl-quiz-card__illustration-container\">\n <svg viewBox=\"0 0 500 140\" preserveAspectRatio=\"none\" aria-hidden=\"true\"\n class=\"ecl-quiz-card__illustration\">\n <defs>\n <g id=\"question-mark\">\n <path\n d=\"M0 0c0 4.343-3.728 7.939-8.531 8.464V9.75a1.22 1.22 0 0 1-2.438 0V7.313a1.22 1.22 0 0 1 1.219-1.22c4.033 0 7.312-2.732 7.312-6.093s-3.279-6.094-7.312-6.094-7.312 2.733-7.312 6.094a1.22 1.22 0 0 1-2.438 0c0-4.704 4.374-8.531 9.75-8.531S0-4.704 0 0Zm-9.75 14.625a2.438 2.438 0 1 0 0 4.875 2.438 2.438 0 0 0 0-4.875Z\" />\n </g>\n </defs>\n @for (mark of illustrationMarks; track mark) {\n <use href=\"#question-mark\" [attr.class]=\"'qm qm-' + mark\" />\n }\n </svg>\n </div>\n }\n <div class=\"ecl-quiz-card__padded\">\n <div class=\"ecl-quiz-card__header\">\n @if (!showIllustration()) {\n <div class=\"ecl-quiz-card__icon\">\n <ecl-icon [icon]=\"getIconName()\" [size]=\"getIconSize()\" iconSet=\"phosphor\">\n </ecl-icon>\n </div>\n }\n </div>\n\n @if (variant() === 'reveal') {\n <div class=\"ecl-quiz-card__question\" [id]=\"questionId()\" #questionElement>{{ question() }}</div>\n <!-- Reveal variant: flip label -->\n <div class=\"ecl-quiz-card__flip\">\n {{ 'ecl.quiz.REVEAL-ANSWER' | translate }}\n <ecl-icon iconSet=\"phosphor\" icon=\"arrow-clockwise\" size=\"m\"></ecl-icon>\n </div>\n } @else {\n <!-- Poll variant: options -->\n <fieldset [attr.aria-describedby]=\"isFirstCard() ? id() + '-skip-instructions' : null\">\n <legend class=\"ecl-quiz-card__question\" [id]=\"questionId()\" #questionElement>{{ question() }}</legend>\n <ol class=\"ecl-quiz-card__options\" type=\"A\">\n @for (option of options(); let i = $index; track i) {\n <li class=\"ecl-quiz-card__option\" [attr.data-match]=\"option.match\" (mouseup)=\"onOptionClick(i)\">\n <label class=\"ecl-quiz-card__label\">\n <input type=\"radio\" [name]=\"id() + '-options'\" [attr.data-match]=\"option.match\"\n [attr.tabindex]=\"isFlipped() ? -1 : null\" (keydown)=\"onOptionKeydown($event, i)\">\n {{ option.text }}</label>\n @if (i === 0 && isFirstCard()) {\n <span class=\"ecl-quiz__skip\" [id]=\"id() + '-skip-instructions'\">{{ 'ecl.quiz.SKIP-INSTRUCTIONS' |\n translate }}</span>\n }\n </li>\n }\n </ol>\n </fieldset>\n }\n </div>\n </div>\n\n <!-- Back face -->\n <div class=\"ecl-quiz-card__back\" #backElement [hidden]=\"!isFlipped()\" [inert]=\"!isFlipped()\" style\n [class.ecl-quiz-card--correct]=\"variant() === 'poll' && isCorrect() === true\">\n @if (showBackPicture()) {\n <picture class=\"ecl-picture ecl-quiz-card__picture\">\n <img class=\"ecl-quiz-card__image\" [src]=\"imageSrc()\" [alt]=\"imageAlt()\">\n </picture>\n }\n <div class=\"ecl-quiz-card__padded\">\n <div class=\"ecl-quiz-card__header\">\n @if (variant() === 'reveal') {\n <div class=\"ecl-quiz-card__icon\">\n <ecl-icon [icon]=\"getIconName()\" [size]=\"getIconSize()\" iconSet=\"phosphor\">\n </ecl-icon>\n </div>\n } @else {\n <!-- Poll variant: success/error icons -->\n <div class=\"ecl-quiz-card__icon\">\n <ecl-icon icon=\"check-circle\" iconSet=\"phosphor\" size=\"xl\" class=\"ecl-quiz-card__icon--success\">\n </ecl-icon>\n <ecl-icon icon=\"x-circle\" size=\"xl\" iconSet=\"phosphor\" class=\"ecl-quiz-card__icon--error\">\n </ecl-icon>\n </div>\n }\n </div>\n\n <div class=\"ecl-quiz-card__answer\" [id]=\"answerId()\" #answerElement>\n <div class=\"ecl-quiz-card__answer-content\">\n @if (answerTitle()) {\n <div class=\"ecl-quiz-card__answer-title\" tabindex=\"0\" #answerTitleEl>{{ answerTitle() }}</div>\n }\n {{ answer() }}\n </div>\n </div>\n\n @if (variant() === 'reveal') {\n <!-- Reveal variant: go back label -->\n <div class=\"ecl-quiz-card__flip\">\n {{ 'ecl.quiz.FLIP-BACK' | translate }}\n <ecl-icon icon=\"arrow-clockwise\" size=\"m\" iconSet=\"phosphor\"></ecl-icon>\n </div>\n } @else {\n <!-- Poll variant: options list on back (showing selected state) -->\n <ol class=\"ecl-quiz-card__options\" type=\"A\">\n @for (option of options(); let i = $index; track i) {\n <li class=\"ecl-quiz-card__option\" [class.ecl-quiz-card__option--selected]=\"selectedOptionIndex() === i\"\n [attr.data-match]=\"option.match\">\n @if (selectedOptionIndex() === i) {\n @if (!option.match) {\n <span class=\"ecl-quiz-card__option-assistive-label\">{{ 'ecl.quiz.YOUR-INCORRECT-ANSWER' | translate }}</span>\n }\n @if (option.match) {\n <span class=\"ecl-quiz-card__option-assistive-label\">{{ 'ecl.quiz.YOUR-CORRECT-ANSWER' | translate }}</span>\n }\n } @else if (option.match) {\n <span class=\"ecl-quiz-card__option-assistive-label\">{{ 'ecl.quiz.CORRECT-ANSWER' | translate }}</span>\n }\n {{ option.text }}\n @if (selectedOptionIndex() === i && !option.match) {\n <span class=\"ecl-quiz-card__option-icon\">\n <ecl-icon icon=\"x-circle\" size=\"s\" iconSet=\"phosphor\"\n class=\"ecl-quiz-card__option-icon--error\"></ecl-icon>\n </span>\n }\n @if (option.match) {\n <span class=\"ecl-quiz-card__option-icon\">\n <ecl-icon icon=\"check-circle\" size=\"s\" iconSet=\"phosphor\"\n class=\"ecl-quiz-card__option-icon--success\"></ecl-icon>\n </span>\n }\n </li>\n }\n </ol>\n }\n </div>\n </div>\n</article>\n", dependencies: [{ kind: "component", type: EclIconComponent, selector: "ecl-icon", inputs: ["iconSet", "icon", "size", "color", "transform", "ariaLabelledby", "role", "title", "ariaHidden", "focusable", "isFlipHorizontal"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
263
291
|
}
|
|
264
292
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclQuizCardComponent, decorators: [{
|
|
265
293
|
type: Component,
|
|
@@ -271,8 +299,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImpor
|
|
|
271
299
|
'[style.transform]': 'styleTransform',
|
|
272
300
|
'(click)': 'onClick()',
|
|
273
301
|
'(keydown)': 'onKeydown($event)',
|
|
274
|
-
}, imports: [EclIconComponent, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<article class=\"ecl-quiz-card__content\" #contentElement>\n <!-- Front face -->\n <div class=\"ecl-quiz-card__front\" #frontElement [hidden]=\"isFlipped()\" [inert]=\"isFlipped()\">\n <
|
|
275
|
-
}], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], question: [{ type: i0.Input, args: [{ isSignal: true, alias: "question", required: false }] }], answer: [{ type: i0.Input, args: [{ isSignal: true, alias: "answer", required: false }] }], answerTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "answerTitle", required: false }] }], category: [{ type: i0.Input, args: [{ isSignal: true, alias: "category", required: false }] }],
|
|
302
|
+
}, imports: [EclIconComponent, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<article class=\"ecl-quiz-card__content\" #contentElement>\n <!-- Front face -->\n <div class=\"ecl-quiz-card__front\" #frontElement [hidden]=\"isFlipped()\" [inert]=\"isFlipped()\">\n @if (showFrontPicture()) {\n <picture class=\"ecl-picture ecl-quiz-card__picture\">\n <img class=\"ecl-quiz-card__image\" [src]=\"imageSrc()\" [alt]=\"imageAlt()\">\n </picture>\n } @else if (showIllustration()) {\n <div class=\"ecl-quiz-card__illustration-container\">\n <svg viewBox=\"0 0 500 140\" preserveAspectRatio=\"none\" aria-hidden=\"true\"\n class=\"ecl-quiz-card__illustration\">\n <defs>\n <g id=\"question-mark\">\n <path\n d=\"M0 0c0 4.343-3.728 7.939-8.531 8.464V9.75a1.22 1.22 0 0 1-2.438 0V7.313a1.22 1.22 0 0 1 1.219-1.22c4.033 0 7.312-2.732 7.312-6.093s-3.279-6.094-7.312-6.094-7.312 2.733-7.312 6.094a1.22 1.22 0 0 1-2.438 0c0-4.704 4.374-8.531 9.75-8.531S0-4.704 0 0Zm-9.75 14.625a2.438 2.438 0 1 0 0 4.875 2.438 2.438 0 0 0 0-4.875Z\" />\n </g>\n </defs>\n @for (mark of illustrationMarks; track mark) {\n <use href=\"#question-mark\" [attr.class]=\"'qm qm-' + mark\" />\n }\n </svg>\n </div>\n }\n <div class=\"ecl-quiz-card__padded\">\n <div class=\"ecl-quiz-card__header\">\n @if (!showIllustration()) {\n <div class=\"ecl-quiz-card__icon\">\n <ecl-icon [icon]=\"getIconName()\" [size]=\"getIconSize()\" iconSet=\"phosphor\">\n </ecl-icon>\n </div>\n }\n </div>\n\n @if (variant() === 'reveal') {\n <div class=\"ecl-quiz-card__question\" [id]=\"questionId()\" #questionElement>{{ question() }}</div>\n <!-- Reveal variant: flip label -->\n <div class=\"ecl-quiz-card__flip\">\n {{ 'ecl.quiz.REVEAL-ANSWER' | translate }}\n <ecl-icon iconSet=\"phosphor\" icon=\"arrow-clockwise\" size=\"m\"></ecl-icon>\n </div>\n } @else {\n <!-- Poll variant: options -->\n <fieldset [attr.aria-describedby]=\"isFirstCard() ? id() + '-skip-instructions' : null\">\n <legend class=\"ecl-quiz-card__question\" [id]=\"questionId()\" #questionElement>{{ question() }}</legend>\n <ol class=\"ecl-quiz-card__options\" type=\"A\">\n @for (option of options(); let i = $index; track i) {\n <li class=\"ecl-quiz-card__option\" [attr.data-match]=\"option.match\" (mouseup)=\"onOptionClick(i)\">\n <label class=\"ecl-quiz-card__label\">\n <input type=\"radio\" [name]=\"id() + '-options'\" [attr.data-match]=\"option.match\"\n [attr.tabindex]=\"isFlipped() ? -1 : null\" (keydown)=\"onOptionKeydown($event, i)\">\n {{ option.text }}</label>\n @if (i === 0 && isFirstCard()) {\n <span class=\"ecl-quiz__skip\" [id]=\"id() + '-skip-instructions'\">{{ 'ecl.quiz.SKIP-INSTRUCTIONS' |\n translate }}</span>\n }\n </li>\n }\n </ol>\n </fieldset>\n }\n </div>\n </div>\n\n <!-- Back face -->\n <div class=\"ecl-quiz-card__back\" #backElement [hidden]=\"!isFlipped()\" [inert]=\"!isFlipped()\" style\n [class.ecl-quiz-card--correct]=\"variant() === 'poll' && isCorrect() === true\">\n @if (showBackPicture()) {\n <picture class=\"ecl-picture ecl-quiz-card__picture\">\n <img class=\"ecl-quiz-card__image\" [src]=\"imageSrc()\" [alt]=\"imageAlt()\">\n </picture>\n }\n <div class=\"ecl-quiz-card__padded\">\n <div class=\"ecl-quiz-card__header\">\n @if (variant() === 'reveal') {\n <div class=\"ecl-quiz-card__icon\">\n <ecl-icon [icon]=\"getIconName()\" [size]=\"getIconSize()\" iconSet=\"phosphor\">\n </ecl-icon>\n </div>\n } @else {\n <!-- Poll variant: success/error icons -->\n <div class=\"ecl-quiz-card__icon\">\n <ecl-icon icon=\"check-circle\" iconSet=\"phosphor\" size=\"xl\" class=\"ecl-quiz-card__icon--success\">\n </ecl-icon>\n <ecl-icon icon=\"x-circle\" size=\"xl\" iconSet=\"phosphor\" class=\"ecl-quiz-card__icon--error\">\n </ecl-icon>\n </div>\n }\n </div>\n\n <div class=\"ecl-quiz-card__answer\" [id]=\"answerId()\" #answerElement>\n <div class=\"ecl-quiz-card__answer-content\">\n @if (answerTitle()) {\n <div class=\"ecl-quiz-card__answer-title\" tabindex=\"0\" #answerTitleEl>{{ answerTitle() }}</div>\n }\n {{ answer() }}\n </div>\n </div>\n\n @if (variant() === 'reveal') {\n <!-- Reveal variant: go back label -->\n <div class=\"ecl-quiz-card__flip\">\n {{ 'ecl.quiz.FLIP-BACK' | translate }}\n <ecl-icon icon=\"arrow-clockwise\" size=\"m\" iconSet=\"phosphor\"></ecl-icon>\n </div>\n } @else {\n <!-- Poll variant: options list on back (showing selected state) -->\n <ol class=\"ecl-quiz-card__options\" type=\"A\">\n @for (option of options(); let i = $index; track i) {\n <li class=\"ecl-quiz-card__option\" [class.ecl-quiz-card__option--selected]=\"selectedOptionIndex() === i\"\n [attr.data-match]=\"option.match\">\n @if (selectedOptionIndex() === i) {\n @if (!option.match) {\n <span class=\"ecl-quiz-card__option-assistive-label\">{{ 'ecl.quiz.YOUR-INCORRECT-ANSWER' | translate }}</span>\n }\n @if (option.match) {\n <span class=\"ecl-quiz-card__option-assistive-label\">{{ 'ecl.quiz.YOUR-CORRECT-ANSWER' | translate }}</span>\n }\n } @else if (option.match) {\n <span class=\"ecl-quiz-card__option-assistive-label\">{{ 'ecl.quiz.CORRECT-ANSWER' | translate }}</span>\n }\n {{ option.text }}\n @if (selectedOptionIndex() === i && !option.match) {\n <span class=\"ecl-quiz-card__option-icon\">\n <ecl-icon icon=\"x-circle\" size=\"s\" iconSet=\"phosphor\"\n class=\"ecl-quiz-card__option-icon--error\"></ecl-icon>\n </span>\n }\n @if (option.match) {\n <span class=\"ecl-quiz-card__option-icon\">\n <ecl-icon icon=\"check-circle\" size=\"s\" iconSet=\"phosphor\"\n class=\"ecl-quiz-card__option-icon--success\"></ecl-icon>\n </span>\n }\n </li>\n }\n </ol>\n }\n </div>\n </div>\n</article>\n" }]
|
|
303
|
+
}], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], question: [{ type: i0.Input, args: [{ isSignal: true, alias: "question", required: false }] }], answer: [{ type: i0.Input, args: [{ isSignal: true, alias: "answer", required: false }] }], answerTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "answerTitle", required: false }] }], category: [{ type: i0.Input, args: [{ isSignal: true, alias: "category", required: false }] }], imageSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageSrc", required: false }] }], imageAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageAlt", required: false }] }], imageDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageDisplay", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSize", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], cardFlip: [{ type: i0.Output, args: ["cardFlip"] }], frontElementRef: [{ type: i0.ViewChild, args: ['frontElement', { isSignal: true }] }], backElementRef: [{ type: i0.ViewChild, args: ['backElement', { isSignal: true }] }], questionElementRef: [{ type: i0.ViewChild, args: ['questionElement', { isSignal: true }] }], answerElementRef: [{ type: i0.ViewChild, args: ['answerElement', { isSignal: true }] }], contentElementRef: [{ type: i0.ViewChild, args: ['contentElement', { isSignal: true }] }], answerTitleRef: [{ type: i0.ViewChild, args: ['answerTitleEl', { isSignal: true }] }] } });
|
|
276
304
|
|
|
277
305
|
/**
|
|
278
306
|
* An ECL quiz carousel component that renders a sequence of `li[eclQuizCard]` cards with navigation dots and previous/next buttons.
|
|
@@ -323,10 +351,10 @@ class EclQuizComponent extends ECLBaseDirective {
|
|
|
323
351
|
...(ngDevMode ? [{ debugName: "showControls" }] : /* istanbul ignore next */ []));
|
|
324
352
|
this.emblaRef = viewChild(EmblaCarouselDirective, /* @ts-ignore */
|
|
325
353
|
...(ngDevMode ? [{ debugName: "emblaRef" }] : /* istanbul ignore next */ []));
|
|
326
|
-
this.dotButtons = viewChildren('dotButton', /* @ts-ignore */
|
|
327
|
-
...(ngDevMode ? [{ debugName: "dotButtons" }] : /* istanbul ignore next */ []));
|
|
328
354
|
this.cd = inject(ChangeDetectorRef);
|
|
329
355
|
this.eclRtlService = inject(EclRtlService);
|
|
356
|
+
this.hostRef = inject(ElementRef);
|
|
357
|
+
this.translate = inject(TranslateService);
|
|
330
358
|
this.destroy$ = new Subject();
|
|
331
359
|
this.cssClasses = computed(() => [
|
|
332
360
|
super.getCssClasses('ecl-quiz'),
|
|
@@ -346,6 +374,20 @@ class EclQuizComponent extends ECLBaseDirective {
|
|
|
346
374
|
/** Number of visible slides per snap. */
|
|
347
375
|
this.slidesPerSnap = signal(1, /* @ts-ignore */
|
|
348
376
|
...(ngDevMode ? [{ debugName: "slidesPerSnap" }] : /* istanbul ignore next */ []));
|
|
377
|
+
/**
|
|
378
|
+
* Pre-translated accessible label for each dot, passed to the shared slider pager.
|
|
379
|
+
* Depends on the current slide grouping, so it is computed here (where that
|
|
380
|
+
* information lives) and translated imperatively.
|
|
381
|
+
*/
|
|
382
|
+
this.dotAriaLabels = computed(() => {
|
|
383
|
+
// Read totalSnaps so the computed re-evaluates when the dot count changes.
|
|
384
|
+
const total = this.totalSnaps();
|
|
385
|
+
return Array.from({ length: total }, (_unused, dotIndex) => {
|
|
386
|
+
const { key, params } = this.getDotAriaLabel(dotIndex);
|
|
387
|
+
return this.translate.instant(key, params);
|
|
388
|
+
});
|
|
389
|
+
}, /* @ts-ignore */
|
|
390
|
+
...(ngDevMode ? [{ debugName: "dotAriaLabels" }] : /* istanbul ignore next */ []));
|
|
349
391
|
}
|
|
350
392
|
/** Returns the aria-label for a dot button at the given snap index. */
|
|
351
393
|
getDotAriaLabel(dotIndex) {
|
|
@@ -487,10 +529,10 @@ class EclQuizComponent extends ECLBaseDirective {
|
|
|
487
529
|
}
|
|
488
530
|
/** Move focus to the last dot button when Escape is pressed. */
|
|
489
531
|
escapeSlider() {
|
|
490
|
-
const dots = this.
|
|
491
|
-
if (dots
|
|
532
|
+
const dots = this.hostRef.nativeElement.querySelectorAll('.ecl-slider-pager__dot');
|
|
533
|
+
if (dots.length > 0) {
|
|
492
534
|
const lastDot = dots[dots.length - 1];
|
|
493
|
-
lastDot.
|
|
535
|
+
lastDot.focus();
|
|
494
536
|
}
|
|
495
537
|
}
|
|
496
538
|
/** Subscribe to cardFlip events on all cards to detect when all are flipped. */
|
|
@@ -504,17 +546,14 @@ class EclQuizComponent extends ECLBaseDirective {
|
|
|
504
546
|
});
|
|
505
547
|
});
|
|
506
548
|
}
|
|
507
|
-
/**
|
|
549
|
+
/**
|
|
550
|
+
* Hook invoked when a poll card flips. The category/sr-status tabindex
|
|
551
|
+
* management was removed in line with upstream ECL (PR #4681), so there is
|
|
552
|
+
* no longer per-card state to propagate here. Retained as an extension
|
|
553
|
+
* point for future "all cards flipped" behaviour.
|
|
554
|
+
*/
|
|
508
555
|
checkAllCardsFlipped() {
|
|
509
|
-
|
|
510
|
-
return;
|
|
511
|
-
}
|
|
512
|
-
const allFlipped = this.cards.toArray().every(card => card.isFlipped());
|
|
513
|
-
if (allFlipped) {
|
|
514
|
-
this.cards.forEach(card => {
|
|
515
|
-
card.allCardsFlipped.set(true);
|
|
516
|
-
});
|
|
517
|
-
}
|
|
556
|
+
// Intentionally left blank.
|
|
518
557
|
}
|
|
519
558
|
/**
|
|
520
559
|
* Equalizes the height of all cards based on the tallest content.
|
|
@@ -639,7 +678,7 @@ class EclQuizComponent extends ECLBaseDirective {
|
|
|
639
678
|
});
|
|
640
679
|
}
|
|
641
680
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclQuizComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
642
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: EclQuizComponent, isStandalone: true, selector: "section[eclQuiz]", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, eclTitle: { classPropertyName: "eclTitle", publicName: "eclTitle", isSignal: true, isRequired: false, transformFunction: null }, eclDescription: { classPropertyName: "eclDescription", publicName: "eclDescription", isSignal: true, isRequired: false, transformFunction: null }, isFullWidth: { classPropertyName: "isFullWidth", publicName: "isFullWidth", isSignal: true, isRequired: false, transformFunction: null }, hasBackground: { classPropertyName: "hasBackground", publicName: "hasBackground", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "keydown": "onKeydown($event)" }, properties: { "class": "cssClasses()" } }, queries: [{ propertyName: "cards", predicate: i0.forwardRef(() => EclQuizCardComponent), descendants: true }], viewQueries: [{ propertyName: "emblaRef", first: true, predicate: EmblaCarouselDirective, descendants: true, isSignal: true }
|
|
681
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: EclQuizComponent, isStandalone: true, selector: "section[eclQuiz]", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, eclTitle: { classPropertyName: "eclTitle", publicName: "eclTitle", isSignal: true, isRequired: false, transformFunction: null }, eclDescription: { classPropertyName: "eclDescription", publicName: "eclDescription", isSignal: true, isRequired: false, transformFunction: null }, isFullWidth: { classPropertyName: "isFullWidth", publicName: "isFullWidth", isSignal: true, isRequired: false, transformFunction: null }, hasBackground: { classPropertyName: "hasBackground", publicName: "hasBackground", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "keydown": "onKeydown($event)" }, properties: { "class": "cssClasses()" } }, queries: [{ propertyName: "cards", predicate: i0.forwardRef(() => EclQuizCardComponent), descendants: true }], viewQueries: [{ propertyName: "emblaRef", first: true, predicate: EmblaCarouselDirective, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (eclTitle() || eclDescription()) {\n<div class=\"ecl-quiz__header\">\n @if (eclTitle()) {\n <div class=\"ecl-quiz__title\">{{ eclTitle() }}</div>\n }\n @if (eclDescription()) {\n <div class=\"ecl-quiz__description\">{{ eclDescription() }}</div>\n }\n</div>\n}\n\n<div class=\"ecl-quiz__viewport\" data-ecl-quiz-slider\n role=\"region\"\n aria-label=\"Quiz slider\"\n aria-roledescription=\"carousel\"\n emblaCarousel\n [options]=\"emblaOptions\"\n [subscribeToEvents]=\"subscribeToEvents\"\n (emblaChange)=\"onEmblaChange($event)\">\n \n <ng-content></ng-content>\n</div>\n\n@if (showControls()) {\n<ecl-slider-pager\n class=\"ecl-quiz__pager\"\n variant=\"dots\"\n prevExtraClasses=\"ecl-quiz__prev\"\n nextExtraClasses=\"ecl-quiz__next\"\n dotsExtraClasses=\"ecl-quiz__dots\"\n dotExtraClasses=\"ecl-quiz__dot\"\n [activeIndex]=\"activeIndex()\"\n [isPrevDisabled]=\"prevDisabled()\"\n [isNextDisabled]=\"nextDisabled()\"\n [dotIndices]=\"getDotIndices()\"\n [dotAriaLabels]=\"dotAriaLabels()\"\n (prev)=\"onPrevClick()\"\n (next)=\"onNextClick()\"\n (goTo)=\"goTo($event)\">\n</ecl-slider-pager>\n\n<div class=\"ecl-quiz__counter\">{{ counterText() }}</div>\n}\n\n", dependencies: [{ kind: "component", type: i1.EclSliderPagerComponent, selector: "ecl-slider-pager", inputs: ["size", "variant", "isPlaying", "isPrevDisabled", "isNextDisabled", "activeIndex", "dotIndices", "dotAriaLabels", "prevExtraClasses", "nextExtraClasses", "dotsExtraClasses", "dotExtraClasses", "playExtraClasses", "pauseExtraClasses"], outputs: ["prev", "next", "goTo", "play", "pause"] }, { kind: "directive", type: EmblaCarouselDirective, selector: "[emblaCarousel]", inputs: ["options", "plugins", "subscribeToEvents", "eventsThrottleTime"], outputs: ["emblaChange"], exportAs: ["emblaCarousel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
643
682
|
}
|
|
644
683
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclQuizComponent, decorators: [{
|
|
645
684
|
type: Component,
|
|
@@ -647,14 +686,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImpor
|
|
|
647
686
|
'[class]': 'cssClasses()',
|
|
648
687
|
'(keydown)': 'onKeydown($event)',
|
|
649
688
|
}, imports: [
|
|
650
|
-
|
|
651
|
-
EclIconComponent,
|
|
689
|
+
...EUI_ECL_SLIDER,
|
|
652
690
|
EmblaCarouselDirective,
|
|
653
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (eclTitle() || eclDescription()) {\n<div class=\"ecl-quiz__header\">\n @if (eclTitle()) {\n <div class=\"ecl-quiz__title\">{{ eclTitle() }}</div>\n }\n @if (eclDescription()) {\n <div class=\"ecl-quiz__description\">{{ eclDescription() }}</div>\n }\n</div>\n}\n\n<div class=\"ecl-quiz__viewport\" data-ecl-quiz-slider\n role=\"region\"\n aria-label=\"Quiz slider\"\n aria-roledescription=\"carousel\"\n emblaCarousel\n [options]=\"emblaOptions\"\n [subscribeToEvents]=\"subscribeToEvents\"\n (emblaChange)=\"onEmblaChange($event)\">\n \n <ng-content></ng-content>\n</div>\n\n@if (showControls()) {\n<
|
|
691
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (eclTitle() || eclDescription()) {\n<div class=\"ecl-quiz__header\">\n @if (eclTitle()) {\n <div class=\"ecl-quiz__title\">{{ eclTitle() }}</div>\n }\n @if (eclDescription()) {\n <div class=\"ecl-quiz__description\">{{ eclDescription() }}</div>\n }\n</div>\n}\n\n<div class=\"ecl-quiz__viewport\" data-ecl-quiz-slider\n role=\"region\"\n aria-label=\"Quiz slider\"\n aria-roledescription=\"carousel\"\n emblaCarousel\n [options]=\"emblaOptions\"\n [subscribeToEvents]=\"subscribeToEvents\"\n (emblaChange)=\"onEmblaChange($event)\">\n \n <ng-content></ng-content>\n</div>\n\n@if (showControls()) {\n<ecl-slider-pager\n class=\"ecl-quiz__pager\"\n variant=\"dots\"\n prevExtraClasses=\"ecl-quiz__prev\"\n nextExtraClasses=\"ecl-quiz__next\"\n dotsExtraClasses=\"ecl-quiz__dots\"\n dotExtraClasses=\"ecl-quiz__dot\"\n [activeIndex]=\"activeIndex()\"\n [isPrevDisabled]=\"prevDisabled()\"\n [isNextDisabled]=\"nextDisabled()\"\n [dotIndices]=\"getDotIndices()\"\n [dotAriaLabels]=\"dotAriaLabels()\"\n (prev)=\"onPrevClick()\"\n (next)=\"onNextClick()\"\n (goTo)=\"goTo($event)\">\n</ecl-slider-pager>\n\n<div class=\"ecl-quiz__counter\">{{ counterText() }}</div>\n}\n\n" }]
|
|
654
692
|
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], eclTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "eclTitle", required: false }] }], eclDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "eclDescription", required: false }] }], isFullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "isFullWidth", required: false }] }], hasBackground: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasBackground", required: false }] }], cards: [{
|
|
655
693
|
type: ContentChildren,
|
|
656
694
|
args: [forwardRef(() => EclQuizCardComponent), { descendants: true }]
|
|
657
|
-
}], emblaRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => EmblaCarouselDirective), { isSignal: true }] }]
|
|
695
|
+
}], emblaRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => EmblaCarouselDirective), { isSignal: true }] }] } });
|
|
658
696
|
|
|
659
697
|
const EUI_ECL_QUIZ = [
|
|
660
698
|
EclQuizComponent,
|