Core

Global config

The library implements a global configuration.
By defining default behaviors within this configuration, redundancy in code is minimized and you ensure consistency in your UI.
Additionally, it supports runtime configuration changes.


How to use

Globally

Use the provideLuiConfig in your main app module or component to store the configuration in the LuiConfigService:

import { LuiConfig, LuiConfigService, provideLuiConfig } from '@lqvrent-workspace/lqvrent-ui/core/config';

const config: LuiConfig = {
  typography: {
    grayScale: 'slate',
    fullWidth: true,
  },
};

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    // ...
  ],
  providers: [
    provideLuiConfig(config),
  ],
  templateUrl: './app.component.html',
})
export class AppComponent {
  constructor() { }
}

Locally

You can use Dependency Injection to reset LUI_CONFIG in a particular component, which will not affect configurations outside of it.

import { LuiConfigService, LUI_CONFIG } from '@lqvrent-workspace/lqvrent-ui/core/config';

@Component({
  providers: [
    // reset local LuiConfigService
    LuiConfigService,
    {
      provide: LUI_CONFIG,
      useValue: {
        typography: {
          grayScale: 'slate',
          fullWidth: true,
        }
      }
    }
  ]
})

Provide template instances

Some components accepts TemplateRef as input.
One of the easiest approaches is to invoke relevant functions from LuiConfigService in the root component:

export class AppComponent implements OnInit {
  @ViewChild('luiIndicatorTpl', { static: true, read: TemplateRef })
  luiIndicator: TemplateRef<void>;

  constructor(
    private readonly luiConfigService: LuiConfigService,
  ) {}

  ngOnInit(): void {
    this.luiConfigService.set('spin', { indicator: this.luiIndicator });
  }
}

However, this violates the separation of concerns principle and causes codes to be bloated in the AppComponent.
To solve this, it is recommended to use a FactoryProvider instead of a ValueProvider:

@Component({
  template: `
    <ng-template #luiIndicatorTpl>
      ...
    </ng-template>
  `
})
export class GlobalTemplatesComponent {
  @ViewChild('luiIndicatorTpl', { static: true, read: TemplateRef })
  luiIndicator: TemplateRef<void>;
}

// The Factory function
const luiConfigFactory = (): LuiConfig => {
  const environmentInjector = inject(EnvironmentInjector);
  const { luiIndicator } = createComponent(GlobalTemplatesComponent, environmentInjector).instance;

  const globalConfig = inject(LuiConfigService, { skipSelf: true }).getConfig();
  const localConfig = {
    spin: {
      indicator: luiIndicator
    }
  };

  const mergedConfig = {
    ...globalConfig,
    ...localConfig
  };
  return mergedConfig;
};

@Component({
  providers: [
    // reset local LuiConfigService
    LuiConfigService,
    {
      provide: LUI_CONFIG,
      useFactory: luiConfigFactory,
    }
  ]
})
export class AppComponent {
  constructor() {}
}

You can also use useFactory to combine the global configuration with the local configuration:

import { LuiConfigService, LUI_CONFIG } from '@lqvrent-workspace/lqvrent-ui/core/config';

@Component({
  providers: [
    // reset local LuiConfigService
    LuiConfigService,
    {
      provide: LUI_CONFIG,
      useFactory: () => {
        // get global LuiConfigService
        const globalConfig = inject(LuiConfigService, { skipSelf: true }).getConfig();
        const localConfig = {
          typography: {
            grayScale: 'slate',
            fullWidth: true,
          }
        };
        // merge local and global config
        const mergedConfig = {
          ...globalConfig,
          ...localConfig
        };
        return mergedConfig;
      },
    }
  ]
})

Change configuration dynamically

You can change the global configuration of a specific component with the set method of LuiConfigService. Example:

import { LuiConfigService } from '@lqvrent-workspace/lqvrent-ui/core/config';

@Component({
  selector: 'app-change-config'
})
export class ChangeConfigComponent {
  constructor(
    private luiConfigService: LuiConfigService,
  ) { }

  changeConfig() {
    this.luiConfigService.set('typography', { grayScale: 'slate' })
  }

  // ...
}

Priority of configurations

For properties that supports configuration, the sequence of priority is the following:

  1. Property directly passed to component/service
  2. Property defined in a configuration by providing LUI_CONFIG
  3. Default configuration value

For example, Typography supports the grayScale configuration property.
First, the library will check if you have defined the property when using the component:

<article lui-typography [luiGrayScale]="slate">
  ...
</article>

If not defined, it will check if you have defined it by providing LUI_CONFIG:

import { LuiConfigService, LUI_CONFIG } from '@lqvrent-workspace/lqvrent-ui/core/config';

// ...
  providers: [
    LuiConfigService,
    {
      provide: LUI_CONFIG,
      useValue: {
        typography: {
          grayScale: 'slate',
        },
        // ...
      }
    }
  ],
// ...

If not provided, the library will use the default configuration, which defines the property with neutral.
You can find the default configurations in this file.


Available parameters

The global configuration object is defined in this file.
You can check the default configuration for each component in this directory.