foundation.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /**
  2. * The Semi Foundation / Adapter architecture split was inspired by Material Component For Web. (https://github.com/material-components/material-components-web)
  3. * We re-implemented our own code based on the principle and added more functions we need according to actual needs.
  4. *
  5. */
  6. import log from '../utils/log';
  7. import { noop } from 'lodash';
  8. export type noopFunction = (...args: any) => any;
  9. // eslint-disable-next-line
  10. export interface DefaultAdapter<P = Record<string, any>, S = Record<string, any>> {
  11. getContext(key: string): any;
  12. getContexts(): any;
  13. getProp(key: string): any;
  14. getProps(): P;
  15. getState(key: string): any;
  16. getStates(): S;
  17. setState<K extends keyof S>(s: Pick<S, K>, callback?: any): void;
  18. getCache(c: string): any;
  19. getCaches(): any;
  20. setCache(key: any, value: any): void;
  21. stopPropagation(e: any): void;
  22. persistEvent: (event: any) => void
  23. }
  24. class BaseFoundation<T extends Partial<DefaultAdapter<P, S>>, P = Record<string, any>, S = Record<string, any>> {
  25. /** @return enum{css className} */
  26. /* istanbul ignore next */
  27. static get cssClasses() {
  28. // Classes extending Foundation should implement this method to return an object which exports every
  29. // CSS class the foundation class needs as a property. e.g. {ACTIVE: 'component--active'}
  30. return {};
  31. }
  32. /** @return enum{strings} */
  33. /* istanbul ignore next */
  34. static get strings() {
  35. // Classes extending Foundation should implement this method to return an object which exports all
  36. // semantic strings as constants. e.g. {ARIA_ROLE: 'tablist'}
  37. return {};
  38. }
  39. /** @return enum{numbers} */
  40. /* istanbul ignore next */
  41. static get numbers() {
  42. // Classes extending Foundation should implement this method to return an object which exports all
  43. // of its semantic numbers as constants. e.g. {ANIMATION_DELAY_MS: 350}
  44. return {};
  45. }
  46. static get defaultAdapter() {
  47. return {
  48. getProp: noop,
  49. getProps: noop,
  50. getState: noop,
  51. getStates: noop,
  52. setState: noop,
  53. getContext: noop,
  54. getContexts: noop,
  55. getCache: noop,
  56. setCache: noop,
  57. getCaches: noop,
  58. stopPropagation: noop,
  59. persistEvent: noop,
  60. };
  61. }
  62. _adapter!: T;
  63. constructor(adapter: T) {
  64. this._adapter = { ...BaseFoundation.defaultAdapter, ...adapter };
  65. }
  66. getProp(key: string) {
  67. return this._adapter.getProp(key);
  68. }
  69. getProps(): any {
  70. return this._adapter.getProps() as any;
  71. }
  72. getState(key: string) {
  73. return this._adapter.getState(key);
  74. }
  75. getStates(): any {
  76. return this._adapter.getStates();
  77. }
  78. setState<K extends keyof S>(states: Pick<S, K>, cb?: (...args: any) => void) {
  79. return this._adapter.setState({ ...states }, cb);
  80. }
  81. getContext(key: string) {
  82. return this._adapter.getContext(key);
  83. }
  84. /* istanbul ignore next */
  85. getContexts() {
  86. return this._adapter.getContexts();
  87. }
  88. /* istanbul ignore next */
  89. getCaches() {
  90. return this._adapter.getCaches();
  91. }
  92. getCache(key: string) {
  93. return this._adapter.getCache(key);
  94. }
  95. setCache(key: string, value: any) {
  96. return key && this._adapter.setCache(key, value);
  97. }
  98. stopPropagation(e: any) {
  99. this._adapter.stopPropagation(e);
  100. }
  101. // Determine whether a controlled component
  102. _isControlledComponent(key: string = 'value') { // eslint-disable-line
  103. const props = this.getProps();
  104. const isControlComponent = key in (props as any);
  105. return isControlComponent;
  106. }
  107. // Does the user have incoming props, eg: _isInProps (value)
  108. _isInProps(key: string) { // eslint-disable-line
  109. const props = this.getProps();
  110. return key in (props as any);
  111. }
  112. init(lifecycle?: any) {
  113. // Subclasses should override this method to perform initialization routines (registering events, etc.)
  114. }
  115. destroy() {
  116. // Subclasses should override this method to perform de-initialization routines (de-registering events, etc.)
  117. }
  118. /* istanbul ignore next */
  119. log(text: string, ...rest: any) {
  120. log(text, ...rest);
  121. }
  122. _persistEvent(e: any) {
  123. // only work for react adapter for now
  124. this._adapter.persistEvent(e);
  125. }
  126. }
  127. export default BaseFoundation;