feature/layout-updates #1
							
								
								
									
										30
									
								
								src/app.js
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								src/app.js
									
									
									
									
									
								
							| @ -49,31 +49,29 @@ const Audiogram =()=> | |||||||
| { | { | ||||||
|     const [State] = Store.Consumer(); |     const [State] = Store.Consumer(); | ||||||
| 
 | 
 | ||||||
|     /** @type {(inAmount:number)=>string} */ const Perc =(inAmount)=> (inAmount*100)+"%"; |     const testMarksL = State.Draw.TestL.Points.map(p=>html`<${UI.Mark} x=${p.X} y=${p.Y} response=${p.Mark?.Resp} right=${false}/>`); | ||||||
|  |     const userMarksL = State.Draw.UserL.Points.map(p=>html`<${UI.Mark} x=${p.X} y=${p.Y} response=${p.Mark?.Resp} right=${false} classes=${State.Live.Mark == p.Mark ? "stroke-bold":""}/>`); | ||||||
|  |     const testMarksR = State.Draw.TestR.Points.map(p=>html`<${UI.Mark} x=${p.X} y=${p.Y} response=${p.Mark?.Resp} right=${true} />`); | ||||||
|  |     const userMarksR = State.Draw.UserR.Points.map(p=>html`<${UI.Mark} x=${p.X} y=${p.Y} response=${p.Mark?.Resp} right=${true} classes=${State.Live.Mark == p.Mark ? "stroke-bold":""}/>`); | ||||||
| 
 | 
 | ||||||
|     const testMarksL = State.Draw.TestL.Points.map(p=>html`<${UI.Mark} x=${Perc(p.X)} y=${Perc(p.Y)} response=${p.Mark.Resp} right=${false}/>`); |     const testLinesL = State.Draw.TestL.Paths.map( p=>html`<line class="opacity-60" x1=${p.Head.X} y1=${p.Head.Y} x2=${p.Tail.X} y2=${p.Tail.Y} />`); | ||||||
|     const userMarksL = State.Draw.UserL.Points.map(p=>html`<${UI.Mark} x=${Perc(p.X)} y=${Perc(p.Y)} response=${p.Mark.Resp} right=${false} classes=${State.Live.Mark == p.Mark ? "stroke-bold":""}/>`); |     const userLinesL = State.Draw.UserL.Paths.map( p=>html`<line class="opacity-60" x1=${p.Head.X} y1=${p.Head.Y} x2=${p.Tail.X} y2=${p.Tail.Y} />`); | ||||||
|     const testMarksR = State.Draw.TestR.Points.map(p=>html`<${UI.Mark} x=${Perc(p.X)} y=${Perc(p.Y)} response=${p.Mark.Resp} right=${true} />`); |     const testLinesR = State.Draw.TestR.Paths.map( p=>html`<line class="opacity-60" x1=${p.Head.X} y1=${p.Head.Y} x2=${p.Tail.X} y2=${p.Tail.Y} />`); | ||||||
|     const userMarksR = State.Draw.UserR.Points.map(p=>html`<${UI.Mark} x=${Perc(p.X)} y=${Perc(p.Y)} response=${p.Mark.Resp} right=${true} classes=${State.Live.Mark == p.Mark ? "stroke-bold":""}/>`); |     const userLinesR = State.Draw.UserR.Paths.map( p=>html`<line class="opacity-60" x1=${p.Head.X} y1=${p.Head.Y} x2=${p.Tail.X} y2=${p.Tail.Y} />`); | ||||||
| 
 |  | ||||||
|     const testLinesL = State.Draw.TestL.Paths.map( p=>html`<line class="opacity-60" x1=${Perc(p.Head.X)} y1=${Perc(p.Head.Y)} x2=${Perc(p.Tail.X)} y2=${Perc(p.Tail.Y)} />`); |  | ||||||
|     const userLinesL = State.Draw.UserL.Paths.map( p=>html`<line class="opacity-60" x1=${Perc(p.Head.X)} y1=${Perc(p.Head.Y)} x2=${Perc(p.Tail.X)} y2=${Perc(p.Tail.Y)} />`); |  | ||||||
|     const testLinesR = State.Draw.TestR.Paths.map( p=>html`<line class="opacity-60" x1=${Perc(p.Head.X)} y1=${Perc(p.Head.Y)} x2=${Perc(p.Tail.X)} y2=${Perc(p.Tail.Y)} />`); |  | ||||||
|     const userLinesR = State.Draw.UserR.Paths.map( p=>html`<line class="opacity-60" x1=${Perc(p.Head.X)} y1=${Perc(p.Head.Y)} x2=${Perc(p.Tail.X)} y2=${Perc(p.Tail.Y)} />`); |  | ||||||
| 
 | 
 | ||||||
|     return html` |     return html` | ||||||
|     <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" > |     <svg class="absolute top-0 w-full h-full overflow-visible transition-all duration-500" style=${{top:State.Draw.Cross?.Y, left:State.Draw.Cross?.X}}> | ||||||
|         <ellipse cx="0" cy="0" rx="5" ry="30" fill="url(#glow)"></ellipse> |         <ellipse cx="0" cy="0" rx="8" ry="30" fill="url(#glow)"></ellipse> | ||||||
|         <ellipse cx="0" cy="0" rx="30" ry="5" fill="url(#glow)"></ellipse> |         <ellipse cx="0" cy="0" rx="30" ry="8" fill="url(#glow)"></ellipse> | ||||||
|         <defs> |         <defs> | ||||||
|             <radialGradient id="glow"> |             <radialGradient id="glow"> | ||||||
|                 <stop stop-color="blue" stop-opacity="0.6" offset="0.0"></stop> |                 <stop stop-color=${State.Chan.Value ? "red" : "blue"} stop-opacity="0.6" offset="0.0"></stop> | ||||||
|                 <stop stop-color="blue" stop-opacity="0.3" offset="0.2"></stop> |                 <stop stop-color=${State.Chan.Value ? "red" : "blue"} stop-opacity="0.3" offset="0.2"></stop> | ||||||
|                 <stop stop-color="blue" stop-opacity="0.0" offset="1.0"></stop> |                 <stop stop-color=${State.Chan.Value ? "red" : "blue"} stop-opacity="0.0" offset="1.0"></stop> | ||||||
|             </radialGradient> |             </radialGradient> | ||||||
|         </defs> |         </defs> | ||||||
|     </svg> |     </svg> | ||||||
|  | |||||||
							
								
								
									
										30
									
								
								src/store.js
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								src/store.js
									
									
									
									
									
								
							| @ -25,6 +25,9 @@ export const ColumnLookup =(inFrequency)=> | |||||||
|     return false; |     return false; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /** @type {(inDecimal:number)=>string} */ | ||||||
|  | const Perc =(inDecimal)=> `${inDecimal*100}%`; | ||||||
|  | 
 | ||||||
| /** Creates a new Store.Context object that contain the current selections  | /** Creates a new Store.Context object that contain the current selections  | ||||||
|  * @type {(inState:Store.State, inTest?:Store.Test)=>Store.Context} */ |  * @type {(inState:Store.State, inTest?:Store.Test)=>Store.Context} */ | ||||||
| const Reselect =(inState, inTest)=> | const Reselect =(inState, inTest)=> | ||||||
| @ -69,8 +72,8 @@ const Redraw =(inTest, inChan, inStim, inIsUser)=> | |||||||
|                 { |                 { | ||||||
|                     /** @type {Store.DrawPoint} */ |                     /** @type {Store.DrawPoint} */ | ||||||
|                     const point = { |                     const point = { | ||||||
|                         X: lookup[1], |                         X: Perc(lookup[1]), | ||||||
|                         Y: (mark.Stim - inStim.Min)/(inStim.Max - inStim.Min), |                         Y: Perc((mark.Stim - inStim.Min)/(inStim.Max - inStim.Min)), | ||||||
|                         Mark: mark |                         Mark: mark | ||||||
|                     }; |                     }; | ||||||
|                     output.Points.push(point); |                     output.Points.push(point); | ||||||
| @ -81,14 +84,21 @@ const Redraw =(inTest, inChan, inStim, inIsUser)=> | |||||||
|         { |         { | ||||||
|             /** @type {Store.DrawLine} */ |             /** @type {Store.DrawLine} */ | ||||||
|             const line = {Head:output.Points[i-1], Tail:output.Points[i]}; |             const line = {Head:output.Points[i-1], Tail:output.Points[i]}; | ||||||
|             if(line.Head.Mark.Resp && line.Tail.Mark.Resp) |             if(line.Head.Mark?.Resp && line.Tail.Mark?.Resp) | ||||||
|             { |             { | ||||||
|                 output.Paths.push(line); |                 output.Paths.push(line); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     return output; |     return output; | ||||||
| } | }; | ||||||
|  | 
 | ||||||
|  | /** Create a new cursor position from the state | ||||||
|  |  * @type {(inState:Store.State)=>Store.DrawPoint} */ | ||||||
|  | const Reposition =(inState)=> ({ | ||||||
|  |     X: Perc(ColumnMapping[inState.Freq.Value][1]), | ||||||
|  |     Y: Perc((inState.Stim.Value - inState.Stim.Min)/(inState.Stim.Max - inState.Stim.Min)) | ||||||
|  | }); | ||||||
| 
 | 
 | ||||||
| /** @type {Store.Reducer} */ | /** @type {Store.Reducer} */ | ||||||
| export function Reducer(inState, inAction) | export function Reducer(inState, inAction) | ||||||
| @ -100,7 +110,9 @@ export function Reducer(inState, inAction) | |||||||
|     { |     { | ||||||
|         const test = clone.Tests[Data]; |         const test = clone.Tests[Data]; | ||||||
|         clone.Live = Reselect(clone, test); |         clone.Live = Reselect(clone, test); | ||||||
|         clone.Draw = { |         clone.Draw = | ||||||
|  |         { | ||||||
|  |             Cross: Reposition(clone), | ||||||
|             UserL: Redraw(test, 0, clone.Stim, true ), |             UserL: Redraw(test, 0, clone.Stim, true ), | ||||||
|             UserR: Redraw(test, 1, clone.Stim, true ), |             UserR: Redraw(test, 1, clone.Stim, true ), | ||||||
|             TestL: Redraw(test, 0, clone.Stim, false), |             TestL: Redraw(test, 0, clone.Stim, false), | ||||||
| @ -123,6 +135,8 @@ export function Reducer(inState, inAction) | |||||||
|         tone.Value += Data*tone.Step; |         tone.Value += Data*tone.Step; | ||||||
|         tone.Value = Math.max(tone.Value, tone.Min); |         tone.Value = Math.max(tone.Value, tone.Min); | ||||||
|         tone.Value = Math.min(tone.Value, tone.Max); |         tone.Value = Math.min(tone.Value, tone.Max); | ||||||
|  | 
 | ||||||
|  |         clone.Draw.Cross = Reposition(clone); | ||||||
|         if(Name != "Stim") |         if(Name != "Stim") | ||||||
|         { |         { | ||||||
|             clone.Live = Reselect(clone); |             clone.Live = Reselect(clone); | ||||||
| @ -133,7 +147,7 @@ export function Reducer(inState, inAction) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** @type {Store.State} */ | /** @type {Store.State} */ | ||||||
| export const Initial = | export const Initial = Reducer( | ||||||
| { | { | ||||||
|     Chan: { Min:0,   Max:1,   Value:0,  Step:1 }, |     Chan: { Min:0,   Max:1,   Value:0,  Step:1 }, | ||||||
|     Freq: { Min:2,   Max:8,   Value:2,  Step:1 }, |     Freq: { Min:2,   Max:8,   Value:2,  Step:1 }, | ||||||
| @ -166,7 +180,7 @@ export const Initial = | |||||||
|             ] |             ] | ||||||
|         } |         } | ||||||
|     ] |     ] | ||||||
| }; | }, {Name:"Test", Data:0}); | ||||||
| 
 | 
 | ||||||
| /** @type {preact.Context<Store.Binding>} */ | /** @type {preact.Context<Store.Binding>} */ | ||||||
| export const Context = React.createContext([Initial, (_a)=>{}]); | export const Context = React.createContext([Initial, (_a)=>{}]); | ||||||
| @ -175,7 +189,7 @@ export const Context = React.createContext([Initial, (_a)=>{}]); | |||||||
| export const Provider =(props)=> | export const Provider =(props)=> | ||||||
| { | { | ||||||
|     /** @type {Store.Binding} */ |     /** @type {Store.Binding} */ | ||||||
|     const reducer = React.useReducer(Reducer, Initial, ()=>Reducer(Initial, {Name:"Test", Data:0})); |     const reducer = React.useReducer(Reducer, Initial); | ||||||
|     return React.createElement(Context.Provider, {value:reducer, children:props.children}); |     return React.createElement(Context.Provider, {value:reducer, children:props.children}); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										6
									
								
								store.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								store.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -25,7 +25,7 @@ declare namespace Store { | |||||||
|     Freq: Range; |     Freq: Range; | ||||||
|     Stim: Range; |     Stim: Range; | ||||||
|     Live: Context; |     Live: Context; | ||||||
|     Draw: DrawTest; |     Draw: DrawChart; | ||||||
|     Tests: Array<Test>; |     Tests: Array<Test>; | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
| @ -42,10 +42,10 @@ declare namespace Store { | |||||||
|   type PlotKeyTest = "TestL" | "TestR"; |   type PlotKeyTest = "TestL" | "TestR"; | ||||||
|   type PlotKey = PlotKeyUser | PlotKeyTest; |   type PlotKey = PlotKeyUser | PlotKeyTest; | ||||||
| 
 | 
 | ||||||
|   type DrawPoint = { X: number; Y: number; Mark: TestFrequencySample }; |   type DrawPoint = { X: string; Y: string; Mark?: TestFrequencySample }; | ||||||
|   type DrawLine = { Head:DrawPoint, Tail:DrawPoint}; |   type DrawLine = { Head:DrawPoint, Tail:DrawPoint}; | ||||||
|   type DrawGroup = { Points: Array<DrawPoint>; Paths: Array<DrawLine> }; |   type DrawGroup = { Points: Array<DrawPoint>; Paths: Array<DrawLine> }; | ||||||
|   type DrawTest = { UserL: DrawGroup, UserR: DrawGroup, TestL: DrawGroup, TestR: DrawGroup }; |   type DrawChart = { Cross?:DrawPoint, UserL: DrawGroup, UserR: DrawGroup, TestL: DrawGroup, TestR: DrawGroup }; | ||||||
| 
 | 
 | ||||||
|   type Binding = [state:State, dispatch:(inAction:Action)=>void] |   type Binding = [state:State, dispatch:(inAction:Action)=>void] | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user