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.
@@ -1,4 +1,4 @@
1
- import React, { createContext, useContext, forwardRef, useMemo, useEffect, useState } from 'react';
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
- 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, useMount, useResponsive, useResponsiveContext, useTheme };
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}