@intlayer/design-system 8.7.6 → 8.7.8-canary.0

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 (117) hide show
  1. package/dist/esm/components/Breadcrumb/index.mjs.map +1 -1
  2. package/dist/esm/components/Browser/Browser.mjs.map +1 -1
  3. package/dist/esm/components/Carousel/index.mjs.map +1 -1
  4. package/dist/esm/components/ContentEditor/ContentEditorTextArea.mjs +1 -1
  5. package/dist/esm/components/DictionaryEditor/NodeWrapper/BooleanWrapper.mjs.map +1 -1
  6. package/dist/esm/components/DictionaryEditor/NodeWrapper/NestedObjectWrapper.mjs.map +1 -1
  7. package/dist/esm/components/DictionaryEditor/NodeWrapper/NumberWrapper.mjs.map +1 -1
  8. package/dist/esm/components/DictionaryEditor/NodeWrapper/index.mjs.map +1 -1
  9. package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/TextEditor.mjs +2 -2
  10. package/dist/esm/components/DictionaryFieldEditor/DictionaryCreationForm/DictionaryCreationForm.mjs +1 -1
  11. package/dist/esm/components/DictionaryFieldEditor/DictionaryDetails/DictionaryDetailsForm.mjs +3 -3
  12. package/dist/esm/components/DictionaryFieldEditor/DictionaryFieldEditor.mjs +1 -1
  13. package/dist/esm/components/DictionaryFieldEditor/EnumKeyInput.mjs.map +1 -1
  14. package/dist/esm/components/DictionaryFieldEditor/KeyPathBreadcrumb.mjs.map +1 -1
  15. package/dist/esm/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.mjs +2 -2
  16. package/dist/esm/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.mjs.map +1 -1
  17. package/dist/esm/components/DictionaryFieldEditor/NodeTypeSelector.mjs.map +1 -1
  18. package/dist/esm/components/DictionaryFieldEditor/SaveForm/SaveForm.mjs +2 -2
  19. package/dist/esm/components/DictionaryFieldEditor/SaveForm/SaveForm.mjs.map +1 -1
  20. package/dist/esm/components/DictionaryFieldEditor/StructureView/StructureView.mjs +1 -1
  21. package/dist/esm/components/DictionaryFieldEditor/StructureView/StructureView.mjs.map +1 -1
  22. package/dist/esm/components/EditableField/EditableFieldInput.mjs.map +1 -1
  23. package/dist/esm/components/Flags/Flag.mjs.map +1 -1
  24. package/dist/esm/components/Form/FormField.mjs.map +1 -1
  25. package/dist/esm/components/Form/FormItem.mjs.map +1 -1
  26. package/dist/esm/components/Form/elements/FormElementWrapper.mjs.map +1 -1
  27. package/dist/esm/components/Form/elements/OTPElement.mjs +1 -1
  28. package/dist/esm/components/HTMLRender/HTMLRender.mjs.map +1 -1
  29. package/dist/esm/components/Headers/index.mjs.map +1 -1
  30. package/dist/esm/components/HeightResizer/index.mjs +25 -0
  31. package/dist/esm/components/HeightResizer/index.mjs.map +1 -1
  32. package/dist/esm/components/IDE/Code.mjs +96 -13
  33. package/dist/esm/components/IDE/Code.mjs.map +1 -1
  34. package/dist/esm/components/IDE/CodeBlockHighlight.mjs +77 -0
  35. package/dist/esm/components/IDE/CodeBlockHighlight.mjs.map +1 -0
  36. package/dist/esm/components/IDE/CodeBlockServer.mjs.map +1 -1
  37. package/dist/esm/components/IDE/CodeConditionalRenderer.mjs +15 -4
  38. package/dist/esm/components/IDE/CodeConditionalRenderer.mjs.map +1 -1
  39. package/dist/esm/components/IDE/CodeFormatSelector.mjs +5 -4
  40. package/dist/esm/components/IDE/CodeFormatSelector.mjs.map +1 -1
  41. package/dist/esm/components/IDE/FileTree.mjs.map +1 -1
  42. package/dist/esm/components/IDE/IDE.mjs.map +1 -1
  43. package/dist/esm/components/IDE/codeTransformer.mjs +228 -0
  44. package/dist/esm/components/IDE/codeTransformer.mjs.map +1 -0
  45. package/dist/esm/components/Input/OTPInput.mjs.map +1 -1
  46. package/dist/esm/components/KeyboardShortcut/KeyboardShortcut.mjs.map +1 -1
  47. package/dist/esm/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.mjs +1 -1
  48. package/dist/esm/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.mjs.map +1 -1
  49. package/dist/esm/components/LocaleSwitcherDropDown/LocaleSwitcher.mjs.map +1 -1
  50. package/dist/esm/components/MarkDownRender/MarkDownIframe.mjs +101 -0
  51. package/dist/esm/components/MarkDownRender/MarkDownIframe.mjs.map +1 -0
  52. package/dist/esm/components/MarkDownRender/MarkDownRender.mjs +2 -9
  53. package/dist/esm/components/MarkDownRender/MarkDownRender.mjs.map +1 -1
  54. package/dist/esm/components/Modal/Modal.mjs +2 -2
  55. package/dist/esm/components/Navbar/MobileNavbar.mjs +1 -1
  56. package/dist/esm/components/Navbar/index.mjs +1 -3
  57. package/dist/esm/components/Navbar/index.mjs.map +1 -1
  58. package/dist/esm/components/Navbar/useNavigation.mjs +3 -0
  59. package/dist/esm/components/Navbar/useNavigation.mjs.map +1 -1
  60. package/dist/esm/components/Pagination/Pagination.mjs +1 -1
  61. package/dist/esm/components/Popover/dynamic.mjs.map +1 -1
  62. package/dist/esm/components/RightDrawer/RightDrawer.mjs +3 -3
  63. package/dist/esm/components/Select/Multiselect.mjs.map +1 -1
  64. package/dist/esm/components/Tab/Tab.mjs.map +1 -1
  65. package/dist/esm/components/TechLogo/TechLogo.mjs.map +1 -1
  66. package/dist/esm/components/TextArea/AutocompleteTextArea.mjs.map +1 -1
  67. package/dist/esm/components/TextArea/ContentEditableTextArea.mjs.map +1 -1
  68. package/dist/esm/components/Toaster/Toast.mjs +6 -1
  69. package/dist/esm/components/Toaster/Toast.mjs.map +1 -1
  70. package/dist/esm/components/WithResizer/index.mjs +24 -0
  71. package/dist/esm/components/WithResizer/index.mjs.map +1 -1
  72. package/dist/esm/hooks/index.mjs +11 -11
  73. package/dist/esm/hooks/reactQuery.mjs +49 -2
  74. package/dist/esm/hooks/reactQuery.mjs.map +1 -1
  75. package/dist/esm/hooks/useAuth/useOAuth2.mjs +1 -1
  76. package/dist/esm/hooks/useAuth/useOAuth2.mjs.map +1 -1
  77. package/dist/esm/hooks/useAuth/useSession.mjs +1 -1
  78. package/dist/esm/hooks/useAuth/useSession.mjs.map +1 -1
  79. package/dist/esm/hooks/useDevice.mjs.map +1 -1
  80. package/dist/esm/hooks/useHorizontalSwipe.mjs.map +1 -1
  81. package/dist/esm/hooks/useIsDarkMode.mjs.map +1 -1
  82. package/dist/esm/hooks/useKeyboardDetector.mjs.map +1 -1
  83. package/dist/esm/hooks/useScrollBlockage/useScrollBlockageStore.mjs.map +1 -1
  84. package/dist/esm/libs/auth.mjs +1 -1
  85. package/dist/esm/libs/auth.mjs.map +1 -1
  86. package/dist/esm/providers/ReactQueryProvider.mjs.map +1 -1
  87. package/dist/esm/tailwind.config.mjs.map +1 -1
  88. package/dist/types/components/Badge/index.d.ts +2 -2
  89. package/dist/types/components/Button/Button.d.ts +4 -4
  90. package/dist/types/components/Command/index.d.ts +1 -1
  91. package/dist/types/components/Container/index.d.ts +7 -7
  92. package/dist/types/components/HeightResizer/index.d.ts.map +1 -1
  93. package/dist/types/components/IDE/Code.d.ts +3 -3
  94. package/dist/types/components/IDE/Code.d.ts.map +1 -1
  95. package/dist/types/components/IDE/CodeBlockHighlight.d.ts +20 -0
  96. package/dist/types/components/IDE/CodeBlockHighlight.d.ts.map +1 -0
  97. package/dist/types/components/IDE/CodeConditionalRenderer.d.ts.map +1 -1
  98. package/dist/types/components/IDE/CodeFormatSelector.d.ts +5 -1
  99. package/dist/types/components/IDE/CodeFormatSelector.d.ts.map +1 -1
  100. package/dist/types/components/IDE/codeTransformer.d.ts +25 -0
  101. package/dist/types/components/IDE/codeTransformer.d.ts.map +1 -0
  102. package/dist/types/components/Input/Checkbox.d.ts +2 -2
  103. package/dist/types/components/Link/Link.d.ts +4 -4
  104. package/dist/types/components/MarkDownRender/MarkDownIframe.d.ts +7 -0
  105. package/dist/types/components/MarkDownRender/MarkDownIframe.d.ts.map +1 -0
  106. package/dist/types/components/MarkDownRender/MarkDownRender.d.ts.map +1 -1
  107. package/dist/types/components/Pagination/Pagination.d.ts +1 -1
  108. package/dist/types/components/SwitchSelector/index.d.ts +1 -1
  109. package/dist/types/components/Tab/Tab.d.ts +1 -1
  110. package/dist/types/components/TabSelector/TabSelector.d.ts +1 -1
  111. package/dist/types/components/Tag/index.d.ts +3 -3
  112. package/dist/types/components/Toaster/Toast.d.ts +1 -1
  113. package/dist/types/components/WithResizer/index.d.ts.map +1 -1
  114. package/dist/types/hooks/index.d.ts +2 -2
  115. package/dist/types/hooks/reactQuery.d.ts +8 -1
  116. package/dist/types/hooks/reactQuery.d.ts.map +1 -1
  117. package/package.json +25 -25
@@ -1 +1 @@
1
- {"version":3,"file":"LocaleSwitcherContent.mjs","names":[],"sources":["../../../../src/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.tsx"],"sourcesContent":["'use client';\n\nimport { usePersistedStore } from '@hooks/usePersistedStore';\nimport { getHTMLTextDir, getLocaleName } from '@intlayer/core/localization';\nimport { ENGLISH } from '@intlayer/types/locales';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport Fuse, { type IFuseOptions } from 'fuse.js';\nimport { Check, Globe, MoveVertical } from 'lucide-react';\nimport { type FC, useMemo, useRef, useState } from 'react';\nimport { useIntlayer, useLocale } from 'react-intlayer';\nimport {\n Button,\n ButtonColor,\n ButtonSize,\n ButtonTextAlign,\n ButtonVariant,\n} from '../Button';\nimport { Container } from '../Container';\nimport { DropDown, type PanelProps } from '../DropDown';\nimport { Input } from '../Input';\nimport {\n SwitchSelector,\n SwitchSelectorColor,\n SwitchSelectorSize,\n} from '../SwitchSelector';\nimport { useLocaleSwitcherContent } from './LocaleSwitcherContentContext';\n\nexport type LocaleSwitcherContentProps = {\n panelProps?: Omit<PanelProps, 'identifier'>;\n isMultilingual?: boolean;\n};\n\nconst DROPDOWN_IDENTIFIER = 'locale-switcher-content';\n\ntype MultilingualAvailableLocales = {\n locale: LocalesValues;\n englishName: string;\n currentLocaleName: string;\n ownLocaleName: string;\n};\n\nexport const LocaleSwitcherContent: FC<LocaleSwitcherContentProps> = ({\n panelProps,\n isMultilingual = true,\n}) => {\n const {\n switchTo,\n searchInput,\n localeSwitcherLabel,\n languageListLabel,\n seeAllLocalesSwitch,\n } = useIntlayer('locale-switcher-content');\n const inputRef = useRef<HTMLInputElement>(null);\n const { locale } = useLocale();\n const { availableLocales, selectedLocales, setSelectedLocales } =\n useLocaleSwitcherContent();\n\n // 1. Memoize the list construction so it doesn't rebuild every render\n const multilingualAvailableLocales: MultilingualAvailableLocales[] = useMemo(\n () =>\n availableLocales.map((localeEl) => {\n const englishName = getLocaleName(localeEl, ENGLISH);\n const currentLocaleName = getLocaleName(localeEl, locale);\n const ownLocaleName = getLocaleName(localeEl);\n return {\n locale: localeEl,\n englishName,\n currentLocaleName,\n ownLocaleName,\n };\n }),\n [availableLocales, locale]\n );\n\n // 2. State for Search Query only (Source of Truth)\n const [searchQuery, setSearchQuery] = useState('');\n\n const [seeAllLocales, setSeeAllLocales] = usePersistedStore(\n 'locale-content-selector-see-all-locales',\n false\n );\n\n // 3. Memoize Fuse instance\n const fuse = useMemo(() => {\n const fuseOptions: IFuseOptions<MultilingualAvailableLocales> = {\n keys: [\n { name: 'ownLocaleName', weight: 0.4 },\n { name: 'englishName', weight: 0.2 },\n { name: 'currentLocaleName', weight: 0.2 },\n { name: 'locale', weight: 0.2 },\n ],\n threshold: 0.02,\n };\n return new Fuse(multilingualAvailableLocales, fuseOptions);\n }, [multilingualAvailableLocales]);\n\n // 4. Derive results from Search Query\n const results = useMemo(() => {\n if (!searchQuery) {\n return multilingualAvailableLocales;\n }\n return fuse.search(searchQuery).map((result) => result.item);\n }, [searchQuery, multilingualAvailableLocales, fuse]);\n\n const handleClickLocale = (localeItem: LocalesValues) => {\n if (isMultilingual) {\n if (selectedLocales.includes(localeItem)) {\n if (selectedLocales.length > 1) {\n setSelectedLocales((prev) => prev.filter((el) => el !== localeItem));\n }\n } else {\n setSelectedLocales((prev) => [...prev, localeItem]);\n }\n } else {\n setSelectedLocales([localeItem]);\n }\n };\n\n const handleSeeAllLocales = (value: boolean) => {\n setSeeAllLocales(value);\n\n if (value) {\n setSelectedLocales(availableLocales);\n } else {\n setSelectedLocales([locale]);\n }\n };\n\n return (\n <div className=\"rounded-xl border border-text text-text transition-colors\">\n <DropDown identifier={DROPDOWN_IDENTIFIER}>\n <DropDown.Trigger\n identifier={DROPDOWN_IDENTIFIER}\n label={localeSwitcherLabel.value}\n className=\"p-0!\"\n roundedSize=\"3xl\"\n color=\"text\"\n >\n <div className=\"flex w-full items-center justify-between text-text\">\n <div className=\"px-2 py-1\">\n <Globe size={16} />\n </div>\n <MoveVertical className=\"self-center\" size={16} />\n </div>\n </DropDown.Trigger>\n\n <DropDown.Panel\n identifier={DROPDOWN_IDENTIFIER}\n isOverable\n isFocusable\n align=\"end\"\n {...panelProps}\n >\n <Container\n className=\"max-h-[60vh] min-w-28\"\n separator=\"y\"\n role=\"listbox\"\n transparency=\"xs\"\n border\n roundedSize=\"3xl\"\n borderColor=\"text\"\n aria-label={languageListLabel.value}\n >\n {isMultilingual && (\n <div className=\"m-auto p-2\">\n <SwitchSelector\n defaultValue={seeAllLocales} // Ensure this uses the persisted state\n onChange={handleSeeAllLocales}\n color={SwitchSelectorColor.TEXT}\n size={SwitchSelectorSize.SM}\n className=\"!w-60\"\n choices={[\n {\n content: seeAllLocalesSwitch.true.value,\n value: true,\n },\n {\n content: seeAllLocalesSwitch.false.value,\n value: false,\n },\n ]}\n />\n </div>\n )}\n\n {!(isMultilingual && seeAllLocales) && (\n <>\n <div className=\"p-3\">\n <Input\n type=\"search\"\n aria-label={searchInput.ariaLabel.value}\n placeholder={searchInput.placeholder.value}\n // Update search query state directly\n onChange={(e) => setSearchQuery(e.target.value)}\n ref={inputRef}\n />\n </div>\n <ol className=\"divide-y divide-dashed divide-text/20 overflow-y-auto p-1\">\n {results.map(\n ({\n locale: localeItem,\n currentLocaleName,\n ownLocaleName,\n }) => (\n <li className=\"px-1.5 py-1\" key={localeItem}>\n <Button\n onClick={() => handleClickLocale(localeItem)}\n label={`${switchTo} ${currentLocaleName}`}\n disabled={\n !(availableLocales ?? availableLocales).includes(\n localeItem\n )\n }\n isActive={selectedLocales.includes(localeItem)}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n isFullWidth\n textAlign={ButtonTextAlign.LEFT}\n size={ButtonSize.SM}\n >\n <div className=\"flex flex-row items-center justify-between gap-3 px-2 py-1\">\n {isMultilingual && (\n <div className=\"w-4\">\n {selectedLocales.includes(localeItem) && (\n <Check className=\"size-full\" />\n )}\n </div>\n )}\n <div className=\"flex flex-1 flex-row items-center justify-between gap-3 px-2 py-1\">\n <div className=\"flex flex-col text-nowrap\">\n <span\n dir={getHTMLTextDir(localeItem)}\n lang={localeItem}\n >\n {ownLocaleName}\n </span>\n <span className=\"text-neutral text-xs\">\n {currentLocaleName}\n </span>\n </div>\n <span className=\"text-neutral text-sm\">\n {localeItem.toUpperCase()}\n </span>\n </div>\n </div>\n </Button>\n </li>\n )\n )}\n </ol>\n </>\n )}\n </Container>\n </DropDown.Panel>\n </DropDown>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"LocaleSwitcherContent.mjs","names":[],"sources":["../../../../src/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.tsx"],"sourcesContent":["'use client';\n\nimport { usePersistedStore } from '@hooks/usePersistedStore';\nimport { getHTMLTextDir, getLocaleName } from '@intlayer/core/localization';\nimport { ENGLISH } from '@intlayer/types/locales';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport Fuse, { type IFuseOptions } from 'fuse.js';\nimport { Check, Globe, MoveVertical } from 'lucide-react';\nimport { type FC, useMemo, useRef, useState } from 'react';\nimport { useIntlayer, useLocale } from 'react-intlayer';\nimport {\n Button,\n ButtonColor,\n ButtonSize,\n ButtonTextAlign,\n ButtonVariant,\n} from '../Button';\nimport { Container } from '../Container';\nimport { DropDown, type PanelProps } from '../DropDown';\nimport { Input } from '../Input';\nimport {\n SwitchSelector,\n SwitchSelectorColor,\n SwitchSelectorSize,\n} from '../SwitchSelector';\nimport { useLocaleSwitcherContent } from './LocaleSwitcherContentContext';\n\nexport type LocaleSwitcherContentProps = {\n panelProps?: Omit<PanelProps, 'identifier'>;\n isMultilingual?: boolean;\n};\n\nconst DROPDOWN_IDENTIFIER = 'locale-switcher-content';\n\ntype MultilingualAvailableLocales = {\n locale: LocalesValues;\n englishName: string;\n currentLocaleName: string;\n ownLocaleName: string;\n};\n\nexport const LocaleSwitcherContent: FC<LocaleSwitcherContentProps> = ({\n panelProps,\n isMultilingual = true,\n}) => {\n const {\n switchTo,\n searchInput,\n localeSwitcherLabel,\n languageListLabel,\n seeAllLocalesSwitch,\n } = useIntlayer('locale-switcher-content');\n const inputRef = useRef<HTMLInputElement>(null);\n const { locale } = useLocale();\n const { availableLocales, selectedLocales, setSelectedLocales } =\n useLocaleSwitcherContent();\n\n // 1. Memoize the list construction so it doesn't rebuild every render\n const multilingualAvailableLocales: MultilingualAvailableLocales[] = useMemo(\n () =>\n availableLocales.map((localeEl) => {\n const englishName = getLocaleName(localeEl, ENGLISH);\n const currentLocaleName = getLocaleName(localeEl, locale);\n const ownLocaleName = getLocaleName(localeEl);\n return {\n locale: localeEl,\n englishName,\n currentLocaleName,\n ownLocaleName,\n };\n }),\n [availableLocales, locale]\n );\n\n // 2. State for Search Query only (Source of Truth)\n const [searchQuery, setSearchQuery] = useState('');\n\n const [seeAllLocales, setSeeAllLocales] = usePersistedStore(\n 'locale-content-selector-see-all-locales',\n false\n );\n\n // 3. Memoize Fuse instance\n const fuse = useMemo(() => {\n const fuseOptions: IFuseOptions<MultilingualAvailableLocales> = {\n keys: [\n { name: 'ownLocaleName', weight: 0.4 },\n { name: 'englishName', weight: 0.2 },\n { name: 'currentLocaleName', weight: 0.2 },\n { name: 'locale', weight: 0.2 },\n ],\n threshold: 0.02,\n };\n return new Fuse(multilingualAvailableLocales, fuseOptions);\n }, [multilingualAvailableLocales]);\n\n // 4. Derive results from Search Query\n const results = useMemo(() => {\n if (!searchQuery) {\n return multilingualAvailableLocales;\n }\n return fuse.search(searchQuery).map((result) => result.item);\n }, [searchQuery, multilingualAvailableLocales, fuse]);\n\n const handleClickLocale = (localeItem: LocalesValues) => {\n if (isMultilingual) {\n if (selectedLocales.includes(localeItem)) {\n if (selectedLocales.length > 1) {\n setSelectedLocales((prev) => prev.filter((el) => el !== localeItem));\n }\n } else {\n setSelectedLocales((prev) => [...prev, localeItem]);\n }\n } else {\n setSelectedLocales([localeItem]);\n }\n };\n\n const handleSeeAllLocales = (value: boolean) => {\n setSeeAllLocales(value);\n\n if (value) {\n setSelectedLocales(availableLocales);\n } else {\n setSelectedLocales([locale]);\n }\n };\n\n return (\n <div className=\"rounded-xl border border-text text-text transition-colors\">\n <DropDown identifier={DROPDOWN_IDENTIFIER}>\n <DropDown.Trigger\n identifier={DROPDOWN_IDENTIFIER}\n label={localeSwitcherLabel.value}\n className=\"p-0!\"\n roundedSize=\"3xl\"\n color=\"text\"\n >\n <div className=\"flex w-full items-center justify-between text-text\">\n <div className=\"px-2 py-1\">\n <Globe size={16} />\n </div>\n <MoveVertical className=\"self-center\" size={16} />\n </div>\n </DropDown.Trigger>\n\n <DropDown.Panel\n identifier={DROPDOWN_IDENTIFIER}\n isOverable\n isFocusable\n align=\"end\"\n {...panelProps}\n >\n <Container\n className=\"max-h-[60vh] min-w-28\"\n separator=\"y\"\n role=\"listbox\"\n transparency=\"xs\"\n border\n roundedSize=\"3xl\"\n borderColor=\"text\"\n aria-label={languageListLabel.value}\n >\n {isMultilingual && (\n <div className=\"m-auto p-2\">\n <SwitchSelector\n defaultValue={seeAllLocales} // Ensure this uses the persisted state\n onChange={handleSeeAllLocales}\n color={SwitchSelectorColor.TEXT}\n size={SwitchSelectorSize.SM}\n className=\"!w-60\"\n choices={[\n {\n content: seeAllLocalesSwitch.true.value,\n value: true,\n },\n {\n content: seeAllLocalesSwitch.false.value,\n value: false,\n },\n ]}\n />\n </div>\n )}\n\n {!(isMultilingual && seeAllLocales) && (\n <>\n <div className=\"p-3\">\n <Input\n type=\"search\"\n aria-label={searchInput.ariaLabel.value}\n placeholder={searchInput.placeholder.value}\n // Update search query state directly\n onChange={(e) => setSearchQuery(e.target.value)}\n ref={inputRef}\n />\n </div>\n <ol className=\"divide-y divide-dashed divide-text/20 overflow-y-auto p-1\">\n {results.map(\n ({\n locale: localeItem,\n currentLocaleName,\n ownLocaleName,\n }) => (\n <li className=\"px-1.5 py-1\" key={localeItem}>\n <Button\n onClick={() => handleClickLocale(localeItem)}\n label={`${switchTo} ${currentLocaleName}`}\n disabled={\n !(availableLocales ?? availableLocales).includes(\n localeItem\n )\n }\n isActive={selectedLocales.includes(localeItem)}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n isFullWidth\n textAlign={ButtonTextAlign.LEFT}\n size={ButtonSize.SM}\n >\n <div className=\"flex flex-row items-center justify-between gap-3 px-2 py-1\">\n {isMultilingual && (\n <div className=\"w-4\">\n {selectedLocales.includes(localeItem) && (\n <Check className=\"size-full\" />\n )}\n </div>\n )}\n <div className=\"flex flex-1 flex-row items-center justify-between gap-3 px-2 py-1\">\n <div className=\"flex flex-col text-nowrap\">\n <span\n dir={getHTMLTextDir(localeItem)}\n lang={localeItem}\n >\n {ownLocaleName}\n </span>\n <span className=\"text-neutral text-xs\">\n {currentLocaleName}\n </span>\n </div>\n <span className=\"text-neutral text-sm\">\n {localeItem.toUpperCase()}\n </span>\n </div>\n </div>\n </Button>\n </li>\n )\n )}\n </ol>\n </>\n )}\n </Container>\n </DropDown.Panel>\n </DropDown>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"LocaleSwitcher.mjs","names":[],"sources":["../../../../src/components/LocaleSwitcherDropDown/LocaleSwitcher.tsx"],"sourcesContent":["'use client';\n\nimport { getHTMLTextDir, getLocaleName } from '@intlayer/core/localization';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport { ENGLISH } from '@intlayer/types/locales';\nimport Fuse, { type IFuseOptions } from 'fuse.js';\nimport { MoveVertical } from 'lucide-react';\nimport { type FC, useCallback, useMemo, useRef, useState } from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport { Button, ButtonColor, ButtonTextAlign, ButtonVariant } from '../Button';\nimport { Container } from '../Container';\nimport { DropDown, type PanelProps } from '../DropDown';\nimport { Input } from '../Input';\n\nexport type LocaleSwitcherProps = {\n locale?: Locale;\n localeList: Locale[];\n availableLocales?: Locale[];\n fullLocaleName?: boolean;\n setLocale: (locale: Locale) => void;\n panelProps?: Omit<PanelProps, 'identifier'>;\n};\n\nconst DROPDOWN_IDENTIFIER = 'locale-switcher';\n\ntype MultilingualAvailableLocales = {\n locale: Locale;\n englishName: string;\n currentLocaleName: string;\n ownLocaleName: string;\n};\n\nexport const LocaleSwitcher: FC<LocaleSwitcherProps> = ({\n locale,\n localeList,\n availableLocales,\n fullLocaleName = true,\n setLocale,\n panelProps,\n}) => {\n let localeName = 'Select a locale';\n const { switchTo, searchInput, languageListLabel, localeSwitcherLabel } =\n useIntlayer('locale-switcher');\n const inputRef = useRef<HTMLInputElement>(null);\n\n const multilingualAvailableLocales: MultilingualAvailableLocales[] = useMemo(\n () =>\n localeList.map((localeEl) => {\n const englishName = getLocaleName(localeEl, ENGLISH);\n const currentLocaleName = getLocaleName(localeEl, locale);\n const ownLocaleName = getLocaleName(localeEl);\n return {\n locale: localeEl,\n englishName,\n currentLocaleName,\n ownLocaleName,\n };\n }),\n [localeList, locale]\n );\n\n const [results, setResults] = useState<MultilingualAvailableLocales[]>(\n multilingualAvailableLocales\n );\n\n // Create a new Fuse instance with the options and documentation data\n const fuse = useMemo(() => {\n const fuseOptions: IFuseOptions<MultilingualAvailableLocales> = {\n keys: [\n { name: 'ownLocaleName', weight: 0.4 },\n { name: 'englishName', weight: 0.2 },\n { name: 'currentLocaleName', weight: 0.2 },\n { name: 'locale', weight: 0.2 },\n ],\n threshold: 0.02, // Defines how fuzzy the matching should be (lower is more strict)\n };\n\n return new Fuse(multilingualAvailableLocales, fuseOptions);\n }, [multilingualAvailableLocales]);\n\n const handleSearch = useCallback(\n (searchQuery: string) => {\n if (searchQuery) {\n // Perform search on every input change\n const searchResults = fuse\n .search(searchQuery)\n .map((result) => result.item);\n setResults(searchResults);\n } else {\n setResults(multilingualAvailableLocales);\n }\n },\n [fuse, multilingualAvailableLocales]\n );\n\n if (locale) {\n localeName = fullLocaleName ? getLocaleName(locale) : locale.toUpperCase();\n }\n\n return (\n <nav\n className=\"rounded-xl border border-text\"\n aria-label={localeSwitcherLabel.value}\n >\n <DropDown identifier={DROPDOWN_IDENTIFIER}>\n <DropDown.Trigger identifier={DROPDOWN_IDENTIFIER} color=\"text\">\n <div className=\"flex w-full items-center justify-between\">\n <div className=\"text-nowrap px-2\">{localeName}</div>\n <MoveVertical className=\"w-5 self-center\" />\n </div>\n </DropDown.Trigger>\n\n <DropDown.Panel\n identifier={DROPDOWN_IDENTIFIER}\n isOverable\n isFocusable\n align=\"end\"\n {...panelProps}\n >\n <Container\n className=\"max-h-[80vh] min-w-28\"\n separator=\"y\"\n role=\"listbox\"\n transparency=\"xs\"\n aria-label={languageListLabel.value}\n >\n <div className=\"p-3\">\n <Input\n type=\"search\"\n aria-label={searchInput.ariaLabel.value}\n placeholder={searchInput.placeholder.value}\n onChange={(e) => handleSearch(e.target.value)}\n ref={inputRef}\n />\n </div>\n <ol className=\"divide-y divide-dashed divide-text/20 overflow-y-auto p-1\">\n {results.map(\n ({ locale: localeItem, currentLocaleName, ownLocaleName }) => (\n <li className=\"px-1.5 py-1\" key={localeItem}>\n <Button\n onClick={() => setLocale(localeItem)}\n label={`${switchTo} ${currentLocaleName}`}\n disabled={\n !(availableLocales ?? localeList).includes(localeItem)\n }\n isActive={locale === localeItem}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n isFullWidth\n textAlign={ButtonTextAlign.LEFT}\n >\n <div className=\"flex flex-row items-center justify-between gap-3 px-2 py-1\">\n <div className=\"flex flex-col text-nowrap\">\n <span\n dir={getHTMLTextDir(localeItem)}\n lang={localeItem}\n suppressHydrationWarning\n >\n {ownLocaleName}\n </span>\n <span\n className=\"text-neutral text-xs\"\n suppressHydrationWarning\n >\n {currentLocaleName}\n </span>\n </div>\n <span className=\"text-neutral text-sm\">\n {localeItem.toUpperCase()}\n </span>\n </div>\n </Button>\n </li>\n )\n )}\n </ol>\n </Container>\n </DropDown.Panel>\n </DropDown>\n </nav>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;AAuBA,MAAM,sBAAsB;AAS5B,MAAa,kBAA2C,EACtD,QACA,YACA,kBACA,iBAAiB,MACjB,WACA,iBACI;CACJ,IAAI,aAAa;CACjB,MAAM,EAAE,UAAU,aAAa,mBAAmB,wBAChD,YAAY,kBAAkB;CAChC,MAAM,WAAW,OAAyB,KAAK;CAE/C,MAAM,+BAA+D,cAEjE,WAAW,KAAK,aAAa;AAI3B,SAAO;GACL,QAAQ;GACR,aALkB,cAAc,UAAU,QAAQ;GAMlD,mBALwB,cAAc,UAAU,OAAO;GAMvD,eALoB,cAAc,SAAS;GAM5C;GACD,EACJ,CAAC,YAAY,OAAO,CACrB;CAED,MAAM,CAAC,SAAS,cAAc,SAC5B,6BACD;CAGD,MAAM,OAAO,cAAc;AAWzB,SAAO,IAAI,KAAK,8BAVgD;GAC9D,MAAM;IACJ;KAAE,MAAM;KAAiB,QAAQ;KAAK;IACtC;KAAE,MAAM;KAAe,QAAQ;KAAK;IACpC;KAAE,MAAM;KAAqB,QAAQ;KAAK;IAC1C;KAAE,MAAM;KAAU,QAAQ;KAAK;IAChC;GACD,WAAW;GACZ,CAEyD;IACzD,CAAC,6BAA6B,CAAC;CAElC,MAAM,eAAe,aAClB,gBAAwB;AACvB,MAAI,YAKF,YAHsB,KACnB,OAAO,YAAY,CACnB,KAAK,WAAW,OAAO,KAAK,CACN;MAEzB,YAAW,6BAA6B;IAG5C,CAAC,MAAM,6BAA6B,CACrC;AAED,KAAI,OACF,cAAa,iBAAiB,cAAc,OAAO,GAAG,OAAO,aAAa;AAG5E,QACE,oBAAC,OAAD;EACE,WAAU;EACV,cAAY,oBAAoB;YAEhC,qBAAC,UAAD;GAAU,YAAY;aAAtB,CACE,oBAAC,SAAS,SAAV;IAAkB,YAAY;IAAqB,OAAM;cACvD,qBAAC,OAAD;KAAK,WAAU;eAAf,CACE,oBAAC,OAAD;MAAK,WAAU;gBAAoB;MAAiB,GACpD,oBAAC,cAAD,EAAc,WAAU,mBAAoB,EACxC;;IACW,GAEnB,oBAAC,SAAS,OAAV;IACE,YAAY;IACZ;IACA;IACA,OAAM;IACN,GAAI;cAEJ,qBAAC,WAAD;KACE,WAAU;KACV,WAAU;KACV,MAAK;KACL,cAAa;KACb,cAAY,kBAAkB;eALhC,CAOE,oBAAC,OAAD;MAAK,WAAU;gBACb,oBAAC,OAAD;OACE,MAAK;OACL,cAAY,YAAY,UAAU;OAClC,aAAa,YAAY,YAAY;OACrC,WAAW,MAAM,aAAa,EAAE,OAAO,MAAM;OAC7C,KAAK;OACL;MACE,GACN,oBAAC,MAAD;MAAI,WAAU;gBACX,QAAQ,KACN,EAAE,QAAQ,YAAY,mBAAmB,oBACxC,oBAAC,MAAD;OAAI,WAAU;iBACZ,oBAAC,QAAD;QACE,eAAe,UAAU,WAAW;QACpC,OAAO,GAAG,SAAS,GAAG;QACtB,UACE,EAAE,oBAAoB,YAAY,SAAS,WAAW;QAExD,UAAU,WAAW;QACrB;QACA;QACA;QACA;kBAEA,qBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,qBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,oBAAC,QAAD;WACE,KAAK,eAAe,WAAW;WAC/B,MAAM;WACN;qBAEC;WACI,GACP,oBAAC,QAAD;WACE,WAAU;WACV;qBAEC;WACI,EACH;aACN,oBAAC,QAAD;UAAM,WAAU;oBACb,WAAW,aAAa;UACpB,EACH;;QACC;OACN,EAlC4B,WAkC5B,CAER;MACE,EACK;;IACG,EACR;;EACP"}
1
+ {"version":3,"file":"LocaleSwitcher.mjs","names":[],"sources":["../../../../src/components/LocaleSwitcherDropDown/LocaleSwitcher.tsx"],"sourcesContent":["'use client';\n\nimport { getHTMLTextDir, getLocaleName } from '@intlayer/core/localization';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport { ENGLISH } from '@intlayer/types/locales';\nimport Fuse, { type IFuseOptions } from 'fuse.js';\nimport { MoveVertical } from 'lucide-react';\nimport { type FC, useCallback, useMemo, useRef, useState } from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport { Button, ButtonColor, ButtonTextAlign, ButtonVariant } from '../Button';\nimport { Container } from '../Container';\nimport { DropDown, type PanelProps } from '../DropDown';\nimport { Input } from '../Input';\n\nexport type LocaleSwitcherProps = {\n locale?: Locale;\n localeList: Locale[];\n availableLocales?: Locale[];\n fullLocaleName?: boolean;\n setLocale: (locale: Locale) => void;\n panelProps?: Omit<PanelProps, 'identifier'>;\n};\n\nconst DROPDOWN_IDENTIFIER = 'locale-switcher';\n\ntype MultilingualAvailableLocales = {\n locale: Locale;\n englishName: string;\n currentLocaleName: string;\n ownLocaleName: string;\n};\n\nexport const LocaleSwitcher: FC<LocaleSwitcherProps> = ({\n locale,\n localeList,\n availableLocales,\n fullLocaleName = true,\n setLocale,\n panelProps,\n}) => {\n let localeName = 'Select a locale';\n const { switchTo, searchInput, languageListLabel, localeSwitcherLabel } =\n useIntlayer('locale-switcher');\n const inputRef = useRef<HTMLInputElement>(null);\n\n const multilingualAvailableLocales: MultilingualAvailableLocales[] = useMemo(\n () =>\n localeList.map((localeEl) => {\n const englishName = getLocaleName(localeEl, ENGLISH);\n const currentLocaleName = getLocaleName(localeEl, locale);\n const ownLocaleName = getLocaleName(localeEl);\n return {\n locale: localeEl,\n englishName,\n currentLocaleName,\n ownLocaleName,\n };\n }),\n [localeList, locale]\n );\n\n const [results, setResults] = useState<MultilingualAvailableLocales[]>(\n multilingualAvailableLocales\n );\n\n // Create a new Fuse instance with the options and documentation data\n const fuse = useMemo(() => {\n const fuseOptions: IFuseOptions<MultilingualAvailableLocales> = {\n keys: [\n { name: 'ownLocaleName', weight: 0.4 },\n { name: 'englishName', weight: 0.2 },\n { name: 'currentLocaleName', weight: 0.2 },\n { name: 'locale', weight: 0.2 },\n ],\n threshold: 0.02, // Defines how fuzzy the matching should be (lower is more strict)\n };\n\n return new Fuse(multilingualAvailableLocales, fuseOptions);\n }, [multilingualAvailableLocales]);\n\n const handleSearch = useCallback(\n (searchQuery: string) => {\n if (searchQuery) {\n // Perform search on every input change\n const searchResults = fuse\n .search(searchQuery)\n .map((result) => result.item);\n setResults(searchResults);\n } else {\n setResults(multilingualAvailableLocales);\n }\n },\n [fuse, multilingualAvailableLocales]\n );\n\n if (locale) {\n localeName = fullLocaleName ? getLocaleName(locale) : locale.toUpperCase();\n }\n\n return (\n <nav\n className=\"rounded-xl border border-text\"\n aria-label={localeSwitcherLabel.value}\n >\n <DropDown identifier={DROPDOWN_IDENTIFIER}>\n <DropDown.Trigger identifier={DROPDOWN_IDENTIFIER} color=\"text\">\n <div className=\"flex w-full items-center justify-between\">\n <div className=\"text-nowrap px-2\">{localeName}</div>\n <MoveVertical className=\"w-5 self-center\" />\n </div>\n </DropDown.Trigger>\n\n <DropDown.Panel\n identifier={DROPDOWN_IDENTIFIER}\n isOverable\n isFocusable\n align=\"end\"\n {...panelProps}\n >\n <Container\n className=\"max-h-[80vh] min-w-28\"\n separator=\"y\"\n role=\"listbox\"\n transparency=\"xs\"\n aria-label={languageListLabel.value}\n >\n <div className=\"p-3\">\n <Input\n type=\"search\"\n aria-label={searchInput.ariaLabel.value}\n placeholder={searchInput.placeholder.value}\n onChange={(e) => handleSearch(e.target.value)}\n ref={inputRef}\n />\n </div>\n <ol className=\"divide-y divide-dashed divide-text/20 overflow-y-auto p-1\">\n {results.map(\n ({ locale: localeItem, currentLocaleName, ownLocaleName }) => (\n <li className=\"px-1.5 py-1\" key={localeItem}>\n <Button\n onClick={() => setLocale(localeItem)}\n label={`${switchTo} ${currentLocaleName}`}\n disabled={\n !(availableLocales ?? localeList).includes(localeItem)\n }\n isActive={locale === localeItem}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n isFullWidth\n textAlign={ButtonTextAlign.LEFT}\n >\n <div className=\"flex flex-row items-center justify-between gap-3 px-2 py-1\">\n <div className=\"flex flex-col text-nowrap\">\n <span\n dir={getHTMLTextDir(localeItem)}\n lang={localeItem}\n suppressHydrationWarning\n >\n {ownLocaleName}\n </span>\n <span\n className=\"text-neutral text-xs\"\n suppressHydrationWarning\n >\n {currentLocaleName}\n </span>\n </div>\n <span className=\"text-neutral text-sm\">\n {localeItem.toUpperCase()}\n </span>\n </div>\n </Button>\n </li>\n )\n )}\n </ol>\n </Container>\n </DropDown.Panel>\n </DropDown>\n </nav>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;AAuBA,MAAM,sBAAsB;AAS5B,MAAa,kBAA2C,EACtD,QACA,YACA,kBACA,iBAAiB,MACjB,WACA,iBACI;CACJ,IAAI,aAAa;CACjB,MAAM,EAAE,UAAU,aAAa,mBAAmB,wBAChD,YAAY,kBAAkB;CAChC,MAAM,WAAW,OAAyB,KAAK;CAE/C,MAAM,+BAA+D,cAEjE,WAAW,KAAK,aAAa;AAI3B,SAAO;GACL,QAAQ;GACR,aALkB,cAAc,UAAU,QAK/B;GACX,mBALwB,cAAc,UAAU,OAK/B;GACjB,eALoB,cAAc,SAKrB;GACd;GACD,EACJ,CAAC,YAAY,OAAO,CACrB;CAED,MAAM,CAAC,SAAS,cAAc,SAC5B,6BACD;CAGD,MAAM,OAAO,cAAc;AAWzB,SAAO,IAAI,KAAK,8BAA8B;GAT5C,MAAM;IACJ;KAAE,MAAM;KAAiB,QAAQ;KAAK;IACtC;KAAE,MAAM;KAAe,QAAQ;KAAK;IACpC;KAAE,MAAM;KAAqB,QAAQ;KAAK;IAC1C;KAAE,MAAM;KAAU,QAAQ;KAAK;IAChC;GACD,WAAW;GAG4C,CAAC;IACzD,CAAC,6BAA6B,CAAC;CAElC,MAAM,eAAe,aAClB,gBAAwB;AACvB,MAAI,YAKF,YAHsB,KACnB,OAAO,YAAY,CACnB,KAAK,WAAW,OAAO,KACF,CAAC;MAEzB,YAAW,6BAA6B;IAG5C,CAAC,MAAM,6BAA6B,CACrC;AAED,KAAI,OACF,cAAa,iBAAiB,cAAc,OAAO,GAAG,OAAO,aAAa;AAG5E,QACE,oBAAC,OAAD;EACE,WAAU;EACV,cAAY,oBAAoB;YAEhC,qBAAC,UAAD;GAAU,YAAY;aAAtB,CACE,oBAAC,SAAS,SAAV;IAAkB,YAAY;IAAqB,OAAM;cACvD,qBAAC,OAAD;KAAK,WAAU;eAAf,CACE,oBAAC,OAAD;MAAK,WAAU;gBAAoB;MAAiB,GACpD,oBAAC,cAAD,EAAc,WAAU,mBAAoB,EACxC;;IACW,GAEnB,oBAAC,SAAS,OAAV;IACE,YAAY;IACZ;IACA;IACA,OAAM;IACN,GAAI;cAEJ,qBAAC,WAAD;KACE,WAAU;KACV,WAAU;KACV,MAAK;KACL,cAAa;KACb,cAAY,kBAAkB;eALhC,CAOE,oBAAC,OAAD;MAAK,WAAU;gBACb,oBAAC,OAAD;OACE,MAAK;OACL,cAAY,YAAY,UAAU;OAClC,aAAa,YAAY,YAAY;OACrC,WAAW,MAAM,aAAa,EAAE,OAAO,MAAM;OAC7C,KAAK;OACL;MACE,GACN,oBAAC,MAAD;MAAI,WAAU;gBACX,QAAQ,KACN,EAAE,QAAQ,YAAY,mBAAmB,oBACxC,oBAAC,MAAD;OAAI,WAAU;iBACZ,oBAAC,QAAD;QACE,eAAe,UAAU,WAAW;QACpC,OAAO,GAAG,SAAS,GAAG;QACtB,UACE,EAAE,oBAAoB,YAAY,SAAS,WAAW;QAExD,UAAU,WAAW;QACrB;QACA;QACA;QACA;kBAEA,qBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,qBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,oBAAC,QAAD;WACE,KAAK,eAAe,WAAW;WAC/B,MAAM;WACN;qBAEC;WACI,GACP,oBAAC,QAAD;WACE,WAAU;WACV;qBAEC;WACI,EACH;aACN,oBAAC,QAAD;UAAM,WAAU;oBACb,WAAW,aAAa;UACpB,EACH;;QACC;OACN,EAlC4B,WAkC5B,CAER;MACE,EACK;;IACG,EACR;;EACP"}
@@ -0,0 +1,101 @@
1
+ 'use client';
2
+
3
+ import { cn } from "../../utils/cn.mjs";
4
+ import { Container } from "../Container/index.mjs";
5
+ import { Button, ButtonSize, ButtonVariant } from "../Button/Button.mjs";
6
+ import { Link } from "../Link/Link.mjs";
7
+ import { Modal, ModalSize } from "../Modal/Modal.mjs";
8
+ import { useState } from "react";
9
+ import { MoveDiagonal } from "lucide-react";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+
12
+ //#region src/components/MarkDownRender/MarkDownIframe.tsx
13
+ function embedLinkMeta(src) {
14
+ if (!src) return {
15
+ href: "",
16
+ label: ""
17
+ };
18
+ if (/^https?:\/\//i.test(src)) try {
19
+ const url = new URL(src);
20
+ return {
21
+ href: url.href,
22
+ label: url.host
23
+ };
24
+ } catch {
25
+ return {
26
+ href: src,
27
+ label: src
28
+ };
29
+ }
30
+ return {
31
+ href: src,
32
+ label: src
33
+ };
34
+ }
35
+ const MarkDownIframe = (props) => {
36
+ const { src, className, title, ...rest } = props;
37
+ const [isModalOpen, setIsModalOpen] = useState(false);
38
+ const { href, label } = embedLinkMeta(src);
39
+ return /* @__PURE__ */ jsxs(Container, {
40
+ roundedSize: "2xl",
41
+ border: true,
42
+ borderColor: "neutral",
43
+ className: "overflow-hidden p-0",
44
+ gap: "none",
45
+ children: [
46
+ /* @__PURE__ */ jsx("iframe", {
47
+ ...rest,
48
+ src,
49
+ title,
50
+ className: cn("block max-h-[80vh] min-h-[12rem] w-full border-0", className)
51
+ }),
52
+ /* @__PURE__ */ jsxs("div", {
53
+ className: "flex items-center justify-between gap-3 border-neutral/30 border-t bg-card/40 px-3 py-1",
54
+ children: [href ? /* @__PURE__ */ jsx(Link, {
55
+ href,
56
+ target: "_blank",
57
+ rel: "noopener noreferrer",
58
+ label: "",
59
+ color: "neutral",
60
+ className: "inline-flex min-w-0 max-w-[calc(100%-3rem)] items-center gap-2 text-neutral text-xs underline-offset-2 hover:text-text hover:underline",
61
+ children: label
62
+ }) : /* @__PURE__ */ jsx("span", {
63
+ className: "text-neutral text-sm",
64
+ children: "Embedded frame"
65
+ }), /* @__PURE__ */ jsx(Button, {
66
+ variant: "hoverable",
67
+ size: "icon-md",
68
+ onClick: () => setIsModalOpen(true),
69
+ label: "Open embedded page in fullscreen",
70
+ Icon: MoveDiagonal
71
+ })]
72
+ }),
73
+ /* @__PURE__ */ jsx(Modal, {
74
+ isOpen: isModalOpen,
75
+ onClose: () => setIsModalOpen(false),
76
+ size: "unset",
77
+ hasCloseButton: true,
78
+ isScrollable: true,
79
+ padding: "sm",
80
+ children: isModalOpen && src ? /* @__PURE__ */ jsx(Container, {
81
+ roundedSize: "2xl",
82
+ border: true,
83
+ borderColor: "neutral",
84
+ className: "overflow-hidden p-0",
85
+ gap: "none",
86
+ children: /* @__PURE__ */ jsx("iframe", {
87
+ ...rest,
88
+ src,
89
+ title: title ?? "Embedded content",
90
+ allowFullScreen: true,
91
+ className: "block min-h-[82vh] w-full border-0"
92
+ })
93
+ }) : null
94
+ })
95
+ ]
96
+ });
97
+ };
98
+
99
+ //#endregion
100
+ export { MarkDownIframe };
101
+ //# sourceMappingURL=MarkDownIframe.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkDownIframe.mjs","names":[],"sources":["../../../../src/components/MarkDownRender/MarkDownIframe.tsx"],"sourcesContent":["'use client';\n\nimport { Button, ButtonSize, ButtonVariant } from '@components/Button';\nimport { Container } from '@components/Container';\nimport { Link } from '@components/Link';\nimport { Modal, ModalSize } from '@components/Modal';\nimport { cn } from '@utils/cn';\nimport { MoveDiagonal } from 'lucide-react';\nimport { type ComponentProps, type FC, useState } from 'react';\n\nfunction embedLinkMeta(src: string | undefined): {\n href: string;\n label: string;\n} {\n if (!src) return { href: '', label: '' };\n if (/^https?:\\/\\//i.test(src)) {\n try {\n const url = new URL(src);\n return { href: url.href, label: url.host };\n } catch {\n return { href: src, label: src };\n }\n }\n return { href: src, label: src };\n}\n\nexport const MarkDownIframe: FC<ComponentProps<'iframe'>> = (props) => {\n const { src, className, title, ...rest } = props;\n const [isModalOpen, setIsModalOpen] = useState(false);\n const { href, label } = embedLinkMeta(src);\n\n return (\n <Container\n roundedSize=\"2xl\"\n border\n borderColor=\"neutral\"\n className=\"overflow-hidden p-0\"\n gap=\"none\"\n >\n <iframe\n {...rest}\n src={src}\n title={title}\n className={cn(\n 'block max-h-[80vh] min-h-[12rem] w-full border-0',\n className\n )}\n />\n <div className=\"flex items-center justify-between gap-3 border-neutral/30 border-t bg-card/40 px-3 py-1\">\n {href ? (\n <Link\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n label=\"\"\n color=\"neutral\"\n className=\"inline-flex min-w-0 max-w-[calc(100%-3rem)] items-center gap-2 text-neutral text-xs underline-offset-2 hover:text-text hover:underline\"\n >\n {label}\n </Link>\n ) : (\n <span className=\"text-neutral text-sm\">Embedded frame</span>\n )}\n <Button\n variant={ButtonVariant.HOVERABLE}\n size={ButtonSize.ICON_MD}\n onClick={() => setIsModalOpen(true)}\n label=\"Open embedded page in fullscreen\"\n Icon={MoveDiagonal}\n />\n </div>\n\n <Modal\n isOpen={isModalOpen}\n onClose={() => setIsModalOpen(false)}\n size={ModalSize.UNSET}\n hasCloseButton\n isScrollable\n padding=\"sm\"\n >\n {isModalOpen && src ? (\n <Container\n roundedSize=\"2xl\"\n border\n borderColor=\"neutral\"\n className=\"overflow-hidden p-0\"\n gap=\"none\"\n >\n <iframe\n {...rest}\n src={src}\n title={title ?? 'Embedded content'}\n allowFullScreen\n className=\"block min-h-[82vh] w-full border-0\"\n />\n </Container>\n ) : null}\n </Modal>\n </Container>\n );\n};\n"],"mappings":";;;;;;;;;;;;AAUA,SAAS,cAAc,KAGrB;AACA,KAAI,CAAC,IAAK,QAAO;EAAE,MAAM;EAAI,OAAO;EAAI;AACxC,KAAI,gBAAgB,KAAK,IAAI,CAC3B,KAAI;EACF,MAAM,MAAM,IAAI,IAAI,IAAI;AACxB,SAAO;GAAE,MAAM,IAAI;GAAM,OAAO,IAAI;GAAM;SACpC;AACN,SAAO;GAAE,MAAM;GAAK,OAAO;GAAK;;AAGpC,QAAO;EAAE,MAAM;EAAK,OAAO;EAAK;;AAGlC,MAAa,kBAAgD,UAAU;CACrE,MAAM,EAAE,KAAK,WAAW,OAAO,GAAG,SAAS;CAC3C,MAAM,CAAC,aAAa,kBAAkB,SAAS,MAAM;CACrD,MAAM,EAAE,MAAM,UAAU,cAAc,IAAI;AAE1C,QACE,qBAAC,WAAD;EACE,aAAY;EACZ;EACA,aAAY;EACZ,WAAU;EACV,KAAI;YALN;GAOE,oBAAC,UAAD;IACE,GAAI;IACC;IACE;IACP,WAAW,GACT,oDACA,UACD;IACD;GACF,qBAAC,OAAD;IAAK,WAAU;cAAf,CACG,OACC,oBAAC,MAAD;KACQ;KACN,QAAO;KACP,KAAI;KACJ,OAAM;KACN,OAAM;KACN,WAAU;eAET;KACI,IAEP,oBAAC,QAAD;KAAM,WAAU;eAAuB;KAAqB,GAE9D,oBAAC,QAAD;KACE;KACA;KACA,eAAe,eAAe,KAAK;KACnC,OAAM;KACN,MAAM;KACN,EACE;;GAEN,oBAAC,OAAD;IACE,QAAQ;IACR,eAAe,eAAe,MAAM;IACpC;IACA;IACA;IACA,SAAQ;cAEP,eAAe,MACd,oBAAC,WAAD;KACE,aAAY;KACZ;KACA,aAAY;KACZ,WAAU;KACV,KAAI;eAEJ,oBAAC,UAAD;MACE,GAAI;MACC;MACL,OAAO,SAAS;MAChB;MACA,WAAU;MACV;KACQ,IACV;IACE;GACE"}
@@ -1,5 +1,4 @@
1
1
  import { cn } from "../../utils/cn.mjs";
2
- import { Container } from "../Container/index.mjs";
3
2
  import { Link } from "../Link/Link.mjs";
4
3
  import { H1, H2, H3, H4, H5, H6 } from "../Headers/index.mjs";
5
4
  import { CodeProvider } from "../IDE/CodeContext.mjs";
@@ -7,6 +6,7 @@ import { Code } from "../IDE/Code.mjs";
7
6
  import { TabProvider } from "../Tab/TabContext.mjs";
8
7
  import { Tab } from "../Tab/Tab.mjs";
9
8
  import { SmartTable } from "../Table/SmartTable.mjs";
9
+ import { MarkDownIframe } from "./MarkDownIframe.mjs";
10
10
  import { memo } from "react";
11
11
  import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
12
12
  import { renderMarkdown } from "react-intlayer";
@@ -133,14 +133,7 @@ const ColumnRenderer = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
133
133
  className: cn("flex-1", className),
134
134
  ...props
135
135
  });
136
- const Iframe = (props) => /* @__PURE__ */ jsx(Container, {
137
- roundedSize: "2xl",
138
- border: true,
139
- background: "none",
140
- borderColor: "neutral",
141
- className: "overflow-hidden",
142
- children: /* @__PURE__ */ jsx("iframe", { ...props })
143
- });
136
+ const Iframe = (props) => /* @__PURE__ */ jsx(MarkDownIframe, { ...props });
144
137
  const staticMarkdownComponents = {
145
138
  h1: H1Renderer,
146
139
  h2: H2Renderer,
@@ -1 +1 @@
1
- {"version":3,"file":"MarkDownRender.mjs","names":[],"sources":["../../../../src/components/MarkDownRender/MarkDownRender.tsx"],"sourcesContent":["import { Container } from '@components/Container';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { cn } from '@utils/cn';\nimport type { ComponentProps, ComponentPropsWithoutRef, FC } from 'react';\nimport { memo } from 'react';\nimport {\n type MarkdownRenderer as MarkdownRendererIntlayer,\n renderMarkdown,\n} from 'react-intlayer';\nimport type { BundledLanguage } from 'shiki/bundle/web';\nimport { H1, H2, H3, H4, H5, H6 } from '../Headers';\nimport { Code } from '../IDE/Code';\nimport { CodeProvider } from '../IDE/CodeContext';\nimport { Link } from '../Link';\nimport { Tab } from '../Tab';\nimport { TabProvider } from '../Tab/TabContext';\nimport { SmartTable } from '../Table';\n\n// Extracted, stable component renderers\nconst H1Renderer = (props: ComponentProps<'h1'>) => (\n <H1 isClickable className=\"text-text\" {...props} />\n);\nconst H2Renderer = (props: ComponentProps<'h2'>) => (\n <H2 isClickable className=\"mt-16 text-text\" {...props} />\n);\nconst H3Renderer = (props: ComponentProps<'h3'>) => (\n <H3 isClickable className=\"mt-5 text-text\" {...props} />\n);\nconst H4Renderer = (props: ComponentProps<'h4'>) => (\n <H4 isClickable className=\"mt-3 text-text\" {...props} />\n);\nconst H5Renderer = (props: ComponentProps<'h5'>) => (\n <H5 isClickable className=\"mt-3 text-text\" {...props} />\n);\nconst H6Renderer = (props: ComponentProps<'h6'>) => (\n <H6 isClickable className=\"mt-3 text-text\" {...props} />\n);\nconst StrongRenderer = (props: ComponentProps<'strong'>) => (\n <strong className=\"text-text\" {...props} />\n);\n\nconst MemoizedCodeBlock = memo(\n ({\n className,\n children,\n isDarkMode,\n ...rest\n }: ComponentProps<'code'> & { isDarkMode?: boolean }) => {\n const content = String(children ?? '').replace(/\\n$/, '');\n const isBlock = !!className;\n\n if (!isBlock) {\n const decodedContent = content.replace(\n /&(?:amp;)?#(\\d+);/g,\n (_, code: string) => String.fromCharCode(parseInt(code, 10))\n );\n return (\n <code className=\"rounded-md border border-neutral/30 bg-card/60 box-decoration-clone px-1.5 py-0.5 font-mono text-sm\">\n {decodedContent}\n </code>\n );\n }\n\n const language = (className?.replace(/lang(?:uage)?-/, '') ||\n 'plaintext') as BundledLanguage;\n\n return (\n <Code {...rest} language={language} showHeader isDarkMode={isDarkMode}>\n {content}\n </Code>\n );\n },\n (prevProps, nextProps) =>\n prevProps.children === nextProps.children &&\n prevProps.className === nextProps.className &&\n prevProps.isDarkMode === nextProps.isDarkMode\n);\n\nconst createCodeRenderer = (isDarkMode?: boolean) => {\n return function CodeWrapper(props: ComponentProps<'code'>) {\n return <MemoizedCodeBlock {...props} isDarkMode={isDarkMode} />;\n };\n};\n\nconst BlockquoteRenderer = ({\n className,\n ...props\n}: ComponentProps<'blockquote'>) => (\n <blockquote\n className={cn(\n 'mt-5 gap-3 border-card border-l-4 pl-5 text-neutral [&_strong]:text-neutral',\n className\n )}\n {...props}\n />\n);\n\nconst UlRenderer = ({ className, ...props }: ComponentProps<'ul'>) => (\n <ul\n className={cn(\n 'mt-5 flex list-disc flex-col gap-3 pl-5 marker:text-neutral/80',\n className\n )}\n {...props}\n />\n);\n\nconst OlRenderer = ({ className, ...props }: ComponentProps<'ol'>) => (\n <ol\n className={cn(\n 'mt-5 flex list-decimal flex-col gap-3 pl-5 marker:text-neutral/80',\n className\n )}\n {...props}\n />\n);\n\nconst ImgRenderer = ({\n className,\n alt,\n src,\n ...props\n}: ComponentProps<'img'>) => (\n <img\n {...props}\n alt={alt ?? ''}\n loading=\"lazy\"\n className={cn('max-h-[80vh] max-w-full rounded-md', className)}\n src={\n src?.includes('github.com')\n ? src\n ?.replace('github.com', 'raw.githubusercontent.com')\n .replace('/blob/', '/') // GitHub raw URLs do not use /blob/\n : src\n }\n />\n);\n\nconst createLinkRenderer = (locale?: LocalesValues) => {\n return (props: ComponentProps<'a'>) => (\n <Link\n isExternalLink={props.href?.startsWith('http')}\n underlined\n locale={locale}\n label=\"\"\n color=\"text\"\n {...(props as any)}\n />\n );\n};\n\nconst PreRenderer = (props: ComponentProps<'pre'>) => <>{props.children}</>;\nconst TableRenderer = (props: ComponentProps<typeof SmartTable>) => (\n <SmartTable isRollable displayModal {...props} />\n);\nconst ThRenderer = ({ className, ...props }: ComponentProps<'th'>) => (\n <th\n className={cn('border-neutral border-b bg-neutral/10 p-4', className)}\n {...props}\n />\n);\nconst TrRenderer = ({ className, ...props }: ComponentProps<'tr'>) => (\n <tr className={cn('hover:/10 hover:bg-neutral/10', className)} {...props} />\n);\nconst TdRenderer = ({ className, ...props }: ComponentProps<'td'>) => (\n <td\n className={cn('border-neutral-500/50 border-b p-4', className)}\n {...props}\n />\n);\nconst HrRenderer = ({ className, ...props }: ComponentProps<'hr'>) => (\n <hr className={cn('mx-6 mt-16 text-neutral', className)} {...props} />\n);\n\nconst TabsRenderer = (props: ComponentProps<typeof Tab>) => (\n <Tab\n {...props}\n className=\"rounded-xl border border-card\"\n headerClassName=\"sticky rounded-xl top-24 z-5 bg-background/70 backdrop-blur overflow-x-auto\"\n />\n);\nconst ColumnsRenderer = ({\n className,\n ...props\n}: ComponentPropsWithoutRef<'div'>) => (\n <div className={cn('flex gap-4 max-md:flex-col', className)} {...props} />\n);\nconst ColumnRenderer = ({\n className,\n ...props\n}: ComponentPropsWithoutRef<'div'>) => (\n <div className={cn('flex-1', className)} {...props} />\n);\n\nconst Iframe = (props: ComponentProps<'iframe'>) => (\n <Container\n roundedSize=\"2xl\"\n border\n background=\"none\"\n borderColor=\"neutral\"\n className=\"overflow-hidden\"\n >\n <iframe {...props} />\n </Container>\n);\n\n// Static configuration object for static renderers\nconst staticMarkdownComponents = {\n h1: H1Renderer,\n h2: H2Renderer,\n h3: H3Renderer,\n h4: H4Renderer,\n h5: H5Renderer,\n h6: H6Renderer,\n strong: StrongRenderer,\n blockquote: BlockquoteRenderer,\n ul: UlRenderer,\n ol: OlRenderer,\n img: ImgRenderer,\n pre: PreRenderer,\n table: TableRenderer,\n th: ThRenderer,\n tr: TrRenderer,\n td: TdRenderer,\n hr: HrRenderer,\n Tabs: TabsRenderer,\n Tab: Tab.Item,\n Columns: ColumnsRenderer,\n Column: ColumnRenderer,\n iframe: Iframe,\n};\n\n// Factory function to create components with dynamic props\nconst createMarkdownComponents = (\n isDarkMode?: boolean,\n locale?: LocalesValues\n) => ({\n ...staticMarkdownComponents,\n code: createCodeRenderer(isDarkMode),\n a: createLinkRenderer(locale),\n});\n\n// Export static renderers for backward compatibility\nexport const baseMarkdownComponents = staticMarkdownComponents;\n\ntype MarkdownRendererProps = {\n children: string;\n isDarkMode?: boolean;\n locale?: LocalesValues;\n forceBlock?: boolean;\n preserveFrontmatter?: boolean;\n tagfilter?: boolean;\n components?: ComponentProps<typeof MarkdownRendererIntlayer>['components'];\n wrapper?: ComponentProps<typeof MarkdownRendererIntlayer>['wrapper'];\n};\n\nexport const getIntlayerMarkdownOptions = (_isDarkMode?: boolean) => ({\n components: baseMarkdownComponents,\n});\n\nexport const MarkdownRenderer: FC<MarkdownRendererProps> = ({\n children,\n isDarkMode = false,\n locale,\n forceBlock,\n preserveFrontmatter,\n tagfilter,\n components: componentsProp,\n wrapper,\n}) => {\n const markdownComponents = createMarkdownComponents(isDarkMode, locale);\n\n const markdownContent = renderMarkdown(children, {\n components: {\n ...markdownComponents,\n ...componentsProp,\n },\n wrapper,\n forceBlock,\n preserveFrontmatter,\n tagfilter,\n });\n\n return (\n <CodeProvider>\n <TabProvider>{markdownContent}</TabProvider>\n </CodeProvider>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"MarkDownRender.mjs","names":[],"sources":["../../../../src/components/MarkDownRender/MarkDownRender.tsx"],"sourcesContent":["import type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { cn } from '@utils/cn';\nimport type { ComponentProps, ComponentPropsWithoutRef, FC } from 'react';\nimport { memo } from 'react';\nimport {\n type MarkdownRenderer as MarkdownRendererIntlayer,\n renderMarkdown,\n} from 'react-intlayer';\nimport type { BundledLanguage } from 'shiki/bundle/web';\nimport { H1, H2, H3, H4, H5, H6 } from '../Headers';\nimport { Code } from '../IDE/Code';\nimport { CodeProvider } from '../IDE/CodeContext';\nimport { Link } from '../Link';\nimport { Tab } from '../Tab';\nimport { TabProvider } from '../Tab/TabContext';\nimport { SmartTable } from '../Table';\nimport { MarkDownIframe } from './MarkDownIframe';\n\n// Extracted, stable component renderers\nconst H1Renderer = (props: ComponentProps<'h1'>) => (\n <H1 isClickable className=\"text-text\" {...props} />\n);\nconst H2Renderer = (props: ComponentProps<'h2'>) => (\n <H2 isClickable className=\"mt-16 text-text\" {...props} />\n);\nconst H3Renderer = (props: ComponentProps<'h3'>) => (\n <H3 isClickable className=\"mt-5 text-text\" {...props} />\n);\nconst H4Renderer = (props: ComponentProps<'h4'>) => (\n <H4 isClickable className=\"mt-3 text-text\" {...props} />\n);\nconst H5Renderer = (props: ComponentProps<'h5'>) => (\n <H5 isClickable className=\"mt-3 text-text\" {...props} />\n);\nconst H6Renderer = (props: ComponentProps<'h6'>) => (\n <H6 isClickable className=\"mt-3 text-text\" {...props} />\n);\nconst StrongRenderer = (props: ComponentProps<'strong'>) => (\n <strong className=\"text-text\" {...props} />\n);\n\nconst MemoizedCodeBlock = memo(\n ({\n className,\n children,\n isDarkMode,\n ...rest\n }: ComponentProps<'code'> & { isDarkMode?: boolean }) => {\n const content = String(children ?? '').replace(/\\n$/, '');\n const isBlock = !!className;\n\n if (!isBlock) {\n const decodedContent = content.replace(\n /&(?:amp;)?#(\\d+);/g,\n (_, code: string) => String.fromCharCode(parseInt(code, 10))\n );\n return (\n <code className=\"rounded-md border border-neutral/30 bg-card/60 box-decoration-clone px-1.5 py-0.5 font-mono text-sm\">\n {decodedContent}\n </code>\n );\n }\n\n const language = (className?.replace(/lang(?:uage)?-/, '') ||\n 'plaintext') as BundledLanguage;\n\n return (\n <Code {...rest} language={language} showHeader isDarkMode={isDarkMode}>\n {content}\n </Code>\n );\n },\n (prevProps, nextProps) =>\n prevProps.children === nextProps.children &&\n prevProps.className === nextProps.className &&\n prevProps.isDarkMode === nextProps.isDarkMode\n);\n\nconst createCodeRenderer = (isDarkMode?: boolean) => {\n return function CodeWrapper(props: ComponentProps<'code'>) {\n return <MemoizedCodeBlock {...props} isDarkMode={isDarkMode} />;\n };\n};\n\nconst BlockquoteRenderer = ({\n className,\n ...props\n}: ComponentProps<'blockquote'>) => (\n <blockquote\n className={cn(\n 'mt-5 gap-3 border-card border-l-4 pl-5 text-neutral [&_strong]:text-neutral',\n className\n )}\n {...props}\n />\n);\n\nconst UlRenderer = ({ className, ...props }: ComponentProps<'ul'>) => (\n <ul\n className={cn(\n 'mt-5 flex list-disc flex-col gap-3 pl-5 marker:text-neutral/80',\n className\n )}\n {...props}\n />\n);\n\nconst OlRenderer = ({ className, ...props }: ComponentProps<'ol'>) => (\n <ol\n className={cn(\n 'mt-5 flex list-decimal flex-col gap-3 pl-5 marker:text-neutral/80',\n className\n )}\n {...props}\n />\n);\n\nconst ImgRenderer = ({\n className,\n alt,\n src,\n ...props\n}: ComponentProps<'img'>) => (\n <img\n {...props}\n alt={alt ?? ''}\n loading=\"lazy\"\n className={cn('max-h-[80vh] max-w-full rounded-md', className)}\n src={\n src?.includes('github.com')\n ? src\n ?.replace('github.com', 'raw.githubusercontent.com')\n .replace('/blob/', '/') // GitHub raw URLs do not use /blob/\n : src\n }\n />\n);\n\nconst createLinkRenderer = (locale?: LocalesValues) => {\n return (props: ComponentProps<'a'>) => (\n <Link\n isExternalLink={props.href?.startsWith('http')}\n underlined\n locale={locale}\n label=\"\"\n color=\"text\"\n {...(props as any)}\n />\n );\n};\n\nconst PreRenderer = (props: ComponentProps<'pre'>) => <>{props.children}</>;\nconst TableRenderer = (props: ComponentProps<typeof SmartTable>) => (\n <SmartTable isRollable displayModal {...props} />\n);\nconst ThRenderer = ({ className, ...props }: ComponentProps<'th'>) => (\n <th\n className={cn('border-neutral border-b bg-neutral/10 p-4', className)}\n {...props}\n />\n);\nconst TrRenderer = ({ className, ...props }: ComponentProps<'tr'>) => (\n <tr className={cn('hover:/10 hover:bg-neutral/10', className)} {...props} />\n);\nconst TdRenderer = ({ className, ...props }: ComponentProps<'td'>) => (\n <td\n className={cn('border-neutral-500/50 border-b p-4', className)}\n {...props}\n />\n);\nconst HrRenderer = ({ className, ...props }: ComponentProps<'hr'>) => (\n <hr className={cn('mx-6 mt-16 text-neutral', className)} {...props} />\n);\n\nconst TabsRenderer = (props: ComponentProps<typeof Tab>) => (\n <Tab\n {...props}\n className=\"rounded-xl border border-card\"\n headerClassName=\"sticky rounded-xl top-24 z-5 bg-background/70 backdrop-blur overflow-x-auto\"\n />\n);\nconst ColumnsRenderer = ({\n className,\n ...props\n}: ComponentPropsWithoutRef<'div'>) => (\n <div className={cn('flex gap-4 max-md:flex-col', className)} {...props} />\n);\nconst ColumnRenderer = ({\n className,\n ...props\n}: ComponentPropsWithoutRef<'div'>) => (\n <div className={cn('flex-1', className)} {...props} />\n);\n\nconst Iframe = (props: ComponentProps<'iframe'>) => (\n <MarkDownIframe {...props} />\n);\n\n// Static configuration object for static renderers\nconst staticMarkdownComponents = {\n h1: H1Renderer,\n h2: H2Renderer,\n h3: H3Renderer,\n h4: H4Renderer,\n h5: H5Renderer,\n h6: H6Renderer,\n strong: StrongRenderer,\n blockquote: BlockquoteRenderer,\n ul: UlRenderer,\n ol: OlRenderer,\n img: ImgRenderer,\n pre: PreRenderer,\n table: TableRenderer,\n th: ThRenderer,\n tr: TrRenderer,\n td: TdRenderer,\n hr: HrRenderer,\n Tabs: TabsRenderer,\n Tab: Tab.Item,\n Columns: ColumnsRenderer,\n Column: ColumnRenderer,\n iframe: Iframe,\n};\n\n// Factory function to create components with dynamic props\nconst createMarkdownComponents = (\n isDarkMode?: boolean,\n locale?: LocalesValues\n) => ({\n ...staticMarkdownComponents,\n code: createCodeRenderer(isDarkMode),\n a: createLinkRenderer(locale),\n});\n\n// Export static renderers for backward compatibility\nexport const baseMarkdownComponents = staticMarkdownComponents;\n\ntype MarkdownRendererProps = {\n children: string;\n isDarkMode?: boolean;\n locale?: LocalesValues;\n forceBlock?: boolean;\n preserveFrontmatter?: boolean;\n tagfilter?: boolean;\n components?: ComponentProps<typeof MarkdownRendererIntlayer>['components'];\n wrapper?: ComponentProps<typeof MarkdownRendererIntlayer>['wrapper'];\n};\n\nexport const getIntlayerMarkdownOptions = (_isDarkMode?: boolean) => ({\n components: baseMarkdownComponents,\n});\n\nexport const MarkdownRenderer: FC<MarkdownRendererProps> = ({\n children,\n isDarkMode = false,\n locale,\n forceBlock,\n preserveFrontmatter,\n tagfilter,\n components: componentsProp,\n wrapper,\n}) => {\n const markdownComponents = createMarkdownComponents(isDarkMode, locale);\n\n const markdownContent = renderMarkdown(children, {\n components: {\n ...markdownComponents,\n ...componentsProp,\n },\n wrapper,\n forceBlock,\n preserveFrontmatter,\n tagfilter,\n });\n\n return (\n <CodeProvider>\n <TabProvider>{markdownContent}</TabProvider>\n </CodeProvider>\n );\n};\n"],"mappings":"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"}
@@ -1,11 +1,11 @@
1
1
  'use client';
2
2
 
3
3
  import { cn } from "../../utils/cn.mjs";
4
+ import { useGetElementOrWindow } from "../../hooks/useGetElementOrWindow.mjs";
5
+ import { useScrollBlockage } from "../../hooks/useScrollBlockage/index.mjs";
4
6
  import { Container } from "../Container/index.mjs";
5
7
  import { Button, ButtonColor, ButtonSize, ButtonVariant } from "../Button/Button.mjs";
6
8
  import { H3 } from "../Headers/index.mjs";
7
- import { useGetElementOrWindow } from "../../hooks/useGetElementOrWindow.mjs";
8
- import { useScrollBlockage } from "../../hooks/useScrollBlockage/index.mjs";
9
9
  import { useEffect } from "react";
10
10
  import { cva } from "class-variance-authority";
11
11
  import { X } from "lucide-react";
@@ -1,9 +1,9 @@
1
1
  'use client';
2
2
 
3
3
  import { cn } from "../../utils/cn.mjs";
4
- import { MaxHeightSmoother } from "../MaxHeightSmoother/index.mjs";
5
4
  import { useScrollBlockage } from "../../hooks/useScrollBlockage/index.mjs";
6
5
  import { useScrollDetection } from "../../hooks/useScrollDetection.mjs";
6
+ import { MaxHeightSmoother } from "../MaxHeightSmoother/index.mjs";
7
7
  import { Burger } from "./Burger.mjs";
8
8
  import { useRef, useState } from "react";
9
9
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,16 +1,14 @@
1
1
  'use client';
2
2
 
3
3
  import { useDevice } from "../../hooks/useDevice.mjs";
4
- import { useIsMounted } from "../../hooks/useIsMounted.mjs";
5
4
  import { DesktopNavbar } from "./DesktopNavbar.mjs";
6
5
  import { Burger } from "./Burger.mjs";
7
6
  import { MobileNavbar } from "./MobileNavbar.mjs";
8
- import { Fragment, jsx } from "react/jsx-runtime";
7
+ import { jsx } from "react/jsx-runtime";
9
8
 
10
9
  //#region src/components/Navbar/index.tsx
11
10
  const Navbar = ({ logo, mobileTopChildren, desktopSections = [], mobileTopSections = [], mobileBottomChildren, mobileBottomSections = [], rightItemsDesktop, rightItemsMobile, selectedChoice, mobileRollable = true }) => {
12
11
  const { isMobile } = useDevice("lg");
13
- if (!useIsMounted()) return /* @__PURE__ */ jsx(Fragment, {});
14
12
  return isMobile ? /* @__PURE__ */ jsx(MobileNavbar, {
15
13
  topChildren: mobileTopChildren,
16
14
  topSections: mobileTopSections,
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/components/Navbar/index.tsx"],"sourcesContent":["'use client';\n\nimport { useDevice } from '@hooks/useDevice';\nimport { useIsMounted } from '@hooks/useIsMounted';\nimport type { ReactElement, ReactNode } from 'react';\nimport type { TabSelectorItemProps } from '../TabSelector';\nimport { DesktopNavbar } from './DesktopNavbar';\nimport { MobileNavbar } from './MobileNavbar';\n\n/**\n * Props for the responsive Navbar component\n * @template T - The tab props type extending TabProps\n */\ntype NavbarProps<T extends TabSelectorItemProps> = {\n /** Logo component or element to display in navbar */\n logo: ReactNode;\n /** Currently selected tab key for active state management */\n selectedChoice: T['key'];\n /** Navigation sections displayed on desktop layout */\n desktopSections?: ReactElement<T>[];\n /** Additional content displayed at top of mobile navbar */\n mobileTopChildren?: ReactNode;\n /** Navigation sections displayed at top of mobile navbar */\n mobileTopSections?: ReactElement<T>[];\n /** Additional content displayed at bottom of mobile navbar */\n mobileBottomChildren?: ReactNode;\n /** Navigation sections displayed at bottom of mobile navbar */\n mobileBottomSections?: ReactElement<T>[];\n /** Right-aligned items for desktop navbar (e.g., user menu, settings) */\n rightItemsDesktop?: ReactNode;\n /** Right-aligned items for mobile navbar */\n rightItemsMobile?: ReactNode;\n /** Whether the mobile navbar should be rollable (default: true) */\n mobileRollable?: boolean;\n};\n\n/**\n * Responsive Navbar Component\n *\n * A highly adaptable navigation component that automatically switches between desktop and mobile\n * layouts based on screen size. Provides comprehensive navigation structure with flexible content areas.\n *\n * Features:\n * - Automatic responsive switching at 'lg' breakpoint (1024px)\n * - Separate section configurations for desktop and mobile layouts\n * - Support for logo placement and right-aligned utility items\n * - Generic typing for tab properties and selected states\n * - Mobile-specific top/bottom content areas for enhanced mobile UX\n * - Hydration-safe rendering with useIsMounted hook\n *\n * @example\n * Basic usage:\n * ```tsx\n * const navSections = [\n * { key: 'home', label: 'Home', href: '/' },\n * { key: 'about', label: 'About', href: '/about' }\n * ];\n *\n * <Navbar\n * logo={<Logo />}\n * selectedChoice=\"home\"\n * desktopSections={navSections}\n * mobileTopSections={navSections}\n * rightItemsDesktop={<UserMenu />}\n * />\n * ```\n *\n * @example\n * Advanced mobile configuration:\n * ```tsx\n * <Navbar\n * logo={<Logo />}\n * selectedChoice={activeTab}\n * desktopSections={mainNavItems}\n * mobileTopSections={primaryMobileNavItems}\n * mobileTopChildren={<SearchBar />}\n * mobileBottomSections={secondaryMobileNavItems}\n * mobileBottomChildren={<UserProfile />}\n * rightItemsDesktop={<DesktopActions />}\n * rightItemsMobile={<MobileActions />}\n * />\n * ```\n *\n * Responsive Behavior:\n * - Desktop (≥1024px): Shows DesktopNavbar with horizontal layout\n * - Mobile (<1024px): Shows MobileNavbar with collapsible vertical layout\n * - Automatic detection with no flash of unstyled content\n *\n * @template T - Tab properties type extending TabProps for type safety\n * @param props - Navbar component props\n * @returns Responsive navbar JSX element\n */\nexport { Burger } from './Burger';\nexport { DesktopNavbar } from './DesktopNavbar';\nexport { MobileNavbar } from './MobileNavbar';\n\nexport const Navbar = <T extends TabSelectorItemProps>({\n logo,\n mobileTopChildren,\n desktopSections = [],\n mobileTopSections = [],\n mobileBottomChildren,\n mobileBottomSections = [],\n rightItemsDesktop,\n rightItemsMobile,\n selectedChoice,\n mobileRollable = true,\n}: NavbarProps<T>) => {\n const { isMobile } = useDevice('lg');\n const isMoUnted = useIsMounted();\n\n if (!isMoUnted) return <></>;\n\n return isMobile ? (\n <MobileNavbar\n topChildren={mobileTopChildren}\n topSections={mobileTopSections}\n bottomChildren={mobileBottomChildren}\n bottomSections={mobileBottomSections}\n logo={logo}\n rightItems={rightItemsMobile}\n rollable={mobileRollable}\n />\n ) : (\n <DesktopNavbar\n sections={desktopSections}\n rightItems={rightItemsDesktop}\n logo={logo}\n selectedChoice={selectedChoice}\n />\n );\n};\n"],"mappings":";;;;;;;;;;AAgGA,MAAa,UAA0C,EACrD,MACA,mBACA,kBAAkB,EAAE,EACpB,oBAAoB,EAAE,EACtB,sBACA,uBAAuB,EAAE,EACzB,mBACA,kBACA,gBACA,iBAAiB,WACG;CACpB,MAAM,EAAE,aAAa,UAAU,KAAK;AAGpC,KAAI,CAFc,cAAc,CAEhB,QAAO,gCAAK;AAE5B,QAAO,WACL,oBAAC,cAAD;EACE,aAAa;EACb,aAAa;EACb,gBAAgB;EAChB,gBAAgB;EACV;EACN,YAAY;EACZ,UAAU;EACV,IAEF,oBAAC,eAAD;EACE,UAAU;EACV,YAAY;EACN;EACU;EAChB"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/components/Navbar/index.tsx"],"sourcesContent":["'use client';\n\nimport { useDevice } from '@hooks/useDevice';\nimport { useIsMounted } from '@hooks/useIsMounted';\nimport type { ReactElement, ReactNode } from 'react';\nimport type { TabSelectorItemProps } from '../TabSelector';\nimport { DesktopNavbar } from './DesktopNavbar';\nimport { MobileNavbar } from './MobileNavbar';\n\n/**\n * Props for the responsive Navbar component\n * @template T - The tab props type extending TabProps\n */\ntype NavbarProps<T extends TabSelectorItemProps> = {\n /** Logo component or element to display in navbar */\n logo: ReactNode;\n /** Currently selected tab key for active state management */\n selectedChoice: T['key'];\n /** Navigation sections displayed on desktop layout */\n desktopSections?: ReactElement<T>[];\n /** Additional content displayed at top of mobile navbar */\n mobileTopChildren?: ReactNode;\n /** Navigation sections displayed at top of mobile navbar */\n mobileTopSections?: ReactElement<T>[];\n /** Additional content displayed at bottom of mobile navbar */\n mobileBottomChildren?: ReactNode;\n /** Navigation sections displayed at bottom of mobile navbar */\n mobileBottomSections?: ReactElement<T>[];\n /** Right-aligned items for desktop navbar (e.g., user menu, settings) */\n rightItemsDesktop?: ReactNode;\n /** Right-aligned items for mobile navbar */\n rightItemsMobile?: ReactNode;\n /** Whether the mobile navbar should be rollable (default: true) */\n mobileRollable?: boolean;\n};\n\n/**\n * Responsive Navbar Component\n *\n * A highly adaptable navigation component that automatically switches between desktop and mobile\n * layouts based on screen size. Provides comprehensive navigation structure with flexible content areas.\n *\n * Features:\n * - Automatic responsive switching at 'lg' breakpoint (1024px)\n * - Separate section configurations for desktop and mobile layouts\n * - Support for logo placement and right-aligned utility items\n * - Generic typing for tab properties and selected states\n * - Mobile-specific top/bottom content areas for enhanced mobile UX\n * - Hydration-safe rendering with useIsMounted hook\n *\n * @example\n * Basic usage:\n * ```tsx\n * const navSections = [\n * { key: 'home', label: 'Home', href: '/' },\n * { key: 'about', label: 'About', href: '/about' }\n * ];\n *\n * <Navbar\n * logo={<Logo />}\n * selectedChoice=\"home\"\n * desktopSections={navSections}\n * mobileTopSections={navSections}\n * rightItemsDesktop={<UserMenu />}\n * />\n * ```\n *\n * @example\n * Advanced mobile configuration:\n * ```tsx\n * <Navbar\n * logo={<Logo />}\n * selectedChoice={activeTab}\n * desktopSections={mainNavItems}\n * mobileTopSections={primaryMobileNavItems}\n * mobileTopChildren={<SearchBar />}\n * mobileBottomSections={secondaryMobileNavItems}\n * mobileBottomChildren={<UserProfile />}\n * rightItemsDesktop={<DesktopActions />}\n * rightItemsMobile={<MobileActions />}\n * />\n * ```\n *\n * Responsive Behavior:\n * - Desktop (≥1024px): Shows DesktopNavbar with horizontal layout\n * - Mobile (<1024px): Shows MobileNavbar with collapsible vertical layout\n * - Automatic detection with no flash of unstyled content\n *\n * @template T - Tab properties type extending TabProps for type safety\n * @param props - Navbar component props\n * @returns Responsive navbar JSX element\n */\nexport { Burger } from './Burger';\nexport { DesktopNavbar } from './DesktopNavbar';\nexport { MobileNavbar } from './MobileNavbar';\n\nexport const Navbar = <T extends TabSelectorItemProps>({\n logo,\n mobileTopChildren,\n desktopSections = [],\n mobileTopSections = [],\n mobileBottomChildren,\n mobileBottomSections = [],\n rightItemsDesktop,\n rightItemsMobile,\n selectedChoice,\n mobileRollable = true,\n}: NavbarProps<T>) => {\n const { isMobile } = useDevice('lg');\n\n return isMobile ? (\n <MobileNavbar\n topChildren={mobileTopChildren}\n topSections={mobileTopSections}\n bottomChildren={mobileBottomChildren}\n bottomSections={mobileBottomSections}\n logo={logo}\n rightItems={rightItemsMobile}\n rollable={mobileRollable}\n />\n ) : (\n <DesktopNavbar\n sections={desktopSections}\n rightItems={rightItemsDesktop}\n logo={logo}\n selectedChoice={selectedChoice}\n />\n );\n};\n"],"mappings":";;;;;;;;;AAgGA,MAAa,UAA0C,EACrD,MACA,mBACA,kBAAkB,EAAE,EACpB,oBAAoB,EAAE,EACtB,sBACA,uBAAuB,EAAE,EACzB,mBACA,kBACA,gBACA,iBAAiB,WACG;CACpB,MAAM,EAAE,aAAa,UAAU,KAAK;AAEpC,QAAO,WACL,oBAAC,cAAD;EACE,aAAa;EACb,aAAa;EACb,gBAAgB;EAChB,gBAAgB;EACV;EACN,YAAY;EACZ,UAAU;EACV,IAEF,oBAAC,eAAD;EACE,UAAU;EACV,YAAY;EACN;EACU;EAChB"}
@@ -142,8 +142,11 @@ const useNavActions = () => {
142
142
  } else onClick?.();
143
143
  };
144
144
  return {
145
+ /** Currently active section ID, null if no section is active */
145
146
  activeSection,
147
+ /** Handler for logo click interactions */
146
148
  onClickLogo,
149
+ /** Handler for section navigation clicks */
147
150
  onClickSection
148
151
  };
149
152
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useNavigation.mjs","names":[],"sources":["../../../../src/components/Navbar/useNavigation.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\n\n/**\n * Interface describing section data used for scroll detection\n */\ninterface SectionData {\n /** Unique identifier of the section element */\n id: string;\n /** Distance from top of document to section start */\n offsetTop: number;\n /** Height of the section element */\n offsetHeight: number;\n}\n\n/**\n * Navigation Actions Hook\n *\n * A comprehensive hook for managing navigation interactions and scroll-based section detection.\n * Provides automatic active section detection based on scroll position and handles smooth\n * scrolling navigation behaviors.\n *\n * Features:\n * - Automatic active section detection based on scroll position\n * - Smooth scrolling to sections within the same page\n * - Logo click handling with home navigation\n * - Section click handling with conditional scrolling vs navigation\n * - Passive scroll event listeners for optimal performance\n * - Viewport-aware active section calculation (using screen height / 4 offset)\n *\n * Active Section Detection:\n * - Monitors all `<section>` elements on the page\n * - Calculates which section is currently in the \"active\" zone\n * - Active zone is defined as the top 25% of the viewport\n * - Updates activeSection state as user scrolls\n *\n * Navigation Behaviors:\n * - Logo click: Scrolls to top if on home page, navigates to home if on other pages\n * - Section click: Smooth scrolls if on same page, executes callback if different page\n * - All scrolling uses smooth behavior for better UX\n *\n * @example\n * Basic usage in navigation component:\n * ```tsx\n * const { activeSection, onClickLogo, onClickSection } = useNavActions();\n *\n * // In navigation items\n * const navItems = sections.map(section => (\n * <TabSelectorItem\n * key={section.id}\n * isActive={activeSection === section.id}\n * onClick={() => onClickSection(section.id, section.url, section.onClick)}\n * >\n * {section.label}\n * </TabSelectorItem>\n * ));\n *\n * // In logo\n * <Logo onClick={() => onClickLogo(navigate)} />\n * ```\n *\n * @example\n * Advanced usage with routing:\n * ```tsx\n * const { activeSection, onClickLogo, onClickSection } = useNavActions();\n * const navigate = useNavigate();\n *\n * const handleLogoClick = () => {\n * onClickLogo((url) => {\n * navigate(url);\n * // Additional logic like analytics\n * trackEvent('logo_click');\n * });\n * };\n *\n * const handleSectionClick = (sectionId: string) => {\n * onClickSection(\n * sectionId,\n * `/page#${sectionId}`,\n * () => {\n * navigate(`/page#${sectionId}`);\n * trackEvent('section_navigation', { sectionId });\n * }\n * );\n * };\n * ```\n *\n * Performance Considerations:\n * - Uses passive scroll event listeners to prevent blocking\n * - Automatically cleans up event listeners on unmount\n * - Efficiently queries DOM elements using native selectors\n * - Calculates section positions dynamically for accuracy\n *\n * @returns Object containing navigation state and action handlers\n */\nexport const useNavActions = () => {\n /** Currently active section ID based on scroll position */\n const [activeSection, setActiveSection] = useState<string | null>(null);\n\n /**\n * Detects which section is currently active based on scroll position\n * Uses viewport-aware calculation to determine active section\n */\n const detectActiveSection = () => {\n const scrollY = window.scrollY;\n const sections = document.querySelectorAll('section');\n const sectionsData: SectionData[] = [];\n\n // Collect position data for all sections\n sections.forEach((section) =>\n sectionsData.push({\n id: section.id,\n offsetTop: section.offsetTop,\n offsetHeight: section.offsetHeight,\n })\n );\n\n // Find section that intersects with the active zone (top 25% of viewport)\n const currentSection = sectionsData.find(\n (section) =>\n section.offsetTop <= scrollY + window.screen.height / 4 &&\n section.offsetTop + section.offsetHeight >\n scrollY + window.screen.height / 4\n );\n\n if (currentSection) {\n setActiveSection(currentSection.id);\n }\n };\n\n // Set up scroll listener for active section detection\n useEffect(() => {\n window.addEventListener('scroll', detectActiveSection, { passive: true });\n\n return () => {\n window.removeEventListener('scroll', detectActiveSection);\n };\n }, []);\n\n /**\n * Handles logo click behavior\n * Scrolls to top if on home page, navigates to home if on other pages\n *\n * @param onClick - Callback function to handle navigation (e.g., router.push)\n */\n const onClickLogo = (onClick: (url: string) => void) => {\n setActiveSection(null);\n\n if (window.location.pathname === '/') {\n window.scrollTo({ top: 0, behavior: 'smooth' });\n } else {\n onClick('/');\n }\n };\n\n /**\n * Handles section navigation click behavior\n * Smooth scrolls if on same page, executes callback if different page\n *\n * @param sectionId - ID of the target section element\n * @param url - URL of the page containing the section (optional)\n * @param onClick - Callback function to handle navigation (optional)\n */\n const onClickSection = (\n sectionId: string,\n url?: string,\n onClick?: () => void\n ) => {\n setActiveSection(sectionId);\n\n // If on the same page, scroll to section\n if (window.location.pathname === url) {\n const sectionEl = document.getElementById(sectionId);\n\n if (sectionEl) {\n sectionEl.scrollIntoView({\n behavior: 'smooth',\n block: 'center',\n inline: 'nearest',\n });\n }\n } else {\n // If on different page, execute callback (typically navigation)\n onClick?.();\n }\n };\n\n return {\n /** Currently active section ID, null if no section is active */\n activeSection,\n /** Handler for logo click interactions */\n onClickLogo,\n /** Handler for section navigation clicks */\n onClickSection,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgGA,MAAa,sBAAsB;;CAEjC,MAAM,CAAC,eAAe,oBAAoB,SAAwB,KAAK;;;;;CAMvE,MAAM,4BAA4B;EAChC,MAAM,UAAU,OAAO;EACvB,MAAM,WAAW,SAAS,iBAAiB,UAAU;EACrD,MAAM,eAA8B,EAAE;AAGtC,WAAS,SAAS,YAChB,aAAa,KAAK;GAChB,IAAI,QAAQ;GACZ,WAAW,QAAQ;GACnB,cAAc,QAAQ;GACvB,CAAC,CACH;EAGD,MAAM,iBAAiB,aAAa,MACjC,YACC,QAAQ,aAAa,UAAU,OAAO,OAAO,SAAS,KACtD,QAAQ,YAAY,QAAQ,eAC1B,UAAU,OAAO,OAAO,SAAS,EACtC;AAED,MAAI,eACF,kBAAiB,eAAe,GAAG;;AAKvC,iBAAgB;AACd,SAAO,iBAAiB,UAAU,qBAAqB,EAAE,SAAS,MAAM,CAAC;AAEzE,eAAa;AACX,UAAO,oBAAoB,UAAU,oBAAoB;;IAE1D,EAAE,CAAC;;;;;;;CAQN,MAAM,eAAe,YAAmC;AACtD,mBAAiB,KAAK;AAEtB,MAAI,OAAO,SAAS,aAAa,IAC/B,QAAO,SAAS;GAAE,KAAK;GAAG,UAAU;GAAU,CAAC;MAE/C,SAAQ,IAAI;;;;;;;;;;CAYhB,MAAM,kBACJ,WACA,KACA,YACG;AACH,mBAAiB,UAAU;AAG3B,MAAI,OAAO,SAAS,aAAa,KAAK;GACpC,MAAM,YAAY,SAAS,eAAe,UAAU;AAEpD,OAAI,UACF,WAAU,eAAe;IACvB,UAAU;IACV,OAAO;IACP,QAAQ;IACT,CAAC;QAIJ,YAAW;;AAIf,QAAO;EAEL;EAEA;EAEA;EACD"}
1
+ {"version":3,"file":"useNavigation.mjs","names":[],"sources":["../../../../src/components/Navbar/useNavigation.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\n\n/**\n * Interface describing section data used for scroll detection\n */\ninterface SectionData {\n /** Unique identifier of the section element */\n id: string;\n /** Distance from top of document to section start */\n offsetTop: number;\n /** Height of the section element */\n offsetHeight: number;\n}\n\n/**\n * Navigation Actions Hook\n *\n * A comprehensive hook for managing navigation interactions and scroll-based section detection.\n * Provides automatic active section detection based on scroll position and handles smooth\n * scrolling navigation behaviors.\n *\n * Features:\n * - Automatic active section detection based on scroll position\n * - Smooth scrolling to sections within the same page\n * - Logo click handling with home navigation\n * - Section click handling with conditional scrolling vs navigation\n * - Passive scroll event listeners for optimal performance\n * - Viewport-aware active section calculation (using screen height / 4 offset)\n *\n * Active Section Detection:\n * - Monitors all `<section>` elements on the page\n * - Calculates which section is currently in the \"active\" zone\n * - Active zone is defined as the top 25% of the viewport\n * - Updates activeSection state as user scrolls\n *\n * Navigation Behaviors:\n * - Logo click: Scrolls to top if on home page, navigates to home if on other pages\n * - Section click: Smooth scrolls if on same page, executes callback if different page\n * - All scrolling uses smooth behavior for better UX\n *\n * @example\n * Basic usage in navigation component:\n * ```tsx\n * const { activeSection, onClickLogo, onClickSection } = useNavActions();\n *\n * // In navigation items\n * const navItems = sections.map(section => (\n * <TabSelectorItem\n * key={section.id}\n * isActive={activeSection === section.id}\n * onClick={() => onClickSection(section.id, section.url, section.onClick)}\n * >\n * {section.label}\n * </TabSelectorItem>\n * ));\n *\n * // In logo\n * <Logo onClick={() => onClickLogo(navigate)} />\n * ```\n *\n * @example\n * Advanced usage with routing:\n * ```tsx\n * const { activeSection, onClickLogo, onClickSection } = useNavActions();\n * const navigate = useNavigate();\n *\n * const handleLogoClick = () => {\n * onClickLogo((url) => {\n * navigate(url);\n * // Additional logic like analytics\n * trackEvent('logo_click');\n * });\n * };\n *\n * const handleSectionClick = (sectionId: string) => {\n * onClickSection(\n * sectionId,\n * `/page#${sectionId}`,\n * () => {\n * navigate(`/page#${sectionId}`);\n * trackEvent('section_navigation', { sectionId });\n * }\n * );\n * };\n * ```\n *\n * Performance Considerations:\n * - Uses passive scroll event listeners to prevent blocking\n * - Automatically cleans up event listeners on unmount\n * - Efficiently queries DOM elements using native selectors\n * - Calculates section positions dynamically for accuracy\n *\n * @returns Object containing navigation state and action handlers\n */\nexport const useNavActions = () => {\n /** Currently active section ID based on scroll position */\n const [activeSection, setActiveSection] = useState<string | null>(null);\n\n /**\n * Detects which section is currently active based on scroll position\n * Uses viewport-aware calculation to determine active section\n */\n const detectActiveSection = () => {\n const scrollY = window.scrollY;\n const sections = document.querySelectorAll('section');\n const sectionsData: SectionData[] = [];\n\n // Collect position data for all sections\n sections.forEach((section) =>\n sectionsData.push({\n id: section.id,\n offsetTop: section.offsetTop,\n offsetHeight: section.offsetHeight,\n })\n );\n\n // Find section that intersects with the active zone (top 25% of viewport)\n const currentSection = sectionsData.find(\n (section) =>\n section.offsetTop <= scrollY + window.screen.height / 4 &&\n section.offsetTop + section.offsetHeight >\n scrollY + window.screen.height / 4\n );\n\n if (currentSection) {\n setActiveSection(currentSection.id);\n }\n };\n\n // Set up scroll listener for active section detection\n useEffect(() => {\n window.addEventListener('scroll', detectActiveSection, { passive: true });\n\n return () => {\n window.removeEventListener('scroll', detectActiveSection);\n };\n }, []);\n\n /**\n * Handles logo click behavior\n * Scrolls to top if on home page, navigates to home if on other pages\n *\n * @param onClick - Callback function to handle navigation (e.g., router.push)\n */\n const onClickLogo = (onClick: (url: string) => void) => {\n setActiveSection(null);\n\n if (window.location.pathname === '/') {\n window.scrollTo({ top: 0, behavior: 'smooth' });\n } else {\n onClick('/');\n }\n };\n\n /**\n * Handles section navigation click behavior\n * Smooth scrolls if on same page, executes callback if different page\n *\n * @param sectionId - ID of the target section element\n * @param url - URL of the page containing the section (optional)\n * @param onClick - Callback function to handle navigation (optional)\n */\n const onClickSection = (\n sectionId: string,\n url?: string,\n onClick?: () => void\n ) => {\n setActiveSection(sectionId);\n\n // If on the same page, scroll to section\n if (window.location.pathname === url) {\n const sectionEl = document.getElementById(sectionId);\n\n if (sectionEl) {\n sectionEl.scrollIntoView({\n behavior: 'smooth',\n block: 'center',\n inline: 'nearest',\n });\n }\n } else {\n // If on different page, execute callback (typically navigation)\n onClick?.();\n }\n };\n\n return {\n /** Currently active section ID, null if no section is active */\n activeSection,\n /** Handler for logo click interactions */\n onClickLogo,\n /** Handler for section navigation clicks */\n onClickSection,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgGA,MAAa,sBAAsB;;CAEjC,MAAM,CAAC,eAAe,oBAAoB,SAAwB,KAAK;;;;;CAMvE,MAAM,4BAA4B;EAChC,MAAM,UAAU,OAAO;EACvB,MAAM,WAAW,SAAS,iBAAiB,UAAU;EACrD,MAAM,eAA8B,EAAE;AAGtC,WAAS,SAAS,YAChB,aAAa,KAAK;GAChB,IAAI,QAAQ;GACZ,WAAW,QAAQ;GACnB,cAAc,QAAQ;GACvB,CAAC,CACH;EAGD,MAAM,iBAAiB,aAAa,MACjC,YACC,QAAQ,aAAa,UAAU,OAAO,OAAO,SAAS,KACtD,QAAQ,YAAY,QAAQ,eAC1B,UAAU,OAAO,OAAO,SAAS,EACtC;AAED,MAAI,eACF,kBAAiB,eAAe,GAAG;;AAKvC,iBAAgB;AACd,SAAO,iBAAiB,UAAU,qBAAqB,EAAE,SAAS,MAAM,CAAC;AAEzE,eAAa;AACX,UAAO,oBAAoB,UAAU,oBAAoB;;IAE1D,EAAE,CAAC;;;;;;;CAQN,MAAM,eAAe,YAAmC;AACtD,mBAAiB,KAAK;AAEtB,MAAI,OAAO,SAAS,aAAa,IAC/B,QAAO,SAAS;GAAE,KAAK;GAAG,UAAU;GAAU,CAAC;MAE/C,SAAQ,IAAI;;;;;;;;;;CAYhB,MAAM,kBACJ,WACA,KACA,YACG;AACH,mBAAiB,UAAU;AAG3B,MAAI,OAAO,SAAS,aAAa,KAAK;GACpC,MAAM,YAAY,SAAS,eAAe,UAAU;AAEpD,OAAI,UACF,WAAU,eAAe;IACvB,UAAU;IACV,OAAO;IACP,QAAQ;IACT,CAAC;QAIJ,YAAW;;AAIf,QAAO;;EAEL;;EAEA;;EAEA;EACD"}
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
 
3
3
  import { cn } from "../../utils/cn.mjs";
4
- import { Button, ButtonColor, ButtonSize, ButtonVariant } from "../Button/Button.mjs";
5
4
  import { useItemSelector } from "../../hooks/useItemSelector.mjs";
5
+ import { Button, ButtonColor, ButtonSize, ButtonVariant } from "../Button/Button.mjs";
6
6
  import { useEffect, useRef } from "react";
7
7
  import { cva } from "class-variance-authority";
8
8
  import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react";
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic.mjs","names":["StaticDetail"],"sources":["../../../../src/components/Popover/dynamic.tsx"],"sourcesContent":["'use client';\n\nimport type { FC } from 'react';\nimport { useEffect, useRef, useState } from 'react';\nimport {\n type DetailProps,\n type PopoverProps,\n PopoverStatic,\n type PopoverType,\n PopoverXAlign,\n PopoverYAlign,\n Detail as StaticDetail,\n} from './static';\n\n/**\n * Popover Component (Client-side)\n *\n * Client-side wrapper around the static Popover component.\n * Reuses the server-side compatible implementation.\n *\n * @param props - Popover component props\n * @returns Trigger container with popover functionality\n */\nconst PopoverComponent: FC<PopoverProps> = (props) => {\n return <PopoverStatic {...props} />;\n};\n\n/**\n * Popover Detail Component (Client-side)\n *\n * Client-side wrapper around the static Detail component that adds automatic\n * positioning logic based on viewport constraints.\n *\n * Features:\n * - Reuses server-side compatible static Detail component\n * - Adds automatic positioning adjustment based on viewport\n * - Calculates optimal X/Y alignment to prevent overflow\n * - Dynamically adjusts max-width based on available space\n * - Listens to window resize and scroll events\n *\n * @param props - Popover Detail component props\n * @returns Positioned popover content with animations and accessibility\n */\nconst Detail: FC<DetailProps> = ({\n xAlign = PopoverXAlign.START,\n yAlign = PopoverYAlign.BELOW,\n ...props\n}) => {\n const popoverRef = useRef<HTMLDivElement>(null);\n const [computedXAlign, setComputedXAlign] = useState(xAlign);\n const [computedYAlign, setComputedYAlign] = useState(yAlign);\n const [maxWidth, setMaxWidth] = useState<number | undefined>(undefined);\n\n useEffect(() => {\n const adjustPosition = () => {\n if (!popoverRef.current) return;\n\n const popoverElement = popoverRef.current;\n const triggerElement = document.getElementById(\n `unrollable-panel-button-${props.identifier}`\n );\n\n if (!triggerElement) return;\n\n const triggerRect = triggerElement.getBoundingClientRect();\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n const gap = 16; // 1rem gap\n const padding = 16; // Additional padding from viewport edges\n\n // Calculate maximum width based on viewport and trigger position\n const maxWidthFromLeft = viewportWidth - triggerRect.left - padding;\n const maxWidthFromRight = triggerRect.right - padding;\n\n // Use the larger space to ensure popover can fit\n const absoluteMaxWidth = Math.max(maxWidthFromLeft, maxWidthFromRight);\n\n setMaxWidth(absoluteMaxWidth);\n\n // Force a layout calculation by temporarily making visible if needed\n const wasInvisible = popoverElement.classList.contains('invisible');\n if (wasInvisible) {\n popoverElement.style.visibility = 'hidden';\n popoverElement.classList.remove('invisible');\n }\n\n // Small delay to ensure max-width is applied and content reflows\n requestAnimationFrame(() => {\n const popoverRect = popoverElement.getBoundingClientRect();\n\n // Restore invisible state if it was invisible\n if (wasInvisible) {\n popoverElement.style.visibility = '';\n popoverElement.classList.add('invisible');\n }\n\n // Determine optimal Y alignment\n let newYAlign = yAlign;\n const spaceBelow = viewportHeight - triggerRect.bottom - gap;\n const spaceAbove = triggerRect.top - gap;\n\n if (yAlign === PopoverYAlign.BELOW && spaceBelow < popoverRect.height) {\n // Not enough space below, try above\n if (spaceAbove >= popoverRect.height) {\n newYAlign = PopoverYAlign.ABOVE;\n }\n } else if (\n yAlign === PopoverYAlign.ABOVE &&\n spaceAbove < popoverRect.height\n ) {\n // Not enough space above, try below\n if (spaceBelow >= popoverRect.height) {\n newYAlign = PopoverYAlign.BELOW;\n }\n }\n\n // Determine optimal X alignment\n let newXAlign = xAlign;\n const spaceRight = viewportWidth - triggerRect.left - padding;\n const spaceLeft = triggerRect.right - padding;\n\n if (xAlign === PopoverXAlign.START && spaceRight < popoverRect.width) {\n // Not enough space on the right, try left\n if (spaceLeft >= popoverRect.width) {\n newXAlign = PopoverXAlign.END;\n }\n } else if (\n xAlign === PopoverXAlign.END &&\n spaceLeft < popoverRect.width\n ) {\n // Not enough space on the left, try right\n if (spaceRight >= popoverRect.width) {\n newXAlign = PopoverXAlign.START;\n }\n }\n\n setComputedYAlign(newYAlign);\n setComputedXAlign(newXAlign);\n });\n };\n\n // Adjust position with a slight delay to ensure DOM is ready\n const timeoutId = setTimeout(adjustPosition, 0);\n\n // Listen to mouse enter on the trigger to recalculate\n const triggerElement = document.getElementById(\n `unrollable-panel-button-${props.identifier}`\n );\n\n if (triggerElement) {\n triggerElement.addEventListener('mouseenter', adjustPosition);\n triggerElement.addEventListener('focusin', adjustPosition);\n }\n\n // Use ResizeObserver to detect popover content size changes\n const resizeObserver = new ResizeObserver(() => {\n adjustPosition();\n });\n\n if (popoverRef.current) {\n resizeObserver.observe(popoverRef.current);\n }\n\n window.addEventListener('resize', adjustPosition);\n window.addEventListener('scroll', adjustPosition, true);\n\n return () => {\n clearTimeout(timeoutId);\n if (triggerElement) {\n triggerElement.removeEventListener('mouseenter', adjustPosition);\n triggerElement.removeEventListener('focusin', adjustPosition);\n }\n resizeObserver.disconnect();\n window.removeEventListener('resize', adjustPosition);\n window.removeEventListener('scroll', adjustPosition, true);\n };\n }, [props.identifier, xAlign, yAlign]);\n\n // Use the static Detail component with computed alignment values\n return (\n <StaticDetail\n {...props}\n xAlign={computedXAlign}\n yAlign={computedYAlign}\n ref={popoverRef}\n style={{\n ...props.style,\n maxWidth: maxWidth ? `${maxWidth}px` : undefined,\n }}\n />\n );\n};\n\n// Create Popover with Detail attached\nexport const Popover: PopoverType = PopoverComponent as PopoverType;\n\nPopover.Detail = Detail;\n"],"mappings":";;;;;;;;;;;;;;;;AAuBA,MAAM,oBAAsC,UAAU;AACpD,QAAO,oBAAC,eAAD,EAAe,GAAI,OAAS;;;;;;;;;;;;;;;;;;AAmBrC,MAAM,UAA2B,EAC/B,kBACA,mBACA,GAAG,YACC;CACJ,MAAM,aAAa,OAAuB,KAAK;CAC/C,MAAM,CAAC,gBAAgB,qBAAqB,SAAS,OAAO;CAC5D,MAAM,CAAC,gBAAgB,qBAAqB,SAAS,OAAO;CAC5D,MAAM,CAAC,UAAU,eAAe,SAA6B,OAAU;AAEvE,iBAAgB;EACd,MAAM,uBAAuB;AAC3B,OAAI,CAAC,WAAW,QAAS;GAEzB,MAAM,iBAAiB,WAAW;GAClC,MAAM,iBAAiB,SAAS,eAC9B,2BAA2B,MAAM,aAClC;AAED,OAAI,CAAC,eAAgB;GAErB,MAAM,cAAc,eAAe,uBAAuB;GAC1D,MAAM,gBAAgB,OAAO;GAC7B,MAAM,iBAAiB,OAAO;GAC9B,MAAM,MAAM;GACZ,MAAM,UAAU;GAGhB,MAAM,mBAAmB,gBAAgB,YAAY,OAAO;GAC5D,MAAM,oBAAoB,YAAY,QAAQ;AAK9C,eAFyB,KAAK,IAAI,kBAAkB,kBAAkB,CAEzC;GAG7B,MAAM,eAAe,eAAe,UAAU,SAAS,YAAY;AACnE,OAAI,cAAc;AAChB,mBAAe,MAAM,aAAa;AAClC,mBAAe,UAAU,OAAO,YAAY;;AAI9C,+BAA4B;IAC1B,MAAM,cAAc,eAAe,uBAAuB;AAG1D,QAAI,cAAc;AAChB,oBAAe,MAAM,aAAa;AAClC,oBAAe,UAAU,IAAI,YAAY;;IAI3C,IAAI,YAAY;IAChB,MAAM,aAAa,iBAAiB,YAAY,SAAS;IACzD,MAAM,aAAa,YAAY,MAAM;AAErC,QAAI,uBAAkC,aAAa,YAAY,QAE7D;SAAI,cAAc,YAAY,OAC5B;eAGF,sBACA,aAAa,YAAY,QAGzB;SAAI,cAAc,YAAY,OAC5B;;IAKJ,IAAI,YAAY;IAChB,MAAM,aAAa,gBAAgB,YAAY,OAAO;IACtD,MAAM,YAAY,YAAY,QAAQ;AAEtC,QAAI,sBAAkC,aAAa,YAAY,OAE7D;SAAI,aAAa,YAAY,MAC3B;eAGF,oBACA,YAAY,YAAY,OAGxB;SAAI,cAAc,YAAY,MAC5B;;AAIJ,sBAAkB,UAAU;AAC5B,sBAAkB,UAAU;KAC5B;;EAIJ,MAAM,YAAY,WAAW,gBAAgB,EAAE;EAG/C,MAAM,iBAAiB,SAAS,eAC9B,2BAA2B,MAAM,aAClC;AAED,MAAI,gBAAgB;AAClB,kBAAe,iBAAiB,cAAc,eAAe;AAC7D,kBAAe,iBAAiB,WAAW,eAAe;;EAI5D,MAAM,iBAAiB,IAAI,qBAAqB;AAC9C,mBAAgB;IAChB;AAEF,MAAI,WAAW,QACb,gBAAe,QAAQ,WAAW,QAAQ;AAG5C,SAAO,iBAAiB,UAAU,eAAe;AACjD,SAAO,iBAAiB,UAAU,gBAAgB,KAAK;AAEvD,eAAa;AACX,gBAAa,UAAU;AACvB,OAAI,gBAAgB;AAClB,mBAAe,oBAAoB,cAAc,eAAe;AAChE,mBAAe,oBAAoB,WAAW,eAAe;;AAE/D,kBAAe,YAAY;AAC3B,UAAO,oBAAoB,UAAU,eAAe;AACpD,UAAO,oBAAoB,UAAU,gBAAgB,KAAK;;IAE3D;EAAC,MAAM;EAAY;EAAQ;EAAO,CAAC;AAGtC,QACE,oBAACA,UAAD;EACE,GAAI;EACJ,QAAQ;EACR,QAAQ;EACR,KAAK;EACL,OAAO;GACL,GAAG,MAAM;GACT,UAAU,WAAW,GAAG,SAAS,MAAM;GACxC;EACD;;AAKN,MAAa,UAAuB;AAEpC,QAAQ,SAAS"}
1
+ {"version":3,"file":"dynamic.mjs","names":["StaticDetail"],"sources":["../../../../src/components/Popover/dynamic.tsx"],"sourcesContent":["'use client';\n\nimport type { FC } from 'react';\nimport { useEffect, useRef, useState } from 'react';\nimport {\n type DetailProps,\n type PopoverProps,\n PopoverStatic,\n type PopoverType,\n PopoverXAlign,\n PopoverYAlign,\n Detail as StaticDetail,\n} from './static';\n\n/**\n * Popover Component (Client-side)\n *\n * Client-side wrapper around the static Popover component.\n * Reuses the server-side compatible implementation.\n *\n * @param props - Popover component props\n * @returns Trigger container with popover functionality\n */\nconst PopoverComponent: FC<PopoverProps> = (props) => {\n return <PopoverStatic {...props} />;\n};\n\n/**\n * Popover Detail Component (Client-side)\n *\n * Client-side wrapper around the static Detail component that adds automatic\n * positioning logic based on viewport constraints.\n *\n * Features:\n * - Reuses server-side compatible static Detail component\n * - Adds automatic positioning adjustment based on viewport\n * - Calculates optimal X/Y alignment to prevent overflow\n * - Dynamically adjusts max-width based on available space\n * - Listens to window resize and scroll events\n *\n * @param props - Popover Detail component props\n * @returns Positioned popover content with animations and accessibility\n */\nconst Detail: FC<DetailProps> = ({\n xAlign = PopoverXAlign.START,\n yAlign = PopoverYAlign.BELOW,\n ...props\n}) => {\n const popoverRef = useRef<HTMLDivElement>(null);\n const [computedXAlign, setComputedXAlign] = useState(xAlign);\n const [computedYAlign, setComputedYAlign] = useState(yAlign);\n const [maxWidth, setMaxWidth] = useState<number | undefined>(undefined);\n\n useEffect(() => {\n const adjustPosition = () => {\n if (!popoverRef.current) return;\n\n const popoverElement = popoverRef.current;\n const triggerElement = document.getElementById(\n `unrollable-panel-button-${props.identifier}`\n );\n\n if (!triggerElement) return;\n\n const triggerRect = triggerElement.getBoundingClientRect();\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n const gap = 16; // 1rem gap\n const padding = 16; // Additional padding from viewport edges\n\n // Calculate maximum width based on viewport and trigger position\n const maxWidthFromLeft = viewportWidth - triggerRect.left - padding;\n const maxWidthFromRight = triggerRect.right - padding;\n\n // Use the larger space to ensure popover can fit\n const absoluteMaxWidth = Math.max(maxWidthFromLeft, maxWidthFromRight);\n\n setMaxWidth(absoluteMaxWidth);\n\n // Force a layout calculation by temporarily making visible if needed\n const wasInvisible = popoverElement.classList.contains('invisible');\n if (wasInvisible) {\n popoverElement.style.visibility = 'hidden';\n popoverElement.classList.remove('invisible');\n }\n\n // Small delay to ensure max-width is applied and content reflows\n requestAnimationFrame(() => {\n const popoverRect = popoverElement.getBoundingClientRect();\n\n // Restore invisible state if it was invisible\n if (wasInvisible) {\n popoverElement.style.visibility = '';\n popoverElement.classList.add('invisible');\n }\n\n // Determine optimal Y alignment\n let newYAlign = yAlign;\n const spaceBelow = viewportHeight - triggerRect.bottom - gap;\n const spaceAbove = triggerRect.top - gap;\n\n if (yAlign === PopoverYAlign.BELOW && spaceBelow < popoverRect.height) {\n // Not enough space below, try above\n if (spaceAbove >= popoverRect.height) {\n newYAlign = PopoverYAlign.ABOVE;\n }\n } else if (\n yAlign === PopoverYAlign.ABOVE &&\n spaceAbove < popoverRect.height\n ) {\n // Not enough space above, try below\n if (spaceBelow >= popoverRect.height) {\n newYAlign = PopoverYAlign.BELOW;\n }\n }\n\n // Determine optimal X alignment\n let newXAlign = xAlign;\n const spaceRight = viewportWidth - triggerRect.left - padding;\n const spaceLeft = triggerRect.right - padding;\n\n if (xAlign === PopoverXAlign.START && spaceRight < popoverRect.width) {\n // Not enough space on the right, try left\n if (spaceLeft >= popoverRect.width) {\n newXAlign = PopoverXAlign.END;\n }\n } else if (\n xAlign === PopoverXAlign.END &&\n spaceLeft < popoverRect.width\n ) {\n // Not enough space on the left, try right\n if (spaceRight >= popoverRect.width) {\n newXAlign = PopoverXAlign.START;\n }\n }\n\n setComputedYAlign(newYAlign);\n setComputedXAlign(newXAlign);\n });\n };\n\n // Adjust position with a slight delay to ensure DOM is ready\n const timeoutId = setTimeout(adjustPosition, 0);\n\n // Listen to mouse enter on the trigger to recalculate\n const triggerElement = document.getElementById(\n `unrollable-panel-button-${props.identifier}`\n );\n\n if (triggerElement) {\n triggerElement.addEventListener('mouseenter', adjustPosition);\n triggerElement.addEventListener('focusin', adjustPosition);\n }\n\n // Use ResizeObserver to detect popover content size changes\n const resizeObserver = new ResizeObserver(() => {\n adjustPosition();\n });\n\n if (popoverRef.current) {\n resizeObserver.observe(popoverRef.current);\n }\n\n window.addEventListener('resize', adjustPosition);\n window.addEventListener('scroll', adjustPosition, true);\n\n return () => {\n clearTimeout(timeoutId);\n if (triggerElement) {\n triggerElement.removeEventListener('mouseenter', adjustPosition);\n triggerElement.removeEventListener('focusin', adjustPosition);\n }\n resizeObserver.disconnect();\n window.removeEventListener('resize', adjustPosition);\n window.removeEventListener('scroll', adjustPosition, true);\n };\n }, [props.identifier, xAlign, yAlign]);\n\n // Use the static Detail component with computed alignment values\n return (\n <StaticDetail\n {...props}\n xAlign={computedXAlign}\n yAlign={computedYAlign}\n ref={popoverRef}\n style={{\n ...props.style,\n maxWidth: maxWidth ? `${maxWidth}px` : undefined,\n }}\n />\n );\n};\n\n// Create Popover with Detail attached\nexport const Popover: PopoverType = PopoverComponent as PopoverType;\n\nPopover.Detail = Detail;\n"],"mappings":";;;;;;;;;;;;;;;;AAuBA,MAAM,oBAAsC,UAAU;AACpD,QAAO,oBAAC,eAAD,EAAe,GAAI,OAAS;;;;;;;;;;;;;;;;;;AAmBrC,MAAM,UAA2B,EAC/B,kBACA,mBACA,GAAG,YACC;CACJ,MAAM,aAAa,OAAuB,KAAK;CAC/C,MAAM,CAAC,gBAAgB,qBAAqB,SAAS,OAAO;CAC5D,MAAM,CAAC,gBAAgB,qBAAqB,SAAS,OAAO;CAC5D,MAAM,CAAC,UAAU,eAAe,SAA6B,OAAU;AAEvE,iBAAgB;EACd,MAAM,uBAAuB;AAC3B,OAAI,CAAC,WAAW,QAAS;GAEzB,MAAM,iBAAiB,WAAW;GAClC,MAAM,iBAAiB,SAAS,eAC9B,2BAA2B,MAAM,aAClC;AAED,OAAI,CAAC,eAAgB;GAErB,MAAM,cAAc,eAAe,uBAAuB;GAC1D,MAAM,gBAAgB,OAAO;GAC7B,MAAM,iBAAiB,OAAO;GAC9B,MAAM,MAAM;GACZ,MAAM,UAAU;GAGhB,MAAM,mBAAmB,gBAAgB,YAAY,OAAO;GAC5D,MAAM,oBAAoB,YAAY,QAAQ;AAK9C,eAFyB,KAAK,IAAI,kBAAkB,kBAExB,CAAC;GAG7B,MAAM,eAAe,eAAe,UAAU,SAAS,YAAY;AACnE,OAAI,cAAc;AAChB,mBAAe,MAAM,aAAa;AAClC,mBAAe,UAAU,OAAO,YAAY;;AAI9C,+BAA4B;IAC1B,MAAM,cAAc,eAAe,uBAAuB;AAG1D,QAAI,cAAc;AAChB,oBAAe,MAAM,aAAa;AAClC,oBAAe,UAAU,IAAI,YAAY;;IAI3C,IAAI,YAAY;IAChB,MAAM,aAAa,iBAAiB,YAAY,SAAS;IACzD,MAAM,aAAa,YAAY,MAAM;AAErC,QAAI,uBAAkC,aAAa,YAAY,QAE7D;SAAI,cAAc,YAAY,OAC5B;eAGF,sBACA,aAAa,YAAY,QAGzB;SAAI,cAAc,YAAY,OAC5B;;IAKJ,IAAI,YAAY;IAChB,MAAM,aAAa,gBAAgB,YAAY,OAAO;IACtD,MAAM,YAAY,YAAY,QAAQ;AAEtC,QAAI,sBAAkC,aAAa,YAAY,OAE7D;SAAI,aAAa,YAAY,MAC3B;eAGF,oBACA,YAAY,YAAY,OAGxB;SAAI,cAAc,YAAY,MAC5B;;AAIJ,sBAAkB,UAAU;AAC5B,sBAAkB,UAAU;KAC5B;;EAIJ,MAAM,YAAY,WAAW,gBAAgB,EAAE;EAG/C,MAAM,iBAAiB,SAAS,eAC9B,2BAA2B,MAAM,aAClC;AAED,MAAI,gBAAgB;AAClB,kBAAe,iBAAiB,cAAc,eAAe;AAC7D,kBAAe,iBAAiB,WAAW,eAAe;;EAI5D,MAAM,iBAAiB,IAAI,qBAAqB;AAC9C,mBAAgB;IAChB;AAEF,MAAI,WAAW,QACb,gBAAe,QAAQ,WAAW,QAAQ;AAG5C,SAAO,iBAAiB,UAAU,eAAe;AACjD,SAAO,iBAAiB,UAAU,gBAAgB,KAAK;AAEvD,eAAa;AACX,gBAAa,UAAU;AACvB,OAAI,gBAAgB;AAClB,mBAAe,oBAAoB,cAAc,eAAe;AAChE,mBAAe,oBAAoB,WAAW,eAAe;;AAE/D,kBAAe,YAAY;AAC3B,UAAO,oBAAoB,UAAU,eAAe;AACpD,UAAO,oBAAoB,UAAU,gBAAgB,KAAK;;IAE3D;EAAC,MAAM;EAAY;EAAQ;EAAO,CAAC;AAGtC,QACE,oBAACA,UAAD;EACE,GAAI;EACJ,QAAQ;EACR,QAAQ;EACR,KAAK;EACL,OAAO;GACL,GAAG,MAAM;GACT,UAAU,WAAW,GAAG,SAAS,MAAM;GACxC;EACD;;AAKN,MAAa,UAAuB;AAEpC,QAAQ,SAAS"}
@@ -1,12 +1,12 @@
1
1
  'use client';
2
2
 
3
+ import { useGetElementOrWindow } from "../../hooks/useGetElementOrWindow.mjs";
4
+ import { useDevice } from "../../hooks/useDevice.mjs";
5
+ import { useScrollBlockage } from "../../hooks/useScrollBlockage/index.mjs";
3
6
  import { Container } from "../Container/index.mjs";
4
7
  import { Button, ButtonColor, ButtonSize, ButtonVariant } from "../Button/Button.mjs";
5
- import { useDevice } from "../../hooks/useDevice.mjs";
6
8
  import { KeyboardShortcut } from "../KeyboardShortcut/KeyboardShortcut.mjs";
7
9
  import { Popover } from "../Popover/dynamic.mjs";
8
- import { useGetElementOrWindow } from "../../hooks/useGetElementOrWindow.mjs";
9
- import { useScrollBlockage } from "../../hooks/useScrollBlockage/index.mjs";
10
10
  import { MaxWidthSmoother } from "../MaxWidthSmoother/index.mjs";
11
11
  import { isElementAtTopAndNotCovered } from "./isElementAtTopAndNotCovered.mjs";
12
12
  import { useRightDrawer } from "./useRightDrawer.mjs";