Browse Source

Revert "Attribute view support sticky layout (#9617)"

This reverts commit 433f4d554125f088a0b790c0d45ec2e5587360cd.
Vanessa 1 year ago
parent
commit
72eed4671e

+ 25 - 41
app/src/assets/scss/business/_av.scss

@@ -72,10 +72,6 @@
     opacity: 0;
     opacity: 0;
     display: flex;
     display: flex;
 
 
-    &[draggable=true] {
-      cursor: grab;
-    }
-
     svg {
     svg {
       height: 25px;
       height: 25px;
     }
     }
@@ -94,10 +90,6 @@
     cursor: pointer;
     cursor: pointer;
   }
   }
 
 
-  &__body {
-    float: left;
-  }
-
   &__row {
   &__row {
     display: flex;
     display: flex;
     border-bottom: 1px solid var(--b3-theme-surface-lighter);
     border-bottom: 1px solid var(--b3-theme-surface-lighter);
@@ -121,10 +113,6 @@
       .av__gutters {
       .av__gutters {
         opacity: 1;
         opacity: 1;
       }
       }
-
-      .av__firstcol svg {
-        opacity: 1;
-      }
     }
     }
 
 
     &--select {
     &--select {
@@ -148,23 +136,11 @@
       }
       }
     }
     }
 
 
-    &--add {
-      .av__firstcol svg {
-        opacity: 1;
-      }
-
-      &:hover {
-        background-color: var(--b3-list-icon-hover);
-      }
-    }
-
     &--header,
     &--header,
     &--footer {
     &--footer {
       background-color: var(--b3-theme-background);
       background-color: var(--b3-theme-background);
-      position: relative;
     }
     }
 
 
-    &--add,
     &--footer {
     &--footer {
       display: flex;
       display: flex;
       border-top: 1px solid var(--b3-theme-surface-lighter);
       border-top: 1px solid var(--b3-theme-surface-lighter);
@@ -208,6 +184,27 @@
         }
         }
       }
       }
     }
     }
+
+    &--add {
+      color: var(--b3-theme-on-surface);
+      padding: 5px 5px 5px 7px;
+      display: flex;
+      align-items: center;
+      transition: background 20ms ease-in 0s;
+      font-size: 87.5%;
+
+      svg {
+        height: 12px;
+        width: 12px;
+        color: var(--b3-theme-on-surface);
+        margin-right: 5px;
+        flex-shrink: 0;
+      }
+
+      &:hover {
+        background-color: var(--b3-list-icon-hover);
+      }
+    }
   }
   }
 
 
   &__cell {
   &__cell {
@@ -237,13 +234,6 @@
       border-radius: var(--b3-border-radius);
       border-radius: var(--b3-border-radius);
     }
     }
 
 
-    &--add {
-      position: sticky;
-      left: 25px;
-      font-size: 87.5%;
-      padding: 0 0.5em;
-    }
-
     .block__icon {
     .block__icon {
       position: absolute;
       position: absolute;
       right: 5px;
       right: 5px;
@@ -275,7 +265,6 @@
 
 
   &__celltext {
   &__celltext {
     overflow: hidden;
     overflow: hidden;
-    line-height: normal;
 
 
     .b3-chip {
     .b3-chip {
       margin: 1px 2px;
       margin: 1px 2px;
@@ -294,14 +283,6 @@
   }
   }
 
 
   &__firstcol {
   &__firstcol {
-    background-color: var(--b3-theme-background);
-    border-right: 1px solid var(--b3-theme-surface-lighter);
-
-    position: sticky;
-    left: 0;
-    width: 24px;
-    z-index: 1;
-
     svg {
     svg {
       color: var(--b3-theme-on-surface);
       color: var(--b3-theme-on-surface);
       height: 33px;
       height: 33px;
@@ -311,6 +292,10 @@
       box-sizing: border-box;
       box-sizing: border-box;
       float: left;
       float: left;
     }
     }
+
+    &:hover svg {
+      opacity: 1;
+    }
   }
   }
 
 
   &__widthdrag {
   &__widthdrag {
@@ -395,7 +380,6 @@
 .protyle-wysiwyg--select,
 .protyle-wysiwyg--select,
 .protyle-wysiwyg--hl {
 .protyle-wysiwyg--hl {
   .av__row--header,
   .av__row--header,
-  .av__firstcol,
   .av__row--footer {
   .av__row--footer {
     background-color: transparent;
     background-color: transparent;
   }
   }

+ 8 - 8
app/src/protyle/render/av/action.ts

@@ -32,7 +32,7 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle
     if (event.shiftKey) {
     if (event.shiftKey) {
         const rowElement = hasClosestByClassName(event.target, "av__row");
         const rowElement = hasClosestByClassName(event.target, "av__row");
         if (rowElement && !rowElement.classList.contains("av__row--header")) {
         if (rowElement && !rowElement.classList.contains("av__row--header")) {
-            selectRow(rowElement.querySelector(".av__check"), "toggle");
+            selectRow(rowElement.querySelector(".av__firstcol"), "toggle");
             return true;
             return true;
         }
         }
     }
     }
@@ -63,8 +63,8 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle
         return true;
         return true;
     }
     }
 
 
-    const gutterElement = hasClosestByClassName(event.target, "av__gutter");
-    if (gutterElement) {
+    const gutterElement = hasClosestByClassName(event.target, "ariaLabel");
+    if (gutterElement && gutterElement.parentElement.classList.contains("av__gutters")) {
         const rowElement = gutterElement.parentElement.parentElement;
         const rowElement = gutterElement.parentElement.parentElement;
         if (gutterElement.dataset.action === "add") {
         if (gutterElement.dataset.action === "add") {
             const avID = blockElement.getAttribute("data-av-id");
             const avID = blockElement.getAttribute("data-av-id");
@@ -97,7 +97,7 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle
         return true;
         return true;
     }
     }
 
 
-    const checkElement = hasClosestByClassName(event.target, "av__check");
+    const checkElement = hasClosestByClassName(event.target, "av__firstcol");
     if (checkElement) {
     if (checkElement) {
         window.siyuan.menus.menu.remove();
         window.siyuan.menus.menu.remove();
         selectRow(checkElement, "toggle");
         selectRow(checkElement, "toggle");
@@ -199,10 +199,10 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle
     if (cellElement && !cellElement.parentElement.classList.contains("av__row--header")) {
     if (cellElement && !cellElement.parentElement.classList.contains("av__row--header")) {
         const type = cellElement.parentElement.parentElement.firstElementChild.querySelector(`[data-col-id="${cellElement.getAttribute("data-col-id")}"]`).getAttribute("data-dtype") as TAVCol;
         const type = cellElement.parentElement.parentElement.firstElementChild.querySelector(`[data-col-id="${cellElement.getAttribute("data-col-id")}"]`).getAttribute("data-dtype") as TAVCol;
         if (type === "updated" || type === "created" || (type === "block" && !cellElement.getAttribute("data-detached"))) {
         if (type === "updated" || type === "created" || (type === "block" && !cellElement.getAttribute("data-detached"))) {
-            selectRow(cellElement.parentElement.querySelector(".av__check"), "toggle");
+            selectRow(cellElement.parentElement.querySelector(".av__firstcol"), "toggle");
         } else {
         } else {
             cellElement.parentElement.parentElement.querySelectorAll(".av__row--select").forEach(item => {
             cellElement.parentElement.parentElement.querySelectorAll(".av__row--select").forEach(item => {
-                item.querySelector(".av__check use").setAttribute("xlink:href", "#iconUncheck");
+                item.querySelector(".av__firstcol use").setAttribute("xlink:href", "#iconUncheck");
                 item.classList.remove("av__row--select");
                 item.classList.remove("av__row--select");
             });
             });
             updateHeader(cellElement.parentElement);
             updateHeader(cellElement.parentElement);
@@ -259,7 +259,7 @@ export const avContextmenu = (protyle: IProtyle, rowElement: HTMLElement, positi
         blockElement.querySelectorAll(".av__row--select").forEach(item => {
         blockElement.querySelectorAll(".av__row--select").forEach(item => {
             item.classList.remove("av__row--select");
             item.classList.remove("av__row--select");
         });
         });
-        blockElement.querySelectorAll(".av__check use").forEach(item => {
+        blockElement.querySelectorAll(".av__firstcol use").forEach(item => {
             item.setAttribute("xlink:href", "#iconUncheck");
             item.setAttribute("xlink:href", "#iconUncheck");
         });
         });
     }
     }
@@ -269,7 +269,7 @@ export const avContextmenu = (protyle: IProtyle, rowElement: HTMLElement, positi
         return true;
         return true;
     }
     }
     rowElement.classList.add("av__row--select");
     rowElement.classList.add("av__row--select");
-    rowElement.querySelector(".av__check use").setAttribute("xlink:href", "#iconCheck");
+    rowElement.querySelector(".av__firstcol use").setAttribute("xlink:href", "#iconCheck");
     const rowIds: string[] = [];
     const rowIds: string[] = [];
     const blockIds: string[] = [];
     const blockIds: string[] = [];
     const rowElements = blockElement.querySelectorAll(".av__row--select:not(.av__row--header)");
     const rowElements = blockElement.querySelectorAll(".av__row--select:not(.av__row--header)");

+ 8 - 7
app/src/protyle/render/av/keydown.ts

@@ -19,7 +19,7 @@ export const avKeydown = (event: KeyboardEvent, nodeElement: HTMLElement, protyl
     if (selectCellElement) {
     if (selectCellElement) {
         if (event.key === "Escape") {
         if (event.key === "Escape") {
             selectCellElement.classList.remove("av__cell--select");
             selectCellElement.classList.remove("av__cell--select");
-            selectRow(selectCellElement.parentElement.querySelector(".av__check"), "select");
+            selectRow(selectCellElement.parentElement.querySelector(".av__firstcol"), "select");
             event.preventDefault();
             event.preventDefault();
             return true;
             return true;
         }
         }
@@ -100,11 +100,11 @@ export const avKeydown = (event: KeyboardEvent, nodeElement: HTMLElement, protyl
         }
         }
         if (event.key === "Escape") {
         if (event.key === "Escape") {
             event.preventDefault();
             event.preventDefault();
-            selectRow(selectRowElements[0].querySelector(".av__check"), "unselectAll");
+            selectRow(selectRowElements[0].querySelector(".av__firstcol"), "unselectAll");
             return true;
             return true;
         }
         }
         if (event.key === "Enter") {
         if (event.key === "Enter") {
-            selectRow(selectRowElements[0].querySelector(".av__check"), "unselectAll");
+            selectRow(selectRowElements[0].querySelector(".av__firstcol"), "unselectAll");
             popTextCell(protyle, [selectRowElements[0].querySelector(".av__cell")]);
             popTextCell(protyle, [selectRowElements[0].querySelector(".av__cell")]);
             event.preventDefault();
             event.preventDefault();
             return true;
             return true;
@@ -112,9 +112,9 @@ export const avKeydown = (event: KeyboardEvent, nodeElement: HTMLElement, protyl
         // TODO event.shiftKey
         // TODO event.shiftKey
         if (event.key === "ArrowUp") {
         if (event.key === "ArrowUp") {
             const previousRowElement = selectRowElements[0].previousElementSibling;
             const previousRowElement = selectRowElements[0].previousElementSibling;
-            selectRow(selectRowElements[0].querySelector(".av__check"), "unselectAll");
+            selectRow(selectRowElements[0].querySelector(".av__firstcol"), "unselectAll");
             if (previousRowElement && !previousRowElement.classList.contains("av__row--header")) {
             if (previousRowElement && !previousRowElement.classList.contains("av__row--header")) {
-                selectRow(previousRowElement.querySelector(".av__check"), "select");
+                selectRow(previousRowElement.querySelector(".av__firstcol"), "select");
                 cellScrollIntoView(nodeElement, previousRowElement.getBoundingClientRect(), true);
                 cellScrollIntoView(nodeElement, previousRowElement.getBoundingClientRect(), true);
             } else {
             } else {
                 nodeElement.classList.add("protyle-wysiwyg--select");
                 nodeElement.classList.add("protyle-wysiwyg--select");
@@ -124,9 +124,9 @@ export const avKeydown = (event: KeyboardEvent, nodeElement: HTMLElement, protyl
         }
         }
         if (event.key === "ArrowDown") {
         if (event.key === "ArrowDown") {
             const nextRowElement = selectRowElements[selectRowElements.length - 1].nextElementSibling;
             const nextRowElement = selectRowElements[selectRowElements.length - 1].nextElementSibling;
-            selectRow(selectRowElements[0].querySelector(".av__check"), "unselectAll");
+            selectRow(selectRowElements[0].querySelector(".av__firstcol"), "unselectAll");
             if (nextRowElement && !nextRowElement.classList.contains("av__row--add")) {
             if (nextRowElement && !nextRowElement.classList.contains("av__row--add")) {
-                selectRow(nextRowElement.querySelector(".av__check"), "select");
+                selectRow(nextRowElement.querySelector(".av__firstcol"), "select");
                 cellScrollIntoView(nodeElement, nextRowElement.getBoundingClientRect(), true);
                 cellScrollIntoView(nodeElement, nextRowElement.getBoundingClientRect(), true);
             } else {
             } else {
                 nodeElement.classList.add("protyle-wysiwyg--select");
                 nodeElement.classList.add("protyle-wysiwyg--select");
@@ -137,3 +137,4 @@ export const avKeydown = (event: KeyboardEvent, nodeElement: HTMLElement, protyl
     }
     }
     return false;
     return false;
 };
 };
+

+ 16 - 24
app/src/protyle/render/av/render.ts

@@ -6,7 +6,6 @@ import * as dayjs from "dayjs";
 import {unicode2Emoji} from "../../../emoji";
 import {unicode2Emoji} from "../../../emoji";
 import {focusBlock} from "../../util/selection";
 import {focusBlock} from "../../util/selection";
 import {isMac} from "../../util/compatibility";
 import {isMac} from "../../util/compatibility";
-import {stickyScrollY} from "../../scroll/stickyScroll";
 
 
 export const avRender = (element: Element, protyle: IProtyle, cb?: () => void) => {
 export const avRender = (element: Element, protyle: IProtyle, cb?: () => void) => {
     let avElements: Element[] = [];
     let avElements: Element[] = [];
@@ -41,6 +40,8 @@ export const avRender = (element: Element, protyle: IProtyle, cb?: () => void) =
                 e.firstElementChild.innerHTML = html;
                 e.firstElementChild.innerHTML = html;
             }
             }
             const left = e.querySelector(".av__scroll")?.scrollLeft || 0;
             const left = e.querySelector(".av__scroll")?.scrollLeft || 0;
+            const headerTransform = (e.querySelector(".av__row--header") as HTMLElement)?.style.transform;
+            const footerTransform = (e.querySelector(".av__row--footer") as HTMLElement)?.style.transform;
             let selectCellId = "";
             let selectCellId = "";
             const selectCellElement = e.querySelector(".av__cell--select") as HTMLElement;
             const selectCellElement = e.querySelector(".av__cell--select") as HTMLElement;
             if (selectCellElement) {
             if (selectCellElement) {
@@ -51,7 +52,7 @@ export const avRender = (element: Element, protyle: IProtyle, cb?: () => void) =
             }, (response) => {
             }, (response) => {
                 const data = response.data.view as IAVTable;
                 const data = response.data.view as IAVTable;
                 // header
                 // header
-                let tableHTML = '<div class="av__row av__row--header"><div class="av__firstcol av__check"><svg style="height: 32px"><use xlink:href="#iconUncheck"></use></svg></div>';
+                let tableHTML = '<div class="av__row av__row--header"><div class="av__firstcol"><svg style="height: 32px"><use xlink:href="#iconUncheck"></use></svg></div>';
                 let calcHTML = "";
                 let calcHTML = "";
                 data.columns.forEach((column: IAVColumn) => {
                 data.columns.forEach((column: IAVColumn) => {
                     if (column.hidden) {
                     if (column.hidden) {
@@ -79,10 +80,10 @@ style="width: ${column.width || "200px"}">${getCalcValue(column) || '<svg><use x
                 data.rows.forEach((row: IAVRow) => {
                 data.rows.forEach((row: IAVRow) => {
                     tableHTML += `<div class="av__row" data-id="${row.id}">
                     tableHTML += `<div class="av__row" data-id="${row.id}">
 <div class="av__gutters">
 <div class="av__gutters">
-    <button class="av__gutter ariaLabel" data-action="add" data-position="right" aria-label="${isMac() ? window.siyuan.languages.addBelowAbove : window.siyuan.languages.addBelowAbove.replace("⌥", "Alt+")}"><svg><use xlink:href="#iconAdd"></use></svg></button>
-    <button class="av__gutter ariaLabel" draggable="true" data-position="right" aria-label="${window.siyuan.languages.rowTip}"><svg><use xlink:href="#iconDrag"></use></svg></button>
+    <button class="ariaLabel" data-action="add" data-position="right" aria-label="${isMac() ? window.siyuan.languages.addBelowAbove : window.siyuan.languages.addBelowAbove.replace("⌥", "Alt+")}"><svg><use xlink:href="#iconAdd"></use></svg></button>
+    <button class="ariaLabel" draggable="true" data-position="right" aria-label="${window.siyuan.languages.rowTip}"><svg><use xlink:href="#iconDrag"></use></svg></button>
 </div>
 </div>
-<div class="av__firstcol av__check"><svg><use xlink:href="#iconUncheck"></use></svg></div>`;
+<div class="av__firstcol"><svg><use xlink:href="#iconUncheck"></use></svg></div>`;
                     row.cells.forEach((cell, index) => {
                     row.cells.forEach((cell, index) => {
                         if (data.columns[index].hidden) {
                         if (data.columns[index].hidden) {
                             return;
                             return;
@@ -149,7 +150,7 @@ style="width: ${column.width || "200px"}">${getCalcValue(column) || '<svg><use x
                         }
                         }
                         if (["text", "template", "url", "email", "phone", "number", "date", "created", "updated"].includes(cell.valueType)) {
                         if (["text", "template", "url", "email", "phone", "number", "date", "created", "updated"].includes(cell.valueType)) {
                             if (cell.value && cell.value[cell.valueType as "url"].content) {
                             if (cell.value && cell.value[cell.valueType as "url"].content) {
-                                text += `<span ${cell.valueType !== "number" ? "" : 'style="right:auto; left:5px;"'} data-type="copy" class="b3-tooltips b3-tooltips__n block__icon" aria-label="${window.siyuan.languages.copy}"><svg><use xlink:href="#iconCopy"></use></svg></span>`;
+                                text += `<span ${cell.valueType !== "number" ? "" : 'style="right:auto;left:5px"'} data-type="copy" class="b3-tooltips b3-tooltips__n block__icon" aria-label="${window.siyuan.languages.copy}"><svg><use xlink:href="#iconCopy"></use></svg></span>`;
                             }
                             }
                         }
                         }
                         tableHTML += `<div class="av__cell" data-id="${cell.id}" data-col-id="${data.columns[index].id}"
                         tableHTML += `<div class="av__cell" data-id="${cell.id}" data-col-id="${data.columns[index].id}"
@@ -195,17 +196,13 @@ ${cell.color ? `color:${cell.color};` : ""}">${text}</div>`;
         <div class="av__counter fn__none"></div>
         <div class="av__counter fn__none"></div>
     </div>
     </div>
     <div class="av__scroll">
     <div class="av__scroll">
-        <div class="av__body">
+        <div style="float: left;">
             ${tableHTML}
             ${tableHTML}
             <div class="av__row--add">
             <div class="av__row--add">
-                <div class="av__firstcol">
-                    <svg><use xlink:href="#iconAdd"></use></svg>
-                </div>
-                <div class="av__cell--add">
-                    ${window.siyuan.languages.addAttr}
-                </div>
+                <svg><use xlink:href="#iconAdd"></use></svg>
+                ${window.siyuan.languages.addAttr}
             </div>
             </div>
-            <div class="av__row--footer"><div class="av__firstcol"></div>${calcHTML}</div>
+            <div class="av__row--footer"><div style="width: 24px"></div>${calcHTML}</div>
         </div>
         </div>
     </div>
     </div>
 </div>`;
 </div>`;
@@ -215,16 +212,11 @@ ${cell.color ? `color:${cell.color};` : ""}">${text}</div>`;
                     if (left) {
                     if (left) {
                         e.querySelector(".av__scroll").scrollLeft = left;
                         e.querySelector(".av__scroll").scrollLeft = left;
                     }
                     }
-                    const bodyElement = e.querySelector<HTMLElement>(".av__body");
-                    if (bodyElement) {
-                        const headerElement = bodyElement.querySelector<HTMLElement>(".av__row--header");
-                        const footerElement = bodyElement.querySelector<HTMLElement>(".av__row--footer");
-                        stickyScrollY(
-                            protyle.contentElement,
-                            bodyElement as HTMLElement,
-                            headerElement ? [{element: headerElement}] : [],
-                            footerElement ? [{element: footerElement}] : [],
-                        );
+                    if (headerTransform) {
+                        (e.querySelector(".av__row--header") as HTMLElement).style.transform = headerTransform;
+                    }
+                    if (footerTransform) {
+                        (e.querySelector(".av__row--footer") as HTMLElement).style.transform = footerTransform;
                     }
                     }
                     if (selectCellId) {
                     if (selectCellId) {
                         const newCellElement = e.querySelector(`.av__row[data-id="${selectCellId.split(Constants.ZWSP)[0]}"] .av__cell[data-col-id="${selectCellId.split(Constants.ZWSP)[1]}"]`);
                         const newCellElement = e.querySelector(`.av__row[data-id="${selectCellId.split(Constants.ZWSP)[0]}"] .av__cell[data-col-id="${selectCellId.split(Constants.ZWSP)[1]}"]`);

+ 2 - 2
app/src/protyle/render/av/row.ts

@@ -6,12 +6,12 @@ export const selectRow = (checkElement: Element, type: "toggle" | "select" | "un
     const useElement = checkElement.querySelector("use");
     const useElement = checkElement.querySelector("use");
     if (rowElement.classList.contains("av__row--header") || type === "unselectAll") {
     if (rowElement.classList.contains("av__row--header") || type === "unselectAll") {
         if ("#iconCheck" === useElement.getAttribute("xlink:href")) {
         if ("#iconCheck" === useElement.getAttribute("xlink:href")) {
-            rowElement.parentElement.querySelectorAll(".av__check").forEach(item => {
+            rowElement.parentElement.querySelectorAll(".av__firstcol").forEach(item => {
                 item.querySelector("use").setAttribute("xlink:href", "#iconUncheck");
                 item.querySelector("use").setAttribute("xlink:href", "#iconUncheck");
                 item.parentElement.classList.remove("av__row--select");
                 item.parentElement.classList.remove("av__row--select");
             });
             });
         } else {
         } else {
-            rowElement.parentElement.querySelectorAll(".av__check").forEach(item => {
+            rowElement.parentElement.querySelectorAll(".av__firstcol").forEach(item => {
                 item.querySelector("use").setAttribute("xlink:href", "#iconCheck");
                 item.querySelector("use").setAttribute("xlink:href", "#iconCheck");
                 item.parentElement.classList.add("av__row--select");
                 item.parentElement.classList.add("av__row--select");
             });
             });

+ 20 - 13
app/src/protyle/scroll/event.ts

@@ -4,7 +4,6 @@ import {fetchPost} from "../../util/fetch";
 import {onGet} from "../util/onGet";
 import {onGet} from "../util/onGet";
 import {isMobile} from "../../util/functions";
 import {isMobile} from "../../util/functions";
 import {hasClosestBlock, hasClosestByClassName} from "../util/hasClosest";
 import {hasClosestBlock, hasClosestByClassName} from "../util/hasClosest";
-import {stickyScrollY} from "./stickyScroll";
 
 
 let getIndexTimeout: number;
 let getIndexTimeout: number;
 export const scrollEvent = (protyle: IProtyle, element: HTMLElement) => {
 export const scrollEvent = (protyle: IProtyle, element: HTMLElement) => {
@@ -26,18 +25,26 @@ export const scrollEvent = (protyle: IProtyle, element: HTMLElement) => {
         }
         }
 
 
         protyle.wysiwyg.element.querySelectorAll(".av").forEach((item: HTMLElement) => {
         protyle.wysiwyg.element.querySelectorAll(".av").forEach((item: HTMLElement) => {
-            const bodyElement = item.querySelector(".av__body") as HTMLElement;
-            
-            if (bodyElement) {
-                const headerElement = bodyElement.querySelector(".av__row--header") as HTMLElement;
-                const footerElement = bodyElement.querySelector(".av__row--footer") as HTMLElement;
-
-                stickyScrollY(
-                    element,
-                    bodyElement,
-                    headerElement ? [{element: headerElement}] : [],
-                    footerElement ? [{element: footerElement}] : [],
-                );
+            if (item.parentElement.classList.contains("protyle-wysiwyg")) {
+                const headerTop = item.offsetTop + 43;
+                const headerElement = item.querySelector(".av__row--header") as HTMLElement;
+                if (headerElement) {
+                    if (headerTop < element.scrollTop && headerTop + headerElement.parentElement.clientHeight > element.scrollTop) {
+                        headerElement.style.transform = `translateY(${element.scrollTop - headerTop}px)`;
+                    } else {
+                        headerElement.style.transform = "";
+                    }
+                }
+                const footerElement = item.querySelector(".av__row--footer") as HTMLElement;
+                if (footerElement) {
+                    const footerBottom = headerTop + footerElement.parentElement.clientHeight;
+                    const scrollBottom = element.scrollTop + element.clientHeight + 5;
+                    if (headerTop + 42 + 36 * 2 < scrollBottom && footerBottom > scrollBottom) {
+                        footerElement.style.transform = `translateY(${scrollBottom - footerBottom}px)`;
+                    } else {
+                        footerElement.style.transform = "";
+                    }
+                }
             }
             }
         });
         });
 
 

+ 0 - 276
app/src/protyle/scroll/stickyScroll.ts

@@ -1,276 +0,0 @@
-export interface IStickyPositionY {
-    top: number;
-    bottom: number;
-}
-
-export interface IStickyElementY {
-    element: HTMLElement;
-    offset?: number;
-}
-
-export interface IStickyContextY extends IStickyElementY {
-    rect: DOMRect;
-    base: number;
-    origin: IStickyPositionY;
-    current: IStickyPositionY;
-    target: IStickyPositionY;
-    style: IStickyPositionY;
-}
-
-export const stickyScrollY = (
-    view: HTMLElement, // 视口元素
-    container: HTMLElement, // 容器元素
-    topElements: IStickyElementY[] = [], // 顶部粘性元素
-    bottomElements: IStickyElementY[] = [], // 底部粘性元素
-) => {
-    if (topElements.length === 0 && bottomElements.length === 0) {
-        return;
-    }
-
-    const viewRect = view.getBoundingClientRect();
-    const containerRect = container.getBoundingClientRect();
-
-    /**
-     * ┏---------------┓
-     * |      view     |
-     * ┗---------------┛ → viewRect.bottom
-     *   ┌-----------┐ --→ containerRect.top
-     *   | container |
-     *   └-----------┘
-     * ====== OR ======
-     *   ┌-----------┐
-     *   | container |
-     *   └-----------┘ --→ containerRect.bottom
-     * ┏---------------┓ → viewRect.top
-     * |      view     |
-     * ┗---------------┛
-     */
-    if (viewRect.bottom <= containerRect.top || containerRect.bottom <= viewRect.top) {
-        return;
-    }
-
-    const topContext: IStickyContextY[] = topElements.map(item => {
-        const rect = item.element.getBoundingClientRect();
-        const base = Number.parseFloat(item.element.style.top) || 0;
-        item.offset ??= 0;
-
-        return {
-            ...item,
-            rect,
-            base,
-            origin: {
-                top: rect.top - base,
-                bottom: rect.bottom - base,
-            },
-            current: {
-                top: rect.top,
-                bottom: rect.bottom,
-            },
-            target: {
-                top: null,
-                bottom: null,
-            },
-            style: {
-                top: null,
-                bottom: null,
-            }
-        };
-    });
-    const bottomContext: IStickyContextY[] = bottomElements.map(item => {
-        const rect = item.element.getBoundingClientRect();
-        const base = Number.parseFloat(item.element.style.bottom) || 0;
-        item.offset ??= 0;
-
-        return {
-            ...item,
-            rect,
-            base,
-            origin: {
-                top: rect.top + base,
-                bottom: rect.bottom + base,
-            },
-            current: {
-                top: rect.top,
-                bottom: rect.bottom,
-            },
-            target: {
-                top: null,
-                bottom: null,
-            },
-            style: {
-                top: null,
-                bottom: null,
-            }
-        };
-    });
-
-    let handleTop = false;
-    let handleBottom = false;
-
-    switch (true) {
-        /**
-         * ┏---------------┓ → viewRect.top
-         * |               |
-         * |      view     |
-         * | ┌-----------┐ | → containerRect.top
-         * ┗-╊-----------╊-┛ → viewRect.bottom
-         *   | container |
-         *   └-----------┘ --→ containerRect.bottom
-         */
-        case viewRect.top <= containerRect.top
-            && containerRect.top <= viewRect.bottom
-            && viewRect.top <= viewRect.bottom:
-            handleBottom = true;
-            break;
-
-        /**
-         * ┏---------------┓ → viewRect.top
-         * |      view     |
-         * | ┌-----------┐ | → containerRect.top
-         * | | container | |
-         * | └-----------┘ | → containerRect.bottom
-         * ┗---------------┛ → viewRect.bottom
-         */
-        case viewRect.top <= containerRect.top
-            && containerRect.bottom <= viewRect.bottom:
-            break;
-
-
-        /**
-         *   ┌-----------┐ --→ containerRect.top
-         * ┏-╊-----------╊-┓ → viewRect.top
-         * | |           | |}→ view
-         * ┗-╊-----------╊-┛ → viewRect.bottom
-         *   | container |
-         *   └-----------┘ --→ containerRect.bottom
-         */
-        case containerRect.top <= viewRect.top
-            && viewRect.bottom <= containerRect.bottom:
-            handleTop = true;
-            handleBottom = true;
-            break;
-
-        /**
-         *   ┌-----------┐ --→ containerRect.top
-         *   | container |
-         * ┏-╊-----------╊-┓ → viewRect.top
-         * | └-----------┘ | → containerRect.bottom
-         * |      view     |
-         * ┗-|-----------|-┛ → viewRect.bottom
-         */
-        case containerRect.top <= viewRect.top
-            && viewRect.top <= containerRect.bottom
-            && containerRect.bottom <= viewRect.bottom:
-            handleTop = true;
-            break;
-
-        default:
-            break;
-    }
-
-    if (handleTop) {
-        if (topContext.length > 0) {
-            topContext.reduceRight((next, current) => {
-                switch (true) {
-                    /**
-                     *   ┌-----------┐ --→ containerRect.top
-                     * ┏-╊-----------╊-┓ → viewRect.top
-                     * | | ┌┄┄┄┄┄┄┄┐ | | → current.target.top - current.offset
-                     * | | ├╌╌╌╌╌╌╌┤ | | → current.origin.top
-                     * | | └╌╌╌╌╌╌╌┘ | | → current.origin.bottom
-                     * | | ┌╌╌╌╌╌╌╌┐ | | → next.origin.top
-                     * | | └╌╌╌╌╌╌╌┘ | | → next.origin.bottom
-                     * ┗-╊-----------╊-┛ → viewRect.bottom
-                     *   └-----------┘ --→ containerRect.bottom
-                     */
-                    case viewRect.top <= (current.origin.top - current.offset):
-                        current.target.top = current.origin.top;
-                        current.target.bottom = current.origin.bottom;
-                        current.style.top = null;
-                        break;
-
-                    /**
-                     *   ┌-----------┐ --→ containerRect.top
-                     *   | ┌╌╌╌╌╌╌╌┐ | --→ current.origin.top
-                     *   | └╌╌╌╌╌╌╌┘ | --→ current.origin.bottom
-                     * ┏-╊-----------╊-┓ → viewRect.top
-                     * | | ┌-------┐ | | → current.target.top
-                     * | | └-------┘ | | → current.target.bottom
-                     * ┗-╊-----------╊-┛ → viewRect.bottom
-                     *   | container |
-                     *   └-----------┘ --→ containerRect.bottom
-                     */
-                    default:
-                        current.target.top = viewRect.top + current.offset;
-                        current.target.bottom = current.target.top + current.rect.height;
-                        if (next) {
-                            const nextTop = Math.min(next.target.top, next.origin.top);
-                            if (nextTop < current.target.bottom) {
-                                const diff = nextTop - current.target.bottom;
-                                current.target.top += diff;
-                                current.target.bottom += diff;
-                            }
-                        }
-                        current.style.top = current.base + (current.target.top - current.current.top);
-                        break;
-                }
-                return current;
-            }, null);
-        }
-    }
-    if (handleBottom) {
-        if (bottomContext.length > 0) {
-            bottomContext.reduce((last, current) => {
-                switch (true) {
-                    /**
-                     *   ┌-----------┐ --→ containerRect.top
-                     * ┏-╊-----------╊-┓ → viewRect.top
-                     * | | ┌╌╌╌╌╌╌╌┐ | | → last.origin.top
-                     * | | └╌╌╌╌╌╌╌┘ | | → last.origin.bottom
-                     * | | ┌╌╌╌╌╌╌╌┐ | | → current.origin.top
-                     * | | ├╌╌╌╌╌╌╌┤ | | → current.origin.bottom
-                     * | | └┄┄┄┄┄┄┄┘ | | → current.target.bottom + current.offset
-                     * ┗-╊-----------╊-┛ → viewRect.bottom
-                     *   └-----------┘ --→ containerRect.bottom
-                     */
-                    case (current.origin.bottom + current.offset) <= viewRect.bottom:
-                        current.target.top = current.origin.top;
-                        current.target.bottom = current.origin.bottom;
-                        current.style.bottom = null;
-                        break;
-
-                    /**
-                     *   ┌-----------┐ --→ containerRect.top
-                     * ┏-╊-----------╊-┓ → viewRect.top
-                     * | | ┌-------┐ | | → current.target.top
-                     * | | └-------┘ | | → current.target.bottom
-                     * ┗-╊-----------╊-┛ → viewRect.bottom
-                     *   | ┌╌╌╌╌╌╌╌┐ | --→ current.origin.top
-                     *   | └╌╌╌╌╌╌╌┘ | --→ current.origin.bottom
-                     *   | container |
-                     *   └-----------┘ --→ containerRect.bottom
-                     */
-                    default:
-                        current.target.bottom = viewRect.bottom - current.offset;
-                        current.target.top = current.target.bottom - current.rect.height;
-                        if (last) {
-                            const lastBottom = Math.max(last.target.bottom, last.origin.bottom);
-                            if (current.target.top < lastBottom) {
-                                const diff = lastBottom - current.target.top;
-                                current.target.top += diff;
-                                current.target.bottom += diff;
-                            }
-                        }
-                        current.style.bottom = current.base - (current.target.bottom - current.current.bottom);
-                        break;
-                }
-                return current;
-            }, null);
-        }
-    }
-
-    [...topContext, ...bottomContext].forEach(item => {
-        item.element.style.top = item.style.top ? `${item.style.top}px` : null;
-        item.element.style.bottom = item.style.bottom ? `${item.style.bottom}px` : null;
-    });
-}

+ 1 - 1
app/src/protyle/wysiwyg/index.ts

@@ -189,7 +189,7 @@ export class WYSIWYG {
         protyle.wysiwyg.element.querySelectorAll(".img--select, .av__cell--select, .av__row--select").forEach((item: HTMLElement) => {
         protyle.wysiwyg.element.querySelectorAll(".img--select, .av__cell--select, .av__row--select").forEach((item: HTMLElement) => {
             if (item.classList.contains("av__row--select") && !hasClosestByClassName(element, "av")) {
             if (item.classList.contains("av__row--select") && !hasClosestByClassName(element, "av")) {
                 item.classList.remove("av__row--select");
                 item.classList.remove("av__row--select");
-                item.querySelector(".av__check use").setAttribute("xlink:href", "#iconUncheck");
+                item.querySelector(".av__firstcol use").setAttribute("xlink:href", "#iconUncheck");
                 updateHeader(item);
                 updateHeader(item);
             } else {
             } else {
                 item.classList.remove("img--select", "av__cell--select");
                 item.classList.remove("img--select", "av__cell--select");