Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions examples/sites/demos/apis/color-select-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,20 @@ export default {
meta: {
stable: '3.19.0'
}
},
{
name: 'colorMode',
type: "'linear-gradient' | 'monochrome'",
defaultValue: 'monochrome',
desc: {
'zh-CN':
'决定色彩选择面板的颜色模式, 如果为 <code>linear-gradient</code> 则表示是线性渐变. 如果是 <code>monochrome</code> 则表示是单色选择',
'en-US':
'Determine the color mode of the color selection panel. If it is<code>linear-gradient</code>, it means it is a linear gradient If it is<code>monochrome</code>, it means monochrome selection'
},
mode: ['pc'],
pcDemo: 'linear-gradient',
meta: { stable: '3.27.0' }
}
],
events: [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<script lang="ts" setup>
import { TinyColorSelectPanel, TinyButton } from '@opentiny/vue'
import { ref } from 'vue'

const color = ref('linear-gradient(120deg, hsla(334, 80%, 40%, 0.32) 0%,#F48FA2FF 96%)')
const visible = ref(false)
const history = ref(['linear-gradient(120deg, hsla(201, 80%, 40%, 0.32) 0%,#8FF2F4FF 96%)'])
const predefineColor = ref(['#66ccff'])
const changeVisible = () => {
visible.value = !visible.value
}
const onConfirm = () => {
hidden()
}
const hidden = () => {
visible.value = false
}
</script>

<template>
<div>
<tiny-button @click="changeVisible">Show Color select panel</tiny-button>
<div style="position: relative">
<tiny-color-select-panel
alpha
color-mode="linear-gradient"
v-model="color"
:visible="visible"
@confirm="onConfirm"
@cancel="hidden"
enable-predefine-color
:predefine="predefineColor"
enable-history
:history="history"
/>
</div>
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { expect, test } from '@playwright/test'

test('线性渐变', async ({ page }) => {
await page.goto('color-select-panel#linear-gradient')
await page.locator('#linear-gradient').getByRole('button', { name: 'Show Color select panel' }).click()
expect(await page.locator('.tiny-color-select-panel__linear-gradient__thumb').count()).toBe(2)
await page.locator('.tiny-color-select-panel__linear-gradient__thumb').first().click()
await page.locator('.tiny-color-select-panel__linear-gradient').click()
await page.locator('.tiny-color-select-panel__linear-gradient > div:nth-child(2)').click()
})

test('线性渐变 (历史记录)', async ({ page }) => {
await page.goto('color-select-panel#linear-gradient')
await page.locator('#linear-gradient').getByRole('button', { name: 'Show Color select panel' }).click()
await expect(page.locator('.tiny-color-select-panel__history__color-block')).toBeVisible()
await expect(page.getByLabel('示例', { exact: true }).getByRole('textbox')).toHaveValue(
'linear-gradient(120deg, hsla(334, 80%, 40%, 0.32) 0%,#F48FA2FF 96%)'
)
await page.locator('.tiny-color-select-panel__history__color-block').click()
await expect(page.getByLabel('示例', { exact: true }).getByRole('textbox')).toHaveValue(
'linear-gradient(120deg, hsla(201, 80%, 40%, 0.32) 0%,#8FF2F4FF 96%)'
)
await page.getByRole('button', { name: '取消' }).click()
await page.locator('#linear-gradient').getByRole('button', { name: 'Show Color select panel' }).click()
await expect(page.getByLabel('示例', { exact: true }).getByRole('textbox')).toHaveValue(
'linear-gradient(120deg, hsla(334, 80%, 40%, 0.32) 0%,#F48FA2FF 96%)'
)
await page.locator('.tiny-color-select-panel__inner__hue-select').click()
await page.getByRole('button', { name: '确定' }).click()
await page.locator('#linear-gradient').getByRole('button', { name: 'Show Color select panel' }).click()
await page.locator('.tiny-color-select-panel__history__color-block').first().click()
await expect(page.getByLabel('示例', { exact: true }).getByRole('textbox')).toHaveValue(
'linear-gradient(120deg, hsla(201, 80%, 40%, 0.32) 0%,#8FF2F4FF 96%)'
)
await page.getByRole('button', { name: '确定' }).click()
await page.locator('#linear-gradient').getByRole('button', { name: 'Show Color select panel' }).click()
await expect(page.getByLabel('示例', { exact: true }).getByRole('textbox')).toHaveValue(
'linear-gradient(120deg, hsla(201, 80%, 40%, 0.32) 0%,#8FF2F4FF 96%)'
)
await page.getByRole('button', { name: '确定' }).click()
})

test('线性渐变 (预定义颜色)', async ({ page }) => {
await page.goto('color-select-panel#linear-gradient')

await page.locator('#linear-gradient').getByRole('button', { name: 'Show Color select panel' }).click()
await expect(page.getByLabel('示例', { exact: true }).getByRole('textbox')).toHaveValue(
'linear-gradient(120deg, hsla(334, 80%, 40%, 0.32) 0%,#F48FA2FF 96%)'
)
await page.locator('.tiny-color-select-panel__predefine__color-block').click()
await expect(page.getByLabel('示例', { exact: true }).getByRole('textbox')).toHaveValue(
'linear-gradient(180deg, #FFFFFFFF 0%,#66CCFFFF 100%)'
)
await page.getByRole('button', { name: '确定' }).click()
await page.locator('#linear-gradient').getByRole('button', { name: 'Show Color select panel' }).click()
await page.locator('.tiny-color-select-panel__history__color-block').first().click()
await expect(page.getByLabel('示例', { exact: true }).getByRole('textbox')).toHaveValue(
'linear-gradient(120deg, hsla(201, 80%, 40%, 0.32) 0%,#8FF2F4FF 96%)'
)
await page.locator('.tiny-color-select-panel__history > div:nth-child(2)').click()
await expect(page.getByLabel('示例', { exact: true }).getByRole('textbox')).toHaveValue(
'linear-gradient(180deg, #FFFFFFFF 0%,#66CCFFFF 100%)'
)
await page.locator('.tiny-color-select-panel__history__color-block').first().click()
await page.getByRole('button', { name: '确定' }).click()
await page.locator('#linear-gradient').getByRole('button', { name: 'Show Color select panel' }).click()
await expect(page.getByLabel('示例', { exact: true }).getByRole('textbox')).toHaveValue(
'linear-gradient(120deg, hsla(201, 80%, 40%, 0.32) 0%,#8FF2F4FF 96%)'
)
await page.getByRole('button', { name: '确定' }).click()
})
45 changes: 45 additions & 0 deletions examples/sites/demos/pc/app/color-select-panel/linear-gradient.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<script lang="ts">
import { defineComponent } from 'vue'
import { ref } from 'vue'
import { TinyButton, TinyColorSelectPanel } from '@opentiny/vue'

export default defineComponent({
components: { TinyButton, TinyColorSelectPanel },
setup() {
const color = ref('linear-gradient(120deg, hsla(334, 80%, 40%, 0.32) 0%,#F48FA2FF 96%)')
const visible = ref(false)
const history = ref(['linear-gradient(120deg, hsla(201, 80%, 40%, 0.32) 0%,#8FF2F4FF 96%)'])
const predefineColor = ref(['#66ccff'])
const changeVisible = () => {
visible.value = !visible.value
}
const onConfirm = () => {
hidden()
}
const hidden = () => {
visible.value = false
}
return { color, visible, history, predefineColor, changeVisible, onConfirm, hidden }
}
})
</script>

<template>
<div>
<tiny-button @click="changeVisible">Show Color select panel</tiny-button>
<div style="position: relative">
<tiny-color-select-panel
alpha
color-mode="linear-gradient"
v-model="color"
:visible="visible"
@confirm="onConfirm"
@cancel="hidden"
enable-predefine-color
:predefine="predefineColor"
enable-history
:history="history"
/>
</div>
</div>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ export default {
},
codeFiles: ['base.vue']
},
{
demoId: 'linear-gradient',
name: {
'zh-CN': '线性渐变',
'en-US': 'Linear Gradient'
},
desc: {
'zh-CN': '通过<code>color-mode</code>设置显示色彩选择的色彩模式。',
'en-US': 'Set the color mode for display color selection through<code>color mode</code>.'
},
codeFiles: ['linear-gradient.vue']
},
{
demoId: 'alpha',
name: {
Expand Down
38 changes: 25 additions & 13 deletions packages/renderless/src/color-select-panel/alpha-select/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import type { IColorSelectPanelAlphProps, IColorSelectPanelRef, ISharedRenderlessParamHooks } from '@/types'
import type {
ColorPanelContext,
IColorSelectPanelAlphProps,
IColorSelectPanelRef,
ISharedRenderlessParamHooks
} from '@/types'
import type { Color } from '../utils/color'
import { getClientXY } from '../utils/getClientXY'
import { useContext } from '../utils/context'

type State = ReturnType<typeof initState>

export const initState = ({ ref, reactive }: ISharedRenderlessParamHooks) => {
const background = ref('')
export const initState = (hooks: ISharedRenderlessParamHooks) => {
const { ref, reactive } = hooks
const ctx = useContext(hooks)
const background = ref(ctx.activeColor.value.color.value)
const left = ref(0)
const state = reactive({ background, left })
const state = reactive({ background, left, activeColor: ctx.activeColor })
return state
}

Expand All @@ -16,7 +24,8 @@ export const useEvent = (
slider: IColorSelectPanelRef<HTMLElement | undefined>,
alphaWrapper: IColorSelectPanelRef<HTMLElement | undefined>,
alphaThumb: IColorSelectPanelRef<HTMLElement | undefined>,
props: IColorSelectPanelAlphProps<Color>
props: IColorSelectPanelAlphProps<Color>,
ctx: ColorPanelContext
) => {
const onDrag = (event: MouseEvent | TouchEvent) => {
if (!slider.value || !alphaThumb.value) {
Expand All @@ -31,7 +40,7 @@ export const useEvent = (
const alpha = Math.round(
((left - alphaThumb.value.offsetWidth / 2) / (rect.width - alphaThumb.value.offsetWidth)) * 100
)
props.color.set('alpha', alpha)
ctx.activeColor.value.color.set('alpha', alpha)
}
const onClick = (event: MouseEvent | TouchEvent) => {
if (event.target !== alphaThumb.value) {
Expand All @@ -47,12 +56,12 @@ export const useEvent = (
if (!el) {
return 0
}
const alpha = props.color.get('alpha')
const alpha = ctx.activeColor.value.color.get('alpha')
return (alpha * (el.offsetWidth - thumb.offsetWidth / 2)) / 100
}
const getBackground = () => {
if (props.color && props.color.value) {
const { r, g, b } = props.color.toRgb()
if (ctx.activeColor && ctx.activeColor.value) {
const { r, g, b } = ctx.activeColor.value.color.toRgb()
return `linear-gradient(to right, rgba(${r}, ${g}, ${b}, 0) 0%, rgba(${r}, ${g}, ${b}, 1) 100%)`
}
return ''
Expand All @@ -67,15 +76,18 @@ export const useEvent = (
export const initWatch = (
props: IColorSelectPanelAlphProps<Color>,
update: () => void,
{ watch }: ISharedRenderlessParamHooks
{ watch }: ISharedRenderlessParamHooks,
ctx: ColorPanelContext
) => {
watch(
() => props.color.get('alpha'),
() => update(),
() => ctx.activeColor.value.color,
() => {
update()
},
{ deep: true }
)
watch(
() => props.color,
() => ctx.activeColor,
() => update(),
{ deep: true }
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { IColorSelectPanelAlphProps, ISharedRenderlessParamHooks, ISharedRe
import type { Color } from '../utils/color'
import { draggable } from '../utils/use-drag'
import { initState, initWatch, useEvent } from '.'
import { useContext } from '../utils/context'

export const api = ['state', 'color', 'slider', 'alphaWrapper', 'alphaThumb', 'onClick']

Expand All @@ -15,8 +16,9 @@ export const renderless = (
const slider = ref<HTMLElement>()
const alphaWrapper = ref<HTMLElement>()
const alphaThumb = ref<HTMLElement>()
const ctx = useContext(hooks)
const state = initState(hooks)
const { update, onClick, onDrag } = useEvent(state, slider, alphaWrapper, alphaThumb, props)
const { update, onClick, onDrag } = useEvent(state, slider, alphaWrapper, alphaThumb, props, ctx)
onMounted(() => {
if (!slider.value || !alphaThumb.value) {
return
Expand All @@ -36,7 +38,7 @@ export const renderless = (
emit('ready', update)
})

initWatch(props, update, hooks)
initWatch(props, update, hooks, ctx)

const api = {
state,
Expand Down
Loading
Loading