worldorbit 2.6.0 → 3.0.1

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 (196) hide show
  1. package/README.md +20 -9
  2. package/dist/browser/core/dist/atlas-edit.d.ts +11 -0
  3. package/dist/browser/core/dist/atlas-edit.js +347 -0
  4. package/dist/browser/core/dist/atlas-utils.d.ts +22 -0
  5. package/dist/browser/core/dist/atlas-utils.js +189 -0
  6. package/dist/browser/core/dist/atlas-validate.d.ts +2 -0
  7. package/dist/browser/core/dist/atlas-validate.js +488 -0
  8. package/dist/browser/core/dist/diagnostics.d.ts +10 -0
  9. package/dist/browser/core/dist/diagnostics.js +109 -0
  10. package/dist/browser/core/dist/draft-parse.d.ts +3 -0
  11. package/dist/browser/core/dist/draft-parse.js +1654 -0
  12. package/dist/browser/core/dist/draft.d.ts +21 -0
  13. package/dist/browser/core/dist/draft.js +482 -0
  14. package/dist/browser/core/dist/errors.d.ts +7 -0
  15. package/dist/browser/core/dist/errors.js +16 -0
  16. package/dist/browser/core/dist/format.d.ts +4 -0
  17. package/dist/browser/core/dist/format.js +613 -0
  18. package/dist/browser/core/dist/index.d.ts +29 -0
  19. package/dist/browser/core/dist/index.js +35 -6542
  20. package/dist/browser/core/dist/load.d.ts +4 -0
  21. package/dist/browser/core/dist/load.js +182 -0
  22. package/dist/browser/core/dist/markdown.d.ts +2 -0
  23. package/dist/browser/core/dist/markdown.js +37 -0
  24. package/dist/browser/core/dist/normalize.d.ts +2 -0
  25. package/dist/browser/core/dist/normalize.js +312 -0
  26. package/dist/browser/core/dist/parse.d.ts +2 -0
  27. package/dist/browser/core/dist/parse.js +133 -0
  28. package/dist/browser/core/dist/scene.d.ts +3 -0
  29. package/dist/browser/core/dist/scene.js +1901 -0
  30. package/dist/browser/core/dist/schema.d.ts +8 -0
  31. package/dist/browser/core/dist/schema.js +298 -0
  32. package/dist/browser/core/dist/spatial-scene.d.ts +3 -0
  33. package/dist/browser/core/dist/spatial-scene.js +420 -0
  34. package/dist/browser/core/dist/tokenize.d.ts +4 -0
  35. package/dist/browser/core/dist/tokenize.js +68 -0
  36. package/dist/browser/core/dist/types.d.ts +637 -0
  37. package/dist/browser/core/dist/types.js +1 -0
  38. package/dist/browser/core/dist/validate.d.ts +2 -0
  39. package/dist/browser/core/dist/validate.js +56 -0
  40. package/dist/browser/editor/dist/editor.d.ts +2 -0
  41. package/dist/browser/editor/dist/editor.js +3700 -0
  42. package/dist/browser/editor/dist/index.d.ts +2 -0
  43. package/dist/browser/editor/dist/index.js +1 -12250
  44. package/dist/browser/editor/dist/types.d.ts +59 -0
  45. package/dist/browser/editor/dist/types.js +1 -0
  46. package/dist/browser/markdown/dist/html.d.ts +3 -0
  47. package/dist/browser/markdown/dist/html.js +64 -0
  48. package/dist/browser/markdown/dist/index.d.ts +4 -0
  49. package/dist/browser/markdown/dist/index.js +3 -6179
  50. package/dist/browser/markdown/dist/rehype.d.ts +10 -0
  51. package/dist/browser/markdown/dist/rehype.js +49 -0
  52. package/dist/browser/markdown/dist/remark.d.ts +9 -0
  53. package/dist/browser/markdown/dist/remark.js +28 -0
  54. package/dist/browser/markdown/dist/types.d.ts +11 -0
  55. package/dist/browser/markdown/dist/types.js +1 -0
  56. package/dist/browser/viewer/dist/atlas-state.d.ts +12 -0
  57. package/dist/browser/viewer/dist/atlas-state.js +269 -0
  58. package/dist/browser/viewer/dist/atlas-viewer.d.ts +2 -0
  59. package/dist/browser/viewer/dist/atlas-viewer.js +495 -0
  60. package/dist/browser/viewer/dist/custom-element.d.ts +1 -0
  61. package/dist/browser/viewer/dist/custom-element.js +78 -0
  62. package/dist/browser/viewer/dist/embed.d.ts +24 -0
  63. package/dist/browser/viewer/dist/embed.js +172 -0
  64. package/dist/browser/viewer/dist/errors.d.ts +6 -0
  65. package/dist/browser/viewer/dist/errors.js +12 -0
  66. package/dist/browser/viewer/dist/index.d.ts +10 -0
  67. package/dist/browser/viewer/dist/index.js +9 -8334
  68. package/dist/browser/viewer/dist/minimap.d.ts +3 -0
  69. package/dist/browser/viewer/dist/minimap.js +63 -0
  70. package/dist/browser/viewer/dist/render.d.ts +6 -0
  71. package/dist/browser/viewer/dist/render.js +670 -0
  72. package/dist/browser/viewer/dist/runtime-3d.d.ts +19 -0
  73. package/dist/browser/viewer/dist/runtime-3d.js +494 -0
  74. package/dist/browser/viewer/dist/theme.d.ts +4 -0
  75. package/dist/browser/viewer/dist/theme.js +103 -0
  76. package/dist/browser/viewer/dist/tooltip.d.ts +3 -0
  77. package/dist/browser/viewer/dist/tooltip.js +198 -0
  78. package/dist/browser/viewer/dist/types.d.ts +292 -0
  79. package/dist/browser/viewer/dist/types.js +1 -0
  80. package/dist/browser/viewer/dist/vendor/three.module.js +53032 -0
  81. package/dist/browser/viewer/dist/viewer-state.d.ts +19 -0
  82. package/dist/browser/viewer/dist/viewer-state.js +162 -0
  83. package/dist/browser/viewer/dist/viewer.d.ts +2 -0
  84. package/dist/browser/viewer/dist/viewer.js +1662 -0
  85. package/dist/unpkg/core/dist/atlas-edit.d.ts +11 -0
  86. package/dist/unpkg/core/dist/atlas-edit.js +347 -0
  87. package/dist/unpkg/core/dist/atlas-utils.d.ts +22 -0
  88. package/dist/unpkg/core/dist/atlas-utils.js +189 -0
  89. package/dist/unpkg/core/dist/atlas-validate.d.ts +2 -0
  90. package/dist/unpkg/core/dist/atlas-validate.js +488 -0
  91. package/dist/unpkg/core/dist/diagnostics.d.ts +10 -0
  92. package/dist/unpkg/core/dist/diagnostics.js +109 -0
  93. package/dist/unpkg/core/dist/draft-parse.d.ts +3 -0
  94. package/dist/unpkg/core/dist/draft-parse.js +1654 -0
  95. package/dist/unpkg/core/dist/draft.d.ts +21 -0
  96. package/dist/unpkg/core/dist/draft.js +482 -0
  97. package/dist/unpkg/core/dist/errors.d.ts +7 -0
  98. package/dist/unpkg/core/dist/errors.js +16 -0
  99. package/dist/unpkg/core/dist/format.d.ts +4 -0
  100. package/dist/unpkg/core/dist/format.js +613 -0
  101. package/dist/unpkg/core/dist/index.d.ts +29 -0
  102. package/dist/unpkg/core/dist/index.js +35 -6614
  103. package/dist/unpkg/core/dist/load.d.ts +4 -0
  104. package/dist/unpkg/core/dist/load.js +182 -0
  105. package/dist/unpkg/core/dist/markdown.d.ts +2 -0
  106. package/dist/unpkg/core/dist/markdown.js +37 -0
  107. package/dist/unpkg/core/dist/normalize.d.ts +2 -0
  108. package/dist/unpkg/core/dist/normalize.js +312 -0
  109. package/dist/unpkg/core/dist/parse.d.ts +2 -0
  110. package/dist/unpkg/core/dist/parse.js +133 -0
  111. package/dist/unpkg/core/dist/scene.d.ts +3 -0
  112. package/dist/unpkg/core/dist/scene.js +1901 -0
  113. package/dist/unpkg/core/dist/schema.d.ts +8 -0
  114. package/dist/unpkg/core/dist/schema.js +298 -0
  115. package/dist/unpkg/core/dist/spatial-scene.d.ts +3 -0
  116. package/dist/unpkg/core/dist/spatial-scene.js +420 -0
  117. package/dist/unpkg/core/dist/tokenize.d.ts +4 -0
  118. package/dist/unpkg/core/dist/tokenize.js +68 -0
  119. package/dist/unpkg/core/dist/types.d.ts +637 -0
  120. package/dist/unpkg/core/dist/types.js +1 -0
  121. package/dist/unpkg/core/dist/validate.d.ts +2 -0
  122. package/dist/unpkg/core/dist/validate.js +56 -0
  123. package/dist/unpkg/editor/dist/editor.d.ts +2 -0
  124. package/dist/unpkg/editor/dist/editor.js +3700 -0
  125. package/dist/unpkg/editor/dist/index.d.ts +2 -0
  126. package/dist/unpkg/editor/dist/index.js +1 -12275
  127. package/dist/unpkg/editor/dist/types.d.ts +59 -0
  128. package/dist/unpkg/editor/dist/types.js +1 -0
  129. package/dist/unpkg/markdown/dist/html.d.ts +3 -0
  130. package/dist/unpkg/markdown/dist/html.js +64 -0
  131. package/dist/unpkg/markdown/dist/index.d.ts +4 -0
  132. package/dist/unpkg/markdown/dist/index.js +3 -6207
  133. package/dist/unpkg/markdown/dist/rehype.d.ts +10 -0
  134. package/dist/unpkg/markdown/dist/rehype.js +49 -0
  135. package/dist/unpkg/markdown/dist/remark.d.ts +9 -0
  136. package/dist/unpkg/markdown/dist/remark.js +28 -0
  137. package/dist/unpkg/markdown/dist/types.d.ts +11 -0
  138. package/dist/unpkg/markdown/dist/types.js +1 -0
  139. package/dist/unpkg/viewer/dist/atlas-state.d.ts +12 -0
  140. package/dist/unpkg/viewer/dist/atlas-state.js +269 -0
  141. package/dist/unpkg/viewer/dist/atlas-viewer.d.ts +2 -0
  142. package/dist/unpkg/viewer/dist/atlas-viewer.js +495 -0
  143. package/dist/unpkg/viewer/dist/custom-element.d.ts +1 -0
  144. package/dist/unpkg/viewer/dist/custom-element.js +78 -0
  145. package/dist/unpkg/viewer/dist/embed.d.ts +24 -0
  146. package/dist/unpkg/viewer/dist/embed.js +172 -0
  147. package/dist/unpkg/viewer/dist/errors.d.ts +6 -0
  148. package/dist/unpkg/viewer/dist/errors.js +12 -0
  149. package/dist/unpkg/viewer/dist/index.d.ts +10 -0
  150. package/dist/unpkg/viewer/dist/index.js +9 -8391
  151. package/dist/unpkg/viewer/dist/minimap.d.ts +3 -0
  152. package/dist/unpkg/viewer/dist/minimap.js +63 -0
  153. package/dist/unpkg/viewer/dist/render.d.ts +6 -0
  154. package/dist/unpkg/viewer/dist/render.js +670 -0
  155. package/dist/unpkg/viewer/dist/runtime-3d.d.ts +19 -0
  156. package/dist/unpkg/viewer/dist/runtime-3d.js +494 -0
  157. package/dist/unpkg/viewer/dist/theme.d.ts +4 -0
  158. package/dist/unpkg/viewer/dist/theme.js +103 -0
  159. package/dist/unpkg/viewer/dist/tooltip.d.ts +3 -0
  160. package/dist/unpkg/viewer/dist/tooltip.js +198 -0
  161. package/dist/unpkg/viewer/dist/types.d.ts +292 -0
  162. package/dist/unpkg/viewer/dist/types.js +1 -0
  163. package/dist/unpkg/viewer/dist/vendor/three.module.js +53032 -0
  164. package/dist/unpkg/viewer/dist/viewer-state.d.ts +19 -0
  165. package/dist/unpkg/viewer/dist/viewer-state.js +162 -0
  166. package/dist/unpkg/viewer/dist/viewer.d.ts +2 -0
  167. package/dist/unpkg/viewer/dist/viewer.js +1662 -0
  168. package/dist/unpkg/worldorbit-core.min.js +10 -10
  169. package/dist/unpkg/worldorbit-editor.min.js +4109 -256
  170. package/dist/unpkg/worldorbit-markdown.min.js +26 -26
  171. package/dist/unpkg/worldorbit-viewer.min.js +3945 -92
  172. package/dist/unpkg/worldorbit.js +32219 -199
  173. package/dist/unpkg/worldorbit.min.js +3949 -96
  174. package/package.json +1 -1
  175. package/packages/core/dist/index.d.ts +1 -0
  176. package/packages/core/dist/index.js +1 -0
  177. package/packages/core/dist/spatial-scene.d.ts +3 -0
  178. package/packages/core/dist/spatial-scene.js +420 -0
  179. package/packages/core/dist/types.d.ts +105 -0
  180. package/packages/editor/dist/editor.js +25 -4
  181. package/packages/editor/dist/types.d.ts +4 -0
  182. package/packages/markdown/dist/html.js +10 -3
  183. package/packages/viewer/dist/atlas-state.js +3 -0
  184. package/packages/viewer/dist/atlas-viewer.js +1 -0
  185. package/packages/viewer/dist/custom-element.js +18 -4
  186. package/packages/viewer/dist/embed.d.ts +5 -1
  187. package/packages/viewer/dist/embed.js +58 -24
  188. package/packages/viewer/dist/errors.d.ts +6 -0
  189. package/packages/viewer/dist/errors.js +12 -0
  190. package/packages/viewer/dist/index.d.ts +1 -0
  191. package/packages/viewer/dist/index.js +1 -0
  192. package/packages/viewer/dist/runtime-3d.d.ts +19 -0
  193. package/packages/viewer/dist/runtime-3d.js +494 -0
  194. package/packages/viewer/dist/types.d.ts +21 -2
  195. package/packages/viewer/dist/vendor/three.module.js +53032 -0
  196. package/packages/viewer/dist/viewer.js +501 -41
@@ -0,0 +1,495 @@
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
+ const scene = activeViewer.getScene();
330
+ const camera = scene.camera;
331
+ return {
332
+ selection: activeViewer.getSelectionDetails(),
333
+ activeViewpoint: activeViewer.getActiveViewpoint(),
334
+ filter: activeViewer.getFilter(),
335
+ atlasState: activeViewer.getAtlasState(),
336
+ visibleObjectIds: activeViewer.getVisibleObjects().map((object) => object.objectId),
337
+ scene: {
338
+ title: scene.title,
339
+ projection: scene.projection,
340
+ renderProjection: scene.renderProjection,
341
+ camera: camera
342
+ ? {
343
+ azimuth: camera.azimuth,
344
+ elevation: camera.elevation,
345
+ roll: camera.roll,
346
+ distance: camera.distance,
347
+ }
348
+ : null,
349
+ renderPreset: scene.renderPreset,
350
+ groupCount: scene.groups.length,
351
+ semanticGroupCount: scene.semanticGroups.length,
352
+ relationCount: scene.relations.length,
353
+ eventCount: scene.events.length,
354
+ viewpointCount: scene.viewpoints.length,
355
+ },
356
+ };
357
+ }
358
+ function renderBookmarks() {
359
+ if (!bookmarkList) {
360
+ return;
361
+ }
362
+ bookmarkList.innerHTML = bookmarks
363
+ .map((bookmark) => `<button type="button" class="wo-atlas-pill" data-bookmark-id="${escapeHtml(bookmark.id)}">${escapeHtml(bookmark.label)}</button>`)
364
+ .join("");
365
+ }
366
+ }
367
+ function buildAtlasViewerMarkup(controls) {
368
+ const toolbarItems = [
369
+ controls.search
370
+ ? `<label class="wo-atlas-field">
371
+ <span>Search</span>
372
+ <input data-atlas-search type="text" placeholder="Search objects, tags, or types" />
373
+ </label>`
374
+ : "",
375
+ controls.typeFilter
376
+ ? `<label class="wo-atlas-field">
377
+ <span>Type</span>
378
+ <select data-atlas-type-filter>
379
+ <option value="">All types</option>
380
+ <option value="star">Star</option>
381
+ <option value="planet">Planet</option>
382
+ <option value="moon">Moon</option>
383
+ <option value="belt">Belt</option>
384
+ <option value="asteroid">Asteroid</option>
385
+ <option value="comet">Comet</option>
386
+ <option value="ring">Ring</option>
387
+ <option value="structure">Structure</option>
388
+ <option value="phenomenon">Phenomenon</option>
389
+ </select>
390
+ </label>`
391
+ : "",
392
+ controls.groupFilter
393
+ ? `<label class="wo-atlas-field">
394
+ <span>Group</span>
395
+ <select data-atlas-group-filter>
396
+ <option value="">All groups</option>
397
+ </select>
398
+ </label>`
399
+ : "",
400
+ controls.viewpointSelect
401
+ ? `<label class="wo-atlas-field">
402
+ <span>Viewpoint</span>
403
+ <select data-atlas-viewpoint>
404
+ <option value="">Scene default</option>
405
+ </select>
406
+ </label>`
407
+ : "",
408
+ controls.bookmarks
409
+ ? `<button type="button" class="wo-atlas-button" data-atlas-bookmark>Save bookmark</button>`
410
+ : "",
411
+ ]
412
+ .filter(Boolean)
413
+ .join("");
414
+ return `<section class="wo-atlas-shell">
415
+ ${toolbarItems ? `<div class="wo-atlas-toolbar" data-atlas-toolbar>${toolbarItems}</div>` : ""}
416
+ <div class="wo-atlas-workspace">
417
+ <div class="wo-atlas-stage" data-atlas-stage></div>
418
+ ${controls.inspector ? `<pre class="wo-atlas-inspector" data-atlas-inspector></pre>` : ""}
419
+ </div>
420
+ <div class="wo-atlas-footer">
421
+ <div class="wo-atlas-results" data-atlas-results></div>
422
+ ${controls.bookmarks ? `<div class="wo-atlas-bookmarks" data-atlas-bookmarks></div>` : ""}
423
+ </div>
424
+ </section>`;
425
+ }
426
+ function installAtlasViewerStyles() {
427
+ if (document.getElementById(STYLE_ID)) {
428
+ return;
429
+ }
430
+ const style = document.createElement("style");
431
+ style.id = STYLE_ID;
432
+ style.textContent = `
433
+ .wo-atlas-shell { display: grid; gap: 16px; min-width: 0; }
434
+ .wo-atlas-toolbar { display: flex; gap: 12px; flex-wrap: wrap; align-items: end; }
435
+ .wo-atlas-workspace { display: grid; gap: 16px; grid-template-columns: minmax(0, 1fr) minmax(260px, 320px); }
436
+ .wo-atlas-stage { min-height: 420px; min-width: 0; }
437
+ .wo-atlas-inspector {
438
+ margin: 0;
439
+ min-height: 420px;
440
+ padding: 16px;
441
+ border-radius: 18px;
442
+ border: 1px solid rgba(255,255,255,0.08);
443
+ background: rgba(7, 16, 25, 0.72);
444
+ color: #edf6ff;
445
+ overflow: auto;
446
+ font: 12px/1.5 "Cascadia Code", "Consolas", monospace;
447
+ white-space: pre-wrap;
448
+ overflow-wrap: anywhere;
449
+ }
450
+ .wo-atlas-footer { display: grid; gap: 12px; }
451
+ .wo-atlas-results, .wo-atlas-bookmarks { display: flex; gap: 8px; flex-wrap: wrap; }
452
+ .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; }
453
+ .wo-atlas-field input, .wo-atlas-field select, .wo-atlas-button, .wo-atlas-pill {
454
+ border: 1px solid rgba(240, 180, 100, 0.2);
455
+ border-radius: 999px;
456
+ background: rgba(240, 180, 100, 0.08);
457
+ color: #edf6ff;
458
+ font: 500 13px/1.4 "Segoe UI Variable", "Segoe UI", sans-serif;
459
+ padding: 10px 14px;
460
+ }
461
+ .wo-atlas-button, .wo-atlas-pill { cursor: pointer; }
462
+ @media (max-width: 1080px) {
463
+ .wo-atlas-workspace { grid-template-columns: 1fr; }
464
+ .wo-atlas-inspector { min-height: 220px; }
465
+ }
466
+ `;
467
+ document.head.append(style);
468
+ }
469
+ function cloneBookmark(bookmark) {
470
+ return {
471
+ ...bookmark,
472
+ atlasState: {
473
+ ...bookmark.atlasState,
474
+ viewerState: { ...bookmark.atlasState.viewerState },
475
+ renderOptions: {
476
+ ...bookmark.atlasState.renderOptions,
477
+ layers: bookmark.atlasState.renderOptions.layers
478
+ ? { ...bookmark.atlasState.renderOptions.layers }
479
+ : undefined,
480
+ scaleModel: bookmark.atlasState.renderOptions.scaleModel
481
+ ? { ...bookmark.atlasState.renderOptions.scaleModel }
482
+ : undefined,
483
+ viewMode: bookmark.atlasState.renderOptions.viewMode ?? "2d",
484
+ },
485
+ filter: bookmark.atlasState.filter ? { ...bookmark.atlasState.filter } : null,
486
+ },
487
+ };
488
+ }
489
+ function escapeHtml(value) {
490
+ return value
491
+ .replaceAll("&", "&amp;")
492
+ .replaceAll("<", "&lt;")
493
+ .replaceAll(">", "&gt;")
494
+ .replaceAll('"', "&quot;");
495
+ }
@@ -0,0 +1 @@
1
+ export declare function defineWorldOrbitViewerElement(tagName?: string): void;
@@ -0,0 +1,78 @@
1
+ import { loadWorldOrbitSource, renderDocumentToScene, } from "@worldorbit/core";
2
+ import { WorldOrbit3DUnavailableError } from "./errors.js";
3
+ import { render3DUnavailableMarkup } from "./embed.js";
4
+ import { renderSceneToSvg } from "./render.js";
5
+ import { createAtlasViewer } from "./atlas-viewer.js";
6
+ import { createInteractiveViewer } from "./viewer.js";
7
+ export function defineWorldOrbitViewerElement(tagName = "worldorbit-viewer") {
8
+ if (typeof window === "undefined" || typeof customElements === "undefined") {
9
+ return;
10
+ }
11
+ if (customElements.get(tagName)) {
12
+ return;
13
+ }
14
+ class WorldOrbitViewerElement extends HTMLElement {
15
+ static get observedAttributes() {
16
+ return ["source", "mode", "theme"];
17
+ }
18
+ viewer = null;
19
+ connectedCallback() {
20
+ this.renderCurrent();
21
+ }
22
+ disconnectedCallback() {
23
+ this.viewer?.destroy();
24
+ this.viewer = null;
25
+ }
26
+ attributeChangedCallback() {
27
+ if (this.isConnected) {
28
+ this.renderCurrent();
29
+ }
30
+ }
31
+ renderCurrent() {
32
+ this.viewer?.destroy();
33
+ this.viewer = null;
34
+ const source = this.getAttribute("source") ?? this.textContent ?? "";
35
+ const mode = this.getAttribute("mode") ?? "interactive";
36
+ if (!source.trim()) {
37
+ this.innerHTML = "";
38
+ return;
39
+ }
40
+ const documentModel = parseSource(source);
41
+ const scene = renderDocumentToScene(documentModel);
42
+ const theme = (this.getAttribute("theme") ?? undefined);
43
+ if (mode === "static") {
44
+ this.innerHTML = renderSceneToSvg(scene, {
45
+ theme,
46
+ });
47
+ return;
48
+ }
49
+ if (mode === "atlas") {
50
+ this.viewer = createAtlasViewer(this, {
51
+ scene,
52
+ theme,
53
+ });
54
+ return;
55
+ }
56
+ try {
57
+ this.viewer = createInteractiveViewer(this, {
58
+ source,
59
+ theme,
60
+ viewMode: mode === "interactive-3d"
61
+ ? "3d"
62
+ : "2d",
63
+ });
64
+ }
65
+ catch (error) {
66
+ if (error instanceof WorldOrbit3DUnavailableError && mode === "interactive-3d") {
67
+ this.innerHTML = render3DUnavailableMarkup(error.message);
68
+ return;
69
+ }
70
+ throw error;
71
+ }
72
+ }
73
+ }
74
+ customElements.define(tagName, WorldOrbitViewerElement);
75
+ }
76
+ function parseSource(source) {
77
+ return loadWorldOrbitSource(source).document;
78
+ }
@@ -0,0 +1,24 @@
1
+ import type { RenderScene, SpatialScene } 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
+ spatialScene?: SpatialScene;
7
+ viewMode?: "2d" | "3d";
8
+ initialViewpointId?: string;
9
+ initialSelectionObjectId?: string;
10
+ initialFilter?: ViewerFilter | null;
11
+ atlasState?: ViewerAtlasState | null;
12
+ minimap?: boolean;
13
+ }): WorldOrbitEmbedPayload;
14
+ export declare function createWorldOrbitEmbedMarkup(payload: WorldOrbitEmbedPayload, options?: Pick<MountWorldOrbitEmbedsOptions, "theme" | "layers" | "subtitle" | "preset"> & {
15
+ className?: string;
16
+ viewMode?: "2d" | "3d";
17
+ initialViewpointId?: string;
18
+ initialSelectionObjectId?: string;
19
+ initialFilter?: ViewerFilter | null;
20
+ atlasState?: ViewerAtlasState | null;
21
+ minimap?: boolean;
22
+ }): string;
23
+ export declare function mountWorldOrbitEmbeds(root?: ParentNode, options?: MountWorldOrbitEmbedsOptions): MountedWorldOrbitEmbeds;
24
+ export declare function render3DUnavailableMarkup(message: string): string;