Welcome to mirror list, hosted at ThFree Co, Russian Federation.

applyStyles.js.flow « modifiers « lib « package « popperjs - github.com/gohugoio/hugo-mod-jslibs-dist.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: e976cf0dbb1564598720777563acd099f4f1ceb2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// @flow
import type { Modifier, ModifierArguments } from '../types';
import getNodeName from '../dom-utils/getNodeName';
import { isHTMLElement } from '../dom-utils/instanceOf';

// This modifier takes the styles prepared by the `computeStyles` modifier
// and applies them to the HTMLElements such as popper and arrow

function applyStyles({ state }: ModifierArguments<{||}>) {
  Object.keys(state.elements).forEach((name) => {
    const style = state.styles[name] || {};

    const attributes = state.attributes[name] || {};
    const element = state.elements[name];

    // arrow is optional + virtual elements
    if (!isHTMLElement(element) || !getNodeName(element)) {
      return;
    }

    // Flow doesn't support to extend this property, but it's the most
    // effective way to apply styles to an HTMLElement
    // $FlowFixMe[cannot-write]
    Object.assign(element.style, style);

    Object.keys(attributes).forEach((name) => {
      const value = attributes[name];
      if (value === false) {
        element.removeAttribute(name);
      } else {
        element.setAttribute(name, value === true ? '' : value);
      }
    });
  });
}

function effect({ state }: ModifierArguments<{||}>) {
  const initialStyles = {
    popper: {
      position: state.options.strategy,
      left: '0',
      top: '0',
      margin: '0',
    },
    arrow: {
      position: 'absolute',
    },
    reference: {},
  };

  Object.assign(state.elements.popper.style, initialStyles.popper);
  state.styles = initialStyles;

  if (state.elements.arrow) {
    Object.assign(state.elements.arrow.style, initialStyles.arrow);
  }

  return () => {
    Object.keys(state.elements).forEach((name) => {
      const element = state.elements[name];
      const attributes = state.attributes[name] || {};

      const styleProperties = Object.keys(
        state.styles.hasOwnProperty(name)
          ? state.styles[name]
          : initialStyles[name]
      );

      // Set all values to an empty string to unset them
      const style = styleProperties.reduce((style, property) => {
        style[property] = '';
        return style;
      }, {});

      // arrow is optional + virtual elements
      if (!isHTMLElement(element) || !getNodeName(element)) {
        return;
      }

      Object.assign(element.style, style);

      Object.keys(attributes).forEach((attribute) => {
        element.removeAttribute(attribute);
      });
    });
  };
}

// eslint-disable-next-line import/no-unused-modules
export type ApplyStylesModifier = Modifier<'applyStyles', {||}>;
export default ({
  name: 'applyStyles',
  enabled: true,
  phase: 'write',
  fn: applyStyles,
  effect,
  requires: ['computeStyles'],
}: ApplyStylesModifier);