worldorbit 2.5.1-5.2

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.
Files changed (117) hide show
  1. package/LICENSE.md +5 -0
  2. package/README.md +468 -0
  3. package/dist/browser/core/dist/index.js +4009 -0
  4. package/dist/browser/markdown/dist/index.js +3951 -0
  5. package/dist/browser/viewer/dist/index.js +5981 -0
  6. package/dist/constants.d.ts +8 -0
  7. package/dist/constants.js +84 -0
  8. package/dist/errors.d.ts +7 -0
  9. package/dist/errors.js +16 -0
  10. package/dist/index.d.ts +18 -0
  11. package/dist/index.js +25 -0
  12. package/dist/normalize.d.ts +2 -0
  13. package/dist/normalize.js +243 -0
  14. package/dist/parse.d.ts +2 -0
  15. package/dist/parse.js +126 -0
  16. package/dist/render.d.ts +6 -0
  17. package/dist/render.js +683 -0
  18. package/dist/tokenize.d.ts +4 -0
  19. package/dist/tokenize.js +68 -0
  20. package/dist/types.d.ts +208 -0
  21. package/dist/types.js +1 -0
  22. package/dist/unpkg/core/dist/index.js +4081 -0
  23. package/dist/unpkg/markdown/dist/index.js +3979 -0
  24. package/dist/unpkg/viewer/dist/index.js +6038 -0
  25. package/dist/unpkg/worldorbit-core.min.js +12 -0
  26. package/dist/unpkg/worldorbit-markdown.min.js +95 -0
  27. package/dist/unpkg/worldorbit-viewer.min.js +251 -0
  28. package/dist/unpkg/worldorbit.d.ts +2 -0
  29. package/dist/unpkg/worldorbit.esm.js +2 -0
  30. package/dist/unpkg/worldorbit.js +8524 -0
  31. package/dist/unpkg/worldorbit.min.js +255 -0
  32. package/dist/validate.d.ts +2 -0
  33. package/dist/validate.js +31 -0
  34. package/dist/viewer-state.d.ts +16 -0
  35. package/dist/viewer-state.js +130 -0
  36. package/dist/viewer.d.ts +2 -0
  37. package/dist/viewer.js +434 -0
  38. package/package.json +68 -0
  39. package/packages/core/README.md +17 -0
  40. package/packages/core/dist/atlas-edit.d.ts +11 -0
  41. package/packages/core/dist/atlas-edit.js +273 -0
  42. package/packages/core/dist/atlas-utils.d.ts +22 -0
  43. package/packages/core/dist/atlas-utils.js +189 -0
  44. package/packages/core/dist/atlas-validate.d.ts +2 -0
  45. package/packages/core/dist/atlas-validate.js +285 -0
  46. package/packages/core/dist/diagnostics.d.ts +10 -0
  47. package/packages/core/dist/diagnostics.js +109 -0
  48. package/packages/core/dist/draft-parse.d.ts +3 -0
  49. package/packages/core/dist/draft-parse.js +1275 -0
  50. package/packages/core/dist/draft.d.ts +18 -0
  51. package/packages/core/dist/draft.js +387 -0
  52. package/packages/core/dist/errors.d.ts +7 -0
  53. package/packages/core/dist/errors.js +16 -0
  54. package/packages/core/dist/format.d.ts +4 -0
  55. package/packages/core/dist/format.js +520 -0
  56. package/packages/core/dist/index.d.ts +28 -0
  57. package/packages/core/dist/index.js +44 -0
  58. package/packages/core/dist/load.d.ts +4 -0
  59. package/packages/core/dist/load.js +175 -0
  60. package/packages/core/dist/markdown.d.ts +2 -0
  61. package/packages/core/dist/markdown.js +37 -0
  62. package/packages/core/dist/normalize.d.ts +2 -0
  63. package/packages/core/dist/normalize.js +311 -0
  64. package/packages/core/dist/parse.d.ts +2 -0
  65. package/packages/core/dist/parse.js +133 -0
  66. package/packages/core/dist/scene.d.ts +3 -0
  67. package/packages/core/dist/scene.js +1565 -0
  68. package/packages/core/dist/schema.d.ts +8 -0
  69. package/packages/core/dist/schema.js +298 -0
  70. package/packages/core/dist/tokenize.d.ts +4 -0
  71. package/packages/core/dist/tokenize.js +68 -0
  72. package/packages/core/dist/types.d.ts +476 -0
  73. package/packages/core/dist/types.js +1 -0
  74. package/packages/core/dist/validate.d.ts +2 -0
  75. package/packages/core/dist/validate.js +56 -0
  76. package/packages/editor/dist/editor.d.ts +2 -0
  77. package/packages/editor/dist/editor.js +3042 -0
  78. package/packages/editor/dist/index.d.ts +2 -0
  79. package/packages/editor/dist/index.js +1 -0
  80. package/packages/editor/dist/types.d.ts +53 -0
  81. package/packages/editor/dist/types.js +1 -0
  82. package/packages/markdown/README.md +9 -0
  83. package/packages/markdown/dist/html.d.ts +3 -0
  84. package/packages/markdown/dist/html.js +57 -0
  85. package/packages/markdown/dist/index.d.ts +4 -0
  86. package/packages/markdown/dist/index.js +3 -0
  87. package/packages/markdown/dist/rehype.d.ts +10 -0
  88. package/packages/markdown/dist/rehype.js +49 -0
  89. package/packages/markdown/dist/remark.d.ts +9 -0
  90. package/packages/markdown/dist/remark.js +28 -0
  91. package/packages/markdown/dist/types.d.ts +11 -0
  92. package/packages/markdown/dist/types.js +1 -0
  93. package/packages/viewer/README.md +13 -0
  94. package/packages/viewer/dist/atlas-state.d.ts +12 -0
  95. package/packages/viewer/dist/atlas-state.js +257 -0
  96. package/packages/viewer/dist/atlas-viewer.d.ts +2 -0
  97. package/packages/viewer/dist/atlas-viewer.js +482 -0
  98. package/packages/viewer/dist/custom-element.d.ts +1 -0
  99. package/packages/viewer/dist/custom-element.js +64 -0
  100. package/packages/viewer/dist/embed.d.ts +20 -0
  101. package/packages/viewer/dist/embed.js +138 -0
  102. package/packages/viewer/dist/index.d.ts +9 -0
  103. package/packages/viewer/dist/index.js +8 -0
  104. package/packages/viewer/dist/minimap.d.ts +3 -0
  105. package/packages/viewer/dist/minimap.js +63 -0
  106. package/packages/viewer/dist/render.d.ts +6 -0
  107. package/packages/viewer/dist/render.js +641 -0
  108. package/packages/viewer/dist/theme.d.ts +4 -0
  109. package/packages/viewer/dist/theme.js +102 -0
  110. package/packages/viewer/dist/tooltip.d.ts +3 -0
  111. package/packages/viewer/dist/tooltip.js +189 -0
  112. package/packages/viewer/dist/types.d.ts +263 -0
  113. package/packages/viewer/dist/types.js +1 -0
  114. package/packages/viewer/dist/viewer-state.d.ts +19 -0
  115. package/packages/viewer/dist/viewer-state.js +162 -0
  116. package/packages/viewer/dist/viewer.d.ts +2 -0
  117. package/packages/viewer/dist/viewer.js +1175 -0
@@ -0,0 +1,482 @@
1
+ import { normalizeViewerFilter } from "./atlas-state.js";
2
+ import { createInteractiveViewer } from "./viewer.js";
3
+ const STYLE_ID = "worldorbit-atlas-viewer-style";
4
+ export function createAtlasViewer(container, options) {
5
+ if (typeof document === "undefined") {
6
+ throw new Error("Atlas viewer requires a browser environment.");
7
+ }
8
+ installAtlasViewerStyles();
9
+ const controls = {
10
+ search: options.controls?.search ?? true,
11
+ typeFilter: options.controls?.typeFilter ?? true,
12
+ groupFilter: options.controls?.groupFilter ?? true,
13
+ viewpointSelect: options.controls?.viewpointSelect ?? true,
14
+ inspector: options.controls?.inspector ?? true,
15
+ bookmarks: options.controls?.bookmarks ?? true,
16
+ };
17
+ container.classList.add("wo-atlas-viewer");
18
+ container.innerHTML = buildAtlasViewerMarkup(controls);
19
+ const toolbar = container.querySelector("[data-atlas-toolbar]");
20
+ const searchInput = container.querySelector("[data-atlas-search]");
21
+ const typeFilterSelect = container.querySelector("[data-atlas-type-filter]");
22
+ const groupFilterSelect = container.querySelector("[data-atlas-group-filter]");
23
+ const viewpointSelect = container.querySelector("[data-atlas-viewpoint]");
24
+ const bookmarkButton = container.querySelector("[data-atlas-bookmark]");
25
+ const bookmarkList = container.querySelector("[data-atlas-bookmarks]");
26
+ const searchResults = container.querySelector("[data-atlas-results]");
27
+ const inspector = container.querySelector("[data-atlas-inspector]");
28
+ const stage = container.querySelector("[data-atlas-stage]");
29
+ if (!stage) {
30
+ throw new Error("Atlas viewer failed to initialize its stage container.");
31
+ }
32
+ const baseFilter = normalizeViewerFilter(options.initialFilter ?? null);
33
+ let searchQuery = options.initialQuery?.trim() ?? baseFilter?.query ?? "";
34
+ let objectTypeFilter = options.initialObjectType ??
35
+ (baseFilter?.objectTypes?.length === 1 ? baseFilter.objectTypes[0] : null);
36
+ let groupFilter = baseFilter?.groupIds?.[0] ?? null;
37
+ let bookmarks = [];
38
+ let viewer;
39
+ viewer = createInteractiveViewer(stage, {
40
+ ...options,
41
+ initialFilter: null,
42
+ onSelectionChange(selection) {
43
+ if (viewer) {
44
+ updateInspector();
45
+ }
46
+ options.onSelectionChange?.(selection);
47
+ },
48
+ onSelectionDetailsChange(details) {
49
+ if (viewer) {
50
+ updateInspector();
51
+ }
52
+ options.onSelectionDetailsChange?.(details);
53
+ },
54
+ onFilterChange(filter, visibleObjects) {
55
+ if (viewer) {
56
+ syncControlsFromFilter(filter);
57
+ updateSearchResults();
58
+ updateInspector();
59
+ }
60
+ options.onFilterChange?.(filter, visibleObjects);
61
+ },
62
+ onViewpointChange(viewpoint) {
63
+ if (viewer) {
64
+ syncViewpointControl();
65
+ updateInspector();
66
+ }
67
+ options.onViewpointChange?.(viewpoint);
68
+ },
69
+ onAtlasStateChange(state) {
70
+ if (viewer) {
71
+ updateInspector();
72
+ }
73
+ options.onAtlasStateChange?.(state);
74
+ },
75
+ onViewChange(state) {
76
+ if (viewer) {
77
+ updateInspector();
78
+ }
79
+ options.onViewChange?.(state);
80
+ },
81
+ });
82
+ applyCurrentFilter();
83
+ populateViewpoints();
84
+ populateGroups();
85
+ syncControlsFromFilter(viewer.getFilter());
86
+ renderBookmarks();
87
+ updateSearchResults();
88
+ updateInspector();
89
+ searchInput?.addEventListener("input", () => {
90
+ searchQuery = searchInput.value.trim();
91
+ applyCurrentFilter();
92
+ });
93
+ typeFilterSelect?.addEventListener("change", () => {
94
+ objectTypeFilter = (typeFilterSelect.value || null);
95
+ applyCurrentFilter();
96
+ });
97
+ groupFilterSelect?.addEventListener("change", () => {
98
+ groupFilter = groupFilterSelect.value || null;
99
+ applyCurrentFilter();
100
+ });
101
+ viewpointSelect?.addEventListener("change", () => {
102
+ const activeViewer = requireViewer();
103
+ if (!viewpointSelect.value) {
104
+ activeViewer.resetView();
105
+ applyCurrentFilter();
106
+ return;
107
+ }
108
+ activeViewer.goToViewpoint(viewpointSelect.value);
109
+ updateInspector();
110
+ });
111
+ bookmarkButton?.addEventListener("click", () => {
112
+ const activeViewer = requireViewer();
113
+ const label = activeViewer.getActiveViewpoint()?.label ??
114
+ activeViewer.getSelectionDetails()?.objectId ??
115
+ `Bookmark ${bookmarks.length + 1}`;
116
+ bookmarks = [...bookmarks, activeViewer.captureBookmark(label, label)];
117
+ renderBookmarks();
118
+ updateInspector();
119
+ });
120
+ bookmarkList?.addEventListener("click", (event) => {
121
+ const button = event.target?.closest("[data-bookmark-id]");
122
+ if (!button) {
123
+ return;
124
+ }
125
+ const bookmark = bookmarks.find((entry) => entry.id === button.dataset.bookmarkId);
126
+ if (!bookmark) {
127
+ return;
128
+ }
129
+ const activeViewer = requireViewer();
130
+ activeViewer.applyBookmark(bookmark);
131
+ syncControlsFromFilter(activeViewer.getFilter());
132
+ updateSearchResults();
133
+ updateInspector();
134
+ });
135
+ searchResults?.addEventListener("click", (event) => {
136
+ const button = event.target?.closest("[data-object-id]");
137
+ if (!button) {
138
+ return;
139
+ }
140
+ requireViewer().focusObject(button.dataset.objectId ?? "");
141
+ updateInspector();
142
+ });
143
+ function requireViewer() {
144
+ if (!viewer) {
145
+ throw new Error("Atlas viewer is not initialized.");
146
+ }
147
+ return viewer;
148
+ }
149
+ const api = {
150
+ element: container,
151
+ get viewer() {
152
+ return requireViewer();
153
+ },
154
+ getViewer() {
155
+ return requireViewer();
156
+ },
157
+ setSource(source) {
158
+ requireViewer().setSource(source);
159
+ refreshAfterInputChange();
160
+ },
161
+ setDocument(document) {
162
+ requireViewer().setDocument(document);
163
+ refreshAfterInputChange();
164
+ },
165
+ setScene(scene) {
166
+ requireViewer().setScene(scene);
167
+ refreshAfterInputChange();
168
+ },
169
+ getAtlasState() {
170
+ return requireViewer().getAtlasState();
171
+ },
172
+ setAtlasState(state) {
173
+ const activeViewer = requireViewer();
174
+ activeViewer.setAtlasState(state);
175
+ syncControlsFromFilter(activeViewer.getFilter());
176
+ updateSearchResults();
177
+ updateInspector();
178
+ },
179
+ getInspectorSnapshot() {
180
+ return buildInspectorSnapshot();
181
+ },
182
+ getSearchQuery() {
183
+ return searchQuery;
184
+ },
185
+ setSearchQuery(query) {
186
+ searchQuery = query.trim();
187
+ if (searchInput) {
188
+ searchInput.value = searchQuery;
189
+ }
190
+ applyCurrentFilter();
191
+ },
192
+ getObjectTypeFilter() {
193
+ return objectTypeFilter;
194
+ },
195
+ setObjectTypeFilter(type) {
196
+ objectTypeFilter = type;
197
+ if (typeFilterSelect) {
198
+ typeFilterSelect.value = type ?? "";
199
+ }
200
+ applyCurrentFilter();
201
+ },
202
+ listSearchResults(limit = 6) {
203
+ return requireViewer().search(searchQuery, limit);
204
+ },
205
+ listBookmarks() {
206
+ return bookmarks.map(cloneBookmark);
207
+ },
208
+ captureBookmark(name, label) {
209
+ const bookmark = requireViewer().captureBookmark(name, label);
210
+ bookmarks = [...bookmarks, bookmark];
211
+ renderBookmarks();
212
+ updateInspector();
213
+ return cloneBookmark(bookmark);
214
+ },
215
+ applyBookmark(bookmark) {
216
+ const activeViewer = requireViewer();
217
+ const result = activeViewer.applyBookmark(bookmark);
218
+ if (result) {
219
+ syncControlsFromFilter(activeViewer.getFilter());
220
+ updateSearchResults();
221
+ updateInspector();
222
+ }
223
+ return result;
224
+ },
225
+ goToViewpoint(id) {
226
+ const result = requireViewer().goToViewpoint(id);
227
+ if (result) {
228
+ updateInspector();
229
+ }
230
+ return result;
231
+ },
232
+ exportSvg() {
233
+ return requireViewer().exportSvg();
234
+ },
235
+ destroy() {
236
+ requireViewer().destroy();
237
+ container.innerHTML = "";
238
+ container.classList.remove("wo-atlas-viewer");
239
+ },
240
+ };
241
+ return api;
242
+ function refreshAfterInputChange() {
243
+ populateViewpoints();
244
+ populateGroups();
245
+ applyCurrentFilter();
246
+ renderBookmarks();
247
+ updateSearchResults();
248
+ updateInspector();
249
+ }
250
+ function applyCurrentFilter() {
251
+ requireViewer().setFilter(buildComposedFilter());
252
+ populateViewpoints();
253
+ updateSearchResults();
254
+ updateInspector();
255
+ }
256
+ function buildComposedFilter() {
257
+ return normalizeViewerFilter({
258
+ query: searchQuery || undefined,
259
+ objectTypes: objectTypeFilter ? [objectTypeFilter] : undefined,
260
+ tags: baseFilter?.tags,
261
+ groupIds: groupFilter ? [groupFilter] : baseFilter?.groupIds,
262
+ includeAncestors: baseFilter?.includeAncestors ?? true,
263
+ });
264
+ }
265
+ function syncControlsFromFilter(filter) {
266
+ searchQuery = filter?.query?.trim() ?? "";
267
+ objectTypeFilter =
268
+ filter?.objectTypes?.length === 1 ? filter.objectTypes[0] : null;
269
+ groupFilter = filter?.groupIds?.length === 1 ? filter.groupIds[0] : null;
270
+ if (searchInput && document.activeElement !== searchInput) {
271
+ searchInput.value = searchQuery;
272
+ }
273
+ if (typeFilterSelect) {
274
+ typeFilterSelect.value = objectTypeFilter ?? "";
275
+ }
276
+ if (groupFilterSelect) {
277
+ groupFilterSelect.value = groupFilter ?? "";
278
+ }
279
+ }
280
+ function populateViewpoints() {
281
+ if (!viewpointSelect) {
282
+ return;
283
+ }
284
+ const activeViewer = requireViewer();
285
+ const active = activeViewer.getActiveViewpoint()?.id ?? "";
286
+ viewpointSelect.innerHTML = [
287
+ `<option value="">Scene default</option>`,
288
+ ...activeViewer
289
+ .listViewpoints()
290
+ .map((viewpoint) => `<option value="${escapeHtml(viewpoint.id)}">${escapeHtml(viewpoint.label)}</option>`),
291
+ ].join("");
292
+ viewpointSelect.value = active;
293
+ }
294
+ function populateGroups() {
295
+ if (!groupFilterSelect) {
296
+ return;
297
+ }
298
+ const activeViewer = requireViewer();
299
+ groupFilterSelect.innerHTML = [
300
+ `<option value="">All groups</option>`,
301
+ ...activeViewer.getScene().semanticGroups.map((group) => `<option value="${escapeHtml(group.id)}">${escapeHtml(group.label)}</option>`),
302
+ ].join("");
303
+ groupFilterSelect.value = groupFilter ?? "";
304
+ }
305
+ function syncViewpointControl() {
306
+ if (!viewpointSelect) {
307
+ return;
308
+ }
309
+ viewpointSelect.value = requireViewer().getActiveViewpoint()?.id ?? "";
310
+ }
311
+ function updateSearchResults() {
312
+ if (!searchResults) {
313
+ return;
314
+ }
315
+ const results = requireViewer().search(searchQuery, 6);
316
+ searchResults.innerHTML = results
317
+ .map((result) => `<button type="button" class="wo-atlas-pill" data-object-id="${escapeHtml(result.objectId)}">${escapeHtml(result.objectId)} - ${escapeHtml(result.type)}</button>`)
318
+ .join("");
319
+ }
320
+ function updateInspector() {
321
+ const snapshot = buildInspectorSnapshot();
322
+ if (inspector) {
323
+ inspector.textContent = JSON.stringify(snapshot, null, 2);
324
+ }
325
+ options.onInspectorChange?.(snapshot);
326
+ }
327
+ function buildInspectorSnapshot() {
328
+ const activeViewer = requireViewer();
329
+ return {
330
+ selection: activeViewer.getSelectionDetails(),
331
+ activeViewpoint: activeViewer.getActiveViewpoint(),
332
+ filter: activeViewer.getFilter(),
333
+ atlasState: activeViewer.getAtlasState(),
334
+ visibleObjectIds: activeViewer.getVisibleObjects().map((object) => object.objectId),
335
+ scene: {
336
+ title: activeViewer.getScene().title,
337
+ projection: activeViewer.getScene().projection,
338
+ renderPreset: activeViewer.getScene().renderPreset,
339
+ groupCount: activeViewer.getScene().groups.length,
340
+ semanticGroupCount: activeViewer.getScene().semanticGroups.length,
341
+ relationCount: activeViewer.getScene().relations.length,
342
+ viewpointCount: activeViewer.getScene().viewpoints.length,
343
+ },
344
+ };
345
+ }
346
+ function renderBookmarks() {
347
+ if (!bookmarkList) {
348
+ return;
349
+ }
350
+ bookmarkList.innerHTML = bookmarks
351
+ .map((bookmark) => `<button type="button" class="wo-atlas-pill" data-bookmark-id="${escapeHtml(bookmark.id)}">${escapeHtml(bookmark.label)}</button>`)
352
+ .join("");
353
+ }
354
+ }
355
+ function buildAtlasViewerMarkup(controls) {
356
+ const toolbarItems = [
357
+ controls.search
358
+ ? `<label class="wo-atlas-field">
359
+ <span>Search</span>
360
+ <input data-atlas-search type="text" placeholder="Search objects, tags, or types" />
361
+ </label>`
362
+ : "",
363
+ controls.typeFilter
364
+ ? `<label class="wo-atlas-field">
365
+ <span>Type</span>
366
+ <select data-atlas-type-filter>
367
+ <option value="">All types</option>
368
+ <option value="star">Star</option>
369
+ <option value="planet">Planet</option>
370
+ <option value="moon">Moon</option>
371
+ <option value="belt">Belt</option>
372
+ <option value="asteroid">Asteroid</option>
373
+ <option value="comet">Comet</option>
374
+ <option value="ring">Ring</option>
375
+ <option value="structure">Structure</option>
376
+ <option value="phenomenon">Phenomenon</option>
377
+ </select>
378
+ </label>`
379
+ : "",
380
+ controls.groupFilter
381
+ ? `<label class="wo-atlas-field">
382
+ <span>Group</span>
383
+ <select data-atlas-group-filter>
384
+ <option value="">All groups</option>
385
+ </select>
386
+ </label>`
387
+ : "",
388
+ controls.viewpointSelect
389
+ ? `<label class="wo-atlas-field">
390
+ <span>Viewpoint</span>
391
+ <select data-atlas-viewpoint>
392
+ <option value="">Scene default</option>
393
+ </select>
394
+ </label>`
395
+ : "",
396
+ controls.bookmarks
397
+ ? `<button type="button" class="wo-atlas-button" data-atlas-bookmark>Save bookmark</button>`
398
+ : "",
399
+ ]
400
+ .filter(Boolean)
401
+ .join("");
402
+ return `<section class="wo-atlas-shell">
403
+ ${toolbarItems ? `<div class="wo-atlas-toolbar" data-atlas-toolbar>${toolbarItems}</div>` : ""}
404
+ <div class="wo-atlas-workspace">
405
+ <div class="wo-atlas-stage" data-atlas-stage></div>
406
+ ${controls.inspector ? `<pre class="wo-atlas-inspector" data-atlas-inspector></pre>` : ""}
407
+ </div>
408
+ <div class="wo-atlas-footer">
409
+ <div class="wo-atlas-results" data-atlas-results></div>
410
+ ${controls.bookmarks ? `<div class="wo-atlas-bookmarks" data-atlas-bookmarks></div>` : ""}
411
+ </div>
412
+ </section>`;
413
+ }
414
+ function installAtlasViewerStyles() {
415
+ if (document.getElementById(STYLE_ID)) {
416
+ return;
417
+ }
418
+ const style = document.createElement("style");
419
+ style.id = STYLE_ID;
420
+ style.textContent = `
421
+ .wo-atlas-shell { display: grid; gap: 16px; min-width: 0; }
422
+ .wo-atlas-toolbar { display: flex; gap: 12px; flex-wrap: wrap; align-items: end; }
423
+ .wo-atlas-workspace { display: grid; gap: 16px; grid-template-columns: minmax(0, 1fr) minmax(260px, 320px); }
424
+ .wo-atlas-stage { min-height: 420px; min-width: 0; }
425
+ .wo-atlas-inspector {
426
+ margin: 0;
427
+ min-height: 420px;
428
+ padding: 16px;
429
+ border-radius: 18px;
430
+ border: 1px solid rgba(255,255,255,0.08);
431
+ background: rgba(7, 16, 25, 0.72);
432
+ color: #edf6ff;
433
+ overflow: auto;
434
+ font: 12px/1.5 "Cascadia Code", "Consolas", monospace;
435
+ white-space: pre-wrap;
436
+ overflow-wrap: anywhere;
437
+ }
438
+ .wo-atlas-footer { display: grid; gap: 12px; }
439
+ .wo-atlas-results, .wo-atlas-bookmarks { display: flex; gap: 8px; flex-wrap: wrap; }
440
+ .wo-atlas-field { display: grid; gap: 6px; min-width: 180px; color: #edf6ff; font: 600 12px/1.4 "Segoe UI Variable", "Segoe UI", sans-serif; text-transform: uppercase; letter-spacing: 0.08em; }
441
+ .wo-atlas-field input, .wo-atlas-field select, .wo-atlas-button, .wo-atlas-pill {
442
+ border: 1px solid rgba(240, 180, 100, 0.2);
443
+ border-radius: 999px;
444
+ background: rgba(240, 180, 100, 0.08);
445
+ color: #edf6ff;
446
+ font: 500 13px/1.4 "Segoe UI Variable", "Segoe UI", sans-serif;
447
+ padding: 10px 14px;
448
+ }
449
+ .wo-atlas-button, .wo-atlas-pill { cursor: pointer; }
450
+ @media (max-width: 1080px) {
451
+ .wo-atlas-workspace { grid-template-columns: 1fr; }
452
+ .wo-atlas-inspector { min-height: 220px; }
453
+ }
454
+ `;
455
+ document.head.append(style);
456
+ }
457
+ function cloneBookmark(bookmark) {
458
+ return {
459
+ ...bookmark,
460
+ atlasState: {
461
+ ...bookmark.atlasState,
462
+ viewerState: { ...bookmark.atlasState.viewerState },
463
+ renderOptions: {
464
+ ...bookmark.atlasState.renderOptions,
465
+ layers: bookmark.atlasState.renderOptions.layers
466
+ ? { ...bookmark.atlasState.renderOptions.layers }
467
+ : undefined,
468
+ scaleModel: bookmark.atlasState.renderOptions.scaleModel
469
+ ? { ...bookmark.atlasState.renderOptions.scaleModel }
470
+ : undefined,
471
+ },
472
+ filter: bookmark.atlasState.filter ? { ...bookmark.atlasState.filter } : null,
473
+ },
474
+ };
475
+ }
476
+ function escapeHtml(value) {
477
+ return value
478
+ .replaceAll("&", "&amp;")
479
+ .replaceAll("<", "&lt;")
480
+ .replaceAll(">", "&gt;")
481
+ .replaceAll('"', "&quot;");
482
+ }
@@ -0,0 +1 @@
1
+ export declare function defineWorldOrbitViewerElement(tagName?: string): void;
@@ -0,0 +1,64 @@
1
+ import { loadWorldOrbitSource, renderDocumentToScene, } from "@worldorbit/core";
2
+ import { renderSceneToSvg } from "./render.js";
3
+ import { createAtlasViewer } from "./atlas-viewer.js";
4
+ import { createInteractiveViewer } from "./viewer.js";
5
+ export function defineWorldOrbitViewerElement(tagName = "worldorbit-viewer") {
6
+ if (typeof window === "undefined" || typeof customElements === "undefined") {
7
+ return;
8
+ }
9
+ if (customElements.get(tagName)) {
10
+ return;
11
+ }
12
+ class WorldOrbitViewerElement extends HTMLElement {
13
+ static get observedAttributes() {
14
+ return ["source", "mode", "theme"];
15
+ }
16
+ viewer = null;
17
+ connectedCallback() {
18
+ this.renderCurrent();
19
+ }
20
+ disconnectedCallback() {
21
+ this.viewer?.destroy();
22
+ this.viewer = null;
23
+ }
24
+ attributeChangedCallback() {
25
+ if (this.isConnected) {
26
+ this.renderCurrent();
27
+ }
28
+ }
29
+ renderCurrent() {
30
+ this.viewer?.destroy();
31
+ this.viewer = null;
32
+ const source = this.getAttribute("source") ?? this.textContent ?? "";
33
+ const mode = this.getAttribute("mode") ?? "interactive";
34
+ if (!source.trim()) {
35
+ this.innerHTML = "";
36
+ return;
37
+ }
38
+ const documentModel = parseSource(source);
39
+ const scene = renderDocumentToScene(documentModel);
40
+ const theme = (this.getAttribute("theme") ?? undefined);
41
+ if (mode === "static") {
42
+ this.innerHTML = renderSceneToSvg(scene, {
43
+ theme,
44
+ });
45
+ return;
46
+ }
47
+ if (mode === "atlas") {
48
+ this.viewer = createAtlasViewer(this, {
49
+ scene,
50
+ theme,
51
+ });
52
+ return;
53
+ }
54
+ this.viewer = createInteractiveViewer(this, {
55
+ scene,
56
+ theme,
57
+ });
58
+ }
59
+ }
60
+ customElements.define(tagName, WorldOrbitViewerElement);
61
+ }
62
+ function parseSource(source) {
63
+ return loadWorldOrbitSource(source).document;
64
+ }
@@ -0,0 +1,20 @@
1
+ import type { RenderScene } from "@worldorbit/core";
2
+ import type { MountedWorldOrbitEmbeds, MountWorldOrbitEmbedsOptions, ViewerAtlasState, ViewerFilter, WorldOrbitEmbedPayload } from "./types.js";
3
+ export declare function serializeWorldOrbitEmbedPayload(payload: WorldOrbitEmbedPayload): string;
4
+ export declare function deserializeWorldOrbitEmbedPayload(serialized: string): WorldOrbitEmbedPayload;
5
+ export declare function createEmbedPayload(scene: RenderScene, mode: WorldOrbitEmbedPayload["mode"], options?: {
6
+ initialViewpointId?: string;
7
+ initialSelectionObjectId?: string;
8
+ initialFilter?: ViewerFilter | null;
9
+ atlasState?: ViewerAtlasState | null;
10
+ minimap?: boolean;
11
+ }): WorldOrbitEmbedPayload;
12
+ export declare function createWorldOrbitEmbedMarkup(payload: WorldOrbitEmbedPayload, options?: Pick<MountWorldOrbitEmbedsOptions, "theme" | "layers" | "subtitle" | "preset"> & {
13
+ className?: string;
14
+ initialViewpointId?: string;
15
+ initialSelectionObjectId?: string;
16
+ initialFilter?: ViewerFilter | null;
17
+ atlasState?: ViewerAtlasState | null;
18
+ minimap?: boolean;
19
+ }): string;
20
+ export declare function mountWorldOrbitEmbeds(root?: ParentNode, options?: MountWorldOrbitEmbedsOptions): MountedWorldOrbitEmbeds;