app-studio 0.7.8 → 0.7.9
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 +100 -74
- 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 +100 -74
- package/dist/app-studio.esm.js.map +1 -1
- package/dist/app-studio.umd.development.js +100 -74
- package/dist/app-studio.umd.development.js.map +1 -1
- package/dist/app-studio.umd.production.min.js +1 -1
- package/dist/stories/IframeSupport.stories.d.ts +3 -0
- package/package.json +8 -1
|
@@ -1066,12 +1066,15 @@ const deepMerge = (target, source) => {
|
|
|
1066
1066
|
}
|
|
1067
1067
|
return merged;
|
|
1068
1068
|
};
|
|
1069
|
+
// Stable default references to prevent unnecessary re-renders and cache invalidation
|
|
1070
|
+
const DEFAULT_THEME_OVERRIDE = {};
|
|
1071
|
+
const DEFAULT_COLORS_OVERRIDE = {};
|
|
1069
1072
|
const ThemeProvider = _ref => {
|
|
1070
1073
|
let {
|
|
1071
|
-
theme: themeOverride =
|
|
1074
|
+
theme: themeOverride = DEFAULT_THEME_OVERRIDE,
|
|
1072
1075
|
mode: initialMode = 'light',
|
|
1073
|
-
dark: darkOverride =
|
|
1074
|
-
light: lightOverride =
|
|
1076
|
+
dark: darkOverride = DEFAULT_COLORS_OVERRIDE,
|
|
1077
|
+
light: lightOverride = DEFAULT_COLORS_OVERRIDE,
|
|
1075
1078
|
children,
|
|
1076
1079
|
strict = false,
|
|
1077
1080
|
targetWindow
|
|
@@ -2950,10 +2953,11 @@ const AnalyticsProvider = _ref => {
|
|
|
2950
2953
|
trackEvent,
|
|
2951
2954
|
children
|
|
2952
2955
|
} = _ref;
|
|
2956
|
+
const value = React.useMemo(() => ({
|
|
2957
|
+
trackEvent
|
|
2958
|
+
}), [trackEvent]);
|
|
2953
2959
|
return /*#__PURE__*/React__default.createElement(AnalyticsContext.Provider, {
|
|
2954
|
-
value:
|
|
2955
|
-
trackEvent
|
|
2956
|
-
}
|
|
2960
|
+
value: value
|
|
2957
2961
|
}, children);
|
|
2958
2962
|
};
|
|
2959
2963
|
|
|
@@ -2985,12 +2989,10 @@ function hashStyleProps(props) {
|
|
|
2985
2989
|
*/
|
|
2986
2990
|
function useStableStyleMemo(propsToProcess, getColor, mediaQueries, devices, manager, theme) {
|
|
2987
2991
|
const cacheRef = React.useRef(null);
|
|
2988
|
-
// Compute hash
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
return hashStyleProps(propsToProcess) + '|' + hash(themeHash);
|
|
2993
|
-
}, [propsToProcess, theme]);
|
|
2992
|
+
// Compute hash directly — no useMemo since propsToProcess is always a new
|
|
2993
|
+
// reference (from destructuring), so the memo deps would always change.
|
|
2994
|
+
const themeHash = theme ? JSON.stringify(theme) : '';
|
|
2995
|
+
const currentHash = hashStyleProps(propsToProcess) + '|' + hash(themeHash);
|
|
2994
2996
|
// Only recompute classes if hash changed
|
|
2995
2997
|
if (!cacheRef.current || cacheRef.current.hash !== currentHash) {
|
|
2996
2998
|
const classes = extractUtilityClasses(propsToProcess, getColor, mediaQueries, devices, manager);
|
|
@@ -3082,44 +3084,44 @@ const Element = /*#__PURE__*/React__default.memo(/*#__PURE__*/React.forwardRef((
|
|
|
3082
3084
|
};
|
|
3083
3085
|
}, [animateOut, manager]);
|
|
3084
3086
|
// Prepare props for processing (apply view/scroll timeline if needed)
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
}
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
}
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
}
|
|
3087
|
+
// No useMemo — `rest` is always a new reference from destructuring, so
|
|
3088
|
+
// memo deps would always change. useStableStyleMemo handles the real
|
|
3089
|
+
// memoization via hash-based comparison.
|
|
3090
|
+
const propsToProcess = {
|
|
3091
|
+
...rest,
|
|
3092
|
+
blend
|
|
3093
|
+
};
|
|
3094
|
+
// Apply view() timeline ONLY if animateOn='View' (not Both or Mount)
|
|
3095
|
+
if (animateOn === 'View' && propsToProcess.animate) {
|
|
3096
|
+
const animations = Array.isArray(propsToProcess.animate) ? propsToProcess.animate : [propsToProcess.animate];
|
|
3097
|
+
propsToProcess.animate = animations.map(anim => {
|
|
3098
|
+
// Only add timeline if not already specified
|
|
3099
|
+
if (!anim.timeline) {
|
|
3100
|
+
return {
|
|
3101
|
+
...anim,
|
|
3102
|
+
timeline: 'view()',
|
|
3103
|
+
range: anim.range || 'entry',
|
|
3104
|
+
fillMode: anim.fillMode || 'both'
|
|
3105
|
+
};
|
|
3106
|
+
}
|
|
3107
|
+
return anim;
|
|
3108
|
+
});
|
|
3109
|
+
}
|
|
3110
|
+
// Apply scroll() timeline if animateOn='Scroll'
|
|
3111
|
+
if (animateOn === 'Scroll' && propsToProcess.animate) {
|
|
3112
|
+
const animations = Array.isArray(propsToProcess.animate) ? propsToProcess.animate : [propsToProcess.animate];
|
|
3113
|
+
propsToProcess.animate = animations.map(anim => {
|
|
3114
|
+
// Only add timeline if not already specified
|
|
3115
|
+
if (!anim.timeline) {
|
|
3116
|
+
return {
|
|
3117
|
+
...anim,
|
|
3118
|
+
timeline: 'scroll()',
|
|
3119
|
+
fillMode: anim.fillMode || 'both'
|
|
3120
|
+
};
|
|
3121
|
+
}
|
|
3122
|
+
return anim;
|
|
3123
|
+
});
|
|
3124
|
+
}
|
|
3123
3125
|
// Use hash-based memoization for style extraction
|
|
3124
3126
|
const utilityClasses = useStableStyleMemo(propsToProcess, getColor, mediaQueries, devices, manager, theme);
|
|
3125
3127
|
const newProps = {
|
|
@@ -5041,14 +5043,28 @@ const WindowSizeProvider = _ref => {
|
|
|
5041
5043
|
width: win?.innerWidth || 0,
|
|
5042
5044
|
height: win?.innerHeight || 0
|
|
5043
5045
|
});
|
|
5046
|
+
const timeoutRef = React.useRef();
|
|
5044
5047
|
React.useEffect(() => {
|
|
5045
5048
|
if (!win) return;
|
|
5046
|
-
const handleResize = () =>
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5049
|
+
const handleResize = () => {
|
|
5050
|
+
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
5051
|
+
timeoutRef.current = setTimeout(() => {
|
|
5052
|
+
const newWidth = win.innerWidth;
|
|
5053
|
+
const newHeight = win.innerHeight;
|
|
5054
|
+
setSize(prev => {
|
|
5055
|
+
if (prev.width === newWidth && prev.height === newHeight) return prev;
|
|
5056
|
+
return {
|
|
5057
|
+
width: newWidth,
|
|
5058
|
+
height: newHeight
|
|
5059
|
+
};
|
|
5060
|
+
});
|
|
5061
|
+
}, 100);
|
|
5062
|
+
};
|
|
5050
5063
|
win.addEventListener('resize', handleResize);
|
|
5051
|
-
return () =>
|
|
5064
|
+
return () => {
|
|
5065
|
+
win.removeEventListener('resize', handleResize);
|
|
5066
|
+
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
5067
|
+
};
|
|
5052
5068
|
}, [win]);
|
|
5053
5069
|
return /*#__PURE__*/React__default.createElement(WindowSizeContext.Provider, {
|
|
5054
5070
|
value: size
|
|
@@ -5081,12 +5097,13 @@ function useActive() {
|
|
|
5081
5097
|
return [ref, active];
|
|
5082
5098
|
}
|
|
5083
5099
|
|
|
5100
|
+
const DEFAULT_CLICK_OUTSIDE_OPTIONS = {};
|
|
5084
5101
|
function useClickOutside(options) {
|
|
5085
5102
|
const [clickedOutside, setClickedOutside] = React.useState(false);
|
|
5086
5103
|
const ref = React.useRef(null);
|
|
5087
5104
|
const {
|
|
5088
5105
|
targetWindow
|
|
5089
|
-
} = options ||
|
|
5106
|
+
} = options || DEFAULT_CLICK_OUTSIDE_OPTIONS;
|
|
5090
5107
|
React.useEffect(() => {
|
|
5091
5108
|
const win = targetWindow || (typeof window !== 'undefined' ? window : null);
|
|
5092
5109
|
if (!win) return;
|
|
@@ -5106,13 +5123,14 @@ function useClickOutside(options) {
|
|
|
5106
5123
|
return [ref, clickedOutside];
|
|
5107
5124
|
}
|
|
5108
5125
|
|
|
5126
|
+
const DEFAULT_ELEMENT_POSITION_OPTIONS = {};
|
|
5109
5127
|
/**
|
|
5110
5128
|
* A React hook to determine an element's relative position within the viewport
|
|
5111
5129
|
* and where the most available space is around it within the viewport.
|
|
5112
5130
|
*/
|
|
5113
5131
|
function useElementPosition(options) {
|
|
5114
5132
|
if (options === void 0) {
|
|
5115
|
-
options =
|
|
5133
|
+
options = DEFAULT_ELEMENT_POSITION_OPTIONS;
|
|
5116
5134
|
}
|
|
5117
5135
|
const {
|
|
5118
5136
|
trackChanges = true,
|
|
@@ -5284,18 +5302,21 @@ function useKeyPress(targetKey) {
|
|
|
5284
5302
|
}
|
|
5285
5303
|
|
|
5286
5304
|
const useMount = callback => {
|
|
5305
|
+
const callbackRef = React.useRef(callback);
|
|
5306
|
+
callbackRef.current = callback;
|
|
5287
5307
|
React.useEffect(() => {
|
|
5288
|
-
|
|
5308
|
+
callbackRef.current();
|
|
5289
5309
|
}, []);
|
|
5290
5310
|
};
|
|
5291
5311
|
|
|
5312
|
+
const DEFAULT_ON_SCREEN_OPTIONS = {};
|
|
5292
5313
|
function useOnScreen(options) {
|
|
5293
5314
|
const ref = React.useRef(null);
|
|
5294
5315
|
const [isOnScreen, setOnScreen] = React.useState(false);
|
|
5295
5316
|
const {
|
|
5296
5317
|
targetWindow,
|
|
5297
5318
|
...observerOptions
|
|
5298
|
-
} = options ||
|
|
5319
|
+
} = options || DEFAULT_ON_SCREEN_OPTIONS;
|
|
5299
5320
|
React.useEffect(() => {
|
|
5300
5321
|
const node = ref.current;
|
|
5301
5322
|
if (!node) return;
|
|
@@ -5314,7 +5335,7 @@ function useOnScreen(options) {
|
|
|
5314
5335
|
return () => {
|
|
5315
5336
|
observer.disconnect();
|
|
5316
5337
|
};
|
|
5317
|
-
}, [targetWindow,
|
|
5338
|
+
}, [targetWindow, observerOptions.root, observerOptions.rootMargin, observerOptions.threshold]);
|
|
5318
5339
|
return [ref, isOnScreen];
|
|
5319
5340
|
}
|
|
5320
5341
|
|
|
@@ -5339,14 +5360,14 @@ const useBreakpoint = () => {
|
|
|
5339
5360
|
devices
|
|
5340
5361
|
} = context;
|
|
5341
5362
|
// Helper to check if current screen matches a breakpoint or device
|
|
5342
|
-
const on = s => devices[s] ? devices[s].includes(screen) : s === screen;
|
|
5343
|
-
return {
|
|
5363
|
+
const on = React.useCallback(s => devices[s] ? devices[s].includes(screen) : s === screen, [devices, screen]);
|
|
5364
|
+
return React.useMemo(() => ({
|
|
5344
5365
|
...context,
|
|
5345
5366
|
screen,
|
|
5346
5367
|
orientation,
|
|
5347
5368
|
on,
|
|
5348
5369
|
is: on
|
|
5349
|
-
};
|
|
5370
|
+
}), [context, screen, orientation, on]);
|
|
5350
5371
|
};
|
|
5351
5372
|
/**
|
|
5352
5373
|
* Hook for components that need exact window dimensions.
|
|
@@ -5377,17 +5398,21 @@ const useResponsive = () => {
|
|
|
5377
5398
|
orientation,
|
|
5378
5399
|
devices
|
|
5379
5400
|
} = context;
|
|
5380
|
-
const on = s => devices[s] ? devices[s].includes(screen) : s === screen;
|
|
5381
|
-
|
|
5401
|
+
const on = React.useCallback(s => devices[s] ? devices[s].includes(screen) : s === screen, [devices, screen]);
|
|
5402
|
+
return React.useMemo(() => ({
|
|
5382
5403
|
...context,
|
|
5383
5404
|
screen,
|
|
5384
5405
|
orientation,
|
|
5385
5406
|
on,
|
|
5386
5407
|
is: on
|
|
5387
|
-
};
|
|
5388
|
-
return result;
|
|
5408
|
+
}), [context, screen, orientation, on]);
|
|
5389
5409
|
};
|
|
5390
5410
|
|
|
5411
|
+
// Stable default references to prevent unnecessary re-renders
|
|
5412
|
+
const DEFAULT_SCROLL_OFFSET = [0, 0];
|
|
5413
|
+
const DEFAULT_SCROLL_OPTIONS = {};
|
|
5414
|
+
const DEFAULT_SCROLL_ANIMATION_OPTIONS = {};
|
|
5415
|
+
const DEFAULT_INFINITE_SCROLL_OPTIONS = {};
|
|
5391
5416
|
// Helper to check if element is a Window object (works across iframes)
|
|
5392
5417
|
const isWindow = obj => {
|
|
5393
5418
|
return obj && obj.window === obj;
|
|
@@ -5421,10 +5446,10 @@ const getScrollDimensions = element => {
|
|
|
5421
5446
|
const useScroll = function (_temp) {
|
|
5422
5447
|
let {
|
|
5423
5448
|
container,
|
|
5424
|
-
offset =
|
|
5449
|
+
offset = DEFAULT_SCROLL_OFFSET,
|
|
5425
5450
|
throttleMs = 100,
|
|
5426
5451
|
disabled = false
|
|
5427
|
-
} = _temp === void 0 ?
|
|
5452
|
+
} = _temp === void 0 ? DEFAULT_SCROLL_OPTIONS : _temp;
|
|
5428
5453
|
const [scrollPosition, setScrollPosition] = React.useState({
|
|
5429
5454
|
x: 0,
|
|
5430
5455
|
y: 0,
|
|
@@ -5563,7 +5588,7 @@ const useScroll = function (_temp) {
|
|
|
5563
5588
|
// Enhanced useScrollAnimation with callback support and iframe support
|
|
5564
5589
|
const useScrollAnimation = function (ref, options) {
|
|
5565
5590
|
if (options === void 0) {
|
|
5566
|
-
options =
|
|
5591
|
+
options = DEFAULT_SCROLL_ANIMATION_OPTIONS;
|
|
5567
5592
|
}
|
|
5568
5593
|
const [isInView, setIsInView] = React.useState(false);
|
|
5569
5594
|
const [progress, setProgress] = React.useState(0);
|
|
@@ -5631,7 +5656,7 @@ const useSmoothScroll = targetWindow => {
|
|
|
5631
5656
|
// Enhanced useInfiniteScroll with debouncing
|
|
5632
5657
|
const useInfiniteScroll = function (callback, options) {
|
|
5633
5658
|
if (options === void 0) {
|
|
5634
|
-
options =
|
|
5659
|
+
options = DEFAULT_INFINITE_SCROLL_OPTIONS;
|
|
5635
5660
|
}
|
|
5636
5661
|
const [sentinel, setSentinel] = React.useState(null);
|
|
5637
5662
|
const callbackRef = React.useRef(callback);
|
|
@@ -5726,12 +5751,13 @@ const useScrollDirection = function (threshold, targetWindow) {
|
|
|
5726
5751
|
|
|
5727
5752
|
const useWindowSize = () => React.useContext(WindowSizeContext);
|
|
5728
5753
|
|
|
5754
|
+
const DEFAULT_IN_VIEW_OPTIONS = {};
|
|
5729
5755
|
function useInView(options) {
|
|
5730
5756
|
const {
|
|
5731
5757
|
triggerOnce = false,
|
|
5732
5758
|
targetWindow,
|
|
5733
5759
|
...observerOptions
|
|
5734
|
-
} = options ||
|
|
5760
|
+
} = options || DEFAULT_IN_VIEW_OPTIONS;
|
|
5735
5761
|
const ref = React.useRef(null);
|
|
5736
5762
|
const [inView, setInView] = React.useState(false);
|
|
5737
5763
|
React.useEffect(() => {
|
|
@@ -5761,7 +5787,7 @@ function useInView(options) {
|
|
|
5761
5787
|
return () => {
|
|
5762
5788
|
observer.disconnect();
|
|
5763
5789
|
};
|
|
5764
|
-
}, [triggerOnce, targetWindow,
|
|
5790
|
+
}, [triggerOnce, targetWindow, observerOptions.root, observerOptions.rootMargin, observerOptions.threshold]);
|
|
5765
5791
|
return {
|
|
5766
5792
|
ref,
|
|
5767
5793
|
inView
|
|
@@ -5846,7 +5872,7 @@ function useIframe(iframeRef) {
|
|
|
5846
5872
|
if (!iframe) return;
|
|
5847
5873
|
const updateState = () => {
|
|
5848
5874
|
const win = iframe.contentWindow;
|
|
5849
|
-
const doc = iframe.contentDocument
|
|
5875
|
+
const doc = win?.document || iframe.contentDocument;
|
|
5850
5876
|
if (win && doc) {
|
|
5851
5877
|
setIframeWindow(win);
|
|
5852
5878
|
setIframeDocument(doc);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-studio.cjs.development.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"app-studio.cjs.development.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|