@shijiu/jsview-vue 2.0.1021 → 2.0.1073

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 (33) hide show
  1. package/package.json +4 -3
  2. package/utils/JsViewEngineWidget/CheckType.js +82 -0
  3. package/utils/JsViewEngineWidget/MetroWidget/AnimationManager.ts +72 -0
  4. package/utils/JsViewEngineWidget/MetroWidget/Const.ts +24 -0
  5. package/utils/JsViewEngineWidget/MetroWidget/ListWidget.vue +295 -0
  6. package/utils/JsViewEngineWidget/MetroWidget/MetroWidget.vue +110 -1651
  7. package/utils/JsViewEngineWidget/MetroWidget/MetroWidgetSetup.js +1867 -0
  8. package/utils/JsViewEngineWidget/MetroWidget/PageUpdater.ts +111 -0
  9. package/utils/JsViewEngineWidget/MetroWidget/RenderItem.ts +153 -0
  10. package/utils/JsViewEngineWidget/MetroWidget/VisibleInfo.ts +43 -0
  11. package/utils/JsViewEngineWidget/MetroWidget/WidgetRectInfo.ts +49 -0
  12. package/utils/JsViewEngineWidget/TemplateParser/CommonMetroTemplate.ts +1424 -0
  13. package/utils/JsViewEngineWidget/TemplateParser/Fence.ts +135 -0
  14. package/utils/JsViewEngineWidget/TemplateParser/ListMetroTemplate.ts +177 -0
  15. package/utils/JsViewEngineWidget/TemplateParser/MetroTemplate.ts +334 -0
  16. package/utils/JsViewEngineWidget/TemplateParser/TemplateItemAdder.ts +147 -0
  17. package/utils/JsViewEngineWidget/TemplateParser/index.ts +4 -0
  18. package/utils/JsViewEngineWidget/{WidgetCommon.js → WidgetCommon.ts} +64 -71
  19. package/utils/JsViewEngineWidget/index.js +2 -1
  20. package/utils/JsViewPlugin/JsvAudio/AudioProxy.js +26 -1
  21. package/utils/JsViewPlugin/JsvAudio/JsvAudio.vue +120 -133
  22. package/utils/JsViewPlugin/JsvAudio/JsvAudioBrowser.vue +11 -7
  23. package/utils/JsViewPlugin/JsvPlayer/GetVersion.js +1 -1
  24. package/utils/JsViewPlugin/JsvPlayer/JsvPlayerBrowser.vue +379 -41
  25. package/utils/JsViewPlugin/JsvPlayer/version.mjs +5 -5
  26. package/utils/JsViewVueTools/JsvHashHistory.js +2 -1
  27. package/utils/JsViewVueWidget/JsvRadarChart.vue +220 -0
  28. package/utils/JsViewVueWidget/JsvSystemAudio.vue +76 -44
  29. package/utils/JsViewVueWidget/index.js +1 -0
  30. package/utils/JsViewEngineWidget/MetroWidget/Const.js +0 -11
  31. package/utils/JsViewEngineWidget/MetroWidget/PageUpdater.js +0 -136
  32. package/utils/JsViewEngineWidget/MetroWidget/ToolFunctions.js +0 -18
  33. package/utils/JsViewEngineWidget/TemplateParser.js +0 -2004
@@ -0,0 +1,1867 @@
1
+ import {
2
+ reactive,
3
+ onMounted,
4
+ onBeforeUnmount,
5
+ onUpdated,
6
+ toRaw,
7
+ nextTick,
8
+ } from "vue";
9
+ import { Forge } from "@shijiu/jsview/dom/jsv-forge-define";
10
+ import {
11
+ CommonMetroTemplate,
12
+ ListMetroTemplate,
13
+ TemplateItemAdder,
14
+ } from "../TemplateParser/index";
15
+ import { PageUpdater } from "./PageUpdater";
16
+ import { SingleRangeModel } from "../RangeModel";
17
+ import { METRO_WIDGET_CONST } from "./Const";
18
+ import {
19
+ EdgeDirection,
20
+ VERTICAL,
21
+ HORIZONTAL,
22
+ SlideSetting,
23
+ } from "../WidgetCommon";
24
+ import { RenderItem } from "./RenderItem";
25
+ import { VisibleInfo } from "./VisibleInfo";
26
+ import { AnimationManager, AnimationTools } from "./AnimationManager";
27
+ import { WidgetRectInfo } from "./WidgetRectInfo";
28
+ import { checkType } from "../CheckType";
29
+
30
+ const TAG = "MetroWidget";
31
+
32
+ const _getMetroTemplate = function (
33
+ widgetRectInfo,
34
+ direction,
35
+ support_history_path,
36
+ layout_type,
37
+ mode
38
+ ) {
39
+ let page_size;
40
+ let line_max;
41
+ if (direction === VERTICAL) {
42
+ line_max = widgetRectInfo.contentWidth;
43
+ page_size = widgetRectInfo.contentHeight;
44
+ } else {
45
+ line_max = widgetRectInfo.contentHeight;
46
+ page_size = widgetRectInfo.contentWidth;
47
+ }
48
+ let metroWidget;
49
+ switch (mode) {
50
+ case "list":
51
+ metroWidget = new ListMetroTemplate(
52
+ direction,
53
+ line_max,
54
+ page_size,
55
+ layout_type,
56
+ support_history_path
57
+ );
58
+ break;
59
+ default:
60
+ metroWidget = new CommonMetroTemplate(
61
+ direction,
62
+ line_max,
63
+ page_size,
64
+ layout_type,
65
+ support_history_path
66
+ );
67
+ break;
68
+ }
69
+ return metroWidget;
70
+ };
71
+
72
+ export const setup = (
73
+ props,
74
+ touchContainerW,
75
+ touchContainerH,
76
+ itemRender,
77
+ locateDiv,
78
+ renderData,
79
+ slideDiv,
80
+ slideDivLeft,
81
+ slideDivTop,
82
+ itemResizeSlideDiv,
83
+ itemResizeSlideLeft,
84
+ itemResizeSlideTop,
85
+ focusNode,
86
+ pageUpdateToken,
87
+ templateMode) => {
88
+ let widgetRectInfo = new WidgetRectInfo(props.width, props.height, props.padding);
89
+ let metroTemplate = _getMetroTemplate(
90
+ widgetRectInfo,
91
+ props.direction,
92
+ props.supportHistoryPath,
93
+ props.layoutType,
94
+ templateMode
95
+ );
96
+ let innerData = [];
97
+ let dataList = [];
98
+ let pageUpdater = null;
99
+ let enterFocusId = -1;
100
+ let enterFocusRect = null;
101
+ let focusId = 0;
102
+ let preFocusId = -1;
103
+ let preEdgeRect = null;
104
+ let isFocus = false;
105
+ let touchListener = null;
106
+ let slidePile = null;
107
+ let dragDirection = Forge.DragSetting.DIRECTION_HORIZONTAL;
108
+ let vertical = props.direction == VERTICAL;
109
+ let preAnchorItemIndex = -1;
110
+ let preSeamlessSlideDirection = 1;
111
+ let templateItemAdder = null;
112
+ let permanentItemList = [];
113
+ let preUpdateVisibleStart = 0;
114
+ let mounted = false;
115
+ let pageRange = vertical ? props.height : props.width;
116
+ let slideLock = false;
117
+ let childSlideEventLock = false;
118
+ let onKeyDownLock = false;
119
+ let visibleInfo = new VisibleInfo();
120
+
121
+ const DEFAULT_ANIMATION_DURATION = 200;
122
+ const animationManager = new AnimationManager();
123
+
124
+ const updateDivPosition =
125
+ (divRef, leftRef, topRef, onStart, onEnd) => (x, y, animInfo) => {
126
+ if (toRaw(divRef.value)) {
127
+ const pre_left = leftRef.value;
128
+ const pre_top = topRef.value;
129
+ leftRef.value = x;
130
+ topRef.value = y;
131
+
132
+ if (animInfo) {
133
+ let startCallback = () => {
134
+ onStart?.();
135
+ animInfo?.onStart?.();
136
+ };
137
+ let endCallback = (animDone) => {
138
+ onEnd?.(animDone);
139
+ animInfo?.onEnd?.(animDone);
140
+ };
141
+
142
+ const delta_x = Math.round(pre_left - x);
143
+ const delta_y = Math.round(pre_top - y);
144
+
145
+ const animNode = AnimationTools.getDivSlideAnim(
146
+ toRaw(divRef.value),
147
+ delta_x,
148
+ delta_y,
149
+ 0,
150
+ 0,
151
+ {
152
+ easing: animInfo.easing,
153
+ duration: animInfo.duration,
154
+ speed: animInfo.speed,
155
+ onStart: startCallback,
156
+ onEnd: endCallback,
157
+ }
158
+ );
159
+ animationManager.tryStartAnim(Forge.sFrameCount.count, animNode);
160
+ } else {
161
+ onStart?.();
162
+ onEnd?.();
163
+ }
164
+ }
165
+ };
166
+
167
+ const updateSlideDiv = updateDivPosition(slideDiv, slideDivLeft, slideDivTop);
168
+
169
+ const _slideTo = (target, animObj) => {
170
+ if (vertical) {
171
+ updateSlideDiv(0, -target - itemResizeSlideTop.value, animObj);
172
+ } else {
173
+ updateSlideDiv(-target - itemResizeSlideLeft.value, 0, animObj);
174
+ }
175
+ _onScroll();
176
+ };
177
+
178
+ const updateItemResizeSlideDiv = updateDivPosition(
179
+ itemResizeSlideDiv,
180
+ itemResizeSlideLeft,
181
+ itemResizeSlideTop
182
+ );
183
+
184
+ let itemMovingInfo = null;
185
+
186
+ let callFocusAfterUpdate = false;
187
+
188
+ //methods
189
+ const _onFocusChange = (id) => {
190
+ props.onFocusChange?.(id);
191
+ };
192
+
193
+ // query functions
194
+ const _getCurrentId = () => {
195
+ return {
196
+ id: focusId,
197
+ index: id2Index(focusId),
198
+ };
199
+ };
200
+
201
+ const _getPosition = (index) => {
202
+ let templateInfo = getItemByIndex(index).templateInfo;
203
+ let x_offset = vertical ? 0 : -visibleInfo.start;
204
+ let y_offset = vertical ? -visibleInfo.start : 0;
205
+ return {
206
+ left: templateInfo.left + x_offset,
207
+ top: templateInfo.top + y_offset,
208
+ width: templateInfo.width,
209
+ height: templateInfo.height,
210
+ };
211
+ };
212
+ const _getTemplatePosition = (index) => {
213
+ let templateInfo = getItemByIndex(index).templateInfo;
214
+ return {
215
+ left: templateInfo.left,
216
+ top: templateInfo.top,
217
+ width: templateInfo.width,
218
+ height: templateInfo.height,
219
+ };
220
+ };
221
+
222
+ const _dispatchEvent = (event) => {
223
+ console.error("dispatchEvent is deprecated and will be removed soon. Use MetroWidget exported method instead.")
224
+ switch (event.type) {
225
+ case Dispatcher.Type.setEnterFocusId:
226
+ setEnterFocusId(event.data);
227
+ break;
228
+ case Dispatcher.Type.setEnterFocusRect:
229
+ setEnterFocusRect(event.data);
230
+ break;
231
+ case Dispatcher.Type.updateItem:
232
+ break;
233
+ case Dispatcher.Type.slideToItem:
234
+ if (event.data) {
235
+ slideToItem(event.data?.id, event.data?.doAnim);
236
+ }
237
+ break;
238
+ case Dispatcher.Type.setFocusId:
239
+ setFocusId(event.data?.id, event.data?.needSlide, event.data?.doAnim);
240
+ break;
241
+ default:
242
+ break;
243
+ }
244
+ };
245
+
246
+ const id2Index = (id) => {
247
+ return metroTemplate.id2Index(id);
248
+ };
249
+
250
+ const index2Id = (index) => {
251
+ return metroTemplate.index2Id(index);
252
+ };
253
+
254
+ const getItemByIndex = (index) => {
255
+ return innerData[index];
256
+ };
257
+
258
+ const getItemById = (id) => {
259
+ return innerData[id2Index(id)];
260
+ };
261
+
262
+ const getNextItem = (anchorId, vDirection, hDirection, moveType) => {
263
+ const nextItem = metroTemplate.getNextItem(
264
+ anchorId,
265
+ vDirection,
266
+ hDirection,
267
+ moveType
268
+ );
269
+ if (nextItem) {
270
+ return innerData[nextItem.index];
271
+ } else {
272
+ return null;
273
+ }
274
+ };
275
+
276
+ const setItemZIndex = (item, z_index, is_focus) => {
277
+ if (item) {
278
+ let i = z_index;
279
+ if (is_focus && item.itemConfig.focusZIndex >= 0) {
280
+ i = item.itemConfig.focusZIndex;
281
+ } else if (item.itemConfig.normalZIndex >= 0) {
282
+ i = item.itemConfig.normalZIndex;
283
+ }
284
+ item.renderStyle.zIndex = i;
285
+ }
286
+ };
287
+
288
+ const onItemClick = (item) => {
289
+ if (!item) { return };
290
+ if (isFocus) {
291
+ item.onClick();
292
+ }
293
+ };
294
+
295
+ const onItemBlur = (blurItem) => {
296
+ if (!blurItem) return;
297
+ setItemZIndex(blurItem, 0, false);
298
+ if (isFocus) {
299
+ blurItem.onBlur();
300
+ }
301
+ };
302
+
303
+ const onItemFocus = (focusItem, rect) => {
304
+ if (!focusItem) return;
305
+ setItemZIndex(focusItem, innerData.length, true);
306
+ if (isFocus) {
307
+ _itemOnFocusSideEffect(focusItem, rect);
308
+ const called = focusItem.onFocus(rect);
309
+ if (!called) {
310
+ callFocusAfterUpdate = true;
311
+ }
312
+ }
313
+ };
314
+
315
+ const setFocusId = (id, needSlide = true, doAnim = false, extraSetting) => {
316
+ if (id == focusId) {
317
+ return;
318
+ }
319
+ templateItemAdder.tryAddItemById(id);
320
+ let next_focus_item = getItemById(id);
321
+ if (next_focus_item) {
322
+ preFocusId = focusId;
323
+ const preFocusItem = getItemById(preFocusId);
324
+ const nextTemplateInfo = next_focus_item.templateInfo;
325
+ focusId = nextTemplateInfo.id;
326
+ onItemBlur(preFocusItem);
327
+ onItemFocus(next_focus_item, preEdgeRect);
328
+ if (needSlide) {
329
+ slideToItem(id2Index(id), doAnim);
330
+ }
331
+ let unlock = null;
332
+ if (extraSetting) {
333
+ if (extraSetting.lockChildSlideEvent) {
334
+ unlock = lock(METRO_WIDGET_CONST.CHILD_SLIDE_EVENT);
335
+ }
336
+ }
337
+
338
+ const curTemplateInfo = getItemById(focusId).templateInfo;
339
+
340
+ let x_off_set = curTemplateInfo.left - nextTemplateInfo.left;
341
+ let y_off_set = curTemplateInfo.top - nextTemplateInfo.top;
342
+ preEdgeRect = {
343
+ direction: null,
344
+ rect: {
345
+ x: x_off_set,
346
+ y: y_off_set,
347
+ width: curTemplateInfo.width,
348
+ height: curTemplateInfo.height,
349
+ },
350
+ };
351
+ unlock?.();
352
+ }
353
+ };
354
+
355
+ const lock = (type) => {
356
+ const unlocker = [];
357
+ if (type & METRO_WIDGET_CONST.SLIDE) {
358
+ slideLock = true;
359
+ unlocker.push(() => {
360
+ slideLock = false;
361
+ });
362
+ }
363
+ if (type & METRO_WIDGET_CONST.CHILD_SLIDE_EVENT) {
364
+ childSlideEventLock = true;
365
+ unlocker.push(() => {
366
+ childSlideEventLock = false;
367
+ });
368
+ }
369
+ if (type & METRO_WIDGET_CONST.ON_KEY_DOWN) {
370
+ onKeyDownLock = true;
371
+ unlocker.push(() => {
372
+ onKeyDownLock = false;
373
+ });
374
+ }
375
+ return () => {
376
+ unlocker.map((item) => {
377
+ item();
378
+ });
379
+ };
380
+ };
381
+
382
+ const unlock = (type) => {
383
+ if (type & METRO_WIDGET_CONST.SLIDE) {
384
+ slideLock = true;
385
+ }
386
+ if (type & METRO_WIDGET_CONST.CHILD_SLIDE_EVENT) {
387
+ childSlideEventLock = true;
388
+ }
389
+ if (type & METRO_WIDGET_CONST.ON_KEY_DOWN) {
390
+ onKeyDownLock = true;
391
+ }
392
+ };
393
+
394
+ const getFocusBlockRef = () => {
395
+ return toRaw(focusNode.value);
396
+ };
397
+
398
+ const setEnterFocusId = (id) => {
399
+ templateItemAdder.tryAddItemById(id);
400
+ enterFocusId = id;
401
+ };
402
+
403
+ const setEnterFocusRect = (rect) => {
404
+ enterFocusRect = rect;
405
+ };
406
+
407
+ const slideTo = (position, doAnim) => {
408
+ templateItemAdder.tryAddItemByPosition(position);
409
+ if (
410
+ typeof position !== "undefined" &&
411
+ position != null &&
412
+ visibleInfo.start !== position
413
+ ) {
414
+ visibleInfo.start = position;
415
+
416
+ const updater = pageUpdater.update(
417
+ metroTemplate,
418
+ visibleInfo.startWithPadding,
419
+ visibleInfo.endWithPadding,
420
+ focusId,
421
+ false,
422
+ permanentItemList
423
+ );
424
+
425
+ let animObj = null;
426
+ if (doAnim) {
427
+ animObj = {
428
+ easing: props.slideSetting.Easing,
429
+ onStart: null,
430
+ speed: props.slideSetting.Speed,
431
+ onEnd: () => {
432
+ updater.apply();
433
+ },
434
+ };
435
+ pageUpdater.applyTmp();
436
+ } else {
437
+ pageUpdater.apply();
438
+ }
439
+ _slideTo(visibleInfo.start, animObj);
440
+ }
441
+ };
442
+
443
+ const slideToItem = (index, doAnim) => {
444
+ templateItemAdder.tryAddItemByIndex(index);
445
+ const targetItem = getItemByIndex(index);
446
+ if (targetItem) {
447
+ const direction = index - preAnchorItemIndex > 0 ? 1 : -1;
448
+ const visible_start = _calculateVisibleStart(targetItem.templateInfo, direction);
449
+ slideTo(visible_start, doAnim);
450
+ }
451
+ };
452
+
453
+ const refreshData = (force_update) => {
454
+ //由于data不支持reactive, 因此数据的更新只通过provideData
455
+ if (!props.provideData) {
456
+ console.error("refreshData: provideData is null.");
457
+ return;
458
+ }
459
+ let _force_update = force_update;
460
+ if (metroTemplate.size === 0) {
461
+ _force_update = true;
462
+ }
463
+ let new_list = toRaw(props.provideData());
464
+ let needSlide = false;
465
+ if (focusId >= new_list.length) {
466
+ focusId = 0;
467
+ preFocusId = -1;
468
+ if (visibleInfo.start !== 0) {
469
+ visibleInfo.start = 0;
470
+ needSlide = true;
471
+ }
472
+ }
473
+ let new_index = 0;
474
+ if (!_force_update) {
475
+ for (new_index = 0; new_index < new_list.length; ++new_index) {
476
+ let already_add = false;
477
+ for (let j = 0; j < innerData.length; ++j) {
478
+ if (new_list[new_index] === innerData[j].customerData) {
479
+ already_add = true;
480
+ break;
481
+ }
482
+ }
483
+ if (!already_add) {
484
+ break;
485
+ }
486
+ }
487
+ }
488
+ let need_update_content = false;
489
+ if (!_force_update && new_index === metroTemplate.size) {
490
+ //原始数据都在
491
+ if (new_index !== new_list.length) {
492
+ //增加数据
493
+ need_update_content = true;
494
+ templateItemAdder.updateData(new_list);
495
+ } else {
496
+ //数据没变
497
+ }
498
+ } else {
499
+ pageUpdateToken.value++;
500
+ //数据更改
501
+ permanentItemList = [];
502
+ need_update_content = true;
503
+ metroTemplate = _getMetroTemplate(
504
+ widgetRectInfo,
505
+ props.direction,
506
+ props.supportHistoryPath,
507
+ props.layoutType,
508
+ templateMode
509
+ );
510
+ innerData = [];
511
+ dataList = new_list;
512
+ templateItemAdder = new TemplateItemAdder(
513
+ metroTemplate,
514
+ dataList,
515
+ props.measures,
516
+ pageRange,
517
+ _onTemplateAdd,
518
+ props.name
519
+ );
520
+ }
521
+ if (need_update_content) {
522
+ if (props.onScroll) {
523
+ templateItemAdder.tryAddItemByIndex(dataList.length - 1);
524
+ } else {
525
+ templateItemAdder.tryAddItemById(focusId);
526
+ }
527
+ let lastTemplateInfo = getItemByIndex(metroTemplate.size - 1)?.templateInfo;
528
+ touchListener = _getTouchListener();
529
+ touchContainerW.value = vertical
530
+ ? props.width
531
+ : lastTemplateInfo
532
+ ? lastTemplateInfo.left + lastTemplateInfo.width
533
+ : 0;
534
+ touchContainerH.value = vertical
535
+ ? lastTemplateInfo
536
+ ? lastTemplateInfo.top + lastTemplateInfo.height
537
+ : 0
538
+ : props.height;
539
+ slidePile = new Forge.RectArea(
540
+ 0,
541
+ 0,
542
+ widgetRectInfo.contentWidth,
543
+ widgetRectInfo.contentHeight,
544
+ );
545
+ dragDirection =
546
+ vertical
547
+ ? Forge.DragSetting.DIRECTION_VERTICAL
548
+ : Forge.DragSetting.DIRECTION_HORIZONTAL;
549
+ }
550
+ const updater = pageUpdater.update(
551
+ metroTemplate,
552
+ visibleInfo.startWithPadding,
553
+ visibleInfo.endWithPadding,
554
+ focusId,
555
+ false,
556
+ permanentItemList
557
+ );
558
+ updater.apply();
559
+ onItemFocus(getItemById(focusId), null);
560
+ if (needSlide) {
561
+ _slideTo(visibleInfo.start, null);
562
+ } else if (need_update_content) {
563
+ _onScroll();
564
+ }
565
+ };
566
+
567
+ const getVisibleItems = () => {
568
+ const [visibleStart, visibleEnd] = metroTemplate.getVisibleItemList(
569
+ visibleInfo.startWithPadding,
570
+ visibleInfo.endWithPadding,
571
+ focusId
572
+ );
573
+ return {
574
+ start: visibleStart,
575
+ end: visibleEnd,
576
+ dataList: dataList.slice(info.visibleStart, info.visibleEnd + 1),
577
+ };
578
+ };
579
+
580
+ const moveFocus = (direction) => {
581
+ if (direction == "left" || direction == 37 || direction == EdgeDirection.left) {
582
+ _moveToNext(-1, 0);
583
+ } else if (direction == "right" || direction == 39 || direction == EdgeDirection.right) {
584
+ _moveToNext(1, 0);
585
+ } else if (direction == "top" || direction == 38 || direction == EdgeDirection.top) {
586
+ _moveToNext(0, -1);
587
+ } else if (direction == "bottom" || direction == 40 || direction == EdgeDirection.bottom) {
588
+ _moveToNext(0, 1);
589
+ } else {
590
+ console.error(TAG, "moveFocus direction is invalid.", direction);
591
+ }
592
+ };
593
+
594
+ const getCustomerDataSize = () => {
595
+ return dataList.length;
596
+ }
597
+
598
+ const exportObject = {
599
+ lock,
600
+ unlock,
601
+ slideTo,
602
+ setFocusId,
603
+ getFocusBlockRef,
604
+ setEnterFocusId,
605
+ setEnterFocusRect,
606
+ slideToItem,
607
+ refreshData,
608
+ _dispatchEvent,
609
+ getVisibleItems,
610
+ moveFocus,
611
+ getCustomerDataSize,
612
+ };
613
+
614
+ const _calculateNearestItemByRect = (visibleSet, enter_rect_info) => {
615
+ let edge_direction = enter_rect_info.direction;
616
+ let rect = enter_rect_info.rect;
617
+ var direction = "";
618
+ var point = { x: 0, y: 0 };
619
+ switch (edge_direction) {
620
+ case EdgeDirection.left:
621
+ direction = "left";
622
+ point.x = rect.x;
623
+ point.y = rect.y + rect.height / 4;
624
+ break;
625
+ case EdgeDirection.right:
626
+ direction = "right";
627
+ point.x = rect.x + rect.width;
628
+ point.y = rect.y + rect.height / 4;
629
+ break;
630
+ case EdgeDirection.top:
631
+ direction = "up";
632
+ point.x = rect.x + rect.width / 4;
633
+ point.y = rect.y;
634
+ break;
635
+ case EdgeDirection.bottom:
636
+ direction = "down";
637
+ point.x = rect.x + rect.width / 4;
638
+ point.y = rect.y + rect.height;
639
+ break;
640
+ default:
641
+ break;
642
+ }
643
+
644
+ var src_x_range = new SingleRangeModel(point.x, point.x);
645
+ var src_y_range = new SingleRangeModel(point.y, point.y);
646
+
647
+ var min_distance_item = null;
648
+ var min_distance = -1;
649
+ var min_direction_weighted = 0;
650
+ var distance = 0;
651
+ var direction_weighted = 0; // 根据进入方向决定的权值,用于保证
652
+
653
+ let key_pos = vertical ? "top" : "left";
654
+ let key_width = vertical ? "height" : "width";
655
+
656
+ for (let index of visibleSet) {
657
+ let itemTemplateInfo = getItemByIndex(index).templateInfo;
658
+ if (!itemTemplateInfo.focusable) continue;
659
+ let full_show =
660
+ itemTemplateInfo[key_pos] >= visibleInfo.start &&
661
+ itemTemplateInfo[key_pos] + itemTemplateInfo[key_width] - 1 <=
662
+ visibleInfo.end;
663
+ if (full_show) {
664
+ let x_pos =
665
+ vertical
666
+ ? itemTemplateInfo.left
667
+ : itemTemplateInfo.left - visibleInfo.start;
668
+ let y_pos =
669
+ vertical
670
+ ? itemTemplateInfo.top - visibleInfo.start
671
+ : itemTemplateInfo.top;
672
+ var target_x_range = new SingleRangeModel(
673
+ x_pos,
674
+ x_pos + itemTemplateInfo.width - 1
675
+ );
676
+ var target_y_range = new SingleRangeModel(
677
+ y_pos,
678
+ y_pos + itemTemplateInfo.height - 1
679
+ );
680
+ switch (direction) {
681
+ case "left":
682
+ if (point.x < x_pos + itemTemplateInfo.width - 1) {
683
+ // 这个点在item左侧,不可能左移到item
684
+ continue;
685
+ }
686
+ if (point.y < y_pos) {
687
+ //1.该点在其上,计算point和item右上角的距离
688
+ distance =
689
+ Math.pow(point.x - (x_pos + itemTemplateInfo.width - 1), 2) +
690
+ Math.pow(y_pos - point.y, 2);
691
+ } else if (src_y_range.IsInterAct(target_y_range)) {
692
+ //2.该点在其中,计算point和item右边框的垂直距离
693
+ distance = Math.pow(
694
+ point.x - (x_pos + itemTemplateInfo.width - 1),
695
+ 2
696
+ );
697
+ } else if (point.y > y_pos + itemTemplateInfo.height - 1) {
698
+ //3.该点在其下,计算point到item右下角的距离
699
+ distance =
700
+ Math.pow(point.x - (x_pos + itemTemplateInfo.width - 1), 2) +
701
+ Math.pow(point.y - (y_pos + itemTemplateInfo.height - 1), 2);
702
+ }
703
+ // point与item右边框的距离作为权值
704
+ direction_weighted = Math.abs(
705
+ point.x - (x_pos + itemTemplateInfo.width - 1)
706
+ );
707
+ break;
708
+ case "right":
709
+ if (point.x > x_pos) {
710
+ // 这个点在item右侧,不可能右移到item
711
+ continue;
712
+ }
713
+ if (point.y < y_pos) {
714
+ //1.该点在其上, 计算point和item左上角的距离
715
+ distance =
716
+ Math.pow(x_pos - point.x, 2) + Math.pow(y_pos - point.y, 2);
717
+ } else if (src_y_range.IsInterAct(target_y_range)) {
718
+ //2.该点在其中,计算point和item左边框的垂直距离
719
+ distance = Math.pow(x_pos - point.x, 2);
720
+ //(x2-x1)^2
721
+ } else if (point.y > y_pos + itemTemplateInfo.height - 1) {
722
+ //3.该点在其下,计算point和item左下角的距离
723
+ distance =
724
+ Math.pow(x_pos - point.x, 2) +
725
+ Math.pow(point.y - (y_pos + itemTemplateInfo.height - 1), 2);
726
+ }
727
+ // point与item左边框的距离作为权值
728
+ direction_weighted = Math.abs(point.x - x_pos);
729
+ break;
730
+ case "up":
731
+ if (point.y < y_pos + itemTemplateInfo.height - 1) {
732
+ // 这个点在item上侧,不可能上移到item
733
+ continue;
734
+ }
735
+ if (point.x < x_pos) {
736
+ //1.该点在其前,计算point和item右下角的距离
737
+ distance =
738
+ Math.pow(point.x - x_pos, 2) +
739
+ Math.pow(point.y - (y_pos + itemTemplateInfo.height - 1), 2);
740
+ } else if (src_x_range.IsInterAct(target_x_range)) {
741
+ //2.该点在其中,计算point和item下边框的垂直距离
742
+ distance = Math.pow(
743
+ point.y - (y_pos + itemTemplateInfo.height - 1),
744
+ 2
745
+ );
746
+ } else if (point.x > x_pos + itemTemplateInfo.width - 1) {
747
+ //3.该点在其后,计算point和item左下角的距离
748
+ distance =
749
+ Math.pow(point.x - (x_pos + itemTemplateInfo.width - 1), 2) +
750
+ Math.pow(point.y - (y_pos + itemTemplateInfo.height - 1), 2);
751
+ }
752
+ // point与item下边框的距离作为权值
753
+ direction_weighted = Math.abs(
754
+ point.y - (y_pos + itemTemplateInfo.height - 1)
755
+ );
756
+ break;
757
+ case "down":
758
+ if (point.y > y_pos) {
759
+ // 这个点在item下侧,不可能下移到item
760
+ continue;
761
+ }
762
+ if (point.x < x_pos) {
763
+ //1.该点在其前,计算point和item右上角的距离
764
+ distance =
765
+ Math.pow(point.x - x_pos, 2) + Math.pow(y_pos - point.y, 2);
766
+ } else if (src_x_range.IsInterAct(target_x_range)) {
767
+ //2.该点在其中,计算point和item上边框的垂直距离
768
+ distance = Math.pow(y_pos - point.y, 2);
769
+ } else if (point.x > x_pos + itemTemplateInfo.width - 1) {
770
+ //3.该点在其后,计算point和item左上角的距离
771
+ distance =
772
+ Math.pow(point.x - (x_pos + itemTemplateInfo.width - 1), 2) +
773
+ Math.pow(y_pos - point.y, 2);
774
+ }
775
+ // point与item上边框的距离作为权值
776
+ direction_weighted = Math.abs(point.y - y_pos);
777
+ break;
778
+ default:
779
+ console.log("direction is error:" + direction);
780
+ break;
781
+ }
782
+ if (min_distance < 0) {
783
+ // 设置首个找到的项目
784
+ min_distance = distance;
785
+ min_direction_weighted = direction_weighted;
786
+ min_distance_item = itemTemplateInfo;
787
+ } else {
788
+ if (
789
+ min_direction_weighted > direction_weighted ||
790
+ (min_direction_weighted === direction_weighted &&
791
+ min_distance > distance)
792
+ ) {
793
+ // 先进行权值比较,在权值相等时,再比较距离
794
+ min_distance = distance;
795
+ min_direction_weighted = direction_weighted;
796
+ min_distance_item = itemTemplateInfo;
797
+ }
798
+ }
799
+ }
800
+ }
801
+
802
+ if (min_distance_item) {
803
+ return min_distance_item.id;
804
+ } else {
805
+ return 0;
806
+ }
807
+ };
808
+
809
+ const focusBlockOnKeyDown = (ev) => {
810
+ if (onKeyDownLock) {
811
+ return true;
812
+ }
813
+ switch (ev.keyCode) {
814
+ case 37:
815
+ _moveToNext(-1, 0);
816
+ break;
817
+ case 38:
818
+ _moveToNext(0, -1);
819
+ break;
820
+ case 39:
821
+ _moveToNext(1, 0);
822
+ break;
823
+ case 40:
824
+ _moveToNext(0, 1);
825
+ break;
826
+ case 13:
827
+ onItemClick(getItemById(focusId));
828
+ break;
829
+ default:
830
+ //只接受上下左右确定键
831
+ return false;
832
+ }
833
+ return true;
834
+ };
835
+
836
+ const flushItemCoord = (index) => {
837
+ for (let i = index; i < innerData.length; ++i) {
838
+ const item = getItemByIndex(i);
839
+ const renderStyle = item.renderStyle;
840
+ const templateInfo = item.templateInfo;
841
+ renderStyle.left = templateInfo.left;
842
+ renderStyle.top = templateInfo.top;
843
+ renderStyle.width = templateInfo.width;
844
+ renderStyle.height = templateInfo.height;
845
+ }
846
+ };
847
+
848
+ const updateItemSize = (index, newSize, locateSet, animInfo = null) => {
849
+ if (index < 0 || !newSize) {
850
+ console.warn(TAG, "updateItemSize params invalid.");
851
+ return;
852
+ }
853
+
854
+ const keyItem = getItemByIndex(index);
855
+ if (
856
+ keyItem.renderStyle.width == newSize.width &&
857
+ keyItem.renderStyle.height == newSize.height
858
+ ) {
859
+ return;
860
+ }
861
+
862
+ const keyItemPreRect = {
863
+ left: keyItem.templateInfo.left,
864
+ top: keyItem.templateInfo.top,
865
+ width: keyItem.templateInfo.width,
866
+ height: keyItem.templateInfo.height,
867
+ };
868
+ const preVisibleStart = visibleInfo.start;
869
+
870
+ metroTemplate.updateItemSize(index, newSize);
871
+
872
+ const locateType = locateSet?.type ?? METRO_WIDGET_CONST.ITEM_RESIZE.WIDGET_SET;
873
+ switch (locateType) {
874
+ case METRO_WIDGET_CONST.ITEM_RESIZE.ANCHOR:
875
+ let anchor = locateSet.anchor;
876
+ if (!checkType(anchor, Number)) {
877
+ console.error(`updateItemSize error: params of locateType 'ANCHOR' is invalid, expected Number but got ${typeof locateSet.anchor}.\n Use default anchor 0.`);
878
+ anchor = 0;
879
+ }
880
+ const sizeKey = vertical ? "height" : "width";
881
+ const newVisibleStart = Math.round(
882
+ keyItem.templateInfo[sizeKey] * anchor
883
+ + preVisibleStart
884
+ - keyItemPreRect[sizeKey] * anchor
885
+ );
886
+ visibleInfo.start = newVisibleStart < 0 ? 0 : newVisibleStart;
887
+ break;
888
+ case METRO_WIDGET_CONST.ITEM_RESIZE.WIDGET_SET:
889
+ visibleInfo.start = _calculateVisibleStart(keyItem.templateInfo, preSeamlessSlideDirection);
890
+ break;
891
+ case METRO_WIDGET_CONST.ITEM_RESIZE.CUSTOMER_SET:
892
+ const customerFunc = locateSet.func;
893
+ if (!checkType(customerFunc, Function)) {
894
+ console.error(`updateItemSize error: params of locateType 'CUSTOMER_SETTING' is invalid, expected Function but got ${typeof locateSet.func}.\n Use locateType 'WIDGET_SETTING'`);
895
+ visibleInfo.start = _calculateVisibleStart(keyItem, preSeamlessSlideDirection);
896
+ break;
897
+ } else {
898
+ // 为了方便理解, 提供给外部以及外部返回的可视区域起始包含padding
899
+ const paddingStart = vertical ? widgetRectInfo.padding.top : widgetRectInfo.padding.left;
900
+ const newItemPadding = customerFunc(
901
+ keyItemPreRect,
902
+ {
903
+ left: keyItem.templateInfo.left,
904
+ top: keyItem.templateInfo.top,
905
+ width: keyItem.templateInfo.width,
906
+ height: keyItem.templateInfo.height,
907
+ },
908
+ (vertical ? keyItemPreRect.top : keyItemPreRect.left) - (preVisibleStart - paddingStart),
909
+ );
910
+ visibleInfo.start = (vertical ? keyItem.templateInfo.top : keyItem.templateInfo.left) - newItemPadding + paddingStart;
911
+ }
912
+ break;
913
+ default:
914
+ throw new Error("undefined locate type", locateSet.type);
915
+ }
916
+
917
+ const updater = pageUpdater.update(
918
+ metroTemplate,
919
+ visibleInfo.startWithPadding - props.keepTraceRange * pageRange,
920
+ Math.min(
921
+ visibleInfo.startMax + visibleInfo.range + visibleInfo.padding.end - 1,
922
+ visibleInfo.endWithPadding + props.keepTraceRange * pageRange
923
+ ),
924
+ keyItem.id,
925
+ false,
926
+ permanentItemList
927
+ );
928
+
929
+ let renderList = [];
930
+ const tmpRange = pageUpdater.getTmpRange();
931
+ if (tmpRange) {
932
+ renderList = Array.from(tmpRange).map((i) => {
933
+ return getItemByIndex(i);
934
+ });
935
+ }
936
+
937
+ const preRectInfo = {};
938
+ for (let i of renderList) {
939
+ preRectInfo[i.index] = {
940
+ left: i.renderStyle.left,
941
+ top: i.renderStyle.top,
942
+ width: i.renderStyle.width,
943
+ height: i.renderStyle.height,
944
+ };
945
+ }
946
+ flushItemCoord(index);
947
+
948
+ //item animation
949
+ if (animInfo) {
950
+ const onItemMoveEnd = (animDone) => {
951
+ itemMovingInfo = null;
952
+ animInfo?.onEnd();
953
+ };
954
+ let curFrameCount = Forge.sFrameCount.count;
955
+ for (let i of renderList) {
956
+ if (i.index < index) {
957
+ continue;
958
+ }
959
+ if (
960
+ preRectInfo[i.index].left != i.renderStyle.left ||
961
+ preRectInfo[i.index].top != i.renderStyle.top
962
+ ) {
963
+ itemMovingInfo = {
964
+ index: index,
965
+ deltaLeft: preRectInfo[i.index].left - i.renderStyle.left,
966
+ deltaTop: preRectInfo[i.index].top - i.renderStyle.top,
967
+ easing: animInfo.easing,
968
+ duration: animInfo.duration,
969
+ frameCount: curFrameCount,
970
+ };
971
+ }
972
+ const doItemAnim = (div) => {
973
+ const animNode = AnimationTools.getDivSlideAnim(
974
+ div,
975
+ preRectInfo[i.index].left - i.renderStyle.left,
976
+ preRectInfo[i.index].top - i.renderStyle.top,
977
+ 0,
978
+ 0,
979
+ {
980
+ easing: animInfo.easing ?? null,
981
+ duration: animInfo.duration ?? DEFAULT_ANIMATION_DURATION,
982
+ onEnd: i.index === index ? onItemMoveEnd : null,
983
+ }
984
+ );
985
+ animationManager.tryStartAnim(curFrameCount, animNode, i.index);
986
+ };
987
+ if (i.rootDiv) {
988
+ doItemAnim(toRaw(i.rootDiv));
989
+ } else {
990
+ i.addDivMountedListener(doItemAnim);
991
+ }
992
+ }
993
+ } else {
994
+ itemMovingInfo = null;
995
+ }
996
+
997
+ const slideDivPos =
998
+ (vertical ? itemResizeSlideTop.value : itemResizeSlideLeft.value) -
999
+ (visibleInfo.start - preVisibleStart);
1000
+
1001
+ if (animInfo) {
1002
+ const slideAnim = {
1003
+ easing: animInfo.easing ?? null,
1004
+ onStart: null,
1005
+ duration: animInfo.duration ?? DEFAULT_ANIMATION_DURATION,
1006
+ onEnd: (animDone) => {
1007
+ updater.apply();
1008
+ },
1009
+ };
1010
+ updater.applyTmp();
1011
+
1012
+ updateItemResizeSlideDiv(
1013
+ vertical ? 0 : slideDivPos,
1014
+ vertical ? slideDivPos : 0,
1015
+ slideAnim
1016
+ );
1017
+ } else {
1018
+ updateItemResizeSlideDiv(
1019
+ vertical ? 0 : slideDivPos,
1020
+ vertical ? slideDivPos : 0,
1021
+ null
1022
+ );
1023
+ pageUpdater.apply();
1024
+ }
1025
+ };
1026
+
1027
+ const _onTemplateAdd = (customerData, templateItem, measuresObj) => {
1028
+ let focusZIndex = -1,
1029
+ normalZIndex = -1;
1030
+ if (
1031
+ typeof measuresObj["zIndex"] != "undefined" &&
1032
+ measuresObj["zIndex"] != null
1033
+ ) {
1034
+ if (typeof measuresObj["zIndex"] == "object") {
1035
+ if (typeof measuresObj["zIndex"]["focus"] == "number") {
1036
+ focusZIndex = measuresObj["zIndex"]["focus"];
1037
+ }
1038
+ if (typeof measuresObj["zIndex"]["normal"] == "number") {
1039
+ normalZIndex = measuresObj["zIndex"]["normal"];
1040
+ }
1041
+ } else if (typeof measuresObj["zIndex"] == "number") {
1042
+ focusZIndex = measuresObj["zIndex"];
1043
+ normalZIndex = measuresObj["zIndex"];
1044
+ }
1045
+ }
1046
+ let itemConfig = {
1047
+ focusZIndex,
1048
+ normalZIndex,
1049
+ permanent: measuresObj.permanent ?? false,
1050
+ doSlide: measuresObj.doSlide ?? true,
1051
+ takeOverSlide: false,
1052
+ };
1053
+
1054
+ if (props.itemConfig) {
1055
+ const c = props.itemConfig(customerData);
1056
+ itemConfig.takeOverSlide = c?.takeOverSlide ?? false;
1057
+ }
1058
+
1059
+ const renderStyle = reactive({
1060
+ left: templateItem.left,
1061
+ top: templateItem.top,
1062
+ width: templateItem.width,
1063
+ height: templateItem.height,
1064
+ zIndex: itemConfig.normalZIndex,
1065
+ });
1066
+
1067
+ const item = new RenderItem(
1068
+ templateItem,
1069
+ customerData,
1070
+ renderStyle,
1071
+ itemConfig,
1072
+ () => {
1073
+ if (callFocusAfterUpdate && item.id === focusId) {
1074
+ nextTick(() => {
1075
+ onItemFocus(item, preEdgeRect);
1076
+ });
1077
+ callFocusAfterUpdate = false;
1078
+ }
1079
+ },
1080
+ //query object
1081
+ {
1082
+ id: templateItem.id,
1083
+ index: templateItem.index,
1084
+ position: _getPosition,
1085
+ templatePosition: _getTemplatePosition,
1086
+ getCurrentFocusId: _getCurrentId,
1087
+ slideTo: slideTo,
1088
+ updateItemSize,
1089
+ widgetHandler: exportObject,
1090
+ }
1091
+ );
1092
+
1093
+ innerData.push(item);
1094
+ if (item.itemConfig.permanent) {
1095
+ permanentItemList.push({
1096
+ index: item.index - 1,
1097
+ alreadyShow: false,
1098
+ });
1099
+ }
1100
+ const lastTemplateInfo = getItemByIndex(metroTemplate.size - 1).templateInfo;
1101
+ if (vertical) {
1102
+ touchContainerH.value = lastTemplateInfo.top + lastTemplateInfo.height - 1;
1103
+ } else {
1104
+ touchContainerW.value = lastTemplateInfo.left + lastTemplateInfo.width - 1;
1105
+ }
1106
+ };
1107
+
1108
+ const _itemOnFocusSideEffect = (item, edgeRect) => {
1109
+ _onFocusChange(item.id);
1110
+ if (item.rootDiv) {
1111
+ let event = {
1112
+ type: "focusRect",
1113
+ direction: edgeRect?.direction?.description,
1114
+ element: toRaw(item.rootDiv),
1115
+ };
1116
+ _bubbleCustomerEvent(event);
1117
+ }
1118
+ };
1119
+
1120
+ const focusBlockOnCustomerEvent = (ev) => {
1121
+ if (ev.type === "focusRect") {
1122
+ if (childSlideEventLock) {
1123
+ return true;
1124
+ }
1125
+ if (ev.ownerNode == exportObject) {
1126
+ return false;
1127
+ }
1128
+ let item_div = ev.element;
1129
+ let direction = 0;
1130
+ if (props.direction == HORIZONTAL) {
1131
+ if (ev.direction == "left") {
1132
+ direction = -1;
1133
+ } else if (ev.direction == "right") {
1134
+ direction = 1;
1135
+ }
1136
+ } else {
1137
+ if (ev.direction == "top") {
1138
+ direction = -1;
1139
+ } else if (ev.direction == "bottom") {
1140
+ direction = 1;
1141
+ }
1142
+ }
1143
+ const item_layout = item_div.jsvGetRelativePosition(toRaw(locateDiv.value));
1144
+
1145
+ let fakeItem = {
1146
+ templateInfo: {
1147
+ left: item_layout.left,
1148
+ top: item_layout.top,
1149
+ width: item_layout.width,
1150
+ height: item_layout.height,
1151
+ centerYPos: Math.floor(item_layout.top + item_layout.height / 2),
1152
+ centerXPos: Math.floor(item_layout.left + item_layout.width / 2),
1153
+ index: id2Index(focusId),
1154
+ },
1155
+ };
1156
+
1157
+ let cur_slide = _calculateVisibleStart(fakeItem.templateInfo, direction);
1158
+ if (cur_slide != visibleInfo.start) {
1159
+ visibleInfo.start = cur_slide;
1160
+ const updater = pageUpdater.update(
1161
+ metroTemplate,
1162
+ visibleInfo.startWithPadding - props.keepTraceRange * pageRange,
1163
+ Math.min(
1164
+ visibleInfo.startMax +
1165
+ visibleInfo.range +
1166
+ visibleInfo.padding.end -
1167
+ 1,
1168
+ visibleInfo.endWithPadding + props.keepTraceRange * pageRange
1169
+ ),
1170
+ focusId,
1171
+ true,
1172
+ permanentItemList
1173
+ );
1174
+ updater.applyTmp();
1175
+ _slideTo(visibleInfo.start, {
1176
+ easing: "",
1177
+ onStart: null,
1178
+ speed: props.slideSetting.Speed,
1179
+ onEnd: () => {
1180
+ updater.apply();
1181
+ },
1182
+ });
1183
+ return true;
1184
+ }
1185
+ }
1186
+ return false;
1187
+ };
1188
+
1189
+ const _bubbleCustomerEvent = (event) => {
1190
+ if (props.sendFocusRectEvent && event) {
1191
+ event.ownerNode = exportObject;
1192
+ toRaw(focusNode.value)?.bubbleCustomerEvent(event);
1193
+ }
1194
+ };
1195
+
1196
+ const _moveToNext = (
1197
+ horizontal_direction,
1198
+ vertical_direction,
1199
+ item_edge_rect
1200
+ ) => {
1201
+ //数据为空时
1202
+ if (innerData.length == 0) {
1203
+ let direction;
1204
+ if (horizontal_direction > 0) {
1205
+ direction = EdgeDirection.right;
1206
+ } else if (horizontal_direction < 0) {
1207
+ direction = EdgeDirection.left;
1208
+ } else if (vertical_direction > 0) {
1209
+ direction = EdgeDirection.bottom;
1210
+ } else if (vertical_direction < 0) {
1211
+ direction = EdgeDirection.top;
1212
+ } else {
1213
+ console.warn(TAG, "moveToNext error");
1214
+ }
1215
+ if (direction) {
1216
+ props.onEdge?.({
1217
+ direction: direction,
1218
+ rect: {
1219
+ x: 0,
1220
+ y: 0,
1221
+ width: 0,
1222
+ height: 0,
1223
+ },
1224
+ });
1225
+ }
1226
+ return;
1227
+ }
1228
+ let next_focus_item = getNextItem(
1229
+ focusId,
1230
+ vertical_direction,
1231
+ horizontal_direction,
1232
+ props.focusMoveType
1233
+ );
1234
+ if (next_focus_item !== null) {
1235
+ preFocusId = focusId;
1236
+ const preFocusItem = getItemByIndex(preFocusId);
1237
+ focusId = next_focus_item.id;
1238
+
1239
+ templateItemAdder.tryAddItem(next_focus_item.templateInfo, 1);
1240
+
1241
+ // itemFocus 和 itemBlur放在计算visibleStart之前, 以便用户更改template后在计算滚动
1242
+ let x_off_set = preFocusItem.templateInfo.left - next_focus_item.templateInfo.left;
1243
+ let y_off_set = preFocusItem.templateInfo.top - next_focus_item.templateInfo.top;
1244
+ if (item_edge_rect && item_edge_rect.rect) {
1245
+ item_edge_rect.rect.x += x_off_set;
1246
+ item_edge_rect.rect.y += y_off_set;
1247
+ preEdgeRect = item_edge_rect;
1248
+ } else {
1249
+ let direction;
1250
+ if (horizontal_direction > 0) {
1251
+ direction = EdgeDirection.right;
1252
+ } else if (horizontal_direction < 0) {
1253
+ direction = EdgeDirection.left;
1254
+ } else if (vertical_direction > 0) {
1255
+ direction = EdgeDirection.bottom;
1256
+ } else if (vertical_direction < 0) {
1257
+ direction = EdgeDirection.top;
1258
+ }
1259
+ preEdgeRect = {
1260
+ direction,
1261
+ rect: {
1262
+ x: x_off_set,
1263
+ y: y_off_set,
1264
+ width: preFocusItem.templateInfo.width,
1265
+ height: preFocusItem.templateInfo.height,
1266
+ },
1267
+ };
1268
+ }
1269
+ onItemBlur(preFocusItem);
1270
+ onItemFocus(next_focus_item, preEdgeRect);
1271
+
1272
+ let cur_visible_start = _calculateVisibleStart(next_focus_item.templateInfo, vertical ? vertical_direction : horizontal_direction);
1273
+ if (
1274
+ !next_focus_item.itemConfig.takeOverSlide &&
1275
+ visibleInfo.start !== cur_visible_start
1276
+ ) {
1277
+ if (next_focus_item.itemConfig.doSlide) {
1278
+ visibleInfo.start = cur_visible_start;
1279
+ const updater = pageUpdater.update(
1280
+ metroTemplate,
1281
+ visibleInfo.startWithPadding - props.keepTraceRange * pageRange,
1282
+ Math.min(
1283
+ visibleInfo.startMax +
1284
+ visibleInfo.range +
1285
+ visibleInfo.padding.end -
1286
+ 1,
1287
+ visibleInfo.endWithPadding + props.keepTraceRange * pageRange
1288
+ ),
1289
+ next_focus_item.id,
1290
+ false,
1291
+ permanentItemList
1292
+ );
1293
+ updater.applyTmp();
1294
+ let animObj = {
1295
+ easing: "",
1296
+ onStart: null,
1297
+ speed: props.slideSetting.Speed,
1298
+ onEnd: (animDone) => {
1299
+ updater.apply();
1300
+ },
1301
+ };
1302
+ _slideTo(visibleInfo.start, animObj);
1303
+ } else {
1304
+ //不做滚动时,保证获焦的item创建
1305
+ const updater = pageUpdater.update(
1306
+ metroTemplate,
1307
+ cur_visible_start,
1308
+ cur_visible_start + visibleInfo.range + visibleInfo.padding.end - 1,
1309
+ next_focus_item.id,
1310
+ false,
1311
+ permanentItemList
1312
+ );
1313
+ updater.apply();
1314
+ }
1315
+ if (
1316
+ itemMovingInfo &&
1317
+ itemMovingInfo.frameCount == Forge.sFrameCount.count
1318
+ ) {
1319
+ //缩放的动画正在进行时
1320
+ const tmpRangeList = pageUpdater.getTmpRange();
1321
+ for (let index of tmpRangeList) {
1322
+ const item = getItemByIndex(index);
1323
+ if (item.index > itemMovingInfo.index && !toRaw(item.rootDiv)) {
1324
+ item.addDivMountedListener((div) => {
1325
+ const animNode = AnimationTools.getDivSlideAnim(
1326
+ toRaw(div),
1327
+ itemMovingInfo.deltaLeft,
1328
+ itemMovingInfo.deltaTop,
1329
+ 0,
1330
+ 0,
1331
+ {
1332
+ easing: itemMovingInfo.easing,
1333
+ duration: itemMovingInfo.duration,
1334
+ }
1335
+ );
1336
+ animationManager.tryStartAnim(
1337
+ Forge.sFrameCount.count,
1338
+ animNode,
1339
+ item.index
1340
+ );
1341
+ });
1342
+ }
1343
+ }
1344
+ }
1345
+ }
1346
+ } else {
1347
+ //到达边缘
1348
+ let x_off_set = vertical ? 0 : visibleInfo.start;
1349
+ let y_off_set = vertical ? visibleInfo.start : 0;
1350
+ let edge;
1351
+ if (horizontal_direction === 1) {
1352
+ edge = EdgeDirection.right;
1353
+ }
1354
+ if (horizontal_direction === -1) {
1355
+ edge = EdgeDirection.left;
1356
+ }
1357
+ if (vertical_direction === 1) {
1358
+ edge = EdgeDirection.bottom;
1359
+ }
1360
+ if (vertical_direction === -1) {
1361
+ edge = EdgeDirection.top;
1362
+ }
1363
+ const curTemplateInfo = getItemById(focusId)?.templateInfo;
1364
+ let rect = {
1365
+ x: curTemplateInfo.left - x_off_set,
1366
+ y: curTemplateInfo.top - y_off_set,
1367
+ width: curTemplateInfo.width,
1368
+ height: curTemplateInfo.height,
1369
+ };
1370
+ props.onEdge?.({ direction: edge, rect: rect });
1371
+ innerData[id2Index(focusId)].onWidgetEdge({
1372
+ direction: edge,
1373
+ });
1374
+ }
1375
+ };
1376
+
1377
+ const _calculateVisibleStart = (targetTemplateInfo, direction) => {
1378
+ if (!targetTemplateInfo) {
1379
+ console.error("MetroWidget: _calculateVisibleStart target item is null");
1380
+ return 0;
1381
+ }
1382
+
1383
+ preSeamlessSlideDirection = direction;
1384
+ preAnchorItemIndex = targetTemplateInfo.index;
1385
+ let pos_key = vertical ? "top" : "left";
1386
+ let size_key = vertical ? "height" : "width";
1387
+ let center_key = vertical ? "centerYPos" : "centerXPos";
1388
+ let new_visible_start = visibleInfo.start;
1389
+
1390
+ switch (props.slideSetting.Type) {
1391
+ case SlideSetting.Type.FIX_POSITION:
1392
+ //FIX_POSITION 模式会将当前 item 的中心固定到指定位置
1393
+ new_visible_start = Math.ceil(
1394
+ targetTemplateInfo[center_key] -
1395
+ visibleInfo.range * props.slideSetting.FixPercent
1396
+ );
1397
+ break;
1398
+ case SlideSetting.Type.WHOLE_PAGE:
1399
+ if (typeof targetTemplateInfo.pageHeadIndex == "undefined") {
1400
+ //TODO 子控制滚动时whole page滚动
1401
+ console.error(
1402
+ "child controlled whole page slide type is not supported."
1403
+ );
1404
+ } else {
1405
+ new_visible_start = getItemByIndex(targetTemplateInfo.pageHeadIndex)
1406
+ .templateInfo[pos_key];
1407
+ }
1408
+
1409
+ break;
1410
+ case SlideSetting.Type.SEAMLESS:
1411
+ if (
1412
+ targetTemplateInfo[size_key] >=
1413
+ visibleInfo.range *
1414
+ (props.slideSetting.EndPercent - props.slideSetting.StartPercent)
1415
+ ) {
1416
+ //尺寸较大的item
1417
+ new_visible_start =
1418
+ targetTemplateInfo[center_key] - visibleInfo.range * 0.5;
1419
+ } else {
1420
+ if (direction > 0) {
1421
+ if (
1422
+ targetTemplateInfo[pos_key] + targetTemplateInfo[size_key] >
1423
+ visibleInfo.start +
1424
+ visibleInfo.range * props.slideSetting.EndPercent
1425
+ ) {
1426
+ new_visible_start =
1427
+ targetTemplateInfo[pos_key] +
1428
+ targetTemplateInfo[size_key] -
1429
+ visibleInfo.range * props.slideSetting.EndPercent;
1430
+ }
1431
+ } else if (direction < 0) {
1432
+ if (
1433
+ targetTemplateInfo[pos_key] <
1434
+ visibleInfo.start +
1435
+ visibleInfo.range * props.slideSetting.StartPercent
1436
+ ) {
1437
+ new_visible_start =
1438
+ targetTemplateInfo[pos_key] -
1439
+ visibleInfo.range * props.slideSetting.StartPercent;
1440
+ }
1441
+ } else {
1442
+ //不是沿widget方向的移动
1443
+ if (targetTemplateInfo[pos_key] < visibleInfo.start) {
1444
+ new_visible_start =
1445
+ targetTemplateInfo[pos_key] -
1446
+ visibleInfo.range * props.slideSetting.StartPercent;
1447
+ } else if (
1448
+ targetTemplateInfo[pos_key] + targetTemplateInfo[size_key] >
1449
+ visibleInfo.end
1450
+ ) {
1451
+ new_visible_start =
1452
+ targetTemplateInfo[pos_key] +
1453
+ targetTemplateInfo[size_key] -
1454
+ visibleInfo.range * props.slideSetting.EndPercent;
1455
+ }
1456
+ }
1457
+ }
1458
+ break;
1459
+ default:
1460
+ console.error(
1461
+ "MetroWidget: undefined slide type",
1462
+ props.slideSetting.Type
1463
+ );
1464
+ }
1465
+
1466
+ if ((props.slideSetting.BoundaryProtect & SlideSetting.START_PROTECT) > 0) {
1467
+ let boundary = 0;
1468
+ //首个元素是占位符时, 在保证获焦区域完全展示的前提下要保证首个不可获焦元素的完全展示
1469
+ const headTemplateInfo = getItemByIndex(0).templateInfo;
1470
+ if (
1471
+ !headTemplateInfo.focusable &&
1472
+ targetTemplateInfo[pos_key] + targetTemplateInfo[size_key] <=
1473
+ visibleInfo.range
1474
+ ) {
1475
+ boundary = headTemplateInfo[size_key];
1476
+ }
1477
+ new_visible_start = new_visible_start < boundary ? 0 : new_visible_start;
1478
+ }
1479
+ if ((props.slideSetting.BoundaryProtect & SlideSetting.END_PROTECT) > 0) {
1480
+ let lastTemplateInfo = getItemByIndex(metroTemplate.size - 1).templateInfo;
1481
+ let last_visible_start =
1482
+ lastTemplateInfo[pos_key] +
1483
+ lastTemplateInfo[size_key] -
1484
+ visibleInfo.range;
1485
+ last_visible_start = last_visible_start < 0 ? 0 : last_visible_start;
1486
+ let boundary = last_visible_start;
1487
+ if (
1488
+ !lastTemplateInfo.focusable &&
1489
+ targetTemplateInfo[pos_key] - last_visible_start >= 0
1490
+ ) {
1491
+ //最后元素是占位符, 在保证获焦区域完全展示的前提下要保证不可获焦元素的完全展示
1492
+ boundary = lastTemplateInfo[pos_key] - visibleInfo.range;
1493
+ }
1494
+ new_visible_start =
1495
+ new_visible_start > boundary ? last_visible_start : new_visible_start;
1496
+ }
1497
+ return Math.round(new_visible_start);
1498
+ };
1499
+
1500
+ const _onFocusableItemEdge = (edge_info) => {
1501
+ let horizontal_direction = 0;
1502
+ let vertical_direction = 0;
1503
+ switch (edge_info.direction) {
1504
+ case EdgeDirection.left:
1505
+ horizontal_direction = -1;
1506
+ break;
1507
+ case EdgeDirection.right:
1508
+ horizontal_direction = 1;
1509
+ break;
1510
+ case EdgeDirection.top:
1511
+ vertical_direction = -1;
1512
+ break;
1513
+ case EdgeDirection.bottom:
1514
+ vertical_direction = 1;
1515
+ break;
1516
+ default:
1517
+ break;
1518
+ }
1519
+ _moveToNext(horizontal_direction, vertical_direction, edge_info);
1520
+ };
1521
+
1522
+ const _ifValidEnterRect = (rect_info) => {
1523
+ return rect_info && rect_info.direction && rect_info.rect;
1524
+ };
1525
+
1526
+ const focusBlockOnFocus = (params) => {
1527
+ isFocus = true;
1528
+ preFocusId = -1;
1529
+ if (innerData.length === 0) {
1530
+ console.warn(`MetroWidget: ${props.name} get focus while data is empty.`);
1531
+ return;
1532
+ }
1533
+ let focus_id =
1534
+ typeof enterFocusId !== "undefined" &&
1535
+ enterFocusId >= 0 &&
1536
+ enterFocusId < metroTemplate.size
1537
+ ? enterFocusId
1538
+ : focusId;
1539
+ focus_id = _ifValidEnterRect(enterFocusRect)
1540
+ ? _calculateNearestItemByRect(pageUpdater.getRange(), enterFocusRect)
1541
+ : focus_id;
1542
+
1543
+ preEdgeRect = enterFocusRect;
1544
+ focusId = focus_id;
1545
+ enterFocusId = -1;
1546
+ enterFocusRect = null;
1547
+ onItemFocus(getItemById(focusId), preEdgeRect);
1548
+ props.onFocus?.();
1549
+ };
1550
+
1551
+ const focusBlockOnBlur = () => {
1552
+ enterFocusId = -1;
1553
+ enterFocusRect = null;
1554
+ preEdgeRect = null;
1555
+ preFocusId = focusId;
1556
+ console.log("testtest focusblock on blur", preFocusId)
1557
+ onItemBlur(getItemById(preFocusId));
1558
+ props.onBlur?.();
1559
+ isFocus = false;
1560
+ };
1561
+
1562
+ const _updateFocusByDragInfo = (viewX, viewY) => {
1563
+ let enterFocusRect = null;
1564
+ //模拟最小区域作为输入区域
1565
+ if (vertical) {
1566
+ enterFocusRect = {
1567
+ direction: EdgeDirection.top,
1568
+ rect: {
1569
+ x: props.left - viewX,
1570
+ y: props.top - viewY,
1571
+ width: 10,
1572
+ height: 10,
1573
+ },
1574
+ };
1575
+ } else {
1576
+ enterFocusRect = {
1577
+ direction: EdgeDirection.left,
1578
+ rect: {
1579
+ x: props.left - viewX,
1580
+ y: props.top - viewY,
1581
+ width: 10,
1582
+ height: 10,
1583
+ },
1584
+ };
1585
+ }
1586
+ focusId = _calculateNearestItemByRect(pageUpdater.getRange(), enterFocusRect);
1587
+ };
1588
+
1589
+ const _onDragUpdateItem = (visible_start, visible_end) => {
1590
+ templateItemAdder.tryAddItemByPosition(visible_end);
1591
+ const updater = pageUpdater.update(
1592
+ metroTemplate,
1593
+ visible_start,
1594
+ visible_end,
1595
+ 0,
1596
+ false,
1597
+ permanentItemList
1598
+ );
1599
+ updater.apply();
1600
+
1601
+ Forge.sRenderBridge.InstantPerformSwap();
1602
+ };
1603
+
1604
+ const _getTouchListener = () => {
1605
+ if (!props.enableTouch) {
1606
+ return null;
1607
+ }
1608
+ let callback = {
1609
+ OnDragStart: (msg) => {
1610
+ if (mounted) {
1611
+ Promise.resolve().then(() => {
1612
+ let cur_visible_start = visibleInfo.start - pageRange * 2;
1613
+ let cur_visible_end = visibleInfo.start + pageRange * 3 - 1;
1614
+ preUpdateVisibleStart = cur_visible_start;
1615
+ _onDragUpdateItem(cur_visible_start, cur_visible_end);
1616
+ });
1617
+ }
1618
+ return true;
1619
+ },
1620
+ OnMoved: (msg) => {
1621
+ if (mounted) {
1622
+ Promise.resolve().then(() => {
1623
+ if (
1624
+ typeof msg.viewY != "undefined" &&
1625
+ typeof msg.viewX != "undefined"
1626
+ ) {
1627
+ if (vertical) {
1628
+ visibleInfo.start = -msg.viewY;
1629
+ } else {
1630
+ visibleInfo.start = -msg.viewX;
1631
+ }
1632
+ if (visibleInfo.start < 0) {
1633
+ visibleInfo.start = 0;
1634
+ }
1635
+ }
1636
+ if (
1637
+ Math.abs(visibleInfo.start - preUpdateVisibleStart) <= pageRange
1638
+ ) {
1639
+ let cur_visible_start = visibleInfo.start - pageRange * 2;
1640
+ let cur_visible_end = visibleInfo.start + pageRange * 3 - 1;
1641
+ preUpdateVisibleStart = cur_visible_start;
1642
+ _onDragUpdateItem(cur_visible_start, cur_visible_end);
1643
+ }
1644
+ });
1645
+ }
1646
+
1647
+ return true;
1648
+ },
1649
+ OnDragEnd: (msg) => {
1650
+ updateSlideDiv(msg["viewX"], msg["viewY"], null);
1651
+ preUpdateVisibleStart = visibleInfo.start;
1652
+ _onDragUpdateItem(
1653
+ visibleInfo.startWithPadding,
1654
+ visibleInfo.endWithPadding
1655
+ );
1656
+ _updateFocusByDragInfo(msg["viewX"], msg["viewY"]);
1657
+ _onScroll();
1658
+ return true;
1659
+ },
1660
+ OnFling: (msg) => {
1661
+ updateSlideDiv(msg["viewX"], msg["viewY"], null);
1662
+ preUpdateVisibleStart = visibleInfo.start;
1663
+ _onDragUpdateItem(
1664
+ visibleInfo.startWithPadding,
1665
+ visibleInfo.endWithPadding
1666
+ );
1667
+ _updateFocusByDragInfo(msg["viewX"], msg["viewY"]);
1668
+ _onScroll();
1669
+ return true;
1670
+ },
1671
+ OnRelease: (msg) => {
1672
+ return true;
1673
+ },
1674
+ };
1675
+ return callback;
1676
+ };
1677
+
1678
+ const _updatePage = (rangeSet) => {
1679
+ const tmpArray = Array.from(rangeSet);
1680
+ renderData.value = tmpArray.map((item) => {
1681
+ return getItemByIndex(item);
1682
+ });
1683
+ if (props.enableItemRenderBreak) {
1684
+ itemRender.value = false;
1685
+ nextTick(() => {
1686
+ itemRender.value = true;
1687
+ });
1688
+ }
1689
+ };
1690
+
1691
+ const _onScroll = () => {
1692
+ if (props.onScroll) {
1693
+ const lastTemplateInfo = getItemByIndex(
1694
+ metroTemplate.size - 1
1695
+ ).templateInfo;
1696
+ let totalWidth;
1697
+ if (vertical) {
1698
+ totalWidth = lastTemplateInfo.top + lastTemplateInfo.height - 1;
1699
+ } else {
1700
+ totalWidth = lastTemplateInfo.left + lastTemplateInfo.width - 1;
1701
+ }
1702
+ props.onScroll(visibleInfo.start, visibleInfo.range, totalWidth);
1703
+ }
1704
+ };
1705
+
1706
+ const _initRootTouch = () => {
1707
+ if (props.enableTouch && toRaw(slideDiv.value)) {
1708
+ let view = toRaw(slideDiv.value).jsvGetProxyView(true);
1709
+ var drag_setting = new Forge.DragSetting(
1710
+ dragDirection,
1711
+ 20,
1712
+ false,
1713
+ slidePile,
1714
+ props.flingPageWidth,
1715
+ props.flingPageEdge
1716
+ );
1717
+ view.EnableDrag(drag_setting, touchListener, "translateMat(dx,dy,0)");
1718
+ }
1719
+ };
1720
+
1721
+ const _initItemViewTouch = (itemDivRef, index) => {
1722
+ if (props.enableTouch) {
1723
+ if (itemDivRef) {
1724
+ // 为view添加触控处理
1725
+ let view = itemDivRef.jsvGetProxyView(true);
1726
+ let dragSetting = new Forge.DragSetting(
1727
+ Forge.DragSetting.DIRECTION_DISABLE,
1728
+ 20,
1729
+ false,
1730
+ new Forge.RectArea(0, 0, 0, 0),
1731
+ -1,
1732
+ 3 / 4
1733
+ );
1734
+ let callback = {
1735
+ OnTap: (msg) => {
1736
+ return onItemClick(getItemById(index));
1737
+ },
1738
+ };
1739
+ view.EnableDrag(dragSetting, callback, "translateMat(dx,dy,0)");
1740
+ }
1741
+ }
1742
+ };
1743
+
1744
+ //init
1745
+ pageUpdater = new PageUpdater(_updatePage);
1746
+ dragDirection = vertical
1747
+ ? Forge.DragSetting.DIRECTION_VERTICAL
1748
+ : Forge.DragSetting.DIRECTION_HORIZONTAL;
1749
+ visibleInfo.range = vertical
1750
+ ? widgetRectInfo.contentHeight
1751
+ : widgetRectInfo.contentWidth;
1752
+ visibleInfo.padding = vertical
1753
+ ? { start: widgetRectInfo.padding.top, end: widgetRectInfo.padding.bottom }
1754
+ : { start: widgetRectInfo.padding.left, end: widgetRectInfo.padding.right };
1755
+
1756
+ if (props.provideData) {
1757
+ dataList = toRaw(props.provideData());
1758
+ } else if (props.data) {
1759
+ dataList = toRaw(props.data);
1760
+ }
1761
+
1762
+ window.metroTemplate = metroTemplate;
1763
+ window.innerData = innerData;
1764
+
1765
+ templateItemAdder = new TemplateItemAdder(
1766
+ metroTemplate,
1767
+ dataList,
1768
+ props.measures,
1769
+ pageRange,
1770
+ _onTemplateAdd,
1771
+ props.name
1772
+ );
1773
+ if (props.onScroll) {
1774
+ templateItemAdder.tryAddItemByIndex(dataList.length - 1);
1775
+ } else {
1776
+ templateItemAdder.tryAddItem(null, 2);
1777
+ }
1778
+
1779
+ //触控相关
1780
+ const lastTemplateInfo = getItemByIndex(metroTemplate.size - 1)?.templateInfo;
1781
+ if (lastTemplateInfo) {
1782
+ touchListener = _getTouchListener();
1783
+ touchContainerW.value =
1784
+ vertical
1785
+ ? props.width
1786
+ : lastTemplateInfo.left + lastTemplateInfo.width;
1787
+ touchContainerH.value =
1788
+ vertical
1789
+ ? lastTemplateInfo.top + lastTemplateInfo.height
1790
+ : props.height;
1791
+ }
1792
+ slidePile = new Forge.RectArea(
1793
+ 0,
1794
+ 0,
1795
+ widgetRectInfo.contentWidth,
1796
+ widgetRectInfo.contentHeight,
1797
+ );
1798
+ let init_focus_id = 0;
1799
+ let cur_visible_start = 0;
1800
+
1801
+ if (typeof props.initFocusId == "number") {
1802
+ templateItemAdder.tryAddItemById(props.initFocusId);
1803
+ const item = getItemById(props.initFocusId);
1804
+ if (item) {
1805
+ init_focus_id = props.initFocusId;
1806
+ if (item.itemConfig.doSlide) {
1807
+ cur_visible_start = _calculateVisibleStart(item.templateInfo, 1);
1808
+ }
1809
+ }
1810
+ }
1811
+ focusId = init_focus_id;
1812
+ visibleInfo.start = cur_visible_start;
1813
+
1814
+ const updater = pageUpdater.update(
1815
+ metroTemplate,
1816
+ visibleInfo.startWithPadding,
1817
+ visibleInfo.endWithPadding,
1818
+ 0,
1819
+ false,
1820
+ permanentItemList
1821
+ );
1822
+ updater.apply();
1823
+
1824
+ onMounted(() => {
1825
+ mounted = true;
1826
+ _initRootTouch();
1827
+ for (let item of renderData.value) {
1828
+ _initItemViewTouch(toRaw(item.rootDiv), item.index);
1829
+ }
1830
+
1831
+ if (visibleInfo.start) {
1832
+ _slideTo(visibleInfo.start, null);
1833
+ }
1834
+
1835
+ onItemFocus(getItemById(focusId), preEdgeRect);
1836
+
1837
+ if (props.enableItemRenderBreak) {
1838
+ nextTick(() => {
1839
+ itemRender.value = true;
1840
+ });
1841
+ }
1842
+ });
1843
+
1844
+ onUpdated(() => {
1845
+ for (let item of renderData.value) {
1846
+ if (!item.touchInit) {
1847
+ _initItemViewTouch(toRaw(item.rootDiv), item.index);
1848
+ }
1849
+ }
1850
+ });
1851
+
1852
+ onBeforeUnmount(() => {
1853
+ mounted = false;
1854
+ });
1855
+
1856
+ return {
1857
+ widgetRectInfo,
1858
+ focusBlockOnFocus,
1859
+ focusBlockOnBlur,
1860
+ focusBlockOnKeyDown,
1861
+ focusBlockOnCustomerEvent,
1862
+ _onFocusableItemEdge,
1863
+ exportObject,
1864
+ }
1865
+ }
1866
+
1867
+ export const RENDER_ITEM_BREAK_KEY = "__QcodeJsviewMetroWidgetSlot";