@thinkersteps_labs/3d-viewer-angular 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,265 @@
1
+ import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { CANONICAL_METAL_PRESETS, getMetalPreset, } from '@thinkersteps_labs/3d-viewer-core';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@angular/common";
6
+ const SWATCH_STYLES = `
7
+ :host {
8
+ display: block;
9
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
10
+ }
11
+ .td-swatch-group {
12
+ display: flex;
13
+ flex-direction: column;
14
+ gap: 8px;
15
+ }
16
+ .td-swatch-header {
17
+ display: flex;
18
+ justify-content: space-between;
19
+ align-items: baseline;
20
+ font-size: 13px;
21
+ font-weight: 500;
22
+ color: #333333;
23
+ }
24
+ .td-swatch-title {
25
+ text-transform: uppercase;
26
+ letter-spacing: 0.05em;
27
+ font-size: 11px;
28
+ font-weight: 600;
29
+ color: #666666;
30
+ }
31
+ .td-swatch-selected-name {
32
+ font-weight: 600;
33
+ color: #111111;
34
+ }
35
+ .td-swatch-row {
36
+ display: flex;
37
+ flex-wrap: wrap;
38
+ gap: 8px;
39
+ align-items: center;
40
+ }
41
+ .td-swatch-pill {
42
+ display: inline-flex;
43
+ align-items: center;
44
+ gap: 8px;
45
+ padding: 6px 12px;
46
+ border-radius: 9999px;
47
+ border: 1px solid #e2e8f0;
48
+ background: #ffffff;
49
+ color: #1e293b;
50
+ font-size: 13px;
51
+ font-weight: 500;
52
+ cursor: pointer;
53
+ transition: all 0.15s ease-in-out;
54
+ outline: none;
55
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
56
+ }
57
+ .td-swatch-pill:hover {
58
+ border-color: #cbd5e1;
59
+ background: #f8fafc;
60
+ transform: translateY(-1px);
61
+ }
62
+ .td-swatch-pill.active {
63
+ border-color: #0f172a;
64
+ background: #0f172a;
65
+ color: #ffffff;
66
+ box-shadow: 0 2px 4px rgba(15, 23, 42, 0.2);
67
+ }
68
+ .td-swatch-dot {
69
+ position: relative;
70
+ width: 32px;
71
+ height: 32px;
72
+ border-radius: 50%;
73
+ border: 2px solid transparent;
74
+ padding: 2px;
75
+ background: transparent;
76
+ cursor: pointer;
77
+ transition: all 0.15s ease-in-out;
78
+ outline: none;
79
+ display: inline-flex;
80
+ align-items: center;
81
+ justify-content: center;
82
+ }
83
+ .td-swatch-dot:hover {
84
+ transform: scale(1.1);
85
+ }
86
+ .td-swatch-dot.active {
87
+ border-color: #0f172a;
88
+ transform: scale(1.08);
89
+ }
90
+ .td-swatch-color-circle {
91
+ width: 100%;
92
+ height: 100%;
93
+ border-radius: 50%;
94
+ border: 1px solid rgba(0, 0, 0, 0.12);
95
+ box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.4), 0 1px 2px rgba(0, 0, 0, 0.08);
96
+ display: inline-block;
97
+ flex-shrink: 0;
98
+ }
99
+ .td-swatch-pill .td-swatch-color-circle {
100
+ width: 14px;
101
+ height: 14px;
102
+ }
103
+ .td-select-wrapper {
104
+ display: flex;
105
+ flex-direction: column;
106
+ gap: 6px;
107
+ }
108
+ .td-select {
109
+ padding: 8px 12px;
110
+ border-radius: 8px;
111
+ border: 1px solid #cbd5e1;
112
+ background-color: #ffffff;
113
+ font-size: 14px;
114
+ color: #1e293b;
115
+ outline: none;
116
+ cursor: pointer;
117
+ transition: border-color 0.15s;
118
+ }
119
+ .td-select:focus {
120
+ border-color: #0f172a;
121
+ box-shadow: 0 0 0 2px rgba(15, 23, 42, 0.1);
122
+ }
123
+ `;
124
+ export class MetalSwatchesComponent {
125
+ constructor() {
126
+ this.valueChange = new EventEmitter();
127
+ this.options = CANONICAL_METAL_PRESETS;
128
+ this.category = 'all';
129
+ this.variant = 'pills';
130
+ this.showLabel = true;
131
+ }
132
+ get visibleOptions() {
133
+ if (this.category === 'all')
134
+ return this.options;
135
+ return this.options.filter((m) => m.category === this.category);
136
+ }
137
+ get activePreset() {
138
+ return this.value ? getMetalPreset(this.value) : undefined;
139
+ }
140
+ isSelected(m) {
141
+ if (!this.value)
142
+ return false;
143
+ const active = this.activePreset;
144
+ return active ? active.id === m.id : this.value === m.id || this.value === m.hex;
145
+ }
146
+ selectMetal(m) {
147
+ this.value = m.id;
148
+ this.valueChange.emit(m.id);
149
+ }
150
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MetalSwatchesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
151
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: MetalSwatchesComponent, isStandalone: true, selector: "td-metal-swatches", inputs: { value: "value", options: "options", category: "category", variant: "variant", showLabel: "showLabel" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `
152
+ <div class="td-swatch-group">
153
+ <div class="td-swatch-header" *ngIf="showLabel">
154
+ <span class="td-swatch-title">Metal</span>
155
+ <span class="td-swatch-selected-name" *ngIf="activePreset">
156
+ {{ activePreset.label }}
157
+ </span>
158
+ </div>
159
+ <div class="td-swatch-row" role="radiogroup" aria-label="Metal Selection">
160
+ <button
161
+ *ngFor="let m of visibleOptions"
162
+ type="button"
163
+ role="radio"
164
+ [attr.aria-checked]="isSelected(m)"
165
+ [title]="m.label"
166
+ class="td-swatch-{{ variant === 'dots' ? 'dot' : 'pill' }}"
167
+ [class.active]="isSelected(m)"
168
+ (click)="selectMetal(m)"
169
+ >
170
+ <span class="td-swatch-color-circle" [style.backgroundColor]="m.hex"></span>
171
+ <span *ngIf="variant === 'pills'">{{ m.label }}</span>
172
+ </button>
173
+ </div>
174
+ </div>
175
+ `, isInline: true, styles: ["\n :host {\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n .td-swatch-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n .td-swatch-header {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n font-size: 13px;\n font-weight: 500;\n color: #333333;\n }\n .td-swatch-title {\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-size: 11px;\n font-weight: 600;\n color: #666666;\n }\n .td-swatch-selected-name {\n font-weight: 600;\n color: #111111;\n }\n .td-swatch-row {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n }\n .td-swatch-pill {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border-radius: 9999px;\n border: 1px solid #e2e8f0;\n background: #ffffff;\n color: #1e293b;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n outline: none;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);\n }\n .td-swatch-pill:hover {\n border-color: #cbd5e1;\n background: #f8fafc;\n transform: translateY(-1px);\n }\n .td-swatch-pill.active {\n border-color: #0f172a;\n background: #0f172a;\n color: #ffffff;\n box-shadow: 0 2px 4px rgba(15, 23, 42, 0.2);\n }\n .td-swatch-dot {\n position: relative;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n border: 2px solid transparent;\n padding: 2px;\n background: transparent;\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n outline: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n .td-swatch-dot:hover {\n transform: scale(1.1);\n }\n .td-swatch-dot.active {\n border-color: #0f172a;\n transform: scale(1.08);\n }\n .td-swatch-color-circle {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 1px solid rgba(0, 0, 0, 0.12);\n box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.4), 0 1px 2px rgba(0, 0, 0, 0.08);\n display: inline-block;\n flex-shrink: 0;\n }\n .td-swatch-pill .td-swatch-color-circle {\n width: 14px;\n height: 14px;\n }\n .td-select-wrapper {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n .td-select {\n padding: 8px 12px;\n border-radius: 8px;\n border: 1px solid #cbd5e1;\n background-color: #ffffff;\n font-size: 14px;\n color: #1e293b;\n outline: none;\n cursor: pointer;\n transition: border-color 0.15s;\n }\n .td-select:focus {\n border-color: #0f172a;\n box-shadow: 0 0 0 2px rgba(15, 23, 42, 0.1);\n }\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
176
+ }
177
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MetalSwatchesComponent, decorators: [{
178
+ type: Component,
179
+ args: [{ selector: 'td-metal-swatches', standalone: true, imports: [CommonModule], template: `
180
+ <div class="td-swatch-group">
181
+ <div class="td-swatch-header" *ngIf="showLabel">
182
+ <span class="td-swatch-title">Metal</span>
183
+ <span class="td-swatch-selected-name" *ngIf="activePreset">
184
+ {{ activePreset.label }}
185
+ </span>
186
+ </div>
187
+ <div class="td-swatch-row" role="radiogroup" aria-label="Metal Selection">
188
+ <button
189
+ *ngFor="let m of visibleOptions"
190
+ type="button"
191
+ role="radio"
192
+ [attr.aria-checked]="isSelected(m)"
193
+ [title]="m.label"
194
+ class="td-swatch-{{ variant === 'dots' ? 'dot' : 'pill' }}"
195
+ [class.active]="isSelected(m)"
196
+ (click)="selectMetal(m)"
197
+ >
198
+ <span class="td-swatch-color-circle" [style.backgroundColor]="m.hex"></span>
199
+ <span *ngIf="variant === 'pills'">{{ m.label }}</span>
200
+ </button>
201
+ </div>
202
+ </div>
203
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["\n :host {\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n .td-swatch-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n .td-swatch-header {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n font-size: 13px;\n font-weight: 500;\n color: #333333;\n }\n .td-swatch-title {\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-size: 11px;\n font-weight: 600;\n color: #666666;\n }\n .td-swatch-selected-name {\n font-weight: 600;\n color: #111111;\n }\n .td-swatch-row {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n }\n .td-swatch-pill {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border-radius: 9999px;\n border: 1px solid #e2e8f0;\n background: #ffffff;\n color: #1e293b;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n outline: none;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);\n }\n .td-swatch-pill:hover {\n border-color: #cbd5e1;\n background: #f8fafc;\n transform: translateY(-1px);\n }\n .td-swatch-pill.active {\n border-color: #0f172a;\n background: #0f172a;\n color: #ffffff;\n box-shadow: 0 2px 4px rgba(15, 23, 42, 0.2);\n }\n .td-swatch-dot {\n position: relative;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n border: 2px solid transparent;\n padding: 2px;\n background: transparent;\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n outline: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n .td-swatch-dot:hover {\n transform: scale(1.1);\n }\n .td-swatch-dot.active {\n border-color: #0f172a;\n transform: scale(1.08);\n }\n .td-swatch-color-circle {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 1px solid rgba(0, 0, 0, 0.12);\n box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.4), 0 1px 2px rgba(0, 0, 0, 0.08);\n display: inline-block;\n flex-shrink: 0;\n }\n .td-swatch-pill .td-swatch-color-circle {\n width: 14px;\n height: 14px;\n }\n .td-select-wrapper {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n .td-select {\n padding: 8px 12px;\n border-radius: 8px;\n border: 1px solid #cbd5e1;\n background-color: #ffffff;\n font-size: 14px;\n color: #1e293b;\n outline: none;\n cursor: pointer;\n transition: border-color 0.15s;\n }\n .td-select:focus {\n border-color: #0f172a;\n box-shadow: 0 0 0 2px rgba(15, 23, 42, 0.1);\n }\n"] }]
204
+ }], propDecorators: { value: [{
205
+ type: Input
206
+ }], valueChange: [{
207
+ type: Output
208
+ }], options: [{
209
+ type: Input
210
+ }], category: [{
211
+ type: Input
212
+ }], variant: [{
213
+ type: Input
214
+ }], showLabel: [{
215
+ type: Input
216
+ }] } });
217
+ export class MetalSelectComponent {
218
+ constructor() {
219
+ this.valueChange = new EventEmitter();
220
+ this.options = CANONICAL_METAL_PRESETS;
221
+ this.label = 'Select Metal';
222
+ }
223
+ get activeValue() {
224
+ const active = this.value ? getMetalPreset(this.value) : undefined;
225
+ return active?.id ?? this.value ?? (this.options[0]?.id || '');
226
+ }
227
+ onSelectChange(event) {
228
+ const target = event.target;
229
+ this.value = target.value;
230
+ this.valueChange.emit(target.value);
231
+ }
232
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MetalSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
233
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: MetalSelectComponent, isStandalone: true, selector: "td-metal-select", inputs: { value: "value", options: "options", label: "label" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `
234
+ <div class="td-select-wrapper">
235
+ <label class="td-swatch-title" *ngIf="label">{{ label }}</label>
236
+ <select class="td-select" [value]="activeValue" (change)="onSelectChange($event)">
237
+ <option *ngFor="let m of options" [value]="m.id">
238
+ {{ m.label }}
239
+ </option>
240
+ </select>
241
+ </div>
242
+ `, isInline: true, styles: ["\n :host {\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n .td-swatch-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n .td-swatch-header {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n font-size: 13px;\n font-weight: 500;\n color: #333333;\n }\n .td-swatch-title {\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-size: 11px;\n font-weight: 600;\n color: #666666;\n }\n .td-swatch-selected-name {\n font-weight: 600;\n color: #111111;\n }\n .td-swatch-row {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n }\n .td-swatch-pill {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border-radius: 9999px;\n border: 1px solid #e2e8f0;\n background: #ffffff;\n color: #1e293b;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n outline: none;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);\n }\n .td-swatch-pill:hover {\n border-color: #cbd5e1;\n background: #f8fafc;\n transform: translateY(-1px);\n }\n .td-swatch-pill.active {\n border-color: #0f172a;\n background: #0f172a;\n color: #ffffff;\n box-shadow: 0 2px 4px rgba(15, 23, 42, 0.2);\n }\n .td-swatch-dot {\n position: relative;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n border: 2px solid transparent;\n padding: 2px;\n background: transparent;\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n outline: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n .td-swatch-dot:hover {\n transform: scale(1.1);\n }\n .td-swatch-dot.active {\n border-color: #0f172a;\n transform: scale(1.08);\n }\n .td-swatch-color-circle {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 1px solid rgba(0, 0, 0, 0.12);\n box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.4), 0 1px 2px rgba(0, 0, 0, 0.08);\n display: inline-block;\n flex-shrink: 0;\n }\n .td-swatch-pill .td-swatch-color-circle {\n width: 14px;\n height: 14px;\n }\n .td-select-wrapper {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n .td-select {\n padding: 8px 12px;\n border-radius: 8px;\n border: 1px solid #cbd5e1;\n background-color: #ffffff;\n font-size: 14px;\n color: #1e293b;\n outline: none;\n cursor: pointer;\n transition: border-color 0.15s;\n }\n .td-select:focus {\n border-color: #0f172a;\n box-shadow: 0 0 0 2px rgba(15, 23, 42, 0.1);\n }\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
243
+ }
244
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MetalSelectComponent, decorators: [{
245
+ type: Component,
246
+ args: [{ selector: 'td-metal-select', standalone: true, imports: [CommonModule], template: `
247
+ <div class="td-select-wrapper">
248
+ <label class="td-swatch-title" *ngIf="label">{{ label }}</label>
249
+ <select class="td-select" [value]="activeValue" (change)="onSelectChange($event)">
250
+ <option *ngFor="let m of options" [value]="m.id">
251
+ {{ m.label }}
252
+ </option>
253
+ </select>
254
+ </div>
255
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["\n :host {\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n .td-swatch-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n .td-swatch-header {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n font-size: 13px;\n font-weight: 500;\n color: #333333;\n }\n .td-swatch-title {\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-size: 11px;\n font-weight: 600;\n color: #666666;\n }\n .td-swatch-selected-name {\n font-weight: 600;\n color: #111111;\n }\n .td-swatch-row {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n }\n .td-swatch-pill {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border-radius: 9999px;\n border: 1px solid #e2e8f0;\n background: #ffffff;\n color: #1e293b;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n outline: none;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);\n }\n .td-swatch-pill:hover {\n border-color: #cbd5e1;\n background: #f8fafc;\n transform: translateY(-1px);\n }\n .td-swatch-pill.active {\n border-color: #0f172a;\n background: #0f172a;\n color: #ffffff;\n box-shadow: 0 2px 4px rgba(15, 23, 42, 0.2);\n }\n .td-swatch-dot {\n position: relative;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n border: 2px solid transparent;\n padding: 2px;\n background: transparent;\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n outline: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n .td-swatch-dot:hover {\n transform: scale(1.1);\n }\n .td-swatch-dot.active {\n border-color: #0f172a;\n transform: scale(1.08);\n }\n .td-swatch-color-circle {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 1px solid rgba(0, 0, 0, 0.12);\n box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.4), 0 1px 2px rgba(0, 0, 0, 0.08);\n display: inline-block;\n flex-shrink: 0;\n }\n .td-swatch-pill .td-swatch-color-circle {\n width: 14px;\n height: 14px;\n }\n .td-select-wrapper {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n .td-select {\n padding: 8px 12px;\n border-radius: 8px;\n border: 1px solid #cbd5e1;\n background-color: #ffffff;\n font-size: 14px;\n color: #1e293b;\n outline: none;\n cursor: pointer;\n transition: border-color 0.15s;\n }\n .td-select:focus {\n border-color: #0f172a;\n box-shadow: 0 0 0 2px rgba(15, 23, 42, 0.1);\n }\n"] }]
256
+ }], propDecorators: { value: [{
257
+ type: Input
258
+ }], valueChange: [{
259
+ type: Output
260
+ }], options: [{
261
+ type: Input
262
+ }], label: [{
263
+ type: Input
264
+ }] } });
265
+ //# sourceMappingURL=metal-swatches.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metal-swatches.component.js","sourceRoot":"","sources":["../../src/swatches/metal-swatches.component.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { EventEmitter } from '@angular/core';
2
+ import { type StonePreset, type StoneColorProp } from '@thinkersteps_labs/3d-viewer-core';
3
+ import * as i0 from "@angular/core";
4
+ export declare class StoneSwatchesComponent {
5
+ value?: StoneColorProp;
6
+ valueChange: EventEmitter<string>;
7
+ options: StonePreset[];
8
+ category: 'all' | 'diamond' | 'gemstone';
9
+ variant: 'pills' | 'dots';
10
+ showLabel: boolean;
11
+ get visibleOptions(): StonePreset[];
12
+ get activePreset(): StonePreset | undefined;
13
+ isSelected(s: StonePreset): boolean;
14
+ selectStone(s: StonePreset): void;
15
+ static ɵfac: i0.ɵɵFactoryDeclaration<StoneSwatchesComponent, never>;
16
+ static ɵcmp: i0.ɵɵComponentDeclaration<StoneSwatchesComponent, "td-stone-swatches", never, { "value": { "alias": "value"; "required": false; }; "options": { "alias": "options"; "required": false; }; "category": { "alias": "category"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "showLabel": { "alias": "showLabel"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
17
+ }
18
+ export declare class StoneSelectComponent {
19
+ value?: StoneColorProp;
20
+ valueChange: EventEmitter<string>;
21
+ options: StonePreset[];
22
+ label: string;
23
+ get activeValue(): string;
24
+ onSelectChange(event: Event): void;
25
+ static ɵfac: i0.ɵɵFactoryDeclaration<StoneSelectComponent, never>;
26
+ static ɵcmp: i0.ɵɵComponentDeclaration<StoneSelectComponent, "td-stone-select", never, { "value": { "alias": "value"; "required": false; }; "options": { "alias": "options"; "required": false; }; "label": { "alias": "label"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
27
+ }
28
+ //# sourceMappingURL=stone-swatches.component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stone-swatches.component.d.ts","sourceRoot":"","sources":["../../src/swatches/stone-swatches.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,YAAY,EAEb,MAAM,eAAe,CAAA;AAEtB,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,cAAc,EACpB,MAAM,mCAAmC,CAAA;;AAyH1C,qBAgCa,sBAAsB;IACxB,KAAK,CAAC,EAAE,cAAc,CAAA;IACrB,WAAW,uBAA6B;IAEzC,OAAO,EAAE,WAAW,EAAE,CAA0B;IAChD,QAAQ,EAAE,KAAK,GAAG,SAAS,GAAG,UAAU,CAAQ;IAChD,OAAO,EAAE,OAAO,GAAG,MAAM,CAAU;IACnC,SAAS,UAAO;IAEzB,IAAI,cAAc,IAAI,WAAW,EAAE,CAGlC;IAED,IAAI,YAAY,IAAI,WAAW,GAAG,SAAS,CAE1C;IAED,UAAU,CAAC,CAAC,EAAE,WAAW,GAAG,OAAO;IAMnC,WAAW,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI;yCAxBtB,sBAAsB;2CAAtB,sBAAsB;CA4BlC;AAED,qBAiBa,oBAAoB;IACtB,KAAK,CAAC,EAAE,cAAc,CAAA;IACrB,WAAW,uBAA6B;IACzC,OAAO,EAAE,WAAW,EAAE,CAA0B;IAChD,KAAK,SAAoB;IAElC,IAAI,WAAW,IAAI,MAAM,CAGxB;IAED,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;yCAXvB,oBAAoB;2CAApB,oBAAoB;CAgBhC"}
@@ -0,0 +1,265 @@
1
+ import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { CANONICAL_STONE_PRESETS, getStonePreset, } from '@thinkersteps_labs/3d-viewer-core';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@angular/common";
6
+ const SWATCH_STYLES = `
7
+ :host {
8
+ display: block;
9
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
10
+ }
11
+ .td-swatch-group {
12
+ display: flex;
13
+ flex-direction: column;
14
+ gap: 8px;
15
+ }
16
+ .td-swatch-header {
17
+ display: flex;
18
+ justify-content: space-between;
19
+ align-items: baseline;
20
+ font-size: 13px;
21
+ font-weight: 500;
22
+ color: #333333;
23
+ }
24
+ .td-swatch-title {
25
+ text-transform: uppercase;
26
+ letter-spacing: 0.05em;
27
+ font-size: 11px;
28
+ font-weight: 600;
29
+ color: #666666;
30
+ }
31
+ .td-swatch-selected-name {
32
+ font-weight: 600;
33
+ color: #111111;
34
+ }
35
+ .td-swatch-row {
36
+ display: flex;
37
+ flex-wrap: wrap;
38
+ gap: 8px;
39
+ align-items: center;
40
+ }
41
+ .td-swatch-pill {
42
+ display: inline-flex;
43
+ align-items: center;
44
+ gap: 8px;
45
+ padding: 6px 12px;
46
+ border-radius: 9999px;
47
+ border: 1px solid #e2e8f0;
48
+ background: #ffffff;
49
+ color: #1e293b;
50
+ font-size: 13px;
51
+ font-weight: 500;
52
+ cursor: pointer;
53
+ transition: all 0.15s ease-in-out;
54
+ outline: none;
55
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
56
+ }
57
+ .td-swatch-pill:hover {
58
+ border-color: #cbd5e1;
59
+ background: #f8fafc;
60
+ transform: translateY(-1px);
61
+ }
62
+ .td-swatch-pill.active {
63
+ border-color: #0f172a;
64
+ background: #0f172a;
65
+ color: #ffffff;
66
+ box-shadow: 0 2px 4px rgba(15, 23, 42, 0.2);
67
+ }
68
+ .td-swatch-dot {
69
+ position: relative;
70
+ width: 32px;
71
+ height: 32px;
72
+ border-radius: 50%;
73
+ border: 2px solid transparent;
74
+ padding: 2px;
75
+ background: transparent;
76
+ cursor: pointer;
77
+ transition: all 0.15s ease-in-out;
78
+ outline: none;
79
+ display: inline-flex;
80
+ align-items: center;
81
+ justify-content: center;
82
+ }
83
+ .td-swatch-dot:hover {
84
+ transform: scale(1.1);
85
+ }
86
+ .td-swatch-dot.active {
87
+ border-color: #0f172a;
88
+ transform: scale(1.08);
89
+ }
90
+ .td-swatch-color-circle {
91
+ width: 100%;
92
+ height: 100%;
93
+ border-radius: 50%;
94
+ border: 1px solid rgba(0, 0, 0, 0.12);
95
+ box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.4), 0 1px 2px rgba(0, 0, 0, 0.08);
96
+ display: inline-block;
97
+ flex-shrink: 0;
98
+ }
99
+ .td-swatch-pill .td-swatch-color-circle {
100
+ width: 14px;
101
+ height: 14px;
102
+ }
103
+ .td-select-wrapper {
104
+ display: flex;
105
+ flex-direction: column;
106
+ gap: 6px;
107
+ }
108
+ .td-select {
109
+ padding: 8px 12px;
110
+ border-radius: 8px;
111
+ border: 1px solid #cbd5e1;
112
+ background-color: #ffffff;
113
+ font-size: 14px;
114
+ color: #1e293b;
115
+ outline: none;
116
+ cursor: pointer;
117
+ transition: border-color 0.15s;
118
+ }
119
+ .td-select:focus {
120
+ border-color: #0f172a;
121
+ box-shadow: 0 0 0 2px rgba(15, 23, 42, 0.1);
122
+ }
123
+ `;
124
+ export class StoneSwatchesComponent {
125
+ constructor() {
126
+ this.valueChange = new EventEmitter();
127
+ this.options = CANONICAL_STONE_PRESETS;
128
+ this.category = 'all';
129
+ this.variant = 'pills';
130
+ this.showLabel = true;
131
+ }
132
+ get visibleOptions() {
133
+ if (this.category === 'all')
134
+ return this.options;
135
+ return this.options.filter((s) => s.category === this.category);
136
+ }
137
+ get activePreset() {
138
+ return this.value ? getStonePreset(this.value) : undefined;
139
+ }
140
+ isSelected(s) {
141
+ if (!this.value)
142
+ return false;
143
+ const active = this.activePreset;
144
+ return active ? active.id === s.id : this.value === s.id || this.value === s.hex;
145
+ }
146
+ selectStone(s) {
147
+ this.value = s.id;
148
+ this.valueChange.emit(s.id);
149
+ }
150
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StoneSwatchesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
151
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: StoneSwatchesComponent, isStandalone: true, selector: "td-stone-swatches", inputs: { value: "value", options: "options", category: "category", variant: "variant", showLabel: "showLabel" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `
152
+ <div class="td-swatch-group">
153
+ <div class="td-swatch-header" *ngIf="showLabel">
154
+ <span class="td-swatch-title">Gemstone</span>
155
+ <span class="td-swatch-selected-name" *ngIf="activePreset">
156
+ {{ activePreset.label }}{{ activePreset.grade ? ' (' + activePreset.grade + ')' : '' }}
157
+ </span>
158
+ </div>
159
+ <div class="td-swatch-row" role="radiogroup" aria-label="Gemstone Selection">
160
+ <button
161
+ *ngFor="let s of visibleOptions"
162
+ type="button"
163
+ role="radio"
164
+ [attr.aria-checked]="isSelected(s)"
165
+ [title]="s.label + (s.grade ? ' - ' + s.grade : '')"
166
+ class="td-swatch-{{ variant === 'dots' ? 'dot' : 'pill' }}"
167
+ [class.active]="isSelected(s)"
168
+ (click)="selectStone(s)"
169
+ >
170
+ <span class="td-swatch-color-circle" [style.backgroundColor]="s.hex"></span>
171
+ <span *ngIf="variant === 'pills'">{{ s.label }}</span>
172
+ </button>
173
+ </div>
174
+ </div>
175
+ `, isInline: true, styles: ["\n :host {\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n .td-swatch-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n .td-swatch-header {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n font-size: 13px;\n font-weight: 500;\n color: #333333;\n }\n .td-swatch-title {\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-size: 11px;\n font-weight: 600;\n color: #666666;\n }\n .td-swatch-selected-name {\n font-weight: 600;\n color: #111111;\n }\n .td-swatch-row {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n }\n .td-swatch-pill {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border-radius: 9999px;\n border: 1px solid #e2e8f0;\n background: #ffffff;\n color: #1e293b;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n outline: none;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);\n }\n .td-swatch-pill:hover {\n border-color: #cbd5e1;\n background: #f8fafc;\n transform: translateY(-1px);\n }\n .td-swatch-pill.active {\n border-color: #0f172a;\n background: #0f172a;\n color: #ffffff;\n box-shadow: 0 2px 4px rgba(15, 23, 42, 0.2);\n }\n .td-swatch-dot {\n position: relative;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n border: 2px solid transparent;\n padding: 2px;\n background: transparent;\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n outline: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n .td-swatch-dot:hover {\n transform: scale(1.1);\n }\n .td-swatch-dot.active {\n border-color: #0f172a;\n transform: scale(1.08);\n }\n .td-swatch-color-circle {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 1px solid rgba(0, 0, 0, 0.12);\n box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.4), 0 1px 2px rgba(0, 0, 0, 0.08);\n display: inline-block;\n flex-shrink: 0;\n }\n .td-swatch-pill .td-swatch-color-circle {\n width: 14px;\n height: 14px;\n }\n .td-select-wrapper {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n .td-select {\n padding: 8px 12px;\n border-radius: 8px;\n border: 1px solid #cbd5e1;\n background-color: #ffffff;\n font-size: 14px;\n color: #1e293b;\n outline: none;\n cursor: pointer;\n transition: border-color 0.15s;\n }\n .td-select:focus {\n border-color: #0f172a;\n box-shadow: 0 0 0 2px rgba(15, 23, 42, 0.1);\n }\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
176
+ }
177
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StoneSwatchesComponent, decorators: [{
178
+ type: Component,
179
+ args: [{ selector: 'td-stone-swatches', standalone: true, imports: [CommonModule], template: `
180
+ <div class="td-swatch-group">
181
+ <div class="td-swatch-header" *ngIf="showLabel">
182
+ <span class="td-swatch-title">Gemstone</span>
183
+ <span class="td-swatch-selected-name" *ngIf="activePreset">
184
+ {{ activePreset.label }}{{ activePreset.grade ? ' (' + activePreset.grade + ')' : '' }}
185
+ </span>
186
+ </div>
187
+ <div class="td-swatch-row" role="radiogroup" aria-label="Gemstone Selection">
188
+ <button
189
+ *ngFor="let s of visibleOptions"
190
+ type="button"
191
+ role="radio"
192
+ [attr.aria-checked]="isSelected(s)"
193
+ [title]="s.label + (s.grade ? ' - ' + s.grade : '')"
194
+ class="td-swatch-{{ variant === 'dots' ? 'dot' : 'pill' }}"
195
+ [class.active]="isSelected(s)"
196
+ (click)="selectStone(s)"
197
+ >
198
+ <span class="td-swatch-color-circle" [style.backgroundColor]="s.hex"></span>
199
+ <span *ngIf="variant === 'pills'">{{ s.label }}</span>
200
+ </button>
201
+ </div>
202
+ </div>
203
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["\n :host {\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n .td-swatch-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n .td-swatch-header {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n font-size: 13px;\n font-weight: 500;\n color: #333333;\n }\n .td-swatch-title {\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-size: 11px;\n font-weight: 600;\n color: #666666;\n }\n .td-swatch-selected-name {\n font-weight: 600;\n color: #111111;\n }\n .td-swatch-row {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n }\n .td-swatch-pill {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border-radius: 9999px;\n border: 1px solid #e2e8f0;\n background: #ffffff;\n color: #1e293b;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n outline: none;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);\n }\n .td-swatch-pill:hover {\n border-color: #cbd5e1;\n background: #f8fafc;\n transform: translateY(-1px);\n }\n .td-swatch-pill.active {\n border-color: #0f172a;\n background: #0f172a;\n color: #ffffff;\n box-shadow: 0 2px 4px rgba(15, 23, 42, 0.2);\n }\n .td-swatch-dot {\n position: relative;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n border: 2px solid transparent;\n padding: 2px;\n background: transparent;\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n outline: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n .td-swatch-dot:hover {\n transform: scale(1.1);\n }\n .td-swatch-dot.active {\n border-color: #0f172a;\n transform: scale(1.08);\n }\n .td-swatch-color-circle {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 1px solid rgba(0, 0, 0, 0.12);\n box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.4), 0 1px 2px rgba(0, 0, 0, 0.08);\n display: inline-block;\n flex-shrink: 0;\n }\n .td-swatch-pill .td-swatch-color-circle {\n width: 14px;\n height: 14px;\n }\n .td-select-wrapper {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n .td-select {\n padding: 8px 12px;\n border-radius: 8px;\n border: 1px solid #cbd5e1;\n background-color: #ffffff;\n font-size: 14px;\n color: #1e293b;\n outline: none;\n cursor: pointer;\n transition: border-color 0.15s;\n }\n .td-select:focus {\n border-color: #0f172a;\n box-shadow: 0 0 0 2px rgba(15, 23, 42, 0.1);\n }\n"] }]
204
+ }], propDecorators: { value: [{
205
+ type: Input
206
+ }], valueChange: [{
207
+ type: Output
208
+ }], options: [{
209
+ type: Input
210
+ }], category: [{
211
+ type: Input
212
+ }], variant: [{
213
+ type: Input
214
+ }], showLabel: [{
215
+ type: Input
216
+ }] } });
217
+ export class StoneSelectComponent {
218
+ constructor() {
219
+ this.valueChange = new EventEmitter();
220
+ this.options = CANONICAL_STONE_PRESETS;
221
+ this.label = 'Select Gemstone';
222
+ }
223
+ get activeValue() {
224
+ const active = this.value ? getStonePreset(this.value) : undefined;
225
+ return active?.id ?? this.value ?? (this.options[0]?.id || '');
226
+ }
227
+ onSelectChange(event) {
228
+ const target = event.target;
229
+ this.value = target.value;
230
+ this.valueChange.emit(target.value);
231
+ }
232
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StoneSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
233
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: StoneSelectComponent, isStandalone: true, selector: "td-stone-select", inputs: { value: "value", options: "options", label: "label" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `
234
+ <div class="td-select-wrapper">
235
+ <label class="td-swatch-title" *ngIf="label">{{ label }}</label>
236
+ <select class="td-select" [value]="activeValue" (change)="onSelectChange($event)">
237
+ <option *ngFor="let s of options" [value]="s.id">
238
+ {{ s.label }} {{ s.grade ? '(' + s.grade + ')' : '' }}
239
+ </option>
240
+ </select>
241
+ </div>
242
+ `, isInline: true, styles: ["\n :host {\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n .td-swatch-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n .td-swatch-header {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n font-size: 13px;\n font-weight: 500;\n color: #333333;\n }\n .td-swatch-title {\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-size: 11px;\n font-weight: 600;\n color: #666666;\n }\n .td-swatch-selected-name {\n font-weight: 600;\n color: #111111;\n }\n .td-swatch-row {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n }\n .td-swatch-pill {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border-radius: 9999px;\n border: 1px solid #e2e8f0;\n background: #ffffff;\n color: #1e293b;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n outline: none;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);\n }\n .td-swatch-pill:hover {\n border-color: #cbd5e1;\n background: #f8fafc;\n transform: translateY(-1px);\n }\n .td-swatch-pill.active {\n border-color: #0f172a;\n background: #0f172a;\n color: #ffffff;\n box-shadow: 0 2px 4px rgba(15, 23, 42, 0.2);\n }\n .td-swatch-dot {\n position: relative;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n border: 2px solid transparent;\n padding: 2px;\n background: transparent;\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n outline: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n .td-swatch-dot:hover {\n transform: scale(1.1);\n }\n .td-swatch-dot.active {\n border-color: #0f172a;\n transform: scale(1.08);\n }\n .td-swatch-color-circle {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 1px solid rgba(0, 0, 0, 0.12);\n box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.4), 0 1px 2px rgba(0, 0, 0, 0.08);\n display: inline-block;\n flex-shrink: 0;\n }\n .td-swatch-pill .td-swatch-color-circle {\n width: 14px;\n height: 14px;\n }\n .td-select-wrapper {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n .td-select {\n padding: 8px 12px;\n border-radius: 8px;\n border: 1px solid #cbd5e1;\n background-color: #ffffff;\n font-size: 14px;\n color: #1e293b;\n outline: none;\n cursor: pointer;\n transition: border-color 0.15s;\n }\n .td-select:focus {\n border-color: #0f172a;\n box-shadow: 0 0 0 2px rgba(15, 23, 42, 0.1);\n }\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
243
+ }
244
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StoneSelectComponent, decorators: [{
245
+ type: Component,
246
+ args: [{ selector: 'td-stone-select', standalone: true, imports: [CommonModule], template: `
247
+ <div class="td-select-wrapper">
248
+ <label class="td-swatch-title" *ngIf="label">{{ label }}</label>
249
+ <select class="td-select" [value]="activeValue" (change)="onSelectChange($event)">
250
+ <option *ngFor="let s of options" [value]="s.id">
251
+ {{ s.label }} {{ s.grade ? '(' + s.grade + ')' : '' }}
252
+ </option>
253
+ </select>
254
+ </div>
255
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["\n :host {\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n .td-swatch-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n .td-swatch-header {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n font-size: 13px;\n font-weight: 500;\n color: #333333;\n }\n .td-swatch-title {\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-size: 11px;\n font-weight: 600;\n color: #666666;\n }\n .td-swatch-selected-name {\n font-weight: 600;\n color: #111111;\n }\n .td-swatch-row {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n }\n .td-swatch-pill {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border-radius: 9999px;\n border: 1px solid #e2e8f0;\n background: #ffffff;\n color: #1e293b;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n outline: none;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);\n }\n .td-swatch-pill:hover {\n border-color: #cbd5e1;\n background: #f8fafc;\n transform: translateY(-1px);\n }\n .td-swatch-pill.active {\n border-color: #0f172a;\n background: #0f172a;\n color: #ffffff;\n box-shadow: 0 2px 4px rgba(15, 23, 42, 0.2);\n }\n .td-swatch-dot {\n position: relative;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n border: 2px solid transparent;\n padding: 2px;\n background: transparent;\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n outline: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n .td-swatch-dot:hover {\n transform: scale(1.1);\n }\n .td-swatch-dot.active {\n border-color: #0f172a;\n transform: scale(1.08);\n }\n .td-swatch-color-circle {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 1px solid rgba(0, 0, 0, 0.12);\n box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.4), 0 1px 2px rgba(0, 0, 0, 0.08);\n display: inline-block;\n flex-shrink: 0;\n }\n .td-swatch-pill .td-swatch-color-circle {\n width: 14px;\n height: 14px;\n }\n .td-select-wrapper {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n .td-select {\n padding: 8px 12px;\n border-radius: 8px;\n border: 1px solid #cbd5e1;\n background-color: #ffffff;\n font-size: 14px;\n color: #1e293b;\n outline: none;\n cursor: pointer;\n transition: border-color 0.15s;\n }\n .td-select:focus {\n border-color: #0f172a;\n box-shadow: 0 0 0 2px rgba(15, 23, 42, 0.1);\n }\n"] }]
256
+ }], propDecorators: { value: [{
257
+ type: Input
258
+ }], valueChange: [{
259
+ type: Output
260
+ }], options: [{
261
+ type: Input
262
+ }], label: [{
263
+ type: Input
264
+ }] } });
265
+ //# sourceMappingURL=stone-swatches.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stone-swatches.component.js","sourceRoot":"","sources":["../../src/swatches/stone-swatches.component.ts"],"names":[],"mappings":"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"}