sh3-core 0.16.1 → 0.17.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 (131) hide show
  1. package/dist/Sh3.svelte +50 -108
  2. package/dist/__screenshots__/handheld.browser.test.ts/handheld-viewport-flip-e2e-viewport-override-flips-chrome-and-body-branches-1.png +0 -0
  3. package/dist/actions/ctx-actions.svelte.test.js +4 -4
  4. package/dist/actions/listActionsFromEntries.test.js +29 -0
  5. package/dist/actions/listActive.js +2 -0
  6. package/dist/actions/listeners.js +4 -0
  7. package/dist/actions/programmatic-dispatch.svelte.test.js +9 -2
  8. package/dist/actions/types.d.ts +8 -0
  9. package/dist/api.d.ts +6 -1
  10. package/dist/api.js +1 -0
  11. package/dist/chrome/CompactChrome.svelte +96 -0
  12. package/dist/chrome/CompactChrome.svelte.d.ts +3 -0
  13. package/dist/chrome/CompactChrome.svelte.test.d.ts +1 -0
  14. package/dist/chrome/CompactChrome.svelte.test.js +67 -0
  15. package/dist/chrome/MenuSheet.svelte +224 -0
  16. package/dist/chrome/MenuSheet.svelte.d.ts +7 -0
  17. package/dist/chrome/MenuSheet.svelte.test.d.ts +1 -0
  18. package/dist/chrome/MenuSheet.svelte.test.js +46 -0
  19. package/dist/contributions/index.d.ts +1 -1
  20. package/dist/contributions/index.js +1 -1
  21. package/dist/contributions/registry.d.ts +17 -1
  22. package/dist/contributions/registry.js +50 -2
  23. package/dist/contributions/scope.test.d.ts +1 -0
  24. package/dist/contributions/scope.test.js +52 -0
  25. package/dist/contributions/types.d.ts +11 -3
  26. package/dist/createShell.js +7 -1
  27. package/dist/fields/address.d.ts +3 -0
  28. package/dist/fields/address.js +36 -0
  29. package/dist/fields/address.test.d.ts +1 -0
  30. package/dist/fields/address.test.js +34 -0
  31. package/dist/fields/decoration.d.ts +7 -0
  32. package/dist/fields/decoration.js +199 -0
  33. package/dist/fields/decoration.svelte.test.d.ts +1 -0
  34. package/dist/fields/decoration.svelte.test.js +177 -0
  35. package/dist/fields/dispatch.d.ts +22 -0
  36. package/dist/fields/dispatch.js +254 -0
  37. package/dist/fields/dispatch.test.d.ts +1 -0
  38. package/dist/fields/dispatch.test.js +175 -0
  39. package/dist/fields/types.d.ts +101 -0
  40. package/dist/fields/types.js +16 -0
  41. package/dist/fields/walker.svelte.test.d.ts +1 -0
  42. package/dist/fields/walker.svelte.test.js +138 -0
  43. package/dist/handheld.browser.test.d.ts +1 -0
  44. package/dist/handheld.browser.test.js +90 -0
  45. package/dist/host.js +27 -2
  46. package/dist/host.svelte.test.d.ts +1 -0
  47. package/dist/host.svelte.test.js +92 -0
  48. package/dist/layout/LayoutRenderer.svelte +12 -1
  49. package/dist/layout/LayoutRenderer.svelte.d.ts +2 -1
  50. package/dist/layout/compact/CompactRenderer.svelte +53 -0
  51. package/dist/layout/compact/CompactRenderer.svelte.d.ts +3 -0
  52. package/dist/layout/compact/CompactRenderer.svelte.test.d.ts +1 -0
  53. package/dist/layout/compact/CompactRenderer.svelte.test.js +76 -0
  54. package/dist/layout/compact/derive.d.ts +3 -0
  55. package/dist/layout/compact/derive.js +155 -0
  56. package/dist/layout/compact/derive.test.d.ts +1 -0
  57. package/dist/layout/compact/derive.test.js +160 -0
  58. package/dist/layout/compact/drawerStore.svelte.d.ts +21 -0
  59. package/dist/layout/compact/drawerStore.svelte.js +75 -0
  60. package/dist/layout/compact/drawerStore.svelte.test.d.ts +1 -0
  61. package/dist/layout/compact/drawerStore.svelte.test.js +43 -0
  62. package/dist/layout/compact/resolveRole.d.ts +6 -0
  63. package/dist/layout/compact/resolveRole.js +13 -0
  64. package/dist/layout/compact/resolveRole.test.d.ts +1 -0
  65. package/dist/layout/compact/resolveRole.test.js +18 -0
  66. package/dist/layout/compact/types.d.ts +27 -0
  67. package/dist/layout/compact/types.js +15 -0
  68. package/dist/layout/presets.compactVariant.test.d.ts +1 -0
  69. package/dist/layout/presets.compactVariant.test.js +27 -0
  70. package/dist/layout/presets.d.ts +12 -0
  71. package/dist/layout/presets.js +16 -0
  72. package/dist/layout/slotHostPool.svelte.d.ts +8 -0
  73. package/dist/layout/slotHostPool.svelte.js +14 -1
  74. package/dist/layout/store.drawers.svelte.test.d.ts +1 -0
  75. package/dist/layout/store.drawers.svelte.test.js +49 -0
  76. package/dist/layout/store.schemaVersion.test.d.ts +1 -0
  77. package/dist/layout/store.schemaVersion.test.js +35 -0
  78. package/dist/layout/store.svelte.js +52 -2
  79. package/dist/layout/types.d.ts +43 -1
  80. package/dist/layout/types.js +1 -1
  81. package/dist/overlays/DrawerSurface.svelte +141 -0
  82. package/dist/overlays/DrawerSurface.svelte.d.ts +12 -0
  83. package/dist/overlays/DrawerSurface.svelte.test.d.ts +1 -0
  84. package/dist/overlays/DrawerSurface.svelte.test.js +67 -0
  85. package/dist/overlays/OverlayRoots.svelte +89 -0
  86. package/dist/overlays/OverlayRoots.svelte.d.ts +3 -0
  87. package/dist/overlays/types.d.ts +1 -1
  88. package/dist/platform/tauri-backend.d.ts +3 -3
  89. package/dist/platform/tauri-backend.js +24 -3
  90. package/dist/projects/session-state.svelte.d.ts +3 -3
  91. package/dist/projects/session-state.svelte.js +5 -4
  92. package/dist/runtime/runVerb.js +2 -2
  93. package/dist/satellite/SatelliteShell.svelte +58 -11
  94. package/dist/satellite/SatelliteShell.svelte.test.d.ts +1 -0
  95. package/dist/satellite/SatelliteShell.svelte.test.js +61 -0
  96. package/dist/sh3Api/fields-walker.svelte.test.d.ts +1 -0
  97. package/dist/sh3Api/fields-walker.svelte.test.js +75 -0
  98. package/dist/sh3Api/headless.d.ts +9 -0
  99. package/dist/sh3Api/headless.js +171 -16
  100. package/dist/sh3Api/headless.svelte.test.js +54 -10
  101. package/dist/sh3Runtime.svelte.d.ts +36 -0
  102. package/dist/sh3Runtime.svelte.js +33 -0
  103. package/dist/sh3core-shard/sh3coreShard.svelte.js +2 -2
  104. package/dist/shards/activate-fields.svelte.test.d.ts +1 -0
  105. package/dist/shards/activate-fields.svelte.test.js +121 -0
  106. package/dist/shards/activate-runtime.test.js +8 -8
  107. package/dist/shards/activate.svelte.js +29 -35
  108. package/dist/shards/types.d.ts +23 -76
  109. package/dist/shell-shard/ScrollbackView.svelte +55 -9
  110. package/dist/shell-shard/Terminal.svelte +1 -1
  111. package/dist/shell-shard/scrollback-stick.d.ts +9 -0
  112. package/dist/shell-shard/scrollback-stick.js +21 -0
  113. package/dist/shell-shard/scrollback-stick.test.d.ts +1 -0
  114. package/dist/shell-shard/scrollback-stick.test.js +25 -0
  115. package/dist/tokens.css +3 -2
  116. package/dist/verbs/types.d.ts +59 -1
  117. package/dist/version.d.ts +1 -1
  118. package/dist/version.js +1 -1
  119. package/dist/viewport/classify.d.ts +8 -0
  120. package/dist/viewport/classify.js +20 -0
  121. package/dist/viewport/classify.test.d.ts +1 -0
  122. package/dist/viewport/classify.test.js +32 -0
  123. package/dist/viewport/store.browser.test.d.ts +1 -0
  124. package/dist/viewport/store.browser.test.js +33 -0
  125. package/dist/viewport/store.svelte.d.ts +9 -0
  126. package/dist/viewport/store.svelte.js +71 -0
  127. package/dist/viewport/store.svelte.test.d.ts +1 -0
  128. package/dist/viewport/store.svelte.test.js +54 -0
  129. package/dist/viewport/types.d.ts +9 -0
  130. package/dist/viewport/types.js +6 -0
  131. package/package.json +1 -1
@@ -0,0 +1,32 @@
1
+ /*
2
+ * Table-driven tests for the viewport classifier. Each row is a real
3
+ * device (or a deliberately-chosen edge case) with the signal tuple
4
+ * expected from a real browser/matchMedia in that device's typical
5
+ * orientation.
6
+ */
7
+ import { describe, it, expect } from 'vitest';
8
+ import { classify } from './classify';
9
+ const ROWS = [
10
+ { name: 'phone portrait', width: 393, coarsePointer: true, noHover: true, dpr: 3, expected: 'compact' },
11
+ { name: 'phone landscape', width: 852, coarsePointer: true, noHover: true, dpr: 3, expected: 'compact' },
12
+ { name: 'tablet portrait', width: 768, coarsePointer: true, noHover: true, dpr: 2, expected: 'compact' },
13
+ { name: 'tablet landscape', width: 1024, coarsePointer: true, noHover: true, dpr: 2, expected: 'compact' },
14
+ { name: 'desktop wide', width: 1920, coarsePointer: false, noHover: false, dpr: 1, expected: 'desktop' },
15
+ { name: 'desktop narrow window', width: 700, coarsePointer: false, noHover: false, dpr: 1, expected: 'compact' },
16
+ { name: 'iPad with mouse attached', width: 1024, coarsePointer: false, noHover: false, dpr: 2, expected: 'desktop' },
17
+ { name: 'small laptop', width: 1366, coarsePointer: false, noHover: false, dpr: 1, expected: 'desktop' },
18
+ { name: 'phone with stylus (hover ok)', width: 412, coarsePointer: true, noHover: false, dpr: 3, expected: 'compact' },
19
+ ];
20
+ describe('classify', () => {
21
+ for (const row of ROWS) {
22
+ it(`${row.name} → ${row.expected}`, () => {
23
+ const result = classify({
24
+ width: row.width,
25
+ coarsePointer: row.coarsePointer,
26
+ noHover: row.noHover,
27
+ dpr: row.dpr,
28
+ });
29
+ expect(result).toBe(row.expected);
30
+ });
31
+ }
32
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,33 @@
1
+ /*
2
+ * Real-signal viewport classification — boots the viewport store under
3
+ * Chromium and asserts initial class + override behavior. happy-dom's
4
+ * matchMedia stub is shallow, so this is the contract pin against a
5
+ * real browser engine.
6
+ */
7
+ import { describe, it, expect, beforeEach } from 'vitest';
8
+ import { viewportStore } from './store.svelte';
9
+ beforeEach(() => {
10
+ viewportStore.__reset();
11
+ });
12
+ describe('viewport store under real browser', () => {
13
+ it('returns a viewport class consistent with the test runner window', () => {
14
+ const info = viewportStore.current;
15
+ expect(info.class).toMatch(/desktop|compact/);
16
+ expect(info.width).toBeGreaterThan(0);
17
+ expect(info.height).toBeGreaterThan(0);
18
+ });
19
+ it('override(compact) immediately flips class', () => {
20
+ const fires = [];
21
+ const unsub = viewportStore.subscribe((i) => fires.push(i.class));
22
+ viewportStore.override('compact');
23
+ expect(viewportStore.current.class).toBe('compact');
24
+ expect(fires).toContain('compact');
25
+ unsub();
26
+ });
27
+ it('override(null) restores auto-derived class', () => {
28
+ viewportStore.override('compact');
29
+ expect(viewportStore.pinned).toBe('compact');
30
+ viewportStore.override(null);
31
+ expect(viewportStore.pinned).toBeNull();
32
+ });
33
+ });
@@ -0,0 +1,9 @@
1
+ import type { ViewportClass, ViewportInfo } from './types';
2
+ export declare const viewportStore: {
3
+ readonly current: ViewportInfo;
4
+ subscribe(cb: (i: ViewportInfo) => void): () => void;
5
+ override(cls: ViewportClass | null): void;
6
+ readonly pinned: ViewportClass | null;
7
+ /** Test-only reset hook. Not exported from index.ts. */
8
+ __reset(): void;
9
+ };
@@ -0,0 +1,71 @@
1
+ /*
2
+ * viewport store — reactive ViewportInfo with subscribe + override.
3
+ *
4
+ * Subscribes to window.resize, screen.orientation.change, and matchMedia
5
+ * change events for `pointer: coarse` / `hover: none`. Re-runs classify(),
6
+ * notifies subscribers only on class change (not every resize tick).
7
+ *
8
+ * Module is loaded eagerly by createShell, but the listener-wiring branch
9
+ * is gated on `typeof window` so node-only test runs don't crash.
10
+ */
11
+ import { classify } from './classify';
12
+ let pinnedClass = $state(null);
13
+ const subscribers = new Set();
14
+ function read() {
15
+ if (typeof window === 'undefined') {
16
+ return { class: 'desktop', width: 1920, height: 1080, coarsePointer: false, noHover: false, dpr: 1 };
17
+ }
18
+ const width = window.innerWidth;
19
+ const height = window.innerHeight;
20
+ const coarsePointer = window.matchMedia('(pointer: coarse)').matches;
21
+ const noHover = window.matchMedia('(hover: none)').matches;
22
+ const dpr = window.devicePixelRatio;
23
+ const cls = pinnedClass !== null && pinnedClass !== void 0 ? pinnedClass : classify({ width, coarsePointer, noHover, dpr });
24
+ return { class: cls, width, height, coarsePointer, noHover, dpr };
25
+ }
26
+ let cached = $state(read());
27
+ function recompute() {
28
+ const next = read();
29
+ const prevClass = cached.class;
30
+ cached = next;
31
+ if (next.class !== prevClass) {
32
+ for (const cb of subscribers)
33
+ cb(next);
34
+ }
35
+ }
36
+ if (typeof window !== 'undefined') {
37
+ window.addEventListener('resize', recompute);
38
+ window.matchMedia('(pointer: coarse)').addEventListener('change', recompute);
39
+ window.matchMedia('(hover: none)').addEventListener('change', recompute);
40
+ if (typeof screen !== 'undefined' && screen.orientation) {
41
+ screen.orientation.addEventListener('change', recompute);
42
+ }
43
+ }
44
+ export const viewportStore = {
45
+ get current() {
46
+ return cached;
47
+ },
48
+ subscribe(cb) {
49
+ subscribers.add(cb);
50
+ return () => { subscribers.delete(cb); };
51
+ },
52
+ override(cls) {
53
+ if (pinnedClass === cls)
54
+ return;
55
+ pinnedClass = cls;
56
+ recompute();
57
+ // recompute only fires subscribers on class change. If override pins
58
+ // to the same class as the auto-derived one, the visible class doesn't
59
+ // change. Force-fire so consumers re-read the override state.
60
+ for (const cb of subscribers)
61
+ cb(cached);
62
+ },
63
+ get pinned() {
64
+ return pinnedClass;
65
+ },
66
+ /** Test-only reset hook. Not exported from index.ts. */
67
+ __reset() {
68
+ pinnedClass = null;
69
+ subscribers.clear();
70
+ },
71
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,54 @@
1
+ /*
2
+ * DOM tests for the viewport store. happy-dom's matchMedia stub returns
3
+ * { matches: false, addEventListener, removeEventListener } so we can
4
+ * verify the wiring without driving the real browser engine.
5
+ *
6
+ * These tests intentionally use the store's __reset hook between cases
7
+ * to isolate subscriber state.
8
+ */
9
+ import { describe, it, expect, beforeEach } from 'vitest';
10
+ import { viewportStore } from './store.svelte';
11
+ describe('viewport store (dom)', () => {
12
+ beforeEach(() => {
13
+ viewportStore.__reset();
14
+ });
15
+ it('current returns a ViewportInfo with shape', () => {
16
+ const info = viewportStore.current;
17
+ expect(info.class).toMatch(/desktop|compact/);
18
+ expect(typeof info.width).toBe('number');
19
+ expect(typeof info.height).toBe('number');
20
+ });
21
+ it('override(compact) flips class to compact', () => {
22
+ viewportStore.override('compact');
23
+ expect(viewportStore.current.class).toBe('compact');
24
+ expect(viewportStore.pinned).toBe('compact');
25
+ });
26
+ it('override(null) restores pinned to null', () => {
27
+ viewportStore.override('compact');
28
+ viewportStore.override(null);
29
+ expect(viewportStore.pinned).toBeNull();
30
+ });
31
+ it('subscribers fire on class change via override', () => {
32
+ const fires = [];
33
+ const unsub = viewportStore.subscribe((i) => fires.push(i.class));
34
+ viewportStore.override('compact');
35
+ expect(fires).toContain('compact');
36
+ unsub();
37
+ });
38
+ it('subscribers fire on override even when class does not change', () => {
39
+ // Auto-class on happy-dom is desktop (default width 1024 + fine pointer).
40
+ // override('desktop') should still fire so consumers see pin state change.
41
+ const fires = [];
42
+ const unsub = viewportStore.subscribe((i) => fires.push(i.class));
43
+ viewportStore.override('desktop');
44
+ expect(fires.length).toBeGreaterThan(0);
45
+ unsub();
46
+ });
47
+ it('unsubscribe stops further notifications', () => {
48
+ const fires = [];
49
+ const unsub = viewportStore.subscribe((i) => fires.push(i.class));
50
+ unsub();
51
+ viewportStore.override('compact');
52
+ expect(fires).toEqual([]);
53
+ });
54
+ });
@@ -0,0 +1,9 @@
1
+ export type ViewportClass = 'desktop' | 'compact';
2
+ export interface ViewportInfo {
3
+ class: ViewportClass;
4
+ width: number;
5
+ height: number;
6
+ coarsePointer: boolean;
7
+ noHover: boolean;
8
+ dpr: number;
9
+ }
@@ -0,0 +1,6 @@
1
+ /*
2
+ * Viewport class types. The classifier (./classify.ts) is pure; the
3
+ * store (./store.svelte.ts) wires it to matchMedia and exposes a
4
+ * reactive ViewportInfo via Sh3.viewport.
5
+ */
6
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sh3-core",
3
- "version": "0.16.1",
3
+ "version": "0.17.2",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"