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