@lobehub/ui 5.24.0 → 5.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/es/A/index.mjs +2 -1
  2. package/es/A/index.mjs.map +1 -1
  3. package/es/Accordion/AccordionItem.mjs +0 -1
  4. package/es/Accordion/AccordionItem.mjs.map +1 -1
  5. package/es/ActionIcon/components/utils.mjs +7 -9
  6. package/es/ActionIcon/components/utils.mjs.map +1 -1
  7. package/es/Checkbox/CheckboxGroup.mjs +4 -2
  8. package/es/Checkbox/CheckboxGroup.mjs.map +1 -1
  9. package/es/CodeDiff/CodeDiff.mjs +20 -18
  10. package/es/CodeDiff/CodeDiff.mjs.map +1 -1
  11. package/es/CodeDiff/PatchDiff.mjs +18 -16
  12. package/es/CodeDiff/PatchDiff.mjs.map +1 -1
  13. package/es/CopyButton/CopyButton.mjs +2 -1
  14. package/es/CopyButton/CopyButton.mjs.map +1 -1
  15. package/es/Highlighter/LangSelect.mjs +41 -40
  16. package/es/Highlighter/LangSelect.mjs.map +1 -1
  17. package/es/Highlighter/SyntaxHighlighter/StaticRenderer.mjs +2 -1
  18. package/es/Highlighter/SyntaxHighlighter/StaticRenderer.mjs.map +1 -1
  19. package/es/HotkeyInput/HotkeyInput.mjs +3 -1
  20. package/es/HotkeyInput/HotkeyInput.mjs.map +1 -1
  21. package/es/HtmlPreview/const.mjs +1 -1
  22. package/es/HtmlPreview/const.mjs.map +1 -1
  23. package/es/Icon/components/utils.mjs +7 -9
  24. package/es/Icon/components/utils.mjs.map +1 -1
  25. package/es/Image/components/Toolbar.mjs +2 -1
  26. package/es/Image/components/Toolbar.mjs.map +1 -1
  27. package/es/Img/index.mjs +2 -1
  28. package/es/Img/index.mjs.map +1 -1
  29. package/es/Markdown/SyntaxMarkdown/StreamdownRender.mjs +2 -1
  30. package/es/Markdown/SyntaxMarkdown/StreamdownRender.mjs.map +1 -1
  31. package/es/Markdown/SyntaxMarkdown/useSmoothStreamContent.mjs +2 -2
  32. package/es/Markdown/SyntaxMarkdown/useSmoothStreamContent.mjs.map +1 -1
  33. package/es/Modal/RawModalStackItem.mjs +6 -5
  34. package/es/Modal/RawModalStackItem.mjs.map +1 -1
  35. package/es/Modal/imperative.mjs +4 -2
  36. package/es/Modal/imperative.mjs.map +1 -1
  37. package/es/NeuralNetworkLoading/NeuralNetworkLoading.mjs +1 -1
  38. package/es/NeuralNetworkLoading/NeuralNetworkLoading.mjs.map +1 -1
  39. package/es/ScrollShadow/ScrollShadow.mjs +13 -12
  40. package/es/ScrollShadow/ScrollShadow.mjs.map +1 -1
  41. package/es/Skeleton/SkeletonButton.mjs +2 -1
  42. package/es/Skeleton/SkeletonButton.mjs.map +1 -1
  43. package/es/SortableList/SortableList.mjs +5 -1
  44. package/es/SortableList/SortableList.mjs.map +1 -1
  45. package/es/Text/Text.mjs +22 -21
  46. package/es/Text/Text.mjs.map +1 -1
  47. package/es/ThemeProvider/ThemeProvider.mjs +3 -2
  48. package/es/ThemeProvider/ThemeProvider.mjs.map +1 -1
  49. package/es/awesome/GradientButton/GradientButton.mjs +1 -3
  50. package/es/awesome/GradientButton/GradientButton.mjs.map +1 -1
  51. package/es/awesome/Spotlight/Spotlight.mjs +2 -1
  52. package/es/awesome/Spotlight/Spotlight.mjs.map +1 -1
  53. package/es/base-ui/Button/Button.mjs +13 -11
  54. package/es/base-ui/Button/Button.mjs.map +1 -1
  55. package/es/base-ui/Button/SplitButton.mjs +2 -1
  56. package/es/base-ui/Button/SplitButton.mjs.map +1 -1
  57. package/es/base-ui/ContextMenu/ContextMenuTrigger.mjs +2 -1
  58. package/es/base-ui/ContextMenu/ContextMenuTrigger.mjs.map +1 -1
  59. package/es/base-ui/ContextMenu/renderItems.mjs +2 -1
  60. package/es/base-ui/ContextMenu/renderItems.mjs.map +1 -1
  61. package/es/base-ui/Drawer/Drawer.d.mts +6 -0
  62. package/es/base-ui/Drawer/Drawer.mjs +152 -0
  63. package/es/base-ui/Drawer/Drawer.mjs.map +1 -0
  64. package/es/base-ui/Drawer/DrawerLayerContext.mjs +10 -0
  65. package/es/base-ui/Drawer/DrawerLayerContext.mjs.map +1 -0
  66. package/es/base-ui/Drawer/DrawerPushContext.mjs +27 -0
  67. package/es/base-ui/Drawer/DrawerPushContext.mjs.map +1 -0
  68. package/es/base-ui/Drawer/atoms.d.mts +58 -0
  69. package/es/base-ui/Drawer/atoms.mjs +262 -0
  70. package/es/base-ui/Drawer/atoms.mjs.map +1 -0
  71. package/es/base-ui/Drawer/constants.d.mts +17 -0
  72. package/es/base-ui/Drawer/constants.mjs +72 -0
  73. package/es/base-ui/Drawer/constants.mjs.map +1 -0
  74. package/es/base-ui/Drawer/index.d.mts +5 -0
  75. package/es/base-ui/Drawer/style.mjs +295 -0
  76. package/es/base-ui/Drawer/style.mjs.map +1 -0
  77. package/es/base-ui/Drawer/type.d.mts +65 -0
  78. package/es/base-ui/DropdownMenu/DropdownMenu.mjs +2 -1
  79. package/es/base-ui/DropdownMenu/DropdownMenu.mjs.map +1 -1
  80. package/es/base-ui/DropdownMenu/atoms.mjs +2 -1
  81. package/es/base-ui/DropdownMenu/atoms.mjs.map +1 -1
  82. package/es/base-ui/DropdownMenu/renderItems.mjs +2 -1
  83. package/es/base-ui/DropdownMenu/renderItems.mjs.map +1 -1
  84. package/es/base-ui/FloatingSheet/FloatingSheet.mjs +4 -1
  85. package/es/base-ui/FloatingSheet/FloatingSheet.mjs.map +1 -1
  86. package/es/base-ui/Input/style.d.mts +1 -1
  87. package/es/base-ui/Modal/atoms.mjs +7 -5
  88. package/es/base-ui/Modal/atoms.mjs.map +1 -1
  89. package/es/base-ui/Modal/imperative.mjs +2 -1
  90. package/es/base-ui/Modal/imperative.mjs.map +1 -1
  91. package/es/base-ui/Popover/atoms.mjs +2 -1
  92. package/es/base-ui/Popover/atoms.mjs.map +1 -1
  93. package/es/base-ui/Popover/context.mjs +4 -2
  94. package/es/base-ui/Popover/context.mjs.map +1 -1
  95. package/es/base-ui/Select/atoms.mjs +2 -1
  96. package/es/base-ui/Select/atoms.mjs.map +1 -1
  97. package/es/base-ui/index.d.mts +6 -1
  98. package/es/base-ui/index.mjs +4 -1
  99. package/es/brand/LobeChat/index.mjs +0 -1
  100. package/es/brand/LobeChat/index.mjs.map +1 -1
  101. package/es/brand/LobeHub/index.mjs +0 -1
  102. package/es/brand/LobeHub/index.mjs.map +1 -1
  103. package/es/brand/Logo3d/index.mjs +2 -1
  104. package/es/brand/Logo3d/index.mjs.map +1 -1
  105. package/es/chat/ChatItem/components/Actions.mjs +5 -4
  106. package/es/chat/ChatItem/components/Actions.mjs.map +1 -1
  107. package/es/chat/ChatList/ChatList.mjs +2 -1
  108. package/es/chat/ChatList/ChatList.mjs.map +1 -1
  109. package/es/color/ColorScales/ScaleRow.mjs +0 -2
  110. package/es/color/ColorScales/ScaleRow.mjs.map +1 -1
  111. package/es/hooks/useMermaid.mjs +2 -1
  112. package/es/hooks/useMermaid.mjs.map +1 -1
  113. package/package.json +1 -1
package/es/A/index.mjs CHANGED
@@ -6,7 +6,8 @@ import { jsx } from "react/jsx-runtime";
6
6
  const createContainer = (as) => memo((props) => createElement(as, props));
7
7
  const A = (props) => {
8
8
  const render = use(ConfigContext)?.aAs || "a";
9
- return /* @__PURE__ */ jsx(useMemo(() => createContainer(render), [render]), { ...props });
9
+ const AContainer = useMemo(() => createContainer(render), [render]);
10
+ return /* @__PURE__ */ jsx(AContainer, { ...props });
10
11
  };
11
12
  A.displayName = "A";
12
13
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/A/index.tsx"],"sourcesContent":["'use client';\n\nimport { createElement, type ElementType, type FC, memo, type Ref, use, useMemo } from 'react';\n\nimport { ConfigContext } from '@/ConfigProvider';\nimport { type AProps } from '@/types';\n\nconst createContainer = (as: ElementType) => memo((props: any) => createElement(as, props));\n\nconst A: FC<AProps & { ref?: Ref<HTMLAnchorElement> }> = (props) => {\n const config = use(ConfigContext);\n const render = config?.aAs || 'a';\n\n const AContainer = useMemo(() => createContainer(render), [render]);\n\n return <AContainer {...props} />;\n};\n\nA.displayName = 'A';\n\nexport default A;\n"],"mappings":";;;;;AAOA,MAAM,mBAAmB,OAAoB,MAAM,UAAe,cAAc,IAAI,KAAK,CAAC;AAE1F,MAAM,KAAoD,UAAU;CAElE,MAAM,SADS,IAAI,aACC,CAAC,EAAE,OAAO;CAI9B,OAAO,oBAFY,cAAc,gBAAgB,MAAM,GAAG,CAAC,MAAM,CAEhD,GAAV,EAAY,GAAI,MAAQ,CAAA;AACjC;AAEA,EAAE,cAAc"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/A/index.tsx"],"sourcesContent":["'use client';\n\nimport { createElement, type ElementType, type FC, memo, type Ref, use, useMemo } from 'react';\n\nimport { ConfigContext } from '@/ConfigProvider';\nimport { type AProps } from '@/types';\n\nconst createContainer = (as: ElementType) => memo((props: any) => createElement(as, props));\n\nconst A: FC<AProps & { ref?: Ref<HTMLAnchorElement> }> = (props) => {\n const config = use(ConfigContext);\n const render = config?.aAs || 'a';\n\n const AContainer = useMemo(() => createContainer(render), [render]);\n\n return <AContainer {...props} />;\n};\n\nA.displayName = 'A';\n\nexport default A;\n"],"mappings":";;;;;AAOA,MAAM,mBAAmB,OAAoB,MAAM,UAAe,cAAc,IAAI,KAAK,CAAC;AAE1F,MAAM,KAAoD,UAAU;CAElE,MAAM,SADS,IAAI,aACC,CAAC,EAAE,OAAO;CAE9B,MAAM,aAAa,cAAc,gBAAgB,MAAM,GAAG,CAAC,MAAM,CAAC;CAElE,OAAO,oBAAC,YAAD,EAAY,GAAI,MAAQ,CAAA;AACjC;AAEA,EAAE,cAAc"}
@@ -169,7 +169,6 @@ const AccordionItem = memo(({ itemKey, title, children, action, alwaysShowAction
169
169
  case " ":
170
170
  e.preventDefault();
171
171
  handleToggle();
172
- break;
173
172
  }
174
173
  }, [
175
174
  allowExpand,
@@ -1 +1 @@
1
- {"version":3,"file":"AccordionItem.mjs","names":["Flexbox"],"sources":["../../src/Accordion/AccordionItem.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\nimport { AnimatePresence } from 'motion/react';\nimport {\n type ComponentPropsWithoutRef,\n type CSSProperties,\n type KeyboardEvent,\n memo,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n} from 'react';\nimport useMergeState from 'use-merge-value';\n\nimport Block from '@/Block';\nimport { Flexbox } from '@/Flex';\nimport { type MotionComponentType, useMotionComponent } from '@/MotionProvider';\nimport Text from '@/Text';\nimport { stopPropagation } from '@/utils/dom';\n\nimport ArrowIcon from './ArrowIcon';\nimport { useAccordionConfig, useAccordionItemState } from './context';\nimport { styles } from './style';\nimport { type AccordionItemProps } from './type';\n\ntype AccordionContentBaseProps = {\n children?: ReactNode;\n className?: string;\n contentInnerClassName: string;\n style?: CSSProperties;\n};\n\ntype AccordionStaticContentProps = AccordionContentBaseProps & {\n isOpen: boolean;\n keepContentMounted: boolean;\n};\n\ntype MotionDivProps = ComponentPropsWithoutRef<MotionComponentType['div']>;\n\ntype AccordionMotionContentProps = AccordionContentBaseProps & {\n contextMotionProps?: MotionDivProps;\n isOpen: boolean;\n skipInitialAnimation: boolean;\n};\n\ntype AccordionItemContentProps = AccordionContentBaseProps & {\n contextMotionProps?: MotionDivProps;\n disableAnimation: boolean;\n isOpen: boolean;\n keepContentMounted: boolean;\n skipInitialAnimation: boolean;\n};\n\nconst motionContainerStyle: CSSProperties = { overflow: 'hidden' };\n\nconst AccordionStaticContent = memo<AccordionStaticContentProps>(\n ({ className, style, children, contentInnerClassName, isOpen, keepContentMounted }) => {\n if (keepContentMounted) {\n return (\n <div\n className={className}\n role=\"region\"\n style={{\n display: isOpen ? 'block' : 'none',\n ...style,\n }}\n >\n <div className={contentInnerClassName}>{children}</div>\n </div>\n );\n }\n\n if (!isOpen) return null;\n\n return (\n <div className={className} role=\"region\" style={style}>\n <div className={contentInnerClassName}>{children}</div>\n </div>\n );\n },\n);\n\nAccordionStaticContent.displayName = 'AccordionStaticContent';\n\nconst AccordionMotionContent = memo<AccordionMotionContentProps>(\n ({\n contextMotionProps,\n className,\n style,\n children,\n contentInnerClassName,\n isOpen,\n skipInitialAnimation,\n }) => {\n const Motion = useMotionComponent();\n\n const motionProps = useMemo(\n () => ({\n animate: 'enter',\n exit: 'exit',\n initial: skipInitialAnimation ? false : 'exit',\n variants: {\n enter: {\n height: 'auto',\n opacity: 1,\n transition: {\n duration: 0.2,\n ease: [0.4, 0, 0.2, 1],\n },\n },\n exit: {\n height: 0,\n opacity: 0,\n transition: {\n duration: 0.2,\n ease: [0.4, 0, 0.2, 1],\n },\n },\n },\n ...contextMotionProps,\n }),\n [contextMotionProps, skipInitialAnimation],\n );\n\n return (\n <AnimatePresence initial={false}>\n {isOpen ? (\n <Motion.div {...(motionProps as any)} style={motionContainerStyle}>\n <div className={className} role=\"region\" style={style}>\n <div className={contentInnerClassName}>{children}</div>\n </div>\n </Motion.div>\n ) : null}\n </AnimatePresence>\n );\n },\n);\n\nAccordionMotionContent.displayName = 'AccordionMotionContent';\n\nconst AccordionItemContent = memo<AccordionItemContentProps>(\n ({\n disableAnimation,\n isOpen,\n keepContentMounted,\n className,\n style,\n children,\n contentInnerClassName,\n contextMotionProps,\n skipInitialAnimation,\n }) => {\n if (disableAnimation || !keepContentMounted) {\n return (\n <AccordionStaticContent\n className={className}\n contentInnerClassName={contentInnerClassName}\n isOpen={isOpen}\n keepContentMounted={keepContentMounted}\n style={style}\n >\n {children}\n </AccordionStaticContent>\n );\n }\n\n return (\n <AccordionMotionContent\n className={className}\n contentInnerClassName={contentInnerClassName}\n contextMotionProps={contextMotionProps}\n isOpen={isOpen}\n skipInitialAnimation={skipInitialAnimation}\n style={style}\n >\n {children}\n </AccordionMotionContent>\n );\n },\n);\n\nAccordionItemContent.displayName = 'AccordionItemContent';\n\nconst AccordionItem = memo<AccordionItemProps>(\n ({\n itemKey,\n title,\n children,\n action,\n alwaysShowAction = false,\n disabled = false,\n allowExpand = true,\n hideIndicator: itemHideIndicator,\n indicatorPlacement: itemIndicatorPlacement,\n indicator: customIndicator,\n classNames,\n paddingInline = 16,\n paddingBlock = 8,\n padding,\n ref,\n variant: customVariant,\n styles: customStyles,\n headerWrapper,\n defaultExpand,\n expand,\n onExpandChange,\n }) => {\n // Per-item state context: only this item's provider re-emits when its\n // own isOpen flips, so siblings stay stable across toggles.\n const itemStateContext = useAccordionItemState();\n const configContext = useAccordionConfig();\n\n // Determine if using standalone mode (has expand or defaultExpand props)\n const isStandalone = expand !== undefined || defaultExpand !== undefined;\n\n // Standalone state management\n const [isExpandedStandalone, setIsExpandedStandalone] = useMergeState<boolean>(\n defaultExpand ?? false,\n {\n onChange: onExpandChange,\n value: expand,\n },\n );\n\n const contextHideIndicator = configContext?.hideIndicator;\n const contextIndicatorPlacement = configContext?.indicatorPlacement;\n const contextKeepContentMounted = configContext?.keepContentMounted;\n const contextDisableAnimation = configContext?.disableAnimation;\n const contextMotionProps = configContext?.motionProps;\n const contextVariant = configContext?.variant ?? 'borderless';\n\n const isInitialRenderRef = useRef(true);\n\n useEffect(() => {\n isInitialRenderRef.current = false;\n }, []);\n\n const isDirectContextItem = itemStateContext?.itemKey === itemKey;\n\n // Determine expanded state\n let isOpen = false;\n if (isStandalone) {\n isOpen = isExpandedStandalone;\n } else if (itemStateContext) {\n isOpen = isDirectContextItem\n ? itemStateContext.isOpen\n : itemStateContext.isOpen || itemStateContext.isOpenKey(itemKey);\n }\n\n // Determine other props with fallbacks\n const hideIndicatorFinal = itemHideIndicator ?? contextHideIndicator ?? false;\n const indicatorPlacementFinal = itemIndicatorPlacement ?? contextIndicatorPlacement ?? 'start';\n const keepContentMounted = contextKeepContentMounted ?? true;\n const disableAnimation = contextDisableAnimation ?? false;\n const variant = customVariant || contextVariant;\n\n const contextOnToggle = useCallback(() => {\n if (!itemStateContext) return;\n if (itemStateContext.itemKey === itemKey) {\n itemStateContext.onToggle();\n return;\n }\n itemStateContext.onToggleNestedKey(itemKey);\n }, [itemStateContext, itemKey]);\n\n const handleToggle = useCallback(() => {\n // If allowExpand is false, only allow controlled expansion via expand prop\n if (!allowExpand) return;\n\n if (!disabled) {\n if (isStandalone) {\n setIsExpandedStandalone(!isExpandedStandalone);\n } else if (contextOnToggle) {\n contextOnToggle();\n }\n }\n }, [\n allowExpand,\n disabled,\n isStandalone,\n setIsExpandedStandalone,\n isExpandedStandalone,\n contextOnToggle,\n ]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n // If allowExpand is false, disable keyboard toggle\n if (!allowExpand || disabled) return;\n\n switch (e.key) {\n case 'Enter':\n case ' ': {\n e.preventDefault();\n handleToggle();\n break;\n }\n }\n },\n [allowExpand, disabled, handleToggle],\n );\n\n const preventTitleTextSelection = useCallback((e: any) => {\n // Prevent browser from creating a selection range on double/multi click,\n // which can accidentally select the content region.\n if (e?.detail > 1) e.preventDefault();\n }, []);\n\n // Build indicator\n const indicator = useMemo(() => {\n if (!allowExpand || hideIndicatorFinal) return null;\n\n if (customIndicator) {\n if (typeof customIndicator === 'function') {\n return (\n <span\n aria-hidden=\"true\"\n className={cx(styles.indicator, classNames?.indicator)}\n style={customStyles?.indicator}\n >\n {customIndicator({ isDisabled: disabled, isOpen })}\n </span>\n );\n }\n return (\n <span\n aria-hidden=\"true\"\n className={cx(styles.indicator, classNames?.indicator)}\n style={customStyles?.indicator}\n >\n {customIndicator}\n </span>\n );\n }\n\n return (\n <span\n aria-hidden=\"true\"\n className={cx(styles.indicator, classNames?.indicator)}\n style={customStyles?.indicator}\n >\n <ArrowIcon className={cx(styles.icon, isOpen && styles.iconRotate)} />\n </span>\n );\n }, [\n allowExpand,\n hideIndicatorFinal,\n customIndicator,\n disabled,\n isOpen,\n classNames,\n customStyles,\n ]);\n\n const skipInitialAnimation = isInitialRenderRef.current && isOpen;\n\n const contentClassName = useMemo(\n () => cx('accordion-content', styles.content, classNames?.content),\n [classNames?.content],\n );\n\n const titleNode = useMemo(\n () =>\n typeof title === 'string' ? (\n <Text ellipsis className={classNames?.title} style={customStyles?.title}>\n {title}\n </Text>\n ) : (\n title\n ),\n [title, classNames?.title, customStyles?.title],\n );\n\n const actionNode = useMemo(\n () =>\n action && (\n <Flexbox\n horizontal\n align={'center'}\n flex={'none'}\n gap={4}\n style={customStyles?.action}\n className={cx(\n 'accordion-action',\n styles.action,\n alwaysShowAction && styles.actionVisible,\n classNames?.action,\n )}\n onClick={stopPropagation}\n >\n {action}\n </Flexbox>\n ),\n [action, alwaysShowAction, classNames?.action, customStyles?.action],\n );\n\n const headerElement = useMemo(() => {\n const header = (\n <Block\n horizontal\n className={cx('accordion-header', styles.header, classNames?.header)}\n clickable={!disabled && allowExpand}\n gap={4}\n justify={'space-between'}\n padding={padding}\n paddingBlock={paddingBlock}\n paddingInline={paddingInline}\n ref={ref}\n variant={customVariant || variant}\n style={{\n alignItems: 'center',\n cursor: disabled ? 'not-allowed' : allowExpand ? 'pointer' : 'default',\n opacity: disabled ? 0.5 : undefined,\n overflow: 'hidden',\n width: '100%',\n ...customStyles?.header,\n }}\n onClick={handleToggle}\n onKeyDown={handleKeyDown}\n >\n {indicatorPlacementFinal === 'start' ? (\n <>\n <Flexbox\n horizontal\n align={'center'}\n className={styles.titleWrapper}\n flex={1}\n gap={2}\n style={{\n overflow: 'hidden',\n }}\n onDoubleClick={preventTitleTextSelection}\n onMouseDown={preventTitleTextSelection}\n >\n {titleNode}\n {indicator}\n </Flexbox>\n <Flexbox horizontal align={'center'} flex={'none'} gap={4}>\n {actionNode}\n </Flexbox>\n </>\n ) : (\n <>\n <Flexbox\n horizontal\n align={'center'}\n className={styles.titleWrapper}\n flex={1}\n gap={2}\n style={{\n overflow: 'hidden',\n }}\n onDoubleClick={preventTitleTextSelection}\n onMouseDown={preventTitleTextSelection}\n >\n {titleNode}\n </Flexbox>\n <Flexbox horizontal align={'center'} flex={'none'} gap={4}>\n {actionNode}\n {indicator}\n </Flexbox>\n </>\n )}\n </Block>\n );\n if (headerWrapper) {\n return headerWrapper(header);\n }\n return header;\n }, [\n classNames?.header,\n disabled,\n allowExpand,\n padding,\n paddingBlock,\n paddingInline,\n ref,\n customVariant,\n variant,\n customStyles?.header,\n handleToggle,\n handleKeyDown,\n indicatorPlacementFinal,\n preventTitleTextSelection,\n titleNode,\n indicator,\n actionNode,\n headerWrapper,\n ]);\n\n return (\n <div\n className={cx('accordion-item', styles.item, classNames?.base)}\n style={customStyles?.base}\n >\n {headerElement}\n <AccordionItemContent\n className={contentClassName}\n contentInnerClassName={styles.contentInner}\n contextMotionProps={contextMotionProps}\n disableAnimation={!!disableAnimation}\n isOpen={isOpen}\n keepContentMounted={!!keepContentMounted}\n skipInitialAnimation={skipInitialAnimation}\n style={customStyles?.content}\n >\n {children}\n </AccordionItemContent>\n </div>\n );\n },\n);\n\nAccordionItem.displayName = 'AccordionItem';\n\nexport default AccordionItem;\n"],"mappings":"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"}
1
+ {"version":3,"file":"AccordionItem.mjs","names":["Flexbox"],"sources":["../../src/Accordion/AccordionItem.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\nimport { AnimatePresence } from 'motion/react';\nimport {\n type ComponentPropsWithoutRef,\n type CSSProperties,\n type KeyboardEvent,\n memo,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n} from 'react';\nimport useMergeState from 'use-merge-value';\n\nimport Block from '@/Block';\nimport { Flexbox } from '@/Flex';\nimport { type MotionComponentType, useMotionComponent } from '@/MotionProvider';\nimport Text from '@/Text';\nimport { stopPropagation } from '@/utils/dom';\n\nimport ArrowIcon from './ArrowIcon';\nimport { useAccordionConfig, useAccordionItemState } from './context';\nimport { styles } from './style';\nimport { type AccordionItemProps } from './type';\n\ntype AccordionContentBaseProps = {\n children?: ReactNode;\n className?: string;\n contentInnerClassName: string;\n style?: CSSProperties;\n};\n\ntype AccordionStaticContentProps = AccordionContentBaseProps & {\n isOpen: boolean;\n keepContentMounted: boolean;\n};\n\ntype MotionDivProps = ComponentPropsWithoutRef<MotionComponentType['div']>;\n\ntype AccordionMotionContentProps = AccordionContentBaseProps & {\n contextMotionProps?: MotionDivProps;\n isOpen: boolean;\n skipInitialAnimation: boolean;\n};\n\ntype AccordionItemContentProps = AccordionContentBaseProps & {\n contextMotionProps?: MotionDivProps;\n disableAnimation: boolean;\n isOpen: boolean;\n keepContentMounted: boolean;\n skipInitialAnimation: boolean;\n};\n\nconst motionContainerStyle: CSSProperties = { overflow: 'hidden' };\n\nconst AccordionStaticContent = memo<AccordionStaticContentProps>(\n ({ className, style, children, contentInnerClassName, isOpen, keepContentMounted }) => {\n if (keepContentMounted) {\n return (\n <div\n className={className}\n role=\"region\"\n style={{\n display: isOpen ? 'block' : 'none',\n ...style,\n }}\n >\n <div className={contentInnerClassName}>{children}</div>\n </div>\n );\n }\n\n if (!isOpen) return null;\n\n return (\n <div className={className} role=\"region\" style={style}>\n <div className={contentInnerClassName}>{children}</div>\n </div>\n );\n },\n);\n\nAccordionStaticContent.displayName = 'AccordionStaticContent';\n\nconst AccordionMotionContent = memo<AccordionMotionContentProps>(\n ({\n contextMotionProps,\n className,\n style,\n children,\n contentInnerClassName,\n isOpen,\n skipInitialAnimation,\n }) => {\n const Motion = useMotionComponent();\n\n const motionProps = useMemo(\n () => ({\n animate: 'enter',\n exit: 'exit',\n initial: skipInitialAnimation ? false : 'exit',\n variants: {\n enter: {\n height: 'auto',\n opacity: 1,\n transition: {\n duration: 0.2,\n ease: [0.4, 0, 0.2, 1],\n },\n },\n exit: {\n height: 0,\n opacity: 0,\n transition: {\n duration: 0.2,\n ease: [0.4, 0, 0.2, 1],\n },\n },\n },\n ...contextMotionProps,\n }),\n [contextMotionProps, skipInitialAnimation],\n );\n\n return (\n <AnimatePresence initial={false}>\n {isOpen ? (\n <Motion.div {...(motionProps as any)} style={motionContainerStyle}>\n <div className={className} role=\"region\" style={style}>\n <div className={contentInnerClassName}>{children}</div>\n </div>\n </Motion.div>\n ) : null}\n </AnimatePresence>\n );\n },\n);\n\nAccordionMotionContent.displayName = 'AccordionMotionContent';\n\nconst AccordionItemContent = memo<AccordionItemContentProps>(\n ({\n disableAnimation,\n isOpen,\n keepContentMounted,\n className,\n style,\n children,\n contentInnerClassName,\n contextMotionProps,\n skipInitialAnimation,\n }) => {\n if (disableAnimation || !keepContentMounted) {\n return (\n <AccordionStaticContent\n className={className}\n contentInnerClassName={contentInnerClassName}\n isOpen={isOpen}\n keepContentMounted={keepContentMounted}\n style={style}\n >\n {children}\n </AccordionStaticContent>\n );\n }\n\n return (\n <AccordionMotionContent\n className={className}\n contentInnerClassName={contentInnerClassName}\n contextMotionProps={contextMotionProps}\n isOpen={isOpen}\n skipInitialAnimation={skipInitialAnimation}\n style={style}\n >\n {children}\n </AccordionMotionContent>\n );\n },\n);\n\nAccordionItemContent.displayName = 'AccordionItemContent';\n\nconst AccordionItem = memo<AccordionItemProps>(\n ({\n itemKey,\n title,\n children,\n action,\n alwaysShowAction = false,\n disabled = false,\n allowExpand = true,\n hideIndicator: itemHideIndicator,\n indicatorPlacement: itemIndicatorPlacement,\n indicator: customIndicator,\n classNames,\n paddingInline = 16,\n paddingBlock = 8,\n padding,\n ref,\n variant: customVariant,\n styles: customStyles,\n headerWrapper,\n defaultExpand,\n expand,\n onExpandChange,\n }) => {\n // Per-item state context: only this item's provider re-emits when its\n // own isOpen flips, so siblings stay stable across toggles.\n const itemStateContext = useAccordionItemState();\n const configContext = useAccordionConfig();\n\n // Determine if using standalone mode (has expand or defaultExpand props)\n const isStandalone = expand !== undefined || defaultExpand !== undefined;\n\n // Standalone state management\n const [isExpandedStandalone, setIsExpandedStandalone] = useMergeState<boolean>(\n defaultExpand ?? false,\n {\n onChange: onExpandChange,\n value: expand,\n },\n );\n\n const contextHideIndicator = configContext?.hideIndicator;\n const contextIndicatorPlacement = configContext?.indicatorPlacement;\n const contextKeepContentMounted = configContext?.keepContentMounted;\n const contextDisableAnimation = configContext?.disableAnimation;\n const contextMotionProps = configContext?.motionProps;\n const contextVariant = configContext?.variant ?? 'borderless';\n\n const isInitialRenderRef = useRef(true);\n\n useEffect(() => {\n isInitialRenderRef.current = false;\n }, []);\n\n const isDirectContextItem = itemStateContext?.itemKey === itemKey;\n\n // Determine expanded state\n let isOpen = false;\n if (isStandalone) {\n isOpen = isExpandedStandalone;\n } else if (itemStateContext) {\n isOpen = isDirectContextItem\n ? itemStateContext.isOpen\n : itemStateContext.isOpen || itemStateContext.isOpenKey(itemKey);\n }\n\n // Determine other props with fallbacks\n const hideIndicatorFinal = itemHideIndicator ?? contextHideIndicator ?? false;\n const indicatorPlacementFinal = itemIndicatorPlacement ?? contextIndicatorPlacement ?? 'start';\n const keepContentMounted = contextKeepContentMounted ?? true;\n const disableAnimation = contextDisableAnimation ?? false;\n const variant = customVariant || contextVariant;\n\n const contextOnToggle = useCallback(() => {\n if (!itemStateContext) return;\n if (itemStateContext.itemKey === itemKey) {\n itemStateContext.onToggle();\n return;\n }\n itemStateContext.onToggleNestedKey(itemKey);\n }, [itemStateContext, itemKey]);\n\n const handleToggle = useCallback(() => {\n // If allowExpand is false, only allow controlled expansion via expand prop\n if (!allowExpand) return;\n\n if (!disabled) {\n if (isStandalone) {\n setIsExpandedStandalone(!isExpandedStandalone);\n } else if (contextOnToggle) {\n contextOnToggle();\n }\n }\n }, [\n allowExpand,\n disabled,\n isStandalone,\n setIsExpandedStandalone,\n isExpandedStandalone,\n contextOnToggle,\n ]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n // If allowExpand is false, disable keyboard toggle\n if (!allowExpand || disabled) return;\n\n switch (e.key) {\n case 'Enter':\n case ' ': {\n e.preventDefault();\n handleToggle();\n break;\n }\n }\n },\n [allowExpand, disabled, handleToggle],\n );\n\n const preventTitleTextSelection = useCallback((e: any) => {\n // Prevent browser from creating a selection range on double/multi click,\n // which can accidentally select the content region.\n if (e?.detail > 1) e.preventDefault();\n }, []);\n\n // Build indicator\n const indicator = useMemo(() => {\n if (!allowExpand || hideIndicatorFinal) return null;\n\n if (customIndicator) {\n if (typeof customIndicator === 'function') {\n return (\n <span\n aria-hidden=\"true\"\n className={cx(styles.indicator, classNames?.indicator)}\n style={customStyles?.indicator}\n >\n {customIndicator({ isDisabled: disabled, isOpen })}\n </span>\n );\n }\n return (\n <span\n aria-hidden=\"true\"\n className={cx(styles.indicator, classNames?.indicator)}\n style={customStyles?.indicator}\n >\n {customIndicator}\n </span>\n );\n }\n\n return (\n <span\n aria-hidden=\"true\"\n className={cx(styles.indicator, classNames?.indicator)}\n style={customStyles?.indicator}\n >\n <ArrowIcon className={cx(styles.icon, isOpen && styles.iconRotate)} />\n </span>\n );\n }, [\n allowExpand,\n hideIndicatorFinal,\n customIndicator,\n disabled,\n isOpen,\n classNames,\n customStyles,\n ]);\n\n const skipInitialAnimation = isInitialRenderRef.current && isOpen;\n\n const contentClassName = useMemo(\n () => cx('accordion-content', styles.content, classNames?.content),\n [classNames?.content],\n );\n\n const titleNode = useMemo(\n () =>\n typeof title === 'string' ? (\n <Text ellipsis className={classNames?.title} style={customStyles?.title}>\n {title}\n </Text>\n ) : (\n title\n ),\n [title, classNames?.title, customStyles?.title],\n );\n\n const actionNode = useMemo(\n () =>\n action && (\n <Flexbox\n horizontal\n align={'center'}\n flex={'none'}\n gap={4}\n style={customStyles?.action}\n className={cx(\n 'accordion-action',\n styles.action,\n alwaysShowAction && styles.actionVisible,\n classNames?.action,\n )}\n onClick={stopPropagation}\n >\n {action}\n </Flexbox>\n ),\n [action, alwaysShowAction, classNames?.action, customStyles?.action],\n );\n\n const headerElement = useMemo(() => {\n const header = (\n <Block\n horizontal\n className={cx('accordion-header', styles.header, classNames?.header)}\n clickable={!disabled && allowExpand}\n gap={4}\n justify={'space-between'}\n padding={padding}\n paddingBlock={paddingBlock}\n paddingInline={paddingInline}\n ref={ref}\n variant={customVariant || variant}\n style={{\n alignItems: 'center',\n cursor: disabled ? 'not-allowed' : allowExpand ? 'pointer' : 'default',\n opacity: disabled ? 0.5 : undefined,\n overflow: 'hidden',\n width: '100%',\n ...customStyles?.header,\n }}\n onClick={handleToggle}\n onKeyDown={handleKeyDown}\n >\n {indicatorPlacementFinal === 'start' ? (\n <>\n <Flexbox\n horizontal\n align={'center'}\n className={styles.titleWrapper}\n flex={1}\n gap={2}\n style={{\n overflow: 'hidden',\n }}\n onDoubleClick={preventTitleTextSelection}\n onMouseDown={preventTitleTextSelection}\n >\n {titleNode}\n {indicator}\n </Flexbox>\n <Flexbox horizontal align={'center'} flex={'none'} gap={4}>\n {actionNode}\n </Flexbox>\n </>\n ) : (\n <>\n <Flexbox\n horizontal\n align={'center'}\n className={styles.titleWrapper}\n flex={1}\n gap={2}\n style={{\n overflow: 'hidden',\n }}\n onDoubleClick={preventTitleTextSelection}\n onMouseDown={preventTitleTextSelection}\n >\n {titleNode}\n </Flexbox>\n <Flexbox horizontal align={'center'} flex={'none'} gap={4}>\n {actionNode}\n {indicator}\n </Flexbox>\n </>\n )}\n </Block>\n );\n if (headerWrapper) {\n return headerWrapper(header);\n }\n return header;\n }, [\n classNames?.header,\n disabled,\n allowExpand,\n padding,\n paddingBlock,\n paddingInline,\n ref,\n customVariant,\n variant,\n customStyles?.header,\n handleToggle,\n handleKeyDown,\n indicatorPlacementFinal,\n preventTitleTextSelection,\n titleNode,\n indicator,\n actionNode,\n headerWrapper,\n ]);\n\n return (\n <div\n className={cx('accordion-item', styles.item, classNames?.base)}\n style={customStyles?.base}\n >\n {headerElement}\n <AccordionItemContent\n className={contentClassName}\n contentInnerClassName={styles.contentInner}\n contextMotionProps={contextMotionProps}\n disableAnimation={!!disableAnimation}\n isOpen={isOpen}\n keepContentMounted={!!keepContentMounted}\n skipInitialAnimation={skipInitialAnimation}\n style={customStyles?.content}\n >\n {children}\n </AccordionItemContent>\n </div>\n );\n },\n);\n\nAccordionItem.displayName = 'AccordionItem';\n\nexport default AccordionItem;\n"],"mappings":"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"}
@@ -23,15 +23,13 @@ const calcSize = (iconSize) => {
23
23
  blockSize = 24;
24
24
  borderRadius = 4;
25
25
  break;
26
- default:
27
- if (iconSize) {
28
- blockSize = iconSize?.blockSize || 36;
29
- borderRadius = iconSize?.borderRadius || 6;
30
- } else {
31
- blockSize = "1.8em";
32
- borderRadius = "0.3em";
33
- }
34
- break;
26
+ default: if (iconSize) {
27
+ blockSize = iconSize?.blockSize || 36;
28
+ borderRadius = iconSize?.borderRadius || 6;
29
+ } else {
30
+ blockSize = "1.8em";
31
+ borderRadius = "0.3em";
32
+ }
35
33
  }
36
34
  return {
37
35
  blockSize,
@@ -1 +1 @@
1
- {"version":3,"file":"utils.mjs","names":[],"sources":["../../../src/ActionIcon/components/utils.ts"],"sourcesContent":["import { isNumber } from 'es-toolkit/compat';\n\nimport type { ActionIconSize } from '@/ActionIcon';\n\nexport const calcSize = (iconSize?: ActionIconSize) => {\n let blockSize: number | string;\n let borderRadius: number | string;\n\n if (isNumber(iconSize)) {\n const blockSize = iconSize * 1.8;\n return {\n blockSize,\n borderRadius: Math.floor(blockSize / 6),\n };\n }\n\n switch (iconSize) {\n case 'large': {\n blockSize = 44;\n borderRadius = 8;\n break;\n }\n case 'middle': {\n blockSize = 36;\n borderRadius = 6;\n break;\n }\n case 'small': {\n blockSize = 24;\n borderRadius = 4;\n break;\n }\n default: {\n if (iconSize) {\n blockSize = iconSize?.blockSize || 36;\n borderRadius = iconSize?.borderRadius || 6;\n } else {\n blockSize = '1.8em';\n borderRadius = '0.3em';\n }\n\n break;\n }\n }\n\n return {\n blockSize,\n borderRadius,\n };\n};\n"],"mappings":";;AAIA,MAAa,YAAY,aAA8B;CACrD,IAAI;CACJ,IAAI;CAEJ,IAAI,SAAS,QAAQ,GAAG;EACtB,MAAM,YAAY,WAAW;EAC7B,OAAO;GACL;GACA,cAAc,KAAK,MAAM,YAAY,CAAC;EACxC;CACF;CAEA,QAAQ,UAAR;EACE,KAAK;GACH,YAAY;GACZ,eAAe;GACf;EAEF,KAAK;GACH,YAAY;GACZ,eAAe;GACf;EAEF,KAAK;GACH,YAAY;GACZ,eAAe;GACf;EAEF;GACE,IAAI,UAAU;IACZ,YAAY,UAAU,aAAa;IACnC,eAAe,UAAU,gBAAgB;GAC3C,OAAO;IACL,YAAY;IACZ,eAAe;GACjB;GAEA;CAEJ;CAEA,OAAO;EACL;EACA;CACF;AACF"}
1
+ {"version":3,"file":"utils.mjs","names":[],"sources":["../../../src/ActionIcon/components/utils.ts"],"sourcesContent":["import { isNumber } from 'es-toolkit/compat';\n\nimport type { ActionIconSize } from '@/ActionIcon';\n\nexport const calcSize = (iconSize?: ActionIconSize) => {\n let blockSize: number | string;\n let borderRadius: number | string;\n\n if (isNumber(iconSize)) {\n const blockSize = iconSize * 1.8;\n return {\n blockSize,\n borderRadius: Math.floor(blockSize / 6),\n };\n }\n\n switch (iconSize) {\n case 'large': {\n blockSize = 44;\n borderRadius = 8;\n break;\n }\n case 'middle': {\n blockSize = 36;\n borderRadius = 6;\n break;\n }\n case 'small': {\n blockSize = 24;\n borderRadius = 4;\n break;\n }\n default: {\n if (iconSize) {\n blockSize = iconSize?.blockSize || 36;\n borderRadius = iconSize?.borderRadius || 6;\n } else {\n blockSize = '1.8em';\n borderRadius = '0.3em';\n }\n\n break;\n }\n }\n\n return {\n blockSize,\n borderRadius,\n };\n};\n"],"mappings":";;AAIA,MAAa,YAAY,aAA8B;CACrD,IAAI;CACJ,IAAI;CAEJ,IAAI,SAAS,QAAQ,GAAG;EACtB,MAAM,YAAY,WAAW;EAC7B,OAAO;GACL;GACA,cAAc,KAAK,MAAM,YAAY,CAAC;EACxC;CACF;CAEA,QAAQ,UAAR;EACE,KAAK;GACH,YAAY;GACZ,eAAe;GACf;EAEF,KAAK;GACH,YAAY;GACZ,eAAe;GACf;EAEF,KAAK;GACH,YAAY;GACZ,eAAe;GACf;EAEF,SACE,IAAI,UAAU;GACZ,YAAY,UAAU,aAAa;GACnC,eAAe,UAAU,gBAAgB;EAC3C,OAAO;GACL,YAAY;GACZ,eAAe;EACjB;CAIJ;CAEA,OAAO;EACL;EACA;CACF;AACF"}
@@ -28,9 +28,11 @@ const CheckboxGroup = ({ defaultValue, disabled, onChange, options, textProps, v
28
28
  wrap: "wrap",
29
29
  ...rest,
30
30
  children: normalizedOptions.map((option) => {
31
+ const isChecked = selectedValues.includes(option.value);
32
+ const isDisabled = disabled || option.disabled;
31
33
  return /* @__PURE__ */ jsx(Checkbox, {
32
- checked: selectedValues.includes(option.value),
33
- disabled: disabled || option.disabled,
34
+ checked: isChecked,
35
+ disabled: isDisabled,
34
36
  shape,
35
37
  size,
36
38
  textProps,
@@ -1 +1 @@
1
- {"version":3,"file":"CheckboxGroup.mjs","names":["Flexbox"],"sources":["../../src/Checkbox/CheckboxGroup.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport useMergeState from 'use-merge-value';\n\nimport { Flexbox } from '@/Flex';\n\nimport Checkbox from './Checkbox';\nimport type { CheckboxGroupProps } from './type';\n\nconst CheckboxGroup: FC<CheckboxGroupProps> = ({\n defaultValue,\n disabled,\n onChange,\n options,\n textProps,\n value,\n shape,\n size,\n ...rest\n}) => {\n const [selectedValues, setSelectedValues] = useMergeState<string[]>(defaultValue || [], {\n defaultValue,\n onChange,\n value,\n });\n\n const handleChange = (optionValue: string, checked: boolean) => {\n const newValues = checked\n ? [...selectedValues, optionValue]\n : selectedValues.filter((v) => v !== optionValue);\n\n setSelectedValues(newValues);\n };\n\n const normalizedOptions = options.map((option) => {\n if (typeof option === 'string') {\n return {\n disabled: false,\n label: option,\n value: option,\n };\n }\n return option;\n });\n\n return (\n <Flexbox horizontal align={'center'} gap={16} wrap={'wrap'} {...rest}>\n {normalizedOptions.map((option) => {\n const isChecked = selectedValues.includes(option.value);\n const isDisabled = disabled || option.disabled;\n\n return (\n <Checkbox\n checked={isChecked}\n disabled={isDisabled}\n key={String(option.value)}\n shape={shape}\n size={size}\n textProps={textProps}\n onChange={(checked) => handleChange(option.value, checked)}\n >\n {option.label}\n </Checkbox>\n );\n })}\n </Flexbox>\n );\n};\n\nCheckboxGroup.displayName = 'CheckboxGroup';\n\nexport default CheckboxGroup;\n"],"mappings":";;;;;AAQA,MAAM,iBAAyC,EAC7C,cACA,UACA,UACA,SACA,WACA,OACA,OACA,MACA,GAAG,WACC;CACJ,MAAM,CAAC,gBAAgB,qBAAqB,cAAwB,gBAAgB,CAAC,GAAG;EACtF;EACA;EACA;CACF,CAAC;CAED,MAAM,gBAAgB,aAAqB,YAAqB;EAC9D,MAAM,YAAY,UACd,CAAC,GAAG,gBAAgB,WAAW,IAC/B,eAAe,QAAQ,MAAM,MAAM,WAAW;EAElD,kBAAkB,SAAS;CAC7B;CAEA,MAAM,oBAAoB,QAAQ,KAAK,WAAW;EAChD,IAAI,OAAO,WAAW,UACpB,OAAO;GACL,UAAU;GACV,OAAO;GACP,OAAO;EACT;EAEF,OAAO;CACT,CAAC;CAED,OACE,oBAACA,mBAAD;EAAS,YAAA;EAAW,OAAO;EAAU,KAAK;EAAI,MAAM;EAAQ,GAAI;EAC7D,UAAA,kBAAkB,KAAK,WAAW;GAIjC,OACE,oBAAC,UAAD;IACE,SALc,eAAe,SAAS,OAAO,KAK5B;IACjB,UALe,YAAY,OAAO;IAO3B;IACD;IACK;IACX,WAAW,YAAY,aAAa,OAAO,OAAO,OAAO;IAExD,UAAA,OAAO;GACA,GAPH,OAAO,OAAO,KAAK,CAOhB;EAEd,CAAC;CACM,CAAA;AAEb;AAEA,cAAc,cAAc"}
1
+ {"version":3,"file":"CheckboxGroup.mjs","names":["Flexbox"],"sources":["../../src/Checkbox/CheckboxGroup.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport useMergeState from 'use-merge-value';\n\nimport { Flexbox } from '@/Flex';\n\nimport Checkbox from './Checkbox';\nimport type { CheckboxGroupProps } from './type';\n\nconst CheckboxGroup: FC<CheckboxGroupProps> = ({\n defaultValue,\n disabled,\n onChange,\n options,\n textProps,\n value,\n shape,\n size,\n ...rest\n}) => {\n const [selectedValues, setSelectedValues] = useMergeState<string[]>(defaultValue || [], {\n defaultValue,\n onChange,\n value,\n });\n\n const handleChange = (optionValue: string, checked: boolean) => {\n const newValues = checked\n ? [...selectedValues, optionValue]\n : selectedValues.filter((v) => v !== optionValue);\n\n setSelectedValues(newValues);\n };\n\n const normalizedOptions = options.map((option) => {\n if (typeof option === 'string') {\n return {\n disabled: false,\n label: option,\n value: option,\n };\n }\n return option;\n });\n\n return (\n <Flexbox horizontal align={'center'} gap={16} wrap={'wrap'} {...rest}>\n {normalizedOptions.map((option) => {\n const isChecked = selectedValues.includes(option.value);\n const isDisabled = disabled || option.disabled;\n\n return (\n <Checkbox\n checked={isChecked}\n disabled={isDisabled}\n key={String(option.value)}\n shape={shape}\n size={size}\n textProps={textProps}\n onChange={(checked) => handleChange(option.value, checked)}\n >\n {option.label}\n </Checkbox>\n );\n })}\n </Flexbox>\n );\n};\n\nCheckboxGroup.displayName = 'CheckboxGroup';\n\nexport default CheckboxGroup;\n"],"mappings":";;;;;AAQA,MAAM,iBAAyC,EAC7C,cACA,UACA,UACA,SACA,WACA,OACA,OACA,MACA,GAAG,WACC;CACJ,MAAM,CAAC,gBAAgB,qBAAqB,cAAwB,gBAAgB,CAAC,GAAG;EACtF;EACA;EACA;CACF,CAAC;CAED,MAAM,gBAAgB,aAAqB,YAAqB;EAC9D,MAAM,YAAY,UACd,CAAC,GAAG,gBAAgB,WAAW,IAC/B,eAAe,QAAQ,MAAM,MAAM,WAAW;EAElD,kBAAkB,SAAS;CAC7B;CAEA,MAAM,oBAAoB,QAAQ,KAAK,WAAW;EAChD,IAAI,OAAO,WAAW,UACpB,OAAO;GACL,UAAU;GACV,OAAO;GACP,OAAO;EACT;EAEF,OAAO;CACT,CAAC;CAED,OACE,oBAACA,mBAAD;EAAS,YAAA;EAAW,OAAO;EAAU,KAAK;EAAI,MAAM;EAAQ,GAAI;EAC7D,UAAA,kBAAkB,KAAK,WAAW;GACjC,MAAM,YAAY,eAAe,SAAS,OAAO,KAAK;GACtD,MAAM,aAAa,YAAY,OAAO;GAEtC,OACE,oBAAC,UAAD;IACE,SAAS;IACT,UAAU;IAEH;IACD;IACK;IACX,WAAW,YAAY,aAAa,OAAO,OAAO,OAAO;IAExD,UAAA,OAAO;GACA,GAPH,OAAO,OAAO,KAAK,CAOhB;EAEd,CAAC;CACM,CAAA;AAEb;AAEA,cAAc,cAAc"}
@@ -50,29 +50,31 @@ const CodeDiff = memo(({ oldContent, newContent, language, fileName, viewMode =
50
50
  language,
51
51
  fileName
52
52
  ]);
53
+ const newFile = useMemo(() => ({
54
+ contents: newContent,
55
+ lang: language,
56
+ name: fileName || "file"
57
+ }), [
58
+ newContent,
59
+ language,
60
+ fileName
61
+ ]);
62
+ const options = useMemo(() => getLobeDiffOptions({
63
+ diffOptions,
64
+ isDarkMode,
65
+ viewMode
66
+ }), [
67
+ isDarkMode,
68
+ viewMode,
69
+ diffOptions
70
+ ]);
53
71
  return /* @__PURE__ */ jsx(DiffPanel, {
54
72
  actions,
55
73
  additions,
56
74
  body: /* @__PURE__ */ jsx(MultiFileDiff, {
57
- newFile: useMemo(() => ({
58
- contents: newContent,
59
- lang: language,
60
- name: fileName || "file"
61
- }), [
62
- newContent,
63
- language,
64
- fileName
65
- ]),
75
+ newFile,
66
76
  oldFile,
67
- options: useMemo(() => getLobeDiffOptions({
68
- diffOptions,
69
- isDarkMode,
70
- viewMode
71
- }), [
72
- isDarkMode,
73
- viewMode,
74
- diffOptions
75
- ])
77
+ options
76
78
  }),
77
79
  className,
78
80
  classNames,
@@ -1 +1 @@
1
- {"version":3,"file":"CodeDiff.mjs","names":[],"sources":["../../src/CodeDiff/CodeDiff.tsx"],"sourcesContent":["'use client';\n\nimport type { FileDiffOptions } from '@pierre/diffs';\nimport { MultiFileDiff } from '@pierre/diffs/react';\nimport { useThemeMode } from 'antd-style';\nimport { memo, useMemo } from 'react';\n\nimport { DiffPanel } from './DiffPanel';\nimport { getLobeDiffOptions, registerLobeDiffThemes } from './theme';\nimport type { CodeDiffProps } from './type';\n\nregisterLobeDiffThemes();\n\nconst countContentChanges = (\n oldContent: string,\n newContent: string,\n): { additions: number; deletions: number } => {\n const oldLines = oldContent.split('\\n');\n const newLines = newContent.split('\\n');\n\n const oldSet = new Set(oldLines);\n const newSet = new Set(newLines);\n\n let deletions = 0;\n let additions = 0;\n\n for (const line of oldLines) {\n if (!newSet.has(line)) {\n deletions++;\n }\n }\n\n for (const line of newLines) {\n if (!oldSet.has(line)) {\n additions++;\n }\n }\n\n return { additions, deletions };\n};\n\nexport const CodeDiff = memo<CodeDiffProps>(\n ({\n oldContent,\n newContent,\n language,\n fileName,\n viewMode = 'split',\n showHeader = true,\n defaultExpand = true,\n fullFeatured = true,\n variant = 'filled',\n className,\n classNames,\n styles: customStyles,\n actionsRender,\n diffOptions,\n ...rest\n }) => {\n const { isDarkMode } = useThemeMode();\n\n const displayName = useMemo(() => {\n if (fileName) return fileName;\n if (language) return language;\n return 'diff';\n }, [fileName, language]);\n\n const { additions, deletions } = useMemo(\n () => countContentChanges(oldContent, newContent),\n [oldContent, newContent],\n );\n\n const actions = useMemo(() => {\n if (!actionsRender) return null;\n return actionsRender({\n newContent,\n oldContent,\n originalNode: null,\n });\n }, [actionsRender, oldContent, newContent]);\n\n const oldFile = useMemo(\n () => ({\n contents: oldContent,\n lang: language as any,\n name: fileName || 'file',\n }),\n [oldContent, language, fileName],\n );\n\n const newFile = useMemo(\n () => ({\n contents: newContent,\n lang: language as any,\n name: fileName || 'file',\n }),\n [newContent, language, fileName],\n );\n\n const options = useMemo<FileDiffOptions<string>>(\n () => getLobeDiffOptions({ diffOptions, isDarkMode, viewMode }),\n [isDarkMode, viewMode, diffOptions],\n );\n\n return (\n <DiffPanel\n actions={actions}\n additions={additions}\n body={<MultiFileDiff newFile={newFile} oldFile={oldFile} options={options} />}\n className={className}\n classNames={classNames}\n dataCodeType=\"code-diff\"\n defaultExpand={defaultExpand}\n deletions={deletions}\n displayName={displayName}\n fileName={fileName}\n fullFeatured={fullFeatured}\n showHeader={showHeader}\n styles={customStyles}\n variant={variant}\n {...rest}\n />\n );\n },\n);\n\nCodeDiff.displayName = 'CodeDiff';\n\nexport default CodeDiff;\n"],"mappings":";;;;;;;;AAWA,uBAAuB;AAEvB,MAAM,uBACJ,YACA,eAC6C;CAC7C,MAAM,WAAW,WAAW,MAAM,IAAI;CACtC,MAAM,WAAW,WAAW,MAAM,IAAI;CAEtC,MAAM,SAAS,IAAI,IAAI,QAAQ;CAC/B,MAAM,SAAS,IAAI,IAAI,QAAQ;CAE/B,IAAI,YAAY;CAChB,IAAI,YAAY;CAEhB,KAAK,MAAM,QAAQ,UACjB,IAAI,CAAC,OAAO,IAAI,IAAI,GAClB;CAIJ,KAAK,MAAM,QAAQ,UACjB,IAAI,CAAC,OAAO,IAAI,IAAI,GAClB;CAIJ,OAAO;EAAE;EAAW;CAAU;AAChC;AAEA,MAAa,WAAW,MACrB,EACC,YACA,YACA,UACA,UACA,WAAW,SACX,aAAa,MACb,gBAAgB,MAChB,eAAe,MACf,UAAU,UACV,WACA,YACA,QAAQ,cACR,eACA,aACA,GAAG,WACC;CACJ,MAAM,EAAE,eAAe,aAAa;CAEpC,MAAM,cAAc,cAAc;EAChC,IAAI,UAAU,OAAO;EACrB,IAAI,UAAU,OAAO;EACrB,OAAO;CACT,GAAG,CAAC,UAAU,QAAQ,CAAC;CAEvB,MAAM,EAAE,WAAW,cAAc,cACzB,oBAAoB,YAAY,UAAU,GAChD,CAAC,YAAY,UAAU,CACzB;CAEA,MAAM,UAAU,cAAc;EAC5B,IAAI,CAAC,eAAe,OAAO;EAC3B,OAAO,cAAc;GACnB;GACA;GACA,cAAc;EAChB,CAAC;CACH,GAAG;EAAC;EAAe;EAAY;CAAU,CAAC;CAE1C,MAAM,UAAU,eACP;EACL,UAAU;EACV,MAAM;EACN,MAAM,YAAY;CACpB,IACA;EAAC;EAAY;EAAU;CAAQ,CACjC;CAgBA,OACE,oBAAC,WAAD;EACW;EACE;EACX,MAAM,oBAAC,eAAD;GAAe,SAlBT,eACP;IACL,UAAU;IACV,MAAM;IACN,MAAM,YAAY;GACpB,IACA;IAAC;IAAY;IAAU;GAAQ,CAYO;GAAY;GAAS,SAT7C,cACR,mBAAmB;IAAE;IAAa;IAAY;GAAS,CAAC,GAC9D;IAAC;IAAY;IAAU;GAAW,CAOwC;EAAI,CAAA;EACjE;EACC;EACZ,cAAa;EACE;EACJ;EACE;EACH;EACI;EACF;EACZ,QAAQ;EACC;EACT,GAAI;CACL,CAAA;AAEL,CACF;AAEA,SAAS,cAAc"}
1
+ {"version":3,"file":"CodeDiff.mjs","names":[],"sources":["../../src/CodeDiff/CodeDiff.tsx"],"sourcesContent":["'use client';\n\nimport type { FileDiffOptions } from '@pierre/diffs';\nimport { MultiFileDiff } from '@pierre/diffs/react';\nimport { useThemeMode } from 'antd-style';\nimport { memo, useMemo } from 'react';\n\nimport { DiffPanel } from './DiffPanel';\nimport { getLobeDiffOptions, registerLobeDiffThemes } from './theme';\nimport type { CodeDiffProps } from './type';\n\nregisterLobeDiffThemes();\n\nconst countContentChanges = (\n oldContent: string,\n newContent: string,\n): { additions: number; deletions: number } => {\n const oldLines = oldContent.split('\\n');\n const newLines = newContent.split('\\n');\n\n const oldSet = new Set(oldLines);\n const newSet = new Set(newLines);\n\n let deletions = 0;\n let additions = 0;\n\n for (const line of oldLines) {\n if (!newSet.has(line)) {\n deletions++;\n }\n }\n\n for (const line of newLines) {\n if (!oldSet.has(line)) {\n additions++;\n }\n }\n\n return { additions, deletions };\n};\n\nexport const CodeDiff = memo<CodeDiffProps>(\n ({\n oldContent,\n newContent,\n language,\n fileName,\n viewMode = 'split',\n showHeader = true,\n defaultExpand = true,\n fullFeatured = true,\n variant = 'filled',\n className,\n classNames,\n styles: customStyles,\n actionsRender,\n diffOptions,\n ...rest\n }) => {\n const { isDarkMode } = useThemeMode();\n\n const displayName = useMemo(() => {\n if (fileName) return fileName;\n if (language) return language;\n return 'diff';\n }, [fileName, language]);\n\n const { additions, deletions } = useMemo(\n () => countContentChanges(oldContent, newContent),\n [oldContent, newContent],\n );\n\n const actions = useMemo(() => {\n if (!actionsRender) return null;\n return actionsRender({\n newContent,\n oldContent,\n originalNode: null,\n });\n }, [actionsRender, oldContent, newContent]);\n\n const oldFile = useMemo(\n () => ({\n contents: oldContent,\n lang: language as any,\n name: fileName || 'file',\n }),\n [oldContent, language, fileName],\n );\n\n const newFile = useMemo(\n () => ({\n contents: newContent,\n lang: language as any,\n name: fileName || 'file',\n }),\n [newContent, language, fileName],\n );\n\n const options = useMemo<FileDiffOptions<string>>(\n () => getLobeDiffOptions({ diffOptions, isDarkMode, viewMode }),\n [isDarkMode, viewMode, diffOptions],\n );\n\n return (\n <DiffPanel\n actions={actions}\n additions={additions}\n body={<MultiFileDiff newFile={newFile} oldFile={oldFile} options={options} />}\n className={className}\n classNames={classNames}\n dataCodeType=\"code-diff\"\n defaultExpand={defaultExpand}\n deletions={deletions}\n displayName={displayName}\n fileName={fileName}\n fullFeatured={fullFeatured}\n showHeader={showHeader}\n styles={customStyles}\n variant={variant}\n {...rest}\n />\n );\n },\n);\n\nCodeDiff.displayName = 'CodeDiff';\n\nexport default CodeDiff;\n"],"mappings":";;;;;;;;AAWA,uBAAuB;AAEvB,MAAM,uBACJ,YACA,eAC6C;CAC7C,MAAM,WAAW,WAAW,MAAM,IAAI;CACtC,MAAM,WAAW,WAAW,MAAM,IAAI;CAEtC,MAAM,SAAS,IAAI,IAAI,QAAQ;CAC/B,MAAM,SAAS,IAAI,IAAI,QAAQ;CAE/B,IAAI,YAAY;CAChB,IAAI,YAAY;CAEhB,KAAK,MAAM,QAAQ,UACjB,IAAI,CAAC,OAAO,IAAI,IAAI,GAClB;CAIJ,KAAK,MAAM,QAAQ,UACjB,IAAI,CAAC,OAAO,IAAI,IAAI,GAClB;CAIJ,OAAO;EAAE;EAAW;CAAU;AAChC;AAEA,MAAa,WAAW,MACrB,EACC,YACA,YACA,UACA,UACA,WAAW,SACX,aAAa,MACb,gBAAgB,MAChB,eAAe,MACf,UAAU,UACV,WACA,YACA,QAAQ,cACR,eACA,aACA,GAAG,WACC;CACJ,MAAM,EAAE,eAAe,aAAa;CAEpC,MAAM,cAAc,cAAc;EAChC,IAAI,UAAU,OAAO;EACrB,IAAI,UAAU,OAAO;EACrB,OAAO;CACT,GAAG,CAAC,UAAU,QAAQ,CAAC;CAEvB,MAAM,EAAE,WAAW,cAAc,cACzB,oBAAoB,YAAY,UAAU,GAChD,CAAC,YAAY,UAAU,CACzB;CAEA,MAAM,UAAU,cAAc;EAC5B,IAAI,CAAC,eAAe,OAAO;EAC3B,OAAO,cAAc;GACnB;GACA;GACA,cAAc;EAChB,CAAC;CACH,GAAG;EAAC;EAAe;EAAY;CAAU,CAAC;CAE1C,MAAM,UAAU,eACP;EACL,UAAU;EACV,MAAM;EACN,MAAM,YAAY;CACpB,IACA;EAAC;EAAY;EAAU;CAAQ,CACjC;CAEA,MAAM,UAAU,eACP;EACL,UAAU;EACV,MAAM;EACN,MAAM,YAAY;CACpB,IACA;EAAC;EAAY;EAAU;CAAQ,CACjC;CAEA,MAAM,UAAU,cACR,mBAAmB;EAAE;EAAa;EAAY;CAAS,CAAC,GAC9D;EAAC;EAAY;EAAU;CAAW,CACpC;CAEA,OACE,oBAAC,WAAD;EACW;EACE;EACX,MAAM,oBAAC,eAAD;GAAwB;GAAkB;GAAkB;EAAU,CAAA;EACjE;EACC;EACZ,cAAa;EACE;EACJ;EACE;EACH;EACI;EACF;EACZ,QAAQ;EACC;EACT,GAAI;CACL,CAAA;AAEL,CACF;AAEA,SAAS,cAAc"}
@@ -32,25 +32,27 @@ const PatchDiff$1 = memo(({ patch, language, fileName, viewMode = "split", showH
32
32
  language
33
33
  ]);
34
34
  const { additions, deletions } = useMemo(() => countPatchChanges(patch), [patch]);
35
+ const actions = useMemo(() => {
36
+ if (!actionsRender) return null;
37
+ return actionsRender({
38
+ originalNode: null,
39
+ patch
40
+ });
41
+ }, [actionsRender, patch]);
42
+ const options = useMemo(() => getLobeDiffOptions({
43
+ diffOptions,
44
+ isDarkMode,
45
+ viewMode
46
+ }), [
47
+ isDarkMode,
48
+ viewMode,
49
+ diffOptions
50
+ ]);
35
51
  return /* @__PURE__ */ jsx(DiffPanel, {
36
- actions: useMemo(() => {
37
- if (!actionsRender) return null;
38
- return actionsRender({
39
- originalNode: null,
40
- patch
41
- });
42
- }, [actionsRender, patch]),
52
+ actions,
43
53
  additions,
44
54
  body: /* @__PURE__ */ jsx(PatchDiff, {
45
- options: useMemo(() => getLobeDiffOptions({
46
- diffOptions,
47
- isDarkMode,
48
- viewMode
49
- }), [
50
- isDarkMode,
51
- viewMode,
52
- diffOptions
53
- ]),
55
+ options,
54
56
  patch
55
57
  }),
56
58
  className,
@@ -1 +1 @@
1
- {"version":3,"file":"PatchDiff.mjs","names":["PatchDiff","PierrePatchDiff"],"sources":["../../src/CodeDiff/PatchDiff.tsx"],"sourcesContent":["'use client';\n\nimport type { FileDiffOptions } from '@pierre/diffs';\nimport { PatchDiff as PierrePatchDiff } from '@pierre/diffs/react';\nimport { useThemeMode } from 'antd-style';\nimport { memo, useMemo } from 'react';\n\nimport { DiffPanel } from './DiffPanel';\nimport { getLobeDiffOptions, registerLobeDiffThemes } from './theme';\nimport type { PatchDiffProps } from './type';\n\nregisterLobeDiffThemes();\n\nconst countPatchChanges = (patch: string): { additions: number; deletions: number } => {\n const lines = patch.split('\\n');\n let additions = 0;\n let deletions = 0;\n\n for (const line of lines) {\n if (line.startsWith('+') && !line.startsWith('+++')) {\n additions++;\n } else if (line.startsWith('-') && !line.startsWith('---')) {\n deletions++;\n }\n }\n\n return { additions, deletions };\n};\n\nexport const PatchDiff = memo<PatchDiffProps>(\n ({\n patch,\n language,\n fileName,\n viewMode = 'split',\n showHeader = true,\n defaultExpand = true,\n fullFeatured = true,\n variant = 'filled',\n className,\n classNames,\n styles: customStyles,\n actionsRender,\n diffOptions,\n ...rest\n }) => {\n const { isDarkMode } = useThemeMode();\n\n const displayName = useMemo(() => {\n if (fileName) return fileName;\n // Try to extract filename from patch header\n const match = patch.match(/^(?:-{3}|\\+{3})\\s+(?:a\\/|b\\/)?(.+?)(?:\\t|$)/m);\n if (match?.[1]) return match[1];\n if (language) return language;\n return 'patch';\n }, [fileName, patch, language]);\n\n const { additions, deletions } = useMemo(() => countPatchChanges(patch), [patch]);\n\n const actions = useMemo(() => {\n if (!actionsRender) return null;\n return actionsRender({\n originalNode: null,\n patch,\n });\n }, [actionsRender, patch]);\n\n const options = useMemo<FileDiffOptions<string>>(\n () => getLobeDiffOptions({ diffOptions, isDarkMode, viewMode }),\n [isDarkMode, viewMode, diffOptions],\n );\n\n return (\n <DiffPanel\n actions={actions}\n additions={additions}\n body={<PierrePatchDiff options={options} patch={patch} />}\n className={className}\n classNames={classNames}\n dataCodeType=\"patch-diff\"\n defaultExpand={defaultExpand}\n deletions={deletions}\n displayName={displayName}\n fileName={fileName}\n fullFeatured={fullFeatured}\n showHeader={showHeader}\n styles={customStyles}\n variant={variant}\n {...rest}\n />\n );\n },\n);\n\nPatchDiff.displayName = 'PatchDiff';\n\nexport default PatchDiff;\n"],"mappings":";;;;;;;;AAWA,uBAAuB;AAEvB,MAAM,qBAAqB,UAA4D;CACrF,MAAM,QAAQ,MAAM,MAAM,IAAI;CAC9B,IAAI,YAAY;CAChB,IAAI,YAAY;CAEhB,KAAK,MAAM,QAAQ,OACjB,IAAI,KAAK,WAAW,GAAG,KAAK,CAAC,KAAK,WAAW,KAAK,GAChD;MACK,IAAI,KAAK,WAAW,GAAG,KAAK,CAAC,KAAK,WAAW,KAAK,GACvD;CAIJ,OAAO;EAAE;EAAW;CAAU;AAChC;AAEA,MAAaA,cAAY,MACtB,EACC,OACA,UACA,UACA,WAAW,SACX,aAAa,MACb,gBAAgB,MAChB,eAAe,MACf,UAAU,UACV,WACA,YACA,QAAQ,cACR,eACA,aACA,GAAG,WACC;CACJ,MAAM,EAAE,eAAe,aAAa;CAEpC,MAAM,cAAc,cAAc;EAChC,IAAI,UAAU,OAAO;EAErB,MAAM,QAAQ,MAAM,MAAM,8CAA8C;EACxE,IAAI,QAAQ,IAAI,OAAO,MAAM;EAC7B,IAAI,UAAU,OAAO;EACrB,OAAO;CACT,GAAG;EAAC;EAAU;EAAO;CAAQ,CAAC;CAE9B,MAAM,EAAE,WAAW,cAAc,cAAc,kBAAkB,KAAK,GAAG,CAAC,KAAK,CAAC;CAehF,OACE,oBAAC,WAAD;EACE,SAfY,cAAc;GAC5B,IAAI,CAAC,eAAe,OAAO;GAC3B,OAAO,cAAc;IACnB,cAAc;IACd;GACF,CAAC;EACH,GAAG,CAAC,eAAe,KAAK,CASL;EACJ;EACX,MAAM,oBAACC,WAAD;GAAiB,SATX,cACR,mBAAmB;IAAE;IAAa;IAAY;GAAS,CAAC,GAC9D;IAAC;IAAY;IAAU;GAAW,CAOM;GAAU;EAAQ,CAAA;EAC7C;EACC;EACZ,cAAa;EACE;EACJ;EACE;EACH;EACI;EACF;EACZ,QAAQ;EACC;EACT,GAAI;CACL,CAAA;AAEL,CACF;AAEA,YAAU,cAAc"}
1
+ {"version":3,"file":"PatchDiff.mjs","names":["PatchDiff","PierrePatchDiff"],"sources":["../../src/CodeDiff/PatchDiff.tsx"],"sourcesContent":["'use client';\n\nimport type { FileDiffOptions } from '@pierre/diffs';\nimport { PatchDiff as PierrePatchDiff } from '@pierre/diffs/react';\nimport { useThemeMode } from 'antd-style';\nimport { memo, useMemo } from 'react';\n\nimport { DiffPanel } from './DiffPanel';\nimport { getLobeDiffOptions, registerLobeDiffThemes } from './theme';\nimport type { PatchDiffProps } from './type';\n\nregisterLobeDiffThemes();\n\nconst countPatchChanges = (patch: string): { additions: number; deletions: number } => {\n const lines = patch.split('\\n');\n let additions = 0;\n let deletions = 0;\n\n for (const line of lines) {\n if (line.startsWith('+') && !line.startsWith('+++')) {\n additions++;\n } else if (line.startsWith('-') && !line.startsWith('---')) {\n deletions++;\n }\n }\n\n return { additions, deletions };\n};\n\nexport const PatchDiff = memo<PatchDiffProps>(\n ({\n patch,\n language,\n fileName,\n viewMode = 'split',\n showHeader = true,\n defaultExpand = true,\n fullFeatured = true,\n variant = 'filled',\n className,\n classNames,\n styles: customStyles,\n actionsRender,\n diffOptions,\n ...rest\n }) => {\n const { isDarkMode } = useThemeMode();\n\n const displayName = useMemo(() => {\n if (fileName) return fileName;\n // Try to extract filename from patch header\n const match = patch.match(/^(?:-{3}|\\+{3})\\s+(?:a\\/|b\\/)?(.+?)(?:\\t|$)/m);\n if (match?.[1]) return match[1];\n if (language) return language;\n return 'patch';\n }, [fileName, patch, language]);\n\n const { additions, deletions } = useMemo(() => countPatchChanges(patch), [patch]);\n\n const actions = useMemo(() => {\n if (!actionsRender) return null;\n return actionsRender({\n originalNode: null,\n patch,\n });\n }, [actionsRender, patch]);\n\n const options = useMemo<FileDiffOptions<string>>(\n () => getLobeDiffOptions({ diffOptions, isDarkMode, viewMode }),\n [isDarkMode, viewMode, diffOptions],\n );\n\n return (\n <DiffPanel\n actions={actions}\n additions={additions}\n body={<PierrePatchDiff options={options} patch={patch} />}\n className={className}\n classNames={classNames}\n dataCodeType=\"patch-diff\"\n defaultExpand={defaultExpand}\n deletions={deletions}\n displayName={displayName}\n fileName={fileName}\n fullFeatured={fullFeatured}\n showHeader={showHeader}\n styles={customStyles}\n variant={variant}\n {...rest}\n />\n );\n },\n);\n\nPatchDiff.displayName = 'PatchDiff';\n\nexport default PatchDiff;\n"],"mappings":";;;;;;;;AAWA,uBAAuB;AAEvB,MAAM,qBAAqB,UAA4D;CACrF,MAAM,QAAQ,MAAM,MAAM,IAAI;CAC9B,IAAI,YAAY;CAChB,IAAI,YAAY;CAEhB,KAAK,MAAM,QAAQ,OACjB,IAAI,KAAK,WAAW,GAAG,KAAK,CAAC,KAAK,WAAW,KAAK,GAChD;MACK,IAAI,KAAK,WAAW,GAAG,KAAK,CAAC,KAAK,WAAW,KAAK,GACvD;CAIJ,OAAO;EAAE;EAAW;CAAU;AAChC;AAEA,MAAaA,cAAY,MACtB,EACC,OACA,UACA,UACA,WAAW,SACX,aAAa,MACb,gBAAgB,MAChB,eAAe,MACf,UAAU,UACV,WACA,YACA,QAAQ,cACR,eACA,aACA,GAAG,WACC;CACJ,MAAM,EAAE,eAAe,aAAa;CAEpC,MAAM,cAAc,cAAc;EAChC,IAAI,UAAU,OAAO;EAErB,MAAM,QAAQ,MAAM,MAAM,8CAA8C;EACxE,IAAI,QAAQ,IAAI,OAAO,MAAM;EAC7B,IAAI,UAAU,OAAO;EACrB,OAAO;CACT,GAAG;EAAC;EAAU;EAAO;CAAQ,CAAC;CAE9B,MAAM,EAAE,WAAW,cAAc,cAAc,kBAAkB,KAAK,GAAG,CAAC,KAAK,CAAC;CAEhF,MAAM,UAAU,cAAc;EAC5B,IAAI,CAAC,eAAe,OAAO;EAC3B,OAAO,cAAc;GACnB,cAAc;GACd;EACF,CAAC;CACH,GAAG,CAAC,eAAe,KAAK,CAAC;CAEzB,MAAM,UAAU,cACR,mBAAmB;EAAE;EAAa;EAAY;CAAS,CAAC,GAC9D;EAAC;EAAY;EAAU;CAAW,CACpC;CAEA,OACE,oBAAC,WAAD;EACW;EACE;EACX,MAAM,oBAACC,WAAD;GAA0B;GAAgB;EAAQ,CAAA;EAC7C;EACC;EACZ,cAAa;EACE;EACJ;EACE;EACH;EACI;EACF;EACZ,QAAQ;EACC;EACT,GAAI;CACL,CAAA;AAEL,CACF;AAEA,YAAU,cAAc"}
@@ -17,7 +17,8 @@ const CopyButton = memo(({ active, content, size, icon, glass = true, onClick, .
17
17
  active: active || copied,
18
18
  icon: copied ? Check : Icon,
19
19
  onClick: async (e) => {
20
- await copyToClipboard(typeof content === "function" ? content() : content);
20
+ const resolvedContent = typeof content === "function" ? content() : content;
21
+ await copyToClipboard(resolvedContent);
21
22
  setCopied();
22
23
  onClick?.(e);
23
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"CopyButton.mjs","names":[],"sources":["../../src/CopyButton/CopyButton.tsx"],"sourcesContent":["'use client';\n\nimport { Check, Copy } from 'lucide-react';\nimport { memo } from 'react';\n\nimport ActionIcon from '@/ActionIcon';\nimport { useCopied } from '@/hooks/useCopied';\nimport { copyToClipboard } from '@/utils/copyToClipboard';\n\nimport type { CopyButtonProps } from './type';\n\nconst CopyButton = memo<CopyButtonProps>(\n ({ active, content, size, icon, glass = true, onClick, ...rest }) => {\n const { copied, setCopied } = useCopied();\n const Icon = icon || Copy;\n\n return (\n <ActionIcon\n glass={glass}\n size={size}\n title={'Copy'}\n {...rest}\n active={active || copied}\n icon={copied ? Check : Icon}\n onClick={async (e) => {\n const resolvedContent = typeof content === 'function' ? content() : content;\n await copyToClipboard(resolvedContent);\n setCopied();\n onClick?.(e);\n }}\n />\n );\n },\n);\n\nCopyButton.displayName = 'CopyButton';\n\nexport default CopyButton;\n"],"mappings":";;;;;;;;AAWA,MAAM,aAAa,MAChB,EAAE,QAAQ,SAAS,MAAM,MAAM,QAAQ,MAAM,SAAS,GAAG,WAAW;CACnE,MAAM,EAAE,QAAQ,cAAc,UAAU;CACxC,MAAM,OAAO,QAAQ;CAErB,OACE,oBAAC,YAAD;EACS;EACD;EACN,OAAO;EACP,GAAI;EACJ,QAAQ,UAAU;EAClB,MAAM,SAAS,QAAQ;EACvB,SAAS,OAAO,MAAM;GAEpB,MAAM,gBADkB,OAAO,YAAY,aAAa,QAAQ,IAAI,OAC/B;GACrC,UAAU;GACV,UAAU,CAAC;EACb;CACD,CAAA;AAEL,CACF;AAEA,WAAW,cAAc"}
1
+ {"version":3,"file":"CopyButton.mjs","names":[],"sources":["../../src/CopyButton/CopyButton.tsx"],"sourcesContent":["'use client';\n\nimport { Check, Copy } from 'lucide-react';\nimport { memo } from 'react';\n\nimport ActionIcon from '@/ActionIcon';\nimport { useCopied } from '@/hooks/useCopied';\nimport { copyToClipboard } from '@/utils/copyToClipboard';\n\nimport type { CopyButtonProps } from './type';\n\nconst CopyButton = memo<CopyButtonProps>(\n ({ active, content, size, icon, glass = true, onClick, ...rest }) => {\n const { copied, setCopied } = useCopied();\n const Icon = icon || Copy;\n\n return (\n <ActionIcon\n glass={glass}\n size={size}\n title={'Copy'}\n {...rest}\n active={active || copied}\n icon={copied ? Check : Icon}\n onClick={async (e) => {\n const resolvedContent = typeof content === 'function' ? content() : content;\n await copyToClipboard(resolvedContent);\n setCopied();\n onClick?.(e);\n }}\n />\n );\n },\n);\n\nCopyButton.displayName = 'CopyButton';\n\nexport default CopyButton;\n"],"mappings":";;;;;;;;AAWA,MAAM,aAAa,MAChB,EAAE,QAAQ,SAAS,MAAM,MAAM,QAAQ,MAAM,SAAS,GAAG,WAAW;CACnE,MAAM,EAAE,QAAQ,cAAc,UAAU;CACxC,MAAM,OAAO,QAAQ;CAErB,OACE,oBAAC,YAAD;EACS;EACD;EACN,OAAO;EACP,GAAI;EACJ,QAAQ,UAAU;EAClB,MAAM,SAAS,QAAQ;EACvB,SAAS,OAAO,MAAM;GACpB,MAAM,kBAAkB,OAAO,YAAY,aAAa,QAAQ,IAAI;GACpE,MAAM,gBAAgB,eAAe;GACrC,UAAU;GACV,UAAU,CAAC;EACb;CACD,CAAA;AAEL,CACF;AAEA,WAAW,cAAc"}
@@ -9,49 +9,50 @@ import { Select } from "antd";
9
9
  import { bundledLanguagesInfo } from "shiki";
10
10
  //#region src/Highlighter/LangSelect.tsx
11
11
  const LangSelect = memo(({ ...rest }) => {
12
+ const options = useMemo(() => [{
13
+ aliases: ["text", "txt"],
14
+ label: /* @__PURE__ */ jsxs(FlexBasic_default, {
15
+ horizontal: true,
16
+ align: "center",
17
+ gap: 4,
18
+ children: [/* @__PURE__ */ jsx(MaterialFileTypeIcon, {
19
+ fallbackUnknownType: false,
20
+ filename: `*.txt`,
21
+ size: 18,
22
+ type: "file",
23
+ variant: "raw"
24
+ }), /* @__PURE__ */ jsx(Text, {
25
+ ellipsis: true,
26
+ fontSize: 13,
27
+ children: "Plaintext"
28
+ })]
29
+ }),
30
+ value: "plaintext"
31
+ }, ...bundledLanguagesInfo.map((item) => ({
32
+ aliases: item.aliases,
33
+ label: /* @__PURE__ */ jsxs(FlexBasic_default, {
34
+ horizontal: true,
35
+ align: "center",
36
+ gap: 4,
37
+ children: [/* @__PURE__ */ jsx(MaterialFileTypeIcon, {
38
+ fallbackUnknownType: false,
39
+ filename: `*.${item?.aliases?.[0] || item.id}`,
40
+ size: 18,
41
+ type: "file",
42
+ variant: "raw"
43
+ }), /* @__PURE__ */ jsx(Text, {
44
+ ellipsis: true,
45
+ fontSize: 13,
46
+ children: item.name
47
+ })]
48
+ }),
49
+ title: (item.aliases || [item.id]).filter(Boolean).map((item) => `*.${item}`).join(","),
50
+ value: item.id
51
+ }))], []);
12
52
  return /* @__PURE__ */ jsx(Select, {
13
53
  showSearch: true,
14
54
  className: "languageTitle",
15
- options: useMemo(() => [{
16
- aliases: ["text", "txt"],
17
- label: /* @__PURE__ */ jsxs(FlexBasic_default, {
18
- horizontal: true,
19
- align: "center",
20
- gap: 4,
21
- children: [/* @__PURE__ */ jsx(MaterialFileTypeIcon, {
22
- fallbackUnknownType: false,
23
- filename: `*.txt`,
24
- size: 18,
25
- type: "file",
26
- variant: "raw"
27
- }), /* @__PURE__ */ jsx(Text, {
28
- ellipsis: true,
29
- fontSize: 13,
30
- children: "Plaintext"
31
- })]
32
- }),
33
- value: "plaintext"
34
- }, ...bundledLanguagesInfo.map((item) => ({
35
- aliases: item.aliases,
36
- label: /* @__PURE__ */ jsxs(FlexBasic_default, {
37
- horizontal: true,
38
- align: "center",
39
- gap: 4,
40
- children: [/* @__PURE__ */ jsx(MaterialFileTypeIcon, {
41
- fallbackUnknownType: false,
42
- filename: `*.${item?.aliases?.[0] || item.id}`,
43
- size: 18,
44
- type: "file",
45
- variant: "raw"
46
- }), /* @__PURE__ */ jsx(Text, {
47
- ellipsis: true,
48
- fontSize: 13,
49
- children: item.name
50
- })]
51
- }),
52
- title: (item.aliases || [item.id]).filter(Boolean).map((item) => `*.${item}`).join(","),
53
- value: item.id
54
- }))], []),
55
+ options,
55
56
  size: "small",
56
57
  suffixIcon: false,
57
58
  variant: "borderless",
@@ -1 +1 @@
1
- {"version":3,"file":"LangSelect.mjs","names":["Flexbox"],"sources":["../../src/Highlighter/LangSelect.tsx"],"sourcesContent":["'use client';\n\nimport { Select, type SelectProps } from 'antd';\nimport { memo, useMemo } from 'react';\nimport { bundledLanguagesInfo } from 'shiki';\n\nimport { Flexbox } from '@/Flex';\nimport MaterialFileTypeIcon from '@/MaterialFileTypeIcon';\nimport Text from '@/Text';\nimport { stopPropagation } from '@/utils/dom';\n\nexport const LangSelect = memo<Omit<SelectProps, 'options'>>(({ ...rest }) => {\n const options = useMemo(\n () => [\n {\n aliases: ['text', 'txt'],\n label: (\n <Flexbox horizontal align={'center'} gap={4}>\n <MaterialFileTypeIcon\n fallbackUnknownType={false}\n filename={`*.txt`}\n size={18}\n type={'file'}\n variant={'raw'}\n />\n <Text ellipsis fontSize={13}>\n Plaintext\n </Text>\n </Flexbox>\n ),\n value: 'plaintext',\n },\n ...bundledLanguagesInfo.map((item) => ({\n aliases: item.aliases,\n label: (\n <Flexbox horizontal align={'center'} gap={4}>\n <MaterialFileTypeIcon\n fallbackUnknownType={false}\n filename={`*.${item?.aliases?.[0] || item.id}`}\n size={18}\n type={'file'}\n variant={'raw'}\n />\n <Text ellipsis fontSize={13}>\n {item.name}\n </Text>\n </Flexbox>\n ),\n title: (item.aliases || [item.id])\n .filter(Boolean)\n .map((item) => `*.${item}`)\n .join(','),\n value: item.id,\n })),\n ],\n [],\n );\n\n return (\n <Select\n showSearch\n className={'languageTitle'}\n options={options}\n size={'small'}\n suffixIcon={false}\n variant={'borderless'}\n style={{\n maxWidth: 240,\n width: '100%',\n }}\n onClick={stopPropagation}\n {...rest}\n />\n );\n});\n\nexport default LangSelect;\n"],"mappings":";;;;;;;;;;AAWA,MAAa,aAAa,MAAoC,EAAE,GAAG,WAAW;CA+C5E,OACE,oBAAC,QAAD;EACE,YAAA;EACA,WAAW;EACX,SAlDY,cACR,CACJ;GACE,SAAS,CAAC,QAAQ,KAAK;GACvB,OACE,qBAACA,mBAAD;IAAS,YAAA;IAAW,OAAO;IAAU,KAAK;IAA1C,UAAA,CACE,oBAAC,sBAAD;KACE,qBAAqB;KACrB,UAAU;KACV,MAAM;KACN,MAAM;KACN,SAAS;IACV,CAAA,GACD,oBAAC,MAAD;KAAM,UAAA;KAAS,UAAU;KAAI,UAAA;IAEvB,CAAA,CACC;;GAEX,OAAO;EACT,GACA,GAAG,qBAAqB,KAAK,UAAU;GACrC,SAAS,KAAK;GACd,OACE,qBAACA,mBAAD;IAAS,YAAA;IAAW,OAAO;IAAU,KAAK;IAA1C,UAAA,CACE,oBAAC,sBAAD;KACE,qBAAqB;KACrB,UAAU,KAAK,MAAM,UAAU,MAAM,KAAK;KAC1C,MAAM;KACN,MAAM;KACN,SAAS;IACV,CAAA,GACD,oBAAC,MAAD;KAAM,UAAA;KAAS,UAAU;KACtB,UAAA,KAAK;IACF,CAAA,CACC;;GAEX,QAAQ,KAAK,WAAW,CAAC,KAAK,EAAE,EAAA,CAC7B,OAAO,OAAO,CAAC,CACf,KAAK,SAAS,KAAK,MAAM,CAAC,CAC1B,KAAK,GAAG;GACX,OAAO,KAAK;EACd,EAAE,CACJ,GACA,CAAC,CAOgB;EACf,MAAM;EACN,YAAY;EACZ,SAAS;EACT,OAAO;GACL,UAAU;GACV,OAAO;EACT;EACA,SAAS;EACT,GAAI;CACL,CAAA;AAEL,CAAC"}
1
+ {"version":3,"file":"LangSelect.mjs","names":["Flexbox"],"sources":["../../src/Highlighter/LangSelect.tsx"],"sourcesContent":["'use client';\n\nimport { Select, type SelectProps } from 'antd';\nimport { memo, useMemo } from 'react';\nimport { bundledLanguagesInfo } from 'shiki';\n\nimport { Flexbox } from '@/Flex';\nimport MaterialFileTypeIcon from '@/MaterialFileTypeIcon';\nimport Text from '@/Text';\nimport { stopPropagation } from '@/utils/dom';\n\nexport const LangSelect = memo<Omit<SelectProps, 'options'>>(({ ...rest }) => {\n const options = useMemo(\n () => [\n {\n aliases: ['text', 'txt'],\n label: (\n <Flexbox horizontal align={'center'} gap={4}>\n <MaterialFileTypeIcon\n fallbackUnknownType={false}\n filename={`*.txt`}\n size={18}\n type={'file'}\n variant={'raw'}\n />\n <Text ellipsis fontSize={13}>\n Plaintext\n </Text>\n </Flexbox>\n ),\n value: 'plaintext',\n },\n ...bundledLanguagesInfo.map((item) => ({\n aliases: item.aliases,\n label: (\n <Flexbox horizontal align={'center'} gap={4}>\n <MaterialFileTypeIcon\n fallbackUnknownType={false}\n filename={`*.${item?.aliases?.[0] || item.id}`}\n size={18}\n type={'file'}\n variant={'raw'}\n />\n <Text ellipsis fontSize={13}>\n {item.name}\n </Text>\n </Flexbox>\n ),\n title: (item.aliases || [item.id])\n .filter(Boolean)\n .map((item) => `*.${item}`)\n .join(','),\n value: item.id,\n })),\n ],\n [],\n );\n\n return (\n <Select\n showSearch\n className={'languageTitle'}\n options={options}\n size={'small'}\n suffixIcon={false}\n variant={'borderless'}\n style={{\n maxWidth: 240,\n width: '100%',\n }}\n onClick={stopPropagation}\n {...rest}\n />\n );\n});\n\nexport default LangSelect;\n"],"mappings":";;;;;;;;;;AAWA,MAAa,aAAa,MAAoC,EAAE,GAAG,WAAW;CAC5E,MAAM,UAAU,cACR,CACJ;EACE,SAAS,CAAC,QAAQ,KAAK;EACvB,OACE,qBAACA,mBAAD;GAAS,YAAA;GAAW,OAAO;GAAU,KAAK;GAA1C,UAAA,CACE,oBAAC,sBAAD;IACE,qBAAqB;IACrB,UAAU;IACV,MAAM;IACN,MAAM;IACN,SAAS;GACV,CAAA,GACD,oBAAC,MAAD;IAAM,UAAA;IAAS,UAAU;IAAI,UAAA;GAEvB,CAAA,CACC;;EAEX,OAAO;CACT,GACA,GAAG,qBAAqB,KAAK,UAAU;EACrC,SAAS,KAAK;EACd,OACE,qBAACA,mBAAD;GAAS,YAAA;GAAW,OAAO;GAAU,KAAK;GAA1C,UAAA,CACE,oBAAC,sBAAD;IACE,qBAAqB;IACrB,UAAU,KAAK,MAAM,UAAU,MAAM,KAAK;IAC1C,MAAM;IACN,MAAM;IACN,SAAS;GACV,CAAA,GACD,oBAAC,MAAD;IAAM,UAAA;IAAS,UAAU;IACtB,UAAA,KAAK;GACF,CAAA,CACC;;EAEX,QAAQ,KAAK,WAAW,CAAC,KAAK,EAAE,EAAA,CAC7B,OAAO,OAAO,CAAC,CACf,KAAK,SAAS,KAAK,MAAM,CAAC,CAC1B,KAAK,GAAG;EACX,OAAO,KAAK;CACd,EAAE,CACJ,GACA,CAAC,CACH;CAEA,OACE,oBAAC,QAAD;EACE,YAAA;EACA,WAAW;EACF;EACT,MAAM;EACN,YAAY;EACZ,SAAS;EACT,OAAO;GACL,UAAU;GACV,OAAO;EACT;EACA,SAAS;EACT,GAAI;CACL,CAAA;AAEL,CAAC"}
@@ -15,8 +15,9 @@ const StaticRenderer = memo(({ children, className, enableTransformer, fallbackC
15
15
  language,
16
16
  theme
17
17
  });
18
+ const containerClassName = typeof data === "string" && data.length > 0 ? className : fallbackClassName;
18
19
  return /* @__PURE__ */ jsx("div", {
19
- className: typeof data === "string" && data.length > 0 ? className : fallbackClassName,
20
+ className: containerClassName,
20
21
  dir: "ltr",
21
22
  style,
22
23
  dangerouslySetInnerHTML: { __html: data || `<pre><code>${escapeHtml(safeChildren)}</code></pre>` }
@@ -1 +1 @@
1
- {"version":3,"file":"StaticRenderer.mjs","names":[],"sources":["../../../src/Highlighter/SyntaxHighlighter/StaticRenderer.tsx"],"sourcesContent":["'use client';\n\nimport { type CSSProperties, memo } from 'react';\nimport type { BuiltinTheme } from 'shiki';\n\nimport { useHighlight } from '@/hooks/useHighlight';\n\ninterface StaticRendererProps {\n children: string;\n className?: string;\n enableTransformer?: boolean;\n fallbackClassName?: string;\n language: string;\n style?: CSSProperties;\n theme?: BuiltinTheme;\n}\n\n// Escape HTML for fallback to prevent XSS\nconst escapeHtml = (str: string) =>\n str\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&#039;');\n\n/**\n * Static renderer for syntax highlighting without animation\n * Uses useHighlight hook to generate HTML and renders it directly\n */\nconst StaticRenderer = memo<StaticRendererProps>(\n ({ children, className, enableTransformer, fallbackClassName, language, style, theme }) => {\n // Safely handle empty or invalid children\n const safeChildren = children ?? '';\n\n const data = useHighlight(safeChildren, {\n enableTransformer,\n language,\n theme,\n });\n\n const hasData = typeof data === 'string' && data.length > 0;\n const containerClassName = hasData ? className : fallbackClassName;\n\n return (\n <div\n className={containerClassName}\n dir=\"ltr\"\n style={style}\n dangerouslySetInnerHTML={{\n __html: data || `<pre><code>${escapeHtml(safeChildren)}</code></pre>`,\n }}\n />\n );\n },\n);\n\nStaticRenderer.displayName = 'StaticRenderer';\n\nexport default StaticRenderer;\n"],"mappings":";;;;;AAkBA,MAAM,cAAc,QAClB,IACG,WAAW,KAAK,OAAO,CAAC,CACxB,WAAW,KAAK,MAAM,CAAC,CACvB,WAAW,KAAK,MAAM,CAAC,CACvB,WAAW,MAAK,QAAQ,CAAC,CACzB,WAAW,KAAK,QAAQ;;;;;AAM7B,MAAM,iBAAiB,MACpB,EAAE,UAAU,WAAW,mBAAmB,mBAAmB,UAAU,OAAO,YAAY;CAEzF,MAAM,eAAe,YAAY;CAEjC,MAAM,OAAO,aAAa,cAAc;EACtC;EACA;EACA;CACF,CAAC;CAKD,OACE,oBAAC,OAAD;EACE,WALY,OAAO,SAAS,YAAY,KAAK,SAAS,IACrB,YAAY;EAK7C,KAAI;EACG;EACP,yBAAyB,EACvB,QAAQ,QAAQ,cAAc,WAAW,YAAY,EAAE,eACzD;CACD,CAAA;AAEL,CACF;AAEA,eAAe,cAAc"}
1
+ {"version":3,"file":"StaticRenderer.mjs","names":[],"sources":["../../../src/Highlighter/SyntaxHighlighter/StaticRenderer.tsx"],"sourcesContent":["'use client';\n\nimport { type CSSProperties, memo } from 'react';\nimport type { BuiltinTheme } from 'shiki';\n\nimport { useHighlight } from '@/hooks/useHighlight';\n\ninterface StaticRendererProps {\n children: string;\n className?: string;\n enableTransformer?: boolean;\n fallbackClassName?: string;\n language: string;\n style?: CSSProperties;\n theme?: BuiltinTheme;\n}\n\n// Escape HTML for fallback to prevent XSS\nconst escapeHtml = (str: string) =>\n str\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&#039;');\n\n/**\n * Static renderer for syntax highlighting without animation\n * Uses useHighlight hook to generate HTML and renders it directly\n */\nconst StaticRenderer = memo<StaticRendererProps>(\n ({ children, className, enableTransformer, fallbackClassName, language, style, theme }) => {\n // Safely handle empty or invalid children\n const safeChildren = children ?? '';\n\n const data = useHighlight(safeChildren, {\n enableTransformer,\n language,\n theme,\n });\n\n const hasData = typeof data === 'string' && data.length > 0;\n const containerClassName = hasData ? className : fallbackClassName;\n\n return (\n <div\n className={containerClassName}\n dir=\"ltr\"\n style={style}\n dangerouslySetInnerHTML={{\n __html: data || `<pre><code>${escapeHtml(safeChildren)}</code></pre>`,\n }}\n />\n );\n },\n);\n\nStaticRenderer.displayName = 'StaticRenderer';\n\nexport default StaticRenderer;\n"],"mappings":";;;;;AAkBA,MAAM,cAAc,QAClB,IACG,WAAW,KAAK,OAAO,CAAC,CACxB,WAAW,KAAK,MAAM,CAAC,CACvB,WAAW,KAAK,MAAM,CAAC,CACvB,WAAW,MAAK,QAAQ,CAAC,CACzB,WAAW,KAAK,QAAQ;;;;;AAM7B,MAAM,iBAAiB,MACpB,EAAE,UAAU,WAAW,mBAAmB,mBAAmB,UAAU,OAAO,YAAY;CAEzF,MAAM,eAAe,YAAY;CAEjC,MAAM,OAAO,aAAa,cAAc;EACtC;EACA;EACA;CACF,CAAC;CAGD,MAAM,qBADU,OAAO,SAAS,YAAY,KAAK,SAAS,IACrB,YAAY;CAEjD,OACE,oBAAC,OAAD;EACE,WAAW;EACX,KAAI;EACG;EACP,yBAAyB,EACvB,QAAQ,QAAQ,cAAc,WAAW,YAAY,EAAE,eACzD;CACD,CAAA;AAEL,CACF;AAEA,eAAe,cAAc"}
@@ -62,7 +62,9 @@ const HotkeyInput = memo(({ value = "", defaultValue = "", resetValue = "", onCh
62
62
  const keysString = keys.join("+");
63
63
  const checkHotkeyConflict = useCallback((newHotkey) => {
64
64
  return hotkeyConflicts.filter((conflictKey) => conflictKey !== resetValue).some((conflictKey) => {
65
- return isEqual(splitKeysByPlus(newHotkey), splitKeysByPlus(conflictKey));
65
+ const newKeys = splitKeysByPlus(newHotkey);
66
+ const conflictKeys = splitKeysByPlus(conflictKey);
67
+ return isEqual(newKeys, conflictKeys);
66
68
  });
67
69
  }, [hotkeyConflicts]);
68
70
  useEffect(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"HotkeyInput.mjs","names":["hotkeyMessages","useControlledState","Flexbox"],"sources":["../../src/HotkeyInput/HotkeyInput.tsx"],"sourcesContent":["'use client';\n\nimport { type InputRef } from 'antd';\nimport { cx, useThemeMode } from 'antd-style';\nimport { isEqual } from 'es-toolkit/compat';\nimport { Undo2Icon, XIcon } from 'lucide-react';\nimport {\n type FocusEvent,\n memo,\n type MouseEvent,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { useHotkeys, useRecordHotkeys } from 'react-hotkeys-hook';\nimport useControlledState from 'use-merge-value';\n\nimport ActionIcon from '@/ActionIcon';\nimport { Flexbox } from '@/Flex';\nimport Hotkey from '@/Hotkey';\nimport { checkIsAppleDevice, NORMATIVE_MODIFIER, splitKeysByPlus } from '@/Hotkey/utils';\nimport hotkeyMessages from '@/i18n/resources/en/hotkey';\nimport { useTranslation } from '@/i18n/useTranslation';\n\nimport { styles, variants } from './style';\nimport { type HotkeyInputProps } from './type';\n\nconst HotkeyInput = memo<HotkeyInputProps>(\n ({\n value = '',\n defaultValue = '',\n resetValue = '',\n onChange,\n onClear,\n onConflict,\n placeholder,\n disabled,\n shadow,\n allowClear,\n allowReset = true,\n style,\n className,\n hotkeyConflicts = [],\n variant,\n texts,\n isApple,\n onBlur,\n onReset,\n onFocus,\n }) => {\n const [isFocused, setIsFocused] = useState(false);\n const [hasConflict, setHasConflict] = useState(false);\n const [hasInvalidCombination, setHasInvalidCombination] = useState(false);\n const inputRef = useRef<InputRef>(null);\n const { isDarkMode } = useThemeMode();\n const { t } = useTranslation(hotkeyMessages);\n const isAppleDevice = useMemo(() => checkIsAppleDevice(isApple), [isApple]);\n const [hotkeyValue, setHotkeyValue] = useControlledState(defaultValue, {\n defaultValue,\n onChange,\n value,\n });\n\n // 使用 useRecordHotkeys 处理快捷键录入\n const [recordedKeys, { start, stop, isRecording, resetKeys }] = useRecordHotkeys();\n\n useHotkeys(\n '*',\n () => {\n inputRef.current?.blur();\n },\n {\n enableOnContentEditable: true,\n enableOnFormTags: true,\n enabled: isRecording && !disabled,\n keydown: false,\n keyup: true,\n preventDefault: true,\n },\n );\n\n // 处理按键,保证格式正确:修饰键在前,最多一个非修饰键在后\n const formatKeys = useCallback((keysSet: Set<string>) => {\n const modifiers: string[] = [];\n const normalKeys: string[] = [];\n\n for (const key of keysSet) {\n // 处理不同表示的修饰键\n const normalizedKey: any = key.toLowerCase();\n if (NORMATIVE_MODIFIER.includes(normalizedKey)) {\n // 统一修饰键表示\n if (\n (!isAppleDevice && normalizedKey === 'ctrl') ||\n (isAppleDevice && normalizedKey === 'meta')\n ) {\n if (!modifiers.includes('mod')) modifiers.push('mod');\n } else if (!modifiers.includes(normalizedKey)) {\n modifiers.push(normalizedKey);\n }\n } else {\n normalKeys.push(key);\n }\n }\n\n // 至少需要一个修饰键\n if (modifiers.length === 0 && normalKeys.length > 0) {\n return { isValid: false, keys: [] };\n }\n\n // 只允许一个非修饰键,如果有多个,只保留最后一个\n const finalKey = normalKeys.length > 0 ? [normalKeys.at(-1)] : [];\n const shortcuts = [modifiers, finalKey];\n\n return {\n // 组合必须包含至少一个按键\n isValid: shortcuts.every((k) => k.length > 0),\n keys: shortcuts.flat(),\n };\n }, []);\n\n // 获取格式化后的按键字符串\n const { isValid, keys } = formatKeys(recordedKeys);\n const keysString = keys.join('+');\n\n // 检查快捷键冲突\n const checkHotkeyConflict = useCallback(\n (newHotkey: string): boolean => {\n return hotkeyConflicts\n .filter((conflictKey) => conflictKey !== resetValue)\n .some((conflictKey) => {\n const newKeys = splitKeysByPlus(newHotkey);\n const conflictKeys = splitKeysByPlus(conflictKey);\n return isEqual(newKeys, conflictKeys);\n });\n },\n [hotkeyConflicts],\n );\n\n // 当按键组合完成时处理结果\n useEffect(() => {\n if (recordedKeys.size > 0 && !isRecording) {\n if (!isValid) {\n setHasInvalidCombination(true);\n setHasConflict(false);\n return;\n }\n\n setHasInvalidCombination(false);\n const newKeysString = keysString;\n\n // 检查冲突\n const conflict = checkHotkeyConflict(newKeysString);\n if (conflict) {\n setHasConflict(true);\n onConflict?.(newKeysString);\n } else {\n setHasConflict(false);\n setHotkeyValue?.(newKeysString);\n }\n }\n }, [\n recordedKeys,\n isRecording,\n isValid,\n keysString,\n checkHotkeyConflict,\n setHotkeyValue,\n onConflict,\n ]);\n\n // 处理输入框焦点\n const handleFocus = (e: FocusEvent<HTMLInputElement>) => {\n if (disabled) return;\n setIsFocused(true);\n setHasConflict(false);\n setHasInvalidCombination(false);\n start(); // 开始记录\n onFocus?.(e);\n };\n\n const handleBlur = (e: FocusEvent<HTMLInputElement>) => {\n setIsFocused(false);\n stop(); // 停止记录\n onBlur?.(e);\n };\n\n const handleClear = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setHotkeyValue?.('');\n resetKeys();\n setHasConflict(false);\n setHasInvalidCombination(false);\n setIsFocused(false);\n stop();\n onClear?.(hotkeyValue);\n };\n\n // 重置功能\n const handleReset = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setHotkeyValue?.(resetValue);\n resetKeys();\n setHasConflict(false);\n setHasInvalidCombination(false);\n setIsFocused(false);\n stop(); // 停止记录\n onReset?.(hotkeyValue, resetValue);\n };\n\n const handleClick = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (disabled || isFocused) return;\n inputRef.current?.focus();\n };\n\n const placeholderText = placeholder ?? t('hotkey.placeholder');\n const resetTitle = texts?.reset ?? t('hotkey.reset');\n const clearTitle = texts?.clear ?? t('hotkey.clear');\n const conflictText = texts?.conflicts ?? t('hotkey.conflict');\n const invalidText = texts?.invalidCombination ?? t('hotkey.invalidCombination');\n\n return (\n <Flexbox\n className={className}\n gap={8}\n style={{\n position: 'relative',\n ...style,\n }}\n >\n <Flexbox\n horizontal\n align={'center'}\n justify={'space-between'}\n className={cx(\n variants({\n disabled,\n error: hasConflict || hasInvalidCombination,\n focused: isFocused,\n shadow,\n variant: variant || (isDarkMode ? 'filled' : 'outlined'),\n }),\n )}\n onClick={handleClick}\n >\n <div style={{ pointerEvents: 'none' }}>\n {isRecording ? (\n <span className={styles.placeholder}>\n {keys.length > 0 ? <Hotkey keys={keysString} /> : placeholderText}\n </span>\n ) : hotkeyValue ? (\n <Hotkey keys={hotkeyValue} />\n ) : (\n <span className={styles.placeholder}>{placeholderText}</span>\n )}\n </div>\n\n {/* 隐藏的输入框,用于接收焦点 */}\n <input\n readOnly\n className={styles.hiddenInput}\n disabled={disabled}\n ref={inputRef as any}\n style={{ pointerEvents: 'none' }}\n onBlur={handleBlur}\n onFocus={handleFocus}\n />\n\n {!isFocused && hotkeyValue && !disabled && (allowReset || allowClear) && (\n <Flexbox horizontal gap={4}>\n {allowReset && hotkeyValue !== resetValue && (\n <ActionIcon\n icon={Undo2Icon}\n size={'small'}\n title={resetTitle}\n variant={'filled'}\n onClick={handleReset}\n />\n )}\n {allowClear && (\n <ActionIcon\n icon={XIcon}\n size={'small'}\n title={clearTitle}\n variant={'filled'}\n onClick={handleClear}\n />\n )}\n </Flexbox>\n )}\n </Flexbox>\n {hasConflict && <div className={styles.errorText}>{conflictText}</div>}\n {hasInvalidCombination && <div className={styles.errorText}>{invalidText}</div>}\n </Flexbox>\n );\n },\n);\n\nHotkeyInput.displayName = 'HotkeyInput';\n\nexport default HotkeyInput;\n"],"mappings":"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"}
1
+ {"version":3,"file":"HotkeyInput.mjs","names":["hotkeyMessages","useControlledState","Flexbox"],"sources":["../../src/HotkeyInput/HotkeyInput.tsx"],"sourcesContent":["'use client';\n\nimport { type InputRef } from 'antd';\nimport { cx, useThemeMode } from 'antd-style';\nimport { isEqual } from 'es-toolkit/compat';\nimport { Undo2Icon, XIcon } from 'lucide-react';\nimport {\n type FocusEvent,\n memo,\n type MouseEvent,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { useHotkeys, useRecordHotkeys } from 'react-hotkeys-hook';\nimport useControlledState from 'use-merge-value';\n\nimport ActionIcon from '@/ActionIcon';\nimport { Flexbox } from '@/Flex';\nimport Hotkey from '@/Hotkey';\nimport { checkIsAppleDevice, NORMATIVE_MODIFIER, splitKeysByPlus } from '@/Hotkey/utils';\nimport hotkeyMessages from '@/i18n/resources/en/hotkey';\nimport { useTranslation } from '@/i18n/useTranslation';\n\nimport { styles, variants } from './style';\nimport { type HotkeyInputProps } from './type';\n\nconst HotkeyInput = memo<HotkeyInputProps>(\n ({\n value = '',\n defaultValue = '',\n resetValue = '',\n onChange,\n onClear,\n onConflict,\n placeholder,\n disabled,\n shadow,\n allowClear,\n allowReset = true,\n style,\n className,\n hotkeyConflicts = [],\n variant,\n texts,\n isApple,\n onBlur,\n onReset,\n onFocus,\n }) => {\n const [isFocused, setIsFocused] = useState(false);\n const [hasConflict, setHasConflict] = useState(false);\n const [hasInvalidCombination, setHasInvalidCombination] = useState(false);\n const inputRef = useRef<InputRef>(null);\n const { isDarkMode } = useThemeMode();\n const { t } = useTranslation(hotkeyMessages);\n const isAppleDevice = useMemo(() => checkIsAppleDevice(isApple), [isApple]);\n const [hotkeyValue, setHotkeyValue] = useControlledState(defaultValue, {\n defaultValue,\n onChange,\n value,\n });\n\n // 使用 useRecordHotkeys 处理快捷键录入\n const [recordedKeys, { start, stop, isRecording, resetKeys }] = useRecordHotkeys();\n\n useHotkeys(\n '*',\n () => {\n inputRef.current?.blur();\n },\n {\n enableOnContentEditable: true,\n enableOnFormTags: true,\n enabled: isRecording && !disabled,\n keydown: false,\n keyup: true,\n preventDefault: true,\n },\n );\n\n // 处理按键,保证格式正确:修饰键在前,最多一个非修饰键在后\n const formatKeys = useCallback((keysSet: Set<string>) => {\n const modifiers: string[] = [];\n const normalKeys: string[] = [];\n\n for (const key of keysSet) {\n // 处理不同表示的修饰键\n const normalizedKey: any = key.toLowerCase();\n if (NORMATIVE_MODIFIER.includes(normalizedKey)) {\n // 统一修饰键表示\n if (\n (!isAppleDevice && normalizedKey === 'ctrl') ||\n (isAppleDevice && normalizedKey === 'meta')\n ) {\n if (!modifiers.includes('mod')) modifiers.push('mod');\n } else if (!modifiers.includes(normalizedKey)) {\n modifiers.push(normalizedKey);\n }\n } else {\n normalKeys.push(key);\n }\n }\n\n // 至少需要一个修饰键\n if (modifiers.length === 0 && normalKeys.length > 0) {\n return { isValid: false, keys: [] };\n }\n\n // 只允许一个非修饰键,如果有多个,只保留最后一个\n const finalKey = normalKeys.length > 0 ? [normalKeys.at(-1)] : [];\n const shortcuts = [modifiers, finalKey];\n\n return {\n // 组合必须包含至少一个按键\n isValid: shortcuts.every((k) => k.length > 0),\n keys: shortcuts.flat(),\n };\n }, []);\n\n // 获取格式化后的按键字符串\n const { isValid, keys } = formatKeys(recordedKeys);\n const keysString = keys.join('+');\n\n // 检查快捷键冲突\n const checkHotkeyConflict = useCallback(\n (newHotkey: string): boolean => {\n return hotkeyConflicts\n .filter((conflictKey) => conflictKey !== resetValue)\n .some((conflictKey) => {\n const newKeys = splitKeysByPlus(newHotkey);\n const conflictKeys = splitKeysByPlus(conflictKey);\n return isEqual(newKeys, conflictKeys);\n });\n },\n [hotkeyConflicts],\n );\n\n // 当按键组合完成时处理结果\n useEffect(() => {\n if (recordedKeys.size > 0 && !isRecording) {\n if (!isValid) {\n setHasInvalidCombination(true);\n setHasConflict(false);\n return;\n }\n\n setHasInvalidCombination(false);\n const newKeysString = keysString;\n\n // 检查冲突\n const conflict = checkHotkeyConflict(newKeysString);\n if (conflict) {\n setHasConflict(true);\n onConflict?.(newKeysString);\n } else {\n setHasConflict(false);\n setHotkeyValue?.(newKeysString);\n }\n }\n }, [\n recordedKeys,\n isRecording,\n isValid,\n keysString,\n checkHotkeyConflict,\n setHotkeyValue,\n onConflict,\n ]);\n\n // 处理输入框焦点\n const handleFocus = (e: FocusEvent<HTMLInputElement>) => {\n if (disabled) return;\n setIsFocused(true);\n setHasConflict(false);\n setHasInvalidCombination(false);\n start(); // 开始记录\n onFocus?.(e);\n };\n\n const handleBlur = (e: FocusEvent<HTMLInputElement>) => {\n setIsFocused(false);\n stop(); // 停止记录\n onBlur?.(e);\n };\n\n const handleClear = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setHotkeyValue?.('');\n resetKeys();\n setHasConflict(false);\n setHasInvalidCombination(false);\n setIsFocused(false);\n stop();\n onClear?.(hotkeyValue);\n };\n\n // 重置功能\n const handleReset = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setHotkeyValue?.(resetValue);\n resetKeys();\n setHasConflict(false);\n setHasInvalidCombination(false);\n setIsFocused(false);\n stop(); // 停止记录\n onReset?.(hotkeyValue, resetValue);\n };\n\n const handleClick = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (disabled || isFocused) return;\n inputRef.current?.focus();\n };\n\n const placeholderText = placeholder ?? t('hotkey.placeholder');\n const resetTitle = texts?.reset ?? t('hotkey.reset');\n const clearTitle = texts?.clear ?? t('hotkey.clear');\n const conflictText = texts?.conflicts ?? t('hotkey.conflict');\n const invalidText = texts?.invalidCombination ?? t('hotkey.invalidCombination');\n\n return (\n <Flexbox\n className={className}\n gap={8}\n style={{\n position: 'relative',\n ...style,\n }}\n >\n <Flexbox\n horizontal\n align={'center'}\n justify={'space-between'}\n className={cx(\n variants({\n disabled,\n error: hasConflict || hasInvalidCombination,\n focused: isFocused,\n shadow,\n variant: variant || (isDarkMode ? 'filled' : 'outlined'),\n }),\n )}\n onClick={handleClick}\n >\n <div style={{ pointerEvents: 'none' }}>\n {isRecording ? (\n <span className={styles.placeholder}>\n {keys.length > 0 ? <Hotkey keys={keysString} /> : placeholderText}\n </span>\n ) : hotkeyValue ? (\n <Hotkey keys={hotkeyValue} />\n ) : (\n <span className={styles.placeholder}>{placeholderText}</span>\n )}\n </div>\n\n {/* 隐藏的输入框,用于接收焦点 */}\n <input\n readOnly\n className={styles.hiddenInput}\n disabled={disabled}\n ref={inputRef as any}\n style={{ pointerEvents: 'none' }}\n onBlur={handleBlur}\n onFocus={handleFocus}\n />\n\n {!isFocused && hotkeyValue && !disabled && (allowReset || allowClear) && (\n <Flexbox horizontal gap={4}>\n {allowReset && hotkeyValue !== resetValue && (\n <ActionIcon\n icon={Undo2Icon}\n size={'small'}\n title={resetTitle}\n variant={'filled'}\n onClick={handleReset}\n />\n )}\n {allowClear && (\n <ActionIcon\n icon={XIcon}\n size={'small'}\n title={clearTitle}\n variant={'filled'}\n onClick={handleClear}\n />\n )}\n </Flexbox>\n )}\n </Flexbox>\n {hasConflict && <div className={styles.errorText}>{conflictText}</div>}\n {hasInvalidCombination && <div className={styles.errorText}>{invalidText}</div>}\n </Flexbox>\n );\n },\n);\n\nHotkeyInput.displayName = 'HotkeyInput';\n\nexport default HotkeyInput;\n"],"mappings":";;;;;;;;;;;;;;;;AA6BA,MAAM,cAAc,MACjB,EACC,QAAQ,IACR,eAAe,IACf,aAAa,IACb,UACA,SACA,YACA,aACA,UACA,QACA,YACA,aAAa,MACb,OACA,WACA,kBAAkB,CAAC,GACnB,SACA,OACA,SACA,QACA,SACA,cACI;CACJ,MAAM,CAAC,WAAW,gBAAgB,SAAS,KAAK;CAChD,MAAM,CAAC,aAAa,kBAAkB,SAAS,KAAK;CACpD,MAAM,CAAC,uBAAuB,4BAA4B,SAAS,KAAK;CACxE,MAAM,WAAW,OAAiB,IAAI;CACtC,MAAM,EAAE,eAAe,aAAa;CACpC,MAAM,EAAE,MAAM,eAAeA,cAAc;CAC3C,MAAM,gBAAgB,cAAc,mBAAmB,OAAO,GAAG,CAAC,OAAO,CAAC;CAC1E,MAAM,CAAC,aAAa,kBAAkBC,cAAmB,cAAc;EACrE;EACA;EACA;CACF,CAAC;CAGD,MAAM,CAAC,cAAc,EAAE,OAAO,MAAM,aAAa,eAAe,iBAAiB;CAEjF,WACE,WACM;EACJ,SAAS,SAAS,KAAK;CACzB,GACA;EACE,yBAAyB;EACzB,kBAAkB;EAClB,SAAS,eAAe,CAAC;EACzB,SAAS;EACT,OAAO;EACP,gBAAgB;CAClB,CACF;CA0CA,MAAM,EAAE,SAAS,SAvCE,aAAa,YAAyB;EACvD,MAAM,YAAsB,CAAC;EAC7B,MAAM,aAAuB,CAAC;EAE9B,KAAK,MAAM,OAAO,SAAS;GAEzB,MAAM,gBAAqB,IAAI,YAAY;GAC3C,IAAI,mBAAmB,SAAS,aAAa,GAGxC;QAAA,CAAC,iBAAiB,kBAAkB,UACpC,iBAAiB,kBAAkB,QAEhC;SAAA,CAAC,UAAU,SAAS,KAAK,GAAG,UAAU,KAAK,KAAK;IAAA,OAC/C,IAAI,CAAC,UAAU,SAAS,aAAa,GAC1C,UAAU,KAAK,aAAa;GAAA,OAG9B,WAAW,KAAK,GAAG;EAEvB;EAGA,IAAI,UAAU,WAAW,KAAK,WAAW,SAAS,GAChD,OAAO;GAAE,SAAS;GAAO,MAAM,CAAC;EAAE;EAKpC,MAAM,YAAY,CAAC,WADF,WAAW,SAAS,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC,IAAI,CAAC,CAC1B;EAEtC,OAAO;GAEL,SAAS,UAAU,OAAO,MAAM,EAAE,SAAS,CAAC;GAC5C,MAAM,UAAU,KAAK;EACvB;CACF,GAAG,CAAC,CAG+B,CAAC,CAAC,YAAY;CACjD,MAAM,aAAa,KAAK,KAAK,GAAG;CAGhC,MAAM,sBAAsB,aACzB,cAA+B;EAC9B,OAAO,gBACJ,QAAQ,gBAAgB,gBAAgB,UAAU,CAAC,CACnD,MAAM,gBAAgB;GACrB,MAAM,UAAU,gBAAgB,SAAS;GACzC,MAAM,eAAe,gBAAgB,WAAW;GAChD,OAAO,QAAQ,SAAS,YAAY;EACtC,CAAC;CACL,GACA,CAAC,eAAe,CAClB;CAGA,gBAAgB;EACd,IAAI,aAAa,OAAO,KAAK,CAAC,aAAa;GACzC,IAAI,CAAC,SAAS;IACZ,yBAAyB,IAAI;IAC7B,eAAe,KAAK;IACpB;GACF;GAEA,yBAAyB,KAAK;GAC9B,MAAM,gBAAgB;GAItB,IADiB,oBAAoB,aAC1B,GAAG;IACZ,eAAe,IAAI;IACnB,aAAa,aAAa;GAC5B,OAAO;IACL,eAAe,KAAK;IACpB,iBAAiB,aAAa;GAChC;EACF;CACF,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAGD,MAAM,eAAe,MAAoC;EACvD,IAAI,UAAU;EACd,aAAa,IAAI;EACjB,eAAe,KAAK;EACpB,yBAAyB,KAAK;EAC9B,MAAM;EACN,UAAU,CAAC;CACb;CAEA,MAAM,cAAc,MAAoC;EACtD,aAAa,KAAK;EAClB,KAAK;EACL,SAAS,CAAC;CACZ;CAEA,MAAM,eAAe,MAAkB;EACrC,EAAE,eAAe;EACjB,EAAE,gBAAgB;EAClB,iBAAiB,EAAE;EACnB,UAAU;EACV,eAAe,KAAK;EACpB,yBAAyB,KAAK;EAC9B,aAAa,KAAK;EAClB,KAAK;EACL,UAAU,WAAW;CACvB;CAGA,MAAM,eAAe,MAAkB;EACrC,EAAE,eAAe;EACjB,EAAE,gBAAgB;EAClB,iBAAiB,UAAU;EAC3B,UAAU;EACV,eAAe,KAAK;EACpB,yBAAyB,KAAK;EAC9B,aAAa,KAAK;EAClB,KAAK;EACL,UAAU,aAAa,UAAU;CACnC;CAEA,MAAM,eAAe,MAAkB;EACrC,EAAE,eAAe;EACjB,EAAE,gBAAgB;EAClB,IAAI,YAAY,WAAW;EAC3B,SAAS,SAAS,MAAM;CAC1B;CAEA,MAAM,kBAAkB,eAAe,EAAE,oBAAoB;CAC7D,MAAM,aAAa,OAAO,SAAS,EAAE,cAAc;CACnD,MAAM,aAAa,OAAO,SAAS,EAAE,cAAc;CACnD,MAAM,eAAe,OAAO,aAAa,EAAE,iBAAiB;CAC5D,MAAM,cAAc,OAAO,sBAAsB,EAAE,2BAA2B;CAE9E,OACE,qBAACC,mBAAD;EACa;EACX,KAAK;EACL,OAAO;GACL,UAAU;GACV,GAAG;EACL;EANF,UAAA;GAQE,qBAACA,mBAAD;IACE,YAAA;IACA,OAAO;IACP,SAAS;IACT,WAAW,GACT,SAAS;KACP;KACA,OAAO,eAAe;KACtB,SAAS;KACT;KACA,SAAS,YAAY,aAAa,WAAW;IAC/C,CAAC,CACH;IACA,SAAS;IAbX,UAAA;KAeE,oBAAC,OAAD;MAAK,OAAO,EAAE,eAAe,OAAO;MACjC,UAAA,cACC,oBAAC,QAAD;OAAM,WAAW,OAAO;OACrB,UAAA,KAAK,SAAS,IAAI,oBAAC,QAAD,EAAQ,MAAM,WAAa,CAAA,IAAI;MAC9C,CAAA,IACJ,cACF,oBAAC,QAAD,EAAQ,MAAM,YAAc,CAAA,IAE5B,oBAAC,QAAD;OAAM,WAAW,OAAO;OAAc,UAAA;MAAsB,CAAA;KAE3D,CAAA;KAGL,oBAAC,SAAD;MACE,UAAA;MACA,WAAW,OAAO;MACR;MACV,KAAK;MACL,OAAO,EAAE,eAAe,OAAO;MAC/B,QAAQ;MACR,SAAS;KACV,CAAA;KAEA,CAAC,aAAa,eAAe,CAAC,aAAa,cAAc,eACxD,qBAACA,mBAAD;MAAS,YAAA;MAAW,KAAK;MAAzB,UAAA,CACG,cAAc,gBAAgB,cAC7B,oBAAC,YAAD;OACE,MAAM;OACN,MAAM;OACN,OAAO;OACP,SAAS;OACT,SAAS;MACV,CAAA,GAEF,cACC,oBAAC,YAAD;OACE,MAAM;OACN,MAAM;OACN,OAAO;OACP,SAAS;OACT,SAAS;MACV,CAAA,CAEI;;IAEJ;;GACR,eAAe,oBAAC,OAAD;IAAK,WAAW,OAAO;IAAY,UAAA;GAAkB,CAAA;GACpE,yBAAyB,oBAAC,OAAD;IAAK,WAAW,OAAO;IAAY,UAAA;GAAiB,CAAA;EACvE;;AAEb,CACF;AAEA,YAAY,cAAc"}
@@ -21,7 +21,7 @@ const DEFAULT_HEIGHT = 400;
21
21
  * Cap for srcDoc length. Beyond a few MB browsers start misbehaving;
22
22
  * we fall back to source-only above this threshold.
23
23
  */
24
- const SRCDOC_MAX_LENGTH = 5 * 1024 * 1024;
24
+ const SRCDOC_MAX_LENGTH = 5242880;
25
25
  const FULL_HTML_MARKERS = [
26
26
  "<!doctype html",
27
27
  "<html",
@@ -1 +1 @@
1
- {"version":3,"file":"const.mjs","names":[],"sources":["../../src/HtmlPreview/const.ts"],"sourcesContent":["/**\n * Default sandbox attribute for HTML preview iframes.\n *\n * Why this exact set:\n * - `allow-scripts` — required by the use case (three.js / p5.js / Tailwind\n * CDN style demos). Without it inline preview degrades to source view.\n * - `allow-forms` — lets demos handle `<form>` submissions in-frame.\n * - `allow-modals` — `alert`/`confirm`/`prompt` are common in toy demos.\n *\n * Deliberately omitted:\n * - `allow-same-origin` — would let scripts read parent cookies / localStorage\n * under cloud deployments, and bridge the IPC boundary on desktop builds.\n * - `allow-popups`, `allow-top-navigation` — phishing surface.\n *\n * Override at your own risk via `sandbox` prop.\n */\nexport const DEFAULT_SANDBOX = 'allow-scripts allow-forms allow-modals';\n\nexport const DEFAULT_HEIGHT = 400;\n\n/**\n * Cap for srcDoc length. Beyond a few MB browsers start misbehaving;\n * we fall back to source-only above this threshold.\n */\nexport const SRCDOC_MAX_LENGTH = 5 * 1024 * 1024;\n\nconst FULL_HTML_MARKERS = ['<!doctype html', '<html', '<HTML'];\n\n/**\n * Is the content a \"full\" HTML document (has `<html>` or `<!DOCTYPE html>`)?\n * Fragments without these markers render poorly inline and should not auto-mount.\n */\nexport const isFullHtmlDocument = (content: string): boolean => {\n if (!content) return false;\n const head = content.slice(0, 1024).toLowerCase();\n return FULL_HTML_MARKERS.some((marker) => head.includes(marker.toLowerCase()));\n};\n\n/**\n * Heuristic for whether streaming HTML is \"stable enough to mount the iframe\".\n * Re-mounting srcDoc on every token reboots scripts (p5.js setup runs each\n * time), so we wait for a clear closing signal.\n */\nexport const isHtmlContentClosed = (content: string): boolean => {\n if (!content) return false;\n const tail = content.slice(-1024).toLowerCase();\n return tail.includes('</html>');\n};\n\n/**\n * Does the content contain a `<script>` tag?\n *\n * Used by `streamingMode: 'auto'` to decide whether live-streaming the\n * iframe is safe. Script-bearing content gets deferred until stable so we\n * don't re-run `setup()` on every token; script-less content (pure\n * markup + styles) streams live for a more responsive feel.\n */\nexport const containsScript = (content: string): boolean => {\n if (!content) return false;\n return /<script\\b/i.test(content);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AAgBA,MAAa,kBAAkB;AAE/B,MAAa,iBAAiB;;;;;AAM9B,MAAa,oBAAoB,IAAI,OAAO;AAE5C,MAAM,oBAAoB;CAAC;CAAkB;CAAS;AAAO;;;;;AAM7D,MAAa,sBAAsB,YAA6B;CAC9D,IAAI,CAAC,SAAS,OAAO;CACrB,MAAM,OAAO,QAAQ,MAAM,GAAG,IAAI,CAAC,CAAC,YAAY;CAChD,OAAO,kBAAkB,MAAM,WAAW,KAAK,SAAS,OAAO,YAAY,CAAC,CAAC;AAC/E;;;;;;AAOA,MAAa,uBAAuB,YAA6B;CAC/D,IAAI,CAAC,SAAS,OAAO;CAErB,OADa,QAAQ,MAAM,KAAK,CAAC,CAAC,YACxB,CAAC,CAAC,SAAS,SAAS;AAChC;;;;;;;;;AAUA,MAAa,kBAAkB,YAA6B;CAC1D,IAAI,CAAC,SAAS,OAAO;CACrB,OAAO,aAAa,KAAK,OAAO;AAClC"}
1
+ {"version":3,"file":"const.mjs","names":[],"sources":["../../src/HtmlPreview/const.ts"],"sourcesContent":["/**\n * Default sandbox attribute for HTML preview iframes.\n *\n * Why this exact set:\n * - `allow-scripts` — required by the use case (three.js / p5.js / Tailwind\n * CDN style demos). Without it inline preview degrades to source view.\n * - `allow-forms` — lets demos handle `<form>` submissions in-frame.\n * - `allow-modals` — `alert`/`confirm`/`prompt` are common in toy demos.\n *\n * Deliberately omitted:\n * - `allow-same-origin` — would let scripts read parent cookies / localStorage\n * under cloud deployments, and bridge the IPC boundary on desktop builds.\n * - `allow-popups`, `allow-top-navigation` — phishing surface.\n *\n * Override at your own risk via `sandbox` prop.\n */\nexport const DEFAULT_SANDBOX = 'allow-scripts allow-forms allow-modals';\n\nexport const DEFAULT_HEIGHT = 400;\n\n/**\n * Cap for srcDoc length. Beyond a few MB browsers start misbehaving;\n * we fall back to source-only above this threshold.\n */\nexport const SRCDOC_MAX_LENGTH = 5 * 1024 * 1024;\n\nconst FULL_HTML_MARKERS = ['<!doctype html', '<html', '<HTML'];\n\n/**\n * Is the content a \"full\" HTML document (has `<html>` or `<!DOCTYPE html>`)?\n * Fragments without these markers render poorly inline and should not auto-mount.\n */\nexport const isFullHtmlDocument = (content: string): boolean => {\n if (!content) return false;\n const head = content.slice(0, 1024).toLowerCase();\n return FULL_HTML_MARKERS.some((marker) => head.includes(marker.toLowerCase()));\n};\n\n/**\n * Heuristic for whether streaming HTML is \"stable enough to mount the iframe\".\n * Re-mounting srcDoc on every token reboots scripts (p5.js setup runs each\n * time), so we wait for a clear closing signal.\n */\nexport const isHtmlContentClosed = (content: string): boolean => {\n if (!content) return false;\n const tail = content.slice(-1024).toLowerCase();\n return tail.includes('</html>');\n};\n\n/**\n * Does the content contain a `<script>` tag?\n *\n * Used by `streamingMode: 'auto'` to decide whether live-streaming the\n * iframe is safe. Script-bearing content gets deferred until stable so we\n * don't re-run `setup()` on every token; script-less content (pure\n * markup + styles) streams live for a more responsive feel.\n */\nexport const containsScript = (content: string): boolean => {\n if (!content) return false;\n return /<script\\b/i.test(content);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AAgBA,MAAa,kBAAkB;AAE/B,MAAa,iBAAiB;;;;;AAM9B,MAAa,oBAAoB;AAEjC,MAAM,oBAAoB;CAAC;CAAkB;CAAS;AAAO;;;;;AAM7D,MAAa,sBAAsB,YAA6B;CAC9D,IAAI,CAAC,SAAS,OAAO;CACrB,MAAM,OAAO,QAAQ,MAAM,GAAG,IAAI,CAAC,CAAC,YAAY;CAChD,OAAO,kBAAkB,MAAM,WAAW,KAAK,SAAS,OAAO,YAAY,CAAC,CAAC;AAC/E;;;;;;AAOA,MAAa,uBAAuB,YAA6B;CAC/D,IAAI,CAAC,SAAS,OAAO;CAErB,OADa,QAAQ,MAAM,KAAK,CAAC,CAAC,YACxB,CAAC,CAAC,SAAS,SAAS;AAChC;;;;;;;;;AAUA,MAAa,kBAAkB,YAA6B;CAC1D,IAAI,CAAC,SAAS,OAAO;CACrB,OAAO,aAAa,KAAK,OAAO;AAClC"}