@onehat/ui 0.3.226 → 0.3.227

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onehat/ui",
3
- "version": "0.3.226",
3
+ "version": "0.3.227",
4
4
  "description": "Base UI for OneHat apps",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -209,8 +209,8 @@ function GridComponent(props) {
209
209
  [isLoading, setIsLoading] = useState(false),
210
210
  [localColumnsConfig, setLocalColumnsConfigRaw] = useState([]),
211
211
  [isDragMode, setIsDragMode] = useState(false),
212
- [dragRowSlot, setDragRowSlot] = useState(null),
213
- [dragRowIx, setDragRowIx] = useState(),
212
+ [cachedDragElements, setCachedDragElements] = useState(null),
213
+ [dragRow, setDragRow] = useState(),
214
214
  getIsExpanded = (index) => {
215
215
  return !!expandedRowsRef.current[index];
216
216
  },
@@ -512,10 +512,9 @@ function GridComponent(props) {
512
512
  parent = row.parentElement,
513
513
  parentRect = parent.getBoundingClientRect(),
514
514
  proxy = row.cloneNode(true),
515
- top = rowRect.top - parentRect.top,
516
- dragRowIx = Array.from(parent.children).indexOf(row)
515
+ top = rowRect.top - parentRect.top;
517
516
 
518
- setDragRowIx(dragRowIx); // the ix of which record is being dragged
517
+ setDragRow(row);
519
518
 
520
519
  proxy.style.top = top + 'px';
521
520
  proxy.style.left = '20px';
@@ -527,212 +526,116 @@ function GridComponent(props) {
527
526
  proxy.style.border = '1px solid #000';
528
527
  return proxy;
529
528
  },
530
- onRowReorderDragStart = (info, e, proxy, node) => {
531
- // console.log('onRowReorderDragStart', info, e, proxy, node);
532
- const
533
- proxyRect = proxy.getBoundingClientRect(),
534
- row = node.parentElement.parentElement,
535
- parent = row.parentElement,
536
- parentRect = parent.getBoundingClientRect(),
537
- rows = _.filter(parent.children, (childNode) => {
538
- return childNode.getBoundingClientRect().height !== 0; // Skip zero-height children
539
- }),
540
- currentY = proxyRect.top - parentRect.top, // top position of pointer, relative to page
541
- headerRowIx = showHeaders ? 0 : null,
542
- firstActualRowIx = showHeaders ? 1 : 0;
543
-
544
- // Figure out which index the user wants
545
- let newIx = 0;
546
- _.each(rows, (child, ix, all) => {
529
+ getOverState = (rows, currentY, mouseX) => {
530
+ // determines which row the mouse is over
531
+ // and whether the marker should be moved to the top or bottom of the row
532
+ let newIx = 0,
533
+ useBottom = false;
534
+ _.each(rows, (row, ix) => {
547
535
  const
548
- rect = child.getBoundingClientRect(), // rect of the row of this iteration
536
+ rect = row.getBoundingClientRect(),
549
537
  {
550
538
  top,
551
539
  bottom,
552
540
  height,
553
541
  } = rect,
554
- compensatedTop = top - parentRect.top,
555
- compensatedBottom = bottom - parentRect.top,
556
- halfHeight = height / 2;
557
-
558
- if (ix === headerRowIx || child === proxy) {
559
- return;
560
- }
561
- if (ix === firstActualRowIx) {
562
- // first row
563
- if (currentY < compensatedTop + halfHeight) {
564
- newIx = firstActualRowIx;
565
- return false;
566
- } else if (currentY < compensatedBottom) {
567
- newIx = firstActualRowIx + 1;
568
- return false;
569
- }
570
- return;
571
- } else if (ix === all.length -1) {
572
- // last row
573
- if (currentY < compensatedTop + halfHeight) {
574
- newIx = ix;
575
- return false;
576
- }
577
- newIx = ix +1;
578
- return false;
579
- }
580
-
581
- // all other rows
582
- if (compensatedTop <= currentY && currentY < compensatedTop + halfHeight) {
542
+ isOver = (
543
+ mouseX >= rect.left &&
544
+ mouseX <= rect.right &&
545
+ currentY >= rect.top &&
546
+ currentY <= rect.bottom
547
+ );
548
+ if (isOver) {
583
549
  newIx = ix;
584
- return false;
585
- } else if (currentY < compensatedBottom) {
586
- newIx = ix +1;
550
+
551
+ const
552
+ halfHeight = height / 2,
553
+ isOverTopHalf = currentY < top + halfHeight;
554
+
555
+ useBottom = !isOverTopHalf;
556
+
587
557
  return false;
588
558
  }
589
559
  });
560
+ return {
561
+ ix: newIx,
562
+ useBottom,
563
+ };
564
+ },
565
+ onRowReorderDragStart = (info, e, proxy, node) => {
566
+ // console.log('onRowReorderDragStart', info, e, proxy, node);
567
+
568
+ const
569
+ proxyRect = proxy.getBoundingClientRect(),
570
+ row = node.parentElement.parentElement,
571
+ flatlist = row.parentElement,
572
+ flatlistRect = flatlist.getBoundingClientRect(),
573
+ rows = _.filter(flatlist.childNodes, (childNode, ix) => {
574
+ const
575
+ isZeroHeight = childNode.getBoundingClientRect().height === 0,
576
+ isProxy = childNode === proxy,
577
+ isHeader = showHeaders && ix === 0;
578
+ return !isZeroHeight && !isProxy && !isHeader;
579
+ }),
580
+ currentY = proxyRect.top - flatlistRect.top, // top position of pointer, relative to page
581
+ { ix, useBottom } = getOverState(rows, currentY, e.clientX);
590
582
 
591
- let useBottom = false;
592
- if (!rows[newIx] || rows[newIx] === proxy) {
593
- newIx--;
594
- useBottom = true;
595
- }
596
583
 
597
584
  // Render marker showing destination location
598
585
  const
599
- rowContainerRect = rows[newIx].getBoundingClientRect(),
600
- top = (useBottom ? rowContainerRect.bottom : rowContainerRect.top) - parentRect.top - parseInt(parent.style.borderWidth), // get relative Y position
601
- gridRowsContainer = gridRef.current._listRef._scrollRef.childNodes[0],
602
- gridRowsContainerRect = gridRowsContainer.getBoundingClientRect(),
586
+ rowContainerRect = rows[ix].getBoundingClientRect(),
587
+ top = (useBottom ? rowContainerRect.bottom : rowContainerRect.top)
588
+ - flatlistRect.top
589
+ - (flatlist.style.borderWidth ? parseInt(flatlist.style.borderWidth) : 0), // get relative Y position
603
590
  marker = document.createElement('div');
604
-
605
591
  marker.style.position = 'absolute';
606
- marker.style.top = top -4 + 'px'; // -4 so it's always visible
592
+ marker.style.top = top + 'px';
607
593
  marker.style.height = '4px';
608
- marker.style.width = gridRowsContainerRect.width + 'px';
594
+ marker.style.width = flatlistRect.width + 'px';
609
595
  marker.style.backgroundColor = '#f00';
596
+ flatlist.appendChild(marker);
610
597
 
611
- gridRowsContainer.appendChild(marker);
612
-
613
- setDragRowSlot({ ix: newIx, marker, useBottom, });
598
+ setCachedDragElements({ ix, useBottom, marker, rows, });
614
599
  },
615
600
  onRowReorderDrag = (info, e, proxy, node) => {
616
601
  // console.log('onRowReorderDrag', info, e, proxy, node);
617
602
  const
603
+ { marker, rows, } = cachedDragElements,
618
604
  proxyRect = proxy.getBoundingClientRect(),
619
605
  row = node.parentElement.parentElement,
620
- parent = row.parentElement,
621
- parentRect = parent.getBoundingClientRect(),
622
- rows = _.filter(parent.children, (childNode) => {
623
- return childNode.getBoundingClientRect().height !== 0; // Skip zero-height children
624
- }),
625
- currentY = proxyRect.top - parentRect.top, // top position of pointer, relative to page
626
- headerRowIx = showHeaders ? 0 : null,
627
- firstActualRowIx = showHeaders ? 1 : 0;
628
-
629
- // Figure out which index the user wants
630
- let newIx = 0;
631
- _.each(rows, (child, ix, all) => {
632
- const
633
- rect = child.getBoundingClientRect(), // rect of the row of this iteration
634
- {
635
- top,
636
- bottom,
637
- height,
638
- } = rect,
639
- compensatedTop = top - parentRect.top,
640
- compensatedBottom = bottom - parentRect.top,
641
- halfHeight = height / 2;
642
-
643
- if (ix === headerRowIx || child === proxy) {
644
- return;
645
- }
646
- if (ix === firstActualRowIx) {
647
- // first row
648
- if (currentY < compensatedTop + halfHeight) {
649
- newIx = firstActualRowIx;
650
- return false;
651
- } else if (currentY < compensatedBottom) {
652
- newIx = firstActualRowIx + 1;
653
- return false;
654
- }
655
- return;
656
- } else if (ix === all.length -1) {
657
- // last row
658
- if (currentY < compensatedTop + halfHeight) {
659
- newIx = ix;
660
- return false;
661
- }
662
- newIx = ix +1;
663
- return false;
664
- }
665
-
666
- // all other rows
667
- if (compensatedTop <= currentY && currentY < compensatedTop + halfHeight) {
668
- newIx = ix;
669
- return false;
670
- } else if (currentY < compensatedBottom) {
671
- newIx = ix +1;
672
- return false;
673
- }
674
- });
675
-
676
- let useBottom = false;
677
- if (!rows[newIx] || rows[newIx] === proxy) {
678
- newIx--;
679
- useBottom = true;
680
- }
606
+ flatlist = row.parentElement,
607
+ flatlistRect = flatlist.getBoundingClientRect(),
608
+ currentY = proxyRect.top - flatlistRect.top, // top position of pointer, relative to page
609
+ { ix, useBottom } = getOverState(rows, currentY, e.clientX);
610
+
681
611
 
682
- // Render marker showing destination location (can't use regular render cycle because this div is absolutely positioned on page)
612
+ // move marker to new location
683
613
  const
684
- rowContainerRect = rows[newIx].getBoundingClientRect(),
685
- top = (useBottom ? rowContainerRect.bottom : rowContainerRect.top) - parentRect.top - parseInt(parent.style.borderWidth); // get relative Y position
686
- let marker = dragRowSlot?.marker;
687
- if (marker) {
688
- marker.style.top = top -4 + 'px'; // -4 so it's always visible
689
- }
690
-
691
- setDragRowSlot({ ix: newIx, marker, useBottom, });
692
- // console.log('onRowReorderDrag slot', newIx);
614
+ rowContainerRect = rows[ix].getBoundingClientRect(),
615
+ top = (useBottom ? rowContainerRect.bottom : rowContainerRect.top)
616
+ - flatlistRect.top
617
+ - (flatlist.style.borderWidth ? parseInt(flatlist.style.borderWidth) : 0); // get relative Y position
618
+ marker.style.top = top + 'px';
693
619
 
620
+ setCachedDragElements({ ix, useBottom, marker, rows, });
694
621
  },
695
622
  onRowReorderDragStop = (delta, e, config) => {
696
623
  // console.log('onRowReorderDragStop', delta, e, config);
697
624
  const
698
- dropIx = dragRowSlot.ix,
699
- compensatedDragIx = showHeaders ? dragRowIx -1 : dragRowIx, // ix, without taking header row into account
700
- compensatedDropIx = showHeaders ? dropIx -1 : dropIx, // // ix, without taking header row into account
701
- dropPosition = dragRowSlot.useBottom ? DROP_POSITION_AFTER : DROP_POSITION_BEFORE;
702
-
703
- let shouldMove = true,
704
- finalDropIx = compensatedDropIx;
705
-
706
- if (dropPosition === DROP_POSITION_BEFORE) {
707
- if (dragRowIx === dropIx || dragRowIx === dropIx -1) { // basically before or after the drag row's origin
708
- // Same as origin; don't do anything
709
- shouldMove = false;
710
- } else {
711
- // Actually move it
712
- if (!Repository) { // If we're just going to be switching rows, rather than telling server to reorder rows, so maybe adjust finalDropIx...
713
- if (finalDropIx > compensatedDragIx) { // if we're dropping *before* the origin ix
714
- finalDropIx = finalDropIx -1; // Because we're using BEFORE, we want to switch with the row *prior to* the ix we're dropping before
715
- }
716
- }
717
- }
718
- } else if (dropPosition === DROP_POSITION_AFTER) {
719
- // Only happens on the very last row. Everything else is BEFORE...
720
- if (dragRowIx === dropIx) {
721
- // Same as origin; don't do anything
722
- shouldMove = false;
723
- }
724
- }
625
+ { ix: dropIx, useBottom, marker, rows, } = cachedDragElements,
626
+ dragIx = rows.indexOf(dragRow);
725
627
 
628
+ const shouldMove = dropIx !== dragIx;
726
629
  if (shouldMove) {
727
630
  // Update the row with the new ix
728
631
  let dragRecord,
729
632
  dropRecord;
730
633
  if (Repository) {
731
- dragRecord = Repository.getByIx(compensatedDragIx);
732
- dropRecord = Repository.getByIx(finalDropIx);
733
-
734
- Repository.reorder(dragRecord, dropRecord, dropPosition);
735
-
634
+ dragRecord = Repository.getByIx(dragIx);
635
+ dropRecord = Repository.getByIx(dropIx);
636
+ if (dropRecord) {
637
+ Repository.reorder(dragRecord, dropRecord, useBottom ? DROP_POSITION_AFTER : DROP_POSITION_BEFORE);
638
+ }
736
639
  } else {
737
640
  function arrayMove(arr, fromIndex, toIndex) {
738
641
  var element = arr[fromIndex];
@@ -743,10 +646,8 @@ function GridComponent(props) {
743
646
  }
744
647
  }
745
648
 
746
- if (dragRowSlot) {
747
- dragRowSlot.marker.remove();
748
- }
749
- setDragRowSlot(null);
649
+ marker.remove();
650
+ setCachedDragElements(null);
750
651
  },
751
652
  calculatePageSize = (containerHeight) => {
752
653
  const
@@ -1027,15 +928,13 @@ function GridComponent(props) {
1027
928
  }
1028
929
 
1029
930
  let grid = <FlatList
931
+ testID="flatlist"
1030
932
  ref={gridRef}
1031
933
  scrollEnabled={CURRENT_MODE === UI_MODE_WEB}
1032
934
  nestedScrollEnabled={true}
1033
935
  contentContainerStyle={{
1034
936
  overflow: 'auto',
1035
- borderWidth: isDragMode ? styles.REORDER_BORDER_WIDTH : 0,
1036
- borderColor: isDragMode ? styles.REORDER_BORDER_COLOR : null,
1037
- borderStyle: styles.REORDER_BORDER_STYLE,
1038
- flex: 1,
937
+ // flex: 1,
1039
938
  }}
1040
939
  refreshing={isLoading}
1041
940
  onRefresh={pullToRefresh ? onRefresh : null}
@@ -1056,6 +955,7 @@ function GridComponent(props) {
1056
955
  bg="trueGray.100"
1057
956
  {...flatListProps}
1058
957
  />
958
+
1059
959
  if (CURRENT_MODE === UI_MODE_REACT_NATIVE) {
1060
960
  grid = <ScrollView flex={1} w="100%">{grid}</ScrollView>
1061
961
  }
@@ -1069,8 +969,22 @@ function GridComponent(props) {
1069
969
  }
1070
970
  }
1071
971
 
972
+ const gridContainerBorderProps = {};
973
+ if (isLoading) {
974
+ gridContainerBorderProps.borderTopWidth = 2;
975
+ gridContainerBorderProps.borderTopColor = '#f00';
976
+ } else if (isDragMode) {
977
+ gridContainerBorderProps.borderWidth = styles.REORDER_BORDER_WIDTH;
978
+ gridContainerBorderProps.borderColor = styles.REORDER_BORDER_COLOR;
979
+ gridContainerBorderProps.borderStyle = styles.REORDER_BORDER_STYLE;
980
+ } else {
981
+ gridContainerBorderProps.borderTopWidth = 1
982
+ gridContainerBorderProps.borderTopColor = 'trueGray.300';
983
+ }
984
+
1072
985
  grid = <Column
1073
986
  {...testProps('Grid')}
987
+ testID="outerContainer"
1074
988
  ref={containerRef}
1075
989
  w="100%"
1076
990
  bg={bg}
@@ -1081,11 +995,19 @@ function GridComponent(props) {
1081
995
  >
1082
996
  {topToolbar}
1083
997
 
1084
- <Column ref={gridContainerRef} w="100%" flex={1} minHeight={40} borderTopWidth={isLoading ? 2 : 1} borderTopColor={isLoading ? '#f00' : 'trueGray.300'} onClick={() => {
1085
- if (!isDragMode && !isInlineEditorShown) {
1086
- deselectAll();
1087
- }
1088
- }}>
998
+ <Column
999
+ testID="gridContainer"
1000
+ ref={gridContainerRef}
1001
+ w="100%"
1002
+ flex={1}
1003
+ minHeight={40}
1004
+ {...gridContainerBorderProps}
1005
+ onClick={() => {
1006
+ if (!isDragMode && !isInlineEditorShown) {
1007
+ deselectAll();
1008
+ }
1009
+ }}
1010
+ >
1089
1011
  {grid}
1090
1012
  </Column>
1091
1013