76 lines
1.4 KiB
JavaScript
76 lines
1.4 KiB
JavaScript
import { Controller } from "@hotwired/stimulus"
|
|
import { computePosition, offset, flip, shift, autoUpdate } from "@floating-ui/dom"
|
|
|
|
export default class extends Controller {
|
|
static targets = ["origin", "floatable"]
|
|
|
|
static values = {
|
|
placement: {
|
|
type: String,
|
|
default: "bottom-start"
|
|
},
|
|
offset: {
|
|
type: Number,
|
|
default: 2
|
|
},
|
|
padding: {
|
|
type: Number,
|
|
default: 16
|
|
}
|
|
}
|
|
|
|
connect() {
|
|
this.cleanup = null
|
|
|
|
if (this.hasFloatableTarget) {
|
|
Object.assign(this.floatableTarget.style, {
|
|
position: "fixed",
|
|
left: "0",
|
|
top: "0",
|
|
})
|
|
}
|
|
}
|
|
|
|
disconnect() {
|
|
if (this.cleanup) {
|
|
this.cleanup()
|
|
this.cleanup = null
|
|
}
|
|
}
|
|
|
|
originTargetConnected() {
|
|
this.arrange()
|
|
}
|
|
|
|
floatableTargetConnected() {
|
|
this.arrange()
|
|
}
|
|
|
|
arrange() {
|
|
if (this.hasOriginTarget && this.hasFloatableTarget) {
|
|
if (this.cleanup) {
|
|
this.cleanup()
|
|
this.cleanup = null
|
|
return
|
|
}
|
|
|
|
this.cleanup = autoUpdate(this.originTarget, this.floatableTarget, () => {
|
|
computePosition(this.originTarget, this.floatableTarget, {
|
|
strategy: "fixed",
|
|
placement: this.placementValue,
|
|
middleware: [
|
|
offset(this.offsetValue),
|
|
flip(),
|
|
shift({ padding: this.paddingValue }),
|
|
]
|
|
}).then(({x, y }) => {
|
|
Object.assign(this.floatableTarget.style, {
|
|
left: `${x}px`,
|
|
top: `${y}px`,
|
|
})
|
|
})
|
|
})
|
|
}
|
|
}
|
|
}
|