@yuneta/gobj-ui 7.23.110 → 7.23.111

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.
@@ -942,7 +942,7 @@ function mt_create$21(gobj) {
942
942
  /***************************************************************
943
943
  * Framework Method: Start
944
944
  ***************************************************************/
945
- function mt_start$18(gobj) {
945
+ function mt_start$19(gobj) {
946
946
  let config = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "config") || {};
947
947
  let priv = gobj.priv;
948
948
  if (!validate_config(config)) {
@@ -1011,7 +1011,7 @@ function mt_start$18(gobj) {
1011
1011
  /***************************************************************
1012
1012
  * Framework Method: Stop
1013
1013
  ***************************************************************/
1014
- function mt_stop$18(gobj) {
1014
+ function mt_stop$19(gobj) {
1015
1015
  let priv = gobj.priv;
1016
1016
  if (!priv) return 0;
1017
1017
  close_toolbar_dropdown(gobj);
@@ -2556,8 +2556,8 @@ function ac_nav_item_close(gobj, event, kw, src) {
2556
2556
  ***************************************************************/
2557
2557
  var gmt$21 = {
2558
2558
  mt_create: mt_create$21,
2559
- mt_start: mt_start$18,
2560
- mt_stop: mt_stop$18,
2559
+ mt_start: mt_start$19,
2560
+ mt_stop: mt_stop$19,
2561
2561
  mt_destroy: mt_destroy$21
2562
2562
  };
2563
2563
  function create_gclass$21(gclass_name) {
@@ -4897,11 +4897,11 @@ function mt_create$18(gobj) {
4897
4897
  /***************************************************************
4898
4898
  * Framework Method: Start
4899
4899
  ***************************************************************/
4900
- function mt_start$17(gobj) {}
4900
+ function mt_start$18(gobj) {}
4901
4901
  /***************************************************************
4902
4902
  * Framework Method: Stop
4903
4903
  ***************************************************************/
4904
- function mt_stop$17(gobj) {
4904
+ function mt_stop$18(gobj) {
4905
4905
  (0, _yuneta_gobj_js.gobj_stop_children)(gobj);
4906
4906
  }
4907
4907
  /***************************************************************
@@ -5188,8 +5188,8 @@ function ac_resize$5(gobj, event, kw, src) {
5188
5188
  ***************************/
5189
5189
  var gmt$18 = {
5190
5190
  mt_create: mt_create$18,
5191
- mt_start: mt_start$17,
5192
- mt_stop: mt_stop$17,
5191
+ mt_start: mt_start$18,
5192
+ mt_stop: mt_stop$18,
5193
5193
  mt_destroy: mt_destroy$18
5194
5194
  };
5195
5195
  /***************************************************************
@@ -5431,11 +5431,11 @@ function mt_create$17(gobj) {
5431
5431
  /***************************************************************
5432
5432
  * Framework Method: Start
5433
5433
  ***************************************************************/
5434
- function mt_start$16(gobj) {}
5434
+ function mt_start$17(gobj) {}
5435
5435
  /***************************************************************
5436
5436
  * Framework Method: Stop
5437
5437
  ***************************************************************/
5438
- function mt_stop$16(gobj) {
5438
+ function mt_stop$17(gobj) {
5439
5439
  (0, _yuneta_gobj_js.gobj_stop_children)(gobj);
5440
5440
  }
5441
5441
  /***************************************************************
@@ -5795,8 +5795,8 @@ function ac_resize$4(gobj, event, kw, src) {
5795
5795
  ***************************/
5796
5796
  var gmt$17 = {
5797
5797
  mt_create: mt_create$17,
5798
- mt_start: mt_start$16,
5799
- mt_stop: mt_stop$16,
5798
+ mt_start: mt_start$17,
5799
+ mt_stop: mt_stop$17,
5800
5800
  mt_destroy: mt_destroy$17
5801
5801
  };
5802
5802
  /***************************************************************
@@ -6922,14 +6922,14 @@ function mt_destroy$16(gobj) {
6922
6922
  /************************************************************
6923
6923
  * Framework Method start
6924
6924
  ************************************************************/
6925
- function mt_start$15(gobj) {
6925
+ function mt_start$16(gobj) {
6926
6926
  let record = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "record");
6927
6927
  if (record) (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_LOAD_RECORD", record, gobj);
6928
6928
  }
6929
6929
  /************************************************************
6930
6930
  * Framework Method stop
6931
6931
  ************************************************************/
6932
- function mt_stop$15(gobj) {}
6932
+ function mt_stop$16(gobj) {}
6933
6933
  /***************************
6934
6934
  * Local Methods
6935
6935
  ***************************/
@@ -9154,8 +9154,8 @@ function cmd_get_picked_files(gobj, cmd, kw, src) {
9154
9154
  }
9155
9155
  var gmt$16 = {
9156
9156
  mt_create: mt_create$16,
9157
- mt_start: mt_start$15,
9158
- mt_stop: mt_stop$15,
9157
+ mt_start: mt_start$16,
9158
+ mt_stop: mt_stop$16,
9159
9159
  mt_destroy: mt_destroy$16,
9160
9160
  mt_command_parser: mt_command_parser$2
9161
9161
  };
@@ -9417,6 +9417,78 @@ var MarkerControl = class {
9417
9417
  (0, _yuneta_gobj_js.gobj_send_event)(this.gobj, "EV_CONTROL_MAP", { user_location: this._enable_user_location }, this.gobj);
9418
9418
  }
9419
9419
  };
9420
+ /***********************************************************************
9421
+ * MAPLIBRE'S OWN CHROME, IN THE APP'S LANGUAGE
9422
+ *
9423
+ * Everything maplibre draws with words -- the zoom tooltips, the
9424
+ * geolocate button, the attribution toggle, a popup's close, and the
9425
+ * notice that teaches the Ctrl + wheel gesture -- comes from its
9426
+ * `locale`, an option merged over its own English defaults at
9427
+ * construction. So a map in a Spanish app was saying *"Zoom in"* and
9428
+ * *"Use Ctrl + scroll to zoom the map"*, which is the same rule this
9429
+ * GUI applies to every other string.
9430
+ *
9431
+ * Two halves, because maplibre reads its strings ONCE, when each
9432
+ * control builds its DOM:
9433
+ *
9434
+ * `yui_maplibre_locale(t)` the `locale` option, for the map's
9435
+ * first paint;
9436
+ * `yui_maplibre_relocalize()` after a language change, which is
9437
+ * the half a `locale` alone cannot
9438
+ * do -- it writes the strings into
9439
+ * the DOM already drawn, and updates
9440
+ * the map's locale so anything built
9441
+ * later is right too.
9442
+ *
9443
+ * The scale units (`km`, `mi`, `nm`) are symbols and are left alone;
9444
+ * the MapLibre logo keeps its name, which is a brand.
9445
+ ***********************************************************************/
9446
+ function yui_maplibre_locale(t) {
9447
+ return {
9448
+ "NavigationControl.ZoomIn": t("zoom in"),
9449
+ "NavigationControl.ZoomOut": t("zoom out"),
9450
+ "NavigationControl.ResetBearing": t("drag to rotate the map, click to reset north"),
9451
+ "GeolocateControl.FindMyLocation": t("find my location"),
9452
+ "GeolocateControl.LocationNotAvailable": t("location not available"),
9453
+ "AttributionControl.ToggleAttribution": t("toggle attribution"),
9454
+ "AttributionControl.MapFeedback": t("map feedback"),
9455
+ "FullscreenControl.Enter": t("enter fullscreen"),
9456
+ "FullscreenControl.Exit": t("exit fullscreen"),
9457
+ "Popup.Close": t("close popup"),
9458
+ "Map.Title": t("map"),
9459
+ "Marker.Title": t("map marker"),
9460
+ "CooperativeGesturesHandler.WindowsHelpText": t("use ctrl + scroll to zoom the map"),
9461
+ "CooperativeGesturesHandler.MacHelpText": t("use cmd + scroll to zoom the map"),
9462
+ "CooperativeGesturesHandler.MobileHelpText": t("use two fingers to move the map")
9463
+ };
9464
+ }
9465
+ function label_ctrl($root, selector, text) {
9466
+ if (!$root || !text) return;
9467
+ for (const $el of $root.querySelectorAll(selector)) {
9468
+ $el.setAttribute("title", text);
9469
+ $el.setAttribute("aria-label", text);
9470
+ }
9471
+ }
9472
+ function yui_maplibre_relocalize(map, t) {
9473
+ if (!map || typeof map.getContainer !== "function") return;
9474
+ const strings = yui_maplibre_locale(t);
9475
+ try {
9476
+ map._locale = Object.assign({}, map._locale, strings);
9477
+ } catch (e) {}
9478
+ const $c = map.getContainer();
9479
+ label_ctrl($c, ".maplibregl-ctrl-zoom-in", strings["NavigationControl.ZoomIn"]);
9480
+ label_ctrl($c, ".maplibregl-ctrl-zoom-out", strings["NavigationControl.ZoomOut"]);
9481
+ label_ctrl($c, ".maplibregl-ctrl-compass", strings["NavigationControl.ResetBearing"]);
9482
+ label_ctrl($c, ".maplibregl-ctrl-geolocate", strings["GeolocateControl.FindMyLocation"]);
9483
+ label_ctrl($c, ".maplibregl-ctrl-attrib-button", strings["AttributionControl.ToggleAttribution"]);
9484
+ label_ctrl($c, ".maplibregl-ctrl-fullscreen", strings["FullscreenControl.Enter"]);
9485
+ label_ctrl($c, ".maplibregl-popup-close-button", strings["Popup.Close"]);
9486
+ const mac = typeof navigator !== "undefined" && (navigator.userAgent || "").includes("Mac");
9487
+ const $desktop = $c.querySelector(".maplibregl-desktop-message");
9488
+ if ($desktop) $desktop.textContent = mac ? strings["CooperativeGesturesHandler.MacHelpText"] : strings["CooperativeGesturesHandler.WindowsHelpText"];
9489
+ const $mobile = $c.querySelector(".maplibregl-mobile-message");
9490
+ if ($mobile) $mobile.textContent = strings["CooperativeGesturesHandler.MobileHelpText"];
9491
+ }
9420
9492
  //#endregion
9421
9493
  //#region src/c_yui_map.js
9422
9494
  /***********************************************************************
@@ -9431,6 +9503,7 @@ var MarkerControl = class {
9431
9503
  * Constants
9432
9504
  ***************************************************************/
9433
9505
  var GCLASS_NAME$15 = "C_YUI_MAP";
9506
+ var GESTURE_HINT_MS = 2e3;
9434
9507
  /***************************************************************
9435
9508
  * Data
9436
9509
  ***************************************************************/
@@ -9457,6 +9530,7 @@ var attrs_table$15 = [
9457
9530
  ];
9458
9531
  var PRIVATE_DATA$15 = {
9459
9532
  xmap: null,
9533
+ gesture_hint_timer: null,
9460
9534
  geojson: null,
9461
9535
  resizeObserver: null,
9462
9536
  width: 0,
@@ -9481,7 +9555,8 @@ function mt_create$15(gobj) {
9481
9555
  if ($map) $map.classList.add(GCLASS_NAME$15);
9482
9556
  Object.assign(map_settings, {
9483
9557
  container: $map,
9484
- cooperativeGestures: true
9558
+ cooperativeGestures: true,
9559
+ locale: yui_maplibre_locale(i18next.t)
9485
9560
  });
9486
9561
  priv.onClick = (ev) => {
9487
9562
  onClick(gobj, ev);
@@ -9499,6 +9574,16 @@ function mt_create$15(gobj) {
9499
9574
  xtouchStart(gobj, ev);
9500
9575
  };
9501
9576
  const map = priv.xmap = new maplibre_gl.Map(map_settings);
9577
+ map.on("cooperativegestureprevented", () => {
9578
+ const $s = map.getCanvasContainer().querySelector(".maplibregl-cooperative-gesture-screen");
9579
+ if (!$s) return;
9580
+ $s.classList.add("MAP_GESTURE_SHOWN");
9581
+ if (priv.gesture_hint_timer) clearTimeout(priv.gesture_hint_timer);
9582
+ priv.gesture_hint_timer = setTimeout(() => {
9583
+ priv.gesture_hint_timer = null;
9584
+ $s.classList.remove("MAP_GESTURE_SHOWN");
9585
+ }, GESTURE_HINT_MS);
9586
+ });
9502
9587
  map.addControl(new maplibre_gl.NavigationControl());
9503
9588
  map.addControl(new MarkerControl(gobj, {}), "top-right");
9504
9589
  map.addControl(new EditControl(gobj, { showMarkerDrag: true }), "top-right");
@@ -9528,10 +9613,46 @@ function mt_create$15(gobj) {
9528
9613
  }
9529
9614
  }
9530
9615
  /***************************************************************
9616
+ * The application changed language: maplibre's own words are
9617
+ * rewritten in place, and the map's locale with them so a
9618
+ * control or a popup built later is right too.
9619
+ ***************************************************************/
9620
+ function ac_language_changed$9(gobj, event, kw, src) {
9621
+ let priv = gobj.priv;
9622
+ if (priv.xmap) yui_maplibre_relocalize(priv.xmap, i18next.t);
9623
+ return 0;
9624
+ }
9625
+ /***************************************************************
9626
+ * Framework Method: Start
9627
+ *
9628
+ * The application's LANGUAGE: what maplibre draws with words is
9629
+ * built from its `locale` when each control builds its DOM, so
9630
+ * `refresh_language()` -- which reaches what carries an i18n key
9631
+ * in OUR dom -- cannot touch any of it. The shell says when the
9632
+ * language changed and this view rewrites those strings.
9633
+ ***************************************************************/
9634
+ function mt_start$15(gobj) {
9635
+ let shell = yui_shell_of(gobj);
9636
+ if (shell) (0, _yuneta_gobj_js.gobj_subscribe_event)(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
9637
+ return 0;
9638
+ }
9639
+ /***************************************************************
9640
+ * Framework Method: Stop
9641
+ ***************************************************************/
9642
+ function mt_stop$15(gobj) {
9643
+ let shell = yui_shell_of(gobj);
9644
+ if (shell) (0, _yuneta_gobj_js.gobj_unsubscribe_event)(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
9645
+ return 0;
9646
+ }
9647
+ /***************************************************************
9531
9648
  * Framework Method: Destroy
9532
9649
  ***************************************************************/
9533
9650
  function mt_destroy$15(gobj) {
9534
9651
  let priv = gobj.priv;
9652
+ if (priv.gesture_hint_timer) {
9653
+ clearTimeout(priv.gesture_hint_timer);
9654
+ priv.gesture_hint_timer = null;
9655
+ }
9535
9656
  if (priv.resizeObserver) {
9536
9657
  priv.resizeObserver.disconnect();
9537
9658
  priv.resizeObserver = null;
@@ -9992,6 +10113,8 @@ function ac_hide$10(gobj, event, kw, src) {
9992
10113
  ***************************/
9993
10114
  var gmt$15 = {
9994
10115
  mt_create: mt_create$15,
10116
+ mt_start: mt_start$15,
10117
+ mt_stop: mt_stop$15,
9995
10118
  mt_destroy: mt_destroy$15
9996
10119
  };
9997
10120
  /***************************************************************
@@ -10003,6 +10126,7 @@ function create_gclass$15(gclass_name) {
10003
10126
  return -1;
10004
10127
  }
10005
10128
  __gclass__$15 = (0, _yuneta_gobj_js.gclass_create)(gclass_name, [
10129
+ ["EV_LANGUAGE_CHANGED", 0],
10006
10130
  ["EV_EDIT_MAP", 0],
10007
10131
  ["EV_CONTROL_MAP", 0],
10008
10132
  ["EV_MAP_ON_LOAD", 0],
@@ -10011,6 +10135,11 @@ function create_gclass$15(gclass_name) {
10011
10135
  ["EV_SHOW", 0],
10012
10136
  ["EV_HIDE", 0]
10013
10137
  ], [["ST_IDLE", [
10138
+ [
10139
+ "EV_LANGUAGE_CHANGED",
10140
+ ac_language_changed$9,
10141
+ null
10142
+ ],
10014
10143
  [
10015
10144
  "EV_EDIT_MAP",
10016
10145
  ac_edit_map,
@@ -937,7 +937,7 @@ function mt_create$21(gobj) {
937
937
  /***************************************************************
938
938
  * Framework Method: Start
939
939
  ***************************************************************/
940
- function mt_start$18(gobj) {
940
+ function mt_start$19(gobj) {
941
941
  let config = gobj_read_attr(gobj, "config") || {};
942
942
  let priv = gobj.priv;
943
943
  if (!validate_config(config)) {
@@ -1006,7 +1006,7 @@ function mt_start$18(gobj) {
1006
1006
  /***************************************************************
1007
1007
  * Framework Method: Stop
1008
1008
  ***************************************************************/
1009
- function mt_stop$18(gobj) {
1009
+ function mt_stop$19(gobj) {
1010
1010
  let priv = gobj.priv;
1011
1011
  if (!priv) return 0;
1012
1012
  close_toolbar_dropdown(gobj);
@@ -2551,8 +2551,8 @@ function ac_nav_item_close(gobj, event, kw, src) {
2551
2551
  ***************************************************************/
2552
2552
  var gmt$21 = {
2553
2553
  mt_create: mt_create$21,
2554
- mt_start: mt_start$18,
2555
- mt_stop: mt_stop$18,
2554
+ mt_start: mt_start$19,
2555
+ mt_stop: mt_stop$19,
2556
2556
  mt_destroy: mt_destroy$21
2557
2557
  };
2558
2558
  function create_gclass$21(gclass_name) {
@@ -4892,11 +4892,11 @@ function mt_create$18(gobj) {
4892
4892
  /***************************************************************
4893
4893
  * Framework Method: Start
4894
4894
  ***************************************************************/
4895
- function mt_start$17(gobj) {}
4895
+ function mt_start$18(gobj) {}
4896
4896
  /***************************************************************
4897
4897
  * Framework Method: Stop
4898
4898
  ***************************************************************/
4899
- function mt_stop$17(gobj) {
4899
+ function mt_stop$18(gobj) {
4900
4900
  gobj_stop_children(gobj);
4901
4901
  }
4902
4902
  /***************************************************************
@@ -5183,8 +5183,8 @@ function ac_resize$5(gobj, event, kw, src) {
5183
5183
  ***************************/
5184
5184
  var gmt$18 = {
5185
5185
  mt_create: mt_create$18,
5186
- mt_start: mt_start$17,
5187
- mt_stop: mt_stop$17,
5186
+ mt_start: mt_start$18,
5187
+ mt_stop: mt_stop$18,
5188
5188
  mt_destroy: mt_destroy$18
5189
5189
  };
5190
5190
  /***************************************************************
@@ -5426,11 +5426,11 @@ function mt_create$17(gobj) {
5426
5426
  /***************************************************************
5427
5427
  * Framework Method: Start
5428
5428
  ***************************************************************/
5429
- function mt_start$16(gobj) {}
5429
+ function mt_start$17(gobj) {}
5430
5430
  /***************************************************************
5431
5431
  * Framework Method: Stop
5432
5432
  ***************************************************************/
5433
- function mt_stop$16(gobj) {
5433
+ function mt_stop$17(gobj) {
5434
5434
  gobj_stop_children(gobj);
5435
5435
  }
5436
5436
  /***************************************************************
@@ -5790,8 +5790,8 @@ function ac_resize$4(gobj, event, kw, src) {
5790
5790
  ***************************/
5791
5791
  var gmt$17 = {
5792
5792
  mt_create: mt_create$17,
5793
- mt_start: mt_start$16,
5794
- mt_stop: mt_stop$16,
5793
+ mt_start: mt_start$17,
5794
+ mt_stop: mt_stop$17,
5795
5795
  mt_destroy: mt_destroy$17
5796
5796
  };
5797
5797
  /***************************************************************
@@ -6917,14 +6917,14 @@ function mt_destroy$16(gobj) {
6917
6917
  /************************************************************
6918
6918
  * Framework Method start
6919
6919
  ************************************************************/
6920
- function mt_start$15(gobj) {
6920
+ function mt_start$16(gobj) {
6921
6921
  let record = gobj_read_attr(gobj, "record");
6922
6922
  if (record) gobj_send_event(gobj, "EV_LOAD_RECORD", record, gobj);
6923
6923
  }
6924
6924
  /************************************************************
6925
6925
  * Framework Method stop
6926
6926
  ************************************************************/
6927
- function mt_stop$15(gobj) {}
6927
+ function mt_stop$16(gobj) {}
6928
6928
  /***************************
6929
6929
  * Local Methods
6930
6930
  ***************************/
@@ -9149,8 +9149,8 @@ function cmd_get_picked_files(gobj, cmd, kw, src) {
9149
9149
  }
9150
9150
  var gmt$16 = {
9151
9151
  mt_create: mt_create$16,
9152
- mt_start: mt_start$15,
9153
- mt_stop: mt_stop$15,
9152
+ mt_start: mt_start$16,
9153
+ mt_stop: mt_stop$16,
9154
9154
  mt_destroy: mt_destroy$16,
9155
9155
  mt_command_parser: mt_command_parser$2
9156
9156
  };
@@ -9412,6 +9412,78 @@ var MarkerControl = class {
9412
9412
  gobj_send_event(this.gobj, "EV_CONTROL_MAP", { user_location: this._enable_user_location }, this.gobj);
9413
9413
  }
9414
9414
  };
9415
+ /***********************************************************************
9416
+ * MAPLIBRE'S OWN CHROME, IN THE APP'S LANGUAGE
9417
+ *
9418
+ * Everything maplibre draws with words -- the zoom tooltips, the
9419
+ * geolocate button, the attribution toggle, a popup's close, and the
9420
+ * notice that teaches the Ctrl + wheel gesture -- comes from its
9421
+ * `locale`, an option merged over its own English defaults at
9422
+ * construction. So a map in a Spanish app was saying *"Zoom in"* and
9423
+ * *"Use Ctrl + scroll to zoom the map"*, which is the same rule this
9424
+ * GUI applies to every other string.
9425
+ *
9426
+ * Two halves, because maplibre reads its strings ONCE, when each
9427
+ * control builds its DOM:
9428
+ *
9429
+ * `yui_maplibre_locale(t)` the `locale` option, for the map's
9430
+ * first paint;
9431
+ * `yui_maplibre_relocalize()` after a language change, which is
9432
+ * the half a `locale` alone cannot
9433
+ * do -- it writes the strings into
9434
+ * the DOM already drawn, and updates
9435
+ * the map's locale so anything built
9436
+ * later is right too.
9437
+ *
9438
+ * The scale units (`km`, `mi`, `nm`) are symbols and are left alone;
9439
+ * the MapLibre logo keeps its name, which is a brand.
9440
+ ***********************************************************************/
9441
+ function yui_maplibre_locale(t) {
9442
+ return {
9443
+ "NavigationControl.ZoomIn": t("zoom in"),
9444
+ "NavigationControl.ZoomOut": t("zoom out"),
9445
+ "NavigationControl.ResetBearing": t("drag to rotate the map, click to reset north"),
9446
+ "GeolocateControl.FindMyLocation": t("find my location"),
9447
+ "GeolocateControl.LocationNotAvailable": t("location not available"),
9448
+ "AttributionControl.ToggleAttribution": t("toggle attribution"),
9449
+ "AttributionControl.MapFeedback": t("map feedback"),
9450
+ "FullscreenControl.Enter": t("enter fullscreen"),
9451
+ "FullscreenControl.Exit": t("exit fullscreen"),
9452
+ "Popup.Close": t("close popup"),
9453
+ "Map.Title": t("map"),
9454
+ "Marker.Title": t("map marker"),
9455
+ "CooperativeGesturesHandler.WindowsHelpText": t("use ctrl + scroll to zoom the map"),
9456
+ "CooperativeGesturesHandler.MacHelpText": t("use cmd + scroll to zoom the map"),
9457
+ "CooperativeGesturesHandler.MobileHelpText": t("use two fingers to move the map")
9458
+ };
9459
+ }
9460
+ function label_ctrl($root, selector, text) {
9461
+ if (!$root || !text) return;
9462
+ for (const $el of $root.querySelectorAll(selector)) {
9463
+ $el.setAttribute("title", text);
9464
+ $el.setAttribute("aria-label", text);
9465
+ }
9466
+ }
9467
+ function yui_maplibre_relocalize(map, t) {
9468
+ if (!map || typeof map.getContainer !== "function") return;
9469
+ const strings = yui_maplibre_locale(t);
9470
+ try {
9471
+ map._locale = Object.assign({}, map._locale, strings);
9472
+ } catch (e) {}
9473
+ const $c = map.getContainer();
9474
+ label_ctrl($c, ".maplibregl-ctrl-zoom-in", strings["NavigationControl.ZoomIn"]);
9475
+ label_ctrl($c, ".maplibregl-ctrl-zoom-out", strings["NavigationControl.ZoomOut"]);
9476
+ label_ctrl($c, ".maplibregl-ctrl-compass", strings["NavigationControl.ResetBearing"]);
9477
+ label_ctrl($c, ".maplibregl-ctrl-geolocate", strings["GeolocateControl.FindMyLocation"]);
9478
+ label_ctrl($c, ".maplibregl-ctrl-attrib-button", strings["AttributionControl.ToggleAttribution"]);
9479
+ label_ctrl($c, ".maplibregl-ctrl-fullscreen", strings["FullscreenControl.Enter"]);
9480
+ label_ctrl($c, ".maplibregl-popup-close-button", strings["Popup.Close"]);
9481
+ const mac = typeof navigator !== "undefined" && (navigator.userAgent || "").includes("Mac");
9482
+ const $desktop = $c.querySelector(".maplibregl-desktop-message");
9483
+ if ($desktop) $desktop.textContent = mac ? strings["CooperativeGesturesHandler.MacHelpText"] : strings["CooperativeGesturesHandler.WindowsHelpText"];
9484
+ const $mobile = $c.querySelector(".maplibregl-mobile-message");
9485
+ if ($mobile) $mobile.textContent = strings["CooperativeGesturesHandler.MobileHelpText"];
9486
+ }
9415
9487
  //#endregion
9416
9488
  //#region src/c_yui_map.js
9417
9489
  /***********************************************************************
@@ -9426,6 +9498,7 @@ var MarkerControl = class {
9426
9498
  * Constants
9427
9499
  ***************************************************************/
9428
9500
  var GCLASS_NAME$15 = "C_YUI_MAP";
9501
+ var GESTURE_HINT_MS = 2e3;
9429
9502
  /***************************************************************
9430
9503
  * Data
9431
9504
  ***************************************************************/
@@ -9452,6 +9525,7 @@ var attrs_table$15 = [
9452
9525
  ];
9453
9526
  var PRIVATE_DATA$15 = {
9454
9527
  xmap: null,
9528
+ gesture_hint_timer: null,
9455
9529
  geojson: null,
9456
9530
  resizeObserver: null,
9457
9531
  width: 0,
@@ -9476,7 +9550,8 @@ function mt_create$15(gobj) {
9476
9550
  if ($map) $map.classList.add(GCLASS_NAME$15);
9477
9551
  Object.assign(map_settings, {
9478
9552
  container: $map,
9479
- cooperativeGestures: true
9553
+ cooperativeGestures: true,
9554
+ locale: yui_maplibre_locale(t)
9480
9555
  });
9481
9556
  priv.onClick = (ev) => {
9482
9557
  onClick(gobj, ev);
@@ -9494,6 +9569,16 @@ function mt_create$15(gobj) {
9494
9569
  xtouchStart(gobj, ev);
9495
9570
  };
9496
9571
  const map = priv.xmap = new maplibregl.Map(map_settings);
9572
+ map.on("cooperativegestureprevented", () => {
9573
+ const $s = map.getCanvasContainer().querySelector(".maplibregl-cooperative-gesture-screen");
9574
+ if (!$s) return;
9575
+ $s.classList.add("MAP_GESTURE_SHOWN");
9576
+ if (priv.gesture_hint_timer) clearTimeout(priv.gesture_hint_timer);
9577
+ priv.gesture_hint_timer = setTimeout(() => {
9578
+ priv.gesture_hint_timer = null;
9579
+ $s.classList.remove("MAP_GESTURE_SHOWN");
9580
+ }, GESTURE_HINT_MS);
9581
+ });
9497
9582
  map.addControl(new maplibregl.NavigationControl());
9498
9583
  map.addControl(new MarkerControl(gobj, {}), "top-right");
9499
9584
  map.addControl(new EditControl(gobj, { showMarkerDrag: true }), "top-right");
@@ -9523,10 +9608,46 @@ function mt_create$15(gobj) {
9523
9608
  }
9524
9609
  }
9525
9610
  /***************************************************************
9611
+ * The application changed language: maplibre's own words are
9612
+ * rewritten in place, and the map's locale with them so a
9613
+ * control or a popup built later is right too.
9614
+ ***************************************************************/
9615
+ function ac_language_changed$9(gobj, event, kw, src) {
9616
+ let priv = gobj.priv;
9617
+ if (priv.xmap) yui_maplibre_relocalize(priv.xmap, t);
9618
+ return 0;
9619
+ }
9620
+ /***************************************************************
9621
+ * Framework Method: Start
9622
+ *
9623
+ * The application's LANGUAGE: what maplibre draws with words is
9624
+ * built from its `locale` when each control builds its DOM, so
9625
+ * `refresh_language()` -- which reaches what carries an i18n key
9626
+ * in OUR dom -- cannot touch any of it. The shell says when the
9627
+ * language changed and this view rewrites those strings.
9628
+ ***************************************************************/
9629
+ function mt_start$15(gobj) {
9630
+ let shell = yui_shell_of(gobj);
9631
+ if (shell) gobj_subscribe_event(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
9632
+ return 0;
9633
+ }
9634
+ /***************************************************************
9635
+ * Framework Method: Stop
9636
+ ***************************************************************/
9637
+ function mt_stop$15(gobj) {
9638
+ let shell = yui_shell_of(gobj);
9639
+ if (shell) gobj_unsubscribe_event(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
9640
+ return 0;
9641
+ }
9642
+ /***************************************************************
9526
9643
  * Framework Method: Destroy
9527
9644
  ***************************************************************/
9528
9645
  function mt_destroy$15(gobj) {
9529
9646
  let priv = gobj.priv;
9647
+ if (priv.gesture_hint_timer) {
9648
+ clearTimeout(priv.gesture_hint_timer);
9649
+ priv.gesture_hint_timer = null;
9650
+ }
9530
9651
  if (priv.resizeObserver) {
9531
9652
  priv.resizeObserver.disconnect();
9532
9653
  priv.resizeObserver = null;
@@ -9987,6 +10108,8 @@ function ac_hide$10(gobj, event, kw, src) {
9987
10108
  ***************************/
9988
10109
  var gmt$15 = {
9989
10110
  mt_create: mt_create$15,
10111
+ mt_start: mt_start$15,
10112
+ mt_stop: mt_stop$15,
9990
10113
  mt_destroy: mt_destroy$15
9991
10114
  };
9992
10115
  /***************************************************************
@@ -9998,6 +10121,7 @@ function create_gclass$15(gclass_name) {
9998
10121
  return -1;
9999
10122
  }
10000
10123
  __gclass__$15 = gclass_create(gclass_name, [
10124
+ ["EV_LANGUAGE_CHANGED", 0],
10001
10125
  ["EV_EDIT_MAP", 0],
10002
10126
  ["EV_CONTROL_MAP", 0],
10003
10127
  ["EV_MAP_ON_LOAD", 0],
@@ -10006,6 +10130,11 @@ function create_gclass$15(gclass_name) {
10006
10130
  ["EV_SHOW", 0],
10007
10131
  ["EV_HIDE", 0]
10008
10132
  ], [["ST_IDLE", [
10133
+ [
10134
+ "EV_LANGUAGE_CHANGED",
10135
+ ac_language_changed$9,
10136
+ null
10137
+ ],
10009
10138
  [
10010
10139
  "EV_EDIT_MAP",
10011
10140
  ac_edit_map,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuneta/gobj-ui",
3
- "version": "7.23.110",
3
+ "version": "7.23.111",
4
4
  "type": "module",
5
5
  "main": "dist/gobj-ui.cjs.js",
6
6
  "module": "dist/gobj-ui.es.js",
package/src/c_yui_map.css CHANGED
@@ -33,3 +33,29 @@
33
33
  .xmap .column {
34
34
  padding: 0 !important;
35
35
  }
36
+
37
+ /*
38
+ * The cooperative-gesture notice: "Use Ctrl + scroll to zoom the map".
39
+ *
40
+ * maplibre's own sheet shows it for 100ms and lets it FADE for a second
41
+ * more (`transition: opacity 1s ease 1s`). Nothing here has transitions,
42
+ * so that fade is cut -- and with it the only thing that made the notice
43
+ * readable, since 100ms is not reading time. `c_yui_map.js` holds it by
44
+ * the clock instead: it appears and disappears at once, and stands still
45
+ * in between.
46
+ */
47
+ .maplibregl-cooperative-gesture-screen,
48
+ .maplibregl-cooperative-gesture-screen.maplibregl-show {
49
+ transition: none !important;
50
+ }
51
+
52
+ .maplibregl-cooperative-gesture-screen.MAP_GESTURE_SHOWN {
53
+ opacity: 1;
54
+ }
55
+
56
+ /* 1.4em leaves the notice in four lines on the small map of a card. It
57
+ * is an instruction, not a headline. */
58
+ .maplibregl-cooperative-gesture-screen {
59
+ font-size: 1rem;
60
+ text-align: center;
61
+ }
package/src/c_yui_map.js CHANGED
@@ -29,6 +29,7 @@ import {
29
29
  gobj_create_service,
30
30
  gobj_start,
31
31
  gobj_name,
32
+ gobj_unsubscribe_event,
32
33
  } from "@yuneta/gobj-js";
33
34
 
34
35
  import "maplibre-gl/dist/maplibre-gl.css"; // Import MapLibre styles
@@ -36,9 +37,15 @@ import * as maplibregl from "maplibre-gl"; // MapLibre GL JS 6 is ESM-only, no d
36
37
 
37
38
  import {
38
39
  EditControl,
39
- MarkerControl
40
+ MarkerControl,
41
+ yui_maplibre_locale,
42
+ yui_maplibre_relocalize
40
43
  } from "./lib_maplibre.js";
41
44
 
45
+ import {t} from "i18next";
46
+
47
+ import {yui_shell_of} from "./c_yui_shell.js";
48
+
42
49
  import "./c_yui_map.css"; // Must be in index.js ?
43
50
 
44
51
  /***************************************************************
@@ -46,6 +53,9 @@ import "./c_yui_map.css"; // Must be in index.js ?
46
53
  ***************************************************************/
47
54
  const GCLASS_NAME = "C_YUI_MAP";
48
55
 
56
+ /* How long the cooperative-gesture notice stays up, in ms. */
57
+ const GESTURE_HINT_MS = 2000;
58
+
49
59
  /***************************************************************
50
60
  * Data
51
61
  ***************************************************************/
@@ -74,6 +84,7 @@ SDATA_END()
74
84
 
75
85
  let PRIVATE_DATA = {
76
86
  xmap: null,
87
+ gesture_hint_timer: null, /* keeps the gesture notice up long enough */
77
88
  geojson: null,
78
89
  resizeObserver: null,
79
90
  width: 0, // map size, data got from resize observer
@@ -132,6 +143,13 @@ function mt_create(gobj)
132
143
  * default is a suggestion -- the demo passes `map_settings` and
133
144
  * never saw it. This is the house gesture, not a suggestion. */
134
145
  cooperativeGestures: true,
146
+ /* maplibre draws words of its own -- the zoom tooltips, the
147
+ * geolocate button, the attribution toggle and the notice that
148
+ * teaches the gesture above -- and they came out in ITS
149
+ * English inside a Spanish app. `locale` is read once, when
150
+ * each control builds its DOM, so the language CHANGE is the
151
+ * other half, in ac_language_changed. */
152
+ locale: yui_maplibre_locale(t),
135
153
  });
136
154
 
137
155
  /*-----------------------------*
@@ -158,6 +176,35 @@ function mt_create(gobj)
158
176
  *-----------------------------*/
159
177
  const map = priv.xmap = new maplibregl.Map(map_settings);
160
178
 
179
+ /* HOW LONG THE NOTICE STAYS UP.
180
+ *
181
+ * maplibre shows it for 100ms and lets it FADE for a second more
182
+ * (`transition: opacity 1s ease 1s`). Nothing in this GUI has
183
+ * transitions, so that fade is cut -- and with it the only thing
184
+ * that made the notice readable, because 100ms is not reading
185
+ * time. It is held by the clock instead: on and off at once, and
186
+ * still in between for as long as it takes to read it.
187
+ *
188
+ * In maplibre's callback and not through the machine, for the same
189
+ * reason as the zoom readout: it is not an action, it is the map
190
+ * acknowledging a gesture it refused, and one wheel fires it
191
+ * dozens of times. */
192
+ map.on("cooperativegestureprevented", () => {
193
+ const $s = map.getCanvasContainer()
194
+ .querySelector(".maplibregl-cooperative-gesture-screen");
195
+ if(!$s) {
196
+ return;
197
+ }
198
+ $s.classList.add("MAP_GESTURE_SHOWN");
199
+ if(priv.gesture_hint_timer) {
200
+ clearTimeout(priv.gesture_hint_timer);
201
+ }
202
+ priv.gesture_hint_timer = setTimeout(() => {
203
+ priv.gesture_hint_timer = null;
204
+ $s.classList.remove("MAP_GESTURE_SHOWN");
205
+ }, GESTURE_HINT_MS);
206
+ });
207
+
161
208
  /*-----------------------------*
162
209
  * Controls
163
210
  *-----------------------------*/
@@ -219,6 +266,51 @@ function mt_create(gobj)
219
266
  }
220
267
  }
221
268
 
269
+ /***************************************************************
270
+ * The application changed language: maplibre's own words are
271
+ * rewritten in place, and the map's locale with them so a
272
+ * control or a popup built later is right too.
273
+ ***************************************************************/
274
+ function ac_language_changed(gobj, event, kw, src)
275
+ {
276
+ let priv = gobj.priv;
277
+
278
+ if(priv.xmap) {
279
+ yui_maplibre_relocalize(priv.xmap, t);
280
+ }
281
+ return 0;
282
+ }
283
+
284
+ /***************************************************************
285
+ * Framework Method: Start
286
+ *
287
+ * The application's LANGUAGE: what maplibre draws with words is
288
+ * built from its `locale` when each control builds its DOM, so
289
+ * `refresh_language()` -- which reaches what carries an i18n key
290
+ * in OUR dom -- cannot touch any of it. The shell says when the
291
+ * language changed and this view rewrites those strings.
292
+ ***************************************************************/
293
+ function mt_start(gobj)
294
+ {
295
+ let shell = yui_shell_of(gobj);
296
+ if(shell) {
297
+ gobj_subscribe_event(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
298
+ }
299
+ return 0;
300
+ }
301
+
302
+ /***************************************************************
303
+ * Framework Method: Stop
304
+ ***************************************************************/
305
+ function mt_stop(gobj)
306
+ {
307
+ let shell = yui_shell_of(gobj);
308
+ if(shell) {
309
+ gobj_unsubscribe_event(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
310
+ }
311
+ return 0;
312
+ }
313
+
222
314
  /***************************************************************
223
315
  * Framework Method: Destroy
224
316
  ***************************************************************/
@@ -226,6 +318,10 @@ function mt_destroy(gobj)
226
318
  {
227
319
  let priv = gobj.priv;
228
320
 
321
+ if(priv.gesture_hint_timer) {
322
+ clearTimeout(priv.gesture_hint_timer);
323
+ priv.gesture_hint_timer = null;
324
+ }
229
325
  if(priv.resizeObserver) {
230
326
  priv.resizeObserver.disconnect();
231
327
  priv.resizeObserver = null;
@@ -934,6 +1030,8 @@ function ac_hide(gobj, event, kw, src)
934
1030
  *---------------------------------------------*/
935
1031
  const gmt = {
936
1032
  mt_create: mt_create,
1033
+ mt_start: mt_start,
1034
+ mt_stop: mt_stop,
937
1035
  mt_destroy: mt_destroy
938
1036
  };
939
1037
 
@@ -952,6 +1050,7 @@ function create_gclass(gclass_name)
952
1050
  *---------------------------------------------*/
953
1051
  const states = [
954
1052
  ["ST_IDLE", [
1053
+ ["EV_LANGUAGE_CHANGED", ac_language_changed, null],
955
1054
  ["EV_EDIT_MAP", ac_edit_map, null],
956
1055
  ["EV_CONTROL_MAP", ac_control_map, null],
957
1056
  ["EV_MAP_ON_LOAD", ac_map_on_load, null],
@@ -966,6 +1065,7 @@ function create_gclass(gclass_name)
966
1065
  * Events
967
1066
  *---------------------------------------------*/
968
1067
  const event_types = [
1068
+ ["EV_LANGUAGE_CHANGED", 0],
969
1069
  ["EV_EDIT_MAP", 0],
970
1070
  ["EV_CONTROL_MAP", 0],
971
1071
  ["EV_MAP_ON_LOAD", 0],
@@ -215,10 +215,116 @@ class MarkerControl {
215
215
  }
216
216
  }
217
217
 
218
+
219
+ /***********************************************************************
220
+ * MAPLIBRE'S OWN CHROME, IN THE APP'S LANGUAGE
221
+ *
222
+ * Everything maplibre draws with words -- the zoom tooltips, the
223
+ * geolocate button, the attribution toggle, a popup's close, and the
224
+ * notice that teaches the Ctrl + wheel gesture -- comes from its
225
+ * `locale`, an option merged over its own English defaults at
226
+ * construction. So a map in a Spanish app was saying *"Zoom in"* and
227
+ * *"Use Ctrl + scroll to zoom the map"*, which is the same rule this
228
+ * GUI applies to every other string.
229
+ *
230
+ * Two halves, because maplibre reads its strings ONCE, when each
231
+ * control builds its DOM:
232
+ *
233
+ * `yui_maplibre_locale(t)` the `locale` option, for the map's
234
+ * first paint;
235
+ * `yui_maplibre_relocalize()` after a language change, which is
236
+ * the half a `locale` alone cannot
237
+ * do -- it writes the strings into
238
+ * the DOM already drawn, and updates
239
+ * the map's locale so anything built
240
+ * later is right too.
241
+ *
242
+ * The scale units (`km`, `mi`, `nm`) are symbols and are left alone;
243
+ * the MapLibre logo keeps its name, which is a brand.
244
+ ***********************************************************************/
245
+ function yui_maplibre_locale(t)
246
+ {
247
+ return {
248
+ "NavigationControl.ZoomIn": t("zoom in"),
249
+ "NavigationControl.ZoomOut": t("zoom out"),
250
+ "NavigationControl.ResetBearing": t("drag to rotate the map, click to reset north"),
251
+ "GeolocateControl.FindMyLocation": t("find my location"),
252
+ "GeolocateControl.LocationNotAvailable": t("location not available"),
253
+ "AttributionControl.ToggleAttribution": t("toggle attribution"),
254
+ "AttributionControl.MapFeedback": t("map feedback"),
255
+ "FullscreenControl.Enter": t("enter fullscreen"),
256
+ "FullscreenControl.Exit": t("exit fullscreen"),
257
+ "Popup.Close": t("close popup"),
258
+ "Map.Title": t("map"),
259
+ "Marker.Title": t("map marker"),
260
+ "CooperativeGesturesHandler.WindowsHelpText": t("use ctrl + scroll to zoom the map"),
261
+ "CooperativeGesturesHandler.MacHelpText": t("use cmd + scroll to zoom the map"),
262
+ "CooperativeGesturesHandler.MobileHelpText": t("use two fingers to move the map"),
263
+ };
264
+ }
265
+
266
+ /* One drawn control: its tooltip and its aria-label say the same
267
+ * thing, and a screen reader needs the second even when the first is
268
+ * what a pointer finds. */
269
+ function label_ctrl($root, selector, text)
270
+ {
271
+ if(!$root || !text) {
272
+ return;
273
+ }
274
+ for(const $el of $root.querySelectorAll(selector)) {
275
+ $el.setAttribute("title", text);
276
+ $el.setAttribute("aria-label", text);
277
+ }
278
+ }
279
+
280
+ function yui_maplibre_relocalize(map, t)
281
+ {
282
+ if(!map || typeof map.getContainer !== "function") {
283
+ return;
284
+ }
285
+ const strings = yui_maplibre_locale(t);
286
+
287
+ /* The map's own table first: a control added later (or a popup
288
+ * opened later) reads it when it builds itself. */
289
+ try {
290
+ map._locale = Object.assign({}, map._locale, strings);
291
+ } catch(e) {
292
+ /* a maplibre that keeps its locale elsewhere: the DOM below
293
+ * still gets translated, which is what is on screen */
294
+ }
295
+
296
+ const $c = map.getContainer();
297
+ label_ctrl($c, ".maplibregl-ctrl-zoom-in", strings["NavigationControl.ZoomIn"]);
298
+ label_ctrl($c, ".maplibregl-ctrl-zoom-out", strings["NavigationControl.ZoomOut"]);
299
+ label_ctrl($c, ".maplibregl-ctrl-compass", strings["NavigationControl.ResetBearing"]);
300
+ label_ctrl($c, ".maplibregl-ctrl-geolocate", strings["GeolocateControl.FindMyLocation"]);
301
+ label_ctrl($c, ".maplibregl-ctrl-attrib-button", strings["AttributionControl.ToggleAttribution"]);
302
+ label_ctrl($c, ".maplibregl-ctrl-fullscreen", strings["FullscreenControl.Enter"]);
303
+ label_ctrl($c, ".maplibregl-popup-close-button", strings["Popup.Close"]);
304
+
305
+ /* The notice of the cooperative gesture: two lines, one for a
306
+ * pointer and one for a finger, built by `_setupUI()` as
307
+ * `.maplibregl-desktop-message` / `.maplibregl-mobile-message`. */
308
+ const mac = (typeof navigator !== "undefined" &&
309
+ (navigator.userAgent || "").includes("Mac"));
310
+ const $desktop = $c.querySelector(".maplibregl-desktop-message");
311
+ if($desktop) {
312
+ $desktop.textContent = mac
313
+ ? strings["CooperativeGesturesHandler.MacHelpText"]
314
+ : strings["CooperativeGesturesHandler.WindowsHelpText"];
315
+ }
316
+ const $mobile = $c.querySelector(".maplibregl-mobile-message");
317
+ if($mobile) {
318
+ $mobile.textContent = strings["CooperativeGesturesHandler.MobileHelpText"];
319
+ }
320
+ }
321
+
218
322
  //=======================================================================
219
323
  // Expose the class via the global object
220
324
  //=======================================================================
221
325
  export {
222
326
  EditControl,
223
- MarkerControl
327
+ MarkerControl,
328
+ yui_maplibre_locale,
329
+ yui_maplibre_relocalize
224
330
  };