diff --git a/.changeset/blue-cycles-sing.md b/.changeset/blue-cycles-sing.md new file mode 100644 index 0000000000..37c68afc46 --- /dev/null +++ b/.changeset/blue-cycles-sing.md @@ -0,0 +1,5 @@ +--- +'@baloise/ds-core': patch +--- + +**styles**: implement the missing responsive classes for spacing diff --git a/.changeset/olive-weeks-look.md b/.changeset/olive-weeks-look.md new file mode 100644 index 0000000000..cd159e1b19 --- /dev/null +++ b/.changeset/olive-weeks-look.md @@ -0,0 +1,5 @@ +--- +'@baloise/ds-core': minor +--- + +**angular**: error component accepts a form group input diff --git a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-clearable-empty-selected.png b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-clearable-empty-selected.png index 673a212874..bcb5610261 100644 Binary files a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-clearable-empty-selected.png and b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-clearable-empty-selected.png differ diff --git a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-desktop-basic-empty-selected.png b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-desktop-basic-empty-selected.png index 1cc4fd931e..b4bd4f347c 100644 Binary files a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-desktop-basic-empty-selected.png and b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-desktop-basic-empty-selected.png differ diff --git a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-desktop-form-field-empty-open.png b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-desktop-form-field-empty-open.png index be0e2c5492..9d30417596 100644 Binary files a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-desktop-form-field-empty-open.png and b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-desktop-form-field-empty-open.png differ diff --git a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-desktop-multiple-chips-empty-open.png b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-desktop-multiple-chips-empty-open.png index 01094ea2a2..c9c9d23243 100644 Binary files a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-desktop-multiple-chips-empty-open.png and b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-desktop-multiple-chips-empty-open.png differ diff --git a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-desktop-multiple-empty-selected.png b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-desktop-multiple-empty-selected.png index d9adfd9b31..dc30dd3d68 100644 Binary files a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-desktop-multiple-empty-selected.png and b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-desktop-multiple-empty-selected.png differ diff --git a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-basic-empty-selected.png b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-basic-empty-selected.png index 056be2cbd1..d0462451a9 100644 Binary files a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-basic-empty-selected.png and b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-basic-empty-selected.png differ diff --git a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-form-field-empty-open.png b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-form-field-empty-open.png index 540c9d5ce8..1dcba138d8 100644 Binary files a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-form-field-empty-open.png and b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-form-field-empty-open.png differ diff --git a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-long-content-empty-closed.png b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-long-content-empty-closed.png index 6dc25a8866..9982bd0043 100644 Binary files a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-long-content-empty-closed.png and b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-long-content-empty-closed.png differ diff --git a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-long-content-empty-open.png b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-long-content-empty-open.png index b5fda3cfec..7ad0a47435 100644 Binary files a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-long-content-empty-open.png and b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-long-content-empty-open.png differ diff --git a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-multiple-chips-empty-open.png b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-multiple-chips-empty-open.png index 3e533b3d25..5bcddb3009 100644 Binary files a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-multiple-chips-empty-open.png and b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-multiple-chips-empty-open.png differ diff --git a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-multiple-empty-selected.png b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-multiple-empty-selected.png index 0226b50755..6887c59017 100644 Binary files a/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-multiple-empty-selected.png and b/e2e/cypress/snapshots/base/visual/bal-dropdown.visual.cy.ts/dropdown-mobile-multiple-empty-selected.png differ diff --git a/libs/nx/src/executors/build-styles/generators/spacing.ts b/libs/nx/src/executors/build-styles/generators/spacing.ts index e22d9a459e..3b55e5ac2c 100644 --- a/libs/nx/src/executors/build-styles/generators/spacing.ts +++ b/libs/nx/src/executors/build-styles/generators/spacing.ts @@ -29,46 +29,60 @@ export const generateSpacing = async (options: BuildStylesExecutorSchema) => { rules: [ // Margin margin.rules, + margin.rulesMobile, margin.rulesTablet, margin.rulesDesktop, marginX.rules, + marginX.rulesMobile, marginX.rulesTablet, marginX.rulesDesktop, marginY.rules, + marginY.rulesMobile, marginY.rulesTablet, marginY.rulesDesktop, marginTop.rules, + marginTop.rulesMobile, marginTop.rulesTablet, marginTop.rulesDesktop, marginRight.rules, + marginRight.rulesMobile, marginRight.rulesTablet, marginRight.rulesDesktop, marginBottom.rules, + marginBottom.rulesMobile, marginBottom.rulesTablet, marginBottom.rulesDesktop, marginLeft.rules, + marginLeft.rulesMobile, marginLeft.rulesTablet, marginLeft.rulesDesktop, // Padding padding.rules, + padding.rulesMobile, padding.rulesTablet, padding.rulesDesktop, paddingX.rules, + paddingX.rulesMobile, paddingX.rulesTablet, paddingX.rulesDesktop, paddingY.rules, + paddingY.rulesMobile, paddingY.rulesTablet, paddingY.rulesDesktop, paddingTop.rules, + paddingTop.rulesMobile, paddingTop.rulesTablet, paddingTop.rulesDesktop, paddingRight.rules, + paddingRight.rulesMobile, paddingRight.rulesTablet, paddingRight.rulesDesktop, paddingBottom.rules, + paddingBottom.rulesMobile, paddingBottom.rulesTablet, paddingBottom.rulesDesktop, paddingLeft.rules, + paddingLeft.rulesMobile, paddingLeft.rulesTablet, paddingLeft.rulesDesktop, ], @@ -78,21 +92,34 @@ export const generateSpacing = async (options: BuildStylesExecutorSchema) => { function generateResponsiveSpace({ keys, property, prefix }) { const { rules: rules } = generateSpace({ keys, property, prefix }) + const { rules: rulesMobile } = generateSpace({ keys, property, prefix, breakpoint: 'mobile' }) const { rules: rulesTablet } = generateSpace({ keys, property, prefix, breakpoint: 'tablet' }) const { rules: rulesDesktop } = generateSpace({ keys, property, prefix, breakpoint: 'desktop' }) - return { rules, rulesTablet, rulesDesktop } + return { rules, rulesMobile, rulesTablet, rulesDesktop } } function generateSpace({ keys, prefix, property, breakpoint = '' }) { - const values = { - [`${prefix}-none`]: '0', - [`${prefix}-auto`]: 'auto', + if (breakpoint === 'mobile') { + const values = {} + for (const index in keys) { + const key = keys[index] + values[`${breakpoint}:${prefix}-${key}`] = `var(--bal-space-${key}${breakpoint ? `-${breakpoint}` : ''})` + } + const rules = utils.styleClass({ property, values, breakpoint, important: true }) + return { rules } + } else { + const values = { + [`${prefix}-none`]: '0', + [`${prefix}-auto`]: 'auto', + } + for (const index in keys) { + const key = keys[index] + values[`${prefix}-${key}`] = `var(--bal-space-${key}${breakpoint ? `-${breakpoint}` : ''})` + if (breakpoint) { + values[`${breakpoint}:${prefix}-${key}`] = `var(--bal-space-${key}${breakpoint ? `-${breakpoint}` : ''})` + } + } + const rules = utils.styleClass({ property, values, breakpoint, important: true }) + return { rules } } - for (const index in keys) { - const key = keys[index] - values[`${prefix}-${key}`] = `var(--bal-space-${key}${breakpoint ? `-${breakpoint}` : ''})` - } - const rules = utils.styleClass({ property, values, breakpoint, important: true }) - - return { rules } } diff --git a/packages/angular-common/src/directives/error.component.ts b/packages/angular-common/src/directives/error.component.ts index 087181a394..6e874793c7 100755 --- a/packages/angular-common/src/directives/error.component.ts +++ b/packages/angular-common/src/directives/error.component.ts @@ -1,6 +1,6 @@ /* eslint-disable @angular-eslint/directive-class-suffix */ import { AfterViewInit, ChangeDetectorRef, Directive, HostBinding, Inject, Injector, Input } from '@angular/core' -import { AbstractControl, ControlContainer } from '@angular/forms' +import { AbstractControl, ControlContainer, FormGroup } from '@angular/forms' import { BehaviorSubject } from 'rxjs' import type { BaloiseDesignSystemAngularConfig } from '../utils/config' @@ -29,6 +29,11 @@ export class BalNgErrorComponent implements AfterViewInit { */ @Input() error?: string + /** + * FormGroup where the control of the error message is located. (optional) + */ + @Input() group?: FormGroup + /** * The name of the form control, which is registered in the form group. */ @@ -48,41 +53,30 @@ export class BalNgErrorComponent implements AfterViewInit { ready = new BehaviorSubject(false) ngAfterViewInit(): void { - raf(() => { - try { - this.controlContainer = this.injector.get(ControlContainer) - } catch { - /* No ControlContainer provided */ - } + this.control = this.getControl() - if (!this.controlContainer) { - return - } + raf(() => this.setup()) + } - try { - this.config = this.injector.get(BalTokenConfig) - } catch { - /* No config provided */ - } + setup = () => { + try { + this.config = this.injector.get(BalTokenConfig) + } catch { + /* No config provided */ + } - this.invalidateOn = this.config?.forms?.invalidateOn || this.invalidateOn + this.invalidateOn = this.config?.forms?.invalidateOn || this.invalidateOn - if (this.controlName) { - this.control = this.controlContainer.control?.get(this.controlName) - if (!this.control) { - console.warn('[BalNgErrorComponent] Could not find the given controlName in the form control container') - } else { - this.ready.next(true) - this.cd.detectChanges() - } - } else { - console.warn('[BalNgErrorComponent] Please provide a controlName') - } - }) + if (!this.control) { + console.warn('[BalNgErrorComponent] Could not find the given controlName in the form control container') + } else { + this.ready.next(true) + this.cd.detectChanges() + } } get hasError(): boolean { - if (this.controlName && this.controlContainer && this.config && this.control) { + if (this.controlName && this.config && this.control) { if (!this.control[this.invalidateOn]) { return false } @@ -103,4 +97,28 @@ export class BalNgErrorComponent implements AfterViewInit { return false } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + private getControl(): AbstractControl | null { + if (this.controlName) { + if (this.group) { + return this.group.get(this.controlName) + } else { + try { + this.controlContainer = this.injector.get(ControlContainer) + } catch { + /* No ControlContainer provided */ + } + + if (!this.controlContainer) { + return null + } + + return this.controlContainer.control?.get(this.controlName) as AbstractControl + } + } else { + console.warn('[BalNgErrorComponent] Please provide a controlName') + } + return null + } } diff --git a/packages/core/src/components/bal-dropdown/bal-dropdown.tsx b/packages/core/src/components/bal-dropdown/bal-dropdown.tsx index 90102bb2ba..a86197f5a7 100644 --- a/packages/core/src/components/bal-dropdown/bal-dropdown.tsx +++ b/packages/core/src/components/bal-dropdown/bal-dropdown.tsx @@ -12,14 +12,7 @@ import { EventEmitter, Method, } from '@stencil/core' -import { - areArraysEqual, - isArrowDownKey, - isArrowUpKey, - isEnterKey, - isEscapeKey, - isSpaceKey, -} from '@baloise/web-app-utils' +import { isArrowDownKey, isArrowUpKey, isEnterKey, isEscapeKey, isSpaceKey } from '@baloise/web-app-utils' import { BEM } from '../../utils/bem' import { LogInstance, Loggable, Logger } from '../../utils/log' import { stopEventBubbling } from '../../utils/form-input' diff --git a/packages/core/src/utils/dropdown/events.ts b/packages/core/src/utils/dropdown/events.ts index 8afaf84f2b..89d3e34a83 100644 --- a/packages/core/src/utils/dropdown/events.ts +++ b/packages/core/src/utils/dropdown/events.ts @@ -1,3 +1,4 @@ +import { rIC } from '../helpers' import { DropdownComponent } from './component' export type DropdownEvents = { @@ -18,8 +19,10 @@ export class DropdownEventsUtil { } handleBlur(ev: FocusEvent) { - this.component.hasFocus = false - this.component.balBlur.emit(ev) + if (!this.component.isExpanded) { + this.component.hasFocus = false + rIC(() => this.component.balBlur.emit(ev)) + } } handleClick(ev: MouseEvent) { @@ -51,6 +54,9 @@ export class DropdownEventsUtil { if (!this.component.el.contains(ev.target as Node)) { this.component.isExpanded = false this.component.listEl?.resetFocus() + + this.component.hasFocus = false + rIC(() => this.component.balBlur.emit(ev as any)) } } }