Bump frontend dependencies to Svelte 5 (#3648)

* Add more recommended VS Code default configs

* Upgrade frontend dependencies including Svelte 5

* Fix derived_references_self runtime error

* Fix lint warnings
This commit is contained in:
Keavon Chambers
2026-01-17 14:31:50 +00:00
committed by Timon Schelling
parent 3b55064f44
commit 915a344a05
24 changed files with 971 additions and 792 deletions
@@ -439,7 +439,7 @@
data-saturation-value-picker
>
{#if !isNone}
<div class="selection-circle" style:top={`${(1 - value) * 100}%`} style:left={`${saturation * 100}%`} />
<div class="selection-circle" style:top={`${(1 - value) * 100}%`} style:left={`${saturation * 100}%`}></div>
{/if}
{#if alignedAxis}
<div
@@ -448,7 +448,7 @@
class:value={alignedAxis === "value"}
style:top={`${(1 - value) * 100}%`}
style:left={`${saturation * 100}%`}
/>
></div>
{/if}
</LayoutCol>
<LayoutCol
@@ -459,7 +459,7 @@
data-hue-picker
>
{#if !isNone}
<div class="selection-needle" style:top={`${(1 - hue) * 100}%`} />
<div class="selection-needle" style:top={`${(1 - hue) * 100}%`}></div>
{/if}
</LayoutCol>
<LayoutCol
@@ -470,7 +470,7 @@
data-alpha-picker
>
{#if !isNone}
<div class="selection-needle" style:top={`${(1 - alpha) * 100}%`} />
<div class="selection-needle" style:top={`${(1 - alpha) * 100}%`}></div>
{/if}
</LayoutCol>
</LayoutRow>
@@ -677,7 +677,7 @@
style:--pure-color-gray={gray}
data-tooltip-label={`Set to ${name}`}
data-tooltip-description={disabled ? "Disabled (read-only)." : ""}
/>
></div>
{/each}
</button>
{#if eyedropperSupported()}
@@ -56,8 +56,8 @@
>
<div class="ring">
<div class="canvas-container">
<canvas width={ZOOM_WINDOW_DIMENSIONS} height={ZOOM_WINDOW_DIMENSIONS} bind:this={zoomPreviewCanvas} />
<div class="pixel-outline" />
<canvas width={ZOOM_WINDOW_DIMENSIONS} height={ZOOM_WINDOW_DIMENSIONS} bind:this={zoomPreviewCanvas}></canvas>
<div class="pixel-outline"></div>
</div>
</div>
</FloatingMenu>
@@ -42,6 +42,7 @@
// Keep the child references outside of the entries array so as to avoid infinite recursion.
let childReferences: MenuList[][] = [];
let openChildValue: string | undefined = undefined;
let search = "";
let reactiveEntries = entries;
let highlighted = activeEntry as MenuListEntry | undefined;
@@ -172,7 +173,7 @@
// Close the containing menu
let childReference = getChildReference(menuListEntry);
if (childReference) {
childReference.open = false;
openChildValue = undefined;
reactiveEntries = reactiveEntries;
}
dispatch("open", false);
@@ -192,7 +193,7 @@
let childReference = getChildReference(menuListEntry);
if (childReference) {
childReference.open = true;
openChildValue = menuListEntry.value;
reactiveEntries = reactiveEntries;
} else {
dispatch("open", true);
@@ -207,19 +208,13 @@
let childReference = getChildReference(menuListEntry);
if (childReference) {
childReference.open = false;
openChildValue = undefined;
reactiveEntries = reactiveEntries;
} else {
dispatch("open", false);
}
}
function isEntryOpen(menuListEntry: MenuListEntry): boolean {
if (!menuListEntry.children?.length) return false;
return getChildReference(menuListEntry)?.open || false;
}
function includeSeparator(entries: MenuListEntry[][], section: MenuListEntry[], sectionIndex: number, search: string): boolean {
const elementsBeforeCurrentSection = entries
.slice(0, sectionIndex)
@@ -242,7 +237,7 @@
// No submenu to open
if (!childReference || !highlightedEntry.children?.length) return false;
childReference.open = true;
openChildValue = highlightedEntry.value;
// The reason we bother taking `highlightdEntry` as an argument is because, when this function is called, it can ensure `highlightedEntry` is not undefined.
// But here we still have to set `highlighted` to itself so Svelte knows to reactively update it after we set its `childReference.open` property.
highlighted = highlighted;
@@ -262,7 +257,7 @@
const menuOpen = open;
const flatEntries = filteredEntries.flat().filter((entry) => !entry.disabled);
const openChild = flatEntries.findIndex((entry) => (entry.children?.length ?? 0) > 0 && getChildReference(entry)?.open);
const openChild = (openChildValue !== undefined && flatEntries.findIndex((entry) => entry.value === openChildValue)) || -1;
// Allow opening menu with space or enter
if (!menuOpen && (e.key === " " || e.key === "Enter")) {
@@ -442,7 +437,7 @@
{#each currentEntries(section, virtualScrollingEntryHeight, virtualScrollingStartIndex, virtualScrollingEndIndex, search) as entry, entryIndex (entryIndex + startIndex)}
<LayoutRow
class="row"
classes={{ open: isEntryOpen(entry), active: entry.label === highlighted?.label, disabled: Boolean(entry.disabled) }}
classes={{ open: openChildValue === entry.value, active: entry.label === highlighted?.label, disabled: Boolean(entry.disabled) }}
styles={{ height: virtualScrollingEntryHeight || "20px" }}
tooltipLabel={entry.tooltipLabel}
tooltipDescription={entry.tooltipDescription}
@@ -454,7 +449,7 @@
{#if entry.icon && drawIcon}
<IconLabel icon={entry.icon} iconSizeOverride={16} class="entry-icon" />
{:else if drawIcon}
<div class="no-icon" />
<div class="no-icon"></div>
{/if}
{#if entry.font}
@@ -470,7 +465,7 @@
{#if entry.children?.length}
<IconLabel class="submenu-arrow" icon="DropdownArrow" />
{:else}
<div class="no-submenu-arrow" />
<div class="no-submenu-arrow"></div>
{/if}
{#if entry.children}
@@ -483,7 +478,7 @@
}}
on:selectedEntryValuePath={({ detail }) => dispatch("selectedEntryValuePath", detail)}
parentsValuePath={[...parentsValuePath, entry.value]}
open={getChildReference(entry)?.open || false}
open={openChildValue === entry.value}
direction="TopRight"
entries={entry.children}
entriesHash={entry.childrenHash || 0n}
@@ -1,5 +1,6 @@
<script lang="ts">
import { createEventDispatcher, getContext, onMount } from "svelte";
import { SvelteMap } from "svelte/reactivity";
import type { FrontendNodeType } from "@graphite/messages";
import type { NodeGraphState } from "@graphite/state-providers/node-graph";
@@ -28,7 +29,7 @@
};
function buildNodeCategories(nodeTypes: FrontendNodeType[], searchTerm: string): [string, NodeCategoryDetails][] {
const categories = new Map<string, NodeCategoryDetails>();
const categories = new SvelteMap<string, NodeCategoryDetails>();
const isTypeSearch = searchTerm.toLowerCase().startsWith("type:");
let typeSearchTerm = "";
let remainingSearchTerms = [searchTerm.toLowerCase()];
@@ -476,7 +476,7 @@
{...$$restProps}
>
{#if displayTail}
<div class="tail" bind:this={tail} />
<div class="tail" bind:this={tail}></div>
{/if}
{#if displayContainer}
<div class="floating-menu-container" bind:this={floatingMenuContainer}>
@@ -580,7 +580,7 @@
{/if}
<div class="text-input" style:width={canvasWidthCSS} style:height={canvasHeightCSS} style:pointer-events={showTextInput ? "auto" : ""}>
{#if showTextInput}
<div bind:this={textInput} style:transform="matrix({textInputMatrix})" on:scroll={preventTextEditingScroll} />
<div bind:this={textInput} style:transform="matrix({textInputMatrix})" on:scroll={preventTextEditingScroll}></div>
{/if}
</div>
{#if !$appWindow.viewportHolePunch}
+3 -2
View File
@@ -1,5 +1,6 @@
<script lang="ts">
import { getContext, onMount, onDestroy, tick } from "svelte";
import { SvelteMap } from "svelte/reactivity";
import type { Editor } from "@graphite/editor";
import {
@@ -54,7 +55,7 @@
let list: LayoutCol | undefined;
// Layer data
let layerCache = new Map<string, LayerPanelEntry>(); // TODO: replace with BigUint64Array as index
let layerCache = new SvelteMap<string, LayerPanelEntry>(); // TODO: replace with BigUint64Array as index
let layers: LayerListingInfo[] = [];
// Interactive dragging
@@ -686,7 +687,7 @@
{/each}
</LayoutCol>
{#if draggingData && !draggingData.highlightFolder && dragInPanel}
<div class="insert-mark" style:left={`${4 + draggingData.insertDepth * 16}px`} style:top={`${draggingData.markerHeight}px`} />
<div class="insert-mark" style:left={`${4 + draggingData.insertDepth * 16}px`} style:top={`${draggingData.markerHeight}px`}></div>
{/if}
</LayoutRow>
<LayoutRow class="bottom-bar" scrollableX={true}>
+4 -4
View File
@@ -349,7 +349,7 @@
}}
/>
{#if index > 0}
<div class="reorder-drag-grip" data-tooltip-description="Reorder this export" />
<div class="reorder-drag-grip" data-tooltip-description="Reorder this export"></div>
{/if}
{/if}
</div>
@@ -396,7 +396,7 @@
>
{#if (hoveringExportIndex === index || editingNameExportIndex === index) && $nodeGraph.updateImportsExports.addImportExport}
{#if index > 0}
<div class="reorder-drag-grip" data-tooltip-description="Reorder this export" />
<div class="reorder-drag-grip" data-tooltip-description="Reorder this export"></div>
{/if}
<IconButton
size={16}
@@ -457,7 +457,7 @@
x: Number($nodeGraph.updateImportsExports.importPosition.x),
y: Number($nodeGraph.updateImportsExports.importPosition.y) + Number($nodeGraph.reorderImportIndex) * 24,
}}
<div class="reorder-bar" style:--offset-left={(position.x - 48) / 24} style:--offset-top={(position.y - 12) / 24} />
<div class="reorder-bar" style:--offset-left={(position.x - 48) / 24} style:--offset-top={(position.y - 12) / 24}></div>
{/if}
{#if $nodeGraph.reorderExportIndex !== undefined}
@@ -465,7 +465,7 @@
x: Number($nodeGraph.updateImportsExports.exportPosition.x),
y: Number($nodeGraph.updateImportsExports.exportPosition.y) + Number($nodeGraph.reorderExportIndex) * 24,
}}
<div class="reorder-bar" style:--offset-left={position.x / 24} style:--offset-top={(position.y - 12) / 24} />
<div class="reorder-bar" style:--offset-left={position.x / 24} style:--offset-top={(position.y - 12) / 24}></div>
{/if}
{/if}
</div>
@@ -24,7 +24,7 @@
<!-- TODO: Implement collapsable sections with properties system -->
<LayoutCol class={`widget-section ${className}`.trim()} {classes}>
<button class="header" class:expanded on:click|stopPropagation={() => (expanded = !expanded)} tabindex="0">
<div class="expand-arrow" />
<div class="expand-arrow"></div>
<TextLabel tooltipLabel={widgetData.name} tooltipDescription={widgetData.description} bold={true}>{widgetData.name}</TextLabel>
<IconButton
icon={widgetData.pinned ? "PinActive" : "PinInactive"}
@@ -12,6 +12,7 @@
const dispatch = createEventDispatcher<{ selectedEntryValuePath: string[] }>();
let self: MenuList;
let open = false;
// Note: IconButton should instead be used if only an icon, but no label, is desired.
// However, if multiple TextButton widgets are used in a group with only some having no label, this component is able to accommodate that.
@@ -93,9 +94,9 @@
</button>
{#if menuListChildrenExists}
<MenuList
on:open={({ detail }) => self && (self.open = detail)}
on:selectedEntryValuePath={({ detail }) => dispatch("selectedEntryValuePath", detail)}
open={self?.open || false}
on:open={({ detail }) => (open = detail)}
{open}
entries={menuListChildren || []}
entriesHash={menuListChildrenHash || 0n}
direction="Bottom"
@@ -114,7 +114,7 @@
on:keydown={(e) => e.key === "Escape" && cancel()}
on:pointerdown
on:contextmenu={(e) => hideContextMenu && e.preventDefault()}
/>
></textarea>
{/if}
{#if label}
<label for={`field-input-${id}`} on:pointerdown>{label}</label>
@@ -754,9 +754,9 @@
bind:this={inputRangeElement}
/>
{#if rangeSliderClickDragState === "Deciding"}
<div class="fake-slider-thumb" />
<div class="fake-slider-thumb"></div>
{/if}
<div class="slider-progress" />
<div class="slider-progress"></div>
{/if}
{/if}
</FieldInput>
@@ -25,15 +25,15 @@
data-tooltip-description={tooltipDescription}
data-tooltip-shortcut={tooltipShortcut?.shortcut ? JSON.stringify(tooltipShortcut.shortcut) : undefined}
>
<button on:click={() => setValue("TopLeft")} class="row-1 col-1" class:active={value === "TopLeft"} tabindex="-1" {disabled}><div /></button>
<button on:click={() => setValue("TopCenter")} class="row-1 col-2" class:active={value === "TopCenter"} tabindex="-1" {disabled}><div /></button>
<button on:click={() => setValue("TopRight")} class="row-1 col-3" class:active={value === "TopRight"} tabindex="-1" {disabled}><div /></button>
<button on:click={() => setValue("CenterLeft")} class="row-2 col-1" class:active={value === "CenterLeft"} tabindex="-1" {disabled}><div /></button>
<button on:click={() => setValue("Center")} class="row-2 col-2" class:active={value === "Center"} tabindex="-1" {disabled}><div /></button>
<button on:click={() => setValue("CenterRight")} class="row-2 col-3" class:active={value === "CenterRight"} tabindex="-1" {disabled}><div /></button>
<button on:click={() => setValue("BottomLeft")} class="row-3 col-1" class:active={value === "BottomLeft"} tabindex="-1" {disabled}><div /></button>
<button on:click={() => setValue("BottomCenter")} class="row-3 col-2" class:active={value === "BottomCenter"} tabindex="-1" {disabled}><div /></button>
<button on:click={() => setValue("BottomRight")} class="row-3 col-3" class:active={value === "BottomRight"} tabindex="-1" {disabled}><div /></button>
<button on:click={() => setValue("TopLeft")} class="row-1 col-1" class:active={value === "TopLeft"} tabindex="-1" {disabled}><div></div></button>
<button on:click={() => setValue("TopCenter")} class="row-1 col-2" class:active={value === "TopCenter"} tabindex="-1" {disabled}><div></div></button>
<button on:click={() => setValue("TopRight")} class="row-1 col-3" class:active={value === "TopRight"} tabindex="-1" {disabled}><div></div></button>
<button on:click={() => setValue("CenterLeft")} class="row-2 col-1" class:active={value === "CenterLeft"} tabindex="-1" {disabled}><div></div></button>
<button on:click={() => setValue("Center")} class="row-2 col-2" class:active={value === "Center"} tabindex="-1" {disabled}><div></div></button>
<button on:click={() => setValue("CenterRight")} class="row-2 col-3" class:active={value === "CenterRight"} tabindex="-1" {disabled}><div></div></button>
<button on:click={() => setValue("BottomLeft")} class="row-3 col-1" class:active={value === "BottomLeft"} tabindex="-1" {disabled}><div></div></button>
<button on:click={() => setValue("BottomCenter")} class="row-3 col-2" class:active={value === "BottomCenter"} tabindex="-1" {disabled}><div></div></button>
<button on:click={() => setValue("BottomRight")} class="row-3 col-3" class:active={value === "BottomRight"} tabindex="-1" {disabled}><div></div></button>
</div>
<style lang="scss" global>
@@ -210,7 +210,7 @@
<div class={`scrollbar-input ${direction.toLowerCase()}`}>
<button class="arrow decrease" on:pointerdown={() => pressArrow(-1)} tabindex="-1" data-scrollbar-arrow></button>
<div class="scroll-track" on:pointerdown={pressTrack} bind:this={scrollTrack}>
<div class="scroll-thumb" on:pointerdown={dragThumb} class:dragging style:top={thumbTop} style:bottom={thumbBottom} style:left={thumbLeft} style:right={thumbRight} />
<div class="scroll-thumb" on:pointerdown={dragThumb} class:dragging style:top={thumbTop} style:bottom={thumbBottom} style:left={thumbLeft} style:right={thumbRight}></div>
</div>
<button class="arrow increase" on:pointerdown={() => pressArrow(1)} tabindex="-1" data-scrollbar-arrow></button>
</div>
@@ -8,7 +8,7 @@
<div class={`separator ${direction.toLowerCase()} ${style.toLowerCase()}`}>
{#if style === "Section"}
<div />
<div></div>
{/if}
</div>