UNPKG

wx-mini-weview

Version:

weixin UI

430 lines (361 loc) 12.5 kB
const { WvInheritable } = require('../../behaviors/WvInheritable'); Component({ options: { styleIsolation: 'apply-shared', addGlobalClass: true, multipleSlots: false }, behaviors: [ WvInheritable({ properties: {}, childrenProperties: { selectorItems: { // Add index property like in tag component index: { type: Number, value: -1 }, // 选择项的值 value: { type: null, value: null }, // 是否禁用 disabled: { type: Boolean, value: false }, // 选中时应用的主题 theme: { type: String, value: 'wv-theme-primary wv-content-light' }, // 是否选中 selected: { type: Boolean, value: false }, // 选中状态的表现形式: 'scale', 'border', 'none' selectionType: { type: String, value: 'none' }, // 是否显示选中状态的勾选标记 checkmark: { type: Boolean, value: true }, // 勾选标记的位置 checkmarkPosition: { type: String, value: 'top-right' }, // 勾选标记的尺寸 checkmarkSize: { type: String, value: '60rpx' }, // 选中时的缩放大小 scaleSize: { type: String, value: '1.06' } } } }) ], relations: { '../selector-item/selector-item': { type: 'child', linked(target) { // Use WvInheritable method to register child node this.linkChildNode('selectorItems', target); // Assign indices this._assignItemIndices(); // Update item states this._updateValue(this.data.value); }, linkChanged() { this._updateValue(this.data.value); }, unlinked(target) { // Use WvInheritable method to unregister child node this.unlinkChildNode('selectorItems', target); // Reassign indices this._assignItemIndices(); // Update item states this._updateValue(this.data.value); } } }, properties: { // External class extClass: { type: String, value: '' }, // Selection mode: 'single' or 'multiple' mode: { type: String, value: 'single' }, // Selected value(s) value: { type: null, value: null, observer(newVal) { this._updateValue(newVal); } }, // Maximum number of selections (for multiple mode) max: { type: Number, value: 0 // 0 means no limit }, // Disable the selector disabled: { type: Boolean, value: false } }, data: { indexToValueMap: {}, // Maps indices to values valueToIndexMap: {} // Maps values to indices }, lifetimes: { attached() { // Component initialization }, ready() { // Initialize with default value this._updateValue(this.data.value); } }, methods: { /** * Assign indices to all selector items * @private */ _assignItemIndices() { const items = this.getChildrenNodes('selectorItems'); if (!items || !items.length) return; const indexToValueMap = {}; const valueToIndexMap = {}; items.forEach((item, idx) => { item.setInheritedProps({ index: idx }); // Map item value to index const itemValue = item.data.wvInheritableApply.value; indexToValueMap[idx] = itemValue; if (itemValue !== undefined && itemValue !== null) { valueToIndexMap[itemValue] = idx; } }); // Update component data mappings this.setData({ indexToValueMap, valueToIndexMap }); }, /** * Update value and sync items state * @param {Any} newVal - The new value (can be mixed type array like ["A", "B", 2]) */ _updateValue(newVal) { let value; value = Array.isArray(newVal) ? newVal : [newVal]; this.setData({ value }, () => { const items = this.getChildrenNodes('selectorItems'); if (!items || !items.length) return; items.forEach(item => { const itemIndex = item.data.wvInheritableApply.index; const itemValue = item.data.wvInheritableApply.value; let isSelected = false; if(value.includes(itemIndex) || value.includes(itemValue)) { isSelected = true; } item.setInheritedProps({ selected: isSelected }); }); this.triggerEvent('change', { value: this.data.value }); }); }, /** * Toggle selection state * @param {Any} valuesToToggle - Values to toggle (single value or array) */ toggle(valuesToToggle) { if (this.data.disabled) return; const itemsToToggle = Array.isArray(valuesToToggle) ? valuesToToggle : [valuesToToggle]; if (itemsToToggle.length === 0) return; // Special handling for single mode if (this.properties.mode === 'single') { const item = itemsToToggle[0]; const selectorItem = typeof item === 'number' ? this.getItemByIndex(item) : this.getItemByValue(item); if (!selectorItem) return; const itemIndex = selectorItem.data.wvInheritableApply.index; const itemValue = selectorItem.data.wvInheritableApply.value; // Check if already selected const currentValue = this.data.value; const isSelected = currentValue === itemIndex || currentValue === itemValue; // If selected, deselect; otherwise select new item this._updateValue(isSelected ? null : (itemValue !== null ? itemValue : itemIndex)); return; } // Multiple mode let newValues = Array.isArray(this.data.value) ? [...this.data.value] : []; // Process each toggle item itemsToToggle.forEach(item => { const selectorItem = typeof item === 'number' ? this.getItemByIndex(item) : this.getItemByValue(item); if (!selectorItem || selectorItem.data.wvInheritableApply.disabled) return; const itemIndex = selectorItem.data.wvInheritableApply.index; const itemValue = selectorItem.data.wvInheritableApply.value; const isSelected = newValues.includes(itemIndex) || newValues.includes(itemValue); if (isSelected) { newValues = newValues.filter(val => val !== itemIndex && val !== itemValue); } else { if (this.properties.max > 0 && newValues.length >= this.properties.max) { return; } // Prefer value, fallback to index const valueToAdd = itemValue !== null && itemValue !== undefined ? itemValue : itemIndex; newValues.push(valueToAdd); } }); this._updateValue(newValues); }, /** * Select items * @param {Any} value - Values to select (single value or array) */ select(value) { let newVal; newVal = Array.isArray(value) ? value : [value]; if(newVal.length === 0) return; if (this.properties.mode === 'single') { newVal = newVal[0]; } this._updateValue(newVal); }, /** * Unselect items * @param {Any} valuesToUnselect - Values to unselect (single value or array) */ unselect(valuesToUnselect) { const itemsToUnselect = Array.isArray(valuesToUnselect) ? valuesToUnselect : [valuesToUnselect]; if (itemsToUnselect.length === 0) return; // Special handling for single mode if (this.properties.mode === 'single') { const currentValue = this.data.value; if (currentValue === null) return; // Check if current selection is in unselect list for (const item of itemsToUnselect) { const selectorItem = typeof item === 'number' ? this.getItemByIndex(item) : this.getItemByValue(item); if (!selectorItem) continue; const itemIndex = selectorItem.data.wvInheritableApply.index; const itemValue = selectorItem.data.wvInheritableApply.value; if (currentValue === itemIndex || currentValue === itemValue) { this._updateValue(null); return; } } return; } // Multiple mode if (!Array.isArray(this.data.value) || this.data.value.length === 0) return; let newValues = [...this.data.value]; // Remove each unselect item itemsToUnselect.forEach(item => { const selectorItem = typeof item === 'number' ? this.getItemByIndex(item) : this.getItemByValue(item); if (!selectorItem) return; const itemIndex = selectorItem.data.wvInheritableApply.index; const itemValue = selectorItem.data.wvInheritableApply.value; // Remove both index and value from array newValues = newValues.filter(val => val !== itemIndex && val !== itemValue); }); // Only update if changed if (newValues.length !== this.data.value.length) { this._updateValue(newValues); } }, /** * Clear all selections */ clear() { const emptyValue = this.properties.mode === 'single' ? null : []; this._updateValue(emptyValue); }, /** * Select all available items */ selectAll() { if (this.properties.mode === 'single') return; const items = this.getChildrenNodes('selectorItems'); if (!items || !items.length) return; const indices = items .filter(item => !item.data.wvInheritableApply.disabled) .map(item => item.data.wvInheritableApply.index); this._updateValue(indices); }, /** * Get item by index * @param {Number} index - Item index * @return {Object|null} Item component instance */ getItemByIndex(index) { const items = this.getChildrenNodes('selectorItems'); if (!items || !items.length || typeof index !== 'number') return null; return items.find(item => item.data.wvInheritableApply.index === index) || null; }, /** * Get item by value * @param {Any} value - Item value * @return {Object|null} Item component instance */ getItemByValue(value) { const items = this.getChildrenNodes('selectorItems'); if (!items || !items.length) return null; return items.find(item => item.data.wvInheritableApply.value === value) || null; }, /** * Get currently selected items * @return {Array} Selected items array */ getSelectedItems() { const items = this.getChildrenNodes('selectorItems'); if (!items || !items.length) return []; const currentValue = this.data.value; const selectedItems = []; items.forEach(item => { const itemIndex = item.data.wvInheritableApply.index; const itemValue = item.data.wvInheritableApply.value; let isSelected = false; if (Array.isArray(currentValue)) { // Array: match any index or value isSelected = currentValue.some(val => { if (typeof val === 'number') { return val === itemIndex; } else { return val === itemValue; } }); } else if (typeof currentValue === 'number') { // Single number: match index isSelected = (itemIndex === currentValue); } else if (currentValue !== null && currentValue !== undefined) { // Other single value: match value isSelected = (itemValue === currentValue); } if (isSelected) { selectedItems.push(item); } }); return selectedItems; }, /** * Get selected values * @return {Any} Current value */ getValue() { return this.data.value; } } });