triangle.js.flow 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // @flow
  2. import getValueAndUnit from '../helpers/getValueAndUnit'
  3. import PolishedError from '../internalHelpers/_errors'
  4. import type { SideKeyword } from '../types/sideKeyword'
  5. import type { Styles } from '../types/style'
  6. import type { TriangleConfiguration } from '../types/triangleConfiguration'
  7. const getBorderWidth = (
  8. pointingDirection: SideKeyword,
  9. height: [number, string],
  10. width: [number, string],
  11. ): string => {
  12. const fullWidth = `${width[0]}${width[1] || ''}`
  13. const halfWidth = `${width[0] / 2}${width[1] || ''}`
  14. const fullHeight = `${height[0]}${height[1] || ''}`
  15. const halfHeight = `${height[0] / 2}${height[1] || ''}`
  16. switch (pointingDirection) {
  17. case 'top':
  18. return `0 ${halfWidth} ${fullHeight} ${halfWidth}`
  19. case 'topLeft':
  20. return `${fullWidth} ${fullHeight} 0 0`
  21. case 'left':
  22. return `${halfHeight} ${fullWidth} ${halfHeight} 0`
  23. case 'bottomLeft':
  24. return `${fullWidth} 0 0 ${fullHeight}`
  25. case 'bottom':
  26. return `${fullHeight} ${halfWidth} 0 ${halfWidth}`
  27. case 'bottomRight':
  28. return `0 0 ${fullWidth} ${fullHeight}`
  29. case 'right':
  30. return `${halfHeight} 0 ${halfHeight} ${fullWidth}`
  31. case 'topRight':
  32. default:
  33. return `0 ${fullWidth} ${fullHeight} 0`
  34. }
  35. }
  36. const getBorderColor = (pointingDirection: SideKeyword, foregroundColor: string): Object => {
  37. switch (pointingDirection) {
  38. case 'top':
  39. case 'bottomRight':
  40. return { borderBottomColor: foregroundColor }
  41. case 'right':
  42. case 'bottomLeft':
  43. return { borderLeftColor: foregroundColor }
  44. case 'bottom':
  45. case 'topLeft':
  46. return { borderTopColor: foregroundColor }
  47. case 'left':
  48. case 'topRight':
  49. return { borderRightColor: foregroundColor }
  50. default:
  51. throw new PolishedError(59)
  52. }
  53. }
  54. /**
  55. * CSS to represent triangle with any pointing direction with an optional background color.
  56. *
  57. * @example
  58. * // Styles as object usage
  59. *
  60. * const styles = {
  61. * ...triangle({ pointingDirection: 'right', width: '100px', height: '100px', foregroundColor: 'red' })
  62. * }
  63. *
  64. *
  65. * // styled-components usage
  66. * const div = styled.div`
  67. * ${triangle({ pointingDirection: 'right', width: '100px', height: '100px', foregroundColor: 'red' })}
  68. *
  69. *
  70. * // CSS as JS Output
  71. *
  72. * div: {
  73. * 'borderColor': 'transparent transparent transparent red',
  74. * 'borderStyle': 'solid',
  75. * 'borderWidth': '50px 0 50px 100px',
  76. * 'height': '0',
  77. * 'width': '0',
  78. * }
  79. */
  80. export default function triangle({
  81. pointingDirection,
  82. height,
  83. width,
  84. foregroundColor,
  85. backgroundColor = 'transparent',
  86. }: TriangleConfiguration): Styles {
  87. const widthAndUnit = getValueAndUnit(width)
  88. const heightAndUnit = getValueAndUnit(height)
  89. if (isNaN(heightAndUnit[0]) || isNaN(widthAndUnit[0])) {
  90. throw new PolishedError(60)
  91. }
  92. return {
  93. width: '0',
  94. height: '0',
  95. borderColor: backgroundColor,
  96. ...getBorderColor(pointingDirection, foregroundColor),
  97. borderStyle: 'solid',
  98. borderWidth: getBorderWidth(pointingDirection, heightAndUnit, widthAndUnit),
  99. }
  100. }