app-studio 0.6.55 → 0.6.57
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/README.md +2 -1
- package/dist/app-studio.cjs.development.js +86 -6
- 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 +85 -7
- package/dist/app-studio.esm.js.map +1 -1
- package/dist/app-studio.umd.development.js +86 -6
- package/dist/app-studio.umd.development.js.map +1 -1
- package/dist/app-studio.umd.production.min.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/providers/Theme.d.ts +2 -0
- package/dist/providers/WindowSize.d.ts +0 -4
- package/docs/Components.md +20 -5
- package/docs/README.md +2 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -207,6 +207,7 @@ A versatile container component extending `Element`, primarily used for layout.
|
|
|
207
207
|
|
|
208
208
|
* `Horizontal`: A `View` with `display: flex`, `flexDirection: row`.
|
|
209
209
|
* `Vertical`: A `View` with `display: flex`, `flexDirection: column`.
|
|
210
|
+
* `Center`: A `View` with `display: flex`, `justifyContent: center`, `alignItems: center`.
|
|
210
211
|
* `HorizontalResponsive`: Switches from `row` to `column` on `mobile`.
|
|
211
212
|
* `VerticalResponsive`: Switches from `column` to `row` on `mobile`.
|
|
212
213
|
* `Scroll`: Basic scrollable view (might need explicit overflow styles).
|
|
@@ -801,7 +802,7 @@ Explore our comprehensive documentation to learn more about App-Studio:
|
|
|
801
802
|
# API Reference Summary
|
|
802
803
|
|
|
803
804
|
* **Core:** `Element`
|
|
804
|
-
* **Components:** `View`, `Horizontal`, `Vertical`, `HorizontalResponsive`, `VerticalResponsive`, `Scroll`, `SafeArea`, `Div`, `Span`, `Text`, `Image`, `ImageBackground`, `Form`, `Input`, `Button`, `Skeleton`.
|
|
805
|
+
* **Components:** `View`, `Horizontal`, `Vertical`, `Center`, `HorizontalResponsive`, `VerticalResponsive`, `Scroll`, `SafeArea`, `Div`, `Span`, `Text`, `Image`, `ImageBackground`, `Form`, `Input`, `Button`, `Skeleton`.
|
|
805
806
|
* **Animation:** `Animation` object with functions like `fadeIn`, `slideInLeft`, `pulse`, etc.
|
|
806
807
|
* **Hooks:** `useActive`, `useClickOutside`, `useElementPosition`, `useFocus`, `useHover`, `useInView`, `useKeyPress`, `useMount`, `useOnScreen`, `useResponsive`, `useScroll`, `useWindowSize`.
|
|
807
808
|
* **Providers:** `ThemeProvider`, `ResponsiveProvider`, `AnalyticsProvider`, `WindowSizeProvider`.
|
|
@@ -899,6 +899,8 @@ const defaultDarkColorConfig = {
|
|
|
899
899
|
const ThemeContext = /*#__PURE__*/React.createContext({
|
|
900
900
|
getColor: () => '',
|
|
901
901
|
getColorHex: () => '',
|
|
902
|
+
getColorRGBA: () => '',
|
|
903
|
+
getColorScheme: () => 'light',
|
|
902
904
|
theme: {},
|
|
903
905
|
colors: {
|
|
904
906
|
main: defaultLightColors,
|
|
@@ -998,6 +1000,42 @@ const normalizeToHex = color => {
|
|
|
998
1000
|
}
|
|
999
1001
|
return trimmed;
|
|
1000
1002
|
};
|
|
1003
|
+
const normalizeToRgba = (color, alphaOverride) => {
|
|
1004
|
+
if (!color || typeof color !== 'string') return String(color);
|
|
1005
|
+
const trimmed = color.trim();
|
|
1006
|
+
const overrideAlpha = typeof alphaOverride === 'number' ? Math.max(0, Math.min(1000, alphaOverride)) / 1000 : undefined;
|
|
1007
|
+
if (trimmed === TRANSPARENT) {
|
|
1008
|
+
const a = overrideAlpha ?? 0;
|
|
1009
|
+
return `rgba(0, 0, 0, ${a})`;
|
|
1010
|
+
}
|
|
1011
|
+
if (trimmed.startsWith('#')) {
|
|
1012
|
+
let hex = trimmed.slice(1);
|
|
1013
|
+
if (hex.length === 3 || hex.length === 4) {
|
|
1014
|
+
hex = hex.split('').map(ch => ch + ch).join('');
|
|
1015
|
+
}
|
|
1016
|
+
if (hex.length !== 6 && hex.length !== 8) return trimmed;
|
|
1017
|
+
const r = parseInt(hex.slice(0, 2), 16);
|
|
1018
|
+
const g = parseInt(hex.slice(2, 4), 16);
|
|
1019
|
+
const b = parseInt(hex.slice(4, 6), 16);
|
|
1020
|
+
const aFromHex = hex.length === 8 ? parseInt(hex.slice(6, 8), 16) / 255 : 1;
|
|
1021
|
+
const a = overrideAlpha ?? aFromHex;
|
|
1022
|
+
return `rgba(${r}, ${g}, ${b}, ${a})`;
|
|
1023
|
+
}
|
|
1024
|
+
if (trimmed.startsWith('rgb')) {
|
|
1025
|
+
const match = trimmed.match(/rgba?\(([^)]+)\)/i);
|
|
1026
|
+
if (!match) return trimmed;
|
|
1027
|
+
const parts = match[1].split(',').map(p => p.trim()).filter(Boolean);
|
|
1028
|
+
const r = Number(parts[0]);
|
|
1029
|
+
const g = Number(parts[1]);
|
|
1030
|
+
const b = Number(parts[2]);
|
|
1031
|
+
const aExisting = parts.length >= 4 ? Number(parts[3]) : 1;
|
|
1032
|
+
if ([r, g, b].some(v => Number.isNaN(v)) || Number.isNaN(aExisting)) return trimmed;
|
|
1033
|
+
const a = overrideAlpha ?? Math.max(0, Math.min(1, aExisting));
|
|
1034
|
+
return `rgba(${r}, ${g}, ${b}, ${a})`;
|
|
1035
|
+
}
|
|
1036
|
+
// If it's already something else (var(), color-mix(), named color), we can't reliably convert.
|
|
1037
|
+
return trimmed;
|
|
1038
|
+
};
|
|
1001
1039
|
// --- Deep Merge Function (remains the same, assuming it works as intended) ---
|
|
1002
1040
|
// Consider using a library like `lodash.merge` or `deepmerge` if complexity grows
|
|
1003
1041
|
// or edge cases (like merging arrays) need different handling.
|
|
@@ -1239,15 +1277,35 @@ const ThemeProvider = _ref => {
|
|
|
1239
1277
|
if (!override) colorCache.set(cacheKey, hex);
|
|
1240
1278
|
return hex;
|
|
1241
1279
|
}, [themeMode, colorCache, resolveColorTokenForMode]);
|
|
1280
|
+
const getColorRGBA = React.useCallback((name, alphaOrOverride, overrideMaybe) => {
|
|
1281
|
+
if (!name || typeof name !== 'string') return String(name);
|
|
1282
|
+
const alpha = typeof alphaOrOverride === 'number' ? alphaOrOverride : undefined;
|
|
1283
|
+
const override = typeof alphaOrOverride === 'object' ? alphaOrOverride : overrideMaybe;
|
|
1284
|
+
const effectiveMode = override?.themeMode ?? themeMode;
|
|
1285
|
+
const alphaKey = typeof alpha === 'number' ? String(alpha) : 'auto';
|
|
1286
|
+
const cacheKey = `${name}-${effectiveMode}-rgba-${alphaKey}`;
|
|
1287
|
+
if (!override && colorCache.has(cacheKey)) {
|
|
1288
|
+
return colorCache.get(cacheKey);
|
|
1289
|
+
}
|
|
1290
|
+
const resolved = resolveColorTokenForMode(name, effectiveMode, override);
|
|
1291
|
+
const rgba = normalizeToRgba(resolved, alpha);
|
|
1292
|
+
if (!override) colorCache.set(cacheKey, rgba);
|
|
1293
|
+
return rgba;
|
|
1294
|
+
}, [themeMode, colorCache, resolveColorTokenForMode]);
|
|
1295
|
+
const getColorScheme = React.useCallback(override => {
|
|
1296
|
+
return override?.themeMode ?? themeMode;
|
|
1297
|
+
}, [themeMode]);
|
|
1242
1298
|
// --- Memoize Context Value ---
|
|
1243
1299
|
const contextValue = React.useMemo(() => ({
|
|
1244
1300
|
getColor,
|
|
1245
1301
|
getColorHex,
|
|
1302
|
+
getColorRGBA,
|
|
1303
|
+
getColorScheme,
|
|
1246
1304
|
theme: mergedTheme,
|
|
1247
1305
|
colors: currentColors,
|
|
1248
1306
|
themeMode,
|
|
1249
1307
|
setThemeMode
|
|
1250
|
-
}), [getColor, getColorHex, mergedTheme, currentColors, themeMode]);
|
|
1308
|
+
}), [getColor, getColorHex, getColorRGBA, getColorScheme, mergedTheme, currentColors, themeMode]);
|
|
1251
1309
|
return /*#__PURE__*/React__default.createElement(ThemeContext.Provider, {
|
|
1252
1310
|
value: contextValue
|
|
1253
1311
|
}, /*#__PURE__*/React__default.createElement("style", null, generateCSSVariables(mergedTheme, themeColors.light, themeColors.dark)), /*#__PURE__*/React__default.createElement("div", {
|
|
@@ -4690,6 +4748,31 @@ function isMobile() {
|
|
|
4690
4748
|
return navigator.userAgent.match(/(iPhone|iPod|Android|ios|iPad)/i);
|
|
4691
4749
|
}
|
|
4692
4750
|
|
|
4751
|
+
const WindowSizeContext = /*#__PURE__*/React.createContext({
|
|
4752
|
+
width: 0,
|
|
4753
|
+
height: 0
|
|
4754
|
+
});
|
|
4755
|
+
const WindowSizeProvider = _ref => {
|
|
4756
|
+
let {
|
|
4757
|
+
children
|
|
4758
|
+
} = _ref;
|
|
4759
|
+
const [size, setSize] = React.useState({
|
|
4760
|
+
width: window.innerWidth,
|
|
4761
|
+
height: window.innerHeight
|
|
4762
|
+
});
|
|
4763
|
+
React.useEffect(() => {
|
|
4764
|
+
const handleResize = () => setSize({
|
|
4765
|
+
width: window.innerWidth,
|
|
4766
|
+
height: window.innerHeight
|
|
4767
|
+
});
|
|
4768
|
+
window.addEventListener('resize', handleResize);
|
|
4769
|
+
return () => window.removeEventListener('resize', handleResize);
|
|
4770
|
+
}, []);
|
|
4771
|
+
return /*#__PURE__*/React__default.createElement(WindowSizeContext.Provider, {
|
|
4772
|
+
value: size
|
|
4773
|
+
}, children);
|
|
4774
|
+
};
|
|
4775
|
+
|
|
4693
4776
|
function useActive() {
|
|
4694
4777
|
const [active, setActive] = React.useState(false);
|
|
4695
4778
|
const ref = React.useRef(null);
|
|
@@ -5229,11 +5312,6 @@ const useScrollDirection = function (threshold) {
|
|
|
5229
5312
|
return scrollDirection;
|
|
5230
5313
|
};
|
|
5231
5314
|
|
|
5232
|
-
const WindowSizeContext = /*#__PURE__*/React.createContext({
|
|
5233
|
-
width: 0,
|
|
5234
|
-
height: 0
|
|
5235
|
-
});
|
|
5236
|
-
|
|
5237
5315
|
const useWindowSize = () => React.useContext(WindowSizeContext);
|
|
5238
5316
|
|
|
5239
5317
|
function useInView(options) {
|
|
@@ -5870,6 +5948,8 @@ exports.UtilityClassManager = UtilityClassManager;
|
|
|
5870
5948
|
exports.Vertical = Vertical;
|
|
5871
5949
|
exports.VerticalResponsive = VerticalResponsive;
|
|
5872
5950
|
exports.View = View;
|
|
5951
|
+
exports.WindowSizeContext = WindowSizeContext;
|
|
5952
|
+
exports.WindowSizeProvider = WindowSizeProvider;
|
|
5873
5953
|
exports.animateOnView = animateOnView;
|
|
5874
5954
|
exports.blurInOnView = blurInOnView;
|
|
5875
5955
|
exports.blurOutOnView = blurOutOnView;
|
|
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|