@tekus/design-system 5.31.0 → 5.32.0
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/fesm2022/tekus-design-system-components-color-picker.mjs +1028 -0
- package/fesm2022/tekus-design-system-components-color-picker.mjs.map +1 -0
- package/fesm2022/tekus-design-system-components-date-picker.mjs +269 -204
- package/fesm2022/tekus-design-system-components-date-picker.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-icon.mjs +119 -7
- package/fesm2022/tekus-design-system-components-icon.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-table.mjs +38 -6
- package/fesm2022/tekus-design-system-components-table.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-time-picker.mjs +443 -0
- package/fesm2022/tekus-design-system-components-time-picker.mjs.map +1 -0
- package/fesm2022/tekus-design-system-utils-wcag-contrast.mjs +97 -0
- package/fesm2022/tekus-design-system-utils-wcag-contrast.mjs.map +1 -0
- package/package.json +13 -1
- package/types/tekus-design-system-components-color-picker.d.ts +356 -0
- package/types/tekus-design-system-components-date-picker.d.ts +191 -141
- package/types/tekus-design-system-components-icon.d.ts +10 -1
- package/types/tekus-design-system-components-table.d.ts +26 -1
- package/types/tekus-design-system-components-time-picker.d.ts +203 -0
- package/types/tekus-design-system-utils-wcag-contrast.d.ts +55 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure utilities implementing the official WCAG 2.x contrast formula
|
|
3
|
+
* (relative luminance + contrast ratio).
|
|
4
|
+
*
|
|
5
|
+
* Thresholds follow the normal-text criteria (conservative):
|
|
6
|
+
* `>= 7` AAA, `>= 4.5` AA, otherwise `fail`.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Parses a hex color (`#abc`, `abc`, `#aabbcc` or `aabbcc`) into RGB channels (0–255).
|
|
10
|
+
* Returns `null` when the value is not a valid hex color.
|
|
11
|
+
*/
|
|
12
|
+
function hexToRgb(hex) {
|
|
13
|
+
let clean = hex.replace('#', '');
|
|
14
|
+
if (/^[0-9a-fA-F]{3}$/.test(clean)) {
|
|
15
|
+
clean = clean[0] + clean[0] + clean[1] + clean[1] + clean[2] + clean[2];
|
|
16
|
+
}
|
|
17
|
+
if (!/^[0-9a-fA-F]{6}$/.test(clean)) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
r: Number.parseInt(clean.slice(0, 2), 16),
|
|
22
|
+
g: Number.parseInt(clean.slice(2, 4), 16),
|
|
23
|
+
b: Number.parseInt(clean.slice(4, 6), 16),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* WCAG relative luminance of a hex color (0 = black, 1 = white).
|
|
28
|
+
* Returns `NaN` for invalid hex values.
|
|
29
|
+
*/
|
|
30
|
+
function relativeLuminance(hex) {
|
|
31
|
+
const rgb = hexToRgb(hex);
|
|
32
|
+
if (!rgb) {
|
|
33
|
+
return Number.NaN;
|
|
34
|
+
}
|
|
35
|
+
const [r, g, b] = [rgb.r, rgb.g, rgb.b].map((c) => {
|
|
36
|
+
const s = c / 255;
|
|
37
|
+
return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
|
|
38
|
+
});
|
|
39
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Contrast ratio between two hex colors, rounded to 2 decimals.
|
|
43
|
+
* Range: 1 (identical) to 21 (black on white).
|
|
44
|
+
*/
|
|
45
|
+
function calcContrastRatio(bg, fg) {
|
|
46
|
+
const l1 = relativeLuminance(bg);
|
|
47
|
+
const l2 = relativeLuminance(fg);
|
|
48
|
+
const lighter = Math.max(l1, l2);
|
|
49
|
+
const darker = Math.min(l1, l2);
|
|
50
|
+
return Number.parseFloat(((lighter + 0.05) / (darker + 0.05)).toFixed(2));
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Maps a contrast ratio to its WCAG level for normal text:
|
|
54
|
+
* `>= 7` → AAA, `>= 4.5` → AA, otherwise `fail`.
|
|
55
|
+
*/
|
|
56
|
+
function resolveWcagLevel(ratio) {
|
|
57
|
+
if (ratio >= 7) {
|
|
58
|
+
return 'AAA';
|
|
59
|
+
}
|
|
60
|
+
if (ratio >= 4.5) {
|
|
61
|
+
return 'AA';
|
|
62
|
+
}
|
|
63
|
+
return 'fail';
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Convenience helper combining {@link calcContrastRatio} and {@link resolveWcagLevel}.
|
|
67
|
+
*/
|
|
68
|
+
function getContrastResult(bg, fg) {
|
|
69
|
+
const ratio = calcContrastRatio(bg, fg);
|
|
70
|
+
return { ratio, level: resolveWcagLevel(ratio) };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Whether a hex color is perceived as light, using the ITU-R BT.601
|
|
74
|
+
* perceived-luminance formula normalized to [0, 1] with a 0.5 threshold.
|
|
75
|
+
* Invalid hex values are treated as dark (`false`).
|
|
76
|
+
*/
|
|
77
|
+
function isLightColor(hex) {
|
|
78
|
+
const rgb = hexToRgb(hex);
|
|
79
|
+
if (!rgb) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
return (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255 > 0.5;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Ideal text color over the given background:
|
|
86
|
+
* black (`#000000`) on light backgrounds, white (`#ffffff`) on dark ones.
|
|
87
|
+
*/
|
|
88
|
+
function getContrastTextColor(background) {
|
|
89
|
+
return isLightColor(background) ? '#000000' : '#ffffff';
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Generated bundle index. Do not edit.
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
export { calcContrastRatio, getContrastResult, getContrastTextColor, hexToRgb, isLightColor, relativeLuminance, resolveWcagLevel };
|
|
97
|
+
//# sourceMappingURL=tekus-design-system-utils-wcag-contrast.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tekus-design-system-utils-wcag-contrast.mjs","sources":["../../../projects/design-system/utils/wcag-contrast/src/wcag-contrast.ts","../../../projects/design-system/utils/wcag-contrast/tekus-design-system-utils-wcag-contrast.ts"],"sourcesContent":["/**\n * Pure utilities implementing the official WCAG 2.x contrast formula\n * (relative luminance + contrast ratio).\n *\n * Thresholds follow the normal-text criteria (conservative):\n * `>= 7` AAA, `>= 4.5` AA, otherwise `fail`.\n */\n\nexport type WcagLevel = 'AAA' | 'AA' | 'fail';\n\nexport interface RgbColor {\n r: number;\n g: number;\n b: number;\n}\n\nexport interface ContrastResult {\n ratio: number;\n level: WcagLevel;\n}\n\n/**\n * Parses a hex color (`#abc`, `abc`, `#aabbcc` or `aabbcc`) into RGB channels (0–255).\n * Returns `null` when the value is not a valid hex color.\n */\nexport function hexToRgb(hex: string): RgbColor | null {\n let clean = hex.replace('#', '');\n if (/^[0-9a-fA-F]{3}$/.test(clean)) {\n clean = clean[0] + clean[0] + clean[1] + clean[1] + clean[2] + clean[2];\n }\n if (!/^[0-9a-fA-F]{6}$/.test(clean)) {\n return null;\n }\n return {\n r: Number.parseInt(clean.slice(0, 2), 16),\n g: Number.parseInt(clean.slice(2, 4), 16),\n b: Number.parseInt(clean.slice(4, 6), 16),\n };\n}\n\n/**\n * WCAG relative luminance of a hex color (0 = black, 1 = white).\n * Returns `NaN` for invalid hex values.\n */\nexport function relativeLuminance(hex: string): number {\n const rgb = hexToRgb(hex);\n if (!rgb) {\n return Number.NaN;\n }\n const [r, g, b] = [rgb.r, rgb.g, rgb.b].map((c) => {\n const s = c / 255;\n return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);\n });\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n\n/**\n * Contrast ratio between two hex colors, rounded to 2 decimals.\n * Range: 1 (identical) to 21 (black on white).\n */\nexport function calcContrastRatio(bg: string, fg: string): number {\n const l1 = relativeLuminance(bg);\n const l2 = relativeLuminance(fg);\n const lighter = Math.max(l1, l2);\n const darker = Math.min(l1, l2);\n return Number.parseFloat(((lighter + 0.05) / (darker + 0.05)).toFixed(2));\n}\n\n/**\n * Maps a contrast ratio to its WCAG level for normal text:\n * `>= 7` → AAA, `>= 4.5` → AA, otherwise `fail`.\n */\nexport function resolveWcagLevel(ratio: number): WcagLevel {\n if (ratio >= 7) {\n return 'AAA';\n }\n if (ratio >= 4.5) {\n return 'AA';\n }\n return 'fail';\n}\n\n/**\n * Convenience helper combining {@link calcContrastRatio} and {@link resolveWcagLevel}.\n */\nexport function getContrastResult(bg: string, fg: string): ContrastResult {\n const ratio = calcContrastRatio(bg, fg);\n return { ratio, level: resolveWcagLevel(ratio) };\n}\n\n/**\n * Whether a hex color is perceived as light, using the ITU-R BT.601\n * perceived-luminance formula normalized to [0, 1] with a 0.5 threshold.\n * Invalid hex values are treated as dark (`false`).\n */\nexport function isLightColor(hex: string): boolean {\n const rgb = hexToRgb(hex);\n if (!rgb) {\n return false;\n }\n return (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255 > 0.5;\n}\n\n/**\n * Ideal text color over the given background:\n * black (`#000000`) on light backgrounds, white (`#ffffff`) on dark ones.\n */\nexport function getContrastTextColor(background: string): string {\n return isLightColor(background) ? '#000000' : '#ffffff';\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"AAAA;;;;;;AAMG;AAeH;;;AAGG;AACG,SAAU,QAAQ,CAAC,GAAW,EAAA;IAClC,IAAI,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;AAChC,IAAA,IAAI,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AAClC,QAAA,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IACzE;IACA,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACnC,QAAA,OAAO,IAAI;IACb;IACA,OAAO;AACL,QAAA,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;AACzC,QAAA,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;AACzC,QAAA,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;KAC1C;AACH;AAEA;;;AAGG;AACG,SAAU,iBAAiB,CAAC,GAAW,EAAA;AAC3C,IAAA,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC;IACzB,IAAI,CAAC,GAAG,EAAE;QACR,OAAO,MAAM,CAAC,GAAG;IACnB;IACA,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAI;AAChD,QAAA,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG;QACjB,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,KAAK,EAAE,GAAG,CAAC;AACtE,IAAA,CAAC,CAAC;IACF,OAAO,MAAM,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC;AAC7C;AAEA;;;AAGG;AACG,SAAU,iBAAiB,CAAC,EAAU,EAAE,EAAU,EAAA;AACtD,IAAA,MAAM,EAAE,GAAG,iBAAiB,CAAC,EAAE,CAAC;AAChC,IAAA,MAAM,EAAE,GAAG,iBAAiB,CAAC,EAAE,CAAC;IAChC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC;IAChC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC;IAC/B,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,GAAG,IAAI,KAAK,MAAM,GAAG,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AAC3E;AAEA;;;AAGG;AACG,SAAU,gBAAgB,CAAC,KAAa,EAAA;AAC5C,IAAA,IAAI,KAAK,IAAI,CAAC,EAAE;AACd,QAAA,OAAO,KAAK;IACd;AACA,IAAA,IAAI,KAAK,IAAI,GAAG,EAAE;AAChB,QAAA,OAAO,IAAI;IACb;AACA,IAAA,OAAO,MAAM;AACf;AAEA;;AAEG;AACG,SAAU,iBAAiB,CAAC,EAAU,EAAE,EAAU,EAAA;IACtD,MAAM,KAAK,GAAG,iBAAiB,CAAC,EAAE,EAAE,EAAE,CAAC;IACvC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,CAAC,KAAK,CAAC,EAAE;AAClD;AAEA;;;;AAIG;AACG,SAAU,YAAY,CAAC,GAAW,EAAA;AACtC,IAAA,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC;IACzB,IAAI,CAAC,GAAG,EAAE;AACR,QAAA,OAAO,KAAK;IACd;IACA,OAAO,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,GAAG,GAAG,CAAC,CAAC,IAAI,GAAG,GAAG,GAAG;AACpE;AAEA;;;AAGG;AACG,SAAU,oBAAoB,CAAC,UAAkB,EAAA;AACrD,IAAA,OAAO,YAAY,CAAC,UAAU,CAAC,GAAG,SAAS,GAAG,SAAS;AACzD;;AC7GA;;AAEG;;;;"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tekus/design-system",
|
|
3
3
|
"description": "Tekus design system library",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.32.0",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"peerDependencies": {
|
|
7
7
|
"@angular/core": "^21.0.0",
|
|
@@ -72,6 +72,10 @@
|
|
|
72
72
|
"types": "./types/tekus-design-system-components-checkbox.d.ts",
|
|
73
73
|
"default": "./fesm2022/tekus-design-system-components-checkbox.mjs"
|
|
74
74
|
},
|
|
75
|
+
"./components/color-picker": {
|
|
76
|
+
"types": "./types/tekus-design-system-components-color-picker.d.ts",
|
|
77
|
+
"default": "./fesm2022/tekus-design-system-components-color-picker.mjs"
|
|
78
|
+
},
|
|
75
79
|
"./components/date-picker": {
|
|
76
80
|
"types": "./types/tekus-design-system-components-date-picker.d.ts",
|
|
77
81
|
"default": "./fesm2022/tekus-design-system-components-date-picker.mjs"
|
|
@@ -172,6 +176,10 @@
|
|
|
172
176
|
"types": "./types/tekus-design-system-components-time-ago.d.ts",
|
|
173
177
|
"default": "./fesm2022/tekus-design-system-components-time-ago.mjs"
|
|
174
178
|
},
|
|
179
|
+
"./components/time-picker": {
|
|
180
|
+
"types": "./types/tekus-design-system-components-time-picker.d.ts",
|
|
181
|
+
"default": "./fesm2022/tekus-design-system-components-time-picker.mjs"
|
|
182
|
+
},
|
|
175
183
|
"./components/toast": {
|
|
176
184
|
"types": "./types/tekus-design-system-components-toast.d.ts",
|
|
177
185
|
"default": "./fesm2022/tekus-design-system-components-toast.mjs"
|
|
@@ -207,6 +215,10 @@
|
|
|
207
215
|
"./utils/sanitizer-utils": {
|
|
208
216
|
"types": "./types/tekus-design-system-utils-sanitizer-utils.d.ts",
|
|
209
217
|
"default": "./fesm2022/tekus-design-system-utils-sanitizer-utils.mjs"
|
|
218
|
+
},
|
|
219
|
+
"./utils/wcag-contrast": {
|
|
220
|
+
"types": "./types/tekus-design-system-utils-wcag-contrast.d.ts",
|
|
221
|
+
"default": "./fesm2022/tekus-design-system-utils-wcag-contrast.mjs"
|
|
210
222
|
}
|
|
211
223
|
},
|
|
212
224
|
"module": "fesm2022/tekus-design-system.mjs",
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { ControlValueAccessor, NgControl, FormControl } from '@angular/forms';
|
|
3
|
+
import { Popover } from 'primeng/popover';
|
|
4
|
+
import { ContrastResult } from '@tekus/design-system/utils/wcag-contrast';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Trigger appearance of `tk-color-picker`.
|
|
8
|
+
* - `input`: swatch + editable HEX value + chevron.
|
|
9
|
+
* - `swatch`: compact swatch + chevron (no HEX shown).
|
|
10
|
+
*/
|
|
11
|
+
type ColorPickerVariant = 'input' | 'swatch';
|
|
12
|
+
/**
|
|
13
|
+
* Reason the picker popover was closed.
|
|
14
|
+
* - `accept`: the selection was confirmed.
|
|
15
|
+
*/
|
|
16
|
+
type ColorPickerCloseReason = 'accept';
|
|
17
|
+
/**
|
|
18
|
+
* Enables or disables each section of the picker popover.
|
|
19
|
+
* Every flag defaults to `true`; disabled sections are not rendered.
|
|
20
|
+
* The contrast section additionally requires a `contrastColor` to be provided.
|
|
21
|
+
*/
|
|
22
|
+
interface ColorPickerSections {
|
|
23
|
+
/** Predefined color palette grid. */
|
|
24
|
+
swatches?: boolean;
|
|
25
|
+
/** User-saved colors grid with the "+" add button. */
|
|
26
|
+
customColors?: boolean;
|
|
27
|
+
/** Saturation/brightness selection canvas. */
|
|
28
|
+
spectrum?: boolean;
|
|
29
|
+
/** Hue slider bar. */
|
|
30
|
+
hue?: boolean;
|
|
31
|
+
/** Color preview + editable HEX field. */
|
|
32
|
+
hex?: boolean;
|
|
33
|
+
/** EyeDropper button (only shown when the browser supports the EyeDropper API). */
|
|
34
|
+
eyedropper?: boolean;
|
|
35
|
+
/** WCAG contrast preview (requires `contrastColor`). */
|
|
36
|
+
contrast?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* UI texts of the picker. All values have English defaults so consumers
|
|
40
|
+
* can localize them with their own i18n solution.
|
|
41
|
+
*/
|
|
42
|
+
interface ColorPickerTexts {
|
|
43
|
+
swatchesLabel?: string;
|
|
44
|
+
customColorsLabel?: string;
|
|
45
|
+
hexLabel?: string;
|
|
46
|
+
contrastLabel?: string;
|
|
47
|
+
contrastSampleText?: string;
|
|
48
|
+
contrastSampleLabel?: string;
|
|
49
|
+
contrastLowLabel?: string;
|
|
50
|
+
invalidHexError?: string;
|
|
51
|
+
requiredError?: string;
|
|
52
|
+
eyedropperLabel?: string;
|
|
53
|
+
addCustomColorLabel?: string;
|
|
54
|
+
removeCustomColorLabel?: string;
|
|
55
|
+
openPickerLabel?: string;
|
|
56
|
+
spectrumLabel?: string;
|
|
57
|
+
hueLabel?: string;
|
|
58
|
+
dialogLabel?: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @component ColorPickerComponent
|
|
63
|
+
* @description
|
|
64
|
+
* Configurable color picker of the Tekus Design System. Renders a trigger
|
|
65
|
+
* (`input` variant with editable HEX, or compact `swatch` variant) that opens
|
|
66
|
+
* a PrimeNG `p-popover` composed of independently toggleable sections:
|
|
67
|
+
* predefined swatches, custom colors, saturation/brightness spectrum, hue bar,
|
|
68
|
+
* HEX field with EyeDropper support, WCAG contrast preview and a
|
|
69
|
+
* Cancel/Accept action bar with temporary selection state.
|
|
70
|
+
* Implements `ControlValueAccessor` for Reactive Forms integration.
|
|
71
|
+
*
|
|
72
|
+
* @usage
|
|
73
|
+
* ```html
|
|
74
|
+
* <tk-color-picker
|
|
75
|
+
* label="Color"
|
|
76
|
+
* [(value)]="color"
|
|
77
|
+
* [contrastColor]="'#ffffff'"
|
|
78
|
+
* (colorChange)="onColor($event)">
|
|
79
|
+
* </tk-color-picker>
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
declare class ColorPickerComponent implements ControlValueAccessor {
|
|
83
|
+
readonly ngControl: NgControl | null;
|
|
84
|
+
private readonly destroyRef;
|
|
85
|
+
private readonly el;
|
|
86
|
+
private readonly init;
|
|
87
|
+
/**
|
|
88
|
+
* @property {ColorPickerVariant} variant
|
|
89
|
+
* @description
|
|
90
|
+
* Trigger appearance: `input` shows swatch + editable HEX + chevron,
|
|
91
|
+
* `swatch` shows only swatch + chevron.
|
|
92
|
+
* @default `'input'`
|
|
93
|
+
*/
|
|
94
|
+
variant: _angular_core.InputSignal<ColorPickerVariant>;
|
|
95
|
+
/**
|
|
96
|
+
* @property {string} label
|
|
97
|
+
* @description
|
|
98
|
+
* Label displayed above the trigger.
|
|
99
|
+
* @default `''`
|
|
100
|
+
*/
|
|
101
|
+
label: _angular_core.InputSignal<string>;
|
|
102
|
+
/**
|
|
103
|
+
* @property {string} hint
|
|
104
|
+
* @description
|
|
105
|
+
* Hint text displayed below the trigger (hidden while an error is shown).
|
|
106
|
+
* @default `''`
|
|
107
|
+
*/
|
|
108
|
+
hint: _angular_core.InputSignal<string>;
|
|
109
|
+
/**
|
|
110
|
+
* @property {boolean} disabled
|
|
111
|
+
* @description
|
|
112
|
+
* Disables the trigger and the popover. Also controlled by Reactive Forms
|
|
113
|
+
* via `setDisabledState`.
|
|
114
|
+
* @default `false`
|
|
115
|
+
*/
|
|
116
|
+
disabled: _angular_core.InputSignal<boolean>;
|
|
117
|
+
/**
|
|
118
|
+
* @property {boolean} required
|
|
119
|
+
* @description
|
|
120
|
+
* When `true`, an empty HEX field shows the required error on blur.
|
|
121
|
+
* @default `false`
|
|
122
|
+
*/
|
|
123
|
+
required: _angular_core.InputSignal<boolean>;
|
|
124
|
+
/**
|
|
125
|
+
* @property {ColorPickerSections} sections
|
|
126
|
+
* @description
|
|
127
|
+
* Enables/disables each popover section. Missing flags default to `true`.
|
|
128
|
+
* Disabling `actionBar` switches the picker to live mode (every valid
|
|
129
|
+
* change is emitted immediately).
|
|
130
|
+
* @default `{}` (all sections enabled)
|
|
131
|
+
*/
|
|
132
|
+
sections: _angular_core.InputSignal<ColorPickerSections>;
|
|
133
|
+
/**
|
|
134
|
+
* @property {string[]} presetColors
|
|
135
|
+
* @description
|
|
136
|
+
* Colors of the predefined palette section.
|
|
137
|
+
* @default Design System base palette
|
|
138
|
+
*/
|
|
139
|
+
presetColors: _angular_core.InputSignal<string[]>;
|
|
140
|
+
/**
|
|
141
|
+
* @property {string | null} contrastColor
|
|
142
|
+
* @description
|
|
143
|
+
* Optional override of the text color used for the WCAG contrast pair.
|
|
144
|
+
* When `null` (default) the text color is resolved automatically from the
|
|
145
|
+
* picked background luminance (ITU-R BT.601): black over light colors,
|
|
146
|
+
* white over dark ones.
|
|
147
|
+
* @default `null`
|
|
148
|
+
*/
|
|
149
|
+
contrastColor: _angular_core.InputSignal<string | null>;
|
|
150
|
+
/**
|
|
151
|
+
* @property {number} maxCustomColors
|
|
152
|
+
* @description
|
|
153
|
+
* Maximum number of custom color slots. Once the list is at capacity, the
|
|
154
|
+
* oldest slot is replaced using a circular buffer — the "+" button stays
|
|
155
|
+
* visible at all times.
|
|
156
|
+
* @default `18`
|
|
157
|
+
*/
|
|
158
|
+
maxCustomColors: _angular_core.InputSignal<number>;
|
|
159
|
+
/**
|
|
160
|
+
* @property {'top' | 'bottom'} placement
|
|
161
|
+
* @description
|
|
162
|
+
* Preferred position of the popover relative to the trigger.
|
|
163
|
+
* @default `'bottom'`
|
|
164
|
+
*/
|
|
165
|
+
placement: _angular_core.InputSignal<"top" | "bottom">;
|
|
166
|
+
/**
|
|
167
|
+
* @property {string} errorMessage
|
|
168
|
+
* @description
|
|
169
|
+
* External error message that overrides the internal validation messages.
|
|
170
|
+
* @default `''`
|
|
171
|
+
*/
|
|
172
|
+
errorMessage: _angular_core.InputSignal<string>;
|
|
173
|
+
/**
|
|
174
|
+
* @property {ColorPickerTexts} texts
|
|
175
|
+
* @description
|
|
176
|
+
* UI texts (section labels, buttons, errors). Defaults are in English so
|
|
177
|
+
* consumers can localize with their own i18n solution.
|
|
178
|
+
* @default `{}` (English defaults)
|
|
179
|
+
*/
|
|
180
|
+
texts: _angular_core.InputSignal<ColorPickerTexts>;
|
|
181
|
+
/**
|
|
182
|
+
* @property {ModelSignal<string>} value
|
|
183
|
+
* @description
|
|
184
|
+
* Confirmed color as a normalized lowercase 6-digit hex with `#`.
|
|
185
|
+
* Two-way bindable.
|
|
186
|
+
* @default `''`
|
|
187
|
+
*/
|
|
188
|
+
value: _angular_core.ModelSignal<string>;
|
|
189
|
+
/**
|
|
190
|
+
* @property {ModelSignal<string[]>} customColors
|
|
191
|
+
* @description
|
|
192
|
+
* User-saved custom colors. Two-way bindable so the consumer decides
|
|
193
|
+
* where to persist them.
|
|
194
|
+
* @default `[]`
|
|
195
|
+
*/
|
|
196
|
+
customColors: _angular_core.ModelSignal<string[]>;
|
|
197
|
+
/**
|
|
198
|
+
* @event colorChange
|
|
199
|
+
* @description
|
|
200
|
+
* Emits the confirmed background hex color: on Accept (action bar mode) or
|
|
201
|
+
* on every valid change (live mode / trigger HEX edit while closed). Never
|
|
202
|
+
* emits invalid values, on hydration, or while disabled.
|
|
203
|
+
*/
|
|
204
|
+
colorChange: _angular_core.OutputEmitterRef<string>;
|
|
205
|
+
/**
|
|
206
|
+
* @event textColorChange
|
|
207
|
+
* @description
|
|
208
|
+
* Emits together with `colorChange`: the ideal text color over the
|
|
209
|
+
* confirmed background (`#000000` on light colors, `#ffffff` on dark ones,
|
|
210
|
+
* or the `contrastColor` override when provided).
|
|
211
|
+
*/
|
|
212
|
+
textColorChange: _angular_core.OutputEmitterRef<string>;
|
|
213
|
+
/**
|
|
214
|
+
* @event validChange
|
|
215
|
+
* @description
|
|
216
|
+
* Emits only when the validity of the HEX value changes.
|
|
217
|
+
*/
|
|
218
|
+
validChange: _angular_core.OutputEmitterRef<boolean>;
|
|
219
|
+
/**
|
|
220
|
+
* @event opened
|
|
221
|
+
* @description
|
|
222
|
+
* Emits when the picker popover opens.
|
|
223
|
+
*/
|
|
224
|
+
opened: _angular_core.OutputEmitterRef<void>;
|
|
225
|
+
/**
|
|
226
|
+
* @event closed
|
|
227
|
+
* @description
|
|
228
|
+
* Emits when the popover closes, with the close reason
|
|
229
|
+
* (`accept` confirmed, `cancel` discarded/restored).
|
|
230
|
+
*/
|
|
231
|
+
closed: _angular_core.OutputEmitterRef<"accept">;
|
|
232
|
+
popover: _angular_core.Signal<Popover | undefined>;
|
|
233
|
+
private swatchBtnRef;
|
|
234
|
+
private inputTriggerRef;
|
|
235
|
+
private panelHexInput;
|
|
236
|
+
/**
|
|
237
|
+
* Internal FormControl handed to the `tk-input-text` trigger so the
|
|
238
|
+
* disabled state propagates through the Design System input.
|
|
239
|
+
*/
|
|
240
|
+
protected readonly triggerControl: FormControl<string | null>;
|
|
241
|
+
protected readonly isOpen: _angular_core.WritableSignal<boolean>;
|
|
242
|
+
protected readonly hue: _angular_core.WritableSignal<number>;
|
|
243
|
+
protected readonly saturation: _angular_core.WritableSignal<number>;
|
|
244
|
+
protected readonly brightness: _angular_core.WritableSignal<number>;
|
|
245
|
+
protected readonly draftHex: _angular_core.WritableSignal<string>;
|
|
246
|
+
protected readonly displayHexNoHash: _angular_core.WritableSignal<string>;
|
|
247
|
+
protected readonly isValid: _angular_core.WritableSignal<boolean>;
|
|
248
|
+
protected readonly errorType: _angular_core.WritableSignal<"invalid" | "required">;
|
|
249
|
+
private readonly cvaDisabled;
|
|
250
|
+
protected readonly isDisabled: _angular_core.Signal<boolean>;
|
|
251
|
+
protected readonly resolvedSections: _angular_core.Signal<Required<ColorPickerSections>>;
|
|
252
|
+
protected readonly t: _angular_core.Signal<Required<ColorPickerTexts>>;
|
|
253
|
+
/** Valid draft hex to paint swatches, or null → neutral fallback via CSS. */
|
|
254
|
+
protected readonly swatchColor: _angular_core.Signal<string | null>;
|
|
255
|
+
/**
|
|
256
|
+
* Text color of the contrast pair: the `contrastColor` override when valid,
|
|
257
|
+
* otherwise resolved automatically from the draft background luminance.
|
|
258
|
+
*/
|
|
259
|
+
protected readonly contrastTextColor: _angular_core.Signal<string>;
|
|
260
|
+
protected readonly contrastResult: _angular_core.Signal<ContrastResult | null>;
|
|
261
|
+
protected readonly showContrast: _angular_core.Signal<boolean>;
|
|
262
|
+
protected readonly eyeDropperSupported: boolean;
|
|
263
|
+
protected readonly showEyedropper: _angular_core.Signal<boolean>;
|
|
264
|
+
protected readonly canAddCustom: _angular_core.Signal<boolean>;
|
|
265
|
+
protected readonly errorText: _angular_core.Signal<string>;
|
|
266
|
+
protected readonly fieldId: string;
|
|
267
|
+
protected readonly panelFieldId: string;
|
|
268
|
+
protected readonly errorId: string;
|
|
269
|
+
private static instanceCount;
|
|
270
|
+
private originalValue;
|
|
271
|
+
private readonly customColorWritePtr;
|
|
272
|
+
private readonly hexInput$;
|
|
273
|
+
onChange: (value: string) => void;
|
|
274
|
+
onTouched: () => void;
|
|
275
|
+
constructor();
|
|
276
|
+
/**
|
|
277
|
+
* @method writeValue
|
|
278
|
+
* @description Hydrates the picker from the form model without emitting.
|
|
279
|
+
*/
|
|
280
|
+
writeValue(value: string): void;
|
|
281
|
+
/**
|
|
282
|
+
* @method registerOnChange
|
|
283
|
+
* @description Registers the Reactive Forms change callback.
|
|
284
|
+
*/
|
|
285
|
+
registerOnChange(fn: (value: string) => void): void;
|
|
286
|
+
/**
|
|
287
|
+
* @method registerOnTouched
|
|
288
|
+
* @description Registers the Reactive Forms touched callback.
|
|
289
|
+
*/
|
|
290
|
+
registerOnTouched(fn: () => void): void;
|
|
291
|
+
/**
|
|
292
|
+
* @method setDisabledState
|
|
293
|
+
* @description Syncs the disabled state from Reactive Forms.
|
|
294
|
+
*/
|
|
295
|
+
setDisabledState(isDisabled: boolean): void;
|
|
296
|
+
protected onTriggerClick(event: Event): void;
|
|
297
|
+
/** Returns the precise anchor element for popover positioning.
|
|
298
|
+
* For the input variant we target the `p-floatlabel` child instead of the
|
|
299
|
+
* full `tk-input-text` host. The host includes a bottom section with
|
|
300
|
+
* `min-height: 1.25rem + margin-top: 0.25rem` that is invisible when empty
|
|
301
|
+
* but would push the panel ~1.5rem below the visible input field.
|
|
302
|
+
*
|
|
303
|
+
* Coupling note: `p-floatlabel` is PrimeNG's float-label host element selector.
|
|
304
|
+
* If PrimeNG renames it in a future major, the `?? host` fallback keeps
|
|
305
|
+
* positioning functional (panel opens ~1.5rem lower than ideal). */
|
|
306
|
+
private getAnchorEl;
|
|
307
|
+
protected onPopoverShow(): void;
|
|
308
|
+
private fixPanelPosition;
|
|
309
|
+
protected onPopoverHide(): void;
|
|
310
|
+
protected onPanelEnter(event: Event): void;
|
|
311
|
+
private confirmAndClose;
|
|
312
|
+
protected onSpectrumChange(change: {
|
|
313
|
+
saturation: number;
|
|
314
|
+
brightness: number;
|
|
315
|
+
}): void;
|
|
316
|
+
protected onHueChange(event: Event): void;
|
|
317
|
+
protected onSwatchPick(color: string): void;
|
|
318
|
+
protected addCustomColor(): void;
|
|
319
|
+
protected isCustomColorSelected(): boolean;
|
|
320
|
+
protected removeCustomColor(): void;
|
|
321
|
+
protected openEyeDropper(): void;
|
|
322
|
+
protected onHexInput(clean: string): void;
|
|
323
|
+
/**
|
|
324
|
+
* Sanitizes typing inside a `tk-input-text` hex field (trigger or popover):
|
|
325
|
+
* strips non-hex characters at the DOM level (keeping the caret behavior of
|
|
326
|
+
* the native input) and feeds the shared validation pipeline.
|
|
327
|
+
*/
|
|
328
|
+
protected onHexNativeInput(event: Event): void;
|
|
329
|
+
/** Blocks non-hex keypresses and enforces 6-char max before char enters the DOM. Enter confirms selection. */
|
|
330
|
+
protected onHexKeydown(event: KeyboardEvent): void;
|
|
331
|
+
/** Strips non-hex chars from pasted text before it reaches the input model. */
|
|
332
|
+
protected onHexPaste(event: ClipboardEvent): void;
|
|
333
|
+
protected onHexBlur(): void;
|
|
334
|
+
private processHexInput;
|
|
335
|
+
private parseHex;
|
|
336
|
+
private applyValidHex;
|
|
337
|
+
private applyInvalidHex;
|
|
338
|
+
private setValid;
|
|
339
|
+
private syncFromValue;
|
|
340
|
+
private setFromHex;
|
|
341
|
+
private applyHsv;
|
|
342
|
+
/**
|
|
343
|
+
* Commits the draft color immediately (live mode).
|
|
344
|
+
*/
|
|
345
|
+
private maybeCommit;
|
|
346
|
+
private commitDraft;
|
|
347
|
+
private normalizeHex;
|
|
348
|
+
private isValidHex;
|
|
349
|
+
private hexToHsv;
|
|
350
|
+
private hsvToHex;
|
|
351
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ColorPickerComponent, never>;
|
|
352
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ColorPickerComponent, "tk-color-picker", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "sections": { "alias": "sections"; "required": false; "isSignal": true; }; "presetColors": { "alias": "presetColors"; "required": false; "isSignal": true; }; "contrastColor": { "alias": "contrastColor"; "required": false; "isSignal": true; }; "maxCustomColors": { "alias": "maxCustomColors"; "required": false; "isSignal": true; }; "placement": { "alias": "placement"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "texts": { "alias": "texts"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "customColors": { "alias": "customColors"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "customColors": "customColorsChange"; "colorChange": "colorChange"; "textColorChange": "textColorChange"; "validChange": "validChange"; "opened": "opened"; "closed": "closed"; }, never, never, true, never>;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export { ColorPickerComponent };
|
|
356
|
+
export type { ColorPickerCloseReason, ColorPickerSections, ColorPickerTexts, ColorPickerVariant };
|