zhl-button 1.0.1

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/ZhlButton.vue ADDED
@@ -0,0 +1,283 @@
1
+ <template>
2
+ <div ref="buttonRef" class="zhl-button-wrapper"></div>
3
+ </template>
4
+
5
+ <script setup>
6
+ import { ref, onUnmounted, onMounted, watch, defineProps, defineEmits } from 'vue'
7
+
8
+ // 导入原始组件和样式 - 样式会自动注入,无需额外引入
9
+ import ZhlButton from './index.js'
10
+ import './style.css'
11
+
12
+ // 如果样式没有自动注入,手动添加样式标签(兼容性处理)
13
+ if (typeof window !== 'undefined' && !document.querySelector('#zhl-button-styles')) {
14
+ const style = document.createElement('style')
15
+ style.id = 'zhl-button-styles'
16
+ style.textContent = `
17
+ /* ZhlButton 样式 - 自动注入 */
18
+ .zhl-btn {
19
+ display: inline-block;
20
+ border: none;
21
+ border-radius: 6px;
22
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
23
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
24
+ font-weight: 500;
25
+ text-align: center;
26
+ text-decoration: none;
27
+ cursor: pointer;
28
+ transition: all 0.2s ease-in-out;
29
+ position: relative;
30
+ overflow: hidden;
31
+ user-select: none;
32
+ outline: none;
33
+ padding: 8px 16px;
34
+ font-size: 14px;
35
+ }
36
+
37
+ .zhl-btn-primary {
38
+ background-color: #1890ff;
39
+ color: #fff;
40
+ }
41
+
42
+ .zhl-btn-primary:hover {
43
+ background-color: #096dd9;
44
+ }
45
+
46
+ .zhl-btn-secondary {
47
+ background-color: #6c757d;
48
+ color: #fff;
49
+ }
50
+
51
+ .zhl-btn-secondary:hover {
52
+ background-color: #5a6268;
53
+ }
54
+
55
+ .zhl-btn-success {
56
+ background-color: #52c41a;
57
+ color: #fff;
58
+ }
59
+
60
+ .zhl-btn-success:hover {
61
+ background-color: #389e0d;
62
+ }
63
+
64
+ .zhl-btn-danger {
65
+ background-color: #ff4d4f;
66
+ color: #fff;
67
+ }
68
+
69
+ .zhl-btn-danger:hover {
70
+ background-color: #cf1322;
71
+ }
72
+
73
+ .zhl-btn-warning {
74
+ background-color: #faad14;
75
+ color: #fff;
76
+ }
77
+
78
+ .zhl-btn-warning:hover {
79
+ background-color: #d48806;
80
+ }
81
+
82
+ .zhl-btn-info {
83
+ background-color: #13c2c2;
84
+ color: #fff;
85
+ }
86
+
87
+ .zhl-btn-info:hover {
88
+ background-color: #08979c;
89
+ }
90
+
91
+ .zhl-btn-light {
92
+ background-color: #f8f9fa;
93
+ color: #212529;
94
+ border: 1px solid #dee2e6;
95
+ }
96
+
97
+ .zhl-btn-light:hover {
98
+ background-color: #e9ecef;
99
+ }
100
+
101
+ .zhl-btn-dark {
102
+ background-color: #343a40;
103
+ color: #fff;
104
+ }
105
+
106
+ .zhl-btn-dark:hover {
107
+ background-color: #23272b;
108
+ }
109
+
110
+ .zhl-btn-outline {
111
+ background-color: transparent;
112
+ color: #1890ff;
113
+ border: 1px solid #1890ff;
114
+ }
115
+
116
+ .zhl-btn-outline:hover {
117
+ background-color: #1890ff;
118
+ color: #fff;
119
+ }
120
+
121
+ .zhl-btn-small {
122
+ padding: 4px 8px;
123
+ font-size: 12px;
124
+ }
125
+
126
+ .zhl-btn-medium {
127
+ padding: 8px 16px;
128
+ font-size: 14px;
129
+ }
130
+
131
+ .zhl-btn-large {
132
+ padding: 12px 24px;
133
+ font-size: 16px;
134
+ }
135
+
136
+ .zhl-btn:disabled {
137
+ opacity: 0.6;
138
+ cursor: not-allowed;
139
+ }
140
+
141
+ .zhl-btn.zhl-btn-loading {
142
+ pointer-events: none;
143
+ opacity: 0.8;
144
+ }
145
+
146
+ .zhl-btn.zhl-btn-loading::after {
147
+ content: '';
148
+ position: absolute;
149
+ top: 50%;
150
+ left: 50%;
151
+ width: 16px;
152
+ height: 16px;
153
+ margin: -8px 0 0 -8px;
154
+ border: 2px solid transparent;
155
+ border-top-color: currentColor;
156
+ border-radius: 50%;
157
+ animation: zhl-btn-spin 1s linear infinite;
158
+ }
159
+
160
+ @keyframes zhl-btn-spin {
161
+ 0% { transform: rotate(0deg); }
162
+ 100% { transform: rotate(360deg); }
163
+ }
164
+ `
165
+ document.head.appendChild(style)
166
+ }
167
+
168
+ // Props定义
169
+ const props = defineProps({
170
+ // 按钮文本
171
+ text: {
172
+ type: String,
173
+ default: '按钮'
174
+ },
175
+ // 按钮类型
176
+ type: {
177
+ type: String,
178
+ default: 'primary',
179
+ validator: (value) => [
180
+ 'primary', 'secondary', 'success', 'danger', 'warning',
181
+ 'info', 'light', 'dark', 'outline'
182
+ ].includes(value)
183
+ },
184
+ // 按钮尺寸
185
+ size: {
186
+ type: String,
187
+ default: 'medium',
188
+ validator: (value) => ['small', 'medium', 'large'].includes(value)
189
+ },
190
+ // 是否禁用
191
+ disabled: {
192
+ type: Boolean,
193
+ default: false
194
+ },
195
+ // 是否加载中
196
+ loading: {
197
+ type: Boolean,
198
+ default: false
199
+ }
200
+ })
201
+
202
+ // Emits定义
203
+ const emit = defineEmits(['click', 'update:loading', 'update:disabled'])
204
+
205
+ // Refs
206
+ const buttonRef = ref(null)
207
+ const buttonInstance = ref(null)
208
+
209
+ // 创建按钮实例
210
+ const createButton = () => {
211
+ if (!buttonRef.value) return
212
+
213
+ // 清理之前的实例
214
+ if (buttonInstance.value) {
215
+ buttonInstance.value.destroy()
216
+ }
217
+
218
+ // 创建新的按钮实例
219
+ buttonInstance.value = new ZhlButton({
220
+ text: props.text,
221
+ type: props.type,
222
+ size: props.size,
223
+ disabled: props.disabled,
224
+ loading: props.loading,
225
+ onClick: handleClick
226
+ })
227
+
228
+ // 渲染到容器
229
+ buttonInstance.value.render(buttonRef.value)
230
+ }
231
+
232
+ // 处理点击事件
233
+ const handleClick = (event) => {
234
+ emit('click', event)
235
+ }
236
+
237
+ // 更新按钮属性
238
+ const updateButton = () => {
239
+ if (!buttonInstance.value) return
240
+
241
+ // 更新各个属性
242
+ buttonInstance.value.setText(props.text)
243
+ buttonInstance.value.setType(props.type)
244
+ buttonInstance.value.setSize(props.size)
245
+ buttonInstance.value.setDisabled(props.disabled)
246
+ buttonInstance.value.setLoading(props.loading)
247
+
248
+ // 触发更新事件
249
+ emit('update:disabled', props.disabled)
250
+ emit('update:loading', props.loading)
251
+ }
252
+
253
+ // 生命周期
254
+ onMounted(() => {
255
+ createButton()
256
+ })
257
+
258
+ onUnmounted(() => {
259
+ if (buttonInstance.value) {
260
+ buttonInstance.value.destroy()
261
+ }
262
+ })
263
+
264
+ // 监听props变化
265
+ watch(
266
+ () => [props.text, props.type, props.size, props.disabled, props.loading],
267
+ () => {
268
+ updateButton()
269
+ },
270
+ { deep: true }
271
+ )
272
+ </script>
273
+
274
+ <style scoped>
275
+ .zhl-button-wrapper {
276
+ display: inline-block;
277
+ }
278
+
279
+ /* 可以在这里添加组件特定的样式 */
280
+ .zhl-button-wrapper :deep(.zhl-btn) {
281
+ /* Vue scoped样式覆盖 */
282
+ }
283
+ </style>
package/demo.js ADDED
@@ -0,0 +1,237 @@
1
+ // ZhlButton Component Demo
2
+ // 导入按钮组件
3
+ const ZhlButton = require("./index.js");
4
+
5
+ console.log("=== ZhlButton Component Demo ===\n");
6
+
7
+ // 等待 DOM 加载完成
8
+ if (typeof document !== "undefined") {
9
+ document.addEventListener("DOMContentLoaded", function () {
10
+ initDemo();
11
+ });
12
+ } else {
13
+ // Node.js 环境下的演示
14
+ initNodeDemo();
15
+ }
16
+
17
+ function initDemo() {
18
+ console.log("初始化演示页面...");
19
+
20
+ // 创建演示容器
21
+ const demoContainer = document.createElement("div");
22
+ demoContainer.style.cssText = `
23
+ padding: 40px;
24
+ max-width: 1200px;
25
+ margin: 0 auto;
26
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
27
+ `;
28
+ demoContainer.innerHTML = `
29
+ <h1 style="color: #333; margin-bottom: 40px;">ZhlButton 组件演示</h1>
30
+
31
+ <section style="margin-bottom: 40px;">
32
+ <h2 style="color: #555; margin-bottom: 20px;">基本按钮类型</h2>
33
+ <div id="basic-types" style="display: flex; flex-wrap: wrap; gap: 15px; margin-bottom: 20px;"></div>
34
+ </section>
35
+
36
+ <section style="margin-bottom: 40px;">
37
+ <h2 style="color: #555; margin-bottom: 20px;">按钮尺寸</h2>
38
+ <div id="sizes" style="display: flex; flex-wrap: wrap; gap: 15px; align-items: center; margin-bottom: 20px;"></div>
39
+ </section>
40
+
41
+ <section style="margin-bottom: 40px;">
42
+ <h2 style="color: #555; margin-bottom: 20px;">交互演示</h2>
43
+ <div id="interactive" style="display: flex; flex-wrap: wrap; gap: 15px; margin-bottom: 20px;"></div>
44
+ <div id="status" style="padding: 15px; background: #f8f9fa; border-radius: 6px; margin-top: 20px;">
45
+ <strong>状态:</strong> <span id="status-text">等待交互...</span>
46
+ </div>
47
+ </section>
48
+ `;
49
+
50
+ document.body.appendChild(demoContainer);
51
+
52
+ // 演示基本按钮类型
53
+ demoBasicTypes();
54
+
55
+ // 演示按钮尺寸
56
+ demoSizes();
57
+
58
+ // 演示交互功能
59
+ demoInteractive();
60
+ }
61
+
62
+ function demoBasicTypes() {
63
+ const container = document.getElementById("basic-types");
64
+ const types = [
65
+ "primary",
66
+ "secondary",
67
+ "success",
68
+ "danger",
69
+ "warning",
70
+ "info",
71
+ "light",
72
+ "dark",
73
+ "outline",
74
+ ];
75
+
76
+ types.forEach((type) => {
77
+ const button = new ZhlButton({
78
+ text: type.charAt(0).toUpperCase() + type.slice(1),
79
+ type: type,
80
+ onClick: () => updateStatus(`点击了 ${type} 按钮`),
81
+ });
82
+
83
+ container.appendChild(button.element);
84
+ });
85
+ }
86
+
87
+ function demoSizes() {
88
+ const container = document.getElementById("sizes");
89
+ const sizes = ["small", "medium", "large"];
90
+
91
+ sizes.forEach((size) => {
92
+ const button = new ZhlButton({
93
+ text: `${size.charAt(0).toUpperCase() + size.slice(1)} Button`,
94
+ size: size,
95
+ type: "primary",
96
+ onClick: () => updateStatus(`点击了 ${size} 尺寸按钮`),
97
+ });
98
+
99
+ container.appendChild(button.element);
100
+ });
101
+ }
102
+
103
+ function demoInteractive() {
104
+ const container = document.getElementById("interactive");
105
+
106
+ // 带点击事件的按钮
107
+ const clickButton = new ZhlButton({
108
+ text: "点击我",
109
+ type: "success",
110
+ onClick: () => {
111
+ updateStatus("按钮被点击了!");
112
+ clickButton.setText("再次点击我");
113
+ },
114
+ });
115
+
116
+ // 加载状态按钮
117
+ const loadingButton = new ZhlButton({
118
+ text: "加载演示",
119
+ type: "info",
120
+ onClick: () => {
121
+ loadingButton.setLoading(true);
122
+ updateStatus("正在加载...");
123
+
124
+ setTimeout(() => {
125
+ loadingButton.setLoading(false);
126
+ updateStatus("加载完成!");
127
+ }, 3000);
128
+ },
129
+ });
130
+
131
+ // 禁用状态按钮
132
+ const disabledButton = new ZhlButton({
133
+ text: "禁用按钮",
134
+ type: "danger",
135
+ disabled: true,
136
+ onClick: () => updateStatus("这个按钮被禁用了"),
137
+ });
138
+
139
+ // 动态更新按钮
140
+ const dynamicButton = new ZhlButton({
141
+ text: "点击改变类型",
142
+ type: "secondary",
143
+ onClick: () => {
144
+ const types = ["primary", "secondary", "success", "warning"];
145
+ const currentIndex = types.indexOf(dynamicButton.type);
146
+ const nextType = types[(currentIndex + 1) % types.length];
147
+ dynamicButton.setType(nextType);
148
+ updateStatus(`按钮类型已更改为: ${nextType}`);
149
+ },
150
+ });
151
+
152
+ container.appendChild(clickButton.element);
153
+ container.appendChild(loadingButton.element);
154
+ container.appendChild(disabledButton.element);
155
+ container.appendChild(dynamicButton.element);
156
+ }
157
+
158
+ function updateStatus(message) {
159
+ const statusText = document.getElementById("status-text");
160
+ if (statusText) {
161
+ statusText.textContent = message;
162
+ console.log("状态更新:", message);
163
+ }
164
+ }
165
+
166
+ // Node.js 环境下的演示
167
+ function initNodeDemo() {
168
+ console.log("Node.js 环境演示");
169
+
170
+ // 检查是否支持 DOM
171
+ if (typeof document === "undefined") {
172
+ console.log("⚠️ 当前环境不支持 DOM,仅演示组件配置功能");
173
+ console.log("");
174
+
175
+ // 演示不同类型的按钮配置
176
+ const buttonConfigs = [
177
+ { text: "主要按钮", type: "primary", size: "medium" },
178
+ { text: "次要按钮", type: "secondary", size: "small" },
179
+ { text: "成功按钮", type: "success", size: "large" },
180
+ { text: "危险按钮", type: "danger", disabled: true },
181
+ { text: "警告按钮", type: "warning", loading: true },
182
+ ];
183
+
184
+ console.log("📝 按钮配置示例:");
185
+ buttonConfigs.forEach((config, index) => {
186
+ console.log(`按钮 ${index + 1}:`, config);
187
+ });
188
+
189
+ console.log("");
190
+ console.log("🔧 API 方法演示:");
191
+ console.log("- ZhlButton.create(options): 工厂方法创建按钮");
192
+ console.log("- button.setText(text): 更新按钮文本");
193
+ console.log("- button.setType(type): 更新按钮类型");
194
+ console.log("- button.setSize(size): 更新按钮尺寸");
195
+ console.log("- button.setDisabled(disabled): 设置禁用状态");
196
+ console.log("- button.setLoading(loading): 设置加载状态");
197
+ console.log("- button.destroy(): 销毁按钮实例");
198
+
199
+ console.log("");
200
+ console.log("📚 支持的按钮类型:");
201
+ const types = [
202
+ "primary",
203
+ "secondary",
204
+ "success",
205
+ "danger",
206
+ "warning",
207
+ "info",
208
+ "light",
209
+ "dark",
210
+ "outline",
211
+ ];
212
+ console.log(types.join(", "));
213
+
214
+ console.log("");
215
+ console.log("📏 支持的按钮尺寸:");
216
+ const sizes = ["small", "medium", "large"];
217
+ console.log(sizes.join(", "));
218
+
219
+ console.log("");
220
+ console.log("✅ 要在浏览器中查看完整演示,请打开 index.html 文件");
221
+
222
+ return;
223
+ }
224
+
225
+ // 如果支持 DOM,则执行浏览器演示
226
+ console.log("✅ 检测到 DOM 支持,启动浏览器演示...");
227
+ initDemo();
228
+ }
229
+
230
+ // 如果在浏览器环境中,自动执行演示
231
+ if (typeof window !== "undefined") {
232
+ window.demo = {
233
+ initDemo,
234
+ initNodeDemo,
235
+ updateStatus,
236
+ };
237
+ }
package/index.d.ts ADDED
@@ -0,0 +1,46 @@
1
+ // TypeScript 类型定义文件
2
+
3
+ export interface ZhlButtonOptions {
4
+ text?: string;
5
+ type?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'light' | 'dark' | 'outline';
6
+ size?: 'small' | 'medium' | 'large';
7
+ disabled?: boolean;
8
+ loading?: boolean;
9
+ onClick?: (event: Event) => void;
10
+ }
11
+
12
+ export class ZhlButton {
13
+ constructor(options?: ZhlButtonOptions);
14
+
15
+ text: string;
16
+ type: string;
17
+ size: string;
18
+ disabled: boolean;
19
+ loading: boolean;
20
+ element: HTMLElement | null;
21
+
22
+ render(target: HTMLElement | string): HTMLElement;
23
+ setText(text: string): void;
24
+ setType(type: string): void;
25
+ setSize(size: string): void;
26
+ setDisabled(disabled: boolean): void;
27
+ setLoading(loading: boolean): void;
28
+ destroy(): void;
29
+
30
+ static create(options?: ZhlButtonOptions): ZhlButton;
31
+ }
32
+
33
+ declare module 'zhl-button' {
34
+ import { DefineComponent } from 'vue';
35
+
36
+ export const ZhlButton: DefineComponent<ZhlButtonProps>;
37
+ export const ZhlButtonComponent: DefineComponent<ZhlButtonProps>;
38
+ }
39
+
40
+ export interface ZhlButtonProps {
41
+ text?: string;
42
+ type?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'light' | 'dark' | 'outline';
43
+ size?: 'small' | 'medium' | 'large';
44
+ disabled?: boolean;
45
+ loading?: boolean;
46
+ }
package/index.js ADDED
@@ -0,0 +1,114 @@
1
+ /**
2
+ * ZhlButton - 一个简单实用的JavaScript按钮组件
3
+ * 支持多种类型、尺寸和交互功能
4
+ */
5
+
6
+ class ZhlButton {
7
+ constructor(options = {}) {
8
+ this.text = options.text || "Button";
9
+ this.type = options.type || "primary";
10
+ this.size = options.size || "medium";
11
+ this.disabled = options.disabled || false;
12
+ this.onClick = options.onClick || null;
13
+ this.loading = options.loading || false;
14
+
15
+ this.element = null;
16
+ this.init();
17
+ }
18
+
19
+ init() {
20
+ this.element = document.createElement("button");
21
+ this.element.className = `zhl-btn zhl-btn-${this.type} zhl-btn-${this.size}`;
22
+ this.element.textContent = this.text;
23
+
24
+ if (this.disabled) {
25
+ this.element.disabled = true;
26
+ }
27
+
28
+ if (this.loading) {
29
+ this.element.classList.add("zhl-btn-loading");
30
+ }
31
+
32
+ if (this.onClick) {
33
+ this.element.addEventListener("click", this.onClick);
34
+ }
35
+ }
36
+
37
+ render(target) {
38
+ if (typeof target === "string") {
39
+ target = document.querySelector(target);
40
+ }
41
+
42
+ if (target) {
43
+ target.appendChild(this.element);
44
+ }
45
+
46
+ return this.element;
47
+ }
48
+
49
+ setText(text) {
50
+ this.text = text;
51
+ if (this.element) {
52
+ this.element.textContent = text;
53
+ }
54
+ }
55
+
56
+ setType(type) {
57
+ this.type = type;
58
+ if (this.element) {
59
+ this.element.className = `zhl-btn zhl-btn-${type} zhl-btn-${this.size}`;
60
+ if (this.loading) {
61
+ this.element.classList.add("zhl-btn-loading");
62
+ }
63
+ }
64
+ }
65
+
66
+ setSize(size) {
67
+ this.size = size;
68
+ if (this.element) {
69
+ this.element.className = `zhl-btn zhl-btn-${this.type} zhl-btn-${size}`;
70
+ if (this.loading) {
71
+ this.element.classList.add("zhl-btn-loading");
72
+ }
73
+ }
74
+ }
75
+
76
+ setDisabled(disabled) {
77
+ this.disabled = disabled;
78
+ if (this.element) {
79
+ this.element.disabled = disabled;
80
+ }
81
+ }
82
+
83
+ setLoading(loading) {
84
+ this.loading = loading;
85
+ if (this.element) {
86
+ if (loading) {
87
+ this.element.classList.add("zhl-btn-loading");
88
+ } else {
89
+ this.element.classList.remove("zhl-btn-loading");
90
+ }
91
+ }
92
+ }
93
+
94
+ destroy() {
95
+ if (this.element && this.element.parentNode) {
96
+ this.element.parentNode.removeChild(this.element);
97
+ }
98
+ }
99
+
100
+ // 静态工厂方法
101
+ static create(options) {
102
+ return new ZhlButton(options);
103
+ }
104
+ }
105
+
106
+ // 导出组件
107
+ if (typeof module !== "undefined" && module.exports) {
108
+ module.exports = ZhlButton;
109
+ } else if (typeof window !== "undefined") {
110
+ window.ZhlButton = ZhlButton;
111
+ }
112
+
113
+ // ES模块导出
114
+ export default ZhlButton;