Passed
Push — task/hygrogen-react-components ( c486f0 )
by Yonathan
07:32
created

resources/assets/js/components/H2Components/Dialog.tsx   A

Complexity

Total Complexity 1
Complexity/F 0

Size

Lines of Code 185
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 1
eloc 146
mnd 1
bc 1
fnc 0
dl 0
loc 185
rs 10
bpm 0
cpm 0
noi 0
c 0
b 0
f 0
1
import * as React from "react";
2
import {
3
  h2ComponentDialogLoad,
4
  h2ComponentDialogLoadResize,
5
  h2ComponentDialogEnableTrigger,
6
} from "@hydrogen-design-system/system/dist/import/latest/components/dialog/scripts/dialog";
7
import { defineMessages, useIntl } from "react-intl";
8
import Button, { ButtonProps } from "./Button";
9
10
const messages = defineMessages({
11
  closeDialog: {
12
    id: "hydrogen.dialog.close",
13
    defaultMessage: "Close",
14
  },
15
});
16
17
interface DialogContext {
18
  id?: string;
19
}
20
21
const DialogContext = React.createContext<DialogContext>({});
22
23
const useDialog = (): Partial<DialogContext> => {
24
  const context = React.useContext(DialogContext);
25
  if (!context) {
26
    throw new Error("This component must be used within a <Dialog> component.");
27
  }
28
  return context;
29
};
30
31
const Actions: React.FunctionComponent = (props) => {
32
  const { id = "dialog" } = useDialog();
33
  const { children } = props;
34
  return (
35
    <div data-h2-dialog-actions {...props}>
36
      {children}
37
    </div>
38
  );
39
};
40
41
const ActionBtn: React.FunctionComponent<ButtonProps> = (props) => {
42
  const { id = "dialog" } = useDialog();
43
  const { onClick, styling, type, children } = props;
44
  const ref = React.useRef(null);
45
  React.useEffect((): void => {
46
    h2ComponentDialogEnableTrigger("latest", ref.current);
47
  });
48
  return (
49
    <Button
50
      styling={styling}
51
      ref={ref}
52
      data-h2-dialog-trigger={`${id}`}
53
      type={type}
54
      onClick={onClick}
55
      {...props}
56
    >
57
      {children}
58
    </Button>
59
  );
60
};
61
62
const Content: React.FunctionComponent = (props) => {
63
  const { id = "dialog" } = useDialog();
64
  const { children } = props;
65
  return (
66
    <div data-h2-dialog-content id={`${id}Content`} {...props}>
67
      {children}
68
    </div>
69
  );
70
};
71
const ExitBtn: React.FunctionComponent = (props) => {
72
  useDialog();
73
  const intl = useIntl();
74
  const { children } = props;
75
  return (
76
    <Button data-h2-dialog-exit-trigger data-h2-bg-color="b(white, 0)">
77
      <i className="fas fa-times" aria-hidden="true" />
78
      <span data-h2-visibility="hidden">
79
        {intl.formatMessage(messages.closeDialog)}
80
      </span>
81
    </Button>
82
  );
83
};
84
85
interface HeaderProps {
86
  className?: string;
87
}
88
89
const Header: React.FunctionComponent<HeaderProps> = (props) => {
90
  useDialog();
91
  const { className, children } = props;
92
  return (
93
    <div data-h2-dialog-title className={className} {...props}>
94
      {children}
95
    </div>
96
  );
97
};
98
99
interface OverlayProps {
100
  overlay?: string;
101
}
102
103
const Overlay: React.FunctionComponent<OverlayProps> = (props) => {
104
  const { overlay } = props;
105
  return <div data-h2-dialog-overlay={`${overlay || "black, .9"}`} />;
106
};
107
108
const Title: React.FunctionComponent = (props) => {
109
  const { id = "dialog" } = useDialog();
110
  const { children } = props;
111
  return (
112
    <h5 data-h2-focus id={`${id}Title`} {...props}>
113
      {children}
114
    </h5>
115
  );
116
};
117
118
interface TriggerProps {
119
  id: string;
120
}
121
122
const Trigger: React.FunctionComponent<TriggerProps> = (props) => {
123
  const { id, children } = props;
124
  const ref = React.useRef(null);
125
  React.useEffect((): void => {
126
    h2ComponentDialogEnableTrigger("latest", ref.current);
127
  });
128
  return (
129
    <button ref={ref} data-h2-dialog-trigger={`${id}`} type="button" {...props}>
130
      {children}
131
    </button>
132
  );
133
};
134
135
interface DialogComposition {
136
  Actions: React.FunctionComponent;
137
  ActionBtn: React.FunctionComponent<ButtonProps>;
138
  Content: React.FunctionComponent;
139
  ExitBtn: React.FunctionComponent;
140
  Header: React.FunctionComponent<HeaderProps>;
141
  Overlay: React.FunctionComponent<OverlayProps>;
142
  Title: React.FunctionComponent;
143
  Trigger: React.FunctionComponent<TriggerProps>;
144
}
145
146
const Dialog: React.FunctionComponent<DialogContext> & DialogComposition = (
147
  props,
148
) => {
149
  const { id, children } = props;
150
  React.useEffect(() => {
151
    h2ComponentDialogLoad();
152
    h2ComponentDialogLoadResize();
153
    h2ComponentDialogEnableTrigger();
154
  });
155
  return (
156
    <DialogContext.Provider value={props}>
157
      <div
158
        aria-hidden="true"
159
        aria-describedby={`${id}Content`}
160
        aria-labelledby={`${id}Title`}
161
        data-h2-dialog={id}
162
        tabIndex={-1}
163
        role="dialog"
164
      >
165
        <div data-h2-dialog-wrapper {...props}>
166
          {children}
167
        </div>
168
      </div>
169
    </DialogContext.Provider>
170
  );
171
};
172
173
// We expose the children components here, as properties.
174
Dialog.Actions = Actions;
175
Dialog.ActionBtn = ActionBtn;
176
Dialog.Content = Content;
177
Dialog.ExitBtn = ExitBtn;
178
Dialog.Header = Header;
179
Dialog.Overlay = Overlay;
180
Dialog.Title = Title;
181
Dialog.Trigger = Trigger;
182
183
// We only export the root component.
184
export default Dialog;
185