app-studio 0.5.21 → 0.5.26
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/app-studio.cjs.development.js +307 -0
- package/dist/app-studio.cjs.development.js.map +1 -1
- package/dist/app-studio.cjs.production.min.js +1 -1
- package/dist/app-studio.esm.js +297 -2
- package/dist/app-studio.esm.js.map +1 -1
- package/dist/app-studio.umd.development.js +307 -0
- package/dist/app-studio.umd.development.js.map +1 -1
- package/dist/app-studio.umd.production.min.js +1 -1
- package/dist/hooks/useActive.d.ts +2 -0
- package/dist/hooks/useClickOutside.d.ts +2 -0
- package/dist/hooks/useFocus.d.ts +2 -0
- package/dist/hooks/useHover.d.ts +2 -0
- package/dist/hooks/useKeyPress.d.ts +1 -0
- package/dist/hooks/useOnScreen.d.ts +2 -0
- package/dist/hooks/useScroll.d.ts +1 -1
- package/dist/hooks/useWindowSize.d.ts +4 -0
- package/dist/index.d.ts +8 -1
- package/package.json +1 -1
package/dist/app-studio.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { createContext, useContext, forwardRef, useMemo, useEffect,
|
|
1
|
+
import React, { createContext, useContext, forwardRef, useMemo, useState, useRef, useEffect, useCallback } from 'react';
|
|
2
2
|
import Color from 'color-convert';
|
|
3
3
|
|
|
4
4
|
const palette = {
|
|
@@ -2492,12 +2492,130 @@ function isMobile() {
|
|
|
2492
2492
|
return navigator.userAgent.match(/(iPhone|iPod|Android|ios|iPad)/i);
|
|
2493
2493
|
}
|
|
2494
2494
|
|
|
2495
|
+
function useActive() {
|
|
2496
|
+
const [active, setActive] = useState(false);
|
|
2497
|
+
const ref = useRef(null);
|
|
2498
|
+
useEffect(() => {
|
|
2499
|
+
const node = ref.current;
|
|
2500
|
+
if (!node) return;
|
|
2501
|
+
const handleMouseDown = () => setActive(true);
|
|
2502
|
+
const handleMouseUp = () => setActive(false);
|
|
2503
|
+
const handleTouchStart = () => setActive(true);
|
|
2504
|
+
const handleTouchEnd = () => setActive(false);
|
|
2505
|
+
node.addEventListener('mousedown', handleMouseDown);
|
|
2506
|
+
node.addEventListener('mouseup', handleMouseUp);
|
|
2507
|
+
node.addEventListener('mouseleave', handleMouseUp);
|
|
2508
|
+
node.addEventListener('touchstart', handleTouchStart);
|
|
2509
|
+
node.addEventListener('touchend', handleTouchEnd);
|
|
2510
|
+
return () => {
|
|
2511
|
+
node.removeEventListener('mousedown', handleMouseDown);
|
|
2512
|
+
node.removeEventListener('mouseup', handleMouseUp);
|
|
2513
|
+
node.removeEventListener('mouseleave', handleMouseUp);
|
|
2514
|
+
node.removeEventListener('touchstart', handleTouchStart);
|
|
2515
|
+
node.removeEventListener('touchend', handleTouchEnd);
|
|
2516
|
+
};
|
|
2517
|
+
}, []);
|
|
2518
|
+
return [ref, active];
|
|
2519
|
+
}
|
|
2520
|
+
|
|
2521
|
+
function useClickOutside() {
|
|
2522
|
+
const [clickedOutside, setClickedOutside] = useState(false);
|
|
2523
|
+
const ref = useRef(null);
|
|
2524
|
+
useEffect(() => {
|
|
2525
|
+
const handleClick = e => {
|
|
2526
|
+
if (ref.current && !ref.current.contains(e.target)) {
|
|
2527
|
+
setClickedOutside(true);
|
|
2528
|
+
} else {
|
|
2529
|
+
setClickedOutside(false);
|
|
2530
|
+
}
|
|
2531
|
+
};
|
|
2532
|
+
document.addEventListener('mousedown', handleClick);
|
|
2533
|
+
return () => {
|
|
2534
|
+
document.removeEventListener('mousedown', handleClick);
|
|
2535
|
+
};
|
|
2536
|
+
}, []);
|
|
2537
|
+
return [ref, clickedOutside];
|
|
2538
|
+
}
|
|
2539
|
+
|
|
2540
|
+
function useFocus() {
|
|
2541
|
+
const [focused, setFocused] = useState(false);
|
|
2542
|
+
const ref = useRef(null);
|
|
2543
|
+
useEffect(() => {
|
|
2544
|
+
const node = ref.current;
|
|
2545
|
+
if (!node) return;
|
|
2546
|
+
const handleFocus = () => setFocused(true);
|
|
2547
|
+
const handleBlur = () => setFocused(false);
|
|
2548
|
+
node.addEventListener('focus', handleFocus);
|
|
2549
|
+
node.addEventListener('blur', handleBlur);
|
|
2550
|
+
return () => {
|
|
2551
|
+
node.removeEventListener('focus', handleFocus);
|
|
2552
|
+
node.removeEventListener('blur', handleBlur);
|
|
2553
|
+
};
|
|
2554
|
+
}, []);
|
|
2555
|
+
return [ref, focused];
|
|
2556
|
+
}
|
|
2557
|
+
|
|
2558
|
+
function useHover() {
|
|
2559
|
+
const [hover, setHover] = useState(false);
|
|
2560
|
+
const ref = useRef(null);
|
|
2561
|
+
useEffect(() => {
|
|
2562
|
+
const node = ref.current;
|
|
2563
|
+
if (!node) return;
|
|
2564
|
+
const handleMouseEnter = () => setHover(true);
|
|
2565
|
+
const handleMouseLeave = () => setHover(false);
|
|
2566
|
+
node.addEventListener('mouseenter', handleMouseEnter);
|
|
2567
|
+
node.addEventListener('mouseleave', handleMouseLeave);
|
|
2568
|
+
return () => {
|
|
2569
|
+
node.removeEventListener('mouseenter', handleMouseEnter);
|
|
2570
|
+
node.removeEventListener('mouseleave', handleMouseLeave);
|
|
2571
|
+
};
|
|
2572
|
+
}, []);
|
|
2573
|
+
return [ref, hover];
|
|
2574
|
+
}
|
|
2575
|
+
|
|
2576
|
+
function useKeyPress(targetKey) {
|
|
2577
|
+
const [keyPressed, setKeyPressed] = useState(false);
|
|
2578
|
+
useEffect(() => {
|
|
2579
|
+
const downHandler = e => {
|
|
2580
|
+
if (e.key === targetKey) setKeyPressed(true);
|
|
2581
|
+
};
|
|
2582
|
+
const upHandler = e => {
|
|
2583
|
+
if (e.key === targetKey) setKeyPressed(false);
|
|
2584
|
+
};
|
|
2585
|
+
window.addEventListener('keydown', downHandler);
|
|
2586
|
+
window.addEventListener('keyup', upHandler);
|
|
2587
|
+
return () => {
|
|
2588
|
+
window.removeEventListener('keydown', downHandler);
|
|
2589
|
+
window.removeEventListener('keyup', upHandler);
|
|
2590
|
+
};
|
|
2591
|
+
}, [targetKey]);
|
|
2592
|
+
return keyPressed;
|
|
2593
|
+
}
|
|
2594
|
+
|
|
2495
2595
|
const useMount = callback => {
|
|
2496
2596
|
useEffect(() => {
|
|
2497
2597
|
callback();
|
|
2498
2598
|
}, []);
|
|
2499
2599
|
};
|
|
2500
2600
|
|
|
2601
|
+
function useOnScreen(options) {
|
|
2602
|
+
const ref = useRef(null);
|
|
2603
|
+
const [isOnScreen, setOnScreen] = useState(false);
|
|
2604
|
+
useEffect(() => {
|
|
2605
|
+
const node = ref.current;
|
|
2606
|
+
if (!node) return;
|
|
2607
|
+
const observer = new IntersectionObserver(_ref => {
|
|
2608
|
+
let [entry] = _ref;
|
|
2609
|
+
setOnScreen(entry.isIntersecting);
|
|
2610
|
+
}, options);
|
|
2611
|
+
observer.observe(node);
|
|
2612
|
+
return () => {
|
|
2613
|
+
observer.unobserve(node);
|
|
2614
|
+
};
|
|
2615
|
+
}, [options]);
|
|
2616
|
+
return [ref, isOnScreen];
|
|
2617
|
+
}
|
|
2618
|
+
|
|
2501
2619
|
const createQuery = (keyScreen, query, set) => {
|
|
2502
2620
|
const mql = window.matchMedia(query);
|
|
2503
2621
|
const onChange = () => {
|
|
@@ -2544,5 +2662,182 @@ const useResponsive = () => {
|
|
|
2544
2662
|
};
|
|
2545
2663
|
};
|
|
2546
2664
|
|
|
2547
|
-
|
|
2665
|
+
const getScrollDimensions = element => {
|
|
2666
|
+
if (element instanceof Window) {
|
|
2667
|
+
return {
|
|
2668
|
+
scrollHeight: document.documentElement.scrollHeight,
|
|
2669
|
+
scrollWidth: document.documentElement.scrollWidth,
|
|
2670
|
+
clientHeight: window.innerHeight,
|
|
2671
|
+
clientWidth: window.innerWidth,
|
|
2672
|
+
scrollTop: window.scrollY,
|
|
2673
|
+
scrollLeft: window.scrollX
|
|
2674
|
+
};
|
|
2675
|
+
}
|
|
2676
|
+
return {
|
|
2677
|
+
scrollHeight: element.scrollHeight,
|
|
2678
|
+
scrollWidth: element.scrollWidth,
|
|
2679
|
+
clientHeight: element.clientHeight,
|
|
2680
|
+
clientWidth: element.clientWidth,
|
|
2681
|
+
scrollTop: element.scrollTop,
|
|
2682
|
+
scrollLeft: element.scrollLeft
|
|
2683
|
+
};
|
|
2684
|
+
};
|
|
2685
|
+
const useScroll = function (_temp) {
|
|
2686
|
+
let {
|
|
2687
|
+
container,
|
|
2688
|
+
offset = [0, 0]
|
|
2689
|
+
} = _temp === void 0 ? {} : _temp;
|
|
2690
|
+
const [scrollPosition, setScrollPosition] = useState({
|
|
2691
|
+
x: 0,
|
|
2692
|
+
y: 0,
|
|
2693
|
+
xProgress: 0,
|
|
2694
|
+
yProgress: 0
|
|
2695
|
+
});
|
|
2696
|
+
const handleScroll = useCallback(() => {
|
|
2697
|
+
if (!container || !container.current) return;
|
|
2698
|
+
const element = container.current;
|
|
2699
|
+
const {
|
|
2700
|
+
scrollHeight,
|
|
2701
|
+
scrollWidth,
|
|
2702
|
+
clientHeight,
|
|
2703
|
+
clientWidth,
|
|
2704
|
+
scrollTop,
|
|
2705
|
+
scrollLeft
|
|
2706
|
+
} = getScrollDimensions(element);
|
|
2707
|
+
const x = scrollLeft + offset[0];
|
|
2708
|
+
const y = scrollTop + offset[1];
|
|
2709
|
+
const maxScrollX = scrollWidth - clientWidth;
|
|
2710
|
+
const maxScrollY = scrollHeight - clientHeight;
|
|
2711
|
+
const xProgress = maxScrollX > 0 ? x / maxScrollX : 1;
|
|
2712
|
+
const yProgress = maxScrollY > 0 ? y / maxScrollY : 1;
|
|
2713
|
+
setScrollPosition(prev => {
|
|
2714
|
+
if (prev.x !== x || prev.y !== y || prev.xProgress !== xProgress || prev.yProgress !== yProgress) {
|
|
2715
|
+
return {
|
|
2716
|
+
x,
|
|
2717
|
+
y,
|
|
2718
|
+
xProgress,
|
|
2719
|
+
yProgress
|
|
2720
|
+
};
|
|
2721
|
+
}
|
|
2722
|
+
return prev;
|
|
2723
|
+
});
|
|
2724
|
+
}, [container, offset]);
|
|
2725
|
+
useEffect(() => {
|
|
2726
|
+
if (!container || container.current) return;
|
|
2727
|
+
const element = container.current || window;
|
|
2728
|
+
element.addEventListener('scroll', handleScroll, {
|
|
2729
|
+
passive: true
|
|
2730
|
+
});
|
|
2731
|
+
window.addEventListener('resize', handleScroll, {
|
|
2732
|
+
passive: true
|
|
2733
|
+
});
|
|
2734
|
+
handleScroll();
|
|
2735
|
+
return () => {
|
|
2736
|
+
element.removeEventListener('scroll', handleScroll);
|
|
2737
|
+
window.removeEventListener('resize', handleScroll);
|
|
2738
|
+
};
|
|
2739
|
+
}, [handleScroll, container]);
|
|
2740
|
+
return scrollPosition;
|
|
2741
|
+
};
|
|
2742
|
+
const useScrollAnimation = function (ref, options) {
|
|
2743
|
+
if (options === void 0) {
|
|
2744
|
+
options = {};
|
|
2745
|
+
}
|
|
2746
|
+
const [isInView, setIsInView] = useState(false);
|
|
2747
|
+
const [progress, setProgress] = useState(0);
|
|
2748
|
+
useEffect(() => {
|
|
2749
|
+
if (!ref.current) return;
|
|
2750
|
+
const observer = new IntersectionObserver(entries => {
|
|
2751
|
+
entries.forEach(entry => {
|
|
2752
|
+
setIsInView(entry.isIntersecting);
|
|
2753
|
+
setProgress(entry.intersectionRatio);
|
|
2754
|
+
});
|
|
2755
|
+
}, {
|
|
2756
|
+
threshold: options.threshold || 0,
|
|
2757
|
+
rootMargin: options.rootMargin || '0px'
|
|
2758
|
+
});
|
|
2759
|
+
observer.observe(ref.current);
|
|
2760
|
+
return () => observer.disconnect();
|
|
2761
|
+
}, [ref, options.threshold, options.rootMargin]);
|
|
2762
|
+
return {
|
|
2763
|
+
isInView,
|
|
2764
|
+
progress
|
|
2765
|
+
};
|
|
2766
|
+
};
|
|
2767
|
+
const useSmoothScroll = () => {
|
|
2768
|
+
return useCallback(function (element, offset) {
|
|
2769
|
+
if (offset === void 0) {
|
|
2770
|
+
offset = 0;
|
|
2771
|
+
}
|
|
2772
|
+
if (!element) return;
|
|
2773
|
+
const targetPosition = element.getBoundingClientRect().top + window.scrollY - offset;
|
|
2774
|
+
window.scrollTo({
|
|
2775
|
+
top: targetPosition,
|
|
2776
|
+
behavior: 'smooth'
|
|
2777
|
+
});
|
|
2778
|
+
}, []);
|
|
2779
|
+
};
|
|
2780
|
+
const useInfiniteScroll = function (callback, options) {
|
|
2781
|
+
if (options === void 0) {
|
|
2782
|
+
options = {};
|
|
2783
|
+
}
|
|
2784
|
+
const [sentinel, setSentinel] = useState(null);
|
|
2785
|
+
useEffect(() => {
|
|
2786
|
+
if (!sentinel || options.isLoading) return;
|
|
2787
|
+
const observer = new IntersectionObserver(entries => {
|
|
2788
|
+
if (entries[0].isIntersecting) callback();
|
|
2789
|
+
}, {
|
|
2790
|
+
threshold: options.threshold || 0
|
|
2791
|
+
});
|
|
2792
|
+
observer.observe(sentinel);
|
|
2793
|
+
return () => observer.disconnect();
|
|
2794
|
+
}, [sentinel, callback, options.threshold, options.isLoading]);
|
|
2795
|
+
return {
|
|
2796
|
+
sentinelRef: setSentinel
|
|
2797
|
+
};
|
|
2798
|
+
};
|
|
2799
|
+
const useScrollDirection = function (threshold) {
|
|
2800
|
+
if (threshold === void 0) {
|
|
2801
|
+
threshold = 0;
|
|
2802
|
+
}
|
|
2803
|
+
const [scrollDirection, setScrollDirection] = useState('up');
|
|
2804
|
+
const [lastScrollY, setLastScrollY] = useState(0);
|
|
2805
|
+
const updateScrollDirection = useCallback(() => {
|
|
2806
|
+
const scrollY = window.scrollY;
|
|
2807
|
+
const direction = scrollY > lastScrollY ? 'down' : 'up';
|
|
2808
|
+
if (Math.abs(scrollY - lastScrollY) > threshold && direction !== scrollDirection) {
|
|
2809
|
+
setScrollDirection(direction);
|
|
2810
|
+
}
|
|
2811
|
+
setLastScrollY(scrollY > 0 ? scrollY : 0);
|
|
2812
|
+
}, [scrollDirection, lastScrollY, threshold]);
|
|
2813
|
+
useEffect(() => {
|
|
2814
|
+
window.addEventListener('scroll', updateScrollDirection, {
|
|
2815
|
+
passive: true
|
|
2816
|
+
});
|
|
2817
|
+
return () => {
|
|
2818
|
+
window.removeEventListener('scroll', updateScrollDirection);
|
|
2819
|
+
};
|
|
2820
|
+
}, [updateScrollDirection]);
|
|
2821
|
+
return scrollDirection;
|
|
2822
|
+
};
|
|
2823
|
+
|
|
2824
|
+
function useWindowSize() {
|
|
2825
|
+
const [size, setSize] = useState({
|
|
2826
|
+
width: window.innerWidth,
|
|
2827
|
+
height: window.innerHeight
|
|
2828
|
+
});
|
|
2829
|
+
useEffect(() => {
|
|
2830
|
+
const handleResize = () => {
|
|
2831
|
+
setSize({
|
|
2832
|
+
width: window.innerWidth,
|
|
2833
|
+
height: window.innerHeight
|
|
2834
|
+
});
|
|
2835
|
+
};
|
|
2836
|
+
window.addEventListener('resize', handleResize);
|
|
2837
|
+
return () => window.removeEventListener('resize', handleResize);
|
|
2838
|
+
}, []);
|
|
2839
|
+
return size;
|
|
2840
|
+
}
|
|
2841
|
+
|
|
2842
|
+
export { Animation, Button, Div, Element, Form, Image, ImageBackground, Input, ResponsiveContext, ResponsiveProvider, SafeArea, Scroll, Shadows, Skeleton, Span, Text, ThemeContext, ThemeProvider, Typography, View, createQuery, defaultColors, defaultThemeMain, getWindowInitialProps, isBrowser, isDev, isMobile, isProd, isSSR, palette, useActive, useClickOutside, useFocus, useHover, useInfiniteScroll, useKeyPress, useMount, useOnScreen, useResponsive, useResponsiveContext, useScroll, useScrollAnimation, useScrollDirection, useSmoothScroll, useTheme, useWindowSize };
|
|
2548
2843
|
//# sourceMappingURL=app-studio.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-studio.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"app-studio.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -2498,12 +2498,130 @@
|
|
|
2498
2498
|
return navigator.userAgent.match(/(iPhone|iPod|Android|ios|iPad)/i);
|
|
2499
2499
|
}
|
|
2500
2500
|
|
|
2501
|
+
function useActive() {
|
|
2502
|
+
const [active, setActive] = React.useState(false);
|
|
2503
|
+
const ref = React.useRef(null);
|
|
2504
|
+
React.useEffect(() => {
|
|
2505
|
+
const node = ref.current;
|
|
2506
|
+
if (!node) return;
|
|
2507
|
+
const handleMouseDown = () => setActive(true);
|
|
2508
|
+
const handleMouseUp = () => setActive(false);
|
|
2509
|
+
const handleTouchStart = () => setActive(true);
|
|
2510
|
+
const handleTouchEnd = () => setActive(false);
|
|
2511
|
+
node.addEventListener('mousedown', handleMouseDown);
|
|
2512
|
+
node.addEventListener('mouseup', handleMouseUp);
|
|
2513
|
+
node.addEventListener('mouseleave', handleMouseUp);
|
|
2514
|
+
node.addEventListener('touchstart', handleTouchStart);
|
|
2515
|
+
node.addEventListener('touchend', handleTouchEnd);
|
|
2516
|
+
return () => {
|
|
2517
|
+
node.removeEventListener('mousedown', handleMouseDown);
|
|
2518
|
+
node.removeEventListener('mouseup', handleMouseUp);
|
|
2519
|
+
node.removeEventListener('mouseleave', handleMouseUp);
|
|
2520
|
+
node.removeEventListener('touchstart', handleTouchStart);
|
|
2521
|
+
node.removeEventListener('touchend', handleTouchEnd);
|
|
2522
|
+
};
|
|
2523
|
+
}, []);
|
|
2524
|
+
return [ref, active];
|
|
2525
|
+
}
|
|
2526
|
+
|
|
2527
|
+
function useClickOutside() {
|
|
2528
|
+
const [clickedOutside, setClickedOutside] = React.useState(false);
|
|
2529
|
+
const ref = React.useRef(null);
|
|
2530
|
+
React.useEffect(() => {
|
|
2531
|
+
const handleClick = e => {
|
|
2532
|
+
if (ref.current && !ref.current.contains(e.target)) {
|
|
2533
|
+
setClickedOutside(true);
|
|
2534
|
+
} else {
|
|
2535
|
+
setClickedOutside(false);
|
|
2536
|
+
}
|
|
2537
|
+
};
|
|
2538
|
+
document.addEventListener('mousedown', handleClick);
|
|
2539
|
+
return () => {
|
|
2540
|
+
document.removeEventListener('mousedown', handleClick);
|
|
2541
|
+
};
|
|
2542
|
+
}, []);
|
|
2543
|
+
return [ref, clickedOutside];
|
|
2544
|
+
}
|
|
2545
|
+
|
|
2546
|
+
function useFocus() {
|
|
2547
|
+
const [focused, setFocused] = React.useState(false);
|
|
2548
|
+
const ref = React.useRef(null);
|
|
2549
|
+
React.useEffect(() => {
|
|
2550
|
+
const node = ref.current;
|
|
2551
|
+
if (!node) return;
|
|
2552
|
+
const handleFocus = () => setFocused(true);
|
|
2553
|
+
const handleBlur = () => setFocused(false);
|
|
2554
|
+
node.addEventListener('focus', handleFocus);
|
|
2555
|
+
node.addEventListener('blur', handleBlur);
|
|
2556
|
+
return () => {
|
|
2557
|
+
node.removeEventListener('focus', handleFocus);
|
|
2558
|
+
node.removeEventListener('blur', handleBlur);
|
|
2559
|
+
};
|
|
2560
|
+
}, []);
|
|
2561
|
+
return [ref, focused];
|
|
2562
|
+
}
|
|
2563
|
+
|
|
2564
|
+
function useHover() {
|
|
2565
|
+
const [hover, setHover] = React.useState(false);
|
|
2566
|
+
const ref = React.useRef(null);
|
|
2567
|
+
React.useEffect(() => {
|
|
2568
|
+
const node = ref.current;
|
|
2569
|
+
if (!node) return;
|
|
2570
|
+
const handleMouseEnter = () => setHover(true);
|
|
2571
|
+
const handleMouseLeave = () => setHover(false);
|
|
2572
|
+
node.addEventListener('mouseenter', handleMouseEnter);
|
|
2573
|
+
node.addEventListener('mouseleave', handleMouseLeave);
|
|
2574
|
+
return () => {
|
|
2575
|
+
node.removeEventListener('mouseenter', handleMouseEnter);
|
|
2576
|
+
node.removeEventListener('mouseleave', handleMouseLeave);
|
|
2577
|
+
};
|
|
2578
|
+
}, []);
|
|
2579
|
+
return [ref, hover];
|
|
2580
|
+
}
|
|
2581
|
+
|
|
2582
|
+
function useKeyPress(targetKey) {
|
|
2583
|
+
const [keyPressed, setKeyPressed] = React.useState(false);
|
|
2584
|
+
React.useEffect(() => {
|
|
2585
|
+
const downHandler = e => {
|
|
2586
|
+
if (e.key === targetKey) setKeyPressed(true);
|
|
2587
|
+
};
|
|
2588
|
+
const upHandler = e => {
|
|
2589
|
+
if (e.key === targetKey) setKeyPressed(false);
|
|
2590
|
+
};
|
|
2591
|
+
window.addEventListener('keydown', downHandler);
|
|
2592
|
+
window.addEventListener('keyup', upHandler);
|
|
2593
|
+
return () => {
|
|
2594
|
+
window.removeEventListener('keydown', downHandler);
|
|
2595
|
+
window.removeEventListener('keyup', upHandler);
|
|
2596
|
+
};
|
|
2597
|
+
}, [targetKey]);
|
|
2598
|
+
return keyPressed;
|
|
2599
|
+
}
|
|
2600
|
+
|
|
2501
2601
|
const useMount = callback => {
|
|
2502
2602
|
React.useEffect(() => {
|
|
2503
2603
|
callback();
|
|
2504
2604
|
}, []);
|
|
2505
2605
|
};
|
|
2506
2606
|
|
|
2607
|
+
function useOnScreen(options) {
|
|
2608
|
+
const ref = React.useRef(null);
|
|
2609
|
+
const [isOnScreen, setOnScreen] = React.useState(false);
|
|
2610
|
+
React.useEffect(() => {
|
|
2611
|
+
const node = ref.current;
|
|
2612
|
+
if (!node) return;
|
|
2613
|
+
const observer = new IntersectionObserver(_ref => {
|
|
2614
|
+
let [entry] = _ref;
|
|
2615
|
+
setOnScreen(entry.isIntersecting);
|
|
2616
|
+
}, options);
|
|
2617
|
+
observer.observe(node);
|
|
2618
|
+
return () => {
|
|
2619
|
+
observer.unobserve(node);
|
|
2620
|
+
};
|
|
2621
|
+
}, [options]);
|
|
2622
|
+
return [ref, isOnScreen];
|
|
2623
|
+
}
|
|
2624
|
+
|
|
2507
2625
|
const createQuery = (keyScreen, query, set) => {
|
|
2508
2626
|
const mql = window.matchMedia(query);
|
|
2509
2627
|
const onChange = () => {
|
|
@@ -2550,6 +2668,183 @@
|
|
|
2550
2668
|
};
|
|
2551
2669
|
};
|
|
2552
2670
|
|
|
2671
|
+
const getScrollDimensions = element => {
|
|
2672
|
+
if (element instanceof Window) {
|
|
2673
|
+
return {
|
|
2674
|
+
scrollHeight: document.documentElement.scrollHeight,
|
|
2675
|
+
scrollWidth: document.documentElement.scrollWidth,
|
|
2676
|
+
clientHeight: window.innerHeight,
|
|
2677
|
+
clientWidth: window.innerWidth,
|
|
2678
|
+
scrollTop: window.scrollY,
|
|
2679
|
+
scrollLeft: window.scrollX
|
|
2680
|
+
};
|
|
2681
|
+
}
|
|
2682
|
+
return {
|
|
2683
|
+
scrollHeight: element.scrollHeight,
|
|
2684
|
+
scrollWidth: element.scrollWidth,
|
|
2685
|
+
clientHeight: element.clientHeight,
|
|
2686
|
+
clientWidth: element.clientWidth,
|
|
2687
|
+
scrollTop: element.scrollTop,
|
|
2688
|
+
scrollLeft: element.scrollLeft
|
|
2689
|
+
};
|
|
2690
|
+
};
|
|
2691
|
+
const useScroll = function (_temp) {
|
|
2692
|
+
let {
|
|
2693
|
+
container,
|
|
2694
|
+
offset = [0, 0]
|
|
2695
|
+
} = _temp === void 0 ? {} : _temp;
|
|
2696
|
+
const [scrollPosition, setScrollPosition] = React.useState({
|
|
2697
|
+
x: 0,
|
|
2698
|
+
y: 0,
|
|
2699
|
+
xProgress: 0,
|
|
2700
|
+
yProgress: 0
|
|
2701
|
+
});
|
|
2702
|
+
const handleScroll = React.useCallback(() => {
|
|
2703
|
+
if (!container || !container.current) return;
|
|
2704
|
+
const element = container.current;
|
|
2705
|
+
const {
|
|
2706
|
+
scrollHeight,
|
|
2707
|
+
scrollWidth,
|
|
2708
|
+
clientHeight,
|
|
2709
|
+
clientWidth,
|
|
2710
|
+
scrollTop,
|
|
2711
|
+
scrollLeft
|
|
2712
|
+
} = getScrollDimensions(element);
|
|
2713
|
+
const x = scrollLeft + offset[0];
|
|
2714
|
+
const y = scrollTop + offset[1];
|
|
2715
|
+
const maxScrollX = scrollWidth - clientWidth;
|
|
2716
|
+
const maxScrollY = scrollHeight - clientHeight;
|
|
2717
|
+
const xProgress = maxScrollX > 0 ? x / maxScrollX : 1;
|
|
2718
|
+
const yProgress = maxScrollY > 0 ? y / maxScrollY : 1;
|
|
2719
|
+
setScrollPosition(prev => {
|
|
2720
|
+
if (prev.x !== x || prev.y !== y || prev.xProgress !== xProgress || prev.yProgress !== yProgress) {
|
|
2721
|
+
return {
|
|
2722
|
+
x,
|
|
2723
|
+
y,
|
|
2724
|
+
xProgress,
|
|
2725
|
+
yProgress
|
|
2726
|
+
};
|
|
2727
|
+
}
|
|
2728
|
+
return prev;
|
|
2729
|
+
});
|
|
2730
|
+
}, [container, offset]);
|
|
2731
|
+
React.useEffect(() => {
|
|
2732
|
+
if (!container || container.current) return;
|
|
2733
|
+
const element = container.current || window;
|
|
2734
|
+
element.addEventListener('scroll', handleScroll, {
|
|
2735
|
+
passive: true
|
|
2736
|
+
});
|
|
2737
|
+
window.addEventListener('resize', handleScroll, {
|
|
2738
|
+
passive: true
|
|
2739
|
+
});
|
|
2740
|
+
handleScroll();
|
|
2741
|
+
return () => {
|
|
2742
|
+
element.removeEventListener('scroll', handleScroll);
|
|
2743
|
+
window.removeEventListener('resize', handleScroll);
|
|
2744
|
+
};
|
|
2745
|
+
}, [handleScroll, container]);
|
|
2746
|
+
return scrollPosition;
|
|
2747
|
+
};
|
|
2748
|
+
const useScrollAnimation = function (ref, options) {
|
|
2749
|
+
if (options === void 0) {
|
|
2750
|
+
options = {};
|
|
2751
|
+
}
|
|
2752
|
+
const [isInView, setIsInView] = React.useState(false);
|
|
2753
|
+
const [progress, setProgress] = React.useState(0);
|
|
2754
|
+
React.useEffect(() => {
|
|
2755
|
+
if (!ref.current) return;
|
|
2756
|
+
const observer = new IntersectionObserver(entries => {
|
|
2757
|
+
entries.forEach(entry => {
|
|
2758
|
+
setIsInView(entry.isIntersecting);
|
|
2759
|
+
setProgress(entry.intersectionRatio);
|
|
2760
|
+
});
|
|
2761
|
+
}, {
|
|
2762
|
+
threshold: options.threshold || 0,
|
|
2763
|
+
rootMargin: options.rootMargin || '0px'
|
|
2764
|
+
});
|
|
2765
|
+
observer.observe(ref.current);
|
|
2766
|
+
return () => observer.disconnect();
|
|
2767
|
+
}, [ref, options.threshold, options.rootMargin]);
|
|
2768
|
+
return {
|
|
2769
|
+
isInView,
|
|
2770
|
+
progress
|
|
2771
|
+
};
|
|
2772
|
+
};
|
|
2773
|
+
const useSmoothScroll = () => {
|
|
2774
|
+
return React.useCallback(function (element, offset) {
|
|
2775
|
+
if (offset === void 0) {
|
|
2776
|
+
offset = 0;
|
|
2777
|
+
}
|
|
2778
|
+
if (!element) return;
|
|
2779
|
+
const targetPosition = element.getBoundingClientRect().top + window.scrollY - offset;
|
|
2780
|
+
window.scrollTo({
|
|
2781
|
+
top: targetPosition,
|
|
2782
|
+
behavior: 'smooth'
|
|
2783
|
+
});
|
|
2784
|
+
}, []);
|
|
2785
|
+
};
|
|
2786
|
+
const useInfiniteScroll = function (callback, options) {
|
|
2787
|
+
if (options === void 0) {
|
|
2788
|
+
options = {};
|
|
2789
|
+
}
|
|
2790
|
+
const [sentinel, setSentinel] = React.useState(null);
|
|
2791
|
+
React.useEffect(() => {
|
|
2792
|
+
if (!sentinel || options.isLoading) return;
|
|
2793
|
+
const observer = new IntersectionObserver(entries => {
|
|
2794
|
+
if (entries[0].isIntersecting) callback();
|
|
2795
|
+
}, {
|
|
2796
|
+
threshold: options.threshold || 0
|
|
2797
|
+
});
|
|
2798
|
+
observer.observe(sentinel);
|
|
2799
|
+
return () => observer.disconnect();
|
|
2800
|
+
}, [sentinel, callback, options.threshold, options.isLoading]);
|
|
2801
|
+
return {
|
|
2802
|
+
sentinelRef: setSentinel
|
|
2803
|
+
};
|
|
2804
|
+
};
|
|
2805
|
+
const useScrollDirection = function (threshold) {
|
|
2806
|
+
if (threshold === void 0) {
|
|
2807
|
+
threshold = 0;
|
|
2808
|
+
}
|
|
2809
|
+
const [scrollDirection, setScrollDirection] = React.useState('up');
|
|
2810
|
+
const [lastScrollY, setLastScrollY] = React.useState(0);
|
|
2811
|
+
const updateScrollDirection = React.useCallback(() => {
|
|
2812
|
+
const scrollY = window.scrollY;
|
|
2813
|
+
const direction = scrollY > lastScrollY ? 'down' : 'up';
|
|
2814
|
+
if (Math.abs(scrollY - lastScrollY) > threshold && direction !== scrollDirection) {
|
|
2815
|
+
setScrollDirection(direction);
|
|
2816
|
+
}
|
|
2817
|
+
setLastScrollY(scrollY > 0 ? scrollY : 0);
|
|
2818
|
+
}, [scrollDirection, lastScrollY, threshold]);
|
|
2819
|
+
React.useEffect(() => {
|
|
2820
|
+
window.addEventListener('scroll', updateScrollDirection, {
|
|
2821
|
+
passive: true
|
|
2822
|
+
});
|
|
2823
|
+
return () => {
|
|
2824
|
+
window.removeEventListener('scroll', updateScrollDirection);
|
|
2825
|
+
};
|
|
2826
|
+
}, [updateScrollDirection]);
|
|
2827
|
+
return scrollDirection;
|
|
2828
|
+
};
|
|
2829
|
+
|
|
2830
|
+
function useWindowSize() {
|
|
2831
|
+
const [size, setSize] = React.useState({
|
|
2832
|
+
width: window.innerWidth,
|
|
2833
|
+
height: window.innerHeight
|
|
2834
|
+
});
|
|
2835
|
+
React.useEffect(() => {
|
|
2836
|
+
const handleResize = () => {
|
|
2837
|
+
setSize({
|
|
2838
|
+
width: window.innerWidth,
|
|
2839
|
+
height: window.innerHeight
|
|
2840
|
+
});
|
|
2841
|
+
};
|
|
2842
|
+
window.addEventListener('resize', handleResize);
|
|
2843
|
+
return () => window.removeEventListener('resize', handleResize);
|
|
2844
|
+
}, []);
|
|
2845
|
+
return size;
|
|
2846
|
+
}
|
|
2847
|
+
|
|
2553
2848
|
exports.Animation = Animation;
|
|
2554
2849
|
exports.Button = Button;
|
|
2555
2850
|
exports.Div = Div;
|
|
@@ -2580,10 +2875,22 @@
|
|
|
2580
2875
|
exports.isProd = isProd;
|
|
2581
2876
|
exports.isSSR = isSSR;
|
|
2582
2877
|
exports.palette = palette;
|
|
2878
|
+
exports.useActive = useActive;
|
|
2879
|
+
exports.useClickOutside = useClickOutside;
|
|
2880
|
+
exports.useFocus = useFocus;
|
|
2881
|
+
exports.useHover = useHover;
|
|
2882
|
+
exports.useInfiniteScroll = useInfiniteScroll;
|
|
2883
|
+
exports.useKeyPress = useKeyPress;
|
|
2583
2884
|
exports.useMount = useMount;
|
|
2885
|
+
exports.useOnScreen = useOnScreen;
|
|
2584
2886
|
exports.useResponsive = useResponsive;
|
|
2585
2887
|
exports.useResponsiveContext = useResponsiveContext;
|
|
2888
|
+
exports.useScroll = useScroll;
|
|
2889
|
+
exports.useScrollAnimation = useScrollAnimation;
|
|
2890
|
+
exports.useScrollDirection = useScrollDirection;
|
|
2891
|
+
exports.useSmoothScroll = useSmoothScroll;
|
|
2586
2892
|
exports.useTheme = useTheme;
|
|
2893
|
+
exports.useWindowSize = useWindowSize;
|
|
2587
2894
|
|
|
2588
2895
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2589
2896
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-studio.umd.development.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"app-studio.umd.development.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|