@lillian10231023/o2-design-system-1 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,262 @@
1
+ # O2 Design System
2
+
3
+ > React component library & design tokens for O2 products.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/o2-design-system)](https://www.npmjs.com/package/o2-design-system)
6
+ [![license](https://img.shields.io/npm/l/o2-design-system)](LICENSE)
7
+
8
+ ---
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ npm install o2-design-system
14
+ # or
15
+ yarn add o2-design-system
16
+ # or
17
+ pnpm add o2-design-system
18
+ ```
19
+
20
+ > **Peer dependencies:** `react >= 17` and `react-dom >= 17` must be installed in your project.
21
+
22
+ ---
23
+
24
+ ## Quick Start
25
+
26
+ Import the CSS once at your app entry (e.g. `main.tsx`):
27
+
28
+ ```tsx
29
+ import 'o2-design-system/dist/index.css'
30
+ ```
31
+
32
+ Then use components directly:
33
+
34
+ ```tsx
35
+ import { Button, Input } from 'o2-design-system'
36
+
37
+ export default function App() {
38
+ return (
39
+ <>
40
+ <Button variant="solid" theme="default">Submit</Button>
41
+ <Button variant="outline" theme="danger" prefixIcon={<TrashIcon />}>Delete</Button>
42
+ <Input label="Email" placeholder="you@example.com" clearable />
43
+ </>
44
+ )
45
+ }
46
+ ```
47
+
48
+ ---
49
+
50
+ ## Components
51
+
52
+ ### Button
53
+
54
+ Trigger actions with clear visual hierarchy.
55
+
56
+ ```tsx
57
+ import { Button, ButtonGroup } from 'o2-design-system'
58
+ ```
59
+
60
+ #### Props
61
+
62
+ | Prop | Type | Default | Description |
63
+ |------|------|---------|-------------|
64
+ | `variant` | `'solid' \| 'outline' \| 'ghost'` | `'solid'` | Visual style — filled / bordered / text-only |
65
+ | `theme` | `'default' \| 'danger'` | `'default'` | Color theme |
66
+ | `size` | `'lg' \| 'md' \| 'sm' \| 'mini'` | `'md'` | Button height: 40 / 32 / 24 / 20 px |
67
+ | `shape` | `'rounded' \| 'pill'` | `'rounded'` | Corner radius: 4px / fully rounded |
68
+ | `disabled` | `boolean` | `false` | Disabled state |
69
+ | `loading` | `boolean` | `false` | Loading state — shows spinner, blocks interaction |
70
+ | `block` | `boolean` | `false` | Full-width, stretches to container |
71
+ | `iconOnly` | `boolean` | `false` | Square icon-only button (no text) |
72
+ | `prefixIcon` | `ReactNode` | — | Icon before label |
73
+ | `suffixIcon` | `ReactNode` | — | Icon after label |
74
+
75
+ #### Variants
76
+
77
+ ```tsx
78
+ // Solid — primary action
79
+ <Button variant="solid">Submit</Button>
80
+
81
+ // Outline — secondary action
82
+ <Button variant="outline">Cancel</Button>
83
+
84
+ // Ghost — lightweight / text action
85
+ <Button variant="ghost">View more</Button>
86
+ ```
87
+
88
+ #### Colors
89
+
90
+ ```tsx
91
+ // Brand blue (default)
92
+ <Button theme="default">Create</Button>
93
+
94
+ // Danger red — destructive actions
95
+ <Button theme="danger">Delete</Button>
96
+ ```
97
+
98
+ #### Sizes
99
+
100
+ ```tsx
101
+ <Button size="lg">Large · 40px</Button>
102
+ <Button size="md">Medium · 32px</Button>
103
+ <Button size="sm">Small · 24px</Button>
104
+ <Button size="mini">Mini · 20px</Button>
105
+ ```
106
+
107
+ #### Icons
108
+
109
+ ```tsx
110
+ <Button prefixIcon={<PlusIcon />}>New</Button>
111
+ <Button suffixIcon={<ChevronDownIcon />}>More</Button>
112
+ <Button iconOnly prefixIcon={<SearchIcon />} aria-label="Search" />
113
+ ```
114
+
115
+ #### Loading
116
+
117
+ ```tsx
118
+ <Button loading>Submitting…</Button>
119
+ ```
120
+
121
+ #### Block
122
+
123
+ ```tsx
124
+ <Button block>Full width</Button>
125
+ ```
126
+
127
+ #### ButtonGroup
128
+
129
+ Merge multiple buttons into a single unit.
130
+
131
+ ```tsx
132
+ <ButtonGroup>
133
+ <Button variant="outline">Option A</Button>
134
+ <Button variant="outline">Option B</Button>
135
+ <Button variant="outline">Option C</Button>
136
+ </ButtonGroup>
137
+
138
+ // Pill shape
139
+ <ButtonGroup shape="pill">
140
+ <Button>Create</Button>
141
+ <Button iconOnly variant="outline" prefixIcon={<ChevronDownIcon />} aria-label="More" />
142
+ </ButtonGroup>
143
+ ```
144
+
145
+ ---
146
+
147
+ ### Input
148
+
149
+ Text input with label, hint, error state, prefix/suffix slots.
150
+
151
+ ```tsx
152
+ import { Input } from 'o2-design-system'
153
+ ```
154
+
155
+ #### Props
156
+
157
+ | Prop | Type | Default | Description |
158
+ |------|------|---------|-------------|
159
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Input height |
160
+ | `status` | `'default' \| 'error'` | `'default'` | Validation state |
161
+ | `label` | `string` | — | Label above input |
162
+ | `hint` | `string` | — | Helper text below input |
163
+ | `errorMsg` | `string` | — | Error text (overrides hint, turns border red) |
164
+ | `prefix` | `ReactNode` | — | Left slot (icon or text) |
165
+ | `suffix` | `ReactNode` | — | Right slot |
166
+ | `clearable` | `boolean` | `false` | Show clear button when value is non-empty |
167
+ | `block` | `boolean` | `false` | Full-width |
168
+ | `disabled` | `boolean` | `false` | Disabled state |
169
+
170
+ #### Examples
171
+
172
+ ```tsx
173
+ // Basic
174
+ <Input placeholder="Enter text…" />
175
+
176
+ // With label & hint
177
+ <Input label="Username" hint="Letters and numbers only" />
178
+
179
+ // Error state
180
+ <Input label="Email" status="error" errorMsg="Invalid email address" />
181
+
182
+ // With icons
183
+ <Input prefix={<SearchIcon />} placeholder="Search…" clearable />
184
+
185
+ // Sizes
186
+ <Input size="lg" placeholder="Large" />
187
+ <Input size="sm" placeholder="Small" />
188
+ ```
189
+
190
+ ---
191
+
192
+ ## Design Tokens
193
+
194
+ O2 Design Tokens are exported as typed JS constants:
195
+
196
+ ```tsx
197
+ import { colors, spacing, radius, typography } from 'o2-design-system'
198
+
199
+ // e.g.
200
+ console.log(colors['品牌_blue_06-常规']) // "#474BFF"
201
+ console.log(spacing.spacing_8) // 8
202
+ console.log(radius.m) // 4
203
+ console.log(typography.body_body_02) // { fontSize: 14, fontWeight: 'regular', lineHeight: 22 }
204
+ ```
205
+
206
+ CSS custom properties are also bundled in `dist/index.css` and can be used directly:
207
+
208
+ ```css
209
+ .my-button {
210
+ background: var(--color-品牌-blue-06-常规);
211
+ border-radius: var(--radius-m);
212
+ }
213
+ ```
214
+
215
+ ---
216
+
217
+ ## Dark Mode
218
+
219
+ Add `data-theme="dark"` to any ancestor element (e.g. `<html>`) to activate dark mode:
220
+
221
+ ```html
222
+ <html data-theme="dark">
223
+ ```
224
+
225
+ All CSS variables will automatically switch to dark values.
226
+
227
+ ---
228
+
229
+ ## Local Development
230
+
231
+ ```bash
232
+ git clone https://github.com/your-org/o2-design-system.git
233
+ cd o2-design-system
234
+ npm install
235
+
236
+ # Start the component preview app
237
+ npm run dev
238
+
239
+ # Build the library for publishing
240
+ npm run build:lib
241
+ ```
242
+
243
+ ---
244
+
245
+ ## Publishing to npm
246
+
247
+ ```bash
248
+ # 1. Login to npm
249
+ npm login
250
+
251
+ # 2. Bump version (patch / minor / major)
252
+ npm version patch
253
+
254
+ # 3. Build & publish (prepublishOnly runs build:lib automatically)
255
+ npm publish --access public
256
+ ```
257
+
258
+ ---
259
+
260
+ ## License
261
+
262
+ MIT © O2 Design Team
@@ -0,0 +1,55 @@
1
+ import { default as React } from 'react';
2
+ /** 按钮类型:实心(主要) | 描边(次要) | 文字(Ghost) */
3
+ export type ButtonVariant = 'solid' | 'outline' | 'ghost';
4
+ /**
5
+ * 按钮颜色主题
6
+ * - default:常规蓝(品牌色)
7
+ * - primary:主要蓝(同 default,语义更明确)
8
+ * - danger:危险红
9
+ * - warning:警告橙
10
+ * - success:成功绿
11
+ */
12
+ export type ButtonTheme = 'default' | 'primary' | 'danger' | 'warning' | 'success';
13
+ /** 尺寸:大(40px) | 中(32px) | 小(24px) | 迷你(20px) */
14
+ export type ButtonSize = 'lg' | 'md' | 'sm' | 'mini';
15
+ /** 按钮形状:半圆角(4px) | 全圆角胶囊 */
16
+ export type ButtonShape = 'rounded' | 'pill';
17
+ export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
18
+ /** 按钮类型,默认 solid */
19
+ variant?: ButtonVariant;
20
+ /** 颜色主题,默认 default */
21
+ theme?: ButtonTheme;
22
+ /** 尺寸,默认 md */
23
+ size?: ButtonSize;
24
+ /** 按钮形状,默认 rounded */
25
+ shape?: ButtonShape;
26
+ /**
27
+ * 加载状态:spinner 显示在文字左侧,按钮进入不可点击态
28
+ * 文字保持可见(不隐藏),视觉上表达"处理中"
29
+ */
30
+ loading?: boolean;
31
+ /** 前置图标 */
32
+ prefixIcon?: React.ReactNode;
33
+ /** 后置图标 */
34
+ suffixIcon?: React.ReactNode;
35
+ /** 仅图标模式(正方形/圆形按钮,无文字) */
36
+ iconOnly?: boolean;
37
+ /** 撑满父容器宽度 */
38
+ block?: boolean;
39
+ children?: React.ReactNode;
40
+ }
41
+ declare const Button: React.FC<ButtonProps>;
42
+ export default Button;
43
+ export interface ButtonGroupProps {
44
+ children: React.ReactNode;
45
+ /** 组内按钮尺寸统一 */
46
+ size?: ButtonSize;
47
+ /** 是否全圆角 */
48
+ shape?: ButtonShape;
49
+ }
50
+ /**
51
+ * ButtonGroup 组合按钮
52
+ * 多个按钮合并为一体,共享边框,中间分隔线自动处理
53
+ * 用法:<ButtonGroup><Button>选项A</Button><Button>选项B</Button></ButtonGroup>
54
+ */
55
+ export declare const ButtonGroup: React.FC<ButtonGroupProps>;
@@ -0,0 +1,2 @@
1
+ export { default as Button, ButtonGroup } from './Button';
2
+ export type { ButtonProps, ButtonVariant, ButtonTheme, ButtonSize, ButtonShape, ButtonGroupProps } from './Button';
@@ -0,0 +1,16 @@
1
+ import { default as React } from 'react';
2
+ export type InputSize = 'sm' | 'md' | 'lg';
3
+ export type InputStatus = 'default' | 'error';
4
+ export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'prefix'> {
5
+ size?: InputSize;
6
+ status?: InputStatus;
7
+ label?: string;
8
+ hint?: string;
9
+ errorMsg?: string;
10
+ prefix?: React.ReactNode;
11
+ suffix?: React.ReactNode;
12
+ clearable?: boolean;
13
+ block?: boolean;
14
+ }
15
+ declare const Input: React.FC<InputProps>;
16
+ export default Input;
@@ -0,0 +1,2 @@
1
+ export { default as Input } from './Input';
2
+ export type { InputProps, InputSize, InputStatus } from './Input';
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),h=require("react"),B=({size:i=14})=>e.jsx("svg",{className:"o2-btn__spinner",width:i,height:i,viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:e.jsx("circle",{cx:"8",cy:"8",r:"6",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeDasharray:"30",strokeDashoffset:"10"})}),E=({variant:i="solid",theme:r="default",size:n="md",shape:l="rounded",loading:t=!1,prefixIcon:_,suffixIcon:a,iconOnly:c=!1,block:u=!1,disabled:s,children:g,className:p="",...o})=>{const f=r==="primary"?"default":r,b=n==="lg"?16:n==="mini"?12:14,m=s||t,F=["o2-btn",`o2-btn--${i}`,`o2-btn--theme-${f}`,`o2-btn--${n}`,l==="pill"?"o2-btn--pill":"",c?"o2-btn--icon-only":"",u?"o2-btn--block":"",t?"o2-btn--loading":"",p].filter(Boolean).join(" ");return e.jsxs("button",{className:F,disabled:m,"aria-busy":t,...o,children:[t&&e.jsx(B,{size:b}),!t&&_&&e.jsx("span",{className:"o2-btn__icon o2-btn__icon--prefix","aria-hidden":"true",children:_}),g&&e.jsx("span",{className:"o2-btn__label",children:g}),!t&&a&&e.jsx("span",{className:"o2-btn__icon o2-btn__icon--suffix","aria-hidden":"true",children:a})]})},W=({children:i,size:r,shape:n})=>{const l=h.Children.map(i,t=>h.isValidElement(t)?h.cloneElement(t,{size:r??t.props.size,shape:n??t.props.shape}):t);return e.jsx("div",{className:`o2-btn-group ${n==="pill"?"o2-btn-group--pill":""}`,children:l})},H=({size:i="md",status:r="default",label:n,hint:l,errorMsg:t,prefix:_,suffix:a,clearable:c=!1,block:u=!1,disabled:s,value:g,defaultValue:p,onChange:o,className:f="",...b})=>{const[m,F]=h.useState(p??""),y=g!==void 0,x=y?g:m,S=d=>{y||F(d.target.value),o==null||o(d)},z=()=>{y||F("");const d={target:{value:""}};o==null||o(d)},j=r==="error"||!!t,A=["o2-input-wrapper",`o2-input-wrapper--${i}`,j?"o2-input-wrapper--error":"",s?"o2-input-wrapper--disabled":"",u?"o2-input-wrapper--block":"",f].filter(Boolean).join(" ");return e.jsxs("div",{className:`o2-input-field ${u?"o2-input-field--block":""}`,children:[n&&e.jsx("label",{className:"o2-input-label",children:n}),e.jsxs("div",{className:A,children:[_&&e.jsx("span",{className:"o2-input-affix o2-input-prefix",children:_}),e.jsx("input",{className:"o2-input",disabled:s,value:x,onChange:S,...b}),c&&x&&!s&&e.jsx("button",{type:"button",className:"o2-input-clear",onClick:z,"aria-label":"清除",children:e.jsx("svg",{viewBox:"0 0 16 16",fill:"currentColor",width:"14",height:"14",children:e.jsx("path",{d:"M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm2.95 9.24-.71.71L8 8.71l-2.24 2.24-.71-.71L7.29 8 5.05 5.76l.71-.71L8 7.29l2.24-2.24.71.71L8.71 8l2.24 2.24z"})})}),a&&e.jsx("span",{className:"o2-input-affix o2-input-suffix",children:a})]}),(l||t)&&e.jsx("p",{className:`o2-input-hint ${j?"o2-input-hint--error":""}`,children:t||l})]})},C={"文字_gray_13-t1":"#121212","文字_gray_09-t2":"#666666","文字_gray_06-t3and禁用":"#A3A3AF",文字_白色:"#FFFFFF",文字_品牌:"#000000",文字_警告:"#000000",文字_危险:"#000000",文字_成功:"#000000",图标_常规:"#121212","描边_l1-gray_03":"#F1F1F1",图标_辅助:"#888996","中性_gray_01-light":"#FFFFFF","中性_gray_02-悬浮and禁用":"#F5F5F7",中性_gray_03:"#F1F1F1",中性_gray_04:"#E4E4E4","中性_gray_05-点击":"#C9C9C9","描边_l2-gray_04":"#E4E4E4","描边_l3-gray_06":"#AFAFAF",描边_悬浮and点击:"#474BFF",图标_禁用:"#A3A3AF",图标_白色:"#FFFFFF",图标_品牌:"#000000",图标_危险:"#000000",图标_警告:"#000000",图标_成功:"#000000","品牌_blue_01-light":"#E8ECFF","品牌_blue_02-浅色and点击":"#C8D0FF","品牌_blue_04-置灰":"#8791FF","品牌_blue_05-悬浮":"#676FFF","品牌_blue_06-常规":"#474BFF","品牌_blue_07-点击":"#2F2CD2","警告_golden_01-light":"#FFFAE3","警告_golden_04-置灰":"#FAD05B","警告_golden_05-悬浮":"#F9BC2D","警告_golden_06-常规":"#F7A600","警告_golden_07-点击":"#CC8100","成功_green_01-light":"#EBFFE7","成功_green_03-置灰":"#88E57D","成功_green_05-悬浮":"#2BCC25","成功_green_06-常规":"#00BF00","成功_green_07-点击":"#00A205","危险_red_01-light":"#FFEBE8","危险_red_04-置灰":"#F66D68","危险_red_05-悬浮":"#F34040","危险_red_06-常规":"#F0181F","危险_red_07-点击":"#C70F1B",背景_界面背景:"#F1F1F1",背景_侧导航背景:"#FAFAFC",背景_主题色背景:"#000000",背景_侧导航二级背景:"#F5F5F7","表格_gray_01-light":"#FFFFFF",表格_斑马线:"#FAFAFC",表格_悬浮:"#000000",表格_标题背景填充使用:"#000000",表格_描边:"#000000",描边_错误:"#F0181F"},N={spacing_0:0,spacing_min:2,spacing_4:4,spacing_8:8,spacing_12:12,spacing_16:16,spacing_20:20},v={s:0,m:4,l:8,xl:12},k={body_body_01:{fontSize:12,fontWeight:"regular",lineHeight:20},body_body_02:{fontSize:14,fontWeight:"regular",lineHeight:22},body_body_03:{fontSize:16,fontWeight:"regular",lineHeight:24},body_body_04:{fontSize:18,fontWeight:"regular",lineHeight:26},body_body_05:{fontSize:20,fontWeight:"regular",lineHeight:28},heading_h0:{fontSize:12,fontWeight:"medium",lineHeight:20},heading_h1:{fontSize:14,fontWeight:"medium",lineHeight:22},heading_h2:{fontSize:16,fontWeight:"medium",lineHeight:24},heading_h3:{fontSize:18,fontWeight:"medium",lineHeight:26},heading_h4:{fontSize:20,fontWeight:"medium",lineHeight:28},heading_h5:{fontSize:24,fontWeight:"medium",lineHeight:32},heading_h6:{fontSize:32,fontWeight:"medium",lineHeight:40},heading_h7:{fontSize:48,fontWeight:"medium",lineHeight:56},link_小:{fontSize:12,fontWeight:"regular",lineHeight:20},link_中:{fontSize:14,fontWeight:"regular",lineHeight:22},link_大:{fontSize:16,fontWeight:"regular",lineHeight:24}};exports.Button=E;exports.ButtonGroup=W;exports.Input=H;exports.colors=C;exports.radius=v;exports.spacing=N;exports.typography=k;
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/components/Button/Button.tsx","../src/components/Input/Input.tsx","../src/tokens/index.ts"],"sourcesContent":["import React from 'react';\nimport './Button.css';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** 按钮类型:实心(主要) | 描边(次要) | 文字(Ghost) */\nexport type ButtonVariant = 'solid' | 'outline' | 'ghost';\n\n/**\n * 按钮颜色主题\n * - default:常规蓝(品牌色)\n * - primary:主要蓝(同 default,语义更明确)\n * - danger:危险红\n * - warning:警告橙\n * - success:成功绿\n */\nexport type ButtonTheme = 'default' | 'primary' | 'danger' | 'warning' | 'success';\n\n/** 尺寸:大(40px) | 中(32px) | 小(24px) | 迷你(20px) */\nexport type ButtonSize = 'lg' | 'md' | 'sm' | 'mini';\n\n/** 按钮形状:半圆角(4px) | 全圆角胶囊 */\nexport type ButtonShape = 'rounded' | 'pill';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** 按钮类型,默认 solid */\n variant?: ButtonVariant;\n /** 颜色主题,默认 default */\n theme?: ButtonTheme;\n /** 尺寸,默认 md */\n size?: ButtonSize;\n /** 按钮形状,默认 rounded */\n shape?: ButtonShape;\n /**\n * 加载状态:spinner 显示在文字左侧,按钮进入不可点击态\n * 文字保持可见(不隐藏),视觉上表达\"处理中\"\n */\n loading?: boolean;\n /** 前置图标 */\n prefixIcon?: React.ReactNode;\n /** 后置图标 */\n suffixIcon?: React.ReactNode;\n /** 仅图标模式(正方形/圆形按钮,无文字) */\n iconOnly?: boolean;\n /** 撑满父容器宽度 */\n block?: boolean;\n children?: React.ReactNode;\n}\n\n// ─── Loading Spinner ──────────────────────────────────────────────────────────\n\nconst Spinner: React.FC<{ size?: number }> = ({ size = 14 }) => (\n <svg\n className=\"o2-btn__spinner\"\n width={size}\n height={size}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <circle\n cx=\"8\" cy=\"8\" r=\"6\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeDasharray=\"30\"\n strokeDashoffset=\"10\"\n />\n </svg>\n);\n\n// ─── Button ───────────────────────────────────────────────────────────────────\n\nconst Button: React.FC<ButtonProps> = ({\n variant = 'solid',\n theme = 'default',\n size = 'md',\n shape = 'rounded',\n loading = false,\n prefixIcon,\n suffixIcon,\n iconOnly = false,\n block = false,\n disabled,\n children,\n className = '',\n ...rest\n}) => {\n // primary 是 default 的语义别名\n const resolvedTheme = theme === 'primary' ? 'default' : theme;\n const spinnerSize = size === 'lg' ? 16 : size === 'mini' ? 12 : 14;\n const isDisabled = disabled || loading;\n\n const cls = [\n 'o2-btn',\n `o2-btn--${variant}`,\n `o2-btn--theme-${resolvedTheme}`,\n `o2-btn--${size}`,\n shape === 'pill' ? 'o2-btn--pill' : '',\n iconOnly ? 'o2-btn--icon-only' : '',\n block ? 'o2-btn--block' : '',\n loading ? 'o2-btn--loading' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <button className={cls} disabled={isDisabled} aria-busy={loading} {...rest}>\n {/* loading 时:spinner 在左侧,文字保留 */}\n {loading && <Spinner size={spinnerSize} />}\n\n {/* 非 loading 时:前置图标 */}\n {!loading && prefixIcon && (\n <span className=\"o2-btn__icon o2-btn__icon--prefix\" aria-hidden=\"true\">\n {prefixIcon}\n </span>\n )}\n\n {/* 文字内容 */}\n {children && <span className=\"o2-btn__label\">{children}</span>}\n\n {/* 后置图标(loading 时隐藏) */}\n {!loading && suffixIcon && (\n <span className=\"o2-btn__icon o2-btn__icon--suffix\" aria-hidden=\"true\">\n {suffixIcon}\n </span>\n )}\n </button>\n );\n};\n\nexport default Button;\n\n// ─── ButtonGroup ──────────────────────────────────────────────────────────────\n\nexport interface ButtonGroupProps {\n children: React.ReactNode;\n /** 组内按钮尺寸统一 */\n size?: ButtonSize;\n /** 是否全圆角 */\n shape?: ButtonShape;\n}\n\n/**\n * ButtonGroup 组合按钮\n * 多个按钮合并为一体,共享边框,中间分隔线自动处理\n * 用法:<ButtonGroup><Button>选项A</Button><Button>选项B</Button></ButtonGroup>\n */\nexport const ButtonGroup: React.FC<ButtonGroupProps> = ({ children, size, shape }) => {\n // 将 size/shape 注入子按钮\n const items = React.Children.map(children, (child) => {\n if (!React.isValidElement(child)) return child;\n return React.cloneElement(child as React.ReactElement<ButtonProps>, {\n size: size ?? (child.props as ButtonProps).size,\n shape: shape ?? (child.props as ButtonProps).shape,\n });\n });\n\n return (\n <div className={`o2-btn-group ${shape === 'pill' ? 'o2-btn-group--pill' : ''}`}>\n {items}\n </div>\n );\n};\n","import React, { useState } from 'react';\nimport './Input.css';\n\nexport type InputSize = 'sm' | 'md' | 'lg';\nexport type InputStatus = 'default' | 'error';\n\nexport interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'prefix'> {\n size?: InputSize;\n status?: InputStatus;\n label?: string;\n hint?: string;\n errorMsg?: string;\n prefix?: React.ReactNode;\n suffix?: React.ReactNode;\n clearable?: boolean;\n block?: boolean;\n}\n\nconst Input: React.FC<InputProps> = ({\n size = 'md',\n status = 'default',\n label,\n hint,\n errorMsg,\n prefix,\n suffix,\n clearable = false,\n block = false,\n disabled,\n value,\n defaultValue,\n onChange,\n className = '',\n ...rest\n}) => {\n const [innerValue, setInnerValue] = useState(defaultValue ?? '');\n const isControlled = value !== undefined;\n const currentValue = isControlled ? value : innerValue;\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) setInnerValue(e.target.value);\n onChange?.(e);\n };\n\n const handleClear = () => {\n if (!isControlled) setInnerValue('');\n const event = { target: { value: '' } } as React.ChangeEvent<HTMLInputElement>;\n onChange?.(event);\n };\n\n const hasError = status === 'error' || !!errorMsg;\n const wrapCls = [\n 'o2-input-wrapper',\n `o2-input-wrapper--${size}`,\n hasError ? 'o2-input-wrapper--error' : '',\n disabled ? 'o2-input-wrapper--disabled' : '',\n block ? 'o2-input-wrapper--block' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div className={`o2-input-field ${block ? 'o2-input-field--block' : ''}`}>\n {label && <label className=\"o2-input-label\">{label}</label>}\n <div className={wrapCls}>\n {prefix && <span className=\"o2-input-affix o2-input-prefix\">{prefix}</span>}\n <input\n className=\"o2-input\"\n disabled={disabled}\n value={currentValue}\n onChange={handleChange}\n {...rest}\n />\n {clearable && currentValue && !disabled && (\n <button\n type=\"button\"\n className=\"o2-input-clear\"\n onClick={handleClear}\n aria-label=\"清除\"\n >\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" width=\"14\" height=\"14\">\n <path d=\"M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm2.95 9.24-.71.71L8 8.71l-2.24 2.24-.71-.71L7.29 8 5.05 5.76l.71-.71L8 7.29l2.24-2.24.71.71L8.71 8l2.24 2.24z\"/>\n </svg>\n </button>\n )}\n {suffix && <span className=\"o2-input-affix o2-input-suffix\">{suffix}</span>}\n </div>\n {(hint || errorMsg) && (\n <p className={`o2-input-hint ${hasError ? 'o2-input-hint--error' : ''}`}>\n {errorMsg || hint}\n </p>\n )}\n </div>\n );\n};\n\nexport default Input;\n","// ─── Design Tokens (JS/TS) ───────────────────────────────────────────────────\n// Auto-generated from variables.json\n\nexport const colors = {\n '文字_gray_13-t1': '#121212',\n '文字_gray_09-t2': '#666666',\n '文字_gray_06-t3and禁用': '#A3A3AF',\n '文字_白色': '#FFFFFF',\n '文字_品牌': '#000000',\n '文字_警告': '#000000',\n '文字_危险': '#000000',\n '文字_成功': '#000000',\n '图标_常规': '#121212',\n '描边_l1-gray_03': '#F1F1F1',\n '图标_辅助': '#888996',\n '中性_gray_01-light': '#FFFFFF',\n '中性_gray_02-悬浮and禁用': '#F5F5F7',\n '中性_gray_03': '#F1F1F1',\n '中性_gray_04': '#E4E4E4',\n '中性_gray_05-点击': '#C9C9C9',\n '描边_l2-gray_04': '#E4E4E4',\n '描边_l3-gray_06': '#AFAFAF',\n '描边_悬浮and点击': '#474BFF',\n '图标_禁用': '#A3A3AF',\n '图标_白色': '#FFFFFF',\n '图标_品牌': '#000000',\n '图标_危险': '#000000',\n '图标_警告': '#000000',\n '图标_成功': '#000000',\n '品牌_blue_01-light': '#E8ECFF',\n '品牌_blue_02-浅色and点击': '#C8D0FF',\n '品牌_blue_04-置灰': '#8791FF',\n '品牌_blue_05-悬浮': '#676FFF',\n '品牌_blue_06-常规': '#474BFF',\n '品牌_blue_07-点击': '#2F2CD2',\n '警告_golden_01-light': '#FFFAE3',\n '警告_golden_04-置灰': '#FAD05B',\n '警告_golden_05-悬浮': '#F9BC2D',\n '警告_golden_06-常规': '#F7A600',\n '警告_golden_07-点击': '#CC8100',\n '成功_green_01-light': '#EBFFE7',\n '成功_green_03-置灰': '#88E57D',\n '成功_green_05-悬浮': '#2BCC25',\n '成功_green_06-常规': '#00BF00',\n '成功_green_07-点击': '#00A205',\n '危险_red_01-light': '#FFEBE8',\n '危险_red_04-置灰': '#F66D68',\n '危险_red_05-悬浮': '#F34040',\n '危险_red_06-常规': '#F0181F',\n '危险_red_07-点击': '#C70F1B',\n '背景_界面背景': '#F1F1F1',\n '背景_侧导航背景': '#FAFAFC',\n '背景_主题色背景': '#000000',\n '背景_侧导航二级背景': '#F5F5F7',\n '表格_gray_01-light': '#FFFFFF',\n '表格_斑马线': '#FAFAFC',\n '表格_悬浮': '#000000',\n '表格_标题背景填充使用': '#000000',\n '表格_描边': '#000000',\n '描边_错误': '#F0181F',\n} as const\n\nexport const spacing = {\n spacing_0: 0,\n spacing_min: 2,\n spacing_4: 4,\n spacing_8: 8,\n spacing_12: 12,\n spacing_16: 16,\n spacing_20: 20,\n} as const\n\nexport const radius = {\n s: 0,\n m: 4,\n l: 8,\n xl: 12,\n} as const\n\nexport const typography = {\n body_body_01: { fontSize: 12, fontWeight: 'regular', lineHeight: 20 },\n body_body_02: { fontSize: 14, fontWeight: 'regular', lineHeight: 22 },\n body_body_03: { fontSize: 16, fontWeight: 'regular', lineHeight: 24 },\n body_body_04: { fontSize: 18, fontWeight: 'regular', lineHeight: 26 },\n body_body_05: { fontSize: 20, fontWeight: 'regular', lineHeight: 28 },\n heading_h0: { fontSize: 12, fontWeight: 'medium', lineHeight: 20 },\n heading_h1: { fontSize: 14, fontWeight: 'medium', lineHeight: 22 },\n heading_h2: { fontSize: 16, fontWeight: 'medium', lineHeight: 24 },\n heading_h3: { fontSize: 18, fontWeight: 'medium', lineHeight: 26 },\n heading_h4: { fontSize: 20, fontWeight: 'medium', lineHeight: 28 },\n heading_h5: { fontSize: 24, fontWeight: 'medium', lineHeight: 32 },\n heading_h6: { fontSize: 32, fontWeight: 'medium', lineHeight: 40 },\n heading_h7: { fontSize: 48, fontWeight: 'medium', lineHeight: 56 },\n link_小: { fontSize: 12, fontWeight: 'regular', lineHeight: 20 },\n link_中: { fontSize: 14, fontWeight: 'regular', lineHeight: 22 },\n link_大: { fontSize: 16, fontWeight: 'regular', lineHeight: 24 },\n} as const\n"],"names":["Spinner","size","jsx","Button","variant","theme","shape","loading","prefixIcon","suffixIcon","iconOnly","block","disabled","children","className","rest","resolvedTheme","spinnerSize","isDisabled","cls","jsxs","ButtonGroup","items","React","child","Input","status","label","hint","errorMsg","prefix","suffix","clearable","value","defaultValue","onChange","innerValue","setInnerValue","useState","isControlled","currentValue","handleChange","e","handleClear","event","hasError","wrapCls","colors","spacing","radius","typography"],"mappings":"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"}
package/dist/index.css ADDED
@@ -0,0 +1 @@
1
+ .o2-btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-4);border:1px solid transparent;border-radius:var(--radius-m);font-family:var(--font-family-base);font-weight:500;line-height:1;white-space:nowrap;cursor:pointer;outline:none;-webkit-user-select:none;user-select:none;transition:background-color .15s ease,border-color .15s ease,color .15s ease,box-shadow .15s ease;position:relative}.o2-btn:focus-visible{outline:2px solid var(--color-品牌-blue-06-常规);outline-offset:2px}.o2-btn--block{width:100%}.o2-btn--lg{height:40px;padding:0 var(--spacing-16);font-size:var(--font-size-body-body-03)}.o2-btn--md{height:32px;padding:0 var(--spacing-12);font-size:var(--font-size-body-body-02)}.o2-btn--sm{height:24px;padding:0 var(--spacing-8);font-size:var(--font-size-body-body-01)}.o2-btn--mini{height:20px;padding:0 var(--spacing-8);font-size:var(--font-size-body-body-01)}.o2-btn--pill{border-radius:999px}.o2-btn--icon-only.o2-btn--lg{width:40px;padding:0}.o2-btn--icon-only.o2-btn--md{width:32px;padding:0}.o2-btn--icon-only.o2-btn--sm{width:24px;padding:0}.o2-btn--icon-only.o2-btn--mini{width:20px;padding:0}.o2-btn__icon{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1em;height:1em}.o2-btn__spinner{animation:o2-spin .7s linear infinite;flex-shrink:0}@keyframes o2-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.o2-btn--loading{cursor:not-allowed}.o2-btn--solid.o2-btn--theme-default{background-color:var(--color-品牌-blue-06-常规);border-color:var(--color-品牌-blue-06-常规);color:#fff;box-shadow:var(--shadow-elevation-品牌色)}.o2-btn--solid.o2-btn--theme-default:hover:not(:disabled){background-color:var(--color-品牌-blue-05-悬浮);border-color:var(--color-品牌-blue-05-悬浮)}.o2-btn--solid.o2-btn--theme-default:active:not(:disabled){background-color:var(--color-品牌-blue-07-点击);border-color:var(--color-品牌-blue-07-点击);box-shadow:none}.o2-btn--solid.o2-btn--theme-default:disabled{background-color:var(--color-品牌-blue-04-置灰);border-color:var(--color-品牌-blue-04-置灰);box-shadow:none;cursor:not-allowed}.o2-btn--solid.o2-btn--theme-danger{background-color:var(--color-危险-red-06-常规);border-color:var(--color-危险-red-06-常规);color:#fff}.o2-btn--solid.o2-btn--theme-danger:hover:not(:disabled){background-color:var(--color-危险-red-05-悬浮);border-color:var(--color-危险-red-05-悬浮)}.o2-btn--solid.o2-btn--theme-danger:active:not(:disabled){background-color:var(--color-危险-red-07-点击);border-color:var(--color-危险-red-07-点击)}.o2-btn--solid.o2-btn--theme-danger:disabled{background-color:var(--color-危险-red-04-置灰);border-color:var(--color-危险-red-04-置灰);cursor:not-allowed}.o2-btn--solid.o2-btn--theme-warning{background-color:var(--color-警告-golden-06-常规);border-color:var(--color-警告-golden-06-常规);color:#fff}.o2-btn--solid.o2-btn--theme-warning:hover:not(:disabled){background-color:var(--color-警告-golden-05-悬浮);border-color:var(--color-警告-golden-05-悬浮)}.o2-btn--solid.o2-btn--theme-warning:active:not(:disabled){background-color:var(--color-警告-golden-07-点击);border-color:var(--color-警告-golden-07-点击)}.o2-btn--solid.o2-btn--theme-warning:disabled{background-color:var(--color-警告-golden-04-置灰);border-color:var(--color-警告-golden-04-置灰);cursor:not-allowed}.o2-btn--solid.o2-btn--theme-success{background-color:var(--color-成功-green-06-常规);border-color:var(--color-成功-green-06-常规);color:#fff}.o2-btn--solid.o2-btn--theme-success:hover:not(:disabled){background-color:var(--color-成功-green-05-悬浮);border-color:var(--color-成功-green-05-悬浮)}.o2-btn--solid.o2-btn--theme-success:active:not(:disabled){background-color:var(--color-成功-green-07-点击);border-color:var(--color-成功-green-07-点击)}.o2-btn--solid.o2-btn--theme-success:disabled{background-color:var(--color-成功-green-03-置灰);border-color:var(--color-成功-green-03-置灰);cursor:not-allowed}.o2-btn--outline.o2-btn--theme-default{background-color:transparent;border-color:var(--color-描边-l2-gray-04);color:var(--color-文字-gray-13-t1)}.o2-btn--outline.o2-btn--theme-default:hover:not(:disabled){border-color:var(--color-描边-悬浮and点击);color:var(--color-品牌-blue-06-常规);background-color:var(--color-品牌-blue-01-light)}.o2-btn--outline.o2-btn--theme-default:active:not(:disabled){border-color:var(--color-品牌-blue-07-点击);color:var(--color-品牌-blue-07-点击);background-color:var(--color-品牌-blue-02-浅色and点击)}.o2-btn--outline.o2-btn--theme-default:disabled{border-color:var(--color-描边-l1-gray-03);color:var(--color-文字-gray-06-t3and禁用);cursor:not-allowed}.o2-btn--outline.o2-btn--theme-danger{background-color:transparent;border-color:var(--color-危险-red-06-常规);color:var(--color-危险-red-06-常规)}.o2-btn--outline.o2-btn--theme-danger:hover:not(:disabled){background-color:var(--color-危险-red-01-light);border-color:var(--color-危险-red-05-悬浮);color:var(--color-危险-red-05-悬浮)}.o2-btn--outline.o2-btn--theme-danger:active:not(:disabled){background-color:var(--color-危险-red-01-light);border-color:var(--color-危险-red-07-点击);color:var(--color-危险-red-07-点击)}.o2-btn--outline.o2-btn--theme-danger:disabled{border-color:var(--color-危险-red-04-置灰);color:var(--color-危险-red-04-置灰);cursor:not-allowed}.o2-btn--outline.o2-btn--theme-warning{background-color:transparent;border-color:var(--color-警告-golden-06-常规);color:var(--color-警告-golden-06-常规)}.o2-btn--outline.o2-btn--theme-warning:hover:not(:disabled){background-color:var(--color-警告-golden-01-light);border-color:var(--color-警告-golden-05-悬浮);color:var(--color-警告-golden-05-悬浮)}.o2-btn--outline.o2-btn--theme-warning:active:not(:disabled){background-color:var(--color-警告-golden-01-light);border-color:var(--color-警告-golden-07-点击);color:var(--color-警告-golden-07-点击)}.o2-btn--outline.o2-btn--theme-warning:disabled{border-color:var(--color-警告-golden-04-置灰);color:var(--color-警告-golden-04-置灰);cursor:not-allowed}.o2-btn--outline.o2-btn--theme-success{background-color:transparent;border-color:var(--color-成功-green-06-常规);color:var(--color-成功-green-06-常规)}.o2-btn--outline.o2-btn--theme-success:hover:not(:disabled){background-color:var(--color-成功-green-01-light);border-color:var(--color-成功-green-05-悬浮);color:var(--color-成功-green-05-悬浮)}.o2-btn--outline.o2-btn--theme-success:active:not(:disabled){background-color:var(--color-成功-green-01-light);border-color:var(--color-成功-green-07-点击);color:var(--color-成功-green-07-点击)}.o2-btn--outline.o2-btn--theme-success:disabled{border-color:var(--color-成功-green-03-置灰);color:var(--color-成功-green-03-置灰);cursor:not-allowed}.o2-btn--ghost.o2-btn--theme-default{background-color:transparent;border-color:transparent;color:var(--color-文字-gray-13-t1)}.o2-btn--ghost.o2-btn--theme-default:hover:not(:disabled){background-color:var(--color-中性-gray-02-悬浮and禁用)}.o2-btn--ghost.o2-btn--theme-default:active:not(:disabled){background-color:var(--color-中性-gray-03)}.o2-btn--ghost.o2-btn--theme-default:disabled{color:var(--color-文字-gray-06-t3and禁用);cursor:not-allowed}.o2-btn--ghost.o2-btn--theme-danger{background-color:transparent;border-color:transparent;color:var(--color-危险-red-06-常规)}.o2-btn--ghost.o2-btn--theme-danger:hover:not(:disabled){background-color:var(--color-危险-red-01-light);color:var(--color-危险-red-05-悬浮)}.o2-btn--ghost.o2-btn--theme-danger:active:not(:disabled){background-color:var(--color-危险-red-01-light);color:var(--color-危险-red-07-点击)}.o2-btn--ghost.o2-btn--theme-danger:disabled{color:var(--color-危险-red-04-置灰);cursor:not-allowed}.o2-btn--ghost.o2-btn--theme-warning{background-color:transparent;border-color:transparent;color:var(--color-警告-golden-06-常规)}.o2-btn--ghost.o2-btn--theme-warning:hover:not(:disabled){background-color:var(--color-警告-golden-01-light);color:var(--color-警告-golden-05-悬浮)}.o2-btn--ghost.o2-btn--theme-warning:active:not(:disabled){background-color:var(--color-警告-golden-01-light);color:var(--color-警告-golden-07-点击)}.o2-btn--ghost.o2-btn--theme-warning:disabled{color:var(--color-警告-golden-04-置灰);cursor:not-allowed}.o2-btn--ghost.o2-btn--theme-success{background-color:transparent;border-color:transparent;color:var(--color-成功-green-06-常规)}.o2-btn--ghost.o2-btn--theme-success:hover:not(:disabled){background-color:var(--color-成功-green-01-light);color:var(--color-成功-green-05-悬浮)}.o2-btn--ghost.o2-btn--theme-success:active:not(:disabled){background-color:var(--color-成功-green-01-light);color:var(--color-成功-green-07-点击)}.o2-btn--ghost.o2-btn--theme-success:disabled{color:var(--color-成功-green-03-置灰);cursor:not-allowed}.o2-btn-group{display:inline-flex;align-items:stretch}.o2-btn-group .o2-btn{border-radius:0;margin-right:-1px;position:relative;z-index:0}.o2-btn-group .o2-btn:hover,.o2-btn-group .o2-btn:focus-visible{z-index:1}.o2-btn-group .o2-btn:first-child{border-radius:var(--radius-m) 0 0 var(--radius-m)}.o2-btn-group .o2-btn:last-child{border-radius:0 var(--radius-m) var(--radius-m) 0;margin-right:0}.o2-btn-group .o2-btn:only-child{border-radius:var(--radius-m)}.o2-btn-group--pill .o2-btn:first-child{border-radius:999px 0 0 999px}.o2-btn-group--pill .o2-btn:last-child{border-radius:0 999px 999px 0}.o2-input-field{display:inline-flex;flex-direction:column;gap:4px;min-width:0}.o2-input-field--block{display:flex;width:100%}.o2-input-label{font-size:13px;font-weight:500;color:var(--color-文字-gray-13-t1, #121212);line-height:20px}.o2-input-wrapper{position:relative;display:inline-flex;align-items:center;background:var(--color-中性-gray-01-light, #FFFFFF);border:1px solid var(--color-描边-l2-gray-04, #E4E4E4);border-radius:var(--radius-m, 4px);transition:border-color .2s,box-shadow .2s;cursor:text;box-sizing:border-box}.o2-input-wrapper--block{width:100%}.o2-input-wrapper:hover:not(.o2-input-wrapper--disabled){border-color:var(--color-描边-l3-gray-06, #AFAFAF)}.o2-input-wrapper:focus-within:not(.o2-input-wrapper--disabled){border-color:var(--color-描边-悬浮and点击, #474BFF);box-shadow:0 0 0 2px #474bff1f;outline:none}.o2-input-wrapper--error{border-color:var(--color-描边-错误, #F0181F)!important}.o2-input-wrapper--error:focus-within{box-shadow:0 0 0 2px #f0181f1f!important}.o2-input-wrapper--disabled{background:var(--color-中性-gray-02-悬浮and禁用, #F5F5F7);border-color:var(--color-描边-l2-gray-04, #E4E4E4);cursor:not-allowed}.o2-input-wrapper--lg{height:40px;padding:0 12px;gap:6px}.o2-input-wrapper--md{height:32px;padding:0 10px;gap:6px}.o2-input-wrapper--sm{height:24px;padding:0 8px;gap:4px}.o2-input{flex:1;min-width:0;border:none;outline:none;background:transparent;color:var(--color-文字-gray-13-t1, #121212);caret-color:var(--color-品牌-blue-06-常规, #474BFF);font-family:var(--font-family-base, "PingFang SC", sans-serif);padding:0}.o2-input-wrapper--lg .o2-input,.o2-input-wrapper--md .o2-input{font-size:14px}.o2-input-wrapper--sm .o2-input{font-size:12px}.o2-input::placeholder{color:var(--color-文字-gray-06-t3and禁用, #A3A3AF)}.o2-input:disabled{cursor:not-allowed;color:var(--color-文字-gray-06-t3and禁用, #A3A3AF)}.o2-input-affix{display:flex;align-items:center;flex-shrink:0;color:var(--color-图标-辅助, #888996);font-size:16px;line-height:1}.o2-input-wrapper--sm .o2-input-affix{font-size:14px}.o2-input-clear{display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;border:none;background:transparent;color:var(--color-图标-辅助, #888996);cursor:pointer;border-radius:50%;transition:color .15s,background-color .15s;width:18px;height:18px}.o2-input-clear:hover{color:var(--color-文字-gray-13-t1, #121212);background:var(--color-中性-gray-03, #F1F1F1)}.o2-input-hint{font-size:12px;color:var(--color-文字-gray-09-t2, #666666);margin:0;line-height:20px}.o2-input-hint--error{color:var(--color-文字-危险, #F0181F)}[data-theme=dark] .o2-input-wrapper{background:var(--color-中性-gray-02-悬浮and禁用, #252525);border-color:var(--color-描边-l2-gray-04, #3A3A3A)}[data-theme=dark] .o2-input-wrapper--disabled{background:var(--color-中性-gray-03, #2E2E2E)}[data-theme=dark] .o2-input-clear:hover{background:var(--color-中性-gray-04, #3A3A3A)}
@@ -0,0 +1,5 @@
1
+ export { default as Button, ButtonGroup } from './components/Button/Button';
2
+ export type { ButtonProps, ButtonVariant, ButtonTheme, ButtonSize, ButtonShape, ButtonGroupProps, } from './components/Button/Button';
3
+ export { default as Input } from './components/Input/Input';
4
+ export type { InputProps, InputSize, InputStatus } from './components/Input/Input';
5
+ export { colors, spacing, radius, typography } from './tokens/index';
package/dist/index.mjs ADDED
@@ -0,0 +1,220 @@
1
+ import { jsxs as z, jsx as n } from "react/jsx-runtime";
2
+ import y, { useState as B } from "react";
3
+ const C = ({ size: i = 14 }) => /* @__PURE__ */ n(
4
+ "svg",
5
+ {
6
+ className: "o2-btn__spinner",
7
+ width: i,
8
+ height: i,
9
+ viewBox: "0 0 16 16",
10
+ fill: "none",
11
+ "aria-hidden": "true",
12
+ children: /* @__PURE__ */ n(
13
+ "circle",
14
+ {
15
+ cx: "8",
16
+ cy: "8",
17
+ r: "6",
18
+ stroke: "currentColor",
19
+ strokeWidth: "2",
20
+ strokeLinecap: "round",
21
+ strokeDasharray: "30",
22
+ strokeDashoffset: "10"
23
+ }
24
+ )
25
+ }
26
+ ), k = ({
27
+ variant: i = "solid",
28
+ theme: l = "default",
29
+ size: t = "md",
30
+ shape: r = "rounded",
31
+ loading: e = !1,
32
+ prefixIcon: _,
33
+ suffixIcon: a,
34
+ iconOnly: u = !1,
35
+ block: g = !1,
36
+ disabled: s,
37
+ children: F,
38
+ className: c = "",
39
+ ...o
40
+ }) => {
41
+ const p = l === "primary" ? "default" : l, f = t === "lg" ? 16 : t === "mini" ? 12 : 14, m = s || e, d = [
42
+ "o2-btn",
43
+ `o2-btn--${i}`,
44
+ `o2-btn--theme-${p}`,
45
+ `o2-btn--${t}`,
46
+ r === "pill" ? "o2-btn--pill" : "",
47
+ u ? "o2-btn--icon-only" : "",
48
+ g ? "o2-btn--block" : "",
49
+ e ? "o2-btn--loading" : "",
50
+ c
51
+ ].filter(Boolean).join(" ");
52
+ return /* @__PURE__ */ z("button", { className: d, disabled: m, "aria-busy": e, ...o, children: [
53
+ e && /* @__PURE__ */ n(C, { size: f }),
54
+ !e && _ && /* @__PURE__ */ n("span", { className: "o2-btn__icon o2-btn__icon--prefix", "aria-hidden": "true", children: _ }),
55
+ F && /* @__PURE__ */ n("span", { className: "o2-btn__label", children: F }),
56
+ !e && a && /* @__PURE__ */ n("span", { className: "o2-btn__icon o2-btn__icon--suffix", "aria-hidden": "true", children: a })
57
+ ] });
58
+ }, w = ({ children: i, size: l, shape: t }) => {
59
+ const r = y.Children.map(i, (e) => y.isValidElement(e) ? y.cloneElement(e, {
60
+ size: l ?? e.props.size,
61
+ shape: t ?? e.props.shape
62
+ }) : e);
63
+ return /* @__PURE__ */ n("div", { className: `o2-btn-group ${t === "pill" ? "o2-btn-group--pill" : ""}`, children: r });
64
+ }, x = ({
65
+ size: i = "md",
66
+ status: l = "default",
67
+ label: t,
68
+ hint: r,
69
+ errorMsg: e,
70
+ prefix: _,
71
+ suffix: a,
72
+ clearable: u = !1,
73
+ block: g = !1,
74
+ disabled: s,
75
+ value: F,
76
+ defaultValue: c,
77
+ onChange: o,
78
+ className: p = "",
79
+ ...f
80
+ }) => {
81
+ const [m, d] = B(c ?? ""), b = F !== void 0, S = b ? F : m, E = (h) => {
82
+ b || d(h.target.value), o == null || o(h);
83
+ }, W = () => {
84
+ b || d("");
85
+ const h = { target: { value: "" } };
86
+ o == null || o(h);
87
+ }, A = l === "error" || !!e, H = [
88
+ "o2-input-wrapper",
89
+ `o2-input-wrapper--${i}`,
90
+ A ? "o2-input-wrapper--error" : "",
91
+ s ? "o2-input-wrapper--disabled" : "",
92
+ g ? "o2-input-wrapper--block" : "",
93
+ p
94
+ ].filter(Boolean).join(" ");
95
+ return /* @__PURE__ */ z("div", { className: `o2-input-field ${g ? "o2-input-field--block" : ""}`, children: [
96
+ t && /* @__PURE__ */ n("label", { className: "o2-input-label", children: t }),
97
+ /* @__PURE__ */ z("div", { className: H, children: [
98
+ _ && /* @__PURE__ */ n("span", { className: "o2-input-affix o2-input-prefix", children: _ }),
99
+ /* @__PURE__ */ n(
100
+ "input",
101
+ {
102
+ className: "o2-input",
103
+ disabled: s,
104
+ value: S,
105
+ onChange: E,
106
+ ...f
107
+ }
108
+ ),
109
+ u && S && !s && /* @__PURE__ */ n(
110
+ "button",
111
+ {
112
+ type: "button",
113
+ className: "o2-input-clear",
114
+ onClick: W,
115
+ "aria-label": "清除",
116
+ children: /* @__PURE__ */ n("svg", { viewBox: "0 0 16 16", fill: "currentColor", width: "14", height: "14", children: /* @__PURE__ */ n("path", { d: "M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm2.95 9.24-.71.71L8 8.71l-2.24 2.24-.71-.71L7.29 8 5.05 5.76l.71-.71L8 7.29l2.24-2.24.71.71L8.71 8l2.24 2.24z" }) })
117
+ }
118
+ ),
119
+ a && /* @__PURE__ */ n("span", { className: "o2-input-affix o2-input-suffix", children: a })
120
+ ] }),
121
+ (r || e) && /* @__PURE__ */ n("p", { className: `o2-input-hint ${A ? "o2-input-hint--error" : ""}`, children: e || r })
122
+ ] });
123
+ }, D = {
124
+ "文字_gray_13-t1": "#121212",
125
+ "文字_gray_09-t2": "#666666",
126
+ "文字_gray_06-t3and禁用": "#A3A3AF",
127
+ 文字_白色: "#FFFFFF",
128
+ 文字_品牌: "#000000",
129
+ 文字_警告: "#000000",
130
+ 文字_危险: "#000000",
131
+ 文字_成功: "#000000",
132
+ 图标_常规: "#121212",
133
+ "描边_l1-gray_03": "#F1F1F1",
134
+ 图标_辅助: "#888996",
135
+ "中性_gray_01-light": "#FFFFFF",
136
+ "中性_gray_02-悬浮and禁用": "#F5F5F7",
137
+ 中性_gray_03: "#F1F1F1",
138
+ 中性_gray_04: "#E4E4E4",
139
+ "中性_gray_05-点击": "#C9C9C9",
140
+ "描边_l2-gray_04": "#E4E4E4",
141
+ "描边_l3-gray_06": "#AFAFAF",
142
+ 描边_悬浮and点击: "#474BFF",
143
+ 图标_禁用: "#A3A3AF",
144
+ 图标_白色: "#FFFFFF",
145
+ 图标_品牌: "#000000",
146
+ 图标_危险: "#000000",
147
+ 图标_警告: "#000000",
148
+ 图标_成功: "#000000",
149
+ "品牌_blue_01-light": "#E8ECFF",
150
+ "品牌_blue_02-浅色and点击": "#C8D0FF",
151
+ "品牌_blue_04-置灰": "#8791FF",
152
+ "品牌_blue_05-悬浮": "#676FFF",
153
+ "品牌_blue_06-常规": "#474BFF",
154
+ "品牌_blue_07-点击": "#2F2CD2",
155
+ "警告_golden_01-light": "#FFFAE3",
156
+ "警告_golden_04-置灰": "#FAD05B",
157
+ "警告_golden_05-悬浮": "#F9BC2D",
158
+ "警告_golden_06-常规": "#F7A600",
159
+ "警告_golden_07-点击": "#CC8100",
160
+ "成功_green_01-light": "#EBFFE7",
161
+ "成功_green_03-置灰": "#88E57D",
162
+ "成功_green_05-悬浮": "#2BCC25",
163
+ "成功_green_06-常规": "#00BF00",
164
+ "成功_green_07-点击": "#00A205",
165
+ "危险_red_01-light": "#FFEBE8",
166
+ "危险_red_04-置灰": "#F66D68",
167
+ "危险_red_05-悬浮": "#F34040",
168
+ "危险_red_06-常规": "#F0181F",
169
+ "危险_red_07-点击": "#C70F1B",
170
+ 背景_界面背景: "#F1F1F1",
171
+ 背景_侧导航背景: "#FAFAFC",
172
+ 背景_主题色背景: "#000000",
173
+ 背景_侧导航二级背景: "#F5F5F7",
174
+ "表格_gray_01-light": "#FFFFFF",
175
+ 表格_斑马线: "#FAFAFC",
176
+ 表格_悬浮: "#000000",
177
+ 表格_标题背景填充使用: "#000000",
178
+ 表格_描边: "#000000",
179
+ 描边_错误: "#F0181F"
180
+ }, $ = {
181
+ spacing_0: 0,
182
+ spacing_min: 2,
183
+ spacing_4: 4,
184
+ spacing_8: 8,
185
+ spacing_12: 12,
186
+ spacing_16: 16,
187
+ spacing_20: 20
188
+ }, L = {
189
+ s: 0,
190
+ m: 4,
191
+ l: 8,
192
+ xl: 12
193
+ }, j = {
194
+ body_body_01: { fontSize: 12, fontWeight: "regular", lineHeight: 20 },
195
+ body_body_02: { fontSize: 14, fontWeight: "regular", lineHeight: 22 },
196
+ body_body_03: { fontSize: 16, fontWeight: "regular", lineHeight: 24 },
197
+ body_body_04: { fontSize: 18, fontWeight: "regular", lineHeight: 26 },
198
+ body_body_05: { fontSize: 20, fontWeight: "regular", lineHeight: 28 },
199
+ heading_h0: { fontSize: 12, fontWeight: "medium", lineHeight: 20 },
200
+ heading_h1: { fontSize: 14, fontWeight: "medium", lineHeight: 22 },
201
+ heading_h2: { fontSize: 16, fontWeight: "medium", lineHeight: 24 },
202
+ heading_h3: { fontSize: 18, fontWeight: "medium", lineHeight: 26 },
203
+ heading_h4: { fontSize: 20, fontWeight: "medium", lineHeight: 28 },
204
+ heading_h5: { fontSize: 24, fontWeight: "medium", lineHeight: 32 },
205
+ heading_h6: { fontSize: 32, fontWeight: "medium", lineHeight: 40 },
206
+ heading_h7: { fontSize: 48, fontWeight: "medium", lineHeight: 56 },
207
+ link_小: { fontSize: 12, fontWeight: "regular", lineHeight: 20 },
208
+ link_中: { fontSize: 14, fontWeight: "regular", lineHeight: 22 },
209
+ link_大: { fontSize: 16, fontWeight: "regular", lineHeight: 24 }
210
+ };
211
+ export {
212
+ k as Button,
213
+ w as ButtonGroup,
214
+ x as Input,
215
+ D as colors,
216
+ L as radius,
217
+ $ as spacing,
218
+ j as typography
219
+ };
220
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../src/components/Button/Button.tsx","../src/components/Input/Input.tsx","../src/tokens/index.ts"],"sourcesContent":["import React from 'react';\nimport './Button.css';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** 按钮类型:实心(主要) | 描边(次要) | 文字(Ghost) */\nexport type ButtonVariant = 'solid' | 'outline' | 'ghost';\n\n/**\n * 按钮颜色主题\n * - default:常规蓝(品牌色)\n * - primary:主要蓝(同 default,语义更明确)\n * - danger:危险红\n * - warning:警告橙\n * - success:成功绿\n */\nexport type ButtonTheme = 'default' | 'primary' | 'danger' | 'warning' | 'success';\n\n/** 尺寸:大(40px) | 中(32px) | 小(24px) | 迷你(20px) */\nexport type ButtonSize = 'lg' | 'md' | 'sm' | 'mini';\n\n/** 按钮形状:半圆角(4px) | 全圆角胶囊 */\nexport type ButtonShape = 'rounded' | 'pill';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** 按钮类型,默认 solid */\n variant?: ButtonVariant;\n /** 颜色主题,默认 default */\n theme?: ButtonTheme;\n /** 尺寸,默认 md */\n size?: ButtonSize;\n /** 按钮形状,默认 rounded */\n shape?: ButtonShape;\n /**\n * 加载状态:spinner 显示在文字左侧,按钮进入不可点击态\n * 文字保持可见(不隐藏),视觉上表达\"处理中\"\n */\n loading?: boolean;\n /** 前置图标 */\n prefixIcon?: React.ReactNode;\n /** 后置图标 */\n suffixIcon?: React.ReactNode;\n /** 仅图标模式(正方形/圆形按钮,无文字) */\n iconOnly?: boolean;\n /** 撑满父容器宽度 */\n block?: boolean;\n children?: React.ReactNode;\n}\n\n// ─── Loading Spinner ──────────────────────────────────────────────────────────\n\nconst Spinner: React.FC<{ size?: number }> = ({ size = 14 }) => (\n <svg\n className=\"o2-btn__spinner\"\n width={size}\n height={size}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <circle\n cx=\"8\" cy=\"8\" r=\"6\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeDasharray=\"30\"\n strokeDashoffset=\"10\"\n />\n </svg>\n);\n\n// ─── Button ───────────────────────────────────────────────────────────────────\n\nconst Button: React.FC<ButtonProps> = ({\n variant = 'solid',\n theme = 'default',\n size = 'md',\n shape = 'rounded',\n loading = false,\n prefixIcon,\n suffixIcon,\n iconOnly = false,\n block = false,\n disabled,\n children,\n className = '',\n ...rest\n}) => {\n // primary 是 default 的语义别名\n const resolvedTheme = theme === 'primary' ? 'default' : theme;\n const spinnerSize = size === 'lg' ? 16 : size === 'mini' ? 12 : 14;\n const isDisabled = disabled || loading;\n\n const cls = [\n 'o2-btn',\n `o2-btn--${variant}`,\n `o2-btn--theme-${resolvedTheme}`,\n `o2-btn--${size}`,\n shape === 'pill' ? 'o2-btn--pill' : '',\n iconOnly ? 'o2-btn--icon-only' : '',\n block ? 'o2-btn--block' : '',\n loading ? 'o2-btn--loading' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <button className={cls} disabled={isDisabled} aria-busy={loading} {...rest}>\n {/* loading 时:spinner 在左侧,文字保留 */}\n {loading && <Spinner size={spinnerSize} />}\n\n {/* 非 loading 时:前置图标 */}\n {!loading && prefixIcon && (\n <span className=\"o2-btn__icon o2-btn__icon--prefix\" aria-hidden=\"true\">\n {prefixIcon}\n </span>\n )}\n\n {/* 文字内容 */}\n {children && <span className=\"o2-btn__label\">{children}</span>}\n\n {/* 后置图标(loading 时隐藏) */}\n {!loading && suffixIcon && (\n <span className=\"o2-btn__icon o2-btn__icon--suffix\" aria-hidden=\"true\">\n {suffixIcon}\n </span>\n )}\n </button>\n );\n};\n\nexport default Button;\n\n// ─── ButtonGroup ──────────────────────────────────────────────────────────────\n\nexport interface ButtonGroupProps {\n children: React.ReactNode;\n /** 组内按钮尺寸统一 */\n size?: ButtonSize;\n /** 是否全圆角 */\n shape?: ButtonShape;\n}\n\n/**\n * ButtonGroup 组合按钮\n * 多个按钮合并为一体,共享边框,中间分隔线自动处理\n * 用法:<ButtonGroup><Button>选项A</Button><Button>选项B</Button></ButtonGroup>\n */\nexport const ButtonGroup: React.FC<ButtonGroupProps> = ({ children, size, shape }) => {\n // 将 size/shape 注入子按钮\n const items = React.Children.map(children, (child) => {\n if (!React.isValidElement(child)) return child;\n return React.cloneElement(child as React.ReactElement<ButtonProps>, {\n size: size ?? (child.props as ButtonProps).size,\n shape: shape ?? (child.props as ButtonProps).shape,\n });\n });\n\n return (\n <div className={`o2-btn-group ${shape === 'pill' ? 'o2-btn-group--pill' : ''}`}>\n {items}\n </div>\n );\n};\n","import React, { useState } from 'react';\nimport './Input.css';\n\nexport type InputSize = 'sm' | 'md' | 'lg';\nexport type InputStatus = 'default' | 'error';\n\nexport interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'prefix'> {\n size?: InputSize;\n status?: InputStatus;\n label?: string;\n hint?: string;\n errorMsg?: string;\n prefix?: React.ReactNode;\n suffix?: React.ReactNode;\n clearable?: boolean;\n block?: boolean;\n}\n\nconst Input: React.FC<InputProps> = ({\n size = 'md',\n status = 'default',\n label,\n hint,\n errorMsg,\n prefix,\n suffix,\n clearable = false,\n block = false,\n disabled,\n value,\n defaultValue,\n onChange,\n className = '',\n ...rest\n}) => {\n const [innerValue, setInnerValue] = useState(defaultValue ?? '');\n const isControlled = value !== undefined;\n const currentValue = isControlled ? value : innerValue;\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) setInnerValue(e.target.value);\n onChange?.(e);\n };\n\n const handleClear = () => {\n if (!isControlled) setInnerValue('');\n const event = { target: { value: '' } } as React.ChangeEvent<HTMLInputElement>;\n onChange?.(event);\n };\n\n const hasError = status === 'error' || !!errorMsg;\n const wrapCls = [\n 'o2-input-wrapper',\n `o2-input-wrapper--${size}`,\n hasError ? 'o2-input-wrapper--error' : '',\n disabled ? 'o2-input-wrapper--disabled' : '',\n block ? 'o2-input-wrapper--block' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div className={`o2-input-field ${block ? 'o2-input-field--block' : ''}`}>\n {label && <label className=\"o2-input-label\">{label}</label>}\n <div className={wrapCls}>\n {prefix && <span className=\"o2-input-affix o2-input-prefix\">{prefix}</span>}\n <input\n className=\"o2-input\"\n disabled={disabled}\n value={currentValue}\n onChange={handleChange}\n {...rest}\n />\n {clearable && currentValue && !disabled && (\n <button\n type=\"button\"\n className=\"o2-input-clear\"\n onClick={handleClear}\n aria-label=\"清除\"\n >\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" width=\"14\" height=\"14\">\n <path d=\"M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zm2.95 9.24-.71.71L8 8.71l-2.24 2.24-.71-.71L7.29 8 5.05 5.76l.71-.71L8 7.29l2.24-2.24.71.71L8.71 8l2.24 2.24z\"/>\n </svg>\n </button>\n )}\n {suffix && <span className=\"o2-input-affix o2-input-suffix\">{suffix}</span>}\n </div>\n {(hint || errorMsg) && (\n <p className={`o2-input-hint ${hasError ? 'o2-input-hint--error' : ''}`}>\n {errorMsg || hint}\n </p>\n )}\n </div>\n );\n};\n\nexport default Input;\n","// ─── Design Tokens (JS/TS) ───────────────────────────────────────────────────\n// Auto-generated from variables.json\n\nexport const colors = {\n '文字_gray_13-t1': '#121212',\n '文字_gray_09-t2': '#666666',\n '文字_gray_06-t3and禁用': '#A3A3AF',\n '文字_白色': '#FFFFFF',\n '文字_品牌': '#000000',\n '文字_警告': '#000000',\n '文字_危险': '#000000',\n '文字_成功': '#000000',\n '图标_常规': '#121212',\n '描边_l1-gray_03': '#F1F1F1',\n '图标_辅助': '#888996',\n '中性_gray_01-light': '#FFFFFF',\n '中性_gray_02-悬浮and禁用': '#F5F5F7',\n '中性_gray_03': '#F1F1F1',\n '中性_gray_04': '#E4E4E4',\n '中性_gray_05-点击': '#C9C9C9',\n '描边_l2-gray_04': '#E4E4E4',\n '描边_l3-gray_06': '#AFAFAF',\n '描边_悬浮and点击': '#474BFF',\n '图标_禁用': '#A3A3AF',\n '图标_白色': '#FFFFFF',\n '图标_品牌': '#000000',\n '图标_危险': '#000000',\n '图标_警告': '#000000',\n '图标_成功': '#000000',\n '品牌_blue_01-light': '#E8ECFF',\n '品牌_blue_02-浅色and点击': '#C8D0FF',\n '品牌_blue_04-置灰': '#8791FF',\n '品牌_blue_05-悬浮': '#676FFF',\n '品牌_blue_06-常规': '#474BFF',\n '品牌_blue_07-点击': '#2F2CD2',\n '警告_golden_01-light': '#FFFAE3',\n '警告_golden_04-置灰': '#FAD05B',\n '警告_golden_05-悬浮': '#F9BC2D',\n '警告_golden_06-常规': '#F7A600',\n '警告_golden_07-点击': '#CC8100',\n '成功_green_01-light': '#EBFFE7',\n '成功_green_03-置灰': '#88E57D',\n '成功_green_05-悬浮': '#2BCC25',\n '成功_green_06-常规': '#00BF00',\n '成功_green_07-点击': '#00A205',\n '危险_red_01-light': '#FFEBE8',\n '危险_red_04-置灰': '#F66D68',\n '危险_red_05-悬浮': '#F34040',\n '危险_red_06-常规': '#F0181F',\n '危险_red_07-点击': '#C70F1B',\n '背景_界面背景': '#F1F1F1',\n '背景_侧导航背景': '#FAFAFC',\n '背景_主题色背景': '#000000',\n '背景_侧导航二级背景': '#F5F5F7',\n '表格_gray_01-light': '#FFFFFF',\n '表格_斑马线': '#FAFAFC',\n '表格_悬浮': '#000000',\n '表格_标题背景填充使用': '#000000',\n '表格_描边': '#000000',\n '描边_错误': '#F0181F',\n} as const\n\nexport const spacing = {\n spacing_0: 0,\n spacing_min: 2,\n spacing_4: 4,\n spacing_8: 8,\n spacing_12: 12,\n spacing_16: 16,\n spacing_20: 20,\n} as const\n\nexport const radius = {\n s: 0,\n m: 4,\n l: 8,\n xl: 12,\n} as const\n\nexport const typography = {\n body_body_01: { fontSize: 12, fontWeight: 'regular', lineHeight: 20 },\n body_body_02: { fontSize: 14, fontWeight: 'regular', lineHeight: 22 },\n body_body_03: { fontSize: 16, fontWeight: 'regular', lineHeight: 24 },\n body_body_04: { fontSize: 18, fontWeight: 'regular', lineHeight: 26 },\n body_body_05: { fontSize: 20, fontWeight: 'regular', lineHeight: 28 },\n heading_h0: { fontSize: 12, fontWeight: 'medium', lineHeight: 20 },\n heading_h1: { fontSize: 14, fontWeight: 'medium', lineHeight: 22 },\n heading_h2: { fontSize: 16, fontWeight: 'medium', lineHeight: 24 },\n heading_h3: { fontSize: 18, fontWeight: 'medium', lineHeight: 26 },\n heading_h4: { fontSize: 20, fontWeight: 'medium', lineHeight: 28 },\n heading_h5: { fontSize: 24, fontWeight: 'medium', lineHeight: 32 },\n heading_h6: { fontSize: 32, fontWeight: 'medium', lineHeight: 40 },\n heading_h7: { fontSize: 48, fontWeight: 'medium', lineHeight: 56 },\n link_小: { fontSize: 12, fontWeight: 'regular', lineHeight: 20 },\n link_中: { fontSize: 14, fontWeight: 'regular', lineHeight: 22 },\n link_大: { fontSize: 16, fontWeight: 'regular', lineHeight: 24 },\n} as const\n"],"names":["Spinner","size","jsx","Button","variant","theme","shape","loading","prefixIcon","suffixIcon","iconOnly","block","disabled","children","className","rest","resolvedTheme","spinnerSize","isDisabled","cls","jsxs","ButtonGroup","items","React","child","Input","status","label","hint","errorMsg","prefix","suffix","clearable","value","defaultValue","onChange","innerValue","setInnerValue","useState","isControlled","currentValue","handleChange","e","handleClear","event","hasError","wrapCls","colors","spacing","radius","typography"],"mappings":"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"}
@@ -0,0 +1,155 @@
1
+ export declare const colors: {
2
+ readonly '\u6587\u5B57_gray_13-t1': "#121212";
3
+ readonly '\u6587\u5B57_gray_09-t2': "#666666";
4
+ readonly '\u6587\u5B57_gray_06-t3and\u7981\u7528': "#A3A3AF";
5
+ readonly 文字_白色: "#FFFFFF";
6
+ readonly 文字_品牌: "#000000";
7
+ readonly 文字_警告: "#000000";
8
+ readonly 文字_危险: "#000000";
9
+ readonly 文字_成功: "#000000";
10
+ readonly 图标_常规: "#121212";
11
+ readonly '\u63CF\u8FB9_l1-gray_03': "#F1F1F1";
12
+ readonly 图标_辅助: "#888996";
13
+ readonly '\u4E2D\u6027_gray_01-light': "#FFFFFF";
14
+ readonly '\u4E2D\u6027_gray_02-\u60AC\u6D6Eand\u7981\u7528': "#F5F5F7";
15
+ readonly 中性_gray_03: "#F1F1F1";
16
+ readonly 中性_gray_04: "#E4E4E4";
17
+ readonly '\u4E2D\u6027_gray_05-\u70B9\u51FB': "#C9C9C9";
18
+ readonly '\u63CF\u8FB9_l2-gray_04': "#E4E4E4";
19
+ readonly '\u63CF\u8FB9_l3-gray_06': "#AFAFAF";
20
+ readonly 描边_悬浮and点击: "#474BFF";
21
+ readonly 图标_禁用: "#A3A3AF";
22
+ readonly 图标_白色: "#FFFFFF";
23
+ readonly 图标_品牌: "#000000";
24
+ readonly 图标_危险: "#000000";
25
+ readonly 图标_警告: "#000000";
26
+ readonly 图标_成功: "#000000";
27
+ readonly '\u54C1\u724C_blue_01-light': "#E8ECFF";
28
+ readonly '\u54C1\u724C_blue_02-\u6D45\u8272and\u70B9\u51FB': "#C8D0FF";
29
+ readonly '\u54C1\u724C_blue_04-\u7F6E\u7070': "#8791FF";
30
+ readonly '\u54C1\u724C_blue_05-\u60AC\u6D6E': "#676FFF";
31
+ readonly '\u54C1\u724C_blue_06-\u5E38\u89C4': "#474BFF";
32
+ readonly '\u54C1\u724C_blue_07-\u70B9\u51FB': "#2F2CD2";
33
+ readonly '\u8B66\u544A_golden_01-light': "#FFFAE3";
34
+ readonly '\u8B66\u544A_golden_04-\u7F6E\u7070': "#FAD05B";
35
+ readonly '\u8B66\u544A_golden_05-\u60AC\u6D6E': "#F9BC2D";
36
+ readonly '\u8B66\u544A_golden_06-\u5E38\u89C4': "#F7A600";
37
+ readonly '\u8B66\u544A_golden_07-\u70B9\u51FB': "#CC8100";
38
+ readonly '\u6210\u529F_green_01-light': "#EBFFE7";
39
+ readonly '\u6210\u529F_green_03-\u7F6E\u7070': "#88E57D";
40
+ readonly '\u6210\u529F_green_05-\u60AC\u6D6E': "#2BCC25";
41
+ readonly '\u6210\u529F_green_06-\u5E38\u89C4': "#00BF00";
42
+ readonly '\u6210\u529F_green_07-\u70B9\u51FB': "#00A205";
43
+ readonly '\u5371\u9669_red_01-light': "#FFEBE8";
44
+ readonly '\u5371\u9669_red_04-\u7F6E\u7070': "#F66D68";
45
+ readonly '\u5371\u9669_red_05-\u60AC\u6D6E': "#F34040";
46
+ readonly '\u5371\u9669_red_06-\u5E38\u89C4': "#F0181F";
47
+ readonly '\u5371\u9669_red_07-\u70B9\u51FB': "#C70F1B";
48
+ readonly 背景_界面背景: "#F1F1F1";
49
+ readonly 背景_侧导航背景: "#FAFAFC";
50
+ readonly 背景_主题色背景: "#000000";
51
+ readonly 背景_侧导航二级背景: "#F5F5F7";
52
+ readonly '\u8868\u683C_gray_01-light': "#FFFFFF";
53
+ readonly 表格_斑马线: "#FAFAFC";
54
+ readonly 表格_悬浮: "#000000";
55
+ readonly 表格_标题背景填充使用: "#000000";
56
+ readonly 表格_描边: "#000000";
57
+ readonly 描边_错误: "#F0181F";
58
+ };
59
+ export declare const spacing: {
60
+ readonly spacing_0: 0;
61
+ readonly spacing_min: 2;
62
+ readonly spacing_4: 4;
63
+ readonly spacing_8: 8;
64
+ readonly spacing_12: 12;
65
+ readonly spacing_16: 16;
66
+ readonly spacing_20: 20;
67
+ };
68
+ export declare const radius: {
69
+ readonly s: 0;
70
+ readonly m: 4;
71
+ readonly l: 8;
72
+ readonly xl: 12;
73
+ };
74
+ export declare const typography: {
75
+ readonly body_body_01: {
76
+ readonly fontSize: 12;
77
+ readonly fontWeight: "regular";
78
+ readonly lineHeight: 20;
79
+ };
80
+ readonly body_body_02: {
81
+ readonly fontSize: 14;
82
+ readonly fontWeight: "regular";
83
+ readonly lineHeight: 22;
84
+ };
85
+ readonly body_body_03: {
86
+ readonly fontSize: 16;
87
+ readonly fontWeight: "regular";
88
+ readonly lineHeight: 24;
89
+ };
90
+ readonly body_body_04: {
91
+ readonly fontSize: 18;
92
+ readonly fontWeight: "regular";
93
+ readonly lineHeight: 26;
94
+ };
95
+ readonly body_body_05: {
96
+ readonly fontSize: 20;
97
+ readonly fontWeight: "regular";
98
+ readonly lineHeight: 28;
99
+ };
100
+ readonly heading_h0: {
101
+ readonly fontSize: 12;
102
+ readonly fontWeight: "medium";
103
+ readonly lineHeight: 20;
104
+ };
105
+ readonly heading_h1: {
106
+ readonly fontSize: 14;
107
+ readonly fontWeight: "medium";
108
+ readonly lineHeight: 22;
109
+ };
110
+ readonly heading_h2: {
111
+ readonly fontSize: 16;
112
+ readonly fontWeight: "medium";
113
+ readonly lineHeight: 24;
114
+ };
115
+ readonly heading_h3: {
116
+ readonly fontSize: 18;
117
+ readonly fontWeight: "medium";
118
+ readonly lineHeight: 26;
119
+ };
120
+ readonly heading_h4: {
121
+ readonly fontSize: 20;
122
+ readonly fontWeight: "medium";
123
+ readonly lineHeight: 28;
124
+ };
125
+ readonly heading_h5: {
126
+ readonly fontSize: 24;
127
+ readonly fontWeight: "medium";
128
+ readonly lineHeight: 32;
129
+ };
130
+ readonly heading_h6: {
131
+ readonly fontSize: 32;
132
+ readonly fontWeight: "medium";
133
+ readonly lineHeight: 40;
134
+ };
135
+ readonly heading_h7: {
136
+ readonly fontSize: 48;
137
+ readonly fontWeight: "medium";
138
+ readonly lineHeight: 56;
139
+ };
140
+ readonly link_小: {
141
+ readonly fontSize: 12;
142
+ readonly fontWeight: "regular";
143
+ readonly lineHeight: 20;
144
+ };
145
+ readonly link_中: {
146
+ readonly fontSize: 14;
147
+ readonly fontWeight: "regular";
148
+ readonly lineHeight: 22;
149
+ };
150
+ readonly link_大: {
151
+ readonly fontSize: 16;
152
+ readonly fontWeight: "regular";
153
+ readonly lineHeight: 24;
154
+ };
155
+ };
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@lillian10231023/o2-design-system-1",
3
+ "version": "0.1.0",
4
+ "description": "O2 Design System — React component library with design tokens",
5
+ "keywords": ["react", "component-library", "design-system", "ui", "o2"],
6
+ "author": "O2 Design Team",
7
+ "license": "MIT",
8
+ "type": "module",
9
+ "main": "./dist/index.cjs",
10
+ "module": "./dist/index.mjs",
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.mjs",
16
+ "require": "./dist/index.cjs"
17
+ },
18
+ "./dist/index.css": "./dist/index.css"
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "sideEffects": [
24
+ "**/*.css"
25
+ ],
26
+ "scripts": {
27
+ "dev": "vite",
28
+ "build:lib": "tsc --project tsconfig.lib.json --noEmit && vite build",
29
+ "build": "vite build",
30
+ "preview": "vite preview",
31
+ "prepublishOnly": "npm run build:lib"
32
+ },
33
+ "peerDependencies": {
34
+ "react": ">=17.0.0",
35
+ "react-dom": ">=17.0.0"
36
+ },
37
+ "dependencies": {},
38
+ "devDependencies": {
39
+ "@types/react": "^18.3.28",
40
+ "@types/react-dom": "^18.3.7",
41
+ "@vitejs/plugin-react": "^4.7.0",
42
+ "react": "^18.3.1",
43
+ "react-dom": "^18.3.1",
44
+ "typescript": "~5.6.2",
45
+ "vite": "^6.4.1",
46
+ "vite-plugin-dts": "^4.5.4"
47
+ },
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "https://github.com/your-org/o2-design-system.git"
51
+ },
52
+ "homepage": "https://github.com/your-org/o2-design-system#readme",
53
+ "bugs": {
54
+ "url": "https://github.com/your-org/o2-design-system/issues"
55
+ }
56
+ }