mirror of
				https://github.com/Tencent/tmagic-editor.git
				synced 2025-11-04 02:28:04 +08:00 
			
		
		
		
	feat(editor,form,schema): 组件样式配置可视化
This commit is contained in:
		
							parent
							
								
									ec94eed787
								
							
						
					
					
						commit
						246e6941d5
					
				@ -1,6 +1,7 @@
 | 
			
		||||
import { describe, expect, test } from 'vitest';
 | 
			
		||||
import path from 'node:path';
 | 
			
		||||
 | 
			
		||||
import { describe, expect, test } from 'vitest';
 | 
			
		||||
 | 
			
		||||
import Core from '../src/Core';
 | 
			
		||||
 | 
			
		||||
describe('Core', () => {
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,12 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <component class="tmagic-design-icon" :is="uiComponent">
 | 
			
		||||
  <component class="tmagic-design-icon" :is="uiComponent" v-bind="uiProps">
 | 
			
		||||
    <slot></slot>
 | 
			
		||||
  </component>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { computed } from 'vue';
 | 
			
		||||
 | 
			
		||||
import { getDesignConfig } from './config';
 | 
			
		||||
import { IconProps } from './types';
 | 
			
		||||
 | 
			
		||||
@ -14,5 +16,6 @@ defineOptions({
 | 
			
		||||
 | 
			
		||||
const ui = getDesignConfig('components')?.icon;
 | 
			
		||||
const uiComponent = ui?.component || 'el-icon';
 | 
			
		||||
defineProps<IconProps>();
 | 
			
		||||
const props = defineProps<IconProps>();
 | 
			
		||||
const uiProps = computed(() => ui?.props(props) || props);
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										69
									
								
								packages/editor/src/fields/StyleSetter/Index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								packages/editor/src/fields/StyleSetter/Index.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,69 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="m-fields-style-setter">
 | 
			
		||||
    <TMagicCollapse :model-value="collapseValue">
 | 
			
		||||
      <template v-for="(item, index) in list" :key="index">
 | 
			
		||||
        <TMagicCollapseItem :name="`${index}`">
 | 
			
		||||
          <template #title><MIcon :icon="Grid"></MIcon>{{ item.title }}</template>
 | 
			
		||||
          <component v-if="item.component" :is="item.component" :values="model[name]" @change="change"></component>
 | 
			
		||||
        </TMagicCollapseItem>
 | 
			
		||||
      </template>
 | 
			
		||||
    </TMagicCollapse>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { shallowRef } from 'vue';
 | 
			
		||||
import { Grid } from '@element-plus/icons-vue';
 | 
			
		||||
 | 
			
		||||
import { TMagicCollapse, TMagicCollapseItem } from '@tmagic/design';
 | 
			
		||||
import type { ContainerChangeEventData, FieldProps } from '@tmagic/form';
 | 
			
		||||
import type { StyleSchema } from '@tmagic/schema';
 | 
			
		||||
 | 
			
		||||
import MIcon from '@editor/components/Icon.vue';
 | 
			
		||||
 | 
			
		||||
import { Background, Border, Font, Layout, Position } from './pro/';
 | 
			
		||||
 | 
			
		||||
defineOptions({
 | 
			
		||||
  name: 'MFieldsStyleSetter',
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
defineProps<FieldProps<StyleSchema>>();
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits<{
 | 
			
		||||
  change: [v: any, eventData: ContainerChangeEventData];
 | 
			
		||||
}>();
 | 
			
		||||
 | 
			
		||||
const list = [
 | 
			
		||||
  {
 | 
			
		||||
    name: 'font',
 | 
			
		||||
    title: '布局',
 | 
			
		||||
    component: Layout,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    title: '文字',
 | 
			
		||||
    component: Font,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    title: '背景',
 | 
			
		||||
    component: Background,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    title: '位置',
 | 
			
		||||
    component: Position,
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    title: '边框与圆角',
 | 
			
		||||
    component: Border,
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const collapseValue = shallowRef(
 | 
			
		||||
  Array(list.length)
 | 
			
		||||
    .fill(1)
 | 
			
		||||
    .map((x, i) => `${i}`),
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
const change = (v: any, eventData: ContainerChangeEventData) => {
 | 
			
		||||
  emit('change', v, eventData);
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@ -0,0 +1,71 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="background-position-container">
 | 
			
		||||
    <div class="presets-value-list">
 | 
			
		||||
      <TMagicButton
 | 
			
		||||
        v-for="(item, index) in list"
 | 
			
		||||
        :key="index"
 | 
			
		||||
        link
 | 
			
		||||
        :class="model[name] === item.value && 'btn-active'"
 | 
			
		||||
        @click="changeHandler(item.value)"
 | 
			
		||||
      >
 | 
			
		||||
        <div :class="['position-icon', item.class, model[name] === item.value && 'active']"></div>
 | 
			
		||||
      </TMagicButton>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="custom-value">
 | 
			
		||||
      <TMagicInput v-model="model[name]" size="small" placeholder="自定义背景位置" clearable @change="changeHandler">
 | 
			
		||||
      </TMagicInput>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { TMagicButton, TMagicInput } from '@tmagic/design';
 | 
			
		||||
import type { FieldProps, FormItem } from '@tmagic/form';
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(['change']);
 | 
			
		||||
defineProps<FieldProps<{ type: 'style-setter' } & FormItem>>();
 | 
			
		||||
 | 
			
		||||
const horizontalList = [
 | 
			
		||||
  {
 | 
			
		||||
    value: 'left',
 | 
			
		||||
    text: '左',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    value: 'center',
 | 
			
		||||
    text: '中',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    value: 'right',
 | 
			
		||||
    text: '右',
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const verticalList = [
 | 
			
		||||
  {
 | 
			
		||||
    value: 'top',
 | 
			
		||||
    text: '上',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    value: 'center',
 | 
			
		||||
    text: '中',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    value: 'bottom',
 | 
			
		||||
    text: '下',
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const list = verticalList
 | 
			
		||||
  .map((vertical) =>
 | 
			
		||||
    horizontalList.map((horizontal) => ({
 | 
			
		||||
      value: `${horizontal.value} ${vertical.value}`,
 | 
			
		||||
      tips: `${horizontal.text}${vertical.text}`,
 | 
			
		||||
      class: `${horizontal.value}-${vertical.value}`,
 | 
			
		||||
    })),
 | 
			
		||||
  )
 | 
			
		||||
  .flat();
 | 
			
		||||
 | 
			
		||||
const changeHandler = (v: string) => {
 | 
			
		||||
  emit('change', v);
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										104
									
								
								packages/editor/src/fields/StyleSetter/components/Border.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								packages/editor/src/fields/StyleSetter/components/Border.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,104 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="border-box-container">
 | 
			
		||||
    <div class="border-icon-container">
 | 
			
		||||
      <div class="border-icon-container-row">
 | 
			
		||||
        <div
 | 
			
		||||
          class="border-icon border-icon-top"
 | 
			
		||||
          :class="{ active: direction === 'Top' }"
 | 
			
		||||
          @click="selectDirection('Top')"
 | 
			
		||||
        ></div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="border-icon-container-row">
 | 
			
		||||
        <div
 | 
			
		||||
          class="border-icon border-icon-left"
 | 
			
		||||
          :class="{ active: direction === 'Left' }"
 | 
			
		||||
          @click="selectDirection('Left')"
 | 
			
		||||
        ></div>
 | 
			
		||||
        <div class="border-icon" :class="{ active: direction === '' }" @click="selectDirection()"></div>
 | 
			
		||||
        <div
 | 
			
		||||
          class="border-icon border-icon-right"
 | 
			
		||||
          :class="{ active: direction === 'Right' }"
 | 
			
		||||
          @click="selectDirection('Right')"
 | 
			
		||||
        ></div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="border-icon-container-row">
 | 
			
		||||
        <div
 | 
			
		||||
          class="border-icon border-icon-bottom"
 | 
			
		||||
          :class="{ active: direction === 'Bottom' }"
 | 
			
		||||
          @click="selectDirection('Bottom')"
 | 
			
		||||
        ></div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="border-value-container">
 | 
			
		||||
      <MContainer :config="config" :model="model" @change="change"></MContainer>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { computed, ref } from 'vue';
 | 
			
		||||
 | 
			
		||||
import type { ContainerChangeEventData, FormValue } from '@tmagic/form';
 | 
			
		||||
import { MContainer } from '@tmagic/form';
 | 
			
		||||
import type { StyleSchema } from '@tmagic/schema';
 | 
			
		||||
 | 
			
		||||
const direction = ref('');
 | 
			
		||||
 | 
			
		||||
const config = computed(() => ({
 | 
			
		||||
  items: [
 | 
			
		||||
    {
 | 
			
		||||
      name: `border${direction.value}Width`,
 | 
			
		||||
      text: '边框宽度',
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      type: 'data-source-field-select',
 | 
			
		||||
      fieldConfig: {
 | 
			
		||||
        type: 'text',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: `border${direction.value}Color`,
 | 
			
		||||
      text: '边框颜色',
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      type: 'data-source-field-select',
 | 
			
		||||
      fieldConfig: {
 | 
			
		||||
        type: 'colorPicker',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: `border${direction.value}Style`,
 | 
			
		||||
      text: '边框样式',
 | 
			
		||||
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      type: 'data-source-field-select',
 | 
			
		||||
      fieldConfig: {
 | 
			
		||||
        type: 'select',
 | 
			
		||||
        options: ['solid', 'dashed', 'dotted'].map((item) => ({
 | 
			
		||||
          value: item,
 | 
			
		||||
          text: item,
 | 
			
		||||
        })),
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const selectDirection = (d?: string) => (direction.value = d || '');
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits<{
 | 
			
		||||
  change: [v: StyleSchema, eventData: ContainerChangeEventData];
 | 
			
		||||
}>();
 | 
			
		||||
 | 
			
		||||
withDefaults(
 | 
			
		||||
  defineProps<{
 | 
			
		||||
    model: FormValue;
 | 
			
		||||
  }>(),
 | 
			
		||||
  {},
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
const change = (value: StyleSchema, eventData: ContainerChangeEventData) => {
 | 
			
		||||
  eventData.changeRecords?.forEach((record) => {
 | 
			
		||||
    emit('change', record.value, {
 | 
			
		||||
      modifyKey: record.propPath,
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										68
									
								
								packages/editor/src/fields/StyleSetter/components/Box.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								packages/editor/src/fields/StyleSetter/components/Box.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,68 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="layout-box-container">
 | 
			
		||||
    <div v-for="(item, index) in list" :key="index" :class="item.class">
 | 
			
		||||
      <span class="help-txt" v-if="item.text">{{ item.text }}</span>
 | 
			
		||||
      <span class="next-input">
 | 
			
		||||
        <input v-model="model[item.name]" @change="change($event, item.name)" placeholder="0" />
 | 
			
		||||
      </span>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import type { ContainerChangeEventData, FormValue } from '@tmagic/form';
 | 
			
		||||
 | 
			
		||||
const list = [
 | 
			
		||||
  {
 | 
			
		||||
    name: 'marginTop',
 | 
			
		||||
    class: 'outer-top-border',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'marginRight',
 | 
			
		||||
    class: 'outer-right-border',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'marginBottom',
 | 
			
		||||
    text: 'MARGIN',
 | 
			
		||||
    class: 'outer-bottom-border',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'marginLeft',
 | 
			
		||||
    class: 'outer-left-border',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'paddingTop',
 | 
			
		||||
    class: 'inner-top-border',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'paddingRight',
 | 
			
		||||
    class: 'inner-right-border',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'paddingBottom',
 | 
			
		||||
    text: 'PADDING',
 | 
			
		||||
    class: 'inner-bottom-border',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'paddingLeft',
 | 
			
		||||
    class: 'inner-left-border',
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits<{
 | 
			
		||||
  change: [v: string, eventData: ContainerChangeEventData];
 | 
			
		||||
}>();
 | 
			
		||||
 | 
			
		||||
withDefaults(
 | 
			
		||||
  defineProps<{
 | 
			
		||||
    model: FormValue;
 | 
			
		||||
  }>(),
 | 
			
		||||
  {},
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
const change = (event: Event, name: string) => {
 | 
			
		||||
  emit('change', (event.target as HTMLInputElement).value, {
 | 
			
		||||
    modifyKey: name,
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@ -0,0 +1,49 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="layout-box-container">
 | 
			
		||||
    <div v-for="(item, index) in list" :key="index" :class="item.class">
 | 
			
		||||
      <span class="next-input">
 | 
			
		||||
        <input v-model="model[item.name]" @change="change($event, item.name)" placeholder="0" />
 | 
			
		||||
      </span>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import type { ContainerChangeEventData, FormValue } from '@tmagic/form';
 | 
			
		||||
 | 
			
		||||
const list = [
 | 
			
		||||
  {
 | 
			
		||||
    name: 'top',
 | 
			
		||||
    class: 'outer-top-border',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'right',
 | 
			
		||||
    class: 'outer-right-border',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'bottom',
 | 
			
		||||
    class: 'outer-bottom-border',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'left',
 | 
			
		||||
    class: 'outer-left-border',
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits<{
 | 
			
		||||
  change: [v: string, eventData: ContainerChangeEventData];
 | 
			
		||||
}>();
 | 
			
		||||
 | 
			
		||||
withDefaults(
 | 
			
		||||
  defineProps<{
 | 
			
		||||
    model: FormValue;
 | 
			
		||||
  }>(),
 | 
			
		||||
  {},
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
const change = (event: Event, name: string) => {
 | 
			
		||||
  emit('change', (event.target as HTMLInputElement).value, {
 | 
			
		||||
    modifyKey: name,
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@ -0,0 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M960 128a64 64 0 0 1 64 64v640a64 64 0 0 1-64 64H64a64 64 0 0 1-64-64V192a64 64 0 0 1 64-64h896z m0 64H64v640h896V192z m-96 64a32 32 0 0 1 32 32v448a32 32 0 0 1-32 32H160a32 32 0 0 1-32-32V288a32 32 0 0 1 32-32h704z"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M960 128a64 64 0 0 1 64 64v640a64 64 0 0 1-64 64H64a64 64 0 0 1-64-64V192a64 64 0 0 1 64-64h896z m0 64H64v640h896V192z m-96 64a32 32 0 0 1 32 32v448a32 32 0 0 1-32 32H160a32 32 0 0 1-32-32V288a32 32 0 0 1 32-32h704z"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,12 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M1024 0v1024H0V0h1024z m-73.142857 73.142857H73.142857v877.714286h877.714286V73.142857z"
 | 
			
		||||
      fill="#1D1F24"
 | 
			
		||||
    ></path>
 | 
			
		||||
    <path
 | 
			
		||||
      d="M512 219.428571v292.571429H219.428571V219.428571h292.571429zM438.857143 292.571429H292.571429v146.285714h146.285714V292.571429z"
 | 
			
		||||
      fill="#1D1F24"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,3 @@
 | 
			
		||||
export { default as BackgroundPositionLeftTop } from './LeftTop.vue';
 | 
			
		||||
export { default as DisplayFlex } from './Flex.vue';
 | 
			
		||||
export { default as DisplayInline } from './Inline.vue';
 | 
			
		||||
@ -0,0 +1,8 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M912.526651 867.741144 555.540144 510.712681l356.986507-357.000833c11.171434-11.18576 11.171434-29.257348 0-40.443108-11.20111-11.18576-29.272697-11.18576-40.444131 0L515.096013 470.267527 158.096203 113.267716c-11.187807-11.159154-29.258371-11.159154-40.444131 0-11.186783 11.186783-11.186783 29.286 0 40.47176L474.623229 510.712681 117.623419 867.741144c-11.159154 11.172457-11.159154 29.216415 0 40.443108 11.18576 11.17348 29.284977 11.17348 40.47176 0l357.000833-357.027439 356.985484 357.027439c11.171434 11.17348 29.243021 11.17348 40.444131 0C923.698085 896.957559 923.725714 878.913601 912.526651 867.741144z"
 | 
			
		||||
      fill="#5D5D5D"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,31 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M884.736 102.4l-147.456 0c-20.48 0-36.864 16.384-36.864 36.864l0 147.456C696.32 311.296 712.704 327.68 733.184 327.68l147.456 0c20.48 0 36.864-16.384 36.864-36.864L917.504 139.264C921.6 118.784 905.216 102.4 884.736 102.4zM884.736 290.816l-147.456 0L737.28 139.264l147.456 0L884.736 290.816z"
 | 
			
		||||
    ></path>
 | 
			
		||||
    <path
 | 
			
		||||
      d="M884.736 696.32l-147.456 0c-20.48 0-36.864 16.384-36.864 36.864l0 147.456c0 20.48 16.384 36.864 36.864 36.864l147.456 0c20.48 0 36.864-16.384 36.864-36.864l0-147.456C921.6 712.704 905.216 696.32 884.736 696.32zM884.736 884.736l-147.456 0 0-147.456 147.456 0L884.736 884.736z"
 | 
			
		||||
    ></path>
 | 
			
		||||
    <path
 | 
			
		||||
      d="M884.736 401.408l-147.456 0c-20.48 0-36.864 16.384-36.864 36.864l0 147.456c0 20.48 16.384 36.864 36.864 36.864l147.456 0c20.48 0 36.864-16.384 36.864-36.864l0-147.456C921.6 417.792 905.216 401.408 884.736 401.408zM884.736 585.728l-147.456 0 0-147.456 147.456 0L884.736 585.728z"
 | 
			
		||||
    ></path>
 | 
			
		||||
    <path
 | 
			
		||||
      d="M585.728 401.408l-147.456 0c-20.48 0-36.864 16.384-36.864 36.864l0 147.456c0 20.48 16.384 36.864 36.864 36.864l147.456 0c20.48 0 36.864-16.384 36.864-36.864l0-147.456C622.592 417.792 606.208 401.408 585.728 401.408zM585.728 585.728l-147.456 0 0-147.456 147.456 0L585.728 585.728z"
 | 
			
		||||
    ></path>
 | 
			
		||||
    <path
 | 
			
		||||
      d="M585.728 102.4l-147.456 0c-20.48 0-36.864 16.384-36.864 36.864l0 147.456c0 20.48 16.384 36.864 36.864 36.864l147.456 0c20.48 0 36.864-16.384 36.864-36.864L622.592 139.264C622.592 118.784 606.208 102.4 585.728 102.4zM585.728 290.816l-147.456 0L438.272 139.264l147.456 0L585.728 290.816z"
 | 
			
		||||
    ></path>
 | 
			
		||||
    <path
 | 
			
		||||
      d="M585.728 696.32l-147.456 0c-20.48 0-36.864 16.384-36.864 36.864l0 147.456c0 20.48 16.384 36.864 36.864 36.864l147.456 0c20.48 0 36.864-16.384 36.864-36.864l0-147.456C622.592 712.704 606.208 696.32 585.728 696.32zM585.728 884.736l-147.456 0 0-147.456 147.456 0L585.728 884.736z"
 | 
			
		||||
    ></path>
 | 
			
		||||
    <path
 | 
			
		||||
      d="M290.816 696.32 139.264 696.32c-20.48 0-36.864 16.384-36.864 36.864l0 147.456c0 20.48 16.384 36.864 36.864 36.864l147.456 0c20.48 0 36.864-16.384 36.864-36.864l0-147.456C327.68 712.704 311.296 696.32 290.816 696.32zM290.816 884.736 139.264 884.736l0-147.456 147.456 0L286.72 884.736z"
 | 
			
		||||
    ></path>
 | 
			
		||||
    <path
 | 
			
		||||
      d="M290.816 401.408 139.264 401.408c-20.48 0-36.864 16.384-36.864 36.864l0 147.456c0 20.48 16.384 36.864 36.864 36.864l147.456 0c20.48 0 36.864-16.384 36.864-36.864l0-147.456C327.68 417.792 311.296 401.408 290.816 401.408zM290.816 585.728 139.264 585.728l0-147.456 147.456 0L286.72 585.728z"
 | 
			
		||||
    ></path>
 | 
			
		||||
    <path
 | 
			
		||||
      d="M290.816 102.4 139.264 102.4c-20.48 0-36.864 16.384-36.864 36.864l0 147.456C102.4 311.296 118.784 327.68 139.264 327.68l147.456 0C311.296 327.68 327.68 311.296 327.68 290.816L327.68 139.264C327.68 118.784 311.296 102.4 290.816 102.4zM290.816 290.816 139.264 290.816 139.264 139.264l147.456 0L286.72 290.816z"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,8 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M796.444444 170.666667h-227.555555v682.666666h227.555555V170.666667z m-56.888888 625.777777h-113.777778V227.555556h113.777778v568.888888zM455.111111 170.666667H227.555556v682.666666h227.555555V170.666667zM398.222222 796.444444H284.444444V227.555556h113.777778v568.888888zM910.222222 56.888889h56.888889v910.222222h-56.888889zM56.888889 56.888889h56.888889v910.222222H56.888889z"
 | 
			
		||||
      fill="#333333"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,8 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M170.666667 227.555556v227.555555h682.666666V227.555556H170.666667z m625.777777 56.888888v113.777778H227.555556V284.444444h568.888888zM170.666667 568.888889v227.555555h682.666666v-227.555555H170.666667z m625.777777 56.888889v113.777778H227.555556v-113.777778h568.888888zM56.888889 56.888889h910.222222v56.888889H56.888889zM56.888889 910.222222h910.222222v56.888889H56.888889z"
 | 
			
		||||
      fill="#333333"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,4 @@
 | 
			
		||||
export { default as BackgroundRepeat } from './Repeat.vue';
 | 
			
		||||
export { default as BackgroundRepeatX } from './RepeatX.vue';
 | 
			
		||||
export { default as BackgroundRepeatY } from './RepeatY.vue';
 | 
			
		||||
export { default as BackgroundNoRepeat } from './NoRepeat.vue';
 | 
			
		||||
@ -0,0 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M960 128a64 64 0 0 1 64 64v640a64 64 0 0 1-64 64H64a64 64 0 0 1-64-64V192a64 64 0 0 1 64-64h896z m0 64H64v640h896V192z m-96 64a32 32 0 0 1 32 32v448a32 32 0 0 1-32 32H160a32 32 0 0 1-32-32V288a32 32 0 0 1 32-32h704z"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M960 128a64 64 0 0 1 64 64v640a64 64 0 0 1-64 64H64a64 64 0 0 1-64-64V192a64 64 0 0 1 64-64h896z m0 64H64v640h896V192zM352 256v512H160V256h192z m256 0v512h-192V256h192z m256 0v512h-192V256h192z"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M787.616 651.36a142.72 142.72 0 0 0 52.864 31.904 205.504 205.504 0 0 0 67.264 10.848 245.76 245.76 0 0 0 38.784-2.4c9.504-1.6 19.36-4 30.208-7.04 8.16-2.24 15.968-5.12 23.36-8.32l23.392-10.816V587.52h-8.736c-3.968 3.424-8.96 7.648-15.104 12.544a190.272 190.272 0 0 1-19.936 13.504 120.32 120.32 0 0 1-27.616 12.544 102.528 102.528 0 0 1-62.72-0.576 80 80 0 0 1-29.824-17.088 89.28 89.28 0 0 1-21.664-32.512c-5.696-13.664-8.64-30.784-8.64-51.296 0-19.744 2.72-36.384 7.968-50.08 5.248-13.664 12.384-24.896 20.992-33.056 9.12-8.832 18.816-14.816 29.632-18.816a101.824 101.824 0 0 1 63.68-0.736c9.408 3.136 18.08 7.04 26.112 11.68 13.024 7.808 25.28 16.768 36.672 26.784H1024v-78.72c-6.08-2.88-13.12-6.08-21.12-9.6a205.984 205.984 0 0 0-57.152-15.36 270.016 270.016 0 0 0-37.056-2.304c-24.864 0-47.744 4-68.704 11.84-20.992 7.776-38.432 18.784-52.64 33.6a144.256 144.256 0 0 0-33.632 54.176 207.68 207.68 0 0 0-12.48 70.176c0 27.84 3.968 52.352 12.16 73.568a146.08 146.08 0 0 0 34.176 53.184l0.064 0.416z m-186.112 34.656a122.912 122.912 0 0 0 42.784-21.504c11.2-8.32 20.224-19.296 26.24-31.936 6.56-13.664 9.888-28.704 9.664-43.904 0-22.784-6.272-41.024-18.912-54.72-12.544-13.92-29.664-23.04-51.104-27.36v-2.304c14.4-6.24 26.688-16.448 35.52-29.408 8.384-12.544 12.544-27.008 12.544-43.52 0-14.24-2.944-26.784-9.12-37.6a65.696 65.696 0 0 0-27.936-26.24 117.44 117.44 0 0 0-36.48-12.096A437.312 437.312 0 0 0 526.656 352h-127.552v340.384h143.392c23.84 0 43.52-2.112 59.008-6.4z m-118.112-271.584h7.968c16.544 0 29.472 0.128 38.656 0.352 9.248 0.576 16.864 1.728 23.04 4a26.24 26.24 0 0 1 14.4 13.12c2.656 5.28 4.064 11.072 4.128 16.96 0.16 6.656-1.056 13.248-3.52 19.392a28.064 28.064 0 0 1-15.04 13.696c-7.04 2.912-14.56 4.48-22.208 4.576-9.472 0.32-20.864 0.544-34.24 0.544h-13.184v-72.64z m6.144 215.52h-6.144v-84.8h18.464c12.64 0 24.736 0 36.384 0.256 9.216-0.16 18.432 0.896 27.36 3.2 9.696 2.848 16.544 7.232 20.512 13.12 4 5.92 6.08 14.24 6.08 25.088 0 8.192-1.728 15.488-4.992 21.824-3.232 6.336-9.696 11.392-18.24 15.392-8.544 4-18.24 5.696-28.48 6.272-10.304 0.224-27.392 0.224-51.328 0.224l0.384-0.576z m-378.56-6.016h124.672l23.36 68.416H348.8L224.32 353.728H124.416L0 692.384h87.52l23.488-68.416-0.064-0.032z m62.336-183.552l41.472 121.44h-82.88l41.408-121.44z"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M960 128a64 64 0 0 1 64 64v640a64 64 0 0 1-64 64H64a64 64 0 0 1-64-64V192a64 64 0 0 1 64-64h896z m0 64H64v640h896V192z m-131.936 158.496c65.984 1.824 109.024 32.512 129.184 92.064l-65.952 15.136-1.856-5.664c-9.984-27.52-30.432-42.112-61.376-43.84-46.72 2.784-71.456 35.296-74.208 97.6 1.856 63.2 26.56 96.64 74.24 100.32 37.536-0.928 59.52-23.36 65.92-67.328L960 559.36l-1.792 7.232c-16.96 63.872-60.352 95.84-130.144 95.84-93.44-4.608-142.464-56.8-147.04-156.672 4.576-98.048 53.6-149.792 147.04-155.296z m-568.928 4.128l114.08 302.336H297.6l-22.016-65.984H160.192L138.24 656.96H64l112.672-302.336h82.464z m278.976 0l7.68 0.32c62.816 3.36 96 27.104 99.52 71.136 0 35.744-19.712 59.552-59.104 71.456 42.144 9.184 65.952 32.544 71.456 70.08 0 59.552-37.568 89.344-112.672 89.344h-148.416v-302.336h141.536z m-4.128 173.152H465.28v81.088h67.328c33.92 0 51.296-13.76 52.224-41.248-2.752-25.632-19.68-38.912-50.848-39.84zM217.92 408.224h-1.376l-0.96 7.36c-1.184 7.232-3.168 13.92-5.92 20.128l-34.336 103.04h87.936l-38.464-104.416-2.624-9.024c-1.6-5.888-3.04-11.584-4.256-17.088z m309.184-2.752H465.28v71.456h61.824c29.344-0.928 44.448-13.76 45.376-38.464-0.96-22.016-16.032-32.992-45.376-32.992z"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M931.37 477.14c-43.94-69.49-93.39-125.03-147.99-166.35L663.31 441.46c8.79 21.36 13.63 44.91 13.63 69.62 0 96.27-73.84 174.32-164.95 174.32-21.63 0-42.28-4.39-61.32-12.47l-94.09 102.52a455.097 455.097 0 0 0 155.41 26.2c172.62 0 312.43-85.54 419.59-256.63 12.83-20.43 12.72-47.45-0.21-67.88zM795.52 127.99L682.24 252.82C627.73 231 570.1 220.04 512.11 220.5c-171.15 0-310.99 85.66-419.48 256.75-12.93 20.43-13.04 47.33-0.2 67.78 46.95 75.15 100.3 133.68 160.01 175.82L131.9 853.65l38.9 42.36 663.6-725.76-38.88-42.26zM519.68 438.37c-3.72-0.59-7.46-0.81-11.27-0.81-45.63 0-82.43 39.03-82.43 87.16 0 4.97 0.42 9.81 1.14 14.54l-57.15 60.14-5.92 8.33c-13.15-24.94-20.5-53.68-20.5-84.28 0-96.3 73.84-174.45 164.95-174.45 27.2 0 52.76 6.93 75.4 19.29l-64.22 70.08z m52.05 135.53c21.74-23.26 27.17-55.48 16.31-81.39l-96.42 103.16c26.59 9.08 58.38 1.48 80.11-21.77z"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,5 @@
 | 
			
		||||
export { default as DisplayBlock } from './Block.vue';
 | 
			
		||||
export { default as DisplayFlex } from './Flex.vue';
 | 
			
		||||
export { default as DisplayInline } from './Inline.vue';
 | 
			
		||||
export { default as DisplayInlineBlock } from './InlineBlock.vue';
 | 
			
		||||
export { default as DisplayNone } from './None.vue';
 | 
			
		||||
@ -0,0 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M896 320H128V0h768v320z m0 320H128v-256h768v256z m-128 192l-256 192-256-192 192-0.032V704h128v128h192z"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M896 704H128v320h768V704z m0-320H128v256h768v-256z m-128-192l-256-192-256 192 192 0.032V320h128V192h192z"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M320 128v768H0V128h320z m320 0v768h-256V128h256z m192 128l192 256-192 256-0.032-192H704v-128h128V256z"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M704 128v768h320V128H704zM384 128v768h256V128h-256zM192 256l-192 256 192 256 0.032-192H320v-128H192V256z"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,4 @@
 | 
			
		||||
export { default as FlexDirectionColumn } from './Column.vue';
 | 
			
		||||
export { default as FlexDirectionColumnReverse } from './ColumnReverse.vue';
 | 
			
		||||
export { default as FlexDirectionRow } from './Row.vue';
 | 
			
		||||
export { default as FlexDirectionRowReverse } from './RowReverse.vue';
 | 
			
		||||
@ -0,0 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path d="M480 1024V0h64v1024h-64z m128-64V64h320v896H608zM96 960V64h320v896H96z"></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path d="M416 160H96v704h320V160z m384 0H480v704h320V160z m128-160h-64v1024h64V0z"></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path d="M608 160h320v704H608V160zM224 160h320v704H224V160zM96 0h64v1024H96V0z"></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M320 864H192v160H128v-160H0V160h128V0h64v160h128v704z m704 0h-128v160h-64v-160h-128V160h128V0h64v160h128v704z"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path d="M64 1024H0V0h64v1024z m384-160H128V160h320v704z m448 0H576V160h320v704z m128 160h-64V0h64v1024z"></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,5 @@
 | 
			
		||||
export { default as JustifyContentCenter } from './Center.vue';
 | 
			
		||||
export { default as JustifyContentFlexEnd } from './FlexEnd.vue';
 | 
			
		||||
export { default as JustifyContentFlexStart } from './FlexStart.vue';
 | 
			
		||||
export { default as JustifyContentSpaceAround } from './SpaceAround.vue';
 | 
			
		||||
export { default as JustifyContentSpaceBetween } from './SpaceBetween.vue';
 | 
			
		||||
@ -0,0 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M128 810.666667h768v85.333333H128z m128-170.666667h512v85.333333H256z m-128-170.666667h768v85.333334H128z m0-341.333333h768v85.333333H128z m128 170.666667h512v85.333333H256z"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M128 810.666667h768v85.333333H128z m0-170.666667h512v85.333333H128z m0-170.666667h768v85.333334H128z m0-341.333333h768v85.333333H128z m0 170.666667h512v85.333333H128z"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
 | 
			
		||||
    <path
 | 
			
		||||
      d="M128 128h768v85.333333H128z m0 682.666667h768v85.333333H128z m213.333333-170.666667h554.666667v85.333333H341.333333z m-213.333333-170.666667h768v85.333334H128z m213.333333-170.666666h554.666667v85.333333H341.333333z"
 | 
			
		||||
    ></path>
 | 
			
		||||
  </svg>
 | 
			
		||||
</template>
 | 
			
		||||
@ -0,0 +1,3 @@
 | 
			
		||||
export { default as AlignLeft } from './Left.vue';
 | 
			
		||||
export { default as AlignCenter } from './Center.vue';
 | 
			
		||||
export { default as AlignRight } from './Right.vue';
 | 
			
		||||
							
								
								
									
										78
									
								
								packages/editor/src/fields/StyleSetter/pro/Background.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								packages/editor/src/fields/StyleSetter/pro/Background.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,78 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <MContainer :config="config" :model="values" @change="change"></MContainer>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { markRaw } from 'vue';
 | 
			
		||||
 | 
			
		||||
import { ContainerChangeEventData, MContainer } from '@tmagic/form';
 | 
			
		||||
import type { StyleSchema } from '@tmagic/schema';
 | 
			
		||||
 | 
			
		||||
import BackgroundPosition from '../components/BackgroundPosition.vue';
 | 
			
		||||
import { BackgroundNoRepeat, BackgroundRepeat, BackgroundRepeatX, BackgroundRepeatY } from '../icons/background-repeat';
 | 
			
		||||
 | 
			
		||||
defineProps<{ values: Partial<StyleSchema> }>();
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits<{
 | 
			
		||||
  change: [v: StyleSchema, eventData: ContainerChangeEventData];
 | 
			
		||||
}>();
 | 
			
		||||
 | 
			
		||||
const config = {
 | 
			
		||||
  items: [
 | 
			
		||||
    {
 | 
			
		||||
      name: 'backgroundColor',
 | 
			
		||||
      text: '背景色',
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      type: 'data-source-field-select',
 | 
			
		||||
      fieldConfig: {
 | 
			
		||||
        type: 'colorPicker',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'backgroundImage',
 | 
			
		||||
      text: '背景图',
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      type: 'data-source-field-select',
 | 
			
		||||
      fieldConfig: {
 | 
			
		||||
        type: 'img-upload',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'backgroundSize',
 | 
			
		||||
      text: '背景尺寸',
 | 
			
		||||
      type: 'radioGroup',
 | 
			
		||||
      childType: 'button',
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      options: [
 | 
			
		||||
        { value: 'auto', text: '默认', tooltip: '默认 auto' },
 | 
			
		||||
        { value: 'contain', text: '等比填充', tooltip: '等比填充 contain' },
 | 
			
		||||
        { value: 'cover', text: '等比覆盖', tooltip: '等比覆盖 cover' },
 | 
			
		||||
      ],
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'backgroundRepeat',
 | 
			
		||||
      text: '重复显示',
 | 
			
		||||
      type: 'radioGroup',
 | 
			
		||||
      childType: 'button',
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      options: [
 | 
			
		||||
        { value: 'repeat', icon: markRaw(BackgroundRepeat), tooltip: '垂直和水平方向重复 repeat' },
 | 
			
		||||
        { value: 'repeat-x', icon: markRaw(BackgroundRepeatX), tooltip: '水平方向重复 repeat-x' },
 | 
			
		||||
        { value: 'repeat-y', icon: markRaw(BackgroundRepeatY), tooltip: '垂直方向重复 repeat-y' },
 | 
			
		||||
        { value: 'no-repeat', icon: markRaw(BackgroundNoRepeat), tooltip: '不重复 no-repeat' },
 | 
			
		||||
      ],
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'backgroundPosition',
 | 
			
		||||
      text: '背景定位',
 | 
			
		||||
      type: 'component',
 | 
			
		||||
      component: BackgroundPosition,
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const change = (value: StyleSchema, eventData: ContainerChangeEventData) => {
 | 
			
		||||
  emit('change', value, eventData);
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										35
									
								
								packages/editor/src/fields/StyleSetter/pro/Border.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								packages/editor/src/fields/StyleSetter/pro/Border.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <MContainer :config="config" :model="values" @change="change"></MContainer>
 | 
			
		||||
  <Border :model="values" @change="change"></Border>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { type ContainerChangeEventData, MContainer } from '@tmagic/form';
 | 
			
		||||
import type { StyleSchema } from '@tmagic/schema';
 | 
			
		||||
 | 
			
		||||
import Border from '../components/Border.vue';
 | 
			
		||||
 | 
			
		||||
defineProps<{ values: Partial<StyleSchema> }>();
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits<{
 | 
			
		||||
  change: [v: StyleSchema, eventData: ContainerChangeEventData];
 | 
			
		||||
}>();
 | 
			
		||||
 | 
			
		||||
const config = {
 | 
			
		||||
  items: [
 | 
			
		||||
    {
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      name: 'borderRadius',
 | 
			
		||||
      text: '圆角',
 | 
			
		||||
      type: 'data-source-field-select',
 | 
			
		||||
      fieldConfig: {
 | 
			
		||||
        type: 'text',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const change = (value: StyleSchema, eventData: ContainerChangeEventData) => {
 | 
			
		||||
  emit('change', value, eventData);
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										90
									
								
								packages/editor/src/fields/StyleSetter/pro/Font.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								packages/editor/src/fields/StyleSetter/pro/Font.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,90 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <MContainer :config="config" :model="values" @change="change"></MContainer>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { markRaw } from 'vue';
 | 
			
		||||
 | 
			
		||||
import { ContainerChangeEventData, MContainer } from '@tmagic/form';
 | 
			
		||||
import type { StyleSchema } from '@tmagic/schema';
 | 
			
		||||
 | 
			
		||||
import { AlignCenter, AlignLeft, AlignRight } from '../icons/text-align';
 | 
			
		||||
 | 
			
		||||
defineProps<{ values: Partial<StyleSchema> }>();
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits<{
 | 
			
		||||
  change: [v: StyleSchema, eventData: ContainerChangeEventData];
 | 
			
		||||
}>();
 | 
			
		||||
 | 
			
		||||
const config = {
 | 
			
		||||
  items: [
 | 
			
		||||
    {
 | 
			
		||||
      type: 'row',
 | 
			
		||||
      items: [
 | 
			
		||||
        {
 | 
			
		||||
          labelWidth: '68px',
 | 
			
		||||
          name: 'fontSize',
 | 
			
		||||
          text: '字号',
 | 
			
		||||
          type: 'data-source-field-select',
 | 
			
		||||
          fieldConfig: {
 | 
			
		||||
            type: 'text',
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          labelWidth: '68px',
 | 
			
		||||
          name: 'lineHeight',
 | 
			
		||||
          text: '行高',
 | 
			
		||||
          type: 'data-source-field-select',
 | 
			
		||||
          fieldConfig: {
 | 
			
		||||
            type: 'text',
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      ],
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'fontWeight',
 | 
			
		||||
      text: '字重',
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      type: 'data-source-field-select',
 | 
			
		||||
      fieldConfig: {
 | 
			
		||||
        type: 'select',
 | 
			
		||||
        options: ['normal', 'bold']
 | 
			
		||||
          .concat(
 | 
			
		||||
            Array(7)
 | 
			
		||||
              .fill(1)
 | 
			
		||||
              .map((x, i) => `${i + 1}00`),
 | 
			
		||||
          )
 | 
			
		||||
          .map((item) => ({
 | 
			
		||||
            value: item,
 | 
			
		||||
            text: item,
 | 
			
		||||
          })),
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      name: 'color',
 | 
			
		||||
      text: '颜色',
 | 
			
		||||
      type: 'data-source-field-select',
 | 
			
		||||
      fieldConfig: {
 | 
			
		||||
        type: 'colorPicker',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'textAlign',
 | 
			
		||||
      text: '对齐',
 | 
			
		||||
      type: 'radioGroup',
 | 
			
		||||
      childType: 'button',
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      options: [
 | 
			
		||||
        { value: 'left', icon: markRaw(AlignLeft), tooltip: '左对齐 row' },
 | 
			
		||||
        { value: 'center', icon: markRaw(AlignCenter), tooltip: '居中对齐 center' },
 | 
			
		||||
        { value: 'right', icon: markRaw(AlignRight), tooltip: '右对齐 right' },
 | 
			
		||||
      ],
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const change = (value: StyleSchema, eventData: ContainerChangeEventData) => {
 | 
			
		||||
  emit('change', value, eventData);
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										164
									
								
								packages/editor/src/fields/StyleSetter/pro/Layout.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								packages/editor/src/fields/StyleSetter/pro/Layout.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,164 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <MContainer :config="config" :model="values" @change="change"></MContainer>
 | 
			
		||||
  <Box :model="values" @change="change"></Box>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { markRaw } from 'vue';
 | 
			
		||||
 | 
			
		||||
import type { ContainerChangeEventData, FormState } from '@tmagic/form';
 | 
			
		||||
import { MContainer } from '@tmagic/form';
 | 
			
		||||
import type { StyleSchema } from '@tmagic/schema';
 | 
			
		||||
 | 
			
		||||
import Box from '../components/Box.vue';
 | 
			
		||||
import { DisplayBlock, DisplayFlex, DisplayInline, DisplayInlineBlock, DisplayNone } from '../icons/display';
 | 
			
		||||
import {
 | 
			
		||||
  FlexDirectionColumn,
 | 
			
		||||
  FlexDirectionColumnReverse,
 | 
			
		||||
  FlexDirectionRow,
 | 
			
		||||
  FlexDirectionRowReverse,
 | 
			
		||||
} from '../icons/flex-direction';
 | 
			
		||||
import {
 | 
			
		||||
  JustifyContentCenter,
 | 
			
		||||
  JustifyContentFlexEnd,
 | 
			
		||||
  JustifyContentFlexStart,
 | 
			
		||||
  JustifyContentSpaceAround,
 | 
			
		||||
  JustifyContentSpaceBetween,
 | 
			
		||||
} from '../icons/justify-content';
 | 
			
		||||
 | 
			
		||||
defineProps<{
 | 
			
		||||
  values: Partial<StyleSchema>;
 | 
			
		||||
}>();
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits<{
 | 
			
		||||
  change: [v: string | StyleSchema, eventData: ContainerChangeEventData];
 | 
			
		||||
}>();
 | 
			
		||||
 | 
			
		||||
const config = {
 | 
			
		||||
  items: [
 | 
			
		||||
    {
 | 
			
		||||
      name: 'display',
 | 
			
		||||
      text: '模式',
 | 
			
		||||
      type: 'radioGroup',
 | 
			
		||||
      childType: 'button',
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      options: [
 | 
			
		||||
        { value: 'inline', icon: markRaw(DisplayInline), tooltip: '内联布局 inline' },
 | 
			
		||||
        { value: 'flex', icon: markRaw(DisplayFlex), tooltip: '弹性布局 flex' },
 | 
			
		||||
        { value: 'block', icon: markRaw(DisplayBlock), tooltip: '块级布局 block' },
 | 
			
		||||
        { value: 'inline-block', icon: markRaw(DisplayInlineBlock), tooltip: '内联块布局 inline-block' },
 | 
			
		||||
        { value: 'none', icon: markRaw(DisplayNone), tooltip: '隐藏 none' },
 | 
			
		||||
      ],
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'flexDirection',
 | 
			
		||||
      text: '主轴方向',
 | 
			
		||||
      type: 'radioGroup',
 | 
			
		||||
      childType: 'button',
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      options: [
 | 
			
		||||
        { value: 'row', icon: markRaw(FlexDirectionRow), tooltip: '水平方向 起点在左侧 row' },
 | 
			
		||||
        { value: 'row-reverse', icon: markRaw(FlexDirectionRowReverse), tooltip: '水平方向 起点在右侧 row-reverse' },
 | 
			
		||||
        { value: 'column', icon: markRaw(FlexDirectionColumn), tooltip: '垂直方向 起点在上沿 column' },
 | 
			
		||||
        {
 | 
			
		||||
          value: 'column-reverse',
 | 
			
		||||
          icon: markRaw(FlexDirectionColumnReverse),
 | 
			
		||||
          tooltip: '垂直方向 起点在下沿 column-reverse',
 | 
			
		||||
        },
 | 
			
		||||
      ],
 | 
			
		||||
      display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.display === 'flex',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'justifyContent',
 | 
			
		||||
      text: '主轴对齐',
 | 
			
		||||
      type: 'radioGroup',
 | 
			
		||||
      childType: 'button',
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      options: [
 | 
			
		||||
        { value: 'flex-start', icon: markRaw(JustifyContentFlexStart), tooltip: '左对齐 flex-start' },
 | 
			
		||||
        { value: 'flex-end', icon: markRaw(JustifyContentFlexEnd), tooltip: '右对齐 flex-end' },
 | 
			
		||||
        { value: 'center', icon: markRaw(JustifyContentCenter), tooltip: '居中 center' },
 | 
			
		||||
        { value: 'space-between', icon: markRaw(JustifyContentSpaceBetween), tooltip: '两端对齐 space-between' },
 | 
			
		||||
        { value: 'space-around', icon: markRaw(JustifyContentSpaceAround), tooltip: '横向平分 space-around' },
 | 
			
		||||
      ],
 | 
			
		||||
      display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.display === 'flex',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'alignItems',
 | 
			
		||||
      text: '辅轴对齐',
 | 
			
		||||
      type: 'radioGroup',
 | 
			
		||||
      childType: 'button',
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      options: [
 | 
			
		||||
        { value: 'flex-start', icon: markRaw(JustifyContentFlexStart), tooltip: '左对齐 flex-start' },
 | 
			
		||||
        { value: 'flex-end', icon: markRaw(JustifyContentFlexEnd), tooltip: '右对齐 flex-end' },
 | 
			
		||||
        { value: 'center', icon: markRaw(JustifyContentCenter), tooltip: '居中 center' },
 | 
			
		||||
        { value: 'space-between', icon: markRaw(JustifyContentSpaceBetween), tooltip: '两端对齐 space-between' },
 | 
			
		||||
        { value: 'space-around', icon: markRaw(JustifyContentSpaceAround), tooltip: '横向平分 space-around' },
 | 
			
		||||
      ],
 | 
			
		||||
      display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.display === 'flex',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      name: 'flexWrap',
 | 
			
		||||
      text: '换行',
 | 
			
		||||
      type: 'radioGroup',
 | 
			
		||||
      childType: 'button',
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      options: [
 | 
			
		||||
        { value: 'nowrap', text: '不换行', tooltip: '不换行 nowrap' },
 | 
			
		||||
        { value: 'wrap', text: '正换行', tooltip: '第一行在上方 wrap' },
 | 
			
		||||
        { value: 'wrap-reverse', text: '逆换行', tooltip: '第一行在下方 wrap-reverse' },
 | 
			
		||||
      ],
 | 
			
		||||
      display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.display === 'flex',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      type: 'row',
 | 
			
		||||
      items: [
 | 
			
		||||
        {
 | 
			
		||||
          name: 'width',
 | 
			
		||||
          text: '宽度',
 | 
			
		||||
          labelWidth: '68px',
 | 
			
		||||
          type: 'data-source-field-select',
 | 
			
		||||
          fieldConfig: {
 | 
			
		||||
            type: 'text',
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          name: 'height',
 | 
			
		||||
          text: '宽度',
 | 
			
		||||
          labelWidth: '68px',
 | 
			
		||||
          type: 'data-source-field-select',
 | 
			
		||||
          fieldConfig: {
 | 
			
		||||
            type: 'text',
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      ],
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      type: 'data-source-field-select',
 | 
			
		||||
      text: 'overflow',
 | 
			
		||||
      name: 'overflow',
 | 
			
		||||
      checkStrictly: false,
 | 
			
		||||
      dataSourceFieldType: ['string'],
 | 
			
		||||
      fieldConfig: {
 | 
			
		||||
        type: 'select',
 | 
			
		||||
        clearable: true,
 | 
			
		||||
        allowCreate: true,
 | 
			
		||||
        options: [
 | 
			
		||||
          { text: 'visible', value: 'visible' },
 | 
			
		||||
          { text: 'hidden', value: 'hidden' },
 | 
			
		||||
          { text: 'clip', value: 'clip' },
 | 
			
		||||
          { text: 'scroll', value: 'scroll' },
 | 
			
		||||
          { text: 'auto', value: 'auto' },
 | 
			
		||||
          { text: 'overlay', value: 'overlay' },
 | 
			
		||||
          { text: 'initial', value: 'initial' },
 | 
			
		||||
        ],
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const change = (value: string | StyleSchema, eventData: ContainerChangeEventData) => {
 | 
			
		||||
  emit('change', value, eventData);
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										48
									
								
								packages/editor/src/fields/StyleSetter/pro/Position.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								packages/editor/src/fields/StyleSetter/pro/Position.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <MContainer :config="config" :model="values" @change="change"></MContainer>
 | 
			
		||||
  <Position v-show="values['position'] !== 'static'" :model="values" @change="change"></Position>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { ContainerChangeEventData, MContainer } from '@tmagic/form';
 | 
			
		||||
import type { StyleSchema } from '@tmagic/schema';
 | 
			
		||||
 | 
			
		||||
import Position from '../components/Position.vue';
 | 
			
		||||
 | 
			
		||||
defineProps<{ values: Partial<StyleSchema> }>();
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits<{
 | 
			
		||||
  change: [v: string | StyleSchema, eventData: ContainerChangeEventData];
 | 
			
		||||
}>();
 | 
			
		||||
 | 
			
		||||
const config = {
 | 
			
		||||
  items: [
 | 
			
		||||
    {
 | 
			
		||||
      name: 'position',
 | 
			
		||||
      text: '定位',
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      type: 'data-source-field-select',
 | 
			
		||||
      fieldConfig: {
 | 
			
		||||
        type: 'select',
 | 
			
		||||
        options: ['static', 'relative', 'absolute', 'fixed', 'sticky'].map((item) => ({
 | 
			
		||||
          value: item,
 | 
			
		||||
          text: item,
 | 
			
		||||
        })),
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      labelWidth: '68px',
 | 
			
		||||
      name: 'zIndex',
 | 
			
		||||
      text: 'zIndex',
 | 
			
		||||
      type: 'data-source-field-select',
 | 
			
		||||
      fieldConfig: {
 | 
			
		||||
        type: 'text',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const change = (value: string | StyleSchema, eventData: ContainerChangeEventData) => {
 | 
			
		||||
  emit('change', value, eventData);
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										5
									
								
								packages/editor/src/fields/StyleSetter/pro/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								packages/editor/src/fields/StyleSetter/pro/index.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
export { default as Background } from './Background.vue';
 | 
			
		||||
export { default as Font } from './Font.vue';
 | 
			
		||||
export { default as Layout } from './Layout.vue';
 | 
			
		||||
export { default as Position } from './Position.vue';
 | 
			
		||||
export { default as Border } from './Border.vue';
 | 
			
		||||
@ -39,6 +39,7 @@ import DisplayConds from './fields/DisplayConds.vue';
 | 
			
		||||
import EventSelect from './fields/EventSelect.vue';
 | 
			
		||||
import KeyValue from './fields/KeyValue.vue';
 | 
			
		||||
import PageFragmentSelect from './fields/PageFragmentSelect.vue';
 | 
			
		||||
import StyleSetter from './fields/StyleSetter/Index.vue';
 | 
			
		||||
import uiSelect from './fields/UISelect.vue';
 | 
			
		||||
import CodeEditor from './layouts/CodeEditor.vue';
 | 
			
		||||
import { setEditorConfig } from './utils/config';
 | 
			
		||||
@ -106,6 +107,7 @@ export { default as TreeNode } from './components/TreeNode.vue';
 | 
			
		||||
export { default as PageFragmentSelect } from './fields/PageFragmentSelect.vue';
 | 
			
		||||
export { default as DisplayConds } from './fields/DisplayConds.vue';
 | 
			
		||||
export { default as CondOpSelect } from './fields/CondOpSelect.vue';
 | 
			
		||||
export { default as StyleSetter } from './fields/StyleSetter/Index.vue';
 | 
			
		||||
 | 
			
		||||
const defaultInstallOpt: EditorInstallOptions = {
 | 
			
		||||
  // eslint-disable-next-line no-eval
 | 
			
		||||
@ -143,5 +145,6 @@ export default {
 | 
			
		||||
    app.component('m-fields-page-fragment-select', PageFragmentSelect);
 | 
			
		||||
    app.component('m-fields-display-conds', DisplayConds);
 | 
			
		||||
    app.component('m-fields-cond-op-select', CondOpSelect);
 | 
			
		||||
    app.component('m-form-style-setter', StyleSetter);
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										113
									
								
								packages/editor/src/theme/style-setter/background.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								packages/editor/src/theme/style-setter/background.scss
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,113 @@
 | 
			
		||||
.background-position-container {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  .presets-value-list {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-wrap: wrap;
 | 
			
		||||
    width: 80px;
 | 
			
		||||
    height: auto;
 | 
			
		||||
    .el-button {
 | 
			
		||||
      & + .el-button {
 | 
			
		||||
        margin-left: 2px;
 | 
			
		||||
      }
 | 
			
		||||
      &:nth-child(3n + 1) {
 | 
			
		||||
        margin-left: 0 !important;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .position-icon {
 | 
			
		||||
      position: relative;
 | 
			
		||||
      width: 14px;
 | 
			
		||||
      height: 14px;
 | 
			
		||||
      border: 1px solid #1d1f24;
 | 
			
		||||
      &.active {
 | 
			
		||||
        background-color: var(--el-color-primary);
 | 
			
		||||
        &::after {
 | 
			
		||||
          border: 1px solid #fff;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      &::after {
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        content: "";
 | 
			
		||||
        border: 1px solid #1d1f24;
 | 
			
		||||
        box-sizing: border-box;
 | 
			
		||||
      }
 | 
			
		||||
      &.left-top {
 | 
			
		||||
        &::after {
 | 
			
		||||
          top: 1px;
 | 
			
		||||
          left: 1px;
 | 
			
		||||
          width: 6px;
 | 
			
		||||
          height: 6px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      &.center-top {
 | 
			
		||||
        &::after {
 | 
			
		||||
          top: 1px;
 | 
			
		||||
          left: 1px;
 | 
			
		||||
          width: 12px;
 | 
			
		||||
          height: 6px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      &.right-top {
 | 
			
		||||
        &::after {
 | 
			
		||||
          top: 1px;
 | 
			
		||||
          right: 1px;
 | 
			
		||||
          width: 6px;
 | 
			
		||||
          height: 6px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      &.left-center {
 | 
			
		||||
        &::after {
 | 
			
		||||
          top: 1px;
 | 
			
		||||
          left: 1px;
 | 
			
		||||
          width: 6px;
 | 
			
		||||
          height: 12px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      &.center-center {
 | 
			
		||||
        &::after {
 | 
			
		||||
          top: 1px;
 | 
			
		||||
          left: 1px;
 | 
			
		||||
          width: 12px;
 | 
			
		||||
          height: 12px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      &.right-center {
 | 
			
		||||
        &::after {
 | 
			
		||||
          top: 1px;
 | 
			
		||||
          right: 1px;
 | 
			
		||||
          width: 6px;
 | 
			
		||||
          height: 12px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      &.left-bottom {
 | 
			
		||||
        &::after {
 | 
			
		||||
          bottom: 1px;
 | 
			
		||||
          left: 1px;
 | 
			
		||||
          width: 6px;
 | 
			
		||||
          height: 6px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      &.center-bottom {
 | 
			
		||||
        &::after {
 | 
			
		||||
          bottom: 1px;
 | 
			
		||||
          left: 1px;
 | 
			
		||||
          width: 12px;
 | 
			
		||||
          height: 6px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      &.right-bottom {
 | 
			
		||||
        &::after {
 | 
			
		||||
          bottom: 1px;
 | 
			
		||||
          right: 1px;
 | 
			
		||||
          width: 6px;
 | 
			
		||||
          height: 6px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  .custom-value {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    flex: 1;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										53
									
								
								packages/editor/src/theme/style-setter/border.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								packages/editor/src/theme/style-setter/border.scss
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,53 @@
 | 
			
		||||
.border-box-container {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  .border-icon-container {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
    width: 88px;
 | 
			
		||||
    &-row {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      justify-content: center;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      & + .border-icon-container-row {
 | 
			
		||||
        margin-top: 8px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    .border-icon {
 | 
			
		||||
      box-sizing: border-box;
 | 
			
		||||
      width: 16px;
 | 
			
		||||
      height: 16px;
 | 
			
		||||
      border-width: 1px;
 | 
			
		||||
      border-color: #111;
 | 
			
		||||
      border-style: solid;
 | 
			
		||||
      cursor: pointer;
 | 
			
		||||
      & + .border-icon {
 | 
			
		||||
        margin-left: 8px;
 | 
			
		||||
      }
 | 
			
		||||
      &.active {
 | 
			
		||||
        border-width: 1px;
 | 
			
		||||
        border-color: var(--el-color-primary);
 | 
			
		||||
      }
 | 
			
		||||
      &.border-icon-top {
 | 
			
		||||
        border-top-width: 2px;
 | 
			
		||||
        border-style: solid dashed dashed dashed;
 | 
			
		||||
      }
 | 
			
		||||
      &.border-icon-right {
 | 
			
		||||
        border-right-width: 2px;
 | 
			
		||||
        border-style: dashed solid dashed dashed;
 | 
			
		||||
      }
 | 
			
		||||
      &.border-icon-bottom {
 | 
			
		||||
        border-bottom-width: 2px;
 | 
			
		||||
        border-style: dashed dashed solid dashed;
 | 
			
		||||
      }
 | 
			
		||||
      &.border-icon-left {
 | 
			
		||||
        border-left-width: 2px;
 | 
			
		||||
        border-style: dashed dashed dashed solid;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  .border-value-container {
 | 
			
		||||
    margin-left: 16px;
 | 
			
		||||
    flex: 1;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								packages/editor/src/theme/style-setter/index.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								packages/editor/src/theme/style-setter/index.scss
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
@use "./border.scss";
 | 
			
		||||
@use "./layout.scss";
 | 
			
		||||
@use "./background.scss";
 | 
			
		||||
 | 
			
		||||
.m-fields-style-setter {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.text-align-list {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
 | 
			
		||||
  .btn-active {
 | 
			
		||||
    color: var(--el-color-primary) !important;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										200
									
								
								packages/editor/src/theme/style-setter/layout.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								packages/editor/src/theme/style-setter/layout.scss
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,200 @@
 | 
			
		||||
// 盒子模型
 | 
			
		||||
.layout-box-container {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  margin: 0 0 16px 16px;
 | 
			
		||||
  width: 270px;
 | 
			
		||||
  height: 150px;
 | 
			
		||||
 | 
			
		||||
  .help-txt {
 | 
			
		||||
    float: left;
 | 
			
		||||
    margin-left: -10px;
 | 
			
		||||
    transform: scale(0.75);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .outer-top-border,
 | 
			
		||||
  .inner-top-border,
 | 
			
		||||
  .outer-right-border,
 | 
			
		||||
  .inner-right-border,
 | 
			
		||||
  .outer-bottom-border,
 | 
			
		||||
  .inner-bottom-border,
 | 
			
		||||
  .outer-left-border,
 | 
			
		||||
  .inner-left-border {
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    transition: all 0.3s ease;
 | 
			
		||||
    .next-input {
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      height: 20px;
 | 
			
		||||
      input {
 | 
			
		||||
        padding: 0;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        border: none;
 | 
			
		||||
        outline: none;
 | 
			
		||||
        margin: 0;
 | 
			
		||||
        font-weight: 400;
 | 
			
		||||
        vertical-align: top;
 | 
			
		||||
        background-color: transparent;
 | 
			
		||||
        color: #333;
 | 
			
		||||
        text-align: center;
 | 
			
		||||
        line-height: 20px;
 | 
			
		||||
        height: 20px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // top
 | 
			
		||||
  .outer-top-border,
 | 
			
		||||
  .inner-top-border {
 | 
			
		||||
    height: 0;
 | 
			
		||||
    border-left: 20px solid transparent;
 | 
			
		||||
    border-right: 20px solid transparent;
 | 
			
		||||
    border-top: 20px solid #d6e4ff;
 | 
			
		||||
    .next-input {
 | 
			
		||||
      left: 0;
 | 
			
		||||
      right: 0;
 | 
			
		||||
      top: -20px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .outer-top-border {
 | 
			
		||||
    top: 0;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    right: 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .inner-top-border {
 | 
			
		||||
    top: 25px;
 | 
			
		||||
    left: 25px;
 | 
			
		||||
    right: 25px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .outer-top-border,
 | 
			
		||||
  .inner-top-border {
 | 
			
		||||
    &:hover {
 | 
			
		||||
      border-top: 20px solid #bfd4fb;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // right
 | 
			
		||||
  .outer-right-border,
 | 
			
		||||
  .inner-right-border {
 | 
			
		||||
    width: 0;
 | 
			
		||||
    border-top: 20px solid transparent;
 | 
			
		||||
    border-bottom: 20px solid transparent;
 | 
			
		||||
    border-right: 20px solid #d6e4ff;
 | 
			
		||||
 | 
			
		||||
    .next-input {
 | 
			
		||||
      top: 0;
 | 
			
		||||
      bottom: 0;
 | 
			
		||||
      right: -20px;
 | 
			
		||||
      width: 20px;
 | 
			
		||||
      margin: auto;
 | 
			
		||||
      input {
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        top: 0;
 | 
			
		||||
        bottom: 0;
 | 
			
		||||
        left: 0;
 | 
			
		||||
        margin: auto;
 | 
			
		||||
        width: 20px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .outer-right-border {
 | 
			
		||||
    top: 5px;
 | 
			
		||||
    bottom: 5px;
 | 
			
		||||
    right: 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .inner-right-border {
 | 
			
		||||
    top: 30px;
 | 
			
		||||
    bottom: 30px;
 | 
			
		||||
    right: 25px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .outer-right-border,
 | 
			
		||||
  .inner-right-border {
 | 
			
		||||
    &:hover {
 | 
			
		||||
      border-right: 20px solid #bfd4fb;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // bottom
 | 
			
		||||
  .outer-bottom-border,
 | 
			
		||||
  .inner-bottom-border {
 | 
			
		||||
    height: 0;
 | 
			
		||||
    border-left: 20px solid transparent;
 | 
			
		||||
    border-right: 20px solid transparent;
 | 
			
		||||
    border-bottom: 20px solid #d6e4ff;
 | 
			
		||||
 | 
			
		||||
    .next-input {
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      left: 0;
 | 
			
		||||
      right: 0;
 | 
			
		||||
      bottom: -20px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .outer-bottom-border {
 | 
			
		||||
    bottom: 0;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    right: 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .inner-bottom-border {
 | 
			
		||||
    bottom: 25px;
 | 
			
		||||
    left: 25px;
 | 
			
		||||
    right: 25px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .outer-bottom-border,
 | 
			
		||||
  .inner-bottom-border {
 | 
			
		||||
    &:hover {
 | 
			
		||||
      border-bottom: 20px solid #bfd4fb;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // left
 | 
			
		||||
  .outer-left-border,
 | 
			
		||||
  .inner-left-border {
 | 
			
		||||
    width: 0;
 | 
			
		||||
    border-top: 20px solid transparent;
 | 
			
		||||
    border-bottom: 20px solid transparent;
 | 
			
		||||
    border-left: 20px solid #d6e4ff;
 | 
			
		||||
 | 
			
		||||
    .next-input {
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      top: 0;
 | 
			
		||||
      bottom: 0;
 | 
			
		||||
      left: -20px;
 | 
			
		||||
      width: 20px;
 | 
			
		||||
      margin: auto;
 | 
			
		||||
      input {
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        top: 0;
 | 
			
		||||
        bottom: 0;
 | 
			
		||||
        right: 0;
 | 
			
		||||
        margin: auto;
 | 
			
		||||
        width: 20px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .outer-left-border {
 | 
			
		||||
    top: 5px;
 | 
			
		||||
    bottom: 5px;
 | 
			
		||||
    left: 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .inner-left-border {
 | 
			
		||||
    top: 30px;
 | 
			
		||||
    bottom: 30px;
 | 
			
		||||
    left: 25px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .outer-left-border,
 | 
			
		||||
  .inner-left-border {
 | 
			
		||||
    &:hover {
 | 
			
		||||
      border-left: 20px solid #bfd4fb;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -26,3 +26,4 @@
 | 
			
		||||
@use "./page-fragment-select.scss";
 | 
			
		||||
@use "./data-source-field.scss";
 | 
			
		||||
@use "./data-source-field-select.scss";
 | 
			
		||||
@use "./style-setter/index.scss";
 | 
			
		||||
 | 
			
		||||
@ -46,305 +46,60 @@ export const styleTabConfig: TabPaneConfig = {
 | 
			
		||||
  items: [
 | 
			
		||||
    {
 | 
			
		||||
      name: 'style',
 | 
			
		||||
      labelWidth: '100px',
 | 
			
		||||
      type: 'style-setter',
 | 
			
		||||
      items: [
 | 
			
		||||
        {
 | 
			
		||||
          type: 'fieldset',
 | 
			
		||||
          legend: '位置',
 | 
			
		||||
          items: [
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'position',
 | 
			
		||||
              text: '固定定位',
 | 
			
		||||
              labelPosition: 'left',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'checkbox',
 | 
			
		||||
                activeValue: 'fixed',
 | 
			
		||||
                inactiveValue: 'absolute',
 | 
			
		||||
                defaultValue: 'absolute',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'left',
 | 
			
		||||
              text: 'left',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string', 'number'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'text',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'top',
 | 
			
		||||
              text: 'top',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string', 'number'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'text',
 | 
			
		||||
              },
 | 
			
		||||
              disabled: (_vm: FormState, { model }: any) =>
 | 
			
		||||
                model.position === 'fixed' && model._magic_position === 'fixedBottom',
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'right',
 | 
			
		||||
              text: 'right',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string', 'number'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'text',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'bottom',
 | 
			
		||||
              text: 'bottom',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string', 'number'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'text',
 | 
			
		||||
              },
 | 
			
		||||
              disabled: (_vm: FormState, { model }: any) =>
 | 
			
		||||
                model.position === 'fixed' && model._magic_position === 'fixedTop',
 | 
			
		||||
            },
 | 
			
		||||
          ],
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          type: 'fieldset',
 | 
			
		||||
          legend: '盒子',
 | 
			
		||||
          items: [
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'display',
 | 
			
		||||
              text: 'display',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'select',
 | 
			
		||||
                clearable: true,
 | 
			
		||||
                allowCreate: true,
 | 
			
		||||
                options: [
 | 
			
		||||
                  { text: 'block', value: 'block' },
 | 
			
		||||
                  { text: 'flex', value: 'flex' },
 | 
			
		||||
                  { text: 'none', value: 'none' },
 | 
			
		||||
                  { text: 'inline-block', value: 'inline-block' },
 | 
			
		||||
                  { text: 'grid', value: 'grid' },
 | 
			
		||||
                  { text: 'inline', value: 'inline' },
 | 
			
		||||
                  { text: 'initial', value: 'initial' },
 | 
			
		||||
                ],
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'width',
 | 
			
		||||
              text: '宽度',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string', 'number'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'text',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'height',
 | 
			
		||||
              text: '高度',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string', 'number'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'text',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              text: 'overflow',
 | 
			
		||||
              name: 'overflow',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'select',
 | 
			
		||||
                clearable: true,
 | 
			
		||||
                allowCreate: true,
 | 
			
		||||
                options: [
 | 
			
		||||
                  { text: 'visible', value: 'visible' },
 | 
			
		||||
                  { text: 'hidden', value: 'hidden' },
 | 
			
		||||
                  { text: 'clip', value: 'clip' },
 | 
			
		||||
                  { text: 'scroll', value: 'scroll' },
 | 
			
		||||
                  { text: 'auto', value: 'auto' },
 | 
			
		||||
                  { text: 'overlay', value: 'overlay' },
 | 
			
		||||
                  { text: 'initial', value: 'initial' },
 | 
			
		||||
                ],
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          ],
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          type: 'fieldset',
 | 
			
		||||
          legend: '边框',
 | 
			
		||||
          items: [
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'borderWidth',
 | 
			
		||||
              text: '宽度',
 | 
			
		||||
              defaultValue: '0',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string', 'number'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'text',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'borderColor',
 | 
			
		||||
              text: '颜色',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'text',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'borderStyle',
 | 
			
		||||
              text: '样式',
 | 
			
		||||
              defaultValue: 'none',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'select',
 | 
			
		||||
                options: [
 | 
			
		||||
                  { text: 'none', value: 'none' },
 | 
			
		||||
                  { text: 'hidden', value: 'hidden' },
 | 
			
		||||
                  { text: 'dotted', value: 'dotted' },
 | 
			
		||||
                  { text: 'dashed', value: 'dashed' },
 | 
			
		||||
                  { text: 'solid', value: 'solid' },
 | 
			
		||||
                  { text: 'double', value: 'double' },
 | 
			
		||||
                  { text: 'groove', value: 'groove' },
 | 
			
		||||
                  { text: 'ridge', value: 'ridge' },
 | 
			
		||||
                  { text: 'inset', value: 'inset' },
 | 
			
		||||
                  { text: 'outset', value: 'outset' },
 | 
			
		||||
                ],
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          ],
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          type: 'fieldset',
 | 
			
		||||
          legend: '背景',
 | 
			
		||||
          items: [
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'backgroundImage',
 | 
			
		||||
              text: '背景图',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'img-upload',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'backgroundColor',
 | 
			
		||||
              text: '背景颜色',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'colorPicker',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'backgroundRepeat',
 | 
			
		||||
              text: '背景图重复',
 | 
			
		||||
              defaultValue: 'no-repeat',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'select',
 | 
			
		||||
                options: [
 | 
			
		||||
                  { text: 'repeat', value: 'repeat' },
 | 
			
		||||
                  { text: 'repeat-x', value: 'repeat-x' },
 | 
			
		||||
                  { text: 'repeat-y', value: 'repeat-y' },
 | 
			
		||||
                  { text: 'no-repeat', value: 'no-repeat' },
 | 
			
		||||
                  { text: 'inherit', value: 'inherit' },
 | 
			
		||||
                ],
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'backgroundSize',
 | 
			
		||||
              text: '背景图大小',
 | 
			
		||||
              defaultValue: '100% 100%',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'text',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          ],
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          type: 'fieldset',
 | 
			
		||||
          legend: '字体',
 | 
			
		||||
          items: [
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'color',
 | 
			
		||||
              text: '颜色',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'colorPicker',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'fontSize',
 | 
			
		||||
              text: '大小',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string', 'number'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'text',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'fontWeight',
 | 
			
		||||
              text: '粗细',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string', 'number'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'text',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          ],
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          type: 'fieldset',
 | 
			
		||||
          legend: '变形',
 | 
			
		||||
          name: 'transform',
 | 
			
		||||
          items: [
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'rotate',
 | 
			
		||||
              text: '旋转角度',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['string'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'text',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: 'data-source-field-select',
 | 
			
		||||
              name: 'scale',
 | 
			
		||||
              text: '缩放',
 | 
			
		||||
              checkStrictly: false,
 | 
			
		||||
              dataSourceFieldType: ['number', 'string'],
 | 
			
		||||
              fieldConfig: {
 | 
			
		||||
                type: 'text',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          names: [
 | 
			
		||||
            'display',
 | 
			
		||||
            'flexDirection',
 | 
			
		||||
            'justifyContent',
 | 
			
		||||
            'alignItems',
 | 
			
		||||
            'flexWrap',
 | 
			
		||||
            'marginTop',
 | 
			
		||||
            'marginRight',
 | 
			
		||||
            'marginBottom',
 | 
			
		||||
            'marginLeft',
 | 
			
		||||
            'paddingTop',
 | 
			
		||||
            'paddingRight',
 | 
			
		||||
            'paddingBottom',
 | 
			
		||||
            'paddingLeft',
 | 
			
		||||
            'width',
 | 
			
		||||
            'height',
 | 
			
		||||
            'overflow',
 | 
			
		||||
            'fontSize',
 | 
			
		||||
            'lineHeight',
 | 
			
		||||
            'fontWeight',
 | 
			
		||||
            'color',
 | 
			
		||||
            'textAlign',
 | 
			
		||||
            'backgroundColor',
 | 
			
		||||
            'backgroundImage',
 | 
			
		||||
            'backgroundSize',
 | 
			
		||||
            'backgroundPosition',
 | 
			
		||||
            'backgroundRepeat',
 | 
			
		||||
            'position',
 | 
			
		||||
            'zIndex',
 | 
			
		||||
            'top',
 | 
			
		||||
            'right',
 | 
			
		||||
            'bottom',
 | 
			
		||||
            'left',
 | 
			
		||||
            'borderRadius',
 | 
			
		||||
            'borderTopWidth',
 | 
			
		||||
            'borderTopStyle',
 | 
			
		||||
            'borderTopColor',
 | 
			
		||||
            'borderRightColor',
 | 
			
		||||
            'borderRightWidth',
 | 
			
		||||
            'borderRightStyle',
 | 
			
		||||
            'borderRightColor',
 | 
			
		||||
            'borderBottomWidth',
 | 
			
		||||
            'borderBottomStyle',
 | 
			
		||||
            'borderBottomColor',
 | 
			
		||||
            'borderLeftStyle',
 | 
			
		||||
            'borderLeftWidth',
 | 
			
		||||
            'borderLeftColor',
 | 
			
		||||
            'borderWidth',
 | 
			
		||||
            'borderStyle',
 | 
			
		||||
            'borderColor',
 | 
			
		||||
          ],
 | 
			
		||||
        },
 | 
			
		||||
      ],
 | 
			
		||||
 | 
			
		||||
@ -306,7 +306,12 @@ const itemProp = computed(() => {
 | 
			
		||||
  return `${n}`;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const tagName = computed(() => `m-${items.value ? 'form' : 'fields'}-${type.value}`);
 | 
			
		||||
const tagName = computed(() => {
 | 
			
		||||
  if (type.value === 'component') {
 | 
			
		||||
    return props.config.component;
 | 
			
		||||
  }
 | 
			
		||||
  return `m-${items.value ? 'form' : 'fields'}-${type.value}`;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const disabled = computed(() => props.disabled || filterFunction(mForm, props.config.disabled, props));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,13 +1,30 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <TMagicRadioGroup v-if="model" v-model="model[name]" :size="size" :disabled="disabled" @change="changeHandler">
 | 
			
		||||
    <TMagicRadio v-for="option in config.options" :value="option.value" :key="`${option.value}`">{{
 | 
			
		||||
      option.text
 | 
			
		||||
    }}</TMagicRadio>
 | 
			
		||||
  <TMagicRadioGroup v-if="model" v-model="model[name]" :size="size" :disabled="disabled">
 | 
			
		||||
    <component
 | 
			
		||||
      :is="itemComponent"
 | 
			
		||||
      v-for="option in config.options"
 | 
			
		||||
      :value="option.value"
 | 
			
		||||
      :key="`${option.value}`"
 | 
			
		||||
      @click.prevent="clickHandler(option.value)"
 | 
			
		||||
    >
 | 
			
		||||
      <TMagicTooltip v-if="option.tooltip" placement="top-start" :content="option.tooltip">
 | 
			
		||||
        <div>
 | 
			
		||||
          <TMagicIcon v-if="option.icon" :size="'16'"><component :is="option.icon"></component></TMagicIcon>
 | 
			
		||||
          <span>{{ option.text }}</span>
 | 
			
		||||
        </div>
 | 
			
		||||
      </TMagicTooltip>
 | 
			
		||||
      <div v-else>
 | 
			
		||||
        <TMagicIcon v-if="option.icon" :size="'16'"><component :is="option.icon"></component></TMagicIcon>
 | 
			
		||||
        <span>{{ option.text }}</span>
 | 
			
		||||
      </div>
 | 
			
		||||
    </component>
 | 
			
		||||
  </TMagicRadioGroup>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { TMagicRadio, TMagicRadioGroup } from '@tmagic/design';
 | 
			
		||||
import { computed } from 'vue';
 | 
			
		||||
 | 
			
		||||
import { TMagicIcon, TMagicRadio, TMagicRadioButton, TMagicRadioGroup, TMagicTooltip } from '@tmagic/design';
 | 
			
		||||
 | 
			
		||||
import type { FieldProps, RadioGroupConfig } from '../schema';
 | 
			
		||||
import { useAddField } from '../utils/useAddField';
 | 
			
		||||
@ -18,11 +35,18 @@ defineOptions({
 | 
			
		||||
 | 
			
		||||
const props = defineProps<FieldProps<RadioGroupConfig>>();
 | 
			
		||||
 | 
			
		||||
const itemComponent = computed(() => (props.config.childType === 'button' ? TMagicRadioButton : TMagicRadio));
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(['change']);
 | 
			
		||||
 | 
			
		||||
const changeHandler = (value: number) => {
 | 
			
		||||
  emit('change', value);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const clickHandler = (item: any) => {
 | 
			
		||||
  props.model[props.name] = props.model[props.name] === item ? '' : item;
 | 
			
		||||
  changeHandler(props.model[props.name]);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
useAddField(props.prop);
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
@ -438,9 +438,12 @@ export interface SwitchConfig extends FormItem {
 | 
			
		||||
 */
 | 
			
		||||
export interface RadioGroupConfig extends FormItem {
 | 
			
		||||
  type: 'radio-group';
 | 
			
		||||
  childType?: 'default' | 'button';
 | 
			
		||||
  options: {
 | 
			
		||||
    value: string | number | boolean;
 | 
			
		||||
    text: string;
 | 
			
		||||
    icon?: any;
 | 
			
		||||
    tooltip?: string;
 | 
			
		||||
  }[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -126,9 +126,7 @@ export interface MComponent {
 | 
			
		||||
  /** 显示条件中配置的数据源条件的编译结果 */
 | 
			
		||||
  condResult?: boolean;
 | 
			
		||||
  /** 组件根Dom的style */
 | 
			
		||||
  style?: {
 | 
			
		||||
    [key: string]: any;
 | 
			
		||||
  };
 | 
			
		||||
  style?: StyleSchema;
 | 
			
		||||
  [NODE_CONDS_KEY]?: DisplayCond[];
 | 
			
		||||
  [key: string]: any;
 | 
			
		||||
}
 | 
			
		||||
@ -308,3 +306,7 @@ export interface UiComponentProps<T extends MNode = MNode> {
 | 
			
		||||
  config: T;
 | 
			
		||||
  model?: any;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface StyleSchema {
 | 
			
		||||
  [key: string]: any;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -13,13 +13,15 @@ interface PageFragmentContainerProps {
 | 
			
		||||
  iteratorContainerId: Id[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const PageFragmentContainer: React.FC<PageFragmentContainerProps> = ({   config,
 | 
			
		||||
const PageFragmentContainer: React.FC<PageFragmentContainerProps> = ({
 | 
			
		||||
  config,
 | 
			
		||||
  id,
 | 
			
		||||
  style,
 | 
			
		||||
  className,
 | 
			
		||||
  containerIndex,
 | 
			
		||||
  iteratorIndex,
 | 
			
		||||
  iteratorContainerId, }) => {
 | 
			
		||||
  iteratorContainerId,
 | 
			
		||||
}) => {
 | 
			
		||||
  const { app } = useApp({
 | 
			
		||||
    config,
 | 
			
		||||
    methods: {},
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,8 @@
 | 
			
		||||
import alias from '@rollup/plugin-alias';
 | 
			
		||||
import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
 | 
			
		||||
import path from 'node:path';
 | 
			
		||||
import { fileURLToPath } from 'node:url';
 | 
			
		||||
 | 
			
		||||
import alias from '@rollup/plugin-alias';
 | 
			
		||||
import dts from 'rollup-plugin-dts';
 | 
			
		||||
 | 
			
		||||
if (!existsSync('temp')) {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user