jianghu-ui 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.
Files changed (112) hide show
  1. package/README.md +376 -0
  2. package/dist/jianghu-ui.css +2318 -0
  3. package/dist/jianghu-ui.js +2 -0
  4. package/dist/jianghu-ui.js.LICENSE.txt +1 -0
  5. package/package.json +56 -0
  6. package/src/Design.stories.mdx +195 -0
  7. package/src/Introduction.stories.mdx +148 -0
  8. package/src/components/JhAddressSelect/JhAddressSelect.md +250 -0
  9. package/src/components/JhAddressSelect/JhAddressSelect.stories.js +282 -0
  10. package/src/components/JhAddressSelect/JhAddressSelect.vue +261 -0
  11. package/src/components/JhCard/JhCard.md +246 -0
  12. package/src/components/JhCard/JhCard.stories.js +688 -0
  13. package/src/components/JhCard/JhCard.vue +604 -0
  14. package/src/components/JhCheckCard/JhCheckCard.md +245 -0
  15. package/src/components/JhCheckCard/JhCheckCard.stories.js +750 -0
  16. package/src/components/JhCheckCard/JhCheckCard.vue +476 -0
  17. package/src/components/JhConfirmDialog/JhConfirmDialog.md +70 -0
  18. package/src/components/JhConfirmDialog/JhConfirmDialog.stories.js +550 -0
  19. package/src/components/JhConfirmDialog/JhConfirmDialog.vue +181 -0
  20. package/src/components/JhDateRangePicker/JhDateRangePicker.md +56 -0
  21. package/src/components/JhDateRangePicker/JhDateRangePicker.stories.js +320 -0
  22. package/src/components/JhDateRangePicker/JhDateRangePicker.vue +307 -0
  23. package/src/components/JhDescriptions/JhDescriptions.md +724 -0
  24. package/src/components/JhDescriptions/JhDescriptions.stories.js +858 -0
  25. package/src/components/JhDescriptions/JhDescriptions.vue +933 -0
  26. package/src/components/JhDraggable/JhDraggable.md +66 -0
  27. package/src/components/JhDraggable/JhDraggable.stories.js +161 -0
  28. package/src/components/JhDraggable/JhDraggable.vue +254 -0
  29. package/src/components/JhDrawer/JhDrawer.md +68 -0
  30. package/src/components/JhDrawer/JhDrawer.stories.js +478 -0
  31. package/src/components/JhDrawer/JhDrawer.vue +281 -0
  32. package/src/components/JhDrawerForm/JhDrawerForm.md +69 -0
  33. package/src/components/JhDrawerForm/JhDrawerForm.stories.js +492 -0
  34. package/src/components/JhDrawerForm/JhDrawerForm.vue +297 -0
  35. package/src/components/JhEditableTable/JhEditableTable.md +507 -0
  36. package/src/components/JhEditableTable/JhEditableTable.stories.js +615 -0
  37. package/src/components/JhEditableTable/JhEditableTable.vue +685 -0
  38. package/src/components/JhFileInput/JhFileInput.md +56 -0
  39. package/src/components/JhFileInput/JhFileInput.stories.js +103 -0
  40. package/src/components/JhFileInput/JhFileInput.vue +253 -0
  41. package/src/components/JhForm/JhForm.md +676 -0
  42. package/src/components/JhForm/JhForm.stories.js +1375 -0
  43. package/src/components/JhForm/JhForm.vue +657 -0
  44. package/src/components/JhFormField/JhFormField.stories.js +217 -0
  45. package/src/components/JhFormField/JhFormField.vue +439 -0
  46. package/src/components/JhFormFields/JhFormFields.md +647 -0
  47. package/src/components/JhFormFields/JhFormFields.stories.js +922 -0
  48. package/src/components/JhFormFields/JhFormFields.vue +998 -0
  49. package/src/components/JhFormList/JhFormList.md +303 -0
  50. package/src/components/JhFormList/JhFormList.stories.js +661 -0
  51. package/src/components/JhFormList/JhFormList.vue +1127 -0
  52. package/src/components/JhJsonEditor/JhJsonEditor.md +54 -0
  53. package/src/components/JhJsonEditor/JhJsonEditor.stories.js +157 -0
  54. package/src/components/JhJsonEditor/JhJsonEditor.vue +178 -0
  55. package/src/components/JhLayout/JhLayout.md +580 -0
  56. package/src/components/JhLayout/JhLayout.stories.js +414 -0
  57. package/src/components/JhLayout/JhLayout.vue +387 -0
  58. package/src/components/JhList/JhList.md +441 -0
  59. package/src/components/JhList/JhList.stories.js +524 -0
  60. package/src/components/JhList/JhList.vue +571 -0
  61. package/src/components/JhMarkdownEditor/JhMarkdownEditor.md +56 -0
  62. package/src/components/JhMarkdownEditor/JhMarkdownEditor.stories.js +191 -0
  63. package/src/components/JhMarkdownEditor/JhMarkdownEditor.vue +188 -0
  64. package/src/components/JhMask/JhMask.md +62 -0
  65. package/src/components/JhMask/JhMask.stories.js +270 -0
  66. package/src/components/JhMask/JhMask.vue +123 -0
  67. package/src/components/JhMenu/JhMenu.md +85 -0
  68. package/src/components/JhMenu/JhMenu.stories.js +384 -0
  69. package/src/components/JhMenu/JhMenu.vue +545 -0
  70. package/src/components/JhModal/JhModal.md +68 -0
  71. package/src/components/JhModal/JhModal.stories.js +562 -0
  72. package/src/components/JhModal/JhModal.vue +235 -0
  73. package/src/components/JhModalForm/JhModalForm.md +69 -0
  74. package/src/components/JhModalForm/JhModalForm.stories.js +592 -0
  75. package/src/components/JhModalForm/JhModalForm.vue +298 -0
  76. package/src/components/JhPageContainer/JhPageContainer.md +409 -0
  77. package/src/components/JhPageContainer/JhPageContainer.stories.js +209 -0
  78. package/src/components/JhPageContainer/JhPageContainer.vue +72 -0
  79. package/src/components/JhQueryFilter/JhQueryFilter.md +77 -0
  80. package/src/components/JhQueryFilter/JhQueryFilter.stories.js +684 -0
  81. package/src/components/JhQueryFilter/JhQueryFilter.vue +429 -0
  82. package/src/components/JhScene/JhScene.md +64 -0
  83. package/src/components/JhScene/JhScene.stories.js +317 -0
  84. package/src/components/JhScene/JhScene.vue +376 -0
  85. package/src/components/JhStatisticCard/JhStatisticCard.md +363 -0
  86. package/src/components/JhStatisticCard/JhStatisticCard.stories.js +847 -0
  87. package/src/components/JhStatisticCard/JhStatisticCard.vue +459 -0
  88. package/src/components/JhStepsForm/JhStepsForm.md +666 -0
  89. package/src/components/JhStepsForm/JhStepsForm.stories.js +1224 -0
  90. package/src/components/JhStepsForm/JhStepsForm.vue +749 -0
  91. package/src/components/JhTable/JhTable.md +730 -0
  92. package/src/components/JhTable/JhTable.stories.js +1444 -0
  93. package/src/components/JhTable/JhTable.vue +2298 -0
  94. package/src/components/JhTableAttachment/JhTableAttachment.md +70 -0
  95. package/src/components/JhTableAttachment/JhTableAttachment.stories.js +198 -0
  96. package/src/components/JhTableAttachment/JhTableAttachment.vue +264 -0
  97. package/src/components/JhToast/JhToast.md +67 -0
  98. package/src/components/JhToast/JhToast.stories.js +386 -0
  99. package/src/components/JhToast/JhToast.vue +239 -0
  100. package/src/components/JhTreeSelect/JhTreeSelect.md +82 -0
  101. package/src/components/JhTreeSelect/JhTreeSelect.stories.js +391 -0
  102. package/src/components/JhTreeSelect/JhTreeSelect.vue +727 -0
  103. package/src/components/JhWaterMark/JhWaterMark.md +190 -0
  104. package/src/components/JhWaterMark/JhWaterMark.stories.js +675 -0
  105. package/src/components/JhWaterMark/JhWaterMark.vue +351 -0
  106. package/src/components/README.md +52 -0
  107. package/src/index.js +135 -0
  108. package/src/style/globalCSSJHV4.css +348 -0
  109. package/src/style/globalCSSVuetifyV4.css +637 -0
  110. package/src/style/storybook.css +4 -0
  111. package/src/tailwind.css +3 -0
  112. package/src/utils/vuetify.js +31 -0
@@ -0,0 +1,351 @@
1
+ <template>
2
+ <div class="jh-watermark" :style="containerStyle">
3
+ <slot></slot>
4
+ </div>
5
+ </template>
6
+
7
+ <script>
8
+ export default {
9
+ name: 'JhWaterMark',
10
+
11
+ props: {
12
+ // 水印文字内容(支持字符串数组实现多行文本)
13
+ content: {
14
+ type: [String, Array],
15
+ default: '',
16
+ },
17
+
18
+ // 图片源,建议导出 2 倍或 3 倍图,优先级高于文字
19
+ image: {
20
+ type: String,
21
+ default: '',
22
+ },
23
+
24
+ // 水印整体宽度
25
+ width: {
26
+ type: Number,
27
+ default: 120,
28
+ },
29
+
30
+ // 水印整体高度
31
+ height: {
32
+ type: Number,
33
+ default: 64,
34
+ },
35
+
36
+ // 水印旋转角度
37
+ rotate: {
38
+ type: Number,
39
+ default: -22,
40
+ },
41
+
42
+ // 水印之间的水平间距
43
+ gapX: {
44
+ type: Number,
45
+ default: 212,
46
+ },
47
+
48
+ // 水印之间的垂直间距
49
+ gapY: {
50
+ type: Number,
51
+ default: 222,
52
+ },
53
+
54
+ // 水印在 canvas 画布上绘制的水平偏移量,正常情况下,水印绘制在中间位置,即 offsetX = gapX / 2
55
+ offsetX: {
56
+ type: Number,
57
+ default: undefined,
58
+ },
59
+
60
+ // 水印在 canvas 画布上绘制的垂直偏移量,正常情况下,水印绘制在中间位置,即 offsetY = gapY / 2
61
+ offsetY: {
62
+ type: Number,
63
+ default: undefined,
64
+ },
65
+
66
+ // 字体配置
67
+ font: {
68
+ type: Object,
69
+ default: () => ({}),
70
+ },
71
+
72
+ // 水印层的 z-index
73
+ zIndex: {
74
+ type: Number,
75
+ default: 9,
76
+ },
77
+
78
+ // 追加的水印元素的根节点
79
+ getContainer: {
80
+ type: Function,
81
+ default: undefined,
82
+ },
83
+ },
84
+
85
+ data() {
86
+ return {
87
+ watermarkUrl: '',
88
+ observer: null,
89
+ };
90
+ },
91
+
92
+ computed: {
93
+ containerStyle() {
94
+ return {
95
+ position: 'relative',
96
+ };
97
+ },
98
+
99
+ // 合并字体配置
100
+ mergedFont() {
101
+ return {
102
+ color: 'rgba(0, 0, 0, 0.15)',
103
+ fontSize: 16,
104
+ fontWeight: 'normal',
105
+ fontFamily: 'sans-serif',
106
+ fontStyle: 'normal',
107
+ textAlign: 'center',
108
+ ...this.font,
109
+ };
110
+ },
111
+
112
+ // 计算实际偏移量
113
+ actualOffsetX() {
114
+ return this.offsetX !== undefined ? this.offsetX : this.gapX / 2;
115
+ },
116
+
117
+ actualOffsetY() {
118
+ return this.offsetY !== undefined ? this.offsetY : this.gapY / 2;
119
+ },
120
+ },
121
+
122
+ watch: {
123
+ content: {
124
+ handler() {
125
+ this.renderWatermark();
126
+ },
127
+ deep: true,
128
+ },
129
+ image() {
130
+ this.renderWatermark();
131
+ },
132
+ width() {
133
+ this.renderWatermark();
134
+ },
135
+ height() {
136
+ this.renderWatermark();
137
+ },
138
+ rotate() {
139
+ this.renderWatermark();
140
+ },
141
+ gapX() {
142
+ this.renderWatermark();
143
+ },
144
+ gapY() {
145
+ this.renderWatermark();
146
+ },
147
+ offsetX() {
148
+ this.renderWatermark();
149
+ },
150
+ offsetY() {
151
+ this.renderWatermark();
152
+ },
153
+ font: {
154
+ handler() {
155
+ this.renderWatermark();
156
+ },
157
+ deep: true,
158
+ },
159
+ },
160
+
161
+ mounted() {
162
+ this.renderWatermark();
163
+ this.observeWatermark();
164
+ },
165
+
166
+ beforeDestroy() {
167
+ this.destroyWatermark();
168
+ if (this.observer) {
169
+ this.observer.disconnect();
170
+ }
171
+ },
172
+
173
+ methods: {
174
+ // 生成水印
175
+ async renderWatermark() {
176
+ const canvas = document.createElement('canvas');
177
+ const ctx = canvas.getContext('2d');
178
+
179
+ const canvasWidth = (this.width + this.gapX) * 2;
180
+ const canvasHeight = (this.height + this.gapY) * 2;
181
+
182
+ canvas.width = canvasWidth;
183
+ canvas.height = canvasHeight;
184
+
185
+ if (this.image) {
186
+ // 使用图片水印
187
+ await this.drawImageWatermark(ctx, canvasWidth, canvasHeight);
188
+ } else if (this.content) {
189
+ // 使用文字水印
190
+ this.drawTextWatermark(ctx, canvasWidth, canvasHeight);
191
+ }
192
+
193
+ this.watermarkUrl = canvas.toDataURL();
194
+ this.updateWatermarkElement();
195
+ },
196
+
197
+ // 绘制图片水印
198
+ drawImageWatermark(ctx, canvasWidth, canvasHeight) {
199
+ return new Promise((resolve, reject) => {
200
+ const img = new Image();
201
+ img.crossOrigin = 'anonymous';
202
+ img.referrerPolicy = 'no-referrer';
203
+
204
+ img.onload = () => {
205
+ ctx.save();
206
+
207
+ // 计算中心点
208
+ const centerX = canvasWidth / 2;
209
+ const centerY = canvasHeight / 2;
210
+
211
+ // 移动到中心点并旋转
212
+ ctx.translate(centerX, centerY);
213
+ ctx.rotate((Math.PI / 180) * this.rotate);
214
+
215
+ // 绘制图片(以中心点为基准)
216
+ ctx.drawImage(
217
+ img,
218
+ -this.width / 2,
219
+ -this.height / 2,
220
+ this.width,
221
+ this.height
222
+ );
223
+
224
+ ctx.restore();
225
+ resolve();
226
+ };
227
+
228
+ img.onerror = () => {
229
+ console.error('Watermark image load failed');
230
+ reject();
231
+ };
232
+
233
+ img.src = this.image;
234
+ });
235
+ },
236
+
237
+ // 绘制文字水印
238
+ drawTextWatermark(ctx, canvasWidth, canvasHeight) {
239
+ const { color, fontSize, fontWeight, fontFamily, fontStyle, textAlign } = this.mergedFont;
240
+
241
+ ctx.save();
242
+
243
+ // 设置字体样式
244
+ ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;
245
+ ctx.fillStyle = color;
246
+ ctx.textAlign = textAlign;
247
+ ctx.textBaseline = 'middle';
248
+
249
+ // 计算中心点
250
+ const centerX = canvasWidth / 2;
251
+ const centerY = canvasHeight / 2;
252
+
253
+ // 移动到中心点并旋转
254
+ ctx.translate(centerX, centerY);
255
+ ctx.rotate((Math.PI / 180) * this.rotate);
256
+
257
+ // 处理多行文本
258
+ const contents = Array.isArray(this.content) ? this.content : [this.content];
259
+ const lineHeight = fontSize * 1.5;
260
+ const totalHeight = contents.length * lineHeight;
261
+ const startY = -totalHeight / 2 + lineHeight / 2;
262
+
263
+ // 绘制每一行文字
264
+ contents.forEach((text, index) => {
265
+ const y = startY + index * lineHeight;
266
+ ctx.fillText(text, 0, y);
267
+ });
268
+
269
+ ctx.restore();
270
+ },
271
+
272
+ // 更新水印元素
273
+ updateWatermarkElement() {
274
+ this.destroyWatermark();
275
+
276
+ const container = this.getContainer ? this.getContainer() : this.$el;
277
+ if (!container) return;
278
+
279
+ const watermarkDiv = document.createElement('div');
280
+ watermarkDiv.className = 'jh-watermark-layer';
281
+ watermarkDiv.style.cssText = `
282
+ position: absolute;
283
+ left: 0;
284
+ right: 0;
285
+ top: 0;
286
+ bottom: 0;
287
+ pointer-events: none;
288
+ z-index: ${this.zIndex};
289
+ background-image: url(${this.watermarkUrl});
290
+ background-repeat: repeat;
291
+ background-position: ${this.actualOffsetX}px ${this.actualOffsetY}px;
292
+ overflow: hidden;
293
+ `;
294
+
295
+ watermarkDiv.setAttribute('data-watermark', 'true');
296
+ container.appendChild(watermarkDiv);
297
+ this.watermarkElement = watermarkDiv;
298
+ },
299
+
300
+ // 销毁水印元素
301
+ destroyWatermark() {
302
+ if (this.watermarkElement && this.watermarkElement.parentNode) {
303
+ this.watermarkElement.parentNode.removeChild(this.watermarkElement);
304
+ this.watermarkElement = null;
305
+ }
306
+ },
307
+
308
+ // 监听水印元素变化,防止被删除或修改
309
+ observeWatermark() {
310
+ if (!window.MutationObserver) return;
311
+
312
+ this.observer = new MutationObserver((mutations) => {
313
+ mutations.forEach((mutation) => {
314
+ if (mutation.type === 'childList') {
315
+ const removed = Array.from(mutation.removedNodes).some(
316
+ (node) => node === this.watermarkElement
317
+ );
318
+ if (removed) {
319
+ this.updateWatermarkElement();
320
+ }
321
+ } else if (mutation.type === 'attributes') {
322
+ if (mutation.target === this.watermarkElement) {
323
+ this.updateWatermarkElement();
324
+ }
325
+ }
326
+ });
327
+ });
328
+
329
+ this.observer.observe(this.$el, {
330
+ childList: true,
331
+ attributes: true,
332
+ subtree: true,
333
+ });
334
+ },
335
+ },
336
+ };
337
+ </script>
338
+
339
+ <style scoped>
340
+ .jh-watermark {
341
+ position: relative;
342
+ min-height: 100%;
343
+ }
344
+
345
+ .jh-watermark-layer {
346
+ position: absolute;
347
+ inset: 0;
348
+ pointer-events: none;
349
+ background-repeat: repeat;
350
+ }
351
+ </style>
@@ -0,0 +1,52 @@
1
+ # JianghuJS UI 组件
2
+
3
+ 这里包含所有的 UI 组件。每个组件都有自己的文件夹,包含:
4
+ - `.vue` 文件:组件实现
5
+ - `.stories.js` 文件:Storybook 故事
6
+ - `.md` 文件:组件文档(可选)
7
+
8
+ ## 组件列表
9
+
10
+ ### 布局组件
11
+ - **JhLayout**: 页面布局组件 - 基于 Ant Design Pro 的 ProLayout,提供侧边、顶部、混合三种布局模式
12
+ - **JhPageContainer**: 页面容器组件 - 提供统一的页面头部和内容区域
13
+ - **JhMenu**: 菜单组件 - 支持多级菜单和响应式设计
14
+ - **JhCard**: 高级卡片组件 - 参考 Ant Design ProCard,支持标题、分栏、栅格、标签页等多种布局功能
15
+
16
+ ### 基础组件
17
+ - **JhButton**: 按钮组件
18
+
19
+ ### 数据展示
20
+ - **JhTable**: 表格组件
21
+ - **JhEditableTable**: 可编辑表格组件
22
+ - **JhTableAttachment**: 附件表格组件
23
+ - **JhDescriptions**: 描述列表组件 - 基于 Ant Design ProDescriptions,支持水平/垂直布局、可编辑、多种 ValueType
24
+ - **JhList**: 列表组件
25
+ - **JhStatisticCard**: 统计卡片组件
26
+ - **JhCheckCard**: 多选卡片组件
27
+ - **JhWaterMark**: 水印组件
28
+
29
+ ### 表单组件
30
+ - **JhForm**: 表单组件
31
+ - **JhFormFields**: 表单字段集组件 - 基于 Ant Design ProComponents FieldSet,支持字段依赖和动态联动
32
+ - **JhFormList**: 表单列表组件
33
+ - **JhQueryFilter**: 查询过滤组件
34
+ - **JhStepsForm**: 分步表单组件
35
+ - **JhFileInput**: 文件上传组件
36
+ - **JhDateRangePicker**: 日期范围选择器
37
+ - **JhTreeSelect**: 树形选择器
38
+ - **JhJsonEditor**: JSON 编辑器
39
+ - **JhMarkdownEditor**: Markdown 编辑器
40
+
41
+ ### 反馈组件
42
+ - **JhModal**: 模态框组件
43
+ - **JhModalForm**: 模态框表单组件
44
+ - **JhDrawer**: 抽屉组件
45
+ - **JhDrawerForm**: 抽屉表单组件
46
+ - **JhToast**: 提示组件
47
+ - **JhMask**: 遮罩组件
48
+ - **JhConfirmDialog**: 确认对话框组件
49
+
50
+ ### 其他组件
51
+ - **JhDraggable**: 拖拽组件
52
+ - **JhScene**: 场景组件
package/src/index.js ADDED
@@ -0,0 +1,135 @@
1
+ // JianghuJS UI Component Library Entry Point
2
+
3
+ // Import global styles
4
+ import './style/storybook.css';
5
+ import './style/globalCSSVuetifyV4.css';
6
+ import './style/globalCSSJHV4.css';
7
+
8
+ // Basic Components
9
+ import JhMenu from './components/JhMenu/JhMenu.vue';
10
+ import JhScene from './components/JhScene/JhScene.vue';
11
+ import JhDateRangePicker from './components/JhDateRangePicker/JhDateRangePicker.vue';
12
+ import JhQueryFilter from './components/JhQueryFilter/JhQueryFilter.vue';
13
+ import JhTable from './components/JhTable/JhTable.vue';
14
+ import JhTreeSelect from './components/JhTreeSelect/JhTreeSelect.vue';
15
+ import JhAddressSelect from './components/JhAddressSelect/JhAddressSelect.vue';
16
+
17
+ // Layout Components
18
+ import JhPageContainer from './components/JhPageContainer/JhPageContainer.vue';
19
+ import JhLayout from './components/JhLayout/JhLayout.vue';
20
+ import JhCard from './components/JhCard/JhCard.vue';
21
+ import JhStatisticCard from './components/JhStatisticCard/JhStatisticCard.vue';
22
+ import JhWaterMark from './components/JhWaterMark/JhWaterMark.vue';
23
+
24
+ // Feedback Components
25
+ import JhMask from './components/JhMask/JhMask.vue';
26
+ import JhToast from './components/JhToast/JhToast.vue';
27
+ import JhConfirmDialog from './components/JhConfirmDialog/JhConfirmDialog.vue';
28
+
29
+ // Pro Components
30
+ import JhForm from './components/JhForm/JhForm.vue';
31
+ import JhModalForm from './components/JhModalForm/JhModalForm.vue';
32
+ import JhDrawerForm from './components/JhDrawerForm/JhDrawerForm.vue';
33
+ import JhModal from './components/JhModal/JhModal.vue';
34
+ import JhDrawer from './components/JhDrawer/JhDrawer.vue';
35
+ import JhStepsForm from './components/JhStepsForm/JhStepsForm.vue';
36
+ import JhFormList from './components/JhFormList/JhFormList.vue';
37
+
38
+ // Advanced Components
39
+ import JhFileInput from './components/JhFileInput/JhFileInput.vue';
40
+ import JhJsonEditor from './components/JhJsonEditor/JhJsonEditor.vue';
41
+ import JhMarkdownEditor from './components/JhMarkdownEditor/JhMarkdownEditor.vue';
42
+ import JhDraggable from './components/JhDraggable/JhDraggable.vue';
43
+ import JhTableAttachment from './components/JhTableAttachment/JhTableAttachment.vue';
44
+ import JhEditableTable from './components/JhEditableTable/JhEditableTable.vue';
45
+
46
+ const components = {
47
+ JhMenu,
48
+ JhScene,
49
+ JhDateRangePicker,
50
+ JhQueryFilter,
51
+ JhTable,
52
+ JhTreeSelect,
53
+ JhAddressSelect,
54
+ // Layout Components
55
+ JhPageContainer,
56
+ JhLayout,
57
+ JhCard,
58
+ JhStatisticCard,
59
+ JhWaterMark,
60
+
61
+ // Pro Components
62
+ JhForm,
63
+ JhModalForm,
64
+ JhDrawerForm,
65
+ JhModal,
66
+ JhDrawer,
67
+ JhStepsForm,
68
+ JhFormList,
69
+ // Advanced Components
70
+ JhFileInput,
71
+ JhJsonEditor,
72
+ JhMarkdownEditor,
73
+ JhDraggable,
74
+ JhTableAttachment,
75
+ JhEditableTable,
76
+
77
+ // Feedback Components
78
+ JhMask,
79
+ JhToast,
80
+ JhConfirmDialog,
81
+ };
82
+
83
+ // Vue plugin install function
84
+ const install = (Vue) => {
85
+ if (install.installed) return;
86
+ install.installed = true;
87
+
88
+ Object.keys(components).forEach((key) => {
89
+ Vue.component(key, components[key]);
90
+ });
91
+ };
92
+
93
+ // Auto-install when Vue is found (browser)
94
+ if (typeof window !== 'undefined' && window.Vue) {
95
+ install(window.Vue);
96
+ }
97
+
98
+ export default {
99
+ install,
100
+ ...components,
101
+ };
102
+
103
+ export {
104
+ // Basic Components
105
+ JhMenu,
106
+ JhScene,
107
+ JhDateRangePicker,
108
+ JhQueryFilter,
109
+ JhTable,
110
+ JhTreeSelect,
111
+ // Layout Components
112
+ JhPageContainer,
113
+ JhCard,
114
+
115
+ // Pro Components
116
+ JhForm,
117
+ JhModalForm,
118
+ JhDrawerForm,
119
+ JhModal,
120
+ JhDrawer,
121
+ JhStepsForm,
122
+ JhFormList,
123
+ // Advanced Components
124
+ JhFileInput,
125
+ JhJsonEditor,
126
+ JhMarkdownEditor,
127
+ JhDraggable,
128
+ JhTableAttachment,
129
+ JhEditableTable,
130
+
131
+ // Feedback Components
132
+ JhMask,
133
+ JhToast,
134
+ JhConfirmDialog,
135
+ };