@krollins/blueprint 0.1.11 → 0.1.13
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/dist/components/accordion.js +393 -0
- package/dist/components/accordion.js.map +1 -0
- package/dist/components/alert.js +213 -0
- package/dist/components/alert.js.map +1 -0
- package/dist/components/avatar.js +237 -0
- package/dist/components/avatar.js.map +1 -0
- package/dist/components/badge.js +144 -0
- package/dist/components/badge.js.map +1 -0
- package/dist/components/breadcrumb.js +481 -0
- package/dist/components/breadcrumb.js.map +1 -0
- package/dist/components/button.js +192 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/card.js +223 -0
- package/dist/components/card.js.map +1 -0
- package/dist/components/checkbox.js +337 -0
- package/dist/components/checkbox.js.map +1 -0
- package/dist/components/color-picker.js +1660 -0
- package/dist/components/color-picker.js.map +1 -0
- package/dist/components/combobox.js +595 -0
- package/dist/components/combobox.js.map +1 -0
- package/dist/components/date-picker.js +726 -0
- package/dist/components/date-picker.js.map +1 -0
- package/dist/components/divider.js +214 -0
- package/dist/components/divider.js.map +1 -0
- package/dist/components/drawer.js +568 -0
- package/dist/components/drawer.js.map +1 -0
- package/dist/components/dropdown.js +377 -0
- package/dist/components/dropdown.js.map +1 -0
- package/dist/components/file-upload.js +669 -0
- package/dist/components/file-upload.js.map +1 -0
- package/dist/components/heading.js +161 -0
- package/dist/components/heading.js.map +1 -0
- package/dist/components/icon.js +599 -0
- package/dist/components/icon.js.map +1 -0
- package/dist/components/input.js +363 -0
- package/dist/components/input.js.map +1 -0
- package/dist/components/link.js +178 -0
- package/dist/components/link.js.map +1 -0
- package/dist/components/menu.js +331 -0
- package/dist/components/menu.js.map +1 -0
- package/dist/components/modal.js +317 -0
- package/dist/components/modal.js.map +1 -0
- package/dist/components/multi-select.js +642 -0
- package/dist/components/multi-select.js.map +1 -0
- package/dist/components/notification.js +429 -0
- package/dist/components/notification.js.map +1 -0
- package/dist/components/number-input.js +556 -0
- package/dist/components/number-input.js.map +1 -0
- package/dist/components/pagination.js +320 -0
- package/dist/components/pagination.js.map +1 -0
- package/dist/components/popover.js +597 -0
- package/dist/components/popover.js.map +1 -0
- package/dist/components/progress.js +219 -0
- package/dist/components/progress.js.map +1 -0
- package/dist/components/radio.js +321 -0
- package/dist/components/radio.js.map +1 -0
- package/dist/components/select.js +498 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/skeleton.js +240 -0
- package/dist/components/skeleton.js.map +1 -0
- package/dist/components/slider.js +9 -0
- package/dist/components/slider.js.map +1 -0
- package/dist/components/spinner.js +133 -0
- package/dist/components/spinner.js.map +1 -0
- package/dist/components/stepper.js +812 -0
- package/dist/components/stepper.js.map +1 -0
- package/dist/components/switch.js +380 -0
- package/dist/components/switch.js.map +1 -0
- package/dist/components/table.js +642 -0
- package/dist/components/table.js.map +1 -0
- package/dist/components/tabs.js +547 -0
- package/dist/components/tabs.js.map +1 -0
- package/dist/components/tag.js +291 -0
- package/dist/components/tag.js.map +1 -0
- package/dist/components/text.js +278 -0
- package/dist/components/text.js.map +1 -0
- package/dist/components/textarea.js +380 -0
- package/dist/components/textarea.js.map +1 -0
- package/dist/components/time-picker.js +457 -0
- package/dist/components/time-picker.js.map +1 -0
- package/dist/components/tooltip.js +239 -0
- package/dist/components/tooltip.js.map +1 -0
- package/dist/components/tree.js +582 -0
- package/dist/components/tree.js.map +1 -0
- package/dist/index.js +93 -17799
- package/dist/index.js.map +1 -1
- package/dist/shared/boolean-converter-XDGfS9LC.js +12 -0
- package/dist/shared/boolean-converter-XDGfS9LC.js.map +1 -0
- package/dist/shared/debounce-BckY30Sf.js +23 -0
- package/dist/shared/debounce-BckY30Sf.js.map +1 -0
- package/dist/shared/memoize-DlOFy-92.js +16 -0
- package/dist/shared/memoize-DlOFy-92.js.map +1 -0
- package/dist/shared/slider-BNt5TITl.js +484 -0
- package/dist/shared/slider-BNt5TITl.js.map +1 -0
- package/package.json +49 -3
|
@@ -0,0 +1,1660 @@
|
|
|
1
|
+
import { css as $, LitElement as x, html as l, nothing as c } from "lit";
|
|
2
|
+
import { property as u, state as f, query as m, customElement as k } from "lit/decorators.js";
|
|
3
|
+
import { b as C } from "../shared/boolean-converter-XDGfS9LC.js";
|
|
4
|
+
const I = $`
|
|
5
|
+
/* ─────────────────────────────────────────────────────────────────────────────
|
|
6
|
+
* Base Styles
|
|
7
|
+
* ───────────────────────────────────────────────────────────────────────────── */
|
|
8
|
+
|
|
9
|
+
:host {
|
|
10
|
+
/* Component-specific custom properties */
|
|
11
|
+
/* stylelint-disable blueprint/no-hardcoded-values */
|
|
12
|
+
--color-picker-width: 350px;
|
|
13
|
+
--color-picker-area-height: 160px;
|
|
14
|
+
--color-picker-swatch-size: var(--bp-spacing-lg);
|
|
15
|
+
--color-picker-handle-size: var(--bp-spacing-md);
|
|
16
|
+
/* stylelint-enable blueprint/no-hardcoded-values */
|
|
17
|
+
|
|
18
|
+
display: inline-block;
|
|
19
|
+
position: relative;
|
|
20
|
+
font-family: var(--bp-font-family);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
:host([disabled]) {
|
|
24
|
+
opacity: var(--bp-opacity-disabled);
|
|
25
|
+
pointer-events: none;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.color-picker {
|
|
29
|
+
position: relative;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Screen reader only text */
|
|
33
|
+
.sr-only {
|
|
34
|
+
position: absolute;
|
|
35
|
+
width: 1px;
|
|
36
|
+
height: 1px;
|
|
37
|
+
padding: 0;
|
|
38
|
+
margin: -1px;
|
|
39
|
+
overflow: hidden;
|
|
40
|
+
clip: rect(0, 0, 0, 0);
|
|
41
|
+
white-space: nowrap;
|
|
42
|
+
border-width: 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* ─────────────────────────────────────────────────────────────────────────────
|
|
46
|
+
* Trigger Button
|
|
47
|
+
* ───────────────────────────────────────────────────────────────────────────── */
|
|
48
|
+
|
|
49
|
+
.trigger {
|
|
50
|
+
display: inline-flex;
|
|
51
|
+
align-items: center;
|
|
52
|
+
gap: var(--bp-spacing-sm);
|
|
53
|
+
padding: var(--bp-spacing-sm) var(--bp-spacing-md);
|
|
54
|
+
background-color: var(--bp-color-surface);
|
|
55
|
+
border: var(--bp-border-width) solid var(--bp-color-border);
|
|
56
|
+
border-radius: var(--bp-border-radius-md);
|
|
57
|
+
cursor: pointer;
|
|
58
|
+
font-family: inherit;
|
|
59
|
+
font-size: var(--bp-font-size-base);
|
|
60
|
+
color: var(--bp-color-text);
|
|
61
|
+
transition:
|
|
62
|
+
border-color var(--bp-transition-fast),
|
|
63
|
+
box-shadow var(--bp-transition-fast);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.trigger:hover:not(:disabled) {
|
|
67
|
+
border-color: var(--bp-color-border-strong);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.trigger:focus-visible {
|
|
71
|
+
outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);
|
|
72
|
+
outline-offset: var(--bp-focus-offset);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.trigger:disabled {
|
|
76
|
+
cursor: not-allowed;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.trigger-swatch {
|
|
80
|
+
display: block;
|
|
81
|
+
width: var(--color-picker-swatch-size);
|
|
82
|
+
height: var(--color-picker-swatch-size);
|
|
83
|
+
border-radius: var(--bp-border-radius-sm);
|
|
84
|
+
border: var(--bp-border-width) solid var(--bp-color-border);
|
|
85
|
+
/* Checkerboard pattern for transparency - functional, not themed */
|
|
86
|
+
/* stylelint-disable blueprint/no-hardcoded-values */
|
|
87
|
+
background-image:
|
|
88
|
+
linear-gradient(45deg, #ccc 25%, transparent 25%),
|
|
89
|
+
linear-gradient(-45deg, #ccc 25%, transparent 25%),
|
|
90
|
+
linear-gradient(45deg, transparent 75%, #ccc 75%),
|
|
91
|
+
linear-gradient(-45deg, transparent 75%, #ccc 75%);
|
|
92
|
+
background-size: var(--bp-spacing-sm) var(--bp-spacing-sm);
|
|
93
|
+
background-position:
|
|
94
|
+
0 0,
|
|
95
|
+
0 calc(var(--bp-spacing-sm) / 2),
|
|
96
|
+
calc(var(--bp-spacing-sm) / 2) calc(var(--bp-spacing-sm) / -2),
|
|
97
|
+
calc(var(--bp-spacing-sm) / -2) 0;
|
|
98
|
+
/* stylelint-enable blueprint/no-hardcoded-values */
|
|
99
|
+
position: relative;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.trigger-swatch::after {
|
|
103
|
+
content: '';
|
|
104
|
+
position: absolute;
|
|
105
|
+
inset: 0;
|
|
106
|
+
background: inherit;
|
|
107
|
+
border-radius: inherit;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.trigger-label {
|
|
111
|
+
color: var(--bp-color-text);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* ─────────────────────────────────────────────────────────────────────────────
|
|
115
|
+
* Picker Panel
|
|
116
|
+
* ───────────────────────────────────────────────────────────────────────────── */
|
|
117
|
+
|
|
118
|
+
.picker {
|
|
119
|
+
position: absolute;
|
|
120
|
+
top: 100%;
|
|
121
|
+
left: 0;
|
|
122
|
+
margin-top: var(--bp-spacing-xs);
|
|
123
|
+
width: var(--color-picker-width);
|
|
124
|
+
background-color: var(--bp-color-surface-elevated);
|
|
125
|
+
border: var(--bp-border-width) solid var(--bp-color-border);
|
|
126
|
+
border-radius: var(--bp-border-radius-lg);
|
|
127
|
+
box-shadow: var(--bp-shadow-lg);
|
|
128
|
+
z-index: var(--bp-z-popover);
|
|
129
|
+
animation: fadeIn var(--bp-transition-fast) ease-out;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
@keyframes fadeIn {
|
|
133
|
+
from {
|
|
134
|
+
opacity: 0;
|
|
135
|
+
transform: translateY(calc(var(--bp-spacing-xs) * -1));
|
|
136
|
+
}
|
|
137
|
+
to {
|
|
138
|
+
opacity: 1;
|
|
139
|
+
transform: translateY(0);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
:host([inline]) .picker {
|
|
144
|
+
position: static;
|
|
145
|
+
margin-top: 0;
|
|
146
|
+
box-shadow: none;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.picker-body {
|
|
150
|
+
padding: var(--bp-spacing-md);
|
|
151
|
+
display: flex;
|
|
152
|
+
flex-direction: column;
|
|
153
|
+
gap: var(--bp-spacing-md);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.picker-main {
|
|
157
|
+
display: flex;
|
|
158
|
+
gap: var(--bp-spacing-sm);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/* ─────────────────────────────────────────────────────────────────────────────
|
|
162
|
+
* Color Area (Saturation/Value)
|
|
163
|
+
* ───────────────────────────────────────────────────────────────────────────── */
|
|
164
|
+
|
|
165
|
+
.color-area {
|
|
166
|
+
flex: 1;
|
|
167
|
+
height: var(--color-picker-area-height);
|
|
168
|
+
position: relative;
|
|
169
|
+
border-radius: var(--bp-border-radius-sm);
|
|
170
|
+
background: var(--hue-color);
|
|
171
|
+
cursor: crosshair;
|
|
172
|
+
touch-action: none;
|
|
173
|
+
user-select: none;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/* White-to-transparent and transparent-to-black gradients - functional for color picking */
|
|
177
|
+
/* stylelint-disable blueprint/no-hardcoded-values */
|
|
178
|
+
.color-area::before {
|
|
179
|
+
content: '';
|
|
180
|
+
position: absolute;
|
|
181
|
+
inset: 0;
|
|
182
|
+
background: linear-gradient(to right, #fff, transparent);
|
|
183
|
+
border-radius: inherit;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.color-area::after {
|
|
187
|
+
content: '';
|
|
188
|
+
position: absolute;
|
|
189
|
+
inset: 0;
|
|
190
|
+
background: linear-gradient(to bottom, transparent, #000);
|
|
191
|
+
border-radius: inherit;
|
|
192
|
+
}
|
|
193
|
+
/* stylelint-enable blueprint/no-hardcoded-values */
|
|
194
|
+
|
|
195
|
+
.color-area:focus-visible {
|
|
196
|
+
outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);
|
|
197
|
+
outline-offset: var(--bp-focus-offset);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* Slider handles use white borders for visibility on any color */
|
|
201
|
+
/* stylelint-disable blueprint/no-hardcoded-values -- white border for contrast on any hue */
|
|
202
|
+
.color-area-handle {
|
|
203
|
+
position: absolute;
|
|
204
|
+
width: var(--color-picker-handle-size);
|
|
205
|
+
height: var(--color-picker-handle-size);
|
|
206
|
+
border: var(--bp-border-width) solid #fff;
|
|
207
|
+
border-radius: 50%;
|
|
208
|
+
box-shadow: var(--bp-shadow-sm);
|
|
209
|
+
transform: translate(-50%, -50%);
|
|
210
|
+
z-index: 1;
|
|
211
|
+
pointer-events: none;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/* Expand touch target to 44×44px minimum (WCAG 2.2) */
|
|
215
|
+
.color-area-handle::after {
|
|
216
|
+
content: '';
|
|
217
|
+
position: absolute;
|
|
218
|
+
/* 44px touch target with 12px visual handle = 16px padding each side */
|
|
219
|
+
inset: calc(var(--bp-spacing-lg) * -1);
|
|
220
|
+
}
|
|
221
|
+
/* stylelint-enable blueprint/no-hardcoded-values */
|
|
222
|
+
|
|
223
|
+
/* ─────────────────────────────────────────────────────────────────────────────
|
|
224
|
+
* Hue Slider
|
|
225
|
+
* ───────────────────────────────────────────────────────────────────────────── */
|
|
226
|
+
|
|
227
|
+
.hue-slider {
|
|
228
|
+
width: var(--bp-spacing-lg);
|
|
229
|
+
height: var(--color-picker-area-height);
|
|
230
|
+
position: relative;
|
|
231
|
+
border-radius: var(--bp-border-radius-sm);
|
|
232
|
+
/* Full hue spectrum gradient - functional, not themed */
|
|
233
|
+
/* stylelint-disable blueprint/no-hardcoded-values */
|
|
234
|
+
background: linear-gradient(
|
|
235
|
+
to bottom,
|
|
236
|
+
hsl(0, 100%, 50%),
|
|
237
|
+
hsl(60, 100%, 50%),
|
|
238
|
+
hsl(120, 100%, 50%),
|
|
239
|
+
hsl(180, 100%, 50%),
|
|
240
|
+
hsl(240, 100%, 50%),
|
|
241
|
+
hsl(300, 100%, 50%),
|
|
242
|
+
hsl(360, 100%, 50%)
|
|
243
|
+
);
|
|
244
|
+
/* stylelint-enable blueprint/no-hardcoded-values */
|
|
245
|
+
cursor: pointer;
|
|
246
|
+
touch-action: none;
|
|
247
|
+
user-select: none;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.hue-slider:focus-visible {
|
|
251
|
+
outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);
|
|
252
|
+
outline-offset: var(--bp-focus-offset);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/* stylelint-disable blueprint/no-hardcoded-values -- white border for contrast on hue spectrum */
|
|
256
|
+
.hue-slider-handle {
|
|
257
|
+
position: absolute;
|
|
258
|
+
left: calc(var(--bp-spacing-xs) * -0.5);
|
|
259
|
+
right: calc(var(--bp-spacing-xs) * -0.5);
|
|
260
|
+
height: var(--bp-spacing-sm);
|
|
261
|
+
border: var(--bp-border-width) solid #fff;
|
|
262
|
+
border-radius: var(--bp-border-radius-sm);
|
|
263
|
+
box-shadow: var(--bp-shadow-sm);
|
|
264
|
+
transform: translateY(-50%);
|
|
265
|
+
pointer-events: none;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/* Expand touch target to 44×44px minimum (WCAG 2.2) */
|
|
269
|
+
.hue-slider-handle::after {
|
|
270
|
+
content: '';
|
|
271
|
+
position: absolute;
|
|
272
|
+
/* 44px touch target with 8px visual handle = 18px padding top/bottom */
|
|
273
|
+
top: calc(var(--bp-spacing-lg) * -2.25);
|
|
274
|
+
bottom: calc(var(--bp-spacing-lg) * -2.25);
|
|
275
|
+
left: 0;
|
|
276
|
+
right: 0;
|
|
277
|
+
}
|
|
278
|
+
/* stylelint-enable blueprint/no-hardcoded-values */
|
|
279
|
+
|
|
280
|
+
/* ─────────────────────────────────────────────────────────────────────────────
|
|
281
|
+
* Alpha Slider
|
|
282
|
+
* ───────────────────────────────────────────────────────────────────────────── */
|
|
283
|
+
|
|
284
|
+
.alpha-slider {
|
|
285
|
+
height: var(--bp-spacing-md);
|
|
286
|
+
position: relative;
|
|
287
|
+
border-radius: var(--bp-border-radius-sm);
|
|
288
|
+
/* Checkerboard pattern for transparency - functional, not themed */
|
|
289
|
+
/* stylelint-disable blueprint/no-hardcoded-values */
|
|
290
|
+
background-image:
|
|
291
|
+
linear-gradient(45deg, #ccc 25%, transparent 25%),
|
|
292
|
+
linear-gradient(-45deg, #ccc 25%, transparent 25%),
|
|
293
|
+
linear-gradient(45deg, transparent 75%, #ccc 75%),
|
|
294
|
+
linear-gradient(-45deg, transparent 75%, #ccc 75%);
|
|
295
|
+
background-size: var(--bp-spacing-sm) var(--bp-spacing-sm);
|
|
296
|
+
background-position:
|
|
297
|
+
0 0,
|
|
298
|
+
0 calc(var(--bp-spacing-sm) / 2),
|
|
299
|
+
calc(var(--bp-spacing-sm) / 2) calc(var(--bp-spacing-sm) / -2),
|
|
300
|
+
calc(var(--bp-spacing-sm) / -2) 0;
|
|
301
|
+
/* stylelint-enable blueprint/no-hardcoded-values */
|
|
302
|
+
cursor: pointer;
|
|
303
|
+
touch-action: none;
|
|
304
|
+
user-select: none;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.alpha-slider::before {
|
|
308
|
+
content: '';
|
|
309
|
+
position: absolute;
|
|
310
|
+
inset: 0;
|
|
311
|
+
background: var(--alpha-gradient);
|
|
312
|
+
border-radius: inherit;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.alpha-slider:focus-visible {
|
|
316
|
+
outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);
|
|
317
|
+
outline-offset: var(--bp-focus-offset);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/* stylelint-disable blueprint/no-hardcoded-values -- white border for contrast on alpha gradient */
|
|
321
|
+
.alpha-slider-handle {
|
|
322
|
+
position: absolute;
|
|
323
|
+
top: calc(var(--bp-spacing-xs) * -0.5);
|
|
324
|
+
bottom: calc(var(--bp-spacing-xs) * -0.5);
|
|
325
|
+
width: var(--bp-spacing-sm);
|
|
326
|
+
border: var(--bp-border-width) solid #fff;
|
|
327
|
+
border-radius: var(--bp-border-radius-sm);
|
|
328
|
+
box-shadow: var(--bp-shadow-sm);
|
|
329
|
+
transform: translateX(-50%);
|
|
330
|
+
pointer-events: none;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/* Expand touch target to 44×44px minimum (WCAG 2.2) */
|
|
334
|
+
.alpha-slider-handle::after {
|
|
335
|
+
content: '';
|
|
336
|
+
position: absolute;
|
|
337
|
+
/* 44px touch target with 8px visual handle = 18px padding left/right */
|
|
338
|
+
left: calc(var(--bp-spacing-lg) * -2.25);
|
|
339
|
+
right: calc(var(--bp-spacing-lg) * -2.25);
|
|
340
|
+
top: 0;
|
|
341
|
+
bottom: 0;
|
|
342
|
+
}
|
|
343
|
+
/* stylelint-enable blueprint/no-hardcoded-values */
|
|
344
|
+
|
|
345
|
+
/* ─────────────────────────────────────────────────────────────────────────────
|
|
346
|
+
* Controls Row
|
|
347
|
+
* ───────────────────────────────────────────────────────────────────────────── */
|
|
348
|
+
|
|
349
|
+
.picker-controls {
|
|
350
|
+
display: flex;
|
|
351
|
+
align-items: flex-start;
|
|
352
|
+
gap: var(--bp-spacing-sm);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/* ─────────────────────────────────────────────────────────────────────────────
|
|
356
|
+
* Preview
|
|
357
|
+
* ───────────────────────────────────────────────────────────────────────────── */
|
|
358
|
+
|
|
359
|
+
.preview {
|
|
360
|
+
display: flex;
|
|
361
|
+
flex-direction: column;
|
|
362
|
+
width: var(--bp-spacing-2xl);
|
|
363
|
+
height: var(--bp-spacing-2xl);
|
|
364
|
+
border-radius: var(--bp-border-radius-sm);
|
|
365
|
+
overflow: hidden;
|
|
366
|
+
border: var(--bp-border-width) solid var(--bp-color-border);
|
|
367
|
+
/* Checkerboard pattern for transparency - functional, not themed */
|
|
368
|
+
/* stylelint-disable blueprint/no-hardcoded-values */
|
|
369
|
+
background-image:
|
|
370
|
+
linear-gradient(45deg, #ccc 25%, transparent 25%),
|
|
371
|
+
linear-gradient(-45deg, #ccc 25%, transparent 25%),
|
|
372
|
+
linear-gradient(45deg, transparent 75%, #ccc 75%),
|
|
373
|
+
linear-gradient(-45deg, transparent 75%, #ccc 75%);
|
|
374
|
+
background-size: var(--bp-spacing-sm) var(--bp-spacing-sm);
|
|
375
|
+
background-position:
|
|
376
|
+
0 0,
|
|
377
|
+
0 calc(var(--bp-spacing-sm) / 2),
|
|
378
|
+
calc(var(--bp-spacing-sm) / 2) calc(var(--bp-spacing-sm) / -2),
|
|
379
|
+
calc(var(--bp-spacing-sm) / -2) 0;
|
|
380
|
+
/* stylelint-enable blueprint/no-hardcoded-values */
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
.preview-swatch {
|
|
384
|
+
flex: 1;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/* ─────────────────────────────────────────────────────────────────────────────
|
|
388
|
+
* Inputs
|
|
389
|
+
* ───────────────────────────────────────────────────────────────────────────── */
|
|
390
|
+
|
|
391
|
+
.inputs-container {
|
|
392
|
+
flex: 1;
|
|
393
|
+
display: flex;
|
|
394
|
+
align-items: flex-start;
|
|
395
|
+
gap: var(--bp-spacing-xs);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.input-row {
|
|
399
|
+
display: flex;
|
|
400
|
+
gap: var(--bp-spacing-xs);
|
|
401
|
+
flex: 1;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.input-group {
|
|
405
|
+
flex: 1;
|
|
406
|
+
display: flex;
|
|
407
|
+
flex-direction: column;
|
|
408
|
+
gap: var(--bp-spacing-2xs);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
.color-input {
|
|
412
|
+
width: 100%;
|
|
413
|
+
padding: var(--bp-spacing-xs);
|
|
414
|
+
font-family: var(--bp-font-family-mono);
|
|
415
|
+
font-size: var(--bp-font-size-sm);
|
|
416
|
+
background-color: var(--bp-color-surface);
|
|
417
|
+
border: var(--bp-border-width) solid var(--bp-color-border);
|
|
418
|
+
border-radius: var(--bp-border-radius-sm);
|
|
419
|
+
color: var(--bp-color-text);
|
|
420
|
+
text-align: center;
|
|
421
|
+
box-sizing: border-box;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
.color-input:focus {
|
|
425
|
+
outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);
|
|
426
|
+
outline-offset: var(--bp-focus-offset);
|
|
427
|
+
border-color: var(--bp-color-primary);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
.color-input::-webkit-inner-spin-button,
|
|
431
|
+
.color-input::-webkit-outer-spin-button {
|
|
432
|
+
-webkit-appearance: none;
|
|
433
|
+
margin: 0;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.color-input[type='number'] {
|
|
437
|
+
-moz-appearance: textfield;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
.hex-input {
|
|
441
|
+
text-transform: uppercase;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.input-label {
|
|
445
|
+
font-size: var(--bp-font-size-xs);
|
|
446
|
+
color: var(--bp-color-text-muted);
|
|
447
|
+
text-align: center;
|
|
448
|
+
text-transform: uppercase;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.format-toggle {
|
|
452
|
+
display: flex;
|
|
453
|
+
align-items: center;
|
|
454
|
+
justify-content: center;
|
|
455
|
+
width: var(--bp-spacing-xl);
|
|
456
|
+
height: var(--bp-spacing-xl);
|
|
457
|
+
padding: 0;
|
|
458
|
+
margin-top: var(--bp-spacing-2xs);
|
|
459
|
+
background-color: var(--bp-color-surface);
|
|
460
|
+
border: var(--bp-border-width) solid var(--bp-color-border);
|
|
461
|
+
border-radius: var(--bp-border-radius-sm);
|
|
462
|
+
color: var(--bp-color-text-muted);
|
|
463
|
+
cursor: pointer;
|
|
464
|
+
transition:
|
|
465
|
+
background-color var(--bp-transition-fast),
|
|
466
|
+
color var(--bp-transition-fast);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
.format-toggle:hover:not(:disabled) {
|
|
470
|
+
background-color: var(--bp-color-surface-subdued);
|
|
471
|
+
color: var(--bp-color-text);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
.format-toggle:focus-visible {
|
|
475
|
+
outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);
|
|
476
|
+
outline-offset: var(--bp-focus-offset);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
.format-toggle svg {
|
|
480
|
+
width: var(--bp-spacing-md);
|
|
481
|
+
height: var(--bp-spacing-md);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/* ─────────────────────────────────────────────────────────────────────────────
|
|
485
|
+
* Eyedropper
|
|
486
|
+
* ───────────────────────────────────────────────────────────────────────────── */
|
|
487
|
+
|
|
488
|
+
.eyedropper-button {
|
|
489
|
+
display: flex;
|
|
490
|
+
align-items: center;
|
|
491
|
+
justify-content: center;
|
|
492
|
+
width: var(--bp-spacing-2xl);
|
|
493
|
+
height: var(--bp-spacing-2xl);
|
|
494
|
+
padding: 0;
|
|
495
|
+
background-color: var(--bp-color-surface);
|
|
496
|
+
border: var(--bp-border-width) solid var(--bp-color-border);
|
|
497
|
+
border-radius: var(--bp-border-radius-sm);
|
|
498
|
+
color: var(--bp-color-text-muted);
|
|
499
|
+
cursor: pointer;
|
|
500
|
+
transition:
|
|
501
|
+
background-color var(--bp-transition-fast),
|
|
502
|
+
color var(--bp-transition-fast);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
.eyedropper-button:hover:not(:disabled) {
|
|
506
|
+
background-color: var(--bp-color-surface-subdued);
|
|
507
|
+
color: var(--bp-color-text);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
.eyedropper-button:focus-visible {
|
|
511
|
+
outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);
|
|
512
|
+
outline-offset: var(--bp-focus-offset);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
.eyedropper-button:disabled {
|
|
516
|
+
cursor: not-allowed;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
.eyedropper-button svg {
|
|
520
|
+
width: var(--bp-spacing-lg);
|
|
521
|
+
height: var(--bp-spacing-lg);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/* ─────────────────────────────────────────────────────────────────────────────
|
|
525
|
+
* Swatches
|
|
526
|
+
* ───────────────────────────────────────────────────────────────────────────── */
|
|
527
|
+
|
|
528
|
+
.swatches-container {
|
|
529
|
+
display: flex;
|
|
530
|
+
flex-wrap: wrap;
|
|
531
|
+
gap: var(--bp-spacing-xs);
|
|
532
|
+
padding-top: var(--bp-spacing-sm);
|
|
533
|
+
border-top: var(--bp-border-width) solid var(--bp-color-border);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
.swatch {
|
|
537
|
+
width: var(--color-picker-swatch-size);
|
|
538
|
+
height: var(--color-picker-swatch-size);
|
|
539
|
+
padding: 0;
|
|
540
|
+
border: var(--bp-border-width) solid var(--bp-color-border);
|
|
541
|
+
border-radius: var(--bp-border-radius-sm);
|
|
542
|
+
cursor: pointer;
|
|
543
|
+
transition: transform var(--bp-transition-fast);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
.swatch:hover:not(:disabled) {
|
|
547
|
+
transform: scale(1.1);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
.swatch:focus-visible {
|
|
551
|
+
outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);
|
|
552
|
+
outline-offset: var(--bp-focus-offset);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
.swatch:disabled {
|
|
556
|
+
cursor: not-allowed;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/* ─────────────────────────────────────────────────────────────────────────────
|
|
560
|
+
* Sizes
|
|
561
|
+
* ───────────────────────────────────────────────────────────────────────────── */
|
|
562
|
+
|
|
563
|
+
.color-picker--sm .trigger {
|
|
564
|
+
padding: var(--bp-spacing-xs) var(--bp-spacing-sm);
|
|
565
|
+
font-size: var(--bp-font-size-sm);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
.color-picker--sm .trigger-swatch {
|
|
569
|
+
width: var(--bp-spacing-lg);
|
|
570
|
+
height: var(--bp-spacing-lg);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
.color-picker--lg .trigger {
|
|
574
|
+
padding: var(--bp-spacing-md) var(--bp-spacing-lg);
|
|
575
|
+
font-size: var(--bp-font-size-lg);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
.color-picker--lg .trigger-swatch {
|
|
579
|
+
width: var(--bp-spacing-xl);
|
|
580
|
+
height: var(--bp-spacing-xl);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/* ─────────────────────────────────────────────────────────────────────────────
|
|
584
|
+
* Reduced Motion
|
|
585
|
+
* ───────────────────────────────────────────────────────────────────────────── */
|
|
586
|
+
|
|
587
|
+
@media (prefers-reduced-motion: reduce) {
|
|
588
|
+
@keyframes fadeIn {
|
|
589
|
+
from,
|
|
590
|
+
to {
|
|
591
|
+
opacity: 1;
|
|
592
|
+
transform: translateY(0);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
.trigger,
|
|
597
|
+
.format-toggle,
|
|
598
|
+
.eyedropper-button,
|
|
599
|
+
.swatch,
|
|
600
|
+
.color-input {
|
|
601
|
+
transition: none;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
`;
|
|
605
|
+
function g(t) {
|
|
606
|
+
return t ? (t = t.trim().toLowerCase(), t.startsWith("#") ? M(t) : t.startsWith("rgb") ? A(t) : t.startsWith("hsl") ? S(t) : null) : null;
|
|
607
|
+
}
|
|
608
|
+
function M(t) {
|
|
609
|
+
t = t.replace("#", "");
|
|
610
|
+
let e, r, a, i = 1;
|
|
611
|
+
if (t.length === 3)
|
|
612
|
+
e = parseInt(t[0] + t[0], 16), r = parseInt(t[1] + t[1], 16), a = parseInt(t[2] + t[2], 16);
|
|
613
|
+
else if (t.length === 4)
|
|
614
|
+
e = parseInt(t[0] + t[0], 16), r = parseInt(t[1] + t[1], 16), a = parseInt(t[2] + t[2], 16), i = parseInt(t[3] + t[3], 16) / 255;
|
|
615
|
+
else if (t.length === 6)
|
|
616
|
+
e = parseInt(t.substring(0, 2), 16), r = parseInt(t.substring(2, 4), 16), a = parseInt(t.substring(4, 6), 16);
|
|
617
|
+
else if (t.length === 8)
|
|
618
|
+
e = parseInt(t.substring(0, 2), 16), r = parseInt(t.substring(2, 4), 16), a = parseInt(t.substring(4, 6), 16), i = parseInt(t.substring(6, 8), 16) / 255;
|
|
619
|
+
else
|
|
620
|
+
return null;
|
|
621
|
+
return isNaN(e) || isNaN(r) || isNaN(a) || isNaN(i) ? null : w({ r: e, g: r, b: a, a: i });
|
|
622
|
+
}
|
|
623
|
+
function A(t) {
|
|
624
|
+
const e = t.match(
|
|
625
|
+
/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+))?\s*\)/
|
|
626
|
+
);
|
|
627
|
+
if (!e) return null;
|
|
628
|
+
const r = parseInt(e[1], 10), a = parseInt(e[2], 10), i = parseInt(e[3], 10), n = e[4] !== void 0 ? parseFloat(e[4]) : 1;
|
|
629
|
+
return w({ r, g: a, b: i, a: n });
|
|
630
|
+
}
|
|
631
|
+
function S(t) {
|
|
632
|
+
const e = t.match(
|
|
633
|
+
/hsla?\(\s*([\d.]+)\s*,\s*([\d.]+)%?\s*,\s*([\d.]+)%?\s*(?:,\s*([\d.]+))?\s*\)/
|
|
634
|
+
);
|
|
635
|
+
if (!e) return null;
|
|
636
|
+
const r = parseFloat(e[1]), a = parseFloat(e[2]), i = parseFloat(e[3]), n = e[4] !== void 0 ? parseFloat(e[4]) : 1;
|
|
637
|
+
return P({ h: r, s: a, l: i, a: n });
|
|
638
|
+
}
|
|
639
|
+
function w(t) {
|
|
640
|
+
const e = t.r / 255, r = t.g / 255, a = t.b / 255, i = Math.max(e, r, a), n = Math.min(e, r, a), h = i - n;
|
|
641
|
+
let p = 0;
|
|
642
|
+
const d = i === 0 ? 0 : h / i * 100, b = i * 100;
|
|
643
|
+
return h !== 0 && (i === e ? p = 60 * ((r - a) / h % 6) : i === r ? p = 60 * ((a - e) / h + 2) : p = 60 * ((e - r) / h + 4)), p < 0 && (p += 360), { h: p, s: d, v: b, a: t.a };
|
|
644
|
+
}
|
|
645
|
+
function v(t) {
|
|
646
|
+
const e = t.h, r = t.s / 100, a = t.v / 100, i = a * r, n = i * (1 - Math.abs(e / 60 % 2 - 1)), h = a - i;
|
|
647
|
+
let p = 0, d = 0, b = 0;
|
|
648
|
+
return e >= 0 && e < 60 ? (p = i, d = n, b = 0) : e >= 60 && e < 120 ? (p = n, d = i, b = 0) : e >= 120 && e < 180 ? (p = 0, d = i, b = n) : e >= 180 && e < 240 ? (p = 0, d = n, b = i) : e >= 240 && e < 300 ? (p = n, d = 0, b = i) : (p = i, d = 0, b = n), {
|
|
649
|
+
r: Math.round((p + h) * 255),
|
|
650
|
+
g: Math.round((d + h) * 255),
|
|
651
|
+
b: Math.round((b + h) * 255),
|
|
652
|
+
a: t.a
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
function P(t) {
|
|
656
|
+
const e = t.h, r = t.s / 100, a = t.l / 100, i = a + r * Math.min(a, 1 - a), n = i === 0 ? 0 : 2 * (1 - a / i);
|
|
657
|
+
return { h: e, s: n * 100, v: i * 100, a: t.a };
|
|
658
|
+
}
|
|
659
|
+
function _(t) {
|
|
660
|
+
const e = t.h, r = t.s / 100, a = t.v / 100, i = a * (1 - r / 2), n = i === 0 || i === 1 ? 0 : (a - i) / Math.min(i, 1 - i);
|
|
661
|
+
return { h: e, s: n * 100, l: i * 100, a: t.a };
|
|
662
|
+
}
|
|
663
|
+
function y(t) {
|
|
664
|
+
return Math.round(t * 100) / 100;
|
|
665
|
+
}
|
|
666
|
+
function H(t, e, r) {
|
|
667
|
+
const a = v(t), i = _(t);
|
|
668
|
+
switch (e) {
|
|
669
|
+
case "rgb":
|
|
670
|
+
return r && t.a < 1 ? `rgba(${a.r}, ${a.g}, ${a.b}, ${y(t.a)})` : `rgb(${a.r}, ${a.g}, ${a.b})`;
|
|
671
|
+
case "hsl":
|
|
672
|
+
return r && t.a < 1 ? `hsla(${Math.round(i.h)}, ${Math.round(i.s)}%, ${Math.round(i.l)}%, ${y(t.a)})` : `hsl(${Math.round(i.h)}, ${Math.round(i.s)}%, ${Math.round(i.l)}%)`;
|
|
673
|
+
default: {
|
|
674
|
+
const n = a.r.toString(16).padStart(2, "0"), h = a.g.toString(16).padStart(2, "0"), p = a.b.toString(16).padStart(2, "0");
|
|
675
|
+
if (r && t.a < 1) {
|
|
676
|
+
const d = Math.round(t.a * 255).toString(16).padStart(2, "0");
|
|
677
|
+
return `#${n}${h}${p}${d}`;
|
|
678
|
+
}
|
|
679
|
+
return `#${n}${h}${p}`;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
var D = Object.defineProperty, O = Object.getOwnPropertyDescriptor, o = (t, e, r, a) => {
|
|
684
|
+
for (var i = a > 1 ? void 0 : a ? O(e, r) : e, n = t.length - 1, h; n >= 0; n--)
|
|
685
|
+
(h = t[n]) && (i = (a ? h(e, r, i) : h(i)) || i);
|
|
686
|
+
return a && i && D(e, r, i), i;
|
|
687
|
+
};
|
|
688
|
+
let s = class extends x {
|
|
689
|
+
constructor() {
|
|
690
|
+
super(), this._open = !1, this._hsv = { h: 0, s: 0, v: 0, a: 1 }, this._originalValue = "", this._eyedropperSupported = !1, this._inputMode = "hex", this._hexInputValue = "", this._isPickingColor = !1, this._isDraggingArea = !1, this._isDraggingHue = !1, this._isDraggingAlpha = !1, this._handleOutsideClick = (t) => {
|
|
691
|
+
t.composedPath().includes(this) || this._close();
|
|
692
|
+
}, this._handleEscapeKey = (t) => {
|
|
693
|
+
t.key === "Escape" && (this.value = this._originalValue, this._parseValue(this._originalValue), this._hexInputValue = this._formatOutput("hex"), this._close());
|
|
694
|
+
}, this.value = "#000000", this.format = "hex", this.alpha = !0, this.swatches = [], this.inline = !1, this.disabled = !1, this.readonly = !1, this.size = "md", this.label = "", this.name = "", this.placeholder = "";
|
|
695
|
+
}
|
|
696
|
+
connectedCallback() {
|
|
697
|
+
super.connectedCallback(), this._eyedropperSupported = "EyeDropper" in window, this._parseValue(this.value), this._hexInputValue = this._formatOutput("hex"), this._inputMode = this.format;
|
|
698
|
+
}
|
|
699
|
+
disconnectedCallback() {
|
|
700
|
+
super.disconnectedCallback(), this._removeGlobalListeners();
|
|
701
|
+
}
|
|
702
|
+
willUpdate(t) {
|
|
703
|
+
t.has("value") && !this._isDragging() && (this._parseValue(this.value), this._hexInputValue = this._formatOutput("hex")), t.has("format") && (this._inputMode = this.format);
|
|
704
|
+
}
|
|
705
|
+
_isDragging() {
|
|
706
|
+
return this._isDraggingArea || this._isDraggingHue || this._isDraggingAlpha;
|
|
707
|
+
}
|
|
708
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
709
|
+
// Color Parsing & Conversion
|
|
710
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
711
|
+
/**
|
|
712
|
+
* Parses a color value string and updates internal HSV state
|
|
713
|
+
* @param value Color string in hex, rgb, or hsl format
|
|
714
|
+
*/
|
|
715
|
+
_parseValue(t) {
|
|
716
|
+
const e = g(t);
|
|
717
|
+
e && (this._hsv = e);
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Formats the current HSV color to the specified output format
|
|
721
|
+
* @param format Output format (hex, rgb, or hsl), defaults to this.format
|
|
722
|
+
* @returns Formatted color string
|
|
723
|
+
*/
|
|
724
|
+
_formatOutput(t = this.format) {
|
|
725
|
+
return H(this._hsv, t, this.alpha);
|
|
726
|
+
}
|
|
727
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
728
|
+
// Event Handlers
|
|
729
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
730
|
+
/**
|
|
731
|
+
* Handles click events on the trigger button
|
|
732
|
+
* Toggles the picker popover open/closed state
|
|
733
|
+
*/
|
|
734
|
+
_handleTriggerClick() {
|
|
735
|
+
this.disabled || this.readonly || this._toggleOpen();
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* Handles keyboard events on the trigger button
|
|
739
|
+
* Opens picker on Enter or Space key
|
|
740
|
+
* @param event Keyboard event
|
|
741
|
+
*/
|
|
742
|
+
_handleTriggerKeydown(t) {
|
|
743
|
+
this.disabled || this.readonly || (t.key === "Enter" || t.key === " ") && (t.preventDefault(), this._toggleOpen());
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Toggles the picker popover between open and closed states
|
|
747
|
+
* Saves original value when opening and emits bp-open/bp-close events
|
|
748
|
+
*/
|
|
749
|
+
_toggleOpen() {
|
|
750
|
+
this._open ? this._close() : (this._open = !0, this._originalValue = this.value, this.dispatchEvent(
|
|
751
|
+
new CustomEvent("bp-open", { bubbles: !0, composed: !0 })
|
|
752
|
+
), this._addGlobalListeners());
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Closes the picker popover
|
|
756
|
+
* Removes global event listeners and emits bp-close event
|
|
757
|
+
*/
|
|
758
|
+
_close() {
|
|
759
|
+
this._open = !1, this._removeGlobalListeners(), this.dispatchEvent(
|
|
760
|
+
new CustomEvent("bp-close", { bubbles: !0, composed: !0 })
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
764
|
+
* Adds global document event listeners for outside clicks and escape key
|
|
765
|
+
* Used when picker popover is open
|
|
766
|
+
*/
|
|
767
|
+
_addGlobalListeners() {
|
|
768
|
+
document.addEventListener("click", this._handleOutsideClick), document.addEventListener("keydown", this._handleEscapeKey);
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Removes global document event listeners
|
|
772
|
+
* Called when picker popover is closed
|
|
773
|
+
*/
|
|
774
|
+
_removeGlobalListeners() {
|
|
775
|
+
document.removeEventListener("click", this._handleOutsideClick), document.removeEventListener("keydown", this._handleEscapeKey);
|
|
776
|
+
}
|
|
777
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
778
|
+
// Color Area Handlers
|
|
779
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
780
|
+
/**
|
|
781
|
+
* Handles pointer down events on the color area
|
|
782
|
+
* Starts saturation/value drag interaction
|
|
783
|
+
* @param event Pointer event
|
|
784
|
+
*/
|
|
785
|
+
_handleColorAreaPointerDown(t) {
|
|
786
|
+
this.disabled || this.readonly || (t.preventDefault(), this._isDraggingArea = !0, this._colorArea.setPointerCapture(t.pointerId), this._updateColorFromPointer(t));
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* Handles pointer move events on the color area during drag
|
|
790
|
+
* Updates color based on pointer position
|
|
791
|
+
* @param event Pointer event
|
|
792
|
+
*/
|
|
793
|
+
_handleColorAreaPointerMove(t) {
|
|
794
|
+
this._isDraggingArea && this._updateColorFromPointer(t);
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* Handles pointer up events on the color area
|
|
798
|
+
* Ends drag interaction and emits change event
|
|
799
|
+
* @param event Pointer event
|
|
800
|
+
*/
|
|
801
|
+
_handleColorAreaPointerUp(t) {
|
|
802
|
+
this._isDraggingArea && (this._isDraggingArea = !1, this._colorArea.releasePointerCapture(t.pointerId), this._emitChange());
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Updates color saturation and value based on pointer position in color area
|
|
806
|
+
* @param event Pointer event with clientX/clientY coordinates
|
|
807
|
+
*/
|
|
808
|
+
_updateColorFromPointer(t) {
|
|
809
|
+
const e = this._colorArea.getBoundingClientRect(), r = Math.max(0, Math.min(t.clientX - e.left, e.width)), a = Math.max(0, Math.min(t.clientY - e.top, e.height));
|
|
810
|
+
this._hsv = {
|
|
811
|
+
...this._hsv,
|
|
812
|
+
s: r / e.width * 100,
|
|
813
|
+
v: 100 - a / e.height * 100
|
|
814
|
+
}, this._hexInputValue = this._formatOutput("hex"), this._emitInput();
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* Handles keyboard navigation on the color area
|
|
818
|
+
* Arrow keys adjust saturation/value, Shift increases step size
|
|
819
|
+
* @param event Keyboard event
|
|
820
|
+
*/
|
|
821
|
+
_handleColorAreaKeydown(t) {
|
|
822
|
+
if (this.disabled || this.readonly) return;
|
|
823
|
+
const e = t.shiftKey ? 10 : 1;
|
|
824
|
+
let r = !1;
|
|
825
|
+
switch (t.key) {
|
|
826
|
+
case "ArrowRight":
|
|
827
|
+
this._hsv = { ...this._hsv, s: Math.min(100, this._hsv.s + e) }, r = !0;
|
|
828
|
+
break;
|
|
829
|
+
case "ArrowLeft":
|
|
830
|
+
this._hsv = { ...this._hsv, s: Math.max(0, this._hsv.s - e) }, r = !0;
|
|
831
|
+
break;
|
|
832
|
+
case "ArrowUp":
|
|
833
|
+
this._hsv = { ...this._hsv, v: Math.min(100, this._hsv.v + e) }, r = !0;
|
|
834
|
+
break;
|
|
835
|
+
case "ArrowDown":
|
|
836
|
+
this._hsv = { ...this._hsv, v: Math.max(0, this._hsv.v - e) }, r = !0;
|
|
837
|
+
break;
|
|
838
|
+
case "Home":
|
|
839
|
+
this._hsv = { ...this._hsv, s: 0 }, r = !0;
|
|
840
|
+
break;
|
|
841
|
+
case "End":
|
|
842
|
+
this._hsv = { ...this._hsv, s: 100 }, r = !0;
|
|
843
|
+
break;
|
|
844
|
+
}
|
|
845
|
+
r && (t.preventDefault(), this._hexInputValue = this._formatOutput("hex"), this._emitInput(), this._emitChange());
|
|
846
|
+
}
|
|
847
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
848
|
+
// Hue Slider Handlers
|
|
849
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
850
|
+
/**
|
|
851
|
+
* Handles pointer down events on the hue slider
|
|
852
|
+
* Starts hue drag interaction
|
|
853
|
+
* @param event Pointer event
|
|
854
|
+
*/
|
|
855
|
+
_handleHuePointerDown(t) {
|
|
856
|
+
this.disabled || this.readonly || (t.preventDefault(), this._isDraggingHue = !0, this._hueSlider.setPointerCapture(t.pointerId), this._updateHueFromPointer(t));
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* Handles pointer move events on the hue slider during drag
|
|
860
|
+
* Updates hue based on pointer position
|
|
861
|
+
* @param event Pointer event
|
|
862
|
+
*/
|
|
863
|
+
_handleHuePointerMove(t) {
|
|
864
|
+
this._isDraggingHue && this._updateHueFromPointer(t);
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Handles pointer up events on the hue slider
|
|
868
|
+
* Ends drag interaction and emits change event
|
|
869
|
+
* @param event Pointer event
|
|
870
|
+
*/
|
|
871
|
+
_handleHuePointerUp(t) {
|
|
872
|
+
this._isDraggingHue && (this._isDraggingHue = !1, this._hueSlider.releasePointerCapture(t.pointerId), this._emitChange());
|
|
873
|
+
}
|
|
874
|
+
/**
|
|
875
|
+
* Updates hue based on pointer position in hue slider
|
|
876
|
+
* @param event Pointer event with clientY coordinate
|
|
877
|
+
*/
|
|
878
|
+
_updateHueFromPointer(t) {
|
|
879
|
+
const e = this._hueSlider.getBoundingClientRect(), a = Math.max(0, Math.min(t.clientY - e.top, e.height)) / e.height * 360;
|
|
880
|
+
this._hsv = { ...this._hsv, h: a }, this._hexInputValue = this._formatOutput("hex"), this._emitInput();
|
|
881
|
+
}
|
|
882
|
+
/**
|
|
883
|
+
* Handles keyboard navigation on the hue slider
|
|
884
|
+
* Arrow keys adjust hue, Shift increases step size
|
|
885
|
+
* @param event Keyboard event
|
|
886
|
+
*/
|
|
887
|
+
_handleHueKeydown(t) {
|
|
888
|
+
if (this.disabled || this.readonly) return;
|
|
889
|
+
const e = t.shiftKey ? 10 : 1;
|
|
890
|
+
let r = !1;
|
|
891
|
+
switch (t.key) {
|
|
892
|
+
case "ArrowDown":
|
|
893
|
+
case "ArrowRight":
|
|
894
|
+
this._hsv = { ...this._hsv, h: (this._hsv.h + e) % 360 }, r = !0;
|
|
895
|
+
break;
|
|
896
|
+
case "ArrowUp":
|
|
897
|
+
case "ArrowLeft":
|
|
898
|
+
this._hsv = { ...this._hsv, h: (this._hsv.h - e + 360) % 360 }, r = !0;
|
|
899
|
+
break;
|
|
900
|
+
case "Home":
|
|
901
|
+
this._hsv = { ...this._hsv, h: 0 }, r = !0;
|
|
902
|
+
break;
|
|
903
|
+
case "End":
|
|
904
|
+
this._hsv = { ...this._hsv, h: 359 }, r = !0;
|
|
905
|
+
break;
|
|
906
|
+
}
|
|
907
|
+
r && (t.preventDefault(), this._hexInputValue = this._formatOutput("hex"), this._emitInput(), this._emitChange());
|
|
908
|
+
}
|
|
909
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
910
|
+
// Alpha Slider Handlers
|
|
911
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
912
|
+
/**
|
|
913
|
+
* Handles pointer down events on the alpha slider
|
|
914
|
+
* Starts alpha drag interaction
|
|
915
|
+
* @param event Pointer event
|
|
916
|
+
*/
|
|
917
|
+
_handleAlphaPointerDown(t) {
|
|
918
|
+
this.disabled || this.readonly || (t.preventDefault(), this._isDraggingAlpha = !0, this._alphaSlider.setPointerCapture(t.pointerId), this._updateAlphaFromPointer(t));
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Handles pointer move events on the alpha slider during drag
|
|
922
|
+
* Updates alpha based on pointer position
|
|
923
|
+
* @param event Pointer event
|
|
924
|
+
*/
|
|
925
|
+
_handleAlphaPointerMove(t) {
|
|
926
|
+
this._isDraggingAlpha && this._updateAlphaFromPointer(t);
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* Handles pointer up events on the alpha slider
|
|
930
|
+
* Ends drag interaction and emits change event
|
|
931
|
+
* @param event Pointer event
|
|
932
|
+
*/
|
|
933
|
+
_handleAlphaPointerUp(t) {
|
|
934
|
+
this._isDraggingAlpha && (this._isDraggingAlpha = !1, this._alphaSlider.releasePointerCapture(t.pointerId), this._emitChange());
|
|
935
|
+
}
|
|
936
|
+
/**
|
|
937
|
+
* Updates alpha based on pointer position in alpha slider
|
|
938
|
+
* @param event Pointer event with clientX coordinate
|
|
939
|
+
*/
|
|
940
|
+
_updateAlphaFromPointer(t) {
|
|
941
|
+
const e = this._alphaSlider.getBoundingClientRect(), a = Math.max(0, Math.min(t.clientX - e.left, e.width)) / e.width;
|
|
942
|
+
this._hsv = { ...this._hsv, a }, this._hexInputValue = this._formatOutput("hex"), this._emitInput();
|
|
943
|
+
}
|
|
944
|
+
/**
|
|
945
|
+
* Handles keyboard navigation on the alpha slider
|
|
946
|
+
* Arrow keys adjust alpha, Shift increases step size
|
|
947
|
+
* @param event Keyboard event
|
|
948
|
+
*/
|
|
949
|
+
_handleAlphaKeydown(t) {
|
|
950
|
+
if (this.disabled || this.readonly) return;
|
|
951
|
+
const e = t.shiftKey ? 0.1 : 0.01;
|
|
952
|
+
let r = !1;
|
|
953
|
+
switch (t.key) {
|
|
954
|
+
case "ArrowRight":
|
|
955
|
+
case "ArrowUp":
|
|
956
|
+
this._hsv = { ...this._hsv, a: Math.min(1, this._hsv.a + e) }, r = !0;
|
|
957
|
+
break;
|
|
958
|
+
case "ArrowLeft":
|
|
959
|
+
case "ArrowDown":
|
|
960
|
+
this._hsv = { ...this._hsv, a: Math.max(0, this._hsv.a - e) }, r = !0;
|
|
961
|
+
break;
|
|
962
|
+
case "Home":
|
|
963
|
+
this._hsv = { ...this._hsv, a: 0 }, r = !0;
|
|
964
|
+
break;
|
|
965
|
+
case "End":
|
|
966
|
+
this._hsv = { ...this._hsv, a: 1 }, r = !0;
|
|
967
|
+
break;
|
|
968
|
+
}
|
|
969
|
+
r && (t.preventDefault(), this._hexInputValue = this._formatOutput("hex"), this._emitInput(), this._emitChange());
|
|
970
|
+
}
|
|
971
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
972
|
+
// Input Handlers
|
|
973
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
974
|
+
/**
|
|
975
|
+
* Handles input events on the hex input field
|
|
976
|
+
* Updates controlled input value
|
|
977
|
+
* @param event Input event
|
|
978
|
+
*/
|
|
979
|
+
_handleHexInput(t) {
|
|
980
|
+
const e = t.target;
|
|
981
|
+
this._hexInputValue = e.value;
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Handles change events on the hex input field
|
|
985
|
+
* Parses and applies hex color value, adds # prefix if missing
|
|
986
|
+
* @param event Change event
|
|
987
|
+
*/
|
|
988
|
+
_handleHexChange(t) {
|
|
989
|
+
let r = t.target.value.trim();
|
|
990
|
+
r && !r.startsWith("#") && (r = "#" + r);
|
|
991
|
+
const a = g(r);
|
|
992
|
+
a ? (this._hsv = a, this._hexInputValue = this._formatOutput("hex"), this._emitInput(), this._emitChange()) : this._hexInputValue = this._formatOutput("hex");
|
|
993
|
+
}
|
|
994
|
+
/**
|
|
995
|
+
* Handles input events on RGB channel inputs
|
|
996
|
+
* Updates color based on red, green, or blue channel value
|
|
997
|
+
* @param channel RGB channel to update ('r', 'g', or 'b')
|
|
998
|
+
* @param event Input event
|
|
999
|
+
*/
|
|
1000
|
+
_handleRgbInput(t, e) {
|
|
1001
|
+
const r = e.target, a = Math.max(0, Math.min(255, parseInt(r.value, 10) || 0)), i = v(this._hsv);
|
|
1002
|
+
i[t] = a, this._hsv = g(`rgba(${i.r}, ${i.g}, ${i.b}, ${i.a})`), this._hexInputValue = this._formatOutput("hex"), this._emitInput();
|
|
1003
|
+
}
|
|
1004
|
+
/**
|
|
1005
|
+
* Handles change events on RGB inputs
|
|
1006
|
+
* Emits bp-change event
|
|
1007
|
+
*/
|
|
1008
|
+
_handleRgbChange() {
|
|
1009
|
+
this._emitChange();
|
|
1010
|
+
}
|
|
1011
|
+
/**
|
|
1012
|
+
* Handles input events on HSL channel inputs
|
|
1013
|
+
* Updates color based on hue, saturation, or lightness value
|
|
1014
|
+
* @param channel HSL channel to update ('h', 's', or 'l')
|
|
1015
|
+
* @param event Input event
|
|
1016
|
+
*/
|
|
1017
|
+
_handleHslInput(t, e) {
|
|
1018
|
+
const r = e.target, a = _(this._hsv);
|
|
1019
|
+
t === "h" ? a.h = Math.max(0, Math.min(360, parseInt(r.value, 10) || 0)) : a[t] = Math.max(0, Math.min(100, parseInt(r.value, 10) || 0)), this._hsv = g(`hsla(${a.h}, ${a.s}%, ${a.l}%, ${a.a})`), this._hexInputValue = this._formatOutput("hex"), this._emitInput();
|
|
1020
|
+
}
|
|
1021
|
+
/**
|
|
1022
|
+
* Handles change events on HSL inputs
|
|
1023
|
+
* Emits bp-change event
|
|
1024
|
+
*/
|
|
1025
|
+
_handleHslChange() {
|
|
1026
|
+
this._emitChange();
|
|
1027
|
+
}
|
|
1028
|
+
/**
|
|
1029
|
+
* Handles input events on the alpha percentage input
|
|
1030
|
+
* Updates alpha channel (0-100%)
|
|
1031
|
+
* @param event Input event
|
|
1032
|
+
*/
|
|
1033
|
+
_handleAlphaInput(t) {
|
|
1034
|
+
const e = t.target, r = Math.max(0, Math.min(100, parseInt(e.value, 10) || 0));
|
|
1035
|
+
this._hsv = { ...this._hsv, a: r / 100 }, this._hexInputValue = this._formatOutput("hex"), this._emitInput();
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Handles change events on alpha input
|
|
1039
|
+
* Emits bp-change event
|
|
1040
|
+
*/
|
|
1041
|
+
_handleAlphaInputChange() {
|
|
1042
|
+
this._emitChange();
|
|
1043
|
+
}
|
|
1044
|
+
/**
|
|
1045
|
+
* Handles format toggle button click
|
|
1046
|
+
* Cycles through hex → rgb → hsl input modes
|
|
1047
|
+
*/
|
|
1048
|
+
_handleFormatToggle() {
|
|
1049
|
+
const t = ["hex", "rgb", "hsl"], e = t.indexOf(this._inputMode);
|
|
1050
|
+
this._inputMode = t[(e + 1) % t.length];
|
|
1051
|
+
}
|
|
1052
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1053
|
+
// Swatch Handlers
|
|
1054
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1055
|
+
/**
|
|
1056
|
+
* Handles click events on predefined color swatches
|
|
1057
|
+
* Updates color to the swatch value
|
|
1058
|
+
* @param color Color string to apply
|
|
1059
|
+
*/
|
|
1060
|
+
_handleSwatchClick(t) {
|
|
1061
|
+
if (this.disabled || this.readonly) return;
|
|
1062
|
+
const e = g(t);
|
|
1063
|
+
e && (this._hsv = e, this._hexInputValue = this._formatOutput("hex"), this._emitInput(), this._emitChange());
|
|
1064
|
+
}
|
|
1065
|
+
/**
|
|
1066
|
+
* Handles keyboard events on swatch elements
|
|
1067
|
+
* Activates swatch on Enter or Space key
|
|
1068
|
+
* @param color Color string to apply
|
|
1069
|
+
* @param event Keyboard event
|
|
1070
|
+
*/
|
|
1071
|
+
_handleSwatchKeydown(t, e) {
|
|
1072
|
+
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), this._handleSwatchClick(t));
|
|
1073
|
+
}
|
|
1074
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1075
|
+
// Eyedropper
|
|
1076
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1077
|
+
/**
|
|
1078
|
+
* Handles eyedropper button click
|
|
1079
|
+
* Opens native EyeDropper API to pick color from screen
|
|
1080
|
+
* Only available in browsers that support the EyeDropper API
|
|
1081
|
+
*/
|
|
1082
|
+
async _handleEyedropper() {
|
|
1083
|
+
if (!(!this._eyedropperSupported || this.disabled || this.readonly)) {
|
|
1084
|
+
this._isPickingColor = !0;
|
|
1085
|
+
try {
|
|
1086
|
+
const e = await new EyeDropper().open();
|
|
1087
|
+
if (e.sRGBHex) {
|
|
1088
|
+
const r = g(e.sRGBHex);
|
|
1089
|
+
r && (this._hsv = r, this._hexInputValue = this._formatOutput("hex"), this._emitInput(), this._emitChange());
|
|
1090
|
+
}
|
|
1091
|
+
} catch {
|
|
1092
|
+
} finally {
|
|
1093
|
+
this._isPickingColor = !1;
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1098
|
+
// Event Emission
|
|
1099
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1100
|
+
/**
|
|
1101
|
+
* Emits bp-input event with current formatted color value
|
|
1102
|
+
* Fired during live color updates (dragging, typing)
|
|
1103
|
+
*/
|
|
1104
|
+
_emitInput() {
|
|
1105
|
+
const t = this._formatOutput();
|
|
1106
|
+
this.dispatchEvent(
|
|
1107
|
+
new CustomEvent("bp-input", {
|
|
1108
|
+
detail: { value: t },
|
|
1109
|
+
bubbles: !0,
|
|
1110
|
+
composed: !0
|
|
1111
|
+
})
|
|
1112
|
+
);
|
|
1113
|
+
}
|
|
1114
|
+
/**
|
|
1115
|
+
* Emits bp-change event and updates the value property
|
|
1116
|
+
* Fired on blur/confirm actions (drag end, input blur)
|
|
1117
|
+
*/
|
|
1118
|
+
_emitChange() {
|
|
1119
|
+
const t = this._formatOutput();
|
|
1120
|
+
this.value = t, this.dispatchEvent(
|
|
1121
|
+
new CustomEvent("bp-change", {
|
|
1122
|
+
detail: { value: t },
|
|
1123
|
+
bubbles: !0,
|
|
1124
|
+
composed: !0
|
|
1125
|
+
})
|
|
1126
|
+
);
|
|
1127
|
+
}
|
|
1128
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1129
|
+
// Rendering
|
|
1130
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1131
|
+
/**
|
|
1132
|
+
* Renders the 2D color area for saturation and value selection
|
|
1133
|
+
* @returns TemplateResult for color area with draggable handle
|
|
1134
|
+
*/
|
|
1135
|
+
_renderColorArea() {
|
|
1136
|
+
const t = `hsl(${this._hsv.h}, 100%, 50%)`, e = this._hsv.s, r = 100 - this._hsv.v;
|
|
1137
|
+
return l`
|
|
1138
|
+
<div
|
|
1139
|
+
class="color-area"
|
|
1140
|
+
part="color-area"
|
|
1141
|
+
role="slider"
|
|
1142
|
+
tabindex="${this.disabled ? -1 : 0}"
|
|
1143
|
+
aria-label="Color selection"
|
|
1144
|
+
aria-valuetext="Saturation ${Math.round(
|
|
1145
|
+
this._hsv.s
|
|
1146
|
+
)}%, Brightness ${Math.round(this._hsv.v)}%"
|
|
1147
|
+
style="--hue-color: ${t}"
|
|
1148
|
+
@pointerdown=${this._handleColorAreaPointerDown}
|
|
1149
|
+
@pointermove=${this._handleColorAreaPointerMove}
|
|
1150
|
+
@pointerup=${this._handleColorAreaPointerUp}
|
|
1151
|
+
@keydown=${this._handleColorAreaKeydown}
|
|
1152
|
+
>
|
|
1153
|
+
<div
|
|
1154
|
+
class="color-area-handle"
|
|
1155
|
+
style="left: ${e}%; top: ${r}%"
|
|
1156
|
+
></div>
|
|
1157
|
+
</div>
|
|
1158
|
+
`;
|
|
1159
|
+
}
|
|
1160
|
+
/**
|
|
1161
|
+
* Renders the vertical hue slider (0-360 degrees)
|
|
1162
|
+
* @returns TemplateResult for hue slider with draggable handle
|
|
1163
|
+
*/
|
|
1164
|
+
_renderHueSlider() {
|
|
1165
|
+
const t = this._hsv.h / 360 * 100;
|
|
1166
|
+
return l`
|
|
1167
|
+
<div
|
|
1168
|
+
class="hue-slider"
|
|
1169
|
+
part="hue-slider"
|
|
1170
|
+
role="slider"
|
|
1171
|
+
tabindex="${this.disabled ? -1 : 0}"
|
|
1172
|
+
aria-label="Hue"
|
|
1173
|
+
aria-valuenow="${Math.round(this._hsv.h)}"
|
|
1174
|
+
aria-valuemin="0"
|
|
1175
|
+
aria-valuemax="360"
|
|
1176
|
+
@pointerdown=${this._handleHuePointerDown}
|
|
1177
|
+
@pointermove=${this._handleHuePointerMove}
|
|
1178
|
+
@pointerup=${this._handleHuePointerUp}
|
|
1179
|
+
@keydown=${this._handleHueKeydown}
|
|
1180
|
+
>
|
|
1181
|
+
<div class="hue-slider-handle" style="top: ${t}%"></div>
|
|
1182
|
+
</div>
|
|
1183
|
+
`;
|
|
1184
|
+
}
|
|
1185
|
+
/**
|
|
1186
|
+
* Renders the horizontal alpha slider (0-100%)
|
|
1187
|
+
* Only shown when alpha property is true
|
|
1188
|
+
* @returns TemplateResult for alpha slider or nothing
|
|
1189
|
+
*/
|
|
1190
|
+
_renderAlphaSlider() {
|
|
1191
|
+
if (!this.alpha) return c;
|
|
1192
|
+
const t = v(this._hsv), e = `rgba(${t.r}, ${t.g}, ${t.b}, 0)`, r = `rgba(${t.r}, ${t.g}, ${t.b}, 1)`, a = this._hsv.a * 100;
|
|
1193
|
+
return l`
|
|
1194
|
+
<div
|
|
1195
|
+
class="alpha-slider"
|
|
1196
|
+
part="alpha-slider"
|
|
1197
|
+
role="slider"
|
|
1198
|
+
tabindex="${this.disabled ? -1 : 0}"
|
|
1199
|
+
aria-label="Opacity"
|
|
1200
|
+
aria-valuenow="${Math.round(this._hsv.a * 100)}"
|
|
1201
|
+
aria-valuemin="0"
|
|
1202
|
+
aria-valuemax="100"
|
|
1203
|
+
style="--alpha-gradient: linear-gradient(to right, ${e}, ${r})"
|
|
1204
|
+
@pointerdown=${this._handleAlphaPointerDown}
|
|
1205
|
+
@pointermove=${this._handleAlphaPointerMove}
|
|
1206
|
+
@pointerup=${this._handleAlphaPointerUp}
|
|
1207
|
+
@keydown=${this._handleAlphaKeydown}
|
|
1208
|
+
>
|
|
1209
|
+
<div class="alpha-slider-handle" style="left: ${a}%"></div>
|
|
1210
|
+
</div>
|
|
1211
|
+
`;
|
|
1212
|
+
}
|
|
1213
|
+
/**
|
|
1214
|
+
* Renders the color preview showing original and current colors
|
|
1215
|
+
* Displays side-by-side comparison with checkerboard background for transparency
|
|
1216
|
+
* @returns TemplateResult for preview swatches
|
|
1217
|
+
*/
|
|
1218
|
+
_renderPreview() {
|
|
1219
|
+
const t = v(this._hsv), e = `rgba(${t.r}, ${t.g}, ${t.b}, ${this._hsv.a})`, r = g(this._originalValue), a = r ? (() => {
|
|
1220
|
+
const i = v(r);
|
|
1221
|
+
return `rgba(${i.r}, ${i.g}, ${i.b}, ${r.a})`;
|
|
1222
|
+
})() : e;
|
|
1223
|
+
return l`
|
|
1224
|
+
<div class="preview" part="preview">
|
|
1225
|
+
<div
|
|
1226
|
+
class="preview-swatch preview-original"
|
|
1227
|
+
style="background: ${a}"
|
|
1228
|
+
title="Original color"
|
|
1229
|
+
aria-label="Original color"
|
|
1230
|
+
></div>
|
|
1231
|
+
<div
|
|
1232
|
+
class="preview-swatch preview-current"
|
|
1233
|
+
style="background: ${e}"
|
|
1234
|
+
title="Current color"
|
|
1235
|
+
aria-label="Current color"
|
|
1236
|
+
></div>
|
|
1237
|
+
</div>
|
|
1238
|
+
`;
|
|
1239
|
+
}
|
|
1240
|
+
/**
|
|
1241
|
+
* Renders the hex color input field
|
|
1242
|
+
* @returns TemplateResult for hex input group
|
|
1243
|
+
*/
|
|
1244
|
+
_renderHexInput() {
|
|
1245
|
+
return l`
|
|
1246
|
+
<div class="input-group">
|
|
1247
|
+
<input
|
|
1248
|
+
type="text"
|
|
1249
|
+
class="color-input hex-input"
|
|
1250
|
+
part="input"
|
|
1251
|
+
.value=${this._hexInputValue}
|
|
1252
|
+
?disabled=${this.disabled}
|
|
1253
|
+
?readonly=${this.readonly}
|
|
1254
|
+
@input=${this._handleHexInput}
|
|
1255
|
+
@change=${this._handleHexChange}
|
|
1256
|
+
aria-label="Hex color value"
|
|
1257
|
+
/>
|
|
1258
|
+
<span class="input-label">HEX</span>
|
|
1259
|
+
</div>
|
|
1260
|
+
`;
|
|
1261
|
+
}
|
|
1262
|
+
/**
|
|
1263
|
+
* Renders RGB color input fields (R, G, B, and optionally A)
|
|
1264
|
+
* @returns TemplateResult for RGB input row
|
|
1265
|
+
*/
|
|
1266
|
+
_renderRgbInputs() {
|
|
1267
|
+
const t = v(this._hsv);
|
|
1268
|
+
return l`
|
|
1269
|
+
<div class="input-row">
|
|
1270
|
+
<div class="input-group">
|
|
1271
|
+
<input
|
|
1272
|
+
type="number"
|
|
1273
|
+
class="color-input"
|
|
1274
|
+
part="input"
|
|
1275
|
+
min="0"
|
|
1276
|
+
max="255"
|
|
1277
|
+
.value=${String(t.r)}
|
|
1278
|
+
?disabled=${this.disabled}
|
|
1279
|
+
?readonly=${this.readonly}
|
|
1280
|
+
@input=${(e) => this._handleRgbInput("r", e)}
|
|
1281
|
+
@change=${this._handleRgbChange}
|
|
1282
|
+
aria-label="Red"
|
|
1283
|
+
/>
|
|
1284
|
+
<span class="input-label">R</span>
|
|
1285
|
+
</div>
|
|
1286
|
+
<div class="input-group">
|
|
1287
|
+
<input
|
|
1288
|
+
type="number"
|
|
1289
|
+
class="color-input"
|
|
1290
|
+
part="input"
|
|
1291
|
+
min="0"
|
|
1292
|
+
max="255"
|
|
1293
|
+
.value=${String(t.g)}
|
|
1294
|
+
?disabled=${this.disabled}
|
|
1295
|
+
?readonly=${this.readonly}
|
|
1296
|
+
@input=${(e) => this._handleRgbInput("g", e)}
|
|
1297
|
+
@change=${this._handleRgbChange}
|
|
1298
|
+
aria-label="Green"
|
|
1299
|
+
/>
|
|
1300
|
+
<span class="input-label">G</span>
|
|
1301
|
+
</div>
|
|
1302
|
+
<div class="input-group">
|
|
1303
|
+
<input
|
|
1304
|
+
type="number"
|
|
1305
|
+
class="color-input"
|
|
1306
|
+
part="input"
|
|
1307
|
+
min="0"
|
|
1308
|
+
max="255"
|
|
1309
|
+
.value=${String(t.b)}
|
|
1310
|
+
?disabled=${this.disabled}
|
|
1311
|
+
?readonly=${this.readonly}
|
|
1312
|
+
@input=${(e) => this._handleRgbInput("b", e)}
|
|
1313
|
+
@change=${this._handleRgbChange}
|
|
1314
|
+
aria-label="Blue"
|
|
1315
|
+
/>
|
|
1316
|
+
<span class="input-label">B</span>
|
|
1317
|
+
</div>
|
|
1318
|
+
${this.alpha ? l`
|
|
1319
|
+
<div class="input-group">
|
|
1320
|
+
<input
|
|
1321
|
+
type="number"
|
|
1322
|
+
class="color-input"
|
|
1323
|
+
part="input"
|
|
1324
|
+
min="0"
|
|
1325
|
+
max="100"
|
|
1326
|
+
.value=${String(Math.round(this._hsv.a * 100))}
|
|
1327
|
+
?disabled=${this.disabled}
|
|
1328
|
+
?readonly=${this.readonly}
|
|
1329
|
+
@input=${this._handleAlphaInput}
|
|
1330
|
+
@change=${this._handleAlphaInputChange}
|
|
1331
|
+
aria-label="Alpha"
|
|
1332
|
+
/>
|
|
1333
|
+
<span class="input-label">A</span>
|
|
1334
|
+
</div>
|
|
1335
|
+
` : c}
|
|
1336
|
+
</div>
|
|
1337
|
+
`;
|
|
1338
|
+
}
|
|
1339
|
+
/**
|
|
1340
|
+
* Renders HSL color input fields (H, S, L, and optionally A)
|
|
1341
|
+
* @returns TemplateResult for HSL input row
|
|
1342
|
+
*/
|
|
1343
|
+
_renderHslInputs() {
|
|
1344
|
+
const t = _(this._hsv);
|
|
1345
|
+
return l`
|
|
1346
|
+
<div class="input-row">
|
|
1347
|
+
<div class="input-group">
|
|
1348
|
+
<input
|
|
1349
|
+
type="number"
|
|
1350
|
+
class="color-input"
|
|
1351
|
+
part="input"
|
|
1352
|
+
min="0"
|
|
1353
|
+
max="360"
|
|
1354
|
+
.value=${String(Math.round(t.h))}
|
|
1355
|
+
?disabled=${this.disabled}
|
|
1356
|
+
?readonly=${this.readonly}
|
|
1357
|
+
@input=${(e) => this._handleHslInput("h", e)}
|
|
1358
|
+
@change=${this._handleHslChange}
|
|
1359
|
+
aria-label="Hue"
|
|
1360
|
+
/>
|
|
1361
|
+
<span class="input-label">H</span>
|
|
1362
|
+
</div>
|
|
1363
|
+
<div class="input-group">
|
|
1364
|
+
<input
|
|
1365
|
+
type="number"
|
|
1366
|
+
class="color-input"
|
|
1367
|
+
part="input"
|
|
1368
|
+
min="0"
|
|
1369
|
+
max="100"
|
|
1370
|
+
.value=${String(Math.round(t.s))}
|
|
1371
|
+
?disabled=${this.disabled}
|
|
1372
|
+
?readonly=${this.readonly}
|
|
1373
|
+
@input=${(e) => this._handleHslInput("s", e)}
|
|
1374
|
+
@change=${this._handleHslChange}
|
|
1375
|
+
aria-label="Saturation"
|
|
1376
|
+
/>
|
|
1377
|
+
<span class="input-label">S</span>
|
|
1378
|
+
</div>
|
|
1379
|
+
<div class="input-group">
|
|
1380
|
+
<input
|
|
1381
|
+
type="number"
|
|
1382
|
+
class="color-input"
|
|
1383
|
+
part="input"
|
|
1384
|
+
min="0"
|
|
1385
|
+
max="100"
|
|
1386
|
+
.value=${String(Math.round(t.l))}
|
|
1387
|
+
?disabled=${this.disabled}
|
|
1388
|
+
?readonly=${this.readonly}
|
|
1389
|
+
@input=${(e) => this._handleHslInput("l", e)}
|
|
1390
|
+
@change=${this._handleHslChange}
|
|
1391
|
+
aria-label="Lightness"
|
|
1392
|
+
/>
|
|
1393
|
+
<span class="input-label">L</span>
|
|
1394
|
+
</div>
|
|
1395
|
+
${this.alpha ? l`
|
|
1396
|
+
<div class="input-group">
|
|
1397
|
+
<input
|
|
1398
|
+
type="number"
|
|
1399
|
+
class="color-input"
|
|
1400
|
+
part="input"
|
|
1401
|
+
min="0"
|
|
1402
|
+
max="100"
|
|
1403
|
+
.value=${String(Math.round(this._hsv.a * 100))}
|
|
1404
|
+
?disabled=${this.disabled}
|
|
1405
|
+
?readonly=${this.readonly}
|
|
1406
|
+
@input=${this._handleAlphaInput}
|
|
1407
|
+
@change=${this._handleAlphaInputChange}
|
|
1408
|
+
aria-label="Alpha"
|
|
1409
|
+
/>
|
|
1410
|
+
<span class="input-label">A</span>
|
|
1411
|
+
</div>
|
|
1412
|
+
` : c}
|
|
1413
|
+
</div>
|
|
1414
|
+
`;
|
|
1415
|
+
}
|
|
1416
|
+
/**
|
|
1417
|
+
* Renders the input controls container with format toggle button
|
|
1418
|
+
* Shows hex, rgb, or hsl inputs based on current input mode
|
|
1419
|
+
* @returns TemplateResult for inputs container
|
|
1420
|
+
*/
|
|
1421
|
+
_renderInputs() {
|
|
1422
|
+
return l`
|
|
1423
|
+
<div class="inputs-container">
|
|
1424
|
+
${this._inputMode === "hex" ? this._renderHexInput() : c}
|
|
1425
|
+
${this._inputMode === "rgb" ? this._renderRgbInputs() : c}
|
|
1426
|
+
${this._inputMode === "hsl" ? this._renderHslInputs() : c}
|
|
1427
|
+
<button
|
|
1428
|
+
type="button"
|
|
1429
|
+
class="format-toggle"
|
|
1430
|
+
@click=${this._handleFormatToggle}
|
|
1431
|
+
?disabled=${this.disabled}
|
|
1432
|
+
aria-label="Cycle color format (${this._inputMode.toUpperCase()})"
|
|
1433
|
+
title="Cycle color format"
|
|
1434
|
+
>
|
|
1435
|
+
<svg
|
|
1436
|
+
viewBox="0 0 24 24"
|
|
1437
|
+
fill="none"
|
|
1438
|
+
stroke="currentColor"
|
|
1439
|
+
stroke-width="2"
|
|
1440
|
+
stroke-linecap="round"
|
|
1441
|
+
stroke-linejoin="round"
|
|
1442
|
+
>
|
|
1443
|
+
<path
|
|
1444
|
+
d="M21.5 2v6h-6M2.5 22v-6h6M2 11.5a10 10 0 0 1 18.8-4.3M22 12.5a10 10 0 0 1-18.8 4.2"
|
|
1445
|
+
/>
|
|
1446
|
+
</svg>
|
|
1447
|
+
</button>
|
|
1448
|
+
</div>
|
|
1449
|
+
`;
|
|
1450
|
+
}
|
|
1451
|
+
/**
|
|
1452
|
+
* Renders predefined color swatches
|
|
1453
|
+
* Shows swatches from the swatches property or slotted content
|
|
1454
|
+
* @returns TemplateResult for swatches container or nothing
|
|
1455
|
+
*/
|
|
1456
|
+
_renderSwatches() {
|
|
1457
|
+
const t = this.swatches.length > 0, e = this.querySelector('[slot="swatches"]') !== null;
|
|
1458
|
+
return !t && !e ? c : l`
|
|
1459
|
+
<div
|
|
1460
|
+
class="swatches-container"
|
|
1461
|
+
part="swatches"
|
|
1462
|
+
role="listbox"
|
|
1463
|
+
aria-label="Color swatches"
|
|
1464
|
+
>
|
|
1465
|
+
<slot name="swatches">
|
|
1466
|
+
${this.swatches.map(
|
|
1467
|
+
(r) => l`
|
|
1468
|
+
<button
|
|
1469
|
+
type="button"
|
|
1470
|
+
class="swatch"
|
|
1471
|
+
part="swatch"
|
|
1472
|
+
role="option"
|
|
1473
|
+
style="background: ${r}"
|
|
1474
|
+
@click=${() => this._handleSwatchClick(r)}
|
|
1475
|
+
@keydown=${(a) => this._handleSwatchKeydown(r, a)}
|
|
1476
|
+
?disabled=${this.disabled}
|
|
1477
|
+
aria-label="${r}"
|
|
1478
|
+
></button>
|
|
1479
|
+
`
|
|
1480
|
+
)}
|
|
1481
|
+
</slot>
|
|
1482
|
+
</div>
|
|
1483
|
+
`;
|
|
1484
|
+
}
|
|
1485
|
+
/**
|
|
1486
|
+
* Renders the eyedropper button if API is supported
|
|
1487
|
+
* @returns TemplateResult for eyedropper button or nothing
|
|
1488
|
+
*/
|
|
1489
|
+
_renderEyedropper() {
|
|
1490
|
+
return this._eyedropperSupported ? l`
|
|
1491
|
+
<button
|
|
1492
|
+
type="button"
|
|
1493
|
+
class="eyedropper-button"
|
|
1494
|
+
@click=${this._handleEyedropper}
|
|
1495
|
+
?disabled=${this.disabled || this.readonly || this._isPickingColor}
|
|
1496
|
+
aria-label="Pick color from screen"
|
|
1497
|
+
aria-busy="${this._isPickingColor}"
|
|
1498
|
+
>
|
|
1499
|
+
<svg
|
|
1500
|
+
viewBox="0 0 24 24"
|
|
1501
|
+
fill="none"
|
|
1502
|
+
stroke="currentColor"
|
|
1503
|
+
stroke-width="2"
|
|
1504
|
+
>
|
|
1505
|
+
<path d="M2 22l1-1h3l9-9m-3-3l3-3 5 5-3 3m-5-5l5 5M12.5 6.5l5 5" />
|
|
1506
|
+
</svg>
|
|
1507
|
+
</button>
|
|
1508
|
+
` : c;
|
|
1509
|
+
}
|
|
1510
|
+
/**
|
|
1511
|
+
* Renders the complete color picker panel
|
|
1512
|
+
* Includes color area, sliders, preview, inputs, and swatches
|
|
1513
|
+
* @returns TemplateResult for picker panel
|
|
1514
|
+
*/
|
|
1515
|
+
_renderPicker() {
|
|
1516
|
+
return l`
|
|
1517
|
+
<div
|
|
1518
|
+
class="picker"
|
|
1519
|
+
part="popover"
|
|
1520
|
+
role="dialog"
|
|
1521
|
+
aria-label="${this.label || "Color picker"}"
|
|
1522
|
+
>
|
|
1523
|
+
<div class="picker-body">
|
|
1524
|
+
<div class="picker-main">
|
|
1525
|
+
${this._renderColorArea()} ${this._renderHueSlider()}
|
|
1526
|
+
</div>
|
|
1527
|
+
${this._renderAlphaSlider()}
|
|
1528
|
+
<div class="picker-controls">
|
|
1529
|
+
${this._renderPreview()} ${this._renderInputs()}
|
|
1530
|
+
${this._renderEyedropper()}
|
|
1531
|
+
</div>
|
|
1532
|
+
${this._renderSwatches()}
|
|
1533
|
+
<slot name="footer"></slot>
|
|
1534
|
+
</div>
|
|
1535
|
+
</div>
|
|
1536
|
+
`;
|
|
1537
|
+
}
|
|
1538
|
+
/**
|
|
1539
|
+
* Renders the trigger button to open the picker popover
|
|
1540
|
+
* Shows current color swatch and optional label
|
|
1541
|
+
* @returns TemplateResult for trigger button
|
|
1542
|
+
*/
|
|
1543
|
+
_renderTrigger() {
|
|
1544
|
+
const t = v(this._hsv), e = `rgba(${t.r}, ${t.g}, ${t.b}, ${this._hsv.a})`, r = this.label || this.placeholder;
|
|
1545
|
+
return l`
|
|
1546
|
+
<button
|
|
1547
|
+
type="button"
|
|
1548
|
+
class="trigger"
|
|
1549
|
+
part="trigger"
|
|
1550
|
+
role="button"
|
|
1551
|
+
aria-haspopup="dialog"
|
|
1552
|
+
aria-expanded="${this._open}"
|
|
1553
|
+
aria-disabled="${this.disabled}"
|
|
1554
|
+
tabindex="${this.disabled ? -1 : 0}"
|
|
1555
|
+
?disabled=${this.disabled}
|
|
1556
|
+
@click=${this._handleTriggerClick}
|
|
1557
|
+
@keydown=${this._handleTriggerKeydown}
|
|
1558
|
+
>
|
|
1559
|
+
<slot name="trigger">
|
|
1560
|
+
<span
|
|
1561
|
+
class="trigger-swatch"
|
|
1562
|
+
style="background: ${e}"
|
|
1563
|
+
></span>
|
|
1564
|
+
${r ? l`<span class="trigger-label"
|
|
1565
|
+
>${this.label || this.placeholder}</span
|
|
1566
|
+
>` : c}
|
|
1567
|
+
</slot>
|
|
1568
|
+
</button>
|
|
1569
|
+
`;
|
|
1570
|
+
}
|
|
1571
|
+
render() {
|
|
1572
|
+
return this.inline ? this._renderPicker() : l`
|
|
1573
|
+
<div class="color-picker color-picker--${this.size}">
|
|
1574
|
+
${this._renderTrigger()}
|
|
1575
|
+
${this._open ? l`
|
|
1576
|
+
<div aria-live="polite" aria-atomic="true" class="sr-only">
|
|
1577
|
+
Current color: ${this._formatOutput()}
|
|
1578
|
+
</div>
|
|
1579
|
+
${this._renderPicker()}
|
|
1580
|
+
` : c}
|
|
1581
|
+
</div>
|
|
1582
|
+
${this.name ? l`<input
|
|
1583
|
+
type="hidden"
|
|
1584
|
+
name="${this.name}"
|
|
1585
|
+
.value=${this._formatOutput()}
|
|
1586
|
+
/>` : c}
|
|
1587
|
+
`;
|
|
1588
|
+
}
|
|
1589
|
+
};
|
|
1590
|
+
s.styles = [I];
|
|
1591
|
+
o([
|
|
1592
|
+
u({ type: String })
|
|
1593
|
+
], s.prototype, "value", 2);
|
|
1594
|
+
o([
|
|
1595
|
+
u({ type: String })
|
|
1596
|
+
], s.prototype, "format", 2);
|
|
1597
|
+
o([
|
|
1598
|
+
u({ converter: C, reflect: !0 })
|
|
1599
|
+
], s.prototype, "alpha", 2);
|
|
1600
|
+
o([
|
|
1601
|
+
u({ type: Array })
|
|
1602
|
+
], s.prototype, "swatches", 2);
|
|
1603
|
+
o([
|
|
1604
|
+
u({ type: Boolean })
|
|
1605
|
+
], s.prototype, "inline", 2);
|
|
1606
|
+
o([
|
|
1607
|
+
u({ type: Boolean, reflect: !0 })
|
|
1608
|
+
], s.prototype, "disabled", 2);
|
|
1609
|
+
o([
|
|
1610
|
+
u({ type: Boolean, reflect: !0 })
|
|
1611
|
+
], s.prototype, "readonly", 2);
|
|
1612
|
+
o([
|
|
1613
|
+
u({ type: String, reflect: !0 })
|
|
1614
|
+
], s.prototype, "size", 2);
|
|
1615
|
+
o([
|
|
1616
|
+
u({ type: String })
|
|
1617
|
+
], s.prototype, "label", 2);
|
|
1618
|
+
o([
|
|
1619
|
+
u({ type: String })
|
|
1620
|
+
], s.prototype, "name", 2);
|
|
1621
|
+
o([
|
|
1622
|
+
u({ type: String })
|
|
1623
|
+
], s.prototype, "placeholder", 2);
|
|
1624
|
+
o([
|
|
1625
|
+
f()
|
|
1626
|
+
], s.prototype, "_open", 2);
|
|
1627
|
+
o([
|
|
1628
|
+
f()
|
|
1629
|
+
], s.prototype, "_hsv", 2);
|
|
1630
|
+
o([
|
|
1631
|
+
f()
|
|
1632
|
+
], s.prototype, "_originalValue", 2);
|
|
1633
|
+
o([
|
|
1634
|
+
f()
|
|
1635
|
+
], s.prototype, "_eyedropperSupported", 2);
|
|
1636
|
+
o([
|
|
1637
|
+
f()
|
|
1638
|
+
], s.prototype, "_inputMode", 2);
|
|
1639
|
+
o([
|
|
1640
|
+
f()
|
|
1641
|
+
], s.prototype, "_hexInputValue", 2);
|
|
1642
|
+
o([
|
|
1643
|
+
f()
|
|
1644
|
+
], s.prototype, "_isPickingColor", 2);
|
|
1645
|
+
o([
|
|
1646
|
+
m(".color-area")
|
|
1647
|
+
], s.prototype, "_colorArea", 2);
|
|
1648
|
+
o([
|
|
1649
|
+
m(".hue-slider")
|
|
1650
|
+
], s.prototype, "_hueSlider", 2);
|
|
1651
|
+
o([
|
|
1652
|
+
m(".alpha-slider")
|
|
1653
|
+
], s.prototype, "_alphaSlider", 2);
|
|
1654
|
+
s = o([
|
|
1655
|
+
k("bp-color-picker")
|
|
1656
|
+
], s);
|
|
1657
|
+
export {
|
|
1658
|
+
s as BpColorPicker
|
|
1659
|
+
};
|
|
1660
|
+
//# sourceMappingURL=color-picker.js.map
|