intelicoreact 2.0.19 → 2.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/Atomic/FormElements/Datepicker/Datepicker.js +1 -1
- package/dist/es/Atomic/FormElements/SwitcherRangeList/SwitcherRangeList.js +1 -1
- package/dist/es/Atomic/UI/Hint/Hint.js +4 -6
- package/dist/es/Atomic/UI/Hint/Hint.js.map +1 -1
- package/dist/es/Atomic/UI/Modal/partials/useMobileModal.js +9 -4
- package/dist/es/Atomic/UI/Modal/partials/useMobileModal.js.map +1 -1
- package/dist/es/Classes/RESTAPI/partials/AbortableFetch.js +9 -2
- package/dist/es/Classes/RESTAPI/partials/AbortableFetch.js.map +1 -1
- package/package.json +2 -2
- /package/dist/es/Atomic/FormElements/{SwitcherRangeList/SwitcherRangeList.styles.css → Datepicker/Datepicker.styles.css} +0 -0
|
@@ -5,7 +5,7 @@ import Langs from "../../../Langs.js";
|
|
|
5
5
|
import Input from "../Input/Input.js";
|
|
6
6
|
import Dropdown from "../Dropdown/Dropdown.js";
|
|
7
7
|
import Switcher from "../Switcher/Switcher.js";
|
|
8
|
-
import '
|
|
8
|
+
import './Datepicker.styles.css';/* empty css */
|
|
9
9
|
import cn from "classnames";
|
|
10
10
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
11
11
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import '../../../styles/base.css';
|
|
2
2
|
import RangeList from "../RangeList/RangeList.js";
|
|
3
3
|
import SwitcherHide from "../SwitcherHide/SwitcherHide.js";
|
|
4
|
-
import '
|
|
4
|
+
import '../Datepicker/Datepicker.styles.css';/* empty css */
|
|
5
5
|
import cn from "classnames";
|
|
6
6
|
import { jsx } from "react/jsx-runtime";
|
|
7
7
|
//#region src/Atomic/FormElements/SwitcherRangeList/SwitcherRangeList.tsx
|
|
@@ -165,14 +165,12 @@ var Hint = ({ hint, side = "right", className, hintContainer = DEFAULT_EMPTY_OBJ
|
|
|
165
165
|
setIsStyleComputed(false);
|
|
166
166
|
setHintContainerStyles();
|
|
167
167
|
onOpenChange?.(isOpen);
|
|
168
|
-
if (isOpen)
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
168
|
+
if (!isOpen) return void 0;
|
|
169
|
+
document.addEventListener("scroll", handleScroll, true);
|
|
170
|
+
document.addEventListener("click", handleClickOutside, true);
|
|
171
|
+
return () => {
|
|
172
172
|
document.removeEventListener("scroll", handleScroll, true);
|
|
173
173
|
document.removeEventListener("click", handleClickOutside, true);
|
|
174
|
-
}
|
|
175
|
-
return () => {
|
|
176
174
|
const timer = hintTimeoutMap.get(hintId);
|
|
177
175
|
if (timer) {
|
|
178
176
|
clearTimeout(timer);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Hint.js","names":[],"sources":["../../../../../src/Atomic/UI/Hint/Hint.tsx"],"sourcesContent":["/* eslint-disable react-web-api/no-leaked-event-listener */\n/* eslint-disable react-dom/no-missing-button-type */\nimport type { ReactNode } from 'react';\nimport type { IHintProps } from './Hint.interface';\n\nimport cn from 'classnames';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { AlertTriangle, HelpCircle } from 'react-feather';\n\nimport { capitalized } from '../../../Functions/utils';\nimport { HelpCircleFilled } from '../../../Molecular/CustomIcons';\n\nimport Spinner from '../../Layout/Spinner/Spinner';\n\nimport { I_AM_OPENED_EVENT_NAME, I_AM_OPENED_EVENT_OPTIONS } from './partials/_constants';\nimport { getHintContainer, HandleClickOutsideObj, HandleScrollObj, initHintContainer } from './partials/_utils';\n\nimport './Hint.scss';\n\n// Глобальный мап для хранения таймеров по hintId\nconst hintTimeoutMap = new Map<string, NodeJS.Timeout>();\n\nlet isContentHoveredOuter = false;\n\nconst DEFAULT_EMPTY_OBJ = {} as IHintProps['hintContainer'];\n\nfunction DEFAULT_VOID_FN(): void {}\n\ninterface IIAmOpenedDetails {\n hintId: string;\n}\n\nconst Hint: React.FC<IHintProps> = ({\n hint,\n side = 'right',\n className,\n hintContainer = DEFAULT_EMPTY_OBJ,\n label = '',\n variant = 'filled',\n handleOpenType = 'click',\n onClickCallback,\n onOpenChange = DEFAULT_VOID_FN,\n key,\n id,\n children,\n icon,\n isAccessability = false,\n testId = 'hint',\n isHoverableContent = false,\n isLoading,\n isCloseOnChildrenClick = false,\n}) => {\n const hintRef = useRef(null);\n const [hintId] = useState<string>(id ?? key ?? Math.random().toString(16).slice(2));\n const [iAmOpenedOptions] = useState<Record<string, any>>({ ...I_AM_OPENED_EVENT_OPTIONS, detail: { hintId } });\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const [isStyleComputed, setIsStyleComputed] = useState<boolean>(false);\n\n // ? Определяем handleScroll-стейт, чтобы никогда не менять ссылку тем самым гарантировать корректную работу removeEventListener.\n // ? Инициализируем стейт вызовом конструктора HandleScrollObj, передаем setIsOpen для записи в объект.\n const [handleScroll] = useState(new (HandleScrollObj as any)(setIsOpen));\n // ? По аналогии определяем handleClickOutside\n const [handleClickOutside] = useState(new (HandleClickOutsideObj as any)(hintId, setIsOpen));\n\n const isCallbackExist: boolean = typeof onClickCallback === 'function';\n\n const handle = {\n onMouseEnter: (): void => {\n const existing = hintTimeoutMap.get(hintId);\n if (existing) clearTimeout(existing);\n\n if (handleOpenType === 'hover') {\n const timer = setTimeout(() => {\n setIsOpen(true);\n !isOpen && onClickCallback?.();\n\n // ? (FIN-10491) Идея следующая:\n // ? Любой hint как только он открывается \"широковещательно орёт\" - \"я открыт!\"\n // ? И, в свою очередь, любой hint слушает \"широковещательный ор\" и как услышит \"думает\" - \"а это не я ли случайно открыт?\".\n // ? Если НЕ он, то тогда он принудительно закрывается\n\n // ? В качестве \"широковещательного ора\" используем систему:\n // ? - диспатчим на \"себе\" ВСПЛЫВАЮЩИЙ кастомный ивент\n // ? - но чтобы \"слышать голоса\" всех хинтов \"слушаем\" на начальной точке всплытия (т.е. на document)\n // @ts-ignore\n hintRef.current?.dispatchEvent?.(new CustomEvent(I_AM_OPENED_EVENT_NAME, iAmOpenedOptions));\n }, 350);\n hintTimeoutMap.set(hintId, timer);\n }\n },\n onMouseLeave: (): void => {\n const existing = hintTimeoutMap.get(hintId);\n if (existing) clearTimeout(existing);\n\n if (!isHoverableContent && handleOpenType === 'hover') {\n const timer = setTimeout(() => {\n setIsOpen(false);\n hintTimeoutMap.delete(hintId);\n }, 1000);\n hintTimeoutMap.set(hintId, timer);\n }\n else if (isHoverableContent && handleOpenType === 'hover') {\n const timer = setTimeout(() => {\n if (!isContentHoveredOuter) {\n setIsOpen(false);\n }\n hintTimeoutMap.delete(hintId);\n }, 100);\n hintTimeoutMap.set(hintId, timer);\n }\n },\n onMouseLeaveHoverableContent: (): void => {\n const existing = hintTimeoutMap.get(hintId);\n if (existing) clearTimeout(existing);\n\n if (isHoverableContent && handleOpenType === 'hover') {\n const timer = setTimeout(() => {\n setIsOpen(false);\n isContentHoveredOuter = false;\n hintTimeoutMap.delete(hintId);\n }, 100);\n hintTimeoutMap.set(hintId, timer);\n }\n },\n onClick: isCloseOnChildrenClick ? (): void => setIsOpen(false) : (): void => {},\n };\n\n const getHintMarkUp = (className: string | undefined): ReactNode => {\n return (\n <div\n data-testid=\"test-hint-text\"\n className={cn('hint__text', `hint__text_${side}`, `hint--${className}__text`)}\n onMouseEnter={(): void => {\n if (isHoverableContent) isContentHoveredOuter = true;\n }}\n onMouseLeave={isHoverableContent ? handle.onMouseLeaveHoverableContent : undefined}\n onClick={handle.onClick}\n style={{ visibility: isStyleComputed ? 'visible' : 'hidden' }}\n >\n {isLoading && <Spinner size=\"small\" />}\n {hint}\n {children}\n </div>\n );\n };\n\n const setHintContainerStyles = (): void | boolean => {\n const hc = getHintContainer(hintId);\n\n if (!hc || !isOpen) return false;\n\n const { width = 0, top = 0, left = 0 } = hintRef?.current !== null ? (hintRef?.current as HTMLElement)?.getBoundingClientRect() : {};\n const { addWidth, addLeft, addTop } = hintContainer ?? {};\n const windowInnerWidth = document.documentElement.clientWidth;\n const windowInnerHeight = document.documentElement.clientHeight;\n\n const sw = hc.getElementsByClassName('hint__text')[0];\n const { width: swWidth, height: swHeight } = sw?.getBoundingClientRect() || {};\n\n hc.style.width = isOpen ? ((addWidth && !Number.isNaN(+addWidth) ? +addWidth : 0) + width)?.toString().concat('px') : '0';\n hc.style.left = isOpen ? ((addLeft && !Number.isNaN(+addLeft) ? +addLeft : 0) + left)?.toString().concat('px') : '0';\n hc.style.top = isOpen ? ((addTop && !Number.isNaN(+addTop) ? +addTop : 0) + top)?.toString().concat('px') : '0';\n hc.style.maxHeight = isOpen ? swHeight?.toString().concat('px') : '0';\n\n // ? Базовое значение погрешности\n // ? В разных свитч-кейсах может использоваться по разному (вся или частично). Определял \"на глазок\"\n const INACCURACY = 20;\n switch (side) {\n case 'top':\n case 'centeredTop':\n if (top - swHeight - (INACCURACY / 2) < 0) {\n sw.classList.remove(`hint__text_${side}`);\n sw.classList.add(`hint__text_${side === 'top' ? 'bottom' : 'centeredBottom'}`);\n }\n break;\n\n case 'bottom':\n case 'centeredBottom':\n if (top + swHeight + INACCURACY > windowInnerHeight) {\n sw.classList.remove(`hint__text_${side}`);\n sw.classList.add(`hint__text_${side === 'bottom' ? 'top' : 'centeredTop'}`);\n }\n break;\n\n case 'left':\n if (left - swWidth - (INACCURACY / 2) < 0) {\n sw.classList.remove(`hint__text_${side}`);\n sw.classList.add('hint__text_right');\n }\n break;\n\n case 'right':\n default:\n if (left + width + swWidth + (INACCURACY / 2) > windowInnerWidth) {\n sw.classList.remove(`hint__text_${side}`);\n sw.classList.add('hint__text_left');\n }\n break;\n }\n\n setIsStyleComputed(true);\n };\n\n const renderHintContainer = (className: string | undefined): React.ReactPortal | null => {\n const hc = getHintContainer(hintId);\n if (!hc) return null;\n return createPortal(getHintMarkUp(className), hc);\n }\n\n useEffect(() => {\n initHintContainer(hintId, hintContainer);\n\n // ? useEffect по нулевой зависимости запускается 1 раз, поэтому ссылка на колбек не изменится\n const iAmOpenedCallback = (ev: Event): CustomEvent<IIAmOpenedDetails> => {\n const event = ev as CustomEvent<IIAmOpenedDetails>;\n if (event?.detail?.hintId !== hintId) {\n setIsOpen(false);\n const timer = hintTimeoutMap.get(hintId);\n if (timer) {\n clearTimeout(timer);\n hintTimeoutMap.delete(hintId);\n }\n }\n return event;\n };\n\n if (hintRef.current) {\n // ? Устанавливаем прослушку на начальной точке всплытия\n document.addEventListener(I_AM_OPENED_EVENT_NAME, iAmOpenedCallback);\n }\n\n return () => {\n document.removeEventListener(I_AM_OPENED_EVENT_NAME, iAmOpenedCallback);\n const timer = hintTimeoutMap.get(hintId);\n if (timer) {\n clearTimeout(timer);\n hintTimeoutMap.delete(hintId);\n }\n };\n }, []);\n\n useEffect(() => {\n setIsStyleComputed(false);\n setHintContainerStyles();\n onOpenChange?.(isOpen);\n\n if (isOpen) {\n document.addEventListener('scroll', handleScroll, true);\n document.addEventListener('click', handleClickOutside, true);\n }\n else {\n document.removeEventListener('scroll', handleScroll, true);\n document.removeEventListener('click', handleClickOutside, true);\n }\n\n return () => {\n const timer = hintTimeoutMap.get(hintId);\n if (timer) {\n clearTimeout(timer);\n hintTimeoutMap.delete(hintId);\n }\n };\n }, [isOpen]);\n\n return (\n <div data-testid={testId} className={cn('hint', className)} ref={hintRef}>\n <button\n tabIndex={isAccessability ? 0 : -1}\n data-testid={typeof label === 'string' && label.length ? label.replace?.(/\\s/g, '-') : `${testId}--button`}\n aria-label={isAccessability && typeof label === 'string' ? label : ''}\n onClick={() =>\n handleOpenType === 'click'\n && (isCallbackExist ? onClickCallback?.() : setIsOpen(!isOpen))}\n onMouseEnter={handle.onMouseEnter}\n onMouseLeave={handle.onMouseLeave}\n className={cn('hint__button', { hint__button_active: isOpen })}\n >\n {icon || icon === null || (\n <>\n {variant === 'outlined' && <HelpCircle width={16} height={16} className=\"hint__icon outlined\" />}\n {variant === 'filled' && <HelpCircleFilled className=\"hint__icon filled\" />}\n {variant === 'warning' && (\n <AlertTriangle className=\"hint__icon\" color=\"#F06D8D\" width={16} height={16} />\n )}\n </>\n )}\n\n {label && (\n <span className={cn('hint__label', { 'color--primary': isOpen })}>\n {typeof label === 'string' ? capitalized(label) : label}\n </span>\n )}\n </button>\n\n {isOpen && renderHintContainer(className)}\n </div>\n );\n}\n\nexport default Hint;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Hint.js","names":[],"sources":["../../../../../src/Atomic/UI/Hint/Hint.tsx"],"sourcesContent":["/* eslint-disable react-dom/no-missing-button-type */\nimport type { ReactNode } from 'react';\nimport type { IHintProps } from './Hint.interface';\n\nimport cn from 'classnames';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { AlertTriangle, HelpCircle } from 'react-feather';\n\nimport { capitalized } from '../../../Functions/utils';\nimport { HelpCircleFilled } from '../../../Molecular/CustomIcons';\n\nimport Spinner from '../../Layout/Spinner/Spinner';\n\nimport { I_AM_OPENED_EVENT_NAME, I_AM_OPENED_EVENT_OPTIONS } from './partials/_constants';\nimport { getHintContainer, HandleClickOutsideObj, HandleScrollObj, initHintContainer } from './partials/_utils';\n\nimport './Hint.scss';\n\n// Глобальный мап для хранения таймеров по hintId\nconst hintTimeoutMap = new Map<string, NodeJS.Timeout>();\n\nlet isContentHoveredOuter = false;\n\nconst DEFAULT_EMPTY_OBJ = {} as IHintProps['hintContainer'];\n\nfunction DEFAULT_VOID_FN(): void {}\n\ninterface IIAmOpenedDetails {\n hintId: string;\n}\n\nconst Hint: React.FC<IHintProps> = ({\n hint,\n side = 'right',\n className,\n hintContainer = DEFAULT_EMPTY_OBJ,\n label = '',\n variant = 'filled',\n handleOpenType = 'click',\n onClickCallback,\n onOpenChange = DEFAULT_VOID_FN,\n key,\n id,\n children,\n icon,\n isAccessability = false,\n testId = 'hint',\n isHoverableContent = false,\n isLoading,\n isCloseOnChildrenClick = false,\n}) => {\n const hintRef = useRef(null);\n const [hintId] = useState<string>(id ?? key ?? Math.random().toString(16).slice(2));\n const [iAmOpenedOptions] = useState<Record<string, any>>({ ...I_AM_OPENED_EVENT_OPTIONS, detail: { hintId } });\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const [isStyleComputed, setIsStyleComputed] = useState<boolean>(false);\n\n // ? Определяем handleScroll-стейт, чтобы никогда не менять ссылку тем самым гарантировать корректную работу removeEventListener.\n // ? Инициализируем стейт вызовом конструктора HandleScrollObj, передаем setIsOpen для записи в объект.\n const [handleScroll] = useState(new (HandleScrollObj as any)(setIsOpen));\n // ? По аналогии определяем handleClickOutside\n const [handleClickOutside] = useState(new (HandleClickOutsideObj as any)(hintId, setIsOpen));\n\n const isCallbackExist: boolean = typeof onClickCallback === 'function';\n\n const handle = {\n onMouseEnter: (): void => {\n const existing = hintTimeoutMap.get(hintId);\n if (existing) clearTimeout(existing);\n\n if (handleOpenType === 'hover') {\n const timer = setTimeout(() => {\n setIsOpen(true);\n !isOpen && onClickCallback?.();\n\n // ? (FIN-10491) Идея следующая:\n // ? Любой hint как только он открывается \"широковещательно орёт\" - \"я открыт!\"\n // ? И, в свою очередь, любой hint слушает \"широковещательный ор\" и как услышит \"думает\" - \"а это не я ли случайно открыт?\".\n // ? Если НЕ он, то тогда он принудительно закрывается\n\n // ? В качестве \"широковещательного ора\" используем систему:\n // ? - диспатчим на \"себе\" ВСПЛЫВАЮЩИЙ кастомный ивент\n // ? - но чтобы \"слышать голоса\" всех хинтов \"слушаем\" на начальной точке всплытия (т.е. на document)\n // @ts-ignore\n hintRef.current?.dispatchEvent?.(new CustomEvent(I_AM_OPENED_EVENT_NAME, iAmOpenedOptions));\n }, 350);\n hintTimeoutMap.set(hintId, timer);\n }\n },\n onMouseLeave: (): void => {\n const existing = hintTimeoutMap.get(hintId);\n if (existing) clearTimeout(existing);\n\n if (!isHoverableContent && handleOpenType === 'hover') {\n const timer = setTimeout(() => {\n setIsOpen(false);\n hintTimeoutMap.delete(hintId);\n }, 1000);\n hintTimeoutMap.set(hintId, timer);\n }\n else if (isHoverableContent && handleOpenType === 'hover') {\n const timer = setTimeout(() => {\n if (!isContentHoveredOuter) {\n setIsOpen(false);\n }\n hintTimeoutMap.delete(hintId);\n }, 100);\n hintTimeoutMap.set(hintId, timer);\n }\n },\n onMouseLeaveHoverableContent: (): void => {\n const existing = hintTimeoutMap.get(hintId);\n if (existing) clearTimeout(existing);\n\n if (isHoverableContent && handleOpenType === 'hover') {\n const timer = setTimeout(() => {\n setIsOpen(false);\n isContentHoveredOuter = false;\n hintTimeoutMap.delete(hintId);\n }, 100);\n hintTimeoutMap.set(hintId, timer);\n }\n },\n onClick: isCloseOnChildrenClick ? (): void => setIsOpen(false) : (): void => {},\n };\n\n const getHintMarkUp = (className: string | undefined): ReactNode => {\n return (\n <div\n data-testid=\"test-hint-text\"\n className={cn('hint__text', `hint__text_${side}`, `hint--${className}__text`)}\n onMouseEnter={(): void => {\n if (isHoverableContent) isContentHoveredOuter = true;\n }}\n onMouseLeave={isHoverableContent ? handle.onMouseLeaveHoverableContent : undefined}\n onClick={handle.onClick}\n style={{ visibility: isStyleComputed ? 'visible' : 'hidden' }}\n >\n {isLoading && <Spinner size=\"small\" />}\n {hint}\n {children}\n </div>\n );\n };\n\n const setHintContainerStyles = (): void | boolean => {\n const hc = getHintContainer(hintId);\n\n if (!hc || !isOpen) return false;\n\n const { width = 0, top = 0, left = 0 } = hintRef?.current !== null ? (hintRef?.current as HTMLElement)?.getBoundingClientRect() : {};\n const { addWidth, addLeft, addTop } = hintContainer ?? {};\n const windowInnerWidth = document.documentElement.clientWidth;\n const windowInnerHeight = document.documentElement.clientHeight;\n\n const sw = hc.getElementsByClassName('hint__text')[0];\n const { width: swWidth, height: swHeight } = sw?.getBoundingClientRect() || {};\n\n hc.style.width = isOpen ? ((addWidth && !Number.isNaN(+addWidth) ? +addWidth : 0) + width)?.toString().concat('px') : '0';\n hc.style.left = isOpen ? ((addLeft && !Number.isNaN(+addLeft) ? +addLeft : 0) + left)?.toString().concat('px') : '0';\n hc.style.top = isOpen ? ((addTop && !Number.isNaN(+addTop) ? +addTop : 0) + top)?.toString().concat('px') : '0';\n hc.style.maxHeight = isOpen ? swHeight?.toString().concat('px') : '0';\n\n // ? Базовое значение погрешности\n // ? В разных свитч-кейсах может использоваться по разному (вся или частично). Определял \"на глазок\"\n const INACCURACY = 20;\n switch (side) {\n case 'top':\n case 'centeredTop':\n if (top - swHeight - (INACCURACY / 2) < 0) {\n sw.classList.remove(`hint__text_${side}`);\n sw.classList.add(`hint__text_${side === 'top' ? 'bottom' : 'centeredBottom'}`);\n }\n break;\n\n case 'bottom':\n case 'centeredBottom':\n if (top + swHeight + INACCURACY > windowInnerHeight) {\n sw.classList.remove(`hint__text_${side}`);\n sw.classList.add(`hint__text_${side === 'bottom' ? 'top' : 'centeredTop'}`);\n }\n break;\n\n case 'left':\n if (left - swWidth - (INACCURACY / 2) < 0) {\n sw.classList.remove(`hint__text_${side}`);\n sw.classList.add('hint__text_right');\n }\n break;\n\n case 'right':\n default:\n if (left + width + swWidth + (INACCURACY / 2) > windowInnerWidth) {\n sw.classList.remove(`hint__text_${side}`);\n sw.classList.add('hint__text_left');\n }\n break;\n }\n\n setIsStyleComputed(true);\n };\n\n const renderHintContainer = (className: string | undefined): React.ReactPortal | null => {\n const hc = getHintContainer(hintId);\n if (!hc) return null;\n return createPortal(getHintMarkUp(className), hc);\n }\n\n useEffect(() => {\n initHintContainer(hintId, hintContainer);\n\n // ? useEffect по нулевой зависимости запускается 1 раз, поэтому ссылка на колбек не изменится\n const iAmOpenedCallback = (ev: Event): CustomEvent<IIAmOpenedDetails> => {\n const event = ev as CustomEvent<IIAmOpenedDetails>;\n if (event?.detail?.hintId !== hintId) {\n setIsOpen(false);\n const timer = hintTimeoutMap.get(hintId);\n if (timer) {\n clearTimeout(timer);\n hintTimeoutMap.delete(hintId);\n }\n }\n return event;\n };\n\n if (hintRef.current) {\n // ? Устанавливаем прослушку на начальной точке всплытия\n document.addEventListener(I_AM_OPENED_EVENT_NAME, iAmOpenedCallback);\n }\n\n return () => {\n document.removeEventListener(I_AM_OPENED_EVENT_NAME, iAmOpenedCallback);\n const timer = hintTimeoutMap.get(hintId);\n if (timer) {\n clearTimeout(timer);\n hintTimeoutMap.delete(hintId);\n }\n };\n }, []);\n\n useEffect(() => {\n setIsStyleComputed(false);\n setHintContainerStyles();\n onOpenChange?.(isOpen);\n\n if (!isOpen) return undefined;\n\n document.addEventListener('scroll', handleScroll, true);\n document.addEventListener('click', handleClickOutside, true);\n\n return () => {\n document.removeEventListener('scroll', handleScroll, true);\n document.removeEventListener('click', handleClickOutside, true);\n const timer = hintTimeoutMap.get(hintId);\n if (timer) {\n clearTimeout(timer);\n hintTimeoutMap.delete(hintId);\n }\n };\n }, [isOpen]);\n\n return (\n <div data-testid={testId} className={cn('hint', className)} ref={hintRef}>\n <button\n tabIndex={isAccessability ? 0 : -1}\n data-testid={typeof label === 'string' && label.length ? label.replace?.(/\\s/g, '-') : `${testId}--button`}\n aria-label={isAccessability && typeof label === 'string' ? label : ''}\n onClick={() =>\n handleOpenType === 'click'\n && (isCallbackExist ? onClickCallback?.() : setIsOpen(!isOpen))}\n onMouseEnter={handle.onMouseEnter}\n onMouseLeave={handle.onMouseLeave}\n className={cn('hint__button', { hint__button_active: isOpen })}\n >\n {icon || icon === null || (\n <>\n {variant === 'outlined' && <HelpCircle width={16} height={16} className=\"hint__icon outlined\" />}\n {variant === 'filled' && <HelpCircleFilled className=\"hint__icon filled\" />}\n {variant === 'warning' && (\n <AlertTriangle className=\"hint__icon\" color=\"#F06D8D\" width={16} height={16} />\n )}\n </>\n )}\n\n {label && (\n <span className={cn('hint__label', { 'color--primary': isOpen })}>\n {typeof label === 'string' ? capitalized(label) : label}\n </span>\n )}\n </button>\n\n {isOpen && renderHintContainer(className)}\n </div>\n );\n}\n\nexport default Hint;\n"],"mappings":"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"}
|
|
@@ -30,12 +30,15 @@ function useMobileModal({ modalRef, withMobileLogic = false, withFixedFooter = f
|
|
|
30
30
|
const [, setContainerScrollHeight] = useState(1);
|
|
31
31
|
useLayoutEffect(() => {
|
|
32
32
|
const el = modalMobileContainerRef?.current;
|
|
33
|
-
if (el)
|
|
33
|
+
if (!el) return void 0;
|
|
34
|
+
const handleContainerScroll = () => {
|
|
34
35
|
setScrollTop((scrollTop) => {
|
|
35
36
|
if (scrollTop !== el.scrollTop) setScrollTopPrev(scrollTop);
|
|
36
37
|
return el.scrollTop;
|
|
37
38
|
});
|
|
38
|
-
}
|
|
39
|
+
};
|
|
40
|
+
el.addEventListener("scroll", handleContainerScroll);
|
|
41
|
+
return () => el.removeEventListener("scroll", handleContainerScroll);
|
|
39
42
|
}, [modalMobileContainerRef?.current]);
|
|
40
43
|
useEffect(() => {
|
|
41
44
|
setScrollDirection((prevScrollDirection) => scrollTop < scrollTopPrev ? SCROLL_DIRECTION.UP : scrollTop > scrollTopPrev ? SCROLL_DIRECTION.DOWN : prevScrollDirection);
|
|
@@ -108,12 +111,14 @@ function useMobileModal({ modalRef, withMobileLogic = false, withFixedFooter = f
|
|
|
108
111
|
window.innerHeight
|
|
109
112
|
]);
|
|
110
113
|
useEffect(() => {
|
|
111
|
-
|
|
114
|
+
const handleWindowResize = () => {
|
|
112
115
|
setContainerScrollHeight((containerScrollHeight) => {
|
|
113
116
|
setScrollHeight(containerScrollHeight - window.innerHeight);
|
|
114
117
|
return containerScrollHeight;
|
|
115
118
|
});
|
|
116
|
-
}
|
|
119
|
+
};
|
|
120
|
+
window.addEventListener("resize", handleWindowResize);
|
|
121
|
+
return () => window.removeEventListener("resize", handleWindowResize);
|
|
117
122
|
}, []);
|
|
118
123
|
return {
|
|
119
124
|
modalMobileContainerRef,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMobileModal.js","names":[],"sources":["../../../../../../src/Atomic/UI/Modal/partials/useMobileModal.tsx"],"sourcesContent":["/* eslint-disable react-web-api/no-leaked-event-listener */\nimport type { MutableRefObject, ReactNode } from 'react';\nimport { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';\n\nimport useIsMobile from '../../../../Functions/useIsMobile/useIsMobile';\n\ntype ScrollDirection = 'up' | 'down';\n\ninterface ModalsLogic {\n IS_HEADER_HIDDEN: boolean;\n IS_HEADER_STICKY: boolean;\n IS_FOOTER_HIDDEN: boolean;\n IS_FOOTER_STICKY: boolean;\n}\n\ninterface UseMobileModalProps {\n modalRef?: React.RefObject<HTMLDivElement>;\n withMobileLogic?: boolean;\n withFixedFooter?: boolean;\n isOpen?: boolean;\n}\n\ninterface UseMobileModalReturn {\n modalMobileContainerRef: MutableRefObject<HTMLDivElement | null>;\n modalMobileHeaderRef: MutableRefObject<HTMLDivElement | null>;\n modalMobileBodyRef: MutableRefObject<HTMLDivElement | null>;\n modalMobileFooterRef: MutableRefObject<HTMLDivElement | null>;\n MODALS_LOGIC: ModalsLogic;\n SCROLL_DIRECTION: { UP: ScrollDirection; DOWN: ScrollDirection };\n scrollTop: number;\n scrollHeight: number;\n renderModal: (modal: ReactNode) => ReactNode;\n isMobile: boolean;\n}\n\nconst SCROLL_DIRECTION = {\n UP: 'up' as ScrollDirection,\n DOWN: 'down' as ScrollDirection,\n};\n\nexport default function useMobileModal({\n modalRef,\n withMobileLogic = false,\n withFixedFooter = false,\n isOpen = false,\n}: UseMobileModalProps): UseMobileModalReturn {\n const modalMobileContainerRef = useRef<HTMLDivElement>(null);\n const modalMobileHeaderRef = useRef<HTMLDivElement>(null);\n const modalMobileFooterRef = useRef<HTMLDivElement>(null);\n const modalMobileBodyRef = useRef<HTMLDivElement>(null);\n\n const { isMobile } = useIsMobile();\n\n const [modalHeight, setModalHeight] = useState(0);\n const [modalsLogic, setModalsLogic] = useState<ModalsLogic>({\n IS_HEADER_HIDDEN: false,\n IS_HEADER_STICKY: false,\n IS_FOOTER_HIDDEN: false,\n IS_FOOTER_STICKY: withFixedFooter,\n });\n const [modalsLogicProps, setModalsLogicProps] = useState({\n headerHeight: 0,\n footerHeight: 0,\n });\n\n const [scrollDirection, setScrollDirection] = useState(SCROLL_DIRECTION.UP);\n const [scrollTopPrev, setScrollTopPrev] = useState(0);\n const [scrollTop, setScrollTop] = useState(0);\n const [scrollHeight, setScrollHeight] = useState(1);\n const [, setContainerScrollHeight] = useState(1);\n\n /* MODALS LOGIC | BEGIN */\n // Count ScrollTop\n useLayoutEffect(() => {\n const el = modalMobileContainerRef?.current;\n if (el) {\n el.addEventListener('scroll', () => {\n setScrollTop((scrollTop) => {\n if (scrollTop !== el.scrollTop) setScrollTopPrev(scrollTop);\n return el.scrollTop;\n });\n });\n }\n }, [modalMobileContainerRef?.current]);\n // Count ScrollDirection\n useEffect(() => {\n setScrollDirection(prevScrollDirection =>\n scrollTop < scrollTopPrev\n ? SCROLL_DIRECTION.UP\n : scrollTop > scrollTopPrev\n ? SCROLL_DIRECTION.DOWN\n : prevScrollDirection,\n );\n }, [scrollTop, scrollTopPrev]);\n // Dynamic Modal Positioning\n useLayoutEffect(() => {\n if (isOpen) {\n const modalStyle = modalRef?.current\n ? modalRef?.current.style\n || window.getComputedStyle(modalRef?.current)\n : {} as CSSStyleDeclaration;\n const computedModalHeight = modalRef?.current\n ? modalHeight + Number.parseFloat(modalStyle?.marginTop || '0')\n : 0;\n const windowHeight\n = document.documentElement.clientHeight\n || window.screen.availHeight\n || window.screen.height;\n if (modalMobileContainerRef?.current) {\n if (computedModalHeight <= windowHeight) {\n modalMobileContainerRef.current.style.display = 'flex';\n modalMobileContainerRef.current.style.alignItems = 'flex-end';\n }\n else {\n modalMobileContainerRef.current?.style?.removeProperty('display');\n modalMobileContainerRef.current?.style?.removeProperty('align-items');\n }\n }\n }\n }, [modalsLogicProps, isOpen, isMobile, modalHeight]);\n\n // Calculating\n useLayoutEffect(() => {\n if (isMobile && isOpen) {\n const newModalHeight = modalRef?.current?.getBoundingClientRect()?.height;\n if (newModalHeight && modalHeight !== newModalHeight) {\n setModalHeight(newModalHeight);\n }\n }\n });\n useEffect(() => {\n if (isMobile && withMobileLogic) {\n const { footerHeight, headerHeight } = modalsLogicProps;\n setModalsLogic(prevStickyLogic => ({\n IS_HEADER_HIDDEN:\n scrollDirection === SCROLL_DIRECTION.DOWN || scrollTop === 0,\n IS_HEADER_STICKY:\n scrollDirection === SCROLL_DIRECTION.UP\n && scrollTop !== 0\n && (scrollTop >= headerHeight || prevStickyLogic.IS_HEADER_STICKY),\n IS_FOOTER_HIDDEN:\n !withFixedFooter\n && (scrollDirection === SCROLL_DIRECTION.UP\n || scrollHeight === Math.round(scrollTop)),\n IS_FOOTER_STICKY:\n (withFixedFooter && scrollHeight > 1)\n || (scrollDirection === SCROLL_DIRECTION.DOWN\n && (scrollHeight - Math.round(scrollTop) >= footerHeight\n || prevStickyLogic.IS_FOOTER_STICKY)),\n }));\n }\n }, [\n scrollTop,\n scrollHeight,\n isMobile,\n withMobileLogic,\n scrollDirection,\n modalsLogicProps,\n modalHeight,\n window.innerHeight,\n ]);\n useLayoutEffect(() => {\n if (\n modalMobileHeaderRef?.current?.getBoundingClientRect()?.height\n !== undefined\n ) {\n setModalsLogicProps(state => ({\n ...state,\n headerHeight: modalMobileHeaderRef?.current?.getBoundingClientRect()?.height ?? 0,\n }));\n }\n }, [modalMobileHeaderRef?.current?.getBoundingClientRect()?.height]);\n useLayoutEffect(() => {\n if (\n modalMobileFooterRef?.current?.getBoundingClientRect()?.height\n !== undefined\n ) {\n setModalsLogicProps(state => ({\n ...state,\n footerHeight: modalMobileFooterRef?.current?.getBoundingClientRect()?.height ?? 0,\n }));\n }\n }, [modalMobileFooterRef?.current?.getBoundingClientRect()?.height]);\n useEffect(() => {\n if (modalMobileContainerRef?.current) {\n setContainerScrollHeight(modalMobileContainerRef?.current?.scrollHeight);\n setScrollHeight(\n modalMobileContainerRef?.current?.scrollHeight - window.innerHeight,\n );\n }\n }, [scrollTop, modalMobileContainerRef?.current, window.innerHeight]);\n useEffect(() => {\n window.addEventListener('resize', () => {\n setContainerScrollHeight((containerScrollHeight) => {\n setScrollHeight(containerScrollHeight - window.innerHeight);\n return containerScrollHeight;\n });\n });\n }, []);\n /* MODALS LOGIC | END */\n\n const renderModal = useCallback(\n (modal: ReactNode): ReactNode => {\n if (!isMobile || !withMobileLogic) return modal;\n\n return (\n <div className=\"modal-mobile-container\" ref={modalMobileContainerRef}>\n {modal}\n </div>\n );\n },\n [isMobile, withMobileLogic],\n );\n\n return {\n modalMobileContainerRef,\n modalMobileHeaderRef,\n modalMobileBodyRef,\n modalMobileFooterRef,\n MODALS_LOGIC: modalsLogic,\n SCROLL_DIRECTION,\n scrollTop,\n scrollHeight,\n renderModal,\n isMobile,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useMobileModal.js","names":[],"sources":["../../../../../../src/Atomic/UI/Modal/partials/useMobileModal.tsx"],"sourcesContent":["import type { MutableRefObject, ReactNode } from 'react';\nimport { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';\n\nimport useIsMobile from '../../../../Functions/useIsMobile/useIsMobile';\n\ntype ScrollDirection = 'up' | 'down';\n\ninterface ModalsLogic {\n IS_HEADER_HIDDEN: boolean;\n IS_HEADER_STICKY: boolean;\n IS_FOOTER_HIDDEN: boolean;\n IS_FOOTER_STICKY: boolean;\n}\n\ninterface UseMobileModalProps {\n modalRef?: React.RefObject<HTMLDivElement>;\n withMobileLogic?: boolean;\n withFixedFooter?: boolean;\n isOpen?: boolean;\n}\n\ninterface UseMobileModalReturn {\n modalMobileContainerRef: MutableRefObject<HTMLDivElement | null>;\n modalMobileHeaderRef: MutableRefObject<HTMLDivElement | null>;\n modalMobileBodyRef: MutableRefObject<HTMLDivElement | null>;\n modalMobileFooterRef: MutableRefObject<HTMLDivElement | null>;\n MODALS_LOGIC: ModalsLogic;\n SCROLL_DIRECTION: { UP: ScrollDirection; DOWN: ScrollDirection };\n scrollTop: number;\n scrollHeight: number;\n renderModal: (modal: ReactNode) => ReactNode;\n isMobile: boolean;\n}\n\nconst SCROLL_DIRECTION = {\n UP: 'up' as ScrollDirection,\n DOWN: 'down' as ScrollDirection,\n};\n\nexport default function useMobileModal({\n modalRef,\n withMobileLogic = false,\n withFixedFooter = false,\n isOpen = false,\n}: UseMobileModalProps): UseMobileModalReturn {\n const modalMobileContainerRef = useRef<HTMLDivElement>(null);\n const modalMobileHeaderRef = useRef<HTMLDivElement>(null);\n const modalMobileFooterRef = useRef<HTMLDivElement>(null);\n const modalMobileBodyRef = useRef<HTMLDivElement>(null);\n\n const { isMobile } = useIsMobile();\n\n const [modalHeight, setModalHeight] = useState(0);\n const [modalsLogic, setModalsLogic] = useState<ModalsLogic>({\n IS_HEADER_HIDDEN: false,\n IS_HEADER_STICKY: false,\n IS_FOOTER_HIDDEN: false,\n IS_FOOTER_STICKY: withFixedFooter,\n });\n const [modalsLogicProps, setModalsLogicProps] = useState({\n headerHeight: 0,\n footerHeight: 0,\n });\n\n const [scrollDirection, setScrollDirection] = useState(SCROLL_DIRECTION.UP);\n const [scrollTopPrev, setScrollTopPrev] = useState(0);\n const [scrollTop, setScrollTop] = useState(0);\n const [scrollHeight, setScrollHeight] = useState(1);\n const [, setContainerScrollHeight] = useState(1);\n\n /* MODALS LOGIC | BEGIN */\n // Count ScrollTop\n useLayoutEffect(() => {\n const el = modalMobileContainerRef?.current;\n if (!el) return undefined;\n /*\n * ? Именованный хендлер + cleanup обязательны: раньше на каждый прогон эффекта\n * ? вешалась НОВАЯ анонимная подписка без снятия — дубли обработчиков скролла\n * ? и ретейн замыканий после анмаунта (вклад в listener-утечку adminka 2026-07).\n */\n const handleContainerScroll = (): void => {\n setScrollTop((scrollTop) => {\n if (scrollTop !== el.scrollTop) setScrollTopPrev(scrollTop);\n return el.scrollTop;\n });\n };\n el.addEventListener('scroll', handleContainerScroll);\n return () => el.removeEventListener('scroll', handleContainerScroll);\n }, [modalMobileContainerRef?.current]);\n // Count ScrollDirection\n useEffect(() => {\n setScrollDirection(prevScrollDirection =>\n scrollTop < scrollTopPrev\n ? SCROLL_DIRECTION.UP\n : scrollTop > scrollTopPrev\n ? SCROLL_DIRECTION.DOWN\n : prevScrollDirection,\n );\n }, [scrollTop, scrollTopPrev]);\n // Dynamic Modal Positioning\n useLayoutEffect(() => {\n if (isOpen) {\n const modalStyle = modalRef?.current\n ? modalRef?.current.style\n || window.getComputedStyle(modalRef?.current)\n : {} as CSSStyleDeclaration;\n const computedModalHeight = modalRef?.current\n ? modalHeight + Number.parseFloat(modalStyle?.marginTop || '0')\n : 0;\n const windowHeight\n = document.documentElement.clientHeight\n || window.screen.availHeight\n || window.screen.height;\n if (modalMobileContainerRef?.current) {\n if (computedModalHeight <= windowHeight) {\n modalMobileContainerRef.current.style.display = 'flex';\n modalMobileContainerRef.current.style.alignItems = 'flex-end';\n }\n else {\n modalMobileContainerRef.current?.style?.removeProperty('display');\n modalMobileContainerRef.current?.style?.removeProperty('align-items');\n }\n }\n }\n }, [modalsLogicProps, isOpen, isMobile, modalHeight]);\n\n // Calculating\n useLayoutEffect(() => {\n if (isMobile && isOpen) {\n const newModalHeight = modalRef?.current?.getBoundingClientRect()?.height;\n if (newModalHeight && modalHeight !== newModalHeight) {\n setModalHeight(newModalHeight);\n }\n }\n });\n useEffect(() => {\n if (isMobile && withMobileLogic) {\n const { footerHeight, headerHeight } = modalsLogicProps;\n setModalsLogic(prevStickyLogic => ({\n IS_HEADER_HIDDEN:\n scrollDirection === SCROLL_DIRECTION.DOWN || scrollTop === 0,\n IS_HEADER_STICKY:\n scrollDirection === SCROLL_DIRECTION.UP\n && scrollTop !== 0\n && (scrollTop >= headerHeight || prevStickyLogic.IS_HEADER_STICKY),\n IS_FOOTER_HIDDEN:\n !withFixedFooter\n && (scrollDirection === SCROLL_DIRECTION.UP\n || scrollHeight === Math.round(scrollTop)),\n IS_FOOTER_STICKY:\n (withFixedFooter && scrollHeight > 1)\n || (scrollDirection === SCROLL_DIRECTION.DOWN\n && (scrollHeight - Math.round(scrollTop) >= footerHeight\n || prevStickyLogic.IS_FOOTER_STICKY)),\n }));\n }\n }, [\n scrollTop,\n scrollHeight,\n isMobile,\n withMobileLogic,\n scrollDirection,\n modalsLogicProps,\n modalHeight,\n window.innerHeight,\n ]);\n useLayoutEffect(() => {\n if (\n modalMobileHeaderRef?.current?.getBoundingClientRect()?.height\n !== undefined\n ) {\n setModalsLogicProps(state => ({\n ...state,\n headerHeight: modalMobileHeaderRef?.current?.getBoundingClientRect()?.height ?? 0,\n }));\n }\n }, [modalMobileHeaderRef?.current?.getBoundingClientRect()?.height]);\n useLayoutEffect(() => {\n if (\n modalMobileFooterRef?.current?.getBoundingClientRect()?.height\n !== undefined\n ) {\n setModalsLogicProps(state => ({\n ...state,\n footerHeight: modalMobileFooterRef?.current?.getBoundingClientRect()?.height ?? 0,\n }));\n }\n }, [modalMobileFooterRef?.current?.getBoundingClientRect()?.height]);\n useEffect(() => {\n if (modalMobileContainerRef?.current) {\n setContainerScrollHeight(modalMobileContainerRef?.current?.scrollHeight);\n setScrollHeight(\n modalMobileContainerRef?.current?.scrollHeight - window.innerHeight,\n );\n }\n }, [scrollTop, modalMobileContainerRef?.current, window.innerHeight]);\n useEffect(() => {\n // ? Cleanup обязателен: анонимная resize-подписка на window жила после анмаунта\n // ? модалки навсегда (по подписке на каждый показ модалки).\n const handleWindowResize = (): void => {\n setContainerScrollHeight((containerScrollHeight) => {\n setScrollHeight(containerScrollHeight - window.innerHeight);\n return containerScrollHeight;\n });\n };\n window.addEventListener('resize', handleWindowResize);\n return () => window.removeEventListener('resize', handleWindowResize);\n }, []);\n /* MODALS LOGIC | END */\n\n const renderModal = useCallback(\n (modal: ReactNode): ReactNode => {\n if (!isMobile || !withMobileLogic) return modal;\n\n return (\n <div className=\"modal-mobile-container\" ref={modalMobileContainerRef}>\n {modal}\n </div>\n );\n },\n [isMobile, withMobileLogic],\n );\n\n return {\n modalMobileContainerRef,\n modalMobileHeaderRef,\n modalMobileBodyRef,\n modalMobileFooterRef,\n MODALS_LOGIC: modalsLogic,\n SCROLL_DIRECTION,\n scrollTop,\n scrollHeight,\n renderModal,\n isMobile,\n };\n}\n"],"mappings":"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"}
|
|
@@ -14,6 +14,13 @@ var HTTP_METHODS = [
|
|
|
14
14
|
function isHttpMethod(value) {
|
|
15
15
|
return HTTP_METHODS.includes(value);
|
|
16
16
|
}
|
|
17
|
+
function toHttpMethod(value) {
|
|
18
|
+
if (typeof value !== "string" || !value) return null;
|
|
19
|
+
const normalized = value.toUpperCase();
|
|
20
|
+
if (isHttpMethod(normalized)) return normalized;
|
|
21
|
+
console.error(`[RESTAPI] Невалидный HTTP-метод "${value}" — значение проигнорировано (сработает merge-fallback).`);
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
17
24
|
var RESPONSE_AS_OBJECT_ALWAYS_VALUE = "always";
|
|
18
25
|
var AbortableFetch = class {
|
|
19
26
|
#pathPrefix = null;
|
|
@@ -138,7 +145,7 @@ var AbortableFetch = class {
|
|
|
138
145
|
const getMergeProps = (key) => safelyMergeProps.all ?? safelyMergeProps[key];
|
|
139
146
|
if (!path || typeof path !== "string") return ac;
|
|
140
147
|
const { name: omitName, path: omitPath, pathPrefix: omitPathPrefix, method: omitMethod, queryParameters: omitQueryParameters, headers: omitHeaders, body: omitBody, options: omitOptions, callback: omitCallback, mergeProps: omitMergeProps, ...optionsRest } = getIsOnlyAnObject(options) ? options : {};
|
|
141
|
-
const localMethod =
|
|
148
|
+
const localMethod = toHttpMethod(method);
|
|
142
149
|
const localCallback = typeof callback === "function" ? (res) => callback(res) : void 0;
|
|
143
150
|
return [...ac, {
|
|
144
151
|
path,
|
|
@@ -291,7 +298,7 @@ var AbortableFetch = class {
|
|
|
291
298
|
setProps(input) {
|
|
292
299
|
const { pathPrefix, method, queryParameters, headers, body, options, callback, catchCallback, everyPromiseCallback, isResponseAsObject } = input;
|
|
293
300
|
if (pathPrefix) this.setPathPrefix(typeof pathPrefix === "string" ? pathPrefix : null);
|
|
294
|
-
if (method) this.setMethod(
|
|
301
|
+
if (method) this.setMethod(toHttpMethod(method));
|
|
295
302
|
if (queryParameters) this.setQueryParameters(this.getQueryArray(queryParameters));
|
|
296
303
|
if (headers) this.setHeaders(getIsOnlyAnObject(headers) ? headers : null);
|
|
297
304
|
if (body) this.setBody(body);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AbortableFetch.js","names":["#isResponseAsObject","#everyPromiseCallback","#callback","#catchCallback","#pathPrefix","#method","#queryParameters","#headers","#body","#options"],"sources":["../../../../../src/Classes/RESTAPI/partials/AbortableFetch.ts"],"sourcesContent":["import type { HttpMethod, UnknownRecord } from './types';\nimport { getIsOnlyAnObject } from './_utils';\n\n// ? Колбэк обработки ответа на разных уровнях цепочки запросов.\n// ? this типизирован как AbortableFetch: everyPromiseCallback/catchCallback вызываются как\n// ? this.#callback(res) и опираются на this === экземпляр AbortableFetch.\ntype ResponseCallback = (this: AbortableFetch, response: unknown) => unknown;\n\n// ? Колбэк отдельного запроса: вызывается как item.callback(res) (без значимого this).\ntype ItemCallback = (response: unknown) => unknown;\n\n// ? Промис результата request() с дополнительным методом отмены всей цепочки запросов.\nexport type AbortablePromise<T> = Promise<T> & { abort: () => void };\n\n// ? Подготовленный (нормализованный) объект описания одного запроса для внутреннего использования.\ninterface PreparedRequest {\n path: string;\n pathPrefix: string;\n method: HttpMethod;\n queryParameters: string;\n headers: Headers;\n body: unknown;\n options: UnknownRecord;\n callback?: ItemCallback;\n isSkipEveryPromiseCallback?: boolean;\n name?: string | number;\n}\n\nconst HTTP_METHODS: readonly string[] = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH'];\n\n// ? Type-guard: является ли строка валидным HTTP-методом.\nfunction isHttpMethod(value: string): value is HttpMethod {\n return HTTP_METHODS.includes(value);\n}\n\nconst RESPONSE_AS_OBJECT_ALWAYS_VALUE = 'always';\nclass AbortableFetch {\n #pathPrefix: string | null = null;\n\n #method: HttpMethod | null = null;\n\n #queryParameters: string[] | null = null;\n\n #headers: UnknownRecord | null = null;\n\n #body: unknown = null;\n\n #options: UnknownRecord | null = null;\n\n #callback: ResponseCallback | null = null;\n\n #catchCallback: ResponseCallback | null = null;\n\n #everyPromiseCallback: ResponseCallback | null = null;\n\n #isResponseAsObject: boolean | 'always' = false;\n\n // ? Последний вход request() — используется repeatRequest() для повторного запроса той же пачки.\n requestInput: string | UnknownRecord | Array<string | UnknownRecord> = [];\n\n constructor(input?: UnknownRecord) {\n if (input && !getIsOnlyAnObject(input)) throw new Error('Not valid input value!');\n this.getPathPrefix = this.getPathPrefix.bind(this);\n this.setPathPrefix = this.setPathPrefix.bind(this);\n this.getMethod = this.getMethod.bind(this);\n this.setMethod = this.setMethod.bind(this);\n this.getQueryParameters = this.getQueryParameters.bind(this);\n this.getQueryString = this.getQueryString.bind(this);\n this.setQueryParameters = this.setQueryParameters.bind(this);\n this.getHeaders = this.getHeaders.bind(this);\n this.getHeadersObj = this.getHeadersObj.bind(this);\n this.setHeaders = this.setHeaders.bind(this);\n this.getBody = this.getBody.bind(this);\n this.setBody = this.setBody.bind(this);\n this.getOptions = this.getOptions.bind(this);\n this.setOptions = this.setOptions.bind(this);\n this.getCallback = this.getCallback.bind(this);\n this.setCallback = this.setCallback.bind(this);\n this.getCatchCallback = this.getCatchCallback.bind(this);\n this.setCatchCallback = this.setCatchCallback.bind(this);\n this.getEveryPromiseCallback = this.getEveryPromiseCallback.bind(this);\n this.setEveryPromiseCallback = this.setEveryPromiseCallback.bind(this);\n this.getIsResponseAsObject = this.getIsResponseAsObject.bind(this);\n this.setIsResponseAsObject = this.setIsResponseAsObject.bind(this);\n this.getProps = this.getProps.bind(this);\n this.setProps = this.setProps.bind(this);\n\n this.request = this.request.bind(this);\n this.repeatRequest = this.repeatRequest.bind(this);\n this.setProps(input || {});\n }\n\n /**\n * Выполняет один или несколько HTTP-запросов (нативный fetch) с возможностью отмены.\n *\n * Метод `abort()` навешивается на прототип возвращаемого промиса (как в исходной реализации),\n * что позволяет отменить всю цепочку запросов вызовом `abort()` на возвращённом промисе.\n *\n * @param props - путь, объект описания запроса или их массив.\n * @returns Промис с результатом (форма зависит от isResponseAsObject); на прототипе доступен `abort()`.\n */\n async request(props: string | UnknownRecord | Array<string | UnknownRecord>): Promise<unknown> {\n if (!getIsOnlyAnObject(props) && !Array.isArray(props) && typeof props !== 'string') throw new Error('Not valid props value!');\n\n const stringifyBody = (b: unknown): FormData | string => (b instanceof FormData ? b : JSON.stringify(b));\n\n this.requestInput = props;\n const requests = getRequestsArray.call(this, props);\n\n const ABORTABLE_FETCH_CONTEXT = this;\n const abortController = new AbortController();\n\n // ? Докидывает на ответ (Response или псевдо-ответ) служебные поля request/name.\n // ? Мутируем исходный объект (важно сохранить Response для downstream-проверок), без приведения типов.\n const addProps = (response: object, request: PreparedRequest): object => {\n return Object.assign(response, {\n request,\n ...(ABORTABLE_FETCH_CONTEXT.#isResponseAsObject ? { name: getIsOnlyAnObject(request) ? request.name || '' : '' } : {}),\n });\n };\n\n const externalRequest = Promise.all(\n requests.map((item) => {\n // Внутренний уровень (каждый запрос из массива)\n\n const safelyQuery = item.path.includes('?') ? `&${item.queryParameters.replace(/\\?/g, '')}` : item.queryParameters;\n const internalRequest = fetch(`${item.pathPrefix}${item.path}${safelyQuery}`, {\n ...item.options,\n method: item.method,\n headers: item.headers,\n ...(item.body ? { body: stringifyBody(item.body) } : {}),\n signal: abortController.signal,\n })\n // ? Докидываем инфы\n .then(async response => addProps(response, item))\n // ! ВАЖНО !\n // ! Гарантируем что каждый запрос ЗАРЕЗОЛВИТСЯ\n .catch(async (response: unknown) => {\n // ? Если fetch отработал по новому и отправил ответы с \"не 200-ми кодами\" в catch,\n // ? то ожидаем что response будет НЕ экземпляром Error, а все-таки экземпляром Response.\n // ? Поэтому в этом случае процессим его как в предыдущем then\n if (response instanceof Response) return Promise.resolve(addProps(response, item));\n\n // ? Во всех остальных случаях трактуем ситуацию как \"запрос НЕ ушел\":\n // ? промис все-равно резолвим, готдаем \"псевдо-ответ\"\n return Promise.resolve(\n addProps(\n {\n ok: false,\n status: 0,\n statusText: response,\n request: item,\n },\n item,\n ),\n );\n })\n // ? Независимо от того что сработакет ожидаем зарезолвленный промис, продолжаем then-chain\n\n // ? Отрабаиываем everyPromiseCallback\n // ? (обязательный колбек для каждого запроса, описаный на уровне экземпляра AbortableFetch)\n .then(async (res) => {\n return typeof ABORTABLE_FETCH_CONTEXT.#everyPromiseCallback === 'function' && !item.isSkipEveryPromiseCallback\n ? await ABORTABLE_FETCH_CONTEXT.#everyPromiseCallback(res)\n : res;\n })\n // ? Отрабаиываем персональныйcallback\n .then(async (res) => {\n return await (typeof item.callback === 'function' ? item.callback(res) : res);\n })\n // ? Подготавливаем структуру для внешнего уровня\n .then(async (res) => {\n return { request: item, response: res, ...(item.name ? { name: item.name } : {}) };\n });\n\n // ? Каждому внутреннему промису в прототипы лепим метод отмены всей цепочки запросов\n const internalProto: { abort?: () => void } = Object.getPrototypeOf(internalRequest);\n internalProto.abort = () => abortController.abort();\n return internalRequest;\n }),\n )\n // Внешний уровень (Promise.all)\n // ? Процессим возврат внешнего уровня (как объект)\n .then(async (resArr) => {\n // ? Если запросов нет, то возвращаем пустой объект или массив, true или \"always\" - равнозначно\n if (resArr.length < 1) {\n return ABORTABLE_FETCH_CONTEXT.#isResponseAsObject ? {} : [];\n }\n\n // ? Если #isResponseAsObject === \"always\", то независимо от количесва запросов выдаем объект\n if (ABORTABLE_FETCH_CONTEXT.#isResponseAsObject === RESPONSE_AS_OBJECT_ALWAYS_VALUE) {\n return resArr.reduce<UnknownRecord>((ac, item) => ({ ...ac, [String(item.name)]: item.response }), {});\n }\n\n // ? Если запрос один, то возвращаем его как одиночный ответ\n if (resArr.length === 1) return resArr[0].response;\n\n // ? Если дощли до сюда, то запросов больше чем 1 и нужно понять как их скомпоновать\n // ? - как объекет (#isResponseAsObject === true работает если запросов больше чем 1)\n // ? - как стандартный ответ от Promise.all (т.е. массив ответов)\n return ABORTABLE_FETCH_CONTEXT.#isResponseAsObject === true\n ? resArr.reduce<UnknownRecord>((ac, item) => ({ ...ac, [String(item.name)]: item.response }), {})\n : resArr.map(item => item.response);\n })\n // ? После отработки формата ответа проверяем/выполняем глобальный callback\n .then(async (res) => {\n return typeof ABORTABLE_FETCH_CONTEXT.#callback === 'function' ? await ABORTABLE_FETCH_CONTEXT.#callback(res) : res;\n })\n // ? На случай режекта Promise.all проверяем/выполняем глобальный catchCallback\n .catch(async (res: unknown) => {\n return typeof ABORTABLE_FETCH_CONTEXT.#catchCallback === 'function' ? await ABORTABLE_FETCH_CONTEXT.#catchCallback(res) : res;\n });\n\n // ? В прототипы Promise.all лепим метод отмены всей цепочки запросов\n const externalProto: { abort?: () => void } = Object.getPrototypeOf(externalRequest);\n externalProto.abort = () => abortController.abort();\n\n return externalRequest;\n\n function getRequestsArray(this: AbortableFetch, input: string | UnknownRecord | Array<string | UnknownRecord>): PreparedRequest[] {\n // ? Приведение к одному формату - массив объектов\n const requestsArray: Array<string | UnknownRecord> = (() => {\n if (typeof input === 'string') return [{ path: input }];\n return Array.isArray(input) ? [...input] : [input];\n })();\n\n return requestsArray.reduce<PreparedRequest[]>((ac, item, index) => {\n const itemObj: UnknownRecord = getIsOnlyAnObject(item) ? item : {};\n const { name, path, method, queryParameters, headers, body, options, callback, mergeProps, isNoPathPrefix, isSkipEveryPromiseCallback }\n = itemObj;\n\n const safelyMergeProps: UnknownRecord = getIsOnlyAnObject(mergeProps) ? mergeProps : {};\n const getMergeProps = (key: string): unknown => safelyMergeProps.all ?? safelyMergeProps[key];\n\n if (!path || typeof path !== 'string') return ac;\n\n const {\n name: omitName,\n path: omitPath,\n pathPrefix: omitPathPrefix,\n method: omitMethod,\n queryParameters: omitQueryParameters,\n headers: omitHeaders,\n body: omitBody,\n options: omitOptions,\n callback: omitCallback,\n mergeProps: omitMergeProps,\n ...optionsRest\n } = getIsOnlyAnObject(options) ? options : {};\n\n // ? Локальный метод запроса, приведённый к HttpMethod (или null, если значение не валидно).\n const localMethod: HttpMethod | null = typeof method === 'string' && isHttpMethod(method) ? method : null;\n // ? Локальный пользовательский callback, обёрнутый в типизированную функцию (без приведения типов).\n const localCallback: ItemCallback | undefined = typeof callback === 'function' ? (res: unknown) => callback(res) : undefined;\n\n return [\n ...ac,\n {\n path,\n pathPrefix: getMergeProps('pathPrefix') === 'onlyLocal' || isNoPathPrefix ? '' : this.#pathPrefix || '',\n method: ((): HttpMethod => {\n if (getMergeProps('method') === 'onlyLocal') return localMethod || 'GET';\n return getMergeProps('method') === 'onlyGlobal' ? this.#method || 'GET' : localMethod || this.#method || 'GET';\n })(),\n queryParameters: ((): string => {\n if ((getMergeProps('queryParameters') ?? getMergeProps('query')) === 'onlyLocal') {\n return this.getQueryString(this.getQueryArray(queryParameters));\n }\n return (getMergeProps('queryParameters') ?? getMergeProps('query')) === 'onlyGlobal'\n ? this.getQueryString(this.getQueryArray(this.#queryParameters))\n : this.getQueryString([...this.getQueryArray(this.#queryParameters), ...this.getQueryArray(queryParameters)]);\n })(),\n headers: ((): Headers => {\n if (getMergeProps('headers') === 'onlyLocal') return this.getHeadersObj(getIsOnlyAnObject(headers) ? headers : {});\n return getMergeProps('headers') === 'onlyGlobal'\n ? this.getHeadersObj({ ...(this.#headers || {}) })\n : this.getHeadersObj({\n ...(this.#headers || {}),\n ...(getIsOnlyAnObject(headers) ? headers : {}),\n });\n })(),\n body: ((): unknown => {\n if (getMergeProps('body') === 'onlyLocal') return body || null;\n if (getMergeProps('body') === 'onlyGlobal') return this.#body || null;\n if (body && this.#body && typeof body === typeof this.#body && typeof body === 'object') {\n return Array.isArray(body)\n ? [...(Array.isArray(this.#body) ? this.#body : []), ...body]\n : { ...(getIsOnlyAnObject(this.#body) ? this.#body : {}), ...(getIsOnlyAnObject(body) ? body : {}) };\n }\n else {\n return body || this.#body || null;\n }\n })(),\n options: ((): UnknownRecord => {\n if (getMergeProps('options') === 'onlyLocal') return { ...optionsRest };\n return getMergeProps('options') === 'onlyGlobal' ? { ...(this.#options || {}) } : { ...(this.#options || {}), ...optionsRest };\n })(),\n callback: localCallback,\n isSkipEveryPromiseCallback: Boolean(isSkipEveryPromiseCallback),\n ...(this.getIsResponseAsObject() ? { name: name && typeof name === 'string' ? name : index } : {}),\n },\n ];\n }, []);\n }\n }\n\n /** Повторяет последний выполненный запрос (ту же пачку). */\n repeatRequest(): Promise<unknown> {\n return this.request(this.requestInput);\n }\n\n // ***** getters and setters *****\n getPathPrefix(): string | null {\n return this.#pathPrefix;\n }\n\n setPathPrefix(value?: string | null): void {\n if (value && typeof value !== 'string') throw new Error('Not valid pathPrefix value!');\n this.#pathPrefix = value || null;\n }\n\n getMethod(): HttpMethod | null {\n return this.#method;\n }\n\n setMethod(value?: HttpMethod | null): void {\n if (value && !isHttpMethod(value)) throw new Error('Not valid method value!');\n this.#method = value || null;\n }\n\n getQueryParameters(): string[] | null {\n return this.#queryParameters;\n }\n\n getQueryArray(value: unknown): string[] {\n if (typeof value === 'string') {\n return (value[0] === '?' ? value.slice(1) : value).split('&');\n }\n else if (Array.isArray(value)) {\n return value.map(item => `${item}`);\n }\n else if (typeof value === 'object' && value !== null) {\n const record: UnknownRecord = getIsOnlyAnObject(value) ? value : {};\n return Object.keys(record)\n .filter(key => Boolean(key) && Boolean(record[key]))\n .map(key => `${key}=${record[key]}`);\n }\n else {\n return [];\n }\n }\n\n getQueryString(value: string[] | null): string {\n if (!value) return '';\n if (!Array.isArray(value)) throw new Error('Not valid query parameters value!');\n return value.length ? `?${value.join('&')}` : '';\n }\n\n setQueryParameters(value?: string[] | null): void {\n if (value && !Array.isArray(value)) throw new Error('Not valid query parameters value!');\n this.#queryParameters = value || null;\n }\n\n getHeaders(): UnknownRecord | null {\n return this.#headers;\n }\n\n getHeadersObj(obj: UnknownRecord): Headers {\n const headers = new Headers();\n if (!obj) return headers;\n\n if (typeof obj !== 'object' || Array.isArray(obj)) throw new Error('Not valid headers value!');\n Object.keys(obj).forEach((key) => {\n headers.append(key, `${obj[key]}`);\n });\n return headers;\n }\n\n setHeaders(value?: UnknownRecord | null): void {\n if (value && (typeof value !== 'object' || Array.isArray(value))) throw new Error('Not valid headers value!');\n this.#headers = value || null;\n }\n\n getBody(): unknown {\n return this.#body;\n }\n\n setBody(value: unknown): void {\n this.#body = value;\n }\n\n getOptions(): UnknownRecord | null {\n return this.#options;\n }\n\n setOptions(value?: UnknownRecord | null): void {\n if (value && (typeof value !== 'object' || Array.isArray(value))) throw new Error('Not valid options value!');\n this.#options = { ...value };\n }\n\n getCallback(): ResponseCallback | null {\n return this.#callback;\n }\n\n setCallback(value?: ResponseCallback | null): void {\n if (value && typeof value !== 'function') throw new Error('Not valid callback value!');\n this.#callback = value || null;\n }\n\n getCatchCallback(): ResponseCallback | null {\n return this.#catchCallback;\n }\n\n setCatchCallback(value?: ResponseCallback | null): void {\n if (value && typeof value !== 'function') throw new Error('Not valid callback value!');\n this.#catchCallback = value || null;\n }\n\n getEveryPromiseCallback(): ResponseCallback | null {\n return this.#everyPromiseCallback;\n }\n\n setEveryPromiseCallback(value?: ResponseCallback | null): void {\n if (value && typeof value !== 'function') throw new Error('Not valid callback value!');\n this.#everyPromiseCallback = value || null;\n }\n\n getIsResponseAsObject(): boolean | 'always' {\n return this.#isResponseAsObject;\n }\n\n setIsResponseAsObject(value: unknown): void {\n this.#isResponseAsObject = typeof value !== 'boolean' && value !== 'always' ? Boolean(value) : value;\n }\n\n getProps(): UnknownRecord {\n return {\n pathPrefix: this.getPathPrefix() || null,\n method: this.getMethod() || null,\n queryParameters: this.getQueryParameters() || null,\n headers: this.getHeaders() || null,\n body: this.getBody() || null,\n options: this.getOptions() || null,\n callback: this.getCallback() || null,\n everyPromiseCallback: this.getEveryPromiseCallback(),\n // isAnywayRunCallback: this.getIsAnywayRunCallback(),\n isResponseAsObject: this.getIsResponseAsObject(),\n };\n }\n\n setProps(input: UnknownRecord): void {\n const {\n pathPrefix,\n method,\n queryParameters,\n headers,\n body,\n options,\n callback,\n catchCallback,\n everyPromiseCallback,\n // isAnywayRunCallback,\n isResponseAsObject,\n } = input;\n if (pathPrefix) this.setPathPrefix(typeof pathPrefix === 'string' ? pathPrefix : null);\n if (method) this.setMethod(typeof method === 'string' && isHttpMethod(method) ? method : null);\n if (queryParameters) this.setQueryParameters(this.getQueryArray(queryParameters));\n if (headers) this.setHeaders(getIsOnlyAnObject(headers) ? headers : null);\n if (body) this.setBody(body);\n if (options) this.setOptions(getIsOnlyAnObject(options) ? options : null);\n // ? Колбэки оборачиваем с сохранением this (через .call): everyPromiseCallback/catchCallback\n // ? опираются на this === экземпляр AbortableFetch. Приведение типов не используется.\n if (callback && typeof callback === 'function') {\n const fn = callback;\n this.setCallback(function wrappedCallback(this: AbortableFetch, response: unknown) {\n return fn.call(this, response);\n });\n }\n if (catchCallback && typeof catchCallback === 'function') {\n const fn = catchCallback;\n this.setCatchCallback(function wrappedCatchCallback(this: AbortableFetch, response: unknown) {\n return fn.call(this, response);\n });\n }\n if (everyPromiseCallback && typeof everyPromiseCallback === 'function') {\n const fn = everyPromiseCallback;\n this.setEveryPromiseCallback(function wrappedEveryPromiseCallback(this: AbortableFetch, response: unknown) {\n return fn.call(this, response);\n });\n }\n // if (isAnywayRunCallback) this.setIsAnywayRunCallback(isAnywayRunCallback);\n if (isResponseAsObject !== undefined) this.setIsResponseAsObject(isResponseAsObject);\n }\n}\n\nexport default AbortableFetch;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AbortableFetch.js","names":["#isResponseAsObject","#everyPromiseCallback","#callback","#catchCallback","#pathPrefix","#method","#queryParameters","#headers","#body","#options"],"sources":["../../../../../src/Classes/RESTAPI/partials/AbortableFetch.ts"],"sourcesContent":["import type { HttpMethod, UnknownRecord } from './types';\nimport { getIsOnlyAnObject } from './_utils';\n\n// ? Колбэк обработки ответа на разных уровнях цепочки запросов.\n// ? this типизирован как AbortableFetch: everyPromiseCallback/catchCallback вызываются как\n// ? this.#callback(res) и опираются на this === экземпляр AbortableFetch.\ntype ResponseCallback = (this: AbortableFetch, response: unknown) => unknown;\n\n// ? Колбэк отдельного запроса: вызывается как item.callback(res) (без значимого this).\ntype ItemCallback = (response: unknown) => unknown;\n\n// ? Промис результата request() с дополнительным методом отмены всей цепочки запросов.\nexport type AbortablePromise<T> = Promise<T> & { abort: () => void };\n\n// ? Подготовленный (нормализованный) объект описания одного запроса для внутреннего использования.\ninterface PreparedRequest {\n path: string;\n pathPrefix: string;\n method: HttpMethod;\n queryParameters: string;\n headers: Headers;\n body: unknown;\n options: UnknownRecord;\n callback?: ItemCallback;\n isSkipEveryPromiseCallback?: boolean;\n name?: string | number;\n}\n\nconst HTTP_METHODS: readonly string[] = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH'];\n\n// ? Type-guard: является ли строка валидным HTTP-методом.\nfunction isHttpMethod(value: string): value is HttpMethod {\n return HTTP_METHODS.includes(value);\n}\n\nfunction toHttpMethod(value: unknown): HttpMethod | null {\n if (typeof value !== 'string' || !value) return null;\n const normalized = value.toUpperCase();\n if (isHttpMethod(normalized)) return normalized;\n console.error(`[RESTAPI] Невалидный HTTP-метод \"${value}\" — значение проигнорировано (сработает merge-fallback).`);\n return null;\n}\n\nconst RESPONSE_AS_OBJECT_ALWAYS_VALUE = 'always';\nclass AbortableFetch {\n #pathPrefix: string | null = null;\n\n #method: HttpMethod | null = null;\n\n #queryParameters: string[] | null = null;\n\n #headers: UnknownRecord | null = null;\n\n #body: unknown = null;\n\n #options: UnknownRecord | null = null;\n\n #callback: ResponseCallback | null = null;\n\n #catchCallback: ResponseCallback | null = null;\n\n #everyPromiseCallback: ResponseCallback | null = null;\n\n #isResponseAsObject: boolean | 'always' = false;\n\n // ? Последний вход request() — используется repeatRequest() для повторного запроса той же пачки.\n requestInput: string | UnknownRecord | Array<string | UnknownRecord> = [];\n\n constructor(input?: UnknownRecord) {\n if (input && !getIsOnlyAnObject(input)) throw new Error('Not valid input value!');\n this.getPathPrefix = this.getPathPrefix.bind(this);\n this.setPathPrefix = this.setPathPrefix.bind(this);\n this.getMethod = this.getMethod.bind(this);\n this.setMethod = this.setMethod.bind(this);\n this.getQueryParameters = this.getQueryParameters.bind(this);\n this.getQueryString = this.getQueryString.bind(this);\n this.setQueryParameters = this.setQueryParameters.bind(this);\n this.getHeaders = this.getHeaders.bind(this);\n this.getHeadersObj = this.getHeadersObj.bind(this);\n this.setHeaders = this.setHeaders.bind(this);\n this.getBody = this.getBody.bind(this);\n this.setBody = this.setBody.bind(this);\n this.getOptions = this.getOptions.bind(this);\n this.setOptions = this.setOptions.bind(this);\n this.getCallback = this.getCallback.bind(this);\n this.setCallback = this.setCallback.bind(this);\n this.getCatchCallback = this.getCatchCallback.bind(this);\n this.setCatchCallback = this.setCatchCallback.bind(this);\n this.getEveryPromiseCallback = this.getEveryPromiseCallback.bind(this);\n this.setEveryPromiseCallback = this.setEveryPromiseCallback.bind(this);\n this.getIsResponseAsObject = this.getIsResponseAsObject.bind(this);\n this.setIsResponseAsObject = this.setIsResponseAsObject.bind(this);\n this.getProps = this.getProps.bind(this);\n this.setProps = this.setProps.bind(this);\n\n this.request = this.request.bind(this);\n this.repeatRequest = this.repeatRequest.bind(this);\n this.setProps(input || {});\n }\n\n /**\n * Выполняет один или несколько HTTP-запросов (нативный fetch) с возможностью отмены.\n *\n * Метод `abort()` навешивается на прототип возвращаемого промиса (как в исходной реализации),\n * что позволяет отменить всю цепочку запросов вызовом `abort()` на возвращённом промисе.\n *\n * @param props - путь, объект описания запроса или их массив.\n * @returns Промис с результатом (форма зависит от isResponseAsObject); на прототипе доступен `abort()`.\n */\n async request(props: string | UnknownRecord | Array<string | UnknownRecord>): Promise<unknown> {\n if (!getIsOnlyAnObject(props) && !Array.isArray(props) && typeof props !== 'string') throw new Error('Not valid props value!');\n\n const stringifyBody = (b: unknown): FormData | string => (b instanceof FormData ? b : JSON.stringify(b));\n\n this.requestInput = props;\n const requests = getRequestsArray.call(this, props);\n\n const ABORTABLE_FETCH_CONTEXT = this;\n const abortController = new AbortController();\n\n // ? Докидывает на ответ (Response или псевдо-ответ) служебные поля request/name.\n // ? Мутируем исходный объект (важно сохранить Response для downstream-проверок), без приведения типов.\n const addProps = (response: object, request: PreparedRequest): object => {\n return Object.assign(response, {\n request,\n ...(ABORTABLE_FETCH_CONTEXT.#isResponseAsObject ? { name: getIsOnlyAnObject(request) ? request.name || '' : '' } : {}),\n });\n };\n\n const externalRequest = Promise.all(\n requests.map((item) => {\n // Внутренний уровень (каждый запрос из массива)\n\n const safelyQuery = item.path.includes('?') ? `&${item.queryParameters.replace(/\\?/g, '')}` : item.queryParameters;\n const internalRequest = fetch(`${item.pathPrefix}${item.path}${safelyQuery}`, {\n ...item.options,\n method: item.method,\n headers: item.headers,\n ...(item.body ? { body: stringifyBody(item.body) } : {}),\n signal: abortController.signal,\n })\n // ? Докидываем инфы\n .then(async response => addProps(response, item))\n // ! ВАЖНО !\n // ! Гарантируем что каждый запрос ЗАРЕЗОЛВИТСЯ\n .catch(async (response: unknown) => {\n // ? Если fetch отработал по новому и отправил ответы с \"не 200-ми кодами\" в catch,\n // ? то ожидаем что response будет НЕ экземпляром Error, а все-таки экземпляром Response.\n // ? Поэтому в этом случае процессим его как в предыдущем then\n if (response instanceof Response) return Promise.resolve(addProps(response, item));\n\n // ? Во всех остальных случаях трактуем ситуацию как \"запрос НЕ ушел\":\n // ? промис все-равно резолвим, готдаем \"псевдо-ответ\"\n return Promise.resolve(\n addProps(\n {\n ok: false,\n status: 0,\n statusText: response,\n request: item,\n },\n item,\n ),\n );\n })\n // ? Независимо от того что сработакет ожидаем зарезолвленный промис, продолжаем then-chain\n\n // ? Отрабаиываем everyPromiseCallback\n // ? (обязательный колбек для каждого запроса, описаный на уровне экземпляра AbortableFetch)\n .then(async (res) => {\n return typeof ABORTABLE_FETCH_CONTEXT.#everyPromiseCallback === 'function' && !item.isSkipEveryPromiseCallback\n ? await ABORTABLE_FETCH_CONTEXT.#everyPromiseCallback(res)\n : res;\n })\n // ? Отрабаиываем персональныйcallback\n .then(async (res) => {\n return await (typeof item.callback === 'function' ? item.callback(res) : res);\n })\n // ? Подготавливаем структуру для внешнего уровня\n .then(async (res) => {\n return { request: item, response: res, ...(item.name ? { name: item.name } : {}) };\n });\n\n // ? Каждому внутреннему промису в прототипы лепим метод отмены всей цепочки запросов\n const internalProto: { abort?: () => void } = Object.getPrototypeOf(internalRequest);\n internalProto.abort = () => abortController.abort();\n return internalRequest;\n }),\n )\n // Внешний уровень (Promise.all)\n // ? Процессим возврат внешнего уровня (как объект)\n .then(async (resArr) => {\n // ? Если запросов нет, то возвращаем пустой объект или массив, true или \"always\" - равнозначно\n if (resArr.length < 1) {\n return ABORTABLE_FETCH_CONTEXT.#isResponseAsObject ? {} : [];\n }\n\n // ? Если #isResponseAsObject === \"always\", то независимо от количесва запросов выдаем объект\n if (ABORTABLE_FETCH_CONTEXT.#isResponseAsObject === RESPONSE_AS_OBJECT_ALWAYS_VALUE) {\n return resArr.reduce<UnknownRecord>((ac, item) => ({ ...ac, [String(item.name)]: item.response }), {});\n }\n\n // ? Если запрос один, то возвращаем его как одиночный ответ\n if (resArr.length === 1) return resArr[0].response;\n\n // ? Если дощли до сюда, то запросов больше чем 1 и нужно понять как их скомпоновать\n // ? - как объекет (#isResponseAsObject === true работает если запросов больше чем 1)\n // ? - как стандартный ответ от Promise.all (т.е. массив ответов)\n return ABORTABLE_FETCH_CONTEXT.#isResponseAsObject === true\n ? resArr.reduce<UnknownRecord>((ac, item) => ({ ...ac, [String(item.name)]: item.response }), {})\n : resArr.map(item => item.response);\n })\n // ? После отработки формата ответа проверяем/выполняем глобальный callback\n .then(async (res) => {\n return typeof ABORTABLE_FETCH_CONTEXT.#callback === 'function' ? await ABORTABLE_FETCH_CONTEXT.#callback(res) : res;\n })\n // ? На случай режекта Promise.all проверяем/выполняем глобальный catchCallback\n .catch(async (res: unknown) => {\n return typeof ABORTABLE_FETCH_CONTEXT.#catchCallback === 'function' ? await ABORTABLE_FETCH_CONTEXT.#catchCallback(res) : res;\n });\n\n // ? В прототипы Promise.all лепим метод отмены всей цепочки запросов\n const externalProto: { abort?: () => void } = Object.getPrototypeOf(externalRequest);\n externalProto.abort = () => abortController.abort();\n\n return externalRequest;\n\n function getRequestsArray(this: AbortableFetch, input: string | UnknownRecord | Array<string | UnknownRecord>): PreparedRequest[] {\n // ? Приведение к одному формату - массив объектов\n const requestsArray: Array<string | UnknownRecord> = (() => {\n if (typeof input === 'string') return [{ path: input }];\n return Array.isArray(input) ? [...input] : [input];\n })();\n\n return requestsArray.reduce<PreparedRequest[]>((ac, item, index) => {\n const itemObj: UnknownRecord = getIsOnlyAnObject(item) ? item : {};\n const { name, path, method, queryParameters, headers, body, options, callback, mergeProps, isNoPathPrefix, isSkipEveryPromiseCallback }\n = itemObj;\n\n const safelyMergeProps: UnknownRecord = getIsOnlyAnObject(mergeProps) ? mergeProps : {};\n const getMergeProps = (key: string): unknown => safelyMergeProps.all ?? safelyMergeProps[key];\n\n if (!path || typeof path !== 'string') return ac;\n\n const {\n name: omitName,\n path: omitPath,\n pathPrefix: omitPathPrefix,\n method: omitMethod,\n queryParameters: omitQueryParameters,\n headers: omitHeaders,\n body: omitBody,\n options: omitOptions,\n callback: omitCallback,\n mergeProps: omitMergeProps,\n ...optionsRest\n } = getIsOnlyAnObject(options) ? options : {};\n\n // ? Локальный метод запроса, приведённый к HttpMethod (или null, если значение не валидно).\n const localMethod: HttpMethod | null = toHttpMethod(method);\n // ? Локальный пользовательский callback, обёрнутый в типизированную функцию (без приведения типов).\n const localCallback: ItemCallback | undefined = typeof callback === 'function' ? (res: unknown) => callback(res) : undefined;\n\n return [\n ...ac,\n {\n path,\n pathPrefix: getMergeProps('pathPrefix') === 'onlyLocal' || isNoPathPrefix ? '' : this.#pathPrefix || '',\n method: ((): HttpMethod => {\n if (getMergeProps('method') === 'onlyLocal') return localMethod || 'GET';\n return getMergeProps('method') === 'onlyGlobal' ? this.#method || 'GET' : localMethod || this.#method || 'GET';\n })(),\n queryParameters: ((): string => {\n if ((getMergeProps('queryParameters') ?? getMergeProps('query')) === 'onlyLocal') {\n return this.getQueryString(this.getQueryArray(queryParameters));\n }\n return (getMergeProps('queryParameters') ?? getMergeProps('query')) === 'onlyGlobal'\n ? this.getQueryString(this.getQueryArray(this.#queryParameters))\n : this.getQueryString([...this.getQueryArray(this.#queryParameters), ...this.getQueryArray(queryParameters)]);\n })(),\n headers: ((): Headers => {\n if (getMergeProps('headers') === 'onlyLocal') return this.getHeadersObj(getIsOnlyAnObject(headers) ? headers : {});\n return getMergeProps('headers') === 'onlyGlobal'\n ? this.getHeadersObj({ ...(this.#headers || {}) })\n : this.getHeadersObj({\n ...(this.#headers || {}),\n ...(getIsOnlyAnObject(headers) ? headers : {}),\n });\n })(),\n body: ((): unknown => {\n if (getMergeProps('body') === 'onlyLocal') return body || null;\n if (getMergeProps('body') === 'onlyGlobal') return this.#body || null;\n if (body && this.#body && typeof body === typeof this.#body && typeof body === 'object') {\n return Array.isArray(body)\n ? [...(Array.isArray(this.#body) ? this.#body : []), ...body]\n : { ...(getIsOnlyAnObject(this.#body) ? this.#body : {}), ...(getIsOnlyAnObject(body) ? body : {}) };\n }\n else {\n return body || this.#body || null;\n }\n })(),\n options: ((): UnknownRecord => {\n if (getMergeProps('options') === 'onlyLocal') return { ...optionsRest };\n return getMergeProps('options') === 'onlyGlobal' ? { ...(this.#options || {}) } : { ...(this.#options || {}), ...optionsRest };\n })(),\n callback: localCallback,\n isSkipEveryPromiseCallback: Boolean(isSkipEveryPromiseCallback),\n ...(this.getIsResponseAsObject() ? { name: name && typeof name === 'string' ? name : index } : {}),\n },\n ];\n }, []);\n }\n }\n\n /** Повторяет последний выполненный запрос (ту же пачку). */\n repeatRequest(): Promise<unknown> {\n return this.request(this.requestInput);\n }\n\n // ***** getters and setters *****\n getPathPrefix(): string | null {\n return this.#pathPrefix;\n }\n\n setPathPrefix(value?: string | null): void {\n if (value && typeof value !== 'string') throw new Error('Not valid pathPrefix value!');\n this.#pathPrefix = value || null;\n }\n\n getMethod(): HttpMethod | null {\n return this.#method;\n }\n\n setMethod(value?: HttpMethod | null): void {\n if (value && !isHttpMethod(value)) throw new Error('Not valid method value!');\n this.#method = value || null;\n }\n\n getQueryParameters(): string[] | null {\n return this.#queryParameters;\n }\n\n getQueryArray(value: unknown): string[] {\n if (typeof value === 'string') {\n return (value[0] === '?' ? value.slice(1) : value).split('&');\n }\n else if (Array.isArray(value)) {\n return value.map(item => `${item}`);\n }\n else if (typeof value === 'object' && value !== null) {\n const record: UnknownRecord = getIsOnlyAnObject(value) ? value : {};\n return Object.keys(record)\n .filter(key => Boolean(key) && Boolean(record[key]))\n .map(key => `${key}=${record[key]}`);\n }\n else {\n return [];\n }\n }\n\n getQueryString(value: string[] | null): string {\n if (!value) return '';\n if (!Array.isArray(value)) throw new Error('Not valid query parameters value!');\n return value.length ? `?${value.join('&')}` : '';\n }\n\n setQueryParameters(value?: string[] | null): void {\n if (value && !Array.isArray(value)) throw new Error('Not valid query parameters value!');\n this.#queryParameters = value || null;\n }\n\n getHeaders(): UnknownRecord | null {\n return this.#headers;\n }\n\n getHeadersObj(obj: UnknownRecord): Headers {\n const headers = new Headers();\n if (!obj) return headers;\n\n if (typeof obj !== 'object' || Array.isArray(obj)) throw new Error('Not valid headers value!');\n Object.keys(obj).forEach((key) => {\n headers.append(key, `${obj[key]}`);\n });\n return headers;\n }\n\n setHeaders(value?: UnknownRecord | null): void {\n if (value && (typeof value !== 'object' || Array.isArray(value))) throw new Error('Not valid headers value!');\n this.#headers = value || null;\n }\n\n getBody(): unknown {\n return this.#body;\n }\n\n setBody(value: unknown): void {\n this.#body = value;\n }\n\n getOptions(): UnknownRecord | null {\n return this.#options;\n }\n\n setOptions(value?: UnknownRecord | null): void {\n if (value && (typeof value !== 'object' || Array.isArray(value))) throw new Error('Not valid options value!');\n this.#options = { ...value };\n }\n\n getCallback(): ResponseCallback | null {\n return this.#callback;\n }\n\n setCallback(value?: ResponseCallback | null): void {\n if (value && typeof value !== 'function') throw new Error('Not valid callback value!');\n this.#callback = value || null;\n }\n\n getCatchCallback(): ResponseCallback | null {\n return this.#catchCallback;\n }\n\n setCatchCallback(value?: ResponseCallback | null): void {\n if (value && typeof value !== 'function') throw new Error('Not valid callback value!');\n this.#catchCallback = value || null;\n }\n\n getEveryPromiseCallback(): ResponseCallback | null {\n return this.#everyPromiseCallback;\n }\n\n setEveryPromiseCallback(value?: ResponseCallback | null): void {\n if (value && typeof value !== 'function') throw new Error('Not valid callback value!');\n this.#everyPromiseCallback = value || null;\n }\n\n getIsResponseAsObject(): boolean | 'always' {\n return this.#isResponseAsObject;\n }\n\n setIsResponseAsObject(value: unknown): void {\n this.#isResponseAsObject = typeof value !== 'boolean' && value !== 'always' ? Boolean(value) : value;\n }\n\n getProps(): UnknownRecord {\n return {\n pathPrefix: this.getPathPrefix() || null,\n method: this.getMethod() || null,\n queryParameters: this.getQueryParameters() || null,\n headers: this.getHeaders() || null,\n body: this.getBody() || null,\n options: this.getOptions() || null,\n callback: this.getCallback() || null,\n everyPromiseCallback: this.getEveryPromiseCallback(),\n // isAnywayRunCallback: this.getIsAnywayRunCallback(),\n isResponseAsObject: this.getIsResponseAsObject(),\n };\n }\n\n setProps(input: UnknownRecord): void {\n const {\n pathPrefix,\n method,\n queryParameters,\n headers,\n body,\n options,\n callback,\n catchCallback,\n everyPromiseCallback,\n // isAnywayRunCallback,\n isResponseAsObject,\n } = input;\n if (pathPrefix) this.setPathPrefix(typeof pathPrefix === 'string' ? pathPrefix : null);\n if (method) this.setMethod(toHttpMethod(method));\n if (queryParameters) this.setQueryParameters(this.getQueryArray(queryParameters));\n if (headers) this.setHeaders(getIsOnlyAnObject(headers) ? headers : null);\n if (body) this.setBody(body);\n if (options) this.setOptions(getIsOnlyAnObject(options) ? options : null);\n // ? Колбэки оборачиваем с сохранением this (через .call): everyPromiseCallback/catchCallback\n // ? опираются на this === экземпляр AbortableFetch. Приведение типов не используется.\n if (callback && typeof callback === 'function') {\n const fn = callback;\n this.setCallback(function wrappedCallback(this: AbortableFetch, response: unknown) {\n return fn.call(this, response);\n });\n }\n if (catchCallback && typeof catchCallback === 'function') {\n const fn = catchCallback;\n this.setCatchCallback(function wrappedCatchCallback(this: AbortableFetch, response: unknown) {\n return fn.call(this, response);\n });\n }\n if (everyPromiseCallback && typeof everyPromiseCallback === 'function') {\n const fn = everyPromiseCallback;\n this.setEveryPromiseCallback(function wrappedEveryPromiseCallback(this: AbortableFetch, response: unknown) {\n return fn.call(this, response);\n });\n }\n // if (isAnywayRunCallback) this.setIsAnywayRunCallback(isAnywayRunCallback);\n if (isResponseAsObject !== undefined) this.setIsResponseAsObject(isResponseAsObject);\n }\n}\n\nexport default AbortableFetch;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "intelicoreact",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.20",
|
|
5
5
|
"description": "IntelicoKit UI component library",
|
|
6
6
|
"author": "Andrey Isakov",
|
|
7
7
|
"license": "ISC",
|
|
@@ -147,6 +147,7 @@
|
|
|
147
147
|
},
|
|
148
148
|
"peerDependencies": {
|
|
149
149
|
"anme": ">=1.0.8",
|
|
150
|
+
"classnames": ">=2",
|
|
150
151
|
"react": ">=18",
|
|
151
152
|
"react-dom": ">=18",
|
|
152
153
|
"react-router-dom": ">=5"
|
|
@@ -161,7 +162,6 @@
|
|
|
161
162
|
"moment": "2.30.1",
|
|
162
163
|
"moment-timezone": "0.5.48",
|
|
163
164
|
"node-fetch": "^3.3.2",
|
|
164
|
-
"postcss-merge-rules": "^8.0.1",
|
|
165
165
|
"react-chartjs-2": "5.3.0",
|
|
166
166
|
"react-feather": "2.0.10",
|
|
167
167
|
"react-input-mask": "2.0.4",
|