@kingsoft-ai/design 0.1.11 → 0.1.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.
@@ -27,6 +27,8 @@ export type ButtonProps = Omit<AriaButtonProps, 'elementType'> & {
27
27
  loading?: boolean;
28
28
  /** 全宽按钮 */
29
29
  fullWidth?: boolean;
30
+ /** 是否禁用(统一 API,优先级高于 isDisabled) */
31
+ disabled?: boolean;
30
32
  /** 自定义类名 */
31
33
  className?: string;
32
34
  /** 子元素 */
@@ -49,6 +51,8 @@ export declare const Button: import("react").ForwardRefExoticComponent<Omit<Aria
49
51
  loading?: boolean;
50
52
  /** 全宽按钮 */
51
53
  fullWidth?: boolean;
54
+ /** 是否禁用(统一 API,优先级高于 isDisabled) */
55
+ disabled?: boolean;
52
56
  /** 自定义类名 */
53
57
  className?: string;
54
58
  /** 子元素 */
@@ -3,6 +3,8 @@ export * from './checkbox';
3
3
  export * from './collapse';
4
4
  export * from './input';
5
5
  export * from './menu';
6
+ export * from './link';
7
+ export * from './modal';
6
8
  export * from './numberInput';
7
9
  export * from './radio';
8
10
  export * from './skeleton';
@@ -0,0 +1,35 @@
1
+ import type { ReactNode } from 'react';
2
+ import { useLink } from 'react-aria';
3
+ import { type LinkVariant, type LinkSize } from './Link.style';
4
+ type UseLinkProps = Parameters<typeof useLink>[0];
5
+ export type LinkProps = UseLinkProps & {
6
+ /** 链接变体:primary (主色), neutral (中性色) */
7
+ variant?: LinkVariant;
8
+ /** 链接尺寸:sm (12px), md (14px), lg (16px) */
9
+ size?: LinkSize;
10
+ /** 是否禁用(统一 API,优先级高于 isDisabled) */
11
+ disabled?: boolean;
12
+ /** 自定义类名 */
13
+ className?: string;
14
+ /** 子元素 */
15
+ children?: ReactNode;
16
+ };
17
+ /**
18
+ * Link 文字链接组件
19
+ *
20
+ * 用于页面内的跳转或操作,支持多种状态和尺寸。
21
+ * 基于 react-aria useLink 实现无障碍访问。
22
+ */
23
+ export declare const Link: import("react").ForwardRefExoticComponent<import("react-aria").AriaLinkOptions & {
24
+ /** 链接变体:primary (主色), neutral (中性色) */
25
+ variant?: LinkVariant;
26
+ /** 链接尺寸:sm (12px), md (14px), lg (16px) */
27
+ size?: LinkSize;
28
+ /** 是否禁用(统一 API,优先级高于 isDisabled) */
29
+ disabled?: boolean;
30
+ /** 自定义类名 */
31
+ className?: string;
32
+ /** 子元素 */
33
+ children?: ReactNode;
34
+ } & import("react").RefAttributes<HTMLAnchorElement>>;
35
+ export {};
@@ -0,0 +1,9 @@
1
+ export type LinkVariant = 'primary' | 'neutral';
2
+ export type LinkSize = 'sm' | 'md' | 'lg';
3
+ export declare const LinkRoot: import("@emotion/styled").StyledComponent<{
4
+ theme?: import("@emotion/react").Theme;
5
+ as?: React.ElementType;
6
+ } & {
7
+ variant: LinkVariant;
8
+ size: LinkSize;
9
+ }, import("react").DetailedHTMLProps<import("react").AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, {}>;
@@ -0,0 +1,3 @@
1
+ export { Link } from './Link';
2
+ export type { LinkProps } from './Link';
3
+ export * from './Link.style';
@@ -0,0 +1,3 @@
1
+ import { TokenGenerator } from '../types/theme-utils';
2
+ import { LinkTokens } from '../types/component-tokens.types';
3
+ export declare const getLinkTokens: TokenGenerator<LinkTokens>;
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Modal 弹窗组件
3
+ *
4
+ * 基于 React Portal 实现的高性能弹窗组件
5
+ * 支持无障碍访问、键盘操作、焦点管理
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * <Modal
10
+ * open={isOpen}
11
+ * onClose={() => setIsOpen(false)}
12
+ * title="确认操作"
13
+ * size="md"
14
+ * >
15
+ * <p>确定要执行此操作吗?</p>
16
+ * </Modal>
17
+ * ```
18
+ */
19
+ import { type ReactNode } from 'react';
20
+ import { ModalHeader, ModalTitle, ModalDescription, ModalCloseButton, ModalContent, ModalFooter, type ModalSize } from './Modal.style';
21
+ export declare const SIZES: readonly ["sm", "md", "lg", "xl", "fullscreen"];
22
+ export interface ModalProps {
23
+ /** 是否打开弹窗 */
24
+ open: boolean;
25
+ /** 关闭弹窗回调 */
26
+ onClose: () => void;
27
+ /** 弹窗标题 */
28
+ title?: ReactNode;
29
+ /** 弹窗描述/副标题 */
30
+ description?: ReactNode;
31
+ /** 弹窗内容 */
32
+ children?: ReactNode;
33
+ /** 底部操作区域 */
34
+ footer?: ReactNode;
35
+ /** 弹窗尺寸 */
36
+ size?: ModalSize;
37
+ /** 是否全屏 */
38
+ fullscreen?: boolean;
39
+ /** 是否垂直居中 */
40
+ centered?: boolean;
41
+ /** 是否显示关闭按钮 */
42
+ closable?: boolean;
43
+ /** 点击遮罩是否关闭 */
44
+ maskClosable?: boolean;
45
+ /** 按 ESC 是否关闭 */
46
+ keyboard?: boolean;
47
+ /** 是否显示遮罩 */
48
+ mask?: boolean;
49
+ /** 关闭后是否销毁子元素 */
50
+ destroyOnClose?: boolean;
51
+ /** 动画类型 */
52
+ animationType?: 'scale' | 'slide' | 'fade';
53
+ /** 挂载的 DOM 节点(默认为 document.body) */
54
+ container?: HTMLElement | null;
55
+ /** 自定义类名 */
56
+ className?: string;
57
+ /** 内容区域自定义类名 */
58
+ contentClassName?: string;
59
+ /** 自定义 z-index */
60
+ zIndex?: number;
61
+ /** 动画结束后的回调 */
62
+ afterClose?: () => void;
63
+ /** 动画开始前的回调 */
64
+ afterOpen?: () => void;
65
+ /** 自定义关闭图标 */
66
+ closeIcon?: ReactNode;
67
+ /** 无障碍:描述 ID */
68
+ 'aria-describedby'?: string;
69
+ /** 无障碍:标签 ID */
70
+ 'aria-labelledby'?: string;
71
+ }
72
+ /**
73
+ * Modal 弹窗组件
74
+ *
75
+ * 高性能、无障碍、可定制的弹窗组件
76
+ */
77
+ export declare const Modal: import("react").ForwardRefExoticComponent<ModalProps & import("react").RefAttributes<HTMLDivElement>>;
78
+ export { ModalHeader, ModalContent, ModalFooter, ModalTitle, ModalDescription, ModalCloseButton, };
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Modal 弹窗样式
3
+ *
4
+ * 基于三层 Token 体系:
5
+ * - Tier 1 (Global): 全局基础值
6
+ * - Tier 2 (Semantic): 语义化映射
7
+ * - Tier 3 (Component): 组件专用 Token
8
+ *
9
+ * 特性:
10
+ * - 优雅的入场/退场动画
11
+ * - 响应式尺寸支持
12
+ * - 无障碍访问友好
13
+ * - 支持暗色主题
14
+ */
15
+ export declare const modalSizes: readonly ["sm", "md", "lg", "xl", "fullscreen"];
16
+ export type ModalSize = (typeof modalSizes)[number];
17
+ /**
18
+ * Modal 遮罩层
19
+ *
20
+ * 特性:
21
+ * - 毛玻璃效果
22
+ * - 点击关闭支持
23
+ * - 优雅的淡入淡出动画
24
+ */
25
+ export declare const ModalOverlay: import("@emotion/styled").StyledComponent<{
26
+ theme?: import("@emotion/react").Theme;
27
+ as?: React.ElementType;
28
+ } & {
29
+ isOpen: boolean;
30
+ isClosing: boolean;
31
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
32
+ /**
33
+ * Modal 容器(用于 Portal 和定位)
34
+ */
35
+ export declare const ModalPortalContainer: import("@emotion/styled").StyledComponent<{
36
+ theme?: import("@emotion/react").Theme;
37
+ as?: React.ElementType;
38
+ } & {
39
+ isOpen: boolean;
40
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
41
+ /**
42
+ * Modal 主容器
43
+ *
44
+ * 特性:
45
+ * - 居中定位
46
+ * - 响应式宽度
47
+ * - 弹性动画效果
48
+ */
49
+ export declare const ModalContainer: import("@emotion/styled").StyledComponent<{
50
+ theme?: import("@emotion/react").Theme;
51
+ as?: React.ElementType;
52
+ } & {
53
+ size: ModalSize;
54
+ isOpen: boolean;
55
+ isClosing: boolean;
56
+ isFullscreen: boolean;
57
+ animationType: "scale" | "slide" | "fade";
58
+ centered: boolean;
59
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
60
+ /**
61
+ * Modal 头部
62
+ *
63
+ * 包含标题、描述和关闭按钮
64
+ */
65
+ export declare const ModalHeader: import("@emotion/styled").StyledComponent<{
66
+ theme?: import("@emotion/react").Theme;
67
+ as?: React.ElementType;
68
+ } & {
69
+ size: ModalSize;
70
+ hasDescription: boolean;
71
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLElement>, HTMLElement>, {}>;
72
+ /**
73
+ * 标题容器
74
+ */
75
+ export declare const ModalTitleWrapper: import("@emotion/styled").StyledComponent<{
76
+ theme?: import("@emotion/react").Theme;
77
+ as?: React.ElementType;
78
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
79
+ /**
80
+ * Modal 标题
81
+ */
82
+ export declare const ModalTitle: import("@emotion/styled").StyledComponent<{
83
+ theme?: import("@emotion/react").Theme;
84
+ as?: React.ElementType;
85
+ } & {
86
+ size: ModalSize;
87
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>, {}>;
88
+ /**
89
+ * Modal 描述
90
+ */
91
+ export declare const ModalDescription: import("@emotion/styled").StyledComponent<{
92
+ theme?: import("@emotion/react").Theme;
93
+ as?: React.ElementType;
94
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>, {}>;
95
+ /**
96
+ * Modal 关闭按钮
97
+ */
98
+ export declare const ModalCloseButton: import("@emotion/styled").StyledComponent<{
99
+ theme?: import("@emotion/react").Theme;
100
+ as?: React.ElementType;
101
+ }, import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, {}>;
102
+ /**
103
+ * Modal 内容区域
104
+ */
105
+ export declare const ModalContent: import("@emotion/styled").StyledComponent<{
106
+ theme?: import("@emotion/react").Theme;
107
+ as?: React.ElementType;
108
+ } & {
109
+ size: ModalSize;
110
+ hasHeader: boolean;
111
+ hasFooter: boolean;
112
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
113
+ /**
114
+ * Modal 底部
115
+ */
116
+ export declare const ModalFooter: import("@emotion/styled").StyledComponent<{
117
+ theme?: import("@emotion/react").Theme;
118
+ as?: React.ElementType;
119
+ } & {
120
+ size: ModalSize;
121
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLElement>, HTMLElement>, {}>;
@@ -0,0 +1,4 @@
1
+ export { Modal, SIZES } from './Modal';
2
+ export type { ModalProps } from './Modal';
3
+ export type { ModalSize } from './Modal.style';
4
+ export { ModalHeader, ModalContent, ModalFooter, ModalTitle, ModalDescription, ModalCloseButton, } from './Modal';
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Modal 组件 Token
3
+ *
4
+ * 基于三层 Token 体系:
5
+ * - Tier 1 (Global): 全局基础值
6
+ * - Tier 2 (Semantic): 语义化映射
7
+ * - Tier 3 (Component): 组件专用 Token
8
+ */
9
+ import { TokenGenerator } from '../types/theme-utils';
10
+ import { ModalTokens } from '../types/component-tokens.types';
11
+ export declare const getModalTokens: TokenGenerator<ModalTokens>;
@@ -35,8 +35,16 @@ export type NumberInputProps = {
35
35
  controls?: 'buttons' | 'arrows';
36
36
  /** 大小:'md' | 'lg' */
37
37
  size?: 'md' | 'lg';
38
- /** 值变化回调(返回 number | undefined) */
39
- onValueChange?: (v: number | undefined) => void;
38
+ /**
39
+ * 值变化回调(统一 API,推荐使用)
40
+ * 等同于其他表单组件的 onChange,返回 number | undefined
41
+ */
42
+ onValueChange?: (value: number | undefined) => void;
43
+ /**
44
+ * 值变化回调别名(统一 API)
45
+ * 与 onValueChange 功能相同,提供与其他表单组件一致的 API 命名
46
+ */
47
+ onChangeValue?: (value: number | undefined) => void;
40
48
  /** 标签文本 */
41
49
  label?: ReactNode;
42
50
  /** 描述文本 */
@@ -51,7 +59,7 @@ export type NumberInputProps = {
51
59
  className?: string;
52
60
  /** 自定义 ID */
53
61
  id?: string;
54
- /** 原生 onChange 保留以便外部使用 */
62
+ /** 原生 input onChange 事件(用于表单库等场景) */
55
63
  onChange?: (e: ChangeEvent<HTMLInputElement>) => void;
56
64
  };
57
65
  /** 数字输入框组件 */
@@ -17,7 +17,7 @@ export interface SelectOptionType {
17
17
  /** 是否禁用该选项 */
18
18
  disabled?: boolean;
19
19
  }
20
- export interface SelectProps<T> extends Omit<AriaSelectProps<T>, 'errorMessage' | 'selectedKey' | 'defaultSelectedKey' | 'onSelectionChange' | 'selectionMode' | 'children' | 'isDisabled'> {
20
+ export interface SelectProps<T> extends Omit<AriaSelectProps<T>, 'errorMessage' | 'selectedKey' | 'defaultSelectedKey' | 'onSelectionChange' | 'selectionMode' | 'children' | 'isDisabled' | 'value' | 'defaultValue' | 'onChange'> {
21
21
  /** 选择模式:single 单选 | multiple 多选 */
22
22
  selectionMode?: SelectionMode;
23
23
  /** 是否正在加载 */
@@ -40,15 +40,21 @@ export interface SelectProps<T> extends Omit<AriaSelectProps<T>, 'errorMessage'
40
40
  errorMessage?: React.ReactNode;
41
41
  /** 多选时最大展示的 Tag 数量 */
42
42
  maxTagCount?: number;
43
- /** 单选时选中的 key */
43
+ /** 受控值(统一 API,单选时为 Key,多选时为 Iterable<Key>,优先级高于 selectedKey/selectedKeys) */
44
+ value?: React.Key | null | Iterable<React.Key>;
45
+ /** 默认值(统一 API,单选时为 Key,多选时为 Iterable<Key>,优先级高于 defaultSelectedKey/defaultSelectedKeys) */
46
+ defaultValue?: React.Key | Iterable<React.Key>;
47
+ /** 值变化回调(统一 API,优先级高于 onSelectionChange) */
48
+ onChange?: (value: SelectionType) => void;
49
+ /** 单选时选中的 key(兼容旧 API) */
44
50
  selectedKey?: React.Key | null;
45
- /** 单选时默认选中的 key */
51
+ /** 单选时默认选中的 key(兼容旧 API) */
46
52
  defaultSelectedKey?: React.Key;
47
- /** 多选时选中的 keys */
53
+ /** 多选时选中的 keys(兼容旧 API) */
48
54
  selectedKeys?: Iterable<React.Key>;
49
- /** 多选时默认选中的 keys */
55
+ /** 多选时默认选中的 keys(兼容旧 API) */
50
56
  defaultSelectedKeys?: Iterable<React.Key>;
51
- /** 选择变化回调(单选返回 key,多选返回 Set) */
57
+ /** 选择变化回调(兼容旧 API,单选返回 key,多选返回 Set) */
52
58
  onSelectionChange?: (keys: SelectionType) => void;
53
59
  /**
54
60
  * 选项数据(推荐使用)
@@ -41,6 +41,10 @@ export type SwitchProps = Omit<AriaSwitchProps, 'children' | 'isDisabled'> & Omi
41
41
  uncheckedLabel?: string;
42
42
  /** 是否禁用(替代 isDisabled) */
43
43
  disabled?: boolean;
44
+ /** 受控值(统一 API,优先级高于 isSelected) */
45
+ value?: boolean;
46
+ /** 默认值(统一 API,优先级高于 defaultSelected) */
47
+ defaultValue?: boolean;
44
48
  /** 外部描述性标签(显示在开关旁边) */
45
49
  children?: ReactNode;
46
50
  /** 自定义类名 */
@@ -61,6 +65,10 @@ export declare const Switch: import("react").ForwardRefExoticComponent<Omit<Aria
61
65
  uncheckedLabel?: string;
62
66
  /** 是否禁用(替代 isDisabled) */
63
67
  disabled?: boolean;
68
+ /** 受控值(统一 API,优先级高于 isSelected) */
69
+ value?: boolean;
70
+ /** 默认值(统一 API,优先级高于 defaultSelected) */
71
+ defaultValue?: boolean;
64
72
  /** 外部描述性标签(显示在开关旁边) */
65
73
  children?: ReactNode;
66
74
  /** 自定义类名 */
@@ -1,5 +1,6 @@
1
- import { AppTheme, ComponentTokens, SemanticColors, SemanticSpacing, SemanticBorderRadius, SemanticTypography, SemanticShadows } from '@kingsoft-ai/theme';
1
+ import { AppTheme, SemanticColors, SemanticSpacing, SemanticBorderRadius, SemanticTypography, SemanticShadows } from '@kingsoft-ai/theme';
2
2
  import { ThemeContext } from './types/theme-utils';
3
+ import { ComponentTokens } from './types/component-tokens.types';
3
4
  export declare const createComponentTokens: (context: ThemeContext) => ComponentTokens;
4
5
  interface SemanticTheme {
5
6
  colors: SemanticColors;
@@ -747,6 +747,145 @@ export interface SelectTokens {
747
747
  };
748
748
  };
749
749
  }
750
+ export interface LinkTokens {
751
+ variant: {
752
+ primary: LinkStateTokens;
753
+ neutral: LinkStateTokens;
754
+ };
755
+ size: {
756
+ sm: {
757
+ fontSize: string;
758
+ };
759
+ md: {
760
+ fontSize: string;
761
+ };
762
+ lg: {
763
+ fontSize: string;
764
+ };
765
+ };
766
+ transition: string;
767
+ borderRadius: string;
768
+ focusRing: {
769
+ color: string;
770
+ offset: string;
771
+ };
772
+ }
773
+ interface LinkStateTokens {
774
+ text: {
775
+ default: string;
776
+ hover: string;
777
+ active: string;
778
+ disabled: string;
779
+ };
780
+ decoration: {
781
+ default: string;
782
+ hover: string;
783
+ };
784
+ }
785
+ export interface ModalTokens {
786
+ size: {
787
+ sm: {
788
+ width: string;
789
+ maxWidth: string;
790
+ padding: string;
791
+ headerPadding: string;
792
+ footerPadding: string;
793
+ titleFontSize: string;
794
+ };
795
+ md: {
796
+ width: string;
797
+ maxWidth: string;
798
+ padding: string;
799
+ headerPadding: string;
800
+ footerPadding: string;
801
+ titleFontSize: string;
802
+ };
803
+ lg: {
804
+ width: string;
805
+ maxWidth: string;
806
+ padding: string;
807
+ headerPadding: string;
808
+ footerPadding: string;
809
+ titleFontSize: string;
810
+ };
811
+ xl: {
812
+ width: string;
813
+ maxWidth: string;
814
+ padding: string;
815
+ headerPadding: string;
816
+ footerPadding: string;
817
+ titleFontSize: string;
818
+ };
819
+ fullscreen: {
820
+ width: string;
821
+ maxWidth: string;
822
+ padding: string;
823
+ headerPadding: string;
824
+ footerPadding: string;
825
+ titleFontSize: string;
826
+ };
827
+ };
828
+ overlay: {
829
+ background: string;
830
+ backdropFilter: string;
831
+ };
832
+ container: {
833
+ background: string;
834
+ borderRadius: string;
835
+ boxShadow: string;
836
+ border: string;
837
+ maxHeight: string;
838
+ };
839
+ header: {
840
+ background: string;
841
+ borderBottom: string;
842
+ minHeight: string;
843
+ gap: string;
844
+ };
845
+ title: {
846
+ color: string;
847
+ fontWeight: number;
848
+ lineHeight: string;
849
+ };
850
+ description: {
851
+ color: string;
852
+ fontSize: string;
853
+ lineHeight: string;
854
+ marginTop: string;
855
+ };
856
+ closeButton: {
857
+ size: string;
858
+ iconSize: string;
859
+ color: string;
860
+ hoverColor: string;
861
+ hoverBackground: string;
862
+ borderRadius: string;
863
+ };
864
+ content: {
865
+ color: string;
866
+ fontSize: string;
867
+ lineHeight: string;
868
+ maxHeight: string;
869
+ };
870
+ footer: {
871
+ background: string;
872
+ borderTop: string;
873
+ minHeight: string;
874
+ gap: string;
875
+ justifyContent: string;
876
+ };
877
+ animation: {
878
+ duration: string;
879
+ easing: string;
880
+ scaleFrom: string;
881
+ scaleTo: string;
882
+ };
883
+ zIndex: {
884
+ overlay: number;
885
+ container: number;
886
+ };
887
+ transition: string;
888
+ }
750
889
  export interface ComponentTokens {
751
890
  button: ButtonTokens;
752
891
  iconButton: IconButtonTokens;
@@ -761,5 +900,7 @@ export interface ComponentTokens {
761
900
  stepper: StepperTokens;
762
901
  numberfield: NumberFieldTokens;
763
902
  menu: MenuTokens;
903
+ link: LinkTokens;
904
+ modal: ModalTokens;
764
905
  }
765
906
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kingsoft-ai/design",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",
@@ -24,8 +24,8 @@
24
24
  "@react-stately/list": "^3.13.1",
25
25
  "@react-stately/select": "^3.8.0",
26
26
  "@react-types/shared": "^3.32.1",
27
- "@kingsoft-ai/icons": "^0.1.4",
28
- "@kingsoft-ai/theme": "^0.1.5"
27
+ "@kingsoft-ai/theme": "^0.1.5",
28
+ "@kingsoft-ai/icons": "^0.1.4"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "@emotion/react": ">=11",