@nanahoshi/mona-ui 0.1.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/README.md +25 -0
- package/fesm2022/nanahoshi-mona-ui-auto-complete.mjs +590 -0
- package/fesm2022/nanahoshi-mona-ui-avatar.mjs +168 -0
- package/fesm2022/nanahoshi-mona-ui-breadcrumb.mjs +220 -0
- package/fesm2022/nanahoshi-mona-ui-button-group.mjs +225 -0
- package/fesm2022/nanahoshi-mona-ui-button.mjs +497 -0
- package/fesm2022/nanahoshi-mona-ui-calendar.mjs +1569 -0
- package/fesm2022/nanahoshi-mona-ui-check-box.mjs +339 -0
- package/fesm2022/nanahoshi-mona-ui-chip.mjs +453 -0
- package/fesm2022/nanahoshi-mona-ui-circular-progress-bar.mjs +200 -0
- package/fesm2022/nanahoshi-mona-ui-color-gradient.mjs +853 -0
- package/fesm2022/nanahoshi-mona-ui-color-palette.mjs +923 -0
- package/fesm2022/nanahoshi-mona-ui-color-picker.mjs +495 -0
- package/fesm2022/nanahoshi-mona-ui-combo-box.mjs +686 -0
- package/fesm2022/nanahoshi-mona-ui-common.mjs +642 -0
- package/fesm2022/nanahoshi-mona-ui-contextmenu.mjs +485 -0
- package/fesm2022/nanahoshi-mona-ui-date-input.mjs +132 -0
- package/fesm2022/nanahoshi-mona-ui-date-picker.mjs +460 -0
- package/fesm2022/nanahoshi-mona-ui-datetime-picker.mjs +659 -0
- package/fesm2022/nanahoshi-mona-ui-dialog.mjs +828 -0
- package/fesm2022/nanahoshi-mona-ui-dropdown-button.mjs +523 -0
- package/fesm2022/nanahoshi-mona-ui-dropdown-list.mjs +615 -0
- package/fesm2022/nanahoshi-mona-ui-dropdowns.mjs +701 -0
- package/fesm2022/nanahoshi-mona-ui-editor.mjs +1400 -0
- package/fesm2022/nanahoshi-mona-ui-expansion-panel.mjs +245 -0
- package/fesm2022/nanahoshi-mona-ui-fieldset.mjs +170 -0
- package/fesm2022/nanahoshi-mona-ui-filter.mjs +680 -0
- package/fesm2022/nanahoshi-mona-ui-grid-grid-footer-cell.component-B9SQH5N-.mjs +105 -0
- package/fesm2022/nanahoshi-mona-ui-grid-grid-footer-table-cell.directive-DlLwcCFT.mjs +42 -0
- package/fesm2022/nanahoshi-mona-ui-grid-grid-list.component-Dgea-O0X.mjs +130 -0
- package/fesm2022/nanahoshi-mona-ui-grid-grid-toggle.component-DIUutx9s.mjs +773 -0
- package/fesm2022/nanahoshi-mona-ui-grid-grid-virtual-list.component-DRHycGIh.mjs +240 -0
- package/fesm2022/nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-C3eZIaJK.mjs +5374 -0
- package/fesm2022/nanahoshi-mona-ui-grid.mjs +2 -0
- package/fesm2022/nanahoshi-mona-ui-internal-filter-input.mjs +87 -0
- package/fesm2022/nanahoshi-mona-ui-internal-indicator-icon.mjs +154 -0
- package/fesm2022/nanahoshi-mona-ui-internal-list.mjs +1356 -0
- package/fesm2022/nanahoshi-mona-ui-internal-tree.mjs +2263 -0
- package/fesm2022/nanahoshi-mona-ui-internal.mjs +379 -0
- package/fesm2022/nanahoshi-mona-ui-list-box.mjs +630 -0
- package/fesm2022/nanahoshi-mona-ui-list-view.mjs +527 -0
- package/fesm2022/nanahoshi-mona-ui-list.mjs +4 -0
- package/fesm2022/nanahoshi-mona-ui-menubar.mjs +966 -0
- package/fesm2022/nanahoshi-mona-ui-multi-select.mjs +641 -0
- package/fesm2022/nanahoshi-mona-ui-notification.mjs +536 -0
- package/fesm2022/nanahoshi-mona-ui-numeric-text-box.mjs +597 -0
- package/fesm2022/nanahoshi-mona-ui-pager.mjs +790 -0
- package/fesm2022/nanahoshi-mona-ui-placeholder.mjs +83 -0
- package/fesm2022/nanahoshi-mona-ui-popover.mjs +325 -0
- package/fesm2022/nanahoshi-mona-ui-popup-menu.mjs +1559 -0
- package/fesm2022/nanahoshi-mona-ui-popup.mjs +1321 -0
- package/fesm2022/nanahoshi-mona-ui-progress-bar.mjs +294 -0
- package/fesm2022/nanahoshi-mona-ui-query.mjs +175 -0
- package/fesm2022/nanahoshi-mona-ui-radio-button.mjs +339 -0
- package/fesm2022/nanahoshi-mona-ui-scroll-view.mjs +565 -0
- package/fesm2022/nanahoshi-mona-ui-slider.mjs +1049 -0
- package/fesm2022/nanahoshi-mona-ui-split-button.mjs +636 -0
- package/fesm2022/nanahoshi-mona-ui-splitter.mjs +843 -0
- package/fesm2022/nanahoshi-mona-ui-stepper.mjs +537 -0
- package/fesm2022/nanahoshi-mona-ui-switch.mjs +308 -0
- package/fesm2022/nanahoshi-mona-ui-tabs.mjs +664 -0
- package/fesm2022/nanahoshi-mona-ui-text-area.mjs +111 -0
- package/fesm2022/nanahoshi-mona-ui-text-box.mjs +369 -0
- package/fesm2022/nanahoshi-mona-ui-theme.mjs +314 -0
- package/fesm2022/nanahoshi-mona-ui-time-picker.mjs +450 -0
- package/fesm2022/nanahoshi-mona-ui-time-selector.mjs +723 -0
- package/fesm2022/nanahoshi-mona-ui-tooltip.mjs +716 -0
- package/fesm2022/nanahoshi-mona-ui-tree-view.mjs +733 -0
- package/fesm2022/nanahoshi-mona-ui-window.mjs +1329 -0
- package/fesm2022/nanahoshi-mona-ui.mjs +9 -0
- package/package.json +289 -0
- package/types/nanahoshi-mona-ui-auto-complete.d.ts +223 -0
- package/types/nanahoshi-mona-ui-avatar.d.ts +642 -0
- package/types/nanahoshi-mona-ui-breadcrumb.d.ts +70 -0
- package/types/nanahoshi-mona-ui-button-group.d.ts +77 -0
- package/types/nanahoshi-mona-ui-button.d.ts +111 -0
- package/types/nanahoshi-mona-ui-calendar.d.ts +262 -0
- package/types/nanahoshi-mona-ui-check-box.d.ts +133 -0
- package/types/nanahoshi-mona-ui-chip.d.ts +130 -0
- package/types/nanahoshi-mona-ui-circular-progress-bar.d.ts +113 -0
- package/types/nanahoshi-mona-ui-color-gradient.d.ts +201 -0
- package/types/nanahoshi-mona-ui-color-palette.d.ts +102 -0
- package/types/nanahoshi-mona-ui-color-picker.d.ts +156 -0
- package/types/nanahoshi-mona-ui-combo-box.d.ts +232 -0
- package/types/nanahoshi-mona-ui-common.d.ts +386 -0
- package/types/nanahoshi-mona-ui-contextmenu.d.ts +129 -0
- package/types/nanahoshi-mona-ui-date-input.d.ts +60 -0
- package/types/nanahoshi-mona-ui-date-picker.d.ts +177 -0
- package/types/nanahoshi-mona-ui-datetime-picker.d.ts +199 -0
- package/types/nanahoshi-mona-ui-dialog.d.ts +261 -0
- package/types/nanahoshi-mona-ui-dropdown-button.d.ts +159 -0
- package/types/nanahoshi-mona-ui-dropdown-list.d.ts +219 -0
- package/types/nanahoshi-mona-ui-dropdowns.d.ts +176 -0
- package/types/nanahoshi-mona-ui-editor.d.ts +113 -0
- package/types/nanahoshi-mona-ui-expansion-panel.d.ts +87 -0
- package/types/nanahoshi-mona-ui-fieldset.d.ts +68 -0
- package/types/nanahoshi-mona-ui-filter.d.ts +115 -0
- package/types/nanahoshi-mona-ui-grid.d.ts +1114 -0
- package/types/nanahoshi-mona-ui-internal-filter-input.d.ts +25 -0
- package/types/nanahoshi-mona-ui-internal-indicator-icon.d.ts +28 -0
- package/types/nanahoshi-mona-ui-internal-list.d.ts +269 -0
- package/types/nanahoshi-mona-ui-internal-tree.d.ts +391 -0
- package/types/nanahoshi-mona-ui-internal.d.ts +136 -0
- package/types/nanahoshi-mona-ui-list-box.d.ts +225 -0
- package/types/nanahoshi-mona-ui-list-view.d.ts +188 -0
- package/types/nanahoshi-mona-ui-list.d.ts +1 -0
- package/types/nanahoshi-mona-ui-menubar.d.ts +198 -0
- package/types/nanahoshi-mona-ui-multi-select.d.ts +247 -0
- package/types/nanahoshi-mona-ui-notification.d.ts +106 -0
- package/types/nanahoshi-mona-ui-numeric-text-box.d.ts +161 -0
- package/types/nanahoshi-mona-ui-pager.d.ts +238 -0
- package/types/nanahoshi-mona-ui-placeholder.d.ts +35 -0
- package/types/nanahoshi-mona-ui-popover.d.ts +130 -0
- package/types/nanahoshi-mona-ui-popup-menu.d.ts +412 -0
- package/types/nanahoshi-mona-ui-popup.d.ts +485 -0
- package/types/nanahoshi-mona-ui-progress-bar.d.ts +139 -0
- package/types/nanahoshi-mona-ui-query.d.ts +89 -0
- package/types/nanahoshi-mona-ui-radio-button.d.ts +128 -0
- package/types/nanahoshi-mona-ui-scroll-view.d.ts +166 -0
- package/types/nanahoshi-mona-ui-slider.d.ts +305 -0
- package/types/nanahoshi-mona-ui-split-button.d.ts +182 -0
- package/types/nanahoshi-mona-ui-splitter.d.ts +70 -0
- package/types/nanahoshi-mona-ui-stepper.d.ts +173 -0
- package/types/nanahoshi-mona-ui-switch.d.ts +125 -0
- package/types/nanahoshi-mona-ui-tabs.d.ts +158 -0
- package/types/nanahoshi-mona-ui-text-area.d.ts +42 -0
- package/types/nanahoshi-mona-ui-text-box.d.ts +164 -0
- package/types/nanahoshi-mona-ui-theme.d.ts +23 -0
- package/types/nanahoshi-mona-ui-time-picker.d.ts +184 -0
- package/types/nanahoshi-mona-ui-time-selector.d.ts +143 -0
- package/types/nanahoshi-mona-ui-tooltip.d.ts +130 -0
- package/types/nanahoshi-mona-ui-tree-view.d.ts +274 -0
- package/types/nanahoshi-mona-ui-window.d.ts +295 -0
- package/types/nanahoshi-mona-ui.d.ts +2 -0
|
@@ -0,0 +1,853 @@
|
|
|
1
|
+
import { Clipboard } from '@angular/cdk/clipboard';
|
|
2
|
+
import { NgTemplateOutlet } from '@angular/common';
|
|
3
|
+
import * as i0 from '@angular/core';
|
|
4
|
+
import { inject, DestroyRef, Injector, signal, NgZone, computed, viewChild, output, input, model, afterNextRender, effect, untracked, Component } from '@angular/core';
|
|
5
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
6
|
+
import { LucideCopy } from '@lucide/angular';
|
|
7
|
+
import { ButtonDirective } from '@nanahoshi/mona-ui/button';
|
|
8
|
+
import { rgba2hex, hsva2rgba, isValidHex, hex2rgba, rgba2hsva, rgba2hsla, isValidHsla, isValidRgb, string2rgba, string2Hsla, hsla2hsva } from '@nanahoshi/mona-ui/internal';
|
|
9
|
+
import { DropdownButtonComponent, DropdownButtonItemComponent } from '@nanahoshi/mona-ui/dropdown-button';
|
|
10
|
+
import { NumericTextBoxComponent, NumericTextBoxPrefixTemplateDirective } from '@nanahoshi/mona-ui/numeric-text-box';
|
|
11
|
+
import { SliderComponent } from '@nanahoshi/mona-ui/slider';
|
|
12
|
+
import { TextBoxComponent, TextBoxPrefixTemplateDirective, TextBoxSuffixTemplateDirective } from '@nanahoshi/mona-ui/text-box';
|
|
13
|
+
import { ThemeService } from '@nanahoshi/mona-ui/theme';
|
|
14
|
+
import { Subject, fromEvent, switchMap, takeUntil, distinctUntilChanged } from 'rxjs';
|
|
15
|
+
import { cva } from 'class-variance-authority';
|
|
16
|
+
|
|
17
|
+
const colorGradientBaseVariants = cva(`
|
|
18
|
+
flex flex-col min-w-64
|
|
19
|
+
p-2 gap-2
|
|
20
|
+
select-none
|
|
21
|
+
|
|
22
|
+
data-[disabled='true']:cursor-not-allowed
|
|
23
|
+
data-[disabled='true']:opacity-50
|
|
24
|
+
data-[disabled='true']:pointer-events-none
|
|
25
|
+
|
|
26
|
+
data-[invalid='true']:border
|
|
27
|
+
data-[invalid='true']:border-error
|
|
28
|
+
data-[invalid='true']:ring-1
|
|
29
|
+
data-[invalid='true']:ring-error
|
|
30
|
+
`);
|
|
31
|
+
const colorGradientHsvRectangleVariants = cva(`
|
|
32
|
+
relative w-full h-40
|
|
33
|
+
bg-[linear-gradient(to_bottom,rgba(0,0,0,0),black),linear-gradient(to_right,white,rgba(255,255,255,0))]
|
|
34
|
+
border border-border
|
|
35
|
+
`, {
|
|
36
|
+
variants: {
|
|
37
|
+
rounded: {
|
|
38
|
+
none: "rounded-none",
|
|
39
|
+
small: "rounded-sm",
|
|
40
|
+
medium: "rounded-md",
|
|
41
|
+
large: "rounded-lg",
|
|
42
|
+
full: "rounded-lg" // Full is not suitable for color gradient rectangle.
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
const colorGradientHsvRectangleHandleVariants = cva(`
|
|
47
|
+
absolute
|
|
48
|
+
w-3 h-3
|
|
49
|
+
cursor-pointer
|
|
50
|
+
border border-foreground
|
|
51
|
+
outline outline-background
|
|
52
|
+
shadow-md
|
|
53
|
+
|
|
54
|
+
focus-visible:ring-2
|
|
55
|
+
focus-visible:ring-primary/40
|
|
56
|
+
focus-visible:ring-offset-2
|
|
57
|
+
`, {
|
|
58
|
+
variants: {
|
|
59
|
+
rounded: {
|
|
60
|
+
none: "rounded-none",
|
|
61
|
+
small: "rounded-sm",
|
|
62
|
+
medium: "rounded-md",
|
|
63
|
+
large: "rounded-lg",
|
|
64
|
+
full: "rounded-full"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
const colorGradientPreviewVariants = cva(`
|
|
69
|
+
w-10 h-10 flex
|
|
70
|
+
border border-border
|
|
71
|
+
`, {
|
|
72
|
+
variants: {
|
|
73
|
+
rounded: {
|
|
74
|
+
none: "rounded-none",
|
|
75
|
+
small: "rounded-sm",
|
|
76
|
+
medium: "rounded-md",
|
|
77
|
+
large: "rounded-lg",
|
|
78
|
+
full: "rounded-full"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
const colorGradientSliderHandleVariants = cva(`
|
|
83
|
+
border-3 border-white/90
|
|
84
|
+
outline outline-solid outline-black/90
|
|
85
|
+
bg-transparent
|
|
86
|
+
w-3 h-3
|
|
87
|
+
`);
|
|
88
|
+
|
|
89
|
+
const colorGradientBaseThemeVariants = (theme) => {
|
|
90
|
+
switch (theme) {
|
|
91
|
+
case "mona":
|
|
92
|
+
return colorGradientBaseVariants;
|
|
93
|
+
default:
|
|
94
|
+
return colorGradientBaseVariants;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
const colorGradientHsvRectangleThemeVariants = (theme) => {
|
|
98
|
+
switch (theme) {
|
|
99
|
+
case "mona":
|
|
100
|
+
return colorGradientHsvRectangleVariants;
|
|
101
|
+
default:
|
|
102
|
+
return colorGradientHsvRectangleVariants;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
const colorGradientHsvRectangleHandleThemeVariants = (theme) => {
|
|
106
|
+
switch (theme) {
|
|
107
|
+
case "mona":
|
|
108
|
+
return colorGradientHsvRectangleHandleVariants;
|
|
109
|
+
default:
|
|
110
|
+
return colorGradientHsvRectangleHandleVariants;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
const colorGradientPreviewThemeVariants = (theme) => {
|
|
114
|
+
switch (theme) {
|
|
115
|
+
case "mona":
|
|
116
|
+
return colorGradientPreviewVariants;
|
|
117
|
+
default:
|
|
118
|
+
return colorGradientPreviewVariants;
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
const colorGradientSliderHandleThemeVariants = (theme) => {
|
|
122
|
+
switch (theme) {
|
|
123
|
+
case "mona":
|
|
124
|
+
return colorGradientSliderHandleVariants;
|
|
125
|
+
default:
|
|
126
|
+
return colorGradientSliderHandleVariants;
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
class ColorGradientComponent {
|
|
131
|
+
#clipboard;
|
|
132
|
+
#destroyRef;
|
|
133
|
+
#injector;
|
|
134
|
+
#themeService;
|
|
135
|
+
#valueChange$;
|
|
136
|
+
#viewReady;
|
|
137
|
+
#zone;
|
|
138
|
+
#internalValueUpdatePending;
|
|
139
|
+
#lastInternalValue;
|
|
140
|
+
constructor() {
|
|
141
|
+
this.#clipboard = inject(Clipboard);
|
|
142
|
+
this.#destroyRef = inject(DestroyRef);
|
|
143
|
+
this.#injector = inject(Injector);
|
|
144
|
+
this.#themeService = inject(ThemeService);
|
|
145
|
+
this.#valueChange$ = new Subject();
|
|
146
|
+
this.#viewReady = signal(false, /* @ts-ignore */
|
|
147
|
+
...(ngDevMode ? [{ debugName: "#viewReady" }] : /* istanbul ignore next */ []));
|
|
148
|
+
this.#zone = inject(NgZone);
|
|
149
|
+
this.#internalValueUpdatePending = false;
|
|
150
|
+
this.#lastInternalValue = undefined;
|
|
151
|
+
this.alpha = signal(255, /* @ts-ignore */
|
|
152
|
+
...(ngDevMode ? [{ debugName: "alpha" }] : /* istanbul ignore next */ []));
|
|
153
|
+
this.alphaInputColor = computed(() => {
|
|
154
|
+
const rgb = this.rgb();
|
|
155
|
+
return rgba2hex(rgb.r, rgb.g, rgb.b, 255);
|
|
156
|
+
}, /* @ts-ignore */
|
|
157
|
+
...(ngDevMode ? [{ debugName: "alphaInputColor" }] : /* istanbul ignore next */ []));
|
|
158
|
+
this.alphaSliderBackground = computed(() => {
|
|
159
|
+
const color = this.alphaInputColor();
|
|
160
|
+
return `linear-gradient(to right, transparent, ${color})`;
|
|
161
|
+
}, /* @ts-ignore */
|
|
162
|
+
...(ngDevMode ? [{ debugName: "alphaSliderBackground" }] : /* istanbul ignore next */ []));
|
|
163
|
+
this.baseClasses = computed(() => {
|
|
164
|
+
const theme = this.#themeService.theme();
|
|
165
|
+
return colorGradientBaseThemeVariants(theme)();
|
|
166
|
+
}, /* @ts-ignore */
|
|
167
|
+
...(ngDevMode ? [{ debugName: "baseClasses" }] : /* istanbul ignore next */ []));
|
|
168
|
+
this.colorInputs = computed(() => {
|
|
169
|
+
const mode = this.colorMode();
|
|
170
|
+
const baseInputs = mode === "rgb" ? this.createRgbInputList() : this.createHsvInputList();
|
|
171
|
+
if (this.opacity()) {
|
|
172
|
+
baseInputs.push({
|
|
173
|
+
key: "a",
|
|
174
|
+
label: "A",
|
|
175
|
+
value: this.alpha(),
|
|
176
|
+
min: 0,
|
|
177
|
+
max: 255,
|
|
178
|
+
change: (value) => this.onAlphaChange(value)
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return baseInputs;
|
|
182
|
+
}, /* @ts-ignore */
|
|
183
|
+
...(ngDevMode ? [{ debugName: "colorInputs" }] : /* istanbul ignore next */ []));
|
|
184
|
+
this.colorMode = signal("rgb", /* @ts-ignore */
|
|
185
|
+
...(ngDevMode ? [{ debugName: "colorMode" }] : /* istanbul ignore next */ []));
|
|
186
|
+
this.colorPreviewClasses = computed(() => {
|
|
187
|
+
const theme = this.#themeService.theme();
|
|
188
|
+
const rounded = this.rounded();
|
|
189
|
+
return colorGradientPreviewThemeVariants(theme)({ rounded });
|
|
190
|
+
}, /* @ts-ignore */
|
|
191
|
+
...(ngDevMode ? [{ debugName: "colorPreviewClasses" }] : /* istanbul ignore next */ []));
|
|
192
|
+
this.colorPreviews = computed(() => [
|
|
193
|
+
{
|
|
194
|
+
type: "current",
|
|
195
|
+
color: this.selectedColor(),
|
|
196
|
+
title: "Current color"
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
type: "last",
|
|
200
|
+
color: this.lastSelectedColor(),
|
|
201
|
+
title: "Previous color",
|
|
202
|
+
onClick: () => this.onResetColorClick()
|
|
203
|
+
}
|
|
204
|
+
], /* @ts-ignore */
|
|
205
|
+
...(ngDevMode ? [{ debugName: "colorPreviews" }] : /* istanbul ignore next */ []));
|
|
206
|
+
this.hex = computed(() => {
|
|
207
|
+
const rgb = this.rgb();
|
|
208
|
+
const alpha = this.alpha();
|
|
209
|
+
const focused = this.hexFocused();
|
|
210
|
+
if (!focused) {
|
|
211
|
+
return rgba2hex(rgb.r, rgb.g, rgb.b, alpha);
|
|
212
|
+
}
|
|
213
|
+
return this.hexInputValue();
|
|
214
|
+
}, /* @ts-ignore */
|
|
215
|
+
...(ngDevMode ? [{ debugName: "hex" }] : /* istanbul ignore next */ []));
|
|
216
|
+
this.hexFocused = signal(false, /* @ts-ignore */
|
|
217
|
+
...(ngDevMode ? [{ debugName: "hexFocused" }] : /* istanbul ignore next */ []));
|
|
218
|
+
this.hsvHandle = viewChild.required("hsvPointer", /* @ts-ignore */
|
|
219
|
+
...(ngDevMode ? [{ debugName: "hsvHandle" }] : /* istanbul ignore next */ []));
|
|
220
|
+
this.hsvHandleLeft = signal(0, /* @ts-ignore */
|
|
221
|
+
...(ngDevMode ? [{ debugName: "hsvHandleLeft" }] : /* istanbul ignore next */ []));
|
|
222
|
+
this.hsvHandleTop = signal(0, /* @ts-ignore */
|
|
223
|
+
...(ngDevMode ? [{ debugName: "hsvHandleTop" }] : /* istanbul ignore next */ []));
|
|
224
|
+
this.hexInputValue = signal("", /* @ts-ignore */
|
|
225
|
+
...(ngDevMode ? [{ debugName: "hexInputValue" }] : /* istanbul ignore next */ []));
|
|
226
|
+
this.hsv = signal({ h: 360, s: 100, v: 100 }, /* @ts-ignore */
|
|
227
|
+
...(ngDevMode ? [{ debugName: "hsv" }] : /* istanbul ignore next */ []));
|
|
228
|
+
this.hsvRectangle = viewChild.required("hsvRectangle", /* @ts-ignore */
|
|
229
|
+
...(ngDevMode ? [{ debugName: "hsvRectangle" }] : /* istanbul ignore next */ []));
|
|
230
|
+
this.hsvRectangleBackground = computed(() => {
|
|
231
|
+
const hsv = this.hsv();
|
|
232
|
+
const rgb = hsva2rgba(hsv.h, 100, 100, 255);
|
|
233
|
+
return `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`;
|
|
234
|
+
}, /* @ts-ignore */
|
|
235
|
+
...(ngDevMode ? [{ debugName: "hsvRectangleBackground" }] : /* istanbul ignore next */ []));
|
|
236
|
+
this.hsvRectangleClasses = computed(() => {
|
|
237
|
+
const theme = this.#themeService.theme();
|
|
238
|
+
const rounded = this.rounded() === "full" ? "large" : this.rounded();
|
|
239
|
+
return colorGradientHsvRectangleThemeVariants(theme)({ rounded });
|
|
240
|
+
}, /* @ts-ignore */
|
|
241
|
+
...(ngDevMode ? [{ debugName: "hsvRectangleClasses" }] : /* istanbul ignore next */ []));
|
|
242
|
+
this.hsvRectangleHandleClasses = computed(() => {
|
|
243
|
+
const theme = this.#themeService.theme();
|
|
244
|
+
const rounded = this.rounded();
|
|
245
|
+
return colorGradientHsvRectangleHandleThemeVariants(theme)({ rounded });
|
|
246
|
+
}, /* @ts-ignore */
|
|
247
|
+
...(ngDevMode ? [{ debugName: "hsvRectangleHandleClasses" }] : /* istanbul ignore next */ []));
|
|
248
|
+
this.hueValue$ = new Subject();
|
|
249
|
+
this.invalidState = computed(() => this.invalid() || (this.required() && this.touched() && !this.value()), /* @ts-ignore */
|
|
250
|
+
...(ngDevMode ? [{ debugName: "invalidState" }] : /* istanbul ignore next */ []));
|
|
251
|
+
this.lastSelectedColor = signal("", /* @ts-ignore */
|
|
252
|
+
...(ngDevMode ? [{ debugName: "lastSelectedColor" }] : /* istanbul ignore next */ []));
|
|
253
|
+
this.rgb = signal({ r: 255, g: 255, b: 255 }, /* @ts-ignore */
|
|
254
|
+
...(ngDevMode ? [{ debugName: "rgb" }] : /* istanbul ignore next */ []));
|
|
255
|
+
this.selectedColor = computed(() => {
|
|
256
|
+
const rgb = this.rgb();
|
|
257
|
+
if (rgb.r == null || rgb.g == null || rgb.b == null) {
|
|
258
|
+
return "";
|
|
259
|
+
}
|
|
260
|
+
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${this.alpha() / 255})`;
|
|
261
|
+
}, /* @ts-ignore */
|
|
262
|
+
...(ngDevMode ? [{ debugName: "selectedColor" }] : /* istanbul ignore next */ []));
|
|
263
|
+
this.sliderHandleClasses = computed(() => {
|
|
264
|
+
const theme = this.#themeService.theme();
|
|
265
|
+
return colorGradientSliderHandleThemeVariants(theme)();
|
|
266
|
+
}, /* @ts-ignore */
|
|
267
|
+
...(ngDevMode ? [{ debugName: "sliderHandleClasses" }] : /* istanbul ignore next */ []));
|
|
268
|
+
this.sliderHeight = 10;
|
|
269
|
+
/**
|
|
270
|
+
* @description Emits when the Apply button is clicked.
|
|
271
|
+
* The `Apply` button is only displayed when `showButtons` is set to true.
|
|
272
|
+
*/
|
|
273
|
+
this.apply = output();
|
|
274
|
+
/**
|
|
275
|
+
* @description Emits when the Cancel button is clicked.
|
|
276
|
+
* The `Cancel` button is only displayed when `showButtons` is set to true.
|
|
277
|
+
*/
|
|
278
|
+
this.cancel = output();
|
|
279
|
+
/**
|
|
280
|
+
* @description Sets the disabled state of the color gradient.
|
|
281
|
+
* @default false
|
|
282
|
+
*/
|
|
283
|
+
this.disabled = input(false, /* @ts-ignore */
|
|
284
|
+
...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
285
|
+
/**
|
|
286
|
+
* @description Specifies the format of the color output.
|
|
287
|
+
* @default "hex"
|
|
288
|
+
*/
|
|
289
|
+
this.format = input("hex", /* @ts-ignore */
|
|
290
|
+
...(ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []));
|
|
291
|
+
/**
|
|
292
|
+
* @description Marks the color gradient as invalid. When bound to a signal form field via `[field]`,
|
|
293
|
+
* this is written by the signal forms `Field` directive.
|
|
294
|
+
* @default false
|
|
295
|
+
*/
|
|
296
|
+
this.invalid = input(false, /* @ts-ignore */
|
|
297
|
+
...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
298
|
+
/**
|
|
299
|
+
* @description Specifies whether the color picker should display the alpha slider.
|
|
300
|
+
* @default true
|
|
301
|
+
*/
|
|
302
|
+
this.opacity = input(true, /* @ts-ignore */
|
|
303
|
+
...(ngDevMode ? [{ debugName: "opacity" }] : /* istanbul ignore next */ []));
|
|
304
|
+
/**
|
|
305
|
+
* @description Marks the color gradient as required for form validation.
|
|
306
|
+
* @default false
|
|
307
|
+
*/
|
|
308
|
+
this.required = input(false, /* @ts-ignore */
|
|
309
|
+
...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
310
|
+
/**
|
|
311
|
+
* @description Specifies the rounded variant of the color picker.
|
|
312
|
+
* @default "medium"
|
|
313
|
+
*/
|
|
314
|
+
this.rounded = input("medium", /* @ts-ignore */
|
|
315
|
+
...(ngDevMode ? [{ debugName: "rounded" }] : /* istanbul ignore next */ []));
|
|
316
|
+
/**
|
|
317
|
+
* @description Specifies whether the color picker should display the buttons.
|
|
318
|
+
* When set to true, the color picker will display the "Apply" and "Cancel" buttons.
|
|
319
|
+
* When set to false, the color picker will not display the buttons and will emit the color value on change.
|
|
320
|
+
* @default true
|
|
321
|
+
*/
|
|
322
|
+
this.showButtons = input(true, /* @ts-ignore */
|
|
323
|
+
...(ngDevMode ? [{ debugName: "showButtons" }] : /* istanbul ignore next */ []));
|
|
324
|
+
/**
|
|
325
|
+
* @description Specifies whether the color picker should display the hex input.
|
|
326
|
+
* @default true
|
|
327
|
+
*/
|
|
328
|
+
this.showHexInput = input(true, /* @ts-ignore */
|
|
329
|
+
...(ngDevMode ? [{ debugName: "showHexInput" }] : /* istanbul ignore next */ []));
|
|
330
|
+
/**
|
|
331
|
+
* @description Specifies whether the color picker should display the channel inputs (RGB or HSV).
|
|
332
|
+
* @default true
|
|
333
|
+
*/
|
|
334
|
+
this.showColorInputs = input(true, /* @ts-ignore */
|
|
335
|
+
...(ngDevMode ? [{ debugName: "showColorInputs" }] : /* istanbul ignore next */ []));
|
|
336
|
+
/**
|
|
337
|
+
* @description Emitted when the color gradient is interacted with on blur or value adjustment.
|
|
338
|
+
* The `FormField` directive listens to this to mark the field as touched.
|
|
339
|
+
*/
|
|
340
|
+
this.touch = output();
|
|
341
|
+
/**
|
|
342
|
+
* @description Marks the color gradient as touched. When bound to a signal form field via `[field]`,
|
|
343
|
+
* this is written by the signal forms `Field` directive.
|
|
344
|
+
* @default false
|
|
345
|
+
*/
|
|
346
|
+
this.touched = input(false, /* @ts-ignore */
|
|
347
|
+
...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
348
|
+
/**
|
|
349
|
+
* @description Two-way bindable current color value.
|
|
350
|
+
* When undefined, the component keeps its default internal color state (white, #ffffffff).
|
|
351
|
+
* @default undefined
|
|
352
|
+
*/
|
|
353
|
+
this.value = model(undefined, /* @ts-ignore */
|
|
354
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
355
|
+
afterNextRender({
|
|
356
|
+
read: () => {
|
|
357
|
+
this.lastSelectedColor.set(this.hex());
|
|
358
|
+
this.setSubscriptions();
|
|
359
|
+
this.#viewReady.set(true);
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
effect(() => {
|
|
363
|
+
if (!this.#viewReady()) {
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
const value = this.value();
|
|
367
|
+
untracked(() => this.syncValue(value));
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
onAlphaChange(value) {
|
|
371
|
+
if (value == null) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
const alpha = this.getValidChannelValue(value, "a");
|
|
375
|
+
this.alpha.set(alpha);
|
|
376
|
+
this.updateHexInputValue();
|
|
377
|
+
if (!this.showButtons()) {
|
|
378
|
+
this.emitValue();
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
onApply() {
|
|
382
|
+
this.lastSelectedColor.set(this.hex());
|
|
383
|
+
this.emitValue();
|
|
384
|
+
this.apply.emit();
|
|
385
|
+
}
|
|
386
|
+
onCancel() {
|
|
387
|
+
this.hexInputValue.set(this.lastSelectedColor());
|
|
388
|
+
this.cancel.emit();
|
|
389
|
+
}
|
|
390
|
+
onClearClick() {
|
|
391
|
+
this.clear();
|
|
392
|
+
if (!this.showButtons()) {
|
|
393
|
+
this.emitValue(null);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
onCopyColorSelect(mode) {
|
|
397
|
+
if (mode === "hex") {
|
|
398
|
+
this.#clipboard.copy(this.hex());
|
|
399
|
+
}
|
|
400
|
+
else if (mode === "rgb") {
|
|
401
|
+
const rgb = this.rgb();
|
|
402
|
+
const alpha = Math.round((this.alpha() / 255) * 100) / 100;
|
|
403
|
+
this.#clipboard.copy(`rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
onHexChange(value) {
|
|
407
|
+
this.hexInputValue.set(value);
|
|
408
|
+
if (!isValidHex(value)) {
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
const rgb = hex2rgba(value);
|
|
412
|
+
const hsv = rgba2hsva(rgb.r, rgb.g, rgb.b, rgb.a);
|
|
413
|
+
this.hsv.update(c => ({ ...c, h: hsv.h, s: hsv.s, v: hsv.v }));
|
|
414
|
+
this.rgb.update(c => ({ ...c, r: rgb.r, g: rgb.g, b: rgb.b }));
|
|
415
|
+
this.alpha.set(rgb.a ?? 255);
|
|
416
|
+
this.hsvHandleLeft.set(this.getPositionFromSaturation(hsv.s));
|
|
417
|
+
this.hsvHandleTop.set(this.getPositionFromValue(hsv.v));
|
|
418
|
+
if (!this.showButtons()) {
|
|
419
|
+
this.emitValue();
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
onHexInputBlur() {
|
|
423
|
+
this.hexFocused.set(false);
|
|
424
|
+
this.updateHexInputValue();
|
|
425
|
+
this.touch.emit();
|
|
426
|
+
}
|
|
427
|
+
onHexInputFocus() {
|
|
428
|
+
this.hexFocused.set(true);
|
|
429
|
+
}
|
|
430
|
+
onHsvChange(value, channel) {
|
|
431
|
+
if (value == null) {
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
value = this.getValidChannelValue(value, channel);
|
|
435
|
+
this.hsv.update(c => ({ ...c, [channel]: value }));
|
|
436
|
+
this.updateOtherNullChannels(channel);
|
|
437
|
+
const hsv = this.hsv();
|
|
438
|
+
const rgb = hsva2rgba(hsv.h, hsv.s, hsv.v, this.alpha());
|
|
439
|
+
this.rgb.update(c => ({ ...c, r: rgb.r, g: rgb.g, b: rgb.b }));
|
|
440
|
+
this.updateHexInputValue();
|
|
441
|
+
this.hsvHandleLeft.set(this.getPositionFromSaturation(hsv.s));
|
|
442
|
+
this.hsvHandleTop.set(this.getPositionFromValue(hsv.v));
|
|
443
|
+
if (!this.showButtons()) {
|
|
444
|
+
this.emitValue();
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
onHsvHandleBlur() {
|
|
448
|
+
this.touch.emit();
|
|
449
|
+
}
|
|
450
|
+
onHsvHandleKeyDown(event) {
|
|
451
|
+
if (this.disabled()) {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
const step = event.shiftKey ? 10 : 1;
|
|
455
|
+
const largeStep = 25;
|
|
456
|
+
let handled = false;
|
|
457
|
+
const currentHsv = this.hsv();
|
|
458
|
+
const currentSaturation = currentHsv.s ?? 0;
|
|
459
|
+
const currentValue = currentHsv.v ?? 0;
|
|
460
|
+
let newSaturation = currentSaturation;
|
|
461
|
+
let newValue = currentValue;
|
|
462
|
+
switch (event.key) {
|
|
463
|
+
case "ArrowLeft":
|
|
464
|
+
newSaturation = this.getValidChannelValue(currentSaturation - step, "s");
|
|
465
|
+
handled = true;
|
|
466
|
+
break;
|
|
467
|
+
case "ArrowRight":
|
|
468
|
+
newSaturation = this.getValidChannelValue(currentSaturation + step, "s");
|
|
469
|
+
handled = true;
|
|
470
|
+
break;
|
|
471
|
+
case "ArrowUp":
|
|
472
|
+
newValue = this.getValidChannelValue(currentValue + step, "v");
|
|
473
|
+
handled = true;
|
|
474
|
+
break;
|
|
475
|
+
case "ArrowDown":
|
|
476
|
+
newValue = this.getValidChannelValue(currentValue - step, "v");
|
|
477
|
+
handled = true;
|
|
478
|
+
break;
|
|
479
|
+
case "Home":
|
|
480
|
+
newSaturation = 0;
|
|
481
|
+
newValue = 100;
|
|
482
|
+
handled = true;
|
|
483
|
+
break;
|
|
484
|
+
case "End":
|
|
485
|
+
newSaturation = 100;
|
|
486
|
+
newValue = 0;
|
|
487
|
+
handled = true;
|
|
488
|
+
break;
|
|
489
|
+
case "PageUp":
|
|
490
|
+
newValue = this.getValidChannelValue(currentValue + largeStep, "v");
|
|
491
|
+
handled = true;
|
|
492
|
+
break;
|
|
493
|
+
case "PageDown":
|
|
494
|
+
newValue = this.getValidChannelValue(currentValue - largeStep, "v");
|
|
495
|
+
handled = true;
|
|
496
|
+
break;
|
|
497
|
+
}
|
|
498
|
+
if (handled) {
|
|
499
|
+
event.preventDefault();
|
|
500
|
+
event.stopPropagation();
|
|
501
|
+
this.updateHsvValues(newSaturation, newValue);
|
|
502
|
+
this.hsvHandleLeft.set(this.getPositionFromSaturation(newSaturation));
|
|
503
|
+
this.hsvHandleTop.set(this.getPositionFromValue(newValue));
|
|
504
|
+
this.updateHexInputValue();
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
onNumericInputBlur() {
|
|
508
|
+
this.touch.emit();
|
|
509
|
+
}
|
|
510
|
+
onPreviousColorKeyDown(event, handler) {
|
|
511
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
512
|
+
event.preventDefault();
|
|
513
|
+
handler?.();
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
onResetColorClick() {
|
|
517
|
+
this.onHexChange(this.lastSelectedColor());
|
|
518
|
+
}
|
|
519
|
+
onRgbChange(value, channel) {
|
|
520
|
+
if (value == null) {
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
value = this.getValidChannelValue(value, channel);
|
|
524
|
+
this.rgb.update(c => ({ ...c, [channel]: value }));
|
|
525
|
+
this.updateOtherNullChannels(channel);
|
|
526
|
+
const rgb = this.rgb();
|
|
527
|
+
const hsv = rgba2hsva(rgb.r, rgb.g, rgb.b, this.alpha());
|
|
528
|
+
this.hsv.update(c => ({ ...c, h: hsv.h, s: hsv.s, v: hsv.v }));
|
|
529
|
+
this.updateHexInputValue();
|
|
530
|
+
this.hsvHandleLeft.set(this.getPositionFromSaturation(hsv.s));
|
|
531
|
+
this.hsvHandleTop.set(this.getPositionFromValue(hsv.v));
|
|
532
|
+
if (!this.showButtons()) {
|
|
533
|
+
this.emitValue();
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
onSliderBlur() {
|
|
537
|
+
this.touch.emit();
|
|
538
|
+
}
|
|
539
|
+
onSwitchColorModeClick() {
|
|
540
|
+
this.colorMode.set(this.colorMode() === "rgb" ? "hsv" : "rgb");
|
|
541
|
+
}
|
|
542
|
+
afterNextRender(callback) {
|
|
543
|
+
afterNextRender(callback, { injector: this.#injector });
|
|
544
|
+
}
|
|
545
|
+
clear() {
|
|
546
|
+
this.hexInputValue.set("");
|
|
547
|
+
this.lastSelectedColor.set("");
|
|
548
|
+
this.rgb.update(c => ({ ...c, r: null, g: null, b: null }));
|
|
549
|
+
this.alpha.set(255);
|
|
550
|
+
this.hsv.update(c => ({ ...c, h: null, s: null, v: null }));
|
|
551
|
+
}
|
|
552
|
+
createHsvInputList() {
|
|
553
|
+
const hue = {
|
|
554
|
+
key: "h",
|
|
555
|
+
label: "H",
|
|
556
|
+
value: this.hsv().h,
|
|
557
|
+
min: 0,
|
|
558
|
+
max: 360,
|
|
559
|
+
change: (value) => this.onHsvChange(value, "h")
|
|
560
|
+
};
|
|
561
|
+
const saturation = {
|
|
562
|
+
key: "s",
|
|
563
|
+
label: "S",
|
|
564
|
+
value: this.hsv().s,
|
|
565
|
+
min: 0,
|
|
566
|
+
max: 100,
|
|
567
|
+
change: (value) => this.onHsvChange(value, "s")
|
|
568
|
+
};
|
|
569
|
+
const value = {
|
|
570
|
+
key: "v",
|
|
571
|
+
label: "V",
|
|
572
|
+
value: this.hsv().v,
|
|
573
|
+
min: 0,
|
|
574
|
+
max: 100,
|
|
575
|
+
change: (value) => this.onHsvChange(value, "v")
|
|
576
|
+
};
|
|
577
|
+
return [hue, saturation, value];
|
|
578
|
+
}
|
|
579
|
+
createRgbInputList() {
|
|
580
|
+
const red = {
|
|
581
|
+
key: "r",
|
|
582
|
+
label: "R",
|
|
583
|
+
value: this.rgb().r,
|
|
584
|
+
min: 0,
|
|
585
|
+
max: 255,
|
|
586
|
+
change: (value) => this.onRgbChange(value, "r")
|
|
587
|
+
};
|
|
588
|
+
const green = {
|
|
589
|
+
key: "g",
|
|
590
|
+
label: "G",
|
|
591
|
+
value: this.rgb().g,
|
|
592
|
+
min: 0,
|
|
593
|
+
max: 255,
|
|
594
|
+
change: (value) => this.onRgbChange(value, "g")
|
|
595
|
+
};
|
|
596
|
+
const blue = {
|
|
597
|
+
key: "b",
|
|
598
|
+
label: "B",
|
|
599
|
+
value: this.rgb().b,
|
|
600
|
+
min: 0,
|
|
601
|
+
max: 255,
|
|
602
|
+
change: (value) => this.onRgbChange(value, "b")
|
|
603
|
+
};
|
|
604
|
+
return [red, green, blue];
|
|
605
|
+
}
|
|
606
|
+
emitValue(value) {
|
|
607
|
+
if (value !== undefined) {
|
|
608
|
+
this.#valueChange$.next(value);
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
const format = this.format();
|
|
612
|
+
const rgb = this.rgb();
|
|
613
|
+
const alpha = this.alpha();
|
|
614
|
+
if (rgb.r == null || rgb.g == null || rgb.b == null || alpha == null) {
|
|
615
|
+
this.#valueChange$.next(null);
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
if (format === "hex") {
|
|
619
|
+
this.#valueChange$.next(rgba2hex(rgb.r, rgb.g, rgb.b, alpha));
|
|
620
|
+
}
|
|
621
|
+
else if (format === "rgb") {
|
|
622
|
+
this.#valueChange$.next(`rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha / 255})`);
|
|
623
|
+
}
|
|
624
|
+
else if (format === "hsl") {
|
|
625
|
+
const hsl = rgba2hsla(rgb.r, rgb.g, rgb.b, alpha);
|
|
626
|
+
this.#valueChange$.next(`hsla(${hsl.h}, ${hsl.s}%, ${hsl.l}%, ${alpha / 255})`);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
getPositionFromSaturation(saturation) {
|
|
630
|
+
if (saturation == null) {
|
|
631
|
+
return 0;
|
|
632
|
+
}
|
|
633
|
+
const maxVal = this.hsvRectangle().nativeElement.offsetWidth;
|
|
634
|
+
const minVal = (saturation / 100) * maxVal;
|
|
635
|
+
return minVal - this.hsvHandle().nativeElement.offsetWidth / 2;
|
|
636
|
+
}
|
|
637
|
+
getPositionFromValue(value) {
|
|
638
|
+
if (value == null) {
|
|
639
|
+
return 0;
|
|
640
|
+
}
|
|
641
|
+
const maxVal = this.hsvRectangle().nativeElement.offsetHeight;
|
|
642
|
+
const minVal = ((100 - value) / 100) * maxVal;
|
|
643
|
+
return minVal - this.hsvHandle().nativeElement.offsetHeight / 2;
|
|
644
|
+
}
|
|
645
|
+
getSaturationFromPosition(left) {
|
|
646
|
+
const minVal = left + this.hsvHandle().nativeElement.offsetWidth / 2;
|
|
647
|
+
const maxVal = this.hsvRectangle().nativeElement.offsetWidth;
|
|
648
|
+
return this.getValidChannelValue(Math.ceil((minVal / maxVal) * 100), "s");
|
|
649
|
+
}
|
|
650
|
+
getValidChannelValue(value, channel) {
|
|
651
|
+
if (channel === "r" || channel === "g" || channel === "b" || channel === "a") {
|
|
652
|
+
return Math.min(255, Math.max(0, value));
|
|
653
|
+
}
|
|
654
|
+
if (channel === "h") {
|
|
655
|
+
return Math.min(360, Math.max(0, value));
|
|
656
|
+
}
|
|
657
|
+
if (channel === "s" || channel === "v") {
|
|
658
|
+
return Math.min(100, Math.max(0, value));
|
|
659
|
+
}
|
|
660
|
+
return value;
|
|
661
|
+
}
|
|
662
|
+
getValueFromPosition(top) {
|
|
663
|
+
const minVal = top + this.hsvHandle().nativeElement.offsetHeight / 2;
|
|
664
|
+
const maxVal = this.hsvRectangle().nativeElement.offsetHeight;
|
|
665
|
+
return this.getValidChannelValue(Math.round(100 - (minVal / maxVal) * 100), "v");
|
|
666
|
+
}
|
|
667
|
+
loadColorFromString(color) {
|
|
668
|
+
if (color == null || !this.hsvRectangle() || !this.hsvHandle()) {
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
const hexValid = isValidHex(color);
|
|
672
|
+
const hsvValid = isValidHsla(color);
|
|
673
|
+
const rgbValid = isValidRgb(color);
|
|
674
|
+
let rgba;
|
|
675
|
+
let hsla;
|
|
676
|
+
let hsva;
|
|
677
|
+
if (hexValid) {
|
|
678
|
+
rgba = hex2rgba(color);
|
|
679
|
+
}
|
|
680
|
+
else if (rgbValid) {
|
|
681
|
+
rgba = string2rgba(color);
|
|
682
|
+
}
|
|
683
|
+
else if (hsvValid) {
|
|
684
|
+
hsla = string2Hsla(color);
|
|
685
|
+
hsva = hsla2hsva(hsla.h, hsla.s, hsla.l, hsla.a);
|
|
686
|
+
rgba = hsva2rgba(hsva.h, hsva.s, hsva.v, hsva.a);
|
|
687
|
+
hsva = {
|
|
688
|
+
h: Math.round(hsva.h),
|
|
689
|
+
s: Math.round(hsva.s),
|
|
690
|
+
v: Math.round(hsva.v),
|
|
691
|
+
a: hsva.a
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
else {
|
|
695
|
+
rgba = { r: null, g: null, b: null, a: null };
|
|
696
|
+
}
|
|
697
|
+
if (!hsva) {
|
|
698
|
+
hsva = rgba2hsva(rgba.r, rgba.g, rgba.b, rgba.a);
|
|
699
|
+
}
|
|
700
|
+
this.updateHsv(hsva);
|
|
701
|
+
this.updateRgb(rgba);
|
|
702
|
+
this.alpha.set(rgba.a ?? 255);
|
|
703
|
+
this.updateHexInputValue();
|
|
704
|
+
this.afterNextRender(() => {
|
|
705
|
+
this.hsvHandleLeft.set(this.getPositionFromSaturation(hsva.s));
|
|
706
|
+
this.hsvHandleTop.set(this.getPositionFromValue(hsva.v));
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
setHsvRectPointerEvents() {
|
|
710
|
+
const pointerDown$ = fromEvent(this.hsvHandle().nativeElement, "pointerdown").pipe(takeUntilDestroyed(this.#destroyRef));
|
|
711
|
+
const pointerMove$ = fromEvent(document, "pointermove").pipe(takeUntilDestroyed(this.#destroyRef));
|
|
712
|
+
const pointerUp$ = fromEvent(document, "pointerup").pipe(takeUntilDestroyed(this.#destroyRef));
|
|
713
|
+
pointerDown$
|
|
714
|
+
.pipe(switchMap(() => pointerMove$.pipe(takeUntil(pointerUp$))))
|
|
715
|
+
.subscribe((event) => {
|
|
716
|
+
this.#zone.run(() => {
|
|
717
|
+
const position = this.updateHsvRectPointerPosition(event);
|
|
718
|
+
this.updateHsvValues(this.getSaturationFromPosition(position.left), this.getValueFromPosition(position.top));
|
|
719
|
+
this.updateHexInputValue();
|
|
720
|
+
});
|
|
721
|
+
});
|
|
722
|
+
fromEvent(this.hsvRectangle().nativeElement, "click")
|
|
723
|
+
.pipe(takeUntilDestroyed(this.#destroyRef))
|
|
724
|
+
.subscribe((event) => {
|
|
725
|
+
const position = this.updateHsvRectPointerPosition(event);
|
|
726
|
+
this.updateHsvValues(this.getSaturationFromPosition(position.left), this.getValueFromPosition(position.top));
|
|
727
|
+
this.updateHexInputValue();
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
setSubscriptions() {
|
|
731
|
+
this.hueValue$.pipe(distinctUntilChanged(), takeUntilDestroyed(this.#destroyRef)).subscribe((value) => {
|
|
732
|
+
this.hsv.update(c => ({ ...c, h: Math.round(value) }));
|
|
733
|
+
this.updateRgbFromHsv();
|
|
734
|
+
this.updateHexInputValue();
|
|
735
|
+
});
|
|
736
|
+
this.setHsvRectPointerEvents();
|
|
737
|
+
this.#valueChange$
|
|
738
|
+
.pipe(takeUntilDestroyed(this.#destroyRef), distinctUntilChanged())
|
|
739
|
+
.subscribe((value) => {
|
|
740
|
+
this.#internalValueUpdatePending = true;
|
|
741
|
+
this.#lastInternalValue = value;
|
|
742
|
+
this.value.set(value);
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
syncValue(value) {
|
|
746
|
+
if (value === undefined) {
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
if (this.#internalValueUpdatePending && value === this.#lastInternalValue) {
|
|
750
|
+
this.#internalValueUpdatePending = false;
|
|
751
|
+
this.#lastInternalValue = undefined;
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
754
|
+
this.#internalValueUpdatePending = false;
|
|
755
|
+
this.#lastInternalValue = undefined;
|
|
756
|
+
if (value === null) {
|
|
757
|
+
this.clear();
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
this.loadColorFromString(value);
|
|
761
|
+
this.lastSelectedColor.set(this.hex());
|
|
762
|
+
}
|
|
763
|
+
updateHexInputValue() {
|
|
764
|
+
const rgb = this.rgb();
|
|
765
|
+
const hex = rgba2hex(rgb.r, rgb.g, rgb.b, this.alpha());
|
|
766
|
+
this.hexInputValue.set(hex);
|
|
767
|
+
}
|
|
768
|
+
updateHsv(hsv) {
|
|
769
|
+
this.hsv.update(c => ({ ...c, h: hsv.h, s: hsv.s, v: hsv.v }));
|
|
770
|
+
}
|
|
771
|
+
updateHsvRectPointerPosition(event) {
|
|
772
|
+
const containerRect = this.hsvRectangle().nativeElement.getBoundingClientRect();
|
|
773
|
+
const pointerRect = this.hsvHandle().nativeElement.getBoundingClientRect();
|
|
774
|
+
const left = event.clientX - containerRect.left - pointerRect.width / 2;
|
|
775
|
+
const top = event.clientY - containerRect.top - pointerRect.height / 2;
|
|
776
|
+
const newLeft = Math.min(Math.max(left, -pointerRect.width / 2), containerRect.width - pointerRect.width / 2);
|
|
777
|
+
const newTop = Math.min(Math.max(top, -pointerRect.height / 2), containerRect.height - pointerRect.height / 2);
|
|
778
|
+
this.hsvHandleLeft.set(newLeft);
|
|
779
|
+
this.hsvHandleTop.set(newTop);
|
|
780
|
+
return { left: newLeft, top: newTop };
|
|
781
|
+
}
|
|
782
|
+
updateHsvValues(saturation, value) {
|
|
783
|
+
this.hsv.update(c => ({
|
|
784
|
+
...c,
|
|
785
|
+
h: c.h ?? 0,
|
|
786
|
+
s: this.getValidChannelValue(saturation, "s"),
|
|
787
|
+
v: this.getValidChannelValue(value, "v")
|
|
788
|
+
}));
|
|
789
|
+
this.updateRgbFromHsv();
|
|
790
|
+
}
|
|
791
|
+
updateOtherNullChannels(channel) {
|
|
792
|
+
if (channel === "r" || channel === "g" || channel === "b") {
|
|
793
|
+
this.rgb.update(c => ({ ...c, r: c.r ?? 0, g: c.g ?? 0, b: c.b ?? 0 }));
|
|
794
|
+
}
|
|
795
|
+
else if (channel === "h" || channel === "s" || channel === "v") {
|
|
796
|
+
this.hsv.update(c => ({ ...c, h: c.h ?? 0, s: c.s ?? 0, v: c.v ?? 0 }));
|
|
797
|
+
}
|
|
798
|
+
else if (channel === "a") {
|
|
799
|
+
this.alpha.set(this.alpha() ?? 255);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
updateRgb(rgba) {
|
|
803
|
+
this.rgb.update(c => ({ ...c, r: rgba.r, g: rgba.g, b: rgba.b }));
|
|
804
|
+
}
|
|
805
|
+
updateRgbFromHsv() {
|
|
806
|
+
const hsv = this.hsv();
|
|
807
|
+
const hue = hsv.h ?? 0;
|
|
808
|
+
const saturation = hsv.s ?? 0;
|
|
809
|
+
const value = hsv.v ?? 0;
|
|
810
|
+
const rgb = hsva2rgba(hue, saturation, value, this.alpha());
|
|
811
|
+
if (this.rgb().r === rgb.r && this.rgb().g === rgb.g && this.rgb().b === rgb.b) {
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
this.rgb.update(c => ({ ...c, r: rgb.r, g: rgb.g, b: rgb.b }));
|
|
815
|
+
if (!this.showButtons()) {
|
|
816
|
+
this.emitValue();
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ColorGradientComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
820
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: ColorGradientComponent, isStandalone: true, selector: "mona-color-gradient", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, opacity: { classPropertyName: "opacity", publicName: "opacity", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, showButtons: { classPropertyName: "showButtons", publicName: "showButtons", isSignal: true, isRequired: false, transformFunction: null }, showHexInput: { classPropertyName: "showHexInput", publicName: "showHexInput", isSignal: true, isRequired: false, transformFunction: null }, showColorInputs: { classPropertyName: "showColorInputs", publicName: "showColorInputs", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { apply: "apply", cancel: "cancel", touch: "touch", value: "valueChange" }, host: { properties: { "class": "baseClasses()", "attr.data-disabled": "disabled()", "attr.data-invalid": "invalidState() || null", "attr.aria-invalid": "invalidState() ? 'true' : null" } }, viewQueries: [{ propertyName: "hsvHandle", first: true, predicate: ["hsvPointer"], descendants: true, isSignal: true }, { propertyName: "hsvRectangle", first: true, predicate: ["hsvRectangle"], descendants: true, isSignal: true }], ngImport: i0, template: "<div [class]=\"hsvRectangleClasses()\" [style.background-color]=\"hsvRectangleBackground()\" #hsvRectangle>\r\n <div\r\n [class]=\"hsvRectangleHandleClasses()\"\r\n [style.left.px]=\"hsvHandleLeft()\"\r\n [style.top.px]=\"hsvHandleTop()\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n [attr.role]=\"'slider'\"\r\n [attr.aria-label]=\"'Color saturation and value'\"\r\n [attr.aria-valuemin]=\"0\"\r\n [attr.aria-valuemax]=\"100\"\r\n [attr.aria-valuenow]=\"hsv().s\"\r\n [attr.aria-valuetext]=\"'Saturation ' + hsv().s + '%, Value ' + hsv().v + '%'\"\r\n [attr.aria-disabled]=\"disabled() || null\"\r\n (keydown)=\"onHsvHandleKeyDown($event)\"\r\n (blur)=\"onHsvHandleBlur()\"\r\n #hsvPointer></div>\r\n</div>\r\n<div class=\"flex items-center gap-2\">\r\n <div class=\"flex flex-1 flex-col gap-1 mr-2\">\r\n <mona-slider\r\n [minValue]=\"0\"\r\n [maxValue]=\"360\"\r\n [trackBackground]=\"'linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000)'\"\r\n [selectionBackground]=\"'transparent'\"\r\n [handleClasses]=\"sliderHandleClasses()\"\r\n [trackSize]=\"sliderHeight\"\r\n [rounded]=\"rounded()\"\r\n [value]=\"hsv().h ?? 0\"\r\n (valueChange)=\"hueValue$.next($event)\"\r\n (touch)=\"onSliderBlur()\"></mona-slider>\r\n @if (opacity()) {\r\n <mona-slider\r\n [minValue]=\"0\"\r\n [maxValue]=\"255\"\r\n [trackBackground]=\"alphaSliderBackground()\"\r\n [selectionBackground]=\"'transparent'\"\r\n [handleClasses]=\"sliderHandleClasses()\"\r\n [trackSize]=\"sliderHeight\"\r\n [rounded]=\"rounded()\"\r\n [value]=\"alpha()\"\r\n (valueChange)=\"onAlphaChange($event)\"\r\n (touch)=\"onSliderBlur()\"></mona-slider>\r\n }\r\n </div>\r\n @for (preview of colorPreviews(); track preview.type) {\r\n <div\r\n [class]=\"colorPreviewClasses()\"\r\n [class.cursor-pointer]=\"$index === 1\"\r\n [style.background-color]=\"preview.color\"\r\n [attr.title]=\"$index === 1 ? preview.title : null\"\r\n [attr.aria-label]=\"$index === 1 ? preview.title : null\"\r\n [attr.aria-hidden]=\"$index === 0 ? 'true' : null\"\r\n [attr.role]=\"$index === 1 ? 'button' : null\"\r\n [attr.tabindex]=\"$index === 1 ? 0 : null\"\r\n (click)=\"preview.onClick?.()\"\r\n (keydown)=\"onPreviousColorKeyDown($event, preview.onClick)\"></div>\r\n }\r\n <button monaButton look=\"ghost\" size=\"small\" aria-label=\"Clear color\" (click)=\"onClearClick()\">\r\n <i class=\"ri-blur-off-line\"></i>\r\n </button>\r\n</div>\r\n<div class=\"flex flex-col gap-2\">\r\n @if (showColorInputs()) {\r\n <div class=\"flex gap-2\">\r\n <div class=\"flex gap-1\">\r\n @for (input of colorInputs(); track input.key) {\r\n <mona-numeric-text-box\r\n [value]=\"input.value\"\r\n [minValue]=\"input.min\"\r\n [maxValue]=\"input.max\"\r\n [decimals]=\"0\"\r\n [spinners]=\"false\"\r\n [nullable]=\"false\"\r\n [rounded]=\"rounded()\"\r\n [size]=\"'small'\"\r\n class=\"w-18\"\r\n (valueChange)=\"input.change($event)\"\r\n (inputBlur)=\"onNumericInputBlur()\">\r\n <ng-template monaNumericTextBoxPrefixTemplate>\r\n <ng-container\r\n [ngTemplateOutlet]=\"numericInputPrefixTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: input.label }\"></ng-container>\r\n </ng-template>\r\n </mona-numeric-text-box>\r\n }\r\n </div>\r\n <div class=\"flex flex-1 items-center justify-end\">\r\n <button\r\n monaButton\r\n look=\"ghost\"\r\n [rounded]=\"rounded()\"\r\n size=\"small\"\r\n aria-label=\"Switch color mode\"\r\n (click)=\"onSwitchColorModeClick()\">\r\n <i class=\"ri-expand-up-down-line\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n @if (showHexInput()) {\r\n <mona-text-box\r\n [rounded]=\"rounded()\"\r\n [value]=\"hex()\"\r\n (valueChange)=\"onHexChange($event)\"\r\n (inputBlur)=\"onHexInputBlur()\"\r\n (inputFocus)=\"onHexInputFocus()\"\r\n class=\"w-full\">\r\n <ng-template monaTextBoxPrefixTemplate>\r\n <ng-container\r\n [ngTemplateOutlet]=\"numericInputPrefixTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: 'HEX', classes: 'w-auto px-2' }\"></ng-container>\r\n </ng-template>\r\n <ng-template monaTextBoxSuffixTemplate>\r\n <mona-dropdown-button look=\"ghost\" aria-label=\"Copy color\" class=\"h-full\">\r\n <svg lucideCopy [size]=\"12\"></svg>\r\n <mona-dropdown-button-item\r\n label=\"Copy as HEX\"\r\n (menuClick)=\"onCopyColorSelect('hex')\"></mona-dropdown-button-item>\r\n <mona-dropdown-button-item\r\n label=\"Copy as RGB\"\r\n (menuClick)=\"onCopyColorSelect('rgb')\"></mona-dropdown-button-item>\r\n </mona-dropdown-button>\r\n </ng-template>\r\n </mona-text-box>\r\n }\r\n @if (showButtons()) {\r\n <div class=\"flex items-center justify-end gap-2\">\r\n <button monaButton [rounded]=\"rounded()\" look=\"primary\" (click)=\"onApply()\">Apply</button>\r\n <button monaButton [rounded]=\"rounded()\" (click)=\"onCancel()\">Cancel</button>\r\n </div>\r\n }\r\n</div>\r\n\r\n<ng-template #numericInputPrefixTemplate let-text let-classes=\"classes\">\r\n <span\r\n [class]=\"classes\"\r\n class=\"inline-flex items-center justify-center select-none w-7.5 bg-secondary h-full text-xs font-semibold border-r border-r-input-border\"\r\n >{{ text }}</span\r\n >\r\n</ng-template>\r\n", dependencies: [{ kind: "component", type: NumericTextBoxComponent, selector: "mona-numeric-text-box", inputs: ["aria-label", "decimals", "disabled", "formatter", "maxValue", "minValue", "nullable", "readonly", "required", "invalid", "rounded", "size", "spinners", "step", "tabindex", "touched", "class", "value"], outputs: ["inputBlur", "inputFocus", "inputFocusOut", "touch", "valueChange"] }, { kind: "directive", type: NumericTextBoxPrefixTemplateDirective, selector: "ng-template[monaNumericTextBoxPrefixTemplate]" }, { kind: "directive", type: ButtonDirective, selector: "button[monaButton]", inputs: ["aria-haspopup", "disabled", "iconOnly", "loading", "look", "rounded", "selected", "size", "tabindex", "toggleable", "class"], outputs: ["disabledChange", "loadingChange", "lookChange", "selectedChange"] }, { kind: "component", type: TextBoxComponent, selector: "mona-text-box", inputs: ["clearButton", "disabled", "inputAttributes", "inputClass", "inputStyle", "invalid", "placeholder", "readonly", "required", "rounded", "size", "touched", "type", "class", "value"], outputs: ["inputBlur", "inputFocus", "touch", "valueChange"] }, { kind: "directive", type: TextBoxPrefixTemplateDirective, selector: "ng-template[monaTextBoxPrefixTemplate]" }, { kind: "directive", type: TextBoxSuffixTemplateDirective, selector: "ng-template[monaTextBoxSuffixTemplate]" }, { kind: "component", type: SliderComponent, selector: "mona-slider", inputs: ["aria-label", "aria-labelledby", "value"], outputs: ["valueChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: DropdownButtonComponent, selector: "mona-dropdown-button", inputs: ["aria-label", "aria-labelledby", "iconOnly", "disabled", "loading", "look", "rounded", "size", "text", "class"], outputs: ["menuItemClick"] }, { kind: "component", type: DropdownButtonItemComponent, selector: "mona-dropdown-button-item" }, { kind: "component", type: LucideCopy, selector: "svg[lucideCopy]" }] }); }
|
|
821
|
+
}
|
|
822
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ColorGradientComponent, decorators: [{
|
|
823
|
+
type: Component,
|
|
824
|
+
args: [{ selector: "mona-color-gradient", imports: [
|
|
825
|
+
NumericTextBoxComponent,
|
|
826
|
+
NumericTextBoxPrefixTemplateDirective,
|
|
827
|
+
ButtonDirective,
|
|
828
|
+
TextBoxComponent,
|
|
829
|
+
TextBoxPrefixTemplateDirective,
|
|
830
|
+
TextBoxSuffixTemplateDirective,
|
|
831
|
+
SliderComponent,
|
|
832
|
+
NgTemplateOutlet,
|
|
833
|
+
DropdownButtonComponent,
|
|
834
|
+
DropdownButtonItemComponent,
|
|
835
|
+
LucideCopy
|
|
836
|
+
], host: {
|
|
837
|
+
"[class]": "baseClasses()",
|
|
838
|
+
"[attr.data-disabled]": "disabled()",
|
|
839
|
+
"[attr.data-invalid]": "invalidState() || null",
|
|
840
|
+
"[attr.aria-invalid]": "invalidState() ? 'true' : null"
|
|
841
|
+
}, template: "<div [class]=\"hsvRectangleClasses()\" [style.background-color]=\"hsvRectangleBackground()\" #hsvRectangle>\r\n <div\r\n [class]=\"hsvRectangleHandleClasses()\"\r\n [style.left.px]=\"hsvHandleLeft()\"\r\n [style.top.px]=\"hsvHandleTop()\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n [attr.role]=\"'slider'\"\r\n [attr.aria-label]=\"'Color saturation and value'\"\r\n [attr.aria-valuemin]=\"0\"\r\n [attr.aria-valuemax]=\"100\"\r\n [attr.aria-valuenow]=\"hsv().s\"\r\n [attr.aria-valuetext]=\"'Saturation ' + hsv().s + '%, Value ' + hsv().v + '%'\"\r\n [attr.aria-disabled]=\"disabled() || null\"\r\n (keydown)=\"onHsvHandleKeyDown($event)\"\r\n (blur)=\"onHsvHandleBlur()\"\r\n #hsvPointer></div>\r\n</div>\r\n<div class=\"flex items-center gap-2\">\r\n <div class=\"flex flex-1 flex-col gap-1 mr-2\">\r\n <mona-slider\r\n [minValue]=\"0\"\r\n [maxValue]=\"360\"\r\n [trackBackground]=\"'linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000)'\"\r\n [selectionBackground]=\"'transparent'\"\r\n [handleClasses]=\"sliderHandleClasses()\"\r\n [trackSize]=\"sliderHeight\"\r\n [rounded]=\"rounded()\"\r\n [value]=\"hsv().h ?? 0\"\r\n (valueChange)=\"hueValue$.next($event)\"\r\n (touch)=\"onSliderBlur()\"></mona-slider>\r\n @if (opacity()) {\r\n <mona-slider\r\n [minValue]=\"0\"\r\n [maxValue]=\"255\"\r\n [trackBackground]=\"alphaSliderBackground()\"\r\n [selectionBackground]=\"'transparent'\"\r\n [handleClasses]=\"sliderHandleClasses()\"\r\n [trackSize]=\"sliderHeight\"\r\n [rounded]=\"rounded()\"\r\n [value]=\"alpha()\"\r\n (valueChange)=\"onAlphaChange($event)\"\r\n (touch)=\"onSliderBlur()\"></mona-slider>\r\n }\r\n </div>\r\n @for (preview of colorPreviews(); track preview.type) {\r\n <div\r\n [class]=\"colorPreviewClasses()\"\r\n [class.cursor-pointer]=\"$index === 1\"\r\n [style.background-color]=\"preview.color\"\r\n [attr.title]=\"$index === 1 ? preview.title : null\"\r\n [attr.aria-label]=\"$index === 1 ? preview.title : null\"\r\n [attr.aria-hidden]=\"$index === 0 ? 'true' : null\"\r\n [attr.role]=\"$index === 1 ? 'button' : null\"\r\n [attr.tabindex]=\"$index === 1 ? 0 : null\"\r\n (click)=\"preview.onClick?.()\"\r\n (keydown)=\"onPreviousColorKeyDown($event, preview.onClick)\"></div>\r\n }\r\n <button monaButton look=\"ghost\" size=\"small\" aria-label=\"Clear color\" (click)=\"onClearClick()\">\r\n <i class=\"ri-blur-off-line\"></i>\r\n </button>\r\n</div>\r\n<div class=\"flex flex-col gap-2\">\r\n @if (showColorInputs()) {\r\n <div class=\"flex gap-2\">\r\n <div class=\"flex gap-1\">\r\n @for (input of colorInputs(); track input.key) {\r\n <mona-numeric-text-box\r\n [value]=\"input.value\"\r\n [minValue]=\"input.min\"\r\n [maxValue]=\"input.max\"\r\n [decimals]=\"0\"\r\n [spinners]=\"false\"\r\n [nullable]=\"false\"\r\n [rounded]=\"rounded()\"\r\n [size]=\"'small'\"\r\n class=\"w-18\"\r\n (valueChange)=\"input.change($event)\"\r\n (inputBlur)=\"onNumericInputBlur()\">\r\n <ng-template monaNumericTextBoxPrefixTemplate>\r\n <ng-container\r\n [ngTemplateOutlet]=\"numericInputPrefixTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: input.label }\"></ng-container>\r\n </ng-template>\r\n </mona-numeric-text-box>\r\n }\r\n </div>\r\n <div class=\"flex flex-1 items-center justify-end\">\r\n <button\r\n monaButton\r\n look=\"ghost\"\r\n [rounded]=\"rounded()\"\r\n size=\"small\"\r\n aria-label=\"Switch color mode\"\r\n (click)=\"onSwitchColorModeClick()\">\r\n <i class=\"ri-expand-up-down-line\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n @if (showHexInput()) {\r\n <mona-text-box\r\n [rounded]=\"rounded()\"\r\n [value]=\"hex()\"\r\n (valueChange)=\"onHexChange($event)\"\r\n (inputBlur)=\"onHexInputBlur()\"\r\n (inputFocus)=\"onHexInputFocus()\"\r\n class=\"w-full\">\r\n <ng-template monaTextBoxPrefixTemplate>\r\n <ng-container\r\n [ngTemplateOutlet]=\"numericInputPrefixTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: 'HEX', classes: 'w-auto px-2' }\"></ng-container>\r\n </ng-template>\r\n <ng-template monaTextBoxSuffixTemplate>\r\n <mona-dropdown-button look=\"ghost\" aria-label=\"Copy color\" class=\"h-full\">\r\n <svg lucideCopy [size]=\"12\"></svg>\r\n <mona-dropdown-button-item\r\n label=\"Copy as HEX\"\r\n (menuClick)=\"onCopyColorSelect('hex')\"></mona-dropdown-button-item>\r\n <mona-dropdown-button-item\r\n label=\"Copy as RGB\"\r\n (menuClick)=\"onCopyColorSelect('rgb')\"></mona-dropdown-button-item>\r\n </mona-dropdown-button>\r\n </ng-template>\r\n </mona-text-box>\r\n }\r\n @if (showButtons()) {\r\n <div class=\"flex items-center justify-end gap-2\">\r\n <button monaButton [rounded]=\"rounded()\" look=\"primary\" (click)=\"onApply()\">Apply</button>\r\n <button monaButton [rounded]=\"rounded()\" (click)=\"onCancel()\">Cancel</button>\r\n </div>\r\n }\r\n</div>\r\n\r\n<ng-template #numericInputPrefixTemplate let-text let-classes=\"classes\">\r\n <span\r\n [class]=\"classes\"\r\n class=\"inline-flex items-center justify-center select-none w-7.5 bg-secondary h-full text-xs font-semibold border-r border-r-input-border\"\r\n >{{ text }}</span\r\n >\r\n</ng-template>\r\n" }]
|
|
842
|
+
}], ctorParameters: () => [], propDecorators: { hsvHandle: [{ type: i0.ViewChild, args: ["hsvPointer", { isSignal: true }] }], hsvRectangle: [{ type: i0.ViewChild, args: ["hsvRectangle", { isSignal: true }] }], apply: [{ type: i0.Output, args: ["apply"] }], cancel: [{ type: i0.Output, args: ["cancel"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], opacity: [{ type: i0.Input, args: [{ isSignal: true, alias: "opacity", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], showButtons: [{ type: i0.Input, args: [{ isSignal: true, alias: "showButtons", required: false }] }], showHexInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHexInput", required: false }] }], showColorInputs: [{ type: i0.Input, args: [{ isSignal: true, alias: "showColorInputs", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
|
|
843
|
+
|
|
844
|
+
/*
|
|
845
|
+
* Public API Surface of @nanahoshi/mona-ui/color-gradient
|
|
846
|
+
*/
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* Generated bundle index. Do not edit.
|
|
850
|
+
*/
|
|
851
|
+
|
|
852
|
+
export { ColorGradientComponent };
|
|
853
|
+
//# sourceMappingURL=nanahoshi-mona-ui-color-gradient.mjs.map
|