FIX: sửa lỗi vẽ grid sai trong PIANO ROLL GRID với snap
This commit is contained in:
+47
-47
@@ -3148,7 +3148,7 @@ const SubTabWaveform = ({
|
||||
const yOff = (y - cTop) / cHeight;
|
||||
return yOff <= 1 / 3 ? Math.max(0, Math.min(3, 3 * (1 - yOff * 3))) : Math.max(-30, Math.min(0, -30 * (yOff - 1 / 3) * (3 / 2)));
|
||||
};
|
||||
const snapVal = v => isPan ? Math.round(v * 20) / 20 : Math.round(v * 2) / 2;
|
||||
const snapValue = v => isPan ? Math.round(v * 20) / 20 : Math.round(v * 2) / 2;
|
||||
const snapTime = t => Math.round(t * 10) / 10;
|
||||
|
||||
// Check if clicking near existing node (any mode)
|
||||
@@ -3171,7 +3171,7 @@ const SubTabWaveform = ({
|
||||
const handleMouseMove = moveEvent => {
|
||||
const currentX = moveEvent.clientX - rect.left + scrollLeft;
|
||||
const ct = Math.max(0, Math.min(wallDuration, currentX / zoom));
|
||||
const val = snapVal(valFromY(moveEvent.clientY - rect.top));
|
||||
const val = snapValue(valFromY(moveEvent.clientY - rect.top));
|
||||
const updated = isPan ? {
|
||||
time: Math.min(snapTime(ct), wallDuration),
|
||||
pan: val
|
||||
@@ -3203,7 +3203,7 @@ const SubTabWaveform = ({
|
||||
const currentX = moveEvent.clientX - rect.left + scrollLeft;
|
||||
const ct = Math.max(0, Math.min(wallDuration, currentX / zoom));
|
||||
const t = +snapTime(ct).toFixed(3);
|
||||
const v = isPan ? +snapVal(valFromY(moveEvent.clientY - rect.top)).toFixed(2) : +snapVal(valFromY(moveEvent.clientY - rect.top)).toFixed(1);
|
||||
const v = isPan ? +snapValue(valFromY(moveEvent.clientY - rect.top)).toFixed(2) : +snapValue(valFromY(moveEvent.clientY - rect.top)).toFixed(1);
|
||||
const key = t + '|' + v;
|
||||
if (key !== lastKey) {
|
||||
pts.push({
|
||||
@@ -3225,10 +3225,10 @@ const SubTabWaveform = ({
|
||||
} else {
|
||||
const newNode = isPan ? {
|
||||
time: +snapTime(startTime).toFixed(3),
|
||||
pan: +snapVal(valFromY(e.clientY - rect.top)).toFixed(2)
|
||||
pan: +snapValue(valFromY(e.clientY - rect.top)).toFixed(2)
|
||||
} : {
|
||||
time: +snapTime(startTime).toFixed(3),
|
||||
db: +snapVal(valFromY(e.clientY - rect.top)).toFixed(1)
|
||||
db: +snapValue(valFromY(e.clientY - rect.top)).toFixed(1)
|
||||
};
|
||||
setSelectedNodeTime(newNode.time);
|
||||
const merged = mergeNodes(curNodes, [newNode]);
|
||||
@@ -3240,7 +3240,7 @@ const SubTabWaveform = ({
|
||||
const handleMouseMove = moveEvent => {
|
||||
const currentX = moveEvent.clientX - rect.left + scrollLeft;
|
||||
const ct = Math.max(0, Math.min(wallDuration, currentX / zoom));
|
||||
const val = snapVal(valFromY(moveEvent.clientY - rect.top));
|
||||
const val = snapValue(valFromY(moveEvent.clientY - rect.top));
|
||||
const updated = isPan ? {
|
||||
time: Math.min(snapTime(ct), wallDuration),
|
||||
pan: val
|
||||
@@ -5792,9 +5792,8 @@ Ví dụ: Nhạc phim epic, dàn nhạc giao hưởng, tempo 130 BPM, giọng Cm
|
||||
}, "Đóng"))));
|
||||
};
|
||||
|
||||
const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClose, onUpdateNotes, onSaveNotes, setSubTabs, onPlayPause, onStop, isPlaying, playPreviewNote, showToast, midiDevices, recordingState, recTempMidiNotes, onRecord, selectedMidiInputId, onMidiInputSelect, activeMidiPitches, onInstrumentSelect, onRescheduleMidi, onSeekPlayhead }) => {
|
||||
const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClose, onUpdateNotes, onSaveNotes, setSubTabs, onPlayPause, onStop, isPlaying, playPreviewNote, showToast, midiDevices, recordingState, recTempMidiNotes, onRecord, selectedMidiInputId, onMidiInputSelect, activeMidiPitches, onInstrumentSelect, onRescheduleMidi, onSeekPlayhead, snapValue, onSnapChange }) => {
|
||||
const [activeRollTool, setActiveRollTool] = React.useState('select');
|
||||
const [snapVal, setSnapVal] = React.useState('1');
|
||||
const [renderTick, setRenderTick] = React.useState(0);
|
||||
const [ccMode, setCcMode] = React.useState('velocity');
|
||||
const [rollZoom, setRollZoom] = React.useState(60); // local horizontal zoom factor
|
||||
@@ -5908,11 +5907,12 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
setSelectedNoteIds([]);
|
||||
};
|
||||
|
||||
const totalBeats = sessionSyncMode ? Math.max(rollBeats, sessionLengthBars * 4 + 16, 64) : Math.max(rollBeats, noteMaxBeat + 16, 64);
|
||||
const drawWidth = totalBeats * pixelsPerBeat;
|
||||
const rawTotalBeats = Math.max(rollBeats, noteMaxBeat + 16, 64);
|
||||
const drawWidth = rawTotalBeats * pixelsPerBeat;
|
||||
const [rollViewWidth, setRollViewWidth] = React.useState(800);
|
||||
const viewWidth = Math.max(drawWidth, rollViewWidth);
|
||||
const viewBeats = Math.ceil(viewWidth / pixelsPerBeat) + 4;
|
||||
const totalBeats = Math.max(rawTotalBeats, viewBeats + 32);
|
||||
|
||||
const [notes, setNotes] = React.useState(st.notes || []);
|
||||
const notesRef = React.useRef(notes);
|
||||
@@ -6147,17 +6147,17 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
|
||||
// Draw snap lines
|
||||
let snapBeats = 0.25;
|
||||
if (snapVal === '1') snapBeats = 1.0;
|
||||
else if (snapVal === '1/2') snapBeats = 0.5;
|
||||
else if (snapVal === '1/4') snapBeats = 0.25;
|
||||
else if (snapVal === '1/8') snapBeats = 0.125;
|
||||
else if (snapVal === '1/16') snapBeats = 0.0625;
|
||||
else if (snapVal === '4') snapBeats = 4.0;
|
||||
else if (snapVal === '1/32') snapBeats = 0.03125;
|
||||
if (snapValue === '1') snapBeats = 1.0;
|
||||
else if (snapValue === '1/2') snapBeats = 0.5;
|
||||
else if (snapValue === '1/4') snapBeats = 0.25;
|
||||
else if (snapValue === '1/8') snapBeats = 0.125;
|
||||
else if (snapValue === '1/16') snapBeats = 0.0625;
|
||||
else if (snapValue === '4') snapBeats = 4.0;
|
||||
else if (snapValue === '1/32') snapBeats = 0.03125;
|
||||
|
||||
for (let beat = 0; beat <= viewBeats; beat += snapBeats) {
|
||||
const x = beat * pixelsPerBeat;
|
||||
if (x > drawWidth) break;
|
||||
if (x > viewWidth) break;
|
||||
const isBar = beat % timeSigNum === 0;
|
||||
ctx.strokeStyle = isBar ? '#444450' : '#2d2d35';
|
||||
ctx.lineWidth = isBar ? 1.2 : 0.6;
|
||||
@@ -6175,9 +6175,9 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
ctx.fillStyle = layer.track_color || '#888';
|
||||
ctx.strokeStyle = layer.track_color || '#888';
|
||||
layer.notes.forEach(function(note) {
|
||||
var snapStart = snapVal !== 'free' ? getSnapBeat(note.relative_start_beat, snapVal) : note.relative_start_beat;
|
||||
var snapStart = snapValue !== 'free' ? getSnapBeat(note.relative_start_beat, snapValue) : note.relative_start_beat;
|
||||
var rawEnd = note.relative_start_beat + note.duration_beats;
|
||||
var snapEnd = snapVal !== 'free' ? getSnapBeat(rawEnd, snapVal) : rawEnd;
|
||||
var snapEnd = snapValue !== 'free' ? getSnapBeat(rawEnd, snapValue) : rawEnd;
|
||||
var x = (renderBeatOffset + snapStart) * pixelsPerBeat;
|
||||
var y = (127 - note.pitch) * NoteHeight;
|
||||
var w = Math.max(2, (snapEnd - snapStart) * pixelsPerBeat);
|
||||
@@ -6190,9 +6190,9 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
|
||||
// Layer 3: Active notes with velocity layer representation
|
||||
notes.forEach((note) => {
|
||||
const snapStart = snapVal !== 'free' ? getSnapBeat(note.start_beat, snapVal) : note.start_beat;
|
||||
const snapStart = snapValue !== 'free' ? getSnapBeat(note.start_beat, snapValue) : note.start_beat;
|
||||
const rawEnd = note.start_beat + note.duration_beats;
|
||||
const snapEnd = snapVal !== 'free' ? getSnapBeat(rawEnd, snapVal) : rawEnd;
|
||||
const snapEnd = snapValue !== 'free' ? getSnapBeat(rawEnd, snapValue) : rawEnd;
|
||||
const x = (renderBeatOffset + snapStart) * pixelsPerBeat;
|
||||
const y = (127 - note.pitch) * NoteHeight;
|
||||
const w = Math.max(2, (snapEnd - snapStart) * pixelsPerBeat);
|
||||
@@ -6215,9 +6215,9 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
// Draw real-time recording notes
|
||||
if (recordingState === 'RECORDING' && recTempMidiNotes && recTempMidiNotes.length > 0) {
|
||||
recTempMidiNotes.forEach(note => {
|
||||
const snapStart = snapVal !== 'free' ? getSnapBeat(note.start_beat, snapVal) : note.start_beat;
|
||||
const snapStart = snapValue !== 'free' ? getSnapBeat(note.start_beat, snapValue) : note.start_beat;
|
||||
const rawEnd = note.start_beat + (note.duration_beats || 0.25);
|
||||
const snapEnd = snapVal !== 'free' ? getSnapBeat(rawEnd, snapVal) : rawEnd;
|
||||
const snapEnd = snapValue !== 'free' ? getSnapBeat(rawEnd, snapValue) : rawEnd;
|
||||
const x = (renderBeatOffset + snapStart) * pixelsPerBeat;
|
||||
const y = (127 - note.pitch) * NoteHeight;
|
||||
const w = Math.max(2, (snapEnd - snapStart) * pixelsPerBeat);
|
||||
@@ -6266,7 +6266,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
}, [notes, snapVal, rollZoom, selectedNoteIds, selectionMarquee, st.currentTime, bpm, viewWidth, viewBeats, recordingState, recTempMidiNotes, showGhostNotes, sessionSyncMode, ghostLayers, renderBeatOffset, renderTick]);
|
||||
}, [notes, snapValue, rollZoom, selectedNoteIds, selectionMarquee, st.currentTime, bpm, viewWidth, viewBeats, recordingState, recTempMidiNotes, showGhostNotes, sessionSyncMode, ghostLayers, renderBeatOffset, renderTick]);
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
const canvas = ccCanvasRef.current;
|
||||
@@ -6406,7 +6406,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
} else {
|
||||
// Ctrl+click on empty space: start selection marquee
|
||||
setSelectedNoteIds([]);
|
||||
const snapStart = getSnapBeat(beat, snapVal);
|
||||
const snapStart = getSnapBeat(beat, snapValue);
|
||||
setSelectionMarquee({
|
||||
startBeat: snapStart, startPitch: pitch,
|
||||
currentBeat: snapStart, currentPitch: pitch
|
||||
@@ -6500,8 +6500,8 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
} else {
|
||||
// Click on empty space with pen tool: DRAW a new note (brush mode with visitedPitches)
|
||||
pushToUndo(notes);
|
||||
const start = getSnapBeat(beat, snapVal);
|
||||
const initialDur = getSnapDuration(snapVal);
|
||||
const start = getSnapBeat(beat, snapValue);
|
||||
const initialDur = getSnapDuration(snapValue);
|
||||
const noteId = 'note_' + Date.now() + Math.random().toString(36).substr(2, 5);
|
||||
const newNote = {
|
||||
id: noteId,
|
||||
@@ -6555,7 +6555,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
const pitch = 127 - Math.floor(y / NoteHeight);
|
||||
|
||||
if (selectionMarquee) {
|
||||
const snappedBeat = getSnapBeat(beat, snapVal);
|
||||
const snappedBeat = getSnapBeat(beat, snapValue);
|
||||
const marquee = {
|
||||
...selectionMarquee,
|
||||
currentBeat: snappedBeat,
|
||||
@@ -6624,7 +6624,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
const lastPitch = draggedNote.lastDrawnPitch !== undefined ? draggedNote.lastDrawnPitch : draggedNote.startOffsetPitch;
|
||||
const pitchChanged = snappedPitch !== lastPitch;
|
||||
const noteBeats = draggedNote.noteStartBeats || [];
|
||||
const defaultDur = getSnapDuration(snapVal);
|
||||
const defaultDur = getSnapDuration(snapValue);
|
||||
|
||||
function playDrawPreview(p, durMs) {
|
||||
stopPreviewNote();
|
||||
@@ -6730,7 +6730,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
return;
|
||||
}
|
||||
if (draggedNote.mode === 'scale') {
|
||||
const newEnd = getSnapBeat(Math.max(draggedNote.firstStart + 0.125, beat), snapVal);
|
||||
const newEnd = getSnapBeat(Math.max(draggedNote.firstStart + 0.125, beat), snapValue);
|
||||
const range = draggedNote.originalEnd - draggedNote.firstStart;
|
||||
if (range <= 0) return;
|
||||
const scaleFactor = Math.max(0.01, (newEnd - draggedNote.firstStart) / range);
|
||||
@@ -6754,7 +6754,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
return;
|
||||
}
|
||||
if (draggedNote.mode === 'resize') {
|
||||
const newDuration = getSnapBeat(Math.max(0.125, beat - draggedNote.originalStart), snapVal);
|
||||
const newDuration = getSnapBeat(Math.max(0.125, beat - draggedNote.originalStart), snapValue);
|
||||
setNotes(prev => prev.map((n, idx) => {
|
||||
if (idx !== draggedNote.idx) return n;
|
||||
return {
|
||||
@@ -6767,7 +6767,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
if (!firstOffset) return;
|
||||
const firstNote = notes.find(n => n.id === firstOffset.id);
|
||||
if (!firstNote) return;
|
||||
const deltaBeat = getSnapBeat(beat - draggedNote.startOffsetBeat, snapVal) - firstOffset.originalStartBeat;
|
||||
const deltaBeat = getSnapBeat(beat - draggedNote.startOffsetBeat, snapValue) - firstOffset.originalStartBeat;
|
||||
// Clamp so no note goes past beat 0
|
||||
const minOrigStart = Math.min(...draggedNote.selectedNotesOffset.map(o => o.originalStartBeat));
|
||||
const clampedDeltaBeat = minOrigStart + deltaBeat < 0 ? -minOrigStart : deltaBeat;
|
||||
@@ -6778,7 +6778,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
if (!offset) return n;
|
||||
return {
|
||||
...n,
|
||||
start_beat: getSnapBeat(Math.max(0, offset.originalStartBeat + clampedDeltaBeat), snapVal),
|
||||
start_beat: getSnapBeat(Math.max(0, offset.originalStartBeat + clampedDeltaBeat), snapValue),
|
||||
pitch: Math.max(0, Math.min(127, offset.originalPitch + deltaPitch))
|
||||
};
|
||||
}));
|
||||
@@ -6814,7 +6814,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
||||
const swallowContextMenuRef = React.useRef(false);
|
||||
|
||||
const findCCNoteIndex = (b, mouseY, ccH) => {
|
||||
const snapped = getSnapBeat(b, snapVal);
|
||||
const snapped = getSnapBeat(b, snapValue);
|
||||
const hits = [];
|
||||
notes.forEach((n, idx) => {
|
||||
if (snapped >= n.start_beat && snapped <= n.start_beat + n.duration_beats) {
|
||||
@@ -7199,8 +7199,8 @@ const beatSec = 60.0 / (parseInt(bpm) || 120);
|
||||
}, React.createElement("span", {
|
||||
className: "text-zinc-500 font-semibold"
|
||||
}, "Snap:"), React.createElement("select", {
|
||||
value: snapVal,
|
||||
onChange: e => { setSnapVal(e.target.value); setRenderTick(t => t + 1); },
|
||||
value: snapValue,
|
||||
onChange: e => { onSnapChange(e.target.value); setRenderTick(t => t + 1); },
|
||||
className: "bg-zinc-800 border border-zinc-700 text-zinc-300 rounded px-1.5 py-0.5 outline-none focus:border-yellow-500"
|
||||
}, ['free', '4', '1', '1/2', '1/4', '1/8', '1/16', '1/32'].map(v => React.createElement("option", {
|
||||
key: v,
|
||||
@@ -7335,7 +7335,7 @@ const beatSec = 60.0 / (parseInt(bpm) || 120);
|
||||
return;
|
||||
}
|
||||
if (e.shiftKey) {
|
||||
const beatSnap = getSnapBeat(clickBeat, snapVal);
|
||||
const beatSnap = getSnapBeat(clickBeat, snapValue);
|
||||
if (loopStartBeat === null) {
|
||||
setLoopStartBeat(Math.max(0, beatSnap - 4));
|
||||
setLoopEndBeat(Math.max(4, beatSnap));
|
||||
@@ -7351,7 +7351,7 @@ const beatSec = 60.0 / (parseInt(bpm) || 120);
|
||||
setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, currentTime: clickTime } : s));
|
||||
}
|
||||
}
|
||||
const snappedStartBeat = getSnapBeat(clickBeat, snapVal);
|
||||
const snappedStartBeat = getSnapBeat(clickBeat, snapValue);
|
||||
rulerDragRef.current = { startX: e.clientX, startBeat: snappedStartBeat, scrollLeft: e.currentTarget.scrollLeft };
|
||||
const onMove = (ev) => {
|
||||
const r = rulerScrollRef.current;
|
||||
@@ -7359,7 +7359,7 @@ const beatSec = 60.0 / (parseInt(bpm) || 120);
|
||||
const rRect = r.getBoundingClientRect();
|
||||
const bx = ev.clientX - rRect.left + rulerDragRef.current.scrollLeft;
|
||||
const rawBeat = Math.max(0, bx / pixelsPerBeat);
|
||||
const beat = getSnapBeat(rawBeat, snapVal);
|
||||
const beat = getSnapBeat(rawBeat, snapValue);
|
||||
if (Math.abs(ev.clientX - rulerDragRef.current.startX) > 5) {
|
||||
if (clickInRange) {
|
||||
const rangeWidth = loopEndBeat - loopStartBeat;
|
||||
@@ -7410,7 +7410,7 @@ const beatSec = 60.0 / (parseInt(bpm) || 120);
|
||||
if (!r) return;
|
||||
const rRect = r.getBoundingClientRect();
|
||||
const bx = ev.clientX - rRect.left + r.scrollLeft;
|
||||
const nBeat = Math.max(0, Math.min(loopEndBeat - 1, getSnapBeat(bx / pixelsPerBeat, snapVal)));
|
||||
const nBeat = Math.max(0, Math.min(loopEndBeat - 1, getSnapBeat(bx / pixelsPerBeat, snapValue)));
|
||||
setLoopStartBeat(nBeat);
|
||||
setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, selectionStart: nBeat * beatSec } : s));
|
||||
};
|
||||
@@ -7427,7 +7427,7 @@ const beatSec = 60.0 / (parseInt(bpm) || 120);
|
||||
if (!r) return;
|
||||
const rRect = r.getBoundingClientRect();
|
||||
const bx = ev.clientX - rRect.left + r.scrollLeft;
|
||||
const nBeat = Math.max(loopStartBeat + 1, getSnapBeat(bx / pixelsPerBeat, snapVal));
|
||||
const nBeat = Math.max(loopStartBeat + 1, getSnapBeat(bx / pixelsPerBeat, snapValue));
|
||||
setLoopEndBeat(nBeat);
|
||||
setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, selectionEnd: nBeat * beatSec } : s));
|
||||
};
|
||||
@@ -9059,13 +9059,13 @@ const App = () => {
|
||||
}
|
||||
};
|
||||
const [activeTool, setActiveTool] = useState('select'); // 'select' | 'grab' | 'razor'
|
||||
const [snapValue, setSnapValue] = useState('1'); // 'free', '1', '1/2', '1/4', '1/8', '1/16', '1/32'
|
||||
const [snapValue, onSnapChangeue] = useState('1'); // 'free', '1', '1/2', '1/4', '1/8', '1/16', '1/32'
|
||||
|
||||
const snapTime = (time, snapVal, bpmVal) => {
|
||||
if (snapVal === 'free') return time;
|
||||
const snapTime = (time, snapValue, bpmVal) => {
|
||||
if (snapValue === 'free') return time;
|
||||
const beatDuration = 60 / parseFloat(bpmVal || 120);
|
||||
let divisor = 1;
|
||||
if (snapVal === '4') divisor = 4; else if (snapVal === '1') divisor = 1; else if (snapVal === '1/2') divisor = 0.5; else if (snapVal === '1/4') divisor = 0.25; else if (snapVal === '1/8') divisor = 0.125; else if (snapVal === '1/16') divisor = 0.0625; else if (snapVal === '1/32') divisor = 0.03125;
|
||||
if (snapValue === '4') divisor = 4; else if (snapValue === '1') divisor = 1; else if (snapValue === '1/2') divisor = 0.5; else if (snapValue === '1/4') divisor = 0.25; else if (snapValue === '1/8') divisor = 0.125; else if (snapValue === '1/16') divisor = 0.0625; else if (snapValue === '1/32') divisor = 0.03125;
|
||||
const gridSpacing = beatDuration * divisor;
|
||||
return Math.round(time / gridSpacing) * gridSpacing;
|
||||
};
|
||||
@@ -18967,7 +18967,7 @@ const App = () => {
|
||||
className: "text-[14px] text-zinc-500 font-bold uppercase ml-2"
|
||||
}, "Snap"), /*#__PURE__*/React.createElement("select", {
|
||||
value: snapValue,
|
||||
onChange: e => setSnapValue(e.target.value),
|
||||
onChange: e => onSnapChangeue(e.target.value),
|
||||
className: "bg-black text-white text-[14px] px-1.5 py-0.5 rounded border border-zinc-700 focus:outline-none focus:border-cyan-500 font-mono cursor-pointer"
|
||||
}, /*#__PURE__*/React.createElement("option", {
|
||||
value: "free"
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user