@nika-js/onlymap 0.4.4 → 0.4.6

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/react.js CHANGED
@@ -1,193 +1,194 @@
1
- var Oe = Object.defineProperty;
2
- var we = (e, t, s) => t in e ? Oe(e, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : e[t] = s;
3
- var re = (e, t, s) => we(e, typeof t != "symbol" ? t + "" : t, s);
4
- import { jsxs as G, jsx as E } from "react/jsx-runtime";
5
- import { createContext as Ee, useContext as xe, forwardRef as Re, useRef as h, useState as $, useId as ae, useCallback as ne, useMemo as T, useLayoutEffect as oe, useEffect as R, useImperativeHandle as Fe, useSyncExternalStore as le } from "react";
6
- import { MANAGED_SLOTS as Ce, slotContainerStyle as Te, FOLD_SIDES as I, MapController as Pe, parseWidgetStyle as Me, foldToggleSlot as ke, foldToggleStyle as $e, foldPanelStyle as je, foldDrawerStyle as Le, resolveSlot as De, foldSideForSlot as Ie, isStoreToken as _e } from "@nika-js/onlymap";
7
- import { createPortal as ce } from "react-dom";
8
- const ue = Ee(null);
9
- function N(e) {
10
- const t = xe(ue);
1
+ var Ee = Object.defineProperty;
2
+ var Re = (e, t, s) => t in e ? Ee(e, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : e[t] = s;
3
+ var ne = (e, t, s) => Re(e, typeof t != "symbol" ? t + "" : t, s);
4
+ import { jsxs as J, jsx as E } from "react/jsx-runtime";
5
+ import { createContext as xe, useContext as Fe, forwardRef as Ce, useRef as h, useState as L, useId as le, useCallback as oe, useMemo as P, useLayoutEffect as se, useEffect as x, useImperativeHandle as Pe, useSyncExternalStore as ce } from "react";
6
+ import { MANAGED_SLOTS as Te, slotContainerStyle as ke, FOLD_SIDES as A, MapController as Me, parseWidgetStyle as Le, foldToggleSlot as $e, foldToggleStyle as je, foldPanelStyle as De, foldDrawerStyle as _e, resolveFoldBreakpointPx as Ae, shouldFoldAtWidth as Ie, DEFAULT_FOLD_BREAKPOINT_PX as ze, resolveSlot as Ke, foldSideForSlot as He, isStoreToken as Ne } from "@nika-js/onlymap";
7
+ import { createPortal as de } from "react-dom";
8
+ const ue = xe(null);
9
+ function W(e) {
10
+ const t = Fe(ue);
11
11
  if (!t) throw new Error(`[onlymapjs] ${e} must be rendered inside <OmMap>.`);
12
12
  return t;
13
13
  }
14
- function J(e, t) {
14
+ function U(e, t) {
15
15
  if (e === t) return !0;
16
16
  const s = Object.keys(e ?? {}), o = Object.keys(t ?? {});
17
17
  return s.length !== o.length ? !1 : s.every((i) => e[i] === t[i]);
18
18
  }
19
- function ze(e, t) {
19
+ function We(e, t) {
20
20
  const { props: s, updateTriggers: o, ...i } = e, { props: b, updateTriggers: m, ...a } = t;
21
- return J(i, a) && J(s, b) && J(o, m);
21
+ return U(i, a) && U(s, b) && U(o, m);
22
22
  }
23
- class Ae {
23
+ class qe {
24
24
  constructor(t) {
25
- re(this, "descriptors", /* @__PURE__ */ new Map());
25
+ ne(this, "descriptors", /* @__PURE__ */ new Map());
26
26
  this.controller = t;
27
27
  }
28
28
  upsert(t) {
29
29
  const s = this.descriptors.get(t.id);
30
- s && ze(s, t) || (this.descriptors.set(t.id, t), this.controller.setLayers([...this.descriptors.values()]));
30
+ s && We(s, t) || (this.descriptors.set(t.id, t), this.controller.setLayers([...this.descriptors.values()]));
31
31
  }
32
32
  remove(t) {
33
33
  this.descriptors.delete(t) && this.controller.setLayers([...this.descriptors.values()]);
34
34
  }
35
35
  }
36
- const H = Ce, Ke = Object.fromEntries(H.map((e) => [e, Te(e)])), se = { display: "flex", pointerEvents: "none", order: 2147483647 }, He = Object.fromEntries(I.map((e) => [e, null]));
37
- function Ne(e) {
36
+ const N = Te, Ve = Object.fromEntries(N.map((e) => [e, ke(e)])), ie = { display: "flex", pointerEvents: "none", order: 2147483647 }, Be = Object.fromEntries(A.map((e) => [e, null]));
37
+ function Ye(e) {
38
38
  const t = e.querySelector(
39
39
  'button:not([disabled]),a[href],input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])'
40
40
  );
41
41
  t ? t.focus() : (e.tabIndex = -1, e.focus());
42
42
  }
43
- function We(e, t) {
43
+ function Ge(e, t) {
44
44
  return Object.entries(t).some(([s, o]) => o !== void 0 && e[s] !== o);
45
45
  }
46
- const Ue = Re(function(t, s) {
47
- const { center: o, zoom: i, pitch: b, bearing: m, basemap: a, basemapKey: l, attribution: g, headless: u, widgetStyle: w, widgetsHidden: v, widgetsFold: p = !0, className: y, style: O, children: j } = t, x = h(null), C = h(null), [c, P] = $(null), [F, D] = $(null), [L, _] = $(
48
- () => Object.fromEntries(H.map((r) => [r, null]))
49
- ), [M, de] = $(!1), [Q, fe] = $(He), [me, ge] = $(
50
- () => Object.fromEntries(I.map((r) => [r, 0]))
51
- ), [be, W] = $(null), U = `om-react-fold-${ae().replaceAll(":", "")}`, ye = h(new Map(I.map((r) => [r, /* @__PURE__ */ new Set()]))), X = u ? JSON.stringify(u) : "", z = h({
46
+ const rt = Ce(function(t, s) {
47
+ const { center: o, zoom: i, pitch: b, bearing: m, basemap: a, basemapKey: l, attribution: g, headless: d, widgetStyle: w, widgetsHidden: v, widgetsFold: p = !0, className: y, style: S, children: $ } = t, R = h(null), C = h(null), [c, T] = L(null), [F, D] = L(null), [j, I] = L(
48
+ () => Object.fromEntries(N.map((r) => [r, null]))
49
+ ), [k, fe] = L(!1), [X, me] = L(Be), [ge, be] = L(
50
+ () => Object.fromEntries(A.map((r) => [r, 0]))
51
+ ), [ye, q] = L(null), Q = `om-react-fold-${le().replaceAll(":", "")}`, pe = h(new Map(A.map((r) => [r, /* @__PURE__ */ new Set()]))), Z = d ? JSON.stringify(d) : "", z = h({
52
52
  badge: null,
53
53
  attribution: null
54
- }), pe = ne((r) => {
54
+ }), he = oe((r) => {
55
55
  D((n) => n === r ? n : r);
56
- }, []), he = T(
56
+ }, []), ve = P(
57
57
  () => Object.fromEntries(
58
- H.map((r) => [
58
+ N.map((r) => [
59
59
  r,
60
60
  (n) => {
61
- _((d) => d[r] === n ? d : { ...d, [r]: n });
61
+ I((u) => u[r] === n ? u : { ...u, [r]: n });
62
62
  }
63
63
  ])
64
64
  ),
65
65
  []
66
- ), ve = T(
66
+ ), Se = P(
67
67
  () => Object.fromEntries(
68
- I.map((r) => [
68
+ A.map((r) => [
69
69
  r,
70
70
  (n) => {
71
- fe((d) => d[r] === n ? d : { ...d, [r]: n });
71
+ me((u) => u[r] === n ? u : { ...u, [r]: n });
72
72
  }
73
73
  ])
74
74
  ),
75
75
  []
76
- ), Z = ne((r, n, d) => {
77
- const f = ye.current.get(r), S = f.size;
78
- d ? f.add(n) : f.delete(n), f.size !== S && ge((Y) => ({ ...Y, [r]: f.size }));
76
+ ), ee = oe((r, n, u) => {
77
+ const f = pe.current.get(r), O = f.size;
78
+ u ? f.add(n) : f.delete(n), f.size !== O && be((_) => ({ ..._, [r]: f.size }));
79
79
  }, []);
80
- oe(() => {
81
- const r = x.current;
80
+ se(() => {
81
+ const r = R.current;
82
82
  if (!r) return;
83
- const n = (f) => {
84
- const S = getComputedStyle(r).getPropertyValue("--om-widget-fold-breakpoint").trim(), Y = /^-?\d+(?:\.\d+)?px$/i.test(S) ? Number.parseFloat(S) : Number(S) || 640;
85
- de(p && f > 0 && f <= Math.max(0, Y));
83
+ let n, u = ze;
84
+ const f = (_) => {
85
+ const G = getComputedStyle(r).getPropertyValue("--om-widget-fold-breakpoint").trim();
86
+ G !== n && (n = G, u = Ae(G, r)), fe((we) => p && Ie(_, u, we));
86
87
  };
87
- if (n(r.getBoundingClientRect().width || (u ? u === !0 ? 800 : u.width ?? 800 : 0)), typeof ResizeObserver > "u") return;
88
- const d = new ResizeObserver(([f]) => n(f.contentRect.width));
89
- return d.observe(r), () => d.disconnect();
90
- }, [p, X]), R(() => {
91
- (!M || v) && W(null);
92
- }, [M, v]);
93
- const ee = h({ center: o, zoom: i, pitch: b, bearing: m });
94
- ee.current = { center: o, zoom: i, pitch: b, bearing: m };
95
- const A = h(t.onReady);
96
- A.current = t.onReady;
97
- const k = h(t.onViewStateChange);
98
- k.current = t.onViewStateChange;
99
- const K = h(t.onRuntimeError);
100
- K.current = t.onRuntimeError;
101
- const q = h(a);
102
- q.current = a;
103
- const V = h(void 0);
104
- oe(() => {
88
+ if (f(r.getBoundingClientRect().width || (d ? d === !0 ? 800 : d.width ?? 800 : 0)), typeof ResizeObserver > "u") return;
89
+ const O = new ResizeObserver(([_]) => f(_.contentRect.width));
90
+ return O.observe(r), () => O.disconnect();
91
+ }, [p, Z]), x(() => {
92
+ (!k || v) && q(null);
93
+ }, [k, v]);
94
+ const te = h({ center: o, zoom: i, pitch: b, bearing: m });
95
+ te.current = { center: o, zoom: i, pitch: b, bearing: m };
96
+ const K = h(t.onReady);
97
+ K.current = t.onReady;
98
+ const M = h(t.onViewStateChange);
99
+ M.current = t.onViewStateChange;
100
+ const H = h(t.onRuntimeError);
101
+ H.current = t.onRuntimeError;
102
+ const V = h(a);
103
+ V.current = a;
104
+ const B = h(void 0);
105
+ se(() => {
105
106
  if (!C.current) return;
106
- const r = ee.current;
107
- V.current = q.current;
108
- const n = new Pe(C.current, {
107
+ const r = te.current;
108
+ B.current = V.current;
109
+ const n = new Me(C.current, {
109
110
  center: r.center,
110
111
  zoom: r.zoom,
111
112
  pitch: r.pitch,
112
113
  bearing: r.bearing,
113
- basemap: q.current,
114
+ basemap: V.current,
114
115
  basemapKey: l,
115
116
  attribution: g,
116
- headless: u ? u === !0 ? {} : u : void 0,
117
+ headless: d ? d === !0 ? {} : d : void 0,
117
118
  chromeHosts: {
118
119
  badge: z.current.badge ?? void 0,
119
120
  attribution: z.current.attribution ?? void 0
120
121
  },
121
122
  onRuntimeError: (f) => {
122
- var S;
123
- return (S = K.current) == null ? void 0 : S.call(K, f);
123
+ var O;
124
+ return (O = H.current) == null ? void 0 : O.call(H, f);
124
125
  }
125
126
  });
126
- P(n);
127
- let d = !0;
127
+ T(n);
128
+ let u = !0;
128
129
  return n.ready.then(() => {
129
130
  var f;
130
- d && ((f = A.current) == null || f.call(A));
131
+ u && ((f = K.current) == null || f.call(K));
131
132
  }), () => {
132
- d = !1, P(null), n.destroy();
133
+ u = !1, T(null), n.destroy();
133
134
  };
134
- }, [X]), R(() => {
135
- !c || V.current === a || (V.current = a, c.setBasemap(a ?? null));
136
- }, [c, a]), Fe(s, () => c, [c]), R(() => {
135
+ }, [Z]), x(() => {
136
+ !c || B.current === a || (B.current = a, c.setBasemap(a ?? null));
137
+ }, [c, a]), Pe(s, () => c, [c]), x(() => {
137
138
  if (!c) return;
138
139
  const r = { longitude: o == null ? void 0 : o[0], latitude: o == null ? void 0 : o[1], zoom: i, pitch: b, bearing: m };
139
- We(c.getViewState(), r) && c.setView(r);
140
- }, [c, o == null ? void 0 : o[0], o == null ? void 0 : o[1], i, b, m]), R(() => {
140
+ Ge(c.getViewState(), r) && c.setView(r);
141
+ }, [c, o == null ? void 0 : o[0], o == null ? void 0 : o[1], i, b, m]), x(() => {
141
142
  var r;
142
143
  if (c)
143
- return (r = k.current) == null || r.call(k, c.getViewState()), c.getStore("viewport").subscribe(() => {
144
+ return (r = M.current) == null || r.call(M, c.getViewState()), c.getStore("viewport").subscribe(() => {
144
145
  var n;
145
- return (n = k.current) == null ? void 0 : n.call(k, c.getViewState());
146
+ return (n = M.current) == null ? void 0 : n.call(M, c.getViewState());
146
147
  });
147
148
  }, [c]);
148
- const Se = T(
149
+ const Oe = P(
149
150
  () => ({
150
151
  position: "absolute",
151
152
  inset: 0,
152
153
  zIndex: 20,
153
154
  pointerEvents: "none",
154
155
  opacity: "var(--om-widget-opacity, 1)",
155
- ...w ? Me(w).properties : void 0
156
+ ...w ? Le(w).properties : void 0
156
157
  }),
157
158
  [w]
158
- ), B = T(() => c ? new Ae(c) : null, [c]), te = T(
159
- () => c && B && F ? { controller: c, layers: B, overlayPane: F, corners: L, widgetsHidden: !!v, widgetsFolded: M, foldPanels: Q, registerFoldedWidget: Z } : null,
160
- [c, B, F, L, v, M, Q, Z]
159
+ ), Y = P(() => c ? new qe(c) : null, [c]), re = P(
160
+ () => c && Y && F ? { controller: c, layers: Y, overlayPane: F, corners: j, widgetsHidden: !!v, widgetsFolded: k, foldPanels: X, registerFoldedWidget: ee } : null,
161
+ [c, Y, F, j, v, k, X, ee]
161
162
  );
162
- return /* @__PURE__ */ G("div", { ref: x, className: y, style: { position: "relative", overflow: "hidden", ...O }, children: [
163
+ return /* @__PURE__ */ J("div", { ref: R, className: y, style: { position: "relative", overflow: "hidden", ...S }, children: [
163
164
  /* @__PURE__ */ E("div", { ref: C, style: { position: "absolute", inset: 0 } }),
164
165
  /* @__PURE__ */ E(
165
166
  "div",
166
167
  {
167
- ref: pe,
168
+ ref: he,
168
169
  style: { position: "absolute", top: 0, left: 0, zIndex: 10, pointerEvents: "none" }
169
170
  }
170
171
  ),
171
- /* @__PURE__ */ E("div", { "data-om-widget-layer": "", style: Se, children: H.map((r) => /* @__PURE__ */ G(
172
+ /* @__PURE__ */ E("div", { "data-om-widget-layer": "", style: Oe, children: N.map((r) => /* @__PURE__ */ J(
172
173
  "div",
173
174
  {
174
175
  "data-om-widget-slot": r,
175
- ref: he[r],
176
+ ref: ve[r],
176
177
  style: {
177
- ...Ke[r],
178
- ...M && r === "bottom-end" ? { bottom: "calc(var(--om-widget-inset-y, 12px) + 28px)" } : void 0
178
+ ...Ve[r],
179
+ ...k && r === "bottom-end" ? { bottom: "calc(var(--om-widget-inset-y, 12px) + 28px)" } : void 0
179
180
  },
180
181
  children: [
181
- M && I.filter((n) => ke(n) === r && me[n] > 0).map((n) => {
182
- const d = be === n;
183
- return /* @__PURE__ */ G(
182
+ k && A.filter((n) => $e(n) === r && ge[n] > 0).map((n) => {
183
+ const u = ye === n;
184
+ return /* @__PURE__ */ J(
184
185
  "div",
185
186
  {
186
187
  "data-om-fold-drawer": n,
187
- style: { ...Le(n), display: v ? "none" : "flex" },
188
+ style: { ..._e(n), display: v ? "none" : "flex" },
188
189
  onKeyDown: (f) => {
189
- var S;
190
- f.key !== "Escape" || !d || (W(null), (S = f.currentTarget.querySelector("[data-om-fold-toggle]")) == null || S.focus(), f.preventDefault(), f.stopPropagation());
190
+ var O;
191
+ f.key !== "Escape" || !u || (q(null), (O = f.currentTarget.querySelector("[data-om-fold-toggle]")) == null || O.focus(), f.preventDefault(), f.stopPropagation());
191
192
  },
192
193
  children: [
193
194
  /* @__PURE__ */ E(
@@ -195,15 +196,15 @@ const Ue = Re(function(t, s) {
195
196
  {
196
197
  type: "button",
197
198
  "data-om-fold-toggle": n,
198
- "aria-expanded": d,
199
- "aria-controls": `${U}-${n}`,
200
- "aria-label": `${d ? "Close" : "Open"} ${n} map controls`,
201
- style: $e(),
199
+ "aria-expanded": u,
200
+ "aria-controls": `${Q}-${n}`,
201
+ "aria-label": `${u ? "Close" : "Open"} ${n} map controls`,
202
+ style: je(),
202
203
  onClick: () => {
203
- W(d ? null : n), d || requestAnimationFrame(() => {
204
- var S;
205
- const f = (S = x.current) == null ? void 0 : S.querySelector(`[data-om-fold-panel="${n}"]`);
206
- f && Ne(f);
204
+ q(u ? null : n), u || requestAnimationFrame(() => {
205
+ var O;
206
+ const f = (O = R.current) == null ? void 0 : O.querySelector(`[data-om-fold-panel="${n}"]`);
207
+ f && Ye(f);
207
208
  });
208
209
  },
209
210
  children: "⋯"
@@ -212,13 +213,13 @@ const Ue = Re(function(t, s) {
212
213
  /* @__PURE__ */ E(
213
214
  "div",
214
215
  {
215
- id: `${U}-${n}`,
216
- ref: ve[n],
216
+ id: `${Q}-${n}`,
217
+ ref: Se[n],
217
218
  "data-om-fold-panel": n,
218
219
  role: "region",
219
220
  "aria-label": `${n} map controls`,
220
- hidden: !d,
221
- style: { ...je(n), display: d ? "flex" : "none" }
221
+ hidden: !u,
222
+ style: { ...De(n), display: u ? "flex" : "none" }
222
223
  }
223
224
  )
224
225
  ]
@@ -233,7 +234,7 @@ const Ue = Re(function(t, s) {
233
234
  ref: (n) => {
234
235
  z.current.badge = n;
235
236
  },
236
- style: se
237
+ style: ie
237
238
  }
238
239
  ),
239
240
  r === "bottom-end" && /* @__PURE__ */ E(
@@ -243,16 +244,16 @@ const Ue = Re(function(t, s) {
243
244
  ref: (n) => {
244
245
  z.current.attribution = n;
245
246
  },
246
- style: se
247
+ style: ie
247
248
  }
248
249
  )
249
250
  ]
250
251
  },
251
252
  r
252
253
  )) }),
253
- te && /* @__PURE__ */ E(ue.Provider, { value: te, children: j })
254
+ re && /* @__PURE__ */ E(ue.Provider, { value: re, children: $ })
254
255
  ] });
255
- }), qe = /* @__PURE__ */ new Set([
256
+ }), Je = /* @__PURE__ */ new Set([
256
257
  "id",
257
258
  "type",
258
259
  "data",
@@ -272,10 +273,10 @@ const Ue = Re(function(t, s) {
272
273
  "onClick",
273
274
  "onHover"
274
275
  ]);
275
- function Xe(e) {
276
- const { controller: t, layers: s } = N("OmLayer"), { id: o } = e, i = {};
276
+ function nt(e) {
277
+ const { controller: t, layers: s } = W("OmLayer"), { id: o } = e, i = {};
277
278
  for (const [l, g] of Object.entries(e))
278
- !qe.has(l) && g !== void 0 && (i[l] = g);
279
+ !Je.has(l) && g !== void 0 && (i[l] = g);
279
280
  const b = {
280
281
  id: o,
281
282
  type: e.type,
@@ -295,33 +296,33 @@ function Xe(e) {
295
296
  updateTriggers: e.updateTriggers,
296
297
  props: i
297
298
  };
298
- R(() => {
299
+ x(() => {
299
300
  s.upsert(b);
300
- }), R(() => () => s.remove(o), [s, o]);
301
+ }), x(() => () => s.remove(o), [s, o]);
301
302
  const m = h(e.onClick);
302
303
  m.current = e.onClick;
303
304
  const a = h(e.onHover);
304
- return a.current = e.onHover, R(
305
+ return a.current = e.onHover, x(
305
306
  () => t.watchPicks((l) => {
306
- var g, u, w;
307
+ var g, d, w;
307
308
  if (l === null) {
308
309
  (g = a.current) == null || g.call(a, null);
309
310
  return;
310
311
  }
311
- l.layerId === o && (l.type === "click" ? (u = m.current) == null || u.call(m, l) : (w = a.current) == null || w.call(a, l));
312
+ l.layerId === o && (l.type === "click" ? (d = m.current) == null || d.call(m, l) : (w = a.current) == null || w.call(a, l));
312
313
  }),
313
314
  [t, o]
314
315
  ), null;
315
316
  }
316
- function Ze({ position: e = "top-start", order: t, fold: s, className: o, style: i, children: b }) {
317
- const { corners: m, widgetsHidden: a, widgetsFolded: l, foldPanels: g, registerFoldedWidget: u } = N("OmWidget"), w = ae(), v = De(e) ?? "top-start", p = l && v !== "manual" && s !== "never", y = v === "manual" ? null : Ie(v);
318
- if (R(() => {
317
+ function ot({ position: e = "top-start", order: t, fold: s, className: o, style: i, children: b }) {
318
+ const { corners: m, widgetsHidden: a, widgetsFolded: l, foldPanels: g, registerFoldedWidget: d } = W("OmWidget"), w = le(), v = Ke(e) ?? "top-start", p = l && v !== "manual" && s !== "never", y = v === "manual" ? null : He(v);
319
+ if (x(() => {
319
320
  if (y)
320
- return u(y, w, p), () => u(y, w, !1);
321
- }, [y, w, p, u]), v === "manual")
321
+ return d(y, w, p), () => d(y, w, !1);
322
+ }, [y, w, p, d]), v === "manual")
322
323
  return /* @__PURE__ */ E("div", { className: o, style: { pointerEvents: "auto", ...i }, children: b });
323
- const O = p && y ? g[y] : m[v];
324
- return O ? ce(
324
+ const S = p && y ? g[y] : m[v];
325
+ return S ? de(
325
326
  /* @__PURE__ */ E(
326
327
  "div",
327
328
  {
@@ -337,13 +338,13 @@ function Ze({ position: e = "top-start", order: t, fold: s, className: o, style:
337
338
  children: b
338
339
  }
339
340
  ),
340
- O
341
+ S
341
342
  ) : null;
342
343
  }
343
- function ie(e, t) {
344
+ function ae(e, t) {
344
345
  return !t || (e == null ? void 0 : e.layerId) === t;
345
346
  }
346
- const Ve = {
347
+ const Ue = {
347
348
  "top-left": "translate(0, 0)",
348
349
  "top-center": "translate(-50%, 0)",
349
350
  "top-right": "translate(-100%, 0)",
@@ -354,47 +355,47 @@ const Ve = {
354
355
  "bottom-center": "translate(-50%, -100%)",
355
356
  "bottom-right": "translate(-100%, -100%)"
356
357
  };
357
- function et(e) {
358
- const { controller: t, overlayPane: s } = N("OmOverlay"), o = h(null), i = h(void 0), b = h(e);
358
+ function st(e) {
359
+ const { controller: t, overlayPane: s } = W("OmOverlay"), o = h(null), i = h(void 0), b = h(e);
359
360
  b.current = e;
360
- const m = T(() => {
361
+ const m = P(() => {
361
362
  const p = t.getStore("selection");
362
- let y, O, j = null;
363
+ let y, S, $ = null;
363
364
  return {
364
365
  subscribe: p.subscribe,
365
366
  getSnapshot: () => {
366
- const x = p.getSnapshot(), { anchorFrom: C, layer: c } = b.current, P = `${C ?? ""}|${c ?? ""}`;
367
- return (x !== y || P !== O) && (y = x, O = P, C === "selection" && ie(x, c) && (j = x)), j;
367
+ const R = p.getSnapshot(), { anchorFrom: C, layer: c } = b.current, T = `${C ?? ""}|${c ?? ""}`;
368
+ return (R !== y || T !== S) && (y = R, S = T, C === "selection" && ae(R, c) && ($ = R)), $;
368
369
  }
369
370
  };
370
- }, [t]), a = le(
371
+ }, [t]), a = ce(
371
372
  m.subscribe,
372
373
  m.getSnapshot,
373
374
  m.getSnapshot
374
375
  );
375
- R(
376
+ x(
376
377
  () => t.registerOverlay((p, y) => {
377
- const O = o.current;
378
- if (!O) return;
379
- const { anchor: j, anchorFrom: x, layer: C, visible: c = !0, anchorOffset: P } = b.current;
378
+ const S = o.current;
379
+ if (!S) return;
380
+ const { anchor: $, anchorFrom: R, layer: C, visible: c = !0, anchorOffset: T } = b.current;
380
381
  let F;
381
- if (x === "selection" ? (ie(y, C) && (i.current = (y == null ? void 0 : y.coordinate) ?? void 0), F = i.current) : F = j, !c || !F || !p) {
382
- O.style.visibility = "hidden";
382
+ if (R === "selection" ? (ae(y, C) && (i.current = (y == null ? void 0 : y.coordinate) ?? void 0), F = i.current) : F = $, !c || !F || !p) {
383
+ S.style.visibility = "hidden";
383
384
  return;
384
385
  }
385
- const [D, L, _] = p.project([F[0], F[1], 0]);
386
- if (!(D >= 0 && D <= p.width && L >= 0 && L <= p.height) || _ !== void 0 && _ < 0) {
387
- O.style.visibility = "hidden";
386
+ const [D, j, I] = p.project([F[0], F[1], 0]);
387
+ if (!(D >= 0 && D <= p.width && j >= 0 && j <= p.height) || I !== void 0 && I < 0) {
388
+ S.style.visibility = "hidden";
388
389
  return;
389
390
  }
390
- O.style.visibility = "visible", O.style.transform = `translate(${D}px, ${L}px) ${Ve[P ?? "bottom-center"]}`;
391
+ S.style.visibility = "visible", S.style.transform = `translate(${D}px, ${j}px) ${Ue[T ?? "bottom-center"]}`;
391
392
  }),
392
393
  [t]
393
- ), R(() => {
394
+ ), x(() => {
394
395
  t.refreshOverlays();
395
396
  });
396
- const { children: l, className: g, style: u, interactive: w = !0 } = e, v = typeof l == "function" ? l(a) : l;
397
- return ce(
397
+ const { children: l, className: g, style: d, interactive: w = !0 } = e, v = typeof l == "function" ? l(a) : l;
398
+ return de(
398
399
  /* @__PURE__ */ E(
399
400
  "div",
400
401
  {
@@ -408,7 +409,7 @@ function et(e) {
408
409
  // hidden until the first flush positions it — never flashes at the origin
409
410
  willChange: "transform",
410
411
  pointerEvents: w ? "auto" : "none",
411
- ...u
412
+ ...d
412
413
  },
413
414
  children: v
414
415
  }
@@ -416,29 +417,29 @@ function et(e) {
416
417
  s
417
418
  );
418
419
  }
419
- function tt(e = []) {
420
- const { controller: t } = N("useOmMap"), s = e.join(" "), o = T(() => {
421
- const m = (s ? s.split(" ") : []).flatMap((l) => _e(l) ? [t.getStore(l)] : (console.warn(`[onlymapjs] useOmMap: "${l}" is not a watch token on the React front-end — expected viewport, selection, layers, or data:<layerId>.`), []));
420
+ function it(e = []) {
421
+ const { controller: t } = W("useOmMap"), s = e.join(" "), o = P(() => {
422
+ const m = (s ? s.split(" ") : []).flatMap((l) => Ne(l) ? [t.getStore(l)] : (console.warn(`[onlymapjs] useOmMap: "${l}" is not a watch token on the React front-end — expected viewport, selection, layers, or data:<layerId>.`), []));
422
423
  let a;
423
424
  return {
424
425
  subscribe: (l) => {
425
- const g = m.map((u) => u.subscribe(l));
426
+ const g = m.map((d) => d.subscribe(l));
426
427
  return () => {
427
- for (const u of g) u();
428
+ for (const d of g) d();
428
429
  };
429
430
  },
430
431
  getSnapshot: () => {
431
432
  const l = m.map((g) => g.getSnapshot());
432
- return (!a || l.some((g, u) => g !== a[u])) && (a = l), a;
433
+ return (!a || l.some((g, d) => g !== a[d])) && (a = l), a;
433
434
  }
434
435
  };
435
- }, [t, s]), i = le(o.subscribe, o.getSnapshot, o.getSnapshot);
436
- return T(() => t.buildCtx(), [t, i]);
436
+ }, [t, s]), i = ce(o.subscribe, o.getSnapshot, o.getSnapshot);
437
+ return P(() => t.buildCtx(), [t, i]);
437
438
  }
438
439
  export {
439
- Xe as OmLayer,
440
- Ue as OmMap,
441
- et as OmOverlay,
442
- Ze as OmWidget,
443
- tt as useOmMap
440
+ nt as OmLayer,
441
+ rt as OmMap,
442
+ st as OmOverlay,
443
+ ot as OmWidget,
444
+ it as useOmMap
444
445
  };
@@ -52,6 +52,14 @@ export interface RuntimeCoreCallbacks {
52
52
  * deck reports none (e.g. off-globe).
53
53
  */
54
54
  onMapPoint?: (coordinate: [number, number] | null, kind: "click" | "hover") => void;
55
+ /**
56
+ * A tileset-bearing layer (Tile3DLayer) finished loading its root tileset
57
+ * — the consumer hook for tools that must reach the LIVE deck tileset
58
+ * (region export, custom traversal) which the IR/metadata surface can't
59
+ * expose. `tileset` is deck's `Tileset3D` (typed `unknown` here to avoid a
60
+ * @loaders.gl/tiles type dependency in the core).
61
+ */
62
+ onTilesetLoad?: (layerId: string, tileset: unknown) => void;
55
63
  /**
56
64
  * Runtime error boundary (spec: "Runtime error boundary") — deck.gl-level
57
65
  * failures (a crashing accessor, an incompatible prop) formatted into the
package/dist/testing.d.ts CHANGED
@@ -51,6 +51,12 @@ export interface TestHarness {
51
51
  pick(opts: PickOptions): Promise<void>;
52
52
  /** Ends the current selection (a hover-off) — the path that auto-hides tooltips. */
53
53
  clearSelection(): Promise<void>;
54
+ /**
55
+ * Feeds a map coordinate through the same path a real deck click/hover
56
+ * takes — drives the draw controller and fires the `om-map-point` event.
57
+ * For testing custom capture tools (sketch/AOI) without a GPU.
58
+ */
59
+ mapPoint(coordinate: [number, number] | null, kind?: "click" | "hover"): Promise<void>;
54
60
  /**
55
61
  * Sets the camera directly (center/zoom/pitch/bearing) — everything
56
62
  * viewport-derived reacts for real: `viewport`-watching widgets,
package/dist/version.d.ts CHANGED
@@ -5,4 +5,4 @@
5
5
  * the build rootDir, and a `define` would need repeating across vite/vitest/
6
6
  * vite-node configs.
7
7
  */
8
- export declare const LIBRARY_VERSION = "0.4.4";
8
+ export declare const LIBRARY_VERSION = "0.4.6";
@@ -32,6 +32,26 @@ export declare function foldToggleSlot(side: FoldSide): ManagedSlot;
32
32
  /** Shared drawer plumbing styles for the HTML and React front-ends. */
33
33
  export declare function foldDrawerStyle(side?: FoldSide): Record<string, string | number>;
34
34
  export declare function foldPanelStyle(side: FoldSide): Record<string, string | number>;
35
+ /** Default fold breakpoint (px) when `--om-widget-fold-breakpoint` is unset. */
36
+ export declare const DEFAULT_FOLD_BREAKPOINT_PX = 640;
37
+ /**
38
+ * Hysteresis band (px) so a map whose width oscillates around the breakpoint
39
+ * (drag-resize, flex, split-pane, a CSS transition) doesn't flap fold/unfold
40
+ * every ResizeObserver tick: fold at width ≤ breakpoint, unfold only once
41
+ * width ≥ breakpoint + this margin.
42
+ */
43
+ export declare const FOLD_HYSTERESIS_PX = 40;
44
+ /**
45
+ * `--om-widget-fold-breakpoint` (already read to `raw`) → px — ONE resolver
46
+ * for both front-ends so they can't fold at different widths. Accepts px, a
47
+ * bare number, or author units (rem/em/vw…) resolved through a transient
48
+ * probe appended to `probeParent` (the browser is the unit converter — no
49
+ * second implementation). Takes the raw string (not the element) so callers
50
+ * can cache on it and skip the probe when unchanged.
51
+ */
52
+ export declare function resolveFoldBreakpointPx(raw: string, probeParent: HTMLElement): number;
53
+ /** Fold decision with hysteresis — pure, shared by both lanes. `currentlyFolded` supplies the band's direction. */
54
+ export declare function shouldFoldAtWidth(width: number, breakpointPx: number, currentlyFolded: boolean): boolean;
35
55
  export declare function foldToggleStyle(): Record<string, string | number>;
36
56
  /** Legacy 4-corner vocabulary (pre-0.4.1) — accepted forever, mapped LOGICALLY. */
37
57
  export declare const LEGACY_POSITION_ALIASES: Readonly<Record<string, ManagedSlot>>;
package/docs/testing.md CHANGED
@@ -111,7 +111,7 @@ it("panning away empties viewport-scoped widgets", async () => {
111
111
  });
112
112
  ```
113
113
 
114
- The harness API: `pick` (synthetic picks fed through the exact code path real deck.gl picks take — columnar layers pick object-less by index, exactly like live), `clearSelection` (hover-off; runs the tooltip auto-hide path), `emit` (any action, same payload contract as `ctx.emit`/`data-emit`), `setView`, `layers()` (the live IR), `flush`, `unmount`. Every verb settles the library's internal batching before resolving — **you never write a sleep**.
114
+ The harness API: `pick` (synthetic picks fed through the exact code path real deck.gl picks take — columnar layers pick object-less by index, exactly like live), `clearSelection` (hover-off; runs the tooltip auto-hide path), `mapPoint` (a click/hover map coordinate through the real onMapPoint path — fires `om-map-point`, drives the draw controller), `emit` (any action, same payload contract as `ctx.emit`/`data-emit`), `setView`, `layers()` (the live IR), `flush`, `unmount`. Every verb settles the library's internal batching before resolving — **you never write a sleep**.
115
115
 
116
116
  **Remote data:** mock `fetch` and the harness waits for it via the readiness signal:
117
117
 
@@ -137,7 +137,9 @@ npx playwright install chromium
137
137
  npx onlymapjs check-layout public/dashboard.html
138
138
  ```
139
139
 
140
- `check-layout` serves the manifest over loopback HTTP (so relative data URLs work), executes it in an isolated headless Chromium context, opens responsive drawers, and checks real geometry/hit-testing at 360, 640, 768, and 1024px. It prints one JSON diagnostic per problem and exits 0 when clean or 1 on layout errors. Because it executes the page, only run it on manifests you trust.
140
+ `check-layout` serves the manifest over loopback HTTP (so relative data URLs work), executes it in an isolated headless Chromium context, opens responsive drawers, and checks real geometry/hit-testing at 360, 640, 768, and 1024px. It prints one JSON diagnostic per problem and exits 0 when clean or 1 on layout errors. Because it executes the page, only run it on manifests you trust. Point it at a **browser-runnable** manifest — one that imports the built library (`@nika-js/onlymap`) — not a framework dev-server page that relies on on-the-fly transpilation (a page importing raw `.ts` will fail to render a canvas, and the tool reports exactly that).
141
+
142
+ To run the same audit inside your own Playwright suite instead of the CLI, import it: `auditLayout(page, { widths })` returns the `LayoutDiagnostic[]` (the CLI is a thin wrapper over it), and `settleLayout(page)` awaits the render/fonts/attribution settle contract. Both come from `@nika-js/onlymap`.
141
143
 
142
144
  1. **`await mapEl.ready`** — resolves when the renderer initialized *and* the first reconcile ran *and* every declared `data` URL settled. Never `waitForTimeout`.
143
145
  2. **`mapEl.projectInternal([lng, lat])`** — derive click/hover pixels from the map's own projection instead of hardcoding coordinates.