@helsenorge/lightbox 8.0.0 → 8.0.2

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.
@@ -1,92 +0,0 @@
1
- import React from 'react';
2
-
3
- import { render, screen, fireEvent } from '@testing-library/react';
4
- import { vi } from 'vitest';
5
-
6
- import LightBox from './LightBox';
7
-
8
- describe('Gitt at LightBox skal vises', (): void => {
9
- describe('Når LightBox vises', (): void => {
10
- test('Så vises LightBox', (): void => {
11
- render(
12
- <LightBox
13
- ariaLabelCloseButton={''}
14
- ariaLabelLeftArrow={''}
15
- ariaLabelRightArrow={''}
16
- ariaLabelCloseTextBox={''}
17
- ariaLabelOpenTextBox={''}
18
- imageAlt={''}
19
- imageSrc={''}
20
- onClose={() => null}
21
- ariaLabelZoomOut={''}
22
- ariaLabelZoomIn={''}
23
- />
24
- );
25
- });
26
-
27
- test('Så vises lukkeknapp med riktig label', (): void => {
28
- render(
29
- <LightBox
30
- ariaLabelCloseButton="Lukk"
31
- ariaLabelLeftArrow=""
32
- ariaLabelRightArrow=""
33
- ariaLabelCloseTextBox=""
34
- ariaLabelOpenTextBox=""
35
- imageAlt=""
36
- imageSrc=""
37
- onClose={() => null}
38
- ariaLabelZoomOut=""
39
- ariaLabelZoomIn=""
40
- />
41
- );
42
-
43
- const closeButton = screen.getByLabelText('Lukk');
44
- expect(closeButton).toBeInTheDocument();
45
- });
46
-
47
- test('Så vises begge pilknapper når callback er gitt', (): void => {
48
- render(
49
- <LightBox
50
- ariaLabelCloseButton=""
51
- ariaLabelLeftArrow="Forrige bilde"
52
- onLeftArrowClick={() => null}
53
- ariaLabelRightArrow="Neste bilde"
54
- onRightArrowClick={() => null}
55
- ariaLabelCloseTextBox=""
56
- ariaLabelOpenTextBox=""
57
- imageAlt=""
58
- imageSrc=""
59
- onClose={() => null}
60
- ariaLabelZoomOut=""
61
- ariaLabelZoomIn=""
62
- />
63
- );
64
-
65
- const rightArrow = screen.getByLabelText('Neste bilde');
66
- const leftArrow = screen.getByLabelText('Forrige bilde');
67
- expect(rightArrow).toBeInTheDocument();
68
- expect(leftArrow).toBeInTheDocument();
69
- });
70
-
71
- test('Så blir onClose funksjonen kalt når lukkeknappen trykkes', (): void => {
72
- const onCloseMock = vi.fn();
73
- render(
74
- <LightBox
75
- ariaLabelCloseButton="Lukk"
76
- ariaLabelLeftArrow=""
77
- ariaLabelRightArrow=""
78
- ariaLabelCloseTextBox=""
79
- ariaLabelOpenTextBox=""
80
- imageAlt=""
81
- imageSrc=""
82
- onClose={onCloseMock}
83
- ariaLabelZoomOut=""
84
- ariaLabelZoomIn=""
85
- />
86
- );
87
- const closeButton = screen.getByLabelText('Lukk');
88
- fireEvent.click(closeButton);
89
- expect(onCloseMock).toHaveBeenCalled();
90
- });
91
- });
92
- });
@@ -1,265 +0,0 @@
1
- import React, { useEffect, useRef, useState } from 'react';
2
-
3
- import classNames from 'classnames';
4
- import { TransformWrapper, TransformComponent, useTransformComponent } from 'react-zoom-pan-pinch';
5
-
6
- import Icon from '@helsenorge/designsystem-react/components/Icon';
7
- import ChevronLeft from '@helsenorge/designsystem-react/components/Icons/ChevronLeft';
8
- import ChevronRight from '@helsenorge/designsystem-react/components/Icons/ChevronRight';
9
- import ChevronsDown from '@helsenorge/designsystem-react/components/Icons/ChevronsDown';
10
- import ChevronsUp from '@helsenorge/designsystem-react/components/Icons/ChevronsUp';
11
- import Minus from '@helsenorge/designsystem-react/components/Icons/Minus';
12
- import PlusSmall from '@helsenorge/designsystem-react/components/Icons/PlusSmall';
13
- import X from '@helsenorge/designsystem-react/components/Icons/X';
14
- import { IconSize, KeyboardEventKey, ZIndex } from '@helsenorge/designsystem-react/constants';
15
- import { useSize } from '@helsenorge/designsystem-react/hooks/useSize';
16
-
17
- import { useKeyboardEvent } from '@helsenorge/designsystem-react';
18
-
19
- import MiniSlider from './MiniSlider';
20
-
21
- import styles from './styles.module.scss';
22
-
23
- export interface LightBoxProps {
24
- /** Aria label for the close button */
25
- ariaLabelCloseButton: string;
26
- /** Aria label for the text box button when its open */
27
- ariaLabelCloseTextBox: string;
28
- /** Aria label for the left arrow button */
29
- ariaLabelLeftArrow: string;
30
- /** Aria label for the full modal describing what the modal contains */
31
- ariaLabelLightBox: string;
32
- /** Aria label for the right arrow button */
33
- ariaLabelRightArrow: string;
34
- /** Aria label for the text box button when its closed */
35
- ariaLabelOpenTextBox: string;
36
- /** Aria label for the zoom in button */
37
- ariaLabelZoomIn: string;
38
- /** Aria label for the zoom out button */
39
- ariaLabelZoomOut: string;
40
- /** Aria label for the slider input component */
41
- ariaLabelZoomSlider: string;
42
- /** If set the text box closes automatically after the given seconds */
43
- closeTextAfterSeconds?: number;
44
- /** Alt text for the image */
45
- imageAlt: string;
46
- /** Source of the image that will be shown */
47
- imageSrc: string;
48
- /** The text for the image that shows in the textbox */
49
- imageText?: string;
50
- /** Function is called when user clicks the close button */
51
- onClose: () => void;
52
- /** Function is called when user clicks the left arrow button. If not given the arrow will not show. */
53
- onLeftArrowClick?: () => void;
54
- /** Function is called when user clicks the right arrow button. If not given the arrow will not show. */
55
- onRightArrowClick?: () => void;
56
- /** Sets the data-testid attribute. */
57
- testId?: string;
58
- }
59
-
60
- const LightBox: React.FC<LightBoxProps> = ({
61
- ariaLabelCloseButton,
62
- ariaLabelLeftArrow,
63
- ariaLabelLightBox,
64
- ariaLabelRightArrow,
65
- ariaLabelCloseTextBox,
66
- ariaLabelOpenTextBox,
67
- ariaLabelZoomIn,
68
- ariaLabelZoomOut,
69
- ariaLabelZoomSlider,
70
- closeTextAfterSeconds,
71
- imageAlt,
72
- imageSrc,
73
- imageText,
74
- onClose,
75
- onLeftArrowClick,
76
- onRightArrowClick,
77
- testId,
78
- }) => {
79
- const [imageTextOpen, setImageTextOpen] = React.useState(true);
80
- const lightBoxRef = useRef<HTMLDivElement>(null);
81
- const textBoxRef = useRef<HTMLParagraphElement>(null);
82
- const { height: textBoxHeight = 0 } = useSize(textBoxRef) || {};
83
- const [zoom, setZoom] = useState(1.0);
84
-
85
- useKeyboardEvent(lightBoxRef, onClose, [KeyboardEventKey.Escape]);
86
-
87
- const updateStates = (newZoom: number): void => {
88
- if (zoom === newZoom) return;
89
- setZoom(newZoom);
90
- };
91
-
92
- useEffect(() => {
93
- if (!closeTextAfterSeconds) return;
94
- const timer = setTimeout(() => {
95
- setImageTextOpen(false);
96
- }, closeTextAfterSeconds * 1000);
97
-
98
- return () => clearTimeout(timer);
99
- }, []);
100
-
101
- return (
102
- <div
103
- data-testid={testId}
104
- className={styles.lightBox}
105
- style={{ zIndex: ZIndex.OverlayScreen }}
106
- role="dialog"
107
- aria-modal={true}
108
- aria-label={ariaLabelLightBox}
109
- ref={lightBoxRef}
110
- >
111
- <button
112
- onClick={onClose}
113
- aria-label={ariaLabelCloseButton}
114
- data-testid="closeButton"
115
- className={classNames(styles.button, styles['close-button'])}
116
- style={{ zIndex: ZIndex.LightBoxButtons }}
117
- >
118
- <Icon svgIcon={X} color="white" size={IconSize.XSmall} />
119
- </button>
120
- {onLeftArrowClick && (
121
- <button
122
- className={classNames(styles.button, styles['arrow-button'], styles['arrow-button--left'])}
123
- onClick={onLeftArrowClick}
124
- aria-label={ariaLabelLeftArrow}
125
- data-testid="leftArrow"
126
- style={{ zIndex: ZIndex.LightBoxButtons }}
127
- >
128
- <Icon svgIcon={ChevronLeft} color="white" size={IconSize.XSmall} />
129
- </button>
130
- )}
131
- {onRightArrowClick && (
132
- <button
133
- className={classNames(styles.button, styles['arrow-button'], styles['arrow-button--right'])}
134
- onClick={onRightArrowClick}
135
- aria-label={ariaLabelRightArrow}
136
- data-testid="rightarrow"
137
- style={{ zIndex: ZIndex.LightBoxButtons }}
138
- >
139
- <Icon svgIcon={ChevronRight} color="white" size={IconSize.XSmall} />
140
- </button>
141
- )}
142
- {imageText && (
143
- <div
144
- className={styles['image-text-box']}
145
- style={{ bottom: imageTextOpen ? '0' : '-' + textBoxHeight + 'px', transition: '0.5s', zIndex: ZIndex.LightBoxButtons }}
146
- >
147
- <button
148
- className={classNames(styles.button, styles['image-text-box__button'])}
149
- onClick={() => setImageTextOpen(!imageTextOpen)}
150
- style={{ zIndex: ZIndex.LightBoxButtons }}
151
- aria-label={imageTextOpen ? ariaLabelCloseTextBox : ariaLabelOpenTextBox}
152
- aria-expanded={imageTextOpen}
153
- >
154
- {imageTextOpen ? (
155
- <Icon svgIcon={ChevronsDown} color="white" size={IconSize.XSmall} />
156
- ) : (
157
- <Icon svgIcon={ChevronsUp} color="white" size={IconSize.XSmall} />
158
- )}
159
- </button>
160
- <div>
161
- <p ref={textBoxRef} className={styles['image-text-box__text']}>
162
- {imageText}
163
- </p>
164
- <div className={styles['image-text-box__overflow-border']}></div>
165
- </div>
166
- </div>
167
- )}
168
- <TransformWrapper initialScale={1} maxScale={4} doubleClick={{ mode: 'toggle', step: 4 }}>
169
- {({ setTransform }) => (
170
- <>
171
- <Controls
172
- transform={setTransform}
173
- updateStates={updateStates}
174
- zoom={zoom}
175
- ariaLabelZoomIn={ariaLabelZoomIn}
176
- ariaLabelZoomOut={ariaLabelZoomOut}
177
- ariaLabelZoomSlider={ariaLabelZoomSlider}
178
- />
179
- <TransformComponent
180
- wrapperStyle={{
181
- zIndex: 1,
182
- width: '100%',
183
- height: '100%',
184
- }}
185
- contentStyle={{
186
- width: '100%',
187
- height: '100%',
188
- }}
189
- >
190
- <img src={imageSrc} alt={imageAlt} />
191
- </TransformComponent>
192
- </>
193
- )}
194
- </TransformWrapper>
195
- </div>
196
- );
197
- };
198
-
199
- const Controls = ({
200
- transform,
201
- updateStates,
202
- zoom,
203
- ariaLabelZoomIn,
204
- ariaLabelZoomOut,
205
- ariaLabelZoomSlider,
206
- }: {
207
- transform: (newPositionX: number, newPositionY: number, newScale: number, animationTime?: number | undefined) => void;
208
- updateStates: (newZoom: number) => void;
209
- zoom: number;
210
- ariaLabelZoomIn: string;
211
- ariaLabelZoomOut: string;
212
- ariaLabelZoomSlider: string;
213
- }): React.JSX.Element => {
214
- useTransformComponent(({ state }) => {
215
- updateStates(state.scale);
216
- });
217
-
218
- const calculateZoomCenter = (newScale: number): number[] => {
219
- const element = document.getElementsByClassName('react-transform-component')[0];
220
- const style = window.getComputedStyle(element);
221
- const matrix = new WebKitCSSMatrix(style.transform);
222
-
223
- const ratio = (newScale - zoom) / zoom + 1;
224
- const x = (matrix.m41 - (window.innerWidth / 2) * (1 - zoom / newScale)) * ratio;
225
- const y = (matrix.m42 - (window.innerHeight / 2) * (1 - zoom / newScale)) * ratio;
226
- return [x, y];
227
- };
228
-
229
- const adjustZoom = (newScale: number | undefined): void => {
230
- if (newScale === undefined || newScale === zoom) return;
231
- if (newScale < 1) newScale = 1;
232
- if (newScale > 4) newScale = 4;
233
- const [x, y] = calculateZoomCenter(newScale);
234
- transform(x, y, newScale, 1);
235
- };
236
-
237
- const adjustZoomWithAnimation = (newScale: number | undefined): void => {
238
- if (newScale === undefined || newScale === zoom) return;
239
- if (newScale < 1) newScale = 1;
240
- if (newScale > 4) newScale = 4;
241
- const [x, y] = calculateZoomCenter(newScale);
242
- transform(x, y, newScale);
243
- };
244
-
245
- return (
246
- <div className={classNames(styles['zoom-buttons'])} style={{ zIndex: ZIndex.LightBoxButtons }}>
247
- <button className={classNames(styles.button)} onClick={() => adjustZoomWithAnimation(zoom - 0.5)} aria-label={ariaLabelZoomOut}>
248
- <Icon svgIcon={Minus} color="white" size={IconSize.XSmall} />
249
- </button>
250
- <MiniSlider
251
- className={styles['slider']}
252
- minValue={1}
253
- maxValue={4}
254
- onChange={adjustZoom}
255
- value={zoom}
256
- ariaLabel={ariaLabelZoomSlider}
257
- />
258
- <button className={classNames(styles.button)} onClick={() => adjustZoomWithAnimation(zoom + 0.5)} aria-label={ariaLabelZoomIn}>
259
- <Icon svgIcon={PlusSmall} color="white" size={IconSize.XSmall} />
260
- </button>
261
- </div>
262
- );
263
- };
264
-
265
- export default LightBox;
@@ -1,37 +0,0 @@
1
- import React, { ChangeEvent } from 'react';
2
-
3
- interface MiniSliderProps {
4
- value: number;
5
- minValue: number;
6
- maxValue: number;
7
- onChange: (newValue: number) => void;
8
- className?: string;
9
- ariaLabel: string;
10
- }
11
-
12
- const MiniSlider = (props: MiniSliderProps): React.JSX.Element => {
13
- const handleOnChange = (event: ChangeEvent<HTMLInputElement>): void => {
14
- event.preventDefault();
15
- const newValue = parseFloat(event.target.value);
16
- props.onChange(newValue);
17
- };
18
-
19
- return (
20
- <div className={props.className}>
21
- <input
22
- onChange={handleOnChange}
23
- type="range"
24
- min={props.minValue}
25
- max={props.maxValue}
26
- value={props.value}
27
- aria-valuenow={props.value}
28
- aria-valuemin={props.minValue}
29
- aria-valuemax={props.maxValue}
30
- aria-label={props.ariaLabel}
31
- step={0.1}
32
- />
33
- </div>
34
- );
35
- };
36
-
37
- export default MiniSlider;
package/tsconfig.json DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.json",
3
- "include": ["src"],
4
- "exclude": ["**/*.test.snap.tsx", "**/*.test.tsx", "**/*.stories.tsx"],
5
- "references": [{ "path": "./tsconfig.node.json" }]
6
- }
@@ -1,10 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "composite": true,
4
- "skipLibCheck": true,
5
- "module": "ESNext",
6
- "moduleResolution": "bundler",
7
- "allowSyntheticDefaultImports": true
8
- },
9
- "include": ["vite.config.ts"]
10
- }
package/vite.config.ts DELETED
@@ -1,83 +0,0 @@
1
- import replace from '@rollup/plugin-replace';
2
- import copy from 'rollup-plugin-copy';
3
- import generatePackageJson from 'rollup-plugin-generate-package-json';
4
- import peerDepsExternal from 'rollup-plugin-peer-deps-external';
5
- import { defineConfig } from 'vite';
6
-
7
- import { entries } from './__scripts__/entries';
8
-
9
- const OUTPUT_DIRECTORY = 'lib';
10
-
11
- export default defineConfig({
12
- build: {
13
- outDir: OUTPUT_DIRECTORY,
14
- sourcemap: true,
15
- lib: {
16
- entry: 'index.js',
17
- formats: ['es'],
18
- },
19
- rollupOptions: {
20
- preserveEntrySignatures: 'strict',
21
- input: entries,
22
- external: [/.module.scss/],
23
- output: {
24
- format: 'es',
25
- entryFileNames: '[name].js',
26
- chunkFileNames: '[name].js',
27
- assetFileNames: '[name].[ext]',
28
- },
29
- plugins: [
30
- peerDepsExternal(),
31
- copy({
32
- targets: [
33
- { src: '*.md', dest: OUTPUT_DIRECTORY },
34
- { src: '../../CHANGELOG.md', dest: OUTPUT_DIRECTORY },
35
- ],
36
- hook: 'writeBundle',
37
- }),
38
- copy({
39
- targets: [
40
- { src: 'src/components/**/*.module.scss*', dest: OUTPUT_DIRECTORY },
41
- { src: 'types/**/*.d.ts*', dest: OUTPUT_DIRECTORY },
42
- ],
43
- hook: 'writeBundle',
44
- flatten: false,
45
- }),
46
- generatePackageJson({
47
- baseContents: ({
48
- name,
49
- type,
50
- description,
51
- repository,
52
- homepage,
53
- version,
54
- author,
55
- license,
56
- dependencies = {},
57
- peerDependencies = {},
58
- sideEffects,
59
- }) => ({
60
- name,
61
- type,
62
- description,
63
- repository,
64
- homepage,
65
- version,
66
- author,
67
- license,
68
- dependencies,
69
- peerDependencies,
70
- sideEffects,
71
- }),
72
- }),
73
- // rollup har begynt å legge til ?used på slutten av styles.module.scss når vi behandler
74
- // dem som external.
75
- replace({
76
- '.module.scss?used': '.module.scss',
77
- '.module.css?used': '.module.css',
78
- preventAssignment: true,
79
- }),
80
- ],
81
- },
82
- },
83
- });
package/vitest.config.ts DELETED
@@ -1,28 +0,0 @@
1
- import { defineConfig } from 'vitest/config';
2
-
3
- export default defineConfig({
4
- test: {
5
- globals: true,
6
- environment: 'jsdom',
7
- setupFiles: ['../designsystem/src/utils/tests/setup-test.ts'],
8
- css: {
9
- modules: {
10
- classNameStrategy: 'non-scoped',
11
- },
12
- },
13
- coverage: {
14
- enabled: true,
15
- provider: 'istanbul',
16
- reporter: ['cobertura', 'lcov', 'json'],
17
- },
18
- reporters: ['default', 'junit'],
19
- outputFile: {
20
- junit: 'test-report.xml',
21
- },
22
- server: {
23
- deps: {
24
- inline: ['@helsenorge/designsystem-react'],
25
- },
26
- },
27
- },
28
- });