@zuzjs/ui 0.9.4 → 0.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/cjs/comps/Chart/index.d.ts +8 -0
  2. package/dist/cjs/comps/Chart/index.js +66 -0
  3. package/dist/cjs/comps/Chart/types.d.ts +10 -0
  4. package/dist/cjs/comps/Chart/types.js +4 -0
  5. package/dist/cjs/comps/Form/index.js +8 -4
  6. package/dist/cjs/comps/Group/index.d.ts +6 -0
  7. package/dist/cjs/comps/Group/index.js +21 -0
  8. package/dist/cjs/comps/Image/index.js +5 -3
  9. package/dist/cjs/comps/Password/index.d.ts +1 -1
  10. package/dist/cjs/comps/Select/index.d.ts +1 -0
  11. package/dist/cjs/comps/Select/index.js +10 -5
  12. package/dist/cjs/comps/Select/types.d.ts +4 -0
  13. package/dist/cjs/comps/Text/index.js +0 -2
  14. package/dist/cjs/comps/TextWheel/index.d.ts +2 -0
  15. package/dist/cjs/comps/TextWheel/index.js +24 -12
  16. package/dist/cjs/comps/TextWheel/types.d.ts +2 -0
  17. package/dist/cjs/comps/index.d.ts +3 -0
  18. package/dist/cjs/comps/index.js +4 -0
  19. package/dist/cjs/funs/index.d.ts +1 -1
  20. package/dist/cjs/funs/index.js +4 -3
  21. package/dist/cjs/hooks/index.d.ts +2 -0
  22. package/dist/cjs/hooks/index.js +2 -0
  23. package/dist/cjs/hooks/useBase.js +52 -11
  24. package/dist/cjs/hooks/useLineChart.d.ts +25 -0
  25. package/dist/cjs/hooks/useLineChart.js +86 -0
  26. package/dist/cjs/hooks/usePosition.d.ts +12 -0
  27. package/dist/cjs/hooks/usePosition.js +191 -0
  28. package/dist/cjs/hooks/useResizeObserver.d.ts +1 -1
  29. package/dist/cjs/hooks/useResizeObserver.js +5 -4
  30. package/dist/cjs/hooks/useScrollbar.js +115 -70
  31. package/dist/cjs/types/enums.d.ts +2 -0
  32. package/dist/cjs/types/enums.js +2 -0
  33. package/dist/cjs/types/index.d.ts +2 -1
  34. package/dist/cjs/types/interfaces.d.ts +3 -2
  35. package/dist/esm/comps/Chart/index.d.ts +8 -0
  36. package/dist/esm/comps/Chart/index.js +66 -0
  37. package/dist/esm/comps/Chart/types.d.ts +10 -0
  38. package/dist/esm/comps/Chart/types.js +4 -0
  39. package/dist/esm/comps/Form/index.js +8 -4
  40. package/dist/esm/comps/Group/index.d.ts +6 -0
  41. package/dist/esm/comps/Group/index.js +21 -0
  42. package/dist/esm/comps/Image/index.js +5 -3
  43. package/dist/esm/comps/Password/index.d.ts +1 -1
  44. package/dist/esm/comps/Select/index.d.ts +1 -0
  45. package/dist/esm/comps/Select/index.js +10 -5
  46. package/dist/esm/comps/Select/types.d.ts +4 -0
  47. package/dist/esm/comps/Text/index.js +0 -2
  48. package/dist/esm/comps/TextWheel/index.d.ts +2 -0
  49. package/dist/esm/comps/TextWheel/index.js +24 -12
  50. package/dist/esm/comps/TextWheel/types.d.ts +2 -0
  51. package/dist/esm/comps/index.d.ts +3 -0
  52. package/dist/esm/comps/index.js +4 -0
  53. package/dist/esm/funs/index.d.ts +1 -1
  54. package/dist/esm/funs/index.js +4 -3
  55. package/dist/esm/hooks/index.d.ts +2 -0
  56. package/dist/esm/hooks/index.js +2 -0
  57. package/dist/esm/hooks/useBase.js +52 -11
  58. package/dist/esm/hooks/useLineChart.d.ts +25 -0
  59. package/dist/esm/hooks/useLineChart.js +86 -0
  60. package/dist/esm/hooks/usePosition.d.ts +12 -0
  61. package/dist/esm/hooks/usePosition.js +191 -0
  62. package/dist/esm/hooks/useResizeObserver.d.ts +1 -1
  63. package/dist/esm/hooks/useResizeObserver.js +5 -4
  64. package/dist/esm/hooks/useScrollbar.js +115 -70
  65. package/dist/esm/types/enums.d.ts +2 -0
  66. package/dist/esm/types/enums.js +2 -0
  67. package/dist/esm/types/index.d.ts +2 -1
  68. package/dist/esm/types/interfaces.d.ts +3 -2
  69. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  70. package/dist/tsconfig.tsbuildinfo +1 -1
  71. package/package.json +2 -2
@@ -0,0 +1,66 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { forwardRef, useEffect, useId, useRef, useState } from "react";
4
+ import { useResizeObserver } from "../..";
5
+ import useBase from "../../hooks/useBase";
6
+ import useLineChart from "../../hooks/useLineChart";
7
+ import Box from "../Box";
8
+ import { CHART } from "./types";
9
+ const Chart = forwardRef((props, ref) => {
10
+ const { data, width, height, lineColor, strokeWidth = 2, gradientStartColor, gradientEndColor, animated, animDuration = 2, animDelay = 0, padding = 0, type, ...pops } = props;
11
+ const { className, style, rest } = useBase(pops);
12
+ const innerRef = useRef(null);
13
+ // State to store the actual dimensions of the container
14
+ const observedDimensions = useResizeObserver(innerRef.current?.parentElement || innerRef);
15
+ const chartWidth = typeof width === 'number' ? width : observedDimensions.width;
16
+ const chartHeight = typeof height === 'number' ? height : observedDimensions.height;
17
+ const dimensionsForChartHook = {
18
+ width: chartWidth,
19
+ height: chartHeight
20
+ };
21
+ // Generate a unique ID for the gradient to avoid conflicts if multiple charts are on the page
22
+ const gradientId = useId(); //`chartGradient-${Math.random().toString(36).substring(2, 9)}`;
23
+ // Use the custom hook to get the SVG path data and area path data
24
+ const { pathD, areaPathD } = useLineChart(data, dimensionsForChartHook, (padding + (strokeWidth || 2)));
25
+ // Refs for the path elements to get their total length for animation
26
+ const linePathRef = useRef(null);
27
+ const areaPathRef = useRef(null);
28
+ // State to store the calculated lengths of the paths
29
+ const [linePathLength, setLinePathLength] = useState(0);
30
+ const [areaPathLength, setAreaPathLength] = useState(0);
31
+ useEffect(() => {
32
+ if (animated) {
33
+ if (linePathRef.current) {
34
+ // Get the total length of the line path for stroke-dasharray animation
35
+ setLinePathLength(linePathRef.current.getTotalLength());
36
+ }
37
+ if (areaPathRef.current) {
38
+ // Get the total length of the area path for stroke-dasharray animation
39
+ setAreaPathLength(areaPathRef.current.getTotalLength());
40
+ }
41
+ }
42
+ }, [animated, pathD, areaPathD, chartWidth, chartHeight]);
43
+ return _jsx(Box, { ref: innerRef, as: `--chart --${type || CHART.Line}-chart ${className}`.trim(), style: {
44
+ ...style,
45
+ width,
46
+ height
47
+ }, ...rest, children: chartWidth > 0 && chartHeight > 0 && _jsxs("svg", { viewBox: `0 0 ${chartWidth} ${chartHeight}`, preserveAspectRatio: "xMidYMid meet" // Ensures the SVG scales nicely
48
+ , children: [_jsx("defs", { children: _jsxs("linearGradient", { id: gradientId, x1: "0%", y1: "0%", x2: "0%", y2: "100%", children: [_jsx("stop", { offset: "0%", stopColor: gradientStartColor }), _jsx("stop", { offset: "100%", stopColor: gradientEndColor })] }) }), _jsx("path", { ref: areaPathRef, d: areaPathD, fill: `url(#${gradientId})`, stroke: "none" // No stroke for the area
49
+ ,
50
+ // Apply animation properties if 'animated' is true
51
+ style: animated ? {
52
+ strokeDasharray: areaPathLength,
53
+ strokeDashoffset: areaPathLength,
54
+ } : {}, children: animated && (_jsx("animate", { attributeName: "stroke-dashoffset", from: areaPathLength, to: "0", dur: `${animDuration || 2}s`, begin: `${animDelay || 0}s`, fill: "freeze" })) }), _jsx("path", { ref: linePathRef, d: pathD, fill: "none" // No fill for the line
55
+ , stroke: lineColor, strokeWidth: strokeWidth, strokeLinecap: "round" // Rounded line caps
56
+ , strokeLinejoin: "round" // Rounded line joins
57
+ ,
58
+ // Apply animation properties if 'animated' is true
59
+ style: animated ? {
60
+ strokeDasharray: linePathLength,
61
+ strokeDashoffset: linePathLength,
62
+ } : {}, children: animated && (_jsx("animate", { attributeName: "stroke-dashoffset", from: linePathLength, to: "0", dur: `${animDuration || 2}s`, begin: `${animDelay || 0}s`, fill: "freeze" // Keep the final state
63
+ })) })] }) });
64
+ });
65
+ Chart.displayName = `Zuz.Chart`;
66
+ export default Chart;
@@ -0,0 +1,10 @@
1
+ import { LineChartProps } from "../../hooks/useLineChart";
2
+ import { BoxProps } from "../Box";
3
+ export declare enum CHART {
4
+ Line = "line"
5
+ }
6
+ export type ChartProps = BoxProps & LineChartProps & {
7
+ type?: CHART;
8
+ animDuration?: number;
9
+ animDelay?: number;
10
+ };
@@ -0,0 +1,4 @@
1
+ export var CHART;
2
+ (function (CHART) {
3
+ CHART["Line"] = "line";
4
+ })(CHART || (CHART = {}));
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { withPost } from "@zuzjs/core";
3
+ import { _, withPost } from "@zuzjs/core";
4
4
  import { forwardRef, startTransition, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
5
- import { addPropsToChildren, isEmail, isEmpty } from "../../funs";
5
+ import { addPropsToChildren, isEmpty } from "../../funs";
6
6
  import { useBase, useToast } from "../../hooks";
7
7
  import { FORMVALIDATION } from "../../types/enums";
8
8
  import Box from "../Box";
@@ -89,8 +89,12 @@ const Form = forwardRef((props, ref) => {
89
89
  }
90
90
  }
91
91
  switch (_with.toUpperCase()) {
92
+ case FORMVALIDATION.IPV4:
93
+ return _(el.value).isIPv4();
94
+ case FORMVALIDATION.IPV6:
95
+ return _(el.value).isIPv6();
92
96
  case FORMVALIDATION.Email:
93
- return isEmail(el.value);
97
+ return _(el.value).isEmail();
94
98
  case FORMVALIDATION.Uri:
95
99
  try {
96
100
  new URL(el.value);
@@ -267,7 +271,7 @@ const Form = forwardRef((props, ref) => {
267
271
  });
268
272
  }
269
273
  }, [innerRef.current]);
270
- const buildChildren = useMemo(() => addPropsToChildren(children, child => child.props.type == `submit`, { ref: submit }), [children]);
274
+ const buildChildren = useMemo(() => addPropsToChildren(children, child => child.props.type == `submit`, index => ({ ref: submit })), [children]);
271
275
  useImperativeHandle(ref, () => ({
272
276
  setLoading(mod) {
273
277
  if (mod) {
@@ -0,0 +1,6 @@
1
+ import { BoxProps } from "../Box";
2
+ declare const Group: import("react").ForwardRefExoticComponent<BoxProps & {
3
+ fxDelay?: number;
4
+ fxStep?: number;
5
+ } & import("react").RefAttributes<HTMLDivElement>>;
6
+ export default Group;
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { forwardRef, useMemo } from "react";
3
+ import { useDelayed } from "../..";
4
+ import { addPropsToChildren } from "../../funs";
5
+ import Box from "../Box";
6
+ const Group = forwardRef((props, ref) => {
7
+ const { children, fx, fxDelay, fxStep, ...rest } = props;
8
+ const when = useDelayed();
9
+ const Children = useMemo(() => {
10
+ if (!fx)
11
+ return children;
12
+ return addPropsToChildren(children, child => !(`fx` in (child.props ?? {})), index => ({ fx: {
13
+ ...fx,
14
+ delay: (fxDelay || 0) + index * (fxStep || .1), // how to increment per index ?
15
+ when
16
+ } }));
17
+ }, [children, when, fx]);
18
+ return _jsx(Box, { className: `--group`, ref: ref, ...rest, children: Children });
19
+ });
20
+ Group.displayName = `Zuz.Group`;
21
+ export default Group;
@@ -1,11 +1,13 @@
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 Image = forwardRef((props, ref) => {
5
- const { style, className, rest } = useBase(props);
5
+ const innerRef = useRef(null);
6
+ const targetRef = useMemo(() => ref && typeof ref !== "function" && ref.current ? ref : innerRef, [ref]);
7
+ const { style, className, rest } = useBase(props, targetRef);
6
8
  if (!rest.src || rest.src == ``)
7
9
  return null;
8
- return _jsx("img", { ref: ref, style: style, className: `${className} flex`, ...rest });
10
+ return _jsx("img", { ref: targetRef, style: style, className: `${className} flex`, ...rest });
9
11
  });
10
12
  Image.displayName = `Zuz.Image`;
11
13
  export default Image;
@@ -2,7 +2,7 @@ import { InputProps } from '../Input';
2
2
  export type PasswordProps = Omit<InputProps, `type` | `numeric`> & {
3
3
  strenthMeter?: boolean;
4
4
  };
5
- declare const Password: import("react").ForwardRefExoticComponent<Omit<InputProps, "type" | "numeric"> & {
5
+ declare const Password: import("react").ForwardRefExoticComponent<Omit<InputProps, "numeric" | "type"> & {
6
6
  strenthMeter?: boolean;
7
7
  } & import("react").RefAttributes<HTMLInputElement>>;
8
8
  export default Password;
@@ -8,5 +8,6 @@ declare const Select: import("react").ForwardRefExoticComponent<Omit<import(".."
8
8
  search?: boolean;
9
9
  onChange?: (v: Option) => void;
10
10
  searchPlaceholder?: string;
11
+ maxHeight?: number;
11
12
  } & import("react").RefAttributes<HTMLDivElement>>;
12
13
  export default Select;
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { forwardRef, useEffect, useId, useMemo, useRef, useState } from "react";
4
- import { useBase } from "../../hooks";
4
+ import { useBase, usePosition } from "../../hooks";
5
+ import { Position } from "../../types/enums";
5
6
  import Box from "../Box";
6
7
  import Button from "../Button";
7
8
  import Input from "../Input";
@@ -9,7 +10,7 @@ import SVGIcons from "../svgicons";
9
10
  import Text from "../Text";
10
11
  import OptionItem from "./optionItem";
11
12
  const Select = forwardRef((props, ref) => {
12
- const { selected, options, label, name, variant, search: withSearch, searchPlaceholder, onChange, ...pops } = props;
13
+ const { selected, options, label, name, variant, search: withSearch, searchPlaceholder, maxHeight, onChange, ...pops } = props;
13
14
  const [value, setValue] = useState(selected ?
14
15
  typeof selected === `string` ? options.find(fo => fo.value === selected) : selected
15
16
  : options[0]);
@@ -17,8 +18,10 @@ const Select = forwardRef((props, ref) => {
17
18
  const [query, setQuery] = useState(null);
18
19
  const _ref = useRef(null);
19
20
  const _search = useRef(null);
21
+ const _pop = useRef(null);
20
22
  const _did = useId();
21
23
  const _id = useMemo(() => name || _did, []);
24
+ const { reposition } = usePosition(_pop, { direction: Position.Bottom, offset: 2 });
22
25
  const { className, style, rest } = useBase(pops);
23
26
  const updateValue = (o) => {
24
27
  setValue(o);
@@ -28,6 +31,7 @@ const Select = forwardRef((props, ref) => {
28
31
  document.body.addEventListener(`click`, (e) => {
29
32
  setChoosing(false);
30
33
  });
34
+ window.dispatchEvent(new Event('resize'));
31
35
  }, []);
32
36
  useEffect(() => {
33
37
  if (choosing) {
@@ -39,10 +43,11 @@ const Select = forwardRef((props, ref) => {
39
43
  }
40
44
  setQuery(null);
41
45
  }
46
+ reposition();
42
47
  }, [choosing]);
43
- return _jsxs(Box, { className: `--select ${variant ? `--${variant}` : ``} ${name ? `--${name}` : ``} rel`.trim(), name: _id, children: [_jsxs(Button, { "data-value": value ? `string` == typeof value ? value : value.value : value || `-1`, className: `--selected flex aic rel ${className}`.trim(), withLabel: false, style: style, onClick: (e) => setChoosing(prev => !prev), ...rest, children: [_jsx(Text, { className: `--label`, children: value ? `string` == typeof value ? value : value.label : label || `Choose` }), _jsx(Box, { className: `--svg-arrow rel flex aic jcc`, children: choosing ? SVGIcons.arrowUp : SVGIcons.arrowDown })] }), _jsxs(Box, { id: _id, className: `--options-list flex cols abs`, style: {
44
- pointerEvents: choosing ? `auto` : `none`,
45
- }, animate: {
48
+ return _jsxs(Box, { className: `--select ${variant ? `--${variant}` : ``} ${name ? `--${name}` : ``} rel`.trim(), name: _id, children: [_jsxs(Button, { "data-value": value ? `string` == typeof value ? value : value.value : value || `-1`, className: `--selected flex aic rel ${className}`.trim(), withLabel: false, style: style, onClick: (e) => setChoosing(prev => !prev), ...rest, children: [_jsx(Text, { className: `--label`, children: value ? `string` == typeof value ? value : value.label : label || `Choose` }), _jsx(Box, { className: `--svg-arrow rel flex aic jcc`, children: choosing ? SVGIcons.arrowUp : SVGIcons.arrowDown })] }), _jsxs(Box, { id: _id, className: `--options-list flex cols abs`, "aria-hidden": !choosing, style: {
49
+ maxHeight: maxHeight || `auto`
50
+ }, ref: _pop, fx: {
46
51
  from: { y: 5, opacity: 0 },
47
52
  to: { y: 0, opacity: 1 },
48
53
  when: choosing,
@@ -55,4 +55,8 @@ export type SelectProps = Omit<BoxProps, "onChange"> & {
55
55
  * Placeholder text for the search input field.
56
56
  */
57
57
  searchPlaceholder?: string;
58
+ /**
59
+ * Max Height
60
+ */
61
+ maxHeight?: number;
58
62
  };
@@ -5,8 +5,6 @@ import Span from '../Span';
5
5
  const Text = forwardRef((props, ref) => {
6
6
  const { h, html, children, lines, ...pops } = props;
7
7
  const { style, className, rest } = useBase(pops);
8
- // const textRef = useTruncateText(lines || 2)
9
- // const mergedRef = useMergedRefs(ref, textRef)
10
8
  const Tag = `h${props.h || 1}`;
11
9
  return _jsx(Tag, { ref: ref, style: style, className: className, ...rest, children: html ? _jsx(Span, { dangerouslySetInnerHTML: { __html: html } }) : children });
12
10
  });
@@ -4,5 +4,7 @@ declare const TextWheel: React.ForwardRefExoticComponent<Omit<import("..").BoxPr
4
4
  value?: number | string;
5
5
  color?: string;
6
6
  direction?: `up` | `down`;
7
+ charDelay?: number | ((index: number) => number);
8
+ charDuration?: number | ((index: number) => number);
7
9
  } & React.RefAttributes<TextWheelHandler>>;
8
10
  export default TextWheel;
@@ -1,54 +1,66 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
4
- import Box from '../Box';
5
- import Span from '../Span';
4
+ import Box from '../Box'; // Assuming these are your custom components
5
+ import Span from '../Span'; // Assuming these are your custom components
6
6
  const TextWheel = forwardRef((props, ref) => {
7
7
  const { as, value, color, direction, ...rest } = props;
8
8
  const divRef = useRef(null);
9
+ // Internal state to manage the displayed value
9
10
  const [_value, _setValue] = useState(value || 0);
11
+ // Expose methods to parent components via ref
10
12
  useImperativeHandle(ref, () => ({
13
+ // Updates the value without immediately triggering a full re-render of characters
14
+ // Useful for when the number of digits changes.
11
15
  updateValue(v) {
12
- if (_value.toString().length != v.toString().length) {
16
+ if (_value.toString().length !== v.toString().length) {
13
17
  _setValue(v);
14
18
  }
15
19
  },
20
+ // Sets the value and triggers the animation for each character
16
21
  setValue(v) {
17
- this.updateValue(v);
22
+ this.updateValue(v); // First, update the internal value to handle length changes
18
23
  if (divRef.current) {
19
24
  const chars = v.toString().split('');
20
25
  divRef.current.querySelectorAll('.--wheel-char').forEach((charElement, index) => {
21
26
  const char = chars[index];
22
27
  if (charElement instanceof HTMLElement) {
28
+ // Set the data-value attribute, which CSS can then use
23
29
  charElement.setAttribute('data-value', char);
24
30
  const track = charElement.querySelector('.--wheel-char-track');
25
31
  if (track instanceof HTMLElement) {
32
+ // Directly update the CSS custom property for immediate animation
26
33
  track.style.setProperty('--v', char);
34
+ // Force a reflow to ensure the transition plays even if the value is the same
35
+ // This is a common trick for re-triggering CSS animations/transitions
36
+ void track.offsetWidth;
27
37
  }
28
38
  }
29
39
  });
30
40
  }
31
41
  }
32
42
  }));
43
+ // Effect to update internal value when the prop `value` changes
33
44
  useEffect(() => {
34
- // console.log(value)
35
45
  _setValue(value || 0);
36
46
  }, [value]);
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) => {
47
+ 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) => {
48
+ // Render non-numeric characters directly (e.g., decimal points)
38
49
  if (isNaN(parseInt(char, 10))) {
39
- return _jsx(Span, { className: "--wheel-char wheel-char-symbol grid", children: char }, `wheel-char-${index}`);
50
+ return _jsx(Span, { className: "--wheel-char wheel-char-symbol grid", children: char }, `wheel-char-symbol-${index}`);
40
51
  }
41
- return _jsx(Span, { "data-value": char, className: `--wheel-char grid ${index > char.toString().split('').length - 3 ? '--wheel-fraction' : ''}`.trim(), children: _jsxs(Span, { className: `--wheel-char-track --wheel-track-${direction || `down`} grid`, style: {
42
- '--v': char
43
- }, children: [_jsx(Span, { children: !direction || direction == `down` ? 0 : 9 }), (!direction || direction == `down` ?
52
+ // Render numeric characters with the wheel effect
53
+ return (_jsx(Span, { "data-value": char, className: `--wheel-char grid ${index > (_value || 0).toString().length - 3 ? '--wheel-fraction' : ''}`.trim(), children: _jsxs(Span, { className: `--wheel-char-track --wheel-track-${direction || `down`} grid`, style: {
54
+ '--v': char // Set the custom property for the current character value
55
+ }, children: [_jsx(Span, { children: !direction || direction === `down` ? 0 : 9 }), (!direction || direction === `down` ?
44
56
  [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
45
57
  : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]).map((val, indx) => {
46
58
  return _jsx(Span, { children: val }, `${index}--${indx}`);
47
- }), _jsx(Span, { children: !direction || direction == `down` ? 9 : 0 })] }) }, `wheel-char-${index}`);
59
+ }), _jsx(Span, { children: !direction || direction === `down` ? 9 : 0 })] }) }, `wheel-char-${index}`));
48
60
  }), color && _jsx(Box, { className: `abs fillx`, style: {
49
61
  zIndex: 1,
50
62
  background: `linear-gradient(0deg, ${color}, transparent, transparent, transparent, ${color})`,
51
- } })] });
63
+ } })] }));
52
64
  });
53
65
  TextWheel.displayName = `Zuz.TextWheel`;
54
66
  export default TextWheel;
@@ -3,6 +3,8 @@ export type TextWheelProps = Omit<BoxProps, "name"> & {
3
3
  value?: number | string;
4
4
  color?: string;
5
5
  direction?: `up` | `down`;
6
+ charDelay?: number | ((index: number) => number);
7
+ charDuration?: number | ((index: number) => number);
6
8
  };
7
9
  export interface TextWheelHandler {
8
10
  setValue: (v: number | string) => void;
@@ -12,6 +12,8 @@ export * from './Avatar/types';
12
12
  export { default as Box, type BoxProps } from './Box';
13
13
  export { default as Button } from './Button';
14
14
  export * from './Button/types';
15
+ export { default as Chart } from './Chart';
16
+ export * from './Chart/types';
15
17
  export { default as CheckBox } from './CheckBox';
16
18
  export * from './CheckBox/types';
17
19
  export { default as ColorScheme } from './ColorScheme';
@@ -36,6 +38,7 @@ export * from './Fab/types';
36
38
  export { default as Filters, type FilterProps } from './Filters';
37
39
  export { default as Form } from './Form';
38
40
  export * from './Form/types';
41
+ export { default as Group } from './Group';
39
42
  export { default as Icon, type IconProps } from './Icon';
40
43
  export { default as Image, type ImageProps } from './Image';
41
44
  export { default as Input, type InputProps } from './Input';
@@ -12,6 +12,8 @@ export * from './Avatar/types';
12
12
  export { default as Box } from './Box';
13
13
  export { default as Button } from './Button';
14
14
  export * from './Button/types';
15
+ export { default as Chart } from './Chart';
16
+ export * from './Chart/types';
15
17
  export { default as CheckBox } from './CheckBox';
16
18
  export * from './CheckBox/types';
17
19
  export { default as ColorScheme } from './ColorScheme';
@@ -36,6 +38,8 @@ export * from './Fab/types';
36
38
  export { default as Filters } from './Filters';
37
39
  export { default as Form } from './Form';
38
40
  export * from './Form/types';
41
+ export { default as Group } from './Group';
42
+ // export * from './Form/types';
39
43
  export { default as Icon } from './Icon';
40
44
  export { default as Image } from './Image';
41
45
  export { default as Input } from './Input';
@@ -63,7 +63,7 @@ export declare const bindKey: (key: KeyCode, fun: () => void, element?: HTMLElem
63
63
  export declare const camelCase: (str: string, ucf?: boolean) => string;
64
64
  export declare const camelCaseToDash: (str: string) => string;
65
65
  export declare const pluralize: (word: string, count: number) => string;
66
- export declare const addPropsToChildren: (children: ReactNode, conditions: (child: ReactElement<any>) => boolean, newProps: object) => ReactNode;
66
+ export declare const addPropsToChildren: (children: ReactNode, conditions: (child: ReactElement<any>) => boolean, getProps: (index: number, element: ReactElement<any>) => object) => ReactNode;
67
67
  export declare const getPositionAroundElement: (x: number, y: number, distance: number, childCount: number) => {
68
68
  x: number;
69
69
  y: number;
@@ -395,16 +395,17 @@ export const camelCase = (str, ucf = false) => {
395
395
  };
396
396
  export const camelCaseToDash = (str) => str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
397
397
  export const pluralize = (word, count) => `${word}${count !== 1 ? 's' : ''}`;
398
- export const addPropsToChildren = (children, conditions, newProps) => {
398
+ export const addPropsToChildren = (children, conditions, getProps) => {
399
+ let i = 0;
399
400
  return Children.map(children, (child) => {
400
401
  if (isValidElement(child)) {
401
402
  const element = child;
402
403
  const newChild = conditions(element)
403
- ? cloneElement(element, { ...newProps })
404
+ ? cloneElement(element, getProps(i++, element))
404
405
  : element;
405
406
  if (element.props.children) {
406
407
  return cloneElement(newChild, {
407
- children: addPropsToChildren(element.props.children, conditions, newProps)
408
+ children: addPropsToChildren(element.props.children, conditions, getProps)
408
409
  });
409
410
  }
410
411
  return newChild;
@@ -11,6 +11,7 @@ export { default as useDebounce } from './useDebounce';
11
11
  export { default as useDelayed, default as useMounted } from './useDelayed';
12
12
  export { default as useDevice } from './useDevice';
13
13
  export { default as useDimensions } from './useDimensions';
14
+ export { default as useLineChart, type DataPoint, type LineChartProps, type UseLineChartDimensions, type UseLineChartReturn } from './useLineChart';
14
15
  export { default as useMediaPlayer, type MediaPlayerProps, type MediaType } from './useMediaPlayer';
15
16
  export { default as useMergedRefs } from './useMergedRefs';
16
17
  export { default as useMutationObserver, type MutationCallback } from './useMutationObserver';
@@ -26,6 +27,7 @@ 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';
30
+ export { default as usePosition } from './usePosition';
29
31
  export { default as useResizeObserver } from './useResizeObserver';
30
32
  export { default as useSlider } from './useSlider';
31
33
  export { default as useToast } from './useToast';
@@ -11,6 +11,7 @@ export { default as useDebounce } from './useDebounce';
11
11
  export { default as useDelayed, default as useMounted } from './useDelayed';
12
12
  export { default as useDevice } from './useDevice';
13
13
  export { default as useDimensions } from './useDimensions';
14
+ export { default as useLineChart } from './useLineChart';
14
15
  export { default as useMediaPlayer } from './useMediaPlayer';
15
16
  export { default as useMergedRefs } from './useMergedRefs';
16
17
  export { default as useMutationObserver } from './useMutationObserver';
@@ -27,6 +28,7 @@ export { default as useScrollPhysics } from './useScrollPhysics';
27
28
  export { default as useSheet } from './useSheet';
28
29
  export { default as useShortcuts } from './useShortcuts';
29
30
  export { default as useNetworkStatus } from './useNetworkStatus';
31
+ export { default as usePosition } from './usePosition';
30
32
  export { default as useResizeObserver } from './useResizeObserver';
31
33
  export { default as useSlider } from './useSlider';
32
34
  export { default as useToast } from './useToast';
@@ -57,6 +57,7 @@ const useBase = (props, ref) => {
57
57
  // { transition: `all ${duration || `0.2`}s ${getAnimationCurve(curve)} ${delay || 0}s` }
58
58
  const _curve = getAnimationCurve(curve);
59
59
  const _transitionList = [];
60
+ const _willChangeList = [];
60
61
  Object.keys(_style).forEach(ck => {
61
62
  let prop = ck;
62
63
  let _subTrans = ck;
@@ -68,11 +69,15 @@ const useBase = (props, ref) => {
68
69
  else if (cssTransformKeys.includes(prop)) {
69
70
  _subTrans = `transform`;
70
71
  }
72
+ // will-change: ${_subTrans};
71
73
  const _newTransition = `${_subTrans} ${duration || `0.2`}s ${_curve} ${delay || 0}s`;
74
+ if (!_willChangeList.includes(_subTrans))
75
+ _willChangeList.push(_subTrans);
72
76
  if (!_transitionList.includes(_newTransition))
73
77
  _transitionList.push(_newTransition);
74
78
  });
75
79
  _transition.transition = _transitionList.join(`, `);
80
+ _transition.willChange = _willChangeList.join(`, `);
76
81
  }
77
82
  // // console.log(_style, _transition)
78
83
  const is = typeof window !== "undefined";
@@ -98,7 +103,7 @@ const useBase = (props, ref) => {
98
103
  };
99
104
  }
100
105
  }
101
- const handleScroll = () => {
106
+ const handleScrollParallax = () => {
102
107
  if (fx && fx.scroll && typeof window !== 'undefined') {
103
108
  const now = performance.now();
104
109
  const dt = (now - lastTime.current) / 1000;
@@ -110,22 +115,58 @@ const useBase = (props, ref) => {
110
115
  if (ref?.current) {
111
116
  const translateX = x ? currentScroll.current.x * x * (multiplier || xMultiplier || .25) : 0;
112
117
  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
118
  animateCSSVar(ref, "--scroll-y", translateY);
119
+ animateCSSVar(ref, "--scroll-x", translateX);
116
120
  }
117
121
  }
118
122
  };
123
+ const handleMouseParallax = (e) => {
124
+ if (!fx || !fx.mouse || typeof window === 'undefined')
125
+ return;
126
+ const now = performance.now();
127
+ const dt = (now - lastTime.current) / 1000;
128
+ lastTime.current = now;
129
+ const { lerpFactor, x, y, multiplier, xMultiplier, yMultiplier } = fx.mouse;
130
+ // Normalize mouse position to center (0) range (-1 to 1)
131
+ const vw = window.innerWidth;
132
+ const vh = window.innerHeight;
133
+ const nx = (e.clientX - vw / 2) / (vw / 2); // -1 to 1
134
+ const ny = (e.clientY - vh / 2) / (vh / 2); // -1 to 1
135
+ const dx = nx - currentScroll.current.x;
136
+ const dy = ny - currentScroll.current.y;
137
+ currentScroll.current.x += dx * (lerpFactor || 0.1);
138
+ currentScroll.current.y += dy * (lerpFactor || 0.1);
139
+ if (ref?.current) {
140
+ const translateX = x ? currentScroll.current.x * (multiplier || xMultiplier || 20) : 0;
141
+ const translateY = y ? currentScroll.current.y * (multiplier || yMultiplier || 20) : 0;
142
+ animateCSSVar(ref, '--mouse-x', translateX);
143
+ animateCSSVar(ref, '--mouse-y', translateY);
144
+ }
145
+ };
119
146
  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)`}`;
147
+ if (typeof window !== 'undefined') {
148
+ if (fx && fx.scroll) {
149
+ if (ref) {
150
+ ref.current.style.willChange = `transform`;
151
+ ref.current.style.transform = `translate3d(0px, var(--scroll-y), 0)`;
152
+ ref.current.style.transition = `transform 0.1s ${fx.curve ? getAnimationCurve(fx.curve) : `var(--spring)`}`;
153
+ }
154
+ window.addEventListener('scroll', handleScrollParallax, { passive: true });
155
+ return () => {
156
+ window.removeEventListener('scroll', handleScrollParallax);
157
+ };
158
+ }
159
+ if (fx && fx.mouse) {
160
+ if (ref) {
161
+ ref.current.style.willChange = `transform`;
162
+ ref.current.style.transform = `translate3d(0px, var(--mouse-y), 0)`;
163
+ ref.current.style.transition = `transform 0.1s ${fx.curve ? getAnimationCurve(fx.curve) : `var(--spring)`}`;
164
+ }
165
+ window.document.addEventListener('mousemove', handleMouseParallax, { passive: true });
166
+ return () => {
167
+ window.removeEventListener('mousemove', handleMouseParallax);
168
+ };
124
169
  }
125
- window.addEventListener('scroll', handleScroll, { passive: true });
126
- return () => {
127
- window.removeEventListener('scroll', handleScroll);
128
- };
129
170
  }
130
171
  }, [ref]);
131
172
  return {
@@ -0,0 +1,25 @@
1
+ export interface DataPoint {
2
+ x: number;
3
+ y: number;
4
+ }
5
+ export interface UseLineChartDimensions {
6
+ width: number;
7
+ height: number;
8
+ }
9
+ export interface UseLineChartReturn {
10
+ pathD: string;
11
+ areaPathD: string;
12
+ }
13
+ export interface LineChartProps {
14
+ data: DataPoint[];
15
+ width?: string | number;
16
+ height?: string | number;
17
+ lineColor?: string;
18
+ strokeWidth?: number;
19
+ gradientStartColor?: string;
20
+ gradientEndColor?: string;
21
+ padding?: number;
22
+ animated?: boolean;
23
+ }
24
+ declare const useLineChart: (data: DataPoint[], dimensions?: UseLineChartDimensions, padding?: number) => UseLineChartReturn;
25
+ export default useLineChart;