@ship-ui/core 0.18.5 → 0.18.11
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/assets/mcp/components.json +2517 -2274
- package/fesm2022/ship-ui-core.mjs +1618 -849
- package/fesm2022/ship-ui-core.mjs.map +1 -1
- package/package.json +2 -1
- package/snippets/ship-ui.code-snippets +292 -258
- package/styles/components/ship-accordion.scss +37 -7
- package/styles/components/ship-blueprint.scss +3 -3
- package/styles/components/ship-button-group.scss +20 -14
- package/styles/components/ship-card.scss +2 -1
- package/styles/components/ship-checkbox.scss +2 -1
- package/styles/components/ship-chip.scss +19 -0
- package/styles/components/ship-color-picker.scss +83 -11
- package/styles/components/ship-dialog.scss +4 -4
- package/styles/components/ship-form-field.scss +2 -1
- package/styles/components/ship-menu.scss +1 -1
- package/styles/components/ship-popover.scss +39 -1
- package/styles/components/ship-progress-bar.scss +1 -1
- package/styles/components/ship-radio.scss +2 -1
- package/styles/components/ship-range-slider.scss +45 -36
- package/styles/components/ship-sheet.utility.scss +2 -1
- package/styles/components/ship-sidenav.scss +3 -3
- package/styles/components/ship-sortable.scss +1 -1
- package/styles/components/ship-table.scss +1 -1
- package/styles/components/ship-tabs.scss +1 -1
- package/styles/components/ship-toggle-card.scss +1 -1
- package/styles/core/apexcharts/apexcharts.scss +4 -4
- package/styles/core/core/variables.scss +39 -34
- package/types/ship-ui-core.d.ts +134 -29
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, inject, computed, ElementRef, Renderer2, input, ChangeDetectionStrategy, Component, viewChild, effect, HostListener, NgModule, signal, Injectable, DOCUMENT, model, output, ApplicationRef, OutputEmitterRef, TemplateRef, createComponent, isSignal, DestroyRef, PLATFORM_ID, ViewChild, Directive, contentChild, contentChildren, afterNextRender, Injector, HostBinding,
|
|
2
|
+
import { InjectionToken, inject, computed, ElementRef, Renderer2, input, ChangeDetectionStrategy, Component, viewChild, effect, HostListener, NgModule, signal, Injectable, DOCUMENT, model, output, ApplicationRef, OutputEmitterRef, TemplateRef, createComponent, isSignal, DestroyRef, PLATFORM_ID, ViewChild, Directive, untracked, contentChild, contentChildren, afterNextRender, Injector, HostBinding, runInInjectionContext, ChangeDetectorRef, viewChildren, ViewContainerRef, EnvironmentInjector } from '@angular/core';
|
|
3
3
|
import { isPlatformBrowser, JsonPipe, DatePipe, isPlatformServer, NgTemplateOutlet } from '@angular/common';
|
|
4
|
+
import { ShipButton as ShipButton$1 } from 'ship-ui';
|
|
4
5
|
import { NgModel } from '@angular/forms';
|
|
5
6
|
import { SIGNAL } from '@angular/core/primitives/signals';
|
|
6
7
|
|
|
8
|
+
const defaultThemeColors = {
|
|
9
|
+
primary: 'hsl(217, 91%, 60%)',
|
|
10
|
+
accent: 'hsl(258, 90%, 66%)',
|
|
11
|
+
warn: 'hsl(37, 92%, 50%)',
|
|
12
|
+
error: 'hsl(0, 84%, 60%)',
|
|
13
|
+
success: 'hsl(159, 84%, 39%)',
|
|
14
|
+
base: 'hsl(0, 0%, 46%)'
|
|
15
|
+
};
|
|
7
16
|
const SHIP_CONFIG = new InjectionToken('Ship UI Config');
|
|
8
17
|
|
|
9
18
|
function shipComponentClasses(componentName, inputs) {
|
|
@@ -40,6 +49,8 @@ function shipComponentClasses(componentName, inputs) {
|
|
|
40
49
|
const dynamic = (inputs.dynamic?.() ?? componentConfig?.dynamic) || false;
|
|
41
50
|
// Resolve readonly (Input > Component Config > false)
|
|
42
51
|
const readonly = (inputs.readonly?.() ?? componentConfig?.readonly) || false;
|
|
52
|
+
// Resolve alwaysShow (Input > Component Config > false)
|
|
53
|
+
const alwaysShow = (inputs.alwaysShow?.() ?? componentConfig?.alwaysShow) || false;
|
|
43
54
|
const classList = [];
|
|
44
55
|
if (color)
|
|
45
56
|
classList.push(color);
|
|
@@ -60,6 +71,8 @@ function shipComponentClasses(componentName, inputs) {
|
|
|
60
71
|
classList.push('dynamic');
|
|
61
72
|
if (readonly)
|
|
62
73
|
classList.push('readonly');
|
|
74
|
+
if (alwaysShow)
|
|
75
|
+
classList.push('always-show');
|
|
63
76
|
return classList.join(' ');
|
|
64
77
|
});
|
|
65
78
|
}
|
|
@@ -654,6 +667,145 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
654
667
|
}]
|
|
655
668
|
}] });
|
|
656
669
|
|
|
670
|
+
function contentProjectionSignal(querySelector, options = { childList: true }) {
|
|
671
|
+
const hostElement = inject((ElementRef)).nativeElement;
|
|
672
|
+
const destroyRef = inject(DestroyRef);
|
|
673
|
+
const projectedElementsSignal = signal([], ...(ngDevMode ? [{ debugName: "projectedElementsSignal" }] : /* istanbul ignore next */ []));
|
|
674
|
+
const updateElements = () => {
|
|
675
|
+
projectedElementsSignal.set(Array.from(hostElement.querySelectorAll(querySelector)));
|
|
676
|
+
};
|
|
677
|
+
updateElements();
|
|
678
|
+
if (typeof MutationObserver === 'undefined')
|
|
679
|
+
return projectedElementsSignal.asReadonly();
|
|
680
|
+
const observer = new MutationObserver((mutations) => {
|
|
681
|
+
const hasChildListChanges = mutations.some((mutation) => mutation.type === 'childList');
|
|
682
|
+
if (hasChildListChanges) {
|
|
683
|
+
updateElements();
|
|
684
|
+
}
|
|
685
|
+
});
|
|
686
|
+
observer.observe(hostElement, options);
|
|
687
|
+
destroyRef.onDestroy(() => observer.disconnect());
|
|
688
|
+
return projectedElementsSignal.asReadonly();
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
class ShipAccordion {
|
|
692
|
+
constructor() {
|
|
693
|
+
this.selfElement = inject((ElementRef)).nativeElement;
|
|
694
|
+
this.name = input(`sh-accordion-${Math.random().toString(36).substring(2, 9)}`, ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
695
|
+
this.value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
696
|
+
this.allowMultiple = input(false, ...(ngDevMode ? [{ debugName: "allowMultiple" }] : /* istanbul ignore next */ []));
|
|
697
|
+
this.variant = input(null, ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
698
|
+
this.size = input(null, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
699
|
+
this.hostClasses = shipComponentClasses('accordion', {
|
|
700
|
+
variant: this.variant,
|
|
701
|
+
size: this.size,
|
|
702
|
+
});
|
|
703
|
+
this.items = contentProjectionSignal('details', {
|
|
704
|
+
childList: true,
|
|
705
|
+
subtree: true,
|
|
706
|
+
attributes: true,
|
|
707
|
+
attributeFilter: ['open', 'value'],
|
|
708
|
+
});
|
|
709
|
+
this.selfElement.addEventListener('toggle', this.onToggle.bind(this), true);
|
|
710
|
+
effect(() => {
|
|
711
|
+
const isMultiple = this.allowMultiple();
|
|
712
|
+
const groupName = this.name();
|
|
713
|
+
const valStr = this.value();
|
|
714
|
+
const vals = valStr ? valStr.split(',').filter((v) => v !== '') : [];
|
|
715
|
+
this.items().forEach((details) => {
|
|
716
|
+
if (!isMultiple) {
|
|
717
|
+
details.setAttribute('name', groupName);
|
|
718
|
+
}
|
|
719
|
+
else {
|
|
720
|
+
details.removeAttribute('name');
|
|
721
|
+
}
|
|
722
|
+
const summary = details.querySelector('summary');
|
|
723
|
+
if (summary && !summary.querySelector('sh-icon')) {
|
|
724
|
+
const icon = document.createElement('sh-icon');
|
|
725
|
+
icon.textContent = 'caret-down';
|
|
726
|
+
summary.appendChild(icon);
|
|
727
|
+
}
|
|
728
|
+
let contentWrapper = details.querySelector(':scope > .content');
|
|
729
|
+
if (!contentWrapper) {
|
|
730
|
+
const newWrapper = document.createElement('div');
|
|
731
|
+
newWrapper.className = 'content';
|
|
732
|
+
const childrenToMove = Array.from(details.childNodes).filter((node) => {
|
|
733
|
+
if (node.nodeType === Node.ELEMENT_NODE &&
|
|
734
|
+
node.tagName.toLowerCase() === 'summary') {
|
|
735
|
+
return false;
|
|
736
|
+
}
|
|
737
|
+
return true;
|
|
738
|
+
});
|
|
739
|
+
childrenToMove.forEach((child) => newWrapper.appendChild(child));
|
|
740
|
+
details.appendChild(newWrapper);
|
|
741
|
+
contentWrapper = newWrapper;
|
|
742
|
+
}
|
|
743
|
+
const itemVal = details.getAttribute('value');
|
|
744
|
+
if (itemVal && vals.includes(itemVal)) {
|
|
745
|
+
// Avoid triggering endless loops by only setting open if it actually changed
|
|
746
|
+
if (!details.open)
|
|
747
|
+
details.open = true;
|
|
748
|
+
}
|
|
749
|
+
else if (itemVal) {
|
|
750
|
+
if (details.open)
|
|
751
|
+
details.open = false;
|
|
752
|
+
}
|
|
753
|
+
});
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
onToggle(event) {
|
|
757
|
+
const target = event.target;
|
|
758
|
+
if (target.tagName !== 'DETAILS')
|
|
759
|
+
return;
|
|
760
|
+
if (!this.selfElement.contains(target))
|
|
761
|
+
return;
|
|
762
|
+
const itemVal = target.getAttribute('value');
|
|
763
|
+
if (!itemVal)
|
|
764
|
+
return; // Uncontrolled details element
|
|
765
|
+
const isOpen = target.open;
|
|
766
|
+
if (this.allowMultiple()) {
|
|
767
|
+
let vals = this.value()
|
|
768
|
+
? this.value()
|
|
769
|
+
.split(',')
|
|
770
|
+
.filter((v) => v !== '')
|
|
771
|
+
: [];
|
|
772
|
+
if (isOpen && !vals.includes(itemVal))
|
|
773
|
+
vals.push(itemVal);
|
|
774
|
+
if (!isOpen)
|
|
775
|
+
vals = vals.filter((v) => v !== itemVal);
|
|
776
|
+
this.value.set(vals.join(','));
|
|
777
|
+
}
|
|
778
|
+
else {
|
|
779
|
+
if (isOpen) {
|
|
780
|
+
this.value.set(itemVal);
|
|
781
|
+
}
|
|
782
|
+
else {
|
|
783
|
+
if (this.value() === itemVal) {
|
|
784
|
+
this.value.set(null);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipAccordion, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
790
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: ShipAccordion, isStandalone: true, selector: "sh-accordion", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, allowMultiple: { classPropertyName: "allowMultiple", publicName: "allowMultiple", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { properties: { "class.sh-accordion": "true", "class": "hostClasses()" } }, ngImport: i0, template: `
|
|
791
|
+
<ng-content></ng-content>
|
|
792
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
793
|
+
}
|
|
794
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipAccordion, decorators: [{
|
|
795
|
+
type: Component,
|
|
796
|
+
args: [{
|
|
797
|
+
selector: 'sh-accordion',
|
|
798
|
+
template: `
|
|
799
|
+
<ng-content></ng-content>
|
|
800
|
+
`,
|
|
801
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
802
|
+
host: {
|
|
803
|
+
'[class.sh-accordion]': 'true',
|
|
804
|
+
'[class]': 'hostClasses()',
|
|
805
|
+
},
|
|
806
|
+
}]
|
|
807
|
+
}], ctorParameters: () => [], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], allowMultiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowMultiple", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
808
|
+
|
|
657
809
|
function classMutationSignal(_element = null) {
|
|
658
810
|
const element = _element ?? inject(ElementRef).nativeElement;
|
|
659
811
|
if (!element)
|
|
@@ -1788,27 +1940,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
1788
1940
|
args: ['document:touchend', ['$event']]
|
|
1789
1941
|
}] } });
|
|
1790
1942
|
|
|
1791
|
-
function contentProjectionSignal(querySelector, options = { childList: true }) {
|
|
1792
|
-
const hostElement = inject((ElementRef)).nativeElement;
|
|
1793
|
-
const destroyRef = inject(DestroyRef);
|
|
1794
|
-
const projectedElementsSignal = signal([], ...(ngDevMode ? [{ debugName: "projectedElementsSignal" }] : /* istanbul ignore next */ []));
|
|
1795
|
-
const updateElements = () => {
|
|
1796
|
-
projectedElementsSignal.set(Array.from(hostElement.querySelectorAll(querySelector)));
|
|
1797
|
-
};
|
|
1798
|
-
updateElements();
|
|
1799
|
-
if (typeof MutationObserver === 'undefined')
|
|
1800
|
-
return projectedElementsSignal.asReadonly();
|
|
1801
|
-
const observer = new MutationObserver((mutations) => {
|
|
1802
|
-
const hasChildListChanges = mutations.some((mutation) => mutation.type === 'childList');
|
|
1803
|
-
if (hasChildListChanges) {
|
|
1804
|
-
updateElements();
|
|
1805
|
-
}
|
|
1806
|
-
});
|
|
1807
|
-
observer.observe(hostElement, options);
|
|
1808
|
-
destroyRef.onDestroy(() => observer.disconnect());
|
|
1809
|
-
return projectedElementsSignal.asReadonly();
|
|
1810
|
-
}
|
|
1811
|
-
|
|
1812
1943
|
class ShipSelectionGroup {
|
|
1813
1944
|
constructor(itemSelector, activeClass) {
|
|
1814
1945
|
this.itemSelector = itemSelector;
|
|
@@ -2112,69 +2243,313 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
2112
2243
|
}]
|
|
2113
2244
|
}], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], sharp: [{ type: i0.Input, args: [{ isSignal: true, alias: "sharp", required: false }] }], dynamic: [{ type: i0.Input, args: [{ isSignal: true, alias: "dynamic", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }] } });
|
|
2114
2245
|
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2246
|
+
function hslToRgbExact(h, s, l) {
|
|
2247
|
+
s /= 100;
|
|
2248
|
+
l /= 100;
|
|
2249
|
+
const k = (n) => (n + h / 30) % 12;
|
|
2250
|
+
const a = s * Math.min(l, 1 - l);
|
|
2251
|
+
const f = (n) => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
|
|
2252
|
+
return [Math.round(255 * f(0)), Math.round(255 * f(8)), Math.round(255 * f(4))];
|
|
2253
|
+
}
|
|
2254
|
+
function hsvToRgbExact(h, s, v) {
|
|
2255
|
+
const sNorm = s / 100;
|
|
2256
|
+
const vNorm = v / 100;
|
|
2257
|
+
const c = vNorm * sNorm;
|
|
2258
|
+
const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
|
|
2259
|
+
const m = vNorm - c;
|
|
2260
|
+
let r = 0, g = 0, b = 0;
|
|
2261
|
+
if (h >= 0 && h < 60) {
|
|
2262
|
+
r = c;
|
|
2263
|
+
g = x;
|
|
2264
|
+
b = 0;
|
|
2265
|
+
}
|
|
2266
|
+
else if (h >= 60 && h < 120) {
|
|
2267
|
+
r = x;
|
|
2268
|
+
g = c;
|
|
2269
|
+
b = 0;
|
|
2270
|
+
}
|
|
2271
|
+
else if (h >= 120 && h < 180) {
|
|
2272
|
+
r = 0;
|
|
2273
|
+
g = c;
|
|
2274
|
+
b = x;
|
|
2275
|
+
}
|
|
2276
|
+
else if (h >= 180 && h < 240) {
|
|
2277
|
+
r = 0;
|
|
2278
|
+
g = x;
|
|
2279
|
+
b = c;
|
|
2280
|
+
}
|
|
2281
|
+
else if (h >= 240 && h < 300) {
|
|
2282
|
+
r = x;
|
|
2283
|
+
g = 0;
|
|
2284
|
+
b = c;
|
|
2285
|
+
}
|
|
2286
|
+
else if (h >= 300 && h < 360) {
|
|
2287
|
+
r = c;
|
|
2288
|
+
g = 0;
|
|
2289
|
+
b = x;
|
|
2290
|
+
}
|
|
2291
|
+
return [Math.round((r + m) * 255), Math.round((g + m) * 255), Math.round((b + m) * 255)];
|
|
2292
|
+
}
|
|
2293
|
+
function rgbToHsv(r, g, b) {
|
|
2294
|
+
r /= 255;
|
|
2295
|
+
g /= 255;
|
|
2296
|
+
b /= 255;
|
|
2297
|
+
const max = Math.max(r, g, b), min = Math.min(r, g, b);
|
|
2298
|
+
const d = max - min;
|
|
2299
|
+
const v = max;
|
|
2300
|
+
const s = max === 0 ? 0 : d / max;
|
|
2301
|
+
let h = 0;
|
|
2302
|
+
if (max !== min) {
|
|
2303
|
+
switch (max) {
|
|
2304
|
+
case r:
|
|
2305
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
2306
|
+
break;
|
|
2307
|
+
case g:
|
|
2308
|
+
h = (b - r) / d + 2;
|
|
2309
|
+
break;
|
|
2310
|
+
case b:
|
|
2311
|
+
h = (r - g) / d + 4;
|
|
2312
|
+
break;
|
|
2313
|
+
}
|
|
2314
|
+
h /= 6;
|
|
2315
|
+
}
|
|
2316
|
+
return { h: h * 360, s: s * 100, v: v * 100 };
|
|
2317
|
+
}
|
|
2318
|
+
function rgbToHex(r, g, b) {
|
|
2319
|
+
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
|
|
2320
|
+
}
|
|
2321
|
+
function rgbaToHex8(r, g, b, a) {
|
|
2322
|
+
const alphaHex = Math.round(a * 255)
|
|
2323
|
+
.toString(16)
|
|
2324
|
+
.padStart(2, '0');
|
|
2325
|
+
return rgbToHex(r, g, b) + alphaHex;
|
|
2326
|
+
}
|
|
2327
|
+
function rgbToHsl(r, g, b) {
|
|
2328
|
+
r /= 255;
|
|
2329
|
+
g /= 255;
|
|
2330
|
+
b /= 255;
|
|
2331
|
+
const max = Math.max(r, g, b), min = Math.min(r, g, b);
|
|
2332
|
+
let h = 0, s = 0, l = (max + min) / 2;
|
|
2333
|
+
if (max === min) {
|
|
2334
|
+
h = s = 0;
|
|
2335
|
+
}
|
|
2336
|
+
else {
|
|
2337
|
+
const d = max - min;
|
|
2338
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
2339
|
+
switch (max) {
|
|
2340
|
+
case r:
|
|
2341
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
2342
|
+
break;
|
|
2343
|
+
case g:
|
|
2344
|
+
h = (b - r) / d + 2;
|
|
2345
|
+
break;
|
|
2346
|
+
case b:
|
|
2347
|
+
h = (r - g) / d + 4;
|
|
2348
|
+
break;
|
|
2349
|
+
}
|
|
2350
|
+
h /= 6;
|
|
2351
|
+
}
|
|
2352
|
+
const hDeg = Math.floor(h * 360);
|
|
2353
|
+
const sPct = Math.round(s * 100);
|
|
2354
|
+
const lPct = Math.round(l * 100);
|
|
2355
|
+
return {
|
|
2356
|
+
h: hDeg,
|
|
2357
|
+
s: sPct,
|
|
2358
|
+
l: lPct,
|
|
2359
|
+
string: `hsl(${hDeg}, ${sPct}%, ${lPct}%)`,
|
|
2360
|
+
};
|
|
2361
|
+
}
|
|
2362
|
+
function rgbToOklch(r, g, b) {
|
|
2363
|
+
// Convert sRGB to Linear sRGB
|
|
2364
|
+
const toLinear = (c) => {
|
|
2365
|
+
const v = c / 255;
|
|
2366
|
+
return v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
|
|
2367
|
+
};
|
|
2368
|
+
const lr = toLinear(r);
|
|
2369
|
+
const lg = toLinear(g);
|
|
2370
|
+
const lb = toLinear(b);
|
|
2371
|
+
// Convert Linear sRGB to LMS (Oklab intermediate)
|
|
2372
|
+
const l = 0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb;
|
|
2373
|
+
const m = 0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb;
|
|
2374
|
+
const s = 0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb;
|
|
2375
|
+
// Cube root of LMS
|
|
2376
|
+
const l_ = Math.cbrt(l);
|
|
2377
|
+
const m_ = Math.cbrt(m);
|
|
2378
|
+
const s_ = Math.cbrt(s);
|
|
2379
|
+
// Convert LMS to OKLAB
|
|
2380
|
+
const oklabL = 0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_;
|
|
2381
|
+
const oklabA = 1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_;
|
|
2382
|
+
const oklabB = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_;
|
|
2383
|
+
// Convert OKLAB to OKLCH
|
|
2384
|
+
const chroma = Math.sqrt(oklabA * oklabA + oklabB * oklabB);
|
|
2385
|
+
let hue = Math.atan2(oklabB, oklabA) * (180 / Math.PI);
|
|
2386
|
+
if (hue < 0)
|
|
2387
|
+
hue += 360;
|
|
2388
|
+
return { l: oklabL, c: chroma, h: hue };
|
|
2389
|
+
}
|
|
2390
|
+
function hslToOklch(h, s, l) {
|
|
2391
|
+
const [r, g, b] = hslToRgbExact(h, s, l);
|
|
2392
|
+
return rgbToOklch(r, g, b);
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2118
2395
|
class ShipColorPicker {
|
|
2119
2396
|
constructor() {
|
|
2120
2397
|
this.#document = inject(DOCUMENT);
|
|
2398
|
+
this.#platformId = inject(PLATFORM_ID);
|
|
2121
2399
|
this.canvasRef = viewChild.required('colorCanvas');
|
|
2122
|
-
this
|
|
2400
|
+
this.#canvasData = signal(null, ...(ngDevMode ? [{ debugName: "#canvasData" }] : /* istanbul ignore next */ []));
|
|
2123
2401
|
this.showDarkColors = input(false, ...(ngDevMode ? [{ debugName: "showDarkColors" }] : /* istanbul ignore next */ []));
|
|
2124
2402
|
this.renderingType = input('hsl', ...(ngDevMode ? [{ debugName: "renderingType" }] : /* istanbul ignore next */ []));
|
|
2125
2403
|
this.gridSize = input(20, ...(ngDevMode ? [{ debugName: "gridSize" }] : /* istanbul ignore next */ []));
|
|
2126
|
-
this.hue =
|
|
2404
|
+
this.hue = model(0, ...(ngDevMode ? [{ debugName: "hue" }] : /* istanbul ignore next */ []));
|
|
2127
2405
|
this.direction = input('horizontal', ...(ngDevMode ? [{ debugName: "direction" }] : /* istanbul ignore next */ []));
|
|
2128
|
-
this.selectedColor = model([255, 255, 255], ...(ngDevMode ? [{ debugName: "selectedColor" }] : /* istanbul ignore next */ []));
|
|
2406
|
+
this.selectedColor = model([255, 255, 255, 1], ...(ngDevMode ? [{ debugName: "selectedColor" }] : /* istanbul ignore next */ []));
|
|
2407
|
+
this.alpha = model(1, ...(ngDevMode ? [{ debugName: "alpha" }] : /* istanbul ignore next */ []));
|
|
2129
2408
|
this.currentColor = output();
|
|
2130
2409
|
this.centerLightness = computed(() => (this.showDarkColors() ? 200 : 100), ...(ngDevMode ? [{ debugName: "centerLightness" }] : /* istanbul ignore next */ []));
|
|
2131
2410
|
this.isDragging = signal(false, ...(ngDevMode ? [{ debugName: "isDragging" }] : /* istanbul ignore next */ []));
|
|
2132
2411
|
this.markerPosition = signal({ x: '50%', y: '50%' }, ...(ngDevMode ? [{ debugName: "markerPosition" }] : /* istanbul ignore next */ []));
|
|
2133
2412
|
this._pos = { x: '0', y: '0' };
|
|
2134
2413
|
this._markerPosition = effect(() => (this._pos = this.markerPosition()), ...(ngDevMode ? [{ debugName: "_markerPosition" }] : /* istanbul ignore next */ []));
|
|
2135
|
-
this
|
|
2136
|
-
this.
|
|
2137
|
-
|
|
2414
|
+
this.#skipMarkerUpdate = false;
|
|
2415
|
+
this.selectedColorRgb = computed(() => {
|
|
2416
|
+
const c = this.selectedColor();
|
|
2417
|
+
return c[3] !== undefined ? `rgba(${c[0]},${c[1]},${c[2]},${c[3]})` : `rgb(${c[0]},${c[1]},${c[2]})`;
|
|
2418
|
+
}, ...(ngDevMode ? [{ debugName: "selectedColorRgb" }] : /* istanbul ignore next */ []));
|
|
2419
|
+
this.selectedColorHex = computed(() => rgbToHex(...this.selectedColor()), ...(ngDevMode ? [{ debugName: "selectedColorHex" }] : /* istanbul ignore next */ []));
|
|
2420
|
+
this.selectedColorHsl = computed(() => rgbToHsl(...this.selectedColor()).string, ...(ngDevMode ? [{ debugName: "selectedColorHsl" }] : /* istanbul ignore next */ []));
|
|
2421
|
+
this.alphaEffect = effect(() => {
|
|
2422
|
+
const a = this.alpha();
|
|
2423
|
+
const current = untracked(() => this.selectedColor());
|
|
2424
|
+
if (current[3] !== a) {
|
|
2425
|
+
this.#skipMarkerUpdate = false;
|
|
2426
|
+
this.selectedColor.set([current[0], current[1], current[2], a]);
|
|
2427
|
+
}
|
|
2428
|
+
}, ...(ngDevMode ? [{ debugName: "alphaEffect" }] : /* istanbul ignore next */ []));
|
|
2429
|
+
this._prevColorStr = '';
|
|
2138
2430
|
this.selectedColorEffect = effect(() => {
|
|
2139
2431
|
const selectedColor = this.selectedColor();
|
|
2140
|
-
const
|
|
2141
|
-
const
|
|
2142
|
-
|
|
2432
|
+
const r = selectedColor[0];
|
|
2433
|
+
const g = selectedColor[1];
|
|
2434
|
+
const b = selectedColor[2];
|
|
2435
|
+
const a = selectedColor[3] ?? 1;
|
|
2436
|
+
untracked(() => {
|
|
2437
|
+
if (this.alpha() !== a) {
|
|
2438
|
+
this.alpha.set(a);
|
|
2439
|
+
}
|
|
2440
|
+
});
|
|
2441
|
+
const str = `${r},${g},${b},${a}`;
|
|
2442
|
+
if (this._prevColorStr === str && !this.#skipMarkerUpdate) {
|
|
2443
|
+
// We still want to clear skipMarkerUpdate if it was set
|
|
2444
|
+
// wait, actually if skipMarkerUpdate is true, it means we JUST dragged.
|
|
2445
|
+
// In that case we do want to emit currentColor.
|
|
2446
|
+
}
|
|
2447
|
+
const hsl = rgbToHsl(r, g, b);
|
|
2448
|
+
const hex = rgbToHex(r, g, b);
|
|
2449
|
+
if (this.#skipMarkerUpdate) {
|
|
2450
|
+
this.#skipMarkerUpdate = false;
|
|
2451
|
+
this._prevColorStr = str;
|
|
2452
|
+
}
|
|
2453
|
+
else {
|
|
2454
|
+
if (this._prevColorStr !== str) {
|
|
2455
|
+
this.updateMarkerFromColor(selectedColor);
|
|
2456
|
+
this._prevColorStr = str;
|
|
2457
|
+
}
|
|
2458
|
+
else {
|
|
2459
|
+
// Color is structurally identical and not from a drag event, skip marker jump
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2143
2462
|
this.currentColor.emit({
|
|
2144
|
-
rgb: `rgb(${
|
|
2463
|
+
rgb: `rgb(${r}, ${g}, ${b})`,
|
|
2464
|
+
rgba: `rgba(${r}, ${g}, ${b}, ${a})`,
|
|
2145
2465
|
hex: hex,
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2466
|
+
hex8: rgbaToHex8(r, g, b, a),
|
|
2467
|
+
hsl: hsl.string,
|
|
2468
|
+
hsla: `hsla(${hsl.h}, ${hsl.s}%, ${hsl.l}%, ${a})`,
|
|
2469
|
+
hue: hsl.h,
|
|
2470
|
+
saturation: hsl.s,
|
|
2471
|
+
alpha: a,
|
|
2149
2472
|
});
|
|
2150
2473
|
}, ...(ngDevMode ? [{ debugName: "selectedColorEffect" }] : /* istanbul ignore next */ []));
|
|
2474
|
+
this.alphaColorRedrawEffect = effect(() => {
|
|
2475
|
+
const color = this.selectedColor();
|
|
2476
|
+
if (this.renderingType() === 'alpha' && this.#canvasData()) {
|
|
2477
|
+
untracked(() => this.drawAlpha());
|
|
2478
|
+
}
|
|
2479
|
+
}, ...(ngDevMode ? [{ debugName: "alphaColorRedrawEffect" }] : /* istanbul ignore next */ []));
|
|
2480
|
+
this.previousLayoutHash = '';
|
|
2481
|
+
this.previousHue = null;
|
|
2151
2482
|
this.renderingTypeEffect = effect(() => {
|
|
2152
|
-
const
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2483
|
+
const currentHue = this.hue();
|
|
2484
|
+
const layoutHash = this.getLayoutHash();
|
|
2485
|
+
const canvasData = untracked(() => this.#canvasData());
|
|
2486
|
+
if (canvasData) {
|
|
2487
|
+
untracked(() => this.drawColorPicker());
|
|
2488
|
+
if (this.previousLayoutHash !== layoutHash) {
|
|
2489
|
+
if (this.renderingType() === 'hsl') {
|
|
2490
|
+
this.adjustMarkerPosition();
|
|
2491
|
+
queueMicrotask(() => this.updateMarkerFromColor(untracked(() => this.selectedColor())));
|
|
2492
|
+
}
|
|
2493
|
+
else {
|
|
2494
|
+
this.updateMarkerFromColor(untracked(() => this.selectedColor()));
|
|
2495
|
+
}
|
|
2496
|
+
this.previousLayoutHash = layoutHash;
|
|
2497
|
+
this.previousHue = currentHue;
|
|
2158
2498
|
}
|
|
2159
|
-
else {
|
|
2160
|
-
|
|
2499
|
+
else if (this.previousHue !== currentHue) {
|
|
2500
|
+
const pos = untracked(() => this.markerPosition());
|
|
2501
|
+
const { canvas, ctx } = canvasData;
|
|
2502
|
+
let x = (parseFloat(pos.x.replace('%', '')) / 100) * Math.max(1, canvas.width - 1);
|
|
2503
|
+
let y = (parseFloat(pos.y.replace('%', '')) / 100) * Math.max(1, canvas.height - 1);
|
|
2504
|
+
x = Math.max(0, Math.min(canvas.width - 1, Math.round(x)));
|
|
2505
|
+
y = Math.max(0, Math.min(canvas.height - 1, Math.round(y)));
|
|
2506
|
+
const color = untracked(() => this.getColorAtPosition(x, y));
|
|
2507
|
+
if (this.renderingType() !== 'alpha') {
|
|
2508
|
+
color[3] = untracked(() => this.selectedColor()[3] ?? 1);
|
|
2509
|
+
}
|
|
2510
|
+
this.#skipMarkerUpdate = true;
|
|
2511
|
+
this.selectedColor.set(color);
|
|
2512
|
+
this.previousHue = currentHue;
|
|
2161
2513
|
}
|
|
2162
2514
|
}
|
|
2163
2515
|
}, ...(ngDevMode ? [{ debugName: "renderingTypeEffect" }] : /* istanbul ignore next */ []));
|
|
2516
|
+
this.#resizeObserver = typeof ResizeObserver !== 'undefined'
|
|
2517
|
+
? new ResizeObserver((entries) => {
|
|
2518
|
+
for (const entry of entries) {
|
|
2519
|
+
if (entry.contentRect.width > 0 && entry.contentRect.height > 0) {
|
|
2520
|
+
this.setCanvasSize();
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
})
|
|
2524
|
+
: null;
|
|
2164
2525
|
this.initColor = null;
|
|
2165
2526
|
}
|
|
2166
2527
|
#document;
|
|
2528
|
+
#platformId;
|
|
2529
|
+
#canvasData;
|
|
2530
|
+
#skipMarkerUpdate;
|
|
2167
2531
|
onResize() {
|
|
2168
2532
|
this.setCanvasSize();
|
|
2169
2533
|
}
|
|
2534
|
+
getLayoutHash() {
|
|
2535
|
+
return `${this.renderingType()}-${this.direction()}-${this.gridSize()}-${this.showDarkColors()}`;
|
|
2536
|
+
}
|
|
2537
|
+
#resizeObserver;
|
|
2170
2538
|
ngAfterViewInit() {
|
|
2171
2539
|
this.initColor = this.selectedColor();
|
|
2540
|
+
const canvas = this.canvasRef()?.nativeElement;
|
|
2541
|
+
if (canvas?.parentElement) {
|
|
2542
|
+
this.#resizeObserver?.observe(canvas.parentElement);
|
|
2543
|
+
}
|
|
2172
2544
|
this.setCanvasSize();
|
|
2173
2545
|
this.initCanvasEvents();
|
|
2174
2546
|
}
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2547
|
+
ngOnDestroy() {
|
|
2548
|
+
this.#resizeObserver?.disconnect();
|
|
2549
|
+
}
|
|
2550
|
+
updateMarkerFromColor(rgba) {
|
|
2551
|
+
const [r, g, b, a] = rgba;
|
|
2552
|
+
const coords = this.findPositionByColor(r, g, b, a);
|
|
2178
2553
|
if (coords === null)
|
|
2179
2554
|
return;
|
|
2180
2555
|
const { x, y } = coords;
|
|
@@ -2187,11 +2562,63 @@ class ShipColorPicker {
|
|
|
2187
2562
|
};
|
|
2188
2563
|
this.updateColorAndMarker(mockEvent, false, true);
|
|
2189
2564
|
}
|
|
2190
|
-
findPositionByColor(r, g, b) {
|
|
2191
|
-
const canvasData = this
|
|
2565
|
+
findPositionByColor(r, g, b, a) {
|
|
2566
|
+
const canvasData = this.#canvasData();
|
|
2192
2567
|
if (!canvasData || !canvasData.canvas)
|
|
2193
2568
|
return null;
|
|
2194
2569
|
const { canvas, ctx } = canvasData;
|
|
2570
|
+
if (canvas.width === 0 || canvas.height === 0)
|
|
2571
|
+
return null;
|
|
2572
|
+
if (this.renderingType() === 'alpha') {
|
|
2573
|
+
const aVal = a ?? 1;
|
|
2574
|
+
if (this.direction() === 'horizontal') {
|
|
2575
|
+
return { x: Math.round(aVal * (canvas.width - 1)), y: Math.round((canvas.height - 1) / 2) };
|
|
2576
|
+
}
|
|
2577
|
+
else {
|
|
2578
|
+
return { x: Math.round((canvas.width - 1) / 2), y: Math.round(aVal * (canvas.height - 1)) };
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
if (this.renderingType() === 'hue') {
|
|
2582
|
+
const hsl = rgbToHsl(r, g, b);
|
|
2583
|
+
const ratio = hsl.h / 360;
|
|
2584
|
+
if (this.direction() === 'horizontal') {
|
|
2585
|
+
return { x: Math.round(ratio * (canvas.width - 1)), y: Math.round((canvas.height - 1) / 2) };
|
|
2586
|
+
}
|
|
2587
|
+
else {
|
|
2588
|
+
return { x: Math.round((canvas.width - 1) / 2), y: Math.round(ratio * (canvas.height - 1)) };
|
|
2589
|
+
}
|
|
2590
|
+
}
|
|
2591
|
+
if (this.renderingType() === 'rgb') {
|
|
2592
|
+
const hsv = rgbToHsv(r, g, b);
|
|
2593
|
+
return {
|
|
2594
|
+
x: Math.round((hsv.s / 100) * (canvas.width - 1)),
|
|
2595
|
+
y: Math.round((1 - hsv.v / 100) * (canvas.height - 1)),
|
|
2596
|
+
};
|
|
2597
|
+
}
|
|
2598
|
+
if (this.renderingType() === 'saturation') {
|
|
2599
|
+
const hsl = rgbToHsl(r, g, b);
|
|
2600
|
+
const ratio = hsl.s / 100;
|
|
2601
|
+
if (this.direction() === 'horizontal') {
|
|
2602
|
+
return { x: Math.round(ratio * (canvas.width - 1)), y: Math.round((canvas.height - 1) / 2) };
|
|
2603
|
+
}
|
|
2604
|
+
else {
|
|
2605
|
+
return { x: Math.round((canvas.width - 1) / 2), y: Math.round(ratio * (canvas.height - 1)) };
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
if (this.renderingType() === 'hsl') {
|
|
2609
|
+
const { centerX, centerY, radius } = canvasData;
|
|
2610
|
+
const hsl = rgbToHsl(r, g, b);
|
|
2611
|
+
const centerL = this.centerLightness();
|
|
2612
|
+
let distance = 0;
|
|
2613
|
+
if (centerL > 0) {
|
|
2614
|
+
distance = ((100 - hsl.l) * radius) / ((50 * centerL) / 100);
|
|
2615
|
+
}
|
|
2616
|
+
const angle = (hsl.h / 360) * 2 * Math.PI - Math.PI;
|
|
2617
|
+
return {
|
|
2618
|
+
x: Math.round(centerX + distance * Math.cos(angle)),
|
|
2619
|
+
y: Math.round(centerY + distance * Math.sin(angle)),
|
|
2620
|
+
};
|
|
2621
|
+
}
|
|
2195
2622
|
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
|
|
2196
2623
|
let bestMatch = { x: 0, y: 0, distance: Infinity };
|
|
2197
2624
|
for (let y = 0; y < canvas.height; y++) {
|
|
@@ -2209,7 +2636,7 @@ class ShipColorPicker {
|
|
|
2209
2636
|
return { x: bestMatch.x, y: bestMatch.y };
|
|
2210
2637
|
}
|
|
2211
2638
|
adjustMarkerPosition() {
|
|
2212
|
-
const { canvas, centerX, centerY, radius } = this
|
|
2639
|
+
const { canvas, centerX, centerY, radius } = this.#canvasData();
|
|
2213
2640
|
let { x, y } = this._pos;
|
|
2214
2641
|
let markerX = (parseFloat(x.replace('%', '')) / 100) * canvas.width;
|
|
2215
2642
|
let markerY = (parseFloat(y.replace('%', '')) / 100) * canvas.height;
|
|
@@ -2224,7 +2651,10 @@ class ShipColorPicker {
|
|
|
2224
2651
|
}
|
|
2225
2652
|
}
|
|
2226
2653
|
initCanvasEvents() {
|
|
2227
|
-
const
|
|
2654
|
+
const data = this.#canvasData();
|
|
2655
|
+
if (!data)
|
|
2656
|
+
return;
|
|
2657
|
+
const { canvas } = data;
|
|
2228
2658
|
canvas.addEventListener('mousedown', (event) => {
|
|
2229
2659
|
this.isDragging.set(true);
|
|
2230
2660
|
this.updateColorAndMarker(event);
|
|
@@ -2247,6 +2677,8 @@ class ShipColorPicker {
|
|
|
2247
2677
|
this.#document.addEventListener('touchcancel', () => this.isDragging.set(false));
|
|
2248
2678
|
}
|
|
2249
2679
|
setCanvasSize() {
|
|
2680
|
+
if (!isPlatformBrowser(this.#platformId))
|
|
2681
|
+
return;
|
|
2250
2682
|
const canvas = this.canvasRef()?.nativeElement;
|
|
2251
2683
|
if (canvas) {
|
|
2252
2684
|
const ctx = canvas.getContext('2d', {
|
|
@@ -2257,7 +2689,7 @@ class ShipColorPicker {
|
|
|
2257
2689
|
const parentWidth = canvas.parentElement?.offsetWidth || canvas.offsetWidth;
|
|
2258
2690
|
canvas.width = parentWidth;
|
|
2259
2691
|
canvas.height = parentWidth;
|
|
2260
|
-
this
|
|
2692
|
+
this.#canvasData.set({
|
|
2261
2693
|
canvas,
|
|
2262
2694
|
ctx,
|
|
2263
2695
|
centerX: canvas.width / 2,
|
|
@@ -2265,10 +2697,42 @@ class ShipColorPicker {
|
|
|
2265
2697
|
radius: Math.min(canvas.width, canvas.height) / 2,
|
|
2266
2698
|
});
|
|
2267
2699
|
this.drawColorPicker();
|
|
2700
|
+
setTimeout(() => {
|
|
2701
|
+
if (!this.isDragging()) {
|
|
2702
|
+
this.updateMarkerFromColor(untracked(() => this.selectedColor()));
|
|
2703
|
+
}
|
|
2704
|
+
});
|
|
2705
|
+
}
|
|
2706
|
+
}
|
|
2707
|
+
getColorAtPosition(mouseX, mouseY) {
|
|
2708
|
+
const { canvas, ctx } = this.#canvasData();
|
|
2709
|
+
const w = Math.max(1, canvas.width - 1);
|
|
2710
|
+
const h = Math.max(1, canvas.height - 1);
|
|
2711
|
+
const xRatio = mouseX / w;
|
|
2712
|
+
const yRatio = mouseY / h;
|
|
2713
|
+
if (this.renderingType() === 'rgb') {
|
|
2714
|
+
return hsvToRgbExact(this.hue(), xRatio * 100, (1 - yRatio) * 100);
|
|
2715
|
+
}
|
|
2716
|
+
else if (this.renderingType() === 'saturation') {
|
|
2717
|
+
const ratio = this.direction() === 'horizontal' ? xRatio : yRatio;
|
|
2718
|
+
return hslToRgbExact(this.hue(), ratio * 100, 50);
|
|
2719
|
+
}
|
|
2720
|
+
else if (this.renderingType() === 'hue') {
|
|
2721
|
+
const ratio = this.direction() === 'horizontal' ? xRatio : yRatio;
|
|
2722
|
+
return hslToRgbExact(ratio * 360, 100, 50);
|
|
2723
|
+
}
|
|
2724
|
+
else if (this.renderingType() === 'alpha') {
|
|
2725
|
+
const ratio = this.direction() === 'horizontal' ? xRatio : yRatio;
|
|
2726
|
+
const current = this.selectedColor();
|
|
2727
|
+
return [current[0], current[1], current[2], parseFloat(ratio.toFixed(2))];
|
|
2728
|
+
}
|
|
2729
|
+
else {
|
|
2730
|
+
const pixelData = ctx.getImageData(mouseX, mouseY, 1, 1).data;
|
|
2731
|
+
return [pixelData[0], pixelData[1], pixelData[2]];
|
|
2268
2732
|
}
|
|
2269
2733
|
}
|
|
2270
2734
|
updateColorAndMarker(event, outsideCanvas = false, onlyMarker = false) {
|
|
2271
|
-
const { canvas, ctx } = this
|
|
2735
|
+
const { canvas, ctx } = this.#canvasData();
|
|
2272
2736
|
let mouseX = event instanceof MouseEvent ? event.offsetX : event.clientX;
|
|
2273
2737
|
let mouseY = event instanceof MouseEvent ? event.offsetY : event.clientY;
|
|
2274
2738
|
if (outsideCanvas) {
|
|
@@ -2289,13 +2753,16 @@ class ShipColorPicker {
|
|
|
2289
2753
|
}
|
|
2290
2754
|
mouseX = Math.max(0, Math.min(canvas.width - 1, Math.round(mouseX)));
|
|
2291
2755
|
mouseY = Math.max(0, Math.min(canvas.height - 1, Math.round(mouseY)));
|
|
2292
|
-
const pixelData = ctx.getImageData(mouseX, mouseY, 1, 1).data;
|
|
2293
|
-
const [r, g, b] = pixelData;
|
|
2294
2756
|
if (!onlyMarker) {
|
|
2295
|
-
this.
|
|
2757
|
+
const newColor = this.getColorAtPosition(mouseX, mouseY);
|
|
2758
|
+
if (this.renderingType() !== 'alpha') {
|
|
2759
|
+
newColor[3] = this.selectedColor()[3] ?? 1;
|
|
2760
|
+
}
|
|
2761
|
+
this.#skipMarkerUpdate = true;
|
|
2762
|
+
this.selectedColor.set(newColor);
|
|
2296
2763
|
}
|
|
2297
|
-
const xPercent = ((mouseX / canvas.width) * 100).toFixed(2) + '%';
|
|
2298
|
-
const yPercent = ((mouseY / canvas.height) * 100).toFixed(2) + '%';
|
|
2764
|
+
const xPercent = ((mouseX / Math.max(1, canvas.width - 1)) * 100).toFixed(2) + '%';
|
|
2765
|
+
const yPercent = ((mouseY / Math.max(1, canvas.height - 1)) * 100).toFixed(2) + '%';
|
|
2299
2766
|
this.markerPosition.set({ x: xPercent, y: yPercent });
|
|
2300
2767
|
}
|
|
2301
2768
|
drawColorPicker() {
|
|
@@ -2309,6 +2776,9 @@ class ShipColorPicker {
|
|
|
2309
2776
|
case 'hue':
|
|
2310
2777
|
this.drawHue();
|
|
2311
2778
|
break;
|
|
2779
|
+
case 'alpha':
|
|
2780
|
+
this.drawAlpha();
|
|
2781
|
+
break;
|
|
2312
2782
|
case 'rgb':
|
|
2313
2783
|
this.drawRgb();
|
|
2314
2784
|
break;
|
|
@@ -2317,32 +2787,48 @@ class ShipColorPicker {
|
|
|
2317
2787
|
break;
|
|
2318
2788
|
}
|
|
2319
2789
|
}
|
|
2790
|
+
drawAlpha() {
|
|
2791
|
+
const { canvas, ctx } = this.#canvasData();
|
|
2792
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
2793
|
+
const w = Math.max(1, canvas.width - 1);
|
|
2794
|
+
const h = Math.max(1, canvas.height - 1);
|
|
2795
|
+
const gradient = ctx.createLinearGradient(0, 0, this.direction() === 'horizontal' ? w : 0, this.direction() === 'horizontal' ? 0 : h);
|
|
2796
|
+
const [r, g, b] = this.selectedColor();
|
|
2797
|
+
gradient.addColorStop(0, `rgba(${r}, ${g}, ${b}, 0)`);
|
|
2798
|
+
gradient.addColorStop(1, `rgba(${r}, ${g}, ${b}, 1)`);
|
|
2799
|
+
ctx.fillStyle = gradient;
|
|
2800
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
2801
|
+
}
|
|
2320
2802
|
drawRgb() {
|
|
2321
|
-
const { canvas, ctx } = this
|
|
2803
|
+
const { canvas, ctx } = this.#canvasData();
|
|
2322
2804
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
2323
|
-
const
|
|
2324
|
-
|
|
2805
|
+
const w = Math.max(1, canvas.width - 1);
|
|
2806
|
+
const h = Math.max(1, canvas.height - 1);
|
|
2807
|
+
const gradient = ctx.createLinearGradient(0, 0, w, 0);
|
|
2808
|
+
gradient.addColorStop(0, '#ffffff');
|
|
2325
2809
|
gradient.addColorStop(1, `hsl(${this.hue()}, 100%, 50%)`);
|
|
2326
2810
|
ctx.fillStyle = gradient;
|
|
2327
2811
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
2328
|
-
const gradient2 = ctx.createLinearGradient(0, 0, 0,
|
|
2812
|
+
const gradient2 = ctx.createLinearGradient(0, 0, 0, h);
|
|
2329
2813
|
gradient2.addColorStop(0, 'rgba(0, 0, 0, 0)');
|
|
2330
|
-
gradient2.addColorStop(1, '
|
|
2814
|
+
gradient2.addColorStop(1, '#000000');
|
|
2331
2815
|
ctx.fillStyle = gradient2;
|
|
2332
2816
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
2333
2817
|
}
|
|
2334
2818
|
drawSaturation() {
|
|
2335
|
-
const { canvas, ctx } = this
|
|
2819
|
+
const { canvas, ctx } = this.#canvasData();
|
|
2336
2820
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
2821
|
+
const w = Math.max(1, canvas.width - 1);
|
|
2822
|
+
const h = Math.max(1, canvas.height - 1);
|
|
2337
2823
|
if (this.direction() === 'horizontal') {
|
|
2338
|
-
const gradient = ctx.createLinearGradient(0, 0,
|
|
2824
|
+
const gradient = ctx.createLinearGradient(0, 0, w, 0);
|
|
2339
2825
|
gradient.addColorStop(0, `hsl(${this.hue()}, 0%, 50%)`);
|
|
2340
2826
|
gradient.addColorStop(1, `hsl(${this.hue()}, 100%, 50%)`);
|
|
2341
2827
|
ctx.fillStyle = gradient;
|
|
2342
2828
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
2343
2829
|
}
|
|
2344
2830
|
else {
|
|
2345
|
-
const gradient = ctx.createLinearGradient(0, 0, 0,
|
|
2831
|
+
const gradient = ctx.createLinearGradient(0, 0, 0, h);
|
|
2346
2832
|
gradient.addColorStop(0, `hsl(${this.hue()}, 0%, 50%)`);
|
|
2347
2833
|
gradient.addColorStop(1, `hsl(${this.hue()}, 100%, 50%)`);
|
|
2348
2834
|
ctx.fillStyle = gradient;
|
|
@@ -2350,9 +2836,11 @@ class ShipColorPicker {
|
|
|
2350
2836
|
}
|
|
2351
2837
|
}
|
|
2352
2838
|
drawHue() {
|
|
2353
|
-
const { canvas, ctx } = this
|
|
2839
|
+
const { canvas, ctx } = this.#canvasData();
|
|
2354
2840
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
2355
|
-
const
|
|
2841
|
+
const w = Math.max(1, canvas.width - 1);
|
|
2842
|
+
const h = Math.max(1, canvas.height - 1);
|
|
2843
|
+
const gradient = ctx.createLinearGradient(0, 0, this.direction() === 'horizontal' ? w : 0, this.direction() === 'horizontal' ? 0 : h);
|
|
2356
2844
|
for (let i = 0; i <= 360; i += 10) {
|
|
2357
2845
|
gradient.addColorStop(i / 360, `hsl(${i}, 100%, 50%)`);
|
|
2358
2846
|
}
|
|
@@ -2360,7 +2848,7 @@ class ShipColorPicker {
|
|
|
2360
2848
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
2361
2849
|
}
|
|
2362
2850
|
drawColorWheel() {
|
|
2363
|
-
const { canvas, ctx, centerX, centerY, radius } = this
|
|
2851
|
+
const { canvas, ctx, centerX, centerY, radius } = this.#canvasData();
|
|
2364
2852
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
2365
2853
|
for (let y = 0; y < canvas.height; y++) {
|
|
2366
2854
|
for (let x = 0; x < canvas.width; x++) {
|
|
@@ -2375,7 +2863,7 @@ class ShipColorPicker {
|
|
|
2375
2863
|
}
|
|
2376
2864
|
}
|
|
2377
2865
|
drawGrid() {
|
|
2378
|
-
const { canvas, ctx } = this
|
|
2866
|
+
const { canvas, ctx } = this.#canvasData();
|
|
2379
2867
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
2380
2868
|
const gridSize = this.gridSize();
|
|
2381
2869
|
const cellSize = canvas.width / gridSize;
|
|
@@ -2396,38 +2884,8 @@ class ShipColorPicker {
|
|
|
2396
2884
|
}
|
|
2397
2885
|
}
|
|
2398
2886
|
}
|
|
2399
|
-
rgbToHex(r, g, b) {
|
|
2400
|
-
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
|
|
2401
|
-
}
|
|
2402
|
-
rgbToHsl(r, g, b) {
|
|
2403
|
-
r /= 255;
|
|
2404
|
-
g /= 255;
|
|
2405
|
-
b /= 255;
|
|
2406
|
-
const max = Math.max(r, g, b), min = Math.min(r, g, b);
|
|
2407
|
-
let h = 0, s = 0, l = (max + min) / 2;
|
|
2408
|
-
if (max === min) {
|
|
2409
|
-
h = s = 0;
|
|
2410
|
-
}
|
|
2411
|
-
else {
|
|
2412
|
-
const d = max - min;
|
|
2413
|
-
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
2414
|
-
switch (max) {
|
|
2415
|
-
case r:
|
|
2416
|
-
h = (g - b) / d + (g < b ? 6 : 0);
|
|
2417
|
-
break;
|
|
2418
|
-
case g:
|
|
2419
|
-
h = (b - r) / d + 2;
|
|
2420
|
-
break;
|
|
2421
|
-
case b:
|
|
2422
|
-
h = (r - g) / d + 4;
|
|
2423
|
-
break;
|
|
2424
|
-
}
|
|
2425
|
-
h /= 6;
|
|
2426
|
-
}
|
|
2427
|
-
return `hsl(${Math.floor(h * 360)}, ${Math.round(s * 100)}%, ${Math.round(l * 100)}%)`;
|
|
2428
|
-
}
|
|
2429
2887
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipColorPicker, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2430
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.5", type: ShipColorPicker, isStandalone: true, selector: "sh-color-picker", inputs: { showDarkColors: { classPropertyName: "showDarkColors", publicName: "showDarkColors", isSignal: true, isRequired: false, transformFunction: null }, renderingType: { classPropertyName: "renderingType", publicName: "renderingType", isSignal: true, isRequired: false, transformFunction: null }, gridSize: { classPropertyName: "gridSize", publicName: "gridSize", isSignal: true, isRequired: false, transformFunction: null }, hue: { classPropertyName: "hue", publicName: "hue", isSignal: true, isRequired: false, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, selectedColor: { classPropertyName: "selectedColor", publicName: "selectedColor", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedColor: "selectedColorChange", currentColor: "currentColor" }, host: { listeners: { "window:resize": "onResize()" }, properties: { "class": "renderingType()", "class.vertical": "(renderingType() === \"hue\" || renderingType() === \"saturation\") && direction() === \"vertical\"" } }, viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["colorCanvas"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
2888
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.5", type: ShipColorPicker, isStandalone: true, selector: "sh-color-picker", inputs: { showDarkColors: { classPropertyName: "showDarkColors", publicName: "showDarkColors", isSignal: true, isRequired: false, transformFunction: null }, renderingType: { classPropertyName: "renderingType", publicName: "renderingType", isSignal: true, isRequired: false, transformFunction: null }, gridSize: { classPropertyName: "gridSize", publicName: "gridSize", isSignal: true, isRequired: false, transformFunction: null }, hue: { classPropertyName: "hue", publicName: "hue", isSignal: true, isRequired: false, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, selectedColor: { classPropertyName: "selectedColor", publicName: "selectedColor", isSignal: true, isRequired: false, transformFunction: null }, alpha: { classPropertyName: "alpha", publicName: "alpha", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { hue: "hueChange", selectedColor: "selectedColorChange", alpha: "alphaChange", currentColor: "currentColor" }, host: { listeners: { "window:resize": "onResize()" }, properties: { "class": "renderingType()", "class.vertical": "(renderingType() === \"hue\" || renderingType() === \"saturation\") && direction() === \"vertical\"" } }, viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["colorCanvas"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
2431
2889
|
<canvas #colorCanvas></canvas>
|
|
2432
2890
|
<div
|
|
2433
2891
|
class="marker"
|
|
@@ -2455,641 +2913,389 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
2455
2913
|
'[class.vertical]': '(renderingType() === "hue" || renderingType() === "saturation") && direction() === "vertical"',
|
|
2456
2914
|
},
|
|
2457
2915
|
}]
|
|
2458
|
-
}], propDecorators: { canvasRef: [{ type: i0.ViewChild, args: ['colorCanvas', { isSignal: true }] }], showDarkColors: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDarkColors", required: false }] }], renderingType: [{ type: i0.Input, args: [{ isSignal: true, alias: "renderingType", required: false }] }], gridSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "gridSize", required: false }] }], hue: [{ type: i0.Input, args: [{ isSignal: true, alias: "hue", required: false }] }], direction: [{ type: i0.Input, args: [{ isSignal: true, alias: "direction", required: false }] }], selectedColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedColor", required: false }] }, { type: i0.Output, args: ["selectedColorChange"] }], currentColor: [{ type: i0.Output, args: ["currentColor"] }], onResize: [{
|
|
2916
|
+
}], propDecorators: { canvasRef: [{ type: i0.ViewChild, args: ['colorCanvas', { isSignal: true }] }], showDarkColors: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDarkColors", required: false }] }], renderingType: [{ type: i0.Input, args: [{ isSignal: true, alias: "renderingType", required: false }] }], gridSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "gridSize", required: false }] }], hue: [{ type: i0.Input, args: [{ isSignal: true, alias: "hue", required: false }] }, { type: i0.Output, args: ["hueChange"] }], direction: [{ type: i0.Input, args: [{ isSignal: true, alias: "direction", required: false }] }], selectedColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedColor", required: false }] }, { type: i0.Output, args: ["selectedColorChange"] }], alpha: [{ type: i0.Input, args: [{ isSignal: true, alias: "alpha", required: false }] }, { type: i0.Output, args: ["alphaChange"] }], currentColor: [{ type: i0.Output, args: ["currentColor"] }], onResize: [{
|
|
2459
2917
|
type: HostListener,
|
|
2460
2918
|
args: ['window:resize', []]
|
|
2461
2919
|
}] } });
|
|
2462
2920
|
|
|
2463
|
-
|
|
2921
|
+
const BASE_SPACE = 4;
|
|
2922
|
+
const SCROLLABLE_STYLES = ['scroll', 'auto'];
|
|
2923
|
+
const DEFAULT_OPTIONS = {
|
|
2924
|
+
width: undefined,
|
|
2925
|
+
height: undefined,
|
|
2926
|
+
closeOnButton: true,
|
|
2927
|
+
closeOnEsc: true,
|
|
2928
|
+
};
|
|
2929
|
+
class ShipPopover {
|
|
2464
2930
|
constructor() {
|
|
2465
|
-
this.#
|
|
2466
|
-
this.
|
|
2467
|
-
this.
|
|
2468
|
-
this.
|
|
2469
|
-
this.
|
|
2470
|
-
this.
|
|
2471
|
-
this.
|
|
2472
|
-
this.
|
|
2473
|
-
this.
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
this.
|
|
2479
|
-
this.
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
this.
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2931
|
+
this.#document = inject(DOCUMENT);
|
|
2932
|
+
this.SUPPORTS_ANCHOR = typeof CSS !== 'undefined' && CSS.supports('position-anchor', '--abc') && CSS.supports('anchor-name', '--abc');
|
|
2933
|
+
this.asMultiLayer = input(false, ...(ngDevMode ? [{ debugName: "asMultiLayer" }] : /* istanbul ignore next */ []));
|
|
2934
|
+
this.asSheetOnMobile = input(false, ...(ngDevMode ? [{ debugName: "asSheetOnMobile" }] : /* istanbul ignore next */ []));
|
|
2935
|
+
this.disableOpenByClick = input(false, ...(ngDevMode ? [{ debugName: "disableOpenByClick" }] : /* istanbul ignore next */ []));
|
|
2936
|
+
this.isOpen = model(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
2937
|
+
this.options = input(...(ngDevMode ? [undefined, { debugName: "options" }] : /* istanbul ignore next */ []));
|
|
2938
|
+
this.closed = output();
|
|
2939
|
+
this.defaultOptionMerge = computed(() => ({
|
|
2940
|
+
...DEFAULT_OPTIONS,
|
|
2941
|
+
...this.options(),
|
|
2942
|
+
}), ...(ngDevMode ? [{ debugName: "defaultOptionMerge" }] : /* istanbul ignore next */ []));
|
|
2943
|
+
this.triggerRef = viewChild.required('triggerRef');
|
|
2944
|
+
this.popoverRef = viewChild('popoverRef', ...(ngDevMode ? [{ debugName: "popoverRef" }] : /* istanbul ignore next */ []));
|
|
2945
|
+
this.popoverContentRef = viewChild('popoverContentRef', ...(ngDevMode ? [{ debugName: "popoverContentRef" }] : /* istanbul ignore next */ []));
|
|
2946
|
+
this.id = signal('--' + generateUniqueId(), ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
2947
|
+
this.menuStyle = signal(null, ...(ngDevMode ? [{ debugName: "menuStyle" }] : /* istanbul ignore next */ []));
|
|
2948
|
+
this.openAbort = null;
|
|
2949
|
+
this.#originalOverflow = null;
|
|
2950
|
+
this.openEffect = effect(() => {
|
|
2951
|
+
const open = this.isOpen();
|
|
2952
|
+
queueMicrotask(() => {
|
|
2953
|
+
const popoverEl = this.popoverRef()?.nativeElement;
|
|
2954
|
+
if (!popoverEl) {
|
|
2955
|
+
this.openAbort?.abort();
|
|
2956
|
+
this.openAbort = null;
|
|
2957
|
+
return;
|
|
2958
|
+
}
|
|
2959
|
+
if (open) {
|
|
2960
|
+
if (this.openAbort) {
|
|
2961
|
+
this.openAbort.abort();
|
|
2962
|
+
}
|
|
2963
|
+
this.openAbort = new AbortController();
|
|
2964
|
+
this.#document.addEventListener('keydown', (e) => {
|
|
2965
|
+
if (e.key === 'Escape' && !this.defaultOptionMerge().closeOnEsc) {
|
|
2966
|
+
e.preventDefault();
|
|
2967
|
+
}
|
|
2968
|
+
if (e.key === 'Escape' && this.defaultOptionMerge().closeOnEsc) {
|
|
2969
|
+
this.isOpen.set(false);
|
|
2970
|
+
}
|
|
2971
|
+
}, {
|
|
2972
|
+
signal: this.openAbort?.signal,
|
|
2973
|
+
});
|
|
2974
|
+
if (!popoverEl.isConnected)
|
|
2975
|
+
return;
|
|
2976
|
+
popoverEl.showPopover();
|
|
2977
|
+
const isMobileSheet = this.asSheetOnMobile() && window.innerWidth <= 768;
|
|
2978
|
+
if (isMobileSheet) {
|
|
2979
|
+
this.#originalOverflow = this.#document.body.style.overflow;
|
|
2980
|
+
this.#document.body.style.overflow = 'hidden';
|
|
2981
|
+
this.menuStyle.set(null); // Clear any leftover inline styles
|
|
2982
|
+
}
|
|
2983
|
+
if (!this.SUPPORTS_ANCHOR && !isMobileSheet) {
|
|
2984
|
+
setTimeout(() => {
|
|
2985
|
+
const scrollableParent = this.#findScrollableParent(popoverEl);
|
|
2986
|
+
scrollableParent.addEventListener('scroll', () => this.#calculateMenuPosition(), {
|
|
2987
|
+
signal: this.openAbort?.signal,
|
|
2988
|
+
});
|
|
2989
|
+
window?.addEventListener('resize', () => this.#calculateMenuPosition(), {
|
|
2990
|
+
signal: this.openAbort?.signal,
|
|
2991
|
+
});
|
|
2992
|
+
this.#calculateMenuPosition();
|
|
2993
|
+
});
|
|
2994
|
+
}
|
|
2995
|
+
}
|
|
2996
|
+
else {
|
|
2997
|
+
this.closed.emit();
|
|
2998
|
+
popoverEl.hidePopover();
|
|
2999
|
+
this.openAbort?.abort();
|
|
3000
|
+
this.openAbort = null;
|
|
3001
|
+
if (this.asSheetOnMobile() && this.#originalOverflow !== null) {
|
|
3002
|
+
this.#document.body.style.overflow = this.#originalOverflow;
|
|
3003
|
+
this.#originalOverflow = null;
|
|
3004
|
+
}
|
|
3005
|
+
}
|
|
3006
|
+
});
|
|
3007
|
+
}, ...(ngDevMode ? [{ debugName: "openEffect" }] : /* istanbul ignore next */ []));
|
|
2504
3008
|
}
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
3009
|
+
#document;
|
|
3010
|
+
#originalOverflow;
|
|
3011
|
+
toggleIsOpen(event) {
|
|
3012
|
+
if (!this.disableOpenByClick()) {
|
|
3013
|
+
event.preventDefault();
|
|
3014
|
+
event.stopPropagation();
|
|
3015
|
+
this.isOpen.set(!this.isOpen());
|
|
3016
|
+
}
|
|
2508
3017
|
}
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
if (this.monthsToShow() === 1)
|
|
3018
|
+
eventClose($event) {
|
|
3019
|
+
if (!this.isOpen())
|
|
2512
3020
|
return;
|
|
2513
|
-
this
|
|
2514
|
-
}
|
|
2515
|
-
#setDateAsCurrent() {
|
|
2516
|
-
const newDate = this.date();
|
|
2517
|
-
if (newDate)
|
|
2518
|
-
this.currentDate.set(newDate);
|
|
2519
|
-
this.#findSelectedAndCalc();
|
|
3021
|
+
this.isOpen.set(false);
|
|
2520
3022
|
}
|
|
2521
|
-
#
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
if (
|
|
2525
|
-
|
|
3023
|
+
#findScrollableParent(element) {
|
|
3024
|
+
let parent = element.parentElement;
|
|
3025
|
+
while (parent) {
|
|
3026
|
+
if (SCROLLABLE_STYLES.indexOf(window?.getComputedStyle(parent).overflowY) > -1 &&
|
|
3027
|
+
parent.scrollHeight > parent.clientHeight) {
|
|
3028
|
+
return parent;
|
|
2526
3029
|
}
|
|
2527
|
-
|
|
2528
|
-
});
|
|
2529
|
-
}
|
|
2530
|
-
#generateMonthDates(date, startOfWeek) {
|
|
2531
|
-
const year = date.getFullYear();
|
|
2532
|
-
const month = date.getMonth();
|
|
2533
|
-
const firstDay = new Date(year, month, 1).getDay();
|
|
2534
|
-
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
2535
|
-
const dates = [];
|
|
2536
|
-
let offset = firstDay - startOfWeek;
|
|
2537
|
-
if (offset < 0) {
|
|
2538
|
-
offset += 7;
|
|
2539
|
-
}
|
|
2540
|
-
const lastDayOfPrevMonth = new Date(year, month, 0).getDate();
|
|
2541
|
-
for (let i = offset - 1; i >= 0; i--) {
|
|
2542
|
-
dates.push(new Date(year, month - 1, lastDayOfPrevMonth - i, 0, 0, 0, 0));
|
|
2543
|
-
}
|
|
2544
|
-
for (let i = 1; i <= daysInMonth; i++) {
|
|
2545
|
-
dates.push(new Date(year, month, i, 0, 0, 0, 0));
|
|
2546
|
-
}
|
|
2547
|
-
let nextMonthDay = 1;
|
|
2548
|
-
while (dates.length % 7 !== 0) {
|
|
2549
|
-
dates.push(new Date(year, month + 1, nextMonthDay++, 0, 0, 0, 0));
|
|
3030
|
+
parent = parent.parentElement;
|
|
2550
3031
|
}
|
|
2551
|
-
return
|
|
3032
|
+
return this.#document.documentElement;
|
|
2552
3033
|
}
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
3034
|
+
/**
|
|
3035
|
+
* Position generators that mirror the CSS position-try-fallbacks.
|
|
3036
|
+
* Each returns { left, top } for the popover-content in fixed coordinates.
|
|
3037
|
+
*/
|
|
3038
|
+
// bottom span-right: below trigger, left edge aligned with trigger left
|
|
3039
|
+
#bottomSpanRight(t, _m) {
|
|
3040
|
+
return { left: t.left, top: t.bottom + BASE_SPACE };
|
|
2560
3041
|
}
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
newDate.setMonth(currentDate.getMonth() - 1);
|
|
2565
|
-
return newDate;
|
|
2566
|
-
});
|
|
2567
|
-
this.#findSelectedAndCalc();
|
|
3042
|
+
// top span-right: above trigger, left edge aligned with trigger left
|
|
3043
|
+
#topSpanRight(t, m) {
|
|
3044
|
+
return { left: t.left, top: t.top - m.height - BASE_SPACE };
|
|
2568
3045
|
}
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
const minutes = existingDate?.getMinutes() ?? 0;
|
|
2573
|
-
const seconds = existingDate?.getSeconds() ?? 0;
|
|
2574
|
-
const milliseconds = existingDate?.getMilliseconds() ?? 0;
|
|
2575
|
-
return new Date(newDate.getFullYear(), newDate.getMonth(), newDate.getDate(), hours, minutes, seconds, milliseconds);
|
|
2576
|
-
};
|
|
2577
|
-
if (!this.asRange()) {
|
|
2578
|
-
this.date.set(createDateWithExistingTime(newDate, this.date()));
|
|
2579
|
-
this.endDate.set(null);
|
|
2580
|
-
}
|
|
2581
|
-
else {
|
|
2582
|
-
const startDate = this.date();
|
|
2583
|
-
const endDate = this.endDate();
|
|
2584
|
-
const utcDate = createDateWithExistingTime(newDate, null);
|
|
2585
|
-
if (!startDate) {
|
|
2586
|
-
this.date.set(utcDate);
|
|
2587
|
-
}
|
|
2588
|
-
else if (!endDate) {
|
|
2589
|
-
if (utcDate < startDate) {
|
|
2590
|
-
this.date.set(utcDate);
|
|
2591
|
-
this.endDate.set(null);
|
|
2592
|
-
}
|
|
2593
|
-
else {
|
|
2594
|
-
this.endDate.set(utcDate);
|
|
2595
|
-
}
|
|
2596
|
-
}
|
|
2597
|
-
else {
|
|
2598
|
-
this.date.set(utcDate);
|
|
2599
|
-
this.endDate.set(null);
|
|
2600
|
-
}
|
|
2601
|
-
}
|
|
2602
|
-
if (this.asRange())
|
|
2603
|
-
return;
|
|
2604
|
-
this.setSelectedDateStylePosition(selectedElement);
|
|
3046
|
+
// bottom span-left: below trigger, right edge aligned with trigger right
|
|
3047
|
+
#bottomSpanLeft(t, m) {
|
|
3048
|
+
return { left: t.right - m.width, top: t.bottom + BASE_SPACE };
|
|
2605
3049
|
}
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
if (startDate === null)
|
|
2610
|
-
return null;
|
|
2611
|
-
const startOfDay = (date) => {
|
|
2612
|
-
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0);
|
|
2613
|
-
};
|
|
2614
|
-
const endOfDay = (date) => {
|
|
2615
|
-
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999);
|
|
2616
|
-
};
|
|
2617
|
-
const currentDate = startOfDay(date);
|
|
2618
|
-
const rangeStart = startOfDay(startDate);
|
|
2619
|
-
const rangeEnd = endDate ? endOfDay(endDate) : null;
|
|
2620
|
-
let classes = [];
|
|
2621
|
-
if (this.asRange()) {
|
|
2622
|
-
if (rangeEnd === null) {
|
|
2623
|
-
if (currentDate.getTime() === rangeStart.getTime()) {
|
|
2624
|
-
classes.push('sel first last');
|
|
2625
|
-
}
|
|
2626
|
-
}
|
|
2627
|
-
else {
|
|
2628
|
-
if (currentDate.getTime() === rangeStart.getTime()) {
|
|
2629
|
-
classes.push('first');
|
|
2630
|
-
}
|
|
2631
|
-
if (currentDate.getTime() === startOfDay(rangeEnd).getTime()) {
|
|
2632
|
-
classes.push('last');
|
|
2633
|
-
}
|
|
2634
|
-
if (currentDate >= rangeStart && currentDate <= rangeEnd) {
|
|
2635
|
-
classes.push('sel');
|
|
2636
|
-
const dayOfWeek = currentDate.getDay();
|
|
2637
|
-
const startOfWeek = this.startOfWeek();
|
|
2638
|
-
if (dayOfWeek === startOfWeek) {
|
|
2639
|
-
classes.push('week-start');
|
|
2640
|
-
}
|
|
2641
|
-
const endOfWeek = (startOfWeek + 6) % 7;
|
|
2642
|
-
if (dayOfWeek === endOfWeek) {
|
|
2643
|
-
classes.push('week-end');
|
|
2644
|
-
}
|
|
2645
|
-
}
|
|
2646
|
-
const nextDate = new Date(currentDate);
|
|
2647
|
-
nextDate.setDate(currentDate.getDate() + 1);
|
|
2648
|
-
const prevDate = new Date(currentDate);
|
|
2649
|
-
prevDate.setDate(currentDate.getDate() - 1);
|
|
2650
|
-
const isFirstOfMonth = currentDate.getDate() === 1;
|
|
2651
|
-
const isLastOfMonth = nextDate.getMonth() !== currentDate.getMonth();
|
|
2652
|
-
if (isFirstOfMonth) {
|
|
2653
|
-
classes.push('month-start');
|
|
2654
|
-
}
|
|
2655
|
-
if (isLastOfMonth) {
|
|
2656
|
-
classes.push('month-end');
|
|
2657
|
-
}
|
|
2658
|
-
}
|
|
2659
|
-
}
|
|
2660
|
-
else {
|
|
2661
|
-
if (currentDate.getTime() === rangeStart.getTime()) {
|
|
2662
|
-
classes.push('sel');
|
|
2663
|
-
}
|
|
2664
|
-
}
|
|
2665
|
-
return classes.join(' ') || null;
|
|
3050
|
+
// top span-left: above trigger, right edge aligned with trigger right
|
|
3051
|
+
#topSpanLeft(t, m) {
|
|
3052
|
+
return { left: t.right - m.width, top: t.top - m.height - BASE_SPACE };
|
|
2666
3053
|
}
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
opacity: '1',
|
|
2671
|
-
});
|
|
3054
|
+
// right span-bottom: to the right of trigger, top edge aligned with trigger top
|
|
3055
|
+
#rightSpanBottom(t, _m) {
|
|
3056
|
+
return { left: t.right + BASE_SPACE, top: t.top };
|
|
2672
3057
|
}
|
|
2673
|
-
|
|
2674
|
-
|
|
3058
|
+
// left span-bottom: to the left of trigger, top edge aligned with trigger top
|
|
3059
|
+
#leftSpanBottom(t, m) {
|
|
3060
|
+
return { left: t.left - m.width - BASE_SPACE, top: t.top };
|
|
2675
3061
|
}
|
|
2676
|
-
|
|
2677
|
-
|
|
3062
|
+
// right center: to the right of trigger, vertically centered
|
|
3063
|
+
#rightCenter(t, m) {
|
|
3064
|
+
return { left: t.right + BASE_SPACE, top: t.top + t.height / 2 - m.height / 2 };
|
|
2678
3065
|
}
|
|
2679
|
-
//
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
return date.getMonth() === offsetDate.getMonth();
|
|
3066
|
+
// left center: to the left of trigger, vertically centered
|
|
3067
|
+
#leftCenter(t, m) {
|
|
3068
|
+
return { left: t.left - m.width - BASE_SPACE, top: t.top + t.height / 2 - m.height / 2 };
|
|
2683
3069
|
}
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
3070
|
+
// right span-top: to the right of trigger, bottom edge aligned with trigger bottom
|
|
3071
|
+
#rightSpanTop(t, m) {
|
|
3072
|
+
return { left: t.right + BASE_SPACE, top: t.bottom - m.height };
|
|
3073
|
+
}
|
|
3074
|
+
// left span-top: to the left of trigger, bottom edge aligned with trigger bottom
|
|
3075
|
+
#leftSpanTop(t, m) {
|
|
3076
|
+
return { left: t.left - m.width - BASE_SPACE, top: t.bottom - m.height };
|
|
3077
|
+
}
|
|
3078
|
+
/** Check if a position fits entirely within the viewport */
|
|
3079
|
+
#fitsInViewport(pos, m) {
|
|
3080
|
+
return (pos.left >= 0 &&
|
|
3081
|
+
pos.top >= 0 &&
|
|
3082
|
+
pos.left + m.width <= window.innerWidth &&
|
|
3083
|
+
pos.top + m.height <= window.innerHeight);
|
|
3084
|
+
}
|
|
3085
|
+
/** Clamp a position so the popover stays within the viewport */
|
|
3086
|
+
#clampToViewport(pos, m) {
|
|
3087
|
+
return {
|
|
3088
|
+
left: Math.max(0, Math.min(pos.left, window.innerWidth - m.width)),
|
|
3089
|
+
top: Math.max(0, Math.min(pos.top, window.innerHeight - m.height)),
|
|
3090
|
+
};
|
|
3091
|
+
}
|
|
3092
|
+
#calculateMenuPosition() {
|
|
3093
|
+
const triggerRect = this.triggerRef()?.nativeElement.getBoundingClientRect();
|
|
3094
|
+
const menuRect = this.popoverContentRef()?.nativeElement.getBoundingClientRect();
|
|
3095
|
+
if (!triggerRect || !menuRect)
|
|
3096
|
+
return;
|
|
3097
|
+
// Mirror the CSS position-try-fallbacks order
|
|
3098
|
+
const tryOrderDefault = [
|
|
3099
|
+
this.#bottomSpanRight,
|
|
3100
|
+
this.#topSpanRight,
|
|
3101
|
+
this.#bottomSpanLeft,
|
|
3102
|
+
this.#topSpanLeft,
|
|
3103
|
+
this.#rightSpanBottom,
|
|
3104
|
+
this.#leftSpanBottom,
|
|
3105
|
+
this.#rightCenter,
|
|
3106
|
+
this.#leftCenter,
|
|
3107
|
+
this.#rightSpanTop,
|
|
3108
|
+
this.#leftSpanTop,
|
|
3109
|
+
];
|
|
3110
|
+
const tryOrderMultiLayer = [
|
|
3111
|
+
this.#rightSpanBottom,
|
|
3112
|
+
this.#rightSpanTop,
|
|
3113
|
+
this.#leftSpanBottom,
|
|
3114
|
+
this.#leftSpanTop,
|
|
3115
|
+
this.#rightCenter,
|
|
3116
|
+
this.#leftCenter,
|
|
3117
|
+
this.#bottomSpanRight,
|
|
3118
|
+
this.#topSpanRight,
|
|
3119
|
+
this.#bottomSpanLeft,
|
|
3120
|
+
this.#topSpanLeft,
|
|
3121
|
+
];
|
|
3122
|
+
const tryOrder = this.asMultiLayer() ? tryOrderMultiLayer : tryOrderDefault;
|
|
3123
|
+
// Try each position, use the first one that fits
|
|
3124
|
+
for (const positionFn of tryOrder) {
|
|
3125
|
+
const pos = positionFn.call(this, triggerRect, menuRect);
|
|
3126
|
+
if (this.#fitsInViewport(pos, menuRect)) {
|
|
3127
|
+
this.menuStyle.set({ left: pos.left + 'px', top: pos.top + 'px' });
|
|
3128
|
+
return;
|
|
3129
|
+
}
|
|
2692
3130
|
}
|
|
2693
|
-
|
|
3131
|
+
// If nothing fits perfectly, use the first position clamped to viewport
|
|
3132
|
+
const fallback = this.#clampToViewport(tryOrder[0].call(this, triggerRect, menuRect), menuRect);
|
|
3133
|
+
this.menuStyle.set({ left: fallback.left + 'px', top: fallback.top + 'px' });
|
|
3134
|
+
}
|
|
3135
|
+
ngOnDestroy() {
|
|
3136
|
+
this.openAbort?.abort();
|
|
3137
|
+
this.openAbort = null;
|
|
3138
|
+
}
|
|
3139
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipPopover, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3140
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ShipPopover, isStandalone: true, selector: "sh-popover", inputs: { asMultiLayer: { classPropertyName: "asMultiLayer", publicName: "asMultiLayer", isSignal: true, isRequired: false, transformFunction: null }, asSheetOnMobile: { classPropertyName: "asSheetOnMobile", publicName: "asSheetOnMobile", isSignal: true, isRequired: false, transformFunction: null }, disableOpenByClick: { classPropertyName: "disableOpenByClick", publicName: "disableOpenByClick", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isOpen: "isOpenChange", closed: "closed" }, host: { properties: { "class.multi-layer": "asMultiLayer()", "class.as-sheet": "asSheetOnMobile()" } }, viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerRef"], descendants: true, isSignal: true }, { propertyName: "popoverRef", first: true, predicate: ["popoverRef"], descendants: true, isSignal: true }, { propertyName: "popoverContentRef", first: true, predicate: ["popoverContentRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
3141
|
+
<div class="trigger" #triggerRef [attr.popovertarget]="id() + 'hello'" (click)="toggleIsOpen($event)">
|
|
3142
|
+
<div class="trigger-wrapper">
|
|
3143
|
+
<ng-content select="[trigger]" />
|
|
3144
|
+
<ng-content select="button" />
|
|
3145
|
+
<ng-content select="[shButton]" />
|
|
2694
3146
|
</div>
|
|
2695
|
-
<
|
|
2696
|
-
</
|
|
2697
|
-
|
|
2698
|
-
<section class="months-container">
|
|
2699
|
-
@for (monthOffset of monthOffsets(); track monthOffset) {
|
|
2700
|
-
<div class="month">
|
|
2701
|
-
<nav class="weekdays">
|
|
2702
|
-
@for (day of weekdays(); track $index) {
|
|
2703
|
-
<div>{{ day }}</div>
|
|
2704
|
-
}
|
|
2705
|
-
</nav>
|
|
2706
|
-
|
|
2707
|
-
<div class="days" #daysRef>
|
|
2708
|
-
@for (calDate of getMonthDates(monthOffset); track $index) {
|
|
2709
|
-
<div
|
|
2710
|
-
#elementRef
|
|
2711
|
-
[class.out-of-scope]="!isCurrentMonth(calDate, monthOffset)"
|
|
2712
|
-
[class]="isDateSelected(calDate)"
|
|
2713
|
-
(click)="setDate(calDate, elementRef)">
|
|
2714
|
-
{{ calDate.getDate() }}
|
|
2715
|
-
</div>
|
|
2716
|
-
}
|
|
3147
|
+
<div class="trigger-anchor" [style.anchor-name]="id()"></div>
|
|
3148
|
+
</div>
|
|
2717
3149
|
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
</div>
|
|
3150
|
+
@if (isOpen()) {
|
|
3151
|
+
<div [attr.id]="id() + 'hello'" popover="manual" #popoverRef class="popover">
|
|
3152
|
+
<div class="overlay" (click)="eventClose($event)"></div>
|
|
3153
|
+
<div class="popover-content" #popoverContentRef [style.position-anchor]="id()" [style]="menuStyle()">
|
|
3154
|
+
<ng-content />
|
|
2724
3155
|
</div>
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
`, isInline: true,
|
|
3156
|
+
</div>
|
|
3157
|
+
}
|
|
3158
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2728
3159
|
}
|
|
2729
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type:
|
|
3160
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipPopover, decorators: [{
|
|
2730
3161
|
type: Component,
|
|
2731
3162
|
args: [{
|
|
2732
|
-
selector: 'sh-
|
|
2733
|
-
imports: [
|
|
3163
|
+
selector: 'sh-popover',
|
|
3164
|
+
imports: [],
|
|
2734
3165
|
template: `
|
|
2735
|
-
<
|
|
2736
|
-
<
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
- {{ getMonthName(getLastVisibleMonth()) }}
|
|
2741
|
-
}
|
|
2742
|
-
{{ getFullYear(currentDate()!) }}
|
|
3166
|
+
<div class="trigger" #triggerRef [attr.popovertarget]="id() + 'hello'" (click)="toggleIsOpen($event)">
|
|
3167
|
+
<div class="trigger-wrapper">
|
|
3168
|
+
<ng-content select="[trigger]" />
|
|
3169
|
+
<ng-content select="button" />
|
|
3170
|
+
<ng-content select="[shButton]" />
|
|
2743
3171
|
</div>
|
|
2744
|
-
<
|
|
2745
|
-
</
|
|
2746
|
-
|
|
2747
|
-
<section class="months-container">
|
|
2748
|
-
@for (monthOffset of monthOffsets(); track monthOffset) {
|
|
2749
|
-
<div class="month">
|
|
2750
|
-
<nav class="weekdays">
|
|
2751
|
-
@for (day of weekdays(); track $index) {
|
|
2752
|
-
<div>{{ day }}</div>
|
|
2753
|
-
}
|
|
2754
|
-
</nav>
|
|
2755
|
-
|
|
2756
|
-
<div class="days" #daysRef>
|
|
2757
|
-
@for (calDate of getMonthDates(monthOffset); track $index) {
|
|
2758
|
-
<div
|
|
2759
|
-
#elementRef
|
|
2760
|
-
[class.out-of-scope]="!isCurrentMonth(calDate, monthOffset)"
|
|
2761
|
-
[class]="isDateSelected(calDate)"
|
|
2762
|
-
(click)="setDate(calDate, elementRef)">
|
|
2763
|
-
{{ calDate.getDate() }}
|
|
2764
|
-
</div>
|
|
2765
|
-
}
|
|
3172
|
+
<div class="trigger-anchor" [style.anchor-name]="id()"></div>
|
|
3173
|
+
</div>
|
|
2766
3174
|
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
</div>
|
|
3175
|
+
@if (isOpen()) {
|
|
3176
|
+
<div [attr.id]="id() + 'hello'" popover="manual" #popoverRef class="popover">
|
|
3177
|
+
<div class="overlay" (click)="eventClose($event)"></div>
|
|
3178
|
+
<div class="popover-content" #popoverContentRef [style.position-anchor]="id()" [style]="menuStyle()">
|
|
3179
|
+
<ng-content />
|
|
2773
3180
|
</div>
|
|
2774
|
-
|
|
2775
|
-
|
|
3181
|
+
</div>
|
|
3182
|
+
}
|
|
2776
3183
|
`,
|
|
2777
3184
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2778
3185
|
host: {
|
|
2779
|
-
'[class.
|
|
2780
|
-
'[class]': '
|
|
2781
|
-
'[class.disabled]': 'disabled()',
|
|
3186
|
+
'[class.multi-layer]': 'asMultiLayer()',
|
|
3187
|
+
'[class.as-sheet]': 'asSheetOnMobile()',
|
|
2782
3188
|
},
|
|
2783
3189
|
}]
|
|
2784
|
-
}], propDecorators: {
|
|
3190
|
+
}], propDecorators: { asMultiLayer: [{ type: i0.Input, args: [{ isSignal: true, alias: "asMultiLayer", required: false }] }], asSheetOnMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "asSheetOnMobile", required: false }] }], disableOpenByClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableOpenByClick", required: false }] }], isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }, { type: i0.Output, args: ["isOpenChange"] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], triggerRef: [{ type: i0.ViewChild, args: ['triggerRef', { isSignal: true }] }], popoverRef: [{ type: i0.ViewChild, args: ['popoverRef', { isSignal: true }] }], popoverContentRef: [{ type: i0.ViewChild, args: ['popoverContentRef', { isSignal: true }] }] } });
|
|
2785
3191
|
|
|
2786
|
-
|
|
2787
|
-
const SCROLLABLE_STYLES = ['scroll', 'auto'];
|
|
2788
|
-
const DEFAULT_OPTIONS = {
|
|
2789
|
-
width: undefined,
|
|
2790
|
-
height: undefined,
|
|
2791
|
-
closeOnButton: true,
|
|
2792
|
-
closeOnEsc: true,
|
|
2793
|
-
};
|
|
2794
|
-
class ShipPopover {
|
|
3192
|
+
class ShipFormFieldPopover {
|
|
2795
3193
|
constructor() {
|
|
2796
|
-
this.#
|
|
2797
|
-
this.SUPPORTS_ANCHOR = typeof CSS !== 'undefined' && CSS.supports('position-anchor', '--abc') && CSS.supports('anchor-name', '--abc');
|
|
2798
|
-
this.asMultiLayer = input(false, ...(ngDevMode ? [{ debugName: "asMultiLayer" }] : /* istanbul ignore next */ []));
|
|
2799
|
-
this.disableOpenByClick = input(false, ...(ngDevMode ? [{ debugName: "disableOpenByClick" }] : /* istanbul ignore next */ []));
|
|
3194
|
+
this.#selfRef = inject(ElementRef);
|
|
2800
3195
|
this.isOpen = model(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
2801
|
-
this.options = input(...(ngDevMode ? [undefined, { debugName: "options" }] : /* istanbul ignore next */ []));
|
|
2802
3196
|
this.closed = output();
|
|
2803
|
-
this.
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
this.
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
this.openEffect = effect(() => {
|
|
2814
|
-
const open = this.isOpen();
|
|
2815
|
-
queueMicrotask(() => {
|
|
2816
|
-
const popoverEl = this.popoverRef()?.nativeElement;
|
|
2817
|
-
if (!popoverEl) {
|
|
2818
|
-
this.openAbort?.abort();
|
|
2819
|
-
this.openAbort = null;
|
|
2820
|
-
return;
|
|
2821
|
-
}
|
|
2822
|
-
if (open) {
|
|
2823
|
-
if (this.openAbort) {
|
|
2824
|
-
this.openAbort.abort();
|
|
2825
|
-
}
|
|
2826
|
-
this.openAbort = new AbortController();
|
|
2827
|
-
this.#document.addEventListener('keydown', (e) => {
|
|
2828
|
-
if (e.key === 'Escape' && !this.defaultOptionMerge().closeOnEsc) {
|
|
2829
|
-
e.preventDefault();
|
|
2830
|
-
}
|
|
2831
|
-
if (e.key === 'Escape' && this.defaultOptionMerge().closeOnEsc) {
|
|
2832
|
-
this.isOpen.set(false);
|
|
2833
|
-
}
|
|
2834
|
-
}, {
|
|
2835
|
-
signal: this.openAbort?.signal,
|
|
2836
|
-
});
|
|
2837
|
-
if (!popoverEl.isConnected)
|
|
2838
|
-
return;
|
|
2839
|
-
popoverEl.showPopover();
|
|
2840
|
-
if (!this.SUPPORTS_ANCHOR) {
|
|
2841
|
-
setTimeout(() => {
|
|
2842
|
-
const scrollableParent = this.#findScrollableParent(popoverEl);
|
|
2843
|
-
scrollableParent.addEventListener('scroll', () => this.#calculateMenuPosition(), {
|
|
2844
|
-
signal: this.openAbort?.signal,
|
|
2845
|
-
});
|
|
2846
|
-
window?.addEventListener('resize', () => this.#calculateMenuPosition(), {
|
|
2847
|
-
signal: this.openAbort?.signal,
|
|
2848
|
-
});
|
|
2849
|
-
this.#calculateMenuPosition();
|
|
2850
|
-
});
|
|
2851
|
-
}
|
|
2852
|
-
}
|
|
2853
|
-
else {
|
|
2854
|
-
this.closed.emit();
|
|
2855
|
-
popoverEl.hidePopover();
|
|
2856
|
-
this.openAbort?.abort();
|
|
2857
|
-
this.openAbort = null;
|
|
2858
|
-
}
|
|
2859
|
-
});
|
|
2860
|
-
}, ...(ngDevMode ? [{ debugName: "openEffect" }] : /* istanbul ignore next */ []));
|
|
3197
|
+
this.color = input(null, ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
3198
|
+
this.variant = input(null, ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
3199
|
+
this.size = input(null, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
3200
|
+
this.readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
3201
|
+
this.hostClasses = shipComponentClasses('formField', {
|
|
3202
|
+
color: this.color,
|
|
3203
|
+
variant: this.variant,
|
|
3204
|
+
size: this.size,
|
|
3205
|
+
readonly: this.readonly,
|
|
3206
|
+
});
|
|
2861
3207
|
}
|
|
2862
|
-
#
|
|
2863
|
-
|
|
2864
|
-
if (
|
|
2865
|
-
|
|
2866
|
-
event.stopPropagation();
|
|
2867
|
-
this.isOpen.set(!this.isOpen());
|
|
3208
|
+
#selfRef;
|
|
3209
|
+
onClick() {
|
|
3210
|
+
if (this.#selfRef.nativeElement.querySelector('input')) {
|
|
3211
|
+
this.#selfRef.nativeElement.querySelector('input').focus();
|
|
2868
3212
|
}
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
if (!this.isOpen())
|
|
2872
|
-
return;
|
|
2873
|
-
this.isOpen.set(false);
|
|
2874
|
-
}
|
|
2875
|
-
#findScrollableParent(element) {
|
|
2876
|
-
let parent = element.parentElement;
|
|
2877
|
-
while (parent) {
|
|
2878
|
-
if (SCROLLABLE_STYLES.indexOf(window?.getComputedStyle(parent).overflowY) > -1 &&
|
|
2879
|
-
parent.scrollHeight > parent.clientHeight) {
|
|
2880
|
-
return parent;
|
|
2881
|
-
}
|
|
2882
|
-
parent = parent.parentElement;
|
|
3213
|
+
if (this.#selfRef.nativeElement.querySelector('textarea')) {
|
|
3214
|
+
this.#selfRef.nativeElement.querySelector('textarea').focus();
|
|
2883
3215
|
}
|
|
2884
|
-
return this.#document.documentElement;
|
|
2885
|
-
}
|
|
2886
|
-
/**
|
|
2887
|
-
* Position generators that mirror the CSS position-try-fallbacks.
|
|
2888
|
-
* Each returns { left, top } for the popover-content in fixed coordinates.
|
|
2889
|
-
*/
|
|
2890
|
-
// bottom span-right: below trigger, left edge aligned with trigger left
|
|
2891
|
-
#bottomSpanRight(t, _m) {
|
|
2892
|
-
return { left: t.left, top: t.bottom + BASE_SPACE };
|
|
2893
|
-
}
|
|
2894
|
-
// top span-right: above trigger, left edge aligned with trigger left
|
|
2895
|
-
#topSpanRight(t, m) {
|
|
2896
|
-
return { left: t.left, top: t.top - m.height - BASE_SPACE };
|
|
2897
|
-
}
|
|
2898
|
-
// bottom span-left: below trigger, right edge aligned with trigger right
|
|
2899
|
-
#bottomSpanLeft(t, m) {
|
|
2900
|
-
return { left: t.right - m.width, top: t.bottom + BASE_SPACE };
|
|
2901
|
-
}
|
|
2902
|
-
// top span-left: above trigger, right edge aligned with trigger right
|
|
2903
|
-
#topSpanLeft(t, m) {
|
|
2904
|
-
return { left: t.right - m.width, top: t.top - m.height - BASE_SPACE };
|
|
2905
|
-
}
|
|
2906
|
-
// right span-bottom: to the right of trigger, top edge aligned with trigger top
|
|
2907
|
-
#rightSpanBottom(t, _m) {
|
|
2908
|
-
return { left: t.right + BASE_SPACE, top: t.top };
|
|
2909
|
-
}
|
|
2910
|
-
// left span-bottom: to the left of trigger, top edge aligned with trigger top
|
|
2911
|
-
#leftSpanBottom(t, m) {
|
|
2912
|
-
return { left: t.left - m.width - BASE_SPACE, top: t.top };
|
|
2913
|
-
}
|
|
2914
|
-
// right center: to the right of trigger, vertically centered
|
|
2915
|
-
#rightCenter(t, m) {
|
|
2916
|
-
return { left: t.right + BASE_SPACE, top: t.top + t.height / 2 - m.height / 2 };
|
|
2917
|
-
}
|
|
2918
|
-
// left center: to the left of trigger, vertically centered
|
|
2919
|
-
#leftCenter(t, m) {
|
|
2920
|
-
return { left: t.left - m.width - BASE_SPACE, top: t.top + t.height / 2 - m.height / 2 };
|
|
2921
|
-
}
|
|
2922
|
-
// right span-top: to the right of trigger, bottom edge aligned with trigger bottom
|
|
2923
|
-
#rightSpanTop(t, m) {
|
|
2924
|
-
return { left: t.right + BASE_SPACE, top: t.bottom - m.height };
|
|
2925
|
-
}
|
|
2926
|
-
// left span-top: to the left of trigger, bottom edge aligned with trigger bottom
|
|
2927
|
-
#leftSpanTop(t, m) {
|
|
2928
|
-
return { left: t.left - m.width - BASE_SPACE, top: t.bottom - m.height };
|
|
2929
|
-
}
|
|
2930
|
-
/** Check if a position fits entirely within the viewport */
|
|
2931
|
-
#fitsInViewport(pos, m) {
|
|
2932
|
-
return (pos.left >= 0 &&
|
|
2933
|
-
pos.top >= 0 &&
|
|
2934
|
-
pos.left + m.width <= window.innerWidth &&
|
|
2935
|
-
pos.top + m.height <= window.innerHeight);
|
|
2936
3216
|
}
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
return {
|
|
2940
|
-
left: Math.max(0, Math.min(pos.left, window.innerWidth - m.width)),
|
|
2941
|
-
top: Math.max(0, Math.min(pos.top, window.innerHeight - m.height)),
|
|
2942
|
-
};
|
|
3217
|
+
close() {
|
|
3218
|
+
this.closed.emit();
|
|
2943
3219
|
}
|
|
2944
|
-
|
|
2945
|
-
const
|
|
2946
|
-
const
|
|
2947
|
-
if (!
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
this.#leftSpanTop,
|
|
2967
|
-
this.#rightCenter,
|
|
2968
|
-
this.#leftCenter,
|
|
2969
|
-
this.#bottomSpanRight,
|
|
2970
|
-
this.#topSpanRight,
|
|
2971
|
-
this.#bottomSpanLeft,
|
|
2972
|
-
this.#topSpanLeft,
|
|
2973
|
-
];
|
|
2974
|
-
const tryOrder = this.asMultiLayer() ? tryOrderMultiLayer : tryOrderDefault;
|
|
2975
|
-
// Try each position, use the first one that fits
|
|
2976
|
-
for (const positionFn of tryOrder) {
|
|
2977
|
-
const pos = positionFn.call(this, triggerRect, menuRect);
|
|
2978
|
-
if (this.#fitsInViewport(pos, menuRect)) {
|
|
2979
|
-
this.menuStyle.set({ left: pos.left + 'px', top: pos.top + 'px' });
|
|
2980
|
-
return;
|
|
3220
|
+
ngOnInit() {
|
|
3221
|
+
const supportFieldSizing = typeof CSS !== 'undefined' && CSS.supports('field-sizing', 'content');
|
|
3222
|
+
const text = this.#selfRef.nativeElement.querySelector('textarea');
|
|
3223
|
+
if (!supportFieldSizing && text !== null) {
|
|
3224
|
+
const text = this.#selfRef.nativeElement.querySelector('textarea');
|
|
3225
|
+
function resize() {
|
|
3226
|
+
text.style.height = 'auto';
|
|
3227
|
+
text.style.height = text.scrollHeight + 'px';
|
|
3228
|
+
}
|
|
3229
|
+
/* 0-timeout to get the already changed text */
|
|
3230
|
+
function delayedResize() {
|
|
3231
|
+
setTimeout(resize, 0);
|
|
3232
|
+
}
|
|
3233
|
+
if (text) {
|
|
3234
|
+
text.addEventListener('change', resize);
|
|
3235
|
+
text.addEventListener('cut', delayedResize);
|
|
3236
|
+
text.addEventListener('paste', delayedResize);
|
|
3237
|
+
text.addEventListener('drop', delayedResize);
|
|
3238
|
+
text.addEventListener('keydown', delayedResize);
|
|
3239
|
+
text.focus();
|
|
3240
|
+
text.select();
|
|
3241
|
+
resize();
|
|
2981
3242
|
}
|
|
2982
3243
|
}
|
|
2983
|
-
// If nothing fits perfectly, use the first position clamped to viewport
|
|
2984
|
-
const fallback = this.#clampToViewport(tryOrder[0].call(this, triggerRect, menuRect), menuRect);
|
|
2985
|
-
this.menuStyle.set({ left: fallback.left + 'px', top: fallback.top + 'px' });
|
|
2986
|
-
}
|
|
2987
|
-
ngOnDestroy() {
|
|
2988
|
-
this.openAbort?.abort();
|
|
2989
|
-
this.openAbort = null;
|
|
2990
3244
|
}
|
|
2991
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type:
|
|
2992
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.
|
|
2993
|
-
<
|
|
2994
|
-
<div class="trigger-wrapper">
|
|
2995
|
-
<ng-content select="[trigger]" />
|
|
2996
|
-
<ng-content select="button" />
|
|
2997
|
-
<ng-content select="[shButton]" />
|
|
2998
|
-
</div>
|
|
2999
|
-
<div class="trigger-anchor" [style.anchor-name]="id()"></div>
|
|
3000
|
-
</div>
|
|
3245
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipFormFieldPopover, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3246
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: ShipFormFieldPopover, isStandalone: true, selector: "sh-form-field-popover", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isOpen: "isOpenChange", closed: "closed" }, host: { listeners: { "click": "onClick()" }, properties: { "class": "hostClasses()" } }, ngImport: i0, template: `
|
|
3247
|
+
<ng-content select="label"></ng-content>
|
|
3001
3248
|
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3249
|
+
<sh-popover
|
|
3250
|
+
[(isOpen)]="isOpen"
|
|
3251
|
+
(closed)="close()"
|
|
3252
|
+
[asSheetOnMobile]="true"
|
|
3253
|
+
[options]="{
|
|
3254
|
+
closeOnButton: false,
|
|
3255
|
+
closeOnEsc: true,
|
|
3256
|
+
}">
|
|
3257
|
+
<div trigger class="input-wrap">
|
|
3258
|
+
<div class="prefix">
|
|
3259
|
+
<ng-content select="[prefix]"></ng-content>
|
|
3260
|
+
<ng-content select="[textPrefix]"></ng-content>
|
|
3007
3261
|
</div>
|
|
3262
|
+
|
|
3263
|
+
<div class="prefix-space"></div>
|
|
3264
|
+
|
|
3265
|
+
<ng-content select="input"></ng-content>
|
|
3266
|
+
|
|
3267
|
+
<ng-content select="textarea"></ng-content>
|
|
3268
|
+
|
|
3269
|
+
<ng-content select="[textSuffix]"></ng-content>
|
|
3270
|
+
<div class="suffix-space"></div>
|
|
3271
|
+
<ng-content select="[suffix]"></ng-content>
|
|
3008
3272
|
</div>
|
|
3009
|
-
|
|
3010
|
-
|
|
3273
|
+
<ng-content select="[popoverContent]"></ng-content>
|
|
3274
|
+
</sh-popover>
|
|
3275
|
+
|
|
3276
|
+
<div class="helpers">
|
|
3277
|
+
<div class="error-wrap">
|
|
3278
|
+
<ng-content select="[error]"></ng-content>
|
|
3279
|
+
</div>
|
|
3280
|
+
|
|
3281
|
+
<div class="hint">
|
|
3282
|
+
<ng-content select="[hint]"></ng-content>
|
|
3283
|
+
</div>
|
|
3284
|
+
</div>
|
|
3285
|
+
`, isInline: true, dependencies: [{ kind: "component", type: ShipPopover, selector: "sh-popover", inputs: ["asMultiLayer", "asSheetOnMobile", "disableOpenByClick", "isOpen", "options"], outputs: ["isOpenChange", "closed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3011
3286
|
}
|
|
3012
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type:
|
|
3287
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipFormFieldPopover, decorators: [{
|
|
3013
3288
|
type: Component,
|
|
3014
3289
|
args: [{
|
|
3015
|
-
selector: 'sh-popover',
|
|
3016
|
-
imports: [],
|
|
3290
|
+
selector: 'sh-form-field-popover',
|
|
3291
|
+
imports: [ShipPopover],
|
|
3017
3292
|
template: `
|
|
3018
|
-
<div class="trigger" #triggerRef [attr.popovertarget]="id() + 'hello'" (click)="toggleIsOpen($event)">
|
|
3019
|
-
<div class="trigger-wrapper">
|
|
3020
|
-
<ng-content select="[trigger]" />
|
|
3021
|
-
<ng-content select="button" />
|
|
3022
|
-
<ng-content select="[shButton]" />
|
|
3023
|
-
</div>
|
|
3024
|
-
<div class="trigger-anchor" [style.anchor-name]="id()"></div>
|
|
3025
|
-
</div>
|
|
3026
|
-
|
|
3027
|
-
@if (isOpen()) {
|
|
3028
|
-
<div [attr.id]="id() + 'hello'" popover="manual" #popoverRef class="popover">
|
|
3029
|
-
<div class="overlay" (click)="eventClose($event)"></div>
|
|
3030
|
-
<div class="popover-content" #popoverContentRef [style.position-anchor]="id()" [style]="menuStyle()">
|
|
3031
|
-
<ng-content />
|
|
3032
|
-
</div>
|
|
3033
|
-
</div>
|
|
3034
|
-
}
|
|
3035
|
-
`,
|
|
3036
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3037
|
-
host: {
|
|
3038
|
-
'[class.multi-layer]': 'asMultiLayer()',
|
|
3039
|
-
},
|
|
3040
|
-
}]
|
|
3041
|
-
}], propDecorators: { asMultiLayer: [{ type: i0.Input, args: [{ isSignal: true, alias: "asMultiLayer", required: false }] }], disableOpenByClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableOpenByClick", required: false }] }], isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }, { type: i0.Output, args: ["isOpenChange"] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], triggerRef: [{ type: i0.ViewChild, args: ['triggerRef', { isSignal: true }] }], popoverRef: [{ type: i0.ViewChild, args: ['popoverRef', { isSignal: true }] }], popoverContentRef: [{ type: i0.ViewChild, args: ['popoverContentRef', { isSignal: true }] }] } });
|
|
3042
|
-
|
|
3043
|
-
class ShipFormFieldPopover {
|
|
3044
|
-
constructor() {
|
|
3045
|
-
this.#selfRef = inject(ElementRef);
|
|
3046
|
-
this.isOpen = model(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
3047
|
-
this.closed = output();
|
|
3048
|
-
}
|
|
3049
|
-
#selfRef;
|
|
3050
|
-
onClick() {
|
|
3051
|
-
if (this.#selfRef.nativeElement.querySelector('input')) {
|
|
3052
|
-
this.#selfRef.nativeElement.querySelector('input').focus();
|
|
3053
|
-
}
|
|
3054
|
-
if (this.#selfRef.nativeElement.querySelector('textarea')) {
|
|
3055
|
-
this.#selfRef.nativeElement.querySelector('textarea').focus();
|
|
3056
|
-
}
|
|
3057
|
-
}
|
|
3058
|
-
close() {
|
|
3059
|
-
this.closed.emit();
|
|
3060
|
-
}
|
|
3061
|
-
ngOnInit() {
|
|
3062
|
-
const supportFieldSizing = typeof CSS !== 'undefined' && CSS.supports('field-sizing', 'content');
|
|
3063
|
-
const text = this.#selfRef.nativeElement.querySelector('textarea');
|
|
3064
|
-
if (!supportFieldSizing && text !== null) {
|
|
3065
|
-
const text = this.#selfRef.nativeElement.querySelector('textarea');
|
|
3066
|
-
function resize() {
|
|
3067
|
-
text.style.height = 'auto';
|
|
3068
|
-
text.style.height = text.scrollHeight + 'px';
|
|
3069
|
-
}
|
|
3070
|
-
/* 0-timeout to get the already changed text */
|
|
3071
|
-
function delayedResize() {
|
|
3072
|
-
setTimeout(resize, 0);
|
|
3073
|
-
}
|
|
3074
|
-
if (text) {
|
|
3075
|
-
text.addEventListener('change', resize);
|
|
3076
|
-
text.addEventListener('cut', delayedResize);
|
|
3077
|
-
text.addEventListener('paste', delayedResize);
|
|
3078
|
-
text.addEventListener('drop', delayedResize);
|
|
3079
|
-
text.addEventListener('keydown', delayedResize);
|
|
3080
|
-
text.focus();
|
|
3081
|
-
text.select();
|
|
3082
|
-
resize();
|
|
3083
|
-
}
|
|
3084
|
-
}
|
|
3085
|
-
}
|
|
3086
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipFormFieldPopover, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3087
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: ShipFormFieldPopover, isStandalone: true, selector: "sh-form-field-popover", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isOpen: "isOpenChange", closed: "closed" }, host: { listeners: { "click": "onClick()" } }, ngImport: i0, template: `
|
|
3088
3293
|
<ng-content select="label"></ng-content>
|
|
3089
3294
|
|
|
3090
3295
|
<sh-popover
|
|
3091
3296
|
[(isOpen)]="isOpen"
|
|
3092
3297
|
(closed)="close()"
|
|
3298
|
+
[asSheetOnMobile]="true"
|
|
3093
3299
|
[options]="{
|
|
3094
3300
|
closeOnButton: false,
|
|
3095
3301
|
closeOnEsc: true,
|
|
@@ -3118,62 +3324,727 @@ class ShipFormFieldPopover {
|
|
|
3118
3324
|
<ng-content select="[error]"></ng-content>
|
|
3119
3325
|
</div>
|
|
3120
3326
|
|
|
3121
|
-
<div class="hint">
|
|
3122
|
-
<ng-content select="[hint]"></ng-content>
|
|
3123
|
-
</div>
|
|
3124
|
-
</div>
|
|
3125
|
-
`,
|
|
3327
|
+
<div class="hint">
|
|
3328
|
+
<ng-content select="[hint]"></ng-content>
|
|
3329
|
+
</div>
|
|
3330
|
+
</div>
|
|
3331
|
+
`,
|
|
3332
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3333
|
+
host: {
|
|
3334
|
+
'[class]': 'hostClasses()',
|
|
3335
|
+
},
|
|
3336
|
+
}]
|
|
3337
|
+
}], propDecorators: { isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }, { type: i0.Output, args: ["isOpenChange"] }], closed: [{ type: i0.Output, args: ["closed"] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], onClick: [{
|
|
3338
|
+
type: HostListener,
|
|
3339
|
+
args: ['click']
|
|
3340
|
+
}] } });
|
|
3341
|
+
|
|
3342
|
+
class ShipColorPickerInput {
|
|
3343
|
+
constructor() {
|
|
3344
|
+
this.#document = inject(DOCUMENT);
|
|
3345
|
+
this.renderingType = input('hsl', ...(ngDevMode ? [{ debugName: "renderingType" }] : /* istanbul ignore next */ []));
|
|
3346
|
+
this.format = input('rgb', ...(ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []));
|
|
3347
|
+
this.color = input(null, ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
3348
|
+
this.variant = input(null, ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
3349
|
+
this.size = input(null, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
3350
|
+
this.readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
3351
|
+
this.closed = output();
|
|
3352
|
+
this.isOpen = model(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
3353
|
+
this.currentClass = classMutationSignal();
|
|
3354
|
+
this.isEyeDropperSupported = typeof window !== 'undefined' && 'EyeDropper' in window;
|
|
3355
|
+
this.showEyeDropper = input(true, ...(ngDevMode ? [{ debugName: "showEyeDropper" }] : /* istanbul ignore next */ []));
|
|
3356
|
+
this.internalHue = signal(0, ...(ngDevMode ? [{ debugName: "internalHue" }] : /* istanbul ignore next */ []));
|
|
3357
|
+
this.internalAlpha = signal(1, ...(ngDevMode ? [{ debugName: "internalAlpha" }] : /* istanbul ignore next */ []));
|
|
3358
|
+
this.internalColorTuple = signal([255, 255, 255, 1], ...(ngDevMode ? [{ debugName: "internalColorTuple" }] : /* istanbul ignore next */ []));
|
|
3359
|
+
this.hasAlpha = computed(() => ['rgba', 'hex8', 'hsla'].includes(this.format()), ...(ngDevMode ? [{ debugName: "hasAlpha" }] : /* istanbul ignore next */ []));
|
|
3360
|
+
this.formattedColorString = computed(() => {
|
|
3361
|
+
const format = this.format();
|
|
3362
|
+
const tuple = this.internalColorTuple();
|
|
3363
|
+
const [r, g, b, aRaw] = tuple;
|
|
3364
|
+
const a = aRaw ?? 1;
|
|
3365
|
+
switch (format) {
|
|
3366
|
+
case 'rgb':
|
|
3367
|
+
return `rgb(${r}, ${g}, ${b})`;
|
|
3368
|
+
case 'rgba':
|
|
3369
|
+
return `rgba(${r}, ${g}, ${b}, ${a})`;
|
|
3370
|
+
case 'hex':
|
|
3371
|
+
return rgbToHex(r, g, b);
|
|
3372
|
+
case 'hex8':
|
|
3373
|
+
return rgbaToHex8(r, g, b, a);
|
|
3374
|
+
case 'hsl':
|
|
3375
|
+
return rgbToHsl(r, g, b).string;
|
|
3376
|
+
case 'hsla': {
|
|
3377
|
+
const hsl = rgbToHsl(r, g, b);
|
|
3378
|
+
return `hsla(${hsl.h}, ${hsl.s}%, ${hsl.l}%, ${a})`;
|
|
3379
|
+
}
|
|
3380
|
+
default:
|
|
3381
|
+
return `rgb(${r}, ${g}, ${b})`;
|
|
3382
|
+
}
|
|
3383
|
+
}, ...(ngDevMode ? [{ debugName: "formattedColorString" }] : /* istanbul ignore next */ []));
|
|
3384
|
+
this.#formatSyncEffect = effect(() => {
|
|
3385
|
+
const str = this.formattedColorString();
|
|
3386
|
+
const input = untracked(() => this.#inputRef());
|
|
3387
|
+
if (input && input.value !== str) {
|
|
3388
|
+
if (this.#document.activeElement !== input) {
|
|
3389
|
+
input.value = str;
|
|
3390
|
+
input.dispatchEvent(new Event('input'));
|
|
3391
|
+
}
|
|
3392
|
+
}
|
|
3393
|
+
}, ...(ngDevMode ? [{ debugName: "#formatSyncEffect" }] : /* istanbul ignore next */ []));
|
|
3394
|
+
this.pureHueColor = computed(() => {
|
|
3395
|
+
return hslToRgbExact(this.internalHue(), 100, 50);
|
|
3396
|
+
}, ...(ngDevMode ? [{ debugName: "pureHueColor" }] : /* istanbul ignore next */ []));
|
|
3397
|
+
this.#inputRef = signal(null, ...(ngDevMode ? [{ debugName: "#inputRef" }] : /* istanbul ignore next */ []));
|
|
3398
|
+
this.#inputObserver = contentProjectionSignal('#input-wrap input');
|
|
3399
|
+
this.#inputRefEffect = effect(() => {
|
|
3400
|
+
const inputs = this.#inputObserver();
|
|
3401
|
+
if (!inputs.length)
|
|
3402
|
+
return;
|
|
3403
|
+
const input = inputs[0];
|
|
3404
|
+
if (!input)
|
|
3405
|
+
return;
|
|
3406
|
+
this.#createCustomInputEventListener(input);
|
|
3407
|
+
input.addEventListener('inputValueChanged', (event) => {
|
|
3408
|
+
this.parseAndSetColor(event.detail.value);
|
|
3409
|
+
});
|
|
3410
|
+
input.addEventListener('input', (event) => {
|
|
3411
|
+
const target = event.target;
|
|
3412
|
+
this.parseAndSetColor(target.value);
|
|
3413
|
+
});
|
|
3414
|
+
input.addEventListener('blur', () => {
|
|
3415
|
+
const str = untracked(() => this.formattedColorString());
|
|
3416
|
+
if (input.value !== str) {
|
|
3417
|
+
input.value = str;
|
|
3418
|
+
input.dispatchEvent(new Event('input'));
|
|
3419
|
+
}
|
|
3420
|
+
});
|
|
3421
|
+
input.addEventListener('focus', () => {
|
|
3422
|
+
this.isOpen.set(true);
|
|
3423
|
+
});
|
|
3424
|
+
this.#inputRef.set(input);
|
|
3425
|
+
input.autocomplete = 'off';
|
|
3426
|
+
if (typeof input.value === 'string' && input.value) {
|
|
3427
|
+
this.parseAndSetColor(input.value);
|
|
3428
|
+
}
|
|
3429
|
+
}, ...(ngDevMode ? [{ debugName: "#inputRefEffect" }] : /* istanbul ignore next */ []));
|
|
3430
|
+
}
|
|
3431
|
+
#document;
|
|
3432
|
+
#formatSyncEffect;
|
|
3433
|
+
#inputRef;
|
|
3434
|
+
#inputObserver;
|
|
3435
|
+
onMainColorChange(colorObj) {
|
|
3436
|
+
if (colorObj.hue !== undefined) {
|
|
3437
|
+
if (this.renderingType() === 'hsl' && colorObj.saturation > 0) {
|
|
3438
|
+
this.internalHue.set(colorObj.hue);
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3441
|
+
}
|
|
3442
|
+
onHuePickerChange(colorObj) {
|
|
3443
|
+
if (colorObj.hue !== undefined && colorObj.hue !== this.internalHue()) {
|
|
3444
|
+
this.internalHue.set(colorObj.hue);
|
|
3445
|
+
}
|
|
3446
|
+
}
|
|
3447
|
+
async openEyeDropper(event) {
|
|
3448
|
+
event.preventDefault();
|
|
3449
|
+
event.stopPropagation();
|
|
3450
|
+
try {
|
|
3451
|
+
// @ts-ignore
|
|
3452
|
+
const eyeDropper = new window.EyeDropper();
|
|
3453
|
+
const result = await eyeDropper.open();
|
|
3454
|
+
if (result && result.sRGBHex) {
|
|
3455
|
+
this.parseAndSetColor(result.sRGBHex);
|
|
3456
|
+
// Force the text field to immediately display the new output string according to the active format
|
|
3457
|
+
const input = untracked(() => this.#inputRef());
|
|
3458
|
+
if (input) {
|
|
3459
|
+
const str = this.formattedColorString();
|
|
3460
|
+
if (input.value !== str) {
|
|
3461
|
+
input.value = str;
|
|
3462
|
+
input.dispatchEvent(new Event('input'));
|
|
3463
|
+
}
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
}
|
|
3467
|
+
catch (e) {
|
|
3468
|
+
// User cancelled
|
|
3469
|
+
}
|
|
3470
|
+
}
|
|
3471
|
+
close() {
|
|
3472
|
+
this.closed.emit(this.formattedColorString());
|
|
3473
|
+
}
|
|
3474
|
+
#inputRefEffect;
|
|
3475
|
+
parseAndSetColor(colorStr) {
|
|
3476
|
+
if (!colorStr)
|
|
3477
|
+
return;
|
|
3478
|
+
if (colorStr === untracked(() => this.formattedColorString()))
|
|
3479
|
+
return;
|
|
3480
|
+
const div = this.#document.createElement('div');
|
|
3481
|
+
div.style.color = colorStr;
|
|
3482
|
+
if (div.style.color === '')
|
|
3483
|
+
return; // Not a valid color format
|
|
3484
|
+
this.#document.body.appendChild(div);
|
|
3485
|
+
const computedColor = getComputedStyle(div).color;
|
|
3486
|
+
this.#document.body.removeChild(div);
|
|
3487
|
+
const rgbaMatch = computedColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
|
|
3488
|
+
if (rgbaMatch) {
|
|
3489
|
+
const r = parseInt(rgbaMatch[1], 10);
|
|
3490
|
+
const g = parseInt(rgbaMatch[2], 10);
|
|
3491
|
+
const b = parseInt(rgbaMatch[3], 10);
|
|
3492
|
+
const a = rgbaMatch[4] ? parseFloat(rgbaMatch[4]) : 1;
|
|
3493
|
+
const current = untracked(() => this.internalColorTuple());
|
|
3494
|
+
if (current[0] !== r || current[1] !== g || current[2] !== b || (current[3] ?? 1) !== a) {
|
|
3495
|
+
this.internalColorTuple.set([r, g, b, a]);
|
|
3496
|
+
this.internalAlpha.set(a);
|
|
3497
|
+
// Also update hue so the hue slider matches the typed color!
|
|
3498
|
+
const max = Math.max(r, g, b) / 255;
|
|
3499
|
+
const min = Math.min(r, g, b) / 255;
|
|
3500
|
+
if (max !== min) {
|
|
3501
|
+
const d = max - min;
|
|
3502
|
+
let h = 0;
|
|
3503
|
+
switch (max) {
|
|
3504
|
+
case r / 255:
|
|
3505
|
+
h = (g / 255 - b / 255) / d + (g / 255 < b / 255 ? 6 : 0);
|
|
3506
|
+
break;
|
|
3507
|
+
case g / 255:
|
|
3508
|
+
h = (b / 255 - r / 255) / d + 2;
|
|
3509
|
+
break;
|
|
3510
|
+
case b / 255:
|
|
3511
|
+
h = (r / 255 - g / 255) / d + 4;
|
|
3512
|
+
break;
|
|
3513
|
+
}
|
|
3514
|
+
h /= 6;
|
|
3515
|
+
this.internalHue.set(Math.floor(h * 360));
|
|
3516
|
+
}
|
|
3517
|
+
}
|
|
3518
|
+
}
|
|
3519
|
+
}
|
|
3520
|
+
hslToRgbExact(h, s, l) {
|
|
3521
|
+
s /= 100;
|
|
3522
|
+
l /= 100;
|
|
3523
|
+
const k = (n) => (n + h / 30) % 12;
|
|
3524
|
+
const a = s * Math.min(l, 1 - l);
|
|
3525
|
+
const f = (n) => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
|
|
3526
|
+
return [Math.round(255 * f(0)), Math.round(255 * f(8)), Math.round(255 * f(4))];
|
|
3527
|
+
}
|
|
3528
|
+
rgbToHex(r, g, b) {
|
|
3529
|
+
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
|
|
3530
|
+
}
|
|
3531
|
+
rgbaToHex8(r, g, b, a) {
|
|
3532
|
+
const alphaHex = Math.round(a * 255)
|
|
3533
|
+
.toString(16)
|
|
3534
|
+
.padStart(2, '0');
|
|
3535
|
+
return this.rgbToHex(r, g, b) + alphaHex;
|
|
3536
|
+
}
|
|
3537
|
+
rgbToHsl(r, g, b) {
|
|
3538
|
+
r /= 255;
|
|
3539
|
+
g /= 255;
|
|
3540
|
+
b /= 255;
|
|
3541
|
+
const max = Math.max(r, g, b), min = Math.min(r, g, b);
|
|
3542
|
+
let h = 0, s = 0, l = (max + min) / 2;
|
|
3543
|
+
if (max === min) {
|
|
3544
|
+
h = s = 0;
|
|
3545
|
+
}
|
|
3546
|
+
else {
|
|
3547
|
+
const d = max - min;
|
|
3548
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
3549
|
+
switch (max) {
|
|
3550
|
+
case r:
|
|
3551
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
3552
|
+
break;
|
|
3553
|
+
case g:
|
|
3554
|
+
h = (b - r) / d + 2;
|
|
3555
|
+
break;
|
|
3556
|
+
case b:
|
|
3557
|
+
h = (r - g) / d + 4;
|
|
3558
|
+
break;
|
|
3559
|
+
}
|
|
3560
|
+
h /= 6;
|
|
3561
|
+
}
|
|
3562
|
+
const hDeg = Math.floor(h * 360);
|
|
3563
|
+
const sPct = Math.round(s * 100);
|
|
3564
|
+
const lPct = Math.round(l * 100);
|
|
3565
|
+
return {
|
|
3566
|
+
h: hDeg,
|
|
3567
|
+
s: sPct,
|
|
3568
|
+
l: lPct,
|
|
3569
|
+
string: `hsl(${hDeg}, ${sPct}%, ${lPct}%)`,
|
|
3570
|
+
};
|
|
3571
|
+
}
|
|
3572
|
+
#createCustomInputEventListener(input) {
|
|
3573
|
+
Object.defineProperty(input, 'value', {
|
|
3574
|
+
configurable: true,
|
|
3575
|
+
get() {
|
|
3576
|
+
const descriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value');
|
|
3577
|
+
return descriptor.get.call(this);
|
|
3578
|
+
},
|
|
3579
|
+
set(newVal) {
|
|
3580
|
+
const descriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value');
|
|
3581
|
+
descriptor.set.call(this, newVal);
|
|
3582
|
+
const inputEvent = new CustomEvent('inputValueChanged', {
|
|
3583
|
+
bubbles: true,
|
|
3584
|
+
cancelable: true,
|
|
3585
|
+
detail: {
|
|
3586
|
+
value: newVal,
|
|
3587
|
+
},
|
|
3588
|
+
});
|
|
3589
|
+
this.dispatchEvent(inputEvent);
|
|
3590
|
+
return newVal;
|
|
3591
|
+
},
|
|
3592
|
+
});
|
|
3593
|
+
return input;
|
|
3594
|
+
}
|
|
3595
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipColorPickerInput, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3596
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ShipColorPickerInput, isStandalone: true, selector: "sh-color-picker-input", inputs: { renderingType: { classPropertyName: "renderingType", publicName: "renderingType", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, showEyeDropper: { classPropertyName: "showEyeDropper", publicName: "showEyeDropper", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", isOpen: "isOpenChange" }, ngImport: i0, template: `
|
|
3597
|
+
<sh-form-field-popover
|
|
3598
|
+
(closed)="close()"
|
|
3599
|
+
[(isOpen)]="isOpen"
|
|
3600
|
+
[class]="currentClass()"
|
|
3601
|
+
[variant]="variant()"
|
|
3602
|
+
[size]="size()"
|
|
3603
|
+
[color]="color()"
|
|
3604
|
+
[readonly]="readonly()"
|
|
3605
|
+
>
|
|
3606
|
+
<ng-content select="label" ngProjectAs="label" />
|
|
3607
|
+
|
|
3608
|
+
<ng-content select="[prefix]" ngProjectAs="[prefix]" />
|
|
3609
|
+
<ng-content select="[textPrefix]" ngProjectAs="[textPrefix]" />
|
|
3610
|
+
|
|
3611
|
+
<div id="input-wrap" class="input-container" ngProjectAs="input">
|
|
3612
|
+
<ng-content select="input" />
|
|
3613
|
+
|
|
3614
|
+
<div class="color-indicator" [style.--indicator-color]="formattedColorString()"></div>
|
|
3615
|
+
|
|
3616
|
+
@if (isEyeDropperSupported && showEyeDropper()) {
|
|
3617
|
+
<button size="xsmall" tabindex="-1" variant="outlined" shButton (click)="openEyeDropper($event)">
|
|
3618
|
+
<sh-icon>eyedropper</sh-icon>
|
|
3619
|
+
</button>
|
|
3620
|
+
}
|
|
3621
|
+
</div>
|
|
3622
|
+
|
|
3623
|
+
<ng-content select="[textSuffix]" ngProjectAs="[textSuffix]" />
|
|
3624
|
+
<ng-content select="[suffix]" ngProjectAs="[suffix]" />
|
|
3625
|
+
|
|
3626
|
+
<div popoverContent>
|
|
3627
|
+
@if (this.isOpen()) {
|
|
3628
|
+
<sh-color-picker
|
|
3629
|
+
[renderingType]="renderingType()"
|
|
3630
|
+
[direction]="'horizontal'"
|
|
3631
|
+
[(selectedColor)]="internalColorTuple"
|
|
3632
|
+
[hue]="internalHue()"
|
|
3633
|
+
[(alpha)]="internalAlpha"
|
|
3634
|
+
(currentColor)="onMainColorChange($event)" />
|
|
3635
|
+
|
|
3636
|
+
@if (renderingType() !== 'hsl') {
|
|
3637
|
+
<sh-color-picker
|
|
3638
|
+
renderingType="hue"
|
|
3639
|
+
[direction]="'horizontal'"
|
|
3640
|
+
[hue]="internalHue()"
|
|
3641
|
+
[selectedColor]="pureHueColor()"
|
|
3642
|
+
(currentColor)="onHuePickerChange($event)" />
|
|
3643
|
+
}
|
|
3644
|
+
|
|
3645
|
+
@if (hasAlpha()) {
|
|
3646
|
+
<sh-color-picker
|
|
3647
|
+
renderingType="alpha"
|
|
3648
|
+
[direction]="'horizontal'"
|
|
3649
|
+
[(alpha)]="internalAlpha"
|
|
3650
|
+
[(selectedColor)]="internalColorTuple" />
|
|
3651
|
+
}
|
|
3652
|
+
}
|
|
3653
|
+
</div>
|
|
3654
|
+
</sh-form-field-popover>
|
|
3655
|
+
`, isInline: true, dependencies: [{ kind: "component", type: ShipFormFieldPopover, selector: "sh-form-field-popover", inputs: ["isOpen", "color", "variant", "size", "readonly"], outputs: ["isOpenChange", "closed"] }, { kind: "component", type: ShipColorPicker, selector: "sh-color-picker", inputs: ["showDarkColors", "renderingType", "gridSize", "hue", "direction", "selectedColor", "alpha"], outputs: ["hueChange", "selectedColorChange", "alphaChange", "currentColor"] }, { kind: "component", type: ShipIcon, selector: "sh-icon", inputs: ["color", "size"] }, { kind: "component", type: ShipButton$1, selector: "[shButton]", inputs: ["color", "variant", "size", "readonly"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3656
|
+
}
|
|
3657
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipColorPickerInput, decorators: [{
|
|
3658
|
+
type: Component,
|
|
3659
|
+
args: [{
|
|
3660
|
+
selector: 'sh-color-picker-input',
|
|
3661
|
+
imports: [ShipFormFieldPopover, ShipColorPicker, ShipIcon, ShipButton$1],
|
|
3662
|
+
template: `
|
|
3663
|
+
<sh-form-field-popover
|
|
3664
|
+
(closed)="close()"
|
|
3665
|
+
[(isOpen)]="isOpen"
|
|
3666
|
+
[class]="currentClass()"
|
|
3667
|
+
[variant]="variant()"
|
|
3668
|
+
[size]="size()"
|
|
3669
|
+
[color]="color()"
|
|
3670
|
+
[readonly]="readonly()"
|
|
3671
|
+
>
|
|
3672
|
+
<ng-content select="label" ngProjectAs="label" />
|
|
3673
|
+
|
|
3674
|
+
<ng-content select="[prefix]" ngProjectAs="[prefix]" />
|
|
3675
|
+
<ng-content select="[textPrefix]" ngProjectAs="[textPrefix]" />
|
|
3676
|
+
|
|
3677
|
+
<div id="input-wrap" class="input-container" ngProjectAs="input">
|
|
3678
|
+
<ng-content select="input" />
|
|
3679
|
+
|
|
3680
|
+
<div class="color-indicator" [style.--indicator-color]="formattedColorString()"></div>
|
|
3681
|
+
|
|
3682
|
+
@if (isEyeDropperSupported && showEyeDropper()) {
|
|
3683
|
+
<button size="xsmall" tabindex="-1" variant="outlined" shButton (click)="openEyeDropper($event)">
|
|
3684
|
+
<sh-icon>eyedropper</sh-icon>
|
|
3685
|
+
</button>
|
|
3686
|
+
}
|
|
3687
|
+
</div>
|
|
3688
|
+
|
|
3689
|
+
<ng-content select="[textSuffix]" ngProjectAs="[textSuffix]" />
|
|
3690
|
+
<ng-content select="[suffix]" ngProjectAs="[suffix]" />
|
|
3691
|
+
|
|
3692
|
+
<div popoverContent>
|
|
3693
|
+
@if (this.isOpen()) {
|
|
3694
|
+
<sh-color-picker
|
|
3695
|
+
[renderingType]="renderingType()"
|
|
3696
|
+
[direction]="'horizontal'"
|
|
3697
|
+
[(selectedColor)]="internalColorTuple"
|
|
3698
|
+
[hue]="internalHue()"
|
|
3699
|
+
[(alpha)]="internalAlpha"
|
|
3700
|
+
(currentColor)="onMainColorChange($event)" />
|
|
3701
|
+
|
|
3702
|
+
@if (renderingType() !== 'hsl') {
|
|
3703
|
+
<sh-color-picker
|
|
3704
|
+
renderingType="hue"
|
|
3705
|
+
[direction]="'horizontal'"
|
|
3706
|
+
[hue]="internalHue()"
|
|
3707
|
+
[selectedColor]="pureHueColor()"
|
|
3708
|
+
(currentColor)="onHuePickerChange($event)" />
|
|
3709
|
+
}
|
|
3710
|
+
|
|
3711
|
+
@if (hasAlpha()) {
|
|
3712
|
+
<sh-color-picker
|
|
3713
|
+
renderingType="alpha"
|
|
3714
|
+
[direction]="'horizontal'"
|
|
3715
|
+
[(alpha)]="internalAlpha"
|
|
3716
|
+
[(selectedColor)]="internalColorTuple" />
|
|
3717
|
+
}
|
|
3718
|
+
}
|
|
3719
|
+
</div>
|
|
3720
|
+
</sh-form-field-popover>
|
|
3721
|
+
`,
|
|
3722
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3723
|
+
}]
|
|
3724
|
+
}], propDecorators: { renderingType: [{ type: i0.Input, args: [{ isSignal: true, alias: "renderingType", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }, { type: i0.Output, args: ["isOpenChange"] }], showEyeDropper: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEyeDropper", required: false }] }] } });
|
|
3725
|
+
|
|
3726
|
+
class ShipDatepicker {
|
|
3727
|
+
constructor() {
|
|
3728
|
+
this.#INIT_DATE = new Date(new Date().setHours(0, 0, 0, 0));
|
|
3729
|
+
this.date = model(null, ...(ngDevMode ? [{ debugName: "date" }] : /* istanbul ignore next */ []));
|
|
3730
|
+
this.endDate = model(null, ...(ngDevMode ? [{ debugName: "endDate" }] : /* istanbul ignore next */ []));
|
|
3731
|
+
this.asRange = input(false, ...(ngDevMode ? [{ debugName: "asRange" }] : /* istanbul ignore next */ []));
|
|
3732
|
+
this.monthsToShow = input(1, ...(ngDevMode ? [{ debugName: "monthsToShow" }] : /* istanbul ignore next */ []));
|
|
3733
|
+
this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
3734
|
+
this.startOfWeek = input(1, ...(ngDevMode ? [{ debugName: "startOfWeek" }] : /* istanbul ignore next */ []));
|
|
3735
|
+
this.weekdayLabels = input(['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], ...(ngDevMode ? [{ debugName: "weekdayLabels" }] : /* istanbul ignore next */ []));
|
|
3736
|
+
this.daysRef = viewChild('daysRef', ...(ngDevMode ? [{ debugName: "daysRef" }] : /* istanbul ignore next */ []));
|
|
3737
|
+
this.currentDate = signal(this.date() ?? this.#INIT_DATE, ...(ngDevMode ? [{ debugName: "currentDate" }] : /* istanbul ignore next */ []));
|
|
3738
|
+
this.monthOffsets = computed(() => {
|
|
3739
|
+
return Array.from({ length: this.monthsToShow() }, (_, i) => i);
|
|
3740
|
+
}, ...(ngDevMode ? [{ debugName: "monthOffsets" }] : /* istanbul ignore next */ []));
|
|
3741
|
+
this.selectedDateStylePosition = signal(null, ...(ngDevMode ? [{ debugName: "selectedDateStylePosition" }] : /* istanbul ignore next */ []));
|
|
3742
|
+
this.weekdays = computed(() => {
|
|
3743
|
+
const startOfWeek = this.startOfWeek();
|
|
3744
|
+
const weekdayLabels = this.weekdayLabels();
|
|
3745
|
+
return weekdayLabels.slice(startOfWeek).concat(weekdayLabels.slice(0, startOfWeek));
|
|
3746
|
+
}, ...(ngDevMode ? [{ debugName: "weekdays" }] : /* istanbul ignore next */ []));
|
|
3747
|
+
this.currentClasses = classMutationSignal();
|
|
3748
|
+
this.someEffect = effect(() => {
|
|
3749
|
+
const _ = this.currentClasses();
|
|
3750
|
+
this.#findSelectedAndCalc();
|
|
3751
|
+
}, ...(ngDevMode ? [{ debugName: "someEffect" }] : /* istanbul ignore next */ []));
|
|
3752
|
+
this.#newDateEffect = effect(() => {
|
|
3753
|
+
if (this.monthsToShow() > 1)
|
|
3754
|
+
return;
|
|
3755
|
+
this.#setDateAsCurrent();
|
|
3756
|
+
}, ...(ngDevMode ? [{ debugName: "#newDateEffect" }] : /* istanbul ignore next */ []));
|
|
3757
|
+
}
|
|
3758
|
+
#INIT_DATE;
|
|
3759
|
+
getLastVisibleMonth() {
|
|
3760
|
+
const lastMonthOffset = this.monthsToShow() - 1;
|
|
3761
|
+
return this.getOffsetDate(lastMonthOffset);
|
|
3762
|
+
}
|
|
3763
|
+
getOffsetDate(monthOffset) {
|
|
3764
|
+
const date = new Date(this.currentDate());
|
|
3765
|
+
date.setMonth(date.getMonth() + monthOffset);
|
|
3766
|
+
return date;
|
|
3767
|
+
}
|
|
3768
|
+
getMonthDates(monthOffset) {
|
|
3769
|
+
const offsetDate = this.getOffsetDate(monthOffset);
|
|
3770
|
+
return this.#generateMonthDates(offsetDate, this.startOfWeek());
|
|
3771
|
+
}
|
|
3772
|
+
#newDateEffect;
|
|
3773
|
+
ngOnInit() {
|
|
3774
|
+
if (this.monthsToShow() === 1)
|
|
3775
|
+
return;
|
|
3776
|
+
this.#setDateAsCurrent();
|
|
3777
|
+
}
|
|
3778
|
+
#setDateAsCurrent() {
|
|
3779
|
+
const newDate = this.date();
|
|
3780
|
+
if (newDate)
|
|
3781
|
+
this.currentDate.set(newDate);
|
|
3782
|
+
this.#findSelectedAndCalc();
|
|
3783
|
+
}
|
|
3784
|
+
#findSelectedAndCalc() {
|
|
3785
|
+
setTimeout(() => {
|
|
3786
|
+
const selectedElement = this.daysRef()?.nativeElement.querySelector('.sel');
|
|
3787
|
+
if (!selectedElement) {
|
|
3788
|
+
return this.selectedDateStylePosition.update((x) => (x ? { ...x, opacity: '0' } : null));
|
|
3789
|
+
}
|
|
3790
|
+
this.setSelectedDateStylePosition(selectedElement);
|
|
3791
|
+
});
|
|
3792
|
+
}
|
|
3793
|
+
#generateMonthDates(date, startOfWeek) {
|
|
3794
|
+
const year = date.getFullYear();
|
|
3795
|
+
const month = date.getMonth();
|
|
3796
|
+
const firstDay = new Date(year, month, 1).getDay();
|
|
3797
|
+
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
3798
|
+
const dates = [];
|
|
3799
|
+
let offset = firstDay - startOfWeek;
|
|
3800
|
+
if (offset < 0) {
|
|
3801
|
+
offset += 7;
|
|
3802
|
+
}
|
|
3803
|
+
const lastDayOfPrevMonth = new Date(year, month, 0).getDate();
|
|
3804
|
+
for (let i = offset - 1; i >= 0; i--) {
|
|
3805
|
+
dates.push(new Date(year, month - 1, lastDayOfPrevMonth - i, 0, 0, 0, 0));
|
|
3806
|
+
}
|
|
3807
|
+
for (let i = 1; i <= daysInMonth; i++) {
|
|
3808
|
+
dates.push(new Date(year, month, i, 0, 0, 0, 0));
|
|
3809
|
+
}
|
|
3810
|
+
let nextMonthDay = 1;
|
|
3811
|
+
while (dates.length % 7 !== 0) {
|
|
3812
|
+
dates.push(new Date(year, month + 1, nextMonthDay++, 0, 0, 0, 0));
|
|
3813
|
+
}
|
|
3814
|
+
return dates;
|
|
3815
|
+
}
|
|
3816
|
+
nextMonth() {
|
|
3817
|
+
this.currentDate.update((currentDate) => {
|
|
3818
|
+
const newDate = new Date(currentDate);
|
|
3819
|
+
newDate.setMonth(currentDate.getMonth() + 1);
|
|
3820
|
+
return newDate;
|
|
3821
|
+
});
|
|
3822
|
+
this.#findSelectedAndCalc();
|
|
3823
|
+
}
|
|
3824
|
+
previousMonth() {
|
|
3825
|
+
this.currentDate.update((currentDate) => {
|
|
3826
|
+
const newDate = new Date(currentDate);
|
|
3827
|
+
newDate.setMonth(currentDate.getMonth() - 1);
|
|
3828
|
+
return newDate;
|
|
3829
|
+
});
|
|
3830
|
+
this.#findSelectedAndCalc();
|
|
3831
|
+
}
|
|
3832
|
+
setDate(newDate, selectedElement) {
|
|
3833
|
+
const createDateWithExistingTime = (newDate, existingDate) => {
|
|
3834
|
+
const hours = existingDate?.getHours() ?? 0;
|
|
3835
|
+
const minutes = existingDate?.getMinutes() ?? 0;
|
|
3836
|
+
const seconds = existingDate?.getSeconds() ?? 0;
|
|
3837
|
+
const milliseconds = existingDate?.getMilliseconds() ?? 0;
|
|
3838
|
+
return new Date(newDate.getFullYear(), newDate.getMonth(), newDate.getDate(), hours, minutes, seconds, milliseconds);
|
|
3839
|
+
};
|
|
3840
|
+
if (!this.asRange()) {
|
|
3841
|
+
this.date.set(createDateWithExistingTime(newDate, this.date()));
|
|
3842
|
+
this.endDate.set(null);
|
|
3843
|
+
}
|
|
3844
|
+
else {
|
|
3845
|
+
const startDate = this.date();
|
|
3846
|
+
const endDate = this.endDate();
|
|
3847
|
+
const utcDate = createDateWithExistingTime(newDate, null);
|
|
3848
|
+
if (!startDate) {
|
|
3849
|
+
this.date.set(utcDate);
|
|
3850
|
+
}
|
|
3851
|
+
else if (!endDate) {
|
|
3852
|
+
if (utcDate < startDate) {
|
|
3853
|
+
this.date.set(utcDate);
|
|
3854
|
+
this.endDate.set(null);
|
|
3855
|
+
}
|
|
3856
|
+
else {
|
|
3857
|
+
this.endDate.set(utcDate);
|
|
3858
|
+
}
|
|
3859
|
+
}
|
|
3860
|
+
else {
|
|
3861
|
+
this.date.set(utcDate);
|
|
3862
|
+
this.endDate.set(null);
|
|
3863
|
+
}
|
|
3864
|
+
}
|
|
3865
|
+
if (this.asRange())
|
|
3866
|
+
return;
|
|
3867
|
+
this.setSelectedDateStylePosition(selectedElement);
|
|
3868
|
+
}
|
|
3869
|
+
isDateSelected(date) {
|
|
3870
|
+
const startDate = this.date();
|
|
3871
|
+
const endDate = this.endDate();
|
|
3872
|
+
if (startDate === null)
|
|
3873
|
+
return null;
|
|
3874
|
+
const startOfDay = (date) => {
|
|
3875
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0);
|
|
3876
|
+
};
|
|
3877
|
+
const endOfDay = (date) => {
|
|
3878
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999);
|
|
3879
|
+
};
|
|
3880
|
+
const currentDate = startOfDay(date);
|
|
3881
|
+
const rangeStart = startOfDay(startDate);
|
|
3882
|
+
const rangeEnd = endDate ? endOfDay(endDate) : null;
|
|
3883
|
+
let classes = [];
|
|
3884
|
+
if (this.asRange()) {
|
|
3885
|
+
if (rangeEnd === null) {
|
|
3886
|
+
if (currentDate.getTime() === rangeStart.getTime()) {
|
|
3887
|
+
classes.push('sel first last');
|
|
3888
|
+
}
|
|
3889
|
+
}
|
|
3890
|
+
else {
|
|
3891
|
+
if (currentDate.getTime() === rangeStart.getTime()) {
|
|
3892
|
+
classes.push('first');
|
|
3893
|
+
}
|
|
3894
|
+
if (currentDate.getTime() === startOfDay(rangeEnd).getTime()) {
|
|
3895
|
+
classes.push('last');
|
|
3896
|
+
}
|
|
3897
|
+
if (currentDate >= rangeStart && currentDate <= rangeEnd) {
|
|
3898
|
+
classes.push('sel');
|
|
3899
|
+
const dayOfWeek = currentDate.getDay();
|
|
3900
|
+
const startOfWeek = this.startOfWeek();
|
|
3901
|
+
if (dayOfWeek === startOfWeek) {
|
|
3902
|
+
classes.push('week-start');
|
|
3903
|
+
}
|
|
3904
|
+
const endOfWeek = (startOfWeek + 6) % 7;
|
|
3905
|
+
if (dayOfWeek === endOfWeek) {
|
|
3906
|
+
classes.push('week-end');
|
|
3907
|
+
}
|
|
3908
|
+
}
|
|
3909
|
+
const nextDate = new Date(currentDate);
|
|
3910
|
+
nextDate.setDate(currentDate.getDate() + 1);
|
|
3911
|
+
const prevDate = new Date(currentDate);
|
|
3912
|
+
prevDate.setDate(currentDate.getDate() - 1);
|
|
3913
|
+
const isFirstOfMonth = currentDate.getDate() === 1;
|
|
3914
|
+
const isLastOfMonth = nextDate.getMonth() !== currentDate.getMonth();
|
|
3915
|
+
if (isFirstOfMonth) {
|
|
3916
|
+
classes.push('month-start');
|
|
3917
|
+
}
|
|
3918
|
+
if (isLastOfMonth) {
|
|
3919
|
+
classes.push('month-end');
|
|
3920
|
+
}
|
|
3921
|
+
}
|
|
3922
|
+
}
|
|
3923
|
+
else {
|
|
3924
|
+
if (currentDate.getTime() === rangeStart.getTime()) {
|
|
3925
|
+
classes.push('sel');
|
|
3926
|
+
}
|
|
3927
|
+
}
|
|
3928
|
+
return classes.join(' ') || null;
|
|
3929
|
+
}
|
|
3930
|
+
setSelectedDateStylePosition(selectedElement) {
|
|
3931
|
+
this.selectedDateStylePosition.set({
|
|
3932
|
+
transform: `translate(${selectedElement.offsetLeft}px, ${selectedElement.offsetTop}px)`,
|
|
3933
|
+
opacity: '1',
|
|
3934
|
+
});
|
|
3935
|
+
}
|
|
3936
|
+
getMonthName(date) {
|
|
3937
|
+
return date.toLocaleString('default', { month: 'long' });
|
|
3938
|
+
}
|
|
3939
|
+
getFullYear(date) {
|
|
3940
|
+
return date.getFullYear();
|
|
3941
|
+
}
|
|
3942
|
+
// Rest of the component methods remain the same, but update isCurrentMonth:
|
|
3943
|
+
isCurrentMonth(date, monthOffset) {
|
|
3944
|
+
const offsetDate = this.getOffsetDate(monthOffset);
|
|
3945
|
+
return date.getMonth() === offsetDate.getMonth();
|
|
3946
|
+
}
|
|
3947
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipDatepicker, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3948
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: ShipDatepicker, isStandalone: true, selector: "sh-datepicker", inputs: { date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null }, endDate: { classPropertyName: "endDate", publicName: "endDate", isSignal: true, isRequired: false, transformFunction: null }, asRange: { classPropertyName: "asRange", publicName: "asRange", isSignal: true, isRequired: false, transformFunction: null }, monthsToShow: { classPropertyName: "monthsToShow", publicName: "monthsToShow", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, startOfWeek: { classPropertyName: "startOfWeek", publicName: "startOfWeek", isSignal: true, isRequired: false, transformFunction: null }, weekdayLabels: { classPropertyName: "weekdayLabels", publicName: "weekdayLabels", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { date: "dateChange", endDate: "endDateChange" }, host: { properties: { "class.as-range": "asRange()", "class": "\"columns-\" + monthsToShow()", "class.disabled": "disabled()" } }, viewQueries: [{ propertyName: "daysRef", first: true, predicate: ["daysRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
3949
|
+
<header>
|
|
3950
|
+
<button (click)="previousMonth()"><sh-icon>caret-left</sh-icon></button>
|
|
3951
|
+
<div class="title">
|
|
3952
|
+
{{ getMonthName(currentDate()!) }}
|
|
3953
|
+
@if (monthsToShow() > 1) {
|
|
3954
|
+
- {{ getMonthName(getLastVisibleMonth()) }}
|
|
3955
|
+
}
|
|
3956
|
+
{{ getFullYear(currentDate()!) }}
|
|
3957
|
+
</div>
|
|
3958
|
+
<button (click)="nextMonth()"><sh-icon>caret-right</sh-icon></button>
|
|
3959
|
+
</header>
|
|
3960
|
+
|
|
3961
|
+
<section class="months-container">
|
|
3962
|
+
@for (monthOffset of monthOffsets(); track monthOffset) {
|
|
3963
|
+
<div class="month">
|
|
3964
|
+
<nav class="weekdays">
|
|
3965
|
+
@for (day of weekdays(); track $index) {
|
|
3966
|
+
<div>{{ day }}</div>
|
|
3967
|
+
}
|
|
3968
|
+
</nav>
|
|
3969
|
+
|
|
3970
|
+
<div class="days" #daysRef>
|
|
3971
|
+
@for (calDate of getMonthDates(monthOffset); track $index) {
|
|
3972
|
+
<div
|
|
3973
|
+
#elementRef
|
|
3974
|
+
[class.out-of-scope]="!isCurrentMonth(calDate, monthOffset)"
|
|
3975
|
+
[class]="isDateSelected(calDate)"
|
|
3976
|
+
(click)="setDate(calDate, elementRef)">
|
|
3977
|
+
{{ calDate.getDate() }}
|
|
3978
|
+
</div>
|
|
3979
|
+
}
|
|
3980
|
+
|
|
3981
|
+
@if (!asRange()) {
|
|
3982
|
+
<article class="days">
|
|
3983
|
+
<div class="sel-el" [style]="selectedDateStylePosition()"></div>
|
|
3984
|
+
</article>
|
|
3985
|
+
}
|
|
3986
|
+
</div>
|
|
3987
|
+
</div>
|
|
3988
|
+
}
|
|
3989
|
+
</section>
|
|
3990
|
+
`, isInline: true, dependencies: [{ kind: "component", type: ShipIcon, selector: "sh-icon", inputs: ["color", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3126
3991
|
}
|
|
3127
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type:
|
|
3992
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipDatepicker, decorators: [{
|
|
3128
3993
|
type: Component,
|
|
3129
3994
|
args: [{
|
|
3130
|
-
selector: 'sh-
|
|
3131
|
-
imports: [
|
|
3995
|
+
selector: 'sh-datepicker',
|
|
3996
|
+
imports: [ShipIcon],
|
|
3132
3997
|
template: `
|
|
3133
|
-
<
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
}">
|
|
3142
|
-
<div trigger class="input-wrap">
|
|
3143
|
-
<div class="prefix">
|
|
3144
|
-
<ng-content select="[prefix]"></ng-content>
|
|
3145
|
-
<ng-content select="[textPrefix]"></ng-content>
|
|
3146
|
-
</div>
|
|
3147
|
-
|
|
3148
|
-
<div class="prefix-space"></div>
|
|
3149
|
-
|
|
3150
|
-
<ng-content select="input"></ng-content>
|
|
3151
|
-
|
|
3152
|
-
<ng-content select="textarea"></ng-content>
|
|
3153
|
-
|
|
3154
|
-
<ng-content select="[textSuffix]"></ng-content>
|
|
3155
|
-
<div class="suffix-space"></div>
|
|
3156
|
-
<ng-content select="[suffix]"></ng-content>
|
|
3998
|
+
<header>
|
|
3999
|
+
<button (click)="previousMonth()"><sh-icon>caret-left</sh-icon></button>
|
|
4000
|
+
<div class="title">
|
|
4001
|
+
{{ getMonthName(currentDate()!) }}
|
|
4002
|
+
@if (monthsToShow() > 1) {
|
|
4003
|
+
- {{ getMonthName(getLastVisibleMonth()) }}
|
|
4004
|
+
}
|
|
4005
|
+
{{ getFullYear(currentDate()!) }}
|
|
3157
4006
|
</div>
|
|
3158
|
-
<
|
|
3159
|
-
</
|
|
4007
|
+
<button (click)="nextMonth()"><sh-icon>caret-right</sh-icon></button>
|
|
4008
|
+
</header>
|
|
3160
4009
|
|
|
3161
|
-
<
|
|
3162
|
-
|
|
3163
|
-
<
|
|
3164
|
-
|
|
4010
|
+
<section class="months-container">
|
|
4011
|
+
@for (monthOffset of monthOffsets(); track monthOffset) {
|
|
4012
|
+
<div class="month">
|
|
4013
|
+
<nav class="weekdays">
|
|
4014
|
+
@for (day of weekdays(); track $index) {
|
|
4015
|
+
<div>{{ day }}</div>
|
|
4016
|
+
}
|
|
4017
|
+
</nav>
|
|
3165
4018
|
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
4019
|
+
<div class="days" #daysRef>
|
|
4020
|
+
@for (calDate of getMonthDates(monthOffset); track $index) {
|
|
4021
|
+
<div
|
|
4022
|
+
#elementRef
|
|
4023
|
+
[class.out-of-scope]="!isCurrentMonth(calDate, monthOffset)"
|
|
4024
|
+
[class]="isDateSelected(calDate)"
|
|
4025
|
+
(click)="setDate(calDate, elementRef)">
|
|
4026
|
+
{{ calDate.getDate() }}
|
|
4027
|
+
</div>
|
|
4028
|
+
}
|
|
4029
|
+
|
|
4030
|
+
@if (!asRange()) {
|
|
4031
|
+
<article class="days">
|
|
4032
|
+
<div class="sel-el" [style]="selectedDateStylePosition()"></div>
|
|
4033
|
+
</article>
|
|
4034
|
+
}
|
|
4035
|
+
</div>
|
|
4036
|
+
</div>
|
|
4037
|
+
}
|
|
4038
|
+
</section>
|
|
3170
4039
|
`,
|
|
3171
4040
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
4041
|
+
host: {
|
|
4042
|
+
'[class.as-range]': 'asRange()',
|
|
4043
|
+
'[class]': '"columns-" + monthsToShow()',
|
|
4044
|
+
'[class.disabled]': 'disabled()',
|
|
4045
|
+
},
|
|
3172
4046
|
}]
|
|
3173
|
-
}], propDecorators: {
|
|
3174
|
-
type: HostListener,
|
|
3175
|
-
args: ['click']
|
|
3176
|
-
}] } });
|
|
4047
|
+
}], propDecorators: { date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }, { type: i0.Output, args: ["dateChange"] }], endDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "endDate", required: false }] }, { type: i0.Output, args: ["endDateChange"] }], asRange: [{ type: i0.Input, args: [{ isSignal: true, alias: "asRange", required: false }] }], monthsToShow: [{ type: i0.Input, args: [{ isSignal: true, alias: "monthsToShow", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], startOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "startOfWeek", required: false }] }], weekdayLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekdayLabels", required: false }] }], daysRef: [{ type: i0.ViewChild, args: ['daysRef', { isSignal: true }] }] } });
|
|
3177
4048
|
|
|
3178
4049
|
class ShipDatepickerInput {
|
|
3179
4050
|
constructor() {
|
|
@@ -3285,7 +4156,7 @@ class ShipDatepickerInput {
|
|
|
3285
4156
|
</sh-form-field-popover>
|
|
3286
4157
|
|
|
3287
4158
|
<ng-template #defaultIndicator></ng-template>
|
|
3288
|
-
`, isInline: true, dependencies: [{ kind: "component", type: ShipDatepicker, selector: "sh-datepicker", inputs: ["date", "endDate", "asRange", "monthsToShow", "disabled", "startOfWeek", "weekdayLabels"], outputs: ["dateChange", "endDateChange"] }, { kind: "component", type: ShipFormFieldPopover, selector: "sh-form-field-popover", inputs: ["isOpen"], outputs: ["isOpenChange", "closed"] }, { kind: "component", type: ShipIcon, selector: "sh-icon", inputs: ["color", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4159
|
+
`, isInline: true, dependencies: [{ kind: "component", type: ShipDatepicker, selector: "sh-datepicker", inputs: ["date", "endDate", "asRange", "monthsToShow", "disabled", "startOfWeek", "weekdayLabels"], outputs: ["dateChange", "endDateChange"] }, { kind: "component", type: ShipFormFieldPopover, selector: "sh-form-field-popover", inputs: ["isOpen", "color", "variant", "size", "readonly"], outputs: ["isOpenChange", "closed"] }, { kind: "component", type: ShipIcon, selector: "sh-icon", inputs: ["color", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3289
4160
|
}
|
|
3290
4161
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipDatepickerInput, decorators: [{
|
|
3291
4162
|
type: Component,
|
|
@@ -3457,7 +4328,7 @@ class ShipDaterangeInput {
|
|
|
3457
4328
|
}
|
|
3458
4329
|
</div>
|
|
3459
4330
|
</sh-form-field-popover>
|
|
3460
|
-
`, isInline: true, dependencies: [{ kind: "component", type: ShipDatepicker, selector: "sh-datepicker", inputs: ["date", "endDate", "asRange", "monthsToShow", "disabled", "startOfWeek", "weekdayLabels"], outputs: ["dateChange", "endDateChange"] }, { kind: "component", type: ShipFormFieldPopover, selector: "sh-form-field-popover", inputs: ["isOpen"], outputs: ["isOpenChange", "closed"] }, { kind: "component", type: ShipIcon, selector: "sh-icon", inputs: ["color", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4331
|
+
`, isInline: true, dependencies: [{ kind: "component", type: ShipDatepicker, selector: "sh-datepicker", inputs: ["date", "endDate", "asRange", "monthsToShow", "disabled", "startOfWeek", "weekdayLabels"], outputs: ["dateChange", "endDateChange"] }, { kind: "component", type: ShipFormFieldPopover, selector: "sh-form-field-popover", inputs: ["isOpen", "color", "variant", "size", "readonly"], outputs: ["isOpenChange", "closed"] }, { kind: "component", type: ShipIcon, selector: "sh-icon", inputs: ["color", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3461
4332
|
}
|
|
3462
4333
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipDaterangeInput, decorators: [{
|
|
3463
4334
|
type: Component,
|
|
@@ -3783,124 +4654,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
3783
4654
|
}]
|
|
3784
4655
|
}], propDecorators: { inputRef: [{ type: i0.ViewChild, args: ['input', { isSignal: true }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }, { type: i0.Output, args: ["placeholderChange"] }], overlayText: [{ type: i0.Input, args: [{ isSignal: true, alias: "overlayText", required: false }] }], files: [{ type: i0.Input, args: [{ isSignal: true, alias: "files", required: false }] }, { type: i0.Output, args: ["filesChange"] }] } });
|
|
3785
4656
|
|
|
3786
|
-
class ShipAccordion {
|
|
3787
|
-
constructor() {
|
|
3788
|
-
this.selfElement = inject((ElementRef)).nativeElement;
|
|
3789
|
-
this.name = input(`sh-accordion-${Math.random().toString(36).substring(2, 9)}`, ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
3790
|
-
this.value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
3791
|
-
this.allowMultiple = input(false, ...(ngDevMode ? [{ debugName: "allowMultiple" }] : /* istanbul ignore next */ []));
|
|
3792
|
-
this.variant = input(null, ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
3793
|
-
this.size = input(null, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
3794
|
-
this.hostClasses = shipComponentClasses('accordion', {
|
|
3795
|
-
variant: this.variant,
|
|
3796
|
-
size: this.size,
|
|
3797
|
-
});
|
|
3798
|
-
this.items = contentProjectionSignal('details', {
|
|
3799
|
-
childList: true,
|
|
3800
|
-
subtree: true,
|
|
3801
|
-
attributes: true,
|
|
3802
|
-
attributeFilter: ['open', 'value'],
|
|
3803
|
-
});
|
|
3804
|
-
this.selfElement.addEventListener('toggle', this.onToggle.bind(this), true);
|
|
3805
|
-
effect(() => {
|
|
3806
|
-
const isMultiple = this.allowMultiple();
|
|
3807
|
-
const groupName = this.name();
|
|
3808
|
-
const valStr = this.value();
|
|
3809
|
-
const vals = valStr ? valStr.split(',').filter((v) => v !== '') : [];
|
|
3810
|
-
this.items().forEach((details) => {
|
|
3811
|
-
if (!isMultiple) {
|
|
3812
|
-
details.setAttribute('name', groupName);
|
|
3813
|
-
}
|
|
3814
|
-
else {
|
|
3815
|
-
details.removeAttribute('name');
|
|
3816
|
-
}
|
|
3817
|
-
const summary = details.querySelector('summary');
|
|
3818
|
-
if (summary && !summary.querySelector('sh-icon')) {
|
|
3819
|
-
const icon = document.createElement('sh-icon');
|
|
3820
|
-
icon.textContent = 'caret-down';
|
|
3821
|
-
summary.appendChild(icon);
|
|
3822
|
-
}
|
|
3823
|
-
let contentWrapper = details.querySelector(':scope > .content');
|
|
3824
|
-
if (!contentWrapper) {
|
|
3825
|
-
const newWrapper = document.createElement('div');
|
|
3826
|
-
newWrapper.className = 'content';
|
|
3827
|
-
const childrenToMove = Array.from(details.childNodes).filter((node) => {
|
|
3828
|
-
if (node.nodeType === Node.ELEMENT_NODE &&
|
|
3829
|
-
node.tagName.toLowerCase() === 'summary') {
|
|
3830
|
-
return false;
|
|
3831
|
-
}
|
|
3832
|
-
return true;
|
|
3833
|
-
});
|
|
3834
|
-
childrenToMove.forEach((child) => newWrapper.appendChild(child));
|
|
3835
|
-
details.appendChild(newWrapper);
|
|
3836
|
-
contentWrapper = newWrapper;
|
|
3837
|
-
}
|
|
3838
|
-
const itemVal = details.getAttribute('value');
|
|
3839
|
-
if (itemVal && vals.includes(itemVal)) {
|
|
3840
|
-
// Avoid triggering endless loops by only setting open if it actually changed
|
|
3841
|
-
if (!details.open)
|
|
3842
|
-
details.open = true;
|
|
3843
|
-
}
|
|
3844
|
-
else if (itemVal) {
|
|
3845
|
-
if (details.open)
|
|
3846
|
-
details.open = false;
|
|
3847
|
-
}
|
|
3848
|
-
});
|
|
3849
|
-
});
|
|
3850
|
-
}
|
|
3851
|
-
onToggle(event) {
|
|
3852
|
-
const target = event.target;
|
|
3853
|
-
if (target.tagName !== 'DETAILS')
|
|
3854
|
-
return;
|
|
3855
|
-
if (!this.selfElement.contains(target))
|
|
3856
|
-
return;
|
|
3857
|
-
const itemVal = target.getAttribute('value');
|
|
3858
|
-
if (!itemVal)
|
|
3859
|
-
return; // Uncontrolled details element
|
|
3860
|
-
const isOpen = target.open;
|
|
3861
|
-
if (this.allowMultiple()) {
|
|
3862
|
-
let vals = this.value()
|
|
3863
|
-
? this.value()
|
|
3864
|
-
.split(',')
|
|
3865
|
-
.filter((v) => v !== '')
|
|
3866
|
-
: [];
|
|
3867
|
-
if (isOpen && !vals.includes(itemVal))
|
|
3868
|
-
vals.push(itemVal);
|
|
3869
|
-
if (!isOpen)
|
|
3870
|
-
vals = vals.filter((v) => v !== itemVal);
|
|
3871
|
-
this.value.set(vals.join(','));
|
|
3872
|
-
}
|
|
3873
|
-
else {
|
|
3874
|
-
if (isOpen) {
|
|
3875
|
-
this.value.set(itemVal);
|
|
3876
|
-
}
|
|
3877
|
-
else {
|
|
3878
|
-
if (this.value() === itemVal) {
|
|
3879
|
-
this.value.set(null);
|
|
3880
|
-
}
|
|
3881
|
-
}
|
|
3882
|
-
}
|
|
3883
|
-
}
|
|
3884
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipAccordion, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3885
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: ShipAccordion, isStandalone: true, selector: "sh-accordion", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, allowMultiple: { classPropertyName: "allowMultiple", publicName: "allowMultiple", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { properties: { "class.sh-accordion": "true", "class": "hostClasses()" } }, ngImport: i0, template: `
|
|
3886
|
-
<ng-content></ng-content>
|
|
3887
|
-
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3888
|
-
}
|
|
3889
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipAccordion, decorators: [{
|
|
3890
|
-
type: Component,
|
|
3891
|
-
args: [{
|
|
3892
|
-
selector: 'sh-accordion',
|
|
3893
|
-
template: `
|
|
3894
|
-
<ng-content></ng-content>
|
|
3895
|
-
`,
|
|
3896
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3897
|
-
host: {
|
|
3898
|
-
'[class.sh-accordion]': 'true',
|
|
3899
|
-
'[class]': 'hostClasses()',
|
|
3900
|
-
},
|
|
3901
|
-
}]
|
|
3902
|
-
}], ctorParameters: () => [], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], allowMultiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowMultiple", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
3903
|
-
|
|
3904
4657
|
class ShipList {
|
|
3905
4658
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipList, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3906
4659
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.5", type: ShipList, isStandalone: true, selector: "sh-list", ngImport: i0, template: `
|
|
@@ -4474,7 +5227,7 @@ class ShipMenu {
|
|
|
4474
5227
|
<ng-content select="[menu]" />
|
|
4475
5228
|
</div>
|
|
4476
5229
|
</sh-popover>
|
|
4477
|
-
`, isInline: true, dependencies: [{ kind: "component", type: ShipPopover, selector: "sh-popover", inputs: ["asMultiLayer", "disableOpenByClick", "isOpen", "options"], outputs: ["isOpenChange", "closed"] }, { kind: "component", type: ShipFormField, selector: "sh-form-field", inputs: ["color", "variant", "size", "readonly"] }, { kind: "component", type: ShipIcon, selector: "sh-icon", inputs: ["color", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5230
|
+
`, isInline: true, dependencies: [{ kind: "component", type: ShipPopover, selector: "sh-popover", inputs: ["asMultiLayer", "asSheetOnMobile", "disableOpenByClick", "isOpen", "options"], outputs: ["isOpenChange", "closed"] }, { kind: "component", type: ShipFormField, selector: "sh-form-field", inputs: ["color", "variant", "size", "readonly"] }, { kind: "component", type: ShipIcon, selector: "sh-icon", inputs: ["color", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4478
5231
|
}
|
|
4479
5232
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipMenu, decorators: [{
|
|
4480
5233
|
type: Component,
|
|
@@ -4674,6 +5427,18 @@ class ShipRangeSlider {
|
|
|
4674
5427
|
max: 100,
|
|
4675
5428
|
step: 1,
|
|
4676
5429
|
}, ...(ngDevMode ? [{ debugName: "inputState" }] : /* istanbul ignore next */ []));
|
|
5430
|
+
this.color = input(null, ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
5431
|
+
this.variant = input(null, ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
5432
|
+
this.size = input(null, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
5433
|
+
this.sharp = input(undefined, ...(ngDevMode ? [{ debugName: "sharp" }] : /* istanbul ignore next */ []));
|
|
5434
|
+
this.alwaysShow = input(undefined, ...(ngDevMode ? [{ debugName: "alwaysShow" }] : /* istanbul ignore next */ []));
|
|
5435
|
+
this.hostClasses = shipComponentClasses('rangeSlider', {
|
|
5436
|
+
color: this.color,
|
|
5437
|
+
variant: this.variant,
|
|
5438
|
+
size: this.size,
|
|
5439
|
+
sharp: this.sharp,
|
|
5440
|
+
alwaysShow: this.alwaysShow,
|
|
5441
|
+
});
|
|
4677
5442
|
this.valuePercentage = computed(() => {
|
|
4678
5443
|
const { min, max } = this.inputState();
|
|
4679
5444
|
const currentValue = this.value() ?? min;
|
|
@@ -4843,7 +5608,7 @@ class ShipRangeSlider {
|
|
|
4843
5608
|
}
|
|
4844
5609
|
}
|
|
4845
5610
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipRangeSlider, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4846
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: ShipRangeSlider, isStandalone: true, selector: "sh-range-slider", inputs: { unit: { classPropertyName: "unit", publicName: "unit", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { properties: { "class.has-input": "this.hasInputElement" } }, ngImport: i0, template: `
|
|
5611
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.5", type: ShipRangeSlider, isStandalone: true, selector: "sh-range-slider", inputs: { unit: { classPropertyName: "unit", publicName: "unit", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, sharp: { classPropertyName: "sharp", publicName: "sharp", isSignal: true, isRequired: false, transformFunction: null }, alwaysShow: { classPropertyName: "alwaysShow", publicName: "alwaysShow", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { properties: { "class.sh-range-slider": "true", "class": "hostClasses()", "class.has-input": "this.hasInputElement" } }, ngImport: i0, template: `
|
|
4847
5612
|
<div class="label">
|
|
4848
5613
|
<ng-content select="label"></ng-content>
|
|
4849
5614
|
</div>
|
|
@@ -4900,8 +5665,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
4900
5665
|
</div>
|
|
4901
5666
|
`,
|
|
4902
5667
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
5668
|
+
host: {
|
|
5669
|
+
'[class.sh-range-slider]': 'true',
|
|
5670
|
+
'[class]': 'hostClasses()',
|
|
5671
|
+
},
|
|
4903
5672
|
}]
|
|
4904
|
-
}], propDecorators: { unit: [{ type: i0.Input, args: [{ isSignal: true, alias: "unit", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], hasInputElement: [{
|
|
5673
|
+
}], propDecorators: { unit: [{ type: i0.Input, args: [{ isSignal: true, alias: "unit", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], sharp: [{ type: i0.Input, args: [{ isSignal: true, alias: "sharp", required: false }] }], alwaysShow: [{ type: i0.Input, args: [{ isSignal: true, alias: "alwaysShow", required: false }] }], hasInputElement: [{
|
|
4905
5674
|
type: HostBinding,
|
|
4906
5675
|
args: ['class.has-input']
|
|
4907
5676
|
}] } });
|
|
@@ -5659,7 +6428,7 @@ class ShipSelect {
|
|
|
5659
6428
|
}
|
|
5660
6429
|
</div>
|
|
5661
6430
|
</sh-popover>
|
|
5662
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ShipPopover, selector: "sh-popover", inputs: ["asMultiLayer", "disableOpenByClick", "isOpen", "options"], outputs: ["isOpenChange", "closed"] }, { kind: "component", type: ShipFormField, selector: "sh-form-field", inputs: ["color", "variant", "size", "readonly"] }, { kind: "component", type: ShipIcon, selector: "sh-icon", inputs: ["color", "size"] }, { kind: "component", type: ShipCheckbox, selector: "sh-checkbox", inputs: ["checked", "color", "variant", "readonly", "disabled", "noInternalInput"], outputs: ["checkedChange"] }, { kind: "component", type: ShipSpinner, selector: "sh-spinner", inputs: ["color"] }, { kind: "component", type: ShipChip, selector: "sh-chip", inputs: ["color", "variant", "size", "sharp", "dynamic", "readonly"] }, { kind: "component", type: ShipDivider, selector: "sh-divider" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6431
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ShipPopover, selector: "sh-popover", inputs: ["asMultiLayer", "asSheetOnMobile", "disableOpenByClick", "isOpen", "options"], outputs: ["isOpenChange", "closed"] }, { kind: "component", type: ShipFormField, selector: "sh-form-field", inputs: ["color", "variant", "size", "readonly"] }, { kind: "component", type: ShipIcon, selector: "sh-icon", inputs: ["color", "size"] }, { kind: "component", type: ShipCheckbox, selector: "sh-checkbox", inputs: ["checked", "color", "variant", "readonly", "disabled", "noInternalInput"], outputs: ["checkedChange"] }, { kind: "component", type: ShipSpinner, selector: "sh-spinner", inputs: ["color"] }, { kind: "component", type: ShipChip, selector: "sh-chip", inputs: ["color", "variant", "size", "sharp", "dynamic", "readonly"] }, { kind: "component", type: ShipDivider, selector: "sh-divider" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5663
6432
|
}
|
|
5664
6433
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: ShipSelect, decorators: [{
|
|
5665
6434
|
type: Component,
|
|
@@ -7727,5 +8496,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
7727
8496
|
* Generated bundle index. Do not edit.
|
|
7728
8497
|
*/
|
|
7729
8498
|
|
|
7730
|
-
export { GridSortable, SHIP_CONFIG, ShipAccordion, ShipAlert, ShipAlertContainer, ShipAlertModule, ShipAlertService, ShipBlueprint, ShipButton, ShipButtonGroup, ShipCard, ShipCheckbox, ShipChip, ShipColorPicker, ShipDatepicker, ShipDatepickerInput, ShipDaterangeInput, ShipDialog, ShipDialogService, ShipDivider, ShipEventCard, ShipFileDragDrop, ShipFileUpload, ShipFormField, ShipFormFieldExperimental, ShipIcon, ShipInputMask, ShipList, ShipMenu, ShipPopover, ShipPreventWheel, ShipProgressBar, ShipRadio, ShipRangeSlider, ShipResize, ShipSelect, ShipSidenav, ShipSort, ShipSortable, ShipSpinner, ShipStepper, ShipStickyColumns, ShipTable, ShipTabs, ShipThemeToggle, ShipToggle, ShipToggleCard, ShipTooltip, ShipTooltipWrapper, ShipVirtualScroll, TEST_NODES, moveIndex, watchHostClass };
|
|
8499
|
+
export { GridSortable, SHIP_CONFIG, ShipAccordion, ShipAlert, ShipAlertContainer, ShipAlertModule, ShipAlertService, ShipBlueprint, ShipButton, ShipButtonGroup, ShipCard, ShipCheckbox, ShipChip, ShipColorPicker, ShipColorPickerInput, ShipDatepicker, ShipDatepickerInput, ShipDaterangeInput, ShipDialog, ShipDialogService, ShipDivider, ShipEventCard, ShipFileDragDrop, ShipFileUpload, ShipFormField, ShipFormFieldExperimental, ShipIcon, ShipInputMask, ShipList, ShipMenu, ShipPopover, ShipPreventWheel, ShipProgressBar, ShipRadio, ShipRangeSlider, ShipResize, ShipSelect, ShipSidenav, ShipSort, ShipSortable, ShipSpinner, ShipStepper, ShipStickyColumns, ShipTable, ShipTabs, ShipThemeToggle, ShipToggle, ShipToggleCard, ShipTooltip, ShipTooltipWrapper, ShipVirtualScroll, TEST_NODES, defaultThemeColors, hslToOklch, hslToRgbExact, hsvToRgbExact, moveIndex, rgbToHex, rgbToHsl, rgbToHsv, rgbToOklch, rgbaToHex8, watchHostClass };
|
|
7731
8500
|
//# sourceMappingURL=ship-ui-core.mjs.map
|