adjust Pulse List layout.
This commit is contained in:
		| @@ -5,14 +5,17 @@ | ||||
|     justify-content: flex-end; | ||||
|     align-items: center; | ||||
|     gap: calc(var(--spacing) * 2); | ||||
|   } | ||||
|     .attribute_unit { | ||||
|       display: flex; | ||||
|       flex-direction: row; | ||||
|       align-items: center; | ||||
|       gap: calc(var(--spacing)); | ||||
|       font-size: var(--body-small-font-size); | ||||
|       line-height: var(--body-small-line-height); | ||||
|       font-weight: var(--body-small-font-weight); | ||||
|       label { | ||||
|       font-weight: bold; | ||||
|         font-weight: 500; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   .pulses { | ||||
|   | ||||
| @@ -1,39 +1,46 @@ | ||||
| import { DndContext } from '@dnd-kit/core'; | ||||
| import { Icon } from '@iconify/react/dist/iconify.js'; | ||||
| import { useAtomValue } from 'jotai'; | ||||
| import { FC } from 'react'; | ||||
| import { useAtom, useAtomValue } from 'jotai'; | ||||
| import { max } from 'lodash-es'; | ||||
| import { FC, useCallback, useMemo } from 'react'; | ||||
| import { ScrollArea } from '../../components/ScrollArea'; | ||||
| import { addPulse, deletePulse } from '../../context/pattern-model'; | ||||
| import { | ||||
|   CurrentPatternAtom, | ||||
|   CurrentPatternDuration, | ||||
|   PulsesInCurrentPatternAtom, | ||||
|   SelectedPulseAtom, | ||||
|   useSavePattern, | ||||
| } from '../../context/Patterns'; | ||||
| import PulseCard from './PulseCard'; | ||||
| import styles from './PulseList.module.css'; | ||||
|  | ||||
| const PulseList: FC = () => { | ||||
|   const pattern = useAtomValue(CurrentPatternAtom); | ||||
|   const pulses = useAtomValue(PulsesInCurrentPatternAtom); | ||||
|   const [pattern, refreshPattern] = useAtom(CurrentPatternAtom); | ||||
|   const duration = useAtomValue(CurrentPatternDuration); | ||||
|   const selectedPulse = useAtomValue(SelectedPulseAtom); | ||||
|   const maxPulseOrder = useMemo( | ||||
|     () => max(pattern?.pulses.map((pulse) => pulse.order) ?? []), | ||||
|     [pattern], | ||||
|   ); | ||||
|   const savePattern = useSavePattern(); | ||||
|  | ||||
|   const handleAddPulseAction = useCallback(async () => { | ||||
|     if (!pattern) return; | ||||
|     addPulse(pattern); | ||||
|     await savePattern(pattern); | ||||
|     refreshPattern(); | ||||
|   }, [pattern]); | ||||
|   const handleDeletePulseAction = useCallback(async () => { | ||||
|     if (!pattern || !selectedPulse) return; | ||||
|     deletePulse(pattern, selectedPulse.id); | ||||
|     await savePattern(pattern); | ||||
|     refreshPattern(); | ||||
|   }, [pattern, selectedPulse]); | ||||
|  | ||||
|   return ( | ||||
|     <> | ||||
|       <div className={styles.pulse_tools}> | ||||
|         <button className="text"> | ||||
|           <Icon icon="material-symbols-light:play-arrow-outline" /> | ||||
|           <span>Test Run</span> | ||||
|         </button> | ||||
|         <button className="text"> | ||||
|           <Icon icon="material-symbols-light:add" /> | ||||
|           <span>Add Pulse</span> | ||||
|         </button> | ||||
|         <button className="text"> | ||||
|           <Icon icon="material-symbols-light:delete-forever-outline" /> | ||||
|           <span>Delete Selected</span> | ||||
|         </button> | ||||
|       </div> | ||||
|       <div className={styles.pulse_tools}> | ||||
|         <div className={styles.attribute_unit}> | ||||
|           <span>{pulses.length ?? 0}</span> | ||||
|           <span>{pattern?.pulses.length ?? 0}</span> | ||||
|           <label>Key Pulses</label> | ||||
|         </div> | ||||
|         <div className={styles.attribute_unit}> | ||||
| @@ -41,13 +48,43 @@ const PulseList: FC = () => { | ||||
|           <span>{duration.toFixed(2)} s</span> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div className={styles.pulse_tools}> | ||||
|         <button className="text" disabled> | ||||
|           <Icon icon="material-symbols-light:play-arrow-outline" /> | ||||
|           <span>Test Run</span> | ||||
|         </button> | ||||
|         <button className="text" onClick={handleAddPulseAction}> | ||||
|           <Icon icon="material-symbols-light:add" /> | ||||
|           <span>Add Pulse</span> | ||||
|         </button> | ||||
|         <button className="text" onClick={handleDeletePulseAction} disabled={!selectedPulse}> | ||||
|           <Icon icon="material-symbols-light:delete-forever-outline" /> | ||||
|           <span>Delete Selected</span> | ||||
|         </button> | ||||
|       </div> | ||||
|       <div className={styles.pulse_tools}> | ||||
|         <button className="text" disabled={!selectedPulse || selectedPulse.order === 1}> | ||||
|           <Icon icon="material-symbols-light:arrow-upward" /> | ||||
|           <span>Move Up</span> | ||||
|         </button> | ||||
|         <button className="text" disabled={!selectedPulse || selectedPulse.order === maxPulseOrder}> | ||||
|           <Icon icon="material-symbols-light:arrow-downward" /> | ||||
|           <span>Move Down</span> | ||||
|         </button> | ||||
|       </div> | ||||
|       <div className={styles.pulses}> | ||||
|         <ScrollArea enableY> | ||||
|           <DndContext> | ||||
|           <div className={styles.pulse_cards}> | ||||
|               {pulses.length === 0 && <div className="empty_prompt">No key pulses.</div>} | ||||
|             {pattern?.pulses.length === 0 ? ( | ||||
|               <div className="empty_prompt">No key pulses.</div> | ||||
|             ) : ( | ||||
|               <> | ||||
|                 {pattern?.pulses.map((pulse) => ( | ||||
|                   <PulseCard key={pulse.id} pulse={pulse} /> | ||||
|                 ))} | ||||
|               </> | ||||
|             )} | ||||
|           </div> | ||||
|           </DndContext> | ||||
|         </ScrollArea> | ||||
|       </div> | ||||
|     </> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user