You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

functions.web.ts 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /* eslint-disable @typescript-eslint/naming-convention */
  2. import { adaptV4Theme, createTheme } from '@mui/material/styles';
  3. import { ITypography, IPalette as Palette1 } from '../ui/types';
  4. import { createColorTokens } from './utils';
  5. declare module '@mui/material/styles' {
  6. // eslint-disable-next-line @typescript-eslint/no-empty-interface
  7. interface Palette extends Palette1 {}
  8. // eslint-disable-next-line @typescript-eslint/no-empty-interface
  9. interface TypographyVariants extends ITypography {}
  10. }
  11. interface ThemeProps {
  12. breakpoints: Object;
  13. colorMap: Object;
  14. colors: Object;
  15. font: Object;
  16. shape: Object;
  17. spacing: Array<number>;
  18. typography: Object;
  19. }
  20. /**
  21. * Creates a MUI theme based on local UI tokens.
  22. *
  23. * @param {Object} arg - The ui tokens.
  24. * @returns {Object}
  25. */
  26. export function createWebTheme({ font, colors, colorMap, shape, spacing, typography, breakpoints }: ThemeProps) {
  27. return createTheme(adaptV4Theme({
  28. spacing,
  29. palette: createColorTokens(colorMap, colors),
  30. shape,
  31. typography: {
  32. // @ts-ignore
  33. font,
  34. ...typography
  35. },
  36. breakpoints
  37. }));
  38. }
  39. /**
  40. * Find the first styled ancestor component of an element.
  41. *
  42. * @param {HTMLElement|null} target - Element to look up.
  43. * @param {string} cssClass - Styled component reference.
  44. * @returns {HTMLElement|null} Ancestor.
  45. */
  46. export const findAncestorByClass = (target: HTMLElement | null, cssClass: string): HTMLElement | null => {
  47. if (!target || target.classList.contains(cssClass)) {
  48. return target;
  49. }
  50. return findAncestorByClass(target.parentElement, cssClass);
  51. };
  52. /**
  53. * Checks if the passed element is visible in the viewport.
  54. *
  55. * @param {Element} element - The element.
  56. * @returns {boolean}
  57. */
  58. export function isElementInTheViewport(element?: Element): boolean {
  59. if (!element) {
  60. return false;
  61. }
  62. if (!document.body.contains(element)) {
  63. return false;
  64. }
  65. const { innerHeight, innerWidth } = window;
  66. const { bottom, left, right, top } = element.getBoundingClientRect();
  67. if (bottom <= innerHeight && top >= 0 && left >= 0 && right <= innerWidth) {
  68. return true;
  69. }
  70. return false;
  71. }
  72. const enterKeyElements = [ 'select', 'textarea', 'summary', 'a' ];
  73. /**
  74. * Informs whether or not the given element does something on its own when pressing the Enter key.
  75. *
  76. * This is useful to correctly submit custom made "forms" that are not using the native form element,
  77. * only when the user is not using an element that needs the enter key to work.
  78. * Note the implementation is incomplete and should be updated as needed if more complex use cases arise
  79. * (for example, the Tabs aria pattern is not handled).
  80. *
  81. * @param {Element} element - The element.
  82. * @returns {boolean}
  83. */
  84. export function operatesWithEnterKey(element: Element): boolean {
  85. if (enterKeyElements.includes(element.tagName.toLowerCase())) {
  86. return true;
  87. }
  88. if (element.tagName.toLowerCase() === 'button' && element.getAttribute('role') === 'button') {
  89. return true;
  90. }
  91. return false;
  92. }