@udixio/ui-react 1.6.4 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +51 -3
- package/dist/index.cjs +3 -3
- package/dist/index.js +1699 -1466
- package/dist/lib/config/config.interface.d.ts +4 -0
- package/dist/lib/config/config.interface.d.ts.map +1 -0
- package/dist/lib/config/define-config.d.ts +4 -0
- package/dist/lib/config/define-config.d.ts.map +1 -0
- package/dist/lib/config/index.d.ts +3 -0
- package/dist/lib/config/index.d.ts.map +1 -0
- package/dist/lib/effects/AnimateOnScroll.d.ts +7 -0
- package/dist/lib/effects/AnimateOnScroll.d.ts.map +1 -0
- package/dist/lib/effects/ThemeProvider.d.ts +3 -2
- package/dist/lib/effects/ThemeProvider.d.ts.map +1 -1
- package/dist/lib/effects/block-scroll.effect.d.ts +22 -0
- package/dist/lib/effects/block-scroll.effect.d.ts.map +1 -0
- package/dist/lib/effects/custom-scroll/custom-scroll.effect.d.ts.map +1 -1
- package/dist/lib/effects/index.d.ts +1 -0
- package/dist/lib/effects/index.d.ts.map +1 -1
- package/dist/lib/effects/scrollDriven.d.ts +5 -0
- package/dist/lib/effects/scrollDriven.d.ts.map +1 -0
- package/dist/lib/effects/smooth-scroll.effect.d.ts +5 -5
- package/dist/lib/effects/smooth-scroll.effect.d.ts.map +1 -1
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/styles/fab.style.d.ts.map +1 -1
- package/dist/scrollDriven-AP2yWhzi.js +121 -0
- package/dist/scrollDriven-DWAu7CR0.cjs +1 -0
- package/package.json +5 -3
- package/src/lib/config/config.interface.ts +9 -0
- package/src/lib/config/define-config.ts +16 -0
- package/src/lib/config/index.ts +2 -0
- package/src/lib/effects/AnimateOnScroll.ts +267 -0
- package/src/lib/effects/ThemeProvider.tsx +78 -52
- package/src/lib/effects/block-scroll.effect.tsx +174 -0
- package/src/lib/effects/custom-scroll/custom-scroll.effect.tsx +16 -5
- package/src/lib/effects/index.ts +1 -0
- package/src/lib/effects/scrollDriven.ts +239 -0
- package/src/lib/effects/smooth-scroll.effect.tsx +105 -72
- package/src/lib/index.ts +1 -0
- package/src/lib/styles/card.style.ts +1 -1
- package/src/lib/styles/fab.style.ts +9 -17
- package/src/lib/styles/slider.style.ts +2 -2
- package/src/lib/styles/tab.style.ts +1 -1
- package/src/lib/styles/tabs.style.ts +3 -3
|
@@ -1,91 +1,124 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
useTransform,
|
|
7
|
-
} from 'motion/react';
|
|
8
|
-
import { CustomScroll, CustomScrollInterface } from './custom-scroll';
|
|
9
|
-
import { classNames, ReactProps } from '../utils';
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { CustomScrollInterface } from './custom-scroll';
|
|
3
|
+
import { ReactProps } from '../utils';
|
|
4
|
+
import { BlockScroll } from './block-scroll.effect';
|
|
5
|
+
import { animate, AnimationPlaybackControls } from 'motion';
|
|
10
6
|
|
|
11
7
|
export const SmoothScroll = ({
|
|
12
|
-
|
|
13
|
-
transition = '.5s',
|
|
8
|
+
transition,
|
|
14
9
|
orientation = 'vertical',
|
|
15
10
|
throttleDuration = 25,
|
|
16
|
-
...restProps
|
|
17
11
|
}: {
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
transition?: {
|
|
13
|
+
duration?: number;
|
|
14
|
+
};
|
|
20
15
|
} & ReactProps<CustomScrollInterface>) => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
scrollTotal: number;
|
|
24
|
-
scrollVisible: number;
|
|
25
|
-
scroll: number;
|
|
26
|
-
} | null>(null);
|
|
16
|
+
// Target value (instant), driven by wheel/touch/keyboard or native scroll sync
|
|
17
|
+
const [scrollY, setScrollY] = useState(0);
|
|
27
18
|
|
|
28
|
-
const
|
|
19
|
+
const [el, setEl] = useState<HTMLHtmlElement>();
|
|
29
20
|
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
[0, 1 - (scroll?.scrollVisible ?? 0) / (scroll?.scrollTotal ?? 0)]
|
|
34
|
-
);
|
|
21
|
+
const isScrolling = useRef(false);
|
|
22
|
+
const scrollTimeoutRef = useRef<NodeJS.Timeout>();
|
|
23
|
+
const lastAppliedYRef = useRef(0);
|
|
35
24
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
setEl(document as unknown as HTMLHtmlElement);
|
|
27
|
+
const y = document.documentElement.scrollTop;
|
|
28
|
+
setScrollY(y);
|
|
29
|
+
lastAppliedYRef.current = y;
|
|
30
|
+
}, []);
|
|
31
|
+
|
|
32
|
+
// Sync native scroll (e.g., scrollbar, programmatic) back to target after a small delay
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
const onScroll = () => {
|
|
35
|
+
if (isScrolling.current) return;
|
|
36
|
+
setScrollY(document.documentElement.scrollTop);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
el?.addEventListener('scroll', onScroll as unknown as EventListener);
|
|
40
|
+
return () => {
|
|
41
|
+
if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current);
|
|
42
|
+
el?.removeEventListener('scroll', onScroll as unknown as EventListener);
|
|
43
|
+
};
|
|
44
|
+
}, [el]);
|
|
40
45
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
// Drive the spring when target changes
|
|
47
|
+
const currentY = useRef<number | null>();
|
|
48
|
+
const animationRef = useRef<AnimationPlaybackControls | null>(null);
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
const y = scrollY;
|
|
51
|
+
|
|
52
|
+
if (animationRef.current) {
|
|
53
|
+
animationRef.current.stop();
|
|
54
|
+
animationRef.current = null;
|
|
50
55
|
}
|
|
51
|
-
};
|
|
52
|
-
const lastChangeTimeRef = useRef<number | null>(null);
|
|
53
|
-
useMotionValueEvent(percentTransform, 'change', (value) => {
|
|
54
|
-
// Récupérer l'heure actuelle
|
|
55
|
-
const now = performance.now();
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
console.log(`Delta temps : ${deltaTime} ms`);
|
|
57
|
+
if (!isScrolling.current) {
|
|
58
|
+
currentY.current = y;
|
|
59
|
+
return;
|
|
61
60
|
}
|
|
61
|
+
animationRef.current = animate(currentY.current ?? y, y, {
|
|
62
|
+
duration: transition?.duration ?? 0.5,
|
|
63
|
+
ease: 'circOut',
|
|
64
|
+
|
|
65
|
+
onUpdate: (value) => {
|
|
66
|
+
if (scrollTimeoutRef.current) {
|
|
67
|
+
clearTimeout(scrollTimeoutRef.current);
|
|
68
|
+
}
|
|
69
|
+
currentY.current = value;
|
|
62
70
|
|
|
63
|
-
|
|
64
|
-
|
|
71
|
+
const html = document.documentElement;
|
|
72
|
+
// Avoid micro-movements causing extra layout work
|
|
73
|
+
const rounded = Math.round(value * 1000) / 1000;
|
|
74
|
+
const last = lastAppliedYRef.current;
|
|
75
|
+
if (Math.abs(rounded - last) < 0.1) return;
|
|
76
|
+
lastAppliedYRef.current = rounded;
|
|
65
77
|
|
|
66
|
-
|
|
67
|
-
|
|
78
|
+
if (isScrolling.current) {
|
|
79
|
+
html.scrollTo({ top: rounded });
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
onComplete: () => {
|
|
83
|
+
scrollTimeoutRef.current = setTimeout(() => {
|
|
84
|
+
isScrolling.current = false;
|
|
85
|
+
}, 300);
|
|
86
|
+
animationRef.current = null;
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
return () => {
|
|
90
|
+
// Safety: stop if effect re-runs quickly
|
|
91
|
+
if (animationRef.current) {
|
|
92
|
+
animationRef.current.stop();
|
|
93
|
+
animationRef.current = null;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}, [scrollY]);
|
|
97
|
+
|
|
98
|
+
if (!el) return null;
|
|
68
99
|
|
|
69
100
|
return (
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
{
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
101
|
+
<BlockScroll
|
|
102
|
+
touch={false}
|
|
103
|
+
el={el as unknown as HTMLElement}
|
|
104
|
+
onScroll={(scroll) => {
|
|
105
|
+
if (
|
|
106
|
+
'deltaY' in scroll &&
|
|
107
|
+
scroll.deltaY !== 0 &&
|
|
108
|
+
el &&
|
|
109
|
+
scrollY !== null
|
|
110
|
+
) {
|
|
111
|
+
let y = scrollY + scroll.deltaY;
|
|
112
|
+
const html = el.querySelector('html');
|
|
113
|
+
if (html) {
|
|
114
|
+
y = Math.min(y, html.scrollHeight - html.clientHeight);
|
|
115
|
+
}
|
|
116
|
+
y = Math.max(y, 0);
|
|
117
|
+
setScrollY(y);
|
|
118
|
+
|
|
119
|
+
isScrolling.current = true;
|
|
120
|
+
}
|
|
121
|
+
}}
|
|
122
|
+
></BlockScroll>
|
|
90
123
|
);
|
|
91
124
|
};
|
package/src/lib/index.ts
CHANGED
|
@@ -5,7 +5,7 @@ export const cardStyle = defaultClassNames<CardInterface>(
|
|
|
5
5
|
'card',
|
|
6
6
|
({ variant, isInteractive }) => ({
|
|
7
7
|
card: classNames(
|
|
8
|
-
'
|
|
8
|
+
'group/card rounded-xl overflow-hidden z-10',
|
|
9
9
|
variant === 'outlined' && 'bg-surface border border-outline-variant',
|
|
10
10
|
variant === 'elevated' && 'bg-surface-container-low shadow-1',
|
|
11
11
|
variant === 'filled' && 'bg-surface-container-highest',
|
|
@@ -20,6 +20,10 @@ export const fabStyle = defaultClassNames<FabInterface>(
|
|
|
20
20
|
variant === 'primary' && 'bg-primary-container',
|
|
21
21
|
variant === 'secondary' && 'bg-secondary-container',
|
|
22
22
|
variant === 'tertiary' && 'bg-tertiary-container',
|
|
23
|
+
variant === 'surface' && 'text-primary',
|
|
24
|
+
variant === 'primary' && 'text-on-primary-container',
|
|
25
|
+
variant === 'secondary' && 'text-on-secondary-container',
|
|
26
|
+
variant === 'tertiary' && 'text-on-tertiary-container',
|
|
23
27
|
),
|
|
24
28
|
stateLayer: classNames(
|
|
25
29
|
'absolute w-full h-full overflow-hidden left-1/2 top-1/2 transform -translate-y-1/2 -translate-x-1/2',
|
|
@@ -33,23 +37,11 @@ export const fabStyle = defaultClassNames<FabInterface>(
|
|
|
33
37
|
'group-hover:hover-state-on-tertiary-container group-focus-visible:focus-state-on-tertiary-container',
|
|
34
38
|
),
|
|
35
39
|
|
|
36
|
-
icon: classNames(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
},
|
|
41
|
-
variant === 'surface' && 'text-primary',
|
|
42
|
-
variant === 'primary' && 'text-on-primary-container',
|
|
43
|
-
variant === 'secondary' && 'text-on-secondary-container',
|
|
44
|
-
variant === 'tertiary' && 'text-on-tertiary-container',
|
|
45
|
-
),
|
|
40
|
+
icon: classNames({
|
|
41
|
+
'size-6': size == 'small' || size == 'medium' || isExtended,
|
|
42
|
+
'size-9': size == 'large' && !isExtended,
|
|
43
|
+
}),
|
|
46
44
|
|
|
47
|
-
label: classNames(
|
|
48
|
-
'text-title-medium text-nowrap',
|
|
49
|
-
variant === 'surface' && 'text-primary',
|
|
50
|
-
variant === 'primary' && 'text-on-primary-container',
|
|
51
|
-
variant === 'secondary' && 'text-on-secondary-container',
|
|
52
|
-
variant === 'tertiary' && 'text-on-tertiary-container',
|
|
53
|
-
),
|
|
45
|
+
label: classNames('text-title-medium text-nowrap'),
|
|
54
46
|
}),
|
|
55
47
|
);
|
|
@@ -5,7 +5,7 @@ export const sliderStyle = defaultClassNames<SliderInterface>(
|
|
|
5
5
|
'slider',
|
|
6
6
|
({ isChanging }) => ({
|
|
7
7
|
slider: classNames([
|
|
8
|
-
'relative w-full h-11 flex items-center rounded gap-x-1.5 cursor-pointer',
|
|
8
|
+
'relative w-full h-11 flex items-center rounded gap-x-1.5 cursor-pointer min-w-32',
|
|
9
9
|
]),
|
|
10
10
|
activeTrack: classNames([
|
|
11
11
|
'h-4 relative transition-all duration-100 bg-primary overflow-hidden rounded-l-full ',
|
|
@@ -23,5 +23,5 @@ export const sliderStyle = defaultClassNames<SliderInterface>(
|
|
|
23
23
|
dot: classNames([
|
|
24
24
|
'h-1 w-1 absolute transform -translate-y-1/2 -translate-x-1/2 top-1/2 rounded-full',
|
|
25
25
|
]),
|
|
26
|
-
})
|
|
26
|
+
}),
|
|
27
27
|
);
|
|
@@ -6,7 +6,7 @@ export const tabStyle = defaultClassNames<TabInterface>(
|
|
|
6
6
|
'tab',
|
|
7
7
|
({ isSelected, icon, label, variant }) => ({
|
|
8
8
|
tab: classNames(
|
|
9
|
-
'
|
|
9
|
+
'flex-1 group outline-none flex px-4 justify-center items-center cursor-pointer',
|
|
10
10
|
{ 'z-10': isSelected },
|
|
11
11
|
Boolean(icon && label) && variant === 'primary' && 'h-16',
|
|
12
12
|
!(Boolean(icon && label) && variant === 'primary') && 'h-12',
|
|
@@ -5,9 +5,9 @@ export const tabsStyle = defaultClassNames<TabsInterface>(
|
|
|
5
5
|
'tabs',
|
|
6
6
|
({ scrollable }) => ({
|
|
7
7
|
tabs: classNames(
|
|
8
|
-
'border-b border-surface-container-highest',
|
|
8
|
+
'border-b border-surface-container-highest bg-surface',
|
|
9
9
|
'flex relative ',
|
|
10
|
-
{ 'overflow-x-auto': scrollable }
|
|
10
|
+
{ 'overflow-x-auto': scrollable },
|
|
11
11
|
),
|
|
12
|
-
})
|
|
12
|
+
}),
|
|
13
13
|
);
|