@intlayer/design-system 8.9.6-canary.0 → 8.9.7

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 (62) hide show
  1. package/dist/esm/components/Avatar/index.mjs +1 -1
  2. package/dist/esm/components/Avatar/index.mjs.map +1 -1
  3. package/dist/esm/components/Container/index.mjs +1 -1
  4. package/dist/esm/components/Container/index.mjs.map +1 -1
  5. package/dist/esm/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.mjs +1 -1
  6. package/dist/esm/components/DropDown/index.mjs +2 -2
  7. package/dist/esm/components/DropDown/index.mjs.map +1 -1
  8. package/dist/esm/components/Input/OTPInput.mjs +1 -1
  9. package/dist/esm/components/Input/OTPInput.mjs.map +1 -1
  10. package/dist/esm/components/MarkDownRender/MarkDownRender.mjs +2 -2
  11. package/dist/esm/components/MarkDownRender/MarkDownRender.mjs.map +1 -1
  12. package/dist/esm/components/MarkDownRender/index.mjs +2 -1
  13. package/dist/esm/components/Pagination/Pagination.mjs +8 -5
  14. package/dist/esm/components/Pagination/Pagination.mjs.map +1 -1
  15. package/dist/esm/components/TechLogo/logos/Atlassian.mjs +22 -0
  16. package/dist/esm/components/TechLogo/logos/Atlassian.mjs.map +1 -0
  17. package/dist/esm/components/TechLogo/logos/Microsoft.mjs +44 -0
  18. package/dist/esm/components/TechLogo/logos/Microsoft.mjs.map +1 -0
  19. package/dist/esm/components/TechLogo/techLogos.mjs +5 -1
  20. package/dist/esm/components/TechLogo/techLogos.mjs.map +1 -1
  21. package/dist/esm/components/Toaster/Toast.mjs +2 -2
  22. package/dist/esm/components/Toaster/Toast.mjs.map +1 -1
  23. package/dist/esm/components/Toaster/index.mjs +2 -2
  24. package/dist/esm/components/index.mjs +3 -2
  25. package/dist/esm/hooks/index.mjs +2 -2
  26. package/dist/esm/hooks/reactQuery.mjs +36 -7
  27. package/dist/esm/hooks/reactQuery.mjs.map +1 -1
  28. package/dist/esm/hooks/useAuth/useOAuth2.mjs +1 -1
  29. package/dist/esm/hooks/useAuth/useSession.mjs +1 -1
  30. package/dist/esm/libs/auth.mjs +1 -1
  31. package/dist/types/components/Avatar/index.d.ts +1 -1
  32. package/dist/types/components/Badge/index.d.ts +2 -2
  33. package/dist/types/components/Button/Button.d.ts +4 -4
  34. package/dist/types/components/CollapsibleTable/CollapsibleTable.d.ts +3 -3
  35. package/dist/types/components/Command/index.d.ts +2 -2
  36. package/dist/types/components/Container/index.d.ts +7 -7
  37. package/dist/types/components/DropDown/index.d.ts +6 -0
  38. package/dist/types/components/DropDown/index.d.ts.map +1 -1
  39. package/dist/types/components/Input/Checkbox.d.ts +3 -3
  40. package/dist/types/components/Input/Input.d.ts +2 -2
  41. package/dist/types/components/Input/OTPInput.d.ts +1 -1
  42. package/dist/types/components/Link/Link.d.ts +4 -4
  43. package/dist/types/components/MarkDownRender/MarkDownRender.d.ts +1 -1
  44. package/dist/types/components/MarkDownRender/index.d.ts +2 -1
  45. package/dist/types/components/Pagination/Pagination.d.ts +2 -2
  46. package/dist/types/components/SwitchSelector/SwitchSelector.d.ts +3 -3
  47. package/dist/types/components/SwitchSelector/VerticalSwitchSelector.d.ts +2 -2
  48. package/dist/types/components/TabSelector/TabSelector.d.ts +1 -1
  49. package/dist/types/components/Tag/index.d.ts +3 -3
  50. package/dist/types/components/TechLogo/logos/Atlassian.d.ts +7 -0
  51. package/dist/types/components/TechLogo/logos/Atlassian.d.ts.map +1 -0
  52. package/dist/types/components/TechLogo/logos/Microsoft.d.ts +7 -0
  53. package/dist/types/components/TechLogo/logos/Microsoft.d.ts.map +1 -0
  54. package/dist/types/components/TechLogo/techLogos.d.ts +4 -2
  55. package/dist/types/components/Toaster/Toast.d.ts +2 -2
  56. package/dist/types/components/Toaster/Toast.d.ts.map +1 -1
  57. package/dist/types/components/Toaster/index.d.ts +2 -2
  58. package/dist/types/components/index.d.ts +3 -2
  59. package/dist/types/hooks/index.d.ts +2 -2
  60. package/dist/types/hooks/reactQuery.d.ts +4 -1
  61. package/dist/types/hooks/reactQuery.d.ts.map +1 -1
  62. package/package.json +15 -15
@@ -85,7 +85,7 @@ const Avatar = ({ fullname, className, isLoading = false, isLoggedIn = true, src
85
85
  ]);
86
86
  return /* @__PURE__ */ jsx(Container, {
87
87
  isClickable,
88
- className: cn(`rounded-full border-[1.3px] border-text p-[1.5px]`, size === "sm" && "size-7 border-[1px] p-[1px]", size === "md" && "size-9", size === "lg" && "size-12", size === "xl" && "size-16", isClickable && `cursor-pointer hover:opacity-80 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2`, !isClickable && focusable && `focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2`, displayLoader && "animate-pulse", className),
88
+ className: cn(`rounded-full border-[1.3px] border-text p-[1.5px]`, size === "sm" && "size-7 border-[1px] p-[1px]", size === "md" && "size-9", size === "lg" && "size-12", size === "xl" && "size-16", size === "2xl" && "size-24", isClickable && `cursor-pointer hover:opacity-80 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2`, !isClickable && focusable && `focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2`, displayLoader && "animate-pulse", className),
89
89
  onClick,
90
90
  ...accessibilityProps,
91
91
  ...props,
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/components/Avatar/index.tsx"],"sourcesContent":["import { cn } from '@utils/cn';\nimport { User } from 'lucide-react';\nimport type { ComponentProps, FC, HTMLAttributes } from 'react';\nimport { useMemo } from 'react';\nimport { Loader } from '../Loader';\n\n/**\n * Props for the Avatar component\n */\nexport interface AvatarProps extends Omit<ComponentProps<'button'>, 'onClick'> {\n /** Image source URL for the avatar */\n src?: string;\n /** Full name used to generate initials and alt text */\n fullname?: string;\n /** Displays a loading spinner when true */\n isLoading?: boolean;\n /** Whether the user is authenticated */\n isLoggedIn?: boolean;\n /** Size variant of the avatar */\n size?: 'sm' | 'md' | 'lg' | 'xl';\n /** Click handler - when provided, makes the avatar clickable */\n onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;\n /** Alternative text for accessibility */\n alt?: string;\n /** Whether the avatar should be focusable when not clickable */\n focusable?: boolean;\n}\n\n/**\n * @description Gets the capital letters from a name.\n * @param name - The name to extract capitals from.\n * @param separator - The separator to split the name (default is an empty string, which splits by each character).\n * @returns {string[]} An array of capital letters from the name.\n */\nexport const getCapitals = (name: string, separator = ' '): string[] => {\n if (!name) return [];\n\n const parts =\n separator === ' '\n ? name.trim().split(/\\s+/) // handle multiple spaces\n : name.split(separator);\n\n return parts.filter(Boolean).map((word) => word.charAt(0).toUpperCase());\n};\n\n/**\n * Container component that renders either a button or div based on interactivity\n */\nconst Container: FC<\n HTMLAttributes<HTMLElement> & {\n isClickable: boolean;\n onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;\n }\n> = ({ isClickable, onClick, ...props }) => {\n if (isClickable && onClick) {\n return (\n <button\n {...(props as ComponentProps<'button'>)}\n onClick={onClick}\n type=\"button\"\n />\n );\n }\n\n return (\n <div\n {...(props as ComponentProps<'div'>)}\n role={\n props.tabIndex !== undefined || props['aria-label'] ? 'img' : undefined\n }\n />\n );\n};\n\n/**\n * Avatar component that displays user profile images, initials, or a default user icon.\n * Supports loading states, authentication states, and accessibility features.\n *\n * @example\n * ```tsx\n * // With image\n * <Avatar src=\"https://example.com/avatar.jpg\" fullname=\"John Doe\" />\n *\n * // With initials\n * <Avatar fullname=\"John Doe\" />\n *\n * // Clickable avatar\n * <Avatar\n * fullname=\"John Doe\"\n * onClick={(e) => console.log('Avatar clicked')}\n * />\n *\n * // Loading state\n * <Avatar isLoading fullname=\"John Doe\" />\n * ```\n */\nexport const Avatar: FC<AvatarProps> = ({\n fullname,\n className,\n isLoading = false,\n isLoggedIn = true,\n src,\n onClick,\n size = 'md',\n alt,\n focusable = false,\n ...props\n}) => {\n const isImageDefined = Boolean(src);\n const isNameDefined = Boolean((fullname ?? '').length > 0);\n const capitals = fullname ? getCapitals(fullname) : undefined;\n\n // Display logic\n const displayLoader = isLoading;\n const displayAvatar = isLoggedIn && !displayLoader && isImageDefined;\n const displayInitials =\n isLoggedIn && !displayLoader && !displayAvatar && isNameDefined;\n const displayUserIcon =\n isLoggedIn && !displayLoader && !displayAvatar && !displayInitials;\n\n const isClickable = onClick !== undefined;\n\n // Accessibility attributes\n const accessibilityProps = useMemo(() => {\n const baseProps: Record<string, any> = {};\n\n if (displayAvatar && alt) {\n baseProps['aria-label'] = alt;\n } else if (displayAvatar && fullname) {\n baseProps['aria-label'] = `Avatar of ${fullname}`;\n } else if (displayInitials && fullname) {\n baseProps['aria-label'] = `Avatar initials for ${fullname}`;\n } else if (displayUserIcon) {\n baseProps['aria-label'] = 'Default user avatar';\n } else if (displayLoader) {\n baseProps['aria-label'] = 'Loading avatar';\n baseProps['aria-busy'] = true;\n }\n\n if (!isClickable && focusable) {\n baseProps.tabIndex = 0;\n }\n\n if (isClickable) {\n baseProps['aria-describedby'] = 'avatar-description';\n }\n\n return baseProps;\n }, [\n displayAvatar,\n displayInitials,\n displayUserIcon,\n displayLoader,\n alt,\n fullname,\n isClickable,\n focusable,\n ]);\n\n return (\n <Container\n isClickable={isClickable}\n className={cn(\n `rounded-full border-[1.3px] border-text p-[1.5px]`,\n size === 'sm' && 'size-7 border-[1px] p-[1px]',\n size === 'md' && 'size-9',\n size === 'lg' && 'size-12',\n size === 'xl' && 'size-16',\n isClickable &&\n `cursor-pointer hover:opacity-80 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2`,\n !isClickable &&\n focusable &&\n `focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2`,\n displayLoader && 'animate-pulse',\n className\n )}\n onClick={onClick}\n {...accessibilityProps}\n {...props}\n >\n <div className=\"relative flex size-full flex-row items-center justify-center\">\n <div className=\"absolute top-0 left-0 flex size-full flex-col items-center justify-center rounded-full bg-text text-text-opposite\">\n {displayLoader && (\n <Loader className=\"w-3/4\" aria-label=\"Loading user avatar\" />\n )}\n\n {displayAvatar && (\n <img\n className=\"size-full rounded-full object-cover\"\n src={src}\n srcSet={src}\n alt={alt ?? `Avatar of ${fullname}`}\n width={59}\n height={59}\n loading=\"lazy\"\n draggable={false}\n />\n )}\n\n {displayInitials && (\n <div className=\"flex size-full items-center justify-center gap-[0.1rem] font-bold text-sm max-md:py-1\">\n {capitals?.map((capital, index) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: Capitals are primitives and order is fixed\n <span key={`${capital}-${index}`}>{capital}</span>\n ))}\n </div>\n )}\n\n {displayUserIcon && (\n <User\n size={cn(\n size === 'sm' && 14,\n size === 'md' && 25,\n size === 'lg' && 30,\n size === 'xl' && 40\n )}\n aria-label=\"Default user icon\"\n />\n )}\n </div>\n </div>\n </Container>\n );\n};\n"],"mappings":";;;;;;;;;;;;;AAkCA,MAAa,eAAe,MAAc,YAAY,QAAkB;CACtE,IAAI,CAAC,MAAM,OAAO,EAAE;CAOpB,QAJE,cAAc,MACV,KAAK,MAAM,CAAC,MAAM,MAAM,GACxB,KAAK,MAAM,UAAU,EAEd,OAAO,QAAQ,CAAC,KAAK,SAAS,KAAK,OAAO,EAAE,CAAC,aAAa,CAAC;;;;;AAM1E,MAAM,aAKD,EAAE,aAAa,SAAS,GAAG,YAAY;CAC1C,IAAI,eAAe,SACjB,OACE,oBAAC,UAAD;EACE,GAAK;EACI;EACT,MAAK;EACL;CAIN,OACE,oBAAC,OAAD;EACE,GAAK;EACL,MACE,MAAM,aAAa,UAAa,MAAM,gBAAgB,QAAQ;EAEhE;;;;;;;;;;;;;;;;;;;;;;;;AA0BN,MAAa,UAA2B,EACtC,UACA,WACA,YAAY,OACZ,aAAa,MACb,KACA,SACA,OAAO,MACP,KACA,YAAY,OACZ,GAAG,YACC;CACJ,MAAM,iBAAiB,QAAQ,IAAI;CACnC,MAAM,gBAAgB,SAAS,YAAY,IAAI,SAAS,EAAE;CAC1D,MAAM,WAAW,WAAW,YAAY,SAAS,GAAG;CAGpD,MAAM,gBAAgB;CACtB,MAAM,gBAAgB,cAAc,CAAC,iBAAiB;CACtD,MAAM,kBACJ,cAAc,CAAC,iBAAiB,CAAC,iBAAiB;CACpD,MAAM,kBACJ,cAAc,CAAC,iBAAiB,CAAC,iBAAiB,CAAC;CAErD,MAAM,cAAc,YAAY;CAGhC,MAAM,qBAAqB,cAAc;EACvC,MAAM,YAAiC,EAAE;EAEzC,IAAI,iBAAiB,KACnB,UAAU,gBAAgB;OACrB,IAAI,iBAAiB,UAC1B,UAAU,gBAAgB,aAAa;OAClC,IAAI,mBAAmB,UAC5B,UAAU,gBAAgB,uBAAuB;OAC5C,IAAI,iBACT,UAAU,gBAAgB;OACrB,IAAI,eAAe;GACxB,UAAU,gBAAgB;GAC1B,UAAU,eAAe;;EAG3B,IAAI,CAAC,eAAe,WAClB,UAAU,WAAW;EAGvB,IAAI,aACF,UAAU,sBAAsB;EAGlC,OAAO;IACN;EACD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;CAEF,OACE,oBAAC,WAAD;EACe;EACb,WAAW,GACT,qDACA,SAAS,QAAQ,+BACjB,SAAS,QAAQ,UACjB,SAAS,QAAQ,WACjB,SAAS,QAAQ,WACjB,eACE,2GACF,CAAC,eACC,aACA,2EACF,iBAAiB,iBACjB,UACD;EACQ;EACT,GAAI;EACJ,GAAI;YAEJ,oBAAC,OAAD;GAAK,WAAU;aACb,qBAAC,OAAD;IAAK,WAAU;cAAf;KACG,iBACC,oBAAC,QAAD;MAAQ,WAAU;MAAQ,cAAW;MAAwB;KAG9D,iBACC,oBAAC,OAAD;MACE,WAAU;MACL;MACL,QAAQ;MACR,KAAK,OAAO,aAAa;MACzB,OAAO;MACP,QAAQ;MACR,SAAQ;MACR,WAAW;MACX;KAGH,mBACC,oBAAC,OAAD;MAAK,WAAU;gBACZ,UAAU,KAAK,SAAS,UAEvB,oBAAC,QAAD,YAAmC,SAAe,EAAvC,GAAG,QAAQ,GAAG,QAAyB,CAClD;MACE;KAGP,mBACC,oBAAC,MAAD;MACE,MAAM,GACJ,SAAS,QAAQ,IACjB,SAAS,QAAQ,IACjB,SAAS,QAAQ,IACjB,SAAS,QAAQ,GAClB;MACD,cAAW;MACX;KAEA;;GACF;EACI"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/components/Avatar/index.tsx"],"sourcesContent":["import { cn } from '@utils/cn';\nimport { User } from 'lucide-react';\nimport type { ComponentProps, FC, HTMLAttributes } from 'react';\nimport { useMemo } from 'react';\nimport { Loader } from '../Loader';\n\n/**\n * Props for the Avatar component\n */\nexport interface AvatarProps extends Omit<ComponentProps<'button'>, 'onClick'> {\n /** Image source URL for the avatar */\n src?: string;\n /** Full name used to generate initials and alt text */\n fullname?: string;\n /** Displays a loading spinner when true */\n isLoading?: boolean;\n /** Whether the user is authenticated */\n isLoggedIn?: boolean;\n /** Size variant of the avatar */\n size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n /** Click handler - when provided, makes the avatar clickable */\n onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;\n /** Alternative text for accessibility */\n alt?: string;\n /** Whether the avatar should be focusable when not clickable */\n focusable?: boolean;\n}\n\n/**\n * @description Gets the capital letters from a name.\n * @param name - The name to extract capitals from.\n * @param separator - The separator to split the name (default is an empty string, which splits by each character).\n * @returns {string[]} An array of capital letters from the name.\n */\nexport const getCapitals = (name: string, separator = ' '): string[] => {\n if (!name) return [];\n\n const parts =\n separator === ' '\n ? name.trim().split(/\\s+/) // handle multiple spaces\n : name.split(separator);\n\n return parts.filter(Boolean).map((word) => word.charAt(0).toUpperCase());\n};\n\n/**\n * Container component that renders either a button or div based on interactivity\n */\nconst Container: FC<\n HTMLAttributes<HTMLElement> & {\n isClickable: boolean;\n onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;\n }\n> = ({ isClickable, onClick, ...props }) => {\n if (isClickable && onClick) {\n return (\n <button\n {...(props as ComponentProps<'button'>)}\n onClick={onClick}\n type=\"button\"\n />\n );\n }\n\n return (\n <div\n {...(props as ComponentProps<'div'>)}\n role={\n props.tabIndex !== undefined || props['aria-label'] ? 'img' : undefined\n }\n />\n );\n};\n\n/**\n * Avatar component that displays user profile images, initials, or a default user icon.\n * Supports loading states, authentication states, and accessibility features.\n *\n * @example\n * ```tsx\n * // With image\n * <Avatar src=\"https://example.com/avatar.jpg\" fullname=\"John Doe\" />\n *\n * // With initials\n * <Avatar fullname=\"John Doe\" />\n *\n * // Clickable avatar\n * <Avatar\n * fullname=\"John Doe\"\n * onClick={(e) => console.log('Avatar clicked')}\n * />\n *\n * // Loading state\n * <Avatar isLoading fullname=\"John Doe\" />\n * ```\n */\nexport const Avatar: FC<AvatarProps> = ({\n fullname,\n className,\n isLoading = false,\n isLoggedIn = true,\n src,\n onClick,\n size = 'md',\n alt,\n focusable = false,\n ...props\n}) => {\n const isImageDefined = Boolean(src);\n const isNameDefined = Boolean((fullname ?? '').length > 0);\n const capitals = fullname ? getCapitals(fullname) : undefined;\n\n // Display logic\n const displayLoader = isLoading;\n const displayAvatar = isLoggedIn && !displayLoader && isImageDefined;\n const displayInitials =\n isLoggedIn && !displayLoader && !displayAvatar && isNameDefined;\n const displayUserIcon =\n isLoggedIn && !displayLoader && !displayAvatar && !displayInitials;\n\n const isClickable = onClick !== undefined;\n\n // Accessibility attributes\n const accessibilityProps = useMemo(() => {\n const baseProps: Record<string, any> = {};\n\n if (displayAvatar && alt) {\n baseProps['aria-label'] = alt;\n } else if (displayAvatar && fullname) {\n baseProps['aria-label'] = `Avatar of ${fullname}`;\n } else if (displayInitials && fullname) {\n baseProps['aria-label'] = `Avatar initials for ${fullname}`;\n } else if (displayUserIcon) {\n baseProps['aria-label'] = 'Default user avatar';\n } else if (displayLoader) {\n baseProps['aria-label'] = 'Loading avatar';\n baseProps['aria-busy'] = true;\n }\n\n if (!isClickable && focusable) {\n baseProps.tabIndex = 0;\n }\n\n if (isClickable) {\n baseProps['aria-describedby'] = 'avatar-description';\n }\n\n return baseProps;\n }, [\n displayAvatar,\n displayInitials,\n displayUserIcon,\n displayLoader,\n alt,\n fullname,\n isClickable,\n focusable,\n ]);\n\n return (\n <Container\n isClickable={isClickable}\n className={cn(\n `rounded-full border-[1.3px] border-text p-[1.5px]`,\n size === 'sm' && 'size-7 border-[1px] p-[1px]',\n size === 'md' && 'size-9',\n size === 'lg' && 'size-12',\n size === 'xl' && 'size-16',\n size === '2xl' && 'size-24',\n isClickable &&\n `cursor-pointer hover:opacity-80 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2`,\n !isClickable &&\n focusable &&\n `focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2`,\n displayLoader && 'animate-pulse',\n className\n )}\n onClick={onClick}\n {...accessibilityProps}\n {...props}\n >\n <div className=\"relative flex size-full flex-row items-center justify-center\">\n <div className=\"absolute top-0 left-0 flex size-full flex-col items-center justify-center rounded-full bg-text text-text-opposite\">\n {displayLoader && (\n <Loader className=\"w-3/4\" aria-label=\"Loading user avatar\" />\n )}\n\n {displayAvatar && (\n <img\n className=\"size-full rounded-full object-cover\"\n src={src}\n srcSet={src}\n alt={alt ?? `Avatar of ${fullname}`}\n width={59}\n height={59}\n loading=\"lazy\"\n draggable={false}\n />\n )}\n\n {displayInitials && (\n <div className=\"flex size-full items-center justify-center gap-[0.1rem] font-bold text-sm max-md:py-1\">\n {capitals?.map((capital, index) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: Capitals are primitives and order is fixed\n <span key={`${capital}-${index}`}>{capital}</span>\n ))}\n </div>\n )}\n\n {displayUserIcon && (\n <User\n size={cn(\n size === 'sm' && 14,\n size === 'md' && 25,\n size === 'lg' && 30,\n size === 'xl' && 40\n )}\n aria-label=\"Default user icon\"\n />\n )}\n </div>\n </div>\n </Container>\n );\n};\n"],"mappings":";;;;;;;;;;;;;AAkCA,MAAa,eAAe,MAAc,YAAY,QAAkB;CACtE,IAAI,CAAC,MAAM,OAAO,EAAE;CAOpB,QAJE,cAAc,MACV,KAAK,MAAM,CAAC,MAAM,MAAM,GACxB,KAAK,MAAM,UAAU,EAEd,OAAO,QAAQ,CAAC,KAAK,SAAS,KAAK,OAAO,EAAE,CAAC,aAAa,CAAC;;;;;AAM1E,MAAM,aAKD,EAAE,aAAa,SAAS,GAAG,YAAY;CAC1C,IAAI,eAAe,SACjB,OACE,oBAAC,UAAD;EACE,GAAK;EACI;EACT,MAAK;EACL;CAIN,OACE,oBAAC,OAAD;EACE,GAAK;EACL,MACE,MAAM,aAAa,UAAa,MAAM,gBAAgB,QAAQ;EAEhE;;;;;;;;;;;;;;;;;;;;;;;;AA0BN,MAAa,UAA2B,EACtC,UACA,WACA,YAAY,OACZ,aAAa,MACb,KACA,SACA,OAAO,MACP,KACA,YAAY,OACZ,GAAG,YACC;CACJ,MAAM,iBAAiB,QAAQ,IAAI;CACnC,MAAM,gBAAgB,SAAS,YAAY,IAAI,SAAS,EAAE;CAC1D,MAAM,WAAW,WAAW,YAAY,SAAS,GAAG;CAGpD,MAAM,gBAAgB;CACtB,MAAM,gBAAgB,cAAc,CAAC,iBAAiB;CACtD,MAAM,kBACJ,cAAc,CAAC,iBAAiB,CAAC,iBAAiB;CACpD,MAAM,kBACJ,cAAc,CAAC,iBAAiB,CAAC,iBAAiB,CAAC;CAErD,MAAM,cAAc,YAAY;CAGhC,MAAM,qBAAqB,cAAc;EACvC,MAAM,YAAiC,EAAE;EAEzC,IAAI,iBAAiB,KACnB,UAAU,gBAAgB;OACrB,IAAI,iBAAiB,UAC1B,UAAU,gBAAgB,aAAa;OAClC,IAAI,mBAAmB,UAC5B,UAAU,gBAAgB,uBAAuB;OAC5C,IAAI,iBACT,UAAU,gBAAgB;OACrB,IAAI,eAAe;GACxB,UAAU,gBAAgB;GAC1B,UAAU,eAAe;;EAG3B,IAAI,CAAC,eAAe,WAClB,UAAU,WAAW;EAGvB,IAAI,aACF,UAAU,sBAAsB;EAGlC,OAAO;IACN;EACD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;CAEF,OACE,oBAAC,WAAD;EACe;EACb,WAAW,GACT,qDACA,SAAS,QAAQ,+BACjB,SAAS,QAAQ,UACjB,SAAS,QAAQ,WACjB,SAAS,QAAQ,WACjB,SAAS,SAAS,WAClB,eACE,2GACF,CAAC,eACC,aACA,2EACF,iBAAiB,iBACjB,UACD;EACQ;EACT,GAAI;EACJ,GAAI;YAEJ,oBAAC,OAAD;GAAK,WAAU;aACb,qBAAC,OAAD;IAAK,WAAU;cAAf;KACG,iBACC,oBAAC,QAAD;MAAQ,WAAU;MAAQ,cAAW;MAAwB;KAG9D,iBACC,oBAAC,OAAD;MACE,WAAU;MACL;MACL,QAAQ;MACR,KAAK,OAAO,aAAa;MACzB,OAAO;MACP,QAAQ;MACR,SAAQ;MACR,WAAW;MACX;KAGH,mBACC,oBAAC,OAAD;MAAK,WAAU;gBACZ,UAAU,KAAK,SAAS,UAEvB,oBAAC,QAAD,YAAmC,SAAe,EAAvC,GAAG,QAAQ,GAAG,QAAyB,CAClD;MACE;KAGP,mBACC,oBAAC,MAAD;MACE,MAAM,GACJ,SAAS,QAAQ,IACjB,SAAS,QAAQ,IACjB,SAAS,QAAQ,IACjB,SAAS,QAAQ,GAClB;MACD,cAAW;MACX;KAEA;;GACF;EACI"}
@@ -58,7 +58,7 @@ const containerVariants = cva("flex flex-col text-text backdrop-blur", {
58
58
  success: "border-success"
59
59
  },
60
60
  background: {
61
- none: "",
61
+ none: "backdrop-blur-none",
62
62
  hoverable: "bg-opacity-5! backdrop-blur-0 hover:bg-opacity-10! hover:backdrop-blur focus:bg-opacity-10! focus:backdrop-blur aria-selected:bg-opacity-15! aria-selected:backdrop-blur",
63
63
  with: ""
64
64
  },
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/components/Container/index.tsx"],"sourcesContent":["import { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport type {\n DetailedHTMLProps,\n FC,\n HTMLAttributes,\n PropsWithChildren,\n} from 'react';\n\n/**\n * Container component variants using class-variance-authority\n * Provides flexible styling options for background, padding, borders, and layout\n */\nexport const containerVariants = cva('flex flex-col text-text backdrop-blur', {\n variants: {\n roundedSize: {\n none: 'rounded-none',\n sm: 'rounded-sm [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-md',\n md: 'rounded-md [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-lg',\n lg: 'rounded-lg [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-xl',\n xl: 'rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl',\n '2xl':\n 'rounded-2xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-3xl',\n '3xl':\n 'rounded-3xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-4xl',\n '4xl':\n 'rounded-4xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[2.5rem]',\n full: 'rounded-full',\n },\n transparency: {\n none: 'bg-card',\n xs: 'bg-card/95',\n sm: 'bg-card/90',\n md: 'bg-card/70',\n lg: 'bg-card/40',\n xl: 'bg-card/20',\n full: '',\n },\n padding: {\n none: 'p-0',\n sm: 'px-3 py-2',\n md: 'px-4 py-3',\n lg: 'px-6 py-4',\n xl: 'px-8 py-6',\n '2xl': 'px-10 py-8',\n },\n separator: {\n without: '',\n x: 'divide-x divide-dashed divide-text/20',\n y: 'divide-y divide-dashed divide-text/20',\n both: 'divide-x divide-y divide-dashed divide-text/20',\n },\n border: {\n none: '',\n with: 'border-[1.3px]',\n },\n borderColor: {\n primary: 'border-primary',\n secondary: 'border-secondary',\n neutral: 'border-neutral',\n card: 'border-card',\n text: 'border-text',\n error: 'border-error',\n warning: 'border-warning',\n success: 'border-success',\n },\n background: {\n none: '',\n hoverable:\n 'bg-opacity-5! backdrop-blur-0 hover:bg-opacity-10! hover:backdrop-blur focus:bg-opacity-10! focus:backdrop-blur aria-selected:bg-opacity-15! aria-selected:backdrop-blur',\n with: '',\n },\n gap: {\n none: 'gap-0',\n sm: 'gap-1',\n md: 'gap-3',\n lg: 'gap-5',\n xl: 'gap-8',\n '2xl': 'gap-10',\n },\n },\n defaultVariants: {\n roundedSize: 'lg',\n border: 'none',\n borderColor: 'text',\n transparency: 'md',\n padding: 'none',\n separator: 'without',\n gap: 'none',\n },\n compoundVariants: [\n {\n background: 'none',\n class: 'bg-transparent',\n },\n ],\n});\n\n/** Available rounded corner sizes for the container */\nexport enum ContainerRoundedSize {\n NONE = 'none',\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n '2xl' = '2xl',\n '3xl' = '3xl',\n '4xl' = '4xl',\n '5xl' = '5xl',\n FULL = 'full',\n}\n\n/** Background transparency levels for the container */\nexport enum ContainerTransparency {\n NONE = 'none',\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n FULL = 'full',\n}\n\n/** Padding sizes for container content */\nexport enum ContainerPadding {\n NONE = 'none',\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n}\n\n/** Separator options for dividing container children */\nexport enum ContainerSeparator {\n WITHOUT = 'without',\n X = 'x',\n Y = 'y',\n BOTH = 'both',\n}\n\n/** Border color options for the container */\nexport enum ContainerBorderColor {\n PRIMARY = 'primary',\n SECONDARY = 'secondary',\n NEUTRAL = 'neutral',\n CARD = 'card',\n TEXT = 'text',\n ERROR = 'error',\n WARNING = 'warning',\n SUCCESS = 'success',\n}\n\n/** Background interaction states for the container */\nexport enum ContainerBackground {\n NONE = 'none',\n HOVERABLE = 'hoverable',\n WITH = 'with',\n}\n\n/** Gap sizes between container children */\nexport enum ContainerGap {\n NONE = 'none',\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n '2xl' = '2xl',\n}\n\n/** Container component props extending HTML div attributes */\nexport type ContainerProps = PropsWithChildren<\n Omit<VariantProps<typeof containerVariants>, 'border'>\n> &\n DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement> & {\n /** Whether to show a border around the container */\n border?: boolean;\n };\n\n/**\n * Container Component\n *\n * A flexible container component for organizing content with customizable styling options.\n * Supports various visual states, layouts, and accessibility features.\n *\n * ## Features\n * - **Flexible Layout**: Supports different padding, gap, and separator options\n * - **Visual Variants**: Multiple background transparency levels and border styles\n * - **Responsive Design**: Configurable rounded corners and spacing\n * - **Semantic HTML**: Proper div element with extensible attributes\n *\n * ## Accessibility\n * - Inherits all standard div accessibility features\n * - Supports ARIA attributes through spread props\n * - Maintains proper semantic structure for screen readers\n *\n * @param children - The content to display inside the container\n * @param roundedSize - Border radius size (default: 'md')\n * @param transparency - Background transparency level (default: 'md')\n * @param padding - Internal padding size (default: 'none')\n * @param separator - Divider lines between children (default: 'without')\n * @param border - Whether to show border (default: false)\n * @param borderColor - Color of the border (default: 'text')\n * @param background - Background interaction behavior (default: 'none')\n * @param gap - Space between child elements (default: 'none')\n * @param className - Additional CSS classes\n * @param props - Additional HTML div attributes including ARIA attributes\n */\nexport const Container: FC<ContainerProps> = ({\n children,\n roundedSize,\n padding,\n transparency,\n separator,\n className,\n border,\n borderColor,\n background,\n gap,\n ...props\n}) => (\n <div\n className={cn(\n containerVariants({\n roundedSize,\n transparency,\n padding,\n separator,\n border:\n typeof border === 'boolean' ? (border ? 'with' : 'none') : undefined,\n background,\n borderColor,\n gap,\n }),\n className\n )}\n {...props}\n >\n {children}\n </div>\n);\n"],"mappings":";;;;;;;;;AAaA,MAAa,oBAAoB,IAAI,yCAAyC;CAC5E,UAAU;EACR,aAAa;GACX,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,OACE;GACF,OACE;GACF,OACE;GACF,MAAM;GACP;EACD,cAAc;GACZ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,MAAM;GACP;EACD,SAAS;GACP,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,OAAO;GACR;EACD,WAAW;GACT,SAAS;GACT,GAAG;GACH,GAAG;GACH,MAAM;GACP;EACD,QAAQ;GACN,MAAM;GACN,MAAM;GACP;EACD,aAAa;GACX,SAAS;GACT,WAAW;GACX,SAAS;GACT,MAAM;GACN,MAAM;GACN,OAAO;GACP,SAAS;GACT,SAAS;GACV;EACD,YAAY;GACV,MAAM;GACN,WACE;GACF,MAAM;GACP;EACD,KAAK;GACH,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,OAAO;GACR;EACF;CACD,iBAAiB;EACf,aAAa;EACb,QAAQ;EACR,aAAa;EACb,cAAc;EACd,SAAS;EACT,WAAW;EACX,KAAK;EACN;CACD,kBAAkB,CAChB;EACE,YAAY;EACZ,OAAO;EACR,CACF;CACF,CAAC;;AAGF,IAAY,uBAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;KACD;;AAGD,IAAY,wBAAL;CACL;CACA;CACA;CACA;CACA;CACA;;KACD;;AAGD,IAAY,mBAAL;CACL;CACA;CACA;CACA;CACA;;KACD;;AAGD,IAAY,qBAAL;CACL;CACA;CACA;CACA;;KACD;;AAGD,IAAY,uBAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;KACD;;AAGD,IAAY,sBAAL;CACL;CACA;CACA;;KACD;;AAGD,IAAY,eAAL;CACL;CACA;CACA;CACA;CACA;CACA;;KACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCD,MAAa,aAAiC,EAC5C,UACA,aACA,SACA,cACA,WACA,WACA,QACA,aACA,YACA,KACA,GAAG,YAEH,oBAAC,OAAD;CACE,WAAW,GACT,kBAAkB;EAChB;EACA;EACA;EACA;EACA,QACE,OAAO,WAAW,YAAa,SAAS,SAAS,SAAU;EAC7D;EACA;EACA;EACD,CAAC,EACF,UACD;CACD,GAAI;CAEH;CACG"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/components/Container/index.tsx"],"sourcesContent":["import { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport type {\n DetailedHTMLProps,\n FC,\n HTMLAttributes,\n PropsWithChildren,\n} from 'react';\n\n/**\n * Container component variants using class-variance-authority\n * Provides flexible styling options for background, padding, borders, and layout\n */\nexport const containerVariants = cva('flex flex-col text-text backdrop-blur', {\n variants: {\n roundedSize: {\n none: 'rounded-none',\n sm: 'rounded-sm [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-md',\n md: 'rounded-md [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-lg',\n lg: 'rounded-lg [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-xl',\n xl: 'rounded-xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl',\n '2xl':\n 'rounded-2xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-3xl',\n '3xl':\n 'rounded-3xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-4xl',\n '4xl':\n 'rounded-4xl [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-[2.5rem]',\n full: 'rounded-full',\n },\n transparency: {\n none: 'bg-card',\n xs: 'bg-card/95',\n sm: 'bg-card/90',\n md: 'bg-card/70',\n lg: 'bg-card/40',\n xl: 'bg-card/20',\n full: '',\n },\n padding: {\n none: 'p-0',\n sm: 'px-3 py-2',\n md: 'px-4 py-3',\n lg: 'px-6 py-4',\n xl: 'px-8 py-6',\n '2xl': 'px-10 py-8',\n },\n separator: {\n without: '',\n x: 'divide-x divide-dashed divide-text/20',\n y: 'divide-y divide-dashed divide-text/20',\n both: 'divide-x divide-y divide-dashed divide-text/20',\n },\n border: {\n none: '',\n with: 'border-[1.3px]',\n },\n borderColor: {\n primary: 'border-primary',\n secondary: 'border-secondary',\n neutral: 'border-neutral',\n card: 'border-card',\n text: 'border-text',\n error: 'border-error',\n warning: 'border-warning',\n success: 'border-success',\n },\n background: {\n none: 'backdrop-blur-none',\n hoverable:\n 'bg-opacity-5! backdrop-blur-0 hover:bg-opacity-10! hover:backdrop-blur focus:bg-opacity-10! focus:backdrop-blur aria-selected:bg-opacity-15! aria-selected:backdrop-blur',\n with: '',\n },\n gap: {\n none: 'gap-0',\n sm: 'gap-1',\n md: 'gap-3',\n lg: 'gap-5',\n xl: 'gap-8',\n '2xl': 'gap-10',\n },\n },\n defaultVariants: {\n roundedSize: 'lg',\n border: 'none',\n borderColor: 'text',\n transparency: 'md',\n padding: 'none',\n separator: 'without',\n gap: 'none',\n },\n compoundVariants: [\n {\n background: 'none',\n class: 'bg-transparent',\n },\n ],\n});\n\n/** Available rounded corner sizes for the container */\nexport enum ContainerRoundedSize {\n NONE = 'none',\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n '2xl' = '2xl',\n '3xl' = '3xl',\n '4xl' = '4xl',\n '5xl' = '5xl',\n FULL = 'full',\n}\n\n/** Background transparency levels for the container */\nexport enum ContainerTransparency {\n NONE = 'none',\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n FULL = 'full',\n}\n\n/** Padding sizes for container content */\nexport enum ContainerPadding {\n NONE = 'none',\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n}\n\n/** Separator options for dividing container children */\nexport enum ContainerSeparator {\n WITHOUT = 'without',\n X = 'x',\n Y = 'y',\n BOTH = 'both',\n}\n\n/** Border color options for the container */\nexport enum ContainerBorderColor {\n PRIMARY = 'primary',\n SECONDARY = 'secondary',\n NEUTRAL = 'neutral',\n CARD = 'card',\n TEXT = 'text',\n ERROR = 'error',\n WARNING = 'warning',\n SUCCESS = 'success',\n}\n\n/** Background interaction states for the container */\nexport enum ContainerBackground {\n NONE = 'none',\n HOVERABLE = 'hoverable',\n WITH = 'with',\n}\n\n/** Gap sizes between container children */\nexport enum ContainerGap {\n NONE = 'none',\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n '2xl' = '2xl',\n}\n\n/** Container component props extending HTML div attributes */\nexport type ContainerProps = PropsWithChildren<\n Omit<VariantProps<typeof containerVariants>, 'border'>\n> &\n DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement> & {\n /** Whether to show a border around the container */\n border?: boolean;\n };\n\n/**\n * Container Component\n *\n * A flexible container component for organizing content with customizable styling options.\n * Supports various visual states, layouts, and accessibility features.\n *\n * ## Features\n * - **Flexible Layout**: Supports different padding, gap, and separator options\n * - **Visual Variants**: Multiple background transparency levels and border styles\n * - **Responsive Design**: Configurable rounded corners and spacing\n * - **Semantic HTML**: Proper div element with extensible attributes\n *\n * ## Accessibility\n * - Inherits all standard div accessibility features\n * - Supports ARIA attributes through spread props\n * - Maintains proper semantic structure for screen readers\n *\n * @param children - The content to display inside the container\n * @param roundedSize - Border radius size (default: 'md')\n * @param transparency - Background transparency level (default: 'md')\n * @param padding - Internal padding size (default: 'none')\n * @param separator - Divider lines between children (default: 'without')\n * @param border - Whether to show border (default: false)\n * @param borderColor - Color of the border (default: 'text')\n * @param background - Background interaction behavior (default: 'none')\n * @param gap - Space between child elements (default: 'none')\n * @param className - Additional CSS classes\n * @param props - Additional HTML div attributes including ARIA attributes\n */\nexport const Container: FC<ContainerProps> = ({\n children,\n roundedSize,\n padding,\n transparency,\n separator,\n className,\n border,\n borderColor,\n background,\n gap,\n ...props\n}) => (\n <div\n className={cn(\n containerVariants({\n roundedSize,\n transparency,\n padding,\n separator,\n border:\n typeof border === 'boolean' ? (border ? 'with' : 'none') : undefined,\n background,\n borderColor,\n gap,\n }),\n className\n )}\n {...props}\n >\n {children}\n </div>\n);\n"],"mappings":";;;;;;;;;AAaA,MAAa,oBAAoB,IAAI,yCAAyC;CAC5E,UAAU;EACR,aAAa;GACX,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,OACE;GACF,OACE;GACF,OACE;GACF,MAAM;GACP;EACD,cAAc;GACZ,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,MAAM;GACP;EACD,SAAS;GACP,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,OAAO;GACR;EACD,WAAW;GACT,SAAS;GACT,GAAG;GACH,GAAG;GACH,MAAM;GACP;EACD,QAAQ;GACN,MAAM;GACN,MAAM;GACP;EACD,aAAa;GACX,SAAS;GACT,WAAW;GACX,SAAS;GACT,MAAM;GACN,MAAM;GACN,OAAO;GACP,SAAS;GACT,SAAS;GACV;EACD,YAAY;GACV,MAAM;GACN,WACE;GACF,MAAM;GACP;EACD,KAAK;GACH,MAAM;GACN,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,OAAO;GACR;EACF;CACD,iBAAiB;EACf,aAAa;EACb,QAAQ;EACR,aAAa;EACb,cAAc;EACd,SAAS;EACT,WAAW;EACX,KAAK;EACN;CACD,kBAAkB,CAChB;EACE,YAAY;EACZ,OAAO;EACR,CACF;CACF,CAAC;;AAGF,IAAY,uBAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;KACD;;AAGD,IAAY,wBAAL;CACL;CACA;CACA;CACA;CACA;CACA;;KACD;;AAGD,IAAY,mBAAL;CACL;CACA;CACA;CACA;CACA;;KACD;;AAGD,IAAY,qBAAL;CACL;CACA;CACA;CACA;;KACD;;AAGD,IAAY,uBAAL;CACL;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;KACD;;AAGD,IAAY,sBAAL;CACL;CACA;CACA;;KACD;;AAGD,IAAY,eAAL;CACL;CACA;CACA;CACA;CACA;CACA;;KACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCD,MAAa,aAAiC,EAC5C,UACA,aACA,SACA,cACA,WACA,WACA,QACA,aACA,YACA,KACA,GAAG,YAEH,oBAAC,OAAD;CACE,WAAW,GACT,kBAAkB;EAChB;EACA;EACA;EACA;EACA,QACE,OAAO,WAAW,YAAa,SAAS,SAAS,SAAU;EAC7D;EACA;EACA;EACD,CAAC,EACF,UACD;CACD,GAAI;CAEH;CACG"}
@@ -4,13 +4,13 @@ import { getIsEditableSection } from "../getIsEditableSection.mjs";
4
4
  import { useState } from "react";
5
5
  import { ChevronRight, Plus } from "lucide-react";
6
6
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
+ import { internationalization } from "@intlayer/config/built";
7
8
  import { useIntlayer } from "react-intlayer";
8
9
  import { useEditedContentActions, useEditorLocale, useFocusUnmergedDictionary } from "@intlayer/editor-react";
9
10
  import { getContentNodeByKeyPath, getEmptyNode, getNodeType } from "@intlayer/core/dictionaryManipulator";
10
11
  import * as NodeTypes from "@intlayer/types/nodeType";
11
12
  import { isSameKeyPath } from "@intlayer/core/utils";
12
13
  import { camelCaseToSentence } from "@intlayer/config/client";
13
- import { internationalization } from "@intlayer/config/built";
14
14
 
15
15
  //#region src/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.tsx
16
16
  const traceKeys = [
@@ -157,7 +157,7 @@ let DropDownYAlign = /* @__PURE__ */ function(DropDownYAlign) {
157
157
  * - Keyboard navigation support when isFocusable is enabled
158
158
  * - Screen reader announcements for state changes
159
159
  */
160
- const Panel = ({ children, isHidden = void 0, isOverable = false, isFocusable = false, align = "start", yAlign = "below", identifier, className, ...props }) => /* @__PURE__ */ jsx("div", {
160
+ const Panel = ({ children, isHidden = void 0, isOverable = false, isFocusable = false, align = "start", yAlign = "below", identifier, className, smootherClassName, ...props }) => /* @__PURE__ */ jsx("div", {
161
161
  className: cn("absolute z-100 min-w-full", align === "start" && "left-0", align === "end" && "right-0", yAlign === "below" && "top-[calc(100%+0.5rem)]", yAlign === "above" && "bottom-[calc(100%+0.5rem)]", className),
162
162
  "aria-hidden": isHidden,
163
163
  role: "region",
@@ -165,7 +165,7 @@ const Panel = ({ children, isHidden = void 0, isOverable = false, isFocusable =
165
165
  id: `dropdown-panel-${identifier}`,
166
166
  children: /* @__PURE__ */ jsx(MaxHeightSmoother, {
167
167
  isHidden,
168
- className: cn("overflow-x-visible", isHidden === false && "invisible", isHidden === true && "visible", isOverable && "group-hover/dropdown:visible group-hover/dropdown:grid-rows-[1fr]", isFocusable && "group-focus-within/dropdown:visible group-focus-within/dropdown:grid-rows-[1fr]"),
168
+ className: cn("overflow-x-visible", isHidden === false && "invisible", isHidden === true && "visible", isOverable && "group-hover/dropdown:visible group-hover/dropdown:grid-rows-[1fr]", isFocusable && "group-focus-within/dropdown:visible group-focus-within/dropdown:grid-rows-[1fr]", smootherClassName),
169
169
  ...props,
170
170
  children
171
171
  })
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/components/DropDown/index.tsx"],"sourcesContent":["import { cn } from '@utils/cn';\nimport type { FC, HTMLAttributes } from 'react';\nimport { Button, type ButtonProps } from '../Button';\nimport { MaxHeightSmoother } from '../MaxHeightSmoother';\n\n/**\n * Props for the DropDown component\n */\nexport interface DropDownProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Unique identifier that links the trigger and panel for accessibility.\n * This is used to generate proper ARIA attributes.\n * @example \"user-menu\"\n * @example \"language-selector\"\n */\n identifier: string;\n}\n\nexport type DropDownType = FC<DropDownProps> & {\n Trigger: FC<TriggerProps>;\n Panel: FC<PanelProps>;\n};\n\n/**\n * DropDown Component\n *\n * A compound component that provides dropdown/popover functionality with flexible trigger mechanisms.\n * Supports hover, focus, and controlled visibility states with proper accessibility features.\n *\n * @example\n * ```tsx\n * // Basic hover dropdown\n * <DropDown identifier=\"menu\">\n * <DropDown.Trigger identifier=\"menu\">\n * Open Menu\n * </DropDown.Trigger>\n * <DropDown.Panel identifier=\"menu\" isOverable>\n * <div>Menu content</div>\n * </DropDown.Panel>\n * </DropDown>\n *\n * // Focus-based dropdown for accessibility\n * <DropDown identifier=\"accessible-menu\">\n * <DropDown.Trigger identifier=\"accessible-menu\">\n * Keyboard Accessible Menu\n * </DropDown.Trigger>\n * <DropDown.Panel identifier=\"accessible-menu\" isFocusable>\n * <div>Accessible content</div>\n * </DropDown.Panel>\n * </DropDown>\n *\n * // Controlled dropdown\n * <DropDown identifier=\"controlled\">\n * <DropDown.Trigger identifier=\"controlled\">\n * Controlled Menu\n * </DropDown.Trigger>\n * <DropDown.Panel identifier=\"controlled\" isHidden={!isOpen}>\n * <div>Controlled content</div>\n * </DropDown.Panel>\n * </DropDown>\n * ```\n *\n * @component\n * @accessibility\n * - Uses proper ARIA attributes (aria-haspopup, aria-labelledby, etc.)\n * - Supports keyboard navigation with focus management\n * - Screen reader compatible with proper role and labeling\n * - Maintains focus trap within dropdown when needed\n */\nexport const DropDown: DropDownType = ({\n children,\n className,\n identifier,\n ...props\n}) => (\n <div\n className={cn(`group/dropdown relative flex`, className)}\n aria-label={`DropDown ${identifier}`}\n id={`dropdown-container-${identifier}`}\n {...props}\n >\n {children}\n </div>\n);\n\n/**\n * Props for the DropDown.Trigger component\n */\nexport interface TriggerProps extends Partial<ButtonProps> {\n /**\n * Unique identifier that matches the parent DropDown identifier\n * @example \"user-menu\"\n */\n identifier: string;\n}\n\n/**\n * DropDown.Trigger Component\n *\n * The clickable/focusable element that controls the dropdown panel visibility.\n * Built on top of the Button component with enhanced dropdown-specific behaviors.\n *\n * @example\n * ```tsx\n * <DropDown.Trigger identifier=\"menu\">\n * <div>Click to open</div>\n * </DropDown.Trigger>\n * ```\n *\n * @component\n * @accessibility\n * - Automatically generates appropriate ARIA attributes\n * - Maintains proper focus management across browsers\n * - Works with keyboard navigation (Tab, Enter, Space)\n * - Announces dropdown state to screen readers\n *\n * @note Don't nest Button components inside the Trigger - it's already a button\n */\nconst Trigger: FC<TriggerProps> = ({\n children,\n identifier,\n className,\n label,\n ...props\n}) => (\n <Button\n className={cn([\n 'w-full cursor-pointer',\n 'group-focus-within/dropdown:bg-current/20 group-focus-within/dropdown:ring-4',\n className,\n ])}\n label={label ?? `Open panel ${identifier}`}\n aria-haspopup=\"true\"\n aria-controls={`dropdown-panel-${identifier}`}\n id={`dropdown-trigger-${identifier}`}\n onClick={(e) => {\n // Ensure focus behavior is consistent across all mobile browsers\n (e.currentTarget as HTMLButtonElement).focus();\n }}\n variant=\"none\"\n {...props}\n >\n {children}\n </Button>\n);\n\n/**\n * Horizontal alignment options for the dropdown panel relative to the trigger\n */\nexport enum DropDownAlign {\n /** Align panel to the start (left in LTR, right in RTL) of the trigger */\n START = 'start',\n /** Align panel to the end (right in LTR, left in RTL) of the trigger */\n END = 'end',\n}\n\n/**\n * Vertical alignment options for the dropdown panel relative to the trigger\n */\nexport enum DropDownYAlign {\n /** Position panel below the trigger (default) */\n BELOW = 'below',\n /** Position panel above the trigger */\n ABOVE = 'above',\n}\n\n/**\n * Props for the DropDown.Panel component\n */\nexport interface PanelProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Whether the panel should be visible when the trigger is focused.\n * Enables keyboard accessibility for the dropdown.\n * @default false\n */\n isFocusable?: boolean;\n\n /**\n * Controls panel visibility explicitly.\n * - `true`: Panel is hidden\n * - `false`: Panel is visible\n * - `undefined`: Panel visibility controlled by hover/focus states\n * @default undefined\n */\n isHidden?: boolean;\n\n /**\n * Whether the panel should be visible when hovering over the trigger.\n * Provides quick access via mouse interaction.\n * @default false\n */\n isOverable?: boolean;\n\n /**\n * Unique identifier that matches the parent DropDown identifier\n * @example \"user-menu\"\n */\n identifier: string;\n\n /**\n * Horizontal alignment of the panel relative to the trigger\n * @default DropDownAlign.START\n */\n align?: DropDownAlign | `${DropDownAlign}`;\n\n /**\n * Vertical alignment of the panel relative to the trigger\n * @default DropDownYAlign.BELOW\n */\n yAlign?: DropDownYAlign | `${DropDownYAlign}`;\n}\n\n/**\n * DropDown.Panel Component\n *\n * The content area that appears when the dropdown is triggered.\n * Supports multiple trigger methods (hover, focus, controlled) with smooth animations.\n *\n * @example\n * ```tsx\n * // Hover-triggered panel\n * <DropDown.Panel identifier=\"menu\" isOverable>\n * <div>Content appears on hover</div>\n * </DropDown.Panel>\n *\n * // Focus-triggered panel (accessible)\n * <DropDown.Panel identifier=\"menu\" isFocusable>\n * <div>Content appears on focus</div>\n * </DropDown.Panel>\n *\n * // Controlled panel\n * <DropDown.Panel identifier=\"menu\" isHidden={!isOpen}>\n * <div>Content visibility controlled externally</div>\n * </DropDown.Panel>\n *\n * // Right-aligned panel\n * <DropDown.Panel identifier=\"menu\" align={DropDownAlign.END} isOverable>\n * <div>Right-aligned content</div>\n * </DropDown.Panel>\n *\n * // Panel opening above the trigger\n * <DropDown.Panel identifier=\"menu\" yAlign={DropDownYAlign.ABOVE} isOverable>\n * <div>Content appears above</div>\n * </DropDown.Panel>\n * ```\n *\n * @component\n * @accessibility\n * - Proper ARIA attributes (role, aria-labelledby, aria-hidden)\n * - Smooth height transitions with MaxHeightSmoother\n * - Keyboard navigation support when isFocusable is enabled\n * - Screen reader announcements for state changes\n */\nconst Panel: FC<PanelProps> = ({\n children,\n isHidden = undefined,\n isOverable = false,\n isFocusable = false,\n align = DropDownAlign.START,\n yAlign = DropDownYAlign.BELOW,\n identifier,\n className,\n ...props\n}) => (\n <div\n className={cn(\n 'absolute z-100 min-w-full',\n /* Horizontal positioning */\n align === DropDownAlign.START && 'left-0',\n align === DropDownAlign.END && 'right-0',\n /* Vertical positioning */\n yAlign === DropDownYAlign.BELOW && 'top-[calc(100%+0.5rem)]',\n yAlign === DropDownYAlign.ABOVE && 'bottom-[calc(100%+0.5rem)]',\n className\n )}\n aria-hidden={isHidden}\n role=\"region\"\n aria-labelledby={`dropdown-trigger-${identifier}`}\n id={`dropdown-panel-${identifier}`}\n >\n <MaxHeightSmoother\n isHidden={isHidden}\n className={cn(\n 'overflow-x-visible',\n isHidden === false && 'invisible',\n isHidden === true && 'visible',\n isOverable &&\n 'group-hover/dropdown:visible group-hover/dropdown:grid-rows-[1fr]',\n isFocusable &&\n 'group-focus-within/dropdown:visible group-focus-within/dropdown:grid-rows-[1fr]'\n )}\n {...props}\n >\n {children}\n </MaxHeightSmoother>\n </div>\n);\n\nDropDown.Trigger = Trigger;\nDropDown.Panel = Panel;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqEA,MAAa,YAA0B,EACrC,UACA,WACA,YACA,GAAG,YAEH,oBAAC,OAAD;CACE,WAAW,GAAG,gCAAgC,UAAU;CACxD,cAAY,YAAY;CACxB,IAAI,sBAAsB;CAC1B,GAAI;CAEH;CACG;;;;;;;;;;;;;;;;;;;;;;;AAoCR,MAAM,WAA6B,EACjC,UACA,YACA,WACA,OACA,GAAG,YAEH,oBAAC,QAAD;CACE,WAAW,GAAG;EACZ;EACA;EACA;EACD,CAAC;CACF,OAAO,SAAS,cAAc;CAC9B,iBAAc;CACd,iBAAe,kBAAkB;CACjC,IAAI,oBAAoB;CACxB,UAAU,MAAM;EAEd,AAAC,EAAE,cAAoC,OAAO;;CAEhD,SAAQ;CACR,GAAI;CAEH;CACM;;;;AAMX,IAAY,gBAAL;;CAEL;;CAEA;;KACD;;;;AAKD,IAAY,iBAAL;;CAEL;;CAEA;;KACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyFD,MAAM,SAAyB,EAC7B,UACA,WAAW,QACX,aAAa,OACb,cAAc,OACd,iBACA,kBACA,YACA,WACA,GAAG,YAEH,oBAAC,OAAD;CACE,WAAW,GACT,6BAEA,qBAAiC,UACjC,mBAA+B,WAE/B,sBAAmC,2BACnC,sBAAmC,8BACnC,UACD;CACD,eAAa;CACb,MAAK;CACL,mBAAiB,oBAAoB;CACrC,IAAI,kBAAkB;WAEtB,oBAAC,mBAAD;EACY;EACV,WAAW,GACT,sBACA,aAAa,SAAS,aACtB,aAAa,QAAQ,WACrB,cACE,qEACF,eACE,kFACH;EACD,GAAI;EAEH;EACiB;CAChB;AAGR,SAAS,UAAU;AACnB,SAAS,QAAQ"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/components/DropDown/index.tsx"],"sourcesContent":["import { cn } from '@utils/cn';\nimport type { FC, HTMLAttributes } from 'react';\nimport { Button, type ButtonProps } from '../Button';\nimport { MaxHeightSmoother } from '../MaxHeightSmoother';\n\n/**\n * Props for the DropDown component\n */\nexport interface DropDownProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Unique identifier that links the trigger and panel for accessibility.\n * This is used to generate proper ARIA attributes.\n * @example \"user-menu\"\n * @example \"language-selector\"\n */\n identifier: string;\n}\n\nexport type DropDownType = FC<DropDownProps> & {\n Trigger: FC<TriggerProps>;\n Panel: FC<PanelProps>;\n};\n\n/**\n * DropDown Component\n *\n * A compound component that provides dropdown/popover functionality with flexible trigger mechanisms.\n * Supports hover, focus, and controlled visibility states with proper accessibility features.\n *\n * @example\n * ```tsx\n * // Basic hover dropdown\n * <DropDown identifier=\"menu\">\n * <DropDown.Trigger identifier=\"menu\">\n * Open Menu\n * </DropDown.Trigger>\n * <DropDown.Panel identifier=\"menu\" isOverable>\n * <div>Menu content</div>\n * </DropDown.Panel>\n * </DropDown>\n *\n * // Focus-based dropdown for accessibility\n * <DropDown identifier=\"accessible-menu\">\n * <DropDown.Trigger identifier=\"accessible-menu\">\n * Keyboard Accessible Menu\n * </DropDown.Trigger>\n * <DropDown.Panel identifier=\"accessible-menu\" isFocusable>\n * <div>Accessible content</div>\n * </DropDown.Panel>\n * </DropDown>\n *\n * // Controlled dropdown\n * <DropDown identifier=\"controlled\">\n * <DropDown.Trigger identifier=\"controlled\">\n * Controlled Menu\n * </DropDown.Trigger>\n * <DropDown.Panel identifier=\"controlled\" isHidden={!isOpen}>\n * <div>Controlled content</div>\n * </DropDown.Panel>\n * </DropDown>\n * ```\n *\n * @component\n * @accessibility\n * - Uses proper ARIA attributes (aria-haspopup, aria-labelledby, etc.)\n * - Supports keyboard navigation with focus management\n * - Screen reader compatible with proper role and labeling\n * - Maintains focus trap within dropdown when needed\n */\nexport const DropDown: DropDownType = ({\n children,\n className,\n identifier,\n ...props\n}) => (\n <div\n className={cn(`group/dropdown relative flex`, className)}\n aria-label={`DropDown ${identifier}`}\n id={`dropdown-container-${identifier}`}\n {...props}\n >\n {children}\n </div>\n);\n\n/**\n * Props for the DropDown.Trigger component\n */\nexport interface TriggerProps extends Partial<ButtonProps> {\n /**\n * Unique identifier that matches the parent DropDown identifier\n * @example \"user-menu\"\n */\n identifier: string;\n}\n\n/**\n * DropDown.Trigger Component\n *\n * The clickable/focusable element that controls the dropdown panel visibility.\n * Built on top of the Button component with enhanced dropdown-specific behaviors.\n *\n * @example\n * ```tsx\n * <DropDown.Trigger identifier=\"menu\">\n * <div>Click to open</div>\n * </DropDown.Trigger>\n * ```\n *\n * @component\n * @accessibility\n * - Automatically generates appropriate ARIA attributes\n * - Maintains proper focus management across browsers\n * - Works with keyboard navigation (Tab, Enter, Space)\n * - Announces dropdown state to screen readers\n *\n * @note Don't nest Button components inside the Trigger - it's already a button\n */\nconst Trigger: FC<TriggerProps> = ({\n children,\n identifier,\n className,\n label,\n ...props\n}) => (\n <Button\n className={cn([\n 'w-full cursor-pointer',\n 'group-focus-within/dropdown:bg-current/20 group-focus-within/dropdown:ring-4',\n className,\n ])}\n label={label ?? `Open panel ${identifier}`}\n aria-haspopup=\"true\"\n aria-controls={`dropdown-panel-${identifier}`}\n id={`dropdown-trigger-${identifier}`}\n onClick={(e) => {\n // Ensure focus behavior is consistent across all mobile browsers\n (e.currentTarget as HTMLButtonElement).focus();\n }}\n variant=\"none\"\n {...props}\n >\n {children}\n </Button>\n);\n\n/**\n * Horizontal alignment options for the dropdown panel relative to the trigger\n */\nexport enum DropDownAlign {\n /** Align panel to the start (left in LTR, right in RTL) of the trigger */\n START = 'start',\n /** Align panel to the end (right in LTR, left in RTL) of the trigger */\n END = 'end',\n}\n\n/**\n * Vertical alignment options for the dropdown panel relative to the trigger\n */\nexport enum DropDownYAlign {\n /** Position panel below the trigger (default) */\n BELOW = 'below',\n /** Position panel above the trigger */\n ABOVE = 'above',\n}\n\n/**\n * Props for the DropDown.Panel component\n */\nexport interface PanelProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Whether the panel should be visible when the trigger is focused.\n * Enables keyboard accessibility for the dropdown.\n * @default false\n */\n isFocusable?: boolean;\n\n /**\n * Controls panel visibility explicitly.\n * - `true`: Panel is hidden\n * - `false`: Panel is visible\n * - `undefined`: Panel visibility controlled by hover/focus states\n * @default undefined\n */\n isHidden?: boolean;\n\n /**\n * Whether the panel should be visible when hovering over the trigger.\n * Provides quick access via mouse interaction.\n * @default false\n */\n isOverable?: boolean;\n\n /**\n * Unique identifier that matches the parent DropDown identifier\n * @example \"user-menu\"\n */\n identifier: string;\n\n /**\n * Horizontal alignment of the panel relative to the trigger\n * @default DropDownAlign.START\n */\n align?: DropDownAlign | `${DropDownAlign}`;\n\n /**\n * Vertical alignment of the panel relative to the trigger\n * @default DropDownYAlign.BELOW\n */\n yAlign?: DropDownYAlign | `${DropDownYAlign}`;\n\n /**\n * Additional className applied directly to the MaxHeightSmoother container.\n * Useful for adding transition delays — e.g. `\"delay-0 group-hover/dropdown:delay-500\"`\n * gives an open delay while keeping the close instant.\n */\n smootherClassName?: string;\n}\n\n/**\n * DropDown.Panel Component\n *\n * The content area that appears when the dropdown is triggered.\n * Supports multiple trigger methods (hover, focus, controlled) with smooth animations.\n *\n * @example\n * ```tsx\n * // Hover-triggered panel\n * <DropDown.Panel identifier=\"menu\" isOverable>\n * <div>Content appears on hover</div>\n * </DropDown.Panel>\n *\n * // Focus-triggered panel (accessible)\n * <DropDown.Panel identifier=\"menu\" isFocusable>\n * <div>Content appears on focus</div>\n * </DropDown.Panel>\n *\n * // Controlled panel\n * <DropDown.Panel identifier=\"menu\" isHidden={!isOpen}>\n * <div>Content visibility controlled externally</div>\n * </DropDown.Panel>\n *\n * // Right-aligned panel\n * <DropDown.Panel identifier=\"menu\" align={DropDownAlign.END} isOverable>\n * <div>Right-aligned content</div>\n * </DropDown.Panel>\n *\n * // Panel opening above the trigger\n * <DropDown.Panel identifier=\"menu\" yAlign={DropDownYAlign.ABOVE} isOverable>\n * <div>Content appears above</div>\n * </DropDown.Panel>\n * ```\n *\n * @component\n * @accessibility\n * - Proper ARIA attributes (role, aria-labelledby, aria-hidden)\n * - Smooth height transitions with MaxHeightSmoother\n * - Keyboard navigation support when isFocusable is enabled\n * - Screen reader announcements for state changes\n */\nconst Panel: FC<PanelProps> = ({\n children,\n isHidden = undefined,\n isOverable = false,\n isFocusable = false,\n align = DropDownAlign.START,\n yAlign = DropDownYAlign.BELOW,\n identifier,\n className,\n smootherClassName,\n ...props\n}) => (\n <div\n className={cn(\n 'absolute z-100 min-w-full',\n /* Horizontal positioning */\n align === DropDownAlign.START && 'left-0',\n align === DropDownAlign.END && 'right-0',\n /* Vertical positioning */\n yAlign === DropDownYAlign.BELOW && 'top-[calc(100%+0.5rem)]',\n yAlign === DropDownYAlign.ABOVE && 'bottom-[calc(100%+0.5rem)]',\n className\n )}\n aria-hidden={isHidden}\n role=\"region\"\n aria-labelledby={`dropdown-trigger-${identifier}`}\n id={`dropdown-panel-${identifier}`}\n >\n <MaxHeightSmoother\n isHidden={isHidden}\n className={cn(\n 'overflow-x-visible',\n isHidden === false && 'invisible',\n isHidden === true && 'visible',\n isOverable &&\n 'group-hover/dropdown:visible group-hover/dropdown:grid-rows-[1fr]',\n isFocusable &&\n 'group-focus-within/dropdown:visible group-focus-within/dropdown:grid-rows-[1fr]',\n smootherClassName\n )}\n {...props}\n >\n {children}\n </MaxHeightSmoother>\n </div>\n);\n\nDropDown.Trigger = Trigger;\nDropDown.Panel = Panel;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqEA,MAAa,YAA0B,EACrC,UACA,WACA,YACA,GAAG,YAEH,oBAAC,OAAD;CACE,WAAW,GAAG,gCAAgC,UAAU;CACxD,cAAY,YAAY;CACxB,IAAI,sBAAsB;CAC1B,GAAI;CAEH;CACG;;;;;;;;;;;;;;;;;;;;;;;AAoCR,MAAM,WAA6B,EACjC,UACA,YACA,WACA,OACA,GAAG,YAEH,oBAAC,QAAD;CACE,WAAW,GAAG;EACZ;EACA;EACA;EACD,CAAC;CACF,OAAO,SAAS,cAAc;CAC9B,iBAAc;CACd,iBAAe,kBAAkB;CACjC,IAAI,oBAAoB;CACxB,UAAU,MAAM;EAEd,AAAC,EAAE,cAAoC,OAAO;;CAEhD,SAAQ;CACR,GAAI;CAEH;CACM;;;;AAMX,IAAY,gBAAL;;CAEL;;CAEA;;KACD;;;;AAKD,IAAY,iBAAL;;CAEL;;CAEA;;KACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgGD,MAAM,SAAyB,EAC7B,UACA,WAAW,QACX,aAAa,OACb,cAAc,OACd,iBACA,kBACA,YACA,WACA,mBACA,GAAG,YAEH,oBAAC,OAAD;CACE,WAAW,GACT,6BAEA,qBAAiC,UACjC,mBAA+B,WAE/B,sBAAmC,2BACnC,sBAAmC,8BACnC,UACD;CACD,eAAa;CACb,MAAK;CACL,mBAAiB,oBAAoB;CACrC,IAAI,kBAAkB;WAEtB,oBAAC,mBAAD;EACY;EACV,WAAW,GACT,sBACA,aAAa,SAAS,aACtB,aAAa,QAAQ,WACrB,cACE,qEACF,eACE,mFACF,kBACD;EACD,GAAI;EAEH;EACiB;CAChB;AAGR,SAAS,UAAU;AACnB,SAAS,QAAQ"}
@@ -478,7 +478,7 @@ const InputOTPSlot = ({ index, className, onClick, onKeyDown, ...props }) => {
478
478
  };
479
479
  const InputOTPSeparator = (props) => /* @__PURE__ */ jsx("div", {
480
480
  "aria-hidden": true,
481
- className: "z-0 table h-0.5 w-3 rounded-full bg-border text-text/50",
481
+ className: "z-0 table h-0.5 w-3 rounded-full text-text/50",
482
482
  ...props,
483
483
  children: /* @__PURE__ */ jsx(MinusIcon, {})
484
484
  });
@@ -1 +1 @@
1
- {"version":3,"file":"OTPInput.mjs","names":[],"sources":["../../../../src/components/Input/OTPInput.tsx"],"sourcesContent":["'use client';\n\n/**\n * This component is a fork of https://github.com/guilhermerodz/input-otp\n */\n\nimport { cn } from '@utils/cn';\nimport { cva } from 'class-variance-authority';\nimport { MinusIcon } from 'lucide-react';\nimport {\n type ChangeEvent,\n type ClipboardEvent,\n type ComponentProps,\n type CSSProperties,\n createContext,\n type FC,\n type InputHTMLAttributes,\n type KeyboardEvent,\n type MouseEvent,\n type ReactNode,\n type RefObject,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { Button, type ButtonProps } from '../Button';\n\n// ---------------- Utilities ----------------\n\nconst syncTimeouts = (cb: (...args: any[]) => unknown): number[] => {\n const t1 = setTimeout(cb, 0); // For faster machines\n const t2 = setTimeout(cb, 1_0);\n const t3 = setTimeout(cb, 5_0);\n return [t1, t2, t3];\n};\n\nconst safeInsertRule = (sheet: CSSStyleSheet, rule: string) => {\n try {\n sheet.insertRule(rule);\n } catch {\n console.error('input-otp could not insert CSS rule:', rule);\n }\n};\n\n// Decided to go with <noscript>\n// instead of `scripting` CSS media query\n// because it's a fallback for initial page load\n// and the <script> tag won't be loaded\n// unless the user has JS disabled.\nconst NOSCRIPT_CSS_FALLBACK = `\n[data-input-otp] {\n --nojs-bg: white !important;\n --nojs-fg: black !important;\n\n background-color: var(--nojs-bg) !important;\n color: var(--nojs-fg) !important;\n caret-color: var(--nojs-fg) !important;\n letter-spacing: .25em !important;\n text-align: center !important;\n border: 1px solid var(--nojs-fg) !important;\n border-radius: 4px !important;\n width: 100% !important;\n}\n@media (prefers-color-scheme: dark) {\n [data-input-otp] {\n --nojs-bg: black !important;\n --nojs-fg: white !important;\n }\n}`;\n\n// ---------------- Constants ----------------\n\nconst PWM_BADGE_MARGIN_RIGHT = 18;\nconst PWM_BADGE_SPACE_WIDTH_PX = 40;\nconst PWM_BADGE_SPACE_WIDTH = `${PWM_BADGE_SPACE_WIDTH_PX}px` as const;\n\nconst PASSWORD_MANAGERS_SELECTORS = [\n '[data-lastpass-icon-root]', // LastPass\n 'com-1password-button', // 1Password\n '[data-dashlanecreated]', // Dashlane\n '[style$=\"2147483647 !important;\"]', // Bitwarden\n].join(',');\n\n// ---------------- Types ----------------\n\nexport type SlotProps = {\n isActive: boolean;\n char: string | null;\n placeholderChar: string | null;\n hasFakeCaret: boolean;\n};\n\nexport type RenderProps = {\n slots: SlotProps[];\n isFocused: boolean;\n isHovering: boolean;\n setSelection: (index: number) => void;\n};\n\ntype OverrideProps<T, R> = Omit<T, keyof R> & R;\n\ntype OTPInputBaseProps = OverrideProps<\n InputHTMLAttributes<HTMLInputElement>,\n {\n value?: string;\n onChange?: (newValue: string) => unknown;\n\n maxLength: number;\n\n onComplete?: (...args: any[]) => unknown;\n onActiveSlotChange?: (activeSlotIndex: number | null) => unknown;\n pushPasswordManagerStrategy?: 'increase-width' | 'none';\n pasteTransformer?: (pasted: string) => string;\n\n containerClassName?: string;\n\n noScriptCSSFallback?: string | null;\n }\n>;\n\ntype InputOTPRenderFn = (props: RenderProps) => ReactNode;\n\nexport type OTPInputProps = OTPInputBaseProps &\n (\n | {\n render: InputOTPRenderFn;\n children?: never;\n }\n | {\n render?: never;\n children: ReactNode;\n }\n );\n\n// ---------------- Hooks ----------------\n\nexport const usePasswordManagerBadge = ({\n containerRef,\n inputRef,\n pushPasswordManagerStrategy,\n isFocused,\n}: {\n containerRef: RefObject<HTMLDivElement | null>;\n inputRef: RefObject<HTMLInputElement | null>;\n pushPasswordManagerStrategy: OTPInputProps['pushPasswordManagerStrategy'];\n isFocused: boolean;\n}) => {\n /** Password managers have a badge\n * and I'll use this state to push them\n * outside the input */\n const [hasPWMBadge, setHasPWMBadge] = useState(false);\n const [hasPWMBadgeSpace, setHasPWMBadgeSpace] = useState(false);\n const [done, setDone] = useState(false);\n\n const willPushPWMBadge =\n pushPasswordManagerStrategy === 'none'\n ? false\n : (pushPasswordManagerStrategy === 'increase-width' ||\n // TODO: remove 'experimental-no-flickering' support in 2.0.0\n pushPasswordManagerStrategy === 'experimental-no-flickering') &&\n hasPWMBadge &&\n hasPWMBadgeSpace;\n\n const trackPWMBadge = () => {\n const container = containerRef.current;\n const input = inputRef.current;\n if (\n !container ||\n !input ||\n done ||\n pushPasswordManagerStrategy === 'none'\n ) {\n return;\n }\n\n const elementToCompare = container;\n\n // Get the top right-center point of the container.\n // That is usually where most password managers place their badge.\n const rightCornerX =\n elementToCompare.getBoundingClientRect().left +\n elementToCompare.offsetWidth;\n const centereredY =\n elementToCompare.getBoundingClientRect().top +\n elementToCompare.offsetHeight / 2;\n const x = rightCornerX - PWM_BADGE_MARGIN_RIGHT;\n const y = centereredY;\n\n // Do an extra search to check for famous password managers\n const pmws = document.querySelectorAll(PASSWORD_MANAGERS_SELECTORS);\n\n // If no password manager is automatically detect,\n // we'll try to dispatch document.elementFromPoint\n // to identify badges\n if (pmws.length === 0) {\n const maybeBadgeEl = document.elementFromPoint(x, y);\n\n // If the found element is the input itself,\n // then we assume it's not a password manager badge.\n // We are not sure. Most times that means there isn't a badge.\n if (maybeBadgeEl === container) {\n return;\n }\n }\n\n setHasPWMBadge(true);\n setDone(true);\n };\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container || pushPasswordManagerStrategy === 'none') {\n return;\n }\n\n // Check if the PWM area is 100% visible\n const checkHasSpace = () => {\n const viewportWidth = window.innerWidth;\n const distanceToRightEdge =\n viewportWidth - container.getBoundingClientRect().right;\n setHasPWMBadgeSpace(distanceToRightEdge >= PWM_BADGE_SPACE_WIDTH_PX);\n };\n\n checkHasSpace();\n const interval = setInterval(checkHasSpace, 1000);\n\n return () => {\n clearInterval(interval);\n };\n }, [containerRef, pushPasswordManagerStrategy]);\n\n useEffect(() => {\n const _isFocused = isFocused || document.activeElement === inputRef.current;\n\n if (pushPasswordManagerStrategy === 'none' || !_isFocused) {\n return;\n }\n const t1 = setTimeout(trackPWMBadge, 0);\n const t2 = setTimeout(trackPWMBadge, 2000);\n const t3 = setTimeout(trackPWMBadge, 5000);\n const t4 = setTimeout(() => {\n setDone(true);\n }, 6000);\n return () => {\n clearTimeout(t1);\n clearTimeout(t2);\n clearTimeout(t3);\n clearTimeout(t4);\n };\n }, [inputRef, isFocused, pushPasswordManagerStrategy]);\n\n return { hasPWMBadge, willPushPWMBadge, PWM_BADGE_SPACE_WIDTH };\n};\n\nexport const usePrevious = <T,>(value: T): T | undefined => {\n const ref = useRef<T | undefined>(undefined);\n useEffect(() => {\n ref.current = value;\n });\n return ref.current;\n};\n\n// ---------------- Context ----------------\n\nexport const OTPInputContext = createContext<RenderProps>({} as RenderProps);\n\n// ---------------- Core Component ----------------\n\nexport const OTPInput: FC<OTPInputProps> = ({\n value: uncheckedValue,\n onChange: uncheckedOnChange,\n maxLength,\n pattern,\n placeholder,\n inputMode = 'numeric',\n onComplete,\n onActiveSlotChange,\n pushPasswordManagerStrategy = 'increase-width',\n pasteTransformer,\n containerClassName,\n noScriptCSSFallback = NOSCRIPT_CSS_FALLBACK,\n render,\n children,\n ...props\n}) => {\n // Only used when `value` state is not provided\n const [internalValue, setInternalValue] = useState(\n typeof props.defaultValue === 'string' ? props.defaultValue : ''\n );\n\n // Definitions\n const value = uncheckedValue ?? internalValue;\n const previousValue = usePrevious(value);\n const onChange = (newValue: string) => {\n uncheckedOnChange?.(newValue);\n setInternalValue(newValue);\n };\n const regexp =\n pattern !== undefined\n ? typeof pattern === 'string'\n ? new RegExp(pattern)\n : pattern\n : null;\n\n /** useRef */\n const inputRef = useRef<HTMLInputElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const initialLoadRef = useRef({\n value,\n onChange,\n isIOS:\n typeof window !== 'undefined' &&\n window?.CSS?.supports?.('-webkit-touch-callout', 'none'),\n });\n const inputMetadataRef = useRef<{\n prev: [number | null, number | null, 'none' | 'forward' | 'backward'];\n }>({\n prev: [\n inputRef.current?.selectionStart ?? null,\n inputRef.current?.selectionEnd ?? null,\n inputRef.current?.selectionDirection ?? 'none',\n ],\n });\n useEffect(() => {\n const input = inputRef.current;\n const container = containerRef.current;\n\n if (!input || !container) {\n return;\n }\n\n // Sync input value\n if (initialLoadRef.current.value !== input.value) {\n initialLoadRef.current.onChange(input.value);\n }\n\n // Previous selection\n inputMetadataRef.current.prev = [\n input.selectionStart,\n input.selectionEnd,\n input.selectionDirection ?? 'none',\n ];\n const onDocumentSelectionChange = () => {\n if (document.activeElement !== input) {\n setMirrorSelectionStart(null);\n setMirrorSelectionEnd(null);\n setActualCaretPosition(null);\n return;\n }\n\n const selectionStart = input.selectionStart;\n const selectionEnd = input.selectionEnd;\n const selectionDirection = input.selectionDirection;\n const maxLength = input.maxLength;\n const value = input.value;\n const previousSelection = inputMetadataRef.current.prev;\n\n let calculatedStart = -1;\n let calculatedEnd = -1;\n let calculatedDirection: 'forward' | 'backward' | 'none' =\n selectionDirection ?? 'none';\n\n if (\n value.length !== 0 &&\n selectionStart !== null &&\n selectionEnd !== null\n ) {\n const isSingleCaret = selectionStart === selectionEnd;\n const isInsertMode =\n selectionStart === value.length && value.length < maxLength;\n\n if (isSingleCaret && !isInsertMode) {\n const caretPosition = selectionStart;\n if (caretPosition === 0) {\n calculatedStart = 0;\n calculatedEnd = 1;\n calculatedDirection = 'forward';\n } else if (caretPosition === maxLength) {\n calculatedStart = caretPosition - 1;\n calculatedEnd = caretPosition;\n calculatedDirection = 'backward';\n } else if (maxLength > 1 && value.length > 1) {\n let offset = 0;\n if (\n previousSelection[0] !== null &&\n previousSelection[1] !== null\n ) {\n calculatedDirection =\n caretPosition < previousSelection[1] ? 'backward' : 'forward';\n const wasPreviouslyInserting =\n previousSelection[0] === previousSelection[1] &&\n previousSelection[0] < maxLength;\n if (\n calculatedDirection === 'backward' &&\n !wasPreviouslyInserting\n ) {\n offset = -1;\n }\n }\n\n calculatedStart = offset + caretPosition;\n calculatedEnd = offset + caretPosition + 1;\n }\n }\n\n if (\n calculatedStart !== -1 &&\n calculatedEnd !== -1 &&\n calculatedStart !== calculatedEnd\n ) {\n inputRef.current?.setSelectionRange(\n calculatedStart,\n calculatedEnd,\n calculatedDirection\n );\n }\n }\n\n const finalSelectionStart =\n calculatedStart !== -1 ? calculatedStart : selectionStart;\n const finalSelectionEnd =\n calculatedEnd !== -1 ? calculatedEnd : selectionEnd;\n const finalDirection = calculatedDirection;\n\n // Track actual caret position (before expansion) for active slot detection\n if (selectionStart !== null && selectionEnd !== null) {\n const isSingleCaret = selectionStart === selectionEnd;\n if (isSingleCaret) {\n setActualCaretPosition(selectionStart);\n } else {\n // When selection is expanded, use the start position as the caret\n setActualCaretPosition(finalSelectionStart);\n }\n } else {\n setActualCaretPosition(null);\n }\n\n setMirrorSelectionStart(finalSelectionStart);\n setMirrorSelectionEnd(finalSelectionEnd);\n inputMetadataRef.current.prev = [\n finalSelectionStart,\n finalSelectionEnd,\n finalDirection,\n ];\n };\n document.addEventListener('selectionchange', onDocumentSelectionChange, {\n capture: true,\n });\n\n // Set initial mirror state\n onDocumentSelectionChange();\n if (document.activeElement === input) {\n setIsFocused(true);\n }\n\n // Apply needed styles\n if (!document.getElementById('input-otp-style')) {\n const styleEl = document.createElement('style');\n styleEl.id = 'input-otp-style';\n document.head.appendChild(styleEl);\n\n if (styleEl.sheet) {\n const autofillStyles =\n 'background: transparent !important; color: transparent !important; border-color: transparent !important; opacity: 0 !important; box-shadow: none !important; -webkit-box-shadow: none !important; -webkit-text-fill-color: transparent !important;';\n\n safeInsertRule(\n styleEl.sheet,\n '[data-input-otp]::selection { background: transparent !important; color: transparent !important; }'\n );\n safeInsertRule(\n styleEl.sheet,\n `[data-input-otp]:autofill { ${autofillStyles} }`\n );\n safeInsertRule(\n styleEl.sheet,\n `[data-input-otp]:-webkit-autofill { ${autofillStyles} }`\n );\n // iOS\n safeInsertRule(\n styleEl.sheet,\n `@supports (-webkit-touch-callout: none) { [data-input-otp] { letter-spacing: -.6em !important; font-weight: 100 !important; font-stretch: ultra-condensed; font-optical-sizing: none !important; left: -1px !important; right: 1px !important; } }`\n );\n // PWM badges\n safeInsertRule(\n styleEl.sheet,\n `[data-input-otp] + * { pointer-events: all !important; }`\n );\n }\n }\n // Track root height\n const updateRootHeight = () => {\n if (container) {\n container.style.setProperty('--root-height', `${input.clientHeight}px`);\n }\n };\n updateRootHeight();\n const resizeObserver = new ResizeObserver(updateRootHeight);\n resizeObserver.observe(input);\n\n return () => {\n document.removeEventListener(\n 'selectionchange',\n onDocumentSelectionChange,\n { capture: true }\n );\n resizeObserver.disconnect();\n };\n }, []);\n\n /** Mirrors for UI rendering purpose only */\n const [isHoveringInput, setIsHoveringInput] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n const [mirrorSelectionStart, setMirrorSelectionStart] = useState<\n number | null\n >(null);\n const [mirrorSelectionEnd, setMirrorSelectionEnd] = useState<number | null>(\n null\n );\n const [actualCaretPosition, setActualCaretPosition] = useState<number | null>(\n null\n );\n\n /** Effects */\n useEffect(() => {\n syncTimeouts(() => {\n // Forcefully remove :autofill state\n inputRef.current?.dispatchEvent(new Event('input'));\n\n // Update the selection state\n const s = inputRef.current?.selectionStart ?? null;\n const e = inputRef.current?.selectionEnd ?? null;\n const dir = inputRef.current?.selectionDirection ?? 'none';\n if (s !== null && e !== null) {\n setMirrorSelectionStart(s);\n setMirrorSelectionEnd(e);\n // Track actual caret position (use start position as caret)\n setActualCaretPosition(s);\n inputMetadataRef.current.prev = [s, e, dir];\n }\n });\n }, [value, isFocused]);\n\n useEffect(() => {\n if (previousValue === undefined) {\n return;\n }\n\n if (\n value !== previousValue &&\n previousValue.length < maxLength &&\n value.length === maxLength\n ) {\n onComplete?.(value);\n }\n }, [maxLength, onComplete, previousValue, value]);\n\n // Track active slot changes\n const previousActiveSlot = useRef<number | null>(null);\n useEffect(() => {\n const activeSlotIndex =\n isFocused && actualCaretPosition !== null ? actualCaretPosition : null;\n\n if (activeSlotIndex !== previousActiveSlot.current) {\n previousActiveSlot.current = activeSlotIndex;\n onActiveSlotChange?.(activeSlotIndex);\n }\n }, [isFocused, actualCaretPosition, onActiveSlotChange]);\n\n const pwmb = usePasswordManagerBadge({\n containerRef,\n inputRef,\n pushPasswordManagerStrategy,\n isFocused,\n });\n\n /** Event handlers */\n const _changeListener = (e: ChangeEvent<HTMLInputElement>) => {\n const newValue = e.currentTarget.value.slice(0, maxLength);\n if (newValue.length > 0 && regexp && !regexp.test(newValue)) {\n e.preventDefault();\n return;\n }\n const maybeHasDeleted =\n typeof previousValue === 'string' &&\n newValue.length < previousValue.length;\n if (maybeHasDeleted) {\n // Since cutting/deleting text doesn't trigger\n // selectionchange event, we'll have to dispatch it manually.\n // NOTE: The following line also triggers when cmd+A then pasting\n // a value with smaller length, which is not ideal for performance.\n document.dispatchEvent(new Event('selectionchange'));\n }\n onChange(newValue);\n };\n const _focusListener = () => {\n if (inputRef.current) {\n const start = Math.min(inputRef.current.value.length, maxLength - 1);\n const end = inputRef.current.value.length;\n inputRef.current?.setSelectionRange(start, end);\n setMirrorSelectionStart(start);\n setMirrorSelectionEnd(end);\n }\n setIsFocused(true);\n };\n // Fix iOS pasting\n const _pasteListener = (e: ClipboardEvent<HTMLInputElement>) => {\n const input = inputRef.current;\n if (\n !pasteTransformer &&\n (!initialLoadRef.current.isIOS || !e.clipboardData || !input)\n ) {\n return;\n }\n\n const _content = e.clipboardData.getData('text/plain');\n const content = pasteTransformer ? pasteTransformer(_content) : _content;\n e.preventDefault();\n\n const start = inputRef.current?.selectionStart;\n const end = inputRef.current?.selectionEnd;\n\n const isReplacing = start !== end;\n\n const newValueUncapped = isReplacing\n ? value.slice(0, start ?? 0) + content + value.slice(end ?? 0) // Replacing\n : value.slice(0, start ?? 0) + content + value.slice(start ?? 0); // Inserting\n const newValue = newValueUncapped.slice(0, maxLength);\n\n if (newValue.length > 0 && regexp && !regexp.test(newValue)) {\n return;\n }\n\n if (input) {\n input.value = newValue;\n onChange(newValue);\n\n const _start = Math.min(newValue.length, maxLength - 1);\n const _end = newValue.length;\n\n input.setSelectionRange(_start, _end);\n setMirrorSelectionStart(_start);\n setMirrorSelectionEnd(_end);\n }\n };\n\n /** Styles - dynamic styles that can't be converted to Tailwind */\n const dynamicInputStyle: CSSProperties = {\n width: pwmb.willPushPWMBadge\n ? `calc(100% + ${pwmb.PWM_BADGE_SPACE_WIDTH})`\n : '100%',\n clipPath: pwmb.willPushPWMBadge\n ? `inset(0 ${pwmb.PWM_BADGE_SPACE_WIDTH} 0 0)`\n : undefined,\n fontSize: 'var(--root-height)',\n };\n\n /** Rendering */\n const renderedInput = (\n <input\n autoComplete={props.autoComplete || 'one-time-code'}\n {...props}\n data-input-otp\n data-input-otp-placeholder-shown={value.length === 0 || undefined}\n data-input-otp-mss={mirrorSelectionStart}\n data-input-otp-mse={mirrorSelectionEnd}\n inputMode={inputMode}\n pattern={regexp?.source}\n aria-placeholder={placeholder}\n className=\"pointer-events-auto absolute inset-0 -z-10 flex h-full border-0 border-transparent bg-transparent text-center font-mono text-transparent tabular-nums leading-none tracking-[-.5em] caret-transparent opacity-100 shadow-none outline-none\"\n style={dynamicInputStyle}\n maxLength={maxLength}\n value={value}\n ref={inputRef}\n onPaste={(e) => {\n _pasteListener(e);\n props.onPaste?.(e);\n }}\n onChange={_changeListener}\n onMouseOver={(e) => {\n setIsHoveringInput(true);\n props.onMouseOver?.(e);\n }}\n onMouseLeave={(e) => {\n setIsHoveringInput(false);\n props.onMouseLeave?.(e);\n }}\n onKeyDown={(e) => {\n // Track arrow key navigation to ensure active slot updates correctly\n if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n // Use requestAnimationFrame to check selection after browser has processed the key\n requestAnimationFrame(() => {\n const input = inputRef.current;\n if (input && document.activeElement === input) {\n const s = input.selectionStart;\n const end = input.selectionEnd;\n if (s !== null && end !== null) {\n // Update actual caret position - use start position as caret\n setActualCaretPosition(s);\n }\n }\n });\n }\n props.onKeyDown?.(e);\n }}\n onFocus={(e) => {\n _focusListener();\n props.onFocus?.(e);\n }}\n onBlur={(e) => {\n setIsFocused(false);\n props.onBlur?.(e);\n }}\n />\n );\n\n const setSelection = (index: number) => {\n const input = inputRef.current;\n if (!input || props.disabled) {\n return;\n }\n\n // Clamp index to valid range\n const clampedIndex = Math.max(0, Math.min(index, maxLength - 1));\n\n // Focus the input if not already focused\n if (document.activeElement !== input) {\n input.focus();\n }\n\n // Set selection to the clicked slot\n // If there's a character at that position, select it; otherwise just position the caret\n const hasChar = value[clampedIndex] !== undefined;\n const start = clampedIndex;\n const end = hasChar ? clampedIndex + 1 : clampedIndex;\n\n input.setSelectionRange(start, end);\n setMirrorSelectionStart(start);\n setMirrorSelectionEnd(end);\n setIsFocused(true);\n };\n\n const contextValue: RenderProps = {\n slots: Array.from({ length: maxLength }).map((_, slotIdx) => {\n const isActive =\n isFocused &&\n mirrorSelectionStart !== null &&\n mirrorSelectionEnd !== null &&\n ((mirrorSelectionStart === mirrorSelectionEnd &&\n slotIdx === mirrorSelectionStart) ||\n (slotIdx >= mirrorSelectionStart && slotIdx < mirrorSelectionEnd));\n\n const char = value[slotIdx] !== undefined ? value[slotIdx] : null;\n const placeholderChar =\n value[0] !== undefined ? null : (placeholder?.[slotIdx] ?? null);\n\n return {\n char,\n placeholderChar,\n isActive,\n hasFakeCaret: isActive && char === null,\n };\n }),\n isFocused,\n isHovering: !props.disabled && isHoveringInput,\n setSelection,\n };\n\n const renderedChildren =\n render !== undefined ? (\n render(contextValue)\n ) : (\n <OTPInputContext.Provider value={contextValue}>\n {children}\n </OTPInputContext.Provider>\n );\n\n return (\n <>\n {noScriptCSSFallback !== null && (\n <noscript>\n <style>{noScriptCSSFallback}</style>\n </noscript>\n )}\n\n <div\n ref={containerRef}\n className={cn(\n 'relative',\n props.disabled ? 'cursor-default' : 'cursor-text',\n containerClassName\n )}\n >\n {renderedChildren}\n\n <div className=\"absolute inset-0\">{renderedInput}</div>\n </div>\n </>\n );\n};\n\n// ---------------- Root ----------------\n\ntype InputOTPProps = Omit<ComponentProps<typeof OTPInput>, 'children'>;\n\nexport const inputSlotVariants = cva('block text-center', {\n variants: {\n size: {\n sm: 'h-4 w-3 text-sm',\n md: 'h-5 w-4 text-base',\n lg: 'h-6 w-5 text-lg',\n xl: 'h-7 w-6 text-xl',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\nexport const InputOTP: FC<InputOTPProps> = ({\n className,\n render,\n ...props\n}) => (\n <OTPInput\n containerClassName=\"relative flex items-center gap-2 has-disabled:opacity-50\"\n className={cn('disabled:cursor-not-allowed', className)}\n render={render!}\n {...props}\n />\n);\n\n// ---------------- Group ----------------\n\nexport const InputOTPGroup = ({\n className,\n ...props\n}: ComponentProps<'div'>) => (\n <div className={cn('z-10 flex items-center gap-3', className)} {...props} />\n);\n\n// ---------------- Slot ----------------\n\ntype InputOTPSlotProps = Omit<ButtonProps, 'variant' | 'label'> & {\n index: number;\n};\n\nexport const InputOTPSlot: FC<InputOTPSlotProps> = ({\n index,\n className,\n onClick,\n onKeyDown,\n ...props\n}) => {\n const inputOTPContext = useContext(OTPInputContext);\n const { char, isActive } = inputOTPContext?.slots[index] ?? {};\n const { setSelection } = inputOTPContext ?? {};\n\n const handleClick = (e: MouseEvent<HTMLButtonElement>) => {\n setSelection?.(index);\n onClick?.(e);\n };\n\n const handleKeyDown = (e: KeyboardEvent<HTMLButtonElement>) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n setSelection?.(index);\n }\n onKeyDown?.(e);\n };\n\n return (\n <Button\n isSelected={isActive}\n variant=\"input\"\n color=\"custom\"\n tabIndex={-1}\n className={cn('relative z-10 px-2!', isActive && 'ring-4!', className)}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n label={null}\n {...props}\n >\n {/* value */}\n <span className=\"relative z-10 flex h-6 w-4 items-center justify-center\">\n {char}\n </span>\n </Button>\n );\n};\n\n// ---------------- Separator ----------------\n\nexport const InputOTPSeparator: FC<ComponentProps<'div'>> = (props) => (\n <div\n aria-hidden\n className=\"z-0 table h-0.5 w-3 rounded-full bg-border text-text/50\"\n {...props}\n >\n <MinusIcon />\n </div>\n);\n\nexport const InputIndicator: FC<ComponentProps<'div'>> = (props) => (\n <div\n data-indicator\n className=\"absolute top-0 z-0 h-full w-auto rounded-xl bg-text/20 ring-4 ring-text/20 transition-[left,width] duration-300 ease-in-out [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl motion-reduce:transition-none\"\n {...props}\n />\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"OTPInput.mjs","names":[],"sources":["../../../../src/components/Input/OTPInput.tsx"],"sourcesContent":["'use client';\n\n/**\n * This component is a fork of https://github.com/guilhermerodz/input-otp\n */\n\nimport { cn } from '@utils/cn';\nimport { cva } from 'class-variance-authority';\nimport { MinusIcon } from 'lucide-react';\nimport {\n type ChangeEvent,\n type ClipboardEvent,\n type ComponentProps,\n type CSSProperties,\n createContext,\n type FC,\n type InputHTMLAttributes,\n type KeyboardEvent,\n type MouseEvent,\n type ReactNode,\n type RefObject,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { Button, type ButtonProps } from '../Button';\n\n// ---------------- Utilities ----------------\n\nconst syncTimeouts = (cb: (...args: any[]) => unknown): number[] => {\n const t1 = setTimeout(cb, 0); // For faster machines\n const t2 = setTimeout(cb, 1_0);\n const t3 = setTimeout(cb, 5_0);\n return [t1, t2, t3];\n};\n\nconst safeInsertRule = (sheet: CSSStyleSheet, rule: string) => {\n try {\n sheet.insertRule(rule);\n } catch {\n console.error('input-otp could not insert CSS rule:', rule);\n }\n};\n\n// Decided to go with <noscript>\n// instead of `scripting` CSS media query\n// because it's a fallback for initial page load\n// and the <script> tag won't be loaded\n// unless the user has JS disabled.\nconst NOSCRIPT_CSS_FALLBACK = `\n[data-input-otp] {\n --nojs-bg: white !important;\n --nojs-fg: black !important;\n\n background-color: var(--nojs-bg) !important;\n color: var(--nojs-fg) !important;\n caret-color: var(--nojs-fg) !important;\n letter-spacing: .25em !important;\n text-align: center !important;\n border: 1px solid var(--nojs-fg) !important;\n border-radius: 4px !important;\n width: 100% !important;\n}\n@media (prefers-color-scheme: dark) {\n [data-input-otp] {\n --nojs-bg: black !important;\n --nojs-fg: white !important;\n }\n}`;\n\n// ---------------- Constants ----------------\n\nconst PWM_BADGE_MARGIN_RIGHT = 18;\nconst PWM_BADGE_SPACE_WIDTH_PX = 40;\nconst PWM_BADGE_SPACE_WIDTH = `${PWM_BADGE_SPACE_WIDTH_PX}px` as const;\n\nconst PASSWORD_MANAGERS_SELECTORS = [\n '[data-lastpass-icon-root]', // LastPass\n 'com-1password-button', // 1Password\n '[data-dashlanecreated]', // Dashlane\n '[style$=\"2147483647 !important;\"]', // Bitwarden\n].join(',');\n\n// ---------------- Types ----------------\n\nexport type SlotProps = {\n isActive: boolean;\n char: string | null;\n placeholderChar: string | null;\n hasFakeCaret: boolean;\n};\n\nexport type RenderProps = {\n slots: SlotProps[];\n isFocused: boolean;\n isHovering: boolean;\n setSelection: (index: number) => void;\n};\n\ntype OverrideProps<T, R> = Omit<T, keyof R> & R;\n\ntype OTPInputBaseProps = OverrideProps<\n InputHTMLAttributes<HTMLInputElement>,\n {\n value?: string;\n onChange?: (newValue: string) => unknown;\n\n maxLength: number;\n\n onComplete?: (...args: any[]) => unknown;\n onActiveSlotChange?: (activeSlotIndex: number | null) => unknown;\n pushPasswordManagerStrategy?: 'increase-width' | 'none';\n pasteTransformer?: (pasted: string) => string;\n\n containerClassName?: string;\n\n noScriptCSSFallback?: string | null;\n }\n>;\n\ntype InputOTPRenderFn = (props: RenderProps) => ReactNode;\n\nexport type OTPInputProps = OTPInputBaseProps &\n (\n | {\n render: InputOTPRenderFn;\n children?: never;\n }\n | {\n render?: never;\n children: ReactNode;\n }\n );\n\n// ---------------- Hooks ----------------\n\nexport const usePasswordManagerBadge = ({\n containerRef,\n inputRef,\n pushPasswordManagerStrategy,\n isFocused,\n}: {\n containerRef: RefObject<HTMLDivElement | null>;\n inputRef: RefObject<HTMLInputElement | null>;\n pushPasswordManagerStrategy: OTPInputProps['pushPasswordManagerStrategy'];\n isFocused: boolean;\n}) => {\n /** Password managers have a badge\n * and I'll use this state to push them\n * outside the input */\n const [hasPWMBadge, setHasPWMBadge] = useState(false);\n const [hasPWMBadgeSpace, setHasPWMBadgeSpace] = useState(false);\n const [done, setDone] = useState(false);\n\n const willPushPWMBadge =\n pushPasswordManagerStrategy === 'none'\n ? false\n : (pushPasswordManagerStrategy === 'increase-width' ||\n // TODO: remove 'experimental-no-flickering' support in 2.0.0\n pushPasswordManagerStrategy === 'experimental-no-flickering') &&\n hasPWMBadge &&\n hasPWMBadgeSpace;\n\n const trackPWMBadge = () => {\n const container = containerRef.current;\n const input = inputRef.current;\n if (\n !container ||\n !input ||\n done ||\n pushPasswordManagerStrategy === 'none'\n ) {\n return;\n }\n\n const elementToCompare = container;\n\n // Get the top right-center point of the container.\n // That is usually where most password managers place their badge.\n const rightCornerX =\n elementToCompare.getBoundingClientRect().left +\n elementToCompare.offsetWidth;\n const centereredY =\n elementToCompare.getBoundingClientRect().top +\n elementToCompare.offsetHeight / 2;\n const x = rightCornerX - PWM_BADGE_MARGIN_RIGHT;\n const y = centereredY;\n\n // Do an extra search to check for famous password managers\n const pmws = document.querySelectorAll(PASSWORD_MANAGERS_SELECTORS);\n\n // If no password manager is automatically detect,\n // we'll try to dispatch document.elementFromPoint\n // to identify badges\n if (pmws.length === 0) {\n const maybeBadgeEl = document.elementFromPoint(x, y);\n\n // If the found element is the input itself,\n // then we assume it's not a password manager badge.\n // We are not sure. Most times that means there isn't a badge.\n if (maybeBadgeEl === container) {\n return;\n }\n }\n\n setHasPWMBadge(true);\n setDone(true);\n };\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container || pushPasswordManagerStrategy === 'none') {\n return;\n }\n\n // Check if the PWM area is 100% visible\n const checkHasSpace = () => {\n const viewportWidth = window.innerWidth;\n const distanceToRightEdge =\n viewportWidth - container.getBoundingClientRect().right;\n setHasPWMBadgeSpace(distanceToRightEdge >= PWM_BADGE_SPACE_WIDTH_PX);\n };\n\n checkHasSpace();\n const interval = setInterval(checkHasSpace, 1000);\n\n return () => {\n clearInterval(interval);\n };\n }, [containerRef, pushPasswordManagerStrategy]);\n\n useEffect(() => {\n const _isFocused = isFocused || document.activeElement === inputRef.current;\n\n if (pushPasswordManagerStrategy === 'none' || !_isFocused) {\n return;\n }\n const t1 = setTimeout(trackPWMBadge, 0);\n const t2 = setTimeout(trackPWMBadge, 2000);\n const t3 = setTimeout(trackPWMBadge, 5000);\n const t4 = setTimeout(() => {\n setDone(true);\n }, 6000);\n return () => {\n clearTimeout(t1);\n clearTimeout(t2);\n clearTimeout(t3);\n clearTimeout(t4);\n };\n }, [inputRef, isFocused, pushPasswordManagerStrategy]);\n\n return { hasPWMBadge, willPushPWMBadge, PWM_BADGE_SPACE_WIDTH };\n};\n\nexport const usePrevious = <T,>(value: T): T | undefined => {\n const ref = useRef<T | undefined>(undefined);\n useEffect(() => {\n ref.current = value;\n });\n return ref.current;\n};\n\n// ---------------- Context ----------------\n\nexport const OTPInputContext = createContext<RenderProps>({} as RenderProps);\n\n// ---------------- Core Component ----------------\n\nexport const OTPInput: FC<OTPInputProps> = ({\n value: uncheckedValue,\n onChange: uncheckedOnChange,\n maxLength,\n pattern,\n placeholder,\n inputMode = 'numeric',\n onComplete,\n onActiveSlotChange,\n pushPasswordManagerStrategy = 'increase-width',\n pasteTransformer,\n containerClassName,\n noScriptCSSFallback = NOSCRIPT_CSS_FALLBACK,\n render,\n children,\n ...props\n}) => {\n // Only used when `value` state is not provided\n const [internalValue, setInternalValue] = useState(\n typeof props.defaultValue === 'string' ? props.defaultValue : ''\n );\n\n // Definitions\n const value = uncheckedValue ?? internalValue;\n const previousValue = usePrevious(value);\n const onChange = (newValue: string) => {\n uncheckedOnChange?.(newValue);\n setInternalValue(newValue);\n };\n const regexp =\n pattern !== undefined\n ? typeof pattern === 'string'\n ? new RegExp(pattern)\n : pattern\n : null;\n\n /** useRef */\n const inputRef = useRef<HTMLInputElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const initialLoadRef = useRef({\n value,\n onChange,\n isIOS:\n typeof window !== 'undefined' &&\n window?.CSS?.supports?.('-webkit-touch-callout', 'none'),\n });\n const inputMetadataRef = useRef<{\n prev: [number | null, number | null, 'none' | 'forward' | 'backward'];\n }>({\n prev: [\n inputRef.current?.selectionStart ?? null,\n inputRef.current?.selectionEnd ?? null,\n inputRef.current?.selectionDirection ?? 'none',\n ],\n });\n useEffect(() => {\n const input = inputRef.current;\n const container = containerRef.current;\n\n if (!input || !container) {\n return;\n }\n\n // Sync input value\n if (initialLoadRef.current.value !== input.value) {\n initialLoadRef.current.onChange(input.value);\n }\n\n // Previous selection\n inputMetadataRef.current.prev = [\n input.selectionStart,\n input.selectionEnd,\n input.selectionDirection ?? 'none',\n ];\n const onDocumentSelectionChange = () => {\n if (document.activeElement !== input) {\n setMirrorSelectionStart(null);\n setMirrorSelectionEnd(null);\n setActualCaretPosition(null);\n return;\n }\n\n const selectionStart = input.selectionStart;\n const selectionEnd = input.selectionEnd;\n const selectionDirection = input.selectionDirection;\n const maxLength = input.maxLength;\n const value = input.value;\n const previousSelection = inputMetadataRef.current.prev;\n\n let calculatedStart = -1;\n let calculatedEnd = -1;\n let calculatedDirection: 'forward' | 'backward' | 'none' =\n selectionDirection ?? 'none';\n\n if (\n value.length !== 0 &&\n selectionStart !== null &&\n selectionEnd !== null\n ) {\n const isSingleCaret = selectionStart === selectionEnd;\n const isInsertMode =\n selectionStart === value.length && value.length < maxLength;\n\n if (isSingleCaret && !isInsertMode) {\n const caretPosition = selectionStart;\n if (caretPosition === 0) {\n calculatedStart = 0;\n calculatedEnd = 1;\n calculatedDirection = 'forward';\n } else if (caretPosition === maxLength) {\n calculatedStart = caretPosition - 1;\n calculatedEnd = caretPosition;\n calculatedDirection = 'backward';\n } else if (maxLength > 1 && value.length > 1) {\n let offset = 0;\n if (\n previousSelection[0] !== null &&\n previousSelection[1] !== null\n ) {\n calculatedDirection =\n caretPosition < previousSelection[1] ? 'backward' : 'forward';\n const wasPreviouslyInserting =\n previousSelection[0] === previousSelection[1] &&\n previousSelection[0] < maxLength;\n if (\n calculatedDirection === 'backward' &&\n !wasPreviouslyInserting\n ) {\n offset = -1;\n }\n }\n\n calculatedStart = offset + caretPosition;\n calculatedEnd = offset + caretPosition + 1;\n }\n }\n\n if (\n calculatedStart !== -1 &&\n calculatedEnd !== -1 &&\n calculatedStart !== calculatedEnd\n ) {\n inputRef.current?.setSelectionRange(\n calculatedStart,\n calculatedEnd,\n calculatedDirection\n );\n }\n }\n\n const finalSelectionStart =\n calculatedStart !== -1 ? calculatedStart : selectionStart;\n const finalSelectionEnd =\n calculatedEnd !== -1 ? calculatedEnd : selectionEnd;\n const finalDirection = calculatedDirection;\n\n // Track actual caret position (before expansion) for active slot detection\n if (selectionStart !== null && selectionEnd !== null) {\n const isSingleCaret = selectionStart === selectionEnd;\n if (isSingleCaret) {\n setActualCaretPosition(selectionStart);\n } else {\n // When selection is expanded, use the start position as the caret\n setActualCaretPosition(finalSelectionStart);\n }\n } else {\n setActualCaretPosition(null);\n }\n\n setMirrorSelectionStart(finalSelectionStart);\n setMirrorSelectionEnd(finalSelectionEnd);\n inputMetadataRef.current.prev = [\n finalSelectionStart,\n finalSelectionEnd,\n finalDirection,\n ];\n };\n document.addEventListener('selectionchange', onDocumentSelectionChange, {\n capture: true,\n });\n\n // Set initial mirror state\n onDocumentSelectionChange();\n if (document.activeElement === input) {\n setIsFocused(true);\n }\n\n // Apply needed styles\n if (!document.getElementById('input-otp-style')) {\n const styleEl = document.createElement('style');\n styleEl.id = 'input-otp-style';\n document.head.appendChild(styleEl);\n\n if (styleEl.sheet) {\n const autofillStyles =\n 'background: transparent !important; color: transparent !important; border-color: transparent !important; opacity: 0 !important; box-shadow: none !important; -webkit-box-shadow: none !important; -webkit-text-fill-color: transparent !important;';\n\n safeInsertRule(\n styleEl.sheet,\n '[data-input-otp]::selection { background: transparent !important; color: transparent !important; }'\n );\n safeInsertRule(\n styleEl.sheet,\n `[data-input-otp]:autofill { ${autofillStyles} }`\n );\n safeInsertRule(\n styleEl.sheet,\n `[data-input-otp]:-webkit-autofill { ${autofillStyles} }`\n );\n // iOS\n safeInsertRule(\n styleEl.sheet,\n `@supports (-webkit-touch-callout: none) { [data-input-otp] { letter-spacing: -.6em !important; font-weight: 100 !important; font-stretch: ultra-condensed; font-optical-sizing: none !important; left: -1px !important; right: 1px !important; } }`\n );\n // PWM badges\n safeInsertRule(\n styleEl.sheet,\n `[data-input-otp] + * { pointer-events: all !important; }`\n );\n }\n }\n // Track root height\n const updateRootHeight = () => {\n if (container) {\n container.style.setProperty('--root-height', `${input.clientHeight}px`);\n }\n };\n updateRootHeight();\n const resizeObserver = new ResizeObserver(updateRootHeight);\n resizeObserver.observe(input);\n\n return () => {\n document.removeEventListener(\n 'selectionchange',\n onDocumentSelectionChange,\n { capture: true }\n );\n resizeObserver.disconnect();\n };\n }, []);\n\n /** Mirrors for UI rendering purpose only */\n const [isHoveringInput, setIsHoveringInput] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n const [mirrorSelectionStart, setMirrorSelectionStart] = useState<\n number | null\n >(null);\n const [mirrorSelectionEnd, setMirrorSelectionEnd] = useState<number | null>(\n null\n );\n const [actualCaretPosition, setActualCaretPosition] = useState<number | null>(\n null\n );\n\n /** Effects */\n useEffect(() => {\n syncTimeouts(() => {\n // Forcefully remove :autofill state\n inputRef.current?.dispatchEvent(new Event('input'));\n\n // Update the selection state\n const s = inputRef.current?.selectionStart ?? null;\n const e = inputRef.current?.selectionEnd ?? null;\n const dir = inputRef.current?.selectionDirection ?? 'none';\n if (s !== null && e !== null) {\n setMirrorSelectionStart(s);\n setMirrorSelectionEnd(e);\n // Track actual caret position (use start position as caret)\n setActualCaretPosition(s);\n inputMetadataRef.current.prev = [s, e, dir];\n }\n });\n }, [value, isFocused]);\n\n useEffect(() => {\n if (previousValue === undefined) {\n return;\n }\n\n if (\n value !== previousValue &&\n previousValue.length < maxLength &&\n value.length === maxLength\n ) {\n onComplete?.(value);\n }\n }, [maxLength, onComplete, previousValue, value]);\n\n // Track active slot changes\n const previousActiveSlot = useRef<number | null>(null);\n useEffect(() => {\n const activeSlotIndex =\n isFocused && actualCaretPosition !== null ? actualCaretPosition : null;\n\n if (activeSlotIndex !== previousActiveSlot.current) {\n previousActiveSlot.current = activeSlotIndex;\n onActiveSlotChange?.(activeSlotIndex);\n }\n }, [isFocused, actualCaretPosition, onActiveSlotChange]);\n\n const pwmb = usePasswordManagerBadge({\n containerRef,\n inputRef,\n pushPasswordManagerStrategy,\n isFocused,\n });\n\n /** Event handlers */\n const _changeListener = (e: ChangeEvent<HTMLInputElement>) => {\n const newValue = e.currentTarget.value.slice(0, maxLength);\n if (newValue.length > 0 && regexp && !regexp.test(newValue)) {\n e.preventDefault();\n return;\n }\n const maybeHasDeleted =\n typeof previousValue === 'string' &&\n newValue.length < previousValue.length;\n if (maybeHasDeleted) {\n // Since cutting/deleting text doesn't trigger\n // selectionchange event, we'll have to dispatch it manually.\n // NOTE: The following line also triggers when cmd+A then pasting\n // a value with smaller length, which is not ideal for performance.\n document.dispatchEvent(new Event('selectionchange'));\n }\n onChange(newValue);\n };\n const _focusListener = () => {\n if (inputRef.current) {\n const start = Math.min(inputRef.current.value.length, maxLength - 1);\n const end = inputRef.current.value.length;\n inputRef.current?.setSelectionRange(start, end);\n setMirrorSelectionStart(start);\n setMirrorSelectionEnd(end);\n }\n setIsFocused(true);\n };\n // Fix iOS pasting\n const _pasteListener = (e: ClipboardEvent<HTMLInputElement>) => {\n const input = inputRef.current;\n if (\n !pasteTransformer &&\n (!initialLoadRef.current.isIOS || !e.clipboardData || !input)\n ) {\n return;\n }\n\n const _content = e.clipboardData.getData('text/plain');\n const content = pasteTransformer ? pasteTransformer(_content) : _content;\n e.preventDefault();\n\n const start = inputRef.current?.selectionStart;\n const end = inputRef.current?.selectionEnd;\n\n const isReplacing = start !== end;\n\n const newValueUncapped = isReplacing\n ? value.slice(0, start ?? 0) + content + value.slice(end ?? 0) // Replacing\n : value.slice(0, start ?? 0) + content + value.slice(start ?? 0); // Inserting\n const newValue = newValueUncapped.slice(0, maxLength);\n\n if (newValue.length > 0 && regexp && !regexp.test(newValue)) {\n return;\n }\n\n if (input) {\n input.value = newValue;\n onChange(newValue);\n\n const _start = Math.min(newValue.length, maxLength - 1);\n const _end = newValue.length;\n\n input.setSelectionRange(_start, _end);\n setMirrorSelectionStart(_start);\n setMirrorSelectionEnd(_end);\n }\n };\n\n /** Styles - dynamic styles that can't be converted to Tailwind */\n const dynamicInputStyle: CSSProperties = {\n width: pwmb.willPushPWMBadge\n ? `calc(100% + ${pwmb.PWM_BADGE_SPACE_WIDTH})`\n : '100%',\n clipPath: pwmb.willPushPWMBadge\n ? `inset(0 ${pwmb.PWM_BADGE_SPACE_WIDTH} 0 0)`\n : undefined,\n fontSize: 'var(--root-height)',\n };\n\n /** Rendering */\n const renderedInput = (\n <input\n autoComplete={props.autoComplete || 'one-time-code'}\n {...props}\n data-input-otp\n data-input-otp-placeholder-shown={value.length === 0 || undefined}\n data-input-otp-mss={mirrorSelectionStart}\n data-input-otp-mse={mirrorSelectionEnd}\n inputMode={inputMode}\n pattern={regexp?.source}\n aria-placeholder={placeholder}\n className=\"pointer-events-auto absolute inset-0 -z-10 flex h-full border-0 border-transparent bg-transparent text-center font-mono text-transparent tabular-nums leading-none tracking-[-.5em] caret-transparent opacity-100 shadow-none outline-none\"\n style={dynamicInputStyle}\n maxLength={maxLength}\n value={value}\n ref={inputRef}\n onPaste={(e) => {\n _pasteListener(e);\n props.onPaste?.(e);\n }}\n onChange={_changeListener}\n onMouseOver={(e) => {\n setIsHoveringInput(true);\n props.onMouseOver?.(e);\n }}\n onMouseLeave={(e) => {\n setIsHoveringInput(false);\n props.onMouseLeave?.(e);\n }}\n onKeyDown={(e) => {\n // Track arrow key navigation to ensure active slot updates correctly\n if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n // Use requestAnimationFrame to check selection after browser has processed the key\n requestAnimationFrame(() => {\n const input = inputRef.current;\n if (input && document.activeElement === input) {\n const s = input.selectionStart;\n const end = input.selectionEnd;\n if (s !== null && end !== null) {\n // Update actual caret position - use start position as caret\n setActualCaretPosition(s);\n }\n }\n });\n }\n props.onKeyDown?.(e);\n }}\n onFocus={(e) => {\n _focusListener();\n props.onFocus?.(e);\n }}\n onBlur={(e) => {\n setIsFocused(false);\n props.onBlur?.(e);\n }}\n />\n );\n\n const setSelection = (index: number) => {\n const input = inputRef.current;\n if (!input || props.disabled) {\n return;\n }\n\n // Clamp index to valid range\n const clampedIndex = Math.max(0, Math.min(index, maxLength - 1));\n\n // Focus the input if not already focused\n if (document.activeElement !== input) {\n input.focus();\n }\n\n // Set selection to the clicked slot\n // If there's a character at that position, select it; otherwise just position the caret\n const hasChar = value[clampedIndex] !== undefined;\n const start = clampedIndex;\n const end = hasChar ? clampedIndex + 1 : clampedIndex;\n\n input.setSelectionRange(start, end);\n setMirrorSelectionStart(start);\n setMirrorSelectionEnd(end);\n setIsFocused(true);\n };\n\n const contextValue: RenderProps = {\n slots: Array.from({ length: maxLength }).map((_, slotIdx) => {\n const isActive =\n isFocused &&\n mirrorSelectionStart !== null &&\n mirrorSelectionEnd !== null &&\n ((mirrorSelectionStart === mirrorSelectionEnd &&\n slotIdx === mirrorSelectionStart) ||\n (slotIdx >= mirrorSelectionStart && slotIdx < mirrorSelectionEnd));\n\n const char = value[slotIdx] !== undefined ? value[slotIdx] : null;\n const placeholderChar =\n value[0] !== undefined ? null : (placeholder?.[slotIdx] ?? null);\n\n return {\n char,\n placeholderChar,\n isActive,\n hasFakeCaret: isActive && char === null,\n };\n }),\n isFocused,\n isHovering: !props.disabled && isHoveringInput,\n setSelection,\n };\n\n const renderedChildren =\n render !== undefined ? (\n render(contextValue)\n ) : (\n <OTPInputContext.Provider value={contextValue}>\n {children}\n </OTPInputContext.Provider>\n );\n\n return (\n <>\n {noScriptCSSFallback !== null && (\n <noscript>\n <style>{noScriptCSSFallback}</style>\n </noscript>\n )}\n\n <div\n ref={containerRef}\n className={cn(\n 'relative',\n props.disabled ? 'cursor-default' : 'cursor-text',\n containerClassName\n )}\n >\n {renderedChildren}\n\n <div className=\"absolute inset-0\">{renderedInput}</div>\n </div>\n </>\n );\n};\n\n// ---------------- Root ----------------\n\ntype InputOTPProps = Omit<ComponentProps<typeof OTPInput>, 'children'>;\n\nexport const inputSlotVariants = cva('block text-center', {\n variants: {\n size: {\n sm: 'h-4 w-3 text-sm',\n md: 'h-5 w-4 text-base',\n lg: 'h-6 w-5 text-lg',\n xl: 'h-7 w-6 text-xl',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\nexport const InputOTP: FC<InputOTPProps> = ({\n className,\n render,\n ...props\n}) => (\n <OTPInput\n containerClassName=\"relative flex items-center gap-2 has-disabled:opacity-50\"\n className={cn('disabled:cursor-not-allowed', className)}\n render={render!}\n {...props}\n />\n);\n\n// ---------------- Group ----------------\n\nexport const InputOTPGroup = ({\n className,\n ...props\n}: ComponentProps<'div'>) => (\n <div className={cn('z-10 flex items-center gap-3', className)} {...props} />\n);\n\n// ---------------- Slot ----------------\n\ntype InputOTPSlotProps = Omit<ButtonProps, 'variant' | 'label'> & {\n index: number;\n};\n\nexport const InputOTPSlot: FC<InputOTPSlotProps> = ({\n index,\n className,\n onClick,\n onKeyDown,\n ...props\n}) => {\n const inputOTPContext = useContext(OTPInputContext);\n const { char, isActive } = inputOTPContext?.slots[index] ?? {};\n const { setSelection } = inputOTPContext ?? {};\n\n const handleClick = (e: MouseEvent<HTMLButtonElement>) => {\n setSelection?.(index);\n onClick?.(e);\n };\n\n const handleKeyDown = (e: KeyboardEvent<HTMLButtonElement>) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n setSelection?.(index);\n }\n onKeyDown?.(e);\n };\n\n return (\n <Button\n isSelected={isActive}\n variant=\"input\"\n color=\"custom\"\n tabIndex={-1}\n className={cn('relative z-10 px-2!', isActive && 'ring-4!', className)}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n label={null}\n {...props}\n >\n {/* value */}\n <span className=\"relative z-10 flex h-6 w-4 items-center justify-center\">\n {char}\n </span>\n </Button>\n );\n};\n\n// ---------------- Separator ----------------\n\nexport const InputOTPSeparator: FC<ComponentProps<'div'>> = (props) => (\n <div\n aria-hidden\n className=\"z-0 table h-0.5 w-3 rounded-full text-text/50\"\n {...props}\n >\n <MinusIcon />\n </div>\n);\n\nexport const InputIndicator: FC<ComponentProps<'div'>> = (props) => (\n <div\n data-indicator\n className=\"absolute top-0 z-0 h-full w-auto rounded-xl bg-text/20 ring-4 ring-text/20 transition-[left,width] duration-300 ease-in-out [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl motion-reduce:transition-none\"\n {...props}\n />\n);\n"],"mappings":"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"}
@@ -3,14 +3,14 @@ import { Link } from "../Link/Link.mjs";
3
3
  import { H1, H2, H3, H4, H5, H6 } from "../Headers/index.mjs";
4
4
  import { CodeProvider } from "../IDE/CodeContext.mjs";
5
5
  import { Code } from "../IDE/Code.mjs";
6
+ import { MarkDownIframe } from "./MarkDownIframe.mjs";
6
7
  import { TabProvider } from "../Tab/TabContext.mjs";
7
8
  import { Tab } from "../Tab/Tab.mjs";
8
9
  import { SmartTable } from "../Table/SmartTable.mjs";
9
10
  import { Hr, Td, Th, Tr } from "../Table/TableElements.mjs";
10
- import { MarkDownIframe } from "./MarkDownIframe.mjs";
11
11
  import { memo } from "react";
12
12
  import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
13
- import { renderMarkdown } from "react-intlayer";
13
+ import { renderMarkdown } from "react-intlayer/markdown";
14
14
 
15
15
  //#region src/components/MarkDownRender/MarkDownRender.tsx
16
16
  const H1Renderer = (props) => /* @__PURE__ */ jsx(H1, {
@@ -1 +1 @@
1
- {"version":3,"file":"MarkDownRender.mjs","names":[],"sources":["../../../../src/components/MarkDownRender/MarkDownRender.tsx"],"sourcesContent":["import type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { cn } from '@utils/cn';\nimport type { ComponentProps, ComponentPropsWithoutRef, FC } from 'react';\nimport { memo } from 'react';\nimport {\n type MarkdownRenderer as MarkdownRendererIntlayer,\n renderMarkdown,\n} from 'react-intlayer';\nimport type { BundledLanguage } from 'shiki/bundle/web';\nimport { H1, H2, H3, H4, H5, H6 } from '../Headers';\nimport { Code } from '../IDE/Code';\nimport { CodeProvider } from '../IDE/CodeContext';\nimport { Link } from '../Link';\nimport { Tab } from '../Tab';\nimport { TabProvider } from '../Tab/TabContext';\nimport { Hr, SmartTable, Td, Th, Tr } from '../Table';\nimport { MarkDownIframe } from './MarkDownIframe';\n\n// Extracted, stable component renderers\nconst H1Renderer = (props: ComponentProps<'h1'>) => (\n <H1 isClickable className=\"text-text\" {...props} />\n);\nconst H2Renderer = (props: ComponentProps<'h2'>) => (\n <H2 isClickable className=\"mt-16 text-text\" {...props} />\n);\nconst H3Renderer = (props: ComponentProps<'h3'>) => (\n <H3 isClickable className=\"mt-5 text-text\" {...props} />\n);\nconst H4Renderer = (props: ComponentProps<'h4'>) => (\n <H4 isClickable className=\"mt-3 text-text\" {...props} />\n);\nconst H5Renderer = (props: ComponentProps<'h5'>) => (\n <H5 isClickable className=\"mt-3 text-text\" {...props} />\n);\nconst H6Renderer = (props: ComponentProps<'h6'>) => (\n <H6 isClickable className=\"mt-3 text-text\" {...props} />\n);\nconst StrongRenderer = (props: ComponentProps<'strong'>) => (\n <strong className=\"text-text\" {...props} />\n);\n\nconst MemoizedCodeBlock = memo(\n ({\n className,\n children,\n isDarkMode,\n ...rest\n }: ComponentProps<'code'> & { isDarkMode?: boolean }) => {\n const content = String(children ?? '').replace(/\\n$/, '');\n const isBlock = !!className;\n\n if (!isBlock) {\n const decodedContent = content.replace(\n /&(?:amp;)?#(\\d+);/g,\n (_, code: string) => String.fromCharCode(parseInt(code, 10))\n );\n return (\n <code className=\"rounded-md border border-neutral/30 bg-card/60 box-decoration-clone px-1.5 py-0.5 font-mono text-sm\">\n {decodedContent}\n </code>\n );\n }\n\n const language = (className?.replace(/lang(?:uage)?-/, '') ||\n 'plaintext') as BundledLanguage;\n\n return (\n <Code {...rest} language={language} showHeader isDarkMode={isDarkMode}>\n {content}\n </Code>\n );\n },\n (prevProps, nextProps) =>\n prevProps.children === nextProps.children &&\n prevProps.className === nextProps.className &&\n prevProps.isDarkMode === nextProps.isDarkMode\n);\n\nconst createCodeRenderer = (isDarkMode?: boolean) => {\n return function CodeWrapper(props: ComponentProps<'code'>) {\n return <MemoizedCodeBlock {...props} isDarkMode={isDarkMode} />;\n };\n};\n\nconst BlockquoteRenderer = ({\n className,\n ...props\n}: ComponentProps<'blockquote'>) => (\n <blockquote\n className={cn(\n 'mt-5 gap-3 border-card border-l-4 pl-5 text-neutral [&_strong]:text-neutral',\n className\n )}\n {...props}\n />\n);\n\nconst UlRenderer = ({ className, ...props }: ComponentProps<'ul'>) => (\n <ul\n className={cn(\n 'mt-5 flex list-disc flex-col gap-3 pl-5 marker:text-neutral/80',\n className\n )}\n {...props}\n />\n);\n\nconst OlRenderer = ({ className, ...props }: ComponentProps<'ol'>) => (\n <ol\n className={cn(\n 'mt-5 flex list-decimal flex-col gap-3 pl-5 marker:text-neutral/80',\n className\n )}\n {...props}\n />\n);\n\nconst ImgRenderer = ({\n className,\n alt,\n src,\n ...props\n}: ComponentProps<'img'>) => (\n <img\n {...props}\n alt={alt ?? ''}\n loading=\"lazy\"\n className={cn('max-h-[80vh] max-w-full rounded-md', className)}\n src={\n src?.includes('github.com')\n ? src\n ?.replace('github.com', 'raw.githubusercontent.com')\n .replace('/blob/', '/') // GitHub raw URLs do not use /blob/\n : src\n }\n />\n);\n\nconst createLinkRenderer = (locale?: LocalesValues) => {\n return (props: ComponentProps<'a'>) => (\n <Link\n isExternalLink={props.href?.startsWith('http')}\n underlined\n locale={locale}\n label=\"\"\n color=\"text\"\n {...(props as any)}\n />\n );\n};\n\nconst PreRenderer = (props: ComponentProps<'pre'>) => <>{props.children}</>;\nconst TableRenderer = (props: ComponentProps<typeof SmartTable>) => (\n <SmartTable isRollable displayModal {...props} />\n);\n\nconst TabsRenderer = (props: ComponentProps<typeof Tab>) => (\n <Tab\n {...props}\n className=\"rounded-xl border border-card\"\n headerClassName=\"sticky rounded-xl top-24 z-5 bg-background/70 backdrop-blur overflow-x-auto\"\n />\n);\nconst ColumnsRenderer = ({\n className,\n ...props\n}: ComponentPropsWithoutRef<'div'>) => (\n <div className={cn('flex gap-4 max-md:flex-col', className)} {...props} />\n);\nconst ColumnRenderer = ({\n className,\n ...props\n}: ComponentPropsWithoutRef<'div'>) => (\n <div className={cn('flex-1', className)} {...props} />\n);\n\nconst Iframe = (props: ComponentProps<'iframe'>) => (\n <MarkDownIframe {...props} />\n);\n\n// Static configuration object for static renderers\nconst staticMarkdownComponents = {\n h1: H1Renderer,\n h2: H2Renderer,\n h3: H3Renderer,\n h4: H4Renderer,\n h5: H5Renderer,\n h6: H6Renderer,\n strong: StrongRenderer,\n blockquote: BlockquoteRenderer,\n ul: UlRenderer,\n ol: OlRenderer,\n img: ImgRenderer,\n pre: PreRenderer,\n table: TableRenderer,\n th: Th,\n tr: Tr,\n td: Td,\n hr: Hr,\n Tabs: TabsRenderer,\n Tab: Tab.Item,\n Columns: ColumnsRenderer,\n Column: ColumnRenderer,\n iframe: Iframe,\n};\n\n// Factory function to create components with dynamic props\nconst createMarkdownComponents = (\n isDarkMode?: boolean,\n locale?: LocalesValues\n) => ({\n ...staticMarkdownComponents,\n code: createCodeRenderer(isDarkMode),\n a: createLinkRenderer(locale),\n});\n\n// Export static renderers for backward compatibility\nexport const baseMarkdownComponents = staticMarkdownComponents;\n\ntype MarkdownRendererProps = {\n children: string;\n isDarkMode?: boolean;\n locale?: LocalesValues;\n forceBlock?: boolean;\n preserveFrontmatter?: boolean;\n tagfilter?: boolean;\n components?: ComponentProps<typeof MarkdownRendererIntlayer>['components'];\n wrapper?: ComponentProps<typeof MarkdownRendererIntlayer>['wrapper'];\n};\n\nexport const getIntlayerMarkdownOptions = (_isDarkMode?: boolean) => ({\n components: baseMarkdownComponents,\n});\n\nexport const MarkdownRenderer: FC<MarkdownRendererProps> = ({\n children,\n isDarkMode = false,\n locale,\n forceBlock,\n preserveFrontmatter,\n tagfilter,\n components: componentsProp,\n wrapper,\n}) => {\n const markdownComponents = createMarkdownComponents(isDarkMode, locale);\n\n const markdownContent = renderMarkdown(children, {\n components: {\n ...markdownComponents,\n ...componentsProp,\n },\n wrapper,\n forceBlock,\n preserveFrontmatter,\n tagfilter,\n });\n\n return (\n <CodeProvider>\n <TabProvider>{markdownContent}</TabProvider>\n </CodeProvider>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"MarkDownRender.mjs","names":[],"sources":["../../../../src/components/MarkDownRender/MarkDownRender.tsx"],"sourcesContent":["import type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport { cn } from '@utils/cn';\nimport type { ComponentProps, ComponentPropsWithoutRef, FC } from 'react';\nimport { memo } from 'react';\nimport {\n type MarkdownRenderer as MarkdownRendererIntlayer,\n renderMarkdown,\n} from 'react-intlayer/markdown';\nimport type { BundledLanguage } from 'shiki/bundle/web';\nimport { H1, H2, H3, H4, H5, H6 } from '../Headers';\nimport { Code } from '../IDE/Code';\nimport { CodeProvider } from '../IDE/CodeContext';\nimport { Link } from '../Link';\nimport { Tab } from '../Tab';\nimport { TabProvider } from '../Tab/TabContext';\nimport { Hr, SmartTable, Td, Th, Tr } from '../Table';\nimport { MarkDownIframe } from './MarkDownIframe';\n\n// Extracted, stable component renderers\nconst H1Renderer = (props: ComponentProps<'h1'>) => (\n <H1 isClickable className=\"text-text\" {...props} />\n);\nconst H2Renderer = (props: ComponentProps<'h2'>) => (\n <H2 isClickable className=\"mt-16 text-text\" {...props} />\n);\nconst H3Renderer = (props: ComponentProps<'h3'>) => (\n <H3 isClickable className=\"mt-5 text-text\" {...props} />\n);\nconst H4Renderer = (props: ComponentProps<'h4'>) => (\n <H4 isClickable className=\"mt-3 text-text\" {...props} />\n);\nconst H5Renderer = (props: ComponentProps<'h5'>) => (\n <H5 isClickable className=\"mt-3 text-text\" {...props} />\n);\nconst H6Renderer = (props: ComponentProps<'h6'>) => (\n <H6 isClickable className=\"mt-3 text-text\" {...props} />\n);\nconst StrongRenderer = (props: ComponentProps<'strong'>) => (\n <strong className=\"text-text\" {...props} />\n);\n\nconst MemoizedCodeBlock = memo(\n ({\n className,\n children,\n isDarkMode,\n ...rest\n }: ComponentProps<'code'> & { isDarkMode?: boolean }) => {\n const content = String(children ?? '').replace(/\\n$/, '');\n const isBlock = !!className;\n\n if (!isBlock) {\n const decodedContent = content.replace(\n /&(?:amp;)?#(\\d+);/g,\n (_, code: string) => String.fromCharCode(parseInt(code, 10))\n );\n return (\n <code className=\"rounded-md border border-neutral/30 bg-card/60 box-decoration-clone px-1.5 py-0.5 font-mono text-sm\">\n {decodedContent}\n </code>\n );\n }\n\n const language = (className?.replace(/lang(?:uage)?-/, '') ||\n 'plaintext') as BundledLanguage;\n\n return (\n <Code {...rest} language={language} showHeader isDarkMode={isDarkMode}>\n {content}\n </Code>\n );\n },\n (prevProps, nextProps) =>\n prevProps.children === nextProps.children &&\n prevProps.className === nextProps.className &&\n prevProps.isDarkMode === nextProps.isDarkMode\n);\n\nconst createCodeRenderer = (isDarkMode?: boolean) => {\n return function CodeWrapper(props: ComponentProps<'code'>) {\n return <MemoizedCodeBlock {...props} isDarkMode={isDarkMode} />;\n };\n};\n\nconst BlockquoteRenderer = ({\n className,\n ...props\n}: ComponentProps<'blockquote'>) => (\n <blockquote\n className={cn(\n 'mt-5 gap-3 border-card border-l-4 pl-5 text-neutral [&_strong]:text-neutral',\n className\n )}\n {...props}\n />\n);\n\nconst UlRenderer = ({ className, ...props }: ComponentProps<'ul'>) => (\n <ul\n className={cn(\n 'mt-5 flex list-disc flex-col gap-3 pl-5 marker:text-neutral/80',\n className\n )}\n {...props}\n />\n);\n\nconst OlRenderer = ({ className, ...props }: ComponentProps<'ol'>) => (\n <ol\n className={cn(\n 'mt-5 flex list-decimal flex-col gap-3 pl-5 marker:text-neutral/80',\n className\n )}\n {...props}\n />\n);\n\nconst ImgRenderer = ({\n className,\n alt,\n src,\n ...props\n}: ComponentProps<'img'>) => (\n <img\n {...props}\n alt={alt ?? ''}\n loading=\"lazy\"\n className={cn('max-h-[80vh] max-w-full rounded-md', className)}\n src={\n src?.includes('github.com')\n ? src\n ?.replace('github.com', 'raw.githubusercontent.com')\n .replace('/blob/', '/') // GitHub raw URLs do not use /blob/\n : src\n }\n />\n);\n\nconst createLinkRenderer = (locale?: LocalesValues) => {\n return (props: ComponentProps<'a'>) => (\n <Link\n isExternalLink={props.href?.startsWith('http')}\n underlined\n locale={locale}\n label=\"\"\n color=\"text\"\n {...(props as any)}\n />\n );\n};\n\nconst PreRenderer = (props: ComponentProps<'pre'>) => <>{props.children}</>;\nconst TableRenderer = (props: ComponentProps<typeof SmartTable>) => (\n <SmartTable isRollable displayModal {...props} />\n);\n\nconst TabsRenderer = (props: ComponentProps<typeof Tab>) => (\n <Tab\n {...props}\n className=\"rounded-xl border border-card\"\n headerClassName=\"sticky rounded-xl top-24 z-5 bg-background/70 backdrop-blur overflow-x-auto\"\n />\n);\nconst ColumnsRenderer = ({\n className,\n ...props\n}: ComponentPropsWithoutRef<'div'>) => (\n <div className={cn('flex gap-4 max-md:flex-col', className)} {...props} />\n);\nconst ColumnRenderer = ({\n className,\n ...props\n}: ComponentPropsWithoutRef<'div'>) => (\n <div className={cn('flex-1', className)} {...props} />\n);\n\nconst Iframe = (props: ComponentProps<'iframe'>) => (\n <MarkDownIframe {...props} />\n);\n\n// Static configuration object for static renderers\nconst staticMarkdownComponents = {\n h1: H1Renderer,\n h2: H2Renderer,\n h3: H3Renderer,\n h4: H4Renderer,\n h5: H5Renderer,\n h6: H6Renderer,\n strong: StrongRenderer,\n blockquote: BlockquoteRenderer,\n ul: UlRenderer,\n ol: OlRenderer,\n img: ImgRenderer,\n pre: PreRenderer,\n table: TableRenderer,\n th: Th,\n tr: Tr,\n td: Td,\n hr: Hr,\n Tabs: TabsRenderer,\n Tab: Tab.Item,\n Columns: ColumnsRenderer,\n Column: ColumnRenderer,\n iframe: Iframe,\n};\n\n// Factory function to create components with dynamic props\nconst createMarkdownComponents = (\n isDarkMode?: boolean,\n locale?: LocalesValues\n) => ({\n ...staticMarkdownComponents,\n code: createCodeRenderer(isDarkMode),\n a: createLinkRenderer(locale),\n});\n\n// Export static renderers for backward compatibility\nexport const baseMarkdownComponents = staticMarkdownComponents;\n\ntype MarkdownRendererProps = {\n children: string;\n isDarkMode?: boolean;\n locale?: LocalesValues;\n forceBlock?: boolean;\n preserveFrontmatter?: boolean;\n tagfilter?: boolean;\n components?: ComponentProps<typeof MarkdownRendererIntlayer>['components'];\n wrapper?: ComponentProps<typeof MarkdownRendererIntlayer>['wrapper'];\n};\n\nexport const getIntlayerMarkdownOptions = (_isDarkMode?: boolean) => ({\n components: baseMarkdownComponents,\n});\n\nexport const MarkdownRenderer: FC<MarkdownRendererProps> = ({\n children,\n isDarkMode = false,\n locale,\n forceBlock,\n preserveFrontmatter,\n tagfilter,\n components: componentsProp,\n wrapper,\n}) => {\n const markdownComponents = createMarkdownComponents(isDarkMode, locale);\n\n const markdownContent = renderMarkdown(children, {\n components: {\n ...markdownComponents,\n ...componentsProp,\n },\n wrapper,\n forceBlock,\n preserveFrontmatter,\n tagfilter,\n });\n\n return (\n <CodeProvider>\n <TabProvider>{markdownContent}</TabProvider>\n </CodeProvider>\n );\n};\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { MarkDownIframe } from "./MarkDownIframe.mjs";
1
2
  import { MarkdownRenderer, baseMarkdownComponents, getIntlayerMarkdownOptions } from "./MarkDownRender.mjs";
2
3
 
3
- export { MarkdownRenderer, baseMarkdownComponents, getIntlayerMarkdownOptions };
4
+ export { MarkDownIframe, MarkdownRenderer, baseMarkdownComponents, getIntlayerMarkdownOptions };
@@ -130,10 +130,13 @@ const Pagination = ({ currentPage, totalPages, onPageChange, showFirstLast = fal
130
130
  /* @__PURE__ */ jsx("div", {
131
131
  className: "flex items-center gap-1 max-md:gap-0.5",
132
132
  children: pageNumbers.map((page, index) => {
133
- if (page === "ellipsis") return /* @__PURE__ */ jsx("div", {
134
- className: "flex h-8 min-w-8 items-center justify-center px-1",
135
- children: /* @__PURE__ */ jsx(MoreHorizontal, { className: "h-4 w-4 text-muted-foreground" })
136
- }, `ellipsis-${page}-${index}`);
133
+ if (page === "ellipsis") {
134
+ const ellipsisKey = index === pageNumbers.indexOf("ellipsis") ? "ellipsis-start" : "ellipsis-end";
135
+ return /* @__PURE__ */ jsx("div", {
136
+ className: "flex h-8 min-w-8 items-center justify-center px-1",
137
+ children: /* @__PURE__ */ jsx(MoreHorizontal, { className: "h-4 w-4 text-muted-foreground" })
138
+ }, ellipsisKey);
139
+ }
137
140
  const isActive = page === currentPage;
138
141
  const refIndex = (showPrevNext ? 1 : 0) + pageNumbers.slice(0, index).filter((p) => p !== "ellipsis").length;
139
142
  return /* @__PURE__ */ jsx(Button, {
@@ -147,7 +150,7 @@ const Pagination = ({ currentPage, totalPages, onPageChange, showFirstLast = fal
147
150
  ref: (el) => {
148
151
  if (el) optionsRefs.current[refIndex] = el;
149
152
  },
150
- className: cn("flex aspect-square h-8 w-8 min-w-0 items-center justify-center p-0 text-sm", size === "sm" && "h-6 w-6 text-xs", size === "lg" && "h-10 w-10 text-base", isActive && "font-semibold"),
153
+ className: cn("flex aspect-square h-8 w-8 min-w-0 items-center justify-center p-0 text-sm", size === "sm" && "h-6 w-6 text-xs", size === "lg" && "size-10 text-base", isActive && "font-semibold"),
151
154
  children: page
152
155
  }, page);
153
156
  })
@@ -1 +1 @@
1
- {"version":3,"file":"Pagination.mjs","names":[],"sources":["../../../../src/components/Pagination/Pagination.tsx"],"sourcesContent":["'use client';\n\nimport { useItemSelector } from '@hooks/useItemSelector';\nimport { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { ChevronLeft, ChevronRight, MoreHorizontal } from 'lucide-react';\nimport {\n type ComponentProps,\n type FC,\n type HTMLAttributes,\n useEffect,\n useRef,\n} from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport { Button, ButtonColor, ButtonSize, ButtonVariant } from '../Button';\n\nexport const paginationVariants = cva(\n 'flex items-center justify-center gap-1',\n {\n variants: {\n size: {\n sm: 'gap-1',\n md: 'gap-2',\n lg: 'gap-3',\n },\n color: {\n text: 'background-text',\n primary: 'background-primary',\n secondary: 'background-secondary',\n neutral: 'background-neutral',\n destructive: 'background-destructive',\n },\n variant: {\n default: '',\n bordered: 'rounded-lg border border-border p-2',\n ghost: 'bg-transparent',\n },\n },\n defaultVariants: {\n size: 'md',\n variant: 'default',\n },\n }\n);\n\nexport enum PaginationSize {\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n}\n\nexport enum PaginationVariant {\n DEFAULT = 'default',\n BORDERED = 'bordered',\n GHOST = 'ghost',\n}\n\nexport type PaginationProps = HTMLAttributes<HTMLDivElement> &\n VariantProps<typeof paginationVariants> & {\n currentPage: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n showFirstLast?: boolean;\n showPrevNext?: boolean;\n maxVisiblePages?: number;\n disabled?: boolean;\n };\n\nconst generatePageNumbers = (\n currentPage: number,\n totalPages: number,\n maxVisiblePages: number\n): (number | 'ellipsis')[] => {\n if (totalPages <= maxVisiblePages) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n\n const pages: (number | 'ellipsis')[] = [];\n const halfVisible = Math.floor(maxVisiblePages / 2);\n\n pages.push(1);\n\n if (currentPage <= halfVisible + 2) {\n for (let i = 2; i <= Math.min(maxVisiblePages - 1, totalPages - 1); i++) {\n pages.push(i);\n }\n if (totalPages > maxVisiblePages) {\n pages.push('ellipsis');\n }\n if (totalPages > 1) {\n pages.push(totalPages);\n }\n } else if (currentPage >= totalPages - halfVisible - 1) {\n if (totalPages > maxVisiblePages) {\n pages.push('ellipsis');\n }\n for (\n let i = Math.max(2, totalPages - maxVisiblePages + 2);\n i <= totalPages;\n i++\n ) {\n pages.push(i);\n }\n } else {\n pages.push('ellipsis');\n const start = currentPage - halfVisible;\n const end = currentPage + halfVisible;\n for (let i = start; i <= end; i++) {\n pages.push(i);\n }\n pages.push('ellipsis');\n pages.push(totalPages);\n }\n\n return pages;\n};\n\nconst selector = (option: HTMLElement) =>\n option?.getAttribute('aria-current') === 'true';\n\nconst getButtonSize = (size?: PaginationSize | `${PaginationSize}` | null) => {\n if (size === PaginationSize.SM) {\n return ButtonSize.ICON_SM;\n } else if (size === PaginationSize.LG) {\n return ButtonSize.ICON_LG;\n } else {\n return ButtonSize.ICON_MD;\n }\n};\n\nconst InputIndicator: FC<ComponentProps<'div'>> = (props) => (\n <div\n className=\"absolute top-0 z-0 h-full w-auto rounded-xl bg-text/20 ring-4 ring-text/10 transition-[left,width] duration-300 ease-in-out [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl motion-reduce:transition-none\"\n {...props}\n />\n);\n\nexport const Pagination: FC<PaginationProps> = ({\n currentPage,\n totalPages,\n onPageChange,\n showFirstLast = false,\n showPrevNext = true,\n maxVisiblePages = 5,\n disabled = false,\n size = PaginationSize.MD,\n variant = PaginationVariant.DEFAULT,\n color = ButtonColor.TEXT,\n className,\n ...props\n}) => {\n const { goToNextPage, goToPreviousPage } = useIntlayer('pagination');\n\n const pageNumbers = generatePageNumbers(\n currentPage,\n totalPages,\n maxVisiblePages\n );\n\n const buttonSize = getButtonSize(size);\n const isFirstPage = currentPage === 1;\n const isLastPage = currentPage === totalPages;\n\n const optionsRefs = useRef<HTMLElement[]>([]);\n const indicatorRef = useRef<HTMLDivElement | null>(null);\n const { choiceIndicatorPosition, calculatePosition } = useItemSelector(\n optionsRefs,\n {\n selector,\n isHoverable: true,\n }\n );\n\n useEffect(() => {\n const timer = setTimeout(() => {\n calculatePosition();\n }, 300);\n\n return () => clearTimeout(timer);\n }, [currentPage, calculatePosition]);\n\n if (totalPages <= 1) return null;\n\n const handlePageChange = (page: number) => {\n if (!disabled && page >= 1 && page <= totalPages && page !== currentPage) {\n onPageChange(page);\n }\n };\n\n return (\n <div\n className={cn(paginationVariants({ size, variant }), className)}\n {...props}\n >\n <div className=\"relative flex items-center gap-1\">\n {choiceIndicatorPosition && (\n <InputIndicator style={choiceIndicatorPosition} ref={indicatorRef} />\n )}\n\n {showPrevNext && (\n <Button\n variant={ButtonVariant.OUTLINE}\n size={buttonSize}\n color={ButtonColor.TEXT}\n onClick={() => handlePageChange(currentPage - 1)}\n disabled={disabled || isFirstPage}\n label={goToPreviousPage.value}\n Icon={ChevronLeft}\n ref={(el) => {\n if (el) optionsRefs.current[0] = el;\n }}\n className=\"min-w-0 px-2\"\n />\n )}\n\n <div className=\"flex items-center gap-1 max-md:gap-0.5\">\n {pageNumbers.map((page, index) => {\n if (page === 'ellipsis') {\n return (\n <div\n key={`ellipsis-${page}-${index}`}\n className=\"flex h-8 min-w-8 items-center justify-center px-1\"\n >\n <MoreHorizontal className=\"h-4 w-4 text-muted-foreground\" />\n </div>\n );\n }\n\n const isActive = page === currentPage;\n // Calculate ref index: offset by 1 if showPrevNext, then count only non-ellipsis items\n const refIndex =\n (showPrevNext ? 1 : 0) +\n pageNumbers.slice(0, index).filter((p) => p !== 'ellipsis')\n .length;\n\n return (\n <Button\n key={page}\n variant={\n isActive ? ButtonVariant.DEFAULT : ButtonVariant.OUTLINE\n }\n size={buttonSize}\n color={ButtonColor.TEXT}\n onClick={() => handlePageChange(page)}\n disabled={disabled}\n label={`Go to page ${page}`}\n aria-current={isActive ? 'true' : 'false'}\n ref={(el) => {\n if (el) optionsRefs.current[refIndex] = el;\n }}\n className={cn(\n 'flex aspect-square h-8 w-8 min-w-0 items-center justify-center p-0 text-sm',\n size === 'sm' && 'h-6 w-6 text-xs',\n size === 'lg' && 'h-10 w-10 text-base',\n isActive && 'font-semibold'\n )}\n >\n {page}\n </Button>\n );\n })}\n </div>\n\n {showPrevNext && (\n <Button\n variant={ButtonVariant.OUTLINE}\n size={buttonSize}\n color={ButtonColor.TEXT}\n onClick={() => handlePageChange(currentPage + 1)}\n disabled={disabled || isLastPage}\n label={goToNextPage.value}\n Icon={ChevronRight}\n ref={(el) => {\n const lastRefIndex =\n (showPrevNext ? 1 : 0) +\n pageNumbers.filter((p) => p !== 'ellipsis').length;\n if (el) optionsRefs.current[lastRefIndex] = el;\n }}\n className=\"min-w-0 px-2\"\n />\n )}\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"Pagination.mjs","names":[],"sources":["../../../../src/components/Pagination/Pagination.tsx"],"sourcesContent":["'use client';\n\nimport { useItemSelector } from '@hooks/useItemSelector';\nimport { cn } from '@utils/cn';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { ChevronLeft, ChevronRight, MoreHorizontal } from 'lucide-react';\nimport {\n type ComponentProps,\n type FC,\n type HTMLAttributes,\n useEffect,\n useRef,\n} from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport { Button, ButtonColor, ButtonSize, ButtonVariant } from '../Button';\n\nexport const paginationVariants = cva(\n 'flex items-center justify-center gap-1',\n {\n variants: {\n size: {\n sm: 'gap-1',\n md: 'gap-2',\n lg: 'gap-3',\n },\n color: {\n text: 'background-text',\n primary: 'background-primary',\n secondary: 'background-secondary',\n neutral: 'background-neutral',\n destructive: 'background-destructive',\n },\n variant: {\n default: '',\n bordered: 'rounded-lg border border-border p-2',\n ghost: 'bg-transparent',\n },\n },\n defaultVariants: {\n size: 'md',\n variant: 'default',\n },\n }\n);\n\nexport enum PaginationSize {\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n}\n\nexport enum PaginationVariant {\n DEFAULT = 'default',\n BORDERED = 'bordered',\n GHOST = 'ghost',\n}\n\nexport type PaginationProps = HTMLAttributes<HTMLDivElement> &\n VariantProps<typeof paginationVariants> & {\n currentPage: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n showFirstLast?: boolean;\n showPrevNext?: boolean;\n maxVisiblePages?: number;\n disabled?: boolean;\n };\n\nconst generatePageNumbers = (\n currentPage: number,\n totalPages: number,\n maxVisiblePages: number\n): (number | 'ellipsis')[] => {\n if (totalPages <= maxVisiblePages) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n\n const pages: (number | 'ellipsis')[] = [];\n const halfVisible = Math.floor(maxVisiblePages / 2);\n\n pages.push(1);\n\n if (currentPage <= halfVisible + 2) {\n for (let i = 2; i <= Math.min(maxVisiblePages - 1, totalPages - 1); i++) {\n pages.push(i);\n }\n if (totalPages > maxVisiblePages) {\n pages.push('ellipsis');\n }\n if (totalPages > 1) {\n pages.push(totalPages);\n }\n } else if (currentPage >= totalPages - halfVisible - 1) {\n if (totalPages > maxVisiblePages) {\n pages.push('ellipsis');\n }\n for (\n let i = Math.max(2, totalPages - maxVisiblePages + 2);\n i <= totalPages;\n i++\n ) {\n pages.push(i);\n }\n } else {\n pages.push('ellipsis');\n const start = currentPage - halfVisible;\n const end = currentPage + halfVisible;\n for (let i = start; i <= end; i++) {\n pages.push(i);\n }\n pages.push('ellipsis');\n pages.push(totalPages);\n }\n\n return pages;\n};\n\nconst selector = (option: HTMLElement) =>\n option?.getAttribute('aria-current') === 'true';\n\nconst getButtonSize = (size?: PaginationSize | `${PaginationSize}` | null) => {\n if (size === PaginationSize.SM) {\n return ButtonSize.ICON_SM;\n } else if (size === PaginationSize.LG) {\n return ButtonSize.ICON_LG;\n } else {\n return ButtonSize.ICON_MD;\n }\n};\n\nconst InputIndicator: FC<ComponentProps<'div'>> = (props) => (\n <div\n className=\"absolute top-0 z-0 h-full w-auto rounded-xl bg-text/20 ring-4 ring-text/10 transition-[left,width] duration-300 ease-in-out [corner-shape:squircle] supports-[corner-shape:squircle]:rounded-2xl motion-reduce:transition-none\"\n {...props}\n />\n);\n\nexport const Pagination: FC<PaginationProps> = ({\n currentPage,\n totalPages,\n onPageChange,\n showFirstLast = false,\n showPrevNext = true,\n maxVisiblePages = 5,\n disabled = false,\n size = PaginationSize.MD,\n variant = PaginationVariant.DEFAULT,\n color = ButtonColor.TEXT,\n className,\n ...props\n}) => {\n const { goToNextPage, goToPreviousPage } = useIntlayer('pagination');\n\n const pageNumbers = generatePageNumbers(\n currentPage,\n totalPages,\n maxVisiblePages\n );\n\n const buttonSize = getButtonSize(size);\n const isFirstPage = currentPage === 1;\n const isLastPage = currentPage === totalPages;\n\n const optionsRefs = useRef<HTMLElement[]>([]);\n const indicatorRef = useRef<HTMLDivElement | null>(null);\n const { choiceIndicatorPosition, calculatePosition } = useItemSelector(\n optionsRefs,\n {\n selector,\n isHoverable: true,\n }\n );\n\n useEffect(() => {\n const timer = setTimeout(() => {\n calculatePosition();\n }, 300);\n\n return () => clearTimeout(timer);\n }, [currentPage, calculatePosition]);\n\n if (totalPages <= 1) return null;\n\n const handlePageChange = (page: number) => {\n if (!disabled && page >= 1 && page <= totalPages && page !== currentPage) {\n onPageChange(page);\n }\n };\n\n return (\n <div\n className={cn(paginationVariants({ size, variant }), className)}\n {...props}\n >\n <div className=\"relative flex items-center gap-1\">\n {choiceIndicatorPosition && (\n <InputIndicator style={choiceIndicatorPosition} ref={indicatorRef} />\n )}\n\n {showPrevNext && (\n <Button\n variant={ButtonVariant.OUTLINE}\n size={buttonSize}\n color={ButtonColor.TEXT}\n onClick={() => handlePageChange(currentPage - 1)}\n disabled={disabled || isFirstPage}\n label={goToPreviousPage.value}\n Icon={ChevronLeft}\n ref={(el) => {\n if (el) optionsRefs.current[0] = el;\n }}\n className=\"min-w-0 px-2\"\n />\n )}\n\n <div className=\"flex items-center gap-1 max-md:gap-0.5\">\n {pageNumbers.map((page, index) => {\n if (page === 'ellipsis') {\n const isFirstEllipsis = index === pageNumbers.indexOf('ellipsis');\n const ellipsisKey = isFirstEllipsis\n ? 'ellipsis-start'\n : 'ellipsis-end';\n return (\n <div\n key={ellipsisKey}\n className=\"flex h-8 min-w-8 items-center justify-center px-1\"\n >\n <MoreHorizontal className=\"h-4 w-4 text-muted-foreground\" />\n </div>\n );\n }\n\n const isActive = page === currentPage;\n // Calculate ref index: offset by 1 if showPrevNext, then count only non-ellipsis items\n const refIndex =\n (showPrevNext ? 1 : 0) +\n pageNumbers.slice(0, index).filter((p) => p !== 'ellipsis')\n .length;\n\n return (\n <Button\n key={page}\n variant={\n isActive ? ButtonVariant.DEFAULT : ButtonVariant.OUTLINE\n }\n size={buttonSize}\n color={ButtonColor.TEXT}\n onClick={() => handlePageChange(page)}\n disabled={disabled}\n label={`Go to page ${page}`}\n aria-current={isActive ? 'true' : 'false'}\n ref={(el) => {\n if (el) optionsRefs.current[refIndex] = el;\n }}\n className={cn(\n 'flex aspect-square h-8 w-8 min-w-0 items-center justify-center p-0 text-sm',\n size === 'sm' && 'h-6 w-6 text-xs',\n size === 'lg' && 'size-10 text-base',\n isActive && 'font-semibold'\n )}\n >\n {page}\n </Button>\n );\n })}\n </div>\n\n {showPrevNext && (\n <Button\n variant={ButtonVariant.OUTLINE}\n size={buttonSize}\n color={ButtonColor.TEXT}\n onClick={() => handlePageChange(currentPage + 1)}\n disabled={disabled || isLastPage}\n label={goToNextPage.value}\n Icon={ChevronRight}\n ref={(el) => {\n const lastRefIndex =\n (showPrevNext ? 1 : 0) +\n pageNumbers.filter((p) => p !== 'ellipsis').length;\n if (el) optionsRefs.current[lastRefIndex] = el;\n }}\n className=\"min-w-0 px-2\"\n />\n )}\n </div>\n </div>\n );\n};\n"],"mappings":"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"}