jy-headless 0.0.24 → 0.0.27
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/components/icons/DownArrowIcon.d.ts +4 -0
- package/dist/components/icons/UpArrowIcon.d.ts +4 -0
- package/dist/components/input/Input.d.ts +2 -2
- package/dist/components/input/NumberInput.d.ts +11 -0
- package/dist/components/modal/Modal.d.ts +1 -1
- package/dist/components/tabs/Tab.d.ts +11 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.esm.js +72 -6
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +72 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { CSSProperties, InputHTMLAttributes, ReactNode } from 'react';
|
|
2
|
-
interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
3
|
-
|
|
2
|
+
export interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
3
|
+
showLimit?: boolean;
|
|
4
4
|
containerStyle?: CSSProperties;
|
|
5
5
|
containerClassName?: string;
|
|
6
6
|
prefixElement?: ReactNode;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import { InputProps } from './Input';
|
|
3
|
+
interface NumberInputProps extends InputProps {
|
|
4
|
+
increaseElement?: ReactNode;
|
|
5
|
+
decreaseElement?: ReactNode;
|
|
6
|
+
min?: number;
|
|
7
|
+
max?: number;
|
|
8
|
+
step?: number;
|
|
9
|
+
}
|
|
10
|
+
declare const NumberInput: React.FC<NumberInputProps>;
|
|
11
|
+
export default NumberInput;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import Button from './components/button/Button';
|
|
2
2
|
import Input from './components/input/Input';
|
|
3
|
+
import NumberInput from './components/input/NumberInput';
|
|
3
4
|
import DesktopKeyboardInput from './components/input/DesktopKeyboardInput';
|
|
4
5
|
import Spinner from './components/spinner/Spinner';
|
|
5
6
|
import RadioInput from './components/radio/RadioInput';
|
|
6
7
|
import RadioGroup from './components/radio/RadioGroup';
|
|
7
8
|
import Modal from './components/modal/Modal';
|
|
8
9
|
import { CallIcon, CloseIcon, HomeIcon, SearchIcon } from './components/icons';
|
|
9
|
-
export { Button, Input, DesktopKeyboardInput, Spinner, CallIcon, CloseIcon, HomeIcon, SearchIcon, RadioInput, RadioGroup, Modal, };
|
|
10
|
+
export { Button, Input, DesktopKeyboardInput, Spinner, CallIcon, CloseIcon, HomeIcon, SearchIcon, RadioInput, RadioGroup, Modal, NumberInput, };
|
package/dist/index.esm.js
CHANGED
|
@@ -54,7 +54,7 @@ const Spinner = ({ color = 'black', size = '1em', spinTime = '2s' }) => {
|
|
|
54
54
|
React.createElement("title", null, "ic_fluent_spinner_ios_20_filled"),
|
|
55
55
|
React.createElement("desc", null, "Created with Sketch."),
|
|
56
56
|
React.createElement("g", { id: "\uD83D\uDD0D-System-Icons", stroke: "none", strokeWidth: "1", fill: "none", fillRule: "evenodd" },
|
|
57
|
-
React.createElement("g", { id: "ic_fluent_spinner_ios_20_filled", fill:
|
|
57
|
+
React.createElement("g", { id: "ic_fluent_spinner_ios_20_filled", fill: color, fillRule: "nonzero" },
|
|
58
58
|
React.createElement("path", { d: "M10,3.5 C6.41015,3.5 3.5,6.41015 3.5,10 C3.5,10.4142 3.16421,10.75 2.75,10.75 C2.33579,10.75 2,10.4142 2,10 C2,5.58172 5.58172,2 10,2 C14.4183,2 18,5.58172 18,10 C18,14.4183 14.4183,18 10,18 C9.58579,18 9.25,17.6642 9.25,17.25 C9.25,16.8358 9.58579,16.5 10,16.5 C13.5899,16.5 16.5,13.5899 16.5,10 C16.5,6.41015 13.5899,3.5 10,3.5 Z", id: "\uD83C\uDFA8-Color" })))))));
|
|
59
59
|
};
|
|
60
60
|
|
|
@@ -67,13 +67,79 @@ const Button = (_a) => {
|
|
|
67
67
|
};
|
|
68
68
|
|
|
69
69
|
const Input = (_a) => {
|
|
70
|
-
var
|
|
70
|
+
var _b;
|
|
71
|
+
var { prefixElement, suffixElement, className, style, containerStyle, containerClassName, showError = false, error, maxLength, showLimit = false } = _a, restProps = __rest(_a, ["prefixElement", "suffixElement", "className", "style", "containerStyle", "containerClassName", "showError", "error", "maxLength", "showLimit"]);
|
|
72
|
+
const [inputValue, setInputValue] = useState(restProps.value);
|
|
73
|
+
const onChange = (e) => {
|
|
74
|
+
setInputValue(e.target.value);
|
|
75
|
+
restProps.onChange(e);
|
|
76
|
+
};
|
|
71
77
|
return (React.createElement("span", { className: containerClassName, style: Object.assign({ position: 'relative', display: 'inline-flex', alignItems: 'center' }, containerStyle) },
|
|
72
78
|
prefixElement,
|
|
73
|
-
React.createElement("input", Object.assign({}, restProps, { className: className, style: Object.assign({ all: 'unset' }, style) })),
|
|
79
|
+
React.createElement("input", Object.assign({}, restProps, { value: inputValue, onChange: onChange, maxLength: maxLength, className: className, style: Object.assign({ all: 'unset' }, style) })),
|
|
80
|
+
showLimit && maxLength && (React.createElement("span", { className: 'max-length' }, (_b = (inputValue !== null && inputValue !== undefined ? inputValue : '').toString().length) !== null && _b !== undefined ? _b : 0,
|
|
81
|
+
"/",
|
|
82
|
+
maxLength)),
|
|
74
83
|
suffixElement,
|
|
75
84
|
showError &&
|
|
76
|
-
(typeof error === 'string' ? (React.createElement("span", { style: { position: 'absolute', top: '100%', left: 0 } }, error)) : (error))));
|
|
85
|
+
(typeof error === 'string' ? (React.createElement("span", { className: 'error-message', style: { position: 'absolute', top: '100%', left: 0 } }, error)) : (error))));
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const UpArrowIcon = ({ color = '#000', size = '1em', bgColor = 'transparent', fill = 'none', }) => {
|
|
89
|
+
return (React.createElement("svg", { width: size, height: size, fill: color, style: { backgroundColor: bgColor }, viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" },
|
|
90
|
+
React.createElement("g", { id: "SVGRepo_bgCarrier", strokeWidth: "0" }),
|
|
91
|
+
React.createElement("g", { id: "SVGRepo_tracerCarrier", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
92
|
+
React.createElement("g", { id: "SVGRepo_iconCarrier" },
|
|
93
|
+
React.createElement("path", { d: "M3 19h18a1.002 1.002 0 0 0 .823-1.569l-9-13c-.373-.539-1.271-.539-1.645 0l-9 13A.999.999 0 0 0 3 19z" }))));
|
|
94
|
+
};
|
|
95
|
+
// COLLECTION: Boxicons Filled Icons
|
|
96
|
+
// LICENSE: CC Attribution License
|
|
97
|
+
// AUTHOR: boxicons
|
|
98
|
+
// https://www.svgrepo.com/svg/334957/up-arrow
|
|
99
|
+
|
|
100
|
+
const DownArrowIcon = ({ color = '#000', size = '1em', bgColor = 'transparent', fill = 'none', }) => {
|
|
101
|
+
return (React.createElement("svg", { width: size, height: size, fill: color, style: { backgroundColor: bgColor }, viewBox: "0 0 24 24", transform: "matrix(1, 0, 0, -1, 0, 0)", xmlns: "http://www.w3.org/2000/svg" },
|
|
102
|
+
React.createElement("g", { id: "SVGRepo_bgCarrier", strokeWidth: "0" }),
|
|
103
|
+
React.createElement("g", { id: "SVGRepo_tracerCarrier", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
104
|
+
React.createElement("g", { id: "SVGRepo_iconCarrier" },
|
|
105
|
+
React.createElement("path", { d: "M3 19h18a1.002 1.002 0 0 0 .823-1.569l-9-13c-.373-.539-1.271-.539-1.645 0l-9 13A.999.999 0 0 0 3 19z" }))));
|
|
106
|
+
};
|
|
107
|
+
// COLLECTION: Boxicons Filled Icons
|
|
108
|
+
// LICENSE: CC Attribution License
|
|
109
|
+
// AUTHOR: boxicons
|
|
110
|
+
// https://www.svgrepo.com/svg/334957/up-arrow
|
|
111
|
+
|
|
112
|
+
const NumberInput = (_a) => {
|
|
113
|
+
var { increaseElement = React.createElement(UpArrowIcon, null), decreaseElement = React.createElement(DownArrowIcon, null), step = 1, min = -Infinity, max = Infinity, value, onChange } = _a, restProps = __rest(_a, ["increaseElement", "decreaseElement", "step", "min", "max", "value", "onChange"]);
|
|
114
|
+
const onNumberInput = (e) => {
|
|
115
|
+
const newValue = Number(e.target.value);
|
|
116
|
+
if (isNaN(newValue)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
onChange(Object.assign(Object.assign({}, e), { target: Object.assign(Object.assign({}, e.target), { value: newValue.toString() }) }));
|
|
120
|
+
};
|
|
121
|
+
const onNumberChange = (dir) => {
|
|
122
|
+
if (isNaN(value)) {
|
|
123
|
+
onChange(null);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
let newValue = (value !== null && value !== undefined ? value : 0) + dir * (step || 1);
|
|
127
|
+
if (newValue > max)
|
|
128
|
+
newValue = max;
|
|
129
|
+
if (newValue < min)
|
|
130
|
+
newValue = min;
|
|
131
|
+
const event = {
|
|
132
|
+
target: Object.assign(Object.assign({}, {}), { value: newValue.toString() }),
|
|
133
|
+
};
|
|
134
|
+
onChange(event);
|
|
135
|
+
};
|
|
136
|
+
const onIncrease = () => {
|
|
137
|
+
onNumberChange(1);
|
|
138
|
+
};
|
|
139
|
+
const onDecrease = () => {
|
|
140
|
+
onNumberChange(-1);
|
|
141
|
+
};
|
|
142
|
+
return (React.createElement(Input, Object.assign({}, restProps, { value: value, onChange: onNumberInput, prefixElement: React.cloneElement(decreaseElement, { onClick: onDecrease }), suffixElement: React.cloneElement(increaseElement, { onClick: onIncrease }) })));
|
|
77
143
|
};
|
|
78
144
|
|
|
79
145
|
const functionRow = [
|
|
@@ -381,7 +447,7 @@ const ModalContext = createContext({
|
|
|
381
447
|
setIsShow: (value) => { },
|
|
382
448
|
});
|
|
383
449
|
|
|
384
|
-
const Modal = ({ opener, children, targetSelector = 'root', }) => {
|
|
450
|
+
const Modal = ({ opener, children, targetSelector = '#root', }) => {
|
|
385
451
|
const [isShow, setIsShow] = useState(false);
|
|
386
452
|
const onHandleShow = () => {
|
|
387
453
|
setIsShow(true);
|
|
@@ -461,5 +527,5 @@ const SearchIcon = ({ color = '#000', size = '1em', bgColor = 'transparent', fil
|
|
|
461
527
|
// AUTHOR: Ankush Syal
|
|
462
528
|
// https://www.svgrepo.com/svg/520583/call
|
|
463
529
|
|
|
464
|
-
export { Button, CallIcon, CloseIcon, DesktopKeyboardInput, HomeIcon, Input, Modal, RadioGroup, RadioInput, SearchIcon, Spinner };
|
|
530
|
+
export { Button, CallIcon, CloseIcon, DesktopKeyboardInput, HomeIcon, Input, Modal, NumberInput, RadioGroup, RadioInput, SearchIcon, Spinner };
|
|
465
531
|
//# sourceMappingURL=index.esm.js.map
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/index.js
CHANGED
|
@@ -56,7 +56,7 @@ const Spinner = ({ color = 'black', size = '1em', spinTime = '2s' }) => {
|
|
|
56
56
|
React.createElement("title", null, "ic_fluent_spinner_ios_20_filled"),
|
|
57
57
|
React.createElement("desc", null, "Created with Sketch."),
|
|
58
58
|
React.createElement("g", { id: "\uD83D\uDD0D-System-Icons", stroke: "none", strokeWidth: "1", fill: "none", fillRule: "evenodd" },
|
|
59
|
-
React.createElement("g", { id: "ic_fluent_spinner_ios_20_filled", fill:
|
|
59
|
+
React.createElement("g", { id: "ic_fluent_spinner_ios_20_filled", fill: color, fillRule: "nonzero" },
|
|
60
60
|
React.createElement("path", { d: "M10,3.5 C6.41015,3.5 3.5,6.41015 3.5,10 C3.5,10.4142 3.16421,10.75 2.75,10.75 C2.33579,10.75 2,10.4142 2,10 C2,5.58172 5.58172,2 10,2 C14.4183,2 18,5.58172 18,10 C18,14.4183 14.4183,18 10,18 C9.58579,18 9.25,17.6642 9.25,17.25 C9.25,16.8358 9.58579,16.5 10,16.5 C13.5899,16.5 16.5,13.5899 16.5,10 C16.5,6.41015 13.5899,3.5 10,3.5 Z", id: "\uD83C\uDFA8-Color" })))))));
|
|
61
61
|
};
|
|
62
62
|
|
|
@@ -69,13 +69,79 @@ const Button = (_a) => {
|
|
|
69
69
|
};
|
|
70
70
|
|
|
71
71
|
const Input = (_a) => {
|
|
72
|
-
var
|
|
72
|
+
var _b;
|
|
73
|
+
var { prefixElement, suffixElement, className, style, containerStyle, containerClassName, showError = false, error, maxLength, showLimit = false } = _a, restProps = __rest(_a, ["prefixElement", "suffixElement", "className", "style", "containerStyle", "containerClassName", "showError", "error", "maxLength", "showLimit"]);
|
|
74
|
+
const [inputValue, setInputValue] = React.useState(restProps.value);
|
|
75
|
+
const onChange = (e) => {
|
|
76
|
+
setInputValue(e.target.value);
|
|
77
|
+
restProps.onChange(e);
|
|
78
|
+
};
|
|
73
79
|
return (React.createElement("span", { className: containerClassName, style: Object.assign({ position: 'relative', display: 'inline-flex', alignItems: 'center' }, containerStyle) },
|
|
74
80
|
prefixElement,
|
|
75
|
-
React.createElement("input", Object.assign({}, restProps, { className: className, style: Object.assign({ all: 'unset' }, style) })),
|
|
81
|
+
React.createElement("input", Object.assign({}, restProps, { value: inputValue, onChange: onChange, maxLength: maxLength, className: className, style: Object.assign({ all: 'unset' }, style) })),
|
|
82
|
+
showLimit && maxLength && (React.createElement("span", { className: 'max-length' }, (_b = (inputValue !== null && inputValue !== undefined ? inputValue : '').toString().length) !== null && _b !== undefined ? _b : 0,
|
|
83
|
+
"/",
|
|
84
|
+
maxLength)),
|
|
76
85
|
suffixElement,
|
|
77
86
|
showError &&
|
|
78
|
-
(typeof error === 'string' ? (React.createElement("span", { style: { position: 'absolute', top: '100%', left: 0 } }, error)) : (error))));
|
|
87
|
+
(typeof error === 'string' ? (React.createElement("span", { className: 'error-message', style: { position: 'absolute', top: '100%', left: 0 } }, error)) : (error))));
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const UpArrowIcon = ({ color = '#000', size = '1em', bgColor = 'transparent', fill = 'none', }) => {
|
|
91
|
+
return (React.createElement("svg", { width: size, height: size, fill: color, style: { backgroundColor: bgColor }, viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" },
|
|
92
|
+
React.createElement("g", { id: "SVGRepo_bgCarrier", strokeWidth: "0" }),
|
|
93
|
+
React.createElement("g", { id: "SVGRepo_tracerCarrier", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
94
|
+
React.createElement("g", { id: "SVGRepo_iconCarrier" },
|
|
95
|
+
React.createElement("path", { d: "M3 19h18a1.002 1.002 0 0 0 .823-1.569l-9-13c-.373-.539-1.271-.539-1.645 0l-9 13A.999.999 0 0 0 3 19z" }))));
|
|
96
|
+
};
|
|
97
|
+
// COLLECTION: Boxicons Filled Icons
|
|
98
|
+
// LICENSE: CC Attribution License
|
|
99
|
+
// AUTHOR: boxicons
|
|
100
|
+
// https://www.svgrepo.com/svg/334957/up-arrow
|
|
101
|
+
|
|
102
|
+
const DownArrowIcon = ({ color = '#000', size = '1em', bgColor = 'transparent', fill = 'none', }) => {
|
|
103
|
+
return (React.createElement("svg", { width: size, height: size, fill: color, style: { backgroundColor: bgColor }, viewBox: "0 0 24 24", transform: "matrix(1, 0, 0, -1, 0, 0)", xmlns: "http://www.w3.org/2000/svg" },
|
|
104
|
+
React.createElement("g", { id: "SVGRepo_bgCarrier", strokeWidth: "0" }),
|
|
105
|
+
React.createElement("g", { id: "SVGRepo_tracerCarrier", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
106
|
+
React.createElement("g", { id: "SVGRepo_iconCarrier" },
|
|
107
|
+
React.createElement("path", { d: "M3 19h18a1.002 1.002 0 0 0 .823-1.569l-9-13c-.373-.539-1.271-.539-1.645 0l-9 13A.999.999 0 0 0 3 19z" }))));
|
|
108
|
+
};
|
|
109
|
+
// COLLECTION: Boxicons Filled Icons
|
|
110
|
+
// LICENSE: CC Attribution License
|
|
111
|
+
// AUTHOR: boxicons
|
|
112
|
+
// https://www.svgrepo.com/svg/334957/up-arrow
|
|
113
|
+
|
|
114
|
+
const NumberInput = (_a) => {
|
|
115
|
+
var { increaseElement = React.createElement(UpArrowIcon, null), decreaseElement = React.createElement(DownArrowIcon, null), step = 1, min = -Infinity, max = Infinity, value, onChange } = _a, restProps = __rest(_a, ["increaseElement", "decreaseElement", "step", "min", "max", "value", "onChange"]);
|
|
116
|
+
const onNumberInput = (e) => {
|
|
117
|
+
const newValue = Number(e.target.value);
|
|
118
|
+
if (isNaN(newValue)) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
onChange(Object.assign(Object.assign({}, e), { target: Object.assign(Object.assign({}, e.target), { value: newValue.toString() }) }));
|
|
122
|
+
};
|
|
123
|
+
const onNumberChange = (dir) => {
|
|
124
|
+
if (isNaN(value)) {
|
|
125
|
+
onChange(null);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
let newValue = (value !== null && value !== undefined ? value : 0) + dir * (step || 1);
|
|
129
|
+
if (newValue > max)
|
|
130
|
+
newValue = max;
|
|
131
|
+
if (newValue < min)
|
|
132
|
+
newValue = min;
|
|
133
|
+
const event = {
|
|
134
|
+
target: Object.assign(Object.assign({}, {}), { value: newValue.toString() }),
|
|
135
|
+
};
|
|
136
|
+
onChange(event);
|
|
137
|
+
};
|
|
138
|
+
const onIncrease = () => {
|
|
139
|
+
onNumberChange(1);
|
|
140
|
+
};
|
|
141
|
+
const onDecrease = () => {
|
|
142
|
+
onNumberChange(-1);
|
|
143
|
+
};
|
|
144
|
+
return (React.createElement(Input, Object.assign({}, restProps, { value: value, onChange: onNumberInput, prefixElement: React.cloneElement(decreaseElement, { onClick: onDecrease }), suffixElement: React.cloneElement(increaseElement, { onClick: onIncrease }) })));
|
|
79
145
|
};
|
|
80
146
|
|
|
81
147
|
const functionRow = [
|
|
@@ -383,7 +449,7 @@ const ModalContext = React.createContext({
|
|
|
383
449
|
setIsShow: (value) => { },
|
|
384
450
|
});
|
|
385
451
|
|
|
386
|
-
const Modal = ({ opener, children, targetSelector = 'root', }) => {
|
|
452
|
+
const Modal = ({ opener, children, targetSelector = '#root', }) => {
|
|
387
453
|
const [isShow, setIsShow] = React.useState(false);
|
|
388
454
|
const onHandleShow = () => {
|
|
389
455
|
setIsShow(true);
|
|
@@ -470,6 +536,7 @@ exports.DesktopKeyboardInput = DesktopKeyboardInput;
|
|
|
470
536
|
exports.HomeIcon = HomeIcon;
|
|
471
537
|
exports.Input = Input;
|
|
472
538
|
exports.Modal = Modal;
|
|
539
|
+
exports.NumberInput = NumberInput;
|
|
473
540
|
exports.RadioGroup = RadioGroup;
|
|
474
541
|
exports.RadioInput = RadioInput;
|
|
475
542
|
exports.SearchIcon = SearchIcon;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|