@farmslot/adapter-web 0.10.1 → 0.10.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.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,10 @@ All notable changes to `@farmslot/adapter-web` are tracked here.
6
6
 
7
7
  - Active-development baseline; add user-facing changes here before release or package publication.
8
8
 
9
+ ## 0.10.2 - 2026-10-15
10
+
11
+ - Share the wallet screenshot HUD's bottom-dock layout, reserving footer space and restoring page padding when cleared or replaced.
12
+
9
13
  ## 0.10.1 - 2026-10-15
10
14
 
11
15
  - Align the installed dependency closure with protocol 0.45.0 and retained-run stack attachment.
@@ -10,6 +10,8 @@ export function hudFile(runtimeDir: any): string;
10
10
  export function readHudState(runtimeDir: any): any;
11
11
  export function writeHudState(runtimeDir: any, state: any): void;
12
12
  export function clearHudState(runtimeDir: any): void;
13
- export function hudRenderExpression(state: any, appOrigin: any): string;
13
+ export function hudRenderExpression(state: any, appOrigin: any, { layout }?: {
14
+ layout?: string | undefined;
15
+ }): string;
14
16
  export const HUD_ELEMENT: "mm-harness-hud";
15
17
  export const HUD_FILE: "hud.json";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farmslot/adapter-web",
3
- "version": "0.10.1",
3
+ "version": "0.10.2",
4
4
  "description": "Web platform adapter for Farmslot recipes: resolve and launch an isolated Chromium, own its CDP port, load unpacked extensions, and keep macOS focus.",
5
5
  "type": "commonjs",
6
6
  "exports": {
@@ -7,8 +7,8 @@
7
7
  // It sits over the chart's top-left corner, below the chart toolbar, away from
8
8
  // the nav bar, the order form, the order rows and the bottom-left dev badge.
9
9
  // State lives in <runtime>/hud.json so the wallet host can redraw it after
10
- // every navigation; the expression only draws on the app origin, never inside
11
- // MetaMask's extension pages.
10
+ // every navigation; the expression draws only on the selected origin.
11
+ // A bottom dock reserves page space for wallet screenshots.
12
12
 
13
13
  import { readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
14
14
  import path from 'node:path';
@@ -117,18 +117,28 @@ const STYLE = `
117
117
  `;
118
118
 
119
119
  // A self-contained page expression: draws (or clears, for null) the HUD when
120
- // the document is on the app origin, and skips the work when the same state
121
- // is already drawn.
122
- export function hudRenderExpression(state, appOrigin) {
120
+ // the document is on the selected origin, and skips an unchanged state/layout.
121
+ // The wallet screenshot consumer uses bottom-dock to keep footer controls clear.
122
+ export function hudRenderExpression(state, appOrigin, { layout = 'card' } = {}) {
123
123
  return `(() => {
124
124
  const state = ${JSON.stringify(state ?? null)};
125
+ const layout = ${JSON.stringify(layout)};
126
+ const docked = layout === 'bottom-dock';
125
127
  if (location.origin !== ${JSON.stringify(String(appOrigin).replace(/\/$/u, ''))}) return { hud: false, reason: 'not-app-origin' };
126
128
  const existing = document.documentElement.querySelector(':scope > ${HUD_ELEMENT}');
127
- if (!state) { existing?.remove(); return { hud: false, cleared: true }; }
128
- if (existing && existing.dataset.seq === String(state.seq)) return (${waitForHudPaint.toString()})(requestAnimationFrame).then(() => ({ hud: true, seq: state.seq, unchanged: true }));
129
- existing?.remove();
129
+ const remove = () => {
130
+ if (existing?.dataset.layout === 'bottom-dock') {
131
+ document.body.style.paddingBottom = existing.dataset.previousPadding;
132
+ document.getElementById('${HUD_ELEMENT}-space')?.remove();
133
+ }
134
+ existing?.remove();
135
+ };
136
+ if (!state) { remove(); return { hud: false, cleared: true }; }
137
+ if (existing && existing.dataset.seq === String(state.seq) && existing.dataset.layout === layout) return (${waitForHudPaint.toString()})(requestAnimationFrame).then(() => ({ hud: true, seq: state.seq, unchanged: true }));
138
+ remove();
130
139
  const host = document.createElement('${HUD_ELEMENT}');
131
140
  host.dataset.seq = String(state.seq);
141
+ host.dataset.layout = layout;
132
142
  host.setAttribute('data-farmslot-hud-node', state.current?.nodeId || '');
133
143
  host.setAttribute('aria-hidden', 'true');
134
144
  host.inert = true;
@@ -137,7 +147,9 @@ export function hudRenderExpression(state, appOrigin) {
137
147
  const el = (tag, cls, value) => { const node = document.createElement(tag); if (cls) node.className = cls; if (value != null) node.textContent = value; return node; };
138
148
  const style = el('style', null, ${JSON.stringify(STYLE)});
139
149
  const box = el('div', 'hud');
140
- if (state.position) {
150
+ if (docked) {
151
+ Object.assign(box.style, { top: 'auto', bottom: '0', left: '0', right: '0', width: '100vw', maxWidth: 'none', maxHeight: 'none', borderRadius: '0', padding: '5px 8px' });
152
+ } else if (state.position) {
141
153
  box.style.top = state.position === 'top' ? '12px' : 'auto';
142
154
  box.style.bottom = state.position === 'bottom' ? '12px' : 'auto';
143
155
  }
@@ -165,6 +177,18 @@ export function hudRenderExpression(state, appOrigin) {
165
177
  if (state.last && state.last.error) box.append(el('div', 'last error', state.last.error));
166
178
  root.append(style, box);
167
179
  document.documentElement.append(host);
168
- return (${waitForHudPaint.toString()})(requestAnimationFrame).then(() => ({ hud: true, seq: state.seq }));
180
+ let height;
181
+ if (docked) {
182
+ height = Math.ceil(box.getBoundingClientRect().height);
183
+ host.dataset.previousPadding = document.body.style.paddingBottom;
184
+ const space = el('div');
185
+ space.id = '${HUD_ELEMENT}-space';
186
+ space.setAttribute('aria-hidden', 'true');
187
+ space.inert = true;
188
+ Object.assign(space.style, { display: 'block', height: height + 'px', pointerEvents: 'none' });
189
+ document.body.append(space);
190
+ document.body.style.paddingBottom = height + 'px';
191
+ }
192
+ return (${waitForHudPaint.toString()})(requestAnimationFrame).then(() => ({ hud: true, seq: state.seq, ...(docked ? { docked: true, height } : {}) }));
169
193
  })()`;
170
194
  }