From 3ce156921ac5b674488f22eacc02a07c3bbf2711 Mon Sep 17 00:00:00 2001 From: Boris Novikov Date: Tue, 7 May 2024 12:40:48 +0400 Subject: [PATCH] feat: setup imports sort plugin --- .eslintrc.json | 19 + package-lock.json | 10 + package.json | 2 + projects/elonkit/src/cdk/a11y/public-api.ts | 2 +- projects/elonkit/src/public-api.ts | 14 +- .../__specs__/action-heading.spec.ts | 17 - .../action-heading-story-basic.source.ts | 19 - .../action-heading-story-basic/index.ts | 1 - .../__stories__/action-heading.stories.mdx | 99 -- .../action-heading.component.html | 3 - .../action-heading.component.scss | 4 - .../action-heading.component.theme.scss | 13 - .../action-heading.component.ts | 10 - .../action-heading/action-heading.module.ts | 31 - .../heading-actions.component.html | 3 - .../heading-actions.component.scss | 4 - .../heading-actions.component.ts | 10 - .../heading-breadcrumbs.component.html | 3 - .../heading-breadcrumbs.component.scss | 3 - .../heading-breadcrumbs.component.ts | 10 - .../heading-header.component.html | 5 - .../heading-header.component.scss | 13 - .../heading-header.component.theme.scss | 7 - .../heading-header.component.ts | 58 - .../heading-main/heading-main.component.html | 3 - .../heading-main/heading-main.component.scss | 8 - .../heading-main/heading-main.component.ts | 10 - .../heading-status.component.html | 3 - .../heading-status.component.scss | 4 - .../heading-status.component.ts | 10 - .../elonkit/src/ui/action-heading/index.ts | 1 - .../src/ui/action-heading/public-api.ts | 7 - .../src/ui/alert/__specs__/alert.spec.ts | 121 -- .../alert-story-actions.source.ts | 11 - .../__stories__/alert-story-actions/index.ts | 1 - .../alert-story-basic.source.ts | 7 - .../__stories__/alert-story-basic/index.ts | 1 - .../alert-story-icon-mapping.component.ts | 55 - .../alert-story-icon-mapping.module.ts | 25 - .../alert-story-icon-mapping.source.ts | 40 - .../alert-story-icon-mapping/index.ts | 3 - .../ui/alert/__stories__/alert.stories.mdx | 167 --- .../elonkit/src/ui/alert/alert.component.html | 26 - .../elonkit/src/ui/alert/alert.component.scss | 50 - .../src/ui/alert/alert.component.theme.scss | 72 -- .../elonkit/src/ui/alert/alert.component.ts | 160 --- projects/elonkit/src/ui/alert/alert.module.ts | 15 - projects/elonkit/src/ui/alert/alert.types.ts | 1 - .../alert-actions.component.html | 3 - .../alert-actions.component.scss | 15 - .../alert-actions.component.theme.scss | 13 - .../alert-actions/alert-actions.component.ts | 10 - .../alert/components/alert-actions/index.ts | 1 - projects/elonkit/src/ui/alert/index.ts | 1 - projects/elonkit/src/ui/alert/public-api.ts | 4 - .../__specs__/audio-player.spec.ts | 61 - .../audio-player-story-basic.component.scss | 3 - .../audio-player-story-basic.component.ts | 14 - .../audio-player-story-basic.module.ts | 15 - .../audio-player-story-basic.source.ts | 5 - .../audio-player-story-basic/index.ts | 4 - .../__stories__/audio-player.stories.mdx | 51 - .../audio-player/audio-player.component.html | 36 - .../audio-player/audio-player.component.scss | 56 - .../audio-player.component.theme.scss | 23 - .../ui/audio-player/audio-player.component.ts | 269 ----- .../ui/audio-player/audio-player.module.ts | 37 - .../audio-player-options.component.html | 85 -- .../audio-player-options.component.scss | 66 -- .../audio-player-options.component.theme.scss | 30 - .../audio-player-options.component.ts | 75 -- .../components/audio-player-options/index.ts | 1 - .../audio-player-time-slider.component.html | 18 - .../audio-player-time-slider.component.scss | 88 -- ...io-player-time-slider.component.theme.scss | 39 - .../audio-player-time-slider.component.ts | 197 ---- .../audio-player-time-slider/index.ts | 1 - .../audio-player-volume.component.html | 29 - .../audio-player-volume.component.scss | 64 -- .../audio-player-volume.component.theme.scss | 41 - .../audio-player-volume.component.ts | 113 -- .../components/audio-player-volume/index.ts | 1 - projects/elonkit/src/ui/audio-player/index.ts | 1 - .../elonkit/src/ui/audio-player/public-api.ts | 5 - .../__specs__/autocomplete-multiple.spec.ts | 176 --- ...lete-multiple-story-service.component.scss | 19 - ...mplete-multiple-story-service.component.ts | 83 -- ...ocomplete-multiple-story-service.module.ts | 19 - ...complete-multiple-story-service.service.ts | 37 - ...ocomplete-multiple-story-service.source.ts | 87 -- .../index.ts | 3 - .../autocomplete-multiple.stories.mdx | 93 -- .../autocomplete-multiple.animations.ts | 10 - .../autocomplete-multiple.component.html | 156 --- .../autocomplete-multiple.component.scss | 231 ---- .../autocomplete-multiple.component.ts | 649 ----------- .../autocomplete-multiple.module.ts | 35 - .../autocomplete-multiple.theme.scss | 103 -- .../autocomplete-multiple.types.ts | 5 - .../src/ui/autocomplete-multiple/index.ts | 1 - .../ui/autocomplete-multiple/public-api.ts | 8 - .../src/ui/avatar/__specs__/avatar.spec.ts | 79 -- .../avatar-story-group.source.ts | 23 - .../__stories__/avatar-story-group/index.ts | 1 - .../avatar-story-image.source.ts | 10 - .../__stories__/avatar-story-image/index.ts | 1 - .../avatar-story-no-image-icon.source.ts | 10 - .../avatar-story-no-image-icon/index.ts | 1 - ...avatar-story-no-image-typography.source.ts | 8 - .../avatar-story-no-image-typography/index.ts | 1 - .../ui/avatar/__stories__/avatar.stories.mdx | 206 ---- .../src/ui/avatar/avatar-group.component.html | 3 - .../src/ui/avatar/avatar-group.component.scss | 36 - .../avatar/avatar-group.component.theme.scss | 7 - .../src/ui/avatar/avatar-group.component.ts | 76 -- .../src/ui/avatar/avatar.component.html | 13 - .../src/ui/avatar/avatar.component.scss | 39 - .../src/ui/avatar/avatar.component.theme.scss | 11 - .../elonkit/src/ui/avatar/avatar.component.ts | 80 -- .../elonkit/src/ui/avatar/avatar.module.ts | 13 - .../elonkit/src/ui/avatar/avatar.types.ts | 10 - projects/elonkit/src/ui/avatar/index.ts | 1 - projects/elonkit/src/ui/avatar/public-api.ts | 4 - .../__specs__/breadcrumbs.spec.resolver.ts | 64 -- .../__specs__/breadcrumbs.spec.routes.ts | 111 -- .../__specs__/breadcrumbs.spec.service.ts | 88 -- .../breadcrumbs/__specs__/breadcrumbs.spec.ts | 191 --- .../breadcrumbs-story-basic.component.ts | 130 --- .../breadcrumbs-story-basic.module.ts | 132 --- .../breadcrumbs-story-basic.resolver.ts | 64 -- .../breadcrumbs-story-basic.service.ts | 88 -- .../breadcrumbs-story-basic.source.ts | 94 -- .../breadcrumbs-story-basic/index.ts | 3 - ...dcrumbs-story-customization.component.scss | 6 - ...eadcrumbs-story-customization.component.ts | 36 - .../breadcrumbs-story-customization.module.ts | 133 --- .../breadcrumbs-story-customization.source.ts | 30 - .../breadcrumbs-story-customization/index.ts | 3 - .../__stories__/breadcrumbs.stories.mdx | 130 --- .../ui/breadcrumbs/breadcrumbs.component.html | 60 - .../ui/breadcrumbs/breadcrumbs.component.scss | 83 -- .../breadcrumbs.component.theme.scss | 27 - .../ui/breadcrumbs/breadcrumbs.component.ts | 290 ----- .../src/ui/breadcrumbs/breadcrumbs.module.ts | 35 - .../ui/breadcrumbs/breadcrumbs.resolver.ts | 14 - .../src/ui/breadcrumbs/breadcrumbs.service.ts | 68 -- .../src/ui/breadcrumbs/breadcrumbs.types.ts | 19 - .../breadcrumbs-breadcrumb.component.html | 47 - .../breadcrumbs-breadcrumb.component.scss | 63 - ...readcrumbs-breadcrumb.component.theme.scss | 31 - .../breadcrumbs-breadcrumb.component.ts | 45 - .../breadcrumbs-breadcrumb/index.ts | 1 - .../breadcrumbs-collapse.component.html | 45 - .../breadcrumbs-collapse.component.scss | 22 - .../breadcrumbs-collapse.component.theme.scss | 10 - .../breadcrumbs-collapse.component.ts | 40 - .../components/breadcrumbs-collapse/index.ts | 1 - .../directives/breadcrumbs-back.directive.ts | 6 - .../directives/breadcrumbs-more.directive.ts | 6 - .../breadcrumbs-separator.directive.ts | 6 - projects/elonkit/src/ui/breadcrumbs/index.ts | 1 - .../elonkit/src/ui/breadcrumbs/public-api.ts | 19 - .../ui/dropzone/__specs__/dropzone.spec.ts | 213 ---- .../dropzone-story-basic.component.html | 12 - .../dropzone-story-basic.component.scss | 3 - .../dropzone-story-basic.component.ts | 38 - .../dropzone-story-basic.module.ts | 14 - .../dropzone-story-basic.source.ts | 22 - .../__stories__/dropzone-story-basic/index.ts | 3 - .../dropzone-story-custom-icon.component.html | 5 - .../dropzone-story-custom-icon.component.scss | 3 - .../dropzone-story-custom-icon.component.ts | 28 - .../dropzone-story-custom-icon.module.ts | 14 - .../dropzone-story-custom-icon.source.ts | 28 - .../dropzone-story-custom-icon/index.ts | 3 - .../dropzone-story-required.component.html | 11 - .../dropzone-story-required.component.scss | 8 - .../dropzone-story-required.component.ts | 30 - .../dropzone-story-required.module.ts | 15 - .../dropzone-story-required.source.ts | 34 - .../dropzone-story-required/index.ts | 3 - .../dropzone/__stories__/dropzone.stories.mdx | 170 --- .../src/ui/dropzone/dropzone.component.html | 31 - .../src/ui/dropzone/dropzone.component.scss | 51 - .../ui/dropzone/dropzone.component.theme.scss | 30 - .../src/ui/dropzone/dropzone.component.ts | 349 ------ .../src/ui/dropzone/dropzone.module.ts | 15 - .../src/ui/dropzone/dropzones.types.ts | 22 - projects/elonkit/src/ui/dropzone/index.ts | 1 - .../elonkit/src/ui/dropzone/public-api.ts | 3 - .../empty-state/__specs__/empty-state.spec.ts | 71 -- .../empty-state-story-basic.source.ts | 5 - .../empty-state-story-basic/index.ts | 1 - .../empty-state-story-button.source.ts | 7 - .../empty-state-story-button/index.ts | 1 - .../__stories__/empty-state.stories.mdx | 169 --- .../ui/empty-state/empty-state.component.html | 21 - .../ui/empty-state/empty-state.component.scss | 45 - .../empty-state.component.theme.scss | 22 - .../ui/empty-state/empty-state.component.ts | 89 -- .../src/ui/empty-state/empty-state.module.ts | 14 - .../src/ui/empty-state/empty-state.types.ts | 17 - projects/elonkit/src/ui/empty-state/index.ts | 1 - .../elonkit/src/ui/empty-state/public-api.ts | 3 - .../demo-wrapper/demo-wrapper.component.ts | 1 + .../icons/demo-wrapper/demo-wrapper.module.ts | 6 +- .../src/ui/icons/demo-wrapper/index.ts | 2 +- .../elonkit/src/ui/icons/icons.service.ts | 2 +- .../elonkit/src/ui/icons/icons.stories.ts | 9 +- projects/elonkit/src/ui/icons/public-api.ts | 2 +- .../__specs__/inline-form-field.spec.ts | 284 ----- .../inline-form-field-story-basic/index.ts | 3 - ...line-form-field-story-basic.component.html | 5 - ...inline-form-field-story-basic.component.ts | 10 - .../inline-form-field-story-basic.module.ts | 17 - .../inline-form-field-story-basic.source.ts | 9 - .../index.ts | 3 - ...orm-field-story-composition.component.html | 36 - ...orm-field-story-composition.component.scss | 4 - ...-form-field-story-composition.component.ts | 15 - ...ine-form-field-story-composition.module.ts | 37 - ...ine-form-field-story-composition.source.ts | 46 - .../index.ts | 3 - ...form-field-story-typography.component.html | 11 - ...e-form-field-story-typography.component.ts | 18 - ...line-form-field-story-typography.module.ts | 17 - ...line-form-field-story-typography.source.ts | 9 - .../index.ts | 3 - ...form-field-story-validation.component.html | 15 - ...form-field-story-validation.component.scss | 4 - ...e-form-field-story-validation.component.ts | 53 - ...line-form-field-story-validation.module.ts | 17 - ...line-form-field-story-validation.source.ts | 56 - .../__stories__/inline-form-field.stories.mdx | 115 -- .../elonkit/src/ui/inline-form-field/index.ts | 1 - .../inline-form-field.component.html | 28 - .../inline-form-field.component.scss | 151 --- .../inline-form-field.component.theme.scss | 16 - .../inline-form-field.component.ts | 210 ---- .../inline-form-field.module.ts | 14 - .../src/ui/inline-form-field/public-api.ts | 2 - .../elonkit/src/ui/locale/locale.service.ts | 1 - projects/elonkit/src/ui/locale/public-api.ts | 2 +- .../ui/paginator/__specs__/paginator.spec.ts | 199 ---- .../paginator-story-basic/index.ts | 3 - .../paginator-story-basic.component.html | 9 - .../paginator-story-basic.component.ts | 35 - .../paginator-story-basic.module.ts | 13 - .../paginator-story-basic.source.ts | 31 - .../index.ts | 5 - ...aginator-story-page-size-options.source.ts | 12 - .../__stories__/paginator.stories.mdx | 108 -- projects/elonkit/src/ui/paginator/index.ts | 1 - .../src/ui/paginator/paginator.component.html | 83 -- .../src/ui/paginator/paginator.component.scss | 129 --- .../paginator/paginator.component.theme.scss | 37 - .../src/ui/paginator/paginator.component.ts | 318 ----- .../src/ui/paginator/paginator.module.ts | 29 - .../elonkit/src/ui/paginator/public-api.ts | 2 - .../ui/surface/surface.component.theme.scss | 13 - .../elonkit/src/ui/surface/surface.source.ts | 15 - .../src/ui/surface/surface.stories.mdx | 30 - .../timepicker/__specs__/timepicker.spec.ts | 116 -- .../timepicker-story-basic/index.ts | 3 - .../timepicker-story-basic.component.html | 4 - .../timepicker-story-basic.component.ts | 10 - .../timepicker-story-basic.module.ts | 17 - .../timepicker-story-basic.source.ts | 16 - .../timepicker-story-required/index.ts | 3 - .../timepicker-story-required.component.html | 4 - .../timepicker-story-required.component.ts | 12 - .../timepicker-story-required.module.ts | 17 - .../timepicker-story-required.source.ts | 16 - .../timepicker-story-seconds/index.ts | 3 - .../timepicker-story-seconds.component.html | 4 - .../timepicker-story-seconds.component.ts | 10 - .../timepicker-story-seconds.module.ts | 17 - .../timepicker-story-seconds.story.ts | 16 - .../__stories__/timepicker.stories.mdx | 77 -- projects/elonkit/src/ui/timepicker/index.ts | 1 - .../elonkit/src/ui/timepicker/public-api.ts | 2 - .../ui/timepicker/timepicker.component.html | 11 - .../src/ui/timepicker/timepicker.component.ts | 313 ----- .../src/ui/timepicker/timepicker.module.ts | 16 - .../src/ui/tooltip/_specs_/tooltip.spec.ts | 95 -- .../_stories_/tooltip-story-basic/index.ts | 3 - .../tooltip-story-basic.component.html | 10 - .../tooltip-story-basic.component.ts | 10 - .../tooltip-story-basic.module.ts | 15 - .../tooltip-story-basic.source.ts | 12 - .../tooltip-story-interactive/index.ts | 3 - .../tooltip-story-interactive.component.html | 37 - .../tooltip-story-interactive.component.ts | 11 - .../tooltip-story-interactive.module.ts | 15 - .../tooltip-story-interactive.source.ts | 18 - .../tooltip-story-listeners/index.ts | 3 - .../tooltip-story-listeners.component.html | 22 - .../tooltip-story-listeners.component.ts | 15 - .../tooltip-story-listeners.module.ts | 15 - .../tooltip-story-listeners.source.ts | 22 - .../_stories_/tooltip-story-theming/index.ts | 3 - .../tooltip-story-theming.component.html | 19 - .../tooltip-story-theming.component.scss | 11 - .../tooltip-story-theming.component.ts | 12 - .../tooltip-story-theming.module.ts | 15 - .../tooltip-story-theming.source.ts | 32 - .../ui/tooltip/_stories_/tooltip.stories.mdx | 176 --- projects/elonkit/src/ui/tooltip/index.ts | 1 - projects/elonkit/src/ui/tooltip/public-api.ts | 3 - .../src/ui/tooltip/tooltip.component.html | 24 - .../src/ui/tooltip/tooltip.component.scss | 62 - .../ui/tooltip/tooltip.component.theme.scss | 23 - .../src/ui/tooltip/tooltip.component.ts | 348 ------ .../src/ui/tooltip/tooltip.directive.ts | 1019 ----------------- .../elonkit/src/ui/tooltip/tooltip.module.ts | 20 - .../elonkit/src/ui/tooltip/tooltip.service.ts | 8 - 316 files changed, 47 insertions(+), 13883 deletions(-) delete mode 100644 projects/elonkit/src/ui/action-heading/__specs__/action-heading.spec.ts delete mode 100644 projects/elonkit/src/ui/action-heading/__stories__/action-heading-story-basic/action-heading-story-basic.source.ts delete mode 100644 projects/elonkit/src/ui/action-heading/__stories__/action-heading-story-basic/index.ts delete mode 100644 projects/elonkit/src/ui/action-heading/__stories__/action-heading.stories.mdx delete mode 100644 projects/elonkit/src/ui/action-heading/action-heading.component.html delete mode 100644 projects/elonkit/src/ui/action-heading/action-heading.component.scss delete mode 100644 projects/elonkit/src/ui/action-heading/action-heading.component.theme.scss delete mode 100644 projects/elonkit/src/ui/action-heading/action-heading.component.ts delete mode 100644 projects/elonkit/src/ui/action-heading/action-heading.module.ts delete mode 100644 projects/elonkit/src/ui/action-heading/heading-actions/heading-actions.component.html delete mode 100644 projects/elonkit/src/ui/action-heading/heading-actions/heading-actions.component.scss delete mode 100644 projects/elonkit/src/ui/action-heading/heading-actions/heading-actions.component.ts delete mode 100644 projects/elonkit/src/ui/action-heading/heading-breadcrumbs/heading-breadcrumbs.component.html delete mode 100644 projects/elonkit/src/ui/action-heading/heading-breadcrumbs/heading-breadcrumbs.component.scss delete mode 100644 projects/elonkit/src/ui/action-heading/heading-breadcrumbs/heading-breadcrumbs.component.ts delete mode 100644 projects/elonkit/src/ui/action-heading/heading-header/heading-header.component.html delete mode 100644 projects/elonkit/src/ui/action-heading/heading-header/heading-header.component.scss delete mode 100644 projects/elonkit/src/ui/action-heading/heading-header/heading-header.component.theme.scss delete mode 100644 projects/elonkit/src/ui/action-heading/heading-header/heading-header.component.ts delete mode 100644 projects/elonkit/src/ui/action-heading/heading-main/heading-main.component.html delete mode 100644 projects/elonkit/src/ui/action-heading/heading-main/heading-main.component.scss delete mode 100644 projects/elonkit/src/ui/action-heading/heading-main/heading-main.component.ts delete mode 100644 projects/elonkit/src/ui/action-heading/heading-status/heading-status.component.html delete mode 100644 projects/elonkit/src/ui/action-heading/heading-status/heading-status.component.scss delete mode 100644 projects/elonkit/src/ui/action-heading/heading-status/heading-status.component.ts delete mode 100644 projects/elonkit/src/ui/action-heading/index.ts delete mode 100644 projects/elonkit/src/ui/action-heading/public-api.ts delete mode 100644 projects/elonkit/src/ui/alert/__specs__/alert.spec.ts delete mode 100644 projects/elonkit/src/ui/alert/__stories__/alert-story-actions/alert-story-actions.source.ts delete mode 100644 projects/elonkit/src/ui/alert/__stories__/alert-story-actions/index.ts delete mode 100644 projects/elonkit/src/ui/alert/__stories__/alert-story-basic/alert-story-basic.source.ts delete mode 100644 projects/elonkit/src/ui/alert/__stories__/alert-story-basic/index.ts delete mode 100644 projects/elonkit/src/ui/alert/__stories__/alert-story-icon-mapping/alert-story-icon-mapping.component.ts delete mode 100644 projects/elonkit/src/ui/alert/__stories__/alert-story-icon-mapping/alert-story-icon-mapping.module.ts delete mode 100644 projects/elonkit/src/ui/alert/__stories__/alert-story-icon-mapping/alert-story-icon-mapping.source.ts delete mode 100644 projects/elonkit/src/ui/alert/__stories__/alert-story-icon-mapping/index.ts delete mode 100644 projects/elonkit/src/ui/alert/__stories__/alert.stories.mdx delete mode 100644 projects/elonkit/src/ui/alert/alert.component.html delete mode 100644 projects/elonkit/src/ui/alert/alert.component.scss delete mode 100644 projects/elonkit/src/ui/alert/alert.component.theme.scss delete mode 100644 projects/elonkit/src/ui/alert/alert.component.ts delete mode 100644 projects/elonkit/src/ui/alert/alert.module.ts delete mode 100644 projects/elonkit/src/ui/alert/alert.types.ts delete mode 100644 projects/elonkit/src/ui/alert/components/alert-actions/alert-actions.component.html delete mode 100644 projects/elonkit/src/ui/alert/components/alert-actions/alert-actions.component.scss delete mode 100644 projects/elonkit/src/ui/alert/components/alert-actions/alert-actions.component.theme.scss delete mode 100644 projects/elonkit/src/ui/alert/components/alert-actions/alert-actions.component.ts delete mode 100644 projects/elonkit/src/ui/alert/components/alert-actions/index.ts delete mode 100644 projects/elonkit/src/ui/alert/index.ts delete mode 100644 projects/elonkit/src/ui/alert/public-api.ts delete mode 100644 projects/elonkit/src/ui/audio-player/__specs__/audio-player.spec.ts delete mode 100644 projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/audio-player-story-basic.component.scss delete mode 100644 projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/audio-player-story-basic.component.ts delete mode 100644 projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/audio-player-story-basic.module.ts delete mode 100644 projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/audio-player-story-basic.source.ts delete mode 100644 projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/index.ts delete mode 100644 projects/elonkit/src/ui/audio-player/__stories__/audio-player.stories.mdx delete mode 100644 projects/elonkit/src/ui/audio-player/audio-player.component.html delete mode 100644 projects/elonkit/src/ui/audio-player/audio-player.component.scss delete mode 100644 projects/elonkit/src/ui/audio-player/audio-player.component.theme.scss delete mode 100644 projects/elonkit/src/ui/audio-player/audio-player.component.ts delete mode 100644 projects/elonkit/src/ui/audio-player/audio-player.module.ts delete mode 100644 projects/elonkit/src/ui/audio-player/components/audio-player-options/audio-player-options.component.html delete mode 100644 projects/elonkit/src/ui/audio-player/components/audio-player-options/audio-player-options.component.scss delete mode 100644 projects/elonkit/src/ui/audio-player/components/audio-player-options/audio-player-options.component.theme.scss delete mode 100644 projects/elonkit/src/ui/audio-player/components/audio-player-options/audio-player-options.component.ts delete mode 100644 projects/elonkit/src/ui/audio-player/components/audio-player-options/index.ts delete mode 100644 projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/audio-player-time-slider.component.html delete mode 100644 projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/audio-player-time-slider.component.scss delete mode 100644 projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/audio-player-time-slider.component.theme.scss delete mode 100644 projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/audio-player-time-slider.component.ts delete mode 100644 projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/index.ts delete mode 100644 projects/elonkit/src/ui/audio-player/components/audio-player-volume/audio-player-volume.component.html delete mode 100644 projects/elonkit/src/ui/audio-player/components/audio-player-volume/audio-player-volume.component.scss delete mode 100644 projects/elonkit/src/ui/audio-player/components/audio-player-volume/audio-player-volume.component.theme.scss delete mode 100644 projects/elonkit/src/ui/audio-player/components/audio-player-volume/audio-player-volume.component.ts delete mode 100644 projects/elonkit/src/ui/audio-player/components/audio-player-volume/index.ts delete mode 100644 projects/elonkit/src/ui/audio-player/index.ts delete mode 100644 projects/elonkit/src/ui/audio-player/public-api.ts delete mode 100644 projects/elonkit/src/ui/autocomplete-multiple/__specs__/autocomplete-multiple.spec.ts delete mode 100644 projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.component.scss delete mode 100644 projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.component.ts delete mode 100644 projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.module.ts delete mode 100644 projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.service.ts delete mode 100644 projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.source.ts delete mode 100644 projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/index.ts delete mode 100644 projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple.stories.mdx delete mode 100644 projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.animations.ts delete mode 100644 projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.component.html delete mode 100644 projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.component.scss delete mode 100644 projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.component.ts delete mode 100644 projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.module.ts delete mode 100644 projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.theme.scss delete mode 100644 projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.types.ts delete mode 100644 projects/elonkit/src/ui/autocomplete-multiple/index.ts delete mode 100644 projects/elonkit/src/ui/autocomplete-multiple/public-api.ts delete mode 100644 projects/elonkit/src/ui/avatar/__specs__/avatar.spec.ts delete mode 100644 projects/elonkit/src/ui/avatar/__stories__/avatar-story-group/avatar-story-group.source.ts delete mode 100644 projects/elonkit/src/ui/avatar/__stories__/avatar-story-group/index.ts delete mode 100644 projects/elonkit/src/ui/avatar/__stories__/avatar-story-image/avatar-story-image.source.ts delete mode 100644 projects/elonkit/src/ui/avatar/__stories__/avatar-story-image/index.ts delete mode 100644 projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-icon/avatar-story-no-image-icon.source.ts delete mode 100644 projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-icon/index.ts delete mode 100644 projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-typography/avatar-story-no-image-typography.source.ts delete mode 100644 projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-typography/index.ts delete mode 100644 projects/elonkit/src/ui/avatar/__stories__/avatar.stories.mdx delete mode 100644 projects/elonkit/src/ui/avatar/avatar-group.component.html delete mode 100644 projects/elonkit/src/ui/avatar/avatar-group.component.scss delete mode 100644 projects/elonkit/src/ui/avatar/avatar-group.component.theme.scss delete mode 100644 projects/elonkit/src/ui/avatar/avatar-group.component.ts delete mode 100644 projects/elonkit/src/ui/avatar/avatar.component.html delete mode 100644 projects/elonkit/src/ui/avatar/avatar.component.scss delete mode 100644 projects/elonkit/src/ui/avatar/avatar.component.theme.scss delete mode 100644 projects/elonkit/src/ui/avatar/avatar.component.ts delete mode 100644 projects/elonkit/src/ui/avatar/avatar.module.ts delete mode 100644 projects/elonkit/src/ui/avatar/avatar.types.ts delete mode 100644 projects/elonkit/src/ui/avatar/index.ts delete mode 100644 projects/elonkit/src/ui/avatar/public-api.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/__specs__/breadcrumbs.spec.resolver.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/__specs__/breadcrumbs.spec.routes.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/__specs__/breadcrumbs.spec.service.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/__specs__/breadcrumbs.spec.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.component.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.module.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.resolver.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.service.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.source.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/index.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/breadcrumbs-story-customization.component.scss delete mode 100644 projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/breadcrumbs-story-customization.component.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/breadcrumbs-story-customization.module.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/breadcrumbs-story-customization.source.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/index.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs.stories.mdx delete mode 100644 projects/elonkit/src/ui/breadcrumbs/breadcrumbs.component.html delete mode 100644 projects/elonkit/src/ui/breadcrumbs/breadcrumbs.component.scss delete mode 100644 projects/elonkit/src/ui/breadcrumbs/breadcrumbs.component.theme.scss delete mode 100644 projects/elonkit/src/ui/breadcrumbs/breadcrumbs.component.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/breadcrumbs.module.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/breadcrumbs.resolver.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/breadcrumbs.service.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/breadcrumbs.types.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/breadcrumbs-breadcrumb.component.html delete mode 100644 projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/breadcrumbs-breadcrumb.component.scss delete mode 100644 projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/breadcrumbs-breadcrumb.component.theme.scss delete mode 100644 projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/breadcrumbs-breadcrumb.component.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/index.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/breadcrumbs-collapse.component.html delete mode 100644 projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/breadcrumbs-collapse.component.scss delete mode 100644 projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/breadcrumbs-collapse.component.theme.scss delete mode 100644 projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/breadcrumbs-collapse.component.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/index.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/directives/breadcrumbs-back.directive.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/directives/breadcrumbs-more.directive.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/directives/breadcrumbs-separator.directive.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/index.ts delete mode 100644 projects/elonkit/src/ui/breadcrumbs/public-api.ts delete mode 100644 projects/elonkit/src/ui/dropzone/__specs__/dropzone.spec.ts delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.component.html delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.component.scss delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.component.ts delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.module.ts delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.source.ts delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/index.ts delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.component.html delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.component.scss delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.component.ts delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.module.ts delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.source.ts delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/index.ts delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.component.html delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.component.scss delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.component.ts delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.module.ts delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.source.ts delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/index.ts delete mode 100644 projects/elonkit/src/ui/dropzone/__stories__/dropzone.stories.mdx delete mode 100644 projects/elonkit/src/ui/dropzone/dropzone.component.html delete mode 100644 projects/elonkit/src/ui/dropzone/dropzone.component.scss delete mode 100644 projects/elonkit/src/ui/dropzone/dropzone.component.theme.scss delete mode 100644 projects/elonkit/src/ui/dropzone/dropzone.component.ts delete mode 100644 projects/elonkit/src/ui/dropzone/dropzone.module.ts delete mode 100644 projects/elonkit/src/ui/dropzone/dropzones.types.ts delete mode 100644 projects/elonkit/src/ui/dropzone/index.ts delete mode 100644 projects/elonkit/src/ui/dropzone/public-api.ts delete mode 100644 projects/elonkit/src/ui/empty-state/__specs__/empty-state.spec.ts delete mode 100644 projects/elonkit/src/ui/empty-state/__stories__/empty-state-story-basic/empty-state-story-basic.source.ts delete mode 100644 projects/elonkit/src/ui/empty-state/__stories__/empty-state-story-basic/index.ts delete mode 100644 projects/elonkit/src/ui/empty-state/__stories__/empty-state-story-button/empty-state-story-button.source.ts delete mode 100644 projects/elonkit/src/ui/empty-state/__stories__/empty-state-story-button/index.ts delete mode 100644 projects/elonkit/src/ui/empty-state/__stories__/empty-state.stories.mdx delete mode 100644 projects/elonkit/src/ui/empty-state/empty-state.component.html delete mode 100644 projects/elonkit/src/ui/empty-state/empty-state.component.scss delete mode 100644 projects/elonkit/src/ui/empty-state/empty-state.component.theme.scss delete mode 100644 projects/elonkit/src/ui/empty-state/empty-state.component.ts delete mode 100644 projects/elonkit/src/ui/empty-state/empty-state.module.ts delete mode 100644 projects/elonkit/src/ui/empty-state/empty-state.types.ts delete mode 100644 projects/elonkit/src/ui/empty-state/index.ts delete mode 100644 projects/elonkit/src/ui/empty-state/public-api.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__specs__/inline-form-field.spec.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/index.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/inline-form-field-story-basic.component.html delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/inline-form-field-story-basic.component.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/inline-form-field-story-basic.module.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/inline-form-field-story-basic.source.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/index.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.component.html delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.component.scss delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.component.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.module.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.source.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/index.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/inline-form-field-story-typography.component.html delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/inline-form-field-story-typography.component.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/inline-form-field-story-typography.module.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/inline-form-field-story-typography.source.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/index.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.component.html delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.component.scss delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.component.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.module.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.source.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field.stories.mdx delete mode 100644 projects/elonkit/src/ui/inline-form-field/index.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/inline-form-field.component.html delete mode 100644 projects/elonkit/src/ui/inline-form-field/inline-form-field.component.scss delete mode 100644 projects/elonkit/src/ui/inline-form-field/inline-form-field.component.theme.scss delete mode 100644 projects/elonkit/src/ui/inline-form-field/inline-form-field.component.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/inline-form-field.module.ts delete mode 100644 projects/elonkit/src/ui/inline-form-field/public-api.ts delete mode 100644 projects/elonkit/src/ui/paginator/__specs__/paginator.spec.ts delete mode 100644 projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/index.ts delete mode 100644 projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/paginator-story-basic.component.html delete mode 100644 projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/paginator-story-basic.component.ts delete mode 100644 projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/paginator-story-basic.module.ts delete mode 100644 projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/paginator-story-basic.source.ts delete mode 100644 projects/elonkit/src/ui/paginator/__stories__/paginator-story-page-size-options/index.ts delete mode 100644 projects/elonkit/src/ui/paginator/__stories__/paginator-story-page-size-options/paginator-story-page-size-options.source.ts delete mode 100644 projects/elonkit/src/ui/paginator/__stories__/paginator.stories.mdx delete mode 100644 projects/elonkit/src/ui/paginator/index.ts delete mode 100644 projects/elonkit/src/ui/paginator/paginator.component.html delete mode 100644 projects/elonkit/src/ui/paginator/paginator.component.scss delete mode 100644 projects/elonkit/src/ui/paginator/paginator.component.theme.scss delete mode 100644 projects/elonkit/src/ui/paginator/paginator.component.ts delete mode 100644 projects/elonkit/src/ui/paginator/paginator.module.ts delete mode 100644 projects/elonkit/src/ui/paginator/public-api.ts delete mode 100644 projects/elonkit/src/ui/surface/surface.component.theme.scss delete mode 100644 projects/elonkit/src/ui/surface/surface.source.ts delete mode 100644 projects/elonkit/src/ui/surface/surface.stories.mdx delete mode 100644 projects/elonkit/src/ui/timepicker/__specs__/timepicker.spec.ts delete mode 100644 projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/index.ts delete mode 100644 projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/timepicker-story-basic.component.html delete mode 100644 projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/timepicker-story-basic.component.ts delete mode 100644 projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/timepicker-story-basic.module.ts delete mode 100644 projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/timepicker-story-basic.source.ts delete mode 100644 projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/index.ts delete mode 100644 projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/timepicker-story-required.component.html delete mode 100644 projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/timepicker-story-required.component.ts delete mode 100644 projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/timepicker-story-required.module.ts delete mode 100644 projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/timepicker-story-required.source.ts delete mode 100644 projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/index.ts delete mode 100644 projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/timepicker-story-seconds.component.html delete mode 100644 projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/timepicker-story-seconds.component.ts delete mode 100644 projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/timepicker-story-seconds.module.ts delete mode 100644 projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/timepicker-story-seconds.story.ts delete mode 100644 projects/elonkit/src/ui/timepicker/__stories__/timepicker.stories.mdx delete mode 100644 projects/elonkit/src/ui/timepicker/index.ts delete mode 100644 projects/elonkit/src/ui/timepicker/public-api.ts delete mode 100644 projects/elonkit/src/ui/timepicker/timepicker.component.html delete mode 100644 projects/elonkit/src/ui/timepicker/timepicker.component.ts delete mode 100644 projects/elonkit/src/ui/timepicker/timepicker.module.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_specs_/tooltip.spec.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/index.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/tooltip-story-basic.component.html delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/tooltip-story-basic.component.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/tooltip-story-basic.module.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/tooltip-story-basic.source.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/index.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/tooltip-story-interactive.component.html delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/tooltip-story-interactive.component.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/tooltip-story-interactive.module.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/tooltip-story-interactive.source.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/index.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/tooltip-story-listeners.component.html delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/tooltip-story-listeners.component.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/tooltip-story-listeners.module.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/tooltip-story-listeners.source.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/index.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.component.html delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.component.scss delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.component.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.module.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.source.ts delete mode 100644 projects/elonkit/src/ui/tooltip/_stories_/tooltip.stories.mdx delete mode 100644 projects/elonkit/src/ui/tooltip/index.ts delete mode 100644 projects/elonkit/src/ui/tooltip/public-api.ts delete mode 100644 projects/elonkit/src/ui/tooltip/tooltip.component.html delete mode 100644 projects/elonkit/src/ui/tooltip/tooltip.component.scss delete mode 100644 projects/elonkit/src/ui/tooltip/tooltip.component.theme.scss delete mode 100644 projects/elonkit/src/ui/tooltip/tooltip.component.ts delete mode 100644 projects/elonkit/src/ui/tooltip/tooltip.directive.ts delete mode 100644 projects/elonkit/src/ui/tooltip/tooltip.module.ts delete mode 100644 projects/elonkit/src/ui/tooltip/tooltip.service.ts diff --git a/.eslintrc.json b/.eslintrc.json index 6b2264e..13f803d 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -10,7 +10,26 @@ "plugin:@angular-eslint/recommended", "plugin:@angular-eslint/template/process-inline-templates" ], + "parserOptions": { + "sourceType": "module", + "ecmaVersion": "latest" + }, + "plugins": ["simple-import-sort"], "rules": { + "simple-import-sort/imports": [ + "error", + { + "groups": [ + ["^@angular", "^rxjs"], + ["^.+\\.types$"], + ["^@angular/material"], + ["^@angular/cdk"], + ["^\\./(?=.*/)(?!/?$)", "^\\.(?!/?$)", "^\\./?$"], + ["^\\.\\.(?!/?$)", "^\\.\\./?$"] + ] + } + ], + "simple-import-sort/exports": "error", "@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/no-empty-function": "off", "@angular-eslint/directive-selector": [ diff --git a/package-lock.json b/package-lock.json index b74327e..e410f7b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -61,6 +61,7 @@ "eslint": "^8.51.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-simple-import-sort": "^12.1.0", "jest": "^29.7.0", "jest-preset-angular": "^14.0.0", "ng-packagr": "^16.2.0", @@ -16536,6 +16537,15 @@ } } }, + "node_modules/eslint-plugin-simple-import-sort": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.0.tgz", + "integrity": "sha512-Y2fqAfC11TcG/WP3TrI1Gi3p3nc8XJyEOJYHyEPEGI/UAgNx6akxxlX74p7SbAQdLcgASKhj8M0GKvH3vq/+ig==", + "dev": true, + "peerDependencies": { + "eslint": ">=5.0.0" + } + }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", diff --git a/package.json b/package.json index 2f67a16..a3c6567 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "prettier:check": "prettier --check .", "prettier:write": "prettier --write .", "lint": "ng lint", + "lint-fix": "ng lint --fix", "lint:stylelint": "npx stylelint \"**/*.scss\"", "lint:stylelint-fix": "npx stylelint \"**/*.scss\" --fix" }, @@ -71,6 +72,7 @@ "eslint": "^8.51.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-simple-import-sort": "^12.1.0", "jest": "^29.7.0", "jest-preset-angular": "^14.0.0", "ng-packagr": "^16.2.0", diff --git a/projects/elonkit/src/cdk/a11y/public-api.ts b/projects/elonkit/src/cdk/a11y/public-api.ts index 419427e..805e96d 100644 --- a/projects/elonkit/src/cdk/a11y/public-api.ts +++ b/projects/elonkit/src/cdk/a11y/public-api.ts @@ -1 +1 @@ -export { FOCUSABLE, getInnerFocusableElement, getPrevFocusableElement, getNextFocusableElement } from './focusable'; +export { FOCUSABLE, getInnerFocusableElement, getNextFocusableElement, getPrevFocusableElement } from './focusable'; diff --git a/projects/elonkit/src/public-api.ts b/projects/elonkit/src/public-api.ts index 0f3bc8b..4497080 100644 --- a/projects/elonkit/src/public-api.ts +++ b/projects/elonkit/src/public-api.ts @@ -1,18 +1,6 @@ /* * Public API Surface of elonkit */ -export * from './ui/action-heading'; -export * from './ui/alert'; -export * from './ui/audio-player'; -export * from './ui/autocomplete-multiple'; -export * from './ui/avatar'; -export * from './ui/breadcrumbs'; -export * from './ui/dropzone'; -export * from './ui/empty-state'; -export * from './ui/inline-form-field'; -export * from './ui/paginator'; -export * from './ui/timepicker'; -export * from './ui/tooltip'; - export * from './ui/icons'; export * from './ui/locale'; + diff --git a/projects/elonkit/src/ui/action-heading/__specs__/action-heading.spec.ts b/projects/elonkit/src/ui/action-heading/__specs__/action-heading.spec.ts deleted file mode 100644 index 9f4ec88..0000000 --- a/projects/elonkit/src/ui/action-heading/__specs__/action-heading.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { ESActionHeadingComponent } from '../action-heading.component'; -import { ESActionHeadingModule } from '../action-heading.module'; -import { render } from '@testing-library/angular'; - -describe('ActionHeading', () => { - it('Should render component with title', async () => { - const { getByText } = await render(ESActionHeadingComponent, { - componentProperties: { - text: 'ActionHeading', - }, - imports: [ESActionHeadingModule], - excludeComponentDeclaration: true, - }); - - expect(getByText('ActionHeading')).toBeInTheDocument(); - }); -}); diff --git a/projects/elonkit/src/ui/action-heading/__stories__/action-heading-story-basic/action-heading-story-basic.source.ts b/projects/elonkit/src/ui/action-heading/__stories__/action-heading-story-basic/action-heading-story-basic.source.ts deleted file mode 100644 index cc02b81..0000000 --- a/projects/elonkit/src/ui/action-heading/__stories__/action-heading-story-basic/action-heading-story-basic.source.ts +++ /dev/null @@ -1,19 +0,0 @@ -export const ACTION_HEADING_STORY_BASIC_SOURCE = { - html: ` - - You / Can / Put / Here / Breadcrumbs - - - Lorem ipsum dolor sit amet consectetur adipisicing elit. - - - - - - - - Status: online - - `, -}; diff --git a/projects/elonkit/src/ui/action-heading/__stories__/action-heading-story-basic/index.ts b/projects/elonkit/src/ui/action-heading/__stories__/action-heading-story-basic/index.ts deleted file mode 100644 index e200c6d..0000000 --- a/projects/elonkit/src/ui/action-heading/__stories__/action-heading-story-basic/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { ACTION_HEADING_STORY_BASIC_SOURCE } from './action-heading-story-basic.source'; diff --git a/projects/elonkit/src/ui/action-heading/__stories__/action-heading.stories.mdx b/projects/elonkit/src/ui/action-heading/__stories__/action-heading.stories.mdx deleted file mode 100644 index a2a1578..0000000 --- a/projects/elonkit/src/ui/action-heading/__stories__/action-heading.stories.mdx +++ /dev/null @@ -1,99 +0,0 @@ -import { Meta, Story, ArgsTable } from '@storybook/addon-docs'; -import { Canvas } from '~storybook/components'; - -import { action } from '@storybook/addon-actions'; -import { MatButtonModule, MatButton } from '@angular/material/button'; - -import { - ESActionHeadingModule, - ESActionHeadingComponent, - ESHeadingBreadcrumbsComponent, - ESHeadingMainComponent, - ESHeadingHeaderComponent, - ESHeadingActionsComponent, - ESHeadingStatusComponent, -} from '..'; - -import { ACTION_HEADING_STORY_BASIC_SOURCE } from './action-heading-story-basic'; - - - -# Action Heading - -The action heading component. - -## Demos - -export const getText = (args, context) => { - return args.text || (context.globals.locale === 'en' ? 'Title' : 'Заголовок'); -}; - - - - {((args, context) => ({ - template: ` - - You / Can / Put / Here / Breadcrumbs - - {{ text }} - - - - - - - Status: online - - `, - moduleMetadata: { - imports: [ESActionHeadingModule, MatButtonModule], - }, - props: { - ...args, - text: getText(args, context), - }, - })).bind({})} - - - -## API - - - -## Constants - -Injection token that can be used to configure the default options for all components within an app. - -```ts -import { ES_HEADER_DEFAULT_OPTIONS } from '@elonkit/angular/ui/action-heading'; -@NgModule({ - providers: [ - { - provide: ES_HEADER_DEFAULT_OPTIONS, - useValue: { - typography: 'es-h4'; - maxLines: 1; - } - } - ] -}) -``` diff --git a/projects/elonkit/src/ui/action-heading/action-heading.component.html b/projects/elonkit/src/ui/action-heading/action-heading.component.html deleted file mode 100644 index d11dec0..0000000 --- a/projects/elonkit/src/ui/action-heading/action-heading.component.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/projects/elonkit/src/ui/action-heading/action-heading.component.scss b/projects/elonkit/src/ui/action-heading/action-heading.component.scss deleted file mode 100644 index 1e2f38c..0000000 --- a/projects/elonkit/src/ui/action-heading/action-heading.component.scss +++ /dev/null @@ -1,4 +0,0 @@ -.es-action-heading { - width: 100%; - padding: 28px 0 24px; -} diff --git a/projects/elonkit/src/ui/action-heading/action-heading.component.theme.scss b/projects/elonkit/src/ui/action-heading/action-heading.component.theme.scss deleted file mode 100644 index e9e7311..0000000 --- a/projects/elonkit/src/ui/action-heading/action-heading.component.theme.scss +++ /dev/null @@ -1,13 +0,0 @@ -@import './heading-header/heading-header.component.theme'; -@mixin es-action-heading-theme($theme, $elonkit-theme) { - @include es-heading-header-theme($theme, $elonkit-theme); - $mono-a: map-get($elonkit-theme, mono-a); - $mono-b: map-get($elonkit-theme, mono-b); - $primary: map-get($theme, primary); - - .es-action-heading { - &__title { - color: mat.get-color-from-palette($mono-a, A900); - } - } -} diff --git a/projects/elonkit/src/ui/action-heading/action-heading.component.ts b/projects/elonkit/src/ui/action-heading/action-heading.component.ts deleted file mode 100644 index 667f3ef..0000000 --- a/projects/elonkit/src/ui/action-heading/action-heading.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core'; - -@Component({ - selector: 'es-action-heading', - templateUrl: './action-heading.component.html', - styleUrls: ['./action-heading.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class ESActionHeadingComponent {} diff --git a/projects/elonkit/src/ui/action-heading/action-heading.module.ts b/projects/elonkit/src/ui/action-heading/action-heading.module.ts deleted file mode 100644 index dfe6852..0000000 --- a/projects/elonkit/src/ui/action-heading/action-heading.module.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { ESActionHeadingComponent } from './action-heading.component'; -import { MatIconModule } from '@angular/material/icon'; -import { MatButtonModule } from '@angular/material/button'; -import { ESHeadingActionsComponent } from './heading-actions/heading-actions.component'; -import { ESHeadingMainComponent } from './heading-main/heading-main.component'; -import { ESHeadingHeaderComponent } from './heading-header/heading-header.component'; -import { ESHeadingStatusComponent } from './heading-status/heading-status.component'; -import { ESHeadingBreadcrumbsComponent } from './heading-breadcrumbs/heading-breadcrumbs.component'; - -@NgModule({ - imports: [CommonModule], - declarations: [ - ESActionHeadingComponent, - ESHeadingBreadcrumbsComponent, - ESHeadingMainComponent, - ESHeadingHeaderComponent, - ESHeadingActionsComponent, - ESHeadingStatusComponent, - ], - exports: [ - ESActionHeadingComponent, - ESHeadingBreadcrumbsComponent, - ESHeadingMainComponent, - ESHeadingHeaderComponent, - ESHeadingActionsComponent, - ESHeadingStatusComponent, - ], -}) -export class ESActionHeadingModule {} diff --git a/projects/elonkit/src/ui/action-heading/heading-actions/heading-actions.component.html b/projects/elonkit/src/ui/action-heading/heading-actions/heading-actions.component.html deleted file mode 100644 index f33a57c..0000000 --- a/projects/elonkit/src/ui/action-heading/heading-actions/heading-actions.component.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/projects/elonkit/src/ui/action-heading/heading-actions/heading-actions.component.scss b/projects/elonkit/src/ui/action-heading/heading-actions/heading-actions.component.scss deleted file mode 100644 index 6e93a0f..0000000 --- a/projects/elonkit/src/ui/action-heading/heading-actions/heading-actions.component.scss +++ /dev/null @@ -1,4 +0,0 @@ -.es-heading-actions { - display: flex; - gap: 16px; -} diff --git a/projects/elonkit/src/ui/action-heading/heading-actions/heading-actions.component.ts b/projects/elonkit/src/ui/action-heading/heading-actions/heading-actions.component.ts deleted file mode 100644 index 5cfc02d..0000000 --- a/projects/elonkit/src/ui/action-heading/heading-actions/heading-actions.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core'; - -@Component({ - selector: 'es-heading-actions', - templateUrl: './heading-actions.component.html', - styleUrls: ['./heading-actions.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class ESHeadingActionsComponent {} diff --git a/projects/elonkit/src/ui/action-heading/heading-breadcrumbs/heading-breadcrumbs.component.html b/projects/elonkit/src/ui/action-heading/heading-breadcrumbs/heading-breadcrumbs.component.html deleted file mode 100644 index 5958da5..0000000 --- a/projects/elonkit/src/ui/action-heading/heading-breadcrumbs/heading-breadcrumbs.component.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/projects/elonkit/src/ui/action-heading/heading-breadcrumbs/heading-breadcrumbs.component.scss b/projects/elonkit/src/ui/action-heading/heading-breadcrumbs/heading-breadcrumbs.component.scss deleted file mode 100644 index d8676b6..0000000 --- a/projects/elonkit/src/ui/action-heading/heading-breadcrumbs/heading-breadcrumbs.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.es-heading-breadcrumbs { - padding: 4px 0; -} diff --git a/projects/elonkit/src/ui/action-heading/heading-breadcrumbs/heading-breadcrumbs.component.ts b/projects/elonkit/src/ui/action-heading/heading-breadcrumbs/heading-breadcrumbs.component.ts deleted file mode 100644 index b9b0f33..0000000 --- a/projects/elonkit/src/ui/action-heading/heading-breadcrumbs/heading-breadcrumbs.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core'; - -@Component({ - selector: 'es-heading-breadcrumbs', - templateUrl: './heading-breadcrumbs.component.html', - styleUrls: ['./heading-breadcrumbs.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class ESHeadingBreadcrumbsComponent {} diff --git a/projects/elonkit/src/ui/action-heading/heading-header/heading-header.component.html b/projects/elonkit/src/ui/action-heading/heading-header/heading-header.component.html deleted file mode 100644 index 372d09f..0000000 --- a/projects/elonkit/src/ui/action-heading/heading-header/heading-header.component.html +++ /dev/null @@ -1,5 +0,0 @@ -

- - - -

diff --git a/projects/elonkit/src/ui/action-heading/heading-header/heading-header.component.scss b/projects/elonkit/src/ui/action-heading/heading-header/heading-header.component.scss deleted file mode 100644 index cd6b2c7..0000000 --- a/projects/elonkit/src/ui/action-heading/heading-header/heading-header.component.scss +++ /dev/null @@ -1,13 +0,0 @@ -.es-heading-header { - align-self: center; - padding: 0; - margin: 0; - word-break: break-word; - min-width: 0; - &__wrapper { - overflow: hidden; - text-overflow: ellipsis; - display: -webkit-box; - -webkit-box-orient: vertical; - } -} diff --git a/projects/elonkit/src/ui/action-heading/heading-header/heading-header.component.theme.scss b/projects/elonkit/src/ui/action-heading/heading-header/heading-header.component.theme.scss deleted file mode 100644 index ad0d0bf..0000000 --- a/projects/elonkit/src/ui/action-heading/heading-header/heading-header.component.theme.scss +++ /dev/null @@ -1,7 +0,0 @@ -@mixin es-heading-header-theme($theme, $elonkit-theme) { - $mono-a: map-get($elonkit-theme, mono-a); - - .es-heading-header { - color: mat.get-color-from-palette($mono-a, A900); - } -} diff --git a/projects/elonkit/src/ui/action-heading/heading-header/heading-header.component.ts b/projects/elonkit/src/ui/action-heading/heading-header/heading-header.component.ts deleted file mode 100644 index 89200c3..0000000 --- a/projects/elonkit/src/ui/action-heading/heading-header/heading-header.component.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Component, ChangeDetectionStrategy, ViewEncapsulation, Input, InjectionToken, Optional, Inject } from '@angular/core'; - -export interface ESHeaderDefaultOptions { - typography?: string; - maxLines?: number; -} - -const DEFAULT_MAX_LINES = 1; -const DEFAULT_TYPOGRAPHY = 'es-h2'; - -export const ES_HEADER_DEFAULT_OPTIONS = new InjectionToken('ES_HEADER_DEFAULT_OPTIONS'); -@Component({ - selector: 'es-heading-header', - templateUrl: './heading-header.component.html', - styleUrls: ['./heading-header.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class ESHeadingHeaderComponent { - private _maxLines: number; - - /** - * Set max lines in header. - */ - @Input() - public get maxLines(): number { - return this._maxLines; - } - public set maxLines(value: number) { - this._maxLines = value || (this.defaultOptions && this.defaultOptions.maxLines) || DEFAULT_MAX_LINES; - } - - private _typography: string; - - /** - * Class applied to text. - */ - @Input() - public get typography(): string { - return this._typography; - } - public set typography(value: string) { - this._typography = value || (this.defaultOptions && this.defaultOptions.typography) || DEFAULT_TYPOGRAPHY; - } - - constructor( - /** - * @internal - */ - @Optional() - @Inject(ES_HEADER_DEFAULT_OPTIONS) - private defaultOptions: ESHeaderDefaultOptions - ) { - this.typography = (defaultOptions && defaultOptions.typography) || DEFAULT_TYPOGRAPHY; - - this.maxLines = (defaultOptions && defaultOptions.maxLines) || DEFAULT_MAX_LINES; - } -} diff --git a/projects/elonkit/src/ui/action-heading/heading-main/heading-main.component.html b/projects/elonkit/src/ui/action-heading/heading-main/heading-main.component.html deleted file mode 100644 index 2909a06..0000000 --- a/projects/elonkit/src/ui/action-heading/heading-main/heading-main.component.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/projects/elonkit/src/ui/action-heading/heading-main/heading-main.component.scss b/projects/elonkit/src/ui/action-heading/heading-main/heading-main.component.scss deleted file mode 100644 index f8abec2..0000000 --- a/projects/elonkit/src/ui/action-heading/heading-main/heading-main.component.scss +++ /dev/null @@ -1,8 +0,0 @@ -.es-heading-main { - padding: 4px 0 8px; - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: flex-start; - gap: 24px; -} diff --git a/projects/elonkit/src/ui/action-heading/heading-main/heading-main.component.ts b/projects/elonkit/src/ui/action-heading/heading-main/heading-main.component.ts deleted file mode 100644 index b4e654f..0000000 --- a/projects/elonkit/src/ui/action-heading/heading-main/heading-main.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core'; - -@Component({ - selector: 'es-heading-main', - templateUrl: './heading-main.component.html', - styleUrls: ['./heading-main.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class ESHeadingMainComponent {} diff --git a/projects/elonkit/src/ui/action-heading/heading-status/heading-status.component.html b/projects/elonkit/src/ui/action-heading/heading-status/heading-status.component.html deleted file mode 100644 index 0226ff8..0000000 --- a/projects/elonkit/src/ui/action-heading/heading-status/heading-status.component.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/projects/elonkit/src/ui/action-heading/heading-status/heading-status.component.scss b/projects/elonkit/src/ui/action-heading/heading-status/heading-status.component.scss deleted file mode 100644 index edba438..0000000 --- a/projects/elonkit/src/ui/action-heading/heading-status/heading-status.component.scss +++ /dev/null @@ -1,4 +0,0 @@ -.es-heading-status { - // @include typography(body100); - // color: map-get($theme-palette-monoA, A600); -} diff --git a/projects/elonkit/src/ui/action-heading/heading-status/heading-status.component.ts b/projects/elonkit/src/ui/action-heading/heading-status/heading-status.component.ts deleted file mode 100644 index fa019b3..0000000 --- a/projects/elonkit/src/ui/action-heading/heading-status/heading-status.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core'; - -@Component({ - selector: 'es-heading-status', - templateUrl: './heading-status.component.html', - styleUrls: ['./heading-status.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class ESHeadingStatusComponent {} diff --git a/projects/elonkit/src/ui/action-heading/index.ts b/projects/elonkit/src/ui/action-heading/index.ts deleted file mode 100644 index 7e1a213..0000000 --- a/projects/elonkit/src/ui/action-heading/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './public-api'; diff --git a/projects/elonkit/src/ui/action-heading/public-api.ts b/projects/elonkit/src/ui/action-heading/public-api.ts deleted file mode 100644 index 9aa6ed2..0000000 --- a/projects/elonkit/src/ui/action-heading/public-api.ts +++ /dev/null @@ -1,7 +0,0 @@ -export { ESActionHeadingComponent } from './action-heading.component'; -export { ESHeadingMainComponent } from './heading-main/heading-main.component'; -export { ESHeadingBreadcrumbsComponent } from './heading-breadcrumbs/heading-breadcrumbs.component'; -export { ESHeadingHeaderComponent } from './heading-header/heading-header.component'; -export { ESHeadingActionsComponent } from './heading-actions/heading-actions.component'; -export { ESHeadingStatusComponent } from './heading-status/heading-status.component'; -export { ESActionHeadingModule } from './action-heading.module'; diff --git a/projects/elonkit/src/ui/alert/__specs__/alert.spec.ts b/projects/elonkit/src/ui/alert/__specs__/alert.spec.ts deleted file mode 100644 index 7a969b3..0000000 --- a/projects/elonkit/src/ui/alert/__specs__/alert.spec.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { Component } from '@angular/core'; -import { MatIconTestingModule } from '@angular/material/icon/testing'; - -import { fireEvent, render, screen } from '@testing-library/angular'; - -import { ESAlertComponent, ESAlertModule, ESAlertVariant } from '..'; -import { en, ESLocaleService, ru } from '../../locale'; - -@Component({ - template: ` - - Title - Message - - `, -}) -class AlertTypographyWrapperComponent {} - -describe('Alert', () => { - it('Should change styles based on variant', async () => { - const component = await render(ESAlertComponent, { - imports: [ESAlertModule], - excludeComponentDeclaration: true, - }); - - for (const variant of ['default', 'info', 'success', 'warning', 'error'] as ESAlertVariant[]) { - component.fixture.componentInstance.variant = variant; - component.fixture.componentInstance.changeDetector.detectChanges(); - - expect(screen.getByTestId('root')).toHaveClass(`es-alert_variant_${variant}`); - } - }); - - it('Should display correct icon', async () => { - const component = await render(ESAlertComponent, { - imports: [ESAlertModule, MatIconTestingModule], - excludeComponentDeclaration: true, - }); - - component.fixture.componentInstance.variant = 'default'; - component.fixture.componentInstance.changeDetector.detectChanges(); - expect(component.fixture.componentInstance.currentIcon).toEqual({ icon: 'info' }); - - component.fixture.componentInstance.variant = 'info'; - component.fixture.componentInstance.changeDetector.detectChanges(); - expect(component.fixture.componentInstance.currentIcon).toEqual({ icon: 'info' }); - - component.fixture.componentInstance.variant = 'success'; - component.fixture.componentInstance.changeDetector.detectChanges(); - expect(component.fixture.componentInstance.currentIcon).toEqual({ icon: 'check_circle' }); - - component.fixture.componentInstance.variant = 'warning'; - component.fixture.componentInstance.changeDetector.detectChanges(); - expect(component.fixture.componentInstance.currentIcon).toEqual({ icon: 'warning' }); - - component.fixture.componentInstance.variant = 'error'; - component.fixture.componentInstance.changeDetector.detectChanges(); - expect(component.fixture.componentInstance.currentIcon).toEqual({ icon: 'error' }); - - component.fixture.componentInstance.icon = 'new_releases'; - component.fixture.componentInstance.changeDetector.detectChanges(); - expect(component.fixture.componentInstance.currentIcon).toEqual({ icon: 'new_releases' }); - - component.fixture.componentInstance.icon = undefined; - component.fixture.componentInstance.svgIcon = 'account'; - component.fixture.componentInstance.changeDetector.detectChanges(); - expect(component.fixture.componentInstance.currentIcon).toEqual({ svgIcon: 'account' }); - }); - - it('Should emit close event', async () => { - const onClose = jest.fn(); - - await render(ESAlertComponent, { - imports: [ESAlertModule], - componentProperties: { - closable: true, - closed: { emit: onClose } as any, - }, - excludeComponentDeclaration: true, - }); - - fireEvent.click(screen.getByLabelText(en.alert.labelClose)); - expect(onClose).toBeCalled(); - }); - - it('Should change locale', async () => { - const localeService = new ESLocaleService(); - localeService.register('ru', ru); - localeService.use('ru'); - - await render(ESAlertComponent, { - imports: [ESAlertModule], - componentProperties: { - closable: true, - }, - providers: [{ provide: ESLocaleService, useValue: localeService }], - excludeComponentDeclaration: true, - }); - - expect(screen.queryByLabelText(ru.alert.labelClose)).not.toBeNull(); - }); - - it('Should accept typography class', async () => { - await render(AlertTypographyWrapperComponent, { - imports: [ESAlertModule], - componentProperties: { - typography: 'app-body-1', - }, - }); - - expect(screen.getByText('Message')).toHaveClass('app-body-1'); - }); - - it('Should accept title typography class', async () => { - await render(AlertTypographyWrapperComponent, { - imports: [ESAlertModule], - }); - - expect(screen.getByText('Title')).toHaveClass('app-body-2'); - }); -}); diff --git a/projects/elonkit/src/ui/alert/__stories__/alert-story-actions/alert-story-actions.source.ts b/projects/elonkit/src/ui/alert/__stories__/alert-story-actions/alert-story-actions.source.ts deleted file mode 100644 index c141f8e..0000000 --- a/projects/elonkit/src/ui/alert/__stories__/alert-story-actions/alert-story-actions.source.ts +++ /dev/null @@ -1,11 +0,0 @@ -export const ALERT_STORY_ACTIONS_SOURCE = { - html: ` - - Message - - - - - - `, -}; diff --git a/projects/elonkit/src/ui/alert/__stories__/alert-story-actions/index.ts b/projects/elonkit/src/ui/alert/__stories__/alert-story-actions/index.ts deleted file mode 100644 index 8b3ab6d..0000000 --- a/projects/elonkit/src/ui/alert/__stories__/alert-story-actions/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { ALERT_STORY_ACTIONS_SOURCE } from './alert-story-actions.source'; diff --git a/projects/elonkit/src/ui/alert/__stories__/alert-story-basic/alert-story-basic.source.ts b/projects/elonkit/src/ui/alert/__stories__/alert-story-basic/alert-story-basic.source.ts deleted file mode 100644 index 11e4c44..0000000 --- a/projects/elonkit/src/ui/alert/__stories__/alert-story-basic/alert-story-basic.source.ts +++ /dev/null @@ -1,7 +0,0 @@ -export const ALERT_STORY_BASIC_SOURCE = { - html: ` - Message - - Message - `, -}; diff --git a/projects/elonkit/src/ui/alert/__stories__/alert-story-basic/index.ts b/projects/elonkit/src/ui/alert/__stories__/alert-story-basic/index.ts deleted file mode 100644 index 2fd995d..0000000 --- a/projects/elonkit/src/ui/alert/__stories__/alert-story-basic/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { ALERT_STORY_BASIC_SOURCE } from './alert-story-basic.source'; diff --git a/projects/elonkit/src/ui/alert/__stories__/alert-story-icon-mapping/alert-story-icon-mapping.component.ts b/projects/elonkit/src/ui/alert/__stories__/alert-story-icon-mapping/alert-story-icon-mapping.component.ts deleted file mode 100644 index 2ff0a12..0000000 --- a/projects/elonkit/src/ui/alert/__stories__/alert-story-icon-mapping/alert-story-icon-mapping.component.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Component, ChangeDetectionStrategy, Input, Output, EventEmitter } from '@angular/core'; - -import { DomSanitizer } from '@angular/platform-browser'; -import { MatIconRegistry } from '@angular/material/icon'; - -@Component({ - selector: 'es-alert-story-icon-mapping', - template: ` - - {{ title }} - {{ content }} - -
- - {{ title }} - {{ content }} - -
- - {{ title }} - {{ content }} -
- - {{ title }} - {{ content }} -
- - {{ title }} - {{ content }} - `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class AlertStoryIconMappingComponent { - @Input() public content: string; - @Input() public title: string; - @Input() public closable: boolean; - - @Output() public closed = new EventEmitter(); - - constructor( - private matIconRegistry: MatIconRegistry, - private domSanitizer: DomSanitizer - ) { - this.matIconRegistry.addSvgIcon('warning', this.domSanitizer.bypassSecurityTrustResourceUrl('/icons/alert/warning.svg')); - - this.matIconRegistry.addSvgIcon('error', this.domSanitizer.bypassSecurityTrustResourceUrl('/icons/alert/error.svg')); - } - - public onClose() { - this.closed.emit(); - } -} diff --git a/projects/elonkit/src/ui/alert/__stories__/alert-story-icon-mapping/alert-story-icon-mapping.module.ts b/projects/elonkit/src/ui/alert/__stories__/alert-story-icon-mapping/alert-story-icon-mapping.module.ts deleted file mode 100644 index 30e5b8c..0000000 --- a/projects/elonkit/src/ui/alert/__stories__/alert-story-icon-mapping/alert-story-icon-mapping.module.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { HttpClientModule } from '@angular/common/http'; - -import { AlertStoryIconMappingComponent } from './alert-story-icon-mapping.component'; - -import { ESAlertModule, ES_ALERT_DEFAULT_OPTIONS } from '../..'; - -@NgModule({ - declarations: [AlertStoryIconMappingComponent], - imports: [CommonModule, HttpClientModule, ESAlertModule], - exports: [AlertStoryIconMappingComponent], - providers: [ - { - provide: ES_ALERT_DEFAULT_OPTIONS, - useValue: { - iconMapping: { - warning: { svgIcon: 'warning' }, - error: { svgIcon: 'error' }, - }, - }, - }, - ], -}) -export class AlertStoryIconMappingModule {} diff --git a/projects/elonkit/src/ui/alert/__stories__/alert-story-icon-mapping/alert-story-icon-mapping.source.ts b/projects/elonkit/src/ui/alert/__stories__/alert-story-icon-mapping/alert-story-icon-mapping.source.ts deleted file mode 100644 index 1dab458..0000000 --- a/projects/elonkit/src/ui/alert/__stories__/alert-story-icon-mapping/alert-story-icon-mapping.source.ts +++ /dev/null @@ -1,40 +0,0 @@ -export const ALERT_STORY_ICON_MAPPING_SOURCE = { - ts: ` - import { ES_ALERT_DEFAULT_OPTIONS } from '@elonkit/angular/ui/alert'; - - @NgModule({ - ... - providers: [{ - provide: ES_ALERT_DEFAULT_OPTIONS, - useValue: { - iconMapping: { - warning: { svgIcon: 'warning' }, - error: { svgIcon: 'error' } - } - } - }] - }) - export class AppModule {} - `, - html: ` - - Message - - - - Message - - - - Message - - - - Message - - - - Message - - `, -}; diff --git a/projects/elonkit/src/ui/alert/__stories__/alert-story-icon-mapping/index.ts b/projects/elonkit/src/ui/alert/__stories__/alert-story-icon-mapping/index.ts deleted file mode 100644 index d561d41..0000000 --- a/projects/elonkit/src/ui/alert/__stories__/alert-story-icon-mapping/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { AlertStoryIconMappingComponent } from './alert-story-icon-mapping.component'; -export { AlertStoryIconMappingModule } from './alert-story-icon-mapping.module'; -export { ALERT_STORY_ICON_MAPPING_SOURCE } from './alert-story-icon-mapping.source'; diff --git a/projects/elonkit/src/ui/alert/__stories__/alert.stories.mdx b/projects/elonkit/src/ui/alert/__stories__/alert.stories.mdx deleted file mode 100644 index 296f23a..0000000 --- a/projects/elonkit/src/ui/alert/__stories__/alert.stories.mdx +++ /dev/null @@ -1,167 +0,0 @@ -import { Meta, Story, ArgsTable } from '@storybook/addon-docs'; -import { Canvas } from '~storybook/components'; - -import { action } from '@storybook/addon-actions'; - -import { ESAlertModule, ESAlertComponent } from '..'; - -import { ALERT_STORY_BASIC_SOURCE } from './alert-story-basic'; -import { ALERT_STORY_ACTIONS_SOURCE } from './alert-story-actions'; -import { - AlertStoryIconMappingModule, - AlertStoryIconMappingComponent, - ALERT_STORY_ICON_MAPPING_SOURCE, -} from './alert-story-icon-mapping'; - - - -# Alert - -An alert displays a short, important message in a way that attracts the user's attention without -interrupting the user's task. - -## Demos - -export const getContent = (args, context) => { - return args.content || (context.globals.locale === 'en' ? 'Message' : 'Сообщение'); -}; - -export const getTitle = (args, context) => { - return args.title || (context.globals.locale === 'en' ? 'Title' : 'Заголовок'); -}; - -export const TemplateBasic = (args, context) => ({ - template: ` - - {{title}} - {{content}} - - `, - moduleMetadata: { - imports: [ESAlertModule], - }, - props: { - ...args, - title: getTitle(args, context), - content: getContent(args, context), - onClose: action('onClose'), - }, -}); - - - - {TemplateBasic.bind({})} - - - {TemplateBasic.bind({})} - - - -We can add actions. - - - - {((args, context) => ({ - template: ` - - {{title}} - {{content}} - - - - - - `, - moduleMetadata: { - imports: [ESAlertModule], - }, - props: { - ...args, - title: getTitle(args, context), - content: getContent(args, context), - onClose: action('onClose'), - onAction: action('onAction'), - onCancel: action('onCancel'), - }, - })).bind({})} - - - -We can override default icon mapping and individual icons. - - - - {((args, context) => ({ - component: AlertStoryIconMappingComponent, - moduleMetadata: { - imports: [AlertStoryIconMappingModule], - }, - props: { - ...args, - title: getTitle(args, context), - content: getContent(args, context), - onClose: action('onClose'), - }, - })).bind({})} - - - -## API - - - -## Constants - -Injection token that can be used to configure the default options for all components within an app. - -```ts -import { ES_ALERT_DEFAULT_OPTIONS } from '@elonkit/angular/ui/alert'; - -@NgModule({ - providers: [ - { - provide: ES_ALERT_DEFAULT_OPTIONS, - useValue: { - typography: 'mat-body-2', - titleTypography: 'mat-body-2', - iconMapping: { - default: { icon: 'info' }, - info: { icon: 'info' }, - success: { icon: 'check_circle' }, - warning: { icon: 'warning' }, - error: { icon: 'error' } - } - } - } - ] -}) -``` diff --git a/projects/elonkit/src/ui/alert/alert.component.html b/projects/elonkit/src/ui/alert/alert.component.html deleted file mode 100644 index ef44e6b..0000000 --- a/projects/elonkit/src/ui/alert/alert.component.html +++ /dev/null @@ -1,26 +0,0 @@ -
-
- - {{ currentIcon.icon || '' }} - -
-
- -
-
- -
-
- -
- -
diff --git a/projects/elonkit/src/ui/alert/alert.component.scss b/projects/elonkit/src/ui/alert/alert.component.scss deleted file mode 100644 index 0a00e0b..0000000 --- a/projects/elonkit/src/ui/alert/alert.component.scss +++ /dev/null @@ -1,50 +0,0 @@ -.es-alert { - border-radius: 6px; - border-style: solid; - border-width: 1px; - box-sizing: border-box; - min-height: 56px; - padding: 7px 16px; - - &__content { - display: flex; - } - - &__text-wrapper { - display: flex; - flex-direction: column; - justify-content: center; - min-height: 40px; - - &:not(:last-child) { - margin-right: 10px; - } - } - - &__title { - font-weight: 700; - - &:empty { - display: none; - } - } - - &__text { - position: relative; - } - - &__icon { - margin: 8px 8px 0 0; - min-width: 24px; - - &_close.mat-icon-button { - border-radius: 4px; - width: 24px; - height: 24px; - line-height: 22px; - margin: -8px; - margin-left: auto; - margin-top: 8px; - } - } -} diff --git a/projects/elonkit/src/ui/alert/alert.component.theme.scss b/projects/elonkit/src/ui/alert/alert.component.theme.scss deleted file mode 100644 index dea3123..0000000 --- a/projects/elonkit/src/ui/alert/alert.component.theme.scss +++ /dev/null @@ -1,72 +0,0 @@ -@import './components/alert-actions/alert-actions.component.theme'; - -@mixin es-alert-theme($theme, $elonkit-theme) { - $warn: map-get($theme, warn); - $info: map-get($elonkit-theme, info); - $positive: map-get($elonkit-theme, positive); - $attention: map-get($elonkit-theme, attention); - $mono-a: map-get($elonkit-theme, mono-a); - - @include es-alert-actions-theme($theme, $elonkit-theme); - - .es-alert { - &_variant { - &_default { - background-color: mat.get-color-from-palette($mono-a, A50); - border-color: mat.get-color-from-palette($mono-a, A100); - } - - &_info { - background-color: mat.get-color-from-palette($info, A100); - border-color: mat.get-color-from-palette($info, A300); - } - - &_success { - background-color: mat.get-color-from-palette($positive, A100); - border-color: mat.get-color-from-palette($positive, A300); - } - - &_warning { - background-color: mat.get-color-from-palette($attention, A100); - border-color: mat.get-color-from-palette($attention, A200); - } - - &_error { - background-color: mat.get-color-from-palette($warn, A100); - border-color: mat.get-color-from-palette($warn, A200); - } - } - - &__text { - color: mat.get-color-from-palette($mono-a, A900); - } - - &__icon { - &_variant { - &_default { - color: mat.get-color-from-palette($mono-a, A500); - } - - &_info { - color: mat.get-color-from-palette($info); - } - - &_success { - color: mat.get-color-from-palette($positive); - } - - &_warning { - color: mat.get-color-from-palette($attention); - } - - &_error { - color: mat.get-color-from-palette($warn); - } - } - - &_close { - color: mat.get-color-from-palette($mono-a, A500); - } - } - } -} diff --git a/projects/elonkit/src/ui/alert/alert.component.ts b/projects/elonkit/src/ui/alert/alert.component.ts deleted file mode 100644 index a5e5f9d..0000000 --- a/projects/elonkit/src/ui/alert/alert.component.ts +++ /dev/null @@ -1,160 +0,0 @@ -import { - Component, - ChangeDetectionStrategy, - ChangeDetectorRef, - ViewEncapsulation, - Input, - Output, - EventEmitter, - InjectionToken, - Optional, - Inject, -} from '@angular/core'; - -import { coerceBooleanProperty } from '@angular/cdk/coercion'; - -import { Observable } from 'rxjs'; - -import { ESAlertVariant } from './alert.types'; -import { ESLocaleService, ESLocale } from '../locale'; - -export interface ESAlertDefaultOptions { - typography?: string; - titleTypography?: string; - iconMapping?: { [key in ESAlertVariant]?: { icon?: string; svgIcon?: string } }; -} - -const DEFAULT_TYPOGRAPHY = 'es-body-100'; -const DEFAULT_TITLE_TYPOGRAPHY = 'es-body-100'; - -const DEFAULT_ICON_MAPPING = { - default: { icon: 'info' }, - info: { icon: 'info' }, - success: { icon: 'check_circle' }, - warning: { icon: 'warning' }, - error: { icon: 'error' }, -}; - -export const ES_ALERT_DEFAULT_OPTIONS = new InjectionToken('ES_ALERT_DEFAULT_OPTIONS'); - -@Component({ - selector: 'es-alert', - templateUrl: './alert.component.html', - styleUrls: ['./alert.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class ESAlertComponent { - private iconMapping: { [key in ESAlertVariant]: { icon?: string; svgIcon?: string } }; - - /** - * The variant of the alert. This defines the color and icon used. - */ - @Input() public variant: ESAlertVariant = 'default'; - - private _typography: string; - - /** - * Class applied to text. - */ - @Input() - public get typography(): string { - return this._typography; - } - public set typography(value: string) { - this._typography = value || (this.defaultOptions && this.defaultOptions.typography) || DEFAULT_TYPOGRAPHY; - } - - private _titleTypography: string; - - /** - * Class applied to title. - */ - @Input() - public get titleTypography(): string { - return this._titleTypography; - } - public set titleTypography(value: string) { - this._titleTypography = value || (this.defaultOptions && this.defaultOptions.titleTypography) || DEFAULT_TITLE_TYPOGRAPHY; - } - - private _closable = false; - - /** - * Show close button. - */ - @Input() - public get closable() { - return this._closable; - } - public set closable(closable: any) { - this._closable = coerceBooleanProperty(closable); - } - - /** - * Override the icon displayed before the text. - * Unless provided, the icon is mapped to the value of the variant input. - */ - @Input() public icon?: string; - - /** - * Override the icon displayed before the text. - * Unless provided, the icon is mapped to the value of the variant input. - */ - @Input() public svgIcon?: string; - - /** - * Event emitted when user clicks close button. - */ - @Output() public closed = new EventEmitter(); - - /** - * @internal - * @ignore - */ - public locale$: Observable; - - /** - * @ignore - */ - constructor( - /** - * @internal - */ - public changeDetector: ChangeDetectorRef, - /** - * @internal - */ - private localeService: ESLocaleService, - /** - * @internal - */ - @Optional() - @Inject(ES_ALERT_DEFAULT_OPTIONS) - private defaultOptions: ESAlertDefaultOptions - ) { - this.locale$ = this.localeService.locale(); - - this.typography = (defaultOptions && defaultOptions.typography) || DEFAULT_TYPOGRAPHY; - this.titleTypography = (defaultOptions && defaultOptions.titleTypography) || DEFAULT_TITLE_TYPOGRAPHY; - this.iconMapping = { ...DEFAULT_ICON_MAPPING, ...defaultOptions?.iconMapping }; - } - - /** - * @internal - * @ignore - */ - public onClose() { - this.closed.emit(); - } - - public get currentIcon(): any { - if (this.icon) { - return { icon: this.icon }; - } - if (this.svgIcon) { - return { svgIcon: this.svgIcon }; - } - return this.iconMapping[this.variant]; - } -} diff --git a/projects/elonkit/src/ui/alert/alert.module.ts b/projects/elonkit/src/ui/alert/alert.module.ts deleted file mode 100644 index 44e1fdb..0000000 --- a/projects/elonkit/src/ui/alert/alert.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; - -import { MatButtonModule } from '@angular/material/button'; -import { MatIconModule } from '@angular/material/icon'; - -import { ESAlertComponent } from './alert.component'; -import { ESAlertActionsComponent } from './components/alert-actions'; - -@NgModule({ - declarations: [ESAlertComponent, ESAlertActionsComponent], - imports: [CommonModule, MatButtonModule, MatIconModule], - exports: [ESAlertComponent, ESAlertActionsComponent, MatButtonModule], -}) -export class ESAlertModule {} diff --git a/projects/elonkit/src/ui/alert/alert.types.ts b/projects/elonkit/src/ui/alert/alert.types.ts deleted file mode 100644 index dde83cb..0000000 --- a/projects/elonkit/src/ui/alert/alert.types.ts +++ /dev/null @@ -1 +0,0 @@ -export type ESAlertVariant = 'default' | 'info' | 'success' | 'warning' | 'error'; diff --git a/projects/elonkit/src/ui/alert/components/alert-actions/alert-actions.component.html b/projects/elonkit/src/ui/alert/components/alert-actions/alert-actions.component.html deleted file mode 100644 index dcc52c4..0000000 --- a/projects/elonkit/src/ui/alert/components/alert-actions/alert-actions.component.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/projects/elonkit/src/ui/alert/components/alert-actions/alert-actions.component.scss b/projects/elonkit/src/ui/alert/components/alert-actions/alert-actions.component.scss deleted file mode 100644 index 703ec3d..0000000 --- a/projects/elonkit/src/ui/alert/components/alert-actions/alert-actions.component.scss +++ /dev/null @@ -1,15 +0,0 @@ -.es-alert-actions { - display: grid; - gap: 8px; - grid-auto-flow: column; - justify-content: flex-start; - margin-bottom: 8px; - margin-left: 32px; - margin-top: 12px; - - .mat-button-base { - line-height: 32px; - padding: 0 8px; - text-transform: uppercase; - } -} diff --git a/projects/elonkit/src/ui/alert/components/alert-actions/alert-actions.component.theme.scss b/projects/elonkit/src/ui/alert/components/alert-actions/alert-actions.component.theme.scss deleted file mode 100644 index 4aedc98..0000000 --- a/projects/elonkit/src/ui/alert/components/alert-actions/alert-actions.component.theme.scss +++ /dev/null @@ -1,13 +0,0 @@ -@mixin es-alert-actions-theme($theme, $elonkit-theme) { - $mono-a: map-get($elonkit-theme, mono-a); - - .es-alert-actions { - .mat-button-base { - color: mat.get-color-from-palette($mono-a, A700); - } - - .mat-flat-button { - background-color: mat.get-color-from-palette($mono-a, A100); - } - } -} diff --git a/projects/elonkit/src/ui/alert/components/alert-actions/alert-actions.component.ts b/projects/elonkit/src/ui/alert/components/alert-actions/alert-actions.component.ts deleted file mode 100644 index 38ac504..0000000 --- a/projects/elonkit/src/ui/alert/components/alert-actions/alert-actions.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core'; - -@Component({ - selector: 'es-alert-actions', - templateUrl: './alert-actions.component.html', - styleUrls: ['./alert-actions.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class ESAlertActionsComponent {} diff --git a/projects/elonkit/src/ui/alert/components/alert-actions/index.ts b/projects/elonkit/src/ui/alert/components/alert-actions/index.ts deleted file mode 100644 index bd00bf9..0000000 --- a/projects/elonkit/src/ui/alert/components/alert-actions/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { ESAlertActionsComponent } from './alert-actions.component'; diff --git a/projects/elonkit/src/ui/alert/index.ts b/projects/elonkit/src/ui/alert/index.ts deleted file mode 100644 index 7e1a213..0000000 --- a/projects/elonkit/src/ui/alert/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './public-api'; diff --git a/projects/elonkit/src/ui/alert/public-api.ts b/projects/elonkit/src/ui/alert/public-api.ts deleted file mode 100644 index aca0797..0000000 --- a/projects/elonkit/src/ui/alert/public-api.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { ESAlertModule } from './alert.module'; -export { ESAlertComponent, ES_ALERT_DEFAULT_OPTIONS, ESAlertDefaultOptions } from './alert.component'; -export { ESAlertActionsComponent } from './components/alert-actions'; -export { ESAlertVariant } from './alert.types'; diff --git a/projects/elonkit/src/ui/audio-player/__specs__/audio-player.spec.ts b/projects/elonkit/src/ui/audio-player/__specs__/audio-player.spec.ts deleted file mode 100644 index 8693153..0000000 --- a/projects/elonkit/src/ui/audio-player/__specs__/audio-player.spec.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { OverlayContainer } from '@angular/cdk/overlay'; -import { inject } from '@angular/core/testing'; -import { MatIconTestingModule } from '@angular/material/icon/testing'; - -import { fireEvent, getByLabelText, render, RenderResult, screen } from '@testing-library/angular'; -import { en } from '../../locale'; -import { ESAudioPlayerComponent } from '../audio-player.component'; -import { ESAudioPlayerModule } from '../audio-player.module'; - -const VOLUME = 46; - -describe('AudioPlayer', () => { - let overlay: OverlayContainer; - let overlayElement: HTMLElement; - let component: RenderResult; - - const onDownloadAudio = jest.fn(); - const onVolumeChanged = jest.fn(); - - beforeEach(async () => { - component = await render(ESAudioPlayerComponent, { - componentProperties: { - volume: VOLUME, - audioDownload: { emit: onDownloadAudio } as any, - volumeChanged: { emit: onVolumeChanged } as any, - }, - imports: [MatIconTestingModule, ESAudioPlayerModule], - excludeComponentDeclaration: true, - }); - - inject([OverlayContainer], (oc: OverlayContainer) => { - overlay = oc; - overlayElement = oc.getContainerElement(); - })(); - }); - - afterEach(inject([OverlayContainer], (currentOverlay: OverlayContainer) => { - currentOverlay.ngOnDestroy(); - overlay.ngOnDestroy(); - - jest.restoreAllMocks(); - })); - - it('Should change volume', async () => { - fireEvent.click(screen.getByLabelText(en.audioPlayer.labelMute)); - - expect(onVolumeChanged).toBeCalledWith(0); - - fireEvent.click(screen.getByLabelText(en.audioPlayer.labelUnmute)); - - expect(onVolumeChanged).toBeCalledWith(VOLUME); - }); - - it('Should download audio', async () => { - fireEvent.mouseEnter(screen.getByLabelText(en.audioPlayer.labelOptions)); - - fireEvent.click(getByLabelText(overlayElement, en.audioPlayer.labelDownload)); - - expect(onDownloadAudio).toBeCalled(); - }); -}); diff --git a/projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/audio-player-story-basic.component.scss b/projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/audio-player-story-basic.component.scss deleted file mode 100644 index 1749f0f..0000000 --- a/projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/audio-player-story-basic.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.audio-player { - max-width: 400px; -} diff --git a/projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/audio-player-story-basic.component.ts b/projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/audio-player-story-basic.component.ts deleted file mode 100644 index a55ddae..0000000 --- a/projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/audio-player-story-basic.component.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; - -@Component({ - selector: 'es-audio-player-story-basic', - styleUrls: ['./audio-player-story-basic.component.scss'], - template: `
- -
`, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class AudioPlayerStoryBasicComponent { - @Input() public source: string; - @Input() public volume: number; -} diff --git a/projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/audio-player-story-basic.module.ts b/projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/audio-player-story-basic.module.ts deleted file mode 100644 index f03e333..0000000 --- a/projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/audio-player-story-basic.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { HttpClientModule } from '@angular/common/http'; -import { NgModule } from '@angular/core'; - -import { CoreModule } from '../../../../../.storybook/core.module'; - -import { ESAudioPlayerModule } from '../..'; -import { AudioPlayerStoryBasicComponent } from './audio-player-story-basic.component'; - -@NgModule({ - declarations: [AudioPlayerStoryBasicComponent], - imports: [CommonModule, HttpClientModule, CoreModule, ESAudioPlayerModule], - exports: [AudioPlayerStoryBasicComponent], -}) -export class AudioPlayerStoryBasicModule {} diff --git a/projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/audio-player-story-basic.source.ts b/projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/audio-player-story-basic.source.ts deleted file mode 100644 index 19a4946..0000000 --- a/projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/audio-player-story-basic.source.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const AUDIO_PLAYER_STORY_BASIC_SOURCE = { - html: ` - - `, -}; diff --git a/projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/index.ts b/projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/index.ts deleted file mode 100644 index 033cb86..0000000 --- a/projects/elonkit/src/ui/audio-player/__stories__/audio-player-story-basic/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { AudioPlayerStoryBasicModule } from './audio-player-story-basic.module'; -export { AudioPlayerStoryBasicComponent } from './audio-player-story-basic.component'; - -export { AUDIO_PLAYER_STORY_BASIC_SOURCE } from './audio-player-story-basic.source'; diff --git a/projects/elonkit/src/ui/audio-player/__stories__/audio-player.stories.mdx b/projects/elonkit/src/ui/audio-player/__stories__/audio-player.stories.mdx deleted file mode 100644 index 8707369..0000000 --- a/projects/elonkit/src/ui/audio-player/__stories__/audio-player.stories.mdx +++ /dev/null @@ -1,51 +0,0 @@ -import { action } from '@storybook/addon-actions'; -import { Canvas } from '~storybook/components'; -import { Meta, Story, ArgsTable } from '@storybook/blocks'; - -import { - AudioPlayerStoryBasicComponent, - AudioPlayerStoryBasicModule, - AUDIO_PLAYER_STORY_BASIC_SOURCE, -} from './audio-player-story-basic'; - -import { ESAudioPlayerComponent } from '..'; - - - -# Audio player - -Audio player allows users to play audio tracks. - -## Demos - - - - {((args) => ({ - component: AudioPlayerStoryBasicComponent, - moduleMetadata: { - imports: [AudioPlayerStoryBasicModule], - }, - props: { - ...args, - }, - })).bind({})} - - - -## API - - diff --git a/projects/elonkit/src/ui/audio-player/audio-player.component.html b/projects/elonkit/src/ui/audio-player/audio-player.component.html deleted file mode 100644 index 56396ab..0000000 --- a/projects/elonkit/src/ui/audio-player/audio-player.component.html +++ /dev/null @@ -1,36 +0,0 @@ -
- - - - - - - - - -
diff --git a/projects/elonkit/src/ui/audio-player/audio-player.component.scss b/projects/elonkit/src/ui/audio-player/audio-player.component.scss deleted file mode 100644 index 1b6fee8..0000000 --- a/projects/elonkit/src/ui/audio-player/audio-player.component.scss +++ /dev/null @@ -1,56 +0,0 @@ -.es-audio-player { - height: 40px; - padding: 0 12px; - display: flex; - flex-wrap: nowrap; - align-items: center; - border-radius: 40px; - - &__button { - &.mat-icon-button { - width: 24px; - height: 24px; - } - - .mat-button-wrapper { - display: flex; - justify-content: center; - } - } - - &__time-slider { - display: flex; - flex: 1; - margin-left: 12px; - position: relative; - } - - &__label { - letter-spacing: 0.4px; - position: relative; - user-select: none; - - &, - &.dark { - margin-left: 16px !important; - } - - &-prefix { - &::before { - content: '-'; - left: -6px; - position: absolute; - } - } - } - - &__volume { - height: 24px; - margin-left: 12px; - } - - &__options { - height: 24px; - margin-left: 8px; - } -} diff --git a/projects/elonkit/src/ui/audio-player/audio-player.component.theme.scss b/projects/elonkit/src/ui/audio-player/audio-player.component.theme.scss deleted file mode 100644 index 75ef5af..0000000 --- a/projects/elonkit/src/ui/audio-player/audio-player.component.theme.scss +++ /dev/null @@ -1,23 +0,0 @@ -@import './components/audio-player-options/audio-player-options.component.theme'; -@import './components/audio-player-time-slider/audio-player-time-slider.component.theme'; -@import './components/audio-player-volume/audio-player-volume.component.theme'; - -@mixin es-audio-player-theme($theme, $elonkit-theme) { - $mono-a: map-get($elonkit-theme, mono-a); - - @include es-audio-player-options-theme($theme, $elonkit-theme); - @include es-audio-player-time-slider-theme($theme, $elonkit-theme); - @include es-audio-player-volume-theme($theme, $elonkit-theme); - - .es-audio-player { - background-color: mat.get-color-from-palette($mono-a, A75); - - &__button.mat-icon-button { - color: mat.get-color-from-palette($mono-a, A600); - } - - &__label { - color: mat.get-color-from-palette($mono-a, A800); - } - } -} diff --git a/projects/elonkit/src/ui/audio-player/audio-player.component.ts b/projects/elonkit/src/ui/audio-player/audio-player.component.ts deleted file mode 100644 index 73a1551..0000000 --- a/projects/elonkit/src/ui/audio-player/audio-player.component.ts +++ /dev/null @@ -1,269 +0,0 @@ -import { - Component, - Input, - Output, - EventEmitter, - ViewEncapsulation, - OnDestroy, - ChangeDetectionStrategy, - ChangeDetectorRef, - InjectionToken, - Optional, - Inject, - AfterViewInit, -} from '@angular/core'; - -import { Observable } from 'rxjs'; - -import { ESLocale, ESLocaleService } from '../locale'; - -export interface ESAudioPlayerDefaultOptions { - rates?: number[]; -} - -export const ES_AUDIO_PLAYER_DEFAULT_OPTIONS = new InjectionToken('ES_AUDIO_PLAYER_DEFAULT_OPTIONS'); - -const DEFAULT_TIME = '00:00:00'; - -@Component({ - selector: 'es-audio-player', - templateUrl: './audio-player.component.html', - styleUrls: ['./audio-player.component.scss'], - encapsulation: ViewEncapsulation.None, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class ESAudioPlayerComponent implements AfterViewInit, OnDestroy { - /** - * Array of playback rates for audio. - */ - @Input() - public set rates(value: number[] | undefined) { - this._rates = value || this.defaultOptions?.rates || [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]; - } - public get rates(): number[] { - return this._rates; - } - private _rates: number[]; - - /** - * Default or previously set volume value in the range from 0 to 100. - */ - @Input() - public set volume(value: number) { - this._volume = value > 100 ? 100 : value; - - this.onSetVolume(this._volume); - } - public get volume(): number { - return this._volume; - } - private _volume = 100; - - /** - * Source of audio track. - */ - @Input() - public set source(value: string) { - this.isAudioDataLoaded = false; - - if (value) { - this.audio.src = value; - - this.audioCurrentTime = 0; - } - } - - /** - * Event emitted when audio track playback completed. - */ - @Output() public audioEnded = new EventEmitter(); - - /** - * Event emitted when need to download audio track. - */ - @Output() public audioDownload = new EventEmitter(); - - /** - * Event emitted when volume changed. - */ - @Output() public volumeChanged = new EventEmitter(); - - /** - * @internal - * @ignore - */ - public audio: HTMLAudioElement = new Audio(); - - /** - * @internal - * @ignore - */ - public audioCurrentTime = 0; - - /** - * @internal - * @ignore - */ - public isAudioDataLoaded = false; - - /** - * @internal - * @ignore - */ - public displayedTime = DEFAULT_TIME; - - /** - * @internal - * @ignore - */ - public isDisplayedLeftTime = true; - - /** - * @internal - * @ignore - */ - public locale$: Observable; - - private onEnded = () => { - // this.isAudioDataLoaded = false; - this.audioEnded.emit(true); - }; - - private onLoadedData = ({ target }: Event) => { - const { duration, currentTime } = target as any; - this.isAudioDataLoaded = true; - this.audio.volume = this.volume / 100; - - this.displayedTime = this.isDisplayedLeftTime ? this.formatTime(duration - currentTime) : this.formatTime(currentTime); - - // tslint:disable-next-line: no-string-literal - // @ts-ignore - if (!this.changeDetector['destroyed']) { - this.changeDetector.detectChanges(); - } - }; - - private onTimeUpdate = ({ target }: Event) => { - const { duration, currentTime } = target as any; - - this.audioCurrentTime = currentTime; - - this.displayedTime = this.isDisplayedLeftTime ? this.formatTime(duration - currentTime) : this.formatTime(currentTime); - - // tslint:disable-next-line: no-string-literal - // @ts-ignore - if (!this.changeDetector['destroyed']) { - this.changeDetector.detectChanges(); - } - }; - - /** - * @ignore - */ - constructor( - /** - * @internal - */ - public localeService: ESLocaleService, - /** - * @internal - */ - private changeDetector: ChangeDetectorRef, - /** - * @internal - */ - @Optional() - @Inject(ES_AUDIO_PLAYER_DEFAULT_OPTIONS) - private defaultOptions: ESAudioPlayerDefaultOptions - ) { - this.rates = defaultOptions?.rates; - this.locale$ = this.localeService.locale(); - } - - /** - * @ignore - */ - public ngAfterViewInit() { - if (this.audio) { - this.addEventsListener(); - } - } - - /** - * @ignore - */ - public ngOnDestroy() { - this.audio.src = ''; - this.audio.removeEventListener('ended', this.onEnded); - this.audio.removeEventListener('loadeddata', this.onLoadedData); - this.audio.removeEventListener('timeupdate', this.onTimeUpdate); - } - - /** - * @internal - * @ignore - */ - public onPlayback() { - this.audio.paused ? this.audio.play() : this.audio.pause(); - } - - /** - * @internal - * @ignore - */ - public onSetVolume(value: number) { - if (this.audio) { - this.audio.volume = value / 100; - this.volumeChanged.emit(value); - } - } - - /** - * @internal - * @ignore - */ - public onSeekTo(value: number) { - this.audio.currentTime = value; - } - - /** - * @internal - * @ignore - */ - public onSetPlaybackRate(value: number) { - this.audio.playbackRate = value; - } - - /** - * @internal - * @ignore - */ - public changeDisplayedTime() { - this.isDisplayedLeftTime = !this.isDisplayedLeftTime; - - this.displayedTime = this.isDisplayedLeftTime - ? this.formatTime(this.audio.duration - this.audioCurrentTime) - : this.formatTime(this.audioCurrentTime); - } - - private addEventsListener() { - this.audio.addEventListener('loadeddata', this.onLoadedData); - this.audio.addEventListener('timeupdate', this.onTimeUpdate); - this.audio.addEventListener('ended', this.onEnded); - } - - private formatTime(time: number): string { - if (!time) { - return DEFAULT_TIME; - } - - const hours = Math.floor(time / 3600); - const minutes = Math.floor((time - hours * 3600) / 60); - const seconds = Math.round(time) - hours * 3600 - minutes * 60; - - const h = hours < 10 ? `0${hours}` : `${hours}`; - const m = minutes < 10 ? `0${minutes}` : `${minutes}`; - const s = seconds < 10 ? `0${seconds}` : `${seconds}`; - return `${h}:${m}:${s}`; - } -} diff --git a/projects/elonkit/src/ui/audio-player/audio-player.module.ts b/projects/elonkit/src/ui/audio-player/audio-player.module.ts deleted file mode 100644 index e6238b7..0000000 --- a/projects/elonkit/src/ui/audio-player/audio-player.module.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { MatButtonModule } from '@angular/material/button'; -import { MatIconModule } from '@angular/material/icon'; -import { MatMenuModule } from '@angular/material/menu'; -import { MatSliderModule } from '@angular/material/slider'; -import { MatListModule } from '@angular/material/list'; -import { FormsModule } from '@angular/forms'; - -import { ESTooltipModule } from '../tooltip'; - -import { ESAudioPlayerComponent } from './audio-player.component'; -import { ESAudioPlayerOptionsComponent } from './components/audio-player-options'; -import { ESAudioPlayerTimeSliderComponent } from './components/audio-player-time-slider'; -import { ESAudioPlayerVolumeComponent } from './components/audio-player-volume'; - -@NgModule({ - declarations: [ - ESAudioPlayerComponent, - ESAudioPlayerOptionsComponent, - ESAudioPlayerTimeSliderComponent, - ESAudioPlayerVolumeComponent, - ], - imports: [ - CommonModule, - MatButtonModule, - MatIconModule, - MatMenuModule, - MatSliderModule, - FormsModule, - MatMenuModule, - MatListModule, - ESTooltipModule, - ], - exports: [ESAudioPlayerComponent], -}) -export class ESAudioPlayerModule {} diff --git a/projects/elonkit/src/ui/audio-player/components/audio-player-options/audio-player-options.component.html b/projects/elonkit/src/ui/audio-player/components/audio-player-options/audio-player-options.component.html deleted file mode 100644 index 09d02ec..0000000 --- a/projects/elonkit/src/ui/audio-player/components/audio-player-options/audio-player-options.component.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - -
- - -
- -
- - - -
-
-
diff --git a/projects/elonkit/src/ui/audio-player/components/audio-player-options/audio-player-options.component.scss b/projects/elonkit/src/ui/audio-player/components/audio-player-options/audio-player-options.component.scss deleted file mode 100644 index eeb9c1d..0000000 --- a/projects/elonkit/src/ui/audio-player/components/audio-player-options/audio-player-options.component.scss +++ /dev/null @@ -1,66 +0,0 @@ -.es-audio-player-options { - &__button { - &.mat-icon-button { - width: 24px; - height: 24px; - } - - .mat-button-wrapper { - display: flex; - justify-content: center; - } - } - - &__label { - &_ml-18 { - margin-left: 18px; - } - } - - &__tooltip { - padding: 0 !important; - } - - &__menu { - width: 176px; - flex-direction: column; - box-shadow: none; - } - - &__menu-item { - height: 44px; - padding: 0; - display: flex; - flex-wrap: nowrap; - align-items: center; - - .mat-button-wrapper { - width: 100%; - padding: 0 18px; - } - } - - &__item-content { - display: flex; - flex-wrap: nowrap; - align-items: center; - font-weight: 400; - - label { - cursor: pointer; - } - } - - &__label-container { - display: flex; - flex-direction: column; - align-items: flex-start; - margin-left: 18px; - } - - &__icon { - &_ml-auto { - margin-left: auto; - } - } -} diff --git a/projects/elonkit/src/ui/audio-player/components/audio-player-options/audio-player-options.component.theme.scss b/projects/elonkit/src/ui/audio-player/components/audio-player-options/audio-player-options.component.theme.scss deleted file mode 100644 index d45c8b8..0000000 --- a/projects/elonkit/src/ui/audio-player/components/audio-player-options/audio-player-options.component.theme.scss +++ /dev/null @@ -1,30 +0,0 @@ -@mixin es-audio-player-options-theme($theme, $elonkit-theme) { - $mono-a: map-get($elonkit-theme, mono-a); - $mono-b: map-get($elonkit-theme, mono-b); - - .es-audio-player-options { - &__button.mat-icon-button { - color: mat.get-color-from-palette($mono-a, A600); - } - - &__sub-label { - color: mat.get-color-from-palette($mono-b, A600); - } - - &__item-content { - color: mat.get-color-from-palette($mono-b, 500); - } - - &__divider { - border-color: mat.get-color-from-palette($mono-b, A100); - } - - &__icon { - color: mat.get-color-from-palette($mono-b, A900); - - &_dark { - color: mat.get-color-from-palette($mono-b, A600); - } - } - } -} diff --git a/projects/elonkit/src/ui/audio-player/components/audio-player-options/audio-player-options.component.ts b/projects/elonkit/src/ui/audio-player/components/audio-player-options/audio-player-options.component.ts deleted file mode 100644 index c1cb996..0000000 --- a/projects/elonkit/src/ui/audio-player/components/audio-player-options/audio-player-options.component.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Component, EventEmitter, Output, ViewEncapsulation, ChangeDetectionStrategy, Input } from '@angular/core'; - -import { Observable } from 'rxjs'; - -import { ESLocale, ESLocaleService } from '../../../locale'; - -@Component({ - selector: 'es-audio-player-options', - templateUrl: './audio-player-options.component.html', - styleUrls: ['./audio-player-options.component.scss'], - encapsulation: ViewEncapsulation.None, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class ESAudioPlayerOptionsComponent { - /** - * Array of playback rates for audio. - */ - @Input() - public rates: number[] | undefined; - - /** - * Source of audio track. - */ - @Input() - public src: string | undefined; - - /** - * Event emitted when playback rate is changed. - */ - @Output() public playbackRateChanged = new EventEmitter(); - - /** - * Event emitted when need to download audio track. - */ - @Output() public downloadClicked = new EventEmitter(); - - /** - * @internal - * @ignore - */ - public isRatePage = false; - - /** - * @internal - * @ignore - */ - public currentRate = 1; - - /** - * @internal - * @ignore - */ - public locale$: Observable; - - /** - * @ignore - */ - constructor( - /** - * @internal - */ - public localeService: ESLocaleService - ) { - this.locale$ = this.localeService.locale(); - } - - /** - * @internal - * @ignore - */ - public onChangePlaybackRate(value: number) { - this.currentRate = value; - this.playbackRateChanged.emit(value); - } -} diff --git a/projects/elonkit/src/ui/audio-player/components/audio-player-options/index.ts b/projects/elonkit/src/ui/audio-player/components/audio-player-options/index.ts deleted file mode 100644 index 18f3481..0000000 --- a/projects/elonkit/src/ui/audio-player/components/audio-player-options/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { ESAudioPlayerOptionsComponent } from './audio-player-options.component'; diff --git a/projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/audio-player-time-slider.component.html b/projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/audio-player-time-slider.component.html deleted file mode 100644 index 3084333..0000000 --- a/projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/audio-player-time-slider.component.html +++ /dev/null @@ -1,18 +0,0 @@ - - -
- {{ tooltipTime }} -
diff --git a/projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/audio-player-time-slider.component.scss b/projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/audio-player-time-slider.component.scss deleted file mode 100644 index ff2d015..0000000 --- a/projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/audio-player-time-slider.component.scss +++ /dev/null @@ -1,88 +0,0 @@ -@use 'sass:math'; - -.es-audio-player-time-slider { - &__slider { - flex: 1; - - &.mat-slider { - padding: 0; - - &:not(.mat-slider-disabled).cdk-mouse-focused .mat-slider-thumb, - &:not(.mat-slider-disabled).cdk-touch-focused .mat-slider-thumb, - &:not(.mat-slider-disabled).cdk-program-focused .mat-slider-thumb, - .cdk-mouse-focused .mat-slider-thumb, - .mat-slider-thumb { - border: 0; - width: 18px; - height: 18px; - transform: scale(0.7); - } - - .mat-slider-focus-ring { - width: 24px; - height: 24px; - right: -13px; - top: -11px; - } - } - - &.mat-slider-horizontal { - height: 40px; - min-width: 50px; - - .mat-slider-wrapper { - left: 0; - right: 0; - top: 18px; - } - - .mat-slider-track-fill, - .mat-slider-track-wrapper, - .mat-slider-track-background { - border-radius: 16px; - height: 4px; - } - } - } - - &__tooltip { - $base: 12; // Triangle base - $height: 8; // Triangle height - - $size: math.round(math.div($base, math.sqrt(2))); // Square side size - $scale: math.div($height, math.div($base, 2)); - $offset: -#{math.div($size, 2)}px; - padding: 4px 8px; - display: none; - - border-radius: 4px; - font-size: 12px; - letter-spacing: 0.4px; - line-height: 16px; - position: absolute; - z-index: 1000; - - &::after { - border-bottom-right-radius: 2px; - content: ''; - width: #{$size}px; - height: #{$size}px; - left: 50%; - position: absolute; - } - - &_top { - &::after { - bottom: $offset; - transform: scaleY($scale) translateX(-50%) rotate(45deg); - } - } - - &_bottom { - &::after { - top: $offset; - transform: scaleY($scale) translateX(-50%) rotate(225deg); - } - } - } -} diff --git a/projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/audio-player-time-slider.component.theme.scss b/projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/audio-player-time-slider.component.theme.scss deleted file mode 100644 index 14e40ea..0000000 --- a/projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/audio-player-time-slider.component.theme.scss +++ /dev/null @@ -1,39 +0,0 @@ -@mixin es-audio-player-time-slider-theme($theme, $elonkit-theme) { - $mono-a: map-get($elonkit-theme, mono-a); - $mono-b: map-get($elonkit-theme, mono-b); - $primary: map-get($theme, primary); - - .es-audio-player-time-slider { - &__slider { - &.mat-slider { - &:not(.mat-slider-disabled).cdk-mouse-focused .mat-slider-thumb, - &:not(.mat-slider-disabled).cdk-touch-focused .mat-slider-thumb, - &:not(.mat-slider-disabled).cdk-program-focused .mat-slider-thumb, - .cdk-mouse-focused .mat-slider-thumb, - .mat-slider-thumb { - background: mat.get-color-from-palette($primary, 500); - } - - .mat-slider-focus-ring { - background-color: mat.get-color-from-palette($mono-a, A200); - } - } - - &.mat-slider-horizontal { - .mat-slider-track-wrapper, - .mat-slider-track-background { - background: mat.get-color-from-palette($primary, 100); - } - } - } - - &__tooltip { - background-color: mat.get-color-from-palette($mono-a, A600); - color: mat.get-color-from-palette($mono-b, 500); - - &::after { - background: linear-gradient(-45deg, mat.get-color-from-palette($mono-a, A600) 50%, transparent 50%); - } - } - } -} diff --git a/projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/audio-player-time-slider.component.ts b/projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/audio-player-time-slider.component.ts deleted file mode 100644 index c1d67ed..0000000 --- a/projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/audio-player-time-slider.component.ts +++ /dev/null @@ -1,197 +0,0 @@ -import { - ChangeDetectionStrategy, - Component, - ElementRef, - EventEmitter, - HostListener, - Input, - Output, - Renderer2, - ViewChild, - ViewEncapsulation, -} from '@angular/core'; -import { MatSlider } from '@angular/material/slider'; - -const TIME_LINE_RANGE = 8; -const TOOLTIP_OFFSET = 21; - -@Component({ - selector: 'es-audio-player-time-slider', - templateUrl: './audio-player-time-slider.component.html', - styleUrls: ['./audio-player-time-slider.component.scss'], - encapsulation: ViewEncapsulation.None, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class ESAudioPlayerTimeSliderComponent { - /** The duration in seconds of the current media resource. */ - @Input() public duration: number; - - /** The current playback position, in seconds */ - @Input() public set audioCurrentTime(time: number) { - this._audioCurrentTime = time; - // if (!this.elementTimeLine._isSliding) { - // this._audioCurrentTime = time; - // } - } - public get audioCurrentTime(): number { - return this._audioCurrentTime; - } - private _audioCurrentTime: number; - - /** Event emitted when current playback position is changed, in seconds. */ - @Output() public timeUpdated = new EventEmitter(); - - /** - * @internal - * @ignore - */ - @ViewChild('timeLine', { static: true }) public elementTimeLine: MatSlider; - - /** - * @internal - * @ignore - */ - @ViewChild('timeTooltip', { static: true }) public elementTimeTooltip: ElementRef; - - /** - * @internal - * @ignore - */ - public tooltipIsShow = false; - - /** - * @internal - * @ignore - */ - public tooltipTime: string | null = null; - - /** - * @internal - * @ignore - */ - public tooltipPosition: string | null = null; - - /** - * @ignore - */ - constructor( - private renderer2: Renderer2, - private elementRef: ElementRef - ) {} - - /** - * @internal - * @ignore - */ - @HostListener('mouseleave') - public onMouseLeave() { - this.hideTooltip(); - } - - /** - * @internal - * @ignore - */ - @HostListener('mousemove', ['$event']) - public onMouseMove(event: MouseEvent) { - if (!this.duration) { - return; - } - - const container = this.elementRef.nativeElement.getBoundingClientRect(); - - const minTop = container.top + container.height / 2 - TIME_LINE_RANGE; - const maxBottom = container.bottom - container.height / 2 + TIME_LINE_RANGE; - - const scrollTop = document.scrollingElement?.scrollTop; - const scrollLeft = document.scrollingElement?.scrollLeft; - - if ( - scrollLeft && - scrollTop && - event.pageX >= container.left + scrollLeft && - event.pageX <= container.right + scrollLeft && - event.pageY > minTop + scrollTop && - event.pageY < maxBottom + scrollTop - ) { - this.tooltipIsShow = true; - - this.renderer2.setAttribute(this.elementTimeTooltip.nativeElement, 'style', 'display: block'); - - const tooltipWidth = this.elementTimeTooltip.nativeElement.clientWidth; - - const currentPositionX = event.pageX - container.left - scrollLeft; - - this.tooltipTime = this.calculateTime(container.width, currentPositionX); - - const tooltipPositionX = event.pageX - container.left - scrollLeft - tooltipWidth / 2; - - if (container.top > TOOLTIP_OFFSET) { - this.tooltipPosition = 'top'; - - this.renderer2.setAttribute( - this.elementTimeTooltip.nativeElement, - 'style', - `display: block; top: ${-TOOLTIP_OFFSET}px; left: ${tooltipPositionX}px` - ); - } else { - this.tooltipPosition = 'bottom'; - - this.renderer2.setAttribute( - this.elementTimeTooltip.nativeElement, - 'style', - `display: block; bottom: ${-TOOLTIP_OFFSET}px; left: ${tooltipPositionX}px` - ); - } - } else { - this.hideTooltip(); - } - } - - /** - * - * @internal - * @ignore - */ - public onSeekTo({ value }: any) { - this.timeUpdated.emit(+value); - } - - /** - * @internal - * @ignore - */ - private hideTooltip() { - if (this.tooltipIsShow) { - this.tooltipIsShow = false; - this.tooltipPosition = null; - - this.renderer2.setAttribute(this.elementTimeTooltip.nativeElement, 'style', `display: none;`); - } - } - - /** - * @internal - * @ignore - */ - private calculateTime(timelineLength: number, position: number): string { - const stepSize = this.duration / timelineLength; - - return this.formatTime(stepSize * position); - } - - /** - * @internal - * @ignore - */ - private formatTime(timeLeft: number): string { - const hours = Math.floor(timeLeft / 3600); - const minutes = Math.floor((timeLeft - hours * 3600) / 60); - const seconds = Math.round(timeLeft) - hours * 3600 - minutes * 60; - - const h = hours < 10 ? `0${hours}` : `${hours}`; - const m = minutes < 10 ? `0${minutes}` : `${minutes}`; - const s = seconds < 10 ? `0${seconds}` : `${seconds}`; - return `${h}:${m}:${s}`; - } -} diff --git a/projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/index.ts b/projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/index.ts deleted file mode 100644 index 6f8cde0..0000000 --- a/projects/elonkit/src/ui/audio-player/components/audio-player-time-slider/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { ESAudioPlayerTimeSliderComponent } from './audio-player-time-slider.component'; diff --git a/projects/elonkit/src/ui/audio-player/components/audio-player-volume/audio-player-volume.component.html b/projects/elonkit/src/ui/audio-player/components/audio-player-volume/audio-player-volume.component.html deleted file mode 100644 index 0e31165..0000000 --- a/projects/elonkit/src/ui/audio-player/components/audio-player-volume/audio-player-volume.component.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - -
- - - - -
-
-
diff --git a/projects/elonkit/src/ui/audio-player/components/audio-player-volume/audio-player-volume.component.scss b/projects/elonkit/src/ui/audio-player/components/audio-player-volume/audio-player-volume.component.scss deleted file mode 100644 index b0c58c7..0000000 --- a/projects/elonkit/src/ui/audio-player/components/audio-player-volume/audio-player-volume.component.scss +++ /dev/null @@ -1,64 +0,0 @@ -.es-audio-player-volume { - &__button { - &.mat-icon-button { - width: 24px; - height: 24px; - } - - .mat-button-wrapper { - display: flex; - justify-content: center; - } - } - - &__container { - max-width: 24px; - display: flex; - flex-direction: column; - align-items: center; - } - - &__slider { - &.mat-slider { - width: 24px; - padding: 0; - - &:not(.mat-slider-disabled).cdk-mouse-focused .mat-slider-thumb, - &:not(.mat-slider-disabled).cdk-touch-focused .mat-slider-thumb, - &:not(.mat-slider-disabled).cdk-program-focused .mat-slider-thumb, - .cdk-mouse-focused .mat-slider-thumb, - .mat-slider-thumb { - border: 0; - width: 18px; - height: 18px; - right: -10px; - transform: scale(0.7); - } - - .mat-slider-focus-ring { - bottom: -10px; - width: 18px; - height: 18px; - left: -8px; - } - - &.mat-slider-vertical { - .mat-slider-wrapper { - left: 10px; - } - - .mat-slider-track-fill, - .mat-slider-track-wrapper, - .mat-slider-track-background { - width: 4px; - } - } - - .mat-slider-track-fill, - .mat-slider-track-wrapper, - .mat-slider-track-background { - border-radius: 16px; - } - } - } -} diff --git a/projects/elonkit/src/ui/audio-player/components/audio-player-volume/audio-player-volume.component.theme.scss b/projects/elonkit/src/ui/audio-player/components/audio-player-volume/audio-player-volume.component.theme.scss deleted file mode 100644 index 9191f99..0000000 --- a/projects/elonkit/src/ui/audio-player/components/audio-player-volume/audio-player-volume.component.theme.scss +++ /dev/null @@ -1,41 +0,0 @@ -@mixin es-audio-player-volume-theme($theme, $elonkit-theme) { - $mono-a: map-get($elonkit-theme, mono-a); - $mono-b: map-get($elonkit-theme, mono-b); - - .es-audio-player-volume { - background-color: mat.get-color-from-palette($mono-a, A75); - - &__button.mat-icon-button { - color: mat.get-color-from-palette($mono-a, A600); - } - - &__slider { - &.mat-slider { - &:not(.mat-slider-disabled).cdk-mouse-focused .mat-slider-thumb, - &:not(.mat-slider-disabled).cdk-touch-focused .mat-slider-thumb, - &:not(.mat-slider-disabled).cdk-program-focused .mat-slider-thumb, - .cdk-mouse-focused .mat-slider-thumb, - .mat-slider-thumb { - background-color: mat.get-color-from-palette($mono-b, 500); - } - - .mat-slider-focus-ring { - background-color: mat.get-color-from-palette($mono-b, A200); - } - - &.mat-slider-vertical { - .mat-slider-track-fill, - .mat-slider-track-wrapper, - .mat-slider-track-background { - background-color: mat.get-color-from-palette($mono-b, 500); - } - - .mat-slider-track-wrapper, - .mat-slider-track-background { - background-color: mat.get-color-from-palette($mono-b, A400); - } - } - } - } - } -} diff --git a/projects/elonkit/src/ui/audio-player/components/audio-player-volume/audio-player-volume.component.ts b/projects/elonkit/src/ui/audio-player/components/audio-player-volume/audio-player-volume.component.ts deleted file mode 100644 index 4c29cc0..0000000 --- a/projects/elonkit/src/ui/audio-player/components/audio-player-volume/audio-player-volume.component.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { Component, Output, EventEmitter, Input, ViewEncapsulation, ChangeDetectionStrategy } from '@angular/core'; - -import { Observable } from 'rxjs'; - -import { ESLocale, ESLocaleService } from '../../../locale'; - -@Component({ - selector: 'es-audio-player-volume', - templateUrl: './audio-player-volume.component.html', - styleUrls: ['./audio-player-volume.component.scss'], - encapsulation: ViewEncapsulation.None, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class ESAudioPlayerVolumeComponent { - /** - * Default or previously set volume value in the range from 0 to 100. - */ - @Input() - public set volume(value: number) { - this.isMute = !value; - this._volume = value; - } - public get volume(): number { - return this._volume; - } - private _volume: number; - - /** - * Event emitted when user changes volume. - */ - @Output() public volumeChanged = new EventEmitter(); - - /** - * @internal - * @ignore - */ - public isMute = false; - - /** - * @internal - * @ignore - */ - public previuseVolume = 0; - - /** - * @internal - * @ignore - */ - public isMoveSlider = false; - - /** - * @internal - * @ignore - */ - public locale$: Observable; - - /** - * @ignore - */ - constructor( - /** - * @internal - */ - public localeService: ESLocaleService - ) { - this.locale$ = this.localeService.locale(); - } - - /** - * @internal - * @ignore - */ - public onVolumeChanged(value: number) { - this.isMoveSlider = false; - this.isMute = !value; - - this.volume = value; - - if (!value) { - this.previuseVolume = 0; - } - this.volumeChanged.emit(value); - } - - /** - * @internal - * @ignore - */ - public onVolumeSliderMove(value: any) { - const val = +value.target.value; - this.isMoveSlider = true; - this.isMute = !val; - - this.volumeChanged.emit(val); - } - - /** - * @internal - * @ignore - */ - public onMute() { - this.isMute = !this.isMute; - - if (this.isMute) { - this.previuseVolume = this.volume; - this.volume = 0; - } else { - this.volume = this.previuseVolume; - } - - this.volumeChanged.emit(this.volume); - } -} diff --git a/projects/elonkit/src/ui/audio-player/components/audio-player-volume/index.ts b/projects/elonkit/src/ui/audio-player/components/audio-player-volume/index.ts deleted file mode 100644 index 09b7c79..0000000 --- a/projects/elonkit/src/ui/audio-player/components/audio-player-volume/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { ESAudioPlayerVolumeComponent } from './audio-player-volume.component'; diff --git a/projects/elonkit/src/ui/audio-player/index.ts b/projects/elonkit/src/ui/audio-player/index.ts deleted file mode 100644 index 7e1a213..0000000 --- a/projects/elonkit/src/ui/audio-player/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './public-api'; diff --git a/projects/elonkit/src/ui/audio-player/public-api.ts b/projects/elonkit/src/ui/audio-player/public-api.ts deleted file mode 100644 index 7fbf1a2..0000000 --- a/projects/elonkit/src/ui/audio-player/public-api.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { ESAudioPlayerModule } from './audio-player.module'; -export { ESAudioPlayerComponent, ESAudioPlayerDefaultOptions, ES_AUDIO_PLAYER_DEFAULT_OPTIONS } from './audio-player.component'; -export { ESAudioPlayerOptionsComponent } from './components/audio-player-options'; -export { ESAudioPlayerTimeSliderComponent } from './components/audio-player-time-slider'; -export { ESAudioPlayerVolumeComponent } from './components/audio-player-volume'; diff --git a/projects/elonkit/src/ui/autocomplete-multiple/__specs__/autocomplete-multiple.spec.ts b/projects/elonkit/src/ui/autocomplete-multiple/__specs__/autocomplete-multiple.spec.ts deleted file mode 100644 index 1eb39b2..0000000 --- a/projects/elonkit/src/ui/autocomplete-multiple/__specs__/autocomplete-multiple.spec.ts +++ /dev/null @@ -1,176 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { ChangeDetectorRef, Component } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; -import { fakeAsync, inject, tick } from '@angular/core/testing'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { OverlayContainer } from '@angular/cdk/overlay'; -import { fireEvent, getByLabelText, render, RenderResult, screen } from '@testing-library/angular'; - -import { of } from 'rxjs'; - -import { ESAutocompleteMultipleModule } from '../autocomplete-multiple.module'; -import { en } from '../../locale'; -import { CoreModule } from '~storybook/core.module'; -import { MatIconTestingModule } from '@angular/material/icon/testing'; - -const OPTIONS = [ - { id: 1, name: 'Estonia' }, - { id: 2, name: 'Iceland' }, - { id: 3, name: 'Norway' }, - { id: 4, name: 'Lithuania' }, - { id: 5, name: 'Sweden' }, - { id: 6, name: 'Austria' }, - { id: 7, name: 'Switzerland' }, - { id: 8, name: 'Albania' }, - { id: 9, name: 'Portugal' }, - { id: 10, name: 'Russia' }, - { id: 11, name: 'India' }, - { id: 12, name: 'Oman' }, -]; - -const FILTERED_OPTIONS = [ - { id: 2, name: 'Iceland' }, - { id: 7, name: 'Switzerland' }, -]; - -const SEARCH_TEXT_LA = 'la'; -const SEARCH_TEXT_O = 'o'; - -const FIND_OPTION_ID = 10; - -@Component({ - template: ` -
- - Country - - - -
- `, -}) -class AutocompleteMultipleComponent { - public form = new FormGroup({ - autocomplete: new FormControl([ - { id: 3, name: 'Norway' }, - { id: 9, name: 'Portugal' }, - { id: 10, name: 'Russia' }, - ]), - }); - - public options = OPTIONS; - - public searchService = (text: string, options?: any[]) => { - const lowerText = text ? text.toLowerCase() : ''; - - const filteredOptions = (options ? options : this.options).filter((option) => option.name.toLowerCase().includes(lowerText)); - - return of(filteredOptions); - }; - - public displayWith = (value: { id: number; name: string }) => value.name; - - constructor(public changeDetector: ChangeDetectorRef) {} -} - -describe('Autocomplete multiple', () => { - let overlay: OverlayContainer; - let overlayElement: HTMLElement; - let component: RenderResult; - - beforeEach(async () => { - component = await render(AutocompleteMultipleComponent, { - imports: [ - CommonModule, - ReactiveFormsModule, - MatFormFieldModule, - CoreModule, - ESAutocompleteMultipleModule, - MatIconTestingModule, - ], - }); - - inject([OverlayContainer], (oc: OverlayContainer) => { - overlay = oc; - overlayElement = oc.getContainerElement(); - })(); - }); - - afterEach(inject([OverlayContainer], (currentOverlay: OverlayContainer) => { - currentOverlay.ngOnDestroy(); - overlay.ngOnDestroy(); - })); - - it('Should display passed options', fakeAsync(async () => { - fireEvent.click(screen.getByLabelText(en.autocompliteMultiple.labelOpenMenu)); - - tick(1000); - - component.fixture.detectChanges(); - - const options = overlayElement.querySelectorAll('[data-testid="mat-option"]'); - expect(options).toHaveLength(OPTIONS.length); - - for (const option of OPTIONS) { - expect(overlayElement.textContent).toContain(option.name); - } - })); - - it('Should display passed options after search', fakeAsync(async () => { - fireEvent.click(screen.getByLabelText(en.autocompliteMultiple.labelOpenMenu)); - - fireEvent.input(getByLabelText(overlayElement, en.autocompliteMultiple.labelSearch), { - target: { value: SEARCH_TEXT_LA }, - }); - - tick(1000); - - component.fixture.detectChanges(); - - const options = overlayElement.querySelectorAll('[data-testid="mat-option"]'); - expect(options).toHaveLength(2); - - for (const option of FILTERED_OPTIONS) { - expect(overlayElement.textContent).toContain(option.name); - } - })); - - it('Should display selected options after a series of actions', fakeAsync(() => { - fireEvent.click(screen.getByLabelText(en.autocompliteMultiple.labelOpenMenu)); - - fireEvent.click(getByLabelText(overlayElement, en.autocompliteMultiple.labelSearchScopeSelected)); - - tick(500); - - component.fixture.detectChanges(); - - let options = overlayElement.querySelectorAll('[data-testid="mat-option"]'); - - expect(options).toHaveLength(3); - - fireEvent.input(getByLabelText(overlayElement, en.autocompliteMultiple.labelSearch), { - target: { value: SEARCH_TEXT_O }, - }); - tick(500); - - component.fixture.detectChanges(); - - options = overlayElement.querySelectorAll('[data-testid="mat-option"]'); - - expect(options).toHaveLength(2); - - fireEvent.click(getByLabelText(overlayElement, en.autocompliteMultiple.labelRemoveChoice)); - tick(500); - - component.fixture.detectChanges(); - - const { autocomplete } = component.fixture.componentInstance.form.value; - - expect(autocomplete).toHaveLength(1); - - expect(autocomplete[0].id).toBe(FIND_OPTION_ID); - })); -}); diff --git a/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.component.scss b/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.component.scss deleted file mode 100644 index 8a786e6..0000000 --- a/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.component.scss +++ /dev/null @@ -1,19 +0,0 @@ -.es-autocomplete-multiple-story-service { - width: 100%; - - &__field.mat-form-field { - width: 300px; - - &.mat-form-field-appearance-outline { - .mat-form-field-infix { - border-top: 0; - padding-bottom: 16px; - padding-top: 16px; - } - - .mat-form-field-label { - top: 2.4em; - } - } - } -} diff --git a/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.component.ts b/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.component.ts deleted file mode 100644 index db1c427..0000000 --- a/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.component.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { Component, Input, ViewEncapsulation } from '@angular/core'; -import { FormBuilder, FormGroup } from '@angular/forms'; - -import { of } from 'rxjs'; -import { map, tap } from 'rxjs/operators'; - -import { AutocompleteMultipleStoryService } from './autocomplete-multiple-story-service.service'; - -@Component({ - selector: 'es-autocomplete-multiple-story-service', - styleUrls: ['./autocomplete-multiple-story-service.component.scss'], - encapsulation: ViewEncapsulation.None, - template: ` -
- - Country - - - -
- `, -}) -export class AutocompleteMultipleStoryServiceComponent { - @Input() public width: number; - - @Input() public showedOptionCount = null; - - @Input() public required: boolean; - - @Input() public disabled: boolean; - - public form: FormGroup; - - public totalOptionCount: number; - - constructor( - private service: AutocompleteMultipleStoryService, - private formBuilder: FormBuilder - ) { - this.form = this.formBuilder.group({ - autocomplete: [ - [ - { id: 3, name: 'Norway' }, - { id: 9, name: 'Portugal' }, - { id: 10, name: 'Russia' }, - ], - ], - }); - } - - public searchService = (text: string, options?: any[]) => { - const lowerText = text ? text.toLowerCase() : ''; - - this.totalOptionCount = 0; - - if (options) { - return of(options.filter((option) => option.name.toLowerCase().includes(lowerText))).pipe( - tap((o) => { - this.totalOptionCount = o.length; - }) - ); - } else { - return this.service.getOptions(lowerText, this.showedOptionCount).pipe( - map((o) => { - this.totalOptionCount = o.totalCount; - - return o.options; - }) - ); - } - }; - - public displayWith = (value: { id: number; name: string }) => value.name; -} diff --git a/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.module.ts b/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.module.ts deleted file mode 100644 index 8ace770..0000000 --- a/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.module.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { ReactiveFormsModule } from '@angular/forms'; -import { MatFormFieldModule } from '@angular/material/form-field'; - -import { CoreModule } from '../../../../../.storybook/core.module'; - -import { ESAutocompleteMultipleModule } from '../..'; - -import { AutocompleteMultipleStoryServiceComponent } from './autocomplete-multiple-story-service.component'; -import { AutocompleteMultipleStoryService } from './autocomplete-multiple-story-service.service'; - -@NgModule({ - declarations: [AutocompleteMultipleStoryServiceComponent], - imports: [CommonModule, ReactiveFormsModule, MatFormFieldModule, CoreModule, ESAutocompleteMultipleModule], - exports: [AutocompleteMultipleStoryServiceComponent], - providers: [AutocompleteMultipleStoryService], -}) -export class AutocompleteMultipleStoryServiceModule {} diff --git a/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.service.ts b/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.service.ts deleted file mode 100644 index 9c2b859..0000000 --- a/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.service.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Injectable } from '@angular/core'; - -import { Observable, of } from 'rxjs'; -import { debounceTime, map } from 'rxjs/operators'; - -const OPTIONS = [ - { id: 1, name: 'Estonia' }, - { id: 2, name: 'Iceland' }, - { id: 3, name: 'Norway' }, - { id: 4, name: 'Lithuania' }, - { id: 5, name: 'Sweden' }, - { id: 6, name: 'Austria' }, - { id: 7, name: 'Switzerland' }, - { id: 8, name: 'Albania' }, - { id: 9, name: 'Portugal' }, - { id: 10, name: 'Russia' }, - { id: 11, name: 'India' }, - { id: 12, name: 'Oman' }, -]; - -@Injectable() -export class AutocompleteMultipleStoryService { - public getOptions(text: string, count?: number | null): Observable { - return of(OPTIONS).pipe( - debounceTime(1000), - map((options) => options.filter((option) => option.name.toLowerCase().includes(text))), - map((options) => { - const o = count ? options.slice(0, count) : options; - - return { - options: o, - totalCount: count ? Math.min(count, o.length) : o.length, - }; - }) - ); - } -} diff --git a/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.source.ts b/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.source.ts deleted file mode 100644 index 62280e4..0000000 --- a/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/autocomplete-multiple-story-service.source.ts +++ /dev/null @@ -1,87 +0,0 @@ -export const AUTOCOMPLETE_MULTIPLE_STORY_SERVICE_SOURCE = { - ts: ` - import { Component, Input, ViewEncapsulation } from '@angular/core'; - import { FormBuilder, FormGroup } from '@angular/forms'; - - import { of } from 'rxjs'; - import { map, tap } from 'rxjs/operators'; - - import { AutocompleteMultipleStoryService } from './autocomplete-multiple-story-service.service'; - - @Component({ - selector: 'es-autocomplete-multiple-story-service', - styleUrls: ['./autocomplete-multiple-story-service.component.scss'], - encapsulation: ViewEncapsulation.None - }) - export class AutocompleteMultipleStoryServiceComponent { - @Input() public width: number; - - @Input() public showedOptionCount = null; - - @Input() public required: boolean; - - @Input() public disabled: boolean; - - public form: FormGroup; - - public totalOptionCount: number; - - constructor(private service: AutocompleteMultipleStoryService, private formBuilder: FormBuilder) { - this.form = this.formBuilder.group({ - autocomplete: [ - [ - { id: 3, name: 'Norway' }, - { id: 9, name: 'Portugal' }, - { id: 10, name: 'Russia' } - ] - ] - }); - } - - public searchService = (text: string, options?: any[]) => { - const lowerText = text ? text.toLowerCase() : ''; - - this.totalOptionCount = 0; - - if (options) { - return of(options.filter((option) => option.name.toLowerCase().includes(lowerText))).pipe( - tap((o) => { - this.totalOptionCount = o.length; - }) - ); - } else { - return this.service.getOptions(lowerText, this.showedOptionCount).pipe( - map((o) => { - this.totalOptionCount = o.totalCount; - - return o.options; - }) - ); - } - }; - - public displayWith = (value: { id: number; name: string }) => value.name; - } - - `, - html: ` -
- - Country - - - -
- `, -}; diff --git a/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/index.ts b/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/index.ts deleted file mode 100644 index 866238b..0000000 --- a/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple-story-service/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { AUTOCOMPLETE_MULTIPLE_STORY_SERVICE_SOURCE } from './autocomplete-multiple-story-service.source'; -export { AutocompleteMultipleStoryServiceModule } from './autocomplete-multiple-story-service.module'; -export { AutocompleteMultipleStoryServiceComponent } from './autocomplete-multiple-story-service.component'; diff --git a/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple.stories.mdx b/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple.stories.mdx deleted file mode 100644 index 1c1ddcb..0000000 --- a/projects/elonkit/src/ui/autocomplete-multiple/__stories__/autocomplete-multiple.stories.mdx +++ /dev/null @@ -1,93 +0,0 @@ -import { Meta, Story, ArgsTable } from '@storybook/addon-docs'; -import { Canvas } from '~storybook/components'; - -import { HttpClientModule } from '@angular/common/http'; - -import { action } from '@storybook/addon-actions'; - -import { ESAutocompleteMultipleComponent } from '..'; - -import { - AutocompleteMultipleStoryServiceModule, - AutocompleteMultipleStoryServiceComponent, - AUTOCOMPLETE_MULTIPLE_STORY_SERVICE_SOURCE, -} from './autocomplete-multiple-story-service'; - - - -# Autocomplete multiple - -Autocomplete multiple is component for multiple select options with support for autocomplete. - -## Demos - - - - {((args) => ({ - component: AutocompleteMultipleStoryServiceComponent, - moduleMetadata: { - imports: [HttpClientModule, AutocompleteMultipleStoryServiceModule], - }, - props: { - ...args, - }, - })).bind({})} - - - -## API - - - -## Interfaces - -```ts -interface ESAutocompleteMultipleDefaultOptionsSizes { - chipLeftMargin: number; - countBadgeMaxWidth: number; -} -``` - -## Constants - -Injection token that can be used to configure the default options for all components within an app. - -```ts -import { ES_AUTOCOMPLETE_MULTIPLE_DEFAULT_OPTIONS } from '@elonkit/angular/ui/autocomplete-multiple'; - -@NgModule({ - providers: [ - { - provide: ES_AUTOCOMPLETE_MULTIPLE_DEFAULT_OPTIONS, - useValue: { - sizes: { - chipLeftMargin: 4, - countBadgeMaxWidth: 40 - } - } - } - ] -}) -``` diff --git a/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.animations.ts b/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.animations.ts deleted file mode 100644 index ca5484a..0000000 --- a/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.animations.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { animate, state, style, transition, trigger } from '@angular/animations'; - -export const ES_AUTOCOMPLETE_ANIMATIONS = [ - trigger('panel', [ - state('void', style({ transform: 'scaleY(0.8)', opacity: 0 })), - state('*', style({ opacity: 1, transform: 'scaleY(1)' })), - transition('void => *', animate('120ms cubic-bezier(0, 0, 0.2, 1)')), - transition('* => void', animate('100ms 25ms linear', style({ opacity: 0 }))), - ]), -]; diff --git a/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.component.html b/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.component.html deleted file mode 100644 index c85e9bc..0000000 --- a/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.component.html +++ /dev/null @@ -1,156 +0,0 @@ -
-
- - - - - - - - - -
- - - - -
- - -
- - {{ locale.autocompliteMultiple.labelTabAll }} - {{ locale.autocompliteMultiple.labelTabSelected }} - {{ locale.autocompliteMultiple.labelTabNotSelected }} - - - - - -
- - - -
- - - - {{ displayWith(option) }} - - - - -
- - -
-
diff --git a/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.component.scss b/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.component.scss deleted file mode 100644 index 3033ad8..0000000 --- a/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.component.scss +++ /dev/null @@ -1,231 +0,0 @@ -.es-autocomplete-multiple { - width: 100%; - height: 24px; - display: flex; - justify-content: space-between; - align-items: center; - - &__value { - max-width: calc(100% - 48px); - display: flex; - justify-content: flex-start; - flex: 1; - padding-right: 4px; - white-space: nowrap; - } - - &__chip-list { - width: 100%; - height: 24px; - flex-wrap: nowrap; - - .mat-chip-list-wrapper { - width: 100%; - margin: 0; - flex-wrap: nowrap; - overflow: hidden; - - .mat-standard-chip { - margin: 0; - } - } - } - - &__chip { - &.mat-standard-chip { - max-width: 160px; - min-height: 24px; - - &:not(:first-child) { - margin-left: 4px; - } - } - - .mat-chip-remove { - min-width: 18px; - } - } - - &__chip-text { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - &__count { - height: 24px; - padding: 4px 5px 4px 4px; - align-items: center; - border: 0 none; - border-radius: 96px; - box-sizing: border-box; - cursor: pointer; - margin-left: 4px; - outline: none; - - &_disabled { - cursor: default; - opacity: 0.7; - } - } - - &__clear.mat-icon-button { - width: 20px; - height: 20px; - display: flex; - justify-content: center; - align-items: center; - margin-left: 4px; - margin-right: 1px; - - .mat-icon { - font-size: 20px; - width: 20px; - height: 20px; - } - } - - &__arrow.mat-icon-button { - width: 18px; - height: 18px; - line-height: 18px; - - .mat-icon { - font-size: 18px; - width: 18px; - height: 18px; - } - } - - &__panel { - border-radius: 4px; - display: flex; - flex-direction: column; - overflow: hidden; - transform-origin: center top; - } - - &__toggle-group { - display: flex; - - &.mat-button-toggle-group-appearance-standard { - border: 0 none; - border-radius: 0; - } - } - - &__button-toggle { - flex: 1; - - &.mat-button-toggle + &.mat-button-toggle { - border-left: 0 none; - } - - &.mat-button-toggle-appearance-standard { - border-bottom-style: solid; - border-bottom-width: 1px; - - &.mat-button-toggle-checked { - border-bottom-width: 2px; - } - - .mat-button-toggle-label-content { - line-height: 32px; - } - } - } - - &__options { - max-height: 208px; - overflow: auto; - - &.mat-list-base { - padding: 0; - } - } - - &__option { - &:first-child { - margin-top: 8px; - } - - &:last-child { - margin-bottom: 8px; - } - - &.mat-list-option.mat-list-option .mat-list-item-content .mat-list-text { - padding-left: 8px; - } - - .mat-list-text { - white-space: nowrap; - } - } - - &__menu { - height: 32px; - display: flex; - align-items: center; - border-bottom-style: solid; - border-bottom-width: 1px; - padding-left: 8px; - } - - &__menu-button { - height: 32px; - - &.mat-button { - border-radius: 0; - height: 32px; - line-height: 32px; - padding: 0 8px; - } - } - - &__footer { - padding: 6px 16px; - display: flex; - justify-content: space-between; - } -} - -.es-autocomplete-multiple-search { - padding: 10px 12px; - display: flex; - align-items: center; - border-bottom-style: solid; - border-bottom-width: 1px; - - &__icon { - flex-shrink: 0; - margin-right: 8px; - } - - &__input { - height: 24px; - padding: 0; - display: block; - background: none; - border: 0; - flex: 1; - outline: none; - } - - &__clear.mat-icon-button { - width: 24px; - height: 24px; - display: flex; - justify-content: center; - align-items: center; - flex-shrink: 0; - line-height: 24px; - margin-left: 8px; - - .mat-icon { - width: 16px; - height: 16px; - display: flex; - font-size: 16px; - } - } -} diff --git a/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.component.ts b/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.component.ts deleted file mode 100644 index 2867eef..0000000 --- a/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.component.ts +++ /dev/null @@ -1,649 +0,0 @@ -import { - Component, - ChangeDetectionStrategy, - ChangeDetectorRef, - ViewEncapsulation, - OnInit, - OnDestroy, - Input, - ViewChild, - HostBinding, - Optional, - Self, - Host, - ElementRef, - AfterViewInit, - Renderer2, - Inject, - InjectionToken, -} from '@angular/core'; -import { ControlValueAccessor, FormControl, FormGroup, FormGroupDirective, NgControl } from '@angular/forms'; - -import { FocusMonitor } from '@angular/cdk/a11y'; -import { coerceBooleanProperty } from '@angular/cdk/coercion'; -import { CdkOverlayOrigin } from '@angular/cdk/overlay'; - -import { MatButton } from '@angular/material/button'; -import { MatChipListbox } from '@angular/material/chips'; -import { MatFormField, MatFormFieldControl } from '@angular/material/form-field'; -import { MatSelectionList, MatSelectionListChange } from '@angular/material/list'; - -import { Observable, Subject, combineLatest, of, BehaviorSubject } from 'rxjs'; -import { catchError, debounceTime, filter, map, shareReplay, startWith, switchMap, takeUntil, tap } from 'rxjs/operators'; - -import { resizeObserver } from '../../utils/resize-observer'; -import { ESLocale, ESLocaleService } from '../locale'; - -import { ES_AUTOCOMPLETE_ANIMATIONS } from './autocomplete-multiple.animations'; -import { ESAutocompleteMultipleSearchScope } from '.'; - -export interface ESAutocompleteMultipleDefaultOptionsSizes { - chipLeftMargin: number; - countBadgeMaxWidth: number; -} - -export interface ESAutocompleteMultipleDefaultOptions { - sizes?: ESAutocompleteMultipleDefaultOptionsSizes; -} - -export const ES_AUTOCOMPLETE_MULTIPLE_DEFAULT_SIZES = { - chipLeftMargin: 4, - countBadgeMaxWidth: 40, -}; - -export const ES_AUTOCOMPLETE_MULTIPLE_DEFAULT_OPTIONS = new InjectionToken( - 'ES_AUTOCOMPLETE_MULTIPLE_DEFAULT_OPTIONS' -); - -const MIN_PANEL_WIDTH = 320; - -@Component({ - selector: 'es-autocomplete-multiple', - templateUrl: './autocomplete-multiple.component.html', - styleUrls: ['./autocomplete-multiple.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, - providers: [{ provide: MatFormFieldControl, useExisting: ESAutocompleteMultipleComponent }], - animations: ES_AUTOCOMPLETE_ANIMATIONS, -}) -export class ESAutocompleteMultipleComponent - implements MatFormFieldControl, ControlValueAccessor, OnInit, OnDestroy, AfterViewInit -{ - private static nextId = 0; - @HostBinding() public id = `es-autocomplete-multiple-${ESAutocompleteMultipleComponent.nextId++}`; - @HostBinding('style.display') public styleDisplay = 'block'; - @HostBinding('style.width') public styleWidth = '100%'; - - @ViewChild('input', { static: false }) private input?: ElementRef; - @ViewChild('arrow', { static: true }) private arrow?: MatButton; - @ViewChild('selectionList', { static: false }) private selectionList?: MatSelectionList; - @ViewChild('chipList', { static: false }) private chipList?: MatChipListbox; - - /** Options search service. When second argument is present, the search should be performed by passed down options. */ - @Input() public service!: (search: string | null | undefined, options?: any[]) => Observable; - - /** Function that maps an option control value to its display value in the trigger. */ - @Input() public displayWith!: (option: any) => string; - - /** Delay before starting search after entering search text. */ - @Input() public searchDebounce = 400; - - /** Placeholder for search input. */ - @Input() - public get placeholder() { - return this._placeholder; - } - public set placeholder(placeholder) { - this._placeholder = placeholder; - this.stateChanges.next(); - } - private _placeholder = ''; - - /** Whether the control is required. */ - @Input() - public get required() { - return this._required; - } - public set required(required) { - this._required = coerceBooleanProperty(required); - this.stateChanges.next(); - } - private _required = false; - - /** Whether the control is disabled. */ - @Input() - public get disabled() { - return this._disabled; - } - public set disabled(disabled) { - this._disabled = coerceBooleanProperty(disabled); - this.stateChanges.next(); - } - private _disabled = false; - - /** - * Sizes of component elements which are used for collapse calculations. - */ - @Input() - public get sizes(): ESAutocompleteMultipleDefaultOptionsSizes { - return this._sizes; - } - public set sizes(value: ESAutocompleteMultipleDefaultOptionsSizes) { - this._sizes = value || this.defaultOptions?.sizes || ES_AUTOCOMPLETE_MULTIPLE_DEFAULT_SIZES; - } - private _sizes: ESAutocompleteMultipleDefaultOptionsSizes; - - /** Total number of options. */ - @Input() - public get optionsCount(): number { - return this._optionsCount || 0; - } - public set optionsCount(value: number) { - this._optionsCount = value || 0; - } - private _optionsCount: number; - - /** - * @internal - * @ignore - */ - public locale$: Observable; - - /** - * @internal - * @ignore - */ - public origin!: CdkOverlayOrigin; - - /** - * @ignore - */ - public describedBy = ''; - - /** - * @internal - * @ignore - */ - private destoryed$ = new Subject(); - - /** - * @ignore - */ - public stateChanges = new Subject(); - - /** - * @ignore - */ - public value: any[] = []; - - /** - * @internal - * @ignore - */ - public isOpen = false; - - /** - * @internal - * @ignore - */ - public width = 0; - - /** - * @internal - * @ignore - */ - public selectionChanged$ = new BehaviorSubject(false); - - /** - * @internal - * @ignore - */ - public options$: Observable; - - /** - * @internal - * @ignore - */ - public filteredOptions$: Observable; - - /** - * @ignore - */ - public focused = false; - - /** - * @internal - * @ignore - */ - public searchScope = ESAutocompleteMultipleSearchScope; - - /** - * @internal - * @ignore - */ - public form = new FormGroup({ - scope: new FormControl(this.searchScope.ALL), - text: new FormControl(''), - }); - - /** - * @internal - * @ignore - */ - public hiddenChipCount = 0; - - /** - * @internal - * @ignore - */ - private filteredOptionsCount = 0; - - /** - * @ignore - */ - @HostBinding('class.floating') - public get shouldLabelFloat() { - return this.focused || !this.empty; - } - - /** - * @ignore - */ - public get errorState(): boolean { - const control = this.ngControl; - const form = this.ngForm; - - if (control) { - return !!(control.invalid && (control.touched || form?.submitted)); - } - - return false; - } - - /** - * @ignore - */ - public get empty() { - return !this.value.length; - } - - /** - * @ignore - */ - constructor( - @Optional() @Self() public ngControl: NgControl, - @Optional() public ngForm: FormGroupDirective, - /** - * @internal - */ - @Optional() @Host() private matFormField: MatFormField, - @Optional() - @Inject(ES_AUTOCOMPLETE_MULTIPLE_DEFAULT_OPTIONS) - private defaultOptions: ESAutocompleteMultipleDefaultOptions, - /** - * @internal - */ - private changeDetectorRef: ChangeDetectorRef, - /** - * @internal - */ - private focusMonitor: FocusMonitor, - /** - * @internal - */ - private rendered2: Renderer2, - /** - * @internal - */ - private elementRef: ElementRef, - /** - * @internal - */ - public localeService: ESLocaleService - ) { - if (this.ngControl != null) { - this.ngControl.valueAccessor = this as any; - } - this.locale$ = this.localeService.locale(); - - this.sizes = defaultOptions?.sizes || ES_AUTOCOMPLETE_MULTIPLE_DEFAULT_SIZES; - - this.options$ = this.form.valueChanges.pipe( - startWith({ scope: this.searchScope.ALL, text: '' }), - debounceTime(this.searchDebounce), - switchMap(({ scope, text }) => { - this.filteredOptionsCount = 0; - - if (scope === this.searchScope.SELECTED) { - return this.service(text, this.value).pipe(catchError(() => of([]))); - } - - return this.service(text).pipe(catchError(() => of([]))); - }), - shareReplay(1) - ); - - this.filteredOptions$ = combineLatest([this.options$, this.selectionChanged$.pipe(filter(() => this.isOpen))]).pipe( - debounceTime(100), - map(([options]) => { - const { scope } = this.form.value; - - if (scope === this.searchScope.ALL) { - return options; - } - - const filtered = - scope === this.searchScope.SELECTED - ? options.filter((option) => this.value.some((o) => o.id === option.id)) - : options.filter((option) => !this.value.some((o) => o.id === option.id)); - - this.optionsCount = this.optionsCount - options.length + filtered.length; - - return filtered; - }), - tap((options) => { - this.filteredOptionsCount = options.length; - }) - ); - } - - /** - * @ignore - */ - public ngOnInit() { - if (this.matFormField) { - this.origin = { - elementRef: this.matFormField.getConnectedOverlayOrigin(), - }; - } - - this.stateChanges.subscribe(() => { - this.changeDetectorRef.detectChanges(); - }); - } - - /** - * @ignore - */ - public ngAfterViewInit() { - combineLatest([ - // tslint:disable-next-line:deprecation - resizeObserver(this.elementRef.nativeElement).pipe(startWith(null), debounceTime(10)), - this.selectionChanged$, - ]) - .pipe(takeUntil(this.destoryed$)) - .subscribe(() => { - this.updateDisplayedChips(); - }); - } - - /** - * @ignore - */ - public ngOnDestroy() { - this.destoryed$.next(); - this.destoryed$.complete(); - this.stateChanges.complete(); - } - - /** - * @ignore - */ - public setDescribedByIds(ids: string[]) { - this.describedBy = ids.join(' '); - } - - /** - * @ignore - */ - public onContainerClick() { - if (this.ngControl.disabled || this.disabled) { - return; - } - - this.isOpen = true; - if (this.matFormField) { - const width = this.matFormField._elementRef.nativeElement.clientWidth; - - this.width = width < MIN_PANEL_WIDTH ? MIN_PANEL_WIDTH : width; - } - this.stateChanges.next(); - - setTimeout(() => { - if (this.input) { - this.input.nativeElement.focus(); - } - }); - } - - /** - * @ignore - */ - public writeValue(value: any[]) { - if (value) { - this.value = value; - this.stateChanges.next(); - } - } - - /** - * @ignore - */ - public registerOnChange(onChange: (value: any) => void) { - this.onChange = onChange; - } - - /** - * @ignore - */ - public onChange = (_: any[]) => {}; - - /** - * @ignore - */ - public registerOnTouched(onTouched: () => void) { - this.onTouched = onTouched; - } - - /** - * @ignore - */ - public onTouched = () => {}; - - /** - * @internal - * @ignore - */ - public onClose(shouldFocusArrow?: boolean) { - this.onTouched(); - this.isOpen = false; - this.form.patchValue({ text: '', scope: this.searchScope.ALL }); - - if (shouldFocusArrow && this.arrow) { - this.focusMonitor.focusVia(this.arrow._elementRef.nativeElement, 'keyboard'); - } - - this.stateChanges.next(); - } - - /** - * @internal - * @ignore - */ - public onClear() { - this.form.patchValue({ text: '' }); - } - - /** - * @internal - * @ignore - */ - public onSelectionChange(event: any) { - const newValue = this.value.slice(); - const option = event.option.value; - - const index = newValue.findIndex((o) => o.id === option.id); - if (index !== -1) { - newValue.splice(index, 1); - } else { - newValue.push(option); - } - - this.value = newValue; - this.changeState(this.value); - } - - /** - * @internal - * @ignore - */ - public onSelectAll() { - const newValue = this.value.slice(); - - this.selectionList?.options.forEach((option) => { - const index = newValue.findIndex((o) => o.id === option.value.id); - - if (index === -1) { - newValue.push(option.value); - } - }); - - this.value = newValue; - this.changeState(this.value); - } - - /** - * @internal - * @ignore - */ - public onDeSelectAll() { - if (this.value.length) { - const newValue = this.value.slice(); - - this.selectionList?.options.forEach((option) => { - const index = newValue.findIndex((o) => o.id === option.value.id); - - if (index !== -1) { - newValue.splice(index, 1); - } - }); - - this.value = newValue; - this.changeState(this.value); - } - } - - /** - * @internal - * @ignore - */ - public onRemoveAll(event: Event) { - event.stopPropagation(); - - this.value = []; - this.changeState(this.value); - } - - /** - * @internal - * @ignore - */ - public onRemove(index: number) { - this.value.splice(index, 1); - this.changeState(this.value); - } - - /** - * @internal - * @ignore - */ - public onShowSelectedTab() { - this.form.patchValue({ scope: this.searchScope.SELECTED }); - } - - /** - * @internal - * @ignore - */ - public isSelected(option: any) { - return !!this.value.find((o) => o.id === option.id); - } - - /** - * @internal - * @ignore - */ - public getShownCountInfo(labelShown: string, labelOf: string) { - return `${labelShown}: ${this.filteredOptionsCount} ${labelOf} ${this.optionsCount}`; - } - - /** - * @internal - * @ignore - */ - public updateDisplayedChips() { - if (this.chipList) { - let count = 0; - - const chips = this.chipList._chips; - - let isOverflow = false; - let offset = 0; - - chips.forEach((chip: any, index: number) => { - this.rendered2.setStyle(chip._elementRef.nativeElement, 'display', 'inline-flex'); - this.rendered2.setStyle(chip._elementRef.nativeElement, 'width', 'auto'); - - const { width: chipListWidth } = chip._elementRef.nativeElement.parentElement.getBoundingClientRect(); - - const { width: chipWidth } = chip._elementRef.nativeElement.getBoundingClientRect(); - - offset += chipWidth; - - if (isOverflow) { - count += 1; - - this.rendered2.setStyle(chip._elementRef.nativeElement, 'display', 'none'); - } else if (chips.length === 1 && chipWidth > chipListWidth) { - this.rendered2.setStyle(chip._elementRef.nativeElement, 'width', `${chipListWidth}px`); - } else if (chips.length === 1) { - this.rendered2.setStyle(chip._elementRef.nativeElement, 'width', 'auto'); - } else { - if (offset <= chipListWidth && index === chips.length - 1) { - return; - } else if (offset > chipListWidth - this.sizes.countBadgeMaxWidth && index) { - count += 1; - - isOverflow = true; - - this.rendered2.setStyle(chip._elementRef.nativeElement, 'display', 'none'); - } else { - const width = - chipWidth + this.sizes.countBadgeMaxWidth > chipListWidth - ? chipListWidth - this.sizes.countBadgeMaxWidth - : chipWidth; - - this.rendered2.setStyle(chip._elementRef.nativeElement, 'width', `${width}px`); - } - } - - offset += this.sizes.chipLeftMargin; - }); - - if (this.hiddenChipCount !== count) { - this.hiddenChipCount = count; - this.stateChanges.next(); - } - } - } - - /** - * @internal - * @ignore - */ - private changeState(value: any[]) { - this.onChange(value); - this.stateChanges.next(); - this.selectionChanged$.next(true); - } -} diff --git a/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.module.ts b/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.module.ts deleted file mode 100644 index 5222726..0000000 --- a/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.module.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { ReactiveFormsModule } from '@angular/forms'; - -import { MatButtonModule } from '@angular/material/button'; -import { MatButtonToggleModule } from '@angular/material/button-toggle'; -import { MatChipsModule } from '@angular/material/chips'; -import { MatIconModule } from '@angular/material/icon'; -import { MatInputModule } from '@angular/material/input'; -import { MatListModule } from '@angular/material/list'; - -import { A11yModule } from '@angular/cdk/a11y'; -import { OverlayModule } from '@angular/cdk/overlay'; - -import { ESAutocompleteMultipleComponent } from './autocomplete-multiple.component'; -import { ESTooltipModule } from '../tooltip'; - -@NgModule({ - imports: [ - CommonModule, - ReactiveFormsModule, - MatButtonModule, - MatButtonToggleModule, - MatChipsModule, - MatIconModule, - MatInputModule, - MatListModule, - A11yModule, - OverlayModule, - ESTooltipModule, - ], - exports: [ESAutocompleteMultipleComponent], - declarations: [ESAutocompleteMultipleComponent], -}) -export class ESAutocompleteMultipleModule {} diff --git a/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.theme.scss b/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.theme.scss deleted file mode 100644 index 1145787..0000000 --- a/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.theme.scss +++ /dev/null @@ -1,103 +0,0 @@ -@mixin es-autocomplete-multiple-theme($theme, $elonkit-theme) { - $accent: map-get($theme, accent); - $mono-a: map-get($elonkit-theme, mono-a); - $mono-b: map-get($elonkit-theme, mono-b); - $primary: map-get($theme, primary); - $surface: map-get($elonkit-theme, surface); - $warn: map-get($theme, warn); - - .es-autocomplete-multiple { - &__chip { - &.mat-standard-chip { - background-color: mat.get-color-from-palette($mono-a, A100); - color: mat.get-color-from-palette($mono-a, A900); - - .mat-chip-remove { - color: mat.get-color-from-palette($mono-a, A500); - } - } - } - - &__count { - background-color: mat.get-color-from-palette($mono-a, A50); - color: mat.get-color-from-palette($mono-a, A600); - } - - &__clear { - color: mat.get-color-from-palette($mono-a, A400); - } - - &__panel { - background-color: mat.get-color-from-palette($surface, 4); - } - - &__menu { - border-bottom-color: mat.get-color-from-palette($mono-a, A100); - } - - &__menu-button { - color: mat.get-color-from-palette($mono-a, A700); - } - - &__button-toggle { - color: mat.get-color-from-palette($mono-a, A600); - - &.mat-button-toggle-appearance-standard { - border-color: mat.get-color-from-palette($mono-a, A100); - - &.mat-button-toggle-checked { - background: mat.get-color-from-palette($mono-b, 500); - border-color: mat.get-color-from-palette($primary, 300); - color: mat.get-color-from-palette($mono-a, A900); - } - } - } - - &__option { - &_selected { - background-color: mat.get-color-from-palette($accent, A100); - - .mat-pseudo-checkbox-checked { - background-color: mat.get-color-from-palette($accent, 300); - } - } - } - - &__divider { - color: mat.get-color-from-palette($mono-a, A100); - } - - &__footer { - color: mat.get-color-from-palette($mono-a, A600); - } - } - - .es-autocomplete-multiple-search { - border-bottom-color: mat.get-color-from-palette($mono-a, A100); - - &__input { - color: mat.get-color-from-palette($mono-a, A900); - - &::placeholder { - color: mat.get-color-from-palette($mono-a, A400); - } - } - - &__icon { - color: mat.get-color-from-palette($mono-a, A500); - } - - &__clear.mat-icon-button { - color: mat.get-color-from-palette($mono-a, A400); - - &:hover, - &:focus { - color: mat.get-color-from-palette($warn, 500); - } - - .mat-button-focus-overlay { - background-color: mat.get-color-from-palette($warn, A50); - } - } - } -} diff --git a/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.types.ts b/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.types.ts deleted file mode 100644 index 262d152..0000000 --- a/projects/elonkit/src/ui/autocomplete-multiple/autocomplete-multiple.types.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum ESAutocompleteMultipleSearchScope { - ALL = 'all', - SELECTED = 'selected', - NOT_SELECTED = 'not_selected', -} diff --git a/projects/elonkit/src/ui/autocomplete-multiple/index.ts b/projects/elonkit/src/ui/autocomplete-multiple/index.ts deleted file mode 100644 index 7e1a213..0000000 --- a/projects/elonkit/src/ui/autocomplete-multiple/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './public-api'; diff --git a/projects/elonkit/src/ui/autocomplete-multiple/public-api.ts b/projects/elonkit/src/ui/autocomplete-multiple/public-api.ts deleted file mode 100644 index b011fb0..0000000 --- a/projects/elonkit/src/ui/autocomplete-multiple/public-api.ts +++ /dev/null @@ -1,8 +0,0 @@ -export { ESAutocompleteMultipleModule } from './autocomplete-multiple.module'; -export { - ESAutocompleteMultipleDefaultOptionsSizes, - ESAutocompleteMultipleDefaultOptions, - ES_AUTOCOMPLETE_MULTIPLE_DEFAULT_OPTIONS, - ESAutocompleteMultipleComponent, -} from './autocomplete-multiple.component'; -export { ESAutocompleteMultipleSearchScope } from './autocomplete-multiple.types'; diff --git a/projects/elonkit/src/ui/avatar/__specs__/avatar.spec.ts b/projects/elonkit/src/ui/avatar/__specs__/avatar.spec.ts deleted file mode 100644 index 1715ed7..0000000 --- a/projects/elonkit/src/ui/avatar/__specs__/avatar.spec.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { Component } from '@angular/core'; -import { render } from '@testing-library/angular'; - -import { ESAvatarComponent } from '../avatar.component'; -import { ESAvatarModule } from '../avatar.module'; -import { ESAvatarVariant } from '../avatar.types'; - -@Component({ - template: `Message`, -}) -class AvatarTypographyComponent {} - -describe('Avatar', () => { - it('Should change avatar variant to round', async () => { - const component = await render(ESAvatarComponent, { - componentProperties: { - variant: ESAvatarVariant.Round, - }, - imports: [ESAvatarModule], - excludeComponentDeclaration: true, - }); - expect(component.getByTestId('avatar')).toHaveClass('es-avatar_variant_round'); - }); - - it('Should change avatar variant to square', async () => { - const component = await render(ESAvatarComponent, { - componentProperties: { - variant: ESAvatarVariant.Square, - }, - imports: [ESAvatarModule], - excludeComponentDeclaration: true, - }); - expect(component.getByTestId('avatar')).toHaveClass('es-avatar_variant_square'); - }); - - it('Should change avatar properties', async () => { - const component = await render(ESAvatarComponent, { - componentProperties: { - size: 200, - }, - imports: [ESAvatarModule], - excludeComponentDeclaration: true, - }); - - expect(component.fixture.componentInstance.size).toBe(200); - }); - - it('Should render text avatar', async () => { - const component = await render(AvatarTypographyComponent, { - imports: [ESAvatarModule], - }); - expect(component.getByText('Message')).toBeInTheDocument(); - }); - - it('Should accept class typography', async () => { - const component = await render(ESAvatarComponent, { - componentProperties: { - typography: 'test-class', - }, - imports: [ESAvatarModule], - excludeComponentDeclaration: true, - }); - - expect(component.getByTestId('typography')).toHaveClass('test-class'); - }); - - it('Should render image with alt text', async () => { - const component = await render(ESAvatarComponent, { - componentProperties: { - src: './test-path-to-icon', - alt: 'alt text', - }, - imports: [ESAvatarModule], - excludeComponentDeclaration: true, - }); - - expect(component.getByAltText('alt text')).toBeInTheDocument(); - }); -}); diff --git a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-group/avatar-story-group.source.ts b/projects/elonkit/src/ui/avatar/__stories__/avatar-story-group/avatar-story-group.source.ts deleted file mode 100644 index 8c5367f..0000000 --- a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-group/avatar-story-group.source.ts +++ /dev/null @@ -1,23 +0,0 @@ -export const AVATAR_STORY_GROUP_SOURCE = { - html: ` - - - - - - `, -}; diff --git a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-group/index.ts b/projects/elonkit/src/ui/avatar/__stories__/avatar-story-group/index.ts deleted file mode 100644 index 951a0ee..0000000 --- a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-group/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { AVATAR_STORY_GROUP_SOURCE } from './avatar-story-group.source'; diff --git a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-image/avatar-story-image.source.ts b/projects/elonkit/src/ui/avatar/__stories__/avatar-story-image/avatar-story-image.source.ts deleted file mode 100644 index 19e12e4..0000000 --- a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-image/avatar-story-image.source.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const AVATAR_STORY_IMAGE_SOURCE = { - html: ` - - `, -}; diff --git a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-image/index.ts b/projects/elonkit/src/ui/avatar/__stories__/avatar-story-image/index.ts deleted file mode 100644 index 4bdaa1a..0000000 --- a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-image/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { AVATAR_STORY_IMAGE_SOURCE } from './avatar-story-image.source'; diff --git a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-icon/avatar-story-no-image-icon.source.ts b/projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-icon/avatar-story-no-image-icon.source.ts deleted file mode 100644 index 30061d9..0000000 --- a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-icon/avatar-story-no-image-icon.source.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const AVATAR_STORY_NO_IMAGE_ICON_SOURCE = { - html: ` - - person - - `, -}; diff --git a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-icon/index.ts b/projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-icon/index.ts deleted file mode 100644 index 4c21745..0000000 --- a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-icon/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { AVATAR_STORY_NO_IMAGE_ICON_SOURCE } from './avatar-story-no-image-icon.source'; diff --git a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-typography/avatar-story-no-image-typography.source.ts b/projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-typography/avatar-story-no-image-typography.source.ts deleted file mode 100644 index c350ceb..0000000 --- a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-typography/avatar-story-no-image-typography.source.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const AVATAR_STORY_NO_IMAGE_TYPOGRAPHY_SOURCE = { - html: ` - `, -}; diff --git a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-typography/index.ts b/projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-typography/index.ts deleted file mode 100644 index 3e04d81..0000000 --- a/projects/elonkit/src/ui/avatar/__stories__/avatar-story-no-image-typography/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { AVATAR_STORY_NO_IMAGE_TYPOGRAPHY_SOURCE } from './avatar-story-no-image-typography.source'; diff --git a/projects/elonkit/src/ui/avatar/__stories__/avatar.stories.mdx b/projects/elonkit/src/ui/avatar/__stories__/avatar.stories.mdx deleted file mode 100644 index 30b7560..0000000 --- a/projects/elonkit/src/ui/avatar/__stories__/avatar.stories.mdx +++ /dev/null @@ -1,206 +0,0 @@ -import { Meta, Story, ArgsTable } from '@storybook/addon-docs'; -import { Canvas } from '~storybook/components'; -import { action } from '@storybook/addon-actions'; - -import { MatIconModule } from '@angular/material/icon'; - -import { ESAvatarComponent, ESAvatarModule, ESAvatarGroupComponent } from '..'; - -import { AVATAR_STORY_IMAGE_SOURCE } from './avatar-story-image'; - -import { AVATAR_STORY_NO_IMAGE_ICON_SOURCE } from './avatar-story-no-image-icon'; - -import { AVATAR_STORY_NO_IMAGE_TYPOGRAPHY_SOURCE } from './avatar-story-no-image-typography'; - -import { AVATAR_STORY_GROUP_SOURCE } from './avatar-story-group'; - - - -# Avatar - -This component allows to display default or custom avatar. - -## Demos - -#### - -#### - -We can create image avatars by passing `src` input to the component. - - - - {((args) => ({ - template: ` - - `, - moduleMetadata: { - imports: [ESAvatarModule], - }, - props: { - ...args, - }, - })).bind({})} - - - -When src input is missing or falsy, content is used instead. Icon or text can be used for a content. - - - - {((args) => ({ - template: ` - - person - - `, - moduleMetadata: { - imports: [ESAvatarModule, MatIconModule], - }, - props: { - ...args, - }, - })).bind({})} - - - - - - {((args) => ({ - template: ` - - НФ - - `, - moduleMetadata: { - imports: [ESAvatarModule], - }, - props: { - ...args, - }, - })).bind({})} - - - -We can use avatar group to render avatars as a stack. Size input of avatar group and nested avatars must match. - - - - {((args) => ({ - template: ` - - - - - - `, - moduleMetadata: { - imports: [ESAvatarModule], - }, - props: { - ...args, - }, - })).bind({})} - - - -## API - -### ESAvatarComponent - - - -### ESAvatarGroupComponent - - - -## Interfaces - -ESAvatarDefaultOptions ESAvatarVariant defines default avatar form - -```ts -export interface ESAvatarDefaultOptions { - size?: number; - typography?: string; - variant?: ESAvatarVariant; -} -``` - -```ts -export enum ESAvatarVariant { - Round = 'round', - Square = 'square', -} -``` - -Injection token that can be used to configure the default options for all components within an app. - -```ts -import { ES_AVATAR_DEFAULT_OPTIONS } from '@elonkit/angular/ui/avatar'; - -@NgModule({ - providers: [ - { - provide: ES_AVATAR_DEFAULT_OPTIONS, - useValue: { - size: 40, - variant: 'round', - typography: 'typography' - } - } - ] -}) -``` diff --git a/projects/elonkit/src/ui/avatar/avatar-group.component.html b/projects/elonkit/src/ui/avatar/avatar-group.component.html deleted file mode 100644 index 00e4a5a..0000000 --- a/projects/elonkit/src/ui/avatar/avatar-group.component.html +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/projects/elonkit/src/ui/avatar/avatar-group.component.scss b/projects/elonkit/src/ui/avatar/avatar-group.component.scss deleted file mode 100644 index 6c88e03..0000000 --- a/projects/elonkit/src/ui/avatar/avatar-group.component.scss +++ /dev/null @@ -1,36 +0,0 @@ -.es-avatar-group { - display: flex; - - es-avatar { - border-radius: 50%; - - &:last-child { - z-index: 1; - } - - &:not(:first-child) { - margin-left: -12px; - } - - /* change the white border to mask only if it's supported: */ - @supports (mask: radial-gradient(transparent 12px, black 0)) { - /* stylelint-disable-next-line */ - - &:not(:last-of-type) { - mask: radial-gradient( - circle at calc((var(--size) * 0.75) + ((var(--size) / 2) + 2px)), - transparent calc((var(--size) / 2) + 2px), - #fff 0 - ); - } - - &:not(:first-of-type) { - margin-left: calc((var(--size) * -0.25) + 2.2px); - } - - .es-avatar { - border: unset !important; - } - } - } -} diff --git a/projects/elonkit/src/ui/avatar/avatar-group.component.theme.scss b/projects/elonkit/src/ui/avatar/avatar-group.component.theme.scss deleted file mode 100644 index a1cb5a2..0000000 --- a/projects/elonkit/src/ui/avatar/avatar-group.component.theme.scss +++ /dev/null @@ -1,7 +0,0 @@ -@mixin es-avatar-group-theme($theme, $elonkit-theme) { - $cl-mono-b: map-get($elonkit-theme, mono-b); - - .es-avatar-group .es-avatar { - border: 2px solid mat.get-color-from-palette($cl-mono-b, 500); - } -} diff --git a/projects/elonkit/src/ui/avatar/avatar-group.component.ts b/projects/elonkit/src/ui/avatar/avatar-group.component.ts deleted file mode 100644 index af40046..0000000 --- a/projects/elonkit/src/ui/avatar/avatar-group.component.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { - Component, - Input, - ChangeDetectionStrategy, - ElementRef, - ViewEncapsulation, - OnInit, - ContentChildren, - QueryList, - AfterContentInit, - Renderer2, - OnDestroy, -} from '@angular/core'; - -import { ESAvatarComponent } from './avatar.component'; -import { takeUntil } from 'rxjs/operators'; -import { Subject } from 'rxjs'; - -@Component({ - selector: 'es-avatar-group', - templateUrl: './avatar-group.component.html', - styleUrls: ['./avatar-group.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class ESAvatarGroupComponent implements OnInit, AfterContentInit, OnDestroy { - @ContentChildren(ESAvatarComponent, { read: ElementRef }) private avatars: QueryList; - /** - * Defines size of the avatar in pixels. - */ - @Input() - public size: number; - - private destroyed$ = new Subject(); - - /** - * @ignore - */ - constructor( - private _elementRef: ElementRef, - private renderer: Renderer2 - ) {} - - /** - * @ignore - */ - public ngOnInit() { - console.log(this.size); - this._elementRef.nativeElement.style.setProperty('--size', `${this.size + `px`}`); - } - - /** - * @ignore - */ - public ngAfterContentInit() { - this.setAvatarsIndex(this.avatars); - this.avatars.changes.pipe(takeUntil(this.destroyed$)).subscribe((avatars) => { - if (avatars) { - this.setAvatarsIndex(avatars); - } - }); - } - - private setAvatarsIndex = (avatars: any[] | QueryList>): void => { - avatars.forEach((avatar, index) => { - this.renderer.setStyle(avatar.nativeElement, 'z-index', index); - }); - }; - - /** - * @ignore - */ - public ngOnDestroy() { - this.destroyed$.next(); - } -} diff --git a/projects/elonkit/src/ui/avatar/avatar.component.html b/projects/elonkit/src/ui/avatar/avatar.component.html deleted file mode 100644 index 48186c8..0000000 --- a/projects/elonkit/src/ui/avatar/avatar.component.html +++ /dev/null @@ -1,13 +0,0 @@ -
- -
- -
-
diff --git a/projects/elonkit/src/ui/avatar/avatar.component.scss b/projects/elonkit/src/ui/avatar/avatar.component.scss deleted file mode 100644 index 9eb24eb..0000000 --- a/projects/elonkit/src/ui/avatar/avatar.component.scss +++ /dev/null @@ -1,39 +0,0 @@ -.es-avatar { - position: relative; - - &__img { - width: 100%; - height: 100%; - object-fit: cover; - } - - &__default { - display: flex; - left: 50%; - position: absolute; - top: 50%; - transform: translate(-50%, -50%); - - img { - width: 100%; - height: 100%; - object-fit: cover; - } - } - - &_variant_square { - border-radius: 8px; - // stylelint-disable-next-line - .es-avatar__img { - border-radius: 5px; - } - } - - &_variant_round { - border-radius: 50%; - // stylelint-disable-next-line - .es-avatar__img { - border-radius: 50%; - } - } -} diff --git a/projects/elonkit/src/ui/avatar/avatar.component.theme.scss b/projects/elonkit/src/ui/avatar/avatar.component.theme.scss deleted file mode 100644 index f98c800..0000000 --- a/projects/elonkit/src/ui/avatar/avatar.component.theme.scss +++ /dev/null @@ -1,11 +0,0 @@ -@import './avatar-group.component.theme'; - -@mixin es-avatar-theme($theme, $elonkit-theme) { - $cl-mono-a: map-get($elonkit-theme, mono-a); - @include es-avatar-group-theme($theme, $elonkit-theme); - - .es-avatar { - background: mat.get-color-from-palette($cl-mono-a, A100); - color: mat.get-color-from-palette($cl-mono-a, A500); - } -} diff --git a/projects/elonkit/src/ui/avatar/avatar.component.ts b/projects/elonkit/src/ui/avatar/avatar.component.ts deleted file mode 100644 index 3579166..0000000 --- a/projects/elonkit/src/ui/avatar/avatar.component.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { Component, Input, ChangeDetectionStrategy, InjectionToken, Optional, Inject, ViewEncapsulation } from '@angular/core'; -import { coerceNumberProperty } from '@angular/cdk/coercion'; - -import { ESAvatarDefaultOptions, ESAvatarVariant } from './avatar.types'; - -export const ES_AVATAR_DEFAULT_OPTIONS = new InjectionToken('ES_AVATAR_DEFAULT_OPTIONS'); - -@Component({ - selector: 'es-avatar', - templateUrl: './avatar.component.html', - styleUrls: ['./avatar.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class ESAvatarComponent { - /** - * @internal - * @ignore - */ - public avatarVariant = ESAvatarVariant; - - /** - * Size of the avatar in pixels. - */ - @Input() - public get size(): number { - return this._size; - } - public set size(value: number | undefined) { - this._size = coerceNumberProperty(value, 40); - } - private _size: number; - - /** - * Class applied to text. - */ - @Input() - public get typography(): string { - return this._typography; - } - public set typography(value: string | undefined) { - this._typography = value || 'es-subtitle-2'; - } - private _typography: string; - - /** - * The alt attribute for avatar image. - */ - @Input() public alt?: string; - - /** - * The src attribute for avatar image. - */ - @Input() public src?: string; - - /** - * The shape of the avatar. - */ - @Input() - public get variant(): ESAvatarVariant { - return this._variant; - } - public set variant(value: ESAvatarVariant | undefined) { - this._variant = value || this.avatarVariant.Round; - } - private _variant: ESAvatarVariant; - - /** - * @ignore - */ - constructor( - @Optional() - @Inject(ES_AVATAR_DEFAULT_OPTIONS) - private defaultOptions: ESAvatarDefaultOptions - ) { - this.size = this.defaultOptions?.size; - this.typography = this.defaultOptions?.typography; - this.variant = this.defaultOptions?.variant; - } -} diff --git a/projects/elonkit/src/ui/avatar/avatar.module.ts b/projects/elonkit/src/ui/avatar/avatar.module.ts deleted file mode 100644 index f0bd085..0000000 --- a/projects/elonkit/src/ui/avatar/avatar.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { MatIconModule } from '@angular/material/icon'; - -import { ESAvatarComponent } from './avatar.component'; -import { ESAvatarGroupComponent } from './avatar-group.component'; - -@NgModule({ - declarations: [ESAvatarComponent, ESAvatarGroupComponent], - imports: [CommonModule, MatIconModule], - exports: [ESAvatarComponent, ESAvatarGroupComponent], -}) -export class ESAvatarModule {} diff --git a/projects/elonkit/src/ui/avatar/avatar.types.ts b/projects/elonkit/src/ui/avatar/avatar.types.ts deleted file mode 100644 index 86f0529..0000000 --- a/projects/elonkit/src/ui/avatar/avatar.types.ts +++ /dev/null @@ -1,10 +0,0 @@ -export interface ESAvatarDefaultOptions { - size?: number; - typography?: string; - variant?: ESAvatarVariant; -} - -export enum ESAvatarVariant { - Round = 'round', - Square = 'square', -} diff --git a/projects/elonkit/src/ui/avatar/index.ts b/projects/elonkit/src/ui/avatar/index.ts deleted file mode 100644 index 7e1a213..0000000 --- a/projects/elonkit/src/ui/avatar/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './public-api'; diff --git a/projects/elonkit/src/ui/avatar/public-api.ts b/projects/elonkit/src/ui/avatar/public-api.ts deleted file mode 100644 index 145e6df..0000000 --- a/projects/elonkit/src/ui/avatar/public-api.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { ESAvatarModule } from './avatar.module'; -export { ESAvatarComponent } from './avatar.component'; -export { ESAvatarGroupComponent } from './avatar-group.component'; -export { ESAvatarDefaultOptions, ESAvatarVariant } from './avatar.types'; diff --git a/projects/elonkit/src/ui/breadcrumbs/__specs__/breadcrumbs.spec.resolver.ts b/projects/elonkit/src/ui/breadcrumbs/__specs__/breadcrumbs.spec.resolver.ts deleted file mode 100644 index 2b8da6b..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/__specs__/breadcrumbs.spec.resolver.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Resolve, ActivatedRouteSnapshot } from '@angular/router'; - -import { CategoriesService, ItemsService } from './breadcrumbs.spec.service'; - -@Injectable() -export class CategoriesListResolver implements Resolve { - constructor(private categoriesService: CategoriesService) {} - - public resolve() { - return this.categoriesService.getAll(); - } -} - -@Injectable() -export class CategoriesShowResolver implements Resolve { - constructor(private categoriesService: CategoriesService) {} - - public resolve(route: ActivatedRouteSnapshot) { - return this.categoriesService.getOne(+route.params['item']); - } -} - -@Injectable() -export class CategoriesShowBreadcrumbsResolver implements Resolve { - public resolve(route: ActivatedRouteSnapshot) { - const category = route.parent?.data['data'].find((e: { id: number }) => e.id === +route.params['category']); - - return { - label: category.title, - breadcrumbs: route.parent?.data['data'] - // @ts-ignore - .map(({ id, title }) => ({ - path: id, - label: title, - })), - }; - } -} - -@Injectable() -export class ItemsListResolver implements Resolve { - constructor(private itemsService: ItemsService) {} - - public resolve(route: ActivatedRouteSnapshot) { - return this.itemsService.getAll(+route.params['category']); - } -} - -@Injectable() -export class ItemsShowResolver implements Resolve { - constructor(private itemsService: ItemsService) {} - - public resolve(route: ActivatedRouteSnapshot) { - return this.itemsService.getOne(+route.params['item']); - } -} - -@Injectable() -export class ItemsShowBreadcrumbsResolver implements Resolve { - public resolve(route: ActivatedRouteSnapshot) { - return { label: route.parent?.data['data'].title }; - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/__specs__/breadcrumbs.spec.routes.ts b/projects/elonkit/src/ui/breadcrumbs/__specs__/breadcrumbs.spec.routes.ts deleted file mode 100644 index d23c350..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/__specs__/breadcrumbs.spec.routes.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { Component, ChangeDetectionStrategy } from '@angular/core'; - -import { ESBreadcrumbsModule, ESBreadcrumbsResolver } from '..'; - -import { - CategoriesListResolver, - CategoriesShowResolver, - CategoriesShowBreadcrumbsResolver, - ItemsListResolver, - ItemsShowResolver, - ItemsShowBreadcrumbsResolver, -} from './breadcrumbs.spec.resolver'; - -@Component({ - selector: 'es-breadcrumbs-spec-root', - template: ` -
- - -
- `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class BreadcrumbsRootComponent {} - -@Component({ - selector: 'es-breadcrumbs-spec-leaf', - template: ``, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class BreadcrumbsLeafComponent {} - -export const ROUTES = [ - { - path: '', - data: { - breadcrumb: { icon: 'home', ariaLabel: 'Home' }, - }, - resolve: { - breadcrumb: ESBreadcrumbsResolver, - }, - children: [ - { - path: '', - component: BreadcrumbsLeafComponent, - }, - { - path: 'categories', - data: { - breadcrumb: { label: 'Categories' }, - }, - resolve: { - data: CategoriesListResolver, // We need to move list resolver one level up in order to use horizontal navigation. - breadcrumb: ESBreadcrumbsResolver, - }, - children: [ - { - path: '', - component: BreadcrumbsLeafComponent, - }, - { - path: ':category', - resolve: { - data: CategoriesShowResolver, - breadcrumb: CategoriesShowBreadcrumbsResolver, - }, - children: [ - { - path: '', - component: BreadcrumbsLeafComponent, - resolve: { - data: ItemsListResolver, - }, - }, - { - path: ':item', - resolve: { - data: ItemsShowResolver, - }, - children: [ - { - path: '', - resolve: { - breadcrumb: ItemsShowBreadcrumbsResolver, - }, - children: [ - { - path: '', - component: BreadcrumbsLeafComponent, - }, - { - path: 'edit', - component: BreadcrumbsLeafComponent, - data: { - breadcrumb: { label: 'Edit' }, - }, - resolve: { - breadcrumb: ESBreadcrumbsResolver, - }, - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, -]; diff --git a/projects/elonkit/src/ui/breadcrumbs/__specs__/breadcrumbs.spec.service.ts b/projects/elonkit/src/ui/breadcrumbs/__specs__/breadcrumbs.spec.service.ts deleted file mode 100644 index 6ba219b..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/__specs__/breadcrumbs.spec.service.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { Injectable } from '@angular/core'; - -import { of } from 'rxjs'; - -const CATEGORIES = [ - { - id: 1, - title: `Category #1`, - }, - { - id: 2, - title: `Category #2`, - }, - { - id: 3, - title: `Category #3`, - }, -]; - -const ITEMS = [ - { - id: 1, - categoryId: 1, - title: `Item #1-1`, - }, - { - id: 2, - categoryId: 1, - title: `Item #1-2`, - }, - { - id: 3, - categoryId: 1, - title: `Item #1-3`, - }, - { - id: 4, - categoryId: 2, - title: `Item #2-1`, - }, - { - id: 5, - categoryId: 2, - title: `Item #2-2`, - }, - { - id: 6, - categoryId: 2, - title: `Item #2-3`, - }, - { - id: 7, - categoryId: 3, - title: `Item #3-1`, - }, - { - id: 8, - categoryId: 3, - title: `Item #3-2`, - }, - { - id: 9, - categoryId: 3, - title: `Item #3-3`, - }, -]; - -@Injectable() -export class CategoriesService { - public getAll() { - return of(CATEGORIES); - } - - public getOne(id: number) { - return of(CATEGORIES.find((item) => item.id === id)); - } -} - -@Injectable() -export class ItemsService { - public getAll(categoryId: number) { - return of(ITEMS.filter((item) => item.categoryId === categoryId)); - } - - public getOne(id: number) { - return of(ITEMS.find((item) => item.id === id)); - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/__specs__/breadcrumbs.spec.ts b/projects/elonkit/src/ui/breadcrumbs/__specs__/breadcrumbs.spec.ts deleted file mode 100644 index 6ec513c..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/__specs__/breadcrumbs.spec.ts +++ /dev/null @@ -1,191 +0,0 @@ -import { fireEvent, render, RenderResult, screen } from '@testing-library/angular'; - -import { NgZone } from '@angular/core'; -import { inject } from '@angular/core/testing'; - -import { CommonModule, Location } from '@angular/common'; -import { RouterTestingModule } from '@angular/router/testing'; -import { OverlayContainer } from '@angular/cdk/overlay'; - -import { ESBreadcrumbsModule } from '..'; -import { en, ESLocaleService, ru } from '../../locale'; - -import { BreadcrumbsLeafComponent, BreadcrumbsRootComponent, ROUTES } from './breadcrumbs.spec.routes'; -import { CategoriesService, ItemsService } from './breadcrumbs.spec.service'; - -import { - CategoriesListResolver, - CategoriesShowBreadcrumbsResolver, - CategoriesShowResolver, - ItemsListResolver, - ItemsShowBreadcrumbsResolver, - ItemsShowResolver, -} from './breadcrumbs.spec.resolver'; - -const setWidth = (component: RenderResult, width: number) => { - Object.defineProperty((component.fixture.nativeElement as HTMLElement).querySelector('.es-breadcrumbs'), 'clientWidth', { - configurable: true, - value: width, - }); -}; - -describe('Breadcrumbs', () => { - describe('Navigation', () => { - let component: RenderResult; - let overlay: OverlayContainer; - let overlayElement: HTMLElement; - - beforeEach(async () => { - component = await render(BreadcrumbsRootComponent, { - declarations: [BreadcrumbsLeafComponent], - imports: [CommonModule, ESBreadcrumbsModule, RouterTestingModule.withRoutes(ROUTES)], - providers: [ - CategoriesService, - ItemsService, - CategoriesListResolver, - CategoriesShowResolver, - CategoriesShowBreadcrumbsResolver, - ItemsListResolver, - ItemsShowResolver, - ItemsShowBreadcrumbsResolver, - ], - componentProperties: { - withBackButton: true, - }, - }); - - inject([OverlayContainer], (oc: OverlayContainer) => { - overlay = oc; - overlayElement = oc.getContainerElement(); - })(); - }); - - afterEach(inject([OverlayContainer], (currentOverlay: OverlayContainer) => { - currentOverlay.ngOnDestroy(); - overlay.ngOnDestroy(); - })); - - it('Should render hierarchy', inject([NgZone, Location], async (zone: NgZone, location: Location) => { - setWidth(component, 1000); - - await component.navigate('/categories/1/1/edit'); - await component.fixture.whenStable(); - - zone.run(() => fireEvent.click(screen.getByText('Item #1-1'))); - await component.fixture.whenStable(); - - expect(location.path()).toBe('/categories/1/1'); - - zone.run(() => fireEvent.click(screen.getByText('Category #1'))); - await component.fixture.whenStable(); - - expect(location.path()).toBe('/categories/1'); - - zone.run(() => fireEvent.click(screen.getByText('Categories'))); - await component.fixture.whenStable(); - - expect(location.path()).toBe('/categories'); - - zone.run(() => fireEvent.click(component.getByLabelText('Home'))); - await component.fixture.whenStable(); - - expect(location.path()).toBe('/'); - })); - - it('Should have horizontal navigation', inject([Location], async (location: Location) => { - setWidth(component, 1000); - - await component.navigate('/categories/1'); - await component.fixture.whenStable(); - - const menu = component.getByLabelText('More'); - fireEvent.click(menu); - - const options = overlayElement.querySelectorAll('a'); - expect(options).toHaveLength(3); - - expect(overlayElement.textContent).toContain('Category #1'); - expect(overlayElement.textContent).toContain('Category #2'); - expect(overlayElement.textContent).toContain('Category #3'); - - await component.navigate(options[1]); - expect(location.path()).toBe('/categories/2'); - - await component.navigate(options[2]); - expect(location.path()).toBe('/categories/3'); - })); - - it('Should collapse', inject([Location], async (location: Location) => { - setWidth(component, 125); - - await component.navigate('/categories/1/1/edit'); - await component.fixture.whenStable(); - - expect(screen.queryByLabelText('Home')).not.toBeNull(); - expect(screen.queryAllByText(en.breadcrumbs.labelBack)).not.toBeNull(); - expect(screen.queryByText('Categories')).toBeNull(); - expect(screen.queryByText('Category 1')).toBeNull(); - expect(screen.queryByText('Item #1-1')).not.toBeNull(); - expect(screen.queryByText('Edit')).not.toBeNull(); - - const menu = component.getByLabelText('More'); - fireEvent.click(menu); - - const options = overlayElement.querySelectorAll('.mat-menu-item'); - expect(options).toHaveLength(2); - - expect(overlayElement.textContent).toContain('Categories'); - expect(overlayElement.textContent).toContain('Category #1'); - - await component.navigate(options[0]); - await component.fixture.whenStable(); - - expect(location.path()).toBe('/categories'); - expect(screen.queryByText('Categories')).not.toBeNull(); - })); - }); - - describe('Locale', () => { - let component: RenderResult; - - beforeEach(async () => { - const localeService = new ESLocaleService(); - localeService.register('ru', ru); - localeService.use('ru'); - - component = await render(BreadcrumbsRootComponent, { - declarations: [BreadcrumbsLeafComponent], - imports: [CommonModule, ESBreadcrumbsModule, RouterTestingModule.withRoutes(ROUTES)], - providers: [ - CategoriesService, - ItemsService, - CategoriesListResolver, - CategoriesShowResolver, - CategoriesShowBreadcrumbsResolver, - ItemsListResolver, - ItemsShowResolver, - ItemsShowBreadcrumbsResolver, - { provide: ESLocaleService, useValue: localeService }, - ], - }); - }); - - it('Should change collapse locale', async () => { - setWidth(component, 150); - - await component.navigate('/categories/1/1/edit'); - await component.fixture.whenStable(); - - expect(screen.queryByLabelText(ru.breadcrumbs.labelMore)).not.toBeNull(); - }); - - it('Should change horizontal navigation locale', async () => { - setWidth(component, 1000); - - await component.navigate('/categories/1'); - await component.fixture.whenStable(); - - expect(screen.queryByLabelText(ru.breadcrumbs.labelMore)).not.toBeNull(); - }); - }); -}); diff --git a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.component.ts b/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.component.ts deleted file mode 100644 index cf4ef4e..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.component.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { Component, ChangeDetectionStrategy, ChangeDetectorRef, OnInit, OnDestroy, Input } from '@angular/core'; -import { Router, ActivatedRoute } from '@angular/router'; - -import { DomSanitizer } from '@angular/platform-browser'; -import { MatIconRegistry } from '@angular/material/icon'; - -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; - -@Component({ - selector: 'es-breadcrumbs-basic', - template: ` - -
- - `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class BreadcrumbsStoryBasicComponent implements OnInit { - @Input() public withBackButton: boolean; - - constructor( - private router: Router, - private matIconRegistry: MatIconRegistry, - private domSanitizer: DomSanitizer - ) { - this.matIconRegistry.addSvgIcon('home', this.domSanitizer.bypassSecurityTrustResourceUrl('/icons/home.svg')); - } - - public ngOnInit() { - // Hack for RouterTestingModule - this.router.navigate(['/categories']); - } -} - -@Component({ - selector: 'es-breadcrumbs-basic-home', - template: ` -

Home

- Categories - `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class BreadcrumbsStoryBasicHomeComponent {} - -@Component({ - selector: 'es-breadcrumbs-basic-categories-list', - template: ` -

Categories

- - `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class BreadcrumbsStoryBasicCategoriesListComponent { - public categories = []; - - constructor(private route: ActivatedRoute) { - this.categories = this.route.snapshot.data['data']; - } -} - -@Component({ - selector: 'es-breadcrumbs-basic-items-list', - template: ` -

Items

- - `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class BreadcrumbsStoryBasicItemsListComponent implements OnInit, OnDestroy { - public items = []; - public destroyed$ = new Subject(); - - constructor( - private changeDetector: ChangeDetectorRef, - private route: ActivatedRoute - ) {} - - public ngOnInit() { - this.route.params.pipe(takeUntil(this.destroyed$)).subscribe(() => { - this.items = this.route.snapshot.data['data']; - this.changeDetector.detectChanges(); - }); - } - - public ngOnDestroy() { - this.destroyed$.next(); - } -} - -@Component({ - selector: 'es-breadcrumbs-basic-items-show', - template: ` -

{{ item.title }}

- Edit - `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class BreadcrumbsStoryBasicItemsShowComponent { - public item; - - constructor(private route: ActivatedRoute) { - this.item = this.route.snapshot.data['data']; - } -} - -@Component({ - selector: 'es-breadcrumbs-basic-items-edit', - template: `

Edit {{ item.title }}

`, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class BreadcrumbsStoryBasicItemsEditComponent { - public item; - - constructor(private route: ActivatedRoute) { - this.item = this.route.snapshot.data['data']; - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.module.ts b/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.module.ts deleted file mode 100644 index dc54b88..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.module.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule, APP_BASE_HREF } from '@angular/common'; -import { HttpClientModule } from '@angular/common/http'; - -import { RouterTestingModule } from '@angular/router/testing'; - -import { - BreadcrumbsStoryBasicComponent, - BreadcrumbsStoryBasicHomeComponent, - BreadcrumbsStoryBasicCategoriesListComponent, - BreadcrumbsStoryBasicItemsListComponent, - BreadcrumbsStoryBasicItemsShowComponent, - BreadcrumbsStoryBasicItemsEditComponent, -} from './breadcrumbs-story-basic.component'; - -import { CategoriesService, ItemsService } from './breadcrumbs-story-basic.service'; - -import { - CategoriesListResolver, - CategoriesShowResolver, - CategoriesShowBreadcrumbsResolver, - ItemsListResolver, - ItemsShowResolver, - ItemsShowBreadcrumbsResolver, -} from './breadcrumbs-story-basic.resolver'; - -import { ESBreadcrumbsModule, ESBreadcrumbsResolver } from '../..'; - -const ROUTES = [ - { - path: '', - data: { - breadcrumb: { svgIcon: 'home', ariaLabel: 'Home' }, - }, - resolve: { - breadcrumb: ESBreadcrumbsResolver, - }, - children: [ - { - path: '', - component: BreadcrumbsStoryBasicHomeComponent, - }, - { - path: 'categories', - data: { - breadcrumb: { label: 'Categories' }, - }, - resolve: { - data: CategoriesListResolver, // We need to move list resolver one level up in order to use horizontal navigation. - breadcrumb: ESBreadcrumbsResolver, - }, - children: [ - { - path: '', - component: BreadcrumbsStoryBasicCategoriesListComponent, - }, - { - path: ':category', - resolve: { - data: CategoriesShowResolver, - breadcrumb: CategoriesShowBreadcrumbsResolver, - }, - children: [ - { - path: '', - component: BreadcrumbsStoryBasicItemsListComponent, - resolve: { - data: ItemsListResolver, - }, - }, - { - path: ':item', - resolve: { - data: ItemsShowResolver, - }, - children: [ - { - path: '', - resolve: { - breadcrumb: ItemsShowBreadcrumbsResolver, - }, - children: [ - { - path: '', - component: BreadcrumbsStoryBasicItemsShowComponent, - }, - { - path: 'edit', - component: BreadcrumbsStoryBasicItemsEditComponent, - data: { - breadcrumb: { label: 'Edit' }, - }, - resolve: { - breadcrumb: ESBreadcrumbsResolver, - }, - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, -]; - -@NgModule({ - declarations: [ - BreadcrumbsStoryBasicComponent, - BreadcrumbsStoryBasicHomeComponent, - BreadcrumbsStoryBasicCategoriesListComponent, - BreadcrumbsStoryBasicItemsListComponent, - BreadcrumbsStoryBasicItemsShowComponent, - BreadcrumbsStoryBasicItemsEditComponent, - ], - imports: [CommonModule, HttpClientModule, ESBreadcrumbsModule, RouterTestingModule.withRoutes(ROUTES)], - exports: [BreadcrumbsStoryBasicComponent], - providers: [ - CategoriesService, - ItemsService, - CategoriesListResolver, - CategoriesShowResolver, - CategoriesShowBreadcrumbsResolver, - ItemsListResolver, - ItemsShowResolver, - ItemsShowBreadcrumbsResolver, - { provide: APP_BASE_HREF, useValue: '/' }, - ], -}) -export class BreadcrumbsStoryBasicModule {} diff --git a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.resolver.ts b/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.resolver.ts deleted file mode 100644 index a28c54e..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.resolver.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; - -import { CategoriesService, ItemsService } from './breadcrumbs-story-basic.service'; - -@Injectable() -export class CategoriesListResolver implements Resolve { - constructor(private categoriesService: CategoriesService) {} - - public resolve() { - return this.categoriesService.getAll(); - } -} - -@Injectable() -export class CategoriesShowResolver implements Resolve { - constructor(private categoriesService: CategoriesService) {} - - public resolve(route: ActivatedRouteSnapshot) { - return this.categoriesService.getOne(+route.params['item']); - } -} - -@Injectable() -export class CategoriesShowBreadcrumbsResolver implements Resolve { - public resolve(route: ActivatedRouteSnapshot) { - const category = route.parent?.data['data'].find((e: { id: number }) => e.id === +route.params['category']); - - return { - label: category.title, - breadcrumbs: route.parent?.data['data'] - // @ts-ignore - .map(({ id, title }) => ({ - path: id, - label: title, - })), - }; - } -} - -@Injectable() -export class ItemsListResolver implements Resolve { - constructor(private itemsService: ItemsService) {} - - public resolve(route: ActivatedRouteSnapshot) { - return this.itemsService.getAll(+route.params['category']); - } -} - -@Injectable() -export class ItemsShowResolver implements Resolve { - constructor(private itemsService: ItemsService) {} - - public resolve(route: ActivatedRouteSnapshot) { - return this.itemsService.getOne(+route.params['item']); - } -} - -@Injectable() -export class ItemsShowBreadcrumbsResolver implements Resolve { - public resolve(route: ActivatedRouteSnapshot) { - return { label: route.parent?.data['data'].title }; - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.service.ts b/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.service.ts deleted file mode 100644 index 6ba219b..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.service.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { Injectable } from '@angular/core'; - -import { of } from 'rxjs'; - -const CATEGORIES = [ - { - id: 1, - title: `Category #1`, - }, - { - id: 2, - title: `Category #2`, - }, - { - id: 3, - title: `Category #3`, - }, -]; - -const ITEMS = [ - { - id: 1, - categoryId: 1, - title: `Item #1-1`, - }, - { - id: 2, - categoryId: 1, - title: `Item #1-2`, - }, - { - id: 3, - categoryId: 1, - title: `Item #1-3`, - }, - { - id: 4, - categoryId: 2, - title: `Item #2-1`, - }, - { - id: 5, - categoryId: 2, - title: `Item #2-2`, - }, - { - id: 6, - categoryId: 2, - title: `Item #2-3`, - }, - { - id: 7, - categoryId: 3, - title: `Item #3-1`, - }, - { - id: 8, - categoryId: 3, - title: `Item #3-2`, - }, - { - id: 9, - categoryId: 3, - title: `Item #3-3`, - }, -]; - -@Injectable() -export class CategoriesService { - public getAll() { - return of(CATEGORIES); - } - - public getOne(id: number) { - return of(CATEGORIES.find((item) => item.id === id)); - } -} - -@Injectable() -export class ItemsService { - public getAll(categoryId: number) { - return of(ITEMS.filter((item) => item.categoryId === categoryId)); - } - - public getOne(id: number) { - return of(ITEMS.find((item) => item.id === id)); - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.source.ts b/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.source.ts deleted file mode 100644 index 0887e02..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.source.ts +++ /dev/null @@ -1,94 +0,0 @@ -export const BREADCRUMBS_STORY_BASIC_SOURCE = { - html: ` - - `, - ts: ` - import { ESBreadcrumbsModule, ESBreadcrumbsResolver } from '@elonkit/angular/ui/breadcrumbs'; - - const ROUTES = [ - { - path: '', - data: { - breadcrumb: { icon: 'home', ariaLabel: 'Home' }, - }, - resolve: { - breadcrumb: ESBreadcrumbsResolver - }, - children: [ - { - path: '', - component: HomeComponent - }, - { - path: 'categories', - data: { - breadcrumb: { label: 'Categories' } - }, - resolve: { - data: CategoriesListResolver, // We need to move list resolver one level up in order to use horizontal navigation. - breadcrumb: ESBreadcrumbsResolver - }, - children: [ - { - path: '', - component: CategoriesListComponent - }, - { - path: ':category', - resolve: { - data: CategoriesShowResolver, - breadcrumb: CategoriesShowBreadcrumbsResolver - }, - children: [ - { - path: '', - component: ItemsListComponent, - resolve: { - data: ItemsListResolver - } - }, - { - path: ':item', - resolve: { - data: ItemsShowResolver - }, - children: [ - { - path: '', - resolve: { - breadcrumb: ItemsShowBreadcrumbsResolver - }, - children: [ - { - path: '', - component: ItemsShowComponent - }, - { - path: 'edit', - component: ItemsEditComponent, - data: { - breadcrumb: { label: 'Edit' } - }, - resolve: { - breadcrumb: ESBreadcrumbsResolver - } - } - ] - } - ] - } - ] - } - ] - } - ] - } - ]; - - @NgModule({ - imports: [..., ESBreadcrumbsModule, RouterModule.forRoot(ROUTES)], - ... - }) - export class AppModule {} - `, -}; diff --git a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/index.ts b/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/index.ts deleted file mode 100644 index 2a47b32..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { BreadcrumbsStoryBasicComponent } from './breadcrumbs-story-basic.component'; -export { BreadcrumbsStoryBasicModule } from './breadcrumbs-story-basic.module'; -export { BREADCRUMBS_STORY_BASIC_SOURCE } from './breadcrumbs-story-basic.source'; diff --git a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/breadcrumbs-story-customization.component.scss b/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/breadcrumbs-story-customization.component.scss deleted file mode 100644 index f746aec..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/breadcrumbs-story-customization.component.scss +++ /dev/null @@ -1,6 +0,0 @@ -.customization { - // stylelint-disable-next-line - .es-breadcrumbs__separator { - margin: 0; - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/breadcrumbs-story-customization.component.ts b/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/breadcrumbs-story-customization.component.ts deleted file mode 100644 index 989c6dc..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/breadcrumbs-story-customization.component.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Component, ChangeDetectionStrategy, ViewEncapsulation, OnInit, Input } from '@angular/core'; -import { Router } from '@angular/router'; -import { ES_BREADCRUMBS_DEFAULT_SIZES } from '../..'; - -@Component({ - selector: 'es-breadcrumbs-customization', - template: ` -
- - chevron_right - keyboard_backspace - more_horiz - -
- -
- `, - styleUrls: ['./breadcrumbs-story-customization.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class BreadcrumbsStoryCustomizationComponent implements OnInit { - public sizes = { - ...ES_BREADCRUMBS_DEFAULT_SIZES, - separator: 24, - }; - - @Input() public withBackButton: boolean; - - constructor(private router: Router) {} - - public ngOnInit() { - // Hack for RouterTestingModule - this.router.navigate(['/categories/1/1/edit']); - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/breadcrumbs-story-customization.module.ts b/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/breadcrumbs-story-customization.module.ts deleted file mode 100644 index f535aab..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/breadcrumbs-story-customization.module.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule, APP_BASE_HREF } from '@angular/common'; -import { MatIconModule } from '@angular/material/icon'; -import { HttpClientModule } from '@angular/common/http'; -import { RouterTestingModule } from '@angular/router/testing'; - -import { BreadcrumbsStoryCustomizationComponent } from './breadcrumbs-story-customization.component'; - -import { - BreadcrumbsStoryBasicHomeComponent, - BreadcrumbsStoryBasicCategoriesListComponent, - BreadcrumbsStoryBasicItemsListComponent, - BreadcrumbsStoryBasicItemsShowComponent, - BreadcrumbsStoryBasicItemsEditComponent, -} from '../breadcrumbs-story-basic/breadcrumbs-story-basic.component'; - -import { CategoriesService, ItemsService } from '../breadcrumbs-story-basic/breadcrumbs-story-basic.service'; - -import { - CategoriesListResolver, - CategoriesShowResolver, - CategoriesShowBreadcrumbsResolver, - ItemsListResolver, - ItemsShowResolver, - ItemsShowBreadcrumbsResolver, -} from '../breadcrumbs-story-basic/breadcrumbs-story-basic.resolver'; - -import { ESBreadcrumbsModule, ESBreadcrumbsResolver } from '../..'; - -const ROUTES = [ - { - path: '', - data: { - breadcrumb: { icon: 'home', ariaLabel: 'Home' }, - }, - resolve: { - breadcrumb: ESBreadcrumbsResolver, - }, - children: [ - { - path: '', - component: BreadcrumbsStoryBasicHomeComponent, - }, - { - path: 'categories', - data: { - breadcrumb: { label: 'Categories' }, - }, - resolve: { - data: CategoriesListResolver, // We need to move list resolver one level up in order to use horizontal navigation. - breadcrumb: ESBreadcrumbsResolver, - }, - children: [ - { - path: '', - component: BreadcrumbsStoryBasicCategoriesListComponent, - }, - { - path: ':category', - resolve: { - data: CategoriesShowResolver, - breadcrumb: CategoriesShowBreadcrumbsResolver, - }, - children: [ - { - path: '', - component: BreadcrumbsStoryBasicItemsListComponent, - resolve: { - data: ItemsListResolver, - }, - }, - { - path: ':item', - resolve: { - data: ItemsShowResolver, - }, - children: [ - { - path: '', - resolve: { - breadcrumb: ItemsShowBreadcrumbsResolver, - }, - children: [ - { - path: '', - component: BreadcrumbsStoryBasicItemsShowComponent, - }, - { - path: 'edit', - component: BreadcrumbsStoryBasicItemsEditComponent, - data: { - breadcrumb: { label: 'Edit' }, - }, - resolve: { - breadcrumb: ESBreadcrumbsResolver, - }, - }, - ], - }, - ], - }, - ], - }, - ], - }, - ], - }, -]; - -@NgModule({ - declarations: [ - BreadcrumbsStoryCustomizationComponent, - BreadcrumbsStoryBasicHomeComponent, - BreadcrumbsStoryBasicCategoriesListComponent, - BreadcrumbsStoryBasicItemsListComponent, - BreadcrumbsStoryBasicItemsShowComponent, - BreadcrumbsStoryBasicItemsEditComponent, - ], - imports: [CommonModule, HttpClientModule, MatIconModule, ESBreadcrumbsModule, RouterTestingModule.withRoutes(ROUTES)], - exports: [BreadcrumbsStoryCustomizationComponent], - providers: [ - CategoriesService, - ItemsService, - CategoriesListResolver, - CategoriesShowResolver, - CategoriesShowBreadcrumbsResolver, - ItemsListResolver, - ItemsShowResolver, - ItemsShowBreadcrumbsResolver, - { provide: APP_BASE_HREF, useValue: '/' }, - ], -}) -export class BreadcrumbsStoryCustomizationModule {} diff --git a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/breadcrumbs-story-customization.source.ts b/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/breadcrumbs-story-customization.source.ts deleted file mode 100644 index 5f83697..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/breadcrumbs-story-customization.source.ts +++ /dev/null @@ -1,30 +0,0 @@ -export const BREADCRUMBS_STORY_CUSTOMIZATION_SOURCE = { - ts: ` - import { ES_BREADCRUMBS_DEFAULT_SIZES } from '@elonkit/angular/ui/breadcrumbs'; - - ... - - public sizes = { - ...ES_BREADCRUMBS_DEFAULT_SIZES, - separator: 24 - }; - `, - html: ` - - - chevron_right - - - keyboard_backspace - - - more_horiz - - - `, - scss: ` - .es-breadcrumbs__separator { - margin: 0; - } - `, -}; diff --git a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/index.ts b/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/index.ts deleted file mode 100644 index da49e76..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-customization/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { BreadcrumbsStoryCustomizationComponent } from './breadcrumbs-story-customization.component'; -export { BreadcrumbsStoryCustomizationModule } from './breadcrumbs-story-customization.module'; -export { BREADCRUMBS_STORY_CUSTOMIZATION_SOURCE } from './breadcrumbs-story-customization.source'; diff --git a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs.stories.mdx b/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs.stories.mdx deleted file mode 100644 index 7f0ced2..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs.stories.mdx +++ /dev/null @@ -1,130 +0,0 @@ -import { Meta, Story, ArgsTable } from '@storybook/addon-docs'; -import { Canvas } from '~storybook/components'; -import { action } from '@storybook/addon-actions'; - -import { ESBreadcrumbsComponent } from '..'; - -import { - BreadcrumbsStoryBasicModule, - BreadcrumbsStoryBasicComponent, - BREADCRUMBS_STORY_BASIC_SOURCE, -} from './breadcrumbs-story-basic'; - -import { - BreadcrumbsStoryCustomizationModule, - BreadcrumbsStoryCustomizationComponent, - BREADCRUMBS_STORY_CUSTOMIZATION_SOURCE, -} from './breadcrumbs-story-customization'; - - - -# Breadcrumbs - -Breadcrumbs indicate the current page’s location within a navigational hierarchy. - -## Demos - -In order to generate breadcrumbs we need to resolve `breadcrumb` key or provide static data with the same key. - -There is a strange behaviour in angular router when resolved data overrides it's child static data. -For this case we provide `ESBreadcrumbsResolver` which copies static data and solves this problem. - -For a horizontal navigation we need to provide an array of nested breadcrumbs. -For more details see [source code](https://github.com/Elonsoft/elonkit/blob/master/projects/elonkit/src/ui/breadcrumbs/__stories__/breadcrumbs-story-basic/breadcrumbs-story-basic.resolver.ts#L31) -of this story. - - - - {((args) => ({ - component: BreadcrumbsStoryBasicComponent, - moduleMetadata: { - imports: [BreadcrumbsStoryBasicModule], - }, - props: { - ...args, - }, - })).bind({})} - - - -We can customize icons and label's font. - - - - {((args) => ({ - component: BreadcrumbsStoryCustomizationComponent, - moduleMetadata: { - imports: [BreadcrumbsStoryCustomizationModule], - }, - props: { - ...args, - }, - })).bind({})} - - - -## API - - - -## Interfaces - -```ts -interface ESBreadcrumbData { - icon?: string; - svgIcon?: string; - label?: string; - breadcrumbs?: Array<{ - path: string | number; - icon?: string; - svgIcon?: string; - label?: string; - }>; -} -``` - -```ts -interface ESBreadcrumbsDefaultOptionsSizes { - itemPadding: number; - icon: number; - iconMargin: number; - menu: number; - separator: number; - more: number; -} -``` - -## Constants - -Injection token that can be used to configure the default options for all components within an app. - -```ts -import { ES_BREADCRUMBS_DEFAULT_OPTIONS } from '@elonkit/angular/ui/breadcrumbs'; - -@NgModule({ - providers: [ - { - provide: ES_BREADCRUMBS_DEFAULT_OPTIONS, - useValue: { - typography: 'es-caption', - sizes: { - itemPadding: 4, - icon: 24, - iconMargin: 4, - menu: 20, - separator: 16, - more: 24 - } - } - } - ] -}) -``` diff --git a/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.component.html b/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.component.html deleted file mode 100644 index 5f9ce1f..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.component.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - -
- - - -
-
- - - -
- - - - -
- - - -
- - - -
diff --git a/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.component.scss b/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.component.scss deleted file mode 100644 index 0a36c47..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.component.scss +++ /dev/null @@ -1,83 +0,0 @@ -.es-breadcrumbs { - display: flex; - align-items: center; - overflow: hidden; - - &__link-back-wrapper { - display: flex; - align-content: center; - } - - &__breadcrumb { - &:last-child { - margin-right: 0; - min-width: 0; - } - } - - &__separator { - width: 24px; - height: 24px; - margin: 0 -4px; - display: inline-block; - fill: currentColor; - - &_single { - width: 1px; - display: flex; - align-items: center; - margin-left: 8px; - margin-right: 8px; - } - } - - &__width { - width: auto; - height: auto; - left: -1000px; - position: absolute; - visibility: hidden; - white-space: nowrap; - z-index: -1; - } - - &__link-back { - height: 24px; - padding: 2px 4px; - display: flex; - align-items: center; - background-color: unset; - border-radius: 4px; - border-width: 0; - cursor: pointer; - min-width: fit-content; - outline: unset; - overflow: hidden; - position: relative; - text-decoration: none; - transition: 200ms; - } - - &__back-icon { - display: flex; - align-items: baseline; - margin-right: 5px; - } - - &__menu { - min-height: auto !important; - - .mat-menu-content:not(:empty) { - padding-bottom: 4px; - padding-top: 4px; - } - - .mat-menu-item { - height: 32px; - display: flex; - align-items: center; - padding-left: 16px; - padding-right: 16px; - } - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.component.theme.scss b/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.component.theme.scss deleted file mode 100644 index 3767b89..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.component.theme.scss +++ /dev/null @@ -1,27 +0,0 @@ -@import './components/breadcrumbs-breadcrumb/breadcrumbs-breadcrumb.component.theme'; -@import './components/breadcrumbs-collapse/breadcrumbs-collapse.component.theme'; - -@mixin es-breadcrumbs-theme($theme, $elonkit-theme) { - @include es-breadcrumbs-breadcrumb-theme($theme, $elonkit-theme); - @include es-breadcrumbs-collapse-theme($theme, $elonkit-theme); - - .es-breadcrumbs { - &__separator { - color: mat.get-color-from-palette(map-get($elonkit-theme, mono-a), A500); - - &_single { - background-color: mat.get-color-from-palette(map-get($elonkit-theme, mono-a), A100); - } - } - - &__link-back { - border-color: mat.get-color-from-palette(map-get($elonkit-theme, mono-a), A500); - color: mat.get-color-from-palette(map-get($elonkit-theme, mono-a), A900); - - &:hover, - &:focus { - background-color: mat.get-color-from-palette(map-get($elonkit-theme, mono-a), A50); - } - } - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.component.ts b/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.component.ts deleted file mode 100644 index 6359cd7..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.component.ts +++ /dev/null @@ -1,290 +0,0 @@ -import { - Component, - ChangeDetectionStrategy, - ChangeDetectorRef, - ViewEncapsulation, - HostListener, - ViewChild, - ElementRef, - OnInit, - OnDestroy, - AfterContentInit, - InjectionToken, - Optional, - Inject, - Input, - ContentChild, - TemplateRef, -} from '@angular/core'; - -import { Subject, Observable } from 'rxjs'; -import { takeUntil, delay } from 'rxjs/operators'; - -import { ESBreadcrumb } from './breadcrumbs.types'; -import { ESBreadcrumbsService } from './breadcrumbs.service'; - -import { ESBreadcrumbsMoreDirective } from './directives/breadcrumbs-more.directive'; -import { ESBreadcrumbsSeparatorDirective } from './directives/breadcrumbs-separator.directive'; -import { ESBreadcrumbsBackDirective } from './directives/breadcrumbs-back.directive'; -import { ESLocaleService, ESLocale } from '../locale'; - -export interface ESBreadcrumbsDefaultOptionsSizes { - itemPadding: number; - icon: number; - iconMargin: number; - menu: number; - separator: number; - more: number; -} - -export interface ESBreadcrumbsDefaultOptions { - typography?: string; - sizes?: ESBreadcrumbsDefaultOptionsSizes; -} - -export const ES_BREADCRUMBS_DEFAULT_TYPOGRAPHY = 'es-caption'; - -export const ES_BREADCRUMBS_DEFAULT_SIZES = { - itemPadding: 4, - icon: 24, - iconMargin: 4, - menu: 20, - separator: 16, - more: 24, -}; - -export const ES_BREADCRUMBS_DEFAULT_OPTIONS = new InjectionToken('ES_BREADCRUMBS_DEFAULT_OPTIONS'); - -@Component({ - selector: 'es-breadcrumbs', - templateUrl: './breadcrumbs.component.html', - styleUrls: ['./breadcrumbs.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class ESBreadcrumbsComponent implements OnInit, OnDestroy, AfterContentInit { - private _typography: string; - - /** - * @internal - * @ignore - */ - public windowHistoryLength: number; - - /** - * Whether to show Back button. - */ - @Input() public withBackButton: ESBreadcrumb; - - /** - * Class applied to breadcrumb labels. - */ - @Input() - public get typography(): string { - return this._typography; - } - public set typography(value: string) { - this._typography = value || this.defaultOptions?.typography || ES_BREADCRUMBS_DEFAULT_TYPOGRAPHY; - } - - private _sizes: ESBreadcrumbsDefaultOptionsSizes; - - /** - * Sizes of component elements which are used for collapse calculations. - */ - @Input() - public get sizes(): ESBreadcrumbsDefaultOptionsSizes { - return this._sizes; - } - public set sizes(value: ESBreadcrumbsDefaultOptionsSizes) { - this._sizes = value || this.defaultOptions?.sizes || ES_BREADCRUMBS_DEFAULT_SIZES; - } - - /** - * @ignore - */ - @ContentChild(ESBreadcrumbsMoreDirective, { read: TemplateRef, static: false }) - public moreTemplate: any; - - /** - * @ignore - */ - @ContentChild(ESBreadcrumbsBackDirective, { read: TemplateRef, static: false }) - public backTemplate: any; - - /** - * @ignore - */ - @ContentChild(ESBreadcrumbsSeparatorDirective, { read: TemplateRef, static: false }) - public separatorTemplate: any; - - /** - * @internal - * @ignore - */ - @ViewChild('navigation', { static: true }) public elementNavigation: ElementRef; - - /** - * @internal - * @ignore - */ - @ViewChild('width', { static: true }) public elementWidth: ElementRef; - - /** - * @internal - * @ignore - */ - @ViewChild('backButton', { static: true }) public elementBackButton: ElementRef; - - /** - * @internal - * @ignore - */ - @HostListener('window:resize') public onResize() { - const element = this.elementNavigation.nativeElement; - const goBackButton = this.elementBackButton.nativeElement; - - if (element && this.breadcrumbs.length > 2) { - const sizes = this.sizes; - const widths = this.breadcrumbs.map(({ data: { label, icon, breadcrumbs } }) => { - let result = 0; - - if (label) { - result += sizes.itemPadding; - result += this.getLabelWidth(label); - } - if (icon) { - result += sizes.icon; - } - if (label && icon) { - result += sizes.iconMargin; - } - if (breadcrumbs) { - result += sizes.menu; - } - - return result; - }); - let scrollWidth = widths.reduce((acc, w) => acc + w, 0) + sizes.separator * (widths.length - 1); - const clientWidth = element.clientWidth - goBackButton.clientWidth; - - const collapseIndexes = []; - const collapseBreadcrumbs = []; - - for (let i = 1; i < widths.length - 1 && scrollWidth > clientWidth; i++) { - if (!collapseIndexes.length) { - scrollWidth += sizes.more + sizes.separator; - } - - collapseIndexes.push(i); - collapseBreadcrumbs.push(this.breadcrumbs[i]); - scrollWidth -= widths[i] + sizes.separator; - } - - this.collapseIndexes = collapseIndexes; - this.collapseBreadcrumbs = collapseBreadcrumbs; - } else if (this.collapseIndexes.length) { - this.collapseIndexes = []; - this.collapseBreadcrumbs = []; - } - } - - /** - * @internal - * @ignore - */ - public breadcrumbs: ESBreadcrumb[] = []; - - /** - * @internal - * @ignore - */ - public collapseIndexes: number[] = []; - - /** - * @internal - * @ignore - */ - public collapseBreadcrumbs: ESBreadcrumb[] = []; - - private destroyed$ = new Subject(); - - constructor( - private changeDetector: ChangeDetectorRef, - private breadcrumbsService: ESBreadcrumbsService, - @Optional() - @Inject(ES_BREADCRUMBS_DEFAULT_OPTIONS) - private defaultOptions: ESBreadcrumbsDefaultOptions, - - private localeService: ESLocaleService - ) { - this.typography = defaultOptions?.typography || ES_BREADCRUMBS_DEFAULT_TYPOGRAPHY; - this.sizes = defaultOptions?.sizes || ES_BREADCRUMBS_DEFAULT_SIZES; - this.locale$ = this.localeService.locale(); - } - - /** - * @ignore - */ - public ngOnInit() { - this.breadcrumbsService.breadcrumbs$.pipe(takeUntil(this.destroyed$), delay(1)).subscribe((breadcrumbs) => { - this.breadcrumbs = breadcrumbs; - this.onResize(); - this.changeDetector.detectChanges(); - }); - - this.locale$.pipe(takeUntil(this.destroyed$)).subscribe((value) => { - this.onResize(); - }); - this.windowHistoryLength = window.history.length; - } - - /** - * @ignore - */ - public ngOnDestroy() { - this.destroyed$.next(); - } - - /** - * @ignore - */ - public ngAfterContentInit() { - if ((document as any).fonts?.ready) { - (document as any).fonts.ready.then(() => { - this.onResize(); - - // Tests in CI fail without this check. - // tslint:disable-next-line - // @ts-ignore - if (!this.changeDetector['destroyed']) { - this.changeDetector.detectChanges(); - } - }); - } - } - - /** - * @internal - * @ignore - */ - public locale$: Observable; - - private getLabelWidth(text: string) { - const container = this.elementWidth.nativeElement; - container.textContent = text; - const width = container.clientWidth + 1; - container.textContent = ''; - return width; - } - - /** - * @internal - * @ignore - */ - public onClick() { - if (window.history.length) { - window.history.back(); - } - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.module.ts b/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.module.ts deleted file mode 100644 index f29d609..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.module.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { RouterModule } from '@angular/router'; - -import { MatButtonModule } from '@angular/material/button'; -import { MatIconModule } from '@angular/material/icon'; -import { MatMenuModule } from '@angular/material/menu'; -import { MatRippleModule } from '@angular/material/core'; - -import { ESBreadcrumbsComponent } from './breadcrumbs.component'; -import { ESBreadcrumbsResolver } from './breadcrumbs.resolver'; - -import { ESBreadcrumbsBreadcrumbComponent } from './components/breadcrumbs-breadcrumb'; -import { ESBreadcrumbsCollapseComponent } from './components/breadcrumbs-collapse'; - -import { ESBreadcrumbsMoreDirective } from './directives/breadcrumbs-more.directive'; -import { ESBreadcrumbsSeparatorDirective } from './directives/breadcrumbs-separator.directive'; -import { ESBreadcrumbsBackDirective } from './directives/breadcrumbs-back.directive'; - -@NgModule({ - declarations: [ - ESBreadcrumbsComponent, - - ESBreadcrumbsBreadcrumbComponent, - ESBreadcrumbsCollapseComponent, - - ESBreadcrumbsMoreDirective, - ESBreadcrumbsSeparatorDirective, - ESBreadcrumbsBackDirective, - ], - imports: [CommonModule, RouterModule, MatButtonModule, MatIconModule, MatMenuModule, MatRippleModule], - exports: [ESBreadcrumbsComponent, ESBreadcrumbsMoreDirective, ESBreadcrumbsSeparatorDirective, ESBreadcrumbsBackDirective], - providers: [ESBreadcrumbsResolver], -}) -export class ESBreadcrumbsModule {} diff --git a/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.resolver.ts b/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.resolver.ts deleted file mode 100644 index 6f54407..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.resolver.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Resolve, ActivatedRouteSnapshot } from '@angular/router'; - -import { ESBreadcrumb } from './breadcrumbs.types'; - -@Injectable() -export class ESBreadcrumbsResolver implements Resolve { - public resolve(route: ActivatedRouteSnapshot) { - if (route.routeConfig && route.routeConfig.data && route.data['breadcrumb']) { - return route.data['breadcrumb']; - } - return null; - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.service.ts b/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.service.ts deleted file mode 100644 index 29879fa..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.service.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Injectable, OnDestroy } from '@angular/core'; -import { Router, ActivatedRoute, NavigationEnd } from '@angular/router'; - -import { Subject, BehaviorSubject } from 'rxjs'; -import { takeUntil, filter } from 'rxjs/operators'; - -import { ESBreadcrumb } from './breadcrumbs.types'; - -@Injectable({ providedIn: 'root' }) -export class ESBreadcrumbsService implements OnDestroy { - public breadcrumbs$ = new BehaviorSubject([]); - public destroyed$ = new Subject(); - - constructor( - private router: Router, - private activatedRoute: ActivatedRoute - ) { - this.getBreadcrumbs(); - - this.router.events - .pipe( - takeUntil(this.destroyed$), - filter((event) => event instanceof NavigationEnd) - ) - .subscribe(() => { - this.getBreadcrumbs(); - }); - } - - public ngOnDestroy() { - this.destroyed$.next(); - } - - private getBreadcrumbs() { - const breadcrumbs = []; - - let route: ActivatedRoute | null = this.activatedRoute; - while (route) { - if ( - (route.routeConfig?.resolve?.['breadcrumb'] || route.routeConfig?.data?.['breadcrumb']) && - route.snapshot.data['breadcrumb'] - ) { - breadcrumbs.push({ - path: this.getPath(route), - parentPath: this.getPath(route.parent), - data: route.snapshot.data['breadcrumb'], - }); - } - route = route.firstChild; - } - - this.breadcrumbs$.next(breadcrumbs); - } - - private getPath(route: ActivatedRoute | null) { - let path = ''; - - while (route) { - const segment = route.snapshot.url.map((s) => s.path).join('/'); - if (segment) { - path = `${segment}/${path}`; - } - route = route.parent; - } - - return `/${path}`; - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.types.ts b/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.types.ts deleted file mode 100644 index 4743579..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/breadcrumbs.types.ts +++ /dev/null @@ -1,19 +0,0 @@ -export interface ESBreadcrumbData { - icon?: string; - svgIcon?: string; - label?: string; - ariaLabel?: string; - breadcrumbs?: Array<{ - path: string | number; - icon?: string; - svgIcon?: string; - label?: string; - ariaLabel?: string; - }>; -} - -export interface ESBreadcrumb { - path: string; - parentPath: string; - data: ESBreadcrumbData; -} diff --git a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/breadcrumbs-breadcrumb.component.html b/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/breadcrumbs-breadcrumb.component.html deleted file mode 100644 index 135c216..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/breadcrumbs-breadcrumb.component.html +++ /dev/null @@ -1,47 +0,0 @@ -
- - - - - - - - - - - - {{ item.icon }} - - {{ item.label }} - - - -
- - - - {{ breadcrumb.data.icon }} - - - {{ breadcrumb.data.svgIcon }} - - - {{ breadcrumb.data.label }} - - diff --git a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/breadcrumbs-breadcrumb.component.scss b/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/breadcrumbs-breadcrumb.component.scss deleted file mode 100644 index 23c8c8a..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/breadcrumbs-breadcrumb.component.scss +++ /dev/null @@ -1,63 +0,0 @@ -.es-breadcrumbs-breadcrumb { - $root: '.es-breadcrumbs-breadcrumb'; - display: flex; - - align-items: center; - flex-shrink: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - - &__link { - height: 24px; - display: flex; - align-items: center; - border-radius: 4px; - min-width: 0; - overflow: hidden; - text-decoration: none; - transition: 200ms; - - &:not(&_last) { - &:hover, - &:focus { - outline: 0; - } - } - } - - &__icon { - + #{$root}__label { - margin-left: 4px; - } - } - - &__label { - overflow: hidden; - padding: 4px; - text-overflow: ellipsis; - } - - &__menu { - &.mat-icon-button { - border-radius: 4px; - width: 20px; - height: 24px; - line-height: 20px; - - &:hover, - &:focus { - outline: 0; - } - } - - .mat-icon { - width: 20px; - height: 24px; - display: flex; - justify-content: center; - align-items: center; - line-height: 20px; - } - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/breadcrumbs-breadcrumb.component.theme.scss b/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/breadcrumbs-breadcrumb.component.theme.scss deleted file mode 100644 index 484c33e..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/breadcrumbs-breadcrumb.component.theme.scss +++ /dev/null @@ -1,31 +0,0 @@ -@mixin es-breadcrumbs-breadcrumb-theme($theme, $elonkit-theme) { - .es-breadcrumbs-breadcrumb { - $root: '.es-breadcrumbs-breadcrumb'; - - &__link { - color: mat.get-color-from-palette(map-get($elonkit-theme, mono-a), A900); - - &_last { - color: mat.get-color-from-palette(map-get($elonkit-theme, mono-a), A500); - } - - &:not(&_last) { - &:hover, - &:focus { - background-color: mat.get-color-from-palette(map-get($elonkit-theme, mono-a), A50); - } - } - } - - &__menu { - color: mat.get-color-from-palette(map-get($elonkit-theme, mono-a), A500); - - &.mat-icon-button { - &:hover, - &:focus { - background-color: mat.get-color-from-palette(map-get($elonkit-theme, mono-a), A50); - } - } - } - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/breadcrumbs-breadcrumb.component.ts b/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/breadcrumbs-breadcrumb.component.ts deleted file mode 100644 index 8e12dd4..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/breadcrumbs-breadcrumb.component.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Component, ChangeDetectionStrategy, ViewEncapsulation, Input } from '@angular/core'; - -import { Observable } from 'rxjs'; - -import { ESBreadcrumb } from '../../breadcrumbs.types'; -import { ESLocaleService, ESLocale } from '../../../locale'; - -@Component({ - selector: 'es-breadcrumbs-breadcrumb', - templateUrl: './breadcrumbs-breadcrumb.component.html', - styleUrls: ['./breadcrumbs-breadcrumb.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class ESBreadcrumbsBreadcrumbComponent { - /** - * @internal - */ - @Input() public breadcrumb: ESBreadcrumb; - - /** - * @internal - */ - @Input() public last = false; - - /** - * @internal - */ - @Input() public typography: string; - - /** - * @internal - * @ignore - */ - public locale$: Observable; - - constructor( - /** - * @internal - */ - public localeService: ESLocaleService - ) { - this.locale$ = this.localeService.locale(); - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/index.ts b/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/index.ts deleted file mode 100644 index b789b05..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-breadcrumb/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { ESBreadcrumbsBreadcrumbComponent } from './breadcrumbs-breadcrumb.component'; diff --git a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/breadcrumbs-collapse.component.html b/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/breadcrumbs-collapse.component.html deleted file mode 100644 index c97cd67..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/breadcrumbs-collapse.component.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - {{ breadcrumb.data.icon }} - {{ breadcrumb.data.label }} - - - - - - {{ item.icon }} - - {{ item.label }} - - - - - diff --git a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/breadcrumbs-collapse.component.scss b/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/breadcrumbs-collapse.component.scss deleted file mode 100644 index 5bd22fa..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/breadcrumbs-collapse.component.scss +++ /dev/null @@ -1,22 +0,0 @@ -.es-breadcrumbs-collapse { - height: 24px; - padding: 0; - display: block; - background: transparent; - border: 0; - border-radius: 4px; - cursor: pointer; - outline: 0; - transition: 200ms; - - &:hover, - &:focus { - outline: 0; - } - - &__more { - width: 24px; - height: 24px; - display: inline-block; - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/breadcrumbs-collapse.component.theme.scss b/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/breadcrumbs-collapse.component.theme.scss deleted file mode 100644 index 879d9da..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/breadcrumbs-collapse.component.theme.scss +++ /dev/null @@ -1,10 +0,0 @@ -@mixin es-breadcrumbs-collapse-theme($theme, $elonkit-theme) { - .es-breadcrumbs-collapse { - color: mat.get-color-from-palette(map-get($elonkit-theme, mono-a), A600); - - &:hover, - &:focus { - background-color: mat.get-color-from-palette(map-get($elonkit-theme, mono-a), A50); - } - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/breadcrumbs-collapse.component.ts b/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/breadcrumbs-collapse.component.ts deleted file mode 100644 index dc71cf7..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/breadcrumbs-collapse.component.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Component, ChangeDetectionStrategy, ViewEncapsulation, Input } from '@angular/core'; - -import { Observable } from 'rxjs'; - -import { ESBreadcrumb } from '../../breadcrumbs.types'; -import { ESLocaleService, ESLocale } from '../../../locale'; - -@Component({ - selector: 'es-breadcrumbs-collapse', - templateUrl: './breadcrumbs-collapse.component.html', - styleUrls: ['./breadcrumbs-collapse.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class ESBreadcrumbsCollapseComponent { - /** - * @internal - */ - @Input() public breadcrumbs: ESBreadcrumb[]; - - /** - * @internal - */ - @Input() public moreTemplate: any; - - /** - * @internal - * @ignore - */ - public locale$: Observable; - - constructor( - /** - * @internal - */ - public localeService: ESLocaleService - ) { - this.locale$ = this.localeService.locale(); - } -} diff --git a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/index.ts b/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/index.ts deleted file mode 100644 index 2b0a4af..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/components/breadcrumbs-collapse/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { ESBreadcrumbsCollapseComponent } from './breadcrumbs-collapse.component'; diff --git a/projects/elonkit/src/ui/breadcrumbs/directives/breadcrumbs-back.directive.ts b/projects/elonkit/src/ui/breadcrumbs/directives/breadcrumbs-back.directive.ts deleted file mode 100644 index 77ae05e..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/directives/breadcrumbs-back.directive.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Directive } from '@angular/core'; - -@Directive({ - selector: '[esBreadcrumbsBack]', -}) -export class ESBreadcrumbsBackDirective {} diff --git a/projects/elonkit/src/ui/breadcrumbs/directives/breadcrumbs-more.directive.ts b/projects/elonkit/src/ui/breadcrumbs/directives/breadcrumbs-more.directive.ts deleted file mode 100644 index e69fe83..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/directives/breadcrumbs-more.directive.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Directive } from '@angular/core'; - -@Directive({ - selector: '[esBreadcrumbsMore]', -}) -export class ESBreadcrumbsMoreDirective {} diff --git a/projects/elonkit/src/ui/breadcrumbs/directives/breadcrumbs-separator.directive.ts b/projects/elonkit/src/ui/breadcrumbs/directives/breadcrumbs-separator.directive.ts deleted file mode 100644 index da13bfa..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/directives/breadcrumbs-separator.directive.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Directive } from '@angular/core'; - -@Directive({ - selector: '[esBreadcrumbsSeparator]', -}) -export class ESBreadcrumbsSeparatorDirective {} diff --git a/projects/elonkit/src/ui/breadcrumbs/index.ts b/projects/elonkit/src/ui/breadcrumbs/index.ts deleted file mode 100644 index 7e1a213..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './public-api'; diff --git a/projects/elonkit/src/ui/breadcrumbs/public-api.ts b/projects/elonkit/src/ui/breadcrumbs/public-api.ts deleted file mode 100644 index eb55766..0000000 --- a/projects/elonkit/src/ui/breadcrumbs/public-api.ts +++ /dev/null @@ -1,19 +0,0 @@ -export { ESBreadcrumbsModule } from './breadcrumbs.module'; -export { - ESBreadcrumbsComponent, - ESBreadcrumbsDefaultOptions, - ESBreadcrumbsDefaultOptionsSizes, - ES_BREADCRUMBS_DEFAULT_OPTIONS, - ES_BREADCRUMBS_DEFAULT_SIZES, - ES_BREADCRUMBS_DEFAULT_TYPOGRAPHY, -} from './breadcrumbs.component'; -export { ESBreadcrumbsResolver } from './breadcrumbs.resolver'; -export { ESBreadcrumbsService } from './breadcrumbs.service'; -export { ESBreadcrumb, ESBreadcrumbData } from './breadcrumbs.types'; - -export { ESBreadcrumbsBreadcrumbComponent } from './components/breadcrumbs-breadcrumb'; -export { ESBreadcrumbsCollapseComponent } from './components/breadcrumbs-collapse'; - -export { ESBreadcrumbsBackDirective } from './directives/breadcrumbs-back.directive'; -export { ESBreadcrumbsMoreDirective } from './directives/breadcrumbs-more.directive'; -export { ESBreadcrumbsSeparatorDirective } from './directives/breadcrumbs-separator.directive'; diff --git a/projects/elonkit/src/ui/dropzone/__specs__/dropzone.spec.ts b/projects/elonkit/src/ui/dropzone/__specs__/dropzone.spec.ts deleted file mode 100644 index 9661ff7..0000000 --- a/projects/elonkit/src/ui/dropzone/__specs__/dropzone.spec.ts +++ /dev/null @@ -1,213 +0,0 @@ -import { fireEvent, render, screen, waitFor } from '@testing-library/angular'; -import { MatIconTestingModule } from '@angular/material/icon/testing'; -import { Component } from '@angular/core'; -import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; -import { CommonModule } from '@angular/common'; -import { MatFormFieldModule } from '@angular/material/form-field'; - -import { ESDropzoneModule } from '../dropzone.module'; -import { ESDropzoneValidationError } from '../dropzones.types'; - -import { firstValueFrom } from 'rxjs'; - -const TEXT_HEADING = 'CHOOSE FILES'; -const TEXT_SUBHEADING = 'This is an example of a description'; -const TEXT_HINT = 'This is an example of a hint'; -const TEXT_ERROR = 'This is an example of an error'; -const TEXT_SUBMIT = 'Submit'; - -const CLASS_HEADING = 'app-body-1'; -const CLASS_SUBHEADING = 'app-caption'; - -@Component({ - template: ` -
- - ${TEXT_HINT} - ${TEXT_ERROR} - - -
- `, -}) -class DropzoneWrapperComponent { - public form = new FormGroup({ - docs: new FormControl([], Validators.required), - }); - public onSubmit(form: any) {} - public onValidate(res: ESDropzoneValidationError[]) {} -} - -describe('Drag And Drop', () => { - it('Should render component', async () => { - await render(DropzoneWrapperComponent, { - imports: [FormsModule, ReactiveFormsModule, CommonModule, MatFormFieldModule, ESDropzoneModule, MatIconTestingModule], - }); - expect(screen.getByText(TEXT_HEADING)).toBeInTheDocument(); - expect(screen.getByText(TEXT_SUBHEADING)).toBeInTheDocument(); - }); - - it('Should show hint', async () => { - await render(DropzoneWrapperComponent, { - imports: [FormsModule, ReactiveFormsModule, CommonModule, MatFormFieldModule, ESDropzoneModule, MatIconTestingModule], - }); - expect(screen.getByText(TEXT_HINT)).toBeInTheDocument(); - }); - - it('Should show error', async () => { - await render(DropzoneWrapperComponent, { - imports: [FormsModule, ReactiveFormsModule, CommonModule, MatFormFieldModule, ESDropzoneModule, MatIconTestingModule], - }); - const submitButton = screen.getByText(TEXT_SUBMIT); - fireEvent.click(submitButton); - expect(screen.getByText(TEXT_ERROR)).toBeInTheDocument(); - }); - - it('Should accept typography classes', async () => { - await render(DropzoneWrapperComponent, { - imports: [FormsModule, ReactiveFormsModule, CommonModule, MatFormFieldModule, ESDropzoneModule, MatIconTestingModule], - }); - expect(screen.getByText(TEXT_HEADING)).toHaveClass(CLASS_HEADING); - expect(screen.getByText(TEXT_SUBHEADING)).toHaveClass(CLASS_SUBHEADING); - }); - - it('Should add class on dragover and remove on drop', async () => { - await render(DropzoneWrapperComponent, { - imports: [FormsModule, ReactiveFormsModule, CommonModule, MatFormFieldModule, ESDropzoneModule, MatIconTestingModule], - }); - - fireEvent.dragOver(screen.getByText(TEXT_HEADING)); - expect(screen.getByTestId('root')).toHaveClass('es-dropzone_dragover'); - - fireEvent.drop(screen.getByText(TEXT_HEADING), { - dataTransfer: { - files: {}, - }, - }); - expect(screen.getByTestId('root')).not.toHaveClass('es-dropzone_dragover'); - }); - - it('Should add files to FormControl on drop', async () => { - const component = await render(DropzoneWrapperComponent, { - imports: [FormsModule, ReactiveFormsModule, CommonModule, MatFormFieldModule, ESDropzoneModule, MatIconTestingModule], - }); - - const fileFixture = { - name: 'filename.png', - type: 'image/png', - }; - const file = new File([''], fileFixture.name, { type: fileFixture.type }); - - fireEvent.drop(screen.getByText(TEXT_HEADING), { - dataTransfer: { - files: { - 0: file, - length: 1, - item(i: number) { - return this[i]; - }, - }, - }, - }); - - const componentInstance = component.fixture.componentInstance; - const componentValue = await firstValueFrom(componentInstance.form.valueChanges); - - expect(componentValue).toEqual({ - docs: [ - { - base64: 'data:image/png;base64,', - content: file, - name: fileFixture.name, - size: 0, - type: fileFixture.type, - }, - ], - }); - }); - - it('Should add files to FormControl on change', async () => { - const component = await render(DropzoneWrapperComponent, { - imports: [FormsModule, ReactiveFormsModule, CommonModule, MatFormFieldModule, ESDropzoneModule, MatIconTestingModule], - }); - - const fileFixture = { - name: 'filename.png', - type: 'image/png', - }; - const file = new File([''], fileFixture.name, { type: fileFixture.type }); - - fireEvent.change(screen.getByTestId('input'), { - target: { - files: { - 0: file, - length: 1, - item(i: number) { - return this[i]; - }, - }, - }, - }); - - const componentInstance = component.fixture.componentInstance; - const componentValue = await firstValueFrom(componentInstance.form.valueChanges); - - expect(componentValue).toEqual({ - docs: [ - { - base64: 'data:image/png;base64,', - content: file, - name: fileFixture.name, - size: 0, - type: fileFixture.type, - }, - ], - }); - }); - - it('Should emit validation errors', async () => { - const component = await render(DropzoneWrapperComponent, { - imports: [FormsModule, ReactiveFormsModule, CommonModule, MatFormFieldModule, ESDropzoneModule, MatIconTestingModule], - }); - - const fileFixture1 = { - name: 'filename1.pdf', - type: 'application/pdf', - }; - const fileFixture2 = { - name: 'filename2.png', - type: 'image/png', - }; - const file1 = new File([''], fileFixture1.name, { type: fileFixture1.type }); - const file2 = new File(['0123456789'], fileFixture2.name, { type: fileFixture2.type }); - const spy = jest.spyOn(component.fixture.componentInstance, 'onValidate'); - - fireEvent.change(screen.getByTestId('input'), { - target: { - files: { - 0: file1, - 1: file2, - length: 2, - item(i: number) { - return this[i]; - }, - }, - }, - }); - - await waitFor(() => - expect(spy).toHaveBeenCalledWith([ - { error: 'FILE_TYPE', fileName: file1.name }, - { error: 'FILE_SIZE', fileName: file2.name }, - ]) - ); - }); -}); diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.component.html b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.component.html deleted file mode 100644 index f597eea..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.component.html +++ /dev/null @@ -1,12 +0,0 @@ -
- - {{ locale === 'en' ? 'This is an example of a hint message' : 'Это пример подсказки' }} - -
diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.component.scss b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.component.scss deleted file mode 100644 index 7fcfd2d..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.dropzone { - max-width: 400px; -} diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.component.ts b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.component.ts deleted file mode 100644 index ffd0286..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.component.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Component, ChangeDetectionStrategy, OnInit, Input, Output, EventEmitter, OnDestroy } from '@angular/core'; -import { FormControl } from '@angular/forms'; - -import { ESDropzoneFile } from '../../dropzones.types'; -import { Subscription } from 'rxjs'; - -@Component({ - selector: 'es-dropzone-basic', - templateUrl: './dropzone-story-basic.component.html', - styleUrls: ['./dropzone-story-basic.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class DropzoneStoryBasicComponent implements OnInit, OnDestroy { - @Input() public heading: string; - @Input() public subheading: string; - @Input() public accept: string; - @Input() public maxSize: number; - @Input() public type: 'base64' | 'binary'; - - @Input() public locale: 'en' | 'ru'; - - @Output() - public changeFiles = new EventEmitter(); - - public docs = new FormControl([]); - - private docSub: Subscription; - - public ngOnInit(): void { - this.docSub = this.docs.valueChanges.subscribe((val) => { - this.changeFiles.emit(val); - }); - } - - public ngOnDestroy(): void { - this.docSub.unsubscribe(); - } -} diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.module.ts b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.module.ts deleted file mode 100644 index 6edec6a..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.module.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatFormFieldModule } from '@angular/material/form-field'; - -import { DropzoneStoryBasicComponent } from './dropzone-story-basic.component'; -import { ESDropzoneModule } from '../..'; - -@NgModule({ - declarations: [DropzoneStoryBasicComponent], - imports: [FormsModule, ReactiveFormsModule, CommonModule, FormsModule, MatFormFieldModule, ESDropzoneModule], - exports: [DropzoneStoryBasicComponent], -}) -export class DropzoneStoryBasicModule {} diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.source.ts b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.source.ts deleted file mode 100644 index 82e2e34..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/dropzone-story-basic.source.ts +++ /dev/null @@ -1,22 +0,0 @@ -export const DROPZONE_STORY_BASIC_SOURCE = { - ts: ` - export class AppComponent { - public docs = new FormControl([]); - } - `, - html: ` -
- - This is an example of a hint message - -
- `, -}; diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/index.ts b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/index.ts deleted file mode 100644 index e4db4bb..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-basic/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { DropzoneStoryBasicModule } from './dropzone-story-basic.module'; -export { DropzoneStoryBasicComponent } from './dropzone-story-basic.component'; -export { DROPZONE_STORY_BASIC_SOURCE } from './dropzone-story-basic.source'; diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.component.html b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.component.html deleted file mode 100644 index aded286..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.component.html +++ /dev/null @@ -1,5 +0,0 @@ -
- - {{ locale === 'en' ? 'This is an example of a hint message' : 'Это пример подсказки' }} - -
diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.component.scss b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.component.scss deleted file mode 100644 index d65bec4..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.form { - max-width: 400px; -} diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.component.ts b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.component.ts deleted file mode 100644 index caf8e22..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.component.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; -import { FormGroup, FormControl } from '@angular/forms'; -import { DomSanitizer } from '@angular/platform-browser'; -import { MatIconRegistry } from '@angular/material/icon'; - -@Component({ - selector: 'es-dropzone-custom-icon', - templateUrl: './dropzone-story-custom-icon.component.html', - styleUrls: ['./dropzone-story-custom-icon.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class DropzoneStoryCustomIconComponent { - @Input() public heading: string; - @Input() public subheading: string; - - @Input() public locale: 'en' | 'ru'; - - public form = new FormGroup({ - docs: new FormControl([]), - }); - - constructor( - private iconRegistry: MatIconRegistry, - private sanitizer: DomSanitizer - ) { - iconRegistry.addSvgIcon('upload', sanitizer.bypassSecurityTrustResourceUrl('/icons/upload.svg')); - } -} diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.module.ts b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.module.ts deleted file mode 100644 index 9029d24..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.module.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatFormFieldModule } from '@angular/material/form-field'; - -import { DropzoneStoryCustomIconComponent } from './dropzone-story-custom-icon.component'; -import { ESDropzoneModule } from '../..'; - -@NgModule({ - declarations: [DropzoneStoryCustomIconComponent], - imports: [FormsModule, ReactiveFormsModule, CommonModule, FormsModule, MatFormFieldModule, ESDropzoneModule], - exports: [DropzoneStoryCustomIconComponent], -}) -export class DropzoneStoryCustomIconModule {} diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.source.ts b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.source.ts deleted file mode 100644 index cb536d9..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/dropzone-story-custom-icon.source.ts +++ /dev/null @@ -1,28 +0,0 @@ -export const DROPZONE_STORY_CUSTOM_ICON_SOURCE = { - ts: ` - export class AppComponent { - public form = new FormGroup({ - docs: new FormControl([]) - }); - - constructor(private iconRegistry: MatIconRegistry, private sanitizer: DomSanitizer) { - iconRegistry.addSvgIcon( - 'upload', - sanitizer.bypassSecurityTrustResourceUrl('/icons/upload.svg') - ); - } - } - `, - html: ` -
- - This is an example of a hint message - -
- `, -}; diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/index.ts b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/index.ts deleted file mode 100644 index b8f9c9b..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-custom-icon/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { DropzoneStoryCustomIconModule } from './dropzone-story-custom-icon.module'; -export { DropzoneStoryCustomIconComponent } from './dropzone-story-custom-icon.component'; -export { DROPZONE_STORY_CUSTOM_ICON_SOURCE } from './dropzone-story-custom-icon.source'; diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.component.html b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.component.html deleted file mode 100644 index 36e860a..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.component.html +++ /dev/null @@ -1,11 +0,0 @@ -
- - {{ locale === 'en' ? 'This is an example of a hint message' : 'Это пример подсказки' }} - - {{ locale === 'en' ? 'Select at least one file' : 'Выберите хотя бы один файл' }} - - - -
diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.component.scss b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.component.scss deleted file mode 100644 index 0974e36..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.component.scss +++ /dev/null @@ -1,8 +0,0 @@ -.form { - max-width: 400px; - - &__submit { - margin-top: 15px; - text-transform: uppercase; - } -} diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.component.ts b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.component.ts deleted file mode 100644 index 4730497..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.component.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; -import { FormGroup, FormControl, Validators } from '@angular/forms'; -import { DomSanitizer } from '@angular/platform-browser'; -import { MatIconRegistry } from '@angular/material/icon'; - -@Component({ - selector: 'es-dropzone-required', - templateUrl: './dropzone-story-required.component.html', - styleUrls: ['./dropzone-story-required.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class DropzoneStoryRequiredComponent { - @Input() public heading: string; - @Input() public subheading: string; - - @Input() public locale: 'en' | 'ru'; - - public form = new FormGroup({ - docs: new FormControl([], Validators.required), - }); - - constructor( - private iconRegistry: MatIconRegistry, - private sanitizer: DomSanitizer - ) { - iconRegistry.addSvgIcon('upload', sanitizer.bypassSecurityTrustResourceUrl('/icons/upload.svg')); - } - - public onSubmit(form: any) {} -} diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.module.ts b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.module.ts deleted file mode 100644 index 8a4e086..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatFormFieldModule } from '@angular/material/form-field'; - -import { DropzoneStoryRequiredComponent } from './dropzone-story-required.component'; -import { ESDropzoneModule } from '../..'; - -@NgModule({ - declarations: [DropzoneStoryRequiredComponent], - imports: [FormsModule, ReactiveFormsModule, MatButtonModule, CommonModule, MatFormFieldModule, ESDropzoneModule], - exports: [DropzoneStoryRequiredComponent], -}) -export class DropzoneStoryRequiredModule {} diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.source.ts b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.source.ts deleted file mode 100644 index 5a22dd5..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/dropzone-story-required.source.ts +++ /dev/null @@ -1,34 +0,0 @@ -export const DROPZONE_STORY_REQUIRED_SOURCE = { - ts: ` - export class AppComponent { - public form = new FormGroup({ - docs: new FormControl([], Validators.required) - }); - ... - public onSubmit(form: any) {} - } - `, - html: ` -
- - This is an example of a hint message - Select at least one file - - -
- `, - scss: ` - .form { - max-width: 400px; - - &__submit { - margin-top: 15px; - text-transform: uppercase; - } - } - `, -}; diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/index.ts b/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/index.ts deleted file mode 100644 index ca9a944..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone-story-required/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { DropzoneStoryRequiredModule } from './dropzone-story-required.module'; -export { DropzoneStoryRequiredComponent } from './dropzone-story-required.component'; -export { DROPZONE_STORY_REQUIRED_SOURCE } from './dropzone-story-required.source'; diff --git a/projects/elonkit/src/ui/dropzone/__stories__/dropzone.stories.mdx b/projects/elonkit/src/ui/dropzone/__stories__/dropzone.stories.mdx deleted file mode 100644 index c9bf61e..0000000 --- a/projects/elonkit/src/ui/dropzone/__stories__/dropzone.stories.mdx +++ /dev/null @@ -1,170 +0,0 @@ -import { Meta, Story, ArgsTable } from '@storybook/addon-docs'; -import { Canvas } from '~storybook/components'; - -import { action } from '@storybook/addon-actions'; - -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; - -import { ESDropzoneComponent } from '..'; - -import { DropzoneStoryBasicModule, DropzoneStoryBasicComponent, DROPZONE_STORY_BASIC_SOURCE } from './dropzone-story-basic'; - -import { - DropzoneStoryRequiredModule, - DropzoneStoryRequiredComponent, - DROPZONE_STORY_REQUIRED_SOURCE, -} from './dropzone-story-required'; - -import { - DropzoneStoryCustomIconModule, - DropzoneStoryCustomIconComponent, - DROPZONE_STORY_CUSTOM_ICON_SOURCE, -} from './dropzone-story-custom-icon'; - - - -# Dropzone - -This component allows to select files on click or by drag and drop. - -## Demos - -export const getHeading = (args, context) => { - return args.heading || (context.globals.locale === 'en' ? 'CHOOSE FILES' : 'ВЫБЕРИТЕ ФАЙЛЫ'); -}; - -export const getSubheading = (args, context) => { - return ( - args.subheading || - (context.globals.locale === 'en' - ? 'or drag files in this area (max size: 50 MB)' - : 'или перетащите файлы в эту область (не более 50 мб)') - ); -}; - -Validation errors are emitted from `validate` output as array of `ESDropzoneValidationError`. - - - - {((args, context) => ({ - component: DropzoneStoryBasicComponent, - moduleMetadata: { - imports: [DropzoneStoryBasicModule], - }, - props: { - ...args, - heading: getHeading(args, context), - subheading: getSubheading(args, context), - locale: context.globals.locale, - changeFiles: action('onChangeFiles'), - validate: action('onValidate'), - }, - })).bind({})} - - - -We can make Control required by adding a Validator. - - - - {((args, context) => ({ - component: DropzoneStoryRequiredComponent, - moduleMetadata: { - imports: [DropzoneStoryRequiredModule], - }, - props: { - ...args, - heading: getHeading(args, context), - subheading: getSubheading(args, context), - locale: context.globals.locale, - }, - })).bind({})} - - - -We can pass `svgIcon` to use custom upload icon. - - - - {((args, context) => ({ - component: DropzoneStoryCustomIconComponent, - moduleMetadata: { - imports: [DropzoneStoryCustomIconModule], - }, - props: { - ...args, - heading: getHeading(args, context), - subheading: getSubheading(args, context), - locale: context.globals.locale, - }, - })).bind({})} - - - -## API - - - -## Interfaces - -```ts -interface ESDropzoneFile { - id?: number; - type?: string; - base64?: string; - name: string; - size: number; - content: File | string; -} -``` - -ESDropzoneDefaultOptions `type` property defines if ESDropzoneFile `content` property will be `base64` or `binary`. - -```ts -interface ESDropzoneDefaultOptions { - accept?: string; - svgIcon?: string; - maxSize?: number; - type?: 'base64' | 'binary'; - headingTypography?: string; - subheadingTypography?: string; -} -``` - -```ts -interface ESDropzoneValidationError { - fileName: string; - error: 'FILE_TYPE' | 'FILE_SIZE'; -} -``` - -Injection token that can be used to configure the default options for all components within an app. - -```ts -import { ES_DROPZONE_DEFAULT_OPTIONS } from '@elonkit/angular/ui/dropzone'; - -@NgModule({ - providers: [ - { - provide: ES_DROPZONE_DEFAULT_OPTIONS, - useValue: { - accept: 'image/png,image/jpg,image/jpeg', - svgIcon: 'upload', - maxSize: 50, - type: 'binary' - } - } - ] -}) -``` diff --git a/projects/elonkit/src/ui/dropzone/dropzone.component.html b/projects/elonkit/src/ui/dropzone/dropzone.component.html deleted file mode 100644 index b76e61e..0000000 --- a/projects/elonkit/src/ui/dropzone/dropzone.component.html +++ /dev/null @@ -1,31 +0,0 @@ - -
- - -
- diff --git a/projects/elonkit/src/ui/dropzone/dropzone.component.scss b/projects/elonkit/src/ui/dropzone/dropzone.component.scss deleted file mode 100644 index 23d9d75..0000000 --- a/projects/elonkit/src/ui/dropzone/dropzone.component.scss +++ /dev/null @@ -1,51 +0,0 @@ -.es-dropzone { - width: 100%; - padding: 24px; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - border-radius: 5px; - box-sizing: border-box; - cursor: pointer; - - &:active, - &:focus { - outline: 0; - } - - &_dragover { - * { - pointer-events: none; - } - } - - &__input { - display: none; - } - - &__heading { - display: flex; - align-items: center; - letter-spacing: 0.5px; - - &:not(:last-child) { - margin-bottom: 4px; - } - } - - &__subheading { - letter-spacing: 0.4px; - margin-bottom: 4px; - } - - &__choose-icon { - margin-right: 8px; - } - - &__hint { - letter-spacing: 0.4px; - margin-top: 8px; - padding: 0 12px; - } -} diff --git a/projects/elonkit/src/ui/dropzone/dropzone.component.theme.scss b/projects/elonkit/src/ui/dropzone/dropzone.component.theme.scss deleted file mode 100644 index fe7de8d..0000000 --- a/projects/elonkit/src/ui/dropzone/dropzone.component.theme.scss +++ /dev/null @@ -1,30 +0,0 @@ -@mixin es-dropzone-theme($theme, $elonkit-theme) { - $mono-a: map-get($elonkit-theme, mono-a); - - .es-dropzone { - background-color: mat.get-color-from-palette($mono-a, A50); - border: 1px dashed mat.get-color-from-palette($mono-a, A200); - - &:hover { - background-color: mat.get-color-from-palette($mono-a, A100); - } - - &:active, - &:focus { - background-color: mat.get-color-from-palette($mono-a, A200); - } - - &_dragover { - background-color: mat.get-color-from-palette($mono-a, A200); - border: 1px dotted mat.get-color-from-palette($mono-a, A200); - } - - &__heading { - color: mat.get-color-from-palette(map-get($theme, primary)); - } - - &__subheading { - color: mat.get-color-from-palette($mono-a, A500); - } - } -} diff --git a/projects/elonkit/src/ui/dropzone/dropzone.component.ts b/projects/elonkit/src/ui/dropzone/dropzone.component.ts deleted file mode 100644 index bd17b0d..0000000 --- a/projects/elonkit/src/ui/dropzone/dropzone.component.ts +++ /dev/null @@ -1,349 +0,0 @@ -import { - Component, - Input, - Optional, - ViewChild, - ElementRef, - ChangeDetectorRef, - ViewEncapsulation, - InjectionToken, - Inject, - Self, - Output, - EventEmitter, - ChangeDetectionStrategy, - DoCheck, -} from '@angular/core'; -import { ControlValueAccessor, FormGroupDirective, NgControl } from '@angular/forms'; -import { coerceNumberProperty } from '@angular/cdk/coercion'; - -import { validateFileType } from '../../utils/validate-file-type'; -import { ESDropzoneFile, ESDropzoneDefaultOptions, ESDropzoneValidationError } from './dropzones.types'; - -export const ES_DROPZONE_DEFAULT_OPTIONS = new InjectionToken('ES_DROPZONE_DEFAULT_OPTIONS'); - -const toFile = (type: string | undefined, file: File | null) => - new Promise((resolve, reject) => { - const reader = new FileReader(); - if (file) { - reader.readAsDataURL(file); - reader.onload = () => { - resolve({ - content: type === 'binary' ? file : (reader.result as string), - name: file.name, - size: file.size, - type: file.type, - base64: reader.result as string, - }); - }; - reader.onerror = (error) => reject(error); - } - }); - -@Component({ - selector: 'es-dropzone', - templateUrl: './dropzone.component.html', - styleUrls: ['./dropzone.component.scss'], - encapsulation: ViewEncapsulation.None, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class ESDropzoneComponent implements ControlValueAccessor, DoCheck { - /** - * @internal - * @ignore - */ - public files: ESDropzoneFile[]; - - /** - * @internal - * @ignore - */ - public isDragover: boolean; - - /** - * Defines Choose Text Label. - */ - @Input() - public heading: string; - - /** - * Defines Drag Text Label. - */ - @Input() - public subheading: string; - - /** - * File types to accept separated by a comma, e.g. `image/png,image/jpg,image/jpeg` - */ - @Input() - public get accept(): string { - return this._accept; - } - public set accept(value: string | undefined) { - this._accept = value || this.defaultOptions?.accept || '*'; - } - private _accept: string; - - /** - * Custom svg icon to render with `chooseText`. - */ - @Input() - public get svgIcon(): string | undefined { - return this._svgIcon; - } - public set svgIcon(value: string | undefined) { - this._svgIcon = value || this.defaultOptions?.svgIcon; - } - private _svgIcon: string | undefined; - - /** - * Max accepted file size in megabytes. - */ - @Input() - public get maxSize(): number | undefined { - return this._maxSize; - } - public set maxSize(value: number | undefined) { - this._maxSize = coerceNumberProperty(value, this.defaultOptions?.maxSize || 0); - } - private _maxSize: number | undefined; - - /** - * Defines if ESDropzoneFile `content` property will be `base64` or `binary` format. - */ - @Input() - public get type(): 'base64' | 'binary' | undefined { - return this._type; - } - public set type(value: 'base64' | 'binary' | undefined) { - this._type = value || this.defaultOptions?.type || 'binary'; - } - private _type: 'base64' | 'binary' | undefined; - - /** - * Class applied to heading text. - */ - @Input() - public get headingTypography(): string | undefined { - return this._headingTypography; - } - public set headingTypography(value: string | undefined) { - this._headingTypography = value || this.defaultOptions?.headingTypography || 'mat-body-2'; - } - private _headingTypography: string | undefined; - - /** - * Class applied to subheading text. - */ - @Input() - public get subheadingTypography(): string | undefined { - return this._subheadingTypography; - } - public set subheadingTypography(value: string | undefined) { - this._subheadingTypography = value || this.defaultOptions?.subheadingTypography || 'mat-caption'; - } - private _subheadingTypography: string | undefined; - - /** - * Array of validation errors is emitted. - */ - @Output() - public validate: EventEmitter = new EventEmitter(); - - /** - * @internal - * @ignore - */ - @ViewChild('fileInput', { static: true }) - public fileInput: ElementRef; - - private propagateChange = (_: any) => {}; - private errors: ESDropzoneValidationError[]; - // tslint:disable-next-line: no-inferrable-types - private errorState = false; - - /** - * @internal - * @ignore - */ - constructor( - private cdRef: ChangeDetectorRef, - @Optional() - @Inject(ES_DROPZONE_DEFAULT_OPTIONS) - private defaultOptions: ESDropzoneDefaultOptions, - /** - * @internal - */ - @Optional() - @Self() - public ngControl: NgControl, - /** - * @internal - */ - @Optional() public ngForm: FormGroupDirective - ) { - if (this.ngControl != null) { - this.ngControl.valueAccessor = this; - } - this.accept = this.defaultOptions?.accept; - this.svgIcon = this.defaultOptions?.svgIcon; - this.maxSize = this.defaultOptions?.maxSize; - this.type = this.defaultOptions?.type; - this.headingTypography = this.defaultOptions?.headingTypography; - this.subheadingTypography = this.defaultOptions?.subheadingTypography; - } - - /** - * @ignore - */ - public ngDoCheck(): void { - const newErrorState = this.isErrorState(); - if (this.errorState !== newErrorState) { - this.cdRef.markForCheck(); - this.errorState = newErrorState; - } - } - - /** - * @ignore - */ - public writeValue(files: ESDropzoneFile[]): void { - this.files = files; - } - - /** - * @ignore - */ - public registerOnChange(fn: any): void { - this.propagateChange = fn; - } - - /** - * @ignore - */ - public registerOnTouched(fn: any): void {} - - /** - * @internal - * @ignore - */ - public async onDrop(e: DragEvent) { - e.preventDefault(); - e.stopPropagation(); - this.errors = []; - const files = e?.dataTransfer?.files as FileList; - for (let i = 0; i < files.length; i++) { - await this.setFile(files.item(i)); - } - this.isDragover = false; - this.cdRef.markForCheck(); - this.propagateChange(this.files); - this.validate.emit(this.errors); - } - - /** - * @internal - * @ignore - */ - public onDragover(e: DragEvent): void { - e.preventDefault(); - e.stopPropagation(); - this.isDragover = true; - } - - /** - * @internal - * @ignore - */ - public onDragleave(e: DragEvent): void { - e.preventDefault(); - e.stopPropagation(); - this.isDragover = false; - } - - /** - * @internal - * @ignore - */ - public onDragend(e: DragEvent): void { - e.preventDefault(); - e.stopPropagation(); - this.isDragover = false; - } - - /** - * @internal - * @ignore - */ - public openSelectFileDialog(): void { - const input = this.fileInput.nativeElement; - input.value = null; - input.click(); - } - - /** - * @internal - * @ignore - */ - public async onChange(e: any) { - e.stopPropagation(); - this.errors = []; - const files = e.target.files as FileList; - for (let i = 0; i < files.length; i++) { - await this.setFile(files.item(i)); - } - this.cdRef.markForCheck(); - this.propagateChange(this.files); - this.validate.emit(this.errors); - } - - /** - * @internal - * @ignore - */ - public get invalid(): boolean { - return this.errorState; - } - - private async setFile(file: File | null) { - if (!this.fileTypeValid(file) || !this.validateFileSize(file)) { - return; - } - - const targetFile = await toFile(this.type, file); - this.files = [...this.files, targetFile]; - } - - private fileTypeValid(file: File | null): boolean { - if (file && !validateFileType(file, this.accept)) { - this.errors.push({ - fileName: file.name, - error: 'FILE_TYPE', - }); - return false; - } - return true; - } - - private get maxSizeInBytes(): number | undefined { - if (this.maxSize) { - return +this.maxSize * 1024 * 1024; - } - return; - } - - private validateFileSize(file: File | null): boolean { - if (file && this.maxSizeInBytes && this.maxSize && file.size > this.maxSizeInBytes) { - this.errors.push({ - fileName: file.name, - error: 'FILE_SIZE', - }); - return false; - } - return true; - } - - private isErrorState(): boolean { - return !!(this.ngControl && this.ngControl.invalid && (this.ngControl.touched || (this.ngForm && this.ngForm.submitted))); - } -} diff --git a/projects/elonkit/src/ui/dropzone/dropzone.module.ts b/projects/elonkit/src/ui/dropzone/dropzone.module.ts deleted file mode 100644 index b7f26be..0000000 --- a/projects/elonkit/src/ui/dropzone/dropzone.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { MatButtonModule } from '@angular/material/button'; -import { MatIconModule } from '@angular/material/icon'; -import { HttpClientModule } from '@angular/common/http'; -import { MatRippleModule } from '@angular/material/core'; - -import { ESDropzoneComponent } from './dropzone.component'; - -@NgModule({ - declarations: [ESDropzoneComponent], - imports: [CommonModule, MatButtonModule, MatIconModule, MatRippleModule, HttpClientModule], - exports: [ESDropzoneComponent], -}) -export class ESDropzoneModule {} diff --git a/projects/elonkit/src/ui/dropzone/dropzones.types.ts b/projects/elonkit/src/ui/dropzone/dropzones.types.ts deleted file mode 100644 index 6be41e7..0000000 --- a/projects/elonkit/src/ui/dropzone/dropzones.types.ts +++ /dev/null @@ -1,22 +0,0 @@ -export interface ESDropzoneFile { - id?: number; - type?: string; - base64?: string; - name: string; - size: number; - content: File | string; -} - -export interface ESDropzoneDefaultOptions { - accept?: string; - svgIcon?: string; - maxSize?: number; - type?: 'base64' | 'binary'; - headingTypography?: string; - subheadingTypography?: string; -} - -export interface ESDropzoneValidationError { - fileName: string; - error: 'FILE_TYPE' | 'FILE_SIZE'; -} diff --git a/projects/elonkit/src/ui/dropzone/index.ts b/projects/elonkit/src/ui/dropzone/index.ts deleted file mode 100644 index 7e1a213..0000000 --- a/projects/elonkit/src/ui/dropzone/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './public-api'; diff --git a/projects/elonkit/src/ui/dropzone/public-api.ts b/projects/elonkit/src/ui/dropzone/public-api.ts deleted file mode 100644 index c48d639..0000000 --- a/projects/elonkit/src/ui/dropzone/public-api.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { ESDropzoneModule } from './dropzone.module'; -export { ESDropzoneComponent, ES_DROPZONE_DEFAULT_OPTIONS } from './dropzone.component'; -export { ESDropzoneFile, ESDropzoneDefaultOptions, ESDropzoneValidationError } from './dropzones.types'; diff --git a/projects/elonkit/src/ui/empty-state/__specs__/empty-state.spec.ts b/projects/elonkit/src/ui/empty-state/__specs__/empty-state.spec.ts deleted file mode 100644 index 1a3605b..0000000 --- a/projects/elonkit/src/ui/empty-state/__specs__/empty-state.spec.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { render } from '@testing-library/angular'; -import { MatIconTestingModule } from '@angular/material/icon/testing'; - -import { ESEmptyStateModule, ESEmptyStateComponent, ESEmptyStateIcon } from '..'; - -const TEXT_HEADING = 'HEADING'; -const TEXT_SUBHEADING = 'SUBHEADING'; - -describe('EmptyState', () => { - it('Should display heading and subheading', async () => { - const component = await render(ESEmptyStateComponent, { - imports: [MatIconTestingModule, ESEmptyStateModule], - excludeComponentDeclaration: true, - componentProperties: { - heading: TEXT_HEADING, - subheading: TEXT_SUBHEADING, - }, - }); - - expect(component.queryByText(TEXT_HEADING)).toBeInTheDocument(); - expect(component.queryByText(TEXT_SUBHEADING)).toBeInTheDocument(); - }); - - it('Should accept typography classes', async () => { - const component = await render(ESEmptyStateComponent, { - imports: [MatIconTestingModule, ESEmptyStateModule], - excludeComponentDeclaration: true, - componentProperties: { - heading: TEXT_HEADING, - headingTypography: 'app-body-1', - subheading: TEXT_SUBHEADING, - subheadingTypography: 'app-caption', - }, - }); - - expect(component.getByText(TEXT_HEADING)).toHaveClass('app-body-1'); - expect(component.getByText(TEXT_SUBHEADING)).toHaveClass('app-caption'); - }); - - it('Should display correct prebuilt icon', async () => { - const component = await render(ESEmptyStateComponent, { - imports: [MatIconTestingModule, ESEmptyStateModule], - excludeComponentDeclaration: true, - componentProperties: { - heading: TEXT_HEADING, - subheading: TEXT_SUBHEADING, - }, - }); - - for (const icon of ['box', 'chat', 'face', 'file', 'lock', 'search']) { - component.fixture.componentInstance.icon = icon as ESEmptyStateIcon; - component.fixture.componentInstance.changeDetector.detectChanges(); - - expect(component.getByTestId('svg')).toHaveAttribute('ng-reflect-svg-icon', `es-empty-state:${icon}`); - } - }); - - it('Should accept custom icon', async () => { - const component = await render(ESEmptyStateComponent, { - imports: [MatIconTestingModule, ESEmptyStateModule], - excludeComponentDeclaration: true, - componentProperties: { - src: 'www.example.com/image.png', - heading: TEXT_HEADING, - subheading: TEXT_SUBHEADING, - }, - }); - - expect(component.getByTestId('img')).toHaveAttribute('src', 'www.example.com/image.png'); - }); -}); diff --git a/projects/elonkit/src/ui/empty-state/__stories__/empty-state-story-basic/empty-state-story-basic.source.ts b/projects/elonkit/src/ui/empty-state/__stories__/empty-state-story-basic/empty-state-story-basic.source.ts deleted file mode 100644 index 3a03d39..0000000 --- a/projects/elonkit/src/ui/empty-state/__stories__/empty-state-story-basic/empty-state-story-basic.source.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const EMPTY_STATE_STORY_BASIC_SOURCE = { - html: ` - - `, -}; diff --git a/projects/elonkit/src/ui/empty-state/__stories__/empty-state-story-basic/index.ts b/projects/elonkit/src/ui/empty-state/__stories__/empty-state-story-basic/index.ts deleted file mode 100644 index ff7ee71..0000000 --- a/projects/elonkit/src/ui/empty-state/__stories__/empty-state-story-basic/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { EMPTY_STATE_STORY_BASIC_SOURCE } from './empty-state-story-basic.source'; diff --git a/projects/elonkit/src/ui/empty-state/__stories__/empty-state-story-button/empty-state-story-button.source.ts b/projects/elonkit/src/ui/empty-state/__stories__/empty-state-story-button/empty-state-story-button.source.ts deleted file mode 100644 index b296e6a..0000000 --- a/projects/elonkit/src/ui/empty-state/__stories__/empty-state-story-button/empty-state-story-button.source.ts +++ /dev/null @@ -1,7 +0,0 @@ -export const EMPTY_STATE_STORY_BUTTON_SOURCE = { - html: ` - - - - `, -}; diff --git a/projects/elonkit/src/ui/empty-state/__stories__/empty-state-story-button/index.ts b/projects/elonkit/src/ui/empty-state/__stories__/empty-state-story-button/index.ts deleted file mode 100644 index a528a4a..0000000 --- a/projects/elonkit/src/ui/empty-state/__stories__/empty-state-story-button/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { EMPTY_STATE_STORY_BUTTON_SOURCE } from './empty-state-story-button.source'; diff --git a/projects/elonkit/src/ui/empty-state/__stories__/empty-state.stories.mdx b/projects/elonkit/src/ui/empty-state/__stories__/empty-state.stories.mdx deleted file mode 100644 index 8015bbe..0000000 --- a/projects/elonkit/src/ui/empty-state/__stories__/empty-state.stories.mdx +++ /dev/null @@ -1,169 +0,0 @@ -import { Meta, Story, ArgsTable } from '@storybook/addon-docs'; -import { Canvas } from '~storybook/components'; -import { CoreModule } from '~storybook/core.module'; - -import { action } from '@storybook/addon-actions'; - -import { HttpClientModule } from '@angular/common/http'; -import { MatButton, MatButtonModule } from '@angular/material/button'; - -import { ESIconsService } from '../../icons'; -import { ESEmptyStateModule, ESEmptyStateComponent } from '..'; - -import { EMPTY_STATE_STORY_BASIC_SOURCE } from './empty-state-story-basic'; -import { EMPTY_STATE_STORY_BUTTON_SOURCE } from './empty-state-story-button'; - - - -# Empty State - -A placeholder to use on pages without content. - -## Demos - -export const getHeading = (args, context) => { - return args.heading || (context.globals.locale === 'en' ? 'There are no entities yet' : 'Здесь пока нет сущностей'); -}; - -export const getSubheading = (args, context) => { - return ( - args.subheading || - (context.globals.locale === 'en' - ? 'There are no entities yet. Do you want to create the first entity?' - : 'Здесь пока нет сущностей. Хотите создать первую сущность?') - ); -}; - - - - {((args, context) => ({ - template: ` - - `, - moduleMetadata: { - imports: [HttpClientModule, CoreModule, ESEmptyStateModule, MatButtonModule], - }, - props: { - ...args, - heading: getHeading(args, context), - subheading: getSubheading(args, context), - }, - })).bind({})} - - - -We can include action button. - - - - {((args, context) => ({ - template: ` - - - - `, - moduleMetadata: { - imports: [HttpClientModule, MatButtonModule, CoreModule, ESEmptyStateModule], - }, - props: { - ...args, - heading: getHeading(args, context), - subheading: getSubheading(args, context), - }, - })).bind({})} - - - -## API - - - -## Interfaces - -```ts -interface ESEmptyStateDefaultOptions { - icon?: - | 'bar-chart' - | 'bell' - | 'box' - | 'camera' - | 'cart' - | 'chat' - | 'face' - | 'file' - | 'filter' - | 'image' - | 'lock' - | 'pie-chart' - | 'search' - | 'smile' - | 'wi-fi' - | 'wi-fi-off'; - headingTypography?: string; - subheadingTypography?: string; -} -``` - -## Constants - -Injection token that can be used to configure the default options for all components within an app. - -```ts -import { ES_EMPTY_STATE_DEFAULT_OPTIONS } from '@elonkit/angular/ui/empty-state'; - -@NgModule({ - providers: [ - { - provide: ES_EMPTY_STATE_DEFAULT_OPTIONS, - useValue: { - icon: 'box', - size: 'medium' - } - } - ] -}) -``` diff --git a/projects/elonkit/src/ui/empty-state/empty-state.component.html b/projects/elonkit/src/ui/empty-state/empty-state.component.html deleted file mode 100644 index d292471..0000000 --- a/projects/elonkit/src/ui/empty-state/empty-state.component.html +++ /dev/null @@ -1,21 +0,0 @@ -
- - - - -
-
- {{ heading }} -
-
{{ subheading }}
-
- -
- -
-
diff --git a/projects/elonkit/src/ui/empty-state/empty-state.component.scss b/projects/elonkit/src/ui/empty-state/empty-state.component.scss deleted file mode 100644 index 0e0868c..0000000 --- a/projects/elonkit/src/ui/empty-state/empty-state.component.scss +++ /dev/null @@ -1,45 +0,0 @@ -.es-empty-state { - max-width: 600px; - padding: 24px; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - - &__image { - margin-bottom: 12px; - - &.mat-icon { - width: 56px; - height: 56px; - display: block; - } - } - - &__text { - &__heading { - margin-bottom: 2px; - text-align: center; - - &:not(:last-child) { - margin-bottom: 2px; - } - } - - &__subheading { - text-align: center; - } - - &:not(:last-child) { - margin-bottom: 20px; - } - } - - &__children { - padding: 8px 0; - } - - .mat-stroked-button { - line-height: 46px; - } -} diff --git a/projects/elonkit/src/ui/empty-state/empty-state.component.theme.scss b/projects/elonkit/src/ui/empty-state/empty-state.component.theme.scss deleted file mode 100644 index a1d760e..0000000 --- a/projects/elonkit/src/ui/empty-state/empty-state.component.theme.scss +++ /dev/null @@ -1,22 +0,0 @@ -@mixin es-empty-state-theme($theme, $elonkit-theme) { - $mono-a: map-get($elonkit-theme, mono-a); - - .es-empty-state { - &__image { - // stylelint-disable-next-line selector-no-qualifying-type - path[data-mono-a='A150'] { - fill: mat.get-color-from-palette($mono-a, A150); - } - } - - &__text { - &__heading { - color: mat.get-color-from-palette($mono-a, A900); - } - - &__subheading { - color: mat.get-color-from-palette($mono-a, A600); - } - } - } -} diff --git a/projects/elonkit/src/ui/empty-state/empty-state.component.ts b/projects/elonkit/src/ui/empty-state/empty-state.component.ts deleted file mode 100644 index ca04f9e..0000000 --- a/projects/elonkit/src/ui/empty-state/empty-state.component.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { - Component, - ChangeDetectionStrategy, - ChangeDetectorRef, - ViewEncapsulation, - Input, - InjectionToken, - Optional, - Inject, -} from '@angular/core'; - -import { ESEmptyStateIcon } from './empty-state.types'; - -export interface ESEmptyStateDefaultOptions { - icon?: ESEmptyStateIcon; - size?: string; -} - -export const ES_EMPTY_STATE_DEFAULT_OPTIONS = new InjectionToken('ES_EMPTY_STATE_DEFAULT_OPTIONS'); - -@Component({ - selector: 'es-empty-state', - templateUrl: './empty-state.component.html', - styleUrls: ['./empty-state.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class ESEmptyStateComponent { - private _icon: ESEmptyStateIcon; - - /** - * Icon to diaplsy. - */ - @Input() - public get icon(): ESEmptyStateIcon { - return this._icon; - } - public set icon(value: ESEmptyStateIcon | undefined) { - this._icon = value || this.defaultOptions?.icon || 'box'; - } - - /** - * Path to image to display instead of the prebuilt icon. - */ - @Input() public src?: string; - - /** - * Heading text. - */ - @Input() public heading: string; - - /** - * Subheading text. - */ - @Input() public subheading: string; - - private _size: string; - - /** - * Size of epty-state. - */ - @Input() - public get size(): string { - return this._size; - } - public set size(value: string | undefined) { - this._size = value || this.defaultOptions?.size || 'mediumn'; - } - - /** - * @internal - * @ignore - */ - constructor( - /** - * @internal - */ - public changeDetector: ChangeDetectorRef, - /** - * @internal - */ - @Optional() - @Inject(ES_EMPTY_STATE_DEFAULT_OPTIONS) - private defaultOptions: ESEmptyStateDefaultOptions - ) { - this.icon = this.defaultOptions?.icon; - this.size = this.defaultOptions?.size; - } -} diff --git a/projects/elonkit/src/ui/empty-state/empty-state.module.ts b/projects/elonkit/src/ui/empty-state/empty-state.module.ts deleted file mode 100644 index e6a292c..0000000 --- a/projects/elonkit/src/ui/empty-state/empty-state.module.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; - -import { MatIconModule, MatIconRegistry } from '@angular/material/icon'; - -import { ESEmptyStateComponent } from './empty-state.component'; - -@NgModule({ - declarations: [ESEmptyStateComponent], - imports: [CommonModule, MatIconModule], - exports: [ESEmptyStateComponent], - providers: [MatIconRegistry], -}) -export class ESEmptyStateModule {} diff --git a/projects/elonkit/src/ui/empty-state/empty-state.types.ts b/projects/elonkit/src/ui/empty-state/empty-state.types.ts deleted file mode 100644 index c8b87d0..0000000 --- a/projects/elonkit/src/ui/empty-state/empty-state.types.ts +++ /dev/null @@ -1,17 +0,0 @@ -export type ESEmptyStateIcon = - | 'bar-chart' - | 'bell' - | 'box' - | 'camera' - | 'cart' - | 'chat' - | 'face' - | 'file' - | 'filter' - | 'image' - | 'lock' - | 'pie-chart' - | 'search' - | 'smile' - | 'wi-fi' - | 'wi-fi-off'; diff --git a/projects/elonkit/src/ui/empty-state/index.ts b/projects/elonkit/src/ui/empty-state/index.ts deleted file mode 100644 index 7e1a213..0000000 --- a/projects/elonkit/src/ui/empty-state/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './public-api'; diff --git a/projects/elonkit/src/ui/empty-state/public-api.ts b/projects/elonkit/src/ui/empty-state/public-api.ts deleted file mode 100644 index fa78c7d..0000000 --- a/projects/elonkit/src/ui/empty-state/public-api.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { ESEmptyStateModule } from './empty-state.module'; -export { ESEmptyStateComponent, ESEmptyStateDefaultOptions, ES_EMPTY_STATE_DEFAULT_OPTIONS } from './empty-state.component'; -export { ESEmptyStateIcon } from './empty-state.types'; diff --git a/projects/elonkit/src/ui/icons/demo-wrapper/demo-wrapper.component.ts b/projects/elonkit/src/ui/icons/demo-wrapper/demo-wrapper.component.ts index e264281..b6b1b81 100644 --- a/projects/elonkit/src/ui/icons/demo-wrapper/demo-wrapper.component.ts +++ b/projects/elonkit/src/ui/icons/demo-wrapper/demo-wrapper.component.ts @@ -1,4 +1,5 @@ import { Component, Input } from '@angular/core'; + import { ES_SVG_ICONS } from '../index'; @Component({ diff --git a/projects/elonkit/src/ui/icons/demo-wrapper/demo-wrapper.module.ts b/projects/elonkit/src/ui/icons/demo-wrapper/demo-wrapper.module.ts index 7a1b824..f8758a7 100644 --- a/projects/elonkit/src/ui/icons/demo-wrapper/demo-wrapper.module.ts +++ b/projects/elonkit/src/ui/icons/demo-wrapper/demo-wrapper.module.ts @@ -1,9 +1,11 @@ -import { NgModule } from '@angular/core'; -import { DemoWrapperComponent } from './demo-wrapper.component'; import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; + import { MatIconModule, MatIconRegistry } from '@angular/material/icon'; import { MatTooltipModule } from '@angular/material/tooltip'; +import { DemoWrapperComponent } from './demo-wrapper.component'; + @NgModule({ imports: [CommonModule, MatIconModule, MatTooltipModule], exports: [DemoWrapperComponent], diff --git a/projects/elonkit/src/ui/icons/demo-wrapper/index.ts b/projects/elonkit/src/ui/icons/demo-wrapper/index.ts index 9c1a6b0..e7dba32 100644 --- a/projects/elonkit/src/ui/icons/demo-wrapper/index.ts +++ b/projects/elonkit/src/ui/icons/demo-wrapper/index.ts @@ -1,2 +1,2 @@ -export { DemoWrapperModule } from './demo-wrapper.module'; export { DemoWrapperComponent } from './demo-wrapper.component'; +export { DemoWrapperModule } from './demo-wrapper.module'; diff --git a/projects/elonkit/src/ui/icons/icons.service.ts b/projects/elonkit/src/ui/icons/icons.service.ts index 3a24e6a..05970b2 100644 --- a/projects/elonkit/src/ui/icons/icons.service.ts +++ b/projects/elonkit/src/ui/icons/icons.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; +import { DomSanitizer } from '@angular/platform-browser'; import { MatIconRegistry } from '@angular/material/icon'; -import { DomSanitizer } from '@angular/platform-browser'; export const ES_SVG_ICONS: { [key: string]: any } = { 'es-empty-state': [ diff --git a/projects/elonkit/src/ui/icons/icons.stories.ts b/projects/elonkit/src/ui/icons/icons.stories.ts index c6c9602..aecf8b3 100644 --- a/projects/elonkit/src/ui/icons/icons.stories.ts +++ b/projects/elonkit/src/ui/icons/icons.stories.ts @@ -1,9 +1,10 @@ -import type { Meta, StoryObj } from '@storybook/angular'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { CoreModule } from '~storybook/core.module'; import { HttpClientModule } from '@angular/common/http'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { DemoWrapperModule, DemoWrapperComponent } from './demo-wrapper'; +import { DemoWrapperComponent, DemoWrapperModule } from './demo-wrapper'; + +import type { Meta, StoryObj } from '@storybook/angular'; +import { CoreModule } from '~storybook/core.module'; const meta: Meta = { component: DemoWrapperModule, diff --git a/projects/elonkit/src/ui/icons/public-api.ts b/projects/elonkit/src/ui/icons/public-api.ts index ec9084f..d00b77f 100644 --- a/projects/elonkit/src/ui/icons/public-api.ts +++ b/projects/elonkit/src/ui/icons/public-api.ts @@ -1 +1 @@ -export { ESIconsService, ES_SVG_ICONS } from './icons.service'; +export { ES_SVG_ICONS, ESIconsService } from './icons.service'; diff --git a/projects/elonkit/src/ui/inline-form-field/__specs__/inline-form-field.spec.ts b/projects/elonkit/src/ui/inline-form-field/__specs__/inline-form-field.spec.ts deleted file mode 100644 index f2b0479..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__specs__/inline-form-field.spec.ts +++ /dev/null @@ -1,284 +0,0 @@ -import { ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core'; -import { fakeAsync, tick } from '@angular/core/testing'; - -import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; - -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; - -import { fireEvent, render, screen } from '@testing-library/angular'; - -import { ESInlineFormFieldComponent, ESInlineFormFieldModule } from '..'; -import { ESLocaleService, ru } from '../../locale'; - -const TEXT_HELLO = 'Hello'; -const TEXT_HELLO_WORLD = 'Hello World'; -const TEXT_ERROR_REQUIRED = 'Required'; - -const TIMEOUT = 100; - -@Component({ - template: ` - - - - - - `, -}) -class InlineFormFieldWrapperComponent { - @Input() public manualSave = false; - @Output() public save = new EventEmitter(); - - public text = TEXT_HELLO; - - public onSave(event) { - this.save.emit(event); - } -} - -@Component({ - template: ` -
- - - - ${TEXT_ERROR_REQUIRED} - - -
- `, -}) -class InlineFormFieldValidationWrapperComponent { - public form = new FormGroup({ - text: new FormControl(TEXT_HELLO, [Validators.required]), - }); -} - -@Component({ - template: ` -
- - - - ${TEXT_ERROR_REQUIRED} - - -
- `, -}) -class InlineFormFieldServerValidationWrapperComponent { - public form = new FormGroup({ - text: new FormControl(TEXT_HELLO), - }); - - constructor(public changeDetector: ChangeDetectorRef) {} - - public onSave(inlineFormField: ESInlineFormFieldComponent) { - setTimeout(() => { - if (this.form.get('text').value.length) { - inlineFormField.setHidden(true); - } else { - this.form.get('text').setErrors({ required: true }); - } - this.changeDetector.detectChanges(); - }, TIMEOUT); - } -} - -describe('InlineFormField', () => { - it('Should update text', async () => { - const component = await render(InlineFormFieldWrapperComponent, { - imports: [FormsModule, MatFormFieldModule, MatInputModule, ESInlineFormFieldModule], - }); - - expect(screen.getByText(TEXT_HELLO)).toBeInTheDocument(); - - const buttonEdit = screen.getByLabelText('Edit'); - fireEvent.click(buttonEdit); - - const input = screen.getByPlaceholderText('Input'); - fireEvent.input(input, { target: { value: TEXT_HELLO_WORLD } }); - - const buttonSave = screen.getByLabelText('Save'); - fireEvent.click(buttonSave); - - expect(component.fixture.componentInstance.text).toBe(TEXT_HELLO_WORLD); - expect(screen.getByText(TEXT_HELLO_WORLD)).toBeInTheDocument(); - }); - - it('Should reset text', async () => { - const component = await render(InlineFormFieldWrapperComponent, { - imports: [FormsModule, MatFormFieldModule, MatInputModule, ESInlineFormFieldModule], - }); - - expect(screen.getByText(TEXT_HELLO)).toBeInTheDocument(); - - const buttonEdit = screen.getByLabelText('Edit'); - fireEvent.click(buttonEdit); - - const input = screen.getByPlaceholderText('Input'); - fireEvent.input(input, { target: { value: TEXT_HELLO_WORLD } }); - - const buttonCancel = screen.getByLabelText('Cancel'); - fireEvent.click(buttonCancel); - - expect(component.fixture.componentInstance.text).toBe(TEXT_HELLO); - expect(screen.getByText(TEXT_HELLO)).toBeInTheDocument(); - }); - - it('Should emit events', async () => { - const onEdit = jest.fn(); - const onSave = jest.fn(); - const onCancel = jest.fn(); - - const component = await render(ESInlineFormFieldComponent, { - componentProperties: { - edit: { - emit: onEdit, - } as any, - save: { - emit: onSave, - } as any, - cancel: { - emit: onCancel, - } as any, - }, - imports: [ESInlineFormFieldModule], - excludeComponentDeclaration: true, - }); - - fireEvent.click(screen.getByLabelText('Edit')); - fireEvent.click(screen.getByLabelText('Save')); - fireEvent.click(screen.getByLabelText('Edit')); - fireEvent.click(screen.getByLabelText('Cancel')); - - expect(onEdit).toBeCalledTimes(2); - expect(onEdit).toBeCalledWith(component.fixture.componentInstance); - - expect(onSave).toBeCalledTimes(1); - expect(onSave).toBeCalledWith(component.fixture.componentInstance); - - expect(onCancel).toBeCalledTimes(1); - expect(onCancel).toBeCalledWith(component.fixture.componentInstance); - }); - - it('Should change locale', async () => { - const localeService = new ESLocaleService(); - localeService.register('ru', ru); - localeService.use('ru'); - - await render(ESInlineFormFieldComponent, { - imports: [ESInlineFormFieldModule], - providers: [{ provide: ESLocaleService, useValue: localeService }], - excludeComponentDeclaration: true, - }); - - const editButton = screen.getByLabelText(ru.inlineFormField.labelEdit); - expect(editButton).toBeInTheDocument(); - fireEvent.click(editButton); - - expect(screen.getByLabelText(ru.inlineFormField.labelSave)).toBeInTheDocument(); - expect(screen.getByLabelText(ru.inlineFormField.labelCancel)).toBeInTheDocument(); - }); - - it('Should accept typography class', async () => { - const component = await render(ESInlineFormFieldComponent, { - imports: [ESInlineFormFieldModule], - excludeComponentDeclaration: true, - }); - - expect(screen.getByTestId('root')).toHaveClass('es-body-200'); - - const typography = 'es-body-100'; - - component.fixture.componentInstance.typography = typography; - component.fixture.componentInstance.changeDetector.detectChanges(); - - expect(screen.getByTestId('root')).toHaveClass(typography); - }); - - it('Should disable default save behaviour', async () => { - const onSave = jest.fn(); - - await render(InlineFormFieldWrapperComponent, { - imports: [FormsModule, MatFormFieldModule, MatInputModule, ESInlineFormFieldModule], - componentProperties: { - manualSave: true, - save: { - emit: onSave, - } as any, - }, - }); - - expect(screen.getByText(TEXT_HELLO)).toBeInTheDocument(); - - const buttonEdit = screen.getByLabelText('Edit'); - fireEvent.click(buttonEdit); - - const input = screen.getByPlaceholderText('Input'); - fireEvent.input(input, { target: { value: TEXT_HELLO_WORLD } }); - - const buttonSave = screen.getByLabelText('Save'); - fireEvent.click(buttonSave); - - expect(screen.getByDisplayValue(TEXT_HELLO_WORLD)).toBeInTheDocument(); - expect(onSave).toBeCalled(); - }); - - it('Should prevent save with validation errors', async () => { - await render(InlineFormFieldValidationWrapperComponent, { - imports: [ReactiveFormsModule, MatFormFieldModule, MatInputModule, ESInlineFormFieldModule], - }); - - expect(screen.getByText(TEXT_HELLO)).toBeInTheDocument(); - - const buttonEdit = screen.getByLabelText('Edit'); - fireEvent.click(buttonEdit); - - const input = screen.getByPlaceholderText('Input'); - fireEvent.input(input, { target: { value: '' } }); - - const buttonSave = screen.getByLabelText('Save'); - fireEvent.click(buttonSave); - - expect(screen.getByText(TEXT_ERROR_REQUIRED)).toBeInTheDocument(); - - fireEvent.input(input, { target: { value: TEXT_HELLO_WORLD } }); - fireEvent.click(buttonSave); - - expect(screen.queryByText(TEXT_ERROR_REQUIRED)).toBeNull(); - expect(screen.getByText(TEXT_HELLO_WORLD)).toBeInTheDocument(); - }); - - it('Should work with server-side validation', fakeAsync(async () => { - await render(InlineFormFieldServerValidationWrapperComponent, { - imports: [ReactiveFormsModule, MatFormFieldModule, MatInputModule, ESInlineFormFieldModule], - }); - - expect(screen.getByText(TEXT_HELLO)).toBeInTheDocument(); - - const buttonEdit = screen.getByLabelText('Edit'); - fireEvent.click(buttonEdit); - - const input = screen.getByPlaceholderText('Input'); - fireEvent.input(input, { target: { value: '' } }); - - const buttonSave = screen.getByLabelText('Save'); - fireEvent.click(buttonSave); - - expect(screen.queryByText(TEXT_ERROR_REQUIRED)).toBeNull(); - - tick(TIMEOUT); - - expect(screen.getByText(TEXT_ERROR_REQUIRED)).toBeInTheDocument(); - - fireEvent.input(input, { target: { value: TEXT_HELLO_WORLD } }); - fireEvent.click(buttonSave); - - tick(TIMEOUT); - - expect(screen.queryByText(TEXT_ERROR_REQUIRED)).toBeNull(); - expect(screen.getByText(TEXT_HELLO_WORLD)).toBeInTheDocument(); - })); -}); diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/index.ts b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/index.ts deleted file mode 100644 index 47bd58d..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { InlineFormFieldStoryBasicModule } from './inline-form-field-story-basic.module'; -export { InlineFormFieldStoryBasicComponent } from './inline-form-field-story-basic.component'; -export { INLINE_FORM_FIELD_STORY_BASIC_SOURCE } from './inline-form-field-story-basic.source'; diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/inline-form-field-story-basic.component.html b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/inline-form-field-story-basic.component.html deleted file mode 100644 index 5cb46a7..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/inline-form-field-story-basic.component.html +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/inline-form-field-story-basic.component.ts b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/inline-form-field-story-basic.component.ts deleted file mode 100644 index 2b1fa5f..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/inline-form-field-story-basic.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component, ChangeDetectionStrategy } from '@angular/core'; - -@Component({ - selector: 'es-inline-form-field-basic', - templateUrl: './inline-form-field-story-basic.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class InlineFormFieldStoryBasicComponent { - public text = 'Hello World'; -} diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/inline-form-field-story-basic.module.ts b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/inline-form-field-story-basic.module.ts deleted file mode 100644 index ccac7f7..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/inline-form-field-story-basic.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; - -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; - -import { InlineFormFieldStoryBasicComponent } from './inline-form-field-story-basic.component'; - -import { ESInlineFormFieldModule } from '../..'; - -@NgModule({ - declarations: [InlineFormFieldStoryBasicComponent], - imports: [CommonModule, FormsModule, MatFormFieldModule, MatInputModule, ESInlineFormFieldModule], - exports: [InlineFormFieldStoryBasicComponent], -}) -export class InlineFormFieldStoryBasicModule {} diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/inline-form-field-story-basic.source.ts b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/inline-form-field-story-basic.source.ts deleted file mode 100644 index f80a83f..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-basic/inline-form-field-story-basic.source.ts +++ /dev/null @@ -1,9 +0,0 @@ -export const INLINE_FORM_FIELD_STORY_BASIC_SOURCE = { - html: ` - - - - - - `, -}; diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/index.ts b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/index.ts deleted file mode 100644 index f127a46..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { InlineFormFieldStoryCompositionModule } from './inline-form-field-story-composition.module'; -export { InlineFormFieldStoryCompositionComponent } from './inline-form-field-story-composition.component'; -export { INLINE_FORM_FIELD_STORY_COMPOSITION_SOURCE } from './inline-form-field-story-composition.source'; diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.component.html b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.component.html deleted file mode 100644 index 3613c9a..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.component.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - Apple - Grape - Pineapple - - - - - - - - This is a hint - - diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.component.scss b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.component.scss deleted file mode 100644 index 76450fd..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.component.scss +++ /dev/null @@ -1,4 +0,0 @@ -.inline-form-field { - display: block; - margin-bottom: 16px; -} diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.component.ts b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.component.ts deleted file mode 100644 index fa55d90..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core'; - -@Component({ - selector: 'es-inline-form-field-composition', - templateUrl: './inline-form-field-story-composition.component.html', - styleUrls: ['./inline-form-field-story-composition.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class InlineFormFieldStoryCompositionComponent { - public date = new Date(); - public text = 'Prefix & Suffix'; - public select = 'Grape'; - public hint = 'Input with hint'; -} diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.module.ts b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.module.ts deleted file mode 100644 index cf8b984..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.module.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; - -import { MatDatepickerModule } from '@angular/material/datepicker'; -import { MatNativeDateModule } from '@angular/material/core'; - -import { MatButtonModule } from '@angular/material/button'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatIconModule } from '@angular/material/icon'; -import { MatInputModule } from '@angular/material/input'; -import { MatSelectModule } from '@angular/material/select'; - -import { InlineFormFieldStoryCompositionComponent } from './inline-form-field-story-composition.component'; - -import { ESInlineFormFieldModule } from '../..'; - -@NgModule({ - declarations: [InlineFormFieldStoryCompositionComponent], - imports: [ - CommonModule, - FormsModule, - - MatDatepickerModule, - MatNativeDateModule, - - MatButtonModule, - MatFormFieldModule, - MatIconModule, - MatInputModule, - MatSelectModule, - - ESInlineFormFieldModule, - ], - exports: [InlineFormFieldStoryCompositionComponent], -}) -export class InlineFormFieldStoryCompositionModule {} diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.source.ts b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.source.ts deleted file mode 100644 index 19893c9..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-composition/inline-form-field-story-composition.source.ts +++ /dev/null @@ -1,46 +0,0 @@ -export const INLINE_FORM_FIELD_STORY_COMPOSITION_SOURCE = { - html: ` - - - - - - - - - - - - - - - - - - - - - Apple - - - Grape - - - Pineapple - - - - - - - - - This is a hint - - - `, -}; diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/index.ts b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/index.ts deleted file mode 100644 index 26ca562..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { InlineFormFieldStoryTypographyModule } from './inline-form-field-story-typography.module'; -export { InlineFormFieldStoryTypographyComponent } from './inline-form-field-story-typography.component'; -export { INLINE_FORM_FIELD_STORY_TYPOGRAPHY_SOURCE } from './inline-form-field-story-typography.source'; diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/inline-form-field-story-typography.component.html b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/inline-form-field-story-typography.component.html deleted file mode 100644 index 83b1fc3..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/inline-form-field-story-typography.component.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/inline-form-field-story-typography.component.ts b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/inline-form-field-story-typography.component.ts deleted file mode 100644 index 1e25c65..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/inline-form-field-story-typography.component.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; - -const TEXT = 'Hello World'; - -const TEXT_MMULTILINE = `Hello World -Good Morning World`; - -@Component({ - selector: 'es-inline-form-field-typography', - templateUrl: './inline-form-field-story-typography.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class InlineFormFieldStoryTypographyComponent { - @Input() public typography: any; - - public text = TEXT; - public textMultiline = TEXT_MMULTILINE; -} diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/inline-form-field-story-typography.module.ts b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/inline-form-field-story-typography.module.ts deleted file mode 100644 index 9d50c46..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/inline-form-field-story-typography.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; - -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; - -import { InlineFormFieldStoryTypographyComponent } from './inline-form-field-story-typography.component'; - -import { ESInlineFormFieldModule } from '../..'; - -@NgModule({ - declarations: [InlineFormFieldStoryTypographyComponent], - imports: [CommonModule, FormsModule, MatFormFieldModule, MatInputModule, ESInlineFormFieldModule], - exports: [InlineFormFieldStoryTypographyComponent], -}) -export class InlineFormFieldStoryTypographyModule {} diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/inline-form-field-story-typography.source.ts b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/inline-form-field-story-typography.source.ts deleted file mode 100644 index 58b3c15..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-typography/inline-form-field-story-typography.source.ts +++ /dev/null @@ -1,9 +0,0 @@ -export const INLINE_FORM_FIELD_STORY_TYPOGRAPHY_SOURCE = { - html: ` - - - - - - `, -}; diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/index.ts b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/index.ts deleted file mode 100644 index 9d611e6..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { InlineFormFieldStoryValidationModule } from './inline-form-field-story-validation.module'; -export { InlineFormFieldStoryValidationComponent } from './inline-form-field-story-validation.component'; -export { INLINE_FORM_FIELD_STORY_VALIDATION_SOURCE } from './inline-form-field-story-validation.source'; diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.component.html b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.component.html deleted file mode 100644 index 76f4e2c..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.component.html +++ /dev/null @@ -1,15 +0,0 @@ -
- - - - This field is required - - - - - - - This field is required - - -
diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.component.scss b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.component.scss deleted file mode 100644 index 76450fd..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.component.scss +++ /dev/null @@ -1,4 +0,0 @@ -.inline-form-field { - display: block; - margin-bottom: 16px; -} diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.component.ts b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.component.ts deleted file mode 100644 index 4c86988..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.component.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Component, ChangeDetectionStrategy, ChangeDetectorRef, ViewEncapsulation } from '@angular/core'; -import { FormBuilder, FormGroup, FormControl, Validators } from '@angular/forms'; - -import { of, throwError } from 'rxjs'; -import { delay, switchMap } from 'rxjs/operators'; - -import { ESInlineFormFieldComponent } from '../..'; - -const save = (value: string) => - of(value).pipe( - delay(100), - switchMap((v) => { - if (v.length) { - return of(v); - } - return throwError({ required: true }); - }) - ); - -@Component({ - selector: 'es-inline-form-field-validation', - templateUrl: './inline-form-field-story-validation.component.html', - styleUrls: ['./inline-form-field-story-validation.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class InlineFormFieldStoryValidationComponent { - public form: FormGroup; - - constructor( - private changeDetector: ChangeDetectorRef, - private formBuilder: FormBuilder - ) { - this.form = this.formBuilder.group({ - text: ['Hello World', [Validators.required]], - server: 'Hello Server Side Validation', - }); - } - - public onSave(inlineFormField: ESInlineFormFieldComponent) { - const value: string = this.form.get('server')?.value; - - save(value).subscribe( - () => { - inlineFormField.setHidden(true); - }, - (errors) => { - this.form.get('server')?.setErrors(errors); - this.changeDetector.detectChanges(); - } - ); - } -} diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.module.ts b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.module.ts deleted file mode 100644 index a958efd..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { ReactiveFormsModule } from '@angular/forms'; - -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; - -import { InlineFormFieldStoryValidationComponent } from './inline-form-field-story-validation.component'; - -import { ESInlineFormFieldModule } from '../..'; - -@NgModule({ - declarations: [InlineFormFieldStoryValidationComponent], - imports: [CommonModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, ESInlineFormFieldModule], - exports: [InlineFormFieldStoryValidationComponent], -}) -export class InlineFormFieldStoryValidationModule {} diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.source.ts b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.source.ts deleted file mode 100644 index 00add5a..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field-story-validation/inline-form-field-story-validation.source.ts +++ /dev/null @@ -1,56 +0,0 @@ -export const INLINE_FORM_FIELD_STORY_VALIDATION_SOURCE = { - ts: ` - @Component({ - ... - }) - export class InlineFormFieldStoryValidationComponent { - form: FormGroup; - - constructor(private changeDetector: ChangeDetectorRef, private formBuilder: FormBuilder) { - this.form = this.formBuilder.group({ - text: ['Hello World', [Validators.required]], - server: 'Hello Server Side Validation' - }); - } - - onSave(inlineFormField: ESInlineFormFieldComponent) { - const value: string = this.form.get('server').value; - - save(value).subscribe( - () => { - inlineFormField.setHidden(true); - }, - errors => { - this.form.get('server').setErrors(errors); - this.changeDetector.detectChanges(); - } - ); - } - } - `, - html: ` -
- - - - - This field is required - - - - - - - - - This field is required - - - -
- `, -}; diff --git a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field.stories.mdx b/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field.stories.mdx deleted file mode 100644 index 602b03c..0000000 --- a/projects/elonkit/src/ui/inline-form-field/__stories__/inline-form-field.stories.mdx +++ /dev/null @@ -1,115 +0,0 @@ -import { Meta, Story, ArgsTable } from '@storybook/addon-docs'; -import { Canvas } from '~storybook/components'; - -import { action } from '@storybook/addon-actions'; - -import { ESInlineFormFieldComponent } from '..'; - -import { - InlineFormFieldStoryBasicModule, - InlineFormFieldStoryBasicComponent, - INLINE_FORM_FIELD_STORY_BASIC_SOURCE, -} from './inline-form-field-story-basic'; - -import { - InlineFormFieldStoryTypographyModule, - InlineFormFieldStoryTypographyComponent, - INLINE_FORM_FIELD_STORY_TYPOGRAPHY_SOURCE, -} from './inline-form-field-story-typography'; - -import { - InlineFormFieldStoryCompositionModule, - InlineFormFieldStoryCompositionComponent, - INLINE_FORM_FIELD_STORY_COMPOSITION_SOURCE, -} from './inline-form-field-story-composition'; - -import { - InlineFormFieldStoryValidationModule, - InlineFormFieldStoryValidationComponent, - INLINE_FORM_FIELD_STORY_VALIDATION_SOURCE, -} from './inline-form-field-story-validation'; - - - -# Inline Form Field - -This component allows inline switching between display value and input. - -## Demos - - - - {{ - component: InlineFormFieldStoryBasicComponent, - moduleMetadata: { - imports: [InlineFormFieldStoryBasicModule], - }, - }} - - - -We can use `typography` input in order to change text presentation. - - - - {((args) => ({ - component: InlineFormFieldStoryTypographyComponent, - moduleMetadata: { - imports: [InlineFormFieldStoryTypographyModule], - }, - props: { - ...args, - }, - })).bind({})} - - - -This component is compatible with any\* Angular Material form field feature. - - - - {{ - component: InlineFormFieldStoryCompositionComponent, - moduleMetadata: { - imports: [InlineFormFieldStoryCompositionModule], - }, - }} - - - -Synchronous validations for template-driven and reactive forms are supported out of the box. -If there are any server-side validations you should take advantage of `manualSave` input. - - - - {{ - component: InlineFormFieldStoryValidationComponent, - moduleMetadata: { - imports: [InlineFormFieldStoryValidationModule], - }, - }} - - - -## API - - - -## Constants - -Injection token that can be used to configure the default options for all components within an app. - -```ts -import { ES_INLINE_FORM_FIELD_DEFAULT_OPTIONS } from '@elonkit/angular/ui/inline-form-field'; - -@NgModule({ - providers: [ - { - provide: ES_INLINE_FORM_FIELD_DEFAULT_OPTIONS, - useValue: { - typography: 'es-body-200' - } - } - ] -}) -``` diff --git a/projects/elonkit/src/ui/inline-form-field/index.ts b/projects/elonkit/src/ui/inline-form-field/index.ts deleted file mode 100644 index 7e1a213..0000000 --- a/projects/elonkit/src/ui/inline-form-field/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './public-api'; diff --git a/projects/elonkit/src/ui/inline-form-field/inline-form-field.component.html b/projects/elonkit/src/ui/inline-form-field/inline-form-field.component.html deleted file mode 100644 index dcaac7c..0000000 --- a/projects/elonkit/src/ui/inline-form-field/inline-form-field.component.html +++ /dev/null @@ -1,28 +0,0 @@ -
-
-
{{ text }}
- -
- -
-
- -
- - -
-
- -
-
- -
-
-
-
diff --git a/projects/elonkit/src/ui/inline-form-field/inline-form-field.component.scss b/projects/elonkit/src/ui/inline-form-field/inline-form-field.component.scss deleted file mode 100644 index 03afea6..0000000 --- a/projects/elonkit/src/ui/inline-form-field/inline-form-field.component.scss +++ /dev/null @@ -1,151 +0,0 @@ -.es-inline-form-field { - width: 100%; - margin: 0; - - &__preview, - &__input { - display: flex; - align-items: flex-start; - } - - &__preview { - &:hover { - /* stylelint-disable-next-line */ - .es-inline-form-field__button_edit .mat-icon-button { - opacity: 1; - } - } - } - - &__text { - line-height: normal; - padding: 5px 0; - white-space: pre-wrap; - } - - &__input { - position: relative; - - /* stylelint-disable selector-max-compound-selectors, selector-no-qualifying-type, indentation */ - - .mat-form-field { - font-weight: inherit; - line-height: normal; - width: 100%; - } - - .mat-form-field-infix { - border-top: 0; - padding: 5px 0; - } - - .mat-form-field-wrapper { - padding-bottom: 0; - padding-right: 64px; - } - - .mat-form-field-underline { - bottom: 0; - } - - .mat-form-field-appearance-standard .mat-form-field-flex { - padding-top: 0; - } - - .mat-input-element { - margin-top: 0; - } - - textarea.mat-input-element { - padding: 0; - margin: 0; - overflow: hidden; - } - - .mat-form-field-subscript-wrapper { - position: absolute; - top: 100%; - } - - .mat-form-field-flex { - align-items: center; - } - - .mat-form-field:not(.mat-form-field-appearance-legacy) { - .mat-form-field-prefix, - .mat-form-field-suffix { - .mat-icon-button { - width: 24px; - height: 24px; - } - - .mat-datepicker-toggle-default-icon { - width: 18px; - } - - .mat-icon { - font-size: 18px; - } - } - } - - .mat-form-field-appearance-standard.mat-form-field-has-label .mat-select:not(.mat-select-empty) .mat-select-arrow-wrapper { - transform: none; - } - } - - &__buttons { - display: flex; - position: absolute; - right: 0; - } - - &__button { - margin-left: 8px; - position: relative; - - &::after { - content: '\a0'; - width: 24px; - padding: 5px 0; - display: block; - font-size: inherit; - line-height: normal; - } - - .mat-icon-button { - font-size: inherit; - width: 24px; - height: 24px; - line-height: 24px; - position: absolute; - top: 50%; - transform: translateY(-50%); - - .mat-button-wrapper { - height: 24px; - display: flex; - align-items: center; - } - } - - .mat-icon { - font-size: 22px; - } - - &_edit { - .mat-icon-button { - opacity: 0; - transition: 200ms; - - &:focus { - opacity: 1; - } - } - - .mat-icon { - font-size: 18px; - } - } - } -} diff --git a/projects/elonkit/src/ui/inline-form-field/inline-form-field.component.theme.scss b/projects/elonkit/src/ui/inline-form-field/inline-form-field.component.theme.scss deleted file mode 100644 index 952a821..0000000 --- a/projects/elonkit/src/ui/inline-form-field/inline-form-field.component.theme.scss +++ /dev/null @@ -1,16 +0,0 @@ -@mixin es-inline-form-field-theme($theme, $elonkit-theme) { - .es-inline-form-field { - &__button { - .mat-icon { - color: mat.get-color-from-palette(map-get($elonkit-theme, mono-a), A500); - } - - // stylelint-disable-next-line - &.es-inline-form-field__button_save { - .mat-icon { - color: mat.get-color-from-palette(map-get($elonkit-theme, positive)); - } - } - } - } -} diff --git a/projects/elonkit/src/ui/inline-form-field/inline-form-field.component.ts b/projects/elonkit/src/ui/inline-form-field/inline-form-field.component.ts deleted file mode 100644 index 4735aa6..0000000 --- a/projects/elonkit/src/ui/inline-form-field/inline-form-field.component.ts +++ /dev/null @@ -1,210 +0,0 @@ -import { - Component, - ChangeDetectionStrategy, - ChangeDetectorRef, - ViewEncapsulation, - Input, - Output, - EventEmitter, - ContentChild, - InjectionToken, - Optional, - Inject, -} from '@angular/core'; - -import { FormControl, FormControlName, NgModel } from '@angular/forms'; - -import { MAT_FORM_FIELD_DEFAULT_OPTIONS, MatFormField } from '@angular/material/form-field'; - -import { Observable } from 'rxjs'; - -import { ESLocaleService, ESLocale } from '../locale'; - -export interface ESInlineFormFieldDefaultOptions { - typography?: string; -} - -const DEFAULT_TYPOGRAPHY = 'es-body-200'; - -export const ES_INLINE_FORM_FIELD_DEFAULT_OPTIONS = new InjectionToken( - 'ES_INLINE_FORM_FIELD_DEFAULT_OPTIONS' -); - -@Component({ - selector: 'es-inline-form-field', - templateUrl: './inline-form-field.component.html', - styleUrls: ['./inline-form-field.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, - providers: [ - { - provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, - useValue: { - appearance: 'standard', - floatLabel: 'never', - }, - }, - ], -}) -export class ESInlineFormFieldComponent { - private _typography: string; - - /** - * Class applied to text. - */ - @Input() - public get typography(): string { - return this._typography; - } - public set typography(value: string) { - this._typography = value || (this.defaultOptions && this.defaultOptions.typography) || DEFAULT_TYPOGRAPHY; - } - - /** - * Text to display. - */ - @Input() public text: string; - - /** - * Disable default behaviour of "save" button and only emit event. - */ - @Input() public manualSave = false; - - /** - * Event emitted when user clicks "edit" button. - */ - @Output() public edit = new EventEmitter(); - - /** - * Event emitted when user clicks "save" button. - */ - @Output() public save = new EventEmitter(); - - /** - * Event emitted when user clicks "cancel" button. - */ - @Output() public cancel = new EventEmitter(); - - @ContentChild(MatFormField) private formField: MatFormField; - - @ContentChild(NgModel) private ngModel: NgModel; - @ContentChild(FormControl) private formControl: FormControl; - @ContentChild(FormControlName) private formControlName: FormControlName; - - /** - * @internal - * @ignore - */ - public isHidden = true; - - /** - * @internal - * @ignore - */ - public locale$: Observable; - - private previousValue: any; - - /** - * @internal - * @ignore - */ - constructor( - /** - * @internal - */ - public changeDetector: ChangeDetectorRef, - /** - * @internal - */ - public localeService: ESLocaleService, - /** - * @internal - */ - @Optional() - @Inject(ES_INLINE_FORM_FIELD_DEFAULT_OPTIONS) - private defaultOptions: ESInlineFormFieldDefaultOptions - ) { - this.locale$ = this.localeService.locale(); - - this.typography = (defaultOptions && defaultOptions.typography) || DEFAULT_TYPOGRAPHY; - } - - private getControl(): FormControl | null { - if (this.formControl) { - return this.formControl; - } - if (this.formControlName) { - return this.formControlName.control; - } - if (this.ngModel) { - return this.ngModel.control; - } - return null; - } - - /** - * Use this method to manually switch between display value and input. - */ - public setHidden(isHidden: boolean) { - this.isHidden = isHidden; - this.changeDetector.detectChanges(); - } - - /** - * @internal - * @ignore - */ - public onEdit() { - const control = this.getControl(); - if (control) { - this.previousValue = control.value; - } - - this.edit.emit(this); - this.isHidden = false; - if (this.formField) { - const element = this.formField._elementRef.nativeElement as HTMLElement; - const input = element.querySelector('input') || element.querySelector('textarea'); - - if (input) { - setTimeout(() => { - input.focus(); - }); - } - } - } - - /** - * @internal - * @ignore - */ - public onSave() { - if (this.manualSave) { - this.save.emit(this); - return; - } - - const control = this.getControl(); - if (control && control.invalid) { - return; - } - - this.save.emit(this); - this.isHidden = true; - } - - /** - * @internal - * @ignore - */ - public onCancel() { - const control = this.getControl(); - if (control) { - control.setValue(this.previousValue); - } - - this.cancel.emit(this); - this.isHidden = true; - } -} diff --git a/projects/elonkit/src/ui/inline-form-field/inline-form-field.module.ts b/projects/elonkit/src/ui/inline-form-field/inline-form-field.module.ts deleted file mode 100644 index d612663..0000000 --- a/projects/elonkit/src/ui/inline-form-field/inline-form-field.module.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; - -import { MatButtonModule } from '@angular/material/button'; -import { MatIconModule } from '@angular/material/icon'; - -import { ESInlineFormFieldComponent } from './inline-form-field.component'; - -@NgModule({ - declarations: [ESInlineFormFieldComponent], - imports: [CommonModule, MatButtonModule, MatIconModule], - exports: [ESInlineFormFieldComponent], -}) -export class ESInlineFormFieldModule {} diff --git a/projects/elonkit/src/ui/inline-form-field/public-api.ts b/projects/elonkit/src/ui/inline-form-field/public-api.ts deleted file mode 100644 index 93e9865..0000000 --- a/projects/elonkit/src/ui/inline-form-field/public-api.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './inline-form-field.module'; -export * from './inline-form-field.component'; diff --git a/projects/elonkit/src/ui/locale/locale.service.ts b/projects/elonkit/src/ui/locale/locale.service.ts index ffba109..e1eae0b 100644 --- a/projects/elonkit/src/ui/locale/locale.service.ts +++ b/projects/elonkit/src/ui/locale/locale.service.ts @@ -1,5 +1,4 @@ import { Injectable } from '@angular/core'; - import { BehaviorSubject } from 'rxjs'; import { map } from 'rxjs/operators'; diff --git a/projects/elonkit/src/ui/locale/public-api.ts b/projects/elonkit/src/ui/locale/public-api.ts index 6d6dfcf..1b6adff 100644 --- a/projects/elonkit/src/ui/locale/public-api.ts +++ b/projects/elonkit/src/ui/locale/public-api.ts @@ -1,2 +1,2 @@ -export { ESLocaleService, ESLocale } from './locale.service'; +export { ESLocale, ESLocaleService } from './locale.service'; export { en, ru } from './locales'; diff --git a/projects/elonkit/src/ui/paginator/__specs__/paginator.spec.ts b/projects/elonkit/src/ui/paginator/__specs__/paginator.spec.ts deleted file mode 100644 index e013f44..0000000 --- a/projects/elonkit/src/ui/paginator/__specs__/paginator.spec.ts +++ /dev/null @@ -1,199 +0,0 @@ -import { inject } from '@angular/core/testing'; -import { OverlayContainer } from '@angular/cdk/overlay'; - -import { fireEvent, getByText, render, screen } from '@testing-library/angular'; - -import { ESPaginatorComponent, ESPaginatorModule } from '..'; -import { en, ESLocaleService, ru } from '../../locale'; - -describe('Paginator', () => { - it('Should calculate corrent number of pages', async () => { - const component = await render(ESPaginatorComponent, { - componentProperties: { - count: 100, - page: 1, - pageSize: 5, - siblingCount: 2, - boundaryCount: 1, - }, - imports: [ESPaginatorModule], - excludeComponentDeclaration: true, - }); - - expect(screen.queryByText('1')).toBeInTheDocument(); - expect(screen.queryByText('2')).toBeInTheDocument(); - expect(screen.queryByText('3')).toBeInTheDocument(); - expect(screen.queryByText('4')).toBeInTheDocument(); - expect(screen.queryByText('5')).toBeInTheDocument(); - expect(screen.queryByText('6')).toBeInTheDocument(); - expect(screen.queryByText('7')).toBeInTheDocument(); - expect(screen.queryByText('8')).toBeNull(); - // ... - expect(screen.queryByText('19')).toBeNull(); - expect(screen.queryByText('20')).toBeInTheDocument(); - - component.fixture.componentInstance.page = 10; - component.fixture.componentInstance.changeDetector.detectChanges(); - - expect(screen.queryByText('1')).toBeInTheDocument(); - expect(screen.queryByText('2')).toBeNull(); - // ... - expect(screen.queryByText('7')).toBeNull(); - expect(screen.queryByText('8')).toBeInTheDocument(); - expect(screen.queryByText('9')).toBeInTheDocument(); - expect(screen.queryByText('10')).toBeInTheDocument(); - expect(screen.queryByText('11')).toBeInTheDocument(); - expect(screen.queryByText('12')).toBeInTheDocument(); - expect(screen.queryByText('13')).toBeNull(); - // ... - expect(screen.queryByText('19')).toBeNull(); - expect(screen.queryByText('20')).toBeInTheDocument(); - - component.fixture.componentInstance.siblingCount = 1; - component.fixture.componentInstance.changeDetector.detectChanges(); - - expect(screen.queryByText('1')).toBeInTheDocument(); - expect(screen.queryByText('2')).toBeNull(); - // ... - expect(screen.queryByText('8')).toBeNull(); - expect(screen.queryByText('9')).toBeInTheDocument(); - expect(screen.queryByText('10')).toBeInTheDocument(); - expect(screen.queryByText('11')).toBeInTheDocument(); - expect(screen.queryByText('12')).toBeNull(); - // ... - expect(screen.queryByText('19')).toBeNull(); - expect(screen.queryByText('20')).toBeInTheDocument(); - - component.fixture.componentInstance.boundaryCount = 2; - component.fixture.componentInstance.changeDetector.detectChanges(); - - expect(screen.queryByText('1')).toBeInTheDocument(); - expect(screen.queryByText('2')).toBeInTheDocument(); - expect(screen.queryByText('3')).toBeNull(); - // ... - expect(screen.queryByText('8')).toBeNull(); - expect(screen.queryByText('9')).toBeInTheDocument(); - expect(screen.queryByText('10')).toBeInTheDocument(); - expect(screen.queryByText('11')).toBeInTheDocument(); - expect(screen.queryByText('12')).toBeNull(); - // ... - expect(screen.queryByText('18')).toBeNull(); - expect(screen.queryByText('19')).toBeInTheDocument(); - expect(screen.queryByText('20')).toBeInTheDocument(); - - component.fixture.componentInstance.page = 20; - component.fixture.componentInstance.changeDetector.detectChanges(); - - expect(screen.queryByText('1')).toBeInTheDocument(); - expect(screen.queryByText('2')).toBeInTheDocument(); - expect(screen.queryByText('3')).toBeNull(); - // ... - expect(screen.queryByText('14')).toBeNull(); - expect(screen.queryByText('15')).toBeInTheDocument(); - expect(screen.queryByText('16')).toBeInTheDocument(); - expect(screen.queryByText('17')).toBeInTheDocument(); - expect(screen.queryByText('18')).toBeInTheDocument(); - expect(screen.queryByText('19')).toBeInTheDocument(); - expect(screen.queryByText('20')).toBeInTheDocument(); - }); - - it('Should emit events', async () => { - const onPageChange = jest.fn(); - const onPageSizeChange = jest.fn(); - - await render(ESPaginatorComponent, { - componentProperties: { - count: 100, - page: 5, - pageSize: 10, - pageChange: { - emit: onPageChange, - } as any, - pageSizeChange: { - emit: onPageSizeChange, - } as any, - }, - imports: [ESPaginatorModule], - excludeComponentDeclaration: true, - }); - - fireEvent.click(screen.getByLabelText(en.paginator.labelPrev)); - expect(onPageChange).toBeCalledWith(4); - - fireEvent.click(screen.getByLabelText(en.paginator.labelNext)); - expect(onPageChange).toBeCalledWith(6); - - fireEvent.click(screen.getByText('7')); - expect(onPageChange).toBeCalledWith(7); - - fireEvent.input(screen.getByLabelText(en.paginator.labelGoTo), { target: { value: '10' } }); - fireEvent.submit(screen.getByLabelText(en.paginator.labelGoTo)); - expect(onPageChange).toBeCalledWith(10); - - fireEvent.click(screen.getByLabelText(en.paginator.labelItemsPerPage).querySelector('.mat-select-trigger')); - fireEvent.click(getByText(document.body, /250/)); - - expect(onPageSizeChange).toBeCalledWith(250); - }); - - it('Should accept page size options', async () => { - let overlay: OverlayContainer; - let overlayElement: HTMLElement; - - await render(ESPaginatorComponent, { - componentProperties: { - count: 100, - page: 5, - pageSize: 10, - pageSizeOptions: [10, 20, 30], - }, - imports: [ESPaginatorModule], - excludeComponentDeclaration: true, - }); - - inject([OverlayContainer], (oc: OverlayContainer) => { - overlay = oc; - overlayElement = oc.getContainerElement(); - })(); - - fireEvent.click(screen.getByLabelText(en.paginator.labelItemsPerPage).querySelector('.mat-select-trigger')); - - const options = overlayElement.querySelectorAll('.mat-option'); - - expect(options).toHaveLength(3); - expect(options[0].textContent).toContain('10'); - expect(options[1].textContent).toContain('20'); - expect(options[2].textContent).toContain('30'); - - inject([OverlayContainer], (currentOverlay: OverlayContainer) => { - currentOverlay.ngOnDestroy(); - overlay.ngOnDestroy(); - })(); - }); - - it('Should change locale', async () => { - const localeService = new ESLocaleService(); - localeService.register('ru', ru); - localeService.use('ru'); - - await render(ESPaginatorComponent, { - componentProperties: { - count: 100, - page: 1, - pageSize: 10, - siblingCount: 2, - boundaryCount: 1, - }, - imports: [ESPaginatorModule], - providers: [{ provide: ESLocaleService, useValue: localeService }], - excludeComponentDeclaration: true, - }); - - expect(screen.getByLabelText(ru.paginator.labelItemsPerPage)).toBeInTheDocument(); - expect(screen.getByText(`1 — 10 ${ru.paginator.labelOf} 100`)).toBeInTheDocument(); - expect(screen.getByLabelText(ru.paginator.labelPrev)).toBeInTheDocument(); - expect(screen.getByLabelText(ru.paginator.labelPrev)).toBeInTheDocument(); - expect(screen.getByLabelText(ru.paginator.labelGoTo)).toBeInTheDocument(); - expect(screen.getByPlaceholderText(`1 ${ru.paginator.labelPage}`)).toBeInTheDocument(); - }); -}); diff --git a/projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/index.ts b/projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/index.ts deleted file mode 100644 index 373f575..0000000 --- a/projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { PaginatorStoryBasicModule } from './paginator-story-basic.module'; -export { PaginatorStoryBasicComponent } from './paginator-story-basic.component'; -export { PAGINATOR_STORY_BASIC_SOURCE } from './paginator-story-basic.source'; diff --git a/projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/paginator-story-basic.component.html b/projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/paginator-story-basic.component.html deleted file mode 100644 index 21fc1e4..0000000 --- a/projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/paginator-story-basic.component.html +++ /dev/null @@ -1,9 +0,0 @@ - diff --git a/projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/paginator-story-basic.component.ts b/projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/paginator-story-basic.component.ts deleted file mode 100644 index 50e3809..0000000 --- a/projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/paginator-story-basic.component.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; - -@Component({ - selector: 'es-paginator-basic', - templateUrl: './paginator-story-basic.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class PaginatorStoryBasicComponent { - private _count: number; - - @Input() - public set count(value: number) { - this._count = value; - this.page = 1; - } - public get count() { - return this._count; - } - - @Input() public siblingCount: number; - @Input() public boundaryCount: number; - @Input() public pageSizeOptions: number[]; - - public page = 1; - public pageSize = 5; - - public onPageChange(page: number) { - this.page = page; - } - - public onPageSizeChange(pageSize: number) { - this.pageSize = pageSize; - this.page = 1; - } -} diff --git a/projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/paginator-story-basic.module.ts b/projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/paginator-story-basic.module.ts deleted file mode 100644 index 4cb8c77..0000000 --- a/projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/paginator-story-basic.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; - -import { PaginatorStoryBasicComponent } from './paginator-story-basic.component'; - -import { ESPaginatorModule } from '../..'; - -@NgModule({ - declarations: [PaginatorStoryBasicComponent], - imports: [CommonModule, ESPaginatorModule], - exports: [PaginatorStoryBasicComponent], -}) -export class PaginatorStoryBasicModule {} diff --git a/projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/paginator-story-basic.source.ts b/projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/paginator-story-basic.source.ts deleted file mode 100644 index d8c8746..0000000 --- a/projects/elonkit/src/ui/paginator/__stories__/paginator-story-basic/paginator-story-basic.source.ts +++ /dev/null @@ -1,31 +0,0 @@ -export const PAGINATOR_STORY_BASIC_SOURCE = { - ts: ` - @Component({ - ... - }) - export class PaginatableDataComponent { - count = 100; - - page = 1; - pageSize = 5; - - onPageChange(page: number) { - this.page = page; - } - - onPageSizeChange(pageSize: number) { - this.pageSize = pageSize; - this.page = 1; - } - } - `, - html: ` - - `, -}; diff --git a/projects/elonkit/src/ui/paginator/__stories__/paginator-story-page-size-options/index.ts b/projects/elonkit/src/ui/paginator/__stories__/paginator-story-page-size-options/index.ts deleted file mode 100644 index 7af6eb5..0000000 --- a/projects/elonkit/src/ui/paginator/__stories__/paginator-story-page-size-options/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { - PaginatorStoryBasicComponent as PaginatorStoryPageSizeOptionsComponent, - PaginatorStoryBasicModule as PaginatorStoryPageSizeOptionsModule, -} from '../paginator-story-basic'; -export { PAGINATOR_STORY_PAGE_SIZE_OPTIONS_SOURCE } from './paginator-story-page-size-options.source'; diff --git a/projects/elonkit/src/ui/paginator/__stories__/paginator-story-page-size-options/paginator-story-page-size-options.source.ts b/projects/elonkit/src/ui/paginator/__stories__/paginator-story-page-size-options/paginator-story-page-size-options.source.ts deleted file mode 100644 index 14bf32e..0000000 --- a/projects/elonkit/src/ui/paginator/__stories__/paginator-story-page-size-options/paginator-story-page-size-options.source.ts +++ /dev/null @@ -1,12 +0,0 @@ -export const PAGINATOR_STORY_PAGE_SIZE_OPTIONS_SOURCE = { - html: ` - - `, -}; diff --git a/projects/elonkit/src/ui/paginator/__stories__/paginator.stories.mdx b/projects/elonkit/src/ui/paginator/__stories__/paginator.stories.mdx deleted file mode 100644 index bda48c0..0000000 --- a/projects/elonkit/src/ui/paginator/__stories__/paginator.stories.mdx +++ /dev/null @@ -1,108 +0,0 @@ -import { Meta, Story, ArgsTable } from '@storybook/addon-docs'; -import { Canvas } from '~storybook/components'; - -import { action } from '@storybook/addon-actions'; - -import { ESPaginatorComponent } from '..'; - -import { PaginatorStoryBasicModule, PaginatorStoryBasicComponent, PAGINATOR_STORY_BASIC_SOURCE } from './paginator-story-basic'; - -import { - PaginatorStoryPageSizeOptionsModule, - PaginatorStoryPageSizeOptionsComponent, - PAGINATOR_STORY_PAGE_SIZE_OPTIONS_SOURCE, -} from './paginator-story-page-size-options'; - - - -# Paginator - -The paginator allows the user to select a specific page from a range of pages. - -## Demos - - - - {((args) => ({ - component: PaginatorStoryBasicComponent, - moduleMetadata: { - imports: [PaginatorStoryBasicModule], - }, - props: { - ...args, - }, - })).bind({})} - - - -We can override default page size options. - - - - {((args) => ({ - component: PaginatorStoryPageSizeOptionsComponent, - moduleMetadata: { - imports: [PaginatorStoryPageSizeOptionsModule], - }, - props: { - ...args, - pageSizeOptions: [5, 6, 7, 8, 9, 10], - }, - })).bind({})} - - - -## API - - - -## Interfaces - -```ts -interface ESPaginatorDefaultOptions { - pageSizeOptions?: number[]; - siblingCount?: number; - boundaryCount?: number; - typography?: string; -} -``` - -## Constants - -Injection token that can be used to configure the default options for all components within an app. - -```ts -import { ES_PAGINATOR_DEFAULT_OPTIONS } from '@elonkit/angular/ui/paginator'; - -@NgModule({ - providers: [ - { - provide: ES_PAGINATOR_DEFAULT_OPTIONS, - useValue: { - pageSizeOptions: [5, 10, 25, 50, 100, 250, 500], - siblingCount: 2, - boundaryCount: 1, - typography: 'es-caption' - } - } - ] -}) -``` diff --git a/projects/elonkit/src/ui/paginator/index.ts b/projects/elonkit/src/ui/paginator/index.ts deleted file mode 100644 index 7e1a213..0000000 --- a/projects/elonkit/src/ui/paginator/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './public-api'; diff --git a/projects/elonkit/src/ui/paginator/paginator.component.html b/projects/elonkit/src/ui/paginator/paginator.component.html deleted file mode 100644 index 39cb2b7..0000000 --- a/projects/elonkit/src/ui/paginator/paginator.component.html +++ /dev/null @@ -1,83 +0,0 @@ -
-
- {{ locale.paginator.labelItemsPerPage }}: - - - {{ size }} - - - - - {{ countStart }} — {{ countEnd }} {{ locale.paginator.labelOf }} {{ count }} - -
- -
- - - - -
- - - -
-
- - - -
- - - -
-
-
diff --git a/projects/elonkit/src/ui/paginator/paginator.component.scss b/projects/elonkit/src/ui/paginator/paginator.component.scss deleted file mode 100644 index d682892..0000000 --- a/projects/elonkit/src/ui/paginator/paginator.component.scss +++ /dev/null @@ -1,129 +0,0 @@ -.es-paginator { - display: flex; - flex-direction: row; - flex-wrap: wrap; - justify-content: space-between; - align-items: baseline; - white-space: nowrap; - - &__size { - display: flex; - align-items: center; - margin-bottom: 16px; - margin-right: 24px; - } - - &__select { - display: block; - margin-left: 4px; - margin-right: 18px; - - &.mat-select { - width: 40px; - } - } - - &__pages { - margin-left: auto; - } - - &__form { - margin-left: 16px; - } - - &__input { - appearance: textfield; - width: 64px; - - &.mat-form-field-appearance-outline .mat-form-field-flex { - padding-bottom: 0; - padding-left: 0.6em; - padding-right: 0.6em; - padding-top: 0; - } - - &.mat-form-field-appearance-outline .mat-form-field-wrapper { - margin-bottom: 0; - margin-top: 0; - padding-bottom: 0; - - .mat-form-field-infix { - border: 0; - font-size: 12px; - padding-bottom: 9px; - padding-top: 14px; - } - } - - .mat-form-field-subscript-wrapper { - display: none; - } - - .mat-input-element { - appearance: textfield; - - &::-webkit-outer-spin-button, - &::-webkit-inner-spin-button { - appearance: none !important; - margin: 0 !important; - } - } - } - - &__items { - display: flex; - align-items: center; - margin-left: -12px; - } - - &__item { - display: flex; - justify-content: center; - align-items: center; - font-size: 12px; - - &-icon { - opacity: 0.38; - margin-top: 12px; - } - - &, - &.mat-icon-button { - width: 32px; - height: 32px; - line-height: unset; - margin: 0; - } - - &:first-child { - margin-left: 0; - } - - &:last-child { - margin-right: 24px; - } - - &_active { - font-weight: 600; - } - - &_arrow { - padding: 0; - - &:disabled { - opacity: 0.3; - } - } - - &_gap { - width: 32px; - display: flex; - align-items: center; - color: inherit; - - &:hover { - background: none; - } - } - } -} diff --git a/projects/elonkit/src/ui/paginator/paginator.component.theme.scss b/projects/elonkit/src/ui/paginator/paginator.component.theme.scss deleted file mode 100644 index 46c02e4..0000000 --- a/projects/elonkit/src/ui/paginator/paginator.component.theme.scss +++ /dev/null @@ -1,37 +0,0 @@ -@mixin es-paginator-theme($theme, $elonkit-theme) { - $accent: map-get($theme, accent); - $mono-a: map-get($elonkit-theme, mono-a); - - .es-paginator { - color: mat.get-color-from-palette($mono-a, A600); - - &__item { - &_active { - background-color: mat.get-color-from-palette($accent, A100); - color: mat.get-color-from-palette($mono-a, A500); - font-weight: 600; - - &.mat-icon-button:disabled { - color: mat.get-color-from-palette($accent); - - &:hover { - background-color: mat.get-color-from-palette($accent, A100); - color: mat.get-color-from-palette($accent); - } - } - - &.mat-icon-button:hover { - color: mat.get-color-from-palette($mono-a, A50); - } - } - - &:hover { - background-color: mat.get-color-from-palette($mono-a, A50); - } - } - } - - .mat-select-arrow { - color: mat.get-color-from-palette($mono-a, A500); - } -} diff --git a/projects/elonkit/src/ui/paginator/paginator.component.ts b/projects/elonkit/src/ui/paginator/paginator.component.ts deleted file mode 100644 index 6cc0527..0000000 --- a/projects/elonkit/src/ui/paginator/paginator.component.ts +++ /dev/null @@ -1,318 +0,0 @@ -import { - Component, - ChangeDetectionStrategy, - ChangeDetectorRef, - ViewEncapsulation, - Input, - Output, - EventEmitter, - InjectionToken, - Optional, - Inject, - HostListener, -} from '@angular/core'; - -import { Observable } from 'rxjs'; - -import { ESLocaleService, ESLocale } from '../locale'; - -function range(start: number, end: number) { - const length = end - start + 1; - return Array.from({ length }, (_, i) => start + i); -} - -export interface ESPaginatorDefaultOptions { - pageSizeOptions?: number[]; - siblingCount?: number; - boundaryCount?: number; - typography?: string; -} - -export const ES_PAGINATOR_DEFAULT_OPTIONS = new InjectionToken('ES_PAGINATOR_DEFAULT_OPTIONS'); - -@Component({ - selector: 'es-paginator', - templateUrl: './paginator.component.html', - styleUrls: ['./paginator.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class ESPaginatorComponent { - /** - * The count of the total number of items that are being paginated. - */ - @Input() public count: number; - - // tslint:disable-next-line - private _page: number; - - /** - * The current page. - */ - @Input() - public set page(page: number) { - this.pageGoTo = ''; - this._page = page; - } - public get page() { - return this._page; - } - - /** - * Number of items to display on a page. - */ - @Input() public pageSize: number; - - private _pageSizeOptions: number[]; - - /** - * The set of provided page size options to display to the user. - */ - @Input() - public set pageSizeOptions(value: number[] | undefined) { - this._pageSizeOptions = value || this.defaultOptions?.pageSizeOptions || [5, 10, 25, 50, 100, 250, 500]; - } - public get pageSizeOptions(): number[] { - return this._pageSizeOptions; - } - - private _siblingCount: number; - - /** - * Number of always visible pages before and after the current page. - */ - @Input() - public set siblingCount(value: number | undefined) { - this._siblingCount = value ?? this.defaultOptions?.siblingCount ?? 2; - } - public get siblingCount(): number { - return this._siblingCount; - } - - private _boundaryCount: number; - - /** - * Number of always visible pages at the beginning and end. - */ - @Input() - public set boundaryCount(value: number | undefined) { - this._boundaryCount = value ?? this.defaultOptions?.boundaryCount ?? 1; - } - public get boundaryCount(): number { - return this._boundaryCount; - } - - private _typography: string; - - /** - * Class applied to text. - */ - @Input() - public get typography(): string { - return this._typography; - } - public set typography(value: string | undefined) { - this._typography = value || this.defaultOptions?.typography || 'es-caption'; - } - - /** - * Event emitted when the paginator changes the page index. - */ - @Output() public pageChange = new EventEmitter(); - - /** - * Event emitted when the paginator changes the page size. - */ - @Output() public pageSizeChange = new EventEmitter(); - - /** - * @internal - * @ignore - */ - public pageGoTo = ''; - - /** - * @internal - * @ignore - */ - public locale$: Observable; - - /** - * @ignore - */ - constructor( - /** - * @internal - */ - public changeDetector: ChangeDetectorRef, - /** - * @internal - */ - private localeService: ESLocaleService, - /** - * @internal - */ - @Optional() - @Inject(ES_PAGINATOR_DEFAULT_OPTIONS) - private defaultOptions: ESPaginatorDefaultOptions - ) { - this.locale$ = this.localeService.locale(); - - this.pageSizeOptions = this.defaultOptions?.pageSizeOptions; - this.siblingCount = this.defaultOptions?.siblingCount; - this.boundaryCount = this.defaultOptions?.boundaryCount; - this.typography = this.defaultOptions?.typography; - } - - /** - * @internal - * @ignore - */ - public get countStart() { - return (this.page - 1) * this.pageSize + (this.count ? 1 : 0); - } - - /** - * @internal - * @ignore - */ - public get countEnd() { - return Math.min(this.page * this.pageSize, this.count); - } - - /** - * @internal - * @ignore - */ - public get pagesCount() { - return Math.ceil(this.count / this.pageSize); - } - - /** - * @internal - * @ignore - */ - public get pages() { - const startPages = range(1, Math.min(this.boundaryCount, this.pagesCount)); - const endPages = range(Math.max(this.pagesCount - this.boundaryCount + 1, this.boundaryCount + 1), this.pagesCount); - - const siblingsStart = Math.max( - Math.min( - // Natural start - this.page - this.siblingCount, - // Lower boundary when page is high - this.pagesCount - this.boundaryCount - this.siblingCount * 2 - 1 - ), - // Greater than startPages - this.boundaryCount + 2 - ); - - const siblingsEnd = Math.min( - Math.max( - // Natural end - this.page + this.siblingCount, - // Upper boundary when page is low - this.boundaryCount + this.siblingCount * 2 + 2 - ), - // Less than endPages - endPages[0] - 2 - ); - - const itemList = [ - ...startPages, - - // Start ellipsis - ...(siblingsStart > this.boundaryCount + 2 - ? [null] - : this.boundaryCount + 1 < this.pagesCount - this.boundaryCount - ? [this.boundaryCount + 1] - : []), - - // Sibling pages - ...range(siblingsStart, siblingsEnd), - - // End ellipsis - ...(siblingsEnd < this.pagesCount - this.boundaryCount - 1 - ? [null] - : this.pagesCount - this.boundaryCount > this.boundaryCount - ? [this.pagesCount - this.boundaryCount] - : []), - - ...endPages, - ]; - - return itemList; - } - - /** - * @internal - * @ignore - */ - public onPageSizeChange(pageSize: number) { - this.pageSizeChange.emit(pageSize); - } - - /** - * @internal - * @ignore - */ - public onPageClick(page: number) { - this.pageChange.emit(page); - } - - /** - * @internal - * @ignore - */ - public onNextPage() { - this.pageChange.emit(Math.min(this.page + 1, this.pagesCount)); - } - - /** - * @internal - * @ignore - */ - public onPrevPage() { - this.pageChange.emit(Math.max(1, this.page - 1)); - } - - /** - * @internal - * @ignore - */ - public onSubmit(event: Event) { - event.preventDefault(); - if (this.pageGoTo) { - const page = Math.max(1, Math.min(+this.pageGoTo, this.pagesCount)); - this.pageChange.emit(page); - } - } - - /** - * Prevent letter typing - */ - /** - * @internal - * @ignore - */ - public onKeyPress(event: KeyboardEvent) { - const key = event.key; - const regex = /[0-9]/; - - if (key === 'Enter' || regex.test(key)) { - return; - } - - event.preventDefault(); - } - - @HostListener('window:keydown.shift.arrowright', ['$event']) public onKeyWrightDown(event: KeyboardEvent) { - this.onNextPage(); - } - - @HostListener('window:keydown.shift.arrowleft', ['$event']) public onKeyLeftDown(event: KeyboardEvent) { - if (this.page !== 1) { - this.onPrevPage(); - } - } -} diff --git a/projects/elonkit/src/ui/paginator/paginator.module.ts b/projects/elonkit/src/ui/paginator/paginator.module.ts deleted file mode 100644 index 8ad05ec..0000000 --- a/projects/elonkit/src/ui/paginator/paginator.module.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; - -import { MatButtonModule } from '@angular/material/button'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatIconModule } from '@angular/material/icon'; -import { MatInputModule } from '@angular/material/input'; -import { MatSelectModule } from '@angular/material/select'; - -import { ESPaginatorComponent } from './paginator.component'; -import { ESTooltipModule } from '../tooltip'; - -@NgModule({ - imports: [ - CommonModule, - FormsModule, - - MatButtonModule, - MatFormFieldModule, - MatIconModule, - MatInputModule, - MatSelectModule, - ESTooltipModule, - ], - exports: [ESPaginatorComponent], - declarations: [ESPaginatorComponent], -}) -export class ESPaginatorModule {} diff --git a/projects/elonkit/src/ui/paginator/public-api.ts b/projects/elonkit/src/ui/paginator/public-api.ts deleted file mode 100644 index f00344d..0000000 --- a/projects/elonkit/src/ui/paginator/public-api.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './paginator.module'; -export * from './paginator.component'; diff --git a/projects/elonkit/src/ui/surface/surface.component.theme.scss b/projects/elonkit/src/ui/surface/surface.component.theme.scss deleted file mode 100644 index aaa58da..0000000 --- a/projects/elonkit/src/ui/surface/surface.component.theme.scss +++ /dev/null @@ -1,13 +0,0 @@ -@mixin es-surface-theme($theme, $elonkit-theme) { - $surface: map-get($elonkit-theme, surface); - - .es-surface { - @each $hue in map-keys($surface) { - @if (not(str-index(inspect($hue), 'contrast') or ($hue == 'text'))) { - &-#{$hue} { - background: map-get($surface, $hue); - } - } - } - } -} diff --git a/projects/elonkit/src/ui/surface/surface.source.ts b/projects/elonkit/src/ui/surface/surface.source.ts deleted file mode 100644 index c1da858..0000000 --- a/projects/elonkit/src/ui/surface/surface.source.ts +++ /dev/null @@ -1,15 +0,0 @@ -export const SURFACE_SOURCE = { - html: ` -
Surface 0
-
Surface 1
-
Surface 2
-
Surface 3
-
Surface 4
-
Surface 6
-
Surface 7
-
Surface 12
-
Surface 16
-
Surface 24
-
Surface On
- `, -}; diff --git a/projects/elonkit/src/ui/surface/surface.stories.mdx b/projects/elonkit/src/ui/surface/surface.stories.mdx deleted file mode 100644 index d708f30..0000000 --- a/projects/elonkit/src/ui/surface/surface.stories.mdx +++ /dev/null @@ -1,30 +0,0 @@ -import { Meta, Story, Props } from '@storybook/addon-docs'; -import { Canvas } from '~storybook/components'; - -import { SURFACE_SOURCE } from './surface.source'; - - - -# Surface - - - - {{ - template: ` -
-
Surface 0
-
Surface 1
-
Surface 2
-
Surface 3
-
Surface 4
-
Surface 6
-
Surface 7
-
Surface 12
-
Surface 16
-
Surface 24
-
Surface On
-
- `, - }} -
-
diff --git a/projects/elonkit/src/ui/timepicker/__specs__/timepicker.spec.ts b/projects/elonkit/src/ui/timepicker/__specs__/timepicker.spec.ts deleted file mode 100644 index f368cff..0000000 --- a/projects/elonkit/src/ui/timepicker/__specs__/timepicker.spec.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { Component, Input } from '@angular/core'; -import { FormsModule } from '@angular/forms'; - -import { fireEvent, render, screen } from '@testing-library/angular'; - -import { ESTimepickerComponent, ESTimepickerModule } from '..'; -import { ESLocaleService, ru } from '../../locale'; - -@Component({ - template: ` `, -}) -class TimepickerWrapperComponent { - @Input() public required: boolean; - - public date = new Date('10.10.10 10:00:00'); -} - -describe('Timepicker', () => { - it('Should mask input', async () => { - await render(ESTimepickerComponent, { - imports: [ESTimepickerModule], - excludeComponentDeclaration: true, - }); - - const input = screen.getByPlaceholderText('HH:MM') as HTMLInputElement; - - fireEvent.input(input, { target: { value: '1010' } }); - - expect(screen.queryByDisplayValue('10:10')).not.toBeNull(); - }); - - it('Should mask input with seconds', async () => { - await render(ESTimepickerComponent, { - componentProperties: { - withSeconds: true, - }, - imports: [ESTimepickerModule], - excludeComponentDeclaration: true, - }); - - const input = screen.getByPlaceholderText('HH:MM:SS') as HTMLInputElement; - - fireEvent.input(input, { target: { value: '101010' } }); - - expect(screen.queryByDisplayValue('10:10:10')).not.toBeNull(); - }); - - it('Should restore previous correct value', async () => { - await render(TimepickerWrapperComponent, { - imports: [FormsModule, ESTimepickerModule], - }); - - const input = screen.getByDisplayValue('10:00') as HTMLInputElement; - - fireEvent.input(input, { target: { value: '10' } }); - expect(screen.queryByDisplayValue('10:__')).not.toBeNull(); - - fireEvent.blur(input); - expect(screen.queryByDisplayValue('10:00')).not.toBeNull(); - }); - - it('Should allow clearing unrequired input', async () => { - await render(TimepickerWrapperComponent, { - componentProperties: { - required: false, - }, - imports: [FormsModule, ESTimepickerModule], - }); - - const input = screen.getByDisplayValue('10:00') as HTMLInputElement; - - fireEvent.input(input, { target: { value: '' } }); - fireEvent.blur(input); - - expect(input.value).toBe(''); - expect(screen.queryByDisplayValue('10:00')).toBeNull(); - }); - - it('Should disallow clearing required input', async () => { - await render(TimepickerWrapperComponent, { - componentProperties: { - required: true, - }, - imports: [FormsModule, ESTimepickerModule], - }); - - const input = screen.getByDisplayValue('10:00') as HTMLInputElement; - - fireEvent.input(input, { target: { value: '' } }); - fireEvent.blur(input); - - expect(input.value).toBe('10:00'); - expect(screen.queryByDisplayValue('10:00')).not.toBeNull(); - }); - - it('Should change locale', async () => { - const localeService = new ESLocaleService(); - localeService.register('ru', ru); - localeService.use('ru'); - - await render(ESTimepickerComponent, { - componentProperties: { - withSeconds: true, - }, - imports: [ESTimepickerModule], - providers: [{ provide: ESLocaleService, useValue: localeService }], - excludeComponentDeclaration: true, - }); - - const { - timepicker: { labelHH, labelMM, labelSS }, - } = ru; - - expect(screen.queryByPlaceholderText(`${labelHH}:${labelMM}:${labelSS}`)).not.toBeNull(); - }); -}); diff --git a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/index.ts b/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/index.ts deleted file mode 100644 index b27576a..0000000 --- a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { TimepickerStoryBasicModule } from './timepicker-story-basic.module'; -export { TimepickerStoryBasicComponent } from './timepicker-story-basic.component'; -export { TIMEPICKER_STORY_BASIC_SOURCE } from './timepicker-story-basic.source'; diff --git a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/timepicker-story-basic.component.html b/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/timepicker-story-basic.component.html deleted file mode 100644 index 4bbdb15..0000000 --- a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/timepicker-story-basic.component.html +++ /dev/null @@ -1,4 +0,0 @@ - - Time - - diff --git a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/timepicker-story-basic.component.ts b/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/timepicker-story-basic.component.ts deleted file mode 100644 index a14dddf..0000000 --- a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/timepicker-story-basic.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component, ChangeDetectionStrategy } from '@angular/core'; - -@Component({ - selector: 'es-timepicker-basic', - templateUrl: './timepicker-story-basic.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class TimepickerStoryBasicComponent { - public date = new Date(0); -} diff --git a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/timepicker-story-basic.module.ts b/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/timepicker-story-basic.module.ts deleted file mode 100644 index ec5b1bb..0000000 --- a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/timepicker-story-basic.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; - -import { MatNativeDateModule } from '@angular/material/core'; -import { MatFormFieldModule } from '@angular/material/form-field'; - -import { TimepickerStoryBasicComponent } from './timepicker-story-basic.component'; - -import { ESTimepickerModule } from '../..'; - -@NgModule({ - declarations: [TimepickerStoryBasicComponent], - imports: [CommonModule, MatNativeDateModule, FormsModule, MatFormFieldModule, ESTimepickerModule], - exports: [TimepickerStoryBasicComponent], -}) -export class TimepickerStoryBasicModule {} diff --git a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/timepicker-story-basic.source.ts b/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/timepicker-story-basic.source.ts deleted file mode 100644 index ab0cba3..0000000 --- a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-basic/timepicker-story-basic.source.ts +++ /dev/null @@ -1,16 +0,0 @@ -export const TIMEPICKER_STORY_BASIC_SOURCE = { - ts: ` - @Component({ - ... - }) - export class FormComponent { - public date = new Date(); - } - `, - html: ` - - Time - - - `, -}; diff --git a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/index.ts b/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/index.ts deleted file mode 100644 index cf4110d..0000000 --- a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { TimepickerStoryRequiredModule } from './timepicker-story-required.module'; -export { TimepickerStoryRequiredComponent } from './timepicker-story-required.component'; -export { TIMEPICKER_STORY_REQUIRED_SOURCE } from './timepicker-story-required.source'; diff --git a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/timepicker-story-required.component.html b/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/timepicker-story-required.component.html deleted file mode 100644 index 919b768..0000000 --- a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/timepicker-story-required.component.html +++ /dev/null @@ -1,4 +0,0 @@ - - Time - - diff --git a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/timepicker-story-required.component.ts b/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/timepicker-story-required.component.ts deleted file mode 100644 index c9d08ab..0000000 --- a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/timepicker-story-required.component.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; - -@Component({ - selector: 'es-timepicker-required', - templateUrl: './timepicker-story-required.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class TimepickerStoryRequiredComponent { - @Input() public required: boolean; - - public date = new Date(0); -} diff --git a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/timepicker-story-required.module.ts b/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/timepicker-story-required.module.ts deleted file mode 100644 index 0e1252f..0000000 --- a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/timepicker-story-required.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; - -import { MatNativeDateModule } from '@angular/material/core'; -import { MatFormFieldModule } from '@angular/material/form-field'; - -import { TimepickerStoryRequiredComponent } from './timepicker-story-required.component'; - -import { ESTimepickerModule } from '../..'; - -@NgModule({ - declarations: [TimepickerStoryRequiredComponent], - imports: [CommonModule, MatNativeDateModule, FormsModule, MatFormFieldModule, ESTimepickerModule], - exports: [TimepickerStoryRequiredComponent], -}) -export class TimepickerStoryRequiredModule {} diff --git a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/timepicker-story-required.source.ts b/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/timepicker-story-required.source.ts deleted file mode 100644 index f25c1a2..0000000 --- a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-required/timepicker-story-required.source.ts +++ /dev/null @@ -1,16 +0,0 @@ -export const TIMEPICKER_STORY_REQUIRED_SOURCE = { - ts: ` - @Component({ - ... - }) - export class FormComponent { - public date = new Date(); - } - `, - html: ` - - Time - - - `, -}; diff --git a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/index.ts b/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/index.ts deleted file mode 100644 index ade65b3..0000000 --- a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { TimepickerStorySecondsModule } from './timepicker-story-seconds.module'; -export { TimepickerStorySecondsComponent } from './timepicker-story-seconds.component'; -export { TIMEPICKER_STORY_SECONDS_SOURCE } from './timepicker-story-seconds.story'; diff --git a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/timepicker-story-seconds.component.html b/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/timepicker-story-seconds.component.html deleted file mode 100644 index 0ac0d89..0000000 --- a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/timepicker-story-seconds.component.html +++ /dev/null @@ -1,4 +0,0 @@ - - Time - - diff --git a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/timepicker-story-seconds.component.ts b/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/timepicker-story-seconds.component.ts deleted file mode 100644 index 57d12c2..0000000 --- a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/timepicker-story-seconds.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component, ChangeDetectionStrategy } from '@angular/core'; - -@Component({ - selector: 'es-timepicker-seconds', - templateUrl: './timepicker-story-seconds.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class TimepickerStorySecondsComponent { - public date = new Date(0); -} diff --git a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/timepicker-story-seconds.module.ts b/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/timepicker-story-seconds.module.ts deleted file mode 100644 index 0766bdd..0000000 --- a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/timepicker-story-seconds.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; - -import { MatNativeDateModule } from '@angular/material/core'; -import { MatFormFieldModule } from '@angular/material/form-field'; - -import { TimepickerStorySecondsComponent } from './timepicker-story-seconds.component'; - -import { ESTimepickerModule } from '../..'; - -@NgModule({ - declarations: [TimepickerStorySecondsComponent], - imports: [CommonModule, MatNativeDateModule, FormsModule, MatFormFieldModule, ESTimepickerModule], - exports: [TimepickerStorySecondsComponent], -}) -export class TimepickerStorySecondsModule {} diff --git a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/timepicker-story-seconds.story.ts b/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/timepicker-story-seconds.story.ts deleted file mode 100644 index df1221f..0000000 --- a/projects/elonkit/src/ui/timepicker/__stories__/timepicker-story-seconds/timepicker-story-seconds.story.ts +++ /dev/null @@ -1,16 +0,0 @@ -export const TIMEPICKER_STORY_SECONDS_SOURCE = { - ts: ` - @Component({ - ... - }) - export class FormComponent { - public date = new Date(); - } - `, - html: ` - - Time - - - `, -}; diff --git a/projects/elonkit/src/ui/timepicker/__stories__/timepicker.stories.mdx b/projects/elonkit/src/ui/timepicker/__stories__/timepicker.stories.mdx deleted file mode 100644 index fd63523..0000000 --- a/projects/elonkit/src/ui/timepicker/__stories__/timepicker.stories.mdx +++ /dev/null @@ -1,77 +0,0 @@ -import { Meta, Story, ArgsTable } from '@storybook/addon-docs'; -import { Canvas } from '~storybook/components'; - -import { action } from '@storybook/addon-actions'; - -import { ESTimepickerComponent } from '..'; - -import { - TimepickerStoryBasicModule, - TimepickerStoryBasicComponent, - TIMEPICKER_STORY_BASIC_SOURCE, -} from './timepicker-story-basic'; - -import { - TimepickerStorySecondsModule, - TimepickerStorySecondsComponent, - TIMEPICKER_STORY_SECONDS_SOURCE, -} from './timepicker-story-seconds'; - -import { - TimepickerStoryRequiredModule, - TimepickerStoryRequiredComponent, - TIMEPICKER_STORY_REQUIRED_SOURCE, -} from './timepicker-story-required'; - - - -# Timepicker - -The timepicker allows users to enter a time through masked text input. -This component named `picker` instead of `input` in case we'll implement an actual picker in the future. - -## Demos - - - - {{ - component: TimepickerStoryBasicComponent, - moduleMetadata: { - imports: [TimepickerStoryBasicModule], - }, - }} - - - -We can use `withSeconds` in order to display seconds input. - - - - {{ - component: TimepickerStorySecondsComponent, - moduleMetadata: { - imports: [TimepickerStorySecondsModule], - }, - }} - - - -When input is required it won't allow to clear existing value. - - - - {((args) => ({ - component: TimepickerStoryRequiredComponent, - moduleMetadata: { - imports: [TimepickerStoryRequiredModule], - }, - props: { - ...args, - }, - })).bind({})} - - - -## API - - diff --git a/projects/elonkit/src/ui/timepicker/index.ts b/projects/elonkit/src/ui/timepicker/index.ts deleted file mode 100644 index 7e1a213..0000000 --- a/projects/elonkit/src/ui/timepicker/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './public-api'; diff --git a/projects/elonkit/src/ui/timepicker/public-api.ts b/projects/elonkit/src/ui/timepicker/public-api.ts deleted file mode 100644 index 2d344d9..0000000 --- a/projects/elonkit/src/ui/timepicker/public-api.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './timepicker.module'; -export * from './timepicker.component'; diff --git a/projects/elonkit/src/ui/timepicker/timepicker.component.html b/projects/elonkit/src/ui/timepicker/timepicker.component.html deleted file mode 100644 index a65bac9..0000000 --- a/projects/elonkit/src/ui/timepicker/timepicker.component.html +++ /dev/null @@ -1,11 +0,0 @@ - diff --git a/projects/elonkit/src/ui/timepicker/timepicker.component.ts b/projects/elonkit/src/ui/timepicker/timepicker.component.ts deleted file mode 100644 index 2fbc701..0000000 --- a/projects/elonkit/src/ui/timepicker/timepicker.component.ts +++ /dev/null @@ -1,313 +0,0 @@ -import { - Component, - ChangeDetectionStrategy, - Input, - OnDestroy, - Optional, - Self, - ChangeDetectorRef, - HostBinding, - ViewChild, - ElementRef, -} from '@angular/core'; - -import { DatePipe } from '@angular/common'; -import { ControlValueAccessor, NgControl, FormGroupDirective } from '@angular/forms'; - -import { coerceBooleanProperty } from '@angular/cdk/coercion'; - -import { MatFormFieldControl } from '@angular/material/form-field'; -import { Subject } from 'rxjs'; - -import createAutoCorrectedDatePipe from 'text-mask-addons/dist/createAutoCorrectedDatePipe'; -const autoCorrectedTimePipe = createAutoCorrectedDatePipe('HH:MM'); -const autoCorrectedTimeSecondsPipe = createAutoCorrectedDatePipe('HH:MM:SS'); - -import { ESLocaleService } from '../locale'; - -@Component({ - selector: 'es-timepicker', - templateUrl: './timepicker.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, - providers: [{ provide: MatFormFieldControl, useExisting: ESTimepickerComponent }], -}) -export class ESTimepickerComponent implements ControlValueAccessor, MatFormFieldControl, OnDestroy { - /** - * @internal - * @ignore - */ - public mask = { - mask: [/\d/, /\d/, ':', /\d/, /\d/], - pipe: autoCorrectedTimePipe, - }; - - private _withSeconds = false; - - /** - * Enable seconds input. - */ - @Input() - public get withSeconds() { - return this._withSeconds; - } - public set withSeconds(withSeconds: any) { - this._withSeconds = coerceBooleanProperty(withSeconds); - - if (this.withSeconds) { - this.mask = { - mask: [/\d/, /\d/, ':', /\d/, /\d/, ':', /\d/, /\d/], - pipe: autoCorrectedTimeSecondsPipe, - }; - } else { - this.mask = { mask: [/\d/, /\d/, ':', /\d/, /\d/], pipe: autoCorrectedTimePipe }; - } - } - - private _required = false; - - /** - * Mark input as required and forbid clearing existing value. - */ - @Input() - public get required() { - return this._required; - } - public set required(required: any) { - this._required = coerceBooleanProperty(required); - this.stateChanges.next(); - } - - private _disabled = false; - - /** - * Disable input. - */ - @Input() - public get disabled() { - return this._disabled; - } - public set disabled(disabled: any) { - this._disabled = coerceBooleanProperty(disabled); - this.stateChanges.next(); - } - - /** - * @ignore - */ - public stateChanges = new Subject(); - - private previousValue = ''; - private _value = ''; - - /** - * @ignore - */ - public get value() { - return this._value; - } - public set value(value: any) { - this._value = value; - this.stateChanges.next(); - } - - private _focused = false; - - /** - * @ignore - */ - public get focused() { - return this._focused; - } - public set focused(focused: boolean) { - this._focused = focused; - this.stateChanges.next(); - } - - /** - * @ignore - */ - public get empty(): boolean { - return !this.value; - } - - /** - * @ignore - */ - public get placeholder(): string { - const { - timepicker: { labelHH, labelMM, labelSS }, - } = this.localeService.currentLocale(); - return this.withSeconds ? `${labelHH}:${labelMM}:${labelSS}` : `${labelHH}:${labelMM}`; - } - - /** - * @ignore - */ - public get errorState(): boolean { - const control = this.ngControl; - const form = this.ngForm; - - if (control) { - return (control.invalid as boolean) && ((control.touched as boolean) || (form && form.submitted)); - } - - return false; - } - - private static nextId = 0; - - /** - * @ignore - */ - @HostBinding() public id = `es-timepicker-${ESTimepickerComponent.nextId++}`; - - /** - * @ignore - */ - @HostBinding('attr.aria-describedby') public describedBy = ''; - - /** - * @ignore - */ - @HostBinding('class.floating') public get shouldLabelFloat() { - return this.focused || !!this.value; - } - - @ViewChild('input', { static: true }) private input: ElementRef; - - /** - * @internal - * @ignore - */ - constructor( - /** - * @internal - */ - public changeDetector: ChangeDetectorRef, - @Optional() @Self() public ngControl: NgControl, - /** - * @internal - */ - @Optional() public ngForm: FormGroupDirective, - private datePipe: DatePipe, - private localeService: ESLocaleService - ) { - if (this.ngControl != null) { - this.ngControl.valueAccessor = this; - } - - this.stateChanges.subscribe(() => { - this.changeDetector.detectChanges(); - }); - } - - /** - * @ignore - */ - public ngOnDestroy() { - this.stateChanges.complete(); - } - - /** - * @ignore - */ - public setDescribedByIds(ids: string[]) { - this.describedBy = ids.join(' '); - } - - /** - * @ignore - */ - public writeValue(value: any) { - if (value !== undefined) { - if (value) { - this.value = this.datePipe.transform(value, this.withSeconds ? 'HH:mm:ss' : 'HH:mm'); - } else { - this.value = ''; - } - this.previousValue = this.value; - this.stateChanges.next(); - } - } - - /** - * @ignore - */ - public registerOnChange(onChange: (value: any) => void) { - this.onChange = onChange; - } - - /** - * @internal - * @ignore - */ - public onChange = (_: any) => {}; - - /** - * @ignore - */ - public registerOnTouched(onTouched: () => void) { - this.onTouched = onTouched; - } - - /** - * @internal - * @ignore - */ - public onTouched = () => {}; - - /** - * @internal - * @ignore - */ - public onInput(event: Event) { - const target = event.target as HTMLInputElement; - this.value = target.value; - } - - /** - * @internal - * @ignore - */ - public onFocus() { - this.focused = true; - this.stateChanges.next(); - } - - /** - * @internal - * @ignore - */ - public onBlur() { - this.onTouched(); - this.focused = false; - - if ((!this.required || this.value) && !this.value.includes('_')) { - if (this.value) { - const [hours, minutes, seconds] = this.value.split(':'); - const date = new Date(); - date.setHours(hours); - date.setMinutes(minutes); - date.setSeconds(this.withSeconds ? seconds || 0 : 0); - this.onChange(date); - } else { - this.onChange(null); - } - this.previousValue = this.value; - } else { - this.value = this.previousValue; - } - - this.stateChanges.next(); - } - - /** - * @ignore - */ - public onContainerClick() { - if (!this.focused && !this.disabled && this.input) { - this.input.nativeElement.focus(); - this.stateChanges.next(); - } - } -} diff --git a/projects/elonkit/src/ui/timepicker/timepicker.module.ts b/projects/elonkit/src/ui/timepicker/timepicker.module.ts deleted file mode 100644 index 9318035..0000000 --- a/projects/elonkit/src/ui/timepicker/timepicker.module.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule, DatePipe } from '@angular/common'; - -import { MatInputModule } from '@angular/material/input'; - -import { TextMaskModule } from 'angular2-text-mask'; - -import { ESTimepickerComponent } from './timepicker.component'; - -@NgModule({ - declarations: [ESTimepickerComponent], - imports: [CommonModule, MatInputModule], - exports: [ESTimepickerComponent], - providers: [DatePipe], -}) -export class ESTimepickerModule {} diff --git a/projects/elonkit/src/ui/tooltip/_specs_/tooltip.spec.ts b/projects/elonkit/src/ui/tooltip/_specs_/tooltip.spec.ts deleted file mode 100644 index 89fb56c..0000000 --- a/projects/elonkit/src/ui/tooltip/_specs_/tooltip.spec.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { Component, Input, ChangeDetectorRef } from '@angular/core'; -import { fakeAsync, tick, flush, inject } from '@angular/core/testing'; -import { OverlayContainer } from '@angular/cdk/overlay'; - -import { render, getByText, queryByText, RenderResult, fireEvent, screen } from '@testing-library/angular'; - -import { ESTooltipModule } from '..'; - -const BUTTON_TEXT = 'Button'; -const BUTTON_ACTION_TEXT = 'Action'; -const BUTTON_CLOSE_TEXT = 'Close'; -const TOOLTIP_TEXT = 'Message'; - -@Component({ - template: ` - - - ${TOOLTIP_TEXT} - - - - `, -}) -class TooltipWrapperComponent { - @Input() public esTooltipArrow: boolean; - @Input() public esTooltipDisableFocusListener: boolean; - @Input() public esTooltipDisableHoverListener: boolean; - @Input() public esTooltipDisableCloseFocusListener: boolean; - @Input() public esTooltipDisableCloseHoverListener: boolean; - @Input() public esTooltipDisableCloseClickListener: boolean; - - constructor(public changeDetector: ChangeDetectorRef) {} -} - -describe('Tooltip', () => { - let overlay: OverlayContainer; - let overlayElement: HTMLElement; - let component: RenderResult; - - beforeEach(async () => { - component = await render(TooltipWrapperComponent, { - imports: [ESTooltipModule], - componentProperties: { - esTooltipArrow: true, - }, - }); - - inject([OverlayContainer], (oc: OverlayContainer) => { - overlay = oc; - overlayElement = oc.getContainerElement(); - })(); - }); - - afterEach(inject([OverlayContainer], (currentOverlay: OverlayContainer) => { - currentOverlay.ngOnDestroy(); - overlay.ngOnDestroy(); - })); - - it('Should display a template', async () => { - fireEvent.mouseEnter(screen.getByText(BUTTON_TEXT)); - expect(queryByText(overlayElement, TOOLTIP_TEXT)).toBeInTheDocument(); - }); - - it('Should render an arrow', async () => { - component.fixture.componentInstance.esTooltipArrow = true; - - fireEvent.mouseEnter(screen.getByText(BUTTON_TEXT)); - expect(overlayElement.querySelector('.es-tooltip__arrow')).toBeInTheDocument(); - }); - - it('Should close tooltip by a close button click', fakeAsync(async () => { - fireEvent.mouseEnter(screen.getByText(BUTTON_TEXT)); - expect(queryByText(overlayElement, TOOLTIP_TEXT)).toBeInTheDocument(); - - fireEvent.click(getByText(overlayElement, BUTTON_CLOSE_TEXT)); - - // Through trial and error... - tick(); - component.fixture.componentInstance.changeDetector.detectChanges(); - tick(); - component.fixture.componentInstance.changeDetector.detectChanges(); - - expect(queryByText(overlayElement, TOOLTIP_TEXT)).not.toBeInTheDocument(); - })); -}); diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/index.ts b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/index.ts deleted file mode 100644 index d494bbe..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { TooltipStoryBasicModule } from './tooltip-story-basic.module'; -export { TooltipStoryBasicComponent } from './tooltip-story-basic.component'; -export { TOOLTIP_STORY_BASIC_SOURCE } from './tooltip-story-basic.source'; diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/tooltip-story-basic.component.html b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/tooltip-story-basic.component.html deleted file mode 100644 index fb66ce1..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/tooltip-story-basic.component.html +++ /dev/null @@ -1,10 +0,0 @@ -
- -
diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/tooltip-story-basic.component.ts b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/tooltip-story-basic.component.ts deleted file mode 100644 index 8df5be2..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/tooltip-story-basic.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; - -@Component({ - selector: 'es-tooltip-story-basic', - templateUrl: './tooltip-story-basic.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class TooltipStoryBasicComponent { - @Input() public esTooltipArrow: boolean; -} diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/tooltip-story-basic.module.ts b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/tooltip-story-basic.module.ts deleted file mode 100644 index 183e47d..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/tooltip-story-basic.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; - -import { MatButtonModule } from '@angular/material/button'; - -import { TooltipStoryBasicComponent } from './tooltip-story-basic.component'; - -import { ESTooltipModule } from '../..'; - -@NgModule({ - declarations: [TooltipStoryBasicComponent], - imports: [CommonModule, MatButtonModule, ESTooltipModule], - exports: [TooltipStoryBasicComponent], -}) -export class TooltipStoryBasicModule {} diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/tooltip-story-basic.source.ts b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/tooltip-story-basic.source.ts deleted file mode 100644 index f9c52ef..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-basic/tooltip-story-basic.source.ts +++ /dev/null @@ -1,12 +0,0 @@ -export const TOOLTIP_STORY_BASIC_SOURCE = { - html: ` - - `, -}; diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/index.ts b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/index.ts deleted file mode 100644 index f25f13b..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { TooltipStoryInteractiveModule } from './tooltip-story-interactive.module'; -export { TooltipStoryInteractiveComponent } from './tooltip-story-interactive.component'; -export { TOOLTIP_STORY_INTERACTIVE_SOURCE } from './tooltip-story-interactive.source'; diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/tooltip-story-interactive.component.html b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/tooltip-story-interactive.component.html deleted file mode 100644 index 4bbfec1..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/tooltip-story-interactive.component.html +++ /dev/null @@ -1,37 +0,0 @@ -
-
- - -
-
- -
-
- - - This is a tooltip with an interactive content. -

- -
diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/tooltip-story-interactive.component.ts b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/tooltip-story-interactive.component.ts deleted file mode 100644 index fd3f54d..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/tooltip-story-interactive.component.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; - -@Component({ - selector: 'es-tooltip-story-interactive', - templateUrl: './tooltip-story-interactive.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class TooltipStoryInteractiveComponent { - @Input() public esTooltipArrow: boolean; - @Input() public esTooltipMouseAimDelay: number; -} diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/tooltip-story-interactive.module.ts b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/tooltip-story-interactive.module.ts deleted file mode 100644 index 3254e5d..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/tooltip-story-interactive.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; - -import { MatButtonModule } from '@angular/material/button'; - -import { TooltipStoryInteractiveComponent } from './tooltip-story-interactive.component'; - -import { ESTooltipModule } from '../..'; - -@NgModule({ - declarations: [TooltipStoryInteractiveComponent], - imports: [CommonModule, MatButtonModule, ESTooltipModule], - exports: [TooltipStoryInteractiveComponent], -}) -export class TooltipStoryInteractiveModule {} diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/tooltip-story-interactive.source.ts b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/tooltip-story-interactive.source.ts deleted file mode 100644 index 8dc453b..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-interactive/tooltip-story-interactive.source.ts +++ /dev/null @@ -1,18 +0,0 @@ -export const TOOLTIP_STORY_INTERACTIVE_SOURCE = { - html: ` - - - This is a tooltip with an interactive content - - - `, -}; diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/index.ts b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/index.ts deleted file mode 100644 index bb5e555..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { TooltipStoryListenersModule } from './tooltip-story-listeners.module'; -export { TooltipStoryListenersComponent } from './tooltip-story-listeners.component'; -export { TOOLTIP_STORY_LISTENERS_SOURCE } from './tooltip-story-listeners.source'; diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/tooltip-story-listeners.component.html b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/tooltip-story-listeners.component.html deleted file mode 100644 index 445058e..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/tooltip-story-listeners.component.html +++ /dev/null @@ -1,22 +0,0 @@ -
- - - Click this button to close the tooltip. -

- -
-
diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/tooltip-story-listeners.component.ts b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/tooltip-story-listeners.component.ts deleted file mode 100644 index f9f45ce..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/tooltip-story-listeners.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; - -@Component({ - selector: 'es-tooltip-story-listeners', - templateUrl: './tooltip-story-listeners.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class TooltipStoryListenersComponent { - @Input() public esTooltipArrow: boolean; - @Input() public esTooltipDisableFocusListener: boolean; - @Input() public esTooltipDisableHoverListener: boolean; - @Input() public esTooltipDisableCloseFocusListener: boolean; - @Input() public esTooltipDisableCloseHoverListener: boolean; - @Input() public esTooltipDisableCloseClickListener: boolean; -} diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/tooltip-story-listeners.module.ts b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/tooltip-story-listeners.module.ts deleted file mode 100644 index affeac6..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/tooltip-story-listeners.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; - -import { MatButtonModule } from '@angular/material/button'; - -import { TooltipStoryListenersComponent } from './tooltip-story-listeners.component'; - -import { ESTooltipModule } from '../..'; - -@NgModule({ - declarations: [TooltipStoryListenersComponent], - imports: [CommonModule, MatButtonModule, ESTooltipModule], - exports: [TooltipStoryListenersComponent], -}) -export class TooltipStoryListenersModule {} diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/tooltip-story-listeners.source.ts b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/tooltip-story-listeners.source.ts deleted file mode 100644 index 2fc9a3f..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-listeners/tooltip-story-listeners.source.ts +++ /dev/null @@ -1,22 +0,0 @@ -export const TOOLTIP_STORY_LISTENERS_SOURCE = { - html: ` - - - Click this button to close the tooltip. -

- -
- `, -}; diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/index.ts b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/index.ts deleted file mode 100644 index 1f074c6..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { TooltipStoryThemingModule } from './tooltip-story-theming.module'; -export { TooltipStoryThemingComponent } from './tooltip-story-theming.component'; -export { TOOLTIP_STORY_THEMING_SOURCE } from './tooltip-story-theming.source'; diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.component.html b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.component.html deleted file mode 100644 index c5cf700..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.component.html +++ /dev/null @@ -1,19 +0,0 @@ -
- -

- -
diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.component.scss b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.component.scss deleted file mode 100644 index be37ca6..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.component.scss +++ /dev/null @@ -1,11 +0,0 @@ -@import '../../tooltip.component.theme'; - -.es-tooltip { - &_purple { - @include es-tooltip-color(#9b78ff, #fff); - } - - &_marine { - @include es-tooltip-color(#3acac0, #fff); - } -} diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.component.ts b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.component.ts deleted file mode 100644 index 589669e..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.component.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Component, ChangeDetectionStrategy, ViewEncapsulation, Input } from '@angular/core'; - -@Component({ - selector: 'es-tooltip-story-theming', - templateUrl: './tooltip-story-theming.component.html', - styleUrls: ['./tooltip-story-theming.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, -}) -export class TooltipStoryThemingComponent { - @Input() public esTooltipArrow: boolean; -} diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.module.ts b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.module.ts deleted file mode 100644 index 80de664..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; - -import { MatButtonModule } from '@angular/material/button'; - -import { TooltipStoryThemingComponent } from './tooltip-story-theming.component'; - -import { ESTooltipModule } from '../..'; - -@NgModule({ - declarations: [TooltipStoryThemingComponent], - imports: [CommonModule, MatButtonModule, ESTooltipModule], - exports: [TooltipStoryThemingComponent], -}) -export class TooltipStoryThemingModule {} diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.source.ts b/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.source.ts deleted file mode 100644 index 6c491aa..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip-story-theming/tooltip-story-theming.source.ts +++ /dev/null @@ -1,32 +0,0 @@ -export const TOOLTIP_STORY_THEMING_SOURCE = { - html: ` - - - - `, - scss: ` - .es-tooltip { - &_purple { - @include es-tooltip-color(#9b78ff, #fff); - } - - &_marine { - @include es-tooltip-color(#3acac0, #fff); - } - } - `, -}; diff --git a/projects/elonkit/src/ui/tooltip/_stories_/tooltip.stories.mdx b/projects/elonkit/src/ui/tooltip/_stories_/tooltip.stories.mdx deleted file mode 100644 index ba2ce68..0000000 --- a/projects/elonkit/src/ui/tooltip/_stories_/tooltip.stories.mdx +++ /dev/null @@ -1,176 +0,0 @@ -import { Meta, Story, ArgsTable } from '@storybook/addon-docs'; -import { Canvas } from '~storybook/components'; - -import { action } from '@storybook/addon-actions'; - -import { ESTooltipModule, ESTooltipDirective } from '..'; - -import { TooltipStoryBasicModule, TooltipStoryBasicComponent, TOOLTIP_STORY_BASIC_SOURCE } from './tooltip-story-basic'; -import { - TooltipStoryInteractiveModule, - TooltipStoryInteractiveComponent, - TOOLTIP_STORY_INTERACTIVE_SOURCE, -} from './tooltip-story-interactive'; -import { TooltipStoryThemingModule, TooltipStoryThemingComponent, TOOLTIP_STORY_THEMING_SOURCE } from './tooltip-story-theming'; -import { - TooltipStoryListenersModule, - TooltipStoryListenersComponent, - TOOLTIP_STORY_LISTENERS_SOURCE, -} from './tooltip-story-listeners'; - - - -# Tooltip - -The tooltip provides a text label that is displayed when the user hovers over or longpresses an element. -This is a copy of Angular Material tooltip with added support for arrows and complex content inside a tooltip. - -## Demos - - - - {((args, context) => ({ - component: TooltipStoryBasicComponent, - moduleMetadata: { - imports: [TooltipStoryBasicModule], - }, - props: { - ...args, - }, - })).bind({})} - - - -We can place interactive content inside a tooltip. - - - - {((args, context) => ({ - component: TooltipStoryInteractiveComponent, - moduleMetadata: { - imports: [TooltipStoryInteractiveModule], - }, - props: { - ...args, - }, - })).bind({})} - - - -We can use `es-tooltip-color` mixin to easily change tooltip colors. - - - - {((args, context) => ({ - component: TooltipStoryThemingComponent, - moduleMetadata: { - imports: [TooltipStoryThemingModule], - }, - props: { - ...args, - }, - })).bind({})} - - - -We can disable open and close listeners. - - - - {((args, context) => ({ - component: TooltipStoryListenersComponent, - moduleMetadata: { - imports: [TooltipStoryListenersModule], - }, - props: { - ...args, - }, - })).bind({})} - - - -## API - -## Constants - -Injection token that can be used to configure the default options for all components within an app. - -```ts -import { ES_TOOLTIP_DEFAULT_OPTIONS } from '@elonkit/angular/ui/tooltip'; - -@NgModule({ - providers: [ - { - provide: ES_TOOLTIP_DEFAULT_OPTIONS, - useValue: { - arrow: false, - mouseAimDelay: 300 - } - } - ] -}) -``` diff --git a/projects/elonkit/src/ui/tooltip/index.ts b/projects/elonkit/src/ui/tooltip/index.ts deleted file mode 100644 index 7e1a213..0000000 --- a/projects/elonkit/src/ui/tooltip/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './public-api'; diff --git a/projects/elonkit/src/ui/tooltip/public-api.ts b/projects/elonkit/src/ui/tooltip/public-api.ts deleted file mode 100644 index 7d182c9..0000000 --- a/projects/elonkit/src/ui/tooltip/public-api.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { ESTooltipComponent } from './tooltip.component'; -export { ESTooltipDirective, ES_TOOLTIP_DEFAULT_OPTIONS, ESTooltipDefaultOptions } from './tooltip.directive'; -export { ESTooltipModule } from './tooltip.module'; diff --git a/projects/elonkit/src/ui/tooltip/tooltip.component.html b/projects/elonkit/src/ui/tooltip/tooltip.component.html deleted file mode 100644 index e361e51..0000000 --- a/projects/elonkit/src/ui/tooltip/tooltip.component.html +++ /dev/null @@ -1,24 +0,0 @@ -
-
- - - - - {{ message }} - -
- -
-
diff --git a/projects/elonkit/src/ui/tooltip/tooltip.component.scss b/projects/elonkit/src/ui/tooltip/tooltip.component.scss deleted file mode 100644 index a9c0c67..0000000 --- a/projects/elonkit/src/ui/tooltip/tooltip.component.scss +++ /dev/null @@ -1,62 +0,0 @@ -@use 'sass:math'; - -$es-tooltip-max-width: 250px; -$es-tooltip-margin: 12px; - -.es-tooltip-panel { - // The overlay reference updates the pointer-events style property directly on the HTMLElement - // depending on the state of the overlay. For tooltips the overlay panel should never enable - // pointer events. To overwrite the inline CSS from the overlay reference `!important` is needed. - pointer-events: none !important; -} - -.es-tooltip { - max-width: $es-tooltip-max-width; - padding: 8px; - margin: $es-tooltip-margin; - border-radius: 4px; - font-family: Roboto, sans-serif; - font-size: 12px; - letter-spacing: 0.4px; - line-height: 16px; - position: relative; - - &__content { - overflow: hidden; - text-overflow: ellipsis; - } - - &__arrow { - $base: 12; // Triangle base - $height: 8; // Triangle height - - $size: math.round(math.div($base, math.sqrt(2))); // Square side size - $scale: math.div($height, math.div($base, 2)); - $offset: -#{math.div($size, 2)}px; - - border-bottom-right-radius: 2px; - width: #{$size}px; - height: #{$size}px; - position: absolute; - - &_bottom { - bottom: $offset; - transform: scaleY($scale) translateX(-50%) rotate(45deg); - } - - &_left { - left: $offset; - transform: scaleX($scale) translateY(-50%) rotate(135deg); - } - - &_top { - top: $offset; - transform: scaleY($scale) translateX(-50%) rotate(225deg); - } - - &_right { - right: $offset; - transform: scaleX($scale) translateY(-50%) rotate(315deg); - } - } -} diff --git a/projects/elonkit/src/ui/tooltip/tooltip.component.theme.scss b/projects/elonkit/src/ui/tooltip/tooltip.component.theme.scss deleted file mode 100644 index 8a165d7..0000000 --- a/projects/elonkit/src/ui/tooltip/tooltip.component.theme.scss +++ /dev/null @@ -1,23 +0,0 @@ -@mixin es-tooltip-color($background, $color, $blur: false) { - background: $background; - color: $color; - - @if $blur { - backdrop-filter: blur($blur); - } - - // stylelint-disable-next-line selector-class-pattern - .es-tooltip__arrow { - background: linear-gradient(-45deg, $background 50%, transparent 50%); - } -} - -@mixin es-tooltip-theme($theme, $es-theme) { - .es-tooltip { - @include es-tooltip-color( - mat.get-color-from-palette(map-get($es-theme, mono-a), A600), - mat.get-color-from-palette(map-get($es-theme, mono-b), 500), - 40px - ); - } -} diff --git a/projects/elonkit/src/ui/tooltip/tooltip.component.ts b/projects/elonkit/src/ui/tooltip/tooltip.component.ts deleted file mode 100644 index d3a6b5e..0000000 --- a/projects/elonkit/src/ui/tooltip/tooltip.component.ts +++ /dev/null @@ -1,348 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - * - * - * Copyright Elonsoft LTD All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file - */ - -import { - ChangeDetectionStrategy, - ChangeDetectorRef, - Component, - OnDestroy, - ViewEncapsulation, - HostListener, - ElementRef, - HostBinding, - TemplateRef, -} from '@angular/core'; - -import { DomSanitizer } from '@angular/platform-browser'; -import { AnimationEvent } from '@angular/animations'; - -import { ESCAPE, hasModifierKey } from '@angular/cdk/keycodes'; -import { FocusMonitor } from '@angular/cdk/a11y'; -import { getNextFocusableElement } from '../../cdk/a11y'; - -import { matTooltipAnimations, TooltipVisibility } from '@angular/material/tooltip'; - -import { Subject } from 'rxjs'; - -import { ESTooltipDirective } from './tooltip.directive'; -import { ESTooltipService } from './tooltip.service'; - -@Component({ - selector: 'es-tooltip-component', - templateUrl: './tooltip.component.html', - styleUrls: ['./tooltip.component.scss'], - encapsulation: ViewEncapsulation.None, - changeDetection: ChangeDetectionStrategy.OnPush, - animations: [matTooltipAnimations.tooltipState], -}) -export class ESTooltipComponent implements OnDestroy { - @HostBinding('style.zoom') public get zoom() { - return this.sanitizer.bypassSecurityTrustStyle(this.visibility === 'visible' ? '1' : ''); - } - - @HostBinding('style.pointer-events') public get pointerEvents() { - return this.sanitizer.bypassSecurityTrustStyle(this.interactive ? 'auto' : ''); - } - - @HostListener('body:click', ['$event']) public onBodyClick(event: Event) { - if (this.disableCloseClickListener) { - return; - } - - const isContainer = - this.elementRef.nativeElement.contains(event.target as HTMLElement) || - this.parentElementRef.nativeElement.contains(event.target as HTMLElement); - - if ((true || this.closeOnInteraction) && !(this.interactive && isContainer)) { - this.hide(0); - } - } - - @HostListener('document:keydown', ['$event']) public onKeyDown(event: KeyboardEvent) { - // tslint:disable-next-line:deprecation - if (event.keyCode === ESCAPE && !hasModifierKey(event)) { - event.preventDefault(); - event.stopPropagation(); - - this.hide(0); - this.focusMonitor.focusVia(this.parentElementRef, 'program'); - } - } - - @HostListener('mouseenter') public onMouseEnter() { - this.parent.cancelPossiblyHide(); - } - - @HostListener('mouseleave', ['$event']) public onMouseLeave(event: MouseEvent) { - if (this.disableCloseHoverListener) { - return; - } - - if (this.interactive && event.relatedTarget !== this.parentElementRef.nativeElement) { - this.hide(0); - } - } - - @HostListener('focusout', ['$event']) public onFocusOut(event: FocusEvent) { - if (this.disableCloseFocusListener) { - return; - } - - // Timeout for correct document.hasFocus detection - setTimeout(() => { - if (this.interactive) { - if ( - document.hasFocus() && - (!event.relatedTarget || - (event.relatedTarget && this.elementRef.nativeElement.contains(event.relatedTarget as HTMLElement))) && - this.elementRef.nativeElement.contains(event.target as HTMLElement) - ) { - return; - } - - const isPrev = - event.relatedTarget && (event.target as HTMLElement).compareDocumentPosition(event.relatedTarget as HTMLElement) === 2; - - if (isPrev) { - this.parentElementRef.nativeElement.focus(); - } else { - this.hide(0); - const element = getNextFocusableElement(this.parentElementRef.nativeElement); - if (element) { - element.focus(); - } - } - } else { - this.hide(0); - } - }); - } - - /** - * @internal - * @ignore - * Message to display in the tooltip. - */ - public message?: string; - - /** - * @internal - * @ignore - * Content to display in the tooltip. - */ - public content?: TemplateRef; - - /** - * @internal - * @ignore - * Wheter the tooltip interactive. - */ - public interactive: boolean; - - /** - * @internal - * @ignore - * The arrow postition. - */ - public arrow: { position: string; offsetX?: number; offsetY?: number } | null = null; - - /** - * @internal - * @ignore - * Do not respond to focus events. - */ - public disableCloseFocusListener = false; - - /** - * @internal - * @ignore - * Do not respond to hover events. - */ - public disableCloseHoverListener = false; - - /** - * @internal - * @ignore - * Do not respond to backdrop click events. - */ - public disableCloseClickListener = false; - - /** - * @internal - * @ignore - * Directive's host element class instance. - */ - public parent: ESTooltipDirective; - - /** - * @internal - * @ignore - * Directive's host element reference. - */ - public parentElementRef: ElementRef; - - /** - * @internal - * @ignore - * Classes to be added to the tooltip. Supports the same syntax as `ngClass`. - */ - public tooltipClass: string | string[] | Set | { [key: string]: any }; - - /** - * @internal - * @ignore - * The timeout ID of any current timer set to show the tooltip. - */ - public showTimeoutId: number | null | ReturnType; - - /** - * @internal - * @ignore - * The timeout ID of any current timer set to hide the tooltip. - */ - public hideTimeoutId: number | null | ReturnType; - - /** - * @internal - * @ignore - * Property watched by the animation framework to show or hide the tooltip. - */ - public visibility: TooltipVisibility = 'initial'; - - /** - * Whether interactions on the page should close the tooltip - */ - private closeOnInteraction = false; - - /** - * Subject for notifying that the tooltip has been hidden from the view. - */ - private readonly onHide$ = new Subject(); - - /** - * @internal - * @ignore - */ - constructor( - private changeDetector: ChangeDetectorRef, - private sanitizer: DomSanitizer, - private focusMonitor: FocusMonitor, - private tooltipService: ESTooltipService, - /** - * @internal - */ - public elementRef: ElementRef - ) {} - - /** - * @ignore - */ - public ngOnDestroy() { - this.onHide$.complete(); - } - - /** - * Shows the tooltip with an animation originating from the provided origin. - * @param delay Amount of milliseconds to the delay showing the tooltip. - */ - public show(delay: number) { - // Cancel the delayed hide if it is scheduled - if (this.hideTimeoutId) { - clearTimeout(this.hideTimeoutId); - this.hideTimeoutId = null; - } - - // Body interactions should cancel the tooltip if there is a delay in showing. - this.closeOnInteraction = true; - this.showTimeoutId = setTimeout(() => { - this.visibility = 'visible'; - this.showTimeoutId = null; - - // Mark for check so if any parent component has set the - // ChangeDetectionStrategy to OnPush it will be checked anyways - this.markForCheck(); - }, delay); - } - - /** - * Begins the animation to hide the tooltip after the provided delay in ms. - * @param delay Amount of milliseconds to delay showing the tooltip. - */ - public hide = (delay = 0) => { - // Cancel the delayed show if it is scheduled - if (this.showTimeoutId) { - clearTimeout(this.showTimeoutId); - this.showTimeoutId = null; - } - - this.hideTimeoutId = setTimeout(() => { - this.visibility = 'hidden'; - this.hideTimeoutId = null; - - // Mark for check so if any parent component has set the - // ChangeDetectionStrategy to OnPush it will be checked anyways - this.markForCheck(); - }, delay); - }; - - /** - * Returns an observable that notifies when the tooltip has been hidden from view. - */ - public afterHidden() { - return this.onHide$.asObservable(); - } - - /** - * Whether the tooltip is being displayed. - */ - public isVisible() { - return this.visibility === 'visible'; - } - - /** - * @internal - * @ignore - */ - public animationStart() { - this.closeOnInteraction = false; - } - - /** - * @internal - * @ignore - */ - public animationDone(event: AnimationEvent) { - const toState = event.toState as TooltipVisibility; - - if (toState === 'hidden' && !this.isVisible()) { - this.onHide$.next(); - this.tooltipService.closed$.next(); - } - - if (toState === 'visible' || toState === 'hidden') { - this.closeOnInteraction = true; - } - } - - /** - * @internal - * @ignore - * Marks that the tooltip needs to be checked in the next change detection run. - * Mainly used for rendering the initial text before positioning a tooltip, which - * can be problematic in components with OnPush change detection. - */ - public markForCheck() { - this.changeDetector.markForCheck(); - } -} diff --git a/projects/elonkit/src/ui/tooltip/tooltip.directive.ts b/projects/elonkit/src/ui/tooltip/tooltip.directive.ts deleted file mode 100644 index 1e46eaa..0000000 --- a/projects/elonkit/src/ui/tooltip/tooltip.directive.ts +++ /dev/null @@ -1,1019 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - * - * - * Copyright Elonsoft LTD All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file - */ - -import { - Directive, - ElementRef, - Inject, - Input, - NgZone, - OnDestroy, - Optional, - InjectionToken, - ViewContainerRef, - AfterViewInit, - HostBinding, - HostListener, - TemplateRef, -} from '@angular/core'; - -import { AriaDescriber, FocusMonitor } from '@angular/cdk/a11y'; -import { getInnerFocusableElement } from '../../cdk/a11y'; - -import { Directionality } from '@angular/cdk/bidi'; -import { BooleanInput, coerceBooleanProperty, NumberInput } from '@angular/cdk/coercion'; -import { ESCAPE, hasModifierKey } from '@angular/cdk/keycodes'; -import { - FlexibleConnectedPositionStrategy, - HorizontalConnectionPos, - OriginConnectionPosition, - Overlay, - OverlayConnectionPosition, - OverlayRef, - ScrollStrategy, - VerticalConnectionPos, - ConnectedOverlayPositionChange, -} from '@angular/cdk/overlay'; -import { Platform, normalizePassiveListenerOptions } from '@angular/cdk/platform'; -import { ComponentPortal } from '@angular/cdk/portal'; -import { ScrollDispatcher } from '@angular/cdk/scrolling'; - -import { - TooltipPosition, - TooltipTouchGestures, - getMatTooltipInvalidPositionError, - MAT_TOOLTIP_SCROLL_STRATEGY, - MAT_TOOLTIP_DEFAULT_OPTIONS, - MatTooltipDefaultOptions, -} from '@angular/material/tooltip'; - -import { Subject } from 'rxjs'; -import { take, takeUntil, delay as delayPipe } from 'rxjs/operators'; - -import { ESTooltipComponent } from './tooltip.component'; -import { ESTooltipService } from './tooltip.service'; - -/** CSS class that will be attached to the overlay panel. */ -const TOOLTIP_PANEL_CLASS = 'es-tooltip-panel'; - -/** Margin of .es-tooltip container */ -const TOOLTIP_MARGIN = 12; - -/** Options used to bind passive event listeners. */ -const passiveListenerOptions = normalizePassiveListenerOptions({ passive: true }); - -/** - * Time between the user putting the pointer on a tooltip - * trigger and the long press event being fired. - */ -const LONGPRESS_DELAY = 500; - -/** - * Number of past mouse locations to track. - */ -const MOUSE_LOCATIONS_TRACKED = 3; - -/** - * Delay in ms before closing a tooltip when mouse moves towards the component. - */ -const MOUSE_AIM_DELAY = 300; - -export interface ESTooltipDefaultOptions { - arrow?: boolean; - mouseAimDelay?: number; -} - -export const ES_TOOLTIP_DEFAULT_OPTIONS = new InjectionToken('ES_TOOLTIP_DEFAULT_OPTIONS'); - -interface ESTooltipMouseLocation { - x: number; - y: number; -} - -function slope(a: ESTooltipMouseLocation, b: ESTooltipMouseLocation) { - return (b.y - a.y) / (b.x - a.x); -} - -@Directive({ - selector: '[esTooltip]', - exportAs: 'esTooltip', -}) -export class ESTooltipDirective implements OnDestroy, AfterViewInit { - @HostBinding('class.es-tooltip-trigger') public class = true; - - @HostListener('document:mousemove', ['$event']) public onMouseMove(event: MouseEvent) { - this.mouseLocations.push({ x: event.pageX, y: event.pageY }); - - if (this.mouseLocations.length > MOUSE_LOCATIONS_TRACKED) { - this.mouseLocations.shift(); - } - } - - @HostListener('focusout', ['$event']) public onFocusOut(event: FocusEvent) { - if (this.disableFocusListener) { - return; - } - - if (this.tooltipInstance) { - if (this.interactive) { - const isNext = - event.relatedTarget && (event.target as HTMLElement).compareDocumentPosition(event.relatedTarget as HTMLElement) === 4; - - const element = getInnerFocusableElement(this.tooltipInstance.elementRef.nativeElement); - - if (isNext && element) { - (element as HTMLElement).focus(); - } else if (event.relatedTarget) { - this.hide(0); - } - } else { - this.hide(0); - } - } - } - - private _position: TooltipPosition = 'below'; - - /** - * Allows the user to define the position of the tooltip relative to the parent element. - */ - @Input('esTooltipPosition') - public get position(): TooltipPosition { - return this._position; - } - public set position(value: TooltipPosition) { - if (value !== this._position) { - this._position = value; - - if (this.overlayRef) { - this.updatePosition(); - - if (this.tooltipInstance) { - this.tooltipInstance.show(0); - } - - this.overlayRef.updatePosition(); - } - } - } - - private _disabled = false; - - /** - * Disables the display of the tooltip. - */ - @Input('esTooltipDisabled') - public get disabled() { - return this._disabled; - } - public set disabled(value: any) { - this._disabled = coerceBooleanProperty(value); - - // If tooltip is disabled, hide immediately. - if (this._disabled) { - this.hide(0); - } else { - this.setupPointerEvents(); - } - } - - /** - * The default delay in ms before showing the tooltip after show is called. - */ - // tslint:disable-next-line:no-input-rename - @Input('esTooltipShowDelay') public showDelay: number = this.defaultOptions?.showDelay; - - /** - * The default delay in ms before hiding the tooltip after hide is called. - */ - // tslint:disable-next-line:no-input-rename - @Input('esTooltipHideDelay') public hideDelay: number = this.defaultOptions?.hideDelay; - - /** - * Delay in ms before closing a tooltip when mouse stops moving towards the tooltip. - */ - // tslint:disable-next-line:no-input-rename - @Input('esTooltipMouseAimDelay') public mouseAimDelay: number = this.esDefaultOptions?.mouseAimDelay || MOUSE_AIM_DELAY; - - /** - * How touch gestures should be handled by the tooltip. On touch devices the tooltip directive - * uses a long press gesture to show and hide, however it can conflict with the native browser - * gestures. To work around the conflict, Angular Material disables native gestures on the - * trigger, but that might not be desirable on particular elements (e.g. inputs and draggable - * elements). The different values for this option configure the touch event handling as follows: - * - auto - Enables touch gestures for all elements, but tries to avoid conflicts with native - * browser gestures on particular elements. In particular, it allows text selection on inputs and - * textareas, and preserves the native browser dragging on elements marked as draggable. - * - on - Enables touch gestures for all elements and disables native browser gestures with no - * exceptions. - * - off - Disables touch gestures. Note that this will prevent the tooltip from showing on touch - * devices. - */ - // tslint:disable-next-line:no-input-rename - @Input('esTooltipTouchGestures') public touchGestures: TooltipTouchGestures = 'auto'; - - private _arrow = this.esDefaultOptions?.arrow ?? false; - - /** - * If true, adds an arrow to the tooltip. - */ - @Input('esTooltipArrow') - public get arrow() { - return this._arrow; - } - public set arrow(value: any) { - this._arrow = coerceBooleanProperty(value); - } - - private _interactive = false; - - /** - * Makes a tooltip interactive, i.e. will not close when the user hovers over the tooltip. - */ - @Input('esTooltipInteractive') - public get interactive() { - return this._interactive; - } - public set interactive(value: any) { - this._interactive = coerceBooleanProperty(value); - } - - private _content: TemplateRef; - - /** - * Template to display instead of the message. - */ - @Input('esTooltipContent') - public get content() { - return this._content; - } - public set content(value) { - if (this.message) { - this.ariaDescriber.removeDescription(this.elementRef.nativeElement, this._message); - } - - this._content = value; - - if (!(this.message || this._content) && this.isTooltipVisible()) { - this.hide(0); - } else { - this.setupPointerEvents(); - this.updateTooltipMessage(); - if (this.message) { - this.ngZone.runOutsideAngular(() => { - Promise.resolve().then(() => { - this.ariaDescriber.describe(this.elementRef.nativeElement, this.message); - }); - }); - } - } - } - - private _message = ''; - - /** - * The message to be displayed in the tooltip. - */ - @Input('esTooltip') - public get message() { - return this._message; - } - public set message(value: string) { - if (this._message) { - this.ariaDescriber.removeDescription(this.elementRef.nativeElement, this._message); - } - - // If the message is not a string (e.g. number), convert it to a string and trim it. - this._message = value != null ? `${value}`.trim() : ''; - - if (!(this._message || this.content) && this.isTooltipVisible()) { - this.hide(0); - } else { - this.setupPointerEvents(); - this.updateTooltipMessage(); - this.ngZone.runOutsideAngular(() => { - // The `AriaDescriber` has some functionality that avoids adding a description if it's the - // same as the `aria-label` of an element, however we can't know whether the tooltip trigger - // has a data-bound `aria-label` or when it'll be set for the first time. We can avoid the - // issue by deferring the description by a tick so Angular has time to set the `aria-label`. - Promise.resolve().then(() => { - this.ariaDescriber.describe(this.elementRef.nativeElement, this.message); - }); - }); - } - } - - private _tooltipClass: string | string[] | Set | { [key: string]: any }; - - /** Classes to be passed to the tooltip. Supports the same syntax as `ngClass`. */ - @Input('esTooltipClass') - public get tooltipClass() { - return this._tooltipClass; - } - public set tooltipClass(value: string | string[] | Set | { [key: string]: any }) { - this._tooltipClass = value; - if (this.tooltipInstance) { - this.setTooltipClass(this._tooltipClass); - } - } - - /** - * Do not respond to focus events. - */ - // tslint:disable-next-line:no-input-rename - @Input('esTooltipDisableFocusListener') public disableFocusListener = false; - - /** - * Do not respond to hover events. - */ - // tslint:disable-next-line:no-input-rename - @Input('esTooltipDisableHoverListener') public disableHoverListener = false; - - /** - * Do not respond to focus events after tooltip is opened. - */ - // tslint:disable-next-line:no-input-rename - @Input('esTooltipDisableCloseFocusListener') public disableCloseFocusListener: boolean; - - /** - * Do not respond to hover events after tooltip is opened. - */ - // tslint:disable-next-line:no-input-rename - @Input('esTooltipDisableCloseHoverListener') public disableCloseHoverListener: boolean; - - /** - * Do not respond to body click events. - */ - // tslint:disable-next-line:no-input-rename - @Input('esTooltipDisableCloseClickListener') public disableCloseClickListener = false; - - /** - * @internal - * @ignore - */ - public overlayRef: OverlayRef | null; - - /** - * @internal - * @ignore - */ - public tooltipInstance: ESTooltipComponent | null; - - private portal: ComponentPortal; - - private scrollStrategy: () => ScrollStrategy; - private viewInitialized = false; - - private isHovered = false; - private mouseLocations: Array = []; - private mouseLastDelayLocation: ESTooltipMouseLocation | null; - private mouseMoveTimeoutId: number | ReturnType; - - private overlayPosition: 'right' | 'left' | 'top' | 'bottom'; - - /** - * Manually-bound passive event listeners. - */ - private passiveListeners = new Map(); - - /** - * Timer started at the last `touchstart` event. - */ - private touchstartTimeout: number | ReturnType; - - /** - * Emits when the component is destroyed. - */ - private readonly destroyed$ = new Subject(); - - /** - * @internal - * @ignore - */ - constructor( - private overlay: Overlay, - private elementRef: ElementRef, - private scrollDispatcher: ScrollDispatcher, - private viewContainerRef: ViewContainerRef, - private ngZone: NgZone, - private platform: Platform, - private ariaDescriber: AriaDescriber, - private focusMonitor: FocusMonitor, - private tooltipService: ESTooltipService, - @Inject(MAT_TOOLTIP_SCROLL_STRATEGY) scrollStrategy: any, - @Optional() private dir: Directionality, - @Optional() - @Inject(MAT_TOOLTIP_DEFAULT_OPTIONS) - private defaultOptions: MatTooltipDefaultOptions, - @Optional() - @Inject(ES_TOOLTIP_DEFAULT_OPTIONS) - private esDefaultOptions: ESTooltipDefaultOptions - ) { - this.scrollStrategy = scrollStrategy; - - if (defaultOptions) { - if (defaultOptions.position) { - this.position = defaultOptions.position; - } - - if (defaultOptions.touchGestures) { - this.touchGestures = defaultOptions.touchGestures; - } - } - - ngZone.runOutsideAngular(() => { - elementRef.nativeElement.addEventListener('keydown', this.onKeyDown); - }); - } - - /** - * @ignore - */ - public ngAfterViewInit() { - // This needs to happen after view init so the initial values for all inputs have been set. - this.viewInitialized = true; - this.setupPointerEvents(); - - this.focusMonitor - .monitor(this.elementRef) - .pipe(takeUntil(this.destroyed$)) - .subscribe((origin) => { - if (this.disableFocusListener) { - return; - } - // Note that the focus monitor runs outside the Angular zone. - if (origin === 'keyboard') { - this.ngZone.run(() => this.show()); - } - }); - } - - /** - * @ignore - * Dispose the tooltip when destroyed. - */ - public ngOnDestroy() { - const nativeElement = this.elementRef.nativeElement; - - clearTimeout(this.touchstartTimeout); - - if (this.overlayRef) { - this.overlayRef.dispose(); - this.tooltipInstance = null; - } - - // Clean up the event listeners set in the constructor - nativeElement.removeEventListener('keydown', this.onKeyDown); - this.passiveListeners.forEach((listener, event) => { - nativeElement.removeEventListener(event, listener, passiveListenerOptions); - }); - this.passiveListeners.clear(); - - this.destroyed$.next(); - this.destroyed$.complete(); - - this.ariaDescriber.removeDescription(nativeElement, this.message); - this.focusMonitor.stopMonitoring(nativeElement); - } - - /** - * Shows the tooltip after the delay in ms, defaults to tooltip-delay-show or 0ms if no input. - */ - public show(delay: number = this.showDelay): void { - if ( - this.disabled || - !(this.message || this.content) || - (this.isTooltipVisible() && !this.tooltipInstance?.showTimeoutId && !this.tooltipInstance?.hideTimeoutId) - ) { - return; - } - - const overlayRef = this.createOverlay(); - this.detach(); - this.portal = this.portal || new ComponentPortal(ESTooltipComponent, this.viewContainerRef); - this.tooltipInstance = overlayRef.attach(this.portal).instance; - this.tooltipInstance - .afterHidden() - .pipe(takeUntil(this.destroyed$)) - .subscribe(() => this.detach()); - this.setTooltipClass(this._tooltipClass); - this.tooltipInstance.parent = this; - this.tooltipInstance.parentElementRef = this.elementRef; - this.tooltipInstance.interactive = this.interactive; - - this.tooltipInstance.disableCloseFocusListener = this.disableCloseFocusListener ?? this.disableFocusListener; - this.tooltipInstance.disableCloseHoverListener = this.disableCloseHoverListener ?? this.disableHoverListener; - this.tooltipInstance.disableCloseClickListener = this.disableCloseClickListener; - - this.updateTooltipMessage(); - this.tooltipInstance.show(delay); - } - - /** - * Hides the tooltip after the delay in ms, defaults to tooltip-delay-hide or 0ms if no input. - */ - public hide(delay: number = this.hideDelay) { - if (this.tooltipInstance) { - this.cancelPossiblyHide(); - this.tooltipInstance.hide(delay); - } - } - - /** - * Shows/hides the tooltip. - */ - public toggle() { - this.isTooltipVisible() ? this.hide() : this.show(); - } - - /** - * Returns true if the tooltip is currently visible to the user. - */ - public isTooltipVisible() { - return !!this.tooltipInstance && this.tooltipInstance.isVisible(); - } - - /** - * Handles the keydown events on the host element. - * Needs to be an arrow function so that we can use it in addEventListener. - */ - private onKeyDown = (event: KeyboardEvent) => { - // tslint:disable-next-line:deprecation - if (this.isTooltipVisible() && event.keyCode === ESCAPE && !hasModifierKey(event)) { - event.preventDefault(); - event.stopPropagation(); - this.ngZone.run(() => this.hide(0)); - } - }; - - /** - * Create the overlay config and position strategy. - */ - private createOverlay(): OverlayRef { - if (this.overlayRef) { - return this.overlayRef; - } - - const scrollableAncestors = this.scrollDispatcher.getAncestorScrollContainers(this.elementRef); - - // Create connected position strategy that listens for scroll events to reposition. - const strategy = this.overlay - .position() - .flexibleConnectedTo(this.elementRef) - .withTransformOriginOn('.es-tooltip') - .withFlexibleDimensions(false) - .withViewportMargin(8) - .withScrollableContainers(scrollableAncestors); - - strategy.positionChanges.pipe(takeUntil(this.destroyed$)).subscribe((change) => { - if (this.tooltipInstance) { - if (change.scrollableViewProperties.isOverlayClipped && this.tooltipInstance.isVisible()) { - // After position changes occur and the overlay is clipped by - // a parent scrollable then close the tooltip. - this.ngZone.run(() => this.hide(0)); - } else { - this.updateTooltipArrowPosition(change); - } - } - }); - - this.overlayRef = this.overlay.create({ - direction: this.dir, - positionStrategy: strategy, - panelClass: TOOLTIP_PANEL_CLASS, - scrollStrategy: this.scrollStrategy(), - }); - - this.updatePosition(); - - this.overlayRef - .detachments() - .pipe(takeUntil(this.destroyed$)) - .subscribe(() => this.detach()); - - return this.overlayRef; - } - - /** - * Detaches the currently-attached tooltip. - */ - private detach() { - if (this.overlayRef && this.overlayRef.hasAttached()) { - this.overlayRef.detach(); - } - - this.tooltipInstance = null; - } - - /** - * Updates the position of the current tooltip. - */ - private updatePosition() { - const position = this.overlayRef?.getConfig().positionStrategy as FlexibleConnectedPositionStrategy; - const origin = this.getOrigin(); - const overlay = this.getOverlayPosition(); - - position.withPositions([ - { ...origin.main, ...overlay.main }, - { ...origin.fallback, ...overlay.fallback }, - ]); - } - - /** - * @internal - * @ignore - * Returns the origin position and a fallback position based on the user's position preference. - * The fallback position is the inverse of the origin (e.g. `'below' -> 'above'`). - */ - public getOrigin(): { main: OriginConnectionPosition; fallback: OriginConnectionPosition } { - const isLtr = !this.dir || this.dir.value === 'ltr'; - const position = this.position; - let originPosition: OriginConnectionPosition; - - if (position === 'above' || position === 'below') { - originPosition = { originX: 'center', originY: position === 'above' ? 'top' : 'bottom' }; - } else if (position === 'before' || (position === 'left' && isLtr) || (position === 'right' && !isLtr)) { - originPosition = { originX: 'start', originY: 'center' }; - } else if (position === 'after' || (position === 'right' && isLtr) || (position === 'left' && !isLtr)) { - originPosition = { originX: 'end', originY: 'center' }; - } else { - throw getMatTooltipInvalidPositionError(position); - } - - const { x, y } = this.invertPosition(originPosition.originX, originPosition.originY); - - return { - main: originPosition, - fallback: { originX: x, originY: y }, - }; - } - - /** - * @internal - * @ignore - * Returns the overlay position and a fallback position based on the user's preference. - */ - public getOverlayPosition(): { - main: OverlayConnectionPosition; - fallback: OverlayConnectionPosition; - } { - const isLtr = !this.dir || this.dir.value === 'ltr'; - const position = this.position; - let overlayPosition: OverlayConnectionPosition; - - if (position === 'above') { - overlayPosition = { overlayX: 'center', overlayY: 'bottom' }; - } else if (position === 'below') { - overlayPosition = { overlayX: 'center', overlayY: 'top' }; - } else if (position === 'before' || (position === 'left' && isLtr) || (position === 'right' && !isLtr)) { - overlayPosition = { overlayX: 'end', overlayY: 'center' }; - } else if (position === 'after' || (position === 'right' && isLtr) || (position === 'left' && !isLtr)) { - overlayPosition = { overlayX: 'start', overlayY: 'center' }; - } else { - throw getMatTooltipInvalidPositionError(position); - } - - const { x, y } = this.invertPosition(overlayPosition.overlayX, overlayPosition.overlayY); - - return { - main: overlayPosition, - fallback: { overlayX: x, overlayY: y }, - }; - } - - /** - * Updates the tooltip message and repositions the overlay according to the new message length. - */ - private updateTooltipMessage() { - // Must wait for the message to be painted to the tooltip so that the overlay can properly - // calculate the correct positioning based on the size of the text. - if (this.tooltipInstance) { - this.tooltipInstance.message = this.message; - this.tooltipInstance.content = this.content; - this.tooltipInstance.markForCheck(); - - this.ngZone.onMicrotaskEmpty - .asObservable() - .pipe(take(1), takeUntil(this.destroyed$)) - .subscribe(() => { - if (this.tooltipInstance) { - this.overlayRef?.updatePosition(); - } - }); - } - } - - /** - * Updates the arrow position. - */ - private updateTooltipArrowPosition(change: ConnectedOverlayPositionChange) { - if (this.arrow && this.tooltipInstance) { - const rect = this.elementRef.nativeElement.getBoundingClientRect(); - const rectTooltip = this.tooltipInstance.elementRef.nativeElement.getBoundingClientRect(); - - const diffX = rect.left - rectTooltip.left - TOOLTIP_MARGIN; - const diffY = rect.top - rectTooltip.top - TOOLTIP_MARGIN; - - const offsetX = Math.ceil(diffX + this.elementRef.nativeElement.clientWidth / 2); - const offsetY = Math.ceil(diffY + this.elementRef.nativeElement.clientHeight / 2); - - if (change.connectionPair.originX === 'end') { - this.overlayPosition = 'right'; - this.tooltipInstance.arrow = { - position: 'left', - offsetY, - }; - } else if (change.connectionPair.originX === 'start') { - this.overlayPosition = 'left'; - this.tooltipInstance.arrow = { - position: 'right', - offsetY, - }; - } else if (change.connectionPair.originY === 'top') { - this.overlayPosition = 'top'; - this.tooltipInstance.arrow = { - position: 'bottom', - offsetX, - }; - } else if (change.connectionPair.originY === 'bottom') { - this.overlayPosition = 'bottom'; - this.tooltipInstance.arrow = { - position: 'top', - offsetX, - }; - } - - this.tooltipInstance.markForCheck(); - } - } - - /** - * Updates the tooltip class. - */ - private setTooltipClass(tooltipClass: string | string[] | Set | { [key: string]: any }) { - if (this.tooltipInstance) { - this.tooltipInstance.tooltipClass = tooltipClass; - this.tooltipInstance.markForCheck(); - } - } - - /** - * Inverts an overlay position. - */ - private invertPosition(x: HorizontalConnectionPos, y: VerticalConnectionPos) { - if (this.position === 'above' || this.position === 'below') { - if (y === 'top') { - y = 'bottom'; - } else if (y === 'bottom') { - y = 'top'; - } - } else { - if (x === 'end') { - x = 'start'; - } else if (x === 'start') { - x = 'end'; - } - } - - return { x, y }; - } - - /** - * Binds the pointer events to the tooltip trigger. - */ - private setupPointerEvents() { - // Optimization: Defer hooking up events if there's no message or the tooltip is disabled. - if (this._disabled || !(this.message || this.content) || !this.viewInitialized || this.passiveListeners.size) { - return; - } - - const onMouseEnter = () => { - this.isHovered = true; - - if (this.disableHoverListener) { - return; - } - - const tooltip = document.querySelector('.es-tooltip'); - if (tooltip) { - this.tooltipService.closed$.pipe(take(1), delayPipe(1)).subscribe(() => { - if (this.isHovered) { - onMouseEnter(); - } - }); - - return; - } - - this.show(); - }; - - // The mouse events shouldn't be bound on mobile devices, because they can prevent the - // first tap from firing its click event or can cause the tooltip to open for clicks. - if (!this.platform.IOS && !this.platform.ANDROID) { - this.passiveListeners.set('mouseenter', onMouseEnter).set('mouseleave', () => { - this.isHovered = false; - - if (this.disableCloseHoverListener ?? this.disableHoverListener) { - return; - } - - if (this.interactive) { - if (this.tooltipInstance) { - this.possiblyHide(); - } - } else { - this.hide(); - } - }); - } else if (this.touchGestures !== 'off') { - this.disableNativeGesturesIfNecessary(); - const touchendListener = () => { - clearTimeout(this.touchstartTimeout); - this.hide(this.defaultOptions.touchendHideDelay); - }; - - this.passiveListeners - .set('touchend', touchendListener) - .set('touchcancel', touchendListener) - .set('touchstart', () => { - // Note that it's important that we don't `preventDefault` here, - // because it can prevent click events from firing on the element. - clearTimeout(this.touchstartTimeout); - this.touchstartTimeout = setTimeout(() => this.show(), LONGPRESS_DELAY); - }); - } - - this.passiveListeners.forEach((listener, event) => { - this.elementRef.nativeElement.addEventListener(event, listener, passiveListenerOptions); - }); - } - - /** - * Disables the native browser gestures, based on how the tooltip has been configured. - */ - private disableNativeGesturesIfNecessary() { - const element = this.elementRef.nativeElement; - const style = element.style; - const gestures = this.touchGestures; - - if (gestures !== 'off') { - // If gestures are set to `auto`, we don't disable text selection on inputs and - // textareas, because it prevents the user from typing into them on iOS Safari. - if (gestures === 'on' || (element.nodeName !== 'INPUT' && element.nodeName !== 'TEXTAREA')) { - style.userSelect = (style as any).msUserSelect = style.webkitUserSelect = (style as any).MozUserSelect = 'none'; - } - - // If we have `auto` gestures and the element uses native HTML dragging, - // we don't set `-webkit-user-drag` because it prevents the native behavior. - if (gestures === 'on' || !element.draggable) { - (style as any).webkitUserDrag = 'none'; - } - - style.touchAction = 'none'; - (style as any).webkitTapHighlightColor = 'transparent'; - } - } - - public cancelPossiblyHide = () => { - if (this.mouseMoveTimeoutId) { - clearTimeout(this.mouseMoveTimeoutId); - } - }; - - private possiblyHide = () => { - const delay = this.getHideDelay(); - - if (delay) { - this.mouseMoveTimeoutId = setTimeout(() => { - this.possiblyHide(); - }, delay); - } else { - this.hide(0); - } - }; - - private getHideDelay = () => { - const tooltip = this.tooltipInstance?.elementRef.nativeElement; - if (tooltip) { - const tooltipRect = tooltip.getBoundingClientRect(); - - const offset = { - top: tooltipRect.top + window.scrollY, - left: tooltipRect.left + window.scrollX, - }; - - const upperLeft = { - x: offset.left, - y: offset.top, - }; - const upperRight = { - x: offset.left + tooltip.offsetWidth, - y: upperLeft.y, - }; - const lowerLeft = { - x: offset.left, - y: offset.top + tooltip.offsetHeight, - }; - const lowerRight = { - x: offset.left + tooltip.offsetWidth, - y: lowerLeft.y, - }; - - const location = this.mouseLocations[this.mouseLocations.length - 1]; - let previousLocation = this.mouseLocations[0]; - - if (!location) { - return 0; - } - - if (!previousLocation) { - previousLocation = location; - } - - if ( - this.mouseLastDelayLocation && - location.x === this.mouseLastDelayLocation.x && - location.y === this.mouseLastDelayLocation.y - ) { - // If the mouse hasn't moved since the last time we checked, immediately hide. - return 0; - } - - let decreasingCorner = upperLeft; - let increasingCorner = lowerLeft; - - if (this.overlayPosition === 'left') { - decreasingCorner = lowerRight; - increasingCorner = upperRight; - } else if (this.overlayPosition === 'bottom') { - decreasingCorner = upperRight; - increasingCorner = upperLeft; - } else if (this.overlayPosition === 'top') { - decreasingCorner = lowerLeft; - increasingCorner = lowerRight; - } - - const decreasingSlope = slope(location, decreasingCorner); - const increasingSlope = slope(location, increasingCorner); - const prevDecreasingSlope = slope(previousLocation, decreasingCorner); - const prevIncreasingSlope = slope(previousLocation, increasingCorner); - - if (decreasingSlope < prevDecreasingSlope && increasingSlope > prevIncreasingSlope) { - this.mouseLastDelayLocation = location; - return this.mouseAimDelay; - } - - this.mouseLastDelayLocation = null; - return 0; - } - return 0; - }; - - /** - * @internal - * @ignore - */ - public static ngAcceptInputType_disabled: BooleanInput; - - /** - * @internal - * @ignore - */ - public static ngAcceptInputType_hideDelay: NumberInput; - - /** - * @internal - * @ignore - */ - public static ngAcceptInputType_showDelay: NumberInput; - - /** - * @internal - * @ignore - */ - public static ngAcceptInputType_mouseAimDelay: NumberInput; - - /** - * @internal - * @ignore - */ - public static ngAcceptInputType_interactive: BooleanInput; - - /** - * @internal - * @ignore - */ - public static ngAcceptInputType_arrow: BooleanInput; -} diff --git a/projects/elonkit/src/ui/tooltip/tooltip.module.ts b/projects/elonkit/src/ui/tooltip/tooltip.module.ts deleted file mode 100644 index daee8ad..0000000 --- a/projects/elonkit/src/ui/tooltip/tooltip.module.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; - -import { A11yModule } from '@angular/cdk/a11y'; -import { OverlayModule } from '@angular/cdk/overlay'; -import { CdkScrollableModule } from '@angular/cdk/scrolling'; - -import { MatCommonModule } from '@angular/material/core'; -import { MAT_TOOLTIP_SCROLL_STRATEGY_FACTORY_PROVIDER } from '@angular/material/tooltip'; - -import { ESTooltipDirective } from './tooltip.directive'; -import { ESTooltipComponent } from './tooltip.component'; - -@NgModule({ - imports: [CommonModule, A11yModule, OverlayModule, MatCommonModule], - exports: [ESTooltipDirective, ESTooltipComponent, CdkScrollableModule, MatCommonModule], - declarations: [ESTooltipDirective, ESTooltipComponent], - providers: [MAT_TOOLTIP_SCROLL_STRATEGY_FACTORY_PROVIDER], -}) -export class ESTooltipModule {} diff --git a/projects/elonkit/src/ui/tooltip/tooltip.service.ts b/projects/elonkit/src/ui/tooltip/tooltip.service.ts deleted file mode 100644 index ad71800..0000000 --- a/projects/elonkit/src/ui/tooltip/tooltip.service.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Injectable } from '@angular/core'; - -import { Subject } from 'rxjs'; - -@Injectable({ providedIn: 'root' }) -export class ESTooltipService { - public closed$ = new Subject(); -}