mirror of
https://github.com/sabjorn7/meetguru.git
synced 2025-12-17 19:07:33 +03:00
237 lines
7.9 KiB
Vue
237 lines
7.9 KiB
Vue
<template>
|
|
<component
|
|
:is="tag"
|
|
class="ww-layout"
|
|
:data-ww-layout-id="layoutId"
|
|
:class="{
|
|
}"
|
|
:style="layoutStyle"
|
|
>
|
|
<slot name="header"></slot>
|
|
<template v-if="internalList[0]">
|
|
<wwLayoutItemContext
|
|
v-for="index in restrictedLength"
|
|
:key="isBound ? `${internalList[0].uid}_${index - 1}` : `${internalList[index - 1].uid}`"
|
|
:index="offset + index - 1"
|
|
:item="isBound ? internalList[0] : internalList[index - 1]"
|
|
:is-repeat="isBound"
|
|
:data="isBound && boundData ? boundData[offset + index - 1] : null"
|
|
:repeated-items="boundData"
|
|
>
|
|
<slot
|
|
v-bind="{
|
|
item: isBound ? internalList[0] : internalList[index - 1],
|
|
index: offset + index - 1,
|
|
data: isBound && boundData ? boundData[offset + index - 1] : null,
|
|
layoutId,
|
|
itemStyle: getItemStyle(index - 1),
|
|
}"
|
|
>
|
|
<wwElement
|
|
v-bind="isBound ? internalList[0] : internalList[index - 1]"
|
|
:extra-style="getItemStyle(index - 1)"
|
|
></wwElement>
|
|
</slot>
|
|
</wwLayoutItemContext>
|
|
</template>
|
|
</component>
|
|
</template>
|
|
|
|
<script>
|
|
const PUSH_LAST_STYLE_VERTICAL = {
|
|
marginTop: 'auto',
|
|
};
|
|
const PUSH_LAST_STYLE_HORIZONTAL = {
|
|
marginLeft: 'auto',
|
|
};
|
|
import { computed, inject, toRef, reactive, provide, onUnmounted, ref } from 'vue';
|
|
|
|
import { useParentContentProperty } from '@/_common/use/useComponent.js';
|
|
import { getDisplayValue } from '@/_common/helpers/component/component.js';
|
|
import { inheritFrom } from '@/_common/helpers/configuration/configuration.js';
|
|
|
|
import { getLayoutStyleFromContent } from '@/_front/helpers/wwLayoutStyle.js';
|
|
import { useRestoreContext } from '@/_front/use/useRestoreContext.js';
|
|
|
|
import wwLayoutItem from './wwLayoutItem.vue';
|
|
import wwLayoutItemContext from './wwLayoutItemContext.vue';
|
|
|
|
|
|
let layoutId = 1;
|
|
const MAX_REPEAT = 200;
|
|
|
|
export default {
|
|
name: 'wwLayout',
|
|
components: {
|
|
wwLayoutItem,
|
|
wwLayoutItemContext,
|
|
},
|
|
props: {
|
|
path: { type: String, required: false, default: undefined },
|
|
tag: { type: String, default: 'div' },
|
|
direction: { type: String, default: null },
|
|
disableDragDrop: { type: Boolean, default: false },
|
|
disableEdit: { type: Boolean, default: false },
|
|
},
|
|
emits: ['update:list'],
|
|
setup(props, { emit }) {
|
|
const id = layoutId++;
|
|
const parentElementUid = inject('_wwElementUid', null);
|
|
const parentElementComponentId = inject('_wwElementComponentId', null);
|
|
const sectionId = inject('sectionId', null);
|
|
const bindingContext = inject('bindingContext', null);
|
|
|
|
const componentContent = inject('componentContent');
|
|
const componentStyle = inject('componentStyle');
|
|
const componentConfiguration = inject('componentConfiguration');
|
|
const componentWwProps = inject('componentWwProps');
|
|
|
|
const { rawProperty, property } = useParentContentProperty(toRef(props, 'path'));
|
|
|
|
useRestoreContext({ path: toRef(props, 'path') });
|
|
|
|
const isBound = computed(() => rawProperty.value && !!rawProperty.value.__wwtype);
|
|
const boundData = computed(() => {
|
|
if (!isBound.value) return null;
|
|
if (!property.value) return null;
|
|
|
|
if (Array.isArray(property.value)) {
|
|
return property.value;
|
|
}
|
|
if (!property.value.data) {
|
|
return null;
|
|
}
|
|
return Array.isArray(property.value.data) ? property.value.data : null;
|
|
});
|
|
const internalList = computed(() => {
|
|
const { __wwtype, repeatable } = rawProperty.value || {};
|
|
return (__wwtype ? repeatable : property.value) || [];
|
|
});
|
|
|
|
const paginationOptions = computed(() => {
|
|
if (!isBound.value) return null;
|
|
if (!property.value) return null;
|
|
if (Array.isArray(property.value)) {
|
|
return null;
|
|
}
|
|
if (!property.value.limit) return null;
|
|
if (!property.value.total) return null;
|
|
return property.value;
|
|
});
|
|
const offset = computed(() => {
|
|
if (paginationOptions.value) return parseInt(paginationOptions.value.offset) || 0;
|
|
return 0;
|
|
});
|
|
const length = computed(() => {
|
|
if (!isBound.value) {
|
|
return internalList.value.length;
|
|
}
|
|
if (paginationOptions.value) {
|
|
if (!boundData.value) {
|
|
return 0;
|
|
} else {
|
|
const maxIndex = Math.min(
|
|
offset.value + parseInt(wwLib.wwFormula.getValue(paginationOptions.value.limit)),
|
|
paginationOptions.value.total || 0
|
|
);
|
|
const length = Math.max(maxIndex - offset.value, 0);
|
|
return isNaN(length) ? 0 : length;
|
|
}
|
|
}
|
|
return boundData.value ? boundData.value.length : 0;
|
|
});
|
|
|
|
const componentContext = {
|
|
content: componentContent,
|
|
wwProps: componentWwProps,
|
|
};
|
|
|
|
let restrictedLength;
|
|
/* wwFront:start */
|
|
// eslint-disable-next-line vue/no-ref-as-operand
|
|
restrictedLength = length;
|
|
/* wwFront:end */
|
|
|
|
const layoutStyle = computed(() => {
|
|
if (props.direction) {
|
|
return {
|
|
flexDirection: props.direction,
|
|
display: 'flex',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
};
|
|
} else if (inheritFrom(componentConfiguration, 'ww-layout')) {
|
|
return getLayoutStyleFromContent(
|
|
componentContent,
|
|
componentStyle,
|
|
componentConfiguration,
|
|
componentContext
|
|
);
|
|
} else {
|
|
return {};
|
|
}
|
|
});
|
|
|
|
|
|
const __wwContainerType = computed(() =>
|
|
getDisplayValue(componentStyle.display, componentConfiguration, componentContext)
|
|
);
|
|
provide('__wwContainerType', __wwContainerType);
|
|
|
|
return {
|
|
layoutId: id,
|
|
layoutStyle,
|
|
parentElementUid,
|
|
sectionId,
|
|
rawProperty,
|
|
property,
|
|
bindingContext,
|
|
isBound,
|
|
boundData,
|
|
length,
|
|
internalList,
|
|
offset,
|
|
paginationOptions,
|
|
componentContent,
|
|
componentStyle,
|
|
restrictedLength,
|
|
};
|
|
},
|
|
computed: {
|
|
},
|
|
|
|
watch: {
|
|
},
|
|
methods: {
|
|
// TODO: one day extrastyle should be removed, now that we do not have wrapper anymore maybe?
|
|
getItemStyle(index) {
|
|
if (this.componentContent['_ww-layout_pushLast']) {
|
|
const push = !this.componentContent['_ww-layout_reverse']
|
|
? index === this.restrictedLength - 1
|
|
: index === 0;
|
|
if (!push) return;
|
|
// This is very important here to return const here
|
|
// Big performance issue if we recreate object at each call
|
|
return this.componentContent['_ww-layout_flexDirection'] === 'column'
|
|
? PUSH_LAST_STYLE_VERTICAL
|
|
: PUSH_LAST_STYLE_HORIZONTAL;
|
|
}
|
|
return;
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
/* No Scoped css to be easily overwrite */
|
|
.ww-layout {
|
|
display: flex;
|
|
pointer-events: initial;
|
|
position: relative;
|
|
|
|
}
|
|
</style>
|
|
|
|
<style lang="scss" scoped>
|
|
</style>
|