Skip to content

Commit

Permalink
feat: custom color picker
Browse files Browse the repository at this point in the history
  • Loading branch information
zzxming authored Dec 7, 2024
2 parents 454c87a + 6a72e03 commit be581c3
Show file tree
Hide file tree
Showing 11 changed files with 603 additions and 66 deletions.
1 change: 1 addition & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default factory({
{
rules: {
'unicorn/prefer-dom-node-dataset': 'off',
'unicorn/consistent-function-scoping': 'off',
'no-cond-assign': 'off',
'new-cap': 'off',
},
Expand Down
70 changes: 43 additions & 27 deletions src/modules/table-menu/table-menu-common.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type Quill from 'quill';
import type { TableUp } from '../..';
import type { TableMenuOptions, ToolOption, TooltipInstance } from '../../utils';
import { createTooltip, debounce, defaultColorMap, isArray, isFunction, randomId } from '../../utils';
import type { TableMenuOptions, ToolOption, TooltipInstance, ToolTipOptions } from '../../utils';
import { createColorPicker, createTooltip, debounce, defaultColorMap, isArray, isFunction, randomId } from '../../utils';
import { colorClassName, defaultTools, maxSaveColorCount, menuColorSelectClassName, usedColors } from './constants';

export type TableMenuOptionsInput = Partial<Omit<TableMenuOptions, 'texts'>>;
Expand All @@ -10,6 +10,10 @@ export class TableMenuCommon {
menu: HTMLElement | null = null;
updateUsedColor: (this: any, color?: string) => void;
colorItemClass = `color-${randomId()}`;
colorChooseTooltipOption: ToolTipOptions = {
direction: 'top',
};

tooltipItem: TooltipInstance[] = [];

constructor(public tableModule: TableUp, public quill: Quill, options: TableMenuOptionsInput) {
Expand Down Expand Up @@ -92,11 +96,9 @@ export class TableMenuCommon {
}
item.appendChild(iconDom);

// color choose handler will trigger when the color input event
if (isColorChoose && attrKey) {
const colorSelectWrapper = this.createColorChoose({ name, icon, handle, isColorChoose, key: attrKey, tip });
const tooltipItem = createTooltip(item, { content: colorSelectWrapper, direction: 'top' });
tooltipItem && this.tooltipItem.push(tooltipItem);
const tooltipItem = this.createColorChoose(item, { name, icon, handle, isColorChoose, key: attrKey, tip });
this.tooltipItem.push(tooltipItem);
item.classList.add(menuColorSelectClassName);
}
else {
Expand All @@ -117,7 +119,7 @@ export class TableMenuCommon {
return toolBox;
};

createColorChoose({ handle, key }: ToolOption) {
createColorChoose(item: HTMLElement, { handle, key }: ToolOption) {
const colorSelectWrapper = document.createElement('div');
colorSelectWrapper.classList.add(colorClassName.selectWrapper);

Expand Down Expand Up @@ -155,30 +157,25 @@ export class TableMenuCommon {
clearColor.addEventListener('click', () => {
handle(this.tableModule, this.getSelectedTds(), null);
});
const label = document.createElement('label');
label.classList.add(colorClassName.btn, 'table-color-custom');
const customColor = document.createElement('span');
const customColor = document.createElement('div');
customColor.classList.add(colorClassName.btn, 'table-color-custom');
customColor.textContent = this.tableModule.options.texts.custom;
const input = document.createElement('input');
input.type = 'color';
Object.assign(input.style, {
width: 0,
height: 0,
padding: 0,
border: 0,
outline: 'none',
opacity: 0,
const colorPicker = createColorPicker({
onChange: (color) => {
handle(this.tableModule, this.getSelectedTds(), color);
this.updateUsedColor(color);
},
});
input.addEventListener('input', () => {
handle(this.tableModule, this.getSelectedTds(), input.value);
this.updateUsedColor(input.value);
}, false);
label.appendChild(customColor);
label.appendChild(input);
const { hide: hideColorPicker, destroy: destroyColorPicker } = createTooltip(customColor, {
direction: 'right',
type: 'click',
content: colorPicker,
container: customColor,
})!;

colorMapRow.appendChild(transparentColor);
colorMapRow.appendChild(clearColor);
colorMapRow.appendChild(label);
colorMapRow.appendChild(customColor);
colorSelectWrapper.appendChild(colorMapRow);

if (usedColors.size > 0) {
Expand All @@ -194,6 +191,8 @@ export class TableMenuCommon {
}

colorSelectWrapper.addEventListener('click', (e) => {
e.stopPropagation();
hideColorPicker();
const item = e.target as HTMLElement;
const color = item.style.backgroundColor;
const selectedTds = this.getSelectedTds();
Expand All @@ -203,7 +202,21 @@ export class TableMenuCommon {
this.updateUsedColor(color);
}
});
return colorSelectWrapper;

return createTooltip(item, {
content: colorSelectWrapper,
onClose(force) {
const isChild = colorSelectWrapper.contains(colorPicker);
if (force && isChild) {
hideColorPicker();
}
return isChild;
},
onDestroy() {
destroyColorPicker();
},
...this.colorChooseTooltipOption,
})!;
}

getSelectedTds() {
Expand All @@ -222,6 +235,9 @@ export class TableMenuCommon {

hideTools() {
this.menu && Object.assign(this.menu.style, { display: 'none' });
for (const tooltip of this.tooltipItem) {
tooltip.hide(true);
}
}

destroy() {
Expand Down
6 changes: 5 additions & 1 deletion src/modules/table-menu/table-menu-contextmenu.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import type Quill from 'quill';
import type TableUp from '../..';
import type { TableMenuOptions } from '../../utils';
import type { TableMenuOptions, ToolTipOptions } from '../../utils';
import { limitDomInViewPort } from '../../utils';
import { contextmenuClassName, menuColorSelectClassName } from './constants';
import { TableMenuCommon } from './table-menu-common';

type TableMenuOptionsInput = Partial<Omit<TableMenuOptions, 'texts'>>;
export class TableMenuContextmenu extends TableMenuCommon {
colorChooseTooltipOption: ToolTipOptions = {
direction: 'right',
};

constructor(public tableModule: TableUp, public quill: Quill, options: TableMenuOptionsInput) {
super(tableModule, quill, options);

Expand Down
9 changes: 3 additions & 6 deletions src/modules/table-scrollbar.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type TableUp from '..';
import type { TableMainFormat } from '../formats';
import Quill from 'quill';
import { addScrollEvent, clearScrollEvent, debounce, handleIfTransitionend } from '../utils';
import { addScrollEvent, clearScrollEvent, debounce } from '../utils';

export class Scrollbar {
minSize: number = 20;
Expand Down Expand Up @@ -115,7 +115,6 @@ export class Scrollbar {
});
this.thumb.classList.add('ql-table-scrollbar-thumb');

// eslint-disable-next-line unicorn/consistent-function-scoping
const mouseMoveDocumentHandler = (e: MouseEvent) => {
if (this.cursorDown === false) return;
const prevPage = this.thumbState[this.propertyMap.axis];
Expand Down Expand Up @@ -180,20 +179,18 @@ export class Scrollbar {
});
}

// eslint-disable-next-line unicorn/consistent-function-scoping
showScrollbar = debounce(() => {
this.cursorLeave = false;
this.scrollbar.classList.remove('transparent');
handleIfTransitionend(this.scrollbar, 150, () => {
this.scrollbar.addEventListener('transitionend', () => {
this.scrollbar.style.display = (this.isVertical ? this.sizeHeight : this.sizeWidth) ? 'block' : 'none';
});
}, 200);

// eslint-disable-next-line unicorn/consistent-function-scoping
hideScrollbar = debounce(() => {
this.cursorLeave = true;
this.scrollbar.classList.add('transparent');
handleIfTransitionend(this.scrollbar, 150, () => {
this.scrollbar.addEventListener('transitionend', () => {
this.scrollbar.style.display = this.cursorDown && (this.isVertical ? this.sizeHeight : this.sizeWidth) ? 'block' : 'none';
});
}, 200);
Expand Down
100 changes: 100 additions & 0 deletions src/style/color-picker.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
@import './variables.less';

.@{namespace}-color-picker {
&__preview {
width: 20px;
height: 20px;
cursor: pointer;
border-radius: 6px;
}

&__content {
.setCssVar(color-picker-bg-color, #ffffff);

box-sizing: border-box;
background: .getCssVar(color-picker-bg-color) [];
border-radius: 6px;
box-shadow: 0 0 6px #b2b5b8;
width: 197px;
height: 186px;
padding: 8px;
}

&__selector {
width: 150px;
height: 150px;
position: absolute;
}

&__background {
width: 100%;
height: 100%;
background: linear-gradient(to top, #000 0%, rgba(0, 0, 0, 0) 100%),
linear-gradient(to right, #fff 0%, rgba(255, 255, 255, 0) 100%);
&-handle {
box-sizing: border-box;
position: absolute;
top: 0px;
left: 150px;
border-radius: 100%;
width: 10px;
height: 10px;
border: 1px solid #ffffff;
cursor: pointer;
transform: translate(-5px, -5px);
opacity: 0.85;
}
}

&__hue {
width: 12px;
height: 150px;
margin-left: 164px;
position: absolute;
opacity: 0.85;
background: linear-gradient(0deg, red 0, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, red);
&-handle {
box-sizing: border-box;
position: absolute;
width: 16px;
height: 10px;
transform: translate(-2px, -5px);
border: 2px solid #ffffff;
opacity: 0.85;
cursor: pointer;
}
}

&__alpha {
width: 150px;
height: 12px;
position: absolute;
margin-top: 158px;
background: linear-gradient(45deg, #ccc 25%, transparent 25%), linear-gradient(135deg, #ccc 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, #ccc 75%), linear-gradient(135deg, transparent 75%, #ccc 75%);
background-size: 12px 12px;
background-position:
0 0,
6px 0,
6px -6px,
0 6px;
&-bg {
position: relative;
height: 100%;
background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, #ffffff 100%);
}
&-handle {
box-sizing: border-box;
position: absolute;
opacity: 0.85;
cursor: pointer;
top: 0;
width: 10px;
height: 16px;
transform: translate(-5px, -2px);
border: 1px solid #ebeef5;
background-color: #ffffff;
box-shadow: 0 0 2px #0009;
}
}
}
13 changes: 13 additions & 0 deletions src/style/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -425,3 +425,16 @@
@import './select-box.less';
@import './tooltip.less';
@import './dialog.less';
@import './color-picker.less';

.@{namespace}-tooltip {
.@{namespace}-color-picker {
&__content {
.setCssVar(color-picker-bg-color, transparent);

width: 181px;
padding: 8px 0px;
box-shadow: none;
}
}
}
Loading

0 comments on commit be581c3

Please sign in to comment.