quill-table-up 3.1.2 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -8
- package/dist/index.css +1 -1
- package/dist/index.d.ts +168 -146
- package/dist/index.js +47 -47
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +52 -52
- package/dist/index.umd.js.map +1 -1
- package/package.json +22 -24
- package/src/__tests__/e2e/custom-creator.test.ts +44 -44
- package/src/__tests__/e2e/editor-page.ts +77 -77
- package/src/__tests__/e2e/table-align.test.ts +104 -104
- package/src/__tests__/e2e/table-blots.test.ts +169 -169
- package/src/__tests__/e2e/table-caption.test.ts +134 -134
- package/src/__tests__/e2e/table-clipboard.test.ts +20 -20
- package/src/__tests__/e2e/table-hack.test.ts +151 -151
- package/src/__tests__/e2e/table-keyboard-handler.test.ts +20 -4
- package/src/__tests__/e2e/table-menu.test.ts +172 -172
- package/src/__tests__/e2e/table-resize.test.ts +654 -9
- package/src/__tests__/e2e/table-scrollbar.test.ts +144 -144
- package/src/__tests__/e2e/table-selection.test.ts +563 -563
- package/src/__tests__/e2e/types.d.ts +8 -7
- package/src/__tests__/e2e/utils.ts +52 -52
- package/src/__tests__/unit/table-blots.test.ts +720 -720
- package/src/__tests__/unit/table-caption.test.ts +234 -234
- package/src/__tests__/unit/table-cell-merge.test.ts +713 -724
- package/src/__tests__/unit/table-clipboard.test.ts +2176 -2176
- package/src/__tests__/unit/table-hack.test.ts +1014 -1014
- package/src/__tests__/unit/table-insert.test.ts +915 -926
- package/src/__tests__/unit/table-redo-undo.test.ts +2429 -2429
- package/src/__tests__/unit/table-remove.test.ts +313 -343
- package/src/__tests__/unit/utils.test-d.ts +49 -49
- package/src/__tests__/unit/utils.test.ts +711 -711
- package/src/__tests__/unit/utils.ts +307 -307
- package/src/__tests__/unit/vitest.d.ts +14 -14
- package/src/formats/container-format.ts +107 -107
- package/src/formats/overrides/block-embed.ts +72 -72
- package/src/formats/overrides/block.ts +95 -95
- package/src/formats/overrides/index.ts +3 -3
- package/src/formats/overrides/scroll.ts +70 -70
- package/src/formats/table-body-format.ts +52 -52
- package/src/formats/table-caption-format.ts +116 -116
- package/src/formats/table-cell-format.ts +304 -304
- package/src/formats/table-cell-inner-format.ts +403 -398
- package/src/formats/table-colgroup-format.ts +136 -136
- package/src/formats/table-foot-format.ts +7 -7
- package/src/formats/table-head-format.ts +7 -7
- package/src/formats/table-main-format.ts +1 -1
- package/src/formats/table-row-format.ts +218 -210
- package/src/formats/utils.ts +6 -6
- package/src/index.ts +19 -19
- package/src/modules/index.ts +7 -7
- package/src/modules/table-align.ts +131 -131
- package/src/modules/table-clipboard/table-clipboard.ts +6 -8
- package/src/modules/table-dom-selector.ts +33 -33
- package/src/modules/table-menu/constants.ts +223 -223
- package/src/modules/table-menu/index.ts +4 -4
- package/src/modules/table-menu/table-menu-common.ts +330 -329
- package/src/modules/table-menu/table-menu-contextmenu.ts +111 -118
- package/src/modules/table-menu/table-menu-select.ts +96 -94
- package/src/modules/table-resize/index.ts +5 -5
- package/src/modules/table-resize/table-resize-box.ts +714 -363
- package/src/modules/table-resize/table-resize-common.ts +246 -382
- package/src/modules/table-resize/table-resize-drag.ts +241 -0
- package/src/modules/table-resize/table-resize-line.ts +244 -182
- package/src/modules/table-resize/table-resize-scale.ts +174 -173
- package/src/modules/table-resize/utils.ts +84 -3
- package/src/modules/table-scrollbar.ts +292 -292
- package/src/modules/table-selection.ts +613 -669
- package/src/style/button.less +45 -45
- package/src/style/color-picker.less +136 -136
- package/src/style/dialog.less +53 -53
- package/src/style/functions.less +9 -9
- package/src/style/index.less +120 -120
- package/src/style/input.less +64 -64
- package/src/style/select-box.less +52 -52
- package/src/style/table-creator.less +56 -56
- package/src/style/table-menu.less +125 -125
- package/src/style/table-resize-scale.less +31 -31
- package/src/style/table-resize.less +249 -202
- package/src/style/table-scrollbar.less +49 -49
- package/src/style/table-selection.less +23 -23
- package/src/style/tooltip.less +19 -19
- package/src/style/variables.less +1 -1
- package/src/svg/arrow-up-down.svg +11 -11
- package/src/svg/convert-cell.svg +7 -7
- package/src/table-up.ts +1363 -1360
- package/src/types.d.ts +4 -4
- package/src/utils/bem.ts +23 -23
- package/src/utils/blot-helper.ts +101 -105
- package/src/utils/color.ts +109 -109
- package/src/utils/components/button.ts +22 -22
- package/src/utils/components/color-picker.ts +236 -236
- package/src/utils/components/dialog.ts +83 -41
- package/src/utils/components/index.ts +6 -6
- package/src/utils/components/input.ts +74 -74
- package/src/utils/components/table/creator.ts +89 -89
- package/src/utils/components/table/index.ts +2 -2
- package/src/utils/components/table/select-box.ts +78 -78
- package/src/utils/components/tooltip.ts +179 -189
- package/src/utils/constants.ts +125 -124
- package/src/utils/drag-helper.ts +112 -0
- package/src/utils/index.ts +15 -14
- package/src/utils/is.ts +9 -9
- package/src/utils/position.ts +60 -60
- package/src/utils/resize-observer-helper.ts +47 -47
- package/src/utils/scroll.ts +145 -47
- package/src/utils/style-helper.ts +47 -47
- package/src/utils/transformer.ts +10 -10
- package/src/utils/transition-event-helper.ts +8 -8
- package/src/utils/types.ts +156 -157
- package/src/utils/utils.ts +12 -12
package/src/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare module '*.svg' {
|
|
2
|
-
const content: string;
|
|
3
|
-
export default content;
|
|
4
|
-
}
|
|
1
|
+
declare module '*.svg' {
|
|
2
|
+
const content: string;
|
|
3
|
+
export default content;
|
|
4
|
+
}
|
package/src/utils/bem.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { cssNamespace } from './constants';
|
|
2
|
-
|
|
3
|
-
export function createBEM(b: string, n: string = cssNamespace) {
|
|
4
|
-
const prefix = n ? `${n}-` : '';
|
|
5
|
-
return {
|
|
6
|
-
/** n-b */
|
|
7
|
-
b: () => `${prefix}${b}`,
|
|
8
|
-
/** n-b__e */
|
|
9
|
-
be: (e?: string) => e ? `${prefix}${b}__${e}` : '',
|
|
10
|
-
/** n-b--m */
|
|
11
|
-
bm: (m?: string) => m ? `${prefix}${b}--${m}` : '',
|
|
12
|
-
/** n-b__e--m */
|
|
13
|
-
bem: (e?: string, m?: string) => e && m ? `${prefix}${b}__${e}--${m}` : '',
|
|
14
|
-
/** n-s */
|
|
15
|
-
ns: (s?: string) => s ? `${prefix}${s}` : '',
|
|
16
|
-
/** n-b-s */
|
|
17
|
-
bs: (s?: string) => s ? `${prefix}${b}-${s}` : '',
|
|
18
|
-
/** --n-v */
|
|
19
|
-
cv: (v?: string) => v ? `--${prefix}${v}` : '',
|
|
20
|
-
/** is-n */
|
|
21
|
-
is: (n: string) => `is-${n}`,
|
|
22
|
-
};
|
|
23
|
-
}
|
|
1
|
+
import { cssNamespace } from './constants';
|
|
2
|
+
|
|
3
|
+
export function createBEM(b: string, n: string = cssNamespace) {
|
|
4
|
+
const prefix = n ? `${n}-` : '';
|
|
5
|
+
return {
|
|
6
|
+
/** n-b */
|
|
7
|
+
b: () => `${prefix}${b}`,
|
|
8
|
+
/** n-b__e */
|
|
9
|
+
be: (e?: string) => e ? `${prefix}${b}__${e}` : '',
|
|
10
|
+
/** n-b--m */
|
|
11
|
+
bm: (m?: string) => m ? `${prefix}${b}--${m}` : '',
|
|
12
|
+
/** n-b__e--m */
|
|
13
|
+
bem: (e?: string, m?: string) => e && m ? `${prefix}${b}__${e}--${m}` : '',
|
|
14
|
+
/** n-s */
|
|
15
|
+
ns: (s?: string) => s ? `${prefix}${s}` : '',
|
|
16
|
+
/** n-b-s */
|
|
17
|
+
bs: (s?: string) => s ? `${prefix}${b}-${s}` : '',
|
|
18
|
+
/** --n-v */
|
|
19
|
+
cv: (v?: string) => v ? `--${prefix}${v}` : '',
|
|
20
|
+
/** is-n */
|
|
21
|
+
is: (n: string) => `is-${n}`,
|
|
22
|
+
};
|
|
23
|
+
}
|
package/src/utils/blot-helper.ts
CHANGED
|
@@ -1,105 +1,101 @@
|
|
|
1
|
-
import type { Parchment as TypeParchment } from 'quill';
|
|
2
|
-
import type { TableBodyFormat, TableCellFormat, TableCellInnerFormat, TableColFormat, TableColgroupFormat, TableMainFormat, TableRowFormat, TableWrapperFormat } from '../formats';
|
|
3
|
-
import type { blotName } from './constants';
|
|
4
|
-
import type { Constructor } from './types';
|
|
5
|
-
|
|
6
|
-
interface ParentBlotReturnMap {
|
|
7
|
-
[blotName.tableWrapper]: TableWrapperFormat;
|
|
8
|
-
[blotName.tableMain]: TableMainFormat;
|
|
9
|
-
[blotName.tableCol]: TableColFormat;
|
|
10
|
-
[blotName.tableColgroup]: TableColgroupFormat;
|
|
11
|
-
[blotName.tableBody]: TableBodyFormat;
|
|
12
|
-
[blotName.tableRow]: TableRowFormat;
|
|
13
|
-
[blotName.tableCell]: TableCellFormat;
|
|
14
|
-
[blotName.tableCellInner]: TableCellInnerFormat;
|
|
15
|
-
}
|
|
16
|
-
type ParentBlotReturn = {
|
|
17
|
-
[key: string]: TypeParchment.Parent;
|
|
18
|
-
} & ParentBlotReturnMap;
|
|
19
|
-
|
|
20
|
-
export function findParentBlot<T extends TypeParchment.Parent, U extends string = string>(
|
|
21
|
-
blot: TypeParchment.Blot,
|
|
22
|
-
targetBlotName: U,
|
|
23
|
-
): U extends keyof ParentBlotReturn ? ParentBlotReturn[U] : T {
|
|
24
|
-
let target = blot.parent;
|
|
25
|
-
while (target && target.statics.blotName !== targetBlotName && target !== blot.scroll) {
|
|
26
|
-
target = target.parent;
|
|
27
|
-
}
|
|
28
|
-
if (target === blot.scroll) {
|
|
29
|
-
throw new Error(`${blot.statics.blotName} must be a child of ${targetBlotName}`);
|
|
30
|
-
}
|
|
31
|
-
return target as any;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function findParentBlots<T extends (keyof ParentBlotReturnMap | string)[]>(
|
|
35
|
-
blot: TypeParchment.Blot,
|
|
36
|
-
targetBlotNames: T,
|
|
37
|
-
): { [K in keyof T]: ParentBlotReturn[T[K]] } {
|
|
38
|
-
const resultBlots: TypeParchment.Parent[] = new Array(targetBlotNames.length);
|
|
39
|
-
const blotNameIndexMaps = new Map<string, number>(targetBlotNames.map((name, i) => [name, i]));
|
|
40
|
-
let target = blot.parent;
|
|
41
|
-
while (target && target !== blot.scroll) {
|
|
42
|
-
if (blotNameIndexMaps.size === 0) break;
|
|
43
|
-
if (blotNameIndexMaps.has(target.statics.blotName)) {
|
|
44
|
-
const index = blotNameIndexMaps.get(target.statics.blotName)!;
|
|
45
|
-
resultBlots[index] = target;
|
|
46
|
-
blotNameIndexMaps.delete(target.statics.blotName);
|
|
47
|
-
}
|
|
48
|
-
target = target.parent;
|
|
49
|
-
}
|
|
50
|
-
if (blotNameIndexMaps.size > 0) {
|
|
51
|
-
throw new Error(`${blot.statics.blotName} must be a child of ${Array.from(blotNameIndexMaps.keys()).join(', ')}`);
|
|
52
|
-
}
|
|
53
|
-
return resultBlots as any;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function findAllParentBlot(Blot: TypeParchment.Blot) {
|
|
57
|
-
const blots: Map<string, TypeParchment.Blot> = new Map();
|
|
58
|
-
let target = Blot;
|
|
59
|
-
while (target && target.statics.blotName !== 'scroll') {
|
|
60
|
-
blots.set(target.statics.blotName, target);
|
|
61
|
-
target = target.parent;
|
|
62
|
-
}
|
|
63
|
-
return blots;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function findChildBlot<T extends TypeParchment.BlotConstructor>(parent: TypeParchment.Parent, blot: T) {
|
|
67
|
-
const descendants: InstanceType<T>[] = [];
|
|
68
|
-
const next = parent.children.iterator();
|
|
69
|
-
let cur: TypeParchment.Blot | null = null;
|
|
70
|
-
while ((cur = next())) {
|
|
71
|
-
if (cur instanceof blot) {
|
|
72
|
-
descendants.push(cur as InstanceType<T>);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return descendants;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function mixinProps<T = any, U = any>(target: T, source: U, excludeReg?: RegExp) {
|
|
79
|
-
for (const prop of Object.getOwnPropertyNames(source)) {
|
|
80
|
-
if (excludeReg
|
|
81
|
-
Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop)!);
|
|
82
|
-
}
|
|
83
|
-
return target;
|
|
84
|
-
}
|
|
85
|
-
export function mixinClass<
|
|
86
|
-
T extends Constructor,
|
|
87
|
-
U extends Constructor[],
|
|
88
|
-
>(
|
|
89
|
-
base: T,
|
|
90
|
-
mixins: U,
|
|
91
|
-
): T & Omit<U[number], 'constructor' | keyof InstanceType<T>> {
|
|
92
|
-
const targetClass: any = class extends base {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
export function isSubclassOf(childClass: any, parentClass: any): boolean {
|
|
104
|
-
return childClass.prototype && childClass.prototype instanceof parentClass;
|
|
105
|
-
}
|
|
1
|
+
import type { Parchment as TypeParchment } from 'quill';
|
|
2
|
+
import type { TableBodyFormat, TableCellFormat, TableCellInnerFormat, TableColFormat, TableColgroupFormat, TableMainFormat, TableRowFormat, TableWrapperFormat } from '../formats';
|
|
3
|
+
import type { blotName } from './constants';
|
|
4
|
+
import type { Constructor } from './types';
|
|
5
|
+
|
|
6
|
+
interface ParentBlotReturnMap {
|
|
7
|
+
[blotName.tableWrapper]: TableWrapperFormat;
|
|
8
|
+
[blotName.tableMain]: TableMainFormat;
|
|
9
|
+
[blotName.tableCol]: TableColFormat;
|
|
10
|
+
[blotName.tableColgroup]: TableColgroupFormat;
|
|
11
|
+
[blotName.tableBody]: TableBodyFormat;
|
|
12
|
+
[blotName.tableRow]: TableRowFormat;
|
|
13
|
+
[blotName.tableCell]: TableCellFormat;
|
|
14
|
+
[blotName.tableCellInner]: TableCellInnerFormat;
|
|
15
|
+
}
|
|
16
|
+
type ParentBlotReturn = {
|
|
17
|
+
[key: string]: TypeParchment.Parent;
|
|
18
|
+
} & ParentBlotReturnMap;
|
|
19
|
+
|
|
20
|
+
export function findParentBlot<T extends TypeParchment.Parent, U extends string = string>(
|
|
21
|
+
blot: TypeParchment.Blot,
|
|
22
|
+
targetBlotName: U,
|
|
23
|
+
): U extends keyof ParentBlotReturn ? ParentBlotReturn[U] : T {
|
|
24
|
+
let target = blot.parent;
|
|
25
|
+
while (target && target.statics.blotName !== targetBlotName && target !== blot.scroll) {
|
|
26
|
+
target = target.parent;
|
|
27
|
+
}
|
|
28
|
+
if (target === blot.scroll) {
|
|
29
|
+
throw new Error(`${blot.statics.blotName} must be a child of ${targetBlotName}`);
|
|
30
|
+
}
|
|
31
|
+
return target as any;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function findParentBlots<T extends (keyof ParentBlotReturnMap | string)[]>(
|
|
35
|
+
blot: TypeParchment.Blot,
|
|
36
|
+
targetBlotNames: T,
|
|
37
|
+
): { [K in keyof T]: ParentBlotReturn[T[K]] } {
|
|
38
|
+
const resultBlots: TypeParchment.Parent[] = new Array(targetBlotNames.length);
|
|
39
|
+
const blotNameIndexMaps = new Map<string, number>(targetBlotNames.map((name, i) => [name, i]));
|
|
40
|
+
let target = blot.parent;
|
|
41
|
+
while (target && target !== blot.scroll) {
|
|
42
|
+
if (blotNameIndexMaps.size === 0) break;
|
|
43
|
+
if (blotNameIndexMaps.has(target.statics.blotName)) {
|
|
44
|
+
const index = blotNameIndexMaps.get(target.statics.blotName)!;
|
|
45
|
+
resultBlots[index] = target;
|
|
46
|
+
blotNameIndexMaps.delete(target.statics.blotName);
|
|
47
|
+
}
|
|
48
|
+
target = target.parent;
|
|
49
|
+
}
|
|
50
|
+
if (blotNameIndexMaps.size > 0) {
|
|
51
|
+
throw new Error(`${blot.statics.blotName} must be a child of ${Array.from(blotNameIndexMaps.keys()).join(', ')}`);
|
|
52
|
+
}
|
|
53
|
+
return resultBlots as any;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function findAllParentBlot(Blot: TypeParchment.Blot) {
|
|
57
|
+
const blots: Map<string, TypeParchment.Blot> = new Map();
|
|
58
|
+
let target = Blot;
|
|
59
|
+
while (target && target.statics.blotName !== 'scroll') {
|
|
60
|
+
blots.set(target.statics.blotName, target);
|
|
61
|
+
target = target.parent;
|
|
62
|
+
}
|
|
63
|
+
return blots;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function findChildBlot<T extends TypeParchment.BlotConstructor>(parent: TypeParchment.Parent, blot: T) {
|
|
67
|
+
const descendants: InstanceType<T>[] = [];
|
|
68
|
+
const next = parent.children.iterator();
|
|
69
|
+
let cur: TypeParchment.Blot | null = null;
|
|
70
|
+
while ((cur = next())) {
|
|
71
|
+
if (cur instanceof blot) {
|
|
72
|
+
descendants.push(cur as InstanceType<T>);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return descendants;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function mixinProps<T = any, U = any>(target: T, source: U, excludeReg?: RegExp) {
|
|
79
|
+
for (const prop of Object.getOwnPropertyNames(source)) {
|
|
80
|
+
if (excludeReg?.test(prop)) continue;
|
|
81
|
+
Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop)!);
|
|
82
|
+
}
|
|
83
|
+
return target;
|
|
84
|
+
}
|
|
85
|
+
export function mixinClass<
|
|
86
|
+
T extends Constructor,
|
|
87
|
+
U extends Constructor[],
|
|
88
|
+
>(
|
|
89
|
+
base: T,
|
|
90
|
+
mixins: U,
|
|
91
|
+
): T & Omit<U[number], 'constructor' | keyof InstanceType<T>> {
|
|
92
|
+
const targetClass: any = class extends base {};
|
|
93
|
+
for (const source of mixins) {
|
|
94
|
+
mixinProps(targetClass.prototype, source.prototype, /^constructor$/);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return targetClass;
|
|
98
|
+
}
|
|
99
|
+
export function isSubclassOf(childClass: any, parentClass: any): boolean {
|
|
100
|
+
return childClass.prototype && childClass.prototype instanceof parentClass;
|
|
101
|
+
}
|
package/src/utils/color.ts
CHANGED
|
@@ -1,109 +1,109 @@
|
|
|
1
|
-
export interface HSB {
|
|
2
|
-
h: number;
|
|
3
|
-
s: number;
|
|
4
|
-
b: number;
|
|
5
|
-
a: number;
|
|
6
|
-
}
|
|
7
|
-
export interface RGB {
|
|
8
|
-
r: number;
|
|
9
|
-
g: number;
|
|
10
|
-
b: number;
|
|
11
|
-
a: number;
|
|
12
|
-
}
|
|
13
|
-
function normalizeValue(value: number | string, max: number | string) {
|
|
14
|
-
value = Math.min(max as number, Math.max(0, Number.parseFloat(`${value}`)));
|
|
15
|
-
|
|
16
|
-
// Handle floating point rounding errors
|
|
17
|
-
if (Math.abs(value - (max as number)) < 0.000_001) {
|
|
18
|
-
return 1;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Convert into [0, 1] range if it isn't already
|
|
22
|
-
return (value % (max as number)) / Number.parseFloat(max as string);
|
|
23
|
-
}
|
|
24
|
-
export function validateHSB(hsb: HSB): HSB {
|
|
25
|
-
return {
|
|
26
|
-
h: Math.min(360, Math.max(0, hsb.h)),
|
|
27
|
-
s: Math.min(100, Math.max(0, hsb.s)),
|
|
28
|
-
b: Math.min(100, Math.max(0, hsb.b)),
|
|
29
|
-
a: Math.min(1, Math.max(0, hsb.a)),
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
export function HEXtoRGB(hex: string): RGB {
|
|
33
|
-
hex = hex.startsWith('#') ? hex.slice(1) : hex;
|
|
34
|
-
const r = Number.parseInt(hex.slice(0, 2), 16);
|
|
35
|
-
const g = Number.parseInt(hex.slice(2, 4), 16);
|
|
36
|
-
const b = Number.parseInt(hex.slice(4, 6), 16);
|
|
37
|
-
const a = Number((Number.parseInt(hex.slice(6, 8) || 'ff', 16) / 255).toFixed(2));
|
|
38
|
-
return { r, g, b, a };
|
|
39
|
-
}
|
|
40
|
-
export function RGBtoHSB(rgb: RGB): HSB {
|
|
41
|
-
let { r, g, b, a } = rgb;
|
|
42
|
-
r = normalizeValue(r, 255);
|
|
43
|
-
g = normalizeValue(g, 255);
|
|
44
|
-
b = normalizeValue(b, 255);
|
|
45
|
-
|
|
46
|
-
const max = Math.max(r, g, b);
|
|
47
|
-
const min = Math.min(r, g, b);
|
|
48
|
-
let h: number;
|
|
49
|
-
const v = max;
|
|
50
|
-
|
|
51
|
-
const d = max - min;
|
|
52
|
-
const s = max === 0 ? 0 : d / max;
|
|
53
|
-
|
|
54
|
-
if (max === min) {
|
|
55
|
-
h = 0; // achromatic
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
switch (max) {
|
|
59
|
-
case r: {
|
|
60
|
-
h = (g - b) / d + (g < b ? 6 : 0);
|
|
61
|
-
break;
|
|
62
|
-
}
|
|
63
|
-
case g: {
|
|
64
|
-
h = (b - r) / d + 2;
|
|
65
|
-
break;
|
|
66
|
-
}
|
|
67
|
-
case b: {
|
|
68
|
-
h = (r - g) / d + 4;
|
|
69
|
-
break;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
h! /= 6;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return { h: h! * 360, s: s * 100, b: v * 100, a };
|
|
76
|
-
}
|
|
77
|
-
export function HSBtoRGB(hsb: HSB): RGB {
|
|
78
|
-
let { h, s, b, a } = hsb;
|
|
79
|
-
h = normalizeValue(h, 360) * 6;
|
|
80
|
-
s = normalizeValue(s, 100);
|
|
81
|
-
b = normalizeValue(b, 100);
|
|
82
|
-
|
|
83
|
-
const i = Math.floor(h);
|
|
84
|
-
const f = h - i;
|
|
85
|
-
const p = b * (1 - s);
|
|
86
|
-
const q = b * (1 - f * s);
|
|
87
|
-
const t = b * (1 - (1 - f) * s);
|
|
88
|
-
const mod = i % 6;
|
|
89
|
-
const r = [b, q, p, p, t, b][mod];
|
|
90
|
-
const g = [t, b, b, q, p, p][mod];
|
|
91
|
-
const v = [p, p, t, b, b, q][mod];
|
|
92
|
-
|
|
93
|
-
return {
|
|
94
|
-
r: Math.round(r * 255),
|
|
95
|
-
g: Math.round(g * 255),
|
|
96
|
-
b: Math.round(v * 255),
|
|
97
|
-
a,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
export function RGBtoHEX(rgb: RGB): string {
|
|
101
|
-
const hex = [rgb.r.toString(16), rgb.g.toString(16), rgb.b.toString(16), Math.round(rgb.a * 255).toString(16)];
|
|
102
|
-
for (const key in hex) {
|
|
103
|
-
if (hex[key].length === 1) {
|
|
104
|
-
hex[key] = `0${hex[key]}`;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
return hex.join('');
|
|
108
|
-
}
|
|
109
|
-
export const HSBtoHEX = (hsb: HSB): string => RGBtoHEX(HSBtoRGB(hsb));
|
|
1
|
+
export interface HSB {
|
|
2
|
+
h: number;
|
|
3
|
+
s: number;
|
|
4
|
+
b: number;
|
|
5
|
+
a: number;
|
|
6
|
+
}
|
|
7
|
+
export interface RGB {
|
|
8
|
+
r: number;
|
|
9
|
+
g: number;
|
|
10
|
+
b: number;
|
|
11
|
+
a: number;
|
|
12
|
+
}
|
|
13
|
+
function normalizeValue(value: number | string, max: number | string) {
|
|
14
|
+
value = Math.min(max as number, Math.max(0, Number.parseFloat(`${value}`)));
|
|
15
|
+
|
|
16
|
+
// Handle floating point rounding errors
|
|
17
|
+
if (Math.abs(value - (max as number)) < 0.000_001) {
|
|
18
|
+
return 1;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Convert into [0, 1] range if it isn't already
|
|
22
|
+
return (value % (max as number)) / Number.parseFloat(max as string);
|
|
23
|
+
}
|
|
24
|
+
export function validateHSB(hsb: HSB): HSB {
|
|
25
|
+
return {
|
|
26
|
+
h: Math.min(360, Math.max(0, hsb.h)),
|
|
27
|
+
s: Math.min(100, Math.max(0, hsb.s)),
|
|
28
|
+
b: Math.min(100, Math.max(0, hsb.b)),
|
|
29
|
+
a: Math.min(1, Math.max(0, hsb.a)),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export function HEXtoRGB(hex: string): RGB {
|
|
33
|
+
hex = hex.startsWith('#') ? hex.slice(1) : hex;
|
|
34
|
+
const r = Number.parseInt(hex.slice(0, 2), 16);
|
|
35
|
+
const g = Number.parseInt(hex.slice(2, 4), 16);
|
|
36
|
+
const b = Number.parseInt(hex.slice(4, 6), 16);
|
|
37
|
+
const a = Number((Number.parseInt(hex.slice(6, 8) || 'ff', 16) / 255).toFixed(2));
|
|
38
|
+
return { r, g, b, a };
|
|
39
|
+
}
|
|
40
|
+
export function RGBtoHSB(rgb: RGB): HSB {
|
|
41
|
+
let { r, g, b, a } = rgb;
|
|
42
|
+
r = normalizeValue(r, 255);
|
|
43
|
+
g = normalizeValue(g, 255);
|
|
44
|
+
b = normalizeValue(b, 255);
|
|
45
|
+
|
|
46
|
+
const max = Math.max(r, g, b);
|
|
47
|
+
const min = Math.min(r, g, b);
|
|
48
|
+
let h: number;
|
|
49
|
+
const v = max;
|
|
50
|
+
|
|
51
|
+
const d = max - min;
|
|
52
|
+
const s = max === 0 ? 0 : d / max;
|
|
53
|
+
|
|
54
|
+
if (max === min) {
|
|
55
|
+
h = 0; // achromatic
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
switch (max) {
|
|
59
|
+
case r: {
|
|
60
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case g: {
|
|
64
|
+
h = (b - r) / d + 2;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
case b: {
|
|
68
|
+
h = (r - g) / d + 4;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
h! /= 6;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return { h: h! * 360, s: s * 100, b: v * 100, a };
|
|
76
|
+
}
|
|
77
|
+
export function HSBtoRGB(hsb: HSB): RGB {
|
|
78
|
+
let { h, s, b, a } = hsb;
|
|
79
|
+
h = normalizeValue(h, 360) * 6;
|
|
80
|
+
s = normalizeValue(s, 100);
|
|
81
|
+
b = normalizeValue(b, 100);
|
|
82
|
+
|
|
83
|
+
const i = Math.floor(h);
|
|
84
|
+
const f = h - i;
|
|
85
|
+
const p = b * (1 - s);
|
|
86
|
+
const q = b * (1 - f * s);
|
|
87
|
+
const t = b * (1 - (1 - f) * s);
|
|
88
|
+
const mod = i % 6;
|
|
89
|
+
const r = [b, q, p, p, t, b][mod];
|
|
90
|
+
const g = [t, b, b, q, p, p][mod];
|
|
91
|
+
const v = [p, p, t, b, b, q][mod];
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
r: Math.round(r * 255),
|
|
95
|
+
g: Math.round(g * 255),
|
|
96
|
+
b: Math.round(v * 255),
|
|
97
|
+
a,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
export function RGBtoHEX(rgb: RGB): string {
|
|
101
|
+
const hex = [rgb.r.toString(16), rgb.g.toString(16), rgb.b.toString(16), Math.round(rgb.a * 255).toString(16)];
|
|
102
|
+
for (const key in hex) {
|
|
103
|
+
if (hex[key].length === 1) {
|
|
104
|
+
hex[key] = `0${hex[key]}`;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return hex.join('');
|
|
108
|
+
}
|
|
109
|
+
export const HSBtoHEX = (hsb: HSB): string => RGBtoHEX(HSBtoRGB(hsb));
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import { createBEM } from '../bem';
|
|
2
|
-
import { isString } from '../is';
|
|
3
|
-
|
|
4
|
-
interface ButtonOptions {
|
|
5
|
-
type: 'confirm' | 'default';
|
|
6
|
-
content: HTMLElement | string;
|
|
7
|
-
}
|
|
8
|
-
export function createButton(options?: Partial<ButtonOptions>) {
|
|
9
|
-
const { type = 'default', content } = options || {};
|
|
10
|
-
const bem = createBEM('button');
|
|
11
|
-
const btn = document.createElement('button');
|
|
12
|
-
btn.classList.add(bem.b(), type);
|
|
13
|
-
if (content) {
|
|
14
|
-
if (isString(content)) {
|
|
15
|
-
btn.textContent = content;
|
|
16
|
-
}
|
|
17
|
-
else {
|
|
18
|
-
btn.appendChild(content);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return btn;
|
|
22
|
-
}
|
|
1
|
+
import { createBEM } from '../bem';
|
|
2
|
+
import { isString } from '../is';
|
|
3
|
+
|
|
4
|
+
interface ButtonOptions {
|
|
5
|
+
type: 'confirm' | 'default';
|
|
6
|
+
content: HTMLElement | string;
|
|
7
|
+
}
|
|
8
|
+
export function createButton(options?: Partial<ButtonOptions>) {
|
|
9
|
+
const { type = 'default', content } = options || {};
|
|
10
|
+
const bem = createBEM('button');
|
|
11
|
+
const btn = document.createElement('button');
|
|
12
|
+
btn.classList.add(bem.b(), type);
|
|
13
|
+
if (content) {
|
|
14
|
+
if (isString(content)) {
|
|
15
|
+
btn.textContent = content;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
btn.appendChild(content);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return btn;
|
|
22
|
+
}
|