intelicoreact 2.0.20 → 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 (210) 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 +5 -4
  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.map +1 -1
  70. package/dist/es/Atomic/FormElements/SwitcherTagsDropdown/SwitcherTagsDropdown.js.map +1 -1
  71. package/dist/es/Atomic/FormElements/SwitcherTextarea/SwitcherTextarea.js.map +1 -1
  72. package/dist/es/Atomic/FormElements/TagsDropdown/TagsDropdown.js.map +1 -1
  73. package/dist/es/Atomic/FormElements/Text/Text.js.map +1 -1
  74. package/dist/es/Atomic/FormElements/TextSwitcher/TextSwitcher.js.map +1 -1
  75. package/dist/es/Atomic/FormElements/Textarea/Textarea.js.map +1 -1
  76. package/dist/es/Atomic/FormElements/TieredCheckboxes/TieredCheckboxes.js +4 -2
  77. package/dist/es/Atomic/FormElements/TieredCheckboxes/TieredCheckboxes.js.map +1 -1
  78. package/dist/es/Atomic/FormElements/TieredCheckboxes/partial/AccordionWithCheckbox.js.map +1 -1
  79. package/dist/es/Atomic/FormElements/TimeRange/TimeRange.js.map +1 -1
  80. package/dist/es/Atomic/FormElements/UserContacts/UserContacts.js.map +1 -1
  81. package/dist/es/Atomic/Layout/Header/Header.js.map +1 -1
  82. package/dist/es/Atomic/Layout/MainMenu/MainMenu.js.map +1 -1
  83. package/dist/es/Atomic/Layout/Spinner/Spinner.js.map +1 -1
  84. package/dist/es/Atomic/UI/Accordion/Accordion.js.map +1 -1
  85. package/dist/es/Atomic/UI/Accordion/AccordionItem.js.map +1 -1
  86. package/dist/es/Atomic/UI/AdvancedTag/AdvTag.js +2 -1
  87. package/dist/es/Atomic/UI/AdvancedTag/AdvTag.js.map +1 -1
  88. package/dist/es/Atomic/UI/AdvancedTag/AdvancedTags.js.map +1 -1
  89. package/dist/es/Atomic/UI/Alert/Alert.js.map +1 -1
  90. package/dist/es/Atomic/UI/Arrow/Arrow.js.map +1 -1
  91. package/dist/es/Atomic/UI/Button/Button.js.map +1 -1
  92. package/dist/es/Atomic/UI/ButtonsBar/ButtonsBar.js.map +1 -1
  93. package/dist/es/Atomic/UI/Chart/Chart.js +2 -1
  94. package/dist/es/Atomic/UI/Chart/Chart.js.map +1 -1
  95. package/dist/es/Atomic/UI/Chart/partial/ChartTypeSwitcherIcon/ChartTypeSwitcherIcon.js.map +1 -1
  96. package/dist/es/Atomic/UI/Chart/partial/utils.js +2 -1
  97. package/dist/es/Atomic/UI/Chart/partial/utils.js.map +1 -1
  98. package/dist/es/Atomic/UI/DateTime/DateTime.js.map +1 -1
  99. package/dist/es/Atomic/UI/DebugContainer/DebugContainer.js.map +1 -1
  100. package/dist/es/Atomic/UI/DoubleString/DoubleString.js.map +1 -1
  101. package/dist/es/Atomic/UI/Hint/Hint.js +4 -6
  102. package/dist/es/Atomic/UI/Hint/Hint.js.map +1 -1
  103. package/dist/es/Atomic/UI/Hint/partials/_utils.js.map +1 -1
  104. package/dist/es/Atomic/UI/Modal/Modal.js.map +1 -1
  105. package/dist/es/Atomic/UI/Modal/ModalHOC.js.map +1 -1
  106. package/dist/es/Atomic/UI/Modal/partials/ModalTitle.js.map +1 -1
  107. package/dist/es/Atomic/UI/Modal/partials/_constants.js.map +1 -1
  108. package/dist/es/Atomic/UI/Modal/partials/_utils.js +1 -4
  109. package/dist/es/Atomic/UI/Modal/partials/_utils.js.map +1 -1
  110. package/dist/es/Atomic/UI/Modal/partials/useMobileModal.js +8 -6
  111. package/dist/es/Atomic/UI/Modal/partials/useMobileModal.js.map +1 -1
  112. package/dist/es/Atomic/UI/NavLine/NavLine.js.map +1 -1
  113. package/dist/es/Atomic/UI/PageTitle/PageTitle.js.map +1 -1
  114. package/dist/es/Atomic/UI/Price/Price.js.map +1 -1
  115. package/dist/es/Atomic/UI/PriceRange/PriceRange.js.map +1 -1
  116. package/dist/es/Atomic/UI/ProgressLine/ProgressLine.js.map +1 -1
  117. package/dist/es/Atomic/UI/Status/Status.js.map +1 -1
  118. package/dist/es/Atomic/UI/Tag/Tag.js.map +1 -1
  119. package/dist/es/Atomic/UI/TagList/TagList.js.map +1 -1
  120. package/dist/es/Atomic/UI/UserBox/UserBox.js.map +1 -1
  121. package/dist/es/Atomic/UI/WizardStepper/ui/StateIcon/StateIcon.js.map +1 -1
  122. package/dist/es/Atomic/UI/WizardStepper/ui/StepRow/StepRow.js.map +1 -1
  123. package/dist/es/Atomic/UI/WizardStepper/ui/StepWrapper/StepWrapper.js.map +1 -1
  124. package/dist/es/Atomic/UI/WizardStepper/ui/icons.js.map +1 -1
  125. package/dist/es/Classes/RESTAPI/partials/CredentialsProcessing.js +4 -2
  126. package/dist/es/Classes/RESTAPI/partials/CredentialsProcessing.js.map +1 -1
  127. package/dist/es/Classes/RESTAPI/partials/sse.js +4 -7
  128. package/dist/es/Classes/RESTAPI/partials/sse.js.map +1 -1
  129. package/dist/es/Functions/fieldValueFormatters.js +1 -3
  130. package/dist/es/Functions/fieldValueFormatters.js.map +1 -1
  131. package/dist/es/Functions/operations.js +22 -20
  132. package/dist/es/Functions/operations.js.map +1 -1
  133. package/dist/es/Functions/useFormTools/form-drivers/ObjectWithIterableObjects.js +8 -6
  134. package/dist/es/Functions/useFormTools/form-drivers/ObjectWithIterableObjects.js.map +1 -1
  135. package/dist/es/Functions/useFormTools/functions/General.js +8 -6
  136. package/dist/es/Functions/useFormTools/functions/General.js.map +1 -1
  137. package/dist/es/Functions/useFormTools/functions/RenderFields.js +6 -5
  138. package/dist/es/Functions/useFormTools/functions/RenderFields.js.map +1 -1
  139. package/dist/es/Functions/useFormTools/index.js +1 -4
  140. package/dist/es/Functions/useFormTools/index.js.map +1 -1
  141. package/dist/es/Functions/utils.js +2 -1
  142. package/dist/es/Functions/utils.js.map +1 -1
  143. package/dist/es/Molecular/CustomIcons/components/AffiliateNetworks.js.map +1 -1
  144. package/dist/es/Molecular/CustomIcons/components/AlertCircle.js.map +1 -1
  145. package/dist/es/Molecular/CustomIcons/components/AppStore.js.map +1 -1
  146. package/dist/es/Molecular/CustomIcons/components/Arrow.js.map +1 -1
  147. package/dist/es/Molecular/CustomIcons/components/ArrowDown.js.map +1 -1
  148. package/dist/es/Molecular/CustomIcons/components/ArrowLeft.js.map +1 -1
  149. package/dist/es/Molecular/CustomIcons/components/ArrowRight.js.map +1 -1
  150. package/dist/es/Molecular/CustomIcons/components/ArrowUp.js.map +1 -1
  151. package/dist/es/Molecular/CustomIcons/components/Bell.js.map +1 -1
  152. package/dist/es/Molecular/CustomIcons/components/Button.js.map +1 -1
  153. package/dist/es/Molecular/CustomIcons/components/Campaigns.js.map +1 -1
  154. package/dist/es/Molecular/CustomIcons/components/Check.js.map +1 -1
  155. package/dist/es/Molecular/CustomIcons/components/Check2.js.map +1 -1
  156. package/dist/es/Molecular/CustomIcons/components/ChevronDown.js.map +1 -1
  157. package/dist/es/Molecular/CustomIcons/components/ChevronDownDisabled.js.map +1 -1
  158. package/dist/es/Molecular/CustomIcons/components/ChevronLeft.js.map +1 -1
  159. package/dist/es/Molecular/CustomIcons/components/ChevronRight.js.map +1 -1
  160. package/dist/es/Molecular/CustomIcons/components/ChevronUp.js.map +1 -1
  161. package/dist/es/Molecular/CustomIcons/components/ChevronUpDown.js.map +1 -1
  162. package/dist/es/Molecular/CustomIcons/components/Close.js.map +1 -1
  163. package/dist/es/Molecular/CustomIcons/components/ColumnsOrder.js.map +1 -1
  164. package/dist/es/Molecular/CustomIcons/components/Delete.js.map +1 -1
  165. package/dist/es/Molecular/CustomIcons/components/Edit.js.map +1 -1
  166. package/dist/es/Molecular/CustomIcons/components/Email.js.map +1 -1
  167. package/dist/es/Molecular/CustomIcons/components/FinturfLogo.js.map +1 -1
  168. package/dist/es/Molecular/CustomIcons/components/FinturfLogo2.js.map +1 -1
  169. package/dist/es/Molecular/CustomIcons/components/Flows.js.map +1 -1
  170. package/dist/es/Molecular/CustomIcons/components/Gift.js.map +1 -1
  171. package/dist/es/Molecular/CustomIcons/components/GoogleAuth.js.map +1 -1
  172. package/dist/es/Molecular/CustomIcons/components/GooglePlay.js.map +1 -1
  173. package/dist/es/Molecular/CustomIcons/components/HelpCircle.js.map +1 -1
  174. package/dist/es/Molecular/CustomIcons/components/HelpCircle2.js.map +1 -1
  175. package/dist/es/Molecular/CustomIcons/components/HelpCircleFilled.js.map +1 -1
  176. package/dist/es/Molecular/CustomIcons/components/Home.js.map +1 -1
  177. package/dist/es/Molecular/CustomIcons/components/Home2.js.map +1 -1
  178. package/dist/es/Molecular/CustomIcons/components/Key.js.map +1 -1
  179. package/dist/es/Molecular/CustomIcons/components/Landers.js.map +1 -1
  180. package/dist/es/Molecular/CustomIcons/components/Lock.js.map +1 -1
  181. package/dist/es/Molecular/CustomIcons/components/Mail.js.map +1 -1
  182. package/dist/es/Molecular/CustomIcons/components/Mastercard.js.map +1 -1
  183. package/dist/es/Molecular/CustomIcons/components/Minus.js.map +1 -1
  184. package/dist/es/Molecular/CustomIcons/components/Offers.js.map +1 -1
  185. package/dist/es/Molecular/CustomIcons/components/Pause.js.map +1 -1
  186. package/dist/es/Molecular/CustomIcons/components/PayPal.js.map +1 -1
  187. package/dist/es/Molecular/CustomIcons/components/PayPalLightLarge.js.map +1 -1
  188. package/dist/es/Molecular/CustomIcons/components/Phone.js.map +1 -1
  189. package/dist/es/Molecular/CustomIcons/components/Play.js.map +1 -1
  190. package/dist/es/Molecular/CustomIcons/components/Plus.js.map +1 -1
  191. package/dist/es/Molecular/CustomIcons/components/Profile.js.map +1 -1
  192. package/dist/es/Molecular/CustomIcons/components/QRCode.js.map +1 -1
  193. package/dist/es/Molecular/CustomIcons/components/Rectangle.js.map +1 -1
  194. package/dist/es/Molecular/CustomIcons/components/Revert.js.map +1 -1
  195. package/dist/es/Molecular/CustomIcons/components/Star.js.map +1 -1
  196. package/dist/es/Molecular/CustomIcons/components/Star2.js.map +1 -1
  197. package/dist/es/Molecular/CustomIcons/components/TrafficSources.js.map +1 -1
  198. package/dist/es/Molecular/CustomIcons/components/Trash.js.map +1 -1
  199. package/dist/es/Molecular/CustomIcons/components/TrashRed.js.map +1 -1
  200. package/dist/es/Molecular/CustomIcons/components/Triggers.js.map +1 -1
  201. package/dist/es/Molecular/CustomIcons/components/User.js.map +1 -1
  202. package/dist/es/Molecular/CustomIcons/components/Visa.js.map +1 -1
  203. package/dist/es/Molecular/CustomIcons/components/X.js.map +1 -1
  204. package/dist/es/Molecular/FormElement/FormElement.js.map +1 -1
  205. package/dist/es/Molecular/InputAddress/InputAddress.js +24 -19
  206. package/dist/es/Molecular/InputAddress/InputAddress.js.map +1 -1
  207. package/dist/es/Molecular/InputCustomFetch/InputCustomFetch.js +17 -11
  208. package/dist/es/Molecular/InputCustomFetch/InputCustomFetch.js.map +1 -1
  209. package/dist/es/Molecular/InputPassword/InputPassword.js.map +1 -1
  210. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.js","names":[],"sources":["../../../../../src/Atomic/UI/Modal/Modal.tsx"],"sourcesContent":["import type { ReactElement, RefObject } from 'react';\nimport type { ISuspendProcessing } from '../../../Functions/useKeyPress/useKeyPress';\nimport type TWithEventManagementAsObj from '../../../types/declaration/TWithEventManagementAsObj';\nimport type { IModalProps } from './Modal.interface';\n\nimport cn from 'classnames';\nimport { useEffect, useLayoutEffect, useMemo, useRef } from 'react';\n\nimport useHandleKeyPress from '../../../Functions/useKeyPress/useHandleKeyPress';\nimport { getIsOnlyAnObject } from '../../../Functions/utils';\nimport Button from '../Button/Button';\n\nimport { EVENTS } from './partials/_constants';\n\nimport { getOnKeyPress, getWithEventManagementStructure } from './partials/_utils';\nimport ModalFooter from './partials/ModalFooter';\nimport ModalTitle from './partials/ModalTitle';\n\nimport useMobileModal from './partials/useMobileModal';\nimport './Modal.scss';\nimport './ModalMobile.scss';\n\nconst attrsForModalBodyDefault = {}\nexport const KEY_CODE = Object.freeze({\n ENTER: 13,\n ESC: 27,\n} as const);\n\nexport function renderModalTitle({\n mode,\n title,\n onlyTitle,\n}: {\n mode?: string;\n title: string;\n onlyTitle?: boolean;\n}): string {\n if (mode && mode !== 'default' && !onlyTitle) {\n return `${mode[0].toUpperCase()}${mode.slice(1)} ${title}`;\n }\n return title;\n}\n\nfunction Modal({\n ref,\n id,\n testId = 'modal',\n zIndex = 100,\n isOpen,\n onConfirm,\n onDecline,\n closeModal,\n className,\n variant = 'primary',\n size,\n mode,\n title,\n onlyTitle,\n atributesForModalBody = attrsForModalBodyDefault,\n confirmBtnClassName,\n confirmBtnLabel,\n confirmBtnVariant = 'primary',\n confirmBtnDisable,\n confirmBtnIcon,\n isConfirmBtnIconPositionRight,\n noConfirmBtn,\n forced,\n closeBtnClassName,\n closeBtnText,\n closeBtnVariant,\n closeBtnDisable,\n closeBtnIcon,\n btnClassNames,\n isCloseBtnIconPositionRight,\n noCloseBtn,\n noHeader,\n noHeaderCloseBtn,\n customHeader,\n declineBtnDisable,\n noFooter,\n customFooter,\n withFixedFooter,\n leftContentOfFooter,\n isSubmittingByEnter: isSubmittingByEnterOuter = true,\n isClosingByEsc: isClosingByEscOuter = true,\n withEventManagement = false,\n submitOnEnter,\n closeOnEsc,\n withMobileLogic,\n children,\n}: IModalProps & { ref?: React.RefObject<HTMLDivElement | null> }): ReactElement | null {\n const internalRef = useRef<HTMLDivElement | null>(null);\n const modalRef = ref || internalRef;\n\n // ? Пояснение разницы между isSubmittingByEnter и confirmBtnDisable (тоже самое для isClosingByEsc и closeBtnDisable)\n // ? - isSubmittingByEnter отключает установку листенера кастомных ивентов, это статика\n // ? (листенеры кастомных ивентов ставятся 1 раз, в useEffect по нулевой зависимости,\n // ? isSubmittingByEnter: false - пропускает его установку)\n // ? - confirmBtnDisable подменяет onConfirm на рефке, это динамика\n // ? (листенер установлен, сработки по кастомным ивентам идут, но НЕ запускается onConfirm)\n const onConfirmRef = useRef(onConfirm);\n const closeModalRef = useRef(closeModal);\n const onDeclineRef = useRef(onDecline);\n\n // todo(vl) - на старых пропах и раньше дефолт был true\n // todo(vl) - поэтому для поддержки старья достаточно отслеживать запреты\n const isSubmittingByEnter = submitOnEnter === false\n ? false\n : isSubmittingByEnterOuter;\n\n const isClosingByEsc = closeOnEsc === false\n ? false\n : isClosingByEscOuter;\n\n // ! Внимание: withEventManagement и withEventManagementStructure НЕ одно и тоже!\n // ! withEventManagementStructure (смотри getWithEventManagementStructure и типизацию)\n // ! - тут ГАРАНТИРОВАНО есть все варианты пропсов из соответствующей ветки InnerTypes (уже настроенные);\n // ! - тут нет ничего из ICommon\n const withEventManagementStructure = getWithEventManagementStructure(id, withEventManagement);\n const isUseAutoBlockingForHandlers = withEventManagementStructure.isWithSubmitAndCloseManagement;\n\n // ? Завязал автоблокировку на ивент-менеджмент для \"мягкого\" перехода, чтобы небыло сюрпризом по всем проектам\n const isOnConfirmBlocked = typeof onConfirm === 'function' && isUseAutoBlockingForHandlers && confirmBtnDisable;\n const isCloseModalBlocked = typeof closeModal === 'function' && isUseAutoBlockingForHandlers && closeBtnDisable;\n const isOnDeclineBlocked = typeof onDecline === 'function' && isUseAutoBlockingForHandlers && declineBtnDisable;\n\n const {\n modalMobileHeaderRef,\n modalMobileBodyRef,\n modalMobileFooterRef,\n MODALS_LOGIC,\n renderModal,\n isMobile,\n scrollTop,\n scrollHeight,\n } = useMobileModal({\n withMobileLogic,\n withFixedFooter,\n isOpen,\n });\n\n // ? Лучше чем useCallback, т.к.\n // ? - НЕ \"дёргает\" верстку (хотя по факту ре-рендер произойдет для useLayoutEffect-ов, но в шедоу-доме ничего не изменится)\n // ? - НЕ замыкает внешние состояния (обеспечивает useLayoutEffect)\n // ? - НЕ нужно переставлять листенеры\n // ? Суть логики: \"иди по этой ссылке и попытайся запустить то что там есть\",\n // ? ссылка - перманентная, содержание может меняться незаметно для оболочки\n const handle = useMemo(() => ({\n confirm: () => onConfirmRef.current?.(),\n close: () => closeModalRef.current?.(),\n\n decline: () => {\n if (typeof onDeclineRef.current === 'function') onDeclineRef.current();\n else closeModalRef.current?.();\n },\n }), []);\n\n // ? Описываем колбеки, чекающие доп. условия приостановки обработки ивентов.\n // ? Я предполагаю, что важно завести эту систему именно через колбеки, которые будут чекать некоторые состояния,\n // ? которые НЕ спровоцируют ререндер для useCalbeck-логики, например активность элементов формы прямо из DOM\n // ? (т.к. эта реализация модалки ничего не знает о состояниях своего внутреннего контента)\n const suspendProcessing = {\n // FIN-12482\n // ? Чтобы НЕ замыкать рефку на модалку в логике, чтобы потом поискать в контенте все текстэриа,\n // ? чтобы оценить есть ли среди них сфокусированная - делаем элеГАнтно:\n // ? оцениваем ev.target, и если target это текстэриа, то вот сейчас то она и сфокусирована,\n // ? т.е нужно приостановить процессы связанные с нажатием enter.\n Enter: (ev: globalThis.KeyboardEvent) => (ev?.target as HTMLElement)?.nodeName === 'TEXTAREA',\n\n // ? Колбеки опциональны, можно передавать только нужные\n // Escape: (ev: globalThis.KeyboardEvent) => false,\n } as ISuspendProcessing;\n\n useHandleKeyPress({\n enterCallback: isSubmittingByEnter && typeof onConfirm === 'function' && !confirmBtnDisable ? handle.confirm : undefined,\n escCallback: isClosingByEsc && typeof closeModal === 'function' ? handle.close : undefined,\n withClamping: false,\n withEventManagementStructure: {\n isWithSubmitAndCloseManagement: confirmBtnDisable || withEventManagementStructure.isWithSubmitAndCloseManagement,\n },\n suspendProcessing,\n });\n\n useLayoutEffect(() => {\n onConfirmRef.current = isOnConfirmBlocked ? undefined : onConfirm;\n }, [onConfirm, isOnConfirmBlocked]);\n\n useLayoutEffect(() => {\n closeModalRef.current = isCloseModalBlocked ? undefined : closeModal;\n }, [closeModal, isCloseModalBlocked]);\n\n useLayoutEffect(() => {\n // ? Нельзя выставить undefined, т.к. в этом случае запустится closeModal (смотри handle.decline)\n onDeclineRef.current = isOnDeclineBlocked ? () => {} : onDecline;\n }, [onDecline, isOnDeclineBlocked]);\n\n // ? Обработка нажатия enter и esc на кастомных ивентах\n useEffect(() => {\n const outerTarget = getIsOnlyAnObject(withEventManagement)\n ? (withEventManagement as TWithEventManagementAsObj<'Modal'>).listenersTarget\n : undefined;\n const target = outerTarget ?? document;\n\n // ? useEffect по нулевой зависимости вызывается 1 раз, а значит ссылка на колбек НЕ изменятся,\n // ? а значит снятие слушателя пройдет корректно\n const onKeyPress = getOnKeyPress({ id, onSubmit: handle.confirm, onClose: handle.close, suspendProcessing });\n\n if (withEventManagementStructure.isWithSubmitAndCloseManagement && !!onKeyPress) {\n if (isSubmittingByEnter) target.addEventListener(EVENTS.iGotAnEnterKeyPress.name, onKeyPress);\n if (isClosingByEsc) target.addEventListener(EVENTS.iGotAnEscKeyPress.name, onKeyPress);\n }\n\n return () => {\n if (withEventManagementStructure.isWithSubmitAndCloseManagement && !!onKeyPress) {\n if (isSubmittingByEnter) target.removeEventListener(EVENTS.iGotAnEnterKeyPress.name, onKeyPress);\n if (isClosingByEsc) target.removeEventListener(EVENTS.iGotAnEscKeyPress.name, onKeyPress);\n }\n }\n }, []);\n\n if (!isOpen) return null;\n\n return (\n <div\n id={`${id}`}\n style={{ zIndex }}\n data-testid={testId}\n className=\"modal-box j5\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={`${testId}-title`}\n >\n {renderModal(\n <>\n <div\n data-testid={`${testId}-overlay`}\n className={isOpen ? 'modal-overlay' : 'hidden'}\n onClick={handle.close}\n role=\"presentation\"\n />\n <div\n ref={modalRef as RefObject<HTMLDivElement>}\n style={{ width: typeof size === 'number' ? `${size}px` : `${size?.replace('px', '')}px` }}\n className={cn(className, {\n 'modal': isOpen,\n 'modal--no-header': isOpen && noHeader && !customHeader,\n 'modal-mobile': isOpen && isMobile,\n 'hidden': !isOpen,\n })}\n >\n {customHeader || (!noHeader && (\n <ModalTitle\n wrapperRef={modalMobileHeaderRef}\n className={cn({\n 'modal__header--hidden': MODALS_LOGIC.IS_HEADER_HIDDEN,\n 'modal__header--sticky': !MODALS_LOGIC.IS_HEADER_HIDDEN && MODALS_LOGIC.IS_HEADER_STICKY,\n })}\n variant={variant}\n isForced={forced}\n onClose={handle.close}\n noHeaderCloseBtn={noHeaderCloseBtn}\n >\n <span id={`${testId}-title`}>{renderModalTitle({ mode, title, onlyTitle })}</span>\n </ModalTitle>\n ))}\n\n <div\n {...atributesForModalBody}\n ref={modalMobileBodyRef}\n className={cn('modal__body', {\n 'modal__body--no-footer': noFooter,\n })}\n role=\"document\"\n >\n {children}\n </div>\n\n {(!noFooter || customFooter) && (\n <ModalFooter\n wrapperRef={modalMobileFooterRef}\n className={cn({\n 'modal__footer--hidden': MODALS_LOGIC.IS_FOOTER_HIDDEN,\n 'modal__footer--sticky':\n !MODALS_LOGIC.IS_FOOTER_HIDDEN\n && MODALS_LOGIC.IS_FOOTER_STICKY\n && scrollTop !== scrollHeight,\n 'modal__footer_with-left-content': leftContentOfFooter,\n })}\n >\n {customFooter || (\n <>\n {leftContentOfFooter}\n {(!noCloseBtn || !noConfirmBtn) && (\n <div className=\"modal__buttons-block\">\n {!noCloseBtn && (\n <Button\n testId=\"modal\"\n className={cn(closeBtnClassName, btnClassNames)}\n variant={closeBtnVariant || 'dark-outline'}\n onClick={handle.decline}\n label={closeBtnText || 'Cancel'}\n disabled={typeof onDecline === 'function' ? declineBtnDisable : closeBtnDisable}\n icon={closeBtnIcon}\n isIconRight={isCloseBtnIconPositionRight}\n tabIndex={1}\n aria-label=\"Close modal\"\n />\n )}\n {!noConfirmBtn && (\n <Button\n testId=\"modal\"\n onClick={handle.confirm}\n label={\n confirmBtnLabel\n || (mode && mode?.[0].toUpperCase() + mode?.slice(1))\n || 'Apply'\n }\n className={cn('ml5', confirmBtnClassName, btnClassNames)}\n variant={confirmBtnVariant}\n disabled={confirmBtnDisable}\n icon={confirmBtnIcon}\n isIconRight={isConfirmBtnIconPositionRight}\n aria-label=\"Confirm modal\"\n />\n )}\n </div>\n )}\n </>\n )}\n </ModalFooter>\n )}\n </div>\n </>,\n )}\n </div>\n );\n}\n\nModal.displayName = 'Modal';\n\nexport default Modal;\n"],"mappings":"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"}
1
+ {"version":3,"file":"Modal.js","names":[],"sources":["../../../../../src/Atomic/UI/Modal/Modal.tsx"],"sourcesContent":["import type { ReactElement, RefObject } from 'react';\nimport type { ISuspendProcessing } from '../../../Functions/useKeyPress/useKeyPress';\nimport type TWithEventManagementAsObj from '../../../types/declaration/TWithEventManagementAsObj';\nimport type { IModalProps } from './Modal.interface';\n\nimport cn from 'classnames';\nimport { useEffect, useLayoutEffect, useMemo, useRef } from 'react';\n\nimport useHandleKeyPress from '../../../Functions/useKeyPress/useHandleKeyPress';\nimport { getIsOnlyAnObject } from '../../../Functions/utils';\nimport Button from '../Button/Button';\n\nimport { EVENTS } from './partials/_constants';\n\nimport { getOnKeyPress, getWithEventManagementStructure } from './partials/_utils';\nimport ModalFooter from './partials/ModalFooter';\nimport ModalTitle from './partials/ModalTitle';\n\nimport useMobileModal from './partials/useMobileModal';\nimport './Modal.scss';\nimport './ModalMobile.scss';\n\nconst attrsForModalBodyDefault = {}\nexport const KEY_CODE = Object.freeze({\n ENTER: 13,\n ESC: 27,\n} as const);\n\nexport function renderModalTitle({\n mode,\n title,\n onlyTitle,\n}: {\n mode?: string;\n title: string;\n onlyTitle?: boolean;\n}): string {\n if (mode && mode !== 'default' && !onlyTitle) {\n return `${mode[0].toUpperCase()}${mode.slice(1)} ${title}`;\n }\n return title;\n}\n\nfunction Modal({\n ref,\n id,\n testId = 'modal',\n zIndex = 100,\n isOpen,\n onConfirm,\n onDecline,\n closeModal,\n className,\n variant = 'primary',\n size,\n mode,\n title,\n onlyTitle,\n atributesForModalBody = attrsForModalBodyDefault,\n confirmBtnClassName,\n confirmBtnLabel,\n confirmBtnVariant = 'primary',\n confirmBtnDisable,\n confirmBtnIcon,\n isConfirmBtnIconPositionRight,\n noConfirmBtn,\n forced,\n closeBtnClassName,\n closeBtnText,\n closeBtnVariant,\n closeBtnDisable,\n closeBtnIcon,\n btnClassNames,\n isCloseBtnIconPositionRight,\n noCloseBtn,\n noHeader,\n noHeaderCloseBtn,\n customHeader,\n declineBtnDisable,\n noFooter,\n customFooter,\n withFixedFooter,\n leftContentOfFooter,\n isSubmittingByEnter: isSubmittingByEnterOuter = true,\n isClosingByEsc: isClosingByEscOuter = true,\n withEventManagement = false,\n submitOnEnter,\n closeOnEsc,\n withMobileLogic,\n children,\n}: IModalProps & { ref?: React.RefObject<HTMLDivElement | null> }): ReactElement | null {\n const internalRef = useRef<HTMLDivElement | null>(null);\n const modalRef = ref || internalRef;\n\n // ? Пояснение разницы между isSubmittingByEnter и confirmBtnDisable (тоже самое для isClosingByEsc и closeBtnDisable)\n // ? - isSubmittingByEnter отключает установку листенера кастомных ивентов, это статика\n // ? (листенеры кастомных ивентов ставятся 1 раз, в useEffect по нулевой зависимости,\n // ? isSubmittingByEnter: false - пропускает его установку)\n // ? - confirmBtnDisable подменяет onConfirm на рефке, это динамика\n // ? (листенер установлен, сработки по кастомным ивентам идут, но НЕ запускается onConfirm)\n const onConfirmRef = useRef(onConfirm);\n const closeModalRef = useRef(closeModal);\n const onDeclineRef = useRef(onDecline);\n\n // todo(vl) - на старых пропах и раньше дефолт был true\n // todo(vl) - поэтому для поддержки старья достаточно отслеживать запреты\n const isSubmittingByEnter = submitOnEnter === false\n ? false\n : isSubmittingByEnterOuter;\n\n const isClosingByEsc = closeOnEsc === false\n ? false\n : isClosingByEscOuter;\n\n // ! Внимание: withEventManagement и withEventManagementStructure НЕ одно и тоже!\n // ! withEventManagementStructure (смотри getWithEventManagementStructure и типизацию)\n // ! - тут ГАРАНТИРОВАНО есть все варианты пропсов из соответствующей ветки InnerTypes (уже настроенные);\n // ! - тут нет ничего из ICommon\n const withEventManagementStructure = getWithEventManagementStructure(id, withEventManagement);\n const isUseAutoBlockingForHandlers = withEventManagementStructure.isWithSubmitAndCloseManagement;\n\n // ? Завязал автоблокировку на ивент-менеджмент для \"мягкого\" перехода, чтобы небыло сюрпризом по всем проектам\n const isOnConfirmBlocked = typeof onConfirm === 'function' && isUseAutoBlockingForHandlers && confirmBtnDisable;\n const isCloseModalBlocked = typeof closeModal === 'function' && isUseAutoBlockingForHandlers && closeBtnDisable;\n const isOnDeclineBlocked = typeof onDecline === 'function' && isUseAutoBlockingForHandlers && declineBtnDisable;\n\n const {\n modalMobileHeaderRef,\n modalMobileBodyRef,\n modalMobileFooterRef,\n MODALS_LOGIC,\n renderModal,\n isMobile,\n scrollTop,\n scrollHeight,\n } = useMobileModal({\n withMobileLogic,\n withFixedFooter,\n isOpen,\n });\n\n // ? Лучше чем useCallback, т.к.\n // ? - НЕ \"дёргает\" верстку (хотя по факту ре-рендер произойдет для useLayoutEffect-ов, но в шедоу-доме ничего не изменится)\n // ? - НЕ замыкает внешние состояния (обеспечивает useLayoutEffect)\n // ? - НЕ нужно переставлять листенеры\n // ? Суть логики: \"иди по этой ссылке и попытайся запустить то что там есть\",\n // ? ссылка - перманентная, содержание может меняться незаметно для оболочки\n const handle = useMemo(() => ({\n confirm: () => onConfirmRef.current?.(),\n close: () => closeModalRef.current?.(),\n\n decline: () => {\n if (typeof onDeclineRef.current === 'function') onDeclineRef.current();\n else closeModalRef.current?.();\n },\n }), []);\n\n // ? Описываем колбеки, чекающие доп. условия приостановки обработки ивентов.\n // ? Я предполагаю, что важно завести эту систему именно через колбеки, которые будут чекать некоторые состояния,\n // ? которые НЕ спровоцируют ререндер для useCalbeck-логики, например активность элементов формы прямо из DOM\n // ? (т.к. эта реализация модалки ничего не знает о состояниях своего внутреннего контента)\n const suspendProcessing = {\n // FIN-12482\n // ? Чтобы НЕ замыкать рефку на модалку в логике, чтобы потом поискать в контенте все текстэриа,\n // ? чтобы оценить есть ли среди них сфокусированная - делаем элеГАнтно:\n // ? оцениваем ev.target, и если target это текстэриа, то вот сейчас то она и сфокусирована,\n // ? т.е нужно приостановить процессы связанные с нажатием enter.\n Enter: (ev: globalThis.KeyboardEvent) => (ev?.target as HTMLElement)?.nodeName === 'TEXTAREA',\n\n // ? Колбеки опциональны, можно передавать только нужные\n // Escape: (ev: globalThis.KeyboardEvent) => false,\n } as ISuspendProcessing;\n\n useHandleKeyPress({\n enterCallback: isSubmittingByEnter && typeof onConfirm === 'function' && !confirmBtnDisable ? handle.confirm : undefined,\n escCallback: isClosingByEsc && typeof closeModal === 'function' ? handle.close : undefined,\n withClamping: false,\n withEventManagementStructure: {\n isWithSubmitAndCloseManagement: confirmBtnDisable || withEventManagementStructure.isWithSubmitAndCloseManagement,\n },\n suspendProcessing,\n });\n\n useLayoutEffect(() => {\n onConfirmRef.current = isOnConfirmBlocked ? undefined : onConfirm;\n }, [onConfirm, isOnConfirmBlocked]);\n\n useLayoutEffect(() => {\n closeModalRef.current = isCloseModalBlocked ? undefined : closeModal;\n }, [closeModal, isCloseModalBlocked]);\n\n useLayoutEffect(() => {\n // ? Нельзя выставить undefined, т.к. в этом случае запустится closeModal (смотри handle.decline)\n onDeclineRef.current = isOnDeclineBlocked ? () => {} : onDecline;\n }, [onDecline, isOnDeclineBlocked]);\n\n // ? Обработка нажатия enter и esc на кастомных ивентах\n useEffect(() => {\n const outerTarget = getIsOnlyAnObject(withEventManagement)\n ? (withEventManagement as TWithEventManagementAsObj<'Modal'>).listenersTarget\n : undefined;\n const target = outerTarget ?? document;\n\n // ? useEffect по нулевой зависимости вызывается 1 раз, а значит ссылка на колбек НЕ изменятся,\n // ? а значит снятие слушателя пройдет корректно\n const onKeyPress = getOnKeyPress({ id, onSubmit: handle.confirm, onClose: handle.close, suspendProcessing });\n\n if (withEventManagementStructure.isWithSubmitAndCloseManagement && !!onKeyPress) {\n if (isSubmittingByEnter) target.addEventListener(EVENTS.iGotAnEnterKeyPress.name, onKeyPress);\n if (isClosingByEsc) target.addEventListener(EVENTS.iGotAnEscKeyPress.name, onKeyPress);\n }\n\n return () => {\n if (withEventManagementStructure.isWithSubmitAndCloseManagement && !!onKeyPress) {\n if (isSubmittingByEnter) target.removeEventListener(EVENTS.iGotAnEnterKeyPress.name, onKeyPress);\n if (isClosingByEsc) target.removeEventListener(EVENTS.iGotAnEscKeyPress.name, onKeyPress);\n }\n }\n }, []);\n\n if (!isOpen) return null;\n\n return (\n <div\n id={`${id}`}\n style={{ zIndex }}\n data-testid={testId}\n className=\"modal-box j5\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={`${testId}-title`}\n >\n {renderModal(\n <>\n <div\n data-testid={`${testId}-overlay`}\n className={isOpen ? 'modal-overlay' : 'hidden'}\n onClick={handle.close}\n role=\"presentation\"\n />\n <div\n ref={modalRef as RefObject<HTMLDivElement>}\n style={{ width: typeof size === 'number' ? `${size}px` : `${size?.replace('px', '')}px` }}\n className={cn(className, {\n 'modal': isOpen,\n 'modal--no-header': isOpen && noHeader && !customHeader,\n 'modal-mobile': isOpen && isMobile,\n 'hidden': !isOpen,\n })}\n >\n {customHeader || (!noHeader && (\n <ModalTitle\n wrapperRef={modalMobileHeaderRef}\n className={cn({\n 'modal__header--hidden': MODALS_LOGIC.IS_HEADER_HIDDEN,\n 'modal__header--sticky': !MODALS_LOGIC.IS_HEADER_HIDDEN && MODALS_LOGIC.IS_HEADER_STICKY,\n })}\n variant={variant}\n isForced={forced}\n onClose={handle.close}\n noHeaderCloseBtn={noHeaderCloseBtn}\n >\n <span id={`${testId}-title`}>{renderModalTitle({ mode, title, onlyTitle })}</span>\n </ModalTitle>\n ))}\n\n <div\n {...atributesForModalBody}\n ref={modalMobileBodyRef}\n className={cn('modal__body', {\n 'modal__body--no-footer': noFooter,\n })}\n role=\"document\"\n >\n {children}\n </div>\n\n {(!noFooter || customFooter) && (\n <ModalFooter\n wrapperRef={modalMobileFooterRef}\n className={cn({\n 'modal__footer--hidden': MODALS_LOGIC.IS_FOOTER_HIDDEN,\n 'modal__footer--sticky':\n !MODALS_LOGIC.IS_FOOTER_HIDDEN\n && MODALS_LOGIC.IS_FOOTER_STICKY\n && scrollTop !== scrollHeight,\n 'modal__footer_with-left-content': leftContentOfFooter,\n })}\n >\n {customFooter || (\n <>\n {leftContentOfFooter}\n {(!noCloseBtn || !noConfirmBtn) && (\n <div className=\"modal__buttons-block\">\n {!noCloseBtn && (\n <Button\n testId=\"modal\"\n className={cn(closeBtnClassName, btnClassNames)}\n variant={closeBtnVariant || 'dark-outline'}\n onClick={handle.decline}\n label={closeBtnText || 'Cancel'}\n disabled={typeof onDecline === 'function' ? declineBtnDisable : closeBtnDisable}\n icon={closeBtnIcon}\n isIconRight={isCloseBtnIconPositionRight}\n tabIndex={1}\n aria-label=\"Close modal\"\n />\n )}\n {!noConfirmBtn && (\n <Button\n testId=\"modal\"\n onClick={handle.confirm}\n label={\n confirmBtnLabel\n || (mode && mode?.[0].toUpperCase() + mode?.slice(1))\n || 'Apply'\n }\n className={cn('ml5', confirmBtnClassName, btnClassNames)}\n variant={confirmBtnVariant}\n disabled={confirmBtnDisable}\n icon={confirmBtnIcon}\n isIconRight={isConfirmBtnIconPositionRight}\n aria-label=\"Confirm modal\"\n />\n )}\n </div>\n )}\n </>\n )}\n </ModalFooter>\n )}\n </div>\n </>,\n )}\n </div>\n );\n}\n\nModal.displayName = 'Modal';\n\nexport default Modal;\n"],"mappings":";;;;;;;;;;;;;;AAsBA,IAAM,2BAA2B,CAAC;AAClC,IAAa,WAAW,OAAO,OAAO;CACpC,OAAO;CACP,KAAK;AACP,CAAU;AAEV,SAAgB,iBAAiB,EAC/B,MACA,OACA,aAKS;CACT,IAAI,QAAQ,SAAS,aAAa,CAAC,WACjC,OAAO,GAAG,KAAK,EAAE,CAAC,YAAY,IAAI,KAAK,MAAM,CAAC,EAAE,GAAG;CAErD,OAAO;AACT;AAEA,SAAS,MAAM,EACb,KACA,IACA,SAAS,SACT,SAAS,KACT,QACA,WACA,WACA,YACA,WACA,UAAU,WACV,MACA,MACA,OACA,WACA,wBAAwB,0BACxB,qBACA,iBACA,oBAAoB,WACpB,mBACA,gBACA,+BACA,cACA,QACA,mBACA,cACA,iBACA,iBACA,cACA,eACA,6BACA,YACA,UACA,kBACA,cACA,mBACA,UACA,cACA,iBACA,qBACA,qBAAqB,2BAA2B,MAChD,gBAAgB,sBAAsB,MACtC,sBAAsB,OACtB,eACA,YACA,iBACA,YACsF;CACtF,MAAM,cAAc,OAA8B,IAAI;CACtD,MAAM,WAAW,OAAO;CAQxB,MAAM,eAAe,OAAO,SAAS;CACrC,MAAM,gBAAgB,OAAO,UAAU;CACvC,MAAM,eAAe,OAAO,SAAS;CAIrC,MAAM,sBAAsB,kBAAkB,QAC1C,QACA;CAEJ,MAAM,iBAAiB,eAAe,QAClC,QACA;CAMJ,MAAM,+BAA+B,gCAAgC,IAAI,mBAAmB;CAC5F,MAAM,+BAA+B,6BAA6B;CAGlE,MAAM,qBAAqB,OAAO,cAAc,cAAc,gCAAgC;CAC9F,MAAM,sBAAsB,OAAO,eAAe,cAAc,gCAAgC;CAChG,MAAM,qBAAqB,OAAO,cAAc,cAAc,gCAAgC;CAE9F,MAAM,EACJ,sBACA,oBACA,sBACA,cACA,aACA,UACA,WACA,iBACE,eAAe;EACjB;EACA;EACA;CACF,CAAC;CAQD,MAAM,SAAS,eAAe;EAC5B,eAAe,aAAa,UAAU;EACtC,aAAa,cAAc,UAAU;EAErC,eAAe;GACb,IAAI,OAAO,aAAa,YAAY,YAAY,aAAa,QAAQ;QAChE,cAAc,UAAU;EAC/B;CACF,IAAI,CAAC,CAAC;CAMN,MAAM,oBAAoB,EAMxB,QAAQ,QAAkC,IAAI,OAAA,EAAwB,aAAa,WAIrF;CAEA,kBAAkB;EAChB,eAAe,uBAAuB,OAAO,cAAc,cAAc,CAAC,oBAAoB,OAAO,UAAU,KAAA;EAC/G,aAAa,kBAAkB,OAAO,eAAe,aAAa,OAAO,QAAQ,KAAA;EACjF,cAAc;EACd,8BAA8B,EAC5B,gCAAgC,qBAAqB,6BAA6B,+BACpF;EACA;CACF,CAAC;CAED,sBAAsB;EACpB,aAAa,UAAU,qBAAqB,KAAA,IAAY;CAC1D,GAAG,CAAC,WAAW,kBAAkB,CAAC;CAElC,sBAAsB;EACpB,cAAc,UAAU,sBAAsB,KAAA,IAAY;CAC5D,GAAG,CAAC,YAAY,mBAAmB,CAAC;CAEpC,sBAAsB;EAEpB,aAAa,UAAU,2BAA2B,CAAC,IAAI;CACzD,GAAG,CAAC,WAAW,kBAAkB,CAAC;CAGlC,gBAAgB;EAId,MAAM,UAHc,kBAAkB,mBAAmB,IACpD,oBAA2D,kBAC5D,KAAA,MAC0B;EAI9B,MAAM,aAAa,cAAc;GAAE;GAAI,UAAU,OAAO;GAAS,SAAS,OAAO;GAAO;EAAkB,CAAC;EAE3G,IAAI,6BAA6B,kCAAkC,CAAC,CAAC,YAAY;GAC/E,IAAI,qBAAqB,OAAO,iBAAiB,OAAO,oBAAoB,MAAM,UAAU;GAC5F,IAAI,gBAAgB,OAAO,iBAAiB,OAAO,kBAAkB,MAAM,UAAU;EACvF;EAEA,aAAa;GACX,IAAI,6BAA6B,kCAAkC,CAAC,CAAC,YAAY;IAC/E,IAAI,qBAAqB,OAAO,oBAAoB,OAAO,oBAAoB,MAAM,UAAU;IAC/F,IAAI,gBAAgB,OAAO,oBAAoB,OAAO,kBAAkB,MAAM,UAAU;GAC1F;EACF;CACF,GAAG,CAAC,CAAC;CAEL,IAAI,CAAC,QAAQ,OAAO;CAEpB,OACE,oBAAC,OAAD;EACE,IAAI,GAAG;EACP,OAAO,EAAE,OAAO;EAChB,eAAa;EACb,WAAU;EACV,MAAK;EACL,cAAW;EACX,mBAAiB,GAAG,OAAO;EAE1B,UAAA,YACC,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,OAAD;GACE,eAAa,GAAG,OAAO;GACvB,WAAW,SAAS,kBAAkB;GACtC,SAAS,OAAO;GAChB,MAAK;EACN,CAAA,GACD,qBAAC,OAAD;GACE,KAAK;GACL,OAAO,EAAE,OAAO,OAAO,SAAS,WAAW,GAAG,KAAK,MAAM,GAAG,MAAM,QAAQ,MAAM,EAAE,EAAE,IAAI;GACxF,WAAW,GAAG,WAAW;IACvB,SAAS;IACT,oBAAoB,UAAU,YAAY,CAAC;IAC3C,gBAAgB,UAAU;IAC1B,UAAU,CAAC;GACb,CAAC;GARH,UAAA;IAUG,gBAAiB,CAAC,YACjB,oBAAC,YAAD;KACE,YAAY;KACZ,WAAW,GAAG;MACZ,yBAAyB,aAAa;MACtC,yBAAyB,CAAC,aAAa,oBAAoB,aAAa;KAC1E,CAAC;KACQ;KACT,UAAU;KACV,SAAS,OAAO;KACE;KAElB,UAAA,oBAAC,QAAD;MAAM,IAAI,GAAG,OAAO;MAAU,UAAA,iBAAiB;OAAE;OAAM;OAAO;MAAU,CAAC;KAAQ,CAAA;IACvE,CAAA;IAGd,oBAAC,OAAD;KACE,GAAI;KACJ,KAAK;KACL,WAAW,GAAG,eAAe,EAC3B,0BAA0B,SAC5B,CAAC;KACD,MAAK;KAEJ;IACE,CAAA;KAEH,CAAC,YAAY,iBACb,oBAAC,aAAD;KACE,YAAY;KACZ,WAAW,GAAG;MACZ,yBAAyB,aAAa;MACtC,yBACI,CAAC,aAAa,oBACX,aAAa,oBACb,cAAc;MACrB,mCAAmC;KACrC,CAAC;KAEA,UAAA,gBACC,qBAAA,UAAA,EAAA,UAAA,CACG,sBACC,CAAC,cAAc,CAAC,iBAChB,qBAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACG,CAAC,cACA,oBAAC,QAAD;OACE,QAAO;OACP,WAAW,GAAG,mBAAmB,aAAa;OAC9C,SAAS,mBAAmB;OAC5B,SAAS,OAAO;OAChB,OAAO,gBAAgB;OACvB,UAAU,OAAO,cAAc,aAAa,oBAAoB;OAChE,MAAM;OACN,aAAa;OACb,UAAU;OACV,cAAW;MACZ,CAAA,GAEF,CAAC,gBACA,oBAAC,QAAD;OACE,QAAO;OACP,SAAS,OAAO;OAChB,OACE,mBACI,QAAQ,OAAO,EAAE,CAAC,YAAY,IAAI,MAAM,MAAM,CAAC,KAChD;OAEL,WAAW,GAAG,OAAO,qBAAqB,aAAa;OACvD,SAAS;OACT,UAAU;OACV,MAAM;OACN,aAAa;OACb,cAAW;MACZ,CAAA,CAEA;KAEP,CAAA,CAAA,EAAA,CAAA;IAEO,CAAA;GAEZ;EACL,CAAA,CAAA,EAAA,CAAA,CACJ;CACG,CAAA;AAET;AAEA,MAAM,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"ModalHOC.js","names":[],"sources":["../../../../../src/Atomic/UI/Modal/ModalHOC.tsx"],"sourcesContent":["import type { IModalHOCProps } from './Modal.interface';\n\nimport cn from 'classnames';\nimport React, { useEffect, useLayoutEffect, useMemo, useRef } from 'react';\n\nimport useHandleKeyPress from '../../../Functions/useKeyPress/useHandleKeyPress';\nimport { EVENTS } from './partials/_constants';\nimport { getOnKeyPress, getWithEventManagementStructure } from './partials/_utils';\n\nimport './Modal.scss';\n\nconst ModalHOC: React.FC<IModalHOCProps> = ({\n id,\n zIndex = 100,\n isOpen,\n closeModal,\n closeBtnDisable,\n\n children,\n className,\n size,\n testId = 'modal',\n\n withEventManagement = false, // ! Полностью проигнорируется если в модалку НЕ прокинут id\n\n // ? isClosingByEsc является явным разрешением/запретом на работу ф-ла,\n // ? в то время как withEventManagement лишь настройка способа реализации этого ф-ла\n isClosingByEsc: isClosingByEscOuter = true,\n closeOnEsc,\n}) => {\n const modalRef = useRef(null);\n const closeModalRef = useRef(closeModal);\n\n // todo(vl) - на старых пропах и раньше дефолт был true\n // todo(vl) - поэтому для поддержки старья достаточно отслеживать запреты\n const isClosingByEsc = closeOnEsc === false\n ? false\n : isClosingByEscOuter;\n\n const withEventManagementStructure = getWithEventManagementStructure(id, withEventManagement);\n\n // ? Лучше чем useCallback, т.к.\n // ? - НЕ \"дёргает\" верстку (хотя по факту ре-рендер произойдет для useLayoutEffect-ов, но в шедоу-доме ничего не изменится)\n // ? - НЕ замыкает внешние состояния (обеспечивает useLayoutEffect)\n // ? - НЕ нужно переставлять листенеры\n // ? Суть логики: \"иди по этой ссылке и попытайся запустить то что там есть\",\n // ? ссылка - перманентная, содержание может меняться незаметно для оболочки\n const handleClose: () => void = useMemo(() => () => closeModalRef.current?.(), []);\n\n useHandleKeyPress({\n escCallback: isClosingByEsc && typeof closeModal === 'function' ? handleClose : undefined,\n withEventManagementStructure,\n });\n\n useLayoutEffect(() => {\n closeModalRef.current = closeBtnDisable ? undefined : closeModal;\n }, [closeModal, closeBtnDisable]);\n\n // ? Обработка нажатия enter и esc на кастомных ивентах\n useEffect(() => {\n // ? useEffect по нулевой зависимости вызывается 1 раз, а значит ссылка на колбек НЕ изменятся,\n // ? а значит снятие слушателя пройдет корректно\n const onKeyPress = getOnKeyPress({ id, onClose: handleClose }); // в ModalHOC onSubmit не запланирован\n\n if (withEventManagementStructure.isWithSubmitAndCloseManagement && !!onKeyPress) {\n // if () document.addEventListener(EVENTS.iGotAnEnterKeyPress.name, onKeyPress); // в ModalHOC onSubmit не запланирован\n if (isClosingByEsc) document.addEventListener(EVENTS.iGotAnEscKeyPress.name, onKeyPress);\n }\n\n return () => {\n if (withEventManagementStructure.isWithSubmitAndCloseManagement && !!onKeyPress) {\n // if () document.removeEventListener(EVENTS.iGotAnEnterKeyPress.name, onKeyPress); // в ModalHOC onSubmit не запланирован\n if (isClosingByEsc) document.removeEventListener(EVENTS.iGotAnEscKeyPress.name, onKeyPress);\n }\n }\n }, []);\n\n if (!isOpen) return null;\n return (\n <div id={`${id}`} style={{ zIndex }} data-testid={testId} className=\"modal-box j5\" role=\"presentation\">\n <div className=\"modal-overlay\" onClick={handleClose} role=\"presentation\" aria-hidden=\"true\" />\n <div\n ref={modalRef}\n style={{ width: size }}\n className={cn(className, 'modal')}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={testId}\n tabIndex={-1}\n >\n {children}\n </div>\n </div>\n );\n};\n\nexport default ModalHOC;\n"],"mappings":";;;;;;;;AAWA,IAAM,YAAsC,EAC1C,IACA,SAAS,KACT,QACA,YACA,iBAEA,UACA,WACA,MACA,SAAS,SAET,sBAAsB,OAItB,gBAAgB,sBAAsB,MACtC,iBACI;CACJ,MAAM,WAAW,OAAO,IAAI;CAC5B,MAAM,gBAAgB,OAAO,UAAU;CAIvC,MAAM,iBAAiB,eAAe,QAClC,QACA;CAEJ,MAAM,+BAA+B,gCAAgC,IAAI,mBAAmB;CAQ5F,MAAM,cAA0B,oBAAoB,cAAc,UAAU,GAAG,CAAC,CAAC;CAEjF,kBAAkB;EAChB,aAAa,kBAAkB,OAAO,eAAe,aAAa,cAAc,KAAA;EAChF;CACF,CAAC;CAED,sBAAsB;EACpB,cAAc,UAAU,kBAAkB,KAAA,IAAY;CACxD,GAAG,CAAC,YAAY,eAAe,CAAC;CAGhC,gBAAgB;EAGd,MAAM,aAAa,cAAc;GAAE;GAAI,SAAS;EAAY,CAAC;EAE7D,IAAI,6BAA6B,kCAAkC,CAAC,CAAC;OAE/D,gBAAgB,SAAS,iBAAiB,OAAO,kBAAkB,MAAM,UAAU;EAAA;EAGzF,aAAa;GACX,IAAI,6BAA6B,kCAAkC,CAAC,CAAC;QAE/D,gBAAgB,SAAS,oBAAoB,OAAO,kBAAkB,MAAM,UAAU;GAAA;EAE9F;CACF,GAAG,CAAC,CAAC;CAEL,IAAI,CAAC,QAAQ,OAAO;CACpB,OACE,qBAAC,OAAD;EAAK,IAAI,GAAG;EAAM,OAAO,EAAE,OAAO;EAAG,eAAa;EAAQ,WAAU;EAAe,MAAK;YAAxF,CACE,oBAAC,OAAD;GAAK,WAAU;GAAgB,SAAS;GAAa,MAAK;GAAe,eAAY;EAAQ,CAAA,GAC7F,oBAAC,OAAD;GACE,KAAK;GACL,OAAO,EAAE,OAAO,KAAK;GACrB,WAAW,GAAG,WAAW,OAAO;GAChC,MAAK;GACL,cAAW;GACX,mBAAiB;GACjB,UAAU;GAET;EACE,CAAA,CACF;;AAET"}
1
+ {"version":3,"file":"ModalHOC.js","names":[],"sources":["../../../../../src/Atomic/UI/Modal/ModalHOC.tsx"],"sourcesContent":["import type { IModalHOCProps } from './Modal.interface';\n\nimport cn from 'classnames';\nimport React, { useEffect, useLayoutEffect, useMemo, useRef } from 'react';\n\nimport useHandleKeyPress from '../../../Functions/useKeyPress/useHandleKeyPress';\nimport { EVENTS } from './partials/_constants';\nimport { getOnKeyPress, getWithEventManagementStructure } from './partials/_utils';\n\nimport './Modal.scss';\n\nconst ModalHOC: React.FC<IModalHOCProps> = ({\n id,\n zIndex = 100,\n isOpen,\n closeModal,\n closeBtnDisable,\n\n children,\n className,\n size,\n testId = 'modal',\n\n withEventManagement = false, // ! Полностью проигнорируется если в модалку НЕ прокинут id\n\n // ? isClosingByEsc является явным разрешением/запретом на работу ф-ла,\n // ? в то время как withEventManagement лишь настройка способа реализации этого ф-ла\n isClosingByEsc: isClosingByEscOuter = true,\n closeOnEsc,\n}) => {\n const modalRef = useRef(null);\n const closeModalRef = useRef(closeModal);\n\n // todo(vl) - на старых пропах и раньше дефолт был true\n // todo(vl) - поэтому для поддержки старья достаточно отслеживать запреты\n const isClosingByEsc = closeOnEsc === false\n ? false\n : isClosingByEscOuter;\n\n const withEventManagementStructure = getWithEventManagementStructure(id, withEventManagement);\n\n // ? Лучше чем useCallback, т.к.\n // ? - НЕ \"дёргает\" верстку (хотя по факту ре-рендер произойдет для useLayoutEffect-ов, но в шедоу-доме ничего не изменится)\n // ? - НЕ замыкает внешние состояния (обеспечивает useLayoutEffect)\n // ? - НЕ нужно переставлять листенеры\n // ? Суть логики: \"иди по этой ссылке и попытайся запустить то что там есть\",\n // ? ссылка - перманентная, содержание может меняться незаметно для оболочки\n const handleClose: () => void = useMemo(() => () => closeModalRef.current?.(), []);\n\n useHandleKeyPress({\n escCallback: isClosingByEsc && typeof closeModal === 'function' ? handleClose : undefined,\n withEventManagementStructure,\n });\n\n useLayoutEffect(() => {\n closeModalRef.current = closeBtnDisable ? undefined : closeModal;\n }, [closeModal, closeBtnDisable]);\n\n // ? Обработка нажатия enter и esc на кастомных ивентах\n useEffect(() => {\n // ? useEffect по нулевой зависимости вызывается 1 раз, а значит ссылка на колбек НЕ изменятся,\n // ? а значит снятие слушателя пройдет корректно\n const onKeyPress = getOnKeyPress({ id, onClose: handleClose }); // в ModalHOC onSubmit не запланирован\n\n if (withEventManagementStructure.isWithSubmitAndCloseManagement && !!onKeyPress) {\n // if () document.addEventListener(EVENTS.iGotAnEnterKeyPress.name, onKeyPress); // в ModalHOC onSubmit не запланирован\n if (isClosingByEsc) document.addEventListener(EVENTS.iGotAnEscKeyPress.name, onKeyPress);\n }\n\n return () => {\n if (withEventManagementStructure.isWithSubmitAndCloseManagement && !!onKeyPress) {\n // if () document.removeEventListener(EVENTS.iGotAnEnterKeyPress.name, onKeyPress); // в ModalHOC onSubmit не запланирован\n if (isClosingByEsc) document.removeEventListener(EVENTS.iGotAnEscKeyPress.name, onKeyPress);\n }\n }\n }, []);\n\n if (!isOpen) return null;\n return (\n <div id={`${id}`} style={{ zIndex }} data-testid={testId} className=\"modal-box j5\" role=\"presentation\">\n <div className=\"modal-overlay\" onClick={handleClose} role=\"presentation\" aria-hidden=\"true\" />\n <div\n ref={modalRef}\n style={{ width: size }}\n className={cn(className, 'modal')}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={testId}\n tabIndex={-1}\n >\n {children}\n </div>\n </div>\n );\n};\n\nexport default ModalHOC;\n"],"mappings":";;;;;;;;AAWA,IAAM,YAAsC,EAC1C,IACA,SAAS,KACT,QACA,YACA,iBAEA,UACA,WACA,MACA,SAAS,SAET,sBAAsB,OAItB,gBAAgB,sBAAsB,MACtC,iBACI;CACJ,MAAM,WAAW,OAAO,IAAI;CAC5B,MAAM,gBAAgB,OAAO,UAAU;CAIvC,MAAM,iBAAiB,eAAe,QAClC,QACA;CAEJ,MAAM,+BAA+B,gCAAgC,IAAI,mBAAmB;CAQ5F,MAAM,cAA0B,oBAAoB,cAAc,UAAU,GAAG,CAAC,CAAC;CAEjF,kBAAkB;EAChB,aAAa,kBAAkB,OAAO,eAAe,aAAa,cAAc,KAAA;EAChF;CACF,CAAC;CAED,sBAAsB;EACpB,cAAc,UAAU,kBAAkB,KAAA,IAAY;CACxD,GAAG,CAAC,YAAY,eAAe,CAAC;CAGhC,gBAAgB;EAGd,MAAM,aAAa,cAAc;GAAE;GAAI,SAAS;EAAY,CAAC;EAE7D,IAAI,6BAA6B,kCAAkC,CAAC,CAAC,YAE/D;OAAA,gBAAgB,SAAS,iBAAiB,OAAO,kBAAkB,MAAM,UAAU;EAAA;EAGzF,aAAa;GACX,IAAI,6BAA6B,kCAAkC,CAAC,CAAC,YAE/D;QAAA,gBAAgB,SAAS,oBAAoB,OAAO,kBAAkB,MAAM,UAAU;GAAA;EAE9F;CACF,GAAG,CAAC,CAAC;CAEL,IAAI,CAAC,QAAQ,OAAO;CACpB,OACE,qBAAC,OAAD;EAAK,IAAI,GAAG;EAAM,OAAO,EAAE,OAAO;EAAG,eAAa;EAAQ,WAAU;EAAe,MAAK;EAAxF,UAAA,CACE,oBAAC,OAAD;GAAK,WAAU;GAAgB,SAAS;GAAa,MAAK;GAAe,eAAY;EAAQ,CAAA,GAC7F,oBAAC,OAAD;GACE,KAAK;GACL,OAAO,EAAE,OAAO,KAAK;GACrB,WAAW,GAAG,WAAW,OAAO;GAChC,MAAK;GACL,cAAW;GACX,mBAAiB;GACjB,UAAU;GAET;EACE,CAAA,CACF;;AAET"}
@@ -1 +1 @@
1
- {"version":3,"file":"ModalTitle.js","names":[],"sources":["../../../../../../src/Atomic/UI/Modal/partials/ModalTitle.tsx"],"sourcesContent":["import type { IModalTitleProps } from '../Modal.interface';\nimport cn from 'classnames';\nimport React, { memo, useLayoutEffect, useMemo, useRef } from 'react';\n\nimport { X } from 'react-feather';\n\nconst ModalTitle: React.FC<IModalTitleProps> = memo(\n ({\n variant = 'primary',\n children,\n isForced = false,\n onClose,\n closeBtnDisable,\n\n noHeaderCloseBtn = false,\n className,\n wrapperRef,\n testId = 'modal-title',\n }) => {\n const closeModalRef = useRef(onClose);\n\n // ! НЕ нужно тут предусматривать обработку нажатия Enter/Esc (предусмотрена в ModalHOC).\n // ? Если нужна эта инкапсулированая логика - пользуйтесь композицией\n // ? - \"закрыватель\" в ModalHOC обеспечит обработку Enter/Esc\n // ? - \"закрыватель\" в ModalTitle накинется на \"крестик\"\n /*\n <ModalHOC\n пропы\n closeModal={ваш_закрыватель}\n >\n <ModalTitle\n пропы\n onClose={ваш_закрыватель}\n >\n {ваша верстка}\n </ModalTitle>\n\n {ваш остальной контент}\n </ModalHOC>\n */\n\n // ? Лучше чем useCallback, т.к.\n // ? - НЕ \"дёргает\" верстку (хотя по факту ре-рендер произойдет для useLayoutEffect-ов, но в шедоу-доме ничего не изменится)\n // ? - НЕ замыкает внешние состояния (обеспечивает useLayoutEffect)\n // ? - НЕ нужно переставлять листенеры\n // ? Суть логики: \"иди по этой ссылке и попытайся запустить то что там есть\",\n // ? ссылка - перманентная, содержание может меняться незаметно для оболочки\n const handleClick: () => void = useMemo(() => () => closeModalRef.current?.(), []);\n\n useLayoutEffect(() => {\n closeModalRef.current = closeBtnDisable ? undefined : onClose;\n }, [onClose, closeBtnDisable]);\n\n return (\n <header\n data-testid={testId}\n ref={wrapperRef}\n className={cn('modal__header', className, {\n [`modal__header-${variant}`]: variant,\n })}\n role=\"banner\"\n aria-label=\"Modal header\"\n >\n <span\n className={cn('modal__header-title', {\n [`modal__header-${variant}-title`]: variant,\n })}\n id={`${testId}-heading`}\n >\n {children}\n </span>\n {!isForced && (\n <button\n type=\"button\"\n onClick={handleClick}\n className={cn('modal-close-icon-box', {\n 'modal-close-icon-box-primary': variant === 'primary',\n 'modal-close-icon-box--hidden': noHeaderCloseBtn,\n })}\n aria-label=\"Close modal\"\n title=\"Close modal\"\n >\n {!noHeaderCloseBtn && <X className=\"modal-close-icon\" role=\"img\" aria-hidden=\"true\" />}\n </button>\n )}\n </header>\n );\n },\n);\n\nModalTitle.displayName = 'ModalTitle';\n\nexport default ModalTitle;\n"],"mappings":";;;;;AAMA,IAAM,aAAyC,MAC5C,EACC,UAAU,WACV,UACA,WAAW,OACX,SACA,iBAEA,mBAAmB,OACnB,WACA,YACA,SAAS,oBACL;CACJ,MAAM,gBAAgB,OAAO,OAAO;CA4BpC,MAAM,cAA0B,oBAAoB,cAAc,UAAU,GAAG,CAAC,CAAC;CAEjF,sBAAsB;EACpB,cAAc,UAAU,kBAAkB,KAAA,IAAY;CACxD,GAAG,CAAC,SAAS,eAAe,CAAC;CAE7B,OACE,qBAAC,UAAD;EACE,eAAa;EACb,KAAK;EACL,WAAW,GAAG,iBAAiB,WAAW,GACvC,iBAAiB,YAAY,QAChC,CAAC;EACD,MAAK;EACL,cAAW;YAPb,CASE,oBAAC,QAAD;GACE,WAAW,GAAG,uBAAuB,GAClC,iBAAiB,QAAQ,UAAU,QACtC,CAAC;GACD,IAAI,GAAG,OAAO;GAEb;EACG,CAAA,GACL,CAAC,YACA,oBAAC,UAAD;GACE,MAAK;GACL,SAAS;GACT,WAAW,GAAG,wBAAwB;IACpC,gCAAgC,YAAY;IAC5C,gCAAgC;GAClC,CAAC;GACD,cAAW;GACX,OAAM;aAEL,CAAC,oBAAoB,oBAAC,GAAD;IAAG,WAAU;IAAmB,MAAK;IAAM,eAAY;GAAQ,CAAA;EAC/E,CAAA,CAEJ;;AAEZ,CACF;AAEA,WAAW,cAAc"}
1
+ {"version":3,"file":"ModalTitle.js","names":[],"sources":["../../../../../../src/Atomic/UI/Modal/partials/ModalTitle.tsx"],"sourcesContent":["import type { IModalTitleProps } from '../Modal.interface';\nimport cn from 'classnames';\nimport React, { memo, useLayoutEffect, useMemo, useRef } from 'react';\n\nimport { X } from 'react-feather';\n\nconst ModalTitle: React.FC<IModalTitleProps> = memo(\n ({\n variant = 'primary',\n children,\n isForced = false,\n onClose,\n closeBtnDisable,\n\n noHeaderCloseBtn = false,\n className,\n wrapperRef,\n testId = 'modal-title',\n }) => {\n const closeModalRef = useRef(onClose);\n\n // ! НЕ нужно тут предусматривать обработку нажатия Enter/Esc (предусмотрена в ModalHOC).\n // ? Если нужна эта инкапсулированая логика - пользуйтесь композицией\n // ? - \"закрыватель\" в ModalHOC обеспечит обработку Enter/Esc\n // ? - \"закрыватель\" в ModalTitle накинется на \"крестик\"\n /*\n <ModalHOC\n пропы\n closeModal={ваш_закрыватель}\n >\n <ModalTitle\n пропы\n onClose={ваш_закрыватель}\n >\n {ваша верстка}\n </ModalTitle>\n\n {ваш остальной контент}\n </ModalHOC>\n */\n\n // ? Лучше чем useCallback, т.к.\n // ? - НЕ \"дёргает\" верстку (хотя по факту ре-рендер произойдет для useLayoutEffect-ов, но в шедоу-доме ничего не изменится)\n // ? - НЕ замыкает внешние состояния (обеспечивает useLayoutEffect)\n // ? - НЕ нужно переставлять листенеры\n // ? Суть логики: \"иди по этой ссылке и попытайся запустить то что там есть\",\n // ? ссылка - перманентная, содержание может меняться незаметно для оболочки\n const handleClick: () => void = useMemo(() => () => closeModalRef.current?.(), []);\n\n useLayoutEffect(() => {\n closeModalRef.current = closeBtnDisable ? undefined : onClose;\n }, [onClose, closeBtnDisable]);\n\n return (\n <header\n data-testid={testId}\n ref={wrapperRef}\n className={cn('modal__header', className, {\n [`modal__header-${variant}`]: variant,\n })}\n role=\"banner\"\n aria-label=\"Modal header\"\n >\n <span\n className={cn('modal__header-title', {\n [`modal__header-${variant}-title`]: variant,\n })}\n id={`${testId}-heading`}\n >\n {children}\n </span>\n {!isForced && (\n <button\n type=\"button\"\n onClick={handleClick}\n className={cn('modal-close-icon-box', {\n 'modal-close-icon-box-primary': variant === 'primary',\n 'modal-close-icon-box--hidden': noHeaderCloseBtn,\n })}\n aria-label=\"Close modal\"\n title=\"Close modal\"\n >\n {!noHeaderCloseBtn && <X className=\"modal-close-icon\" role=\"img\" aria-hidden=\"true\" />}\n </button>\n )}\n </header>\n );\n },\n);\n\nModalTitle.displayName = 'ModalTitle';\n\nexport default ModalTitle;\n"],"mappings":";;;;;AAMA,IAAM,aAAyC,MAC5C,EACC,UAAU,WACV,UACA,WAAW,OACX,SACA,iBAEA,mBAAmB,OACnB,WACA,YACA,SAAS,oBACL;CACJ,MAAM,gBAAgB,OAAO,OAAO;CA4BpC,MAAM,cAA0B,oBAAoB,cAAc,UAAU,GAAG,CAAC,CAAC;CAEjF,sBAAsB;EACpB,cAAc,UAAU,kBAAkB,KAAA,IAAY;CACxD,GAAG,CAAC,SAAS,eAAe,CAAC;CAE7B,OACE,qBAAC,UAAD;EACE,eAAa;EACb,KAAK;EACL,WAAW,GAAG,iBAAiB,WAAW,GACvC,iBAAiB,YAAY,QAChC,CAAC;EACD,MAAK;EACL,cAAW;EAPb,UAAA,CASE,oBAAC,QAAD;GACE,WAAW,GAAG,uBAAuB,GAClC,iBAAiB,QAAQ,UAAU,QACtC,CAAC;GACD,IAAI,GAAG,OAAO;GAEb;EACG,CAAA,GACL,CAAC,YACA,oBAAC,UAAD;GACE,MAAK;GACL,SAAS;GACT,WAAW,GAAG,wBAAwB;IACpC,gCAAgC,YAAY;IAC5C,gCAAgC;GAClC,CAAC;GACD,cAAW;GACX,OAAM;GAEL,UAAA,CAAC,oBAAoB,oBAAC,GAAD;IAAG,WAAU;IAAmB,MAAK;IAAM,eAAY;GAAQ,CAAA;EAC/E,CAAA,CAEJ;;AAEZ,CACF;AAEA,WAAW,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"_constants.js","names":[],"sources":["../../../../../../src/Atomic/UI/Modal/partials/_constants.ts"],"sourcesContent":["// ? Опции для диспатча ивента\nexport const DEFAULT_EVENT_OPTIONS = Object.freeze({\n bubbles: true,\n cancelable: true,\n composed: false,\n});\n\n// ? Возможные ключи кастомных ивентов, предусмотренных в системе обработки (внутренний нейминг)\nexport enum ModalEventsInnerKeys {\n iGotAnEnterKeyPress = 'iGotAnEnterKeyPress',\n iGotAnEscKeyPress = 'iGotAnEscKeyPress',\n}\n\n/** Тип значения ev.key (KeyboardEvent.key) — привязка к глобальному типу, без своего union */\nexport type KeyboardEventKey = globalThis.KeyboardEvent['key'];\n\n// ? Интерфейс ивента (константная информация об ивенте)\nexport interface ICustomEvent<Key extends ModalEventsInnerKeys> {\n // ? внутренний ключ, соотношение с внутренним неймингом\n innerKey: Key;\n // ? Полное название ивента (используется для диспатча)\n // ? Для полного имени кастомного ивента используется следующий шаблон:\n // ? 'условная_цель_ивента:описание_того_что_произошло'\n // ? На уровне проекта пнредполагается, что константа EVENTS будет импортирована (как и диспатчер),\n // ? И диспатчится будут ивенты на манеру: dispatch(EVENTS.iGotAnEnterKeyPress.name, ...остальные_аргументы)\n name: string;\n // ? НО )) если комуто лень, то можно воспоьзоваться кототким имененм и прописать \"руками\"\n // ? Например: dispatch('enterIsPressed', ...остальные_аргументы), если 'enterIsPressed' указано в shortName нужного ивента\n // ? Но, нужно помнить, что на обработку (уровень либы) ивент придет все-равно с полным имененм (custonEvent.type),\n // ? так написан диспатчер\n shortName: string;\n\n // ? Идетнтификатор для механики suspendProcessing: ключ колбека из suspendProcessing с которым соотносится этот ивент.\n // ? Завязал бы механику suspendProcessing на типизацию и нейминг отсюда, но вынужден поддерживать старые механики\n // ? (в частности useKeyPress), а там как бы не очень логично юзать \"какую-то левую типизацию\"\n // ? На текущий момент. система кастомных ивентов \"умеет\" обрабатывать нажатия клавиш (enter и escape),\n // ? поэтому логично выбрать ev.key (ключ клавиши в ивенте - KeyboardEventKey).\n // ? Но в дальнейшем система может раширяться и затрагиватьивенты \"не клавишные\", поэтому предусматриваю прото стринговое велью.\n middlewareKey: string | KeyboardEventKey;\n // ? Опции для диспатча ивента, можно переиспользовать DEFAULT_EVENT_OPTIONS, можно прописать свои значения\n options: EventInit;\n}\n\n/** Объект, у которого каждый ключ K из енама задаёт тип значения ICustomEvent<K> */\n// ? Объект у которого\n// ? - ключи могут быть ТОЛЬКО из ModalEventsInnerKeys\n// ? - ключ объекта задает ключ дженерика ICustomEvent (фиксируем конкретный ивент с внутренним неймингом, в ивенте - innerKey)\nexport type IConstantInfoAboutModalEvents<Keys extends ModalEventsInnerKeys> = { [K in Keys]: ICustomEvent<K> };\n\n// ? Описание всех кастомных ивентов, предусмотренных в системе обработки.\nexport const EVENTS: IConstantInfoAboutModalEvents<ModalEventsInnerKeys> = Object.freeze({\n [ModalEventsInnerKeys.iGotAnEnterKeyPress]: {\n innerKey: ModalEventsInnerKeys.iGotAnEnterKeyPress,\n name: 'modal:i-got-an-enter-key-press',\n shortName: 'enterIsPressed',\n middlewareKey: 'Enter',\n options: DEFAULT_EVENT_OPTIONS,\n },\n [ModalEventsInnerKeys.iGotAnEscKeyPress]: {\n innerKey: ModalEventsInnerKeys.iGotAnEscKeyPress,\n name: 'modal:i-got-an-esc-key-press',\n shortName: 'escIsPressed',\n middlewareKey: 'Escape',\n options: DEFAULT_EVENT_OPTIONS,\n },\n});\n"],"mappings":";AACA,IAAa,wBAAwB,OAAO,OAAO;CACjD,SAAS;CACT,YAAY;CACZ,UAAU;AACZ,CAAC;AA6CD,IAAa,SAA8D,OAAO,OAAO;0BAC3C;EAC1C,UAAA;EACA,MAAM;EACN,WAAW;EACX,eAAe;EACf,SAAS;CACX;wBAC0C;EACxC,UAAA;EACA,MAAM;EACN,WAAW;EACX,eAAe;EACf,SAAS;CACX;AACF,CAAC"}
1
+ {"version":3,"file":"_constants.js","names":[],"sources":["../../../../../../src/Atomic/UI/Modal/partials/_constants.ts"],"sourcesContent":["// ? Опции для диспатча ивента\nexport const DEFAULT_EVENT_OPTIONS = Object.freeze({\n bubbles: true,\n cancelable: true,\n composed: false,\n});\n\n// ? Возможные ключи кастомных ивентов, предусмотренных в системе обработки (внутренний нейминг)\nexport enum ModalEventsInnerKeys {\n iGotAnEnterKeyPress = 'iGotAnEnterKeyPress',\n iGotAnEscKeyPress = 'iGotAnEscKeyPress',\n}\n\n/** Тип значения ev.key (KeyboardEvent.key) — привязка к глобальному типу, без своего union */\nexport type KeyboardEventKey = globalThis.KeyboardEvent['key'];\n\n// ? Интерфейс ивента (константная информация об ивенте)\nexport interface ICustomEvent<Key extends ModalEventsInnerKeys> {\n // ? внутренний ключ, соотношение с внутренним неймингом\n innerKey: Key;\n // ? Полное название ивента (используется для диспатча)\n // ? Для полного имени кастомного ивента используется следующий шаблон:\n // ? 'условная_цель_ивента:описание_того_что_произошло'\n // ? На уровне проекта пнредполагается, что константа EVENTS будет импортирована (как и диспатчер),\n // ? И диспатчится будут ивенты на манеру: dispatch(EVENTS.iGotAnEnterKeyPress.name, ...остальные_аргументы)\n name: string;\n // ? НО )) если комуто лень, то можно воспоьзоваться кототким имененм и прописать \"руками\"\n // ? Например: dispatch('enterIsPressed', ...остальные_аргументы), если 'enterIsPressed' указано в shortName нужного ивента\n // ? Но, нужно помнить, что на обработку (уровень либы) ивент придет все-равно с полным имененм (custonEvent.type),\n // ? так написан диспатчер\n shortName: string;\n\n // ? Идетнтификатор для механики suspendProcessing: ключ колбека из suspendProcessing с которым соотносится этот ивент.\n // ? Завязал бы механику suspendProcessing на типизацию и нейминг отсюда, но вынужден поддерживать старые механики\n // ? (в частности useKeyPress), а там как бы не очень логично юзать \"какую-то левую типизацию\"\n // ? На текущий момент. система кастомных ивентов \"умеет\" обрабатывать нажатия клавиш (enter и escape),\n // ? поэтому логично выбрать ev.key (ключ клавиши в ивенте - KeyboardEventKey).\n // ? Но в дальнейшем система может раширяться и затрагиватьивенты \"не клавишные\", поэтому предусматриваю прото стринговое велью.\n middlewareKey: string | KeyboardEventKey;\n // ? Опции для диспатча ивента, можно переиспользовать DEFAULT_EVENT_OPTIONS, можно прописать свои значения\n options: EventInit;\n}\n\n/** Объект, у которого каждый ключ K из енама задаёт тип значения ICustomEvent<K> */\n// ? Объект у которого\n// ? - ключи могут быть ТОЛЬКО из ModalEventsInnerKeys\n// ? - ключ объекта задает ключ дженерика ICustomEvent (фиксируем конкретный ивент с внутренним неймингом, в ивенте - innerKey)\nexport type IConstantInfoAboutModalEvents<Keys extends ModalEventsInnerKeys> = { [K in Keys]: ICustomEvent<K> };\n\n// ? Описание всех кастомных ивентов, предусмотренных в системе обработки.\nexport const EVENTS: IConstantInfoAboutModalEvents<ModalEventsInnerKeys> = Object.freeze({\n [ModalEventsInnerKeys.iGotAnEnterKeyPress]: {\n innerKey: ModalEventsInnerKeys.iGotAnEnterKeyPress,\n name: 'modal:i-got-an-enter-key-press',\n shortName: 'enterIsPressed',\n middlewareKey: 'Enter',\n options: DEFAULT_EVENT_OPTIONS,\n },\n [ModalEventsInnerKeys.iGotAnEscKeyPress]: {\n innerKey: ModalEventsInnerKeys.iGotAnEscKeyPress,\n name: 'modal:i-got-an-esc-key-press',\n shortName: 'escIsPressed',\n middlewareKey: 'Escape',\n options: DEFAULT_EVENT_OPTIONS,\n },\n});\n"],"mappings":";AACA,IAAa,wBAAwB,OAAO,OAAO;CACjD,SAAS;CACT,YAAY;CACZ,UAAU;AACZ,CAAC;AA6CD,IAAa,SAA8D,OAAO,OAAO;EAC3C,wBAAA;EAC1C,UAAA;EACA,MAAM;EACN,WAAW;EACX,eAAe;EACf,SAAS;CACX;EAC0C,sBAAA;EACxC,UAAA;EACA,MAAM;EACN,WAAW;EACX,eAAe;EACf,SAAS;CACX;AACF,CAAC"}
@@ -19,10 +19,7 @@ function getOnKeyPress({ id: modalId, onSubmit, onClose, suspendProcessing }) {
19
19
  case EVENTS.iGotAnEnterKeyPress.name:
20
20
  onSubmit?.();
21
21
  break;
22
- case EVENTS.iGotAnEscKeyPress.name:
23
- onClose?.();
24
- break;
25
- default: break;
22
+ case EVENTS.iGotAnEscKeyPress.name: onClose?.();
26
23
  }
27
24
  };
28
25
  }
@@ -1 +1 @@
1
- {"version":3,"file":"_utils.js","names":[],"sources":["../../../../../../src/Atomic/UI/Modal/partials/_utils.ts"],"sourcesContent":["import type { ISuspendProcessing } from '../../../../Functions/useKeyPress/useKeyPress';\nimport type TWithEventManagementAsObj from '../../../../types/declaration/TWithEventManagementAsObj';\nimport type { IModalProps } from '../Modal.interface';\nimport type { ICustomEvent, ModalEventsInnerKeys } from './_constants';\n\nimport { isISuspendProcessing } from '../../../../Functions/useKeyPress/useKeyPress';\nimport { getIsOnlyAnObject } from '../../../../Functions/utils';\nimport { EVENTS } from './_constants';\n\n// ? Геттер объекта конфигурации для включения/выключения функционала управления ивентами\n// ? Гарантирует возврат структуры с ПОЛНЫМ набором возможных опций\nexport function getWithEventManagementStructure(\n modalId: number | string | null | undefined,\n withEventManagement?: IModalProps['withEventManagement'],\n): TWithEventManagementAsObj<'Modal', true> {\n // ! Тут ДОЛЖНЫ БЫТЬ перечислены все варианты из типа TWithEventManagementAsObj<'Modal'> (БЕЗ пропсов ICommon)\n // ! Именно поэтому типизация используется с isHard-опцией и через satisfies\n const output = {\n isWithSubmitAndCloseManagement: false,\n } satisfies TWithEventManagementAsObj<'Modal', true>;\n\n // ? Итерируемся по описанным вариантам\n for (const key in output) {\n // ? Если в модалку НЕ передан id, то система НЕ сможет работать корректно\n if (!modalId) {\n output[key as keyof typeof output] = false;\n }\n else {\n // ? Приcваиваем значения пропам заданной структуры исходя из withEventManagement\n // ? - если withEventManagement объект, то это соответствующая пропа (если такая есть)\n // ? - либо это приведённое к логическому типу значение withEventManagement\n output[key as keyof typeof output] = (\n getIsOnlyAnObject(withEventManagement)\n ? ((withEventManagement as TWithEventManagementAsObj<'Modal'>)[key as keyof TWithEventManagementAsObj<'Modal'>] ?? false)\n : !!withEventManagement\n );\n }\n }\n\n return output;\n}\n\n// ? Геттер колбека для задиспатченных ивентов\n// ? (сделано через геттер чтобы не дублироваться для Modal и ModalHOC,\n// ? если пишется для одного места, то в гетере нет смысла, можно все писать в useEffect)\nexport function getOnKeyPress({\n id: modalId,\n onSubmit,\n onClose,\n suspendProcessing,\n}: {\n id: number | string | null | undefined;\n onSubmit?: () => unknown;\n onClose?: () => unknown;\n suspendProcessing?: ISuspendProcessing | null;\n}): ((ev: Event) => void) | null {\n if (!modalId) return null;\n\n return function onKeyPress(ev: Event): void {\n // ? Приведение типизации\n const customEvent = ev as CustomEvent;\n // ? Достаем детали задиспатченного ивента\n const { id: eventId, realEvent } = customEvent.detail || {};\n // ? Достаем из справочника константную инфу об кастомном ивенте\n const constantInfoAboutCustomEvent = (\n Object.values(EVENTS).find(ev => ev.name === customEvent.type || ev.shortName === customEvent.type) || {}\n ) as ICustomEvent<ModalEventsInnerKeys>;\n // ? Выясняем ключ для системы suspendProcessing\n const middlewareKey = constantInfoAboutCustomEvent.middlewareKey || 'incorrectKey';\n\n const safelySuspendProcessing = (isISuspendProcessing(suspendProcessing) ? suspendProcessing : {}) as ISuspendProcessing;\n\n // ? Делаем что-либо если\n // ? - если есть modalId (модалка идентифицирована)\n // ? - если есть eventId (при диспатче кастомного ивента на уровне проекта указали кому адресован ивент)\n // ? - если eventId === modalId (задиспатченый ивент предназначен этой модалке)\n // ? - если нет оснований приостановить обработку (есть колбек и его запуск вернул true, т.е. \"да, приостановить\")\n if (modalId && eventId && eventId === modalId && !(safelySuspendProcessing[middlewareKey]?.(realEvent))) {\n // ? В ev.type приходит ПОЛНОЕ имя ивента (так написан диспатчер)\n switch (customEvent.type) {\n case EVENTS.iGotAnEnterKeyPress.name: {\n onSubmit?.();\n break;\n }\n case EVENTS.iGotAnEscKeyPress.name: {\n onClose?.();\n break;\n }\n default: { break; }\n }\n }\n };\n}\n\n// ? Диспатчер ивентов (для экспорта, для удобства и корректности диспатчей на местах)\n// ? eventName - определяет ивент, который вы хотите запустить\n// ? uniqueId - планируется что это будет ключ модалки (ключ ветки в ModalStore)\n// ? target - передавайте тоже самое, что/если прокидывали в пропу withEventManagement.listenersTarget\nexport function dispatchEventForModalManagement(\n realEvent: globalThis.KeyboardEvent,\n nameOfCustomEvent: string,\n uniqueIdOfRecipient: number | string,\n target?: HTMLElement | Document,\n): void {\n const { repeat, altKey, ctrlKey, shiftKey, metaKey } = realEvent;\n const isPressingWithoutAuxiliaryKeys = !altKey && !ctrlKey && !shiftKey && !metaKey;\n\n if (!repeat && isPressingWithoutAuxiliaryKeys) {\n const event = Object.values(EVENTS).find(ev => ev.name === nameOfCustomEvent || ev.shortName === nameOfCustomEvent);\n if (event && uniqueIdOfRecipient) {\n (target ?? document).dispatchEvent(new CustomEvent(event.name, { ...event.options, detail: { id: uniqueIdOfRecipient, realEvent } }));\n }\n }\n}\n"],"mappings":";;;;AAWA,SAAgB,gCACd,SACA,qBAC0C;CAG1C,MAAM,SAAS,EACb,gCAAgC,MAClC;CAGA,KAAK,MAAM,OAAO,QAEhB,IAAI,CAAC,SACH,OAAO,OAA8B;MAMrC,OAAO,OACL,kBAAkB,mBAAmB,IAC/B,oBAA2D,QAAoD,QACjH,CAAC,CAAC;CAKZ,OAAO;AACT;AAKA,SAAgB,cAAc,EAC5B,IAAI,SACJ,UACA,SACA,qBAM+B;CAC/B,IAAI,CAAC,SAAS,OAAO;CAErB,OAAO,SAAS,WAAW,IAAiB;EAE1C,MAAM,cAAc;EAEpB,MAAM,EAAE,IAAI,SAAS,cAAc,YAAY,UAAU,CAAC;EAM1D,MAAM,iBAHJ,OAAO,OAAO,MAAM,CAAC,CAAC,MAAK,OAAM,GAAG,SAAS,YAAY,QAAQ,GAAG,cAAc,YAAY,IAAI,KAAK,CAAC,EAAA,CAGvD,iBAAiB;EAEpE,MAAM,0BAA2B,qBAAqB,iBAAiB,IAAI,oBAAoB,CAAC;EAOhG,IAAI,WAAW,WAAW,YAAY,WAAW,CAAE,wBAAwB,cAAc,GAAG,SAAS,GAEnG,QAAQ,YAAY,MAApB;GACE,KAAK,OAAO,oBAAoB;IAC9B,WAAW;IACX;GAEF,KAAK,OAAO,kBAAkB;IAC5B,UAAU;IACV;GAEF,SAAW;EACb;CAEJ;AACF;AAMA,SAAgB,gCACd,WACA,mBACA,qBACA,QACM;CACN,MAAM,EAAE,QAAQ,QAAQ,SAAS,UAAU,YAAY;CAGvD,IAAI,CAAC,UAFkC,CAAC,UAAU,CAAC,WAAW,CAAC,YAAY,CAAC,SAE7B;EAC7C,MAAM,QAAQ,OAAO,OAAO,MAAM,CAAC,CAAC,MAAK,OAAM,GAAG,SAAS,qBAAqB,GAAG,cAAc,iBAAiB;EAClH,IAAI,SAAS,qBACX,CAAC,UAAU,SAAA,CAAU,cAAc,IAAI,YAAY,MAAM,MAAM;GAAE,GAAG,MAAM;GAAS,QAAQ;IAAE,IAAI;IAAqB;GAAU;EAAE,CAAC,CAAC;CAExI;AACF"}
1
+ {"version":3,"file":"_utils.js","names":[],"sources":["../../../../../../src/Atomic/UI/Modal/partials/_utils.ts"],"sourcesContent":["import type { ISuspendProcessing } from '../../../../Functions/useKeyPress/useKeyPress';\nimport type TWithEventManagementAsObj from '../../../../types/declaration/TWithEventManagementAsObj';\nimport type { IModalProps } from '../Modal.interface';\nimport type { ICustomEvent, ModalEventsInnerKeys } from './_constants';\n\nimport { isISuspendProcessing } from '../../../../Functions/useKeyPress/useKeyPress';\nimport { getIsOnlyAnObject } from '../../../../Functions/utils';\nimport { EVENTS } from './_constants';\n\n// ? Геттер объекта конфигурации для включения/выключения функционала управления ивентами\n// ? Гарантирует возврат структуры с ПОЛНЫМ набором возможных опций\nexport function getWithEventManagementStructure(\n modalId: number | string | null | undefined,\n withEventManagement?: IModalProps['withEventManagement'],\n): TWithEventManagementAsObj<'Modal', true> {\n // ! Тут ДОЛЖНЫ БЫТЬ перечислены все варианты из типа TWithEventManagementAsObj<'Modal'> (БЕЗ пропсов ICommon)\n // ! Именно поэтому типизация используется с isHard-опцией и через satisfies\n const output = {\n isWithSubmitAndCloseManagement: false,\n } satisfies TWithEventManagementAsObj<'Modal', true>;\n\n // ? Итерируемся по описанным вариантам\n for (const key in output) {\n // ? Если в модалку НЕ передан id, то система НЕ сможет работать корректно\n if (!modalId) {\n output[key as keyof typeof output] = false;\n }\n else {\n // ? Приcваиваем значения пропам заданной структуры исходя из withEventManagement\n // ? - если withEventManagement объект, то это соответствующая пропа (если такая есть)\n // ? - либо это приведённое к логическому типу значение withEventManagement\n output[key as keyof typeof output] = (\n getIsOnlyAnObject(withEventManagement)\n ? ((withEventManagement as TWithEventManagementAsObj<'Modal'>)[key as keyof TWithEventManagementAsObj<'Modal'>] ?? false)\n : !!withEventManagement\n );\n }\n }\n\n return output;\n}\n\n// ? Геттер колбека для задиспатченных ивентов\n// ? (сделано через геттер чтобы не дублироваться для Modal и ModalHOC,\n// ? если пишется для одного места, то в гетере нет смысла, можно все писать в useEffect)\nexport function getOnKeyPress({\n id: modalId,\n onSubmit,\n onClose,\n suspendProcessing,\n}: {\n id: number | string | null | undefined;\n onSubmit?: () => unknown;\n onClose?: () => unknown;\n suspendProcessing?: ISuspendProcessing | null;\n}): ((ev: Event) => void) | null {\n if (!modalId) return null;\n\n return function onKeyPress(ev: Event): void {\n // ? Приведение типизации\n const customEvent = ev as CustomEvent;\n // ? Достаем детали задиспатченного ивента\n const { id: eventId, realEvent } = customEvent.detail || {};\n // ? Достаем из справочника константную инфу об кастомном ивенте\n const constantInfoAboutCustomEvent = (\n Object.values(EVENTS).find(ev => ev.name === customEvent.type || ev.shortName === customEvent.type) || {}\n ) as ICustomEvent<ModalEventsInnerKeys>;\n // ? Выясняем ключ для системы suspendProcessing\n const middlewareKey = constantInfoAboutCustomEvent.middlewareKey || 'incorrectKey';\n\n const safelySuspendProcessing = (isISuspendProcessing(suspendProcessing) ? suspendProcessing : {}) as ISuspendProcessing;\n\n // ? Делаем что-либо если\n // ? - если есть modalId (модалка идентифицирована)\n // ? - если есть eventId (при диспатче кастомного ивента на уровне проекта указали кому адресован ивент)\n // ? - если eventId === modalId (задиспатченый ивент предназначен этой модалке)\n // ? - если нет оснований приостановить обработку (есть колбек и его запуск вернул true, т.е. \"да, приостановить\")\n if (modalId && eventId && eventId === modalId && !(safelySuspendProcessing[middlewareKey]?.(realEvent))) {\n // ? В ev.type приходит ПОЛНОЕ имя ивента (так написан диспатчер)\n switch (customEvent.type) {\n case EVENTS.iGotAnEnterKeyPress.name: {\n onSubmit?.();\n break;\n }\n case EVENTS.iGotAnEscKeyPress.name: {\n onClose?.();\n break;\n }\n default: { break; }\n }\n }\n };\n}\n\n// ? Диспатчер ивентов (для экспорта, для удобства и корректности диспатчей на местах)\n// ? eventName - определяет ивент, который вы хотите запустить\n// ? uniqueId - планируется что это будет ключ модалки (ключ ветки в ModalStore)\n// ? target - передавайте тоже самое, что/если прокидывали в пропу withEventManagement.listenersTarget\nexport function dispatchEventForModalManagement(\n realEvent: globalThis.KeyboardEvent,\n nameOfCustomEvent: string,\n uniqueIdOfRecipient: number | string,\n target?: HTMLElement | Document,\n): void {\n const { repeat, altKey, ctrlKey, shiftKey, metaKey } = realEvent;\n const isPressingWithoutAuxiliaryKeys = !altKey && !ctrlKey && !shiftKey && !metaKey;\n\n if (!repeat && isPressingWithoutAuxiliaryKeys) {\n const event = Object.values(EVENTS).find(ev => ev.name === nameOfCustomEvent || ev.shortName === nameOfCustomEvent);\n if (event && uniqueIdOfRecipient) {\n (target ?? document).dispatchEvent(new CustomEvent(event.name, { ...event.options, detail: { id: uniqueIdOfRecipient, realEvent } }));\n }\n }\n}\n"],"mappings":";;;;AAWA,SAAgB,gCACd,SACA,qBAC0C;CAG1C,MAAM,SAAS,EACb,gCAAgC,MAClC;CAGA,KAAK,MAAM,OAAO,QAEhB,IAAI,CAAC,SACH,OAAO,OAA8B;MAMrC,OAAO,OACL,kBAAkB,mBAAmB,IAC/B,oBAA2D,QAAoD,QACjH,CAAC,CAAC;CAKZ,OAAO;AACT;AAKA,SAAgB,cAAc,EAC5B,IAAI,SACJ,UACA,SACA,qBAM+B;CAC/B,IAAI,CAAC,SAAS,OAAO;CAErB,OAAO,SAAS,WAAW,IAAiB;EAE1C,MAAM,cAAc;EAEpB,MAAM,EAAE,IAAI,SAAS,cAAc,YAAY,UAAU,CAAC;EAM1D,MAAM,iBAHJ,OAAO,OAAO,MAAM,CAAC,CAAC,MAAK,OAAM,GAAG,SAAS,YAAY,QAAQ,GAAG,cAAc,YAAY,IAAI,KAAK,CAAC,EAAA,CAGvD,iBAAiB;EAEpE,MAAM,0BAA2B,qBAAqB,iBAAiB,IAAI,oBAAoB,CAAC;EAOhG,IAAI,WAAW,WAAW,YAAY,WAAW,CAAE,wBAAwB,cAAc,GAAG,SAAS,GAEnG,QAAQ,YAAY,MAApB;GACE,KAAK,OAAO,oBAAoB;IAC9B,WAAW;IACX;GAEF,KAAK,OAAO,kBAAkB,MAC5B,UAAU;EAId;CAEJ;AACF;AAMA,SAAgB,gCACd,WACA,mBACA,qBACA,QACM;CACN,MAAM,EAAE,QAAQ,QAAQ,SAAS,UAAU,YAAY;CAGvD,IAAI,CAAC,UAFkC,CAAC,UAAU,CAAC,WAAW,CAAC,YAAY,CAAC,SAE7B;EAC7C,MAAM,QAAQ,OAAO,OAAO,MAAM,CAAC,CAAC,MAAK,OAAM,GAAG,SAAS,qBAAqB,GAAG,cAAc,iBAAiB;EAClH,IAAI,SAAS,qBACX,CAAC,UAAU,SAAA,CAAU,cAAc,IAAI,YAAY,MAAM,MAAM;GAAE,GAAG,MAAM;GAAS,QAAQ;IAAE,IAAI;IAAqB;GAAU;EAAE,CAAC,CAAC;CAExI;AACF"}
@@ -48,12 +48,14 @@ function useMobileModal({ modalRef, withMobileLogic = false, withFixedFooter = f
48
48
  const modalStyle = modalRef?.current ? modalRef?.current.style || window.getComputedStyle(modalRef?.current) : {};
49
49
  const computedModalHeight = modalRef?.current ? modalHeight + Number.parseFloat(modalStyle?.marginTop || "0") : 0;
50
50
  const windowHeight = document.documentElement.clientHeight || window.screen.availHeight || window.screen.height;
51
- if (modalMobileContainerRef?.current) if (computedModalHeight <= windowHeight) {
52
- modalMobileContainerRef.current.style.display = "flex";
53
- modalMobileContainerRef.current.style.alignItems = "flex-end";
54
- } else {
55
- modalMobileContainerRef.current?.style?.removeProperty("display");
56
- modalMobileContainerRef.current?.style?.removeProperty("align-items");
51
+ if (modalMobileContainerRef?.current) {
52
+ if (computedModalHeight <= windowHeight) {
53
+ modalMobileContainerRef.current.style.display = "flex";
54
+ modalMobileContainerRef.current.style.alignItems = "flex-end";
55
+ } else {
56
+ modalMobileContainerRef.current?.style?.removeProperty("display");
57
+ modalMobileContainerRef.current?.style?.removeProperty("align-items");
58
+ }
57
59
  }
58
60
  }
59
61
  }, [
@@ -1 +1 @@
1
- {"version":3,"file":"useMobileModal.js","names":[],"sources":["../../../../../../src/Atomic/UI/Modal/partials/useMobileModal.tsx"],"sourcesContent":["import type { MutableRefObject, ReactNode } from 'react';\nimport { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';\n\nimport useIsMobile from '../../../../Functions/useIsMobile/useIsMobile';\n\ntype ScrollDirection = 'up' | 'down';\n\ninterface ModalsLogic {\n IS_HEADER_HIDDEN: boolean;\n IS_HEADER_STICKY: boolean;\n IS_FOOTER_HIDDEN: boolean;\n IS_FOOTER_STICKY: boolean;\n}\n\ninterface UseMobileModalProps {\n modalRef?: React.RefObject<HTMLDivElement>;\n withMobileLogic?: boolean;\n withFixedFooter?: boolean;\n isOpen?: boolean;\n}\n\ninterface UseMobileModalReturn {\n modalMobileContainerRef: MutableRefObject<HTMLDivElement | null>;\n modalMobileHeaderRef: MutableRefObject<HTMLDivElement | null>;\n modalMobileBodyRef: MutableRefObject<HTMLDivElement | null>;\n modalMobileFooterRef: MutableRefObject<HTMLDivElement | null>;\n MODALS_LOGIC: ModalsLogic;\n SCROLL_DIRECTION: { UP: ScrollDirection; DOWN: ScrollDirection };\n scrollTop: number;\n scrollHeight: number;\n renderModal: (modal: ReactNode) => ReactNode;\n isMobile: boolean;\n}\n\nconst SCROLL_DIRECTION = {\n UP: 'up' as ScrollDirection,\n DOWN: 'down' as ScrollDirection,\n};\n\nexport default function useMobileModal({\n modalRef,\n withMobileLogic = false,\n withFixedFooter = false,\n isOpen = false,\n}: UseMobileModalProps): UseMobileModalReturn {\n const modalMobileContainerRef = useRef<HTMLDivElement>(null);\n const modalMobileHeaderRef = useRef<HTMLDivElement>(null);\n const modalMobileFooterRef = useRef<HTMLDivElement>(null);\n const modalMobileBodyRef = useRef<HTMLDivElement>(null);\n\n const { isMobile } = useIsMobile();\n\n const [modalHeight, setModalHeight] = useState(0);\n const [modalsLogic, setModalsLogic] = useState<ModalsLogic>({\n IS_HEADER_HIDDEN: false,\n IS_HEADER_STICKY: false,\n IS_FOOTER_HIDDEN: false,\n IS_FOOTER_STICKY: withFixedFooter,\n });\n const [modalsLogicProps, setModalsLogicProps] = useState({\n headerHeight: 0,\n footerHeight: 0,\n });\n\n const [scrollDirection, setScrollDirection] = useState(SCROLL_DIRECTION.UP);\n const [scrollTopPrev, setScrollTopPrev] = useState(0);\n const [scrollTop, setScrollTop] = useState(0);\n const [scrollHeight, setScrollHeight] = useState(1);\n const [, setContainerScrollHeight] = useState(1);\n\n /* MODALS LOGIC | BEGIN */\n // Count ScrollTop\n useLayoutEffect(() => {\n const el = modalMobileContainerRef?.current;\n if (!el) return undefined;\n /*\n * ? Именованный хендлер + cleanup обязательны: раньше на каждый прогон эффекта\n * ? вешалась НОВАЯ анонимная подписка без снятия — дубли обработчиков скролла\n * ? и ретейн замыканий после анмаунта (вклад в listener-утечку adminka 2026-07).\n */\n const handleContainerScroll = (): void => {\n setScrollTop((scrollTop) => {\n if (scrollTop !== el.scrollTop) setScrollTopPrev(scrollTop);\n return el.scrollTop;\n });\n };\n el.addEventListener('scroll', handleContainerScroll);\n return () => el.removeEventListener('scroll', handleContainerScroll);\n }, [modalMobileContainerRef?.current]);\n // Count ScrollDirection\n useEffect(() => {\n setScrollDirection(prevScrollDirection =>\n scrollTop < scrollTopPrev\n ? SCROLL_DIRECTION.UP\n : scrollTop > scrollTopPrev\n ? SCROLL_DIRECTION.DOWN\n : prevScrollDirection,\n );\n }, [scrollTop, scrollTopPrev]);\n // Dynamic Modal Positioning\n useLayoutEffect(() => {\n if (isOpen) {\n const modalStyle = modalRef?.current\n ? modalRef?.current.style\n || window.getComputedStyle(modalRef?.current)\n : {} as CSSStyleDeclaration;\n const computedModalHeight = modalRef?.current\n ? modalHeight + Number.parseFloat(modalStyle?.marginTop || '0')\n : 0;\n const windowHeight\n = document.documentElement.clientHeight\n || window.screen.availHeight\n || window.screen.height;\n if (modalMobileContainerRef?.current) {\n if (computedModalHeight <= windowHeight) {\n modalMobileContainerRef.current.style.display = 'flex';\n modalMobileContainerRef.current.style.alignItems = 'flex-end';\n }\n else {\n modalMobileContainerRef.current?.style?.removeProperty('display');\n modalMobileContainerRef.current?.style?.removeProperty('align-items');\n }\n }\n }\n }, [modalsLogicProps, isOpen, isMobile, modalHeight]);\n\n // Calculating\n useLayoutEffect(() => {\n if (isMobile && isOpen) {\n const newModalHeight = modalRef?.current?.getBoundingClientRect()?.height;\n if (newModalHeight && modalHeight !== newModalHeight) {\n setModalHeight(newModalHeight);\n }\n }\n });\n useEffect(() => {\n if (isMobile && withMobileLogic) {\n const { footerHeight, headerHeight } = modalsLogicProps;\n setModalsLogic(prevStickyLogic => ({\n IS_HEADER_HIDDEN:\n scrollDirection === SCROLL_DIRECTION.DOWN || scrollTop === 0,\n IS_HEADER_STICKY:\n scrollDirection === SCROLL_DIRECTION.UP\n && scrollTop !== 0\n && (scrollTop >= headerHeight || prevStickyLogic.IS_HEADER_STICKY),\n IS_FOOTER_HIDDEN:\n !withFixedFooter\n && (scrollDirection === SCROLL_DIRECTION.UP\n || scrollHeight === Math.round(scrollTop)),\n IS_FOOTER_STICKY:\n (withFixedFooter && scrollHeight > 1)\n || (scrollDirection === SCROLL_DIRECTION.DOWN\n && (scrollHeight - Math.round(scrollTop) >= footerHeight\n || prevStickyLogic.IS_FOOTER_STICKY)),\n }));\n }\n }, [\n scrollTop,\n scrollHeight,\n isMobile,\n withMobileLogic,\n scrollDirection,\n modalsLogicProps,\n modalHeight,\n window.innerHeight,\n ]);\n useLayoutEffect(() => {\n if (\n modalMobileHeaderRef?.current?.getBoundingClientRect()?.height\n !== undefined\n ) {\n setModalsLogicProps(state => ({\n ...state,\n headerHeight: modalMobileHeaderRef?.current?.getBoundingClientRect()?.height ?? 0,\n }));\n }\n }, [modalMobileHeaderRef?.current?.getBoundingClientRect()?.height]);\n useLayoutEffect(() => {\n if (\n modalMobileFooterRef?.current?.getBoundingClientRect()?.height\n !== undefined\n ) {\n setModalsLogicProps(state => ({\n ...state,\n footerHeight: modalMobileFooterRef?.current?.getBoundingClientRect()?.height ?? 0,\n }));\n }\n }, [modalMobileFooterRef?.current?.getBoundingClientRect()?.height]);\n useEffect(() => {\n if (modalMobileContainerRef?.current) {\n setContainerScrollHeight(modalMobileContainerRef?.current?.scrollHeight);\n setScrollHeight(\n modalMobileContainerRef?.current?.scrollHeight - window.innerHeight,\n );\n }\n }, [scrollTop, modalMobileContainerRef?.current, window.innerHeight]);\n useEffect(() => {\n // ? Cleanup обязателен: анонимная resize-подписка на window жила после анмаунта\n // ? модалки навсегда (по подписке на каждый показ модалки).\n const handleWindowResize = (): void => {\n setContainerScrollHeight((containerScrollHeight) => {\n setScrollHeight(containerScrollHeight - window.innerHeight);\n return containerScrollHeight;\n });\n };\n window.addEventListener('resize', handleWindowResize);\n return () => window.removeEventListener('resize', handleWindowResize);\n }, []);\n /* MODALS LOGIC | END */\n\n const renderModal = useCallback(\n (modal: ReactNode): ReactNode => {\n if (!isMobile || !withMobileLogic) return modal;\n\n return (\n <div className=\"modal-mobile-container\" ref={modalMobileContainerRef}>\n {modal}\n </div>\n );\n },\n [isMobile, withMobileLogic],\n );\n\n return {\n modalMobileContainerRef,\n modalMobileHeaderRef,\n modalMobileBodyRef,\n modalMobileFooterRef,\n MODALS_LOGIC: modalsLogic,\n SCROLL_DIRECTION,\n scrollTop,\n scrollHeight,\n renderModal,\n isMobile,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useMobileModal.js","names":[],"sources":["../../../../../../src/Atomic/UI/Modal/partials/useMobileModal.tsx"],"sourcesContent":["import type { MutableRefObject, ReactNode } from 'react';\nimport { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';\n\nimport useIsMobile from '../../../../Functions/useIsMobile/useIsMobile';\n\ntype ScrollDirection = 'up' | 'down';\n\ninterface ModalsLogic {\n IS_HEADER_HIDDEN: boolean;\n IS_HEADER_STICKY: boolean;\n IS_FOOTER_HIDDEN: boolean;\n IS_FOOTER_STICKY: boolean;\n}\n\ninterface UseMobileModalProps {\n modalRef?: React.RefObject<HTMLDivElement>;\n withMobileLogic?: boolean;\n withFixedFooter?: boolean;\n isOpen?: boolean;\n}\n\ninterface UseMobileModalReturn {\n modalMobileContainerRef: MutableRefObject<HTMLDivElement | null>;\n modalMobileHeaderRef: MutableRefObject<HTMLDivElement | null>;\n modalMobileBodyRef: MutableRefObject<HTMLDivElement | null>;\n modalMobileFooterRef: MutableRefObject<HTMLDivElement | null>;\n MODALS_LOGIC: ModalsLogic;\n SCROLL_DIRECTION: { UP: ScrollDirection; DOWN: ScrollDirection };\n scrollTop: number;\n scrollHeight: number;\n renderModal: (modal: ReactNode) => ReactNode;\n isMobile: boolean;\n}\n\nconst SCROLL_DIRECTION = {\n UP: 'up' as ScrollDirection,\n DOWN: 'down' as ScrollDirection,\n};\n\nexport default function useMobileModal({\n modalRef,\n withMobileLogic = false,\n withFixedFooter = false,\n isOpen = false,\n}: UseMobileModalProps): UseMobileModalReturn {\n const modalMobileContainerRef = useRef<HTMLDivElement>(null);\n const modalMobileHeaderRef = useRef<HTMLDivElement>(null);\n const modalMobileFooterRef = useRef<HTMLDivElement>(null);\n const modalMobileBodyRef = useRef<HTMLDivElement>(null);\n\n const { isMobile } = useIsMobile();\n\n const [modalHeight, setModalHeight] = useState(0);\n const [modalsLogic, setModalsLogic] = useState<ModalsLogic>({\n IS_HEADER_HIDDEN: false,\n IS_HEADER_STICKY: false,\n IS_FOOTER_HIDDEN: false,\n IS_FOOTER_STICKY: withFixedFooter,\n });\n const [modalsLogicProps, setModalsLogicProps] = useState({\n headerHeight: 0,\n footerHeight: 0,\n });\n\n const [scrollDirection, setScrollDirection] = useState(SCROLL_DIRECTION.UP);\n const [scrollTopPrev, setScrollTopPrev] = useState(0);\n const [scrollTop, setScrollTop] = useState(0);\n const [scrollHeight, setScrollHeight] = useState(1);\n const [, setContainerScrollHeight] = useState(1);\n\n /* MODALS LOGIC | BEGIN */\n // Count ScrollTop\n useLayoutEffect(() => {\n const el = modalMobileContainerRef?.current;\n if (!el) return undefined;\n /*\n * ? Именованный хендлер + cleanup обязательны: раньше на каждый прогон эффекта\n * ? вешалась НОВАЯ анонимная подписка без снятия — дубли обработчиков скролла\n * ? и ретейн замыканий после анмаунта (вклад в listener-утечку adminka 2026-07).\n */\n const handleContainerScroll = (): void => {\n setScrollTop((scrollTop) => {\n if (scrollTop !== el.scrollTop) setScrollTopPrev(scrollTop);\n return el.scrollTop;\n });\n };\n el.addEventListener('scroll', handleContainerScroll);\n return () => el.removeEventListener('scroll', handleContainerScroll);\n }, [modalMobileContainerRef?.current]);\n // Count ScrollDirection\n useEffect(() => {\n setScrollDirection(prevScrollDirection =>\n scrollTop < scrollTopPrev\n ? SCROLL_DIRECTION.UP\n : scrollTop > scrollTopPrev\n ? SCROLL_DIRECTION.DOWN\n : prevScrollDirection,\n );\n }, [scrollTop, scrollTopPrev]);\n // Dynamic Modal Positioning\n useLayoutEffect(() => {\n if (isOpen) {\n const modalStyle = modalRef?.current\n ? modalRef?.current.style\n || window.getComputedStyle(modalRef?.current)\n : {} as CSSStyleDeclaration;\n const computedModalHeight = modalRef?.current\n ? modalHeight + Number.parseFloat(modalStyle?.marginTop || '0')\n : 0;\n const windowHeight\n = document.documentElement.clientHeight\n || window.screen.availHeight\n || window.screen.height;\n if (modalMobileContainerRef?.current) {\n if (computedModalHeight <= windowHeight) {\n modalMobileContainerRef.current.style.display = 'flex';\n modalMobileContainerRef.current.style.alignItems = 'flex-end';\n }\n else {\n modalMobileContainerRef.current?.style?.removeProperty('display');\n modalMobileContainerRef.current?.style?.removeProperty('align-items');\n }\n }\n }\n }, [modalsLogicProps, isOpen, isMobile, modalHeight]);\n\n // Calculating\n useLayoutEffect(() => {\n if (isMobile && isOpen) {\n const newModalHeight = modalRef?.current?.getBoundingClientRect()?.height;\n if (newModalHeight && modalHeight !== newModalHeight) {\n setModalHeight(newModalHeight);\n }\n }\n });\n useEffect(() => {\n if (isMobile && withMobileLogic) {\n const { footerHeight, headerHeight } = modalsLogicProps;\n setModalsLogic(prevStickyLogic => ({\n IS_HEADER_HIDDEN:\n scrollDirection === SCROLL_DIRECTION.DOWN || scrollTop === 0,\n IS_HEADER_STICKY:\n scrollDirection === SCROLL_DIRECTION.UP\n && scrollTop !== 0\n && (scrollTop >= headerHeight || prevStickyLogic.IS_HEADER_STICKY),\n IS_FOOTER_HIDDEN:\n !withFixedFooter\n && (scrollDirection === SCROLL_DIRECTION.UP\n || scrollHeight === Math.round(scrollTop)),\n IS_FOOTER_STICKY:\n (withFixedFooter && scrollHeight > 1)\n || (scrollDirection === SCROLL_DIRECTION.DOWN\n && (scrollHeight - Math.round(scrollTop) >= footerHeight\n || prevStickyLogic.IS_FOOTER_STICKY)),\n }));\n }\n }, [\n scrollTop,\n scrollHeight,\n isMobile,\n withMobileLogic,\n scrollDirection,\n modalsLogicProps,\n modalHeight,\n window.innerHeight,\n ]);\n useLayoutEffect(() => {\n if (\n modalMobileHeaderRef?.current?.getBoundingClientRect()?.height\n !== undefined\n ) {\n setModalsLogicProps(state => ({\n ...state,\n headerHeight: modalMobileHeaderRef?.current?.getBoundingClientRect()?.height ?? 0,\n }));\n }\n }, [modalMobileHeaderRef?.current?.getBoundingClientRect()?.height]);\n useLayoutEffect(() => {\n if (\n modalMobileFooterRef?.current?.getBoundingClientRect()?.height\n !== undefined\n ) {\n setModalsLogicProps(state => ({\n ...state,\n footerHeight: modalMobileFooterRef?.current?.getBoundingClientRect()?.height ?? 0,\n }));\n }\n }, [modalMobileFooterRef?.current?.getBoundingClientRect()?.height]);\n useEffect(() => {\n if (modalMobileContainerRef?.current) {\n setContainerScrollHeight(modalMobileContainerRef?.current?.scrollHeight);\n setScrollHeight(\n modalMobileContainerRef?.current?.scrollHeight - window.innerHeight,\n );\n }\n }, [scrollTop, modalMobileContainerRef?.current, window.innerHeight]);\n useEffect(() => {\n // ? Cleanup обязателен: анонимная resize-подписка на window жила после анмаунта\n // ? модалки навсегда (по подписке на каждый показ модалки).\n const handleWindowResize = (): void => {\n setContainerScrollHeight((containerScrollHeight) => {\n setScrollHeight(containerScrollHeight - window.innerHeight);\n return containerScrollHeight;\n });\n };\n window.addEventListener('resize', handleWindowResize);\n return () => window.removeEventListener('resize', handleWindowResize);\n }, []);\n /* MODALS LOGIC | END */\n\n const renderModal = useCallback(\n (modal: ReactNode): ReactNode => {\n if (!isMobile || !withMobileLogic) return modal;\n\n return (\n <div className=\"modal-mobile-container\" ref={modalMobileContainerRef}>\n {modal}\n </div>\n );\n },\n [isMobile, withMobileLogic],\n );\n\n return {\n modalMobileContainerRef,\n modalMobileHeaderRef,\n modalMobileBodyRef,\n modalMobileFooterRef,\n MODALS_LOGIC: modalsLogic,\n SCROLL_DIRECTION,\n scrollTop,\n scrollHeight,\n renderModal,\n isMobile,\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"NavLine.js","names":[],"sources":["../../../../../src/Atomic/UI/NavLine/NavLine.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { HTMLElementOrAnchor, RefType } from '../../../types/base.types';\nimport type { INavLineItem, INavLineProps } from './NavLine.interface';\nimport cn from 'classnames';\nimport React, { createRef, useCallback, useEffect, useRef, useState } from 'react';\n\nimport * as Icons from 'react-feather';\n\nimport { NavLink } from 'react-router-dom';\n\nimport { KEYBOARD_KEY_CODES } from '../../../Constants/index.constants';\n\nimport './NavLine.scss';\n\nconst CN = 'nav-line';\n\n/**\n * Проверяет и нормализует ref\n * @param ref - React ref объект или функция обратного вызова\n * @returns Нормализованный ref или null\n */\nfunction checkedRef<T extends HTMLElementOrAnchor = HTMLElement>(ref: RefType<T>): RefType<T> {\n if (!ref) return null;\n return typeof ref === 'function' ? (node: T) => ref(node) : ref;\n}\n\nconst NavLine: React.FC<INavLineProps> = ({\n root = '',\n activeTab,\n variant,\n onChange,\n className,\n items,\n children,\n isLocal = false,\n mode,\n isNavigateByKeys,\n isTabLoading,\n scrollMode = false,\n testId = CN,\n}) => {\n const [navLineItems, setNavLineItems] = useState<\n Array<INavLineItem & { ref: React.RefObject<HTMLElement> }>\n >([]);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const wrapperInnerRef = useRef<HTMLDivElement>(null);\n const [showScrollButtons, setShowScrollButtons] = useState(false);\n const [canScrollLeft, setCanScrollLeft] = useState(false);\n const [canScrollRight, setCanScrollRight] = useState(false);\n const [isScrollBlocked, setIsScrollBlocked] = useState(false);\n\n const checkScroll = useCallback(() => {\n const inner = wrapperInnerRef.current;\n if (!inner) return;\n\n const hasOverflow = inner.scrollWidth > inner.clientWidth;\n const canScrollLeft = inner.scrollLeft > 0;\n const canScrollRight = inner.scrollLeft < inner.scrollWidth - inner.clientWidth;\n\n setShowScrollButtons(hasOverflow);\n setCanScrollLeft(canScrollLeft);\n setCanScrollRight(canScrollRight);\n }, []);\n\n const scroll = useCallback(\n (direction: 'left' | 'right') => {\n if (isScrollBlocked || !wrapperInnerRef.current) return;\n\n setIsScrollBlocked(true);\n const scrollAmount = 100;\n const offset = direction === 'left' ? -scrollAmount : scrollAmount;\n\n try {\n wrapperInnerRef.current.scrollBy({\n left: offset,\n behavior: 'smooth',\n });\n }\n catch (error) {\n console.error('scrollBy is not supported', error);\n // Fallback для браузеров, не поддерживающих scrollBy\n if (wrapperInnerRef.current) {\n wrapperInnerRef.current.scrollLeft += offset;\n }\n }\n\n setTimeout(() => {\n setIsScrollBlocked(false);\n checkScroll();\n }, 300);\n },\n [isScrollBlocked, checkScroll],\n );\n\n const handleWheel = useCallback(\n (e: WheelEvent) => {\n if (!scrollMode) return;\n e.preventDefault();\n\n if (e.deltaY > 0) {\n scroll('right');\n }\n else {\n scroll('left');\n }\n },\n [scroll, scrollMode],\n );\n\n const onTabChange = useCallback(\n (item: INavLineItem) => {\n if (!item.disabled && !(mode === 'create' && item.tabId !== 'general')) {\n onChange(item.tabId);\n }\n },\n [mode, onChange],\n );\n\n const navigateByKeys = useCallback(\n (event: KeyboardEvent) => {\n if (event.repeat) return;\n\n const activeTabIndex = items.findIndex(tab => tab.tabId === activeTab);\n const nextTabID = items[activeTabIndex + 1]?.tabId;\n const prevTabID = items[activeTabIndex - 1]?.tabId;\n\n if (event.keyCode === KEYBOARD_KEY_CODES.ARROW_RIGHT && nextTabID) {\n onChange(nextTabID);\n }\n else if (event.keyCode === KEYBOARD_KEY_CODES.ARROW_LEFT && prevTabID) {\n onChange(prevTabID);\n }\n },\n [activeTab, items, onChange],\n );\n\n // Инициализация табов с ref\n useEffect(() => {\n setNavLineItems(\n items.map(item => ({\n ...item,\n ref: createRef<HTMLElement>(),\n })),\n );\n }, [items]);\n\n // Обработка клавиатурной навигации\n useEffect(() => {\n if (isNavigateByKeys && !isTabLoading) {\n document.addEventListener('keydown', navigateByKeys);\n }\n\n return () => document.removeEventListener('keydown', navigateByKeys);\n }, [isNavigateByKeys, isTabLoading, navigateByKeys]);\n\n // Настройка скролла\n useEffect(() => {\n if (!scrollMode) return;\n\n const inner = wrapperInnerRef.current;\n if (!inner) return;\n\n const resizeObserver = new ResizeObserver(checkScroll);\n resizeObserver.observe(inner);\n\n inner.addEventListener('scroll', checkScroll);\n inner.addEventListener('wheel', handleWheel, { passive: false });\n\n checkScroll();\n\n return () => {\n resizeObserver.disconnect();\n inner.removeEventListener('scroll', checkScroll);\n inner.removeEventListener('wheel', handleWheel);\n };\n }, [scrollMode, checkScroll, handleWheel]);\n\n const renderNavItem = (item: INavLineItem & { ref: React.RefObject<HTMLElement> }): ReactNode => {\n const Icon = item.icon ? Icons[item.icon as keyof typeof Icons] : null;\n const isDisabled = item.disabled || (mode === 'create' && item.tabId !== 'general');\n\n const commonProps = {\n 'title': item.title,\n 'className': cn(\n { 'nav-line__item': !variant },\n { 'nav-line--simple__item': variant === 'simple' },\n { active: activeTab === item.tabId },\n { disabled: isDisabled },\n { 'nav-line__item--hidden': item.isHidden },\n ),\n 'role': 'tab',\n 'aria-selected': activeTab === item.tabId,\n 'aria-disabled': isDisabled,\n 'tabIndex': isDisabled ? -1 : 0,\n };\n\n const content = (\n <div className=\"nav-line__content\">\n {Icon && (\n <div className=\"nav-line__item--icon\" aria-hidden=\"true\">\n <Icon />\n </div>\n )}\n <span className={cn({ 'nav-line__item--label': variant !== 'simple' })}>{item.label}</span>\n {item.count !== undefined && (\n <span className=\"nav-line-count\" aria-label={`${item.count} items`}>\n (\n {item.count}\n )\n </span>\n )}\n </div>\n );\n if (isLocal) {\n return (\n <span\n key={`tab__${item.tabId}`}\n {...commonProps}\n ref={checkedRef(item.ref)}\n onClick={() => !isDisabled && onTabChange(item)}\n onKeyPress={(e: React.KeyboardEvent) => {\n if (!isDisabled && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n onTabChange(item);\n }\n }}\n >\n {content}\n </span>\n );\n }\n\n return (\n <NavLink\n key={`tab__${item.tabId}`}\n {...commonProps}\n to={`${root}${item?.linkChapter || item.tabId}/`}\n onClick={(e) => {\n if (isDisabled) {\n e.preventDefault();\n }\n }}\n >\n {content}\n </NavLink>\n );\n };\n\n return (\n <div className=\"nav-line-wrapper\">\n <div\n data-testid={testId}\n className={cn(\n { [CN]: !variant },\n { [`${CN}--simple`]: variant === 'simple' },\n { [`${CN}--scroll-mode`]: scrollMode },\n className,\n )}\n ref={wrapperRef}\n >\n {scrollMode && showScrollButtons && (\n <button\n type=\"button\"\n data-testid=\"nav-line-scroll-prev\"\n className=\"nav-line--simple__arrow nav-line--simple__arrow--prev\"\n onClick={() => scroll('left')}\n aria-label=\"Scroll previous\"\n disabled={!canScrollLeft}\n >\n <Icons.ChevronLeft />\n </button>\n )}\n\n <div\n ref={wrapperInnerRef}\n className={cn({ 'nav-line__inner': !variant }, { 'nav-line--simple__inner': variant === 'simple' })}\n role=\"tablist\"\n aria-orientation=\"horizontal\"\n >\n {navLineItems.map(renderNavItem)}\n </div>\n\n {scrollMode && showScrollButtons && (\n <button\n type=\"button\"\n data-testid=\"nav-line-scroll-next\"\n className=\"nav-line--simple__arrow nav-line--simple__arrow--next\"\n onClick={() => scroll('right')}\n aria-label=\"Scroll next\"\n disabled={!canScrollRight}\n >\n <Icons.ChevronRight />\n </button>\n )}\n\n {children && (\n <div className=\"nav-line__body\" role=\"tabpanel\">\n {children}\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default NavLine;\n"],"mappings":"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"}
1
+ {"version":3,"file":"NavLine.js","names":[],"sources":["../../../../../src/Atomic/UI/NavLine/NavLine.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { HTMLElementOrAnchor, RefType } from '../../../types/base.types';\nimport type { INavLineItem, INavLineProps } from './NavLine.interface';\nimport cn from 'classnames';\nimport React, { createRef, useCallback, useEffect, useRef, useState } from 'react';\n\nimport * as Icons from 'react-feather';\n\nimport { NavLink } from 'react-router-dom';\n\nimport { KEYBOARD_KEY_CODES } from '../../../Constants/index.constants';\n\nimport './NavLine.scss';\n\nconst CN = 'nav-line';\n\n/**\n * Проверяет и нормализует ref\n * @param ref - React ref объект или функция обратного вызова\n * @returns Нормализованный ref или null\n */\nfunction checkedRef<T extends HTMLElementOrAnchor = HTMLElement>(ref: RefType<T>): RefType<T> {\n if (!ref) return null;\n return typeof ref === 'function' ? (node: T) => ref(node) : ref;\n}\n\nconst NavLine: React.FC<INavLineProps> = ({\n root = '',\n activeTab,\n variant,\n onChange,\n className,\n items,\n children,\n isLocal = false,\n mode,\n isNavigateByKeys,\n isTabLoading,\n scrollMode = false,\n testId = CN,\n}) => {\n const [navLineItems, setNavLineItems] = useState<\n Array<INavLineItem & { ref: React.RefObject<HTMLElement> }>\n >([]);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const wrapperInnerRef = useRef<HTMLDivElement>(null);\n const [showScrollButtons, setShowScrollButtons] = useState(false);\n const [canScrollLeft, setCanScrollLeft] = useState(false);\n const [canScrollRight, setCanScrollRight] = useState(false);\n const [isScrollBlocked, setIsScrollBlocked] = useState(false);\n\n const checkScroll = useCallback(() => {\n const inner = wrapperInnerRef.current;\n if (!inner) return;\n\n const hasOverflow = inner.scrollWidth > inner.clientWidth;\n const canScrollLeft = inner.scrollLeft > 0;\n const canScrollRight = inner.scrollLeft < inner.scrollWidth - inner.clientWidth;\n\n setShowScrollButtons(hasOverflow);\n setCanScrollLeft(canScrollLeft);\n setCanScrollRight(canScrollRight);\n }, []);\n\n const scroll = useCallback(\n (direction: 'left' | 'right') => {\n if (isScrollBlocked || !wrapperInnerRef.current) return;\n\n setIsScrollBlocked(true);\n const scrollAmount = 100;\n const offset = direction === 'left' ? -scrollAmount : scrollAmount;\n\n try {\n wrapperInnerRef.current.scrollBy({\n left: offset,\n behavior: 'smooth',\n });\n }\n catch (error) {\n console.error('scrollBy is not supported', error);\n // Fallback для браузеров, не поддерживающих scrollBy\n if (wrapperInnerRef.current) {\n wrapperInnerRef.current.scrollLeft += offset;\n }\n }\n\n setTimeout(() => {\n setIsScrollBlocked(false);\n checkScroll();\n }, 300);\n },\n [isScrollBlocked, checkScroll],\n );\n\n const handleWheel = useCallback(\n (e: WheelEvent) => {\n if (!scrollMode) return;\n e.preventDefault();\n\n if (e.deltaY > 0) {\n scroll('right');\n }\n else {\n scroll('left');\n }\n },\n [scroll, scrollMode],\n );\n\n const onTabChange = useCallback(\n (item: INavLineItem) => {\n if (!item.disabled && !(mode === 'create' && item.tabId !== 'general')) {\n onChange(item.tabId);\n }\n },\n [mode, onChange],\n );\n\n const navigateByKeys = useCallback(\n (event: KeyboardEvent) => {\n if (event.repeat) return;\n\n const activeTabIndex = items.findIndex(tab => tab.tabId === activeTab);\n const nextTabID = items[activeTabIndex + 1]?.tabId;\n const prevTabID = items[activeTabIndex - 1]?.tabId;\n\n if (event.keyCode === KEYBOARD_KEY_CODES.ARROW_RIGHT && nextTabID) {\n onChange(nextTabID);\n }\n else if (event.keyCode === KEYBOARD_KEY_CODES.ARROW_LEFT && prevTabID) {\n onChange(prevTabID);\n }\n },\n [activeTab, items, onChange],\n );\n\n // Инициализация табов с ref\n useEffect(() => {\n setNavLineItems(\n items.map(item => ({\n ...item,\n ref: createRef<HTMLElement>(),\n })),\n );\n }, [items]);\n\n // Обработка клавиатурной навигации\n useEffect(() => {\n if (isNavigateByKeys && !isTabLoading) {\n document.addEventListener('keydown', navigateByKeys);\n }\n\n return () => document.removeEventListener('keydown', navigateByKeys);\n }, [isNavigateByKeys, isTabLoading, navigateByKeys]);\n\n // Настройка скролла\n useEffect(() => {\n if (!scrollMode) return;\n\n const inner = wrapperInnerRef.current;\n if (!inner) return;\n\n const resizeObserver = new ResizeObserver(checkScroll);\n resizeObserver.observe(inner);\n\n inner.addEventListener('scroll', checkScroll);\n inner.addEventListener('wheel', handleWheel, { passive: false });\n\n checkScroll();\n\n return () => {\n resizeObserver.disconnect();\n inner.removeEventListener('scroll', checkScroll);\n inner.removeEventListener('wheel', handleWheel);\n };\n }, [scrollMode, checkScroll, handleWheel]);\n\n const renderNavItem = (item: INavLineItem & { ref: React.RefObject<HTMLElement> }): ReactNode => {\n const Icon = item.icon ? Icons[item.icon as keyof typeof Icons] : null;\n const isDisabled = item.disabled || (mode === 'create' && item.tabId !== 'general');\n\n const commonProps = {\n 'title': item.title,\n 'className': cn(\n { 'nav-line__item': !variant },\n { 'nav-line--simple__item': variant === 'simple' },\n { active: activeTab === item.tabId },\n { disabled: isDisabled },\n { 'nav-line__item--hidden': item.isHidden },\n ),\n 'role': 'tab',\n 'aria-selected': activeTab === item.tabId,\n 'aria-disabled': isDisabled,\n 'tabIndex': isDisabled ? -1 : 0,\n };\n\n const content = (\n <div className=\"nav-line__content\">\n {Icon && (\n <div className=\"nav-line__item--icon\" aria-hidden=\"true\">\n <Icon />\n </div>\n )}\n <span className={cn({ 'nav-line__item--label': variant !== 'simple' })}>{item.label}</span>\n {item.count !== undefined && (\n <span className=\"nav-line-count\" aria-label={`${item.count} items`}>\n (\n {item.count}\n )\n </span>\n )}\n </div>\n );\n if (isLocal) {\n return (\n <span\n key={`tab__${item.tabId}`}\n {...commonProps}\n ref={checkedRef(item.ref)}\n onClick={() => !isDisabled && onTabChange(item)}\n onKeyPress={(e: React.KeyboardEvent) => {\n if (!isDisabled && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n onTabChange(item);\n }\n }}\n >\n {content}\n </span>\n );\n }\n\n return (\n <NavLink\n key={`tab__${item.tabId}`}\n {...commonProps}\n to={`${root}${item?.linkChapter || item.tabId}/`}\n onClick={(e) => {\n if (isDisabled) {\n e.preventDefault();\n }\n }}\n >\n {content}\n </NavLink>\n );\n };\n\n return (\n <div className=\"nav-line-wrapper\">\n <div\n data-testid={testId}\n className={cn(\n { [CN]: !variant },\n { [`${CN}--simple`]: variant === 'simple' },\n { [`${CN}--scroll-mode`]: scrollMode },\n className,\n )}\n ref={wrapperRef}\n >\n {scrollMode && showScrollButtons && (\n <button\n type=\"button\"\n data-testid=\"nav-line-scroll-prev\"\n className=\"nav-line--simple__arrow nav-line--simple__arrow--prev\"\n onClick={() => scroll('left')}\n aria-label=\"Scroll previous\"\n disabled={!canScrollLeft}\n >\n <Icons.ChevronLeft />\n </button>\n )}\n\n <div\n ref={wrapperInnerRef}\n className={cn({ 'nav-line__inner': !variant }, { 'nav-line--simple__inner': variant === 'simple' })}\n role=\"tablist\"\n aria-orientation=\"horizontal\"\n >\n {navLineItems.map(renderNavItem)}\n </div>\n\n {scrollMode && showScrollButtons && (\n <button\n type=\"button\"\n data-testid=\"nav-line-scroll-next\"\n className=\"nav-line--simple__arrow nav-line--simple__arrow--next\"\n onClick={() => scroll('right')}\n aria-label=\"Scroll next\"\n disabled={!canScrollRight}\n >\n <Icons.ChevronRight />\n </button>\n )}\n\n {children && (\n <div className=\"nav-line__body\" role=\"tabpanel\">\n {children}\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default NavLine;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PageTitle.js","names":[],"sources":["../../../../../src/Atomic/UI/PageTitle/PageTitle.tsx"],"sourcesContent":["import type { IPageTitleProps } from './PageTitle.interface';\nimport cn from 'classnames';\nimport React from 'react';\n\nimport { Home } from 'react-feather';\n\nimport './PageTitle.scss';\n\nconst RC = 'page-title';\n\nconst PageTitle: React.FC<IPageTitleProps> = ({ title, pages, children, testId = RC }) => (\n <div data-testid={testId} className={RC} role=\"region\" aria-label={title}>\n <div className={`${RC}__wrap`}>\n <h1 className={`${RC}__title`}>{title}</h1>\n {pages.length > 0 && (\n <nav className={`${RC}__pages`} aria-label=\"Breadcrumb\">\n <ol className={`${RC}__list`}>\n <li>\n <a className={`${RC}__link`} href=\"/\" aria-label=\"Home page\">\n <Home aria-hidden=\"true\" />\n </a>\n </li>\n\n {pages.map(({ name, path }, index) => (\n <li key={path}>\n <span className={`${RC}__delimiter`} aria-hidden=\"true\">\n /\n </span>\n {pages.length - 1 === index\n ? (\n <span className={cn(`${RC}__link`, `${RC}__link_last`)} aria-current=\"page\">\n {name}\n </span>\n )\n : (\n <a className={`${RC}__link`} href={path}>\n {name}\n </a>\n )}\n </li>\n ))}\n </ol>\n </nav>\n )}\n </div>\n {children}\n </div>\n);\n\nexport default PageTitle;\n"],"mappings":";;;;;;AAQA,IAAM,KAAK;AAEX,IAAM,aAAwC,EAAE,OAAO,OAAO,UAAU,SAAS,SAC/E,qBAAC,OAAD;CAAK,eAAa;CAAQ,WAAW;CAAI,MAAK;CAAS,cAAY;WAAnE,CACE,qBAAC,OAAD;EAAK,WAAW,GAAG,GAAG;YAAtB,CACE,oBAAC,MAAD;GAAI,WAAW,GAAG,GAAG;aAAW;EAAU,CAAA,GACzC,MAAM,SAAS,KACd,oBAAC,OAAD;GAAK,WAAW,GAAG,GAAG;GAAU,cAAW;aACzC,qBAAC,MAAD;IAAI,WAAW,GAAG,GAAG;cAArB,CACE,oBAAC,MAAD,EAAA,UACE,oBAAC,KAAD;KAAG,WAAW,GAAG,GAAG;KAAS,MAAK;KAAI,cAAW;eAC/C,oBAAC,MAAD,EAAM,eAAY,OAAQ,CAAA;IACzB,CAAA,EACD,CAAA,GAEH,MAAM,KAAK,EAAE,MAAM,QAAQ,UAC1B,qBAAC,MAAD,EAAA,UAAA,CACE,oBAAC,QAAD;KAAM,WAAW,GAAG,GAAG;KAAc,eAAY;eAAO;IAElD,CAAA,GACL,MAAM,SAAS,MAAM,QAEhB,oBAAC,QAAD;KAAM,WAAW,GAAG,GAAG,GAAG,SAAS,GAAG,GAAG,YAAY;KAAG,gBAAa;eAClE;IACG,CAAA,IAGN,oBAAC,KAAD;KAAG,WAAW,GAAG,GAAG;KAAS,MAAM;eAChC;IACA,CAAA,CAEP,EAAA,GAfK,IAeL,CACL,CACC;;EACD,CAAA,CAEJ;KACJ,QACE"}
1
+ {"version":3,"file":"PageTitle.js","names":[],"sources":["../../../../../src/Atomic/UI/PageTitle/PageTitle.tsx"],"sourcesContent":["import type { IPageTitleProps } from './PageTitle.interface';\nimport cn from 'classnames';\nimport React from 'react';\n\nimport { Home } from 'react-feather';\n\nimport './PageTitle.scss';\n\nconst RC = 'page-title';\n\nconst PageTitle: React.FC<IPageTitleProps> = ({ title, pages, children, testId = RC }) => (\n <div data-testid={testId} className={RC} role=\"region\" aria-label={title}>\n <div className={`${RC}__wrap`}>\n <h1 className={`${RC}__title`}>{title}</h1>\n {pages.length > 0 && (\n <nav className={`${RC}__pages`} aria-label=\"Breadcrumb\">\n <ol className={`${RC}__list`}>\n <li>\n <a className={`${RC}__link`} href=\"/\" aria-label=\"Home page\">\n <Home aria-hidden=\"true\" />\n </a>\n </li>\n\n {pages.map(({ name, path }, index) => (\n <li key={path}>\n <span className={`${RC}__delimiter`} aria-hidden=\"true\">\n /\n </span>\n {pages.length - 1 === index\n ? (\n <span className={cn(`${RC}__link`, `${RC}__link_last`)} aria-current=\"page\">\n {name}\n </span>\n )\n : (\n <a className={`${RC}__link`} href={path}>\n {name}\n </a>\n )}\n </li>\n ))}\n </ol>\n </nav>\n )}\n </div>\n {children}\n </div>\n);\n\nexport default PageTitle;\n"],"mappings":";;;;;;AAQA,IAAM,KAAK;AAEX,IAAM,aAAwC,EAAE,OAAO,OAAO,UAAU,SAAS,SAC/E,qBAAC,OAAD;CAAK,eAAa;CAAQ,WAAW;CAAI,MAAK;CAAS,cAAY;CAAnE,UAAA,CACE,qBAAC,OAAD;EAAK,WAAW,GAAG,GAAG;EAAtB,UAAA,CACE,oBAAC,MAAD;GAAI,WAAW,GAAG,GAAG;GAAW,UAAA;EAAU,CAAA,GACzC,MAAM,SAAS,KACd,oBAAC,OAAD;GAAK,WAAW,GAAG,GAAG;GAAU,cAAW;GACzC,UAAA,qBAAC,MAAD;IAAI,WAAW,GAAG,GAAG;IAArB,UAAA,CACE,oBAAC,MAAD,EAAA,UACE,oBAAC,KAAD;KAAG,WAAW,GAAG,GAAG;KAAS,MAAK;KAAI,cAAW;KAC/C,UAAA,oBAAC,MAAD,EAAM,eAAY,OAAQ,CAAA;IACzB,CAAA,EACD,CAAA,GAEH,MAAM,KAAK,EAAE,MAAM,QAAQ,UAC1B,qBAAC,MAAD,EAAA,UAAA,CACE,oBAAC,QAAD;KAAM,WAAW,GAAG,GAAG;KAAc,eAAY;KAAO,UAAA;IAElD,CAAA,GACL,MAAM,SAAS,MAAM,QAEhB,oBAAC,QAAD;KAAM,WAAW,GAAG,GAAG,GAAG,SAAS,GAAG,GAAG,YAAY;KAAG,gBAAa;KAClE,UAAA;IACG,CAAA,IAGN,oBAAC,KAAD;KAAG,WAAW,GAAG,GAAG;KAAS,MAAM;KAChC,UAAA;IACA,CAAA,CAEP,EAAA,GAfK,IAeL,CACL,CACC;;EACD,CAAA,CAEJ;CACJ,CAAA,GAAA,QACE"}
@@ -1 +1 @@
1
- {"version":3,"file":"Price.js","names":[],"sources":["../../../../../src/Atomic/UI/Price/Price.tsx"],"sourcesContent":["import type { IPriceProps } from './Price.interface';\nimport cn from 'classnames';\n\nimport React from 'react';\n\nimport { formatToPriceWithCurrency } from '../../../Functions/fieldValueFormatters';\n\nconst CN = 'price';\n\nconst Price: React.FC<IPriceProps> = ({ value, currencyCode, isSymbolAfter, className, testId = CN }) => {\n if (value === undefined || value === null) return null;\n return (\n <div\n data-testid={testId}\n className={cn(CN, className)}\n role=\"contentinfo\"\n aria-label={`Price: ${formatToPriceWithCurrency(value, currencyCode, isSymbolAfter ? 'after' : 'before')}`}\n >\n {formatToPriceWithCurrency(value, currencyCode, isSymbolAfter ? 'after' : 'before')}\n </div>\n );\n};\n\nexport default Price;\n"],"mappings":";;;;;AAOA,IAAM,KAAK;AAEX,IAAM,SAAgC,EAAE,OAAO,cAAc,eAAe,WAAW,SAAS,SAAS;CACvG,IAAI,UAAU,KAAA,KAAa,UAAU,MAAM,OAAO;CAClD,OACE,oBAAC,OAAD;EACE,eAAa;EACb,WAAW,GAAG,IAAI,SAAS;EAC3B,MAAK;EACL,cAAY,UAAU,0BAA0B,OAAO,cAAc,gBAAgB,UAAU,QAAQ;YAEtG,0BAA0B,OAAO,cAAc,gBAAgB,UAAU,QAAQ;CAC/E,CAAA;AAET"}
1
+ {"version":3,"file":"Price.js","names":[],"sources":["../../../../../src/Atomic/UI/Price/Price.tsx"],"sourcesContent":["import type { IPriceProps } from './Price.interface';\nimport cn from 'classnames';\n\nimport React from 'react';\n\nimport { formatToPriceWithCurrency } from '../../../Functions/fieldValueFormatters';\n\nconst CN = 'price';\n\nconst Price: React.FC<IPriceProps> = ({ value, currencyCode, isSymbolAfter, className, testId = CN }) => {\n if (value === undefined || value === null) return null;\n return (\n <div\n data-testid={testId}\n className={cn(CN, className)}\n role=\"contentinfo\"\n aria-label={`Price: ${formatToPriceWithCurrency(value, currencyCode, isSymbolAfter ? 'after' : 'before')}`}\n >\n {formatToPriceWithCurrency(value, currencyCode, isSymbolAfter ? 'after' : 'before')}\n </div>\n );\n};\n\nexport default Price;\n"],"mappings":";;;;;AAOA,IAAM,KAAK;AAEX,IAAM,SAAgC,EAAE,OAAO,cAAc,eAAe,WAAW,SAAS,SAAS;CACvG,IAAI,UAAU,KAAA,KAAa,UAAU,MAAM,OAAO;CAClD,OACE,oBAAC,OAAD;EACE,eAAa;EACb,WAAW,GAAG,IAAI,SAAS;EAC3B,MAAK;EACL,cAAY,UAAU,0BAA0B,OAAO,cAAc,gBAAgB,UAAU,QAAQ;EAEtG,UAAA,0BAA0B,OAAO,cAAc,gBAAgB,UAAU,QAAQ;CAC/E,CAAA;AAET"}
@@ -1 +1 @@
1
- {"version":3,"file":"PriceRange.js","names":[],"sources":["../../../../../src/Atomic/UI/PriceRange/PriceRange.tsx"],"sourcesContent":["import type { IPriceRangeProps } from './PriceRange.interface';\nimport cn from 'classnames';\n\nimport React from 'react';\n\nimport { formatToPriceWithUSD } from '../../../Functions/fieldValueFormatters';\n\nconst CN = 'price-range';\n\nconst PriceRange: React.FC<IPriceRangeProps> = ({ from, to, mode, testId = CN }) => {\n return (\n <div data-testid={testId} className={cn(CN, 'j4')} role=\"region\" aria-label=\"Price range\">\n {mode === 'simple'\n ? (\n <span aria-live=\"polite\">\n {from}\n {' - '}\n {to}\n </span>\n )\n : (\n <span aria-live=\"polite\">\n {formatToPriceWithUSD(from?.toString())}\n {' - '}\n {formatToPriceWithUSD(to?.toString())}\n </span>\n )}\n </div>\n );\n};\n\nexport default PriceRange;\n"],"mappings":";;;;;AAOA,IAAM,KAAK;AAEX,IAAM,cAA0C,EAAE,MAAM,IAAI,MAAM,SAAS,SAAS;CAClF,OACE,oBAAC,OAAD;EAAK,eAAa;EAAQ,WAAW,GAAG,IAAI,IAAI;EAAG,MAAK;EAAS,cAAW;YACzE,SAAS,WAEJ,qBAAC,QAAD;GAAM,aAAU;aAAhB;IACG;IACA;IACA;GACG;OAGN,qBAAC,QAAD;GAAM,aAAU;aAAhB;IACG,qBAAqB,MAAM,SAAS,CAAC;IACrC;IACA,qBAAqB,IAAI,SAAS,CAAC;GAChC;;CAET,CAAA;AAET"}
1
+ {"version":3,"file":"PriceRange.js","names":[],"sources":["../../../../../src/Atomic/UI/PriceRange/PriceRange.tsx"],"sourcesContent":["import type { IPriceRangeProps } from './PriceRange.interface';\nimport cn from 'classnames';\n\nimport React from 'react';\n\nimport { formatToPriceWithUSD } from '../../../Functions/fieldValueFormatters';\n\nconst CN = 'price-range';\n\nconst PriceRange: React.FC<IPriceRangeProps> = ({ from, to, mode, testId = CN }) => {\n return (\n <div data-testid={testId} className={cn(CN, 'j4')} role=\"region\" aria-label=\"Price range\">\n {mode === 'simple'\n ? (\n <span aria-live=\"polite\">\n {from}\n {' - '}\n {to}\n </span>\n )\n : (\n <span aria-live=\"polite\">\n {formatToPriceWithUSD(from?.toString())}\n {' - '}\n {formatToPriceWithUSD(to?.toString())}\n </span>\n )}\n </div>\n );\n};\n\nexport default PriceRange;\n"],"mappings":";;;;;AAOA,IAAM,KAAK;AAEX,IAAM,cAA0C,EAAE,MAAM,IAAI,MAAM,SAAS,SAAS;CAClF,OACE,oBAAC,OAAD;EAAK,eAAa;EAAQ,WAAW,GAAG,IAAI,IAAI;EAAG,MAAK;EAAS,cAAW;EACzE,UAAA,SAAS,WAEJ,qBAAC,QAAD;GAAM,aAAU;GAAhB,UAAA;IACG;IACA;IACA;GACG;EAGN,CAAA,IAAA,qBAAC,QAAD;GAAM,aAAU;GAAhB,UAAA;IACG,qBAAqB,MAAM,SAAS,CAAC;IACrC;IACA,qBAAqB,IAAI,SAAS,CAAC;GAChC;;CAET,CAAA;AAET"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProgressLine.js","names":[],"sources":["../../../../../src/Atomic/UI/ProgressLine/ProgressLine.tsx"],"sourcesContent":["import type { IProgressLineProps } from './ProgressLine.interface';\nimport cn from 'classnames';\n\nimport React from 'react';\n\nimport { addBitDepthPoints } from '../../../Functions/utils';\n\nimport './ProgressLine.scss';\n\nconst CN = 'progress-line';\nconst ProgressLine: React.FC<IProgressLineProps> = ({\n label = '',\n labelAlign = 'left',\n renderValue = false,\n renderValueInPercents = false,\n valueMeasurement = '',\n valueHorizontalPosition = 'right',\n valueVerticalPosition = 'center',\n symbolsAfterComma = 0,\n minValue = 0,\n maxValue = 100,\n value = 0,\n showExtremums = false,\n extremumsPosition = 'top',\n variant = 'info',\n useVariantLabelColor = true,\n isShowLine = true,\n className,\n testId = CN,\n}) => {\n const getFilledLineWidth = (): string => {\n if (value > maxValue) value = maxValue;\n return `${(((value - minValue) * 100) / (maxValue - minValue)).toFixed(symbolsAfterComma)}%`;\n };\n\n const renderLabel = (): JSX.Element | null => {\n if (!label) return null;\n return <div className={`progress-line__wrapper__label align-${labelAlign}`}>{label}</div>;\n };\n\n const renderProgressValue = (): JSX.Element | null => {\n if (!renderValue) return null;\n return (\n <div className=\"progress-line__wrapper__value\" aria-live=\"polite\">\n {renderValueInPercents\n ? getFilledLineWidth()\n : `${addBitDepthPoints(String(value))} ${valueMeasurement}`}\n </div>\n );\n };\n\n const renderExtremums = (): JSX.Element | null => {\n if (!showExtremums) return null;\n return (\n <div aria-hidden=\"true\" className={`progress-line__wrapper__extremums position-${extremumsPosition}`}>\n <div className=\"progress-line__wrapper__extremums--min\">\n {renderValueInPercents ? '0 %' : `${minValue} ${valueMeasurement}`}\n </div>\n <div className=\"progress-line__wrapper__extremums--max\">\n {renderValueInPercents ? '100 %' : `${maxValue} ${valueMeasurement}`}\n </div>\n </div>\n );\n };\n\n const renderFilledLine = (): JSX.Element => {\n return (\n <div\n className=\"progress-line__wrapper__line--filled\"\n role=\"progressbar\"\n aria-label={`Progress: ${value} out of ${maxValue}`}\n aria-valuenow={value}\n aria-valuemin={minValue}\n aria-valuemax={maxValue}\n style={{ width: getFilledLineWidth() }}\n >\n </div>\n );\n };\n\n const renderLine = (): JSX.Element => {\n return (\n <div className=\"progress-line__wrapper__line\">\n {renderExtremums()}\n {renderFilledLine()}\n </div>\n );\n };\n\n return (\n <div className={cn(CN, className)} data-testid={testId} role=\"region\" aria-label=\"Progress line\">\n {renderLabel()}\n <div\n className={`progress-line__wrapper variant-${\n useVariantLabelColor && variant\n } value-${valueVerticalPosition}-${valueHorizontalPosition} ${className}`}\n >\n {renderProgressValue()}\n {isShowLine && renderLine()}\n </div>\n </div>\n );\n};\n\nexport default ProgressLine;\n"],"mappings":";;;;;;AASA,IAAM,KAAK;AACX,IAAM,gBAA8C,EAClD,QAAQ,IACR,aAAa,QACb,cAAc,OACd,wBAAwB,OACxB,mBAAmB,IACnB,0BAA0B,SAC1B,wBAAwB,UACxB,oBAAoB,GACpB,WAAW,GACX,WAAW,KACX,QAAQ,GACR,gBAAgB,OAChB,oBAAoB,OACpB,UAAU,QACV,uBAAuB,MACvB,aAAa,MACb,WACA,SAAS,SACL;CACJ,MAAM,2BAAmC;EACvC,IAAI,QAAQ,UAAU,QAAQ;EAC9B,OAAO,KAAM,QAAQ,YAAY,OAAQ,WAAW,UAAA,CAAW,QAAQ,iBAAiB,EAAE;CAC5F;CAEA,MAAM,oBAAwC;EAC5C,IAAI,CAAC,OAAO,OAAO;EACnB,OAAO,oBAAC,OAAD;GAAK,WAAW,uCAAuC;aAAe;EAAW,CAAA;CAC1F;CAEA,MAAM,4BAAgD;EACpD,IAAI,CAAC,aAAa,OAAO;EACzB,OACE,oBAAC,OAAD;GAAK,WAAU;GAAgC,aAAU;aACtD,wBACG,mBAAmB,IACnB,GAAG,kBAAkB,OAAO,KAAK,CAAC,EAAE,GAAG;EACxC,CAAA;CAET;CAEA,MAAM,wBAA4C;EAChD,IAAI,CAAC,eAAe,OAAO;EAC3B,OACE,qBAAC,OAAD;GAAK,eAAY;GAAO,WAAW,8CAA8C;aAAjF,CACE,oBAAC,OAAD;IAAK,WAAU;cACZ,wBAAwB,QAAQ,GAAG,SAAS,GAAG;GAC7C,CAAA,GACL,oBAAC,OAAD;IAAK,WAAU;cACZ,wBAAwB,UAAU,GAAG,SAAS,GAAG;GAC/C,CAAA,CACF;;CAET;CAEA,MAAM,yBAAsC;EAC1C,OACE,oBAAC,OAAD;GACE,WAAU;GACV,MAAK;GACL,cAAY,aAAa,MAAM,UAAU;GACzC,iBAAe;GACf,iBAAe;GACf,iBAAe;GACf,OAAO,EAAE,OAAO,mBAAmB,EAAE;EAElC,CAAA;CAET;CAEA,MAAM,mBAAgC;EACpC,OACE,qBAAC,OAAD;GAAK,WAAU;aAAf,CACG,gBAAgB,GAChB,iBAAiB,CACf;;CAET;CAEA,OACE,qBAAC,OAAD;EAAK,WAAW,GAAG,IAAI,SAAS;EAAG,eAAa;EAAQ,MAAK;EAAS,cAAW;YAAjF,CACG,YAAY,GACb,qBAAC,OAAD;GACE,WAAW,kCACT,wBAAwB,QACzB,SAAS,sBAAsB,GAAG,wBAAwB,GAAG;aAHhE,CAKG,oBAAoB,GACpB,cAAc,WAAW,CACvB;IACF;;AAET"}
1
+ {"version":3,"file":"ProgressLine.js","names":[],"sources":["../../../../../src/Atomic/UI/ProgressLine/ProgressLine.tsx"],"sourcesContent":["import type { IProgressLineProps } from './ProgressLine.interface';\nimport cn from 'classnames';\n\nimport React from 'react';\n\nimport { addBitDepthPoints } from '../../../Functions/utils';\n\nimport './ProgressLine.scss';\n\nconst CN = 'progress-line';\nconst ProgressLine: React.FC<IProgressLineProps> = ({\n label = '',\n labelAlign = 'left',\n renderValue = false,\n renderValueInPercents = false,\n valueMeasurement = '',\n valueHorizontalPosition = 'right',\n valueVerticalPosition = 'center',\n symbolsAfterComma = 0,\n minValue = 0,\n maxValue = 100,\n value = 0,\n showExtremums = false,\n extremumsPosition = 'top',\n variant = 'info',\n useVariantLabelColor = true,\n isShowLine = true,\n className,\n testId = CN,\n}) => {\n const getFilledLineWidth = (): string => {\n if (value > maxValue) value = maxValue;\n return `${(((value - minValue) * 100) / (maxValue - minValue)).toFixed(symbolsAfterComma)}%`;\n };\n\n const renderLabel = (): JSX.Element | null => {\n if (!label) return null;\n return <div className={`progress-line__wrapper__label align-${labelAlign}`}>{label}</div>;\n };\n\n const renderProgressValue = (): JSX.Element | null => {\n if (!renderValue) return null;\n return (\n <div className=\"progress-line__wrapper__value\" aria-live=\"polite\">\n {renderValueInPercents\n ? getFilledLineWidth()\n : `${addBitDepthPoints(String(value))} ${valueMeasurement}`}\n </div>\n );\n };\n\n const renderExtremums = (): JSX.Element | null => {\n if (!showExtremums) return null;\n return (\n <div aria-hidden=\"true\" className={`progress-line__wrapper__extremums position-${extremumsPosition}`}>\n <div className=\"progress-line__wrapper__extremums--min\">\n {renderValueInPercents ? '0 %' : `${minValue} ${valueMeasurement}`}\n </div>\n <div className=\"progress-line__wrapper__extremums--max\">\n {renderValueInPercents ? '100 %' : `${maxValue} ${valueMeasurement}`}\n </div>\n </div>\n );\n };\n\n const renderFilledLine = (): JSX.Element => {\n return (\n <div\n className=\"progress-line__wrapper__line--filled\"\n role=\"progressbar\"\n aria-label={`Progress: ${value} out of ${maxValue}`}\n aria-valuenow={value}\n aria-valuemin={minValue}\n aria-valuemax={maxValue}\n style={{ width: getFilledLineWidth() }}\n >\n </div>\n );\n };\n\n const renderLine = (): JSX.Element => {\n return (\n <div className=\"progress-line__wrapper__line\">\n {renderExtremums()}\n {renderFilledLine()}\n </div>\n );\n };\n\n return (\n <div className={cn(CN, className)} data-testid={testId} role=\"region\" aria-label=\"Progress line\">\n {renderLabel()}\n <div\n className={`progress-line__wrapper variant-${\n useVariantLabelColor && variant\n } value-${valueVerticalPosition}-${valueHorizontalPosition} ${className}`}\n >\n {renderProgressValue()}\n {isShowLine && renderLine()}\n </div>\n </div>\n );\n};\n\nexport default ProgressLine;\n"],"mappings":";;;;;;AASA,IAAM,KAAK;AACX,IAAM,gBAA8C,EAClD,QAAQ,IACR,aAAa,QACb,cAAc,OACd,wBAAwB,OACxB,mBAAmB,IACnB,0BAA0B,SAC1B,wBAAwB,UACxB,oBAAoB,GACpB,WAAW,GACX,WAAW,KACX,QAAQ,GACR,gBAAgB,OAChB,oBAAoB,OACpB,UAAU,QACV,uBAAuB,MACvB,aAAa,MACb,WACA,SAAS,SACL;CACJ,MAAM,2BAAmC;EACvC,IAAI,QAAQ,UAAU,QAAQ;EAC9B,OAAO,KAAM,QAAQ,YAAY,OAAQ,WAAW,UAAA,CAAW,QAAQ,iBAAiB,EAAE;CAC5F;CAEA,MAAM,oBAAwC;EAC5C,IAAI,CAAC,OAAO,OAAO;EACnB,OAAO,oBAAC,OAAD;GAAK,WAAW,uCAAuC;GAAe,UAAA;EAAW,CAAA;CAC1F;CAEA,MAAM,4BAAgD;EACpD,IAAI,CAAC,aAAa,OAAO;EACzB,OACE,oBAAC,OAAD;GAAK,WAAU;GAAgC,aAAU;GACtD,UAAA,wBACG,mBAAmB,IACnB,GAAG,kBAAkB,OAAO,KAAK,CAAC,EAAE,GAAG;EACxC,CAAA;CAET;CAEA,MAAM,wBAA4C;EAChD,IAAI,CAAC,eAAe,OAAO;EAC3B,OACE,qBAAC,OAAD;GAAK,eAAY;GAAO,WAAW,8CAA8C;GAAjF,UAAA,CACE,oBAAC,OAAD;IAAK,WAAU;IACZ,UAAA,wBAAwB,QAAQ,GAAG,SAAS,GAAG;GAC7C,CAAA,GACL,oBAAC,OAAD;IAAK,WAAU;IACZ,UAAA,wBAAwB,UAAU,GAAG,SAAS,GAAG;GAC/C,CAAA,CACF;;CAET;CAEA,MAAM,yBAAsC;EAC1C,OACE,oBAAC,OAAD;GACE,WAAU;GACV,MAAK;GACL,cAAY,aAAa,MAAM,UAAU;GACzC,iBAAe;GACf,iBAAe;GACf,iBAAe;GACf,OAAO,EAAE,OAAO,mBAAmB,EAAE;EAElC,CAAA;CAET;CAEA,MAAM,mBAAgC;EACpC,OACE,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACG,gBAAgB,GAChB,iBAAiB,CACf;;CAET;CAEA,OACE,qBAAC,OAAD;EAAK,WAAW,GAAG,IAAI,SAAS;EAAG,eAAa;EAAQ,MAAK;EAAS,cAAW;EAAjF,UAAA,CACG,YAAY,GACb,qBAAC,OAAD;GACE,WAAW,kCACT,wBAAwB,QACzB,SAAS,sBAAsB,GAAG,wBAAwB,GAAG;GAHhE,UAAA,CAKG,oBAAoB,GACpB,cAAc,WAAW,CACvB;EACF,CAAA,CAAA;;AAET"}
@@ -1 +1 @@
1
- {"version":3,"file":"Status.js","names":[],"sources":["../../../../../src/Atomic/UI/Status/Status.tsx"],"sourcesContent":["import type { IStatusProps } from './Status.interface';\nimport cn from 'classnames';\n\nimport React from 'react';\n\nimport './Status.scss';\n\nfunction defaultOnClick(): void {}\n\nconst Status: React.FC<IStatusProps> = ({\n icon,\n value,\n label,\n status,\n disabled,\n type,\n active = 0,\n pause = 0,\n className,\n noBackground,\n children,\n testId = 'status',\n onClick = defaultOnClick,\n}) => {\n if (!status) return null;\n\n const text = children && typeof children === 'string' ? children : value || label || status;\n const formattedLabel = text?.[0].toUpperCase() + text?.slice(1);\n\n return (\n <div onClick={onClick} data-testid={testId} className={cn({ disabled }, className)}>\n {type === 'number'\n ? (\n <div>\n {active === 0 && pause === 0\n ? (\n <div className=\"status status--error\">\n <span>{active}</span>\n </div>\n )\n : (\n <div className=\"status status--warning\">\n <span className=\"status--number-active\">{active}</span>\n <span className=\"color--gray-gull\"> / </span>\n <span className={pause > 0 ? 'color--froly' : 'color--gray-gull'}>{pause}</span>\n </div>\n )}\n </div>\n )\n : (\n <div\n className={cn(\n 'status',\n `status--${status}`,\n {\n 'status--no-bg': noBackground && status === 'pause',\n 'color--gray-gull': noBackground && status === 'pause' && !className,\n 'j4': !!icon,\n },\n className,\n )}\n >\n {icon}\n {formattedLabel}\n </div>\n )}\n </div>\n );\n};\n\nexport default Status;\n"],"mappings":";;;;;AAOA,SAAS,iBAAuB,CAAC;AAEjC,IAAM,UAAkC,EACtC,MACA,OACA,OACA,QACA,UACA,MACA,SAAS,GACT,QAAQ,GACR,WACA,cACA,UACA,SAAS,UACT,UAAU,qBACN;CACJ,IAAI,CAAC,QAAQ,OAAO;CAEpB,MAAM,OAAO,YAAY,OAAO,aAAa,WAAW,WAAW,SAAS,SAAS;CACrF,MAAM,iBAAiB,OAAO,EAAE,CAAC,YAAY,IAAI,MAAM,MAAM,CAAC;CAE9D,OACE,oBAAC,OAAD;EAAc;EAAS,eAAa;EAAQ,WAAW,GAAG,EAAE,SAAS,GAAG,SAAS;YAC9E,SAAS,WAEJ,oBAAC,OAAD,EAAA,UACG,WAAW,KAAK,UAAU,IAErB,oBAAC,OAAD;GAAK,WAAU;aACb,oBAAC,QAAD,EAAA,UAAO,OAAa,CAAA;EACjB,CAAA,IAGL,qBAAC,OAAD;GAAK,WAAU;aAAf;IACE,oBAAC,QAAD;KAAM,WAAU;eAAyB;IAAa,CAAA;IACtD,oBAAC,QAAD;KAAM,WAAU;eAAmB;IAAS,CAAA;IAC5C,oBAAC,QAAD;KAAM,WAAW,QAAQ,IAAI,iBAAiB;eAAqB;IAAY,CAAA;GAC5E;KAER,CAAA,IAGL,qBAAC,OAAD;GACE,WAAW,GACT,UACA,WAAW,UACX;IACE,iBAAiB,gBAAgB,WAAW;IAC5C,oBAAoB,gBAAgB,WAAW,WAAW,CAAC;IAC3D,MAAM,CAAC,CAAC;GACV,GACA,SACF;aAVF,CAYG,MACA,cACE;;CAER,CAAA;AAET"}
1
+ {"version":3,"file":"Status.js","names":[],"sources":["../../../../../src/Atomic/UI/Status/Status.tsx"],"sourcesContent":["import type { IStatusProps } from './Status.interface';\nimport cn from 'classnames';\n\nimport React from 'react';\n\nimport './Status.scss';\n\nfunction defaultOnClick(): void {}\n\nconst Status: React.FC<IStatusProps> = ({\n icon,\n value,\n label,\n status,\n disabled,\n type,\n active = 0,\n pause = 0,\n className,\n noBackground,\n children,\n testId = 'status',\n onClick = defaultOnClick,\n}) => {\n if (!status) return null;\n\n const text = children && typeof children === 'string' ? children : value || label || status;\n const formattedLabel = text?.[0].toUpperCase() + text?.slice(1);\n\n return (\n <div onClick={onClick} data-testid={testId} className={cn({ disabled }, className)}>\n {type === 'number'\n ? (\n <div>\n {active === 0 && pause === 0\n ? (\n <div className=\"status status--error\">\n <span>{active}</span>\n </div>\n )\n : (\n <div className=\"status status--warning\">\n <span className=\"status--number-active\">{active}</span>\n <span className=\"color--gray-gull\"> / </span>\n <span className={pause > 0 ? 'color--froly' : 'color--gray-gull'}>{pause}</span>\n </div>\n )}\n </div>\n )\n : (\n <div\n className={cn(\n 'status',\n `status--${status}`,\n {\n 'status--no-bg': noBackground && status === 'pause',\n 'color--gray-gull': noBackground && status === 'pause' && !className,\n 'j4': !!icon,\n },\n className,\n )}\n >\n {icon}\n {formattedLabel}\n </div>\n )}\n </div>\n );\n};\n\nexport default Status;\n"],"mappings":";;;;;AAOA,SAAS,iBAAuB,CAAC;AAEjC,IAAM,UAAkC,EACtC,MACA,OACA,OACA,QACA,UACA,MACA,SAAS,GACT,QAAQ,GACR,WACA,cACA,UACA,SAAS,UACT,UAAU,qBACN;CACJ,IAAI,CAAC,QAAQ,OAAO;CAEpB,MAAM,OAAO,YAAY,OAAO,aAAa,WAAW,WAAW,SAAS,SAAS;CACrF,MAAM,iBAAiB,OAAO,EAAE,CAAC,YAAY,IAAI,MAAM,MAAM,CAAC;CAE9D,OACE,oBAAC,OAAD;EAAc;EAAS,eAAa;EAAQ,WAAW,GAAG,EAAE,SAAS,GAAG,SAAS;EAC9E,UAAA,SAAS,WAEJ,oBAAC,OAAD,EAAA,UACG,WAAW,KAAK,UAAU,IAErB,oBAAC,OAAD;GAAK,WAAU;GACb,UAAA,oBAAC,QAAD,EAAA,UAAO,OAAa,CAAA;EACjB,CAAA,IAGL,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA;IACE,oBAAC,QAAD;KAAM,WAAU;KAAyB,UAAA;IAAa,CAAA;IACtD,oBAAC,QAAD;KAAM,WAAU;KAAmB,UAAA;IAAS,CAAA;IAC5C,oBAAC,QAAD;KAAM,WAAW,QAAQ,IAAI,iBAAiB;KAAqB,UAAA;IAAY,CAAA;GAC5E;EAER,CAAA,EAAA,CAAA,IAGL,qBAAC,OAAD;GACE,WAAW,GACT,UACA,WAAW,UACX;IACE,iBAAiB,gBAAgB,WAAW;IAC5C,oBAAoB,gBAAgB,WAAW,WAAW,CAAC;IAC3D,MAAM,CAAC,CAAC;GACV,GACA,SACF;GAVF,UAAA,CAYG,MACA,cACE;;CAER,CAAA;AAET"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tag.js","names":[],"sources":["../../../../../src/Atomic/UI/Tag/Tag.tsx"],"sourcesContent":["import type { ITagProps } from './Tag.interface';\nimport cn from 'classnames';\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { AlertTriangle, X } from 'react-feather';\nimport Spinner from '../../Layout/Spinner';\n\nimport './Tag.scss';\n\nconst CN = 'tag';\n\nfunction defaultOnClick(): void {}\n\nconst Tag: React.FC<ITagProps> = ({\n value,\n className,\n style,\n label,\n warning,\n isWarningHint = true,\n removeItem,\n name,\n isPopup,\n popupInfoContent,\n popupClassName,\n id,\n isUseInTable,\n isNoDismiss = true,\n onClick = defaultOnClick,\n testId = CN,\n}) => {\n const tagRef = useRef<HTMLDivElement>(null);\n\n const [isTagHover, setIsTagHover] = useState<boolean>(false);\n const [isTagPopupOpened, setIsTagPopupOpened] = useState<boolean>(false);\n\n const { x, y, height, width } = tagRef?.current?.getBoundingClientRect() ?? {};\n const { scrollY } = window;\n\n const tagPopupStyles = useMemo(() => {\n if (!isTagPopupOpened || !tagRef?.current) return {};\n\n const { x, y, height, width } = tagRef?.current?.getBoundingClientRect();\n\n return {\n left: `${x}px`,\n top: `${y + scrollY}px`,\n transform: `translate(calc(-1 * calc(100% - ${width / 2 + 22}px)), ${height + 10}px)`,\n };\n }, [isTagPopupOpened, x, y, width, height, scrollY]);\n\n const tagLabelStyle = useMemo(() => {\n const styleObj: React.CSSProperties = {};\n\n const bgColor = style?.backgroundColor ?? style?.background;\n\n if (bgColor === '#242424') {\n styleObj.color = '#fff';\n }\n\n return styleObj;\n }, [style]);\n\n const handle = {\n onTagClick: (event: React.MouseEvent<HTMLDivElement>) => {\n if (isUseInTable) {\n event.stopPropagation();\n }\n if (isPopup) {\n setIsTagPopupOpened(!isTagPopupOpened);\n }\n onClick(id, event);\n },\n };\n\n const handleClickOutside = (): void => {\n setIsTagPopupOpened(false);\n };\n\n useEffect(() => {\n document.addEventListener('click', handleClickOutside, true);\n return () => {\n document.removeEventListener('click', handleClickOutside, true);\n };\n }, []);\n\n useEffect(() => {\n const handleScroll = (): void => {\n setIsTagPopupOpened(false);\n };\n\n window.addEventListener('scroll', handleScroll, true);\n return () => {\n window.removeEventListener('scroll', handleScroll, true);\n };\n }, []);\n\n return (\n <div\n onMouseEnter={() => setIsTagHover(true)}\n onMouseLeave={() => setIsTagHover(false)}\n data-testid={testId}\n role=\"listitem\"\n aria-label={`Tag: ${label || name}`}\n className={cn(CN, className, { 'tag-warn': warning })}\n style={style ?? {}}\n onClick={event => handle.onTagClick(event)}\n ref={tagRef}\n >\n {warning && typeof warning === 'string' && (\n <AlertTriangle className=\"advanced-tags--warning-icon mr5\" aria-label=\"Warning\" />\n )}\n {warning && typeof warning === 'string' && isTagHover && isWarningHint && (\n <div className=\"tag__warn-hint\" role=\"tooltip\">\n {warning}\n </div>\n )}\n <span className=\"tag__label\" style={tagLabelStyle}>{label || name}</span>\n\n {removeItem && !isNoDismiss && (\n <button\n type=\"button\"\n onClick={(e) => {\n e?.preventDefault();\n e?.stopPropagation();\n removeItem(value);\n }}\n aria-label={`Remove ${label || name}`}\n className=\"tag__button\"\n >\n <X className=\"color--text\" />\n </button>\n )}\n\n {isTagPopupOpened\n && createPortal(\n <div id={`tagPopup${value}`} className={cn('tag__popup', popupClassName)} style={tagPopupStyles}>\n {!popupInfoContent ? <Spinner size=\"small\" /> : popupInfoContent}\n </div>,\n document.getElementById('root')!,\n )}\n </div>\n );\n};\n\nexport default Tag;\n"],"mappings":"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"}
1
+ {"version":3,"file":"Tag.js","names":[],"sources":["../../../../../src/Atomic/UI/Tag/Tag.tsx"],"sourcesContent":["import type { ITagProps } from './Tag.interface';\nimport cn from 'classnames';\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { AlertTriangle, X } from 'react-feather';\nimport Spinner from '../../Layout/Spinner';\n\nimport './Tag.scss';\n\nconst CN = 'tag';\n\nfunction defaultOnClick(): void {}\n\nconst Tag: React.FC<ITagProps> = ({\n value,\n className,\n style,\n label,\n warning,\n isWarningHint = true,\n removeItem,\n name,\n isPopup,\n popupInfoContent,\n popupClassName,\n id,\n isUseInTable,\n isNoDismiss = true,\n onClick = defaultOnClick,\n testId = CN,\n}) => {\n const tagRef = useRef<HTMLDivElement>(null);\n\n const [isTagHover, setIsTagHover] = useState<boolean>(false);\n const [isTagPopupOpened, setIsTagPopupOpened] = useState<boolean>(false);\n\n const { x, y, height, width } = tagRef?.current?.getBoundingClientRect() ?? {};\n const { scrollY } = window;\n\n const tagPopupStyles = useMemo(() => {\n if (!isTagPopupOpened || !tagRef?.current) return {};\n\n const { x, y, height, width } = tagRef?.current?.getBoundingClientRect();\n\n return {\n left: `${x}px`,\n top: `${y + scrollY}px`,\n transform: `translate(calc(-1 * calc(100% - ${width / 2 + 22}px)), ${height + 10}px)`,\n };\n }, [isTagPopupOpened, x, y, width, height, scrollY]);\n\n const tagLabelStyle = useMemo(() => {\n const styleObj: React.CSSProperties = {};\n\n const bgColor = style?.backgroundColor ?? style?.background;\n\n if (bgColor === '#242424') {\n styleObj.color = '#fff';\n }\n\n return styleObj;\n }, [style]);\n\n const handle = {\n onTagClick: (event: React.MouseEvent<HTMLDivElement>) => {\n if (isUseInTable) {\n event.stopPropagation();\n }\n if (isPopup) {\n setIsTagPopupOpened(!isTagPopupOpened);\n }\n onClick(id, event);\n },\n };\n\n const handleClickOutside = (): void => {\n setIsTagPopupOpened(false);\n };\n\n useEffect(() => {\n document.addEventListener('click', handleClickOutside, true);\n return () => {\n document.removeEventListener('click', handleClickOutside, true);\n };\n }, []);\n\n useEffect(() => {\n const handleScroll = (): void => {\n setIsTagPopupOpened(false);\n };\n\n window.addEventListener('scroll', handleScroll, true);\n return () => {\n window.removeEventListener('scroll', handleScroll, true);\n };\n }, []);\n\n return (\n <div\n onMouseEnter={() => setIsTagHover(true)}\n onMouseLeave={() => setIsTagHover(false)}\n data-testid={testId}\n role=\"listitem\"\n aria-label={`Tag: ${label || name}`}\n className={cn(CN, className, { 'tag-warn': warning })}\n style={style ?? {}}\n onClick={event => handle.onTagClick(event)}\n ref={tagRef}\n >\n {warning && typeof warning === 'string' && (\n <AlertTriangle className=\"advanced-tags--warning-icon mr5\" aria-label=\"Warning\" />\n )}\n {warning && typeof warning === 'string' && isTagHover && isWarningHint && (\n <div className=\"tag__warn-hint\" role=\"tooltip\">\n {warning}\n </div>\n )}\n <span className=\"tag__label\" style={tagLabelStyle}>{label || name}</span>\n\n {removeItem && !isNoDismiss && (\n <button\n type=\"button\"\n onClick={(e) => {\n e?.preventDefault();\n e?.stopPropagation();\n removeItem(value);\n }}\n aria-label={`Remove ${label || name}`}\n className=\"tag__button\"\n >\n <X className=\"color--text\" />\n </button>\n )}\n\n {isTagPopupOpened\n && createPortal(\n <div id={`tagPopup${value}`} className={cn('tag__popup', popupClassName)} style={tagPopupStyles}>\n {!popupInfoContent ? <Spinner size=\"small\" /> : popupInfoContent}\n </div>,\n document.getElementById('root')!,\n )}\n </div>\n );\n};\n\nexport default Tag;\n"],"mappings":"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"}
@@ -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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"}