@sakuzu/maplibre-gl-draw-ui 1.2.0 → 1.2.1

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
@@ -7,6 +7,18 @@ follows semantic versioning.
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.1] - 2026-10-02
11
+
12
+ ### Fixed in 1.2.1
13
+
14
+ - In a sheet the inspector passes the sheet's height to its panel, so
15
+ the content scrolls and the foot stays in view (#14).
16
+ - The delete button of the toolbar is off while the draw is read-only,
17
+ as the Delete of the inspector is (#19).
18
+ - The bottom corners and the actions card write what their observers
19
+ measure in the next frame, so WebKit reports no ResizeObserver loop
20
+ (#21).
21
+
10
22
  ## [1.2.0] - 2026-10-02
11
23
 
12
24
  The narrow screen and the stage, from the visual review: the map's
@@ -47,6 +47,8 @@ export interface CornerLift {
47
47
  * box reaches the corner across
48
48
  *
49
49
  * The boxes are measured where maplibre-gl places them, without what this moved. The attribution
50
- * and the right region are followed with a ResizeObserver, as the toolbar and the corners are.
50
+ * and the right region are followed with a ResizeObserver, as the toolbar and the corners are:
51
+ * the boxes are read in the observer's delivery and the custom properties are written in the next
52
+ * frame, so that what they move is not measured again in the same delivery.
51
53
  */
52
54
  export declare function cornerLift(container: HTMLElement, root: HTMLElement): CornerLift;
package/dist/index.js CHANGED
@@ -1892,6 +1892,17 @@ function Dropdown($$anchor, $$props) {
1892
1892
  $$props.onOpenChange?.($.get(open));
1893
1893
  });
1894
1894
  let anchor = $.state(void 0);
1895
+ let told = false;
1896
+ $.user_effect(() => {
1897
+ const el = $.get(anchor);
1898
+ const now = $.get(open);
1899
+ if (!el || now === told) return;
1900
+ told = now;
1901
+ el.dispatchEvent(new CustomEvent("kata-menu-toggle", {
1902
+ bubbles: true,
1903
+ detail: { open: now }
1904
+ }));
1905
+ });
1895
1906
  let panelEl = $.state(void 0);
1896
1907
  let placed = $.state(false);
1897
1908
  let pos = $.state($.proxy({
@@ -9458,6 +9469,22 @@ function TreeRow($$anchor, $$props) {
9458
9469
  if (frame) cancelAnimationFrame(frame);
9459
9470
  };
9460
9471
  });
9472
+ let rowEl = $.state(void 0);
9473
+ let menuOpen = $.state(false);
9474
+ $.user_effect(() => {
9475
+ const el = $.get(rowEl);
9476
+ if (!el) return;
9477
+ const from = /* @__PURE__ */ new Set();
9478
+ const onMenuToggle = (e) => {
9479
+ const target = e.target;
9480
+ if (!target) return;
9481
+ if (e.detail?.open) from.add(target);
9482
+ else from.delete(target);
9483
+ $.set(menuOpen, from.size > 0);
9484
+ };
9485
+ el.addEventListener("kata-menu-toggle", onMenuToggle);
9486
+ return () => el.removeEventListener("kata-menu-toggle", onMenuToggle);
9487
+ });
9461
9488
  function toggle() {
9462
9489
  expanded(!expanded());
9463
9490
  $$props.ontoggle?.(expanded());
@@ -9480,6 +9507,7 @@ function TreeRow($$anchor, $$props) {
9480
9507
  $.attribute_effect(div, () => ({
9481
9508
  class: "tree-row",
9482
9509
  "data-dim": hidden() || dimmed() || dragging() ? "" : void 0,
9510
+ "data-open": $.get(menuOpen) ? "" : void 0,
9483
9511
  role: "treeitem",
9484
9512
  "aria-selected": sel(),
9485
9513
  "aria-expanded": expandable() ? expanded() : void 0,
@@ -9592,6 +9620,7 @@ function TreeRow($$anchor, $$props) {
9592
9620
  });
9593
9621
  }
9594
9622
  $.reset(div);
9623
+ $.bind_this(div, ($$value) => $.set(rowEl, $$value), () => $.get(rowEl));
9595
9624
  $.append($$anchor, div);
9596
9625
  $.pop();
9597
9626
  }
@@ -10204,9 +10233,11 @@ function Sheet($$anchor, $$props) {
10204
10233
  full: 1
10205
10234
  };
10206
10235
  const MIN_DRAG = 48;
10236
+ const MIN_MOVE = 4;
10207
10237
  let el = $.state(void 0);
10208
10238
  let dragH = $.state(null);
10209
10239
  let dragging = $.state(false);
10240
+ let dragged = false;
10210
10241
  let startY = 0;
10211
10242
  let startH = 0;
10212
10243
  let parentH = 0;
@@ -10216,8 +10247,12 @@ function Sheet($$anchor, $$props) {
10216
10247
  stage(next);
10217
10248
  $$props.onstage?.(next);
10218
10249
  }
10219
- function cycle() {
10250
+ function cycle(e) {
10220
10251
  if ($.get(dragging)) return;
10252
+ if (dragged && e.detail > 0) {
10253
+ dragged = false;
10254
+ return;
10255
+ }
10221
10256
  go(stages()[$.get(index) >= stages().length - 1 ? 0 : $.get(index) + 1]);
10222
10257
  }
10223
10258
  function down(e) {
@@ -10227,6 +10262,7 @@ function Sheet($$anchor, $$props) {
10227
10262
  startH = $.get(el).getBoundingClientRect().height;
10228
10263
  $.set(dragH, startH, true);
10229
10264
  $.set(dragging, true);
10265
+ dragged = false;
10230
10266
  e.currentTarget.setPointerCapture?.(e.pointerId);
10231
10267
  }
10232
10268
  function move(e) {
@@ -10234,18 +10270,22 @@ function Sheet($$anchor, $$props) {
10234
10270
  const h = startH + (startY - e.clientY);
10235
10271
  $.set(dragH, Math.max(MIN_DRAG, Math.min(parentH * .94, h)), true);
10236
10272
  }
10237
- function up() {
10273
+ function up(e) {
10238
10274
  if (!$.get(dragging)) return;
10239
10275
  $.set(dragging, false);
10240
- const frac = ($.get(dragH) ?? 0) / (parentH || 1);
10276
+ const h = $.get(dragH) ?? 0;
10241
10277
  $.set(dragH, null);
10278
+ if (Math.abs(e.clientY - startY) < MIN_MOVE) return;
10279
+ dragged = true;
10280
+ const frac = h / (parentH || 1);
10242
10281
  if (closable() && frac < FRAC[stages()[0]] * .55) {
10243
10282
  $$props.onclose?.();
10244
10283
  return;
10245
10284
  }
10246
- let best = stages()[0];
10285
+ const near = stages().filter((_, i) => h > startH ? i >= $.get(index) : h < startH ? i <= $.get(index) : true);
10286
+ let best = near[0];
10247
10287
  let bestD = Number.POSITIVE_INFINITY;
10248
- for (const s of stages()) {
10288
+ for (const s of near) {
10249
10289
  const d = Math.abs(FRAC[s] - frac);
10250
10290
  if (d < bestD) {
10251
10291
  bestD = d;
@@ -10566,7 +10606,7 @@ function Section($$anchor, $$props) {
10566
10606
  }
10567
10607
  //#endregion
10568
10608
  //#region ../node_modules/@sakuzu/kata/dist/svelte/components/Stat.svelte
10569
- var root$18 = $.from_html(`<div class="stat svelte-1hxotol" data-role="stat"><span class="v svelte-1hxotol"> </span> <span class="k svelte-1hxotol"><!><span class="t svelte-1hxotol"> </span></span></div>`);
10609
+ var root$18 = $.from_html(`<div class="stat svelte-1hxotol" data-role="stat" data-pass=""><span class="v svelte-1hxotol"> </span> <span class="k svelte-1hxotol"><!><span class="t svelte-1hxotol"> </span></span></div>`);
10570
10610
  function Stat($$anchor, $$props) {
10571
10611
  var div = root$18();
10572
10612
  var span = $.child(div);
@@ -12290,10 +12330,12 @@ function Actions($$anchor, $$props) {
12290
12330
  const attribution = () => $$props.corner?.querySelector(":scope > .maplibregl-control-container > .maplibregl-ctrl-bottom-right > .maplibregl-ctrl-attrib") ?? null;
12291
12331
  const toolbar = (root) => root.querySelector("[data-region=\"bottom\"] [data-role=\"drawbar\"]");
12292
12332
  const reopenButton = (root) => root.querySelector(":scope > [data-role=\"reopen\"] > [data-role=\"floating\"]");
12293
- function place() {
12333
+ /** Where the card goes, measured now: the room it reserves, its height above the bottom, and
12334
+ * the room above it; null while it is not on the page */
12335
+ function measure() {
12294
12336
  const root = $.get(card)?.parentElement;
12295
12337
  const el = floating();
12296
- if (!root || !el) return;
12338
+ if (!root || !el) return null;
12297
12339
  const box = root.getBoundingClientRect();
12298
12340
  const r = el.getBoundingClientRect();
12299
12341
  const scale = bottomLeft()?.getBoundingClientRect();
@@ -12304,11 +12346,41 @@ function Actions($$anchor, $$props) {
12304
12346
  if (b && b.width > 0 && b.height > 0 && r.right > b.left && r.left < b.right) next = Math.max(next, box.bottom - b.top);
12305
12347
  next = Math.max(0, Math.round(next));
12306
12348
  const reserve = `${Math.max(0, Math.round(r.height + (box.bottom - r.bottom) + (next - $.get(bottom))))}px`;
12307
- if (root.style.getPropertyValue(RESERVE) !== reserve) root.style.setProperty(RESERVE, reserve);
12308
- $.set(bottom, next, true);
12309
12349
  const button = reopen() ? reopenButton(root)?.getBoundingClientRect() : void 0;
12310
12350
  const above = button && button.height > 0 ? button.height : 0;
12311
- $.set(room, Math.max(0, Math.round(box.height - next - above)), true);
12351
+ return {
12352
+ root,
12353
+ reserve,
12354
+ bottom: next,
12355
+ room: Math.max(0, Math.round(box.height - next - above))
12356
+ };
12357
+ }
12358
+ /** Writes a place measured before */
12359
+ function write(at) {
12360
+ const { root, reserve } = at;
12361
+ if (root.style.getPropertyValue(RESERVE) !== reserve) root.style.setProperty(RESERVE, reserve);
12362
+ $.set(bottom, at.bottom, true);
12363
+ $.set(room, at.room, true);
12364
+ }
12365
+ let frame = 0;
12366
+ /** Places the card now */
12367
+ function place() {
12368
+ if (frame) cancelAnimationFrame(frame);
12369
+ frame = 0;
12370
+ const at = measure();
12371
+ if (at) write(at);
12372
+ }
12373
+ /**
12374
+ * An observer's delivery: measures now and writes in the next frame, so that what the writes
12375
+ * move is not measured again in the same delivery
12376
+ */
12377
+ function placeLater() {
12378
+ const at = measure();
12379
+ if (frame) cancelAnimationFrame(frame);
12380
+ frame = at ? requestAnimationFrame(() => {
12381
+ frame = 0;
12382
+ write(at);
12383
+ }) : 0;
12312
12384
  }
12313
12385
  $.user_effect(() => {
12314
12386
  const el = $.get(card) && floating();
@@ -12322,7 +12394,7 @@ function Actions($$anchor, $$props) {
12322
12394
  place();
12323
12395
  return () => root.style.removeProperty(RESERVE);
12324
12396
  }
12325
- const observer = new ResizeObserver(() => place());
12397
+ const observer = new ResizeObserver(() => placeLater());
12326
12398
  let bar = null;
12327
12399
  const watch = () => {
12328
12400
  bar = toolbar(root);
@@ -12340,19 +12412,21 @@ function Actions($$anchor, $$props) {
12340
12412
  const mutations = typeof MutationObserver === "undefined" || !shell ? null : new MutationObserver(() => {
12341
12413
  if (toolbar(root) === bar) return;
12342
12414
  watch();
12343
- place();
12415
+ placeLater();
12344
12416
  });
12345
12417
  mutations?.observe(shell, {
12346
12418
  childList: true,
12347
12419
  subtree: true
12348
12420
  });
12349
- const moves = typeof MutationObserver === "undefined" || !$$props.corner ? null : new MutationObserver(() => place());
12421
+ const moves = typeof MutationObserver === "undefined" || !$$props.corner ? null : new MutationObserver(() => placeLater());
12350
12422
  if ($$props.corner) moves?.observe($$props.corner, {
12351
12423
  attributes: true,
12352
12424
  attributeFilter: ["style"]
12353
12425
  });
12354
12426
  place();
12355
12427
  return () => {
12428
+ if (frame) cancelAnimationFrame(frame);
12429
+ frame = 0;
12356
12430
  observer.disconnect();
12357
12431
  mutations?.disconnect();
12358
12432
  moves?.disconnect();
@@ -16562,6 +16636,7 @@ function Toolbar($$anchor, $$props) {
16562
16636
  /** Whether the tooltips show the keys (when the keyboard shortcuts are on) */
16563
16637
  const mode = $.derived(() => follow($$props.draw, ["mode.changed"], () => $$props.draw.getMode()));
16564
16638
  const selected = $.derived(() => follow($$props.draw, ["selection.changed"], () => $$props.draw.selection.get().ids.length));
16639
+ const readOnly = $.derived(() => follow($$props.draw, ["readOnly.changed"], () => $$props.draw.isReadOnly()));
16565
16640
  const snapOn = $.derived(() => follow($$props.draw, ["options.changed"], () => $$props.draw.options.get().snapping?.enabled !== false));
16566
16641
  let settings = $.state(void 0);
16567
16642
  const m = $.derived(() => $$props.messages.get());
@@ -16577,7 +16652,7 @@ function Toolbar($$anchor, $$props) {
16577
16652
  kbd: keys() ? formatShortcut("delete") : void 0,
16578
16653
  group: DELETE_ID,
16579
16654
  tone: "danger",
16580
- disabled: $.get(selected).get() === 0
16655
+ disabled: $.get(selected).get() === 0 || $.get(readOnly).get()
16581
16656
  }] : []]);
16582
16657
  const toggles = $.derived(() => snapping() ? [{
16583
16658
  id: SNAPPING_ID,
@@ -17054,11 +17129,14 @@ var upDown = (a, b) => a.top < b.bottom && b.top < a.bottom;
17054
17129
  * box reaches the corner across
17055
17130
  *
17056
17131
  * The boxes are measured where maplibre-gl places them, without what this moved. The attribution
17057
- * and the right region are followed with a ResizeObserver, as the toolbar and the corners are.
17132
+ * and the right region are followed with a ResizeObserver, as the toolbar and the corners are:
17133
+ * the boxes are read in the observer's delivery and the custom properties are written in the next
17134
+ * frame, so that what they move is not measured again in the same delivery.
17058
17135
  */
17059
17136
  function cornerLift(container, root) {
17060
17137
  let destroyed = false;
17061
17138
  let observer;
17139
+ let frame = 0;
17062
17140
  let observed = [];
17063
17141
  let inset = {
17064
17142
  top: 0,
@@ -17101,12 +17179,13 @@ function cornerLift(container, root) {
17101
17179
  container.style.setProperty("--mgd-ui-lift-right", `${right}px`);
17102
17180
  container.style.setProperty("--mgd-ui-shift-right", `${shift}px`);
17103
17181
  }
17104
- function apply() {
17105
- if (destroyed) return;
17106
- if (!container.isConnected) {
17107
- set(0, 0, 0);
17108
- return;
17109
- }
17182
+ /** What to apply, measured now: the lift of each corner and the shift of the right controls */
17183
+ function measure() {
17184
+ if (!container.isConnected) return {
17185
+ left: 0,
17186
+ right: 0,
17187
+ shift: 0
17188
+ };
17110
17189
  const box = container.getBoundingClientRect();
17111
17190
  const place = (side) => {
17112
17191
  const el = corner(side);
@@ -17144,7 +17223,28 @@ function cornerLift(container, root) {
17144
17223
  const l = moved(left, 0, -liftLeft);
17145
17224
  if (across(a, l) && upDown(a, l)) liftLeft = Math.round(left.bottom - a.top);
17146
17225
  }
17147
- set(Math.max(0, liftLeft), liftRight, shift);
17226
+ return {
17227
+ left: Math.max(0, liftLeft),
17228
+ right: liftRight,
17229
+ shift
17230
+ };
17231
+ }
17232
+ function apply() {
17233
+ if (destroyed) return;
17234
+ if (frame) cancelAnimationFrame(frame);
17235
+ frame = 0;
17236
+ const next = measure();
17237
+ set(next.left, next.right, next.shift);
17238
+ }
17239
+ /** The observer's delivery: measures now, and writes in the next frame */
17240
+ function delivered() {
17241
+ if (destroyed) return;
17242
+ const next = measure();
17243
+ if (frame) cancelAnimationFrame(frame);
17244
+ frame = requestAnimationFrame(() => {
17245
+ frame = 0;
17246
+ if (!destroyed) set(next.left, next.right, next.shift);
17247
+ });
17148
17248
  }
17149
17249
  function follow() {
17150
17250
  const next = [
@@ -17159,7 +17259,7 @@ function cornerLift(container, root) {
17159
17259
  observer?.disconnect();
17160
17260
  observed = next;
17161
17261
  if (typeof ResizeObserver === "undefined") return;
17162
- observer ??= new ResizeObserver(apply);
17262
+ observer ??= new ResizeObserver(delivered);
17163
17263
  for (const el of observed) observer.observe(el);
17164
17264
  }
17165
17265
  return {
@@ -17172,6 +17272,8 @@ function cornerLift(container, root) {
17172
17272
  destroy() {
17173
17273
  if (destroyed) return;
17174
17274
  destroyed = true;
17275
+ if (frame) cancelAnimationFrame(frame);
17276
+ frame = 0;
17175
17277
  observer?.disconnect();
17176
17278
  observer = void 0;
17177
17279
  observed = [];