resizeHandle.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. (function() {
  2. const GRADIO_MIN_WIDTH = 320;
  3. const GRID_TEMPLATE_COLUMNS = '1fr 16px 1fr';
  4. const PAD = 16;
  5. const DEBOUNCE_TIME = 100;
  6. const R = {
  7. tracking: false,
  8. parent: null,
  9. parentWidth: null,
  10. leftCol: null,
  11. leftColStartWidth: null,
  12. screenX: null,
  13. };
  14. let resizeTimer;
  15. let parents = [];
  16. function setLeftColGridTemplate(el, width) {
  17. el.style.gridTemplateColumns = `${width}px 16px 1fr`;
  18. }
  19. function displayResizeHandle(parent) {
  20. if (window.innerWidth < GRADIO_MIN_WIDTH * 2 + PAD * 4) {
  21. parent.style.display = 'flex';
  22. if (R.handle != null) {
  23. R.handle.style.opacity = '0';
  24. }
  25. return false;
  26. } else {
  27. parent.style.display = 'grid';
  28. if (R.handle != null) {
  29. R.handle.style.opacity = '100';
  30. }
  31. return true;
  32. }
  33. }
  34. function afterResize(parent) {
  35. if (displayResizeHandle(parent) && parent.style.gridTemplateColumns != GRID_TEMPLATE_COLUMNS) {
  36. const oldParentWidth = R.parentWidth;
  37. const newParentWidth = parent.offsetWidth;
  38. const widthL = parseInt(parent.style.gridTemplateColumns.split(' ')[0]);
  39. const ratio = newParentWidth / oldParentWidth;
  40. const newWidthL = Math.max(Math.floor(ratio * widthL), GRADIO_MIN_WIDTH);
  41. setLeftColGridTemplate(parent, newWidthL);
  42. R.parentWidth = newParentWidth;
  43. }
  44. }
  45. function setup(parent) {
  46. const leftCol = parent.firstElementChild;
  47. const rightCol = parent.lastElementChild;
  48. parents.push(parent);
  49. parent.style.display = 'grid';
  50. parent.style.gap = '0';
  51. parent.style.gridTemplateColumns = GRID_TEMPLATE_COLUMNS;
  52. const resizeHandle = document.createElement('div');
  53. resizeHandle.classList.add('resize-handle');
  54. parent.insertBefore(resizeHandle, rightCol);
  55. resizeHandle.addEventListener('mousedown', (evt) => {
  56. if (evt.button !== 0) return;
  57. evt.preventDefault();
  58. evt.stopPropagation();
  59. document.body.classList.add('resizing');
  60. R.tracking = true;
  61. R.parent = parent;
  62. R.parentWidth = parent.offsetWidth;
  63. R.handle = resizeHandle;
  64. R.leftCol = leftCol;
  65. R.leftColStartWidth = leftCol.offsetWidth;
  66. R.screenX = evt.screenX;
  67. });
  68. resizeHandle.addEventListener('dblclick', (evt) => {
  69. evt.preventDefault();
  70. evt.stopPropagation();
  71. parent.style.gridTemplateColumns = GRID_TEMPLATE_COLUMNS;
  72. });
  73. afterResize(parent);
  74. }
  75. window.addEventListener('mousemove', (evt) => {
  76. if (evt.button !== 0) return;
  77. if (R.tracking) {
  78. evt.preventDefault();
  79. evt.stopPropagation();
  80. const delta = R.screenX - evt.screenX;
  81. const leftColWidth = Math.max(Math.min(R.leftColStartWidth - delta, R.parent.offsetWidth - GRADIO_MIN_WIDTH - PAD), GRADIO_MIN_WIDTH);
  82. setLeftColGridTemplate(R.parent, leftColWidth);
  83. }
  84. });
  85. window.addEventListener('mouseup', (evt) => {
  86. if (evt.button !== 0) return;
  87. if (R.tracking) {
  88. evt.preventDefault();
  89. evt.stopPropagation();
  90. R.tracking = false;
  91. document.body.classList.remove('resizing');
  92. }
  93. });
  94. window.addEventListener('resize', () => {
  95. clearTimeout(resizeTimer);
  96. resizeTimer = setTimeout(function() {
  97. for (const parent of parents) {
  98. afterResize(parent);
  99. }
  100. }, DEBOUNCE_TIME);
  101. });
  102. setupResizeHandle = setup;
  103. })();
  104. onUiLoaded(function() {
  105. for (var elem of gradioApp().querySelectorAll('.resize-handle-row')) {
  106. if (!elem.querySelector('.resize-handle')) {
  107. setupResizeHandle(elem);
  108. }
  109. }
  110. });