@seniorsistemas/angular-components 19.3.0 → 19.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/breadcrumb/lib/dynamic-breadcrumb/dynamic-breadcrumb.component.d.ts +1 -2
- package/calendar-mask/lib/calendar-mask/calendar-mask.directive.d.ts +0 -1
- package/chips/lib/chips/chips/chips.component.d.ts +1 -2
- package/code-editor/lib/code-editor/code-editor.component.d.ts +0 -2
- package/code-editor/lib/code-editor/infra/utils/custom-translations/custom-translations.module.d.ts +1 -3
- package/common/lib/svg-factory/svg-factory.directive.d.ts +1 -2
- package/content-generator/lib/content-generator/content-generator.component.d.ts +1 -6
- package/content-generator/lib/services/IAssist/iassist.service.d.ts +0 -3
- package/country-phone-picker/lib/country-phone-picker/country-phone-picker.component.d.ts +0 -3
- package/country-phone-picker/lib/country-phone-picker/country-phone-picker.service.d.ts +0 -2
- package/currency/lib/currency.service.d.ts +0 -2
- package/custom-fields/lib/custom-fields/custom-fields.component.d.ts +3 -7
- package/custom-fields/lib/custom-fields/custom-fields.service.d.ts +0 -2
- package/dynamic-form/dynamic-form/components/lookup/lookup.component.d.ts +0 -2
- package/dynamic-form/dynamic-form/form-field/fields/autocomplete/autocomplete-field.component.d.ts +1 -2
- package/dynamic-form/dynamic-form/form-field/fields/bignumber/bignumber-field.component.d.ts +1 -3
- package/dynamic-form/dynamic-form/form-field/fields/calendar/calendar-field.component.d.ts +1 -2
- package/dynamic-form/dynamic-form/form-field/fields/chips/chips-field.component.d.ts +1 -3
- package/dynamic-form/dynamic-form/form-field/fields/country-phone-picker/country-phone-picker-field.component.d.ts +1 -2
- package/dynamic-form/dynamic-form/form-field/fields/currency/currency-field.component.d.ts +1 -3
- package/dynamic-form/dynamic-form/form-field/fields/file-picker/file-picker-field.component.d.ts +1 -2
- package/dynamic-form/dynamic-form/form-field/fields/number/number-field.component.d.ts +1 -3
- package/dynamic-form/dynamic-form/form-field/fields/password/password-field.component.d.ts +1 -2
- package/dynamic-form/dynamic-form/form-field/fields/text/text-field.component.d.ts +1 -2
- package/dynamic-form/dynamic-form/form-field/fields/text-area/text-area-field.component.d.ts +1 -2
- package/empty-state/lib/empty-state/go-back/go-back.component.d.ts +0 -2
- package/esm2022/badge/lib/badge/badge.component.mjs +3 -3
- package/esm2022/breadcrumb/lib/dynamic-breadcrumb/dynamic-breadcrumb.component.mjs +10 -13
- package/esm2022/calendar-mask/lib/calendar-mask/calendar-mask.directive.mjs +7 -11
- package/esm2022/chips/lib/chips/chips/chips.component.mjs +5 -8
- package/esm2022/code-editor/lib/code-editor/code-editor.component.mjs +6 -9
- package/esm2022/code-editor/lib/code-editor/infra/utils/custom-translations/custom-translations.module.mjs +8 -13
- package/esm2022/common/lib/svg-factory/svg-factory.directive.mjs +6 -10
- package/esm2022/content-generator/lib/content-generator/content-generator.component.mjs +24 -30
- package/esm2022/content-generator/lib/services/IAssist/iassist.service.mjs +9 -12
- package/esm2022/country-phone-picker/lib/country-phone-picker/country-phone-picker.component.mjs +15 -23
- package/esm2022/country-phone-picker/lib/country-phone-picker/country-phone-picker.service.mjs +6 -9
- package/esm2022/currency/lib/currency.service.mjs +6 -9
- package/esm2022/custom-fields/lib/custom-fields/custom-fields.component.mjs +17 -25
- package/esm2022/custom-fields/lib/custom-fields/custom-fields.service.mjs +6 -9
- package/esm2022/dynamic-form/dynamic-form/components/lookup/lookup.component.mjs +22 -28
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/autocomplete/autocomplete-field.component.mjs +6 -10
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/bignumber/bignumber-field.component.mjs +12 -17
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/calendar/calendar-field.component.mjs +5 -8
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/chips/chips-field.component.mjs +12 -17
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/country-phone-picker/country-phone-picker-field.component.mjs +5 -8
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/currency/currency-field.component.mjs +13 -19
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/file-picker/file-picker-field.component.mjs +6 -10
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/number/number-field.component.mjs +14 -19
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/password/password-field.component.mjs +5 -8
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/text/text-field.component.mjs +5 -8
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/text-area/text-area-field.component.mjs +5 -8
- package/esm2022/empty-state/lib/empty-state/go-back/go-back.component.mjs +8 -11
- package/esm2022/file-picker/lib/file-picker/file-picker.component.mjs +17 -21
- package/esm2022/gantt/lib/gantt/components/gantt/gantt.mjs +6 -2
- package/esm2022/gantt/lib/gantt/gantt.component.mjs +8 -4
- package/esm2022/global-search/lib/global-search/global-search.component.mjs +5 -8
- package/esm2022/image-cropper/lib/image-cropper/image-cropper.service.mjs +7 -12
- package/esm2022/infinite-scroll/lib/infinite-scroll/infinite-scroll.directive.mjs +5 -8
- package/esm2022/info-sign/lib/info-sign/info-sign.directive.mjs +6 -10
- package/esm2022/inline-edit/lib/inline-edit/components/fields/inline-edit-calendar/inline-edit-calendar.component.mjs +9 -12
- package/esm2022/inline-edit/lib/inline-edit/components/fields/inline-edit-number/inline-edit-number.component.mjs +14 -17
- package/esm2022/inline-edit/lib/inline-edit/components/inline-edit-item/inline-edit-item.component.mjs +12 -15
- package/esm2022/insights/lib/insights/components/insights-card/insights-card.component.mjs +15 -19
- package/esm2022/interactive-content/lib/interactive-content/interactive-content.directive.mjs +5 -8
- package/esm2022/kanban/lib/kanban/components/kanban-column/kanban-column.component.mjs +10 -13
- package/esm2022/kanban/lib/kanban/components/kanban-item/kanban-item.component.mjs +10 -13
- package/esm2022/kanban/lib/kanban/kanban.component.mjs +23 -17
- package/esm2022/loading-state/lib/loading-state/loading-state.directive.mjs +10 -16
- package/esm2022/locale/lib/locale/locale.service.mjs +8 -12
- package/esm2022/locale/lib/locale/pipes/localized-bignumber.pipe.mjs +6 -9
- package/esm2022/locale/lib/locale/pipes/localized-currency.pipe.mjs +6 -9
- package/esm2022/locale/lib/locale/pipes/localized-date.pipe.mjs +6 -9
- package/esm2022/locale/lib/locale/pipes/localized-number.pipe.mjs +6 -9
- package/esm2022/locale/lib/locale/pipes/localized-time.pipe.mjs +6 -9
- package/esm2022/localized-number-input/lib/localized-number-input/localized-number-input.directive.mjs +6 -9
- package/esm2022/navigation-button/lib/navigation-button/navigation-button.component.mjs +5 -8
- package/esm2022/numeric/lib/numeric.pipe.mjs +8 -12
- package/esm2022/numeric/lib/numeric.service.mjs +6 -9
- package/esm2022/password-strength/lib/password-strength/password-strength.component.mjs +8 -11
- package/esm2022/password-strength/lib/password-strength/password-strength.directive.mjs +10 -16
- package/esm2022/picklist/lib/picklist/picklist.component.mjs +5 -8
- package/esm2022/profile-picture-picker/lib/profile-picture-picker/profile-picture-picker.component.mjs +15 -19
- package/esm2022/progressbar/lib/progressbar/components/progressbar-determinate/progressbar-determinate.component.mjs +8 -11
- package/esm2022/progressbar/lib/progressbar/progressbar.module.mjs +5 -4
- package/esm2022/select-button/lib/select-button/select-button.component.mjs +3 -3
- package/esm2022/shared/lib/accessibility/paginator-accessibility.directive.mjs +8 -13
- package/esm2022/shared/lib/accessibility/table-checkbox-accessibility.directive.mjs +5 -8
- package/esm2022/slide-in-bar/lib/slide-in-bar/slide-in-bar.component.mjs +9 -12
- package/esm2022/speech-recognition/lib/speech-recognition/speech-recognition/speech-recognition.component.mjs +12 -16
- package/esm2022/speech-recognition/lib/speech-recognition/speech-recognition.service.mjs +12 -16
- package/esm2022/speech-recognition/lib/speech-recognition/text-to-speech.service.mjs +8 -10
- package/esm2022/split-button/lib/split-button/split-button.component.mjs +5 -8
- package/esm2022/table/lib/table/row-toggler/row-toggler.directive.mjs +7 -7
- package/esm2022/table/lib/table/table-column/table-columns.component.mjs +20 -29
- package/esm2022/table/lib/table/table-paging/table-paging.component.mjs +9 -16
- package/esm2022/table-header/lib/table-header/table-header-checkbox.component.mjs +11 -13
- package/esm2022/text-area/lib/text-area/text-area.component.mjs +5 -8
- package/esm2022/thumbnail/lib/thumbnail/thumbnail.component.mjs +8 -11
- package/esm2022/tiered-menu/lib/tiered-menu/components/tiered-menu/tiered-menu.component.mjs +16 -24
- package/esm2022/tiered-menu/lib/tiered-menu/components/tiered-menu-item/tiered-menu-item.component.mjs +8 -11
- package/esm2022/tiered-menu/lib/tiered-menu/components/tiered-menu-nested/tiered-menu-nested.component.mjs +12 -16
- package/esm2022/tiered-menu/lib/tiered-menu/tiered-menu.directive.mjs +13 -25
- package/esm2022/toast/lib/toast/toast.service.mjs +7 -12
- package/esm2022/tree/lib/tree/components/tree-node-item/tree-node-item.component.mjs +10 -14
- package/esm2022/workspace-switch/lib/workspace-switch/workspace-switch.component.mjs +6 -10
- package/fesm2022/seniorsistemas-angular-components-badge.mjs +2 -2
- package/fesm2022/seniorsistemas-angular-components-badge.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-breadcrumb.mjs +10 -12
- package/fesm2022/seniorsistemas-angular-components-breadcrumb.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-calendar-mask.mjs +6 -10
- package/fesm2022/seniorsistemas-angular-components-calendar-mask.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-chips.mjs +4 -7
- package/fesm2022/seniorsistemas-angular-components-chips.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-code-editor.mjs +10 -18
- package/fesm2022/seniorsistemas-angular-components-code-editor.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-common.mjs +5 -9
- package/fesm2022/seniorsistemas-angular-components-common.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-content-generator.mjs +29 -40
- package/fesm2022/seniorsistemas-angular-components-content-generator.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-country-phone-picker.mjs +16 -28
- package/fesm2022/seniorsistemas-angular-components-country-phone-picker.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-currency.mjs +5 -8
- package/fesm2022/seniorsistemas-angular-components-currency.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-custom-fields.mjs +45 -59
- package/fesm2022/seniorsistemas-angular-components-custom-fields.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-dynamic-form.mjs +108 -157
- package/fesm2022/seniorsistemas-angular-components-dynamic-form.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-empty-state.mjs +4 -8
- package/fesm2022/seniorsistemas-angular-components-empty-state.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-file-picker.mjs +17 -22
- package/fesm2022/seniorsistemas-angular-components-file-picker.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-gantt.mjs +12 -4
- package/fesm2022/seniorsistemas-angular-components-gantt.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-global-search.mjs +4 -7
- package/fesm2022/seniorsistemas-angular-components-global-search.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-image-cropper.mjs +6 -11
- package/fesm2022/seniorsistemas-angular-components-image-cropper.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-infinite-scroll.mjs +4 -7
- package/fesm2022/seniorsistemas-angular-components-infinite-scroll.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-info-sign.mjs +5 -9
- package/fesm2022/seniorsistemas-angular-components-info-sign.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-inline-edit.mjs +29 -38
- package/fesm2022/seniorsistemas-angular-components-inline-edit.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-insights.mjs +17 -22
- package/fesm2022/seniorsistemas-angular-components-insights.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-interactive-content.mjs +4 -7
- package/fesm2022/seniorsistemas-angular-components-interactive-content.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-kanban.mjs +30 -30
- package/fesm2022/seniorsistemas-angular-components-kanban.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-loading-state.mjs +7 -15
- package/fesm2022/seniorsistemas-angular-components-loading-state.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-locale.mjs +22 -41
- package/fesm2022/seniorsistemas-angular-components-locale.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-localized-number-input.mjs +5 -8
- package/fesm2022/seniorsistemas-angular-components-localized-number-input.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-navigation-button.mjs +4 -7
- package/fesm2022/seniorsistemas-angular-components-navigation-button.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-numeric.mjs +9 -16
- package/fesm2022/seniorsistemas-angular-components-numeric.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-password-strength.mjs +13 -24
- package/fesm2022/seniorsistemas-angular-components-password-strength.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-picklist.mjs +4 -7
- package/fesm2022/seniorsistemas-angular-components-picklist.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-profile-picture-picker.mjs +14 -21
- package/fesm2022/seniorsistemas-angular-components-profile-picture-picker.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-progressbar.mjs +11 -14
- package/fesm2022/seniorsistemas-angular-components-progressbar.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-select-button.mjs +2 -2
- package/fesm2022/seniorsistemas-angular-components-select-button.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-shared.mjs +10 -18
- package/fesm2022/seniorsistemas-angular-components-shared.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-slide-in-bar.mjs +7 -10
- package/fesm2022/seniorsistemas-angular-components-slide-in-bar.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-speech-recognition.mjs +23 -34
- package/fesm2022/seniorsistemas-angular-components-speech-recognition.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-split-button.mjs +4 -7
- package/fesm2022/seniorsistemas-angular-components-split-button.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-table-header.mjs +10 -12
- package/fesm2022/seniorsistemas-angular-components-table-header.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-table.mjs +30 -47
- package/fesm2022/seniorsistemas-angular-components-table.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-text-area.mjs +4 -7
- package/fesm2022/seniorsistemas-angular-components-text-area.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-thumbnail.mjs +6 -9
- package/fesm2022/seniorsistemas-angular-components-thumbnail.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-tiered-menu.mjs +30 -55
- package/fesm2022/seniorsistemas-angular-components-tiered-menu.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-toast.mjs +6 -11
- package/fesm2022/seniorsistemas-angular-components-toast.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-tree.mjs +9 -14
- package/fesm2022/seniorsistemas-angular-components-tree.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-workspace-switch.mjs +5 -9
- package/fesm2022/seniorsistemas-angular-components-workspace-switch.mjs.map +1 -1
- package/file-picker/lib/file-picker/file-picker.component.d.ts +0 -4
- package/file-upload/README.md +9 -37
- package/gantt/lib/gantt/gantt.component.d.ts +1 -0
- package/global-search/lib/global-search/global-search.component.d.ts +1 -2
- package/ia-insight/README.md +17 -0
- package/image-cropper/lib/image-cropper/image-cropper.service.d.ts +1 -2
- package/infinite-scroll/lib/infinite-scroll/infinite-scroll.directive.d.ts +1 -2
- package/info-sign/lib/info-sign/info-sign.directive.d.ts +1 -2
- package/inline-edit/lib/inline-edit/components/fields/inline-edit-calendar/inline-edit-calendar.component.d.ts +1 -2
- package/inline-edit/lib/inline-edit/components/fields/inline-edit-number/inline-edit-number.component.d.ts +0 -2
- package/inline-edit/lib/inline-edit/components/inline-edit-item/inline-edit-item.component.d.ts +0 -2
- package/insights/lib/insights/components/insights-card/insights-card.component.d.ts +0 -4
- package/interactive-content/lib/interactive-content/interactive-content.directive.d.ts +1 -2
- package/kanban/lib/kanban/components/kanban-column/kanban-column.component.d.ts +0 -2
- package/kanban/lib/kanban/components/kanban-item/kanban-item.component.d.ts +0 -2
- package/kanban/lib/kanban/kanban.component.d.ts +2 -2
- package/loading-state/lib/loading-state/loading-state.directive.d.ts +1 -2
- package/locale/lib/locale/locale.service.d.ts +0 -3
- package/locale/lib/locale/pipes/localized-bignumber.pipe.d.ts +0 -2
- package/locale/lib/locale/pipes/localized-currency.pipe.d.ts +0 -2
- package/locale/lib/locale/pipes/localized-date.pipe.d.ts +0 -2
- package/locale/lib/locale/pipes/localized-number.pipe.d.ts +0 -2
- package/locale/lib/locale/pipes/localized-time.pipe.d.ts +0 -2
- package/localized-number-input/lib/localized-number-input/localized-number-input.directive.d.ts +0 -2
- package/navigation-button/lib/navigation-button/navigation-button.component.d.ts +1 -2
- package/numeric/lib/numeric.pipe.d.ts +0 -3
- package/numeric/lib/numeric.service.d.ts +0 -2
- package/package.json +12 -12
- package/password-strength/lib/password-strength/password-strength.component.d.ts +0 -2
- package/password-strength/lib/password-strength/password-strength.directive.d.ts +1 -2
- package/picklist/lib/picklist/picklist.component.d.ts +1 -2
- package/product-header/README.md +17 -0
- package/profile-picture-picker/lib/profile-picture-picker/profile-picture-picker.component.d.ts +0 -4
- package/progressbar/lib/progressbar/components/progressbar-determinate/progressbar-determinate.component.d.ts +0 -2
- package/progressbar/lib/progressbar/progressbar.module.d.ts +2 -1
- package/shared/lib/accessibility/paginator-accessibility.directive.d.ts +1 -3
- package/shared/lib/accessibility/table-checkbox-accessibility.directive.d.ts +1 -2
- package/slide-in-bar/lib/slide-in-bar/slide-in-bar.component.d.ts +0 -2
- package/speech-recognition/lib/speech-recognition/speech-recognition/speech-recognition.component.d.ts +0 -4
- package/speech-recognition/lib/speech-recognition/speech-recognition.service.d.ts +1 -5
- package/speech-recognition/lib/speech-recognition/text-to-speech.service.d.ts +1 -3
- package/split-button/lib/split-button/split-button.component.d.ts +1 -2
- package/table/lib/table/row-toggler/row-toggler.directive.d.ts +1 -1
- package/table/lib/table/table-column/table-columns.component.d.ts +2 -6
- package/table/lib/table/table-paging/table-paging.component.d.ts +0 -3
- package/table-header/lib/table-header/table-header-checkbox.component.d.ts +1 -1
- package/text-area/lib/text-area/text-area.component.d.ts +1 -2
- package/text-area-ia/README.md +17 -0
- package/thumbnail/lib/thumbnail/thumbnail.component.d.ts +0 -2
- package/tiered-menu/lib/tiered-menu/components/tiered-menu/tiered-menu.component.d.ts +1 -3
- package/tiered-menu/lib/tiered-menu/components/tiered-menu-item/tiered-menu-item.component.d.ts +0 -2
- package/tiered-menu/lib/tiered-menu/components/tiered-menu-nested/tiered-menu-nested.component.d.ts +0 -2
- package/tiered-menu/lib/tiered-menu/tiered-menu.directive.d.ts +1 -5
- package/toast/lib/toast/toast.service.d.ts +0 -2
- package/tree/lib/tree/components/tree-node-item/tree-node-item.component.d.ts +1 -3
- package/workspace-switch/lib/workspace-switch/workspace-switch.component.d.ts +1 -2
- package/confirm-dialog/README.md +0 -226
- package/numeric-mask/README.md +0 -395
- package/pin-code-field/README.md +0 -366
- package/spotlight/README.md +0 -311
package/pin-code-field/README.md
DELETED
|
@@ -1,366 +0,0 @@
|
|
|
1
|
-
# Pin Code Field
|
|
2
|
-
|
|
3
|
-
O `PinCodeFieldComponent` é um componente customizado que encapsula múltiplos inputs para entrada de códigos de autenticação (tokens, OTP, etc.). O componente implementa `ControlValueAccessor`, tornando-o totalmente compatível com formulários reativos e template-driven do Angular.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- Compatível com `ngModel` e `ReactiveForms` (`ControlValueAccessor`)
|
|
8
|
-
- Validação flexível delegada ao `FormControl` do usuário
|
|
9
|
-
- Configuração flexível de comprimento do código
|
|
10
|
-
- Suporte a caracteres alfanuméricos e especiais (opcional)
|
|
11
|
-
- Navegação entre campos com setas (esquerda/direita)
|
|
12
|
-
- Suporte a colar código (trunca se maior que o comprimento)
|
|
13
|
-
- Suporte a backspace com navegação automática
|
|
14
|
-
- Estados visuais: normal, foco, desabilitado e erro
|
|
15
|
-
- Controle de estado de erro via input `invalid`
|
|
16
|
-
- Help text descritivo
|
|
17
|
-
- Acessibilidade completa (ARIA labels, roles, etc.)
|
|
18
|
-
- Integração com `s-control-errors` para exibição de mensagens de erro
|
|
19
|
-
|
|
20
|
-
## Dependências
|
|
21
|
-
|
|
22
|
-
Nenhuma dependência adicional além do Angular.
|
|
23
|
-
|
|
24
|
-
## Utilização
|
|
25
|
-
|
|
26
|
-
**[Exemplo completo de implementação](../../../../src/app/components/pin-code-field-showcase)**
|
|
27
|
-
|
|
28
|
-
- **Componente**: `PinCodeFieldComponent`
|
|
29
|
-
- **Seletor do componente**: `s-pin-code-field`
|
|
30
|
-
|
|
31
|
-
### Import
|
|
32
|
-
|
|
33
|
-
```typescript
|
|
34
|
-
import { PinCodeFieldComponent } from '@seniorsistemas/angular-components/pin-code-field';
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Exemplos de utilização
|
|
38
|
-
|
|
39
|
-
### Exemplo básico com template-driven forms
|
|
40
|
-
|
|
41
|
-
```html
|
|
42
|
-
<form #myForm="ngForm">
|
|
43
|
-
<s-pin-code-field
|
|
44
|
-
name="code"
|
|
45
|
-
[(ngModel)]="code"
|
|
46
|
-
[length]="6"
|
|
47
|
-
helpText="Digite o código enviado para seu email"
|
|
48
|
-
>
|
|
49
|
-
</s-pin-code-field>
|
|
50
|
-
</form>
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### Exemplo com formulário reativo
|
|
54
|
-
|
|
55
|
-
```typescript
|
|
56
|
-
import { Component } from '@angular/core';
|
|
57
|
-
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
|
58
|
-
|
|
59
|
-
@Component({
|
|
60
|
-
selector: 'app-auth-form',
|
|
61
|
-
template: `
|
|
62
|
-
<form [formGroup]="form">
|
|
63
|
-
<s-pin-code-field
|
|
64
|
-
formControlName="code"
|
|
65
|
-
[length]="6"
|
|
66
|
-
[alphanumeric]="false"
|
|
67
|
-
[invalid]="(form.get('code')?.invalid && form.get('code')?.dirty) || false"
|
|
68
|
-
helpText="Digite o código de 6 dígitos"
|
|
69
|
-
>
|
|
70
|
-
</s-pin-code-field>
|
|
71
|
-
<s-control-errors
|
|
72
|
-
[control]="form.get('code')"
|
|
73
|
-
[errorMessages]="errorMessages"
|
|
74
|
-
[displayErrors]="submitted"
|
|
75
|
-
>
|
|
76
|
-
</s-control-errors>
|
|
77
|
-
</form>
|
|
78
|
-
`,
|
|
79
|
-
})
|
|
80
|
-
export class AuthFormComponent {
|
|
81
|
-
form: FormGroup;
|
|
82
|
-
submitted = false;
|
|
83
|
-
errorMessages = {
|
|
84
|
-
required: 'Este campo é obrigatório e não foi preenchido.',
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
constructor(private fb: FormBuilder) {
|
|
88
|
-
this.form = this.fb.group({
|
|
89
|
-
code: ['', [Validators.required()]],
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### Exemplo com listener de preenchimento
|
|
96
|
-
|
|
97
|
-
```html
|
|
98
|
-
<s-pin-code-field
|
|
99
|
-
[(ngModel)]="code"
|
|
100
|
-
[length]="6"
|
|
101
|
-
(codeFilled)="onCodeFilled($event)"
|
|
102
|
-
>
|
|
103
|
-
</s-pin-code-field>
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
export class MyComponent {
|
|
108
|
-
code: string = '';
|
|
109
|
-
|
|
110
|
-
onCodeFilled(code: string) {
|
|
111
|
-
console.log('Código completado:', code);
|
|
112
|
-
// Realizar verificação do código
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
### Exemplo com caracteres alfanuméricos
|
|
118
|
-
|
|
119
|
-
```html
|
|
120
|
-
<s-pin-code-field
|
|
121
|
-
[(ngModel)]="code"
|
|
122
|
-
[length]="8"
|
|
123
|
-
[alphanumeric]="true"
|
|
124
|
-
helpText="Código pode conter letras, números e caracteres especiais"
|
|
125
|
-
>
|
|
126
|
-
</s-pin-code-field>
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
## Inputs
|
|
130
|
-
|
|
131
|
-
| Nome | Tipo | Valor Padrão | Obrigatório | Descrição |
|
|
132
|
-
| -------------- | ---------------- | ------------ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
133
|
-
| `length` | `input<number>` | 6 | Não | Quantidade de caracteres que o código deve ter. |
|
|
134
|
-
| `alphanumeric` | `input<boolean>` | false | Não | Se true, aceita letras, números e caracteres especiais. Se false, aceita apenas números. |
|
|
135
|
-
| `helpText` | `input<string>` | '' | Não | Texto de ajuda exibido abaixo dos campos. |
|
|
136
|
-
| `invalid` | `input<boolean>` | false | Não | Controla se o componente exibe estado de erro (borda vermelha). Use em conjunto com `FormControl.invalid && FormControl.dirty` para validação. |
|
|
137
|
-
| `disabled` | `model<boolean>` | false | Não | Desabilita todos os campos impedindo entrada de dados. Two-way binding. |
|
|
138
|
-
|
|
139
|
-
## Outputs
|
|
140
|
-
|
|
141
|
-
| Nome | Tipo | Descrição |
|
|
142
|
-
| ------------ | ---------------------- | -------------------------------------------------------------------------------------------------- |
|
|
143
|
-
| `codeFilled` | `EventEmitter<string>` | Emitido quando todos os caracteres do código são preenchidos. Emite o código completo como string. |
|
|
144
|
-
|
|
145
|
-
## Validators
|
|
146
|
-
|
|
147
|
-
O componente exporta dois validators personalizados que trabalham como `ValidatorFn` do Angular:
|
|
148
|
-
|
|
149
|
-
### `incomplete(length?: number)`
|
|
150
|
-
|
|
151
|
-
Valida se o código foi totalmente preenchido. Retorna erro `incomplete` se houver preenchimento parcial.
|
|
152
|
-
|
|
153
|
-
```typescript
|
|
154
|
-
const control = new FormControl('', [Validators.required(), incomplete(6)]);
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
**Parâmetro:**
|
|
158
|
-
|
|
159
|
-
- `length` (opcional): Comprimento esperado do código (padrão: 6)
|
|
160
|
-
|
|
161
|
-
**Retorna:**
|
|
162
|
-
|
|
163
|
-
- `{ incomplete: true }` se o valor parcial for preenchido
|
|
164
|
-
- `null` se o código estiver completo ou vazio
|
|
165
|
-
|
|
166
|
-
### `pasteError(component?: PinCodeFieldComponent)`
|
|
167
|
-
|
|
168
|
-
Valida se houve erro ao colar conteúdo inválido. Retorna erro `pasteError` quando um paste inválido é detectado.
|
|
169
|
-
|
|
170
|
-
```typescript
|
|
171
|
-
const control = new FormControl('', [pasteError()]);
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
**Nota:** Este validator monitora o estado interno do componente para detectar tentativas de paste com conteúdo inválido.
|
|
175
|
-
|
|
176
|
-
## Comportamentos
|
|
177
|
-
|
|
178
|
-
### Navegação
|
|
179
|
-
|
|
180
|
-
- **Seta Direita**: Move o foco para o próximo campo
|
|
181
|
-
- **Seta Esquerda**: Move o foco para o campo anterior
|
|
182
|
-
- **Seta Para Cima/Baixo**: Sem efeito
|
|
183
|
-
|
|
184
|
-
### Entrada de Dados
|
|
185
|
-
|
|
186
|
-
- A digitação automática avança para o próximo campo quando um caractere é inserido
|
|
187
|
-
- No último campo, a digitação não causa mudança de foco
|
|
188
|
-
- Todos os campos são preenchidos ao colar um código válido
|
|
189
|
-
|
|
190
|
-
### Backspace
|
|
191
|
-
|
|
192
|
-
- **Campo preenchido**: Limpa o campo atual e mantém o foco
|
|
193
|
-
- **Campo vazio**: Move para o campo anterior, limpa-o e mantém o foco no anterior
|
|
194
|
-
|
|
195
|
-
### Paste (Colar)
|
|
196
|
-
|
|
197
|
-
- Filtra caracteres inválidos de acordo com a configuração `alphanumeric`
|
|
198
|
-
- Se o texto colado é maior que o comprimento, trunca automaticamente
|
|
199
|
-
- Preenche os campos disponíveis com o texto colado filtrado
|
|
200
|
-
- Emite o evento `codeFilled` quando todos os campos são preenchidos
|
|
201
|
-
- A validação de valores aceitáveis é responsabilidade do `FormControl` validator
|
|
202
|
-
|
|
203
|
-
### Estados Visuais
|
|
204
|
-
|
|
205
|
-
- **Normal**: Borda cinza, fundo branco
|
|
206
|
-
- **Foco**: Borda azul com ring de foco
|
|
207
|
-
- **Desabilitado**: Fundo cinza claro, texto cinza, sem interação
|
|
208
|
-
- **Erro**: Borda e ring vermelhos (quando `invalid` input é true)
|
|
209
|
-
|
|
210
|
-
## Validação
|
|
211
|
-
|
|
212
|
-
O componente **não exporta validators pré-construídos**. A validação é responsabilidade do usuário via `FormControl.validator`.
|
|
213
|
-
|
|
214
|
-
Exemplos de validators customizados:
|
|
215
|
-
|
|
216
|
-
```typescript
|
|
217
|
-
// Validar que o código tem exatamente 6 dígitos
|
|
218
|
-
const requiredValidator = Validators.required();
|
|
219
|
-
|
|
220
|
-
// Validador customizado para rejeitar valor específico
|
|
221
|
-
const notBlacklisted: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
|
|
222
|
-
const value = control.value as string;
|
|
223
|
-
if (value === '123456') {
|
|
224
|
-
return { blacklisted: true };
|
|
225
|
-
}
|
|
226
|
-
return null;
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
const form = this.fb.group({
|
|
230
|
-
code: ['', [requiredValidator, notBlacklisted]],
|
|
231
|
-
});
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
### Mostrando Erros de Validação
|
|
235
|
-
|
|
236
|
-
Use o input `invalid` para controlar visualmente o estado de erro:
|
|
237
|
-
|
|
238
|
-
```html
|
|
239
|
-
<s-pin-code-field
|
|
240
|
-
formControlName="code"
|
|
241
|
-
[invalid]="(form.get('code')?.invalid && form.get('code')?.dirty) || false"
|
|
242
|
-
>
|
|
243
|
-
</s-pin-code-field>
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
## Acessibilidade
|
|
247
|
-
|
|
248
|
-
O componente implementa padrões de acessibilidade completos:
|
|
249
|
-
|
|
250
|
-
- Cada input tem um `aria-label` descritivo com sua posição no código
|
|
251
|
-
- O container tem `role="group"` e associação com help text
|
|
252
|
-
- `aria-invalid` é definido quando há erro
|
|
253
|
-
- `aria-describedby` conecta inputs ao help text
|
|
254
|
-
- `inputmode` é configurado corretamente (numeric/text)
|
|
255
|
-
- `autocomplete="off"` previne preenchimento automático indesejado
|
|
256
|
-
- Todos os estados visuais incluem indicadores para leitores de tela
|
|
257
|
-
|
|
258
|
-
## Exemplos Completos
|
|
259
|
-
|
|
260
|
-
### Integração com Reactive Forms e validação customizada
|
|
261
|
-
|
|
262
|
-
```typescript
|
|
263
|
-
import { Component, OnInit } from '@angular/core';
|
|
264
|
-
import { FormBuilder, FormGroup, Validators, AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';
|
|
265
|
-
|
|
266
|
-
// Validador customizado que rejeita um valor específico
|
|
267
|
-
const notBlacklisted: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
|
|
268
|
-
const value = control.value as string;
|
|
269
|
-
if (value === '123456') {
|
|
270
|
-
return { blacklisted: true };
|
|
271
|
-
}
|
|
272
|
-
return null;
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
@Component({
|
|
276
|
-
selector: 'app-verify-code',
|
|
277
|
-
template: `
|
|
278
|
-
<form [formGroup]="verifyForm">
|
|
279
|
-
<s-pin-code-field
|
|
280
|
-
formControlName="verificationCode"
|
|
281
|
-
[length]="6"
|
|
282
|
-
[alphanumeric]="false"
|
|
283
|
-
[invalid]="(control?.invalid && control?.dirty) || false"
|
|
284
|
-
helpText="Digite o código de 6 dígitos enviado"
|
|
285
|
-
(codeFilled)="verifyCode($event)"
|
|
286
|
-
>
|
|
287
|
-
</s-pin-code-field>
|
|
288
|
-
|
|
289
|
-
<s-control-errors
|
|
290
|
-
[control]="control"
|
|
291
|
-
[errorMessages]="errorMessages"
|
|
292
|
-
[displayErrors]="submitted"
|
|
293
|
-
>
|
|
294
|
-
</s-control-errors>
|
|
295
|
-
|
|
296
|
-
<button
|
|
297
|
-
[disabled]="!verifyForm.valid"
|
|
298
|
-
(click)="submit()"
|
|
299
|
-
>
|
|
300
|
-
Verificar
|
|
301
|
-
</button>
|
|
302
|
-
</form>
|
|
303
|
-
`,
|
|
304
|
-
})
|
|
305
|
-
export class VerifyCodeComponent implements OnInit {
|
|
306
|
-
verifyForm!: FormGroup;
|
|
307
|
-
submitted = false;
|
|
308
|
-
errorMessages = {
|
|
309
|
-
required: 'Código obrigatório',
|
|
310
|
-
blacklisted: 'Este código não é válido',
|
|
311
|
-
};
|
|
312
|
-
|
|
313
|
-
get control() {
|
|
314
|
-
return this.verifyForm.get('verificationCode');
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
constructor(private fb: FormBuilder) {}
|
|
318
|
-
|
|
319
|
-
ngOnInit() {
|
|
320
|
-
this.verifyForm = this.fb.group({
|
|
321
|
-
verificationCode: ['', [Validators.required, notBlacklisted]],
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
verifyCode(code: string) {
|
|
326
|
-
console.log('Código completo:', code);
|
|
327
|
-
// Enviar para API de verificação
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
submit() {
|
|
331
|
-
this.submitted = true;
|
|
332
|
-
if (this.verifyForm.valid) {
|
|
333
|
-
this.verifyCode(this.verifyForm.value.verificationCode);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
### Com loading e desabilitação após envio
|
|
340
|
-
|
|
341
|
-
```typescript
|
|
342
|
-
export class VerifyCodeComponent {
|
|
343
|
-
verifyForm!: FormGroup;
|
|
344
|
-
isLoading = false;
|
|
345
|
-
|
|
346
|
-
verifyCode(code: string) {
|
|
347
|
-
this.isLoading = true;
|
|
348
|
-
// Desabilita o campo durante a requisição
|
|
349
|
-
this.verifyForm.get('verificationCode')?.disable();
|
|
350
|
-
|
|
351
|
-
this.authService.verify(code).subscribe(
|
|
352
|
-
(response) => {
|
|
353
|
-
// Sucesso
|
|
354
|
-
this.isLoading = false;
|
|
355
|
-
},
|
|
356
|
-
(error) => {
|
|
357
|
-
// Erro - reabilita o formulário
|
|
358
|
-
this.isLoading = false;
|
|
359
|
-
this.verifyForm.get('verificationCode')?.enable();
|
|
360
|
-
this.verifyForm.get('verificationCode')?.reset();
|
|
361
|
-
},
|
|
362
|
-
);
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
```
|
|
366
|
-
|
package/spotlight/README.md
DELETED
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
# Spotlight
|
|
2
|
-
|
|
3
|
-
## Descrição
|
|
4
|
-
|
|
5
|
-
O Spotlight é uma biblioteca para criação de **tours guiados** (onboarding com múltiplos passos) e **destaques simples** (dicas únicas sobre um elemento). O posicionamento do popover é gerenciado automaticamente pelo Angular CDK, com fallbacks inteligentes para manter o popover sempre visível.
|
|
6
|
-
|
|
7
|
-
Dois modos de operação:
|
|
8
|
-
|
|
9
|
-
- **Tour**: sequência de passos com navegação Próximo / Voltar / Concluído, contador de progresso, focus trap e bloqueio de scroll.
|
|
10
|
-
- **Destaque simples**: popover único com botão "Entendi" e opção de "Não mostrar novamente".
|
|
11
|
-
|
|
12
|
-
## Instalação
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
npm install @seniorsistemas/angular-components/spotlight
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## Conceitos
|
|
19
|
-
|
|
20
|
-
### Diretiva `sSpotlightStep`
|
|
21
|
-
|
|
22
|
-
Registra um elemento do DOM como alvo de um passo do tour. Deve ser aplicada ao elemento que receberá o destaque.
|
|
23
|
-
|
|
24
|
-
```html
|
|
25
|
-
<button sSpotlightStep="meu-botao">Salvar</button>
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
O valor do atributo é o `stepId`, que deve corresponder ao `stepId` definido nos passos do tour.
|
|
29
|
-
Quando o valor do binding muda dinamicamente, a diretiva desregistra o ID anterior e registra o novo automaticamente.
|
|
30
|
-
|
|
31
|
-
### `SpotlightTourService`
|
|
32
|
-
|
|
33
|
-
Serviço singleton que controla o estado do tour. Injete-o no componente que inicia o tour.
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## Tour (múltiplos passos)
|
|
38
|
-
|
|
39
|
-
### 1. Marque os elementos no template
|
|
40
|
-
|
|
41
|
-
```html
|
|
42
|
-
<input sSpotlightStep="produto-nome" ... />
|
|
43
|
-
<select sSpotlightStep="produto-categoria" ... />
|
|
44
|
-
<button sSpotlightStep="salvar-btn">Salvar</button>
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### 2. Inicie o tour pelo serviço
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
import { SpotlightTourService, SpotlightStep } from '@seniorsistemas/angular-components/spotlight';
|
|
51
|
-
|
|
52
|
-
@Component({ ... })
|
|
53
|
-
export class MeuComponent {
|
|
54
|
-
private readonly tourService = inject(SpotlightTourService);
|
|
55
|
-
|
|
56
|
-
private readonly passos: SpotlightStep[] = [
|
|
57
|
-
{
|
|
58
|
-
stepId: 'produto-nome',
|
|
59
|
-
title: 'Nome do produto',
|
|
60
|
-
message: 'Informe o nome completo do produto.',
|
|
61
|
-
position: 'bottom-center',
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
stepId: 'produto-categoria',
|
|
65
|
-
title: 'Categoria',
|
|
66
|
-
message: 'Selecione a categoria correta.',
|
|
67
|
-
position: 'bottom-end',
|
|
68
|
-
beforeNext: () => {
|
|
69
|
-
// Executado antes de avançar — útil para trocar abas, expandir seções, etc.
|
|
70
|
-
this.activeTab.set('detalhes');
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
stepId: 'salvar-btn',
|
|
75
|
-
title: 'Salvar',
|
|
76
|
-
message: 'Clique aqui para salvar as alterações.',
|
|
77
|
-
position: 'top-center',
|
|
78
|
-
},
|
|
79
|
-
];
|
|
80
|
-
|
|
81
|
-
public iniciarTour(): void {
|
|
82
|
-
this.tourService.start(this.passos);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### 3. Reaja aos eventos do tour
|
|
88
|
-
|
|
89
|
-
```typescript
|
|
90
|
-
private readonly destroyRef = inject(DestroyRef);
|
|
91
|
-
|
|
92
|
-
public constructor() {
|
|
93
|
-
this.tourService.stopped$
|
|
94
|
-
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
95
|
-
.subscribe((event) => {
|
|
96
|
-
// Salve o estado para persistência
|
|
97
|
-
localStorage.setItem('tour-onboarding', JSON.stringify({
|
|
98
|
-
reason: event.reason, // 'completed' | 'interrupted'
|
|
99
|
-
doNotShowAgain: event.doNotShowAgain,
|
|
100
|
-
stepIndex: event.stepIndex,
|
|
101
|
-
}));
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
---
|
|
107
|
-
|
|
108
|
-
## Destaque Simples
|
|
109
|
-
|
|
110
|
-
Use `tourService.spotlight()` para exibir um destaque em um único elemento.
|
|
111
|
-
|
|
112
|
-
```html
|
|
113
|
-
<div sSpotlightStep="novo-recurso">...</div>
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
```typescript
|
|
117
|
-
import { SpotlightTourService, SpotlightConfig } from '@seniorsistemas/angular-components/spotlight';
|
|
118
|
-
|
|
119
|
-
@Component({ ... })
|
|
120
|
-
export class MeuComponent {
|
|
121
|
-
private readonly tourService = inject(SpotlightTourService);
|
|
122
|
-
|
|
123
|
-
public mostrarDica(): void {
|
|
124
|
-
const config: SpotlightConfig = {
|
|
125
|
-
title: 'Novidade!',
|
|
126
|
-
message: 'Este recurso foi adicionado recentemente.',
|
|
127
|
-
position: 'bottom-center',
|
|
128
|
-
// showDoNotShowAgain é true por padrão — passe false para suprimir o checkbox
|
|
129
|
-
dismissible: true,
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
this.tourService.spotlight('novo-recurso', config);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
Ao encerrar, `stopped$` emite com `reason: 'dismissed'` (usuário fechou) ou `reason: 'completed'` (clicou em "Entendi"). Quando `doNotShowAgain` é `true`, salve essa preferência para não exibir novamente.
|
|
138
|
-
|
|
139
|
-
---
|
|
140
|
-
|
|
141
|
-
## `SpotlightStep`
|
|
142
|
-
|
|
143
|
-
| Propriedade | Tipo | Obrigatório | Descrição |
|
|
144
|
-
|---|---|---|---|
|
|
145
|
-
| `stepId` | `string` | ✓ | Identificador único do passo. Deve corresponder ao valor do `sSpotlightStep` no template. |
|
|
146
|
-
| `title` | `string \| TemplateRef<any>` | ✓ | Título do popover (máx. recomendado: 30 caracteres). |
|
|
147
|
-
| `message` | `string \| TemplateRef<any>` | ✓ | Texto descritivo (máx. recomendado: 75 caracteres). |
|
|
148
|
-
| `position` | `SpotlightPosition` | — | Posição preferida do popover. Padrão: `'bottom-center'`. |
|
|
149
|
-
| `content` | `TemplateRef<any> \| null` | — | Conteúdo visual customizado (imagem, gif, vídeo) exibido acima da mensagem. |
|
|
150
|
-
| `actions` | `SpotlightStepAction[]` | — | Botões de ação customizados exibidos antes dos botões de navegação. |
|
|
151
|
-
| `showBackdrop` | `boolean` | — | Exibe o backdrop escurecido ao redor do elemento destacado. Padrão: `true`. |
|
|
152
|
-
| `dismissible` | `boolean` | — | Permite fechar o spotlight clicando fora ou pressionando Escape. Padrão: `true`. |
|
|
153
|
-
| `beforeNext` | `() => void \| Promise<void>` | — | Callback executado antes de avançar para o próximo passo. Suporta async/await. |
|
|
154
|
-
| `beforePrevious` | `() => void \| Promise<void>` | — | Callback executado antes de voltar ao passo anterior. Suporta async/await. |
|
|
155
|
-
|
|
156
|
-
## `SpotlightConfig`
|
|
157
|
-
|
|
158
|
-
Equivalente ao `SpotlightStep` sem `stepId`, `beforeNext` e `beforePrevious`. Usado exclusivamente com `tourService.spotlight()`. Inclui a propriedade adicional:
|
|
159
|
-
|
|
160
|
-
| Propriedade | Tipo | Descrição |
|
|
161
|
-
|---|---|---|
|
|
162
|
-
| `showDoNotShowAgain` | `boolean` | Exibe o checkbox "Não mostrar novamente". Padrão: `true`. Passe `false` para suprimir. |
|
|
163
|
-
|
|
164
|
-
## `SpotlightStepAction`
|
|
165
|
-
|
|
166
|
-
| Propriedade | Tipo | Descrição |
|
|
167
|
-
|---|---|---|
|
|
168
|
-
| `label` | `string` | Texto do botão. |
|
|
169
|
-
| `handler` | `() => void` | Função executada ao clicar no botão. |
|
|
170
|
-
|
|
171
|
-
---
|
|
172
|
-
|
|
173
|
-
## `SpotlightTourService`
|
|
174
|
-
|
|
175
|
-
### Propriedades
|
|
176
|
-
|
|
177
|
-
| Propriedade | Tipo | Descrição |
|
|
178
|
-
|---|---|---|
|
|
179
|
-
| `isActive` | `Signal<boolean>` | `true` enquanto o tour estiver ativo. |
|
|
180
|
-
| `currentStep` | `Signal<SpotlightStep \| undefined>` | Passo atualmente exibido. |
|
|
181
|
-
| `currentIndex` | `Signal<number>` | Índice do passo atual (base 0). |
|
|
182
|
-
| `totalSteps` | `Signal<number>` | Total de passos do tour. |
|
|
183
|
-
| `stopped$` | `Observable<SpotlightStopEvent>` | Emite quando o tour é encerrado. |
|
|
184
|
-
| `stepChanged$` | `Observable<SpotlightStepChangedEvent>` | Emite ao mudar de passo (incluindo o primeiro). |
|
|
185
|
-
|
|
186
|
-
### Métodos
|
|
187
|
-
|
|
188
|
-
| Método | Descrição |
|
|
189
|
-
|---|---|
|
|
190
|
-
| `start(steps: SpotlightStep[])` | Inicia o tour com a lista de passos fornecida. Ignora arrays vazios. Se houver um tour ativo, encerra-o (emitindo `stopped$`) antes de iniciar o novo. |
|
|
191
|
-
| `spotlight(stepId, config: SpotlightConfig)` | Exibe um destaque simples em um único elemento. |
|
|
192
|
-
| `next(doNotShowAgain?: boolean)` | Avança para o próximo passo ou conclui o tour. |
|
|
193
|
-
| `previous()` | Volta ao passo anterior. |
|
|
194
|
-
| `stop(event?: Partial<SpotlightStopEvent>)` | Encerra o tour programaticamente. |
|
|
195
|
-
| `registerElement(stepId, el)` | Registra um elemento (usado internamente pela diretiva). |
|
|
196
|
-
| `unregisterElement(stepId)` | Remove o registro de um elemento. |
|
|
197
|
-
| `getElement(stepId)` | Retorna o `ElementRef` registrado para o `stepId`. |
|
|
198
|
-
|
|
199
|
-
---
|
|
200
|
-
|
|
201
|
-
## Eventos (`SpotlightStopEvent`)
|
|
202
|
-
|
|
203
|
-
Emitido por `stopped$` ao encerrar o tour.
|
|
204
|
-
|
|
205
|
-
| Campo | Tipo | Descrição |
|
|
206
|
-
|---|---|---|
|
|
207
|
-
| `reason` | `SpotlightStopReason` | Razão do encerramento. |
|
|
208
|
-
| `doNotShowAgain` | `boolean` | `true` se o usuário marcou "Não mostrar novamente". |
|
|
209
|
-
| `stepId` | `string` | `stepId` do passo em que o tour foi encerrado. |
|
|
210
|
-
| `stepIndex` | `number` | Índice (base 0) do passo em que o tour foi encerrado. |
|
|
211
|
-
| `totalSteps` | `number` | Total de passos do tour. |
|
|
212
|
-
|
|
213
|
-
### `SpotlightStopReason`
|
|
214
|
-
|
|
215
|
-
| Valor | Quando ocorre | Comportamento recomendado |
|
|
216
|
-
|---|---|---|
|
|
217
|
-
| `'completed'` | Usuário clicou em "Concluído" ou "Entendi" | Nunca reexibir |
|
|
218
|
-
| `'interrupted'` | Usuário fechou o tour antes de concluir (X, Escape, clique fora) | Reexibir na próxima sessão |
|
|
219
|
-
| `'dismissed'` | Usuário fechou um destaque simples | Reexibir após cooldown |
|
|
220
|
-
|
|
221
|
-
### `SpotlightStepChangedEvent`
|
|
222
|
-
|
|
223
|
-
Emitido por `stepChanged$` a cada mudança de passo.
|
|
224
|
-
|
|
225
|
-
| Campo | Tipo | Descrição |
|
|
226
|
-
|---|---|---|
|
|
227
|
-
| `stepId` | `string` | `stepId` do novo passo. |
|
|
228
|
-
| `stepIndex` | `number` | Índice (base 0) do novo passo. |
|
|
229
|
-
| `totalSteps` | `number` | Total de passos do tour. |
|
|
230
|
-
|
|
231
|
-
---
|
|
232
|
-
|
|
233
|
-
## Posições Disponíveis (`SpotlightPosition`)
|
|
234
|
-
|
|
235
|
-
| Valor | Descrição |
|
|
236
|
-
|---|---|
|
|
237
|
-
| `'top-start'` | Acima do elemento, alinhado à esquerda |
|
|
238
|
-
| `'top-center'` | Acima do elemento, centralizado |
|
|
239
|
-
| `'top-end'` | Acima do elemento, alinhado à direita |
|
|
240
|
-
| `'bottom-start'` | Abaixo do elemento, alinhado à esquerda |
|
|
241
|
-
| `'bottom-center'` | Abaixo do elemento, centralizado |
|
|
242
|
-
| `'bottom-end'` | Abaixo do elemento, alinhado à direita |
|
|
243
|
-
| `'left-start'` | À esquerda do elemento, alinhado ao topo |
|
|
244
|
-
| `'left-center'` | À esquerda do elemento, centralizado |
|
|
245
|
-
| `'left-end'` | À esquerda do elemento, alinhado à base |
|
|
246
|
-
| `'right-start'` | À direita do elemento, alinhado ao topo |
|
|
247
|
-
| `'right-center'` | À direita do elemento, centralizado |
|
|
248
|
-
| `'right-end'` | À direita do elemento, alinhado à base |
|
|
249
|
-
|
|
250
|
-
> O CDK ajusta automaticamente a posição quando não há espaço suficiente, garantindo que o popover sempre permaneça visível.
|
|
251
|
-
|
|
252
|
-
---
|
|
253
|
-
|
|
254
|
-
## Persistência
|
|
255
|
-
|
|
256
|
-
A persistência do estado (se o tour já foi visto, preferência "Não mostrar novamente", etc.) é responsabilidade do produto consumidor. Use os dados emitidos por `stopped$` para implementar a estratégia adequada:
|
|
257
|
-
|
|
258
|
-
```typescript
|
|
259
|
-
this.tourService.stopped$.subscribe((event) => {
|
|
260
|
-
const estado = {
|
|
261
|
-
reason: event.reason,
|
|
262
|
-
doNotShowAgain: event.doNotShowAgain,
|
|
263
|
-
contentVersion: 'v2', // versão do conteúdo do tour, controlada pelo produto
|
|
264
|
-
};
|
|
265
|
-
localStorage.setItem('tour-onboarding', JSON.stringify(estado));
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
// Na inicialização:
|
|
269
|
-
const salvo = JSON.parse(localStorage.getItem('tour-onboarding') ?? 'null');
|
|
270
|
-
const deveExibir =
|
|
271
|
-
!salvo ||
|
|
272
|
-
salvo.contentVersion !== 'v2' || // novo conteúdo → reexibir
|
|
273
|
-
salvo.reason === 'interrupted'; // não concluiu → reexibir
|
|
274
|
-
|
|
275
|
-
if (deveExibir && !salvo?.doNotShowAgain) {
|
|
276
|
-
// Chamar tourService.start(passos) no momento adequado
|
|
277
|
-
}
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
---
|
|
281
|
-
|
|
282
|
-
## Telemetria
|
|
283
|
-
|
|
284
|
-
Use os observables do serviço para enviar eventos ao seu sistema de analytics:
|
|
285
|
-
|
|
286
|
-
```typescript
|
|
287
|
-
// Tour iniciado (step 0)
|
|
288
|
-
this.tourService.stepChanged$
|
|
289
|
-
.pipe(filter((e) => e.stepIndex === 0 && e.totalSteps > 1))
|
|
290
|
-
.subscribe(() => analytics.track('tour_viewed'));
|
|
291
|
-
|
|
292
|
-
// Tour concluído
|
|
293
|
-
this.tourService.stopped$
|
|
294
|
-
.pipe(filter((e) => e.reason === 'completed' && e.totalSteps > 1))
|
|
295
|
-
.subscribe(() => analytics.track('tour_completed'));
|
|
296
|
-
|
|
297
|
-
// Tour interrompido
|
|
298
|
-
this.tourService.stopped$
|
|
299
|
-
.pipe(filter((e) => e.reason === 'interrupted'))
|
|
300
|
-
.subscribe(() => analytics.track('tour_interrupted'));
|
|
301
|
-
|
|
302
|
-
// Destaque simples fechado
|
|
303
|
-
this.tourService.stopped$
|
|
304
|
-
.pipe(filter((e) => e.reason === 'dismissed'))
|
|
305
|
-
.subscribe(() => analytics.track('spotlight_dismissed'));
|
|
306
|
-
|
|
307
|
-
// "Não mostrar novamente" marcado
|
|
308
|
-
this.tourService.stopped$
|
|
309
|
-
.pipe(filter((e) => e.doNotShowAgain))
|
|
310
|
-
.subscribe(() => analytics.track('spotlight_do_not_show_again_checked'));
|
|
311
|
-
```
|