feat(components):[color-picker] add props size、predefine and history (#711)

* feat(components):[color-picker] add props size、predefine and history

* fix(e2e):[color-picker] Add e2e tests for size, predefine, and history in color-picker

* fix(e2e):[color-picker] fix e2e tests bug

* add key
This commit is contained in:
fanbingbing16 2023-11-03 18:18:09 +08:00 committed by GitHub
parent 32cca5ede1
commit fc6c6cb2c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 348 additions and 6 deletions

View File

@ -0,0 +1,23 @@
<template>
<div>
<ColorPicker v-model="color" :history="history" />
<Button @click="addHistoryColor">Append history color</Button>
<Button @click="popHistoryColor">Pop history color</Button>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { ColorPicker, Button } from '@opentiny/vue';
const color = ref('#66ccff');
const history = ref(['#66ccff']);
const randomHex = () => "#" + Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, "0");
const addHistoryColor = () => {
history.value.push(
randomHex()
);
}
const popHistoryColor = () => {
history.value.pop();
}
</script>

View File

@ -0,0 +1,29 @@
import { test, expect } from '@playwright/test'
test('测试历史记录', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('color-picker#history')
await page.locator('.tiny-color-picker__trigger').click()
await page.waitForSelector('.tiny-collapse-item__arrow')
const arrow = page.locator('.tiny-collapse-item__arrow')
await arrow.click()
await expect(page.locator('.tiny-color-select-panel__history')).toHaveCount(1)
await page.locator('.mr20.fw-bold').click()
//用户行为更改历史记录测试
await page.getByRole('button', { name: 'Append history color' }).click()
await page.locator('.tiny-color-picker__trigger').click()
await page.waitForSelector('.tiny-collapse-item__arrow')
await page.locator('.tiny-collapse-item__arrow').click()
await expect(page.locator('.tiny-color-select-panel__history .tiny-color-select-panel__history__color-block:nth-child(2)')).toBeVisible()
//点击色块中心并点击选择历史记录增加1的测试
const black = page.locator('.black')
const center = await black.boundingBox()
const x = center?.x ?? 0 + (center?.width ?? 0) / 2
const y = center?.y ?? 0 + (center?.height ?? 0) / 2
await black.click(x, y)
await page.getByRole('button', { name: '选择' }).click()
await page.locator('.tiny-color-picker__trigger').click()
await page.waitForSelector('.tiny-collapse-item__arrow')
await page.locator('.tiny-collapse-item__arrow').click()
await expect(page.locator('.tiny-color-select-panel__history .tiny-color-select-panel__history__color-block:nth-child(3)')).toBeVisible()
})

View File

@ -0,0 +1,37 @@
<template>
<div>
<tiny-color-picker v-model="color" :history="history" />
<Button @click="addHistoryColor">Append history color</Button>
<Button @click="popHistoryColor">Pop history color</Button>
</div>
</template>
<script>
import { ref } from 'vue';
import { ColorPicker, Button } from '@opentiny/vue';
export default {
components: {
TinyColorPicker: ColorPicker,
Button
},
setup() {
const color = ref('#66ccff');
const history = ref(['#66ccff25']);
const randomHex = () => "#" + Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, "0");
const addHistoryColor = () => {
history.value.push(
randomHex()
);
}
const popHistoryColor = () => {
history.value.pop();
}
return {
color,
history,
addHistoryColor,
popHistoryColor
}
}
}
</script>

View File

@ -0,0 +1,23 @@
<template>
<div>
<ColorPicker v-model="color" :predefine="predefine" />
<Button @click="addPredefineColor">Append predefine color</Button>
<Button @click="popPredefineColor">Pop predefine color</Button>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { ColorPicker, Button } from '@opentiny/vue';
const color = ref('#66ccff');
const randomHex = () => "#" + Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, "0");
const predefine = ref(new Array(8).fill(0).map(() => randomHex()))
const addPredefineColor = () => {
predefine.value.push(
randomHex()
);
}
const popPredefineColor = () => {
predefine.value.pop();
}
</script>

View File

@ -0,0 +1,18 @@
import { test, expect } from '@playwright/test'
test('测试预定义颜色', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('color-picker#predefine')
await page.locator('.tiny-color-picker__trigger').click()
await page.waitForSelector('.tiny-collapse-item__arrow')
const arrow = page.locator('.tiny-collapse-item__arrow')
await arrow.click()
await expect(page.locator('.tiny-color-select-panel__predefine .tiny-color-select-panel__predefine__color-block:nth-child(8)')).toBeVisible()
await page.locator('.mr20.fw-bold').click()
//用户行为预定义颜色测试
await page.getByRole('button', { name: 'Append predefine color' }).click()
await page.locator('.tiny-color-picker__trigger').click()
await page.waitForSelector('.tiny-collapse-item__arrow')
await page.locator('.tiny-collapse-item__arrow').click()
await expect(page.locator('.tiny-color-select-panel__predefine .tiny-color-select-panel__predefine__color-block:nth-child(9)')).toBeVisible()
})

View File

@ -0,0 +1,37 @@
<template>
<div>
<tiny-color-picker v-model="color" :predefine="predefine" />
<Button @click="addPredefineColor">Append predefine color</Button>
<Button @click="popPredefineColor">Pop predefine color</Button>
</div>
</template>
<script>
import { ref } from 'vue';
import { ColorPicker, Button } from '@opentiny/vue';
export default {
components: {
TinyColorPicker: ColorPicker,
Button
},
setup() {
const color = ref('#66ccff');
const randomHex = () => "#" + Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, "0");
const predefine = ref(new Array(8).fill(0).map(() => randomHex()))
const addPredefineColor = () => {
predefine.value.push(
randomHex()
);
}
const popPredefineColor = () => {
predefine.value.pop();
}
return {
color,
predefine,
addPredefineColor,
popPredefineColor
}
}
}
</script>

View File

@ -0,0 +1,14 @@
<template>
<div>
<tiny-color-picker v-model="color" size="large" />
<tiny-color-picker v-model="color" size="medium" />
<tiny-color-picker v-model="color" size="small" />
<tiny-color-picker v-model="color" size="mini" />
</div>
</template>
<script setup>
import { ColorPicker as TinyColorPicker } from '@opentiny/vue'
import { ref } from 'vue'
const color = ref('#66ccff')
</script>

View File

@ -0,0 +1,10 @@
import { test, expect } from '@playwright/test'
test('测试尺寸', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('color-picker#size')
await expect(page.locator('.tiny-color-picker__trigger.tiny-color-picker--large')).toHaveCSS('width', '64px')
await expect(page.locator('.tiny-color-picker__trigger.tiny-color-picker--medium')).toHaveCSS('width', '48px')
await expect(page.locator('.tiny-color-picker__trigger.tiny-color-picker--small')).toHaveCSS('width', '36px')
await expect(page.locator('.tiny-color-picker__trigger.tiny-color-picker--mini')).toHaveCSS('width', '24px')
})

View File

@ -0,0 +1,22 @@
<template>
<div>
<tiny-color-picker v-model="color" size="large" />
<tiny-color-picker v-model="color" size="medium" />
<tiny-color-picker v-model="color" size="small" />
<tiny-color-picker v-model="color" size="mini" />
</div>
</template>
<script>
import { ColorPicker } from '@opentiny/vue'
export default {
components: {
TinyColorPicker: ColorPicker
},
data() {
return {
color: '#66ccff',
}
}
}
</script>

View File

@ -8,6 +8,12 @@ export default {
'desc': { 'zh-CN': '详细用法参考如下示例', 'en-US': 'For details, see the following example.' },
'codeFiles': ['base.vue']
},
{
'demoId': 'size',
'name': { 'zh-CN': '尺寸设置', 'en-US': 'Size Setting' },
'desc': { 'zh-CN': '通过 size 属性设置large 、medium 、small 、mini 四种不同大小尺寸。不设置时为默认尺寸。', 'en-US': 'For details, see the following example.' },
'codeFiles': ['size.vue']
},
{
'demoId': 'event',
'name': { 'zh-CN': '事件触发', 'en-US': 'event' },
@ -20,6 +26,27 @@ export default {
'desc': { 'zh-CN': 'Alpha选择', 'en-US': 'Alpha select.' },
'codeFiles': ['alpha.vue']
},
{
'demoId': 'history',
'name': { 'zh-CN': '历史记录', 'en-US': 'history' },
'desc': {
'zh-CN': '当history不为undefined时, 将会启用历史记录功能。当用户点击确认时, 将会自动将颜色插入到history. 用户行为会更改历史记录, 外部可以更改历史记录',
'en-US': 'When history is not undefined, the history function will be enabled. When the user clicks confirm, the color will automatically be inserted into the history User behavior can change history, and external users can also change history'
},
'codeFiles': ['history.vue']
},
{
'demoId': 'predefine',
'name': {
'zh-CN': '预定义颜色',
'en-US': 'predefine color'
},
'desc': {
'zh-CN': '提供给一些定义颜色, 用户行为不会更改预定义颜色, 但外部可以更改',
'en-US': 'Provide some defined colors, user behavior will not change the predefined colors, but can be changed externally'
},
'codeFiles': ['predefine.vue']
},
{
'demoId': 'default-visible',
'name': { 'zh-CN': '默认显示', 'en-US': 'default-visible' },
@ -64,6 +91,16 @@ export default {
},
demoId: 'default-visible'
},
{
name: 'size',
type: 'string',
defaultValue: '',
desc: {
'zh-CN': '定义color-picker尺寸;该属性的可选值为 large / medium / small / mini',
'en-US': 'Define color-picker dimensions; The optional values for this attribute are large/medium/small/mini'
},
demoId: 'size'
},
{
name: 'alpha',
type: 'boolean',
@ -73,6 +110,26 @@ export default {
'en-US': 'enable alpha select or not'
},
demoId: 'enable-alpha'
},
{
name: 'history',
type: 'string[] | undefined',
defaultValue: 'undefined',
desc: {
'zh-CN': '启用历史记录',
'en-US': 'enable history or not'
},
demoId: 'history'
},
{
name: 'predefine',
type: 'string[] | undefined',
defaultValue: 'undefined',
desc: {
'zh-CN': '启用预定义颜色',
'en-US': 'enable predefine or not'
},
demoId: 'predefine'
}
],
'events': [

View File

@ -16,7 +16,7 @@ export const api = [
]
export const renderless = (props, context, { emit }) => {
const { modelValue, visible } = context.toRefs(props)
const { modelValue, visible, predefine, size, history } = context.toRefs(props)
const hex = context.ref(modelValue.value ?? 'transparent')
const res = context.ref(modelValue.value ?? 'transparent')
const triggerBg = context.ref(modelValue.value ?? 'transparent')
@ -25,6 +25,12 @@ export const renderless = (props, context, { emit }) => {
const changeVisible = (state: boolean) => {
isShow.value = state
}
const stack: Ref<string[]> = context.ref(
[...(history?.value ?? [])]
)
const predefineStack: Ref<string[]> = context.ref(
[...(predefine?.value ?? [])]
)
const color = new Color(hex.value, props.alpha)
const state = context.reactive({
isShow,
@ -32,8 +38,17 @@ export const renderless = (props, context, { emit }) => {
color,
triggerBg,
defaultValue: modelValue,
res
res,
predefineStack,
size: size ?? '',
stack
})
context.watch(predefine, (newPredefine: string[]) => {
predefineStack.value = [...newPredefine];
}, { deep: true })
context.watch(history, (newHistory: string[]) => {
stack.value = [...newHistory]
}, { deep: true })
context.watch(modelValue, (newValue) => {
hex.value = newValue
res.value = newValue

View File

@ -126,4 +126,23 @@
}
}
}
&--large {
width: var(--ti-color-picker-size-large-width);
height: var(--ti-color-picker-size-large-height);
}
&--small {
width: var(--ti-color-picker-size-small-width);
height: var(--ti-color-picker-size-small-height);
}
&--medium {
width: var(--ti-color-picker-size-medium-width);
height: var(--ti-color-picker-size-medium-height);
}
&--mini {
width: var(--ti-color-picker-size-mini-width);
height: var(--ti-color-picker-size-mini-height);
}
}

View File

@ -10,4 +10,24 @@
--ti-color-picker-shadow: var(--ti-common-shadow-2-down);
--ti-color-picker__select__wrapper-zindex: 1000;
--ti-color-picker__wrapper-bg: var(--ti-common-color-bg-white-emphasize);
// 超大尺寸高度
--ti-color-picker-size-large-height: var(--ti-common-size-16x);
// 超大尺寸宽度
--ti-color-picker-size-large-width: var(--ti-common-size-16x);
// 中等尺寸高度
--ti-color-picker-size-medium-height: var(--ti-common-size-12x);
// 中等尺寸最小宽度
--ti-color-picker-size-medium-width: var(--ti-common-size-12x);
// 小型高度
--ti-color-picker-size-small-height: var(--ti-common-size-9x);
// 小尺寸宽度
--ti-color-picker-size-small-width: var(--ti-common-size-9x);
// 迷你尺寸按钮高度
--ti-color-picker-size-mini-height: var(--ti-common-size-6x);
// 迷你尺寸宽度
--ti-color-picker-size-mini-width: var(--ti-common-size-6x);
}

View File

@ -13,7 +13,16 @@ export default defineComponent({
},
modelValue: String,
visible: Boolean,
alpha: Boolean
alpha: Boolean,
predefine: Array,
history: Array,
size: {
type: String,
default: '',
validator(val: string) {
return ['large', 'medium', 'small', 'mini', ''].includes(val)
}
},
},
setup(props, context) {
return $setup({ props, context, template })

View File

@ -1,5 +1,12 @@
<template>
<div class="tiny-color-picker__trigger" @click="() => changeVisible(!state.isShow)">
<div
:class="[{
'tiny-color-picker__trigger': true
},
state.size ? 'tiny-color-picker--' + state.size : '',
]"
@click="() => changeVisible(!state.isShow)"
>
<div
class="tiny-color-picker__inner"
:style="{
@ -17,6 +24,8 @@
v-model="state.hex"
:visible="state.isShow"
:alpha="alpha"
:predefine="state.predefineStack.length > 0 ? state.predefineStack : undefined"
:history="state.stack.length > 0 ? state.stack : undefined"
/>
</Transition>
</div>
@ -31,13 +40,13 @@ import '@opentiny/vue-theme/color-picker/index.less'
export default defineComponent({
emits: ['update:modelValue', 'confirm', 'cancel'],
props: [...props, 'modelValue', 'visible', 'alpha'],
props: [...props, 'modelValue', 'visible', 'alpha', 'predefine', 'history', 'size'],
components: {
IconChevronDown: IconChevronDown(),
ColorSelect: colorSelect
},
setup(props, context) {
return setup({ props, context, renderless, api })
}
},
})
</script>