index.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import baseComponent from '../helpers/baseComponent'
  2. import classNames from '../helpers/libs/classNames'
  3. import styleToCssString from '../helpers/libs/styleToCssString'
  4. import fieldNamesBehavior from '../helpers/mixins/fieldNamesBehavior'
  5. import eventsMixin from '../helpers/mixins/eventsMixin'
  6. import * as common from '../helpers/wxs/common'
  7. /**
  8. * css var prefix
  9. */
  10. const cssVarPattern = /^--/
  11. function getCheckedValues(newVal, oldVal = []) {
  12. let checkedValues = [...oldVal]
  13. checkedValues = checkedValues.indexOf(newVal) !== -1 ? checkedValues.filter((n) => n !== newVal) : [...checkedValues, newVal]
  14. return checkedValues
  15. }
  16. const getOptions = (options, fieldNames) => common.getOptions(options, fieldNames)
  17. baseComponent({
  18. useField: true,
  19. behaviors: [fieldNamesBehavior, eventsMixin()],
  20. relations: {
  21. '../field/index': {
  22. type: 'ancestor',
  23. },
  24. },
  25. properties: {
  26. prefixCls: {
  27. type: String,
  28. value: 'wux-selector-group',
  29. },
  30. theme: {
  31. type: String,
  32. value: 'balanced',
  33. },
  34. shape: {
  35. type: String,
  36. value: 'default',
  37. },
  38. columns: {
  39. type: Number,
  40. value: 3,
  41. },
  42. gap: {
  43. type: Number,
  44. value: 8,
  45. },
  46. options: {
  47. type: Array,
  48. value: [],
  49. },
  50. defaultValue: {
  51. type: Array,
  52. value: [],
  53. },
  54. value: {
  55. type: Array,
  56. value: [],
  57. observer(newVal) {
  58. if (this.data.controlled) {
  59. this.updated(newVal)
  60. }
  61. },
  62. },
  63. controlled: {
  64. type: Boolean,
  65. value: false,
  66. },
  67. multiple: {
  68. type: Boolean,
  69. value: false,
  70. },
  71. showCheckMark: {
  72. type: Boolean,
  73. value: true,
  74. },
  75. },
  76. data: {
  77. extStyle: '',
  78. inputValue: [],
  79. },
  80. observers: {
  81. ['columns, gap'](columns, gap) {
  82. this.updateStyle(columns, gap)
  83. },
  84. },
  85. computed: {
  86. classes: ['prefixCls, theme, shape', function(prefixCls, theme, shape) {
  87. const finalShape = ['rounded', 'rectangular'].includes(shape) ? shape : ''
  88. const wrap = classNames(prefixCls, {
  89. [`${prefixCls}--${theme}`]: theme,
  90. })
  91. const grid = `${prefixCls}__grid`
  92. const gridItem = classNames(`${prefixCls}__grid-item`, {
  93. [`${prefixCls}__grid-item--${shape}`]: finalShape,
  94. })
  95. const desc = `${prefixCls}__desc`
  96. const checkMark = `${prefixCls}__check-mark`
  97. const checkMarkIcon = `${prefixCls}__check-mark-icon`
  98. const selectable = `${prefixCls}__selectable`
  99. return {
  100. wrap,
  101. grid,
  102. gridItem,
  103. desc,
  104. checkMark,
  105. checkMarkIcon,
  106. selectable,
  107. }
  108. }],
  109. },
  110. methods: {
  111. updated(inputValue) {
  112. if (this.hasFieldDecorator) return
  113. if (this.data.inputValue !== inputValue) {
  114. this.setData({ inputValue })
  115. }
  116. },
  117. updateStyle(columns, gap) {
  118. const extStyle = styleToCssString({
  119. '--selector-group-columns': columns,
  120. '--selector-group-column-gap': `${gap * 2}rpx`,
  121. }, { exclude: cssVarPattern })
  122. if (extStyle !== this.data.extStyle) {
  123. this.setData({
  124. extStyle,
  125. })
  126. }
  127. },
  128. onCheckboxChange(e) {
  129. const { value, checked } = e.detail
  130. const { inputValue, multiple } = this.data
  131. const checkedValues = multiple
  132. ? getCheckedValues(value, inputValue)
  133. : checked ? [value] : []
  134. if (!this.data.controlled) {
  135. this.updated(checkedValues)
  136. }
  137. this.triggerEvent('change', { ...this.getValue(checkedValues) })
  138. },
  139. getValue(value = this.data.inputValue, _cols = this.data.options) {
  140. const fieldNames = this.getFieldNames()
  141. const labelName = fieldNames.label
  142. const valueName = fieldNames.value
  143. const cols = getOptions(_cols, fieldNames)
  144. // Keep sort with value
  145. const checkedValues = value.reduce((acc, val) => (
  146. [
  147. ...acc,
  148. ...cols.filter((option) => option[valueName] === val),
  149. ]
  150. ), [])
  151. const displayValue = checkedValues.map((option) => option[labelName])
  152. const allValues = cols.map((option) => option[valueName])
  153. const selectedIndex = value.map((n) => allValues.indexOf(n))
  154. return {
  155. value,
  156. displayValue,
  157. selectedIndex,
  158. selectedValue: value,
  159. cols,
  160. }
  161. },
  162. },
  163. attached() {
  164. const { defaultValue, value, controlled } = this.data
  165. const inputValue = controlled ? value : defaultValue
  166. this.updated(inputValue)
  167. },
  168. })