@sdcorejs/angular 19.1.5 → 19.2.0
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 +12 -4
- package/assets/scss/core/menu.scss +18 -0
- package/assets/scss/core/utilities/_misc.scss +15 -0
- package/assets/scss/sd-core.scss +1 -0
- package/components/anchor/src/components/anchor/anchor.component.d.ts +3 -1
- package/components/badge/src/badge.component.d.ts +1 -0
- package/components/ckeditor-styles/src/ckeditor-styles.component.d.ts +1 -1
- package/components/form-generic/src/components/form-builder/components/expression-builder/expression-builder.component.d.ts +2 -1
- package/components/form-generic/src/components/form-builder/form-builder.component.d.ts +3 -1
- package/components/form-generic/src/components/form-render/components/item/components/checkbox/checkbox.component.d.ts +34 -0
- package/components/form-generic/src/components/form-render/components/item/components/index.d.ts +1 -0
- package/components/form-generic/src/components/form-render/components/item/components/table/table.component.d.ts +6 -1
- package/components/form-generic/src/components/sd-feel-expression/sd-feel-expression.component.d.ts +1 -1
- package/components/form-generic/src/configurations/form.configuration.d.ts +1 -1
- package/components/form-generic/src/models/form-generic-component.model.d.ts +8 -8
- package/components/form-generic/src/models/form-generic-definition-selection.model.d.ts +5 -5
- package/components/form-generic/src/models/form-generic-expression.model.d.ts +12 -12
- package/components/form-generic/src/models/index.d.ts +1 -0
- package/components/form-generic/src/services/form-generic.service.d.ts +2 -2
- package/components/import-excel/src/import-excel.component.d.ts +1 -0
- package/components/index.d.ts +6 -1
- package/components/mini-editor/src/mini-editor.model.d.ts +1 -1
- package/components/modal/src/modal.component.d.ts +3 -2
- package/components/modal-resizable/src/modal-resizable.component.d.ts +92 -0
- package/components/modal-resizable/src/modal-resizable.registry.d.ts +22 -0
- package/components/org-chart/src/org-chart.component.d.ts +6 -0
- package/components/preview/src/preview-image/preview-image.component.d.ts +1 -0
- package/components/preview/src/preview-pdf/pdf-worker-inline.generated.d.ts +7 -0
- package/components/query-bar/src/components/actions-bar/actions-bar.component.d.ts +6 -2
- package/components/query-bar/src/components/build-chip/build-chip.component.d.ts +4 -1
- package/components/query-bar/src/components/chip-popover/chip-popover.component.d.ts +8 -0
- package/components/query-bar/src/components/field-picker/field-picker.component.d.ts +2 -0
- package/components/query-bar/src/components/inline-chip/inline-chip.component.d.ts +2 -0
- package/components/query-bar/src/components/inline-value-chip/inline-value-chip.component.d.ts +3 -3
- package/components/query-bar/src/components/saved-filters-menu/saved-filters-menu.component.d.ts +9 -4
- package/components/query-bar/src/query-bar.component.d.ts +32 -5
- package/components/query-bar/src/query-bar.model.d.ts +15 -12
- package/components/query-builder/src/query-builder.component.d.ts +76 -39
- package/components/query-builder/src/query-builder.model.d.ts +59 -52
- package/components/query-builder/src/query-builder.serializer.d.ts +15 -6
- package/components/section/src/section.component.d.ts +3 -0
- package/components/side-drawer/src/body-scroll-lock.service.d.ts +10 -0
- package/components/splitter/src/splitter-handle/splitter-handle.component.d.ts +1 -0
- package/components/tab-router/index.d.ts +2 -1
- package/components/tab-router/src/actions/tab-router.action.d.ts +2 -2
- package/components/tab-router/src/components/tab-router-item/tab-router-item.component.d.ts +2 -2
- package/components/tab-router/src/components/tab-router-nav/tab-router-nav.component.d.ts +3 -3
- package/components/tab-router/src/components/tab-router-outlet/tab-router-outlet.component.d.ts +3 -3
- package/components/tab-router/src/decorators/tab.decorator.d.ts +13 -1
- package/components/tab-router/src/events/tab-router.event.d.ts +3 -3
- package/components/tab-router/src/models/tab-router.model.d.ts +2 -2
- package/components/tab-router/src/pipes/tab-info.pipe.d.ts +2 -2
- package/components/tab-router/src/services/tab-router.service.d.ts +9 -9
- package/components/table/index.d.ts +1 -0
- package/components/table/src/components/config/config.component.d.ts +6 -1
- package/components/table/src/components/desktop-cell/view/view.component.d.ts +1 -0
- package/components/table/src/components/filter/external-filter/external-filter.component.d.ts +1 -1
- package/components/table/src/components/filter/mobile-filter/mobile-filter.component.d.ts +1 -1
- package/components/table/src/components/selector-action/action-filter.pipe.d.ts +8 -1
- package/components/table/src/components/selector-action/selector-action.component.d.ts +2 -0
- package/components/table/src/directives/index.d.ts +1 -0
- package/components/table/src/directives/sd-table-command-header-def.directive.d.ts +24 -0
- package/components/table/src/models/table-column.model.d.ts +30 -13
- package/components/table/src/models/table-item.model.d.ts +30 -1
- package/components/table/src/models/table-option-selector.model.d.ts +5 -4
- package/components/table/src/models/table-option.model.d.ts +12 -0
- package/components/table/src/pipes/sd-group.pipe.d.ts +6 -2
- package/components/table/src/services/table-export/table-export.service.d.ts +3 -1
- package/components/table/src/services/table-filter/table-filter.model.d.ts +15 -15
- package/components/table/src/services/table-filter/table-filter.service.d.ts +2 -2
- package/components/table/src/services/table-format/table-format.service.d.ts +1 -1
- package/components/table/src/services/table-selection/selection-action.util.d.ts +24 -0
- package/components/table/src/services/table-selection/table-selection.util.d.ts +31 -0
- package/components/table/src/services/tree/tree.util.d.ts +3 -2
- package/components/table/src/table.component.d.ts +52 -6
- package/components/tree/src/tree-item-def.directive.d.ts +1 -1
- package/components/tree/src/tree.component.d.ts +16 -4
- package/components/tree/src/tree.model.d.ts +31 -25
- package/components/upload-file/src/configurations/upload-file.configuration.d.ts +2 -2
- package/components/upload-file/src/upload-file.component.d.ts +4 -1
- package/configurations/src/sd-core.configuration.d.ts +1 -2
- package/fesm2022/sdcorejs-angular-components-anchor.mjs +36 -12
- package/fesm2022/sdcorejs-angular-components-anchor.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs +2 -2
- package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-badge.mjs +15 -2
- package/fesm2022/sdcorejs-angular-components-badge.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-button.mjs +2 -2
- package/fesm2022/sdcorejs-angular-components-button.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-ckeditor-styles.mjs +1 -1
- package/fesm2022/sdcorejs-angular-components-ckeditor-styles.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-code-editor.mjs +3 -3
- package/fesm2022/sdcorejs-angular-components-code-editor.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-data-state.mjs +3 -3
- package/fesm2022/sdcorejs-angular-components-data-state.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-editor.mjs +2 -2
- package/fesm2022/sdcorejs-angular-components-editor.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-form-generic.mjs +324 -192
- package/fesm2022/sdcorejs-angular-components-form-generic.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-history.mjs +4 -4
- package/fesm2022/sdcorejs-angular-components-history.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-import-excel.mjs +13 -5
- package/fesm2022/sdcorejs-angular-components-import-excel.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-inform.mjs +3 -3
- package/fesm2022/sdcorejs-angular-components-inform.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-modal-resizable.mjs +164 -8
- package/fesm2022/sdcorejs-angular-components-modal-resizable.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-modal.mjs +30 -18
- package/fesm2022/sdcorejs-angular-components-modal.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-org-chart.mjs +60 -13
- package/fesm2022/sdcorejs-angular-components-org-chart.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-preview.mjs +58 -19
- package/fesm2022/sdcorejs-angular-components-preview.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-query-bar.mjs +192 -30
- package/fesm2022/sdcorejs-angular-components-query-bar.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-query-builder.mjs +187 -127
- package/fesm2022/sdcorejs-angular-components-query-builder.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-section.mjs +16 -2
- package/fesm2022/sdcorejs-angular-components-section.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-side-drawer.mjs +83 -24
- package/fesm2022/sdcorejs-angular-components-side-drawer.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-splitter.mjs +57 -21
- package/fesm2022/sdcorejs-angular-components-splitter.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-stepper.mjs +2 -2
- package/fesm2022/sdcorejs-angular-components-stepper.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-tab-router.mjs +68 -20
- package/fesm2022/sdcorejs-angular-components-tab-router.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-tab.mjs +3 -2
- package/fesm2022/sdcorejs-angular-components-tab.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-table.mjs +556 -254
- package/fesm2022/sdcorejs-angular-components-table.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-tree.mjs +80 -17
- package/fesm2022/sdcorejs-angular-components-tree.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-upload-file.mjs +48 -13
- package/fesm2022/sdcorejs-angular-components-upload-file.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components.mjs +6 -1
- package/fesm2022/sdcorejs-angular-components.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-configurations.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-directives.mjs +45 -8
- package/fesm2022/sdcorejs-angular-directives.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs +40 -29
- package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-checkbox.mjs +5 -5
- package/fesm2022/sdcorejs-angular-forms-checkbox.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs +67 -50
- package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-chip.mjs +57 -43
- package/fesm2022/sdcorejs-angular-forms-chip.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-date-range.mjs +233 -63
- package/fesm2022/sdcorejs-angular-forms-date-range.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-date.mjs +208 -41
- package/fesm2022/sdcorejs-angular-forms-date.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-datetime.mjs +130 -26
- package/fesm2022/sdcorejs-angular-forms-datetime.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-entity-picker.mjs +39 -15
- package/fesm2022/sdcorejs-angular-forms-entity-picker.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-input-color.mjs +16 -5
- package/fesm2022/sdcorejs-angular-forms-input-color.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-input-number.mjs +24 -9
- package/fesm2022/sdcorejs-angular-forms-input-number.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-input.mjs +58 -10
- package/fesm2022/sdcorejs-angular-forms-input.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-models.mjs +279 -6
- package/fesm2022/sdcorejs-angular-forms-models.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-radio.mjs +4 -4
- package/fesm2022/sdcorejs-angular-forms-radio.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-select.mjs +135 -37
- package/fesm2022/sdcorejs-angular-forms-select.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-switch.mjs +18 -3
- package/fesm2022/sdcorejs-angular-forms-switch.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-textarea.mjs +51 -62
- package/fesm2022/sdcorejs-angular-forms-textarea.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-time-range.mjs +57 -12
- package/fesm2022/sdcorejs-angular-forms-time-range.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-time.mjs +16 -5
- package/fesm2022/sdcorejs-angular-forms-time.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-tree-select.mjs +100 -9
- package/fesm2022/sdcorejs-angular-forms-tree-select.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms.mjs +91 -46
- package/fesm2022/sdcorejs-angular-forms.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-handlers.mjs +18 -3
- package/fesm2022/sdcorejs-angular-handlers.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-i18n.mjs +510 -68
- package/fesm2022/sdcorejs-angular-i18n.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-interceptors.mjs +87 -29
- package/fesm2022/sdcorejs-angular-interceptors.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-modules-auth.mjs +25 -15
- package/fesm2022/sdcorejs-angular-modules-auth.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-modules-icon.mjs +2 -2
- package/fesm2022/sdcorejs-angular-modules-icon.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-modules-keycloak.mjs +32 -3
- package/fesm2022/sdcorejs-angular-modules-keycloak.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-modules-layout.mjs +441 -135
- package/fesm2022/sdcorejs-angular-modules-layout.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-modules-permission.mjs +177 -40
- package/fesm2022/sdcorejs-angular-modules-permission.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-pipes.mjs +62 -28
- package/fesm2022/sdcorejs-angular-pipes.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-api.mjs +123 -13
- package/fesm2022/sdcorejs-angular-services-api.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-cache.mjs +53 -3
- package/fesm2022/sdcorejs-angular-services-cache.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-confirm.mjs +25 -73
- package/fesm2022/sdcorejs-angular-services-confirm.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-excel.mjs +12 -10
- package/fesm2022/sdcorejs-angular-services-excel.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-loading.mjs +75 -84
- package/fesm2022/sdcorejs-angular-services-loading.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-notify.mjs +46 -5
- package/fesm2022/sdcorejs-angular-services-notify.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-storage.mjs +4 -0
- package/fesm2022/sdcorejs-angular-services-storage.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services.mjs +0 -1
- package/fesm2022/sdcorejs-angular-services.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-utilities-extensions.mjs +225 -80
- package/fesm2022/sdcorejs-angular-utilities-extensions.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-utilities-models.mjs +1 -63
- package/fesm2022/sdcorejs-angular-utilities-models.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular.mjs +17 -10
- package/fesm2022/sdcorejs-angular.mjs.map +1 -1
- package/forms/autocomplete/src/autocomplete.component.d.ts +5 -2
- package/forms/chip-calendar/src/chip-calendar.component.d.ts +10 -0
- package/forms/date/src/date-input.util.d.ts +18 -0
- package/forms/date/src/date.component.d.ts +21 -3
- package/forms/date-range/src/date-range.component.d.ts +13 -2
- package/forms/datetime/src/datetime.component.d.ts +13 -2
- package/forms/entity-picker/src/entity-picker.component.d.ts +9 -3
- package/forms/input/src/input.component.d.ts +3 -0
- package/forms/input-color/src/input-color.component.d.ts +4 -0
- package/forms/input-number/src/input-number.component.d.ts +3 -0
- package/forms/models/index.d.ts +4 -0
- package/forms/models/src/sd-form-control-connector.d.ts +12 -0
- package/forms/models/src/sd-model-facing-control.d.ts +43 -0
- package/forms/models/src/sd-search.model.d.ts +1 -1
- package/forms/models/src/sd-selection-data.model.d.ts +1 -1
- package/forms/models/src/sd-strict-date-adapter.d.ts +26 -0
- package/forms/models/src/sd-temporal-transform.d.ts +31 -0
- package/forms/models/src/sd-timer-scope.d.ts +29 -0
- package/forms/select/src/select.component.d.ts +27 -4
- package/forms/src/forms.module.d.ts +22 -13
- package/forms/switch/src/switch.component.d.ts +5 -0
- package/forms/textarea/src/textarea.component.d.ts +5 -3
- package/forms/time-range/src/time-range.component.d.ts +22 -1
- package/forms/tree-select/src/tree-select.component.d.ts +36 -5
- package/i18n/src/en.d.ts +94 -10
- package/i18n/src/i18n.messages.d.ts +1 -1
- package/i18n/src/i18n.pipe.d.ts +3 -3
- package/i18n/src/i18n.service.d.ts +2 -1
- package/i18n/src/i18n.types.d.ts +0 -3
- package/interceptors/no-internet/no-internet.interceptor.d.ts +11 -1
- package/modules/auth/services/auth.model.d.ts +1 -1
- package/modules/keycloak/keycloak.service.d.ts +1 -0
- package/modules/layout/components/shared/menu-tree/menu-tree.component.d.ts +2 -0
- package/modules/layout/components/sidebar-mobile-v1/components/sidebar/sidebar.component.d.ts +3 -3
- package/modules/layout/components/sidebar-mobile-v1/main.component.d.ts +3 -3
- package/modules/layout/components/sidebar-mobile-v2/main.component.d.ts +3 -3
- package/modules/layout/components/sidebar-mobile-v3/main.component.d.ts +3 -3
- package/modules/layout/components/sidebar-v1/components/sidebar/sidebar.component.d.ts +8 -3
- package/modules/layout/components/sidebar-v1/main.component.d.ts +3 -3
- package/modules/layout/components/sidebar-v2/main.component.d.ts +3 -3
- package/modules/layout/components/sidebar-v3/main.component.d.ts +3 -3
- package/modules/layout/index.d.ts +1 -0
- package/modules/layout/modules/forbidden/pages/root/root.component.d.ts +5 -0
- package/modules/layout/modules/not-found/pages/root/root.component.d.ts +5 -0
- package/modules/layout/services/layout.service.d.ts +21 -0
- package/modules/layout/services/storage/storage.service.d.ts +52 -7
- package/modules/layout/utils/index.d.ts +1 -0
- package/modules/layout/utils/tab-name.util.d.ts +8 -0
- package/modules/permission/src/configurations/permission.configuration.d.ts +11 -0
- package/modules/permission/src/directives/permission.directive.d.ts +2 -1
- package/modules/permission/src/services/permission.service.d.ts +52 -1
- package/package.json +48 -33
- package/pipes/src/safe-html.pipe.d.ts +26 -4
- package/pipes/src/time-different.pipe.d.ts +1 -0
- package/public-api.d.ts +11 -10
- package/services/api/src/api-host.d.ts +15 -0
- package/services/api/src/api.model.d.ts +14 -0
- package/services/api/src/api.module.d.ts +6 -0
- package/services/cache/src/cache.model.d.ts +10 -0
- package/services/index.d.ts +0 -1
- package/services/notify/index.d.ts +1 -1
- package/utilities/extensions/index.d.ts +1 -5
- package/utilities/extensions/src/url-safety.d.ts +72 -0
- package/utilities/extensions/src/utility.extension.d.ts +9 -5
- package/utilities/models/index.d.ts +0 -10
- package/components/base/index.d.ts +0 -1
- package/components/base/src/base-secure.component.d.ts +0 -8
- package/components/document-builder/index.d.ts +0 -4
- package/components/document-builder/src/components/header-footer-builder/header-footer-builder.component.d.ts +0 -15
- package/components/document-builder/src/components/header-footer-builder/plugins/page-number.plugin.d.ts +0 -4
- package/components/document-builder/src/components/index.d.ts +0 -1
- package/components/document-builder/src/document-builder.component.d.ts +0 -53
- package/components/document-builder/src/document-builder.config.d.ts +0 -21
- package/components/document-builder/src/document-builder.model.d.ts +0 -41
- package/components/document-builder/src/document-builder.utils.d.ts +0 -10
- package/components/document-builder/src/plugins/block-space/block-space.plugin.d.ts +0 -9
- package/components/document-builder/src/plugins/ck-comment/ck-comment.plugin.d.ts +0 -44
- package/components/document-builder/src/plugins/ck-comment/ck-comment.plugin.model.d.ts +0 -57
- package/components/document-builder/src/plugins/heading/heading.plugin.d.ts +0 -5
- package/components/document-builder/src/plugins/highlight-range/highlight-range.plugin.d.ts +0 -4
- package/components/document-builder/src/plugins/image-custom/image-custom.plugin.d.ts +0 -31
- package/components/document-builder/src/plugins/image-upload/image-upload.plugin.d.ts +0 -5
- package/components/document-builder/src/plugins/index.d.ts +0 -11
- package/components/document-builder/src/plugins/page-orientation/page-orientation.plugin.d.ts +0 -24
- package/components/document-builder/src/plugins/paste-handler/filters/bookmark.d.ts +0 -14
- package/components/document-builder/src/plugins/paste-handler/filters/br.d.ts +0 -15
- package/components/document-builder/src/plugins/paste-handler/filters/image.d.ts +0 -25
- package/components/document-builder/src/plugins/paste-handler/filters/list.d.ts +0 -29
- package/components/document-builder/src/plugins/paste-handler/filters/parse.d.ts +0 -35
- package/components/document-builder/src/plugins/paste-handler/filters/removeboldwrapper.d.ts +0 -15
- package/components/document-builder/src/plugins/paste-handler/filters/removegooglesheetstag.d.ts +0 -15
- package/components/document-builder/src/plugins/paste-handler/filters/removeinvalidtablewidth.d.ts +0 -15
- package/components/document-builder/src/plugins/paste-handler/filters/removemsattributes.d.ts +0 -15
- package/components/document-builder/src/plugins/paste-handler/filters/removestyleblock.d.ts +0 -15
- package/components/document-builder/src/plugins/paste-handler/filters/removexmlns.d.ts +0 -15
- package/components/document-builder/src/plugins/paste-handler/filters/replacemsfootnotes.d.ts +0 -54
- package/components/document-builder/src/plugins/paste-handler/filters/space.d.ts +0 -27
- package/components/document-builder/src/plugins/paste-handler/filters/table.d.ts +0 -16
- package/components/document-builder/src/plugins/paste-handler/filters/utils.d.ts +0 -25
- package/components/document-builder/src/plugins/paste-handler/index.d.ts +0 -35
- package/components/document-builder/src/plugins/paste-handler/normalizers/googledocsnormalizer.d.ts +0 -31
- package/components/document-builder/src/plugins/paste-handler/normalizers/googlesheetsnormalizer.d.ts +0 -31
- package/components/document-builder/src/plugins/paste-handler/normalizers/mswordnormalizer.d.ts +0 -29
- package/components/document-builder/src/plugins/paste-handler/types.d.ts +0 -30
- package/components/document-builder/src/plugins/table-custom/index.d.ts +0 -34
- package/components/document-builder/src/plugins/variable/variable.plugin.d.ts +0 -51
- package/components/table/src/pipes/selection-visible-select-all.pipe.d.ts +0 -9
- package/fesm2022/sdcorejs-angular-components-base.mjs +0 -23
- package/fesm2022/sdcorejs-angular-components-base.mjs.map +0 -1
- package/fesm2022/sdcorejs-angular-components-document-builder.mjs +0 -5038
- package/fesm2022/sdcorejs-angular-components-document-builder.mjs.map +0 -1
- package/fesm2022/sdcorejs-angular-models.mjs +0 -6
- package/fesm2022/sdcorejs-angular-models.mjs.map +0 -1
- package/fesm2022/sdcorejs-angular-services-docx.mjs +0 -291
- package/fesm2022/sdcorejs-angular-services-docx.mjs.map +0 -1
- package/fesm2022/sdcorejs-angular-services-license.mjs +0 -97
- package/fesm2022/sdcorejs-angular-services-license.mjs.map +0 -1
- package/models/index.d.ts +0 -1
- package/models/src/language.model.d.ts +0 -2
- package/services/docx/index.d.ts +0 -1
- package/services/docx/src/lib/docx.model.d.ts +0 -9
- package/services/docx/src/lib/docx.service.d.ts +0 -14
- package/services/docx/src/lib/pandoc-core.d.ts +0 -11
- package/services/docx/src/public-api.d.ts +0 -2
- package/services/license/index.d.ts +0 -1
- package/services/license/src/license.service.d.ts +0 -9
- package/utilities/extensions/src/array.extension.d.ts +0 -1
- package/utilities/extensions/src/color.extension.d.ts +0 -5
- package/utilities/extensions/src/date.extension.d.ts +0 -1
- package/utilities/extensions/src/number.extension.d.ts +0 -1
- package/utilities/extensions/src/string.extension.d.ts +0 -50
- package/utilities/models/src/color.model.d.ts +0 -4
- package/utilities/models/src/empty.model.d.ts +0 -4
- package/utilities/models/src/filter.model.d.ts +0 -12
- package/utilities/models/src/maybe-async.model.d.ts +0 -10
- package/utilities/models/src/nested-key-of.model.d.ts +0 -4
- package/utilities/models/src/operator.model.d.ts +0 -13
- package/utilities/models/src/order.model.d.ts +0 -4
- package/utilities/models/src/paging.model.d.ts +0 -8
- package/utilities/models/src/pattern.model.d.ts +0 -21
- package/utilities/models/src/size.model.d.ts +0 -4
|
@@ -961,11 +961,11 @@ class SdAutoidInspector {
|
|
|
961
961
|
}, 1800);
|
|
962
962
|
}
|
|
963
963
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdAutoidInspector, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
964
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdAutoidInspector, isStandalone: true, selector: "sd-autoid-inspector", inputs: { enabled: { classPropertyName: "enabled", publicName: "enabled", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: "@let _enabled = enabled();\n@let _open = open();\n@if (_enabled && !dismissed()) {\n <div class=\"sd-autoid-inspector__fab-wrap\">\n <button\n type=\"button\"\n class=\"sd-autoid-inspector__fab\"\n data-autoid=\"sd-autoid-inspector-fab\"\n [attr.data-opened]=\"dataOpened()\"\n [matTooltip]=\"_open ? '\u0110\u00F3ng AutoId Inspector' : 'M\u1EDF AutoId Inspector'\"\n matTooltipPosition=\"left\"\n (click)=\"togglePanel()\">\n <sd-icon [name]=\"_open ? 'close' : 'tag'\"></sd-icon>\n </button>\n <button\n type=\"button\"\n class=\"sd-autoid-inspector__fab-dismiss\"\n matTooltip=\"\u1EA8n t\u1EA1m \u2014 reload trang \u0111\u1EC3 hi\u1EC7n l\u1EA1i\"\n matTooltipPosition=\"left\"\n aria-label=\"\u1EA8n t\u1EA1m FAB\"\n (click)=\"dismissFab($event)\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n </div>\n}\n\n@if (_enabled && _open) {\n @let _segment = segment();\n <button type=\"button\" class=\"sd-autoid-inspector__backdrop\" aria-label=\"\u0110\u00F3ng AutoId Inspector\" (click)=\"closePanel()\"></button>\n <section\n class=\"sd-autoid-inspector__panel\"\n role=\"dialog\"\n aria-label=\"AutoId Inspector\"\n data-autoid=\"sd-autoid-inspector-panel\"\n [attr.data-segment]=\"dataSegment()\"\n [attr.data-highlight-on]=\"dataHighlightOn()\"\n [attr.data-element-count]=\"dataElementCount()\"\n [attr.data-missing-count]=\"dataMissingCount()\"\n [attr.data-duplicate-count]=\"dataDuplicateCount()\">\n <header class=\"sd-autoid-inspector__header\">\n <div class=\"sd-autoid-inspector__segments\">\n <button type=\"button\" [class.is-active]=\"_segment === 'audit'\" (click)=\"setSegment('audit')\">\n Audit\n @if (audit(); as a) {\n <span class=\"sd-autoid-inspector__badge\" [class.is-warn]=\"a.missingCount + a.duplicateCount > 0\">\n {{ a.missingCount + a.duplicateCount }}\n </span>\n }\n </button>\n <button type=\"button\" [class.is-active]=\"_segment === 'elements'\" (click)=\"setSegment('elements')\">\n Elements\n <span class=\"sd-autoid-inspector__badge\">{{ elements().length }}</span>\n </button>\n <button type=\"button\" [class.is-active]=\"_segment === 'export'\" (click)=\"setSegment('export')\">Export</button>\n </div>\n <div class=\"sd-autoid-inspector__actions\">\n <button type=\"button\" class=\"sd-autoid-inspector__icon-btn\" matTooltip=\"Qu\u00E9t l\u1EA1i\" (click)=\"refresh()\">\n <sd-icon name=\"refresh\"></sd-icon>\n </button>\n <button type=\"button\" class=\"sd-autoid-inspector__close-btn\" matTooltip=\"\u0110\u00F3ng\" aria-label=\"\u0110\u00F3ng panel\" (click)=\"closePanel()\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n </div>\n </header>\n\n @if (copyOk()) {\n <div class=\"sd-autoid-inspector__toast\">\u0110\u00E3 copy \u2713</div>\n }\n\n <div class=\"sd-autoid-inspector__body\">\n @switch (_segment) {\n @case ('audit') {\n <ng-container *ngTemplateOutlet=\"auditTpl\"></ng-container>\n }\n @case ('elements') {\n <ng-container *ngTemplateOutlet=\"elementsTpl\"></ng-container>\n }\n @case ('export') {\n <ng-container *ngTemplateOutlet=\"exportTpl\"></ng-container>\n }\n }\n </div>\n </section>\n\n <ng-template #auditTpl>\n @if (audit(); as a) {\n @let _highlightOn = highlightOn();\n <div class=\"sd-autoid-inspector__audit-toolbar\">\n <button type=\"button\" class=\"sd-autoid-inspector__toggle\" [class.is-on]=\"_highlightOn\" (click)=\"toggleHighlight()\">\n <sd-icon [name]=\"_highlightOn ? 'visibility' : 'visibility_off'\"></sd-icon>\n <span>Highlight DOM</span>\n <span class=\"sd-autoid-inspector__toggle-state\">{{ _highlightOn ? 'ON' : 'OFF' }}</span>\n </button>\n </div>\n <div class=\"sd-autoid-inspector__summary\">\n <div class=\"sd-autoid-inspector__stat is-info\">\n <div class=\"sd-autoid-inspector__stat-value\">{{ a.total }}</div>\n <div class=\"sd-autoid-inspector__stat-label\">T\u1ED5ng autoid</div>\n </div>\n <div class=\"sd-autoid-inspector__stat\" [class.is-error]=\"a.duplicateCount > 0\" [class.is-success]=\"a.duplicateCount === 0\">\n <div class=\"sd-autoid-inspector__stat-value\">{{ a.duplicateCount }}</div>\n <div class=\"sd-autoid-inspector__stat-label\">Tr\u00F9ng</div>\n </div>\n <div class=\"sd-autoid-inspector__stat\" [class.is-warning]=\"a.missingCount > 0\" [class.is-success]=\"a.missingCount === 0\">\n <div class=\"sd-autoid-inspector__stat-value\">{{ a.missingCount }}</div>\n <div class=\"sd-autoid-inspector__stat-label\">Thi\u1EBFu</div>\n </div>\n </div>\n\n @if (a.duplicateCount > 0) {\n <h4 class=\"sd-autoid-inspector__section-title\">\n <sd-icon class=\"is-error\" name=\"error\"></sd-icon>\n Autoid b\u1ECB tr\u00F9ng\n </h4>\n <div class=\"sd-autoid-inspector__table-wrap\">\n <table class=\"sd-autoid-inspector__table\">\n <thead>\n <tr>\n <th>Autoid</th>\n <th>S\u1ED1 l\u1EA7n</th>\n </tr>\n </thead>\n <tbody>\n @for (entry of a.duplicates | keyvalue; track entry.key) {\n <tr class=\"is-error\">\n <td>\n <code>{{ entry.key }}</code>\n </td>\n <td>{{ entry.value }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n @if (a.missingCount > 0) {\n <h4 class=\"sd-autoid-inspector__section-title\">\n <sd-icon class=\"is-warning\" name=\"warning_amber\"></sd-icon>\n Element thi\u1EBFu autoid\n </h4>\n <div class=\"sd-autoid-inspector__table-wrap\">\n <table class=\"sd-autoid-inspector__table\">\n <thead>\n <tr>\n <th>Tag</th>\n <th>Name hint</th>\n <th>Selector</th>\n </tr>\n </thead>\n <tbody>\n @for (m of a.missing; track $index) {\n <tr class=\"is-warning\">\n <td>\n <code>{{ m.tag }}</code>\n </td>\n <td>{{ m.nameHint }}</td>\n <td>\n <code>{{ m.selector }}</code>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n @if (a.duplicateCount === 0 && a.missingCount === 0) {\n <div class=\"sd-autoid-inspector__success-card\">\n <sd-icon name=\"check_circle\"></sd-icon>\n <div>\n <strong>Kh\u00F4ng c\u00F3 element thi\u1EBFu ho\u1EB7c tr\u00F9ng autoid.</strong>\n <small>Trang \u0111\u00E3 \u0111\u1EA1t chu\u1EA9n convention autoid.</small>\n </div>\n </div>\n }\n }\n </ng-template>\n\n <ng-template #elementsTpl>\n @let _filter = filter();\n <div class=\"sd-autoid-inspector__filter\">\n <sd-icon name=\"search\"></sd-icon>\n <input type=\"text\" placeholder=\"L\u1ECDc theo autoid / name / tag\" [ngModel]=\"_filter\" (ngModelChange)=\"filter.set($event)\" />\n @if (_filter) {\n <button type=\"button\" class=\"sd-autoid-inspector__icon-btn\" matTooltip=\"Xo\u00E1 filter\" (click)=\"filter.set('')\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n }\n </div>\n\n <!-- Top-level elements (not inside any sd-table) -->\n <h4 class=\"sd-autoid-inspector__section-title\">\n Top-level elements\n <span class=\"sd-autoid-inspector__badge\">{{ topLevelElements().length }}</span>\n </h4>\n <div class=\"sd-autoid-inspector__table-wrap\">\n <table class=\"sd-autoid-inspector__table\">\n <thead>\n <tr>\n <th class=\"is-num\">STT</th>\n <th>Name</th>\n <th>Autoid</th>\n <th>Tag</th>\n <th>State</th>\n <th>Value</th>\n </tr>\n </thead>\n <tbody>\n @for (el of topLevelElements(); track el.autoid + $index) {\n <tr [class.is-error]=\"el.duplicate\">\n <td class=\"is-num\">{{ el.stt }}</td>\n <td>{{ el.name || '\u2014' }}</td>\n <td>\n <div class=\"sd-autoid-inspector__autoid-cell\">\n <code>{{ el.autoid }}</code>\n <button\n type=\"button\"\n class=\"sd-autoid-inspector__icon-btn is-primary\"\n matTooltip=\"Copy xpath\"\n (click)=\"copyXpath(el.autoid)\">\n <sd-icon name=\"content_copy\"></sd-icon>\n </button>\n </div>\n </td>\n <td>\n <span class=\"sd-autoid-inspector__tag-chip\">{{ el.tag }}</span>\n </td>\n <td class=\"sd-autoid-inspector__state-cell\">\n @if (el.state.disabled !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-error]=\"el.state.disabled === 'true'\">\n disabled={{ el.state.disabled }}\n </span>\n }\n @if (el.state.loading !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-warning]=\"el.state.loading === 'true'\">\n loading={{ el.state.loading }}\n </span>\n }\n @if (el.state.empty !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-info]=\"el.state.empty === 'true'\">\n empty={{ el.state.empty }}\n </span>\n }\n @if (el.state.invalid !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-error]=\"el.state.invalid === 'true'\">\n invalid={{ el.state.invalid }}\n </span>\n }\n @if (el.state.opened !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-info]=\"el.state.opened === 'true'\">\n opened={{ el.state.opened }}\n </span>\n }\n @if (el.state.count !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> count={{ el.state.count }} </span>\n }\n @if (el.state.required !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-warning]=\"el.state.required === 'true'\">\n required={{ el.state.required }}\n </span>\n }\n @if (el.state.maxlength !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> maxlength={{ el.state.maxlength }} </span>\n }\n @if (el.state.minlength !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> minlength={{ el.state.minlength }} </span>\n }\n @if (el.state.pattern !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> pattern={{ el.state.pattern }} </span>\n }\n @if (el.state.errorMessage !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-error\"> error: {{ el.state.errorMessage }} </span>\n }\n </td>\n <td class=\"sd-autoid-inspector__value\" [matTooltip]=\"el.state.dataValue || el.text || ''\">\n {{ el.state.dataValue || el.text || '\u2014' }}\n </td>\n </tr>\n } @empty {\n <tr>\n <td colspan=\"6\" class=\"sd-autoid-inspector__empty\">Kh\u00F4ng c\u00F3 k\u1EBFt qu\u1EA3.</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <!-- One section per sd-table group -->\n @for (group of tableGroups(); track group.scope) {\n <h4 class=\"sd-autoid-inspector__section-title\">\n <sd-icon class=\"is-info\" name=\"table_chart\"></sd-icon>\n Inside <code>{{ group.scope }}</code>\n <span class=\"sd-autoid-inspector__badge\">{{ group.items.length }}</span>\n </h4>\n <div class=\"sd-autoid-inspector__table-wrap\">\n <table class=\"sd-autoid-inspector__table\">\n <thead>\n <tr>\n <th class=\"is-num\">STT</th>\n <th>Name</th>\n <th>Autoid</th>\n <th>Tag</th>\n <th>State</th>\n <th>Value</th>\n </tr>\n </thead>\n <tbody>\n @for (el of group.items; track el.autoid + $index) {\n <tr [class.is-error]=\"el.duplicate\">\n <td class=\"is-num\">{{ el.stt }}</td>\n <td>{{ el.name || '\u2014' }}</td>\n <td>\n <div class=\"sd-autoid-inspector__autoid-cell\">\n <code>{{ el.autoid }}</code>\n <button\n type=\"button\"\n class=\"sd-autoid-inspector__icon-btn is-primary\"\n matTooltip=\"Copy xpath\"\n (click)=\"copyXpath(el.autoid)\">\n <sd-icon name=\"content_copy\"></sd-icon>\n </button>\n </div>\n </td>\n <td>\n <span class=\"sd-autoid-inspector__tag-chip\">{{ el.tag }}</span>\n </td>\n <td class=\"sd-autoid-inspector__state-cell\">\n @if (el.state.disabled !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-error]=\"el.state.disabled === 'true'\">\n disabled={{ el.state.disabled }}\n </span>\n }\n @if (el.state.loading !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-warning]=\"el.state.loading === 'true'\">\n loading={{ el.state.loading }}\n </span>\n }\n @if (el.state.empty !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-info]=\"el.state.empty === 'true'\">\n empty={{ el.state.empty }}\n </span>\n }\n @if (el.state.invalid !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-error]=\"el.state.invalid === 'true'\">\n invalid={{ el.state.invalid }}\n </span>\n }\n @if (el.state.opened !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-info]=\"el.state.opened === 'true'\">\n opened={{ el.state.opened }}\n </span>\n }\n @if (el.state.count !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> count={{ el.state.count }} </span>\n }\n @if (el.state.required !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-warning]=\"el.state.required === 'true'\">\n required={{ el.state.required }}\n </span>\n }\n @if (el.state.maxlength !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> maxlength={{ el.state.maxlength }} </span>\n }\n @if (el.state.minlength !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> minlength={{ el.state.minlength }} </span>\n }\n @if (el.state.pattern !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> pattern={{ el.state.pattern }} </span>\n }\n @if (el.state.errorMessage !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-error\"> error: {{ el.state.errorMessage }} </span>\n }\n </td>\n <td class=\"sd-autoid-inspector__value\" [matTooltip]=\"el.state.dataValue || el.text || ''\">\n {{ el.state.dataValue || el.text || '\u2014' }}\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </ng-template>\n\n <ng-template #exportTpl>\n <div class=\"sd-autoid-inspector__export-grid\">\n <button type=\"button\" matTooltip=\"Copy JSON v\u00E0o clipboard\" (click)=\"copyJson()\">\n <sd-icon name=\"content_copy\"></sd-icon>\n <span>Copy JSON</span>\n <small>clipboard</small>\n </button>\n <button type=\"button\" matTooltip=\"T\u1EA3i file JSON\" (click)=\"exportJson()\">\n <sd-icon name=\"download\"></sd-icon>\n <span>JSON</span>\n <small>.json</small>\n </button>\n <button type=\"button\" matTooltip=\"T\u1EA3i file CSV\" (click)=\"exportCsv()\">\n <sd-icon name=\"table_view\"></sd-icon>\n <span>CSV</span>\n <small>.csv</small>\n </button>\n <button type=\"button\" matTooltip=\"T\u1EA3i MD POM skeleton \u2014 cho AI vi\u1EBFt auto-test\" (click)=\"exportMdPom()\">\n <sd-icon name=\"code\"></sd-icon>\n <span>MD POM</span>\n <small>AI test</small>\n </button>\n <button type=\"button\" matTooltip=\"T\u1EA3i MD reference table \u2014 group theo tag sd-*\" (click)=\"exportMdTable()\">\n <sd-icon name=\"view_list\"></sd-icon>\n <span>MD Table</span>\n <small>reference</small>\n </button>\n </div>\n\n @if (e2eGeneratorHost()) {\n @let _e2eExporting = e2eExporting();\n <div class=\"sd-autoid-inspector__export-section\">\n <h4 class=\"sd-autoid-inspector__section-title\">\n <sd-icon class=\"is-info\" name=\"auto_awesome\"></sd-icon>\n T\u1EA1o E2E test\n </h4>\n <div class=\"sd-autoid-inspector__export-grid is-e2e\">\n <button\n type=\"button\"\n matTooltip=\"T\u1EA1o b\u1ED9 test Playwright (.zip)\"\n [disabled]=\"_e2eExporting !== null\"\n (click)=\"exportE2eTest('playwright')\">\n <sd-icon [name]=\"_e2eExporting === 'playwright' ? 'hourglass_empty' : 'play_arrow'\"></sd-icon>\n <span>Playwright</span>\n <small>.zip</small>\n </button>\n <button\n type=\"button\"\n matTooltip=\"T\u1EA1o b\u1ED9 test Robot Framework (.zip)\"\n [disabled]=\"_e2eExporting !== null\"\n (click)=\"openRobotExportContext()\">\n <sd-icon [name]=\"_e2eExporting === 'robot' ? 'hourglass_empty' : 'smart_toy'\"></sd-icon>\n <span>Robot Framework</span>\n <small>.zip</small>\n </button>\n </div>\n\n @if (robotContextOpen()) {\n <div class=\"sd-autoid-inspector__context-backdrop\" role=\"presentation\" (click)=\"closeRobotExportContext()\"></div>\n <section\n class=\"sd-autoid-inspector__context-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"sd-autoid-robot-context-title\">\n <header class=\"sd-autoid-inspector__context-header\">\n <div>\n <h4 id=\"sd-autoid-robot-context-title\">Ng\u1EEF c\u1EA3nh QC cho Robot Framework</h4>\n <small>Requirement, test case, test data</small>\n </div>\n <button type=\"button\" class=\"sd-autoid-inspector__icon-btn\" matTooltip=\"\u0110\u00F3ng\" (click)=\"closeRobotExportContext()\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n </header>\n\n <div class=\"sd-autoid-inspector__context-form\">\n <label>\n <span>Component</span>\n <input\n type=\"text\"\n placeholder=\"SP-Wallet\"\n [ngModel]=\"robotExportContext().component || ''\"\n (ngModelChange)=\"updateRobotExportContext('component', $event)\" />\n </label>\n <label>\n <span>Story / Trace</span>\n <input\n type=\"text\"\n placeholder=\"US-001, AC-01\"\n [ngModel]=\"robotExportContext().storyLinkages || ''\"\n (ngModelChange)=\"updateRobotExportContext('storyLinkages', $event)\" />\n </label>\n <label class=\"is-full\">\n <span>Requirement / AC / BR</span>\n <textarea\n rows=\"4\"\n placeholder=\"D\u00E1n requirement ho\u1EB7c acceptance criteria...\"\n [ngModel]=\"robotExportContext().requirement || ''\"\n (ngModelChange)=\"updateRobotExportContext('requirement', $event)\"></textarea>\n </label>\n <label class=\"is-full\">\n <span>Test case QC \u0111\u00E3 \u0111\u1ECBnh ngh\u0129a</span>\n <textarea\n rows=\"4\"\n placeholder=\"TC-001: ...\"\n [ngModel]=\"robotExportContext().testCases || ''\"\n (ngModelChange)=\"updateRobotExportContext('testCases', $event)\"></textarea>\n </label>\n <label class=\"is-full\">\n <span>Test data</span>\n <textarea\n rows=\"3\"\n placeholder=\"wallet=V\u00ED A, amount=100000...\"\n [ngModel]=\"robotExportContext().testData || ''\"\n (ngModelChange)=\"updateRobotExportContext('testData', $event)\"></textarea>\n </label>\n <label class=\"is-full\">\n <span>Precondition</span>\n <textarea\n rows=\"2\"\n placeholder=\"User \u0111\u00E3 \u0111\u0103ng nh\u1EADp, d\u1EEF li\u1EC7u v\u00ED \u0111\u00E3 t\u1ED3n t\u1EA1i...\"\n [ngModel]=\"robotExportContext().precondition || ''\"\n (ngModelChange)=\"updateRobotExportContext('precondition', $event)\"></textarea>\n </label>\n <label class=\"is-full\">\n <span>Ghi ch\u00FA format QC</span>\n <textarea\n rows=\"3\"\n placeholder=\"Smoke=Y, Auto=Y, \u01B0u ti\u00EAn happy path...\"\n [ngModel]=\"robotExportContext().qcNotes || ''\"\n (ngModelChange)=\"updateRobotExportContext('qcNotes', $event)\"></textarea>\n </label>\n </div>\n\n <footer class=\"sd-autoid-inspector__context-actions\">\n <button type=\"button\" class=\"is-secondary\" [disabled]=\"_e2eExporting !== null\" (click)=\"closeRobotExportContext()\">\n Hu\u1EF7\n </button>\n <button\n type=\"button\"\n class=\"is-primary\"\n [disabled]=\"_e2eExporting !== null || !hasRobotExportContext()\"\n (click)=\"confirmRobotExport()\">\n <sd-icon [name]=\"_e2eExporting === 'robot' ? 'hourglass_empty' : 'download'\"></sd-icon>\n <span>\u0110\u1ED3ng \u00FD xu\u1EA5t</span>\n </button>\n </footer>\n </section>\n }\n\n @if (e2eExportOk(); as targetLabel) {\n <div class=\"sd-autoid-inspector__export-message is-success\">\u0110\u00E3 t\u1EA3i b\u1ED9 test {{ targetLabel }}.</div>\n }\n @if (e2eExportError(); as error) {\n <div class=\"sd-autoid-inspector__export-message is-error\">\n {{ error }}\n </div>\n }\n </div>\n }\n </ng-template>\n}\n", styles: [":host{position:fixed;inset:auto 0 0 auto;z-index:100000;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-size:13px;color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__fab-wrap{position:fixed;right:16px;bottom:16px;z-index:100000}.sd-autoid-inspector__fab-wrap:hover .sd-autoid-inspector__fab-dismiss{opacity:1;transform:scale(1);pointer-events:auto}.sd-autoid-inspector__fab{width:36px;height:36px;border-radius:50%;border:none;background:var(--sd-primary, #005cbb);color:#fff;cursor:pointer;box-shadow:0 3px 10px #00000038;display:inline-flex;align-items:center;justify-content:center;transition:transform .15s ease,background .15s ease,box-shadow .15s ease}.sd-autoid-inspector__fab:hover{background:var(--sd-primary-dark, #00458f);transform:scale(1.08);box-shadow:0 5px 14px #00000047}.sd-autoid-inspector__fab sd-icon{font-size:18px;width:18px;height:18px}.sd-autoid-inspector__fab-dismiss{position:absolute;top:-6px;right:-6px;width:18px;height:18px;border-radius:50%;border:1px solid var(--sd-border, #c4c6d0);background:#fff;color:var(--sd-text-secondary, #44474f);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;opacity:0;transform:scale(.7);pointer-events:none;transition:opacity .12s ease,transform .12s ease,color .12s ease,background .12s ease;box-shadow:0 1px 4px #00000026}.sd-autoid-inspector__fab-dismiss:hover{background:var(--sd-error-light, #ffdad6);color:var(--sd-error-dark, #93000a);border-color:var(--sd-error, #ba1a1a)}.sd-autoid-inspector__fab-dismiss sd-icon{font-size:12px;width:12px;height:12px;line-height:12px}.sd-autoid-inspector__backdrop{position:fixed;inset:0;padding:0;border:none;background:#00000052;z-index:100001;backdrop-filter:blur(2px)}.sd-autoid-inspector__panel{position:fixed;right:20px;bottom:80px;width:min(860px,100vw - 40px);max-height:calc(100vh - 110px);background:#fff;border-radius:12px;box-shadow:0 16px 48px #00000038;display:flex;flex-direction:column;z-index:100002;overflow:hidden;border:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__header{display:flex;align-items:center;gap:8px;padding:8px 10px;border-bottom:1px solid var(--sd-border, #c4c6d0);background:var(--sd-surface-muted, #e7e8ed);flex-shrink:0}.sd-autoid-inspector__segments{display:inline-flex;border:1px solid var(--sd-border, #c4c6d0);border-radius:8px;background:#fff;overflow:hidden}.sd-autoid-inspector__segments button{border:none;background:transparent;padding:5px 12px;cursor:pointer;font-size:12px;font-weight:500;color:var(--sd-text-secondary, #44474f);display:inline-flex;align-items:center;gap:6px;border-right:1px solid var(--sd-border, #c4c6d0);transition:background .12s ease,color .12s ease}.sd-autoid-inspector__segments button:last-child{border-right:none}.sd-autoid-inspector__segments button:hover:not(.is-active){background:var(--sd-surface-muted, #e7e8ed);color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__segments button.is-active{background:var(--sd-primary, #005cbb);color:#fff}.sd-autoid-inspector__badge{background:var(--sd-border, #c4c6d0);color:var(--sd-text, #1a1b1f);border-radius:10px;padding:0 7px;font-size:11px;font-weight:600;line-height:16px}.is-active .sd-autoid-inspector__badge{background:#ffffff40;color:#fff}.sd-autoid-inspector__badge.is-warn{background:var(--sd-error, #ba1a1a);color:#fff}.sd-autoid-inspector__actions{display:inline-flex;gap:4px;margin-left:auto}.sd-autoid-inspector__icon-btn{border:none;background:transparent;cursor:pointer;padding:4px;border-radius:6px;color:var(--sd-text-secondary, #44474f);display:inline-flex;align-items:center;justify-content:center;transition:background .12s ease,color .12s ease}.sd-autoid-inspector__icon-btn:hover{background:var(--sd-surface-muted, #e7e8ed);color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__icon-btn.is-primary{color:var(--sd-primary, #005cbb)}.sd-autoid-inspector__icon-btn.is-primary:hover{background:var(--sd-primary-light, #d7e3ff);color:var(--sd-primary-dark, #00458f)}.sd-autoid-inspector__icon-btn sd-icon{font-size:18px;width:18px;height:18px}.sd-autoid-inspector__close-btn{border:none;cursor:pointer;padding:4px;border-radius:50%;width:28px;height:28px;background:transparent;color:var(--sd-text-secondary, #44474f);display:inline-flex;align-items:center;justify-content:center;transition:background .12s ease,color .12s ease}.sd-autoid-inspector__close-btn:hover{background:var(--sd-error-light, #ffdad6);color:var(--sd-error-dark, #93000a)}.sd-autoid-inspector__close-btn sd-icon{font-size:18px;width:18px;height:18px}.sd-autoid-inspector__body{padding:14px;overflow:auto;flex:1;background:#fff}.sd-autoid-inspector__toast{position:absolute;top:56px;right:14px;background:var(--sd-success, #2e7d32);color:#fff;padding:6px 12px;border-radius:6px;font-size:12px;z-index:2;box-shadow:0 4px 12px #0000002e}.sd-autoid-inspector__audit-toolbar{display:flex;justify-content:flex-end;margin-bottom:12px}.sd-autoid-inspector__toggle{display:inline-flex;align-items:center;gap:8px;border:1px solid var(--sd-border, #c4c6d0);background:#fff;border-radius:999px;padding:5px 12px 5px 10px;cursor:pointer;font-size:12px;font-weight:500;color:var(--sd-text-secondary, #44474f);transition:all .15s ease}.sd-autoid-inspector__toggle:hover{border-color:var(--sd-primary, #005cbb);color:var(--sd-primary, #005cbb)}.sd-autoid-inspector__toggle.is-on{border-color:var(--sd-primary, #005cbb);color:var(--sd-primary, #005cbb);background:var(--sd-primary-light, #d7e3ff)}.sd-autoid-inspector__toggle sd-icon{font-size:16px;width:16px;height:16px}.sd-autoid-inspector__toggle-state{font-size:10px;font-weight:700;padding:1px 7px;border-radius:999px;background:var(--sd-border, #c4c6d0);color:var(--sd-text-secondary, #44474f)}.is-on .sd-autoid-inspector__toggle-state{background:var(--sd-primary, #005cbb);color:#fff}.sd-autoid-inspector__summary{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:16px}.sd-autoid-inspector__stat{background:var(--sd-surface-muted, #e7e8ed);border-radius:10px;padding:12px;text-align:center;border:1px solid transparent}.sd-autoid-inspector__stat.is-info{background:var(--sd-info-light, #d4f7f6);border-color:var(--sd-info, #006a6a)}.sd-autoid-inspector__stat.is-info .sd-autoid-inspector__stat-value{color:var(--sd-info, #006a6a)}.sd-autoid-inspector__stat.is-success{background:var(--sd-success-light, #d8f0d3);border-color:var(--sd-success, #2e7d32)}.sd-autoid-inspector__stat.is-success .sd-autoid-inspector__stat-value{color:var(--sd-success-dark, #1b5e20)}.sd-autoid-inspector__stat.is-warning{background:var(--sd-warning-light, #ffddb0);border-color:var(--sd-warning, #a66300)}.sd-autoid-inspector__stat.is-warning .sd-autoid-inspector__stat-value{color:var(--sd-warning-dark, #7a4d00)}.sd-autoid-inspector__stat.is-error{background:var(--sd-error-light, #ffdad6);border-color:var(--sd-error, #ba1a1a)}.sd-autoid-inspector__stat.is-error .sd-autoid-inspector__stat-value{color:var(--sd-error-dark, #93000a)}.sd-autoid-inspector__stat-value{font-size:22px;font-weight:700;line-height:1;margin-bottom:4px}.sd-autoid-inspector__stat-label{font-size:11px;color:var(--sd-text-secondary, #44474f);text-transform:uppercase;letter-spacing:.4px;font-weight:600}.sd-autoid-inspector__section-title{display:flex;align-items:center;gap:6px;margin:14px 0 8px;font-size:13px;font-weight:600;color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__section-title sd-icon{font-size:18px;width:18px;height:18px}.sd-autoid-inspector__section-title sd-icon.is-error{color:var(--sd-error, #ba1a1a)}.sd-autoid-inspector__section-title sd-icon.is-warning{color:var(--sd-warning, #a66300)}.sd-autoid-inspector__section-title sd-icon.is-info{color:var(--sd-info, #006a6a)}.sd-autoid-inspector__success-card{display:flex;align-items:center;gap:12px;padding:14px 16px;background:var(--sd-success-light, #d8f0d3);border:1px solid var(--sd-success, #2e7d32);border-radius:10px;color:var(--sd-success-dark, #1b5e20)}.sd-autoid-inspector__success-card sd-icon{font-size:28px;width:28px;height:28px;color:var(--sd-success, #2e7d32)}.sd-autoid-inspector__success-card strong{display:block;font-size:13px;margin-bottom:2px}.sd-autoid-inspector__success-card small{font-size:11px;opacity:.85}.sd-autoid-inspector__table-wrap{border:1px solid var(--sd-border, #c4c6d0);border-radius:8px;overflow:auto;max-height:60vh;background:#fff}.sd-autoid-inspector__table{width:100%;border-collapse:separate;border-spacing:0;font-size:12px}.sd-autoid-inspector__table th,.sd-autoid-inspector__table td{padding:8px 10px;text-align:left;vertical-align:middle;border-bottom:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__table thead th{position:sticky;top:0;z-index:1;background:var(--sd-surface-muted, #e7e8ed);font-weight:600;color:var(--sd-text, #1a1b1f);text-transform:none;font-size:11px;letter-spacing:.3px;border-bottom:none;box-shadow:inset 0 -1px 0 var(--sd-border, #c4c6d0),0 2px 4px #0000000a;white-space:nowrap}.sd-autoid-inspector__table thead th.is-num{text-align:right;width:50px}.sd-autoid-inspector__table tbody tr{transition:background .1s ease}.sd-autoid-inspector__table tbody tr:hover{background:var(--sd-primary-light, #d7e3ff)}.sd-autoid-inspector__table tbody tr:last-child td{border-bottom:none}.sd-autoid-inspector__table tbody tr.is-error{background:var(--sd-error-light, #ffdad6)}.sd-autoid-inspector__table tbody tr.is-error:hover{background:var(--sd-error-light, #ffdad6);filter:brightness(.98)}.sd-autoid-inspector__table tbody tr.is-warning{background:var(--sd-warning-light, #ffddb0)}.sd-autoid-inspector__table tbody tr.is-warning:hover{background:var(--sd-warning-light, #ffddb0);filter:brightness(.98)}.sd-autoid-inspector__table td.is-num{text-align:right;color:var(--sd-text-secondary, #44474f);font-variant-numeric:tabular-nums}.sd-autoid-inspector__table code{font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:11px;background:var(--sd-surface-muted, #e7e8ed);padding:2px 6px;border-radius:4px;color:var(--sd-primary-dark, #00458f);border:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__autoid-cell{display:inline-flex;align-items:center;gap:6px}.sd-autoid-inspector__tag-chip{display:inline-block;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:11px;background:var(--sd-info-light, #d4f7f6);color:var(--sd-info, #006a6a);border:1px solid var(--sd-info, #006a6a);padding:1px 8px;border-radius:999px;font-weight:500}.sd-autoid-inspector__value{max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--sd-text-secondary, #44474f);font-style:italic}.sd-autoid-inspector__state-cell{display:flex;flex-wrap:wrap;gap:4px;align-items:center;min-width:0}.sd-autoid-inspector__state-chip{display:inline-block;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:10px;background:var(--sd-surface-muted, #e7e8ed);color:var(--sd-text-secondary, #44474f);border:1px solid var(--sd-border, #c4c6d0);padding:1px 6px;border-radius:999px;font-weight:500;white-space:nowrap}.sd-autoid-inspector__state-chip.is-error{background:var(--sd-error-light, #ffdad6);color:var(--sd-error-dark, #93000a);border-color:var(--sd-error, #ba1a1a)}.sd-autoid-inspector__state-chip.is-warning{background:var(--sd-warning-light, #ffddb0);color:var(--sd-warning-dark, #7a4d00);border-color:var(--sd-warning, #a66300)}.sd-autoid-inspector__state-chip.is-info{background:var(--sd-info-light, #d4f7f6);color:var(--sd-info, #006a6a);border-color:var(--sd-info, #006a6a)}.sd-autoid-inspector__empty{text-align:center;color:var(--sd-text-secondary, #44474f);padding:24px;font-style:italic}.sd-autoid-inspector__filter{display:flex;align-items:center;gap:6px;background:var(--sd-surface-muted, #e7e8ed);border:1px solid var(--sd-border, #c4c6d0);border-radius:8px;padding:6px 10px;margin-bottom:12px;transition:border-color .15s ease}.sd-autoid-inspector__filter:focus-within{border-color:var(--sd-primary, #005cbb);background:#fff}.sd-autoid-inspector__filter input{flex:1;border:none;background:transparent;outline:none;font-size:13px;color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__filter input::placeholder{color:var(--sd-border-strong, #74777f)}.sd-autoid-inspector__filter>sd-icon{font-size:18px;width:18px;height:18px;color:var(--sd-text-secondary, #44474f)}.sd-autoid-inspector__export-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(112px,1fr));gap:8px}.sd-autoid-inspector__export-grid.is-e2e{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}.sd-autoid-inspector__export-grid button{border:1px solid var(--sd-border, #c4c6d0);background:#fff;border-radius:10px;padding:12px 10px;cursor:pointer;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;min-width:0;transition:border-color .15s ease,background .15s ease,transform .12s ease;text-align:center}.sd-autoid-inspector__export-grid button:hover{border-color:var(--sd-primary, #005cbb);background:var(--sd-primary-light, #d7e3ff);transform:translateY(-1px)}.sd-autoid-inspector__export-grid button:disabled{cursor:wait;opacity:.68;transform:none}.sd-autoid-inspector__export-grid button span{font-size:12px;font-weight:600;color:var(--sd-text, #1a1b1f);line-height:1.25}.sd-autoid-inspector__export-grid button small{font-size:10px;color:var(--sd-text-secondary, #44474f);line-height:1.2}.sd-autoid-inspector__export-grid button sd-icon{font-size:22px;width:22px;height:22px;color:var(--sd-primary, #005cbb)}.sd-autoid-inspector__export-section{margin-top:14px;padding-top:12px;border-top:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__context-backdrop{position:fixed;inset:0;z-index:10001;background:#141c2652}.sd-autoid-inspector__context-dialog{position:fixed;z-index:10002;top:50%;left:50%;width:min(720px,100vw - 28px);max-height:min(720px,100vh - 28px);transform:translate(-50%,-50%);display:flex;flex-direction:column;border:1px solid var(--sd-border, #c4c6d0);border-radius:8px;background:#fff;box-shadow:0 18px 48px #0f172a38;overflow:hidden}.sd-autoid-inspector__context-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:14px 16px;border-bottom:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__context-header h4{margin:0;font-size:15px;font-weight:700;line-height:1.3;color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__context-header small{display:block;margin-top:2px;font-size:11px;color:var(--sd-text-secondary, #44474f);line-height:1.3}.sd-autoid-inspector__context-form{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;padding:14px 16px;overflow:auto}.sd-autoid-inspector__context-form label{display:flex;flex-direction:column;gap:6px;min-width:0}.sd-autoid-inspector__context-form label.is-full{grid-column:1/-1}.sd-autoid-inspector__context-form span{font-size:12px;font-weight:600;color:var(--sd-text, #1a1b1f);line-height:1.25}.sd-autoid-inspector__context-form input,.sd-autoid-inspector__context-form textarea{width:100%;min-width:0;border:1px solid var(--sd-border, #c4c6d0);border-radius:6px;padding:8px 10px;color:var(--sd-text, #1a1b1f);font:inherit;font-size:12px;line-height:1.4;outline:none;resize:vertical}.sd-autoid-inspector__context-form input:focus,.sd-autoid-inspector__context-form textarea:focus{border-color:var(--sd-primary, #005cbb);box-shadow:0 0 0 2px color-mix(in srgb,var(--sd-primary, #005cbb) 18%,transparent)}.sd-autoid-inspector__context-actions{display:flex;justify-content:flex-end;gap:8px;padding:12px 16px;border-top:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__context-actions button{min-height:34px;border-radius:6px;padding:0 12px;border:1px solid var(--sd-border, #c4c6d0);background:#fff;color:var(--sd-text, #1a1b1f);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:6px;font-size:12px;font-weight:600}.sd-autoid-inspector__context-actions button.is-primary{border-color:var(--sd-primary, #005cbb);background:var(--sd-primary, #005cbb);color:#fff}.sd-autoid-inspector__context-actions button:disabled{cursor:not-allowed;opacity:.62}.sd-autoid-inspector__context-actions button sd-icon{font-size:17px;width:17px;height:17px}.sd-autoid-inspector__export-message{margin-top:10px;border-radius:8px;padding:8px 10px;font-size:12px;line-height:1.35}.sd-autoid-inspector__export-message.is-success{background:var(--sd-success-light, #d8f0d3);color:var(--sd-success-dark, #1b5e20);border:1px solid var(--sd-success, #2e7d32)}.sd-autoid-inspector__export-message.is-error{background:var(--sd-error-light, #ffdad6);color:var(--sd-error-dark, #93000a);border:1px solid var(--sd-error, #ba1a1a)}@media(max-width:560px){.sd-autoid-inspector__context-form{grid-template-columns:1fr}.sd-autoid-inspector__context-actions{flex-direction:column-reverse}.sd-autoid-inspector__context-actions button{width:100%}}\n"], dependencies: [{ kind: "component", type: SdIcon, selector: "sd-icon", inputs: ["name", "fontIcon", "color", "set", "fontSet", "size", "strokeWidth", "absoluteStrokeWidth", "ariaLabel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.KeyValuePipe, name: "keyvalue" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
964
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdAutoidInspector, isStandalone: true, selector: "sd-autoid-inspector", inputs: { enabled: { classPropertyName: "enabled", publicName: "enabled", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: "@let _enabled = enabled();\n@let _open = open();\n@if (_enabled && !dismissed()) {\n <div class=\"sd-autoid-inspector__fab-wrap\">\n <button\n type=\"button\"\n class=\"sd-autoid-inspector__fab\"\n data-autoid=\"sd-autoid-inspector-fab\"\n [attr.data-opened]=\"dataOpened()\"\n [matTooltip]=\"_open ? '\u0110\u00F3ng AutoId Inspector' : 'M\u1EDF AutoId Inspector'\"\n matTooltipPosition=\"left\"\n (click)=\"togglePanel()\">\n <sd-icon [name]=\"_open ? 'close' : 'tag'\"></sd-icon>\n </button>\n <button\n type=\"button\"\n class=\"sd-autoid-inspector__fab-dismiss\"\n matTooltip=\"\u1EA8n t\u1EA1m \u2014 reload trang \u0111\u1EC3 hi\u1EC7n l\u1EA1i\"\n matTooltipPosition=\"left\"\n aria-label=\"\u1EA8n t\u1EA1m FAB\"\n (click)=\"dismissFab($event)\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n </div>\n}\n\n@if (_enabled && _open) {\n @let _segment = segment();\n <button type=\"button\" class=\"sd-autoid-inspector__backdrop\" aria-label=\"\u0110\u00F3ng AutoId Inspector\" (click)=\"closePanel()\"></button>\n <section\n class=\"sd-autoid-inspector__panel\"\n role=\"dialog\"\n aria-label=\"AutoId Inspector\"\n data-autoid=\"sd-autoid-inspector-panel\"\n [attr.data-segment]=\"dataSegment()\"\n [attr.data-highlight-on]=\"dataHighlightOn()\"\n [attr.data-element-count]=\"dataElementCount()\"\n [attr.data-missing-count]=\"dataMissingCount()\"\n [attr.data-duplicate-count]=\"dataDuplicateCount()\">\n <header class=\"sd-autoid-inspector__header\">\n <div class=\"sd-autoid-inspector__segments\">\n <button type=\"button\" [class.is-active]=\"_segment === 'audit'\" (click)=\"setSegment('audit')\">\n Audit\n @if (audit(); as a) {\n <span class=\"sd-autoid-inspector__badge\" [class.is-warn]=\"a.missingCount + a.duplicateCount > 0\">\n {{ a.missingCount + a.duplicateCount }}\n </span>\n }\n </button>\n <button type=\"button\" [class.is-active]=\"_segment === 'elements'\" (click)=\"setSegment('elements')\">\n Elements\n <span class=\"sd-autoid-inspector__badge\">{{ elements().length }}</span>\n </button>\n <button type=\"button\" [class.is-active]=\"_segment === 'export'\" (click)=\"setSegment('export')\">Export</button>\n </div>\n <div class=\"sd-autoid-inspector__actions\">\n <button type=\"button\" class=\"sd-autoid-inspector__icon-btn\" matTooltip=\"Qu\u00E9t l\u1EA1i\" (click)=\"refresh()\">\n <sd-icon name=\"refresh\"></sd-icon>\n </button>\n <button type=\"button\" class=\"sd-autoid-inspector__close-btn\" matTooltip=\"\u0110\u00F3ng\" aria-label=\"\u0110\u00F3ng panel\" (click)=\"closePanel()\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n </div>\n </header>\n\n @if (copyOk()) {\n <div class=\"sd-autoid-inspector__toast\">\u0110\u00E3 copy \u2713</div>\n }\n\n <div class=\"sd-autoid-inspector__body\">\n @switch (_segment) {\n @case ('audit') {\n <ng-container *ngTemplateOutlet=\"auditTpl\"></ng-container>\n }\n @case ('elements') {\n <ng-container *ngTemplateOutlet=\"elementsTpl\"></ng-container>\n }\n @case ('export') {\n <ng-container *ngTemplateOutlet=\"exportTpl\"></ng-container>\n }\n }\n </div>\n </section>\n\n <ng-template #auditTpl>\n @if (audit(); as a) {\n @let _highlightOn = highlightOn();\n <div class=\"sd-autoid-inspector__audit-toolbar\">\n <button type=\"button\" class=\"sd-autoid-inspector__toggle\" [class.is-on]=\"_highlightOn\" (click)=\"toggleHighlight()\">\n <sd-icon [name]=\"_highlightOn ? 'visibility' : 'visibility_off'\"></sd-icon>\n <span>Highlight DOM</span>\n <span class=\"sd-autoid-inspector__toggle-state\">{{ _highlightOn ? 'ON' : 'OFF' }}</span>\n </button>\n </div>\n <div class=\"sd-autoid-inspector__summary\">\n <div class=\"sd-autoid-inspector__stat is-info\">\n <div class=\"sd-autoid-inspector__stat-value\">{{ a.total }}</div>\n <div class=\"sd-autoid-inspector__stat-label\">T\u1ED5ng autoid</div>\n </div>\n <div class=\"sd-autoid-inspector__stat\" [class.is-error]=\"a.duplicateCount > 0\" [class.is-success]=\"a.duplicateCount === 0\">\n <div class=\"sd-autoid-inspector__stat-value\">{{ a.duplicateCount }}</div>\n <div class=\"sd-autoid-inspector__stat-label\">Tr\u00F9ng</div>\n </div>\n <div class=\"sd-autoid-inspector__stat\" [class.is-warning]=\"a.missingCount > 0\" [class.is-success]=\"a.missingCount === 0\">\n <div class=\"sd-autoid-inspector__stat-value\">{{ a.missingCount }}</div>\n <div class=\"sd-autoid-inspector__stat-label\">Thi\u1EBFu</div>\n </div>\n </div>\n\n @if (a.duplicateCount > 0) {\n <h4 class=\"sd-autoid-inspector__section-title\">\n <sd-icon class=\"is-error\" name=\"error\"></sd-icon>\n Autoid b\u1ECB tr\u00F9ng\n </h4>\n <div class=\"sd-autoid-inspector__table-wrap\">\n <table class=\"sd-autoid-inspector__table\">\n <thead>\n <tr>\n <th>Autoid</th>\n <th>S\u1ED1 l\u1EA7n</th>\n </tr>\n </thead>\n <tbody>\n @for (entry of a.duplicates | keyvalue; track entry.key) {\n <tr class=\"is-error\">\n <td>\n <code>{{ entry.key }}</code>\n </td>\n <td>{{ entry.value }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n @if (a.missingCount > 0) {\n <h4 class=\"sd-autoid-inspector__section-title\">\n <sd-icon class=\"is-warning\" name=\"warning_amber\"></sd-icon>\n Element thi\u1EBFu autoid\n </h4>\n <div class=\"sd-autoid-inspector__table-wrap\">\n <table class=\"sd-autoid-inspector__table\">\n <thead>\n <tr>\n <th>Tag</th>\n <th>Name hint</th>\n <th>Selector</th>\n </tr>\n </thead>\n <tbody>\n @for (m of a.missing; track $index) {\n <tr class=\"is-warning\">\n <td>\n <code>{{ m.tag }}</code>\n </td>\n <td>{{ m.nameHint }}</td>\n <td>\n <code>{{ m.selector }}</code>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n @if (a.duplicateCount === 0 && a.missingCount === 0) {\n <div class=\"sd-autoid-inspector__success-card\">\n <sd-icon name=\"check_circle\"></sd-icon>\n <div>\n <strong>Kh\u00F4ng c\u00F3 element thi\u1EBFu ho\u1EB7c tr\u00F9ng autoid.</strong>\n <small>Trang \u0111\u00E3 \u0111\u1EA1t chu\u1EA9n convention autoid.</small>\n </div>\n </div>\n }\n }\n </ng-template>\n\n <ng-template #elementsTpl>\n @let _filter = filter();\n <div class=\"sd-autoid-inspector__filter\">\n <sd-icon name=\"search\"></sd-icon>\n <input type=\"text\" placeholder=\"L\u1ECDc theo autoid / name / tag\" [ngModel]=\"_filter\" (ngModelChange)=\"filter.set($event)\" />\n @if (_filter) {\n <button type=\"button\" class=\"sd-autoid-inspector__icon-btn\" matTooltip=\"Xo\u00E1 filter\" (click)=\"filter.set('')\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n }\n </div>\n\n <!-- Top-level elements (not inside any sd-table) -->\n <h4 class=\"sd-autoid-inspector__section-title\">\n Top-level elements\n <span class=\"sd-autoid-inspector__badge\">{{ topLevelElements().length }}</span>\n </h4>\n <div class=\"sd-autoid-inspector__table-wrap\">\n <table class=\"sd-autoid-inspector__table\">\n <thead>\n <tr>\n <th class=\"is-num\">STT</th>\n <th>Name</th>\n <th>Autoid</th>\n <th>Tag</th>\n <th>State</th>\n <th>Value</th>\n </tr>\n </thead>\n <tbody>\n @for (el of topLevelElements(); track el.autoid + $index) {\n <tr [class.is-error]=\"el.duplicate\">\n <td class=\"is-num\">{{ el.stt }}</td>\n <td>{{ el.name || '\u2014' }}</td>\n <td>\n <div class=\"sd-autoid-inspector__autoid-cell\">\n <code>{{ el.autoid }}</code>\n <button\n type=\"button\"\n class=\"sd-autoid-inspector__icon-btn is-primary\"\n matTooltip=\"Copy xpath\"\n (click)=\"copyXpath(el.autoid)\">\n <sd-icon name=\"content_copy\"></sd-icon>\n </button>\n </div>\n </td>\n <td>\n <span class=\"sd-autoid-inspector__tag-chip\">{{ el.tag }}</span>\n </td>\n <td class=\"sd-autoid-inspector__state-cell\">\n @if (el.state.disabled !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-error]=\"el.state.disabled === 'true'\">\n disabled={{ el.state.disabled }}\n </span>\n }\n @if (el.state.loading !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-warning]=\"el.state.loading === 'true'\">\n loading={{ el.state.loading }}\n </span>\n }\n @if (el.state.empty !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-info]=\"el.state.empty === 'true'\">\n empty={{ el.state.empty }}\n </span>\n }\n @if (el.state.invalid !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-error]=\"el.state.invalid === 'true'\">\n invalid={{ el.state.invalid }}\n </span>\n }\n @if (el.state.opened !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-info]=\"el.state.opened === 'true'\">\n opened={{ el.state.opened }}\n </span>\n }\n @if (el.state.count !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> count={{ el.state.count }} </span>\n }\n @if (el.state.required !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-warning]=\"el.state.required === 'true'\">\n required={{ el.state.required }}\n </span>\n }\n @if (el.state.maxlength !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> maxlength={{ el.state.maxlength }} </span>\n }\n @if (el.state.minlength !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> minlength={{ el.state.minlength }} </span>\n }\n @if (el.state.pattern !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> pattern={{ el.state.pattern }} </span>\n }\n @if (el.state.errorMessage !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-error\"> error: {{ el.state.errorMessage }} </span>\n }\n </td>\n <td class=\"sd-autoid-inspector__value\" [matTooltip]=\"el.state.dataValue || el.text || ''\">\n {{ el.state.dataValue || el.text || '\u2014' }}\n </td>\n </tr>\n } @empty {\n <tr>\n <td colspan=\"6\" class=\"sd-autoid-inspector__empty\">Kh\u00F4ng c\u00F3 k\u1EBFt qu\u1EA3.</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <!-- One section per sd-table group -->\n @for (group of tableGroups(); track group.scope) {\n <h4 class=\"sd-autoid-inspector__section-title\">\n <sd-icon class=\"is-info\" name=\"table_chart\"></sd-icon>\n Inside <code>{{ group.scope }}</code>\n <span class=\"sd-autoid-inspector__badge\">{{ group.items.length }}</span>\n </h4>\n <div class=\"sd-autoid-inspector__table-wrap\">\n <table class=\"sd-autoid-inspector__table\">\n <thead>\n <tr>\n <th class=\"is-num\">STT</th>\n <th>Name</th>\n <th>Autoid</th>\n <th>Tag</th>\n <th>State</th>\n <th>Value</th>\n </tr>\n </thead>\n <tbody>\n @for (el of group.items; track el.autoid + $index) {\n <tr [class.is-error]=\"el.duplicate\">\n <td class=\"is-num\">{{ el.stt }}</td>\n <td>{{ el.name || '\u2014' }}</td>\n <td>\n <div class=\"sd-autoid-inspector__autoid-cell\">\n <code>{{ el.autoid }}</code>\n <button\n type=\"button\"\n class=\"sd-autoid-inspector__icon-btn is-primary\"\n matTooltip=\"Copy xpath\"\n (click)=\"copyXpath(el.autoid)\">\n <sd-icon name=\"content_copy\"></sd-icon>\n </button>\n </div>\n </td>\n <td>\n <span class=\"sd-autoid-inspector__tag-chip\">{{ el.tag }}</span>\n </td>\n <td class=\"sd-autoid-inspector__state-cell\">\n @if (el.state.disabled !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-error]=\"el.state.disabled === 'true'\">\n disabled={{ el.state.disabled }}\n </span>\n }\n @if (el.state.loading !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-warning]=\"el.state.loading === 'true'\">\n loading={{ el.state.loading }}\n </span>\n }\n @if (el.state.empty !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-info]=\"el.state.empty === 'true'\">\n empty={{ el.state.empty }}\n </span>\n }\n @if (el.state.invalid !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-error]=\"el.state.invalid === 'true'\">\n invalid={{ el.state.invalid }}\n </span>\n }\n @if (el.state.opened !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-info]=\"el.state.opened === 'true'\">\n opened={{ el.state.opened }}\n </span>\n }\n @if (el.state.count !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> count={{ el.state.count }} </span>\n }\n @if (el.state.required !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-warning]=\"el.state.required === 'true'\">\n required={{ el.state.required }}\n </span>\n }\n @if (el.state.maxlength !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> maxlength={{ el.state.maxlength }} </span>\n }\n @if (el.state.minlength !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> minlength={{ el.state.minlength }} </span>\n }\n @if (el.state.pattern !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> pattern={{ el.state.pattern }} </span>\n }\n @if (el.state.errorMessage !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-error\"> error: {{ el.state.errorMessage }} </span>\n }\n </td>\n <td class=\"sd-autoid-inspector__value\" [matTooltip]=\"el.state.dataValue || el.text || ''\">\n {{ el.state.dataValue || el.text || '\u2014' }}\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </ng-template>\n\n <ng-template #exportTpl>\n <div class=\"sd-autoid-inspector__export-grid\">\n <button type=\"button\" matTooltip=\"Copy JSON v\u00E0o clipboard\" (click)=\"copyJson()\">\n <sd-icon name=\"content_copy\"></sd-icon>\n <span>Copy JSON</span>\n <small>clipboard</small>\n </button>\n <button type=\"button\" matTooltip=\"T\u1EA3i file JSON\" (click)=\"exportJson()\">\n <sd-icon name=\"download\"></sd-icon>\n <span>JSON</span>\n <small>.json</small>\n </button>\n <button type=\"button\" matTooltip=\"T\u1EA3i file CSV\" (click)=\"exportCsv()\">\n <sd-icon name=\"table_view\"></sd-icon>\n <span>CSV</span>\n <small>.csv</small>\n </button>\n <button type=\"button\" matTooltip=\"T\u1EA3i MD POM skeleton \u2014 cho AI vi\u1EBFt auto-test\" (click)=\"exportMdPom()\">\n <sd-icon name=\"code\"></sd-icon>\n <span>MD POM</span>\n <small>AI test</small>\n </button>\n <button type=\"button\" matTooltip=\"T\u1EA3i MD reference table \u2014 group theo tag sd-*\" (click)=\"exportMdTable()\">\n <sd-icon name=\"view_list\"></sd-icon>\n <span>MD Table</span>\n <small>reference</small>\n </button>\n </div>\n\n @if (e2eGeneratorHost()) {\n @let _e2eExporting = e2eExporting();\n <div class=\"sd-autoid-inspector__export-section\">\n <h4 class=\"sd-autoid-inspector__section-title\">\n <sd-icon class=\"is-info\" name=\"auto_awesome\"></sd-icon>\n T\u1EA1o E2E test\n </h4>\n <div class=\"sd-autoid-inspector__export-grid is-e2e\">\n <button\n type=\"button\"\n matTooltip=\"T\u1EA1o b\u1ED9 test Playwright (.zip)\"\n [disabled]=\"_e2eExporting !== null\"\n (click)=\"exportE2eTest('playwright')\">\n <sd-icon [name]=\"_e2eExporting === 'playwright' ? 'hourglass_empty' : 'play_arrow'\"></sd-icon>\n <span>Playwright</span>\n <small>.zip</small>\n </button>\n <button\n type=\"button\"\n matTooltip=\"T\u1EA1o b\u1ED9 test Robot Framework (.zip)\"\n [disabled]=\"_e2eExporting !== null\"\n (click)=\"openRobotExportContext()\">\n <sd-icon [name]=\"_e2eExporting === 'robot' ? 'hourglass_empty' : 'smart_toy'\"></sd-icon>\n <span>Robot Framework</span>\n <small>.zip</small>\n </button>\n </div>\n\n @if (robotContextOpen()) {\n <div class=\"sd-autoid-inspector__context-backdrop\" role=\"presentation\" (click)=\"closeRobotExportContext()\"></div>\n <section\n class=\"sd-autoid-inspector__context-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"sd-autoid-robot-context-title\">\n <header class=\"sd-autoid-inspector__context-header\">\n <div>\n <h4 id=\"sd-autoid-robot-context-title\">Ng\u1EEF c\u1EA3nh QC cho Robot Framework</h4>\n <small>Requirement, test case, test data</small>\n </div>\n <button type=\"button\" class=\"sd-autoid-inspector__icon-btn\" matTooltip=\"\u0110\u00F3ng\" (click)=\"closeRobotExportContext()\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n </header>\n\n <div class=\"sd-autoid-inspector__context-form\">\n <label>\n <span>Component</span>\n <input\n type=\"text\"\n placeholder=\"SP-Wallet\"\n [ngModel]=\"robotExportContext().component || ''\"\n (ngModelChange)=\"updateRobotExportContext('component', $event)\" />\n </label>\n <label>\n <span>Story / Trace</span>\n <input\n type=\"text\"\n placeholder=\"US-001, AC-01\"\n [ngModel]=\"robotExportContext().storyLinkages || ''\"\n (ngModelChange)=\"updateRobotExportContext('storyLinkages', $event)\" />\n </label>\n <label class=\"is-full\">\n <span>Requirement / AC / BR</span>\n <textarea\n rows=\"4\"\n placeholder=\"D\u00E1n requirement ho\u1EB7c acceptance criteria...\"\n [ngModel]=\"robotExportContext().requirement || ''\"\n (ngModelChange)=\"updateRobotExportContext('requirement', $event)\"></textarea>\n </label>\n <label class=\"is-full\">\n <span>Test case QC \u0111\u00E3 \u0111\u1ECBnh ngh\u0129a</span>\n <textarea\n rows=\"4\"\n placeholder=\"TC-001: ...\"\n [ngModel]=\"robotExportContext().testCases || ''\"\n (ngModelChange)=\"updateRobotExportContext('testCases', $event)\"></textarea>\n </label>\n <label class=\"is-full\">\n <span>Test data</span>\n <textarea\n rows=\"3\"\n placeholder=\"wallet=V\u00ED A, amount=100000...\"\n [ngModel]=\"robotExportContext().testData || ''\"\n (ngModelChange)=\"updateRobotExportContext('testData', $event)\"></textarea>\n </label>\n <label class=\"is-full\">\n <span>Precondition</span>\n <textarea\n rows=\"2\"\n placeholder=\"User \u0111\u00E3 \u0111\u0103ng nh\u1EADp, d\u1EEF li\u1EC7u v\u00ED \u0111\u00E3 t\u1ED3n t\u1EA1i...\"\n [ngModel]=\"robotExportContext().precondition || ''\"\n (ngModelChange)=\"updateRobotExportContext('precondition', $event)\"></textarea>\n </label>\n <label class=\"is-full\">\n <span>Ghi ch\u00FA format QC</span>\n <textarea\n rows=\"3\"\n placeholder=\"Smoke=Y, Auto=Y, \u01B0u ti\u00EAn happy path...\"\n [ngModel]=\"robotExportContext().qcNotes || ''\"\n (ngModelChange)=\"updateRobotExportContext('qcNotes', $event)\"></textarea>\n </label>\n </div>\n\n <footer class=\"sd-autoid-inspector__context-actions\">\n <button type=\"button\" class=\"is-secondary\" [disabled]=\"_e2eExporting !== null\" (click)=\"closeRobotExportContext()\">\n Hu\u1EF7\n </button>\n <button\n type=\"button\"\n class=\"is-primary\"\n [disabled]=\"_e2eExporting !== null || !hasRobotExportContext()\"\n (click)=\"confirmRobotExport()\">\n <sd-icon [name]=\"_e2eExporting === 'robot' ? 'hourglass_empty' : 'download'\"></sd-icon>\n <span>\u0110\u1ED3ng \u00FD xu\u1EA5t</span>\n </button>\n </footer>\n </section>\n }\n\n @if (e2eExportOk(); as targetLabel) {\n <div class=\"sd-autoid-inspector__export-message is-success\">\u0110\u00E3 t\u1EA3i b\u1ED9 test {{ targetLabel }}.</div>\n }\n @if (e2eExportError(); as error) {\n <div class=\"sd-autoid-inspector__export-message is-error\">\n {{ error }}\n </div>\n }\n </div>\n }\n </ng-template>\n}\n", styles: [":host{position:fixed;inset:auto 0 0 auto;z-index:100000;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-size:13px;color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__fab-wrap{position:fixed;right:16px;bottom:16px;z-index:100000}.sd-autoid-inspector__fab-wrap:hover .sd-autoid-inspector__fab-dismiss{opacity:1;transform:scale(1);pointer-events:auto}.sd-autoid-inspector__fab{width:36px;height:36px;border-radius:50%;border:none;background:var(--sd-primary, #005cbb);color:#fff;cursor:pointer;box-shadow:0 3px 10px #00000038;display:inline-flex;align-items:center;justify-content:center;transition:transform .15s ease,background .15s ease,box-shadow .15s ease}.sd-autoid-inspector__fab:hover{background:var(--sd-primary-dark, #00458f);transform:scale(1.08);box-shadow:0 5px 14px #00000047}.sd-autoid-inspector__fab sd-icon{font-size:18px;width:18px;height:18px}.sd-autoid-inspector__fab-dismiss{position:absolute;top:-6px;right:-6px;width:18px;height:18px;border-radius:50%;border:1px solid var(--sd-border, #c4c6d0);background:#fff;color:var(--sd-text-secondary, #44474f);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;opacity:0;transform:scale(.7);pointer-events:none;transition:opacity .12s ease,transform .12s ease,color .12s ease,background .12s ease;box-shadow:0 1px 4px #00000026}.sd-autoid-inspector__fab-dismiss:hover{background:var(--sd-error-light, #ffdad6);color:var(--sd-error-dark, #93000a);border-color:var(--sd-error, #ba1a1a)}.sd-autoid-inspector__fab-dismiss sd-icon{font-size:12px;width:12px;height:12px;line-height:12px}.sd-autoid-inspector__backdrop{position:fixed;inset:0;padding:0;border:none;background:#00000052;z-index:100001;backdrop-filter:blur(2px)}.sd-autoid-inspector__panel{position:fixed;right:20px;bottom:80px;width:min(860px,100vw - 40px);max-height:calc(100vh - 110px);background:#fff;border-radius:12px;box-shadow:0 16px 48px #00000038;display:flex;flex-direction:column;z-index:100002;overflow:hidden;border:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__header{display:flex;align-items:center;gap:8px;padding:8px 10px;border-bottom:1px solid var(--sd-border, #c4c6d0);background:var(--sd-surface-muted, #e7e8ed);flex-shrink:0}.sd-autoid-inspector__segments{display:inline-flex;border:1px solid var(--sd-border, #c4c6d0);border-radius:8px;background:#fff;overflow:hidden}.sd-autoid-inspector__segments button{border:none;background:transparent;padding:5px 12px;cursor:pointer;font-size:12px;font-weight:500;color:var(--sd-text-secondary, #44474f);display:inline-flex;align-items:center;gap:6px;border-right:1px solid var(--sd-border, #c4c6d0);transition:background .12s ease,color .12s ease}.sd-autoid-inspector__segments button:last-child{border-right:none}.sd-autoid-inspector__segments button:hover:not(.is-active){background:var(--sd-surface-muted, #e7e8ed);color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__segments button.is-active{background:var(--sd-primary, #005cbb);color:#fff}.sd-autoid-inspector__badge{background:var(--sd-border, #c4c6d0);color:var(--sd-text, #1a1b1f);border-radius:10px;padding:0 7px;font-size:11px;font-weight:600;line-height:16px}.is-active .sd-autoid-inspector__badge{background:#ffffff40;color:#fff}.sd-autoid-inspector__badge.is-warn{background:var(--sd-error, #ba1a1a);color:#fff}.sd-autoid-inspector__actions{display:inline-flex;gap:4px;margin-left:auto}.sd-autoid-inspector__icon-btn{border:none;background:transparent;cursor:pointer;padding:4px;border-radius:6px;color:var(--sd-text-secondary, #44474f);display:inline-flex;align-items:center;justify-content:center;transition:background .12s ease,color .12s ease}.sd-autoid-inspector__icon-btn:hover{background:var(--sd-surface-muted, #e7e8ed);color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__icon-btn.is-primary{color:var(--sd-primary, #005cbb)}.sd-autoid-inspector__icon-btn.is-primary:hover{background:var(--sd-primary-light, #d7e3ff);color:var(--sd-primary-dark, #00458f)}.sd-autoid-inspector__icon-btn sd-icon{font-size:18px;width:18px;height:18px}.sd-autoid-inspector__close-btn{border:none;cursor:pointer;padding:4px;border-radius:50%;width:28px;height:28px;background:transparent;color:var(--sd-text-secondary, #44474f);display:inline-flex;align-items:center;justify-content:center;transition:background .12s ease,color .12s ease}.sd-autoid-inspector__close-btn:hover{background:var(--sd-error-light, #ffdad6);color:var(--sd-error-dark, #93000a)}.sd-autoid-inspector__close-btn sd-icon{font-size:18px;width:18px;height:18px}.sd-autoid-inspector__body{padding:14px;overflow:auto;flex:1;background:#fff}.sd-autoid-inspector__toast{position:absolute;top:56px;right:14px;background:var(--sd-success, #2e7d32);color:#fff;padding:6px 12px;border-radius:6px;font-size:12px;z-index:2;box-shadow:0 4px 12px #0000002e}.sd-autoid-inspector__audit-toolbar{display:flex;justify-content:flex-end;margin-bottom:12px}.sd-autoid-inspector__toggle{display:inline-flex;align-items:center;gap:8px;border:1px solid var(--sd-border, #c4c6d0);background:#fff;border-radius:999px;padding:5px 12px 5px 10px;cursor:pointer;font-size:12px;font-weight:500;color:var(--sd-text-secondary, #44474f);transition:all .15s ease}.sd-autoid-inspector__toggle:hover{border-color:var(--sd-primary, #005cbb);color:var(--sd-primary, #005cbb)}.sd-autoid-inspector__toggle.is-on{border-color:var(--sd-primary, #005cbb);color:var(--sd-primary, #005cbb);background:var(--sd-primary-light, #d7e3ff)}.sd-autoid-inspector__toggle sd-icon{font-size:16px;width:16px;height:16px}.sd-autoid-inspector__toggle-state{font-size:10px;font-weight:700;padding:1px 7px;border-radius:999px;background:var(--sd-border, #c4c6d0);color:var(--sd-text-secondary, #44474f)}.is-on .sd-autoid-inspector__toggle-state{background:var(--sd-primary, #005cbb);color:#fff}.sd-autoid-inspector__summary{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:16px}.sd-autoid-inspector__stat{background:var(--sd-surface-muted, #e7e8ed);border-radius:10px;padding:12px;text-align:center;border:1px solid transparent}.sd-autoid-inspector__stat.is-info{background:var(--sd-info-light, #d4f7f6);border-color:var(--sd-info, #006a6a)}.sd-autoid-inspector__stat.is-info .sd-autoid-inspector__stat-value{color:var(--sd-info, #006a6a)}.sd-autoid-inspector__stat.is-success{background:var(--sd-success-light, #d8f0d3);border-color:var(--sd-success, #2e7d32)}.sd-autoid-inspector__stat.is-success .sd-autoid-inspector__stat-value{color:var(--sd-success-dark, #1b5e20)}.sd-autoid-inspector__stat.is-warning{background:var(--sd-warning-light, #ffddb0);border-color:var(--sd-warning, #a66300)}.sd-autoid-inspector__stat.is-warning .sd-autoid-inspector__stat-value{color:var(--sd-warning-dark, #7a4d00)}.sd-autoid-inspector__stat.is-error{background:var(--sd-error-light, #ffdad6);border-color:var(--sd-error, #ba1a1a)}.sd-autoid-inspector__stat.is-error .sd-autoid-inspector__stat-value{color:var(--sd-error-dark, #93000a)}.sd-autoid-inspector__stat-value{font-size:22px;font-weight:700;line-height:1;margin-bottom:4px}.sd-autoid-inspector__stat-label{font-size:11px;color:var(--sd-text-secondary, #44474f);text-transform:uppercase;letter-spacing:.4px;font-weight:600}.sd-autoid-inspector__section-title{display:flex;align-items:center;gap:6px;margin:14px 0 8px;font-size:13px;font-weight:600;color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__section-title sd-icon{font-size:18px;width:18px;height:18px}.sd-autoid-inspector__section-title sd-icon.is-error{color:var(--sd-error, #ba1a1a)}.sd-autoid-inspector__section-title sd-icon.is-warning{color:var(--sd-warning, #a66300)}.sd-autoid-inspector__section-title sd-icon.is-info{color:var(--sd-info, #006a6a)}.sd-autoid-inspector__success-card{display:flex;align-items:center;gap:12px;padding:14px 16px;background:var(--sd-success-light, #d8f0d3);border:1px solid var(--sd-success, #2e7d32);border-radius:10px;color:var(--sd-success-dark, #1b5e20)}.sd-autoid-inspector__success-card sd-icon{font-size:28px;width:28px;height:28px;color:var(--sd-success, #2e7d32)}.sd-autoid-inspector__success-card strong{display:block;font-size:13px;margin-bottom:2px}.sd-autoid-inspector__success-card small{font-size:11px;opacity:.85}.sd-autoid-inspector__table-wrap{border:1px solid var(--sd-border, #c4c6d0);border-radius:8px;overflow:auto;max-height:60vh;background:#fff}.sd-autoid-inspector__table{width:100%;border-collapse:separate;border-spacing:0;font-size:12px}.sd-autoid-inspector__table th,.sd-autoid-inspector__table td{padding:8px 10px;text-align:left;vertical-align:middle;border-bottom:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__table thead th{position:sticky;top:0;z-index:1;background:var(--sd-surface-muted, #e7e8ed);font-weight:600;color:var(--sd-text, #1a1b1f);text-transform:none;font-size:11px;letter-spacing:.3px;border-bottom:none;box-shadow:inset 0 -1px 0 var(--sd-border, #c4c6d0),0 2px 4px #0000000a;white-space:nowrap}.sd-autoid-inspector__table thead th.is-num{text-align:right;width:50px}.sd-autoid-inspector__table tbody tr{transition:background .1s ease}.sd-autoid-inspector__table tbody tr:hover{background:var(--sd-primary-light, #d7e3ff)}.sd-autoid-inspector__table tbody tr:last-child td{border-bottom:none}.sd-autoid-inspector__table tbody tr.is-error{background:var(--sd-error-light, #ffdad6)}.sd-autoid-inspector__table tbody tr.is-error:hover{background:var(--sd-error-light, #ffdad6);filter:brightness(.98)}.sd-autoid-inspector__table tbody tr.is-warning{background:var(--sd-warning-light, #ffddb0)}.sd-autoid-inspector__table tbody tr.is-warning:hover{background:var(--sd-warning-light, #ffddb0);filter:brightness(.98)}.sd-autoid-inspector__table td.is-num{text-align:right;color:var(--sd-text-secondary, #44474f);font-variant-numeric:tabular-nums}.sd-autoid-inspector__table code{font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:11px;background:var(--sd-surface-muted, #e7e8ed);padding:2px 6px;border-radius:4px;color:var(--sd-primary-dark, #00458f);border:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__autoid-cell{display:inline-flex;align-items:center;gap:6px}.sd-autoid-inspector__tag-chip{display:inline-block;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:11px;background:var(--sd-info-light, #d4f7f6);color:var(--sd-info, #006a6a);border:1px solid var(--sd-info, #006a6a);padding:1px 8px;border-radius:999px;font-weight:500}.sd-autoid-inspector__value{max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--sd-text-secondary, #44474f);font-style:italic}.sd-autoid-inspector__state-cell{display:flex;flex-wrap:wrap;gap:4px;align-items:center;min-width:0}.sd-autoid-inspector__state-chip{display:inline-block;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:10px;background:var(--sd-surface-muted, #e7e8ed);color:var(--sd-text-secondary, #44474f);border:1px solid var(--sd-border, #c4c6d0);padding:1px 6px;border-radius:999px;font-weight:500;white-space:nowrap}.sd-autoid-inspector__state-chip.is-error{background:var(--sd-error-light, #ffdad6);color:var(--sd-error-dark, #93000a);border-color:var(--sd-error, #ba1a1a)}.sd-autoid-inspector__state-chip.is-warning{background:var(--sd-warning-light, #ffddb0);color:var(--sd-warning-dark, #7a4d00);border-color:var(--sd-warning, #a66300)}.sd-autoid-inspector__state-chip.is-info{background:var(--sd-info-light, #d4f7f6);color:var(--sd-info, #006a6a);border-color:var(--sd-info, #006a6a)}.sd-autoid-inspector__empty{text-align:center;color:var(--sd-text-secondary, #44474f);padding:24px;font-style:italic}.sd-autoid-inspector__filter{display:flex;align-items:center;gap:6px;background:var(--sd-surface-muted, #e7e8ed);border:1px solid var(--sd-border, #c4c6d0);border-radius:8px;padding:6px 10px;margin-bottom:12px;transition:border-color .15s ease}.sd-autoid-inspector__filter:focus-within{border-color:var(--sd-primary, #005cbb);background:#fff}.sd-autoid-inspector__filter input{flex:1;border:none;background:transparent;outline:none;font-size:13px;color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__filter input::placeholder{color:var(--sd-border-strong, #74777f)}.sd-autoid-inspector__filter input:focus-visible{outline:2px solid var(--sd-primary, #005cbb);outline-offset:1px;border-radius:4px}.sd-autoid-inspector__filter>sd-icon{font-size:18px;width:18px;height:18px;color:var(--sd-text-secondary, #44474f)}.sd-autoid-inspector__export-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(112px,1fr));gap:8px}.sd-autoid-inspector__export-grid.is-e2e{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}.sd-autoid-inspector__export-grid button{border:1px solid var(--sd-border, #c4c6d0);background:#fff;border-radius:10px;padding:12px 10px;cursor:pointer;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;min-width:0;transition:border-color .15s ease,background .15s ease,transform .12s ease;text-align:center}.sd-autoid-inspector__export-grid button:hover{border-color:var(--sd-primary, #005cbb);background:var(--sd-primary-light, #d7e3ff);transform:translateY(-1px)}.sd-autoid-inspector__export-grid button:disabled{cursor:wait;opacity:.68;transform:none}.sd-autoid-inspector__export-grid button span{font-size:12px;font-weight:600;color:var(--sd-text, #1a1b1f);line-height:1.25}.sd-autoid-inspector__export-grid button small{font-size:10px;color:var(--sd-text-secondary, #44474f);line-height:1.2}.sd-autoid-inspector__export-grid button sd-icon{font-size:22px;width:22px;height:22px;color:var(--sd-primary, #005cbb)}.sd-autoid-inspector__export-section{margin-top:14px;padding-top:12px;border-top:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__context-backdrop{position:fixed;inset:0;z-index:10001;background:#141c2652}.sd-autoid-inspector__context-dialog{position:fixed;z-index:10002;top:50%;left:50%;width:min(720px,100vw - 28px);max-height:min(720px,100vh - 28px);transform:translate(-50%,-50%);display:flex;flex-direction:column;border:1px solid var(--sd-border, #c4c6d0);border-radius:8px;background:#fff;box-shadow:0 18px 48px #0f172a38;overflow:hidden}.sd-autoid-inspector__context-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:14px 16px;border-bottom:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__context-header h4{margin:0;font-size:15px;font-weight:700;line-height:1.3;color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__context-header small{display:block;margin-top:2px;font-size:11px;color:var(--sd-text-secondary, #44474f);line-height:1.3}.sd-autoid-inspector__context-form{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;padding:14px 16px;overflow:auto}.sd-autoid-inspector__context-form label{display:flex;flex-direction:column;gap:6px;min-width:0}.sd-autoid-inspector__context-form label.is-full{grid-column:1/-1}.sd-autoid-inspector__context-form span{font-size:12px;font-weight:600;color:var(--sd-text, #1a1b1f);line-height:1.25}.sd-autoid-inspector__context-form input,.sd-autoid-inspector__context-form textarea{width:100%;min-width:0;border:1px solid var(--sd-border, #c4c6d0);border-radius:6px;padding:8px 10px;color:var(--sd-text, #1a1b1f);font:inherit;font-size:12px;line-height:1.4;outline:none;resize:vertical}.sd-autoid-inspector__context-form input:focus,.sd-autoid-inspector__context-form textarea:focus{border-color:var(--sd-primary, #005cbb);box-shadow:0 0 0 2px color-mix(in srgb,var(--sd-primary, #005cbb) 18%,transparent)}.sd-autoid-inspector__context-actions{display:flex;justify-content:flex-end;gap:8px;padding:12px 16px;border-top:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__context-actions button{min-height:34px;border-radius:6px;padding:0 12px;border:1px solid var(--sd-border, #c4c6d0);background:#fff;color:var(--sd-text, #1a1b1f);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:6px;font-size:12px;font-weight:600}.sd-autoid-inspector__context-actions button.is-primary{border-color:var(--sd-primary, #005cbb);background:var(--sd-primary, #005cbb);color:#fff}.sd-autoid-inspector__context-actions button:disabled{cursor:not-allowed;opacity:.62}.sd-autoid-inspector__context-actions button sd-icon{font-size:17px;width:17px;height:17px}.sd-autoid-inspector__export-message{margin-top:10px;border-radius:8px;padding:8px 10px;font-size:12px;line-height:1.35}.sd-autoid-inspector__export-message.is-success{background:var(--sd-success-light, #d8f0d3);color:var(--sd-success-dark, #1b5e20);border:1px solid var(--sd-success, #2e7d32)}.sd-autoid-inspector__export-message.is-error{background:var(--sd-error-light, #ffdad6);color:var(--sd-error-dark, #93000a);border:1px solid var(--sd-error, #ba1a1a)}@media(max-width:560px){.sd-autoid-inspector__context-form{grid-template-columns:1fr}.sd-autoid-inspector__context-actions{flex-direction:column-reverse}.sd-autoid-inspector__context-actions button{width:100%}}\n"], dependencies: [{ kind: "component", type: SdIcon, selector: "sd-icon", inputs: ["name", "fontIcon", "color", "set", "fontSet", "size", "strokeWidth", "absoluteStrokeWidth", "ariaLabel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.KeyValuePipe, name: "keyvalue" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
965
965
|
}
|
|
966
966
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdAutoidInspector, decorators: [{
|
|
967
967
|
type: Component,
|
|
968
|
-
args: [{ selector: 'sd-autoid-inspector', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [SdIcon, CommonModule, FormsModule, MatTooltipModule], template: "@let _enabled = enabled();\n@let _open = open();\n@if (_enabled && !dismissed()) {\n <div class=\"sd-autoid-inspector__fab-wrap\">\n <button\n type=\"button\"\n class=\"sd-autoid-inspector__fab\"\n data-autoid=\"sd-autoid-inspector-fab\"\n [attr.data-opened]=\"dataOpened()\"\n [matTooltip]=\"_open ? '\u0110\u00F3ng AutoId Inspector' : 'M\u1EDF AutoId Inspector'\"\n matTooltipPosition=\"left\"\n (click)=\"togglePanel()\">\n <sd-icon [name]=\"_open ? 'close' : 'tag'\"></sd-icon>\n </button>\n <button\n type=\"button\"\n class=\"sd-autoid-inspector__fab-dismiss\"\n matTooltip=\"\u1EA8n t\u1EA1m \u2014 reload trang \u0111\u1EC3 hi\u1EC7n l\u1EA1i\"\n matTooltipPosition=\"left\"\n aria-label=\"\u1EA8n t\u1EA1m FAB\"\n (click)=\"dismissFab($event)\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n </div>\n}\n\n@if (_enabled && _open) {\n @let _segment = segment();\n <button type=\"button\" class=\"sd-autoid-inspector__backdrop\" aria-label=\"\u0110\u00F3ng AutoId Inspector\" (click)=\"closePanel()\"></button>\n <section\n class=\"sd-autoid-inspector__panel\"\n role=\"dialog\"\n aria-label=\"AutoId Inspector\"\n data-autoid=\"sd-autoid-inspector-panel\"\n [attr.data-segment]=\"dataSegment()\"\n [attr.data-highlight-on]=\"dataHighlightOn()\"\n [attr.data-element-count]=\"dataElementCount()\"\n [attr.data-missing-count]=\"dataMissingCount()\"\n [attr.data-duplicate-count]=\"dataDuplicateCount()\">\n <header class=\"sd-autoid-inspector__header\">\n <div class=\"sd-autoid-inspector__segments\">\n <button type=\"button\" [class.is-active]=\"_segment === 'audit'\" (click)=\"setSegment('audit')\">\n Audit\n @if (audit(); as a) {\n <span class=\"sd-autoid-inspector__badge\" [class.is-warn]=\"a.missingCount + a.duplicateCount > 0\">\n {{ a.missingCount + a.duplicateCount }}\n </span>\n }\n </button>\n <button type=\"button\" [class.is-active]=\"_segment === 'elements'\" (click)=\"setSegment('elements')\">\n Elements\n <span class=\"sd-autoid-inspector__badge\">{{ elements().length }}</span>\n </button>\n <button type=\"button\" [class.is-active]=\"_segment === 'export'\" (click)=\"setSegment('export')\">Export</button>\n </div>\n <div class=\"sd-autoid-inspector__actions\">\n <button type=\"button\" class=\"sd-autoid-inspector__icon-btn\" matTooltip=\"Qu\u00E9t l\u1EA1i\" (click)=\"refresh()\">\n <sd-icon name=\"refresh\"></sd-icon>\n </button>\n <button type=\"button\" class=\"sd-autoid-inspector__close-btn\" matTooltip=\"\u0110\u00F3ng\" aria-label=\"\u0110\u00F3ng panel\" (click)=\"closePanel()\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n </div>\n </header>\n\n @if (copyOk()) {\n <div class=\"sd-autoid-inspector__toast\">\u0110\u00E3 copy \u2713</div>\n }\n\n <div class=\"sd-autoid-inspector__body\">\n @switch (_segment) {\n @case ('audit') {\n <ng-container *ngTemplateOutlet=\"auditTpl\"></ng-container>\n }\n @case ('elements') {\n <ng-container *ngTemplateOutlet=\"elementsTpl\"></ng-container>\n }\n @case ('export') {\n <ng-container *ngTemplateOutlet=\"exportTpl\"></ng-container>\n }\n }\n </div>\n </section>\n\n <ng-template #auditTpl>\n @if (audit(); as a) {\n @let _highlightOn = highlightOn();\n <div class=\"sd-autoid-inspector__audit-toolbar\">\n <button type=\"button\" class=\"sd-autoid-inspector__toggle\" [class.is-on]=\"_highlightOn\" (click)=\"toggleHighlight()\">\n <sd-icon [name]=\"_highlightOn ? 'visibility' : 'visibility_off'\"></sd-icon>\n <span>Highlight DOM</span>\n <span class=\"sd-autoid-inspector__toggle-state\">{{ _highlightOn ? 'ON' : 'OFF' }}</span>\n </button>\n </div>\n <div class=\"sd-autoid-inspector__summary\">\n <div class=\"sd-autoid-inspector__stat is-info\">\n <div class=\"sd-autoid-inspector__stat-value\">{{ a.total }}</div>\n <div class=\"sd-autoid-inspector__stat-label\">T\u1ED5ng autoid</div>\n </div>\n <div class=\"sd-autoid-inspector__stat\" [class.is-error]=\"a.duplicateCount > 0\" [class.is-success]=\"a.duplicateCount === 0\">\n <div class=\"sd-autoid-inspector__stat-value\">{{ a.duplicateCount }}</div>\n <div class=\"sd-autoid-inspector__stat-label\">Tr\u00F9ng</div>\n </div>\n <div class=\"sd-autoid-inspector__stat\" [class.is-warning]=\"a.missingCount > 0\" [class.is-success]=\"a.missingCount === 0\">\n <div class=\"sd-autoid-inspector__stat-value\">{{ a.missingCount }}</div>\n <div class=\"sd-autoid-inspector__stat-label\">Thi\u1EBFu</div>\n </div>\n </div>\n\n @if (a.duplicateCount > 0) {\n <h4 class=\"sd-autoid-inspector__section-title\">\n <sd-icon class=\"is-error\" name=\"error\"></sd-icon>\n Autoid b\u1ECB tr\u00F9ng\n </h4>\n <div class=\"sd-autoid-inspector__table-wrap\">\n <table class=\"sd-autoid-inspector__table\">\n <thead>\n <tr>\n <th>Autoid</th>\n <th>S\u1ED1 l\u1EA7n</th>\n </tr>\n </thead>\n <tbody>\n @for (entry of a.duplicates | keyvalue; track entry.key) {\n <tr class=\"is-error\">\n <td>\n <code>{{ entry.key }}</code>\n </td>\n <td>{{ entry.value }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n @if (a.missingCount > 0) {\n <h4 class=\"sd-autoid-inspector__section-title\">\n <sd-icon class=\"is-warning\" name=\"warning_amber\"></sd-icon>\n Element thi\u1EBFu autoid\n </h4>\n <div class=\"sd-autoid-inspector__table-wrap\">\n <table class=\"sd-autoid-inspector__table\">\n <thead>\n <tr>\n <th>Tag</th>\n <th>Name hint</th>\n <th>Selector</th>\n </tr>\n </thead>\n <tbody>\n @for (m of a.missing; track $index) {\n <tr class=\"is-warning\">\n <td>\n <code>{{ m.tag }}</code>\n </td>\n <td>{{ m.nameHint }}</td>\n <td>\n <code>{{ m.selector }}</code>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n @if (a.duplicateCount === 0 && a.missingCount === 0) {\n <div class=\"sd-autoid-inspector__success-card\">\n <sd-icon name=\"check_circle\"></sd-icon>\n <div>\n <strong>Kh\u00F4ng c\u00F3 element thi\u1EBFu ho\u1EB7c tr\u00F9ng autoid.</strong>\n <small>Trang \u0111\u00E3 \u0111\u1EA1t chu\u1EA9n convention autoid.</small>\n </div>\n </div>\n }\n }\n </ng-template>\n\n <ng-template #elementsTpl>\n @let _filter = filter();\n <div class=\"sd-autoid-inspector__filter\">\n <sd-icon name=\"search\"></sd-icon>\n <input type=\"text\" placeholder=\"L\u1ECDc theo autoid / name / tag\" [ngModel]=\"_filter\" (ngModelChange)=\"filter.set($event)\" />\n @if (_filter) {\n <button type=\"button\" class=\"sd-autoid-inspector__icon-btn\" matTooltip=\"Xo\u00E1 filter\" (click)=\"filter.set('')\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n }\n </div>\n\n <!-- Top-level elements (not inside any sd-table) -->\n <h4 class=\"sd-autoid-inspector__section-title\">\n Top-level elements\n <span class=\"sd-autoid-inspector__badge\">{{ topLevelElements().length }}</span>\n </h4>\n <div class=\"sd-autoid-inspector__table-wrap\">\n <table class=\"sd-autoid-inspector__table\">\n <thead>\n <tr>\n <th class=\"is-num\">STT</th>\n <th>Name</th>\n <th>Autoid</th>\n <th>Tag</th>\n <th>State</th>\n <th>Value</th>\n </tr>\n </thead>\n <tbody>\n @for (el of topLevelElements(); track el.autoid + $index) {\n <tr [class.is-error]=\"el.duplicate\">\n <td class=\"is-num\">{{ el.stt }}</td>\n <td>{{ el.name || '\u2014' }}</td>\n <td>\n <div class=\"sd-autoid-inspector__autoid-cell\">\n <code>{{ el.autoid }}</code>\n <button\n type=\"button\"\n class=\"sd-autoid-inspector__icon-btn is-primary\"\n matTooltip=\"Copy xpath\"\n (click)=\"copyXpath(el.autoid)\">\n <sd-icon name=\"content_copy\"></sd-icon>\n </button>\n </div>\n </td>\n <td>\n <span class=\"sd-autoid-inspector__tag-chip\">{{ el.tag }}</span>\n </td>\n <td class=\"sd-autoid-inspector__state-cell\">\n @if (el.state.disabled !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-error]=\"el.state.disabled === 'true'\">\n disabled={{ el.state.disabled }}\n </span>\n }\n @if (el.state.loading !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-warning]=\"el.state.loading === 'true'\">\n loading={{ el.state.loading }}\n </span>\n }\n @if (el.state.empty !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-info]=\"el.state.empty === 'true'\">\n empty={{ el.state.empty }}\n </span>\n }\n @if (el.state.invalid !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-error]=\"el.state.invalid === 'true'\">\n invalid={{ el.state.invalid }}\n </span>\n }\n @if (el.state.opened !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-info]=\"el.state.opened === 'true'\">\n opened={{ el.state.opened }}\n </span>\n }\n @if (el.state.count !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> count={{ el.state.count }} </span>\n }\n @if (el.state.required !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-warning]=\"el.state.required === 'true'\">\n required={{ el.state.required }}\n </span>\n }\n @if (el.state.maxlength !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> maxlength={{ el.state.maxlength }} </span>\n }\n @if (el.state.minlength !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> minlength={{ el.state.minlength }} </span>\n }\n @if (el.state.pattern !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> pattern={{ el.state.pattern }} </span>\n }\n @if (el.state.errorMessage !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-error\"> error: {{ el.state.errorMessage }} </span>\n }\n </td>\n <td class=\"sd-autoid-inspector__value\" [matTooltip]=\"el.state.dataValue || el.text || ''\">\n {{ el.state.dataValue || el.text || '\u2014' }}\n </td>\n </tr>\n } @empty {\n <tr>\n <td colspan=\"6\" class=\"sd-autoid-inspector__empty\">Kh\u00F4ng c\u00F3 k\u1EBFt qu\u1EA3.</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <!-- One section per sd-table group -->\n @for (group of tableGroups(); track group.scope) {\n <h4 class=\"sd-autoid-inspector__section-title\">\n <sd-icon class=\"is-info\" name=\"table_chart\"></sd-icon>\n Inside <code>{{ group.scope }}</code>\n <span class=\"sd-autoid-inspector__badge\">{{ group.items.length }}</span>\n </h4>\n <div class=\"sd-autoid-inspector__table-wrap\">\n <table class=\"sd-autoid-inspector__table\">\n <thead>\n <tr>\n <th class=\"is-num\">STT</th>\n <th>Name</th>\n <th>Autoid</th>\n <th>Tag</th>\n <th>State</th>\n <th>Value</th>\n </tr>\n </thead>\n <tbody>\n @for (el of group.items; track el.autoid + $index) {\n <tr [class.is-error]=\"el.duplicate\">\n <td class=\"is-num\">{{ el.stt }}</td>\n <td>{{ el.name || '\u2014' }}</td>\n <td>\n <div class=\"sd-autoid-inspector__autoid-cell\">\n <code>{{ el.autoid }}</code>\n <button\n type=\"button\"\n class=\"sd-autoid-inspector__icon-btn is-primary\"\n matTooltip=\"Copy xpath\"\n (click)=\"copyXpath(el.autoid)\">\n <sd-icon name=\"content_copy\"></sd-icon>\n </button>\n </div>\n </td>\n <td>\n <span class=\"sd-autoid-inspector__tag-chip\">{{ el.tag }}</span>\n </td>\n <td class=\"sd-autoid-inspector__state-cell\">\n @if (el.state.disabled !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-error]=\"el.state.disabled === 'true'\">\n disabled={{ el.state.disabled }}\n </span>\n }\n @if (el.state.loading !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-warning]=\"el.state.loading === 'true'\">\n loading={{ el.state.loading }}\n </span>\n }\n @if (el.state.empty !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-info]=\"el.state.empty === 'true'\">\n empty={{ el.state.empty }}\n </span>\n }\n @if (el.state.invalid !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-error]=\"el.state.invalid === 'true'\">\n invalid={{ el.state.invalid }}\n </span>\n }\n @if (el.state.opened !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-info]=\"el.state.opened === 'true'\">\n opened={{ el.state.opened }}\n </span>\n }\n @if (el.state.count !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> count={{ el.state.count }} </span>\n }\n @if (el.state.required !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-warning]=\"el.state.required === 'true'\">\n required={{ el.state.required }}\n </span>\n }\n @if (el.state.maxlength !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> maxlength={{ el.state.maxlength }} </span>\n }\n @if (el.state.minlength !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> minlength={{ el.state.minlength }} </span>\n }\n @if (el.state.pattern !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> pattern={{ el.state.pattern }} </span>\n }\n @if (el.state.errorMessage !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-error\"> error: {{ el.state.errorMessage }} </span>\n }\n </td>\n <td class=\"sd-autoid-inspector__value\" [matTooltip]=\"el.state.dataValue || el.text || ''\">\n {{ el.state.dataValue || el.text || '\u2014' }}\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </ng-template>\n\n <ng-template #exportTpl>\n <div class=\"sd-autoid-inspector__export-grid\">\n <button type=\"button\" matTooltip=\"Copy JSON v\u00E0o clipboard\" (click)=\"copyJson()\">\n <sd-icon name=\"content_copy\"></sd-icon>\n <span>Copy JSON</span>\n <small>clipboard</small>\n </button>\n <button type=\"button\" matTooltip=\"T\u1EA3i file JSON\" (click)=\"exportJson()\">\n <sd-icon name=\"download\"></sd-icon>\n <span>JSON</span>\n <small>.json</small>\n </button>\n <button type=\"button\" matTooltip=\"T\u1EA3i file CSV\" (click)=\"exportCsv()\">\n <sd-icon name=\"table_view\"></sd-icon>\n <span>CSV</span>\n <small>.csv</small>\n </button>\n <button type=\"button\" matTooltip=\"T\u1EA3i MD POM skeleton \u2014 cho AI vi\u1EBFt auto-test\" (click)=\"exportMdPom()\">\n <sd-icon name=\"code\"></sd-icon>\n <span>MD POM</span>\n <small>AI test</small>\n </button>\n <button type=\"button\" matTooltip=\"T\u1EA3i MD reference table \u2014 group theo tag sd-*\" (click)=\"exportMdTable()\">\n <sd-icon name=\"view_list\"></sd-icon>\n <span>MD Table</span>\n <small>reference</small>\n </button>\n </div>\n\n @if (e2eGeneratorHost()) {\n @let _e2eExporting = e2eExporting();\n <div class=\"sd-autoid-inspector__export-section\">\n <h4 class=\"sd-autoid-inspector__section-title\">\n <sd-icon class=\"is-info\" name=\"auto_awesome\"></sd-icon>\n T\u1EA1o E2E test\n </h4>\n <div class=\"sd-autoid-inspector__export-grid is-e2e\">\n <button\n type=\"button\"\n matTooltip=\"T\u1EA1o b\u1ED9 test Playwright (.zip)\"\n [disabled]=\"_e2eExporting !== null\"\n (click)=\"exportE2eTest('playwright')\">\n <sd-icon [name]=\"_e2eExporting === 'playwright' ? 'hourglass_empty' : 'play_arrow'\"></sd-icon>\n <span>Playwright</span>\n <small>.zip</small>\n </button>\n <button\n type=\"button\"\n matTooltip=\"T\u1EA1o b\u1ED9 test Robot Framework (.zip)\"\n [disabled]=\"_e2eExporting !== null\"\n (click)=\"openRobotExportContext()\">\n <sd-icon [name]=\"_e2eExporting === 'robot' ? 'hourglass_empty' : 'smart_toy'\"></sd-icon>\n <span>Robot Framework</span>\n <small>.zip</small>\n </button>\n </div>\n\n @if (robotContextOpen()) {\n <div class=\"sd-autoid-inspector__context-backdrop\" role=\"presentation\" (click)=\"closeRobotExportContext()\"></div>\n <section\n class=\"sd-autoid-inspector__context-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"sd-autoid-robot-context-title\">\n <header class=\"sd-autoid-inspector__context-header\">\n <div>\n <h4 id=\"sd-autoid-robot-context-title\">Ng\u1EEF c\u1EA3nh QC cho Robot Framework</h4>\n <small>Requirement, test case, test data</small>\n </div>\n <button type=\"button\" class=\"sd-autoid-inspector__icon-btn\" matTooltip=\"\u0110\u00F3ng\" (click)=\"closeRobotExportContext()\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n </header>\n\n <div class=\"sd-autoid-inspector__context-form\">\n <label>\n <span>Component</span>\n <input\n type=\"text\"\n placeholder=\"SP-Wallet\"\n [ngModel]=\"robotExportContext().component || ''\"\n (ngModelChange)=\"updateRobotExportContext('component', $event)\" />\n </label>\n <label>\n <span>Story / Trace</span>\n <input\n type=\"text\"\n placeholder=\"US-001, AC-01\"\n [ngModel]=\"robotExportContext().storyLinkages || ''\"\n (ngModelChange)=\"updateRobotExportContext('storyLinkages', $event)\" />\n </label>\n <label class=\"is-full\">\n <span>Requirement / AC / BR</span>\n <textarea\n rows=\"4\"\n placeholder=\"D\u00E1n requirement ho\u1EB7c acceptance criteria...\"\n [ngModel]=\"robotExportContext().requirement || ''\"\n (ngModelChange)=\"updateRobotExportContext('requirement', $event)\"></textarea>\n </label>\n <label class=\"is-full\">\n <span>Test case QC \u0111\u00E3 \u0111\u1ECBnh ngh\u0129a</span>\n <textarea\n rows=\"4\"\n placeholder=\"TC-001: ...\"\n [ngModel]=\"robotExportContext().testCases || ''\"\n (ngModelChange)=\"updateRobotExportContext('testCases', $event)\"></textarea>\n </label>\n <label class=\"is-full\">\n <span>Test data</span>\n <textarea\n rows=\"3\"\n placeholder=\"wallet=V\u00ED A, amount=100000...\"\n [ngModel]=\"robotExportContext().testData || ''\"\n (ngModelChange)=\"updateRobotExportContext('testData', $event)\"></textarea>\n </label>\n <label class=\"is-full\">\n <span>Precondition</span>\n <textarea\n rows=\"2\"\n placeholder=\"User \u0111\u00E3 \u0111\u0103ng nh\u1EADp, d\u1EEF li\u1EC7u v\u00ED \u0111\u00E3 t\u1ED3n t\u1EA1i...\"\n [ngModel]=\"robotExportContext().precondition || ''\"\n (ngModelChange)=\"updateRobotExportContext('precondition', $event)\"></textarea>\n </label>\n <label class=\"is-full\">\n <span>Ghi ch\u00FA format QC</span>\n <textarea\n rows=\"3\"\n placeholder=\"Smoke=Y, Auto=Y, \u01B0u ti\u00EAn happy path...\"\n [ngModel]=\"robotExportContext().qcNotes || ''\"\n (ngModelChange)=\"updateRobotExportContext('qcNotes', $event)\"></textarea>\n </label>\n </div>\n\n <footer class=\"sd-autoid-inspector__context-actions\">\n <button type=\"button\" class=\"is-secondary\" [disabled]=\"_e2eExporting !== null\" (click)=\"closeRobotExportContext()\">\n Hu\u1EF7\n </button>\n <button\n type=\"button\"\n class=\"is-primary\"\n [disabled]=\"_e2eExporting !== null || !hasRobotExportContext()\"\n (click)=\"confirmRobotExport()\">\n <sd-icon [name]=\"_e2eExporting === 'robot' ? 'hourglass_empty' : 'download'\"></sd-icon>\n <span>\u0110\u1ED3ng \u00FD xu\u1EA5t</span>\n </button>\n </footer>\n </section>\n }\n\n @if (e2eExportOk(); as targetLabel) {\n <div class=\"sd-autoid-inspector__export-message is-success\">\u0110\u00E3 t\u1EA3i b\u1ED9 test {{ targetLabel }}.</div>\n }\n @if (e2eExportError(); as error) {\n <div class=\"sd-autoid-inspector__export-message is-error\">\n {{ error }}\n </div>\n }\n </div>\n }\n </ng-template>\n}\n", styles: [":host{position:fixed;inset:auto 0 0 auto;z-index:100000;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-size:13px;color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__fab-wrap{position:fixed;right:16px;bottom:16px;z-index:100000}.sd-autoid-inspector__fab-wrap:hover .sd-autoid-inspector__fab-dismiss{opacity:1;transform:scale(1);pointer-events:auto}.sd-autoid-inspector__fab{width:36px;height:36px;border-radius:50%;border:none;background:var(--sd-primary, #005cbb);color:#fff;cursor:pointer;box-shadow:0 3px 10px #00000038;display:inline-flex;align-items:center;justify-content:center;transition:transform .15s ease,background .15s ease,box-shadow .15s ease}.sd-autoid-inspector__fab:hover{background:var(--sd-primary-dark, #00458f);transform:scale(1.08);box-shadow:0 5px 14px #00000047}.sd-autoid-inspector__fab sd-icon{font-size:18px;width:18px;height:18px}.sd-autoid-inspector__fab-dismiss{position:absolute;top:-6px;right:-6px;width:18px;height:18px;border-radius:50%;border:1px solid var(--sd-border, #c4c6d0);background:#fff;color:var(--sd-text-secondary, #44474f);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;opacity:0;transform:scale(.7);pointer-events:none;transition:opacity .12s ease,transform .12s ease,color .12s ease,background .12s ease;box-shadow:0 1px 4px #00000026}.sd-autoid-inspector__fab-dismiss:hover{background:var(--sd-error-light, #ffdad6);color:var(--sd-error-dark, #93000a);border-color:var(--sd-error, #ba1a1a)}.sd-autoid-inspector__fab-dismiss sd-icon{font-size:12px;width:12px;height:12px;line-height:12px}.sd-autoid-inspector__backdrop{position:fixed;inset:0;padding:0;border:none;background:#00000052;z-index:100001;backdrop-filter:blur(2px)}.sd-autoid-inspector__panel{position:fixed;right:20px;bottom:80px;width:min(860px,100vw - 40px);max-height:calc(100vh - 110px);background:#fff;border-radius:12px;box-shadow:0 16px 48px #00000038;display:flex;flex-direction:column;z-index:100002;overflow:hidden;border:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__header{display:flex;align-items:center;gap:8px;padding:8px 10px;border-bottom:1px solid var(--sd-border, #c4c6d0);background:var(--sd-surface-muted, #e7e8ed);flex-shrink:0}.sd-autoid-inspector__segments{display:inline-flex;border:1px solid var(--sd-border, #c4c6d0);border-radius:8px;background:#fff;overflow:hidden}.sd-autoid-inspector__segments button{border:none;background:transparent;padding:5px 12px;cursor:pointer;font-size:12px;font-weight:500;color:var(--sd-text-secondary, #44474f);display:inline-flex;align-items:center;gap:6px;border-right:1px solid var(--sd-border, #c4c6d0);transition:background .12s ease,color .12s ease}.sd-autoid-inspector__segments button:last-child{border-right:none}.sd-autoid-inspector__segments button:hover:not(.is-active){background:var(--sd-surface-muted, #e7e8ed);color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__segments button.is-active{background:var(--sd-primary, #005cbb);color:#fff}.sd-autoid-inspector__badge{background:var(--sd-border, #c4c6d0);color:var(--sd-text, #1a1b1f);border-radius:10px;padding:0 7px;font-size:11px;font-weight:600;line-height:16px}.is-active .sd-autoid-inspector__badge{background:#ffffff40;color:#fff}.sd-autoid-inspector__badge.is-warn{background:var(--sd-error, #ba1a1a);color:#fff}.sd-autoid-inspector__actions{display:inline-flex;gap:4px;margin-left:auto}.sd-autoid-inspector__icon-btn{border:none;background:transparent;cursor:pointer;padding:4px;border-radius:6px;color:var(--sd-text-secondary, #44474f);display:inline-flex;align-items:center;justify-content:center;transition:background .12s ease,color .12s ease}.sd-autoid-inspector__icon-btn:hover{background:var(--sd-surface-muted, #e7e8ed);color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__icon-btn.is-primary{color:var(--sd-primary, #005cbb)}.sd-autoid-inspector__icon-btn.is-primary:hover{background:var(--sd-primary-light, #d7e3ff);color:var(--sd-primary-dark, #00458f)}.sd-autoid-inspector__icon-btn sd-icon{font-size:18px;width:18px;height:18px}.sd-autoid-inspector__close-btn{border:none;cursor:pointer;padding:4px;border-radius:50%;width:28px;height:28px;background:transparent;color:var(--sd-text-secondary, #44474f);display:inline-flex;align-items:center;justify-content:center;transition:background .12s ease,color .12s ease}.sd-autoid-inspector__close-btn:hover{background:var(--sd-error-light, #ffdad6);color:var(--sd-error-dark, #93000a)}.sd-autoid-inspector__close-btn sd-icon{font-size:18px;width:18px;height:18px}.sd-autoid-inspector__body{padding:14px;overflow:auto;flex:1;background:#fff}.sd-autoid-inspector__toast{position:absolute;top:56px;right:14px;background:var(--sd-success, #2e7d32);color:#fff;padding:6px 12px;border-radius:6px;font-size:12px;z-index:2;box-shadow:0 4px 12px #0000002e}.sd-autoid-inspector__audit-toolbar{display:flex;justify-content:flex-end;margin-bottom:12px}.sd-autoid-inspector__toggle{display:inline-flex;align-items:center;gap:8px;border:1px solid var(--sd-border, #c4c6d0);background:#fff;border-radius:999px;padding:5px 12px 5px 10px;cursor:pointer;font-size:12px;font-weight:500;color:var(--sd-text-secondary, #44474f);transition:all .15s ease}.sd-autoid-inspector__toggle:hover{border-color:var(--sd-primary, #005cbb);color:var(--sd-primary, #005cbb)}.sd-autoid-inspector__toggle.is-on{border-color:var(--sd-primary, #005cbb);color:var(--sd-primary, #005cbb);background:var(--sd-primary-light, #d7e3ff)}.sd-autoid-inspector__toggle sd-icon{font-size:16px;width:16px;height:16px}.sd-autoid-inspector__toggle-state{font-size:10px;font-weight:700;padding:1px 7px;border-radius:999px;background:var(--sd-border, #c4c6d0);color:var(--sd-text-secondary, #44474f)}.is-on .sd-autoid-inspector__toggle-state{background:var(--sd-primary, #005cbb);color:#fff}.sd-autoid-inspector__summary{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:16px}.sd-autoid-inspector__stat{background:var(--sd-surface-muted, #e7e8ed);border-radius:10px;padding:12px;text-align:center;border:1px solid transparent}.sd-autoid-inspector__stat.is-info{background:var(--sd-info-light, #d4f7f6);border-color:var(--sd-info, #006a6a)}.sd-autoid-inspector__stat.is-info .sd-autoid-inspector__stat-value{color:var(--sd-info, #006a6a)}.sd-autoid-inspector__stat.is-success{background:var(--sd-success-light, #d8f0d3);border-color:var(--sd-success, #2e7d32)}.sd-autoid-inspector__stat.is-success .sd-autoid-inspector__stat-value{color:var(--sd-success-dark, #1b5e20)}.sd-autoid-inspector__stat.is-warning{background:var(--sd-warning-light, #ffddb0);border-color:var(--sd-warning, #a66300)}.sd-autoid-inspector__stat.is-warning .sd-autoid-inspector__stat-value{color:var(--sd-warning-dark, #7a4d00)}.sd-autoid-inspector__stat.is-error{background:var(--sd-error-light, #ffdad6);border-color:var(--sd-error, #ba1a1a)}.sd-autoid-inspector__stat.is-error .sd-autoid-inspector__stat-value{color:var(--sd-error-dark, #93000a)}.sd-autoid-inspector__stat-value{font-size:22px;font-weight:700;line-height:1;margin-bottom:4px}.sd-autoid-inspector__stat-label{font-size:11px;color:var(--sd-text-secondary, #44474f);text-transform:uppercase;letter-spacing:.4px;font-weight:600}.sd-autoid-inspector__section-title{display:flex;align-items:center;gap:6px;margin:14px 0 8px;font-size:13px;font-weight:600;color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__section-title sd-icon{font-size:18px;width:18px;height:18px}.sd-autoid-inspector__section-title sd-icon.is-error{color:var(--sd-error, #ba1a1a)}.sd-autoid-inspector__section-title sd-icon.is-warning{color:var(--sd-warning, #a66300)}.sd-autoid-inspector__section-title sd-icon.is-info{color:var(--sd-info, #006a6a)}.sd-autoid-inspector__success-card{display:flex;align-items:center;gap:12px;padding:14px 16px;background:var(--sd-success-light, #d8f0d3);border:1px solid var(--sd-success, #2e7d32);border-radius:10px;color:var(--sd-success-dark, #1b5e20)}.sd-autoid-inspector__success-card sd-icon{font-size:28px;width:28px;height:28px;color:var(--sd-success, #2e7d32)}.sd-autoid-inspector__success-card strong{display:block;font-size:13px;margin-bottom:2px}.sd-autoid-inspector__success-card small{font-size:11px;opacity:.85}.sd-autoid-inspector__table-wrap{border:1px solid var(--sd-border, #c4c6d0);border-radius:8px;overflow:auto;max-height:60vh;background:#fff}.sd-autoid-inspector__table{width:100%;border-collapse:separate;border-spacing:0;font-size:12px}.sd-autoid-inspector__table th,.sd-autoid-inspector__table td{padding:8px 10px;text-align:left;vertical-align:middle;border-bottom:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__table thead th{position:sticky;top:0;z-index:1;background:var(--sd-surface-muted, #e7e8ed);font-weight:600;color:var(--sd-text, #1a1b1f);text-transform:none;font-size:11px;letter-spacing:.3px;border-bottom:none;box-shadow:inset 0 -1px 0 var(--sd-border, #c4c6d0),0 2px 4px #0000000a;white-space:nowrap}.sd-autoid-inspector__table thead th.is-num{text-align:right;width:50px}.sd-autoid-inspector__table tbody tr{transition:background .1s ease}.sd-autoid-inspector__table tbody tr:hover{background:var(--sd-primary-light, #d7e3ff)}.sd-autoid-inspector__table tbody tr:last-child td{border-bottom:none}.sd-autoid-inspector__table tbody tr.is-error{background:var(--sd-error-light, #ffdad6)}.sd-autoid-inspector__table tbody tr.is-error:hover{background:var(--sd-error-light, #ffdad6);filter:brightness(.98)}.sd-autoid-inspector__table tbody tr.is-warning{background:var(--sd-warning-light, #ffddb0)}.sd-autoid-inspector__table tbody tr.is-warning:hover{background:var(--sd-warning-light, #ffddb0);filter:brightness(.98)}.sd-autoid-inspector__table td.is-num{text-align:right;color:var(--sd-text-secondary, #44474f);font-variant-numeric:tabular-nums}.sd-autoid-inspector__table code{font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:11px;background:var(--sd-surface-muted, #e7e8ed);padding:2px 6px;border-radius:4px;color:var(--sd-primary-dark, #00458f);border:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__autoid-cell{display:inline-flex;align-items:center;gap:6px}.sd-autoid-inspector__tag-chip{display:inline-block;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:11px;background:var(--sd-info-light, #d4f7f6);color:var(--sd-info, #006a6a);border:1px solid var(--sd-info, #006a6a);padding:1px 8px;border-radius:999px;font-weight:500}.sd-autoid-inspector__value{max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--sd-text-secondary, #44474f);font-style:italic}.sd-autoid-inspector__state-cell{display:flex;flex-wrap:wrap;gap:4px;align-items:center;min-width:0}.sd-autoid-inspector__state-chip{display:inline-block;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:10px;background:var(--sd-surface-muted, #e7e8ed);color:var(--sd-text-secondary, #44474f);border:1px solid var(--sd-border, #c4c6d0);padding:1px 6px;border-radius:999px;font-weight:500;white-space:nowrap}.sd-autoid-inspector__state-chip.is-error{background:var(--sd-error-light, #ffdad6);color:var(--sd-error-dark, #93000a);border-color:var(--sd-error, #ba1a1a)}.sd-autoid-inspector__state-chip.is-warning{background:var(--sd-warning-light, #ffddb0);color:var(--sd-warning-dark, #7a4d00);border-color:var(--sd-warning, #a66300)}.sd-autoid-inspector__state-chip.is-info{background:var(--sd-info-light, #d4f7f6);color:var(--sd-info, #006a6a);border-color:var(--sd-info, #006a6a)}.sd-autoid-inspector__empty{text-align:center;color:var(--sd-text-secondary, #44474f);padding:24px;font-style:italic}.sd-autoid-inspector__filter{display:flex;align-items:center;gap:6px;background:var(--sd-surface-muted, #e7e8ed);border:1px solid var(--sd-border, #c4c6d0);border-radius:8px;padding:6px 10px;margin-bottom:12px;transition:border-color .15s ease}.sd-autoid-inspector__filter:focus-within{border-color:var(--sd-primary, #005cbb);background:#fff}.sd-autoid-inspector__filter input{flex:1;border:none;background:transparent;outline:none;font-size:13px;color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__filter input::placeholder{color:var(--sd-border-strong, #74777f)}.sd-autoid-inspector__filter>sd-icon{font-size:18px;width:18px;height:18px;color:var(--sd-text-secondary, #44474f)}.sd-autoid-inspector__export-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(112px,1fr));gap:8px}.sd-autoid-inspector__export-grid.is-e2e{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}.sd-autoid-inspector__export-grid button{border:1px solid var(--sd-border, #c4c6d0);background:#fff;border-radius:10px;padding:12px 10px;cursor:pointer;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;min-width:0;transition:border-color .15s ease,background .15s ease,transform .12s ease;text-align:center}.sd-autoid-inspector__export-grid button:hover{border-color:var(--sd-primary, #005cbb);background:var(--sd-primary-light, #d7e3ff);transform:translateY(-1px)}.sd-autoid-inspector__export-grid button:disabled{cursor:wait;opacity:.68;transform:none}.sd-autoid-inspector__export-grid button span{font-size:12px;font-weight:600;color:var(--sd-text, #1a1b1f);line-height:1.25}.sd-autoid-inspector__export-grid button small{font-size:10px;color:var(--sd-text-secondary, #44474f);line-height:1.2}.sd-autoid-inspector__export-grid button sd-icon{font-size:22px;width:22px;height:22px;color:var(--sd-primary, #005cbb)}.sd-autoid-inspector__export-section{margin-top:14px;padding-top:12px;border-top:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__context-backdrop{position:fixed;inset:0;z-index:10001;background:#141c2652}.sd-autoid-inspector__context-dialog{position:fixed;z-index:10002;top:50%;left:50%;width:min(720px,100vw - 28px);max-height:min(720px,100vh - 28px);transform:translate(-50%,-50%);display:flex;flex-direction:column;border:1px solid var(--sd-border, #c4c6d0);border-radius:8px;background:#fff;box-shadow:0 18px 48px #0f172a38;overflow:hidden}.sd-autoid-inspector__context-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:14px 16px;border-bottom:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__context-header h4{margin:0;font-size:15px;font-weight:700;line-height:1.3;color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__context-header small{display:block;margin-top:2px;font-size:11px;color:var(--sd-text-secondary, #44474f);line-height:1.3}.sd-autoid-inspector__context-form{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;padding:14px 16px;overflow:auto}.sd-autoid-inspector__context-form label{display:flex;flex-direction:column;gap:6px;min-width:0}.sd-autoid-inspector__context-form label.is-full{grid-column:1/-1}.sd-autoid-inspector__context-form span{font-size:12px;font-weight:600;color:var(--sd-text, #1a1b1f);line-height:1.25}.sd-autoid-inspector__context-form input,.sd-autoid-inspector__context-form textarea{width:100%;min-width:0;border:1px solid var(--sd-border, #c4c6d0);border-radius:6px;padding:8px 10px;color:var(--sd-text, #1a1b1f);font:inherit;font-size:12px;line-height:1.4;outline:none;resize:vertical}.sd-autoid-inspector__context-form input:focus,.sd-autoid-inspector__context-form textarea:focus{border-color:var(--sd-primary, #005cbb);box-shadow:0 0 0 2px color-mix(in srgb,var(--sd-primary, #005cbb) 18%,transparent)}.sd-autoid-inspector__context-actions{display:flex;justify-content:flex-end;gap:8px;padding:12px 16px;border-top:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__context-actions button{min-height:34px;border-radius:6px;padding:0 12px;border:1px solid var(--sd-border, #c4c6d0);background:#fff;color:var(--sd-text, #1a1b1f);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:6px;font-size:12px;font-weight:600}.sd-autoid-inspector__context-actions button.is-primary{border-color:var(--sd-primary, #005cbb);background:var(--sd-primary, #005cbb);color:#fff}.sd-autoid-inspector__context-actions button:disabled{cursor:not-allowed;opacity:.62}.sd-autoid-inspector__context-actions button sd-icon{font-size:17px;width:17px;height:17px}.sd-autoid-inspector__export-message{margin-top:10px;border-radius:8px;padding:8px 10px;font-size:12px;line-height:1.35}.sd-autoid-inspector__export-message.is-success{background:var(--sd-success-light, #d8f0d3);color:var(--sd-success-dark, #1b5e20);border:1px solid var(--sd-success, #2e7d32)}.sd-autoid-inspector__export-message.is-error{background:var(--sd-error-light, #ffdad6);color:var(--sd-error-dark, #93000a);border:1px solid var(--sd-error, #ba1a1a)}@media(max-width:560px){.sd-autoid-inspector__context-form{grid-template-columns:1fr}.sd-autoid-inspector__context-actions{flex-direction:column-reverse}.sd-autoid-inspector__context-actions button{width:100%}}\n"] }]
|
|
968
|
+
args: [{ selector: 'sd-autoid-inspector', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [SdIcon, CommonModule, FormsModule, MatTooltipModule], template: "@let _enabled = enabled();\n@let _open = open();\n@if (_enabled && !dismissed()) {\n <div class=\"sd-autoid-inspector__fab-wrap\">\n <button\n type=\"button\"\n class=\"sd-autoid-inspector__fab\"\n data-autoid=\"sd-autoid-inspector-fab\"\n [attr.data-opened]=\"dataOpened()\"\n [matTooltip]=\"_open ? '\u0110\u00F3ng AutoId Inspector' : 'M\u1EDF AutoId Inspector'\"\n matTooltipPosition=\"left\"\n (click)=\"togglePanel()\">\n <sd-icon [name]=\"_open ? 'close' : 'tag'\"></sd-icon>\n </button>\n <button\n type=\"button\"\n class=\"sd-autoid-inspector__fab-dismiss\"\n matTooltip=\"\u1EA8n t\u1EA1m \u2014 reload trang \u0111\u1EC3 hi\u1EC7n l\u1EA1i\"\n matTooltipPosition=\"left\"\n aria-label=\"\u1EA8n t\u1EA1m FAB\"\n (click)=\"dismissFab($event)\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n </div>\n}\n\n@if (_enabled && _open) {\n @let _segment = segment();\n <button type=\"button\" class=\"sd-autoid-inspector__backdrop\" aria-label=\"\u0110\u00F3ng AutoId Inspector\" (click)=\"closePanel()\"></button>\n <section\n class=\"sd-autoid-inspector__panel\"\n role=\"dialog\"\n aria-label=\"AutoId Inspector\"\n data-autoid=\"sd-autoid-inspector-panel\"\n [attr.data-segment]=\"dataSegment()\"\n [attr.data-highlight-on]=\"dataHighlightOn()\"\n [attr.data-element-count]=\"dataElementCount()\"\n [attr.data-missing-count]=\"dataMissingCount()\"\n [attr.data-duplicate-count]=\"dataDuplicateCount()\">\n <header class=\"sd-autoid-inspector__header\">\n <div class=\"sd-autoid-inspector__segments\">\n <button type=\"button\" [class.is-active]=\"_segment === 'audit'\" (click)=\"setSegment('audit')\">\n Audit\n @if (audit(); as a) {\n <span class=\"sd-autoid-inspector__badge\" [class.is-warn]=\"a.missingCount + a.duplicateCount > 0\">\n {{ a.missingCount + a.duplicateCount }}\n </span>\n }\n </button>\n <button type=\"button\" [class.is-active]=\"_segment === 'elements'\" (click)=\"setSegment('elements')\">\n Elements\n <span class=\"sd-autoid-inspector__badge\">{{ elements().length }}</span>\n </button>\n <button type=\"button\" [class.is-active]=\"_segment === 'export'\" (click)=\"setSegment('export')\">Export</button>\n </div>\n <div class=\"sd-autoid-inspector__actions\">\n <button type=\"button\" class=\"sd-autoid-inspector__icon-btn\" matTooltip=\"Qu\u00E9t l\u1EA1i\" (click)=\"refresh()\">\n <sd-icon name=\"refresh\"></sd-icon>\n </button>\n <button type=\"button\" class=\"sd-autoid-inspector__close-btn\" matTooltip=\"\u0110\u00F3ng\" aria-label=\"\u0110\u00F3ng panel\" (click)=\"closePanel()\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n </div>\n </header>\n\n @if (copyOk()) {\n <div class=\"sd-autoid-inspector__toast\">\u0110\u00E3 copy \u2713</div>\n }\n\n <div class=\"sd-autoid-inspector__body\">\n @switch (_segment) {\n @case ('audit') {\n <ng-container *ngTemplateOutlet=\"auditTpl\"></ng-container>\n }\n @case ('elements') {\n <ng-container *ngTemplateOutlet=\"elementsTpl\"></ng-container>\n }\n @case ('export') {\n <ng-container *ngTemplateOutlet=\"exportTpl\"></ng-container>\n }\n }\n </div>\n </section>\n\n <ng-template #auditTpl>\n @if (audit(); as a) {\n @let _highlightOn = highlightOn();\n <div class=\"sd-autoid-inspector__audit-toolbar\">\n <button type=\"button\" class=\"sd-autoid-inspector__toggle\" [class.is-on]=\"_highlightOn\" (click)=\"toggleHighlight()\">\n <sd-icon [name]=\"_highlightOn ? 'visibility' : 'visibility_off'\"></sd-icon>\n <span>Highlight DOM</span>\n <span class=\"sd-autoid-inspector__toggle-state\">{{ _highlightOn ? 'ON' : 'OFF' }}</span>\n </button>\n </div>\n <div class=\"sd-autoid-inspector__summary\">\n <div class=\"sd-autoid-inspector__stat is-info\">\n <div class=\"sd-autoid-inspector__stat-value\">{{ a.total }}</div>\n <div class=\"sd-autoid-inspector__stat-label\">T\u1ED5ng autoid</div>\n </div>\n <div class=\"sd-autoid-inspector__stat\" [class.is-error]=\"a.duplicateCount > 0\" [class.is-success]=\"a.duplicateCount === 0\">\n <div class=\"sd-autoid-inspector__stat-value\">{{ a.duplicateCount }}</div>\n <div class=\"sd-autoid-inspector__stat-label\">Tr\u00F9ng</div>\n </div>\n <div class=\"sd-autoid-inspector__stat\" [class.is-warning]=\"a.missingCount > 0\" [class.is-success]=\"a.missingCount === 0\">\n <div class=\"sd-autoid-inspector__stat-value\">{{ a.missingCount }}</div>\n <div class=\"sd-autoid-inspector__stat-label\">Thi\u1EBFu</div>\n </div>\n </div>\n\n @if (a.duplicateCount > 0) {\n <h4 class=\"sd-autoid-inspector__section-title\">\n <sd-icon class=\"is-error\" name=\"error\"></sd-icon>\n Autoid b\u1ECB tr\u00F9ng\n </h4>\n <div class=\"sd-autoid-inspector__table-wrap\">\n <table class=\"sd-autoid-inspector__table\">\n <thead>\n <tr>\n <th>Autoid</th>\n <th>S\u1ED1 l\u1EA7n</th>\n </tr>\n </thead>\n <tbody>\n @for (entry of a.duplicates | keyvalue; track entry.key) {\n <tr class=\"is-error\">\n <td>\n <code>{{ entry.key }}</code>\n </td>\n <td>{{ entry.value }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n @if (a.missingCount > 0) {\n <h4 class=\"sd-autoid-inspector__section-title\">\n <sd-icon class=\"is-warning\" name=\"warning_amber\"></sd-icon>\n Element thi\u1EBFu autoid\n </h4>\n <div class=\"sd-autoid-inspector__table-wrap\">\n <table class=\"sd-autoid-inspector__table\">\n <thead>\n <tr>\n <th>Tag</th>\n <th>Name hint</th>\n <th>Selector</th>\n </tr>\n </thead>\n <tbody>\n @for (m of a.missing; track $index) {\n <tr class=\"is-warning\">\n <td>\n <code>{{ m.tag }}</code>\n </td>\n <td>{{ m.nameHint }}</td>\n <td>\n <code>{{ m.selector }}</code>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n @if (a.duplicateCount === 0 && a.missingCount === 0) {\n <div class=\"sd-autoid-inspector__success-card\">\n <sd-icon name=\"check_circle\"></sd-icon>\n <div>\n <strong>Kh\u00F4ng c\u00F3 element thi\u1EBFu ho\u1EB7c tr\u00F9ng autoid.</strong>\n <small>Trang \u0111\u00E3 \u0111\u1EA1t chu\u1EA9n convention autoid.</small>\n </div>\n </div>\n }\n }\n </ng-template>\n\n <ng-template #elementsTpl>\n @let _filter = filter();\n <div class=\"sd-autoid-inspector__filter\">\n <sd-icon name=\"search\"></sd-icon>\n <input type=\"text\" placeholder=\"L\u1ECDc theo autoid / name / tag\" [ngModel]=\"_filter\" (ngModelChange)=\"filter.set($event)\" />\n @if (_filter) {\n <button type=\"button\" class=\"sd-autoid-inspector__icon-btn\" matTooltip=\"Xo\u00E1 filter\" (click)=\"filter.set('')\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n }\n </div>\n\n <!-- Top-level elements (not inside any sd-table) -->\n <h4 class=\"sd-autoid-inspector__section-title\">\n Top-level elements\n <span class=\"sd-autoid-inspector__badge\">{{ topLevelElements().length }}</span>\n </h4>\n <div class=\"sd-autoid-inspector__table-wrap\">\n <table class=\"sd-autoid-inspector__table\">\n <thead>\n <tr>\n <th class=\"is-num\">STT</th>\n <th>Name</th>\n <th>Autoid</th>\n <th>Tag</th>\n <th>State</th>\n <th>Value</th>\n </tr>\n </thead>\n <tbody>\n @for (el of topLevelElements(); track el.autoid + $index) {\n <tr [class.is-error]=\"el.duplicate\">\n <td class=\"is-num\">{{ el.stt }}</td>\n <td>{{ el.name || '\u2014' }}</td>\n <td>\n <div class=\"sd-autoid-inspector__autoid-cell\">\n <code>{{ el.autoid }}</code>\n <button\n type=\"button\"\n class=\"sd-autoid-inspector__icon-btn is-primary\"\n matTooltip=\"Copy xpath\"\n (click)=\"copyXpath(el.autoid)\">\n <sd-icon name=\"content_copy\"></sd-icon>\n </button>\n </div>\n </td>\n <td>\n <span class=\"sd-autoid-inspector__tag-chip\">{{ el.tag }}</span>\n </td>\n <td class=\"sd-autoid-inspector__state-cell\">\n @if (el.state.disabled !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-error]=\"el.state.disabled === 'true'\">\n disabled={{ el.state.disabled }}\n </span>\n }\n @if (el.state.loading !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-warning]=\"el.state.loading === 'true'\">\n loading={{ el.state.loading }}\n </span>\n }\n @if (el.state.empty !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-info]=\"el.state.empty === 'true'\">\n empty={{ el.state.empty }}\n </span>\n }\n @if (el.state.invalid !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-error]=\"el.state.invalid === 'true'\">\n invalid={{ el.state.invalid }}\n </span>\n }\n @if (el.state.opened !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-info]=\"el.state.opened === 'true'\">\n opened={{ el.state.opened }}\n </span>\n }\n @if (el.state.count !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> count={{ el.state.count }} </span>\n }\n @if (el.state.required !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-warning]=\"el.state.required === 'true'\">\n required={{ el.state.required }}\n </span>\n }\n @if (el.state.maxlength !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> maxlength={{ el.state.maxlength }} </span>\n }\n @if (el.state.minlength !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> minlength={{ el.state.minlength }} </span>\n }\n @if (el.state.pattern !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> pattern={{ el.state.pattern }} </span>\n }\n @if (el.state.errorMessage !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-error\"> error: {{ el.state.errorMessage }} </span>\n }\n </td>\n <td class=\"sd-autoid-inspector__value\" [matTooltip]=\"el.state.dataValue || el.text || ''\">\n {{ el.state.dataValue || el.text || '\u2014' }}\n </td>\n </tr>\n } @empty {\n <tr>\n <td colspan=\"6\" class=\"sd-autoid-inspector__empty\">Kh\u00F4ng c\u00F3 k\u1EBFt qu\u1EA3.</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <!-- One section per sd-table group -->\n @for (group of tableGroups(); track group.scope) {\n <h4 class=\"sd-autoid-inspector__section-title\">\n <sd-icon class=\"is-info\" name=\"table_chart\"></sd-icon>\n Inside <code>{{ group.scope }}</code>\n <span class=\"sd-autoid-inspector__badge\">{{ group.items.length }}</span>\n </h4>\n <div class=\"sd-autoid-inspector__table-wrap\">\n <table class=\"sd-autoid-inspector__table\">\n <thead>\n <tr>\n <th class=\"is-num\">STT</th>\n <th>Name</th>\n <th>Autoid</th>\n <th>Tag</th>\n <th>State</th>\n <th>Value</th>\n </tr>\n </thead>\n <tbody>\n @for (el of group.items; track el.autoid + $index) {\n <tr [class.is-error]=\"el.duplicate\">\n <td class=\"is-num\">{{ el.stt }}</td>\n <td>{{ el.name || '\u2014' }}</td>\n <td>\n <div class=\"sd-autoid-inspector__autoid-cell\">\n <code>{{ el.autoid }}</code>\n <button\n type=\"button\"\n class=\"sd-autoid-inspector__icon-btn is-primary\"\n matTooltip=\"Copy xpath\"\n (click)=\"copyXpath(el.autoid)\">\n <sd-icon name=\"content_copy\"></sd-icon>\n </button>\n </div>\n </td>\n <td>\n <span class=\"sd-autoid-inspector__tag-chip\">{{ el.tag }}</span>\n </td>\n <td class=\"sd-autoid-inspector__state-cell\">\n @if (el.state.disabled !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-error]=\"el.state.disabled === 'true'\">\n disabled={{ el.state.disabled }}\n </span>\n }\n @if (el.state.loading !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-warning]=\"el.state.loading === 'true'\">\n loading={{ el.state.loading }}\n </span>\n }\n @if (el.state.empty !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-info]=\"el.state.empty === 'true'\">\n empty={{ el.state.empty }}\n </span>\n }\n @if (el.state.invalid !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-error]=\"el.state.invalid === 'true'\">\n invalid={{ el.state.invalid }}\n </span>\n }\n @if (el.state.opened !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-info]=\"el.state.opened === 'true'\">\n opened={{ el.state.opened }}\n </span>\n }\n @if (el.state.count !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> count={{ el.state.count }} </span>\n }\n @if (el.state.required !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip\" [class.is-warning]=\"el.state.required === 'true'\">\n required={{ el.state.required }}\n </span>\n }\n @if (el.state.maxlength !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> maxlength={{ el.state.maxlength }} </span>\n }\n @if (el.state.minlength !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> minlength={{ el.state.minlength }} </span>\n }\n @if (el.state.pattern !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-info\"> pattern={{ el.state.pattern }} </span>\n }\n @if (el.state.errorMessage !== undefined) {\n <span class=\"sd-autoid-inspector__state-chip is-error\"> error: {{ el.state.errorMessage }} </span>\n }\n </td>\n <td class=\"sd-autoid-inspector__value\" [matTooltip]=\"el.state.dataValue || el.text || ''\">\n {{ el.state.dataValue || el.text || '\u2014' }}\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </ng-template>\n\n <ng-template #exportTpl>\n <div class=\"sd-autoid-inspector__export-grid\">\n <button type=\"button\" matTooltip=\"Copy JSON v\u00E0o clipboard\" (click)=\"copyJson()\">\n <sd-icon name=\"content_copy\"></sd-icon>\n <span>Copy JSON</span>\n <small>clipboard</small>\n </button>\n <button type=\"button\" matTooltip=\"T\u1EA3i file JSON\" (click)=\"exportJson()\">\n <sd-icon name=\"download\"></sd-icon>\n <span>JSON</span>\n <small>.json</small>\n </button>\n <button type=\"button\" matTooltip=\"T\u1EA3i file CSV\" (click)=\"exportCsv()\">\n <sd-icon name=\"table_view\"></sd-icon>\n <span>CSV</span>\n <small>.csv</small>\n </button>\n <button type=\"button\" matTooltip=\"T\u1EA3i MD POM skeleton \u2014 cho AI vi\u1EBFt auto-test\" (click)=\"exportMdPom()\">\n <sd-icon name=\"code\"></sd-icon>\n <span>MD POM</span>\n <small>AI test</small>\n </button>\n <button type=\"button\" matTooltip=\"T\u1EA3i MD reference table \u2014 group theo tag sd-*\" (click)=\"exportMdTable()\">\n <sd-icon name=\"view_list\"></sd-icon>\n <span>MD Table</span>\n <small>reference</small>\n </button>\n </div>\n\n @if (e2eGeneratorHost()) {\n @let _e2eExporting = e2eExporting();\n <div class=\"sd-autoid-inspector__export-section\">\n <h4 class=\"sd-autoid-inspector__section-title\">\n <sd-icon class=\"is-info\" name=\"auto_awesome\"></sd-icon>\n T\u1EA1o E2E test\n </h4>\n <div class=\"sd-autoid-inspector__export-grid is-e2e\">\n <button\n type=\"button\"\n matTooltip=\"T\u1EA1o b\u1ED9 test Playwright (.zip)\"\n [disabled]=\"_e2eExporting !== null\"\n (click)=\"exportE2eTest('playwright')\">\n <sd-icon [name]=\"_e2eExporting === 'playwright' ? 'hourglass_empty' : 'play_arrow'\"></sd-icon>\n <span>Playwright</span>\n <small>.zip</small>\n </button>\n <button\n type=\"button\"\n matTooltip=\"T\u1EA1o b\u1ED9 test Robot Framework (.zip)\"\n [disabled]=\"_e2eExporting !== null\"\n (click)=\"openRobotExportContext()\">\n <sd-icon [name]=\"_e2eExporting === 'robot' ? 'hourglass_empty' : 'smart_toy'\"></sd-icon>\n <span>Robot Framework</span>\n <small>.zip</small>\n </button>\n </div>\n\n @if (robotContextOpen()) {\n <div class=\"sd-autoid-inspector__context-backdrop\" role=\"presentation\" (click)=\"closeRobotExportContext()\"></div>\n <section\n class=\"sd-autoid-inspector__context-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"sd-autoid-robot-context-title\">\n <header class=\"sd-autoid-inspector__context-header\">\n <div>\n <h4 id=\"sd-autoid-robot-context-title\">Ng\u1EEF c\u1EA3nh QC cho Robot Framework</h4>\n <small>Requirement, test case, test data</small>\n </div>\n <button type=\"button\" class=\"sd-autoid-inspector__icon-btn\" matTooltip=\"\u0110\u00F3ng\" (click)=\"closeRobotExportContext()\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n </header>\n\n <div class=\"sd-autoid-inspector__context-form\">\n <label>\n <span>Component</span>\n <input\n type=\"text\"\n placeholder=\"SP-Wallet\"\n [ngModel]=\"robotExportContext().component || ''\"\n (ngModelChange)=\"updateRobotExportContext('component', $event)\" />\n </label>\n <label>\n <span>Story / Trace</span>\n <input\n type=\"text\"\n placeholder=\"US-001, AC-01\"\n [ngModel]=\"robotExportContext().storyLinkages || ''\"\n (ngModelChange)=\"updateRobotExportContext('storyLinkages', $event)\" />\n </label>\n <label class=\"is-full\">\n <span>Requirement / AC / BR</span>\n <textarea\n rows=\"4\"\n placeholder=\"D\u00E1n requirement ho\u1EB7c acceptance criteria...\"\n [ngModel]=\"robotExportContext().requirement || ''\"\n (ngModelChange)=\"updateRobotExportContext('requirement', $event)\"></textarea>\n </label>\n <label class=\"is-full\">\n <span>Test case QC \u0111\u00E3 \u0111\u1ECBnh ngh\u0129a</span>\n <textarea\n rows=\"4\"\n placeholder=\"TC-001: ...\"\n [ngModel]=\"robotExportContext().testCases || ''\"\n (ngModelChange)=\"updateRobotExportContext('testCases', $event)\"></textarea>\n </label>\n <label class=\"is-full\">\n <span>Test data</span>\n <textarea\n rows=\"3\"\n placeholder=\"wallet=V\u00ED A, amount=100000...\"\n [ngModel]=\"robotExportContext().testData || ''\"\n (ngModelChange)=\"updateRobotExportContext('testData', $event)\"></textarea>\n </label>\n <label class=\"is-full\">\n <span>Precondition</span>\n <textarea\n rows=\"2\"\n placeholder=\"User \u0111\u00E3 \u0111\u0103ng nh\u1EADp, d\u1EEF li\u1EC7u v\u00ED \u0111\u00E3 t\u1ED3n t\u1EA1i...\"\n [ngModel]=\"robotExportContext().precondition || ''\"\n (ngModelChange)=\"updateRobotExportContext('precondition', $event)\"></textarea>\n </label>\n <label class=\"is-full\">\n <span>Ghi ch\u00FA format QC</span>\n <textarea\n rows=\"3\"\n placeholder=\"Smoke=Y, Auto=Y, \u01B0u ti\u00EAn happy path...\"\n [ngModel]=\"robotExportContext().qcNotes || ''\"\n (ngModelChange)=\"updateRobotExportContext('qcNotes', $event)\"></textarea>\n </label>\n </div>\n\n <footer class=\"sd-autoid-inspector__context-actions\">\n <button type=\"button\" class=\"is-secondary\" [disabled]=\"_e2eExporting !== null\" (click)=\"closeRobotExportContext()\">\n Hu\u1EF7\n </button>\n <button\n type=\"button\"\n class=\"is-primary\"\n [disabled]=\"_e2eExporting !== null || !hasRobotExportContext()\"\n (click)=\"confirmRobotExport()\">\n <sd-icon [name]=\"_e2eExporting === 'robot' ? 'hourglass_empty' : 'download'\"></sd-icon>\n <span>\u0110\u1ED3ng \u00FD xu\u1EA5t</span>\n </button>\n </footer>\n </section>\n }\n\n @if (e2eExportOk(); as targetLabel) {\n <div class=\"sd-autoid-inspector__export-message is-success\">\u0110\u00E3 t\u1EA3i b\u1ED9 test {{ targetLabel }}.</div>\n }\n @if (e2eExportError(); as error) {\n <div class=\"sd-autoid-inspector__export-message is-error\">\n {{ error }}\n </div>\n }\n </div>\n }\n </ng-template>\n}\n", styles: [":host{position:fixed;inset:auto 0 0 auto;z-index:100000;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-size:13px;color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__fab-wrap{position:fixed;right:16px;bottom:16px;z-index:100000}.sd-autoid-inspector__fab-wrap:hover .sd-autoid-inspector__fab-dismiss{opacity:1;transform:scale(1);pointer-events:auto}.sd-autoid-inspector__fab{width:36px;height:36px;border-radius:50%;border:none;background:var(--sd-primary, #005cbb);color:#fff;cursor:pointer;box-shadow:0 3px 10px #00000038;display:inline-flex;align-items:center;justify-content:center;transition:transform .15s ease,background .15s ease,box-shadow .15s ease}.sd-autoid-inspector__fab:hover{background:var(--sd-primary-dark, #00458f);transform:scale(1.08);box-shadow:0 5px 14px #00000047}.sd-autoid-inspector__fab sd-icon{font-size:18px;width:18px;height:18px}.sd-autoid-inspector__fab-dismiss{position:absolute;top:-6px;right:-6px;width:18px;height:18px;border-radius:50%;border:1px solid var(--sd-border, #c4c6d0);background:#fff;color:var(--sd-text-secondary, #44474f);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;opacity:0;transform:scale(.7);pointer-events:none;transition:opacity .12s ease,transform .12s ease,color .12s ease,background .12s ease;box-shadow:0 1px 4px #00000026}.sd-autoid-inspector__fab-dismiss:hover{background:var(--sd-error-light, #ffdad6);color:var(--sd-error-dark, #93000a);border-color:var(--sd-error, #ba1a1a)}.sd-autoid-inspector__fab-dismiss sd-icon{font-size:12px;width:12px;height:12px;line-height:12px}.sd-autoid-inspector__backdrop{position:fixed;inset:0;padding:0;border:none;background:#00000052;z-index:100001;backdrop-filter:blur(2px)}.sd-autoid-inspector__panel{position:fixed;right:20px;bottom:80px;width:min(860px,100vw - 40px);max-height:calc(100vh - 110px);background:#fff;border-radius:12px;box-shadow:0 16px 48px #00000038;display:flex;flex-direction:column;z-index:100002;overflow:hidden;border:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__header{display:flex;align-items:center;gap:8px;padding:8px 10px;border-bottom:1px solid var(--sd-border, #c4c6d0);background:var(--sd-surface-muted, #e7e8ed);flex-shrink:0}.sd-autoid-inspector__segments{display:inline-flex;border:1px solid var(--sd-border, #c4c6d0);border-radius:8px;background:#fff;overflow:hidden}.sd-autoid-inspector__segments button{border:none;background:transparent;padding:5px 12px;cursor:pointer;font-size:12px;font-weight:500;color:var(--sd-text-secondary, #44474f);display:inline-flex;align-items:center;gap:6px;border-right:1px solid var(--sd-border, #c4c6d0);transition:background .12s ease,color .12s ease}.sd-autoid-inspector__segments button:last-child{border-right:none}.sd-autoid-inspector__segments button:hover:not(.is-active){background:var(--sd-surface-muted, #e7e8ed);color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__segments button.is-active{background:var(--sd-primary, #005cbb);color:#fff}.sd-autoid-inspector__badge{background:var(--sd-border, #c4c6d0);color:var(--sd-text, #1a1b1f);border-radius:10px;padding:0 7px;font-size:11px;font-weight:600;line-height:16px}.is-active .sd-autoid-inspector__badge{background:#ffffff40;color:#fff}.sd-autoid-inspector__badge.is-warn{background:var(--sd-error, #ba1a1a);color:#fff}.sd-autoid-inspector__actions{display:inline-flex;gap:4px;margin-left:auto}.sd-autoid-inspector__icon-btn{border:none;background:transparent;cursor:pointer;padding:4px;border-radius:6px;color:var(--sd-text-secondary, #44474f);display:inline-flex;align-items:center;justify-content:center;transition:background .12s ease,color .12s ease}.sd-autoid-inspector__icon-btn:hover{background:var(--sd-surface-muted, #e7e8ed);color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__icon-btn.is-primary{color:var(--sd-primary, #005cbb)}.sd-autoid-inspector__icon-btn.is-primary:hover{background:var(--sd-primary-light, #d7e3ff);color:var(--sd-primary-dark, #00458f)}.sd-autoid-inspector__icon-btn sd-icon{font-size:18px;width:18px;height:18px}.sd-autoid-inspector__close-btn{border:none;cursor:pointer;padding:4px;border-radius:50%;width:28px;height:28px;background:transparent;color:var(--sd-text-secondary, #44474f);display:inline-flex;align-items:center;justify-content:center;transition:background .12s ease,color .12s ease}.sd-autoid-inspector__close-btn:hover{background:var(--sd-error-light, #ffdad6);color:var(--sd-error-dark, #93000a)}.sd-autoid-inspector__close-btn sd-icon{font-size:18px;width:18px;height:18px}.sd-autoid-inspector__body{padding:14px;overflow:auto;flex:1;background:#fff}.sd-autoid-inspector__toast{position:absolute;top:56px;right:14px;background:var(--sd-success, #2e7d32);color:#fff;padding:6px 12px;border-radius:6px;font-size:12px;z-index:2;box-shadow:0 4px 12px #0000002e}.sd-autoid-inspector__audit-toolbar{display:flex;justify-content:flex-end;margin-bottom:12px}.sd-autoid-inspector__toggle{display:inline-flex;align-items:center;gap:8px;border:1px solid var(--sd-border, #c4c6d0);background:#fff;border-radius:999px;padding:5px 12px 5px 10px;cursor:pointer;font-size:12px;font-weight:500;color:var(--sd-text-secondary, #44474f);transition:all .15s ease}.sd-autoid-inspector__toggle:hover{border-color:var(--sd-primary, #005cbb);color:var(--sd-primary, #005cbb)}.sd-autoid-inspector__toggle.is-on{border-color:var(--sd-primary, #005cbb);color:var(--sd-primary, #005cbb);background:var(--sd-primary-light, #d7e3ff)}.sd-autoid-inspector__toggle sd-icon{font-size:16px;width:16px;height:16px}.sd-autoid-inspector__toggle-state{font-size:10px;font-weight:700;padding:1px 7px;border-radius:999px;background:var(--sd-border, #c4c6d0);color:var(--sd-text-secondary, #44474f)}.is-on .sd-autoid-inspector__toggle-state{background:var(--sd-primary, #005cbb);color:#fff}.sd-autoid-inspector__summary{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:16px}.sd-autoid-inspector__stat{background:var(--sd-surface-muted, #e7e8ed);border-radius:10px;padding:12px;text-align:center;border:1px solid transparent}.sd-autoid-inspector__stat.is-info{background:var(--sd-info-light, #d4f7f6);border-color:var(--sd-info, #006a6a)}.sd-autoid-inspector__stat.is-info .sd-autoid-inspector__stat-value{color:var(--sd-info, #006a6a)}.sd-autoid-inspector__stat.is-success{background:var(--sd-success-light, #d8f0d3);border-color:var(--sd-success, #2e7d32)}.sd-autoid-inspector__stat.is-success .sd-autoid-inspector__stat-value{color:var(--sd-success-dark, #1b5e20)}.sd-autoid-inspector__stat.is-warning{background:var(--sd-warning-light, #ffddb0);border-color:var(--sd-warning, #a66300)}.sd-autoid-inspector__stat.is-warning .sd-autoid-inspector__stat-value{color:var(--sd-warning-dark, #7a4d00)}.sd-autoid-inspector__stat.is-error{background:var(--sd-error-light, #ffdad6);border-color:var(--sd-error, #ba1a1a)}.sd-autoid-inspector__stat.is-error .sd-autoid-inspector__stat-value{color:var(--sd-error-dark, #93000a)}.sd-autoid-inspector__stat-value{font-size:22px;font-weight:700;line-height:1;margin-bottom:4px}.sd-autoid-inspector__stat-label{font-size:11px;color:var(--sd-text-secondary, #44474f);text-transform:uppercase;letter-spacing:.4px;font-weight:600}.sd-autoid-inspector__section-title{display:flex;align-items:center;gap:6px;margin:14px 0 8px;font-size:13px;font-weight:600;color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__section-title sd-icon{font-size:18px;width:18px;height:18px}.sd-autoid-inspector__section-title sd-icon.is-error{color:var(--sd-error, #ba1a1a)}.sd-autoid-inspector__section-title sd-icon.is-warning{color:var(--sd-warning, #a66300)}.sd-autoid-inspector__section-title sd-icon.is-info{color:var(--sd-info, #006a6a)}.sd-autoid-inspector__success-card{display:flex;align-items:center;gap:12px;padding:14px 16px;background:var(--sd-success-light, #d8f0d3);border:1px solid var(--sd-success, #2e7d32);border-radius:10px;color:var(--sd-success-dark, #1b5e20)}.sd-autoid-inspector__success-card sd-icon{font-size:28px;width:28px;height:28px;color:var(--sd-success, #2e7d32)}.sd-autoid-inspector__success-card strong{display:block;font-size:13px;margin-bottom:2px}.sd-autoid-inspector__success-card small{font-size:11px;opacity:.85}.sd-autoid-inspector__table-wrap{border:1px solid var(--sd-border, #c4c6d0);border-radius:8px;overflow:auto;max-height:60vh;background:#fff}.sd-autoid-inspector__table{width:100%;border-collapse:separate;border-spacing:0;font-size:12px}.sd-autoid-inspector__table th,.sd-autoid-inspector__table td{padding:8px 10px;text-align:left;vertical-align:middle;border-bottom:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__table thead th{position:sticky;top:0;z-index:1;background:var(--sd-surface-muted, #e7e8ed);font-weight:600;color:var(--sd-text, #1a1b1f);text-transform:none;font-size:11px;letter-spacing:.3px;border-bottom:none;box-shadow:inset 0 -1px 0 var(--sd-border, #c4c6d0),0 2px 4px #0000000a;white-space:nowrap}.sd-autoid-inspector__table thead th.is-num{text-align:right;width:50px}.sd-autoid-inspector__table tbody tr{transition:background .1s ease}.sd-autoid-inspector__table tbody tr:hover{background:var(--sd-primary-light, #d7e3ff)}.sd-autoid-inspector__table tbody tr:last-child td{border-bottom:none}.sd-autoid-inspector__table tbody tr.is-error{background:var(--sd-error-light, #ffdad6)}.sd-autoid-inspector__table tbody tr.is-error:hover{background:var(--sd-error-light, #ffdad6);filter:brightness(.98)}.sd-autoid-inspector__table tbody tr.is-warning{background:var(--sd-warning-light, #ffddb0)}.sd-autoid-inspector__table tbody tr.is-warning:hover{background:var(--sd-warning-light, #ffddb0);filter:brightness(.98)}.sd-autoid-inspector__table td.is-num{text-align:right;color:var(--sd-text-secondary, #44474f);font-variant-numeric:tabular-nums}.sd-autoid-inspector__table code{font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:11px;background:var(--sd-surface-muted, #e7e8ed);padding:2px 6px;border-radius:4px;color:var(--sd-primary-dark, #00458f);border:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__autoid-cell{display:inline-flex;align-items:center;gap:6px}.sd-autoid-inspector__tag-chip{display:inline-block;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:11px;background:var(--sd-info-light, #d4f7f6);color:var(--sd-info, #006a6a);border:1px solid var(--sd-info, #006a6a);padding:1px 8px;border-radius:999px;font-weight:500}.sd-autoid-inspector__value{max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--sd-text-secondary, #44474f);font-style:italic}.sd-autoid-inspector__state-cell{display:flex;flex-wrap:wrap;gap:4px;align-items:center;min-width:0}.sd-autoid-inspector__state-chip{display:inline-block;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:10px;background:var(--sd-surface-muted, #e7e8ed);color:var(--sd-text-secondary, #44474f);border:1px solid var(--sd-border, #c4c6d0);padding:1px 6px;border-radius:999px;font-weight:500;white-space:nowrap}.sd-autoid-inspector__state-chip.is-error{background:var(--sd-error-light, #ffdad6);color:var(--sd-error-dark, #93000a);border-color:var(--sd-error, #ba1a1a)}.sd-autoid-inspector__state-chip.is-warning{background:var(--sd-warning-light, #ffddb0);color:var(--sd-warning-dark, #7a4d00);border-color:var(--sd-warning, #a66300)}.sd-autoid-inspector__state-chip.is-info{background:var(--sd-info-light, #d4f7f6);color:var(--sd-info, #006a6a);border-color:var(--sd-info, #006a6a)}.sd-autoid-inspector__empty{text-align:center;color:var(--sd-text-secondary, #44474f);padding:24px;font-style:italic}.sd-autoid-inspector__filter{display:flex;align-items:center;gap:6px;background:var(--sd-surface-muted, #e7e8ed);border:1px solid var(--sd-border, #c4c6d0);border-radius:8px;padding:6px 10px;margin-bottom:12px;transition:border-color .15s ease}.sd-autoid-inspector__filter:focus-within{border-color:var(--sd-primary, #005cbb);background:#fff}.sd-autoid-inspector__filter input{flex:1;border:none;background:transparent;outline:none;font-size:13px;color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__filter input::placeholder{color:var(--sd-border-strong, #74777f)}.sd-autoid-inspector__filter input:focus-visible{outline:2px solid var(--sd-primary, #005cbb);outline-offset:1px;border-radius:4px}.sd-autoid-inspector__filter>sd-icon{font-size:18px;width:18px;height:18px;color:var(--sd-text-secondary, #44474f)}.sd-autoid-inspector__export-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(112px,1fr));gap:8px}.sd-autoid-inspector__export-grid.is-e2e{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}.sd-autoid-inspector__export-grid button{border:1px solid var(--sd-border, #c4c6d0);background:#fff;border-radius:10px;padding:12px 10px;cursor:pointer;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;min-width:0;transition:border-color .15s ease,background .15s ease,transform .12s ease;text-align:center}.sd-autoid-inspector__export-grid button:hover{border-color:var(--sd-primary, #005cbb);background:var(--sd-primary-light, #d7e3ff);transform:translateY(-1px)}.sd-autoid-inspector__export-grid button:disabled{cursor:wait;opacity:.68;transform:none}.sd-autoid-inspector__export-grid button span{font-size:12px;font-weight:600;color:var(--sd-text, #1a1b1f);line-height:1.25}.sd-autoid-inspector__export-grid button small{font-size:10px;color:var(--sd-text-secondary, #44474f);line-height:1.2}.sd-autoid-inspector__export-grid button sd-icon{font-size:22px;width:22px;height:22px;color:var(--sd-primary, #005cbb)}.sd-autoid-inspector__export-section{margin-top:14px;padding-top:12px;border-top:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__context-backdrop{position:fixed;inset:0;z-index:10001;background:#141c2652}.sd-autoid-inspector__context-dialog{position:fixed;z-index:10002;top:50%;left:50%;width:min(720px,100vw - 28px);max-height:min(720px,100vh - 28px);transform:translate(-50%,-50%);display:flex;flex-direction:column;border:1px solid var(--sd-border, #c4c6d0);border-radius:8px;background:#fff;box-shadow:0 18px 48px #0f172a38;overflow:hidden}.sd-autoid-inspector__context-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:14px 16px;border-bottom:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__context-header h4{margin:0;font-size:15px;font-weight:700;line-height:1.3;color:var(--sd-text, #1a1b1f)}.sd-autoid-inspector__context-header small{display:block;margin-top:2px;font-size:11px;color:var(--sd-text-secondary, #44474f);line-height:1.3}.sd-autoid-inspector__context-form{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;padding:14px 16px;overflow:auto}.sd-autoid-inspector__context-form label{display:flex;flex-direction:column;gap:6px;min-width:0}.sd-autoid-inspector__context-form label.is-full{grid-column:1/-1}.sd-autoid-inspector__context-form span{font-size:12px;font-weight:600;color:var(--sd-text, #1a1b1f);line-height:1.25}.sd-autoid-inspector__context-form input,.sd-autoid-inspector__context-form textarea{width:100%;min-width:0;border:1px solid var(--sd-border, #c4c6d0);border-radius:6px;padding:8px 10px;color:var(--sd-text, #1a1b1f);font:inherit;font-size:12px;line-height:1.4;outline:none;resize:vertical}.sd-autoid-inspector__context-form input:focus,.sd-autoid-inspector__context-form textarea:focus{border-color:var(--sd-primary, #005cbb);box-shadow:0 0 0 2px color-mix(in srgb,var(--sd-primary, #005cbb) 18%,transparent)}.sd-autoid-inspector__context-actions{display:flex;justify-content:flex-end;gap:8px;padding:12px 16px;border-top:1px solid var(--sd-border, #c4c6d0)}.sd-autoid-inspector__context-actions button{min-height:34px;border-radius:6px;padding:0 12px;border:1px solid var(--sd-border, #c4c6d0);background:#fff;color:var(--sd-text, #1a1b1f);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:6px;font-size:12px;font-weight:600}.sd-autoid-inspector__context-actions button.is-primary{border-color:var(--sd-primary, #005cbb);background:var(--sd-primary, #005cbb);color:#fff}.sd-autoid-inspector__context-actions button:disabled{cursor:not-allowed;opacity:.62}.sd-autoid-inspector__context-actions button sd-icon{font-size:17px;width:17px;height:17px}.sd-autoid-inspector__export-message{margin-top:10px;border-radius:8px;padding:8px 10px;font-size:12px;line-height:1.35}.sd-autoid-inspector__export-message.is-success{background:var(--sd-success-light, #d8f0d3);color:var(--sd-success-dark, #1b5e20);border:1px solid var(--sd-success, #2e7d32)}.sd-autoid-inspector__export-message.is-error{background:var(--sd-error-light, #ffdad6);color:var(--sd-error-dark, #93000a);border:1px solid var(--sd-error, #ba1a1a)}@media(max-width:560px){.sd-autoid-inspector__context-form{grid-template-columns:1fr}.sd-autoid-inspector__context-actions{flex-direction:column-reverse}.sd-autoid-inspector__context-actions button{width:100%}}\n"] }]
|
|
969
969
|
}], propDecorators: { onEscape: [{
|
|
970
970
|
type: HostListener,
|
|
971
971
|
args: ['document:keydown.escape']
|