@intlayer/design-system 8.11.2 → 8.11.3

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 (61) hide show
  1. package/dist/esm/api/useAuth/useOAuth2.mjs +2 -2
  2. package/dist/esm/api/useAuth/useSession.mjs +1 -1
  3. package/dist/esm/api/useIntlayerAPI.mjs +1 -1
  4. package/dist/esm/components/Accordion/Accordion.mjs +1 -1
  5. package/dist/esm/components/Accordion/Accordion.mjs.map +1 -1
  6. package/dist/esm/components/Carousel/index.mjs +7 -9
  7. package/dist/esm/components/Carousel/index.mjs.map +1 -1
  8. package/dist/esm/components/ContentEditor/ContentEditorTextArea.mjs +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 +4 -4
  12. package/dist/esm/components/DictionaryFieldEditor/DictionaryFieldEditor.mjs +1 -1
  13. package/dist/esm/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.mjs +1 -1
  14. package/dist/esm/components/DictionaryFieldEditor/SaveForm/SaveForm.mjs +2 -2
  15. package/dist/esm/components/DictionaryFieldEditor/StructureView/StructureView.mjs +1 -1
  16. package/dist/esm/components/Form/elements/OTPElement.mjs +1 -1
  17. package/dist/esm/components/IDE/MonacoCode.mjs +1 -1
  18. package/dist/esm/components/IDE/MonacoCode.mjs.map +1 -1
  19. package/dist/esm/components/Link/Link.mjs +13 -3
  20. package/dist/esm/components/Link/Link.mjs.map +1 -1
  21. package/dist/esm/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.mjs +1 -1
  22. package/dist/esm/components/Modal/Modal.mjs +3 -3
  23. package/dist/esm/components/Modal/Modal.mjs.map +1 -1
  24. package/dist/esm/components/Navbar/MobileNavbar.mjs +1 -1
  25. package/dist/esm/components/Pagination/Pagination.mjs +1 -1
  26. package/dist/esm/components/Pattern/DotPattern.mjs +1 -1
  27. package/dist/esm/components/Pattern/DotPattern.mjs.map +1 -1
  28. package/dist/esm/components/RightDrawer/RightDrawer.mjs +3 -3
  29. package/dist/esm/components/Steps/index.mjs +38 -0
  30. package/dist/esm/components/Steps/index.mjs.map +1 -0
  31. package/dist/esm/components/SwitchSelector/SwitchSelector.mjs +1 -1
  32. package/dist/esm/components/SwitchSelector/SwitchSelector.mjs.map +1 -1
  33. package/dist/esm/components/Tab/Tab.mjs +1 -1
  34. package/dist/esm/components/Table/TableElements.mjs +1 -1
  35. package/dist/esm/components/Table/TableElements.mjs.map +1 -1
  36. package/dist/esm/components/WithResizer/index.mjs +1 -1
  37. package/dist/esm/components/WithResizer/index.mjs.map +1 -1
  38. package/dist/esm/components/index.mjs +2 -1
  39. package/dist/esm/hooks/index.mjs +8 -8
  40. package/dist/types/api/useIntlayerAPI.d.ts +3 -3
  41. package/dist/types/components/Badge/index.d.ts +3 -3
  42. package/dist/types/components/Button/Button.d.ts +4 -4
  43. package/dist/types/components/Carousel/index.d.ts +3 -1
  44. package/dist/types/components/Carousel/index.d.ts.map +1 -1
  45. package/dist/types/components/CollapsibleTable/CollapsibleTable.d.ts +3 -3
  46. package/dist/types/components/Command/index.d.ts +10 -10
  47. package/dist/types/components/Container/index.d.ts +6 -6
  48. package/dist/types/components/DictionaryFieldEditor/DictionaryDetails/useDictionaryDetailsSchema.d.ts +1 -1
  49. package/dist/types/components/Input/Checkbox.d.ts +2 -2
  50. package/dist/types/components/Input/Input.d.ts +1 -1
  51. package/dist/types/components/Input/OTPInput.d.ts +1 -1
  52. package/dist/types/components/Link/Link.d.ts +5 -5
  53. package/dist/types/components/Link/Link.d.ts.map +1 -1
  54. package/dist/types/components/Pagination/Pagination.d.ts +1 -1
  55. package/dist/types/components/Steps/index.d.ts +17 -0
  56. package/dist/types/components/Steps/index.d.ts.map +1 -0
  57. package/dist/types/components/SwitchSelector/SwitchSelector.d.ts +1 -1
  58. package/dist/types/components/SwitchSelector/VerticalSwitchSelector.d.ts +1 -1
  59. package/dist/types/components/Tag/index.d.ts +2 -2
  60. package/dist/types/components/index.d.ts +2 -1
  61. package/package.json +19 -14
@@ -1,9 +1,9 @@
1
1
  'use client';
2
2
 
3
- import { editor } from "@intlayer/config/built";
4
3
  import { useQuery } from "@tanstack/react-query";
5
- import { getOAuthAPI } from "@intlayer/api";
4
+ import { editor } from "@intlayer/config/built";
6
5
  import { useConfiguration } from "@intlayer/editor-react";
6
+ import { getOAuthAPI } from "@intlayer/api";
7
7
  import { defu } from "defu";
8
8
 
9
9
  //#region src/api/useAuth/useOAuth2.ts
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
 
3
3
  import { getAuthAPI } from "../../libs/auth.mjs";
4
- import { editor } from "@intlayer/config/built";
5
4
  import { useQuery, useQueryClient } from "@tanstack/react-query";
5
+ import { editor } from "@intlayer/config/built";
6
6
  import { useConfiguration } from "@intlayer/editor-react";
7
7
 
8
8
  //#region src/api/useAuth/useSession.ts
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { getAuthAPI } from "../libs/auth.mjs";
4
4
  import { useAuth } from "./useAuth/useAuth.mjs";
5
+ import { useConfiguration } from "@intlayer/editor-react";
5
6
  import { getIntlayerAPI } from "@intlayer/api";
6
7
  import { getAiAPI } from "@intlayer/api/ai";
7
8
  import { getAuditAPI } from "@intlayer/api/audit";
@@ -21,7 +22,6 @@ import { getStripeAPI } from "@intlayer/api/stripe";
21
22
  import { getTagAPI } from "@intlayer/api/tag";
22
23
  import { getTranslateAPI } from "@intlayer/api/translate";
23
24
  import { getUserAPI } from "@intlayer/api/user";
24
- import { useConfiguration } from "@intlayer/editor-react";
25
25
 
26
26
  //#region src/api/useIntlayerAPI.ts
27
27
  const useIntlayerOAuthOptions = (props) => {
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { cn } from "../../utils/cn.mjs";
4
- import { Button, ButtonColor, ButtonVariant } from "../Button/Button.mjs";
4
+ import { Button } from "../Button/Button.mjs";
5
5
  import { MaxHeightSmoother } from "../MaxHeightSmoother/index.mjs";
6
6
  import { useId, useState } from "react";
7
7
  import { ChevronDown } from "lucide-react";
@@ -1 +1 @@
1
- {"version":3,"file":"Accordion.mjs","names":[],"sources":["../../../../src/components/Accordion/Accordion.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport { ChevronDown } from 'lucide-react';\nimport {\n type FC,\n type KeyboardEvent,\n type MouseEvent,\n type ReactNode,\n useId,\n useState,\n} from 'react';\nimport {\n Button,\n ButtonColor,\n type ButtonProps,\n ButtonVariant,\n} from '../Button';\nimport { MaxHeightSmoother } from '../MaxHeightSmoother';\n\nexport interface AccordionProps\n extends Omit<ButtonProps, 'children' | 'onToggle'> {\n /** The content displayed in the accordion header */\n header: ReactNode;\n /** The collapsible content inside the accordion */\n children: ReactNode;\n /** Controls whether the accordion is open (controlled mode) */\n isOpen?: boolean;\n /** Default open state (uncontrolled mode) */\n defaultIsOpen?: boolean;\n /** Called when the accordion state changes */\n onToggle?: (isOpen: boolean) => void;\n /** Disable the accordion interaction */\n disabled?: boolean;\n /** Custom class for the content container */\n contentClassName?: string;\n /** Custom class for the header container */\n headerClassName?: string;\n /** Accessible label for screen readers */\n 'aria-label'?: string;\n /** ID for the accordion content (for aria-controls) */\n contentId?: string;\n}\n\n/**\n * Accordion component that allows the user to expand and collapse content.\n * It provides a header with a chevron icon that controls the visibility of the content.\n *\n * Features:\n * - Supports both controlled and uncontrolled modes\n * - Accessible with proper ARIA attributes\n * - Keyboard navigation support\n * - Smooth animations for expand/collapse\n * - Customizable styling\n *\n * @param header - The content of the header.\n * @param children - The content to be expanded and collapsed.\n * @param isOpen - Controlled state for whether the content is expanded.\n * @param defaultIsOpen - Default open state for uncontrolled mode.\n * @param onToggle - Callback when the accordion state changes.\n * @param disabled - Whether the accordion is disabled.\n * @param contentClassName - Custom class for the content container.\n * @param headerClassName - Custom class for the header.\n * @param contentId - ID for the content (used for aria-controls).\n *\n * @example\n * // Uncontrolled mode\n * <Accordion header=\"Accordion Header\" defaultIsOpen={true}>\n * <p>Accordion content</p>\n * </Accordion>\n *\n * @example\n * // Controlled mode\n * <Accordion\n * header=\"Controlled Accordion\"\n * isOpen={isOpen}\n * onToggle={setIsOpen}\n * >\n * <p>Controlled content</p>\n * </Accordion>\n */\nexport const Accordion: FC<AccordionProps> = ({\n children,\n header,\n isOpen,\n defaultIsOpen = false,\n onToggle,\n onClick,\n disabled = false,\n contentClassName,\n headerClassName,\n contentId,\n 'aria-label': ariaLabel,\n ...props\n}) => {\n // Determine if we're in controlled or uncontrolled mode\n const isControlled = isOpen !== undefined;\n const [internalIsOpen, setInternalIsOpen] = useState(defaultIsOpen);\n const id = useId();\n\n // Use controlled value if provided, otherwise use internal state\n const isExpandedState = isControlled ? isOpen : internalIsOpen;\n const isHidden = !isExpandedState;\n\n // Generate unique ID for content if not provided\n const generatedContentId = contentId ?? `${id}-accordion-content`;\n\n const handleToggle = (e: MouseEvent<HTMLButtonElement>) => {\n if (disabled) return;\n\n const newIsOpen = !isExpandedState;\n\n // Update internal state if uncontrolled\n if (!isControlled) {\n setInternalIsOpen(newIsOpen);\n }\n\n // Call external handlers\n onToggle?.(newIsOpen);\n onClick?.(e);\n };\n\n const handleKeyDown = (e: KeyboardEvent<HTMLButtonElement>) => {\n // Enter and Space should toggle the accordion\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleToggle(e as any);\n }\n };\n\n return (\n <div className=\"w-full\">\n <Button\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n onClick={handleToggle}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n isFullWidth\n className={cn(\n 'flex items-center justify-between gap-2',\n headerClassName\n )}\n IconRight={ChevronDown}\n iconClassName={cn(\n 'transform transition-transform duration-500 ease-in-out',\n isExpandedState ? 'rotate-0' : '-rotate-180'\n )}\n aria-expanded={isExpandedState}\n aria-controls={generatedContentId}\n aria-label={ariaLabel}\n role=\"button\"\n {...props}\n >\n {header}\n </Button>\n\n <MaxHeightSmoother\n id={generatedContentId}\n tabIndex={isHidden ? -1 : undefined}\n isHidden={isHidden}\n className={contentClassName}\n role=\"region\"\n aria-labelledby={generatedContentId}\n >\n {children}\n </MaxHeightSmoother>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiFA,MAAa,aAAiC,EAC5C,UACA,QACA,QACA,gBAAgB,OAChB,UACA,SACA,WAAW,OACX,kBACA,iBACA,WACA,cAAc,WACd,GAAG,YACC;CAEJ,MAAM,eAAe,WAAW;CAChC,MAAM,CAAC,gBAAgB,qBAAqB,SAAS,aAAa;CAClE,MAAM,KAAK,MAAM;CAGjB,MAAM,kBAAkB,eAAe,SAAS;CAChD,MAAM,WAAW,CAAC;CAGlB,MAAM,qBAAqB,aAAa,GAAG,GAAG;CAE9C,MAAM,gBAAgB,MAAqC;EACzD,IAAI,UAAU;EAEd,MAAM,YAAY,CAAC;EAGnB,IAAI,CAAC,cACH,kBAAkB,SAAS;EAI7B,WAAW,SAAS;EACpB,UAAU,CAAC;CACb;CAEA,MAAM,iBAAiB,MAAwC;EAE7D,IAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;GACtC,EAAE,eAAe;GACjB,aAAa,CAAQ;EACvB;CACF;CAEA,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,oBAAC,QAAD;GACE;GACA;GACA,SAAS;GACT,WAAW;GACD;GACV;GACA,WAAW,GACT,2CACA,eACF;GACA,WAAW;GACX,eAAe,GACb,2DACA,kBAAkB,aAAa,aACjC;GACA,iBAAe;GACf,iBAAe;GACf,cAAY;GACZ,MAAK;GACL,GAAI;aAEH;EACK,IAER,oBAAC,mBAAD;GACE,IAAI;GACJ,UAAU,WAAW,KAAK;GAChB;GACV,WAAW;GACX,MAAK;GACL,mBAAiB;GAEhB;EACgB,EAChB;;AAET"}
1
+ {"version":3,"file":"Accordion.mjs","names":[],"sources":["../../../../src/components/Accordion/Accordion.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport { ChevronDown } from 'lucide-react';\nimport {\n type FC,\n type KeyboardEvent,\n type MouseEvent,\n type ReactNode,\n useId,\n useState,\n} from 'react';\nimport {\n Button,\n ButtonColor,\n type ButtonProps,\n ButtonVariant,\n} from '../Button';\nimport { MaxHeightSmoother } from '../MaxHeightSmoother';\n\nexport interface AccordionProps\n extends Omit<ButtonProps, 'children' | 'onToggle'> {\n /** The content displayed in the accordion header */\n header: ReactNode;\n /** The collapsible content inside the accordion */\n children: ReactNode;\n /** Controls whether the accordion is open (controlled mode) */\n isOpen?: boolean;\n /** Default open state (uncontrolled mode) */\n defaultIsOpen?: boolean;\n /** Called when the accordion state changes */\n onToggle?: (isOpen: boolean) => void;\n /** Disable the accordion interaction */\n disabled?: boolean;\n /** Custom class for the content container */\n contentClassName?: string;\n /** Custom class for the header container */\n headerClassName?: string;\n /** Accessible label for screen readers */\n 'aria-label'?: string;\n /** ID for the accordion content (for aria-controls) */\n contentId?: string;\n}\n\n/**\n * Accordion component that allows the user to expand and collapse content.\n * It provides a header with a chevron icon that controls the visibility of the content.\n *\n * Features:\n * - Supports both controlled and uncontrolled modes\n * - Accessible with proper ARIA attributes\n * - Keyboard navigation support\n * - Smooth animations for expand/collapse\n * - Customizable styling\n *\n * @param header - The content of the header.\n * @param children - The content to be expanded and collapsed.\n * @param isOpen - Controlled state for whether the content is expanded.\n * @param defaultIsOpen - Default open state for uncontrolled mode.\n * @param onToggle - Callback when the accordion state changes.\n * @param disabled - Whether the accordion is disabled.\n * @param contentClassName - Custom class for the content container.\n * @param headerClassName - Custom class for the header.\n * @param contentId - ID for the content (used for aria-controls).\n *\n * @example\n * // Uncontrolled mode\n * <Accordion header=\"Accordion Header\" defaultIsOpen={true}>\n * <p>Accordion content</p>\n * </Accordion>\n *\n * @example\n * // Controlled mode\n * <Accordion\n * header=\"Controlled Accordion\"\n * isOpen={isOpen}\n * onToggle={setIsOpen}\n * >\n * <p>Controlled content</p>\n * </Accordion>\n */\nexport const Accordion: FC<AccordionProps> = ({\n children,\n header,\n isOpen,\n defaultIsOpen = false,\n onToggle,\n onClick,\n disabled = false,\n contentClassName,\n headerClassName,\n contentId,\n 'aria-label': ariaLabel,\n ...props\n}) => {\n // Determine if we're in controlled or uncontrolled mode\n const isControlled = isOpen !== undefined;\n const [internalIsOpen, setInternalIsOpen] = useState(defaultIsOpen);\n const id = useId();\n\n // Use controlled value if provided, otherwise use internal state\n const isExpandedState = isControlled ? isOpen : internalIsOpen;\n const isHidden = !isExpandedState;\n\n // Generate unique ID for content if not provided\n const generatedContentId = contentId ?? `${id}-accordion-content`;\n\n const handleToggle = (e: MouseEvent<HTMLButtonElement>) => {\n if (disabled) return;\n\n const newIsOpen = !isExpandedState;\n\n // Update internal state if uncontrolled\n if (!isControlled) {\n setInternalIsOpen(newIsOpen);\n }\n\n // Call external handlers\n onToggle?.(newIsOpen);\n onClick?.(e);\n };\n\n const handleKeyDown = (e: KeyboardEvent<HTMLButtonElement>) => {\n // Enter and Space should toggle the accordion\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleToggle(e as any);\n }\n };\n\n return (\n <div className=\"w-full\">\n <Button\n variant=\"hoverable\"\n color=\"text\"\n onClick={handleToggle}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n isFullWidth\n className={cn(\n 'flex items-center justify-between gap-2',\n headerClassName\n )}\n IconRight={ChevronDown}\n iconClassName={cn(\n 'transform transition-transform duration-500 ease-in-out',\n isExpandedState ? 'rotate-0' : '-rotate-180'\n )}\n aria-expanded={isExpandedState}\n aria-controls={generatedContentId}\n aria-label={ariaLabel}\n role=\"button\"\n {...props}\n >\n {header}\n </Button>\n\n <MaxHeightSmoother\n id={generatedContentId}\n tabIndex={isHidden ? -1 : undefined}\n isHidden={isHidden}\n className={contentClassName}\n role=\"region\"\n aria-labelledby={generatedContentId}\n >\n {children}\n </MaxHeightSmoother>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiFA,MAAa,aAAiC,EAC5C,UACA,QACA,QACA,gBAAgB,OAChB,UACA,SACA,WAAW,OACX,kBACA,iBACA,WACA,cAAc,WACd,GAAG,YACC;CAEJ,MAAM,eAAe,WAAW;CAChC,MAAM,CAAC,gBAAgB,qBAAqB,SAAS,aAAa;CAClE,MAAM,KAAK,MAAM;CAGjB,MAAM,kBAAkB,eAAe,SAAS;CAChD,MAAM,WAAW,CAAC;CAGlB,MAAM,qBAAqB,aAAa,GAAG,GAAG;CAE9C,MAAM,gBAAgB,MAAqC;EACzD,IAAI,UAAU;EAEd,MAAM,YAAY,CAAC;EAGnB,IAAI,CAAC,cACH,kBAAkB,SAAS;EAI7B,WAAW,SAAS;EACpB,UAAU,CAAC;CACb;CAEA,MAAM,iBAAiB,MAAwC;EAE7D,IAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;GACtC,EAAE,eAAe;GACjB,aAAa,CAAQ;EACvB;CACF;CAEA,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,oBAAC,QAAD;GACE,SAAQ;GACR,OAAM;GACN,SAAS;GACT,WAAW;GACD;GACV;GACA,WAAW,GACT,2CACA,eACF;GACA,WAAW;GACX,eAAe,GACb,2DACA,kBAAkB,aAAa,aACjC;GACA,iBAAe;GACf,iBAAe;GACf,cAAY;GACZ,MAAK;GACL,GAAI;aAEH;EACK,IAER,oBAAC,mBAAD;GACE,IAAI;GACJ,UAAU,WAAW,KAAK;GAChB;GACV,WAAW;GACX,MAAK;GACL,mBAAiB;GAEhB;EACgB,EAChB;;AAET"}
@@ -37,19 +37,17 @@ const getCardScale = (index, displayedIndex) => {
37
37
  const getCardPositionX = (index, displayedIndex, containerWidth) => {
38
38
  return `${(index - displayedIndex) * Math.min(containerWidth * (containerWidth < 600 ? .15 : .3), 300)}px`;
39
39
  };
40
- const CarouselItem = ({ children, className, ...props }) => {
41
- return /* @__PURE__ */ jsx("div", {
42
- className: cn("h-full w-full", className),
43
- ...props,
44
- children
45
- });
46
- };
40
+ const CarouselItem = Object.assign(({ children, className, ...props }) => /* @__PURE__ */ jsx("div", {
41
+ className: cn("size-full", className),
42
+ ...props,
43
+ children
44
+ }), { isCarouselItem: true });
47
45
  const CarouselIndicators = ({ className, disableKeyboardShortcuts = false, ...props }) => {
48
46
  const { selectedIndex, setSelectedIndex, totalItems, handlePrev, handleNext } = useCarousel();
49
47
  const { goToSlide, previousSlide, nextSlide } = useIntlayer("carousel");
50
48
  if (totalItems <= 1) return null;
51
49
  return /* @__PURE__ */ jsxs("div", {
52
- className: cn("absolute bottom-4 left-1/2 z-50 flex -translate-x-1/2 flex-row items-center gap-2", className),
50
+ className: cn("absolute bottom-0 left-1/2 z-50 flex -translate-x-1/2 flex-row items-center gap-2 pb-4", className),
53
51
  ...props,
54
52
  children: [
55
53
  /* @__PURE__ */ jsxs(Popover, {
@@ -131,7 +129,7 @@ const partitionCarouselChildren = (children) => {
131
129
  const slides = [];
132
130
  const others = [];
133
131
  children.forEach((child) => {
134
- if (isValidElement(child) && child.type === CarouselItem) slides.push(child);
132
+ if (isValidElement(child) && (child.type === CarouselItem || child.type.isCarouselItem === true)) slides.push(child);
135
133
  else others.push(child);
136
134
  });
137
135
  return [slides, others];
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/components/Carousel/index.tsx"],"sourcesContent":["'use client';\n\nimport {\n Button,\n ButtonColor,\n ButtonSize,\n ButtonVariant,\n} from '@components/Button';\nimport { KeyboardShortcut } from '@components/KeyboardShortcut';\nimport { Popover } from '@components/Popover';\nimport { cn } from '@utils/cn';\nimport { ChevronLeft, ChevronRight } from 'lucide-react';\nimport {\n Children,\n createContext,\n type FC,\n type HTMLAttributes,\n isValidElement,\n type MouseEventHandler,\n type ReactElement,\n type ReactNode,\n type TouchEventHandler,\n useContext,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport { useIntlayer } from 'react-intlayer';\n\n// ------------------------------------------------------------------\n// Configuration\n// ------------------------------------------------------------------\nconst SWIPE_THRESHOLD_DIVISOR = 5;\nconst TRANSITION_DELAY_MS = 50;\n\n// ------------------------------------------------------------------\n// Context Definition\n// ------------------------------------------------------------------\ntype CarouselContextValue = {\n selectedIndex: number;\n setSelectedIndex: (index: number) => void;\n totalItems: number;\n handlePrev: () => void;\n handleNext: () => void;\n};\n\nconst CarouselContext = createContext<CarouselContextValue | null>(null);\n\nconst useCarousel = () => {\n const context = useContext(CarouselContext);\n if (!context) {\n throw new Error('useCarousel must be used within a Carousel');\n }\n return context;\n};\n\n// ------------------------------------------------------------------\n// Helper Functions\n// ------------------------------------------------------------------\nconst getCardStyle = (index: number, displayedIndex: number) => {\n const diff = Math.abs(index - displayedIndex);\n switch (diff) {\n case 0:\n return 'opacity-100 z-40';\n case 1:\n return 'opacity-75 z-30 cursor-pointer';\n case 2:\n return 'opacity-50 z-20 pointer-events-none';\n default:\n return 'opacity-0 z-10 pointer-events-none';\n }\n};\n\nconst getCardScale = (index: number, displayedIndex: number) => {\n const diff = Math.abs(index - displayedIndex);\n switch (diff) {\n case 0:\n return 1;\n case 1:\n return 0.9;\n case 2:\n return 0.8;\n default:\n return 0.7;\n }\n};\n\n// This allows the calculation to work on SSR without hydration mismatch.\n// Your original logic: (3 * screenWidth) / 10 === 30% of viewport width\nconst getCardPositionX = (\n index: number,\n displayedIndex: number,\n containerWidth: number\n) => {\n const diff = index - displayedIndex;\n const gapPercentage = containerWidth < 600 ? 0.15 : 0.3; // Dropped to 15% for a tighter cluster\n const step = Math.min(containerWidth * gapPercentage, 300);\n\n // The 'px' here is mandatory\n return `${diff * step}px`;\n};\n\n// ------------------------------------------------------------------\n// Sub-Component: Item\n// ------------------------------------------------------------------\ntype CarouselItemProps = HTMLAttributes<HTMLDivElement> & {\n children: ReactNode;\n};\n\nconst CarouselItem: FC<CarouselItemProps> = ({\n children,\n className,\n ...props\n}) => {\n return (\n <div className={cn('h-full w-full', className)} {...props}>\n {children}\n </div>\n );\n};\n\n// ------------------------------------------------------------------\n// Sub-Component: Indicators (Controller)\n// ------------------------------------------------------------------\ntype CarouselIndicatorsProps = HTMLAttributes<HTMLDivElement> & {\n disableKeyboardShortcuts?: boolean;\n};\n\nconst CarouselIndicators: FC<CarouselIndicatorsProps> = ({\n className,\n disableKeyboardShortcuts = false,\n ...props\n}) => {\n const {\n selectedIndex,\n setSelectedIndex,\n totalItems,\n handlePrev,\n handleNext,\n } = useCarousel();\n const { goToSlide, previousSlide, nextSlide } = useIntlayer('carousel');\n\n if (totalItems <= 1) return null;\n\n return (\n <div\n className={cn(\n 'absolute bottom-4 left-1/2 z-50 flex -translate-x-1/2 flex-row items-center gap-2',\n className\n )}\n {...props}\n >\n <Popover identifier=\"carousel-prev\">\n <Button\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.NEUTRAL}\n label={previousSlide.value}\n roundedSize=\"full\"\n onClick={(e) => {\n e.stopPropagation();\n handlePrev();\n }}\n Icon={ChevronLeft}\n size={ButtonSize.ICON_MD}\n disabled={selectedIndex === 0}\n />\n\n <Popover.Detail identifier=\"carousel-prev\">\n <div className=\"flex items-center gap-2 p-2\">\n <span className=\"whitespace-nowrap text-neutral text-xs\">\n {previousSlide.value}\n </span>\n <KeyboardShortcut\n shortcut=\"ArrowLeft\"\n disabled={disableKeyboardShortcuts}\n size=\"sm\"\n onTriggered={handlePrev}\n />\n </div>\n </Popover.Detail>\n </Popover>\n\n {Array.from({ length: totalItems }).map((_, index) => {\n const isActive = index === selectedIndex;\n return (\n <button\n key={index}\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n setSelectedIndex(index);\n }}\n aria-label={goToSlide({ index: index + 1 }).value}\n className={cn(\n 'h-2.5 w-2.5 rounded-full transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-neutral-400 focus:ring-offset-2',\n isActive ? 'scale-110 bg-text' : 'bg-text/20 hover:bg-text/40'\n )}\n />\n );\n })}\n\n <Popover identifier=\"carousel-next\">\n <Button\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.NEUTRAL}\n roundedSize=\"full\"\n label={nextSlide.value}\n onClick={(e) => {\n e.stopPropagation();\n handleNext();\n }}\n Icon={ChevronRight}\n size={ButtonSize.ICON_MD}\n disabled={selectedIndex === totalItems - 1}\n />\n\n <Popover.Detail identifier=\"carousel-next\">\n <div className=\"flex items-center gap-2 p-2\">\n <span className=\"whitespace-nowrap text-neutral text-xs\">\n {nextSlide.value}\n </span>\n <KeyboardShortcut\n shortcut=\"ArrowRight\"\n size=\"sm\"\n onTriggered={handleNext}\n disabled={disableKeyboardShortcuts}\n />\n </div>\n </Popover.Detail>\n </Popover>\n </div>\n );\n};\n\n// ------------------------------------------------------------------\n// Main Component: Carousel Root\n// ------------------------------------------------------------------\ntype CarouselProps = HTMLAttributes<HTMLDivElement> & {\n children: ReactNode;\n initialIndex?: number;\n onIndexChange?: (index: number) => void;\n};\n\nconst partitionCarouselChildren = (\n children: ReactNode[]\n): [ReactElement[], ReactNode[]] => {\n const slides: ReactElement[] = [];\n const others: ReactNode[] = [];\n\n children.forEach((child) => {\n if (isValidElement(child) && child.type === CarouselItem) {\n slides.push(child);\n } else {\n others.push(child);\n }\n });\n\n return [slides, others];\n};\n\nconst CarouselRoot: FC<CarouselProps> = ({\n children,\n className,\n initialIndex = 0,\n onIndexChange,\n ...props\n}) => {\n const allChildren = Children.toArray(children);\n const [slides, others] = partitionCarouselChildren(allChildren);\n const totalItems = slides.length;\n\n // State Management\n const [selectedIndex, setSelectedIndex] = useState<number>(initialIndex);\n const [displayedIndex, setDisplayedIndex] = useState<number>(initialIndex);\n const [containerHeight, setContainerHeight] = useState<number>(0);\n const [containerWidth, setContainerWidth] = useState<number>(0);\n\n useLayoutEffect(() => {\n const calculateDimensions = () => {\n if (!containerRef.current) return;\n\n // Track Width\n const width = containerRef.current.clientWidth;\n setContainerWidth(width);\n\n // Track Height (existing logic)\n const heights = itemsRef.current.map((item) => item?.offsetHeight || 0);\n const maxHeight = Math.max(0, ...heights);\n if (maxHeight > 0) {\n setContainerHeight(maxHeight + 40);\n }\n };\n\n calculateDimensions();\n\n const observer = new ResizeObserver(() => {\n calculateDimensions();\n });\n\n if (containerRef.current) observer.observe(containerRef.current);\n itemsRef.current.forEach((item) => {\n if (item) observer.observe(item);\n });\n\n return () => observer.disconnect();\n }, [totalItems]);\n\n // Drag State\n const [startX, setStartX] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n\n // Refs\n const containerRef = useRef<HTMLDivElement>(null);\n const itemsRef = useRef<(HTMLDivElement | null)[]>([]);\n\n // Navigation Logic\n const handleSwitchItem = (diff: number) => {\n if (containerWidth === 0) return;\n\n // Use container width for the threshold\n const swipeStep = containerWidth / SWIPE_THRESHOLD_DIVISOR;\n const numSwipe = Math.round(diff / swipeStep);\n\n if (Math.abs(numSwipe) >= 1) {\n const newIndex = displayedIndex - numSwipe;\n const clampedIndex = Math.max(0, Math.min(newIndex, totalItems - 1));\n\n if (clampedIndex !== selectedIndex) {\n setSelectedIndex(clampedIndex);\n setStartX((prev) => prev + diff);\n }\n }\n };\n\n const handleNext = () => {\n setSelectedIndex((prev) => Math.min(prev + 1, totalItems - 1));\n };\n\n const handlePrev = () => {\n setSelectedIndex((prev) => Math.max(prev - 1, 0));\n };\n\n // Input Handlers\n const handleMouseDown: MouseEventHandler<HTMLDivElement> = (e) => {\n setIsDragging(true);\n setStartX(e.clientX);\n };\n const handleMouseMove: MouseEventHandler<HTMLDivElement> = (e) => {\n if (isDragging) handleSwitchItem(e.clientX - startX);\n };\n const handleDragEnd = () => setIsDragging(false);\n const handleTouchStart: TouchEventHandler<HTMLDivElement> = (e) => {\n setIsDragging(true);\n setStartX(e.touches[0].clientX);\n };\n const handleTouchMove: TouchEventHandler<HTMLDivElement> = (e) => {\n if (isDragging) handleSwitchItem(e.touches[0].clientX - startX);\n };\n\n // Effects\n useEffect(() => {\n if (selectedIndex) onIndexChange?.(selectedIndex);\n }, [selectedIndex, onIndexChange]);\n\n useEffect(() => {\n let interval: NodeJS.Timeout;\n\n if (selectedIndex !== displayedIndex) {\n interval = setInterval(() => {\n setDisplayedIndex((prev) => {\n if (prev === selectedIndex) {\n clearInterval(interval);\n return prev;\n }\n return prev < selectedIndex ? prev + 1 : prev - 1;\n });\n }, TRANSITION_DELAY_MS);\n }\n return () => clearInterval(interval);\n }, [selectedIndex, displayedIndex]);\n\n // Calculate height based on the MAX height of ALL items\n useLayoutEffect(() => {\n const calculateMaxHeight = () => {\n const heights = itemsRef.current.map((item) => item?.offsetHeight || 0);\n const maxHeight = Math.max(0, ...heights);\n\n if (maxHeight > 0) {\n setContainerHeight(maxHeight + 40);\n }\n };\n\n calculateMaxHeight();\n\n const observer = new ResizeObserver(() => {\n calculateMaxHeight();\n });\n\n itemsRef.current.forEach((item) => {\n if (item) observer.observe(item);\n });\n\n return () => observer.disconnect();\n }, [totalItems]); // Removed isMounted dependency\n\n return (\n <CarouselContext.Provider\n value={{\n selectedIndex,\n setSelectedIndex,\n totalItems,\n handlePrev,\n handleNext,\n }}\n >\n <div\n ref={containerRef}\n className={cn(\n 'relative flex w-full cursor-grab select-none items-center overflow-hidden outline-none transition-[height] duration-300 ease-in-out focus:outline-none focus:outline-none focus:ring-0 active:cursor-grabbing',\n 'max-w-[1400px]',\n className\n )}\n style={{\n height: containerHeight > 0 ? containerHeight : 'auto',\n minHeight: '400px',\n }}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleDragEnd}\n onMouseLeave={handleDragEnd}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleDragEnd}\n role=\"region\"\n aria-label=\"Carousel\"\n {...props}\n >\n {slides.map((child, index) => {\n return (\n <div\n key={index}\n role=\"button\"\n tabIndex={0}\n ref={(el) => {\n itemsRef.current[index] = el;\n }}\n // FIX 2: Removed isMounted checks and invisible classes.\n // CSS units allow correct SSR rendering.\n className={cn(\n 'absolute left-1/2 -translate-x-1/2 transition-all duration-300 ease-in-out',\n 'outline-none ring-0 focus:outline-none focus:ring-0 focus:ring-offset-0 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0',\n getCardStyle(index, displayedIndex)\n )}\n onClick={(e) => {\n e.stopPropagation();\n setSelectedIndex(index);\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') setSelectedIndex(index);\n }}\n style={{\n transform: `\n translateX(${getCardPositionX(\n index,\n displayedIndex,\n containerWidth\n )})\n scale(${getCardScale(index, displayedIndex)})\n `,\n }}\n >\n {child}\n </div>\n );\n })}\n\n {others}\n </div>\n </CarouselContext.Provider>\n );\n};\n\nexport const Carousel = Object.assign(CarouselRoot, {\n Item: CarouselItem,\n Indicators: CarouselIndicators,\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/components/Carousel/index.tsx"],"sourcesContent":["'use client';\n\nimport {\n Button,\n ButtonColor,\n ButtonSize,\n ButtonVariant,\n} from '@components/Button';\nimport { KeyboardShortcut } from '@components/KeyboardShortcut';\nimport { Popover } from '@components/Popover';\nimport { cn } from '@utils/cn';\nimport { ChevronLeft, ChevronRight } from 'lucide-react';\nimport {\n Children,\n createContext,\n type FC,\n type HTMLAttributes,\n isValidElement,\n type MouseEventHandler,\n type ReactElement,\n type ReactNode,\n type TouchEventHandler,\n useContext,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport { useIntlayer } from 'react-intlayer';\n\n// ------------------------------------------------------------------\n// Configuration\n// ------------------------------------------------------------------\nconst SWIPE_THRESHOLD_DIVISOR = 5;\nconst TRANSITION_DELAY_MS = 50;\n\n// ------------------------------------------------------------------\n// Context Definition\n// ------------------------------------------------------------------\ntype CarouselContextValue = {\n selectedIndex: number;\n setSelectedIndex: (index: number) => void;\n totalItems: number;\n handlePrev: () => void;\n handleNext: () => void;\n};\n\nconst CarouselContext = createContext<CarouselContextValue | null>(null);\n\nconst useCarousel = () => {\n const context = useContext(CarouselContext);\n if (!context) {\n throw new Error('useCarousel must be used within a Carousel');\n }\n return context;\n};\n\n// ------------------------------------------------------------------\n// Helper Functions\n// ------------------------------------------------------------------\nconst getCardStyle = (index: number, displayedIndex: number) => {\n const diff = Math.abs(index - displayedIndex);\n switch (diff) {\n case 0:\n return 'opacity-100 z-40';\n case 1:\n return 'opacity-75 z-30 cursor-pointer';\n case 2:\n return 'opacity-50 z-20 pointer-events-none';\n default:\n return 'opacity-0 z-10 pointer-events-none';\n }\n};\n\nconst getCardScale = (index: number, displayedIndex: number) => {\n const diff = Math.abs(index - displayedIndex);\n switch (diff) {\n case 0:\n return 1;\n case 1:\n return 0.9;\n case 2:\n return 0.8;\n default:\n return 0.7;\n }\n};\n\n// This allows the calculation to work on SSR without hydration mismatch.\n// Your original logic: (3 * screenWidth) / 10 === 30% of viewport width\nconst getCardPositionX = (\n index: number,\n displayedIndex: number,\n containerWidth: number\n) => {\n const diff = index - displayedIndex;\n const gapPercentage = containerWidth < 600 ? 0.15 : 0.3; // Dropped to 15% for a tighter cluster\n const step = Math.min(containerWidth * gapPercentage, 300);\n\n // The 'px' here is mandatory\n return `${diff * step}px`;\n};\n\n// ------------------------------------------------------------------\n// Sub-Component: Item\n// ------------------------------------------------------------------\ntype CarouselItemProps = HTMLAttributes<HTMLDivElement> & {\n children: ReactNode;\n};\n\nconst CarouselItem: FC<CarouselItemProps> & { isCarouselItem: true } =\n Object.assign(\n ({ children, className, ...props }: CarouselItemProps) => (\n <div className={cn('size-full', className)} {...props}>\n {children}\n </div>\n ),\n { isCarouselItem: true as const }\n );\n\n// ------------------------------------------------------------------\n// Sub-Component: Indicators (Controller)\n// ------------------------------------------------------------------\ntype CarouselIndicatorsProps = HTMLAttributes<HTMLDivElement> & {\n disableKeyboardShortcuts?: boolean;\n};\n\nconst CarouselIndicators: FC<CarouselIndicatorsProps> = ({\n className,\n disableKeyboardShortcuts = false,\n ...props\n}) => {\n const {\n selectedIndex,\n setSelectedIndex,\n totalItems,\n handlePrev,\n handleNext,\n } = useCarousel();\n const { goToSlide, previousSlide, nextSlide } = useIntlayer('carousel');\n\n if (totalItems <= 1) return null;\n\n return (\n <div\n className={cn(\n 'absolute bottom-0 left-1/2 z-50 flex -translate-x-1/2 flex-row items-center gap-2 pb-4',\n className\n )}\n {...props}\n >\n <Popover identifier=\"carousel-prev\">\n <Button\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.NEUTRAL}\n label={previousSlide.value}\n roundedSize=\"full\"\n onClick={(e) => {\n e.stopPropagation();\n handlePrev();\n }}\n Icon={ChevronLeft}\n size={ButtonSize.ICON_MD}\n disabled={selectedIndex === 0}\n />\n\n <Popover.Detail identifier=\"carousel-prev\">\n <div className=\"flex items-center gap-2 p-2\">\n <span className=\"whitespace-nowrap text-neutral text-xs\">\n {previousSlide.value}\n </span>\n <KeyboardShortcut\n shortcut=\"ArrowLeft\"\n disabled={disableKeyboardShortcuts}\n size=\"sm\"\n onTriggered={handlePrev}\n />\n </div>\n </Popover.Detail>\n </Popover>\n\n {Array.from({ length: totalItems }).map((_, index) => {\n const isActive = index === selectedIndex;\n return (\n <button\n key={index}\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n setSelectedIndex(index);\n }}\n aria-label={goToSlide({ index: index + 1 }).value}\n className={cn(\n 'h-2.5 w-2.5 rounded-full transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-neutral-400 focus:ring-offset-2',\n isActive ? 'scale-110 bg-text' : 'bg-text/20 hover:bg-text/40'\n )}\n />\n );\n })}\n\n <Popover identifier=\"carousel-next\">\n <Button\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.NEUTRAL}\n roundedSize=\"full\"\n label={nextSlide.value}\n onClick={(e) => {\n e.stopPropagation();\n handleNext();\n }}\n Icon={ChevronRight}\n size={ButtonSize.ICON_MD}\n disabled={selectedIndex === totalItems - 1}\n />\n\n <Popover.Detail identifier=\"carousel-next\">\n <div className=\"flex items-center gap-2 p-2\">\n <span className=\"whitespace-nowrap text-neutral text-xs\">\n {nextSlide.value}\n </span>\n <KeyboardShortcut\n shortcut=\"ArrowRight\"\n size=\"sm\"\n onTriggered={handleNext}\n disabled={disableKeyboardShortcuts}\n />\n </div>\n </Popover.Detail>\n </Popover>\n </div>\n );\n};\n\n// ------------------------------------------------------------------\n// Main Component: Carousel Root\n// ------------------------------------------------------------------\ntype CarouselProps = HTMLAttributes<HTMLDivElement> & {\n children: ReactNode;\n initialIndex?: number;\n onIndexChange?: (index: number) => void;\n};\n\nconst partitionCarouselChildren = (\n children: ReactNode[]\n): [ReactElement[], ReactNode[]] => {\n const slides: ReactElement[] = [];\n const others: ReactNode[] = [];\n\n children.forEach((child) => {\n if (\n isValidElement(child) &&\n (child.type === CarouselItem ||\n (child.type as { isCarouselItem?: boolean }).isCarouselItem === true)\n ) {\n slides.push(child);\n } else {\n others.push(child);\n }\n });\n\n return [slides, others];\n};\n\nconst CarouselRoot: FC<CarouselProps> = ({\n children,\n className,\n initialIndex = 0,\n onIndexChange,\n ...props\n}) => {\n const allChildren = Children.toArray(children);\n const [slides, others] = partitionCarouselChildren(allChildren);\n const totalItems = slides.length;\n\n // State Management\n const [selectedIndex, setSelectedIndex] = useState<number>(initialIndex);\n const [displayedIndex, setDisplayedIndex] = useState<number>(initialIndex);\n const [containerHeight, setContainerHeight] = useState<number>(0);\n const [containerWidth, setContainerWidth] = useState<number>(0);\n\n useLayoutEffect(() => {\n const calculateDimensions = () => {\n if (!containerRef.current) return;\n\n // Track Width\n const width = containerRef.current.clientWidth;\n setContainerWidth(width);\n\n // Track Height (existing logic)\n const heights = itemsRef.current.map((item) => item?.offsetHeight || 0);\n const maxHeight = Math.max(0, ...heights);\n if (maxHeight > 0) {\n setContainerHeight(maxHeight + 40);\n }\n };\n\n calculateDimensions();\n\n const observer = new ResizeObserver(() => {\n calculateDimensions();\n });\n\n if (containerRef.current) observer.observe(containerRef.current);\n itemsRef.current.forEach((item) => {\n if (item) observer.observe(item);\n });\n\n return () => observer.disconnect();\n }, [totalItems]);\n\n // Drag State\n const [startX, setStartX] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n\n // Refs\n const containerRef = useRef<HTMLDivElement>(null);\n const itemsRef = useRef<(HTMLDivElement | null)[]>([]);\n\n // Navigation Logic\n const handleSwitchItem = (diff: number) => {\n if (containerWidth === 0) return;\n\n // Use container width for the threshold\n const swipeStep = containerWidth / SWIPE_THRESHOLD_DIVISOR;\n const numSwipe = Math.round(diff / swipeStep);\n\n if (Math.abs(numSwipe) >= 1) {\n const newIndex = displayedIndex - numSwipe;\n const clampedIndex = Math.max(0, Math.min(newIndex, totalItems - 1));\n\n if (clampedIndex !== selectedIndex) {\n setSelectedIndex(clampedIndex);\n setStartX((prev) => prev + diff);\n }\n }\n };\n\n const handleNext = () => {\n setSelectedIndex((prev) => Math.min(prev + 1, totalItems - 1));\n };\n\n const handlePrev = () => {\n setSelectedIndex((prev) => Math.max(prev - 1, 0));\n };\n\n // Input Handlers\n const handleMouseDown: MouseEventHandler<HTMLDivElement> = (e) => {\n setIsDragging(true);\n setStartX(e.clientX);\n };\n const handleMouseMove: MouseEventHandler<HTMLDivElement> = (e) => {\n if (isDragging) handleSwitchItem(e.clientX - startX);\n };\n const handleDragEnd = () => setIsDragging(false);\n const handleTouchStart: TouchEventHandler<HTMLDivElement> = (e) => {\n setIsDragging(true);\n setStartX(e.touches[0]!.clientX);\n };\n const handleTouchMove: TouchEventHandler<HTMLDivElement> = (e) => {\n if (isDragging) handleSwitchItem(e.touches[0]!.clientX - startX);\n };\n\n // Effects\n useEffect(() => {\n if (selectedIndex) onIndexChange?.(selectedIndex);\n }, [selectedIndex, onIndexChange]);\n\n useEffect(() => {\n let interval: NodeJS.Timeout;\n\n if (selectedIndex !== displayedIndex) {\n interval = setInterval(() => {\n setDisplayedIndex((prev) => {\n if (prev === selectedIndex) {\n clearInterval(interval);\n return prev;\n }\n return prev < selectedIndex ? prev + 1 : prev - 1;\n });\n }, TRANSITION_DELAY_MS);\n }\n return () => clearInterval(interval);\n }, [selectedIndex, displayedIndex]);\n\n // Calculate height based on the MAX height of ALL items\n useLayoutEffect(() => {\n const calculateMaxHeight = () => {\n const heights = itemsRef.current.map((item) => item?.offsetHeight || 0);\n const maxHeight = Math.max(0, ...heights);\n\n if (maxHeight > 0) {\n setContainerHeight(maxHeight + 40);\n }\n };\n\n calculateMaxHeight();\n\n const observer = new ResizeObserver(() => {\n calculateMaxHeight();\n });\n\n itemsRef.current.forEach((item) => {\n if (item) observer.observe(item);\n });\n\n return () => observer.disconnect();\n }, [totalItems]); // Removed isMounted dependency\n\n return (\n <CarouselContext.Provider\n value={{\n selectedIndex,\n setSelectedIndex,\n totalItems,\n handlePrev,\n handleNext,\n }}\n >\n <div\n ref={containerRef}\n className={cn(\n 'relative flex w-full cursor-grab select-none items-center overflow-hidden outline-none transition-[height] duration-300 ease-in-out focus:outline-none focus:outline-none focus:ring-0 active:cursor-grabbing',\n 'max-w-[1400px]',\n className\n )}\n style={{\n height: containerHeight > 0 ? containerHeight : 'auto',\n minHeight: '400px',\n }}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleDragEnd}\n onMouseLeave={handleDragEnd}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleDragEnd}\n role=\"region\"\n aria-label=\"Carousel\"\n {...props}\n >\n {slides.map((child, index) => {\n return (\n <div\n key={index}\n role=\"button\"\n tabIndex={0}\n ref={(el) => {\n itemsRef.current[index] = el;\n }}\n // FIX 2: Removed isMounted checks and invisible classes.\n // CSS units allow correct SSR rendering.\n className={cn(\n 'absolute left-1/2 -translate-x-1/2 transition-all duration-300 ease-in-out',\n 'outline-none ring-0 focus:outline-none focus:ring-0 focus:ring-offset-0 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0',\n getCardStyle(index, displayedIndex)\n )}\n onClick={(e) => {\n e.stopPropagation();\n setSelectedIndex(index);\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') setSelectedIndex(index);\n }}\n style={{\n transform: `\n translateX(${getCardPositionX(\n index,\n displayedIndex,\n containerWidth\n )})\n scale(${getCardScale(index, displayedIndex)})\n `,\n }}\n >\n {child}\n </div>\n );\n })}\n\n {others}\n </div>\n </CarouselContext.Provider>\n );\n};\n\nexport const Carousel = Object.assign(CarouselRoot, {\n Item: CarouselItem,\n Indicators: CarouselIndicators,\n});\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
 
3
- import { useUser } from "../../api/useUser/index.mjs";
4
3
  import { Button, ButtonColor, ButtonSize, ButtonVariant } from "../Button/Button.mjs";
5
4
  import { AutoCompleteTextarea } from "../TextArea/AutocompleteTextArea.mjs";
5
+ import { useUser } from "../../api/useUser/index.mjs";
6
6
  import { useEffect, useState } from "react";
7
7
  import { Check, X } from "lucide-react";
8
8
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -1,6 +1,5 @@
1
1
  'use client';
2
2
 
3
- import { useAuditContentDeclarationField } from "../../../api/hooks/ai.mjs";
4
3
  import { Container } from "../../Container/index.mjs";
5
4
  import { Loader } from "../../Loader/index.mjs";
6
5
  import { Button, ButtonColor, ButtonSize, ButtonTextAlign, ButtonVariant } from "../../Button/Button.mjs";
@@ -8,6 +7,7 @@ import { Accordion } from "../../Accordion/Accordion.mjs";
8
7
  import { InputVariant } from "../../Input/Input.mjs";
9
8
  import { SwitchSelector, SwitchSelectorColor, SwitchSelectorSize } from "../../SwitchSelector/SwitchSelector.mjs";
10
9
  import { useLocaleSwitcherContent } from "../../LocaleSwitcherContentDropDown/LocaleSwitcherContentContext.mjs";
10
+ import { useAuditContentDeclarationField } from "../../../api/hooks/ai.mjs";
11
11
  import { ContentEditorInput as ContentEditorInput$1 } from "../../ContentEditor/ContentEditorInput.mjs";
12
12
  import { ContentEditorTextArea as ContentEditorTextArea$1 } from "../../ContentEditor/ContentEditorTextArea.mjs";
13
13
  import { renameKey } from "./object.mjs";
@@ -17,9 +17,9 @@ import { SafeHtmlRenderer } from "./SafeHtmlRenderer.mjs";
17
17
  import { Fragment, Suspense, lazy, memo, useState } from "react";
18
18
  import { Plus, Trash, WandSparkles } from "lucide-react";
19
19
  import { jsx, jsxs } from "react/jsx-runtime";
20
- import { useConfiguration, useEditedContent } from "@intlayer/editor-react";
21
20
  import { useIntlayer, useLocale } from "react-intlayer";
22
21
  import { getLocaleName } from "@intlayer/core/localization";
22
+ import { useConfiguration, useEditedContent } from "@intlayer/editor-react";
23
23
  import { getEmptyNode, getNodeType } from "@intlayer/core/dictionaryManipulator";
24
24
  import * as NodeTypes from "@intlayer/types/nodeType";
25
25
  import { camelCaseToSentence } from "@intlayer/config/client";
@@ -1,9 +1,9 @@
1
1
  'use client';
2
2
 
3
+ import { ButtonColor } from "../../Button/Button.mjs";
3
4
  import { useSession } from "../../../api/useAuth/useSession.mjs";
4
5
  import { useAddDictionary } from "../../../api/hooks/dictionary.mjs";
5
6
  import { useGetProjects } from "../../../api/hooks/project.mjs";
6
- import { ButtonColor } from "../../Button/Button.mjs";
7
7
  import { MultiSelect } from "../../Select/Multiselect.mjs";
8
8
  import { useForm } from "../../Form/FormBase.mjs";
9
9
  import { Form } from "../../Form/Form.mjs";
@@ -1,12 +1,12 @@
1
1
  'use client';
2
2
 
3
+ import { Loader } from "../../Loader/index.mjs";
4
+ import { ButtonColor, ButtonSize, ButtonVariant } from "../../Button/Button.mjs";
5
+ import { Checkbox } from "../../Input/Checkbox.mjs";
3
6
  import { useSession } from "../../../api/useAuth/useSession.mjs";
4
7
  import { useAuditContentDeclarationMetadata } from "../../../api/hooks/ai.mjs";
5
8
  import { useGetProjects } from "../../../api/hooks/project.mjs";
6
9
  import { useGetTags } from "../../../api/hooks/tag.mjs";
7
- import { Loader } from "../../Loader/index.mjs";
8
- import { ButtonColor, ButtonSize, ButtonVariant } from "../../Button/Button.mjs";
9
- import { Checkbox } from "../../Input/Checkbox.mjs";
10
10
  import { MultiSelect } from "../../Select/Multiselect.mjs";
11
11
  import { Select } from "../../Select/Select.mjs";
12
12
  import { useForm as useForm$1 } from "../../Form/FormBase.mjs";
@@ -15,8 +15,8 @@ import { useDictionaryDetailsSchema } from "./useDictionaryDetailsSchema.mjs";
15
15
  import { useEffect } from "react";
16
16
  import { WandSparkles } from "lucide-react";
17
17
  import { jsx, jsxs } from "react/jsx-runtime";
18
- import { useEditedContent } from "@intlayer/editor-react";
19
18
  import { useIntlayer } from "react-intlayer";
19
+ import { useEditedContent } from "@intlayer/editor-react";
20
20
  import { useWatch } from "react-hook-form";
21
21
  import { AnimatePresence, motion } from "framer-motion";
22
22
 
@@ -13,8 +13,8 @@ import { StructureEditor } from "./StructureEditor.mjs";
13
13
  import { useEffect, useState } from "react";
14
14
  import { ArrowLeft } from "lucide-react";
15
15
  import { jsx, jsxs } from "react/jsx-runtime";
16
- import { useConfiguration, useDictionariesRecordActions, useFocusUnmergedDictionary } from "@intlayer/editor-react";
17
16
  import { useIntlayer } from "react-intlayer";
17
+ import { useConfiguration, useDictionariesRecordActions, useFocusUnmergedDictionary } from "@intlayer/editor-react";
18
18
 
19
19
  //#region src/components/DictionaryFieldEditor/DictionaryFieldEditor.tsx
20
20
  const DictionaryFieldEditor = ({ dictionary, onClickDictionaryList, isDarkMode, mode, onDelete, onSave, showReturnButton = true }) => {
@@ -5,8 +5,8 @@ import { getIsEditableSection } from "../getIsEditableSection.mjs";
5
5
  import { useState } from "react";
6
6
  import { ChevronRight, Plus } from "lucide-react";
7
7
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
8
- import { useEditedContentActions, useEditorLocale, useFocusUnmergedDictionary } from "@intlayer/editor-react";
9
8
  import { useIntlayer } from "react-intlayer";
9
+ import { useEditedContentActions, useEditorLocale, useFocusUnmergedDictionary } from "@intlayer/editor-react";
10
10
  import { getContentNodeByKeyPath, getEmptyNode, getNodeType } from "@intlayer/core/dictionaryManipulator";
11
11
  import * as NodeTypes from "@intlayer/types/nodeType";
12
12
  import { isSameKeyPath } from "@intlayer/core/utils";
@@ -1,17 +1,17 @@
1
1
  'use client';
2
2
 
3
3
  import { cn } from "../../../utils/cn.mjs";
4
+ import { ButtonColor, ButtonVariant } from "../../Button/Button.mjs";
4
5
  import { useAuth } from "../../../api/useAuth/useAuth.mjs";
5
6
  import { useDeleteDictionary, usePushDictionaries } from "../../../api/hooks/dictionary.mjs";
6
7
  import { useWriteDictionary } from "../../../api/hooks/editor.mjs";
7
- import { ButtonColor, ButtonVariant } from "../../Button/Button.mjs";
8
8
  import { Form } from "../../Form/Form.mjs";
9
9
  import { Modal, ModalSize } from "../../Modal/Modal.mjs";
10
10
  import { useState } from "react";
11
11
  import { ArrowUpFromLine, Download, RotateCcw, Save, Trash } from "lucide-react";
12
12
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
13
- import { useDictionariesRecordActions, useEditedContent } from "@intlayer/editor-react";
14
13
  import { useIntlayer } from "react-intlayer";
14
+ import { useDictionariesRecordActions, useEditedContent } from "@intlayer/editor-react";
15
15
 
16
16
  //#region src/components/DictionaryFieldEditor/SaveForm/SaveForm.tsx
17
17
  const SaveForm = ({ dictionary, mode, className, onDelete, onSave, ...props }) => {
@@ -7,8 +7,8 @@ import { EditableFieldInput } from "../../EditableField/EditableFieldInput.mjs";
7
7
  import { NodeTypeSelector } from "../NodeTypeSelector.mjs";
8
8
  import { Plus, Trash } from "lucide-react";
9
9
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
- import { useConfiguration, useEditedContentActions, useFocusUnmergedDictionary } from "@intlayer/editor-react";
11
10
  import { useIntlayer } from "react-intlayer";
11
+ import { useConfiguration, useEditedContentActions, useFocusUnmergedDictionary } from "@intlayer/editor-react";
12
12
  import { getDefaultNode, getNodeChildren, getNodeType } from "@intlayer/core/dictionaryManipulator";
13
13
  import * as NodeTypes from "@intlayer/types/nodeType";
14
14
  import { isSameKeyPath } from "@intlayer/core/utils";
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
- import { useItemSelector } from "../../../hooks/useItemSelector.mjs";
4
3
  import { InputIndicator, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot } from "../../Input/OTPInput.mjs";
4
+ import { useItemSelector } from "../../../hooks/useItemSelector.mjs";
5
5
  import { useFormField } from "../FormField.mjs";
6
6
  import { FormItemLayout } from "../layout/FormItemLayout.mjs";
7
7
  import { Form } from "../Form.mjs";
@@ -55,7 +55,7 @@ const MonacoCode = ({ children, language, isDarkMode, showLineNumbers, showCopyB
55
55
  };
56
56
  const isShowLineNumbers = showLineNumbers ?? (typeof children === "string" ? children.split("\n").length > 1 : false);
57
57
  return /* @__PURE__ */ jsxs("div", {
58
- className: cn("relative h-full w-full text-sm", showLineNumbers && "ml-0"),
58
+ className: cn("relative size-full text-sm", showLineNumbers && "ml-0"),
59
59
  children: [showCopyButton && /* @__PURE__ */ jsx("div", {
60
60
  className: "sticky top-5 z-10",
61
61
  children: /* @__PURE__ */ jsx("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"MonacoCode.mjs","names":[],"sources":["../../../../src/components/IDE/MonacoCode.tsx"],"sourcesContent":["'use client';\n\nimport type { OnChange, OnMount } from '@monaco-editor/react';\nimport { cn } from '@utils/cn';\nimport { type FC, lazy, Suspense, useRef, useState } from 'react';\nimport { CopyButton } from '../CopyButton';\nimport { Loader } from '../Loader';\n\nconst Editor = lazy(() =>\n import('@monaco-editor/react').then((mod) => ({ default: mod.Editor }))\n);\n\ntype CodeCompProps = {\n children: string;\n language: string;\n isDarkMode?: boolean;\n showLineNumbers?: boolean;\n showCopyButton?: boolean;\n isReadOnly?: boolean;\n onChange?: OnChange;\n};\n\nexport const MonacoCode: FC<CodeCompProps> = ({\n children,\n language,\n isDarkMode,\n showLineNumbers,\n showCopyButton = true,\n isReadOnly = false,\n onChange,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const ideRef = useRef(null);\n const [editorSize, setEditorSize] = useState<{\n height: number;\n width: number;\n }>({ height: 0, width: 0 });\n\n const theme = isDarkMode ? 'vs-dark-transparent' : 'hc-light-theme';\n\n const handleMountIde: OnMount = (editor, monaco) => {\n // first time you set the height based on content Height\n\n ideRef.current = editor as any;\n const contentHeight = (editor.getContentHeight() ?? 0) + 25;\n\n monaco.editor.defineTheme('vs-dark-transparent', {\n base: 'vs-dark',\n inherit: true,\n rules: [],\n colors: {\n 'editor.background': '#00000000',\n },\n });\n monaco.editor.defineTheme('hc-light-theme', {\n base: 'vs',\n inherit: true,\n rules: [],\n colors: {\n 'editor.background': '#00000000',\n },\n });\n\n monaco.editor.setTheme(theme);\n\n // Disable TypeScript diagnostics\n monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({\n noSemanticValidation: true, // Disables type checking\n noSyntaxValidation: true, // Disables syntax errors\n });\n\n // Disable JavaScript diagnostics\n monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({\n noSemanticValidation: true,\n noSyntaxValidation: true,\n });\n\n // Disable unnecessary language features (e.g., suggestions, quick fixes)\n monaco.languages.typescript.typescriptDefaults.setCompilerOptions({\n noLib: true,\n allowNonTsExtensions: true,\n });\n\n monaco.languages.typescript.javascriptDefaults.setCompilerOptions({\n noLib: true,\n allowNonTsExtensions: true,\n });\n\n setEditorSize({\n height: contentHeight,\n width: containerRef.current?.clientWidth ?? 0,\n });\n };\n\n const isShowLineNumbers =\n showLineNumbers ??\n (typeof children === 'string' ? children.split('\\n').length > 1 : false);\n\n return (\n <div\n className={cn(\n 'relative h-full w-full text-sm',\n showLineNumbers && 'ml-0'\n )}\n >\n {showCopyButton && (\n <div className=\"sticky top-5 z-10\">\n <div\n className={cn('absolute right-2 bottom-0 flex h-7 items-center')}\n >\n <CopyButton content={children} />\n </div>\n </div>\n )}\n <div\n className=\"z-0 grid size-full grid-cols-[0px] overflow-auto\"\n ref={containerRef}\n >\n <Suspense fallback={<Loader />}>\n <Editor\n {...editorSize}\n defaultLanguage=\"typescript\"\n language={language}\n loading={<Loader />}\n defaultValue={String(children).replace(/\\n$/, '')}\n onMount={handleMountIde}\n onChange={onChange}\n options={{\n contextmenu: false,\n readOnly: isReadOnly,\n cursorStyle: 'line',\n minimap: { enabled: false },\n scrollbar: {\n vertical: 'hidden',\n verticalScrollbarSize: 0,\n alwaysConsumeMouseWheel: false,\n },\n folding: false, // Disable code folding\n renderValidationDecorations: 'off', // Disable error/warning decorations\n quickSuggestions: false, // Disable IntelliSense\n parameterHints: { enabled: false }, // Disable parameter hints\n suggestOnTriggerCharacters: false, // Disable suggestions on typing\n\n mouseWheelScrollSensitivity: 0,\n fastScrollSensitivity: 0,\n scrollBeyondLastLine: false,\n lineNumbers: isShowLineNumbers ? 'on' : 'off',\n }}\n theme={theme}\n className=\"my-2 rounded-md\"\n />\n </Suspense>\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;AAQA,MAAM,SAAS,WACb,OAAO,wBAAwB,MAAM,SAAS,EAAE,SAAS,IAAI,OAAO,EAAE,CACxE;AAYA,MAAa,cAAiC,EAC5C,UACA,UACA,YACA,iBACA,iBAAiB,MACjB,aAAa,OACb,eACI;CACJ,MAAM,eAAe,OAAuB,IAAI;CAChD,MAAM,SAAS,OAAO,IAAI;CAC1B,MAAM,CAAC,YAAY,iBAAiB,SAGjC;EAAE,QAAQ;EAAG,OAAO;CAAE,CAAC;CAE1B,MAAM,QAAQ,aAAa,wBAAwB;CAEnD,MAAM,kBAA2B,QAAQ,WAAW;EAGlD,OAAO,UAAU;EACjB,MAAM,iBAAiB,OAAO,iBAAiB,KAAK,KAAK;EAEzD,OAAO,OAAO,YAAY,uBAAuB;GAC/C,MAAM;GACN,SAAS;GACT,OAAO,CAAC;GACR,QAAQ,EACN,qBAAqB,YACvB;EACF,CAAC;EACD,OAAO,OAAO,YAAY,kBAAkB;GAC1C,MAAM;GACN,SAAS;GACT,OAAO,CAAC;GACR,QAAQ,EACN,qBAAqB,YACvB;EACF,CAAC;EAED,OAAO,OAAO,SAAS,KAAK;EAG5B,OAAO,UAAU,WAAW,mBAAmB,sBAAsB;GACnE,sBAAsB;GACtB,oBAAoB;EACtB,CAAC;EAGD,OAAO,UAAU,WAAW,mBAAmB,sBAAsB;GACnE,sBAAsB;GACtB,oBAAoB;EACtB,CAAC;EAGD,OAAO,UAAU,WAAW,mBAAmB,mBAAmB;GAChE,OAAO;GACP,sBAAsB;EACxB,CAAC;EAED,OAAO,UAAU,WAAW,mBAAmB,mBAAmB;GAChE,OAAO;GACP,sBAAsB;EACxB,CAAC;EAED,cAAc;GACZ,QAAQ;GACR,OAAO,aAAa,SAAS,eAAe;EAC9C,CAAC;CACH;CAEA,MAAM,oBACJ,oBACC,OAAO,aAAa,WAAW,SAAS,MAAM,IAAI,EAAE,SAAS,IAAI;CAEpE,OACE,qBAAC,OAAD;EACE,WAAW,GACT,kCACA,mBAAmB,MACrB;YAJF,CAMG,kBACC,oBAAC,OAAD;GAAK,WAAU;aACb,oBAAC,OAAD;IACE,WAAW,GAAG,iDAAiD;cAE/D,oBAAC,YAAD,EAAY,SAAS,SAAW;GAC7B;EACF,IAEP,oBAAC,OAAD;GACE,WAAU;GACV,KAAK;aAEL,oBAAC,UAAD;IAAU,UAAU,oBAAC,QAAD,CAAS;cAC3B,oBAAC,QAAD;KACE,GAAI;KACJ,iBAAgB;KACN;KACV,SAAS,oBAAC,QAAD,CAAS;KAClB,cAAc,OAAO,QAAQ,EAAE,QAAQ,OAAO,EAAE;KAChD,SAAS;KACC;KACV,SAAS;MACP,aAAa;MACb,UAAU;MACV,aAAa;MACb,SAAS,EAAE,SAAS,MAAM;MAC1B,WAAW;OACT,UAAU;OACV,uBAAuB;OACvB,yBAAyB;MAC3B;MACA,SAAS;MACT,6BAA6B;MAC7B,kBAAkB;MAClB,gBAAgB,EAAE,SAAS,MAAM;MACjC,4BAA4B;MAE5B,6BAA6B;MAC7B,uBAAuB;MACvB,sBAAsB;MACtB,aAAa,oBAAoB,OAAO;KAC1C;KACO;KACP,WAAU;IACX;GACO;EACP,EACF;;AAET"}
1
+ {"version":3,"file":"MonacoCode.mjs","names":[],"sources":["../../../../src/components/IDE/MonacoCode.tsx"],"sourcesContent":["'use client';\n\nimport type { OnChange, OnMount } from '@monaco-editor/react';\nimport { cn } from '@utils/cn';\nimport { type FC, lazy, Suspense, useRef, useState } from 'react';\nimport { CopyButton } from '../CopyButton';\nimport { Loader } from '../Loader';\n\nconst Editor = lazy(() =>\n import('@monaco-editor/react').then((mod) => ({ default: mod.Editor }))\n);\n\ntype CodeCompProps = {\n children: string;\n language: string;\n isDarkMode?: boolean;\n showLineNumbers?: boolean;\n showCopyButton?: boolean;\n isReadOnly?: boolean;\n onChange?: OnChange;\n};\n\nexport const MonacoCode: FC<CodeCompProps> = ({\n children,\n language,\n isDarkMode,\n showLineNumbers,\n showCopyButton = true,\n isReadOnly = false,\n onChange,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const ideRef = useRef(null);\n const [editorSize, setEditorSize] = useState<{\n height: number;\n width: number;\n }>({ height: 0, width: 0 });\n\n const theme = isDarkMode ? 'vs-dark-transparent' : 'hc-light-theme';\n\n const handleMountIde: OnMount = (editor, monaco) => {\n // first time you set the height based on content Height\n\n ideRef.current = editor as any;\n const contentHeight = (editor.getContentHeight() ?? 0) + 25;\n\n monaco.editor.defineTheme('vs-dark-transparent', {\n base: 'vs-dark',\n inherit: true,\n rules: [],\n colors: {\n 'editor.background': '#00000000',\n },\n });\n monaco.editor.defineTheme('hc-light-theme', {\n base: 'vs',\n inherit: true,\n rules: [],\n colors: {\n 'editor.background': '#00000000',\n },\n });\n\n monaco.editor.setTheme(theme);\n\n // Disable TypeScript diagnostics\n monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({\n noSemanticValidation: true, // Disables type checking\n noSyntaxValidation: true, // Disables syntax errors\n });\n\n // Disable JavaScript diagnostics\n monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({\n noSemanticValidation: true,\n noSyntaxValidation: true,\n });\n\n // Disable unnecessary language features (e.g., suggestions, quick fixes)\n monaco.languages.typescript.typescriptDefaults.setCompilerOptions({\n noLib: true,\n allowNonTsExtensions: true,\n });\n\n monaco.languages.typescript.javascriptDefaults.setCompilerOptions({\n noLib: true,\n allowNonTsExtensions: true,\n });\n\n setEditorSize({\n height: contentHeight,\n width: containerRef.current?.clientWidth ?? 0,\n });\n };\n\n const isShowLineNumbers =\n showLineNumbers ??\n (typeof children === 'string' ? children.split('\\n').length > 1 : false);\n\n return (\n <div\n className={cn('relative size-full text-sm', showLineNumbers && 'ml-0')}\n >\n {showCopyButton && (\n <div className=\"sticky top-5 z-10\">\n <div\n className={cn('absolute right-2 bottom-0 flex h-7 items-center')}\n >\n <CopyButton content={children} />\n </div>\n </div>\n )}\n <div\n className=\"z-0 grid size-full grid-cols-[0px] overflow-auto\"\n ref={containerRef}\n >\n <Suspense fallback={<Loader />}>\n <Editor\n {...editorSize}\n defaultLanguage=\"typescript\"\n language={language}\n loading={<Loader />}\n defaultValue={String(children).replace(/\\n$/, '')}\n onMount={handleMountIde}\n onChange={onChange}\n options={{\n contextmenu: false,\n readOnly: isReadOnly,\n cursorStyle: 'line',\n minimap: { enabled: false },\n scrollbar: {\n vertical: 'hidden',\n verticalScrollbarSize: 0,\n alwaysConsumeMouseWheel: false,\n },\n folding: false, // Disable code folding\n renderValidationDecorations: 'off', // Disable error/warning decorations\n quickSuggestions: false, // Disable IntelliSense\n parameterHints: { enabled: false }, // Disable parameter hints\n suggestOnTriggerCharacters: false, // Disable suggestions on typing\n\n mouseWheelScrollSensitivity: 0,\n fastScrollSensitivity: 0,\n scrollBeyondLastLine: false,\n lineNumbers: isShowLineNumbers ? 'on' : 'off',\n }}\n theme={theme}\n className=\"my-2 rounded-md\"\n />\n </Suspense>\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;AAQA,MAAM,SAAS,WACb,OAAO,wBAAwB,MAAM,SAAS,EAAE,SAAS,IAAI,OAAO,EAAE,CACxE;AAYA,MAAa,cAAiC,EAC5C,UACA,UACA,YACA,iBACA,iBAAiB,MACjB,aAAa,OACb,eACI;CACJ,MAAM,eAAe,OAAuB,IAAI;CAChD,MAAM,SAAS,OAAO,IAAI;CAC1B,MAAM,CAAC,YAAY,iBAAiB,SAGjC;EAAE,QAAQ;EAAG,OAAO;CAAE,CAAC;CAE1B,MAAM,QAAQ,aAAa,wBAAwB;CAEnD,MAAM,kBAA2B,QAAQ,WAAW;EAGlD,OAAO,UAAU;EACjB,MAAM,iBAAiB,OAAO,iBAAiB,KAAK,KAAK;EAEzD,OAAO,OAAO,YAAY,uBAAuB;GAC/C,MAAM;GACN,SAAS;GACT,OAAO,CAAC;GACR,QAAQ,EACN,qBAAqB,YACvB;EACF,CAAC;EACD,OAAO,OAAO,YAAY,kBAAkB;GAC1C,MAAM;GACN,SAAS;GACT,OAAO,CAAC;GACR,QAAQ,EACN,qBAAqB,YACvB;EACF,CAAC;EAED,OAAO,OAAO,SAAS,KAAK;EAG5B,OAAO,UAAU,WAAW,mBAAmB,sBAAsB;GACnE,sBAAsB;GACtB,oBAAoB;EACtB,CAAC;EAGD,OAAO,UAAU,WAAW,mBAAmB,sBAAsB;GACnE,sBAAsB;GACtB,oBAAoB;EACtB,CAAC;EAGD,OAAO,UAAU,WAAW,mBAAmB,mBAAmB;GAChE,OAAO;GACP,sBAAsB;EACxB,CAAC;EAED,OAAO,UAAU,WAAW,mBAAmB,mBAAmB;GAChE,OAAO;GACP,sBAAsB;EACxB,CAAC;EAED,cAAc;GACZ,QAAQ;GACR,OAAO,aAAa,SAAS,eAAe;EAC9C,CAAC;CACH;CAEA,MAAM,oBACJ,oBACC,OAAO,aAAa,WAAW,SAAS,MAAM,IAAI,EAAE,SAAS,IAAI;CAEpE,OACE,qBAAC,OAAD;EACE,WAAW,GAAG,8BAA8B,mBAAmB,MAAM;YADvE,CAGG,kBACC,oBAAC,OAAD;GAAK,WAAU;aACb,oBAAC,OAAD;IACE,WAAW,GAAG,iDAAiD;cAE/D,oBAAC,YAAD,EAAY,SAAS,SAAW;GAC7B;EACF,IAEP,oBAAC,OAAD;GACE,WAAU;GACV,KAAK;aAEL,oBAAC,UAAD;IAAU,UAAU,oBAAC,QAAD,CAAS;cAC3B,oBAAC,QAAD;KACE,GAAI;KACJ,iBAAgB;KACN;KACV,SAAS,oBAAC,QAAD,CAAS;KAClB,cAAc,OAAO,QAAQ,EAAE,QAAQ,OAAO,EAAE;KAChD,SAAS;KACC;KACV,SAAS;MACP,aAAa;MACb,UAAU;MACV,aAAa;MACb,SAAS,EAAE,SAAS,MAAM;MAC1B,WAAW;OACT,UAAU;OACV,uBAAuB;OACvB,yBAAyB;MAC3B;MACA,SAAS;MACT,6BAA6B;MAC7B,kBAAkB;MAClB,gBAAgB,EAAE,SAAS,MAAM;MACjC,4BAA4B;MAE5B,6BAA6B;MAC7B,uBAAuB;MACvB,sBAAsB;MACtB,aAAa,oBAAoB,OAAO;KAC1C;KACO;KACP,WAAU;IACX;GACO;EACP,EACF;;AAET"}
@@ -186,9 +186,19 @@ const linkVariants = cva("gap-3 transition-all duration-300 focus-visible:outlin
186
186
  size: "md"
187
187
  }
188
188
  });
189
- const checkIsExternalLink = ({ href, isExternalLink: isExternalLinkProp }) => {
190
- const isValidHref = typeof href === "string" && href.trim() !== "";
191
- return isExternalLinkProp === true || typeof isExternalLinkProp === "undefined" && isValidHref && /^https?:\/\//.test(href);
189
+ const checkIsExternalLink = ({ href, isExternalLink: isExternalLinkProp }, url) => {
190
+ if (typeof isExternalLinkProp === "boolean") return isExternalLinkProp;
191
+ if (!(typeof href === "string" && href.trim() !== "")) return false;
192
+ if (!/^https?:\/\//.test(href)) return false;
193
+ if (url) try {
194
+ const hrefHost = new URL(href).hostname;
195
+ const currentHost = new URL(url.startsWith("http") ? url : `https://${url}`).hostname;
196
+ const getBaseDomain = (host) => host.split(".").slice(-2).join(".");
197
+ return getBaseDomain(hrefHost) !== getBaseDomain(currentHost);
198
+ } catch {
199
+ return true;
200
+ }
201
+ return true;
192
202
  };
193
203
  const isTextChildren = (children) => {
194
204
  if (typeof children === "string" || typeof children === "number") return true;
@@ -1 +1 @@
1
- {"version":3,"file":"Link.mjs","names":[],"sources":["../../../../src/components/Link/Link.tsx"],"sourcesContent":["import { getLocalizedUrl } from '@intlayer/core/localization';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { ExternalLink, MoveRight } from 'lucide-react';\nimport {\n type AnchorHTMLAttributes,\n type DetailedHTMLProps,\n type FC,\n isValidElement,\n type ReactNode,\n} from 'react';\n\n/**\n * Visual style variants for Link component\n */\nexport enum LinkVariant {\n DEFAULT = 'default',\n INVISIBLE_LINK = 'invisible-link',\n BUTTON = 'button',\n BUTTON_OUTLINED = 'button-outlined',\n HOVERABLE = 'hoverable',\n}\n\n/**\n * Color theme variants for Link component\n */\nexport enum LinkColor {\n PRIMARY = 'primary',\n SECONDARY = 'secondary',\n NEUTRAL = 'neutral',\n LIGHT = 'light',\n DARK = 'dark',\n TEXT = 'text',\n TEXT_INVERSE = 'text-inverse',\n ERROR = 'error',\n SUCCESS = 'success',\n CUSTOM = 'custom',\n}\n\nexport enum LinkRoundedSize {\n NONE = 'none',\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n TWO_XL = '2xl',\n THREE_XL = '3xl',\n FULL = 'full',\n}\n\nexport enum LinkSize {\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n CUSTOM = 'custom',\n}\n\nexport enum LinkUnderlined {\n DEFAULT = 'default',\n TRUE = 'true',\n FALSE = 'false',\n}\n\nexport const linkVariants = cva(\n 'gap-3 transition-all duration-300 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n variant: {\n [`${LinkVariant.DEFAULT}`]:\n 'h-auto justify-start border-inherit bg-current/0 px-1 font-medium decoration-[1.5] underline-offset-5 hover:bg-current/0 hover:text-current/80 hover:underline hover:underline-offset-6',\n [`${LinkVariant.INVISIBLE_LINK}`]:\n 'h-auto justify-start border-inherit bg-current/0 px-1 underline-offset-5 hover:bg-current/0 aria-[current]:bg-current/5',\n\n [`${LinkVariant.BUTTON}`]:\n 'relative flex cursor-pointer flex-row items-center justify-center gap-2 rounded-full bg-current text-center font-medium text-text ring-0 *:text-text-opposite hover:bg-current/90 hover:ring-5 aria-selected:ring-5 aria-[current]:ring-5',\n\n [`${LinkVariant.BUTTON_OUTLINED}`]:\n 'relative flex cursor-pointer flex-row items-center justify-center gap-2 rounded-full border-[1.3px] border-current text-center font-medium text-text ring-0 *:text-text hover:bg-current/20 hover:ring-5 aria-selected:ring-5 aria-[current]:ring-5',\n\n [`${LinkVariant.HOVERABLE}`]:\n 'rounded-lg border-none bg-current/0 transition *:text-current! hover:bg-current/20 aria-[current]:bg-current/5',\n },\n roundedSize: {\n [`${LinkRoundedSize.NONE}`]: 'rounded-none',\n [`${LinkRoundedSize.SM}`]:\n 'rounded-lg [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-xl',\n [`${LinkRoundedSize.MD}`]:\n 'rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl',\n [`${LinkRoundedSize.LG}`]:\n 'rounded-2xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-3xl',\n [`${LinkRoundedSize.XL}`]:\n 'rounded-3xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-4xl',\n [`${LinkRoundedSize.TWO_XL}`]:\n 'rounded-4xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[2.5rem]',\n [`${LinkRoundedSize.THREE_XL}`]:\n 'rounded-[2.5rem] [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[3rem]',\n [`${LinkRoundedSize.FULL}`]: 'rounded-full',\n },\n color: {\n [`${LinkColor.PRIMARY}`]: 'text-primary',\n [`${LinkColor.SECONDARY}`]: 'text-secondary',\n [`${LinkColor.NEUTRAL}`]: 'text-neutral',\n [`${LinkColor.LIGHT}`]: 'text-white',\n [`${LinkColor.DARK}`]: 'text-neutral-800',\n [`${LinkColor.TEXT}`]: 'text-text',\n [`${LinkColor.TEXT_INVERSE}`]: 'text-text-opposite',\n [`${LinkColor.ERROR}`]: 'text-error',\n [`${LinkColor.SUCCESS}`]: 'text-success',\n [`${LinkColor.CUSTOM}`]: '',\n },\n size: {\n [`${LinkSize.SM}`]: 'text-sm',\n [`${LinkSize.MD}`]: 'text-base',\n [`${LinkSize.LG}`]: 'text-lg',\n [`${LinkSize.XL}`]: 'text-xl',\n [`${LinkSize.CUSTOM}`]: '',\n },\n underlined: {\n [LinkUnderlined.DEFAULT]: '',\n [LinkUnderlined.TRUE]: 'underline',\n [LinkUnderlined.FALSE]: 'no-underline',\n },\n },\n // Compound variants handle height and padding\n compoundVariants: [\n // ---------------------------------------------------------\n // FIX START: Correctly Handle Contrast for TEXT_INVERSE\n // ---------------------------------------------------------\n {\n // Filled Button + Inverse Color (e.g., White Button):\n // We DO NOT override parent text color (it must remain 'text-opposite' so bg-current is white).\n // We ONLY override children to be 'text-text' (Dark) so they show up on white.\n variant: LinkVariant.BUTTON,\n color: LinkColor.TEXT_INVERSE,\n class: '*:text-text',\n },\n {\n // Outlined Button + Inverse Color (e.g., White Border):\n // Parent is 'text-opposite' (Border is white).\n // Children must also be 'text-opposite' (White text) to show on dark background.\n variant: LinkVariant.BUTTON_OUTLINED,\n color: LinkColor.TEXT_INVERSE,\n class: 'text-text-opposite *:text-text-opposite',\n },\n\n // Min height and padding for button variants\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n size: LinkSize.SM,\n class: 'min-h-7 px-3 max-md:py-1',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n size: LinkSize.MD,\n class: 'min-h-8 px-6 max-md:py-2',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n size: LinkSize.LG,\n class: 'min-h-10 px-8 max-md:py-3',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n size: LinkSize.XL,\n class: 'min-h-11 px-10 max-md:py-4',\n },\n // Ring color variants\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.PRIMARY,\n class: 'ring-primary/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.SECONDARY,\n class: 'ring-secondary/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.NEUTRAL,\n class: 'ring-neutral/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.LIGHT,\n class: 'ring-white/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.DARK,\n class: 'ring-neutral-800/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.TEXT,\n class: 'ring-text/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.TEXT_INVERSE,\n class: 'ring-text-opposite/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.ERROR,\n class: 'ring-error/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.SUCCESS,\n class: 'ring-success/20',\n },\n ],\n\n defaultVariants: {\n variant: LinkVariant.DEFAULT,\n roundedSize: LinkRoundedSize.MD,\n underlined: LinkUnderlined.DEFAULT,\n size: LinkSize.MD,\n },\n }\n);\n\nexport type LinkProps = DetailedHTMLProps<\n AnchorHTMLAttributes<HTMLAnchorElement>,\n HTMLAnchorElement\n> &\n VariantProps<typeof linkVariants> & {\n label: string;\n isExternalLink?: boolean;\n isPageSection?: boolean;\n isActive?: boolean;\n locale?: LocalesValues;\n };\n\nexport const checkIsExternalLink = ({\n href,\n isExternalLink: isExternalLinkProp,\n}: Pick<LinkProps, 'href' | 'isExternalLink'>): boolean => {\n const isValidHref = typeof href === 'string' && href.trim() !== '';\n const isExternalLink =\n isExternalLinkProp === true ||\n (typeof isExternalLinkProp === 'undefined' &&\n isValidHref &&\n /^https?:\\/\\//.test(href));\n\n return isExternalLink;\n};\n\nexport const isTextChildren = (children: ReactNode): boolean => {\n if (typeof children === 'string' || typeof children === 'number') {\n return true;\n }\n if (Array.isArray(children)) {\n return children.every(isTextChildren);\n }\n if (isValidElement(children)) {\n return isTextChildren(\n (children.props as { children?: ReactNode }).children\n );\n }\n return false;\n};\n\nexport const Link: FC<LinkProps> = (props) => {\n const {\n variant = LinkVariant.DEFAULT,\n color = LinkColor.CUSTOM,\n roundedSize,\n children,\n label,\n className,\n isActive,\n underlined,\n locale,\n size,\n isExternalLink: isExternalLinkProp,\n isPageSection: isPageSectionProp,\n href: hrefProp,\n ...otherProps\n } = props;\n\n const isExternalLink = isExternalLinkProp ?? checkIsExternalLink(props);\n const isPageSection = isPageSectionProp ?? hrefProp?.startsWith('#') ?? false;\n\n const isChildrenString = isTextChildren(children);\n const isButton =\n variant === LinkVariant.BUTTON || variant === LinkVariant.BUTTON_OUTLINED;\n\n const rel = isExternalLink ? 'noopener noreferrer nofollow' : undefined;\n\n const target = isExternalLink ? '_blank' : '_self';\n\n const resolvedHref =\n locale && hrefProp && !isExternalLink && !isPageSection\n ? getLocalizedUrl(hrefProp, locale)\n : hrefProp;\n\n const href = resolvedHref === '' ? undefined : resolvedHref;\n\n return (\n <a\n href={href}\n aria-label={label}\n rel={rel}\n target={target}\n aria-current={isActive ? 'page' : undefined}\n suppressHydrationWarning\n className={cn(\n linkVariants({\n variant,\n color,\n roundedSize,\n underlined,\n size,\n className,\n })\n )}\n {...otherProps}\n >\n {isButton && isChildrenString ? <span>{children}</span> : children}\n\n {isExternalLink && isChildrenString && (\n <ExternalLink className=\"ml-2 inline-block size-4\" />\n )}\n {isPageSection && <MoveRight className=\"ml-2 inline-block size-4\" />}\n </a>\n );\n};\n"],"mappings":";;;;;;;;;;;AAgBA,IAAY,cAAL;CACL;CACA;CACA;CACA;CACA;;AACF;;;;AAKA,IAAY,YAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;AACF;AAEA,IAAY,kBAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;AACF;AAEA,IAAY,WAAL;CACL;CACA;CACA;CACA;CACA;;AACF;AAEA,IAAY,iBAAL;CACL;CACA;CACA;;AACF;AAEA,MAAa,eAAe,IAC1B,iHACA;CACE,UAAU;EACR,SAAS;IACN,YACC;IACD,mBACC;IAED,WACC;IAED,oBACC;IAED,cACC;EACJ;EACA,aAAa;IACV,SAA4B;IAC5B,OACC;IACD,OACC;IACD,OACC;IACD,OACC;IACD,QACC;IACD,QACC;IACD,SAA4B;EAC/B;EACA,OAAO;IACJ,YAAyB;IACzB,cAA2B;IAC3B,YAAyB;IACzB,UAAuB;IACvB,SAAsB;IACtB,SAAsB;IACtB,iBAA8B;IAC9B,UAAuB;IACvB,YAAyB;IACzB,WAAwB;EAC3B;EACA,MAAM;IACH,OAAmB;IACnB,OAAmB;IACnB,OAAmB;IACnB,OAAmB;IACnB,WAAuB;EAC1B;EACA,YAAY;gBACgB;aACH;cACC;EAC1B;CACF;CAEA,kBAAkB;EAIhB;GAIE;GACA;GACA,OAAO;EACT;EACA;GAIE;GACA;GACA,OAAO;EACT;EAGA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EAEA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;CACF;CAEA,iBAAiB;EACf;EACA;EACA;EACA;CACF;AACF,CACF;AAcA,MAAa,uBAAuB,EAClC,MACA,gBAAgB,yBACyC;CACzD,MAAM,cAAc,OAAO,SAAS,YAAY,KAAK,KAAK,MAAM;CAOhE,OALE,uBAAuB,QACtB,OAAO,uBAAuB,eAC7B,eACA,eAAe,KAAK,IAAI;AAG9B;AAEA,MAAa,kBAAkB,aAAiC;CAC9D,IAAI,OAAO,aAAa,YAAY,OAAO,aAAa,UACtD,OAAO;CAET,IAAI,MAAM,QAAQ,QAAQ,GACxB,OAAO,SAAS,MAAM,cAAc;CAEtC,IAAI,eAAe,QAAQ,GACzB,OAAO,eACJ,SAAS,MAAmC,QAC/C;CAEF,OAAO;AACT;AAEA,MAAa,QAAuB,UAAU;CAC5C,MAAM,EACJ,qBACA,kBACA,aACA,UACA,OACA,WACA,UACA,YACA,QACA,MACA,gBAAgB,oBAChB,eAAe,mBACf,MAAM,UACN,GAAG,eACD;CAEJ,MAAM,iBAAiB,sBAAsB,oBAAoB,KAAK;CACtE,MAAM,gBAAgB,qBAAqB,UAAU,WAAW,GAAG,KAAK;CAExE,MAAM,mBAAmB,eAAe,QAAQ;CAChD,MAAM,WACJ,wBAAkC;CAEpC,MAAM,MAAM,iBAAiB,iCAAiC;CAE9D,MAAM,SAAS,iBAAiB,WAAW;CAE3C,MAAM,eACJ,UAAU,YAAY,CAAC,kBAAkB,CAAC,gBACtC,gBAAgB,UAAU,MAAM,IAChC;CAIN,OACE,qBAAC,KAAD;EACE,MAJS,iBAAiB,KAAK,SAAY;EAK3C,cAAY;EACP;EACG;EACR,gBAAc,WAAW,SAAS;EAClC;EACA,WAAW,GACT,aAAa;GACX;GACA;GACA;GACA;GACA;GACA;EACF,CAAC,CACH;EACA,GAAI;YAjBN;GAmBG,YAAY,mBAAmB,oBAAC,QAAD,EAAO,SAAe,KAAI;GAEzD,kBAAkB,oBACjB,oBAAC,cAAD,EAAc,WAAU,2BAA4B;GAErD,iBAAiB,oBAAC,WAAD,EAAW,WAAU,2BAA4B;EAClE;;AAEP"}
1
+ {"version":3,"file":"Link.mjs","names":[],"sources":["../../../../src/components/Link/Link.tsx"],"sourcesContent":["import { getLocalizedUrl } from '@intlayer/core/localization';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { ExternalLink, MoveRight } from 'lucide-react';\nimport {\n type AnchorHTMLAttributes,\n type DetailedHTMLProps,\n type FC,\n isValidElement,\n type ReactNode,\n} from 'react';\n\n/**\n * Visual style variants for Link component\n */\nexport enum LinkVariant {\n DEFAULT = 'default',\n INVISIBLE_LINK = 'invisible-link',\n BUTTON = 'button',\n BUTTON_OUTLINED = 'button-outlined',\n HOVERABLE = 'hoverable',\n}\n\n/**\n * Color theme variants for Link component\n */\nexport enum LinkColor {\n PRIMARY = 'primary',\n SECONDARY = 'secondary',\n NEUTRAL = 'neutral',\n LIGHT = 'light',\n DARK = 'dark',\n TEXT = 'text',\n TEXT_INVERSE = 'text-inverse',\n ERROR = 'error',\n SUCCESS = 'success',\n CUSTOM = 'custom',\n}\n\nexport enum LinkRoundedSize {\n NONE = 'none',\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n TWO_XL = '2xl',\n THREE_XL = '3xl',\n FULL = 'full',\n}\n\nexport enum LinkSize {\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n CUSTOM = 'custom',\n}\n\nexport enum LinkUnderlined {\n DEFAULT = 'default',\n TRUE = 'true',\n FALSE = 'false',\n}\n\nexport const linkVariants = cva(\n 'gap-3 transition-all duration-300 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n variant: {\n [`${LinkVariant.DEFAULT}`]:\n 'h-auto justify-start border-inherit bg-current/0 px-1 font-medium decoration-[1.5] underline-offset-5 hover:bg-current/0 hover:text-current/80 hover:underline hover:underline-offset-6',\n [`${LinkVariant.INVISIBLE_LINK}`]:\n 'h-auto justify-start border-inherit bg-current/0 px-1 underline-offset-5 hover:bg-current/0 aria-[current]:bg-current/5',\n\n [`${LinkVariant.BUTTON}`]:\n 'relative flex cursor-pointer flex-row items-center justify-center gap-2 rounded-full bg-current text-center font-medium text-text ring-0 *:text-text-opposite hover:bg-current/90 hover:ring-5 aria-selected:ring-5 aria-[current]:ring-5',\n\n [`${LinkVariant.BUTTON_OUTLINED}`]:\n 'relative flex cursor-pointer flex-row items-center justify-center gap-2 rounded-full border-[1.3px] border-current text-center font-medium text-text ring-0 *:text-text hover:bg-current/20 hover:ring-5 aria-selected:ring-5 aria-[current]:ring-5',\n\n [`${LinkVariant.HOVERABLE}`]:\n 'rounded-lg border-none bg-current/0 transition *:text-current! hover:bg-current/20 aria-[current]:bg-current/5',\n },\n roundedSize: {\n [`${LinkRoundedSize.NONE}`]: 'rounded-none',\n [`${LinkRoundedSize.SM}`]:\n 'rounded-lg [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-xl',\n [`${LinkRoundedSize.MD}`]:\n 'rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl',\n [`${LinkRoundedSize.LG}`]:\n 'rounded-2xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-3xl',\n [`${LinkRoundedSize.XL}`]:\n 'rounded-3xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-4xl',\n [`${LinkRoundedSize.TWO_XL}`]:\n 'rounded-4xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[2.5rem]',\n [`${LinkRoundedSize.THREE_XL}`]:\n 'rounded-[2.5rem] [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[3rem]',\n [`${LinkRoundedSize.FULL}`]: 'rounded-full',\n },\n color: {\n [`${LinkColor.PRIMARY}`]: 'text-primary',\n [`${LinkColor.SECONDARY}`]: 'text-secondary',\n [`${LinkColor.NEUTRAL}`]: 'text-neutral',\n [`${LinkColor.LIGHT}`]: 'text-white',\n [`${LinkColor.DARK}`]: 'text-neutral-800',\n [`${LinkColor.TEXT}`]: 'text-text',\n [`${LinkColor.TEXT_INVERSE}`]: 'text-text-opposite',\n [`${LinkColor.ERROR}`]: 'text-error',\n [`${LinkColor.SUCCESS}`]: 'text-success',\n [`${LinkColor.CUSTOM}`]: '',\n },\n size: {\n [`${LinkSize.SM}`]: 'text-sm',\n [`${LinkSize.MD}`]: 'text-base',\n [`${LinkSize.LG}`]: 'text-lg',\n [`${LinkSize.XL}`]: 'text-xl',\n [`${LinkSize.CUSTOM}`]: '',\n },\n underlined: {\n [LinkUnderlined.DEFAULT]: '',\n [LinkUnderlined.TRUE]: 'underline',\n [LinkUnderlined.FALSE]: 'no-underline',\n },\n },\n // Compound variants handle height and padding\n compoundVariants: [\n // ---------------------------------------------------------\n // FIX START: Correctly Handle Contrast for TEXT_INVERSE\n // ---------------------------------------------------------\n {\n // Filled Button + Inverse Color (e.g., White Button):\n // We DO NOT override parent text color (it must remain 'text-opposite' so bg-current is white).\n // We ONLY override children to be 'text-text' (Dark) so they show up on white.\n variant: LinkVariant.BUTTON,\n color: LinkColor.TEXT_INVERSE,\n class: '*:text-text',\n },\n {\n // Outlined Button + Inverse Color (e.g., White Border):\n // Parent is 'text-opposite' (Border is white).\n // Children must also be 'text-opposite' (White text) to show on dark background.\n variant: LinkVariant.BUTTON_OUTLINED,\n color: LinkColor.TEXT_INVERSE,\n class: 'text-text-opposite *:text-text-opposite',\n },\n\n // Min height and padding for button variants\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n size: LinkSize.SM,\n class: 'min-h-7 px-3 max-md:py-1',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n size: LinkSize.MD,\n class: 'min-h-8 px-6 max-md:py-2',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n size: LinkSize.LG,\n class: 'min-h-10 px-8 max-md:py-3',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n size: LinkSize.XL,\n class: 'min-h-11 px-10 max-md:py-4',\n },\n // Ring color variants\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.PRIMARY,\n class: 'ring-primary/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.SECONDARY,\n class: 'ring-secondary/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.NEUTRAL,\n class: 'ring-neutral/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.LIGHT,\n class: 'ring-white/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.DARK,\n class: 'ring-neutral-800/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.TEXT,\n class: 'ring-text/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.TEXT_INVERSE,\n class: 'ring-text-opposite/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.ERROR,\n class: 'ring-error/20',\n },\n {\n variant: [LinkVariant.BUTTON, LinkVariant.BUTTON_OUTLINED],\n color: LinkColor.SUCCESS,\n class: 'ring-success/20',\n },\n ],\n\n defaultVariants: {\n variant: LinkVariant.DEFAULT,\n roundedSize: LinkRoundedSize.MD,\n underlined: LinkUnderlined.DEFAULT,\n size: LinkSize.MD,\n },\n }\n);\n\nexport type LinkProps = DetailedHTMLProps<\n AnchorHTMLAttributes<HTMLAnchorElement>,\n HTMLAnchorElement\n> &\n VariantProps<typeof linkVariants> & {\n label: string;\n isExternalLink?: boolean;\n isPageSection?: boolean;\n isActive?: boolean;\n locale?: LocalesValues;\n };\n\nexport const checkIsExternalLink = (\n {\n href,\n isExternalLink: isExternalLinkProp,\n }: Pick<LinkProps, 'href' | 'isExternalLink'>,\n url?: string\n): boolean => {\n // Explicit prop override takes precedence\n if (typeof isExternalLinkProp === 'boolean') {\n return isExternalLinkProp;\n }\n\n const isValidHref = typeof href === 'string' && href.trim() !== '';\n\n if (!isValidHref) return false;\n\n // Relative URLs (e.g., '/about') are always internal\n if (!/^https?:\\/\\//.test(href)) {\n return false;\n }\n\n // Compare base domains\n if (url) {\n try {\n const hrefHost = new URL(href).hostname;\n // Ensure the reference url has a protocol so URL() can parse it correctly\n const currentHost = new URL(\n url.startsWith('http') ? url : `https://${url}`\n ).hostname;\n\n // Extract the root domain (e.g., 'app.intlayer.org' -> 'intlayer.org')\n const getBaseDomain = (host: string) =>\n host.split('.').slice(-2).join('.');\n\n return getBaseDomain(hrefHost) !== getBaseDomain(currentHost);\n } catch {\n // If URL parsing fails for any reason, default to treating it as external\n return true;\n }\n }\n\n // Absolute URL with no comparison URL provided\n return true;\n};\n\nexport const isTextChildren = (children: ReactNode): boolean => {\n if (typeof children === 'string' || typeof children === 'number') {\n return true;\n }\n if (Array.isArray(children)) {\n return children.every(isTextChildren);\n }\n if (isValidElement(children)) {\n return isTextChildren(\n (children.props as { children?: ReactNode }).children\n );\n }\n return false;\n};\n\nexport const Link: FC<LinkProps> = (props) => {\n const {\n variant = LinkVariant.DEFAULT,\n color = LinkColor.CUSTOM,\n roundedSize,\n children,\n label,\n className,\n isActive,\n underlined,\n locale,\n size,\n isExternalLink: isExternalLinkProp,\n isPageSection: isPageSectionProp,\n href: hrefProp,\n ...otherProps\n } = props;\n\n const isExternalLink = isExternalLinkProp ?? checkIsExternalLink(props);\n const isPageSection = isPageSectionProp ?? hrefProp?.startsWith('#') ?? false;\n\n const isChildrenString = isTextChildren(children);\n const isButton =\n variant === LinkVariant.BUTTON || variant === LinkVariant.BUTTON_OUTLINED;\n\n const rel = isExternalLink ? 'noopener noreferrer nofollow' : undefined;\n\n const target = isExternalLink ? '_blank' : '_self';\n\n const resolvedHref =\n locale && hrefProp && !isExternalLink && !isPageSection\n ? getLocalizedUrl(hrefProp, locale)\n : hrefProp;\n\n const href = resolvedHref === '' ? undefined : resolvedHref;\n\n return (\n <a\n href={href}\n aria-label={label}\n rel={rel}\n target={target}\n aria-current={isActive ? 'page' : undefined}\n suppressHydrationWarning\n className={cn(\n linkVariants({\n variant,\n color,\n roundedSize,\n underlined,\n size,\n className,\n })\n )}\n {...otherProps}\n >\n {isButton && isChildrenString ? <span>{children}</span> : children}\n\n {isExternalLink && isChildrenString && (\n <ExternalLink className=\"ml-2 inline-block size-4\" />\n )}\n {isPageSection && <MoveRight className=\"ml-2 inline-block size-4\" />}\n </a>\n );\n};\n"],"mappings":";;;;;;;;;;;AAgBA,IAAY,cAAL;CACL;CACA;CACA;CACA;CACA;;AACF;;;;AAKA,IAAY,YAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;AACF;AAEA,IAAY,kBAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;AACF;AAEA,IAAY,WAAL;CACL;CACA;CACA;CACA;CACA;;AACF;AAEA,IAAY,iBAAL;CACL;CACA;CACA;;AACF;AAEA,MAAa,eAAe,IAC1B,iHACA;CACE,UAAU;EACR,SAAS;IACN,YACC;IACD,mBACC;IAED,WACC;IAED,oBACC;IAED,cACC;EACJ;EACA,aAAa;IACV,SAA4B;IAC5B,OACC;IACD,OACC;IACD,OACC;IACD,OACC;IACD,QACC;IACD,QACC;IACD,SAA4B;EAC/B;EACA,OAAO;IACJ,YAAyB;IACzB,cAA2B;IAC3B,YAAyB;IACzB,UAAuB;IACvB,SAAsB;IACtB,SAAsB;IACtB,iBAA8B;IAC9B,UAAuB;IACvB,YAAyB;IACzB,WAAwB;EAC3B;EACA,MAAM;IACH,OAAmB;IACnB,OAAmB;IACnB,OAAmB;IACnB,OAAmB;IACnB,WAAuB;EAC1B;EACA,YAAY;gBACgB;aACH;cACC;EAC1B;CACF;CAEA,kBAAkB;EAIhB;GAIE;GACA;GACA,OAAO;EACT;EACA;GAIE;GACA;GACA,OAAO;EACT;EAGA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EAEA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;EACA;GACE,SAAS,4BAAgD;GACzD;GACA,OAAO;EACT;CACF;CAEA,iBAAiB;EACf;EACA;EACA;EACA;CACF;AACF,CACF;AAcA,MAAa,uBACX,EACE,MACA,gBAAgB,sBAElB,QACY;CAEZ,IAAI,OAAO,uBAAuB,WAChC,OAAO;CAKT,IAAI,EAFgB,OAAO,SAAS,YAAY,KAAK,KAAK,MAAM,KAE9C,OAAO;CAGzB,IAAI,CAAC,eAAe,KAAK,IAAI,GAC3B,OAAO;CAIT,IAAI,KACF,IAAI;EACF,MAAM,WAAW,IAAI,IAAI,IAAI,EAAE;EAE/B,MAAM,cAAc,IAAI,IACtB,IAAI,WAAW,MAAM,IAAI,MAAM,WAAW,KAC5C,EAAE;EAGF,MAAM,iBAAiB,SACrB,KAAK,MAAM,GAAG,EAAE,MAAM,EAAE,EAAE,KAAK,GAAG;EAEpC,OAAO,cAAc,QAAQ,MAAM,cAAc,WAAW;CAC9D,QAAQ;EAEN,OAAO;CACT;CAIF,OAAO;AACT;AAEA,MAAa,kBAAkB,aAAiC;CAC9D,IAAI,OAAO,aAAa,YAAY,OAAO,aAAa,UACtD,OAAO;CAET,IAAI,MAAM,QAAQ,QAAQ,GACxB,OAAO,SAAS,MAAM,cAAc;CAEtC,IAAI,eAAe,QAAQ,GACzB,OAAO,eACJ,SAAS,MAAmC,QAC/C;CAEF,OAAO;AACT;AAEA,MAAa,QAAuB,UAAU;CAC5C,MAAM,EACJ,qBACA,kBACA,aACA,UACA,OACA,WACA,UACA,YACA,QACA,MACA,gBAAgB,oBAChB,eAAe,mBACf,MAAM,UACN,GAAG,eACD;CAEJ,MAAM,iBAAiB,sBAAsB,oBAAoB,KAAK;CACtE,MAAM,gBAAgB,qBAAqB,UAAU,WAAW,GAAG,KAAK;CAExE,MAAM,mBAAmB,eAAe,QAAQ;CAChD,MAAM,WACJ,wBAAkC;CAEpC,MAAM,MAAM,iBAAiB,iCAAiC;CAE9D,MAAM,SAAS,iBAAiB,WAAW;CAE3C,MAAM,eACJ,UAAU,YAAY,CAAC,kBAAkB,CAAC,gBACtC,gBAAgB,UAAU,MAAM,IAChC;CAIN,OACE,qBAAC,KAAD;EACE,MAJS,iBAAiB,KAAK,SAAY;EAK3C,cAAY;EACP;EACG;EACR,gBAAc,WAAW,SAAS;EAClC;EACA,WAAW,GACT,aAAa;GACX;GACA;GACA;GACA;GACA;GACA;EACF,CAAC,CACH;EACA,GAAI;YAjBN;GAmBG,YAAY,mBAAmB,oBAAC,QAAD,EAAO,SAAe,KAAI;GAEzD,kBAAkB,oBACjB,oBAAC,cAAD,EAAc,WAAU,2BAA4B;GAErD,iBAAiB,oBAAC,WAAD,EAAW,WAAU,2BAA4B;EAClE;;AAEP"}
@@ -1,11 +1,11 @@
1
1
  'use client';
2
2
 
3
- import { usePersistedStore } from "../../hooks/usePersistedStore.mjs";
4
3
  import { Container } from "../Container/index.mjs";
5
4
  import { Button, ButtonColor, ButtonSize, ButtonTextAlign, ButtonVariant } from "../Button/Button.mjs";
6
5
  import { DropDown } from "../DropDown/index.mjs";
7
6
  import { Input } from "../Input/Input.mjs";
8
7
  import { SwitchSelector, SwitchSelectorColor, SwitchSelectorSize } from "../SwitchSelector/SwitchSelector.mjs";
8
+ import { usePersistedStore } from "../../hooks/usePersistedStore.mjs";
9
9
  import { useLocaleSwitcherContent } from "./LocaleSwitcherContentContext.mjs";
10
10
  import { useMemo, useRef, useState } from "react";
11
11
  import { Check, Globe, MoveVertical } from "lucide-react";
@@ -1,10 +1,10 @@
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";
6
4
  import { Container } from "../Container/index.mjs";
7
5
  import { Button, ButtonColor, ButtonSize, ButtonVariant } from "../Button/Button.mjs";
6
+ import { useGetElementOrWindow } from "../../hooks/useGetElementOrWindow.mjs";
7
+ import { useScrollBlockage } from "../../hooks/useScrollBlockage/index.mjs";
8
8
  import { H3 } from "../Headers/index.mjs";
9
9
  import { useEffect } from "react";
10
10
  import { cva } from "class-variance-authority";
@@ -189,7 +189,7 @@ const Modal = ({ children, isOpen, container, onClose, hasCloseButton = false, t
189
189
  }), /* @__PURE__ */ jsx("div", {
190
190
  className: cn("flex min-h-0 w-full flex-1 flex-col", isScrollable === true && "overflow-auto", isScrollable === "y" && "overflow-y-auto overflow-x-hidden", isScrollable === "x" && "overflow-x-auto overflow-y-hidden", !isScrollable && "overflow-visible"),
191
191
  children: /* @__PURE__ */ jsx("div", {
192
- className: cn("flex h-full w-full flex-1 flex-col", contentPaddingClass),
192
+ className: cn("flex size-full flex-1 flex-col", contentPaddingClass),
193
193
  children
194
194
  })
195
195
  })]