@thinkersteps_labs/3d-viewer-angular 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +107 -107
- package/dist/swatches/jewelry-customizer.component.js +117 -117
- package/dist/swatches/metal-swatches.component.js +183 -183
- package/dist/swatches/stone-swatches.component.js +183 -183
- package/package.json +49 -49
- package/dist/index.cjs +0 -2
- package/dist/index.cjs.map +0 -1
- package/dist/src/index.d.ts +0 -5
- package/dist/src/viewer.component.d.ts +0 -96
- package/dist/src/viewer.module.d.ts +0 -18
|
@@ -3,123 +3,123 @@ import { CommonModule } from '@angular/common';
|
|
|
3
3
|
import { CANONICAL_STONE_PRESETS, getStonePreset, } from '@thinkersteps_labs/3d-viewer-core';
|
|
4
4
|
import * as i0 from "@angular/core";
|
|
5
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
|
-
}
|
|
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
123
|
`;
|
|
124
124
|
export class StoneSwatchesComponent {
|
|
125
125
|
constructor() {
|
|
@@ -148,58 +148,58 @@ export class StoneSwatchesComponent {
|
|
|
148
148
|
this.valueChange.emit(s.id);
|
|
149
149
|
}
|
|
150
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>
|
|
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
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
176
|
}
|
|
177
177
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StoneSwatchesComponent, decorators: [{
|
|
178
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>
|
|
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
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
204
|
}], propDecorators: { value: [{
|
|
205
205
|
type: Input
|
|
@@ -230,28 +230,28 @@ export class StoneSelectComponent {
|
|
|
230
230
|
this.valueChange.emit(target.value);
|
|
231
231
|
}
|
|
232
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>
|
|
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
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
243
|
}
|
|
244
244
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StoneSelectComponent, decorators: [{
|
|
245
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>
|
|
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
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
256
|
}], propDecorators: { value: [{
|
|
257
257
|
type: Input
|
package/package.json
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@thinkersteps_labs/3d-viewer-angular",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"license": "MIT",
|
|
5
|
-
"repository": {
|
|
6
|
-
"type": "git",
|
|
7
|
-
"url": "git+https://github.com/lalitthinker/3d-jewelry-viewer.git",
|
|
8
|
-
"directory": "packages/angular"
|
|
9
|
-
},
|
|
10
|
-
"publishConfig": {
|
|
11
|
-
"access": "public"
|
|
12
|
-
},
|
|
13
|
-
"type": "module",
|
|
14
|
-
"main": "./dist/index.js",
|
|
15
|
-
"module": "./dist/index.js",
|
|
16
|
-
"types": "./dist/index.d.ts",
|
|
17
|
-
"exports": {
|
|
18
|
-
".": {
|
|
19
|
-
"types": "./dist/index.d.ts",
|
|
20
|
-
"import": "./dist/index.js",
|
|
21
|
-
"default": "./dist/index.js"
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
"files": [
|
|
25
|
-
"dist"
|
|
26
|
-
],
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
"@
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"@angular/
|
|
39
|
-
"@
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"@
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@thinkersteps_labs/3d-viewer-angular",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/lalitthinker/3d-jewelry-viewer.git",
|
|
8
|
+
"directory": "packages/angular"
|
|
9
|
+
},
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "./dist/index.js",
|
|
15
|
+
"module": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"import": "./dist/index.js",
|
|
21
|
+
"default": "./dist/index.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@angular/common": ">=18.0.0",
|
|
29
|
+
"@angular/core": ">=18.0.0",
|
|
30
|
+
"three": ">=0.150.0",
|
|
31
|
+
"@thinkersteps_labs/3d-viewer-core": "1.1.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@angular/common": "^18.2.0",
|
|
35
|
+
"@angular/compiler": "^18.2.0",
|
|
36
|
+
"@angular/compiler-cli": "^18.2.0",
|
|
37
|
+
"@angular/core": "^18.2.0",
|
|
38
|
+
"@angular/platform-browser": "^18.2.0",
|
|
39
|
+
"@types/node": "^20.11.0",
|
|
40
|
+
"rxjs": "^7.8.0",
|
|
41
|
+
"three": "^0.160.0",
|
|
42
|
+
"typescript": "~5.5.4",
|
|
43
|
+
"zone.js": "^0.14.0",
|
|
44
|
+
"@thinkersteps_labs/3d-viewer-core": "1.1.0"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "ngc -p tsconfig.json",
|
|
48
|
+
"typecheck": "tsc --noEmit"
|
|
49
|
+
}
|
|
50
50
|
}
|
package/dist/index.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("@angular/core"),s=require("@3d-viewer/core");function p(l){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(l){for(const t in l)if(t!=="default"){const h=Object.getOwnPropertyDescriptor(l,t);Object.defineProperty(e,t,h.get?h:{enumerable:!0,get:()=>l[t]})}}return e.default=l,Object.freeze(e)}const r=p(i),a=class a{constructor(){this.source=null,this.loaded=new i.EventEmitter,this.progress=new i.EventEmitter,this.partSelected=new i.EventEmitter,this.error=new i.EventEmitter,this.change=new i.EventEmitter,this.viewer=null,this.abortCtrl=null,this.initRafId=null,this.pendingSource=null}getViewer(){return this.viewer}ngAfterViewInit(){this.initRafId=requestAnimationFrame(()=>{this.initRafId=null;const e={...this.options,...this.background!==void 0&&{background:this.background},...this.fov!==void 0&&{fov:this.fov},...this.shadows!==void 0&&{shadows:this.shadows},...this.autoRotate!==void 0&&{autoRotate:this.autoRotate},...this.quality!==void 0&&{quality:this.quality},...this.metalEnvUrl!==void 0&&{metalEnvUrl:this.metalEnvUrl},...this.gemEnvUrl!==void 0&&{gemEnvUrl:this.gemEnvUrl}};this.viewer=s.createViewer(this.containerRef.nativeElement,e),this.viewer.on("loaded",({parts:t})=>this.loaded.emit(t)),this.viewer.on("loading",({progress:t})=>this.progress.emit(t)),this.viewer.on("error",t=>this.error.emit(t)),this.viewer.on("partSelected",t=>this.partSelected.emit(t)),this.viewer.on("change",t=>this.change.emit(t)),this.pendingSource&&(this._loadSource(this.pendingSource),this.pendingSource=null),this.state?this.viewer.setState(this.state):(this.metalColor&&this.viewer.setMetalColor(this.metalColor),this.stoneColor&&this.viewer.setStoneColor(this.stoneColor)),this.autoRotate!==void 0&&(this.autoRotate?this.viewer.startRotation():this.viewer.stopRotation()),this.quality&&this.viewer.setQuality(this.quality)})}ngOnChanges(e){if(!this.viewer){e.source&&(this.pendingSource=this.source);return}if(e.source){const t=e.source.previousValue;this._isSameSource(t,this.source)||this._loadSource(this.source)}e.state&&this.state?this.viewer.setState(this.state):(e.metalColor&&this.metalColor&&this.viewer.setMetalColor(this.metalColor),e.stoneColor&&this.stoneColor&&this.viewer.setStoneColor(this.stoneColor)),e.autoRotate&&this.autoRotate!==void 0&&(this.autoRotate?this.viewer.startRotation():this.viewer.stopRotation()),e.quality&&this.quality&&this.viewer.setQuality(this.quality)}ngOnDestroy(){var e,t;this.initRafId!==null&&(cancelAnimationFrame(this.initRafId),this.initRafId=null),(e=this.abortCtrl)==null||e.abort(),(t=this.viewer)==null||t.dispose(),this.viewer=null}_loadSource(e){var t;if((t=this.abortCtrl)==null||t.abort(),!!this.viewer){if(!e){this.viewer.unload();return}this.abortCtrl=new AbortController,this.viewer.load(e,{signal:this.abortCtrl.signal}).catch(()=>{})}}_isSameSource(e,t){return e===t?!0:!e||!t?!1:"url"in e&&"url"in t?e.url===t.url&&e.format===t.format&&e.mtlUrl===t.mtlUrl:"data"in e&&"data"in t?e.data===t.data&&e.format===t.format:!1}};a.ɵfac=r.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"18.2.14",ngImport:r,type:a,deps:[],target:r.ɵɵFactoryTarget.Component}),a.ɵcmp=r.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"18.2.14",type:a,isStandalone:!0,selector:"td-viewer",inputs:{source:"source",metalColor:"metalColor",stoneColor:"stoneColor",background:"background",metalEnvUrl:"metalEnvUrl",gemEnvUrl:"gemEnvUrl",fov:"fov",shadows:"shadows",options:"options",autoRotate:"autoRotate",quality:"quality",state:"state"},outputs:{loaded:"loaded",progress:"progress",partSelected:"partSelected",error:"error",change:"change"},viewQueries:[{propertyName:"containerRef",first:!0,predicate:["container"],descendants:!0}],usesOnChanges:!0,ngImport:r,template:'<div #container style="width:100%;height:100%;display:block;"></div>',isInline:!0,styles:[""],changeDetection:r.ChangeDetectionStrategy.OnPush});let n=a;r.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"18.2.14",ngImport:r,type:n,decorators:[{type:i.Component,args:[{selector:"td-viewer",standalone:!0,template:'<div #container style="width:100%;height:100%;display:block;"></div>',changeDetection:i.ChangeDetectionStrategy.OnPush}]}],propDecorators:{source:[{type:i.Input}],metalColor:[{type:i.Input}],stoneColor:[{type:i.Input}],background:[{type:i.Input}],metalEnvUrl:[{type:i.Input}],gemEnvUrl:[{type:i.Input}],fov:[{type:i.Input}],shadows:[{type:i.Input}],options:[{type:i.Input}],autoRotate:[{type:i.Input}],quality:[{type:i.Input}],state:[{type:i.Input}],loaded:[{type:i.Output}],progress:[{type:i.Output}],partSelected:[{type:i.Output}],error:[{type:i.Output}],change:[{type:i.Output}],containerRef:[{type:i.ViewChild,args:["container"]}]}});const o=class o{};o.ɵfac=r.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"18.2.14",ngImport:r,type:o,deps:[],target:r.ɵɵFactoryTarget.NgModule}),o.ɵmod=r.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"18.2.14",ngImport:r,type:o,imports:[n],exports:[n]}),o.ɵinj=r.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"18.2.14",ngImport:r,type:o});let u=o;r.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"18.2.14",ngImport:r,type:u,decorators:[{type:i.NgModule,args:[{imports:[n],exports:[n]}]}]});Object.defineProperty(exports,"ALL_METAL_PRESETS",{enumerable:!0,get:()=>s.ALL_METAL_PRESETS});Object.defineProperty(exports,"ALL_STONE_PRESETS",{enumerable:!0,get:()=>s.ALL_STONE_PRESETS});Object.defineProperty(exports,"DIAMOND_PRESETS",{enumerable:!0,get:()=>s.DIAMOND_PRESETS});Object.defineProperty(exports,"GEMSTONE_PRESETS",{enumerable:!0,get:()=>s.GEMSTONE_PRESETS});Object.defineProperty(exports,"METAL_PRESETS",{enumerable:!0,get:()=>s.METAL_PRESETS});Object.defineProperty(exports,"PHYSICALLY_BASED_METAL_PRESETS",{enumerable:!0,get:()=>s.PHYSICALLY_BASED_METAL_PRESETS});Object.defineProperty(exports,"STONE_PRESETS",{enumerable:!0,get:()=>s.STONE_PRESETS});exports.ViewerComponent=n;exports.ViewerModule=u;
|
|
2
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/viewer.component.ts","../src/viewer.module.ts"],"sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n ElementRef,\n ViewChild,\n OnChanges,\n AfterViewInit,\n OnDestroy,\n SimpleChanges,\n ChangeDetectionStrategy,\n} from '@angular/core'\nimport {\n createViewer,\n type Viewer,\n type ModelSource,\n type ViewerOptions,\n type ViewerState,\n type PartInfo,\n type PartType,\n} from '@3d-viewer/core'\n\n/**\n * Angular wrapper for @3d-viewer/core.\n *\n * Usage (standalone):\n * import { ViewerComponent } from '@3d-viewer/angular'\n *\n * Usage (NgModule — for Angular 18 apps like AngularJMS):\n * import { ViewerModule } from '@3d-viewer/angular'\n *\n * @example\n * ```html\n * <td-viewer\n * [source]=\"modelSource\"\n * [metalColor]=\"'18k-yellow-gold'\"\n * (loaded)=\"onLoaded($event)\"\n * (error)=\"onError($event)\"\n * ></td-viewer>\n * ```\n */\n@Component({\n selector: 'td-viewer',\n standalone: true,\n template: `<div #container style=\"width:100%;height:100%;display:block;\"></div>`,\n styles: [`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n position: relative;\n }\n `],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ViewerComponent implements AfterViewInit, OnChanges, OnDestroy {\n\n // ── Inputs ────────────────────────────────────────────────────────────────\n\n /** The 3D model to load. Supports URL or raw ArrayBuffer/Blob. Set null to unload. */\n @Input() source: ModelSource | null = null\n\n /** Metal preset ID or hex color string. Reactive post-init. */\n @Input() metalColor?: string\n\n /** Stone preset ID or hex color string. Reactive post-init. */\n @Input() stoneColor?: string\n\n /** Background color as hex string or number. */\n @Input() background?: string | number\n\n /** Metal HDR environment URL or buffer. */\n @Input() metalEnvUrl?: string | ArrayBuffer\n\n /** Gemstone HDR environment URL or buffer. */\n @Input() gemEnvUrl?: string | ArrayBuffer\n\n /** Camera field of view. */\n @Input() fov?: number\n\n /** Enable shadow rendering. */\n @Input() shadows?: boolean\n\n /**\n * Init-time viewer options (background, fov, shadows, etc.).\n * Changes after mount are ignored — use dedicated reactive inputs instead.\n */\n @Input() options?: ViewerOptions\n\n /**\n * Reactive auto-rotation toggle. Calls startRotation() / stopRotation() on change.\n * Overrides the autoRotate flag in `options` after initialization.\n */\n @Input() autoRotate?: boolean\n\n /**\n * Reactive render quality. Calls setQuality() on change.\n * Overrides the quality flag in `options` after initialization.\n */\n @Input() quality?: 'low' | 'medium' | 'high'\n\n /**\n * Full viewer state object. When changed, calls viewer.setState() — a COMPLETE\n * replace of metalColor, stoneColor, camera, and part overrides. Not a merge.\n * Takes precedence over individual metalColor / stoneColor inputs.\n */\n @Input() state?: ViewerState\n\n // ── Outputs ───────────────────────────────────────────────────────────────\n\n /** Emits classified part list when model finishes loading. $event = PartInfo[] */\n @Output() loaded = new EventEmitter<PartInfo[]>()\n\n /** Emits loading progress 0-1. $event = number */\n @Output() progress = new EventEmitter<number>()\n\n /** Emits clicked part info. $event = { meshId: string, type: PartType } */\n @Output() partSelected = new EventEmitter<{ meshId: string; type: PartType }>()\n\n /** Emits Error when model loading fails. */\n @Output() error = new EventEmitter<Error>()\n\n /**\n * Emits full ViewerState on every metal/stone/camera change.\n * Use for persistence, undo history, or sharing a viewer URL.\n * Note: OrbitControls dragging emits state updates continuously.\n */\n @Output() change = new EventEmitter<ViewerState>()\n\n // ── Private ───────────────────────────────────────────────────────────────\n\n @ViewChild('container') private containerRef!: ElementRef<HTMLDivElement>\n\n private viewer: Viewer | null = null\n private abortCtrl: AbortController | null = null\n private initRafId: number | null = null\n\n /**\n * Source received before viewer is initialized. Applied in ngAfterViewInit.\n * Needed because ngOnChanges fires before ngAfterViewInit on first render.\n */\n private pendingSource: ModelSource | null = null\n\n // ── Public Access ─────────────────────────────────────────────────────────\n\n /** Direct access to underlying @3d-viewer/core instance (null before mount/after destroy). */\n getViewer(): Viewer | null {\n return this.viewer\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────────────────\n\n ngAfterViewInit(): void {\n // requestAnimationFrame ensures the container has real layout dimensions\n // before createViewer initializes the WebGLRenderer (matches AngularJMS pattern).\n this.initRafId = requestAnimationFrame(() => {\n this.initRafId = null\n const viewerOptions: ViewerOptions = {\n ...this.options,\n ...(this.background !== undefined && { background: this.background }),\n ...(this.fov !== undefined && { fov: this.fov }),\n ...(this.shadows !== undefined && { shadows: this.shadows }),\n ...(this.autoRotate !== undefined && { autoRotate: this.autoRotate }),\n ...(this.quality !== undefined && { quality: this.quality }),\n ...(this.metalEnvUrl !== undefined && { metalEnvUrl: this.metalEnvUrl }),\n ...(this.gemEnvUrl !== undefined && { gemEnvUrl: this.gemEnvUrl }),\n }\n this.viewer = createViewer(this.containerRef.nativeElement, viewerOptions)\n\n this.viewer.on('loaded', ({ parts }) => this.loaded.emit(parts))\n this.viewer.on('loading', ({ progress }) => this.progress.emit(progress))\n this.viewer.on('error', (err) => this.error.emit(err))\n this.viewer.on('partSelected', (info) => this.partSelected.emit(info))\n this.viewer.on('change', (state) => this.change.emit(state))\n\n // Apply initial model source if one was queued.\n if (this.pendingSource) {\n this._loadSource(this.pendingSource)\n this.pendingSource = null\n }\n\n // Precedence: full state snapshot overrides individual color inputs\n if (this.state) {\n this.viewer.setState(this.state)\n } else {\n if (this.metalColor) this.viewer.setMetalColor(this.metalColor)\n if (this.stoneColor) this.viewer.setStoneColor(this.stoneColor)\n }\n\n if (this.autoRotate !== undefined) {\n if (this.autoRotate) this.viewer.startRotation()\n else this.viewer.stopRotation()\n }\n if (this.quality) this.viewer.setQuality(this.quality)\n })\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n // Guard: viewer is null until ngAfterViewInit + rAF fires.\n if (!this.viewer) {\n if (changes['source']) {\n this.pendingSource = this.source\n }\n return\n }\n\n if (changes['source']) {\n const prev = changes['source'].previousValue as ModelSource | null | undefined\n if (!this._isSameSource(prev, this.source)) {\n this._loadSource(this.source)\n }\n }\n\n // Precedence: if 'state' changed in this cycle, setState handles everything.\n // Individual color inputs in the same cycle are ignored.\n if (changes['state'] && this.state) {\n this.viewer.setState(this.state)\n } else {\n if (changes['metalColor'] && this.metalColor) this.viewer.setMetalColor(this.metalColor)\n if (changes['stoneColor'] && this.stoneColor) this.viewer.setStoneColor(this.stoneColor)\n }\n\n if (changes['autoRotate'] && this.autoRotate !== undefined) {\n if (this.autoRotate) this.viewer.startRotation()\n else this.viewer.stopRotation()\n }\n if (changes['quality'] && this.quality) this.viewer.setQuality(this.quality)\n }\n\n ngOnDestroy(): void {\n if (this.initRafId !== null) {\n cancelAnimationFrame(this.initRafId)\n this.initRafId = null\n }\n this.abortCtrl?.abort()\n this.viewer?.dispose()\n this.viewer = null\n }\n\n // ── Helpers ───────────────────────────────────────────────────────────────\n\n private _loadSource(source: ModelSource | null): void {\n this.abortCtrl?.abort()\n if (!this.viewer) return\n\n if (!source) {\n this.viewer.unload()\n return\n }\n\n this.abortCtrl = new AbortController()\n this.viewer.load(source, { signal: this.abortCtrl.signal }).catch(() => {\n // Error is emitted via the viewer's 'error' event — no duplicate handling needed.\n })\n }\n\n private _isSameSource(a: ModelSource | null | undefined, b: ModelSource | null | undefined): boolean {\n if (a === b) return true\n if (!a || !b) return false\n if ('url' in a && 'url' in b) {\n return a.url === b.url && a.format === b.format && a.mtlUrl === b.mtlUrl\n }\n if ('data' in a && 'data' in b) {\n return a.data === b.data && a.format === b.format\n }\n return false\n }\n}\n","import { NgModule } from '@angular/core'\nimport { ViewerComponent } from './viewer.component'\n\n/**\n * Import this module in NgModule-based Angular apps (Angular 18 style, like AngularJMS).\n *\n * @example\n * ```typescript\n * import { ViewerModule } from '@3d-viewer/angular'\n *\n * @NgModule({ imports: [ViewerModule] })\n * export class YourFeatureModule {}\n * ```\n */\n@NgModule({\n imports: [ViewerComponent],\n exports: [ViewerComponent],\n})\nexport class ViewerModule {}\n"],"names":["_ViewerComponent","EventEmitter","viewerOptions","createViewer","parts","progress","err","info","state","changes","prev","_a","_b","source","a","b","i0","ViewerComponent","Component","ChangeDetectionStrategy","Input","Output","_ViewerModule","ViewerModule"],"mappings":"waAwDOA,EAAA,MAAAA,CAAA,CAKI,aAA6B,CAyD5B,KAAA,OAAA,KAgBV,KAAQ,OAAwB,IAAAC,eAEhC,KAAQ,SAA2B,IAAAA,eAMnC,KAAA,aAAA,IAAAA,eAAA,KAAA,MAAA,IAAAA,eAME,KAAO,OAAK,IAAAA,eACd,KAAA,OAAA,KAAA,KAAA,UAAA,KAIA,KAAA,UAAwB,KAOlB,KAAI,cAAK,IAA0D,CAGA,WAC1D,CACT,OAAI,KAAK,MAA6D,CAGxE,iBAAc,CAId,KAAK,UAAU,sBAAuB,IAAM,CACvC,KAAA,UAAU,KACV,MAAOC,GAGH,GAAA,KAAA,QACF,GAAA,KAAY,aAAK,QAAa,CAAA,WAAA,KAAA,YAC9B,GAAA,KAAA,MAAgB,QAAA,CAAA,IAAA,KAAA,KACvB,GAAA,KAAA,UAAA,QAAA,CAAA,QAAA,KAAA,SAGS,GAAA,KAAO,aAAA,QAAA,CAAA,WAAA,KAAA,YACT,GAAO,KAAA,UAAc,QAAK,CAAA,QAAA,KAAA,SAC1B,GAAA,KAAA,cAAA,QAAA,CAAA,YAAA,KAAA,gBACI,KAAA,YAAiB,QAAO,CAAA,UAAmB,KAAU,UAC9D,EACF,KAAA,OAAAC,EAAAA,aAAA,KAAA,aAAA,cAAAD,CAAA,EAEI,wBAAoB,CAAW,CAAA,MAAAE,CAAA,IAAA,KAAA,OAAA,KAAAA,CAAA,CAAA,EAC7B,KAAK,OAAA,GAAA,UAAiB,CAAA,CAAO,SAAAC,CAAA,IAAc,KAAA,SAAA,KAAAA,CAAA,CAAA,EAC1C,KAAA,UAAY,QAAAC,GAAa,KAAA,MAAA,KAAAA,CAAA,CAAA,EAChC,KAAA,OAAA,GAAA,eAAAC,GAAA,KAAA,aAAA,KAAAA,CAAA,CAAA,OACS,OAAS,GAAA,SAAYC,QAAgB,OAAO,KAAAA,CAAA,CAAA,EAEzD,KAAA,gBAEY,KAAA,YAA8B,KAAA,aAAA,EAE9B,KAAA,cAAQ,MAGhB,KAAA,MACA,KAAA,OAAA,SAAA,KAAA,KAAA,GAIa,KAAA,YACH,KAAA,OAAc,mBAAoB,UAAA,EACrC,KAAY,YACnB,KAAA,OAAA,cAAA,KAAA,UAAA,GAKU,KAAA,aAAiB,SACf,KAAA,WACP,KAAA,OAAA,cAAA,cAEmB,gBAGd,KAAA,SACD,KAAA,OAAY,WAAY,KAAA,OAAA,CAAc,CAAA,CAEjD,CACA,YAAYC,EAAS,CAGvB,GAAA,CAAA,KAAoB,OAAA,YAEhB,KAAA,cAA0B,KAAS,QAErC,MACA,CACA,KAAa,OAAQ,CAChB,MAASC,EAAAD,EAAA,OAAA,cAChB,KAAA,cAAAC,EAAA,KAAA,MAAA,GAAA,KAAA,YAAA,KAAA,MAAA,CAKE,GAIc,OAAO,KAAA,MACnB,KAAA,OAAA,SAAA,KAAA,KAAA,GAIUD,EAAK,YAAkB,KAAK,YAEvC,KAAA,OAAA,cAAA,KAAA,UAAA,EACHA,EAAA,YAAA,KAAA,YAEsB,KAAmC,OAA4C,cAAA,KAAA,UAAA,GAE9FA,EAAS,YAAO,KAAA,aAAA,SACjB,KAAS,WACF,KAAA,OAAU,gBAEjB,KAAU,OAAK,aAAa,GAEhCA,EAAA,SAAA,KAAA,SACO,KAAA,OAAA,WAAA,KAAA,OAAA,CACT,CACF,aAAA,SA/MW,KAAA,YAAA,OAAF,qBAAA,KAAA,SAAA,EALI,KAAA,UAKF,OAGFE,EAAA,KAAA,YAAA,MAAAA,EAAA,SARIC,EAAA,KAAA,SAAA,MAAAA,EAQF,UAGA,KAAA,OAAA,IAAR,CAGQ,YAAAC,EAAA,OAdE,IAcJF,EAAA,KAAA,YAAA,MAAAA,EAAA,QAdI,EAAA,KAAA,OAiBJ,IAAA,CAAAE,EAAA,CAjBI,KAAA,OAiBF,OAAA,EAGA,MAAF,CApBI,KAAA,UAoBF,IAAA,gBAGA,KAAA,OAAA,KAAAA,EAAA,CAAA,OAAA,KAAA,UAAA,OAAA,EAAA,MAAA,IAAA,CAvBE,CAAA,EA0BF,CAAR,cAAMC,EAAAC,EAAA,CA1BI,OAAAD,IAAAC,EAgCF,GAAF,CAAAD,GAAA,CAAAC,EAAE,GAMA,QAAAD,GAAA,QAAAC,EAAFD,EAAA,MAAAC,EAAA,KAAAD,EAAA,SAAAC,EAAA,QAAAD,EAAA,SAAAC,EAAA,OAME,SAAAD,GAAA,SAAAC,EAAFD,EAAA,OAAAC,EAAA,MAAAD,EAAA,SAAAC,EAAA,OAOE,EAAR,CAKS,EAxDCf,EAAA,KAmDFgB,EAAA,mBAAA,CAAA,WAAA,SAAA,QAAA,UAAA,SAAAA,EAAA,KAAAhB,EAAA,KAAA,CAAA,EAAA,OAAAgB,EAAA,gBAAA,SAAA,CAAA,EAKChB,EAAA,KAAAgB,EAAA,qBAAA,CAAA,WAAA,SAAA,QAAA,UAAA,KAAAhB,EAAA,aAAA,GAAA,SAAA,YAAA,OAAA,CAAA,OAAA,SAAA,WAAA,aAAA,WAAA,aAAA,WAAA,aAAA,YAAA,cAAA,UAAA,YAAA,IAAA,MAAA,QAAA,UAAA,QAAA,UAAA,WAAA,aAAA,QAAA,UAAA,MAAA,OAAA,EAAA,QAAA,CAAA,OAAA,SAAA,SAAA,WAAA,aAAA,eAAA,MAAA,QAAA,OAAA,UAAA,YAAA,CAAA,CAAA,aAAA,eAAA,MAAA,GAAA,UAAA,CAAA,WAAA,EAAA,YAAA,EAAA,CAAA,EAAA,cAAA,GAAA,SAAAgB,EAAA,SAAA,uEAAA,SAAA,GAAA,OAAA,CAAA,EAAA,EAAA,gBAAAA,EAAA,wBAAA,MAAA,CAAA,EAxDL,IAAAC,EAAAjB,EAwDGgB,EAxDG,yBAwDD,CAAA,WAAA,SAAA,QAAA,UAAA,SAAAA,EAAA,KAAAC,EAAA,WAAA,CAAA,CAGA,KAAAC,EAAAA,UAAF,KAAA,CAAA,CAAA,SAAA,YAAA,WAAA,GAAA,SAAA,uEAAA,gBAAAC,EAAAA,wBAAA,MAAA,CAAA,CAAA,CA3DG,EAAA,eA2DD,CAAA,OAAA,CAAA,CAGA,KAAAC,EAAAA,KAAA,CAAF,EAAA,WAAA,CAAA,CA9DG,KA8DDA,EAAAA,KAGA,CAAA,EAAA,WAAA,CAAA,CAAF,KAAAA,EAAAA,KAAA,CAjEG,EAAA,WAiED,CAAA,CAOA,KAAAA,EAAAA,KAAA,CAAF,EAAA,YAAA,CAAA,CAxEG,KAwEDA,EAAAA,KAIsB,CAAA,EAAA,UAAA,CAAA,CAArB,KAAAA,EAAAA,KAAW,CA5EX,EAAA,IA4EqB,CAAA,CA5ErB,KAANA,EAAAA,KAAA,CAdI,EAAA,QAAA,CAAA,CACC,KAAAA,EAAAA,KAAA,CACV,EAAY,QAAA,CAAA,CACF,KAAAA,EAAAA,KAAA,CACD,EAAA,WAAA,CAAA,CAAA,KAAAA,EAAAA,KAAA,CAAA,EAAA,QAAA,CAAA,CAAA,KAAAA,EAAAA,KAAA,CAAA,EAAA,MAAA,CAAA,CAAA,KAAAA,EAAAA,KAAA,CAAA,EAAA,OAAA,CAAA,CAOR,KAAAC,EAAAA,MAAA,YACgB,CAAA,CAClB,KAAAA,EAAAA,MAAA,CACY,EAAA,aAAA,CAAA,0HCtCA,MAAAC,EAAA,MAAAA,CAAN,CAFoB,EAFjBA,EAAA,KAAAN,EAAA,mBAAA,CAAA,WAAA,SAAA,QAAA,UAAA,SAAAA,EAAA,KAAAM,EAAA,KAAA,CAAA,EAAA,OAAAN,EAAA,gBAAA,QAAA,CAAA,EACCM,EAAC,KAAAN,EAAA,oBAAe,CAAA,WAAA,SAAA,QAAA,UAAA,SAAAA,EAAA,KAAAM,EAAA,QAAA,CAAAL,CAAA,EAAA,QAAA,CAAAA,CAAA,CAAA,CAAA,EAChBK,EAAC,KAAAN,EAAA,oBAAe,CAAA,WAAA,SAAA,QAAA,UAAA,SAAAA,EAAA,KAAAM,CAAA,CAAA,EAEd,IAAAC,EAAAD,EADZN,EACY,yBAAA,CAAA,WAAA,SAAA,QAAA,UAAA,SAAAA,EAAA,KAAAO,EAAA,WAAA,CAAA"}
|
package/dist/src/index.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export { ViewerComponent } from './viewer.component';
|
|
2
|
-
export { ViewerModule } from './viewer.module';
|
|
3
|
-
export { METAL_PRESETS, STONE_PRESETS, PHYSICALLY_BASED_METAL_PRESETS, DIAMOND_PRESETS, GEMSTONE_PRESETS, ALL_METAL_PRESETS, ALL_STONE_PRESETS, } from '@3d-viewer/core';
|
|
4
|
-
export type { MetalPreset, StonePreset } from '@3d-viewer/core';
|
|
5
|
-
export type { ModelSource, ViewerOptions, ViewerState, PartInfo, PartType, Viewer, } from '@3d-viewer/core';
|