@zuzjs/ui 0.8.8 → 0.9.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/dist/cjs/comps/Box/index.js +5 -3
- package/dist/cjs/comps/Form/index.js +34 -10
- package/dist/cjs/comps/ProgressBar/index.d.ts +1 -0
- package/dist/cjs/comps/ProgressBar/index.js +8 -4
- package/dist/cjs/comps/ProgressBar/types.d.ts +2 -1
- package/dist/cjs/comps/Table/index.d.ts +2 -2
- package/dist/cjs/comps/Table/index.js +27 -6
- package/dist/cjs/comps/Table/types.d.ts +5 -1
- package/dist/cjs/comps/TextWheel/index.js +1 -1
- package/dist/cjs/comps/Toast/types.d.ts +3 -2
- package/dist/cjs/funs/css.js +0 -1
- package/dist/cjs/funs/stylesheet.js +4 -0
- package/dist/cjs/hooks/index.d.ts +1 -0
- package/dist/cjs/hooks/index.js +1 -0
- package/dist/cjs/hooks/useBase.d.ts +2 -2
- package/dist/cjs/hooks/useBase.js +39 -22
- package/dist/cjs/hooks/useScrollPhysics.d.ts +22 -0
- package/dist/cjs/hooks/useScrollPhysics.js +69 -0
- package/dist/cjs/hooks/useSlider.d.ts +1 -1
- package/dist/cjs/types/enums.d.ts +2 -1
- package/dist/cjs/types/enums.js +1 -0
- package/dist/cjs/types/index.d.ts +5 -0
- package/dist/cjs/types/interfaces.d.ts +9 -0
- package/dist/css/styles.css +1 -1
- package/dist/esm/comps/Box/index.js +5 -3
- package/dist/esm/comps/Form/index.js +34 -10
- package/dist/esm/comps/ProgressBar/index.d.ts +1 -0
- package/dist/esm/comps/ProgressBar/index.js +8 -4
- package/dist/esm/comps/ProgressBar/types.d.ts +2 -1
- package/dist/esm/comps/Table/index.d.ts +2 -2
- package/dist/esm/comps/Table/index.js +27 -6
- package/dist/esm/comps/Table/types.d.ts +5 -1
- package/dist/esm/comps/TextWheel/index.js +1 -1
- package/dist/esm/comps/Toast/types.d.ts +3 -2
- package/dist/esm/funs/css.js +0 -1
- package/dist/esm/funs/stylesheet.js +4 -0
- package/dist/esm/hooks/index.d.ts +1 -0
- package/dist/esm/hooks/index.js +1 -0
- package/dist/esm/hooks/useBase.d.ts +2 -2
- package/dist/esm/hooks/useBase.js +39 -22
- package/dist/esm/hooks/useScrollPhysics.d.ts +22 -0
- package/dist/esm/hooks/useScrollPhysics.js +69 -0
- package/dist/esm/hooks/useSlider.d.ts +1 -1
- package/dist/esm/types/enums.d.ts +2 -1
- package/dist/esm/types/enums.js +1 -0
- package/dist/esm/types/index.d.ts +5 -0
- package/dist/esm/types/interfaces.d.ts +9 -0
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef } from "react";
|
|
2
|
+
import { forwardRef, useMemo, useRef } from "react";
|
|
3
3
|
import { useBase } from "../../hooks";
|
|
4
4
|
const Box = forwardRef((props, ref) => {
|
|
5
5
|
const { style, withEditor, ...pops } = props;
|
|
6
|
-
const
|
|
6
|
+
const innerRef = useRef(null);
|
|
7
|
+
const targetRef = useMemo(() => ref && typeof ref !== "function" && ref.current ? ref : innerRef, [ref]);
|
|
8
|
+
const { style: _style, className, rest } = useBase(pops, targetRef);
|
|
7
9
|
// const handleInternalClick = (e: React.MouseEvent<HTMLDivElement>) => {
|
|
8
10
|
// // if ( withEditor && isBrowser ) {
|
|
9
11
|
// // // window.dispatchEvent(new CustomEvent(`ZUZ_COMP_SELECTED`, {
|
|
@@ -15,7 +17,7 @@ const Box = forwardRef((props, ref) => {
|
|
|
15
17
|
// // // }))
|
|
16
18
|
// // }
|
|
17
19
|
// }
|
|
18
|
-
return _jsx("div", { ref: ref,
|
|
20
|
+
return _jsx("div", { ref: ref || innerRef,
|
|
19
21
|
// onClick={handleInternalClick}
|
|
20
22
|
className: `${className} ${withEditor ? `--with-zuz-editor` : ``}`.trim(), style: {
|
|
21
23
|
..._style,
|
|
@@ -3,8 +3,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { withPost } from "@zuzjs/core";
|
|
4
4
|
import { forwardRef, startTransition, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
|
|
5
5
|
import { addPropsToChildren, isEmail, isEmpty } from "../../funs";
|
|
6
|
-
import { useBase } from "../../hooks";
|
|
7
|
-
import { FORMVALIDATION
|
|
6
|
+
import { useBase, useToast } from "../../hooks";
|
|
7
|
+
import { FORMVALIDATION } from "../../types/enums";
|
|
8
8
|
import Box from "../Box";
|
|
9
9
|
import Cover from "../Cover";
|
|
10
10
|
import Sheet, { isSheetHandler } from "../Sheet";
|
|
@@ -24,6 +24,7 @@ const Form = forwardRef((props, ref) => {
|
|
|
24
24
|
const innerRef = useRef(null);
|
|
25
25
|
const sheet = useRef(null);
|
|
26
26
|
const submit = useRef(null);
|
|
27
|
+
const toast = useToast();
|
|
27
28
|
/**
|
|
28
29
|
* Utility function to select multiple DOM elements within the form based on a CSS query.
|
|
29
30
|
* @param query - CSS selector to match elements inside the form.
|
|
@@ -91,8 +92,13 @@ const Form = forwardRef((props, ref) => {
|
|
|
91
92
|
case FORMVALIDATION.Email:
|
|
92
93
|
return isEmail(el.value);
|
|
93
94
|
case FORMVALIDATION.Uri:
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
try {
|
|
96
|
+
new URL(el.value);
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
96
102
|
case FORMVALIDATION.Password:
|
|
97
103
|
console.log(`Add FORMVALIDATION.Password`);
|
|
98
104
|
return false;
|
|
@@ -188,7 +194,8 @@ const Form = forwardRef((props, ref) => {
|
|
|
188
194
|
const _onSubmit = useCallback(() => {
|
|
189
195
|
const { error, errorMsg, payload } = _buildFormData();
|
|
190
196
|
if (error) {
|
|
191
|
-
|
|
197
|
+
toast.error(errorMsg);
|
|
198
|
+
// sheet.current!.error(errorMsg)
|
|
192
199
|
}
|
|
193
200
|
else if (action) {
|
|
194
201
|
// If `action` is defined, submit the form data to the specified endpoint
|
|
@@ -199,7 +206,8 @@ const Form = forwardRef((props, ref) => {
|
|
|
199
206
|
}
|
|
200
207
|
else
|
|
201
208
|
setLoading(true);
|
|
202
|
-
sheet.current
|
|
209
|
+
// sheet.current!.hide()
|
|
210
|
+
toast.clearAll();
|
|
203
211
|
// submit.current?.setState(ButtonState.Loading)
|
|
204
212
|
withPost(action, { ...payload, ...(withData || {}) })
|
|
205
213
|
.then(_resp => {
|
|
@@ -219,8 +227,10 @@ const Form = forwardRef((props, ref) => {
|
|
|
219
227
|
if (onSuccess)
|
|
220
228
|
onSuccess(resp);
|
|
221
229
|
else {
|
|
222
|
-
|
|
223
|
-
sheet.current
|
|
230
|
+
toast.clearAll();
|
|
231
|
+
// sheet.current!.hide()
|
|
232
|
+
// sheet.current!.success(resp.message || `Redirecting..`)
|
|
233
|
+
toast.success(resp.message || `Redirecting...`);
|
|
224
234
|
}
|
|
225
235
|
})
|
|
226
236
|
.catch(err => {
|
|
@@ -234,7 +244,8 @@ const Form = forwardRef((props, ref) => {
|
|
|
234
244
|
if (onError)
|
|
235
245
|
onError(err);
|
|
236
246
|
else
|
|
237
|
-
|
|
247
|
+
toast.error(err.message || `We cannot process your request at this time.`);
|
|
248
|
+
// sheet.current!.show(err.message || `We cannot process your request at this time.`, 4, SHEET.Error)
|
|
238
249
|
});
|
|
239
250
|
});
|
|
240
251
|
}
|
|
@@ -261,14 +272,27 @@ const Form = forwardRef((props, ref) => {
|
|
|
261
272
|
setLoading(mod) {
|
|
262
273
|
if (mod) {
|
|
263
274
|
sheet.current.hide();
|
|
275
|
+
try {
|
|
276
|
+
toast.clearAll();
|
|
277
|
+
}
|
|
278
|
+
catch (e) { }
|
|
264
279
|
}
|
|
265
280
|
setLoading(mod);
|
|
266
281
|
},
|
|
267
282
|
showError(errorMsg) {
|
|
268
|
-
|
|
283
|
+
if (typeof errorMsg == `string`) {
|
|
284
|
+
toast.error(errorMsg);
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
sheet.current.error(errorMsg, 4);
|
|
288
|
+
}
|
|
269
289
|
},
|
|
270
290
|
hideError() {
|
|
271
291
|
sheet.current.hide();
|
|
292
|
+
try {
|
|
293
|
+
toast.clearAll();
|
|
294
|
+
}
|
|
295
|
+
catch (e) { }
|
|
272
296
|
},
|
|
273
297
|
init() {
|
|
274
298
|
_init();
|
|
@@ -3,5 +3,6 @@ import { ProgressHandler } from "./types";
|
|
|
3
3
|
declare const ProgressBar: import("react").ForwardRefExoticComponent<BoxProps & {
|
|
4
4
|
progress?: number;
|
|
5
5
|
type?: import("../..").PROGRESS;
|
|
6
|
+
animated?: boolean;
|
|
6
7
|
} & import("react").RefAttributes<ProgressHandler>>;
|
|
7
8
|
export default ProgressBar;
|
|
@@ -4,20 +4,24 @@ import { forwardRef, useEffect, useImperativeHandle, useRef } from "react";
|
|
|
4
4
|
import { useBase } from "../../hooks";
|
|
5
5
|
import Box from "../Box";
|
|
6
6
|
const ProgressBar = forwardRef((props, ref) => {
|
|
7
|
-
const { progress, type, ...pops } = props;
|
|
7
|
+
const { progress, type, animated, ...pops } = props;
|
|
8
8
|
const bar = useRef(null);
|
|
9
9
|
useImperativeHandle(ref, () => ({
|
|
10
|
-
|
|
10
|
+
setProgress: (p) => {
|
|
11
11
|
bar.current.style.width = `${p * 100}%`;
|
|
12
12
|
}
|
|
13
13
|
}), []);
|
|
14
14
|
useEffect(() => {
|
|
15
15
|
if (progress && bar.current) {
|
|
16
|
-
|
|
16
|
+
if (animated) {
|
|
17
|
+
setTimeout(() => bar.current.style.width = `${progress * 100}%`, 500);
|
|
18
|
+
}
|
|
19
|
+
else
|
|
20
|
+
bar.current.style.width = `${progress * 100}%`;
|
|
17
21
|
}
|
|
18
22
|
}, [progress, bar.current]);
|
|
19
23
|
const { className, style, rest } = useBase(pops);
|
|
20
|
-
return _jsx(Box, { className: `--progress flex rel ${className}`.trim(), style: style, ...rest, children: _jsx(Box, { ref: bar, className: `--bar rel` }) });
|
|
24
|
+
return _jsx(Box, { className: `--progress ${animated ? `--animated` : ``} flex rel ${className}`.trim(), style: style, ...rest, children: _jsx(Box, { ref: bar, className: `--bar rel` }) });
|
|
21
25
|
});
|
|
22
26
|
ProgressBar.displayName = `Zuz.ProgressBar`;
|
|
23
27
|
export default ProgressBar;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { JSX, Ref } from "react";
|
|
2
|
-
import type { TableProps } from "./types";
|
|
2
|
+
import type { TableController, TableProps } from "./types";
|
|
3
3
|
declare const ForwardedTable: <T>(props: TableProps<T> & {
|
|
4
|
-
ref?: Ref<
|
|
4
|
+
ref?: Ref<TableController>;
|
|
5
5
|
}) => JSX.Element;
|
|
6
6
|
export default ForwardedTable;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { forwardRef, useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { PubSub, SPINNER, Spinner, Text, TRANSITION_CURVES, TRANSITIONS, uuid } from "../..";
|
|
5
5
|
import { useBase } from "../../hooks";
|
|
6
6
|
import Box from "../Box";
|
|
@@ -63,7 +63,7 @@ import TRow from "./row";
|
|
|
63
63
|
* ```
|
|
64
64
|
*/
|
|
65
65
|
const Table = (props, ref) => {
|
|
66
|
-
const { schema, rows, rowCount, rowsPerPage, currentPage, pagination, paginationHash, showPaginationOnZeroPageCount, animateRows, header, rowClassName, selectableRows, hoverable, sortBy, loading, loadingRowCount, loadingMessage, spinner, onSort, onRowSelectToggle, onPageChange, onRowContextMenu, ...pops } = props;
|
|
66
|
+
const { schema, rows, rowCount, rowsPerPage, currentPage, pagination, paginationHash, showPaginationOnZeroPageCount, animateRows, header, rowClassName, selectableRows, hoverable, sortBy, loading: _loading, loadingRowCount, loadingMessage, spinner, emptyMessage, onSort, onRowSelectToggle, onPageChange, onRowContextMenu, ...pops } = props;
|
|
67
67
|
const _pagination = useRef(null);
|
|
68
68
|
const _schemaParsed = useMemo(() => schema.reduce((prev, c) => {
|
|
69
69
|
prev[c.id] = {
|
|
@@ -85,22 +85,43 @@ const Table = (props, ref) => {
|
|
|
85
85
|
const pubsub = useMemo(() => new PubSub(), []);
|
|
86
86
|
const rowKeys = useRef(rows.map(() => uuid()));
|
|
87
87
|
const [_sortBy, setSortBy] = useState(sortBy || null);
|
|
88
|
-
// const
|
|
89
|
-
//
|
|
88
|
+
// const [ _loading, _setLoading ] = useState(loading || false)
|
|
89
|
+
// const _loading = useRef<boolean>(loading || false)
|
|
90
|
+
const [_loadingMessage, _setLoadingMessage] = useState(loadingMessage || `loading`);
|
|
91
|
+
const isEmpty = useMemo(() => !_loading && rows && rows.length == 0, [_loading, rows]);
|
|
92
|
+
const renderEmpty = useCallback(() => {
|
|
93
|
+
if (emptyMessage) {
|
|
94
|
+
if (typeof emptyMessage == `function`) {
|
|
95
|
+
const Empty = emptyMessage;
|
|
96
|
+
return _jsx(Empty, {});
|
|
97
|
+
}
|
|
98
|
+
return emptyMessage;
|
|
99
|
+
}
|
|
100
|
+
return _jsx(Text, { as: `tac s:18 mt:75`, children: "No Record Found" });
|
|
101
|
+
}, [_loading, rows]);
|
|
90
102
|
useEffect(() => {
|
|
91
103
|
rowKeys.current = rows.map(() => uuid()); // Update only when rows change
|
|
92
104
|
}, [rows]);
|
|
105
|
+
// useEffect(() => {
|
|
106
|
+
// if ( loading != undefined && loading != _loading ) _setLoading(loading)
|
|
107
|
+
// }, [loading])
|
|
93
108
|
const handleSort = (col, dir) => {
|
|
94
109
|
setSortBy(col);
|
|
95
110
|
onSort?.(col, dir);
|
|
96
111
|
};
|
|
97
112
|
const possiblePage = (rowCount || (rows ? rows.length : 0)) / (rowsPerPage || 10);
|
|
98
113
|
const _paginated = useMemo(() => (showPaginationOnZeroPageCount || (possiblePage > 1)) ? _jsx(Pagination, { hash: paginationHash, ref: _pagination, renderOnZeroPageCount: showPaginationOnZeroPageCount, onPageChange: onPageChange, paginationStyle: PaginationStyle.Table, startPage: currentPage, itemCount: rowCount || (rows ? rows.length : 0), itemsPerPage: rowsPerPage || 10 }) : null, [currentPage, rowCount]);
|
|
99
|
-
|
|
114
|
+
useImperativeHandle(ref, () => ({
|
|
115
|
+
setLoading(mod) {
|
|
116
|
+
// _setLoading(mod)
|
|
117
|
+
// _loading.current = mod
|
|
118
|
+
}
|
|
119
|
+
}));
|
|
120
|
+
return _jsxs(Box, { as: `--table ${(hoverable ?? true) ? `--hoverable` : ``} flex cols rel ${className}`, ref: _tableRef, children: [_header == true && _jsx(TRow, { sortBy: _sortBy, onSort: handleSort, tableRef: _tableRef, pubsub: pubsub, selectable: selectableRows, index: -1, schema: schema, loading: true, styles: _schemaParsed }), _loading && _jsxs(Box, { as: `abs center-x flex aic --table-spinner`, children: [_jsx(Spinner, { type: spinner || SPINNER.Simple }), _loadingMessage && _jsx(Text, { as: `--table-loading-message`, children: _loadingMessage })] }), _loading && Array(loadingRowCount || 5).fill({}).map((row, index) => _jsx(TRow, { tableRef: _tableRef, index: index, pubsub: pubsub, schema: schema, styles: _schemaParsed, loading: true, animate: animateRows }, `--trow-loading-${index}-${schema[0].id}`)), !_loading && rows && rows.map((row, index) => _jsx(TRow, { tableRef: _tableRef, pubsub: pubsub, loading: false, index: index, schema: schema, ids: _cols, styles: _schemaParsed, animate: animateRows, data: row, rowClassName: rowClassName, selectable: selectableRows, onSelect: onRowSelectToggle, onContextMenu: onRowContextMenu }, `--trow-${rowKeys.current[index] || index}-${schema[0].id}`)), isEmpty && renderEmpty(), _jsx(Box, { "aria-hidden": !pagination || !_paginated, ...(animateRows ? { fx: {
|
|
100
121
|
transition: TRANSITIONS.SlideInBottom,
|
|
101
122
|
curve: TRANSITION_CURVES.EaseInOut,
|
|
102
123
|
delay: .02 * (rows.length + 1),
|
|
103
|
-
when: !
|
|
124
|
+
when: !_loading && rows && pagination && _paginated != null
|
|
104
125
|
} } : {}), as: `--row flex aic --row-footer`, children: pagination && _paginated ? _paginated : null })] });
|
|
105
126
|
};
|
|
106
127
|
Table.displayName = `Zuz.Table`;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { ReactNode, RefObject } from "react";
|
|
1
|
+
import { FC, ReactNode, RefObject } from "react";
|
|
2
2
|
import { PubSub, SPINNER } from "../..";
|
|
3
3
|
import { dynamicObject } from "../../types";
|
|
4
4
|
import { BoxProps } from "../Box";
|
|
5
5
|
import { PaginationCallback } from "../Pagination/types";
|
|
6
|
+
export interface TableController {
|
|
7
|
+
setLoading: (mod: boolean) => void;
|
|
8
|
+
}
|
|
6
9
|
/**
|
|
7
10
|
* Callback function for row selection.
|
|
8
11
|
*
|
|
@@ -140,6 +143,7 @@ export type TableProps<T> = BoxProps & {
|
|
|
140
143
|
loadingRowCount?: number;
|
|
141
144
|
loadingMessage?: string;
|
|
142
145
|
spinner?: SPINNER;
|
|
146
|
+
emptyMessage?: ReactNode | FC;
|
|
143
147
|
onRowSelectToggle?: RowSelectCallback<T>;
|
|
144
148
|
onRowContextMenu?: (e: React.MouseEvent<HTMLDivElement, MouseEvent>, row: T) => void;
|
|
145
149
|
onPageChange?: PaginationCallback;
|
|
@@ -34,7 +34,7 @@ const TextWheel = forwardRef((props, ref) => {
|
|
|
34
34
|
// console.log(value)
|
|
35
35
|
_setValue(value || 0);
|
|
36
36
|
}, [value]);
|
|
37
|
-
return _jsxs(Box, { className: `--text-wheel flex aic
|
|
37
|
+
return _jsxs(Box, { className: `--text-wheel flex aic rel`, "aria-hidden": true, as: as, ref: divRef, ...rest, children: [(_value || 0).toString().split('').map((char, index) => {
|
|
38
38
|
if (isNaN(parseInt(char, 10))) {
|
|
39
39
|
return _jsx(Span, { className: "--wheel-char wheel-char-symbol grid", children: char }, `wheel-char-${index}`);
|
|
40
40
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
1
2
|
import { dynamic } from "../..";
|
|
2
3
|
import { TRANSITION_CURVES } from "../../types/enums";
|
|
3
4
|
export declare enum ToastType {
|
|
@@ -12,8 +13,8 @@ export interface ToastData {
|
|
|
12
13
|
id: number;
|
|
13
14
|
type: ToastType;
|
|
14
15
|
icon?: string;
|
|
15
|
-
title?: string;
|
|
16
|
-
message?: string;
|
|
16
|
+
title?: string | ReactNode;
|
|
17
|
+
message?: string | ReactNode;
|
|
17
18
|
duration?: number;
|
|
18
19
|
onClick?: () => void;
|
|
19
20
|
}
|
package/dist/cjs/funs/css.js
CHANGED
|
@@ -453,7 +453,11 @@ export const cssFilterKeys = [
|
|
|
453
453
|
];
|
|
454
454
|
export const cssWithKeys = {
|
|
455
455
|
w: `width`,
|
|
456
|
+
minW: `minWidth`,
|
|
457
|
+
maxW: `maxWidth`,
|
|
456
458
|
h: `height`,
|
|
459
|
+
minH: `minHeight`,
|
|
460
|
+
maxH: `maxHeight`,
|
|
457
461
|
x: `translateX`,
|
|
458
462
|
y: `translateY`,
|
|
459
463
|
z: `translateZ`,
|
|
@@ -22,6 +22,7 @@ export { default as useImage } from './useImage';
|
|
|
22
22
|
export { default as useImageCropper } from './useImageCropper';
|
|
23
23
|
export { default as useIntersectionObserver } from './useIntersectionObserver';
|
|
24
24
|
export { default as useScrollbar } from './useScrollbar';
|
|
25
|
+
export { default as useScrollPhysics } from './useScrollPhysics';
|
|
25
26
|
export { default as useSheet } from './useSheet';
|
|
26
27
|
export { default as useShortcuts } from './useShortcuts';
|
|
27
28
|
export { default as useNetworkStatus } from './useNetworkStatus';
|
package/dist/cjs/hooks/index.js
CHANGED
|
@@ -23,6 +23,7 @@ export { default as useImage } from './useImage';
|
|
|
23
23
|
export { default as useImageCropper } from './useImageCropper';
|
|
24
24
|
export { default as useIntersectionObserver } from './useIntersectionObserver';
|
|
25
25
|
export { default as useScrollbar } from './useScrollbar';
|
|
26
|
+
export { default as useScrollPhysics } from './useScrollPhysics';
|
|
26
27
|
export { default as useSheet } from './useSheet';
|
|
27
28
|
export { default as useShortcuts } from './useShortcuts';
|
|
28
29
|
export { default as useNetworkStatus } from './useNetworkStatus';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ComponentPropsWithRef, CSSProperties, JSX } from "react";
|
|
1
|
+
import { ComponentPropsWithRef, CSSProperties, JSX, RefObject } from "react";
|
|
2
2
|
import { Props } from "../types";
|
|
3
|
-
declare const useBase: <T extends keyof JSX.IntrinsicElements>(props: Props<T>) => {
|
|
3
|
+
declare const useBase: <T extends keyof JSX.IntrinsicElements>(props: Props<T>, ref?: RefObject<HTMLElement>) => {
|
|
4
4
|
style: CSSProperties;
|
|
5
5
|
className: string;
|
|
6
6
|
rest: ComponentPropsWithRef<T>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { animateCSSVar } from "@zuzjs/core";
|
|
2
|
+
import { useEffect, useRef } from "react";
|
|
1
3
|
import { cleanProps, css } from "../funs";
|
|
2
4
|
import { buildWithStyles, getAnimationCurve, getAnimationTransition } from "../funs/css";
|
|
3
|
-
import { cssFilterKeys, cssTransformKeys, cssWithKeys } from "../funs/stylesheet";
|
|
5
|
+
import { cssFilterKeys, cssProps, cssTransformKeys, cssWithKeys } from "../funs/stylesheet";
|
|
4
6
|
let useDrag = null;
|
|
5
7
|
const buildSkeletonStyle = (s) => {
|
|
6
8
|
const makeValue = (v, unit = `px`) => {
|
|
@@ -28,13 +30,15 @@ const buildSkeletonStyle = (s) => {
|
|
|
28
30
|
}
|
|
29
31
|
return style;
|
|
30
32
|
};
|
|
31
|
-
const useBase = (props) => {
|
|
32
|
-
const { as, fx, animate, transition: autoTransition, skeleton, className, shimmer, propsToRemove, draggable, dragOptions, ...rest } = props || {};
|
|
33
|
+
const useBase = (props, ref) => {
|
|
34
|
+
const { as, fx, animate, timeline, transition: autoTransition, skeleton, className, shimmer, propsToRemove, draggable, dragOptions, ...rest } = props || {};
|
|
35
|
+
const currentScroll = useRef({ x: 0, y: 0 });
|
|
36
|
+
const lastTime = useRef(performance.now());
|
|
33
37
|
let cx = [];
|
|
34
38
|
if (as) {
|
|
35
39
|
cx = css().Build(`string` == typeof as ? as : as.join(` `)).cx;
|
|
36
40
|
}
|
|
37
|
-
const { transition, from, to, exit, when, duration, delay, curve } = autoTransition ? {
|
|
41
|
+
const { transition, from, to, exit, when, duration, delay, curve, scroll } = autoTransition ? {
|
|
38
42
|
transition: autoTransition,
|
|
39
43
|
duration: 0.3
|
|
40
44
|
} : fx || animate || {};
|
|
@@ -48,23 +52,6 @@ const useBase = (props) => {
|
|
|
48
52
|
else {
|
|
49
53
|
_style = transition ? getAnimationTransition(transition, false, true) : from || {};
|
|
50
54
|
}
|
|
51
|
-
// Track previous value of 'when'
|
|
52
|
-
// const prevWhenRef = useRef<boolean | undefined>(when);
|
|
53
|
-
// if (undefined === when) {
|
|
54
|
-
// _style = transition ? getAnimationTransition(transition, true) : { ...from, ...to };
|
|
55
|
-
// } else if (true === when) {
|
|
56
|
-
// _style = transition ? getAnimationTransition(transition, false) : { ...(to || {}) };
|
|
57
|
-
// } else {
|
|
58
|
-
// // Check if exit style should be applied
|
|
59
|
-
// const wasTrue = prevWhenRef.current === true;
|
|
60
|
-
// if (wasTrue && exit) {
|
|
61
|
-
// _style = { ...(exit || {}) };
|
|
62
|
-
// } else {
|
|
63
|
-
// _style = transition ? getAnimationTransition(transition, false, true) : from || {};
|
|
64
|
-
// }
|
|
65
|
-
// }
|
|
66
|
-
// // Update previous value for next render
|
|
67
|
-
// prevWhenRef.current = when;
|
|
68
55
|
const _transition = {};
|
|
69
56
|
if (transition || (from && to)) {
|
|
70
57
|
// { transition: `all ${duration || `0.2`}s ${getAnimationCurve(curve)} ${delay || 0}s` }
|
|
@@ -76,7 +63,7 @@ const useBase = (props) => {
|
|
|
76
63
|
if (prop in cssWithKeys) {
|
|
77
64
|
_subTrans = cssTransformKeys.includes(cssWithKeys[prop].toString()) ? `transform`
|
|
78
65
|
: cssFilterKeys.includes(cssWithKeys[prop].toString()) ? `filter`
|
|
79
|
-
: _subTrans;
|
|
66
|
+
: _subTrans in cssProps ? cssProps[_subTrans] : _subTrans; //(cssWithKeys[prop] || _subTrans).toString() // _subTrans
|
|
80
67
|
}
|
|
81
68
|
else if (cssTransformKeys.includes(prop)) {
|
|
82
69
|
_subTrans = `transform`;
|
|
@@ -111,6 +98,36 @@ const useBase = (props) => {
|
|
|
111
98
|
};
|
|
112
99
|
}
|
|
113
100
|
}
|
|
101
|
+
const handleScroll = () => {
|
|
102
|
+
if (fx && fx.scroll && typeof window !== 'undefined') {
|
|
103
|
+
const now = performance.now();
|
|
104
|
+
const dt = (now - lastTime.current) / 1000;
|
|
105
|
+
lastTime.current = now;
|
|
106
|
+
const { lerpFactor, x, y, multiplier, xMultiplier, yMultiplier } = fx.scroll;
|
|
107
|
+
const delta = window.scrollY - currentScroll.current.y;
|
|
108
|
+
const velocity = delta / dt;
|
|
109
|
+
currentScroll.current.y += delta * (lerpFactor || .1);
|
|
110
|
+
if (ref?.current) {
|
|
111
|
+
const translateX = x ? currentScroll.current.x * x * (multiplier || xMultiplier || .25) : 0;
|
|
112
|
+
const translateY = y ? currentScroll.current.y * y * (multiplier || yMultiplier || .25) : 0;
|
|
113
|
+
// ref.current.style.setProperty(`--scroll-y`, `${translateY}px`)
|
|
114
|
+
// transform = `translate3d(${translateX}px, ${translateY}px, 0)`.trim()
|
|
115
|
+
animateCSSVar(ref, "--scroll-y", translateY);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
if (fx && fx.scroll && typeof window !== 'undefined') {
|
|
121
|
+
if (ref) {
|
|
122
|
+
ref.current.style.transform = `translate3d(0px, var(--scroll-y), 0)`;
|
|
123
|
+
ref.current.style.transition = `transform 0.1s ${fx.curve ? getAnimationCurve(fx.curve) : `var(--spring)`}`;
|
|
124
|
+
}
|
|
125
|
+
window.addEventListener('scroll', handleScroll, { passive: true });
|
|
126
|
+
return () => {
|
|
127
|
+
window.removeEventListener('scroll', handleScroll);
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
}, [ref]);
|
|
114
131
|
return {
|
|
115
132
|
style: {
|
|
116
133
|
...buildWithStyles(_style),
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
type ScrollPhysicsOptions = {
|
|
3
|
+
lerpFactor?: number;
|
|
4
|
+
x?: number;
|
|
5
|
+
y?: number;
|
|
6
|
+
xMultiplier?: number;
|
|
7
|
+
yMultiplier?: number;
|
|
8
|
+
scale?: {
|
|
9
|
+
min: number;
|
|
10
|
+
max: number;
|
|
11
|
+
factor: number;
|
|
12
|
+
};
|
|
13
|
+
rotate?: {
|
|
14
|
+
direction?: 1 | -1;
|
|
15
|
+
multiplier?: number;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
declare const useScrollPhysics: (ref: RefObject<HTMLElement>, options: ScrollPhysicsOptions) => {
|
|
19
|
+
position: RefObject<number>;
|
|
20
|
+
velocity: RefObject<number>;
|
|
21
|
+
};
|
|
22
|
+
export default useScrollPhysics;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { clamp } from '@zuzjs/core';
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
const useScrollPhysics = (ref, options) => {
|
|
4
|
+
const { lerpFactor = 0.1, x, y, xMultiplier = 0.25, yMultiplier = 0.25, scale, rotate, } = options;
|
|
5
|
+
const position = useRef(0);
|
|
6
|
+
const velocity = useRef(0);
|
|
7
|
+
const current = useRef(0);
|
|
8
|
+
const target = useRef(0);
|
|
9
|
+
const lastTime = useRef(performance.now());
|
|
10
|
+
const raf = useRef(null);
|
|
11
|
+
const isRunning = useRef(false);
|
|
12
|
+
const smoothedVelocity = useRef(0);
|
|
13
|
+
const threshold = 0.2; // minimum delta to trigger animation
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (typeof window === 'undefined')
|
|
16
|
+
return;
|
|
17
|
+
const tick = () => {
|
|
18
|
+
const now = performance.now();
|
|
19
|
+
const dt = (now - lastTime.current) / 1000;
|
|
20
|
+
lastTime.current = now;
|
|
21
|
+
const delta = target.current - current.current;
|
|
22
|
+
const v = delta / dt;
|
|
23
|
+
// Update position & velocity
|
|
24
|
+
current.current += delta * lerpFactor;
|
|
25
|
+
position.current = current.current;
|
|
26
|
+
velocity.current = v;
|
|
27
|
+
smoothedVelocity.current += (v - smoothedVelocity.current) * lerpFactor;
|
|
28
|
+
// Apply transform
|
|
29
|
+
if (ref.current) {
|
|
30
|
+
const translateX = x ? position.current * x * xMultiplier : 0;
|
|
31
|
+
const translateY = y ? position.current * y * yMultiplier : 0;
|
|
32
|
+
const scaleValue = scale
|
|
33
|
+
? clamp(scale.max - Math.abs(smoothedVelocity.current) * scale.factor, scale.min, scale.max) : 1;
|
|
34
|
+
const rotateValue = rotate
|
|
35
|
+
? velocity.current * (rotate.multiplier ?? 1) * (rotate.direction ?? 1)
|
|
36
|
+
: 0;
|
|
37
|
+
ref.current.style.transform = `
|
|
38
|
+
translate3d(${translateX}px, ${translateY}px, 0)
|
|
39
|
+
scale(${scaleValue})
|
|
40
|
+
rotate(${rotateValue}deg)
|
|
41
|
+
`.trim();
|
|
42
|
+
}
|
|
43
|
+
// If still moving, continue animating
|
|
44
|
+
if (Math.abs(delta) > threshold || Math.abs(v) > threshold) {
|
|
45
|
+
raf.current = requestAnimationFrame(tick);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
isRunning.current = false;
|
|
49
|
+
raf.current = null;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const handleScroll = () => {
|
|
53
|
+
target.current = window.scrollY;
|
|
54
|
+
if (!isRunning.current) {
|
|
55
|
+
lastTime.current = performance.now();
|
|
56
|
+
raf.current = requestAnimationFrame(tick);
|
|
57
|
+
isRunning.current = true;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
window.addEventListener('scroll', handleScroll, { passive: true });
|
|
61
|
+
return () => {
|
|
62
|
+
window.removeEventListener('scroll', handleScroll);
|
|
63
|
+
if (raf.current)
|
|
64
|
+
cancelAnimationFrame(raf.current);
|
|
65
|
+
};
|
|
66
|
+
}, [lerpFactor, x, y, xMultiplier, yMultiplier, scale, rotate]);
|
|
67
|
+
return { position, velocity };
|
|
68
|
+
};
|
|
69
|
+
export default useScrollPhysics;
|
package/dist/cjs/types/enums.js
CHANGED
|
@@ -24,6 +24,7 @@ export var FORMVALIDATION;
|
|
|
24
24
|
FORMVALIDATION["Password"] = "PASSWORD";
|
|
25
25
|
FORMVALIDATION["MatchField"] = "MATCHFIELD";
|
|
26
26
|
FORMVALIDATION["Pattern"] = "*";
|
|
27
|
+
FORMVALIDATION["GreaterThan"] = "GREATER_THAN";
|
|
27
28
|
})(FORMVALIDATION || (FORMVALIDATION = {}));
|
|
28
29
|
export var SHEET;
|
|
29
30
|
(function (SHEET) {
|
|
@@ -48,6 +48,7 @@ export interface ZuzProps {
|
|
|
48
48
|
animate?: animationProps;
|
|
49
49
|
/** Animation configuration using {@link animationProps} */
|
|
50
50
|
fx?: animationProps;
|
|
51
|
+
timeline?: animationProps[];
|
|
51
52
|
transition?: TRANSITIONS;
|
|
52
53
|
/** Skeleton placeholder configuration using {@link Skeleton} */
|
|
53
54
|
skeleton?: Skeleton;
|
|
@@ -67,7 +68,11 @@ export type FormInputs = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElem
|
|
|
67
68
|
export type cssShortKey = keyof cssShortKeys;
|
|
68
69
|
export type cssShortKeys = {
|
|
69
70
|
w: string | number;
|
|
71
|
+
minW: string | number;
|
|
72
|
+
maxW: string | number;
|
|
70
73
|
h: string | number;
|
|
74
|
+
minH: string | number;
|
|
75
|
+
maxH: string | number;
|
|
71
76
|
x: string | number;
|
|
72
77
|
y: string | number;
|
|
73
78
|
z: string | number;
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { dynamicObject } from ".";
|
|
2
2
|
import { SKELETON, TRANSITION_CURVES, TRANSITIONS } from "./enums";
|
|
3
|
+
export interface scrollEffectProps {
|
|
4
|
+
lerpFactor?: number;
|
|
5
|
+
x?: number;
|
|
6
|
+
y?: number;
|
|
7
|
+
multiplier?: number;
|
|
8
|
+
xMultiplier?: number;
|
|
9
|
+
yMultiplier?: number;
|
|
10
|
+
}
|
|
3
11
|
/**
|
|
4
12
|
* `animationProps` defines the properties to control animation effects
|
|
5
13
|
* applied to elements. Supports transitions with timing configurations.
|
|
@@ -26,6 +34,7 @@ export interface animationProps {
|
|
|
26
34
|
delay?: number;
|
|
27
35
|
/** Easing curve applied to the animation, as a string or {@link TRANSITION_CURVES} */
|
|
28
36
|
curve?: string | TRANSITION_CURVES;
|
|
37
|
+
scroll?: scrollEffectProps;
|
|
29
38
|
}
|
|
30
39
|
/**
|
|
31
40
|
* `Skeleton` defines properties for a skeleton loader, used to indicate
|