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