feat(editor): Add color picker design system component (#6179)

* feat(editor): Add color picker design system component

* fix(editor): remove type imports

* fix(editor): fix v-model

* fix(editor): fix props

* fix(editor): color picker view model

* test(editor): add some basic test to color picker

* fix(editor): update color picker styles

* fix(editor): color picker view model

* test(editor): update snapshot
This commit is contained in:
Csaba Tuncsik
2023-05-11 15:28:05 +02:00
committed by GitHub
parent bd1bffcd53
commit 823e88500c
7 changed files with 449 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
import { action } from '@storybook/addon-actions';
import type { StoryFn } from '@storybook/vue';
import N8nColorPicker from './ColorPicker.vue';
export default {
title: 'Atoms/ColorPicker',
component: N8nColorPicker,
argTypes: {
disabled: {
control: 'boolean',
},
size: {
control: 'select',
options: ['mini', 'small', 'medium', 'large'],
},
showAlpha: {
control: 'boolean',
},
colorFormat: {
control: 'select',
options: ['hsl', 'hsv', 'hex', 'rgb'],
},
popperClass: {
control: 'text',
},
predefine: {
control: 'array',
},
},
};
const methods = {
onChange: action('change'),
onActiveChange: action('active-change'),
onInput: action('input'),
};
const DefaultTemplate: StoryFn = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components: {
N8nColorPicker,
},
data: () => ({
color: null,
}),
template:
'<n8n-color-picker v-model="color" v-bind="$props" @input="onInput" @change="onChange" @active-change="onActiveChange" />',
methods,
});
export const Default = DefaultTemplate.bind({});
Default.args = {
disabled: false,
size: 'medium',
showAlpha: false,
colorFormat: '',
popperClass: '',
showInput: true,
};

View File

@@ -0,0 +1,99 @@
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { ColorPicker } from 'element-ui';
import N8nInput from '../N8nInput';
export type Props = {
disabled?: boolean;
size?: 'small' | 'medium' | 'mini';
showAlpha?: boolean;
colorFormat?: 'hex' | 'rgb' | 'hsl' | 'hsv';
popperClass?: string;
predefine?: string[];
value?: string;
showInput?: boolean;
};
const props = withDefaults(defineProps<Props>(), {
disabled: false,
size: 'medium',
showAlpha: false,
colorFormat: 'hex',
popperClass: '',
showInput: true,
value: null,
});
const color = ref(props.value);
const colorPickerProps = computed(() => {
const { value, showInput, ...rest } = props;
return rest;
});
const emit = defineEmits<{
(event: 'input', value: string): void;
(event: 'change', value: string): void;
(event: 'active-change', value: string): void;
}>();
const model = computed({
get() {
return color.value;
},
set(value: string) {
color.value = value;
emit('input', value);
},
});
const onChange = (value: string) => {
emit('change', value);
};
const onInput = (value: string) => {
color.value = value;
};
const onActiveChange = (value: string) => {
emit('active-change', value);
};
</script>
<template>
<span :class="['n8n-color-picker', $style.component]">
<color-picker
v-model="model"
v-bind="colorPickerProps"
@change="onChange"
@active-change="onActiveChange"
/>
<n8n-input
v-if="showInput"
:class="$style.input"
:disabled="props.disabled"
:size="props.size"
:value="color"
@input="onInput"
type="text"
/>
</span>
</template>
<style lang="scss" module>
.component {
display: inline-flex;
align-items: center;
}
.input {
margin-left: var(--spacing-3xs);
}
</style>
<style lang="scss" scoped>
:deep(.el-color-picker) {
.el-color-picker__empty,
.el-color-picker__icon {
display: none;
}
}
</style>

View File

@@ -0,0 +1,16 @@
import { render } from '@testing-library/vue';
import N8nColorPicker from '../ColorPicker.vue';
describe('components', () => {
describe('N8nColorPicker', () => {
it('should render with input', () => {
const { container } = render(N8nColorPicker);
expect(container).toMatchSnapshot();
});
it('should render without input', () => {
const { container } = render(N8nColorPicker, { props: { showInput: false } });
expect(container).toMatchSnapshot();
});
});
});

View File

@@ -0,0 +1,269 @@
// Vitest Snapshot v1
exports[`components > N8nColorPicker > should render with input 1`] = `
<div>
<span
class="n8n-color-picker component"
data-v-dab78bb8=""
>
<div
class="el-color-picker el-color-picker--medium"
data-v-dab78bb8=""
>
<!---->
<div
class="el-color-picker__trigger"
>
<span
class="el-color-picker__color"
>
<span
class="el-color-picker__color-inner"
style="background-color: transparent;"
/>
<span
class="el-color-picker__empty el-icon-close"
/>
</span>
<span
class="el-color-picker__icon el-icon-arrow-down"
style="display: none;"
/>
</div>
<transition-stub
class="el-color-picker__panel"
name="el-zoom-in-top"
>
<div
class="el-color-dropdown"
style="display: none;"
>
<div
class="el-color-dropdown__main-wrapper"
>
<div
class="el-color-hue-slider is-vertical"
style="float: right;"
>
<div
class="el-color-hue-slider__bar"
/>
<div
class="el-color-hue-slider__thumb"
style="left: 0px; top: 0px;"
/>
</div>
<div
class="el-color-svpanel"
style="background-color: rgb(255, 0, 0);"
>
<div
class="el-color-svpanel__white"
/>
<div
class="el-color-svpanel__black"
/>
<div
class="el-color-svpanel__cursor"
style="top: 0px; left: 0px;"
>
<div />
</div>
</div>
</div>
<!---->
<!---->
<div
class="el-color-dropdown__btns"
>
<span
class="el-color-dropdown__value"
>
<div
class="el-input el-input--mini"
>
<!---->
<input
autocomplete="off"
class="el-input__inner"
type="text"
/>
<!---->
<!---->
<!---->
<!---->
</div>
</span>
<button
class="el-button el-color-dropdown__link-btn el-button--text el-button--mini"
type="button"
>
<!---->
<!---->
<span>
清空
</span>
</button>
<button
class="el-button el-color-dropdown__btn el-button--default el-button--mini is-plain"
type="button"
>
<!---->
<!---->
<span>
确定
</span>
</button>
</div>
</div>
</transition-stub>
</div>
<div
class="el-input el-input--medium n8n-input input"
data-v-dab78bb8=""
>
<!---->
<input
autocomplete="off"
class="el-input__inner"
type="text"
/>
<!---->
<!---->
<!---->
<!---->
</div>
</span>
</div>
`;
exports[`components > N8nColorPicker > should render without input 1`] = `
<div>
<span
class="n8n-color-picker component"
data-v-dab78bb8=""
>
<div
class="el-color-picker el-color-picker--medium"
data-v-dab78bb8=""
>
<!---->
<div
class="el-color-picker__trigger"
>
<span
class="el-color-picker__color"
>
<span
class="el-color-picker__color-inner"
style="background-color: transparent;"
/>
<span
class="el-color-picker__empty el-icon-close"
/>
</span>
<span
class="el-color-picker__icon el-icon-arrow-down"
style="display: none;"
/>
</div>
<transition-stub
class="el-color-picker__panel"
name="el-zoom-in-top"
>
<div
class="el-color-dropdown"
style="display: none;"
>
<div
class="el-color-dropdown__main-wrapper"
>
<div
class="el-color-hue-slider is-vertical"
style="float: right;"
>
<div
class="el-color-hue-slider__bar"
/>
<div
class="el-color-hue-slider__thumb"
style="left: 0px; top: 0px;"
/>
</div>
<div
class="el-color-svpanel"
style="background-color: rgb(255, 0, 0);"
>
<div
class="el-color-svpanel__white"
/>
<div
class="el-color-svpanel__black"
/>
<div
class="el-color-svpanel__cursor"
style="top: 0px; left: 0px;"
>
<div />
</div>
</div>
</div>
<!---->
<!---->
<div
class="el-color-dropdown__btns"
>
<span
class="el-color-dropdown__value"
>
<div
class="el-input el-input--mini"
>
<!---->
<input
autocomplete="off"
class="el-input__inner"
type="text"
/>
<!---->
<!---->
<!---->
<!---->
</div>
</span>
<button
class="el-button el-color-dropdown__link-btn el-button--text el-button--mini"
type="button"
>
<!---->
<!---->
<span>
清空
</span>
</button>
<button
class="el-button el-color-dropdown__btn el-button--default el-button--mini is-plain"
type="button"
>
<!---->
<!---->
<span>
确定
</span>
</button>
</div>
</div>
</transition-stub>
</div>
<!---->
</span>
</div>
`;

View File

@@ -0,0 +1,3 @@
import N8nColorPicker from './ColorPicker.vue';
export default N8nColorPicker;

View File

@@ -48,3 +48,4 @@ export { default as N8nUsersList } from './N8nUsersList';
export { default as N8nResizeWrapper } from './N8nResizeWrapper';
export { default as N8nRecycleScroller } from './N8nRecycleScroller';
export { default as N8nCheckbox } from './N8nCheckbox';
export { default as N8nColorPicker } from './N8nColorPicker';

View File

@@ -51,6 +51,7 @@ import {
N8nResizeWrapper,
N8nRecycleScroller,
N8nCheckbox,
N8nColorPicker,
} from './components';
export const N8nPlugin: PluginObject<{}> = {
@@ -105,5 +106,6 @@ export const N8nPlugin: PluginObject<{}> = {
app.component('n8n-resize-wrapper', N8nResizeWrapper);
app.component('n8n-recycle-scroller', N8nRecycleScroller);
app.component('n8n-checkbox', N8nCheckbox);
app.component('n8n-color-picker', N8nColorPicker);
},
};