logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe git clone https://hacktivis.me/git/pleroma-fe.git

pleromafe.js (17211B)


  1. import { invertLightness, brightness } from 'chromatism'
  2. import { alphaBlend, mixrgb } from '../color_convert/color_convert.js'
  3. /* This is a definition of all layer combinations
  4. * each key is a topmost layer, each value represents layer underneath
  5. * this is essentially a simplified tree
  6. */
  7. export const LAYERS = {
  8. undelay: null, // root
  9. topBar: null, // no transparency support
  10. badge: null, // no transparency support
  11. profileTint: null, // doesn't matter
  12. fg: null,
  13. bg: 'underlay',
  14. highlight: 'bg',
  15. panel: 'bg',
  16. popover: 'bg',
  17. selectedMenu: 'popover',
  18. btn: 'bg',
  19. btnPanel: 'panel',
  20. btnTopBar: 'topBar',
  21. input: 'bg',
  22. inputPanel: 'panel',
  23. inputTopBar: 'topBar',
  24. alert: 'bg',
  25. alertPanel: 'panel',
  26. poll: 'bg',
  27. chatBg: 'underlay',
  28. chatMessage: 'chatBg'
  29. }
  30. /* By default opacity slots have 1 as default opacity
  31. * this allows redefining it to something else
  32. */
  33. export const DEFAULT_OPACITY = {
  34. profileTint: 0.5,
  35. alert: 0.5,
  36. input: 0.5,
  37. faint: 0.5,
  38. underlay: 0.15,
  39. alertPopup: 0.95
  40. }
  41. /** SUBJECT TO CHANGE IN THE FUTURE, this is all beta
  42. * Color and opacity slots definitions. Each key represents a slot.
  43. *
  44. * Short-hands:
  45. * String beginning with `--` - value after dashes treated as sole
  46. * dependency - i.e. `--value` equivalent to { depends: ['value']}
  47. * String beginning with `#` - value would be treated as solid color
  48. * defined in hexadecimal representation (i.e. #FFFFFF) and will be
  49. * used as default. `#FFFFFF` is equivalent to { default: '#FFFFFF'}
  50. *
  51. * Full definition:
  52. * @property {String[]} depends - color slot names this color depends ones.
  53. * cyclic dependencies are supported to some extent but not recommended.
  54. * @property {String} [opacity] - opacity slot used by this color slot.
  55. * opacity is inherited from parents. To break inheritance graph use null
  56. * @property {Number} [priority] - EXPERIMENTAL. used to pre-sort slots so
  57. * that slots with higher priority come earlier
  58. * @property {Function(mod, ...colors)} [color] - function that will be
  59. * used to determine the color. By default it just copies first color in
  60. * dependency list.
  61. * @argument {Number} mod - `1` (light-on-dark) or `-1` (dark-on-light)
  62. * depending on background color (for textColor)/given color.
  63. * @argument {...Object} deps - each argument after mod represents each
  64. * color from `depends` array. All colors take user customizations into
  65. * account and represented by { r, g, b } objects.
  66. * @returns {Object} resulting color, should be in { r, g, b } form
  67. *
  68. * @property {Boolean|String} [textColor] - true to mark color slot as text
  69. * color. This enables automatic text color generation for the slot. Use
  70. * 'preserve' string if you don't want text color to fall back to
  71. * black/white. Use 'bw' to only ever use black or white. This also makes
  72. * following properties required:
  73. * @property {String} [layer] - which layer the text sit on top on - used
  74. * to account for transparency in text color calculation
  75. * layer is inherited from parents. To break inheritance graph use null
  76. * @property {String} [variant] - which color slot is background (same as
  77. * above, used to account for transparency)
  78. */
  79. export const SLOT_INHERITANCE = {
  80. bg: {
  81. depends: [],
  82. opacity: 'bg',
  83. priority: 1
  84. },
  85. wallpaper: {
  86. depends: ['bg'],
  87. color: (mod, bg) => brightness(-2 * mod, bg).rgb
  88. },
  89. fg: {
  90. depends: [],
  91. priority: 1
  92. },
  93. text: {
  94. depends: [],
  95. layer: 'bg',
  96. opacity: null,
  97. priority: 1
  98. },
  99. underlay: {
  100. default: '#000000',
  101. opacity: 'underlay'
  102. },
  103. link: {
  104. depends: ['accent'],
  105. priority: 1
  106. },
  107. accent: {
  108. depends: ['link'],
  109. priority: 1
  110. },
  111. faint: {
  112. depends: ['text'],
  113. opacity: 'faint'
  114. },
  115. faintLink: {
  116. depends: ['link'],
  117. opacity: 'faint'
  118. },
  119. postFaintLink: {
  120. depends: ['postLink'],
  121. opacity: 'faint'
  122. },
  123. cBlue: '#0000ff',
  124. cRed: '#FF0000',
  125. cGreen: '#00FF00',
  126. cOrange: '#E3FF00',
  127. profileBg: {
  128. depends: ['bg'],
  129. color: (mod, bg) => ({
  130. r: Math.floor(bg.r * 0.53),
  131. g: Math.floor(bg.g * 0.56),
  132. b: Math.floor(bg.b * 0.59)
  133. })
  134. },
  135. profileTint: {
  136. depends: ['bg'],
  137. layer: 'profileTint',
  138. opacity: 'profileTint'
  139. },
  140. highlight: {
  141. depends: ['bg'],
  142. color: (mod, bg) => brightness(5 * mod, bg).rgb
  143. },
  144. highlightLightText: {
  145. depends: ['lightText'],
  146. layer: 'highlight',
  147. textColor: true
  148. },
  149. highlightPostLink: {
  150. depends: ['postLink'],
  151. layer: 'highlight',
  152. textColor: 'preserve'
  153. },
  154. highlightFaintText: {
  155. depends: ['faint'],
  156. layer: 'highlight',
  157. textColor: true
  158. },
  159. highlightFaintLink: {
  160. depends: ['faintLink'],
  161. layer: 'highlight',
  162. textColor: 'preserve'
  163. },
  164. highlightPostFaintLink: {
  165. depends: ['postFaintLink'],
  166. layer: 'highlight',
  167. textColor: 'preserve'
  168. },
  169. highlightText: {
  170. depends: ['text'],
  171. layer: 'highlight',
  172. textColor: true
  173. },
  174. highlightLink: {
  175. depends: ['link'],
  176. layer: 'highlight',
  177. textColor: 'preserve'
  178. },
  179. highlightIcon: {
  180. depends: ['highlight', 'highlightText'],
  181. color: (mod, bg, text) => mixrgb(bg, text)
  182. },
  183. popover: {
  184. depends: ['bg'],
  185. opacity: 'popover'
  186. },
  187. popoverLightText: {
  188. depends: ['lightText'],
  189. layer: 'popover',
  190. textColor: true
  191. },
  192. popoverPostLink: {
  193. depends: ['postLink'],
  194. layer: 'popover',
  195. textColor: 'preserve'
  196. },
  197. popoverFaintText: {
  198. depends: ['faint'],
  199. layer: 'popover',
  200. textColor: true
  201. },
  202. popoverFaintLink: {
  203. depends: ['faintLink'],
  204. layer: 'popover',
  205. textColor: 'preserve'
  206. },
  207. popoverPostFaintLink: {
  208. depends: ['postFaintLink'],
  209. layer: 'popover',
  210. textColor: 'preserve'
  211. },
  212. popoverText: {
  213. depends: ['text'],
  214. layer: 'popover',
  215. textColor: true
  216. },
  217. popoverLink: {
  218. depends: ['link'],
  219. layer: 'popover',
  220. textColor: 'preserve'
  221. },
  222. popoverIcon: {
  223. depends: ['popover', 'popoverText'],
  224. color: (mod, bg, text) => mixrgb(bg, text)
  225. },
  226. selectedPost: '--highlight',
  227. selectedPostFaintText: {
  228. depends: ['highlightFaintText'],
  229. layer: 'highlight',
  230. variant: 'selectedPost',
  231. textColor: true
  232. },
  233. selectedPostLightText: {
  234. depends: ['highlightLightText'],
  235. layer: 'highlight',
  236. variant: 'selectedPost',
  237. textColor: true
  238. },
  239. selectedPostPostLink: {
  240. depends: ['highlightPostLink'],
  241. layer: 'highlight',
  242. variant: 'selectedPost',
  243. textColor: 'preserve'
  244. },
  245. selectedPostFaintLink: {
  246. depends: ['highlightFaintLink'],
  247. layer: 'highlight',
  248. variant: 'selectedPost',
  249. textColor: 'preserve'
  250. },
  251. selectedPostText: {
  252. depends: ['highlightText'],
  253. layer: 'highlight',
  254. variant: 'selectedPost',
  255. textColor: true
  256. },
  257. selectedPostLink: {
  258. depends: ['highlightLink'],
  259. layer: 'highlight',
  260. variant: 'selectedPost',
  261. textColor: 'preserve'
  262. },
  263. selectedPostIcon: {
  264. depends: ['selectedPost', 'selectedPostText'],
  265. color: (mod, bg, text) => mixrgb(bg, text)
  266. },
  267. selectedMenu: {
  268. depends: ['bg'],
  269. color: (mod, bg) => brightness(5 * mod, bg).rgb
  270. },
  271. selectedMenuLightText: {
  272. depends: ['highlightLightText'],
  273. layer: 'selectedMenu',
  274. variant: 'selectedMenu',
  275. textColor: true
  276. },
  277. selectedMenuFaintText: {
  278. depends: ['highlightFaintText'],
  279. layer: 'selectedMenu',
  280. variant: 'selectedMenu',
  281. textColor: true
  282. },
  283. selectedMenuFaintLink: {
  284. depends: ['highlightFaintLink'],
  285. layer: 'selectedMenu',
  286. variant: 'selectedMenu',
  287. textColor: 'preserve'
  288. },
  289. selectedMenuText: {
  290. depends: ['highlightText'],
  291. layer: 'selectedMenu',
  292. variant: 'selectedMenu',
  293. textColor: true
  294. },
  295. selectedMenuLink: {
  296. depends: ['highlightLink'],
  297. layer: 'selectedMenu',
  298. variant: 'selectedMenu',
  299. textColor: 'preserve'
  300. },
  301. selectedMenuIcon: {
  302. depends: ['selectedMenu', 'selectedMenuText'],
  303. color: (mod, bg, text) => mixrgb(bg, text)
  304. },
  305. selectedMenuPopover: {
  306. depends: ['popover'],
  307. color: (mod, bg) => brightness(5 * mod, bg).rgb
  308. },
  309. selectedMenuPopoverLightText: {
  310. depends: ['selectedMenuLightText'],
  311. layer: 'selectedMenuPopover',
  312. variant: 'selectedMenuPopover',
  313. textColor: true
  314. },
  315. selectedMenuPopoverFaintText: {
  316. depends: ['selectedMenuFaintText'],
  317. layer: 'selectedMenuPopover',
  318. variant: 'selectedMenuPopover',
  319. textColor: true
  320. },
  321. selectedMenuPopoverFaintLink: {
  322. depends: ['selectedMenuFaintLink'],
  323. layer: 'selectedMenuPopover',
  324. variant: 'selectedMenuPopover',
  325. textColor: 'preserve'
  326. },
  327. selectedMenuPopoverText: {
  328. depends: ['selectedMenuText'],
  329. layer: 'selectedMenuPopover',
  330. variant: 'selectedMenuPopover',
  331. textColor: true
  332. },
  333. selectedMenuPopoverLink: {
  334. depends: ['selectedMenuLink'],
  335. layer: 'selectedMenuPopover',
  336. variant: 'selectedMenuPopover',
  337. textColor: 'preserve'
  338. },
  339. selectedMenuPopoverIcon: {
  340. depends: ['selectedMenuPopover', 'selectedMenuText'],
  341. color: (mod, bg, text) => mixrgb(bg, text)
  342. },
  343. lightText: {
  344. depends: ['text'],
  345. layer: 'bg',
  346. textColor: 'preserve',
  347. color: (mod, text) => brightness(20 * mod, text).rgb
  348. },
  349. postLink: {
  350. depends: ['link'],
  351. layer: 'bg',
  352. textColor: 'preserve'
  353. },
  354. postGreentext: {
  355. depends: ['cGreen'],
  356. layer: 'bg',
  357. textColor: 'preserve'
  358. },
  359. postCyantext: {
  360. depends: ['cBlue'],
  361. layer: 'bg',
  362. textColor: 'preserve'
  363. },
  364. border: {
  365. depends: ['fg'],
  366. opacity: 'border',
  367. color: (mod, fg) => brightness(2 * mod, fg).rgb
  368. },
  369. poll: {
  370. depends: ['accent', 'bg'],
  371. copacity: 'poll',
  372. color: (mod, accent, bg) => alphaBlend(accent, 0.4, bg)
  373. },
  374. pollText: {
  375. depends: ['text'],
  376. layer: 'poll',
  377. textColor: true
  378. },
  379. icon: {
  380. depends: ['bg', 'text'],
  381. inheritsOpacity: false,
  382. color: (mod, bg, text) => mixrgb(bg, text)
  383. },
  384. // Foreground
  385. fgText: {
  386. depends: ['text'],
  387. layer: 'fg',
  388. textColor: true
  389. },
  390. fgLink: {
  391. depends: ['link'],
  392. layer: 'fg',
  393. textColor: 'preserve'
  394. },
  395. // Panel header
  396. panel: {
  397. depends: ['fg'],
  398. opacity: 'panel'
  399. },
  400. panelText: {
  401. depends: ['text'],
  402. layer: 'panel',
  403. textColor: true
  404. },
  405. panelFaint: {
  406. depends: ['fgText'],
  407. layer: 'panel',
  408. opacity: 'faint',
  409. textColor: true
  410. },
  411. panelLink: {
  412. depends: ['fgLink'],
  413. layer: 'panel',
  414. textColor: 'preserve'
  415. },
  416. // Top bar
  417. topBar: '--fg',
  418. topBarText: {
  419. depends: ['fgText'],
  420. layer: 'topBar',
  421. textColor: true
  422. },
  423. topBarLink: {
  424. depends: ['fgLink'],
  425. layer: 'topBar',
  426. textColor: 'preserve'
  427. },
  428. // Tabs
  429. tab: {
  430. depends: ['btn']
  431. },
  432. tabText: {
  433. depends: ['btnText'],
  434. layer: 'btn',
  435. textColor: true
  436. },
  437. tabActiveText: {
  438. depends: ['text'],
  439. layer: 'bg',
  440. textColor: true
  441. },
  442. // Buttons
  443. btn: {
  444. depends: ['fg'],
  445. variant: 'btn',
  446. opacity: 'btn'
  447. },
  448. btnText: {
  449. depends: ['fgText'],
  450. layer: 'btn',
  451. textColor: true
  452. },
  453. btnPanelText: {
  454. depends: ['btnText'],
  455. layer: 'btnPanel',
  456. variant: 'btn',
  457. textColor: true
  458. },
  459. btnTopBarText: {
  460. depends: ['btnText'],
  461. layer: 'btnTopBar',
  462. variant: 'btn',
  463. textColor: true
  464. },
  465. // Buttons: pressed
  466. btnPressed: {
  467. depends: ['btn'],
  468. layer: 'btn'
  469. },
  470. btnPressedText: {
  471. depends: ['btnText'],
  472. layer: 'btn',
  473. variant: 'btnPressed',
  474. textColor: true
  475. },
  476. btnPressedPanel: {
  477. depends: ['btnPressed'],
  478. layer: 'btn'
  479. },
  480. btnPressedPanelText: {
  481. depends: ['btnPanelText'],
  482. layer: 'btnPanel',
  483. variant: 'btnPressed',
  484. textColor: true
  485. },
  486. btnPressedTopBar: {
  487. depends: ['btnPressed'],
  488. layer: 'btn'
  489. },
  490. btnPressedTopBarText: {
  491. depends: ['btnTopBarText'],
  492. layer: 'btnTopBar',
  493. variant: 'btnPressed',
  494. textColor: true
  495. },
  496. // Buttons: toggled
  497. btnToggled: {
  498. depends: ['btn'],
  499. layer: 'btn',
  500. color: (mod, btn) => brightness(mod * 20, btn).rgb
  501. },
  502. btnToggledText: {
  503. depends: ['btnText'],
  504. layer: 'btn',
  505. variant: 'btnToggled',
  506. textColor: true
  507. },
  508. btnToggledPanelText: {
  509. depends: ['btnPanelText'],
  510. layer: 'btnPanel',
  511. variant: 'btnToggled',
  512. textColor: true
  513. },
  514. btnToggledTopBarText: {
  515. depends: ['btnTopBarText'],
  516. layer: 'btnTopBar',
  517. variant: 'btnToggled',
  518. textColor: true
  519. },
  520. // Buttons: disabled
  521. btnDisabled: {
  522. depends: ['btn', 'bg'],
  523. color: (mod, btn, bg) => alphaBlend(btn, 0.25, bg)
  524. },
  525. btnDisabledText: {
  526. depends: ['btnText', 'btnDisabled'],
  527. layer: 'btn',
  528. variant: 'btnDisabled',
  529. color: (mod, text, btn) => alphaBlend(text, 0.25, btn)
  530. },
  531. btnDisabledPanelText: {
  532. depends: ['btnPanelText', 'btnDisabled'],
  533. layer: 'btnPanel',
  534. variant: 'btnDisabled',
  535. color: (mod, text, btn) => alphaBlend(text, 0.25, btn)
  536. },
  537. btnDisabledTopBarText: {
  538. depends: ['btnTopBarText', 'btnDisabled'],
  539. layer: 'btnTopBar',
  540. variant: 'btnDisabled',
  541. color: (mod, text, btn) => alphaBlend(text, 0.25, btn)
  542. },
  543. // Input fields
  544. input: {
  545. depends: ['fg'],
  546. opacity: 'input'
  547. },
  548. inputText: {
  549. depends: ['text'],
  550. layer: 'input',
  551. textColor: true
  552. },
  553. inputPanelText: {
  554. depends: ['panelText'],
  555. layer: 'inputPanel',
  556. variant: 'input',
  557. textColor: true
  558. },
  559. inputTopbarText: {
  560. depends: ['topBarText'],
  561. layer: 'inputTopBar',
  562. variant: 'input',
  563. textColor: true
  564. },
  565. alertError: {
  566. depends: ['cRed'],
  567. opacity: 'alert'
  568. },
  569. alertErrorText: {
  570. depends: ['text'],
  571. layer: 'alert',
  572. variant: 'alertError',
  573. textColor: true
  574. },
  575. alertErrorPanelText: {
  576. depends: ['panelText'],
  577. layer: 'alertPanel',
  578. variant: 'alertError',
  579. textColor: true
  580. },
  581. alertWarning: {
  582. depends: ['cOrange'],
  583. opacity: 'alert'
  584. },
  585. alertWarningText: {
  586. depends: ['text'],
  587. layer: 'alert',
  588. variant: 'alertWarning',
  589. textColor: true
  590. },
  591. alertWarningPanelText: {
  592. depends: ['panelText'],
  593. layer: 'alertPanel',
  594. variant: 'alertWarning',
  595. textColor: true
  596. },
  597. alertSuccess: {
  598. depends: ['cGreen'],
  599. opacity: 'alert'
  600. },
  601. alertSuccessText: {
  602. depends: ['text'],
  603. layer: 'alert',
  604. variant: 'alertSuccess',
  605. textColor: true
  606. },
  607. alertSuccessPanelText: {
  608. depends: ['panelText'],
  609. layer: 'alertPanel',
  610. variant: 'alertSuccess',
  611. textColor: true
  612. },
  613. alertNeutral: {
  614. depends: ['text'],
  615. opacity: 'alert'
  616. },
  617. alertNeutralText: {
  618. depends: ['text'],
  619. layer: 'alert',
  620. variant: 'alertNeutral',
  621. color: (mod, text) => invertLightness(text).rgb,
  622. textColor: true
  623. },
  624. alertNeutralPanelText: {
  625. depends: ['panelText'],
  626. layer: 'alertPanel',
  627. variant: 'alertNeutral',
  628. textColor: true
  629. },
  630. alertPopupError: {
  631. depends: ['alertError'],
  632. opacity: 'alertPopup'
  633. },
  634. alertPopupErrorText: {
  635. depends: ['alertErrorText'],
  636. layer: 'popover',
  637. variant: 'alertPopupError',
  638. textColor: true
  639. },
  640. alertPopupWarning: {
  641. depends: ['alertWarning'],
  642. opacity: 'alertPopup'
  643. },
  644. alertPopupWarningText: {
  645. depends: ['alertWarningText'],
  646. layer: 'popover',
  647. variant: 'alertPopupWarning',
  648. textColor: true
  649. },
  650. alertPopupSuccess: {
  651. depends: ['alertSuccess'],
  652. opacity: 'alertPopup'
  653. },
  654. alertPopupSuccessText: {
  655. depends: ['alertSuccessText'],
  656. layer: 'popover',
  657. variant: 'alertPopupSuccess',
  658. textColor: true
  659. },
  660. alertPopupNeutral: {
  661. depends: ['alertNeutral'],
  662. opacity: 'alertPopup'
  663. },
  664. alertPopupNeutralText: {
  665. depends: ['alertNeutralText'],
  666. layer: 'popover',
  667. variant: 'alertPopupNeutral',
  668. textColor: true
  669. },
  670. badgeNotification: '--cRed',
  671. badgeNotificationText: {
  672. depends: ['text', 'badgeNotification'],
  673. layer: 'badge',
  674. variant: 'badgeNotification',
  675. textColor: 'bw'
  676. },
  677. badgeNeutral: '--cGreen',
  678. badgeNeutralText: {
  679. depends: ['text', 'badgeNeutral'],
  680. layer: 'badge',
  681. variant: 'badgeNeutral',
  682. textColor: 'bw'
  683. },
  684. chatBg: {
  685. depends: ['bg']
  686. },
  687. chatMessageIncomingBg: {
  688. depends: ['chatBg']
  689. },
  690. chatMessageIncomingText: {
  691. depends: ['text'],
  692. layer: 'chatMessage',
  693. variant: 'chatMessageIncomingBg',
  694. textColor: true
  695. },
  696. chatMessageIncomingLink: {
  697. depends: ['link'],
  698. layer: 'chatMessage',
  699. variant: 'chatMessageIncomingBg',
  700. textColor: 'preserve'
  701. },
  702. chatMessageIncomingBorder: {
  703. depends: ['border'],
  704. opacity: 'border',
  705. color: (mod, border) => brightness(2 * mod, border).rgb
  706. },
  707. chatMessageOutgoingBg: {
  708. depends: ['chatMessageIncomingBg'],
  709. color: (mod, chatMessage) => brightness(5 * mod, chatMessage).rgb
  710. },
  711. chatMessageOutgoingText: {
  712. depends: ['text'],
  713. layer: 'chatMessage',
  714. variant: 'chatMessageOutgoingBg',
  715. textColor: true
  716. },
  717. chatMessageOutgoingLink: {
  718. depends: ['link'],
  719. layer: 'chatMessage',
  720. variant: 'chatMessageOutgoingBg',
  721. textColor: 'preserve'
  722. },
  723. chatMessageOutgoingBorder: {
  724. depends: ['chatMessageOutgoingBg'],
  725. opacity: 'border',
  726. color: (mod, border) => brightness(2 * mod, border).rgb
  727. }
  728. }