@holyer-lib/ui 0.0.11 → 0.2.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/dist/ui.esm.js CHANGED
@@ -10,6 +10,527 @@ function __$styleInject(css) {
10
10
  return css;
11
11
  }
12
12
 
13
+ function __$styleInject$3(css) {
14
+ if (!css) return;
15
+
16
+ if (typeof window == 'undefined') return;
17
+ var style = document.createElement('style');
18
+ style.setAttribute('media', 'screen');
19
+
20
+ style.innerHTML = css;
21
+ document.head.appendChild(style);
22
+ return css;
23
+ }
24
+
25
+ __$styleInject$3(".hi-expand-panel {\n position: relative;\n display: flex;\n transition: flex 0.3s ease;\n}\n.hi-expand-panel:hover .hi-expand-panel--control-trigger {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.hi-expand-panel--content {\n height: 100%;\n width: 100%;\n overflow: auto;\n padding: 16px;\n box-sizing: border-box;\n}\n.hi-expand-panel--control-draggable:hover {\n cursor: var(--control-draggable-cursor);\n}\n.hi-expand-panel--control-dragging {\n background-color: var(--control-dragging-bg-color) !important;\n}\n.hi-expand-panel--right .hi-expand-panel--control,\n.hi-expand-panel--left .hi-expand-panel--control {\n position: absolute;\n height: 100%;\n width: 1px;\n background-color: var(--td-gray-color-4);\n}\n.hi-expand-panel--right .hi-expand-panel--control-trigger,\n.hi-expand-panel--left .hi-expand-panel--control-trigger {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n cursor: pointer;\n background-color: var(--td-font-white-1);\n border: 1px solid var(--td-gray-color-4);\n width: 12px;\n height: 56px;\n display: none;\n border-radius: 6px;\n}\n.hi-expand-panel--right {\n flex-direction: row;\n}\n.hi-expand-panel--right .hi-expand-panel--control {\n right: 0;\n}\n.hi-expand-panel--right .hi-expand-panel--control-trigger {\n right: -6px;\n}\n.hi-expand-panel--left {\n flex-direction: row-reverse;\n}\n.hi-expand-panel--left .hi-expand-panel--control {\n left: 0;\n}\n.hi-expand-panel--left .hi-expand-panel--control-trigger {\n left: -6px;\n}\n.hi-expand-panel--top .hi-expand-panel--control,\n.hi-expand-panel--bottom .hi-expand-panel--control {\n position: absolute;\n width: 100%;\n height: 1px;\n background-color: var(--td-gray-color-4);\n}\n.hi-expand-panel--top .hi-expand-panel--control-trigger,\n.hi-expand-panel--bottom .hi-expand-panel--control-trigger {\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n cursor: pointer;\n background-color: var(--td-font-white-1);\n border: 1px solid var(--td-gray-color-4);\n width: 56px;\n height: 12px;\n display: none;\n border-radius: 6px;\n}\n.hi-expand-panel--top {\n flex-direction: column-reverse;\n}\n.hi-expand-panel--top .hi-expand-panel--control {\n top: 0;\n}\n.hi-expand-panel--top .hi-expand-panel--control-trigger {\n top: -6px;\n}\n.hi-expand-panel--bottom {\n flex-direction: column;\n}\n.hi-expand-panel--bottom .hi-expand-panel--control {\n bottom: 0;\n}\n.hi-expand-panel--bottom .hi-expand-panel--control-trigger {\n bottom: -6px;\n}\n");
26
+
27
+ /**
28
+ * 类型判断工具
29
+ */
30
+
31
+ /**
32
+ * 将数值或字符串转换为合法的 CSS 长度值(用于 style 绑定)
33
+ * - 若为 number,自动追加 'px' 单位
34
+ * - 若为 string,原样返回(假定用户已提供合法 CSS 长度值)
35
+ * @param {number|string} value - 输入值(如 100, '100%', '50vh', 'auto')
36
+ * @returns {string} 合法的 CSS 长度字符串 默认值为 0
37
+ * @example
38
+ * formatSize(100) // '100px'
39
+ * formatSize('100%') // '100%'
40
+ * formatSize('50vh') // '50vh'
41
+ * formatSize(null) // 0
42
+ * formatSize(undefined) // 0
43
+ */
44
+ function formatSize$1(value) {
45
+ if (typeof value === 'number') {
46
+ return `${value}px`;
47
+ }
48
+ if (typeof value === 'string') {
49
+ if (value.trim() === '') {
50
+ return 0;
51
+ }
52
+ return value;
53
+ }
54
+ return 0;
55
+ }
56
+
57
+ //
58
+
59
+ const validateSize = val => {
60
+ if (typeof val === 'number') {
61
+ return val >= 0;
62
+ }
63
+ return true;
64
+ };
65
+
66
+ var script$3 = {
67
+ name: 'HiExpandPanel',
68
+ model: {
69
+ prop: 'expanded',
70
+ event: 'update:expanded'
71
+ },
72
+ props: {
73
+ // 支持受控和非受控两种模式
74
+ expanded: {
75
+ type: Boolean,
76
+ default: undefined
77
+ },
78
+
79
+ placement: {
80
+ type: String,
81
+ default: 'right',
82
+ validator: v => ['left', 'right', 'top', 'bottom'].includes(v)
83
+ },
84
+
85
+ size: {
86
+ type: [Number, String],
87
+ default: 280,
88
+ validator: validateSize
89
+ },
90
+
91
+ minSize: {
92
+ type: [Number, String],
93
+ default: 240,
94
+ validator: validateSize
95
+ },
96
+
97
+ maxSize: {
98
+ type: [Number, String],
99
+ default: 480,
100
+ validator: validateSize
101
+ },
102
+
103
+ collapsedSize: {
104
+ type: [String, Number],
105
+ default: 24,
106
+ validator: validateSize
107
+ },
108
+
109
+ draggable: {
110
+ type: Boolean,
111
+ default: true
112
+ },
113
+
114
+ showTrigger: {
115
+ type: Boolean,
116
+ default: true
117
+ },
118
+
119
+ cacheKey: {
120
+ type: String,
121
+ default: ''
122
+ },
123
+
124
+ cacheVersion: {
125
+ type: String,
126
+ default: ''
127
+ },
128
+
129
+ draggingBgColor: {
130
+ type: String,
131
+ default: 'var(--td-gray-color-6)'
132
+ }
133
+ },
134
+ data() {
135
+ let cachedData = {};
136
+ if (this.cacheKey) {
137
+ try {
138
+ const stored = localStorage.getItem(`${this.cacheKey}${this.cacheVersion}`);
139
+ if (stored) {
140
+ cachedData = JSON.parse(stored);
141
+ }
142
+ } catch (e) {
143
+ // eslint-disable-next-line no-console
144
+ console.warn(`HiExpandPanel: Failed to parse cache for key "${this.cacheKey}"`, e);
145
+ cachedData = {};
146
+ }
147
+ }
148
+
149
+ // 核心逻辑:有外部控制就用外部控制,否则用缓存
150
+ const useExternal = this.expanded !== undefined;
151
+ const initialExpanded = useExternal
152
+ ? this.expanded
153
+ : cachedData.cachedExpanded !== undefined
154
+ ? cachedData.cachedExpanded
155
+ : true;
156
+ const initialSize = useExternal
157
+ ? this.size
158
+ : cachedData.cachedSize !== undefined
159
+ ? cachedData.cachedSize
160
+ : this.size;
161
+
162
+ return {
163
+ innerExpanded: initialExpanded,
164
+ clientSize: initialSize,
165
+ isDragging: false,
166
+ startX: 0,
167
+ startY: 0,
168
+ startWidth: 0,
169
+ startHeight: 0,
170
+ hasExternalControl: useExternal
171
+ };
172
+ },
173
+ computed: {
174
+ isHorizontal() {
175
+ return ['left', 'right'].includes(this.placement);
176
+ },
177
+
178
+ // 根据展开状态和方向动态计算面板尺寸限制
179
+ getContainerStyles() {
180
+ // 如果未展开,直接返回空对象,不设置min/max尺寸
181
+ if (!this.innerExpanded) return {};
182
+ // 展开时根据方向设置对应的min/max尺寸
183
+ return this.isHorizontal
184
+ ? {
185
+ minWidth: formatSize$1(this.minSize),
186
+ maxWidth: formatSize$1(this.maxSize)
187
+ }
188
+ : {
189
+ minHeight: formatSize$1(this.minSize),
190
+ maxHeight: formatSize$1(this.maxSize)
191
+ };
192
+ },
193
+ panelStyle() {
194
+ const getWidth = () => {
195
+ if (this.isHorizontal) {
196
+ return this.innerExpanded ? formatSize$1(this.clientSize) : formatSize$1(this.collapsedSize) || 0;
197
+ }
198
+ return '100%';
199
+ };
200
+
201
+ const getHeight = () => {
202
+ if (this.isHorizontal) {
203
+ return '100%';
204
+ }
205
+ return this.innerExpanded ? formatSize$1(this.clientSize) : formatSize$1(this.collapsedSize) || 0;
206
+ };
207
+
208
+ return {
209
+ width: getWidth(),
210
+ height: getHeight(),
211
+ ...this.getContainerStyles,
212
+ transition: this.isDragging ? 'none' : 'flex 0.3s ease',
213
+ '--control-draggable-cursor': this.isHorizontal ? 'col-resize' : 'row-resize',
214
+ '--control-dragging-bg-color': this.draggingBgColor
215
+ };
216
+ }
217
+ },
218
+ watch: {
219
+ expanded(newVal) {
220
+ // 只有在组件是受控时才更新状态
221
+ if (this.hasExternalControl) {
222
+ if (newVal !== this.innerExpanded) {
223
+ this.innerExpanded = newVal;
224
+ }
225
+ }
226
+ },
227
+
228
+ innerExpanded(newVal) {
229
+ this.$emit('update:expanded', newVal);
230
+ this.$emit('expand-change', newVal);
231
+ if (this.cacheKey) {
232
+ this.handleSaveCache();
233
+ }
234
+ }
235
+ },
236
+ methods: {
237
+ handleToggle() {
238
+ this.innerExpanded = !this.innerExpanded;
239
+ },
240
+
241
+ handleSaveCache() {
242
+ if (this.cacheKey) {
243
+ localStorage.setItem(
244
+ `${this.cacheKey}${this.cacheVersion}`,
245
+ JSON.stringify({
246
+ cachedSize: this.clientSize,
247
+ cachedExpanded: this.innerExpanded
248
+ })
249
+ );
250
+ }
251
+ },
252
+
253
+ handleDragMousedown(e) {
254
+ if (!this.draggable) return;
255
+ e.preventDefault();
256
+ this.isDragging = true;
257
+ this.startX = e.clientX;
258
+ this.startY = e.clientY;
259
+
260
+ const panelRect = this.$refs.hiExpandPanelRef.getBoundingClientRect();
261
+ this.startWidth = panelRect.width;
262
+ this.startHeight = panelRect.height;
263
+
264
+ this.handleCreateMousemoveListener();
265
+ // 添加全局样式防止选中文本
266
+ document.body.style.userSelect = 'none';
267
+ },
268
+
269
+ // 核心逻辑:根据鼠标移动计算新的尺寸
270
+ handleDragMousemove(e) {
271
+ if (!this.isDragging) return;
272
+ // 只在需要阻止默认行为时调用 preventDefault
273
+ e.preventDefault();
274
+
275
+ let newSize;
276
+ if (this.isHorizontal) {
277
+ // 根据放置位置决定宽度变化的方向
278
+ const moveWidth = this.placement === 'left' ? this.startX - e.clientX : e.clientX - this.startX;
279
+ newSize = this.startWidth + moveWidth;
280
+ } else {
281
+ // 根据放置位置决定高度变化的方向
282
+ const moveHeight = this.placement === 'top' ? this.startY - e.clientY : e.clientY - this.startY;
283
+ newSize = this.startHeight + moveHeight;
284
+ }
285
+
286
+ // minSize 和 maxSize 已经限制了最大宽高,直接取 newSize 设置 clientSize 即可
287
+ this.clientSize = newSize;
288
+ },
289
+
290
+ // 鼠标松开结束拖动
291
+ handleDragMouseup() {
292
+ if (!this.isDragging) return;
293
+ this.isDragging = false;
294
+ this.handleSaveCache();
295
+ // 清理事件监听
296
+ this.handleClearMousemoveListener();
297
+ this.$emit('drag-end', {
298
+ size: this.clientSize,
299
+ expanded: this.innerExpanded
300
+ });
301
+
302
+ // 恢复全局样式
303
+ document.body.style.userSelect = '';
304
+ },
305
+
306
+ // 添加拖拽事件监听
307
+ handleCreateMousemoveListener() {
308
+ document.addEventListener('mousemove', this.handleDragMousemove);
309
+ document.addEventListener('mouseup', this.handleDragMouseup);
310
+ },
311
+
312
+ // 移除拖拽事件监听
313
+ handleClearMousemoveListener() {
314
+ document.removeEventListener('mousemove', this.handleDragMousemove);
315
+ document.removeEventListener('mouseup', this.handleDragMouseup);
316
+ }
317
+ }
318
+ };
319
+
320
+ function normalizeComponent$3(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) {
321
+ if (typeof shadowMode !== 'boolean') {
322
+ createInjectorSSR = createInjector;
323
+ createInjector = shadowMode;
324
+ shadowMode = false;
325
+ }
326
+ // Vue.extend constructor export interop.
327
+ const options = typeof script === 'function' ? script.options : script;
328
+ // render functions
329
+ if (template && template.render) {
330
+ options.render = template.render;
331
+ options.staticRenderFns = template.staticRenderFns;
332
+ options._compiled = true;
333
+ // functional template
334
+ if (isFunctionalTemplate) {
335
+ options.functional = true;
336
+ }
337
+ }
338
+ // scopedId
339
+ if (scopeId) {
340
+ options._scopeId = scopeId;
341
+ }
342
+ let hook;
343
+ if (moduleIdentifier) {
344
+ // server build
345
+ hook = function (context) {
346
+ // 2.3 injection
347
+ context =
348
+ context || // cached call
349
+ (this.$vnode && this.$vnode.ssrContext) || // stateful
350
+ (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional
351
+ // 2.2 with runInNewContext: true
352
+ if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
353
+ context = __VUE_SSR_CONTEXT__;
354
+ }
355
+ // inject component styles
356
+ if (style) {
357
+ style.call(this, createInjectorSSR(context));
358
+ }
359
+ // register component module identifier for async chunk inference
360
+ if (context && context._registeredComponents) {
361
+ context._registeredComponents.add(moduleIdentifier);
362
+ }
363
+ };
364
+ // used by ssr in case component is cached and beforeCreate
365
+ // never gets called
366
+ options._ssrRegister = hook;
367
+ }
368
+ else if (style) {
369
+ hook = shadowMode
370
+ ? function (context) {
371
+ style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot));
372
+ }
373
+ : function (context) {
374
+ style.call(this, createInjector(context));
375
+ };
376
+ }
377
+ if (hook) {
378
+ if (options.functional) {
379
+ // register for functional component in vue file
380
+ const originalRender = options.render;
381
+ options.render = function renderWithStyleInjection(h, context) {
382
+ hook.call(context);
383
+ return originalRender(h, context);
384
+ };
385
+ }
386
+ else {
387
+ // inject component registration as beforeCreate hook
388
+ const existing = options.beforeCreate;
389
+ options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
390
+ }
391
+ }
392
+ return script;
393
+ }
394
+
395
+ /* script */
396
+ const __vue_script__$3 = script$3;
397
+
398
+ /* template */
399
+ var __vue_render__$3 = function () {
400
+ var _vm = this;
401
+ var _h = _vm.$createElement;
402
+ var _c = _vm._self._c || _h;
403
+ return _c(
404
+ "div",
405
+ {
406
+ ref: "hiExpandPanelRef",
407
+ class: ["hi-expand-panel", "hi-expand-panel--" + _vm.placement],
408
+ style: _vm.panelStyle,
409
+ },
410
+ [
411
+ _c(
412
+ "div",
413
+ {
414
+ directives: [
415
+ {
416
+ name: "show",
417
+ rawName: "v-show",
418
+ value: _vm.innerExpanded,
419
+ expression: "innerExpanded",
420
+ },
421
+ ],
422
+ staticClass: "hi-expand-panel--content",
423
+ },
424
+ [_vm._t("default")],
425
+ 2
426
+ ),
427
+ _vm._v(" "),
428
+ _c(
429
+ "div",
430
+ {
431
+ class: [
432
+ "hi-expand-panel--control",
433
+ {
434
+ "hi-expand-panel--control-draggable":
435
+ _vm.draggable && _vm.innerExpanded,
436
+ "hi-expand-panel--control-dragging":
437
+ _vm.isDragging && _vm.innerExpanded,
438
+ },
439
+ ],
440
+ on: {
441
+ mousedown: _vm.handleDragMousedown,
442
+ mousemove: _vm.handleDragMousemove,
443
+ mouseup: _vm.handleDragMouseup,
444
+ },
445
+ },
446
+ [
447
+ _vm.$slots.trigger || _vm.showTrigger
448
+ ? _c(
449
+ "div",
450
+ {
451
+ staticClass: "hi-expand-panel--control-trigger",
452
+ on: {
453
+ click: function ($event) {
454
+ $event.stopPropagation();
455
+ return _vm.handleToggle.apply(null, arguments)
456
+ },
457
+ mousedown: function ($event) {
458
+ $event.stopPropagation();
459
+ },
460
+ },
461
+ },
462
+ [
463
+ _vm._t("trigger", function () {
464
+ return [
465
+ _vm.isHorizontal
466
+ ? [
467
+ _vm.placement === "right"
468
+ ? _c("span", [
469
+ _vm._v(_vm._s(_vm.innerExpanded ? "◂" : "▸")),
470
+ ])
471
+ : _c("span", [
472
+ _vm._v(_vm._s(_vm.innerExpanded ? "▸" : "◂")),
473
+ ]),
474
+ ]
475
+ : [
476
+ _vm.placement === "top"
477
+ ? _c("span", [
478
+ _vm._v(_vm._s(_vm.innerExpanded ? "▾" : "▴")),
479
+ ])
480
+ : _c("span", [
481
+ _vm._v(_vm._s(_vm.innerExpanded ? "▴" : "▾")),
482
+ ]),
483
+ ],
484
+ ]
485
+ }),
486
+ ],
487
+ 2
488
+ )
489
+ : _vm._e(),
490
+ ]
491
+ ),
492
+ ]
493
+ )
494
+ };
495
+ var __vue_staticRenderFns__$3 = [];
496
+ __vue_render__$3._withStripped = true;
497
+
498
+ /* style */
499
+ const __vue_inject_styles__$3 = undefined;
500
+ /* scoped */
501
+ const __vue_scope_id__$3 = undefined;
502
+ /* module identifier */
503
+ const __vue_module_identifier__$3 = undefined;
504
+ /* functional template */
505
+ const __vue_is_functional_template__$3 = false;
506
+ /* style inject */
507
+
508
+ /* style inject SSR */
509
+
510
+ /* style inject shadow dom */
511
+
512
+
513
+
514
+ const __vue_component__$3 = /*#__PURE__*/normalizeComponent$3(
515
+ { render: __vue_render__$3, staticRenderFns: __vue_staticRenderFns__$3 },
516
+ __vue_inject_styles__$3,
517
+ __vue_script__$3,
518
+ __vue_scope_id__$3,
519
+ __vue_is_functional_template__$3,
520
+ __vue_module_identifier__$3,
521
+ false,
522
+ undefined,
523
+ undefined,
524
+ undefined
525
+ );
526
+
527
+ __vue_component__$3.name = 'HiExpandPanel';
528
+
529
+ // 添加 install
530
+ __vue_component__$3.install = Vue => {
531
+ Vue.component(__vue_component__$3.name, __vue_component__$3);
532
+ };
533
+
13
534
  function __$styleInject$2(css) {
14
535
  if (!css) return;
15
536
 
@@ -1037,6 +1558,7 @@ __vue_component__.install = Vue => {
1037
1558
 
1038
1559
  // eslint-disable-next-line prettier/prettier
1039
1560
  const components = [
1561
+ __vue_component__$3,
1040
1562
  __vue_component__$2,
1041
1563
  __vue_component__$1,
1042
1564
  __vue_component__
@@ -1050,6 +1572,7 @@ const install = function (Vue) {
1050
1572
 
1051
1573
  var index = {
1052
1574
  install,
1575
+ HiExpandPanel: __vue_component__$3,
1053
1576
  HiExpandText: __vue_component__$2,
1054
1577
  HiTitle: __vue_component__$1,
1055
1578
  HiVirtualList: __vue_component__