Add the onresize event handler to Element (#2479)

* Add the capability to handle resize event for web target

* Add the capability to handle resize event for desktop target

* Return all the sizes, not just the first one

* Fix conversion from platform to generic ResizedData for liveview

* Update the generated interpreter js code base

* Fix clippy warnings

* Fix inconsistent use of block_size and inline_size

* Rename `onresized` event to `onresize`

* Remove the the special-casing logic from the binding logic

* Propagating the resize events using CustomEvent

* Fix case convention in core ts

* revert changes to unified bindings

* Cleanup as suggested

* add a resize example

* Fix desktop resize events

* remove tracing from resize example

* use the raw resize entry so we can downcast on web

* remove unused ResizeEventDetail

---------

Co-authored-by: Evan Almloff <evanalmloff@gmail.com>
This commit is contained in:
ASR-ASUandEvan Almloff authored and GitHub committed 2024-08-15 01:23:49 +00:00
1 parent 4d6fb74e87
commit 2f49a89638
19 files changed
+442 -50

No files matched your search

+35 -2
View File
@@ -19,6 +19,8 @@ export class BaseInterpreter {
root: HTMLElement;
handler: EventListener;
resizeObserver: ResizeObserver;
nodes: Node[];
stack: Node[];
templates: {
@@ -39,8 +41,35 @@ export class BaseInterpreter {
this.stack = [root];
this.templates = {};
if (handler) {
this.handler = handler;
this.handler = handler;
}
handleResizeEvent(entry: ResizeObserverEntry) {
const target = entry.target;
let event = new CustomEvent<ResizeObserverEntry>("resize", {
bubbles: false,
detail: entry,
});
target.dispatchEvent(event);
}
createObserver(element: HTMLElement) {
// Lazily create the resize observer
if (!this.resizeObserver) {
this.resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
this.handleResizeEvent(entry);
}
});
}
this.resizeObserver.observe(element);
}
removeObserver(element: HTMLElement) {
if (this.resizeObserver) {
this.resizeObserver.unobserve(element);
}
}
@@ -59,6 +88,10 @@ export class BaseInterpreter {
}
element.addEventListener(event_name, this.handler);
}
if (event_name == "resize") {
this.createObserver(element);
}
}
removeListener(element: HTMLElement, event_name: string, bubbles: boolean) {
+3 -2
View File
@@ -98,6 +98,7 @@ export class NativeInterpreter extends JSChannel_ {
// make sure we pass the handler to the base interpreter
const handler: EventListener = (event) =>
this.handleEvent(event, event.type, true);
super.initialize(root, handler);
}
@@ -209,7 +210,7 @@ export class NativeInterpreter extends JSChannel_ {
// This is to support the prevent_default: "onclick" attribute that dioxus has had for a while, but is not necessary
// now that we expose preventDefault to the virtualdom on desktop
// Liveview will still need to use this
this.preventDefaults(event, target);
this.preventDefaults(event);
// liveview does not have synchronous event handling, so we need to send the event to the host
if (this.liveview) {
@@ -262,7 +263,7 @@ export class NativeInterpreter extends JSChannel_ {
// - prevent anchor tags from navigating
// - prevent buttons from submitting forms
// - let the virtualdom attempt to prevent the event
preventDefaults(event: Event, target: EventTarget) {
preventDefaults(event: Event) {
if (event.type === "submit") {
event.preventDefault();
}
+48
View File
@@ -58,6 +58,13 @@ export function serializeEvent(
extend({});
}
if (event instanceof CustomEvent) {
const detail = event.detail;
if (detail instanceof ResizeObserverEntry) {
extend(serializeResizeEventDetail(detail));
}
}
// safari is quirky and doesn't have TouchEvent
if (typeof TouchEvent !== "undefined" && event instanceof TouchEvent) {
extend(serializeTouchEvent(event));
@@ -96,6 +103,47 @@ export function serializeEvent(
return contents;
}
function toSerializableResizeObserverSize(
size: ResizeObserverSize,
is_inline_width: boolean
): Object {
return [
is_inline_width ? size.inlineSize : size.blockSize,
is_inline_width ? size.blockSize : size.inlineSize,
];
}
export function serializeResizeEventDetail(
detail: ResizeObserverEntry
): SerializedEvent {
let is_inline_width = true;
if (detail.target instanceof HTMLElement) {
let target_style = window.getComputedStyle(detail.target);
let target_writing_mode = target_style.getPropertyValue("writing-mode");
if (target_writing_mode !== "horizontal-tb") {
is_inline_width = false;
}
}
return {
border_box_size:
detail.borderBoxSize !== undefined
? toSerializableResizeObserverSize(
detail.borderBoxSize[0],
is_inline_width
)
: detail.contentRect,
content_box_size:
detail.contentBoxSize !== undefined
? toSerializableResizeObserverSize(
detail.contentBoxSize[0],
is_inline_width
)
: detail.contentRect,
content_rect: detail.contentRect,
};
}
function serializeInputEvent(
event: InputEvent,
target: EventTarget