mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-23 21:38:44 +08:00
chore: merge blocksuite source code (#9213)
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
import type { Disposable } from '@blocksuite/global/utils';
|
||||
import {
|
||||
autoPlacement,
|
||||
autoUpdate,
|
||||
computePosition,
|
||||
offset,
|
||||
type Rect,
|
||||
shift,
|
||||
size,
|
||||
} from '@floating-ui/dom';
|
||||
|
||||
export function listenClickAway(
|
||||
element: HTMLElement,
|
||||
onClickAway: () => void
|
||||
): Disposable {
|
||||
const callback = (event: MouseEvent) => {
|
||||
const inside = event.composedPath().includes(element);
|
||||
if (!inside) {
|
||||
onClickAway();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('click', callback);
|
||||
|
||||
return {
|
||||
dispose: () => {
|
||||
document.removeEventListener('click', callback);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
type Display = 'show' | 'hidden';
|
||||
|
||||
const ATTR_SHOW = 'data-show';
|
||||
/**
|
||||
* Using attribute 'data-show' to control popper visibility.
|
||||
*
|
||||
* ```css
|
||||
* selector {
|
||||
* display: none;
|
||||
* }
|
||||
* selector[data-show] {
|
||||
* display: block;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export function createButtonPopper(
|
||||
reference: HTMLElement,
|
||||
popperElement: HTMLElement,
|
||||
stateUpdated: (state: { display: Display }) => void = () => {
|
||||
/** DEFAULT EMPTY FUNCTION */
|
||||
},
|
||||
{
|
||||
mainAxis,
|
||||
crossAxis,
|
||||
rootBoundary,
|
||||
ignoreShift,
|
||||
}: {
|
||||
mainAxis?: number;
|
||||
crossAxis?: number;
|
||||
rootBoundary?: Rect | (() => Rect | undefined);
|
||||
ignoreShift?: boolean;
|
||||
} = {}
|
||||
) {
|
||||
let display: Display = 'hidden';
|
||||
let cleanup: (() => void) | void;
|
||||
|
||||
const originMaxHeight = window.getComputedStyle(popperElement).maxHeight;
|
||||
|
||||
function compute() {
|
||||
const overflowOptions = {
|
||||
rootBoundary:
|
||||
typeof rootBoundary === 'function' ? rootBoundary() : rootBoundary,
|
||||
};
|
||||
|
||||
computePosition(reference, popperElement, {
|
||||
middleware: [
|
||||
offset({
|
||||
mainAxis: mainAxis ?? 14,
|
||||
crossAxis: crossAxis ?? 0,
|
||||
}),
|
||||
autoPlacement({
|
||||
allowedPlacements: ['top', 'bottom'],
|
||||
...overflowOptions,
|
||||
}),
|
||||
shift(overflowOptions),
|
||||
size({
|
||||
...overflowOptions,
|
||||
apply({ availableHeight }) {
|
||||
popperElement.style.maxHeight = originMaxHeight
|
||||
? `min(${originMaxHeight}, ${availableHeight}px)`
|
||||
: `${availableHeight}px`;
|
||||
},
|
||||
}),
|
||||
],
|
||||
})
|
||||
.then(({ x, y, middlewareData: data }) => {
|
||||
if (!ignoreShift) {
|
||||
x += data.shift?.x ?? 0;
|
||||
y += data.shift?.y ?? 0;
|
||||
}
|
||||
Object.assign(popperElement.style, {
|
||||
position: 'absolute',
|
||||
zIndex: 1,
|
||||
left: `${x}px`,
|
||||
top: `${y}px`,
|
||||
});
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
|
||||
const show = (force = false) => {
|
||||
const displayed = display === 'show';
|
||||
|
||||
if (displayed && !force) return;
|
||||
|
||||
if (!displayed) {
|
||||
popperElement.setAttribute(ATTR_SHOW, '');
|
||||
display = 'show';
|
||||
stateUpdated({ display });
|
||||
}
|
||||
|
||||
cleanup?.();
|
||||
cleanup = autoUpdate(reference, popperElement, compute, {
|
||||
animationFrame: true,
|
||||
});
|
||||
};
|
||||
|
||||
const hide = () => {
|
||||
if (display === 'hidden') return;
|
||||
popperElement.removeAttribute(ATTR_SHOW);
|
||||
display = 'hidden';
|
||||
stateUpdated({ display });
|
||||
cleanup?.();
|
||||
};
|
||||
|
||||
const toggle = () => {
|
||||
if (popperElement.hasAttribute(ATTR_SHOW)) {
|
||||
hide();
|
||||
} else {
|
||||
show();
|
||||
}
|
||||
};
|
||||
|
||||
const clickAway = listenClickAway(reference, () => hide());
|
||||
|
||||
return {
|
||||
get state() {
|
||||
return display;
|
||||
},
|
||||
show,
|
||||
hide,
|
||||
toggle,
|
||||
dispose: () => {
|
||||
cleanup?.();
|
||||
clickAway.dispose();
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user