Simple monitor for displaying MIDI status for digital pianos.
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

150 lines
4.6 KiB

  1. import * as React from 'react'
  2. import { DropdownInput } from '../DropdownInput'
  3. import { Config } from '../../../../common/config'
  4. export interface SettingsFormProps extends React.HTMLProps<HTMLElementTagNameMap['form']> {
  5. defaultValues?: Config
  6. ranges: Record<string, string>
  7. scaleFactors: Record<string, string>
  8. midiAccess?: MIDIAccess
  9. lastStateChangeTimestamp?: number
  10. naturalKeyWidths: number[]
  11. }
  12. export const SettingsForm: React.FC<SettingsFormProps> = ({
  13. disabled,
  14. midiAccess,
  15. ranges,
  16. defaultValues = {},
  17. scaleFactors,
  18. lastStateChangeTimestamp,
  19. naturalKeyWidths,
  20. ...etcProps
  21. }) => {
  22. const inputs = typeof midiAccess !== 'undefined' ? Array.from(midiAccess.inputs) : undefined
  23. return (
  24. <form {...etcProps}>
  25. <fieldset disabled={disabled} className="contents">
  26. <legend className="sr-only">Settings</legend>
  27. <div className="flex flex-col gap-4">
  28. <div>
  29. <DropdownInput
  30. label="Input device"
  31. name="queryDeviceKey"
  32. defaultValue={defaultValues?.['queryDeviceKey']}
  33. key={lastStateChangeTimestamp}
  34. >
  35. {inputs?.map(([name, device]) => (
  36. <option key={name} value={name}>
  37. {device.name}
  38. </option>
  39. ))}
  40. </DropdownInput>
  41. </div>
  42. <div className="flex-auto">
  43. <DropdownInput
  44. name="range"
  45. label="Keyboard range"
  46. defaultValue={defaultValues?.['range']}
  47. >
  48. {Object.entries(ranges).map(([name, range]) => (
  49. <option key={name} value={range}>
  50. {name}
  51. </option>
  52. ))}
  53. </DropdownInput>
  54. </div>
  55. <div className="flex justify-between items-center gap-8 h-10">
  56. <div>Scale factor</div>
  57. <div className="flex items-center gap-8">
  58. {Object.entries(scaleFactors).map(([label, value]) => (
  59. <div key={value}>
  60. <label>
  61. <input
  62. name="scaleFactor"
  63. type="radio"
  64. value={value}
  65. defaultChecked={
  66. defaultValues?.['scaleFactor']?.toString() === value.toString()
  67. }
  68. />{' '}
  69. {label}
  70. </label>
  71. </div>
  72. ))}
  73. </div>
  74. </div>
  75. <div className="flex-auto">
  76. <DropdownInput
  77. name="naturalKeyWidth"
  78. label="Natural key width"
  79. defaultValue={defaultValues?.['naturalKeyWidth']}
  80. >
  81. {naturalKeyWidths.map((n) => (
  82. <option key={n} value={n}>
  83. {n}
  84. </option>
  85. ))}
  86. </DropdownInput>
  87. </div>
  88. <div className="flex justify-between items-center gap-8">
  89. <div>Natural key color</div>
  90. <div>
  91. <input
  92. name="naturalKeyColor"
  93. type="color"
  94. className="h-10"
  95. defaultValue={defaultValues?.['naturalKeyColor']}
  96. />
  97. </div>
  98. </div>
  99. <div className="flex justify-between items-center gap-8">
  100. <div>Accidental key color</div>
  101. <div>
  102. <input
  103. name="accidentalKeyColor"
  104. type="color"
  105. className="h-10"
  106. defaultValue={defaultValues?.['accidentalKeyColor']}
  107. />
  108. </div>
  109. </div>
  110. <div className="mt-12 flex gap-4">
  111. <div className="w-0 flex-auto">
  112. <button
  113. className="w-full h-10 rounded border overflow-hidden"
  114. type="submit"
  115. name="action"
  116. value="cancelSaveConfig"
  117. >
  118. Cancel
  119. </button>
  120. </div>
  121. <div className="w-0 flex-auto">
  122. <button
  123. className="w-full h-10 rounded border overflow-hidden"
  124. type="submit"
  125. name="action"
  126. value="resetConfig"
  127. >
  128. Reset to Defaults
  129. </button>
  130. </div>
  131. </div>
  132. <div>
  133. <button
  134. className="w-full h-10 rounded border bg-white text-black overflow-hidden"
  135. type="submit"
  136. name="action"
  137. value="saveConfig"
  138. >
  139. Save
  140. </button>
  141. </div>
  142. </div>
  143. </fieldset>
  144. </form>
  145. )
  146. }