From 5b624ae0c77ea935fe874dcb977eb22dd17cd60c Mon Sep 17 00:00:00 2001 From: Derek Burgman Date: Thu, 10 Feb 2022 07:44:58 -0600 Subject: [PATCH] feat: added dbxStyleBody - DbxStyleBody is used to apply the currently configured styling to body - Updated DbxStyleService to handle configuration concerning which styles are available/appropriate or not --- packages/dbx-form/src/_index.scss | 8 ++ .../formly/field/selection/generic_TODO.scss | 9 -- .../lib/formly/field/value/array/_array.scss | 51 ++++++++- .../value/array/array.field.component.ts | 102 +++++++++++++----- .../field/value/array/array.field.module.ts | 16 ++- .../formly/field/value/array/array.field.ts | 29 +++++ .../src/lib/formly/field/value/array/index.ts | 1 + .../formly/field/value/phone/phone.field.ts | 4 +- .../field/value/text/text.address.field.ts | 26 ++--- .../dbx-web/src/lib/button/button.module.ts | 5 +- packages/dbx-web/src/lib/layout/bar/_bar.scss | 1 - .../dbx-web/src/lib/layout/flex/_flex.scss | 2 +- .../dbx-web/src/lib/layout/style/index.ts | 1 + .../lib/layout/style/style.body.directive.ts | 28 +++++ .../src/lib/layout/style/style.directive.ts | 1 - .../lib/layout/style/style.layout.module.ts | 7 +- .../src/lib/layout/style/style.service.ts | 91 ++++++++++++++-- .../lib/layout/style/style.set.directive.ts | 52 +++++++-- .../src/app/container/layout.component.html | 5 +- .../src/app/container/layout.component.scss | 1 - .../src/app/container/layout.component.ts | 7 ++ .../src/app/modules/demo/style/_demo.scss | 2 +- .../doc/container/layout.component.html | 2 +- .../form/component/example.form.component.ts | 4 +- .../form/container/value.component.html | 9 +- .../modules/form/container/value.component.ts | 17 ++- .../form/container/wrapper.component.html | 16 +-- packages/demo/src/root.module.ts | 8 +- packages/demo/src/style/_default.scss | 16 --- packages/demo/src/style/_doc.scss | 11 +- packages/demo/src/style/_style.scss | 1 - packages/demo/src/styles.scss | 2 +- packages/util/src/lib/getter.ts | 17 ++- packages/util/src/lib/string.ts | 4 + 34 files changed, 425 insertions(+), 131 deletions(-) create mode 100644 packages/dbx-form/src/lib/formly/field/value/array/array.field.ts create mode 100644 packages/dbx-web/src/lib/layout/style/style.body.directive.ts delete mode 100644 packages/demo/src/style/_default.scss diff --git a/packages/dbx-form/src/_index.scss b/packages/dbx-form/src/_index.scss index c7cb8611e..4306d656a 100644 --- a/packages/dbx-form/src/_index.scss +++ b/packages/dbx-form/src/_index.scss @@ -1,4 +1,5 @@ @use '@angular/material'as mat; +@use './lib/style/all-theme' as dbx-form-theme; // Structural @forward './lib/style/core'show core; @@ -9,3 +10,10 @@ get-dbx-form-theme-config; // Theme bundles @forward './lib/style/all-theme'show all-component-themes; + +// Create Theme +@mixin theme($root-selector, $theme-config) { + #{$root-selector} { + @include dbx-form-theme.all-component-themes($theme-config); + } +} diff --git a/packages/dbx-form/src/lib/formly/field/selection/generic_TODO.scss b/packages/dbx-form/src/lib/formly/field/selection/generic_TODO.scss index 3ef39a38f..334804bc8 100644 --- a/packages/dbx-form/src/lib/formly/field/selection/generic_TODO.scss +++ b/packages/dbx-form/src/lib/formly/field/selection/generic_TODO.scss @@ -14,15 +14,6 @@ } } -.form-repeat-section { - .form-repeat-section-field { - h4 { - margin: 0; - display: inline; - } - } -} - .searchable-field-form-loading { margin: -18px; } diff --git a/packages/dbx-form/src/lib/formly/field/value/array/_array.scss b/packages/dbx-form/src/lib/formly/field/value/array/_array.scss index 5adb19967..d8aeeeede 100644 --- a/packages/dbx-form/src/lib/formly/field/value/array/_array.scss +++ b/packages/dbx-form/src/lib/formly/field/value/array/_array.scss @@ -1,12 +1,59 @@ +@use 'sass:map'; +@use 'sass:color'; @use '../../../../style/theming'; // MARK: Variables // MARK: Mixin -@mixin core() {} +@mixin core() { -@mixin color($theme-config) {} + .example-custom-placeholder { + background: #ccc; + border: dotted 3px #999; + min-height: 100px; + transition: transform 250ms cubic-bezier(0, 0, 0.2, 1); + } + + .dbx-form-repeat-array { + .dbx-form-repeat-array-field { + + @include theming.elevation(1); + + h4 { + margin: 0; + display: inline; + + .repeat-array-number { + margin-right: 4px; + } + } + + padding: 0; + margin-bottom: 2px; + // border: 1px solid rgba(0, 0, 0, 0.04); + + .dbx-form-repeat-array-field-content { + display: block; + padding: 6px; + } + } + } + +} + +@mixin color($theme-config) { + $color-config: theming.get-color-config($theme-config); + $background: map.get($color-config, 'background'); + + $form-repeat-array-field-bg: theming.get-color-from-palette($background, 'card'); + + .dbx-form-repeat-array-field { + background: $form-repeat-array-field-bg; + border: 4px solid $form-repeat-array-field-bg; + } + +} @mixin typography($typography-config) {} diff --git a/packages/dbx-form/src/lib/formly/field/value/array/array.field.component.ts b/packages/dbx-form/src/lib/formly/field/value/array/array.field.component.ts index 3fc00cf29..b4fd6dd5f 100644 --- a/packages/dbx-form/src/lib/formly/field/value/array/array.field.component.ts +++ b/packages/dbx-form/src/lib/formly/field/value/array/array.field.component.ts @@ -1,49 +1,56 @@ +import { CdkDragDrop } from '@angular/cdk/drag-drop'; import { Component } from '@angular/core'; -import { Maybe } from '@dereekb/util'; -import { FieldArrayType, FormlyTemplateOptions } from '@ngx-formly/core'; +import { GetterWithInput, getValueFromObjectOrGetter, Maybe } from '@dereekb/util'; +import { FieldArrayTypeConfig, FieldArrayType, FormlyTemplateOptions, FormlyFieldConfig } from '@ngx-formly/core'; -export interface FormRepeatSectionConfig { - itemLabel?: string; +export interface DbxFormRepeatArrayConfig { + labelForField?: string | GetterWithInput; addText?: string; removeText?: string; } -export interface FormRepeatTypeTemplateOptions extends FormlyTemplateOptions, FormRepeatSectionConfig { - repeatSection?: FormRepeatSectionConfig; +export interface DbxFormRepeatArrayTemplateOptions extends FormlyTemplateOptions, DbxFormRepeatArrayConfig { + repeatSection: DbxFormRepeatArrayConfig; +} + +export interface DbxFormRepeatArrayFormlyConfig extends FieldArrayTypeConfig { + templateOptions: DbxFormRepeatArrayTemplateOptions; } @Component({ template: ` -
- -
- -
-
-

{{ itemLabel }}{{ i + 1 }}

- - +
+ + +
+
+
+ + + +

{{ i + 1 }}{{ labelForItem(field) }}

+ + +
+
- -
- - -
- - +
+ + +
` }) -export class DbxFormRepeatTypeComponent extends FieldArrayType { +export class DbxFormRepeatArrayTypeComponent extends FieldArrayType{ - get repeatSection(): FormRepeatSectionConfig { - return (this.to as FormRepeatTypeTemplateOptions).repeatSection ?? {}; + get repeatSection(): DbxFormRepeatArrayConfig { + return this.to.repeatSection; } - get itemLabel(): string { - return this.repeatSection.itemLabel ?? '#'; + get label(): string { + return this.field.templateOptions.label ?? this.field.key as string; } get addText(): string { @@ -72,4 +79,41 @@ export class DbxFormRepeatTypeComponent extends FieldArrayType { } } + /** + * Moves the target index up one value. + * + * @param index + */ + moveUp(index: number) { + if (index === 0) { + return; + } + + this.swapIndexes(index, index - 1); + } + + moveDown(index: number) { + this.swapIndexes(index, index + 1); + } + + swapIndexes(currentIndex: number, targetIndex: number) { + const array: any[] = this.model; + const targetValue = array[currentIndex]; + + if (!targetValue) { + return; + } + + this.remove(currentIndex); + this.add(targetIndex, targetValue); + } + + drop(event: CdkDragDrop) { + this.swapIndexes(event.previousIndex, event.currentIndex); + } + + labelForItem(field: FormlyFieldConfig): string { + return getValueFromObjectOrGetter(this.repeatSection.labelForField ?? '', field); + } + } diff --git a/packages/dbx-form/src/lib/formly/field/value/array/array.field.module.ts b/packages/dbx-form/src/lib/formly/field/value/array/array.field.module.ts index b6faaf8ad..ad736da51 100644 --- a/packages/dbx-form/src/lib/formly/field/value/array/array.field.module.ts +++ b/packages/dbx-form/src/lib/formly/field/value/array/array.field.module.ts @@ -1,11 +1,14 @@ +import { MatIconModule } from '@angular/material/icon'; import { MatDividerModule } from '@angular/material/divider'; import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { ReactiveFormsModule } from '@angular/forms'; import { MatFormFieldModule } from '@angular/material/form-field'; import { FormlyModule } from '@ngx-formly/core'; -import { DbxFormRepeatTypeComponent } from './array.field.component'; -import { DbxButtonModule } from '@dereekb/dbx-web'; +import { DbxFormRepeatArrayTypeComponent } from './array.field.component'; +import { DbxButtonModule, DbxSectionLayoutModule, DbxBarLayoutModule } from '@dereekb/dbx-web'; +import { MatButtonModule } from '@angular/material/button'; +import { DragDropModule } from '@angular/cdk/drag-drop'; @NgModule({ imports: [ @@ -13,15 +16,20 @@ import { DbxButtonModule } from '@dereekb/dbx-web'; MatFormFieldModule, ReactiveFormsModule, MatDividerModule, + MatButtonModule, + MatIconModule, + DragDropModule, + DbxSectionLayoutModule, + DbxBarLayoutModule, DbxButtonModule, FormlyModule.forChild({ types: [ - { name: 'repeat', component: DbxFormRepeatTypeComponent } + { name: 'repeatarray', component: DbxFormRepeatArrayTypeComponent } ] }) ], declarations: [ - DbxFormRepeatTypeComponent + DbxFormRepeatArrayTypeComponent ], exports: [] }) diff --git a/packages/dbx-form/src/lib/formly/field/value/array/array.field.ts b/packages/dbx-form/src/lib/formly/field/value/array/array.field.ts new file mode 100644 index 000000000..b73cddaa7 --- /dev/null +++ b/packages/dbx-form/src/lib/formly/field/value/array/array.field.ts @@ -0,0 +1,29 @@ +import { FormlyFieldConfig } from '@ngx-formly/core'; +import { FieldConfig } from "../../field"; +import { DbxFormRepeatArrayConfig } from './array.field.component'; + +export interface RepeatArrayFieldConfig extends DbxFormRepeatArrayConfig, FieldConfig { + label?: string; + repeatFieldGroup: FormlyFieldConfig[]; + maxLength?: number; +} + +export function repeatArrayField({ key, label, required = false, repeatFieldGroup, maxLength, addText, removeText, labelForField }: RepeatArrayFieldConfig): FormlyFieldConfig { + return { + key, + type: 'repeatarray', + templateOptions: { + label, + required, + repeatSection: { + labelForField, + addText, + removeText, + }, + maxLength + }, + fieldArray: { + fieldGroup: repeatFieldGroup + } + }; +} diff --git a/packages/dbx-form/src/lib/formly/field/value/array/index.ts b/packages/dbx-form/src/lib/formly/field/value/array/index.ts index 56f39e3f5..78106b593 100644 --- a/packages/dbx-form/src/lib/formly/field/value/array/index.ts +++ b/packages/dbx-form/src/lib/formly/field/value/array/index.ts @@ -1,2 +1,3 @@ export * from './array.field.component'; export * from './array.field.module'; +export * from './array.field'; diff --git a/packages/dbx-form/src/lib/formly/field/value/phone/phone.field.ts b/packages/dbx-form/src/lib/formly/field/value/phone/phone.field.ts index ec6aa4dbe..e71e88a40 100644 --- a/packages/dbx-form/src/lib/formly/field/value/phone/phone.field.ts +++ b/packages/dbx-form/src/lib/formly/field/value/phone/phone.field.ts @@ -54,7 +54,7 @@ export interface PhoneAndLabelFieldGroupConfig extends PhoneFormlyFieldsConfig { required?: boolean; } -export function phoneAndLabelFieldGroup({ key = 'phone', label = 'Phone Number', required, phoneField, labelField }: PhoneAndLabelFieldGroupConfig): FormlyFieldConfig { +export function phoneAndLabelFieldGroup({ key = 'phone', label = 'Phone Number', required = false, phoneField, labelField }: PhoneAndLabelFieldGroupConfig = {}): FormlyFieldConfig { return { key, wrappers: ['section'], @@ -74,7 +74,7 @@ export interface PhoneListFieldConfig extends PhoneAndLabelFieldGroupConfig { } } -export function phoneListField({ key = 'phones', label = 'Phone Numbers', repeatSection, required = false, maxPhones = 6, phoneField, labelField }: PhoneListFieldConfig): FormlyFieldConfig { +export function phoneListField({ key = 'phones', label = 'Phone Numbers', repeatSection, required = false, maxPhones = 6, phoneField, labelField }: PhoneListFieldConfig = {}): FormlyFieldConfig { return { key, type: 'repeat', diff --git a/packages/dbx-form/src/lib/formly/field/value/text/text.address.field.ts b/packages/dbx-form/src/lib/formly/field/value/text/text.address.field.ts index fb63ef6b9..24ee23bd1 100644 --- a/packages/dbx-form/src/lib/formly/field/value/text/text.address.field.ts +++ b/packages/dbx-form/src/lib/formly/field/value/text/text.address.field.ts @@ -3,6 +3,7 @@ import { textField } from './text.field'; import { cityField, countryField, stateField, zipCodeField } from './text.additional.field'; import { flexLayoutWrapper } from '../../wrapper/wrapper'; import { FieldConfig } from '../../field'; +import { repeatArrayField } from '..'; export const ADDRESS_LINE_MAX_LENGTH = 100; @@ -56,22 +57,13 @@ export interface AddressListFieldConfig extends FieldConfig { } export function addressListField({ key = 'addresses', required = false, maxAddresses = 6 }: Partial = {}): FormlyFieldConfig { - return { + return repeatArrayField({ key, - type: 'repeat', - wrappers: ['section'], - templateOptions: { - label: 'Addresses', - placeholder: '', - required, - repeatSection: { - addText: 'Add Address', - removeText: 'Remove Address' - }, - maxLength: maxAddresses - }, - fieldArray: { - fieldGroup: addressFormlyFields() - } - }; + label: 'Addresses', + labelForField: 'Address', + addText: 'Add Address', + removeText: 'Remove Address', + maxLength: maxAddresses, + repeatFieldGroup: addressFormlyFields() + }); } diff --git a/packages/dbx-web/src/lib/button/button.module.ts b/packages/dbx-web/src/lib/button/button.module.ts index 586585fbe..95eb9d276 100644 --- a/packages/dbx-web/src/lib/button/button.module.ts +++ b/packages/dbx-web/src/lib/button/button.module.ts @@ -1,6 +1,4 @@ -import { MatIconModule } from '@angular/material/icon'; import { NgModule } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; import { MatProgressButtonsModule } from 'mat-progress-buttons'; import { DbxButtonComponent } from './button.component'; import { DbxButtonSpacerComponent } from './button.spacer.component'; @@ -9,8 +7,6 @@ import { CommonModule } from '@angular/common'; @NgModule({ imports: [ CommonModule, - MatIconModule, - MatButtonModule, MatProgressButtonsModule ], declarations: [ @@ -18,6 +14,7 @@ import { CommonModule } from '@angular/common'; DbxButtonSpacerComponent ], exports: [ + MatProgressButtonsModule, DbxButtonComponent, DbxButtonSpacerComponent ], diff --git a/packages/dbx-web/src/lib/layout/bar/_bar.scss b/packages/dbx-web/src/lib/layout/bar/_bar.scss index fbbecd032..897da1cd5 100644 --- a/packages/dbx-web/src/lib/layout/bar/_bar.scss +++ b/packages/dbx-web/src/lib/layout/bar/_bar.scss @@ -19,7 +19,6 @@ $bar-vertical-padding: theming.$padding-1; } .dbx-bar { - height: 100%; box-sizing: border-box; padding: $bar-vertical-padding; display: flex; diff --git a/packages/dbx-web/src/lib/layout/flex/_flex.scss b/packages/dbx-web/src/lib/layout/flex/_flex.scss index 1c712b93b..4a2b0f57e 100644 --- a/packages/dbx-web/src/lib/layout/flex/_flex.scss +++ b/packages/dbx-web/src/lib/layout/flex/_flex.scss @@ -16,7 +16,7 @@ $dbx-flex-group-columns-count: 6; // padding: $dbx-flex-group-padding; margin: 0 #{-$dbx-flex-group-padding} #{-$dbx-flex-group-padding} 0; - padding: $dbx-flex-group-padding $dbx-flex-group-padding 0; + // padding: 0 $dbx-flex-group-padding $dbx-flex-group-padding 0; >* { box-sizing: border-box; diff --git a/packages/dbx-web/src/lib/layout/style/index.ts b/packages/dbx-web/src/lib/layout/style/index.ts index d33622c4d..de9f1395b 100644 --- a/packages/dbx-web/src/lib/layout/style/index.ts +++ b/packages/dbx-web/src/lib/layout/style/index.ts @@ -3,3 +3,4 @@ export * from './spacer.directive'; export * from './style.directive'; export * from './style.service'; export * from './style.set.directive'; +export * from './style.body.directive'; diff --git a/packages/dbx-web/src/lib/layout/style/style.body.directive.ts b/packages/dbx-web/src/lib/layout/style/style.body.directive.ts new file mode 100644 index 000000000..0b770e864 --- /dev/null +++ b/packages/dbx-web/src/lib/layout/style/style.body.directive.ts @@ -0,0 +1,28 @@ +import { Directive, ChangeDetectorRef, Renderer2 } from '@angular/core'; +import { DbxStyleService } from './style.service'; +import { AbstractSubscriptionDirective, safeDetectChanges } from '@dereekb/dbx-core'; +import { delay } from 'rxjs'; + +/** + * Used to style the body document using the style provided by DbxStyleService. + */ +@Directive({ + selector: '[dbxStyleBody]', + host: { + '[class]': 'style' + } +}) +export class DbxStyleBodyDirective extends AbstractSubscriptionDirective { + + private _currentStyle: string = ''; + + constructor(private renderer: Renderer2, readonly styleService: DbxStyleService, private cdRef: ChangeDetectorRef) { + super(styleService.style$.pipe(delay(0)).subscribe((style) => { + this._currentStyle && this.renderer.removeClass(document.body, this._currentStyle); + style && this.renderer.addClass(document.body, style); + this._currentStyle = style; + safeDetectChanges(this.cdRef); + })); + } + +} diff --git a/packages/dbx-web/src/lib/layout/style/style.directive.ts b/packages/dbx-web/src/lib/layout/style/style.directive.ts index d3ba67cf0..f7caecb86 100644 --- a/packages/dbx-web/src/lib/layout/style/style.directive.ts +++ b/packages/dbx-web/src/lib/layout/style/style.directive.ts @@ -19,7 +19,6 @@ export class DbxStyleDirective extends AbstractSubscriptionDirective { constructor(readonly styleService: DbxStyleService, private cdRef: ChangeDetectorRef) { super(styleService.style$.pipe(delay(0)).subscribe((style) => { this.style = style; - console.log('inporting style: ', this.style); safeDetectChanges(this.cdRef); })); } diff --git a/packages/dbx-web/src/lib/layout/style/style.layout.module.ts b/packages/dbx-web/src/lib/layout/style/style.layout.module.ts index bfe43aa7f..c8bfe49e1 100644 --- a/packages/dbx-web/src/lib/layout/style/style.layout.module.ts +++ b/packages/dbx-web/src/lib/layout/style/style.layout.module.ts @@ -3,6 +3,7 @@ import { DbxStyleDirective } from './style.directive'; import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { DbxSpacerDirective } from './spacer.directive'; +import { DbxStyleBodyDirective } from './style.body.directive'; @NgModule({ imports: [ @@ -11,12 +12,14 @@ import { DbxSpacerDirective } from './spacer.directive'; declarations: [ DbxSpacerDirective, DbxStyleDirective, - DbxSetStyleDirective + DbxSetStyleDirective, + DbxStyleBodyDirective ], exports: [ DbxSpacerDirective, DbxStyleDirective, - DbxSetStyleDirective + DbxSetStyleDirective, + DbxStyleBodyDirective ] }) export class DbxStyleLayoutModule { } diff --git a/packages/dbx-web/src/lib/layout/style/style.service.ts b/packages/dbx-web/src/lib/layout/style/style.service.ts index a0d788b10..ba5372103 100644 --- a/packages/dbx-web/src/lib/layout/style/style.service.ts +++ b/packages/dbx-web/src/lib/layout/style/style.service.ts @@ -1,9 +1,22 @@ import { Destroyable } from '@dereekb/util'; -import { switchMapMaybeObs } from '@dereekb/rxjs'; -import { BehaviorSubject, Observable, shareReplay } from 'rxjs'; -import { Injectable } from '@angular/core'; +import { switchMapMaybeObs, filterMaybe } from '@dereekb/rxjs'; +import { BehaviorSubject, Observable, combineLatest, distinctUntilChanged, map, switchMap, shareReplay } from 'rxjs'; +import { Inject, Injectable, InjectionToken, Optional } from '@angular/core'; import { Maybe } from '@dereekb/util'; +export const DBX_STYLE_DEFAULT_CONFIG_TOKEN = new InjectionToken('DbxStyleService_DefaultConfig'); + +export interface DbxStyleConfig { + /** + * Root style name. + */ + style: string; + /** + * Suffixes available to this configuration. + */ + suffixes?: Set; +} + /** * Used for managing styles within an app. */ @@ -12,17 +25,77 @@ import { Maybe } from '@dereekb/util'; }) export class DbxStyleService implements Destroyable { - private _style = new BehaviorSubject>>(undefined); - readonly style$ = this._style.pipe(switchMapMaybeObs(), shareReplay(1)); + private _defaultConfig = new BehaviorSubject>(undefined); + private _config = new BehaviorSubject>>(undefined); + private _suffix = new BehaviorSubject>(undefined); + + readonly config$ = this._config.pipe( + switchMap((x) => { + if (x == null) { + return this._defaultConfig; + } else { + return x; + } + }), + filterMaybe(), + distinctUntilChanged(), + shareReplay(1) + ); + + readonly suffix$ = this._suffix.pipe(distinctUntilChanged()); + readonly style$ = this.getStyleWithConfig(this.config$); + + constructor(@Optional() @Inject(DBX_STYLE_DEFAULT_CONFIG_TOKEN) defaultConfig?: DbxStyleConfig) { + this._defaultConfig.next(defaultConfig); + } + + get suffix(): Maybe { + return this._suffix.value; + } + + set suffix(suffix: Maybe) { + this._suffix.next(suffix); + } + + getStyleWithConfig(configObs: Observable): Observable { + return combineLatest([configObs, this.suffix$]).pipe( + map(([config, suffix]) => { + let style = config.style; + + if (suffix != null && config.suffixes) { + const sanitizedSuffix = ((suffix[0] === '-') ? suffix?.slice(1) : suffix); + + if (config.suffixes.has(sanitizedSuffix)) { + style = `${style}-${sanitizedSuffix}`; + } + } + + return style!; + }), + distinctUntilChanged() + ); + } + + toggleDarkSuffix(dark?: Maybe) { + let toggle: boolean = (dark != null) ? dark : this.suffix !== '-dark'; - constructor() { } + if (toggle) { + this.suffix = '-dark'; + } else { + this.suffix = undefined; + } + } + + setDefaultConfig(defaultConfig: DbxStyleConfig) { + this._defaultConfig.next(defaultConfig); + } - setStyle(style: Observable) { - this._style.next(style); + setConfig(config: Observable) { + this._config.next(config); } destroy(): void { - this._style.complete(); + this._config.complete(); } } diff --git a/packages/dbx-web/src/lib/layout/style/style.set.directive.ts b/packages/dbx-web/src/lib/layout/style/style.set.directive.ts index 33d68290c..12fa1c302 100644 --- a/packages/dbx-web/src/lib/layout/style/style.set.directive.ts +++ b/packages/dbx-web/src/lib/layout/style/style.set.directive.ts @@ -1,8 +1,11 @@ +import { splitCommaSeparatedStringToSet } from '@dereekb/util'; +import { Observable, distinctUntilChanged, map, shareReplay } from 'rxjs'; import { filterMaybe } from '@dereekb/rxjs'; -import { BehaviorSubject } from 'rxjs'; -import { Directive, Input, OnDestroy, AfterViewInit, ChangeDetectorRef, OnInit } from '@angular/core'; +import { BehaviorSubject, delay, combineLatest } from 'rxjs'; +import { Directive, Input, OnDestroy, ChangeDetectorRef, OnInit } from '@angular/core'; import { Maybe } from '@dereekb/util'; -import { DbxStyleService } from './style.service'; +import { DbxStyleConfig, DbxStyleService } from './style.service'; +import { AbstractSubscriptionDirective, safeDetectChanges } from '@dereekb/dbx-core'; /** * Used to denote which app style to use for all children below this. @@ -13,15 +16,41 @@ import { DbxStyleService } from './style.service'; selector: '[dbxSetStyle]', host: { 'class': 'dbx-style-root', - '[class]': 'style' + '[class]': 'outputStyle' } }) -export class DbxSetStyleDirective implements OnDestroy, OnInit { +export class DbxSetStyleDirective extends AbstractSubscriptionDirective implements OnDestroy, OnInit { + private _suffixes = new BehaviorSubject>(undefined); private _style = new BehaviorSubject>(undefined); + readonly style$ = this._style.pipe(filterMaybe()); + readonly suffixes$ = this._suffixes.pipe(distinctUntilChanged(), map(splitCommaSeparatedStringToSet)); + + readonly config$: Observable = combineLatest([this.style$, this.suffixes$]).pipe( + map(([style, suffixes]) => ({ style, suffixes })), + shareReplay(1) + ); + + readonly outputStyle$ = this.styleService.getStyleWithConfig(this.config$); + outputStyle: string = ''; + + constructor(readonly styleService: DbxStyleService, readonly cdRef: ChangeDetectorRef) { + super(); + } + + ngOnInit(): void { + this.styleService.setConfig(this.config$); + this.sub = this.outputStyle$.pipe(delay(0)).subscribe((style) => { + this.outputStyle = style; + safeDetectChanges(this.cdRef); + }); + } - constructor(readonly styleService: DbxStyleService, readonly cdRef: ChangeDetectorRef) {} + override ngOnDestroy(): void { + super.ngOnDestroy(); + this._style.complete(); + } @Input('dbxSetStyle') get style(): string { @@ -32,12 +61,15 @@ export class DbxSetStyleDirective implements OnDestroy, OnInit { this._style.next(style); } - ngOnDestroy(): void { - this._style.complete(); + @Input() + get suffixes(): Maybe { + return this._suffixes.value; } - ngOnInit(): void { - this.styleService.setStyle(this.style$); + set suffixes(suffixes: Maybe) { + this._suffixes.next(suffixes); } + + } diff --git a/packages/demo/src/app/container/layout.component.html b/packages/demo/src/app/container/layout.component.html index 5a4576139..7b53cf50d 100644 --- a/packages/demo/src/app/container/layout.component.html +++ b/packages/demo/src/app/container/layout.component.html @@ -1,4 +1,4 @@ -
+
@@ -12,6 +12,9 @@ + + +