@hlf-fe/pulmo-ui 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/README.md +21 -54
  2. package/dist/components/buttons/button/button.js +1 -1
  3. package/dist/components/buttons/button/button.stories.js +6 -1
  4. package/dist/components/buttons/loading-button/loading-button.d.ts +14 -0
  5. package/dist/components/buttons/loading-button/loading-button.js +26 -0
  6. package/dist/components/buttons/loading-button/loading-button.stories.d.ts +7 -0
  7. package/dist/components/buttons/loading-button/loading-button.stories.js +23 -0
  8. package/dist/components/buttons/text-button/text-button.d.ts +20 -0
  9. package/dist/components/buttons/text-button/text-button.js +61 -0
  10. package/dist/components/buttons/text-button/text-button.stories.d.ts +6 -0
  11. package/dist/components/buttons/text-button/text-button.stories.js +16 -0
  12. package/dist/components/decorator/decorator.d.ts +7 -0
  13. package/dist/components/decorator/decorator.js +13 -0
  14. package/dist/components/feedback/alert/alert.d.ts +17 -0
  15. package/dist/components/feedback/alert/alert.js +68 -0
  16. package/dist/components/feedback/alert/alert.stories.d.ts +6 -0
  17. package/dist/components/feedback/alert/alert.stories.js +23 -0
  18. package/dist/components/icons/chevron-left-icon/chevron-left-icon.d.ts +7 -0
  19. package/dist/components/icons/chevron-left-icon/chevron-left-icon.js +3 -0
  20. package/dist/components/icons/chevron-left-icon/chevron-left-icon.stories.d.ts +6 -0
  21. package/dist/components/icons/chevron-left-icon/chevron-left-icon.stories.js +14 -0
  22. package/dist/components/icons/chevron-right-icon/chevron-right-icon.d.ts +7 -0
  23. package/dist/components/icons/chevron-right-icon/chevron-right-icon.js +3 -0
  24. package/dist/components/icons/chevron-right-icon/chevron-right-icon.stories.d.ts +6 -0
  25. package/dist/components/icons/chevron-right-icon/chevron-right-icon.stories.js +14 -0
  26. package/dist/components/icons/close-icon/close-icon.d.ts +12 -0
  27. package/dist/components/icons/close-icon/close-icon.js +9 -0
  28. package/dist/components/icons/close-icon/close-icon.stories.d.ts +6 -0
  29. package/dist/components/icons/close-icon/close-icon.stories.js +16 -0
  30. package/dist/components/icons/exclamation-mark-icon/exclamation-mark-icon.d.ts +3 -0
  31. package/dist/components/icons/exclamation-mark-icon/exclamation-mark-icon.js +3 -0
  32. package/dist/components/icons/exclamation-mark-icon/exclamation-mark-icon.stories.d.ts +6 -0
  33. package/dist/components/icons/exclamation-mark-icon/exclamation-mark-icon.stories.js +16 -0
  34. package/dist/components/icons/loading-spinner/loading-spinner.d.ts +20 -0
  35. package/dist/components/icons/loading-spinner/loading-spinner.js +32 -0
  36. package/dist/components/icons/loading-spinner/loading-spinner.stories.d.ts +6 -0
  37. package/dist/components/icons/loading-spinner/loading-spinner.stories.js +18 -0
  38. package/dist/components/icons/search-icon/search-icon.d.ts +5 -0
  39. package/dist/components/icons/search-icon/search-icon.js +3 -0
  40. package/dist/components/icons/search-icon/search-icon.stories.d.ts +6 -0
  41. package/dist/components/icons/search-icon/search-icon.stories.js +18 -0
  42. package/dist/components/icons/toggable-chevron/toggable-chevron.d.ts +12 -0
  43. package/dist/components/icons/toggable-chevron/toggable-chevron.js +20 -0
  44. package/dist/components/icons/toggable-chevron/toggable-chevron.stories.d.ts +7 -0
  45. package/dist/components/icons/toggable-chevron/toggable-chevron.stories.js +21 -0
  46. package/dist/components/icons/toggable-plus-minus-icon/toggable-plus-minus-icon.d.ts +6 -0
  47. package/dist/components/icons/toggable-plus-minus-icon/toggable-plus-minus-icon.js +13 -0
  48. package/dist/components/icons/toggable-plus-minus-icon/toggable-plus-minus-icon.stories.d.ts +7 -0
  49. package/dist/components/icons/toggable-plus-minus-icon/toggable-plus-minus-icon.stories.js +21 -0
  50. package/dist/components/icons/warning-icon/warning-icon.d.ts +3 -0
  51. package/dist/components/icons/warning-icon/warning-icon.js +3 -0
  52. package/dist/components/icons/warning-icon/warning-icon.stories.d.ts +6 -0
  53. package/dist/components/icons/warning-icon/warning-icon.stories.js +16 -0
  54. package/dist/components/inputs/dropdown/dropdown-list-item.d.ts +6 -0
  55. package/dist/components/inputs/dropdown/dropdown-list-item.js +33 -0
  56. package/dist/components/inputs/dropdown/dropdown.d.ts +13 -0
  57. package/dist/components/inputs/dropdown/dropdown.js +109 -0
  58. package/dist/components/inputs/dropdown/dropdown.stories.d.ts +7 -0
  59. package/dist/components/inputs/dropdown/dropdown.stories.js +84 -0
  60. package/dist/components/inputs/form-error/form-error.d.ts +11 -0
  61. package/dist/components/inputs/form-error/form-error.js +16 -0
  62. package/dist/components/inputs/form-error/form-error.stories.d.ts +6 -0
  63. package/dist/components/inputs/form-error/form-error.stories.js +22 -0
  64. package/dist/components/inputs/form-label/form-label.d.ts +7 -0
  65. package/dist/components/inputs/form-label/form-label.js +12 -0
  66. package/dist/components/inputs/form-label/form-label.stories.d.ts +6 -0
  67. package/dist/components/inputs/form-label/form-label.stories.js +16 -0
  68. package/dist/components/inputs/text-field/text-field.d.ts +32 -0
  69. package/dist/components/inputs/text-field/text-field.js +65 -0
  70. package/dist/components/inputs/text-field/text-field.stories.d.ts +11 -0
  71. package/dist/components/inputs/text-field/text-field.stories.js +51 -0
  72. package/dist/components/layout/accordion/accordion.d.ts +13 -0
  73. package/dist/components/layout/accordion/accordion.js +115 -0
  74. package/dist/components/layout/accordion/accordion.stories.d.ts +6 -0
  75. package/dist/components/layout/accordion/accordion.stories.js +14 -0
  76. package/dist/components/layout/container/container.d.ts +10 -0
  77. package/dist/components/layout/container/container.js +19 -0
  78. package/dist/components/layout/container/container.stories.d.ts +9 -0
  79. package/dist/components/layout/container/container.stories.js +47 -0
  80. package/dist/components/layout/image/image.d.ts +22 -0
  81. package/dist/components/layout/image/image.js +27 -0
  82. package/dist/components/layout/image/image.stories.d.ts +6 -0
  83. package/dist/components/layout/image/image.stories.js +33 -0
  84. package/dist/components/modules/email-signup-form/email-signup-form.d.ts +16 -0
  85. package/dist/components/modules/email-signup-form/email-signup-form.js +63 -0
  86. package/dist/components/modules/email-signup-form/email-signup-form.stories.d.ts +9 -0
  87. package/dist/components/modules/email-signup-form/email-signup-form.stories.js +51 -0
  88. package/dist/components/modules/entry-list/entry-list.d.ts +27 -0
  89. package/dist/components/modules/entry-list/entry-list.js +54 -0
  90. package/dist/components/modules/entry-list/entry-list.stories.d.ts +6 -0
  91. package/dist/components/modules/entry-list/entry-list.stories.js +14 -0
  92. package/dist/components/navigation/pagination/pagination.d.ts +12 -0
  93. package/dist/components/navigation/pagination/pagination.js +114 -0
  94. package/dist/components/navigation/pagination/pagination.stories.d.ts +6 -0
  95. package/dist/components/navigation/pagination/pagination.stories.js +21 -0
  96. package/dist/constants/general.d.ts +4 -0
  97. package/dist/constants/general.js +5 -0
  98. package/dist/hoc/withDefaultTheme.d.ts +1 -1
  99. package/dist/hoc/withDefaultTheme.js +4 -8
  100. package/dist/index.d.ts +40 -2
  101. package/dist/index.js +42 -2
  102. package/dist/styles/mixins.js +8 -4
  103. package/dist/styles/theme.d.ts +11 -9
  104. package/dist/styles/theme.js +12 -11
  105. package/package.json +78 -67
  106. package/dist/App.d.ts +0 -3
  107. package/dist/App.js +0 -10
  108. package/dist/main.d.ts +0 -1
  109. package/dist/main.js +0 -6
  110. package/dist/stories/Button.d.ts +0 -14
  111. package/dist/stories/Button.js +0 -20
  112. package/dist/stories/Button.stories.d.ts +0 -23
  113. package/dist/stories/Button.stories.js +0 -44
  114. package/dist/stories/Header.d.ts +0 -12
  115. package/dist/stories/Header.js +0 -4
  116. package/dist/stories/Header.stories.d.ts +0 -18
  117. package/dist/stories/Header.stories.js +0 -26
  118. package/dist/stories/Page.d.ts +0 -3
  119. package/dist/stories/Page.js +0 -7
  120. package/dist/stories/Page.stories.d.ts +0 -12
  121. package/dist/stories/Page.stories.js +0 -24
  122. package/dist/styles/styles/mixins/theme-mixins.d.ts +0 -5
  123. package/dist/styles/styles/mixins/theme-mixins.js +0 -37
  124. package/dist/styles/styles/mixins/units.d.ts +0 -3
  125. package/dist/styles/styles/mixins/units.js +0 -3
  126. package/dist/styles/styles/mixins.d.ts +0 -48
  127. package/dist/styles/styles/mixins.js +0 -336
  128. package/dist/styles/styles/theme.d.ts +0 -135
  129. package/dist/styles/styles/theme.js +0 -77
  130. package/dist/styles/types.d.ts +0 -3
  131. package/dist/styles/types.js +0 -1
  132. package/dist/styles/withDefaultTheme.d.ts +0 -1
  133. package/dist/styles/withDefaultTheme.js +0 -12
@@ -0,0 +1,65 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, } from "react";
3
+ import { FormError } from "../../../components/inputs/form-error/form-error";
4
+ import { rem } from "../../../styles/units";
5
+ import styled, { css } from "styled-components";
6
+ const variantInputWrapperStyles = {
7
+ default: css `
8
+ height: ${rem(56)};
9
+ `,
10
+ rounded: css `
11
+ height: ${rem(48)};
12
+ `,
13
+ };
14
+ const variantInputStyles = {
15
+ default: css `
16
+ border-radius: ${rem(5)};
17
+ `,
18
+ rounded: css `
19
+ border-radius: ${rem(24)};
20
+ `,
21
+ };
22
+ export const TextField = forwardRef(({ dataTest, value, name, type = "text", variant = "default", placeholder, onChange, onBlur, onFocus, onKeyDown, className, ariaLabel, ariaDescribedBy, register, errors, pattern, inputMode = "text", startAdornment, endAdornment, }, ref) => {
23
+ return (_jsxs(InputContainer, { children: [_jsxs(InputWrapper, { className: className, variant: variant, startAdornment: startAdornment, children: [startAdornment && _jsx(StartAdornment, { children: startAdornment }), _jsx(StyledInput, { "data-test": dataTest, variant: variant, value: value, ref: ref, type: type, id: name, name: name, placeholder: placeholder, onChange: onChange, onBlur: onBlur, onFocus: onFocus, onKeyDown: onKeyDown, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, inputMode: inputMode, pattern: pattern, startAdornment: startAdornment, ...register }), endAdornment && _jsx(EndAdornment, { children: endAdornment })] }), errors && name && _jsx(FormError, { errors: errors, name: name })] }));
24
+ });
25
+ TextField.displayName = "TextField";
26
+ const InputContainer = styled.div `
27
+ width: 100%;
28
+ `;
29
+ const InputWrapper = styled.div `
30
+ display: flex;
31
+ position: relative;
32
+ ${({ variant }) => variantInputWrapperStyles[variant]};
33
+ `;
34
+ const StyledInput = styled.input `
35
+ width: 100%;
36
+ font-family: ${({ theme }) => theme.valueRegular};
37
+ font-size: ${rem(16)};
38
+ background-color: ${({ theme }) => theme.white};
39
+ border: ${rem(1)} solid ${({ theme }) => theme.grayTransparent};
40
+ padding-right: ${rem(16)};
41
+
42
+ &:focus {
43
+ outline: none;
44
+ border: ${rem(1)} solid ${({ theme }) => theme.gray};
45
+ }
46
+
47
+ ${({ variant }) => variantInputStyles[variant]};
48
+ padding-left: ${({ startAdornment }) => (startAdornment ? rem(40) : rem(20))};
49
+ `;
50
+ const StartAdornment = styled.div `
51
+ position: absolute;
52
+ display: flex;
53
+ align-items: center;
54
+ top: 0;
55
+ left: ${rem(10)};
56
+ height: 100%;
57
+ `;
58
+ const EndAdornment = styled.div `
59
+ position: absolute;
60
+ display: flex;
61
+ align-items: center;
62
+ top: 0;
63
+ right: ${rem(15)};
64
+ height: 100%;
65
+ `;
@@ -0,0 +1,11 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { TextField } from "./text-field";
3
+ declare const meta: Meta<typeof TextField>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof TextField>;
6
+ export declare const Default: Story;
7
+ export declare const Rounded: Story;
8
+ export declare const DefaultWithStartAdornment: Story;
9
+ export declare const DefaultWithEndAdornment: Story;
10
+ export declare const RoundedWithStartAdornment: Story;
11
+ export declare const RoundedWithEndAdornment: Story;
@@ -0,0 +1,51 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Decorator } from "../../../components/decorator/decorator";
3
+ import { SearchIcon } from "../../../components/icons/search-icon/search-icon";
4
+ import { TextField } from "./text-field";
5
+ const meta = {
6
+ title: "Inputs/TextField",
7
+ component: TextField,
8
+ decorators: [
9
+ (Story) => (_jsx(Decorator, { maxWidth: "250px", children: _jsx(Story, {}) })),
10
+ ],
11
+ };
12
+ export default meta;
13
+ export const Default = {
14
+ args: {
15
+ placeholder: "placeholder",
16
+ },
17
+ };
18
+ export const Rounded = {
19
+ args: {
20
+ variant: "rounded",
21
+ placeholder: "placeholder",
22
+ },
23
+ };
24
+ export const DefaultWithStartAdornment = {
25
+ args: {
26
+ variant: "default",
27
+ placeholder: "placeholder",
28
+ startAdornment: _jsx(SearchIcon, { width: 26, height: 26 }),
29
+ },
30
+ };
31
+ export const DefaultWithEndAdornment = {
32
+ args: {
33
+ variant: "default",
34
+ placeholder: "placeholder",
35
+ endAdornment: _jsx(SearchIcon, { width: 26, height: 26 }),
36
+ },
37
+ };
38
+ export const RoundedWithStartAdornment = {
39
+ args: {
40
+ variant: "rounded",
41
+ placeholder: "placeholder",
42
+ startAdornment: _jsx(SearchIcon, { width: 26, height: 26 }),
43
+ },
44
+ };
45
+ export const RoundedWithEndAdornment = {
46
+ args: {
47
+ variant: "rounded",
48
+ placeholder: "placeholder",
49
+ endAdornment: _jsx(SearchIcon, { width: 26, height: 26 }),
50
+ },
51
+ };
@@ -0,0 +1,13 @@
1
+ import { ReactNode } from "react";
2
+ export type AccordionItemProps = {
3
+ heading: string;
4
+ panelId: string;
5
+ regionId: string;
6
+ initiallyExpanded?: boolean;
7
+ children?: ReactNode;
8
+ headingLevel?: "h2" | "h3";
9
+ };
10
+ export declare const AccordionItem: ({ heading, headingLevel, panelId, regionId, initiallyExpanded, children, }: AccordionItemProps) => import("react/jsx-runtime").JSX.Element;
11
+ export declare const Accordion: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
12
+ disabled?: boolean;
13
+ }>> & string;
@@ -0,0 +1,115 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from "react";
3
+ import styled, { css } from "styled-components";
4
+ import { media } from "../../../styles/mixins";
5
+ import { rem } from "../../../styles/units";
6
+ import { ToggablePlusMinusIcon } from "../../../components/icons/toggable-plus-minus-icon/toggable-plus-minus-icon";
7
+ var PanelState;
8
+ (function (PanelState) {
9
+ PanelState[PanelState["CLOSED"] = 0] = "CLOSED";
10
+ PanelState[PanelState["OPENING"] = 1] = "OPENING";
11
+ PanelState[PanelState["OPENED"] = 2] = "OPENED";
12
+ PanelState[PanelState["CLOSING"] = 3] = "CLOSING";
13
+ })(PanelState || (PanelState = {}));
14
+ export const AccordionItem = ({ heading, headingLevel, panelId, regionId, initiallyExpanded, children, }) => {
15
+ const [height, setHeight] = useState(0);
16
+ const [panelState, setPanelState] = useState(!initiallyExpanded ? PanelState.CLOSED : PanelState.OPENING);
17
+ const ref = useRef(null);
18
+ useEffect(() => {
19
+ if (panelState === PanelState.OPENING ||
20
+ panelState === PanelState.CLOSING) {
21
+ setHeight(ref.current?.scrollHeight ?? 0);
22
+ }
23
+ }, [panelState]);
24
+ useEffect(() => {
25
+ if (height > 0 && panelState === PanelState.CLOSING) {
26
+ setHeight(0);
27
+ }
28
+ }, [height, panelState]);
29
+ const onAnimationComplete = () => {
30
+ if (panelState === PanelState.OPENING) {
31
+ setPanelState(PanelState.OPENED);
32
+ }
33
+ else if (panelState === PanelState.CLOSING) {
34
+ setPanelState(PanelState.CLOSED);
35
+ }
36
+ };
37
+ const togglePanel = () => {
38
+ const isClosed = panelState === PanelState.CLOSED || panelState === PanelState.CLOSING;
39
+ setPanelState(isClosed ? PanelState.OPENING : PanelState.CLOSING);
40
+ };
41
+ const isExpanded = panelState !== PanelState.CLOSED;
42
+ return (_jsxs(AccordionPanel, { children: [_jsx(StyledHeading, { as: headingLevel, children: _jsxs(StyledButton, { "data-test": `accordion-header${isExpanded ? "-expanded" : ""}`, id: panelId, "aria-expanded": isExpanded, "aria-controls": regionId, onClick: togglePanel, children: [_jsx(Text, { children: heading }), _jsx(StyledToggablePlusMinusIcon, { isOpen: isExpanded })] }) }), _jsx(AccodrionContent, { "data-test": "accordion-content", ref: ref, id: regionId, role: "region", "aria-labelledby": panelId, contentHeight: height, useAutoHeight: panelState === PanelState.OPENED, onTransitionEnd: onAnimationComplete, children: _jsx(Content, { hidden: !isExpanded, children: children }) })] }));
43
+ };
44
+ const AccodrionContent = styled.div `
45
+ overflow: hidden;
46
+ transition: height 0.3s ease-in-out;
47
+ height: ${({ contentHeight }) => `${contentHeight}px`};
48
+ height: ${({ useAutoHeight }) => useAutoHeight && "auto"};
49
+ `;
50
+ const Content = styled.div `
51
+ padding: ${rem(15)} 0;
52
+ padding-top: 0;
53
+
54
+ ${media.M `
55
+ padding: ${rem(25)} 0;
56
+ padding-top: 0;
57
+ `}
58
+ `;
59
+ const AccordionPanel = styled.div `
60
+ position: relative;
61
+ `;
62
+ const StyledHeading = styled.h2 `
63
+ position: relative;
64
+ z-index: 1;
65
+ margin: 0;
66
+ border-top: 1px solid rgba(51, 51, 51, 0.2);
67
+ `;
68
+ const Text = styled.span `
69
+ font-size: ${rem(18)};
70
+ cursor: pointer;
71
+ ${media.M `
72
+ font-size: ${rem(20)};
73
+ `}
74
+ `;
75
+ const StyledButton = styled.button `
76
+ width: 100%;
77
+ display: flex;
78
+ align-items: center;
79
+ padding: 0;
80
+ margin: 0;
81
+ text-align: left;
82
+ font-weight: 400;
83
+ line-height: ${rem(24)};
84
+ font-size: ${rem(16)};
85
+ padding: ${rem(15)} 0;
86
+ background-color: transparent;
87
+ border: none;
88
+
89
+ ${({ theme }) => css `
90
+ color: ${theme.blackLight};
91
+ font-family: ${theme.valueBold};
92
+ `}
93
+
94
+ ${media.M `
95
+ line-height: ${rem(26)};
96
+ font-size: ${rem(18)};
97
+ padding: ${rem(25)} 0;
98
+ `}
99
+ `;
100
+ const StyledToggablePlusMinusIcon = styled(ToggablePlusMinusIcon) `
101
+ cursor: pointer;
102
+ margin-left: auto;
103
+ margin-right: ${rem(10)};
104
+ `;
105
+ export const Accordion = styled.div `
106
+ border-bottom: 1px solid rgba(51, 51, 51, 0.2);
107
+ width: 100%;
108
+
109
+ ${({ disabled }) => disabled &&
110
+ css `
111
+ pointer-events: none;
112
+ opacity: 0.5;
113
+ user-select: none;
114
+ `};
115
+ `;
@@ -0,0 +1,6 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Accordion } from "./accordion";
3
+ declare const meta: Meta<typeof Accordion>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof Accordion>;
6
+ export declare const Default: Story;
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Accordion, AccordionItem } from "./accordion";
3
+ import { Decorator } from "../../../components/decorator/decorator";
4
+ const meta = {
5
+ title: "Layout/Accordion",
6
+ component: Accordion,
7
+ decorators: [
8
+ (Story) => (_jsx(Decorator, { maxWidth: "800px", children: _jsx(Story, {}) })),
9
+ ],
10
+ };
11
+ export default meta;
12
+ export const Default = {
13
+ render: () => (_jsxs(Accordion, { children: [_jsx(AccordionItem, { heading: "In volutpat est eu dolor efficitur", panelId: "1", regionId: "1", children: "Aliquam erat volutpat. Nulla facilisi. Vestibulum eget ullamcorper elit. Praesent mattis arcu ante, in gravida eros pharetra sit amet. Praesent mattis arcu ante, in gravida eros pharetra sit amet. Etiam ac enim lorem. Proin euismod vulputate faucibus." }), _jsx(AccordionItem, { heading: "Vestibulum eget ullamcorper,\r\n Praesent mattis arcu ante", panelId: "2", regionId: "2", children: "Aliquam erat volutpat. Nulla facilisi. Vestibulum eget ullamcorper, Praesent mattis arcu ante, in gravida eros pharetra sit amet. Etiam ac enim lorem. Proin euismod vulputate faucibus." }), _jsx(AccordionItem, { heading: "In volutpat est eu dolor efficitur", panelId: "3", regionId: "3", children: "Aliquam erat volutpat. Nulla facilisi. Vestibulum eget ullamcorper elit. Praesent mattis arcu ante, in gravida eros pharetra sit amet. Praesent mattis arcu ante, in gravida eros pharetra sit amet. Etiam ac enim lorem. Proin euismod vulputate faucibus." }), _jsx(AccordionItem, { heading: "Vestibulum eget ullamcorper,\r\n Praesent mattis arcu ante", panelId: "4", regionId: "4", children: "Aliquam erat volutpat. Nulla facilisi. Vestibulum eget ullamcorper, Praesent mattis arcu ante, in gravida eros pharetra sit amet. Etiam ac enim lorem. Proin euismod vulputate faucibus." })] })),
14
+ };
@@ -0,0 +1,10 @@
1
+ import { ReactNode, CSSProperties } from "react";
2
+ type Sizes = "sm" | "lg" | "xl";
3
+ type CSSTypes = Pick<CSSProperties, "position" | "display">;
4
+ export type ContainerProps = {
5
+ children: ReactNode;
6
+ maxWidth?: Sizes;
7
+ className?: string;
8
+ } & CSSTypes;
9
+ export declare const Container: ({ children, className, maxWidth, position, display, }: ContainerProps) => import("react/jsx-runtime").JSX.Element;
10
+ export {};
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { siteWidthRow, siteWidthRowXL, siteWidthRowS } from "../../../styles/mixins";
3
+ import styled from "styled-components";
4
+ const MAX_WIDTH = {
5
+ sm: siteWidthRowS,
6
+ lg: siteWidthRow,
7
+ xl: siteWidthRowXL,
8
+ };
9
+ const getMaxWidth = (size) => {
10
+ return MAX_WIDTH?.[size];
11
+ };
12
+ export const Container = ({ children, className, maxWidth = "lg", position = "static", display = "block", }) => {
13
+ return (_jsx(Div, { className: className, maxWidth: getMaxWidth(maxWidth), display: display, position: position, children: children }));
14
+ };
15
+ const Div = styled.div `
16
+ ${({ maxWidth }) => maxWidth};
17
+ display: ${({ display }) => display};
18
+ position: ${({ position }) => position};
19
+ `;
@@ -0,0 +1,9 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Container } from "./container";
3
+ declare const meta: Meta<typeof Container>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof Container>;
6
+ export declare const Default: Story;
7
+ export declare const Small: Story;
8
+ export declare const Large: Story;
9
+ export declare const ExtraLarge: Story;
@@ -0,0 +1,47 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Container } from "./container";
3
+ import styled from "styled-components";
4
+ import { rem } from "../../../styles/units";
5
+ const meta = {
6
+ title: "Layout/Container",
7
+ component: Container,
8
+ decorators: [(Story) => _jsx(Story, {})],
9
+ };
10
+ export default meta;
11
+ const PlaceholderBlock = styled.div `
12
+ display: flex;
13
+ justify-content: center;
14
+ align-items: center;
15
+ background-color: #d6ebe3;
16
+ width: 100%;
17
+ height: ${rem(300)};
18
+ color: #333;
19
+ border-radius: ${rem(10)};
20
+ `;
21
+ const Heading = styled.h1 `
22
+ font-size: ${rem(52)};
23
+ `;
24
+ export const Default = {
25
+ args: {
26
+ maxWidth: "lg",
27
+ children: (_jsx(PlaceholderBlock, { children: _jsx(Heading, { children: "lg" }) })),
28
+ },
29
+ };
30
+ export const Small = {
31
+ args: {
32
+ maxWidth: "sm",
33
+ children: (_jsx(PlaceholderBlock, { children: _jsx(Heading, { children: "sm" }) })),
34
+ },
35
+ };
36
+ export const Large = {
37
+ args: {
38
+ maxWidth: "lg",
39
+ children: (_jsx(PlaceholderBlock, { children: _jsx(Heading, { children: "lg" }) })),
40
+ },
41
+ };
42
+ export const ExtraLarge = {
43
+ args: {
44
+ maxWidth: "xl",
45
+ children: (_jsx(PlaceholderBlock, { children: _jsx(Heading, { children: "xl" }) })),
46
+ },
47
+ };
@@ -0,0 +1,22 @@
1
+ import { IGatsbyImageData } from "gatsby-plugin-image";
2
+ export type ImageProps = {
3
+ image: {
4
+ description: string;
5
+ gatsbyImageData: IGatsbyImageData;
6
+ url?: string;
7
+ extension?: string;
8
+ };
9
+ imageSmall?: {
10
+ description?: string;
11
+ gatsbyImageData?: IGatsbyImageData;
12
+ };
13
+ className?: string;
14
+ imgClassName?: string;
15
+ width?: string;
16
+ height?: string;
17
+ bpSmallDevice?: number;
18
+ objectPosition?: string;
19
+ onLoad?: () => void;
20
+ loading?: "eager" | "lazy";
21
+ };
22
+ export declare const Image: ({ image, imageSmall, className, imgClassName, width, height, bpSmallDevice, objectPosition, loading, onLoad, }: ImageProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { GatsbyImage, getImage, withArtDirection, } from "gatsby-plugin-image";
3
+ import { BREAKPOINT_VALUES } from "../../../styles/theme";
4
+ import { em } from "../../../styles/units";
5
+ const SVG = "svg";
6
+ export const Image = ({ image, imageSmall, className = "", imgClassName = "", width = "auto", height = "auto", bpSmallDevice = BREAKPOINT_VALUES.M, objectPosition = "50% 50%", loading = "lazy", onLoad, }) => {
7
+ const desc = image?.description;
8
+ const contentType = image?.extension;
9
+ const fileUrl = image?.url;
10
+ const gatsbyImageData = getImage(image?.gatsbyImageData);
11
+ const gatsbyImageDataSmall = imageSmall?.gatsbyImageData
12
+ ? getImage(imageSmall?.gatsbyImageData)
13
+ : false;
14
+ const images = gatsbyImageData && gatsbyImageDataSmall
15
+ ? withArtDirection(gatsbyImageData, [
16
+ {
17
+ media: `(max-width: ${em(bpSmallDevice - 1)})`,
18
+ image: gatsbyImageDataSmall,
19
+ },
20
+ ])
21
+ : gatsbyImageData;
22
+ if (contentType === SVG && fileUrl)
23
+ return (_jsx("img", { width: width, height: height, className: className, src: fileUrl, alt: desc }));
24
+ if (images)
25
+ return (_jsx(GatsbyImage, { className: className, imgClassName: imgClassName, image: images, loading: loading, alt: desc ?? "", objectPosition: objectPosition, onLoad: onLoad }));
26
+ return null;
27
+ };
@@ -0,0 +1,6 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Image } from "./image";
3
+ declare const meta: Meta<typeof Image>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof Image>;
6
+ export declare const Default: Story;
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Image } from "./image";
3
+ import { Decorator } from "../../../components/decorator/decorator";
4
+ // @ts-ignore
5
+ import placeholderImage from "assets/placeholder-img.png";
6
+ const mockGatsbyImageData = {
7
+ layout: "constrained",
8
+ images: {
9
+ fallback: {
10
+ src: placeholderImage,
11
+ srcSet: `${placeholderImage} 1x`,
12
+ sizes: "(min-width: 600px) 600px, 100vw",
13
+ },
14
+ },
15
+ width: 600,
16
+ height: 400,
17
+ };
18
+ const meta = {
19
+ title: "Layout/Image",
20
+ component: Image,
21
+ decorators: [
22
+ (Story) => (_jsx(Decorator, { children: _jsx(Story, {}) })),
23
+ ],
24
+ };
25
+ export default meta;
26
+ export const Default = {
27
+ args: {
28
+ image: {
29
+ description: "Exempelbild",
30
+ gatsbyImageData: mockGatsbyImageData,
31
+ },
32
+ },
33
+ };
@@ -0,0 +1,16 @@
1
+ export type EmailSignupFormProps = {
2
+ heading?: string;
3
+ description?: string;
4
+ localeText: {
5
+ emailLabel: string;
6
+ sendButtonText: string;
7
+ successMessage?: string;
8
+ errorMessage?: string;
9
+ };
10
+ onSubmit: (email: string) => void;
11
+ onReset?: () => void;
12
+ loading: boolean;
13
+ success: boolean;
14
+ failed: boolean;
15
+ };
16
+ export declare const EmailSignupForm: ({ heading, description, localeText, onSubmit, loading, success, failed, }: EmailSignupFormProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,63 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useForm } from "react-hook-form";
3
+ import { yupResolver } from "@hookform/resolvers/yup";
4
+ import * as yup from "yup";
5
+ import { TextField } from "../../../components/inputs/text-field/text-field";
6
+ import { LoadingButton } from "../../../components/buttons/loading-button/loading-button";
7
+ import { FormLabel } from "../../../components/inputs/form-label/form-label";
8
+ import { Alert } from "../../../components/feedback/alert/alert";
9
+ import styled from "styled-components";
10
+ import { media } from "../../../styles/mixins";
11
+ import { rem } from "../../../styles/units";
12
+ const schema = yup.object({
13
+ email: yup.string().email().required(),
14
+ });
15
+ export const EmailSignupForm = ({ heading, description, localeText, onSubmit, loading, success, failed, }) => {
16
+ const { emailLabel, sendButtonText, successMessage, errorMessage } = localeText;
17
+ const { register, handleSubmit, formState: { errors }, } = useForm({
18
+ mode: "onChange",
19
+ resolver: yupResolver(schema),
20
+ });
21
+ return (_jsx(Container, { children: !success ? (_jsxs(Box, { children: [heading && _jsx(Heading, { children: heading }), description && _jsx(Text, { children: description }), _jsx(FormLabel, { htmlFor: "email", children: emailLabel }), _jsxs(TextFieldAndButton, { children: [_jsx(TextField, { type: "email", name: "email", errors: errors, register: register("email") }), _jsx(StyledLoadingButton, { onClick: handleSubmit(({ email }) => onSubmit(email)), children: sendButtonText, disabled: loading, loading: loading, btnSize: "l", fullWidthMobile: true })] }), failed && _jsx(StyledAlert, { severity: "error", children: errorMessage })] })) : (_jsx(BoxCenter, { children: _jsx(Heading, { children: successMessage }) })) }));
22
+ };
23
+ const Container = styled.form ``;
24
+ const TextFieldAndButton = styled.div `
25
+ display: flex;
26
+ flex-direction: column;
27
+ width: 100%;
28
+
29
+ ${media.L `
30
+ flex-direction: row;
31
+ `}
32
+ `;
33
+ const Box = styled.div ``;
34
+ const BoxCenter = styled(Box) `
35
+ display: flex;
36
+ width: 100%;
37
+ justify-content: center;
38
+ align-items: center;
39
+ `;
40
+ const Heading = styled.h2 `
41
+ font-family: ${({ theme }) => theme.valueBold};
42
+ font-size: ${rem(32)};
43
+ color: ${({ theme }) => theme.blackLight};
44
+ line-height: 1.5;
45
+ margin: 0;
46
+ `;
47
+ const Text = styled.p `
48
+ color: ${({ theme }) => theme.blackLight};
49
+ font-size: ${rem(18)};
50
+ `;
51
+ const StyledAlert = styled(Alert) `
52
+ margin-top: ${rem(15)};
53
+ `;
54
+ const StyledLoadingButton = styled(LoadingButton) `
55
+ width: 100%;
56
+ margin-top: ${rem(15)};
57
+
58
+ ${media.L `
59
+ margin-left: ${rem(15)};
60
+ margin-top: 0;
61
+ width: auto;
62
+ `}
63
+ `;
@@ -0,0 +1,9 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { EmailSignupForm } from "./email-signup-form";
3
+ declare const meta: Meta<typeof EmailSignupForm>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof EmailSignupForm>;
6
+ export declare const Default: Story;
7
+ export declare const Loading: Story;
8
+ export declare const Error: Story;
9
+ export declare const Success: Story;
@@ -0,0 +1,51 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { EmailSignupForm } from "./email-signup-form";
3
+ import { Decorator } from "../../../components/decorator/decorator";
4
+ const meta = {
5
+ title: "Modules/EmailSignupForm",
6
+ component: EmailSignupForm,
7
+ decorators: [
8
+ (Story) => (_jsx(Decorator, { maxWidth: "600px", children: _jsx(Story, {}) })),
9
+ ],
10
+ };
11
+ export default meta;
12
+ const baseArgs = {
13
+ heading: "Fusce dapibus mollis orci, at lobortis nisi mattis eget",
14
+ description: "Sed in tellus ex. Integer eget placerat nulla, eu tincidunt orci. Morbi erat sapien, laoreet eget commodo vel, consectetur vitae arcu.",
15
+ localeText: {
16
+ emailLabel: "Your email address",
17
+ sendButtonText: "Subscribe",
18
+ successMessage: "Thank you for subscribing!",
19
+ goBackText: "Back to form",
20
+ errorMessage: undefined,
21
+ },
22
+ loading: false,
23
+ success: false,
24
+ onSubmit: (email) => alert(`Submitted: ${email}`),
25
+ onReset: () => alert("Reset"),
26
+ };
27
+ export const Default = {
28
+ args: baseArgs,
29
+ };
30
+ export const Loading = {
31
+ args: {
32
+ ...baseArgs,
33
+ loading: true,
34
+ },
35
+ };
36
+ export const Error = {
37
+ args: {
38
+ ...baseArgs,
39
+ localeText: {
40
+ ...baseArgs.localeText,
41
+ errorMessage: "Something went wrong. Please try again.",
42
+ },
43
+ failed: true,
44
+ },
45
+ };
46
+ export const Success = {
47
+ args: {
48
+ ...baseArgs,
49
+ success: true,
50
+ },
51
+ };
@@ -0,0 +1,27 @@
1
+ import { media } from "../../../styles/mixins";
2
+ export type EntryListProps = {
3
+ children: React.ReactNode;
4
+ };
5
+ export type EntryListItemProps = {
6
+ children: React.ReactNode;
7
+ };
8
+ export type EntryListHeadingProps = {
9
+ children: React.ReactNode;
10
+ fontSizeMobile?: number;
11
+ fontSizeDesktop?: number;
12
+ breakpoint?: keyof typeof media;
13
+ as?: "h2" | "h3";
14
+ };
15
+ export type EntryListTextProps = {
16
+ children: React.ReactNode;
17
+ fontSizeMobile?: number;
18
+ fontSizeDesktop?: number;
19
+ breakpoint?: keyof typeof media;
20
+ as?: "span" | "p";
21
+ bold?: boolean;
22
+ color?: string;
23
+ };
24
+ export declare const EntryList: ({ children }: EntryListProps) => import("react/jsx-runtime").JSX.Element;
25
+ export declare const EntryListItem: ({ children }: EntryListItemProps) => import("react/jsx-runtime").JSX.Element;
26
+ export declare const EntryListText: ({ children, fontSizeMobile, fontSizeDesktop, breakpoint, bold, as, color, }: EntryListTextProps) => import("react/jsx-runtime").JSX.Element;
27
+ export declare const EntryListHeading: ({ children, fontSizeMobile, fontSizeDesktop, as, breakpoint, }: EntryListHeadingProps) => import("react/jsx-runtime").JSX.Element;