sort,\n openRelatedTo: '.aio-input-table'\n }}\n key='sortbutton' caret={false} type='select' options={sortOptions} className='aio-input-table-toolbar-icon'\n text={}\n onSwap={(from, to, swap) => this.setSorts(swap(sorts, from, to))}\n />\n )\n }\n}\nclass Layout extends Component {\n static contextType = AIContext;\n constructor(props) {\n super(props);\n this.dom = createRef()\n }\n getClassName(label, disabled) {\n let { type, getProp, getOptionProp, datauniqid } = this.context;\n let { option } = this.props;\n let cls;\n let className;\n if (option !== undefined) {\n cls = `aio-input-option aio-input-${type}-option`\n if (getProp('multiple')) { cls += ` aio-input-${type}-multiple-option` }\n className = getOptionProp(option, 'className')\n }\n else {\n cls = `aio-input aio-input-${type}`;\n if(type === 'slider'){\n let direction = getProp('direction','right')\n if(direction === 'left' || direction === 'right'){cls += ' aio-input-slider-horizontal'}\n else {cls += ' aio-input-slider-vertical'}\n }\n if (type === 'file' && disabled) { cls += ' disabled' }\n className = getProp('className');\n let rtl = getProp('rtl');\n if (rtl) { cls += ' aio-input-rtl' }\n\n }\n cls += ' ' + datauniqid;\n cls += label ? ' has-label' : '';\n cls += className ? ' ' + className : '';\n return cls;\n }\n getProps() {\n let { onSwap, dragStart, dragOver, drop, click, optionClick } = this.context;\n let { option, realIndex, renderIndex } = this.props;\n let { label, disabled, style, center, loading, attrs } = this.properties;\n let props = {\n ...attrs,\n className: this.getClassName(label, disabled),\n onClick: loading ? undefined : (option === undefined ? (e) => click(e, this.dom) : () => optionClick(option)),\n ref: this.dom, disabled, style: { justifyContent: center ? 'center' : undefined, ...style }, 'data-label': label\n }\n if (option && onSwap) {\n props.datarealindex = realIndex;\n props.datarenderindex = renderIndex;\n props.onDragStart = dragStart;\n props.onDragOver = dragOver;\n props.onDrop = drop;\n props.draggable = true;\n }\n return props;\n }\n getDefaultChecked() {\n let { type, getProp } = this.context;\n if (type === 'checkbox') { return !!getProp('value') }\n }\n getProperties() {\n let { option, text } = this.props;\n if (!option) {\n let { getProp } = this.context;\n let properties = {\n label: getProp('label'),\n tabIndex: getProp('tabIndex'),\n attrs: getProp('attrs', {}),\n caret: getProp('caret'),\n className: getProp('className'),\n disabled: getProp('disabled'),\n style: getProp('style'),\n text: text !== undefined ? text : getProp('text'),\n checkIcon: getProp('checkIcon', []),\n checked: getProp('checked', this.getDefaultChecked()),\n before: getProp('before'),\n after: getProp('after'),\n subtext: getProp('subtext'),\n onClick: getProp('onClick'),\n center: getProp('center'),\n loading: getProp('loading')\n }\n return properties\n }\n return option\n }\n getItemClassName(key){\n let { type } = this.context;\n let { option } = this.props;\n return `aio-input-${key} aio-input-${option ? `${type}-option` : type}-${key}`\n }\n render() {\n let { type } = this.context;\n let { option } = this.props;\n this.properties = this.getProperties()\n let { checked, checkIcon, before, text, subtext, after, caret, center, loading } = this.properties;\n let content = (\n <>\n \n {before !== undefined && {before}
}\n \n {text !== undefined &&
{text}
}\n {subtext !== undefined &&
{subtext}
}\n
\n {after !== undefined && {after}
}\n {loading && {loading === true ? : loading}
}\n {caret && {caret === true ? : caret}
}\n >\n )\n let props = this.getProps();\n if (type === 'file') { return (<>>) }\n return ({content}
)\n }\n}\nclass CheckIcon extends Component {\n static contextType = AIContext;\n render() {\n let { gap } = this.context;\n let { checked, checkIcon = [] } = this.props;\n if (checked === undefined) { return null }\n if (typeof checkIcon === 'function') {\n return (\n <>\n {checkIcon(checked)}\n \n >\n )\n }\n let [outerSize, innerSize, stroke, outerColor = 'dodgerblue', innerColor = outerColor, round = false] = checkIcon;\n return (\n <>\n \n \n >\n );\n }\n}\nexport class InputFile extends Component {\n static contextType = AIContext;\n change(e) {\n let { value = [], onChange = () => { },multiple } = this.context;\n let Files = e.target.files;\n let result = multiple?[...value]:[];\n let names = result.map(({ name }) => name);\n for (let i = 0; i < Files.length; i++) {\n let file = Files[i];\n if (names.indexOf(file.name) !== -1) { continue }\n result.push({ name: file.name, size: file.size, file })\n }\n onChange(result)\n }\n render() {\n let { disabled, multiple } = this.context;\n let props = { disabled, type: 'file', style: { display: 'none' }, multiple, onChange: (e) => this.change(e) }\n return \n }\n}\nexport class Files extends Component {\n static contextType = AIContext;\n render() {\n let { value = [], rtl } = this.context;\n if (!value.length) { return null }\n return (\n {value.map((o, i) => )}
\n )\n }\n}\nclass File extends Component {\n static contextType = AIContext;\n getFile(filename, fileSize) {\n let nameLength = 20;\n try {\n let minName, sizeString;\n let lastDotIndex = filename.lastIndexOf('.');\n let name = filename.slice(0, lastDotIndex);\n let format = filename.slice(lastDotIndex + 1, filename.length);\n if (name.length > nameLength) {\n minName = name.slice(0, parseInt(nameLength / 2)) + '...' + name.slice(name.length - parseInt(nameLength / 2), name.length) + '.' + format;\n }\n else { minName = filename; }\n let size = fileSize;\n let gb = size / (1024 * 1024 * 1024), mb = size / (1024 * 1024), kb = size / 1024;\n if (gb >= 1) { sizeString = gb.toFixed(2) + ' GB'; }\n else if (mb >= 1) { sizeString = mb.toFixed(2) + ' MB'; }\n else if (kb >= 1) { sizeString = kb.toFixed(2) + ' KB'; }\n else { sizeString = size + ' byte' }\n return { minName, sizeString }\n }\n catch {\n return { minName: 'untitle', sizeString: '0' }\n }\n }\n remove(index) {\n let { onChange = () => { }, value = [] } = this.context;\n let newValue = [];\n for (let i = 0; i < value.length; i++) {\n if (i === index) { continue }\n newValue.push(value[i])\n }\n onChange(newValue);\n }\n render() {\n let { name, url, size, index } = this.props;\n let { minName, sizeString } = this.getFile(name, size);\n return (\n \n
\n \n
\n
DownloadUrl(url, name)}>\n {`${minName} (${sizeString})`}\n
\n
this.remove(index)}>\n \n
\n
\n )\n }\n}\nconst DPContext = createContext();\nclass DatePicker extends Component {\n static contextType = AIContext;\n render() {\n let { getProp } = this.context;\n let props = {\n unit: getProp('unit', 'day'), calendarType: getProp('calendarType', 'gregorian'),\n disabled: getProp('disabled', false), value: getProp('value'),\n onChange: getProp('onChange', () => { }), onClear: getProp('onClear'),\n startYear: getProp('startYear'), endYear: getProp('endYear'),\n theme: getProp('theme'), size: getProp('size'), dateAttrs: getProp('dateAttrs')\n }\n return ()\n }\n}\nclass Calendar extends Component {\n constructor(props) {\n super(props);\n let { calendarType = 'gregorian', value } = props;\n let { getToday, convertToArray, getMonths, getWeekDay } = AIODate();\n let today = getToday({ calendarType });\n if (!value) { value = today }\n let [year, month, day] = convertToArray({ date: value })\n let months = getMonths({ calendarType });\n this.state = {\n activeDate: { year, month, day }, years: this.getYears(), today,\n todayWeekDay: getWeekDay({ date: today }).weekDay,\n months, thisMonthString: months[today[1] - 1],\n }\n }\n translate(text) {\n let { unit = 'day', calendarType = 'gregorian', translate = (text) => text } = this.props;\n if (text === 'Today') {\n if (unit === 'month') { text = 'This Month' }\n else if (unit === 'hour') { text = 'This Hour' }\n }\n let obj = { 'Clear': 'حذف', 'This Hour': 'ساعت کنونی', 'Today': 'امروز', 'This Month': 'ماه جاری', }\n let res = text;\n if (calendarType === 'jalali' && obj[text]) { res = obj[text] }\n return translate(res)\n }\n changeActiveDate(obj) {\n let newActiveDate;\n if (obj === 'today') {\n let { today } = this.state, { unit = 'day' } = this.props;\n let [year, month, day] = today;\n newActiveDate = { year, month, day: unit === 'month' ? 1 : day };\n }\n else { newActiveDate = { ...this.state.activeDate, ...obj } }\n this.setState({ activeDate: newActiveDate })\n }\n getYears() {\n let start, end;\n let { calendarType, startYear, endYear } = this.props;\n let today = AIODate().getToday({ calendarType });\n if (typeof startYear === 'string' && startYear.indexOf('-') === 0) {\n start = today[0] - parseInt(startYear.slice(1, startYear.length));\n }\n else { start = parseInt(startYear); }\n if (typeof endYear === 'string' && endYear.indexOf('+') === 0) {\n end = today[0] + parseInt(endYear.slice(1, endYear.length));\n }\n else { end = parseInt(endYear); }\n let years = [];\n for (var i = start; i <= end; i++) { years.push(i); }\n return years;\n }\n getPopupStyle() {\n var { size, disabled, theme = [] } = this.props;\n return {\n width: size, fontSize: size / 17, background: theme[1], color: theme[0], stroke: theme[0],\n cursor: disabled === true ? 'not-allowed' : undefined,\n };\n }\n getContext() {\n return {\n ...this.props, ...this.state,\n changeActiveDate: this.changeActiveDate.bind(this),\n translate: this.translate.bind(this),\n SetState: (obj) => this.setState(obj),\n onChange: ({ year, month, day, hour }) => {\n let { onChange = () => { }, calendarType, unit, value } = this.props;\n let { months } = this.state;\n let dateArray = [year, month, day, hour];\n let jalaliDateArray = calendarType === 'gregorian' ? AIODate().toJalali({ date: dateArray }) : dateArray;\n let gregorianDateArray = calendarType === 'jalali' ? AIODate().toGregorian({ date: dateArray }) : dateArray;\n let { weekDay, index: weekDayIndex } = unit === 'month' ? { weekDay: null, index: null } : AIODate().getWeekDay({ date: dateArray })\n let get2digit = (v) => {\n if (v === undefined) { return }\n v = v.toString();\n return v.length === 1 ? `0${v}` : v\n }\n let dateString;\n let splitter = typeof value === 'string' ? AIODate().getSplitter(value) : '/';\n if (unit === 'month') { dateString = `${year}${splitter}${get2digit(month)}` }\n else if (unit === 'day') { dateString = `${year}${splitter}${get2digit(month)}${splitter}${get2digit(day)}` }\n else if (unit === 'hour') { dateString = `${year}${splitter}${get2digit(month)}${splitter}${get2digit(day)}${splitter}${get2digit(hour)}` }\n let monthString = months[month - 1];\n let jalaliMonthString = calendarType === 'gregorian' ? AIODate().getMonths({ calendarType: 'jalali' })[month - 1] : monthString;\n let gregorianMonthString = calendarType === 'jalali' ? AIODate().getMonths({ calendarType: 'gregorian' })[month - 1] : monthString;\n let props = {\n months, jalaliDateArray, gregorianDateArray, dateArray, weekDay, weekDayIndex, dateString,\n year, month, day, hour, monthString, jalaliMonthString, gregorianMonthString,\n }\n onChange(dateString, props)\n }\n }\n }\n render() {\n return (\n \n \n \n );\n }\n}\nCalendar.defaultProps = {\n size: 180, calendarType: 'gregorian', disabled: false,\n startYear: '-10', endYear: '+20', unit: 'day',\n setDisabled: () => false\n}\nclass DPToday extends Component {\n static contextType = DPContext;\n render() {\n let { calendarType = 'gregorian', size, unit = 'day', theme = [], translate, today, todayWeekDay, thisMonthString } = this.context;\n return (\n \n
{translate('Today')}
\n {\n (unit === 'day' || unit === 'hour') &&\n <>\n
{calendarType === 'gregorian' ? todayWeekDay.slice(0, 3) : todayWeekDay}
\n
{today[2]}
\n
{calendarType === 'gregorian' ? thisMonthString.slice(0, 3) : thisMonthString}
\n >\n }\n {unit === 'month' &&
{calendarType === 'gregorian' ? thisMonthString.slice(0, 3) : thisMonthString}
}\n
{today[0]}
\n {unit === 'hour' &&
{today[3] + ':00'}
}\n
\n )\n }\n}\nclass DPFooter extends Component {\n static contextType = DPContext;\n render() {\n let { onClear, disabled, size, changeActiveDate, translate } = this.context;\n if (disabled) { return null }\n let buttonStyle = { padding: `${size / 20}px 0` };\n return (\n \n {onClear && }\n \n
\n )\n }\n}\nclass DPBody extends Component {\n static contextType = DPContext;\n getStyle() {\n let { size, calendarType = 'gregorian', unit = 'day' } = this.context;\n var columnCount = { hour: 4, day: 7, month: 3 }[unit];\n var rowCount = { hour: 6, day: 7, month: 4 }[unit];\n var padding = size / 18, fontSize = size / 15,\n a = (size - padding * 2) / columnCount;\n var rowHeight = { hour: size / 7, day: a, month: size / 6, year: size / 7 }[unit];\n var gridTemplateColumns = '', gridTemplateRows = '';\n for (let i = 1; i <= columnCount; i++) {\n gridTemplateColumns += a + 'px' + (i !== columnCount ? ' ' : '')\n }\n for (let i = 1; i <= rowCount; i++) {\n gridTemplateRows += (rowHeight) + 'px' + (i !== rowCount ? ' ' : '')\n }\n let direction = calendarType === 'gregorian' ? 'ltr' : 'rtl';\n return { gridTemplateColumns, gridTemplateRows, direction, padding, fontSize }\n }\n render() {\n let { unit = 'day', activeDate } = this.context;\n return (\n \n {unit === 'hour' && new Array(24).fill(0).map((o, i) => )}\n {unit === 'day' && }\n {unit === 'month' && new Array(12).fill(0).map((o, i) => )}\n
\n )\n }\n}\nclass DPBodyDay extends Component {\n static contextType = DPContext;\n render() {\n let { calendarType = 'gregorian', theme = [], activeDate } = this.context;\n let firstDayWeekDayIndex = AIODate().getWeekDay({ date: [activeDate.year, activeDate.month, 1] }).index;\n var daysLength = AIODate().getMonthDaysLength({ date: [activeDate.year, activeDate.month] });\n let weekDays = AIODate().getWeekDays({ calendarType });\n return (<>\n {weekDays.map((weekDay, i) => )}\n {new Array(firstDayWeekDayIndex).fill(0).map((o, i) => )}\n {new Array(daysLength).fill(0).map((o, i) => )}\n {new Array(42 - (firstDayWeekDayIndex + daysLength)).fill(0).map((o, i) => )}\n >)\n }\n}\nclass DPCell_Weekday extends Component {\n static contextType = DPContext;\n render() {\n let { calendarType = 'gregorian', theme = [], translate } = this.context;\n let { weekDay } = this.props;\n return (\n \n {translate(weekDay.slice(0, calendarType === 'gregorian' ? 2 : 1))}\n
\n )\n }\n}\nclass DPCell extends Component {\n static contextType = DPContext;\n getClassName(isActive, isToday, isDisabled, className) {\n var str = 'aio-input-datepicker-cell';\n if (isDisabled) { str += ' aio-input-datepicker-disabled' }\n if (isActive) { str += ' aio-input-datepicker-active'; }\n if (isToday) { str += ' today'; }\n if (className) { str += ' className'; }\n return str;\n }\n render() {\n let { unit = 'day', theme = [], onChange, dateAttrs, disabled, calendarType = 'gregorian', value, translate } = this.context;\n let { dateArray } = this.props;\n let { isEqual, isMatch, getMonths, getToday } = AIODate();\n let isActive = !value?false:AIODate().isEqual(dateArray, value);\n let isToday = isEqual(dateArray, getToday({ calendarType }))\n let isDisabled = typeof disabled === 'boolean' ? disabled : isMatch({ date: dateArray, matchers: disabled })\n let attrs = {}\n if (dateAttrs) { attrs = dateAttrs({ dateArray, isToday, isDisabled, isActive, isMatch: (o) => isMatch({ date: dateArray, matchers: o }) }) || {} }\n let className = this.getClassName(isActive, isToday, isDisabled, attrs.className);\n let onClick = isDisabled ? undefined : () => { onChange({ year: dateArray[0], month: dateArray[1], day: dateArray[2], hour: dateArray[3] }, true) };\n let style = {}\n if (!isDisabled) { style.background = theme[1]; }\n if (className.indexOf('aio-input-datepicker-active') !== -1) {\n style.background = theme[0];\n style.color = theme[1];\n }\n if (className.indexOf('today') !== -1) { style.border = `1px solid ${theme[0]}` }\n style = { ...style, ...attrs.style }\n let text;\n if (unit === 'hour') { text = dateArray[3] + ':00' }\n else if (unit === 'day') { text = dateArray[2] }\n else if (unit === 'month') {\n let months = getMonths({ calendarType });\n text = translate(calendarType === 'gregorian' ? months[dateArray[1] - 1].slice(0, 3) : months[dateArray[1] - 1])\n }\n return {isDisabled ? {text} : text}
\n }\n}\nclass DPHeader extends Component {\n static contextType = DPContext;\n getYears() {\n let { activeDate, years, changeActiveDate } = this.context;\n let props = {\n value: activeDate.year, options: years, optionText: 'option.toString()', optionValue: 'option',\n onChange: (year) => { changeActiveDate({ year }) }\n }\n return ()\n }\n getMonths() {\n let { calendarType = 'gregorian', activeDate, changeActiveDate, months, translate } = this.context;\n let props = {\n value: activeDate.month, onChange: (month) => { changeActiveDate({ month }) },\n options: months.map((o, i) => { return { value: i + 1, text: translate(calendarType === 'gregorian' ? o.slice(0, 3) : o) } })\n }\n return ()\n }\n getDays() {\n let { activeDate, changeActiveDate } = this.context;\n let daysLength = AIODate().getMonthDaysLength({ date: [activeDate.year, activeDate.month] });\n let options = new Array(daysLength).fill(0).map((o, i) => { return { text: (i + 1).toString(), value: i + 1 } })\n let props = { value: activeDate.day, options, onChange: (day) => changeActiveDate({ day }) }\n return ()\n }\n render() {\n let { unit = 'day', size, calendarType = 'gregorian' } = this.context;\n return (\n \n
\n
\n {this.getYears()}\n {unit !== 'month' ? this.getMonths() : null}\n {unit === 'hour' ? this.getDays() : null}\n
\n
\n
\n )\n }\n}\nclass DPHeaderDropdown extends Component {\n static contextType = DPContext;\n render() {\n //این شرط فقط در حالت سال رخ میدهد در شرایطی که فقط یک سال قابل انتخاب است\n if(this.props.options.length === 1){return this.props.options[0]}\n let { size, theme = [] } = this.context;\n let props = {\n ...this.props, search: false,\n caret: false, type: 'select', popupAttrs: { style: { maxHeight: size * 1.2 } },\n className: 'aio-input-datepicker-dropdown', popover: { attrs: { style: { maxHeight: 200 } } },\n optionStyle: { height: size / 6, background: theme[1], color: theme[0] }\n }\n return ()\n }\n}\nclass DPArrow extends Component {\n static contextType = DPContext;\n change() {\n let { calendarType, unit = 'day', years, changeActiveDate, activeDate } = this.context;\n let { type } = this.props;\n let offset = (calendarType === 'gregorian' ? 1 : -1) * (type === 'minus' ? -1 : 1);\n let date = [activeDate.year, activeDate.month, activeDate.day]\n let next = AIODate().getByOffset({ date, offset, unit: { 'hour': 'day', 'day': 'month', 'month': 'year' }[unit] })\n if (next[0] > years[years.length - 1] || next[0] < years[0]) { return }\n if (unit === 'month') { changeActiveDate({ year: next[0] }) }\n if (unit === 'day') { changeActiveDate({ year: next[0], month: next[1] }) }\n if (unit === 'hour') { changeActiveDate({ year: next[0], month: next[1], day: next[2] }) }\n }\n getIcon() {\n let { theme = [] } = this.context, { type } = this.props;\n return \n }\n render() {\n let { size } = this.context;\n return ( this.change()}>{this.getIcon()}
)\n }\n}\n\nconst SliderContext = createContext();\nexport class Slider extends Component{\n constructor(props){\n super(props);\n var {direction} = this.props;\n this.touch = 'ontouchstart' in document.documentElement;\n if(direction === 'left'){\n this.getDiff = function (x,y,client){return x - client.x;}; this.oriention = 'horizontal';\n }\n else if(direction === 'right'){\n this.getDiff = function (x,y,client){return client.x - x;}; this.oriention = 'horizontal';\n }\n else if(direction === 'top'){\n this.getDiff = function (x,y,client){return y - client.y;}; this.oriention = 'vertical'; this.flexDirection = 'column-reverse';\n }\n else{\n this.getDiff = function (x,y,client){return client.y - y;}; this.oriention = 'vertical'; this.flexDirection = 'column';\n }\n this.dom = createRef();\n this.state = { \n isDown:false,\n } \n }\n getClient(e){return this.touch?{x: e.changedTouches[0].clientX,y:e.changedTouches[0].clientY }:{x:e.clientX,y:e.clientY}}\n getPercentByValue(value,start,end){return 100 * (value - start) / (end - start);} //getPercentByValue\n fix(number){\n let dotPos = this.props.step.toString().indexOf('.');\n let a = dotPos === -1?0:this.props.step.toString().length - dotPos - 1;\n return parseFloat((number).toFixed(a));\n }\n getStartByStep(start,step){\n var a = Math.round((start - step) / step) * step; \n while(a < start){a += step;} return a;\n }\n eventHandler(selector, event, action,type = 'bind'){\n var me = { mousedown: \"touchstart\", mousemove: \"touchmove\", mouseup: \"touchend\" };\n event = this.touch ? me[event] : event;\n var element = typeof selector === \"string\"? (selector === \"window\"?$(window):$(selector)):selector; \n element.unbind(event, action); \n if(type === 'bind'){element.bind(event, action)}\n }\n getValidValue(){\n let {value,start,end,min = start,max = end,step} = this.props;\n for(var i = 0; i < value.length; i++){\n var point = value[i];\n point = Math.round((point - start)/step) * step + start;\n if(point < min){point = min;}\n if(point > max){point = max;}\n value[i] = point; \n }\n return value\n }\n getOffset(x,y,size,e){\n var {start,end,step} = this.props,client = this.getClient(e);\n return Math.round((end - start) * this.getDiff(x,y,client) / size / step) * step;\n }\n getValue(value,param = this.props){return typeof value === 'function'?value(param):value;}\n getPercents(){\n var {start,end} = this.props; \n var percents = this.value.map((o,i)=>[\n this.getPercentByValue(i?this.value[i - 1]:start,start,end),\n this.getPercentByValue(o,start,end)\n ]);\n percents.push([percents[percents.length - 1][1],100])\n return percents;\n }\n decreaseAll(step = this.props.step){\n var start = this.props.start;\n var {min = start} = this.props;\n var offset = Math.min(step,this.value[0] - this.getValue(min));\n for(var i = 0; i < this.value.length; i++){\n this.value[i] -= offset;\n this.value[i] = this.fix(this.value[i])\n }\n this.moved = true;\n }\n increaseAll(step = this.props.step){\n var end = this.props.end;\n var {max = end} = this.props;\n var offset = Math.min(step,this.getValue(max) - this.value[this.value.length - 1]);\n for(var i = 0; i < this.value.length; i++){\n this.value[i] += offset;\n this.value[i] = this.fix(this.value[i])\n }\n this.moved = true;\n }\n mouseDown(e,index,type){\n e.preventDefault();\n var {start,end,min = start,max = end,onChange,disabled} = this.props;\n if(!onChange || disabled){return}\n var {x,y} = this.getClient(e),dom = $(this.dom.current);\n var pointContainers = dom.find('.aio-slider-point-container');\n var size = dom.find('.aio-slider-line')[this.oriention === 'horizontal'?'width':'height']();\n var length = this.value.length;\n \n this.eventHandler('window','mousemove',$.proxy(this.mouseMove,this));\n this.eventHandler('window','mouseup',$.proxy(this.mouseUp,this));\n \n this.moved = false;\n this.setState({isDown:true});\n pointContainers.css({zIndex:10}); \n \n if(type === 'point'){\n let pointContainer = pointContainers.eq(index);\n pointContainer.css({zIndex:100});\n pointContainer.find('.aio-slider-point').addClass('active');\n var current = this.value[index];\n var before = index === 0?min:this.value[index - 1];\n var after = index === this.value.length - 1?max:this.value[index + 1] \n this.startOffset = {\n x,y,size,index:[index],value:[current], \n startLimit:before - current,endLimit:after - current,\n }\n }\n else{\n let pointContainer1 = pointContainers.eq(index - 1);\n let pointContainer2 = pointContainers.eq(index);\n pointContainer1.css({zIndex:100});\n pointContainer2.css({zIndex:100});\n let p1 = pointContainer1.find('.aio-slider-point');\n let p2 = pointContainer2.find('.aio-slider-point');\n p1.addClass('active');\n p2.addClass('active');\n\n if(index === 0){this.decreaseAll();}\n else if(index === length){this.increaseAll();}\n if(index === 0 || index === length){\n this.startOffset = {\n x,y,size,\n index:this.value.map((o,i)=>i),value:this.value.map((o)=>o), \n startLimit:min - this.value[0],endLimit:max - this.value[length - 1],\n }\n }\n else{\n var point1 = this.value[index - 1],point2 = this.value[index];\n var before = index === 1?min:this.value[index - 2];//مقدار قبلی رنج\n var after = index === length - 1?max:this.value[index + 1]; //مقدار بعدی رنج\n this.startOffset = {\n x,y,size,index:[index - 1,index],\n value:[point1,point2],startLimit:before - point1,endLimit:after - point2,\n }\n }\n }\n }\n \n mouseMove(e){\n let {onChange} = this.props;\n var {x,y,size,value,startLimit,endLimit,index} = this.startOffset;\n var offset = this.getOffset(x,y,size,e);\n if(offset < startLimit){offset = startLimit;}\n else if(offset > endLimit){offset = endLimit;}\n for(var i = 0; i < value.length; i++){\n let Index = index[i],Value = value[i],newValue = parseFloat(Value) + offset;\n if(this.value[Index] === newValue){return;}\n this.value[Index] = this.fix(newValue);\n } \n this.moved = true;\n onChange(this.value,true);\n }\n mouseUp(){\n this.eventHandler('window','mousemove',this.mouseMove,'unbind');\n this.eventHandler('window','mouseup',this.mouseUp,'unbind');\n let {onChange} = this.props;\n var points = $(this.dom.current).find('.aio-slider-point');\n points.removeClass('active');\n this.setState({isDown:false});\n if(this.moved){onChange(this.value,false);}\n }\n getContext(){\n return {\n ...this.props,\n touch:this.touch,\n fix:this.fix.bind(this),\n oriention:this.oriention,\n getValue:this.getValue.bind(this), \n isDown:this.state.isDown,\n mouseDown:this.mouseDown.bind(this),\n getStartByStep:this.getStartByStep.bind(this),\n getPercentByValue:this.getPercentByValue.bind(this),\n value:this.value\n }; \n }\n getStyle(){\n let {attrs} = this.props;\n let {style = {}} = attrs;\n var obj = {...style};\n obj = {...obj};\n obj.direction = 'ltr';\n obj.flexDirection = this.flexDirection;\n return obj\n }\n getClassName(){\n let {attrs,disabled} = this.props,{className} = attrs;\n return `aio-slider ${this.context.oriention}${className?' ' + className:''}${disabled?' disabled':''}`;\n }\n render(){\n this.value = this.getValidValue();\n this.context = this.getContext();\n var {labelStep,scaleStep,attrs} = this.props;\n var percents = this.getPercents();\n return (\n \n \n
\n \n {labelStep && }\n {scaleStep && }\n {this.value.map((o,i)=>)}\n \n {this.value.map((o,i)=>)}\n
\n
\n \n );\n }\n}\nSlider.defaultProps = {\n direction:'right',editLabel:(a)=>a,labelStyle:{},labelRotate:0,\n value:[0],scaleStyle:{},getPointHTML:()=>'',style:()=>{},\n start:0,end:100,step:1,activegetPointStyle:{},getText:()=>{return ''},attrs:{},\n pointStyle:{},lineStyle:{},fillStyle:{},valueStyle:{},textStyle:{},editValue:(value,index)=>value,textStyle:()=>{}\n}\nclass SliderLine extends Component{\n static contextType = SliderContext;\n render(){\n var {lineStyle} = this.context;\n return ()\n }\n}\n\nclass SliderFill extends Component{ \n static contextType = SliderContext;\n getContainerStyle(){\n var {oriention,direction} = this.context,{percent} = this.props;\n var obj = {}; \n obj[{right:'left',left:'right',top:'bottom',bottom:'top'}[direction]] = percent[0] + '%';\n if(oriention === 'horizontal'){obj.width = (percent[1] - percent[0]) + '%';} \n else{obj.height = (percent[1] - percent[0]) + '%';}\n return obj;\n }\n \n render(){\n var {mouseDown,rangeEvents = {},fillStyle,getText,textStyle,touch,value} = this.context;\n var {index} = this.props;\n var containerProps = {\n 'data-index':index,className:'aio-slider-fill-container',\n [touch?'onTouchStart':'onMouseDown']:(e)=>{\n mouseDown(e,index,'fill')\n },\n style:this.getContainerStyle()\n }\n for(let prop in rangeEvents){\n containerProps[prop] = ()=>rangeEvents[prop](index)\n }\n let text = getText(index,this.context);\n let style,active;\n if(typeof fillStyle === 'function'){\n style = fillStyle(index,this.context);\n }\n else{\n if(value.length === 1 && index === 0){\n style = fillStyle;\n active = true\n }\n if(value.length > 1 && index !== 0 && index !== value.length){\n style = fillStyle;\n active = true;\n }\n }\n return (\n \n
\n {text !== undefined &&
{text}
}\n
\n );\n }\n}\n\nclass SliderPoint extends Component{ \n static contextType = SliderContext;\n getContainerStyle(){\n var {direction} = this.context,{percent} = this.props;\n return {\n [{right:'left',left:'right',top:'bottom',bottom:'top'}[direction]]:percent[1] + '%'};\n }\n getValueStyle(){\n var {showValue,isDown,valueStyle} = this.context;\n var {index} = this.props;\n if(showValue === false){return {display:'none'}}\n if(showValue === true || showValue === 'inline' || isDown){return typeof valueStyle === 'function'?valueStyle(index,this.context):valueStyle;}\n return {display:'none'};\n }\n render(){\n var {value,mouseDown,editValue,pointEvents,getPointHTML,pointStyle,touch,fix,showValue} = this.context;\n var {index} = this.props;\n var point = value[index];\n var props = {\n style:this.getContainerStyle(),'data-index':index,className:'aio-slider-point-container', \n [touch?'onTouchStart':'onMouseDown']:(e)=>mouseDown(e,index,'point')\n };\n for(let prop in pointEvents){props[prop] = ()=>pointEvents[prop](index)}\n var pointProps = {className:'aio-slider-point',style:typeof pointStyle === 'function'?pointStyle(index,this.context):pointStyle,'data-index':index};\n var valueProps = {\n style:this.getValueStyle(),\n className:`aio-slider-value ${'aio-slider-value-' + index}` + (showValue === 'inline'?' aio-slider-value-inline':'')\n };\n let html = getPointHTML(index,this.context);\n return (\n \n {showValue !== 'inline' &&
{html}
}\n
{editValue(fix(point),index)}
\n
\n );\n }\n}\n\nclass SliderLabels extends Component{\n static contextType = SliderContext;\n constructor(props){\n super(props);\n this.dom = createRef();\n $(window).on('resize',this.update.bind(this))\n }\n getLabelsByStep(labelStep){\n var {start,label = {},end,getStartByStep} = this.context;\n var Labels = [];\n var value = getStartByStep(start,labelStep); \n var key = 0;\n while (value <= end) {\n Labels.push(\n \n );\n value += labelStep;\n value = parseFloat(value.toFixed(6))\n key++;\n } \n return Labels;\n }\n getLabels(labelStep){return labelStep.map((o)=>)}\n update(){ \n var container = $(this.dom.current); \n var labels = container.find('.aio-slider-label div'); \n if(!labels.length){return;}\n var {direction,label = {}} = this.context;\n var firstLabel = labels.eq(0);\n var firstLabelThickness = firstLabel.attr('datarotated') === 'yes'?'height':'width';\n if(direction === 'right'){\n var end = firstLabel.offset().left + firstLabel[firstLabelThickness]();\n for(var i = 1; i < labels.length; i++){\n var label = labels.eq(i);\n let thickness = label.attr('datarotated') === 'yes'?'height':'width'; \n label.css({display:'block'}) \n var left = label.offset().left\n \n var width = label[thickness]();\n if(left < end + 5){ \n label.css({display:'none'})\n }\n else{end = left + width;} \n }\n }\n else if(direction === 'left'){\n var end = firstLabel.offset().left;\n for(var i = 1; i < labels.length; i++){\n var label = labels.eq(i);\n let thickness = label.attr('datarotated') === 'yes'?'height':'width'; \n label.css({display:'block'})\n var left = label.offset().left\n var width = label[thickness]();\n var right = left + width;\n if(right > end - 5){\n label.css({display:'none'})\n }\n else{end = left;} \n }\n }\n }\n componentDidMount(){this.update()}\n componentDidUpdate(){this.update()}\n render(){\n let {labelStep} = this.context;\n return (\n \n {Array.isArray(labelStep)?this.getLabels(labelStep):this.getLabelsByStep(labelStep)}\n
\n );\n }\n}\n\nclass SliderLabel extends Component{\n static contextType = SliderContext;\n getStyle(rotate){\n var {start,end,getPercentByValue,direction,labelStyle} = this.context;\n var {value} = this.props;\n var obj = typeof labelStyle === 'function'?labelStyle(value,this.context):labelStyle;\n obj = !obj?{}:{...obj}\n try{\n let key = {right:'left',left:'right',top:'bottom',bottom:'top'}[direction];\n obj[key] = getPercentByValue(value,start,end) + '%';\n }\n catch{\n debugger\n let key = {right:'left',left:'right',top:'bottom',bottom:'top'}[direction];\n obj[key] = getPercentByValue(value,start,end) + '%';\n }\n \n if(rotate){\n obj.transform = `rotate(${rotate + 'deg'})`;\n obj.justifyContent = rotate > 0?'flex-start':'flex-end' \n }\n return obj; \n } \n click(e){\n var {onLabelClick} = this.context;\n e.stopPropagation();\n if(!onLabelClick){return}\n var {value} = this.props;\n onLabelClick(value);\n }\n render(){\n let {editLabel,labelRotate} = this.context;\n let {value} = this.props;\n let rotate = typeof labelRotate === 'function'?labelRotate(value):labelRotate;\n let text;\n try{text = editLabel(value)}\n catch{text = ''}\n return (\n \n );\n }\n}\n\nclass SliderScales extends Component{\n static contextType = SliderContext;\n getScalesByStep(scaleStep){\n var {start,end,getStartByStep} = this.context;\n var value = getStartByStep(start,scaleStep);\n var key = 0,scales = []; \n while (value <= end) {\n scales.push();\n value += scaleStep;\n key++;\n }\n return scales;\n }\n getScales(scaleStep){return scaleStep.map((o)=>)}\n render(){\n let {scaleStep} = this.context; \n let scales = Array.isArray(scaleStep)?this.getScales(scaleStep):this.getScalesByStep(scaleStep)\n return ({scales}
);\n }\n}\nclass SliderScale extends Component{\n static contextType = SliderContext;\n getStyle(){\n var {scaleStyle} = this.context;\n var {start,end,direction,getPercentByValue} = this.context,{value} = this.props;\n var obj = typeof scaleStyle === 'function'?scaleStyle(value,this.context):scaleStyle;\n obj = !obj?{}:{...obj}\n if(!obj){obj = {}}\n obj[{right:'left',left:'right',top:'bottom',bottom:'top'}[direction]] = getPercentByValue(value,start,end) + '%';\n return obj;\n }\n render(){\n let {getScaleHTML} = this.context,{value} = this.props;\n return ({getScaleHTML && getScaleHTML(value)}
);\n }\n}\n","import React, { Component, createRef } from 'react';\nimport RVD from './../react-virtual-dom/react-virtual-dom';\nimport AIOStorage from './../aio-storage/aio-storage';\nimport AIOInput from './../aio-input/aio-input';\nimport { Icon } from '@mdi/react';\nimport { mdiCellphone, mdiLock, mdiLoading, mdiAccount, mdiAccountBoxOutline, mdiEmail, mdiChevronRight } from '@mdi/js';\nimport AIOService from './../aio-service/aio-service';\n\nimport './index.css';\nexport default class AIOlogin{\n getActions = ({removeToken,getToken,setToken,getUserId})=>{\n this.removeToken = removeToken;\n this.getToken = getToken;\n this.setToken = setToken;\n this.getUserId = getUserId;\n }\n render = (props)=>{\n return this.getActions(obj)}/>\n }\n}\nclass AIOLOGIN extends Component {\n constructor(props) {\n super(props);\n let {id, checkToken,COMPONENT,onSubmit} = props;\n if (!id) { console.error(`aio-login error=> missing id props`) }\n if (!COMPONENT) { console.error(`aio-login error=> missing COMPONENT props`) }\n props.getActions({\n removeToken:this.removeToken.bind(this),\n getToken:this.getToken.bind(this),\n setToken:this.setToken.bind(this),\n getUserId:this.getUserId.bind(this),\n })\n this.valid = true\n this.tokenStorage = AIOStorage(`${id}-token`);\n this.state = {\n isAutenticated: false,\n apis: AIOService({\n id: `${id}login`,\n getResponse: () => {\n return {\n checkToken: async () => {\n let {token,userId,isAuthenticated} = this.getStorage();\n if (!token || !isAuthenticated) { return { result: false } }\n let result = await checkToken(token,userId);\n if(result === false){this.removeToken()}\n return { result }\n },\n onSubmit:async ({model,mode}) =>{\n this.removeToken();\n let {mode:Mode,error = 'خطایی رخ داد',token} = await onSubmit(model,mode);\n if(Mode === 'Error'){return {result:error}}\n return {result:{Mode,token}}\n }\n }\n },\n onCatch: (res) => { \n this.setState({ isAutenticated: false }); \n return 'error' \n }\n })\n }\n }\n getStorage(){\n let token = this.tokenStorage.load({ name: 'token', def: false });\n let userId = this.tokenStorage.load({ name: 'userId', def: '' });\n let isAuthenticated = this.tokenStorage.load({ name: 'isAuthenticated', def: false });\n return {token,userId,isAuthenticated} \n }\n setStorage(key,value){this.tokenStorage.save({name:key,value});}\n removeToken(){this.tokenStorage.remove({name:'token'});}\n getToken(){return this.getStorage().token;}\n getUserId(){return this.getStorage().userId}\n setToken(token){this.setStorage('token',token)}\n async componentDidMount() {\n if (!this.valid) { return }\n let res = await this.state.apis({\n api: 'checkToken', name: 'بررسی توکن',\n errorMessage: 'اتصال خود را بررسی کنید',\n })\n this.mounted = true;\n if(res === false){this.removeToken()}\n this.setState({ isAutenticated: res });\n }\n logout() { this.removeToken(); window.location.reload() }\n render() {\n if (!this.valid) { return null }\n if (!this.mounted) { return null }\n let { registerFields, layout, otpLength, COMPONENT, id, time = 16,methods,className,style,model,registerButton } = this.props;\n let { isAutenticated,apis } = this.state;\n if (isAutenticated) {\n let {token,userId} = this.getStorage();\n COMPONENT({token,userId,logout: this.logout.bind(this)})\n return null\n }\n if (registerFields) {\n registerFields = registerFields.map(({ before, label, field, type,required }) => {\n return { label, field, type, before,required }\n })\n }\n let html = (\n {\n let name = {\n \"OTPPhoneNumber\":'ارسال شماره همراه',\n \"OTPCode\":'ارسال کد یکبار مصرف',\n \"UserName\":'ارسال نام کاربری و رمز عبور',\n \"PhoneNumber\":'ارسال شماره همراه و رمز عبور',\n \"Email\":'ارسال آدرس ایمیل و رمز عبور',\n \"Register\":'عملیات ثبت نام'\n }[mode];\n let {token,Mode} = await apis({\n api:'onSubmit', parameter: {model,mode}, name,loading:false\n })\n let modes = [];\n if(mode === 'OTPPhoneNumber'){modes = ['Error','OTPCode','Authenticated']}\n else{modes = ['Error','Authenticated']}\n if(registerFields){modes.push('Register')}\n if(modes.indexOf(Mode) === -1){\n console.error(`aio-login error => onSubmit props should returns an object contain mode(${modes.join(' | ')})`)\n return\n }\n if(['OTPPhoneNumber','PhoneNumber','UserName','Email'].indexOf(mode) !== -1){\n this.setStorage('userId',model[mode]);\n }\n if (token) { \n this.setStorage('token',token);\n \n this.setState({ token})\n }\n if(Mode === 'Authenticated'){\n this.setStorage('isAuthenticated',true);\n this.setState({isAutenticated:true})\n }\n else {return Mode}\n }}\n />\n )\n if (layout) { return layout(html) }\n return html\n }\n}\nclass LoginForm extends Component {\n constructor(props) {\n super(props);\n this.dom = createRef()\n this.storage = AIOStorage(props.id + 'aio-login');\n let { time = 30, fields = [],model = {} } = props;\n let mode = props.methods[0];\n this.state = {\n mode,fields, time, recode: false,\n formError: true,\n userId: model[mode],\n model: this.getInitialModel(mode)\n }\n }\n changeMode(mode){\n let { model = {} } = this.props;\n this.setState({\n mode,\n formError: true,\n userId: model[mode],\n model: this.getInitialModel(mode)\n })\n }\n getInitialModel(mode) {\n if(!mode){mode = this.state.mode}\n let { model = {},methods } = this.props;\n let obj = {password:'',OTPCode:''};\n for(let i = 0; i < methods.length; i++){\n obj[methods[i]] = model[methods[i]] || '';\n }\n return obj;\n }\n getWaitingTime(){\n let {time,mode} = this.state;\n let lastTry = this.storage.load({name:'lastTry' + mode,def: new Date().getTime() - (time * 1000)})\n let now = new Date().getTime();\n let res = Math.round((now - lastTry) / 1000);\n if(res < time){return time - res}\n return 0\n }\n setLastTry(){\n let {mode} = this.state;\n this.storage.save({name:'lastTry' + mode,value:new Date().getTime()})\n }\n async onSubmit() {\n let {onSubmit} = this.props;\n let { loading, formError,model,mode } = this.state;\n if (formError || loading) { return }\n this.setState({loading:true})\n let Mode = await onSubmit(model,mode);\n this.setState({loading:false})\n this.setLastTry();\n if(Mode === 'Register'){this.setState({mode:'Register',userId:model[mode]})}\n if(Mode === 'OTPCode'){this.setState({mode:'OTPCode',userId:model[mode]})}\n }\n title_layout() {\n let { mode } = this.state;\n if(mode === 'OTPCode'){return false}\n let {methods} = this.props;\n let dic = {OTPPhoneNumber:'کد یکبار مصرف',Email:'ایمیل',UserName:'نام کاربری',PhoneNumber:'شماره همراه و رمز عبور'}\n let html = mode === 'Register'?`ثبت نام`:`ورود با ${dic[mode]}`\n return {\n className: 'aio-login-title',\n align: 'v',\n row:[\n {show:mode === 'Register',html:,size:48,align:'vh',onClick:()=>this.changeMode(methods[0])},\n {html}\n ]\n }\n }\n subtitle_layout() {\n let { mode,userId } = this.state;\n let html = '';\n if(mode === 'OTPPhoneNumber'){\n html = 'شماره همراه خود را وارد کنید . پیامکی حاوی کد برای شما ارسال خواهد شد'\n }\n else if(mode === 'OTPCode'){\n html = `کد پیامک شده به شماره ی ${userId} را وارد کنید`\n }\n return { html, className: 'aio-login-subtitle' }\n }\n getInputs() {\n let { fields, mode, model, userId } = this.state;\n let {model:InitialModel = {}} = this.props;\n let {otpLength} = this.props;\n if (mode === 'Register') {\n return [...fields.map((o) => { return { input:{...o,label:undefined},label:o.label, field: 'value.register.' + o.field, validations: o.required ? [['required']] : undefined } })]\n }\n let inputs = [\n {\n show:mode === 'UserName',field: 'value.UserName',label: 'نام کاربری', \n input:{\n type: 'text', disabled:!!InitialModel.UserName,placeholder: 'نام کاربری',before: ,\n style:{direction:'ltr'}\n },\n validations: [['function', () => errorHandler('UserName', model.UserName)]]\n },\n {\n show:mode === 'OTPPhoneNumber' || mode === 'PhoneNumber',field: `value.${mode}`,label: 'شماره همراه',\n input:{\n type: 'text',disabled:!!InitialModel.OTPPhoneNumber || !! InitialModel.PhoneNumber,justNumber: true,before: , \n placeholder: '09...',maxLength:11,style:{direction:'ltr'}\n }, \n validations: [['function', () => errorHandler('PhoneNumber', model[mode])]]\n },\n {\n show:mode === 'Email',field: 'value.Email',label: 'ایمیل', \n input:{type: 'text', disabled:!!InitialModel.Email,before: ,style:{direction:'ltr'}}, \n validations: [['function', () => errorHandler('Email', model.Email)]],\n },\n {\n show:!!userId && mode === 'OTPCode',field: 'value.OTPCode', label: 'کد پیامک شده',\n input:{\n maxLength: otpLength, justNumber: true, type: 'text', placeholder: Array(otpLength).fill('-').join(''),\n className:'aio-login-otp-code'\n },\n validations: [['function', () => errorHandler('OTPCode', model.OTPCode, otpLength)]]\n },\n {\n show:mode !== 'OTPPhoneNumber' && mode !== 'OTPCode',field: 'value.password',label: 'رمز عبور', \n input:{type: 'password',before: ,style:{direction:'ltr'}}, \n validations: [['function', () => errorHandler('password', model.password)]]\n }\n ];\n return inputs\n }\n form_layout() {\n let { model,userId,mode } = this.state;\n return {\n className:'ofy-auto',\n html: (\n {\n this.setState({ model,formError:!!Object.keys(errors).length})}\n }\n inputs={{props:{gap:12},column:this.getInputs()}}\n />\n )\n }\n }\n submit_layout() {\n let { loading,formError,mode } = this.state;\n let waitingTime = this.getWaitingTime();\n let text = mode === 'Register'?'ثبت نام':'ورود';\n if(waitingTime){\n setTimeout(()=>this.setState({}),1000)\n text = `لطفا ${waitingTime} ثانیه صبر کنید`\n }\n return {\n style: { padding: '0 12px' }, className: 'm-b-12',\n gap:12,\n row: [\n {\n flex: 1,\n html: (\n !!formError || !!waitingTime}\n onClick={() => this.onSubmit()}\n loading={loading}\n />\n )\n }\n ]\n }\n }\n changeUserId_layout(){\n let { mode } = this.state;\n if(mode !== 'OTPCode'){return false}\n return {\n onClick: () => this.changeMode('OTPPhoneNumber'), \n className: 'aio-login-text m-b-12', align: 'vh', html: 'تغییر شماره همراه'\n }\n }\n recode_layout() {\n let { mode ,model} = this.state;\n if (mode !== 'OTPCode') { return false }\n let waitingTime = this.getWaitingTime();\n if(!!waitingTime){return false}\n return {\n className: 'aio-login-text m-b-12', html: `ارسال مجدد کد`, align: 'vh',\n onClick: () => {\n this.setState({mode:'OTPPhoneNumber',model:{...model,OTPCode:''}})\n\n }\n } \n }\n changeMode_layout() {\n let { mode } = this.state;\n if (mode === 'Register') { return false }\n let { methods } = this.props;\n let others = []\n for (let i = 0; i < methods.length; i++) {\n let key = methods[i];\n if (mode === key) { continue }\n if(mode === 'OTPCode' && key === 'OTPPhoneNumber'){continue}\n let title = {OTPPhoneNumber:'رمز یکبار مصرف',UserName:'نام کاربری و رمز عبور',Email:'آدرس ایمیل و رمز عبور',PhoneNumber:'شماره همراه و رمز عبور'}[key];\n let icon = {OTPPhoneNumber: mdiAccount,PhoneNumber: mdiCellphone,UserName: mdiAccountBoxOutline,Email:mdiEmail}[key]\n others.push({\n flex: 1,\n className: `of-visible aio-login-other-method aio-login-${key}`,\n onClick: () => this.changeMode(key),\n row: [\n { html: , align: 'vh' },\n { size: 6 },\n { align: 'v', html: title }\n ]\n })\n }\n if (!others.length) { return false }\n return {\n className: 'p-h-12',\n column: [\n {\n gap: 6,\n row: [\n { flex: 1, html: , align: 'v' },\n { html: 'یا ورود با', align: 'v', className: 'aio-login-or bold' },\n { flex: 1, html: , align: 'v' },\n ]\n },\n { size: 12 },\n { grid: others, gridCols: 1, gridRow: { gap: 12 } }\n ]\n }\n }\n register_layout(){\n let {registerButton} = this.props;\n let {mode} = this.state;\n if(!registerButton || mode === 'Register'){return false}\n return {\n align:'vh',\n html:(\n \n )\n }\n }\n render() {\n let {className,style} = this.props;\n return (\n { if (e.keyCode === 13) { this.onSubmit() } } },\n column: [\n { \n column: [\n this.title_layout(), \n this.subtitle_layout()\n ] \n },\n this.form_layout(),\n this.submit_layout(),\n {\n gap:12,align:'h',\n row:[\n this.recode_layout(),\n this.changeUserId_layout()\n ]\n },\n this.changeMode_layout(),\n this.register_layout()\n ]\n }}\n />\n )\n }\n}\nfunction errorHandler(field, value = '', otpLength) {\n return {\n UserName() {\n if (!value) { return 'نام کاربری را وارد کنید' }\n return false\n },\n PhoneNumber() {\n if (!value) { return 'شماره همراه خود را وارد کنید' }\n if (value.indexOf('09') !== 0) { return 'شماره همراه باید با 09 شروع شود' }\n if (value.length !== 11) { return 'شماره همراه باید 11 رقم باشد' }\n return false\n },\n Email() {\n let atSignIndex = value.indexOf('@');\n if (!value) { return 'ایمیل خود را وارد کنید' }\n if (atSignIndex < 1) { return 'ایمیل خود را به درستی وارد کنید' }\n if (value.indexOf('.') === -1) { return 'ایمیل خود را به درستی وارد کنید' }\n if (value.lastIndexOf('.') > value.length - 3) { return 'ایمیل خود را به درستی وارد کنید' }\n return false\n },\n password() {\n if (value.length < 6) { return 'رمز عبور باید شامل حداقل 6 کاراکتر باشد' }\n return false\n },\n OTPCode() {\n let res;\n if (value.length !== otpLength) { res = `کد ورود باید شامل ${otpLength} کاراکتر باشد` }\n else { res = false }\n return res\n }\n }[field](value)\n}\n\nclass SubmitButton extends Component {\n state = { reload: false }\n async onClick() {\n let { onClick, loading } = this.props;\n if (loading) { return; }\n await onClick();\n }\n render() {\n let { disabled, loading, text,outline } = this.props;\n let { reload } = this.state;\n if (loading && !reload) { setTimeout(() => this.setState({ reload: true }), 16 * 1000) }\n let loadingText = reload ? 'بارگزاری مجدد' : 'در حال ارسال';\n return (\n <>\n \n {\n loading &&\n { if (reload) { window.location.reload() } }}\n >
\n }\n >\n )\n }\n}\n\n","import React, { Component, createRef } from 'react';\nimport * as ReactDOMServer from 'react-dom/server';\nimport { Icon } from '@mdi/react';\nimport { mdiClose, mdiChevronRight, mdiChevronLeft } from '@mdi/js';\nimport RVD from './../../npm/react-virtual-dom/react-virtual-dom';\nimport $ from 'jquery';\nimport './aio-popup.css';\n\n\nexport default class AIOPopup {\n constructor(obj = {}){\n this.rtl = obj.rtl\n }\n render = () => {\n return (\n <>\n {\n this._addModal = addModal;\n this._removeModal = removeModal;\n this._getModals = getModals;\n }}\n />\n {\n this._addSnakebar = add;\n }}/>\n >\n )\n }\n getModals = ()=>this._getModals()\n addModal = (obj = {},animate = true)=>{\n if(obj.id === undefined){obj.id = 'popup' + Math.round(Math.random() * 1000000)}\n this._addModal(obj,animate)\n }\n removeModal = (arg,animate = true)=> this._removeModal(arg,animate);\n addAlert = (obj = {}) => {\n let { icon, type = '', text = '', subtext = '', time = 10, className, closeText = 'بستن' } = obj\n Alert({icon,type,text,subtext,time,className,closeText})\n }\n addSnakebar = (obj = {})=>{\n let {text,index,type,subtext,action = {},time = 6,rtl} = obj;\n this._addSnakebar({text,index,type,subtext,action,time,rtl})\n }\n}\nclass Popups extends Component {\n constructor(props) {\n super(props);\n let { getActions = () => { } } = props\n this.state = {modals: []}\n getActions({\n removeModal: this.removeModal.bind(this),\n addModal: this.addModal.bind(this),\n getModals: ()=>[...this.state.modals]\n })\n }\n change(obj) {\n let { onChange = () => { } } = this.props;\n for(let prop in obj){this.state[prop] = obj[prop]}\n this.setState(obj, () => onChange({ ...this.state }))\n }\n addModal(o,animate = true) {\n if(typeof o !== 'object'){\n console.error('aio-popup => addModal modal parameter to add is not an object');\n return;\n }\n if(o.id === undefined){\n console.error('aio-popup => addModal missing modal id property');\n return;\n }\n let { modals } = this.state;\n let newModals = modals.filter(({ id }) => id !== o.id);\n newModals.push({...o,mounted:o.position === 'popover'?false:!animate})\n this.change({ modals: newModals })\n }\n async removeModal(arg = 'last',animate = true) {\n if(arg === 'all'){this.change({ modals: [] });}\n else{\n this.mount(arg,false);\n setTimeout(()=>{\n let { modals } = this.state;\n let modal = arg === 'last'?modals[modals.length - 1]:modals.find((o) => o.id === arg);\n if(modal.onClose){modal.onClose()}\n else if(arg === 'last'){this.change({ modals: modals.slice(0,modals.length - 1) })}\n else {this.change({ modals: modals.filter((o) => o.id !== arg) })}\n },animate?300:0)\n }\n }\n mount(id = 'last',state){\n try{\n let { modals } = this.state;\n if(id === 'last'){id = modals[modals.length - 1].id}\n let newModals = modals.map((o)=>o.id === id?{...o,mounted:state}:o)\n this.change({modals:newModals})\n }\n catch{return}\n }\n getModals() {\n let { modals } = this.state;\n if (!modals.length) { return null }\n return modals.map(({popover, \n position,text,onSubmit, rtl = this.props.rtl, attrs = {}, onClose,backdrop, header,footer, closeType, body, id,mounted }, i) => {\n let props = {\n id,backdrop,footer,text,onSubmit,header,popover,\n position, rtl, attrs, closeType, body,index: i,mounted,\n onClose: () => this.removeModal(id),\n onMount:()=>this.mount(id,true)\n }\n return \n })\n }\n render() {\n return (\n <>\n {this.getModals()}\n >\n )\n }\n}\n\nclass Popup extends Component {\n constructor(props) {\n super(props); \n this.dom = createRef();\n this.state = {popoverStyle:undefined}\n }\n async onClose() {\n let { onClose } = this.props;\n onClose();\n }\n componentDidMount(){\n let {popover = {},position,mounted,onMount} = this.props;\n setTimeout(()=>{\n this.setState({\n popoverStyle:position === 'popover'?this.getPopoverStyle():{},\n })\n if(!mounted){onMount()}\n },0)\n if(popover.getTarget){\n this.dui = 'a' + (Math.round(Math.random() * 10000000));\n let target = popover.getTarget();\n target.attr('data-uniq-id',this.dui)\n }\n $(window).unbind('click',this.handleBackClick)\n $(window).bind('click',$.proxy(this.handleBackClick,this))\n }\n handleBackClick(e){\n if(!this.dui){return}\n let target = $(e.target)\n if(this.props.backdrop !== false || target.attr('data-uniq-id') === this.dui || target.parents(`[data-uniq-id=${this.dui}]`).length){\n return\n }\n this.onClose();\n }\n header_layout() {\n let { rtl,header } = this.props;\n if (typeof header !== 'object') { return false }\n return {html:this.onClose()}/>}\n }\n body_layout(){\n let {body = {}} = this.props;\n return { flex:1,html: }\n }\n footer_layout() {\n let {closeText,submitText,onSubmit,footer,type} = this.props;\n let handleClose = this.onClose.bind(this);\n let props = {closeText,submitText,onSubmit,footer,type,handleClose};\n return {html:}\n }\n getBackDropClassName() {\n let { rtl,position = 'fullscreen',backdrop,mounted } = this.props;\n let className = 'aio-popup-backdrop';\n if (backdrop && backdrop.attrs && backdrop.attrs.className) { className += ' ' + backdrop.attrs.className }\n className += ` aio-popup-position-${position}`\n className += backdrop === false?' aio-popup-backdrop-off':''\n className += rtl?' rtl':' ltr'\n if(!mounted){className += ' not-mounted'}\n return className\n }\n backClick(e) {\n e.stopPropagation();\n let target = $(e.target);\n let { backdrop = {} } = this.props;\n if (backdrop.close === false) { return }\n if(!target.hasClass('aio-popup-backdrop')){return}\n this.onClose()\n }\n getPopoverStyle(){\n let { popover = {},rtl,attrs = {} } = this.props;\n let {getTarget,openRelatedTo,fitHorizontal,fixStyle = (o) => o} = popover; \n if(!getTarget) { return {} }\n let target = getTarget();\n if (!target || !target.length) { return {}}\n let popup = $(this.dom.current);\n let style = Align(popup, target, { fixStyle: fixStyle, pageSelector: openRelatedTo, fitHorizontal, style: attrs.style, rtl })\n return {...style,position:'fixed'}\n }\n render() {\n let { rtl, attrs = {},backdrop,mounted} = this.props;\n let {popoverStyle} = this.state\n let backdropProps = {\n ...(backdrop?backdrop.attrs:{}),\n className: this.getBackDropClassName(),\n onClick: backdrop === false?undefined:(e) => this.backClick(e),\n }\n let style = { ...popoverStyle,...attrs.style,flex:'none'}\n let className = 'aio-popup' + (rtl ? ' rtl' : ' ltr') + (!mounted?' not-mounted':'') + (attrs.className?' ' + attrs.className:'');\n return (\n \n \n
\n )\n }\n}\nfunction ModalHeader({rtl,header,handleClose}){\n if(typeof header !== 'object'){return null}\n let {title,subtitle,buttons = [],onClose,backButton,attrs = {}} = header;\n function close(e){if(onClose){onClose(e)} else{handleClose()}}\n function backButton_layout(){\n if(!backButton || onClose === false){return false}\n let path,style;\n if(rtl){path = mdiChevronRight; style = {marginLeft:12}}\n else {path = mdiChevronLeft; style = {marginRight:12}}\n return { html: , align: 'vh', onClick: () => onClose() ,style}\n }\n function title_layout(){\n if(!title){return false}\n if(!subtitle){\n return { flex: 1,align: 'v', html: title, className: 'aio-popup-title' } \n }\n else {\n return { \n flex: 1, align: 'v',\n column:[\n {html:title,className: 'aio-popup-title'},\n {html:subtitle,className: 'aio-popup-subtitle'}\n ] \n }\n }\n }\n function buttons_layout(){\n if(!buttons.length){return false}\n return {\n gap:6,align:'vh',\n row:()=>buttons.map(([text,attrs = {}])=>{\n let {onClick = ()=>{},className} = attrs;\n attrs.className = 'aio-popup-header-button' + (className?' ' + className:'');\n attrs.onClick = ()=> onClick({close:handleClose})\n return {html:(),align:'vh'}\n })\n }\n }\n function close_layout(){\n if(backButton || onClose === false){return false}\n return { html: , align: 'vh', onClick: (e) => close(e),className:'aio-popup-header-close-button' }\n }\n let className = 'aio-popup-header' + (attrs.className?' ' + attrs.className:'')\n let style = attrs.style;\n return ()\n}\nfunction ModalBody({handleClose,body}){\n let {render,attrs = {}} = body;\n return (\n \n {typeof render === 'function' && render({close:handleClose})}\n
\n )\n}\nfunction ModalFooter({type,closeText = 'Close',submitText = 'Submit',footer,handleClose,onSubmit}){\n if(typeof footer !== 'object'){return null}\n let {attrs = {}} = footer;\n let {buttons = []} = footer;\n function buttons_layout(){\n if(!buttons.length){return false}\n return {\n gap:6,align:'vh',\n row:()=>buttons.map(([text,attrs = {}])=>{\n let {onClick = ()=>{},className} = attrs;\n attrs.className = 'aio-popup-footer-button' + (className?' ' + className:'');\n attrs.onClick = ()=> onClick({close:handleClose})\n return {html:(),align:'vh'}\n })\n }\n }\n let className = 'aio-popup-footer' + (attrs.className?' ' + attrs.className:'')\n let style = attrs.style;\n return ()\n}\n\n\nfunction Alert(obj = {}) {\n let { icon,type,text,subtext,time,className,closeText} = obj;\n let $$ = {\n time: 0,\n getId() {\n return 'aa' + Math.round((Math.random() * 100000000))\n },\n getBarRender() {\n return ``\n },\n updateBarRender() {\n $(`.aio-popup-alert-container.${$$.id} .aio-popup-time`).html($$.getBarRender())\n },\n getRender() {\n return (`\n \n `)\n },\n close() {\n $('.' + $$.id).remove()\n },\n getIcon() {\n if (icon === false) { return '' }\n return icon || {\n error: (``),\n warning: (``),\n info: (``),\n success: (``)\n }[type] || ''\n },\n startTimer() {\n setTimeout(() => {\n if ($$.time >= 100) { $$.time = 100; $$.close(); return}\n $$.time += 2;\n $$.updateBarRender();\n $$.startTimer();\n }, time / 50 * 1000)\n },\n render() {\n $('body').append($$.getRender());\n $('button.' + $$.id).off('click', $$.close);\n $('button.' + $$.id).on('click', $$.close)\n }\n }\n $$.id = $$.getId();\n $$.render();\n if (time) { $$.startTimer(); }\n}\nclass AIOSnackeBar extends Component{\n constructor(props){\n super(props);\n this.state = {items:[]}\n props.getActions({add:this.add.bind(this)})\n }\n add(item){\n let {items} = this.state;\n this.setState({items:items.concat({...item,id:'a' + Math.round(Math.random() * 1000000000)})})\n }\n remove(id){\n let {items} = this.state;\n this.setState({items:items.filter((o,i)=>o.id !== id)})\n }\n render(){\n let {items} = this.state;\n let {rtl = false} = this.props;\n return (\n <>\n {\n items.map((item,i)=>{\n return (\n this.remove(id)}/>\n )\n })\n }\n >\n )\n }\n}\n\nclass SnackebarItem extends Component{\n constructor(props){\n super(props);\n this.state = {mounted:false,timer:0,bottom:0}\n }\n componentDidMount(){\n let {time = 8} = this.props;\n setTimeout(()=>this.setState({mounted:true}),0)\n setTimeout(()=>this.remove(),time * 1000)\n }\n remove(){\n let {onRemove,id} = this.props;\n this.setState({mounted:false})\n setTimeout(()=>onRemove(id),200)\n }\n info_svg(){return ()}\n success_svg(){return ()}\n getSvg(type){return type === 'error' || type === 'warning' || type === 'info'?this.info_svg():this.success_svg()}\n getBottom(index){\n let els = $('.aio-popup-snakebar-item-container'),sum = 12;\n for(let i = 0; i < index; i++){sum += els.eq(i).height() + 6;}\n return sum\n }\n render(){\n let {mounted} = this.state;\n let {text,index,type,subtext,action,time,rtl} = this.props;\n let bottom = this.getBottom(index)\n return (\n this.remove()} className={'aio-popup-snakebar-item-container' + (mounted?' mounted':'')} style={{bottom,direction:rtl?'rtl':undefined}}>\n
\n
{this.getSvg(type)}
\n
\n
{text}
\n {!!subtext &&
{subtext}
}\n
\n {\n !!action.text && \n
}\n
\n
\n
\n )\n }\n}\n//id,onClose,backdrop,getTarget,position,fixStyle,attrs,fitHorizontal,openRelatedTo,rtl,body\nfunction Align(dom,target,config = {}){\n let {fitHorizontal,style,fixStyle = (o)=>o,pageSelector,rtl} = config;\n let $$ = {\n getDomLimit(dom){\n let offset = dom.offset();\n let left = offset.left - window.pageXOffset;\n let top = offset.top - window.pageYOffset;\n let width = dom.outerWidth();\n let height = dom.outerHeight();\n let right = left + width;\n let bottom = top + height;\n return {left,top,right,bottom,width,height};\n },\n getPageLimit(dom,pageSelector){\n let page = pageSelector?dom.parents(pageSelector):undefined;\n page = Array.isArray(page) && page.length === 0?undefined:page;\n let bodyWidth = window.innerWidth;\n let bodyHeight = window.innerHeight;\n let pageLimit = page?$$.getDomLimit(page):{left:0,top:0,right:bodyWidth,bottom:bodyHeight};\n if(pageLimit.left < 0){pageLimit.left = 0;}\n if(pageLimit.right > bodyWidth){pageLimit.right = bodyWidth;}\n if(pageLimit.top < 0){pageLimit.top = 0;}\n if(pageLimit.bottom > bodyHeight){pageLimit.bottom = bodyHeight;}\n return pageLimit;\n },\n align(){\n let pageLimit = $$.getPageLimit(dom,pageSelector);\n let targetLimit = $$.getDomLimit(target);\n let domLimit = $$.getDomLimit(dom); \n domLimit.top = targetLimit.bottom\n domLimit.bottom = domLimit.top + domLimit.height; \n if(fitHorizontal){domLimit.width = targetLimit.width}\n //اگر راست به چپ باید باشد\n if(rtl){\n //راست المان را با راست هدف ست کن\n domLimit.right = targetLimit.right;\n //چپ المان را بروز رسانی کن\n domLimit.left = domLimit.right - domLimit.width;\n //اگر المان از سمت چپ از صفحه بیرون زد سمت چپ المان را با سمت چپ صفحه ست کن\n if(domLimit.left < pageLimit.left){domLimit.left = pageLimit.left;}\n }\n //اگر چپ به راست باید باشد\n else{\n //چپ المان را با چپ هدف ست کن\n domLimit.left = targetLimit.left; \n //راست المان را بروز رسانی کن\n domLimit.right = domLimit.left + domLimit.width;\n //اگر المان از سمت راست صفحه بیرون زد سمت چپ المان را با پهنای المان ست کن\n if(domLimit.right > pageLimit.right){domLimit.left = pageLimit.right - domLimit.width;}\n }\n //اگر المان از سمت پایین صفحه بیرون زد\n if(domLimit.bottom > pageLimit.bottom){\n if(domLimit.height > targetLimit.top - pageLimit.top){domLimit.top = pageLimit.bottom - domLimit.height;} \n else{domLimit.top = targetLimit.top - domLimit.height;}\n }\n else{domLimit.top = targetLimit.bottom;}\n let overflowY;\n if(domLimit.height > pageLimit.bottom - pageLimit.top){\n domLimit.top = 6;\n domLimit.bottom = undefined;\n domLimit.height = pageLimit.bottom - pageLimit.top - 12;\n overflowY = 'auto';\n }\n let finalStyle = {left:domLimit.left,top:domLimit.top,width:domLimit.width,overflowY,...style}\n return fixStyle(finalStyle,{targetLimit,pageLimit})\n }\n }\n return $$.align();\n}","import Axios from \"axios\";\nimport AIODate from \"./../../npm/aio-date/aio-date\";\nimport AIOStorage from './../../npm/aio-storage/aio-storage';\nimport AIOPopup from \"../aio-popup/aio-popup\";\nimport './index.css';\nimport $ from \"jquery\";\nexport let helper = {\n showAlert(obj = {}){\n let inst = new AIOPopup();\n inst.addAlert(obj)\n },\n getDateAndTime(value){\n try{\n let res = AIODate().toJalali({date:value});\n let miliseconds = AIODate().getTime({date:value})\n let [year,month,day,hour,minute] = res;\n let date = `${year}/${month}/${day}`;\n let time = `${hour}:${minute}`;\n let delta = AIODate().getDelta({date:value});\n let remainingTime = delta.type === 'passed'?{day:0,hour:0,minute:0,second:0}:delta;\n let passedTime = delta.type === 'remaining'?{day:0,hour:0,minute:0,second:0}:delta;\n return {date,time,dateAndTime:`${date} ${time}`,remainingTime,passedTime,miliseconds}\n }\n catch{\n return {date:'',time:'',dateAndTime:'',remainingTime:0,passedTime:0,miliseconds:0}\n }\n },\n arabicToFarsi(value){\n try{return value.replace(/ك/g, \"ک\").replace(/ي/g, \"ی\");}\n catch{return value}\n }\n}\nexport default function services(obj = {}) {\n let {\n getState,token,loader,id,\n getResponse,\n getMock = ()=>{return {}},\n onCatch = ()=>{},\n getError = ()=>{},\n baseUrl\n } = obj;\n if(typeof id !== 'string'){console.error('aio-storage => id should be an string, but id is:',id); return;}\n return Service({\n getState,token,loader,id,onCatch,getError,baseUrl,\n getResponse:getResponse({getState,token,helper,baseUrl,Axios}),\n getMock:getMock({getState,token,helper,baseUrl}) \n })\n}\nfunction AIOServiceLoading(id){\n return (`\n \n `)\n}\nfunction Service(config) {\n function validate(result,{validation,api,def,name,errorMessage,successMessage,messageTime}){\n name = typeof name === 'function'?name():name;\n name = name || api;\n if(typeof result === 'string'){\n if(errorMessage !== false){\n if(errorMessage === undefined){errorMessage = `${name} با خطا روبرو شد`}\n helper.showAlert({type:'error',text:errorMessage,subtext:result});\n }\n return def === undefined?result:def;\n }\n else{\n if(successMessage){\n successMessage = typeof successMessage === 'function'?successMessage(result):successMessage\n if(successMessage === true){successMessage = ''}\n helper.showAlert({type:'success',text:`${name} با موفقیت انجام شد`,subtext:successMessage,time:messageTime});\n }\n }\n return result;\n }\n function handleLoading({loading = true,loadingParent = 'body',api},state){\n if(loading){\n if(state){\n $(loadingParent).append(typeof config.loader === 'function'?config.loader():AIOServiceLoading(api));\n }\n else{\n let loadingDom = $('#' + api);\n if(!loadingDom.length){loadingDom = $('.aio-service-loading')}\n loadingDom.remove()\n }\n }\n }\n function getFromCache({cache}){\n if (cache) {\n let storage = AIOStorage(config.id);\n return storage.load({name:cache.name,time:cache.time})\n }\n }\n async function getResultByResponse(obj,getMock){//return undefined(getResponse not set) or string(error) or response\n let {\n api,parameter,\n onCatch = config.onCatch,\n getError = config.getError\n } = obj\n try{\n let {\n getResponse = config.getResponse[api]\n } = obj;\n if(!getResponse){\n let error = `aio-service error => missing getResponse function in ${api} api`\n helper.showAlert({type:'error',text:error});\n return error;\n }\n let {response,result,mock} = await getResponse(parameter);\n if(mock && typeof getMock === 'function'){return getMock(parameter);}\n if(response){\n let error = getError(response,obj);\n if(typeof error === 'string'){return error}\n }\n return result\n }\n catch(err){\n let catcheResult = onCatch(err,api);\n if(typeof catcheResult === 'string'){return catcheResult}\n else{return err.message} \n }\n }\n async function fetchData(obj){\n let {\n api,parameter,\n getMock = config.getMock[api]\n } = obj;\n let cache = getFromCache(obj);\n if(cache !== undefined){return cache}\n handleLoading(obj,true);\n if(obj.token){\n let tokenResult = typeof obj.token === 'function'?obj.token():obj.token;\n Axios.defaults.headers.common['Authorization'] = `Bearer ${tokenResult}`;\n }\n else if(config.token){\n let tokenResult = typeof config.token === 'function'?config.token():config.token;\n Axios.defaults.headers.common['Authorization'] = `Bearer ${tokenResult}`;\n }\n let res;\n try{\n let result = await getResultByResponse(obj,getMock); \n if(result === undefined){if(getMock){res = getMock(parameter)}}\n else{res = result;}\n }\n catch(err){\n res = err.message;\n }\n handleLoading(obj,false);\n return res;\n }\n return async (obj) => {\n let { callback,cache,api,onError} = obj;\n if(!api){\n helper.showAlert({type:'error',text:`aio-service error => missing api property`});\n return;\n }\n let result = await fetchData(obj);\n result = validate(result,obj);\n if(cache){AIOStorage(config.id).save({name:cache.name,value:result})}\n if(callback && typeof result !== 'string'){callback(result);}\n if(onError && typeof result === 'string'){onError(result);}\n return result;\n }\n}\n\nexport function RemoveCache(id,name){\n if(id === undefined){return}\n let storage = AIOStorage(id);\n storage.remove({name})\n}\nexport function GetCache(id){\n if(id === undefined){return}\n let storage = AIOStorage(id);\n return storage.getModel()\n}","export default function StorageClass(key){\n if(!key){return}\n let a = {\n init(){\n if(!key){\n console.error('AIOStorage error => AIOStorage should initiate by an string parameter as storage name. example let storage = AIOStorage(\"my storage\")')\n }\n let res = localStorage.getItem('storageClass' + key);\n if(res === undefined || res === null){this.set({list:{},time:{}});}\n else{this.set(JSON.parse(res))}\n },\n set(obj = this.obj){\n this.obj = obj;\n localStorage.setItem('storageClass' + key,JSON.stringify(obj));\n },\n getParentAndTarget(name){\n let arr = name.split('.');\n let target = arr[arr.length - 1];\n arr.pop();\n let parent = this.obj.list;\n for(let i = 0; i < arr.length; i++){\n parent[arr[i]] = parent[arr[i]] || {};\n parent = parent[arr[i]];\n }\n return {parent,target};\n },\n save(obj){\n if(typeof obj !== 'object' || Array.isArray(obj)){\n console.error(`\n AIOStorage error => AIOStorage().save should get an object as parameter. example Storage.save({value:any,name:string,confirm:boolean})\n value (required) (value for save in storage object)\n name (required) (if not set it will set by prompt)\n confirm (optional) (if true method will get confirm from user to overright key on storage object)\n `)\n return;\n }\n let {value,name,confirm} = obj;\n try{value = JSON.parse(JSON.stringify(value))}\n catch{value = value;}\n if(!this.obj){this.init()}\n name = this.getNameByPropmt(name,'Save As');\n if(!name || name === null){return}\n let {parent,target} = this.getParentAndTarget(name);\n if(confirm && parent[target] !== undefined){\n let res = window.confirm('Replace ' + target + ' ?');\n if(!res){this.save({value}); return;}\n }\n parent[target] = value;\n this.obj.time = this.obj.time || {}\n this.obj.time[name] = new Date().getTime()\n this.set();\n },\n getNameByPropmt(name,text){\n if(name){return name}\n return window.prompt(text);\n },\n remove(obj){\n if(typeof obj !== 'object' || Array.isArray(obj)){\n console.error(`\n AIOStorage error => AIOStorage().remove should get an object as parameter. example Storage.remove({name:string,callback:function});\n name (required) (name is key of storage object to remove)\n callback (optional) (callback will call after removing)\n `)\n return;\n }\n let {name,callback = ()=>{}} = obj;\n let list = {};\n let time = {};\n for(let prop in this.obj.list){if(prop !== name){list[prop] = this.obj.list[prop]}}\n for(let prop in this.obj.time){if(prop !== name){time[prop] = this.obj.time[prop]}}\n this.obj.list = list;\n this.obj.time = this.obj.time || {}\n this.obj.time = time;\n this.set();\n callback();\n },\n getList(name = ''){\n let {parent} = this.getParentAndTarget(name)\n return Object.keys(parent)\n },\n getTime(name){return this.obj.time[name] || new Date().getTime()},\n load(obj){\n if(typeof obj !== 'object' || Array.isArray(obj) || typeof obj.name !== 'string'){\n console.error(`\n AIOStorage error => AIOStorage().remove should get an object as parameter. example Storage.remove({name:string,def:any,time:number});\n name (required) (name is key of storage object to load)\n def (optional) (if not found value by name, def will saved by name and Storage.load will return def)\n time (optional) (miliseconds time limit to store in AIOStorage) \n `)\n return;\n }\n let {name,def,time} = obj;\n if(!this.obj){this.init()}\n let {parent,target} = this.getParentAndTarget(name)\n let res = parent[target];\n if(time){\n let thisTime = new Date().getTime();\n let lastTime = this.getTime(name);\n let dif = Math.abs(thisTime - lastTime);\n console.log('dif',dif)\n if(dif > time){\n res = undefined\n }\n }\n if(res === undefined && def !== undefined){\n res = typeof def === 'function'?def():def;\n this.save({value:def,name});\n }\n return res;\n },\n clear(){localStorage.clear(key);},\n reset(){this.set({list:{},time:{}})},\n download({file,name}) {\n name = this.getNameByPropmt(name,'Inter file name');\n if(!name || name === null){return}\n let text = JSON.stringify(file)\n var element = document.createElement('a');\n element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));\n element.setAttribute('download', name);\n element.style.display = 'none'; \n document.body.appendChild(element);\n element.click();\n document.body.removeChild(element);\n },\n export(){\n let name = window.prompt('Please Inter File Name');\n if(name === null || !name){return;}\n this.download(this.obj.list,name)\n },\n read({file,callback = ()=>{}}){\n var fr = new FileReader();\n fr.onload=()=>{\n try{\n callback(JSON.parse(fr.result));\n }\n catch{return;}\n } \n fr.readAsText(file);\n },\n import({file,callback = ()=>{}}){\n this.read({file,callback:(obj)=>{\n if(obj === undefined){return;}\n this.set({list:obj,time:{}});\n callback()\n }})\n }\n }\n a.init();\n return {\n save:a.save.bind(a),\n load:a.load.bind(a),\n getList:a.getList.bind(a),\n getTime:a.getTime.bind(a),\n reset:a.reset.bind(a),\n clear:a.clear.bind(a),\n remove:a.remove.bind(a),\n export:a.export.bind(a),\n read:a.read.bind(a),\n download:a.download.bind(a),\n import:a.import.bind(a)\n }\n }","import $ from 'jquery';\nexport default function AIOSwip({dom,start = ()=>{},move = ()=>{},end = ()=>{},speedX = 1,speedY = 1,stepX = 1,stepY = 1,parameter}){\n let a = {\n init(){\n this.eventHandler(dom,'mousedown',$.proxy(this.mouseDown,this))\n },\n getClient(e){\n let touch = 'ontouchstart' in document.documentElement;\n return touch?{x: e.changedTouches[0].clientX,y:e.changedTouches[0].clientY }:{x:e.clientX,y:e.clientY}\n },\n eventHandler(selector, event, action,type = 'bind'){\n var me = { mousedown: \"touchstart\", mousemove: \"touchmove\", mouseup: \"touchend\" }; \n event = 'ontouchstart' in document.documentElement ? me[event] : event;\n var element = typeof selector === \"string\"?(selector === \"window\"?$(window):$(selector)):selector; \n element.unbind(event, action); \n if(type === 'bind'){element.bind(event, action)}\n },\n getPercentByValue(value,start,end){\n return 100 * (value - start) / (end - start)\n },\n getMousePosition(e){\n let client = this.getClient(e);\n var x = client.x - this.left;\n var y = client.y - this.top;\n var xp = this.getPercentByValue(x,0,this.width);\n var yp = this.getPercentByValue(y,0,this.height);\n return {xp,yp,clientX:client.x,clientY:client.y,x,y}\n },\n mouseDown(e){\n var offset = dom.offset();\n this.width = dom.width();\n this.height = dom.height(); \n this.left = offset.left;\n this.top = offset.top;\n let mp = this.getMousePosition(e)\n this.so = {\n client:{x:mp.clientX,y:mp.clientY}\n };\n let res = start({mousePosition:{...mp},parameter,e});\n if(res === false){return}\n if(Array.isArray(res)){\n let x = res[0];\n let y = res[1]\n this.so.x = x;\n this.so.y = y;\n }\n this.eventHandler('window','mousemove',$.proxy(this.mouseMove,this));\n this.eventHandler('window','mouseup',$.proxy(this.mouseUp,this))\n },\n mouseMove(e){\n let client = this.getClient(e);\n let dx = client.x - this.so.client.x;\n let dy = client.y - this.so.client.y;\n dx = Math.round(dx * speedX)\n dy = Math.round(dy * speedY)\n dx = Math.floor(dx / stepX) * stepX;\n dy = Math.floor(dy / stepY) * stepY;\n if(dx === this.dx && dy === this.dy){return}\n this.dx = dx;\n this.dy = dy;\n let dist = Math.round(Math.sqrt(Math.pow(dx,2) + Math.pow(dy,2)))\n this.dist = dist;\n let x,y;\n if(this.so.x !== undefined && this.so.y !== undefined){\n x = this.so.x + dx;\n y = this.so.y + dy;\n }\n move({dx,dy,dist,x,y,parameter,mousePosition:{...this.getMousePosition(e)},e});\n },\n mouseUp(e){\n this.eventHandler('window','mousemove',this.mouseMove,'unbind');\n this.eventHandler('window','mouseup',this.mouseUp,'unbind');\n end({dx:this.dx,dy:this.dy,dist:this.dist,parameter,e})\n }\n }\n a.init();\n}","import AIODate from './../aio-date/aio-date';\nexport default function AIOValidation(props) {\n let $$ = {\n translate(text){\n if(!text){return text}\n let {lang} = props;\n let dict = {\n 'should be contain':'باید شامل',\n 'should be before':'باید قبل از',\n 'cannot be after':'نمی تواند بعد از',\n 'should be after':'باید بعد از',\n 'cannot be before':'نمی تواند قبل از',\n 'should not be contain':'نمی تواند شامل',\n 'should be less than':'باید کمتر از',\n 'should be more than':'باید بیشتر از',\n 'could not be more than':'نباید بزرگ تر از',\n 'could not be less than':'نباید کوچک تر از',\n 'character(s)':'کاراکتر',\n 'item(s)':'مورد',\n 'should be equal':'باید برابر',\n 'cannot be equal':'نمی تواند برابر'\n }\n return lang === 'fa'?dict[text]:text\n },\n getMessage(target,{be,validation,unit = ''}){\n let [a,b,params = {}] = validation;\n let {title = props.title,target:targetPresentation = target,message} = params;\n if(message){return message}\n return `${title} ${this.translate(be)} ${JSON.stringify(targetPresentation)} ${unit}` + (props.lang === 'fa'?' باشد':'')\n },\n contain(target,validation,value){\n let config = {be:'should be contain',validation};\n if(target === 'number'){\n if(!/\\d/.test(value)){return this.getMessage('number',config)}\n }\n else if(target === 'letter'){\n if(!/[a-zA-Z]/.test(value)){return this.getMessage('letter',config)} \n } \n else if(target === 'uppercase'){\n if(!/[A-Z]/.test(value)){return this.getMessage('uppercase',config)}\n } \n else if(target === 'lowercase'){\n if(!/[a-z]/.test(value)){return this.getMessage('lowercase',config)}\n } \n else if(target === 'symbol'){\n if(!/[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>\\/?]+/.test(value)){\n return this.getMessage('symbol',config)\n }\n }\n else if(typeof target.test === 'function'){\n if(!target.test(value)){return this.getMessage(target.toString(),config)} \n }\n else{\n if(value.indexOf(target) === -1 && target !== undefined){return this.getMessage(target,config)}\n }\n },\n notContain(target,validation,value){\n let config = {be:'should not be contain',validation};\n if(target === 'number'){\n if(/\\d/.test(value)){return this.getMessage('number',config)}\n } \n else if(target === 'letter'){\n if(/[a-zA-Z]/.test(value)){return this.getMessage('letter',config)} \n } \n else if(target === 'uppercase'){\n if(/[A-Z]/.test(value)){return this.getMessage('uppercase',config)}\n } \n else if(target === 'lowercase'){\n if(/[a-z]/.test(value)){return this.getMessage('lowercase',config)}\n }\n else if(target === 'symbol'){\n if(/[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>\\/?]+/.test(value)){\n return this.getMessage('symbol',config)\n }\n }\n else if(typeof target.test === 'function'){\n if(target.test(value)){return this.getMessage(target.toString(),config)} \n } \n else {\n if(value.indexOf(target) !== -1){return this.getMessage(target,config)}\n }\n },\n length(target,validation,value,unit,exact){\n if(exact){return this.getMessage(target,{validation,be:'should be contain',unit})}\n if(value.length !== target){return this.getMessage(target,{validation,be:'should be contain',unit})}\n },\n notLength(target,validation,value,unit,exact){\n if(exact){return this.getMessage(target,{validation,be:'should not be contain',unit})}\n if(value.length === target){return this.getMessage(target,{validation,be:'should not be contain',unit})}\n },\n lengthLess(target,validation,value,unit,exact){\n if(exact){return this.getMessage(target,{validation,be:'should be less than',unit})}\n if(value.length >= target){return this.getMessage(target,{validation,be:'should be less than',unit})}\n },\n lengthLessEqual(target,validation,value,unit,exact){\n if(exact){return this.getMessage(target,{validation,be:'could not be more than',unit})}\n if(value.length > target){return this.getMessage(target,{validation,be:'could not be more than',unit})}\n },\n lengthMore(target,validation,value,unit,exact){\n if(exact){return this.getMessage(target,{validation,be:'should be more than',unit})}\n if(value.length <= target){return this.getMessage(target,{validation,be:'should be more than',unit})}\n },\n lengthMoreEqual(target,validation,value,unit,exact){\n if(exact){return this.getMessage(target,{validation,be:'could not be less than',unit})}\n if(value.length < target){return this.getMessage(target,{validation,be:'could not be less than',unit})}\n },\n equal(target,validation,value,a,exact){\n if(exact){this.getMessage(target,{validation,be:'should be equal'})}\n if(JSON.stringify(value) !== JSON.stringify(target)){\n return this.getMessage(target,{validation,be:'should be equal'})\n }\n },\n not(target,validation,value,a,exact){\n if(exact){return this.getMessage(target,{validation,be:'cannot be equal'})}\n if(JSON.stringify(value) === JSON.stringify(target)){\n return this.getMessage(target,{validation,be:'cannot be equal'})\n }\n },\n dateLess(target,validation,value,a,exact){\n if(exact){return this.getMessage(target,{validation,be:'should be before'})}\n if(AIODate().isGreater(value,target) || AIODate().isEqual(value,target)){\n return this.getMessage(target,{validation,be:'should be before'})\n }\n },\n dateLessEqual(target,validation,value,a,exact){\n if(exact){return this.getMessage(target,{validation,be:'cannot be after'})}\n if(AIODate().isGreater(value,target)){\n return this.getMessage(target,{validation,be:'cannot be after'})\n }\n },\n dateMore(target,validation,value,a,exact){\n if(exact){return this.getMessage(target,{validation,be:'should be after'})}\n if(AIODate().isLess(value,target) || AIODate().isEqual(value,target)){\n return this.getMessage(target,{validation,be:'should be after'})\n }\n },\n dateMoreEqual(target,validation,value,a,exact){\n if(exact){this.getMessage(target,{validation,be:'cannot be before'})}\n if(AIODate().isLess(value,target)){\n return this.getMessage(target,{validation,be:'cannot be before'})\n }\n },\n less(target,validation,value,a,exact){\n if(exact){return this.getMessage(target,{validation,be:'should be less than'})}\n if(typeof value === 'number' && typeof target === 'number' && value >= target){\n return this.getMessage(target,{validation,be:'should be less than'})\n }\n },\n lessEqual(target,validation,value,a,exact){\n if(exact){return this.getMessage(target,{validation,be:'could not be more than'})}\n if(typeof value === 'number' && typeof target === 'number' && value > target){\n return this.getMessage(target,{validation,be:'could not be more than'})\n }\n },\n more(target,validation,value,a,exact){\n if(exact){return this.getMessage(target,{validation,be:'should be more than'})}\n if(typeof value === 'number' && typeof target === 'number' && value <= target){\n return this.getMessage(target,{validation,be:'should be more than'})\n }\n },\n moreEqual(target,validation,value,a,exact){\n if(exact){return this.getMessage(target,{validation,be:'could not be less than'})}\n if(typeof value === 'number' && typeof target === 'number' && value < target){\n return this.getMessage(target,{validation,be:'could not be less than'})\n }\n },\n getResult(fn,target,validation,value,unit){\n target = Array.isArray(target)?target:[target];\n if(Array.isArray(target)){\n let matchedTargets = [];\n let notMatchedTargets = [];\n for(let i = 0; i < target.length; i++){\n let result = this[fn](target[i],validation,value,unit)\n if(!result){matchedTargets.push(target[i])}\n else{notMatchedTargets.push(target[i])}\n }\n if(matchedTargets.length){return}\n // if(notMatchedTargets.length > 3){\n // notMatchedTargets = [notMatchedTargets[0],notMatchedTargets[1],notMatchedTargets[2],'...']\n // }\n return this[fn](notMatchedTargets.join(' or '),validation,value,unit,true)\n }\n else{\n let result = this[fn](target,validation,value,unit)\n if(result){return result}\n }\n \n },\n getValidation(){\n let {lang = 'en',value,validations = []} = props; \n let unit = '';\n if(Array.isArray(value)){unit = this.translate('item(s)')}\n else if(typeof value === 'string'){unit = this.translate('character(s)')}\n for(let i = 0; i < validations.length; i++){\n let [type,target,params = {}] = validations[i];\n let result;\n if(type === 'function'){\n result = target(value);\n }\n else if(type === 'required'){\n if(value === undefined || value === null || value === '' || value === false || value.length === 0){\n let {title = props.title} = params;\n if(lang === 'en'){return `${title} is required`}\n if(lang === 'fa'){return `وارد کردن ${title} ضروری است`}\n }\n }\n else if(type === 'contain'){result = this.getResult('contain',target,validations[i],value)}\n else if(type === '!contain'){result = this.getResult('notContain',target,validations[i],value)}\n else if(type === 'length'){result = this.getResult('length',target,validations[i],value,unit)}\n else if(type === '!length'){result = this.getResult('notLength',target,validations[i],value,unit)}\n else if(type === 'length<'){result = this.getResult('lengthLess',target,validations[i],value,unit)}\n else if(type === 'length<='){result = this.getResult('lengthLessEqual',target,validations[i],value,unit)}\n else if(type === 'length>'){result = this.getResult('lengthMore',target,validations[i],value,unit)}\n else if(type === 'length>='){result = this.getResult('lengthMoreEqual',target,validations[i],value,unit)}\n else if(type === '='){result = this.getResult('equal',target,validations[i],value)}\n else if(type === '!='){result = this.getResult('not',target,validations[i],value)}\n else if(type === '<'){result = this.getResult('less',target,validations[i],value)}\n else if(type === '<='){result = this.getResult('lessEqual',target,validations[i],value)}\n else if(type === '>'){result = this.getResult('more',target,validations[i],value)}\n else if(type === '>='){result = this.getResult('moreEqual',target,validations[i],value)}\n else if(type === 'date<'){result = this.getResult('dateLess',target,validations[i],value)}\n else if(type === 'date<='){result = this.getResult('dateLessEqual',target,validations[i],value)}\n else if(type === 'date>'){result = this.getResult('dateMore',target,validations[i],value)}\n else if(type === 'date>='){result = this.getResult('dateMoreEqual',target,validations[i],value)}\n if(result){return result}\n }\n return ''\n }\n }\n props.translate = props.translate || function (text){\n return text\n }\n props.lang = props.lang || 'en';\n let validation;\n try{validation = $$.getValidation()}\n catch{validation = ''}\n return validation; \n }\n","import React, { Component, useEffect, useRef, useState, createRef } from \"react\";\nimport RVD from './../../npm/react-virtual-dom/react-virtual-dom';\nimport Axios from 'axios';\nimport { Icon } from '@mdi/react';\nimport { mdiClose, mdiCrosshairsGps, mdiLoading, mdiMagnify } from '@mdi/js';\nimport $ from 'jquery';\nimport \"./index.css\";\n\nexport default class Map extends Component {\n constructor(props) {\n super(props);\n let { latitude = 35.699739, longitude = 51.338097 } = props;\n this.state = { latitude, longitude,prevLatitude:props.latitude,prevLongitude:props.longitude, delay: props.delay }\n }\n ipLookUp() {\n $.ajax('http://ip-api.com/json')\n .then(\n (response) => {\n let { lat, lon } = response;\n this.flyTo(lat, lon)\n },\n\n (data, status) => {\n console.log('Request failed. Returned status of', status);\n }\n );\n }\n handlePermission() {\n navigator.permissions.query({ name: 'geolocation' }).then((result) => {\n if (result.state === 'granted') {\n console.log(result.state);\n }\n else if (result.state === 'prompt') {\n console.log(result.state);\n }\n else if (result.state === 'denied') {\n console.log(result.state);\n }\n });\n }\n goToCurrentPoint() {\n if (\"geolocation\" in navigator) {\n this.handlePermission();\n // check if geolocation is supported/enabled on current browser\n navigator.geolocation.getCurrentPosition(\n (position) => {\n let { latitude, longitude } = position.coords;\n this.apis.flyTo(latitude, longitude);\n },\n (error_message) => this.ipLookUp()\n )\n }\n else { this.ipLookUp() }\n }\n setCoords({ latitude, longitude }) {\n clearTimeout(this.timeout);\n this.timeout = setTimeout(() => {\n let {onChange = ()=>{}} = this.props;\n this.setState({ latitude, longitude });\n onChange(latitude,longitude)\n }, 500);\n }\n flyTo(lat, lng) {\n this.map.flyTo([lat, lng], 18);\n this.setState({ latitude: lat, longotude: lng })\n }\n panTo(lat, lng) {\n this.map.panTo({ lat, lng })\n this.setState({ latitude: lat, longitude: lng })\n }\n footer_layout() {\n let { onSubmit } = this.props;\n if (!onSubmit) { return null }\n let { latitude, longitude } = this.state;\n return (\n this.goToCurrentPoint()} />, align: 'vh' },\n { flex: 1, html: }\n ]\n },\n ]\n }}\n />\n )\n }\n componentDidMount(){\n let {delay} = this.state;\n if(!delay){return}\n setTimeout(()=>{\n this.setState({delay:false})\n },delay)\n }\n render() {\n let {\n changeView, zoom = 12, onClick, style, search,\n apiKey = 'web.3037ddd42c9e4173af6427782584a2a1',\n onChange,\n onSubmit\n } = this.props;\n let { latitude, longitude, delay,prevLatitude,prevLongitude } = this.state;\n if(this.props.latitude !== prevLatitude || this.props.longitude !== prevLongitude){\n let { latitude = 35.699739, longitude = 51.338097 } = this.props;\n setTimeout(()=>this.setState({latitude,longitude,prevLatitude:latitude,prevLongitude:longitude}),0)\n }\n if (delay) { return null }\n return (\n \n {\n console.log('msf')\n }}\n onInit={(L, myMap) => {\n this.map = myMap;\n this.marker = L.marker([latitude, longitude])\n .addTo(myMap)\n .bindPopup('I am a popup.');\n if (onClick) {\n myMap.on('click', (e) => onClick());\n }\n if (onChange || onSubmit) {\n myMap.on('move', (e) => {\n //marker.setLatLng(e.target.getCenter())\n let { lat, lng } = e.target.getCenter()\n this.marker.setLatLng({ lat, lng })\n this.setCoords({ latitude: lat, longitude: lng })\n });\n myMap.on('click', (e) => {\n //marker.setLatLng(e.target.getCenter())\n let { lat, lng } = e.latlng\n this.panTo(lat, lng);\n });\n }\n\n // L.circle([35.699739, 51.338097], {\n // color: 'dodgerblue',\n // fillColor: 'dodgerblue',\n // fillOpacity: 0.5,\n // radius: 1500\n // }).addTo(myMap);\n }}\n style={{ position: 'absolute', left: 0, top: 0, width: '100%', height: '100%', zIndex: 0 }}\n />\n {this.footer_layout()}\n {\n search &&\n this.flyTo(lat, lng)}\n />\n }\n
\n )\n }\n}\nclass MapSearch extends Component {\n constructor(props) {\n super(props);\n this.dom = createRef()\n this.state = { searchValue: '', searchResult: [], loading: false, showResult: false }\n }\n async changeSearch(searchValue) {\n let { latitude, longitude } = this.props;\n this.setState({ searchValue });\n\n clearTimeout(this.timeout);\n this.timeout = setTimeout(async () => {\n let param = {\n headers: {\n 'Api-Key': 'service.8f13cd0a4d2442399a3d690d26e993ed',\n 'Authorization': undefined\n }\n }\n let url = `https://api.neshan.org/v1/search?term=${searchValue}&lat=${latitude}&lng=${longitude}`;\n this.setState({ loading: true })\n let res = await Axios.get(url, param);\n this.setState({ loading: false })\n if (res.status !== 200) { return }\n this.setState({ searchResult: res.data.items })\n }, 1000)\n }\n space_layout(type) {\n let { searchResult, showResult } = this.state;\n if (type === 'last') {\n if (!searchResult || !searchResult.length || !showResult) { return false }\n }\n let layout = { onClick: () => this.setState({ showResult: false }) };\n if (type === 'first') { layout.size = 12; }\n else { layout.flex = 1; }\n return layout;\n }\n input_layout() {\n let { searchValue, loading, showResult, searchResult } = this.state;\n let showCloseButton = !!showResult && !!searchResult.length;\n let showLoading = !!loading;\n return {\n className: 'p-h-12',\n row: [\n {\n align: 'h', flex: 1,\n html: (\n this.changeSearch(e.target.value)}\n onClick={() => this.setState({ showResult: true })}\n style={{\n width: '100%', padding: '0 12px', height: 36,\n boxSizing: 'border-box', borderRadius: 4, fontFamily: 'inherit', outline: 'none', border: 'none'\n }}\n type='text' placeholder='جستجو'\n />\n )\n },\n {\n size: 36, show: showLoading, align: 'vh', style: { color: '#888', background: '#fff' },\n html: \n },\n {\n size: 36, show: showCloseButton, align: 'vh', style: { color: '#888', background: '#fff' },\n html: this.setState({ showResult: false })} />\n },\n {\n size: 36, show: !showCloseButton && !showLoading, align: 'vh', style: { color: '#888', background: '#fff' },\n html: \n }\n ]\n }\n }\n result_layout() {\n let { searchResult, showResult } = this.state;\n if (!searchResult || !searchResult.length || !showResult) { return false }\n let { onClick } = this.props;\n return {\n style: { background: 'rgba(255,255,255,0.95)', height: 'fit-content', maxHeight: 400 },\n className: 'm-h-12 p-v-12 ofy-auto m-t-3 br-4', gap: 3,\n column: searchResult.map(({ title, address, location }) => {\n return {\n onClick: () => {\n this.setState({ showResult: false });\n onClick(location.y, location.x, title)\n },\n column: [\n {\n html: title, className: 'p-h-12 fs-12', align: 'v'\n },\n { html: address, className: 'p-h-12 fs-10', align: 'v', style: { opacity: 0.5 } }\n ]\n }\n })\n }\n }\n render() {\n let { searchResult, showResult } = this.state;\n let isOpen = true;\n if (!searchResult || !searchResult.length || !showResult) { isOpen = false }\n return (\n \n )\n }\n}\nconst BASE_URL = \"https://static.neshan.org\";\nconst DEFAULT_URL = `${BASE_URL}/sdk/leaflet/1.4.0/leaflet.js`;\nfunction NeshanLoader(props) {\n const createScript = () => {\n const { onError, onLoad } = props;\n const script = document.createElement(\"script\");\n\n script.src = DEFAULT_URL;\n\n script.onload = () => {\n if (onLoad) onLoad();\n return;\n };\n\n script.onerror = () => {\n if (onError) onError();\n return;\n };\n\n document.body.appendChild(script);\n };\n\n return createScript();\n};\nconst NeshanMap = (props) => {\n const { style, options, onInit } = props;\n const mapEl = useRef(null);\n const [init, setInit] = useState(false)\n\n const defaultStyle = {\n width: \"600px\",\n height: \"450px\",\n margin: 0,\n padding: 0,\n background: \"#eee\",\n };\n\n const defaultOptions = {\n key: \"YOUR_API_KEY\",\n maptype: \"dreamy\",\n poi: true,\n traffic: false,\n center: [35.699739, 51.338097],\n zoom: 14,\n };\n\n useEffect(() => {\n if (init) { return }\n setInit(true)\n NeshanLoader({\n onLoad: () => {\n let map = new window.L.Map(mapEl.current, { ...defaultOptions, ...options });\n if (onInit) onInit(window.L, map);\n },\n onError: () => {\n console.error(\"Neshan Maps Error: This page didn't load Neshan Maps correctly\");\n },\n });\n });\n return ;\n};\n\nexport function getDistance(p1,p2) {\n let {latitude:lat1,longitude:lon1} = p1;\n let {latitude:lat2,longitude:lon2} = p2;\n let rad = Math.PI / 180;\n let radius = 6371; //earth radius in kilometers\n return Math.acos(Math.sin(lat2 * rad) * Math.sin(lat1 * rad) + Math.cos(lat2 * rad) * Math.cos(lat1 * rad) * Math.cos(lon2 * rad - lon1 * rad)) * radius; //result in Kilometers\n}","import React, { Component } from 'react';\nimport AIOStorage from './../../npm/aio-storage/aio-storage';\nimport { Icon } from '@mdi/react';\nimport { mdiMenu, mdiChevronRight, mdiChevronLeft, mdiChevronDown } from '@mdi/js';\nimport RVD from './../../npm/react-virtual-dom/react-virtual-dom';\nimport AIOPopup from '../aio-popup/aio-popup';\nimport $ from 'jquery';\nimport './react-super-app.css';\nexport default class RSA {\n constructor(props = {}) {\n let { rtl, maxWidth } = props;\n this.rtl = rtl;\n this.maxWidth = maxWidth;\n this.popup = new AIOPopup({ rtl })\n }\n render = (props) => {\n return (\n <>\n {\n this.getNavId = getNavId;\n this.setNavId = setNavId;\n this.openSide = openSide;\n this.closeSide = closeSide;\n }}\n />\n >\n )\n }\n addModal = (obj) => this.popup.addModal(obj);\n removeModal = (obj) => this.popup.removeModal(obj);\n addSnakebar = (obj) => this.popup.addSnakebar(obj);\n}\nclass ReactSuperApp extends Component {\n constructor(props) {\n super(props);\n let { touch = 'ontouchstart' in document.documentElement, splash, splashTime = 7000 } = props;\n this.storage = AIOStorage('rsa-cache');\n window.oncontextmenu = function (event) {\n event.preventDefault();\n event.stopPropagation();\n return false;\n };\n this.state = {\n navId: this.initNavId(),\n splash,\n showSplash: true,\n confirm: false,\n touch,\n changeTheme: (index) => {\n let { themes } = props;\n this.theme = this.theme || 0;\n if (index === 'init') {\n this.theme = this.storage.load({ name: 'theme', value: 0 });\n }\n else if (typeof (index) === 'number') {\n this.theme = index;\n }\n else {\n this.theme++;\n }\n this.storage.save({ value: this.theme, name: 'theme' });\n if (this.theme > themes.length - 1) { this.theme = 0 }\n let target;\n try {\n target = themes[this.theme] || {};\n }\n catch { target = {} }\n for (let prop in target) {\n document.documentElement.style.setProperty(prop, target[prop]);\n }\n\n },\n openSide:this.openSide.bind(this),\n closeSide:this.closeSide.bind(this),\n setNavId: this.setNavId.bind(this),\n getNavId:this.getNavId.bind(this)\n }\n if (props.themes) { this.state.changeTheme('init') }\n if (splash) { setTimeout(() => this.setState({ splash: false }), splashTime) }\n props.getActions({ ...this.state })\n }\n getNavId(){return this.state.navId}\n setNavId(navId){this.setState({navId})}\n initNavId() {\n let { navs, navId } = this.props;\n if (!navs) { return false }\n if (navId) {\n let res = this.getNavById(navId);\n if (res !== false) { return navId }\n }\n if (!navs.length) { return false }\n return navs.filter(({ show = () => true }) => show())[0].id;\n }\n header_layout(nav) {\n let { header,headerContent, side, title = () => nav.text } = this.props;\n if (header === false) { return false }\n if(typeof header === 'function'){\n return {\n style: { flex: 'none', width: '100%' }, align: 'v', className: 'rsa-header of-visible',\n html: header()\n }\n }\n return {\n style: { flex: 'none', width: '100%' }, align: 'v', className: 'rsa-header of-visible',\n row: [\n { size: 60, show: !!side, html: , align: 'vh', attrs: { onClick: () => this.openSide() } },\n { show: title !== false, html: () => title(nav), className: 'rsa-header-title' },\n { flex: 1, show: !!headerContent, html: () => headerContent(), className: 'of-visible' },\n ]\n }\n }\n getNavById(id) {\n let { navs } = this.props;\n this.res = false;\n this.getNavById_req(navs, id);\n return this.res;\n }\n getNavById_req(navs, id) {\n if (this.res) { return; }\n for (let i = 0; i < navs.length; i++) {\n if (this.res) { return; }\n let nav = navs[i];\n let { show = () => true } = nav;\n if (!show()) { continue }\n if (nav.id === id) { this.res = nav; break; }\n if (nav.navs) { this.getNavById_req(nav.navs, id); }\n }\n }\n getMainClassName() {\n let { rtl, className: cls } = this.props;\n let className = 'rsa-main';\n className += cls ? ' ' + cls : '';\n className += rtl ? ' rtl' : ' ltr';\n return className;\n }\n navigation_layout(type) {\n let { navs = [], navHeader, rtl } = this.props;\n if (!navs.length) { return false }\n let { navId } = this.state;\n let props = { navs, navHeader, navId, setNavId: (navId) => this.setNavId(navId), type, rtl }\n return { className: 'of-visible', html: () };\n }\n page_layout(nav) {\n let { body = () => '' } = this.props;\n let content = body(this.state);\n return {\n flex: 1,\n column: [\n this.header_layout(nav),\n { flex: 1, html: {content}
},\n this.navigation_layout('bottom')\n ]\n }\n }\n\n renderMain() {\n let { navId } = this.state;\n let { navs, style } = this.props;\n let nav = navs ? this.getNavById(navId) : false;\n let layout = { style, className: this.getMainClassName() }\n layout.row = [this.navigation_layout('side'), this.page_layout(nav)]\n return ()\n }\n openSide() {\n let { popup, rtl } = this.props;\n popup.addModal({\n position: rtl ? 'right' : 'left', id: 'rsadefaultsidemodal',\n backdrop:{attrs:{className:'rsa-sidemenu-backdrop'}},\n body: { render: ({ close }) => this.renderSide(close) },\n })\n }\n closeSide(){\n let { popup } = this.props;\n popup.removeModal('rsadefaultsidemodal')\n }\n renderSide(close) {\n let { side = {}, rtl } = this.props;\n return close()} />\n }\n render() {\n let { splash } = this.state;\n let { style, className, maxWidth, popup } = this.props;\n return (\n \n
\n {this.renderMain()},\n {popup.render()}\n {splash && splash()}\n
\n
\n );\n }\n}\nclass Navigation extends Component {\n state = { openDic: {} }\n header_layout() {\n let { navHeader } = this.props;\n if (!navHeader) { return { size: 12 } }\n return { html: navHeader() };\n }\n items_layout(navs, level) {\n return {\n flex: 1, className: 'ofy-auto',\n column: navs.filter(({ show = () => true }) => show()).map((o, i) => {\n if (o.navs) {\n let { openDic } = this.state;\n let open = openDic[o.id] === undefined ? true : openDic[o.id]\n let column = [this.item_layout(o, level)]\n if (open) { column.push(this.items_layout(o.navs, level + 1)) }\n return { gap: 12, column }\n }\n return this.item_layout(o, level)\n })\n }\n }\n toggle(id) {\n let { openDic } = this.state;\n let open = openDic[id] === undefined ? true : openDic[id]\n this.setState({ openDic: { ...openDic, [id]: !open } })\n }\n item_layout(o, level = 0) {\n let { setNavId, navId, rtl } = this.props;\n let { openDic } = this.state;\n let { id, icon, navs } = o;\n let text = typeof o.text === 'function' ? o.text() : o.text;\n let active = id === navId;\n let open = openDic[id] === undefined ? true : openDic[id]\n return {\n className: 'rsa-navigation-item' + (active ? ' active' : ''), attrs: { onClick: () => navs ? this.toggle(id) : setNavId(id) },\n row: [\n { size: level * 16 },\n { show: navs !== undefined, size: 24, html: navs ? : '', align: 'vh' },\n { show: !!icon, size: 48, html: () => typeof icon === 'function' ? icon(active) : icon, align: 'vh' },\n { html: text, align: 'v' }\n ]\n }\n }\n bottomMenu_layout({ icon, text, id }) {\n let { navId, setNavId } = this.props;\n let active = id === navId;\n return {\n flex: 1, className: 'rsa-bottom-menu-item of-visible' + (active ? ' active' : ''), attrs: { onClick: () => setNavId(id) },\n column: [\n { flex: 2 },\n { show: !!icon, html: () => typeof icon === 'function' ? icon(active) : icon, align: 'vh', className: 'of-visible' },\n { flex: 1 },\n { html: text, align: 'vh', className: 'rsa-bottom-menu-item-text' },\n { flex: 1 }\n ]\n }\n }\n render() {\n let { type, navs } = this.props;\n if (type === 'bottom') {\n return ( true }) => show()).map((o) => this.bottomMenu_layout(o)) }} />)\n }\n return ();\n }\n}\nclass SideMenu extends Component {\n header_layout() {\n let { header } = this.props;\n if (!header) { return false }\n return { html: header(), className: 'rsa-sidemenu-header' };\n }\n items_layout() {\n let { items, onClose } = this.props;\n return {\n flex: 1, gap: 12,\n column: items.map((o, i) => {\n let { icon = () => , text, id, className, onClick = () => { }, show = () => true } = o;\n let Show = show();\n return {\n show: Show !== false, size: 36, className: 'rsa-sidemenu-item' + (className ? ' ' + className : ''), onClick: () => { onClick(o); onClose() },\n row: [\n { size: 48, html: typeof icon === 'function'?icon():icon, align: 'vh' },\n { html: text, align: 'v' }\n ]\n }\n })\n }\n }\n footer_layout() {\n let { footer } = this.props;\n if (!footer) { return false }\n return { html: footer(), className: 'rsa-sidemenu-footer' };\n }\n componentDidMount() {\n setTimeout(() => this.setState({ open: true }), 0)\n }\n render() {\n let { attrs = {} } = this.props;\n return (\n \n );\n }\n}\n","import React,{Component,Fragment} from \"react\";\nimport $ from 'jquery';\nimport \"./index.css\";\nlet RVDCLS = {\n rvd:'rvd',pointer:'rvd-pointer',gap:'rvd-gap',justify:'rvd-justify',align:'rvd-align',\n row:'rvd-row',column:'rvd-column',hidexs:'rvd-hide-xs',hidesm:'rvd-hide-sm',hidemd:'rvd-hide-md',hidelg:'rvd-hide-lg'\n}\nexport default class ReactVirtualDom extends Component {\n getClassName(pointer,isRoot,props){\n let className = RVDCLS.rvd;\n if(isRoot){className += ' rvd-root'}\n if(props.className){className += ' ' + props.className}\n if(pointer){ className += ' ' + RVDCLS.pointer;}\n if(props.align === 'v'){className += ' ' + (props.column?RVDCLS.justify:RVDCLS.align);}\n else if(props.align === 'h'){className += ' ' + (props.column?RVDCLS.align:RVDCLS.justify);}\n else if(props.align === 'vh'){className += ` ${RVDCLS.justify} ${RVDCLS.align}`;}\n if(props.row){className += ' ' + RVDCLS.row}\n else if(props.column || props.grid){className += ' ' + RVDCLS.column}\n let hideClassName = getHideClassName(props)\n return className + (hideClassName?' ' + hideClassName:'');\n }\n getProps(obj,index,parent = {},isRoot){\n let {htmls = {}} = this.props;\n let {childsProps = ()=>{return {}}} = parent;\n let Props = (typeof childsProps === 'function'?childsProps(obj,index):childsProps) || {};\n let props = {...Props,...obj}\n let {swapId,size,flex,onClick,html,style,longTouch} = props; \n let attrs = obj.attrs || Props.attrs || {};\n let pointer = !!onClick || !!attrs.onClick;\n let childs = [];\n html = typeof html === 'function'?html():html;\n if(typeof html === 'string' && htmls[html]){\n html = htmls[html](obj)\n }\n let dataId = 'a' + Math.random();\n style = {...attrs.style,...style}\n if(parent.row){\n if(size !== undefined){style.width = size; flex = undefined}\n }\n else if(parent.column || parent.grid){\n if(size !== undefined){style.height = size; flex = undefined}\n }\n if(obj.row){childs = typeof obj.row === 'function'?obj.row():obj.row;}\n else if(obj.column){childs = typeof obj.column === 'function'?obj.column():obj.column}\n else if(obj.grid){\n let {gridCols = 2} = obj;\n let grid = typeof obj.grid === 'function'?obj.grid():obj.grid;\n for(let i = 0; i < grid.length; i+=gridCols){\n let row = [];\n let gridRow = typeof obj.gridRow === 'function'?obj.gridRow(i):obj.gridRow;\n for(let j = i; j < i + gridCols; j++){\n if(grid[j]){row.push(grid[j])}\n } \n childs.push({\n row:[...row],...gridRow\n })\n }\n obj.column = [...childs]\n }\n let className = this.getClassName(pointer,isRoot,props);\n let gapAttrs = getGapAttrs(obj,parent,props,dataId)\n if(swapId !== undefined){\n attrs.draggable = true;\n attrs.onDragStart = (e)=>{\n let {swapHandleClassName} = this.props;\n if(swapHandleClassName){\n if(!$(e.target).hasClass(swapHandleClassName) && $(e.target).parents('.' + swapHandleClassName).length === 0){return;}\n }\n this.swapId = swapId;\n }\n attrs.onDragOver = (e)=>e.preventDefault();\n attrs.onDrop = ()=>{\n let {onSwap = ()=>{}} = this.props;\n if(this.swapId === swapId){return;}\n onSwap(this.swapId,swapId);\n this.swapId = false\n }\n } \n attrs = {onClick,...attrs,style:{flex,...style},className,'data-id':dataId};\n if(props.egg){attrs.onClick = ()=>this.egg(props.egg)}\n if(longTouch){\n attrs['ontouchstart' in document.documentElement?'onTouchStart':'onMouseDown'] = (e)=>{\n this.lt = dataId;\n this[dataId + 'callback'] = longTouch;\n this.timer()\n eventHandler('mouseup',$.proxy(this.longTouchMouseUp,this));\n }\n }\n if(this.props.loading && html){\n html = (\n <>\n {html}
\n \n >\n )\n attrs.onClick = undefined\n }\n return {childs,html,attrs,gapAttrs}\n }\n getLayout(obj,index,parent,isRoot){\n if(typeof obj === 'object' && typeof parent === 'object'){obj.props = {...parent.props,...obj.props}}\n let {getLayout} = this.props;\n if(!obj || obj === null || (typeof obj.show === 'function'?obj.show():obj.show) === false){return ''}\n if(getLayout){obj = getLayout(obj,parent)}\n let {childs,html,attrs,gapAttrs} = this.getProps(obj,index,parent,isRoot)\n return (\n \n \n {childs.length?childs.map((o,i)=>{this.getLayout(o,i,obj,false)}):html}\n
\n {parent && (parent.gap !== undefined || (parent.props && parent.props.gap !== undefined)) && }\n \n ) \n }\n egg({callback = ()=>{},count = 10}){\n this.eggCounter++;\n if(this.eggCounter >= count){callback()}\n clearTimeout(this.timeOut);\n this.timeOut = setTimeout(()=>this.eggCounter = 0,500)\n }\n longTouchMouseUp(){\n eventHandler('mouseup',this.longTouchMouseUp,'unbind');\n clearInterval(this[this.lt + 'interval']);\n }\n timer(){\n this.time = 0;\n this[this.lt + 'interval'] = setInterval(()=>{\n this.time++;\n if(this.time > 50){\n clearInterval(this[this.lt + 'interval']);\n this[this.lt + 'callback']()\n }\n },10)\n }\n \n render(){\n var {gap,layout} = this.props;\n return this.getLayout(layout,0,undefined,true);\n }\n}\nReactVirtualDom.defaultProps = {gap:0,layout:{}};\n\nexport function RVDRemoveV(selector,callback){\n $(selector).animate({opacity:0},100).animate({height:0,padding:0},150,callback);\n}\nexport function RVDRemoveH(selector,callback){\n $(selector).animate({opacity:0},100).animate({width:0,padding:0},150,callback);\n}\nexport function RVDRemove(selector,callback){\n $(selector).animate({opacity:0},200,callback);\n}\nfunction eventHandler(event, action,type = 'bind'){\n event = 'ontouchstart' in document.documentElement ? { mousemove: \"touchmove\", mouseup: \"touchend\" }[event] : event;\n $(window).unbind(event, action);\n if(type === 'bind'){$(window).bind(event, action)}\n}\nfunction getGapAttrs(obj,parent = {},props = {},dataId){\n let $$ = {\n getClient(e){return 'ontouchstart' in document.documentElement?{x:e.changedTouches[0].clientX,y:e.changedTouches[0].clientY}:{x:e.clientX,y:e.clientY}},\n mouseMove(e){\n var {rtl} = this.props;\n var {pos,axis,size,dataId} = this.so;\n var client = this.getClient(e);\n var offset = (client[axis] - pos[axis]) * (rtl?-1:1);\n if(offset % 24 !== 0){return}\n this.so.newSize = offset + size;\n var panel = $('[data-id=\"'+dataId+'\"]');\n panel.css({[{'x':'width','y':'height'}[axis]]:this.so.newSize})\n },\n mouseUp(){\n eventHandler('mousemove',this.mouseMove,'unbind');\n eventHandler('mouseup',this.mouseUp,'unbind');\n var {onResize,newSize} = this.so;\n onResize(newSize);\n },\n getGap(obj,parent,dir){\n let gap = parent['gap' + dir] || parent.gap || (parent.props?parent.props['gap' + dir] || parent.props.gap:undefined)\n return typeof gap === 'function'?gap(obj,parent):gap;\n },\n getClassName(){\n let className = RVDCLS.gap;\n if(parent.gapAttrs && parent.gapAttrs.className){className += ' ' + parent.gapAttrs.className}\n let hideClassName = getHideClassName(props)\n return className + (hideClassName?' ' + hideClassName:'');\n },\n getGapAttrs(){\n let {size,onResize} = props;\n let style = {},axis;\n if(parent.row){\n axis = 'x';\n style.width = this.getGap(obj,parent,'H');\n if(size && onResize){style.cursor = 'col-resize';}\n }\n else if(parent.column || parent.grid){\n axis = 'y'\n style.height = this.getGap(obj,parent,'V');\n if(size && onResize){style.cursor = 'row-resize';}\n }\n else {return {}}\n if(parent.gapAttrs && parent.gapAttrs.style){style = {...style,...parent.gapAttrs.style}}\n let gapAttrs = {\n className:this.getClassName(),style,draggable:false,\n onDragStart:(e)=>{e.preventDefault(); return false}\n };\n if(size && onResize){\n gapAttrs['ontouchstart' in document.documentElement?'onTouchStart':'onMouseDown'] = (e)=>{\n this.so = {pos:this.getClient(e),onResize,axis,size,dataId};\n eventHandler('mousemove',$.proxy(this.mouseMove,this));\n eventHandler('mouseup',$.proxy(this.mouseUp,this));\n }\n }\n return gapAttrs;\n }\n } \n return $$.getGapAttrs()\n}\nfunction getHideClassName(props){\n let hide_xs,hide_sm,hide_md,hide_lg,className; \n if(props.show_xs){hide_xs = false; hide_sm = true; hide_md = true; hide_lg = true;}\n if(props.hide_xs){hide_xs = true;}\n if(props.show_sm){hide_xs = true; hide_sm = false; hide_md = true; hide_lg = true;}\n if(props.hide_sm){hide_sm = true;}\n if(props.show_md){hide_xs = true; hide_sm = true; hide_md = false; hide_lg = true;}\n if(props.hide_md){hide_md = true;}\n if(props.show_lg){hide_xs = true; hide_sm = true; hide_md = true; hide_lg = false;}\n if(props.hide_lg){hide_lg = true;}\n if(hide_xs){className += ' ' + RVDCLS.hidexs;}\n if(hide_sm){className += ' ' + RVDCLS.hidesm;}\n if(hide_md){className += ' ' + RVDCLS.hidemd;}\n if(hide_lg){className += ' ' + RVDCLS.hidelg;}\n return className;\n}","import React,{Component} from \"react\";\nimport RVD from './../react-virtual-dom/react-virtual-dom';\nimport AIOInput from \"../aio-input/aio-input\";\nimport {Icon} from \"@mdi/react\";\nimport { mdiDeleteOutline, mdiHistory, mdiMagnify } from \"@mdi/js\";\nimport './search-box.css';\nexport default class SearchBox extends Component{\n constructor(props){\n super(props);\n this.state = {\n searchValue:props.value || '',\n historyMode:props.historyMode,\n historyList:[]\n }\n }\n async getHistory(){\n let {history} = this.props;\n if(!history){return false}\n this.setState({historyList:await history.get()})\n }\n componentDidMount(){\n this.getHistory()\n }\n change(searchValue){\n let {onChange} = this.props;\n if(!onChange){return}\n this.setState({searchValue});\n clearTimeout(this.timeout);\n this.timeout = setTimeout(()=>onChange(searchValue),800)\n }\n icon_layout(){\n return {\n className:'search-box-icon',\n align:'vh',\n html:\n }\n }\n input_layout(){\n let {searchValue} = this.state;\n return {\n flex:1,\n html:(\n this.change(e.target.value)}\n placeholder=\"جستجو\"\n />\n )\n }\n }\n history_layout(){\n let {historyList} = this.state;\n return {\n column:[\n {\n html:'تاریخچه جستجو',align:'v',className:'search-box-label'\n },\n {\n flex:1,className:'ofy-auto',column:historyList.map((text)=>this.historyItem_layout(text))\n }\n ]\n }\n }\n removeHistory(text){\n let {historyList} = this.state;\n let newHistoryList = historyList.filter((o)=>o !== text)\n this.setState({historyList:newHistoryList})\n }\n historyItem_layout(text){\n let {history} = this.props;\n return {\n size:36,className:'search-box-history-item',\n row:[\n {\n flex:1,onClick:()=>this.change(text),\n row:[\n {size:36,html:,align:'vh'},\n {flex:1,html:text,align:'v'}\n ]\n },\n {\n size:36,html:,align:'vh',\n onClick:async ()=>{\n let res = await history.remove(text);\n if(res === true){this.removeHistory(text)}\n }\n }\n ]\n }\n }\n historyModeRender(){\n return (\n }\n style={{width:'100%',justifyContent:'flex-start'}}\n popOver={()=>this.renderPopup()}\n />\n )\n }\n renderPopup(){\n return (\n \n )\n }\n renderSearchBox(){\n return (\n \n )\n }\n render(){\n let {history,onClick} = this.props;\n return (\n \n {history && this.historyModeRender()}\n {!history && this.renderSearchBox()}\n
\n )\n }\n}\n\n\n","import React,{Component} from \"react\";\nimport RVD from './../npm/react-virtual-dom/react-virtual-dom';\nimport AppContext from \"../app-context\";\nimport { Icon } from '@mdi/react';\nimport { mdiChevronRight } from \"@mdi/js\";\nexport default class PopupHeader extends Component {\n static contextType = AppContext;\n onClose() {\n let { rsa } = this.context;\n rsa.removeModal();\n }\n render() {\n let { title } = this.props;\n return (\n , align: 'vh', onClick: () => this.onClose() },\n { flex: 1, html: title, className: 'fs-18 bold', align: 'vh' },\n { size: 48 }\n ]\n }}\n />\n )\n }\n}\n\n","import React,{Component} from \"react\";\nimport RVD from './../../npm/react-virtual-dom/react-virtual-dom';\nimport SplitNumber from \"../../npm/aio-functions/split-number\";\nimport PopupHeader from './../../components/popup-header';\nimport AppContext from \"../../app-context\";\nimport {Icon} from '@mdi/react';\nimport { mdiArrowDown,mdiArrowUp } from \"@mdi/js\";\nexport default class Kife_pool extends Component{\n static contextType = AppContext;\n state = {tarikhche:[]}\n componentDidMount(){\n let {apis} = this.context;\n apis({\n api:'tarikhcheye_kife_pool',\n callback:(tarikhche)=>this.setState({tarikhche})\n })\n }\n render(){\n let {mojoodiye_kife_pool} = this.context;\n let {tarikhche} = this.state;\n return (\n },\n {html:},\n {\n size:48,className:'p-h-12',\n row:[\n {html:'تراکنش های کیف پول',align:'v',className:'fs-14 bold'},\n {flex:1},\n {html:'مشاهده همه',className:'theme-link',align:'v'}\n ]\n },\n {\n flex:1,gap:6,className:'ofy-auto',\n column:tarikhche.map((o)=>{\n return {html:}\n })\n }\n ]\n }}\n \n />\n )\n }\n}\n\nclass MojoodiCard extends Component{\n render(){\n let {value} = this.props;\n return (\n \n )\n }\n}\nclass TarikhcheCard extends Component{\n render(){\n let {type,date,time,amount} = this.props;\n return (\n ,align:'vh'},\n {\n flex:1,\n column:[\n {\n row:[\n {html:type === 'in'?'واریز وجه':'برداشت وجه',className:'fs-14 bold'},\n {flex:1},\n {html:date}\n ]\n },\n {\n row:[\n {html:`مبلغ ${SplitNumber(amount)} ریال`},\n {flex:1},\n {html:time}\n ]\n }\n ]\n }\n ]\n }}\n />\n )\n }\n}","import React, { Component } from \"react\";\nimport RVD from './../npm/react-virtual-dom/react-virtual-dom';\nimport SplitNumber from \"../npm/aio-functions/split-number\";\nimport { Icon } from '@mdi/react';\nimport { mdiAccount, mdiAccountCircleOutline, mdiChevronRight, mdiLock, mdiMapMarker, mdiPlusCircle, mdiPlusThick } from '@mdi/js';\nimport AIOInput from \"../npm/aio-input/aio-input\";\nimport Map from './../npm/map/map';\nimport Timer from \"../components/timer\";\nimport AppContext from \"../app-context\";\nimport Card from \"../card/card\";\nimport PopupHeader from \"../components/popup-header\";\nimport Kife_pool from \"../components/kife-pool/kife-pool\";\nexport default class Profile extends Component {\n static contextType = AppContext;\n constructor(props) {\n super(props);\n this.state = {\n items: [\n { icon: , text: 'اطلاعات شخصی', id: 'ettelaate_shakhsi' },\n { icon: , text: 'تنظیم یا ویرایش رمز عبور', id: 'password',show:()=>this.context.isRegistered },\n { icon: , text: 'آدرس ها', id: 'address_ha' },\n { icon: , text: 'تخفیف ها',id:'takhfif_ha' },\n { icon: , text: 'رستوران های محبوب',id:'restoran_haye_mahboob' },\n //{ icon: , text: 'نظرات من' },\n //{ icon: , text: 'شبکه اجتماعی غذا' },\n //{ icon: , text: 'دعوت از دوستان' },\n //{ icon: , text: 'تنظیمات' },\n //{ icon: , text: 'قوانین' },\n { icon: , text: 'خروج',id:'exit' }\n ]\n }\n }\n kife_pool_layout(){\n let { mojoodiye_kife_pool,rsa } = this.context;\n return {\n onClick:()=>{\n rsa.addModal({ header: false, body: {render:() => } })\n },\n column: [\n { flex: 1 },\n {\n align: 'v', gap: 3,\n style: { border: '1px solid' },\n className: 'h-24 br-12 p-h-6',\n row: [\n { html: 'کیف پول', className: 'fs-10' },\n { html: SplitNumber(mojoodiye_kife_pool), className: 'fs-12 bold' },\n { html: 'تومان', className: 'fs-10' },\n { html: }\n ]\n },\n { flex: 1 }\n ]\n }\n }\n openModal(key) {\n let { rsa,logout } = this.context;\n let { addModal } = rsa;\n if(key === 'exit'){\n logout();\n }\n if (key === 'ettelaate_shakhsi') {\n addModal({ position:'fullscreen',header: false, body: {render:() => }})\n }\n if (key === 'password') {\n addModal({ position:'fullscreen',header: false, body: {render:() => }})\n }\n if (key === 'address_ha') {\n addModal({ position:'fullscreen',header: false, body: {render:() => }})\n }\n if (key === 'takhfif_ha') {\n addModal({ position:'fullscreen',header: false, body: {render:() => }})\n }\n if (key === 'restoran_haye_mahboob') {\n addModal({ position:'fullscreen',header: false, body: {render:() => }})\n }\n }\n header_layout() {\n let { profile,mobile } = this.context;\n return {\n className: 'p-6',\n row: [\n {\n size: 60, align: 'vh',\n html: \n },\n {\n flex: 1,\n column: [\n { flex: 1 },\n { html: profile.firstName && profile.lastName?`${profile.firstName} ${profile.lastName}`:'شما ثبت نام نشده اید', className: 'fs-14 bold' },\n { html: mobile, className: 'fs-12' },\n { flex: 1 }\n ]\n },\n this.kife_pool_layout()\n ]\n }\n }\n body_layout() {\n let { items } = this.state;\n return {\n flex: 1, className: 'ofy-auto',\n column: items.filter(({show = ()=>true})=>show()).map(({ icon, text, id }) => {\n return {\n size: 48,\n onClick: () => this.openModal(id),\n row: [\n { size: 48, html: icon, align: 'vh' },\n { flex: 1, html: text, align: 'v' }\n ]\n }\n })\n }\n }\n render() {\n return (\n \n )\n }\n}\n\nclass Ettelaate_shakhsi extends Component {\n static contextType = AppContext;\n constructor(props) {\n super(props);\n this.state = { profile: {} }\n }\n componentDidMount() {\n let { profile } = this.context;\n this.setState({ profile })\n }\n form_layout() {\n let { profile,mobile } = this.state;\n let { appSetting } = this.context;\n let inputs = appSetting.profileFields.filter(({editable})=>editable).map(({type,label,clientField})=>{\n return { input:{type}, label, field: `value.${clientField}` }\n })\n return {\n flex: 1, className: 'ofy-auto',\n column: [\n {\n column: [\n { html: , style: { color: '#888' }, align: 'vh' },\n { html: `${profile.firstName} ${profile.lastName}`, align: 'vh', className: 'fs-14 bold' },\n { html: mobile, align: 'vh', className: 'fs-12' }\n ]\n },\n {\n html: (\n this.setState({ profile })}\n inputs={{props:{gap:12},column:inputs}}\n />\n )\n }\n ]\n }\n }\n footer_layout() {\n let {apis,changeStore,isRegistered,mobile} = this.context; \n return {\n align: 'vh',\n className: 'p-24',\n html: (\n \n )\n }\n }\n render() {\n return (\n },\n this.form_layout(),\n this.footer_layout()\n ]\n }}\n />\n )\n }\n}\nclass Passwrod extends Component {\n static contextType = AppContext;\n constructor(props) {\n super(props);\n this.state = { model:{password: ''} }\n }\n form_layout() {\n let { model } = this.state;\n let {mobile} = this.context;\n let inputs = [\n { input:{type:'text',disabled:true}, label:'شماره همراه', field: mobile },\n { input:{type:'password'}, label:'رمز عبور', field: `value.password` }\n ]\n return {\n flex: 1, className: 'ofy-auto',\n column: [\n {\n html: (\n this.setState({ model })}\n inputs={{props:{gap:12},column:inputs}}\n />\n )\n }\n ]\n }\n }\n footer_layout() {\n let {apis,rsa,changeStore,isRegistered,profile,mobile} = this.context;\n return {\n align: 'vh',\n className: 'p-24',\n html: (\n \n )\n }\n }\n render() {\n return (\n },\n this.form_layout(),\n this.footer_layout()\n ]\n }}\n />\n )\n }\n}\nclass Address_ha extends Component {\n static contextType = AppContext;\n async onSubmit(address,type){\n let {changeStore,rsa,apis,addresses} = this.context;\n await apis({\n api:'addressForm',\n parameter:{address,type},\n callback:()=>{\n if(type === 'add'){addresses.push(address);}\n else{addresses = addresses.map((o)=>address.id === o.id?address:o)}\n changeStore({addresses},` => onSubmit`);\n rsa.removeModal()\n },\n name:()=>`${type === 'add'?'افزودن':'ویرایش'} آدرس `,\n successMessage:true\n })\n }\n add_layout() {\n return {\n size: 48, className: 'p-h-12',\n onClick:()=>{\n let { rsa } = this.context;\n rsa.addModal({\n header: false,\n body: {render:() => this.onSubmit(address,'add')} />}\n })\n },\n row: [\n { size: 36, html: , align: 'vh' },\n { flex: 1, html: 'افزودن آدرس جدید', align: 'v', className: 'fs-14 bold' }\n ]\n }\n }\n cards_layout() {\n let { addresses } = this.context;\n return {\n flex: 1, className: 'ofy-auto',\n column: addresses.map((o) => {\n let { title, address } = o;\n return {\n size: 72, className: 'm-12 m-t-0 br-12',\n style: { border: '1px solid #aaa' },\n onClick: () => {\n let { rsa } = this.context;\n rsa.addModal({\n position:'fullscreen',header: false,\n body: {render:() => this.onSubmit(model,'edit')} />}\n })\n },\n row: [\n { size: 72, align: 'vh', html: },\n {\n flex: 1,\n column: [\n { flex: 1 },\n { html: title, className: 'fs-14 bold' },\n { html: address, className: 'fs-12' },\n { flex: 1 }\n ]\n }\n ]\n }\n })\n }\n }\n render() {\n return (\n },\n this.add_layout(),\n this.cards_layout(),\n\n ]\n }}\n />\n )\n }\n}\nclass Address_form extends Component {\n static contextType = AppContext;\n constructor(props) {\n super(props);\n let { model } = props;\n this.state = {\n error: true,\n model: model || {},\n type: !!model ? 'edit' : 'add'\n }\n }\n onMapClick() {\n let {model} = this.state;\n let { rsa } = this.context;\n rsa.addModal({\n header: false,\n position: 'fullscreen',\n body: {\n render:() => (\n {\n let { model } = this.state;\n model.latitude = latitude;\n model.longitude = longitude;\n model.address = address;\n this.setState({ model })\n }}\n latitude={model.latitude}\n longitude={model.longitude} \n />\n )\n }\n })\n }\n onSubmit(){\n let {onSubmit} = this.props;\n let {model} = this.state;\n onSubmit(model)\n }\n form_layout() {\n let {model,type} = this.state;\n return {\n flex: 1,\n html: (\n {\n let {model} = this.state;\n return (\n