Musical keyboard component written in React.
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

478 строки
14 KiB

  1. import * as React from 'react'
  2. import * as PropTypes from 'prop-types'
  3. import {
  4. BOTTOM_CSS_ATTRIBUTES,
  5. LEFT_CSS_ATTRIBUTES,
  6. WIDTH_CSS_ATTRIBUTES,
  7. ORIENTATIONS,
  8. } from '../../services/constants'
  9. const LIGHT_COLOR = 'white'
  10. const propTypes = {
  11. label: PropTypes.string,
  12. orientation: PropTypes.oneOf(ORIENTATIONS),
  13. }
  14. type Props = PropTypes.InferProps<typeof propTypes>
  15. const StyledAccidentalKey: React.FC<Props> = ({ label = '', orientation = 0 }) => (
  16. <div
  17. style={{
  18. width: '100%',
  19. height: '100%',
  20. position: 'relative',
  21. }}
  22. >
  23. <div
  24. style={{
  25. position: 'absolute',
  26. top: 0,
  27. left: 0,
  28. width: '100%',
  29. height: '100%',
  30. }}
  31. >
  32. <div
  33. style={{
  34. width: '100%',
  35. height: '100%',
  36. position: 'relative',
  37. }}
  38. >
  39. <div
  40. style={{
  41. width: '100%',
  42. height: '100%',
  43. position: 'absolute',
  44. top: 0,
  45. left: 0,
  46. borderRadius: 'calc(1px * var(--size-scale-factor, 1))',
  47. boxShadow: '0 0 0 calc(1px * var(--size-scale-factor, 1)) rgba(0, 0, 0, 0.25)',
  48. }}
  49. />
  50. <div
  51. style={{
  52. width: '100%',
  53. height: '100%',
  54. backgroundColor: 'black',
  55. position: 'absolute',
  56. top: 0,
  57. left: 0,
  58. borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
  59. }}
  60. />
  61. <div
  62. style={{
  63. width: '100%',
  64. height: 'calc(6 / 50 * 100%)',
  65. padding: '0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
  66. boxSizing: 'border-box',
  67. position: 'absolute',
  68. bottom: 0,
  69. left: 0,
  70. }}
  71. >
  72. <div
  73. style={{
  74. width: '100%',
  75. height: '100%',
  76. borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
  77. backgroundColor: `var(--color-accidental-key, #35313b)`,
  78. maskImage: 'linear-gradient(to bottom, white, rgba(0, 0, 0, 0.9))',
  79. WebkitMaskImage: 'linear-gradient(to bottom, white, rgba(0, 0, 0, 0.9))',
  80. }}
  81. />
  82. </div>
  83. <div
  84. style={{
  85. width: '100%',
  86. height: 'calc(44 / 50 * 100%)',
  87. padding: 'calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) 0',
  88. boxSizing: 'border-box',
  89. position: 'absolute',
  90. top: 0,
  91. left: 0,
  92. }}
  93. >
  94. <div
  95. style={{
  96. width: '100%',
  97. height: '100%',
  98. backgroundColor: `var(--color-accidental-key, #35313b)`,
  99. }}
  100. />
  101. </div>
  102. <div
  103. style={{
  104. width: '100%',
  105. height: 'calc(4px * var(--size-scale-factor, 1))',
  106. padding: 'calc(1px * var(--size-scale-factor, 1)) 0 0 0',
  107. boxSizing: 'border-box',
  108. position: 'absolute',
  109. top: 0,
  110. left: 0,
  111. }}
  112. >
  113. <div
  114. style={{
  115. width: '100%',
  116. height: '100%',
  117. backgroundColor: 'black',
  118. opacity: '0.12',
  119. }}
  120. />
  121. </div>
  122. <div
  123. style={{
  124. width: 'calc(2px * var(--size-scale-factor, 1))',
  125. height: 'calc(10 / 52 * 100%)',
  126. padding: '0 calc(1px * var(--size-scale-factor, 1)) 0 0',
  127. boxSizing: 'border-box',
  128. position: 'absolute',
  129. top: 0,
  130. right: 0,
  131. }}
  132. >
  133. <div
  134. style={{
  135. width: '100%',
  136. height: '100%',
  137. backgroundColor: LIGHT_COLOR,
  138. maskImage: 'linear-gradient(to bottom, transparent, white)',
  139. WebkitMaskImage: 'linear-gradient(to bottom, transparent, white)',
  140. opacity: '0.4',
  141. }}
  142. />
  143. </div>
  144. <div
  145. style={{
  146. width: 'calc(2px * var(--size-scale-factor, 1))',
  147. height: 'calc(34 / 52 * 100%)',
  148. boxSizing: 'border-box',
  149. position: 'absolute',
  150. bottom: 'calc(8 / 52 * 100%)',
  151. right: 0,
  152. paddingRight: 'calc(1px * var(--size-scale-factor, 1))',
  153. paddingLeft: 0,
  154. }}
  155. >
  156. <div
  157. style={{
  158. width: '100%',
  159. height: '100%',
  160. backgroundColor: LIGHT_COLOR,
  161. opacity: '0.4',
  162. borderBottomRightRadius: 'calc(1px * var(--size-scale-factor, 1))',
  163. }}
  164. />
  165. </div>
  166. <div
  167. style={{
  168. width: '100%',
  169. height: 'calc(6 / 52 * 100%)',
  170. padding:
  171. '0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
  172. boxSizing: 'border-box',
  173. position: 'absolute',
  174. bottom: 0,
  175. left: 0,
  176. }}
  177. >
  178. <div
  179. style={{
  180. width: '100%',
  181. height: '100%',
  182. backgroundColor: LIGHT_COLOR,
  183. borderRadius:
  184. 'calc(4px * var(--size-scale-factor, 1)) calc(4px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
  185. opacity: '0.12',
  186. }}
  187. />
  188. </div>
  189. <div
  190. style={{
  191. width: '100%',
  192. height: 'calc(38 / 52 * 100%)',
  193. padding: '0 calc(3px * var(--size-scale-factor, 1)) 0 calc(3px * var(--size-scale-factor, 1))',
  194. boxSizing: 'border-box',
  195. position: 'absolute',
  196. top: 'calc(3px * var(--size-scale-factor, 1))',
  197. left: 0,
  198. }}
  199. >
  200. <div
  201. style={{
  202. width: '100%',
  203. height: '100%',
  204. backgroundColor: LIGHT_COLOR,
  205. maskImage: 'linear-gradient(to bottom, transparent, white)',
  206. WebkitMaskImage: 'linear-gradient(to bottom, transparent, white)',
  207. borderRadius: 99999,
  208. opacity: 0.12,
  209. }}
  210. />
  211. </div>
  212. <div
  213. style={{
  214. width: '100%',
  215. paddingTop: 0,
  216. paddingRight: 'calc(1px * var(--size-scale-factor, 1))',
  217. paddingLeft: 'calc(2px * var(--size-scale-factor, 1))',
  218. boxSizing: 'border-box',
  219. position: 'absolute',
  220. bottom: 'calc(8 / 52 * 100%)',
  221. left: 0,
  222. height: 'calc(1px * var(--size-scale-factor, 1))',
  223. }}
  224. >
  225. <div
  226. style={{
  227. width: '100%',
  228. height: '100%',
  229. backgroundColor: LIGHT_COLOR,
  230. borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
  231. opacity: '0.4',
  232. }}
  233. />
  234. </div>
  235. </div>
  236. </div>
  237. <div
  238. style={{
  239. position: 'absolute',
  240. top: 0,
  241. left: 0,
  242. width: '100%',
  243. height: '100%',
  244. opacity: 'var(--opacity-highlight)',
  245. }}
  246. >
  247. <div
  248. style={{
  249. width: '100%',
  250. height: '100%',
  251. position: 'relative',
  252. }}
  253. >
  254. <div
  255. style={{
  256. width: '100%',
  257. height: '100%',
  258. position: 'absolute',
  259. top: 0,
  260. left: 0,
  261. borderRadius: 'calc(1px * var(--size-scale-factor, 1))',
  262. boxShadow: '0 0 0 calc(1px * var(--size-scale-factor, 1)) rgba(0, 0, 0, 0.25)',
  263. }}
  264. />
  265. <div
  266. style={{
  267. width: '100%',
  268. height: '100%',
  269. backgroundColor: 'black',
  270. position: 'absolute',
  271. top: 0,
  272. left: 0,
  273. borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
  274. }}
  275. />
  276. <div
  277. style={{
  278. width: '100%',
  279. height: 'calc(6 / 50 * 100%)',
  280. padding: '0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
  281. boxSizing: 'border-box',
  282. position: 'absolute',
  283. bottom: 0,
  284. left: 0,
  285. }}
  286. >
  287. <div
  288. style={{
  289. width: '100%',
  290. height: '100%',
  291. borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
  292. backgroundColor: 'var(--color-active-key, Highlight)',
  293. maskImage: 'linear-gradient(to bottom, white, rgba(0, 0, 0, 0.9))',
  294. WebkitMaskImage: 'linear-gradient(to bottom, white, rgba(0, 0, 0, 0.9))',
  295. opacity: 0.75,
  296. }}
  297. />
  298. </div>
  299. <div
  300. style={{
  301. width: '100%',
  302. height: 'calc(44 / 50 * 100%)',
  303. padding: 'calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) 0',
  304. boxSizing: 'border-box',
  305. position: 'absolute',
  306. top: 0,
  307. left: 0,
  308. }}
  309. >
  310. <div
  311. style={{
  312. width: '100%',
  313. height: '100%',
  314. backgroundColor: 'var(--color-active-key, Highlight)',
  315. opacity: 0.75,
  316. }}
  317. />
  318. </div>
  319. <div
  320. style={{
  321. width: '100%',
  322. height: 'calc(4px * var(--size-scale-factor, 1))',
  323. padding: 'calc(1px * var(--size-scale-factor, 1)) 0 0 0',
  324. boxSizing: 'border-box',
  325. position: 'absolute',
  326. top: 0,
  327. left: 0,
  328. }}
  329. >
  330. <div
  331. style={{
  332. width: '100%',
  333. height: '100%',
  334. backgroundColor: 'black',
  335. opacity: '0.12',
  336. }}
  337. />
  338. </div>
  339. <div
  340. style={{
  341. width: 'calc(2px * var(--size-scale-factor, 1))',
  342. height: 'calc(10 / 52 * 100%)',
  343. padding: '0 calc(1px * var(--size-scale-factor, 1)) 0 0',
  344. boxSizing: 'border-box',
  345. position: 'absolute',
  346. top: 0,
  347. right: 0,
  348. opacity: 0.5,
  349. }}
  350. >
  351. <div
  352. style={{
  353. width: '100%',
  354. height: '100%',
  355. backgroundColor: LIGHT_COLOR,
  356. maskImage: 'linear-gradient(to bottom, transparent, white)',
  357. WebkitMaskImage: 'linear-gradient(to bottom, transparent, white)',
  358. opacity: '0.4',
  359. }}
  360. />
  361. </div>
  362. <div
  363. style={{
  364. width: 'calc(2px * var(--size-scale-factor, 1))',
  365. height: 'calc(38 / 52 * 100%)',
  366. boxSizing: 'border-box',
  367. position: 'absolute',
  368. bottom: 'calc(4 / 52 * 100%)',
  369. right: 0,
  370. paddingRight: 'calc(1px * var(--size-scale-factor, 1))',
  371. paddingLeft: 0,
  372. opacity: 0.5,
  373. }}
  374. >
  375. <div
  376. style={{
  377. width: '100%',
  378. height: '100%',
  379. backgroundColor: LIGHT_COLOR,
  380. opacity: '0.4',
  381. borderBottomRightRadius: 'calc(1px * var(--size-scale-factor, 1))',
  382. }}
  383. />
  384. </div>
  385. <div
  386. style={{
  387. width: '100%',
  388. height: 'calc(2 / 52 * 100%)',
  389. padding:
  390. '0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
  391. boxSizing: 'border-box',
  392. position: 'absolute',
  393. bottom: 0,
  394. left: 0,
  395. }}
  396. >
  397. <div
  398. style={{
  399. width: '100%',
  400. height: '100%',
  401. backgroundColor: LIGHT_COLOR,
  402. borderRadius:
  403. 'calc(4px * var(--size-scale-factor, 1)) calc(4px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
  404. opacity: '0.12',
  405. }}
  406. />
  407. </div>
  408. <div
  409. style={{
  410. width: '100%',
  411. height: 'calc(42 / 52 * 100%)',
  412. padding: '0 calc(3px * var(--size-scale-factor, 1)) 0 calc(3px * var(--size-scale-factor, 1))',
  413. boxSizing: 'border-box',
  414. position: 'absolute',
  415. top: 'calc(3px * var(--size-scale-factor, 1))',
  416. left: 0,
  417. }}
  418. >
  419. <div
  420. style={{
  421. width: '100%',
  422. height: '100%',
  423. backgroundColor: LIGHT_COLOR,
  424. maskImage: 'linear-gradient(to bottom, transparent, white)',
  425. WebkitMaskImage: 'linear-gradient(to bottom, transparent, white)',
  426. borderRadius: 99999,
  427. opacity: 0.06,
  428. }}
  429. />
  430. </div>
  431. <div
  432. style={{
  433. width: '100%',
  434. paddingTop: 0,
  435. paddingRight: 'calc(1px * var(--size-scale-factor, 1))',
  436. paddingLeft: 'calc(2px * var(--size-scale-factor, 1))',
  437. boxSizing: 'border-box',
  438. position: 'absolute',
  439. bottom: 'calc(4 / 52 * 100%)',
  440. left: 0,
  441. height: 'calc(1px * var(--size-scale-factor, 1))',
  442. opacity: 0.5,
  443. }}
  444. >
  445. <div
  446. style={{
  447. width: '100%',
  448. height: '100%',
  449. backgroundColor: LIGHT_COLOR,
  450. borderRadius: '0 0 calc(1px * var(--size-scale-factor, 1)) calc(1px * var(--size-scale-factor, 1))',
  451. opacity: '0.4',
  452. }}
  453. />
  454. </div>
  455. </div>
  456. </div>
  457. <div
  458. style={{
  459. position: 'absolute',
  460. display: 'grid',
  461. placeContent: 'center',
  462. filter: 'invert(100)',
  463. [BOTTOM_CSS_ATTRIBUTES[orientation || 0]]: 0,
  464. [LEFT_CSS_ATTRIBUTES[orientation || 0]]: 0,
  465. [WIDTH_CSS_ATTRIBUTES[orientation || 0]]: '100%',
  466. }}
  467. >
  468. {label}
  469. </div>
  470. </div>
  471. )
  472. export default StyledAccidentalKey