@geogirafe/lib-geoportal 1.2.0-dev.2870319621 → 1.2.0-dev.2873796427

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.
Files changed (54) hide show
  1. package/base/GirafeDraggableElement.js +2 -2
  2. package/base/GirafeResizableElement.js +4 -4
  3. package/components/basemap/component.js +1 -1
  4. package/components/cross-section/cross-section-settings/component.js +1 -1
  5. package/components/cross-section/scatterplot.js +1 -1
  6. package/components/drawing/component-mobile.js +5 -1
  7. package/components/drawing/component.js +8 -4
  8. package/components/drawing/fixed-dimension/component.js +1 -1
  9. package/components/edit/component.js +1 -1
  10. package/components/edit/editform/component.js +1 -1
  11. package/components/extlayers/component.js +1 -1
  12. package/components/map-2d/component.js +1 -1
  13. package/components/map-2d/tools/swipemanager.js +2 -2
  14. package/components/modals/component.js +1 -1
  15. package/components/print/component.js +7 -7
  16. package/components/print/tools/MFPLegendEncoder.js +1 -1
  17. package/components/querybuilder/component.js +2 -2
  18. package/components/scale/component.js +1 -1
  19. package/components/search/component.js +5 -1
  20. package/components/search-mobile/component.js +5 -1
  21. package/components/selectionwindow/component.js +1 -1
  22. package/components/share/component.js +1 -1
  23. package/components/themes/component.js +6 -1
  24. package/components/themes-mobile/layer-selected/component.js +1 -1
  25. package/components/timerestriction/timepicker/component.js +1 -1
  26. package/components/timerestriction/timeslider/component.js +4 -4
  27. package/components/treeview/tools/treeviewelement.d.ts +1 -2
  28. package/components/treeview/tools/treeviewelement.js +12 -12
  29. package/components/treeview/tools/treeviewfilter.js +3 -3
  30. package/components/treeview/tools/treeviewgroupelement.d.ts +2 -1
  31. package/components/treeview/tools/treeviewgroupelement.js +11 -2
  32. package/components/treeview/treeviewgroup/component.js +18 -19
  33. package/components/treeview/treeviewitem/component.d.ts +1 -1
  34. package/components/treeview/treeviewitem/component.js +27 -29
  35. package/components/treeview/treeviewroot/component.d.ts +2 -1
  36. package/components/treeview/treeviewroot/component.js +25 -4
  37. package/components/treeview/treeviewtheme/component.js +20 -16
  38. package/components/userpreferences/component.js +5 -1
  39. package/models/layers/grouplayer.js +1 -1
  40. package/models/layers/themelayer.js +1 -1
  41. package/models/xmlTypes.js +1 -1
  42. package/package.json +1 -1
  43. package/templates/iframe.html +4 -38
  44. package/templates/index.html +4 -38
  45. package/templates/public/about.json +1 -1
  46. package/templates/vite.config.js +1 -4
  47. package/tools/ordering/orderingmanager.d.ts +1 -0
  48. package/tools/ordering/orderingmanager.js +35 -8
  49. package/tools/resizewindow.js +6 -6
  50. package/tools/share/serializers/globeserializer.d.ts +4 -1
  51. package/tools/share/serializers/globeserializer.js +4 -1
  52. package/tools/state/brain/brain.d.ts +1 -0
  53. package/tools/state/brain/brain.js +30 -19
  54. package/tools/time/layertimeformatter.js +1 -1
@@ -15,12 +15,16 @@ export default class UserPreferencesComponent extends GirafeHTMLElement {
15
15
  styleUrls = null;
16
16
  template = () => {
17
17
  return uHtml `<style>
18
+ .picker_wrapper.no_alpha .picker_alpha{display:none}.picker_wrapper.no_editor .picker_editor{z-index:-1;opacity:0;position:absolute}.picker_wrapper.no_cancel .picker_cancel{display:none}.layout_default.picker_wrapper{flex-flow:wrap;justify-content:space-between;align-items:stretch;width:25em;padding:.5em;font-size:10px;display:flex}.layout_default.picker_wrapper input,.layout_default.picker_wrapper button{font-size:1rem}.layout_default.picker_wrapper>*{margin:.5em}.layout_default.picker_wrapper:before{content:"";order:1;width:100%;height:0;display:block}.layout_default .picker_slider,.layout_default .picker_selector{padding:1em}.layout_default .picker_hue{width:100%}.layout_default .picker_sl{flex:auto}.layout_default .picker_sl:before{content:"";padding-bottom:100%;display:block}.layout_default .picker_editor{order:1;width:6.5rem}.layout_default .picker_editor input{width:100%;height:100%}.layout_default .picker_sample{flex:auto;order:1}.layout_default .picker_done,.layout_default .picker_cancel{order:1}.picker_wrapper{box-sizing:border-box;cursor:default;color:#444;pointer-events:auto;background:#f2f2f2;font-family:sans-serif;box-shadow:0 0 0 1px silver}.picker_wrapper:focus{outline:none}.picker_wrapper button,.picker_wrapper input{box-sizing:border-box;border:none;outline:none;box-shadow:0 0 0 1px silver}.picker_wrapper button:focus,.picker_wrapper button:active,.picker_wrapper input:focus,.picker_wrapper input:active{box-shadow:0 0 2px 1px #1e90ff}.picker_wrapper button{cursor:pointer;background-color:#f5f5f5;background-image:linear-gradient(#0000,#dcdcdc);padding:.4em .6em}.picker_wrapper button:active{background-image:linear-gradient(#dcdcdc,#0000)}.picker_wrapper button:hover{background-color:#fff}.picker_selector{z-index:1;cursor:pointer;background:currentColor;border:2px solid #fff;border-radius:100%;display:block;position:absolute;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);box-shadow:0 0 3px 1px #67b9ff}.picker_slider .picker_selector{border-radius:2px}.picker_hue{background-image:linear-gradient(90deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red);position:relative;box-shadow:0 0 0 1px silver}.picker_sl{background-image:linear-gradient(#fff,#fff0 50%),linear-gradient(#0000 50%,#000),linear-gradient(90deg,gray,#80808000);position:relative;box-shadow:0 0 0 1px silver}.picker_alpha,.picker_sample{background:linear-gradient(45deg,#d3d3d3 25%,#0000 25% 75%,#d3d3d3 75%) 0 0/2em 2em,linear-gradient(45deg,#d3d3d3 25%,#fff 25% 75%,#d3d3d3 75%) 1em 1em/2em 2em;position:relative;box-shadow:0 0 0 1px silver}.picker_alpha .picker_selector,.picker_sample .picker_selector{background:0 0}.picker_editor input{padding:.2em .4em;font-family:monospace}.picker_sample:before{content:"";background:currentColor;width:100%;height:100%;display:block;position:absolute}.picker_arrow{z-index:-1;position:absolute}.picker_wrapper.popup{z-index:2;margin:1.5em;position:absolute}.picker_wrapper.popup,.picker_wrapper.popup .picker_arrow:before,.picker_wrapper.popup .picker_arrow:after{background:#f2f2f2;box-shadow:0 0 10px 1px #0006}.picker_wrapper.popup .picker_arrow{width:3em;height:3em;margin:0}.picker_wrapper.popup .picker_arrow:before,.picker_wrapper.popup .picker_arrow:after{content:"";z-index:-99;display:block;position:absolute;top:0;left:0}.picker_wrapper.popup .picker_arrow:before{-webkit-transform-origin:0 100%;transform-origin:0 100%;width:100%;height:100%;-webkit-transform:skew(45deg);transform:skew(45deg)}.picker_wrapper.popup .picker_arrow:after{width:150%;height:150%;box-shadow:none}.popup.popup_top{bottom:100%;left:0}.popup.popup_top .picker_arrow{bottom:0;left:0;-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.popup.popup_bottom{top:100%;left:0}.popup.popup_bottom .picker_arrow{top:0;left:0;-webkit-transform:rotate(90deg)scaleY(-1);transform:rotate(90deg)scaleY(-1)}.popup.popup_left{top:0;right:100%}.popup.popup_left .picker_arrow{top:0;right:0;-webkit-transform:scaleX(-1);transform:scaleX(-1)}.popup.popup_right{top:0;left:100%}.popup.popup_right .picker_arrow{top:0;left:0}
19
+ </style><style>
20
+ .picker_wrapper,.picker_arrow:after,.picker_arrow:before{background-color:var(--bkg-color)!important}.picker_wrapper,.picker_arrow:before{box-shadow:0 0 10px 1px var(--text-color-grad1)!important}.picker_wrapper.fixedPosition{transform:translate(-260px)}.picker_arrow.fixedPosition{transform:translate(200px)rotate(90deg)scaleX(-1)!important}
21
+ </style><style>
18
22
  .hidden{display:none!important}.gg-rotate90{transform:rotate(90deg)}.gg-rotate180{transform:rotate(180deg)}.gg-rotate270{transform:rotate(270deg)}img{filter:var(--svg-filter)}img.legend-image{filter:var(--svg-map-filter);background:var(--svg-legend-bkg)}div{scrollbar-width:thin}a,a:visited{color:var(--link-color)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes spin-wait{0%{transform:rotate(0)}7%{transform:rotate(360deg)}to{transform:rotate(360deg)}}.gg-spin{animation-name:spin;animation-duration:2s;animation-timing-function:linear;animation-iteration-count:infinite}.gg-spin-wait{animation-name:spin-wait;animation-duration:10s;animation-timing-function:linear;animation-iteration-count:infinite}::-webkit-scrollbar{width:5px}::-webkit-scrollbar-thumb{background:#999}button,input,select,textarea{font:inherit}.gg-button,.gg-select,.gg-input,.gg-textarea{background-color:var(--bkg-color);color:var(--text-color);border:var(--app-standard-border);box-sizing:border-box;cursor:pointer;border-radius:3px;outline:0;margin:0;padding:0 0 0 .5rem;display:inline-block}.gg-label{background-color:var(--bkg-color);color:var(--text-color);border:none;align-items:center;margin:0;padding:0;display:flex}.gg-button,.gg-select,.gg-input,.gg-label{min-height:calc(var(--app-standard-height) / 1.5)}.gg-textarea{max-height:initial;resize:vertical;height:6rem;padding:.5rem;line-height:1.3rem}.gg-input{cursor:text}.gg-checkbox{accent-color:var(--text-color);cursor:pointer;width:1.2rem}.gg-range{accent-color:var(--text-color)}.gg-button{padding:0 .5rem}.gg-button.active{border:solid 1px var(--text-color-grad1);background-color:var(--bkg-color-grad2)}.gg-button:disabled{background-color:var(--bkg-color-grad1);color:var(--text-color-grad2);cursor:not-allowed;border:none}.gg-button:disabled img{filter:opacity(.6)}.gg-input:disabled,.gg-select:disabled,.gg-textarea:disabled{background-color:var(--bkg-color-grad1);color:var(--text-color-grad2);cursor:not-allowed}.gg-button>img{vertical-align:middle}.gg-icon-button{color:var(--text-color);cursor:pointer;background-color:#0000;border:none;flex-direction:column;justify-content:center;align-items:center;padding:0;display:flex}.gg-icon{justify-content:center;align-items:center;display:flex}.gg-big,.gg-big-withtext{min-width:var(--app-standard-height);min-height:var(--app-standard-height);max-height:var(--app-standard-height)}.gg-big img,.gg-big-withtext img{width:calc(var(--app-standard-height) - 1.5rem);margin:0}.gg-big-withtext span{font-variant:small-caps;padding:0 1rem;font-size:.9rem}.gg-medium,.gg-medium-withtext{min-width:calc(var(--app-standard-height) / 1.2);min-height:calc(var(--app-standard-height) / 1.2);max-height:calc(var(--app-standard-height) / 1.2);flex-direction:row}.gg-medium img{width:calc(var(--app-standard-height) / 2.4);margin:0}.gg-medium-withtext img{width:calc(var(--app-standard-height) / 2.4);margin-left:.5rem}.gg-medium-withtext span{padding:0 1rem 0 .5rem;font-size:.9rem}.gg-small,.gg-small-withtext{min-width:calc(var(--app-standard-height) / 2);min-height:calc(var(--app-standard-height) / 2);max-height:calc(var(--app-standard-height) / 2);flex-direction:row}.gg-small img{width:calc(var(--app-standard-height) / 3);margin:0}.gg-small-withtext img{width:calc(var(--app-standard-height) / 3);margin-left:.5rem}.gg-small-withtext span{padding:0 .5rem 0 .3rem;font-size:.9rem}.gg-button:hover:not(:disabled),.gg-select:hover:not(:disabled),.gg-input:hover:not(:disabled),.gg-textarea:hover:not(:disabled),.gg-icon-button:hover:not(:disabled){background-color:var(--bkg-color-grad1)}.gg-opacity{opacity:.5}.gg-opacity:hover{opacity:1;background-color:#0000}.gg-tabs{cursor:pointer;grid-auto-flow:column;padding-bottom:1rem;font-size:1rem;display:grid}.gg-tab{border:none;border-bottom:var(--app-standard-border);cursor:pointer;color:var(--text-color);background:0 0;padding:.5rem}.gg-tab.active{border-bottom:solid 1px var(--text-color)}.girafe-button-big,.girafe-button-large,.girafe-button-small,.girafe-button-tiny{color:var(--text-color);background-color:#0000;border:none;flex-direction:column;display:flex}.girafe-button-big:hover,.girafe-button-large:hover,.girafe-button-small:hover,.girafe-button-tiny:hover{background-color:var(--bkg-color-grad1);cursor:pointer}.girafe-button-big.dark,.girafe-button-large.dark,.girafe-button-small.dark,.girafe-button-tiny.dark{background-color:var(--bkg-color);filter:invert()}.girafe-button-big{width:var(--app-standard-height);height:var(--app-standard-height);align-items:center;padding:1rem}.girafe-button-big img{overflow:hidden}.girafe-button-large{flex-direction:row}.girafe-button-large img{height:2rem;margin:.3rem}.girafe-button-large span{height:2rem;margin:.3rem;line-height:2rem}.girafe-button-small{min-width:calc(var(--app-standard-height) / 2);height:calc(var(--app-standard-height) / 2);align-items:center;padding:.5rem}.girafe-button-small img{overflow:hidden}.girafe-button-small span{text-align:left;text-overflow:ellipsis;width:100%;overflow:hidden}.girafe-button-tiny{align-items:center;width:1rem;height:1rem;padding:0}.girafe-button-tiny img{overflow:hidden}.girafe-onboarding-theme{background-color:var(--bkg-color)!important;color:var(--text-color)!important}.girafe-onboarding-theme button{background-color:var(--bkg-color)!important;color:var(--text-color)!important;text-shadow:none!important}.girafe-onboarding-theme button.driver-popover-close-btn{z-index:10000}.tippy-box{background-color:var(--bkg-color)!important;border:var(--app-standard-border)!important}.tippy-content{color:var(--text-color)!important}.tippy-arrow{color:var(--bkg-color)!important}.tippy-box[data-theme~=error]{background-color:var(--error-color);white-space:pre-line}div.tippy-box[data-theme=image-popup]{border:var(--app-standard-border)!important;& div.tippy-content{background-color:var(--bkg-color)!important;& img{max-width:20rem;max-height:20rem}}& div.tippy-arrow{color:var(--bkg-color)!important}}
19
23
  </style><style>
20
24
  #content{background:var(--bkg-color);color:var(--text-color);margin:0;padding:1rem}.preference-group{padding-bottom:1rem}.preference-group-title{padding-bottom:10px;font-weight:700}.preference-row{flex-direction:column;padding-bottom:8px;display:flex}.with-checkbox,.with-colorpicker{flex-direction:row;justify-content:space-between;align-items:center;height:2rem}.colorpicker{border:solid 1px var(--text-color);cursor:pointer;border-radius:3px;width:1.5rem;height:1.5rem}#reset-all{justify-self:end}#footer{margin-top:2rem}
21
25
  </style>
22
26
  <style>${this.customStyle}</style>
23
- <link rel="stylesheet" href="lib/vanilla-picker/vanilla-picker.csp.css"><link rel="stylesheet" href="styles/girafecolorpicker.css"><div id="panel"><div id="content">${this.preferenceGroups.map(group => uHtml `<div class="preference-group"><div class="preference-group-title" i18n="${group}">${group}</div>${this.getPreferencesByGroup(group).map(([preference, key]) => uHtmlFor(preference, key) ` ${preference.uiElement === 'select' ? uHtml `<div class="preference-row" hidden="${!preference.visible}"><label for="${key}" class="gg-label" i18n="${key}">${key}</label> <select id="${key}" class="gg-select" onchange="${(evt) => this.onSelectOption(key, evt)}" onmousedown="${() => this.onOpenSelectOption(key)}">${preference.options.map(option => uHtml `<option i18n="${option.label}" ?selected="${preference.currentValue === option.value}" value="${option.label}">${option.label}</option>`)}</select></div>` : uHtml ``} ${preference.uiElement === 'checkbox' ? uHtml `<div class="preference-row with-checkbox" hidden="${!preference.visible}"><label for="${key}" i18n="${key}">${key}</label> <input id="${key}" type="checkbox" class="gg-checkbox" ?checked="${preference.currentValue}" onchange="${() => this.changePreference(key, !preference.currentValue)}"></div>` : uHtml ``} ${preference.uiElement === 'color' ? uHtml `<div class="preference-row with-colorpicker" hidden="${!preference.visible}"><label for="${key}" i18n="${key}">${key}</label> <button class="colorpicker" id="${key}"></button></div>` : uHtml ``} `)}</div>`)}<div id="footer"><button id="reset-all" class="gg-button" tip="Reset all preferences back to the default value" i18n="Reset All" onclick="${() => this.onResetAll()}">Reset All</button></div></div></div>
27
+ <div id="panel"><div id="content">${this.preferenceGroups.map(group => uHtml `<div class="preference-group"><div class="preference-group-title" i18n="${group}">${group}</div>${this.getPreferencesByGroup(group).map(([preference, key]) => uHtmlFor(preference, key) ` ${preference.uiElement === 'select' ? uHtml `<div class="preference-row" hidden="${!preference.visible}"><label for="${key}" class="gg-label" i18n="${key}">${key}</label> <select id="${key}" class="gg-select" onchange="${(evt) => this.onSelectOption(key, evt)}" onmousedown="${() => this.onOpenSelectOption(key)}">${preference.options.map(option => uHtml `<option i18n="${option.label}" ?selected="${preference.currentValue === option.value}" value="${option.label}">${option.label}</option>`)}</select></div>` : uHtml ``} ${preference.uiElement === 'checkbox' ? uHtml `<div class="preference-row with-checkbox" hidden="${!preference.visible}"><label for="${key}" i18n="${key}">${key}</label> <input id="${key}" type="checkbox" class="gg-checkbox" ?checked="${preference.currentValue}" onchange="${() => this.changePreference(key, !preference.currentValue)}"></div>` : uHtml ``} ${preference.uiElement === 'color' ? uHtml `<div class="preference-row with-colorpicker" hidden="${!preference.visible}"><label for="${key}" i18n="${key}">${key}</label> <button class="colorpicker" id="${key}"></button></div>` : uHtml ``} `)}</div>`)}<div id="footer"><button id="reset-all" class="gg-button" tip="Reset all preferences back to the default value" i18n="Reset All" onclick="${() => this.onResetAll()}">Reset All</button></div></div></div>
24
28
  ${this.htmlUnsafe(this.feedbackTemplateHtml ?? '')}`;
25
29
  };
26
30
  isPanelVisible = false;
@@ -21,7 +21,7 @@ class GroupLayer extends BaseLayer {
21
21
  children = [];
22
22
  constructor(id, name, order, options) {
23
23
  super(id, name, order, options);
24
- this.isExpanded = options?.isDefaultExpanded || false;
24
+ this.isExpanded = options?.isDefaultExpanded ?? false;
25
25
  this.isExclusiveGroup = options?.isExclusiveGroup ?? false;
26
26
  this._isMixed = options?.isMixed;
27
27
  this.timeOptions = options?.time;
@@ -17,7 +17,7 @@ class ThemeLayer extends BaseLayer {
17
17
  children = [];
18
18
  constructor(id, name, order, icon, options) {
19
19
  super(id, name, order, options);
20
- this.isExpanded = options?.isDefaultExpanded || true;
20
+ this.isExpanded = options?.isDefaultExpanded ?? true;
21
21
  this.isExclusiveTheme = options?.isExclusiveTheme ?? false;
22
22
  this.icon = icon;
23
23
  }
@@ -40,7 +40,7 @@ export const xmlTypesStrList = [
40
40
  ...xmlGeometryTypesStrList
41
41
  ];
42
42
  export function isStringNumeric(str) {
43
- return str.trim().length > 0 && !isNaN(Number(str)); // ensure strings of whitespace fail or mixed chars and numbers like '2n'
43
+ return str.trim().length > 0 && !Number.isNaN(Number(str)); // ensure strings of whitespace fail or mixed chars and numbers like '2n'
44
44
  }
45
45
  export function isString(attributeType) {
46
46
  return xmlStringTypesStrList.includes(attributeType);
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "GeoGirafe PSC",
6
6
  "url": "https://doc.geogirafe.org"
7
7
  },
8
- "version": "1.2.0-dev.2870319621",
8
+ "version": "1.2.0-dev.2873796427",
9
9
  "type": "module",
10
10
  "engines": {
11
11
  "node": ">=20.19.0"
@@ -28,44 +28,10 @@
28
28
  <link rel="stylesheet" href="styles/common.css" />
29
29
  <link rel="stylesheet" href="styles/iframe.css" />
30
30
 
31
- <link
32
- rel="preload"
33
- as="style"
34
- onload="
35
- this.onload = null;
36
- this.rel = 'stylesheet';
37
- "
38
- href="lib/tippy.js/tippy.css" />
39
- <link
40
- rel="preload"
41
- as="style"
42
- onload="
43
- this.onload = null;
44
- this.rel = 'stylesheet';
45
- "
46
- href="lib/tippy.js/backdrop.css" />
47
- <link
48
- rel="preload"
49
- as="style"
50
- onload="
51
- this.onload = null;
52
- this.rel = 'stylesheet';
53
- "
54
- href="lib/tippy.js/border.css" />
55
- <link
56
- rel="preload"
57
- as="style"
58
- onload="
59
- this.onload = null;
60
- this.rel = 'stylesheet';
61
- "
62
- href="lib/tippy.js/svg-arrow.css" />
63
- <noscript>
64
- <link rel="stylesheet" href="lib/tippy.js/tippy.css" />
65
- <link rel="stylesheet" href="lib/tippy.js/backdrop.css" />
66
- <link rel="stylesheet" href="lib/tippy.js/border.css" />
67
- <link rel="stylesheet" href="lib/tippy.js/svg-arrow.css" />
68
- </noscript>
31
+ <link rel="stylesheet" href="node_modules/tippy.js/dist/tippy.css" />
32
+ <link rel="stylesheet" href="node_modules/tippy.js/dist/backdrop.css" />
33
+ <link rel="stylesheet" href="node_modules/tippy.js/dist/border.css" />
34
+ <link rel="stylesheet" href="node_modules/tippy.js/dist/svg-arrow.css" />
69
35
 
70
36
  <script type="module" src="src/main.iframe.ts"></script>
71
37
  <title>GeoGirafe iFrame</title>
@@ -33,44 +33,10 @@
33
33
  <link rel="stylesheet" href="styles/common.css" />
34
34
  <link rel="stylesheet" href="styles/index.css" />
35
35
 
36
- <link
37
- rel="preload"
38
- as="style"
39
- onload="
40
- this.onload = null;
41
- this.rel = 'stylesheet';
42
- "
43
- href="lib/tippy.js/tippy.css" />
44
- <link
45
- rel="preload"
46
- as="style"
47
- onload="
48
- this.onload = null;
49
- this.rel = 'stylesheet';
50
- "
51
- href="lib/tippy.js/backdrop.css" />
52
- <link
53
- rel="preload"
54
- as="style"
55
- onload="
56
- this.onload = null;
57
- this.rel = 'stylesheet';
58
- "
59
- href="lib/tippy.js/border.css" />
60
- <link
61
- rel="preload"
62
- as="style"
63
- onload="
64
- this.onload = null;
65
- this.rel = 'stylesheet';
66
- "
67
- href="lib/tippy.js/svg-arrow.css" />
68
- <noscript>
69
- <link rel="stylesheet" href="lib/tippy.js/tippy.css" />
70
- <link rel="stylesheet" href="lib/tippy.js/backdrop.css" />
71
- <link rel="stylesheet" href="lib/tippy.js/border.css" />
72
- <link rel="stylesheet" href="lib/tippy.js/svg-arrow.css" />
73
- </noscript>
36
+ <link rel="stylesheet" href="node_modules/tippy.js/dist/tippy.css" />
37
+ <link rel="stylesheet" href="node_modules/tippy.js/dist/backdrop.css" />
38
+ <link rel="stylesheet" href="node_modules/tippy.js/dist/border.css" />
39
+ <link rel="stylesheet" href="node_modules/tippy.js/dist/svg-arrow.css" />
74
40
 
75
41
  <script type="module" src="src/main.ts"></script>
76
42
  <title>GeoGirafe</title>
@@ -1 +1 @@
1
- {"version":"1.2.0-dev.2870319621", "build":"2870319621", "date":"22/09/2026"}
1
+ {"version":"1.2.0-dev.2873796427", "build":"2873796427", "date":"23/09/2026"}
@@ -141,10 +141,7 @@ export default defineConfig(({ command, mode }) => {
141
141
  { src: `${geogirafeSource}/tools/sw/*.js`, dest: '' },
142
142
  { src: `${geogirafeSource}/styles/*.css`, dest: 'styles/' },
143
143
  { src: `${geogirafeSource}/assets/*`, dest: '' },
144
- { src: `${geogirafeSource}/tools/auth/silentlogincallback.html`, dest: '' },
145
- { src: 'node_modules/tabulator-tables/dist/css/tabulator.min.css', dest: 'lib/tabulator-tables/' },
146
- { src: 'node_modules/tippy.js/dist/*.css', dest: 'lib/tippy.js/' },
147
- { src: 'node_modules/vanilla-picker/dist/*.css', dest: 'lib/vanilla-picker/' }
144
+ { src: `${geogirafeSource}/tools/auth/silentlogincallback.html`, dest: '' }
148
145
  ]
149
146
  }),
150
147
  // This second usage of viteStaticCopy is dedicated to the library.
@@ -2,6 +2,7 @@ import GirafeSingleton from '../../base/GirafeSingleton.js';
2
2
  export declare const LayerTreeStartOrder = 1000;
3
3
  export default class OrderingManager extends GirafeSingleton {
4
4
  private timeoutId?;
5
+ private isReordering;
5
6
  private get state();
6
7
  initializeSingleton(): void;
7
8
  private registerEvents;
@@ -5,6 +5,7 @@ import ThemeLayer from '../../models/layers/themelayer.js';
5
5
  export const LayerTreeStartOrder = 1000;
6
6
  export default class OrderingManager extends GirafeSingleton {
7
7
  timeoutId;
8
+ isReordering = false;
8
9
  get state() {
9
10
  return this.context.stateManager.state;
10
11
  }
@@ -14,12 +15,17 @@ export default class OrderingManager extends GirafeSingleton {
14
15
  registerEvents() {
15
16
  this.context.stateManager.subscribe('layers.layersList', (oldLayers, newLayers) => this.onLayerListChanged(oldLayers, newLayers));
16
17
  this.context.stateManager.subscribe(/layers\.layersList\..*\.children/, (oldLayers, newLayers) => this.onLayerListChanged(oldLayers, newLayers));
17
- this.context.stateManager.subscribe(/layers\.layersList\..*\.order/, () => this.reorderLayers());
18
+ this.context.stateManager.subscribe(/layers\.layersList\..*\.order/, () => {
19
+ if (!this.isReordering) {
20
+ this.reorderLayers();
21
+ }
22
+ });
18
23
  }
19
24
  onLayerListChanged(oldLayers, newLayers) {
20
25
  // Need to reorder only if new layers were added.
21
- const addedLayers = newLayers.filter((newChild) => !oldLayers.find((oldChild) => oldChild.treeItemId === newChild.treeItemId));
22
- if (addedLayers.length > 0) {
26
+ const oldTreeItemIds = new Set(oldLayers.map((oldChild) => oldChild.treeItemId));
27
+ const hasAddedLayers = newLayers.some((newChild) => !oldTreeItemIds.has(newChild.treeItemId));
28
+ if (hasAddedLayers) {
23
29
  this.reorderLayers();
24
30
  }
25
31
  }
@@ -35,16 +41,37 @@ export default class OrderingManager extends GirafeSingleton {
35
41
  clearTimeout(this.timeoutId);
36
42
  }
37
43
  this.timeoutId = setTimeout(() => {
38
- const orderedLayers = this.getSortedLayers(this.state.layers.layersList);
39
- const counter = { index: LayerTreeStartOrder };
40
- this.context.stateManager.batchChanges(() => this.reorderLayersRecursively(orderedLayers, counter));
44
+ this.timeoutId = undefined;
45
+ this.isReordering = true;
46
+ const wasRenderEnabled = this.state.treeview.renderEnabled;
47
+ if (wasRenderEnabled) {
48
+ this.state.treeview.renderEnabled = false;
49
+ }
50
+ try {
51
+ const orderedLayers = this.getSortedLayers(this.state.layers.layersList);
52
+ const counter = { index: LayerTreeStartOrder };
53
+ this.context.stateManager.batchChanges(() => this.reorderLayersRecursively(orderedLayers, counter));
54
+ }
55
+ finally {
56
+ if (wasRenderEnabled) {
57
+ this.state.treeview.renderEnabled = true;
58
+ }
59
+ this.isReordering = false;
60
+ }
41
61
  });
42
62
  }
43
63
  reorderLayersRecursively(orderedLayers, counter) {
44
64
  // Traverse the layertree in depth first to renumber all the elements
45
65
  for (const layer of orderedLayers) {
46
- console.debug(`Setting layer ${layer.name} to order=${counter.index}`);
47
- layer.order = counter.index++;
66
+ // NOTE REG : Setting a variable to the very same value is managed by brain in theory,
67
+ // and no event will be sent by brain is the value is identical.
68
+ // But even if the call to a proxy has a small cost, here during a reorder, it can be called many times
69
+ // Because we reorder the whole treeview, which can be very big.
70
+ // Therefore, it is more performant here to add this test before setting the variable to the same value.
71
+ const nextOrder = counter.index++;
72
+ if (layer.order !== nextOrder) {
73
+ layer.order = nextOrder;
74
+ }
48
75
  if (layer instanceof GroupLayer || layer instanceof ThemeLayer) {
49
76
  const orderedChilds = this.getSortedLayers(layer.children);
50
77
  this.reorderLayersRecursively(orderedChilds, counter);
@@ -108,12 +108,12 @@ export default class ResizeWindow {
108
108
  this.width = dimension.width;
109
109
  this.height = dimension.height;
110
110
  const css = getComputedStyle(this.host);
111
- this.minHeight = parseInt(css.minHeight) || 0;
112
- this.maxHeight = parseInt(css.maxHeight) || Infinity;
113
- this.minWidth = parseInt(css.minWidth) || 0;
114
- this.maxWidth = parseInt(css.maxWidth) || Infinity;
115
- this.top = parseInt(css.top) || 0;
116
- this.left = parseInt(css.left) || 0;
111
+ this.minHeight = Number.parseInt(css.minHeight) || 0;
112
+ this.maxHeight = Number.parseInt(css.maxHeight) || Infinity;
113
+ this.minWidth = Number.parseInt(css.minWidth) || 0;
114
+ this.maxWidth = Number.parseInt(css.maxWidth) || Infinity;
115
+ this.top = Number.parseInt(css.top) || 0;
116
+ this.left = Number.parseInt(css.left) || 0;
117
117
  // Call a function whenever the cursor moves.
118
118
  document.onmousemove = (dragEvent) => this.resize(dragEvent, direction);
119
119
  // Detach events.
@@ -7,6 +7,9 @@ export default class GlobeSerializer implements IBrainSerializer<GlobeState> {
7
7
  private get globe();
8
8
  brainSerialize(globe: GlobeState): string;
9
9
  brainDeserialize(str: string): void;
10
- /** Applies the layout a display mode of the previous versions corresponds to. */
10
+ /**
11
+ * Applies the layout a display mode of the previous versions corresponds to.
12
+ * TODO REG: Remove the legacy code when not used any more
13
+ * */
11
14
  private deserializeLegacyDisplay;
12
15
  }
@@ -39,7 +39,10 @@ export default class GlobeSerializer {
39
39
  globe.loaded = false;
40
40
  this.deserializeLegacyDisplay(parsedGlobe.display);
41
41
  }
42
- /** Applies the layout a display mode of the previous versions corresponds to. */
42
+ /**
43
+ * Applies the layout a display mode of the previous versions corresponds to.
44
+ * TODO REG: Remove the legacy code when not used any more
45
+ * */
43
46
  deserializeLegacyDisplay(display) {
44
47
  if (display === undefined) {
45
48
  return;
@@ -54,6 +54,7 @@ export default class Brain<T extends Record<string | symbol, any>> {
54
54
  private getOrCreateProxyForValue;
55
55
  private cleanProxyForValue;
56
56
  private recalculateChildrenForArray;
57
+ private cleanPreviousChildren;
57
58
  private updateChildPathsRecursively;
58
59
  private handleGetVirtualProperties;
59
60
  private handleGetIgnored;
@@ -84,7 +84,7 @@ export default class Brain {
84
84
  parents: parents.map((p) => p.__brainId).join('|')
85
85
  });
86
86
  if (this.mergeMinimalPathsCache.has(cacheKey)) {
87
- return this.mergeMinimalPathsCache.get(cacheKey);
87
+ return [...this.mergeMinimalPathsCache.get(cacheKey)];
88
88
  }
89
89
  const minimalPaths = new Set();
90
90
  const parentsPaths = [];
@@ -108,7 +108,7 @@ export default class Brain {
108
108
  }
109
109
  const returnValue = Array.from(minimalPaths);
110
110
  this.mergeMinimalPathsCache.set(cacheKey, returnValue);
111
- return returnValue;
111
+ return [...returnValue];
112
112
  }
113
113
  isRightParent(candidate, parentsPaths) {
114
114
  if (parentsPaths.length === 0 || parentsPaths[0].length === 0) {
@@ -193,37 +193,48 @@ export default class Brain {
193
193
  // Recursively update child paths for consistency
194
194
  this.updateChildPathsRecursively(valueProxy, valueProxy.__brainFullPaths);
195
195
  }
196
- recalculateChildrenForArray(proxy, target, oldValue) {
196
+ recalculateChildrenForArray(proxy, target, _oldValue) {
197
197
  if (!Array.isArray(target)) {
198
198
  throw new TypeError('This method is only for arrays');
199
199
  }
200
- // Clean previous childs
201
- proxy.__brainChildren.clear();
200
+ const currentChildProxies = new Set();
201
+ // Save the previous children in a temporary Set, and clean the children
202
+ // (We use this for performance reason : a Set is a lot more performant to access)
203
+ const previousChildren = new Map(proxy.__brainChildren);
204
+ const previousChildProxies = new Set(previousChildren.values());
205
+ this.cleanPreviousChildren(previousChildren, proxy);
202
206
  for (let i = 0; i < target.length; ++i) {
203
207
  const childValue = target[i];
204
208
  const childPaths = proxy.__brainFullPaths.map((path) => this.getFullPath(path, i.toString()));
205
- const childOldValue = oldValue.find((oldChild) => areEqual(oldChild, childValue));
206
- if (childOldValue) {
207
- const oldChildIndex = oldValue.indexOf(childOldValue);
208
- const oldChildPaths = proxy.__brainFullPaths.map((path) => this.getFullPath(path, oldChildIndex));
209
- this.cleanProxyForValue(proxy, i.toString(), childValue, oldChildPaths);
210
- }
211
209
  const childProxy = this.getOrCreateProxyForValue(proxy, i.toString(), childValue, childPaths);
212
210
  if (childProxy) {
213
211
  proxy.__brainChildren.set(i.toString(), childProxy);
212
+ currentChildProxies.add(childProxy);
214
213
  }
215
- if (oldValue && oldValue.length > target.length) {
216
- for (let i = target.length; i < oldValue.length; i++) {
217
- const childPaths = proxy.__brainFullPaths.map((path) => this.getFullPath(path, i.toString()));
218
- this.cleanProxyForValue(proxy, i.toString(), oldValue[i], childPaths);
214
+ }
215
+ for (const childProxy of previousChildProxies) {
216
+ if (!currentChildProxies.has(childProxy)) {
217
+ const parents = childProxy.__brainParents;
218
+ const index = parents.indexOf(proxy);
219
+ if (index >= 0) {
220
+ parents.splice(index, 1);
219
221
  }
220
222
  }
221
- for (const [key, childProxy] of proxy.__brainChildren.entries()) {
222
- const childPaths = proxy.__brainFullPaths.map((path) => this.getFullPath(path, key));
223
- this.proxyToFullPaths.set(childProxy, childPaths);
224
- this.updateChildPathsRecursively(childProxy, childPaths);
223
+ this.updateChildPathsRecursively(childProxy, childProxy.__brainFullPaths);
224
+ }
225
+ }
226
+ cleanPreviousChildren(previousChildren, proxy) {
227
+ for (const [key, childProxy] of previousChildren.entries()) {
228
+ const fullPaths = childProxy.__brainFullPaths;
229
+ const childFullPaths = proxy.__brainFullPaths.map((path) => this.getFullPath(path, key));
230
+ for (const childFullPath of childFullPaths) {
231
+ const index = fullPaths.indexOf(childFullPath);
232
+ if (index >= 0) {
233
+ fullPaths.splice(index, 1);
234
+ }
225
235
  }
226
236
  }
237
+ proxy.__brainChildren.clear();
227
238
  }
228
239
  updateChildPathsRecursively(proxy, parentPaths, visited = new Set()) {
229
240
  if (visited.has(proxy)) {
@@ -152,7 +152,7 @@ class LayerTimeFormatter {
152
152
  return temporalFilter;
153
153
  }
154
154
  isValidDateString(dateString) {
155
- return !isNaN(Date.parse(dateString));
155
+ return !Number.isNaN(Date.parse(dateString));
156
156
  }
157
157
  isWithinRange(date) {
158
158
  return date >= this.minValue && date <= this.maxValue;