feature/layout-updates #1
							
								
								
									
										14
									
								
								src/app.js
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								src/app.js
									
									
									
									
									
								
							| @ -64,7 +64,19 @@ const Audiogram =()=> | |||||||
|     <svg class="absolute top-0 w-full h-full overflow-visible stroke(blue-700 bold draw) opacity-50">${testMarksL}${testLinesL}</svg> |     <svg class="absolute top-0 w-full h-full overflow-visible stroke(blue-700 bold draw) opacity-50">${testMarksL}${testLinesL}</svg> | ||||||
|     <svg class="absolute top-0 w-full h-full overflow-visible stroke(red-700 bold draw)  opacity-50">${testMarksR}${testLinesR}</svg> |     <svg class="absolute top-0 w-full h-full overflow-visible stroke(red-700 bold draw)  opacity-50">${testMarksR}${testLinesR}</svg> | ||||||
|     <svg class="absolute top-0 w-full h-full overflow-visible stroke(blue-700 2 draw)">${userMarksL}${userLinesL}</svg> |     <svg class="absolute top-0 w-full h-full overflow-visible stroke(blue-700 2 draw)">${userMarksL}${userLinesL}</svg> | ||||||
|     <svg class="absolute top-0 w-full h-full overflow-visible stroke(red-700 2 draw)">${userMarksR}${userLinesR}</svg>`; |     <svg class="absolute top-0 w-full h-full overflow-visible stroke(red-700 2 draw)">${userMarksR}${userLinesR}</svg> | ||||||
|  |     <svg class="absolute top-0 w-full h-full overflow-visible" > | ||||||
|  |         <ellipse cx="0" cy="0" rx="5" ry="30" fill="url(#glow)"></ellipse> | ||||||
|  |         <ellipse cx="0" cy="0" rx="30" ry="5" fill="url(#glow)"></ellipse> | ||||||
|  |         <defs> | ||||||
|  |             <radialGradient id="glow"> | ||||||
|  |                 <stop stop-color="blue" stop-opacity="0.6" offset="0.0"></stop> | ||||||
|  |                 <stop stop-color="blue" stop-opacity="0.3" offset="0.2"></stop> | ||||||
|  |                 <stop stop-color="blue" stop-opacity="0.0" offset="1.0"></stop> | ||||||
|  |             </radialGradient> | ||||||
|  |         </defs> | ||||||
|  |     </svg> | ||||||
|  |     `;
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| React.render(html` | React.render(html` | ||||||
|  | |||||||
							
								
								
									
										64
									
								
								src/store.js
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								src/store.js
									
									
									
									
									
								
							| @ -28,8 +28,6 @@ export const ColumnLookup =(inFrequency)=> | |||||||
| /** @type {(freq:Store.TestFrequency, chan:number, user:boolean)=>Store.TestFrequencySample|undefined} */ | /** @type {(freq:Store.TestFrequency, chan:number, user:boolean)=>Store.TestFrequencySample|undefined} */ | ||||||
| export const MarkGet =(freq, chan, user)=> freq[/** @type {Store.PlotKey} */ (`${user ? "User" : "Test"}${chan ? "R" : "L"}`)]; | export const MarkGet =(freq, chan, user)=> freq[/** @type {Store.PlotKey} */ (`${user ? "User" : "Test"}${chan ? "R" : "L"}`)]; | ||||||
| 
 | 
 | ||||||
| /** @type {(freq:Store.TestFrequency, chan:number, mark:Store.TestFrequencySample|undefined)=>Store.TestFrequencySample|undefined} */ |  | ||||||
| export const MarkSet =(freq, chan, mark)=> freq[ chan ? "UserR" : "UserL" ] = mark; |  | ||||||
| 
 | 
 | ||||||
| /** @type {Store.State} */ | /** @type {Store.State} */ | ||||||
| export const Initial = | export const Initial = | ||||||
| @ -67,47 +65,37 @@ export const Initial = | |||||||
|     ] |     ] | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** @type {Record<string, Store.ContextUpdater>} */ | 
 | ||||||
| const Update = | /** @type {(inState:Store.State, inTest?:Store.Test)=>Store.Context} */ | ||||||
|  | const Reselect =(inState, inTest)=> | ||||||
| { | { | ||||||
|     Freq(inState) |     /** @type {Store.Context} */ | ||||||
|     { |     const output = { Test:inTest??inState.Live.Test }; | ||||||
|     const column = ColumnMapping[inState.Freq.Value]; |     const column = ColumnMapping[inState.Freq.Value]; | ||||||
|     if(column && inState.Live.Test) |     if(column && inState.Live.Test) | ||||||
|     { |     { | ||||||
|         const hz = column[0]; |         const hz = column[0]; | ||||||
|             inState.Live.Freq = undefined; |  | ||||||
|         for(let i=0; i<inState.Live.Test.Plot.length; i++) |         for(let i=0; i<inState.Live.Test.Plot.length; i++) | ||||||
|         { |         { | ||||||
|             const plot = inState.Live.Test.Plot[i]; |             const plot = inState.Live.Test.Plot[i]; | ||||||
|             if(plot.Hz == hz) |             if(plot.Hz == hz) | ||||||
|             { |             { | ||||||
|                     inState.Live.Freq = plot; |                 output.Freq = plot; | ||||||
|                     return true; |                 output.Mark = plot[`User${inState.Chan.Value ? "R" : "L"}`]; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|         return false; |     return output; | ||||||
|     }, |  | ||||||
|     Mark(inState) |  | ||||||
|     { |  | ||||||
|         const freq = inState.Live.Freq; |  | ||||||
|         if(freq) |  | ||||||
|         { |  | ||||||
|             inState.Live.Mark = MarkGet(freq, inState.Chan.Value, true); |  | ||||||
|             return true; |  | ||||||
|         } |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | /** @type {(inTest:Store.Test|undefined, inChan:number, inStim:Store.Range, inIsUser:boolean)=>Store.DrawGroup} */ | ||||||
| /** @type {(inTest:Store.Test, inChan:number, inStim:Store.Range, inIsUser:boolean)=>Store.DrawGroup} */ | const Redraw =(inTest, inChan, inStim, inIsUser)=> | ||||||
| export function Congtiguous(inTest, inChan, inStim, inIsUser) |  | ||||||
| { | { | ||||||
|     /** @type {Store.DrawGroup} */ |     /** @type {Store.DrawGroup} */ | ||||||
|     const output = {Points:[], Paths:[]}; |     const output = {Points:[], Paths:[]}; | ||||||
| 
 | 
 | ||||||
|  |     if(inTest) | ||||||
|  |     { | ||||||
|         let plot; |         let plot; | ||||||
|         for(let i=0; i<inTest.Plot.length; i++) |         for(let i=0; i<inTest.Plot.length; i++) | ||||||
|         { |         { | ||||||
| @ -137,6 +125,7 @@ export function Congtiguous(inTest, inChan, inStim, inIsUser) | |||||||
|                 output.Paths.push(line); |                 output.Paths.push(line); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|     return output; |     return output; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -149,24 +138,27 @@ export function Reducer(inState, inAction) | |||||||
| 
 | 
 | ||||||
|     if(Name == "Test") |     if(Name == "Test") | ||||||
|     { |     { | ||||||
|         clone.Live.Test = clone.Tests[Data]; |         const test = clone.Tests[Data]; | ||||||
|         Update.Freq(clone); |         clone.Live = Reselect(clone, test); | ||||||
|         Update.Mark(clone); |  | ||||||
|         clone.Draw = { |         clone.Draw = { | ||||||
|             UserL: Congtiguous(clone.Live.Test, 0, clone.Stim, true ), |             UserL: Redraw(test, 0, clone.Stim, true ), | ||||||
|             UserR: Congtiguous(clone.Live.Test, 1, clone.Stim, true ), |             UserR: Redraw(test, 1, clone.Stim, true ), | ||||||
|             TestL: Congtiguous(clone.Live.Test, 0, clone.Stim, false), |             TestL: Redraw(test, 0, clone.Stim, false), | ||||||
|             TestR: Congtiguous(clone.Live.Test, 1, clone.Stim, false) |             TestR: Redraw(test, 1, clone.Stim, false) | ||||||
|         }; |         }; | ||||||
|         clone.Live = {...clone.Live}; |  | ||||||
|     } |     } | ||||||
|     else if (Name == "Mark") |     else if (Name == "Mark") | ||||||
|     { |     { | ||||||
|         if(clone.Live.Test && clone.Live.Freq) |         if(clone.Live.Test && clone.Live.Freq) | ||||||
|         { |         { | ||||||
|             clone.Live.Mark = MarkSet(clone.Live.Freq, clone.Chan.Value, Data !== null ? {Stim:clone.Stim.Value, Resp:Data} : undefined); |             const key = clone.Chan.Value == 0 ? "UserL" : "UserR"; | ||||||
|             clone.Draw[clone.Chan.Value == 0 ? "UserL" : "UserR"] = Congtiguous(clone.Live.Test, clone.Chan.Value, clone.Stim, true); | 
 | ||||||
|  |             clone.Live.Mark = Data !== null ? {Stim:clone.Stim.Value, Resp:Data} : undefined; | ||||||
|  |             clone.Live.Freq[key] = clone.Live.Mark; | ||||||
|  |             clone.Live.Freq = {...clone.Live.Freq}; | ||||||
|             clone.Live = {...clone.Live}; |             clone.Live = {...clone.Live}; | ||||||
|  |              | ||||||
|  |             clone.Draw[key] = Redraw(clone.Live.Test, clone.Chan.Value, clone.Stim, true); | ||||||
|             clone.Draw = {...clone.Draw}; |             clone.Draw = {...clone.Draw}; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -179,9 +171,7 @@ export function Reducer(inState, inAction) | |||||||
|         clone[Name] = tone; |         clone[Name] = tone; | ||||||
|         if(Name != "Stim") |         if(Name != "Stim") | ||||||
|         { |         { | ||||||
|             Update.Freq(clone); |             clone.Live = Reselect(clone); | ||||||
|             Update.Mark(clone); |  | ||||||
|             clone.Live = {...clone.Live}; |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								src/ui.js
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								src/ui.js
									
									
									
									
									
								
							| @ -1,6 +1,6 @@ | |||||||
| import React from "https://esm.sh/preact@10.11.3/compat"; | import React from "https://esm.sh/preact@10.11.3/compat"; | ||||||
| import { html } from "https://esm.sh/htm@3.1.1/preact"; | import { html } from "https://esm.sh/htm@3.1.1/preact"; | ||||||
| import { ColumnMapping } from "./store.js"; | import * as Store from "./store.js"; | ||||||
| 
 | 
 | ||||||
| /** @typedef {({children}:{children?:preact.ComponentChildren})=>preact.VNode} BasicElement */ | /** @typedef {({children}:{children?:preact.ComponentChildren})=>preact.VNode} BasicElement */ | ||||||
| 
 | 
 | ||||||
| @ -37,10 +37,11 @@ export function Button({children, icon, light, disabled, inactive, onClick}) | |||||||
| /** @type {BasicElement} */ | /** @type {BasicElement} */ | ||||||
| export function Chart({children}) | export function Chart({children}) | ||||||
| { | { | ||||||
|  |     const [State] = Store.Consumer(); | ||||||
|     const inset = 20; |     const inset = 20; | ||||||
|     /** @type {Array<preact.VNode>} */ |     /** @type {Array<preact.VNode>} */ | ||||||
|     const rules = []; |     const rules = []; | ||||||
|     ColumnMapping.forEach(([label, position, normal])=> |     Store.ColumnMapping.forEach(([label, position, normal])=> | ||||||
|     { |     { | ||||||
|         rules.push(html` |         rules.push(html` | ||||||
|         <span class="block absolute top-[-${inset}px] left-[${position*100}%] w-0 h-[calc(100%+${inset*2}px)] border-r(1 slate-400) ${!normal && "border-dashed"}"> |         <span class="block absolute top-[-${inset}px] left-[${position*100}%] w-0 h-[calc(100%+${inset*2}px)] border-r(1 slate-400) ${!normal && "border-dashed"}"> | ||||||
| @ -49,12 +50,10 @@ export function Chart({children}) | |||||||
|         ); |         ); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     const dbMin = -10; |     for(let db = State.Stim.Min; db <= State.Stim.Max; db+=10) | ||||||
|     const dbMax = 120; |  | ||||||
|     for(let db = dbMin; db <= dbMax; db+=10) |  | ||||||
|     { |     { | ||||||
|         rules.push(html` |         rules.push(html` | ||||||
|         <span class="block absolute  left-[-${inset}px]   top-[${((db-dbMin) / (dbMax-dbMin))*100}%]   h-0 w-[calc(100%+${inset*2}px)] border-b(${db == 0 ? "2 black" : "1 slate-400"})"> |         <span class="block absolute  left-[-${inset}px]   top-[${((db-State.Stim.Min) / (State.Stim.Max-State.Stim.Min))*100}%]   h-0 w-[calc(100%+${inset*2}px)] border-b(${db == 0 ? "2 black" : "1 slate-400"})"> | ||||||
|             <span class="block absolute top-0 left-0 -translate-x-full -translate-y-1/2 pr-2">${db}</span> |             <span class="block absolute top-0 left-0 -translate-x-full -translate-y-1/2 pr-2">${db}</span> | ||||||
|         </span>` |         </span>` | ||||||
|         ); |         ); | ||||||
| @ -87,7 +86,6 @@ const Glyph = { | |||||||
|     <line vector-effect="non-scaling-stroke" x1="100%" y1="100%" x2="25%"  y2="100%"></line> |     <line vector-effect="non-scaling-stroke" x1="100%" y1="100%" x2="25%"  y2="100%"></line> | ||||||
|     <line vector-effect="non-scaling-stroke" x1="100%" y1="100%" x2="100%" y2="25%" ></line>`, |     <line vector-effect="non-scaling-stroke" x1="100%" y1="100%" x2="100%" y2="25%" ></line>`, | ||||||
| 
 | 
 | ||||||
|     //style="transform: translate(50%, 50%) rotate(-15deg) scale(0.5);"
 |  | ||||||
|     X: ({children})=> html` |     X: ({children})=> html` | ||||||
|     <line x1="-50%" y1="-50%" x2="50%" y2="50%" ></line> |     <line x1="-50%" y1="-50%" x2="50%" y2="50%" ></line> | ||||||
|     <line x1="-50%" y1="50%"  x2="50%" y2="-50%"></line> |     <line x1="-50%" y1="50%"  x2="50%" y2="-50%"></line> | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user