intelicoreact 2.0.19 → 2.0.21

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.
Files changed (214) hide show
  1. package/dist/es/Atomic/FormElements/ActionAlert/ActionAlert.js.map +1 -1
  2. package/dist/es/Atomic/FormElements/AdvancedStatus/AdvancedStatus.js.map +1 -1
  3. package/dist/es/Atomic/FormElements/Calendar/Calendar.js +2 -1
  4. package/dist/es/Atomic/FormElements/Calendar/Calendar.js.map +1 -1
  5. package/dist/es/Atomic/FormElements/CheckboxInput/CheckboxInput.js.map +1 -1
  6. package/dist/es/Atomic/FormElements/CheckboxesLine/CheckboxesLine.js.map +1 -1
  7. package/dist/es/Atomic/FormElements/Datepicker/Datepicker.js +6 -5
  8. package/dist/es/Atomic/FormElements/Datepicker/Datepicker.js.map +1 -1
  9. package/dist/es/Atomic/FormElements/Datepicker/components/DatepickerCalendar.js +2 -1
  10. package/dist/es/Atomic/FormElements/Datepicker/components/DatepickerCalendar.js.map +1 -1
  11. package/dist/es/Atomic/FormElements/Dropdown/Dropdown.js +35 -26
  12. package/dist/es/Atomic/FormElements/Dropdown/Dropdown.js.map +1 -1
  13. package/dist/es/Atomic/FormElements/Dropdown/_utils.js +14 -9
  14. package/dist/es/Atomic/FormElements/Dropdown/_utils.js.map +1 -1
  15. package/dist/es/Atomic/FormElements/DropdownLiveSearch/DropdownLiveSearch.js.map +1 -1
  16. package/dist/es/Atomic/FormElements/FileLoader/FileLoader.js.map +1 -1
  17. package/dist/es/Atomic/FormElements/FileLoader/partial/LoadZone.js +1 -1
  18. package/dist/es/Atomic/FormElements/FileLoader/partial/LoadZone.js.map +1 -1
  19. package/dist/es/Atomic/FormElements/FileLoader/partial/LoadedContent.js +15 -13
  20. package/dist/es/Atomic/FormElements/FileLoader/partial/LoadedContent.js.map +1 -1
  21. package/dist/es/Atomic/FormElements/FileLoaderDescription/FileLoaderDescription.js +1 -1
  22. package/dist/es/Atomic/FormElements/FileLoaderDescription/FileLoaderDescription.js.map +1 -1
  23. package/dist/es/Atomic/FormElements/FileLoaderLocal/FileLoaderLocal.js +23 -19
  24. package/dist/es/Atomic/FormElements/FileLoaderLocal/FileLoaderLocal.js.map +1 -1
  25. package/dist/es/Atomic/FormElements/FileLoaderLocalGroup/FileLoaderLocalGroup.js +1 -1
  26. package/dist/es/Atomic/FormElements/FileLoaderLocalGroup/FileLoaderLocalGroup.js.map +1 -1
  27. package/dist/es/Atomic/FormElements/FormattedRawSSN/FormattedRawSSN.js.map +1 -1
  28. package/dist/es/Atomic/FormElements/Input/Input.js.map +1 -1
  29. package/dist/es/Atomic/FormElements/Input/hooks/useInputValueProcessing.js +0 -1
  30. package/dist/es/Atomic/FormElements/Input/hooks/useInputValueProcessing.js.map +1 -1
  31. package/dist/es/Atomic/FormElements/InputCalendar/InputCalendar.js.map +1 -1
  32. package/dist/es/Atomic/FormElements/InputColor/InputColor.js.map +1 -1
  33. package/dist/es/Atomic/FormElements/InputCurrency/InputCurrency.js +28 -25
  34. package/dist/es/Atomic/FormElements/InputCurrency/InputCurrency.js.map +1 -1
  35. package/dist/es/Atomic/FormElements/InputDateRange/InputDateRange.js +2 -1
  36. package/dist/es/Atomic/FormElements/InputDateRange/InputDateRange.js.map +1 -1
  37. package/dist/es/Atomic/FormElements/InputDateRange/components/DateInput.js.map +1 -1
  38. package/dist/es/Atomic/FormElements/InputDateRange/components/Datepicker.js.map +1 -1
  39. package/dist/es/Atomic/FormElements/InputDateRange/components/OpenedPart.js.map +1 -1
  40. package/dist/es/Atomic/FormElements/InputDateRange/components/SelectItem.js.map +1 -1
  41. package/dist/es/Atomic/FormElements/InputLink/InputLink.js.map +1 -1
  42. package/dist/es/Atomic/FormElements/InputMask3/InputMask3.js +16 -14
  43. package/dist/es/Atomic/FormElements/InputMask3/InputMask3.js.map +1 -1
  44. package/dist/es/Atomic/FormElements/InputWithAction/InputWithAction.js.map +1 -1
  45. package/dist/es/Atomic/FormElements/InputsRow/InputsRow.js +3 -2
  46. package/dist/es/Atomic/FormElements/InputsRow/InputsRow.js.map +1 -1
  47. package/dist/es/Atomic/FormElements/Label/Label.js.map +1 -1
  48. package/dist/es/Atomic/FormElements/MobileCalendar/MobileCalendar.js.map +1 -1
  49. package/dist/es/Atomic/FormElements/MultiSelect/MultiSelect.js.map +1 -1
  50. package/dist/es/Atomic/FormElements/RadioGroup/RadioGroup.js.map +1 -1
  51. package/dist/es/Atomic/FormElements/RadioGroupWithInput/RadioGroupWithInput.js.map +1 -1
  52. package/dist/es/Atomic/FormElements/RadioInput/RadioInput.js.map +1 -1
  53. package/dist/es/Atomic/FormElements/RadioRowSwitcher/RadioRowSwitcher.js.map +1 -1
  54. package/dist/es/Atomic/FormElements/RangeCalendar/RangeCalendar.js +2 -1
  55. package/dist/es/Atomic/FormElements/RangeCalendar/RangeCalendar.js.map +1 -1
  56. package/dist/es/Atomic/FormElements/RangeInputs/RangeInputs.js.map +1 -1
  57. package/dist/es/Atomic/FormElements/RangeList/RangeList.js.map +1 -1
  58. package/dist/es/Atomic/FormElements/RangeList/partial/RangeListRow.js.map +1 -1
  59. package/dist/es/Atomic/FormElements/RangeSlider/RangeSlider.js +9 -6
  60. package/dist/es/Atomic/FormElements/RangeSlider/RangeSlider.js.map +1 -1
  61. package/dist/es/Atomic/FormElements/RangeSlider2/RangeSlider2.js +4 -2
  62. package/dist/es/Atomic/FormElements/RangeSlider2/RangeSlider2.js.map +1 -1
  63. package/dist/es/Atomic/FormElements/SwitchableRow/SwitchableRow.js.map +1 -1
  64. package/dist/es/Atomic/FormElements/Switcher/Switcher.js.map +1 -1
  65. package/dist/es/Atomic/FormElements/SwitcherCheckbox/SwitcherCheckbox.js.map +1 -1
  66. package/dist/es/Atomic/FormElements/SwitcherHide/SwitcherHide.js.map +1 -1
  67. package/dist/es/Atomic/FormElements/SwitcherRadio/SwitcherRadio.js.map +1 -1
  68. package/dist/es/Atomic/FormElements/SwitcherRange/SwitcherRange.js.map +1 -1
  69. package/dist/es/Atomic/FormElements/SwitcherRangeList/SwitcherRangeList.js +1 -1
  70. package/dist/es/Atomic/FormElements/SwitcherRangeList/SwitcherRangeList.js.map +1 -1
  71. package/dist/es/Atomic/FormElements/SwitcherTagsDropdown/SwitcherTagsDropdown.js.map +1 -1
  72. package/dist/es/Atomic/FormElements/SwitcherTextarea/SwitcherTextarea.js.map +1 -1
  73. package/dist/es/Atomic/FormElements/TagsDropdown/TagsDropdown.js.map +1 -1
  74. package/dist/es/Atomic/FormElements/Text/Text.js.map +1 -1
  75. package/dist/es/Atomic/FormElements/TextSwitcher/TextSwitcher.js.map +1 -1
  76. package/dist/es/Atomic/FormElements/Textarea/Textarea.js.map +1 -1
  77. package/dist/es/Atomic/FormElements/TieredCheckboxes/TieredCheckboxes.js +4 -2
  78. package/dist/es/Atomic/FormElements/TieredCheckboxes/TieredCheckboxes.js.map +1 -1
  79. package/dist/es/Atomic/FormElements/TieredCheckboxes/partial/AccordionWithCheckbox.js.map +1 -1
  80. package/dist/es/Atomic/FormElements/TimeRange/TimeRange.js.map +1 -1
  81. package/dist/es/Atomic/FormElements/UserContacts/UserContacts.js.map +1 -1
  82. package/dist/es/Atomic/Layout/Header/Header.js.map +1 -1
  83. package/dist/es/Atomic/Layout/MainMenu/MainMenu.js.map +1 -1
  84. package/dist/es/Atomic/Layout/Spinner/Spinner.js.map +1 -1
  85. package/dist/es/Atomic/UI/Accordion/Accordion.js.map +1 -1
  86. package/dist/es/Atomic/UI/Accordion/AccordionItem.js.map +1 -1
  87. package/dist/es/Atomic/UI/AdvancedTag/AdvTag.js +2 -1
  88. package/dist/es/Atomic/UI/AdvancedTag/AdvTag.js.map +1 -1
  89. package/dist/es/Atomic/UI/AdvancedTag/AdvancedTags.js.map +1 -1
  90. package/dist/es/Atomic/UI/Alert/Alert.js.map +1 -1
  91. package/dist/es/Atomic/UI/Arrow/Arrow.js.map +1 -1
  92. package/dist/es/Atomic/UI/Button/Button.js.map +1 -1
  93. package/dist/es/Atomic/UI/ButtonsBar/ButtonsBar.js.map +1 -1
  94. package/dist/es/Atomic/UI/Chart/Chart.js +2 -1
  95. package/dist/es/Atomic/UI/Chart/Chart.js.map +1 -1
  96. package/dist/es/Atomic/UI/Chart/partial/ChartTypeSwitcherIcon/ChartTypeSwitcherIcon.js.map +1 -1
  97. package/dist/es/Atomic/UI/Chart/partial/utils.js +2 -1
  98. package/dist/es/Atomic/UI/Chart/partial/utils.js.map +1 -1
  99. package/dist/es/Atomic/UI/DateTime/DateTime.js.map +1 -1
  100. package/dist/es/Atomic/UI/DebugContainer/DebugContainer.js.map +1 -1
  101. package/dist/es/Atomic/UI/DoubleString/DoubleString.js.map +1 -1
  102. package/dist/es/Atomic/UI/Hint/Hint.js +8 -12
  103. package/dist/es/Atomic/UI/Hint/Hint.js.map +1 -1
  104. package/dist/es/Atomic/UI/Hint/partials/_utils.js.map +1 -1
  105. package/dist/es/Atomic/UI/Modal/Modal.js.map +1 -1
  106. package/dist/es/Atomic/UI/Modal/ModalHOC.js.map +1 -1
  107. package/dist/es/Atomic/UI/Modal/partials/ModalTitle.js.map +1 -1
  108. package/dist/es/Atomic/UI/Modal/partials/_constants.js.map +1 -1
  109. package/dist/es/Atomic/UI/Modal/partials/_utils.js +1 -4
  110. package/dist/es/Atomic/UI/Modal/partials/_utils.js.map +1 -1
  111. package/dist/es/Atomic/UI/Modal/partials/useMobileModal.js +17 -10
  112. package/dist/es/Atomic/UI/Modal/partials/useMobileModal.js.map +1 -1
  113. package/dist/es/Atomic/UI/NavLine/NavLine.js.map +1 -1
  114. package/dist/es/Atomic/UI/PageTitle/PageTitle.js.map +1 -1
  115. package/dist/es/Atomic/UI/Price/Price.js.map +1 -1
  116. package/dist/es/Atomic/UI/PriceRange/PriceRange.js.map +1 -1
  117. package/dist/es/Atomic/UI/ProgressLine/ProgressLine.js.map +1 -1
  118. package/dist/es/Atomic/UI/Status/Status.js.map +1 -1
  119. package/dist/es/Atomic/UI/Tag/Tag.js.map +1 -1
  120. package/dist/es/Atomic/UI/TagList/TagList.js.map +1 -1
  121. package/dist/es/Atomic/UI/UserBox/UserBox.js.map +1 -1
  122. package/dist/es/Atomic/UI/WizardStepper/ui/StateIcon/StateIcon.js.map +1 -1
  123. package/dist/es/Atomic/UI/WizardStepper/ui/StepRow/StepRow.js.map +1 -1
  124. package/dist/es/Atomic/UI/WizardStepper/ui/StepWrapper/StepWrapper.js.map +1 -1
  125. package/dist/es/Atomic/UI/WizardStepper/ui/icons.js.map +1 -1
  126. package/dist/es/Classes/RESTAPI/partials/AbortableFetch.js +9 -2
  127. package/dist/es/Classes/RESTAPI/partials/AbortableFetch.js.map +1 -1
  128. package/dist/es/Classes/RESTAPI/partials/CredentialsProcessing.js +4 -2
  129. package/dist/es/Classes/RESTAPI/partials/CredentialsProcessing.js.map +1 -1
  130. package/dist/es/Classes/RESTAPI/partials/sse.js +4 -7
  131. package/dist/es/Classes/RESTAPI/partials/sse.js.map +1 -1
  132. package/dist/es/Functions/fieldValueFormatters.js +1 -3
  133. package/dist/es/Functions/fieldValueFormatters.js.map +1 -1
  134. package/dist/es/Functions/operations.js +22 -20
  135. package/dist/es/Functions/operations.js.map +1 -1
  136. package/dist/es/Functions/useFormTools/form-drivers/ObjectWithIterableObjects.js +8 -6
  137. package/dist/es/Functions/useFormTools/form-drivers/ObjectWithIterableObjects.js.map +1 -1
  138. package/dist/es/Functions/useFormTools/functions/General.js +8 -6
  139. package/dist/es/Functions/useFormTools/functions/General.js.map +1 -1
  140. package/dist/es/Functions/useFormTools/functions/RenderFields.js +6 -5
  141. package/dist/es/Functions/useFormTools/functions/RenderFields.js.map +1 -1
  142. package/dist/es/Functions/useFormTools/index.js +1 -4
  143. package/dist/es/Functions/useFormTools/index.js.map +1 -1
  144. package/dist/es/Functions/utils.js +2 -1
  145. package/dist/es/Functions/utils.js.map +1 -1
  146. package/dist/es/Molecular/CustomIcons/components/AffiliateNetworks.js.map +1 -1
  147. package/dist/es/Molecular/CustomIcons/components/AlertCircle.js.map +1 -1
  148. package/dist/es/Molecular/CustomIcons/components/AppStore.js.map +1 -1
  149. package/dist/es/Molecular/CustomIcons/components/Arrow.js.map +1 -1
  150. package/dist/es/Molecular/CustomIcons/components/ArrowDown.js.map +1 -1
  151. package/dist/es/Molecular/CustomIcons/components/ArrowLeft.js.map +1 -1
  152. package/dist/es/Molecular/CustomIcons/components/ArrowRight.js.map +1 -1
  153. package/dist/es/Molecular/CustomIcons/components/ArrowUp.js.map +1 -1
  154. package/dist/es/Molecular/CustomIcons/components/Bell.js.map +1 -1
  155. package/dist/es/Molecular/CustomIcons/components/Button.js.map +1 -1
  156. package/dist/es/Molecular/CustomIcons/components/Campaigns.js.map +1 -1
  157. package/dist/es/Molecular/CustomIcons/components/Check.js.map +1 -1
  158. package/dist/es/Molecular/CustomIcons/components/Check2.js.map +1 -1
  159. package/dist/es/Molecular/CustomIcons/components/ChevronDown.js.map +1 -1
  160. package/dist/es/Molecular/CustomIcons/components/ChevronDownDisabled.js.map +1 -1
  161. package/dist/es/Molecular/CustomIcons/components/ChevronLeft.js.map +1 -1
  162. package/dist/es/Molecular/CustomIcons/components/ChevronRight.js.map +1 -1
  163. package/dist/es/Molecular/CustomIcons/components/ChevronUp.js.map +1 -1
  164. package/dist/es/Molecular/CustomIcons/components/ChevronUpDown.js.map +1 -1
  165. package/dist/es/Molecular/CustomIcons/components/Close.js.map +1 -1
  166. package/dist/es/Molecular/CustomIcons/components/ColumnsOrder.js.map +1 -1
  167. package/dist/es/Molecular/CustomIcons/components/Delete.js.map +1 -1
  168. package/dist/es/Molecular/CustomIcons/components/Edit.js.map +1 -1
  169. package/dist/es/Molecular/CustomIcons/components/Email.js.map +1 -1
  170. package/dist/es/Molecular/CustomIcons/components/FinturfLogo.js.map +1 -1
  171. package/dist/es/Molecular/CustomIcons/components/FinturfLogo2.js.map +1 -1
  172. package/dist/es/Molecular/CustomIcons/components/Flows.js.map +1 -1
  173. package/dist/es/Molecular/CustomIcons/components/Gift.js.map +1 -1
  174. package/dist/es/Molecular/CustomIcons/components/GoogleAuth.js.map +1 -1
  175. package/dist/es/Molecular/CustomIcons/components/GooglePlay.js.map +1 -1
  176. package/dist/es/Molecular/CustomIcons/components/HelpCircle.js.map +1 -1
  177. package/dist/es/Molecular/CustomIcons/components/HelpCircle2.js.map +1 -1
  178. package/dist/es/Molecular/CustomIcons/components/HelpCircleFilled.js.map +1 -1
  179. package/dist/es/Molecular/CustomIcons/components/Home.js.map +1 -1
  180. package/dist/es/Molecular/CustomIcons/components/Home2.js.map +1 -1
  181. package/dist/es/Molecular/CustomIcons/components/Key.js.map +1 -1
  182. package/dist/es/Molecular/CustomIcons/components/Landers.js.map +1 -1
  183. package/dist/es/Molecular/CustomIcons/components/Lock.js.map +1 -1
  184. package/dist/es/Molecular/CustomIcons/components/Mail.js.map +1 -1
  185. package/dist/es/Molecular/CustomIcons/components/Mastercard.js.map +1 -1
  186. package/dist/es/Molecular/CustomIcons/components/Minus.js.map +1 -1
  187. package/dist/es/Molecular/CustomIcons/components/Offers.js.map +1 -1
  188. package/dist/es/Molecular/CustomIcons/components/Pause.js.map +1 -1
  189. package/dist/es/Molecular/CustomIcons/components/PayPal.js.map +1 -1
  190. package/dist/es/Molecular/CustomIcons/components/PayPalLightLarge.js.map +1 -1
  191. package/dist/es/Molecular/CustomIcons/components/Phone.js.map +1 -1
  192. package/dist/es/Molecular/CustomIcons/components/Play.js.map +1 -1
  193. package/dist/es/Molecular/CustomIcons/components/Plus.js.map +1 -1
  194. package/dist/es/Molecular/CustomIcons/components/Profile.js.map +1 -1
  195. package/dist/es/Molecular/CustomIcons/components/QRCode.js.map +1 -1
  196. package/dist/es/Molecular/CustomIcons/components/Rectangle.js.map +1 -1
  197. package/dist/es/Molecular/CustomIcons/components/Revert.js.map +1 -1
  198. package/dist/es/Molecular/CustomIcons/components/Star.js.map +1 -1
  199. package/dist/es/Molecular/CustomIcons/components/Star2.js.map +1 -1
  200. package/dist/es/Molecular/CustomIcons/components/TrafficSources.js.map +1 -1
  201. package/dist/es/Molecular/CustomIcons/components/Trash.js.map +1 -1
  202. package/dist/es/Molecular/CustomIcons/components/TrashRed.js.map +1 -1
  203. package/dist/es/Molecular/CustomIcons/components/Triggers.js.map +1 -1
  204. package/dist/es/Molecular/CustomIcons/components/User.js.map +1 -1
  205. package/dist/es/Molecular/CustomIcons/components/Visa.js.map +1 -1
  206. package/dist/es/Molecular/CustomIcons/components/X.js.map +1 -1
  207. package/dist/es/Molecular/FormElement/FormElement.js.map +1 -1
  208. package/dist/es/Molecular/InputAddress/InputAddress.js +24 -19
  209. package/dist/es/Molecular/InputAddress/InputAddress.js.map +1 -1
  210. package/dist/es/Molecular/InputCustomFetch/InputCustomFetch.js +17 -11
  211. package/dist/es/Molecular/InputCustomFetch/InputCustomFetch.js.map +1 -1
  212. package/dist/es/Molecular/InputPassword/InputPassword.js.map +1 -1
  213. package/package.json +2 -2
  214. /package/dist/es/Atomic/FormElements/{SwitcherRangeList/SwitcherRangeList.styles.css → Datepicker/Datepicker.styles.css} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"TagList.js","names":[],"sources":["../../../../../src/Atomic/UI/TagList/TagList.tsx"],"sourcesContent":["import type { ITagProps } from '../Tag/Tag.interface';\n\nimport type { ITagListProps } from './TagList.interface';\nimport cn from 'classnames';\n\nimport {\n createRef,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport { Edit3 } from 'react-feather';\n\nimport { checkedRef } from '../../../Functions/utils';\nimport Tag from '../Tag/Tag';\nimport './TagList.scss';\n\nconst TagList: React.FC<ITagListProps> = ({\n disabled,\n className,\n onTagClick,\n removeItem,\n items,\n withToggle = true,\n disableShowMore = false,\n shownItemsCount = 'auto',\n testId = 'test-taglist',\n refProp,\n\n renderOrder,\n\n onEditClick,\n onToggleRenderAll,\n isUseInTable,\n}) => {\n const wrapperRef = useRef<HTMLDivElement | null>(null);\n const [tagList, setTagList] = useState<(ITagProps & { itemRef: React.RefObject<HTMLDivElement> })[]>([]);\n\n const [staticTagsCount, setStaticTagsCount] = useState(-1);\n const [renderItemsCount, setRenderItemsCount] = useState(-1);\n const [renderAll, setRenderAll] = useState(!withToggle);\n\n const wrapperWidth\n = wrapperRef?.current?.getBoundingClientRect()?.width ?? -1;\n\n const setRenderAllInterceptor = (v: boolean, event: any): void => {\n setRenderAll(v);\n onToggleRenderAll?.(v);\n event?.stopPropagation();\n event?.preventDefault();\n };\n\n const getStaticTagsCount = (computedWidth: number): number => {\n if (typeof shownItemsCount === 'number') return shownItemsCount;\n\n const delta = typeof onEditClick === 'function' ? 60 : 32;\n const result = tagList.reduce <{\n count: number;\n width: number;\n items: { w: number; r: HTMLDivElement | null }[];\n skip?: boolean;\n }>((result, { itemRef }, index) => {\n if (result.skip) return result;\n\n const itemStyle\n = itemRef?.current && window.getComputedStyle(itemRef.current);\n\n const itemWidth = [\n Number.parseInt((itemRef.current?.getBoundingClientRect()?.width ?? 0).toString(), 10),\n Number.parseInt((itemStyle?.marginLeft ?? 0).toString(), 10),\n Number.parseInt((itemStyle?.marginRight ?? 0).toString(), 10),\n ].reduce((result, item) => {\n if (!Number.isNaN(item)) result += item;\n return result;\n }, 0);\n\n if (\n (!Number.isNaN(itemWidth)\n && itemWidth > 0\n && itemWidth + result.width < computedWidth - delta)\n || index === 0\n ) {\n result = {\n count: result.count + 1,\n width: result.width + itemWidth,\n items: [...result.items, { w: itemWidth, r: itemRef?.current }],\n };\n }\n else {\n result.skip = true;\n }\n\n return result;\n }, { count: 0, width: 0, items: [], skip: false });\n if (result?.items?.length === 1 && result.items[0].r && tagList.length > 1) {\n result.items[0].r.style.maxWidth = `${computedWidth - delta - 8}px`;\n }\n\n return result?.count;\n };\n\n const cancelDefault = (_e: string | undefined, cb: () => void): void => {\n cb?.();\n };\n\n const renderTags = (): (JSX.Element | null)[] => {\n const tagsRenderOrder\n = renderOrder ?? tagList.map(({ value, id }) => id ?? value);\n\n return tagsRenderOrder.map((v, i) => {\n const item = tagList.find(({ value, id }) => {\n // НЕ РЕФАКТОРИТЬ вариант через || дает необъяснимый сайд эффект\n if (id) return id === v; // сначала ищем по id\n if (value) return value === v; // потом по value\n return false;\n });\n\n if (!item) return null;\n\n const isHidden\n = renderItemsCount !== -1 && staticTagsCount !== -1\n ? i >= renderItemsCount\n : false;\n\n return (\n <div\n className={`tag-list_wrapper_item ${isHidden ? 'tag-list_wrapper_item--hidden' : ''}`}\n key={`tag-list-item-${item?.id ?? item?.value}`}\n ref={checkedRef(item?.itemRef)}\n >\n <Tag\n testId={`test-taglist-item-${item?.id ?? item?.value}`}\n {...item}\n onClick={onTagClick}\n removeItem={removeItem}\n isUseInTable={isUseInTable}\n />\n </div>\n );\n });\n };\n\n const renderMoreTags = (): JSX.Element | null => {\n if (\n (typeof shownItemsCount === 'number' && tagList?.length < shownItemsCount)\n || !tagList?.length\n || disableShowMore\n ) {\n return null;\n }\n const restItems = tagList.length - renderItemsCount;\n\n if (restItems === 0 || !withToggle || staticTagsCount === -1) return null;\n\n return (\n <Tag\n label={`+${restItems}`}\n className=\"tag-list_wrapper_render-more\"\n onClick={\n disableShowMore\n ? () => {}\n : (value, event) => cancelDefault(value, () => setRenderAllInterceptor(true, event))\n }\n isUseInTable={isUseInTable}\n />\n );\n };\n const renderHideTags = (): JSX.Element | null => {\n if (\n renderItemsCount !== tagList?.length\n || !withToggle\n || staticTagsCount === -1\n || staticTagsCount === tagList?.length\n ) {\n return null;\n }\n\n return (\n <Tag\n label=\"...\"\n className=\"tag-list_wrapper_hide-more\"\n onClick={(value, event) => cancelDefault(value, () => setRenderAllInterceptor(false, event))}\n isUseInTable={isUseInTable}\n />\n );\n };\n\n // Set TagList Items\n useEffect(() => {\n setStaticTagsCount(-1);\n setRenderItemsCount(-1);\n setRenderAllInterceptor(false, null);\n const itemsWithRef = items.map(item => ({ ...item, itemRef: createRef<HTMLDivElement>() }));\n setTagList(itemsWithRef);\n }, [items]);\n\n // Count Row Tags\n useLayoutEffect(() => {\n if (withToggle && wrapperWidth !== -1 && staticTagsCount === -1) {\n let computedWidth = wrapperWidth;\n\n if (computedWidth === 0) {\n computedWidth = Number.parseInt(\n (wrapperRef?.current\n ? window.getComputedStyle(wrapperRef?.current)?.width\n : 0).toString(),\n );\n }\n\n if (!Number.isNaN(computedWidth)) {\n setStaticTagsCount(getStaticTagsCount(computedWidth));\n }\n }\n }, [tagList, wrapperWidth, wrapperRef?.current]);\n\n //\n useLayoutEffect(() => {\n setRenderItemsCount(staticTagsCount);\n }, [staticTagsCount]);\n\n // Toggle Show/Hide More Tags\n useEffect(() => {\n setRenderItemsCount(renderAll ? tagList?.length : staticTagsCount);\n }, [renderAll]);\n\n useEffect(() => {\n if (wrapperRef?.current && refProp) refProp.current = wrapperRef?.current;\n }, [wrapperRef?.current]);\n\n return (\n <div\n data-testid={testId}\n className={cn(\n 'tag-list_wrapper',\n `${\n renderItemsCount !== tagList?.length\n || !withToggle\n || staticTagsCount === -1\n || staticTagsCount === tagList?.length\n ? 'tag-list_wrapper--only-static-items'\n : 'tag-list_wrapper--all-items'\n }`,\n className,\n { 'tag-list_wrapper--disabled': disabled },\n )}\n style={{\n visibility: staticTagsCount === -1 ? 'hidden' : 'visible',\n zIndex: staticTagsCount === -1 ? '-1' : 'auto',\n }}\n ref={wrapperRef}\n >\n {renderTags()}\n {renderMoreTags()}\n {renderHideTags()}\n {typeof onEditClick === 'function' && (\n <div className=\"tag-list__edit-trigger\">\n <Edit3 onClick={onEditClick} />\n </div>\n )}\n </div>\n );\n}\n\nexport default TagList;\n"],"mappings":"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"}
1
+ {"version":3,"file":"TagList.js","names":[],"sources":["../../../../../src/Atomic/UI/TagList/TagList.tsx"],"sourcesContent":["import type { ITagProps } from '../Tag/Tag.interface';\n\nimport type { ITagListProps } from './TagList.interface';\nimport cn from 'classnames';\n\nimport {\n createRef,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport { Edit3 } from 'react-feather';\n\nimport { checkedRef } from '../../../Functions/utils';\nimport Tag from '../Tag/Tag';\nimport './TagList.scss';\n\nconst TagList: React.FC<ITagListProps> = ({\n disabled,\n className,\n onTagClick,\n removeItem,\n items,\n withToggle = true,\n disableShowMore = false,\n shownItemsCount = 'auto',\n testId = 'test-taglist',\n refProp,\n\n renderOrder,\n\n onEditClick,\n onToggleRenderAll,\n isUseInTable,\n}) => {\n const wrapperRef = useRef<HTMLDivElement | null>(null);\n const [tagList, setTagList] = useState<(ITagProps & { itemRef: React.RefObject<HTMLDivElement> })[]>([]);\n\n const [staticTagsCount, setStaticTagsCount] = useState(-1);\n const [renderItemsCount, setRenderItemsCount] = useState(-1);\n const [renderAll, setRenderAll] = useState(!withToggle);\n\n const wrapperWidth\n = wrapperRef?.current?.getBoundingClientRect()?.width ?? -1;\n\n const setRenderAllInterceptor = (v: boolean, event: any): void => {\n setRenderAll(v);\n onToggleRenderAll?.(v);\n event?.stopPropagation();\n event?.preventDefault();\n };\n\n const getStaticTagsCount = (computedWidth: number): number => {\n if (typeof shownItemsCount === 'number') return shownItemsCount;\n\n const delta = typeof onEditClick === 'function' ? 60 : 32;\n const result = tagList.reduce <{\n count: number;\n width: number;\n items: { w: number; r: HTMLDivElement | null }[];\n skip?: boolean;\n }>((result, { itemRef }, index) => {\n if (result.skip) return result;\n\n const itemStyle\n = itemRef?.current && window.getComputedStyle(itemRef.current);\n\n const itemWidth = [\n Number.parseInt((itemRef.current?.getBoundingClientRect()?.width ?? 0).toString(), 10),\n Number.parseInt((itemStyle?.marginLeft ?? 0).toString(), 10),\n Number.parseInt((itemStyle?.marginRight ?? 0).toString(), 10),\n ].reduce((result, item) => {\n if (!Number.isNaN(item)) result += item;\n return result;\n }, 0);\n\n if (\n (!Number.isNaN(itemWidth)\n && itemWidth > 0\n && itemWidth + result.width < computedWidth - delta)\n || index === 0\n ) {\n result = {\n count: result.count + 1,\n width: result.width + itemWidth,\n items: [...result.items, { w: itemWidth, r: itemRef?.current }],\n };\n }\n else {\n result.skip = true;\n }\n\n return result;\n }, { count: 0, width: 0, items: [], skip: false });\n if (result?.items?.length === 1 && result.items[0].r && tagList.length > 1) {\n result.items[0].r.style.maxWidth = `${computedWidth - delta - 8}px`;\n }\n\n return result?.count;\n };\n\n const cancelDefault = (_e: string | undefined, cb: () => void): void => {\n cb?.();\n };\n\n const renderTags = (): (JSX.Element | null)[] => {\n const tagsRenderOrder\n = renderOrder ?? tagList.map(({ value, id }) => id ?? value);\n\n return tagsRenderOrder.map((v, i) => {\n const item = tagList.find(({ value, id }) => {\n // НЕ РЕФАКТОРИТЬ вариант через || дает необъяснимый сайд эффект\n if (id) return id === v; // сначала ищем по id\n if (value) return value === v; // потом по value\n return false;\n });\n\n if (!item) return null;\n\n const isHidden\n = renderItemsCount !== -1 && staticTagsCount !== -1\n ? i >= renderItemsCount\n : false;\n\n return (\n <div\n className={`tag-list_wrapper_item ${isHidden ? 'tag-list_wrapper_item--hidden' : ''}`}\n key={`tag-list-item-${item?.id ?? item?.value}`}\n ref={checkedRef(item?.itemRef)}\n >\n <Tag\n testId={`test-taglist-item-${item?.id ?? item?.value}`}\n {...item}\n onClick={onTagClick}\n removeItem={removeItem}\n isUseInTable={isUseInTable}\n />\n </div>\n );\n });\n };\n\n const renderMoreTags = (): JSX.Element | null => {\n if (\n (typeof shownItemsCount === 'number' && tagList?.length < shownItemsCount)\n || !tagList?.length\n || disableShowMore\n ) {\n return null;\n }\n const restItems = tagList.length - renderItemsCount;\n\n if (restItems === 0 || !withToggle || staticTagsCount === -1) return null;\n\n return (\n <Tag\n label={`+${restItems}`}\n className=\"tag-list_wrapper_render-more\"\n onClick={\n disableShowMore\n ? () => {}\n : (value, event) => cancelDefault(value, () => setRenderAllInterceptor(true, event))\n }\n isUseInTable={isUseInTable}\n />\n );\n };\n const renderHideTags = (): JSX.Element | null => {\n if (\n renderItemsCount !== tagList?.length\n || !withToggle\n || staticTagsCount === -1\n || staticTagsCount === tagList?.length\n ) {\n return null;\n }\n\n return (\n <Tag\n label=\"...\"\n className=\"tag-list_wrapper_hide-more\"\n onClick={(value, event) => cancelDefault(value, () => setRenderAllInterceptor(false, event))}\n isUseInTable={isUseInTable}\n />\n );\n };\n\n // Set TagList Items\n useEffect(() => {\n setStaticTagsCount(-1);\n setRenderItemsCount(-1);\n setRenderAllInterceptor(false, null);\n const itemsWithRef = items.map(item => ({ ...item, itemRef: createRef<HTMLDivElement>() }));\n setTagList(itemsWithRef);\n }, [items]);\n\n // Count Row Tags\n useLayoutEffect(() => {\n if (withToggle && wrapperWidth !== -1 && staticTagsCount === -1) {\n let computedWidth = wrapperWidth;\n\n if (computedWidth === 0) {\n computedWidth = Number.parseInt(\n (wrapperRef?.current\n ? window.getComputedStyle(wrapperRef?.current)?.width\n : 0).toString(),\n );\n }\n\n if (!Number.isNaN(computedWidth)) {\n setStaticTagsCount(getStaticTagsCount(computedWidth));\n }\n }\n }, [tagList, wrapperWidth, wrapperRef?.current]);\n\n //\n useLayoutEffect(() => {\n setRenderItemsCount(staticTagsCount);\n }, [staticTagsCount]);\n\n // Toggle Show/Hide More Tags\n useEffect(() => {\n setRenderItemsCount(renderAll ? tagList?.length : staticTagsCount);\n }, [renderAll]);\n\n useEffect(() => {\n if (wrapperRef?.current && refProp) refProp.current = wrapperRef?.current;\n }, [wrapperRef?.current]);\n\n return (\n <div\n data-testid={testId}\n className={cn(\n 'tag-list_wrapper',\n `${\n renderItemsCount !== tagList?.length\n || !withToggle\n || staticTagsCount === -1\n || staticTagsCount === tagList?.length\n ? 'tag-list_wrapper--only-static-items'\n : 'tag-list_wrapper--all-items'\n }`,\n className,\n { 'tag-list_wrapper--disabled': disabled },\n )}\n style={{\n visibility: staticTagsCount === -1 ? 'hidden' : 'visible',\n zIndex: staticTagsCount === -1 ? '-1' : 'auto',\n }}\n ref={wrapperRef}\n >\n {renderTags()}\n {renderMoreTags()}\n {renderHideTags()}\n {typeof onEditClick === 'function' && (\n <div className=\"tag-list__edit-trigger\">\n <Edit3 onClick={onEditClick} />\n </div>\n )}\n </div>\n );\n}\n\nexport default TagList;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"UserBox.js","names":[],"sources":["../../../../../src/Atomic/UI/UserBox/UserBox.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { IUserBoxProps } from './UserBox.interface';\nimport cn from 'classnames';\n\nimport React from 'react';\nimport { getColorById } from '../../../Functions/utils';\n\nimport Label from '../../FormElements/Label/Label';\nimport Button from '../Button/Button';\n\nimport './UserBox.scss';\n\nconst UserBox: React.FC<IUserBoxProps> = ({\n name = 'Username',\n role,\n id,\n onClick,\n isModal,\n className,\n colors,\n testId = 'userbox',\n}) => {\n const getNameFirstLetter = name.charAt(0).toUpperCase();\n\n const renderUser = (): ReactNode => {\n if (isModal) {\n return (\n <>\n <div style={{ backgroundColor: getColorById(id, colors) }} className=\"td-user-box__avatar\">\n {getNameFirstLetter}\n </div>\n <div className=\"td-user-box__user-data\">\n <Button className=\"p0 no-shadow\" onClick={onClick} label={name} variant=\"link\" />\n {role && <span>{role}</span>}\n </div>\n </>\n );\n }\n else {\n return (\n <>\n <div style={{ backgroundColor: getColorById(id) }} className=\"td-user-box__avatar\">\n {getNameFirstLetter}\n </div>\n <div className=\"td-user-box__user-data\">\n <Label label={name} />\n {role && <span aria-label={`User role: ${role}`}>{role}</span>}\n </div>\n </>\n );\n }\n };\n\n return (\n <div\n data-testid={testId}\n className={cn('td-user-box', className)}\n role=\"region\"\n aria-label={`User box for ${name}`}\n >\n {renderUser()}\n </div>\n );\n};\n\nexport default UserBox;\n"],"mappings":";;;;;;;;AAYA,IAAM,WAAoC,EACxC,OAAO,YACP,MACA,IACA,SACA,SACA,WACA,QACA,SAAS,gBACL;CACJ,MAAM,qBAAqB,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY;CAEtD,MAAM,mBAA8B;EAClC,IAAI,SACF,OACE,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,OAAD;GAAK,OAAO,EAAE,iBAAiB,aAAa,IAAI,MAAM,EAAE;GAAG,WAAU;aAClE;EACE,CAAA,GACL,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,QAAD;IAAQ,WAAU;IAAwB;IAAS,OAAO;IAAM,SAAQ;GAAQ,CAAA,GAC/E,QAAQ,oBAAC,QAAD,EAAA,UAAO,KAAW,CAAA,CACxB;IACL,EAAA,CAAA;OAIJ,OACE,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,OAAD;GAAK,OAAO,EAAE,iBAAiB,aAAa,EAAE,EAAE;GAAG,WAAU;aAC1D;EACE,CAAA,GACL,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,OAAD,EAAO,OAAO,KAAO,CAAA,GACpB,QAAQ,oBAAC,QAAD;IAAM,cAAY,cAAc;cAAS;GAAW,CAAA,CAC1D;IACL,EAAA,CAAA;CAGR;CAEA,OACE,oBAAC,OAAD;EACE,eAAa;EACb,WAAW,GAAG,eAAe,SAAS;EACtC,MAAK;EACL,cAAY,gBAAgB;YAE3B,WAAW;CACT,CAAA;AAET"}
1
+ {"version":3,"file":"UserBox.js","names":[],"sources":["../../../../../src/Atomic/UI/UserBox/UserBox.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { IUserBoxProps } from './UserBox.interface';\nimport cn from 'classnames';\n\nimport React from 'react';\nimport { getColorById } from '../../../Functions/utils';\n\nimport Label from '../../FormElements/Label/Label';\nimport Button from '../Button/Button';\n\nimport './UserBox.scss';\n\nconst UserBox: React.FC<IUserBoxProps> = ({\n name = 'Username',\n role,\n id,\n onClick,\n isModal,\n className,\n colors,\n testId = 'userbox',\n}) => {\n const getNameFirstLetter = name.charAt(0).toUpperCase();\n\n const renderUser = (): ReactNode => {\n if (isModal) {\n return (\n <>\n <div style={{ backgroundColor: getColorById(id, colors) }} className=\"td-user-box__avatar\">\n {getNameFirstLetter}\n </div>\n <div className=\"td-user-box__user-data\">\n <Button className=\"p0 no-shadow\" onClick={onClick} label={name} variant=\"link\" />\n {role && <span>{role}</span>}\n </div>\n </>\n );\n }\n else {\n return (\n <>\n <div style={{ backgroundColor: getColorById(id) }} className=\"td-user-box__avatar\">\n {getNameFirstLetter}\n </div>\n <div className=\"td-user-box__user-data\">\n <Label label={name} />\n {role && <span aria-label={`User role: ${role}`}>{role}</span>}\n </div>\n </>\n );\n }\n };\n\n return (\n <div\n data-testid={testId}\n className={cn('td-user-box', className)}\n role=\"region\"\n aria-label={`User box for ${name}`}\n >\n {renderUser()}\n </div>\n );\n};\n\nexport default UserBox;\n"],"mappings":";;;;;;;;AAYA,IAAM,WAAoC,EACxC,OAAO,YACP,MACA,IACA,SACA,SACA,WACA,QACA,SAAS,gBACL;CACJ,MAAM,qBAAqB,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY;CAEtD,MAAM,mBAA8B;EAClC,IAAI,SACF,OACE,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,OAAD;GAAK,OAAO,EAAE,iBAAiB,aAAa,IAAI,MAAM,EAAE;GAAG,WAAU;GAClE,UAAA;EACE,CAAA,GACL,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,oBAAC,QAAD;IAAQ,WAAU;IAAwB;IAAS,OAAO;IAAM,SAAQ;GAAQ,CAAA,GAC/E,QAAQ,oBAAC,QAAD,EAAA,UAAO,KAAW,CAAA,CACxB;EACL,CAAA,CAAA,EAAA,CAAA;OAIJ,OACE,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,OAAD;GAAK,OAAO,EAAE,iBAAiB,aAAa,EAAE,EAAE;GAAG,WAAU;GAC1D,UAAA;EACE,CAAA,GACL,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,oBAAC,OAAD,EAAO,OAAO,KAAO,CAAA,GACpB,QAAQ,oBAAC,QAAD;IAAM,cAAY,cAAc;IAAS,UAAA;GAAW,CAAA,CAC1D;EACL,CAAA,CAAA,EAAA,CAAA;CAGR;CAEA,OACE,oBAAC,OAAD;EACE,eAAa;EACb,WAAW,GAAG,eAAe,SAAS;EACtC,MAAK;EACL,cAAY,gBAAgB;EAE3B,UAAA,WAAW;CACT,CAAA;AAET"}
@@ -1 +1 @@
1
- {"version":3,"file":"StateIcon.js","names":[],"sources":["../../../../../../../src/Atomic/UI/WizardStepper/ui/StateIcon/StateIcon.tsx"],"sourcesContent":["import type { IStateIconProps } from '../../WizardStepper.interface';\nimport cn from 'classnames';\n\nimport React from 'react';\nimport { WIZARD_STEP_VARIANTS } from '../../constructor';\n\nimport './StateIcon.scss';\n\nconst DefaultPoint: React.FC = () => {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <circle cx=\"8\" cy=\"8\" r=\"4\" />\n </svg>\n );\n};\n\nconst DonePoint: React.FC = () => {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M12.5 5L7 10.5L4 7.5\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n );\n};\n\nconst RC = 'state-icon';\n\nconst { ACTIVE, DEFAULT, DONE } = WIZARD_STEP_VARIANTS;\n\nexport const StateIcon: React.FC<IStateIconProps> = ({ variant = DEFAULT, className }) => {\n const computedState = variant === ACTIVE || variant === DONE ? variant : DEFAULT;\n\n const Inner = {\n [DEFAULT]: <DefaultPoint />,\n [ACTIVE]: <DefaultPoint />,\n [DONE]: <DonePoint />,\n };\n\n return <div className={cn(RC, `${RC}--${computedState}`, className)}>{Inner[computedState]}</div>;\n};\n"],"mappings":";;;;;;AAQA,IAAM,qBAA+B;CACnC,OACE,oBAAC,OAAD;EAAK,OAAM;EAAK,QAAO;EAAK,SAAQ;EAAY,MAAK;YACnD,oBAAC,UAAD;GAAQ,IAAG;GAAI,IAAG;GAAI,GAAE;EAAK,CAAA;CAC1B,CAAA;AAET;AAEA,IAAM,kBAA4B;CAChC,OACE,oBAAC,OAAD;EAAK,OAAM;EAAK,QAAO;EAAK,SAAQ;EAAY,MAAK;YACnD,oBAAC,QAAD;GAAM,GAAE;GAAuB,aAAY;GAAI,eAAc;GAAQ,gBAAe;EAAS,CAAA;CAC1F,CAAA;AAET;AAEA,IAAM,KAAK;AAEX,IAAM,EAAE,QAAQ,SAAS,SAAS;AAElC,IAAa,aAAwC,EAAE,UAAU,SAAS,gBAAgB;CACxF,MAAM,gBAAgB,YAAY,UAAU,YAAY,OAAO,UAAU;CAEzE,MAAM,QAAQ;GACX,UAAU,oBAAC,cAAD,CAAe,CAAA;GACzB,SAAS,oBAAC,cAAD,CAAe,CAAA;GACxB,OAAO,oBAAC,WAAD,CAAY,CAAA;CACtB;CAEA,OAAO,oBAAC,OAAD;EAAK,WAAW,GAAG,IAAI,GAAG,GAAG,IAAI,iBAAiB,SAAS;YAAI,MAAM;CAAoB,CAAA;AAClG"}
1
+ {"version":3,"file":"StateIcon.js","names":[],"sources":["../../../../../../../src/Atomic/UI/WizardStepper/ui/StateIcon/StateIcon.tsx"],"sourcesContent":["import type { IStateIconProps } from '../../WizardStepper.interface';\nimport cn from 'classnames';\n\nimport React from 'react';\nimport { WIZARD_STEP_VARIANTS } from '../../constructor';\n\nimport './StateIcon.scss';\n\nconst DefaultPoint: React.FC = () => {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <circle cx=\"8\" cy=\"8\" r=\"4\" />\n </svg>\n );\n};\n\nconst DonePoint: React.FC = () => {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M12.5 5L7 10.5L4 7.5\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n );\n};\n\nconst RC = 'state-icon';\n\nconst { ACTIVE, DEFAULT, DONE } = WIZARD_STEP_VARIANTS;\n\nexport const StateIcon: React.FC<IStateIconProps> = ({ variant = DEFAULT, className }) => {\n const computedState = variant === ACTIVE || variant === DONE ? variant : DEFAULT;\n\n const Inner = {\n [DEFAULT]: <DefaultPoint />,\n [ACTIVE]: <DefaultPoint />,\n [DONE]: <DonePoint />,\n };\n\n return <div className={cn(RC, `${RC}--${computedState}`, className)}>{Inner[computedState]}</div>;\n};\n"],"mappings":";;;;;;AAQA,IAAM,qBAA+B;CACnC,OACE,oBAAC,OAAD;EAAK,OAAM;EAAK,QAAO;EAAK,SAAQ;EAAY,MAAK;EACnD,UAAA,oBAAC,UAAD;GAAQ,IAAG;GAAI,IAAG;GAAI,GAAE;EAAK,CAAA;CAC1B,CAAA;AAET;AAEA,IAAM,kBAA4B;CAChC,OACE,oBAAC,OAAD;EAAK,OAAM;EAAK,QAAO;EAAK,SAAQ;EAAY,MAAK;EACnD,UAAA,oBAAC,QAAD;GAAM,GAAE;GAAuB,aAAY;GAAI,eAAc;GAAQ,gBAAe;EAAS,CAAA;CAC1F,CAAA;AAET;AAEA,IAAM,KAAK;AAEX,IAAM,EAAE,QAAQ,SAAS,SAAS;AAElC,IAAa,aAAwC,EAAE,UAAU,SAAS,gBAAgB;CACxF,MAAM,gBAAgB,YAAY,UAAU,YAAY,OAAO,UAAU;CAEzE,MAAM,QAAQ;GACX,UAAU,oBAAC,cAAD,CAAe,CAAA;GACzB,SAAS,oBAAC,cAAD,CAAe,CAAA;GACxB,OAAO,oBAAC,WAAD,CAAY,CAAA;CACtB;CAEA,OAAO,oBAAC,OAAD;EAAK,WAAW,GAAG,IAAI,GAAG,GAAG,IAAI,iBAAiB,SAAS;EAAI,UAAA,MAAM;CAAoB,CAAA;AAClG"}
@@ -1 +1 @@
1
- {"version":3,"file":"StepRow.js","names":[],"sources":["../../../../../../../src/Atomic/UI/WizardStepper/ui/StepRow/StepRow.tsx"],"sourcesContent":["import type { IStepRowProps } from '../../WizardStepper.interface';\nimport cn from 'classnames';\nimport React from 'react';\nimport Status from '../../../Status/Status';\nimport { WIZARD_STEP_VARIANTS } from '../../constructor';\nimport StateIcon from '../StateIcon';\nimport './StepRow.scss';\n\nconst RC = 'step-row';\n\nconst { DEFAULT, ACTIVE, DONE } = WIZARD_STEP_VARIANTS;\n\nconst StepRow: React.FC<IStepRowProps> = ({\n label,\n description,\n className,\n isOptional,\n isFinished,\n isActive,\n titleSlot,\n contentSlot,\n customIcons,\n}) => {\n const title = label;\n\n const rowVariant = (() => {\n if (isActive) return ACTIVE;\n if (isFinished) return DONE;\n return DEFAULT;\n })();\n\n const alternaviteIconFromProps = (() => {\n if (isActive) return customIcons?.activeIcon;\n if (isFinished) return customIcons?.doneIcon;\n return customIcons?.defaultIcon;\n })();\n\n const CorrectIcon: React.FC = () => {\n if (!customIcons || Object?.values(customIcons)?.every(icon => !icon)) {\n return <StateIcon variant={rowVariant} />;\n }\n\n return alternaviteIconFromProps as React.ReactElement<any, any> || null;\n };\n\n return (\n <div key={label} className={cn(RC, `${RC}--${rowVariant}`, className)}>\n <div className={cn(`${RC}__state-point`, `${RC}__state-point--${rowVariant}`)}>\n <CorrectIcon />\n </div>\n\n <div className={`${RC}__content`}>\n <div className={`${RC}__title`}>\n <div className={`${RC}__title-left`}>\n <div className={cn(`${RC}__title-text`, { 'text-muted': rowVariant === DEFAULT })}>\n {title}\n </div>\n {isOptional && <Status label=\"Optional\" status=\"draft\" />}\n </div>\n\n {titleSlot && (\n <div className={`${RC}__title-right`}>\n {titleSlot}\n </div>\n )}\n </div>\n\n {description && <div className={`${RC}__description`}>{description}</div>}\n {contentSlot && <div className={`${RC}__body`}>{contentSlot}</div>}\n </div>\n </div>\n );\n};\n\nexport default StepRow;\n"],"mappings":";;;;;;;;AAQA,IAAM,KAAK;AAEX,IAAM,EAAE,SAAS,QAAQ,SAAS;AAElC,IAAM,WAAoC,EACxC,OACA,aACA,WACA,YACA,YACA,UACA,WACA,aACA,kBACI;CACJ,MAAM,QAAQ;CAEd,MAAM,oBAAoB;EACxB,IAAI,UAAU,OAAO;EACrB,IAAI,YAAY,OAAO;EACvB,OAAO;CACT,EAAA,CAAG;CAEH,MAAM,kCAAkC;EACtC,IAAI,UAAU,OAAO,aAAa;EAClC,IAAI,YAAY,OAAO,aAAa;EACpC,OAAO,aAAa;CACtB,EAAA,CAAG;CAEH,MAAM,oBAA8B;EAClC,IAAI,CAAC,eAAe,QAAQ,OAAO,WAAW,CAAC,EAAE,OAAM,SAAQ,CAAC,IAAI,GAClE,OAAO,oBAAC,mBAAD,EAAW,SAAS,WAAa,CAAA;EAG1C,OAAO,4BAA4D;CACrE;CAEA,OACE,qBAAC,OAAD;EAAiB,WAAW,GAAG,IAAI,GAAG,GAAG,IAAI,cAAc,SAAS;YAApE,CACE,oBAAC,OAAD;GAAK,WAAW,GAAG,GAAG,GAAG,gBAAgB,GAAG,GAAG,iBAAiB,YAAY;aAC1E,oBAAC,aAAD,CAAc,CAAA;EACX,CAAA,GAEL,qBAAC,OAAD;GAAK,WAAW,GAAG,GAAG;aAAtB;IACE,qBAAC,OAAD;KAAK,WAAW,GAAG,GAAG;eAAtB,CACE,qBAAC,OAAD;MAAK,WAAW,GAAG,GAAG;gBAAtB,CACE,oBAAC,OAAD;OAAK,WAAW,GAAG,GAAG,GAAG,eAAe,EAAE,cAAc,eAAe,QAAQ,CAAC;iBAC7E;MACE,CAAA,GACJ,cAAc,oBAAC,QAAD;OAAQ,OAAM;OAAW,QAAO;MAAS,CAAA,CACrD;SAEJ,aACC,oBAAC,OAAD;MAAK,WAAW,GAAG,GAAG;gBACnB;KACE,CAAA,CAEJ;;IAEJ,eAAe,oBAAC,OAAD;KAAK,WAAW,GAAG,GAAG;eAAiB;IAAiB,CAAA;IACvE,eAAe,oBAAC,OAAD;KAAK,WAAW,GAAG,GAAG;eAAU;IAAiB,CAAA;GAC9D;IACF;IAxBK,KAwBL;AAET"}
1
+ {"version":3,"file":"StepRow.js","names":[],"sources":["../../../../../../../src/Atomic/UI/WizardStepper/ui/StepRow/StepRow.tsx"],"sourcesContent":["import type { IStepRowProps } from '../../WizardStepper.interface';\nimport cn from 'classnames';\nimport React from 'react';\nimport Status from '../../../Status/Status';\nimport { WIZARD_STEP_VARIANTS } from '../../constructor';\nimport StateIcon from '../StateIcon';\nimport './StepRow.scss';\n\nconst RC = 'step-row';\n\nconst { DEFAULT, ACTIVE, DONE } = WIZARD_STEP_VARIANTS;\n\nconst StepRow: React.FC<IStepRowProps> = ({\n label,\n description,\n className,\n isOptional,\n isFinished,\n isActive,\n titleSlot,\n contentSlot,\n customIcons,\n}) => {\n const title = label;\n\n const rowVariant = (() => {\n if (isActive) return ACTIVE;\n if (isFinished) return DONE;\n return DEFAULT;\n })();\n\n const alternaviteIconFromProps = (() => {\n if (isActive) return customIcons?.activeIcon;\n if (isFinished) return customIcons?.doneIcon;\n return customIcons?.defaultIcon;\n })();\n\n const CorrectIcon: React.FC = () => {\n if (!customIcons || Object?.values(customIcons)?.every(icon => !icon)) {\n return <StateIcon variant={rowVariant} />;\n }\n\n return alternaviteIconFromProps as React.ReactElement<any, any> || null;\n };\n\n return (\n <div key={label} className={cn(RC, `${RC}--${rowVariant}`, className)}>\n <div className={cn(`${RC}__state-point`, `${RC}__state-point--${rowVariant}`)}>\n <CorrectIcon />\n </div>\n\n <div className={`${RC}__content`}>\n <div className={`${RC}__title`}>\n <div className={`${RC}__title-left`}>\n <div className={cn(`${RC}__title-text`, { 'text-muted': rowVariant === DEFAULT })}>\n {title}\n </div>\n {isOptional && <Status label=\"Optional\" status=\"draft\" />}\n </div>\n\n {titleSlot && (\n <div className={`${RC}__title-right`}>\n {titleSlot}\n </div>\n )}\n </div>\n\n {description && <div className={`${RC}__description`}>{description}</div>}\n {contentSlot && <div className={`${RC}__body`}>{contentSlot}</div>}\n </div>\n </div>\n );\n};\n\nexport default StepRow;\n"],"mappings":";;;;;;;;AAQA,IAAM,KAAK;AAEX,IAAM,EAAE,SAAS,QAAQ,SAAS;AAElC,IAAM,WAAoC,EACxC,OACA,aACA,WACA,YACA,YACA,UACA,WACA,aACA,kBACI;CACJ,MAAM,QAAQ;CAEd,MAAM,oBAAoB;EACxB,IAAI,UAAU,OAAO;EACrB,IAAI,YAAY,OAAO;EACvB,OAAO;CACT,EAAA,CAAG;CAEH,MAAM,kCAAkC;EACtC,IAAI,UAAU,OAAO,aAAa;EAClC,IAAI,YAAY,OAAO,aAAa;EACpC,OAAO,aAAa;CACtB,EAAA,CAAG;CAEH,MAAM,oBAA8B;EAClC,IAAI,CAAC,eAAe,QAAQ,OAAO,WAAW,CAAC,EAAE,OAAM,SAAQ,CAAC,IAAI,GAClE,OAAO,oBAAC,mBAAD,EAAW,SAAS,WAAa,CAAA;EAG1C,OAAO,4BAA4D;CACrE;CAEA,OACE,qBAAC,OAAD;EAAiB,WAAW,GAAG,IAAI,GAAG,GAAG,IAAI,cAAc,SAAS;EAApE,UAAA,CACE,oBAAC,OAAD;GAAK,WAAW,GAAG,GAAG,GAAG,gBAAgB,GAAG,GAAG,iBAAiB,YAAY;GAC1E,UAAA,oBAAC,aAAD,CAAc,CAAA;EACX,CAAA,GAEL,qBAAC,OAAD;GAAK,WAAW,GAAG,GAAG;GAAtB,UAAA;IACE,qBAAC,OAAD;KAAK,WAAW,GAAG,GAAG;KAAtB,UAAA,CACE,qBAAC,OAAD;MAAK,WAAW,GAAG,GAAG;MAAtB,UAAA,CACE,oBAAC,OAAD;OAAK,WAAW,GAAG,GAAG,GAAG,eAAe,EAAE,cAAc,eAAe,QAAQ,CAAC;OAC7E,UAAA;MACE,CAAA,GACJ,cAAc,oBAAC,QAAD;OAAQ,OAAM;OAAW,QAAO;MAAS,CAAA,CACrD;KAEJ,CAAA,GAAA,aACC,oBAAC,OAAD;MAAK,WAAW,GAAG,GAAG;MACnB,UAAA;KACE,CAAA,CAEJ;;IAEJ,eAAe,oBAAC,OAAD;KAAK,WAAW,GAAG,GAAG;KAAiB,UAAA;IAAiB,CAAA;IACvE,eAAe,oBAAC,OAAD;KAAK,WAAW,GAAG,GAAG;KAAU,UAAA;IAAiB,CAAA;GAC9D;EACF,CAAA,CAAA;CAxBK,GAAA,KAwBL;AAET"}
@@ -1 +1 @@
1
- {"version":3,"file":"StepWrapper.js","names":[],"sources":["../../../../../../../src/Atomic/UI/WizardStepper/ui/StepWrapper/StepWrapper.tsx"],"sourcesContent":["import type { IStepWrapperProps } from '../../WizardStepper.interface';\nimport classNames from 'classnames';\n\nimport React from 'react';\nimport Box from '../../../Box/Box';\nimport { alternativeIconSet } from '../icons';\nimport StepRow from '../StepRow/StepRow';\n\nimport './StepWrapper.scss';\n\nconst StepWrapper: React.FC<IStepWrapperProps> = ({\n steps,\n customIcons,\n variant = 'default',\n className,\n testId = 'step-wrapper',\n}) => {\n if (!steps?.length) return <div data-testid=\"empty-state\">No steps available</div>;\n\n const renderStepRow = (step: IStepWrapperProps['steps'][number]): JSX.Element => {\n const { key, ...stepProps } = step;\n return (\n <StepRow\n key={key}\n {...stepProps}\n customIcons={customIcons || alternativeIconSet}\n />\n );\n };\n\n switch (variant) {\n case 'ghost':\n return (\n <Box\n className={classNames('step-wrapper', 'step-wrapper-ghost', className)}\n data-testid={testId}\n >\n {steps?.map(renderStepRow)}\n </Box>\n );\n case 'cardActive':\n return (\n <div\n className={classNames('step-wrapper', 'step-wrapper-card-active', className)}\n data-testid={testId}\n >\n {steps?.map(renderStepRow)}\n </div>\n );\n default:\n return (\n <div\n className={classNames('step-wrapper', className)}\n data-testid={testId}\n >\n {steps?.map(renderStepRow)}\n </div>\n );\n }\n};\n\nexport default StepWrapper;\n"],"mappings":";;;;;;;;AAUA,IAAM,eAA4C,EAChD,OACA,aACA,UAAU,WACV,WACA,SAAS,qBACL;CACJ,IAAI,CAAC,OAAO,QAAQ,OAAO,oBAAC,OAAD;EAAK,eAAY;YAAc;CAAuB,CAAA;CAEjF,MAAM,iBAAiB,SAA0D;EAC/E,MAAM,EAAE,KAAK,GAAG,cAAc;EAC9B,OACE,oBAAC,SAAD;GAEE,GAAI;GACJ,aAAa,eAAe;EAC7B,GAHM,GAGN;CAEL;CAEA,QAAQ,SAAR;EACE,KAAK,SACH,OACE,oBAAC,KAAD;GACE,WAAW,GAAW,gBAAgB,sBAAsB,SAAS;GACrE,eAAa;aAEZ,OAAO,IAAI,aAAa;EACtB,CAAA;EAET,KAAK,cACH,OACE,oBAAC,OAAD;GACE,WAAW,GAAW,gBAAgB,4BAA4B,SAAS;GAC3E,eAAa;aAEZ,OAAO,IAAI,aAAa;EACtB,CAAA;EAET,SACE,OACE,oBAAC,OAAD;GACE,WAAW,GAAW,gBAAgB,SAAS;GAC/C,eAAa;aAEZ,OAAO,IAAI,aAAa;EACtB,CAAA;CAEX;AACF"}
1
+ {"version":3,"file":"StepWrapper.js","names":[],"sources":["../../../../../../../src/Atomic/UI/WizardStepper/ui/StepWrapper/StepWrapper.tsx"],"sourcesContent":["import type { IStepWrapperProps } from '../../WizardStepper.interface';\nimport classNames from 'classnames';\n\nimport React from 'react';\nimport Box from '../../../Box/Box';\nimport { alternativeIconSet } from '../icons';\nimport StepRow from '../StepRow/StepRow';\n\nimport './StepWrapper.scss';\n\nconst StepWrapper: React.FC<IStepWrapperProps> = ({\n steps,\n customIcons,\n variant = 'default',\n className,\n testId = 'step-wrapper',\n}) => {\n if (!steps?.length) return <div data-testid=\"empty-state\">No steps available</div>;\n\n const renderStepRow = (step: IStepWrapperProps['steps'][number]): JSX.Element => {\n const { key, ...stepProps } = step;\n return (\n <StepRow\n key={key}\n {...stepProps}\n customIcons={customIcons || alternativeIconSet}\n />\n );\n };\n\n switch (variant) {\n case 'ghost':\n return (\n <Box\n className={classNames('step-wrapper', 'step-wrapper-ghost', className)}\n data-testid={testId}\n >\n {steps?.map(renderStepRow)}\n </Box>\n );\n case 'cardActive':\n return (\n <div\n className={classNames('step-wrapper', 'step-wrapper-card-active', className)}\n data-testid={testId}\n >\n {steps?.map(renderStepRow)}\n </div>\n );\n default:\n return (\n <div\n className={classNames('step-wrapper', className)}\n data-testid={testId}\n >\n {steps?.map(renderStepRow)}\n </div>\n );\n }\n};\n\nexport default StepWrapper;\n"],"mappings":";;;;;;;;AAUA,IAAM,eAA4C,EAChD,OACA,aACA,UAAU,WACV,WACA,SAAS,qBACL;CACJ,IAAI,CAAC,OAAO,QAAQ,OAAO,oBAAC,OAAD;EAAK,eAAY;EAAc,UAAA;CAAuB,CAAA;CAEjF,MAAM,iBAAiB,SAA0D;EAC/E,MAAM,EAAE,KAAK,GAAG,cAAc;EAC9B,OACE,oBAAC,SAAD;GAEE,GAAI;GACJ,aAAa,eAAe;EAC7B,GAHM,GAGN;CAEL;CAEA,QAAQ,SAAR;EACE,KAAK,SACH,OACE,oBAAC,KAAD;GACE,WAAW,GAAW,gBAAgB,sBAAsB,SAAS;GACrE,eAAa;GAEZ,UAAA,OAAO,IAAI,aAAa;EACtB,CAAA;EAET,KAAK,cACH,OACE,oBAAC,OAAD;GACE,WAAW,GAAW,gBAAgB,4BAA4B,SAAS;GAC3E,eAAa;GAEZ,UAAA,OAAO,IAAI,aAAa;EACtB,CAAA;EAET,SACE,OACE,oBAAC,OAAD;GACE,WAAW,GAAW,gBAAgB,SAAS;GAC/C,eAAa;GAEZ,UAAA,OAAO,IAAI,aAAa;EACtB,CAAA;CAEX;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"icons.js","names":[],"sources":["../../../../../../src/Atomic/UI/WizardStepper/ui/icons.tsx"],"sourcesContent":["import React from 'react';\n\nconst DoneIcon: React.FC<React.SVGProps<SVGSVGElement>> = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect width=\"20\" height=\"20\" rx=\"10\" fill=\"#69A457\" />\n <mask id=\"mask0_54394_4001\" style={{ maskType: 'alpha' }} maskUnits=\"userSpaceOnUse\" x=\"2\" y=\"2\" width=\"16\" height=\"16\">\n <path d=\"M14.5 7L9 12.5L6 9.5\" stroke=\"black\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </mask>\n <g mask=\"url(#mask0_54394_4001)\">\n <rect x=\"2\" y=\"2\" width=\"16\" height=\"16\" fill=\"white\" />\n </g>\n </svg>\n)\n\nconst TodoIcon: React.FC<React.SVGProps<SVGSVGElement>> = () => {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g clipPath=\"url(#clip0_54394_4448)\">\n <circle cx=\"10\" cy=\"10\" r=\"7\" fill=\"white\" stroke=\"#B3B8CB\" strokeWidth=\"2\" />\n </g>\n <defs>\n <clipPath id=\"clip0_54394_4448\">\n <rect width=\"16\" height=\"16\" fill=\"white\" transform=\"translate(2 2)\" />\n </clipPath>\n </defs>\n </svg>\n\n );\n};\n\nconst ActiveIcon: React.FC<React.SVGProps<SVGSVGElement>> = () => {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect width=\"20\" height=\"20\" rx=\"10\" fill=\"#E8F9E5\" />\n ii\n <mask id=\"mask0_54394_1459\" style={{ maskType: 'alpha' }} maskUnits=\"userSpaceOnUse\" x=\"2\" y=\"2\" width=\"16\" height=\"16\">\n <circle cx=\"10\" cy=\"10\" r=\"4\" fill=\"#171D33\" />\n </mask>\n <g mask=\"url(#mask0_54394_1459)\">\n <rect x=\"2\" y=\"2\" width=\"16\" height=\"16\" fill=\"#171D33\" />\n </g>\n </svg>\n\n );\n};\n\nexport const alternativeIconSet: {\n defaultIcon: React.ReactElement;\n doneIcon: React.ReactElement;\n activeIcon: React.ReactElement;\n} = {\n defaultIcon: <TodoIcon />,\n doneIcon: <DoneIcon />,\n activeIcon: <ActiveIcon />,\n};\n"],"mappings":";;;AAEA,IAAM,iBACJ,qBAAC,OAAD;CAAK,OAAM;CAAK,QAAO;CAAK,SAAQ;CAAY,MAAK;CAAO,OAAM;WAAlE;EACE,oBAAC,QAAD;GAAM,OAAM;GAAK,QAAO;GAAK,IAAG;GAAK,MAAK;EAAW,CAAA;EACrD,oBAAC,QAAD;GAAM,IAAG;GAAmB,OAAO,EAAE,UAAU,QAAQ;GAAG,WAAU;GAAiB,GAAE;GAAI,GAAE;GAAI,OAAM;GAAK,QAAO;aACjH,oBAAC,QAAD;IAAM,GAAE;IAAuB,QAAO;IAAQ,aAAY;IAAI,eAAc;IAAQ,gBAAe;GAAS,CAAA;EACxG,CAAA;EACN,oBAAC,KAAD;GAAG,MAAK;aACN,oBAAC,QAAD;IAAM,GAAE;IAAI,GAAE;IAAI,OAAM;IAAK,QAAO;IAAK,MAAK;GAAS,CAAA;EACtD,CAAA;CACA;;AAGP,IAAM,iBAA0D;CAC9D,OACE,qBAAC,OAAD;EAAK,OAAM;EAAK,QAAO;EAAK,SAAQ;EAAY,MAAK;EAAO,OAAM;YAAlE,CACE,oBAAC,KAAD;GAAG,UAAS;aACV,oBAAC,UAAD;IAAQ,IAAG;IAAK,IAAG;IAAK,GAAE;IAAI,MAAK;IAAQ,QAAO;IAAU,aAAY;GAAK,CAAA;EAC5E,CAAA,GACH,oBAAC,QAAD,EAAA,UACE,oBAAC,YAAD;GAAU,IAAG;aACX,oBAAC,QAAD;IAAM,OAAM;IAAK,QAAO;IAAK,MAAK;IAAQ,WAAU;GAAkB,CAAA;EAC9D,CAAA,EACN,CAAA,CACH;;AAGT;AAEA,IAAM,mBAA4D;CAChE,OACE,qBAAC,OAAD;EAAK,OAAM;EAAK,QAAO;EAAK,SAAQ;EAAY,MAAK;EAAO,OAAM;YAAlE;GACE,oBAAC,QAAD;IAAM,OAAM;IAAK,QAAO;IAAK,IAAG;IAAK,MAAK;GAAW,CAAA;GAAC;GAEtD,oBAAC,QAAD;IAAM,IAAG;IAAmB,OAAO,EAAE,UAAU,QAAQ;IAAG,WAAU;IAAiB,GAAE;IAAI,GAAE;IAAI,OAAM;IAAK,QAAO;cACjH,oBAAC,UAAD;KAAQ,IAAG;KAAK,IAAG;KAAK,GAAE;KAAI,MAAK;IAAW,CAAA;GAC1C,CAAA;GACN,oBAAC,KAAD;IAAG,MAAK;cACN,oBAAC,QAAD;KAAM,GAAE;KAAI,GAAE;KAAI,OAAM;KAAK,QAAO;KAAK,MAAK;IAAW,CAAA;GACxD,CAAA;EACA;;AAGT;AAEA,IAAa,qBAIT;CACF,aAAa,oBAAC,UAAD,CAAW,CAAA;CACxB,UAAU,oBAAC,UAAD,CAAW,CAAA;CACrB,YAAY,oBAAC,YAAD,CAAa,CAAA;AAC3B"}
1
+ {"version":3,"file":"icons.js","names":[],"sources":["../../../../../../src/Atomic/UI/WizardStepper/ui/icons.tsx"],"sourcesContent":["import React from 'react';\n\nconst DoneIcon: React.FC<React.SVGProps<SVGSVGElement>> = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect width=\"20\" height=\"20\" rx=\"10\" fill=\"#69A457\" />\n <mask id=\"mask0_54394_4001\" style={{ maskType: 'alpha' }} maskUnits=\"userSpaceOnUse\" x=\"2\" y=\"2\" width=\"16\" height=\"16\">\n <path d=\"M14.5 7L9 12.5L6 9.5\" stroke=\"black\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </mask>\n <g mask=\"url(#mask0_54394_4001)\">\n <rect x=\"2\" y=\"2\" width=\"16\" height=\"16\" fill=\"white\" />\n </g>\n </svg>\n)\n\nconst TodoIcon: React.FC<React.SVGProps<SVGSVGElement>> = () => {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g clipPath=\"url(#clip0_54394_4448)\">\n <circle cx=\"10\" cy=\"10\" r=\"7\" fill=\"white\" stroke=\"#B3B8CB\" strokeWidth=\"2\" />\n </g>\n <defs>\n <clipPath id=\"clip0_54394_4448\">\n <rect width=\"16\" height=\"16\" fill=\"white\" transform=\"translate(2 2)\" />\n </clipPath>\n </defs>\n </svg>\n\n );\n};\n\nconst ActiveIcon: React.FC<React.SVGProps<SVGSVGElement>> = () => {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect width=\"20\" height=\"20\" rx=\"10\" fill=\"#E8F9E5\" />\n ii\n <mask id=\"mask0_54394_1459\" style={{ maskType: 'alpha' }} maskUnits=\"userSpaceOnUse\" x=\"2\" y=\"2\" width=\"16\" height=\"16\">\n <circle cx=\"10\" cy=\"10\" r=\"4\" fill=\"#171D33\" />\n </mask>\n <g mask=\"url(#mask0_54394_1459)\">\n <rect x=\"2\" y=\"2\" width=\"16\" height=\"16\" fill=\"#171D33\" />\n </g>\n </svg>\n\n );\n};\n\nexport const alternativeIconSet: {\n defaultIcon: React.ReactElement;\n doneIcon: React.ReactElement;\n activeIcon: React.ReactElement;\n} = {\n defaultIcon: <TodoIcon />,\n doneIcon: <DoneIcon />,\n activeIcon: <ActiveIcon />,\n};\n"],"mappings":";;;AAEA,IAAM,iBACJ,qBAAC,OAAD;CAAK,OAAM;CAAK,QAAO;CAAK,SAAQ;CAAY,MAAK;CAAO,OAAM;CAAlE,UAAA;EACE,oBAAC,QAAD;GAAM,OAAM;GAAK,QAAO;GAAK,IAAG;GAAK,MAAK;EAAW,CAAA;EACrD,oBAAC,QAAD;GAAM,IAAG;GAAmB,OAAO,EAAE,UAAU,QAAQ;GAAG,WAAU;GAAiB,GAAE;GAAI,GAAE;GAAI,OAAM;GAAK,QAAO;GACjH,UAAA,oBAAC,QAAD;IAAM,GAAE;IAAuB,QAAO;IAAQ,aAAY;IAAI,eAAc;IAAQ,gBAAe;GAAS,CAAA;EACxG,CAAA;EACN,oBAAC,KAAD;GAAG,MAAK;GACN,UAAA,oBAAC,QAAD;IAAM,GAAE;IAAI,GAAE;IAAI,OAAM;IAAK,QAAO;IAAK,MAAK;GAAS,CAAA;EACtD,CAAA;CACA;;AAGP,IAAM,iBAA0D;CAC9D,OACE,qBAAC,OAAD;EAAK,OAAM;EAAK,QAAO;EAAK,SAAQ;EAAY,MAAK;EAAO,OAAM;EAAlE,UAAA,CACE,oBAAC,KAAD;GAAG,UAAS;GACV,UAAA,oBAAC,UAAD;IAAQ,IAAG;IAAK,IAAG;IAAK,GAAE;IAAI,MAAK;IAAQ,QAAO;IAAU,aAAY;GAAK,CAAA;EAC5E,CAAA,GACH,oBAAC,QAAD,EAAA,UACE,oBAAC,YAAD;GAAU,IAAG;GACX,UAAA,oBAAC,QAAD;IAAM,OAAM;IAAK,QAAO;IAAK,MAAK;IAAQ,WAAU;GAAkB,CAAA;EAC9D,CAAA,EACN,CAAA,CACH;;AAGT;AAEA,IAAM,mBAA4D;CAChE,OACE,qBAAC,OAAD;EAAK,OAAM;EAAK,QAAO;EAAK,SAAQ;EAAY,MAAK;EAAO,OAAM;EAAlE,UAAA;GACE,oBAAC,QAAD;IAAM,OAAM;IAAK,QAAO;IAAK,IAAG;IAAK,MAAK;GAAW,CAAA;GAAC;GAEtD,oBAAC,QAAD;IAAM,IAAG;IAAmB,OAAO,EAAE,UAAU,QAAQ;IAAG,WAAU;IAAiB,GAAE;IAAI,GAAE;IAAI,OAAM;IAAK,QAAO;IACjH,UAAA,oBAAC,UAAD;KAAQ,IAAG;KAAK,IAAG;KAAK,GAAE;KAAI,MAAK;IAAW,CAAA;GAC1C,CAAA;GACN,oBAAC,KAAD;IAAG,MAAK;IACN,UAAA,oBAAC,QAAD;KAAM,GAAE;KAAI,GAAE;KAAI,OAAM;KAAK,QAAO;KAAK,MAAK;IAAW,CAAA;GACxD,CAAA;EACA;;AAGT;AAEA,IAAa,qBAIT;CACF,aAAa,oBAAC,UAAD,CAAW,CAAA;CACxB,UAAU,oBAAC,UAAD,CAAW,CAAA;CACrB,YAAY,oBAAC,YAAD,CAAa,CAAA;AAC3B"}
@@ -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 = typeof method === "string" && isHttpMethod(method) ? method : null;
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(typeof method === "string" && isHttpMethod(method) ? method : null);
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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"}
@@ -60,8 +60,10 @@ var CredentialsProcessing = class {
60
60
  return getIsOnlyAnObject(result) ? result : {};
61
61
  };
62
62
  if (typeof importCredentials === "function") this.importCredentials = (cred) => importCredentials(cred);
63
- if (saveCredentials || isUseRefreshTokensPropcessing) if (typeof saveCredentials !== "function") throw new Error("No saveCredentials method [CredentialsProcessing]");
64
- else this.saveCredentials = (cred) => saveCredentials(cred);
63
+ if (saveCredentials || isUseRefreshTokensPropcessing) {
64
+ if (typeof saveCredentials !== "function") throw new Error("No saveCredentials method [CredentialsProcessing]");
65
+ else this.saveCredentials = (cred) => saveCredentials(cred);
66
+ }
65
67
  if (isUseRefreshTokensPropcessing) {
66
68
  if (typeof refreshCredentials === "function") this.refreshCredentialsByOuter = (cred) => refreshCredentials(cred);
67
69
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"CredentialsProcessing.js","names":[],"sources":["../../../../../src/Classes/RESTAPI/partials/CredentialsProcessing.ts"],"sourcesContent":["import type { CredentialsState, RESTAPISettings, UnknownRecord } from './types';\nimport { getIsOnlyAnObject } from './_utils';\n\n/**\n * Декодирует payload JWT-токена.\n *\n * @param token - JWT-строка вида `header.payload.signature`.\n * @returns Распарсенный payload (объект) либо `null`, если декодирование не удалось.\n */\nexport function decodeJWT(token: string): UnknownRecord | null {\n try {\n const payload = token.split('.')[1] ?? '';\n const decoded: unknown = JSON.parse(atob(payload));\n return getIsOnlyAnObject(decoded) ? decoded : null;\n }\n catch {\n return null;\n }\n}\n\n/**\n * Обработчик учётных данных (токенов): добавляет токен в запросы и (опционально) реализует\n * флоу рефреша токенов. Конфигурируется через настройку `credentialsProcessing`.\n */\nclass CredentialsProcessing {\n // ? Индекс-сигнатура: getRESTAPIContext навешивается извне (из конструктора RESTAPI).\n [key: string]: unknown;\n\n /** Включён ли флоу рефреша токенов. */\n isUseRefreshTokensPropcessing = false;\n\n /** Учётные данные по умолчанию (пустые). */\n DEFAULT_CREDENTIALS: CredentialsState = {};\n\n /** Внешний метод получения учётных данных. */\n getCredentialsByOuter!: () => unknown;\n\n /** Внешний метод формирования заголовков авторизации по токену. */\n getHeadersForAuthorize!: (token: string) => UnknownRecord;\n\n /** Необязательный преобразователь учётных данных после getCredentials. */\n importCredentials?: (cred: unknown) => unknown;\n\n /** Необязательный метод сохранения учётных данных (обязателен для флоу рефреша). */\n saveCredentials?: (cred: unknown) => unknown;\n\n /** Внешний метод рефреша учётных данных. */\n refreshCredentialsByOuter?: (cred: CredentialsState) => unknown;\n\n /** Полный путь до эндпоинта рефреша токена. */\n REFRESH_TOKEN_PATH?: string;\n\n /** Коды ответа, по которым триггерится попытка рефреша. */\n CODES_USING_THE_REFRESH_ATTEMPT?: number[];\n\n /** Ключ флага «рефреш начат» в localStorage. */\n REFRESH_TOKEN_FLAG = 'refreshTokenFlag';\n\n /** Интервал опроса флага обновления токена, мс. */\n INTERVAL_FOR_CHECKING_TOKEN_UPDATE = 50;\n\n /** Колбэк, вызываемый после неудачного рефреша. */\n callbackAfterRejectRefresh?: () => unknown;\n\n /** Доступ к верхнему контексту RESTAPI (навешивается из конструктора RESTAPI). */\n getRESTAPIContext?: () => unknown;\n\n constructor(settings: RESTAPISettings) {\n const { credentialsProcessing } = settings;\n const {\n // ? Для корректной работы установки токенов в запросы от API\n // ? нужно передавать методы getCredentials и getHeadersForAuthorize\n getCredentials,\n getHeadersForAuthorize, // ? На вход получит токен, должна вернуть объект для коструктора Headers\n\n // ? Так же опционально можно передавать\n importCredentials, // ? если он передается, то он будет применяться к выводу от вызова getCredentials\n saveCredentials, // ? можно будет найти в объекте credentialsProcessing, чтобы использовать кастомными методами\n\n // ! Либо вызов getCredentials, либо цепочка вызовов importCredentials(getCredentials())\n // ! должна возвращать требуемую классом структуру\n // ! Класс требует структуры\n // ! - { token }, если флоу рефреш токена НЕ используется\n // ! - { token, refreshToken, expires }, если используется флоу рефреш токена\n\n // *********\n\n // ? Подключает флоу рефреша токенов\n isUseRefreshTokensPropcessing = false,\n\n // ! Для корректной работы флоу рефреша токенов передача метода saveCredentials становится ОБЯЗАТЕЛЬНОЙ\n\n // ? Так же для корректной работы флоу рефреша токенов нужно\n // ? - либо\n refreshCredentials, // ! метод должен возвращать такую же структуру как и метод getCredentials,\n // ? на вход получит текущие креды, к выходу будет применен importCredentials, если этот метод передавался\n // ? - либо\n REFRESH_TOKEN_PATH, // ! REFRESH_TOKEN_PATH передается ПОЛНОСТЬЮ (глобальная адресация)!\n CODES_USING_THE_REFRESH_ATTEMPT, // ? указывает по каким кодам ответа триггериться рефреш, массив чисел\n\n // ? Опционально\n REFRESH_TOKEN_FLAG = 'refreshTokenFlag',\n INTERVAL_FOR_CHECKING_TOKEN_UPDATE = 50, // ms\n callbackAfterRejectRefresh,\n } = credentialsProcessing || {};\n\n if (typeof getCredentials !== 'function') throw new Error('No getCredentials method [CredentialsProcessing]');\n if (typeof getHeadersForAuthorize !== 'function') {\n throw new TypeError('No getHeadersForAuthorize method [CredentialsProcessing]');\n }\n if (importCredentials && typeof importCredentials !== 'function') {\n throw new Error('Bad importCredentials method [CredentialsProcessing]');\n }\n\n this.isUseRefreshTokensPropcessing = Boolean(isUseRefreshTokensPropcessing);\n this.DEFAULT_CREDENTIALS = {};\n // ? Внешние функции оборачиваем в типизированные обёртки (без приведения типов / типа Function).\n this.getCredentialsByOuter = () => getCredentials();\n this.getHeadersForAuthorize = (token: string) => {\n const result = getHeadersForAuthorize(token);\n return getIsOnlyAnObject(result) ? result : {};\n };\n if (typeof importCredentials === 'function') this.importCredentials = (cred: unknown) => importCredentials(cred);\n\n // ? Если метод передан или если не передан, но включен флоу обновления токенов (тогда saveCredentials обязателен)\n if (saveCredentials || isUseRefreshTokensPropcessing) {\n if (typeof saveCredentials !== 'function') throw new Error('No saveCredentials method [CredentialsProcessing]');\n else this.saveCredentials = (cred: unknown) => saveCredentials(cred);\n }\n\n if (isUseRefreshTokensPropcessing) {\n if (typeof refreshCredentials === 'function') {\n this.refreshCredentialsByOuter = (cred: CredentialsState) => refreshCredentials(cred);\n }\n else {\n if (typeof this.refreshCredentialsByOuter === 'function' && typeof REFRESH_TOKEN_PATH !== 'string') {\n throw new TypeError('No REFRESH_TOKEN_PATH [CredentialsProcessing]');\n }\n this.REFRESH_TOKEN_PATH = typeof REFRESH_TOKEN_PATH === 'string' ? REFRESH_TOKEN_PATH : undefined;\n }\n\n if (!Array.isArray(CODES_USING_THE_REFRESH_ATTEMPT)) {\n throw new TypeError('No CODES_USING_THE_REFRESH_ATTEMPT [CredentialsProcessing]');\n }\n if (!CODES_USING_THE_REFRESH_ATTEMPT.every(i => typeof i === 'number')) {\n throw new Error('Invalid format of CODES_USING_THE_REFRESH_ATTEMPT elements [CredentialsProcessing]');\n }\n\n if (typeof REFRESH_TOKEN_FLAG !== 'string') throw new Error('Bad REFRESH_TOKEN_FLAG [CredentialsProcessing]');\n if (typeof INTERVAL_FOR_CHECKING_TOKEN_UPDATE !== 'number') {\n throw new TypeError('Bad INTERVAL_FOR_CHECKING_TOKEN_UPDATE [CredentialsProcessing]');\n }\n if (typeof INTERVAL_FOR_CHECKING_TOKEN_UPDATE !== 'number') {\n throw new TypeError('Bad INTERVAL_FOR_CHECKING_TOKEN_UPDATE [CredentialsProcessing]');\n }\n if (callbackAfterRejectRefresh && typeof callbackAfterRejectRefresh !== 'function') {\n throw new Error('Bad INTERVAL_FOR_CHECKING_TOKEN_UPDATE [CredentialsProcessing]');\n }\n\n this.CODES_USING_THE_REFRESH_ATTEMPT = CODES_USING_THE_REFRESH_ATTEMPT;\n this.REFRESH_TOKEN_FLAG = REFRESH_TOKEN_FLAG;\n this.INTERVAL_FOR_CHECKING_TOKEN_UPDATE = INTERVAL_FOR_CHECKING_TOKEN_UPDATE;\n\n if (typeof callbackAfterRejectRefresh === 'function') this.callbackAfterRejectRefresh = () => callbackAfterRejectRefresh();\n }\n }\n\n /** Возвращает значение флага «рефреш начат» из localStorage. */\n getIsTokenStartRefresh(): string | null {\n return localStorage.getItem(this.REFRESH_TOKEN_FLAG);\n }\n\n /** Выставляет флаг «рефреш начат» в localStorage. */\n setIsTokenStartRefresh(): void {\n localStorage.setItem(this.REFRESH_TOKEN_FLAG, String(true));\n }\n\n /** Снимает флаг «рефреш начат» из localStorage. */\n removeIsTokenStartRefresh(): void {\n localStorage.removeItem(this.REFRESH_TOKEN_FLAG);\n }\n\n /**\n * Возвращает текущие учётные данные (с учётом importCredentials и проверки истечения JWT).\n *\n * @param isCatchCallbackProcess - флаг процесса обработки ошибки (отключает проверку истечения).\n * @param callback - необязательный колбэк, получающий итоговые учётные данные.\n * @returns Промис с учётными данными.\n */\n async getCredentials(isCatchCallbackProcess?: boolean, callback?: (cred: CredentialsState) => unknown): Promise<CredentialsState> {\n let credentials: unknown = await this.getCredentialsByOuter();\n\n if (typeof this.importCredentials === 'function') credentials = await this.importCredentials(credentials);\n const credObj: CredentialsState = getIsOnlyAnObject(credentials) ? credentials : {};\n\n const token = credObj.token || null;\n\n if (token && !isCatchCallbackProcess) {\n let decoded: UnknownRecord | null;\n try {\n decoded = decodeJWT(token);\n }\n catch {\n decoded = null;\n }\n const currentTime = Date.now() / 1000;\n if (decoded !== null && Number(decoded.exp) < currentTime) credObj.isNeedRefresh = true;\n }\n\n if (callback) await callback({ ...credObj, isCatchCallbackProcess });\n return { ...credObj, isCatchCallbackProcess };\n }\n\n /**\n * Выполняет рефреш учётных данных (внешним методом либо дефолтным OAuth-флоу).\n *\n * @param currentCredentials - текущие учётные данные.\n * @param callback - необязательный колбэк сохранения новых учётных данных.\n * @returns Промис с новыми учётными данными.\n */\n async refreshCredentials(currentCredentials: CredentialsState, callback?: (cred: CredentialsState) => unknown): Promise<CredentialsState> {\n const CONTEXT = this;\n\n async function finalize(cred: CredentialsState): Promise<CredentialsState> {\n if (callback) await callback(cred);\n return Promise.resolve(cred).then(async (res) => {\n CONTEXT.removeIsTokenStartRefresh();\n return res;\n });\n }\n\n if (!currentCredentials?.token || !currentCredentials?.refreshToken) return finalize(CONTEXT.DEFAULT_CREDENTIALS);\n\n // ! ВНИМАНИЕ! Данный механизм рефреша принят на проекте finturfreactfrontend (админка)\n // ! На кабинете он ТОЧНО НЕ ТАКОЙ\n async function refreshCredentialsByDefault(): Promise<Response> {\n const { token, refreshToken } = currentCredentials;\n // ? Заголовки авторизации формируем через конструктор Headers из пар «ключ-значение».\n const headers = new Headers(Object.entries(CONTEXT.getHeadersForAuthorize(token || '')).map(([key, value]): [string, string] => [key, `${value}`]));\n\n const body = new FormData();\n body.append('grant_type', 'refresh_token');\n body.append('refresh_token', refreshToken || '');\n body.append('client_id', 'oauth');\n body.append('client_secret', 'secret');\n body.append('access_type', 'offline');\n\n return fetch(`${CONTEXT.REFRESH_TOKEN_PATH}`, {\n mode: 'cors',\n method: 'POST',\n headers,\n body,\n redirect: 'follow',\n });\n }\n\n // ? Передавайте собственный refreshCredentials при получении экземляра RESTAPI, если не уверены,\n // ? что механизм рефреша токенов ИМЕННО ТАКОЙ как в ф-и refreshCredentialsByDefault!\n // ! currentCredentials передаются в формате класса! ({ token, refreshToken, expires })\n const newCredentials\n = typeof CONTEXT.refreshCredentialsByOuter === 'function'\n ? await CONTEXT.refreshCredentialsByOuter(currentCredentials)\n : await refreshCredentialsByDefault();\n\n return finalize(getIsOnlyAnObject(newCredentials) ? newCredentials : CONTEXT.DEFAULT_CREDENTIALS);\n }\n\n /**\n * Ожидает завершения рефреша токена (или запускает его флаг при необходимости).\n *\n * @param isNeedRefresh - выставить ли флаг «рефреш начат» при отсутствии активного рефреша.\n * @returns Промис, который резолвится по завершении ожидания.\n */\n async waitRefresh(isNeedRefresh?: boolean): Promise<void> {\n return new Promise<void>((resolve) => {\n if (!this.getIsTokenStartRefresh()) {\n if (isNeedRefresh) this.setIsTokenStartRefresh();\n resolve();\n }\n else {\n const intervalId = setInterval(() => {\n if (!this.getIsTokenStartRefresh()) {\n clearInterval(intervalId);\n resolve();\n }\n }, this.INTERVAL_FOR_CHECKING_TOKEN_UPDATE);\n }\n });\n }\n\n /**\n * Обрабатывает учётные данные: при необходимости рефрешит токен и возвращает актуальные данные.\n *\n * @param cred - текущие учётные данные.\n * @returns Промис с актуальными учётными данными (с флагом isRefreshFailed при неудаче).\n */\n async processCredentials(cred: CredentialsState): Promise<CredentialsState> {\n if (!cred.isNeedRefresh && !cred.isCatchCallbackProcess) return cred;\n\n const CONTEXT = this;\n\n return CONTEXT.refreshCredentials(cred, response => CONTEXT.saveCredentials?.(response)).then(() => {\n return new Promise<CredentialsState>((resolve) => {\n setTimeout(async () => {\n const newCredentials = await CONTEXT.getCredentials();\n if (!newCredentials?.token) {\n newCredentials.isRefreshFailed = true;\n setTimeout(() => {\n CONTEXT?.callbackAfterRejectRefresh?.();\n }, 0);\n }\n resolve(newCredentials);\n }, 0);\n });\n });\n }\n}\n\nexport default CredentialsProcessing;\n"],"mappings":"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"}
1
+ {"version":3,"file":"CredentialsProcessing.js","names":[],"sources":["../../../../../src/Classes/RESTAPI/partials/CredentialsProcessing.ts"],"sourcesContent":["import type { CredentialsState, RESTAPISettings, UnknownRecord } from './types';\nimport { getIsOnlyAnObject } from './_utils';\n\n/**\n * Декодирует payload JWT-токена.\n *\n * @param token - JWT-строка вида `header.payload.signature`.\n * @returns Распарсенный payload (объект) либо `null`, если декодирование не удалось.\n */\nexport function decodeJWT(token: string): UnknownRecord | null {\n try {\n const payload = token.split('.')[1] ?? '';\n const decoded: unknown = JSON.parse(atob(payload));\n return getIsOnlyAnObject(decoded) ? decoded : null;\n }\n catch {\n return null;\n }\n}\n\n/**\n * Обработчик учётных данных (токенов): добавляет токен в запросы и (опционально) реализует\n * флоу рефреша токенов. Конфигурируется через настройку `credentialsProcessing`.\n */\nclass CredentialsProcessing {\n // ? Индекс-сигнатура: getRESTAPIContext навешивается извне (из конструктора RESTAPI).\n [key: string]: unknown;\n\n /** Включён ли флоу рефреша токенов. */\n isUseRefreshTokensPropcessing = false;\n\n /** Учётные данные по умолчанию (пустые). */\n DEFAULT_CREDENTIALS: CredentialsState = {};\n\n /** Внешний метод получения учётных данных. */\n getCredentialsByOuter!: () => unknown;\n\n /** Внешний метод формирования заголовков авторизации по токену. */\n getHeadersForAuthorize!: (token: string) => UnknownRecord;\n\n /** Необязательный преобразователь учётных данных после getCredentials. */\n importCredentials?: (cred: unknown) => unknown;\n\n /** Необязательный метод сохранения учётных данных (обязателен для флоу рефреша). */\n saveCredentials?: (cred: unknown) => unknown;\n\n /** Внешний метод рефреша учётных данных. */\n refreshCredentialsByOuter?: (cred: CredentialsState) => unknown;\n\n /** Полный путь до эндпоинта рефреша токена. */\n REFRESH_TOKEN_PATH?: string;\n\n /** Коды ответа, по которым триггерится попытка рефреша. */\n CODES_USING_THE_REFRESH_ATTEMPT?: number[];\n\n /** Ключ флага «рефреш начат» в localStorage. */\n REFRESH_TOKEN_FLAG = 'refreshTokenFlag';\n\n /** Интервал опроса флага обновления токена, мс. */\n INTERVAL_FOR_CHECKING_TOKEN_UPDATE = 50;\n\n /** Колбэк, вызываемый после неудачного рефреша. */\n callbackAfterRejectRefresh?: () => unknown;\n\n /** Доступ к верхнему контексту RESTAPI (навешивается из конструктора RESTAPI). */\n getRESTAPIContext?: () => unknown;\n\n constructor(settings: RESTAPISettings) {\n const { credentialsProcessing } = settings;\n const {\n // ? Для корректной работы установки токенов в запросы от API\n // ? нужно передавать методы getCredentials и getHeadersForAuthorize\n getCredentials,\n getHeadersForAuthorize, // ? На вход получит токен, должна вернуть объект для коструктора Headers\n\n // ? Так же опционально можно передавать\n importCredentials, // ? если он передается, то он будет применяться к выводу от вызова getCredentials\n saveCredentials, // ? можно будет найти в объекте credentialsProcessing, чтобы использовать кастомными методами\n\n // ! Либо вызов getCredentials, либо цепочка вызовов importCredentials(getCredentials())\n // ! должна возвращать требуемую классом структуру\n // ! Класс требует структуры\n // ! - { token }, если флоу рефреш токена НЕ используется\n // ! - { token, refreshToken, expires }, если используется флоу рефреш токена\n\n // *********\n\n // ? Подключает флоу рефреша токенов\n isUseRefreshTokensPropcessing = false,\n\n // ! Для корректной работы флоу рефреша токенов передача метода saveCredentials становится ОБЯЗАТЕЛЬНОЙ\n\n // ? Так же для корректной работы флоу рефреша токенов нужно\n // ? - либо\n refreshCredentials, // ! метод должен возвращать такую же структуру как и метод getCredentials,\n // ? на вход получит текущие креды, к выходу будет применен importCredentials, если этот метод передавался\n // ? - либо\n REFRESH_TOKEN_PATH, // ! REFRESH_TOKEN_PATH передается ПОЛНОСТЬЮ (глобальная адресация)!\n CODES_USING_THE_REFRESH_ATTEMPT, // ? указывает по каким кодам ответа триггериться рефреш, массив чисел\n\n // ? Опционально\n REFRESH_TOKEN_FLAG = 'refreshTokenFlag',\n INTERVAL_FOR_CHECKING_TOKEN_UPDATE = 50, // ms\n callbackAfterRejectRefresh,\n } = credentialsProcessing || {};\n\n if (typeof getCredentials !== 'function') throw new Error('No getCredentials method [CredentialsProcessing]');\n if (typeof getHeadersForAuthorize !== 'function') {\n throw new TypeError('No getHeadersForAuthorize method [CredentialsProcessing]');\n }\n if (importCredentials && typeof importCredentials !== 'function') {\n throw new Error('Bad importCredentials method [CredentialsProcessing]');\n }\n\n this.isUseRefreshTokensPropcessing = Boolean(isUseRefreshTokensPropcessing);\n this.DEFAULT_CREDENTIALS = {};\n // ? Внешние функции оборачиваем в типизированные обёртки (без приведения типов / типа Function).\n this.getCredentialsByOuter = () => getCredentials();\n this.getHeadersForAuthorize = (token: string) => {\n const result = getHeadersForAuthorize(token);\n return getIsOnlyAnObject(result) ? result : {};\n };\n if (typeof importCredentials === 'function') this.importCredentials = (cred: unknown) => importCredentials(cred);\n\n // ? Если метод передан или если не передан, но включен флоу обновления токенов (тогда saveCredentials обязателен)\n if (saveCredentials || isUseRefreshTokensPropcessing) {\n if (typeof saveCredentials !== 'function') throw new Error('No saveCredentials method [CredentialsProcessing]');\n else this.saveCredentials = (cred: unknown) => saveCredentials(cred);\n }\n\n if (isUseRefreshTokensPropcessing) {\n if (typeof refreshCredentials === 'function') {\n this.refreshCredentialsByOuter = (cred: CredentialsState) => refreshCredentials(cred);\n }\n else {\n if (typeof this.refreshCredentialsByOuter === 'function' && typeof REFRESH_TOKEN_PATH !== 'string') {\n throw new TypeError('No REFRESH_TOKEN_PATH [CredentialsProcessing]');\n }\n this.REFRESH_TOKEN_PATH = typeof REFRESH_TOKEN_PATH === 'string' ? REFRESH_TOKEN_PATH : undefined;\n }\n\n if (!Array.isArray(CODES_USING_THE_REFRESH_ATTEMPT)) {\n throw new TypeError('No CODES_USING_THE_REFRESH_ATTEMPT [CredentialsProcessing]');\n }\n if (!CODES_USING_THE_REFRESH_ATTEMPT.every(i => typeof i === 'number')) {\n throw new Error('Invalid format of CODES_USING_THE_REFRESH_ATTEMPT elements [CredentialsProcessing]');\n }\n\n if (typeof REFRESH_TOKEN_FLAG !== 'string') throw new Error('Bad REFRESH_TOKEN_FLAG [CredentialsProcessing]');\n if (typeof INTERVAL_FOR_CHECKING_TOKEN_UPDATE !== 'number') {\n throw new TypeError('Bad INTERVAL_FOR_CHECKING_TOKEN_UPDATE [CredentialsProcessing]');\n }\n if (typeof INTERVAL_FOR_CHECKING_TOKEN_UPDATE !== 'number') {\n throw new TypeError('Bad INTERVAL_FOR_CHECKING_TOKEN_UPDATE [CredentialsProcessing]');\n }\n if (callbackAfterRejectRefresh && typeof callbackAfterRejectRefresh !== 'function') {\n throw new Error('Bad INTERVAL_FOR_CHECKING_TOKEN_UPDATE [CredentialsProcessing]');\n }\n\n this.CODES_USING_THE_REFRESH_ATTEMPT = CODES_USING_THE_REFRESH_ATTEMPT;\n this.REFRESH_TOKEN_FLAG = REFRESH_TOKEN_FLAG;\n this.INTERVAL_FOR_CHECKING_TOKEN_UPDATE = INTERVAL_FOR_CHECKING_TOKEN_UPDATE;\n\n if (typeof callbackAfterRejectRefresh === 'function') this.callbackAfterRejectRefresh = () => callbackAfterRejectRefresh();\n }\n }\n\n /** Возвращает значение флага «рефреш начат» из localStorage. */\n getIsTokenStartRefresh(): string | null {\n return localStorage.getItem(this.REFRESH_TOKEN_FLAG);\n }\n\n /** Выставляет флаг «рефреш начат» в localStorage. */\n setIsTokenStartRefresh(): void {\n localStorage.setItem(this.REFRESH_TOKEN_FLAG, String(true));\n }\n\n /** Снимает флаг «рефреш начат» из localStorage. */\n removeIsTokenStartRefresh(): void {\n localStorage.removeItem(this.REFRESH_TOKEN_FLAG);\n }\n\n /**\n * Возвращает текущие учётные данные (с учётом importCredentials и проверки истечения JWT).\n *\n * @param isCatchCallbackProcess - флаг процесса обработки ошибки (отключает проверку истечения).\n * @param callback - необязательный колбэк, получающий итоговые учётные данные.\n * @returns Промис с учётными данными.\n */\n async getCredentials(isCatchCallbackProcess?: boolean, callback?: (cred: CredentialsState) => unknown): Promise<CredentialsState> {\n let credentials: unknown = await this.getCredentialsByOuter();\n\n if (typeof this.importCredentials === 'function') credentials = await this.importCredentials(credentials);\n const credObj: CredentialsState = getIsOnlyAnObject(credentials) ? credentials : {};\n\n const token = credObj.token || null;\n\n if (token && !isCatchCallbackProcess) {\n let decoded: UnknownRecord | null;\n try {\n decoded = decodeJWT(token);\n }\n catch {\n decoded = null;\n }\n const currentTime = Date.now() / 1000;\n if (decoded !== null && Number(decoded.exp) < currentTime) credObj.isNeedRefresh = true;\n }\n\n if (callback) await callback({ ...credObj, isCatchCallbackProcess });\n return { ...credObj, isCatchCallbackProcess };\n }\n\n /**\n * Выполняет рефреш учётных данных (внешним методом либо дефолтным OAuth-флоу).\n *\n * @param currentCredentials - текущие учётные данные.\n * @param callback - необязательный колбэк сохранения новых учётных данных.\n * @returns Промис с новыми учётными данными.\n */\n async refreshCredentials(currentCredentials: CredentialsState, callback?: (cred: CredentialsState) => unknown): Promise<CredentialsState> {\n const CONTEXT = this;\n\n async function finalize(cred: CredentialsState): Promise<CredentialsState> {\n if (callback) await callback(cred);\n return Promise.resolve(cred).then(async (res) => {\n CONTEXT.removeIsTokenStartRefresh();\n return res;\n });\n }\n\n if (!currentCredentials?.token || !currentCredentials?.refreshToken) return finalize(CONTEXT.DEFAULT_CREDENTIALS);\n\n // ! ВНИМАНИЕ! Данный механизм рефреша принят на проекте finturfreactfrontend (админка)\n // ! На кабинете он ТОЧНО НЕ ТАКОЙ\n async function refreshCredentialsByDefault(): Promise<Response> {\n const { token, refreshToken } = currentCredentials;\n // ? Заголовки авторизации формируем через конструктор Headers из пар «ключ-значение».\n const headers = new Headers(Object.entries(CONTEXT.getHeadersForAuthorize(token || '')).map(([key, value]): [string, string] => [key, `${value}`]));\n\n const body = new FormData();\n body.append('grant_type', 'refresh_token');\n body.append('refresh_token', refreshToken || '');\n body.append('client_id', 'oauth');\n body.append('client_secret', 'secret');\n body.append('access_type', 'offline');\n\n return fetch(`${CONTEXT.REFRESH_TOKEN_PATH}`, {\n mode: 'cors',\n method: 'POST',\n headers,\n body,\n redirect: 'follow',\n });\n }\n\n // ? Передавайте собственный refreshCredentials при получении экземляра RESTAPI, если не уверены,\n // ? что механизм рефреша токенов ИМЕННО ТАКОЙ как в ф-и refreshCredentialsByDefault!\n // ! currentCredentials передаются в формате класса! ({ token, refreshToken, expires })\n const newCredentials\n = typeof CONTEXT.refreshCredentialsByOuter === 'function'\n ? await CONTEXT.refreshCredentialsByOuter(currentCredentials)\n : await refreshCredentialsByDefault();\n\n return finalize(getIsOnlyAnObject(newCredentials) ? newCredentials : CONTEXT.DEFAULT_CREDENTIALS);\n }\n\n /**\n * Ожидает завершения рефреша токена (или запускает его флаг при необходимости).\n *\n * @param isNeedRefresh - выставить ли флаг «рефреш начат» при отсутствии активного рефреша.\n * @returns Промис, который резолвится по завершении ожидания.\n */\n async waitRefresh(isNeedRefresh?: boolean): Promise<void> {\n return new Promise<void>((resolve) => {\n if (!this.getIsTokenStartRefresh()) {\n if (isNeedRefresh) this.setIsTokenStartRefresh();\n resolve();\n }\n else {\n const intervalId = setInterval(() => {\n if (!this.getIsTokenStartRefresh()) {\n clearInterval(intervalId);\n resolve();\n }\n }, this.INTERVAL_FOR_CHECKING_TOKEN_UPDATE);\n }\n });\n }\n\n /**\n * Обрабатывает учётные данные: при необходимости рефрешит токен и возвращает актуальные данные.\n *\n * @param cred - текущие учётные данные.\n * @returns Промис с актуальными учётными данными (с флагом isRefreshFailed при неудаче).\n */\n async processCredentials(cred: CredentialsState): Promise<CredentialsState> {\n if (!cred.isNeedRefresh && !cred.isCatchCallbackProcess) return cred;\n\n const CONTEXT = this;\n\n return CONTEXT.refreshCredentials(cred, response => CONTEXT.saveCredentials?.(response)).then(() => {\n return new Promise<CredentialsState>((resolve) => {\n setTimeout(async () => {\n const newCredentials = await CONTEXT.getCredentials();\n if (!newCredentials?.token) {\n newCredentials.isRefreshFailed = true;\n setTimeout(() => {\n CONTEXT?.callbackAfterRejectRefresh?.();\n }, 0);\n }\n resolve(newCredentials);\n }, 0);\n });\n });\n }\n}\n\nexport default CredentialsProcessing;\n"],"mappings":"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"}
@@ -37,13 +37,10 @@ function parseSSEEvent(block) {
37
37
  event.id = value;
38
38
  hasField = true;
39
39
  break;
40
- case "retry":
41
- if (/^\d+$/.test(value)) {
42
- event.retry = Number(value);
43
- hasField = true;
44
- }
45
- break;
46
- default: break;
40
+ case "retry": if (/^\d+$/.test(value)) {
41
+ event.retry = Number(value);
42
+ hasField = true;
43
+ }
47
44
  }
48
45
  });
49
46
  if (!hasField) return null;
@@ -1 +1 @@
1
- {"version":3,"file":"sse.js","names":[],"sources":["../../../../../src/Classes/RESTAPI/partials/sse.ts"],"sourcesContent":["import type { SSEEvent, SSEReadOptions, StreamResponseLike } from './types';\n\n// ? Утилиты для обработки Server-Sent Events (text/event-stream).\n// ? Используются крейтером createRequest_sse (смотри класс ApiRequestCreators).\n// ? Реализация следует спецификации EventSource:\n// ? - события разделяются пустой строкой;\n// ? - строки вида \"field:value\" (один ведущий пробел в value отбрасывается);\n// ? - строка, начинающаяся с \":\", — комментарий (игнорируется);\n// ? - несколько полей data склеиваются через \"\\n\";\n// ? - поддерживаемые поля: event, data, id, retry.\n\n/**\n * Парсит один блок SSE (текст между пустыми строками) в объект события.\n *\n * Возвращает `null`, если в блоке не оказалось ни одного значимого поля\n * (например, блок состоял только из комментариев/heartbeat-а).\n *\n * @param block - сырой текстовый блок SSE (без завершающей пустой строки).\n * @returns Разобранное событие {@link SSEEvent} либо `null`.\n */\nexport function parseSSEEvent(block: string): SSEEvent | null {\n if (typeof block !== 'string') return null;\n\n const event: SSEEvent = { event: 'message', data: '', id: undefined, retry: undefined };\n const dataLines: string[] = [];\n let hasField = false;\n\n block.split('\\n').forEach((line) => {\n // ? Пустая строка внутри блока невозможна (по ней блок и режется), но на всякий случай пропускаем.\n // ? Строка-комментарий начинается с двоеточия.\n if (line === '' || line[0] === ':') return;\n\n const colonIdx = line.indexOf(':');\n const field = colonIdx === -1 ? line : line.slice(0, colonIdx);\n let value = colonIdx === -1 ? '' : line.slice(colonIdx + 1);\n // ? По спеке отбрасывается ровно один ведущий пробел значения.\n if (value[0] === ' ') value = value.slice(1);\n\n switch (field) {\n case 'event':\n event.event = value;\n hasField = true;\n break;\n case 'data':\n dataLines.push(value);\n hasField = true;\n break;\n case 'id':\n event.id = value;\n hasField = true;\n break;\n case 'retry':\n if (/^\\d+$/.test(value)) {\n event.retry = Number(value);\n hasField = true;\n }\n break;\n default:\n // ? Неизвестные поля по спеке игнорируются.\n break;\n }\n });\n\n if (!hasField) return null;\n event.data = dataLines.join('\\n');\n return event;\n}\n\n// ? Безопасный вызов пользовательского колбэка: его ошибка не должна рвать чтение потока.\nfunction safeCall(fn: unknown, ...args: unknown[]): void {\n if (typeof fn !== 'function') return;\n try {\n // ? fn сужен до функции type-guard-ом выше — вызываем без приведения типов.\n fn(...args);\n }\n catch {\n /* пользовательский колбэк не влияет на чтение потока */\n }\n}\n\n/**\n * Читает тело Response как поток Server-Sent Events.\n *\n * Резолвится массивом всех полученных событий ПОСЛЕ закрытия потока.\n * Прерывание потока через `AbortController` трактуется как штатное завершение\n * (возвращается то, что успели собрать); любая иная ошибка чтения пробрасывается выше.\n *\n * @param response - объект Response (или duck-typed с `body.getReader()`).\n * @param options - колбэки и опции обработки потока (см. {@link SSEReadOptions}).\n * @param options.onEvent - вызывается на каждое распарсенное событие.\n * @param options.onChunk - вызывается на полезную нагрузку (поле data) каждого события.\n * @param options.handlers - карта `{ имяСобытия: cb }` для обработки по полю `event`.\n * @param options.parseJson - если `true`, поле `data` прогоняется через `JSON.parse`.\n * @returns Промис с массивом всех распарсенных событий {@link SSEEvent}.\n */\nexport async function readSSE(response: StreamResponseLike, { onEvent, onChunk, handlers, parseJson }: SSEReadOptions = {}): Promise<SSEEvent[]> {\n const events: SSEEvent[] = [];\n // ? Нет тела — нечего читать (защита от null и для strictNullChecks).\n const stream = response.body;\n if (!stream) return events;\n\n const reader = stream.getReader();\n const decoder = new TextDecoder('utf-8');\n let buffer = '';\n // ? Отложенный хвостовой \"\\r\": может оказаться первой половиной \"\\r\\n\", разорванного на границе чанков.\n // ? Без этого наивная нормализация превратила бы \"\\r\" + \"\\n\" в \"\\n\\n\" и создала ложный разделитель событий.\n let pendingCR = '';\n\n // ? Нормализует переводы строк в одном чанке (SSE допускает CR, LF и CRLF).\n const normalize = (chunk: string): string => chunk.replace(/\\r\\n|\\r/g, '\\n');\n\n // ? Диспетчер одного готового блока: парсит, аккумулирует и дёргает колбэки.\n const flush = (rawBlock: string): void => {\n const event = parseSSEEvent(rawBlock);\n if (!event) return;\n\n // ? Опциональный JSON-парсинг полезной нагрузки (под бэкенды, шлющие JSON в data).\n if (parseJson && typeof event.data === 'string' && event.data !== '') {\n try {\n event.data = JSON.parse(event.data);\n }\n catch {\n /* не валидный JSON — оставляем data строкой */\n }\n }\n\n events.push(event);\n safeCall(onEvent, event);\n safeCall(onChunk, event.data, event);\n // ? Типизированный обработчик по имени события (event: delta|status|done|...).\n if (handlers) safeCall(handlers[event.event], event.data, event);\n };\n\n try {\n // ? Читаем поток до закрытия, по мере прихода чанков нарезаем готовые события.\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n // ? Нормализуем только пришедший чанк (линейная сложность), переноса всего буфера не делаем.\n let chunk = pendingCR + decoder.decode(value, { stream: true });\n pendingCR = '';\n // ? Если чанк оканчивается на \"\\r\" — откладываем его: вдруг следующий чанк начнётся с \"\\n\" (CRLF на границе).\n if (chunk.endsWith('\\r')) {\n pendingCR = '\\r';\n chunk = chunk.slice(0, -1);\n }\n buffer += normalize(chunk);\n\n // ? Вырезаем все завершённые события (разделитель — пустая строка).\n let sepIdx;\n // eslint-disable-next-line no-cond-assign\n while ((sepIdx = buffer.indexOf('\\n\\n')) !== -1) {\n const rawBlock = buffer.slice(0, sepIdx);\n buffer = buffer.slice(sepIdx + 2);\n flush(rawBlock);\n }\n }\n\n // ? Добиваем декодер, отложенный \"\\r\" и хвост, если поток закрылся без финальной пустой строки.\n buffer += normalize(pendingCR + decoder.decode());\n buffer = buffer.replace(/\\n+$/g, '');\n if (buffer !== '') flush(buffer);\n }\n catch (error: unknown) {\n // ? Прерывание (abort) — это штатное завершение стрима: возвращаем то, что успели собрать.\n // ? Любую иную ошибку чтения пробрасываем выше (её обработает catchCallback/пользователь).\n // ? abort бросает DOMException с name === 'AbortError' (в Node он не instanceof Error) — проверяем поле через guard.\n const name = error && typeof error === 'object' && 'name' in error ? error.name : undefined;\n if (name !== 'AbortError') throw error;\n }\n finally {\n try {\n reader.releaseLock?.();\n }\n catch {\n /* releaseLock может бросить, если поток уже отпущен — игнорируем */\n }\n }\n\n return events;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"sse.js","names":[],"sources":["../../../../../src/Classes/RESTAPI/partials/sse.ts"],"sourcesContent":["import type { SSEEvent, SSEReadOptions, StreamResponseLike } from './types';\n\n// ? Утилиты для обработки Server-Sent Events (text/event-stream).\n// ? Используются крейтером createRequest_sse (смотри класс ApiRequestCreators).\n// ? Реализация следует спецификации EventSource:\n// ? - события разделяются пустой строкой;\n// ? - строки вида \"field:value\" (один ведущий пробел в value отбрасывается);\n// ? - строка, начинающаяся с \":\", — комментарий (игнорируется);\n// ? - несколько полей data склеиваются через \"\\n\";\n// ? - поддерживаемые поля: event, data, id, retry.\n\n/**\n * Парсит один блок SSE (текст между пустыми строками) в объект события.\n *\n * Возвращает `null`, если в блоке не оказалось ни одного значимого поля\n * (например, блок состоял только из комментариев/heartbeat-а).\n *\n * @param block - сырой текстовый блок SSE (без завершающей пустой строки).\n * @returns Разобранное событие {@link SSEEvent} либо `null`.\n */\nexport function parseSSEEvent(block: string): SSEEvent | null {\n if (typeof block !== 'string') return null;\n\n const event: SSEEvent = { event: 'message', data: '', id: undefined, retry: undefined };\n const dataLines: string[] = [];\n let hasField = false;\n\n block.split('\\n').forEach((line) => {\n // ? Пустая строка внутри блока невозможна (по ней блок и режется), но на всякий случай пропускаем.\n // ? Строка-комментарий начинается с двоеточия.\n if (line === '' || line[0] === ':') return;\n\n const colonIdx = line.indexOf(':');\n const field = colonIdx === -1 ? line : line.slice(0, colonIdx);\n let value = colonIdx === -1 ? '' : line.slice(colonIdx + 1);\n // ? По спеке отбрасывается ровно один ведущий пробел значения.\n if (value[0] === ' ') value = value.slice(1);\n\n switch (field) {\n case 'event':\n event.event = value;\n hasField = true;\n break;\n case 'data':\n dataLines.push(value);\n hasField = true;\n break;\n case 'id':\n event.id = value;\n hasField = true;\n break;\n case 'retry':\n if (/^\\d+$/.test(value)) {\n event.retry = Number(value);\n hasField = true;\n }\n break;\n default:\n // ? Неизвестные поля по спеке игнорируются.\n break;\n }\n });\n\n if (!hasField) return null;\n event.data = dataLines.join('\\n');\n return event;\n}\n\n// ? Безопасный вызов пользовательского колбэка: его ошибка не должна рвать чтение потока.\nfunction safeCall(fn: unknown, ...args: unknown[]): void {\n if (typeof fn !== 'function') return;\n try {\n // ? fn сужен до функции type-guard-ом выше — вызываем без приведения типов.\n fn(...args);\n }\n catch {\n /* пользовательский колбэк не влияет на чтение потока */\n }\n}\n\n/**\n * Читает тело Response как поток Server-Sent Events.\n *\n * Резолвится массивом всех полученных событий ПОСЛЕ закрытия потока.\n * Прерывание потока через `AbortController` трактуется как штатное завершение\n * (возвращается то, что успели собрать); любая иная ошибка чтения пробрасывается выше.\n *\n * @param response - объект Response (или duck-typed с `body.getReader()`).\n * @param options - колбэки и опции обработки потока (см. {@link SSEReadOptions}).\n * @param options.onEvent - вызывается на каждое распарсенное событие.\n * @param options.onChunk - вызывается на полезную нагрузку (поле data) каждого события.\n * @param options.handlers - карта `{ имяСобытия: cb }` для обработки по полю `event`.\n * @param options.parseJson - если `true`, поле `data` прогоняется через `JSON.parse`.\n * @returns Промис с массивом всех распарсенных событий {@link SSEEvent}.\n */\nexport async function readSSE(response: StreamResponseLike, { onEvent, onChunk, handlers, parseJson }: SSEReadOptions = {}): Promise<SSEEvent[]> {\n const events: SSEEvent[] = [];\n // ? Нет тела — нечего читать (защита от null и для strictNullChecks).\n const stream = response.body;\n if (!stream) return events;\n\n const reader = stream.getReader();\n const decoder = new TextDecoder('utf-8');\n let buffer = '';\n // ? Отложенный хвостовой \"\\r\": может оказаться первой половиной \"\\r\\n\", разорванного на границе чанков.\n // ? Без этого наивная нормализация превратила бы \"\\r\" + \"\\n\" в \"\\n\\n\" и создала ложный разделитель событий.\n let pendingCR = '';\n\n // ? Нормализует переводы строк в одном чанке (SSE допускает CR, LF и CRLF).\n const normalize = (chunk: string): string => chunk.replace(/\\r\\n|\\r/g, '\\n');\n\n // ? Диспетчер одного готового блока: парсит, аккумулирует и дёргает колбэки.\n const flush = (rawBlock: string): void => {\n const event = parseSSEEvent(rawBlock);\n if (!event) return;\n\n // ? Опциональный JSON-парсинг полезной нагрузки (под бэкенды, шлющие JSON в data).\n if (parseJson && typeof event.data === 'string' && event.data !== '') {\n try {\n event.data = JSON.parse(event.data);\n }\n catch {\n /* не валидный JSON — оставляем data строкой */\n }\n }\n\n events.push(event);\n safeCall(onEvent, event);\n safeCall(onChunk, event.data, event);\n // ? Типизированный обработчик по имени события (event: delta|status|done|...).\n if (handlers) safeCall(handlers[event.event], event.data, event);\n };\n\n try {\n // ? Читаем поток до закрытия, по мере прихода чанков нарезаем готовые события.\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n // ? Нормализуем только пришедший чанк (линейная сложность), переноса всего буфера не делаем.\n let chunk = pendingCR + decoder.decode(value, { stream: true });\n pendingCR = '';\n // ? Если чанк оканчивается на \"\\r\" — откладываем его: вдруг следующий чанк начнётся с \"\\n\" (CRLF на границе).\n if (chunk.endsWith('\\r')) {\n pendingCR = '\\r';\n chunk = chunk.slice(0, -1);\n }\n buffer += normalize(chunk);\n\n // ? Вырезаем все завершённые события (разделитель — пустая строка).\n let sepIdx;\n // eslint-disable-next-line no-cond-assign\n while ((sepIdx = buffer.indexOf('\\n\\n')) !== -1) {\n const rawBlock = buffer.slice(0, sepIdx);\n buffer = buffer.slice(sepIdx + 2);\n flush(rawBlock);\n }\n }\n\n // ? Добиваем декодер, отложенный \"\\r\" и хвост, если поток закрылся без финальной пустой строки.\n buffer += normalize(pendingCR + decoder.decode());\n buffer = buffer.replace(/\\n+$/g, '');\n if (buffer !== '') flush(buffer);\n }\n catch (error: unknown) {\n // ? Прерывание (abort) — это штатное завершение стрима: возвращаем то, что успели собрать.\n // ? Любую иную ошибку чтения пробрасываем выше (её обработает catchCallback/пользователь).\n // ? abort бросает DOMException с name === 'AbortError' (в Node он не instanceof Error) — проверяем поле через guard.\n const name = error && typeof error === 'object' && 'name' in error ? error.name : undefined;\n if (name !== 'AbortError') throw error;\n }\n finally {\n try {\n reader.releaseLock?.();\n }\n catch {\n /* releaseLock может бросить, если поток уже отпущен — игнорируем */\n }\n }\n\n return events;\n}\n"],"mappings":"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"}
@@ -31,9 +31,7 @@ var intlNumbersFormatter = (inputValue, settings = {}) => {
31
31
  case "currency":
32
32
  numberStyle = "currency";
33
33
  break;
34
- default:
35
- numberStyle = "decimal";
36
- break;
34
+ default: numberStyle = "decimal";
37
35
  }
38
36
  const { quantity, isRenderAlways = false, minimumFractionDigits: inputMinimumFractionDigits, maximumFractionDigits: inputMaximumFractionDigits, conditionallyMinimumFractionDigits } = fractionDigits;
39
37
  const dotIndex = safelyInputValue?.indexOf(".");