@laser-ui/components 1.5.0 → 1.6.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
4
4
 
5
+ # [1.6.0](https://github.com/laser-ui/laser-ui/compare/v1.5.1...v1.6.0) (2024-11-16)
6
+
7
+ ### Features
8
+
9
+ - **components:** add `ImageLoader` ([e1f7fef](https://github.com/laser-ui/laser-ui/commit/e1f7fef8749872f9ba9769bdab3b2a0a20f41044))
10
+ - **components:** image preview support more user-friendly gesture operation ([1993a3b](https://github.com/laser-ui/laser-ui/commit/1993a3b2d24a75270c4618114293fb33764e773f))
11
+
12
+ ## [1.5.1](https://github.com/laser-ui/laser-ui/compare/v1.5.0...v1.5.1) (2024-11-01)
13
+
14
+ ### Bug Fixes
15
+
16
+ - **components:** fix form run async validator ([82010e8](https://github.com/laser-ui/laser-ui/commit/82010e83ad8c4de021a3bda9f1a552564ac06c54))
17
+
5
18
  # [1.5.0](https://github.com/laser-ui/laser-ui/compare/v1.4.0...v1.5.0) (2024-10-15)
6
19
 
7
20
  ### Features
package/form/FormItem.js CHANGED
@@ -6,7 +6,7 @@ import CheckCircleFilled from '@material-design-icons/svg/filled/check_circle.sv
6
6
  import ErrorFilled from '@material-design-icons/svg/filled/error.svg?react';
7
7
  import HelpOutlineOutlined from '@material-design-icons/svg/outlined/help_outline.svg?react';
8
8
  import { isBoolean, isFunction, isNull, isNumber, isString, isUndefined } from 'lodash';
9
- import { useContext, useId, useRef } from 'react';
9
+ import { useContext, useEffect, useId, useRef } from 'react';
10
10
  import { FormError } from './internal/FormError';
11
11
  import { Validators } from './model/validators';
12
12
  import { CLASSES, FormContext, FormGroupContext } from './vars';
@@ -41,7 +41,9 @@ export function FormItem(props) {
41
41
  if (isNull(formControl)) {
42
42
  throw new Error(`Cant find '${controlName}', please check if name exists!`);
43
43
  }
44
- formControl._emitChange = forceUpdate;
44
+ formControl._emitChange = () => {
45
+ formControl._emitChange = true;
46
+ };
45
47
  obj[controlName] = {
46
48
  control: formControl,
47
49
  invalid: false,
@@ -52,6 +54,24 @@ export function FormItem(props) {
52
54
  });
53
55
  return obj;
54
56
  })();
57
+ useEffect(() => {
58
+ const clear = [];
59
+ for (const { control } of Object.values(formControlProviders)) {
60
+ if (control._emitChange === true) {
61
+ forceUpdate();
62
+ }
63
+ control._emitChange = forceUpdate;
64
+ clear.push(() => {
65
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
66
+ control._emitChange = () => { };
67
+ });
68
+ }
69
+ return () => {
70
+ for (const cb of clear) {
71
+ cb();
72
+ }
73
+ };
74
+ }, []);
55
75
  const required = (() => {
56
76
  if (isBoolean(requiredProp)) {
57
77
  return requiredProp;
package/form/hooks.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { useEventCallback, useForceUpdate, useIsomorphicLayoutEffect } from '@laser-ui/hooks';
2
2
  import { isString } from 'lodash';
3
- import { useRef, useState } from 'react';
3
+ import { useEffect, useRef, useState } from 'react';
4
4
  export function useForm(initForm, deps) {
5
5
  const forceUpdate = useForceUpdate();
6
6
  const emitChange = useEventCallback((control) => {
@@ -39,7 +39,9 @@ export function useForm(initForm, deps) {
39
39
  });
40
40
  const [form, setForm] = useState(() => {
41
41
  const form = initForm();
42
- form._emitChange = emitChange;
42
+ form._emitChange = () => {
43
+ form._emitChange = true;
44
+ };
43
45
  return form;
44
46
  });
45
47
  const previousDeps = useRef([]);
@@ -55,5 +57,15 @@ export function useForm(initForm, deps) {
55
57
  }
56
58
  forceUpdate();
57
59
  });
60
+ useEffect(() => {
61
+ if (form._emitChange === true) {
62
+ forceUpdate();
63
+ }
64
+ form._emitChange = emitChange;
65
+ return () => {
66
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
67
+ form._emitChange = () => { };
68
+ };
69
+ }, []);
58
70
  return [form, updateForm];
59
71
  }
package/image/Image.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  /// <reference types="react" />
2
2
  import type { ImageProps } from './types';
3
3
  import { ImageAction } from './ImageAction';
4
+ import { ImageLoader } from './ImageLoader';
4
5
  import { ImagePreview } from './ImagePreview';
5
6
  export declare const Image: {
6
7
  (props: ImageProps): JSX.Element | null;
8
+ Loader: typeof ImageLoader;
7
9
  Action: typeof ImageAction;
8
10
  Preview: typeof ImagePreview;
9
11
  };
package/image/Image.js CHANGED
@@ -4,6 +4,7 @@ import { useForceUpdate } from '@laser-ui/hooks';
4
4
  import { checkNodeExist } from '@laser-ui/utils';
5
5
  import { Children, useRef } from 'react';
6
6
  import { ImageAction } from './ImageAction';
7
+ import { ImageLoader } from './ImageLoader';
7
8
  import { ImagePreview } from './ImagePreview';
8
9
  import { CLASSES } from './vars';
9
10
  import { useComponentProps, useStyled } from '../hooks';
@@ -46,5 +47,6 @@ export const Image = (props) => {
46
47
  forceUpdate();
47
48
  } }))] })));
48
49
  };
50
+ Image.Loader = ImageLoader;
49
51
  Image.Action = ImageAction;
50
52
  Image.Preview = ImagePreview;
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ import type { ImageLoaderProps } from './types';
3
+ export declare const ImageLoader: {
4
+ (props: ImageLoaderProps): JSX.Element | null;
5
+ KEYS: (keyof HTMLImageElement)[];
6
+ };
@@ -0,0 +1,37 @@
1
+ import { useEffect, useState } from 'react';
2
+ const IMGS = new Map();
3
+ export const ImageLoader = (props) => {
4
+ var _a;
5
+ const { src, keys = ImageLoader.KEYS, children } = props;
6
+ const [img, setImg] = useState((_a = IMGS.get(src)) !== null && _a !== void 0 ? _a : null);
7
+ useEffect(() => {
8
+ const img = new Image();
9
+ img.src = src;
10
+ const handleLoad = () => {
11
+ var _a;
12
+ const oldImg = (_a = IMGS.get(src)) !== null && _a !== void 0 ? _a : {};
13
+ const newImg = {};
14
+ let update = false;
15
+ for (const key of keys) {
16
+ newImg[key] = img[key];
17
+ if (!Object.is(newImg[key], oldImg[key])) {
18
+ update = true;
19
+ }
20
+ }
21
+ if (update) {
22
+ setImg(newImg);
23
+ }
24
+ };
25
+ if (img.complete) {
26
+ handleLoad();
27
+ }
28
+ else {
29
+ img.onload = () => {
30
+ handleLoad();
31
+ };
32
+ }
33
+ // eslint-disable-next-line react-hooks/exhaustive-deps
34
+ }, [src]);
35
+ return img ? children(img) : null;
36
+ };
37
+ ImageLoader.KEYS = ['naturalWidth', 'naturalHeight'];
@@ -1,7 +1,7 @@
1
1
  import { __rest } from "tslib";
2
2
  import { createElement as _createElement } from "react";
3
3
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
- import { useEvent, useImmer, useRefExtra } from '@laser-ui/hooks';
4
+ import { useEvent, useRefExtra } from '@laser-ui/hooks';
5
5
  import CloseOutlined from '@material-design-icons/svg/outlined/close.svg?react';
6
6
  import KeyboardArrowLeftOutlined from '@material-design-icons/svg/outlined/keyboard_arrow_left.svg?react';
7
7
  import KeyboardArrowRightOutlined from '@material-design-icons/svg/outlined/keyboard_arrow_right.svg?react';
@@ -22,18 +22,19 @@ import { ROOT_DATA } from '../root/vars';
22
22
  import { mergeCS } from '../utils';
23
23
  import { TTANSITION_DURING_BASE } from '../vars';
24
24
  export function ImagePreview(props) {
25
- var _a, _b, _c;
26
- const _d = useComponentProps('ImagePreview', props), { styleOverrides, styleProvider, list, visible, active: activeProp, defaultActive, escClosable = true, zIndex: zIndexProp, onActiveChange, onClose, afterVisibleChange } = _d, restProps = __rest(_d, ["styleOverrides", "styleProvider", "list", "visible", "active", "defaultActive", "escClosable", "zIndex", "onActiveChange", "onClose", "afterVisibleChange"]);
25
+ const _a = useComponentProps('ImagePreview', props), { styleOverrides, styleProvider, list, visible, active: activeProp, defaultActive, escClosable = true, zIndex: zIndexProp, onActiveChange, onClose, afterVisibleChange } = _a, restProps = __rest(_a, ["styleOverrides", "styleProvider", "list", "visible", "active", "defaultActive", "escClosable", "zIndex", "onActiveChange", "onClose", "afterVisibleChange"]);
27
26
  const namespace = useNamespace();
28
27
  const styled = useStyled(PREVIEW_CLASSES, { 'image-preview': styleProvider === null || styleProvider === void 0 ? void 0 : styleProvider['image-preview'] }, styleOverrides);
29
28
  const previewRef = useRef(null);
30
29
  const windowRef = useRefExtra(() => window);
31
30
  const dataRef = useRef({
31
+ transform: new Map(),
32
+ initialScale: 1,
32
33
  prevActiveEl: null,
33
34
  eventData: {},
35
+ mouse: { x: 0, y: 0 },
34
36
  });
35
37
  const [active, changeActive] = useControlled(defaultActive !== null && defaultActive !== void 0 ? defaultActive : 0, activeProp, onActiveChange);
36
- const activeSrc = list[active].src;
37
38
  const [offset, setOffset] = useState(() => {
38
39
  if (ROOT_DATA.windowSize.width) {
39
40
  return ~~((ROOT_DATA.windowSize.width - 108) / 120);
@@ -48,68 +49,88 @@ export function ImagePreview(props) {
48
49
  startIndex = Math.max(endIndex - offset * 2, 0);
49
50
  const [isDragging, setIsDragging] = useState(false);
50
51
  const listenDragEvent = visible && isDragging;
51
- const [position, setPosition] = useImmer(new Map());
52
- const activePosition = (_a = position.get(activeSrc)) !== null && _a !== void 0 ? _a : { top: 0, left: 0 };
53
- const [rotate, setRotate] = useImmer(new Map());
54
- const activeRotate = (_b = rotate.get(activeSrc)) !== null && _b !== void 0 ? _b : 0;
55
- const [scale, setScale] = useImmer(new Map());
56
- const activeScale = (_c = scale.get(activeSrc)) !== null && _c !== void 0 ? _c : 1;
57
52
  const maxZIndex = useMaxIndex(visible);
58
53
  const zIndex = !isUndefined(zIndexProp) ? zIndexProp : `calc(var(--${namespace}-zindex-fixed) + ${maxZIndex})`;
59
54
  useLockScroll(visible);
55
+ const setTransform = (update, scaleByClick = false) => {
56
+ var _a, _b;
57
+ const transform = (_a = dataRef.current.transform.get(active)) !== null && _a !== void 0 ? _a : { top: 0, left: 0, scale: 1, rotate: 0 };
58
+ const prevScale = transform.scale;
59
+ const prevRotate = transform.rotate;
60
+ update(transform);
61
+ dataRef.current.transform.set(active, transform);
62
+ if (previewRef.current) {
63
+ const img = document.querySelector(`[data-index="${active}"]`);
64
+ const imgWrapper = img.parentElement;
65
+ const transform = (_b = dataRef.current.transform.get(active)) !== null && _b !== void 0 ? _b : { top: 0, left: 0, scale: 1, rotate: 0 };
66
+ if (transform.rotate !== prevRotate) {
67
+ transform.top = 0;
68
+ transform.left = 0;
69
+ transform.scale = 1;
70
+ }
71
+ else if (transform.scale !== prevScale) {
72
+ const rect = imgWrapper.getBoundingClientRect();
73
+ const offsetScale = transform.scale - prevScale;
74
+ const offsetWidth = ((scaleByClick ? window.innerWidth / 2 : dataRef.current.mouse.x) - rect.x) / prevScale;
75
+ const offsetHeight = ((scaleByClick ? window.innerHeight / 2 : dataRef.current.mouse.y) - rect.y) / prevScale;
76
+ transform.left = transform.left - offsetScale * offsetWidth;
77
+ transform.top = transform.top - offsetScale * offsetHeight;
78
+ }
79
+ imgWrapper.style.transform = `translate(${transform.left}px, ${transform.top}px) scale(${transform.scale})`;
80
+ img.style.transform = `rotate(${transform.rotate}deg)`;
81
+ }
82
+ };
60
83
  const handleMove = () => {
61
- const { initMove, currentMove, initScale, currentScale } = dataRef.current.eventData;
62
- if (initMove && currentMove) {
63
- const movementX = currentMove.x - initMove.x;
64
- const movementY = currentMove.y - initMove.y;
65
- setPosition((draft) => {
66
- var _a;
67
- const oldPosition = (_a = draft.get(activeSrc)) !== null && _a !== void 0 ? _a : { top: 0, left: 0 };
68
- draft.set(activeSrc, {
69
- top: oldPosition.top + movementY,
70
- left: oldPosition.left + movementX,
71
- });
84
+ const { initialMove, currentMove, initialTouches, currentTouches } = dataRef.current.eventData;
85
+ const updates = [];
86
+ if (initialMove && currentMove) {
87
+ const movementX = currentMove.x - initialMove.x;
88
+ const movementY = currentMove.y - initialMove.y;
89
+ updates.push((transform) => {
90
+ transform.top = transform.top + movementY;
91
+ transform.left = transform.left + movementX;
72
92
  });
73
- dataRef.current.eventData.initMove = currentMove;
93
+ dataRef.current.eventData.initialMove = currentMove;
74
94
  dataRef.current.eventData.currentMove = undefined;
75
95
  }
76
- if (initScale && currentScale) {
77
- const initLength = Math.sqrt(Math.pow(initScale.x0 - initScale.x1, 2) + Math.pow(initScale.y0 - initScale.y1, 2));
78
- const currentLength = Math.sqrt(Math.pow(currentScale.x0 - currentScale.x1, 2) + Math.pow(currentScale.y0 - currentScale.y1, 2));
79
- setScale((draft) => {
80
- var _a;
81
- const oldScale = (_a = draft.get(activeSrc)) !== null && _a !== void 0 ? _a : 1;
82
- draft.set(activeSrc, Math.max(oldScale + (currentLength - initLength) / 100, 1));
96
+ if (initialTouches && currentTouches) {
97
+ const initialLength = Math.sqrt(Math.pow(initialTouches.x0 - initialTouches.x1, 2) + Math.pow(initialTouches.y0 - initialTouches.y1, 2));
98
+ const currentLength = Math.sqrt(Math.pow(currentTouches.x0 - currentTouches.x1, 2) + Math.pow(currentTouches.y0 - currentTouches.y1, 2));
99
+ updates.push((transform) => {
100
+ transform.scale = Math.max(dataRef.current.initialScale * (currentLength / initialLength), 1);
83
101
  });
84
- dataRef.current.eventData.initScale = currentScale;
85
- dataRef.current.eventData.currentScale = undefined;
102
+ dataRef.current.eventData.currentTouches = undefined;
86
103
  }
104
+ setTransform((transform) => {
105
+ for (const update of updates) {
106
+ update(transform);
107
+ }
108
+ });
87
109
  };
88
110
  useEvent(windowRef, 'touchmove', (e) => {
89
111
  e.preventDefault();
90
112
  if (e.touches.length === 2) {
91
- dataRef.current.eventData.initMove = dataRef.current.eventData.currentMove = undefined;
92
- const newScale = {
113
+ dataRef.current.eventData.initialMove = dataRef.current.eventData.currentMove = undefined;
114
+ const touches = {
93
115
  x0: e.touches[0].clientX,
94
116
  y0: e.touches[0].clientY,
95
117
  x1: e.touches[1].clientX,
96
118
  y1: e.touches[1].clientY,
97
119
  };
98
- if (isUndefined(dataRef.current.eventData.initScale)) {
99
- dataRef.current.eventData.initScale = newScale;
120
+ if (isUndefined(dataRef.current.eventData.initialTouches)) {
121
+ dataRef.current.eventData.initialTouches = touches;
100
122
  }
101
123
  else {
102
- dataRef.current.eventData.currentScale = newScale;
124
+ dataRef.current.eventData.currentTouches = touches;
103
125
  }
104
126
  }
105
127
  else {
106
- dataRef.current.eventData.initScale = dataRef.current.eventData.currentScale = undefined;
107
128
  const newMove = {
108
129
  x: e.touches[0].clientX,
109
130
  y: e.touches[0].clientY,
110
131
  };
111
- if (isUndefined(dataRef.current.eventData.initMove)) {
112
- dataRef.current.eventData.initMove = newMove;
132
+ if (isUndefined(dataRef.current.eventData.initialMove)) {
133
+ dataRef.current.eventData.initialMove = newMove;
113
134
  }
114
135
  else {
115
136
  dataRef.current.eventData.currentMove = newMove;
@@ -118,19 +139,22 @@ export function ImagePreview(props) {
118
139
  handleMove();
119
140
  }, { passive: false }, !listenDragEvent);
120
141
  useEvent(windowRef, 'mousemove', (e) => {
121
- e.preventDefault();
122
142
  const newMove = {
123
143
  x: e.clientX,
124
144
  y: e.clientY,
125
145
  };
126
- if (isUndefined(dataRef.current.eventData.initMove)) {
127
- dataRef.current.eventData.initMove = newMove;
128
- }
129
- else {
130
- dataRef.current.eventData.currentMove = newMove;
146
+ dataRef.current.mouse = newMove;
147
+ if (isDragging) {
148
+ e.preventDefault();
149
+ if (isUndefined(dataRef.current.eventData.initialMove)) {
150
+ dataRef.current.eventData.initialMove = newMove;
151
+ }
152
+ else {
153
+ dataRef.current.eventData.currentMove = newMove;
154
+ }
155
+ handleMove();
131
156
  }
132
- handleMove();
133
- }, {}, !listenDragEvent);
157
+ });
134
158
  useEvent(windowRef, 'mouseup', () => {
135
159
  setIsDragging(false);
136
160
  }, {}, !listenDragEvent);
@@ -198,59 +222,61 @@ export function ImagePreview(props) {
198
222
  changeActive(val - 1);
199
223
  }
200
224
  } })), _jsx("span", { children: "/" }), _jsx("span", { children: list.length })] })), _jsx("li", Object.assign({}, styled('image-preview__toolbar-rotate'), { children: _jsx(Button, { pattern: "text", icon: _jsx(Icon, { children: _jsx(Rotate90DegreesCwOutlined, {}) }), onClick: () => {
201
- setRotate((draft) => {
202
- var _a;
203
- const oldRotate = (_a = draft.get(activeSrc)) !== null && _a !== void 0 ? _a : 0;
204
- draft.set(activeSrc, oldRotate + 90);
225
+ setTransform((transform) => {
226
+ transform.rotate = transform.rotate + 90;
205
227
  });
206
228
  } }) })), _jsx("li", Object.assign({}, styled('image-preview__toolbar-zoom-out'), { children: _jsx(Button, { pattern: "text", icon: _jsx(Icon, { children: _jsx(ZoomOutOutlined, {}) }), onClick: () => {
207
- setScale((draft) => {
208
- var _a;
209
- const oldScale = (_a = draft.get(activeSrc)) !== null && _a !== void 0 ? _a : 1;
210
- draft.set(activeSrc, Math.max(oldScale / 1.3, 1));
211
- });
212
- } }) })), _jsx("li", Object.assign({}, styled('image-preview__toolbar-zoom'), { children: _jsx(Input.Number, Object.assign({}, styled('image-preview__toolbar-zoom-input'), { model: Math.round(activeScale * 100), min: 100, step: 10, integer: true, onModelChange: (val) => {
213
- if (!isNull(val)) {
214
- setScale((draft) => {
215
- draft.set(activeSrc, val / 100);
216
- });
217
- }
218
- } })) })), _jsx("li", Object.assign({}, styled('image-preview__toolbar-zoom-in'), { children: _jsx(Button, { pattern: "text", icon: _jsx(Icon, { children: _jsx(ZoomInOutlined, {}) }), onClick: () => {
219
- setScale((draft) => {
220
- var _a;
221
- const oldScale = (_a = draft.get(activeSrc)) !== null && _a !== void 0 ? _a : 1;
222
- draft.set(activeSrc, oldScale * 1.3);
223
- });
229
+ setTransform((transform) => {
230
+ transform.scale = Math.max(transform.scale / 1.3, 1);
231
+ }, true);
232
+ } }) })), _jsx("li", Object.assign({}, styled('image-preview__toolbar-zoom-in'), { children: _jsx(Button, { pattern: "text", icon: _jsx(Icon, { children: _jsx(ZoomInOutlined, {}) }), onClick: () => {
233
+ setTransform((transform) => {
234
+ transform.scale = transform.scale * 1.3;
235
+ }, true);
224
236
  } }) })), _jsx("li", Object.assign({}, styled('image-preview__toolbar-close'), { children: _jsx(Button, { pattern: "text", icon: _jsx(Icon, { children: _jsx(CloseOutlined, {}) }), onClick: () => {
225
237
  onClose === null || onClose === void 0 ? void 0 : onClose();
226
- } }) }))] })), _jsx("img", Object.assign({}, list[active], mergeCS(styled('image-preview__img'), {
238
+ } }) }))] })), list.map((img, index) => (_jsx("div", Object.assign({}, mergeCS(styled('image-preview__img-wrapper'), {
227
239
  style: {
228
- transform: `translate(${activePosition.left}px, ${activePosition.top}px) rotate(${activeRotate}deg) scale(${activeScale})`,
240
+ display: index === active ? undefined : 'none',
229
241
  },
230
- }), { tabIndex: -1, onMouseDown: (e) => {
231
- if (e.button === 0) {
232
- e.preventDefault();
242
+ }), { children: _jsx("img", Object.assign({}, img, styled('image-preview__img'), { tabIndex: -1, "data-index": index, onMouseDown: (e) => {
243
+ if (e.button === 0) {
244
+ e.preventDefault();
245
+ e.currentTarget.focus({ preventScroll: true });
246
+ dataRef.current.eventData = {};
247
+ setIsDragging(true);
248
+ }
249
+ }, onMouseUp: (e) => {
250
+ if (e.button === 0) {
251
+ e.preventDefault();
252
+ }
253
+ }, onTouchStart: (e) => {
254
+ var _a, _b;
233
255
  e.currentTarget.focus({ preventScroll: true });
234
256
  dataRef.current.eventData = {};
235
- setIsDragging(true);
236
- }
237
- }, onMouseUp: (e) => {
238
- if (e.button === 0) {
239
- e.preventDefault();
240
- }
241
- }, onTouchStart: (e) => {
242
- e.currentTarget.focus({ preventScroll: true });
243
- dataRef.current.eventData = {};
244
- setIsDragging(true);
245
- }, onTouchEnd: () => {
246
- setIsDragging(false);
247
- }, onWheel: (e) => {
248
- setScale((draft) => {
249
- var _a;
250
- const oldScale = (_a = draft.get(activeSrc)) !== null && _a !== void 0 ? _a : 1;
251
- draft.set(activeSrc, e.deltaY < 0 ? oldScale + 0.1 : Math.max(oldScale - 0.1, 1));
252
- });
253
- } })), _jsx("ul", Object.assign({}, styled('image-preview__thumbnail-list'), { children: list.map((imgProps, index) => index >= startIndex &&
257
+ if (e.touches.length === 1) {
258
+ setIsDragging(true);
259
+ }
260
+ else if (e.touches.length === 2) {
261
+ dataRef.current.initialScale = (_b = (_a = dataRef.current.transform.get(active)) === null || _a === void 0 ? void 0 : _a.scale) !== null && _b !== void 0 ? _b : 1;
262
+ dataRef.current.mouse = {
263
+ x: Math.min(e.touches[0].clientX, e.touches[1].clientX) + Math.abs(e.touches[0].clientX - e.touches[1].clientX),
264
+ y: Math.min(e.touches[0].clientY, e.touches[1].clientY) + Math.abs(e.touches[0].clientY - e.touches[1].clientY),
265
+ };
266
+ }
267
+ }, onTouchEnd: (e) => {
268
+ if (e.touches.length === 1) {
269
+ dataRef.current.eventData.initialTouches = dataRef.current.eventData.currentTouches = undefined;
270
+ }
271
+ else {
272
+ setIsDragging(false);
273
+ }
274
+ }, onWheel: (e) => {
275
+ setTransform((transform) => {
276
+ transform.scale =
277
+ e.deltaY < 0 ? transform.scale + transform.scale * 0.1 : Math.max(transform.scale - transform.scale * 0.1, 1);
278
+ });
279
+ } })) }), index))), _jsx("ul", Object.assign({}, styled('image-preview__thumbnail-list'), { children: list.map((imgProps, index) => index >= startIndex &&
254
280
  index <= endIndex && (_createElement("li", Object.assign({}, styled('image-preview__thumbnail', {
255
281
  'image-preview__thumbnail.is-active': active === index,
256
282
  }), { key: index, onClick: () => {
package/image/types.d.ts CHANGED
@@ -8,6 +8,11 @@ export interface ImageProps extends BaseProps<'image', typeof CLASSES>, Omit<Rea
8
8
  error?: React.ReactNode;
9
9
  actions?: React.ReactElement[];
10
10
  }
11
+ export interface ImageLoaderProps<K extends keyof HTMLImageElement = 'naturalWidth' | 'naturalHeight'> {
12
+ src: string;
13
+ keys?: K[];
14
+ children: (img: Pick<HTMLImageElement, K>) => JSX.Element | null;
15
+ }
11
16
  export interface ImageActionProps extends BaseProps<'image', typeof CLASSES>, React.ButtonHTMLAttributes<HTMLButtonElement> {
12
17
  }
13
18
  export interface ImagePreviewProps extends BaseProps<'image-preview', typeof PREVIEW_CLASSES>, Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
package/image/vars.d.ts CHANGED
@@ -14,10 +14,9 @@ export declare const PREVIEW_CLASSES: {
14
14
  'image-preview__toolbar-page-input': string;
15
15
  'image-preview__toolbar-rotate': string;
16
16
  'image-preview__toolbar-zoom-out': string;
17
- 'image-preview__toolbar-zoom': string;
18
- 'image-preview__toolbar-zoom-input': string;
19
17
  'image-preview__toolbar-zoom-in': string;
20
18
  'image-preview__toolbar-close': string;
19
+ 'image-preview__img-wrapper': string;
21
20
  'image-preview__img': string;
22
21
  'image-preview__thumbnail-list': string;
23
22
  'image-preview__thumbnail': string;
package/image/vars.js CHANGED
@@ -14,10 +14,9 @@ export const PREVIEW_CLASSES = {
14
14
  'image-preview__toolbar-page-input': '^image-preview__toolbar-page-input',
15
15
  'image-preview__toolbar-rotate': '^image-preview__toolbar-rotate',
16
16
  'image-preview__toolbar-zoom-out': '^image-preview__toolbar-zoom-out',
17
- 'image-preview__toolbar-zoom': '^image-preview__toolbar-zoom',
18
- 'image-preview__toolbar-zoom-input': '^image-preview__toolbar-zoom-input',
19
17
  'image-preview__toolbar-zoom-in': '^image-preview__toolbar-zoom-in',
20
18
  'image-preview__toolbar-close': '^image-preview__toolbar-close',
19
+ 'image-preview__img-wrapper': '^image-preview__img-wrapper',
21
20
  'image-preview__img': '^image-preview__img',
22
21
  'image-preview__thumbnail-list': '^image-preview__thumbnail-list',
23
22
  'image-preview__thumbnail': '^image-preview__thumbnail',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@laser-ui/components",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "React components.",
5
5
  "keywords": [
6
6
  "ui",
@@ -40,5 +40,5 @@
40
40
  "access": "public",
41
41
  "directory": "../../dist/libs/components"
42
42
  },
43
- "gitHead": "316da1ed34c626ca27819993998c0a745455d0b4"
43
+ "gitHead": "d370cebd8849f88aec086791221e6d08fbe27192"
44
44
  }