feat(editor): F4.4b the design tools: palette, moving, cables, menus, undo
The palette in Java's order with Java's icons and names: a device dragged onto the surface lands with its icon at the drop point, a tapped one in the middle of the view; a new router asks for 2 to 8 interfaces as Java does. A tap selects, a drag moves (divided by the scale), a long press or the three-dot button opens Java's menu. The cable tool plugs by a drag or by two taps, shows WAN or LAN on a home router's halves and Java's messages when refused. Delete removes the selection; undo and redo by button and Ctrl+Z/Ctrl+Y, each editor with its own origin. Browser tests with mouse and touch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
// The editor's page. Embedded in the dashboard (F6) it gets its document and
|
||||
// language over the bridge; on its own — for development and the browser
|
||||
// tests — it opens one of FILIUS' examples or a file (`?example=<name>`
|
||||
// opens that example at once, `?lang=en` and `?theme=dark` set the rest).
|
||||
// tests — it opens one of FILIUS' examples, an empty project or a file
|
||||
// (`?example=<name>` opens that example at once, `?example=new` an empty
|
||||
// project, `?lang=en` and `?theme=dark` set the rest).
|
||||
|
||||
import { StrictMode, useEffect, useState } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import * as Y from 'yjs';
|
||||
import { writeProject } from '@mdg-filius/doc';
|
||||
import { emptyProject, topologyView, writeProject } from '@mdg-filius/doc';
|
||||
import { openProjectArchive } from '@mdg-filius/fls';
|
||||
import { startBridge } from './bridge/dashboardBridge.js';
|
||||
import { Editor } from './Editor.js';
|
||||
@@ -14,6 +15,8 @@ import { LanguageProvider, translate, type Language } from './i18n/i18n.js';
|
||||
import './theme/tokens.css';
|
||||
|
||||
const EXAMPLES = import.meta.glob('../../../corpus/java-examples/*.fls', { query: '?url', import: 'default', eager: true }) as Record<string, string>;
|
||||
/** `?example=new`: an empty project. */
|
||||
const NEW_PROJECT = 'new';
|
||||
const exampleUrl = (name: string) => Object.entries(EXAMPLES).find(([path]) => path.endsWith(`/${name}`))?.[1];
|
||||
|
||||
function docOf(bytes: Uint8Array): Y.Doc {
|
||||
@@ -44,6 +47,12 @@ function App() {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (example === NEW_PROJECT) {
|
||||
const doc = new Y.Doc();
|
||||
writeProject(doc, emptyProject());
|
||||
setDoc(doc);
|
||||
return;
|
||||
}
|
||||
const url = exampleUrl(example);
|
||||
if (url === undefined) return;
|
||||
void fetch(url)
|
||||
@@ -51,6 +60,11 @@ function App() {
|
||||
.then((buffer) => setDoc(docOf(new Uint8Array(buffer))));
|
||||
}, [example]);
|
||||
|
||||
// The development page lets its browser tests read the document's drawing (never the editor embedded in the dashboard).
|
||||
useEffect(() => {
|
||||
(window as unknown as { filiusDev?: unknown }).filiusDev = doc === null ? undefined : { view: () => topologyView(doc) };
|
||||
}, [doc]);
|
||||
|
||||
const t = (key: string) => translate(language, key);
|
||||
return (
|
||||
<LanguageProvider language={language}>
|
||||
@@ -61,6 +75,7 @@ function App() {
|
||||
{t('dev.example')}{' '}
|
||||
<select value={example} onChange={(event) => setExample(event.target.value)}>
|
||||
<option value="" />
|
||||
<option value={NEW_PROJECT}>{t('dev.newProject')}</option>
|
||||
{Object.keys(EXAMPLES)
|
||||
.map((path) => path.slice(path.lastIndexOf('/') + 1))
|
||||
.sort()
|
||||
|
||||
Reference in New Issue
Block a user