@virtualdisplay.io/client 3.5.1 → 3.7.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/CHANGELOG.md +16 -0
- package/README.md +16 -421
- package/README.npm.md +16 -421
- package/dist/index.d.ts +108 -13
- package/dist/virtualdisplay.client.cjs.js +3 -3
- package/dist/virtualdisplay.client.cjs.js.map +1 -1
- package/dist/virtualdisplay.client.es.js +278 -68
- package/dist/virtualdisplay.client.es.js.map +1 -1
- package/dist/virtualdisplay.client.umd.js +3 -3
- package/dist/virtualdisplay.client.umd.js.map +1 -1
- package/package.json +11 -11
package/README.npm.md
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
# Virtualdisplay client
|
|
2
2
|
|
|
3
|
-
TypeScript library for embedding interactive 3D product models in web
|
|
4
|
-
applications.
|
|
5
|
-
|
|
6
|
-
**Key features:**
|
|
7
|
-
|
|
8
|
-
- Simple attribute-based API for product configurators
|
|
9
|
-
- Fire-and-forget messaging with automatic state synchronization
|
|
10
|
-
- Zero external dependencies (all bundled)
|
|
11
|
-
- Works with any frontend framework or vanilla JavaScript
|
|
3
|
+
TypeScript library for embedding interactive 3D product models in web applications.
|
|
12
4
|
|
|
13
5
|
## Installation
|
|
14
6
|
|
|
@@ -20,14 +12,6 @@ pnpm add @virtualdisplay.io/client
|
|
|
20
12
|
yarn add @virtualdisplay.io/client
|
|
21
13
|
```
|
|
22
14
|
|
|
23
|
-
## What's new in v3.1
|
|
24
|
-
|
|
25
|
-
- Simplified message handling with unified event system
|
|
26
|
-
- JSON Schema validation using AJV
|
|
27
|
-
- Cleaner, more maintainable codebase
|
|
28
|
-
- Improved TypeScript types
|
|
29
|
-
- Better error messages with specific error codes
|
|
30
|
-
|
|
31
15
|
## Quick start
|
|
32
16
|
|
|
33
17
|
### Simple product (no options)
|
|
@@ -70,414 +54,25 @@ client.setMapping({
|
|
|
70
54
|
|
|
71
55
|
// Control via product options
|
|
72
56
|
client.getAttribute('Color')?.select('Red');
|
|
73
|
-
|
|
74
|
-
// Or store the attribute for multiple operations
|
|
75
|
-
const sizeAttribute = client.getAttribute('Size');
|
|
76
|
-
if (sizeAttribute) {
|
|
77
|
-
sizeAttribute.select('Large');
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## How it works
|
|
82
|
-
|
|
83
|
-
The 3D server hosts the viewer in an iframe, keeping WebGL complexity isolated
|
|
84
|
-
from your application. The client library handles all communication via
|
|
85
|
-
postMessage and manages state locally using an attribute mapping system.
|
|
86
|
-
|
|
87
|
-
**Key principles:**
|
|
88
|
-
|
|
89
|
-
- **Iframe architecture**: 3D server loads the viewer independently
|
|
90
|
-
- **Fire-and-forget**: Send messages without waiting for confirmation
|
|
91
|
-
- **Attribute mapping**: Connect your product options to 3D model parts
|
|
92
|
-
- **State synchronization**: Client and 3D server stay in sync automatically
|
|
93
|
-
- **Domain-driven design**: Clean separation of concerns with simplified
|
|
94
|
-
architecture
|
|
95
|
-
- **Event-driven**: Loosely coupled components communicate via events
|
|
96
|
-
|
|
97
|
-
## Product options
|
|
98
|
-
|
|
99
|
-
### When do you need mapping
|
|
100
|
-
|
|
101
|
-
Before diving in, it's important to understand when you need attribute mapping:
|
|
102
|
-
|
|
103
|
-
**No mapping needed:**
|
|
104
|
-
|
|
105
|
-
- Static 3D models that always look the same
|
|
106
|
-
- Product showcases without options
|
|
107
|
-
- Architectural visualizations
|
|
108
|
-
- Art pieces or sculptures
|
|
109
|
-
- Single-configuration products
|
|
110
|
-
|
|
111
|
-
**Mapping required:**
|
|
112
|
-
|
|
113
|
-
- Products where users can change colors (different textures/materials per option)
|
|
114
|
-
- Products with size options (different 3D meshes per size)
|
|
115
|
-
- Modular products (parts that can be added/removed)
|
|
116
|
-
- Any product where different options show different 3D elements
|
|
117
|
-
|
|
118
|
-
### Attribute mapping
|
|
119
|
-
|
|
120
|
-
The mapping system bridges your business logic with the 3D visualization. It
|
|
121
|
-
serves multiple purposes:
|
|
122
|
-
|
|
123
|
-
**Why mapping is essential:**
|
|
124
|
-
|
|
125
|
-
- The 3D server is generic - it doesn't know your specific product options
|
|
126
|
-
- Your business rules (stock, pricing, combinations) change independently from
|
|
127
|
-
the 3D model
|
|
128
|
-
- You control exactly which parts of the model are shown for each option
|
|
129
|
-
- You can group multiple 3D nodes (meshes, materials) into logical product
|
|
130
|
-
choices
|
|
131
|
-
|
|
132
|
-
**How it works:** The mapping connects your product options to specific parts of
|
|
133
|
-
the 3D model:
|
|
134
|
-
|
|
135
|
-
```typescript
|
|
136
|
-
client.setMapping({
|
|
137
|
-
attributes: [
|
|
138
|
-
{
|
|
139
|
-
name: 'Color',
|
|
140
|
-
values: [
|
|
141
|
-
{
|
|
142
|
-
value: 'Red',
|
|
143
|
-
nodeIds: ['mat_red_sole', 'mat_red_laces', 'mat_red_logo'],
|
|
144
|
-
isSelected: true,
|
|
145
|
-
},
|
|
146
|
-
{
|
|
147
|
-
value: 'Blue',
|
|
148
|
-
nodeIds: ['mat_blue_sole', 'mat_blue_laces', 'mat_blue_logo'],
|
|
149
|
-
},
|
|
150
|
-
],
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
name: 'Material',
|
|
154
|
-
values: [
|
|
155
|
-
{ value: 'Leather', nodeIds: ['material_leather_upper'] },
|
|
156
|
-
{
|
|
157
|
-
value: 'Canvas',
|
|
158
|
-
nodeIds: ['material_canvas_upper'],
|
|
159
|
-
isSelected: true,
|
|
160
|
-
},
|
|
161
|
-
],
|
|
162
|
-
},
|
|
163
|
-
],
|
|
164
|
-
});
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
**Structure explained:**
|
|
168
|
-
|
|
169
|
-
- `attribute` - A product feature like Color, Size, or Material
|
|
170
|
-
- `value` - A specific option like Red, Blue, Small, or Large
|
|
171
|
-
- `nodeIds` - The 3D model parts that represent this option
|
|
172
|
-
- `isSelected` - Whether this option is selected by default
|
|
173
|
-
|
|
174
|
-
**Example benefits:**
|
|
175
|
-
|
|
176
|
-
```typescript
|
|
177
|
-
// Group related 3D parts into one logical choice
|
|
178
|
-
{
|
|
179
|
-
value: 'Red',
|
|
180
|
-
nodeIds: [
|
|
181
|
-
'mesh_sole_red', // Red sole mesh
|
|
182
|
-
'material_laces_red', // Red laces material
|
|
183
|
-
'texture_logo_red', // Red logo texture
|
|
184
|
-
'mesh_stitching_red' // Red stitching details
|
|
185
|
-
]
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// The server automatically handles showing Red parts
|
|
189
|
-
// and hiding Blue/Green parts when Red is selected
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
**Key advantages:**
|
|
193
|
-
|
|
194
|
-
- Full control over what's visible without modifying the 3D model
|
|
195
|
-
- Business logic stays in your application, not in the 3D server
|
|
196
|
-
- Easy to update when products or availability changes
|
|
197
|
-
- Group complex 3D structures into simple user choices
|
|
198
|
-
|
|
199
|
-
**Need help with mapping?**
|
|
200
|
-
|
|
201
|
-
- We help you connect your product catalog to your 3D models
|
|
202
|
-
- Visual mapping tool coming soon to simplify this process
|
|
203
|
-
- Contact <support@virtualdisplay.io> for mapping assistance
|
|
204
|
-
|
|
205
|
-
### Complete flow
|
|
206
|
-
|
|
207
|
-
Here's how the client, mapping system, and 3D server work together:
|
|
208
|
-
|
|
209
|
-
**Phase by phase breakdown:**
|
|
210
|
-
|
|
211
|
-
#### Phase 0: Initialization (always happens)
|
|
212
|
-
|
|
213
|
-
- Client creates iframe and loads 3D server
|
|
214
|
-
- Server initializes the 3D model with all nodes visible
|
|
215
|
-
- Server sends complete node state to client
|
|
216
|
-
- Client now knows about all available nodes in the model
|
|
217
|
-
|
|
218
|
-
**Note:** For simple models without options, this is all you need!
|
|
219
|
-
|
|
220
|
-
#### Phase 1: Configuration (only for configurable products)
|
|
221
|
-
|
|
222
|
-
- You call `setMapping()` with your product structure
|
|
223
|
-
- Client stores the attribute mapping locally
|
|
224
|
-
- Client sends mutations for all `isSelected: true` values
|
|
225
|
-
- Server applies these changes and hides non-selected options
|
|
226
|
-
- Server sends back confirmed state
|
|
227
|
-
- Local state updates based on server response
|
|
228
|
-
- onChange callbacks fire for initial UI synchronization
|
|
229
|
-
|
|
230
|
-
#### Phase 2: User interaction (only for configurable products)
|
|
231
|
-
|
|
232
|
-
- User selects a different option in your UI
|
|
233
|
-
- You call `getAttribute('Color').select('Blue')`
|
|
234
|
-
- Client sends mutation request to server
|
|
235
|
-
- Your code continues immediately (doesn't wait for server response)
|
|
236
|
-
- Server updates the 3D model
|
|
237
|
-
- Server sends back the confirmed state
|
|
238
|
-
- Local state updates based on server response
|
|
239
|
-
- onChange callbacks fire with the actual state
|
|
240
|
-
- UI stays perfectly synchronized with 3D model
|
|
241
|
-
|
|
242
|
-
**Important:** The pattern is identical for both initial mapping and user
|
|
243
|
-
interactions. In both cases:
|
|
244
|
-
|
|
245
|
-
1. Client sends mutations to server
|
|
246
|
-
2. Server applies changes to 3D model
|
|
247
|
-
3. Server sends back confirmed state
|
|
248
|
-
4. Client updates local state based on server response
|
|
249
|
-
5. onChange callbacks fire with the actual state
|
|
250
|
-
|
|
251
|
-
This ensures the server remains the single source of truth for all state
|
|
252
|
-
changes.
|
|
253
|
-
|
|
254
|
-
## Advanced usage
|
|
255
|
-
|
|
256
|
-
### Live state synchronization
|
|
257
|
-
|
|
258
|
-
Keep your UI in sync with the 3D server state using onChange callbacks:
|
|
259
|
-
|
|
260
|
-
```typescript
|
|
261
|
-
const colorAttribute = client.getAttribute('Color');
|
|
262
|
-
|
|
263
|
-
colorAttribute?.getValues().forEach((value) => {
|
|
264
|
-
value.onChange = () => {
|
|
265
|
-
// Update UI when state changes
|
|
266
|
-
updateButton(value.value, value.isSelected);
|
|
267
|
-
};
|
|
268
|
-
});
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
### Mapping validation
|
|
272
|
-
|
|
273
|
-
Validate your mapping configuration during development:
|
|
274
|
-
|
|
275
|
-
```typescript
|
|
276
|
-
import { mappingSchema } from '@virtualdisplay.io/client';
|
|
277
|
-
import Ajv from 'ajv';
|
|
278
|
-
|
|
279
|
-
const validate = new Ajv().compile(mappingSchema);
|
|
280
|
-
if (!validate(myMapping)) {
|
|
281
|
-
console.error('Invalid mapping:', validate.errors);
|
|
282
|
-
}
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
## Real-world integration examples
|
|
286
|
-
|
|
287
|
-
### CMS integration
|
|
288
|
-
|
|
289
|
-
The Virtualdisplay client is CMS-agnostic. Store the mapping configuration in
|
|
290
|
-
your CMS alongside your product data:
|
|
291
|
-
|
|
292
|
-
```typescript
|
|
293
|
-
// Fetch product with 3D mapping from your CMS
|
|
294
|
-
const product = await fetch('/api/products/sneaker-pro').then((r) => r.json());
|
|
295
|
-
|
|
296
|
-
// Use the stored mapping directly
|
|
297
|
-
client.setMapping(product.server3dMapping);
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
**Best practices:**
|
|
301
|
-
|
|
302
|
-
- Store the complete mapping configuration with each product
|
|
303
|
-
- Update mappings when product options or availability changes
|
|
304
|
-
- Let your CMS handle filtering of unavailable combinations
|
|
305
|
-
- Version your mappings when 3D models are updated
|
|
306
|
-
|
|
307
|
-
## Example
|
|
308
|
-
|
|
309
|
-
See the [color configurator example](./examples/color-configurator/) for a
|
|
310
|
-
complete working implementation that demonstrates:
|
|
311
|
-
|
|
312
|
-
- Setting up the client
|
|
313
|
-
- Defining attribute mappings
|
|
314
|
-
- Binding UI controls to attributes
|
|
315
|
-
- Real-time state synchronization
|
|
316
|
-
|
|
317
|
-
## API reference
|
|
318
|
-
|
|
319
|
-
### ClientOptions
|
|
320
|
-
|
|
321
|
-
```typescript
|
|
322
|
-
interface ClientOptions {
|
|
323
|
-
parent: string | HTMLElement; // Container element or selector
|
|
324
|
-
license: string; // Your license key
|
|
325
|
-
model: string; // Model ID to load
|
|
326
|
-
debug?: boolean; // Enable debug logging (default: false)
|
|
327
|
-
language?: string; // Language for UI inside the iframe (default: 'nl', supported: 'nl', 'en', 'de')
|
|
328
|
-
}
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
### Methods
|
|
332
|
-
|
|
333
|
-
#### `setMapping(configuration: MappingConfiguration): void`
|
|
334
|
-
|
|
335
|
-
Configure attribute-to-node mapping for product variants. This is the primary
|
|
336
|
-
method for setting up your product configurator. Call this once with your
|
|
337
|
-
complete configuration - the client efficiently handles all updates.
|
|
338
|
-
|
|
339
|
-
```typescript
|
|
340
|
-
client.setMapping({
|
|
341
|
-
attributes: [
|
|
342
|
-
{
|
|
343
|
-
name: 'Color',
|
|
344
|
-
values: [
|
|
345
|
-
{ value: 'Red', nodeIds: ['node1', 'node2'], isSelected: true },
|
|
346
|
-
{ value: 'Blue', nodeIds: ['node3', 'node4'] },
|
|
347
|
-
],
|
|
348
|
-
},
|
|
349
|
-
],
|
|
350
|
-
});
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
#### `getAttribute(name: string): AttributeSelector | undefined`
|
|
354
|
-
|
|
355
|
-
Get an attribute selector for changing values. Returns undefined if the
|
|
356
|
-
attribute doesn't exist.
|
|
357
|
-
|
|
358
|
-
```typescript
|
|
359
|
-
const colorAttr = client.getAttribute('Color');
|
|
360
|
-
if (colorAttr) {
|
|
361
|
-
colorAttr.select('Blue');
|
|
362
|
-
}
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
#### `destroy(): void`
|
|
366
|
-
|
|
367
|
-
Clean up and remove the client connection. Always call this when unmounting your
|
|
368
|
-
component.
|
|
369
|
-
|
|
370
|
-
```typescript
|
|
371
|
-
// React example
|
|
372
|
-
useEffect(() => {
|
|
373
|
-
const client = new VirtualdisplayClient({ ... });
|
|
374
|
-
return () => client.destroy();
|
|
375
|
-
}, []);
|
|
376
57
|
```
|
|
377
58
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
```typescript
|
|
381
|
-
interface MappingConfiguration {
|
|
382
|
-
attributes: AttributeConfig[];
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
interface AttributeConfig {
|
|
386
|
-
name: string; // Attribute name (e.g., 'Color')
|
|
387
|
-
values: AttributeValueConfig[]; // Possible values
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
interface AttributeValueConfig {
|
|
391
|
-
value: string; // Value name (e.g., 'Red')
|
|
392
|
-
nodeIds: string[]; // 3D node IDs for this value
|
|
393
|
-
isSelected?: boolean; // Default selection state
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
class AttributeSelector {
|
|
397
|
-
// Properties
|
|
398
|
-
name: string; // Attribute name (getter)
|
|
399
|
-
currentValue: string | undefined; // Current selected value (getter)
|
|
400
|
-
availableValues: string[]; // All possible values (getter)
|
|
401
|
-
|
|
402
|
-
// Methods
|
|
403
|
-
select(value: string): AttributeSelector; // Select a value (chainable)
|
|
404
|
-
onChange(callback: () => void): AttributeSelector; // Register change callback (chainable)
|
|
405
|
-
getValues(): AttributeValue[]; // Get all AttributeValue objects
|
|
406
|
-
getValue(value: string): AttributeValue | undefined; // Get specific AttributeValue
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
class AttributeValue {
|
|
410
|
-
// Properties
|
|
411
|
-
value: string; // The value name (e.g., 'Red') - getter
|
|
412
|
-
nodeList: string[]; // Associated 3D node IDs - getter
|
|
413
|
-
isSelected: boolean; // Current selection state - getter
|
|
414
|
-
onChange?: () => void; // Callback when selection changes - property
|
|
415
|
-
}
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
#### NodeSelector
|
|
419
|
-
|
|
420
|
-
The client exports `NodeSelector` for direct node manipulation. This is intended
|
|
421
|
-
for specialized tools like mapping editors and inspectors, not for typical
|
|
422
|
-
product configurators. For product configurators, use the attribute-based API.
|
|
423
|
-
|
|
424
|
-
### Error handling
|
|
425
|
-
|
|
426
|
-
The client throws `VirtualdisplayError` for known error conditions:
|
|
427
|
-
|
|
428
|
-
```typescript
|
|
429
|
-
import {
|
|
430
|
-
VirtualdisplayClient,
|
|
431
|
-
VirtualdisplayError,
|
|
432
|
-
ERROR_CODES,
|
|
433
|
-
} from '@virtualdisplay.io/client';
|
|
434
|
-
|
|
435
|
-
try {
|
|
436
|
-
client.getAttribute('NonExistent').select('Value');
|
|
437
|
-
} catch (error) {
|
|
438
|
-
if (error instanceof VirtualdisplayError) {
|
|
439
|
-
switch (error.code) {
|
|
440
|
-
case ERROR_CODES.ATTRIBUTE_NOT_FOUND:
|
|
441
|
-
console.error('Attribute does not exist');
|
|
442
|
-
break;
|
|
443
|
-
case ERROR_CODES.NO_MAPPING:
|
|
444
|
-
console.error('Call setMapping() first');
|
|
445
|
-
break;
|
|
446
|
-
// Handle other error codes
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
**Error codes:**
|
|
453
|
-
|
|
454
|
-
- `NO_MAPPING` - No mapping configuration set
|
|
455
|
-
- `ATTRIBUTE_NOT_FOUND` - Requested attribute doesn't exist
|
|
456
|
-
- `VALUE_NOT_FOUND` - Requested value doesn't exist for attribute
|
|
457
|
-
- `INVALID_MAPPING` - Mapping configuration is invalid
|
|
458
|
-
- `PARENT_NOT_FOUND` - Parent element for iframe not found
|
|
459
|
-
|
|
460
|
-
## Contributing
|
|
461
|
-
|
|
462
|
-
See [CONTRIBUTING.md](./CONTRIBUTING.md) for development setup and guidelines.
|
|
463
|
-
|
|
464
|
-
## Troubleshooting
|
|
465
|
-
|
|
466
|
-
### Common issues
|
|
467
|
-
|
|
468
|
-
**Iframe not loading:**
|
|
59
|
+
## Key features
|
|
469
60
|
|
|
470
|
-
-
|
|
471
|
-
-
|
|
472
|
-
-
|
|
61
|
+
- **Simple API**: Attribute-based product configuration
|
|
62
|
+
- **Fire-and-forget**: Send commands without waiting for responses
|
|
63
|
+
- **State sync**: Automatic synchronization between client and 3D viewer
|
|
64
|
+
- **Framework-agnostic**: Works with React, Vue, Angular, or vanilla JS
|
|
65
|
+
- **TypeScript first**: Full type safety and IntelliSense support
|
|
66
|
+
- **Minimal dependencies**: Only essential validation and logging included
|
|
473
67
|
|
|
474
|
-
|
|
68
|
+
## Documentation
|
|
475
69
|
|
|
476
|
-
|
|
477
|
-
- Verify attribute names match exactly (case-sensitive)
|
|
478
|
-
- Check that node IDs in your mapping exist in the 3D model
|
|
70
|
+
For complete documentation including:
|
|
479
71
|
|
|
480
|
-
|
|
72
|
+
- API reference
|
|
73
|
+
- Advanced examples
|
|
74
|
+
- Integration guides
|
|
75
|
+
- Architecture diagrams
|
|
76
|
+
- Troubleshooting
|
|
481
77
|
|
|
482
|
-
|
|
483
|
-
for release notes and version history.
|
|
78
|
+
Visit our [GitHub repository](https://github.com/virtualdisplay-io/client)
|
package/dist/index.d.ts
CHANGED
|
@@ -9,11 +9,6 @@ declare class Attribute {
|
|
|
9
9
|
private readonly values;
|
|
10
10
|
constructor(name: string);
|
|
11
11
|
addValue(attributeValue: AttributeValue): void;
|
|
12
|
-
/**
|
|
13
|
-
* Select a value - returns mutations needed for the change
|
|
14
|
-
* Pure function - no side effects
|
|
15
|
-
*/
|
|
16
|
-
select(value: string): Mutation[];
|
|
17
12
|
getDefaultMutations(): Mutation[];
|
|
18
13
|
getCurrentValue(): AttributeValue | undefined;
|
|
19
14
|
getValue(valueName: string): AttributeValue | undefined;
|
|
@@ -21,6 +16,7 @@ declare class Attribute {
|
|
|
21
16
|
hasValue(valueName: string): boolean;
|
|
22
17
|
get name(): string;
|
|
23
18
|
get currentSelection(): string | undefined;
|
|
19
|
+
clear(): void;
|
|
24
20
|
}
|
|
25
21
|
|
|
26
22
|
/**
|
|
@@ -28,7 +24,7 @@ declare class Attribute {
|
|
|
28
24
|
*/
|
|
29
25
|
export declare interface AttributeConfig {
|
|
30
26
|
readonly name: string;
|
|
31
|
-
readonly values: AttributeValueConfig[]
|
|
27
|
+
readonly values: DynamicValue<AttributeValueConfig[]>;
|
|
32
28
|
}
|
|
33
29
|
|
|
34
30
|
/**
|
|
@@ -75,9 +71,12 @@ export declare class AttributeSelector {
|
|
|
75
71
|
* Handles business logic and coordinates with other domains via events
|
|
76
72
|
*/
|
|
77
73
|
declare class AttributeService {
|
|
78
|
-
private
|
|
74
|
+
private attributes;
|
|
79
75
|
private readonly eventBus;
|
|
80
76
|
private isInitialized;
|
|
77
|
+
private mappingConfig;
|
|
78
|
+
private readonly selections;
|
|
79
|
+
private readonly currentState;
|
|
81
80
|
constructor(eventBus: EventBus);
|
|
82
81
|
/**
|
|
83
82
|
* Load mapping configuration and apply defaults
|
|
@@ -89,8 +88,48 @@ declare class AttributeService {
|
|
|
89
88
|
getAllAttributes(): Attribute[];
|
|
90
89
|
get initialized(): boolean;
|
|
91
90
|
private syncStateWithAttributes;
|
|
92
|
-
private getAttributeValueForNode;
|
|
93
91
|
clear(): void;
|
|
92
|
+
/**
|
|
93
|
+
* Create context for dynamic evaluation
|
|
94
|
+
*/
|
|
95
|
+
private createContext;
|
|
96
|
+
/**
|
|
97
|
+
* Evaluate a property that might be static or dynamic
|
|
98
|
+
*/
|
|
99
|
+
private evaluateProperty;
|
|
100
|
+
/**
|
|
101
|
+
* Evaluate the entire mapping with current context
|
|
102
|
+
*/
|
|
103
|
+
private evaluateMapping;
|
|
104
|
+
/**
|
|
105
|
+
* Create a single attribute from configuration
|
|
106
|
+
*/
|
|
107
|
+
private createAttributeFromConfig;
|
|
108
|
+
/**
|
|
109
|
+
* Initialize selections from default values
|
|
110
|
+
*/
|
|
111
|
+
private initializeSelections;
|
|
112
|
+
/**
|
|
113
|
+
* Check if the mapping configuration contains dynamic elements
|
|
114
|
+
*/
|
|
115
|
+
private hasDynamicMapping;
|
|
116
|
+
/**
|
|
117
|
+
* Update current state map with visible nodes per attribute
|
|
118
|
+
*/
|
|
119
|
+
private updateCurrentState;
|
|
120
|
+
private getVisibleNodesForAttribute;
|
|
121
|
+
/**
|
|
122
|
+
* Get initial mutations for default selections
|
|
123
|
+
*/
|
|
124
|
+
private getInitialMutations;
|
|
125
|
+
/**
|
|
126
|
+
* Calculate mutations by comparing old and new state
|
|
127
|
+
*/
|
|
128
|
+
private calculateMutations;
|
|
129
|
+
/**
|
|
130
|
+
* Check if a node is visible in the given state
|
|
131
|
+
*/
|
|
132
|
+
private isNodeVisible;
|
|
94
133
|
}
|
|
95
134
|
|
|
96
135
|
/**
|
|
@@ -114,11 +153,12 @@ declare class AttributeValue {
|
|
|
114
153
|
|
|
115
154
|
/**
|
|
116
155
|
* Configuration for a single attribute value
|
|
156
|
+
* All properties can be static or dynamic
|
|
117
157
|
*/
|
|
118
158
|
export declare interface AttributeValueConfig {
|
|
119
|
-
readonly value: string
|
|
120
|
-
readonly nodeIds: string[]
|
|
121
|
-
readonly isSelected?: boolean
|
|
159
|
+
readonly value: DynamicValue<string>;
|
|
160
|
+
readonly nodeIds: DynamicValue<string[]>;
|
|
161
|
+
readonly isSelected?: DynamicValue<boolean>;
|
|
122
162
|
}
|
|
123
163
|
|
|
124
164
|
/**
|
|
@@ -163,6 +203,19 @@ export declare interface CameraCommand {
|
|
|
163
203
|
readonly value?: number;
|
|
164
204
|
}
|
|
165
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Camera configuration options
|
|
208
|
+
*/
|
|
209
|
+
export declare interface CameraConfig {
|
|
210
|
+
readonly initialRotate?: number;
|
|
211
|
+
readonly initialTilt?: number;
|
|
212
|
+
readonly initialZoom?: number;
|
|
213
|
+
readonly minZoom?: number;
|
|
214
|
+
readonly maxZoom?: number;
|
|
215
|
+
readonly minTilt?: number;
|
|
216
|
+
readonly maxTilt?: number;
|
|
217
|
+
}
|
|
218
|
+
|
|
166
219
|
/**
|
|
167
220
|
* Camera message sent to server
|
|
168
221
|
*/
|
|
@@ -183,6 +236,8 @@ export declare interface ClientOptions {
|
|
|
183
236
|
readonly arEnabled?: boolean;
|
|
184
237
|
readonly fullscreenEnabled?: boolean;
|
|
185
238
|
readonly loadingIndicatorEnabled?: boolean;
|
|
239
|
+
readonly ui?: UIConfig;
|
|
240
|
+
readonly camera?: CameraConfig;
|
|
186
241
|
}
|
|
187
242
|
|
|
188
243
|
/**
|
|
@@ -213,6 +268,11 @@ export declare interface DomainEvents extends Record<string, unknown> {
|
|
|
213
268
|
[EVENT_NAMES.INITIAL_STATE_RECEIVED]: VoidEvent;
|
|
214
269
|
}
|
|
215
270
|
|
|
271
|
+
/**
|
|
272
|
+
* A value that can be static or dynamically computed
|
|
273
|
+
*/
|
|
274
|
+
declare type DynamicValue<T> = T | ((context: MappingContext) => T);
|
|
275
|
+
|
|
216
276
|
export declare function enableDebugMode(): void;
|
|
217
277
|
|
|
218
278
|
/**
|
|
@@ -242,7 +302,6 @@ export declare const EVENT_NAMES: {
|
|
|
242
302
|
readonly STATE_CHANGED: "state:changed";
|
|
243
303
|
readonly INITIAL_STATE_RECEIVED: "state:initial-received";
|
|
244
304
|
readonly SNAPSHOT_MESSAGE: "snapshot:take";
|
|
245
|
-
readonly SNAPSHOT_DEVELOPED: "snapshot:developed";
|
|
246
305
|
};
|
|
247
306
|
|
|
248
307
|
/**
|
|
@@ -278,6 +337,14 @@ export declare interface MappingConfiguration {
|
|
|
278
337
|
readonly attributes: AttributeConfig[];
|
|
279
338
|
}
|
|
280
339
|
|
|
340
|
+
/**
|
|
341
|
+
* Context provided to dynamic value functions
|
|
342
|
+
*/
|
|
343
|
+
declare interface MappingContext {
|
|
344
|
+
getValue: (attributeName: string) => string | undefined;
|
|
345
|
+
getAllValues: () => Map<string, string>;
|
|
346
|
+
}
|
|
347
|
+
|
|
281
348
|
export declare const mappingSchema: {
|
|
282
349
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
283
350
|
"title": "Virtualdisplay mapping configuration",
|
|
@@ -356,6 +423,14 @@ export declare class MappingValidator {
|
|
|
356
423
|
* @throws {VirtualdisplayError} When mapping configuration is invalid
|
|
357
424
|
*/
|
|
358
425
|
static validate(config: MappingConfiguration): void;
|
|
426
|
+
/**
|
|
427
|
+
* Check if configuration contains dynamic values (functions)
|
|
428
|
+
*/
|
|
429
|
+
static containsDynamicValues(config: MappingConfiguration): boolean;
|
|
430
|
+
/**
|
|
431
|
+
* Basic structure validation for dynamic mappings
|
|
432
|
+
*/
|
|
433
|
+
private static validateBasicStructure;
|
|
359
434
|
}
|
|
360
435
|
|
|
361
436
|
/**
|
|
@@ -602,6 +677,7 @@ export declare interface UIConfig {
|
|
|
602
677
|
*/
|
|
603
678
|
export declare interface ViewerConfig {
|
|
604
679
|
readonly ui?: UIConfig;
|
|
680
|
+
readonly camera?: CameraConfig;
|
|
605
681
|
}
|
|
606
682
|
|
|
607
683
|
/**
|
|
@@ -687,9 +763,24 @@ export declare class VirtualdisplayViewerService {
|
|
|
687
763
|
constructor(eventBus: EventBus);
|
|
688
764
|
/**
|
|
689
765
|
* Send initial configuration based on client options
|
|
690
|
-
*
|
|
766
|
+
* Supports both individual properties and ui object
|
|
691
767
|
*/
|
|
692
768
|
sendInitialConfig(options: ClientOptions): void;
|
|
769
|
+
/**
|
|
770
|
+
* Build UI configuration from client options
|
|
771
|
+
*
|
|
772
|
+
* Supports both legacy properties (options.arEnabled) and the newer ui object
|
|
773
|
+
* for backward compatibility. Legacy properties take precedence when both exist.
|
|
774
|
+
*/
|
|
775
|
+
private buildUIConfig;
|
|
776
|
+
/**
|
|
777
|
+
* Extract UI values from options, with legacy properties taking precedence
|
|
778
|
+
*/
|
|
779
|
+
private extractUIValues;
|
|
780
|
+
/**
|
|
781
|
+
* Build viewer configuration from UI config and camera config
|
|
782
|
+
*/
|
|
783
|
+
private buildViewerConfig;
|
|
693
784
|
/**
|
|
694
785
|
* Update AR button visibility
|
|
695
786
|
*/
|
|
@@ -718,6 +809,10 @@ export declare class VirtualdisplayViewerService {
|
|
|
718
809
|
* Send UI configuration to server
|
|
719
810
|
*/
|
|
720
811
|
private sendUIConfig;
|
|
812
|
+
/**
|
|
813
|
+
* Send full viewer configuration to server
|
|
814
|
+
*/
|
|
815
|
+
private sendConfig;
|
|
721
816
|
}
|
|
722
817
|
|
|
723
818
|
declare interface VoidEvent {
|