index.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import baseComponent from '../helpers/baseComponent'
  2. import classNames from '../helpers/libs/classNames'
  3. import styleToCssString from '../helpers/libs/styleToCssString'
  4. import safeAreaBehavior from '../helpers/mixins/safeAreaBehavior'
  5. import { getSafeAreaInset } from '../helpers/hooks/useSafeArea'
  6. /**
  7. * css var prefix
  8. */
  9. const cssVarPattern = /^--/
  10. baseComponent({
  11. behaviors: [safeAreaBehavior],
  12. properties: {
  13. prefixCls: {
  14. type: String,
  15. value: 'wux-safe-area',
  16. },
  17. multiple: {
  18. type: Number,
  19. value: 1,
  20. },
  21. wrapStyle: {
  22. type: [String, Object],
  23. value: '',
  24. },
  25. forceRender: {
  26. type: Boolean,
  27. value: false,
  28. },
  29. supports: {
  30. type: Boolean,
  31. value: false,
  32. },
  33. },
  34. data: {
  35. extStyle: '',
  36. },
  37. computed: {
  38. classes: ['prefixCls, forceRender, supports, safeAreaConfig, isIPhoneX', function(prefixCls, forceRender, supports, safeAreaConfig, isIPhoneX) {
  39. const wrap = classNames(prefixCls, {
  40. [`${prefixCls}--position-bottom`]: (forceRender || isIPhoneX) && safeAreaConfig.bottom,
  41. [`${prefixCls}--position-top`]: (forceRender || isIPhoneX) && !safeAreaConfig.bottom,
  42. [`${prefixCls}--supports`]: (forceRender || isIPhoneX) && supports,
  43. })
  44. return {
  45. wrap,
  46. }
  47. }],
  48. },
  49. observers: {
  50. ['safeAreaConfig, safeAreaStyle, isIPhoneX, multiple, wrapStyle, forceRender, supports'](...args) {
  51. const [
  52. safeAreaConfig,
  53. safeAreaStyle,
  54. isIPhoneX,
  55. multiple,
  56. wrapStyle,
  57. forceRender,
  58. supports,
  59. ] = args
  60. this.updateStyle({
  61. safeAreaConfig,
  62. safeAreaStyle,
  63. isIPhoneX,
  64. multiple,
  65. wrapStyle,
  66. forceRender,
  67. supports,
  68. })
  69. },
  70. },
  71. methods: {
  72. updateStyle(props) {
  73. const {
  74. safeAreaConfig,
  75. safeAreaStyle,
  76. isIPhoneX,
  77. multiple,
  78. wrapStyle,
  79. forceRender,
  80. supports,
  81. } = props
  82. const position = safeAreaConfig.bottom ? 'bottom' : safeAreaConfig.top ? 'top' : 'none'
  83. const normalStyle = {}
  84. const varStyle = {
  85. ['--safe-area-multiple']: multiple,
  86. }
  87. if (
  88. (forceRender || isIPhoneX) &&
  89. !supports &&
  90. ['bottom', 'top'].includes(position)
  91. ) {
  92. const safeAreaInset = getSafeAreaInset(safeAreaStyle)
  93. const property = position === 'bottom' ? 'paddingBottom' : 'paddingTop'
  94. normalStyle[property] = `calc(${safeAreaInset[position]}PX * ${multiple})`
  95. varStyle[`--safe-area-inset-${position}`] = `${safeAreaInset[position]}PX`
  96. varStyle[property] = `calc(var(--safe-area-inset-${position}) * var(--safe-area-multiple))`
  97. }
  98. const extStyle = styleToCssString(
  99. styleToCssString(normalStyle) + styleToCssString(varStyle, { exclude: cssVarPattern }) + styleToCssString(wrapStyle)
  100. )
  101. if (extStyle !== this.data.extStyle) {
  102. this.setData({
  103. extStyle,
  104. })
  105. }
  106. },
  107. },
  108. attached() {
  109. this.updateStyle(this.data)
  110. },
  111. })