فهرست منبع

test wiazrd in main view

JAQUIN_C 1 ماه پیش
والد
کامیت
9043bd4440
1فایلهای تغییر یافته به همراه108 افزوده شده و 33 حذف شده
  1. 108 33
      src/ClockBuilder.tsx

+ 108 - 33
src/ClockBuilder.tsx

@@ -2,42 +2,58 @@ import { useEffect, useMemo, useRef, useState } from "react";
 import ClockTimeline from "./assets/ClockTimeline";
 import { buildBlueprint } from "./blueprint/Blueprintbuilder";
 import { encodeBlueprintFileBrowser } from "./blueprint/parser";
-import type { ClockBlock, } from "./assets/types";
+import type { ClockBlock } from "./assets/types";
 import styles from "./ClockBuilder.module.css";
 import SelectedBlockPanel from "./assets/components/SelectedBlockPanel";
 import SelectSignal from "./assets/SelectSignal";
 import ExpressionInput from "./assets/components/ExpressionInpux";
 import { useClockStore } from "./store/useClockStore";
-
+import ClockWizard from "./assets/components/ClockWizard";
 
 export default function ClockBuilder() {
   //  Subscribe to the Global Store
   const {
-    duration, setDuration,
-    clockSignal, setClockSignal,
-    rows, rowOrder,
+    duration,
+    setDuration,
+    clockSignal,
+    setClockSignal,
+    rows,
+    rowOrder,
     blocks,
     selectedBlockIds,
-    addBlocks, removeBlocks,
-    loadState
+    addBlocks,
+    removeBlocks,
+    loadState,
   } = useClockStore();
 
   //  Local UI State (Keep this in the component!)
   const [displayUnit, setDisplayUnit] = useState<"s" | "m">("s");
-  const [beltReference, setBeltReference] = useState({ name: "turbo-belt", itemsPerSecond: 240 });
+  const [beltReference, setBeltReference] = useState({
+    name: "turbo-belt",
+    itemsPerSecond: 240,
+  });
   const [output, setOutput] = useState("");
-  const [status, setStatus] = useState<{ text: string; ok: boolean } | null>(null);
+  const [status, setStatus] = useState<{ text: string; ok: boolean } | null>(
+    null,
+  );
 
   // Derived Data for Exports/Generation
   // We convert our normalized Objects back to Arrays on the fly for the Factorio generator
-  const rowsArray = useMemo(() => rowOrder.map(id => rows[id]), [rows, rowOrder]);
+  const rowsArray = useMemo(
+    () => rowOrder.map((id) => rows[id]),
+    [rows, rowOrder],
+  );
   const blocksArray = useMemo(() => Object.values(blocks), [blocks]);
   const totalCombinators = useMemo(() => rowsArray.length + 1, [rowsArray]);
 
   // Keyboard Shortcuts (Ctrl+D and Delete)
   useEffect(() => {
     const isEditable = (el: Element | null) =>
-      !!el && (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT" || (el as HTMLElement).isContentEditable);
+      !!el &&
+      (el.tagName === "INPUT" ||
+        el.tagName === "TEXTAREA" ||
+        el.tagName === "SELECT" ||
+        (el as HTMLElement).isContentEditable);
 
     const handler = (e: KeyboardEvent) => {
       if (isEditable(document.activeElement)) return;
@@ -45,7 +61,7 @@ export default function ClockBuilder() {
       if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "d") {
         e.preventDefault();
         if (selectedBlockIds.size === 0) return;
-        
+
         const clones: ClockBlock[] = [];
         selectedBlockIds.forEach((id) => {
           const b = blocks[id];
@@ -57,7 +73,7 @@ export default function ClockBuilder() {
             });
           }
         });
-        
+
         // Use the new batch action
         addBlocks(clones);
       } else if (e.key === "Delete") {
@@ -74,8 +90,15 @@ export default function ClockBuilder() {
   // File I/O
   const handleSaveFile = () => {
     // We save the original array format for backward compatibility
-    const config = { duration, clockSignal, rows: rowsArray, blocks: blocksArray };
-    const blob = new Blob([JSON.stringify(config, null, 2)], { type: "application/json" });
+    const config = {
+      duration,
+      clockSignal,
+      rows: rowsArray,
+      blocks: blocksArray,
+    };
+    const blob = new Blob([JSON.stringify(config, null, 2)], {
+      type: "application/json",
+    });
     const url = URL.createObjectURL(blob);
     const a = document.createElement("a");
     a.href = url;
@@ -92,10 +115,14 @@ export default function ClockBuilder() {
     reader.onload = () => {
       try {
         const parsed = JSON.parse(reader.result as string);
-        
+
         // Re-normalize the saved array data before injecting it into the store
-        const loadedRows = Object.fromEntries(parsed.rows.map((r: any) => [r.id, r]));
-        const loadedBlocks = Object.fromEntries(parsed.blocks.map((b: any) => [b.id, b]));
+        const loadedRows = Object.fromEntries(
+          parsed.rows.map((r: any) => [r.id, r]),
+        );
+        const loadedBlocks = Object.fromEntries(
+          parsed.blocks.map((b: any) => [b.id, b]),
+        );
         const loadedRowOrder = parsed.rows.map((r: any) => r.id);
 
         loadState({
@@ -104,9 +131,9 @@ export default function ClockBuilder() {
           rows: loadedRows,
           rowOrder: loadedRowOrder,
           blocks: loadedBlocks,
-          selectedBlockIds: new Set()
+          selectedBlockIds: new Set(),
         });
-        
+
         setStatus({ text: "Clock loaded.", ok: true });
       } catch {
         setStatus({ text: "That file isn't a valid clock export.", ok: false });
@@ -119,15 +146,26 @@ export default function ClockBuilder() {
   // Factorio Blueprint Generation
   const handleGenerate = () => {
     if (rowsArray.length === 0 || blocksArray.length === 0) {
-      setStatus({ text: "Add at least one row and one block first.", ok: false });
+      setStatus({
+        text: "Add at least one row and one block first.",
+        ok: false,
+      });
       return;
     }
     try {
       // Passes the derived arrays to the existing blueprint logic
-      const bp = buildBlueprint({ duration, clockSignal, rows: rowsArray, blocks: blocksArray });
+      const bp = buildBlueprint({
+        duration,
+        clockSignal,
+        rows: rowsArray,
+        blocks: blocksArray,
+      });
       const str = encodeBlueprintFileBrowser(bp);
       setOutput(str);
-      setStatus({ text: `Generated — ${bp.blueprint.entities.length} combinators.`, ok: true });
+      setStatus({
+        text: `Generated — ${bp.blueprint.entities.length} combinators.`,
+        ok: true,
+      });
     } catch (err) {
       setStatus({ text: `Error: ${(err as Error).message}`, ok: false });
     }
@@ -153,11 +191,17 @@ export default function ClockBuilder() {
 
         <div className={styles.field}>
           <label>Clock signal icon</label>
-          <SelectSignal value={clockSignal?.name} onSelectSignal={(_, sig) => setClockSignal(sig)} />
+          <SelectSignal
+            value={clockSignal?.name}
+            onSelectSignal={(_, sig) => setClockSignal(sig)}
+          />
         </div>
         <div className={styles.field}>
           <label>Throughput unit</label>
-          <select value={displayUnit} onChange={(e) => setDisplayUnit(e.target.value as "s" | "m")}>
+          <select
+            value={displayUnit}
+            onChange={(e) => setDisplayUnit(e.target.value as "s" | "m")}
+          >
             <option value="s">items/s</option>
             <option value="m">items/min</option>
           </select>
@@ -167,18 +211,27 @@ export default function ClockBuilder() {
           <input
             type="text"
             value={beltReference.name}
-            onChange={(e) => setBeltReference({ ...beltReference, name: e.target.value })}
+            onChange={(e) =>
+              setBeltReference({ ...beltReference, name: e.target.value })
+            }
           />
           <input
             type="number"
             value={beltReference.itemsPerSecond}
-            onChange={(e) => setBeltReference({ ...beltReference, itemsPerSecond: Number(e.target.value) || 0 })}
+            onChange={(e) =>
+              setBeltReference({
+                ...beltReference,
+                itemsPerSecond: Number(e.target.value) || 0,
+              })
+            }
           />
         </div>
       </div>
+      <ClockWizard />
 
+      <hr className={styles.divider} />
       <ClockTimeline />
-      
+
       <SelectedBlockPanel />
 
       <div className={styles.footer}>
@@ -186,7 +239,11 @@ export default function ClockBuilder() {
           <button className={styles.generateBtn} onClick={handleGenerate}>
             Generate blueprint
           </button>
-          <button className={styles.copyBtn} onClick={handleCopy} disabled={!output}>
+          <button
+            className={styles.copyBtn}
+            onClick={handleCopy}
+            disabled={!output}
+          >
             Copy string
           </button>
           <span className={styles.count}>
@@ -195,13 +252,31 @@ export default function ClockBuilder() {
           <button className={styles.copyBtn} onClick={handleSaveFile}>
             Save clock
           </button>
-          <input ref={fileInputRef} type="file" accept="application/json" hidden onChange={handleLoadFile} />
-          <button className={styles.copyBtn} onClick={() => fileInputRef.current?.click()}>
+          <input
+            ref={fileInputRef}
+            type="file"
+            accept="application/json"
+            hidden
+            onChange={handleLoadFile}
+          />
+          <button
+            className={styles.copyBtn}
+            onClick={() => fileInputRef.current?.click()}
+          >
             Load clock
           </button>
-          {status && <span className={status.ok ? styles.statusOk : styles.statusErr}>{status.text}</span>}
+          {status && (
+            <span className={status.ok ? styles.statusOk : styles.statusErr}>
+              {status.text}
+            </span>
+          )}
         </div>
-        <textarea className={styles.output} readOnly value={output} placeholder="Blueprint string will appear here…" />
+        <textarea
+          className={styles.output}
+          readOnly
+          value={output}
+          placeholder="Blueprint string will appear here…"
+        />
       </div>
     </div>
   );