@thinkersteps_labs/3d-viewer-react 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/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +45 -45
package/README.md
CHANGED
|
@@ -1,107 +1,107 @@
|
|
|
1
|
-
# @thinkersteps_labs/3d-viewer-react
|
|
2
|
-
|
|
3
|
-
Official React component wrapper for `@thinkersteps_labs/3d-viewer-core`. Renders photorealistic 3D jewelry viewers, swatches, and customizers in Next.js, Remix, Vite, and standard React applications.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Installation
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
pnpm add @thinkersteps_labs/3d-viewer-react @thinkersteps_labs/3d-viewer-core three
|
|
11
|
-
# or with npm
|
|
12
|
-
npm install @thinkersteps_labs/3d-viewer-react @thinkersteps_labs/3d-viewer-core three
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## 1. Turnkey Customizer (5-Line Embed)
|
|
18
|
-
|
|
19
|
-
The `<JewelryCustomizer />` provides a complete, responsive 3D canvas and luxury swatch controls out of the box:
|
|
20
|
-
|
|
21
|
-
```tsx
|
|
22
|
-
import { JewelryCustomizer } from '@thinkersteps_labs/3d-viewer-react'
|
|
23
|
-
|
|
24
|
-
export function ProductPage() {
|
|
25
|
-
return (
|
|
26
|
-
<JewelryCustomizer
|
|
27
|
-
src="https://cdn.example.com/models/solitaire-ring.glb"
|
|
28
|
-
defaultMetal="yellow-gold-18k"
|
|
29
|
-
defaultStone="diamond-d"
|
|
30
|
-
height={520}
|
|
31
|
-
autoRotate
|
|
32
|
-
onMetalChange={(metal) => console.log('Selected metal:', metal)}
|
|
33
|
-
onStoneChange={(stone) => console.log('Selected stone:', stone)}
|
|
34
|
-
/>
|
|
35
|
-
)
|
|
36
|
-
}
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
## 2. Composable Primitives (`<Viewer />` + Swatches)
|
|
42
|
-
|
|
43
|
-
Combine `<Viewer />` with pre-built `<MetalSwatches />` and `<StoneSwatches />` for custom layouts:
|
|
44
|
-
|
|
45
|
-
```tsx
|
|
46
|
-
import { useState } from 'react'
|
|
47
|
-
import {
|
|
48
|
-
Viewer,
|
|
49
|
-
MetalSwatches,
|
|
50
|
-
StoneSwatches,
|
|
51
|
-
type MetalColorProp,
|
|
52
|
-
type StoneColorProp,
|
|
53
|
-
} from '@thinkersteps_labs/3d-viewer-react'
|
|
54
|
-
|
|
55
|
-
export function Customizer() {
|
|
56
|
-
const [metal, setMetal] = useState<MetalColorProp>('yellow-gold-18k')
|
|
57
|
-
const [stone, setStone] = useState<StoneColorProp>('diamond-d')
|
|
58
|
-
|
|
59
|
-
return (
|
|
60
|
-
<div style={{ maxWidth: '840px', margin: '0 auto' }}>
|
|
61
|
-
<Viewer
|
|
62
|
-
src="https://cdn.example.com/models/solitaire-ring.glb"
|
|
63
|
-
metalColor={metal}
|
|
64
|
-
stoneColor={stone}
|
|
65
|
-
height={500}
|
|
66
|
-
autoRotate
|
|
67
|
-
/>
|
|
68
|
-
|
|
69
|
-
<div style={{ marginTop: '16px', display: 'flex', flexDirection: 'column', gap: '14px' }}>
|
|
70
|
-
<MetalSwatches value={metal} onChange={setMetal} variant="pills" />
|
|
71
|
-
<StoneSwatches value={stone} onChange={setStone} variant="pills" />
|
|
72
|
-
</div>
|
|
73
|
-
</div>
|
|
74
|
-
)
|
|
75
|
-
}
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
---
|
|
79
|
-
|
|
80
|
-
## 3. Headless Hook (`useJewelryCustomizer`)
|
|
81
|
-
|
|
82
|
-
For custom UI layouts with pre-wired state and preset lookup:
|
|
83
|
-
|
|
84
|
-
```tsx
|
|
85
|
-
import { Viewer, useJewelryCustomizer } from '@thinkersteps_labs/3d-viewer-react'
|
|
86
|
-
|
|
87
|
-
export function HeadlessCustomizer() {
|
|
88
|
-
const { metal, setMetal, stone, setStone, metalOptions, stoneOptions, viewerProps } =
|
|
89
|
-
useJewelryCustomizer({
|
|
90
|
-
defaultMetal: 'yellow-gold-18k',
|
|
91
|
-
defaultStone: 'diamond-d',
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
return (
|
|
95
|
-
<div>
|
|
96
|
-
<Viewer src="/models/ring.glb" {...viewerProps} height={480} />
|
|
97
|
-
{/* Build your bespoke buttons, dropdowns, or swatches */}
|
|
98
|
-
</div>
|
|
99
|
-
)
|
|
100
|
-
}
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
---
|
|
104
|
-
|
|
105
|
-
## License
|
|
106
|
-
|
|
107
|
-
MIT
|
|
1
|
+
# @thinkersteps_labs/3d-viewer-react
|
|
2
|
+
|
|
3
|
+
Official React component wrapper for `@thinkersteps_labs/3d-viewer-core`. Renders photorealistic 3D jewelry viewers, swatches, and customizers in Next.js, Remix, Vite, and standard React applications.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @thinkersteps_labs/3d-viewer-react @thinkersteps_labs/3d-viewer-core three
|
|
11
|
+
# or with npm
|
|
12
|
+
npm install @thinkersteps_labs/3d-viewer-react @thinkersteps_labs/3d-viewer-core three
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 1. Turnkey Customizer (5-Line Embed)
|
|
18
|
+
|
|
19
|
+
The `<JewelryCustomizer />` provides a complete, responsive 3D canvas and luxury swatch controls out of the box:
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { JewelryCustomizer } from '@thinkersteps_labs/3d-viewer-react'
|
|
23
|
+
|
|
24
|
+
export function ProductPage() {
|
|
25
|
+
return (
|
|
26
|
+
<JewelryCustomizer
|
|
27
|
+
src="https://cdn.example.com/models/solitaire-ring.glb"
|
|
28
|
+
defaultMetal="yellow-gold-18k"
|
|
29
|
+
defaultStone="diamond-d"
|
|
30
|
+
height={520}
|
|
31
|
+
autoRotate
|
|
32
|
+
onMetalChange={(metal) => console.log('Selected metal:', metal)}
|
|
33
|
+
onStoneChange={(stone) => console.log('Selected stone:', stone)}
|
|
34
|
+
/>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 2. Composable Primitives (`<Viewer />` + Swatches)
|
|
42
|
+
|
|
43
|
+
Combine `<Viewer />` with pre-built `<MetalSwatches />` and `<StoneSwatches />` for custom layouts:
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import { useState } from 'react'
|
|
47
|
+
import {
|
|
48
|
+
Viewer,
|
|
49
|
+
MetalSwatches,
|
|
50
|
+
StoneSwatches,
|
|
51
|
+
type MetalColorProp,
|
|
52
|
+
type StoneColorProp,
|
|
53
|
+
} from '@thinkersteps_labs/3d-viewer-react'
|
|
54
|
+
|
|
55
|
+
export function Customizer() {
|
|
56
|
+
const [metal, setMetal] = useState<MetalColorProp>('yellow-gold-18k')
|
|
57
|
+
const [stone, setStone] = useState<StoneColorProp>('diamond-d')
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<div style={{ maxWidth: '840px', margin: '0 auto' }}>
|
|
61
|
+
<Viewer
|
|
62
|
+
src="https://cdn.example.com/models/solitaire-ring.glb"
|
|
63
|
+
metalColor={metal}
|
|
64
|
+
stoneColor={stone}
|
|
65
|
+
height={500}
|
|
66
|
+
autoRotate
|
|
67
|
+
/>
|
|
68
|
+
|
|
69
|
+
<div style={{ marginTop: '16px', display: 'flex', flexDirection: 'column', gap: '14px' }}>
|
|
70
|
+
<MetalSwatches value={metal} onChange={setMetal} variant="pills" />
|
|
71
|
+
<StoneSwatches value={stone} onChange={setStone} variant="pills" />
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 3. Headless Hook (`useJewelryCustomizer`)
|
|
81
|
+
|
|
82
|
+
For custom UI layouts with pre-wired state and preset lookup:
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
85
|
+
import { Viewer, useJewelryCustomizer } from '@thinkersteps_labs/3d-viewer-react'
|
|
86
|
+
|
|
87
|
+
export function HeadlessCustomizer() {
|
|
88
|
+
const { metal, setMetal, stone, setStone, metalOptions, stoneOptions, viewerProps } =
|
|
89
|
+
useJewelryCustomizer({
|
|
90
|
+
defaultMetal: 'yellow-gold-18k',
|
|
91
|
+
defaultStone: 'diamond-d',
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<div>
|
|
96
|
+
<Viewer src="/models/ring.glb" {...viewerProps} height={480} />
|
|
97
|
+
{/* Build your bespoke buttons, dropdowns, or swatches */}
|
|
98
|
+
</div>
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
MIT
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/Viewer.tsx","../src/swatches/MetalSwatches.tsx","../src/swatches/StoneSwatches.tsx","../src/swatches/JewelryCustomizer.tsx","../src/swatches/useJewelryCustomizer.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\r\nimport { useRef, useEffect, forwardRef, useImperativeHandle, type CSSProperties } from 'react'\r\nimport {\r\n createViewer,\r\n normalizeModelSource,\r\n type Viewer as CoreViewer,\r\n type ModelSource,\r\n type ViewerSourceInput,\r\n type MetalColorProp,\r\n type StoneColorProp,\r\n type ViewerOptions,\r\n type ViewerState,\r\n type PartInfo,\r\n type MaterialSlotInfo,\r\n type PartType,\r\n} from '@thinkersteps_labs/3d-viewer-core'\r\n\r\nexport interface ViewerRef extends CoreViewer { }\r\n\r\nexport interface ViewerProps {\r\n /** 3D model URL or source object. Takes precedence over `source` if both provided. */\r\n src?: string\r\n /** 3D model source (URL string, ModelSource payload, or null). */\r\n source?: ViewerSourceInput\r\n /** Metal preset ID or hex code. IDE autocompletes standard presets. */\r\n metalColor?: MetalColorProp\r\n /** Stone preset ID or hex code. IDE autocompletes standard presets. */\r\n stoneColor?: StoneColorProp\r\n /** Bulk material name or slot ID color overrides. */\r\n materialColors?: Record<string, string>\r\n /** Part color overrides keyed by partId or partId:slotIndex. */\r\n partColors?: Record<string, string>\r\n background?: string | number\r\n metalEnvUrl?: string | ArrayBuffer\r\n gemEnvUrl?: string | ArrayBuffer\r\n options?: ViewerOptions\r\n fov?: number\r\n shadows?: boolean\r\n autoRotate?: boolean\r\n quality?: 'low' | 'medium' | 'high'\r\n /** Explicit container height (e.g. 520 or '520px'). Prevents zero-height collapse. */\r\n height?: number | string\r\n /** Explicit container min-height. */\r\n minHeight?: number | string\r\n /** Aspect ratio for responsive sizing (e.g. '16/9' or '4/3'). */\r\n aspectRatio?: string\r\n onLoaded?: (parts: PartInfo[], materials?: MaterialSlotInfo[]) => void\r\n onPartSelected?: (info: {\r\n meshId: string\r\n partId?: string\r\n type: PartType\r\n slotIndex?: number\r\n slotId?: string\r\n materialName?: string\r\n }) => void\r\n onChange?: (state: ViewerState) => void\r\n onError?: (err: Error) => void\r\n onProgress?: (progress: number) => void\r\n className?: string\r\n style?: CSSProperties\r\n}\r\n\r\nexport const Viewer = forwardRef<ViewerRef, ViewerProps>(function Viewer(props, ref) {\r\n const {\r\n src,\r\n source,\r\n metalColor,\r\n stoneColor,\r\n materialColors,\r\n partColors,\r\n background,\r\n metalEnvUrl,\r\n gemEnvUrl,\r\n options,\r\n fov,\r\n shadows,\r\n autoRotate,\r\n quality,\r\n height,\r\n minHeight,\r\n aspectRatio,\r\n className,\r\n style,\r\n } = props\r\n const containerRef = useRef<HTMLDivElement>(null)\r\n const viewerRef = useRef<ViewerRef | null>(null)\r\n const cb = useRef(props)\r\n cb.current = props\r\n\r\n useImperativeHandle(ref, () => viewerRef.current!, [])\r\n\r\n useEffect(() => {\r\n if (!containerRef.current) return\r\n const viewer = createViewer(containerRef.current, {\r\n ...options,\r\n ...(background !== undefined && { background }),\r\n ...(fov !== undefined && { fov }),\r\n ...(shadows !== undefined && { shadows }),\r\n ...(autoRotate !== undefined && { autoRotate }),\r\n ...(quality !== undefined && { quality }),\r\n ...(metalEnvUrl !== undefined && { metalEnvUrl }),\r\n ...(gemEnvUrl !== undefined && { gemEnvUrl }),\r\n })\r\n viewerRef.current = viewer\r\n if (import.meta.env.DEV && typeof window !== 'undefined') (window as any).__viewer = viewer\r\n if (ref) {\r\n if (typeof ref === 'function') ref(viewer)\r\n else (ref as any).current = viewer\r\n }\r\n viewer.on('loaded', ({ parts, materials }) => cb.current.onLoaded?.(parts, materials))\r\n viewer.on('partSelected', (info) => cb.current.onPartSelected?.(info))\r\n viewer.on('change', (state) => cb.current.onChange?.(state))\r\n viewer.on('error', (err) => cb.current.onError?.(err))\r\n viewer.on('loading', ({ progress }) => cb.current.onProgress?.(progress))\r\n return () => {\r\n viewer.dispose()\r\n if (ref) {\r\n if (typeof ref === 'function') ref(null)\r\n else (ref as any).current = null\r\n }\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [])\r\n\r\n useEffect(() => {\r\n if (!viewerRef.current) return\r\n const resolved = normalizeModelSource(src ?? source)\r\n if (!resolved) {\r\n viewerRef.current.unload()\r\n return\r\n }\r\n const ac = new AbortController()\r\n viewerRef.current.load(resolved, { signal: ac.signal })\r\n return () => ac.abort()\r\n }, [src, source])\r\n\r\n useEffect(() => {\r\n if (metalColor) viewerRef.current?.setMetalColor(metalColor)\r\n }, [metalColor])\r\n\r\n useEffect(() => {\r\n if (stoneColor) viewerRef.current?.setStoneColor(stoneColor)\r\n }, [stoneColor])\r\n\r\n const prevMaterialColorsRef = useRef<Record<string, string>>({})\r\n useEffect(() => {\r\n if (!viewerRef.current) return\r\n const prev = prevMaterialColorsRef.current\r\n const next = materialColors ?? {}\r\n\r\n for (const key of Object.keys(prev)) {\r\n if (!(key in next)) {\r\n viewerRef.current.clearMaterialColor(key)\r\n }\r\n }\r\n for (const [key, color] of Object.entries(next)) {\r\n if (prev[key] !== color) {\r\n viewerRef.current.setMaterialColor(key, color)\r\n }\r\n }\r\n prevMaterialColorsRef.current = { ...next }\r\n }, [materialColors])\r\n\r\n const prevPartColorsRef = useRef<Record<string, string>>({})\r\n useEffect(() => {\r\n if (!viewerRef.current) return\r\n const prev = prevPartColorsRef.current\r\n const next = partColors ?? {}\r\n\r\n for (const key of Object.keys(prev)) {\r\n if (!(key in next)) {\r\n if (key.includes(':')) {\r\n const [partId, slotIdxStr] = key.split(':')\r\n const slotIndex = parseInt(slotIdxStr ?? '', 10)\r\n viewerRef.current.clearPartColor(partId ?? '', isNaN(slotIndex) ? undefined : slotIndex)\r\n } else {\r\n viewerRef.current.clearPartColor(key)\r\n }\r\n }\r\n }\r\n for (const [key, color] of Object.entries(next)) {\r\n if (prev[key] !== color) {\r\n if (key.includes(':')) {\r\n const [partId, slotIdxStr] = key.split(':')\r\n const slotIndex = parseInt(slotIdxStr ?? '', 10)\r\n viewerRef.current.setPartColor(partId ?? '', color, isNaN(slotIndex) ? undefined : slotIndex)\r\n } else {\r\n viewerRef.current.setPartColor(key, color)\r\n }\r\n }\r\n }\r\n prevPartColorsRef.current = { ...next }\r\n }, [partColors])\r\n\r\n useEffect(() => {\r\n if (!viewerRef.current) return\r\n if (autoRotate) viewerRef.current.startRotation()\r\n else viewerRef.current.stopRotation()\r\n }, [autoRotate])\r\n\r\n useEffect(() => {\r\n if (quality) viewerRef.current?.setQuality(quality)\r\n }, [quality])\r\n\r\n const containerStyle: CSSProperties = {\r\n width: '100%',\r\n height: height !== undefined ? (typeof height === 'number' ? `${height}px` : height) : '100%',\r\n minHeight: minHeight !== undefined ? (typeof minHeight === 'number' ? `${minHeight}px` : minHeight) : undefined,\r\n aspectRatio,\r\n position: 'relative',\r\n ...style,\r\n }\r\n\r\n return (\r\n <div\r\n ref={containerRef}\r\n className={className}\r\n style={containerStyle}\r\n />\r\n )\r\n})\r\n\r\nexport default Viewer\r\n","import React, { type CSSProperties } from 'react'\r\nimport {\r\n CANONICAL_METAL_PRESETS,\r\n getMetalPreset,\r\n type MetalPreset,\r\n type MetalColorProp,\r\n} from '@thinkersteps_labs/3d-viewer-core'\r\nimport './swatches.css'\r\n\r\nexport interface MetalSwatchesProps {\r\n value?: MetalColorProp\r\n onChange?: (metalId: string, preset?: MetalPreset) => void\r\n options?: MetalPreset[]\r\n category?: 'all' | 'gold' | 'platinum-silver' | 'alternative'\r\n variant?: 'pills' | 'dots'\r\n showLabel?: boolean\r\n className?: string\r\n style?: CSSProperties\r\n}\r\n\r\nexport function MetalSwatches({\r\n value,\r\n onChange,\r\n options = CANONICAL_METAL_PRESETS,\r\n category = 'all',\r\n variant = 'pills',\r\n showLabel = true,\r\n className = '',\r\n style,\r\n}: MetalSwatchesProps) {\r\n const filteredOptions = category === 'all'\r\n ? options\r\n : options.filter((m) => m.category === category)\r\n\r\n const activePreset = value ? getMetalPreset(value) : undefined\r\n const activeId = activePreset?.id ?? value\r\n\r\n return (\r\n <div className={`td-swatch-group ${className}`} style={style}>\r\n {showLabel && (\r\n <div className=\"td-swatch-header\">\r\n <span className=\"td-swatch-title\">Metal</span>\r\n {activePreset && (\r\n <span className=\"td-swatch-selected-name\">{activePreset.label}</span>\r\n )}\r\n </div>\r\n )}\r\n <div className=\"td-swatch-row\" role=\"radiogroup\" aria-label=\"Metal Selection\">\r\n {filteredOptions.map((m) => {\r\n const isSelected = activeId === m.id || value === m.hex\r\n return (\r\n <button\r\n key={m.id}\r\n type=\"button\"\r\n role=\"radio\"\r\n aria-checked={isSelected}\r\n title={m.label}\r\n className={`td-swatch-${variant === 'dots' ? 'dot' : 'pill'} ${isSelected ? 'active' : ''}`}\r\n onClick={() => onChange?.(m.id, m)}\r\n >\r\n <span\r\n className=\"td-swatch-color-circle\"\r\n style={{ backgroundColor: m.hex }}\r\n />\r\n {variant === 'pills' && <span>{m.label}</span>}\r\n </button>\r\n )\r\n })}\r\n </div>\r\n </div>\r\n )\r\n}\r\n\r\nexport interface MetalSelectProps {\r\n value?: MetalColorProp\r\n onChange?: (metalId: string, preset?: MetalPreset) => void\r\n options?: MetalPreset[]\r\n label?: string\r\n className?: string\r\n style?: CSSProperties\r\n}\r\n\r\nexport function MetalSelect({\r\n value,\r\n onChange,\r\n options = CANONICAL_METAL_PRESETS,\r\n label = 'Select Metal',\r\n className = '',\r\n style,\r\n}: MetalSelectProps) {\r\n const activePreset = value ? getMetalPreset(value) : undefined\r\n const activeValue = activePreset?.id ?? value ?? options[0]?.id\r\n\r\n return (\r\n <div className={`td-select-wrapper ${className}`} style={style}>\r\n {label && <label className=\"td-swatch-title\">{label}</label>}\r\n <select\r\n className=\"td-select\"\r\n value={activeValue}\r\n onChange={(e) => {\r\n const val = e.target.value\r\n const preset = getMetalPreset(val)\r\n onChange?.(val, preset)\r\n }}\r\n >\r\n {options.map((m) => (\r\n <option key={m.id} value={m.id}>\r\n {m.label}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n )\r\n}\r\n","import React, { type CSSProperties } from 'react'\r\nimport {\r\n CANONICAL_STONE_PRESETS,\r\n getStonePreset,\r\n type StonePreset,\r\n type StoneColorProp,\r\n} from '@thinkersteps_labs/3d-viewer-core'\r\nimport './swatches.css'\r\n\r\nexport interface StoneSwatchesProps {\r\n value?: StoneColorProp\r\n onChange?: (stoneId: string, preset?: StonePreset) => void\r\n options?: StonePreset[]\r\n category?: 'all' | 'diamond' | 'gemstone'\r\n variant?: 'pills' | 'dots'\r\n showLabel?: boolean\r\n className?: string\r\n style?: CSSProperties\r\n}\r\n\r\nexport function StoneSwatches({\r\n value,\r\n onChange,\r\n options = CANONICAL_STONE_PRESETS,\r\n category = 'all',\r\n variant = 'pills',\r\n showLabel = true,\r\n className = '',\r\n style,\r\n}: StoneSwatchesProps) {\r\n const filteredOptions = category === 'all'\r\n ? options\r\n : options.filter((s) => s.category === category)\r\n\r\n const activePreset = value ? getStonePreset(value) : undefined\r\n const activeId = activePreset?.id ?? value\r\n\r\n return (\r\n <div className={`td-swatch-group ${className}`} style={style}>\r\n {showLabel && (\r\n <div className=\"td-swatch-header\">\r\n <span className=\"td-swatch-title\">Gemstone</span>\r\n {activePreset && (\r\n <span className=\"td-swatch-selected-name\">\r\n {activePreset.label}\r\n {activePreset.grade ? ` (${activePreset.grade})` : ''}\r\n </span>\r\n )}\r\n </div>\r\n )}\r\n <div className=\"td-swatch-row\" role=\"radiogroup\" aria-label=\"Gemstone Selection\">\r\n {filteredOptions.map((s) => {\r\n const isSelected = activeId === s.id || value === s.hex\r\n return (\r\n <button\r\n key={s.id}\r\n type=\"button\"\r\n role=\"radio\"\r\n aria-checked={isSelected}\r\n title={`${s.label}${s.grade ? ` - ${s.grade}` : ''}`}\r\n className={`td-swatch-${variant === 'dots' ? 'dot' : 'pill'} ${isSelected ? 'active' : ''}`}\r\n onClick={() => onChange?.(s.id, s)}\r\n >\r\n <span\r\n className=\"td-swatch-color-circle\"\r\n style={{ backgroundColor: s.hex }}\r\n />\r\n {variant === 'pills' && <span>{s.label}</span>}\r\n </button>\r\n )\r\n })}\r\n </div>\r\n </div>\r\n )\r\n}\r\n\r\nexport interface StoneSelectProps {\r\n value?: StoneColorProp\r\n onChange?: (stoneId: string, preset?: StonePreset) => void\r\n options?: StonePreset[]\r\n label?: string\r\n className?: string\r\n style?: CSSProperties\r\n}\r\n\r\nexport function StoneSelect({\r\n value,\r\n onChange,\r\n options = CANONICAL_STONE_PRESETS,\r\n label = 'Select Gemstone',\r\n className = '',\r\n style,\r\n}: StoneSelectProps) {\r\n const activePreset = value ? getStonePreset(value) : undefined\r\n const activeValue = activePreset?.id ?? value ?? options[0]?.id\r\n\r\n return (\r\n <div className={`td-select-wrapper ${className}`} style={style}>\r\n {label && <label className=\"td-swatch-title\">{label}</label>}\r\n <select\r\n className=\"td-select\"\r\n value={activeValue}\r\n onChange={(e) => {\r\n const val = e.target.value\r\n const preset = getStonePreset(val)\r\n onChange?.(val, preset)\r\n }}\r\n >\r\n {options.map((s) => (\r\n <option key={s.id} value={s.id}>\r\n {s.label} {s.grade ? `(${s.grade})` : ''}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n )\r\n}\r\n","import React, { useState, type CSSProperties } from 'react'\r\nimport {\r\n type MetalColorProp,\r\n type StoneColorProp,\r\n type ViewerSourceInput,\r\n type MetalPreset,\r\n type StonePreset,\r\n type PartInfo,\r\n type PartType,\r\n} from '@thinkersteps_labs/3d-viewer-core'\r\nimport { Viewer, type ViewerRef } from '../Viewer'\r\nimport { MetalSwatches, MetalSelect } from './MetalSwatches'\r\nimport { StoneSwatches, StoneSelect } from './StoneSwatches'\r\nimport './swatches.css'\r\n\r\nexport interface JewelryCustomizerProps {\r\n src?: string\r\n source?: ViewerSourceInput\r\n defaultMetal?: MetalColorProp\r\n defaultStone?: StoneColorProp\r\n metal?: MetalColorProp\r\n onMetalChange?: (metal: string, preset?: MetalPreset) => void\r\n stone?: StoneColorProp\r\n onStoneChange?: (stone: string, preset?: StonePreset) => void\r\n metalOptions?: MetalPreset[]\r\n stoneOptions?: StonePreset[]\r\n controlsVariant?: 'pills' | 'dots' | 'select' | 'none'\r\n height?: number | string\r\n autoRotate?: boolean\r\n quality?: 'low' | 'medium' | 'high'\r\n fov?: number\r\n shadows?: boolean\r\n onLoaded?: (parts: PartInfo[]) => void\r\n onPartSelected?: (info: { meshId: string; type: PartType }) => void\r\n className?: string\r\n style?: CSSProperties\r\n viewerRef?: React.Ref<ViewerRef>\r\n}\r\n\r\nexport function JewelryCustomizer({\r\n src,\r\n source,\r\n defaultMetal = 'yellow-gold-18k',\r\n defaultStone = 'diamond-d',\r\n metal: controlledMetal,\r\n onMetalChange,\r\n stone: controlledStone,\r\n onStoneChange,\r\n metalOptions,\r\n stoneOptions,\r\n controlsVariant = 'pills',\r\n height = 520,\r\n autoRotate = true,\r\n quality = 'high',\r\n fov,\r\n shadows,\r\n onLoaded,\r\n onPartSelected,\r\n className = '',\r\n style,\r\n viewerRef,\r\n}: JewelryCustomizerProps) {\r\n const [internalMetal, setInternalMetal] = useState<MetalColorProp>(defaultMetal)\r\n const [internalStone, setInternalStone] = useState<StoneColorProp>(defaultStone)\r\n\r\n const currentMetal = controlledMetal !== undefined ? controlledMetal : internalMetal\r\n const currentStone = controlledStone !== undefined ? controlledStone : internalStone\r\n\r\n const handleMetalChange = (val: string, preset?: MetalPreset) => {\r\n if (controlledMetal === undefined) setInternalMetal(val)\r\n onMetalChange?.(val, preset)\r\n }\r\n\r\n const handleStoneChange = (val: string, preset?: StonePreset) => {\r\n if (controlledStone === undefined) setInternalStone(val)\r\n onStoneChange?.(val, preset)\r\n }\r\n\r\n const viewportHeight = typeof height === 'number' ? `${height}px` : height\r\n\r\n return (\r\n <div className={`td-customizer-card ${className}`} style={style}>\r\n <div className=\"td-customizer-viewport\" style={{ height: viewportHeight }}>\r\n <Viewer\r\n ref={viewerRef}\r\n src={src}\r\n source={source}\r\n metalColor={currentMetal}\r\n stoneColor={currentStone}\r\n autoRotate={autoRotate}\r\n quality={quality}\r\n fov={fov}\r\n shadows={shadows}\r\n onLoaded={onLoaded}\r\n onPartSelected={onPartSelected}\r\n />\r\n </div>\r\n\r\n {controlsVariant !== 'none' && (\r\n <div className=\"td-customizer-controls\">\r\n {controlsVariant === 'select' ? (\r\n <>\r\n <MetalSelect\r\n value={currentMetal}\r\n onChange={handleMetalChange}\r\n options={metalOptions}\r\n />\r\n <StoneSelect\r\n value={currentStone}\r\n onChange={handleStoneChange}\r\n options={stoneOptions}\r\n />\r\n </>\r\n ) : (\r\n <>\r\n <MetalSwatches\r\n value={currentMetal}\r\n onChange={handleMetalChange}\r\n options={metalOptions}\r\n variant={controlsVariant}\r\n />\r\n <StoneSwatches\r\n value={currentStone}\r\n onChange={handleStoneChange}\r\n options={stoneOptions}\r\n variant={controlsVariant}\r\n />\r\n </>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n","import { useState, useMemo } from 'react'\r\nimport {\r\n CANONICAL_METAL_PRESETS,\r\n CANONICAL_STONE_PRESETS,\r\n getMetalPreset,\r\n getStonePreset,\r\n type MetalColorProp,\r\n type StoneColorProp,\r\n type MetalPreset,\r\n type StonePreset,\r\n} from '@thinkersteps_labs/3d-viewer-core'\r\n\r\nexport interface UseJewelryCustomizerOptions {\r\n defaultMetal?: MetalColorProp\r\n defaultStone?: StoneColorProp\r\n metalOptions?: MetalPreset[]\r\n stoneOptions?: StonePreset[]\r\n}\r\n\r\nexport interface UseJewelryCustomizerReturn {\r\n metal: MetalColorProp\r\n setMetal: (val: MetalColorProp) => void\r\n stone: StoneColorProp\r\n setStone: (val: StoneColorProp) => void\r\n metalPreset?: MetalPreset\r\n stonePreset?: StonePreset\r\n metalOptions: MetalPreset[]\r\n stoneOptions: StonePreset[]\r\n viewerProps: {\r\n metalColor: MetalColorProp\r\n stoneColor: StoneColorProp\r\n }\r\n}\r\n\r\nexport function useJewelryCustomizer(\r\n options: UseJewelryCustomizerOptions = {}\r\n): UseJewelryCustomizerReturn {\r\n const {\r\n defaultMetal = 'yellow-gold-18k',\r\n defaultStone = 'diamond-d',\r\n metalOptions = CANONICAL_METAL_PRESETS,\r\n stoneOptions = CANONICAL_STONE_PRESETS,\r\n } = options\r\n\r\n const [metal, setMetal] = useState<MetalColorProp>(defaultMetal)\r\n const [stone, setStone] = useState<StoneColorProp>(defaultStone)\r\n\r\n const metalPreset = useMemo(() => getMetalPreset(metal), [metal])\r\n const stonePreset = useMemo(() => getStonePreset(stone), [stone])\r\n\r\n const viewerProps = useMemo(\r\n () => ({\r\n metalColor: metal,\r\n stoneColor: stone,\r\n }),\r\n [metal, stone]\r\n )\r\n\r\n return {\r\n metal,\r\n setMetal,\r\n stone,\r\n setStone,\r\n metalPreset,\r\n stonePreset,\r\n metalOptions,\r\n stoneOptions,\r\n viewerProps,\r\n }\r\n}\r\n"],"names":["Viewer","forwardRef","props","ref","src","source","metalColor","stoneColor","materialColors","partColors","background","metalEnvUrl","gemEnvUrl","options","fov","shadows","autoRotate","quality","height","minHeight","aspectRatio","className","style","containerRef","useRef","viewerRef","cb","useImperativeHandle","useEffect","viewer","createViewer","parts","materials","_b","_a","info","state","err","progress","resolved","normalizeModelSource","ac","prevMaterialColorsRef","prev","next","key","color","prevPartColorsRef","partId","slotIdxStr","slotIndex","containerStyle","jsx","MetalSwatches","value","onChange","CANONICAL_METAL_PRESETS","category","variant","showLabel","filteredOptions","m","activePreset","getMetalPreset","activeId","jsxs","isSelected","MetalSelect","label","activeValue","e","val","preset","StoneSwatches","CANONICAL_STONE_PRESETS","s","getStonePreset","StoneSelect","JewelryCustomizer","defaultMetal","defaultStone","controlledMetal","onMetalChange","controlledStone","onStoneChange","metalOptions","stoneOptions","controlsVariant","onLoaded","onPartSelected","internalMetal","setInternalMetal","useState","internalStone","setInternalStone","currentMetal","currentStone","handleMetalChange","handleStoneChange","viewportHeight","Fragment","useJewelryCustomizer","metal","setMetal","stone","setStone","metalPreset","useMemo","stonePreset","viewerProps"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/Viewer.tsx","../src/swatches/MetalSwatches.tsx","../src/swatches/StoneSwatches.tsx","../src/swatches/JewelryCustomizer.tsx","../src/swatches/useJewelryCustomizer.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\nimport { useRef, useEffect, forwardRef, useImperativeHandle, type CSSProperties } from 'react'\nimport {\n createViewer,\n normalizeModelSource,\n type Viewer as CoreViewer,\n type ModelSource,\n type ViewerSourceInput,\n type MetalColorProp,\n type StoneColorProp,\n type ViewerOptions,\n type ViewerState,\n type PartInfo,\n type MaterialSlotInfo,\n type PartType,\n} from '@thinkersteps_labs/3d-viewer-core'\n\nexport interface ViewerRef extends CoreViewer { }\n\nexport interface ViewerProps {\n /** 3D model URL or source object. Takes precedence over `source` if both provided. */\n src?: string\n /** 3D model source (URL string, ModelSource payload, or null). */\n source?: ViewerSourceInput\n /** Metal preset ID or hex code. IDE autocompletes standard presets. */\n metalColor?: MetalColorProp\n /** Stone preset ID or hex code. IDE autocompletes standard presets. */\n stoneColor?: StoneColorProp\n /** Bulk material name or slot ID color overrides. */\n materialColors?: Record<string, string>\n /** Part color overrides keyed by partId or partId:slotIndex. */\n partColors?: Record<string, string>\n background?: string | number\n metalEnvUrl?: string | ArrayBuffer\n gemEnvUrl?: string | ArrayBuffer\n options?: ViewerOptions\n fov?: number\n shadows?: boolean\n autoRotate?: boolean\n quality?: 'low' | 'medium' | 'high'\n /** Explicit container height (e.g. 520 or '520px'). Prevents zero-height collapse. */\n height?: number | string\n /** Explicit container min-height. */\n minHeight?: number | string\n /** Aspect ratio for responsive sizing (e.g. '16/9' or '4/3'). */\n aspectRatio?: string\n onLoaded?: (parts: PartInfo[], materials?: MaterialSlotInfo[]) => void\n onPartSelected?: (info: {\n meshId: string\n partId?: string\n type: PartType\n slotIndex?: number\n slotId?: string\n materialName?: string\n }) => void\n onChange?: (state: ViewerState) => void\n onError?: (err: Error) => void\n onProgress?: (progress: number) => void\n className?: string\n style?: CSSProperties\n}\n\nexport const Viewer = forwardRef<ViewerRef, ViewerProps>(function Viewer(props, ref) {\n const {\n src,\n source,\n metalColor,\n stoneColor,\n materialColors,\n partColors,\n background,\n metalEnvUrl,\n gemEnvUrl,\n options,\n fov,\n shadows,\n autoRotate,\n quality,\n height,\n minHeight,\n aspectRatio,\n className,\n style,\n } = props\n const containerRef = useRef<HTMLDivElement>(null)\n const viewerRef = useRef<ViewerRef | null>(null)\n const cb = useRef(props)\n cb.current = props\n\n useImperativeHandle(ref, () => viewerRef.current!, [])\n\n useEffect(() => {\n if (!containerRef.current) return\n const viewer = createViewer(containerRef.current, {\n ...options,\n ...(background !== undefined && { background }),\n ...(fov !== undefined && { fov }),\n ...(shadows !== undefined && { shadows }),\n ...(autoRotate !== undefined && { autoRotate }),\n ...(quality !== undefined && { quality }),\n ...(metalEnvUrl !== undefined && { metalEnvUrl }),\n ...(gemEnvUrl !== undefined && { gemEnvUrl }),\n })\n viewerRef.current = viewer\n if (import.meta.env.DEV && typeof window !== 'undefined') (window as any).__viewer = viewer\n if (ref) {\n if (typeof ref === 'function') ref(viewer)\n else (ref as any).current = viewer\n }\n viewer.on('loaded', ({ parts, materials }) => cb.current.onLoaded?.(parts, materials))\n viewer.on('partSelected', (info) => cb.current.onPartSelected?.(info))\n viewer.on('change', (state) => cb.current.onChange?.(state))\n viewer.on('error', (err) => cb.current.onError?.(err))\n viewer.on('loading', ({ progress }) => cb.current.onProgress?.(progress))\n return () => {\n viewer.dispose()\n if (ref) {\n if (typeof ref === 'function') ref(null)\n else (ref as any).current = null\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n useEffect(() => {\n if (!viewerRef.current) return\n const resolved = normalizeModelSource(src ?? source)\n if (!resolved) {\n viewerRef.current.unload()\n return\n }\n const ac = new AbortController()\n viewerRef.current.load(resolved, { signal: ac.signal })\n return () => ac.abort()\n }, [src, source])\n\n useEffect(() => {\n if (metalColor) viewerRef.current?.setMetalColor(metalColor)\n }, [metalColor])\n\n useEffect(() => {\n if (stoneColor) viewerRef.current?.setStoneColor(stoneColor)\n }, [stoneColor])\n\n const prevMaterialColorsRef = useRef<Record<string, string>>({})\n useEffect(() => {\n if (!viewerRef.current) return\n const prev = prevMaterialColorsRef.current\n const next = materialColors ?? {}\n\n for (const key of Object.keys(prev)) {\n if (!(key in next)) {\n viewerRef.current.clearMaterialColor(key)\n }\n }\n for (const [key, color] of Object.entries(next)) {\n if (prev[key] !== color) {\n viewerRef.current.setMaterialColor(key, color)\n }\n }\n prevMaterialColorsRef.current = { ...next }\n }, [materialColors])\n\n const prevPartColorsRef = useRef<Record<string, string>>({})\n useEffect(() => {\n if (!viewerRef.current) return\n const prev = prevPartColorsRef.current\n const next = partColors ?? {}\n\n for (const key of Object.keys(prev)) {\n if (!(key in next)) {\n if (key.includes(':')) {\n const [partId, slotIdxStr] = key.split(':')\n const slotIndex = parseInt(slotIdxStr ?? '', 10)\n viewerRef.current.clearPartColor(partId ?? '', isNaN(slotIndex) ? undefined : slotIndex)\n } else {\n viewerRef.current.clearPartColor(key)\n }\n }\n }\n for (const [key, color] of Object.entries(next)) {\n if (prev[key] !== color) {\n if (key.includes(':')) {\n const [partId, slotIdxStr] = key.split(':')\n const slotIndex = parseInt(slotIdxStr ?? '', 10)\n viewerRef.current.setPartColor(partId ?? '', color, isNaN(slotIndex) ? undefined : slotIndex)\n } else {\n viewerRef.current.setPartColor(key, color)\n }\n }\n }\n prevPartColorsRef.current = { ...next }\n }, [partColors])\n\n useEffect(() => {\n if (!viewerRef.current) return\n if (autoRotate) viewerRef.current.startRotation()\n else viewerRef.current.stopRotation()\n }, [autoRotate])\n\n useEffect(() => {\n if (quality) viewerRef.current?.setQuality(quality)\n }, [quality])\n\n const containerStyle: CSSProperties = {\n width: '100%',\n height: height !== undefined ? (typeof height === 'number' ? `${height}px` : height) : '100%',\n minHeight: minHeight !== undefined ? (typeof minHeight === 'number' ? `${minHeight}px` : minHeight) : undefined,\n aspectRatio,\n position: 'relative',\n ...style,\n }\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={containerStyle}\n />\n )\n})\n\nexport default Viewer\n","import React, { type CSSProperties } from 'react'\nimport {\n CANONICAL_METAL_PRESETS,\n getMetalPreset,\n type MetalPreset,\n type MetalColorProp,\n} from '@thinkersteps_labs/3d-viewer-core'\nimport './swatches.css'\n\nexport interface MetalSwatchesProps {\n value?: MetalColorProp\n onChange?: (metalId: string, preset?: MetalPreset) => void\n options?: MetalPreset[]\n category?: 'all' | 'gold' | 'platinum-silver' | 'alternative'\n variant?: 'pills' | 'dots'\n showLabel?: boolean\n className?: string\n style?: CSSProperties\n}\n\nexport function MetalSwatches({\n value,\n onChange,\n options = CANONICAL_METAL_PRESETS,\n category = 'all',\n variant = 'pills',\n showLabel = true,\n className = '',\n style,\n}: MetalSwatchesProps) {\n const filteredOptions = category === 'all'\n ? options\n : options.filter((m) => m.category === category)\n\n const activePreset = value ? getMetalPreset(value) : undefined\n const activeId = activePreset?.id ?? value\n\n return (\n <div className={`td-swatch-group ${className}`} style={style}>\n {showLabel && (\n <div className=\"td-swatch-header\">\n <span className=\"td-swatch-title\">Metal</span>\n {activePreset && (\n <span className=\"td-swatch-selected-name\">{activePreset.label}</span>\n )}\n </div>\n )}\n <div className=\"td-swatch-row\" role=\"radiogroup\" aria-label=\"Metal Selection\">\n {filteredOptions.map((m) => {\n const isSelected = activeId === m.id || value === m.hex\n return (\n <button\n key={m.id}\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n title={m.label}\n className={`td-swatch-${variant === 'dots' ? 'dot' : 'pill'} ${isSelected ? 'active' : ''}`}\n onClick={() => onChange?.(m.id, m)}\n >\n <span\n className=\"td-swatch-color-circle\"\n style={{ backgroundColor: m.hex }}\n />\n {variant === 'pills' && <span>{m.label}</span>}\n </button>\n )\n })}\n </div>\n </div>\n )\n}\n\nexport interface MetalSelectProps {\n value?: MetalColorProp\n onChange?: (metalId: string, preset?: MetalPreset) => void\n options?: MetalPreset[]\n label?: string\n className?: string\n style?: CSSProperties\n}\n\nexport function MetalSelect({\n value,\n onChange,\n options = CANONICAL_METAL_PRESETS,\n label = 'Select Metal',\n className = '',\n style,\n}: MetalSelectProps) {\n const activePreset = value ? getMetalPreset(value) : undefined\n const activeValue = activePreset?.id ?? value ?? options[0]?.id\n\n return (\n <div className={`td-select-wrapper ${className}`} style={style}>\n {label && <label className=\"td-swatch-title\">{label}</label>}\n <select\n className=\"td-select\"\n value={activeValue}\n onChange={(e) => {\n const val = e.target.value\n const preset = getMetalPreset(val)\n onChange?.(val, preset)\n }}\n >\n {options.map((m) => (\n <option key={m.id} value={m.id}>\n {m.label}\n </option>\n ))}\n </select>\n </div>\n )\n}\n","import React, { type CSSProperties } from 'react'\nimport {\n CANONICAL_STONE_PRESETS,\n getStonePreset,\n type StonePreset,\n type StoneColorProp,\n} from '@thinkersteps_labs/3d-viewer-core'\nimport './swatches.css'\n\nexport interface StoneSwatchesProps {\n value?: StoneColorProp\n onChange?: (stoneId: string, preset?: StonePreset) => void\n options?: StonePreset[]\n category?: 'all' | 'diamond' | 'gemstone'\n variant?: 'pills' | 'dots'\n showLabel?: boolean\n className?: string\n style?: CSSProperties\n}\n\nexport function StoneSwatches({\n value,\n onChange,\n options = CANONICAL_STONE_PRESETS,\n category = 'all',\n variant = 'pills',\n showLabel = true,\n className = '',\n style,\n}: StoneSwatchesProps) {\n const filteredOptions = category === 'all'\n ? options\n : options.filter((s) => s.category === category)\n\n const activePreset = value ? getStonePreset(value) : undefined\n const activeId = activePreset?.id ?? value\n\n return (\n <div className={`td-swatch-group ${className}`} style={style}>\n {showLabel && (\n <div className=\"td-swatch-header\">\n <span className=\"td-swatch-title\">Gemstone</span>\n {activePreset && (\n <span className=\"td-swatch-selected-name\">\n {activePreset.label}\n {activePreset.grade ? ` (${activePreset.grade})` : ''}\n </span>\n )}\n </div>\n )}\n <div className=\"td-swatch-row\" role=\"radiogroup\" aria-label=\"Gemstone Selection\">\n {filteredOptions.map((s) => {\n const isSelected = activeId === s.id || value === s.hex\n return (\n <button\n key={s.id}\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n title={`${s.label}${s.grade ? ` - ${s.grade}` : ''}`}\n className={`td-swatch-${variant === 'dots' ? 'dot' : 'pill'} ${isSelected ? 'active' : ''}`}\n onClick={() => onChange?.(s.id, s)}\n >\n <span\n className=\"td-swatch-color-circle\"\n style={{ backgroundColor: s.hex }}\n />\n {variant === 'pills' && <span>{s.label}</span>}\n </button>\n )\n })}\n </div>\n </div>\n )\n}\n\nexport interface StoneSelectProps {\n value?: StoneColorProp\n onChange?: (stoneId: string, preset?: StonePreset) => void\n options?: StonePreset[]\n label?: string\n className?: string\n style?: CSSProperties\n}\n\nexport function StoneSelect({\n value,\n onChange,\n options = CANONICAL_STONE_PRESETS,\n label = 'Select Gemstone',\n className = '',\n style,\n}: StoneSelectProps) {\n const activePreset = value ? getStonePreset(value) : undefined\n const activeValue = activePreset?.id ?? value ?? options[0]?.id\n\n return (\n <div className={`td-select-wrapper ${className}`} style={style}>\n {label && <label className=\"td-swatch-title\">{label}</label>}\n <select\n className=\"td-select\"\n value={activeValue}\n onChange={(e) => {\n const val = e.target.value\n const preset = getStonePreset(val)\n onChange?.(val, preset)\n }}\n >\n {options.map((s) => (\n <option key={s.id} value={s.id}>\n {s.label} {s.grade ? `(${s.grade})` : ''}\n </option>\n ))}\n </select>\n </div>\n )\n}\n","import React, { useState, type CSSProperties } from 'react'\nimport {\n type MetalColorProp,\n type StoneColorProp,\n type ViewerSourceInput,\n type MetalPreset,\n type StonePreset,\n type PartInfo,\n type PartType,\n} from '@thinkersteps_labs/3d-viewer-core'\nimport { Viewer, type ViewerRef } from '../Viewer'\nimport { MetalSwatches, MetalSelect } from './MetalSwatches'\nimport { StoneSwatches, StoneSelect } from './StoneSwatches'\nimport './swatches.css'\n\nexport interface JewelryCustomizerProps {\n src?: string\n source?: ViewerSourceInput\n defaultMetal?: MetalColorProp\n defaultStone?: StoneColorProp\n metal?: MetalColorProp\n onMetalChange?: (metal: string, preset?: MetalPreset) => void\n stone?: StoneColorProp\n onStoneChange?: (stone: string, preset?: StonePreset) => void\n metalOptions?: MetalPreset[]\n stoneOptions?: StonePreset[]\n controlsVariant?: 'pills' | 'dots' | 'select' | 'none'\n height?: number | string\n autoRotate?: boolean\n quality?: 'low' | 'medium' | 'high'\n fov?: number\n shadows?: boolean\n onLoaded?: (parts: PartInfo[]) => void\n onPartSelected?: (info: { meshId: string; type: PartType }) => void\n className?: string\n style?: CSSProperties\n viewerRef?: React.Ref<ViewerRef>\n}\n\nexport function JewelryCustomizer({\n src,\n source,\n defaultMetal = 'yellow-gold-18k',\n defaultStone = 'diamond-d',\n metal: controlledMetal,\n onMetalChange,\n stone: controlledStone,\n onStoneChange,\n metalOptions,\n stoneOptions,\n controlsVariant = 'pills',\n height = 520,\n autoRotate = true,\n quality = 'high',\n fov,\n shadows,\n onLoaded,\n onPartSelected,\n className = '',\n style,\n viewerRef,\n}: JewelryCustomizerProps) {\n const [internalMetal, setInternalMetal] = useState<MetalColorProp>(defaultMetal)\n const [internalStone, setInternalStone] = useState<StoneColorProp>(defaultStone)\n\n const currentMetal = controlledMetal !== undefined ? controlledMetal : internalMetal\n const currentStone = controlledStone !== undefined ? controlledStone : internalStone\n\n const handleMetalChange = (val: string, preset?: MetalPreset) => {\n if (controlledMetal === undefined) setInternalMetal(val)\n onMetalChange?.(val, preset)\n }\n\n const handleStoneChange = (val: string, preset?: StonePreset) => {\n if (controlledStone === undefined) setInternalStone(val)\n onStoneChange?.(val, preset)\n }\n\n const viewportHeight = typeof height === 'number' ? `${height}px` : height\n\n return (\n <div className={`td-customizer-card ${className}`} style={style}>\n <div className=\"td-customizer-viewport\" style={{ height: viewportHeight }}>\n <Viewer\n ref={viewerRef}\n src={src}\n source={source}\n metalColor={currentMetal}\n stoneColor={currentStone}\n autoRotate={autoRotate}\n quality={quality}\n fov={fov}\n shadows={shadows}\n onLoaded={onLoaded}\n onPartSelected={onPartSelected}\n />\n </div>\n\n {controlsVariant !== 'none' && (\n <div className=\"td-customizer-controls\">\n {controlsVariant === 'select' ? (\n <>\n <MetalSelect\n value={currentMetal}\n onChange={handleMetalChange}\n options={metalOptions}\n />\n <StoneSelect\n value={currentStone}\n onChange={handleStoneChange}\n options={stoneOptions}\n />\n </>\n ) : (\n <>\n <MetalSwatches\n value={currentMetal}\n onChange={handleMetalChange}\n options={metalOptions}\n variant={controlsVariant}\n />\n <StoneSwatches\n value={currentStone}\n onChange={handleStoneChange}\n options={stoneOptions}\n variant={controlsVariant}\n />\n </>\n )}\n </div>\n )}\n </div>\n )\n}\n","import { useState, useMemo } from 'react'\nimport {\n CANONICAL_METAL_PRESETS,\n CANONICAL_STONE_PRESETS,\n getMetalPreset,\n getStonePreset,\n type MetalColorProp,\n type StoneColorProp,\n type MetalPreset,\n type StonePreset,\n} from '@thinkersteps_labs/3d-viewer-core'\n\nexport interface UseJewelryCustomizerOptions {\n defaultMetal?: MetalColorProp\n defaultStone?: StoneColorProp\n metalOptions?: MetalPreset[]\n stoneOptions?: StonePreset[]\n}\n\nexport interface UseJewelryCustomizerReturn {\n metal: MetalColorProp\n setMetal: (val: MetalColorProp) => void\n stone: StoneColorProp\n setStone: (val: StoneColorProp) => void\n metalPreset?: MetalPreset\n stonePreset?: StonePreset\n metalOptions: MetalPreset[]\n stoneOptions: StonePreset[]\n viewerProps: {\n metalColor: MetalColorProp\n stoneColor: StoneColorProp\n }\n}\n\nexport function useJewelryCustomizer(\n options: UseJewelryCustomizerOptions = {}\n): UseJewelryCustomizerReturn {\n const {\n defaultMetal = 'yellow-gold-18k',\n defaultStone = 'diamond-d',\n metalOptions = CANONICAL_METAL_PRESETS,\n stoneOptions = CANONICAL_STONE_PRESETS,\n } = options\n\n const [metal, setMetal] = useState<MetalColorProp>(defaultMetal)\n const [stone, setStone] = useState<StoneColorProp>(defaultStone)\n\n const metalPreset = useMemo(() => getMetalPreset(metal), [metal])\n const stonePreset = useMemo(() => getStonePreset(stone), [stone])\n\n const viewerProps = useMemo(\n () => ({\n metalColor: metal,\n stoneColor: stone,\n }),\n [metal, stone]\n )\n\n return {\n metal,\n setMetal,\n stone,\n setStone,\n metalPreset,\n stonePreset,\n metalOptions,\n stoneOptions,\n viewerProps,\n }\n}\n"],"names":["Viewer","forwardRef","props","ref","src","source","metalColor","stoneColor","materialColors","partColors","background","metalEnvUrl","gemEnvUrl","options","fov","shadows","autoRotate","quality","height","minHeight","aspectRatio","className","style","containerRef","useRef","viewerRef","cb","useImperativeHandle","useEffect","viewer","createViewer","parts","materials","_b","_a","info","state","err","progress","resolved","normalizeModelSource","ac","prevMaterialColorsRef","prev","next","key","color","prevPartColorsRef","partId","slotIdxStr","slotIndex","containerStyle","jsx","MetalSwatches","value","onChange","CANONICAL_METAL_PRESETS","category","variant","showLabel","filteredOptions","m","activePreset","getMetalPreset","activeId","jsxs","isSelected","MetalSelect","label","activeValue","e","val","preset","StoneSwatches","CANONICAL_STONE_PRESETS","s","getStonePreset","StoneSelect","JewelryCustomizer","defaultMetal","defaultStone","controlledMetal","onMetalChange","controlledStone","onStoneChange","metalOptions","stoneOptions","controlsVariant","onLoaded","onPartSelected","internalMetal","setInternalMetal","useState","internalStone","setInternalStone","currentMetal","currentStone","handleMetalChange","handleStoneChange","viewportHeight","Fragment","useJewelryCustomizer","metal","setMetal","stone","setStone","metalPreset","useMemo","stonePreset","viewerProps"],"mappings":"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"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/Viewer.tsx","../src/swatches/MetalSwatches.tsx","../src/swatches/StoneSwatches.tsx","../src/swatches/JewelryCustomizer.tsx","../src/swatches/useJewelryCustomizer.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\r\nimport { useRef, useEffect, forwardRef, useImperativeHandle, type CSSProperties } from 'react'\r\nimport {\r\n createViewer,\r\n normalizeModelSource,\r\n type Viewer as CoreViewer,\r\n type ModelSource,\r\n type ViewerSourceInput,\r\n type MetalColorProp,\r\n type StoneColorProp,\r\n type ViewerOptions,\r\n type ViewerState,\r\n type PartInfo,\r\n type MaterialSlotInfo,\r\n type PartType,\r\n} from '@thinkersteps_labs/3d-viewer-core'\r\n\r\nexport interface ViewerRef extends CoreViewer { }\r\n\r\nexport interface ViewerProps {\r\n /** 3D model URL or source object. Takes precedence over `source` if both provided. */\r\n src?: string\r\n /** 3D model source (URL string, ModelSource payload, or null). */\r\n source?: ViewerSourceInput\r\n /** Metal preset ID or hex code. IDE autocompletes standard presets. */\r\n metalColor?: MetalColorProp\r\n /** Stone preset ID or hex code. IDE autocompletes standard presets. */\r\n stoneColor?: StoneColorProp\r\n /** Bulk material name or slot ID color overrides. */\r\n materialColors?: Record<string, string>\r\n /** Part color overrides keyed by partId or partId:slotIndex. */\r\n partColors?: Record<string, string>\r\n background?: string | number\r\n metalEnvUrl?: string | ArrayBuffer\r\n gemEnvUrl?: string | ArrayBuffer\r\n options?: ViewerOptions\r\n fov?: number\r\n shadows?: boolean\r\n autoRotate?: boolean\r\n quality?: 'low' | 'medium' | 'high'\r\n /** Explicit container height (e.g. 520 or '520px'). Prevents zero-height collapse. */\r\n height?: number | string\r\n /** Explicit container min-height. */\r\n minHeight?: number | string\r\n /** Aspect ratio for responsive sizing (e.g. '16/9' or '4/3'). */\r\n aspectRatio?: string\r\n onLoaded?: (parts: PartInfo[], materials?: MaterialSlotInfo[]) => void\r\n onPartSelected?: (info: {\r\n meshId: string\r\n partId?: string\r\n type: PartType\r\n slotIndex?: number\r\n slotId?: string\r\n materialName?: string\r\n }) => void\r\n onChange?: (state: ViewerState) => void\r\n onError?: (err: Error) => void\r\n onProgress?: (progress: number) => void\r\n className?: string\r\n style?: CSSProperties\r\n}\r\n\r\nexport const Viewer = forwardRef<ViewerRef, ViewerProps>(function Viewer(props, ref) {\r\n const {\r\n src,\r\n source,\r\n metalColor,\r\n stoneColor,\r\n materialColors,\r\n partColors,\r\n background,\r\n metalEnvUrl,\r\n gemEnvUrl,\r\n options,\r\n fov,\r\n shadows,\r\n autoRotate,\r\n quality,\r\n height,\r\n minHeight,\r\n aspectRatio,\r\n className,\r\n style,\r\n } = props\r\n const containerRef = useRef<HTMLDivElement>(null)\r\n const viewerRef = useRef<ViewerRef | null>(null)\r\n const cb = useRef(props)\r\n cb.current = props\r\n\r\n useImperativeHandle(ref, () => viewerRef.current!, [])\r\n\r\n useEffect(() => {\r\n if (!containerRef.current) return\r\n const viewer = createViewer(containerRef.current, {\r\n ...options,\r\n ...(background !== undefined && { background }),\r\n ...(fov !== undefined && { fov }),\r\n ...(shadows !== undefined && { shadows }),\r\n ...(autoRotate !== undefined && { autoRotate }),\r\n ...(quality !== undefined && { quality }),\r\n ...(metalEnvUrl !== undefined && { metalEnvUrl }),\r\n ...(gemEnvUrl !== undefined && { gemEnvUrl }),\r\n })\r\n viewerRef.current = viewer\r\n if (import.meta.env.DEV && typeof window !== 'undefined') (window as any).__viewer = viewer\r\n if (ref) {\r\n if (typeof ref === 'function') ref(viewer)\r\n else (ref as any).current = viewer\r\n }\r\n viewer.on('loaded', ({ parts, materials }) => cb.current.onLoaded?.(parts, materials))\r\n viewer.on('partSelected', (info) => cb.current.onPartSelected?.(info))\r\n viewer.on('change', (state) => cb.current.onChange?.(state))\r\n viewer.on('error', (err) => cb.current.onError?.(err))\r\n viewer.on('loading', ({ progress }) => cb.current.onProgress?.(progress))\r\n return () => {\r\n viewer.dispose()\r\n if (ref) {\r\n if (typeof ref === 'function') ref(null)\r\n else (ref as any).current = null\r\n }\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [])\r\n\r\n useEffect(() => {\r\n if (!viewerRef.current) return\r\n const resolved = normalizeModelSource(src ?? source)\r\n if (!resolved) {\r\n viewerRef.current.unload()\r\n return\r\n }\r\n const ac = new AbortController()\r\n viewerRef.current.load(resolved, { signal: ac.signal })\r\n return () => ac.abort()\r\n }, [src, source])\r\n\r\n useEffect(() => {\r\n if (metalColor) viewerRef.current?.setMetalColor(metalColor)\r\n }, [metalColor])\r\n\r\n useEffect(() => {\r\n if (stoneColor) viewerRef.current?.setStoneColor(stoneColor)\r\n }, [stoneColor])\r\n\r\n const prevMaterialColorsRef = useRef<Record<string, string>>({})\r\n useEffect(() => {\r\n if (!viewerRef.current) return\r\n const prev = prevMaterialColorsRef.current\r\n const next = materialColors ?? {}\r\n\r\n for (const key of Object.keys(prev)) {\r\n if (!(key in next)) {\r\n viewerRef.current.clearMaterialColor(key)\r\n }\r\n }\r\n for (const [key, color] of Object.entries(next)) {\r\n if (prev[key] !== color) {\r\n viewerRef.current.setMaterialColor(key, color)\r\n }\r\n }\r\n prevMaterialColorsRef.current = { ...next }\r\n }, [materialColors])\r\n\r\n const prevPartColorsRef = useRef<Record<string, string>>({})\r\n useEffect(() => {\r\n if (!viewerRef.current) return\r\n const prev = prevPartColorsRef.current\r\n const next = partColors ?? {}\r\n\r\n for (const key of Object.keys(prev)) {\r\n if (!(key in next)) {\r\n if (key.includes(':')) {\r\n const [partId, slotIdxStr] = key.split(':')\r\n const slotIndex = parseInt(slotIdxStr ?? '', 10)\r\n viewerRef.current.clearPartColor(partId ?? '', isNaN(slotIndex) ? undefined : slotIndex)\r\n } else {\r\n viewerRef.current.clearPartColor(key)\r\n }\r\n }\r\n }\r\n for (const [key, color] of Object.entries(next)) {\r\n if (prev[key] !== color) {\r\n if (key.includes(':')) {\r\n const [partId, slotIdxStr] = key.split(':')\r\n const slotIndex = parseInt(slotIdxStr ?? '', 10)\r\n viewerRef.current.setPartColor(partId ?? '', color, isNaN(slotIndex) ? undefined : slotIndex)\r\n } else {\r\n viewerRef.current.setPartColor(key, color)\r\n }\r\n }\r\n }\r\n prevPartColorsRef.current = { ...next }\r\n }, [partColors])\r\n\r\n useEffect(() => {\r\n if (!viewerRef.current) return\r\n if (autoRotate) viewerRef.current.startRotation()\r\n else viewerRef.current.stopRotation()\r\n }, [autoRotate])\r\n\r\n useEffect(() => {\r\n if (quality) viewerRef.current?.setQuality(quality)\r\n }, [quality])\r\n\r\n const containerStyle: CSSProperties = {\r\n width: '100%',\r\n height: height !== undefined ? (typeof height === 'number' ? `${height}px` : height) : '100%',\r\n minHeight: minHeight !== undefined ? (typeof minHeight === 'number' ? `${minHeight}px` : minHeight) : undefined,\r\n aspectRatio,\r\n position: 'relative',\r\n ...style,\r\n }\r\n\r\n return (\r\n <div\r\n ref={containerRef}\r\n className={className}\r\n style={containerStyle}\r\n />\r\n )\r\n})\r\n\r\nexport default Viewer\r\n","import React, { type CSSProperties } from 'react'\r\nimport {\r\n CANONICAL_METAL_PRESETS,\r\n getMetalPreset,\r\n type MetalPreset,\r\n type MetalColorProp,\r\n} from '@thinkersteps_labs/3d-viewer-core'\r\nimport './swatches.css'\r\n\r\nexport interface MetalSwatchesProps {\r\n value?: MetalColorProp\r\n onChange?: (metalId: string, preset?: MetalPreset) => void\r\n options?: MetalPreset[]\r\n category?: 'all' | 'gold' | 'platinum-silver' | 'alternative'\r\n variant?: 'pills' | 'dots'\r\n showLabel?: boolean\r\n className?: string\r\n style?: CSSProperties\r\n}\r\n\r\nexport function MetalSwatches({\r\n value,\r\n onChange,\r\n options = CANONICAL_METAL_PRESETS,\r\n category = 'all',\r\n variant = 'pills',\r\n showLabel = true,\r\n className = '',\r\n style,\r\n}: MetalSwatchesProps) {\r\n const filteredOptions = category === 'all'\r\n ? options\r\n : options.filter((m) => m.category === category)\r\n\r\n const activePreset = value ? getMetalPreset(value) : undefined\r\n const activeId = activePreset?.id ?? value\r\n\r\n return (\r\n <div className={`td-swatch-group ${className}`} style={style}>\r\n {showLabel && (\r\n <div className=\"td-swatch-header\">\r\n <span className=\"td-swatch-title\">Metal</span>\r\n {activePreset && (\r\n <span className=\"td-swatch-selected-name\">{activePreset.label}</span>\r\n )}\r\n </div>\r\n )}\r\n <div className=\"td-swatch-row\" role=\"radiogroup\" aria-label=\"Metal Selection\">\r\n {filteredOptions.map((m) => {\r\n const isSelected = activeId === m.id || value === m.hex\r\n return (\r\n <button\r\n key={m.id}\r\n type=\"button\"\r\n role=\"radio\"\r\n aria-checked={isSelected}\r\n title={m.label}\r\n className={`td-swatch-${variant === 'dots' ? 'dot' : 'pill'} ${isSelected ? 'active' : ''}`}\r\n onClick={() => onChange?.(m.id, m)}\r\n >\r\n <span\r\n className=\"td-swatch-color-circle\"\r\n style={{ backgroundColor: m.hex }}\r\n />\r\n {variant === 'pills' && <span>{m.label}</span>}\r\n </button>\r\n )\r\n })}\r\n </div>\r\n </div>\r\n )\r\n}\r\n\r\nexport interface MetalSelectProps {\r\n value?: MetalColorProp\r\n onChange?: (metalId: string, preset?: MetalPreset) => void\r\n options?: MetalPreset[]\r\n label?: string\r\n className?: string\r\n style?: CSSProperties\r\n}\r\n\r\nexport function MetalSelect({\r\n value,\r\n onChange,\r\n options = CANONICAL_METAL_PRESETS,\r\n label = 'Select Metal',\r\n className = '',\r\n style,\r\n}: MetalSelectProps) {\r\n const activePreset = value ? getMetalPreset(value) : undefined\r\n const activeValue = activePreset?.id ?? value ?? options[0]?.id\r\n\r\n return (\r\n <div className={`td-select-wrapper ${className}`} style={style}>\r\n {label && <label className=\"td-swatch-title\">{label}</label>}\r\n <select\r\n className=\"td-select\"\r\n value={activeValue}\r\n onChange={(e) => {\r\n const val = e.target.value\r\n const preset = getMetalPreset(val)\r\n onChange?.(val, preset)\r\n }}\r\n >\r\n {options.map((m) => (\r\n <option key={m.id} value={m.id}>\r\n {m.label}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n )\r\n}\r\n","import React, { type CSSProperties } from 'react'\r\nimport {\r\n CANONICAL_STONE_PRESETS,\r\n getStonePreset,\r\n type StonePreset,\r\n type StoneColorProp,\r\n} from '@thinkersteps_labs/3d-viewer-core'\r\nimport './swatches.css'\r\n\r\nexport interface StoneSwatchesProps {\r\n value?: StoneColorProp\r\n onChange?: (stoneId: string, preset?: StonePreset) => void\r\n options?: StonePreset[]\r\n category?: 'all' | 'diamond' | 'gemstone'\r\n variant?: 'pills' | 'dots'\r\n showLabel?: boolean\r\n className?: string\r\n style?: CSSProperties\r\n}\r\n\r\nexport function StoneSwatches({\r\n value,\r\n onChange,\r\n options = CANONICAL_STONE_PRESETS,\r\n category = 'all',\r\n variant = 'pills',\r\n showLabel = true,\r\n className = '',\r\n style,\r\n}: StoneSwatchesProps) {\r\n const filteredOptions = category === 'all'\r\n ? options\r\n : options.filter((s) => s.category === category)\r\n\r\n const activePreset = value ? getStonePreset(value) : undefined\r\n const activeId = activePreset?.id ?? value\r\n\r\n return (\r\n <div className={`td-swatch-group ${className}`} style={style}>\r\n {showLabel && (\r\n <div className=\"td-swatch-header\">\r\n <span className=\"td-swatch-title\">Gemstone</span>\r\n {activePreset && (\r\n <span className=\"td-swatch-selected-name\">\r\n {activePreset.label}\r\n {activePreset.grade ? ` (${activePreset.grade})` : ''}\r\n </span>\r\n )}\r\n </div>\r\n )}\r\n <div className=\"td-swatch-row\" role=\"radiogroup\" aria-label=\"Gemstone Selection\">\r\n {filteredOptions.map((s) => {\r\n const isSelected = activeId === s.id || value === s.hex\r\n return (\r\n <button\r\n key={s.id}\r\n type=\"button\"\r\n role=\"radio\"\r\n aria-checked={isSelected}\r\n title={`${s.label}${s.grade ? ` - ${s.grade}` : ''}`}\r\n className={`td-swatch-${variant === 'dots' ? 'dot' : 'pill'} ${isSelected ? 'active' : ''}`}\r\n onClick={() => onChange?.(s.id, s)}\r\n >\r\n <span\r\n className=\"td-swatch-color-circle\"\r\n style={{ backgroundColor: s.hex }}\r\n />\r\n {variant === 'pills' && <span>{s.label}</span>}\r\n </button>\r\n )\r\n })}\r\n </div>\r\n </div>\r\n )\r\n}\r\n\r\nexport interface StoneSelectProps {\r\n value?: StoneColorProp\r\n onChange?: (stoneId: string, preset?: StonePreset) => void\r\n options?: StonePreset[]\r\n label?: string\r\n className?: string\r\n style?: CSSProperties\r\n}\r\n\r\nexport function StoneSelect({\r\n value,\r\n onChange,\r\n options = CANONICAL_STONE_PRESETS,\r\n label = 'Select Gemstone',\r\n className = '',\r\n style,\r\n}: StoneSelectProps) {\r\n const activePreset = value ? getStonePreset(value) : undefined\r\n const activeValue = activePreset?.id ?? value ?? options[0]?.id\r\n\r\n return (\r\n <div className={`td-select-wrapper ${className}`} style={style}>\r\n {label && <label className=\"td-swatch-title\">{label}</label>}\r\n <select\r\n className=\"td-select\"\r\n value={activeValue}\r\n onChange={(e) => {\r\n const val = e.target.value\r\n const preset = getStonePreset(val)\r\n onChange?.(val, preset)\r\n }}\r\n >\r\n {options.map((s) => (\r\n <option key={s.id} value={s.id}>\r\n {s.label} {s.grade ? `(${s.grade})` : ''}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n )\r\n}\r\n","import React, { useState, type CSSProperties } from 'react'\r\nimport {\r\n type MetalColorProp,\r\n type StoneColorProp,\r\n type ViewerSourceInput,\r\n type MetalPreset,\r\n type StonePreset,\r\n type PartInfo,\r\n type PartType,\r\n} from '@thinkersteps_labs/3d-viewer-core'\r\nimport { Viewer, type ViewerRef } from '../Viewer'\r\nimport { MetalSwatches, MetalSelect } from './MetalSwatches'\r\nimport { StoneSwatches, StoneSelect } from './StoneSwatches'\r\nimport './swatches.css'\r\n\r\nexport interface JewelryCustomizerProps {\r\n src?: string\r\n source?: ViewerSourceInput\r\n defaultMetal?: MetalColorProp\r\n defaultStone?: StoneColorProp\r\n metal?: MetalColorProp\r\n onMetalChange?: (metal: string, preset?: MetalPreset) => void\r\n stone?: StoneColorProp\r\n onStoneChange?: (stone: string, preset?: StonePreset) => void\r\n metalOptions?: MetalPreset[]\r\n stoneOptions?: StonePreset[]\r\n controlsVariant?: 'pills' | 'dots' | 'select' | 'none'\r\n height?: number | string\r\n autoRotate?: boolean\r\n quality?: 'low' | 'medium' | 'high'\r\n fov?: number\r\n shadows?: boolean\r\n onLoaded?: (parts: PartInfo[]) => void\r\n onPartSelected?: (info: { meshId: string; type: PartType }) => void\r\n className?: string\r\n style?: CSSProperties\r\n viewerRef?: React.Ref<ViewerRef>\r\n}\r\n\r\nexport function JewelryCustomizer({\r\n src,\r\n source,\r\n defaultMetal = 'yellow-gold-18k',\r\n defaultStone = 'diamond-d',\r\n metal: controlledMetal,\r\n onMetalChange,\r\n stone: controlledStone,\r\n onStoneChange,\r\n metalOptions,\r\n stoneOptions,\r\n controlsVariant = 'pills',\r\n height = 520,\r\n autoRotate = true,\r\n quality = 'high',\r\n fov,\r\n shadows,\r\n onLoaded,\r\n onPartSelected,\r\n className = '',\r\n style,\r\n viewerRef,\r\n}: JewelryCustomizerProps) {\r\n const [internalMetal, setInternalMetal] = useState<MetalColorProp>(defaultMetal)\r\n const [internalStone, setInternalStone] = useState<StoneColorProp>(defaultStone)\r\n\r\n const currentMetal = controlledMetal !== undefined ? controlledMetal : internalMetal\r\n const currentStone = controlledStone !== undefined ? controlledStone : internalStone\r\n\r\n const handleMetalChange = (val: string, preset?: MetalPreset) => {\r\n if (controlledMetal === undefined) setInternalMetal(val)\r\n onMetalChange?.(val, preset)\r\n }\r\n\r\n const handleStoneChange = (val: string, preset?: StonePreset) => {\r\n if (controlledStone === undefined) setInternalStone(val)\r\n onStoneChange?.(val, preset)\r\n }\r\n\r\n const viewportHeight = typeof height === 'number' ? `${height}px` : height\r\n\r\n return (\r\n <div className={`td-customizer-card ${className}`} style={style}>\r\n <div className=\"td-customizer-viewport\" style={{ height: viewportHeight }}>\r\n <Viewer\r\n ref={viewerRef}\r\n src={src}\r\n source={source}\r\n metalColor={currentMetal}\r\n stoneColor={currentStone}\r\n autoRotate={autoRotate}\r\n quality={quality}\r\n fov={fov}\r\n shadows={shadows}\r\n onLoaded={onLoaded}\r\n onPartSelected={onPartSelected}\r\n />\r\n </div>\r\n\r\n {controlsVariant !== 'none' && (\r\n <div className=\"td-customizer-controls\">\r\n {controlsVariant === 'select' ? (\r\n <>\r\n <MetalSelect\r\n value={currentMetal}\r\n onChange={handleMetalChange}\r\n options={metalOptions}\r\n />\r\n <StoneSelect\r\n value={currentStone}\r\n onChange={handleStoneChange}\r\n options={stoneOptions}\r\n />\r\n </>\r\n ) : (\r\n <>\r\n <MetalSwatches\r\n value={currentMetal}\r\n onChange={handleMetalChange}\r\n options={metalOptions}\r\n variant={controlsVariant}\r\n />\r\n <StoneSwatches\r\n value={currentStone}\r\n onChange={handleStoneChange}\r\n options={stoneOptions}\r\n variant={controlsVariant}\r\n />\r\n </>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n","import { useState, useMemo } from 'react'\r\nimport {\r\n CANONICAL_METAL_PRESETS,\r\n CANONICAL_STONE_PRESETS,\r\n getMetalPreset,\r\n getStonePreset,\r\n type MetalColorProp,\r\n type StoneColorProp,\r\n type MetalPreset,\r\n type StonePreset,\r\n} from '@thinkersteps_labs/3d-viewer-core'\r\n\r\nexport interface UseJewelryCustomizerOptions {\r\n defaultMetal?: MetalColorProp\r\n defaultStone?: StoneColorProp\r\n metalOptions?: MetalPreset[]\r\n stoneOptions?: StonePreset[]\r\n}\r\n\r\nexport interface UseJewelryCustomizerReturn {\r\n metal: MetalColorProp\r\n setMetal: (val: MetalColorProp) => void\r\n stone: StoneColorProp\r\n setStone: (val: StoneColorProp) => void\r\n metalPreset?: MetalPreset\r\n stonePreset?: StonePreset\r\n metalOptions: MetalPreset[]\r\n stoneOptions: StonePreset[]\r\n viewerProps: {\r\n metalColor: MetalColorProp\r\n stoneColor: StoneColorProp\r\n }\r\n}\r\n\r\nexport function useJewelryCustomizer(\r\n options: UseJewelryCustomizerOptions = {}\r\n): UseJewelryCustomizerReturn {\r\n const {\r\n defaultMetal = 'yellow-gold-18k',\r\n defaultStone = 'diamond-d',\r\n metalOptions = CANONICAL_METAL_PRESETS,\r\n stoneOptions = CANONICAL_STONE_PRESETS,\r\n } = options\r\n\r\n const [metal, setMetal] = useState<MetalColorProp>(defaultMetal)\r\n const [stone, setStone] = useState<StoneColorProp>(defaultStone)\r\n\r\n const metalPreset = useMemo(() => getMetalPreset(metal), [metal])\r\n const stonePreset = useMemo(() => getStonePreset(stone), [stone])\r\n\r\n const viewerProps = useMemo(\r\n () => ({\r\n metalColor: metal,\r\n stoneColor: stone,\r\n }),\r\n [metal, stone]\r\n )\r\n\r\n return {\r\n metal,\r\n setMetal,\r\n stone,\r\n setStone,\r\n metalPreset,\r\n stonePreset,\r\n metalOptions,\r\n stoneOptions,\r\n viewerProps,\r\n }\r\n}\r\n"],"names":["Viewer","forwardRef","props","ref","src","source","metalColor","stoneColor","materialColors","partColors","background","metalEnvUrl","gemEnvUrl","options","fov","shadows","autoRotate","quality","height","minHeight","aspectRatio","className","style","containerRef","useRef","viewerRef","cb","useImperativeHandle","useEffect","viewer","createViewer","parts","materials","_b","_a","info","state","err","progress","resolved","normalizeModelSource","ac","prevMaterialColorsRef","prev","next","key","color","prevPartColorsRef","partId","slotIdxStr","slotIndex","containerStyle","jsx","MetalSwatches","value","onChange","CANONICAL_METAL_PRESETS","category","variant","showLabel","filteredOptions","m","activePreset","getMetalPreset","activeId","jsxs","isSelected","MetalSelect","label","activeValue","e","val","preset","StoneSwatches","CANONICAL_STONE_PRESETS","s","getStonePreset","StoneSelect","JewelryCustomizer","defaultMetal","defaultStone","controlledMetal","onMetalChange","controlledStone","onStoneChange","metalOptions","stoneOptions","controlsVariant","onLoaded","onPartSelected","internalMetal","setInternalMetal","useState","internalStone","setInternalStone","currentMetal","currentStone","handleMetalChange","handleStoneChange","viewportHeight","Fragment","useJewelryCustomizer","metal","setMetal","stone","setStone","metalPreset","useMemo","stonePreset","viewerProps"],"mappings":";;;;AA8DO,MAAMA,IAASC,EAAmC,SAAgBC,GAAOC,GAAK;AACnF,QAAM;AAAA,IACJ,KAAAC;AAAA,IACA,QAAAC;AAAA,IACA,YAAAC;AAAA,IACA,YAAAC;AAAA,IACA,gBAAAC;AAAA,IACA,YAAAC;AAAA,IACA,YAAAC;AAAA,IACA,aAAAC;AAAA,IACA,WAAAC;AAAA,IACA,SAAAC;AAAA,IACA,KAAAC;AAAA,IACA,SAAAC;AAAA,IACA,YAAAC;AAAA,IACA,SAAAC;AAAA,IACA,QAAAC;AAAA,IACA,WAAAC;AAAA,IACA,aAAAC;AAAA,IACA,WAAAC;AAAA,IACA,OAAAC;AAAA,EAAA,IACEpB,GACEqB,IAAeC,EAAuB,IAAI,GAC1CC,IAAYD,EAAyB,IAAI,GACzCE,IAAKF,EAAOtB,CAAK;AACvB,EAAAwB,EAAG,UAAUxB,GAEbyB,EAAoBxB,GAAK,MAAMsB,EAAU,SAAU,CAAA,CAAE,GAErDG,EAAU,MAAM;AACd,QAAI,CAACL,EAAa,QAAS;AAC3B,UAAMM,IAASC,EAAaP,EAAa,SAAS;AAAA,MAChD,GAAGV;AAAA,MACH,GAAIH,MAAe,UAAa,EAAE,YAAAA,EAAA;AAAA,MAClC,GAAII,MAAQ,UAAa,EAAE,KAAAA,EAAA;AAAA,MAC3B,GAAIC,MAAY,UAAa,EAAE,SAAAA,EAAA;AAAA,MAC/B,GAAIC,MAAe,UAAa,EAAE,YAAAA,EAAA;AAAA,MAClC,GAAIC,MAAY,UAAa,EAAE,SAAAA,EAAA;AAAA,MAC/B,GAAIN,MAAgB,UAAa,EAAE,aAAAA,EAAA;AAAA,MACnC,GAAIC,MAAc,UAAa,EAAE,WAAAA,EAAA;AAAA,IAAU,CAC5C;AACD,WAAAa,EAAU,UAAUI,GAEhB1B,MACE,OAAOA,KAAQ,aAAYA,EAAI0B,CAAM,MACvB,UAAUA,IAE9BA,EAAO,GAAG,UAAU,CAAC,EAAE,OAAAE,GAAO,WAAAC,QAAU;;AAAM,cAAAC,KAAAC,IAAAR,EAAG,SAAQ,aAAX,gBAAAO,EAAA,KAAAC,GAAsBH,GAAOC;AAAA,KAAU,GACrFH,EAAO,GAAG,gBAAgB,CAACM,MAAA;;AAAS,cAAAF,KAAAC,IAAAR,EAAG,SAAQ,mBAAX,gBAAAO,EAAA,KAAAC,GAA4BC;AAAA,KAAK,GACrEN,EAAO,GAAG,UAAU,CAACO,MAAA;;AAAU,cAAAH,KAAAC,IAAAR,EAAG,SAAQ,aAAX,gBAAAO,EAAA,KAAAC,GAAsBE;AAAA,KAAM,GAC3DP,EAAO,GAAG,SAAS,CAACQ,MAAA;;AAAQ,cAAAJ,KAAAC,IAAAR,EAAG,SAAQ,YAAX,gBAAAO,EAAA,KAAAC,GAAqBG;AAAA,KAAI,GACrDR,EAAO,GAAG,WAAW,CAAC,EAAE,UAAAS;;AAAe,cAAAL,KAAAC,IAAAR,EAAG,SAAQ,eAAX,gBAAAO,EAAA,KAAAC,GAAwBI;AAAA,KAAS,GACjE,MAAM;AACX,MAAAT,EAAO,QAAA,GACH1B,MACE,OAAOA,KAAQ,aAAYA,EAAI,IAAI,MACrB,UAAU;AAAA,IAEhC;AAAA,EAEF,GAAG,CAAA,CAAE,GAELyB,EAAU,MAAM;AACd,QAAI,CAACH,EAAU,QAAS;AACxB,UAAMc,IAAWC,EAAqBpC,KAAOC,CAAM;AACnD,QAAI,CAACkC,GAAU;AACb,MAAAd,EAAU,QAAQ,OAAA;AAClB;AAAA,IACF;AACA,UAAMgB,IAAK,IAAI,gBAAA;AACf,WAAAhB,EAAU,QAAQ,KAAKc,GAAU,EAAE,QAAQE,EAAG,QAAQ,GAC/C,MAAMA,EAAG,MAAA;AAAA,EAClB,GAAG,CAACrC,GAAKC,CAAM,CAAC,GAEhBuB,EAAU,MAAM;;AACd,IAAItB,OAAY4B,IAAAT,EAAU,YAAV,QAAAS,EAAmB,cAAc5B;AAAA,EACnD,GAAG,CAACA,CAAU,CAAC,GAEfsB,EAAU,MAAM;;AACd,IAAIrB,OAAY2B,IAAAT,EAAU,YAAV,QAAAS,EAAmB,cAAc3B;AAAA,EACnD,GAAG,CAACA,CAAU,CAAC;AAEf,QAAMmC,IAAwBlB,EAA+B,EAAE;AAC/D,EAAAI,EAAU,MAAM;AACd,QAAI,CAACH,EAAU,QAAS;AACxB,UAAMkB,IAAOD,EAAsB,SAC7BE,IAAOpC,KAAkB,CAAA;AAE/B,eAAWqC,KAAO,OAAO,KAAKF,CAAI;AAChC,MAAME,KAAOD,KACXnB,EAAU,QAAQ,mBAAmBoB,CAAG;AAG5C,eAAW,CAACA,GAAKC,CAAK,KAAK,OAAO,QAAQF,CAAI;AAC5C,MAAID,EAAKE,CAAG,MAAMC,KAChBrB,EAAU,QAAQ,iBAAiBoB,GAAKC,CAAK;AAGjD,IAAAJ,EAAsB,UAAU,EAAE,GAAGE,EAAA;AAAA,EACvC,GAAG,CAACpC,CAAc,CAAC;AAEnB,QAAMuC,IAAoBvB,EAA+B,EAAE;AAC3D,EAAAI,EAAU,MAAM;AACd,QAAI,CAACH,EAAU,QAAS;AACxB,UAAMkB,IAAOI,EAAkB,SACzBH,IAAOnC,KAAc,CAAA;AAE3B,eAAWoC,KAAO,OAAO,KAAKF,CAAI;AAChC,UAAI,EAAEE,KAAOD;AACX,YAAIC,EAAI,SAAS,GAAG,GAAG;AACrB,gBAAM,CAACG,GAAQC,CAAU,IAAIJ,EAAI,MAAM,GAAG,GACpCK,IAAY,SAASD,KAAc,IAAI,EAAE;AAC/C,UAAAxB,EAAU,QAAQ,eAAeuB,KAAU,IAAI,MAAME,CAAS,IAAI,SAAYA,CAAS;AAAA,QACzF;AACE,UAAAzB,EAAU,QAAQ,eAAeoB,CAAG;AAI1C,eAAW,CAACA,GAAKC,CAAK,KAAK,OAAO,QAAQF,CAAI;AAC5C,UAAID,EAAKE,CAAG,MAAMC;AAChB,YAAID,EAAI,SAAS,GAAG,GAAG;AACrB,gBAAM,CAACG,GAAQC,CAAU,IAAIJ,EAAI,MAAM,GAAG,GACpCK,IAAY,SAASD,KAAc,IAAI,EAAE;AAC/C,UAAAxB,EAAU,QAAQ,aAAauB,KAAU,IAAIF,GAAO,MAAMI,CAAS,IAAI,SAAYA,CAAS;AAAA,QAC9F;AACE,UAAAzB,EAAU,QAAQ,aAAaoB,GAAKC,CAAK;AAI/C,IAAAC,EAAkB,UAAU,EAAE,GAAGH,EAAA;AAAA,EACnC,GAAG,CAACnC,CAAU,CAAC,GAEfmB,EAAU,MAAM;AACd,IAAKH,EAAU,YACXT,IAAYS,EAAU,QAAQ,cAAA,IAC7BA,EAAU,QAAQ,aAAA;AAAA,EACzB,GAAG,CAACT,CAAU,CAAC,GAEfY,EAAU,MAAM;;AACd,IAAIX,OAASiB,IAAAT,EAAU,YAAV,QAAAS,EAAmB,WAAWjB;AAAA,EAC7C,GAAG,CAACA,CAAO,CAAC;AAEZ,QAAMkC,IAAgC;AAAA,IACpC,OAAO;AAAA,IACP,QAAQjC,MAAW,SAAa,OAAOA,KAAW,WAAW,GAAGA,CAAM,OAAOA,IAAU;AAAA,IACvF,WAAWC,MAAc,SAAa,OAAOA,KAAc,WAAW,GAAGA,CAAS,OAAOA,IAAa;AAAA,IACtG,aAAAC;AAAA,IACA,UAAU;AAAA,IACV,GAAGE;AAAA,EAAA;AAGL,SACE,gBAAA8B;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAK7B;AAAA,MACL,WAAAF;AAAA,MACA,OAAO8B;AAAA,IAAA;AAAA,EAAA;AAGb,CAAC;ACxMM,SAASE,EAAc;AAAA,EAC5B,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,SAAA1C,IAAU2C;AAAA,EACV,UAAAC,IAAW;AAAA,EACX,SAAAC,IAAU;AAAA,EACV,WAAAC,IAAY;AAAA,EACZ,WAAAtC,IAAY;AAAA,EACZ,OAAAC;AACF,GAAuB;AACrB,QAAMsC,IAAkBH,MAAa,QACjC5C,IACAA,EAAQ,OAAO,CAACgD,MAAMA,EAAE,aAAaJ,CAAQ,GAE3CK,IAAeR,IAAQS,EAAeT,CAAK,IAAI,QAC/CU,KAAWF,KAAA,gBAAAA,EAAc,OAAMR;AAErC,2BACG,OAAA,EAAI,WAAW,mBAAmBjC,CAAS,IAAI,OAAAC,GAC7C,UAAA;AAAA,IAAAqC,KACC,gBAAAM,EAAC,OAAA,EAAI,WAAU,oBACb,UAAA;AAAA,MAAA,gBAAAb,EAAC,QAAA,EAAK,WAAU,mBAAkB,UAAA,SAAK;AAAA,MACtCU,KACC,gBAAAV,EAAC,QAAA,EAAK,WAAU,2BAA2B,YAAa,MAAA,CAAM;AAAA,IAAA,GAElE;AAAA,IAEF,gBAAAA,EAAC,OAAA,EAAI,WAAU,iBAAgB,MAAK,cAAa,cAAW,mBACzD,UAAAQ,EAAgB,IAAI,CAACC,MAAM;AAC1B,YAAMK,IAAaF,MAAaH,EAAE,MAAMP,MAAUO,EAAE;AACpD,aACE,gBAAAI;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,MAAK;AAAA,UACL,MAAK;AAAA,UACL,gBAAcC;AAAA,UACd,OAAOL,EAAE;AAAA,UACT,WAAW,aAAaH,MAAY,SAAS,QAAQ,MAAM,IAAIQ,IAAa,WAAW,EAAE;AAAA,UACzF,SAAS,MAAMX,KAAA,gBAAAA,EAAWM,EAAE,IAAIA;AAAA,UAEhC,UAAA;AAAA,YAAA,gBAAAT;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO,EAAE,iBAAiBS,EAAE,IAAA;AAAA,cAAI;AAAA,YAAA;AAAA,YAEjCH,MAAY,WAAW,gBAAAN,EAAC,QAAA,EAAM,YAAE,MAAA,CAAM;AAAA,UAAA;AAAA,QAAA;AAAA,QAZlCS,EAAE;AAAA,MAAA;AAAA,IAeb,CAAC,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;AAWO,SAASM,EAAY;AAAA,EAC1B,OAAAb;AAAA,EACA,UAAAC;AAAA,EACA,SAAA1C,IAAU2C;AAAA,EACV,OAAAY,IAAQ;AAAA,EACR,WAAA/C,IAAY;AAAA,EACZ,OAAAC;AACF,GAAqB;;AACnB,QAAMwC,IAAeR,IAAQS,EAAeT,CAAK,IAAI,QAC/Ce,KAAcP,KAAA,gBAAAA,EAAc,OAAMR,OAASpB,IAAArB,EAAQ,CAAC,MAAT,gBAAAqB,EAAY;AAE7D,2BACG,OAAA,EAAI,WAAW,qBAAqBb,CAAS,IAAI,OAAAC,GAC/C,UAAA;AAAA,IAAA8C,KAAS,gBAAAhB,EAAC,SAAA,EAAM,WAAU,mBAAmB,UAAAgB,GAAM;AAAA,IACpD,gBAAAhB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,OAAOiB;AAAA,QACP,UAAU,CAACC,MAAM;AACf,gBAAMC,IAAMD,EAAE,OAAO,OACfE,IAAST,EAAeQ,CAAG;AACjC,UAAAhB,KAAA,QAAAA,EAAWgB,GAAKC;AAAA,QAClB;AAAA,QAEC,UAAA3D,EAAQ,IAAI,CAACgD,MACZ,gBAAAT,EAAC,UAAA,EAAkB,OAAOS,EAAE,IACzB,UAAAA,EAAE,MAAA,GADQA,EAAE,EAEf,CACD;AAAA,MAAA;AAAA,IAAA;AAAA,EACH,GACF;AAEJ;AC7FO,SAASY,EAAc;AAAA,EAC5B,OAAAnB;AAAA,EACA,UAAAC;AAAA,EACA,SAAA1C,IAAU6D;AAAA,EACV,UAAAjB,IAAW;AAAA,EACX,SAAAC,IAAU;AAAA,EACV,WAAAC,IAAY;AAAA,EACZ,WAAAtC,IAAY;AAAA,EACZ,OAAAC;AACF,GAAuB;AACrB,QAAMsC,IAAkBH,MAAa,QACjC5C,IACAA,EAAQ,OAAO,CAAC8D,MAAMA,EAAE,aAAalB,CAAQ,GAE3CK,IAAeR,IAAQsB,EAAetB,CAAK,IAAI,QAC/CU,KAAWF,KAAA,gBAAAA,EAAc,OAAMR;AAErC,2BACG,OAAA,EAAI,WAAW,mBAAmBjC,CAAS,IAAI,OAAAC,GAC7C,UAAA;AAAA,IAAAqC,KACC,gBAAAM,EAAC,OAAA,EAAI,WAAU,oBACb,UAAA;AAAA,MAAA,gBAAAb,EAAC,QAAA,EAAK,WAAU,mBAAkB,UAAA,YAAQ;AAAA,MACzCU,KACC,gBAAAG,EAAC,QAAA,EAAK,WAAU,2BACb,UAAA;AAAA,QAAAH,EAAa;AAAA,QACbA,EAAa,QAAQ,KAAKA,EAAa,KAAK,MAAM;AAAA,MAAA,EAAA,CACrD;AAAA,IAAA,GAEJ;AAAA,IAEF,gBAAAV,EAAC,OAAA,EAAI,WAAU,iBAAgB,MAAK,cAAa,cAAW,sBACzD,UAAAQ,EAAgB,IAAI,CAACe,MAAM;AAC1B,YAAMT,IAAaF,MAAaW,EAAE,MAAMrB,MAAUqB,EAAE;AACpD,aACE,gBAAAV;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,MAAK;AAAA,UACL,MAAK;AAAA,UACL,gBAAcC;AAAA,UACd,OAAO,GAAGS,EAAE,KAAK,GAAGA,EAAE,QAAQ,MAAMA,EAAE,KAAK,KAAK,EAAE;AAAA,UAClD,WAAW,aAAajB,MAAY,SAAS,QAAQ,MAAM,IAAIQ,IAAa,WAAW,EAAE;AAAA,UACzF,SAAS,MAAMX,KAAA,gBAAAA,EAAWoB,EAAE,IAAIA;AAAA,UAEhC,UAAA;AAAA,YAAA,gBAAAvB;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO,EAAE,iBAAiBuB,EAAE,IAAA;AAAA,cAAI;AAAA,YAAA;AAAA,YAEjCjB,MAAY,WAAW,gBAAAN,EAAC,QAAA,EAAM,YAAE,MAAA,CAAM;AAAA,UAAA;AAAA,QAAA;AAAA,QAZlCuB,EAAE;AAAA,MAAA;AAAA,IAeb,CAAC,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;AAWO,SAASE,GAAY;AAAA,EAC1B,OAAAvB;AAAA,EACA,UAAAC;AAAA,EACA,SAAA1C,IAAU6D;AAAA,EACV,OAAAN,IAAQ;AAAA,EACR,WAAA/C,IAAY;AAAA,EACZ,OAAAC;AACF,GAAqB;;AACnB,QAAMwC,IAAeR,IAAQsB,EAAetB,CAAK,IAAI,QAC/Ce,KAAcP,KAAA,gBAAAA,EAAc,OAAMR,OAASpB,IAAArB,EAAQ,CAAC,MAAT,gBAAAqB,EAAY;AAE7D,2BACG,OAAA,EAAI,WAAW,qBAAqBb,CAAS,IAAI,OAAAC,GAC/C,UAAA;AAAA,IAAA8C,KAAS,gBAAAhB,EAAC,SAAA,EAAM,WAAU,mBAAmB,UAAAgB,GAAM;AAAA,IACpD,gBAAAhB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,OAAOiB;AAAA,QACP,UAAU,CAACC,MAAM;AACf,gBAAMC,IAAMD,EAAE,OAAO,OACfE,IAASI,EAAeL,CAAG;AACjC,UAAAhB,KAAA,QAAAA,EAAWgB,GAAKC;AAAA,QAClB;AAAA,QAEC,UAAA3D,EAAQ,IAAI,CAAC8D,wBACX,UAAA,EAAkB,OAAOA,EAAE,IACzB,UAAA;AAAA,UAAAA,EAAE;AAAA,UAAM;AAAA,UAAEA,EAAE,QAAQ,IAAIA,EAAE,KAAK,MAAM;AAAA,QAAA,EAAA,GAD3BA,EAAE,EAEf,CACD;AAAA,MAAA;AAAA,IAAA;AAAA,EACH,GACF;AAEJ;AC7EO,SAASG,GAAkB;AAAA,EAChC,KAAA1E;AAAA,EACA,QAAAC;AAAA,EACA,cAAA0E,IAAe;AAAA,EACf,cAAAC,IAAe;AAAA,EACf,OAAOC;AAAA,EACP,eAAAC;AAAA,EACA,OAAOC;AAAA,EACP,eAAAC;AAAA,EACA,cAAAC;AAAA,EACA,cAAAC;AAAA,EACA,iBAAAC,IAAkB;AAAA,EAClB,QAAArE,IAAS;AAAA,EACT,YAAAF,IAAa;AAAA,EACb,SAAAC,IAAU;AAAA,EACV,KAAAH;AAAA,EACA,SAAAC;AAAA,EACA,UAAAyE;AAAA,EACA,gBAAAC;AAAA,EACA,WAAApE,IAAY;AAAA,EACZ,OAAAC;AAAA,EACA,WAAAG;AACF,GAA2B;AACzB,QAAM,CAACiE,GAAeC,CAAgB,IAAIC,EAAyBb,CAAY,GACzE,CAACc,GAAeC,CAAgB,IAAIF,EAAyBZ,CAAY,GAEzEe,IAAed,MAAoB,SAAYA,IAAkBS,GACjEM,IAAeb,MAAoB,SAAYA,IAAkBU,GAEjEI,IAAoB,CAAC1B,GAAaC,MAAyB;AAC/D,IAAIS,MAAoB,UAAWU,EAAiBpB,CAAG,GACvDW,KAAA,QAAAA,EAAgBX,GAAKC;AAAA,EACvB,GAEM0B,IAAoB,CAAC3B,GAAaC,MAAyB;AAC/D,IAAIW,MAAoB,UAAWW,EAAiBvB,CAAG,GACvDa,KAAA,QAAAA,EAAgBb,GAAKC;AAAA,EACvB,GAEM2B,IAAiB,OAAOjF,KAAW,WAAW,GAAGA,CAAM,OAAOA;AAEpE,2BACG,OAAA,EAAI,WAAW,sBAAsBG,CAAS,IAAI,OAAAC,GACjD,UAAA;AAAA,IAAA,gBAAA8B,EAAC,SAAI,WAAU,0BAAyB,OAAO,EAAE,QAAQ+C,KACvD,UAAA,gBAAA/C;AAAA,MAACpD;AAAA,MAAA;AAAA,QACC,KAAKyB;AAAA,QACL,KAAArB;AAAA,QACA,QAAAC;AAAA,QACA,YAAY0F;AAAA,QACZ,YAAYC;AAAA,QACZ,YAAAhF;AAAA,QACA,SAAAC;AAAA,QACA,KAAAH;AAAA,QACA,SAAAC;AAAA,QACA,UAAAyE;AAAA,QACA,gBAAAC;AAAA,MAAA;AAAA,IAAA,GAEJ;AAAA,IAECF,MAAoB,UACnB,gBAAAnC,EAAC,OAAA,EAAI,WAAU,0BACZ,UAAAmC,MAAoB,WACnB,gBAAAtB,EAAAmC,GAAA,EACE,UAAA;AAAA,MAAA,gBAAAhD;AAAA,QAACe;AAAA,QAAA;AAAA,UACC,OAAO4B;AAAA,UACP,UAAUE;AAAA,UACV,SAASZ;AAAA,QAAA;AAAA,MAAA;AAAA,MAEX,gBAAAjC;AAAA,QAACyB;AAAA,QAAA;AAAA,UACC,OAAOmB;AAAA,UACP,UAAUE;AAAA,UACV,SAASZ;AAAA,QAAA;AAAA,MAAA;AAAA,IACX,EAAA,CACF,IAEA,gBAAArB,EAAAmC,GAAA,EACE,UAAA;AAAA,MAAA,gBAAAhD;AAAA,QAACC;AAAA,QAAA;AAAA,UACC,OAAO0C;AAAA,UACP,UAAUE;AAAA,UACV,SAASZ;AAAA,UACT,SAASE;AAAA,QAAA;AAAA,MAAA;AAAA,MAEX,gBAAAnC;AAAA,QAACqB;AAAA,QAAA;AAAA,UACC,OAAOuB;AAAA,UACP,UAAUE;AAAA,UACV,SAASZ;AAAA,UACT,SAASC;AAAA,QAAA;AAAA,MAAA;AAAA,IACX,EAAA,CACF,EAAA,CAEJ;AAAA,EAAA,GAEJ;AAEJ;ACnGO,SAASc,GACdxF,IAAuC,IACX;AAC5B,QAAM;AAAA,IACJ,cAAAkE,IAAe;AAAA,IACf,cAAAC,IAAe;AAAA,IACf,cAAAK,IAAe7B;AAAA,IACf,cAAA8B,IAAeZ;AAAA,EAAA,IACb7D,GAEE,CAACyF,GAAOC,CAAQ,IAAIX,EAAyBb,CAAY,GACzD,CAACyB,GAAOC,CAAQ,IAAIb,EAAyBZ,CAAY,GAEzD0B,IAAcC,EAAQ,MAAM5C,EAAeuC,CAAK,GAAG,CAACA,CAAK,CAAC,GAC1DM,IAAcD,EAAQ,MAAM/B,EAAe4B,CAAK,GAAG,CAACA,CAAK,CAAC,GAE1DK,IAAcF;AAAA,IAClB,OAAO;AAAA,MACL,YAAYL;AAAA,MACZ,YAAYE;AAAA,IAAA;AAAA,IAEd,CAACF,GAAOE,CAAK;AAAA,EAAA;AAGf,SAAO;AAAA,IACL,OAAAF;AAAA,IACA,UAAAC;AAAA,IACA,OAAAC;AAAA,IACA,UAAAC;AAAA,IACA,aAAAC;AAAA,IACA,aAAAE;AAAA,IACA,cAAAvB;AAAA,IACA,cAAAC;AAAA,IACA,aAAAuB;AAAA,EAAA;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/Viewer.tsx","../src/swatches/MetalSwatches.tsx","../src/swatches/StoneSwatches.tsx","../src/swatches/JewelryCustomizer.tsx","../src/swatches/useJewelryCustomizer.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\nimport { useRef, useEffect, forwardRef, useImperativeHandle, type CSSProperties } from 'react'\nimport {\n createViewer,\n normalizeModelSource,\n type Viewer as CoreViewer,\n type ModelSource,\n type ViewerSourceInput,\n type MetalColorProp,\n type StoneColorProp,\n type ViewerOptions,\n type ViewerState,\n type PartInfo,\n type MaterialSlotInfo,\n type PartType,\n} from '@thinkersteps_labs/3d-viewer-core'\n\nexport interface ViewerRef extends CoreViewer { }\n\nexport interface ViewerProps {\n /** 3D model URL or source object. Takes precedence over `source` if both provided. */\n src?: string\n /** 3D model source (URL string, ModelSource payload, or null). */\n source?: ViewerSourceInput\n /** Metal preset ID or hex code. IDE autocompletes standard presets. */\n metalColor?: MetalColorProp\n /** Stone preset ID or hex code. IDE autocompletes standard presets. */\n stoneColor?: StoneColorProp\n /** Bulk material name or slot ID color overrides. */\n materialColors?: Record<string, string>\n /** Part color overrides keyed by partId or partId:slotIndex. */\n partColors?: Record<string, string>\n background?: string | number\n metalEnvUrl?: string | ArrayBuffer\n gemEnvUrl?: string | ArrayBuffer\n options?: ViewerOptions\n fov?: number\n shadows?: boolean\n autoRotate?: boolean\n quality?: 'low' | 'medium' | 'high'\n /** Explicit container height (e.g. 520 or '520px'). Prevents zero-height collapse. */\n height?: number | string\n /** Explicit container min-height. */\n minHeight?: number | string\n /** Aspect ratio for responsive sizing (e.g. '16/9' or '4/3'). */\n aspectRatio?: string\n onLoaded?: (parts: PartInfo[], materials?: MaterialSlotInfo[]) => void\n onPartSelected?: (info: {\n meshId: string\n partId?: string\n type: PartType\n slotIndex?: number\n slotId?: string\n materialName?: string\n }) => void\n onChange?: (state: ViewerState) => void\n onError?: (err: Error) => void\n onProgress?: (progress: number) => void\n className?: string\n style?: CSSProperties\n}\n\nexport const Viewer = forwardRef<ViewerRef, ViewerProps>(function Viewer(props, ref) {\n const {\n src,\n source,\n metalColor,\n stoneColor,\n materialColors,\n partColors,\n background,\n metalEnvUrl,\n gemEnvUrl,\n options,\n fov,\n shadows,\n autoRotate,\n quality,\n height,\n minHeight,\n aspectRatio,\n className,\n style,\n } = props\n const containerRef = useRef<HTMLDivElement>(null)\n const viewerRef = useRef<ViewerRef | null>(null)\n const cb = useRef(props)\n cb.current = props\n\n useImperativeHandle(ref, () => viewerRef.current!, [])\n\n useEffect(() => {\n if (!containerRef.current) return\n const viewer = createViewer(containerRef.current, {\n ...options,\n ...(background !== undefined && { background }),\n ...(fov !== undefined && { fov }),\n ...(shadows !== undefined && { shadows }),\n ...(autoRotate !== undefined && { autoRotate }),\n ...(quality !== undefined && { quality }),\n ...(metalEnvUrl !== undefined && { metalEnvUrl }),\n ...(gemEnvUrl !== undefined && { gemEnvUrl }),\n })\n viewerRef.current = viewer\n if (import.meta.env.DEV && typeof window !== 'undefined') (window as any).__viewer = viewer\n if (ref) {\n if (typeof ref === 'function') ref(viewer)\n else (ref as any).current = viewer\n }\n viewer.on('loaded', ({ parts, materials }) => cb.current.onLoaded?.(parts, materials))\n viewer.on('partSelected', (info) => cb.current.onPartSelected?.(info))\n viewer.on('change', (state) => cb.current.onChange?.(state))\n viewer.on('error', (err) => cb.current.onError?.(err))\n viewer.on('loading', ({ progress }) => cb.current.onProgress?.(progress))\n return () => {\n viewer.dispose()\n if (ref) {\n if (typeof ref === 'function') ref(null)\n else (ref as any).current = null\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n useEffect(() => {\n if (!viewerRef.current) return\n const resolved = normalizeModelSource(src ?? source)\n if (!resolved) {\n viewerRef.current.unload()\n return\n }\n const ac = new AbortController()\n viewerRef.current.load(resolved, { signal: ac.signal })\n return () => ac.abort()\n }, [src, source])\n\n useEffect(() => {\n if (metalColor) viewerRef.current?.setMetalColor(metalColor)\n }, [metalColor])\n\n useEffect(() => {\n if (stoneColor) viewerRef.current?.setStoneColor(stoneColor)\n }, [stoneColor])\n\n const prevMaterialColorsRef = useRef<Record<string, string>>({})\n useEffect(() => {\n if (!viewerRef.current) return\n const prev = prevMaterialColorsRef.current\n const next = materialColors ?? {}\n\n for (const key of Object.keys(prev)) {\n if (!(key in next)) {\n viewerRef.current.clearMaterialColor(key)\n }\n }\n for (const [key, color] of Object.entries(next)) {\n if (prev[key] !== color) {\n viewerRef.current.setMaterialColor(key, color)\n }\n }\n prevMaterialColorsRef.current = { ...next }\n }, [materialColors])\n\n const prevPartColorsRef = useRef<Record<string, string>>({})\n useEffect(() => {\n if (!viewerRef.current) return\n const prev = prevPartColorsRef.current\n const next = partColors ?? {}\n\n for (const key of Object.keys(prev)) {\n if (!(key in next)) {\n if (key.includes(':')) {\n const [partId, slotIdxStr] = key.split(':')\n const slotIndex = parseInt(slotIdxStr ?? '', 10)\n viewerRef.current.clearPartColor(partId ?? '', isNaN(slotIndex) ? undefined : slotIndex)\n } else {\n viewerRef.current.clearPartColor(key)\n }\n }\n }\n for (const [key, color] of Object.entries(next)) {\n if (prev[key] !== color) {\n if (key.includes(':')) {\n const [partId, slotIdxStr] = key.split(':')\n const slotIndex = parseInt(slotIdxStr ?? '', 10)\n viewerRef.current.setPartColor(partId ?? '', color, isNaN(slotIndex) ? undefined : slotIndex)\n } else {\n viewerRef.current.setPartColor(key, color)\n }\n }\n }\n prevPartColorsRef.current = { ...next }\n }, [partColors])\n\n useEffect(() => {\n if (!viewerRef.current) return\n if (autoRotate) viewerRef.current.startRotation()\n else viewerRef.current.stopRotation()\n }, [autoRotate])\n\n useEffect(() => {\n if (quality) viewerRef.current?.setQuality(quality)\n }, [quality])\n\n const containerStyle: CSSProperties = {\n width: '100%',\n height: height !== undefined ? (typeof height === 'number' ? `${height}px` : height) : '100%',\n minHeight: minHeight !== undefined ? (typeof minHeight === 'number' ? `${minHeight}px` : minHeight) : undefined,\n aspectRatio,\n position: 'relative',\n ...style,\n }\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={containerStyle}\n />\n )\n})\n\nexport default Viewer\n","import React, { type CSSProperties } from 'react'\nimport {\n CANONICAL_METAL_PRESETS,\n getMetalPreset,\n type MetalPreset,\n type MetalColorProp,\n} from '@thinkersteps_labs/3d-viewer-core'\nimport './swatches.css'\n\nexport interface MetalSwatchesProps {\n value?: MetalColorProp\n onChange?: (metalId: string, preset?: MetalPreset) => void\n options?: MetalPreset[]\n category?: 'all' | 'gold' | 'platinum-silver' | 'alternative'\n variant?: 'pills' | 'dots'\n showLabel?: boolean\n className?: string\n style?: CSSProperties\n}\n\nexport function MetalSwatches({\n value,\n onChange,\n options = CANONICAL_METAL_PRESETS,\n category = 'all',\n variant = 'pills',\n showLabel = true,\n className = '',\n style,\n}: MetalSwatchesProps) {\n const filteredOptions = category === 'all'\n ? options\n : options.filter((m) => m.category === category)\n\n const activePreset = value ? getMetalPreset(value) : undefined\n const activeId = activePreset?.id ?? value\n\n return (\n <div className={`td-swatch-group ${className}`} style={style}>\n {showLabel && (\n <div className=\"td-swatch-header\">\n <span className=\"td-swatch-title\">Metal</span>\n {activePreset && (\n <span className=\"td-swatch-selected-name\">{activePreset.label}</span>\n )}\n </div>\n )}\n <div className=\"td-swatch-row\" role=\"radiogroup\" aria-label=\"Metal Selection\">\n {filteredOptions.map((m) => {\n const isSelected = activeId === m.id || value === m.hex\n return (\n <button\n key={m.id}\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n title={m.label}\n className={`td-swatch-${variant === 'dots' ? 'dot' : 'pill'} ${isSelected ? 'active' : ''}`}\n onClick={() => onChange?.(m.id, m)}\n >\n <span\n className=\"td-swatch-color-circle\"\n style={{ backgroundColor: m.hex }}\n />\n {variant === 'pills' && <span>{m.label}</span>}\n </button>\n )\n })}\n </div>\n </div>\n )\n}\n\nexport interface MetalSelectProps {\n value?: MetalColorProp\n onChange?: (metalId: string, preset?: MetalPreset) => void\n options?: MetalPreset[]\n label?: string\n className?: string\n style?: CSSProperties\n}\n\nexport function MetalSelect({\n value,\n onChange,\n options = CANONICAL_METAL_PRESETS,\n label = 'Select Metal',\n className = '',\n style,\n}: MetalSelectProps) {\n const activePreset = value ? getMetalPreset(value) : undefined\n const activeValue = activePreset?.id ?? value ?? options[0]?.id\n\n return (\n <div className={`td-select-wrapper ${className}`} style={style}>\n {label && <label className=\"td-swatch-title\">{label}</label>}\n <select\n className=\"td-select\"\n value={activeValue}\n onChange={(e) => {\n const val = e.target.value\n const preset = getMetalPreset(val)\n onChange?.(val, preset)\n }}\n >\n {options.map((m) => (\n <option key={m.id} value={m.id}>\n {m.label}\n </option>\n ))}\n </select>\n </div>\n )\n}\n","import React, { type CSSProperties } from 'react'\nimport {\n CANONICAL_STONE_PRESETS,\n getStonePreset,\n type StonePreset,\n type StoneColorProp,\n} from '@thinkersteps_labs/3d-viewer-core'\nimport './swatches.css'\n\nexport interface StoneSwatchesProps {\n value?: StoneColorProp\n onChange?: (stoneId: string, preset?: StonePreset) => void\n options?: StonePreset[]\n category?: 'all' | 'diamond' | 'gemstone'\n variant?: 'pills' | 'dots'\n showLabel?: boolean\n className?: string\n style?: CSSProperties\n}\n\nexport function StoneSwatches({\n value,\n onChange,\n options = CANONICAL_STONE_PRESETS,\n category = 'all',\n variant = 'pills',\n showLabel = true,\n className = '',\n style,\n}: StoneSwatchesProps) {\n const filteredOptions = category === 'all'\n ? options\n : options.filter((s) => s.category === category)\n\n const activePreset = value ? getStonePreset(value) : undefined\n const activeId = activePreset?.id ?? value\n\n return (\n <div className={`td-swatch-group ${className}`} style={style}>\n {showLabel && (\n <div className=\"td-swatch-header\">\n <span className=\"td-swatch-title\">Gemstone</span>\n {activePreset && (\n <span className=\"td-swatch-selected-name\">\n {activePreset.label}\n {activePreset.grade ? ` (${activePreset.grade})` : ''}\n </span>\n )}\n </div>\n )}\n <div className=\"td-swatch-row\" role=\"radiogroup\" aria-label=\"Gemstone Selection\">\n {filteredOptions.map((s) => {\n const isSelected = activeId === s.id || value === s.hex\n return (\n <button\n key={s.id}\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n title={`${s.label}${s.grade ? ` - ${s.grade}` : ''}`}\n className={`td-swatch-${variant === 'dots' ? 'dot' : 'pill'} ${isSelected ? 'active' : ''}`}\n onClick={() => onChange?.(s.id, s)}\n >\n <span\n className=\"td-swatch-color-circle\"\n style={{ backgroundColor: s.hex }}\n />\n {variant === 'pills' && <span>{s.label}</span>}\n </button>\n )\n })}\n </div>\n </div>\n )\n}\n\nexport interface StoneSelectProps {\n value?: StoneColorProp\n onChange?: (stoneId: string, preset?: StonePreset) => void\n options?: StonePreset[]\n label?: string\n className?: string\n style?: CSSProperties\n}\n\nexport function StoneSelect({\n value,\n onChange,\n options = CANONICAL_STONE_PRESETS,\n label = 'Select Gemstone',\n className = '',\n style,\n}: StoneSelectProps) {\n const activePreset = value ? getStonePreset(value) : undefined\n const activeValue = activePreset?.id ?? value ?? options[0]?.id\n\n return (\n <div className={`td-select-wrapper ${className}`} style={style}>\n {label && <label className=\"td-swatch-title\">{label}</label>}\n <select\n className=\"td-select\"\n value={activeValue}\n onChange={(e) => {\n const val = e.target.value\n const preset = getStonePreset(val)\n onChange?.(val, preset)\n }}\n >\n {options.map((s) => (\n <option key={s.id} value={s.id}>\n {s.label} {s.grade ? `(${s.grade})` : ''}\n </option>\n ))}\n </select>\n </div>\n )\n}\n","import React, { useState, type CSSProperties } from 'react'\nimport {\n type MetalColorProp,\n type StoneColorProp,\n type ViewerSourceInput,\n type MetalPreset,\n type StonePreset,\n type PartInfo,\n type PartType,\n} from '@thinkersteps_labs/3d-viewer-core'\nimport { Viewer, type ViewerRef } from '../Viewer'\nimport { MetalSwatches, MetalSelect } from './MetalSwatches'\nimport { StoneSwatches, StoneSelect } from './StoneSwatches'\nimport './swatches.css'\n\nexport interface JewelryCustomizerProps {\n src?: string\n source?: ViewerSourceInput\n defaultMetal?: MetalColorProp\n defaultStone?: StoneColorProp\n metal?: MetalColorProp\n onMetalChange?: (metal: string, preset?: MetalPreset) => void\n stone?: StoneColorProp\n onStoneChange?: (stone: string, preset?: StonePreset) => void\n metalOptions?: MetalPreset[]\n stoneOptions?: StonePreset[]\n controlsVariant?: 'pills' | 'dots' | 'select' | 'none'\n height?: number | string\n autoRotate?: boolean\n quality?: 'low' | 'medium' | 'high'\n fov?: number\n shadows?: boolean\n onLoaded?: (parts: PartInfo[]) => void\n onPartSelected?: (info: { meshId: string; type: PartType }) => void\n className?: string\n style?: CSSProperties\n viewerRef?: React.Ref<ViewerRef>\n}\n\nexport function JewelryCustomizer({\n src,\n source,\n defaultMetal = 'yellow-gold-18k',\n defaultStone = 'diamond-d',\n metal: controlledMetal,\n onMetalChange,\n stone: controlledStone,\n onStoneChange,\n metalOptions,\n stoneOptions,\n controlsVariant = 'pills',\n height = 520,\n autoRotate = true,\n quality = 'high',\n fov,\n shadows,\n onLoaded,\n onPartSelected,\n className = '',\n style,\n viewerRef,\n}: JewelryCustomizerProps) {\n const [internalMetal, setInternalMetal] = useState<MetalColorProp>(defaultMetal)\n const [internalStone, setInternalStone] = useState<StoneColorProp>(defaultStone)\n\n const currentMetal = controlledMetal !== undefined ? controlledMetal : internalMetal\n const currentStone = controlledStone !== undefined ? controlledStone : internalStone\n\n const handleMetalChange = (val: string, preset?: MetalPreset) => {\n if (controlledMetal === undefined) setInternalMetal(val)\n onMetalChange?.(val, preset)\n }\n\n const handleStoneChange = (val: string, preset?: StonePreset) => {\n if (controlledStone === undefined) setInternalStone(val)\n onStoneChange?.(val, preset)\n }\n\n const viewportHeight = typeof height === 'number' ? `${height}px` : height\n\n return (\n <div className={`td-customizer-card ${className}`} style={style}>\n <div className=\"td-customizer-viewport\" style={{ height: viewportHeight }}>\n <Viewer\n ref={viewerRef}\n src={src}\n source={source}\n metalColor={currentMetal}\n stoneColor={currentStone}\n autoRotate={autoRotate}\n quality={quality}\n fov={fov}\n shadows={shadows}\n onLoaded={onLoaded}\n onPartSelected={onPartSelected}\n />\n </div>\n\n {controlsVariant !== 'none' && (\n <div className=\"td-customizer-controls\">\n {controlsVariant === 'select' ? (\n <>\n <MetalSelect\n value={currentMetal}\n onChange={handleMetalChange}\n options={metalOptions}\n />\n <StoneSelect\n value={currentStone}\n onChange={handleStoneChange}\n options={stoneOptions}\n />\n </>\n ) : (\n <>\n <MetalSwatches\n value={currentMetal}\n onChange={handleMetalChange}\n options={metalOptions}\n variant={controlsVariant}\n />\n <StoneSwatches\n value={currentStone}\n onChange={handleStoneChange}\n options={stoneOptions}\n variant={controlsVariant}\n />\n </>\n )}\n </div>\n )}\n </div>\n )\n}\n","import { useState, useMemo } from 'react'\nimport {\n CANONICAL_METAL_PRESETS,\n CANONICAL_STONE_PRESETS,\n getMetalPreset,\n getStonePreset,\n type MetalColorProp,\n type StoneColorProp,\n type MetalPreset,\n type StonePreset,\n} from '@thinkersteps_labs/3d-viewer-core'\n\nexport interface UseJewelryCustomizerOptions {\n defaultMetal?: MetalColorProp\n defaultStone?: StoneColorProp\n metalOptions?: MetalPreset[]\n stoneOptions?: StonePreset[]\n}\n\nexport interface UseJewelryCustomizerReturn {\n metal: MetalColorProp\n setMetal: (val: MetalColorProp) => void\n stone: StoneColorProp\n setStone: (val: StoneColorProp) => void\n metalPreset?: MetalPreset\n stonePreset?: StonePreset\n metalOptions: MetalPreset[]\n stoneOptions: StonePreset[]\n viewerProps: {\n metalColor: MetalColorProp\n stoneColor: StoneColorProp\n }\n}\n\nexport function useJewelryCustomizer(\n options: UseJewelryCustomizerOptions = {}\n): UseJewelryCustomizerReturn {\n const {\n defaultMetal = 'yellow-gold-18k',\n defaultStone = 'diamond-d',\n metalOptions = CANONICAL_METAL_PRESETS,\n stoneOptions = CANONICAL_STONE_PRESETS,\n } = options\n\n const [metal, setMetal] = useState<MetalColorProp>(defaultMetal)\n const [stone, setStone] = useState<StoneColorProp>(defaultStone)\n\n const metalPreset = useMemo(() => getMetalPreset(metal), [metal])\n const stonePreset = useMemo(() => getStonePreset(stone), [stone])\n\n const viewerProps = useMemo(\n () => ({\n metalColor: metal,\n stoneColor: stone,\n }),\n [metal, stone]\n )\n\n return {\n metal,\n setMetal,\n stone,\n setStone,\n metalPreset,\n stonePreset,\n metalOptions,\n stoneOptions,\n viewerProps,\n }\n}\n"],"names":["Viewer","forwardRef","props","ref","src","source","metalColor","stoneColor","materialColors","partColors","background","metalEnvUrl","gemEnvUrl","options","fov","shadows","autoRotate","quality","height","minHeight","aspectRatio","className","style","containerRef","useRef","viewerRef","cb","useImperativeHandle","useEffect","viewer","createViewer","parts","materials","_b","_a","info","state","err","progress","resolved","normalizeModelSource","ac","prevMaterialColorsRef","prev","next","key","color","prevPartColorsRef","partId","slotIdxStr","slotIndex","containerStyle","jsx","MetalSwatches","value","onChange","CANONICAL_METAL_PRESETS","category","variant","showLabel","filteredOptions","m","activePreset","getMetalPreset","activeId","jsxs","isSelected","MetalSelect","label","activeValue","e","val","preset","StoneSwatches","CANONICAL_STONE_PRESETS","s","getStonePreset","StoneSelect","JewelryCustomizer","defaultMetal","defaultStone","controlledMetal","onMetalChange","controlledStone","onStoneChange","metalOptions","stoneOptions","controlsVariant","onLoaded","onPartSelected","internalMetal","setInternalMetal","useState","internalStone","setInternalStone","currentMetal","currentStone","handleMetalChange","handleStoneChange","viewportHeight","Fragment","useJewelryCustomizer","metal","setMetal","stone","setStone","metalPreset","useMemo","stonePreset","viewerProps"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@thinkersteps_labs/3d-viewer-react",
|
|
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/react"
|
|
9
|
-
},
|
|
10
|
-
"publishConfig": {
|
|
11
|
-
"access": "public"
|
|
12
|
-
},
|
|
13
|
-
"type": "module",
|
|
14
|
-
"main": "./dist/index.cjs",
|
|
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
|
-
"require": "./dist/index.cjs"
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
"files": [
|
|
25
|
-
"dist"
|
|
26
|
-
],
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"@
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@thinkersteps_labs/3d-viewer-react",
|
|
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/react"
|
|
9
|
+
},
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "./dist/index.cjs",
|
|
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
|
+
"require": "./dist/index.cjs"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"react": ">=18.0.0",
|
|
29
|
+
"three": ">=0.150.0",
|
|
30
|
+
"@thinkersteps_labs/3d-viewer-core": "1.1.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^20.11.0",
|
|
34
|
+
"@types/react": "^18.2.0",
|
|
35
|
+
"@vitejs/plugin-react": "^4.2.0",
|
|
36
|
+
"react": "^18.2.0",
|
|
37
|
+
"three": "^0.160.0",
|
|
38
|
+
"vite": "^5.0.0",
|
|
39
|
+
"vite-plugin-dts": "^3.7.0",
|
|
40
|
+
"@thinkersteps_labs/3d-viewer-core": "1.1.0"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "vite build",
|
|
44
|
+
"typecheck": "tsc --noEmit"
|
|
45
|
+
}
|
|
46
46
|
}
|