@uxf/core-react 11.124.0 → 11.126.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/README.md +288 -217
- package/components/viewport-height-polyfill.js +2 -2
- package/hooks/use-media-query.js +1 -1
- package/package.json +3 -3
- package/swipeable/types.d.ts +2 -2
- package/swipeable/use-swipeable.d.ts +4 -2
package/README.md
CHANGED
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
# UXF Core-React
|
|
2
2
|
|
|
3
3
|
## Components
|
|
4
|
+
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
### Hide
|
|
7
8
|
|
|
8
9
|
Conditionally hide some jsx content.
|
|
10
|
+
|
|
9
11
|
```tsx
|
|
10
12
|
import { Hide } from "@uxf/core-react/components/hide";
|
|
11
13
|
|
|
12
|
-
<Hide when={SOME_CONDITION}
|
|
13
|
-
...some content
|
|
14
|
-
</Hide>
|
|
14
|
+
<Hide when={SOME_CONDITION}>...some content</Hide>;
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
### Show
|
|
18
18
|
|
|
19
19
|
Conditionally show some jsx content.
|
|
20
|
+
|
|
20
21
|
```tsx
|
|
21
22
|
import { Show } from "@uxf/core-react/components/show";
|
|
22
23
|
|
|
23
|
-
<Show when={SOME_CONDITION}
|
|
24
|
-
...some content
|
|
25
|
-
</Show>
|
|
24
|
+
<Show when={SOME_CONDITION}>...some content</Show>;
|
|
26
25
|
```
|
|
27
26
|
|
|
28
27
|
### ViewportHeightPolyfill
|
|
@@ -30,13 +29,15 @@ import { Show } from "@uxf/core-react/components/show";
|
|
|
30
29
|
Polyfill for custom css variable `--viewport-height` to mimic functionality of browser's [dynamic viewport height](https://web.dev/blog/viewport-units).
|
|
31
30
|
|
|
32
31
|
Add component to react app root (eg. `_app.tsx`).
|
|
32
|
+
|
|
33
33
|
```tsx
|
|
34
34
|
import { ViewportHeightPolyfill } from "@uxf/core-react/components/viewport-height-polyfill";
|
|
35
35
|
|
|
36
|
-
<ViewportHeightPolyfill
|
|
36
|
+
<ViewportHeightPolyfill />;
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
Add css variable declaration with fallback to app global styles (eg. `base.css`) if already not there.
|
|
40
|
+
|
|
40
41
|
```css
|
|
41
42
|
:root {
|
|
42
43
|
--viewport-height: 100vh;
|
|
@@ -48,10 +49,13 @@ Add css variable declaration with fallback to app global styles (eg. `base.css`)
|
|
|
48
49
|
```
|
|
49
50
|
|
|
50
51
|
## Hooks
|
|
52
|
+
|
|
51
53
|
---
|
|
54
|
+
|
|
52
55
|
### useBodyScrollLock
|
|
53
56
|
|
|
54
57
|
Lock scrolling on body element. Useful for modals, popovers, etc.
|
|
58
|
+
|
|
55
59
|
```tsx
|
|
56
60
|
import { useBodyScrollLock } from "@uxf/core-react/hooks/use-body-scroll-lock";
|
|
57
61
|
import { useState } from "react";
|
|
@@ -62,32 +66,49 @@ const [isOpen, setIsOpen] = useState<boolean>();
|
|
|
62
66
|
const clearAllOnclose = false;
|
|
63
67
|
|
|
64
68
|
useBodyScrollLock<HTMLDivElement>(innerRef, isOpen, {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
allowTouchMove: undefined, // https://github.com/willmcpo/body-scroll-lock#allowtouchmove
|
|
70
|
+
clearAllOnClose: false, // optionally call clearAllBodyScrollLocks method on unmount
|
|
71
|
+
reserveScrollBarGap: undefined, // https://github.com/willmcpo/body-scroll-lock#reservescrollbargap
|
|
68
72
|
});
|
|
69
73
|
|
|
70
|
-
<div ref={innerRef}>Element which activates scroll lock on its parent elements.</div
|
|
74
|
+
<div ref={innerRef}>Element which activates scroll lock on its parent elements.</div>;
|
|
71
75
|
```
|
|
76
|
+
|
|
72
77
|
---
|
|
78
|
+
|
|
73
79
|
### isMounted
|
|
80
|
+
|
|
74
81
|
Check if component is mounted.
|
|
82
|
+
|
|
75
83
|
```tsx
|
|
76
84
|
import { useIsMounted } from "@uxf/core-react/hooks/use-is-mounted";
|
|
77
85
|
|
|
78
86
|
const isMounted = useIsMounted();
|
|
79
87
|
```
|
|
88
|
+
|
|
80
89
|
---
|
|
90
|
+
|
|
81
91
|
### useIsomorphicLayoutEffect
|
|
92
|
+
|
|
82
93
|
Returns `useEffect` on client and `useLayoutEffect` on server.
|
|
94
|
+
|
|
83
95
|
```tsx
|
|
84
96
|
import { useIsomorphicLayoutEffect } from "@uxf/core-react/hooks/use-isomorphic-layout-effect";
|
|
85
97
|
|
|
86
|
-
useIsomorphicLayoutEffect(
|
|
98
|
+
useIsomorphicLayoutEffect(
|
|
99
|
+
() => {
|
|
100
|
+
/* code */
|
|
101
|
+
},
|
|
102
|
+
[/* deps */],
|
|
103
|
+
);
|
|
87
104
|
```
|
|
105
|
+
|
|
88
106
|
---
|
|
107
|
+
|
|
89
108
|
### useKey
|
|
109
|
+
|
|
90
110
|
Trigger callback on given key.
|
|
111
|
+
|
|
91
112
|
```tsx
|
|
92
113
|
import { useKey } from "@uxf/core-react/hooks/use-key";
|
|
93
114
|
import { useRef } from "react";
|
|
@@ -96,19 +117,24 @@ const targetRef = useRef<HTMLDivElement>(null);
|
|
|
96
117
|
const disabled = false; // eg. for passing disabled state
|
|
97
118
|
|
|
98
119
|
useKey<HTMLDivElement>("Enter", () => console.log("callback"), {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
120
|
+
disabled,
|
|
121
|
+
targetRef, // if not provided, then `document` will be used
|
|
122
|
+
type: "keydown",
|
|
102
123
|
});
|
|
103
124
|
|
|
104
|
-
<div ref={targetRef} tabIndex={0}>
|
|
125
|
+
<div ref={targetRef} tabIndex={0}>
|
|
126
|
+
Element with callback triggerable by enter key.
|
|
127
|
+
</div>;
|
|
105
128
|
```
|
|
129
|
+
|
|
106
130
|
---
|
|
131
|
+
|
|
107
132
|
### useMinWindowWidth
|
|
108
133
|
|
|
109
134
|
> **Deprecated** — Use `useMediaQuery` instead.
|
|
110
135
|
|
|
111
136
|
Returns boolean if window width is equal or greater than given value.
|
|
137
|
+
|
|
112
138
|
```tsx
|
|
113
139
|
import { useMinWindowWidth } from "@uxf/core-react/hooks/use-min-window-width";
|
|
114
140
|
|
|
@@ -118,25 +144,37 @@ const isDesktopWithDebounce = useMinWindowWidth(1200, 200); // will be updated e
|
|
|
118
144
|
const example = isDesktop ? "desktop" : "tablet";
|
|
119
145
|
const debouncedExample = isDesktopWithDebounce ? "debouncedDesktop" : "debouncedTablet";
|
|
120
146
|
```
|
|
147
|
+
|
|
121
148
|
---
|
|
149
|
+
|
|
122
150
|
### usePagination
|
|
151
|
+
|
|
123
152
|
Returns array of pagination items.
|
|
153
|
+
|
|
124
154
|
```ts
|
|
125
155
|
import { usePagination } from "@uxf/core-react/hooks/use-pagination";
|
|
126
156
|
|
|
127
|
-
const paginationItems = usePagination({ page: 1, count: 10 })
|
|
157
|
+
const paginationItems = usePagination({ page: 1, count: 10 });
|
|
128
158
|
```
|
|
159
|
+
|
|
129
160
|
---
|
|
161
|
+
|
|
130
162
|
### useRafState
|
|
163
|
+
|
|
131
164
|
Updates state only in the callback of `requestAnimationFrame`.
|
|
165
|
+
|
|
132
166
|
```tsx
|
|
133
167
|
import { useRafState } from "@uxf/core-react/hooks/use-raf-state";
|
|
134
168
|
|
|
135
169
|
const [state, setState] = useRafState<boolean>(false);
|
|
136
170
|
```
|
|
171
|
+
|
|
137
172
|
---
|
|
173
|
+
|
|
138
174
|
### useOnMount
|
|
175
|
+
|
|
139
176
|
Calls the callback on component mount.
|
|
177
|
+
|
|
140
178
|
```tsx
|
|
141
179
|
import { useOnUnmount } from "@uxf/core-react/hooks/use-on-unmount";
|
|
142
180
|
|
|
@@ -144,17 +182,30 @@ const exampleCallback = () => {};
|
|
|
144
182
|
|
|
145
183
|
useOnUnmount(exampleCallback());
|
|
146
184
|
```
|
|
185
|
+
|
|
147
186
|
---
|
|
187
|
+
|
|
148
188
|
### useOnUpdate
|
|
189
|
+
|
|
149
190
|
Calls the callback only on component update, except initial mount.
|
|
191
|
+
|
|
150
192
|
```tsx
|
|
151
193
|
import { useOnUpdate } from "@uxf/core-react/hooks/use-on-update";
|
|
152
194
|
|
|
153
|
-
useOnUpdate(
|
|
195
|
+
useOnUpdate(
|
|
196
|
+
() => {
|
|
197
|
+
/* code */
|
|
198
|
+
},
|
|
199
|
+
[/* deps */],
|
|
200
|
+
);
|
|
154
201
|
```
|
|
202
|
+
|
|
155
203
|
---
|
|
204
|
+
|
|
156
205
|
### useWindowScroll
|
|
206
|
+
|
|
157
207
|
Returns x and y scroll coordinates of window on scroll.
|
|
208
|
+
|
|
158
209
|
```tsx
|
|
159
210
|
import { useWindowScroll } from "@uxf/core-react/hooks/use-window-scroll";
|
|
160
211
|
|
|
@@ -162,9 +213,13 @@ const windowScroll = useWindowScroll();
|
|
|
162
213
|
|
|
163
214
|
const example = windowScroll && windowScroll.y > 100 ? "scroled" : "on top";
|
|
164
215
|
```
|
|
216
|
+
|
|
165
217
|
---
|
|
218
|
+
|
|
166
219
|
### useWindowSize
|
|
220
|
+
|
|
167
221
|
Returns window width and height.
|
|
222
|
+
|
|
168
223
|
```tsx
|
|
169
224
|
import { useWindowSize } from "@uxf/core-react/hooks/use-window-size";
|
|
170
225
|
|
|
@@ -172,9 +227,13 @@ const windowSize = useWindowSize();
|
|
|
172
227
|
|
|
173
228
|
const example = windowSize && windowSize.width > 1200 ? "desktop" : "tablet";
|
|
174
229
|
```
|
|
230
|
+
|
|
175
231
|
---
|
|
232
|
+
|
|
176
233
|
### useFocusTrap
|
|
234
|
+
|
|
177
235
|
Locks focus inside given element.
|
|
236
|
+
|
|
178
237
|
```tsx
|
|
179
238
|
import { useFocusTrap } from "@uxf/core-react/hooks/use-focus-trap";
|
|
180
239
|
import { useState } from "react";
|
|
@@ -183,11 +242,15 @@ const [active, setActive] = useState<boolean>();
|
|
|
183
242
|
|
|
184
243
|
const focusTrapRef = useFocusTrap(active);
|
|
185
244
|
|
|
186
|
-
<div ref={focusTrapRef}>Element which trap focus inside if `active` is truthy.</div
|
|
245
|
+
<div ref={focusTrapRef}>Element which trap focus inside if `active` is truthy.</div>;
|
|
187
246
|
```
|
|
247
|
+
|
|
188
248
|
---
|
|
249
|
+
|
|
189
250
|
### useFocusReturn
|
|
251
|
+
|
|
190
252
|
Returns focus to last active element.
|
|
253
|
+
|
|
191
254
|
```tsx
|
|
192
255
|
import { useFocusReturn } from "@uxf/core-react/hooks/use-focus-return";
|
|
193
256
|
import { useState } from "react";
|
|
@@ -197,113 +260,128 @@ const [active, setActive] = useState<boolean>();
|
|
|
197
260
|
// Returns focus to last active element, e.g. in Modal or Popover
|
|
198
261
|
useFocusReturn(active);
|
|
199
262
|
```
|
|
263
|
+
|
|
200
264
|
---
|
|
265
|
+
|
|
201
266
|
### useAnchorProps
|
|
267
|
+
|
|
202
268
|
Returns props for anchor element.
|
|
269
|
+
|
|
203
270
|
```tsx
|
|
204
271
|
import { useAnchorProps } from "@uxf/core-react/clickable/use-anchor-props";
|
|
205
272
|
import { AnchorHTMLAttributes } from "react";
|
|
206
273
|
|
|
207
274
|
// extends <a /> by `analyticsCallback`, `disabled`, `loading`, `submit` props
|
|
208
275
|
const anchorProps = useAnchorProps<AnchorHTMLAttributes<HTMLAnchorElement>>({
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
276
|
+
analyticsCallback: () => console.log("analytics"),
|
|
277
|
+
disabled: false,
|
|
278
|
+
href: "https://www.google.com/",
|
|
279
|
+
loading: false,
|
|
280
|
+
onClick: () => console.log("success"),
|
|
281
|
+
type: "submit", // simulate <button type="submit" /> function
|
|
215
282
|
});
|
|
216
283
|
|
|
217
|
-
<a {...anchorProps}>Click me</a
|
|
284
|
+
<a {...anchorProps}>Click me</a>;
|
|
218
285
|
|
|
219
286
|
// example with generics
|
|
220
287
|
import { UseAnchorProps, useAnchorProps } from "@uxf/core-react/clickable/use-anchor-props";
|
|
221
288
|
import { AnchorHTMLAttributes } from "react";
|
|
222
289
|
|
|
223
290
|
interface Props extends UseAnchorProps, AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
224
|
-
|
|
291
|
+
customProp?: boolean;
|
|
225
292
|
}
|
|
226
293
|
|
|
227
294
|
const anchorProps = useAnchorProps<Props>({
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
295
|
+
customProp: true,
|
|
296
|
+
loading: false,
|
|
297
|
+
href: "https://www.google.com/",
|
|
231
298
|
});
|
|
232
299
|
|
|
233
|
-
<a {...anchorProps}>Click me</a
|
|
234
|
-
|
|
300
|
+
<a {...anchorProps}>Click me</a>;
|
|
235
301
|
```
|
|
302
|
+
|
|
236
303
|
---
|
|
304
|
+
|
|
237
305
|
### useButtonProps
|
|
306
|
+
|
|
238
307
|
Returns props for button element.
|
|
308
|
+
|
|
239
309
|
```tsx
|
|
240
310
|
import { useButtonProps } from "@uxf/core-react/clickable/use-button-props";
|
|
241
311
|
import { ButtonHTMLAttributes } from "react";
|
|
242
312
|
|
|
243
313
|
// extends <button /> by `analyticsCallback` and `loading` props
|
|
244
314
|
const buttonProps = useButtonProps<ButtonHTMLAttributes<HTMLButtonElement>>({
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
315
|
+
analyticsCallback: () => console.log("analytics"),
|
|
316
|
+
disabled: false,
|
|
317
|
+
loading: false,
|
|
318
|
+
onClick: () => console.log("success"),
|
|
319
|
+
type: "submit",
|
|
250
320
|
});
|
|
251
321
|
|
|
252
|
-
<button {...buttonProps}>Click me</button
|
|
322
|
+
<button {...buttonProps}>Click me</button>;
|
|
253
323
|
|
|
254
324
|
// example with generics
|
|
255
325
|
import { UseButtonProps, useButtonProps } from "@uxf/core-react/clickable/use-button-props";
|
|
256
326
|
import { ButtonHTMLAttributes } from "react";
|
|
257
327
|
|
|
258
328
|
interface Props extends UseButtonProps, ButtonHTMLAttributes<HTMLButtonElement> {
|
|
259
|
-
|
|
329
|
+
customProp?: boolean;
|
|
260
330
|
}
|
|
261
331
|
|
|
262
332
|
const buttonProps = useButtonProps<Props>({
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
333
|
+
customProp: true,
|
|
334
|
+
loading: false,
|
|
335
|
+
type: "submit",
|
|
266
336
|
});
|
|
267
337
|
|
|
268
|
-
<button {...buttonProps}>Click me</button
|
|
338
|
+
<button {...buttonProps}>Click me</button>;
|
|
269
339
|
```
|
|
340
|
+
|
|
270
341
|
---
|
|
342
|
+
|
|
271
343
|
### useClickableProps
|
|
344
|
+
|
|
272
345
|
Returns props for clickable element.
|
|
346
|
+
|
|
273
347
|
```tsx
|
|
274
348
|
import { useClickableProps } from "@uxf/core-react/clickable/use-clickable-props";
|
|
275
349
|
import { HTMLAttributes } from "react";
|
|
276
350
|
|
|
277
351
|
// extends any HTML element by `analyticsCallback`, `disabled`, `loading`, `submit` props
|
|
278
352
|
const clickableProps = useClickableProps<HTMLAttributes<HTMLDivElement>>({
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
353
|
+
analyticsCallback: () => console.log("analytics"),
|
|
354
|
+
disabled: false,
|
|
355
|
+
loading: false,
|
|
356
|
+
onClick: () => console.log("success"),
|
|
357
|
+
type: "submit", // simulate <button type="submit" /> function
|
|
284
358
|
});
|
|
285
359
|
|
|
286
|
-
<div {...clickableProps}>Click me</div
|
|
360
|
+
<div {...clickableProps}>Click me</div>;
|
|
287
361
|
|
|
288
362
|
// example with generics
|
|
289
363
|
import { UseClickableProps, useClickableProps } from "@uxf/core-react/clickable/use-clickable-props";
|
|
290
364
|
import { HTMLAttributes } from "react";
|
|
291
365
|
|
|
292
366
|
interface Props extends UseClickableProps, HTMLAttributes<HTMLDivElement> {
|
|
293
|
-
|
|
367
|
+
customProp?: boolean;
|
|
294
368
|
}
|
|
295
369
|
|
|
296
370
|
const buttonProps = useClickableProps<Props>({
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
371
|
+
customProp: true,
|
|
372
|
+
hidden: false,
|
|
373
|
+
loading: false,
|
|
300
374
|
});
|
|
301
375
|
|
|
302
|
-
<button {...buttonProps}>Click me</button
|
|
376
|
+
<button {...buttonProps}>Click me</button>;
|
|
303
377
|
```
|
|
378
|
+
|
|
304
379
|
---
|
|
380
|
+
|
|
305
381
|
### useMouseDragToScroll
|
|
382
|
+
|
|
306
383
|
Allow to scroll element by dragging mouse.
|
|
384
|
+
|
|
307
385
|
```tsx
|
|
308
386
|
import { useMouseDragToScroll } from "@uxf/core-react/hooks/use-mouse-drag-to-scroll";
|
|
309
387
|
|
|
@@ -311,11 +389,15 @@ const targetRef = useRef<HTMLDivElement>(null);
|
|
|
311
389
|
|
|
312
390
|
const style = useMouseDragToScroll(scrollRef);
|
|
313
391
|
|
|
314
|
-
<div style={style}>Drag to scroll</div
|
|
392
|
+
<div style={style}>Drag to scroll</div>;
|
|
315
393
|
```
|
|
394
|
+
|
|
316
395
|
---
|
|
396
|
+
|
|
317
397
|
### useInputFocus
|
|
398
|
+
|
|
318
399
|
Manage focus states of input element.
|
|
400
|
+
|
|
319
401
|
```tsx
|
|
320
402
|
import { useInputFocus } from "@uxf/core-react/hooks/use-input-focus";
|
|
321
403
|
|
|
@@ -328,53 +410,73 @@ const input = useInputFocus(focusRef, onBlur, onFocus);
|
|
|
328
410
|
<button onClick={input.focus}>Focus input</button>
|
|
329
411
|
<input onBlur={input.onBlur} onFocus={input.onFocus} ref={focusRef} />
|
|
330
412
|
```
|
|
413
|
+
|
|
331
414
|
---
|
|
415
|
+
|
|
332
416
|
### useLatest
|
|
417
|
+
|
|
333
418
|
Allways returns latest value of given variable.
|
|
419
|
+
|
|
334
420
|
```tsx
|
|
335
421
|
import { useLatest } from "@uxf/core-react/hooks/use-latest";
|
|
336
422
|
|
|
337
423
|
const latestState = useLatest(someUnstableWhatever);
|
|
338
424
|
|
|
339
425
|
useEffect(() => {
|
|
340
|
-
|
|
341
|
-
}, [latestState])
|
|
426
|
+
latestState.current(); // use newest state of 'someUnstableWhatever' without affecting this effetct update
|
|
427
|
+
}, [latestState]);
|
|
342
428
|
```
|
|
429
|
+
|
|
343
430
|
---
|
|
431
|
+
|
|
344
432
|
### usePrevious
|
|
433
|
+
|
|
345
434
|
Returns previous value of given variable.
|
|
435
|
+
|
|
346
436
|
```tsx
|
|
347
437
|
import { usePrevious } from "@uxf/core-react/hooks/use-previous";
|
|
348
438
|
|
|
349
439
|
const previousState = usePrevious(someUnstableWhatever);
|
|
350
440
|
|
|
351
441
|
useEffect(() => {
|
|
352
|
-
|
|
353
|
-
}, [previousState])
|
|
442
|
+
previousState.current(); // use state of 'someUnstableWhatever' from previous render without affecting this effetct update
|
|
443
|
+
}, [previousState]);
|
|
354
444
|
```
|
|
445
|
+
|
|
355
446
|
---
|
|
447
|
+
|
|
356
448
|
### useToggle
|
|
449
|
+
|
|
357
450
|
Returns boolean state and methods to toggle it.
|
|
451
|
+
|
|
358
452
|
```tsx
|
|
359
453
|
import { useToggle } from "@uxf/core-react/hooks/use-toggle";
|
|
360
454
|
|
|
361
455
|
const [isVisible, toggleIsVisible, setVisible, setInvisible] = useToggle(false);
|
|
362
456
|
|
|
363
|
-
<button onClick={toggleIsVisible}>Toggle visibility</button
|
|
457
|
+
<button onClick={toggleIsVisible}>Toggle visibility</button>;
|
|
364
458
|
```
|
|
459
|
+
|
|
365
460
|
---
|
|
461
|
+
|
|
366
462
|
### useIncrement
|
|
463
|
+
|
|
367
464
|
Returns number state and methods to increment, decrement and reset.
|
|
465
|
+
|
|
368
466
|
```tsx
|
|
369
467
|
import { useIncrement } from "@uxf/core-react/hooks/use-increment";
|
|
370
468
|
|
|
371
469
|
const [count, increment, decrement, reset] = useIncrement(5, 1);
|
|
372
470
|
|
|
373
|
-
<button onClick={increment}>Toggle visibility</button
|
|
471
|
+
<button onClick={increment}>Toggle visibility</button>;
|
|
374
472
|
```
|
|
473
|
+
|
|
375
474
|
---
|
|
475
|
+
|
|
376
476
|
### useDebounce
|
|
477
|
+
|
|
377
478
|
Returns the latest value after given delay.
|
|
479
|
+
|
|
378
480
|
```tsx
|
|
379
481
|
import { useDebounce } from "@uxf/core-react/hooks/use-debounce";
|
|
380
482
|
|
|
@@ -386,10 +488,13 @@ const debouncedValue = useDebounce<string>("some value", 300);
|
|
|
386
488
|
```tsx
|
|
387
489
|
import { nl2br } from "@uxf/core-react/string/nl2br";
|
|
388
490
|
|
|
389
|
-
<div>{nl2br("Hello\nWorld")}</div
|
|
491
|
+
<div>{nl2br("Hello\nWorld")}</div>;
|
|
390
492
|
```
|
|
493
|
+
|
|
391
494
|
---
|
|
495
|
+
|
|
392
496
|
### useMediaQuery
|
|
497
|
+
|
|
393
498
|
Returns whether the given media query is currently matched. Optionally accepts a callback that is called on every change.
|
|
394
499
|
|
|
395
500
|
Uses `window.matchMedia` with a `change` event listener (via `AbortController`) for efficient updates.
|
|
@@ -415,9 +520,10 @@ const isDesktopClientOnly = useMediaQuery(`(min-width: ${twScreens.sm})`, undefi
|
|
|
415
520
|
```
|
|
416
521
|
|
|
417
522
|
**Parameters:**
|
|
523
|
+
|
|
418
524
|
- `mediaQueryString` – CSS media query string
|
|
419
|
-
- `callback`
|
|
420
|
-
- `isSSR`
|
|
525
|
+
- `callback` _(optional)_ – called with `(isMatching, mediaQueryString)` on every match change
|
|
526
|
+
- `isSSR` _(optional, default: `true`)_ – when `true`, initial state is `false` to avoid SSR/hydration mismatch; when `false`, initial state is read directly from `window.matchMedia` (use only in client-only components)
|
|
421
527
|
|
|
422
528
|
## Drag and Drop (DND) Hooks
|
|
423
529
|
|
|
@@ -431,16 +537,17 @@ Low-level hook that provides the core drag-and-drop functionality. Used as a bui
|
|
|
431
537
|
import { useSortableCore } from "@uxf/core-react/dnd/hooks/use-sortable-core";
|
|
432
538
|
|
|
433
539
|
const {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
540
|
+
activeElement, // Currently dragged element
|
|
541
|
+
setActiveElement, // Set active element manually
|
|
542
|
+
onDragStart, // Drag start handler
|
|
543
|
+
onDragCancel, // Drag cancel handler
|
|
544
|
+
sensors, // DND sensors (pointer, keyboard)
|
|
545
|
+
dropAnimationConfig, // Animation configuration for drop
|
|
440
546
|
} = useSortableCore();
|
|
441
547
|
```
|
|
442
548
|
|
|
443
549
|
---
|
|
550
|
+
|
|
444
551
|
### useSortableSingle
|
|
445
552
|
|
|
446
553
|
Hook for implementing drag-and-drop sorting within a single list. Manages item reordering and state internally.
|
|
@@ -452,58 +559,51 @@ import { useSortableSingle } from "@uxf/core-react/dnd/hooks/use-sortable-single
|
|
|
452
559
|
import { SortableItem } from "./sortable-item"; // Your sortable item component
|
|
453
560
|
|
|
454
561
|
interface Task {
|
|
455
|
-
|
|
456
|
-
|
|
562
|
+
id: string;
|
|
563
|
+
title: string;
|
|
457
564
|
}
|
|
458
565
|
|
|
459
566
|
function TaskList() {
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
))}
|
|
496
|
-
</SortableContext>
|
|
497
|
-
|
|
498
|
-
<DragOverlay dropAnimation={dropAnimationConfig}>
|
|
499
|
-
{activeItem ? <div>{activeItem.title}</div> : null}
|
|
500
|
-
</DragOverlay>
|
|
501
|
-
</DndContext>
|
|
502
|
-
);
|
|
567
|
+
const initialTasks: Task[] = [
|
|
568
|
+
{ id: "1", title: "Write documentation" },
|
|
569
|
+
{ id: "2", title: "Review PR" },
|
|
570
|
+
{ id: "3", title: "Deploy to production" },
|
|
571
|
+
];
|
|
572
|
+
|
|
573
|
+
const {
|
|
574
|
+
items, // Current items state
|
|
575
|
+
setItems, // Update items manually
|
|
576
|
+
activeItem, // Currently dragged item
|
|
577
|
+
onDragStart,
|
|
578
|
+
onDragEnd,
|
|
579
|
+
onDragCancel,
|
|
580
|
+
sensors,
|
|
581
|
+
dropAnimationConfig,
|
|
582
|
+
} = useSortableSingle(initialTasks, (fromIndex, toIndex, updatedList) => {
|
|
583
|
+
// Optional callback when items are reordered
|
|
584
|
+
console.log(`Moved from ${fromIndex} to ${toIndex}`, updatedList);
|
|
585
|
+
});
|
|
586
|
+
|
|
587
|
+
return (
|
|
588
|
+
<DndContext sensors={sensors} onDragStart={onDragStart} onDragEnd={onDragEnd} onDragCancel={onDragCancel}>
|
|
589
|
+
<SortableContext items={items.map((item) => item.id)} strategy={verticalListSortingStrategy}>
|
|
590
|
+
{items.map((task) => (
|
|
591
|
+
<SortableItem key={task.id} id={task.id}>
|
|
592
|
+
{task.title}
|
|
593
|
+
</SortableItem>
|
|
594
|
+
))}
|
|
595
|
+
</SortableContext>
|
|
596
|
+
|
|
597
|
+
<DragOverlay dropAnimation={dropAnimationConfig}>
|
|
598
|
+
{activeItem ? <div>{activeItem.title}</div> : null}
|
|
599
|
+
</DragOverlay>
|
|
600
|
+
</DndContext>
|
|
601
|
+
);
|
|
503
602
|
}
|
|
504
603
|
```
|
|
505
604
|
|
|
506
605
|
---
|
|
606
|
+
|
|
507
607
|
### useSortableMulti
|
|
508
608
|
|
|
509
609
|
Hook for implementing drag-and-drop between multiple sections/lists. Ideal for kanban boards, categorized lists, or visible/hidden column management.
|
|
@@ -515,89 +615,80 @@ import { useSortableMulti } from "@uxf/core-react/dnd/hooks/use-sortable-multi";
|
|
|
515
615
|
import { SortableItem } from "./sortable-item"; // Your sortable item component
|
|
516
616
|
|
|
517
617
|
interface Task {
|
|
518
|
-
|
|
519
|
-
|
|
618
|
+
id: string;
|
|
619
|
+
title: string;
|
|
520
620
|
}
|
|
521
621
|
|
|
522
622
|
interface Sections {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
623
|
+
todo: Task[];
|
|
624
|
+
inProgress: Task[];
|
|
625
|
+
done: Task[];
|
|
526
626
|
}
|
|
527
627
|
|
|
528
628
|
function KanbanBoard() {
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
>
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
))}
|
|
581
|
-
</SortableContext>
|
|
582
|
-
</div>
|
|
583
|
-
))}
|
|
584
|
-
</div>
|
|
585
|
-
|
|
586
|
-
<DragOverlay dropAnimation={dropAnimationConfig}>
|
|
587
|
-
{activeItem ? <div>{activeItem.title}</div> : null}
|
|
588
|
-
</DragOverlay>
|
|
589
|
-
</DndContext>
|
|
590
|
-
);
|
|
629
|
+
const [sections, setSections] = useState<Sections>({
|
|
630
|
+
todo: [
|
|
631
|
+
{ id: "1", title: "Design UI" },
|
|
632
|
+
{ id: "2", title: "Write tests" },
|
|
633
|
+
],
|
|
634
|
+
inProgress: [{ id: "3", title: "Implement feature" }],
|
|
635
|
+
done: [{ id: "4", title: "Setup project" }],
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
const {
|
|
639
|
+
getSectionItemsIds, // Get IDs for a section (handles empty sections)
|
|
640
|
+
activeItem, // Currently dragged item
|
|
641
|
+
onDragStart,
|
|
642
|
+
onDragEnd,
|
|
643
|
+
onDragCancel,
|
|
644
|
+
sensors,
|
|
645
|
+
dropAnimationConfig,
|
|
646
|
+
} = useSortableMulti<Task, Sections>(sections, setSections, (sourceKey, destKey, fromIndex, toIndex, nextState) => {
|
|
647
|
+
// Optional callback when items are moved between sections
|
|
648
|
+
console.log(`Moved from ${String(sourceKey)} to ${String(destKey)}`);
|
|
649
|
+
// Save to backend, analytics, etc.
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
return (
|
|
653
|
+
<DndContext
|
|
654
|
+
sensors={sensors}
|
|
655
|
+
collisionDetection={rectIntersection}
|
|
656
|
+
onDragStart={onDragStart}
|
|
657
|
+
onDragEnd={onDragEnd}
|
|
658
|
+
onDragCancel={onDragCancel}
|
|
659
|
+
>
|
|
660
|
+
<div className="kanban-board">
|
|
661
|
+
{(Object.keys(sections) as Array<keyof Sections>).map((sectionKey) => (
|
|
662
|
+
<div key={sectionKey} className="kanban-column">
|
|
663
|
+
<h3>{sectionKey}</h3>
|
|
664
|
+
<SortableContext items={getSectionItemsIds(sectionKey)} strategy={verticalListSortingStrategy}>
|
|
665
|
+
{sections[sectionKey].map((task) => (
|
|
666
|
+
<SortableItem key={task.id} id={task.id}>
|
|
667
|
+
{task.title}
|
|
668
|
+
</SortableItem>
|
|
669
|
+
))}
|
|
670
|
+
</SortableContext>
|
|
671
|
+
</div>
|
|
672
|
+
))}
|
|
673
|
+
</div>
|
|
674
|
+
|
|
675
|
+
<DragOverlay dropAnimation={dropAnimationConfig}>
|
|
676
|
+
{activeItem ? <div>{activeItem.title}</div> : null}
|
|
677
|
+
</DragOverlay>
|
|
678
|
+
</DndContext>
|
|
679
|
+
);
|
|
591
680
|
}
|
|
592
681
|
```
|
|
593
682
|
|
|
594
683
|
**Notes:**
|
|
684
|
+
|
|
595
685
|
- Items must have an `id: string` property
|
|
596
686
|
- `getSectionItemsIds` automatically handles empty sections by returning placeholder IDs
|
|
597
687
|
- Use `rectIntersection` collision detection for better multi-section behavior
|
|
598
688
|
- The hook manages item movement between sections automatically
|
|
599
689
|
|
|
600
690
|
---
|
|
691
|
+
|
|
601
692
|
### useSortableItems
|
|
602
693
|
|
|
603
694
|
Legacy hook for drag-and-drop sorting. Consider using `useSortableSingle` for new implementations.
|
|
@@ -605,20 +696,13 @@ Legacy hook for drag-and-drop sorting. Consider using `useSortableSingle` for ne
|
|
|
605
696
|
```tsx
|
|
606
697
|
import { useSortableItems } from "@uxf/core-react/dnd/hooks/use-sortable-items";
|
|
607
698
|
|
|
608
|
-
const {
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
onDragCancel
|
|
616
|
-
} = useSortableItems({
|
|
617
|
-
items: myItems,
|
|
618
|
-
handleDragEnd: (activeIndex, overIndex) => {
|
|
619
|
-
// Handle reorder
|
|
620
|
-
}
|
|
621
|
-
});
|
|
699
|
+
const { memoizedSensors, dropAnimationConfig, itemsIds, activeItem, onDragStart, onDragEnd, onDragCancel } =
|
|
700
|
+
useSortableItems({
|
|
701
|
+
items: myItems,
|
|
702
|
+
handleDragEnd: (activeIndex, overIndex) => {
|
|
703
|
+
// Handle reorder
|
|
704
|
+
},
|
|
705
|
+
});
|
|
622
706
|
```
|
|
623
707
|
|
|
624
708
|
---
|
|
@@ -686,16 +770,12 @@ import formTranslations from "@uxf/form/translations/cs.json";
|
|
|
686
770
|
// Create a translation function for your language
|
|
687
771
|
const t = createDefaultT({
|
|
688
772
|
...uiTranslations,
|
|
689
|
-
...formTranslations
|
|
773
|
+
...formTranslations,
|
|
690
774
|
});
|
|
691
775
|
|
|
692
776
|
// Provide the translation function to your app
|
|
693
777
|
function App() {
|
|
694
|
-
|
|
695
|
-
<TranslationsProvider value={t}>
|
|
696
|
-
{/* Your app content */}
|
|
697
|
-
</TranslationsProvider>
|
|
698
|
-
);
|
|
778
|
+
return <TranslationsProvider value={t}>{/* Your app content */}</TranslationsProvider>;
|
|
699
779
|
}
|
|
700
780
|
```
|
|
701
781
|
|
|
@@ -708,14 +788,10 @@ import { TranslationsProvider } from "@uxf/core-react/translations";
|
|
|
708
788
|
import useTranslation from "next-translate/useTranslation"; // Or any other translation library
|
|
709
789
|
|
|
710
790
|
function App() {
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
<TranslationsProvider value={t}>
|
|
716
|
-
{/* Your app content */}
|
|
717
|
-
</TranslationsProvider>
|
|
718
|
-
);
|
|
791
|
+
// Get the translation function from your translation library
|
|
792
|
+
const { t } = useTranslation();
|
|
793
|
+
|
|
794
|
+
return <TranslationsProvider value={t}>{/* Your app content */}</TranslationsProvider>;
|
|
719
795
|
}
|
|
720
796
|
```
|
|
721
797
|
|
|
@@ -727,13 +803,8 @@ To use translations in your components, use the `useUxfTranslation` hook:
|
|
|
727
803
|
import { useUxfTranslation } from "@uxf/core-react/translations";
|
|
728
804
|
|
|
729
805
|
function MyComponent() {
|
|
730
|
-
|
|
806
|
+
const t = useUxfTranslation();
|
|
731
807
|
|
|
732
|
-
|
|
733
|
-
<div>
|
|
734
|
-
{t("form:validation.required")}
|
|
735
|
-
</div>
|
|
736
|
-
);
|
|
808
|
+
return <div>{t("form:validation.required")}</div>;
|
|
737
809
|
}
|
|
738
810
|
```
|
|
739
|
-
|
|
@@ -35,10 +35,10 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
})();
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
37
|
exports.ViewportHeightPolyfill = ViewportHeightPolyfill;
|
|
38
|
-
const use_is_mounted_1 = require("@uxf/core-react/hooks/use-is-mounted");
|
|
39
|
-
const use_on_mount_1 = require("@uxf/core-react/hooks/use-on-mount");
|
|
40
38
|
const is_not_nil_1 = require("@uxf/core/utils/is-not-nil");
|
|
41
39
|
const react_1 = __importStar(require("react"));
|
|
40
|
+
const use_is_mounted_1 = require("@uxf/core-react/hooks/use-is-mounted");
|
|
41
|
+
const use_on_mount_1 = require("@uxf/core-react/hooks/use-on-mount");
|
|
42
42
|
function ViewportHeightPolyfill() {
|
|
43
43
|
const isMounted = (0, use_is_mounted_1.useIsMounted)();
|
|
44
44
|
const [viewportHeight, setViewportHeight] = (0, react_1.useState)();
|
package/hooks/use-media-query.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"use client";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.useMediaQuery = useMediaQuery;
|
|
5
|
-
const use_latest_1 = require("@uxf/core-react/hooks/use-latest");
|
|
6
5
|
const react_1 = require("react");
|
|
6
|
+
const use_latest_1 = require("@uxf/core-react/hooks/use-latest");
|
|
7
7
|
function useMediaQuery(mediaQueryString, callback, isSSR = true) {
|
|
8
8
|
const [isMatching, setIsMatching] = (0, react_1.useState)(isSSR ? false : window.matchMedia(mediaQueryString).matches);
|
|
9
9
|
const latestCallback = (0, use_latest_1.useLatest)(callback);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uxf/core-react",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.126.0",
|
|
4
4
|
"description": "UXF Core",
|
|
5
5
|
"author": "UX Fans s.r.o",
|
|
6
6
|
"license": "MIT",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"peerDependencies": {
|
|
15
15
|
"@dnd-kit/core": "^6.3.1",
|
|
16
16
|
"@dnd-kit/sortable": "^10.0.0",
|
|
17
|
-
"@uxf/core": "11.
|
|
17
|
+
"@uxf/core": "11.126.0",
|
|
18
18
|
"react": ">=18.2.0",
|
|
19
19
|
"react-dom": ">=18.2.0"
|
|
20
20
|
},
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"@dnd-kit/sortable": "^10.0.0",
|
|
24
24
|
"@types/react": "18.3.31",
|
|
25
25
|
"@types/react-dom": "18.3.7",
|
|
26
|
-
"@uxf/core": "11.
|
|
26
|
+
"@uxf/core": "11.126.0",
|
|
27
27
|
"react": "18.3.1",
|
|
28
28
|
"react-dom": "18.3.1"
|
|
29
29
|
}
|
package/swipeable/types.d.ts
CHANGED
|
@@ -134,8 +134,8 @@ export interface ConfigurationOptions {
|
|
|
134
134
|
export type SwipeableProps = Partial<SwipeableCallbacks & ConfigurationOptions>;
|
|
135
135
|
export type SwipeablePropsWithDefaultOptions = Partial<SwipeableCallbacks> & ConfigurationOptions;
|
|
136
136
|
export interface SwipeableHandlers {
|
|
137
|
-
ref(element: HTMLElement | null)
|
|
138
|
-
onMouseDown
|
|
137
|
+
ref: (element: HTMLElement | null) => void;
|
|
138
|
+
onMouseDown?: (event: React.MouseEvent) => void;
|
|
139
139
|
}
|
|
140
140
|
export type SwipeableState = {
|
|
141
141
|
cleanUpTouch?: () => void;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
import { DOWN, LEFT, RIGHT,
|
|
2
|
-
|
|
1
|
+
import { DOWN, LEFT, RIGHT, UP } from "./types";
|
|
2
|
+
import type { SwipeableHandlers, SwipeableProps } from "./types";
|
|
3
|
+
export { DOWN, LEFT, RIGHT, UP };
|
|
4
|
+
export type { SwipeableDirectionCallbacks, SwipeableHandlers, SwipeableProps, SwipeCallback, SwipeDirections, SwipeEventData, TapCallback, Vector2, } from "./types";
|
|
3
5
|
export declare function useSwipeable(options: SwipeableProps): SwipeableHandlers;
|