Svelte: Fix calling DOM API functions on the actual elements
This commit is contained in:
parent
0019340096
commit
fb10e5194e
|
|
@ -321,7 +321,6 @@ impl NodeGraphMessageHandler {
|
||||||
disabled: network.disabled.contains(id),
|
disabled: network.disabled.contains(id),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
log::debug!("Frontend Nodes:\n{:#?}\n\nLinks:\n{:#?}", nodes, links);
|
|
||||||
responses.push_back(FrontendMessage::UpdateNodeGraph { nodes, links }.into());
|
responses.push_back(FrontendMessage::UpdateNodeGraph { nodes, links }.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -423,7 +422,6 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &mut dyn Iterator<Item = &
|
||||||
input_node,
|
input_node,
|
||||||
input_node_connector_index,
|
input_node_connector_index,
|
||||||
} => {
|
} => {
|
||||||
log::debug!("Connect primary output from node {output_node} to input of index {input_node_connector_index} on node {input_node}.");
|
|
||||||
let node_id = input_node;
|
let node_id = input_node;
|
||||||
|
|
||||||
let Some(network) = self.get_active_network(document) else {
|
let Some(network) = self.get_active_network(document) else {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
const dialog = getContext<DialogState>("dialog");
|
const dialog = getContext<DialogState>("dialog");
|
||||||
|
|
||||||
let dialogModal: FloatingMenu;
|
let self: FloatingMenu;
|
||||||
|
|
||||||
export function dismiss() {
|
export function dismiss() {
|
||||||
dialog.dismissDialog();
|
dialog.dismissDialog();
|
||||||
|
|
@ -19,12 +19,12 @@
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
// Focus the first button in the popup
|
// Focus the first button in the popup
|
||||||
const emphasizedOrFirstButton = (dialogModal.div().querySelector("[data-emphasized]") || dialogModal.div().querySelector("[data-text-button]") || undefined) as HTMLButtonElement | undefined;
|
const emphasizedOrFirstButton = (self.div().querySelector("[data-emphasized]") || self.div().querySelector("[data-text-button]") || undefined) as HTMLButtonElement | undefined;
|
||||||
emphasizedOrFirstButton?.focus();
|
emphasizedOrFirstButton?.focus();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<FloatingMenu open={true} class="dialog-modal" type="Dialog" direction="Center" bind:this={dialogModal} data-dialog-modal>
|
<FloatingMenu open={true} class="dialog-modal" type="Dialog" direction="Center" bind:this={self} data-dialog-modal>
|
||||||
<LayoutRow>
|
<LayoutRow>
|
||||||
<LayoutCol class="icon-column">
|
<LayoutCol class="icon-column">
|
||||||
<!-- `$dialog.icon` class exists to provide special sizing in CSS to specific icons -->
|
<!-- `$dialog.icon` class exists to provide special sizing in CSS to specific icons -->
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
import TextLabel from "@/components/widgets/labels/TextLabel.svelte";
|
import TextLabel from "@/components/widgets/labels/TextLabel.svelte";
|
||||||
import UserInputLabel from "@/components/widgets/labels/UserInputLabel.svelte";
|
import UserInputLabel from "@/components/widgets/labels/UserInputLabel.svelte";
|
||||||
|
|
||||||
let floatingMenu: FloatingMenu;
|
let self: FloatingMenu;
|
||||||
let scroller: LayoutCol;
|
let scroller: LayoutCol;
|
||||||
|
|
||||||
// emits: ["update:open", "update:activeEntry", "naturalWidth"],
|
// emits: ["update:open", "update:activeEntry", "naturalWidth"],
|
||||||
|
|
@ -35,8 +35,8 @@
|
||||||
// Called only when `open` is changed from outside this component (with v-model)
|
// Called only when `open` is changed from outside this component (with v-model)
|
||||||
$: watchOpen(open);
|
$: watchOpen(open);
|
||||||
$: dispatch("open", isOpen);
|
$: dispatch("open", isOpen);
|
||||||
$: watchEntries(entries, floatingMenu);
|
$: watchEntries(entries, self);
|
||||||
$: watchDrawIcon(drawIcon, floatingMenu);
|
$: watchDrawIcon(drawIcon, self);
|
||||||
$: virtualScrollingTotalHeight = entries.length === 0 ? 0 : entries[0].length * virtualScrollingEntryHeight;
|
$: virtualScrollingTotalHeight = entries.length === 0 ? 0 : entries[0].length * virtualScrollingEntryHeight;
|
||||||
$: virtualScrollingStartIndex = Math.floor(virtualScrollingEntriesStart / virtualScrollingEntryHeight) || 0;
|
$: virtualScrollingStartIndex = Math.floor(virtualScrollingEntriesStart / virtualScrollingEntryHeight) || 0;
|
||||||
$: virtualScrollingEndIndex = entries.length === 0 ? 0 : Math.min(entries[0].length, virtualScrollingStartIndex + 1 + 400 / virtualScrollingEntryHeight);
|
$: virtualScrollingEndIndex = entries.length === 0 ? 0 : Math.min(entries[0].length, virtualScrollingStartIndex + 1 + 400 / virtualScrollingEntryHeight);
|
||||||
|
|
@ -48,12 +48,12 @@
|
||||||
|
|
||||||
// TODO: Svelte: fix infinite loop and reenable
|
// TODO: Svelte: fix infinite loop and reenable
|
||||||
function watchEntries(_: MenuListEntry[][], floatingMenu: FloatingMenu) {
|
function watchEntries(_: MenuListEntry[][], floatingMenu: FloatingMenu) {
|
||||||
// floatingMenu?.measureAndEmitNaturalWidth();
|
// floatingMenu?.div().measureAndEmitNaturalWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Svelte: fix infinite loop and reenable
|
// TODO: Svelte: fix infinite loop and reenable
|
||||||
function watchDrawIcon(_: boolean, floatingMenu: FloatingMenu) {
|
function watchDrawIcon(_: boolean, floatingMenu: FloatingMenu) {
|
||||||
// floatingMenu?.measureAndEmitNaturalWidth();
|
// floatingMenu?.div().measureAndEmitNaturalWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onScroll(e: Event) {
|
function onScroll(e: Event) {
|
||||||
|
|
@ -198,7 +198,7 @@
|
||||||
{direction}
|
{direction}
|
||||||
{minWidth}
|
{minWidth}
|
||||||
scrollableY={scrollableY && virtualScrollingEntryHeight === 0}
|
scrollableY={scrollableY && virtualScrollingEntryHeight === 0}
|
||||||
bind:this={floatingMenu}
|
bind:this={self}
|
||||||
>
|
>
|
||||||
<!-- If we put the scrollableY on the layoutcol for non-font dropdowns then for some reason it always creates a tiny scrollbar.
|
<!-- If we put the scrollableY on the layoutcol for non-font dropdowns then for some reason it always creates a tiny scrollbar.
|
||||||
However when we are using the virtual scrolling then we need the layoutcol to be scrolling so we can bind the events without using $refs. -->
|
However when we are using the virtual scrolling then we need the layoutcol to be scrolling so we can bind the events without using $refs. -->
|
||||||
|
|
|
||||||
|
|
@ -132,10 +132,10 @@
|
||||||
// Required to correctly position content when scrolled (it has a `position: fixed` to prevent clipping)
|
// Required to correctly position content when scrolled (it has a `position: fixed` to prevent clipping)
|
||||||
// We use `.style` on a ref (instead of a `:style` Vue binding) because the binding causes the `updated()` hook to call the function we're in recursively forever
|
// We use `.style` on a ref (instead of a `:style` Vue binding) because the binding causes the `updated()` hook to call the function we're in recursively forever
|
||||||
const tailOffset = type === "Popover" ? 10 : 0;
|
const tailOffset = type === "Popover" ? 10 : 0;
|
||||||
if (direction === "Bottom") floatingMenuContent.style.top = `${tailOffset + floatingMenuBounds.top}px`;
|
if (direction === "Bottom") floatingMenuContent.div().style.top = `${tailOffset + floatingMenuBounds.top}px`;
|
||||||
if (direction === "Top") floatingMenuContent.style.bottom = `${tailOffset + floatingMenuBounds.bottom}px`;
|
if (direction === "Top") floatingMenuContent.div().style.bottom = `${tailOffset + floatingMenuBounds.bottom}px`;
|
||||||
if (direction === "Right") floatingMenuContent.style.left = `${tailOffset + floatingMenuBounds.left}px`;
|
if (direction === "Right") floatingMenuContent.div().style.left = `${tailOffset + floatingMenuBounds.left}px`;
|
||||||
if (direction === "Left") floatingMenuContent.style.right = `${tailOffset + floatingMenuBounds.right}px`;
|
if (direction === "Left") floatingMenuContent.div().style.right = `${tailOffset + floatingMenuBounds.right}px`;
|
||||||
|
|
||||||
// Required to correctly position tail when scrolled (it has a `position: fixed` to prevent clipping)
|
// Required to correctly position tail when scrolled (it has a `position: fixed` to prevent clipping)
|
||||||
// We use `.style` on a ref (instead of a `:style` Vue binding) because the binding causes the `updated()` hook to call the function we're in recursively forever
|
// We use `.style` on a ref (instead of a `:style` Vue binding) because the binding causes the `updated()` hook to call the function we're in recursively forever
|
||||||
|
|
@ -154,11 +154,11 @@
|
||||||
|
|
||||||
// We use `.style` on a ref (instead of a `:style` Vue binding) because the binding causes the `updated()` hook to call the function we're in recursively forever
|
// We use `.style` on a ref (instead of a `:style` Vue binding) because the binding causes the `updated()` hook to call the function we're in recursively forever
|
||||||
if (floatingMenuContentBounds.left - windowEdgeMargin <= workspaceBounds.left) {
|
if (floatingMenuContentBounds.left - windowEdgeMargin <= workspaceBounds.left) {
|
||||||
floatingMenuContent.style.left = `${windowEdgeMargin}px`;
|
floatingMenuContent.div().style.left = `${windowEdgeMargin}px`;
|
||||||
if (workspaceBounds.left + floatingMenuContainerBounds.left === 12) zeroedBorderHorizontal = "Left";
|
if (workspaceBounds.left + floatingMenuContainerBounds.left === 12) zeroedBorderHorizontal = "Left";
|
||||||
}
|
}
|
||||||
if (floatingMenuContentBounds.right + windowEdgeMargin >= workspaceBounds.right) {
|
if (floatingMenuContentBounds.right + windowEdgeMargin >= workspaceBounds.right) {
|
||||||
floatingMenuContent.style.right = `${windowEdgeMargin}px`;
|
floatingMenuContent.div().style.right = `${windowEdgeMargin}px`;
|
||||||
if (workspaceBounds.right - floatingMenuContainerBounds.right === 12) zeroedBorderHorizontal = "Right";
|
if (workspaceBounds.right - floatingMenuContainerBounds.right === 12) zeroedBorderHorizontal = "Right";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -167,11 +167,11 @@
|
||||||
|
|
||||||
// We use `.style` on a ref (instead of a `:style` Vue binding) because the binding causes the `updated()` hook to call the function we're in recursively forever
|
// We use `.style` on a ref (instead of a `:style` Vue binding) because the binding causes the `updated()` hook to call the function we're in recursively forever
|
||||||
if (floatingMenuContentBounds.top - windowEdgeMargin <= workspaceBounds.top) {
|
if (floatingMenuContentBounds.top - windowEdgeMargin <= workspaceBounds.top) {
|
||||||
floatingMenuContent.style.top = `${windowEdgeMargin}px`;
|
floatingMenuContent.div().style.top = `${windowEdgeMargin}px`;
|
||||||
if (workspaceBounds.top + floatingMenuContainerBounds.top === 12) zeroedBorderVertical = "Top";
|
if (workspaceBounds.top + floatingMenuContainerBounds.top === 12) zeroedBorderVertical = "Top";
|
||||||
}
|
}
|
||||||
if (floatingMenuContentBounds.bottom + windowEdgeMargin >= workspaceBounds.bottom) {
|
if (floatingMenuContentBounds.bottom + windowEdgeMargin >= workspaceBounds.bottom) {
|
||||||
floatingMenuContent.style.bottom = `${windowEdgeMargin}px`;
|
floatingMenuContent.div().style.bottom = `${windowEdgeMargin}px`;
|
||||||
if (workspaceBounds.bottom - floatingMenuContainerBounds.bottom === 12) zeroedBorderVertical = "Bottom";
|
if (workspaceBounds.bottom - floatingMenuContainerBounds.bottom === 12) zeroedBorderVertical = "Bottom";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -181,16 +181,16 @@
|
||||||
// We use `.style` on a ref (instead of a `:style` Vue binding) because the binding causes the `updated()` hook to call the function we're in recursively forever
|
// We use `.style` on a ref (instead of a `:style` Vue binding) because the binding causes the `updated()` hook to call the function we're in recursively forever
|
||||||
switch (`${zeroedBorderVertical}${zeroedBorderHorizontal}`) {
|
switch (`${zeroedBorderVertical}${zeroedBorderHorizontal}`) {
|
||||||
case "TopLeft":
|
case "TopLeft":
|
||||||
floatingMenuContent.style.borderTopLeftRadius = "0";
|
floatingMenuContent.div().style.borderTopLeftRadius = "0";
|
||||||
break;
|
break;
|
||||||
case "TopRight":
|
case "TopRight":
|
||||||
floatingMenuContent.style.borderTopRightRadius = "0";
|
floatingMenuContent.div().style.borderTopRightRadius = "0";
|
||||||
break;
|
break;
|
||||||
case "BottomLeft":
|
case "BottomLeft":
|
||||||
floatingMenuContent.style.borderBottomLeftRadius = "0";
|
floatingMenuContent.div().style.borderBottomLeftRadius = "0";
|
||||||
break;
|
break;
|
||||||
case "BottomRight":
|
case "BottomRight":
|
||||||
floatingMenuContent.style.borderBottomRightRadius = "0";
|
floatingMenuContent.div().style.borderBottomRightRadius = "0";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
@ -219,7 +219,7 @@
|
||||||
|
|
||||||
// Measure the width of the floating menu content element, if it's currently visible
|
// Measure the width of the floating menu content element, if it's currently visible
|
||||||
// The result will be `undefined` if the menu is invisible, perhaps because an ancestor component is hidden with a falsy `v-if` condition
|
// The result will be `undefined` if the menu is invisible, perhaps because an ancestor component is hidden with a falsy `v-if` condition
|
||||||
const naturalWidth: number | undefined = floatingMenuContent?.clientWidth;
|
const naturalWidth: number | undefined = floatingMenuContent?.div().clientWidth;
|
||||||
|
|
||||||
// Turn off measuring mode for the component, which triggers another call to the `updated()` Vue event, so we can turn off the protection after that has happened
|
// Turn off measuring mode for the component, which triggers another call to the `updated()` Vue event, so we can turn off the protection after that has happened
|
||||||
measuringOngoing = false;
|
measuringOngoing = false;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
export let scrollableX: boolean = false;
|
export let scrollableX: boolean = false;
|
||||||
export let scrollableY: boolean = false;
|
export let scrollableY: boolean = false;
|
||||||
|
|
||||||
let divElement: HTMLDivElement;
|
let self: HTMLDivElement;
|
||||||
|
|
||||||
$: extraClasses = Object.entries(classes)
|
$: extraClasses = Object.entries(classes)
|
||||||
.flatMap((classAndState) => (classAndState[1] ? [classAndState[0]] : []))
|
.flatMap((classAndState) => (classAndState[1] ? [classAndState[0]] : []))
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
.join(" ");
|
.join(" ");
|
||||||
|
|
||||||
export function div(): HTMLDivElement {
|
export function div(): HTMLDivElement {
|
||||||
return divElement;
|
return self;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -29,21 +29,52 @@
|
||||||
class:scrollable-y={scrollableY}
|
class:scrollable-y={scrollableY}
|
||||||
style={`${styleName} ${extraStyles}`.trim() || undefined}
|
style={`${styleName} ${extraStyles}`.trim() || undefined}
|
||||||
title={tooltip}
|
title={tooltip}
|
||||||
bind:this={divElement}
|
bind:this={self}
|
||||||
|
on:focus
|
||||||
|
on:blur
|
||||||
|
on:fullscreenchange
|
||||||
|
on:fullscreenerror
|
||||||
|
on:scroll
|
||||||
|
on:cut
|
||||||
|
on:copy
|
||||||
|
on:paste
|
||||||
|
on:keydown
|
||||||
|
on:keypress
|
||||||
|
on:keyup
|
||||||
|
on:auxclick
|
||||||
on:click
|
on:click
|
||||||
|
on:contextmenu
|
||||||
on:dblclick
|
on:dblclick
|
||||||
|
on:mousedown
|
||||||
|
on:mouseenter
|
||||||
|
on:mouseleave
|
||||||
|
on:mousemove
|
||||||
|
on:mouseover
|
||||||
|
on:mouseout
|
||||||
|
on:mouseup
|
||||||
|
on:select
|
||||||
|
on:wheel
|
||||||
|
on:drag
|
||||||
|
on:dragend
|
||||||
|
on:dragenter
|
||||||
|
on:dragstart
|
||||||
|
on:dragleave
|
||||||
|
on:dragover
|
||||||
|
on:drop
|
||||||
|
on:touchcancel
|
||||||
|
on:touchend
|
||||||
|
on:touchmove
|
||||||
|
on:touchstart
|
||||||
|
on:pointerover
|
||||||
|
on:pointerenter
|
||||||
on:pointerdown
|
on:pointerdown
|
||||||
on:pointermove
|
on:pointermove
|
||||||
on:pointerup
|
on:pointerup
|
||||||
on:dragleave
|
on:pointercancel
|
||||||
on:dragover
|
on:pointerout
|
||||||
on:dragstart
|
on:pointerleave
|
||||||
on:dragend
|
on:gotpointercapture
|
||||||
on:drop
|
on:lostpointercapture
|
||||||
on:wheel
|
|
||||||
on:scroll
|
|
||||||
on:focus
|
|
||||||
on:blur
|
|
||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
export let scrollableX: boolean = false;
|
export let scrollableX: boolean = false;
|
||||||
export let scrollableY: boolean = false;
|
export let scrollableY: boolean = false;
|
||||||
|
|
||||||
let divElement: HTMLDivElement;
|
let self: HTMLDivElement;
|
||||||
|
|
||||||
$: extraClasses = Object.entries(classes)
|
$: extraClasses = Object.entries(classes)
|
||||||
.flatMap((classAndState) => (classAndState[1] ? [classAndState[0]] : []))
|
.flatMap((classAndState) => (classAndState[1] ? [classAndState[0]] : []))
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
.join(" ");
|
.join(" ");
|
||||||
|
|
||||||
export function div(): HTMLDivElement {
|
export function div(): HTMLDivElement {
|
||||||
return divElement;
|
return self;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -29,21 +29,52 @@
|
||||||
class:scrollable-y={scrollableY}
|
class:scrollable-y={scrollableY}
|
||||||
style={`${styleName} ${extraStyles}`.trim() || undefined}
|
style={`${styleName} ${extraStyles}`.trim() || undefined}
|
||||||
title={tooltip}
|
title={tooltip}
|
||||||
bind:this={divElement}
|
bind:this={self}
|
||||||
|
on:focus
|
||||||
|
on:blur
|
||||||
|
on:fullscreenchange
|
||||||
|
on:fullscreenerror
|
||||||
|
on:scroll
|
||||||
|
on:cut
|
||||||
|
on:copy
|
||||||
|
on:paste
|
||||||
|
on:keydown
|
||||||
|
on:keypress
|
||||||
|
on:keyup
|
||||||
|
on:auxclick
|
||||||
on:click
|
on:click
|
||||||
|
on:contextmenu
|
||||||
on:dblclick
|
on:dblclick
|
||||||
|
on:mousedown
|
||||||
|
on:mouseenter
|
||||||
|
on:mouseleave
|
||||||
|
on:mousemove
|
||||||
|
on:mouseover
|
||||||
|
on:mouseout
|
||||||
|
on:mouseup
|
||||||
|
on:select
|
||||||
|
on:wheel
|
||||||
|
on:drag
|
||||||
|
on:dragend
|
||||||
|
on:dragenter
|
||||||
|
on:dragstart
|
||||||
|
on:dragleave
|
||||||
|
on:dragover
|
||||||
|
on:drop
|
||||||
|
on:touchcancel
|
||||||
|
on:touchend
|
||||||
|
on:touchmove
|
||||||
|
on:touchstart
|
||||||
|
on:pointerover
|
||||||
|
on:pointerenter
|
||||||
on:pointerdown
|
on:pointerdown
|
||||||
on:pointermove
|
on:pointermove
|
||||||
on:pointerup
|
on:pointerup
|
||||||
on:dragleave
|
on:pointercancel
|
||||||
on:dragover
|
on:pointerout
|
||||||
on:dragstart
|
on:pointerleave
|
||||||
on:dragend
|
on:gotpointercapture
|
||||||
on:drop
|
on:lostpointercapture
|
||||||
on:wheel
|
|
||||||
on:scroll
|
|
||||||
on:focus
|
|
||||||
on:blur
|
|
||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,9 @@
|
||||||
import { type Editor } from "@/wasm-communication/editor";
|
import { type Editor } from "@/wasm-communication/editor";
|
||||||
import { type DocumentState } from "@/state-providers/document";
|
import { type DocumentState } from "@/state-providers/document";
|
||||||
|
|
||||||
let self: LayoutCol;
|
|
||||||
let rulerHorizontal: CanvasRuler;
|
let rulerHorizontal: CanvasRuler;
|
||||||
let rulerVertical: CanvasRuler;
|
let rulerVertical: CanvasRuler;
|
||||||
let canvasDiv: HTMLDivElement;
|
let canvasContainer: HTMLDivElement;
|
||||||
|
|
||||||
const editor = getContext<Editor>("editor");
|
const editor = getContext<Editor>("editor");
|
||||||
const document = getContext<DocumentState>("document");
|
const document = getContext<DocumentState>("document");
|
||||||
|
|
@ -116,7 +115,7 @@
|
||||||
function canvasPointerDown(e: PointerEvent) {
|
function canvasPointerDown(e: PointerEvent) {
|
||||||
const onEditbox = e.target instanceof HTMLDivElement && e.target.contentEditable;
|
const onEditbox = e.target instanceof HTMLDivElement && e.target.contentEditable;
|
||||||
|
|
||||||
if (!onEditbox) canvasDiv?.setPointerCapture(e.pointerId);
|
if (!onEditbox) canvasContainer?.setPointerCapture(e.pointerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update rendered SVGs
|
// Update rendered SVGs
|
||||||
|
|
@ -127,7 +126,7 @@
|
||||||
await tick();
|
await tick();
|
||||||
|
|
||||||
if (textInput) {
|
if (textInput) {
|
||||||
const foreignObject = canvasDiv.getElementsByTagName("foreignObject")[0] as SVGForeignObjectElement;
|
const foreignObject = canvasContainer.getElementsByTagName("foreignObject")[0] as SVGForeignObjectElement;
|
||||||
if (foreignObject.children.length > 0) return;
|
if (foreignObject.children.length > 0) return;
|
||||||
|
|
||||||
const addedInput = foreignObject.appendChild(textInput);
|
const addedInput = foreignObject.appendChild(textInput);
|
||||||
|
|
@ -285,8 +284,8 @@
|
||||||
// Resize elements to render the new viewport size
|
// Resize elements to render the new viewport size
|
||||||
export function viewportResize() {
|
export function viewportResize() {
|
||||||
// Resize the canvas
|
// Resize the canvas
|
||||||
canvasSvgWidth = Math.ceil(parseFloat(getComputedStyle(canvasDiv).width));
|
canvasSvgWidth = Math.ceil(parseFloat(getComputedStyle(canvasContainer).width));
|
||||||
canvasSvgHeight = Math.ceil(parseFloat(getComputedStyle(canvasDiv).height));
|
canvasSvgHeight = Math.ceil(parseFloat(getComputedStyle(canvasContainer).height));
|
||||||
|
|
||||||
// Resize the rulers
|
// Resize the rulers
|
||||||
rulerHorizontal?.resize();
|
rulerHorizontal?.resize();
|
||||||
|
|
@ -382,7 +381,7 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<LayoutCol class="document" bind:this={self}>
|
<LayoutCol class="document">
|
||||||
<LayoutRow class="options-bar" scrollableX={true}>
|
<LayoutRow class="options-bar" scrollableX={true}>
|
||||||
<WidgetLayout layout={$document.documentModeLayout} />
|
<WidgetLayout layout={$document.documentModeLayout} />
|
||||||
<WidgetLayout layout={$document.toolOptionsLayout} />
|
<WidgetLayout layout={$document.toolOptionsLayout} />
|
||||||
|
|
@ -422,7 +421,7 @@
|
||||||
y={cursorTop}
|
y={cursorTop}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="canvas" on:pointerdown={(e) => canvasPointerDown(e)} on:dragover={(e) => e.preventDefault()} on:drop={(e) => pasteFile(e)} bind:this={canvasDiv} data-canvas>
|
<div class="canvas" on:pointerdown={(e) => canvasPointerDown(e)} on:dragover={(e) => e.preventDefault()} on:drop={(e) => pasteFile(e)} bind:this={canvasContainer} data-canvas>
|
||||||
<svg class="artboards" style:width={canvasWidthCSS} style:height={canvasHeightCSS}>
|
<svg class="artboards" style:width={canvasWidthCSS} style:height={canvasHeightCSS}>
|
||||||
{@html artboardSvg}
|
{@html artboardSvg}
|
||||||
</svg>
|
</svg>
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@
|
||||||
|
|
||||||
await tick();
|
await tick();
|
||||||
|
|
||||||
const textInput: HTMLInputElement | undefined = list?.querySelector("[data-text-input]:not([disabled])") || undefined;
|
const textInput = (list?.div().querySelector("[data-text-input]:not([disabled])") || undefined) as HTMLInputElement | undefined;
|
||||||
textInput?.select();
|
textInput?.select();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,7 +169,7 @@
|
||||||
|
|
||||||
function calculateDragIndex(tree: LayoutCol, clientY: number, select?: () => void): DraggingData {
|
function calculateDragIndex(tree: LayoutCol, clientY: number, select?: () => void): DraggingData {
|
||||||
const treeChildren = tree.div().children;
|
const treeChildren = tree.div().children;
|
||||||
const treeOffset = tree.getBoundingClientRect().top;
|
const treeOffset = tree.div().getBoundingClientRect().top;
|
||||||
|
|
||||||
// Closest distance to the middle of the row along the Y axis
|
// Closest distance to the middle of the row along the Y axis
|
||||||
let closest = Infinity;
|
let closest = Infinity;
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@
|
||||||
let zoomFactor = 1 + Math.abs(scrollY) * WHEEL_RATE;
|
let zoomFactor = 1 + Math.abs(scrollY) * WHEEL_RATE;
|
||||||
if (scrollY > 0) zoomFactor = 1 / zoomFactor;
|
if (scrollY > 0) zoomFactor = 1 / zoomFactor;
|
||||||
|
|
||||||
const { x, y, width, height } = graph.getBoundingClientRect();
|
const { x, y, width, height } = graph.div().getBoundingClientRect();
|
||||||
|
|
||||||
transform.scale *= zoomFactor;
|
transform.scale *= zoomFactor;
|
||||||
|
|
||||||
|
|
@ -222,7 +222,7 @@
|
||||||
|
|
||||||
// Handle the add node popup on right click
|
// Handle the add node popup on right click
|
||||||
if (e.button === 2) {
|
if (e.button === 2) {
|
||||||
const graphBounds = graph.getBoundingClientRect();
|
const graphBounds = graph.div().getBoundingClientRect();
|
||||||
nodeListLocation = {
|
nodeListLocation = {
|
||||||
x: Math.round(((e.clientX - graphBounds.x) / transform.scale - transform.x) / GRID_SIZE),
|
x: Math.round(((e.clientX - graphBounds.x) / transform.scale - transform.x) / GRID_SIZE),
|
||||||
y: Math.round(((e.clientY - graphBounds.y) / transform.scale - transform.y) / GRID_SIZE),
|
y: Math.round(((e.clientY - graphBounds.y) / transform.scale - transform.y) / GRID_SIZE),
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
export let sharpRightCorners = false;
|
export let sharpRightCorners = false;
|
||||||
export let placeholder: string | undefined = undefined;
|
export let placeholder: string | undefined = undefined;
|
||||||
|
|
||||||
let input: HTMLInputElement | HTMLTextAreaElement;
|
let inputOrTextarea: HTMLInputElement | HTMLTextAreaElement;
|
||||||
let id = `${Math.random()}`.substring(2);
|
let id = `${Math.random()}`.substring(2);
|
||||||
let macKeyboardLayout = platformIsMac();
|
let macKeyboardLayout = platformIsMac();
|
||||||
let inputValue = value;
|
let inputValue = value;
|
||||||
|
|
@ -40,20 +40,28 @@
|
||||||
export function selectAllText(currentText: string) {
|
export function selectAllText(currentText: string) {
|
||||||
// Setting the value directly is required to make `input.select()` work
|
// Setting the value directly is required to make `input.select()` work
|
||||||
// TODO: Svelte: Test if the above message is still true
|
// TODO: Svelte: Test if the above message is still true
|
||||||
input.value = currentText;
|
inputOrTextarea.value = currentText;
|
||||||
input.select();
|
inputOrTextarea.select();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function focus() {
|
||||||
|
inputOrTextarea.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function unFocus() {
|
export function unFocus() {
|
||||||
input.blur();
|
inputOrTextarea.blur();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getInputElementValue(): string {
|
export function getValue(): string {
|
||||||
return input.value;
|
return inputOrTextarea.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setInputElementValue(value: string) {
|
export function setInputElementValue(value: string) {
|
||||||
input.value = value;
|
inputOrTextarea.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function element(): HTMLInputElement | HTMLTextAreaElement {
|
||||||
|
return inputOrTextarea;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -68,7 +76,7 @@
|
||||||
{disabled}
|
{disabled}
|
||||||
{placeholder}
|
{placeholder}
|
||||||
bind:value={inputValue}
|
bind:value={inputValue}
|
||||||
bind:this={input}
|
bind:this={inputOrTextarea}
|
||||||
on:focus={() => dispatch("textFocused")}
|
on:focus={() => dispatch("textFocused")}
|
||||||
on:blur={() => dispatch("textChanged")}
|
on:blur={() => dispatch("textChanged")}
|
||||||
on:change={() => dispatch("textChanged")}
|
on:change={() => dispatch("textChanged")}
|
||||||
|
|
@ -85,7 +93,7 @@
|
||||||
{spellcheck}
|
{spellcheck}
|
||||||
{disabled}
|
{disabled}
|
||||||
bind:value={inputValue}
|
bind:value={inputValue}
|
||||||
bind:this={input}
|
bind:this={inputOrTextarea}
|
||||||
on:focus={() => dispatch("textFocused")}
|
on:focus={() => dispatch("textFocused")}
|
||||||
on:blur={() => dispatch("textChanged")}
|
on:blur={() => dispatch("textChanged")}
|
||||||
on:change={() => dispatch("textChanged")}
|
on:change={() => dispatch("textChanged")}
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@
|
||||||
export let incrementCallbackIncrease: (() => void) | undefined = undefined;
|
export let incrementCallbackIncrease: (() => void) | undefined = undefined;
|
||||||
export let incrementCallbackDecrease: (() => void) | undefined = undefined;
|
export let incrementCallbackDecrease: (() => void) | undefined = undefined;
|
||||||
|
|
||||||
let fieldInput: FieldInput;
|
let self: FieldInput;
|
||||||
let text = displayText(value);
|
let text = displayText(value);
|
||||||
let editing = false;
|
let editing = false;
|
||||||
// Stays in sync with a binding to the actual input range slider element.
|
// Stays in sync with a binding to the actual input range slider element.
|
||||||
|
|
@ -127,7 +127,7 @@
|
||||||
function sliderPointerUp() {
|
function sliderPointerUp() {
|
||||||
// User clicked but didn't drag, so we focus the text input element
|
// User clicked but didn't drag, so we focus the text input element
|
||||||
if (rangeSliderClickDragState === "mousedown") {
|
if (rangeSliderClickDragState === "mousedown") {
|
||||||
const inputElement = fieldInput.querySelector("[data-input-element]") as HTMLInputElement | undefined;
|
const inputElement = self.element().querySelector("[data-input-element]") as HTMLInputElement | undefined;
|
||||||
if (!inputElement) return;
|
if (!inputElement) return;
|
||||||
|
|
||||||
// Set the slider position back to the original position to undo the user moving it
|
// Set the slider position back to the original position to undo the user moving it
|
||||||
|
|
@ -148,7 +148,7 @@
|
||||||
|
|
||||||
editing = true;
|
editing = true;
|
||||||
|
|
||||||
fieldInput.selectAllText(text);
|
self.selectAllText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called only when `value` is changed from the <input> element via user input and committed, either with the
|
// Called only when `value` is changed from the <input> element via user input and committed, either with the
|
||||||
|
|
@ -164,7 +164,7 @@
|
||||||
|
|
||||||
editing = false;
|
editing = false;
|
||||||
|
|
||||||
fieldInput.unFocus();
|
self.unFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCancelTextChange() {
|
function onCancelTextChange() {
|
||||||
|
|
@ -172,7 +172,7 @@
|
||||||
|
|
||||||
editing = false;
|
editing = false;
|
||||||
|
|
||||||
fieldInput.unFocus();
|
self.unFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onIncrement(direction: "Decrease" | "Increase") {
|
function onIncrement(direction: "Decrease" | "Increase") {
|
||||||
|
|
@ -245,7 +245,7 @@
|
||||||
{sharpRightCorners}
|
{sharpRightCorners}
|
||||||
spellcheck={false}
|
spellcheck={false}
|
||||||
styles={{ "min-width": minWidth > 0 ? `${minWidth}px` : undefined, "--progress-factor": (rangeSliderValueAsRendered - rangeMin) / (rangeMax - rangeMin) }}
|
styles={{ "min-width": minWidth > 0 ? `${minWidth}px` : undefined, "--progress-factor": (rangeSliderValueAsRendered - rangeMin) / (rangeMax - rangeMin) }}
|
||||||
bind:this={fieldInput}
|
bind:this={self}
|
||||||
>
|
>
|
||||||
{#if value !== undefined && mode === "Increment" && incrementBehavior !== "None"}
|
{#if value !== undefined && mode === "Increment" && incrementBehavior !== "None"}
|
||||||
<button class="arrow left" on:click={() => onIncrement("Decrease")} tabindex="-1" />
|
<button class="arrow left" on:click={() => onIncrement("Decrease")} tabindex="-1" />
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,17 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from "svelte";
|
|
||||||
|
|
||||||
import { type IconName } from "@/utility-functions/icons";
|
import { type IconName } from "@/utility-functions/icons";
|
||||||
|
|
||||||
import LayoutRow from "@/components/layout/LayoutRow.svelte";
|
import LayoutRow from "@/components/layout/LayoutRow.svelte";
|
||||||
import CheckboxInput from "@/components/widgets/inputs/CheckboxInput.svelte";
|
import CheckboxInput from "@/components/widgets/inputs/CheckboxInput.svelte";
|
||||||
|
|
||||||
// emits: ["update:checked"],
|
|
||||||
const dispatch = createEventDispatcher<{ checked: boolean }>();
|
|
||||||
|
|
||||||
export let checked: boolean;
|
export let checked: boolean;
|
||||||
export let disabled = false;
|
export let disabled = false;
|
||||||
export let icon: IconName = "Checkmark";
|
export let icon: IconName = "Checkmark";
|
||||||
export let tooltip: string | undefined = undefined;
|
export let tooltip: string | undefined = undefined;
|
||||||
|
|
||||||
let checkboxInput: CheckboxInput;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<LayoutRow class="optional-input" classes={{ disabled }}>
|
<LayoutRow class="optional-input" classes={{ disabled }}>
|
||||||
<CheckboxInput {checked} on:checked {disabled} {icon} {tooltip} bind:this={checkboxInput} />
|
<CheckboxInput {checked} on:checked {disabled} {icon} {tooltip} />
|
||||||
</LayoutRow>
|
</LayoutRow>
|
||||||
|
|
||||||
<style lang="scss" global>
|
<style lang="scss" global>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
export let tooltip: string | undefined = undefined;
|
export let tooltip: string | undefined = undefined;
|
||||||
export let disabled = false;
|
export let disabled = false;
|
||||||
|
|
||||||
let fieldInput: FieldInput;
|
let self: FieldInput;
|
||||||
let editing = false;
|
let editing = false;
|
||||||
let inputValue = value;
|
let inputValue = value;
|
||||||
|
|
||||||
|
|
@ -30,16 +30,20 @@
|
||||||
onCancelTextChange();
|
onCancelTextChange();
|
||||||
|
|
||||||
// TODO: Find a less hacky way to do this
|
// TODO: Find a less hacky way to do this
|
||||||
dispatch("commitText", fieldInput.getInputElementValue());
|
dispatch("commitText", self.getValue());
|
||||||
|
|
||||||
// Required if value is not changed by the parent component upon update:value event
|
// Required if value is not changed by the parent component upon update:value event
|
||||||
fieldInput.setInputElementValue(value);
|
self.setInputElementValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCancelTextChange() {
|
function onCancelTextChange() {
|
||||||
editing = false;
|
editing = false;
|
||||||
|
|
||||||
fieldInput.unFocus();
|
self.unFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function focus() {
|
||||||
|
self.focus();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -59,7 +63,7 @@
|
||||||
{disabled}
|
{disabled}
|
||||||
{tooltip}
|
{tooltip}
|
||||||
value={inputValue}
|
value={inputValue}
|
||||||
bind:this={fieldInput}
|
bind:this={self}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<style lang="scss" global>
|
<style lang="scss" global>
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
export let minWidth = 0;
|
export let minWidth = 0;
|
||||||
export let sharpRightCorners = false;
|
export let sharpRightCorners = false;
|
||||||
|
|
||||||
let fieldInput: FieldInput;
|
let self: FieldInput;
|
||||||
let editing = false;
|
let editing = false;
|
||||||
let text = value;
|
let text = value;
|
||||||
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
function onTextFocused() {
|
function onTextFocused() {
|
||||||
editing = true;
|
editing = true;
|
||||||
|
|
||||||
fieldInput.selectAllText(text);
|
self.selectAllText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called only when `value` is changed from the <input> element via user input and committed, either with the
|
// Called only when `value` is changed from the <input> element via user input and committed, either with the
|
||||||
|
|
@ -40,16 +40,20 @@
|
||||||
onCancelTextChange();
|
onCancelTextChange();
|
||||||
|
|
||||||
// TODO: Find a less hacky way to do this
|
// TODO: Find a less hacky way to do this
|
||||||
dispatch("commitText", fieldInput.getInputElementValue());
|
dispatch("commitText", self.getValue());
|
||||||
|
|
||||||
// Required if value is not changed by the parent component upon update:value event
|
// Required if value is not changed by the parent component upon update:value event
|
||||||
fieldInput.setInputElementValue(value);
|
self.setInputElementValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCancelTextChange() {
|
function onCancelTextChange() {
|
||||||
editing = false;
|
editing = false;
|
||||||
|
|
||||||
fieldInput.unFocus();
|
self.unFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function focus() {
|
||||||
|
self.focus();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -68,7 +72,7 @@
|
||||||
{tooltip}
|
{tooltip}
|
||||||
{placeholder}
|
{placeholder}
|
||||||
{sharpRightCorners}
|
{sharpRightCorners}
|
||||||
bind:this={fieldInput}
|
bind:this={self}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<style lang="scss" global>
|
<style lang="scss" global>
|
||||||
|
|
|
||||||
|
|
@ -115,8 +115,6 @@ fn handle_message(message: String) -> String {
|
||||||
let serialized = ron::to_string(&send_frontend_message_to_js(response.clone())).unwrap();
|
let serialized = ron::to_string(&send_frontend_message_to_js(response.clone())).unwrap();
|
||||||
if let Err(error) = ron::from_str::<FrontendMessage>(&serialized) {
|
if let Err(error) = ron::from_str::<FrontendMessage>(&serialized) {
|
||||||
log::error!("Error deserializing message: {}", error);
|
log::error!("Error deserializing message: {}", error);
|
||||||
log::debug!("{:#?}", response);
|
|
||||||
log::debug!("{}", serialized);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue