pingk-react-component-lib 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Pingk
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,131 @@
1
+ # Pingk React Component Lib
2
+
3
+ 一个基于 React + TypeScript + Vite 构建的轻量级组件库。
4
+
5
+ ## ✨ 特性
6
+
7
+ * 📦 开箱即用,支持 NPM 安装和 CDN 引入
8
+ * 🦕 完全使用 TypeScript 编写,提供完整的类型定义
9
+ * ⚡️ 基于 Vite 构建,支持 ESM 和 UMD 格式
10
+ * 🎨 内置 BEM 规范的 Sass 样式
11
+
12
+ ## 📦 安装
13
+
14
+ ### 使用包管理器
15
+
16
+ ```bash
17
+ # npm
18
+ npm install pingk-react-component-lib
19
+
20
+ # pnpm
21
+ pnpm add pingk-react-component-lib
22
+
23
+ # yarn
24
+ yarn add pingk-react-component-lib
25
+ ```
26
+
27
+ ### 浏览器直接引入 (CDN)
28
+
29
+ 你也可以直接通过 CDN 引入 UMD 格式的文件:
30
+
31
+ ```html
32
+ <!-- 引入样式 -->
33
+ <link rel="stylesheet" href="https://unpkg.com/pingk-react-component-lib/dist/index.css">
34
+
35
+ <!-- 引入依赖 -->
36
+ <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
37
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
38
+
39
+ <!-- 引入组件库 -->
40
+ <script src="https://unpkg.com/pingk-react-component-lib/dist/index.umd.cjs"></script>
41
+ ```
42
+
43
+ ## 🔨 快速上手
44
+
45
+ ### 在 React 项目中使用
46
+
47
+ ```tsx
48
+ import { useState } from 'react';
49
+ import { MyButton, MyRadio } from 'pingk-react-component-lib';
50
+ // 如果构建工具没有自动处理 CSS注入,可能需要手动引入(视具体配置而定)
51
+ // import 'pingk-react-component-lib/dist/index.css';
52
+
53
+ function App() {
54
+ const [radioValue, setRadioValue] = useState('1');
55
+
56
+ return (
57
+ <div>
58
+ <h2>Button 示例</h2>
59
+ <MyButton
60
+ label="点击我"
61
+ variant="primary"
62
+ onClick={() => alert('Clicked!')}
63
+ />
64
+
65
+ <h2>Radio 示例</h2>
66
+ <MyRadio
67
+ label="选项 A"
68
+ name="group1"
69
+ value="1"
70
+ checked={radioValue === '1'}
71
+ onChange={(e) => setRadioValue(e.target.value)}
72
+ />
73
+ <MyRadio
74
+ label="选项 B"
75
+ name="group1"
76
+ value="2"
77
+ checked={radioValue === '2'}
78
+ onChange={(e) => setRadioValue(e.target.value)}
79
+ />
80
+ </div>
81
+ );
82
+ }
83
+ ```
84
+
85
+ ## 📚 组件文档
86
+
87
+ ### MyButton
88
+
89
+ 基础按钮组件。
90
+
91
+ | 属性 | 类型 | 默认值 | 说明 |
92
+ | :--- | :--- | :--- | :--- |
93
+ | `label` | `string` | **必填** | 按钮显示的文本内容 |
94
+ | `variant` | `'primary' \| 'default'` | `'default'` | 按钮样式变体 |
95
+ | `disabled` | `boolean` | `false` | 是否禁用按钮 |
96
+ | `onClick` | `(event: React.MouseEvent) => void` | `-` | 点击事件回调 |
97
+ | `...props` | `React.ButtonHTMLAttributes` | `-` | 其他原生 button 属性 |
98
+
99
+ ### MyRadio
100
+
101
+ 单选框组件。
102
+
103
+ | 属性 | 类型 | 默认值 | 说明 |
104
+ | :--- | :--- | :--- | :--- |
105
+ | `label` | `string` | `-` | 单选框右侧的标签文本 |
106
+ | `checked` | `boolean` | `-` | 是否选中 |
107
+ | `disabled` | `boolean` | `false` | 是否禁用 |
108
+ | `onChange` | `(event: React.ChangeEvent) => void` | `-` | 状态改变回调 |
109
+ | `...props` | `React.InputHTMLAttributes` | `-` | 其他原生 input[type="radio"] 属性 |
110
+
111
+ ## 💻 本地开发
112
+
113
+ 如果你想参与本项目开发,请参考 [开发指南](./REACT_TS_COMPONENT_DEV_GUIDE.md)。
114
+
115
+ ```bash
116
+ # 克隆项目
117
+ git clone https://github.com/your-repo/pingk-react-component-lib.git
118
+
119
+ # 安装依赖
120
+ pnpm install
121
+
122
+ # 启动开发服务器
123
+ pnpm dev
124
+
125
+ # 运行测试
126
+ pnpm test
127
+ ```
128
+
129
+ ## 📄 License
130
+
131
+ MIT
package/dist/App.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ declare function App(): import("react/jsx-runtime").JSX.Element;
2
+ export default App;
3
+ //# sourceMappingURL=App.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../src/App.tsx"],"names":[],"mappings":"AAGA,iBAAS,GAAG,4CAyEX;AAED,eAAe,GAAG,CAAA"}
@@ -0,0 +1,23 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * MyButton 组件属性接口定义
4
+ */
5
+ export interface MyButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
6
+ /** 按钮显示文本 */
7
+ label: string;
8
+ /** 按钮变体类型 */
9
+ variant?: 'primary' | 'default';
10
+ /** 是否禁用 */
11
+ disabled?: boolean;
12
+ /** 点击事件处理函数 */
13
+ onClick?: React.MouseEventHandler<HTMLButtonElement>;
14
+ }
15
+ /**
16
+ * 业务按钮组件
17
+ *
18
+ * @example
19
+ * <MyButton label="点击我" variant="primary" onClick={() => console.log('clicked')} />
20
+ */
21
+ declare const MyButton: React.FC<MyButtonProps>;
22
+ export default MyButton;
23
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/MyButton/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,cAAc,CAAC;AAEtB;;GAEG;AACH,MAAM,WAAW,aAAc,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;IAClF,aAAa;IACb,KAAK,EAAE,MAAM,CAAC;IACd,aAAa;IACb,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAChC,WAAW;IACX,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe;IACf,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;CACtD;AAED;;;;;GAKG;AACH,QAAA,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAqCrC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { default as React } from 'react';
2
+ export interface MyRadioProps extends React.InputHTMLAttributes<HTMLInputElement> {
3
+ /** 标签文本 */
4
+ label?: string;
5
+ }
6
+ /**
7
+ * 单选框组件
8
+ */
9
+ declare const MyRadio: React.FC<MyRadioProps>;
10
+ export default MyRadio;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/MyRadio/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,cAAc,CAAC;AAEtB,MAAM,WAAW,YAAa,SAAQ,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC;IAC/E,WAAW;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,QAAA,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAkBnC,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { default as MyButton } from './MyButton';
2
+ export type { MyButtonProps } from './MyButton';
3
+ export { default as MyRadio } from './MyRadio';
4
+ export type { MyRadioProps } from './MyRadio';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/C,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC"}
package/dist/index.css ADDED
@@ -0,0 +1 @@
1
+ .my-lib-button{padding:8px 16px;border-radius:4px;border:1px solid transparent;cursor:pointer;transition:all .2s;font-size:14px}.my-lib-button:disabled{cursor:not-allowed;background-color:#f5f5f5;border-color:#d9d9d9;color:#00000040}.my-lib-button:disabled:hover{background-color:#f5f5f5;border-color:#d9d9d9;color:#00000040}.my-lib-button--default{background-color:#fff;border-color:#d9d9d9;color:#333}.my-lib-button--default:hover:not(:disabled){color:#4995ff;border-color:#4995ff}.my-lib-button--primary{background-color:#1677ff;color:#fff}.my-lib-button--primary:hover:not(:disabled){background-color:#4995ff}.my-lib-radio{display:inline-flex;align-items:center;cursor:pointer;font-size:14px;color:#333;margin-right:8px;-webkit-user-select:none;user-select:none}.my-lib-radio__input{position:absolute;opacity:0;width:0;height:0}.my-lib-radio__input:checked+.my-lib-radio__inner{border-color:#1677ff;background-color:#1677ff}.my-lib-radio__input:checked+.my-lib-radio__inner:after{transform:translate(-50%,-50%) scale(1)}.my-lib-radio__input:disabled+.my-lib-radio__inner{background-color:#f5f5f5;border-color:#d9d9d9;cursor:not-allowed}.my-lib-radio__input:disabled+.my-lib-radio__inner:after{background-color:#00000040}.my-lib-radio__input:disabled~.my-lib-radio__label{color:#00000040;cursor:not-allowed}.my-lib-radio__inner{position:relative;display:inline-block;width:16px;height:16px;border:1px solid #d9d9d9;border-radius:50%;background-color:#fff;margin-right:8px;transition:all .2s;box-sizing:border-box}.my-lib-radio__inner:after{content:"";position:absolute;top:50%;left:50%;width:6px;height:6px;border-radius:50%;background-color:#fff;transform:translate(-50%,-50%) scale(0);transition:transform .2s}.my-lib-radio__label{transition:color .2s}
@@ -0,0 +1,5 @@
1
+ export { default as MyButton } from './components/MyButton';
2
+ export type { MyButtonProps } from './components/MyButton';
3
+ export { default as MyRadio } from './components/MyRadio';
4
+ export type { MyRadioProps } from './components/MyRadio';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,45 @@
1
+ import e from "react";
2
+ import './index.css';const s = ({
3
+ label: t,
4
+ variant: n = "default",
5
+ className: l = "",
6
+ disabled: a = !1,
7
+ onClick: r,
8
+ ...m
9
+ }) => {
10
+ const o = (i) => {
11
+ if (a) {
12
+ i.preventDefault();
13
+ return;
14
+ }
15
+ r && r(i);
16
+ };
17
+ return /* @__PURE__ */ e.createElement(
18
+ "button",
19
+ {
20
+ className: `my-lib-button my-lib-button--${n} ${l}`,
21
+ onClick: o,
22
+ disabled: a,
23
+ ...m
24
+ },
25
+ t
26
+ );
27
+ }, u = ({
28
+ label: t,
29
+ className: n = "",
30
+ disabled: l,
31
+ ...a
32
+ }) => /* @__PURE__ */ e.createElement("label", { className: `my-lib-radio ${n}` }, /* @__PURE__ */ e.createElement(
33
+ "input",
34
+ {
35
+ type: "radio",
36
+ className: "my-lib-radio__input",
37
+ disabled: l,
38
+ ...a
39
+ }
40
+ ), /* @__PURE__ */ e.createElement("span", { className: "my-lib-radio__inner" }), t && /* @__PURE__ */ e.createElement("span", { className: "my-lib-radio__label" }, t));
41
+ export {
42
+ s as MyButton,
43
+ u as MyRadio
44
+ };
45
+ //# sourceMappingURL=index.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.es.js","sources":["../src/components/MyButton/index.tsx","../src/components/MyRadio/index.tsx"],"sourcesContent":["import React from 'react';\nimport './index.scss'; // 引入 SCSS 样式\n\n/**\n * MyButton 组件属性接口定义\n */\nexport interface MyButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** 按钮显示文本 */\n label: string;\n /** 按钮变体类型 */\n variant?: 'primary' | 'default';\n /** 是否禁用 */\n disabled?: boolean;\n /** 点击事件处理函数 */\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n}\n\n/**\n * 业务按钮组件\n *\n * @example\n * <MyButton label=\"点击我\" variant=\"primary\" onClick={() => console.log('clicked')} />\n */\nconst MyButton: React.FC<MyButtonProps> = ({\n label,\n variant = 'default',\n className = '',\n disabled = false,\n onClick,\n ...props\n}) => {\n // 处理点击事件,确保禁用状态下不触发\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n // 1. 禁用状态检查\n // 虽然 HTML disabled 属性通常会阻止点击事件,\n // 但在某些特定情况或自定义组件封装中,显式拦截更加安全。\n if (disabled) {\n e.preventDefault();\n return;\n }\n\n // 2. 执行传入的点击回调\n if (onClick) {\n onClick(e);\n }\n };\n\n return (\n <button\n className={`my-lib-button my-lib-button--${variant} ${className}`}\n // 绑定内部处理函数,而非直接透传 onClick\n onClick={handleClick}\n // 将 disabled 属性透传给原生 button 元素,\n // 这会自动触发浏览器的默认禁用行为(如不可聚焦、样式变化等)\n disabled={disabled}\n {...props}\n >\n {label}\n </button>\n );\n};\n\nexport default MyButton;\n","import React from 'react';\nimport './index.scss';\n\nexport interface MyRadioProps extends React.InputHTMLAttributes<HTMLInputElement> {\n /** 标签文本 */\n label?: string;\n}\n\n/**\n * 单选框组件\n */\nconst MyRadio: React.FC<MyRadioProps> = ({\n label,\n className = '',\n disabled,\n ...props\n}) => {\n return (\n <label className={`my-lib-radio ${className}`}>\n <input\n type=\"radio\"\n className=\"my-lib-radio__input\"\n disabled={disabled}\n {...props}\n />\n <span className=\"my-lib-radio__inner\" />\n {label && <span className=\"my-lib-radio__label\">{label}</span>}\n </label>\n );\n};\n\nexport default MyRadio;\n"],"names":["MyButton","label","variant","className","disabled","onClick","props","handleClick","e","React","MyRadio"],"mappings":";AAuBA,MAAMA,IAAoC,CAAC;AAAA,EACzC,OAAAC;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,WAAAC,IAAY;AAAA,EACZ,UAAAC,IAAW;AAAA,EACX,SAAAC;AAAA,EACA,GAAGC;AACL,MAAM;AAEJ,QAAMC,IAAc,CAACC,MAA2C;AAI9D,QAAIJ,GAAU;AACZ,MAAAI,EAAE,eAAA;AACF;AAAA,IACF;AAGA,IAAIH,KACFA,EAAQG,CAAC;AAAA,EAEb;AAEA,SACE,gBAAAC,EAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,gCAAgCP,CAAO,IAAIC,CAAS;AAAA,MAE/D,SAASI;AAAA,MAGT,UAAAH;AAAA,MACC,GAAGE;AAAA,IAAA;AAAA,IAEHL;AAAA,EAAA;AAGP,GCjDMS,IAAkC,CAAC;AAAA,EACvC,OAAAT;AAAA,EACA,WAAAE,IAAY;AAAA,EACZ,UAAAC;AAAA,EACA,GAAGE;AACL,MAEI,gBAAAG,EAAA,cAAC,SAAA,EAAM,WAAW,gBAAgBN,CAAS,MACzC,gBAAAM,EAAA;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,MAAK;AAAA,IACL,WAAU;AAAA,IACV,UAAAL;AAAA,IACC,GAAGE;AAAA,EAAA;AAAA,GAEN,gBAAAG,EAAA,cAAC,QAAA,EAAK,WAAU,sBAAA,CAAsB,GACrCR,KAAS,gBAAAQ,EAAA,cAAC,QAAA,EAAK,WAAU,sBAAA,GAAuBR,CAAM,CACzD;"}
@@ -0,0 +1,3 @@
1
+ (function(r,o){typeof exports=="object"&&typeof module<"u"?o(exports,require("react")):typeof define=="function"&&define.amd?define(["exports","react"],o):(r=typeof globalThis<"u"?globalThis:r||self,o(r.PingkReactComponentLib={},r.React))})(this,(function(r,o){"use strict";var l=document.createElement("style");l.textContent=`.my-lib-button{padding:8px 16px;border-radius:4px;border:1px solid transparent;cursor:pointer;transition:all .2s;font-size:14px}.my-lib-button:disabled{cursor:not-allowed;background-color:#f5f5f5;border-color:#d9d9d9;color:#00000040}.my-lib-button:disabled:hover{background-color:#f5f5f5;border-color:#d9d9d9;color:#00000040}.my-lib-button--default{background-color:#fff;border-color:#d9d9d9;color:#333}.my-lib-button--default:hover:not(:disabled){color:#4995ff;border-color:#4995ff}.my-lib-button--primary{background-color:#1677ff;color:#fff}.my-lib-button--primary:hover:not(:disabled){background-color:#4995ff}.my-lib-radio{display:inline-flex;align-items:center;cursor:pointer;font-size:14px;color:#333;margin-right:8px;-webkit-user-select:none;user-select:none}.my-lib-radio__input{position:absolute;opacity:0;width:0;height:0}.my-lib-radio__input:checked+.my-lib-radio__inner{border-color:#1677ff;background-color:#1677ff}.my-lib-radio__input:checked+.my-lib-radio__inner:after{transform:translate(-50%,-50%) scale(1)}.my-lib-radio__input:disabled+.my-lib-radio__inner{background-color:#f5f5f5;border-color:#d9d9d9;cursor:not-allowed}.my-lib-radio__input:disabled+.my-lib-radio__inner:after{background-color:#00000040}.my-lib-radio__input:disabled~.my-lib-radio__label{color:#00000040;cursor:not-allowed}.my-lib-radio__inner{position:relative;display:inline-block;width:16px;height:16px;border:1px solid #d9d9d9;border-radius:50%;background-color:#fff;margin-right:8px;transition:all .2s;box-sizing:border-box}.my-lib-radio__inner:after{content:"";position:absolute;top:50%;left:50%;width:6px;height:6px;border-radius:50%;background-color:#fff;transform:translate(-50%,-50%) scale(0);transition:transform .2s}.my-lib-radio__label{transition:color .2s}
2
+ /*$vite$:1*/`,document.head.appendChild(l);const b=({label:e,variant:t="default",className:n="",disabled:i=!1,onClick:d,...s})=>{const f=a=>{if(i){a.preventDefault();return}d&&d(a)};return o.createElement("button",{className:`my-lib-button my-lib-button--${t} ${n}`,onClick:f,disabled:i,...s},e)},c=({label:e,className:t="",disabled:n,...i})=>o.createElement("label",{className:`my-lib-radio ${t}`},o.createElement("input",{type:"radio",className:"my-lib-radio__input",disabled:n,...i}),o.createElement("span",{className:"my-lib-radio__inner"}),e&&o.createElement("span",{className:"my-lib-radio__label"},e));r.MyButton=b,r.MyRadio=c,Object.defineProperty(r,Symbol.toStringTag,{value:"Module"})}));
3
+ //# sourceMappingURL=index.umd.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.umd.cjs","sources":["../src/components/MyButton/index.tsx","../src/components/MyRadio/index.tsx"],"sourcesContent":["import React from 'react';\nimport './index.scss'; // 引入 SCSS 样式\n\n/**\n * MyButton 组件属性接口定义\n */\nexport interface MyButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** 按钮显示文本 */\n label: string;\n /** 按钮变体类型 */\n variant?: 'primary' | 'default';\n /** 是否禁用 */\n disabled?: boolean;\n /** 点击事件处理函数 */\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n}\n\n/**\n * 业务按钮组件\n *\n * @example\n * <MyButton label=\"点击我\" variant=\"primary\" onClick={() => console.log('clicked')} />\n */\nconst MyButton: React.FC<MyButtonProps> = ({\n label,\n variant = 'default',\n className = '',\n disabled = false,\n onClick,\n ...props\n}) => {\n // 处理点击事件,确保禁用状态下不触发\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n // 1. 禁用状态检查\n // 虽然 HTML disabled 属性通常会阻止点击事件,\n // 但在某些特定情况或自定义组件封装中,显式拦截更加安全。\n if (disabled) {\n e.preventDefault();\n return;\n }\n\n // 2. 执行传入的点击回调\n if (onClick) {\n onClick(e);\n }\n };\n\n return (\n <button\n className={`my-lib-button my-lib-button--${variant} ${className}`}\n // 绑定内部处理函数,而非直接透传 onClick\n onClick={handleClick}\n // 将 disabled 属性透传给原生 button 元素,\n // 这会自动触发浏览器的默认禁用行为(如不可聚焦、样式变化等)\n disabled={disabled}\n {...props}\n >\n {label}\n </button>\n );\n};\n\nexport default MyButton;\n","import React from 'react';\nimport './index.scss';\n\nexport interface MyRadioProps extends React.InputHTMLAttributes<HTMLInputElement> {\n /** 标签文本 */\n label?: string;\n}\n\n/**\n * 单选框组件\n */\nconst MyRadio: React.FC<MyRadioProps> = ({\n label,\n className = '',\n disabled,\n ...props\n}) => {\n return (\n <label className={`my-lib-radio ${className}`}>\n <input\n type=\"radio\"\n className=\"my-lib-radio__input\"\n disabled={disabled}\n {...props}\n />\n <span className=\"my-lib-radio__inner\" />\n {label && <span className=\"my-lib-radio__label\">{label}</span>}\n </label>\n );\n};\n\nexport default MyRadio;\n"],"names":["MyButton","label","variant","className","disabled","onClick","props","handleClick","e","React","MyRadio"],"mappings":";2CAuBA,MAAMA,EAAoC,CAAC,CACzC,MAAAC,EACA,QAAAC,EAAU,UACV,UAAAC,EAAY,GACZ,SAAAC,EAAW,GACX,QAAAC,EACA,GAAGC,CACL,IAAM,CAEJ,MAAMC,EAAeC,GAA2C,CAI9D,GAAIJ,EAAU,CACZI,EAAE,eAAA,EACF,MACF,CAGIH,GACFA,EAAQG,CAAC,CAEb,EAEA,OACEC,EAAA,cAAC,SAAA,CACC,UAAW,gCAAgCP,CAAO,IAAIC,CAAS,GAE/D,QAASI,EAGT,SAAAH,EACC,GAAGE,CAAA,EAEHL,CAAA,CAGP,ECjDMS,EAAkC,CAAC,CACvC,MAAAT,EACA,UAAAE,EAAY,GACZ,SAAAC,EACA,GAAGE,CACL,IAEIG,EAAA,cAAC,QAAA,CAAM,UAAW,gBAAgBN,CAAS,IACzCM,EAAA,cAAC,QAAA,CACC,KAAK,QACL,UAAU,sBACV,SAAAL,EACC,GAAGE,CAAA,CAAA,EAENG,EAAA,cAAC,OAAA,CAAK,UAAU,qBAAA,CAAsB,EACrCR,GAASQ,EAAA,cAAC,OAAA,CAAK,UAAU,qBAAA,EAAuBR,CAAM,CACzD"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.tsx"],"names":[],"mappings":""}
package/dist/vite.svg ADDED
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "pingk-react-component-lib",
3
+ "version": "1.0.0",
4
+ "description": "A simple React + TypeScript component library built with Vite",
5
+ "author": "Pingk",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "react",
9
+ "typescript",
10
+ "component",
11
+ "library",
12
+ "vite",
13
+ "ui"
14
+ ],
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/your-username/pingk-react-component-lib.git"
18
+ },
19
+ "homepage": "https://github.com/your-username/pingk-react-component-lib#readme",
20
+ "bugs": {
21
+ "url": "https://github.com/your-username/pingk-react-component-lib/issues"
22
+ },
23
+ "type": "module",
24
+ "files": [
25
+ "dist"
26
+ ],
27
+ "main": "./dist/index.umd.cjs",
28
+ "module": "./dist/index.es.js",
29
+ "types": "./dist/index.d.ts",
30
+ "unpkg": "./dist/index.umd.cjs",
31
+ "jsdelivr": "./dist/index.umd.cjs",
32
+ "exports": {
33
+ ".": {
34
+ "types": "./dist/index.d.ts",
35
+ "import": "./dist/index.es.js",
36
+ "require": "./dist/index.umd.cjs"
37
+ },
38
+ "./dist/index.css": "./dist/index.css"
39
+ },
40
+ "peerDependencies": {
41
+ "react": ">=16.8.0",
42
+ "react-dom": ">=16.8.0"
43
+ },
44
+ "sideEffects": [
45
+ "**/*.css"
46
+ ],
47
+ "scripts": {
48
+ "dev": "vite",
49
+ "build": "tsc && vite build",
50
+ "test": "vitest",
51
+ "preview": "vite preview"
52
+ },
53
+ "devDependencies": {
54
+ "@eslint/js": "^9.39.1",
55
+ "@testing-library/dom": "^10.4.1",
56
+ "@testing-library/jest-dom": "^6.9.1",
57
+ "@testing-library/react": "^16.3.1",
58
+ "@testing-library/user-event": "^14.6.1",
59
+ "@types/node": "^24.10.1",
60
+ "@types/react": "^19.2.5",
61
+ "@types/react-dom": "^19.2.3",
62
+ "@vitejs/plugin-react": "^5.1.1",
63
+ "eslint": "^9.39.1",
64
+ "eslint-plugin-react-hooks": "^7.0.1",
65
+ "eslint-plugin-react-refresh": "^0.4.24",
66
+ "globals": "^16.5.0",
67
+ "jsdom": "^27.4.0",
68
+ "react": "^19.2.0",
69
+ "react-dom": "^19.2.0",
70
+ "sass": "^1.97.1",
71
+ "typescript": "~5.9.3",
72
+ "typescript-eslint": "^8.46.4",
73
+ "vite": "^7.2.4",
74
+ "vite-plugin-dts": "^4.5.4",
75
+ "vite-plugin-lib-inject-css": "^2.2.2",
76
+ "vitest": "^4.0.16"
77
+ }
78
+ }