UNPKG

aio-input

Version:

generate all input types in react j

1,142 lines 186 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { createElement as _createElement } from "react"; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { createRef, useContext, createContext, useState, useEffect, useRef, Fragment } from 'react'; import usePopup from "aio-popup"; import * as UT from 'aio-utils'; import AIODate from 'aio-date'; import { $ } from 'aio-deps'; import './index.css'; //@ts-ignore import successSound from "./success.mp3"; //@ts-ignore import errorSound from "./error.mp3"; import AIOCanvas from 'aio-canvas'; const Context = createContext({}); const Provider = ({ value, children }) => { return (_jsx(Context.Provider, { value: value, children: children })); }; const useProvider = () => useContext(Context); const AIOInput = (p) => { const fixMultiple = (props) => { props.multiple = true; if (!props.value) { props.value = []; } if (!Array.isArray(props.value)) { props.value = []; } }; const props = Object.assign({}, p); if (props.type === 'text') { if (typeof props.value !== 'string') { props.value = ''; } } else if (props.type === 'number') { if (typeof props.value !== 'number') { props.value = undefined; } } else if (props.type === 'panels') { props.deSelect = true; } else if (props.type === 'multiSelect') { props.type = 'select'; if (props.text === undefined) { props.text = 'Select Items'; } fixMultiple(props); } else if (props.type === 'multiDate') { props.type = 'date'; props.option = Object.assign(Object.assign({}, props.option), { text: (o) => o, value: (o) => o }); fixMultiple(props); } else if (props.type === 'multiTime') { props.type = 'time'; props.option = Object.assign(Object.assign({}, props.option), { text: (o) => o, value: (o) => o }); fixMultiple(props); } else if (props.type === 'multiButtons') { props.type = 'buttons'; fixMultiple(props); } else if (props.type === 'multiSlider') { props.type = 'range'; props.round = 0; fixMultiple(props); } else if (props.type === 'slider') { props.type = 'range'; props.round = 0; } else if (props.type === 'multiSpinner') { props.type = 'range'; if (!props.round || typeof props.round !== 'number') { props.round = 1; } fixMultiple(props); } else if (props.type === 'spinner') { props.type = 'range'; if (!props.round || typeof props.round !== 'number') { props.round = 1; } } else if (props.type === 'multiCheckbox') { props.type = 'radio'; fixMultiple(props); } else if (props.type === 'multiImage') { props.type = 'image'; fixMultiple(props); } else if (props.type === 'multiPanels') { props.type = 'panels'; fixMultiple(props); } else if (props.type === 'multiFile') { props.type = 'file'; fixMultiple(props); } else if (props.type === 'range') { return null; } else if (props.type === 'tree') { if (props.size === undefined) { props.size = 36; } } if (props.type === 'file') { if (props.placeholder === undefined && props.text === undefined && props.multiple) { props.text = 'Select Files'; } props.deSelect = props.deSelect !== false ? true : false; } else if (props.type === 'select' && !props.text && props.multiple) { props.text = 'Select Items'; } else if (props.type === 'date') { if (props.multiple) { props.text = props.text || `Select Dates`; } } else if (props.type === 'time') { if (props.multiple) { props.text = props.text || `Select Times`; } } if (props.type === 'text' && (props.options || props.fetchSuggestions) && !props.isSuggestion) { return _jsx(SuggestionInput, Object.assign({}, props)); } return _jsx(AIOINPUT, Object.assign({}, props)); }; export default AIOInput; function AIOINPUT(props) { const propsRef = useRef(props); propsRef.current = props; let [types] = useState(getTypes(props)); let [DATE] = useState(new AIODate()); let { type, value, attrs = {}, rtl } = props; const changable = !!props.onChange && props.disabled !== true; let [parentDom] = useState(createRef()); const isInputFocusedRef = useRef(false); const setInputFocused = (v) => isInputFocusedRef.current = v; const domRef = useRef(undefined); const setDomRef = (dom) => domRef.current = dom; const getDomRef = () => domRef.current; let [datauniqid] = useState('aiobutton' + (Math.round(Math.random() * 10000000))); let popup = usePopup({ rtl: props.rtl }); const optionsHook = useOptions(); const optionDetailsRef = useRef({ list: [], dic: {} }); const dateHook = useDate(() => { return Object.assign(Object.assign({}, props), { type: props.type === 'date' ? 'date' : 'time' }); }); let [showPassword, SetShowPassword] = useState(false); function setShowPassword(state) { SetShowPassword(state === undefined ? !showPassword : state); } function getPopover() { const dom = getDomRef(); let className = 'aio-input-popover ai-border-radius-md'; className += ` aio-input-popover-${rtl ? 'rtl' : 'ltr'}`; if (types.hasOption) { className += ' aio-input-dropdown'; } const popover = (props.popover || {}); let body = null; if (popover.body) { body = popover.body; } else if (type === 'date') { body = _jsx(CalendarWraper, { onClose: closePopup }); } else if (type === 'time') { body = _jsx(CalendarWraper, { onClose: closePopup }); } else { if (optionDetailsRef.current.list.length === 0) { return; } body = _jsx(Options, {}); } const modalAttrs = UT.AddToAttrs(Object.assign({}, popover.modalAttrs), { className }); let obj = Object.assign(Object.assign({}, (props.popover || {})), { rtl: !!props.rtl, focus: !types.hasKeyboard, position: popover.position || 'popover', fitHorizontal: ['text', 'number', 'textarea'].indexOf(type) !== -1 || (type === 'select' && !!props.multiple) || !!popover.fitHorizontal, onClose: () => closePopup(), body, getTarget: () => $(dom.current), modalAttrs }); return obj; } function closePopup() { popup.removeModal(); setTimeout(() => $(parentDom.current).focus(), 0); } function openPopover() { let open = !!popup.getModals().length; if (open) { return; } const popover = getPopover(); if (!popover) { return; } popup.addModal(popover); } function AIChange(a, b) { if (props.onChange) { props.onChange(a, b); } } function click(e) { if (type === 'checkbox') { AIChange(!value, e); } else if (types.isDropdown) { openPopover(); } else if (typeof props.onClick === 'function') { props.onClick(e); } else if (attrs.onClick) { attrs.onClick(); } } function optionClick(optionDetail) { let { attrs = {}, onClick, close } = optionDetail; if (onClick) { onClick(optionDetail.optionOrg, optionDetail); } else if (attrs.onClick) { attrs.onClick(optionDetail); } else if (changable) { if (types.isInput) { /*do nothing*/ } else if (type === 'tree') { /*do nothing*/ } else if (type === 'file') { /*do nothing*/ } else if (type === 'toggleButton') { let newIndex = optionDetail.index + 1; if (newIndex > optionDetailsRef.current.list.length - 1) { newIndex = 0; } const newOptionDetail = optionDetailsRef.current.list[newIndex]; AIChange(newOptionDetail.value, newOptionDetail); } else if (types.isMultiple) { let { maxLength } = props, newValue; value = value || []; if (value.indexOf(optionDetail.value) === -1) { newValue = value.concat(optionDetail.value); } else { newValue = value.filter((o) => o !== optionDetail.value); } while (!!maxLength && newValue.length > maxLength) { newValue = newValue.slice(1, newValue.length); } AIChange(newValue, optionDetail); } else { if (optionDetail.value !== props.value) { AIChange(optionDetail.value, optionDetail); } else if (props.deSelect) { if (type === 'radio' || type === 'tabs' || type === 'buttons' || type === 'panels') { AIChange(undefined, optionDetail); } } } } if (close) { closePopup(); } } function tagClick(optionDetail, isRemove) { var _a, _b; if (props.disabled === true || optionDetail.disabled === true) { return; } const propsValue = props.value || []; let newValue = []; if (isRemove !== false) { if (props.type === 'tags') { newValue = propsValue.filter((rpv, i) => rpv !== undefined && i !== optionDetail.index); } else if (props.type === 'file') { if (props.multiple) { newValue = propsValue.filter((rpv) => rpv.name !== optionDetail.value); } else { newValue = undefined; } } else { newValue = propsValue.filter((rpv) => rpv !== optionDetail.value); } AIChange(newValue, optionDetail); } else if ((_a = optionDetail.tagAttrs) === null || _a === void 0 ? void 0 : _a.onClick) { (_b = optionDetail.tagAttrs) === null || _b === void 0 ? void 0 : _b.onClick(optionDetail); } } //inja kheili mohemme baraye inke chejoori option ha sakhte beshan type ha dastane khodeshoono daran baraye sakhtan option ha //tags options nadare pas value ro be onvane options dar nazar migire //date time options nadare pas dateDetails ro be onvane options dar nazar migire function getOptionDetails() { let optionOrgs = []; if (type === 'date' || type === 'time') { if (!props.multiple) { return { list: [], dic: {} }; } optionOrgs = dateValueDetails.map((o) => (Object.assign({}, o))); } else if (type === 'file') { optionOrgs = getFileOptions(props.value); } else if (type === 'tags') { optionOrgs = props.value || []; } else if (props.options) { optionOrgs = props.options; } else { optionOrgs = []; } return optionsHook.getOptions({ rootProps: props, optionOrgs, optionProp: props.option || {}, getOptionDetails: () => optionDetailsRef.current.list }); } //use in mutiple date and time function getDateValueDetails() { if (!props.multiple || !types.isDate) { return []; } const { value = [] } = props; let values = Array.isArray(value) ? [...value] : (value !== undefined ? [value] : []); return values.map((o) => dateHook.getDateDetails(o)); } function getFileOptions(v) { const value = !v ? [] : (Array.isArray(v) ? v : [v]); return value.map((file) => { let filename = file.name || 'untitle'; let fileSize = file.size || 0; try { const minName = UT.Ellipsis(filename, 20, 'center'); const sizeString = new UT.FileClass().SizeToString(fileSize); const tagBefore = _jsx(FileIcon, { file: file }, file.name); return { tagText: minName, tagSubtext: sizeString, tagBefore, value: filename }; } catch (_a) { return { tagText: 'untitle' }; } }); } const isDraggable = () => types.hasOption && !!props.onSwap; const render = () => { if (types.hasTags) { return _jsx(HasTags, {}); } //date , time , select , file if (types.isRootOptions) { return _jsx(RootOptions, {}); } //tabs , buttons , tags , radio if (types.isInput) { return _jsx(Input_Input, {}); } //text , number , textarea , password, 'color' if (type === 'range') { return _jsx(Input_Range, {}); } //slider , 'spinner' if (type === 'toggleButton') { return _jsx(Input_ToggleButton, {}); } if (type === 'mask') { return _jsx(Input_Mask, {}); } if (type === 'panels') { return _jsx(Panels, {}); } if (type === 'tree') { return _jsx(Input_Tree, {}); } if (type === 'list') { return _jsx(List, {}); } if (type === 'image') { return _jsx(Input_Image, {}); } return _jsx(AILayout, {}); }; useEffect(() => { if (props.isSuggestion && isInputFocusedRef.current) { const { options = [] } = props; if (options.length) { openPopover(); } else { closePopup(); } } }, [props.isSuggestion ? props.options : undefined]); if (!type) { return null; } const dateValueDetails = getDateValueDetails(); optionDetailsRef.current = getOptionDetails(); return (_jsxs(Provider, { value: { changable, AIChange, optionDetails: optionDetailsRef.current, popup, setDomRef, getDomRef, dateHook, optionsHook, tagClick, rootProps: Object.assign(Object.assign({}, props), { value }), datauniqid, touch: 'ontouchstart' in document.documentElement, isDraggable, openPopover, click, optionClick, types, showPassword, setShowPassword, DATE, dateValueDetails, setInputFocused }, children: [render(), " ", popup.render()] })); } // #endregion main // #region types function getTypes(props) { function isDropdown() { if (['select', 'date', 'time'].indexOf(type) !== -1) { return true; } if (['text', 'number', 'textarea'].indexOf(type) !== -1 && props.options) { return true; } if (type === 'button' && props.popover) { return true; } return false; } let { type, multiple, optionsWrap = ['radio', 'select'].indexOf(type) !== -1 } = props; let isMultiple; if (type === 'tags') { isMultiple = true; } else if (['radio', 'range', 'file', 'image', 'buttons', 'select', 'date', 'time', 'panels', 'tabs'].indexOf(type) !== -1) { isMultiple = !!multiple; } else { isMultiple = false; } ; return { isDate: ['date', 'time'].indexOf(type) !== -1, isMultiple, isInput: ['text', 'number', 'textarea', 'password', 'color'].indexOf(type) !== -1, isDropdown: isDropdown(), hasOption: ['text', 'number', 'textarea', 'color', 'select', 'radio', 'tabs', 'list', 'buttons', 'tags'].indexOf(type) !== -1, isRootOptions: ['radio', 'tabs', 'buttons', 'tags'].indexOf(type) !== -1, ai_height: ['text', 'number', 'password', 'color', 'select', 'date', 'time', 'checkbox', 'file'].indexOf(type) !== -1, hasPlaceholder: ['text', 'number', 'textarea', 'color', 'select', 'image', 'date', 'time'].indexOf(type) !== -1, hasKeyboard: ['text', 'textarea', 'number', 'password'].indexOf(type) !== -1, hasText: ['checkbox', 'button', 'select'].indexOf(type) !== -1, hasSearch: ['select'].indexOf(type) !== -1, hasWrap: !!optionsWrap, hasTags: ['date', 'time', 'select', 'file'].indexOf(type) !== -1, hasInlineDeSelect: ['text', 'number', 'date', 'time', 'select', 'file'].indexOf(type) !== -1 }; } export const AIMask = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'mask' })); export const AIText = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'text' })); export const AINumber = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'number' })); export const AITextarea = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'textarea' })); export const AIPassword = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'password' })); export const AIColor = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'color' })); export const AIToggleButton = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'toggleButton' })); export const AISelect = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'select' })); export const AIMultiSelect = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'multiSelect' })); export const AIRadio = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'radio' })); export const AIMultiCheckbox = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'multiCheckbox' })); export const AITabs = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'tabs' })); export const AIButtons = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'buttons' })); export const AIMultiButtons = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'multiButtons' })); export const AITags = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'tags' })); export const AITree = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'tree' })); export const AIImage = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'image' })); export const AIMultiImage = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'multiImage' })); export const AIFile = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'file' })); export const AIMultiFile = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'multiFile' })); export const AICheckbox = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'checkbox' })); export const AIDate = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'date' })); export const AIMultiDate = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'multiDate' })); export const AITime = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'time' })); export const AIMultiTime = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'multiTime' })); export const AIPanels = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'panels' })); export const AIMultiPanels = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'multiPanels' })); export const AIList = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'list' })); export const AISlider = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'slider' })); export const AIMultiSlider = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'multiSlider' })); export const AISpinner = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'spinner' })); export const AIMultiSpinner = (props) => _jsx(AIOInput, Object.assign({}, props, { type: 'multiSpinner' })); // #endregion types // #region layout const useLayout = () => { const { rootProps, click, optionClick, types, changable, AIChange, showPassword, setShowPassword, touch, datauniqid, popup, tagClick, isDraggable, optionDetails } = useProvider(); const getCheckbox = (optionDetail, isTag) => { if (isTag) { return null; } const { multiple, type, checkIcon } = rootProps; const hasCheckbox = !!optionDetail ? typeof optionDetail.checked === 'boolean' : rootProps.type === 'checkbox'; if (!hasCheckbox) { return null; } const checked = !!optionDetail ? optionDetail.checked : !!rootProps.value; if (rootProps.switchOptions) { return _jsx(Switch, { value: rootProps.value, switchOptions: rootProps.switchOptions }); } return (_jsx(CheckIcon, { round: !multiple && type === 'radio', checked: checked, checkIcon: optionDetail ? optionDetail.checkIcon : checkIcon })); }; const getDragIcon = (optionDetail) => { if (!isDraggable() || !optionDetail) { return null; } const d = "M9,3H11V5H9V3M13,3H15V5H13V3M9,7H11V9H9V7M13,7H15V9H13V7M9,11H11V13H9V11M13,11H15V13H13V11M9,15H11V17H9V15M13,15H15V17H13V15M9,19H11V21H9V19M13,19H15V21H13V19Z"; return (_jsx("svg", { viewBox: "8 4 10 13", role: "presentation", style: { width: 12, height: '1.8rem' }, children: _jsx("path", { d: d, style: { fill: 'currentcolor' } }) })); }; const getBefore = (optionDetail, isTag, indent) => { const before = isTag ? (optionDetail === null || optionDetail === void 0 ? void 0 : optionDetail.tagBefore) || new UT.GetSvg('em').getIcon('mdiCircleMedium', 0.7) : (optionDetail ? optionDetail === null || optionDetail === void 0 ? void 0 : optionDetail.before : rootProps.before); const dragIcon = getDragIcon(optionDetail); const Indent = (!!indent && indent !== null) ? indent : null; const Checkbox = getCheckbox(optionDetail, isTag); const FileIconNode = rootProps.type === 'file' && !rootProps.multiple && !!rootProps.value ? _jsx(FileIcon, { file: rootProps.value }) : null; const res = [ dragIcon, Indent, Checkbox, before, FileIconNode ].filter((o) => o !== undefined && o !== null && !!o); if (!res.length) { return null; } return _jsx("div", { className: "aio-input-before", children: res.map((o, i) => _jsx(Fragment, { children: o }, 'layoutbefore' + i)) }); }; const getAfter = (optionDetail, isTag) => { const after = isTag ? optionDetail === null || optionDetail === void 0 ? void 0 : optionDetail.tagAfter : (optionDetail ? optionDetail === null || optionDetail === void 0 ? void 0 : optionDetail.after : rootProps.after); const hasDeselect = !rootProps.multiple && !!rootProps.deSelect && types.hasInlineDeSelect && !optionDetail && !!changable && rootProps.value !== undefined && rootProps.value !== null && rootProps.value !== ''; const hasPreview = !!rootProps.preview && !optionDetail && !!changable && rootProps.type === 'password'; const hasTagRemove = !!isTag && !!changable; function getCaret() { if (isTag || !types.isDropdown || optionDetail || (types.isInput && !rootProps.options)) { return null; } let { caret } = rootProps; if (caret === false) { return null; } return _jsx("div", { className: 'aio-input-caret', children: caret === undefined ? new UT.GetSvg('em').getIcon('mdiChevronDown', .8) : caret }); } const res = [ after, hasDeselect ? _jsx("div", { className: 'aio-input-deSelect', onClick: (e) => { e.stopPropagation(); e.preventDefault(); AIChange(undefined, undefined); }, children: new UT.GetSvg('em').getIcon('mdiClose', .8) }, `afterdeselect`) : null, hasPreview ? _jsx("div", { className: 'aio-input-password-preview', onClick: () => setShowPassword(), children: new UT.GetSvg('em').getIcon(showPassword ? 'mdiEyeOff' : 'mdiEye', .8) }, `afterpreview`) : null, hasTagRemove ? _jsx("div", { className: `aio-input-tag-icon aio-input-tag-remove`, onClick: (e) => { e.stopPropagation(); tagClick(optionDetail, true); }, children: new UT.GetSvg('em').getIcon('mdiClose', 0.7) }) : null, getCaret() ].filter((o) => o !== undefined && o !== null); if (!res.length) { return null; } return _jsx(_Fragment, { children: res.map((o, i) => _jsx("div", { className: "aio-input-after", children: o }, 'layoutafter' + i)) }); }; const getClassName = (optionDetail, isTag) => { const { type, rtl, round, vertical } = rootProps; const disabled = rootProps.disabled || (optionDetail === null || optionDetail === void 0 ? void 0 : optionDetail.disabled); const res = []; if (optionDetail) { if (optionDetail.className) { res.push(optionDetail.className); } if (isTag) { res.push(`aio-input-tag ai-padding-sm ai-border-radius-sm aio-input-${type}-tag`); res.push('aio-input-active-bgcolor'); } else { res.push(`aio-input-option ai-border-radius-md aio-input-${type}-option ai-height ai-padding-md ai-padding-h`); if (types.isDropdown) { res.push(`aio-input-dropdown-option`); } if (optionDetail.active === true) { res.push('active'); if (type === 'tabs') { res.push('aio-input-active-color'); } if (type === 'buttons') { res.push('aio-input-active-bgcolor'); } if (type === 'toggleButton') { res.push('aio-input-active-bgcolor'); } } if (optionDetail.justify === true) { res.push('aio-input-option-justify'); } if (type === 'tree') { let size = rootProps.size || 36; size = Math.round(size / 12) * 12; if (size < 24) { size = 24; } if (size > 120) { size = 120; } res.push(`aio-input-size-${size}`); } } } else { if (rootProps.className) { res.push(rootProps.className); } res.push(`aio-input`); if (['radio', 'buttons', 'tabs'].indexOf(rootProps.type) === -1) { res.push(`ai-padding-md`); } res.push('ai-border-radius-md'); res.push(`aio-input-${type}`); if (touch) { res.push('aio-input-touch'); } if (types.isInput) { res.push(`aio-input-input`); } if (type === 'select' && rootProps.multiple && !rootProps.hideTags) { res.push('aio-input-multiselect'); } if (types.ai_height) { res.push(`ai-height ai-padding-h`); } if (rootProps.justify) { res.push('aio-input-justify'); } res.push(rtl ? 'aio-input-rtl' : 'aio-input-ltr'); if (!!popup.getModals().length && ['text', 'number', 'textarea'].indexOf(type) !== -1) { res.push('z-index-input'); } if (type === 'range') { if (round) { res.push('aio-input-range-round'); } if (vertical) { res.push('aio-input-range-vertical'); } else { res.push('aio-input-range-horizontal'); } } } if (disabled === true) { res.push('disabled'); } if (datauniqid) { res.push(datauniqid); } return res.join(' '); }; const getStyle = (optionDetail) => { const style = (optionDetail ? optionDetail === null || optionDetail === void 0 ? void 0 : optionDetail.style : rootProps.style) || {}; if (rootProps.type === 'list' && optionDetail) { style.height = rootProps.size || 36; } return style; }; const keyDown = (e) => { const code = e.keyCode; if (code === 13) { click(e); } }; const getAttrs = (optionDetail, isTag) => { const disabled = rootProps.disabled || (optionDetail === null || optionDetail === void 0 ? void 0 : optionDetail.disabled); let attrs; if (isTag) { attrs = optionDetail === null || optionDetail === void 0 ? void 0 : optionDetail.tagAttrs; } else if (optionDetail) { attrs = optionDetail.attrs; } else { attrs = rootProps.attrs; } return UT.AddToAttrs(attrs, { className: getClassName(optionDetail, isTag), style: getStyle(optionDetail), attrs: { onClick: disabled === true ? undefined : (e) => { e.stopPropagation(); if (optionDetail) { if (isTag) { tagClick(optionDetail, false); } else { optionClick(optionDetail); } } else { click(e); } }, "data-index": optionDetail === null || optionDetail === void 0 ? void 0 : optionDetail.index, onKeyDown: (e) => keyDown(e), } }); }; const getText = (optionDetail, isTag) => { const { type } = rootProps; if (optionDetail) { if (isTag && optionDetail.tagText !== undefined) { return optionDetail.tagText; } return optionDetail.text; } else { if (rootProps.type === 'select' && !rootProps.multiple) { if (rootProps.text !== undefined) { return rootProps.text; } if (rootProps.value !== null && rootProps.value !== undefined) { const option = optionDetails.dic[`a${rootProps.value}`]; if (option) { return option.text; } } } if (rootProps.type === 'mask') { return _jsx(AIMaskComponent, {}); } if (type === 'tags') { return _jsx(Options, { isTag: true }); } else { return rootProps.text; } } }; const getSubtext = (optionDetail, isTag) => { if (optionDetail) { if (isTag && optionDetail.tagSubtext !== undefined) { return optionDetail.tagSubtext; } return optionDetail.subtext; } else { return rootProps.subtext; } }; return { getText, getSubtext, getBefore, getAfter, getAttrs }; }; const AILayout = (props) => { const { isTag, optionDetail, indent, html } = props; const { rootProps } = useProvider(); const layout = useLayout(); return (_jsx(Layout, { optionDetail: optionDetail, html: html, text: props.text || layout.getText(optionDetail, isTag), subtext: layout.getSubtext(optionDetail, isTag), before: layout.getBefore(optionDetail, isTag, indent), after: layout.getAfter(optionDetail, isTag), attrs: layout.getAttrs(optionDetail, isTag), placeholder: rootProps.placeholder, justify: optionDetail ? optionDetail.justify : rootProps.justify })); }; const Layout = (props) => { let { rootProps, setDomRef } = useProvider(); let { optionDetail, html } = props; let { type } = rootProps; let [dom] = useState(createRef()); // const [recognition, setRecognition] = useState<any>() // useEffect(() => { // if (!('webkitSpeechRecognition' in window)) { return } // let { voice } = rootProps; // if (!voice || !changable || !types.hasKeyboard) { return } // // @ts-ignore // const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; // if (!SpeechRecognition) { return } // const recognition = new SpeechRecognition(); // recognition.lang = { en: 'en-US', fa: 'fa-IR' }[voice]; // recognition.continuous = true; // recognition.interimResults = false; // recognition.onresult = (event: any) => { // const result = event.results[0][0].transcript; // AIChange(result, undefined); // }; // recognition.onerror = (event: any) => { // console.error('خطا در تشخیص گفتار: ', event.error); // }; // recognition.onend = () => { // console.log('تشخیص گفتار پایان یافت.'); // }; // setRecognition(recognition) // return () => { recognition.stop(); }; // }, []); function cls(key, hasSubtext) { let className = `aio-input-${key}`; if (optionDetail) { className += ` aio-input-${type}-option-${key}`; } else { className += ` aio-input-${type}-${key}`; } if (hasSubtext) { className += ` aio-input-has-subtext`; } return className; } function Text() { let { text, placeholder, justify, subtext } = props; if (text === undefined && placeholder !== undefined) { text = _jsx("div", { className: 'aio-input-placeholder', children: placeholder }); } if (text !== undefined) { const className = `${cls('value', !!subtext)}${justify ? ' aio-input-value-justify' : ''}`; return _jsx("div", { className: className, "data-subtext": subtext, children: text }); } else if (type === 'checkbox') { return null; } else { return _jsx("div", { style: { flex: 1 } }); } } // function startVoice() { // recognition.start(); // } // function voice() { // if (!recognition) { return null } // return <div className='aio-input-voice' onClick={() => startVoice()}>{I('mdiMicrophoneOutline', 0.8)}</div> // } let content = (_jsxs(_Fragment, { children: [!!props.before && props.before, Text(), !!props.after && props.after, html !== undefined && html] })); if (!optionDetail) { setDomRef(dom); } return (_jsx("label", Object.assign({ tabIndex: optionDetail ? undefined : 1, ref: dom }, props.attrs, { children: content }))); }; const HasTags = () => { let { rootProps, optionDetails, dateHook } = useProvider(); const { type, value, multiple, hideTags } = rootProps; const getOptionDetails = () => { if (!multiple || hideTags) { return []; } if (type === 'select') { let values = Array.isArray(value) ? [...value] : (value !== undefined ? [value] : []); if (!values.length) { return []; } return values.map((o) => optionDetails.dic['a' + o]); } if (type === 'date' || type === 'time' || type === 'file') { return optionDetails.list; } return []; }; const getOptions = () => { const optionDetails = getOptionDetails(); return !optionDetails.length ? null : _jsx(Options, { isTag: true, optionDetails: getOptionDetails() }); }; const getText = () => { var _a; if (rootProps.text) { return rootProps.text; } if (type === 'date' || type === 'time') { return _jsx("div", { style: { direction: 'ltr', width: 'fit-content' }, children: dateHook.getDateText(rootProps.value, true) }); } if (type === 'select') { return (_a = optionDetails.dic['a' + rootProps.value]) === null || _a === void 0 ? void 0 : _a.text; } if (type === 'file') { if (!!rootProps.value) { try { return rootProps.value.name; } catch (_b) { } } } }; const options = getOptions(); const text = getText(); const html = type === 'file' ? _jsx(InputFile, {}) : undefined; return options === null ? _jsx(AILayout, { html: html, text: text }) : _jsxs("div", { className: 'aio-input-multiselect-container', children: [_jsx(AILayout, { text: text, html: html }), options] }); }; const RootOptions = () => _jsx(AILayout, { text: _jsx(Options, {}) }); const Input_Input = () => _jsx(AILayout, { text: _jsx(Input, {}) }); const Input_Range = () => { const { rootProps: props } = useProvider(); return (_jsx(AIRangeComponent, { fill: props.fill, grooveAttrs: props.grooveAttrs, point: props.point, ranges: props.ranges, start: props.start, end: props.end, max: props.max, min: props.min, step: props.step, labels: props.labels, size: props.size, handle: props.handle, rotate: props.rotate, round: props.round, reverse: props.reverse, vertical: props.vertical, rangesDisabled: props.rangesDisabled, className: props.className, style: props.style, attrs: props.attrs, disabled: props.disabled, text: props.text, value: props.value, onChange: props.onChange, multiple: props.multiple })); }; const Input_Tree = () => { const { rootProps } = useProvider(); function getProps() { const props = rootProps; return { size: rootProps.size || 36, indent: props.indent || 24, value: props.value || [], actions: props.actions, addText: props.addText, onAdd: props.onAdd, onRemove: props.onRemove, onToggle: props.onToggle, removeText: props.removeText, setChilds: props.setChilds, onChange: props.onChange || (() => { }), option: props.option, attrs: props.attrs, className: props.className, rtl: props.rtl, style: props.style, }; } return _jsx(AITreeComponent, Object.assign({}, getProps())); }; const Input_Mask = () => _jsx(AILayout, { text: _jsx(AIMaskComponent, {}) }); const Input_ToggleButton = () => { const { optionDetails, rootProps } = useProvider(); let option = optionDetails.list.find((o) => rootProps.value !== undefined && o.value === rootProps.value) || optionDetails.list[0]; return !option ? null : _jsx(AILayout, { optionDetail: option }); }; export const CheckIcon = (props) => { if (props.checked === undefined) { return null; } if (Array.isArray(props.checkIcon)) { return _jsx(_Fragment, { children: props.checkIcon[props.checked === false ? 0 : 1] || null }); } return (_jsx("div", { className: 'aio-input-check-out aio-input-active-color' + (props.checked ? ' checked' : '') + (props.round ? ' aio-input-check-round' : ''), style: { background: 'none' }, children: _jsx("div", { className: 'aio-input-active-bg aio-input-check-in' }) })); }; const Switch = ({ value = false, switchOptions = {} }) => { const { rootProps } = useProvider(); const { onChange = () => { } } = rootProps; const { textButton = null, textOff = null, textOn = null, bgOn, bgOff, colorOn, colorOff, groove, size, width, attrs } = switchOptions || {}; const Attrs = UT.AddToAttrs(attrs, { className: ['aio-input-switch', !!value ? 'active' : ''], style: { fontSize: size, width, background: !!value ? bgOn : bgOff }, attrs: { onClick: () => onChange(!value) } }); const buttonAttrs = UT.AddToAttrs({}, { className: ['aio-input-switch-button', !!value ? 'active' : ''], style: { background: !!value ? colorOn : colorOff } }); return (_jsxs("div", Object.assign({}, Attrs, { children: [_jsx("div", { className: "aio-input-switch-off-content", children: _jsx("div", { className: "aio-input-switch-text", children: textOff }) }), _jsx("div", { className: "aio-input-switch-on-content", children: _jsx("div", { className: "aio-input-switch-text", children: textOn }) }), !!groove && _jsx("div", { className: "aio-input-switch-groove" }), _jsx("div", Object.assign({}, buttonAttrs, { children: textButton }))] }))); }; // #endregion layout // #region input const Input = () => { const { rootProps, types, showPassword, optionDetails, AIChange, changable, setInputFocused } = useProvider(); const { type, delay = 500 } = rootProps; const { maxLength = Infinity, spin = true } = rootProps; let { filter = [] } = rootProps; let [dom] = useState(createRef()); let [temp] = useState({ atimeout: undefined, btimeout: undefined, clicked: false }); let [datauniqid] = useState(`ac${Math.round(Math.random() * 100000)}`); let [value, setValue] = useState(rootProps.value || ''); let valueRef = useRef(value); const getRef = () => { const { inputAttrs = {} } = rootProps; if (inputAttrs.ref) { return inputAttrs.ref; } return dom; }; valueRef.current = value; function setSwip() { if (type === 'number' && rootProps.swip) { new UT.Swip({ speedY: rootProps.swip * 0.2, reverseY: true, minY: rootProps.min, maxY: rootProps.max, stepY: rootProps.swip, dom: () => { const ref = getRef(); if (ref !== null && ref.current !== null) { const res = $(ref.current); return res; } }, start: () => { let vref = +valueRef.current; vref = isNaN(vref) ? 0 : vref; return [0, vref]; }, move: (p) => { let { y } = p.change || { y: 0 }; if (rootProps.min !== undefined && y < rootProps.min) { y = rootProps.min; } if (rootProps.max !== undefined && y > rootProps.max) { y = rootProps.max; } change(y); } }); } } useEffect(() => { setSwip(); }, []); function getValidValue() { let v = rootProps.value; if (type === 'number') { if (v === '') { return undefined; } //important because +('') is 0 else if (!isNaN(+v)) { v = +v; if (typeof rootProps.min === 'number' && v < rootProps.min) { v = rootProps.min; } else if (typeof rootProps.max === 'number' && v > rootProps.max) { v = rootProps.max; } } } return v; } function update() { clearTimeout(temp.atimeout); temp.atimeout = setTimeout(() => { let v = getValidValue(); if (v !== value) { setValue(v); } }, delay); } useEffect(() => { update(); }, [rootProps.value]); function change(value) { if (!changable) { return; } if (!Array.isArray(filter)) { filter = []; } if (types.hasKeyboard) { value = UT.keyboard_filter(value, { maxLength, filter, toPersian: true }); } if (rootProps.type === 'number') { if (value === '') { value = undefined; } else { value = +value; } } setValue(value); if (!rootProps.blurChange) { clearTimeout(temp.btimeout); temp.btimeout = setTimeout(() => AIChange(value, undefined), delay); } } function click() { if (rootProps.autoHighlight === false) { return; } if (temp.clicked) { return; } temp.clicked = true; $(getRef().current).focus().select(); } function blur() { temp.clicked = false; setInputFocused(false); if (rootProps.blurChange && changable) { AIChange(value, undefined); } } function inputFocus() { setInputFocused(true); } function getInputAttrs() { let InputAttrs = UT.AddToAttrs(rootProps.inputAttrs, { className: !spin ? 'no-spin' : undefined, style: rootProps.justify ? { textAlign: 'center' } : undefined }); let p = Object.assign(Object.assign({}, InputAttrs), { ref: getRef(), value, type, disabled: rootProps.disabled, placeholder: rootProps.placeholder, list: rootProps.options ? datauniqid : undefined, onClick: () => click(), onChange: (e) => change(e.target.value), onBlur: () => blur(), onFocus: () => inputFocus() }); if (type === 'password' && showPassword) { p = Object.assign(Object.assign({}, p), { type: 'text', style: Object.assign(Object.assign({}, p.style), { textAlign: 'center' }) }); } if (filter.length === 1 && filter[0] === 'number') { p.pattern = "\d*"; p.inputMode = "numeric"; } return p; } let attrs = getInputAttrs(); if (type === 'color') { return (_jsxs("label", { style: { width: '100%', height: '100%', background: value }, children: [_jsx("input", Object.assign({}, attrs, { style: { opacity: 0 } })), !!optionDetails.list.length && _jsx("datalist", { id: datauniqid, children: optionDetails.list.map((o) => _jsx("option", { value: o.value })) })] })); } else if (type === 'textarea') { return _jsx("textarea", Object.assign({}, attrs)); } else { return (_jsx("input", Object.assign({}, attrs))); } }; export const useForm = (p) => { const initDataRef = useRef(JSON.parse(JSON.stringify(p.data))); const initDataStringRef = useRef(JSON.stringify(p.data)); const tagsResultRef = useRef([]); const fieldChangesRef = useRef({}); const getChanges = () => { return Object.keys(fieldChangesRef.current).map((field) => fieldChangesRef.current[field]); }; const getInput = (input) => { const { option = {} } = p; const obj = {}; for (let prop in option) { if (prop === 'validate') { continue; } obj[prop] = option[prop]({ field: input.field, data: dataRef.current }); } return Object.assign(Object.assign({}, obj), input); }; const getTag = (param) => { const change = (v) => { const error = errorHook.getErrorByInput(input, v); if (!error) { changeByInput(input, v, error); } }; let valuePresent = ''; const { value, input, disabled } = param; if (!input.tag) { return; } let label = input.tag === true ? input.label : input.tag; if ((value === undefined || value === null || value === '') && input.type !== 'checkbox') { return; } if (input.type === 'date') { const { dateUnit = 'day', jalali } = input; if (dateUnit === 'month') { valuePresent = new AIODate().getDateByPattern(value, '{year}/{month}', jalali); } else if (dateUnit === 'day') { valuePresent = new AIODate().getDateByPattern(value, '{year}/{month}/{day}', jalali); } } else if (input.type === 'time') { const { timeUnit = { year: true, month: true, day: true }, jalali } = input; valuePresent = new AIODate().getDateByPattern(value, `{year}/{month}/{day}${timeUnit.hour ? ` - {hour} : ${timeUnit.minute ? '{minute}' : '00'}` : ''}`, jalali); } else if (['radio', 'select', 'buttons', 'toggleButton'].indexOf(input.type) !== -1) { const { options = [] } = input; if (input.multiple) { if (!Array.isArray(value) || !value.length) { return; } valuePresent = options.filter((o) => value.indexOf(o.value) !== -1).map((o) => o.text).join(' | '); } else { valuePresent = options.find((o) => o.value === value).text; } } else if (input.type === 'checkbox') { valuePresent = input.text || input.label; label = (_jsx("div", { className: "ai-tag-checkbox", onClick: () => change(!value), children: _jsx(CheckIcon, { checked: !!value }) })); } else if (typeof value === 'number') { valuePresent = UT.SplitNumber(value)