@found-in-space/skykit 0.2.0-alpha.20260528 → 0.2.0-alpha.20260530
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 +10 -7
- package/package.json +4 -4
- package/src/__tests__/skykit-browser.test.js +51 -9
- package/src/__tests__/skykit.test.js +36 -0
- package/src/browser.js +10 -0
- package/src/hr-diagram.js +3 -1
- package/src/index.d.ts +10 -1
- package/src/index.js +6 -0
- package/src/utils.js +1 -0
package/README.md
CHANGED
|
@@ -69,7 +69,7 @@ Optional attributes keep small tweaks HTML-only:
|
|
|
69
69
|
data-skykit-magnitude="7"
|
|
70
70
|
data-skykit-speed="4"
|
|
71
71
|
data-skykit-exposure="2600"
|
|
72
|
-
data-skykit-look-at="
|
|
72
|
+
data-skykit-look-at="05h 36m 12.81s, −01° 12′ 06.9″"
|
|
73
73
|
data-skykit-mouse-mode="strafe"
|
|
74
74
|
data-skykit-persistent-cache="off"
|
|
75
75
|
style="width: 100%; height: 520px; background: #02040b"
|
|
@@ -77,11 +77,12 @@ Optional attributes keep small tweaks HTML-only:
|
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
`data-skykit-look-at` accepts RA/Dec text such as
|
|
80
|
-
`
|
|
81
|
-
parsec-space `x,y,z` target for exact generated
|
|
82
|
-
defaults to `grab`; use `look` or
|
|
83
|
-
direction, or `none` to disable mouse
|
|
84
|
-
storage is enabled by default for
|
|
80
|
+
`05h 36m 12.81s, −01° 12′ 06.9″`, decimal degrees such as
|
|
81
|
+
`84.053393,-1.201926`, or a parsec-space `x,y,z` target for exact generated
|
|
82
|
+
coordinates. `data-skykit-mouse-mode` defaults to `grab`; use `look` or
|
|
83
|
+
`strafe` for the first-person mouse-look direction, or `none` to disable mouse
|
|
84
|
+
drag controls. Persistent browser Cache API storage is enabled by default for
|
|
85
|
+
octree ranges; set
|
|
85
86
|
`data-skykit-persistent-cache="off"` to keep caching session-only.
|
|
86
87
|
|
|
87
88
|
The host dispatches `skykit-browser-ready` with `{ browser, viewer }` in
|
|
@@ -120,15 +121,17 @@ For small scripted interactions, use the browser handle:
|
|
|
120
121
|
<script type="module">
|
|
121
122
|
import {
|
|
122
123
|
SKYKIT_ACTIONS,
|
|
124
|
+
createRaDecLookAt,
|
|
123
125
|
createSkykitNavigationPlugin,
|
|
124
126
|
} from 'https://esm.sh/@found-in-space/skykit';
|
|
125
127
|
|
|
126
128
|
const browser = await Skykit.whenReady();
|
|
127
129
|
await browser.install(createSkykitNavigationPlugin());
|
|
130
|
+
const alnilam = createRaDecLookAt('05h 36m 12.81s', '−01° 12′ 06.9″');
|
|
128
131
|
|
|
129
132
|
document.querySelector('#orion').addEventListener('click', () => {
|
|
130
133
|
browser.viewer.actions.invoke(SKYKIT_ACTIONS.navigation.transitionTo, {
|
|
131
|
-
view: { lookAt:
|
|
134
|
+
view: { lookAt: alnilam },
|
|
132
135
|
movement: { durationSecs: 3 },
|
|
133
136
|
});
|
|
134
137
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@found-in-space/skykit",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.20260530",
|
|
4
4
|
"description": "Slim composition and teaching layer for Found in Space packages",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -71,9 +71,9 @@
|
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@found-in-space/anchored-image": "0.2.0-alpha.0",
|
|
73
73
|
"@found-in-space/hr-diagram": "0.2.0-alpha.1",
|
|
74
|
-
"@found-in-space/meta-sidecar-provider": "0.2.0-alpha.
|
|
75
|
-
"@found-in-space/spatial": "0.2.0-alpha.
|
|
76
|
-
"@found-in-space/star-octree-provider": "0.2.0-alpha.
|
|
74
|
+
"@found-in-space/meta-sidecar-provider": "0.2.0-alpha.1",
|
|
75
|
+
"@found-in-space/spatial": "0.2.0-alpha.20260529",
|
|
76
|
+
"@found-in-space/star-octree-provider": "0.2.0-alpha.1",
|
|
77
77
|
"@found-in-space/star-trees": "0.2.0-alpha.0",
|
|
78
78
|
"@found-in-space/three-star-field": "0.2.0-alpha.0"
|
|
79
79
|
},
|
|
@@ -191,6 +191,25 @@ test('createSkykitBrowser enables persistent provider cache by default and can o
|
|
|
191
191
|
});
|
|
192
192
|
});
|
|
193
193
|
|
|
194
|
+
test('createSkykitBrowser treats forbidden Cache API access as disabled', async () => {
|
|
195
|
+
await withFakeWindow(async () => {
|
|
196
|
+
await withForbiddenCaches(async () => {
|
|
197
|
+
const browser = await createSkykitBrowser({
|
|
198
|
+
host: createHost(),
|
|
199
|
+
status: false,
|
|
200
|
+
renderer: createRenderer(),
|
|
201
|
+
starField: createStarField(),
|
|
202
|
+
autoResize: false,
|
|
203
|
+
autoDispose: false,
|
|
204
|
+
autoStart: false,
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
assert.equal(browser.provider.describe().capabilities.persistentCache, false);
|
|
208
|
+
await browser.dispose();
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
194
213
|
test('browser.install adds plugins after startup and cleans returned teardowns', async () => {
|
|
195
214
|
await withFakeWindow(async () => {
|
|
196
215
|
const calls = [];
|
|
@@ -330,7 +349,7 @@ async function withFakeWindow(callback) {
|
|
|
330
349
|
}
|
|
331
350
|
|
|
332
351
|
async function withFakeCaches(callback) {
|
|
333
|
-
const previousCaches = globalThis
|
|
352
|
+
const previousCaches = Object.getOwnPropertyDescriptor(globalThis, 'caches');
|
|
334
353
|
const previousFetch = globalThis.fetch;
|
|
335
354
|
const cache = {
|
|
336
355
|
async match() {
|
|
@@ -369,14 +388,7 @@ async function withFakeCaches(callback) {
|
|
|
369
388
|
try {
|
|
370
389
|
await callback();
|
|
371
390
|
} finally {
|
|
372
|
-
|
|
373
|
-
delete globalThis.caches;
|
|
374
|
-
} else {
|
|
375
|
-
Object.defineProperty(globalThis, 'caches', {
|
|
376
|
-
configurable: true,
|
|
377
|
-
value: previousCaches,
|
|
378
|
-
});
|
|
379
|
-
}
|
|
391
|
+
restoreGlobalProperty('caches', previousCaches);
|
|
380
392
|
if (previousFetch === undefined) {
|
|
381
393
|
delete globalThis.fetch;
|
|
382
394
|
} else {
|
|
@@ -388,6 +400,36 @@ async function withFakeCaches(callback) {
|
|
|
388
400
|
}
|
|
389
401
|
}
|
|
390
402
|
|
|
403
|
+
async function withForbiddenCaches(callback) {
|
|
404
|
+
const previousCaches = Object.getOwnPropertyDescriptor(globalThis, 'caches');
|
|
405
|
+
const previousWarn = console.warn;
|
|
406
|
+
|
|
407
|
+
Object.defineProperty(globalThis, 'caches', {
|
|
408
|
+
configurable: true,
|
|
409
|
+
get() {
|
|
410
|
+
const error = new Error('Cache API storage is blocked.');
|
|
411
|
+
error.name = 'SecurityError';
|
|
412
|
+
throw error;
|
|
413
|
+
},
|
|
414
|
+
});
|
|
415
|
+
console.warn = () => {};
|
|
416
|
+
|
|
417
|
+
try {
|
|
418
|
+
await callback();
|
|
419
|
+
} finally {
|
|
420
|
+
console.warn = previousWarn;
|
|
421
|
+
restoreGlobalProperty('caches', previousCaches);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function restoreGlobalProperty(name, descriptor) {
|
|
426
|
+
if (descriptor) {
|
|
427
|
+
Object.defineProperty(globalThis, name, descriptor);
|
|
428
|
+
} else {
|
|
429
|
+
delete globalThis[name];
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
391
433
|
function createHost() {
|
|
392
434
|
return {
|
|
393
435
|
children: [],
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
createDesktopSkykitObserverRig,
|
|
18
18
|
createObject3dLayer,
|
|
19
19
|
createObject3dPlugin,
|
|
20
|
+
createRaDecLookAt,
|
|
20
21
|
createMouseLookPlugin,
|
|
21
22
|
createSkyGrabPlugin,
|
|
22
23
|
createSkykitDefaultKeyboardNavigationBindings,
|
|
@@ -313,6 +314,19 @@ test('viewer derives camera orientation from lookAt targets, sky coordinates, an
|
|
|
313
314
|
assertVectorApprox(localVectorFromView(view, { x: 0, y: 1, z: 0 }), { x: 0, y: 1, z: 0 });
|
|
314
315
|
await skyViewer.dispose();
|
|
315
316
|
|
|
317
|
+
const alnilamViewer = await createSkykitViewer({
|
|
318
|
+
renderer: createRenderer(),
|
|
319
|
+
view: {
|
|
320
|
+
lookAt: createRaDecLookAt('05h 36m 12.81s', '−01° 12′ 06.9″'),
|
|
321
|
+
},
|
|
322
|
+
});
|
|
323
|
+
view = alnilamViewer.getViewState();
|
|
324
|
+
assertVectorApprox(
|
|
325
|
+
localVectorFromView(view, { x: 0, y: 0, z: -1 }),
|
|
326
|
+
directionFromRaDec(84.053375, -1.2019166666666667),
|
|
327
|
+
);
|
|
328
|
+
await alnilamViewer.dispose();
|
|
329
|
+
|
|
316
330
|
const starViewer = await createSkykitViewer({
|
|
317
331
|
renderer: createRenderer(),
|
|
318
332
|
view: { lookAt: { star: 'hyades' } },
|
|
@@ -1539,6 +1553,17 @@ test('navigation transition action restores pose with independent lane durations
|
|
|
1539
1553
|
assert.deepEqual(viewer.getViewState().observerPc, { x: 0, y: 0, z: 0 });
|
|
1540
1554
|
assert.deepEqual(viewer.getViewState().orientationIcrs, orientationAfterExplicitTransition);
|
|
1541
1555
|
|
|
1556
|
+
await viewer.actions.invoke(SKYKIT_ACTIONS.navigation.transitionTo, {
|
|
1557
|
+
lookAt: '05:36:12.81, −01:12:06.9',
|
|
1558
|
+
orientation: { durationSecs: 1 },
|
|
1559
|
+
});
|
|
1560
|
+
viewer.update(1);
|
|
1561
|
+
viewer.update(0);
|
|
1562
|
+
assertVectorApprox(
|
|
1563
|
+
localVectorFromView(viewer.getViewState(), { x: 0, y: 0, z: -1 }),
|
|
1564
|
+
directionFromRaDec(84.053375, -1.2019166666666667),
|
|
1565
|
+
);
|
|
1566
|
+
|
|
1542
1567
|
await viewer.dispose();
|
|
1543
1568
|
});
|
|
1544
1569
|
|
|
@@ -1959,6 +1984,17 @@ function assertVectorApprox(actual, expected, epsilon = 1e-9) {
|
|
|
1959
1984
|
assert.ok(Math.abs(actual.z - expected.z) < epsilon, `z ${actual.z} !== ${expected.z}`);
|
|
1960
1985
|
}
|
|
1961
1986
|
|
|
1987
|
+
function directionFromRaDec(raDeg, decDeg) {
|
|
1988
|
+
const ra = raDeg * Math.PI / 180;
|
|
1989
|
+
const dec = decDeg * Math.PI / 180;
|
|
1990
|
+
const cosDec = Math.cos(dec);
|
|
1991
|
+
return {
|
|
1992
|
+
x: Math.cos(ra) * cosDec,
|
|
1993
|
+
y: Math.sin(ra) * cosDec,
|
|
1994
|
+
z: Math.sin(dec),
|
|
1995
|
+
};
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1962
1998
|
function createPointerTarget() {
|
|
1963
1999
|
const target = createEventTarget();
|
|
1964
2000
|
target.clientWidth = 800;
|
package/src/browser.js
CHANGED
|
@@ -6,6 +6,12 @@ import {
|
|
|
6
6
|
} from '@found-in-space/star-octree-provider';
|
|
7
7
|
import { createObserverShellStrategy } from '@found-in-space/star-trees';
|
|
8
8
|
import { createThreeStarField } from '@found-in-space/three-star-field';
|
|
9
|
+
import {
|
|
10
|
+
createRaDecLookAt,
|
|
11
|
+
parseDeclination,
|
|
12
|
+
parseRightAscension,
|
|
13
|
+
parseSpatialLookAtText,
|
|
14
|
+
} from '@found-in-space/spatial';
|
|
9
15
|
|
|
10
16
|
import { createSkykitAnimationLoop } from './animation-loop.js';
|
|
11
17
|
import { SKYKIT_ACTIONS, SKYKIT_CONTROLS } from './actions.js';
|
|
@@ -181,8 +187,12 @@ export async function createSkykitBrowser(input = {}) {
|
|
|
181
187
|
skykit: {
|
|
182
188
|
SKYKIT_ACTIONS,
|
|
183
189
|
SKYKIT_CONTROLS,
|
|
190
|
+
createRaDecLookAt,
|
|
184
191
|
createObject3dPlugin,
|
|
185
192
|
createSkykitNavigationPlugin,
|
|
193
|
+
parseDeclination,
|
|
194
|
+
parseRightAscension,
|
|
195
|
+
parseSpatialLookAtText,
|
|
186
196
|
},
|
|
187
197
|
};
|
|
188
198
|
}
|
package/src/hr-diagram.js
CHANGED
|
@@ -393,7 +393,9 @@ function cloneViewState(view) {
|
|
|
393
393
|
...view,
|
|
394
394
|
observerPc: clonePoint(view.observerPc),
|
|
395
395
|
renderObserverPosition: clonePoint(view.renderObserverPosition),
|
|
396
|
-
...(view.lookAt
|
|
396
|
+
...(view.lookAt
|
|
397
|
+
? { lookAt: typeof view.lookAt === 'object' ? { ...view.lookAt } : view.lookAt }
|
|
398
|
+
: {}),
|
|
397
399
|
...(view.targetPc ? { targetPc: clonePoint(view.targetPc) } : {}),
|
|
398
400
|
...(view.motion
|
|
399
401
|
? {
|
package/src/index.d.ts
CHANGED
|
@@ -56,7 +56,9 @@ export interface QuaternionLike {
|
|
|
56
56
|
w: number;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
export
|
|
59
|
+
export type SkykitLookAtInput = string | SkykitLookAtSpecInput;
|
|
60
|
+
|
|
61
|
+
export interface SkykitLookAtSpecInput {
|
|
60
62
|
targetPc?: Vector3Like | [number, number, number];
|
|
61
63
|
raDeg?: number;
|
|
62
64
|
raHours?: number;
|
|
@@ -68,6 +70,13 @@ export interface SkykitLookAtInput {
|
|
|
68
70
|
[key: string]: unknown;
|
|
69
71
|
}
|
|
70
72
|
|
|
73
|
+
export {
|
|
74
|
+
createRaDecLookAt,
|
|
75
|
+
parseDeclination,
|
|
76
|
+
parseRightAscension,
|
|
77
|
+
parseSpatialLookAtText,
|
|
78
|
+
} from '@found-in-space/spatial';
|
|
79
|
+
|
|
71
80
|
export interface SkykitObserverMotion {
|
|
72
81
|
velocityPcPerSec: Vector3Like;
|
|
73
82
|
speedPcPerSec: number;
|
package/src/index.js
CHANGED
|
@@ -12,6 +12,12 @@ export {
|
|
|
12
12
|
} from './actions.js';
|
|
13
13
|
export { createSkykitAnimationLoop } from './animation-loop.js';
|
|
14
14
|
export { createSkykitDebugBridge, installSkykitDebugGlobal } from './debug.js';
|
|
15
|
+
export {
|
|
16
|
+
createRaDecLookAt,
|
|
17
|
+
parseDeclination,
|
|
18
|
+
parseRightAscension,
|
|
19
|
+
parseSpatialLookAtText,
|
|
20
|
+
} from '@found-in-space/spatial';
|
|
15
21
|
export { createSkykitHrDiagramPlugin } from './hr-diagram.js';
|
|
16
22
|
export { createObject3dLayer } from './layers.js';
|
|
17
23
|
export { createDesktopSkykitObserverRig } from './observer-rig.js';
|
package/src/utils.js
CHANGED
|
@@ -211,6 +211,7 @@ function resolveViewLook(input, observerPc, options = {}) {
|
|
|
211
211
|
* @returns {import('./index.d.ts').SkykitLookAtInput | null}
|
|
212
212
|
*/
|
|
213
213
|
function cloneLookAt(lookAt) {
|
|
214
|
+
if (typeof lookAt === 'string') return lookAt;
|
|
214
215
|
if (!lookAt || typeof lookAt !== 'object') return null;
|
|
215
216
|
const source = /** @type {Record<string, unknown>} */ (lookAt);
|
|
216
217
|
return {
|