| <template> | |
| <div class="option-control"> | |
| <component | |
| :is="uiComponent" | |
| v-bind="uiAttrs" | |
| :value="defaultValue" | |
| @change="onValueChange"> | |
| </component> | |
| </div> | |
| </template> | |
| <script> | |
| import ControlColor from '../controls/ControlColor.vue'; | |
| import ControlBoolean from '../controls/ControlBoolean.vue'; | |
| import ControlNumber from '../controls/ControlNumber.vue'; | |
| import ControlVector from '../controls/ControlVector.vue'; | |
| import ControlEnum from '../controls/ControlEnum.vue'; | |
| import ControlPercent from '../controls/ControlPercent.vue'; | |
| import {store, changeOption} from '../store'; | |
| import ControlPercentVector from '../controls/ControlPercentVector.vue'; | |
| import ControlText from '../controls/ControlText.vue'; | |
| import ControlIcon from '../controls/ControlIcon.vue'; | |
| const uiComponentMap = { | |
| boolean: ControlBoolean, | |
| color: ControlColor, | |
| number: ControlNumber, | |
| vector: ControlVector, | |
| enum: ControlEnum, | |
| // Use number for angle temporary | |
| angle: ControlNumber, | |
| percent: ControlPercent, | |
| percentvector: ControlPercentVector, | |
| text: ControlText, | |
| icon: ControlIcon | |
| }; | |
| const uiComponentDefault = { | |
| boolean: () => false, | |
| color: () => null, | |
| number: () => 0, | |
| angle: () => 0, | |
| percent: () => '50', | |
| enum: (controlConfig) => { | |
| return controlConfig.options.split(',')[0].trim(); | |
| }, | |
| vector: (conntrolConfig) => { | |
| if (!conntrolConfig.dims) { | |
| throw new Error('Must specify dims in vector'); | |
| } | |
| return conntrolConfig.dims.split(',') | |
| .map(dim => 0).join(','); | |
| }, | |
| percentvector: (conntrolConfig) => { | |
| if (!conntrolConfig.dims) { | |
| throw new Error('Must specify dims in vector'); | |
| } | |
| return conntrolConfig.dims.split(',') | |
| .map(dim => '50%').join(','); | |
| } | |
| } | |
| function omitTypeAndDefault(obj) { | |
| const newObj = {}; | |
| for (let key in obj) { | |
| if (obj.hasOwnProperty(key) && key !== 'type' && key !== 'default') { | |
| newObj[key] = obj[key]; | |
| } | |
| } | |
| return newObj; | |
| } | |
| export default { | |
| name: 'OptionControl', | |
| props: ['controlConfig', 'optionPath'], | |
| data() { | |
| return { | |
| shared: store | |
| }; | |
| }, | |
| computed: { | |
| uiComponent() { | |
| return uiComponentMap[this.controlConfig.type]; | |
| }, | |
| uiAttrs() { | |
| return omitTypeAndDefault(this.controlConfig); | |
| }, | |
| defaultValue() { | |
| const controlConfig = this.controlConfig; | |
| return controlConfig.default != null | |
| ? controlConfig.default | |
| : (uiComponentDefault[controlConfig.type] && uiComponentDefault[controlConfig.type](controlConfig)); | |
| } | |
| }, | |
| methods: { | |
| onValueChange(value) { | |
| // If clean before setOption. | |
| this.shared.cleanMode = this.controlConfig.clean; | |
| // console.log(this.optionPath, value); | |
| if (this.shared.currentExampleOption) { | |
| this.shared.currentExampleOption = Object.freeze( | |
| changeOption(this.shared.currentExampleOption, this.optionPath, value) | |
| ); | |
| } | |
| } | |
| } | |
| } | |
| </script> | |
| <style lang="scss"> | |
| .option-control { | |
| margin-top: 10px; | |
| } | |
| </style> |