-
Notifications
You must be signed in to change notification settings - Fork 1
/
tooltips.ts
92 lines (81 loc) · 3.4 KB
/
tooltips.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import { PrismEditor } from "./index.js"
import { createTemplate } from "./core.js"
import { cursorPosition } from "./extensions/cursor.js"
const template = /* @__PURE__ */ createTemplate(
'<div class=pce-tooltip style=z-index:5;top:auto;display:flex;overflow-x:clip><div>',
)
/**
* Moves to tooltip to align with the cursor and shows it.
* @param preferPlacingAboveCursor Whether the preferred position is above the cursor or not.
*/
export type ShowTooltip = (preferPlacingAboveCursor?: boolean) => void
/** Function removing the tooltip from the DOM. */
export type HideTooltip = () => void
/**
* Utility making it easy to add tooltips positioned on the cursor to an editor. Before you
* can show the tooltip, a {@link cursorPosition} extension must be added to the editor.
*
* This works by appending your tooltip to a flex container. You can style this container
* with the selector `.pce-tooltip` if needed. This container is then added to the editor's
* overlays. It also has `overflow-x: clip` to prevent your tooltip from overflowing in
* browsers that support it.
*
* If you want your tooltip to always be visible when scrolling horizontally, you can add
* `position: sticky` along with the `right` and `left` CSS properties to it.
*
* @param editor Editor you want to add the tooltip to.
* @param element Element for the tooltip.
* @param fixedWidth If false, the tooltip will shrink instead of getting offset to
* the left if there's not enough space to the right of the cursor. Defaults to `true`.
* @returns Show and hide functions.
*
* @example
* const [show, hide] = addTooltip(editor, element)
*/
export const addTooltip = (
editor: PrismEditor,
element: HTMLElement,
fixedWidth = true,
): [ShowTooltip, HideTooltip] => {
const container = template()
const style = container.style
const spacer = <HTMLDivElement>container.firstChild
container.append(element)
;(fixedWidth ? element : spacer).style.flexShrink = <any>0
return [
(above?: boolean) => {
let cursor = editor.extensions.cursor
if (cursor) {
let { left, right, top, bottom, height } = cursor.getPosition()
container.parentNode || editor.overlays.append(container)
spacer.style.width = (editor.options.rtl ? right : left) + "px"
let placeAbove =
!above == top > bottom && (above ? top : bottom) < container.clientHeight ? !above : above
style[placeAbove ? "bottom" : "top"] = height + (placeAbove ? bottom : top) + "px"
style[placeAbove ? "top" : "bottom"] = "auto"
}
},
() => container.remove(),
]
}
const observer =
window.ResizeObserver &&
/* @__PURE__ */ new ResizeObserver(e =>
e.forEach(entry => {
const el = entry.target
const wrapper = el.querySelector<HTMLDivElement>(".pce-wrapper")!
const style = getComputedStyle(wrapper)
wrapper.style.paddingBottom = `${
el.clientHeight - parseFloat(style.marginBottom) - parseFloat(style.lineHeight)
}px`
}),
)
/** Allows users to scroll past the last line in the editor by adding padding to the wrapper. */
export const addOverscroll = (editor: PrismEditor) => {
observer && observer.observe(editor.scrollContainer)
}
/** Removes the ability to scroll past the last line in the editor. */
export const removeOverscroll = (editor: PrismEditor) => {
observer && observer.unobserve(editor.scrollContainer)
editor.wrapper.style.paddingBottom = ""
}