| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- import { useMemo } from "react";
- import Icon from "./icon";
- import styles from "./ClockTimeline.module.css";
- import { ACTION_PRESETS } from "./types";
- import TimelineRow from "./components/TimelineRow";
- import { useClockStore } from "../store/useClockStore";
- type Props = {};
- export const defaultActivationSignal = {
- type: "virtual-signal",
- name: "signal-check",
- subgroup: "virtual-signal",
- icon: "virtual-signal/signal-check.png",
- order: "a[checked]",
- };
- export default function ClockTimeline({}: Props) {
- const { duration, rowOrder, alignmentTick, addRow } = useClockStore();
- const majorTicks = useMemo(() => {
- const step = Math.max(1, Math.round(duration / 10));
- const out: number[] = [];
- for (let t = 0; t <= duration; t += step) out.push(t);
- return out;
- }, [duration]);
- const onPaletteDragStart = (e: React.DragEvent, presetId: string) => {
- e.dataTransfer.setData("text/plain", presetId);
- e.dataTransfer.effectAllowed = "copy";
- };
- const handleAddRow = () => {
- addRow({
- id: `row-${Date.now()}`,
- name: `Row ${rowOrder.length + 1}`,
- signals: [defaultActivationSignal],
- stackSize: 16,
- inserterCount: 1,
- });
- };
- return (
- <div className={styles.wrap}>
- <div className={styles.palette}>
- {ACTION_PRESETS.map((p) => (
- <div
- key={p.id}
- className={styles.chip}
- draggable
- onDragStart={(e) => onPaletteDragStart(e, p.id)}
- >
- {p.fromItem && (
- <Icon iconName={`item/${p.fromItem}.png`} size={20} />
- )}
- <span>{p.label}</span>
- <span className={styles.chipTicks}>{p.ticks}t</span>
- </div>
- ))}
- <span className={styles.hint}>
- Drag onto a row · Shift-click to multi-select · Ctrl+D to duplicate
- </span>
- </div>
- <div className={styles.ruler}>
- {majorTicks.map((t) => (
- <div
- key={t}
- className={styles.rulerTick}
- style={{ left: `${(t / duration) * 100}%` }}
- >
- <span>{t}</span>
- </div>
- ))}
- <div className={styles.rulerReset} />
- </div>
- <div className={styles.rows}>
- {alignmentTick !== null && (
- <div
- className={styles.alignGuide}
- style={{ left: `${(alignmentTick / duration) * 100}%` }}
- />
- )}
- {rowOrder.map((rowId) => (
- <TimelineRow key={rowId} rowId={rowId} />
- ))}
- <button className={styles.addRowBtn} onClick={handleAddRow}>
- + Add row
- </button>
- </div>
- </div>
- );
- }
|