@floegence/floe-webapp-core 0.86.18 → 0.86.20

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.
@@ -1,4 +1,5 @@
1
1
  import { type JSX } from 'solid-js';
2
+ import { type GraphMinimapProps } from './GraphMinimap';
2
3
  import type { GraphLayout, GraphLayoutNode, GraphObjectEvent, GraphObjectRef, GraphViewport } from './types';
3
4
  export interface GraphNodeRenderContext {
4
5
  selected: () => boolean;
@@ -22,9 +23,7 @@ export interface GraphCanvasProps {
22
23
  /** Overlay content should use shared SurfaceFloatingLayer for point placement. */
23
24
  overlay?: JSX.Element;
24
25
  /** Optional interactive overview. Its geometry follows the same visible layout. */
25
- minimap?: {
26
- ariaLabel: string;
27
- };
26
+ minimap?: Pick<GraphMinimapProps, 'ariaLabel' | 'nodeStyle'>;
28
27
  class?: string;
29
28
  }
30
29
  /** Controlled graph surface. Hosts own documents and selection; Floe owns geometry and input. */
@@ -1,11 +1,11 @@
1
- import { insert as w, createComponent as x, setAttribute as l, effect as S, className as K, template as I, memo as ae, setStyleProperty as T, use as ie, delegateEvents as oe } from "solid-js/web";
1
+ import { insert as w, createComponent as x, setAttribute as l, effect as L, className as K, template as I, memo as ae, setStyleProperty as T, use as ie, delegateEvents as oe } from "solid-js/web";
2
2
  import { createUniqueId as le, createSignal as O, createMemo as y, onMount as ce, For as j, Show as D, onCleanup as de } from "solid-js";
3
3
  import { InfiniteCanvas as ue } from "../ui/InfiniteCanvas.js";
4
4
  import { resolveSurfaceInteractionTargetRole as se } from "../ui/localInteractionSurface.js";
5
5
  import { graphRelatedEdges as U, graphEdgeLabelPosition as he, graphSectionPath as ge } from "./geometry.js";
6
6
  import { GraphMinimap as fe } from "./GraphMinimap.js";
7
7
  var ve = /* @__PURE__ */ I("<div data-floe-canvas-pan-surface=true role=group tabindex=0>"), me = /* @__PURE__ */ I("<div role=region tabindex=0>"), be = /* @__PURE__ */ I('<svg class=floe-graph__edges width=1 height=1><defs><marker viewBox="0 0 8 8"refX=7 refY=4 markerWidth=7 markerHeight=7 orient=auto-start-reverse><path d="M1 1 L7 4 L1 7"fill=none stroke=context-stroke stroke-width=1.2>'), xe = /* @__PURE__ */ I("<svg><g><path class=floe-graph__edge></path><path class=floe-graph__edge-target tabindex=0 role=button data-floe-canvas-pan-surface=true></svg>", !1, !0, !1), ye = /* @__PURE__ */ I("<svg><text class=floe-graph__edge-label aria-hidden=true></svg>", !1, !0, !1);
8
- function Le(i) {
8
+ function Ee(i) {
9
9
  const H = `graph-arrow-${le()}`;
10
10
  let g;
11
11
  const [J, Q] = O(null), [V, Z] = O({
@@ -103,7 +103,7 @@ function Le(i) {
103
103
  }, r.$$focusout = () => f(null), r.$$focusin = () => f(t), r.addEventListener("pointerleave", () => f(null)), r.addEventListener("pointerenter", () => f(t)), w(r, (() => {
104
104
  var a = ae(() => !!(e.kind === "group" && i.renderGroup));
105
105
  return () => a() ? i.renderGroup(e, n) : i.renderNode(e, n);
106
- })()), S((a) => {
106
+ })()), L((a) => {
107
107
  var m = e.kind === "group" ? "floe-graph__group" : "floe-graph__node", c = e.id, d = A(t), _ = `${e.x}px`, P = `${e.y}px`, $ = `${e.width}px`, u = `${e.height}px`, v = e.label;
108
108
  return m !== a.e && K(r, a.e = m), c !== a.t && l(r, "data-graph-object", a.t = c), d !== a.a && l(r, "data-selected", a.a = d), _ !== a.o && T(r, "left", a.o = _), P !== a.i && T(r, "top", a.i = P), $ !== a.n && T(r, "width", a.n = $), u !== a.s && T(r, "height", a.s = u), v !== a.h && l(r, "aria-label", a.h = v), a;
109
109
  }, {
@@ -179,9 +179,9 @@ function Le(i) {
179
179
  },
180
180
  children: (o) => (() => {
181
181
  var b = ye();
182
- return w(b, () => u.label), S((h) => {
183
- var M = /^\d+$/.test(u.label), E = o().x, L = o().y - 6;
184
- return M !== h.e && l(b, "data-count", h.e = M), E !== h.t && l(b, "x", h.t = E), L !== h.a && l(b, "y", h.a = L), h;
182
+ return w(b, () => u.label), L((h) => {
183
+ var M = /^\d+$/.test(u.label), S = o().x, E = o().y - 6;
184
+ return M !== h.e && l(b, "data-count", h.e = M), S !== h.t && l(b, "x", h.t = S), E !== h.a && l(b, "y", h.a = E), h;
185
185
  }, {
186
186
  e: void 0,
187
187
  t: void 0,
@@ -190,9 +190,9 @@ function Le(i) {
190
190
  })()
191
191
  }), s), s.$$keydown = (o) => G(v, o), s.$$contextmenu = (o) => z(v, o), s.$$click = (o) => {
192
192
  o.stopPropagation(), i.onActivate?.(k(v, o.currentTarget, o));
193
- }, s.addEventListener("blur", () => f(null)), s.addEventListener("focus", () => f(v)), s.addEventListener("pointerleave", () => f(null)), s.addEventListener("pointerenter", () => f(v)), S((o) => {
194
- var b = u.id, h = ee().has(u.id), M = A(v), E = W(), L = W(), q = u.label;
195
- return b !== o.e && l(C, "data-graph-object", o.e = b), h !== o.t && l(C, "data-emphasized", o.t = h), M !== o.a && l(C, "data-selected", o.a = M), E !== o.o && l(R, "d", o.o = E), L !== o.i && l(s, "d", o.i = L), q !== o.n && l(s, "aria-label", o.n = q), o;
193
+ }, s.addEventListener("blur", () => f(null)), s.addEventListener("focus", () => f(v)), s.addEventListener("pointerleave", () => f(null)), s.addEventListener("pointerenter", () => f(v)), L((o) => {
194
+ var b = u.id, h = ee().has(u.id), M = A(v), S = W(), E = W(), q = u.label;
195
+ return b !== o.e && l(C, "data-graph-object", o.e = b), h !== o.t && l(C, "data-emphasized", o.t = h), M !== o.a && l(C, "data-selected", o.a = M), S !== o.o && l(R, "d", o.o = S), E !== o.i && l(s, "d", o.i = E), q !== o.n && l(s, "aria-label", o.n = q), o;
196
196
  }, {
197
197
  e: void 0,
198
198
  t: void 0,
@@ -204,7 +204,7 @@ function Le(i) {
204
204
  }
205
205
  });
206
206
  }
207
- }), null), S(() => l(d, "aria-label", i.ariaLabel)), d;
207
+ }), null), L(() => l(d, "aria-label", i.ariaLabel)), d;
208
208
  })(), x(j, {
209
209
  get each() {
210
210
  return m();
@@ -234,9 +234,12 @@ function Le(i) {
234
234
  },
235
235
  get ariaLabel() {
236
236
  return n().ariaLabel;
237
+ },
238
+ get nodeStyle() {
239
+ return n().nodeStyle;
237
240
  }
238
241
  })
239
- }), null), w(e, () => i.overlay, null), S((n) => {
242
+ }), null), w(e, () => i.overlay, null), L((n) => {
240
243
  var r = `floe-graph ${i.class ?? ""}`, a = i.ariaLabel;
241
244
  return r !== n.e && K(e, n.e = r), a !== n.t && l(e, "aria-label", n.t = a), n;
242
245
  }, {
@@ -247,5 +250,5 @@ function Le(i) {
247
250
  }
248
251
  oe(["focusin", "focusout", "click", "contextmenu", "keydown"]);
249
252
  export {
250
- Le as GraphCanvas
253
+ Ee as GraphCanvas
251
254
  };
@@ -1,4 +1,9 @@
1
- import type { GraphLayout, GraphViewport } from './types';
1
+ import type { GraphLayout, GraphLayoutNode, GraphViewport } from './types';
2
+ export interface GraphMinimapNodeStyle {
3
+ /** CSS colors, including theme variables. Omitted colors retain the defaults. */
4
+ fill?: string;
5
+ stroke?: string;
6
+ }
2
7
  export interface GraphMinimapProps {
3
8
  layout: GraphLayout;
4
9
  viewport: GraphViewport;
@@ -9,6 +14,8 @@ export interface GraphMinimapProps {
9
14
  onViewportChange: (viewport: GraphViewport) => void;
10
15
  onInteractionStart?: () => void;
11
16
  ariaLabel: string;
17
+ /** Host appearance over the exact layout. Equal styles share one SVG path. */
18
+ nodeStyle?: (node: GraphLayoutNode) => GraphMinimapNodeStyle | undefined;
12
19
  }
13
20
  /** A lightweight navigator over the exact main-canvas geometry. No second layout. */
14
21
  export declare function GraphMinimap(props: GraphMinimapProps): import("solid-js").JSX.Element;
@@ -1,74 +1,127 @@
1
- import { effect as S, setAttribute as d, template as z, use as A, delegateEvents as k } from "solid-js/web";
2
- import { createMemo as w } from "solid-js";
3
- import { graphSectionPath as D, fitGraphViewport as L } from "./geometry.js";
4
- var V = /* @__PURE__ */ z('<svg class=floe-graph__minimap role=region tabindex=0 preserveAspectRatio="xMidYMid meet"data-floe-canvas-interactive=true><path class=floe-graph__minimap-groups></path><path class=floe-graph__minimap-edges></path><path class=floe-graph__minimap-nodes></path><rect class=floe-graph__minimap-viewport>');
5
- function R(e) {
6
- let h, n;
7
- const c = w(() => {
1
+ import { insert as k, createComponent as _, effect as g, setAttribute as h, style as C, template as f, use as S, delegateEvents as z } from "solid-js/web";
2
+ import { createMemo as w, For as I } from "solid-js";
3
+ import { graphSectionPath as A, fitGraphViewport as D } from "./geometry.js";
4
+ var L = /* @__PURE__ */ f('<svg class=floe-graph__minimap role=region tabindex=0 preserveAspectRatio="xMidYMid meet"data-floe-canvas-interactive=true><path class=floe-graph__minimap-edges></path><rect class=floe-graph__minimap-viewport>'), V = /* @__PURE__ */ f("<svg><path class=floe-graph__minimap-groups></svg>", !1, !0, !1), E = /* @__PURE__ */ f("<svg><path class=floe-graph__minimap-nodes></svg>", !1, !0, !1);
5
+ function R(i) {
6
+ let v, s;
7
+ const u = w(() => {
8
8
  const {
9
- x: i,
10
- y: o,
11
- width: s,
12
- height: v
13
- } = e.layout.bounds, a = Math.max(s, v, 1) * 0.04;
9
+ x: e,
10
+ y: l,
11
+ width: d,
12
+ height: n
13
+ } = i.layout.bounds, t = Math.max(d, n, 1) * 0.04;
14
14
  return {
15
- x: i - a,
16
- y: o - a,
17
- width: s + a * 2,
18
- height: v + a * 2
15
+ x: e - t,
16
+ y: l - t,
17
+ width: d + t * 2,
18
+ height: n + t * 2
19
19
  };
20
- }), g = (i) => e.layout.nodes.filter((o) => (o.kind === "group" ? "group" : "node") === i).map((o) => `M${o.x},${o.y}h${o.width}v${o.height}h${-o.width}Z`).join(""), C = w(() => g("node")), I = w(() => g("group")), P = w(() => e.layout.edges.flatMap((i) => i.sections.map(D)).join(" ")), u = (i) => {
21
- const o = h?.getScreenCTM();
22
- return o ? new DOMPoint(i.clientX, i.clientY).matrixTransform(o.inverse()) : void 0;
23
- }, f = (i) => {
24
- n?.id === i.pointerId && (n = void 0, h?.hasPointerCapture(i.pointerId) && h.releasePointerCapture(i.pointerId));
20
+ }), m = w(() => {
21
+ const e = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map();
22
+ for (const n of i.layout.nodes) {
23
+ const t = i.nodeStyle?.(n) ?? {}, o = n.kind === "group" ? e : l, r = JSON.stringify([t.fill ?? null, t.stroke ?? null]);
24
+ let a = o.get(r);
25
+ a || (a = {
26
+ ...t,
27
+ paths: []
28
+ }, o.set(r, a)), a.paths.push(`M${n.x},${n.y}h${n.width}v${n.height}h${-n.width}Z`);
29
+ }
30
+ const d = (n) => [...n.values()].map(({
31
+ paths: t,
32
+ ...o
33
+ }) => ({
34
+ ...o,
35
+ path: t.join("")
36
+ }));
37
+ return {
38
+ groups: d(e),
39
+ nodes: d(l)
40
+ };
41
+ }), p = (e) => ({
42
+ "--graph-minimap-fill": e.fill,
43
+ "--graph-minimap-stroke": e.stroke,
44
+ "--graph-minimap-opacity": e.fill || e.stroke ? "1" : void 0
45
+ }), P = w(() => i.layout.edges.flatMap((e) => e.sections.map(A)).join(" ")), y = (e) => {
46
+ const l = v?.getScreenCTM();
47
+ return l ? new DOMPoint(e.clientX, e.clientY).matrixTransform(l.inverse()) : void 0;
48
+ }, x = (e) => {
49
+ s?.id === e.pointerId && (s = void 0, v?.hasPointerCapture(e.pointerId) && v.releasePointerCapture(e.pointerId));
25
50
  };
26
51
  return (() => {
27
- var i = V(), o = i.firstChild, s = o.nextSibling, v = s.nextSibling, a = v.nextSibling;
28
- i.$$keydown = (t) => {
29
- const l = {
52
+ var e = L(), l = e.firstChild, d = l.nextSibling;
53
+ e.$$keydown = (t) => {
54
+ const r = {
30
55
  ArrowLeft: [1, 0],
31
56
  ArrowRight: [-1, 0],
32
57
  ArrowUp: [0, 1],
33
58
  ArrowDown: [0, -1]
34
59
  }[t.key];
35
- !l && t.key !== "Home" || (t.preventDefault(), t.stopPropagation(), e.onInteractionStart?.(), e.onViewportChange(l ? {
36
- ...e.viewport,
37
- x: e.viewport.x + l[0] * e.size.width * 0.2,
38
- y: e.viewport.y + l[1] * e.size.height * 0.2
39
- } : L(e.layout.bounds, e.size, 24)));
40
- }, i.addEventListener("lostpointercapture", () => {
41
- n = void 0;
42
- }), i.addEventListener("pointercancel", f), i.$$pointerup = f, i.$$pointermove = (t) => {
43
- if (n?.id !== t.pointerId) return;
44
- const r = u(t);
45
- r && e.onViewportChange({
46
- ...n.viewport,
47
- x: n.viewport.x - (r.x - n.x) * n.viewport.scale,
48
- y: n.viewport.y - (r.y - n.y) * n.viewport.scale
60
+ !r && t.key !== "Home" || (t.preventDefault(), t.stopPropagation(), i.onInteractionStart?.(), i.onViewportChange(r ? {
61
+ ...i.viewport,
62
+ x: i.viewport.x + r[0] * i.size.width * 0.2,
63
+ y: i.viewport.y + r[1] * i.size.height * 0.2
64
+ } : D(i.layout.bounds, i.size, 24)));
65
+ }, e.addEventListener("lostpointercapture", () => {
66
+ s = void 0;
67
+ }), e.addEventListener("pointercancel", x), e.$$pointerup = x, e.$$pointermove = (t) => {
68
+ if (s?.id !== t.pointerId) return;
69
+ const o = y(t);
70
+ o && i.onViewportChange({
71
+ ...s.viewport,
72
+ x: s.viewport.x - (o.x - s.x) * s.viewport.scale,
73
+ y: s.viewport.y - (o.y - s.y) * s.viewport.scale
49
74
  });
50
- }, i.$$pointerdown = (t) => {
75
+ }, e.$$pointerdown = (t) => {
51
76
  if (t.button !== 0) return;
52
- const r = u(t);
53
- r && (t.preventDefault(), t.stopPropagation(), e.onInteractionStart?.(), h.focus({
77
+ const o = y(t);
78
+ o && (t.preventDefault(), t.stopPropagation(), i.onInteractionStart?.(), v.focus({
54
79
  preventScroll: !0
55
- }), t.target.matches(".floe-graph__minimap-viewport") || e.onViewportChange({
56
- ...e.viewport,
57
- x: e.size.width / 2 - r.x * e.viewport.scale,
58
- y: e.size.height / 2 - r.y * e.viewport.scale
59
- }), n = {
80
+ }), t.target.matches(".floe-graph__minimap-viewport") || i.onViewportChange({
81
+ ...i.viewport,
82
+ x: i.size.width / 2 - o.x * i.viewport.scale,
83
+ y: i.size.height / 2 - o.y * i.viewport.scale
84
+ }), s = {
60
85
  id: t.pointerId,
61
- x: r.x,
62
- y: r.y,
86
+ x: o.x,
87
+ y: o.y,
63
88
  viewport: {
64
- ...e.viewport
89
+ ...i.viewport
65
90
  }
66
- }, h.setPointerCapture(t.pointerId));
91
+ }, v.setPointerCapture(t.pointerId));
67
92
  };
68
- var m = h;
69
- return typeof m == "function" ? A(m, i) : h = i, S((t) => {
70
- var r = e.ariaLabel, l = `${c().x} ${c().y} ${c().width} ${c().height}`, x = I(), y = P(), p = C(), $ = -e.viewport.x / e.viewport.scale, b = -e.viewport.y / e.viewport.scale, _ = e.size.width / e.viewport.scale, M = e.size.height / e.viewport.scale;
71
- return r !== t.e && d(i, "aria-label", t.e = r), l !== t.t && d(i, "viewBox", t.t = l), x !== t.a && d(o, "d", t.a = x), y !== t.o && d(s, "d", t.o = y), p !== t.i && d(v, "d", t.i = p), $ !== t.n && d(a, "x", t.n = $), b !== t.s && d(a, "y", t.s = b), _ !== t.h && d(a, "width", t.h = _), M !== t.r && d(a, "height", t.r = M), t;
93
+ var n = v;
94
+ return typeof n == "function" ? S(n, e) : v = e, k(e, _(I, {
95
+ get each() {
96
+ return m().groups;
97
+ },
98
+ children: (t) => (() => {
99
+ var o = V();
100
+ return g((r) => {
101
+ var a = t.path, c = p(t);
102
+ return a !== r.e && h(o, "d", r.e = a), r.t = C(o, c, r.t), r;
103
+ }, {
104
+ e: void 0,
105
+ t: void 0
106
+ }), o;
107
+ })()
108
+ }), l), k(e, _(I, {
109
+ get each() {
110
+ return m().nodes;
111
+ },
112
+ children: (t) => (() => {
113
+ var o = E();
114
+ return g((r) => {
115
+ var a = t.path, c = p(t);
116
+ return a !== r.e && h(o, "d", r.e = a), r.t = C(o, c, r.t), r;
117
+ }, {
118
+ e: void 0,
119
+ t: void 0
120
+ }), o;
121
+ })()
122
+ }), d), g((t) => {
123
+ var o = i.ariaLabel, r = `${u().x} ${u().y} ${u().width} ${u().height}`, a = P(), c = -i.viewport.x / i.viewport.scale, $ = -i.viewport.y / i.viewport.scale, b = i.size.width / i.viewport.scale, M = i.size.height / i.viewport.scale;
124
+ return o !== t.e && h(e, "aria-label", t.e = o), r !== t.t && h(e, "viewBox", t.t = r), a !== t.a && h(l, "d", t.a = a), c !== t.o && h(d, "x", t.o = c), $ !== t.i && h(d, "y", t.i = $), b !== t.n && h(d, "width", t.n = b), M !== t.s && h(d, "height", t.s = M), t;
72
125
  }, {
73
126
  e: void 0,
74
127
  t: void 0,
@@ -76,13 +129,11 @@ function R(e) {
76
129
  o: void 0,
77
130
  i: void 0,
78
131
  n: void 0,
79
- s: void 0,
80
- h: void 0,
81
- r: void 0
82
- }), i;
132
+ s: void 0
133
+ }), e;
83
134
  })();
84
135
  }
85
- k(["pointerdown", "pointermove", "pointerup", "keydown"]);
136
+ z(["pointerdown", "pointermove", "pointerup", "keydown"]);
86
137
  export {
87
138
  R as GraphMinimap
88
139
  };
package/dist/graph.css CHANGED
@@ -90,13 +90,16 @@
90
90
  outline-offset: 2px;
91
91
  }
92
92
  .floe-graph__minimap-nodes {
93
- fill: var(--muted-foreground);
94
- opacity: 0.65;
93
+ fill: var(--graph-minimap-fill, var(--muted-foreground));
94
+ stroke: var(--graph-minimap-stroke, none);
95
+ stroke-width: 0.7px;
96
+ vector-effect: non-scaling-stroke;
97
+ opacity: var(--graph-minimap-opacity, 0.65);
95
98
  pointer-events: none;
96
99
  }
97
100
  .floe-graph__minimap-groups {
98
- fill: color-mix(in srgb, var(--primary) 10%, transparent);
99
- stroke: var(--muted-foreground);
101
+ fill: var(--graph-minimap-fill, color-mix(in srgb, var(--primary) 10%, transparent));
102
+ stroke: var(--graph-minimap-stroke, var(--muted-foreground));
100
103
  stroke-width: 0.7px;
101
104
  vector-effect: non-scaling-stroke;
102
105
  pointer-events: none;
@@ -147,6 +150,11 @@
147
150
  }
148
151
  .floe-graph__minimap-nodes {
149
152
  fill: CanvasText;
153
+ stroke: CanvasText;
154
+ opacity: 1;
155
+ }
156
+ .floe-graph__minimap-groups {
157
+ fill: Canvas;
150
158
  }
151
159
  .floe-graph__minimap-groups,
152
160
  .floe-graph__minimap-edges {
@@ -23,8 +23,8 @@ export interface RemoteInputOptions<T> {
23
23
  export interface RemoteInputController<T> {
24
24
  readonly element: HTMLTextAreaElement;
25
25
  bindTarget(target: T | null): void;
26
- /** Physical preserves the host layout; text uses every local confirmed edit. */
27
- setTextInputMode(mode: 'physical' | 'text'): void;
26
+ /** Physical-only bypasses the local editor and input method entirely. */
27
+ setTextInputMode(mode: 'physical' | 'text' | 'physical-only'): void;
28
28
  setAnchor(clientX: number, clientY: number): void;
29
29
  focus(): void;
30
30
  setKeyboardVisible(visible: boolean): void;
@@ -1,17 +1,17 @@
1
- function j(n) {
2
- const { surface: A } = n, x = A.ownerDocument, c = x.defaultView;
3
- if (!c) throw new Error("Remote input requires an attached document");
4
- const i = x.createElement("textarea");
5
- i.className = "floe-remote-input", i.setAttribute("aria-label", n.label), i.setAttribute("autocorrect", "off"), i.autocomplete = "off", i.autocapitalize = "off", i.spellcheck = !1, i.wrap = "off", i.disabled = !0, i.tabIndex = -1, x.body.append(i);
6
- let l = null, K = 0, f = !1, R = !1, o = null, h = !1, a = null, w = "physical";
7
- const k = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Set(), C = /* @__PURE__ */ new Set(), L = /* @__PURE__ */ new Set();
1
+ function O(a) {
2
+ const { surface: c } = a, k = c.ownerDocument, u = k.defaultView;
3
+ if (!u) throw new Error("Remote input requires an attached document");
4
+ const l = k.createElement("textarea");
5
+ l.className = "floe-remote-input", l.setAttribute("aria-label", a.label), l.setAttribute("autocorrect", "off"), l.autocomplete = "off", l.autocapitalize = "off", l.spellcheck = !1, l.wrap = "off", l.disabled = !0, l.tabIndex = -1, k.body.append(l);
6
+ let i = null, M = 0, d = !1, V = !1, o = null, K = !1, f = null, r = "physical", D = !1;
7
+ const x = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Set(), T = /* @__PURE__ */ new Set(), S = /* @__PURE__ */ new Set();
8
8
  let $ = null;
9
- const V = [];
10
- function s(e, t, r) {
11
- const d = r;
12
- e.addEventListener(t, d), V.push(() => e.removeEventListener(t, d));
9
+ const I = [];
10
+ function s(e, t, n) {
11
+ const m = n;
12
+ e.addEventListener(t, m), I.push(() => e.removeEventListener(t, m));
13
13
  }
14
- const b = (e) => e.code || e.key, M = (e, t) => ({
14
+ const w = (e) => e.code || e.key, C = (e, t) => ({
15
15
  key: e.key,
16
16
  code: e.code,
17
17
  pressed: t,
@@ -22,147 +22,165 @@ function j(n) {
22
22
  altKey: e.altKey,
23
23
  metaKey: e.metaKey
24
24
  });
25
- function T(e) {
26
- R !== e && (R = e, n.onKeyboardVisibilityChange?.(e));
25
+ function L(e) {
26
+ V !== e && (V = e, a.onKeyboardVisibilityChange?.(e));
27
27
  }
28
- function p() {
29
- const e = A.getBoundingClientRect(), t = c.visualViewport, r = Math.max(e.left, t?.offsetLeft ?? 0), d = Math.max(e.top, t?.offsetTop ?? 0), y = Math.min(e.right, (t?.offsetLeft ?? 0) + (t?.width ?? c.innerWidth)), I = Math.min(e.bottom, (t?.offsetTop ?? 0) + (t?.height ?? c.innerHeight)), P = Math.max(1, Math.min(320, y - r - 8));
30
- i.style.maxWidth = `${P}px`;
31
- const B = i.getBoundingClientRect(), N = $?.x ?? r + 12, W = $?.y ?? d + 12;
32
- i.style.left = `${Math.max(r, Math.min(N, y - B.width - 4))}px`, i.style.top = `${Math.max(d, Math.min(W, I - B.height - 4))}px`;
28
+ function h() {
29
+ const e = c.getBoundingClientRect(), t = u.visualViewport, n = Math.max(e.left, t?.offsetLeft ?? 0), m = Math.max(e.top, t?.offsetTop ?? 0), g = Math.min(e.right, (t?.offsetLeft ?? 0) + (t?.width ?? u.innerWidth)), j = Math.min(e.bottom, (t?.offsetTop ?? 0) + (t?.height ?? u.innerHeight)), q = Math.max(1, Math.min(320, g - n - 8));
30
+ l.style.maxWidth = `${q}px`;
31
+ const B = l.getBoundingClientRect(), G = $?.x ?? n + 12, H = $?.y ?? m + 12;
32
+ l.style.left = `${Math.max(n, Math.min(G, g - B.width - 4))}px`, l.style.top = `${Math.max(m, Math.min(H, j - B.height - 4))}px`;
33
33
  }
34
- function m() {
35
- i.value = "", delete i.dataset.composing, a = null;
34
+ function p() {
35
+ l.value = "", delete l.dataset.composing, f = null;
36
36
  }
37
- function E() {
38
- const e = l, t = u.size > 0;
39
- u.clear(), k.clear(), C.clear(), e !== null && t && n.release(e);
37
+ function z() {
38
+ const e = i, t = y.size > 0;
39
+ y.clear(), x.clear(), T.clear(), e !== null && t && a.release(e);
40
40
  }
41
- function g() {
42
- K++, o && (o.cancelled = !0), h = !0, m(), E(), o && x.activeElement === i && i.blur();
41
+ function b() {
42
+ M++, o && (o.cancelled = !0), K = !0, p(), z(), o && k.activeElement === l && l.blur();
43
43
  }
44
- function S(e) {
45
- !e || l === null || f || (w === "text" && u.size && (u.clear(), C.clear(), n.release(l)), n.commitText(e, l));
44
+ function A(e) {
45
+ !e || i === null || d || r === "physical-only" || (r === "text" && y.size && (y.clear(), T.clear(), a.release(i)), a.commitText(e, i));
46
46
  }
47
- function z(e) {
48
- if (l !== null) {
47
+ function E(e) {
48
+ if (i !== null) {
49
49
  if (!/^(Shift|Control|Alt|Meta)(Left|Right)$/.test(e.code))
50
- for (const [t, r] of [
50
+ for (const [t, n] of [
51
51
  ["Shift", e.shiftKey],
52
52
  ["Control", e.ctrlKey],
53
53
  ["Alt", e.altKey],
54
54
  ["Meta", e.metaKey]
55
55
  ]) {
56
- if (!r || [...u].some((y) => y === `${t}Left` || y === `${t}Right`)) continue;
57
- const d = [...k.values()].find((y) => y.code === `${t}Left` || y.code === `${t}Right`) ?? { ...e, key: t, code: `${t}Left`, pressed: !0, repeat: !1, location: 1 };
58
- u.add(d.code), k.has(d.code) || C.add(d.code), n.sendKey(d, l);
56
+ if (!n || [...y].some((g) => g === `${t}Left` || g === `${t}Right`)) continue;
57
+ const m = [...x.values()].find((g) => g.code === `${t}Left` || g.code === `${t}Right`) ?? { ...e, key: t, code: `${t}Left`, pressed: !0, repeat: !1, location: 1 };
58
+ y.add(m.code), x.has(m.code) || T.add(m.code), a.sendKey(m, i);
59
59
  }
60
- u.add(e.code || e.key), n.sendKey(e, l);
60
+ y.add(e.code || e.key), a.sendKey(e, i);
61
61
  }
62
62
  }
63
- function D(e) {
64
- if (l === null) return;
65
- const t = { key: e, code: e, pressed: !0, repeat: !1, shiftKey: !1, ctrlKey: !1, altKey: !1, metaKey: !1, location: 0 }, r = l;
66
- n.sendKey(t, r), l === r && n.sendKey({ ...t, pressed: !1 }, r);
67
- }
68
63
  function F(e) {
69
- if (l === null || f) {
70
- m();
64
+ if (i === null) return;
65
+ const t = { key: e, code: e, pressed: !0, repeat: !1, shiftKey: !1, ctrlKey: !1, altKey: !1, metaKey: !1, location: 0 }, n = i;
66
+ a.sendKey(t, n), i === n && a.sendKey({ ...t, pressed: !1 }, n);
67
+ }
68
+ function P(e) {
69
+ if (i === null || d || r === "physical-only") {
70
+ p();
71
71
  return;
72
72
  }
73
- if (o?.cancelled || o && o.epoch !== K) {
74
- m();
73
+ if (o?.cancelled || o && o.epoch !== M) {
74
+ p();
75
75
  return;
76
76
  }
77
77
  if (e.isComposing) {
78
- o ??= { epoch: K, committed: !1, cancelled: !1 }, i.dataset.composing = "true", p();
78
+ o ??= { epoch: M, committed: !1, cancelled: !1 }, l.dataset.composing = "true", h();
79
79
  return;
80
80
  }
81
81
  if (o) {
82
- !o.committed && i.value && (o.committed = !0, S(i.value)), m();
82
+ !o.committed && l.value && (o.committed = !0, A(l.value)), p();
83
83
  return;
84
84
  }
85
- if (h || e.inputType === "insertFromComposition") {
86
- h = !1, m();
85
+ if (K || e.inputType === "insertFromComposition") {
86
+ K = !1, p();
87
87
  return;
88
88
  }
89
- const t = i.value;
90
- w === "physical" && a && t === a.key && !a.altKey && t.length === 1 ? z(a) : S(t), m();
89
+ const t = l.value;
90
+ r === "physical" && f && t === f.key && !f.altKey && t.length === 1 ? E(f) : A(t), p();
91
91
  }
92
- return s(i, "keydown", (e) => {
93
- if (!(l === null || f)) {
94
- if (e.stopPropagation(), o?.cancelled && !e.isComposing && e.key !== "Process" && e.keyCode !== 229 && (o = null), e.isComposing || o || e.key === "Process" || e.keyCode === 229) {
95
- L.add(b(e)), a = null;
92
+ function N(e) {
93
+ if (!(i === null || d) && e.currentTarget === c == (r === "physical-only")) {
94
+ if (e.stopPropagation(), r === "physical-only") {
95
+ e.preventDefault(), S.delete(w(e)), e.code && !a.clipboard?.(e, i) && E(C(e, !0));
96
+ return;
97
+ }
98
+ if (o?.cancelled && !e.isComposing && e.key !== "Process" && e.keyCode !== 229 && (o = null), e.isComposing || o || e.key === "Process" || e.keyCode === 229) {
99
+ S.add(w(e)), f = null;
96
100
  return;
97
101
  }
98
- if (L.delete(b(e)), h = !1, n.clipboard?.(e, l)) {
99
- a = null;
102
+ if (S.delete(w(e)), K = !1, a.clipboard?.(e, i)) {
103
+ f = null;
100
104
  return;
101
105
  }
102
- if (w === "text" && /^(Shift|Control|Alt|Meta)(Left|Right)$/.test(e.code)) {
103
- k.set(b(e), M(e, !0));
106
+ if (r === "text" && /^(Shift|Control|Alt|Meta)(Left|Right)$/.test(e.code)) {
107
+ x.set(w(e), C(e, !0));
104
108
  return;
105
109
  }
106
110
  if (e.key === "Dead" || e.key === "Unidentified") {
107
- a = null;
111
+ f = null;
108
112
  return;
109
113
  }
110
114
  if (Array.from(e.key).length === 1 && !e.metaKey && (!e.ctrlKey || e.getModifierState("AltGraph"))) {
111
- a = M(e, !0);
115
+ f = C(e, !0);
112
116
  return;
113
117
  }
114
- e.preventDefault(), z(M(e, !0));
118
+ e.preventDefault(), E(C(e, !0));
115
119
  }
116
- }), s(i, "keyup", (e) => {
117
- if (e.stopPropagation(), a = null, k.delete(b(e)), !L.delete(b(e)) && (l !== null && u.delete(b(e)) && n.sendKey(M(e, !1), l), l !== null && ![...u].some((t) => !/^(Shift|Control|Alt|Meta)(Left|Right)$/.test(t)))) {
118
- for (const t of C)
119
- u.delete(t), n.sendKey({ ...M(e, !1), code: t, key: t.replace(/Left$/, ""), location: 1 }, l);
120
- C.clear();
120
+ }
121
+ function W(e) {
122
+ if (e.currentTarget === c == (r === "physical-only") && (e.stopPropagation(), f = null, x.delete(w(e)), !S.delete(w(e)) && (i !== null && y.delete(w(e)) && a.sendKey(C(e, !1), i), i !== null && ![...y].some((t) => !/^(Shift|Control|Alt|Meta)(Left|Right)$/.test(t))))) {
123
+ for (const t of T)
124
+ y.delete(t), a.sendKey({ ...C(e, !1), code: t, key: t.replace(/Left$/, ""), location: 1 }, i);
125
+ T.clear();
121
126
  }
122
- }), s(i, "beforeinput", (e) => {
123
- if (l === null || f) {
124
- e.preventDefault();
127
+ }
128
+ for (const e of [l, c])
129
+ s(e, "keydown", N), s(e, "keyup", W);
130
+ s(l, "beforeinput", (e) => {
131
+ if (i === null || d || r === "physical-only") {
132
+ e.preventDefault(), p();
125
133
  return;
126
134
  }
127
135
  if (e.isComposing || o || e.inputType === "insertCompositionText" || e.inputType === "deleteCompositionText" || e.inputType === "insertFromComposition") return;
128
- h = !1;
129
- const r = { deleteContentBackward: "Backspace", deleteContentForward: "Delete", insertLineBreak: "Enter", insertParagraph: "Enter" }[e.inputType];
130
- r && (e.preventDefault(), m(), D(r));
131
- }), s(i, "input", F), s(i, "compositionstart", () => {
132
- o = { epoch: K, committed: !1, cancelled: l === null }, h = !1, a = null, i.dataset.composing = "true", p();
133
- }), s(i, "compositionend", (e) => {
136
+ K = !1;
137
+ const n = { deleteContentBackward: "Backspace", deleteContentForward: "Delete", insertLineBreak: "Enter", insertParagraph: "Enter" }[e.inputType];
138
+ n && (e.preventDefault(), p(), F(n));
139
+ }), s(l, "input", P), s(l, "compositionstart", () => {
140
+ if (r === "physical-only") {
141
+ p();
142
+ return;
143
+ }
144
+ o = { epoch: M, committed: !1, cancelled: i === null }, K = !1, f = null, l.dataset.composing = "true", h();
145
+ }), s(l, "compositionend", (e) => {
134
146
  const t = o;
135
- o = null, h = !0, m(), t && !t.cancelled && !t.committed && t.epoch === K && S(e.data);
136
- }), s(i, "blur", () => {
137
- g(), T(!1);
138
- }), s(c, "blur", g), s(c, "pagehide", g), s(c, "resize", p), c.visualViewport && (s(c.visualViewport, "resize", p), s(c.visualViewport, "scroll", p)), p(), {
139
- element: i,
147
+ o = null, K = !0, p(), t && !t.cancelled && !t.committed && t.epoch === M && A(e.data);
148
+ }), s(l, "blur", () => {
149
+ b(), L(!1);
150
+ }), s(c, "blur", () => {
151
+ r === "physical-only" && b();
152
+ }), s(u, "blur", b), s(u, "pagehide", b), s(u, "resize", h), u.visualViewport && (s(u.visualViewport, "resize", h), s(u.visualViewport, "scroll", h));
153
+ function R() {
154
+ i === null || d || (r === "physical-only" ? (c.hasAttribute("tabindex") || (c.tabIndex = -1, D = !0), c.focus({ preventScroll: !0 })) : (l.focus({ preventScroll: !0 }), h()));
155
+ }
156
+ return h(), {
157
+ element: l,
140
158
  bindTarget(e) {
141
- f || Object.is(l, e) || (g(), l = e, i.disabled = e === null);
159
+ d || Object.is(i, e) || (b(), i = e, l.disabled = e === null || r === "physical-only");
142
160
  },
143
161
  setTextInputMode(e) {
144
- f || e === w || (g(), w = e);
162
+ if (d || e === r) return;
163
+ const t = k.activeElement === l || k.activeElement === c;
164
+ b(), r = e, l.disabled = i === null || e === "physical-only", e === "physical-only" && L(!1), t && R();
145
165
  },
146
166
  setAnchor(e, t) {
147
- !Number.isFinite(e) || !Number.isFinite(t) || ($ = { x: e, y: t }, p());
148
- },
149
- focus() {
150
- l === null || f || (i.focus({ preventScroll: !0 }), p());
167
+ !Number.isFinite(e) || !Number.isFinite(t) || ($ = { x: e, y: t }, h());
151
168
  },
169
+ focus: R,
152
170
  setKeyboardVisible(e) {
153
- e && l !== null && !f ? (i.focus({ preventScroll: !0 }), T(!0), p()) : (i.blur(), T(!1));
171
+ e && i !== null && !d ? (R(), L(r !== "physical-only")) : ((r === "physical-only" ? c : l).blur(), L(!1));
154
172
  },
155
- release: E,
156
- reset: g,
173
+ release: z,
174
+ reset: b,
157
175
  dispose() {
158
- if (!f) {
159
- g(), f = !0, l = null;
160
- for (const e of V) e();
161
- i.remove(), T(!1);
176
+ if (!d) {
177
+ b(), d = !0, i = null;
178
+ for (const e of I) e();
179
+ D && c.removeAttribute("tabindex"), l.remove(), L(!1);
162
180
  }
163
181
  }
164
182
  };
165
183
  }
166
184
  export {
167
- j as createRemoteInput
185
+ O as createRemoteInput
168
186
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floegence/floe-webapp-core",
3
- "version": "0.86.18",
3
+ "version": "0.86.20",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",