@sd-angular/core 19.0.0-beta.98 → 19.0.3
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/README.md +720 -716
- package/assets/images/coming-soon.svg +23 -0
- package/assets/images/data-empty.svg +21 -0
- package/assets/images/expired.svg +22 -0
- package/assets/images/file-error.svg +28 -0
- package/assets/images/filter-empty.svg +20 -0
- package/assets/images/filter-required.svg +21 -0
- package/assets/images/forbidden.svg +15 -0
- package/assets/images/image-error.svg +27 -0
- package/assets/images/maintenance.svg +23 -0
- package/assets/images/not-found.svg +20 -0
- package/assets/images/offline.svg +20 -0
- package/assets/images/submitted.svg +18 -0
- package/assets/images/success.svg +18 -0
- package/assets/images/unauthorized.svg +22 -0
- package/assets/images/unknown-error.svg +18 -0
- package/assets/scss/README.md +433 -353
- package/assets/scss/core/_inline-edit.scss +105 -0
- package/assets/scss/core/form.scss +58 -1
- package/assets/scss/core/image.scss +35 -0
- package/assets/scss/core/utilities/_base.scss +6 -6
- package/assets/scss/core/utilities/_grid.scss +4 -3
- package/assets/scss/core/utilities/_index.scss +1 -1
- package/assets/scss/core/utilities/_sizing.scss +2 -2
- package/assets/scss/sd-core.scss +1 -2
- package/components/anchor/src/components/anchor/anchor.component.d.ts +5 -5
- package/components/anchor/src/components/anchor-nav/anchor-nav.component.d.ts +21 -0
- package/components/autoid-inspector/src/autoid-inspector.component.d.ts +18 -0
- package/components/autoid-inspector/src/models/autoid-element.model.d.ts +45 -1
- package/components/autoid-inspector/src/models/autoid-export-format.model.d.ts +19 -0
- package/components/autoid-inspector/src/services/autoid-export.service.d.ts +10 -2
- package/components/autoid-inspector/src/services/autoid-scanner.service.d.ts +26 -3
- package/components/badge/src/badge.component.d.ts +20 -3
- package/components/button/src/button.component.d.ts +2 -1
- package/components/ckeditor-styles/index.d.ts +1 -0
- package/components/ckeditor-styles/src/ckeditor-styles.component.d.ts +25 -0
- package/components/editor/src/editor.component.d.ts +2 -0
- package/components/form-generic/src/components/form-builder/form-builder.component.d.ts +12 -13
- package/components/form-generic/src/models/form-generic-component.model.d.ts +5 -6
- package/components/form-generic/src/models/form-generic-expression.model.d.ts +1 -1
- package/components/history/models/history.model.d.ts +2 -2
- package/components/index.d.ts +2 -0
- package/components/inform/index.d.ts +2 -0
- package/components/inform/src/inform-action.directive.d.ts +9 -0
- package/components/inform/src/inform.component.d.ts +59 -0
- package/components/modal/src/modal.component.d.ts +3 -1
- package/components/modal-resizable/index.d.ts +1 -0
- package/components/modal-resizable/src/modal-resizable.component.d.ts +29 -0
- package/components/operator/index.d.ts +1 -0
- package/components/operator/src/operator.component.d.ts +34 -0
- package/components/query-bar/index.d.ts +2 -0
- package/components/query-bar/src/components/actions-bar/actions-bar.component.d.ts +28 -0
- package/components/query-bar/src/components/build-chip/build-chip.component.d.ts +67 -0
- package/components/query-bar/src/components/chip-popover/chip-popover.component.d.ts +73 -0
- package/components/query-bar/src/components/field-picker/field-picker.component.d.ts +37 -0
- package/components/query-bar/src/components/inline-chip/inline-chip.component.d.ts +76 -0
- package/components/query-bar/src/components/inline-value-chip/inline-value-chip.component.d.ts +67 -0
- package/components/query-bar/src/components/popover-chip/popover-chip.component.d.ts +35 -0
- package/components/query-bar/src/components/saved-filters-menu/saved-filters-menu.component.d.ts +39 -0
- package/components/query-bar/src/query-bar.component.d.ts +137 -0
- package/components/query-bar/src/query-bar.model.d.ts +136 -0
- package/components/section/src/section.component.d.ts +2 -1
- package/components/side-drawer/src/side-drawer.component.d.ts +7 -3
- package/components/stepper/index.d.ts +2 -0
- package/components/stepper/src/step.component.d.ts +17 -0
- package/components/stepper/src/stepper.component.d.ts +33 -0
- package/components/tab/index.d.ts +2 -0
- package/components/tab/src/tab-group.component.d.ts +37 -0
- package/components/tab/src/tab.component.d.ts +13 -0
- package/components/tab-router/src/decorators/tab.decorator.d.ts +2 -2
- package/components/tab-router/src/models/tab-router.model.d.ts +2 -2
- package/components/table/index.d.ts +1 -0
- package/components/table/src/components/column-title/column-title.component.d.ts +1 -1
- package/components/table/src/components/command/desktop-command.component.d.ts +14 -0
- package/components/table/src/components/command/pipes/command.pipe.d.ts +30 -0
- package/components/table/src/components/command/pipes/filter.pipe.d.ts +35 -0
- package/components/table/src/components/config/config.component.d.ts +9 -14
- package/components/table/src/components/desktop-cell/desktop-cell.component.d.ts +4 -4
- package/components/table/src/components/filter/column-filter/column-filter.component.d.ts +32 -0
- package/components/table/src/components/filter/external-filter/external-filter.component.d.ts +27 -0
- package/components/table/src/components/filter/index.d.ts +3 -0
- package/components/table/src/components/filter/mobile-filter/mobile-filter.component.d.ts +42 -0
- package/components/table/src/components/index.d.ts +1 -2
- package/components/table/src/components/selector-action/selector-action.component.d.ts +5 -5
- package/components/table/src/configurations/table.configuration.d.ts +3 -3
- package/components/table/src/directives/index.d.ts +1 -0
- package/components/table/src/directives/sd-table-cell-def.directive.d.ts +13 -5
- package/components/table/src/directives/sd-table-column-filter-def.directive.d.ts +13 -5
- package/components/table/src/directives/sd-table-expand-def.directive.d.ts +10 -4
- package/components/table/src/directives/sd-table-filter-def.directive.d.ts +5 -5
- package/components/table/src/directives/sd-table-footer-def.directive.d.ts +13 -5
- package/components/table/src/directives/sd-table-group-def.directive.d.ts +44 -0
- package/components/table/src/directives/sd-table-title-def.directive.d.ts +11 -5
- package/components/table/src/models/index.d.ts +1 -0
- package/components/table/src/models/table-column.model.d.ts +13 -13
- package/components/table/src/models/table-command.model.d.ts +3 -2
- package/components/table/src/models/table-item.model.d.ts +19 -4
- package/components/table/src/models/table-option-export.model.d.ts +3 -3
- package/components/table/src/models/table-option-group.model.d.ts +19 -2
- package/components/table/src/models/table-option-selector.model.d.ts +17 -1
- package/components/table/src/models/table-option-tree.model.d.ts +96 -8
- package/components/table/src/models/table-option.model.d.ts +24 -2
- package/components/table/src/pipes/sd-group.pipe.d.ts +15 -1
- package/components/table/src/services/table-filter/table-filter.model.d.ts +9 -9
- package/components/table/src/services/table-filter/table-filter.service.d.ts +2 -2
- package/components/table/src/services/tree/tree.util.d.ts +43 -2
- package/components/table/src/table.component.d.ts +42 -14
- package/components/upload-file/src/upload-file.component.d.ts +3 -0
- package/components/view/src/view.component.d.ts +35 -1
- package/directives/src/sd-desktop.directive.d.ts +2 -4
- package/directives/src/sd-mobile.directive.d.ts +2 -4
- package/fesm2022/sd-angular-core-components-anchor.mjs +95 -62
- package/fesm2022/sd-angular-core-components-anchor.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-autoid-inspector.mjs +254 -29
- package/fesm2022/sd-angular-core-components-autoid-inspector.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-avatar.mjs +2 -2
- package/fesm2022/sd-angular-core-components-avatar.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-badge.mjs +18 -3
- package/fesm2022/sd-angular-core-components-badge.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-button.mjs +2 -2
- package/fesm2022/sd-angular-core-components-button.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-ckeditor-styles.mjs +38 -0
- package/fesm2022/sd-angular-core-components-ckeditor-styles.mjs.map +1 -0
- package/fesm2022/sd-angular-core-components-document-builder.mjs +10 -8
- package/fesm2022/sd-angular-core-components-document-builder.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-editor.mjs +6 -2
- package/fesm2022/sd-angular-core-components-editor.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-form-generic.mjs +151 -237
- package/fesm2022/sd-angular-core-components-form-generic.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-history.mjs +3 -2
- package/fesm2022/sd-angular-core-components-history.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-inform.mjs +190 -0
- package/fesm2022/sd-angular-core-components-inform.mjs.map +1 -0
- package/fesm2022/sd-angular-core-components-mini-editor.mjs +4 -3
- package/fesm2022/sd-angular-core-components-mini-editor.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-modal-resizable.mjs +158 -0
- package/fesm2022/sd-angular-core-components-modal-resizable.mjs.map +1 -0
- package/fesm2022/sd-angular-core-components-modal.mjs +5 -4
- package/fesm2022/sd-angular-core-components-modal.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-operator.mjs +77 -0
- package/fesm2022/sd-angular-core-components-operator.mjs.map +1 -0
- package/fesm2022/sd-angular-core-components-preview.mjs +4 -4
- package/fesm2022/sd-angular-core-components-preview.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-query-bar.mjs +1384 -0
- package/fesm2022/sd-angular-core-components-query-bar.mjs.map +1 -0
- package/fesm2022/sd-angular-core-components-quick-action.mjs +2 -2
- package/fesm2022/sd-angular-core-components-quick-action.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-section.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-side-drawer.mjs +17 -11
- package/fesm2022/sd-angular-core-components-side-drawer.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-splitter.mjs +5 -2
- package/fesm2022/sd-angular-core-components-splitter.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-stepper.mjs +140 -0
- package/fesm2022/sd-angular-core-components-stepper.mjs.map +1 -0
- package/fesm2022/sd-angular-core-components-tab-router.mjs +3 -3
- package/fesm2022/sd-angular-core-components-tab-router.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-tab.mjs +145 -0
- package/fesm2022/sd-angular-core-components-tab.mjs.map +1 -0
- package/fesm2022/sd-angular-core-components-table.mjs +1138 -725
- package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-upload-file.mjs +28 -23
- package/fesm2022/sd-angular-core-components-upload-file.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-view.mjs +44 -9
- package/fesm2022/sd-angular-core-components-view.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components.mjs +2 -0
- package/fesm2022/sd-angular-core-components.mjs.map +1 -1
- package/fesm2022/sd-angular-core-directives.mjs +19 -21
- package/fesm2022/sd-angular-core-directives.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-autocomplete.mjs +46 -14
- package/fesm2022/sd-angular-core-forms-autocomplete.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-checkbox.mjs +101 -85
- package/fesm2022/sd-angular-core-forms-checkbox.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-chip-calendar.mjs +101 -61
- package/fesm2022/sd-angular-core-forms-chip-calendar.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-chip.mjs +98 -52
- package/fesm2022/sd-angular-core-forms-chip.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-date-range.mjs +73 -10
- package/fesm2022/sd-angular-core-forms-date-range.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-date.mjs +45 -15
- package/fesm2022/sd-angular-core-forms-date.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-datetime.mjs +39 -14
- package/fesm2022/sd-angular-core-forms-datetime.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-directives.mjs +18 -24
- package/fesm2022/sd-angular-core-forms-directives.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-inline-text.mjs +167 -0
- package/fesm2022/sd-angular-core-forms-inline-text.mjs.map +1 -0
- package/fesm2022/sd-angular-core-forms-input-color.mjs +119 -0
- package/fesm2022/sd-angular-core-forms-input-color.mjs.map +1 -0
- package/fesm2022/sd-angular-core-forms-input-number.mjs +72 -14
- package/fesm2022/sd-angular-core-forms-input-number.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-input.mjs +96 -29
- package/fesm2022/sd-angular-core-forms-input.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-models.mjs +107 -2
- package/fesm2022/sd-angular-core-forms-models.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-radio.mjs +134 -174
- package/fesm2022/sd-angular-core-forms-radio.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-select.mjs +74 -23
- package/fesm2022/sd-angular-core-forms-select.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-switch.mjs +98 -96
- package/fesm2022/sd-angular-core-forms-switch.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-textarea.mjs +39 -12
- package/fesm2022/sd-angular-core-forms-textarea.mjs.map +1 -1
- package/fesm2022/sd-angular-core-i18n.mjs +270 -20
- package/fesm2022/sd-angular-core-i18n.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-auth.mjs +4 -4
- package/fesm2022/sd-angular-core-modules-auth.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-authom.mjs +1 -1
- package/fesm2022/sd-angular-core-modules-authom.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-layout.mjs +23 -23
- package/fesm2022/sd-angular-core-modules-layout.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-permission.mjs +3 -3
- package/fesm2022/sd-angular-core-modules-permission.mjs.map +1 -1
- package/fesm2022/sd-angular-core-pipes.mjs +2 -2
- package/fesm2022/sd-angular-core-pipes.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-api.mjs +3 -3
- package/fesm2022/sd-angular-core-services-api.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-cache.mjs +3 -2
- package/fesm2022/sd-angular-core-services-cache.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-confirm.mjs +1 -1
- package/fesm2022/sd-angular-core-services-confirm.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-excel.mjs +6 -5
- package/fesm2022/sd-angular-core-services-excel.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-notify.mjs +18 -5
- package/fesm2022/sd-angular-core-services-notify.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-storage.mjs +2 -2
- package/fesm2022/sd-angular-core-services-storage.mjs.map +1 -1
- package/fesm2022/sd-angular-core-utilities-data-state.mjs +38 -0
- package/fesm2022/sd-angular-core-utilities-data-state.mjs.map +1 -0
- package/fesm2022/sd-angular-core-utilities-models.mjs.map +1 -1
- package/fesm2022/sd-angular-core-utilities.mjs +1 -0
- package/fesm2022/sd-angular-core-utilities.mjs.map +1 -1
- package/forms/autocomplete/src/autocomplete.component.d.ts +29 -10
- package/forms/checkbox/src/checkbox.component.d.ts +24 -20
- package/forms/chip/src/chip.component.d.ts +29 -20
- package/forms/chip-calendar/src/chip-calendar.component.d.ts +31 -22
- package/forms/date/src/date.component.d.ts +27 -9
- package/forms/date-range/src/date-range.component.d.ts +32 -5
- package/forms/datetime/src/datetime.component.d.ts +25 -8
- package/forms/directives/src/item-def.directive.d.ts +10 -5
- package/forms/directives/src/label-def.directive.d.ts +3 -2
- package/forms/directives/src/suffix-def.directive.d.ts +3 -2
- package/forms/directives/src/view-def.directive.d.ts +9 -9
- package/forms/inline-text/index.d.ts +1 -0
- package/forms/inline-text/src/inline-text.component.d.ts +76 -0
- package/forms/input/src/input.component.d.ts +35 -13
- package/forms/input-color/index.d.ts +1 -0
- package/forms/input-color/src/input-color.component.d.ts +34 -0
- package/forms/input-number/src/input-number.component.d.ts +31 -11
- package/forms/models/index.d.ts +2 -0
- package/forms/models/src/form-control-state.d.ts +23 -0
- package/forms/models/src/sd-custom-validator.model.d.ts +13 -1
- package/forms/models/src/sd-viewed.d.ts +38 -0
- package/forms/radio/src/radio.component.d.ts +37 -35
- package/forms/select/src/select.component.d.ts +41 -14
- package/forms/switch/src/switch.component.d.ts +25 -23
- package/forms/textarea/src/textarea.component.d.ts +22 -8
- package/i18n/src/en.d.ts +50 -3
- package/modules/auth/configurations/auth.configuration.d.ts +4 -4
- package/modules/layout/configurations/layout.configuration.d.ts +3 -3
- package/modules/permission/src/configurations/permission.configuration.d.ts +3 -3
- package/package.json +89 -49
- package/sd-angular-core-19.0.3.tgz +0 -0
- package/services/confirm/src/lib/components/dialog-confirm/dialog-confirm.component.d.ts +3 -3
- package/services/confirm/src/lib/confirm.service.d.ts +9 -9
- package/services/notify/src/components/toast/toast.component.d.ts +4 -0
- package/utilities/data-state/index.d.ts +1 -0
- package/utilities/data-state/src/data-state.d.ts +11 -0
- package/utilities/index.d.ts +1 -0
- package/utilities/models/src/icon.model.d.ts +1 -1
- package/assets/scss/bootstrap-4.6.2/_alert.scss +0 -52
- package/assets/scss/bootstrap-4.6.2/_badge.scss +0 -54
- package/assets/scss/bootstrap-4.6.2/_breadcrumb.scss +0 -42
- package/assets/scss/bootstrap-4.6.2/_button-group.scss +0 -163
- package/assets/scss/bootstrap-4.6.2/_buttons.scss +0 -142
- package/assets/scss/bootstrap-4.6.2/_card.scss +0 -286
- package/assets/scss/bootstrap-4.6.2/_carousel.scss +0 -200
- package/assets/scss/bootstrap-4.6.2/_close.scss +0 -40
- package/assets/scss/bootstrap-4.6.2/_code.scss +0 -48
- package/assets/scss/bootstrap-4.6.2/_custom-forms.scss +0 -526
- package/assets/scss/bootstrap-4.6.2/_dropdown.scss +0 -192
- package/assets/scss/bootstrap-4.6.2/_forms.scss +0 -347
- package/assets/scss/bootstrap-4.6.2/_functions.scss +0 -190
- package/assets/scss/bootstrap-4.6.2/_grid.scss +0 -73
- package/assets/scss/bootstrap-4.6.2/_images.scss +0 -42
- package/assets/scss/bootstrap-4.6.2/_input-group.scss +0 -211
- package/assets/scss/bootstrap-4.6.2/_jumbotron.scss +0 -17
- package/assets/scss/bootstrap-4.6.2/_list-group.scss +0 -154
- package/assets/scss/bootstrap-4.6.2/_media.scss +0 -8
- package/assets/scss/bootstrap-4.6.2/_mixins.scss +0 -47
- package/assets/scss/bootstrap-4.6.2/_modal.scss +0 -240
- package/assets/scss/bootstrap-4.6.2/_nav.scss +0 -125
- package/assets/scss/bootstrap-4.6.2/_navbar.scss +0 -332
- package/assets/scss/bootstrap-4.6.2/_pagination.scss +0 -74
- package/assets/scss/bootstrap-4.6.2/_popover.scss +0 -170
- package/assets/scss/bootstrap-4.6.2/_print.scss +0 -132
- package/assets/scss/bootstrap-4.6.2/_progress.scss +0 -47
- package/assets/scss/bootstrap-4.6.2/_reboot.scss +0 -484
- package/assets/scss/bootstrap-4.6.2/_root.scss +0 -19
- package/assets/scss/bootstrap-4.6.2/_spinners.scss +0 -65
- package/assets/scss/bootstrap-4.6.2/_tables.scss +0 -185
- package/assets/scss/bootstrap-4.6.2/_toasts.scss +0 -46
- package/assets/scss/bootstrap-4.6.2/_tooltip.scss +0 -115
- package/assets/scss/bootstrap-4.6.2/_transitions.scss +0 -26
- package/assets/scss/bootstrap-4.6.2/_type.scss +0 -125
- package/assets/scss/bootstrap-4.6.2/_utilities.scss +0 -18
- package/assets/scss/bootstrap-4.6.2/_variables.scss +0 -1150
- package/assets/scss/bootstrap-4.6.2/bootstrap-grid.scss +0 -30
- package/assets/scss/bootstrap-4.6.2/bootstrap-reboot.scss +0 -12
- package/assets/scss/bootstrap-4.6.2/bootstrap.scss +0 -44
- package/assets/scss/bootstrap-4.6.2/mixins/_alert.scss +0 -13
- package/assets/scss/bootstrap-4.6.2/mixins/_background-variant.scss +0 -23
- package/assets/scss/bootstrap-4.6.2/mixins/_badge.scss +0 -17
- package/assets/scss/bootstrap-4.6.2/mixins/_border-radius.scss +0 -76
- package/assets/scss/bootstrap-4.6.2/mixins/_box-shadow.scss +0 -20
- package/assets/scss/bootstrap-4.6.2/mixins/_breakpoints.scss +0 -123
- package/assets/scss/bootstrap-4.6.2/mixins/_buttons.scss +0 -110
- package/assets/scss/bootstrap-4.6.2/mixins/_caret.scss +0 -62
- package/assets/scss/bootstrap-4.6.2/mixins/_clearfix.scss +0 -7
- package/assets/scss/bootstrap-4.6.2/mixins/_deprecate.scss +0 -10
- package/assets/scss/bootstrap-4.6.2/mixins/_float.scss +0 -14
- package/assets/scss/bootstrap-4.6.2/mixins/_forms.scss +0 -195
- package/assets/scss/bootstrap-4.6.2/mixins/_gradients.scss +0 -45
- package/assets/scss/bootstrap-4.6.2/mixins/_grid-framework.scss +0 -80
- package/assets/scss/bootstrap-4.6.2/mixins/_grid.scss +0 -69
- package/assets/scss/bootstrap-4.6.2/mixins/_hover.scss +0 -37
- package/assets/scss/bootstrap-4.6.2/mixins/_image.scss +0 -36
- package/assets/scss/bootstrap-4.6.2/mixins/_list-group.scss +0 -21
- package/assets/scss/bootstrap-4.6.2/mixins/_lists.scss +0 -7
- package/assets/scss/bootstrap-4.6.2/mixins/_nav-divider.scss +0 -11
- package/assets/scss/bootstrap-4.6.2/mixins/_pagination.scss +0 -22
- package/assets/scss/bootstrap-4.6.2/mixins/_reset-text.scss +0 -17
- package/assets/scss/bootstrap-4.6.2/mixins/_resize.scss +0 -6
- package/assets/scss/bootstrap-4.6.2/mixins/_screen-reader.scss +0 -34
- package/assets/scss/bootstrap-4.6.2/mixins/_size.scss +0 -7
- package/assets/scss/bootstrap-4.6.2/mixins/_table-row.scss +0 -39
- package/assets/scss/bootstrap-4.6.2/mixins/_text-emphasis.scss +0 -17
- package/assets/scss/bootstrap-4.6.2/mixins/_text-hide.scss +0 -11
- package/assets/scss/bootstrap-4.6.2/mixins/_text-truncate.scss +0 -8
- package/assets/scss/bootstrap-4.6.2/mixins/_transition.scss +0 -26
- package/assets/scss/bootstrap-4.6.2/mixins/_visibility.scss +0 -8
- package/assets/scss/bootstrap-4.6.2/utilities/_align.scss +0 -8
- package/assets/scss/bootstrap-4.6.2/utilities/_background.scss +0 -19
- package/assets/scss/bootstrap-4.6.2/utilities/_borders.scss +0 -75
- package/assets/scss/bootstrap-4.6.2/utilities/_clearfix.scss +0 -3
- package/assets/scss/bootstrap-4.6.2/utilities/_display.scss +0 -26
- package/assets/scss/bootstrap-4.6.2/utilities/_embed.scss +0 -39
- package/assets/scss/bootstrap-4.6.2/utilities/_flex.scss +0 -51
- package/assets/scss/bootstrap-4.6.2/utilities/_float.scss +0 -11
- package/assets/scss/bootstrap-4.6.2/utilities/_interactions.scss +0 -5
- package/assets/scss/bootstrap-4.6.2/utilities/_overflow.scss +0 -5
- package/assets/scss/bootstrap-4.6.2/utilities/_position.scss +0 -32
- package/assets/scss/bootstrap-4.6.2/utilities/_screenreaders.scss +0 -11
- package/assets/scss/bootstrap-4.6.2/utilities/_shadows.scss +0 -6
- package/assets/scss/bootstrap-4.6.2/utilities/_sizing.scss +0 -20
- package/assets/scss/bootstrap-4.6.2/utilities/_spacing.scss +0 -73
- package/assets/scss/bootstrap-4.6.2/utilities/_stretched-link.scss +0 -19
- package/assets/scss/bootstrap-4.6.2/utilities/_text.scss +0 -72
- package/assets/scss/bootstrap-4.6.2/utilities/_visibility.scss +0 -13
- package/assets/scss/bootstrap-4.6.2/vendor/_rfs.scss +0 -228
- package/assets/scss/core/bootstrap.scss +0 -13
- package/components/anchor/src/components/anchor-vertical/anchor-vertical-list.component.d.ts +0 -18
- package/components/table/src/components/column-filter/column-filter.component.d.ts +0 -40
- package/components/table/src/components/desktop-command/desktop-command.component.d.ts +0 -15
- package/components/table/src/components/external-filter/external-filter.component.d.ts +0 -36
- package/components/table/src/pipes/command-disable.pipe.d.ts +0 -9
- package/components/table/src/pipes/command-filter.pipe.d.ts +0 -25
- package/components/table/src/pipes/command-title.pipe.d.ts +0 -9
- package/sd-angular-core-19.0.0-beta.98.tgz +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { InjectionToken } from '@angular/core';
|
|
1
|
+
import { InjectionToken, signal, inject, DestroyRef, effect, untracked, computed, booleanAttribute } from '@angular/core';
|
|
2
2
|
import { FormControl } from '@angular/forms';
|
|
3
3
|
import { Subject } from 'rxjs';
|
|
4
|
+
import { startWith } from 'rxjs/operators';
|
|
4
5
|
|
|
5
6
|
const SD_FORM_CONFIGURATION = new InjectionToken('sd.form.configuration');
|
|
6
7
|
|
|
@@ -29,6 +30,18 @@ class SdFormControl extends FormControl {
|
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Inline-error sentinel validator. Returns `{ inlineError: true }` so the form
|
|
35
|
+
* template can render `<mat-error>{{ inlineError }}</mat-error>` whenever the
|
|
36
|
+
* host component has a non-empty `[inlineError]` input. The error message
|
|
37
|
+
* itself is read from the input — this validator only flags the state.
|
|
38
|
+
*
|
|
39
|
+
* why: each form component (input, textarea, select, checkbox, radio, switch,
|
|
40
|
+
* date, datetime, input-number, autocomplete) previously declared the same
|
|
41
|
+
* private `customInlineErrorValidator()` method. Centralized here so adding
|
|
42
|
+
* another form component does not silently re-introduce the duplicate.
|
|
43
|
+
*/
|
|
44
|
+
const SdInlineErrorValidator = () => ({ inlineError: true });
|
|
32
45
|
const HandleSdCustomValidator = (func) => {
|
|
33
46
|
return async (c) => {
|
|
34
47
|
const value = c.value === 0 ? c.value : c.value || null;
|
|
@@ -54,9 +67,101 @@ const HandleSdCustomValidator = (func) => {
|
|
|
54
67
|
};
|
|
55
68
|
};
|
|
56
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Wrap an AbstractControl Signal into a reactive snapshot signal.
|
|
72
|
+
*
|
|
73
|
+
* Re-emits on every value, status, touched, or dirty change so
|
|
74
|
+
* downstream consumers can derive `data-disabled`, `data-value`,
|
|
75
|
+
* `data-empty`, and `data-invalid` host-binding attributes from a
|
|
76
|
+
* single, lazily evaluated signal.
|
|
77
|
+
*
|
|
78
|
+
* "invalid" is intentionally gated on `touched || dirty` so validation
|
|
79
|
+
* errors are not surfaced until the user has interacted with the field.
|
|
80
|
+
*
|
|
81
|
+
* Must be called inside an Angular injection context (constructor,
|
|
82
|
+
* field initialiser, or `runInInjectionContext`).
|
|
83
|
+
*/
|
|
84
|
+
function sdFormControlState(control) {
|
|
85
|
+
// A tick counter incremented on every control event (value, status,
|
|
86
|
+
// touched, dirty). Written only from the effect below — never inside
|
|
87
|
+
// a computed() — satisfying Angular's no-side-effect-in-reactive rule.
|
|
88
|
+
const tick = signal(0);
|
|
89
|
+
const destroyRef = inject(DestroyRef);
|
|
90
|
+
// Holds the active RxJS subscription so it can be torn down when the
|
|
91
|
+
// control instance changes or the host component is destroyed.
|
|
92
|
+
let subscription = null;
|
|
93
|
+
// An effect re-runs whenever the control Signal changes, tears down the
|
|
94
|
+
// old subscription and creates a fresh one for the incoming control.
|
|
95
|
+
// `AbstractControl.events` (Angular 14+) covers value, status, touched,
|
|
96
|
+
// and dirty changes — a superset of valueChanges + statusChanges.
|
|
97
|
+
const effectRef = effect(() => {
|
|
98
|
+
const c = control(); // tracked — effect re-runs on change
|
|
99
|
+
// effect() runs asynchronously; the old subscription is torn down on the next
|
|
100
|
+
// scheduled run, not synchronously on signal change. A one-tick window of
|
|
101
|
+
// double-subscription is harmless due to computed() memoization.
|
|
102
|
+
subscription?.unsubscribe();
|
|
103
|
+
subscription = null;
|
|
104
|
+
if (c) {
|
|
105
|
+
subscription = c.events.pipe(startWith(null)).subscribe(() => {
|
|
106
|
+
// Increment outside reactive context to avoid Angular's
|
|
107
|
+
// "signal written from computed / template" error.
|
|
108
|
+
untracked(() => tick.update(n => n + 1));
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
// Clean up effect and subscription when host component is destroyed.
|
|
113
|
+
destroyRef.onDestroy(() => {
|
|
114
|
+
effectRef.destroy();
|
|
115
|
+
subscription?.unsubscribe();
|
|
116
|
+
});
|
|
117
|
+
return computed(() => {
|
|
118
|
+
const _control = control();
|
|
119
|
+
tick(); // reactive dependency — recomputes on every control event
|
|
120
|
+
if (!_control) {
|
|
121
|
+
return { value: undefined, disabled: false, invalid: false, touched: false };
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
value: _control.value,
|
|
125
|
+
disabled: _control.disabled,
|
|
126
|
+
invalid: _control.invalid && (_control.touched || _control.dirty),
|
|
127
|
+
touched: _control.touched,
|
|
128
|
+
};
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* `viewed` input transform. Keeps `booleanAttribute` coercion so a bare attribute
|
|
134
|
+
* (`<sd-select viewed>`) still resolves to `true`, but intercepts the literal
|
|
135
|
+
* `'inline'` first — `booleanAttribute('inline')` would otherwise coerce it to `true`.
|
|
136
|
+
*/
|
|
137
|
+
function sdViewedTransform(v) {
|
|
138
|
+
return v === 'inline' ? 'inline' : booleanAttribute(v);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Compose the tri-state `viewed` semantics into a control. `open` opens the control's
|
|
142
|
+
* native picker (mat-select panel / mat-calendar / overlay). In `'inline'` mode the editor
|
|
143
|
+
* is always rendered (chrome hidden via CSS), so `open()` can fire immediately on click —
|
|
144
|
+
* no render-swap, the view text never disappears.
|
|
145
|
+
*
|
|
146
|
+
* @param viewed the control's `viewed` input signal.
|
|
147
|
+
* @param open opens the control's picker; called by `enterInlineEdit`.
|
|
148
|
+
* @param disabled the control's disabled state. why: a disabled `'inline'` field must behave
|
|
149
|
+
* like `viewed=true` (static, NOT click-to-edit) — you can't edit a disabled control.
|
|
150
|
+
*/
|
|
151
|
+
function sdViewedInline(viewed, open, disabled) {
|
|
152
|
+
// why: disabled biến 'inline' thành static view (isInline=false, isViewed=true) — không cho sửa.
|
|
153
|
+
const isInline = computed(() => viewed() === 'inline' && !disabled?.());
|
|
154
|
+
const isViewed = computed(() => viewed() === true || (viewed() === 'inline' && !!disabled?.()));
|
|
155
|
+
const enterInlineEdit = () => {
|
|
156
|
+
if (isInline())
|
|
157
|
+
open?.();
|
|
158
|
+
};
|
|
159
|
+
return { isInline, isViewed, enterInlineEdit };
|
|
160
|
+
}
|
|
161
|
+
|
|
57
162
|
/**
|
|
58
163
|
* Generated bundle index. Do not edit.
|
|
59
164
|
*/
|
|
60
165
|
|
|
61
|
-
export { HandleSdCustomValidator, SD_FORM_CONFIGURATION, SdFormControl };
|
|
166
|
+
export { HandleSdCustomValidator, SD_FORM_CONFIGURATION, SdFormControl, SdInlineErrorValidator, sdFormControlState, sdViewedInline, sdViewedTransform };
|
|
62
167
|
//# sourceMappingURL=sd-angular-core-forms-models.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sd-angular-core-forms-models.mjs","sources":["../../../projects/sd-angular/forms/models/src/sd-form.configuration.ts","../../../projects/sd-angular/forms/models/src/sd-form-control.model.ts","../../../projects/sd-angular/forms/models/src/sd-custom-validator.model.ts","../../../projects/sd-angular/forms/models/sd-angular-core-forms-models.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport { MatFormFieldAppearance } from '@angular/material/form-field';\n\nexport interface ISdFormConfiguration {\n appearance?: MatFormFieldAppearance;\n}\n\nexport const SD_FORM_CONFIGURATION = new InjectionToken<ISdFormConfiguration>('sd.form.configuration');\n","import { FormControl, AsyncValidatorFn, ValidatorFn, FormControlOptions, FormControlState } from '@angular/forms';\nimport { Subject } from 'rxjs';\n\nexport class SdFormControl extends FormControl {\n sdChanges: Subject<boolean> = new Subject<boolean>();\n untouchChanges: Subject<boolean> = new Subject<boolean>();\n touchChanges: Subject<boolean> = new Subject<boolean>();\n pristineChanges: Subject<boolean> = new Subject<boolean>();\n constructor(\n formState?: FormControlState<any>,\n validatorOrOpts?: ValidatorFn | ValidatorFn[] | FormControlOptions | null,\n asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null\n ) {\n super(formState, validatorOrOpts, asyncValidator);\n }\n\n override markAsUntouched(opts?: { onlySelf?: boolean; emitEvent?: boolean }): void {\n super.markAsUntouched(opts);\n this.untouchChanges.next(true);\n this.sdChanges.next(true);\n }\n\n override markAsTouched(opts?: { onlySelf?: boolean; emitEvent?: boolean }): void {\n super.markAsTouched(opts);\n this.touchChanges.next(true);\n this.sdChanges.next(true);\n }\n\n override markAsPristine(opts?: { onlySelf?: boolean; emitEvent?: boolean }): void {\n super.markAsPristine(opts);\n this.pristineChanges.next(true);\n this.sdChanges.next(true);\n }\n}\n","import { AbstractControl, AsyncValidatorFn } from '@angular/forms';\r\n\r\nexport type SdCustomValidator = (value: any) => string | Promise<string>;\r\nexport const HandleSdCustomValidator = (func: SdCustomValidator): AsyncValidatorFn => {\r\n return async (c: AbstractControl): Promise<Record<string, any> | null> => { \r\n const value = c.value===0 ? c.value : c.value || null;\r\n if (func && typeof func === 'function') {\r\n const result = func(value);\r\n if (result instanceof Promise) {\r\n const message = await result;\r\n if (message) {\r\n return {\r\n customValidator: message,\r\n };\r\n }\r\n return null;\r\n }\r\n if (result) {\r\n return {\r\n customValidator: result,\r\n };\r\n }\r\n return null;\r\n }\r\n return null;\r\n };\r\n};\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;MAOa,qBAAqB,GAAG,IAAI,cAAc,CAAuB,uBAAuB;;ACJ/F,MAAO,aAAc,SAAQ,WAAW,CAAA;AAC5C,IAAA,SAAS,GAAqB,IAAI,OAAO,EAAW;AACpD,IAAA,cAAc,GAAqB,IAAI,OAAO,EAAW;AACzD,IAAA,YAAY,GAAqB,IAAI,OAAO,EAAW;AACvD,IAAA,eAAe,GAAqB,IAAI,OAAO,EAAW;AAC1D,IAAA,WAAA,CACE,SAAiC,EACjC,eAAyE,EACzE,cAA6D,EAAA;AAE7D,QAAA,KAAK,CAAC,SAAS,EAAE,eAAe,EAAE,cAAc,CAAC;IACnD;AAES,IAAA,eAAe,CAAC,IAAkD,EAAA;AACzE,QAAA,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC;AAC3B,QAAA,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;AAC9B,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;IAC3B;AAES,IAAA,aAAa,CAAC,IAAkD,EAAA;AACvE,QAAA,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC;AACzB,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;AAC5B,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;IAC3B;AAES,IAAA,cAAc,CAAC,IAAkD,EAAA;AACxE,QAAA,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC;AAC1B,QAAA,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;AAC/B,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;IAC3B;AACD;;AC9BM,MAAM,uBAAuB,GAAG,CAAC,IAAuB,KAAsB;AACnF,IAAA,OAAO,OAAO,CAAkB,KAAyC;QACvE,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,KAAG,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,IAAI;AACrD,QAAA,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE;AACtC,YAAA,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC;AAC1B,YAAA,IAAI,MAAM,YAAY,OAAO,EAAE;AAC7B,gBAAA,MAAM,OAAO,GAAG,MAAM,MAAM;gBAC5B,IAAI,OAAO,EAAE;oBACX,OAAO;AACL,wBAAA,eAAe,EAAE,OAAO;qBACzB;gBACH;AACA,gBAAA,OAAO,IAAI;YACb;YACA,IAAI,MAAM,EAAE;gBACV,OAAO;AACL,oBAAA,eAAe,EAAE,MAAM;iBACxB;YACH;AACA,YAAA,OAAO,IAAI;QACb;AACA,QAAA,OAAO,IAAI;AACb,IAAA,CAAC;AACH;;AC1BA;;AAEG;;;;"}
|
|
1
|
+
{"version":3,"file":"sd-angular-core-forms-models.mjs","sources":["../../../projects/sd-angular/forms/models/src/sd-form.configuration.ts","../../../projects/sd-angular/forms/models/src/sd-form-control.model.ts","../../../projects/sd-angular/forms/models/src/sd-custom-validator.model.ts","../../../projects/sd-angular/forms/models/src/form-control-state.ts","../../../projects/sd-angular/forms/models/src/sd-viewed.ts","../../../projects/sd-angular/forms/models/sd-angular-core-forms-models.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport { MatFormFieldAppearance } from '@angular/material/form-field';\n\nexport interface ISdFormConfiguration {\n appearance?: MatFormFieldAppearance;\n}\n\nexport const SD_FORM_CONFIGURATION = new InjectionToken<ISdFormConfiguration>('sd.form.configuration');\n","import { FormControl, AsyncValidatorFn, ValidatorFn, FormControlOptions, FormControlState } from '@angular/forms';\nimport { Subject } from 'rxjs';\n\nexport class SdFormControl extends FormControl {\n sdChanges: Subject<boolean> = new Subject<boolean>();\n untouchChanges: Subject<boolean> = new Subject<boolean>();\n touchChanges: Subject<boolean> = new Subject<boolean>();\n pristineChanges: Subject<boolean> = new Subject<boolean>();\n constructor(\n formState?: FormControlState<any>,\n validatorOrOpts?: ValidatorFn | ValidatorFn[] | FormControlOptions | null,\n asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null\n ) {\n super(formState, validatorOrOpts, asyncValidator);\n }\n\n override markAsUntouched(opts?: { onlySelf?: boolean; emitEvent?: boolean }): void {\n super.markAsUntouched(opts);\n this.untouchChanges.next(true);\n this.sdChanges.next(true);\n }\n\n override markAsTouched(opts?: { onlySelf?: boolean; emitEvent?: boolean }): void {\n super.markAsTouched(opts);\n this.touchChanges.next(true);\n this.sdChanges.next(true);\n }\n\n override markAsPristine(opts?: { onlySelf?: boolean; emitEvent?: boolean }): void {\n super.markAsPristine(opts);\n this.pristineChanges.next(true);\n this.sdChanges.next(true);\n }\n}\n","import { AbstractControl, AsyncValidatorFn, ValidatorFn } from '@angular/forms';\r\n\r\nexport type SdCustomValidator = (value: any) => string | Promise<string>;\r\n\r\n/**\r\n * Inline-error sentinel validator. Returns `{ inlineError: true }` so the form\r\n * template can render `<mat-error>{{ inlineError }}</mat-error>` whenever the\r\n * host component has a non-empty `[inlineError]` input. The error message\r\n * itself is read from the input — this validator only flags the state.\r\n *\r\n * why: each form component (input, textarea, select, checkbox, radio, switch,\r\n * date, datetime, input-number, autocomplete) previously declared the same\r\n * private `customInlineErrorValidator()` method. Centralized here so adding\r\n * another form component does not silently re-introduce the duplicate.\r\n */\r\nexport const SdInlineErrorValidator: ValidatorFn = (): Record<string, unknown> | null => ({ inlineError: true });\r\n\r\nexport const HandleSdCustomValidator = (func: SdCustomValidator): AsyncValidatorFn => {\r\n return async (c: AbstractControl): Promise<Record<string, any> | null> => { \r\n const value = c.value===0 ? c.value : c.value || null;\r\n if (func && typeof func === 'function') {\r\n const result = func(value);\r\n if (result instanceof Promise) {\r\n const message = await result;\r\n if (message) {\r\n return {\r\n customValidator: message,\r\n };\r\n }\r\n return null;\r\n }\r\n if (result) {\r\n return {\r\n customValidator: result,\r\n };\r\n }\r\n return null;\r\n }\r\n return null;\r\n };\r\n};\r\n","import { DestroyRef, EffectRef, Signal, computed, effect, inject, signal, untracked } from '@angular/core';\r\nimport { AbstractControl } from '@angular/forms';\r\nimport { Subscription } from 'rxjs';\r\nimport { startWith } from 'rxjs/operators';\r\n\r\nexport interface SdFormControlSnapshot<T> {\r\n value: T | undefined;\r\n disabled: boolean;\r\n invalid: boolean;\r\n touched: boolean;\r\n}\r\n\r\n/**\r\n * Wrap an AbstractControl Signal into a reactive snapshot signal.\r\n *\r\n * Re-emits on every value, status, touched, or dirty change so\r\n * downstream consumers can derive `data-disabled`, `data-value`,\r\n * `data-empty`, and `data-invalid` host-binding attributes from a\r\n * single, lazily evaluated signal.\r\n *\r\n * \"invalid\" is intentionally gated on `touched || dirty` so validation\r\n * errors are not surfaced until the user has interacted with the field.\r\n *\r\n * Must be called inside an Angular injection context (constructor,\r\n * field initialiser, or `runInInjectionContext`).\r\n */\r\nexport function sdFormControlState<T = unknown>(\r\n control: Signal<AbstractControl<T> | null | undefined>\r\n): Signal<SdFormControlSnapshot<T>> {\r\n // A tick counter incremented on every control event (value, status,\r\n // touched, dirty). Written only from the effect below — never inside\r\n // a computed() — satisfying Angular's no-side-effect-in-reactive rule.\r\n const tick = signal(0);\r\n const destroyRef = inject(DestroyRef);\r\n\r\n // Holds the active RxJS subscription so it can be torn down when the\r\n // control instance changes or the host component is destroyed.\r\n let subscription: Subscription | null = null;\r\n\r\n // An effect re-runs whenever the control Signal changes, tears down the\r\n // old subscription and creates a fresh one for the incoming control.\r\n // `AbstractControl.events` (Angular 14+) covers value, status, touched,\r\n // and dirty changes — a superset of valueChanges + statusChanges.\r\n const effectRef: EffectRef = effect(() => {\r\n const c = control(); // tracked — effect re-runs on change\r\n // effect() runs asynchronously; the old subscription is torn down on the next\r\n // scheduled run, not synchronously on signal change. A one-tick window of\r\n // double-subscription is harmless due to computed() memoization.\r\n subscription?.unsubscribe();\r\n subscription = null;\r\n\r\n if (c) {\r\n subscription = c.events.pipe(startWith(null)).subscribe(() => {\r\n // Increment outside reactive context to avoid Angular's\r\n // \"signal written from computed / template\" error.\r\n untracked(() => tick.update(n => n + 1));\r\n });\r\n }\r\n });\r\n\r\n // Clean up effect and subscription when host component is destroyed.\r\n destroyRef.onDestroy(() => {\r\n effectRef.destroy();\r\n subscription?.unsubscribe();\r\n });\r\n\r\n return computed((): SdFormControlSnapshot<T> => {\r\n const _control = control();\r\n tick(); // reactive dependency — recomputes on every control event\r\n\r\n if (!_control) {\r\n return { value: undefined, disabled: false, invalid: false, touched: false };\r\n }\r\n\r\n return {\r\n value: _control.value as T,\r\n disabled: _control.disabled,\r\n invalid: _control.invalid && (_control.touched || _control.dirty),\r\n touched: _control.touched,\r\n };\r\n });\r\n}\r\n","import { booleanAttribute, computed, Signal } from '@angular/core';\n\n/**\n * Three display states shared by sd-form-controls:\n * - `false` → full edit chrome (input / dropdown).\n * - `true` → static read-only view (`<sd-view>` text), no editor.\n * - `'inline'` → the editor is STILL rendered (so its panel works), but its chrome is\n * hidden; the `<sd-view>` text is the visible face / trigger. Click the text to open\n * the picker's panel. The text is retained while the panel is open — it only changes\n * when a new value is committed (JIRA-style click-to-edit).\n */\nexport type SdViewed = boolean | 'inline';\nexport type SdViewedInput = SdViewed | '' | null | undefined;\n\n/**\n * `viewed` input transform. Keeps `booleanAttribute` coercion so a bare attribute\n * (`<sd-select viewed>`) still resolves to `true`, but intercepts the literal\n * `'inline'` first — `booleanAttribute('inline')` would otherwise coerce it to `true`.\n */\nexport function sdViewedTransform(v: SdViewedInput): SdViewed {\n return v === 'inline' ? 'inline' : booleanAttribute(v);\n}\n\nexport interface SdViewedInlineApi {\n /** `viewed() === 'inline'` — editor rendered but chrome hidden; sd-view text is the trigger face. */\n readonly isInline: Signal<boolean>;\n /** `viewed() === true` — static read-only view (no editor rendered). */\n readonly isViewed: Signal<boolean>;\n /** Open the picker from the inline text face. No-op unless `'inline'`. */\n enterInlineEdit(): void;\n}\n\n/**\n * Compose the tri-state `viewed` semantics into a control. `open` opens the control's\n * native picker (mat-select panel / mat-calendar / overlay). In `'inline'` mode the editor\n * is always rendered (chrome hidden via CSS), so `open()` can fire immediately on click —\n * no render-swap, the view text never disappears.\n *\n * @param viewed the control's `viewed` input signal.\n * @param open opens the control's picker; called by `enterInlineEdit`.\n * @param disabled the control's disabled state. why: a disabled `'inline'` field must behave\n * like `viewed=true` (static, NOT click-to-edit) — you can't edit a disabled control.\n */\nexport function sdViewedInline(viewed: Signal<SdViewed>, open?: () => void, disabled?: Signal<boolean>): SdViewedInlineApi {\n // why: disabled biến 'inline' thành static view (isInline=false, isViewed=true) — không cho sửa.\n const isInline = computed(() => viewed() === 'inline' && !disabled?.());\n const isViewed = computed(() => viewed() === true || (viewed() === 'inline' && !!disabled?.()));\n const enterInlineEdit = (): void => {\n if (isInline()) open?.();\n };\n return { isInline, isViewed, enterInlineEdit };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as i1 from '@angular/common';
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { input,
|
|
4
|
+
import { inject, ChangeDetectorRef, input, booleanAttribute, model, contentChild, output, computed, effect, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
5
5
|
import * as i2 from '@angular/forms';
|
|
6
|
-
import { NgForm, Validators, ReactiveFormsModule } from '@angular/forms';
|
|
6
|
+
import { NgForm, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
|
|
7
7
|
import * as i3 from '@angular/material/form-field';
|
|
8
8
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
9
9
|
import { MatIconModule } from '@angular/material/icon';
|
|
@@ -13,219 +13,179 @@ import { MatTooltipModule } from '@angular/material/tooltip';
|
|
|
13
13
|
import { Subscription } from 'rxjs';
|
|
14
14
|
import * as uuid from 'uuid';
|
|
15
15
|
import { SdSuffixDefDirective, SdLabelDefDirective, SdViewDefDirective } from '@sd-angular/core/forms/directives';
|
|
16
|
-
import { SdFormControl } from '@sd-angular/core/forms/models';
|
|
16
|
+
import { SdFormControl, sdViewedTransform, sdViewedInline, sdFormControlState, SdInlineErrorValidator } from '@sd-angular/core/forms/models';
|
|
17
|
+
import { sdIsEmpty, sdSerializeDataValue } from '@sd-angular/core/utilities/data-state';
|
|
17
18
|
import { TranslatePipe } from '@sd-angular/core/i18n';
|
|
18
19
|
import { SdEmptyPipe } from '@sd-angular/core/pipes';
|
|
19
20
|
import { SdLabel } from '@sd-angular/core/forms/label';
|
|
20
21
|
import { SdHrefDirective } from '@sd-angular/core/directives';
|
|
21
22
|
|
|
22
|
-
/* eslint-disable @angular-eslint/no-input-rename */
|
|
23
23
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
24
24
|
// eslint-disable-next-line @angular-eslint/component-class-suffix
|
|
25
25
|
class SdRadio {
|
|
26
|
-
ref;
|
|
26
|
+
#ref = inject(ChangeDetectorRef);
|
|
27
27
|
id = `I${uuid.v4()}`;
|
|
28
|
-
autoIdInput = input(undefined, { alias: 'autoId' });
|
|
29
|
-
autoId = computed(() => (this.autoIdInput() ? `forms-radio-${this.autoIdInput()}` : undefined));
|
|
30
28
|
#name = uuid.v4();
|
|
31
|
-
set name(val) {
|
|
32
|
-
if (val) {
|
|
33
|
-
this.#name = val;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
29
|
formControl = new SdFormControl();
|
|
37
|
-
// get isNumber() {
|
|
38
|
-
// if (this.#model || this.#model === 0) {
|
|
39
|
-
// return typeof (this.#model) === 'number';
|
|
40
|
-
// }
|
|
41
|
-
// if (this.items?.length) {
|
|
42
|
-
// if (this.valueField) {
|
|
43
|
-
// return typeof (this.items[0][this.valueField]) === 'number';
|
|
44
|
-
// } else {
|
|
45
|
-
// return typeof (this.items[0]) === 'number';
|
|
46
|
-
// }
|
|
47
|
-
// }
|
|
48
|
-
// return false;
|
|
49
|
-
// }
|
|
50
|
-
#form;
|
|
51
|
-
set form(val) {
|
|
52
|
-
if (val) {
|
|
53
|
-
if (val instanceof NgForm) {
|
|
54
|
-
this.#form = val.form;
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
this.#form = val;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
label;
|
|
62
|
-
placeholder;
|
|
63
|
-
display = 'row';
|
|
64
|
-
set _display(display) {
|
|
65
|
-
this.display = display || 'row';
|
|
66
|
-
}
|
|
67
|
-
// Model
|
|
68
|
-
set model(value) {
|
|
69
|
-
if (value !== this.formControl.value) {
|
|
70
|
-
this.formControl.setValue(value, {
|
|
71
|
-
emitEvent: false,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
// Items
|
|
76
|
-
items = [];
|
|
77
|
-
set pItems(items) {
|
|
78
|
-
if (!Array.isArray(items)) {
|
|
79
|
-
this.items = [];
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
this.items = items;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
valueField;
|
|
86
|
-
displayField;
|
|
87
|
-
// Validator
|
|
88
|
-
required = false;
|
|
89
|
-
set _required(val) {
|
|
90
|
-
this.required = val === '' || !!val;
|
|
91
|
-
this.#updateValidator();
|
|
92
|
-
}
|
|
93
|
-
inlineError;
|
|
94
|
-
set _inlineError(val) {
|
|
95
|
-
this.inlineError = val;
|
|
96
|
-
this.#updateValidator();
|
|
97
|
-
}
|
|
98
|
-
// Optional
|
|
99
|
-
set disabled(val) {
|
|
100
|
-
val = val === '' || val;
|
|
101
|
-
if (val) {
|
|
102
|
-
this.formControl.disable();
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
this.formControl.enable();
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
viewed = false;
|
|
109
|
-
set _viewed(val) {
|
|
110
|
-
this.viewed = val === '' || !!val;
|
|
111
|
-
}
|
|
112
|
-
hyperlink;
|
|
113
|
-
sdSuffixDef;
|
|
114
|
-
sdLabelDef;
|
|
115
|
-
sdViewDef;
|
|
116
|
-
modelChange = new EventEmitter();
|
|
117
|
-
sdChange = new EventEmitter();
|
|
118
|
-
sdSelection = new EventEmitter();
|
|
119
30
|
#subscription = new Subscription();
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
31
|
+
// Inputs — accept null|undefined at boundary, transform to canonical
|
|
32
|
+
autoIdInput = input(undefined, {
|
|
33
|
+
alias: 'autoId',
|
|
34
|
+
transform: (v) => v ?? undefined,
|
|
35
|
+
});
|
|
36
|
+
name = input(undefined, {
|
|
37
|
+
transform: (v) => v ?? undefined,
|
|
38
|
+
});
|
|
39
|
+
// why: parent may bind NgForm (template-driven), FormGroup (reactive), or a wrapper with `.form`.
|
|
40
|
+
// Transform once at the input boundary so the rest of the component only deals with FormGroup.
|
|
41
|
+
form = input(undefined, {
|
|
42
|
+
transform: (val) => {
|
|
43
|
+
if (!val)
|
|
44
|
+
return undefined;
|
|
45
|
+
if (val instanceof NgForm)
|
|
46
|
+
return val.form;
|
|
47
|
+
if (val instanceof FormGroup)
|
|
48
|
+
return val;
|
|
49
|
+
if (val?.form instanceof FormGroup)
|
|
50
|
+
return val.form;
|
|
51
|
+
return undefined;
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
label = input(undefined, {
|
|
55
|
+
transform: (v) => v ?? undefined,
|
|
56
|
+
});
|
|
57
|
+
placeholder = input(undefined, {
|
|
58
|
+
transform: (v) => v ?? undefined,
|
|
59
|
+
});
|
|
60
|
+
display = input('row', {
|
|
61
|
+
transform: (v) => v || 'row',
|
|
62
|
+
});
|
|
63
|
+
items = input([], {
|
|
64
|
+
transform: (v) => (Array.isArray(v) ? v : []),
|
|
65
|
+
});
|
|
66
|
+
valueField = input.required();
|
|
67
|
+
displayField = input.required();
|
|
68
|
+
required = input(false, { transform: booleanAttribute });
|
|
69
|
+
inlineError = input(undefined, {
|
|
70
|
+
transform: (v) => v ?? undefined,
|
|
71
|
+
});
|
|
72
|
+
disabled = input(false, { transform: booleanAttribute });
|
|
73
|
+
/** Display mode: `false` edit · `true` static view · `'inline'` interactive (disabled `'inline'` → static). */
|
|
74
|
+
viewed = input(false, { transform: sdViewedTransform });
|
|
75
|
+
// why: tri-state viewed — `'inline'` keeps the radio group interactive; disabled `'inline'` → static.
|
|
76
|
+
#viewedState = sdViewedInline(this.viewed, undefined, this.disabled);
|
|
77
|
+
/** `true` when the static read-only view should render. */
|
|
78
|
+
isViewed = this.#viewedState.isViewed;
|
|
79
|
+
// why: legacy callers pass `null` → fallback to 'primary'. Color enum mở rộng hơn ThemePalette,
|
|
80
|
+
// áp dụng qua host attr [data-sd-color] + SCSS override MDC token vars (mat [color] không nhận 'success'/'info'/...).
|
|
81
|
+
color = input('primary', {
|
|
82
|
+
transform: (v) => v || 'primary',
|
|
83
|
+
});
|
|
84
|
+
hyperlink = input(undefined, {
|
|
85
|
+
transform: (v) => v ?? undefined,
|
|
86
|
+
});
|
|
87
|
+
// Two-way model
|
|
88
|
+
model = model(undefined);
|
|
89
|
+
// Content children
|
|
90
|
+
sdSuffixDef = contentChild(SdSuffixDefDirective);
|
|
91
|
+
sdLabelDef = contentChild(SdLabelDefDirective);
|
|
92
|
+
sdViewDef = contentChild(SdViewDefDirective);
|
|
93
|
+
// Outputs (modelChange auto-generated by model() signal)
|
|
94
|
+
sdChange = output();
|
|
95
|
+
sdSelection = output();
|
|
96
|
+
// Computed (template bindings)
|
|
97
|
+
autoId = computed(() => (this.autoIdInput() ? `forms-radio-${this.autoIdInput()}` : undefined));
|
|
98
|
+
// Kept for back-compat with templates that read `normalizedItems()` — alias of items()
|
|
99
|
+
normalizedItems = computed(() => this.items());
|
|
100
|
+
#state = sdFormControlState(computed(() => this.formControl));
|
|
101
|
+
dataDisabled = computed(() => (this.#state().disabled ? 'true' : 'false'));
|
|
102
|
+
dataEmpty = computed(() => (sdIsEmpty(this.#state().value) ? 'true' : 'false'));
|
|
103
|
+
dataValue = computed(() => sdSerializeDataValue(this.#state().value));
|
|
104
|
+
dataRequired = computed(() => (this.required() ? 'true' : 'false'));
|
|
105
|
+
viewedText = computed(() => {
|
|
106
|
+
const items = this.items();
|
|
107
|
+
const vField = this.valueField();
|
|
108
|
+
const dField = this.displayField();
|
|
109
|
+
// why: tìm item match value rồi trả về string ở `displayField`, không trả nguyên object (sẽ in [object Object]).
|
|
110
|
+
const match = items.find(e => this.formControl?.value?.toString() === e?.[vField]?.toString());
|
|
111
|
+
return match?.[dField] ?? '';
|
|
112
|
+
});
|
|
113
|
+
constructor() {
|
|
114
|
+
effect(() => {
|
|
115
|
+
const val = this.name();
|
|
116
|
+
if (val)
|
|
117
|
+
this.#name = val;
|
|
118
|
+
});
|
|
119
|
+
effect(() => {
|
|
120
|
+
const value = this.model();
|
|
121
|
+
if (value !== this.formControl.value) {
|
|
122
|
+
this.formControl.setValue(value, { emitEvent: false });
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
effect(() => {
|
|
126
|
+
if (this.disabled())
|
|
127
|
+
this.formControl.disable();
|
|
128
|
+
else
|
|
129
|
+
this.formControl.enable();
|
|
130
|
+
});
|
|
131
|
+
effect(() => {
|
|
132
|
+
this.required();
|
|
133
|
+
this.inlineError();
|
|
134
|
+
this.#updateValidator();
|
|
135
|
+
});
|
|
125
136
|
}
|
|
126
137
|
ngOnInit() {
|
|
127
138
|
this.#subscription.add(this.formControl.sdChanges.subscribe(() => {
|
|
128
|
-
|
|
129
|
-
this.ref.markForCheck();
|
|
139
|
+
this.#ref.markForCheck();
|
|
130
140
|
}));
|
|
131
141
|
}
|
|
132
142
|
ngAfterViewInit() {
|
|
133
143
|
this.#subscription.add(this.formControl.valueChanges.subscribe(value => {
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
// }
|
|
138
|
-
this.modelChange.emit(val);
|
|
139
|
-
this.sdChange.emit(val);
|
|
144
|
+
const vField = this.valueField();
|
|
145
|
+
this.model.set(value);
|
|
146
|
+
this.sdChange.emit(value);
|
|
140
147
|
this.sdSelection.emit({
|
|
141
|
-
value
|
|
142
|
-
item: this.items
|
|
148
|
+
value,
|
|
149
|
+
item: this.items().find(e => value?.toString() === e?.[vField]?.toString()),
|
|
143
150
|
});
|
|
144
151
|
}));
|
|
145
|
-
this
|
|
152
|
+
this.form()?.addControl(this.#name, this.formControl);
|
|
146
153
|
}
|
|
147
154
|
ngOnDestroy() {
|
|
148
155
|
this.#subscription.unsubscribe();
|
|
149
|
-
this
|
|
156
|
+
this.form()?.removeControl(this.#name);
|
|
150
157
|
}
|
|
151
158
|
#updateValidator = () => {
|
|
152
159
|
this.formControl.clearValidators();
|
|
153
160
|
const validators = [];
|
|
154
|
-
if (this.required) {
|
|
161
|
+
if (this.required()) {
|
|
155
162
|
validators.push(Validators.required);
|
|
156
163
|
}
|
|
157
|
-
if (this.inlineError) {
|
|
158
|
-
validators.push(
|
|
164
|
+
if (this.inlineError()) {
|
|
165
|
+
validators.push(SdInlineErrorValidator);
|
|
159
166
|
}
|
|
160
167
|
this.formControl.setValidators(validators);
|
|
161
168
|
this.formControl.updateValueAndValidity();
|
|
162
169
|
};
|
|
163
|
-
// Hàm tạo Validators tùy chỉnh cho inlineError
|
|
164
|
-
customInlineErrorValidator() {
|
|
165
|
-
return () => {
|
|
166
|
-
return { inlineError: true };
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
170
|
reValidate = () => {
|
|
170
171
|
this.formControl.updateValueAndValidity({ emitEvent: true });
|
|
171
172
|
};
|
|
172
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdRadio, deps: [
|
|
173
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdRadio, isStandalone: true, selector: "sd-radio", inputs: { autoIdInput: { classPropertyName: "autoIdInput", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal:
|
|
173
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdRadio, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
174
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdRadio, isStandalone: true, selector: "sd-radio", inputs: { autoIdInput: { classPropertyName: "autoIdInput", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: true, transformFunction: null }, displayField: { classPropertyName: "displayField", publicName: "displayField", isSignal: true, isRequired: true, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, inlineError: { classPropertyName: "inlineError", publicName: "inlineError", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, viewed: { classPropertyName: "viewed", publicName: "viewed", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, hyperlink: { classPropertyName: "hyperlink", publicName: "hyperlink", isSignal: true, isRequired: false, transformFunction: null }, model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { model: "modelChange", sdChange: "sdChange", sdSelection: "sdSelection" }, host: { properties: { "class.sd-c-primary": "color() === 'primary'", "class.sd-c-secondary": "color() === 'secondary'", "class.sd-c-info": "color() === 'info'", "class.sd-c-success": "color() === 'success'", "class.sd-c-warning": "color() === 'warning'", "class.sd-c-error": "color() === 'error'" } }, queries: [{ propertyName: "sdSuffixDef", first: true, predicate: SdSuffixDefDirective, descendants: true, isSignal: true }, { propertyName: "sdLabelDef", first: true, predicate: SdLabelDefDirective, descendants: true, isSignal: true }, { propertyName: "sdViewDef", first: true, predicate: SdViewDefDirective, descendants: true, isSignal: true }], ngImport: i0, template: "@let _sdLabelDef = sdLabelDef();\r\n@let _label = label();\r\n@let _display = display();\r\n@let _valueField = valueField();\r\n@let _hyperlink = hyperlink();\r\n\r\n@if (isViewed()) {\r\n @if (_sdLabelDef?.templateRef) {\r\n <ng-container *ngTemplateOutlet=\"_sdLabelDef!.templateRef\"> </ng-container>\r\n } @else if (_label) {\r\n <div class=\"T14R text-black400\">{{ _label }}</div>\r\n }\r\n @if (_hyperlink) {\r\n <!-- N\u1EBFu c\u00F3 hyperlink th\u00EC d\u00F9ng th\u1EBB a -->\r\n <a [sdHref]=\"_hyperlink!\">{{ viewedText() }}</a>\r\n } @else {\r\n <!-- Ngo\u00E0i ra d\u00F9ng th\u1EBB m\u1EB7c \u0111\u1ECBnh -->\r\n <div class=\"T14M\">{{ viewedText() | sdEmpty }}</div>\r\n }\r\n} @else {\r\n <section [ngClass]=\"{ 'c-section': _display === 'row' }\">\r\n @if (_sdLabelDef?.templateRef) {\r\n <ng-container *ngTemplateOutlet=\"_sdLabelDef!.templateRef\"> </ng-container>\r\n } @else if (_label) {\r\n <sd-label [label]=\"_label!\" [required]=\"required()\"></sd-label>\r\n }\r\n <mat-radio-group\r\n [class.c-radio-group-column]=\"_display === 'column'\"\r\n [class.c-radio-group-row]=\"_display === 'row'\"\r\n [formControl]=\"formControl\"\r\n [attr.data-autoId]=\"autoId()\"\r\n [attr.data-disabled]=\"dataDisabled()\"\r\n [attr.data-empty]=\"dataEmpty()\"\r\n [attr.data-value]=\"dataValue()\"\r\n [attr.data-required]=\"dataRequired()\">\r\n @for (item of normalizedItems(); track item[valueField()]) {\r\n <mat-radio-button [class.m-0]=\"_display === 'column'\" [class.mr-16]=\"_display === 'row'\" [value]=\"item[_valueField]\">\r\n {{ item[displayField()] }}\r\n </mat-radio-button>\r\n }\r\n </mat-radio-group>\r\n\r\n @if (formControl.errors?.['required'] && formControl.touched) {\r\n <mat-error>\r\n {{ 'core.form.radio.required' | translate }}\r\n </mat-error>\r\n } @else if (formControl.errors?.['inlineError'] && formControl.touched) {\r\n <mat-error>\r\n {{ inlineError() }}\r\n </mat-error>\r\n }\r\n </section>\r\n}\r\n", styles: [":host{height:100%;display:flex;flex-direction:column}:host ::ng-deep label.mdc-label{margin-bottom:0}:host{--sd-c: var(--sd-primary)}:host(.sd-c-secondary){--sd-c: var(--sd-secondary)}:host(.sd-c-info){--sd-c: var(--sd-info)}:host(.sd-c-success){--sd-c: var(--sd-success)}:host(.sd-c-warning){--sd-c: var(--sd-warning)}:host(.sd-c-error){--sd-c: var(--sd-error)}:host ::ng-deep .mat-mdc-radio-button,:host ::ng-deep .mat-mdc-radio-group,:host ::ng-deep .mdc-radio{--mdc-radio-selected-icon-color: var(--sd-c) !important;--mdc-radio-selected-focus-icon-color: var(--sd-c) !important;--mdc-radio-selected-hover-icon-color: var(--sd-c) !important;--mdc-radio-selected-pressed-icon-color: var(--sd-c) !important;--mdc-radio-selected-focus-state-layer-color: var(--sd-c) !important;--mdc-radio-selected-hover-state-layer-color: var(--sd-c) !important;--mat-radio-selected-icon-color: var(--sd-c) !important;--mat-radio-selected-focus-icon-color: var(--sd-c) !important;--mat-radio-selected-hover-icon-color: var(--sd-c) !important;--mat-radio-selected-pressed-icon-color: var(--sd-c) !important;--mat-radio-checked-ripple-color: var(--sd-c) !important;--mat-radio-checked-state-layer-color: var(--sd-c) !important}.c-section{align-content:center;align-items:center}.c-radio-group-column{flex:1;display:flex;flex-direction:column;align-items:flex-start}.c-radio-group-row{flex:1;display:flex;flex-direction:row;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatRadioModule }, { kind: "directive", type: i4.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i4.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "component", type: SdLabel, selector: "sd-label", inputs: ["label", "description", "required", "helperText"] }, { kind: "pipe", type: SdEmptyPipe, name: "sdEmpty" }, { kind: "directive", type: SdHrefDirective, selector: "a[sdHref]", inputs: ["sdHref"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
174
175
|
}
|
|
175
176
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdRadio, decorators: [{
|
|
176
177
|
type: Component,
|
|
177
|
-
args: [{ selector: 'sd-radio', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true,
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
args: ['display']
|
|
189
|
-
}], model: [{
|
|
190
|
-
type: Input
|
|
191
|
-
}], pItems: [{
|
|
192
|
-
type: Input,
|
|
193
|
-
args: ['items']
|
|
194
|
-
}], valueField: [{
|
|
195
|
-
type: Input,
|
|
196
|
-
args: [{ required: true }]
|
|
197
|
-
}], displayField: [{
|
|
198
|
-
type: Input,
|
|
199
|
-
args: [{ required: true }]
|
|
200
|
-
}], _required: [{
|
|
201
|
-
type: Input,
|
|
202
|
-
args: ['required']
|
|
203
|
-
}], _inlineError: [{
|
|
204
|
-
type: Input,
|
|
205
|
-
args: ['inlineError']
|
|
206
|
-
}], disabled: [{
|
|
207
|
-
type: Input
|
|
208
|
-
}], _viewed: [{
|
|
209
|
-
type: Input,
|
|
210
|
-
args: ['viewed']
|
|
211
|
-
}], hyperlink: [{
|
|
212
|
-
type: Input
|
|
213
|
-
}], sdSuffixDef: [{
|
|
214
|
-
type: ContentChild,
|
|
215
|
-
args: [SdSuffixDefDirective]
|
|
216
|
-
}], sdLabelDef: [{
|
|
217
|
-
type: ContentChild,
|
|
218
|
-
args: [SdLabelDefDirective]
|
|
219
|
-
}], sdViewDef: [{
|
|
220
|
-
type: ContentChild,
|
|
221
|
-
args: [SdViewDefDirective]
|
|
222
|
-
}], modelChange: [{
|
|
223
|
-
type: Output
|
|
224
|
-
}], sdChange: [{
|
|
225
|
-
type: Output
|
|
226
|
-
}], sdSelection: [{
|
|
227
|
-
type: Output
|
|
228
|
-
}] } });
|
|
178
|
+
args: [{ selector: 'sd-radio', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: {
|
|
179
|
+
// why: host class .sd-c-<x> + default sd-c-primary cho fallback. Thay data-sd-color
|
|
180
|
+
// để tránh edge case host-attr-binding không reactive trong vài cảnh build pipeline.
|
|
181
|
+
'[class.sd-c-primary]': "color() === 'primary'",
|
|
182
|
+
'[class.sd-c-secondary]': "color() === 'secondary'",
|
|
183
|
+
'[class.sd-c-info]': "color() === 'info'",
|
|
184
|
+
'[class.sd-c-success]': "color() === 'success'",
|
|
185
|
+
'[class.sd-c-warning]': "color() === 'warning'",
|
|
186
|
+
'[class.sd-c-error]': "color() === 'error'",
|
|
187
|
+
}, imports: [CommonModule, ReactiveFormsModule, MatTooltipModule, MatFormFieldModule, MatIconModule, MatRadioModule, SdLabel, SdEmptyPipe, SdHrefDirective, TranslatePipe], template: "@let _sdLabelDef = sdLabelDef();\r\n@let _label = label();\r\n@let _display = display();\r\n@let _valueField = valueField();\r\n@let _hyperlink = hyperlink();\r\n\r\n@if (isViewed()) {\r\n @if (_sdLabelDef?.templateRef) {\r\n <ng-container *ngTemplateOutlet=\"_sdLabelDef!.templateRef\"> </ng-container>\r\n } @else if (_label) {\r\n <div class=\"T14R text-black400\">{{ _label }}</div>\r\n }\r\n @if (_hyperlink) {\r\n <!-- N\u1EBFu c\u00F3 hyperlink th\u00EC d\u00F9ng th\u1EBB a -->\r\n <a [sdHref]=\"_hyperlink!\">{{ viewedText() }}</a>\r\n } @else {\r\n <!-- Ngo\u00E0i ra d\u00F9ng th\u1EBB m\u1EB7c \u0111\u1ECBnh -->\r\n <div class=\"T14M\">{{ viewedText() | sdEmpty }}</div>\r\n }\r\n} @else {\r\n <section [ngClass]=\"{ 'c-section': _display === 'row' }\">\r\n @if (_sdLabelDef?.templateRef) {\r\n <ng-container *ngTemplateOutlet=\"_sdLabelDef!.templateRef\"> </ng-container>\r\n } @else if (_label) {\r\n <sd-label [label]=\"_label!\" [required]=\"required()\"></sd-label>\r\n }\r\n <mat-radio-group\r\n [class.c-radio-group-column]=\"_display === 'column'\"\r\n [class.c-radio-group-row]=\"_display === 'row'\"\r\n [formControl]=\"formControl\"\r\n [attr.data-autoId]=\"autoId()\"\r\n [attr.data-disabled]=\"dataDisabled()\"\r\n [attr.data-empty]=\"dataEmpty()\"\r\n [attr.data-value]=\"dataValue()\"\r\n [attr.data-required]=\"dataRequired()\">\r\n @for (item of normalizedItems(); track item[valueField()]) {\r\n <mat-radio-button [class.m-0]=\"_display === 'column'\" [class.mr-16]=\"_display === 'row'\" [value]=\"item[_valueField]\">\r\n {{ item[displayField()] }}\r\n </mat-radio-button>\r\n }\r\n </mat-radio-group>\r\n\r\n @if (formControl.errors?.['required'] && formControl.touched) {\r\n <mat-error>\r\n {{ 'core.form.radio.required' | translate }}\r\n </mat-error>\r\n } @else if (formControl.errors?.['inlineError'] && formControl.touched) {\r\n <mat-error>\r\n {{ inlineError() }}\r\n </mat-error>\r\n }\r\n </section>\r\n}\r\n", styles: [":host{height:100%;display:flex;flex-direction:column}:host ::ng-deep label.mdc-label{margin-bottom:0}:host{--sd-c: var(--sd-primary)}:host(.sd-c-secondary){--sd-c: var(--sd-secondary)}:host(.sd-c-info){--sd-c: var(--sd-info)}:host(.sd-c-success){--sd-c: var(--sd-success)}:host(.sd-c-warning){--sd-c: var(--sd-warning)}:host(.sd-c-error){--sd-c: var(--sd-error)}:host ::ng-deep .mat-mdc-radio-button,:host ::ng-deep .mat-mdc-radio-group,:host ::ng-deep .mdc-radio{--mdc-radio-selected-icon-color: var(--sd-c) !important;--mdc-radio-selected-focus-icon-color: var(--sd-c) !important;--mdc-radio-selected-hover-icon-color: var(--sd-c) !important;--mdc-radio-selected-pressed-icon-color: var(--sd-c) !important;--mdc-radio-selected-focus-state-layer-color: var(--sd-c) !important;--mdc-radio-selected-hover-state-layer-color: var(--sd-c) !important;--mat-radio-selected-icon-color: var(--sd-c) !important;--mat-radio-selected-focus-icon-color: var(--sd-c) !important;--mat-radio-selected-hover-icon-color: var(--sd-c) !important;--mat-radio-selected-pressed-icon-color: var(--sd-c) !important;--mat-radio-checked-ripple-color: var(--sd-c) !important;--mat-radio-checked-state-layer-color: var(--sd-c) !important}.c-section{align-content:center;align-items:center}.c-radio-group-column{flex:1;display:flex;flex-direction:column;align-items:flex-start}.c-radio-group-row{flex:1;display:flex;flex-direction:row;align-items:center}\n"] }]
|
|
188
|
+
}], ctorParameters: () => [] });
|
|
229
189
|
|
|
230
190
|
/**
|
|
231
191
|
* Generated bundle index. Do not edit.
|