Style.ts 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import { Options } from '../../types';
  2. import { forOwn } from '@splidejs/utils';
  3. interface Styles {
  4. [ breakpoint: string ]: {
  5. [ selector: string ]: Record<string, string | number>
  6. };
  7. }
  8. /**
  9. * The class for generating styles as a string.
  10. *
  11. * @since 3.0.0
  12. */
  13. export class Style {
  14. /**
  15. * The collection of registered styles categorized by each breakpoint.
  16. */
  17. private readonly styles: Styles = {};
  18. /**
  19. * The ID of the slider.
  20. */
  21. private readonly id: string;
  22. /**
  23. * Holds options.
  24. */
  25. private readonly options: Options;
  26. /**
  27. * The Style constructor.
  28. *
  29. * @param id - A slider ID.
  30. * @param options - Options.
  31. */
  32. constructor( id: string, options: Options ) {
  33. this.id = id;
  34. this.options = options;
  35. }
  36. /**
  37. * Registers a CSS rule.
  38. *
  39. * @param selector - A selector.
  40. * @param prop
  41. * @param value
  42. * @param breakpoint
  43. */
  44. rule( selector: string, prop: string, value: string | number, breakpoint?: string ): void {
  45. breakpoint = breakpoint || 'default';
  46. const selectors = ( this.styles[ breakpoint ] = this.styles[ breakpoint ] || {} );
  47. const styles = ( selectors[ selector ] = selectors[ selector ] || {} );
  48. styles[ prop ] = value;
  49. }
  50. /**
  51. * Builds styles as a single string.
  52. *
  53. * @return Built styles.
  54. */
  55. build(): string {
  56. let css = '';
  57. if ( this.styles.default ) {
  58. css += this.buildSelectors( this.styles.default );
  59. }
  60. Object.keys( this.styles )
  61. .sort( ( n, m ) => this.options.mediaQuery === 'min' ? +n - +m : +m - +n )
  62. .forEach( breakpoint => {
  63. if ( breakpoint !== 'default' ) {
  64. css += `@media screen and (max-width: ${ breakpoint }px) {`;
  65. css += this.buildSelectors( this.styles[ breakpoint ] );
  66. css += `}`;
  67. }
  68. } );
  69. return css;
  70. }
  71. /**
  72. * Builds styles for each breakpoint.
  73. *
  74. * @param selectors - An object with styles.
  75. *
  76. * @return Built styles.
  77. */
  78. private buildSelectors( selectors: Record<string, Record<string, string | number>> ): string {
  79. let css = '';
  80. forOwn( selectors, ( styles, selector ) => {
  81. css += `${ `#${ this.id } ${ selector }`.trim() } {`;
  82. forOwn( styles, ( value, prop ) => {
  83. if ( value || value === 0 ) {
  84. css += `${ prop }: ${ value };`;
  85. }
  86. } );
  87. css += '}';
  88. } );
  89. return css;
  90. }
  91. }