Files
黄森斌 4d213938e9 fix update widget occur error (#16139)
* fix update widget occur error

* update expression
2023-08-31 16:22:24 +08:00

1265 lines
43 KiB
JavaScript

/* eslint-disable @typescript-eslint/no-unused-expressions */
/* eslint-disable consistent-return */
/* eslint-disable @typescript-eslint/no-unsafe-return */
const { join } = require('path');
module.paths.push(join(Editor.App.path, 'node_modules'));
const Vue = require('vue/dist/vue.min.js');
const propUtils = require('../utils/prop');
const cssMediaWidth = 340;
let layout = 'vertical';
exports.template = `
<style>
.widget-component {
position: relative;
margin-bottom: 4px;
margin-left: 4px;
}
.widget-component[layout='horizontal'] {
margin-left: 8px;
}
.widget-component[layout='vertical']>.layout {
padding-left: 0;
padding-top: 8px;
}
.widget-component[layout='vertical']>.layout .rect {
position: relative;
top: 0;
left: 0;
height: 154px;
width: 150px;
margin: 0 auto;
}
.widget-component[layout='horizontal']>.layout .rect {
position: absolute;
top: calc(50% - 65px);
left: -5px;
}
.widget-component .m20-t {
margin-top: 20px;
}
.widget-component>.layout {
position: relative;
padding-left: 150px;
padding-top: 8px;
padding-bottom: 8px;
}
.widget-component>.layout .ui-prop {
display: inline-block;
}
.widget-component>.layout ui-num-input {
max-width: 80px;
user-select: none;
}
.widget-component>.layout ui-checkbox {
user-select: none;
}
.widget-component>.layout .rect>.top {
position: absolute;
top: 0;
left: 0;
width: 140px;
height: 20px;
text-align: center;
}
.widget-component>.layout .rect>.right {
position: absolute;
top: 140px;
left: 120px;
width: 140px;
text-align: center;
height: 20px;
transform: rotate(-90deg);
transform-origin: 0 0;
}
.widget-component>.layout .rect>.bottom {
position: absolute;
top: 125px;
left: 0;
width: 140px;
height: 20px;
text-align: center;
}
.widget-component>.layout .rect>.left {
position: absolute;
top: 140px;
left: -2px;
width: 140px;
text-align: center;
height: 20px;
transform: rotate(-90deg);
transform-origin: 0 0;
}
.widget-component>.layout .rect .widget-rect {
position: absolute;
top: 21px;
left: 20px;
width: 100px;
height: 100px;
background-color: var(--color-normal-fill-weaker);
border: 1px solid var(--color-normal-fill-important);
box-shadow: var(--color-normal-fill-emphasis) 0 0 4px;
box-sizing: border-box;
}
.widget-component>.layout .rect .widget-rect>.center {
position: absolute;
top: 25%;
left: 25%;
width: 50%;
height: 50%;
z-index: 2;
background-color: var(--color-normal-fill);
border: 1px solid var(--color-normal-fill-important);
border-radius: 2px;
box-sizing: border-box;
}
.widget-component>.layout .rect .widget-rect>.center[bottom] {
top: auto;
bottom: 12.5%;
}
.widget-component>.layout .rect .widget-rect>.center[bottom][top] {
height: auto;
}
.widget-component>.layout .rect .widget-rect>.center[bottom]>ui-icon[bottom] {
display: block;
}
.widget-component>.layout .rect .widget-rect>.center[top] {
top: 12.5%;
}
.widget-component>.layout .rect .widget-rect>.center[top]>ui-icon[top] {
display: block;
}
.widget-component>.layout .rect .widget-rect>.center[right] {
left: auto;
right: 12.5%;
}
.widget-component>.layout .rect .widget-rect>.center[right][left] {
width: auto;
}
.widget-component>.layout .rect .widget-rect>.center[right]>ui-icon[right] {
display: block;
}
.widget-component>.layout .rect .widget-rect>.center[left] {
left: 12.5%;
}
.widget-component>.layout .rect .widget-rect>.center[left]>ui-icon[left] {
display: block;
}
.widget-component>.layout .rect .widget-rect>.center>ui-icon {
display: none;
}
.widget-component>.layout .rect .widget-rect>.center>ui-icon[top] {
position: absolute;
top: -15px;
left: calc(50% - 7px);
font-size: 11px;
line-height: 10px;
}
.widget-component>.layout .rect .widget-rect>.center>ui-icon[right] {
transform: rotate(90deg);
position: absolute;
right: -15px;
top: calc(50% - 7px);
font-size: 11px;
line-height: 11px;
}
.widget-component>.layout .rect .widget-rect>.center>ui-icon[bottom] {
position: absolute;
bottom: -15px;
left: calc(50% - 7px);
font-size: 11px;
line-height: 10px;
}
.widget-component>.layout .rect .widget-rect>.center>ui-icon[left] {
transform: rotate(90deg);
position: absolute;
left: -15px;
top: calc(50% - 7px);
font-size: 11px;
line-height: 11px;
}
.widget-component>.layout .rect .widget-rect>.top {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 12.5%;
border-bottom: 1px dashed var(--color-normal-contrast);
}
.widget-component>.layout .rect .widget-rect>.bottom {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 12.5%;
border-top: 1px dashed var(--color-normal-contrast);
}
.widget-component>.layout .rect .widget-rect>.left {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 12.5%;
border-right: 1px dashed var(--color-normal-contrast);
}
.widget-component>.layout .rect .widget-rect>.right {
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 12.5%;
border-left: 1px dashed var(--color-normal-contrast);
}
.widget-component>.layout .rect .widget-rect>.horizontal {
position: absolute;
top: 50%;
left: 0;
right: 0;
z-index: 11;
height: 1px;
border-top: 1px dashed var(--color-normal-contrast);
font-size: 0;
}
.widget-component>.layout .rect .widget-rect>.vertical {
position: absolute;
top: 0;
left: 50%;
bottom: 0;
z-index: 11;
width: 1px;
border-left: 1px dashed var(--color-normal-contrast);
font-size: 0;
}
.widget-component>.layout>.right>.line {
--ui-prop-margin-left: 0;
display: flex;
justify-content: space-between;
}
.widget-component>.layout>.right>.line>.name {
width: 60%;
}
.widget-component>.layout>.right>.inputs>.ui-prop {
visibility: hidden;
pointer-events: none;
}
.widget-component>.layout>.right>.inputs>.ui-prop[active] {
visibility: visible;
pointer-events: auto;
}
.widget-component .button-group {
border: 1px solid var(--color-default-border-important);
border-radius: 2px;
overflow: hidden;
display: flex;
flex: 1;
justify-content: space-between;
}
.widget-component .button-group .button {
flex: 1;
padding: 0 5px;
text-align: center;
font-size: 11px;
border-right: 1px solid var(--color-default-border-important);
cursor: pointer;
}
.widget-component .button-group .button:last-child {
border-right: none;
}
.widget-component .button-group .button[active],
.widget-component .button-group .button:hover {
color: var(--color-normal-contrast-weakest);
background-color: var(--color-normal-fill-emphasis);
}
.widget-component .button-group .button[active] .icon .long,
.widget-component .button-group .button[active] .icon .short,
.widget-component .button-group .button:hover .icon .long,
.widget-component .button-group .button:hover .icon .short {
background-color: var(--color-normal-contrast-weakest);
}
.widget-component .button-group .button .icon {
width: 18px;
height: 18px;
margin: 1px auto 0 auto;
font-size: 0;
position: relative;
}
.widget-component .button-group .button .icon .line {
position: absolute;
z-index: 3;
}
.widget-component .button-group .button .icon .line.second {
display: none;
}
.widget-component .button-group .button .icon .long {
position: absolute;
width: 12px;
height: 4px;
background-color: var(--color-normal-contrast-weakest);
}
.widget-component .button-group .button .icon .short {
position: absolute;
width: 7px;
height: 4px;
background-color: var(--color-normal-contrast-weakest);
}
.widget-component .button-group .button .left.bottom {
transform: rotate(-90deg);
}
.widget-component .button-group .button .left .line {
left: 0;
top: 0;
height: 100%;
border-left: 1px dashed var(--color-focus-border);
}
.widget-component .button-group .button .left .long {
left: 2px;
top: 4px;
}
.widget-component .button-group .button .left .short {
left: 2px;
top: 11px;
}
.widget-component .button-group .button .center.middle {
transform: rotate(-90deg);
}
.widget-component .button-group .button .center .line {
left: 9px;
top: 0;
height: 100%;
border-left: 1px dashed var(--color-focus-border);
}
.widget-component .button-group .button .center .long {
left: 4px;
top: 4px;
}
.widget-component .button-group .button .center .short {
left: 6px;
top: 11px;
}
.widget-component .button-group .button .right.top {
transform: rotate(-90deg);
}
.widget-component .button-group .button .right .line {
right: 0;
top: 0;
height: 100%;
border-left: 1px dashed var(--color-focus-border);
}
.widget-component .button-group .button .right .long {
right: 2px;
top: 4px;
}
.widget-component .button-group .button .right .short {
right: 2px;
top: 11px;
}
.widget-component .button-group .button .horizontal.vertical {
transform: rotate(-90deg);
}
.widget-component .button-group .button .horizontal .line {
left: 0;
top: 0;
height: 100%;
border-left: 1px dashed var(--color-focus-border);
}
.widget-component .button-group .button .horizontal .line.second {
display: block;
left: unset;
right: 0;
top: 0;
}
.widget-component .button-group .button .horizontal .long {
left: 2px;
right: 2px;
top: 4px;
width: auto;
}
.widget-component .button-group .button .horizontal .short {
left: 2px;
right: 2px;
top: 11px;
width: auto;
}
.widget-component .direction>.name {
display: inline-block;
}
.widget-component .direction>.icon {
float: right;
font-size: 10px;
margin-right: 2px;
}
.widget-component .direction>.icon>ui-icon:hover {
color: var(--color-warn-fill);
}
.widget-component .direction>.icon>.lock {
color: var(--color-warn-fill);
}
</style>
<div id="app"></div>
`;
const excludeList = ['uuid', 'name', 'enabled', '_name', '_objFlags', '__scriptAsset', 'node', '_enabled', '__prefab', 'target', 'isAlignTop', 'isAlignBottom', 'isAlignLeft', 'isAlignRight', 'isAlignVerticalCenter', 'isAlignHorizontalCenter', 'isStretchWidth', 'isStretchHeight', 'top', 'editorTop', 'bottom', 'editorBottom', 'left', 'editorLeft', 'right', 'editorRight', 'horizontalCenter', 'editorHorizontalCenter', 'verticalCenter', 'editorVerticalCenter', 'isAbsoluteTop', 'isAbsoluteBottom', 'isAbsoluteLeft', 'isAbsoluteRight', 'isAbsoluteHorizontalCenter', 'isAbsoluteVerticalCenter', 'alignMode', 'alignFlags', '_alignFlags', '_target', '_left', '_right', '_top', '_bottom', '_horizontalCenter', '_verticalCenter', '_isAbsLeft', '_isAbsRight', '_isAbsTop', '_isAbsBottom', '_isAbsHorizontalCenter', '_isAbsVerticalCenter', '_originalWidth', '_originalHeight', '_alignMode', '_lockFlags'];
// Used to determine if the value is locked
const LockFlags = {
top: 1 << 0,
middle: 1 << 1,
bottom: 1 << 2,
left: 1 << 3,
center: 1 << 4,
right: 1 << 5,
};
exports.$ = {
app: '#app',
};
exports.methods = {
getObjectByKey(target, key) {
let params = [];
if (typeof key === 'string') {
params = key.split('.');
} else if (key instanceof Array) {
params = key;
}
if (params.length > 0) {
const value = params.shift();
return this.getObjectByKey(target[value], params);
} else {
return target;
}
},
getDimensionHorizontal() {
const {
isAlignLeft, isAlignRight, isAlignHorizontalCenter,
} = this.dump.value;
let dimension = '';
if (isAlignLeft.value) {
dimension = 'left';
}
if (isAlignRight.value) {
dimension = 'right';
}
if (isAlignLeft.value && isAlignRight.value) {
dimension = 'stretch';
}
if (isAlignHorizontalCenter.value) {
dimension = 'center';
}
return dimension;
},
getDimensionVertical() {
const {
isAlignTop, isAlignBottom, isAlignVerticalCenter,
} = this.dump.value;
let dimension = '';
if (isAlignTop.value) {
dimension = 'top';
}
if (isAlignBottom.value) {
dimension = 'bottom';
}
if (isAlignTop.value && isAlignBottom.value) {
dimension = 'stretch';
}
if (isAlignVerticalCenter.value) {
dimension = 'middle';
}
return dimension;
},
isInvalid(key) {
if (Array.isArray(this.dump.value[key].values)) {
return this.dump.value[key].values.some((value) => value !== this.dump.value[key].value);
}
return false;
},
update() {
for (const key in uiElements) {
const element = uiElements[key];
if (typeof element.update === 'function') {
element.update.call(this);
}
}
},
change(key, newValue) {
this.dump.value[key].value = newValue;
this.$refs.summitProp.dump = this.dump.value[key];
if ('values' in this.dump.value[key]) {
this.dump.value[key].values.forEach((_, index) => {
this.dump.value[key].values[index] = newValue;
});
}
this.$refs.summitProp.dispatch('change-dump');
},
snapshot() {
// next tick snapshot
setTimeout(() => {
this.$refs.summitProp.dispatch('confirm-dump');
});
},
getUnit(type) {
const data = this.dump.value;
switch (type) {
case 'editorTop':
return data.isAbsoluteTop.value ? 'px' : '%';
case 'editorBottom':
return data.isAbsoluteBottom.value ? 'px' : '%';
case 'editorLeft':
return data.isAbsoluteLeft.value ? 'px' : '%';
case 'editorRight':
return data.isAbsoluteRight.value ? 'px' : '%';
case 'editorHorizontalCenter':
return data.isAbsoluteHorizontalCenter.value ? 'px' : '%';
case 'editorVerticalCenter':
return data.isAbsoluteVerticalCenter.value ? 'px' : '%';
default:
break;
}
},
changeUnit(type) {
function update(dump, force) {
if (force !== true && dump === this.dump) {
return;
}
const value = dump.value;
switch (type) {
case 'editorTop':
value.isAbsoluteTop.value = !value.isAbsoluteTop.value;
if ('values' in value.isAbsoluteTop) {
value.isAbsoluteTop.values.forEach((val, index) => {
value.isAbsoluteTop.values[index] = value.isAbsoluteTop.value;
});
}
return { path: 'isAbsoluteTop', dump: value.isAbsoluteTop };
case 'editorBottom':
value.isAbsoluteBottom.value = !value.isAbsoluteBottom.value;
if ('values' in value.isAbsoluteBottom) {
value.isAbsoluteBottom.values.forEach((val, index) => {
value.isAbsoluteBottom.values[index] = value.isAbsoluteBottom.value;
});
}
return { path: 'isAbsoluteBottom', dump: value.isAbsoluteBottom };
case 'editorLeft':
value.isAbsoluteLeft.value = !value.isAbsoluteLeft.value;
if ('values' in value.isAbsoluteLeft) {
value.isAbsoluteLeft.values.forEach((val, index) => {
value.isAbsoluteLeft.values[index] = value.isAbsoluteLeft.value;
});
}
return { path: 'isAbsoluteLeft', dump: value.isAbsoluteLeft };
case 'editorRight':
value.isAbsoluteRight.value = !value.isAbsoluteRight.value;
if ('values' in value.isAbsoluteRight) {
value.isAbsoluteRight.values.forEach((val, index) => {
value.isAbsoluteRight.values[index] = value.isAbsoluteRight.value;
});
}
return { path: 'isAbsoluteRight', dump: value.isAbsoluteRight };
case 'editorHorizontalCenter':
value.isAbsoluteHorizontalCenter.value = !value.isAbsoluteHorizontalCenter.value;
if ('values' in value.isAbsoluteHorizontalCenter) {
value.isAbsoluteHorizontalCenter.values.forEach((val, index) => {
value.isAbsoluteHorizontalCenter.values[index] = value.isAbsoluteHorizontalCenter.value;
});
}
return { path: 'isAbsoluteHorizontalCenter', dump: value.isAbsoluteHorizontalCenter };
case 'editorVerticalCenter':
value.isAbsoluteVerticalCenter.value = !value.isAbsoluteVerticalCenter.value;
if ('values' in value.isAbsoluteVerticalCenter) {
value.isAbsoluteVerticalCenter.values.forEach((val, index) => {
value.isAbsoluteVerticalCenter.values[index] = value.isAbsoluteVerticalCenter.value;
});
}
return { path: 'isAbsoluteVerticalCenter', dump: value.isAbsoluteVerticalCenter };
default:
break;
}
}
const { dump } = update(this.dump, true);
this.$refs.summitProp.dump = dump;
this.$refs.summitProp.dispatch('change-dump');
this.snapshot();
},
select(event) {
// Handling through delegated events
const button = event.path.find((element) => element && element.classList && element.classList.contains('button'));
if (!button) {
return;
}
const dimension = button.getAttribute('dimension');
let horizontal;
let vertical;
switch (dimension) {
case 'horizontal':
horizontal = {
isAlignLeft: {
value: false,
},
isAlignRight: {
value: false,
},
isAlignHorizontalCenter: {
value: false,
},
};
break;
case 'left':
horizontal = {
isAlignLeft: {
value: true,
},
isAlignRight: {
value: false,
},
isAlignHorizontalCenter: {
value: false,
},
};
break;
case 'center':
horizontal = {
isAlignLeft: {
value: false,
},
isAlignRight: {
value: false,
},
isAlignHorizontalCenter: {
value: true,
},
};
break;
case 'right':
horizontal = {
isAlignLeft: {
value: false,
},
isAlignRight: {
value: true,
},
isAlignHorizontalCenter: {
value: false,
},
};
break;
case 'h-stretch':
horizontal = {
isAlignLeft: {
value: true,
},
isAlignRight: {
value: true,
},
isAlignHorizontalCenter: {
value: false,
},
};
break;
case 'vertical':
vertical = {
isAlignTop: {
value: false,
},
isAlignVerticalCenter: {
value: false,
},
isAlignBottom: {
value: false,
},
};
break;
case 'top':
vertical = {
isAlignTop: {
value: true,
},
isAlignVerticalCenter: {
value: false,
},
isAlignBottom: {
value: false,
},
};
break;
case 'middle':
vertical = {
isAlignTop: {
value: false,
},
isAlignVerticalCenter: {
value: true,
},
isAlignBottom: {
value: false,
},
};
break;
case 'bottom':
vertical = {
isAlignTop: {
value: false,
},
isAlignVerticalCenter: {
value: false,
},
isAlignBottom: {
value: true,
},
};
break;
case 'v-stretch':
vertical = {
isAlignTop: {
value: true,
},
isAlignVerticalCenter: {
value: false,
},
isAlignBottom: {
value: true,
},
};
break;
default:
break;
}
const dump = this.dump;
if (horizontal) {
if (dump.value.isAlignLeft.value !== horizontal.isAlignLeft.value || !this.isHorizontalAlignValid) {
dump.value.isAlignLeft.value = horizontal.isAlignLeft.value;
this.$refs.summitProp.dump = dump.value.isAlignLeft;
if ('values' in dump.value.isAlignLeft) {
dump.value.isAlignLeft.values.forEach((val, index) => {
dump.value.isAlignLeft.values[index] = dump.value.isAlignLeft.value;
});
}
this.$refs.summitProp.dispatch('change-dump');
}
if (dump.value.isAlignRight.value !== horizontal.isAlignRight.value || !this.isHorizontalAlignValid) {
dump.value.isAlignRight.value = horizontal.isAlignRight.value;
this.$refs.summitProp.dump = dump.value.isAlignRight;
if ('values' in dump.value.isAlignRight) {
dump.value.isAlignRight.values.forEach((val, index) => {
dump.value.isAlignRight.values[index] = dump.value.isAlignRight.value;
});
}
this.$refs.summitProp.dispatch('change-dump');
}
if (dump.value.isAlignHorizontalCenter.value !== horizontal.isAlignHorizontalCenter.value || !this.isHorizontalAlignValid) {
dump.value.isAlignHorizontalCenter.value = horizontal.isAlignHorizontalCenter.value;
this.$refs.summitProp.dump = dump.value.isAlignHorizontalCenter;
if ('values' in dump.value.isAlignHorizontalCenter) {
dump.value.isAlignHorizontalCenter.values.forEach((val, index) => {
dump.value.isAlignHorizontalCenter.values[index] = dump.value.isAlignHorizontalCenter.value;
});
}
this.$refs.summitProp.dispatch('change-dump');
}
this.dimensionHorizontal = this.getDimensionHorizontal();
}
if (vertical) {
if (dump.value.isAlignTop.value !== vertical.isAlignTop.value || !this.isVerticalAlignValid) {
dump.value.isAlignTop.value = vertical.isAlignTop.value;
this.$refs.summitProp.dump = dump.value.isAlignTop;
if ('values' in dump.value.isAlignTop) {
dump.value.isAlignTop.values.forEach((val, index) => {
dump.value.isAlignTop.values[index] = dump.value.isAlignTop.value;
});
}
this.$refs.summitProp.dispatch('change-dump');
}
if (dump.value.isAlignVerticalCenter.value !== vertical.isAlignVerticalCenter.value || !this.isVerticalAlignValid) {
dump.value.isAlignVerticalCenter.value = vertical.isAlignVerticalCenter.value;
this.$refs.summitProp.dump = dump.value.isAlignVerticalCenter;
if ('values' in dump.value.isAlignVerticalCenter) {
dump.value.isAlignVerticalCenter.values.forEach((val, index) => {
dump.value.isAlignVerticalCenter.values[index] = dump.value.isAlignVerticalCenter.value;
});
}
this.$refs.summitProp.dispatch('change-dump');
}
if (dump.value.isAlignBottom.value !== vertical.isAlignBottom.value || !this.isVerticalAlignValid) {
dump.value.isAlignBottom.value = vertical.isAlignBottom.value;
this.$refs.summitProp.dump = dump.value.isAlignBottom;
if ('values' in dump.value.isAlignBottom) {
dump.value.isAlignBottom.values.forEach((val, index) => {
dump.value.isAlignBottom.values[index] = dump.value.isAlignBottom.value;
});
}
this.$refs.summitProp.dispatch('change-dump');
}
this.dimensionVertical = this.getDimensionVertical();
}
this.snapshot();
},
toggleLock(direction) {
const isLock = this.isLock(direction);
let directions = [direction];
let lockValue = this.dump.value._lockFlags.value;
const isStretchWidth = this.dump.value.isStretchWidth.value;
const isStretchHeight = this.dump.value.isStretchHeight.value;
const stretchWidth = ['left', 'right'];
if (isStretchWidth && stretchWidth.includes(direction)) {
directions = stretchWidth;
}
const stretchHeight = ['top', 'bottom'];
if (isStretchHeight && stretchHeight.includes(direction)) {
directions = stretchHeight;
}
directions.forEach((dir) => {
const lockDirection = LockFlags[dir];
if (isLock) {
lockValue &= ~lockDirection;
} else {
lockValue |= lockDirection;
}
});
// Submit data
this.dump.value._lockFlags.value = lockValue;
this.$refs.summitProp.dump = this.dump.value._lockFlags;
if ('values' in this.dump.value._lockFlags) {
this.dump.value._lockFlags.values.forEach((val, index) => {
this.dump.value._lockFlags.values[index] = lockValue;
});
}
this.$refs.summitProp.dispatch('change-dump');
this.snapshot();
},
isLock(direction) {
const lockValue = this.dump.value._lockFlags.value;
const lockDirection = LockFlags[direction];
return lockValue & lockDirection;
},
setLayout() {
const rect = this.$this.getBoundingClientRect();
this.layout ??= layout;
if (rect.width) {
if (rect.width > cssMediaWidth) {
layout = this.layout = 'horizontal';
} else {
layout = this.layout = 'vertical';
}
}
},
};
const uiElements = {
baseProps: {
ready() {
this.$baseProps = this.$el && this.$el.querySelectorAll('ui-prop:not(.customProp)');
},
update() {
if (!this.$baseProps) {
uiElements.baseProps.ready.call(this);
}
this.$baseProps.forEach((element) => {
const key = element.getAttribute('dump-key');
const dump = this.getObjectByKey(this.dump.value, key);
const isEmpty = element.getAttribute('empty');
if (!isEmpty) {
const isShow = dump.visible;
if (isShow) {
element.render(dump);
}
element.style = isShow ? '' : 'display: none;';
}
});
},
},
customProps: {
update() {
if (!this.$customProps) {
this.$customProps = this.$el.querySelector('#customProps');
}
propUtils.updateCustomPropElements(this.$customProps, excludeList, this.dump, (element, prop) => {
element.className = 'customProp';
if (prop.dump.visible) {
element.render(prop.dump);
}
element.hidden = !prop.dump.visible;
});
},
},
};
const template = /* html*/`
<div class="widget-component" :layout="layout">
<!--TODO: don't hack-->
<ui-prop ref="summitProp" style="display:none"></ui-prop>
<div class="layout">
<div class="rect">
<div class="top" v-show="dimensionVertical==='top' || dimensionVertical==='stretch'">top</div>
<div class="right" v-show="dimensionHorizontal==='right' || dimensionHorizontal==='stretch'">right</div>
<div class="bottom" v-show="dimensionVertical==='bottom' || dimensionVertical==='stretch'">bottom</div>
<div class="left" v-show="dimensionHorizontal==='left' || dimensionHorizontal==='stretch'">left</div>
<div class="widget-rect">
<div class="center" :top="dump.value.isAlignTop.value" :bottom="dump.value.isAlignBottom.value"
:left="dump.value.isAlignLeft.value" :right="dump.value.isAlignRight.value">
<ui-icon value="arrowsv" top></ui-icon>
<ui-icon value="arrowsv" right></ui-icon>
<ui-icon value="arrowsv" bottom></ui-icon>
<ui-icon value="arrowsv" left></ui-icon>
</div>
<div class="top" v-if="dump.value.isAlignTop.value">
</div>
<div class="bottom" v-if="dump.value.isAlignBottom.value">
</div>
<div class="left" v-if="dump.value.isAlignLeft.value">
</div>
<div class="right" v-if="dump.value.isAlignRight.value">
</div>
<div class="vertical" v-if="dump.value.isAlignHorizontalCenter.value"></div>
<div class="horizontal" v-if="dump.value.isAlignVerticalCenter.value"></div>
</div>
</div>
<div class="right">
<div class="line">
<ui-label>Horizontal Alignment</ui-label>
</div>
<div class="line">
<div class="button-group" @click="select($event)">
<div class="button" dimension="horizontal" :active="isHorizontalAlignValid && dimensionHorizontal === ''">NONE</div>
<div class="button" dimension="left" :active="isHorizontalAlignValid && dimensionHorizontal === 'left'">
<widget-icon class="left" title="Left"></widget-icon>
</div>
<div class="button" dimension="center" :active="isHorizontalAlignValid && dimensionHorizontal === 'center'">
<widget-icon class="center" title="Center"></widget-icon>
</div>
<div class="button" dimension="right" :active="isHorizontalAlignValid && dimensionHorizontal === 'right'">
<widget-icon class="right" title="Right"></widget-icon>
</div>
<div class="button" dimension="h-stretch" :active="isHorizontalAlignValid && dimensionHorizontal === 'stretch'">
<widget-icon class="horizontal" title="Horizontal Stretch"></widget-icon>
</div>
</div>
</div>
<div class="line inputs" v-if="dimensionHorizontal && isHorizontalAlignValid">
<ui-prop empty="true" type="dump" dump-key="editorLeft" :active="isHorizontalAlignValid && dump.value.isAlignLeft.value">
<div class="direction" v-show="dump.value.isAlignLeft.value">
<span class="name">Left</span>
<div class="icon" title="Lock left value" @click="toggleLock('left')">
<ui-icon class="lock" value="lock" v-if="isLock('left')"></ui-icon>
<ui-icon value="unlock" v-else></ui-icon>
</div>
</div>
<ui-num-input tabindex="0" :unit="getUnit('editorLeft')" :invalid="isInvalid('editorLeft')"
:disabled="!dump.value.isAlignLeft.value" :value="dump.value.editorLeft.value"
@change="change('editorLeft', $event.target.value)"
@confirm="snapshot()"
@unit-click="changeUnit('editorLeft')"
v-show="dump.value.isAlignLeft.value">
</ui-num-input>
</ui-prop>
<ui-prop empty="true" type="dump" dump-key="editorHorizontalCenter"
:active="isHorizontalAlignValid && dump.value.isAlignHorizontalCenter.value">
<div class="direction" v-show="dump.value.isAlignHorizontalCenter.value">
<span class="name">Center</span>
<div class="icon" title="Lock center value" @click="toggleLock('center')">
<ui-icon class="lock" value="lock" v-if="isLock('center')"></ui-icon>
<ui-icon value="unlock" v-else></ui-icon>
</div>
</div>
<ui-num-input tabindex="0" :unit="getUnit('editorHorizontalCenter')"
v-show="dump.value.isAlignHorizontalCenter.value" :invalid="isInvalid('editorHorizontalCenter')"
:disabled="!dump.value.isAlignHorizontalCenter.value"
:value="dump.value.editorHorizontalCenter.value"
@change="change('editorHorizontalCenter', $event.target.value)"
@confirm="snapshot()"
@unit-click="changeUnit('editorHorizontalCenter')"></ui-num-input>
</ui-prop>
<ui-prop empty="true" type="dump" dump-key="editorRight" :active="isHorizontalAlignValid && dump.value.isAlignRight.value">
<div class="direction" v-show="dump.value.isAlignRight.value">
<span class="name">Right</span>
<div class="icon" title="Lock right value" @click="toggleLock('right')">
<ui-icon class="lock" value="lock" v-if="isLock('right')"></ui-icon>
<ui-icon value="unlock" v-else></ui-icon>
</div>
</div>
<ui-num-input tabindex="0" :unit="getUnit('editorRight')" :invalid="isInvalid('editorRight')"
:disabled="!dump.value.isAlignRight.value" :value="dump.value.editorRight.value"
v-show="dump.value.isAlignRight.value"
@change="change('editorRight', $event.target.value)"
@confirm="snapshot()"
@unit-click="changeUnit('editorRight')">
</ui-num-input>
</ui-prop>
</div>
<div class="line m20-t">
<ui-label>Vertical Alignment</ui-label>
</div>
<div class="line">
<div class="button-group" @click="select($event)">
<div class="button" dimension="vertical" :active="isVerticalAlignValid && dimensionVertical === ''">NONE</div>
<div class="button" dimension="top" :active="isVerticalAlignValid && dimensionVertical === 'top'">
<widget-icon class="top right" title="Top"></widget-icon>
</div>
<div class="button" dimension="middle" :active="isVerticalAlignValid && dimensionVertical === 'middle'">
<widget-icon class="middle center" title="Middle"></widget-icon>
</div>
<div class="button" dimension="bottom" :active="isVerticalAlignValid && dimensionVertical === 'bottom'">
<widget-icon class="bottom left" title="Bottom"></widget-icon>
</div>
<div class="button" dimension="v-stretch" :active="isVerticalAlignValid && dimensionVertical === 'stretch'">
<widget-icon class="vertical horizontal" title="Vertical Stretch"></widget-icon>
</div>
</div>
</div>
<div class="line inputs" v-if="dimensionVertical && isVerticalAlignValid">
<ui-prop empty="true" type="dump" dump-key="editorTop" :active="isVerticalAlignValid && dump.value.isAlignTop.value">
<div class="direction" v-show="dump.value.isAlignTop.value">
<span class="name">Top</span>
<div class="icon" title="Lock top value" @click="toggleLock('top')">
<ui-icon class="lock" value="lock" v-if="isLock('top')"></ui-icon>
<ui-icon value="unlock" v-else></ui-icon>
</div>
</div>
<ui-num-input tabindex="0" :unit="getUnit('editorTop')" :invalid="isInvalid('editorTop')"
:disabled="!dump.value.isAlignTop.value"
@change="change('editorTop', $event.target.value)"
@confirm="snapshot()"
:value="dump.value.editorTop.value" @unit-click="changeUnit('editorTop')"
v-show="dump.value.isAlignTop.value">
</ui-num-input>
</ui-prop>
<ui-prop empty="true" type="dump" dump-key="editorVerticalCenter"
:active="isVerticalAlignValid && dump.value.isAlignVerticalCenter.value">
<div class="direction" v-show="dump.value.isAlignVerticalCenter.value">
<span class="name">Middle</span>
<div class="icon" title="Lock middle value" @click="toggleLock('middle')">
<ui-icon class="lock" value="lock" v-if="isLock('middle')"></ui-icon>
<ui-icon value="unlock" v-else></ui-icon>
</div>
</div>
<ui-num-input tabindex="0" :unit="getUnit('editorVerticalCenter')"
:invalid="isInvalid('editorVerticalCenter')" :disabled="!dump.value.isAlignVerticalCenter.value"
@change="change('editorVerticalCenter', $event.target.value)"
@confirm="snapshot()"
:value="dump.value.editorVerticalCenter.value" @unit-click="changeUnit('editorVerticalCenter')"
v-show="dump.value.isAlignVerticalCenter.value"></ui-num-input>
</ui-prop>
<ui-prop empty="true" type="dump" dump-key="editorBottom" :active="isVerticalAlignValid && dump.value.isAlignBottom.value">
<div class="direction" v-show="dump.value.isAlignBottom.value">
<span class="name">Bottom</span>
<div class="icon" title="Lock bottom value" @click="toggleLock('bottom')">
<ui-icon class="lock" value="lock" v-if="isLock('bottom')"></ui-icon>
<ui-icon value="unlock" v-else></ui-icon>
</div>
</div>
<ui-num-input tabindex="0" :unit="getUnit('editorBottom')" :invalid="isInvalid('editorBottom')"
:disabled="!dump.value.isAlignBottom.value" :value="dump.value.editorBottom.value"
@change="change('editorBottom', $event.target.value)"
@confirm="snapshot()"
@unit-click="changeUnit('editorBottom')"
v-show="dump.value.isAlignBottom.value">
</ui-num-input>
</ui-prop>
</div>
</div>
</div>
<ui-prop type="dump" dump-key="target"></ui-prop>
<ui-prop type="dump" dump-key="alignMode"></ui-prop>
<!-- Render other data that is not taken over -->
<div id="customProps"></div>
</div>
`;
const components = {
'widget-icon': {
template: `
<div class="icon">
<span class="line"></span>
<span class="long"></span>
<span class="short"></span>
<span class="line second"></span>
</div>
`,
},
};
const computed = {
isHorizontalAlignValid() {
return !(this.isInvalid('isAlignLeft') || this.isInvalid('isAlignRight') || this.isInvalid('isAlignHorizontalCenter'));
},
isVerticalAlignValid() {
return !(this.isInvalid('isAlignTop') || this.isInvalid('isAlignBottom') || this.isInvalid('isAlignVerticalCenter'));
},
};
exports.ready = function() {
this.resizeObserver = new window.ResizeObserver((entries) => {
window.requestAnimationFrame(() => {
// avoid error: ResizeObserver loop limit exceeded
if (!Array.isArray(entries) || !entries.length) {
return;
}
this.setLayout();
});
});
this.resizeObserver.observe(this.$this);
for (const key in uiElements) {
const element = uiElements[key];
if (typeof element.ready === 'function') {
element.ready.call(this);
}
}
};
exports.update = function(dump) {
this.dump = dump;
this.dimensionHorizontal = this.getDimensionHorizontal();
this.dimensionVertical = this.getDimensionVertical();
this.setLayout();
if (!this.vm) {
this.vm = new Vue({
el: this.$.app,
data: this,
template,
components,
computed,
methods: exports.methods,
});
}
this.vm.update();
};
exports.close = function() {
this.resizeObserver.unobserve(this.$this);
};