@fiodos/web-core 0.1.3 → 0.1.4
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/dist/cjs/orb/mountOrb.js +30 -7
- package/dist/esm/orb/mountOrb.js +31 -8
- package/package.json +1 -1
package/dist/cjs/orb/mountOrb.js
CHANGED
|
@@ -65,6 +65,18 @@ function ensureStyles() {
|
|
|
65
65
|
el.textContent = CSS;
|
|
66
66
|
document.head.appendChild(el);
|
|
67
67
|
}
|
|
68
|
+
// Content box of the layout viewport. `documentElement.clientWidth/Height`
|
|
69
|
+
// EXCLUDE a classic scrollbar that occupies real width/height (Windows, some
|
|
70
|
+
// Linux/Chromium); overlay scrollbars (macOS, mobile) report the same value as
|
|
71
|
+
// the layout viewport. Anchoring against this — not `innerWidth` — keeps a
|
|
72
|
+
// right/bottom-edge orb just INSIDE the scrollbar instead of under/over it.
|
|
73
|
+
function viewportContentSize() {
|
|
74
|
+
const de = typeof document !== 'undefined' ? document.documentElement : null;
|
|
75
|
+
return {
|
|
76
|
+
width: de?.clientWidth || window.innerWidth,
|
|
77
|
+
height: de?.clientHeight || window.innerHeight,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
68
80
|
function cornerToPosition(corner) {
|
|
69
81
|
switch (corner) {
|
|
70
82
|
case 'bottom-left':
|
|
@@ -161,14 +173,15 @@ function mountOrb(controller, options = {}) {
|
|
|
161
173
|
}
|
|
162
174
|
function reposition() {
|
|
163
175
|
const size = orbDiameterPx();
|
|
164
|
-
const
|
|
176
|
+
const content = viewportContentSize();
|
|
177
|
+
const { left, top } = (0, core_1.resolveOrbAnchorPx)({
|
|
165
178
|
viewportWidth: window.innerWidth,
|
|
166
179
|
viewportHeight: window.innerHeight,
|
|
180
|
+
contentWidth: content.width,
|
|
181
|
+
contentHeight: content.height,
|
|
167
182
|
orbDiameter: size,
|
|
168
183
|
position: effectivePosition(),
|
|
169
184
|
});
|
|
170
|
-
const left = Math.max(8, window.innerWidth - insets.right - size);
|
|
171
|
-
const top = Math.max(8, window.innerHeight - insets.bottom - size);
|
|
172
185
|
root.style.left = `${left}px`;
|
|
173
186
|
root.style.top = `${top}px`;
|
|
174
187
|
root.style.right = '';
|
|
@@ -197,6 +210,14 @@ function mountOrb(controller, options = {}) {
|
|
|
197
210
|
}
|
|
198
211
|
}
|
|
199
212
|
window.addEventListener('resize', reposition);
|
|
213
|
+
// Recalc when a scrollbar appears/disappears as the page content changes (the
|
|
214
|
+
// content box shrinks/grows even when the window size doesn't), so the orb
|
|
215
|
+
// never ends up overlapped by — or detached from — the scrollbar edge.
|
|
216
|
+
let contentObserver;
|
|
217
|
+
if (typeof ResizeObserver !== 'undefined' && document.documentElement) {
|
|
218
|
+
contentObserver = new ResizeObserver(() => reposition());
|
|
219
|
+
contentObserver.observe(document.documentElement);
|
|
220
|
+
}
|
|
200
221
|
// Keep the conversation bar above the keyboard as the visual viewport resizes
|
|
201
222
|
// (keyboard open/close) or scrolls on mobile browsers.
|
|
202
223
|
const visualViewport = window.visualViewport;
|
|
@@ -240,9 +261,10 @@ function mountOrb(controller, options = {}) {
|
|
|
240
261
|
dragging = true;
|
|
241
262
|
e.preventDefault();
|
|
242
263
|
const size = orbDiameterPx();
|
|
264
|
+
const content = viewportContentSize();
|
|
243
265
|
const margin = 8;
|
|
244
|
-
const maxLeft =
|
|
245
|
-
const maxTop =
|
|
266
|
+
const maxLeft = content.width - margin - size;
|
|
267
|
+
const maxTop = content.height - margin - size;
|
|
246
268
|
const left = Math.min(maxLeft, Math.max(margin, originLeft + dx));
|
|
247
269
|
const top = Math.min(maxTop, Math.max(margin, originTop + dy));
|
|
248
270
|
root.style.left = `${left}px`;
|
|
@@ -252,8 +274,8 @@ function mountOrb(controller, options = {}) {
|
|
|
252
274
|
draggedPosition = (0, core_1.viewportPixelsToOrbScreenPosition)({
|
|
253
275
|
centerX: left + size / 2,
|
|
254
276
|
centerY: top + size / 2,
|
|
255
|
-
viewportWidth:
|
|
256
|
-
viewportHeight:
|
|
277
|
+
viewportWidth: content.width,
|
|
278
|
+
viewportHeight: content.height,
|
|
257
279
|
orbDiameter: size,
|
|
258
280
|
});
|
|
259
281
|
applyDeployment();
|
|
@@ -688,6 +710,7 @@ function mountOrb(controller, options = {}) {
|
|
|
688
710
|
unsubscribe();
|
|
689
711
|
stopWatch();
|
|
690
712
|
window.removeEventListener('resize', reposition);
|
|
713
|
+
contentObserver?.disconnect();
|
|
691
714
|
visualViewport?.removeEventListener('resize', onViewportChange);
|
|
692
715
|
visualViewport?.removeEventListener('scroll', onViewportChange);
|
|
693
716
|
clearOverlay();
|
package/dist/esm/orb/mountOrb.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* - CONFIRMATIONS: the same security model (manifest decides; strict phrase /
|
|
17
17
|
* deliberate tap for payment-grade; loose "yes" never resolves strict).
|
|
18
18
|
*/
|
|
19
|
-
import { DEFAULT_ORB_SCREEN_POSITION, createWebOrbHaptics,
|
|
19
|
+
import { DEFAULT_ORB_SCREEN_POSITION, createWebOrbHaptics, resolveOrbAnchorPx, resolveOrbDeployment, snapOrbScreenPositionToSide, viewportPixelsToOrbScreenPosition, } from '@fiodos/core';
|
|
20
20
|
import { buildKeyboardChip, createOrbVisual, DEFAULT_ORB_APPEARANCE, } from './orbView.js';
|
|
21
21
|
import { watchPublishedConfig } from './publishedConfig.js';
|
|
22
22
|
const STYLE_ID = 'fyodos-orb-styles';
|
|
@@ -62,6 +62,18 @@ function ensureStyles() {
|
|
|
62
62
|
el.textContent = CSS;
|
|
63
63
|
document.head.appendChild(el);
|
|
64
64
|
}
|
|
65
|
+
// Content box of the layout viewport. `documentElement.clientWidth/Height`
|
|
66
|
+
// EXCLUDE a classic scrollbar that occupies real width/height (Windows, some
|
|
67
|
+
// Linux/Chromium); overlay scrollbars (macOS, mobile) report the same value as
|
|
68
|
+
// the layout viewport. Anchoring against this — not `innerWidth` — keeps a
|
|
69
|
+
// right/bottom-edge orb just INSIDE the scrollbar instead of under/over it.
|
|
70
|
+
function viewportContentSize() {
|
|
71
|
+
const de = typeof document !== 'undefined' ? document.documentElement : null;
|
|
72
|
+
return {
|
|
73
|
+
width: de?.clientWidth || window.innerWidth,
|
|
74
|
+
height: de?.clientHeight || window.innerHeight,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
65
77
|
function cornerToPosition(corner) {
|
|
66
78
|
switch (corner) {
|
|
67
79
|
case 'bottom-left':
|
|
@@ -158,14 +170,15 @@ export function mountOrb(controller, options = {}) {
|
|
|
158
170
|
}
|
|
159
171
|
function reposition() {
|
|
160
172
|
const size = orbDiameterPx();
|
|
161
|
-
const
|
|
173
|
+
const content = viewportContentSize();
|
|
174
|
+
const { left, top } = resolveOrbAnchorPx({
|
|
162
175
|
viewportWidth: window.innerWidth,
|
|
163
176
|
viewportHeight: window.innerHeight,
|
|
177
|
+
contentWidth: content.width,
|
|
178
|
+
contentHeight: content.height,
|
|
164
179
|
orbDiameter: size,
|
|
165
180
|
position: effectivePosition(),
|
|
166
181
|
});
|
|
167
|
-
const left = Math.max(8, window.innerWidth - insets.right - size);
|
|
168
|
-
const top = Math.max(8, window.innerHeight - insets.bottom - size);
|
|
169
182
|
root.style.left = `${left}px`;
|
|
170
183
|
root.style.top = `${top}px`;
|
|
171
184
|
root.style.right = '';
|
|
@@ -194,6 +207,14 @@ export function mountOrb(controller, options = {}) {
|
|
|
194
207
|
}
|
|
195
208
|
}
|
|
196
209
|
window.addEventListener('resize', reposition);
|
|
210
|
+
// Recalc when a scrollbar appears/disappears as the page content changes (the
|
|
211
|
+
// content box shrinks/grows even when the window size doesn't), so the orb
|
|
212
|
+
// never ends up overlapped by — or detached from — the scrollbar edge.
|
|
213
|
+
let contentObserver;
|
|
214
|
+
if (typeof ResizeObserver !== 'undefined' && document.documentElement) {
|
|
215
|
+
contentObserver = new ResizeObserver(() => reposition());
|
|
216
|
+
contentObserver.observe(document.documentElement);
|
|
217
|
+
}
|
|
197
218
|
// Keep the conversation bar above the keyboard as the visual viewport resizes
|
|
198
219
|
// (keyboard open/close) or scrolls on mobile browsers.
|
|
199
220
|
const visualViewport = window.visualViewport;
|
|
@@ -237,9 +258,10 @@ export function mountOrb(controller, options = {}) {
|
|
|
237
258
|
dragging = true;
|
|
238
259
|
e.preventDefault();
|
|
239
260
|
const size = orbDiameterPx();
|
|
261
|
+
const content = viewportContentSize();
|
|
240
262
|
const margin = 8;
|
|
241
|
-
const maxLeft =
|
|
242
|
-
const maxTop =
|
|
263
|
+
const maxLeft = content.width - margin - size;
|
|
264
|
+
const maxTop = content.height - margin - size;
|
|
243
265
|
const left = Math.min(maxLeft, Math.max(margin, originLeft + dx));
|
|
244
266
|
const top = Math.min(maxTop, Math.max(margin, originTop + dy));
|
|
245
267
|
root.style.left = `${left}px`;
|
|
@@ -249,8 +271,8 @@ export function mountOrb(controller, options = {}) {
|
|
|
249
271
|
draggedPosition = viewportPixelsToOrbScreenPosition({
|
|
250
272
|
centerX: left + size / 2,
|
|
251
273
|
centerY: top + size / 2,
|
|
252
|
-
viewportWidth:
|
|
253
|
-
viewportHeight:
|
|
274
|
+
viewportWidth: content.width,
|
|
275
|
+
viewportHeight: content.height,
|
|
254
276
|
orbDiameter: size,
|
|
255
277
|
});
|
|
256
278
|
applyDeployment();
|
|
@@ -685,6 +707,7 @@ export function mountOrb(controller, options = {}) {
|
|
|
685
707
|
unsubscribe();
|
|
686
708
|
stopWatch();
|
|
687
709
|
window.removeEventListener('resize', reposition);
|
|
710
|
+
contentObserver?.disconnect();
|
|
688
711
|
visualViewport?.removeEventListener('resize', onViewportChange);
|
|
689
712
|
visualViewport?.removeEventListener('scroll', onViewportChange);
|
|
690
713
|
clearOverlay();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fiodos/web-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Framework-agnostic browser layer for the Fiodos agent: a vanilla AgentController (orchestrator), DOM adapters (navigation/voice/storage), HTTP client and decision engine over @fiodos/core. Shared base for @fiodos/vue, @fiodos/svelte and @fiodos/angular (no framework imports).",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"publishConfig": {
|