mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-09 05:28:13 +08:00
Fix Bezier-rs interactive demos and migrate its Webpack bundler to Vite
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import { WasmBezier } from "@/../wasm/pkg";
|
||||
import bezierFeatures, { BezierFeatureKey } from "@/features/bezier-features";
|
||||
import type { BezierFeatureKey } from "@/features/bezier-features";
|
||||
import bezierFeatures from "@/features/bezier-features";
|
||||
import { renderDemo } from "@/utils/render";
|
||||
import { getConstructorKey, getCurveType, BezierCallback, BezierCurveType, InputOption, WasmBezierManipulatorKey, Demo } from "@/utils/types";
|
||||
import type { BezierCallback, BezierCurveType, InputOption, WasmBezierManipulatorKey, Demo } from "@/utils/types";
|
||||
import { getConstructorKey, getCurveType } from "@/utils/types";
|
||||
|
||||
const SELECTABLE_RANGE = 10;
|
||||
|
||||
@@ -54,8 +56,7 @@ class BezierDemo extends HTMLElement implements Demo {
|
||||
this.render();
|
||||
|
||||
const figure = this.querySelector("figure") as HTMLElement;
|
||||
const wasm = await import("@/../wasm/pkg");
|
||||
this.bezier = wasm.WasmBezier[getConstructorKey(curveType)](this.points);
|
||||
this.bezier = WasmBezier[getConstructorKey(curveType)](this.points);
|
||||
this.drawDemo(figure);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import bezierFeatures, { BezierFeatureKey } from "@/features/bezier-features";
|
||||
import type { BezierFeatureKey } from "@/features/bezier-features";
|
||||
import bezierFeatures from "@/features/bezier-features";
|
||||
import { renderDemoPane } from "@/utils/render";
|
||||
import { BezierCurveType, BEZIER_CURVE_TYPE, BezierDemoOptions, InputOption, Demo, DemoPane, BezierDemoArgs } from "@/utils/types";
|
||||
import type { BezierCurveType, BezierDemoOptions, InputOption, DemoPane, BezierDemoArgs } from "@/utils/types";
|
||||
import { BEZIER_CURVE_TYPE } from "@/utils/types";
|
||||
|
||||
const demoDefaults = {
|
||||
Linear: {
|
||||
@@ -66,7 +68,7 @@ class BezierDemoPane extends HTMLElement implements DemoPane {
|
||||
renderDemoPane(this);
|
||||
}
|
||||
|
||||
buildDemo(demo: BezierDemoArgs): Demo {
|
||||
buildDemo(demo: BezierDemoArgs): HTMLElement {
|
||||
const bezierDemo = document.createElement("bezier-demo");
|
||||
bezierDemo.setAttribute("title", demo.title);
|
||||
bezierDemo.setAttribute("points", JSON.stringify(demo.points));
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { WasmSubpath } from "@/../wasm/pkg";
|
||||
import subpathFeatures, { SubpathFeatureKey } from "@/features/subpath-features";
|
||||
import type { SubpathFeatureKey } from "@/features/subpath-features";
|
||||
import subpathFeatures from "@/features/subpath-features";
|
||||
import { renderDemo } from "@/utils/render";
|
||||
|
||||
import { SubpathCallback, WasmSubpathInstance, WasmSubpathManipulatorKey, InputOption } from "@/utils/types";
|
||||
import type { SubpathCallback, WasmSubpathInstance, WasmSubpathManipulatorKey, InputOption } from "@/utils/types";
|
||||
|
||||
const SELECTABLE_RANGE = 10;
|
||||
const POINT_INDEX_TO_MANIPULATOR: WasmSubpathManipulatorKey[] = ["set_anchor", "set_in_handle", "set_out_handle"];
|
||||
@@ -48,8 +48,7 @@ class SubpathDemo extends HTMLElement {
|
||||
this.render();
|
||||
|
||||
const figure = this.querySelector("figure") as HTMLElement;
|
||||
const wasm = await import("@/../wasm/pkg");
|
||||
this.subpath = wasm.WasmSubpath.from_triples(this.triples, this.closed) as WasmSubpathInstance;
|
||||
this.subpath = WasmSubpath.from_triples(this.triples, this.closed) as WasmSubpathInstance;
|
||||
this.drawDemo(figure);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import subpathFeatures, { SubpathFeatureKey } from "@/features/subpath-features";
|
||||
import type { SubpathFeatureKey } from "@/features/subpath-features";
|
||||
import subpathFeatures from "@/features/subpath-features";
|
||||
import { renderDemoPane } from "@/utils/render";
|
||||
import { Demo, DemoPane, SubpathDemoArgs, SubpathInputOption } from "@/utils/types";
|
||||
import type { DemoPane, SubpathDemoArgs, SubpathInputOption } from "@/utils/types";
|
||||
|
||||
class SubpathDemoPane extends HTMLElement implements DemoPane {
|
||||
// Props
|
||||
@@ -56,7 +57,7 @@ class SubpathDemoPane extends HTMLElement implements DemoPane {
|
||||
renderDemoPane(this);
|
||||
}
|
||||
|
||||
buildDemo(demo: SubpathDemoArgs): Demo {
|
||||
buildDemo(demo: SubpathDemoArgs): HTMLElement {
|
||||
const subpathDemo = document.createElement("subpath-demo");
|
||||
subpathDemo.setAttribute("title", demo.title);
|
||||
subpathDemo.setAttribute("triples", JSON.stringify(demo.triples));
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { WasmBezier } from "@/../wasm/pkg";
|
||||
import { capOptions, tSliderOptions, bezierTValueVariantOptions, errorOptions, minimumSeparationOptions } from "@/utils/options";
|
||||
import { BezierDemoOptions, WasmBezierInstance, BezierCallback, InputOption, BEZIER_T_VALUE_VARIANTS } from "@/utils/types";
|
||||
import type { BezierDemoOptions, WasmBezierInstance, BezierCallback, InputOption } from "@/utils/types";
|
||||
import { BEZIER_T_VALUE_VARIANTS } from "@/utils/types";
|
||||
|
||||
const bezierFeatures = {
|
||||
constructor: {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { capOptions, joinOptions, tSliderOptions, subpathTValueVariantOptions, intersectionErrorOptions, minimumSeparationOptions } from "@/utils/options";
|
||||
import { SubpathCallback, SubpathInputOption, WasmSubpathInstance, SUBPATH_T_VALUE_VARIANTS } from "@/utils/types";
|
||||
import type { SubpathCallback, SubpathInputOption, WasmSubpathInstance } from "@/utils/types";
|
||||
import { SUBPATH_T_VALUE_VARIANTS } from "@/utils/types";
|
||||
|
||||
const subpathFeatures = {
|
||||
constructor: {
|
||||
@@ -71,7 +72,7 @@ const subpathFeatures = {
|
||||
[210, 150],
|
||||
],
|
||||
options.error,
|
||||
options.minimum_separation
|
||||
options.minimum_separation,
|
||||
),
|
||||
inputOptions: [intersectionErrorOptions, minimumSeparationOptions],
|
||||
},
|
||||
@@ -85,7 +86,7 @@ const subpathFeatures = {
|
||||
[135, 180],
|
||||
],
|
||||
options.error,
|
||||
options.minimum_separation
|
||||
options.minimum_separation,
|
||||
),
|
||||
inputOptions: [intersectionErrorOptions, minimumSeparationOptions],
|
||||
},
|
||||
@@ -100,7 +101,7 @@ const subpathFeatures = {
|
||||
[200, 140],
|
||||
],
|
||||
options.error,
|
||||
options.minimum_separation
|
||||
options.minimum_separation,
|
||||
),
|
||||
inputOptions: [intersectionErrorOptions, minimumSeparationOptions],
|
||||
},
|
||||
|
||||
@@ -1,26 +1,36 @@
|
||||
import { default as init } from "@/../wasm/pkg";
|
||||
import BezierDemo from "@/components/BezierDemo";
|
||||
import BezierDemoPane from "@/components/BezierDemoPane";
|
||||
import SubpathDemo from "@/components/SubpathDemo";
|
||||
import SubpathDemoPane from "@/components/SubpathDemoPane";
|
||||
import type { BezierFeatureKey } from "@/features/bezier-features";
|
||||
import bezierFeatures from "@/features/bezier-features";
|
||||
import type { SubpathFeatureKey } from "@/features/subpath-features";
|
||||
import subpathFeatures from "@/features/subpath-features";
|
||||
|
||||
import bezierFeatures, { BezierFeatureKey } from "@/features/bezier-features";
|
||||
import subpathFeatures, { SubpathFeatureKey } from "@/features/subpath-features";
|
||||
(async () => {
|
||||
await init();
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"bezier-demo": BezierDemo;
|
||||
"bezier-demo-pane": BezierDemoPane;
|
||||
"subpath-demo": SubpathDemo;
|
||||
"subpath-demo-pane": SubpathDemoPane;
|
||||
}
|
||||
}
|
||||
window.customElements.define("bezier-demo", BezierDemo);
|
||||
window.customElements.define("bezier-demo-pane", BezierDemoPane);
|
||||
window.customElements.define("subpath-demo", SubpathDemo);
|
||||
window.customElements.define("subpath-demo-pane", SubpathDemoPane);
|
||||
|
||||
window.customElements.define("bezier-demo", BezierDemo);
|
||||
window.customElements.define("bezier-demo-pane", BezierDemoPane);
|
||||
window.customElements.define("subpath-demo", SubpathDemo);
|
||||
window.customElements.define("subpath-demo-pane", SubpathDemoPane);
|
||||
window.addEventListener("hashchange", (e: Event) => {
|
||||
const hashChangeEvent = e as HashChangeEvent;
|
||||
const isOldHashSolo = isUrlSolo(hashChangeEvent.oldURL);
|
||||
const isNewHashSolo = isUrlSolo(hashChangeEvent.newURL);
|
||||
const target = document.getElementById(window.location.hash.substring(1));
|
||||
// Determine whether the page needs to recompute which examples to show
|
||||
if (!target || isOldHashSolo !== isNewHashSolo) {
|
||||
renderExamples();
|
||||
}
|
||||
});
|
||||
|
||||
function renderBezierPane(featureName: BezierFeatureKey, container: HTMLElement | null) {
|
||||
renderExamples();
|
||||
})();
|
||||
|
||||
function renderBezierPane(featureName: BezierFeatureKey, container?: HTMLElement) {
|
||||
const feature = bezierFeatures[featureName];
|
||||
const demo = document.createElement("bezier-demo-pane");
|
||||
|
||||
@@ -30,7 +40,7 @@ function renderBezierPane(featureName: BezierFeatureKey, container: HTMLElement
|
||||
container?.append(demo);
|
||||
}
|
||||
|
||||
function renderSubpathPane(featureName: SubpathFeatureKey, container: HTMLElement | null) {
|
||||
function renderSubpathPane(featureName: SubpathFeatureKey, container?: HTMLElement) {
|
||||
const feature = subpathFeatures[featureName];
|
||||
const demo = document.createElement("subpath-demo-pane");
|
||||
|
||||
@@ -46,17 +56,6 @@ function isUrlSolo(url: string): boolean {
|
||||
return splitHash?.length === 3 && splitHash?.[2] === "solo";
|
||||
}
|
||||
|
||||
window.addEventListener("hashchange", (e: Event) => {
|
||||
const hashChangeEvent = e as HashChangeEvent;
|
||||
const isOldHashSolo = isUrlSolo(hashChangeEvent.oldURL);
|
||||
const isNewHashSolo = isUrlSolo(hashChangeEvent.newURL);
|
||||
const target = document.getElementById(window.location.hash.substring(1));
|
||||
// Determine whether the page needs to recompute which examples to show
|
||||
if (!target || isOldHashSolo !== isNewHashSolo) {
|
||||
renderExamples();
|
||||
}
|
||||
});
|
||||
|
||||
function renderExamples() {
|
||||
const hash = window.location.hash;
|
||||
const splitHash = hash.split("/");
|
||||
@@ -64,10 +63,10 @@ function renderExamples() {
|
||||
// Determine which examples to render based on hash
|
||||
if (splitHash[0] === "#bezier" && splitHash[1] in bezierFeatures && splitHash[2] === "solo") {
|
||||
window.document.body.innerHTML = `<div id="bezier-demos"></div>`;
|
||||
renderBezierPane(splitHash[1] as BezierFeatureKey, document.getElementById("bezier-demos"));
|
||||
renderBezierPane(splitHash[1] as BezierFeatureKey, document.getElementById("bezier-demos") || undefined);
|
||||
} else if (splitHash[0] === "#subpath" && splitHash[1] in subpathFeatures && splitHash[2] === "solo") {
|
||||
window.document.body.innerHTML = `<div id="subpath-demos"></div>`;
|
||||
renderSubpathPane(splitHash[1] as SubpathFeatureKey, document.getElementById("subpath-demos"));
|
||||
renderSubpathPane(splitHash[1] as SubpathFeatureKey, document.getElementById("subpath-demos") || undefined);
|
||||
} else {
|
||||
window.document.body.innerHTML = `
|
||||
<h1 class="website-header">Bezier-rs Interactive Documentation</h1>
|
||||
@@ -83,8 +82,8 @@ function renderExamples() {
|
||||
<div id="subpath-demos"></div>
|
||||
`.trim();
|
||||
|
||||
const bezierDemos = document.getElementById("bezier-demos");
|
||||
const subpathDemos = document.getElementById("subpath-demos");
|
||||
const bezierDemos = document.getElementById("bezier-demos") || undefined;
|
||||
const subpathDemos = document.getElementById("subpath-demos") || undefined;
|
||||
|
||||
(Object.keys(bezierFeatures) as BezierFeatureKey[]).forEach((feature) => renderBezierPane(feature, bezierDemos));
|
||||
(Object.keys(subpathFeatures) as SubpathFeatureKey[]).forEach((feature) => renderSubpathPane(feature, subpathDemos));
|
||||
@@ -98,5 +97,3 @@ function renderExamples() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderExamples();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Demo, DemoPane, InputOption } from "@/utils/types";
|
||||
import type { Demo, DemoPane, InputOption } from "@/utils/types";
|
||||
|
||||
export function renderDemo(demo: Demo) {
|
||||
const header = document.createElement("h4");
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export type WasmRawInstance = typeof import("@/../wasm/pkg");
|
||||
import type * as WasmPkg from "@/../wasm/pkg";
|
||||
|
||||
export type WasmRawInstance = typeof WasmPkg;
|
||||
export type WasmBezierInstance = InstanceType<WasmRawInstance["WasmBezier"]>;
|
||||
|
||||
export type WasmBezierKey = keyof WasmBezierInstance;
|
||||
@@ -9,7 +11,7 @@ export type WasmSubpathInstance = InstanceType<WasmRawInstance["WasmSubpath"]>;
|
||||
export type WasmSubpathManipulatorKey = "set_anchor" | "set_in_handle" | "set_out_handle";
|
||||
|
||||
export const BEZIER_CURVE_TYPE = ["Linear", "Quadratic", "Cubic"] as const;
|
||||
export type BezierCurveType = typeof BEZIER_CURVE_TYPE[number];
|
||||
export type BezierCurveType = (typeof BEZIER_CURVE_TYPE)[number];
|
||||
|
||||
export type BezierCallback = (bezier: WasmBezierInstance, options: Record<string, number>, mouseLocation?: [number, number]) => string;
|
||||
export type SubpathCallback = (subpath: WasmSubpathInstance, options: Record<string, number>, mouseLocation?: [number, number]) => string;
|
||||
@@ -59,22 +61,22 @@ export function getConstructorKey(bezierCurveType: BezierCurveType): WasmBezierC
|
||||
return mapping[bezierCurveType];
|
||||
}
|
||||
|
||||
export interface DemoArgs {
|
||||
export type DemoArgs = {
|
||||
title: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
export interface BezierDemoArgs extends DemoArgs {
|
||||
export type BezierDemoArgs = {
|
||||
points: number[][];
|
||||
inputOptions: InputOption[];
|
||||
}
|
||||
} & DemoArgs;
|
||||
|
||||
export interface SubpathDemoArgs extends DemoArgs {
|
||||
export type SubpathDemoArgs = {
|
||||
triples: (number[] | undefined)[][];
|
||||
closed: boolean;
|
||||
}
|
||||
} & DemoArgs;
|
||||
|
||||
export interface Demo extends HTMLElement {
|
||||
export type Demo = {
|
||||
inputOptions: InputOption[];
|
||||
sliderData: Record<string, number>;
|
||||
sliderUnits: Record<string, string | string[]>;
|
||||
@@ -84,14 +86,14 @@ export interface Demo extends HTMLElement {
|
||||
onMouseUp(): void;
|
||||
onMouseMove(event: MouseEvent): void;
|
||||
getSliderUnit(sliderValue: number, variable: string): string;
|
||||
}
|
||||
} & HTMLElement;
|
||||
|
||||
export interface DemoPane extends HTMLElement {
|
||||
export type DemoPane = {
|
||||
name: string;
|
||||
demos: DemoArgs[];
|
||||
id: string;
|
||||
buildDemo(demo: DemoArgs): Demo;
|
||||
}
|
||||
buildDemo(demo: DemoArgs): HTMLElement;
|
||||
} & HTMLElement;
|
||||
|
||||
export const BEZIER_T_VALUE_VARIANTS = ["Parametric", "Euclidean"] as const;
|
||||
export const SUBPATH_T_VALUE_VARIANTS = ["GlobalParametric", "GlobalEuclidean"] as const;
|
||||
|
||||
Reference in New Issue
Block a user