@aloudata/aloudata-design 3.0.11 → 3.0.12

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 (37) hide show
  1. package/dist/Checkbox/index.js +2 -1
  2. package/dist/Checkbox/index.js.map +1 -1
  3. package/dist/Checkbox/type.d.ts +1 -0
  4. package/dist/Drawer/index.d.ts +1 -0
  5. package/dist/Drawer/index.js +2 -2
  6. package/dist/Drawer/index.js.map +1 -1
  7. package/dist/Form/index.d.ts +12 -21
  8. package/dist/Form/index.js +2 -1
  9. package/dist/Form/index.js.map +1 -1
  10. package/dist/Input/components/Input/index.d.ts +1 -1
  11. package/dist/Input/components/Input/index.js +3 -2
  12. package/dist/Input/components/Input/index.js.map +1 -1
  13. package/dist/Input/components/Password/index.d.ts +3 -2
  14. package/dist/Input/components/Password/index.js +2 -2
  15. package/dist/Input/components/Password/index.js.map +1 -1
  16. package/dist/Input/components/TextArea/index.d.ts +1 -1
  17. package/dist/Input/components/TextArea/index.js +5 -1
  18. package/dist/Input/components/TextArea/index.js.map +1 -1
  19. package/dist/Popconfirm/index.d.ts +2 -0
  20. package/dist/Popconfirm/index.js +61 -36
  21. package/dist/Popconfirm/index.js.map +1 -1
  22. package/dist/Popover/index.d.ts +6 -0
  23. package/dist/Popover/index.js +33 -3
  24. package/dist/Popover/index.js.map +1 -1
  25. package/dist/Select/BaseSelect.js +1 -1
  26. package/dist/Select/BaseSelect.js.map +1 -1
  27. package/dist/Select/interface.d.ts +1 -1
  28. package/dist/Tabs/index.d.ts +1 -0
  29. package/dist/Tabs/index.js +16 -6
  30. package/dist/Tabs/index.js.map +1 -1
  31. package/dist/Typography/index.d.ts +10 -7
  32. package/dist/Typography/index.js +38 -15
  33. package/dist/Typography/index.js.map +1 -1
  34. package/dist/Upload/index.d.ts +1 -1
  35. package/dist/Upload/index.js.map +1 -1
  36. package/dist/aloudata-design.css +1 -1
  37. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/Tabs/index.tsx"],"sourcesContent":["import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { cn } from '../lib/utils';\nimport { ChevronLeftLine, ChevronRightLine, CloseLightLine } from '../Icon';\nimport TabPane from './TabPane';\n\nexport type TabsSize = 'default' | 'small';\n\ninterface TabItem {\n key: string;\n label: React.ReactNode;\n children?: React.ReactNode;\n disabled?: boolean;\n closable?: boolean;\n icon?: React.ReactNode;\n forceRender?: boolean;\n className?: string;\n}\n\nexport interface ITabsProps {\n size?: TabsSize;\n activeKey?: string;\n defaultActiveKey?: string;\n onChange?: (activeKey: string) => void;\n onTabClick?: (activeKey: string, e: React.MouseEvent) => void;\n destroyInactiveTabPane?: boolean;\n centered?: boolean;\n adaptHeight?: boolean;\n tabPosition?: 'left' | 'right' | 'top' | 'bottom';\n className?: string;\n children?: React.ReactNode;\n headerBackgroundColor?: string;\n monospace?: boolean;\n padding?: boolean | number;\n compact?: boolean;\n hasDividing?: boolean;\n items?: TabItem[];\n type?: 'line' | 'card' | 'editable-card';\n tabBarExtraContent?:\n | React.ReactNode\n | { left?: React.ReactNode; right?: React.ReactNode };\n onEdit?: (\n targetKey: string | React.MouseEvent | React.KeyboardEvent,\n action: 'add' | 'remove',\n ) => void;\n hideAdd?: boolean;\n style?: React.CSSProperties;\n popupClassName?: string;\n tabBarGutter?: number;\n moreIcon?: React.ReactNode;\n /** 透传到 Tabs 根容器的 data-testid,用于自动化测试定位 */\n 'data-testid'?: string;\n /** 透传到 Tabs 根容器的 aria-label,用于可访问性与自动化测试定位 */\n 'aria-label'?: string;\n}\n\nexport default function Tabs(props: ITabsProps) {\n const {\n size,\n className,\n adaptHeight,\n style = {},\n monospace: propsMonospace,\n tabPosition = 'top',\n padding: propsPadding = false,\n compact,\n hasDividing = true,\n items,\n activeKey: controlledActiveKey,\n defaultActiveKey,\n onChange,\n onTabClick,\n destroyInactiveTabPane,\n centered,\n tabBarExtraContent,\n headerBackgroundColor,\n children,\n type,\n onEdit,\n hideAdd,\n 'data-testid': dataTestId,\n 'aria-label': ariaLabel,\n } = props;\n\n const isEditable = type === 'editable-card';\n const isCard = type === 'card' || type === 'editable-card';\n\n // Derive items from children if not provided\n const resolvedItems: TabItem[] = useMemo(() => {\n if (items) return items;\n return React.Children.toArray(children)\n .filter(React.isValidElement)\n .map((child: any) => ({\n key: child.key || child.props.key || '',\n label: child.props.tab,\n children: child.props.children,\n disabled: child.props.disabled,\n closable: child.props.closable,\n forceRender: child.props.forceRender,\n }));\n }, [items, children]);\n\n const firstKey = resolvedItems[0]?.key || '';\n const [innerActiveKey, setInnerActiveKey] = useState(\n defaultActiveKey || firstKey,\n );\n const mergedActiveKey =\n controlledActiveKey !== undefined ? controlledActiveKey : innerActiveKey;\n const activeKey = resolvedItems.some((item) => item.key === mergedActiveKey)\n ? mergedActiveKey\n : firstKey;\n\n const handleTabClick = (key: string, e: React.MouseEvent) => {\n if (controlledActiveKey === undefined) {\n setInnerActiveKey(key);\n }\n onChange?.(key);\n onTabClick?.(key, e);\n };\n\n const handleRemove = (key: string, e: React.MouseEvent) => {\n e.stopPropagation();\n onEdit?.(key, 'remove');\n };\n\n const handleAdd = (e: React.MouseEvent) => {\n onEdit?.(e, 'add');\n };\n\n const monospace = tabPosition !== 'top' ? false : propsMonospace;\n const paddingVal = useMemo(() => {\n if (tabPosition !== 'top') return 0;\n if (typeof propsPadding === 'number') return propsPadding;\n if (typeof propsPadding === 'boolean' && propsPadding) return 20;\n return 0;\n }, [propsPadding, tabPosition]);\n\n const isVertical = tabPosition === 'left' || tabPosition === 'right';\n\n const extraLeft =\n tabBarExtraContent &&\n typeof tabBarExtraContent === 'object' &&\n 'left' in tabBarExtraContent\n ? tabBarExtraContent.left\n : null;\n const extraRight = tabBarExtraContent\n ? typeof tabBarExtraContent === 'object' && 'right' in tabBarExtraContent\n ? tabBarExtraContent.right\n : React.isValidElement(tabBarExtraContent)\n ? tabBarExtraContent\n : null\n : null;\n\n // Scroll state for overflow\n const navListRef = useRef<HTMLDivElement>(null);\n const [canScrollLeft, setCanScrollLeft] = useState(false);\n const [canScrollRight, setCanScrollRight] = useState(false);\n\n const checkScroll = useCallback(() => {\n const el = navListRef.current;\n if (!el || isVertical) {\n setCanScrollLeft(false);\n setCanScrollRight(false);\n return;\n }\n const { scrollLeft, scrollWidth, clientWidth } = el;\n setCanScrollLeft(scrollLeft > 1);\n setCanScrollRight(scrollLeft + clientWidth < scrollWidth - 1);\n }, [isVertical]);\n\n useEffect(() => {\n checkScroll();\n const el = navListRef.current;\n if (!el) return;\n // Use ResizeObserver to detect size changes\n let ro: ResizeObserver | undefined;\n if (typeof ResizeObserver !== 'undefined') {\n ro = new ResizeObserver(() => checkScroll());\n ro.observe(el);\n }\n el.addEventListener('scroll', checkScroll, { passive: true });\n return () => {\n el.removeEventListener('scroll', checkScroll);\n ro?.disconnect();\n };\n }, [checkScroll, resolvedItems.length]);\n\n const scrollBy = (delta: number) => {\n const el = navListRef.current;\n if (el) {\n el.scrollBy({ left: delta, behavior: 'smooth' });\n }\n };\n\n const showScrollButtons = canScrollLeft || canScrollRight;\n\n return (\n <div\n data-testid={dataTestId}\n aria-label={ariaLabel}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs ant-tabs tw-flex',\n isVertical ? 'tw-flex-row' : 'tw-flex-col',\n adaptHeight && 'ald-adapt-height tw-h-full',\n size !== 'small' && 'ald-tabs-default',\n monospace && 'ald-tabs-monospace',\n compact && 'ald-tabs-compact',\n !hasDividing && 'ald-tabs-no-dividing',\n className,\n )}\n style={\n {\n ...style,\n '--header-bg-color': headerBackgroundColor,\n '--tabs-padding': `${paddingVal}px`,\n } as React.CSSProperties\n }\n >\n {/* Tab nav */}\n <div\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-nav ant-tabs-nav tw-flex tw-items-center',\n !isVertical && 'tw-mb-5',\n !isVertical &&\n hasDividing &&\n 'tw-border-0 tw-border-b tw-border-solid tw-border-b-[var(--global-cool-grey-100)]',\n !isVertical && compact && '!tw-mb-0',\n isVertical &&\n 'tw-flex-col tw-border-0 tw-border-r tw-border-solid tw-border-r-[var(--global-cool-grey-100)]',\n )}\n style={\n headerBackgroundColor\n ? { backgroundColor: headerBackgroundColor }\n : undefined\n }\n >\n {extraLeft}\n\n {/* Scroll left button */}\n {showScrollButtons && !isVertical && (\n <button\n type=\"button\"\n className={cn(\n 'ald-tabs-scroll-btn tw-flex tw-shrink-0 tw-items-center tw-justify-center tw-border-none tw-bg-transparent tw-p-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]',\n !canScrollLeft && 'tw-invisible',\n )}\n onClick={() => scrollBy(-200)}\n aria-label=\"Scroll tabs left\"\n >\n <ChevronLeftLine size={16} />\n </button>\n )}\n\n <div\n className=\"ald-tabs-nav-wrap ant-tabs-nav-wrap tw-min-w-0 tw-flex-1\"\n style={paddingVal ? { margin: `0 ${paddingVal}px` } : undefined}\n >\n <div\n ref={navListRef}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-nav-list ant-tabs-nav-list tw-flex tw-overflow-hidden',\n isVertical && 'tw-flex-col',\n centered && !isVertical && 'tw-justify-center',\n monospace && '[&>*]:tw-flex-1',\n isCard ? 'tw-gap-1' : !monospace && 'tw-gap-8',\n )}\n style={\n !isVertical\n ? { scrollbarWidth: 'none', msOverflowStyle: 'none' }\n : undefined\n }\n >\n {resolvedItems.map((item) => {\n const isActive = activeKey === item.key;\n // For editable-card, closable defaults to true unless explicitly set to false\n const showClose = isEditable && item.closable !== false;\n\n return (\n <div\n key={item.key}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-tab ant-tabs-tab tw-relative tw-flex tw-shrink-0 tw-cursor-pointer tw-items-center tw-gap-2 tw-whitespace-nowrap tw-transition-colors',\n // Card / editable-card styling\n isCard\n ? cn(\n 'tw-h-10 tw-rounded-t-[6px] tw-border tw-border-b-0 tw-border-solid tw-px-4 tw-text-sm tw-leading-5',\n 'tw-gap-sp-75',\n isActive\n ? 'tw-border-[var(--alias-colors-border-default)] tw-bg-[var(--background-default)] tw-font-medium tw-text-[var(--alias-colors-text-selected)]'\n : 'tw-border-[var(--alias-colors-border-default)] tw-bg-[var(--alias-colors-bg-skeleton-subtler)] tw-text-[var(--alias-colors-text-subtle)] hover:tw-text-inherit',\n )\n : cn(\n size === 'small'\n ? 'tw-py-2 tw-text-xs tw-leading-4'\n : 'tw-py-2.5 tw-text-sm tw-leading-5',\n monospace && 'tw-justify-center',\n isActive\n ? 'tw-font-medium tw-text-[var(--alias-colors-text-selected)]'\n : 'tw-font-medium tw-text-[var(--alias-colors-text-subtle)] hover:tw-text-inherit',\n ),\n item.disabled &&\n 'tw-pointer-events-none tw-cursor-default tw-opacity-50',\n )}\n onClick={\n item.disabled\n ? undefined\n : (e) => handleTabClick(item.key, e)\n }\n >\n {item.icon}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n <span className=\"ant-tabs-tab-btn\">{item.label}</span>\n {/* Close button for editable-card */}\n {showClose && (\n <span\n className=\"ald-tabs-tab-remove tw-m-0 tw-grid tw-size-4 tw-cursor-pointer tw-place-items-center tw-p-0 tw-text-[var(--alias-colors-icon-subtle)] tw-transition-colors hover:tw-text-[var(--alias-colors-text-default)]\"\n onClick={(e) => handleRemove(item.key, e)}\n aria-label={`Remove ${item.label}`}\n >\n <CloseLightLine size={12} />\n </span>\n )}\n {/* Active indicator for non-card line tabs */}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n {!isCard && isActive && !isVertical && (\n <div className=\"ant-tabs-ink-bar tw-absolute tw-inset-x-0 tw--bottom-px tw-h-[2px] tw-rounded-[2px] tw-bg-[var(--alias-colors-border-selected)]\" />\n )}\n {!isCard && isActive && isVertical && (\n <div className=\"tw-absolute tw-inset-y-0 tw--right-px tw-w-[2px] tw-rounded-[2px] tw-bg-[var(--alias-colors-border-selected)]\" />\n )}\n </div>\n );\n })}\n </div>\n </div>\n\n {/* Scroll right button */}\n {showScrollButtons && !isVertical && (\n <button\n type=\"button\"\n className={cn(\n 'ald-tabs-scroll-btn tw-flex tw-shrink-0 tw-items-center tw-justify-center tw-border-none tw-bg-transparent tw-p-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]',\n !canScrollRight && 'tw-invisible',\n )}\n onClick={() => scrollBy(200)}\n aria-label=\"Scroll tabs right\"\n >\n <ChevronRightLine size={16} />\n </button>\n )}\n\n {/* Add button for editable-card */}\n {isEditable && !hideAdd && (\n <button\n type=\"button\"\n className=\"ald-tabs-nav-add tw-ml-1 tw-flex tw-shrink-0 tw-cursor-pointer tw-items-center tw-justify-center tw-rounded tw-border tw-border-solid tw-border-[var(--border-default)] tw-bg-[var(--background-default)] tw-px-2 tw-py-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]\"\n onClick={handleAdd}\n aria-label=\"Add tab\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n </button>\n )}\n\n {extraRight}\n </div>\n\n {/* Tab content */}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n <div\n className={cn(\n 'ald-tabs-content ant-tabs-content ant-tabs-content-holder tw-min-h-0 tw-flex-1',\n adaptHeight && 'tw-h-full',\n )}\n style={\n paddingVal\n ? { padding: `0 ${paddingVal}px ${paddingVal}px` }\n : undefined\n }\n >\n {resolvedItems.map((item) => {\n const isActive = item.key === activeKey;\n if (!isActive && destroyInactiveTabPane && !item.forceRender) {\n return null;\n }\n return (\n <div\n key={item.key}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-tabpane ant-tabs-tabpane',\n // v2 行为:adaptHeight 时 tabpane 撑满内容区,子元素的百分比高度才能解析\n adaptHeight && 'tw-h-full tw-overflow-y-auto',\n isActive ? 'ant-tabs-tabpane-active tw-block' : 'tw-hidden',\n )}\n role=\"tabpanel\"\n >\n {item.children}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nTabs.TabPane = TabPane;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/Tabs/index.tsx"],"sourcesContent":["import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { cn } from '../lib/utils';\nimport { ChevronLeftLine, ChevronRightLine, CloseLightLine } from '../Icon';\nimport TabPane from './TabPane';\n\nexport type TabsSize = 'default' | 'small';\n\ninterface TabItem {\n key: string;\n label: React.ReactNode;\n children?: React.ReactNode;\n disabled?: boolean;\n closable?: boolean;\n icon?: React.ReactNode;\n forceRender?: boolean;\n className?: string;\n}\n\nexport interface ITabsProps {\n size?: TabsSize;\n activeKey?: string;\n defaultActiveKey?: string;\n onChange?: (activeKey: string) => void;\n onTabClick?: (activeKey: string, e: React.MouseEvent) => void;\n destroyInactiveTabPane?: boolean;\n centered?: boolean;\n adaptHeight?: boolean;\n tabPosition?: 'left' | 'right' | 'top' | 'bottom';\n className?: string;\n children?: React.ReactNode;\n headerBackgroundColor?: string;\n monospace?: boolean;\n padding?: boolean | number;\n compact?: boolean;\n hasDividing?: boolean;\n items?: TabItem[];\n type?: 'line' | 'card' | 'editable-card';\n tabBarExtraContent?:\n | React.ReactNode\n | { left?: React.ReactNode; right?: React.ReactNode };\n onEdit?: (\n targetKey: string | React.MouseEvent | React.KeyboardEvent,\n action: 'add' | 'remove',\n ) => void;\n hideAdd?: boolean;\n style?: React.CSSProperties;\n tabBarStyle?: React.CSSProperties;\n popupClassName?: string;\n tabBarGutter?: number;\n moreIcon?: React.ReactNode;\n /** 透传到 Tabs 根容器的 data-testid,用于自动化测试定位 */\n 'data-testid'?: string;\n /** 透传到 Tabs 根容器的 aria-label,用于可访问性与自动化测试定位 */\n 'aria-label'?: string;\n}\n\nexport default function Tabs(props: ITabsProps) {\n const {\n size,\n className,\n adaptHeight,\n style = {},\n monospace: propsMonospace,\n tabPosition = 'top',\n padding: propsPadding = false,\n compact,\n hasDividing = true,\n items,\n activeKey: controlledActiveKey,\n defaultActiveKey,\n onChange,\n onTabClick,\n destroyInactiveTabPane,\n centered,\n tabBarExtraContent,\n headerBackgroundColor,\n children,\n type,\n onEdit,\n hideAdd,\n tabBarStyle,\n 'data-testid': dataTestId,\n 'aria-label': ariaLabel,\n } = props;\n\n const isEditable = type === 'editable-card';\n const isCard = type === 'card' || type === 'editable-card';\n\n // Derive items from children if not provided\n const resolvedItems: TabItem[] = useMemo(() => {\n if (items) return items;\n return React.Children.toArray(children)\n .filter(React.isValidElement)\n .map((child: any) => ({\n key: child.key || child.props.key || '',\n label: child.props.tab,\n children: child.props.children,\n disabled: child.props.disabled,\n closable: child.props.closable,\n forceRender: child.props.forceRender,\n }));\n }, [items, children]);\n\n const firstKey = resolvedItems[0]?.key || '';\n const [innerActiveKey, setInnerActiveKey] = useState(\n defaultActiveKey || firstKey,\n );\n const mergedActiveKey =\n controlledActiveKey !== undefined ? controlledActiveKey : innerActiveKey;\n const activeKey = resolvedItems.some((item) => item.key === mergedActiveKey)\n ? mergedActiveKey\n : firstKey;\n\n const handleTabClick = (key: string, e: React.MouseEvent) => {\n if (controlledActiveKey === undefined) {\n setInnerActiveKey(key);\n }\n onChange?.(key);\n onTabClick?.(key, e);\n };\n\n const handleRemove = (key: string, e: React.MouseEvent) => {\n e.stopPropagation();\n onEdit?.(key, 'remove');\n };\n\n const handleAdd = (e: React.MouseEvent) => {\n onEdit?.(e, 'add');\n };\n\n const monospace = tabPosition !== 'top' ? false : propsMonospace;\n const paddingVal = useMemo(() => {\n if (tabPosition !== 'top') return 0;\n if (typeof propsPadding === 'number') return propsPadding;\n if (typeof propsPadding === 'boolean' && propsPadding) return 20;\n return 0;\n }, [propsPadding, tabPosition]);\n\n const isTop = tabPosition === 'top';\n const isBottom = tabPosition === 'bottom';\n const isLeft = tabPosition === 'left';\n const isRight = tabPosition === 'right';\n const isVertical = tabPosition === 'left' || tabPosition === 'right';\n const rootDirectionClass = isRight\n ? 'tw-flex-row-reverse'\n : isLeft\n ? 'tw-flex-row'\n : isBottom\n ? 'tw-flex-col-reverse'\n : 'tw-flex-col';\n\n const extraLeft =\n tabBarExtraContent &&\n typeof tabBarExtraContent === 'object' &&\n 'left' in tabBarExtraContent\n ? tabBarExtraContent.left\n : null;\n const extraRight = tabBarExtraContent\n ? typeof tabBarExtraContent === 'object' && 'right' in tabBarExtraContent\n ? tabBarExtraContent.right\n : React.isValidElement(tabBarExtraContent)\n ? tabBarExtraContent\n : null\n : null;\n\n // Scroll state for overflow\n const navListRef = useRef<HTMLDivElement>(null);\n const [canScrollLeft, setCanScrollLeft] = useState(false);\n const [canScrollRight, setCanScrollRight] = useState(false);\n\n const checkScroll = useCallback(() => {\n const el = navListRef.current;\n if (!el || isVertical) {\n setCanScrollLeft(false);\n setCanScrollRight(false);\n return;\n }\n const { scrollLeft, scrollWidth, clientWidth } = el;\n setCanScrollLeft(scrollLeft > 1);\n setCanScrollRight(scrollLeft + clientWidth < scrollWidth - 1);\n }, [isVertical]);\n\n useEffect(() => {\n checkScroll();\n const el = navListRef.current;\n if (!el) return;\n // Use ResizeObserver to detect size changes\n let ro: ResizeObserver | undefined;\n if (typeof ResizeObserver !== 'undefined') {\n ro = new ResizeObserver(() => checkScroll());\n ro.observe(el);\n }\n el.addEventListener('scroll', checkScroll, { passive: true });\n return () => {\n el.removeEventListener('scroll', checkScroll);\n ro?.disconnect();\n };\n }, [checkScroll, resolvedItems.length]);\n\n const scrollBy = (delta: number) => {\n const el = navListRef.current;\n if (el) {\n el.scrollBy({ left: delta, behavior: 'smooth' });\n }\n };\n\n const showScrollButtons = canScrollLeft || canScrollRight;\n\n return (\n <div\n data-testid={dataTestId}\n aria-label={ariaLabel}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs ant-tabs tw-flex',\n rootDirectionClass,\n adaptHeight && 'ald-adapt-height tw-h-full',\n size !== 'small' && 'ald-tabs-default',\n monospace && 'ald-tabs-monospace',\n compact && 'ald-tabs-compact',\n !hasDividing && 'ald-tabs-no-dividing',\n className,\n )}\n style={\n {\n ...style,\n '--header-bg-color': headerBackgroundColor,\n '--tabs-padding': `${paddingVal}px`,\n } as React.CSSProperties\n }\n >\n {/* Tab nav */}\n <div\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-nav ant-tabs-nav tw-flex tw-items-center',\n isTop && 'tw-mb-5',\n isBottom && 'tw-mt-5',\n isTop &&\n hasDividing &&\n 'tw-border-0 tw-border-b tw-border-solid tw-border-b-[var(--global-cool-grey-100)]',\n isBottom &&\n hasDividing &&\n 'tw-border-0 tw-border-t tw-border-solid tw-border-t-[var(--global-cool-grey-100)]',\n isTop && compact && '!tw-mb-0',\n isBottom && compact && '!tw-mt-0',\n isLeft &&\n 'tw-flex-col tw-border-0 tw-border-r tw-border-solid tw-border-r-[var(--global-cool-grey-100)]',\n isRight &&\n 'tw-flex-col tw-border-0 tw-border-l tw-border-solid tw-border-l-[var(--global-cool-grey-100)]',\n )}\n style={\n headerBackgroundColor || tabBarStyle\n ? {\n ...tabBarStyle,\n ...(headerBackgroundColor\n ? { backgroundColor: headerBackgroundColor }\n : {}),\n }\n : undefined\n }\n >\n {extraLeft}\n\n {/* Scroll left button */}\n {showScrollButtons && !isVertical && (\n <button\n type=\"button\"\n className={cn(\n 'ald-tabs-scroll-btn tw-flex tw-shrink-0 tw-items-center tw-justify-center tw-border-none tw-bg-transparent tw-p-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]',\n !canScrollLeft && 'tw-invisible',\n )}\n onClick={() => scrollBy(-200)}\n aria-label=\"Scroll tabs left\"\n >\n <ChevronLeftLine size={16} />\n </button>\n )}\n\n <div\n className=\"ald-tabs-nav-wrap ant-tabs-nav-wrap tw-min-w-0 tw-flex-1\"\n style={paddingVal ? { margin: `0 ${paddingVal}px` } : undefined}\n >\n <div\n ref={navListRef}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-nav-list ant-tabs-nav-list tw-flex tw-overflow-hidden',\n isVertical && 'tw-flex-col',\n centered && !isVertical && 'tw-justify-center',\n monospace && '[&>*]:tw-flex-1',\n isCard ? 'tw-gap-1' : !monospace && 'tw-gap-8',\n )}\n style={\n !isVertical\n ? { scrollbarWidth: 'none', msOverflowStyle: 'none' }\n : undefined\n }\n >\n {resolvedItems.map((item) => {\n const isActive = activeKey === item.key;\n // For editable-card, closable defaults to true unless explicitly set to false\n const showClose = isEditable && item.closable !== false;\n\n return (\n <div\n key={item.key}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-tab ant-tabs-tab tw-relative tw-flex tw-shrink-0 tw-cursor-pointer tw-items-center tw-gap-2 tw-whitespace-nowrap tw-transition-colors',\n // Card / editable-card styling\n isCard\n ? cn(\n 'tw-h-10 tw-rounded-t-[6px] tw-border tw-border-b-0 tw-border-solid tw-px-4 tw-text-sm tw-leading-5',\n 'tw-gap-sp-75',\n isActive\n ? 'tw-border-[var(--alias-colors-border-default)] tw-bg-[var(--background-default)] tw-font-medium tw-text-[var(--alias-colors-text-selected)]'\n : 'tw-border-[var(--alias-colors-border-default)] tw-bg-[var(--alias-colors-bg-skeleton-subtler)] tw-text-[var(--alias-colors-text-subtle)] hover:tw-text-inherit',\n )\n : cn(\n size === 'small'\n ? 'tw-py-2 tw-text-xs tw-leading-4'\n : 'tw-py-2.5 tw-text-sm tw-leading-5',\n monospace && 'tw-justify-center',\n isActive\n ? 'tw-font-medium tw-text-[var(--alias-colors-text-selected)]'\n : 'tw-font-medium tw-text-[var(--alias-colors-text-subtle)] hover:tw-text-inherit',\n ),\n item.disabled &&\n 'tw-pointer-events-none tw-cursor-default tw-opacity-50',\n )}\n onClick={\n item.disabled\n ? undefined\n : (e) => handleTabClick(item.key, e)\n }\n >\n {item.icon}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n <span className=\"ant-tabs-tab-btn\">{item.label}</span>\n {/* Close button for editable-card */}\n {showClose && (\n <span\n className=\"ald-tabs-tab-remove tw-m-0 tw-grid tw-size-4 tw-cursor-pointer tw-place-items-center tw-p-0 tw-text-[var(--alias-colors-icon-subtle)] tw-transition-colors hover:tw-text-[var(--alias-colors-text-default)]\"\n onClick={(e) => handleRemove(item.key, e)}\n aria-label={`Remove ${item.label}`}\n >\n <CloseLightLine size={12} />\n </span>\n )}\n {/* Active indicator for non-card line tabs */}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n {!isCard && isActive && isTop && (\n <div className=\"ant-tabs-ink-bar tw-absolute tw-inset-x-0 tw--bottom-px tw-h-[2px] tw-rounded-[2px] tw-bg-[var(--alias-colors-border-selected)]\" />\n )}\n {!isCard && isActive && isBottom && (\n <div className=\"ant-tabs-ink-bar tw-absolute tw-inset-x-0 tw--top-px tw-h-[2px] tw-rounded-[2px] tw-bg-[var(--alias-colors-border-selected)]\" />\n )}\n {!isCard && isActive && isLeft && (\n <div className=\"tw-absolute tw-inset-y-0 tw--right-px tw-w-[2px] tw-rounded-[2px] tw-bg-[var(--alias-colors-border-selected)]\" />\n )}\n {!isCard && isActive && isRight && (\n <div className=\"tw-absolute tw-inset-y-0 tw--left-px tw-w-[2px] tw-rounded-[2px] tw-bg-[var(--alias-colors-border-selected)]\" />\n )}\n </div>\n );\n })}\n </div>\n </div>\n\n {/* Scroll right button */}\n {showScrollButtons && !isVertical && (\n <button\n type=\"button\"\n className={cn(\n 'ald-tabs-scroll-btn tw-flex tw-shrink-0 tw-items-center tw-justify-center tw-border-none tw-bg-transparent tw-p-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]',\n !canScrollRight && 'tw-invisible',\n )}\n onClick={() => scrollBy(200)}\n aria-label=\"Scroll tabs right\"\n >\n <ChevronRightLine size={16} />\n </button>\n )}\n\n {/* Add button for editable-card */}\n {isEditable && !hideAdd && (\n <button\n type=\"button\"\n className=\"ald-tabs-nav-add tw-ml-1 tw-flex tw-shrink-0 tw-cursor-pointer tw-items-center tw-justify-center tw-rounded tw-border tw-border-solid tw-border-[var(--border-default)] tw-bg-[var(--background-default)] tw-px-2 tw-py-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]\"\n onClick={handleAdd}\n aria-label=\"Add tab\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n </button>\n )}\n\n {extraRight}\n </div>\n\n {/* Tab content */}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n <div\n className={cn(\n 'ald-tabs-content ant-tabs-content ant-tabs-content-holder tw-min-h-0 tw-flex-1',\n adaptHeight && 'tw-h-full',\n )}\n style={\n paddingVal\n ? { padding: `0 ${paddingVal}px ${paddingVal}px` }\n : undefined\n }\n >\n {resolvedItems.map((item) => {\n const isActive = item.key === activeKey;\n if (!isActive && destroyInactiveTabPane && !item.forceRender) {\n return null;\n }\n return (\n <div\n key={item.key}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-tabpane ant-tabs-tabpane',\n // v2 行为:adaptHeight 时 tabpane 撑满内容区,子元素的百分比高度才能解析\n adaptHeight && 'tw-h-full tw-overflow-y-auto',\n isActive ? 'ant-tabs-tabpane-active tw-block' : 'tw-hidden',\n )}\n role=\"tabpanel\"\n >\n {item.children}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nTabs.TabPane = TabPane;\n"],"mappings":"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"}
@@ -15,7 +15,10 @@ interface CopyableConfig {
15
15
  onCopy?: () => void;
16
16
  tooltips?: [React.ReactNode, React.ReactNode];
17
17
  }
18
- interface TextProps {
18
+ type EllipsisConfig = boolean | {
19
+ rows?: number;
20
+ };
21
+ interface TextProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'type'> {
19
22
  className?: string;
20
23
  style?: React.CSSProperties;
21
24
  children?: React.ReactNode;
@@ -26,24 +29,24 @@ interface TextProps {
26
29
  code?: boolean;
27
30
  disabled?: boolean;
28
31
  type?: 'secondary' | 'success' | 'warning' | 'danger';
29
- ellipsis?: boolean;
32
+ ellipsis?: EllipsisConfig;
30
33
  copyable?: boolean | CopyableConfig;
31
34
  }
32
- interface TitleProps {
35
+ interface TitleProps extends React.HTMLAttributes<HTMLHeadingElement> {
33
36
  className?: string;
34
37
  style?: React.CSSProperties;
35
38
  children?: React.ReactNode;
36
39
  level?: 1 | 2 | 3 | 4 | 5;
37
- ellipsis?: boolean;
40
+ ellipsis?: EllipsisConfig;
38
41
  }
39
- interface ParagraphProps {
42
+ interface ParagraphProps extends React.HTMLAttributes<HTMLDivElement> {
40
43
  className?: string;
41
44
  style?: React.CSSProperties;
42
45
  children?: React.ReactNode;
43
- ellipsis?: boolean;
46
+ ellipsis?: EllipsisConfig;
44
47
  copyable?: boolean | CopyableConfig;
45
48
  }
46
- interface LinkProps {
49
+ interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
47
50
  className?: string;
48
51
  style?: React.CSSProperties;
49
52
  children?: React.ReactNode;
@@ -40,8 +40,9 @@ var Typography = ({ className, style, children }) => /* @__PURE__ */ jsx("articl
40
40
  style,
41
41
  children
42
42
  });
43
- Typography.Text = ({ className, style, children, strong, italic, underline, code, disabled, type, ellipsis, copyable, ...rest }) => {
44
- const del = rest.delete;
43
+ Typography.Text = ({ className, style, children, strong, italic, underline, code, disabled, type, ellipsis, copyable, delete: del, ...rest }) => {
44
+ const isEllipsis = Boolean(ellipsis);
45
+ const ellipsisRows = typeof ellipsis === "object" ? ellipsis.rows : void 0;
45
46
  let content = children;
46
47
  if (code) content = /* @__PURE__ */ jsx("code", { children: content });
47
48
  if (del) content = /* @__PURE__ */ jsx("del", { children: content });
@@ -49,34 +50,56 @@ Typography.Text = ({ className, style, children, strong, italic, underline, code
49
50
  if (italic) content = /* @__PURE__ */ jsx("i", { children: content });
50
51
  if (strong) content = /* @__PURE__ */ jsx("strong", { children: content });
51
52
  return /* @__PURE__ */ jsxs("span", {
52
- className: cn("ald-typography-text", disabled && "tw-cursor-not-allowed tw-opacity-50", type === "secondary" && "tw-text-[var(--content-secondary)]", type === "success" && "tw-text-[var(--content-positive-primary)]", type === "warning" && "tw-text-[var(--content-warning-primary)]", type === "danger" && "tw-text-[var(--content-negative-primary)]", ellipsis && "tw-truncate", className),
53
- style,
53
+ className: cn("ald-typography-text", disabled && "tw-cursor-not-allowed tw-opacity-50", type === "secondary" && "tw-text-[var(--content-secondary)]", type === "success" && "tw-text-[var(--content-positive-primary)]", type === "warning" && "tw-text-[var(--content-warning-primary)]", type === "danger" && "tw-text-[var(--content-negative-primary)]", isEllipsis && (ellipsisRows ? "tw-overflow-hidden" : "tw-truncate"), className),
54
+ style: {
55
+ ...style,
56
+ ...ellipsisRows ? {
57
+ display: "-webkit-box",
58
+ WebkitLineClamp: ellipsisRows,
59
+ WebkitBoxOrient: "vertical"
60
+ } : {}
61
+ },
62
+ ...rest,
54
63
  children: [content, copyable && /* @__PURE__ */ jsx(CopyButton, {
55
64
  copyable,
56
65
  children
57
66
  })]
58
67
  });
59
68
  };
60
- Typography.Title = ({ className, style, children, level = 1, ellipsis }) => {
69
+ Typography.Title = ({ className, style, children, level = 1, ellipsis, ...rest }) => {
61
70
  return /* @__PURE__ */ jsx(`h${level}`, {
62
- className: cn("ald-typography-title tw-font-semibold tw-text-[var(--content-primary)]", ellipsis && "tw-truncate", className),
71
+ className: cn("ald-typography-title tw-font-semibold tw-text-[var(--content-primary)]", Boolean(ellipsis) && "tw-truncate", className),
63
72
  style,
73
+ ...rest,
64
74
  children
65
75
  });
66
76
  };
67
- Typography.Paragraph = ({ className, style, children, ellipsis, copyable }) => /* @__PURE__ */ jsxs("div", {
68
- className: cn("ald-typography-paragraph", ellipsis && "tw-truncate", className),
69
- style,
70
- children: [children, copyable && /* @__PURE__ */ jsx(CopyButton, {
71
- copyable,
72
- children
73
- })]
74
- });
75
- Typography.Link = ({ className, style, children, href, target }) => /* @__PURE__ */ jsx("a", {
77
+ Typography.Paragraph = ({ className, style, children, ellipsis, copyable, ...rest }) => {
78
+ const isEllipsis = Boolean(ellipsis);
79
+ const ellipsisRows = typeof ellipsis === "object" ? ellipsis.rows : void 0;
80
+ return /* @__PURE__ */ jsxs("div", {
81
+ className: cn("ald-typography-paragraph", isEllipsis && (ellipsisRows ? "tw-overflow-hidden" : "tw-truncate"), className),
82
+ style: {
83
+ ...style,
84
+ ...ellipsisRows ? {
85
+ display: "-webkit-box",
86
+ WebkitLineClamp: ellipsisRows,
87
+ WebkitBoxOrient: "vertical"
88
+ } : {}
89
+ },
90
+ ...rest,
91
+ children: [children, copyable && /* @__PURE__ */ jsx(CopyButton, {
92
+ copyable,
93
+ children
94
+ })]
95
+ });
96
+ };
97
+ Typography.Link = ({ className, style, children, href, target, ...rest }) => /* @__PURE__ */ jsx("a", {
76
98
  className: cn("ald-typography-link tw-text-[var(--alias-colors-link-default)] hover:tw-text-[var(--alias-colors-link-hover)]", className),
77
99
  style,
78
100
  href,
79
101
  target,
102
+ ...rest,
80
103
  children
81
104
  });
82
105
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/Typography/index.tsx"],"sourcesContent":["import React, { useCallback, useState } from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface TypographyProps {\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n}\n\ninterface TypographyComponent extends React.FC<TypographyProps> {\n Text: React.FC<TextProps>;\n Title: React.FC<TitleProps>;\n Paragraph: React.FC<ParagraphProps>;\n Link: React.FC<LinkProps>;\n}\n\ninterface CopyableConfig {\n text?: string;\n onCopy?: () => void;\n tooltips?: [React.ReactNode, React.ReactNode];\n}\n\ninterface TextProps {\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n strong?: boolean;\n italic?: boolean;\n underline?: boolean;\n delete?: boolean;\n code?: boolean;\n disabled?: boolean;\n type?: 'secondary' | 'success' | 'warning' | 'danger';\n ellipsis?: boolean;\n copyable?: boolean | CopyableConfig;\n}\n\ninterface TitleProps {\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n level?: 1 | 2 | 3 | 4 | 5;\n ellipsis?: boolean;\n}\n\ninterface ParagraphProps {\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n ellipsis?: boolean;\n copyable?: boolean | CopyableConfig;\n}\n\ninterface LinkProps {\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n href?: string;\n target?: string;\n}\n\nfunction CopyButton({\n copyable,\n children,\n}: {\n copyable: boolean | CopyableConfig;\n children: React.ReactNode;\n}) {\n const [copied, setCopied] = useState(false);\n\n const handleCopy = useCallback(() => {\n const config =\n typeof copyable === 'object' ? copyable : ({} as CopyableConfig);\n const textToCopy =\n config.text ?? (typeof children === 'string' ? children : '');\n navigator.clipboard.writeText(String(textToCopy)).then(() => {\n setCopied(true);\n config.onCopy?.();\n setTimeout(() => setCopied(false), 2000);\n });\n }, [copyable, children]);\n\n return (\n <span\n role=\"button\"\n tabIndex={0}\n className=\"ald-typography-copy tw-ml-1 tw-inline-flex tw-cursor-pointer tw-align-middle tw-text-[var(--content-secondary)] hover:tw-text-[var(--content-primary)]\"\n onClick={handleCopy}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') handleCopy();\n }}\n aria-label=\"Copy\"\n >\n {copied ? (\n <span className=\"tw-text-xs tw-text-[var(--content-positive-primary)]\">\n Copied!\n </span>\n ) : (\n <svg\n viewBox=\"0 0 16 16\"\n width=\"1em\"\n height=\"1em\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M4 2a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V2zm2-1a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H6z\" />\n <path d=\"M2 4a1 1 0 0 0-1 1v9a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1v-1h1v1a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h1v1H2z\" />\n </svg>\n )}\n </span>\n );\n}\n\nconst Typography: TypographyComponent = ({ className, style, children }) => (\n <article className={cn('ald-typography', className)} style={style}>\n {children}\n </article>\n);\n\nTypography.Text = ({\n className,\n style,\n children,\n strong,\n italic,\n underline,\n code,\n disabled,\n type,\n ellipsis,\n copyable,\n ...rest\n}) => {\n const del = (rest as { delete?: boolean }).delete;\n let content: React.ReactNode = children;\n if (code) content = <code>{content}</code>;\n if (del) content = <del>{content}</del>;\n if (underline) content = <u>{content}</u>;\n if (italic) content = <i>{content}</i>;\n if (strong) content = <strong>{content}</strong>;\n\n return (\n <span\n className={cn(\n 'ald-typography-text',\n disabled && 'tw-cursor-not-allowed tw-opacity-50',\n type === 'secondary' && 'tw-text-[var(--content-secondary)]',\n type === 'success' && 'tw-text-[var(--content-positive-primary)]',\n type === 'warning' && 'tw-text-[var(--content-warning-primary)]',\n type === 'danger' && 'tw-text-[var(--content-negative-primary)]',\n ellipsis && 'tw-truncate',\n className,\n )}\n style={style}\n >\n {content}\n {copyable && <CopyButton copyable={copyable}>{children}</CopyButton>}\n </span>\n );\n};\n\nTypography.Title = ({ className, style, children, level = 1, ellipsis }) => {\n const Tag = `h${level}` as keyof JSX.IntrinsicElements;\n return (\n <Tag\n className={cn(\n 'ald-typography-title tw-font-semibold tw-text-[var(--content-primary)]',\n ellipsis && 'tw-truncate',\n className,\n )}\n style={style}\n >\n {children}\n </Tag>\n );\n};\n\nTypography.Paragraph = ({ className, style, children, ellipsis, copyable }) => (\n <div\n className={cn(\n 'ald-typography-paragraph',\n ellipsis && 'tw-truncate',\n className,\n )}\n style={style}\n >\n {children}\n {copyable && <CopyButton copyable={copyable}>{children}</CopyButton>}\n </div>\n);\n\nTypography.Link = ({ className, style, children, href, target }) => (\n <a\n className={cn(\n 'ald-typography-link tw-text-[var(--alias-colors-link-default)] hover:tw-text-[var(--alias-colors-link-hover)]',\n className,\n )}\n style={style}\n href={href}\n target={target}\n >\n {children}\n </a>\n);\n\nexport default Typography;\n"],"mappings":";;;;AA6DA,SAAS,WAAW,EAClB,UACA,YAIC;CACD,MAAM,CAAC,QAAQ,aAAa,SAAS,MAAM;CAE3C,MAAM,aAAa,kBAAkB;EACnC,MAAM,SACJ,OAAO,aAAa,WAAW,WAAY,EAAE;EAC/C,MAAM,aACJ,OAAO,SAAS,OAAO,aAAa,WAAW,WAAW;AAC5D,YAAU,UAAU,UAAU,OAAO,WAAW,CAAC,CAAC,WAAW;AAC3D,aAAU,KAAK;AACf,UAAO,UAAU;AACjB,oBAAiB,UAAU,MAAM,EAAE,IAAK;IACxC;IACD,CAAC,UAAU,SAAS,CAAC;AAExB,QACE,oBAAC,QAAD;EACE,MAAK;EACL,UAAU;EACV,WAAU;EACV,SAAS;EACT,YAAY,MAAM;AAChB,OAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,IAAK,aAAY;;EAEtD,cAAW;YAEV,SACC,oBAAC,QAAD;GAAM,WAAU;aAAuD;GAEhE,CAAA,GAEP,qBAAC,OAAD;GACE,SAAQ;GACR,OAAM;GACN,QAAO;GACP,MAAK;GACL,eAAY;aALd,CAOE,oBAAC,QAAD,EAAM,GAAE,8IAA+I,CAAA,EACvJ,oBAAC,QAAD,EAAM,GAAE,kHAAmH,CAAA,CACvH;;EAEH,CAAA;;AAIX,IAAM,cAAmC,EAAE,WAAW,OAAO,eAC3D,oBAAC,WAAD;CAAS,WAAW,GAAG,kBAAkB,UAAU;CAAS;CACzD;CACO,CAAA;AAGZ,WAAW,QAAQ,EACjB,WACA,OACA,UACA,QACA,QACA,WACA,MACA,UACA,MACA,UACA,UACA,GAAG,WACC;CACJ,MAAM,MAAO,KAA8B;CAC3C,IAAI,UAA2B;AAC/B,KAAI,KAAM,WAAU,oBAAC,QAAD,EAAA,UAAO,SAAe,CAAA;AAC1C,KAAI,IAAK,WAAU,oBAAC,OAAD,EAAA,UAAM,SAAc,CAAA;AACvC,KAAI,UAAW,WAAU,oBAAC,KAAD,EAAA,UAAI,SAAY,CAAA;AACzC,KAAI,OAAQ,WAAU,oBAAC,KAAD,EAAA,UAAI,SAAY,CAAA;AACtC,KAAI,OAAQ,WAAU,oBAAC,UAAD,EAAA,UAAS,SAAiB,CAAA;AAEhD,QACE,qBAAC,QAAD;EACE,WAAW,GACT,uBACA,YAAY,uCACZ,SAAS,eAAe,sCACxB,SAAS,aAAa,6CACtB,SAAS,aAAa,4CACtB,SAAS,YAAY,6CACrB,YAAY,eACZ,UACD;EACM;YAXT,CAaG,SACA,YAAY,oBAAC,YAAD;GAAsB;GAAW;GAAsB,CAAA,CAC/D;;;AAIX,WAAW,SAAS,EAAE,WAAW,OAAO,UAAU,QAAQ,GAAG,eAAe;AAE1E,QACE,oBAFU,IAAI,SAEd;EACE,WAAW,GACT,0EACA,YAAY,eACZ,UACD;EACM;EAEN;EACG,CAAA;;AAIV,WAAW,aAAa,EAAE,WAAW,OAAO,UAAU,UAAU,eAC9D,qBAAC,OAAD;CACE,WAAW,GACT,4BACA,YAAY,eACZ,UACD;CACM;WANT,CAQG,UACA,YAAY,oBAAC,YAAD;EAAsB;EAAW;EAAsB,CAAA,CAChE;;AAGR,WAAW,QAAQ,EAAE,WAAW,OAAO,UAAU,MAAM,aACrD,oBAAC,KAAD;CACE,WAAW,GACT,iHACA,UACD;CACM;CACD;CACE;CAEP;CACC,CAAA"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/Typography/index.tsx"],"sourcesContent":["import React, { useCallback, useState } from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface TypographyProps {\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n}\n\ninterface TypographyComponent extends React.FC<TypographyProps> {\n Text: React.FC<TextProps>;\n Title: React.FC<TitleProps>;\n Paragraph: React.FC<ParagraphProps>;\n Link: React.FC<LinkProps>;\n}\n\ninterface CopyableConfig {\n text?: string;\n onCopy?: () => void;\n tooltips?: [React.ReactNode, React.ReactNode];\n}\n\ntype EllipsisConfig = boolean | { rows?: number };\n\ninterface TextProps\n extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'type'> {\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n strong?: boolean;\n italic?: boolean;\n underline?: boolean;\n delete?: boolean;\n code?: boolean;\n disabled?: boolean;\n type?: 'secondary' | 'success' | 'warning' | 'danger';\n ellipsis?: EllipsisConfig;\n copyable?: boolean | CopyableConfig;\n}\n\ninterface TitleProps extends React.HTMLAttributes<HTMLHeadingElement> {\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n level?: 1 | 2 | 3 | 4 | 5;\n ellipsis?: EllipsisConfig;\n}\n\ninterface ParagraphProps extends React.HTMLAttributes<HTMLDivElement> {\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n ellipsis?: EllipsisConfig;\n copyable?: boolean | CopyableConfig;\n}\n\ninterface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n href?: string;\n target?: string;\n}\n\nfunction CopyButton({\n copyable,\n children,\n}: {\n copyable: boolean | CopyableConfig;\n children: React.ReactNode;\n}) {\n const [copied, setCopied] = useState(false);\n\n const handleCopy = useCallback(() => {\n const config =\n typeof copyable === 'object' ? copyable : ({} as CopyableConfig);\n const textToCopy =\n config.text ?? (typeof children === 'string' ? children : '');\n navigator.clipboard.writeText(String(textToCopy)).then(() => {\n setCopied(true);\n config.onCopy?.();\n setTimeout(() => setCopied(false), 2000);\n });\n }, [copyable, children]);\n\n return (\n <span\n role=\"button\"\n tabIndex={0}\n className=\"ald-typography-copy tw-ml-1 tw-inline-flex tw-cursor-pointer tw-align-middle tw-text-[var(--content-secondary)] hover:tw-text-[var(--content-primary)]\"\n onClick={handleCopy}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') handleCopy();\n }}\n aria-label=\"Copy\"\n >\n {copied ? (\n <span className=\"tw-text-xs tw-text-[var(--content-positive-primary)]\">\n Copied!\n </span>\n ) : (\n <svg\n viewBox=\"0 0 16 16\"\n width=\"1em\"\n height=\"1em\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M4 2a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V2zm2-1a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H6z\" />\n <path d=\"M2 4a1 1 0 0 0-1 1v9a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1v-1h1v1a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h1v1H2z\" />\n </svg>\n )}\n </span>\n );\n}\n\nconst Typography: TypographyComponent = ({ className, style, children }) => (\n <article className={cn('ald-typography', className)} style={style}>\n {children}\n </article>\n);\n\nTypography.Text = ({\n className,\n style,\n children,\n strong,\n italic,\n underline,\n code,\n disabled,\n type,\n ellipsis,\n copyable,\n delete: del,\n ...rest\n}) => {\n const isEllipsis = Boolean(ellipsis);\n const ellipsisRows = typeof ellipsis === 'object' ? ellipsis.rows : undefined;\n let content: React.ReactNode = children;\n if (code) content = <code>{content}</code>;\n if (del) content = <del>{content}</del>;\n if (underline) content = <u>{content}</u>;\n if (italic) content = <i>{content}</i>;\n if (strong) content = <strong>{content}</strong>;\n\n return (\n <span\n className={cn(\n 'ald-typography-text',\n disabled && 'tw-cursor-not-allowed tw-opacity-50',\n type === 'secondary' && 'tw-text-[var(--content-secondary)]',\n type === 'success' && 'tw-text-[var(--content-positive-primary)]',\n type === 'warning' && 'tw-text-[var(--content-warning-primary)]',\n type === 'danger' && 'tw-text-[var(--content-negative-primary)]',\n isEllipsis && (ellipsisRows ? 'tw-overflow-hidden' : 'tw-truncate'),\n className,\n )}\n style={{\n ...style,\n ...(ellipsisRows\n ? {\n display: '-webkit-box',\n WebkitLineClamp: ellipsisRows,\n WebkitBoxOrient: 'vertical',\n }\n : {}),\n }}\n {...rest}\n >\n {content}\n {copyable && <CopyButton copyable={copyable}>{children}</CopyButton>}\n </span>\n );\n};\n\nTypography.Title = ({\n className,\n style,\n children,\n level = 1,\n ellipsis,\n ...rest\n}) => {\n const Tag = `h${level}` as React.ElementType;\n const isEllipsis = Boolean(ellipsis);\n return (\n <Tag\n className={cn(\n 'ald-typography-title tw-font-semibold tw-text-[var(--content-primary)]',\n isEllipsis && 'tw-truncate',\n className,\n )}\n style={style}\n {...rest}\n >\n {children}\n </Tag>\n );\n};\n\nTypography.Paragraph = ({\n className,\n style,\n children,\n ellipsis,\n copyable,\n ...rest\n}) => {\n const isEllipsis = Boolean(ellipsis);\n const ellipsisRows = typeof ellipsis === 'object' ? ellipsis.rows : undefined;\n\n return (\n <div\n className={cn(\n 'ald-typography-paragraph',\n isEllipsis && (ellipsisRows ? 'tw-overflow-hidden' : 'tw-truncate'),\n className,\n )}\n style={{\n ...style,\n ...(ellipsisRows\n ? {\n display: '-webkit-box',\n WebkitLineClamp: ellipsisRows,\n WebkitBoxOrient: 'vertical',\n }\n : {}),\n }}\n {...rest}\n >\n {children}\n {copyable && <CopyButton copyable={copyable}>{children}</CopyButton>}\n </div>\n );\n};\n\nTypography.Link = ({ className, style, children, href, target, ...rest }) => (\n <a\n className={cn(\n 'ald-typography-link tw-text-[var(--alias-colors-link-default)] hover:tw-text-[var(--alias-colors-link-hover)]',\n className,\n )}\n style={style}\n href={href}\n target={target}\n {...rest}\n >\n {children}\n </a>\n);\n\nexport default Typography;\n"],"mappings":"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"}
@@ -32,7 +32,7 @@ export interface UploadProps<T = any> {
32
32
  headers?: Record<string, string>;
33
33
  data?: Record<string, unknown> | ((file: RcFile | string | Blob) => Record<string, unknown>);
34
34
  withCredentials?: boolean;
35
- beforeUpload?: (file: RcFile, fileList: RcFile[]) => boolean | Promise<void | Blob | File>;
35
+ beforeUpload?: (file: RcFile, fileList: RcFile[]) => boolean | void | Blob | File | Promise<boolean | void | Blob | File>;
36
36
  customRequest?: (options: {
37
37
  file: RcFile;
38
38
  filename?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/Upload/index.tsx"],"sourcesContent":["import './upload.css';\n\nimport RcUpload from 'rc-upload';\nimport type {\n RcFile as RcUploadFile,\n UploadProgressEvent,\n UploadProps as RcUploadProps,\n} from 'rc-upload/es/interface';\nimport React, { useCallback, useMemo, useRef, useState } from 'react';\nimport {\n CheckCircleFill,\n CloseCircleFill,\n CloseLightLine,\n EyeOnLine,\n LoadingLine,\n TrashLightLine,\n} from '../Icon';\nimport { cn } from '../lib/utils';\nimport Tooltip from '../Tooltip';\n\n// ---------------------------------------------------------------------------\n// Public types – preserved from the previous API surface\n// ---------------------------------------------------------------------------\n\nexport interface UploadFile<T = any> {\n uid: string;\n name: string;\n status?: 'uploading' | 'done' | 'error' | 'removed';\n url?: string;\n thumbUrl?: string;\n size?: number;\n type?: string;\n percent?: number;\n originFileObj?: RcFile;\n response?: T;\n error?: any;\n linkProps?: any;\n}\n\nexport type RcFile = RcUploadFile;\n\nexport interface UploadChangeParam<T = UploadFile> {\n file: T;\n fileList: T[];\n event?: UploadProgressEvent;\n}\n\nexport interface ShowUploadListInterface {\n showRemoveIcon?: boolean;\n showPreviewIcon?: boolean;\n showDownloadIcon?: boolean;\n}\n\nexport interface UploadProps<T = any> {\n accept?: string;\n action?: string | ((file: RcFile) => string | Promise<string>);\n method?: 'POST' | 'PUT' | 'PATCH' | 'post' | 'put' | 'patch';\n headers?: Record<string, string>;\n data?:\n | Record<string, unknown>\n | ((file: RcFile | string | Blob) => Record<string, unknown>);\n withCredentials?: boolean;\n beforeUpload?: (\n file: RcFile,\n fileList: RcFile[],\n ) => boolean | Promise<void | Blob | File>;\n customRequest?: (options: {\n file: RcFile;\n filename?: string;\n data?: Record<string, unknown>;\n headers?: Record<string, string>;\n onProgress?: (event: { percent: number }) => void;\n onSuccess?: (body: unknown, xhr?: XMLHttpRequest) => void;\n onError?: (event: Error) => void;\n withCredentials?: boolean;\n action?: string;\n method?: string;\n }) => void;\n disabled?: boolean;\n fileList?: UploadFile<T>[];\n defaultFileList?: UploadFile<T>[];\n maxCount?: number;\n multiple?: boolean;\n directory?: boolean;\n name?: string;\n listType?: 'text' | 'picture' | 'picture-card';\n showUploadList?: boolean | ShowUploadListInterface;\n onChange?: (info: UploadChangeParam<UploadFile<T>>) => void;\n onRemove?: (file: UploadFile<T>) => void | boolean | Promise<void | boolean>;\n onPreview?: (file: UploadFile<T>) => void;\n onDownload?: (file: UploadFile<T>) => void;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n openFileDialogOnClick?: boolean;\n /** @deprecated Use `id` instead */\n prefixCls?: string;\n id?: string;\n}\n\nexport interface UploadListProps {\n items?: UploadFile[];\n listType?: 'text' | 'picture' | 'picture-card';\n showUploadList?: boolean | ShowUploadListInterface;\n onRemove?: (file: UploadFile) => void;\n onPreview?: (file: UploadFile) => void;\n onDownload?: (file: UploadFile) => void;\n disabled?: boolean;\n}\n\nexport interface DraggerProps extends UploadProps {\n height?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nlet fileUid = 0;\n\nfunction getUid(): string {\n fileUid += 1;\n return `ald-upload-${Date.now()}-${fileUid}`;\n}\n\nfunction fileToUploadFile(\n file: RcFile,\n status: UploadFile['status'] = 'uploading',\n): UploadFile {\n return {\n uid: file.uid ?? getUid(),\n name: file.name,\n size: file.size,\n type: file.type,\n status,\n percent: 0,\n originFileObj: file,\n };\n}\n\nfunction isImageUrl(file: UploadFile): boolean {\n if (file.type) return file.type.startsWith('image/');\n const ext = file.name?.split('.').pop()?.toLowerCase() ?? '';\n return ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp', 'svg', 'ico'].includes(\n ext,\n );\n}\n\nfunction getThumbUrl(file: UploadFile): string | undefined {\n if (file.thumbUrl) return file.thumbUrl;\n if (file.url) return file.url;\n if (file.originFileObj && isImageUrl(file)) {\n try {\n return URL.createObjectURL(file.originFileObj);\n } catch {\n return undefined;\n }\n }\n return undefined;\n}\n\n// ---------------------------------------------------------------------------\n// UploadList\n// ---------------------------------------------------------------------------\n\nfunction UploadList({\n items = [],\n listType = 'text',\n showUploadList = true,\n onRemove,\n onPreview,\n disabled,\n}: UploadListProps) {\n if (!showUploadList || items.length === 0) return null;\n\n const showConfig: ShowUploadListInterface =\n typeof showUploadList === 'object'\n ? showUploadList\n : {\n showRemoveIcon: true,\n showPreviewIcon: true,\n showDownloadIcon: false,\n };\n\n const isPictureType = listType === 'picture' || listType === 'picture-card';\n\n return (\n <ul className={cn('ald-upload-list', `ald-upload-list-${listType}`)}>\n {items.map((file) => {\n const thumbUrl = isPictureType ? getThumbUrl(file) : undefined;\n\n return (\n <li\n key={file.uid}\n className={cn(\n 'ald-upload-list-item',\n `ald-upload-list-item-${file.status || 'done'}`,\n )}\n >\n {/* Thumbnail for picture types */}\n {isPictureType && (\n <div className=\"ald-upload-list-item-thumbnail\">\n {thumbUrl ? (\n <img src={thumbUrl} alt={file.name} />\n ) : (\n <div className=\"ald-upload-list-item-file-icon\">\n <FileIcon />\n </div>\n )}\n </div>\n )}\n\n {/* Status icon for text type */}\n {!isPictureType && (\n <span className=\"ald-upload-list-item-status-icon\">\n {file.status === 'uploading' && (\n <span className=\"ald-upload-list-item-loading-icon\">\n <LoadingLine style={{ fontSize: 14 }} />\n </span>\n )}\n {file.status === 'done' && (\n <CheckCircleFill style={{ fontSize: 14 }} />\n )}\n {file.status === 'error' && (\n <CloseCircleFill style={{ fontSize: 14 }} />\n )}\n </span>\n )}\n\n {/* File name */}\n <Tooltip title={file.name}>\n <span\n className=\"ald-upload-list-item-name\"\n onClick={() => onPreview?.(file)}\n style={onPreview ? { cursor: 'pointer' } : undefined}\n >\n {file.name}\n </span>\n </Tooltip>\n\n {/* Actions */}\n <span className=\"ald-upload-list-item-actions\">\n {showConfig.showPreviewIcon &&\n onPreview &&\n file.status === 'done' && (\n <button\n type=\"button\"\n className=\"ald-upload-list-item-action\"\n title=\"Preview\"\n onClick={() => onPreview(file)}\n >\n <EyeOnLine style={{ fontSize: 14 }} />\n </button>\n )}\n {showConfig.showRemoveIcon !== false && !disabled && (\n <button\n type=\"button\"\n className=\"ald-upload-list-item-action\"\n title=\"Remove\"\n onClick={() => onRemove?.(file)}\n >\n {listType === 'picture-card' ? (\n <TrashLightLine style={{ fontSize: 14 }} />\n ) : (\n <CloseLightLine style={{ fontSize: 14 }} />\n )}\n </button>\n )}\n </span>\n\n {/* Progress bar */}\n {file.status === 'uploading' && (\n <div className=\"ald-upload-list-item-progress\">\n <div\n className=\"ald-upload-list-item-progress-bar\"\n style={{ width: `${file.percent ?? 0}%` }}\n />\n </div>\n )}\n </li>\n );\n })}\n </ul>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Simple file icon SVG (inline to avoid extra dependency)\n// ---------------------------------------------------------------------------\n\nfunction FileIcon() {\n return (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n </svg>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Upload component\n// ---------------------------------------------------------------------------\n\nfunction Upload<T = any>(props: UploadProps<T>) {\n const {\n accept,\n action,\n method,\n headers,\n data,\n withCredentials,\n beforeUpload,\n customRequest,\n disabled = false,\n fileList: controlledFileList,\n defaultFileList,\n maxCount,\n multiple,\n directory,\n name = 'file',\n listType = 'text',\n showUploadList = true,\n onChange,\n onRemove,\n onPreview,\n onDownload,\n className,\n style,\n children,\n openFileDialogOnClick = true,\n id,\n } = props;\n\n const isControlled = controlledFileList !== undefined;\n const [internalFileList, setInternalFileList] = useState<UploadFile<T>[]>(\n defaultFileList ?? [],\n );\n\n const mergedFileList = isControlled ? controlledFileList! : internalFileList;\n\n // Keep a ref to latest list so callbacks always see fresh state\n const fileListRef = useRef(mergedFileList);\n fileListRef.current = mergedFileList;\n\n const rcUploadRef = useRef<any>(null);\n\n // ----- helpers to update state & fire onChange -----\n\n const updateFileList = useCallback(\n (newFile: UploadFile<T>, event?: UploadProgressEvent) => {\n const nextList = fileListRef.current.map((f) =>\n f.uid === newFile.uid ? newFile : f,\n );\n // If the file is new, append it\n if (!nextList.some((f) => f.uid === newFile.uid)) {\n nextList.push(newFile);\n }\n if (!isControlled) {\n setInternalFileList(nextList);\n }\n onChange?.({\n file: newFile,\n fileList: nextList,\n event,\n });\n },\n [isControlled, onChange],\n );\n\n // ----- rc-upload callback props -----\n\n const onBatchStart: RcUploadProps['onBatchStart'] = useCallback(\n (batchFileInfoList: { file: RcFile; parsedFile: any }[]) => {\n let nextList = [...fileListRef.current];\n\n for (const { file } of batchFileInfoList) {\n const uploadFile = fileToUploadFile(file, 'uploading') as UploadFile<T>;\n\n if (maxCount && nextList.length >= maxCount) {\n // replace if maxCount === 1, otherwise skip\n if (maxCount === 1) {\n nextList = [uploadFile];\n }\n continue;\n }\n nextList.push(uploadFile);\n }\n\n if (!isControlled) {\n setInternalFileList(nextList);\n }\n\n // Fire onChange for the first new file\n const firstNew = batchFileInfoList[0];\n if (firstNew) {\n const f = nextList.find((x) => x.uid === firstNew.file.uid);\n if (f) {\n onChange?.({ file: f, fileList: nextList });\n }\n }\n },\n [isControlled, maxCount, onChange],\n );\n\n const onRcProgress = useCallback(\n (event: UploadProgressEvent, file: RcFile) => {\n const target = fileListRef.current.find((f) => f.uid === file.uid);\n if (!target) return;\n const updated: UploadFile<T> = {\n ...target,\n status: 'uploading',\n percent: event.percent ?? 0,\n };\n updateFileList(updated, event);\n },\n [updateFileList],\n );\n\n const onRcSuccess = useCallback(\n (response: any, file: RcFile) => {\n const target = fileListRef.current.find((f) => f.uid === file.uid);\n if (!target) return;\n const updated: UploadFile<T> = {\n ...target,\n status: 'done',\n percent: 100,\n response,\n };\n updateFileList(updated);\n },\n [updateFileList],\n );\n\n const onRcError = useCallback(\n (error: Error, _ret: any, file: RcFile) => {\n const target = fileListRef.current.find((f) => f.uid === file.uid);\n if (!target) return;\n const updated: UploadFile<T> = {\n ...target,\n status: 'error',\n error,\n };\n updateFileList(updated);\n },\n [updateFileList],\n );\n\n // ----- remove handler -----\n\n const handleRemove = useCallback(\n async (file: UploadFile<T>) => {\n const result = await onRemove?.(file as any);\n if (result === false) return;\n const nextList = fileListRef.current.filter((f) => f.uid !== file.uid);\n if (!isControlled) {\n setInternalFileList(nextList);\n }\n const removedFile: UploadFile<T> = { ...file, status: 'removed' };\n onChange?.({ file: removedFile, fileList: nextList });\n },\n [isControlled, onChange, onRemove],\n );\n\n // ----- rc-upload props -----\n\n const rcUploadProps: RcUploadProps = useMemo(\n () => ({\n accept,\n action: action as RcUploadProps['action'],\n method,\n headers,\n data: data as RcUploadProps['data'],\n withCredentials,\n beforeUpload: beforeUpload as RcUploadProps['beforeUpload'],\n customRequest: customRequest as RcUploadProps['customRequest'],\n disabled,\n multiple,\n directory,\n name,\n openFileDialogOnClick,\n id,\n prefixCls: 'ald-upload',\n onBatchStart,\n onProgress: onRcProgress,\n onSuccess: onRcSuccess,\n onError: onRcError,\n }),\n [\n accept,\n action,\n method,\n headers,\n data,\n withCredentials,\n beforeUpload,\n customRequest,\n disabled,\n multiple,\n directory,\n name,\n openFileDialogOnClick,\n id,\n onBatchStart,\n onRcProgress,\n onRcSuccess,\n onRcError,\n ],\n );\n\n const isPictureCard = listType === 'picture-card';\n\n return (\n <span\n className={cn(\n 'ald-upload',\n { 'ald-upload-disabled': disabled },\n className,\n )}\n style={style}\n >\n {isPictureCard ? (\n // picture-card: render list first, then the upload trigger\n <>\n <UploadList\n items={mergedFileList as UploadFile[]}\n listType={listType}\n showUploadList={showUploadList}\n onRemove={handleRemove as any}\n onPreview={onPreview as any}\n onDownload={onDownload as any}\n disabled={disabled}\n />\n {(!maxCount || mergedFileList.length < maxCount) && (\n <RcUpload {...rcUploadProps} ref={rcUploadRef}>\n <div className=\"ald-upload-select\">{children}</div>\n </RcUpload>\n )}\n </>\n ) : (\n // text / picture: render trigger then list\n <>\n <RcUpload {...rcUploadProps} ref={rcUploadRef}>\n <div className=\"ald-upload-select\">{children}</div>\n </RcUpload>\n <UploadList\n items={mergedFileList as UploadFile[]}\n listType={listType}\n showUploadList={showUploadList}\n onRemove={handleRemove as any}\n onPreview={onPreview as any}\n onDownload={onDownload as any}\n disabled={disabled}\n />\n </>\n )}\n </span>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Dragger sub-component\n// ---------------------------------------------------------------------------\n\nfunction Dragger(props: DraggerProps) {\n const { height, style, disabled, className, children, ...restProps } = props;\n const [dragOver, setDragOver] = useState(false);\n\n const mergedStyle: React.CSSProperties = {\n ...style,\n ...(height !== null && height !== undefined ? { height } : {}),\n };\n\n return (\n <Upload\n {...restProps}\n disabled={disabled}\n className={cn('ald-upload-dragger-wrapper', className)}\n style={mergedStyle}\n >\n <div\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n className={cn('ald-upload-dragger ant-upload-drag', {\n 'ald-upload-drag-hover': dragOver,\n 'ant-upload-drag-hover': dragOver,\n 'ald-upload-disabled': disabled,\n 'ant-upload-disabled': disabled,\n })}\n onDragOver={(e) => {\n e.preventDefault();\n if (!disabled) setDragOver(true);\n }}\n onDragLeave={() => setDragOver(false)}\n onDrop={() => setDragOver(false)}\n >\n {children}\n </div>\n </Upload>\n );\n}\n\nUpload.Dragger = Dragger;\n\nexport default Upload as typeof Upload & { Dragger: typeof Dragger };\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/Upload/index.tsx"],"sourcesContent":["import './upload.css';\n\nimport RcUpload from 'rc-upload';\nimport type {\n RcFile as RcUploadFile,\n UploadProgressEvent,\n UploadProps as RcUploadProps,\n} from 'rc-upload/es/interface';\nimport React, { useCallback, useMemo, useRef, useState } from 'react';\nimport {\n CheckCircleFill,\n CloseCircleFill,\n CloseLightLine,\n EyeOnLine,\n LoadingLine,\n TrashLightLine,\n} from '../Icon';\nimport { cn } from '../lib/utils';\nimport Tooltip from '../Tooltip';\n\n// ---------------------------------------------------------------------------\n// Public types – preserved from the previous API surface\n// ---------------------------------------------------------------------------\n\nexport interface UploadFile<T = any> {\n uid: string;\n name: string;\n status?: 'uploading' | 'done' | 'error' | 'removed';\n url?: string;\n thumbUrl?: string;\n size?: number;\n type?: string;\n percent?: number;\n originFileObj?: RcFile;\n response?: T;\n error?: any;\n linkProps?: any;\n}\n\nexport type RcFile = RcUploadFile;\n\nexport interface UploadChangeParam<T = UploadFile> {\n file: T;\n fileList: T[];\n event?: UploadProgressEvent;\n}\n\nexport interface ShowUploadListInterface {\n showRemoveIcon?: boolean;\n showPreviewIcon?: boolean;\n showDownloadIcon?: boolean;\n}\n\nexport interface UploadProps<T = any> {\n accept?: string;\n action?: string | ((file: RcFile) => string | Promise<string>);\n method?: 'POST' | 'PUT' | 'PATCH' | 'post' | 'put' | 'patch';\n headers?: Record<string, string>;\n data?:\n | Record<string, unknown>\n | ((file: RcFile | string | Blob) => Record<string, unknown>);\n withCredentials?: boolean;\n beforeUpload?: (\n file: RcFile,\n fileList: RcFile[],\n ) => boolean | void | Blob | File | Promise<boolean | void | Blob | File>;\n customRequest?: (options: {\n file: RcFile;\n filename?: string;\n data?: Record<string, unknown>;\n headers?: Record<string, string>;\n onProgress?: (event: { percent: number }) => void;\n onSuccess?: (body: unknown, xhr?: XMLHttpRequest) => void;\n onError?: (event: Error) => void;\n withCredentials?: boolean;\n action?: string;\n method?: string;\n }) => void;\n disabled?: boolean;\n fileList?: UploadFile<T>[];\n defaultFileList?: UploadFile<T>[];\n maxCount?: number;\n multiple?: boolean;\n directory?: boolean;\n name?: string;\n listType?: 'text' | 'picture' | 'picture-card';\n showUploadList?: boolean | ShowUploadListInterface;\n onChange?: (info: UploadChangeParam<UploadFile<T>>) => void;\n onRemove?: (file: UploadFile<T>) => void | boolean | Promise<void | boolean>;\n onPreview?: (file: UploadFile<T>) => void;\n onDownload?: (file: UploadFile<T>) => void;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n openFileDialogOnClick?: boolean;\n /** @deprecated Use `id` instead */\n prefixCls?: string;\n id?: string;\n}\n\nexport interface UploadListProps {\n items?: UploadFile[];\n listType?: 'text' | 'picture' | 'picture-card';\n showUploadList?: boolean | ShowUploadListInterface;\n onRemove?: (file: UploadFile) => void;\n onPreview?: (file: UploadFile) => void;\n onDownload?: (file: UploadFile) => void;\n disabled?: boolean;\n}\n\nexport interface DraggerProps extends UploadProps {\n height?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nlet fileUid = 0;\n\nfunction getUid(): string {\n fileUid += 1;\n return `ald-upload-${Date.now()}-${fileUid}`;\n}\n\nfunction fileToUploadFile(\n file: RcFile,\n status: UploadFile['status'] = 'uploading',\n): UploadFile {\n return {\n uid: file.uid ?? getUid(),\n name: file.name,\n size: file.size,\n type: file.type,\n status,\n percent: 0,\n originFileObj: file,\n };\n}\n\nfunction isImageUrl(file: UploadFile): boolean {\n if (file.type) return file.type.startsWith('image/');\n const ext = file.name?.split('.').pop()?.toLowerCase() ?? '';\n return ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp', 'svg', 'ico'].includes(\n ext,\n );\n}\n\nfunction getThumbUrl(file: UploadFile): string | undefined {\n if (file.thumbUrl) return file.thumbUrl;\n if (file.url) return file.url;\n if (file.originFileObj && isImageUrl(file)) {\n try {\n return URL.createObjectURL(file.originFileObj);\n } catch {\n return undefined;\n }\n }\n return undefined;\n}\n\n// ---------------------------------------------------------------------------\n// UploadList\n// ---------------------------------------------------------------------------\n\nfunction UploadList({\n items = [],\n listType = 'text',\n showUploadList = true,\n onRemove,\n onPreview,\n disabled,\n}: UploadListProps) {\n if (!showUploadList || items.length === 0) return null;\n\n const showConfig: ShowUploadListInterface =\n typeof showUploadList === 'object'\n ? showUploadList\n : {\n showRemoveIcon: true,\n showPreviewIcon: true,\n showDownloadIcon: false,\n };\n\n const isPictureType = listType === 'picture' || listType === 'picture-card';\n\n return (\n <ul className={cn('ald-upload-list', `ald-upload-list-${listType}`)}>\n {items.map((file) => {\n const thumbUrl = isPictureType ? getThumbUrl(file) : undefined;\n\n return (\n <li\n key={file.uid}\n className={cn(\n 'ald-upload-list-item',\n `ald-upload-list-item-${file.status || 'done'}`,\n )}\n >\n {/* Thumbnail for picture types */}\n {isPictureType && (\n <div className=\"ald-upload-list-item-thumbnail\">\n {thumbUrl ? (\n <img src={thumbUrl} alt={file.name} />\n ) : (\n <div className=\"ald-upload-list-item-file-icon\">\n <FileIcon />\n </div>\n )}\n </div>\n )}\n\n {/* Status icon for text type */}\n {!isPictureType && (\n <span className=\"ald-upload-list-item-status-icon\">\n {file.status === 'uploading' && (\n <span className=\"ald-upload-list-item-loading-icon\">\n <LoadingLine style={{ fontSize: 14 }} />\n </span>\n )}\n {file.status === 'done' && (\n <CheckCircleFill style={{ fontSize: 14 }} />\n )}\n {file.status === 'error' && (\n <CloseCircleFill style={{ fontSize: 14 }} />\n )}\n </span>\n )}\n\n {/* File name */}\n <Tooltip title={file.name}>\n <span\n className=\"ald-upload-list-item-name\"\n onClick={() => onPreview?.(file)}\n style={onPreview ? { cursor: 'pointer' } : undefined}\n >\n {file.name}\n </span>\n </Tooltip>\n\n {/* Actions */}\n <span className=\"ald-upload-list-item-actions\">\n {showConfig.showPreviewIcon &&\n onPreview &&\n file.status === 'done' && (\n <button\n type=\"button\"\n className=\"ald-upload-list-item-action\"\n title=\"Preview\"\n onClick={() => onPreview(file)}\n >\n <EyeOnLine style={{ fontSize: 14 }} />\n </button>\n )}\n {showConfig.showRemoveIcon !== false && !disabled && (\n <button\n type=\"button\"\n className=\"ald-upload-list-item-action\"\n title=\"Remove\"\n onClick={() => onRemove?.(file)}\n >\n {listType === 'picture-card' ? (\n <TrashLightLine style={{ fontSize: 14 }} />\n ) : (\n <CloseLightLine style={{ fontSize: 14 }} />\n )}\n </button>\n )}\n </span>\n\n {/* Progress bar */}\n {file.status === 'uploading' && (\n <div className=\"ald-upload-list-item-progress\">\n <div\n className=\"ald-upload-list-item-progress-bar\"\n style={{ width: `${file.percent ?? 0}%` }}\n />\n </div>\n )}\n </li>\n );\n })}\n </ul>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Simple file icon SVG (inline to avoid extra dependency)\n// ---------------------------------------------------------------------------\n\nfunction FileIcon() {\n return (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n </svg>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Upload component\n// ---------------------------------------------------------------------------\n\nfunction Upload<T = any>(props: UploadProps<T>) {\n const {\n accept,\n action,\n method,\n headers,\n data,\n withCredentials,\n beforeUpload,\n customRequest,\n disabled = false,\n fileList: controlledFileList,\n defaultFileList,\n maxCount,\n multiple,\n directory,\n name = 'file',\n listType = 'text',\n showUploadList = true,\n onChange,\n onRemove,\n onPreview,\n onDownload,\n className,\n style,\n children,\n openFileDialogOnClick = true,\n id,\n } = props;\n\n const isControlled = controlledFileList !== undefined;\n const [internalFileList, setInternalFileList] = useState<UploadFile<T>[]>(\n defaultFileList ?? [],\n );\n\n const mergedFileList = isControlled ? controlledFileList! : internalFileList;\n\n // Keep a ref to latest list so callbacks always see fresh state\n const fileListRef = useRef(mergedFileList);\n fileListRef.current = mergedFileList;\n\n const rcUploadRef = useRef<any>(null);\n\n // ----- helpers to update state & fire onChange -----\n\n const updateFileList = useCallback(\n (newFile: UploadFile<T>, event?: UploadProgressEvent) => {\n const nextList = fileListRef.current.map((f) =>\n f.uid === newFile.uid ? newFile : f,\n );\n // If the file is new, append it\n if (!nextList.some((f) => f.uid === newFile.uid)) {\n nextList.push(newFile);\n }\n if (!isControlled) {\n setInternalFileList(nextList);\n }\n onChange?.({\n file: newFile,\n fileList: nextList,\n event,\n });\n },\n [isControlled, onChange],\n );\n\n // ----- rc-upload callback props -----\n\n const onBatchStart: RcUploadProps['onBatchStart'] = useCallback(\n (batchFileInfoList: { file: RcFile; parsedFile: any }[]) => {\n let nextList = [...fileListRef.current];\n\n for (const { file } of batchFileInfoList) {\n const uploadFile = fileToUploadFile(file, 'uploading') as UploadFile<T>;\n\n if (maxCount && nextList.length >= maxCount) {\n // replace if maxCount === 1, otherwise skip\n if (maxCount === 1) {\n nextList = [uploadFile];\n }\n continue;\n }\n nextList.push(uploadFile);\n }\n\n if (!isControlled) {\n setInternalFileList(nextList);\n }\n\n // Fire onChange for the first new file\n const firstNew = batchFileInfoList[0];\n if (firstNew) {\n const f = nextList.find((x) => x.uid === firstNew.file.uid);\n if (f) {\n onChange?.({ file: f, fileList: nextList });\n }\n }\n },\n [isControlled, maxCount, onChange],\n );\n\n const onRcProgress = useCallback(\n (event: UploadProgressEvent, file: RcFile) => {\n const target = fileListRef.current.find((f) => f.uid === file.uid);\n if (!target) return;\n const updated: UploadFile<T> = {\n ...target,\n status: 'uploading',\n percent: event.percent ?? 0,\n };\n updateFileList(updated, event);\n },\n [updateFileList],\n );\n\n const onRcSuccess = useCallback(\n (response: any, file: RcFile) => {\n const target = fileListRef.current.find((f) => f.uid === file.uid);\n if (!target) return;\n const updated: UploadFile<T> = {\n ...target,\n status: 'done',\n percent: 100,\n response,\n };\n updateFileList(updated);\n },\n [updateFileList],\n );\n\n const onRcError = useCallback(\n (error: Error, _ret: any, file: RcFile) => {\n const target = fileListRef.current.find((f) => f.uid === file.uid);\n if (!target) return;\n const updated: UploadFile<T> = {\n ...target,\n status: 'error',\n error,\n };\n updateFileList(updated);\n },\n [updateFileList],\n );\n\n // ----- remove handler -----\n\n const handleRemove = useCallback(\n async (file: UploadFile<T>) => {\n const result = await onRemove?.(file as any);\n if (result === false) return;\n const nextList = fileListRef.current.filter((f) => f.uid !== file.uid);\n if (!isControlled) {\n setInternalFileList(nextList);\n }\n const removedFile: UploadFile<T> = { ...file, status: 'removed' };\n onChange?.({ file: removedFile, fileList: nextList });\n },\n [isControlled, onChange, onRemove],\n );\n\n // ----- rc-upload props -----\n\n const rcUploadProps: RcUploadProps = useMemo(\n () => ({\n accept,\n action: action as RcUploadProps['action'],\n method,\n headers,\n data: data as RcUploadProps['data'],\n withCredentials,\n beforeUpload: beforeUpload as RcUploadProps['beforeUpload'],\n customRequest: customRequest as RcUploadProps['customRequest'],\n disabled,\n multiple,\n directory,\n name,\n openFileDialogOnClick,\n id,\n prefixCls: 'ald-upload',\n onBatchStart,\n onProgress: onRcProgress,\n onSuccess: onRcSuccess,\n onError: onRcError,\n }),\n [\n accept,\n action,\n method,\n headers,\n data,\n withCredentials,\n beforeUpload,\n customRequest,\n disabled,\n multiple,\n directory,\n name,\n openFileDialogOnClick,\n id,\n onBatchStart,\n onRcProgress,\n onRcSuccess,\n onRcError,\n ],\n );\n\n const isPictureCard = listType === 'picture-card';\n\n return (\n <span\n className={cn(\n 'ald-upload',\n { 'ald-upload-disabled': disabled },\n className,\n )}\n style={style}\n >\n {isPictureCard ? (\n // picture-card: render list first, then the upload trigger\n <>\n <UploadList\n items={mergedFileList as UploadFile[]}\n listType={listType}\n showUploadList={showUploadList}\n onRemove={handleRemove as any}\n onPreview={onPreview as any}\n onDownload={onDownload as any}\n disabled={disabled}\n />\n {(!maxCount || mergedFileList.length < maxCount) && (\n <RcUpload {...rcUploadProps} ref={rcUploadRef}>\n <div className=\"ald-upload-select\">{children}</div>\n </RcUpload>\n )}\n </>\n ) : (\n // text / picture: render trigger then list\n <>\n <RcUpload {...rcUploadProps} ref={rcUploadRef}>\n <div className=\"ald-upload-select\">{children}</div>\n </RcUpload>\n <UploadList\n items={mergedFileList as UploadFile[]}\n listType={listType}\n showUploadList={showUploadList}\n onRemove={handleRemove as any}\n onPreview={onPreview as any}\n onDownload={onDownload as any}\n disabled={disabled}\n />\n </>\n )}\n </span>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Dragger sub-component\n// ---------------------------------------------------------------------------\n\nfunction Dragger(props: DraggerProps) {\n const { height, style, disabled, className, children, ...restProps } = props;\n const [dragOver, setDragOver] = useState(false);\n\n const mergedStyle: React.CSSProperties = {\n ...style,\n ...(height !== null && height !== undefined ? { height } : {}),\n };\n\n return (\n <Upload\n {...restProps}\n disabled={disabled}\n className={cn('ald-upload-dragger-wrapper', className)}\n style={mergedStyle}\n >\n <div\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n className={cn('ald-upload-dragger ant-upload-drag', {\n 'ald-upload-drag-hover': dragOver,\n 'ant-upload-drag-hover': dragOver,\n 'ald-upload-disabled': disabled,\n 'ant-upload-disabled': disabled,\n })}\n onDragOver={(e) => {\n e.preventDefault();\n if (!disabled) setDragOver(true);\n }}\n onDragLeave={() => setDragOver(false)}\n onDrop={() => setDragOver(false)}\n >\n {children}\n </div>\n </Upload>\n );\n}\n\nUpload.Dragger = Dragger;\n\nexport default Upload as typeof Upload & { Dragger: typeof Dragger };\n"],"mappings":"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"}