@ethlete/components 1.0.0-next.77 → 1.0.0-next.79
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/CHANGELOG.md +119 -0
- package/design/accordion.ts +73 -0
- package/design/avatar.ts +90 -0
- package/design/badge.ts +48 -0
- package/design/banner.ts +77 -0
- package/design/bracket.ts +457 -0
- package/design/breadcrumb.ts +145 -0
- package/design/button.ts +49 -0
- package/design/calendar.ts +306 -0
- package/design/card.ts +92 -0
- package/design/carousel.ts +240 -0
- package/design/chart.ts +512 -0
- package/design/checkbox.ts +275 -0
- package/design/chip.ts +64 -0
- package/design/config.json +22 -0
- package/design/control.ts +19 -0
- package/design/copy-button.ts +59 -0
- package/design/description-list.ts +41 -0
- package/design/dialog.ts +214 -0
- package/design/divider.ts +27 -0
- package/design/empty-state.ts +45 -0
- package/design/floating-action.ts +55 -0
- package/design/form-field.ts +40 -1
- package/design/grid.ts +148 -0
- package/design/icon-set.ts +19 -0
- package/design/icon.ts +9 -0
- package/design/input.ts +86 -0
- package/design/kbd.ts +19 -0
- package/design/loader.ts +152 -0
- package/design/masonry.ts +115 -0
- package/design/match.ts +131 -0
- package/design/menu.ts +143 -0
- package/design/notification.ts +129 -0
- package/design/otp-input.ts +107 -0
- package/design/pagination.ts +120 -0
- package/design/picture.ts +80 -0
- package/design/progress-steps.ts +79 -0
- package/design/query-error.ts +60 -0
- package/design/radio-group.ts +132 -0
- package/design/scheduler.ts +369 -0
- package/design/scrollable.ts +218 -0
- package/design/scrollbar.ts +47 -0
- package/design/sdk/assets/fallback.svg +1 -0
- package/design/sdk/assets/tall.svg +1 -0
- package/design/sdk/assets/wide.svg +1 -0
- package/design/sdk/components/accent-on-light/accent-on-light.css +35 -0
- package/design/sdk/components/accent-on-light/accent-on-light.ts +10 -0
- package/design/sdk/components/accent-on-light/shared/controls.ts +46 -0
- package/design/sdk/components/accordion/accordion.css +17 -0
- package/design/sdk/components/accordion/accordion.ts +64 -0
- package/design/sdk/components/avatar/avatar.css +14 -0
- package/design/sdk/components/avatar/avatar.ts +78 -0
- package/design/sdk/components/badge/badge.css +13 -0
- package/design/sdk/components/badge/badge.ts +52 -0
- package/design/sdk/components/banner/banner.css +18 -0
- package/design/sdk/components/banner/banner.ts +87 -0
- package/design/sdk/components/bracket/bracket.css +59 -0
- package/design/sdk/components/bracket/bracket.ts +143 -0
- package/design/sdk/components/breadcrumb/breadcrumb.css +25 -0
- package/design/sdk/components/breadcrumb/breadcrumb.ts +81 -0
- package/design/sdk/components/button/button.css +33 -0
- package/design/sdk/components/button/button.ts +82 -0
- package/design/sdk/components/calendar/calendar.css +33 -0
- package/design/sdk/components/calendar/calendar.ts +96 -0
- package/design/sdk/components/card/card.css +19 -0
- package/design/sdk/components/card/card.ts +61 -0
- package/design/sdk/components/carousel/carousel.css +44 -0
- package/design/sdk/components/carousel/carousel.ts +74 -0
- package/design/sdk/components/chart/chart.css +56 -0
- package/design/sdk/components/chart/chart.ts +98 -0
- package/design/sdk/components/chip/chip.css +18 -0
- package/design/sdk/components/chip/chip.ts +76 -0
- package/design/sdk/components/copy-button/copy-button.css +14 -0
- package/design/sdk/components/copy-button/copy-button.ts +59 -0
- package/design/sdk/components/description-list/description-list.css +7 -0
- package/design/sdk/components/description-list/description-list.ts +53 -0
- package/design/sdk/components/dialog/dialog.css +29 -0
- package/design/sdk/components/dialog/dialog.ts +78 -0
- package/design/sdk/components/divider/divider.css +26 -0
- package/design/sdk/components/divider/divider.ts +43 -0
- package/design/sdk/components/empty-state/empty-state.css +15 -0
- package/design/sdk/components/empty-state/empty-state.ts +56 -0
- package/design/sdk/components/floating-action/floating-action.css +51 -0
- package/design/sdk/components/floating-action/floating-action.ts +63 -0
- package/design/sdk/components/form-field/form-field.ts +118 -0
- package/design/sdk/components/grid/grid.css +17 -0
- package/design/sdk/components/grid/grid.ts +80 -0
- package/design/sdk/components/input/input.css +75 -0
- package/design/sdk/components/input/input.ts +79 -0
- package/design/sdk/components/kbd/kbd.css +25 -0
- package/design/sdk/components/kbd/kbd.ts +57 -0
- package/design/sdk/components/loader/loader.css +37 -0
- package/design/sdk/components/loader/loader.ts +68 -0
- package/design/sdk/components/masonry/masonry.css +7 -0
- package/design/sdk/components/masonry/masonry.ts +42 -0
- package/design/sdk/components/match/match.css +25 -0
- package/design/sdk/components/match/match.ts +76 -0
- package/design/sdk/components/menu/menu.css +22 -0
- package/design/sdk/components/menu/menu.ts +91 -0
- package/design/sdk/components/notification/notification.css +32 -0
- package/design/sdk/components/notification/notification.ts +106 -0
- package/design/sdk/components/otp-input/otp-input.css +35 -0
- package/design/sdk/components/otp-input/otp-input.ts +64 -0
- package/design/sdk/components/pagination/pagination.css +14 -0
- package/design/sdk/components/pagination/pagination.ts +75 -0
- package/design/sdk/components/picture/picture.css +37 -0
- package/design/sdk/components/picture/picture.ts +96 -0
- package/design/sdk/components/progress-steps/progress-steps.css +37 -0
- package/design/sdk/components/progress-steps/progress-steps.ts +91 -0
- package/design/sdk/components/query-error/query-error.css +33 -0
- package/design/sdk/components/query-error/query-error.ts +120 -0
- package/design/sdk/components/scheduler/scheduler.css +55 -0
- package/design/sdk/components/scheduler/scheduler.ts +239 -0
- package/design/sdk/components/scrollable/scrollable.css +58 -0
- package/design/sdk/components/scrollable/scrollable.ts +133 -0
- package/design/sdk/components/scrollbar/scrollbar.css +78 -0
- package/design/sdk/components/scrollbar/scrollbar.ts +123 -0
- package/design/sdk/components/select/select.css +5 -0
- package/design/sdk/components/select/select.ts +16 -0
- package/design/sdk/components/select/shared/select-part.ts +75 -0
- package/design/sdk/components/select-panel/select-panel.css +3 -0
- package/design/sdk/components/select-panel/select-panel.ts +124 -0
- package/design/sdk/components/skeleton/skeleton.css +22 -0
- package/design/sdk/components/skeleton/skeleton.ts +50 -0
- package/design/sdk/components/slider/slider.css +52 -0
- package/design/sdk/components/slider/slider.ts +86 -0
- package/design/sdk/components/standings/standings.css +33 -0
- package/design/sdk/components/standings/standings.ts +130 -0
- package/design/sdk/components/stat-tile/stat-tile.css +15 -0
- package/design/sdk/components/stat-tile/stat-tile.ts +84 -0
- package/design/sdk/components/stream/stream.css +48 -0
- package/design/sdk/components/stream/stream.ts +38 -0
- package/design/sdk/components/switch/switch.css +35 -0
- package/design/sdk/components/switch/switch.ts +63 -0
- package/design/sdk/components/table/table.css +67 -0
- package/design/sdk/components/table/table.ts +160 -0
- package/design/sdk/components/tabs/tabs.css +13 -0
- package/design/sdk/components/tabs/tabs.ts +74 -0
- package/design/sdk/components/textarea/textarea.css +116 -0
- package/design/sdk/components/textarea/textarea.ts +64 -0
- package/design/sdk/components/timeline/timeline.css +30 -0
- package/design/sdk/components/timeline/timeline.ts +87 -0
- package/design/sdk/components/toolbar/toolbar.css +24 -0
- package/design/sdk/components/toolbar/toolbar.ts +87 -0
- package/design/sdk/components/tooltip/tooltip.css +15 -0
- package/design/sdk/components/tooltip/tooltip.ts +28 -0
- package/design/sdk/components/tree/selected-tint.css +15 -0
- package/design/sdk/components/tree/tree.ts +70 -0
- package/design/sdk/fixtures.ts +0 -0
- package/design/sdk/foundations/colors/colors.css +632 -0
- package/design/sdk/foundations/colors/colors.ts +188 -0
- package/design/sdk/foundations/colors/overrides.json +19 -0
- package/design/sdk/foundations/colors/shared/contrast.ts +120 -0
- package/design/sdk/foundations/elevation/elevation.css +6 -0
- package/design/sdk/foundations/elevation/elevation.ts +11 -0
- package/design/sdk/foundations/elevation/shared/elevation/scene.css +101 -0
- package/design/sdk/foundations/elevation/shared/elevation/scene.ts +74 -0
- package/design/sdk/foundations/icons/icons.ts +119 -0
- package/design/select.ts +113 -28
- package/design/skeleton.ts +67 -0
- package/design/slider.ts +155 -0
- package/design/standings.ts +161 -0
- package/design/stat-tile.ts +109 -0
- package/design/stream.ts +92 -0
- package/design/switch.ts +83 -0
- package/design/table.ts +302 -0
- package/design/tabs.ts +75 -0
- package/design/textarea.ts +92 -0
- package/design/timeline.ts +52 -0
- package/design/toolbar.ts +95 -0
- package/design/tooltip.ts +87 -0
- package/design/tree.ts +106 -0
- package/fesm2022/ethlete-components.mjs +240 -199
- package/fesm2022/ethlete-components.mjs.map +1 -1
- package/package.json +1 -1
- package/src/lib/accordion/accordion.component.css +2 -1
- package/src/lib/avatar/avatar.component.css +10 -0
- package/src/lib/badge/badge.component.css +2 -2
- package/src/lib/banner/banner.component.css +3 -1
- package/src/lib/breadcrumb/breadcrumb-outlet.component.css +5 -0
- package/src/lib/breadcrumb/breadcrumb.component.css +5 -1
- package/src/lib/button/button.component.css +19 -0
- package/src/lib/button/icon-button.component.css +19 -20
- package/src/lib/button/split-button.component.css +5 -1
- package/src/lib/calendar/calendar.component.css +13 -3
- package/src/lib/card/card.component.css +4 -0
- package/src/lib/carousel/carousel-autoplay-styles.component.css +1 -1
- package/src/lib/carousel/carousel.component.css +2 -2
- package/src/lib/chart/chart-axis.component.css +3 -3
- package/src/lib/chip/chip.component.css +8 -2
- package/src/lib/description-list/description-list.component.css +2 -1
- package/src/lib/empty-state/empty-state.component.css +4 -0
- package/src/lib/floating-action/floating-action-styles.component.css +27 -0
- package/src/lib/focus-ring/focus-ring-styles.component.css +4 -1
- package/src/lib/forms/checkbox/checkbox.component.css +31 -5
- package/src/lib/forms/color-input/color-input.component.css +3 -1
- package/src/lib/forms/color-input/color-picker-panel.component.css +6 -2
- package/src/lib/forms/date-time/date-input/date-input.component.css +1 -1
- package/src/lib/forms/date-time/date-time-input/date-time-input.component.css +1 -1
- package/src/lib/forms/date-time/duration-input/duration-input.component.css +1 -1
- package/src/lib/forms/date-time/range-input-shell-styles.component.css +1 -1
- package/src/lib/forms/date-time/time-input/time-input.component.css +1 -1
- package/src/lib/forms/description/description.component.css +7 -0
- package/src/lib/forms/dropzone/dropzone.component.css +26 -0
- package/src/lib/forms/form-field/form-field-control-suffix-styles.component.css +4 -2
- package/src/lib/forms/form-field/form-field-text-shell-styles.component.css +74 -17
- package/src/lib/forms/form-field/form-field-textarea-styles.component.css +62 -0
- package/src/lib/forms/form-field/form-field.component.css +6 -0
- package/src/lib/forms/form-field/headless/label.directive.css +1 -1
- package/src/lib/forms/input/input.component.css +6 -2
- package/src/lib/forms/input/number-input.component.css +2 -2
- package/src/lib/forms/input/password-input.component.css +4 -3
- package/src/lib/forms/otp-input/otp-input.component.css +23 -4
- package/src/lib/forms/phone-input/phone-input.component.css +4 -3
- package/src/lib/forms/rating/rating.component.css +2 -1
- package/src/lib/forms/rich-text-editor/rich-text-editor.component.css +1 -1
- package/src/lib/forms/select/select-option-styles.component.css +3 -2
- package/src/lib/forms/selection-card-styles.component.css +3 -2
- package/src/lib/forms/selection-list/checkbox-group/checkbox-group-select-all.component.css +4 -2
- package/src/lib/forms/selection-list/checkbox-group/checkbox-option.component.css +4 -2
- package/src/lib/forms/selection-list/radio-group/radio.component.css +5 -2
- package/src/lib/forms/selection-list/segmented-button-group/segmented-button.component.css +2 -1
- package/src/lib/forms/slider/range-slider.component.css +98 -6
- package/src/lib/forms/slider/slider.component.css +96 -4
- package/src/lib/forms/switch/switch.component.css +47 -4
- package/src/lib/forms/tag-input/tag-input.component.css +2 -2
- package/src/lib/forms/textarea/textarea-autosize-styles.component.css +2 -3
- package/src/lib/forms/textarea/textarea.component.css +7 -2
- package/src/lib/grid/grid-item-toolbar.component.css +10 -0
- package/src/lib/grid/grid-item.component.css +6 -1
- package/src/lib/icon/headless/align-icons.ts +30 -0
- package/src/lib/icon/headless/arrow-out-up-right-icon.ts +17 -0
- package/src/lib/icon/headless/arrow-right-icon.ts +23 -0
- package/src/lib/icon/headless/arrow-up-icon.ts +30 -0
- package/src/lib/icon/headless/arrows-left-right-icon.ts +31 -0
- package/src/lib/icon/headless/bold-icon.ts +11 -0
- package/src/lib/icon/headless/calendar-icon.ts +21 -0
- package/src/lib/icon/headless/check-icon.ts +14 -0
- package/src/lib/icon/headless/chevron-icon.ts +14 -0
- package/src/lib/icon/headless/circle-check-icon.ts +14 -0
- package/src/lib/icon/headless/circle-info-icon.ts +14 -0
- package/src/lib/icon/headless/clipboard-check-icon.ts +28 -0
- package/src/lib/icon/headless/clock-icon.ts +21 -0
- package/src/lib/icon/headless/code-block-icon.ts +15 -0
- package/src/lib/icon/headless/code-icon.ts +14 -0
- package/src/lib/icon/headless/ellipsis-icon.ts +13 -0
- package/src/lib/icon/headless/ellipsis-vertical-icon.ts +13 -0
- package/src/lib/icon/headless/eye-icons.ts +27 -0
- package/src/lib/icon/headless/eyedropper-icon.ts +22 -0
- package/src/lib/icon/headless/file-icon.ts +16 -0
- package/src/lib/icon/headless/filter-icon.ts +11 -0
- package/src/lib/icon/headless/floppy-disk-icon.ts +27 -0
- package/src/lib/icon/headless/focus-frame-icon.ts +16 -0
- package/src/lib/icon/headless/grid-2x2-icon.ts +17 -0
- package/src/lib/icon/headless/heading-1-icon.ts +11 -0
- package/src/lib/icon/headless/heading-2-icon.ts +11 -0
- package/src/lib/icon/headless/heading-3-icon.ts +11 -0
- package/src/lib/icon/headless/icon-definition.ts +14 -0
- package/src/lib/icon/headless/image-icon.ts +14 -0
- package/src/lib/icon/headless/italic-icon.ts +19 -0
- package/src/lib/icon/headless/link-icon.ts +17 -0
- package/src/lib/icon/headless/list-bulleted-icon.ts +14 -0
- package/src/lib/icon/headless/list-numbered-icon.ts +14 -0
- package/src/lib/icon/headless/location-icon.ts +21 -0
- package/src/lib/icon/headless/lock-icon.ts +14 -0
- package/src/lib/icon/headless/minus-icon.ts +14 -0
- package/src/lib/icon/headless/paragraph-icon.ts +11 -0
- package/src/lib/icon/headless/pause-icon.ts +11 -0
- package/src/lib/icon/headless/pencil-icon.ts +21 -0
- package/src/lib/icon/headless/play-icon.ts +10 -0
- package/src/lib/icon/headless/plus-icon.ts +21 -0
- package/src/lib/icon/headless/quote-icon.ts +15 -0
- package/src/lib/icon/headless/rotate-right-icon.ts +16 -0
- package/src/lib/icon/headless/star-icon.ts +14 -0
- package/src/lib/icon/headless/strikethrough-icon.ts +18 -0
- package/src/lib/icon/headless/table-icon.ts +15 -0
- package/src/lib/icon/headless/thumbtack-icon.ts +18 -0
- package/src/lib/icon/headless/times-icon.ts +14 -0
- package/src/lib/icon/headless/trash-icon.ts +24 -0
- package/src/lib/icon/headless/triangle-exclamation-icon.ts +14 -0
- package/src/lib/icon/headless/trophy-icon.ts +24 -0
- package/src/lib/icon/headless/underline-icon.ts +12 -0
- package/src/lib/icon/headless/undo-redo-icons.ts +24 -0
- package/src/lib/icon/headless/upload-icon.ts +16 -0
- package/src/lib/loader/brand-loader/brand-loader.component.css +4 -1
- package/src/lib/loader/progress-bar/progress-bar.component.css +1 -1
- package/src/lib/loader/spinner/spinner-styles.component.css +1 -1
- package/src/lib/match/match-card.component.css +9 -3
- package/src/lib/match/match-score.component.css +4 -1
- package/src/lib/menu/menu-selection-item.component.css +1 -1
- package/src/lib/menu/menu.component.css +5 -0
- package/src/lib/overlay/overlay-container.component.css +4 -0
- package/src/lib/pagination/pagination.component.css +4 -0
- package/src/lib/progress-steps/progress-step.component.css +4 -4
- package/src/lib/query-error/query-error.component.css +4 -0
- package/src/lib/scheduler/scheduler-appointment-styles.component.css +21 -5
- package/src/lib/scheduler/scheduler-month-view.component.css +4 -2
- package/src/lib/scheduler/scheduler-time-grid-view.component.css +8 -2
- package/src/lib/scrollable/headless/scrollable-navigation.component.css +1 -1
- package/src/lib/standings/standings-pick.component.css +1 -1
- package/src/lib/standings/standings.component.css +10 -10
- package/src/lib/stat-tile/stat-tile-sparkline.component.css +1 -1
- package/src/lib/stream/consent/stream-consent.component.css +99 -0
- package/src/lib/stream/error/stream-player-error.component.css +100 -0
- package/src/lib/stream/loading/stream-player-loading.component.css +16 -0
- package/src/lib/stream/pip/pip-slot-placeholder.component.css +68 -0
- package/src/lib/stream/stream-player-slot-styles.component.css +4 -0
- package/src/lib/table/table-resize-grip.component.css +2 -1
- package/src/lib/table/table-select-cell.component.css +45 -15
- package/src/lib/table/table.component.css +15 -5
- package/src/lib/tabs/tab-bar-styles.component.css +1 -1
- package/src/lib/tabs/tabs/tab-group.component.css +111 -0
- package/src/lib/time-picker/time-picker.component.css +2 -1
- package/src/lib/timeline/timeline-item.component.css +5 -1
- package/src/lib/toolbar/toolbar.component.css +4 -0
- package/src/lib/tooltip/tooltip.component.css +14 -0
- package/src/lib/tree/tree.component.css +2 -2
- package/types/ethlete-components.d.ts +62 -53
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import iconButtonBase from '../src/lib/button/icon-button.component.css?inline';
|
|
2
|
+
import textButtonBase from '../src/lib/button/text-button.component.css?inline';
|
|
3
|
+
import { CIRCLE_CHECK_ICON } from '../src/lib/icon/headless/circle-check-icon';
|
|
4
|
+
import { CIRCLE_INFO_ICON } from '../src/lib/icon/headless/circle-info-icon';
|
|
5
|
+
import iconBase from '../src/lib/icon/headless/icon-styles.component.css?inline';
|
|
6
|
+
import { TIMES_ICON } from '../src/lib/icon/headless/times-icon';
|
|
7
|
+
import { TRIANGLE_EXCLAMATION_ICON } from '../src/lib/icon/headless/triangle-exclamation-icon';
|
|
8
|
+
import spinnerBase from '../src/lib/loader/spinner/spinner-styles.component.css?inline';
|
|
9
|
+
import notificationBase from '../src/lib/notification/notification.component.css?inline';
|
|
10
|
+
import { buttonStyles } from './button';
|
|
11
|
+
import { iconMarkup } from './icon';
|
|
12
|
+
|
|
13
|
+
export type NotificationMockAction = {
|
|
14
|
+
label: string;
|
|
15
|
+
/** Extra attributes on the action button, e.g. design markers. */
|
|
16
|
+
attributes?: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type NotificationMockOptions = {
|
|
20
|
+
status: 'success' | 'error' | 'info' | 'loading';
|
|
21
|
+
title: string;
|
|
22
|
+
message?: string;
|
|
23
|
+
/** The `action` of the notification config. */
|
|
24
|
+
action?: NotificationMockAction;
|
|
25
|
+
/** The `secondaryAction` of the notification config. */
|
|
26
|
+
secondaryAction?: NotificationMockAction;
|
|
27
|
+
/**
|
|
28
|
+
* The color theme name the manager resolves for the status (`statusColorMapping`, else the semantic theme of
|
|
29
|
+
* its type). Left out, the notification takes the color theme around it.
|
|
30
|
+
*/
|
|
31
|
+
color?: string;
|
|
32
|
+
/** A surface theme name the app registers. Left out, the notification inherits it. */
|
|
33
|
+
surface?: string;
|
|
34
|
+
/** Extra attributes on the dismiss button, e.g. design markers. */
|
|
35
|
+
dismissAttributes?: string;
|
|
36
|
+
/** Extra attributes on the notification, e.g. design markers. */
|
|
37
|
+
attributes?: string;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const STATUS_ICONS = {
|
|
41
|
+
success: CIRCLE_CHECK_ICON,
|
|
42
|
+
error: TRIANGLE_EXCLAMATION_ICON,
|
|
43
|
+
info: CIRCLE_INFO_ICON,
|
|
44
|
+
loading: null,
|
|
45
|
+
} as const;
|
|
46
|
+
|
|
47
|
+
/** The stylesheets `notification()` draws with: the real notification, icon button, text button, spinner and icon CSS. */
|
|
48
|
+
export const notificationStyles = /* @__PURE__ */ [
|
|
49
|
+
buttonStyles,
|
|
50
|
+
iconBase,
|
|
51
|
+
iconButtonBase,
|
|
52
|
+
textButtonBase,
|
|
53
|
+
spinnerBase,
|
|
54
|
+
notificationBase,
|
|
55
|
+
`@layer components {
|
|
56
|
+
.et-notification-mock-stack {
|
|
57
|
+
display: flex;
|
|
58
|
+
flex-direction: column;
|
|
59
|
+
align-items: flex-end;
|
|
60
|
+
gap: var(--et-notification-stack-gap, 0.5rem);
|
|
61
|
+
}
|
|
62
|
+
.et-notification-mock-spinner {
|
|
63
|
+
--et-spinner-size: 16px;
|
|
64
|
+
--et-spinner-stroke-width: 2px;
|
|
65
|
+
}
|
|
66
|
+
.et-notification-mock-spinner circle {
|
|
67
|
+
stroke-dasharray: 18.85px;
|
|
68
|
+
stroke-dashoffset: 9.42px;
|
|
69
|
+
stroke-width: 12.5%;
|
|
70
|
+
}
|
|
71
|
+
}`,
|
|
72
|
+
].join('\n');
|
|
73
|
+
|
|
74
|
+
const spinner = () => {
|
|
75
|
+
const circle = `<svg viewBox="0 0 8 8" class="et-spinner-circle-graphic" xmlns="http://www.w3.org/2000/svg" focusable="false"><circle r="3" cx="50%" cy="50%"></circle></svg>`;
|
|
76
|
+
|
|
77
|
+
return `<et-spinner data-et-skip="CLIPPED" class="et-notification-spinner et-notification-mock-spinner et-color--inherited et-spinner" role="progressbar" aria-label="Loading"><div class="et-spinner-indeterminate"><div class="et-spinner-indeterminate-container" aria-hidden="true"><div class="et-spinner-layer"><div class="et-spinner-circle-clipper et-spinner-circle-left">${circle}</div><div class="et-spinner-gap-patch">${circle}</div><div class="et-spinner-circle-clipper et-spinner-circle-right">${circle}</div></div></div></div></et-spinner>`;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const dismissButton = (color: string | undefined, attributes?: string) => {
|
|
81
|
+
const classes = [
|
|
82
|
+
'et-notification-dismiss-btn',
|
|
83
|
+
'et-surface-interactive',
|
|
84
|
+
'et-color-interactive',
|
|
85
|
+
'et-icon-button',
|
|
86
|
+
'et-focus-ring',
|
|
87
|
+
`et-color--${color ?? 'inherited'}`,
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
return `<button ${attributes ?? ''} etNotificationDismiss type="button" aria-label="Dismiss" class="${classes.join(' ')}" data-variant="transparent" data-size="xs"><div class="et-icon-button-icon">${iconMarkup(TIMES_ICON)}</div></button>`;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const actionButton = (action: NotificationMockAction, slot: 'primary' | 'secondary') => {
|
|
94
|
+
const classes = [
|
|
95
|
+
slot === 'secondary' && 'et-notification-secondary-action',
|
|
96
|
+
'et-text-button',
|
|
97
|
+
'et-color-interactive',
|
|
98
|
+
'et-focus-ring',
|
|
99
|
+
'et-color--inherited',
|
|
100
|
+
].filter(Boolean);
|
|
101
|
+
const slotAttribute = slot === 'secondary' ? 'etNotificationAction="secondary"' : 'etNotificationAction';
|
|
102
|
+
|
|
103
|
+
return `<button ${action.attributes ?? ''} ${slotAttribute} type="button" class="${classes.join(' ')}" data-icon-alignment="start" data-size="xs"><div class="et-text-button-contents">${action.label}</div></button>`;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/** Draws an `et-notification` as the notification stack renders it, entered and at rest, as HTML. */
|
|
107
|
+
export const notification = (options: NotificationMockOptions) => {
|
|
108
|
+
const icon = STATUS_ICONS[options.status];
|
|
109
|
+
const glyph = icon ? iconMarkup(icon, 'et-notification-icon') : options.status === 'loading' ? spinner() : '';
|
|
110
|
+
const header = `<div class="et-notification-header">${glyph}<span class="et-notification-title">${options.title}</span>${dismissButton(options.color, options.dismissAttributes)}</div>`;
|
|
111
|
+
const message = options.message ? `<p class="et-notification-message">${options.message}</p>` : '';
|
|
112
|
+
const actions = [
|
|
113
|
+
options.action && actionButton(options.action, 'primary'),
|
|
114
|
+
options.secondaryAction && actionButton(options.secondaryAction, 'secondary'),
|
|
115
|
+
].filter(Boolean);
|
|
116
|
+
const footer = actions.length ? `<div class="et-notification-footer">${actions.join('')}</div>` : '';
|
|
117
|
+
const classes = [
|
|
118
|
+
'et-notification',
|
|
119
|
+
`et-color--${options.color ?? 'inherited'}`,
|
|
120
|
+
`et-surface--${options.surface ?? 'inherited'}`,
|
|
121
|
+
'et-animation-enter-done',
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
return `<et-notification ${options.attributes ?? ''} class="${classes.join(' ')}"><div class="et-notification-content">${header}${message}${footer}</div></et-notification>`;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
/** Draws notifications in the stack's column and gap, in flow instead of fixed to the viewport. */
|
|
128
|
+
export const notificationStack = (notifications: string[]) =>
|
|
129
|
+
`<div class="et-notification-stack et-notification-mock-stack">${notifications.join('')}</div>`;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import formSupport from '../src/lib/forms/form-field/form-support-styles.component.css?inline';
|
|
2
|
+
import label from '../src/lib/forms/form-field/headless/label.directive.css?inline';
|
|
3
|
+
import otpInputBase from '../src/lib/forms/otp-input/otp-input.component.css?inline';
|
|
4
|
+
|
|
5
|
+
/** An interaction a frame forces with the `data-et-force` design marker. */
|
|
6
|
+
export type OtpInputMockForce = 'hover' | 'active';
|
|
7
|
+
|
|
8
|
+
export type OtpInputMockOptions = {
|
|
9
|
+
/** The number of segments. */
|
|
10
|
+
length?: number;
|
|
11
|
+
/** The typed characters; only the first `length` show. */
|
|
12
|
+
value?: string;
|
|
13
|
+
/** Draws each typed character as a dot. */
|
|
14
|
+
masked?: boolean;
|
|
15
|
+
/** Draws the field focused: the caret segment after the last character, or the last segment when full. */
|
|
16
|
+
focused?: boolean;
|
|
17
|
+
/** The label, as HTML. */
|
|
18
|
+
label?: string;
|
|
19
|
+
/** The hint, as HTML. Hidden while an `error` shows. */
|
|
20
|
+
hint?: string;
|
|
21
|
+
/** The error message, as HTML. Draws the field touched and invalid. */
|
|
22
|
+
error?: string;
|
|
23
|
+
/** The color theme name the app registers for errors, e.g. `danger` in Storybook. */
|
|
24
|
+
errorColor?: string;
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
readonly?: boolean;
|
|
27
|
+
required?: boolean;
|
|
28
|
+
/** Unique per frame: the label and message ids derive from it. */
|
|
29
|
+
id?: string;
|
|
30
|
+
/** A color theme name the app registers. */
|
|
31
|
+
color?: string;
|
|
32
|
+
/** Forced interactions on the field. */
|
|
33
|
+
force?: OtpInputMockForce | OtpInputMockForce[];
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/** The stylesheets `otpInput()` draws with: the real `et-otp-input` and form support CSS. */
|
|
37
|
+
export const otpInputStyles = /* @__PURE__ */ [label, formSupport, otpInputBase].join('\n');
|
|
38
|
+
|
|
39
|
+
const forceList = (force: OtpInputMockForce | OtpInputMockForce[] | undefined) =>
|
|
40
|
+
force === undefined ? [] : Array.isArray(force) ? force : [force];
|
|
41
|
+
|
|
42
|
+
/** Draws `<et-otp-input>` as HTML, with the DOM the component renders. */
|
|
43
|
+
export const otpInput = (options: OtpInputMockOptions) => {
|
|
44
|
+
const { id = 'otp-input', length = 6, value = '' } = options;
|
|
45
|
+
const ids = { hint: `et-form-field-hint-${id}`, error: `et-form-field-error-${id}` };
|
|
46
|
+
const labelId = options.label !== undefined ? `et-label-${id}` : null;
|
|
47
|
+
const invalid = options.error !== undefined;
|
|
48
|
+
const supportId = invalid ? ids.error : options.hint !== undefined ? ids.hint : null;
|
|
49
|
+
const colorClass = invalid && options.errorColor ? options.errorColor : (options.color ?? 'inherited');
|
|
50
|
+
const chars = value.slice(0, length);
|
|
51
|
+
const caretIndex = options.focused && !options.readonly ? Math.min(chars.length, length - 1) : -1;
|
|
52
|
+
const force = forceList(options.force);
|
|
53
|
+
|
|
54
|
+
const hostAttributes = [
|
|
55
|
+
`class="et-otp-input et-color--${colorClass}"`,
|
|
56
|
+
invalid && 'data-error="true"',
|
|
57
|
+
force.length > 0 && `data-et-force="${force.join(' ')}"`,
|
|
58
|
+
].filter(Boolean);
|
|
59
|
+
|
|
60
|
+
const segments = Array.from({ length }, (_, index) => {
|
|
61
|
+
const char = chars[index];
|
|
62
|
+
const attributes = [
|
|
63
|
+
'class="et-otp-input-segment"',
|
|
64
|
+
index === caretIndex && 'data-caret="true"',
|
|
65
|
+
char !== undefined && 'data-filled="true"',
|
|
66
|
+
].filter(Boolean);
|
|
67
|
+
const content =
|
|
68
|
+
char !== undefined
|
|
69
|
+
? `<span class="et-otp-input-segment-char">${options.masked ? '•' : char}</span>`
|
|
70
|
+
: index === caretIndex
|
|
71
|
+
? '<span class="et-otp-input-caret"></span>'
|
|
72
|
+
: '';
|
|
73
|
+
|
|
74
|
+
return `<div ${attributes.join(' ')}>${content}</div>`;
|
|
75
|
+
}).join('');
|
|
76
|
+
|
|
77
|
+
const inputAttributes = [
|
|
78
|
+
'class="et-otp-input-native"',
|
|
79
|
+
'autocapitalize="off"',
|
|
80
|
+
'autocomplete="one-time-code"',
|
|
81
|
+
'spellcheck="false"',
|
|
82
|
+
`type="${options.masked ? 'password' : 'text'}"`,
|
|
83
|
+
'inputmode="numeric"',
|
|
84
|
+
`value="${chars}"`,
|
|
85
|
+
options.required && 'required',
|
|
86
|
+
options.disabled && 'disabled',
|
|
87
|
+
options.readonly && 'readonly',
|
|
88
|
+
labelId && `aria-labelledby="${labelId}"`,
|
|
89
|
+
supportId && `aria-describedby="${supportId}"`,
|
|
90
|
+
invalid && 'aria-invalid="true"',
|
|
91
|
+
].filter(Boolean);
|
|
92
|
+
|
|
93
|
+
const labelHtml = labelId
|
|
94
|
+
? `<et-label id="${labelId}"${options.disabled ? ' data-disabled="true"' : ''}><span class="et-label-content">${options.label}</span>${options.required ? '<span aria-hidden="true" class="et-label-required-marker">*</span>' : ''}</et-label>`
|
|
95
|
+
: '';
|
|
96
|
+
|
|
97
|
+
const support =
|
|
98
|
+
options.hint === undefined && options.error === undefined
|
|
99
|
+
? ''
|
|
100
|
+
: `<et-form-support class="et-form-support"><div class="et-form-support-stack">${
|
|
101
|
+
invalid
|
|
102
|
+
? `<div class="et-form-support-content et-form-support-errors${options.errorColor ? ` et-color--${options.errorColor}` : ''}" id="${ids.error}" aria-atomic="true" aria-live="polite" data-active="true" data-direction="from-below" data-state="active"><et-form-error class="et-form-error">${options.error}</et-form-error></div>`
|
|
103
|
+
: `<div class="et-form-support-content et-form-support-hint" id="${ids.hint}" data-active="true" data-direction="from-above" data-state="active"><et-hint>${options.hint}</et-hint></div>`
|
|
104
|
+
}</div></et-form-support>`;
|
|
105
|
+
|
|
106
|
+
return `<et-otp-input ${hostAttributes.join(' ')}>${labelHtml}<div class="et-otp-input-field"><div class="et-otp-input-segments" aria-hidden="true">${segments}</div><input ${inputAttributes.join(' ')}></div>${support}</et-otp-input>`;
|
|
107
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import paginationBase from '../src/lib/pagination/pagination.component.css?inline';
|
|
2
|
+
import { button, buttonStyles } from './button';
|
|
3
|
+
|
|
4
|
+
type PaginationMockControlType = 'first' | 'previous' | 'next' | 'last';
|
|
5
|
+
|
|
6
|
+
export type PaginationMockItem =
|
|
7
|
+
| {
|
|
8
|
+
type: 'page';
|
|
9
|
+
page: number;
|
|
10
|
+
current?: boolean;
|
|
11
|
+
/** Extra attributes on the item's button, e.g. design markers. */
|
|
12
|
+
attributes?: string;
|
|
13
|
+
}
|
|
14
|
+
| {
|
|
15
|
+
type: PaginationMockControlType;
|
|
16
|
+
/** The page the control goes to; links draw it into their href. */
|
|
17
|
+
page?: number;
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
attributes?: string;
|
|
20
|
+
}
|
|
21
|
+
| { type: 'ellipsis' };
|
|
22
|
+
|
|
23
|
+
export type PaginationMockOptions = {
|
|
24
|
+
items: PaginationMockItem[];
|
|
25
|
+
/** Defaults to `md`. */
|
|
26
|
+
size?: 'sm' | 'md';
|
|
27
|
+
/** Draws `<a href>` items instead of `<button>`s, as `renderAs="links"` does. */
|
|
28
|
+
renderAs?: 'buttons' | 'links';
|
|
29
|
+
/** The "Showing 1–10 of 200" readout before the list, as `totalItems` and `pageSize` turn it on. */
|
|
30
|
+
range?: string;
|
|
31
|
+
/** Draws the compact pager: this "3 / 20" readout, then only the previous and next items. */
|
|
32
|
+
compactStatus?: string;
|
|
33
|
+
/** Defaults to `true`, as `responsive` sets it. */
|
|
34
|
+
fitWidth?: boolean;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const CHEVRON_PATHS: Record<PaginationMockControlType, string> = {
|
|
38
|
+
first: 'M11 3 6 8l5 5M5 3v10',
|
|
39
|
+
previous: 'M10 3 5 8l5 5',
|
|
40
|
+
next: 'M6 3l5 5-5 5',
|
|
41
|
+
last: 'M5 3l5 5-5 5M11 3v10',
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const CONTROL_LABELS: Record<PaginationMockControlType, string> = {
|
|
45
|
+
first: 'First page',
|
|
46
|
+
previous: 'Previous page',
|
|
47
|
+
next: 'Next page',
|
|
48
|
+
last: 'Last page',
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const chevron = (type: PaginationMockControlType) =>
|
|
52
|
+
`<svg viewBox="0 0 16 16" width="14" height="14" fill="none" aria-hidden="true"><path d="${CHEVRON_PATHS[type]}" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
|
|
53
|
+
|
|
54
|
+
/** The stylesheets `pagination()` draws with: the real `et-pagination` and `et-button` CSS. */
|
|
55
|
+
export const paginationStyles = `${buttonStyles}\n${paginationBase}`;
|
|
56
|
+
|
|
57
|
+
const control = (item: Exclude<PaginationMockItem, { type: 'ellipsis' }>, renderAs: 'buttons' | 'links') => {
|
|
58
|
+
const isPage = item.type === 'page';
|
|
59
|
+
const current = isPage && !!item.current;
|
|
60
|
+
const disabled = !isPage && !!item.disabled;
|
|
61
|
+
const link = renderAs === 'links' && !disabled && item.page !== undefined;
|
|
62
|
+
const label = isPage ? `Page ${item.page}` : CONTROL_LABELS[item.type];
|
|
63
|
+
|
|
64
|
+
const markup = button({
|
|
65
|
+
label: isPage ? `${item.page}` : chevron(item.type),
|
|
66
|
+
size: 'sm',
|
|
67
|
+
variant: current ? 'filled' : 'transparent',
|
|
68
|
+
color: current ? undefined : 'surface',
|
|
69
|
+
disabled,
|
|
70
|
+
tag: link ? 'a' : 'button',
|
|
71
|
+
class: isPage ? 'et-pagination-button' : 'et-pagination-button et-pagination-button--control',
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const attributes = [
|
|
75
|
+
item.attributes,
|
|
76
|
+
link && `href="?page=${item.page}"`,
|
|
77
|
+
`aria-label="${label}"`,
|
|
78
|
+
current && 'aria-current="page"',
|
|
79
|
+
`data-type="${item.type}"`,
|
|
80
|
+
].filter(Boolean);
|
|
81
|
+
|
|
82
|
+
return markup.replace(/^<(button|a) /, `<$1 ${attributes.join(' ')} `);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const listItem = (item: PaginationMockItem, renderAs: 'buttons' | 'links') =>
|
|
86
|
+
`<li data-type="${item.type}" class="et-pagination-item">${
|
|
87
|
+
item.type === 'ellipsis'
|
|
88
|
+
? '<span class="et-pagination-ellipsis" aria-hidden="true">…</span>'
|
|
89
|
+
: control(item, renderAs)
|
|
90
|
+
}</li>`;
|
|
91
|
+
|
|
92
|
+
const readout = (text: string) =>
|
|
93
|
+
`<span class="et-pagination-readout-sizer" aria-hidden="true">${text}</span><span class="et-pagination-readout-text">${text}</span>`;
|
|
94
|
+
|
|
95
|
+
/** Draws `<et-pagination>` as HTML, with the DOM and classes the component renders. */
|
|
96
|
+
export const pagination = (options: PaginationMockOptions) => {
|
|
97
|
+
const { size = 'md', renderAs = 'buttons', compactStatus, fitWidth = true } = options;
|
|
98
|
+
const compact = compactStatus !== undefined;
|
|
99
|
+
|
|
100
|
+
const hostAttributes = [
|
|
101
|
+
'class="et-pagination-host"',
|
|
102
|
+
'role="navigation"',
|
|
103
|
+
'aria-label="Pagination"',
|
|
104
|
+
`data-size="${size}"`,
|
|
105
|
+
compact && 'data-compact=""',
|
|
106
|
+
fitWidth && !compact && 'data-fit-width=""',
|
|
107
|
+
].filter(Boolean);
|
|
108
|
+
|
|
109
|
+
const range =
|
|
110
|
+
!compact && options.range ? `<p class="et-pagination-range" aria-live="polite">${readout(options.range)}</p>` : '';
|
|
111
|
+
|
|
112
|
+
const items = compact
|
|
113
|
+
? `<li class="et-pagination-status" aria-live="polite">${readout(compactStatus)}</li>${options.items
|
|
114
|
+
.filter((item) => item.type === 'previous' || item.type === 'next')
|
|
115
|
+
.map((item) => listItem(item, renderAs))
|
|
116
|
+
.join('')}`
|
|
117
|
+
: options.items.map((item) => listItem(item, renderAs)).join('');
|
|
118
|
+
|
|
119
|
+
return `<et-pagination ${hostAttributes.join(' ')}>${range}<ul class="et-pagination-list">${items}</ul></et-pagination>`;
|
|
120
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import pictureBase from '../src/lib/picture/picture.component.css?inline';
|
|
2
|
+
|
|
3
|
+
export type PictureMockSource = {
|
|
4
|
+
srcset: string;
|
|
5
|
+
media?: string;
|
|
6
|
+
type?: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type PictureMockOptions = {
|
|
10
|
+
/** The `<img>` URL. Left out, no `<img>` renders, as when `defaultSrc` has not arrived yet. */
|
|
11
|
+
src?: string;
|
|
12
|
+
alt: string;
|
|
13
|
+
/** The `<source>` candidates before the `<img>`. */
|
|
14
|
+
sources?: PictureMockSource[];
|
|
15
|
+
/** The `<figcaption>` text. Left out, no caption renders. */
|
|
16
|
+
figcaption?: string;
|
|
17
|
+
/** Held only when `width` is left out, as the component does. */
|
|
18
|
+
aspectRatio?: string;
|
|
19
|
+
width?: number;
|
|
20
|
+
height?: number;
|
|
21
|
+
fit?: 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';
|
|
22
|
+
/** The host's `data-state`. Left out, `loaded`. */
|
|
23
|
+
state?: 'loading' | 'loaded' | 'error';
|
|
24
|
+
/** The projected `etPicturePlaceholder` HTML, drawn while `state` is `loading`. */
|
|
25
|
+
placeholder?: string;
|
|
26
|
+
/** The projected `etPictureError` HTML, drawn while `state` is `error`. */
|
|
27
|
+
error?: string;
|
|
28
|
+
/** Extra attributes on the host, e.g. a style or design markers. */
|
|
29
|
+
attributes?: string;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/** The stylesheet `picture()` draws with: the real picture CSS. */
|
|
33
|
+
export const pictureStyles = /* @__PURE__ */ [pictureBase].join('\n');
|
|
34
|
+
|
|
35
|
+
const attr = (name: string, value: string | number | undefined) => (value === undefined ? '' : ` ${name}="${value}"`);
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Draws `<et-picture>` as HTML: the figure, the picture with its sources and `<img>`, the placeholder or error slot
|
|
39
|
+
* for the state, and the caption.
|
|
40
|
+
*/
|
|
41
|
+
export const picture = (options: PictureMockOptions) => {
|
|
42
|
+
const state = options.state ?? 'loaded';
|
|
43
|
+
const aspectRatio = options.width === undefined ? options.aspectRatio : undefined;
|
|
44
|
+
const hostStyle = [
|
|
45
|
+
options.fit ? `--_et-picture-fit: ${options.fit}` : '',
|
|
46
|
+
aspectRatio ? `--_et-picture-aspect-ratio: ${aspectRatio}` : '',
|
|
47
|
+
].filter(Boolean);
|
|
48
|
+
const host = [
|
|
49
|
+
options.attributes,
|
|
50
|
+
'class="et-picture"',
|
|
51
|
+
`data-state="${state}"`,
|
|
52
|
+
options.fit ? `data-fit="${options.fit}"` : '',
|
|
53
|
+
aspectRatio ? `data-aspect-ratio="${aspectRatio}"` : '',
|
|
54
|
+
hostStyle.length ? `style="${hostStyle.join('; ')}"` : '',
|
|
55
|
+
].filter(Boolean);
|
|
56
|
+
|
|
57
|
+
const sources = (options.sources ?? [])
|
|
58
|
+
.map((source) => `<source${attr('type', source.type)} srcset="${source.srcset}"${attr('media', source.media)}>`)
|
|
59
|
+
.join('');
|
|
60
|
+
const img =
|
|
61
|
+
options.src === undefined
|
|
62
|
+
? ''
|
|
63
|
+
: `<img src="${options.src}" alt="${options.alt}"${attr('width', options.width)}${attr('height', options.height)}` +
|
|
64
|
+
`${aspectRatio ? ` style="aspect-ratio: ${aspectRatio}"` : ''} class="et-picture-img">`;
|
|
65
|
+
const slot =
|
|
66
|
+
state === 'loading' && options.placeholder
|
|
67
|
+
? `<span class="et-picture-slot" aria-hidden="true">${options.placeholder}</span>`
|
|
68
|
+
: state === 'error' && options.error
|
|
69
|
+
? `<span class="et-picture-slot">${options.error}</span>`
|
|
70
|
+
: '';
|
|
71
|
+
const caption = options.figcaption
|
|
72
|
+
? `<figcaption class="et-picture-figcaption">${options.figcaption}</figcaption>`
|
|
73
|
+
: '';
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
`<et-picture ${host.join(' ')}><figure class="et-picture-figure">` +
|
|
77
|
+
`<picture class="et-picture-picture">${sources}${img}${slot}</picture>${caption}` +
|
|
78
|
+
`</figure></et-picture>`
|
|
79
|
+
);
|
|
80
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import focusRing from '../src/lib/focus-ring/focus-ring-styles.component.css?inline';
|
|
2
|
+
import { CHECK_ICON } from '../src/lib/icon/headless/check-icon';
|
|
3
|
+
import { IconDefinition } from '../src/lib/icon/headless/icon-definition';
|
|
4
|
+
import iconBase from '../src/lib/icon/headless/icon-styles.component.css?inline';
|
|
5
|
+
import { TIMES_ICON } from '../src/lib/icon/headless/times-icon';
|
|
6
|
+
import { TRIANGLE_EXCLAMATION_ICON } from '../src/lib/icon/headless/triangle-exclamation-icon';
|
|
7
|
+
import progressStepBase from '../src/lib/progress-steps/progress-step.component.css?inline';
|
|
8
|
+
import progressStepsBase from '../src/lib/progress-steps/progress-steps.component.css?inline';
|
|
9
|
+
import { iconMarkup } from './icon';
|
|
10
|
+
|
|
11
|
+
export type ProgressStepMockState = 'complete' | 'current' | 'upcoming' | 'success' | 'warning' | 'error';
|
|
12
|
+
|
|
13
|
+
export type ProgressStepMockStep = {
|
|
14
|
+
/** The step label, as HTML. */
|
|
15
|
+
label: string;
|
|
16
|
+
state?: ProgressStepMockState;
|
|
17
|
+
/** The muted second line, as HTML. */
|
|
18
|
+
description?: string;
|
|
19
|
+
/** Draws the step on a link or a button, as `<a et-progress-step>` or `<button et-progress-step>`. */
|
|
20
|
+
as?: 'a' | 'button';
|
|
21
|
+
/**
|
|
22
|
+
* The color theme name the step forces, as the app's semantic theme for `success`, `warning` and `error`
|
|
23
|
+
* resolves. Left out, the step takes the color theme around it.
|
|
24
|
+
*/
|
|
25
|
+
color?: string;
|
|
26
|
+
/** Extra attributes on the step, e.g. design markers. */
|
|
27
|
+
attributes?: string;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type ProgressStepsMockOptions = {
|
|
31
|
+
steps: ProgressStepMockStep[];
|
|
32
|
+
orientation?: 'horizontal' | 'vertical';
|
|
33
|
+
/** Extra attributes on the steps, e.g. design markers. */
|
|
34
|
+
attributes?: string;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/** The stylesheets `progressSteps()` draws with: the real progress steps, focus ring and icon CSS. */
|
|
38
|
+
export const progressStepsStyles = /* @__PURE__ */ [focusRing, iconBase, progressStepsBase, progressStepBase].join(
|
|
39
|
+
'\n',
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const STATE_ICONS: Partial<Record<ProgressStepMockState, IconDefinition>> = {
|
|
43
|
+
complete: CHECK_ICON,
|
|
44
|
+
success: CHECK_ICON,
|
|
45
|
+
warning: TRIANGLE_EXCLAMATION_ICON,
|
|
46
|
+
error: TIMES_ICON,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const step = (item: ProgressStepMockStep) => {
|
|
50
|
+
const state = item.state ?? 'upcoming';
|
|
51
|
+
const tag = item.as ?? 'et-progress-step';
|
|
52
|
+
const icon = STATE_ICONS[state];
|
|
53
|
+
const marker = icon ? iconMarkup(icon) : '<span class="et-progress-step-marker-number"></span>';
|
|
54
|
+
const description = item.description ? `<span etProgressStepDescription>${item.description}</span>` : '';
|
|
55
|
+
const attributes = [
|
|
56
|
+
item.attributes,
|
|
57
|
+
item.as !== undefined && 'et-progress-step=""',
|
|
58
|
+
item.as === 'a' && 'href="#"',
|
|
59
|
+
item.as === 'button' && 'type="button"',
|
|
60
|
+
`class="et-color--${item.color ?? 'inherited'} et-focus-ring et-progress-step"`,
|
|
61
|
+
`data-state="${state}"`,
|
|
62
|
+
state === 'current' && 'aria-current="step"',
|
|
63
|
+
item.as === undefined && 'role="listitem"',
|
|
64
|
+
].filter(Boolean);
|
|
65
|
+
|
|
66
|
+
return `<${tag} ${attributes.join(' ')}><span class="et-progress-step-marker">${marker}</span><span class="et-progress-step-text"><span class="et-progress-step-label">${item.label}</span>${description}</span></${tag}>`;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/** Draws an `et-progress-steps` row or column with its `et-progress-step`s as the components render them, as HTML. */
|
|
70
|
+
export const progressSteps = (options: ProgressStepsMockOptions) => {
|
|
71
|
+
const attributes = [
|
|
72
|
+
options.attributes,
|
|
73
|
+
'class="et-progress-steps"',
|
|
74
|
+
'role="list"',
|
|
75
|
+
`data-orientation="${options.orientation ?? 'horizontal'}"`,
|
|
76
|
+
].filter(Boolean);
|
|
77
|
+
|
|
78
|
+
return `<et-progress-steps ${attributes.join(' ')}>${options.steps.map(step).join('')}</et-progress-steps>`;
|
|
79
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { TRIANGLE_EXCLAMATION_ICON } from '../src/lib/icon/headless/triangle-exclamation-icon';
|
|
2
|
+
import queryErrorBase from '../src/lib/query-error/query-error.component.css?inline';
|
|
3
|
+
import { bannerStyles } from './banner';
|
|
4
|
+
import { button } from './button';
|
|
5
|
+
import { iconMarkup } from './icon';
|
|
6
|
+
|
|
7
|
+
export type QueryErrorMockOptions = {
|
|
8
|
+
/** The HTTP status, drawn as the host's `data-status`. */
|
|
9
|
+
status: number;
|
|
10
|
+
title: string;
|
|
11
|
+
/** One message draws a paragraph; more than one, or `list`, a violation list. */
|
|
12
|
+
messages: string[];
|
|
13
|
+
list?: boolean;
|
|
14
|
+
/** Draws the default retry button with this label. Left out, no retry button. */
|
|
15
|
+
retry?: string;
|
|
16
|
+
/** Extra attributes on the retry button, e.g. design markers. */
|
|
17
|
+
retryAttributes?: string;
|
|
18
|
+
/** The projected `etQueryErrorActions` HTML. Replaces the retry button. */
|
|
19
|
+
actions?: string;
|
|
20
|
+
/** The color theme name the banner forces: the `color` input, else the app's `type: 'error'` theme. */
|
|
21
|
+
color: string;
|
|
22
|
+
/** Extra attributes on the host, e.g. a style or design markers. */
|
|
23
|
+
attributes?: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/** The stylesheets `queryError()` draws with: the real banner, button, icon and query-error CSS. */
|
|
27
|
+
export const queryErrorStyles = /* @__PURE__ */ [bannerStyles, queryErrorBase].join('\n');
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Draws `<et-query-error>` as HTML: the error banner with its icon, the title, the message or violation list, and
|
|
31
|
+
* the retry button or the projected actions.
|
|
32
|
+
*/
|
|
33
|
+
export const queryError = (options: QueryErrorMockOptions) => {
|
|
34
|
+
const isList = options.list ?? options.messages.length > 1;
|
|
35
|
+
const body = isList
|
|
36
|
+
? `<ul class="et-query-error-list" etBannerBody>${options.messages
|
|
37
|
+
.map((message) => `<li class="et-query-error-list-item">${message}</li>`)
|
|
38
|
+
.join('')}</ul>`
|
|
39
|
+
: `<p class="et-query-error-message" etBannerBody>${options.messages[0] ?? ''}</p>`;
|
|
40
|
+
const retry =
|
|
41
|
+
options.retry === undefined
|
|
42
|
+
? ''
|
|
43
|
+
: button({ label: options.retry }).replace('<button ', `<button ${options.retryAttributes ?? ''} `);
|
|
44
|
+
const actionsContent = options.actions ?? retry;
|
|
45
|
+
const actions = actionsContent ? `<div class="et-query-error-actions" etBannerAction>${actionsContent}</div>` : '';
|
|
46
|
+
const host = [
|
|
47
|
+
options.attributes,
|
|
48
|
+
'class="et-query-error-host et-query-error"',
|
|
49
|
+
'role="alert"',
|
|
50
|
+
`data-status="${options.status}"`,
|
|
51
|
+
isList ? 'data-list=""' : '',
|
|
52
|
+
].filter(Boolean);
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
`<et-query-error ${host.join(' ')}>` +
|
|
56
|
+
`<et-banner class="et-color--${options.color} et-banner" data-type="error">${iconMarkup(TRIANGLE_EXCLAMATION_ICON)}` +
|
|
57
|
+
`<div class="et-banner-content"><h3 class="et-query-error-title" etBannerHeading>${options.title}</h3>${body}${actions}</div>` +
|
|
58
|
+
`</et-banner></et-query-error>`
|
|
59
|
+
);
|
|
60
|
+
};
|