@jupytergis/base 0.14.1 → 0.16.0-alpha.0

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 (397) hide show
  1. package/lib/commands/BaseCommandIDs.d.ts +6 -0
  2. package/lib/commands/BaseCommandIDs.js +6 -0
  3. package/lib/commands/index.js +245 -55
  4. package/lib/commands/operationCommands.js +2 -2
  5. package/lib/constants.js +6 -1
  6. package/lib/{panelview/annotationPanel.js → features/annotations/AnnotationsPanel.js} +1 -1
  7. package/lib/{annotations → features/annotations}/index.d.ts +1 -0
  8. package/lib/{annotations → features/annotations}/index.js +1 -0
  9. package/lib/{console → features/console}/consoleview.js +1 -1
  10. package/lib/{panelview/filter-panel → features/filter}/Filter.js +4 -4
  11. package/lib/{panelview/filter-panel → features/filter}/FilterRow.d.ts +3 -2
  12. package/lib/{panelview/filter-panel → features/filter}/FilterRow.js +2 -1
  13. package/lib/{panelview/identify-panel → features/identify}/IdentifyPanel.d.ts +2 -0
  14. package/lib/features/identify/IdentifyPanel.js +102 -0
  15. package/lib/features/identify/components/FeatureCard.d.ts +17 -0
  16. package/lib/features/identify/components/FeatureCard.js +26 -0
  17. package/lib/features/identify/components/FeatureCardHeader.d.ts +11 -0
  18. package/lib/features/identify/components/FeatureCardHeader.js +30 -0
  19. package/lib/features/identify/components/FeatureFloater.d.ts +7 -0
  20. package/lib/features/identify/components/FeatureFloater.js +19 -0
  21. package/lib/features/identify/components/FeaturePropertyList.d.ts +11 -0
  22. package/lib/features/identify/components/FeaturePropertyList.js +18 -0
  23. package/lib/features/identify/components/FeatureRow.d.ts +13 -0
  24. package/lib/features/identify/components/FeatureRow.js +25 -0
  25. package/lib/features/identify/components/PropertyEditors.d.ts +44 -0
  26. package/lib/features/identify/components/PropertyEditors.js +56 -0
  27. package/lib/features/identify/hooks/useIdentifyPropertyEditor.d.ts +11 -0
  28. package/lib/features/identify/hooks/useIdentifyPropertyEditor.js +132 -0
  29. package/lib/features/identify/types/editorTypes.d.ts +21 -0
  30. package/lib/features/identify/utils/getFeatureIdentifier.d.ts +5 -0
  31. package/lib/features/identify/utils/getFeatureIdentifier.js +14 -0
  32. package/lib/features/identify/utils/highlightLayer.d.ts +11 -0
  33. package/lib/features/identify/utils/highlightLayer.js +57 -0
  34. package/lib/features/identify/utils/highlightStyle.d.ts +7 -0
  35. package/lib/features/identify/utils/highlightStyle.js +40 -0
  36. package/lib/{dialogs/layerBrowserDialog.js → features/layer-browser/index.js} +2 -2
  37. package/lib/features/layers/forms/layer/geoTiffLayerForm.d.ts +3 -0
  38. package/lib/{formbuilder/objectform/layer/webGlLayerForm.js → features/layers/forms/layer/geoTiffLayerForm.js} +5 -5
  39. package/lib/{formbuilder/objectform → features/layers/forms}/layer/heatmapLayerForm.js +4 -4
  40. package/lib/{formbuilder/objectform → features/layers/forms}/layer/hillshadeLayerForm.js +4 -4
  41. package/lib/{formbuilder/objectform → features/layers/forms}/layer/index.d.ts +1 -1
  42. package/lib/{formbuilder/objectform → features/layers/forms}/layer/index.js +1 -1
  43. package/lib/{formbuilder/objectform → features/layers/forms}/layer/layerform.d.ts +1 -1
  44. package/lib/{formbuilder/objectform → features/layers/forms}/layer/layerform.js +4 -4
  45. package/lib/features/layers/forms/layer/storySegmentLayerForm.js +150 -0
  46. package/lib/{formbuilder/objectform → features/layers/forms}/layer/vectorlayerform.js +4 -4
  47. package/lib/{formbuilder/objectform → features/layers/forms}/source/geojsonsource.js +5 -5
  48. package/lib/features/layers/forms/source/geopackagesource.d.ts +3 -0
  49. package/lib/features/layers/forms/source/geopackagesource.js +93 -0
  50. package/lib/{formbuilder/objectform → features/layers/forms}/source/geotiffsource.js +5 -5
  51. package/lib/{formbuilder/objectform → features/layers/forms}/source/index.d.ts +2 -0
  52. package/lib/{formbuilder/objectform → features/layers/forms}/source/index.js +2 -0
  53. package/lib/{formbuilder/objectform → features/layers/forms}/source/pathbasedsource.js +5 -5
  54. package/lib/{formbuilder/objectform → features/layers/forms}/source/sourceform.d.ts +1 -1
  55. package/lib/{formbuilder/objectform → features/layers/forms}/source/sourceform.js +4 -4
  56. package/lib/{formbuilder/objectform → features/layers/forms}/source/tilesourceform.js +4 -4
  57. package/lib/features/layers/forms/source/wmsTileSource.d.ts +4 -0
  58. package/lib/features/layers/forms/source/wmsTileSource.js +78 -0
  59. package/lib/{dialogs → features/layers}/layerCreationFormDialog.d.ts +1 -1
  60. package/lib/{dialogs → features/layers}/layerCreationFormDialog.js +1 -1
  61. package/lib/features/layers/symbology/Grammar.d.ts +11 -0
  62. package/lib/features/layers/symbology/Grammar.js +235 -0
  63. package/lib/{dialogs/symbology/vector_layer/types → features/layers/symbology}/Heatmap.d.ts +1 -1
  64. package/lib/{dialogs/symbology/vector_layer/types → features/layers/symbology}/Heatmap.js +30 -10
  65. package/lib/{dialogs → features/layers}/symbology/classificationModes.d.ts +6 -6
  66. package/lib/{dialogs → features/layers}/symbology/classificationModes.js +57 -57
  67. package/lib/features/layers/symbology/colorRampUtils.d.ts +65 -0
  68. package/lib/features/layers/symbology/colorRampUtils.js +242 -0
  69. package/lib/features/layers/symbology/components/MappingRow.d.ts +40 -0
  70. package/lib/features/layers/symbology/components/MappingRow.js +516 -0
  71. package/lib/features/layers/symbology/components/NumericInput.d.ts +20 -0
  72. package/lib/features/layers/symbology/components/NumericInput.js +44 -0
  73. package/lib/features/layers/symbology/components/ScaleEditor.d.ts +33 -0
  74. package/lib/features/layers/symbology/components/ScaleEditor.js +221 -0
  75. package/lib/{dialogs → features/layers}/symbology/components/color_ramp/ColorRampControls.d.ts +1 -1
  76. package/lib/{dialogs → features/layers}/symbology/components/color_ramp/ColorRampControls.js +3 -2
  77. package/lib/{dialogs → features/layers}/symbology/components/color_ramp/ColorRampSelector.d.ts +2 -1
  78. package/lib/{dialogs → features/layers}/symbology/components/color_ramp/ColorRampSelector.js +12 -15
  79. package/lib/{dialogs → features/layers}/symbology/components/color_ramp/ColorRampSelectorEntry.d.ts +2 -2
  80. package/lib/{dialogs → features/layers}/symbology/components/color_ramp/ColorRampSelectorEntry.js +3 -11
  81. package/lib/{dialogs → features/layers}/symbology/components/color_ramp/ModeSelectRow.d.ts +1 -1
  82. package/lib/features/layers/symbology/components/color_ramp/RgbaColorPicker.d.ts +13 -0
  83. package/lib/features/layers/symbology/components/color_ramp/RgbaColorPicker.js +128 -0
  84. package/lib/{dialogs → features/layers}/symbology/components/color_stops/StopContainer.js +3 -1
  85. package/lib/{dialogs → features/layers}/symbology/components/color_stops/StopRow.d.ts +2 -2
  86. package/lib/{dialogs → features/layers}/symbology/components/color_stops/StopRow.js +12 -7
  87. package/lib/features/layers/symbology/grammarToOLLayer.d.ts +27 -0
  88. package/lib/features/layers/symbology/grammarToOLLayer.js +145 -0
  89. package/lib/features/layers/symbology/grammarToOLStyle.d.ts +32 -0
  90. package/lib/features/layers/symbology/grammarToOLStyle.js +467 -0
  91. package/lib/{dialogs → features/layers}/symbology/hooks/useGetBandInfo.d.ts +1 -1
  92. package/lib/{dialogs → features/layers}/symbology/hooks/useGetBandInfo.js +1 -1
  93. package/lib/{dialogs → features/layers}/symbology/hooks/useGetProperties.js +1 -1
  94. package/lib/{dialogs → features/layers}/symbology/hooks/useGetSymbology.js +4 -2
  95. package/lib/features/layers/symbology/styleBuilder.d.ts +21 -0
  96. package/lib/features/layers/symbology/styleBuilder.js +145 -0
  97. package/lib/{dialogs → features/layers}/symbology/symbologyDialog.d.ts +3 -2
  98. package/lib/{dialogs → features/layers}/symbology/symbologyDialog.js +12 -12
  99. package/lib/features/layers/symbology/symbologyUtils.d.ts +41 -0
  100. package/lib/features/layers/symbology/symbologyUtils.js +114 -0
  101. package/lib/{panelview/objectproperties.d.ts → features/objectproperties/index.d.ts} +1 -1
  102. package/lib/{panelview/objectproperties.js → features/objectproperties/index.js} +5 -10
  103. package/lib/{dialogs → features/processing}/ProcessingFormDialog.d.ts +1 -1
  104. package/lib/{dialogs → features/processing}/ProcessingFormDialog.js +28 -14
  105. package/lib/features/processing/forms/MapExtentToggle.d.ts +13 -0
  106. package/lib/features/processing/forms/MapExtentToggle.js +20 -0
  107. package/lib/features/processing/forms/clipRasterByExtentForm.d.ts +10 -0
  108. package/lib/features/processing/forms/clipRasterByExtentForm.js +99 -0
  109. package/lib/{formbuilder/objectform/process → features/processing/forms}/dissolveProcessForm.js +5 -5
  110. package/lib/{formbuilder/objectform → features/processing/forms}/processingForm.d.ts +1 -1
  111. package/lib/{formbuilder/objectform → features/processing/forms}/processingForm.js +6 -6
  112. package/lib/features/processing/forms/rasterizeForm.d.ts +10 -0
  113. package/lib/features/processing/forms/rasterizeForm.js +75 -0
  114. package/lib/features/processing/forms/useMapExtent.d.ts +22 -0
  115. package/lib/features/processing/forms/useMapExtent.js +57 -0
  116. package/lib/{processing → features/processing}/index.d.ts +19 -2
  117. package/lib/features/processing/index.js +1246 -0
  118. package/lib/{processing → features/processing}/processingCommands.d.ts +1 -1
  119. package/lib/features/processing/processingCommands.js +168 -0
  120. package/lib/features/processing/serverProcessing.d.ts +51 -0
  121. package/lib/features/processing/serverProcessing.js +99 -0
  122. package/lib/{stacBrowser → features/stac-browser}/components/StacPanel.js +2 -2
  123. package/lib/{stacBrowser → features/stac-browser}/components/filter-extension/QueryableComboBox.js +64 -21
  124. package/lib/{stacBrowser → features/stac-browser}/components/filter-extension/QueryableRow.js +1 -1
  125. package/lib/{stacBrowser → features/stac-browser}/components/filter-extension/StacFilterExtensionPanel.js +2 -2
  126. package/lib/{stacBrowser → features/stac-browser}/components/filter-extension/StacQueryableFilters.js +1 -1
  127. package/lib/{stacBrowser → features/stac-browser}/components/geodes/StacFilterSection.js +3 -3
  128. package/lib/{stacBrowser → features/stac-browser}/components/shared/StacPanelResults.js +3 -3
  129. package/lib/{stacBrowser → features/stac-browser}/components/shared/StacSpatialExtent.js +1 -1
  130. package/lib/{stacBrowser → features/stac-browser}/components/shared/StacTemporalExtent.js +1 -1
  131. package/lib/{stacBrowser → features/stac-browser}/context/StacResultsContext.js +2 -2
  132. package/lib/{stacBrowser → features/stac-browser}/hooks/useGeodesSearch.js +2 -2
  133. package/lib/{stacBrowser → features/stac-browser}/hooks/useStacFilterExtension.d.ts +1 -1
  134. package/lib/{stacBrowser → features/stac-browser}/hooks/useStacFilterExtension.js +198 -114
  135. package/lib/{stacBrowser → features/stac-browser}/hooks/useStacSearch.d.ts +1 -0
  136. package/lib/{stacBrowser → features/stac-browser}/hooks/useStacSearch.js +19 -11
  137. package/lib/features/stac-browser/types/types.js +1 -0
  138. package/lib/{panelview/story-maps → features/story}/SpectaPanel.d.ts +4 -1
  139. package/lib/{panelview/story-maps → features/story}/SpectaPanel.js +3 -4
  140. package/lib/{panelview/story-maps → features/story}/StoryEditorPanel.js +1 -1
  141. package/lib/{panelview/story-maps → features/story}/StoryViewerPanel.d.ts +12 -11
  142. package/lib/features/story/StoryViewerPanel.js +64 -0
  143. package/lib/features/story/__tests__/fixtures/listStoryTestItems.d.ts +9 -0
  144. package/lib/features/story/__tests__/fixtures/listStoryTestItems.js +21 -0
  145. package/lib/features/story/components/ListStoryMapOverlayPanel.d.ts +10 -0
  146. package/lib/features/story/components/ListStoryMapOverlayPanel.js +11 -0
  147. package/lib/features/story/components/ListStoryMarkdownMeasurePane.d.ts +11 -0
  148. package/lib/features/story/components/ListStoryMarkdownMeasurePane.js +55 -0
  149. package/lib/features/story/components/ListStoryOverlayMarkdown.d.ts +15 -0
  150. package/lib/features/story/components/ListStoryOverlayMarkdown.js +93 -0
  151. package/lib/features/story/components/ListStoryStageOverlay.d.ts +12 -0
  152. package/lib/features/story/components/ListStoryStageOverlay.js +132 -0
  153. package/lib/features/story/components/ListStoryVirtualScrollTrack.d.ts +6 -0
  154. package/lib/features/story/components/ListStoryVirtualScrollTrack.js +7 -0
  155. package/lib/{panelview/story-maps → features/story}/components/SpectaDesktopView.d.ts +4 -2
  156. package/lib/features/story/components/SpectaDesktopView.js +67 -0
  157. package/lib/{panelview/story-maps → features/story}/components/SpectaMobileView.d.ts +2 -4
  158. package/lib/{panelview/story-maps → features/story}/components/SpectaMobileView.js +3 -3
  159. package/lib/features/story/components/SpectaSingleModeContent.d.ts +18 -0
  160. package/lib/features/story/components/SpectaSingleModeContent.js +8 -0
  161. package/lib/features/story/context/ListStoryScrollTrackContext.d.ts +15 -0
  162. package/lib/features/story/context/ListStoryScrollTrackContext.js +142 -0
  163. package/lib/features/story/hooks/useCurrentSegmentIndex.d.ts +3 -0
  164. package/lib/features/story/hooks/useCurrentSegmentIndex.js +17 -0
  165. package/lib/features/story/hooks/useListStoryScroll.d.ts +15 -0
  166. package/lib/features/story/hooks/useListStoryScroll.js +107 -0
  167. package/lib/features/story/hooks/useQueuedMarkdownHeightMeasure.d.ts +19 -0
  168. package/lib/features/story/hooks/useQueuedMarkdownHeightMeasure.js +56 -0
  169. package/lib/features/story/hooks/useStoryImagePreload.d.ts +1 -0
  170. package/lib/features/story/hooks/useStoryImagePreload.js +24 -0
  171. package/lib/{panelview/story-maps → features/story}/hooks/useStoryMap.d.ts +2 -7
  172. package/lib/{panelview/story-maps → features/story}/hooks/useStoryMap.js +20 -44
  173. package/lib/features/story/hooks/useStoryScrollState.d.ts +21 -0
  174. package/lib/features/story/hooks/useStoryScrollState.js +39 -0
  175. package/lib/features/story/hooks/useStorySegmentSync.d.ts +8 -0
  176. package/lib/features/story/hooks/useStorySegmentSync.js +51 -0
  177. package/lib/features/story/types/types.d.ts +38 -0
  178. package/lib/features/story/types/types.js +1 -0
  179. package/lib/features/story/utils/computeListStoryScrollState.d.ts +12 -0
  180. package/lib/features/story/utils/computeListStoryScrollState.js +70 -0
  181. package/lib/features/story/utils/listStoryMeasureQueue.d.ts +11 -0
  182. package/lib/features/story/utils/listStoryMeasureQueue.js +14 -0
  183. package/lib/features/story/utils/listStoryScrollTrack.d.ts +17 -0
  184. package/lib/features/story/utils/listStoryScrollTrack.js +72 -0
  185. package/lib/features/story/utils/spectaPresentation.d.ts +9 -0
  186. package/lib/features/story/utils/spectaPresentation.js +37 -0
  187. package/lib/features/story/utils/storySegmentViewItems.d.ts +5 -0
  188. package/lib/features/story/utils/storySegmentViewItems.js +30 -0
  189. package/lib/index.d.ts +11 -9
  190. package/lib/index.js +11 -9
  191. package/lib/keybindings.json +5 -0
  192. package/lib/mainview/OpenEOTileLayer.d.ts +49 -0
  193. package/lib/mainview/OpenEOTileLayer.js +179 -0
  194. package/lib/mainview/TemporalSlider.js +11 -9
  195. package/lib/mainview/geoJsonFeaturePatch.d.ts +9 -0
  196. package/lib/mainview/geoJsonFeaturePatch.js +43 -0
  197. package/lib/mainview/mainView.d.ts +93 -8
  198. package/lib/mainview/mainView.js +1286 -529
  199. package/lib/mainview/mainviewwidget.d.ts +5 -1
  200. package/lib/mainview/mainviewwidget.js +4 -2
  201. package/lib/shared/components/Button.d.ts +1 -1
  202. package/lib/shared/components/DropdownMenu.d.ts +1 -0
  203. package/lib/shared/components/DropdownMenu.js +3 -2
  204. package/lib/shared/components/NativeSelect.d.ts +8 -0
  205. package/lib/shared/components/NativeSelect.js +29 -0
  206. package/lib/shared/components/Tabs.d.ts +3 -3
  207. package/lib/shared/components/Tabs.js +5 -5
  208. package/lib/{formbuilder → shared/formbuilder}/creationform.js +71 -4
  209. package/lib/{formbuilder → shared/formbuilder}/editform.js +1 -1
  210. package/lib/{formbuilder → shared/formbuilder}/formselectors.d.ts +2 -2
  211. package/lib/{formbuilder → shared/formbuilder}/formselectors.js +13 -4
  212. package/lib/shared/formbuilder/index.d.ts +4 -0
  213. package/lib/shared/formbuilder/index.js +4 -0
  214. package/lib/{formbuilder → shared/formbuilder}/objectform/SchemaForm.d.ts +1 -1
  215. package/lib/{formbuilder → shared/formbuilder}/objectform/StoryEditorForm.d.ts +1 -1
  216. package/lib/{formbuilder → shared/formbuilder}/objectform/StoryEditorForm.js +1 -1
  217. package/lib/{formbuilder → shared/formbuilder}/objectform/components/LayerSelect.js +1 -1
  218. package/lib/{formbuilder → shared/formbuilder}/objectform/components/SegmentFormSymbology.js +4 -4
  219. package/lib/{formbuilder → shared/formbuilder}/objectform/components/SourcePropertiesField.js +1 -1
  220. package/lib/{formbuilder → shared/formbuilder}/objectform/components/StorySegmentReset.js +1 -1
  221. package/lib/shared/formbuilder/objectform/components/WmsTileSourceUrlInput.d.ts +3 -0
  222. package/lib/shared/formbuilder/objectform/components/WmsTileSourceUrlInput.js +84 -0
  223. package/lib/{formbuilder → shared/formbuilder}/objectform/fileselectorwidget.js +8 -1
  224. package/lib/{formbuilder → shared/formbuilder}/objectform/schemaUtils.d.ts +3 -1
  225. package/lib/{formbuilder → shared/formbuilder}/objectform/schemaUtils.js +11 -0
  226. package/lib/{formbuilder → shared/formbuilder}/objectform/useSchemaFormState.d.ts +2 -2
  227. package/lib/{formbuilder → shared/formbuilder}/objectform/useSchemaFormState.js +1 -1
  228. package/lib/{icons.d.ts → shared/icons.d.ts} +2 -0
  229. package/lib/{icons.js → shared/icons.js} +28 -18
  230. package/lib/tools.d.ts +3 -1
  231. package/lib/tools.js +140 -6
  232. package/lib/types.d.ts +12 -1
  233. package/lib/types.js +6 -1
  234. package/lib/{menus.js → workspace/menus.js} +14 -2
  235. package/lib/workspace/panels/components/TabbedPanel.d.ts +17 -0
  236. package/lib/workspace/panels/components/TabbedPanel.js +19 -0
  237. package/lib/{panelview → workspace/panels}/components/layers.js +82 -20
  238. package/lib/workspace/panels/components/legendItem.js +680 -0
  239. package/lib/workspace/panels/hooks/useLayerTree.d.ts +19 -0
  240. package/lib/workspace/panels/hooks/useLayerTree.js +103 -0
  241. package/lib/workspace/panels/hooks/useRightPanelOptions.d.ts +27 -0
  242. package/lib/workspace/panels/hooks/useRightPanelOptions.js +72 -0
  243. package/lib/workspace/panels/hooks/useUIState.d.ts +2 -0
  244. package/lib/workspace/panels/hooks/useUIState.js +25 -0
  245. package/lib/{panelview → workspace/panels}/index.d.ts +1 -1
  246. package/lib/{panelview → workspace/panels}/index.js +1 -1
  247. package/lib/{panelview → workspace/panels}/leftpanel.d.ts +1 -1
  248. package/lib/workspace/panels/leftpanel.js +70 -0
  249. package/lib/{panelview/rightpanel.d.ts → workspace/panels/mergedpanel.d.ts} +6 -5
  250. package/lib/workspace/panels/mergedpanel.js +166 -0
  251. package/lib/workspace/panels/rightpanel.d.ts +25 -0
  252. package/lib/{panelview → workspace/panels}/rightpanel.js +53 -63
  253. package/lib/{statusbar → workspace/statusbar}/StatusBar.js +5 -4
  254. package/lib/{toolbar → workspace/toolbar}/widget.d.ts +2 -0
  255. package/lib/{toolbar → workspace/toolbar}/widget.js +33 -5
  256. package/lib/{widget.d.ts → workspace/widget.d.ts} +7 -5
  257. package/lib/{widget.js → workspace/widget.js} +16 -7
  258. package/package.json +19 -4
  259. package/style/base.css +109 -1
  260. package/style/icons/geopackage.svg +95 -0
  261. package/style/icons/pencil_solid.svg +7 -0
  262. package/style/identify.css +95 -0
  263. package/style/layerBrowser.css +28 -0
  264. package/style/leftPanel.css +25 -0
  265. package/style/shared/button.css +12 -0
  266. package/style/shared/dropdownMenu.css +9 -0
  267. package/style/shared/nativeSelect.css +75 -0
  268. package/style/shared/tabs.css +3 -3
  269. package/style/spectaProgressBar.css +0 -1
  270. package/style/storyPanel.css +142 -9
  271. package/style/storySpectaArticleOverlay.css +129 -0
  272. package/style/symbologyDialog.css +330 -28
  273. package/lib/dialogs/symbology/colorRampUtils.d.ts +0 -20
  274. package/lib/dialogs/symbology/colorRampUtils.js +0 -132
  275. package/lib/dialogs/symbology/symbologyUtils.d.ts +0 -33
  276. package/lib/dialogs/symbology/symbologyUtils.js +0 -180
  277. package/lib/dialogs/symbology/tiff_layer/TiffRendering.d.ts +0 -4
  278. package/lib/dialogs/symbology/tiff_layer/TiffRendering.js +0 -42
  279. package/lib/dialogs/symbology/tiff_layer/components/BandRow.d.ts +0 -23
  280. package/lib/dialogs/symbology/tiff_layer/components/BandRow.js +0 -59
  281. package/lib/dialogs/symbology/tiff_layer/types/MultibandColor.d.ts +0 -4
  282. package/lib/dialogs/symbology/tiff_layer/types/MultibandColor.js +0 -92
  283. package/lib/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.d.ts +0 -5
  284. package/lib/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.js +0 -301
  285. package/lib/dialogs/symbology/vector_layer/VectorRendering.d.ts +0 -4
  286. package/lib/dialogs/symbology/vector_layer/VectorRendering.js +0 -112
  287. package/lib/dialogs/symbology/vector_layer/components/ValueSelect.d.ts +0 -8
  288. package/lib/dialogs/symbology/vector_layer/components/ValueSelect.js +0 -9
  289. package/lib/dialogs/symbology/vector_layer/types/Canonical.d.ts +0 -4
  290. package/lib/dialogs/symbology/vector_layer/types/Canonical.js +0 -65
  291. package/lib/dialogs/symbology/vector_layer/types/Categorized.d.ts +0 -4
  292. package/lib/dialogs/symbology/vector_layer/types/Categorized.js +0 -196
  293. package/lib/dialogs/symbology/vector_layer/types/Graduated.d.ts +0 -4
  294. package/lib/dialogs/symbology/vector_layer/types/Graduated.js +0 -250
  295. package/lib/dialogs/symbology/vector_layer/types/SimpleSymbol.d.ts +0 -4
  296. package/lib/dialogs/symbology/vector_layer/types/SimpleSymbol.js +0 -105
  297. package/lib/formbuilder/index.d.ts +0 -4
  298. package/lib/formbuilder/index.js +0 -4
  299. package/lib/formbuilder/objectform/layer/storySegmentLayerForm.js +0 -95
  300. package/lib/formbuilder/objectform/layer/webGlLayerForm.d.ts +0 -3
  301. package/lib/formbuilder/objectform/process/index.d.ts +0 -1
  302. package/lib/formbuilder/objectform/process/index.js +0 -1
  303. package/lib/panelview/components/legendItem.js +0 -200
  304. package/lib/panelview/identify-panel/IdentifyPanel.js +0 -102
  305. package/lib/panelview/leftpanel.js +0 -139
  306. package/lib/panelview/story-maps/StoryViewerPanel.js +0 -116
  307. package/lib/panelview/story-maps/components/SpectaDesktopView.js +0 -49
  308. package/lib/processing/index.js +0 -200
  309. package/lib/processing/processingCommands.js +0 -67
  310. /package/lib/{panelview/annotationPanel.d.ts → features/annotations/AnnotationsPanel.d.ts} +0 -0
  311. /package/lib/{annotations → features/annotations}/components/Annotation.d.ts +0 -0
  312. /package/lib/{annotations → features/annotations}/components/Annotation.js +0 -0
  313. /package/lib/{annotations → features/annotations}/components/AnnotationFloater.d.ts +0 -0
  314. /package/lib/{annotations → features/annotations}/components/AnnotationFloater.js +0 -0
  315. /package/lib/{annotations → features/annotations}/components/Message.d.ts +0 -0
  316. /package/lib/{annotations → features/annotations}/components/Message.js +0 -0
  317. /package/lib/{annotations → features/annotations}/model.d.ts +0 -0
  318. /package/lib/{annotations → features/annotations}/model.js +0 -0
  319. /package/lib/{console → features/console}/consoleview.d.ts +0 -0
  320. /package/lib/{console → features/console}/index.d.ts +0 -0
  321. /package/lib/{console → features/console}/index.js +0 -0
  322. /package/lib/{panelview/filter-panel → features/filter}/Filter.d.ts +0 -0
  323. /package/lib/{stacBrowser/types/types.js → features/identify/types/editorTypes.js} +0 -0
  324. /package/lib/{dialogs/layerBrowserDialog.d.ts → features/layer-browser/index.d.ts} +0 -0
  325. /package/lib/{formbuilder/objectform → features/layers/forms}/layer/heatmapLayerForm.d.ts +0 -0
  326. /package/lib/{formbuilder/objectform → features/layers/forms}/layer/hillshadeLayerForm.d.ts +0 -0
  327. /package/lib/{formbuilder/objectform → features/layers/forms}/layer/storySegmentLayerForm.d.ts +0 -0
  328. /package/lib/{formbuilder/objectform → features/layers/forms}/layer/vectorlayerform.d.ts +0 -0
  329. /package/lib/{formbuilder/objectform → features/layers/forms}/source/geojsonsource.d.ts +0 -0
  330. /package/lib/{formbuilder/objectform → features/layers/forms}/source/geotiffsource.d.ts +0 -0
  331. /package/lib/{formbuilder/objectform → features/layers/forms}/source/pathbasedsource.d.ts +0 -0
  332. /package/lib/{formbuilder/objectform → features/layers/forms}/source/tilesourceform.d.ts +0 -0
  333. /package/lib/{dialogs → features/layers}/symbology/components/color_ramp/ModeSelectRow.js +0 -0
  334. /package/lib/{dialogs → features/layers}/symbology/components/color_ramp/cmocean.json +0 -0
  335. /package/lib/{dialogs → features/layers}/symbology/components/color_stops/StopContainer.d.ts +0 -0
  336. /package/lib/{dialogs → features/layers}/symbology/hooks/useEffectiveSymbologyParams.d.ts +0 -0
  337. /package/lib/{dialogs → features/layers}/symbology/hooks/useEffectiveSymbologyParams.js +0 -0
  338. /package/lib/{dialogs → features/layers}/symbology/hooks/useGetProperties.d.ts +0 -0
  339. /package/lib/{dialogs → features/layers}/symbology/hooks/useGetSymbology.d.ts +0 -0
  340. /package/lib/{dialogs → features/layers}/symbology/hooks/useOkSignal.d.ts +0 -0
  341. /package/lib/{dialogs → features/layers}/symbology/hooks/useOkSignal.js +0 -0
  342. /package/lib/{formbuilder/objectform/process → features/processing/forms}/dissolveProcessForm.d.ts +0 -0
  343. /package/lib/{processing → features/processing}/processingFormToParam.d.ts +0 -0
  344. /package/lib/{processing → features/processing}/processingFormToParam.js +0 -0
  345. /package/lib/{stacBrowser → features/stac-browser}/components/StacPanel.d.ts +0 -0
  346. /package/lib/{stacBrowser → features/stac-browser}/components/filter-extension/QueryableComboBox.d.ts +0 -0
  347. /package/lib/{stacBrowser → features/stac-browser}/components/filter-extension/QueryableRow.d.ts +0 -0
  348. /package/lib/{stacBrowser → features/stac-browser}/components/filter-extension/StacFilterExtensionPanel.d.ts +0 -0
  349. /package/lib/{stacBrowser → features/stac-browser}/components/filter-extension/StacQueryableFilters.d.ts +0 -0
  350. /package/lib/{stacBrowser → features/stac-browser}/components/geodes/StacFilterSection.d.ts +0 -0
  351. /package/lib/{stacBrowser → features/stac-browser}/components/geodes/StacGeodesFilterPanel.d.ts +0 -0
  352. /package/lib/{stacBrowser → features/stac-browser}/components/geodes/StacGeodesFilterPanel.js +0 -0
  353. /package/lib/{stacBrowser → features/stac-browser}/components/shared/StacPanelResults.d.ts +0 -0
  354. /package/lib/{stacBrowser → features/stac-browser}/components/shared/StacSpatialExtent.d.ts +0 -0
  355. /package/lib/{stacBrowser → features/stac-browser}/components/shared/StacTemporalExtent.d.ts +0 -0
  356. /package/lib/{stacBrowser → features/stac-browser}/constants.d.ts +0 -0
  357. /package/lib/{stacBrowser → features/stac-browser}/constants.js +0 -0
  358. /package/lib/{stacBrowser → features/stac-browser}/context/StacResultsContext.d.ts +0 -0
  359. /package/lib/{stacBrowser → features/stac-browser}/hooks/useGeodesSearch.d.ts +0 -0
  360. /package/lib/{stacBrowser → features/stac-browser}/index.d.ts +0 -0
  361. /package/lib/{stacBrowser → features/stac-browser}/index.js +0 -0
  362. /package/lib/{stacBrowser → features/stac-browser}/types/types.d.ts +0 -0
  363. /package/lib/{panelview/story-maps → features/story}/StoryEditorPanel.d.ts +0 -0
  364. /package/lib/{panelview/story-maps → features/story}/components/PreviewModeSwitch.d.ts +0 -0
  365. /package/lib/{panelview/story-maps → features/story}/components/PreviewModeSwitch.js +0 -0
  366. /package/lib/{panelview/story-maps → features/story}/components/StoryContentSection.d.ts +0 -0
  367. /package/lib/{panelview/story-maps → features/story}/components/StoryContentSection.js +0 -0
  368. /package/lib/{panelview/story-maps → features/story}/components/StoryImageSection.d.ts +0 -0
  369. /package/lib/{panelview/story-maps → features/story}/components/StoryImageSection.js +0 -0
  370. /package/lib/{panelview/story-maps → features/story}/components/StoryNavBar.d.ts +0 -0
  371. /package/lib/{panelview/story-maps → features/story}/components/StoryNavBar.js +0 -0
  372. /package/lib/{panelview/story-maps → features/story}/components/StorySubtitleSection.d.ts +0 -0
  373. /package/lib/{panelview/story-maps → features/story}/components/StorySubtitleSection.js +0 -0
  374. /package/lib/{panelview/story-maps → features/story}/components/StoryTitleSection.d.ts +0 -0
  375. /package/lib/{panelview/story-maps → features/story}/components/StoryTitleSection.js +0 -0
  376. /package/lib/{formbuilder → shared/formbuilder}/creationform.d.ts +0 -0
  377. /package/lib/{formbuilder → shared/formbuilder}/editform.d.ts +0 -0
  378. /package/lib/{formbuilder → shared/formbuilder}/objectform/SchemaForm.js +0 -0
  379. /package/lib/{formbuilder → shared/formbuilder}/objectform/components/LayerSelect.d.ts +0 -0
  380. /package/lib/{formbuilder → shared/formbuilder}/objectform/components/OpacitySlider.d.ts +0 -0
  381. /package/lib/{formbuilder → shared/formbuilder}/objectform/components/OpacitySlider.js +0 -0
  382. /package/lib/{formbuilder → shared/formbuilder}/objectform/components/SegmentFormSymbology.d.ts +0 -0
  383. /package/lib/{formbuilder → shared/formbuilder}/objectform/components/SourcePropertiesField.d.ts +0 -0
  384. /package/lib/{formbuilder → shared/formbuilder}/objectform/components/StorySegmentReset.d.ts +0 -0
  385. /package/lib/{formbuilder → shared/formbuilder}/objectform/fileselectorwidget.d.ts +0 -0
  386. /package/lib/{store.d.ts → shared/store.d.ts} +0 -0
  387. /package/lib/{store.js → shared/store.js} +0 -0
  388. /package/lib/{menus.d.ts → workspace/menus.d.ts} +0 -0
  389. /package/lib/{panelview → workspace/panels}/components/layers.d.ts +0 -0
  390. /package/lib/{panelview → workspace/panels}/components/legendItem.d.ts +0 -0
  391. /package/lib/{panelview → workspace/panels}/header.d.ts +0 -0
  392. /package/lib/{panelview → workspace/panels}/header.js +0 -0
  393. /package/lib/{statusbar → workspace/statusbar}/SpectaPresentationProgressBar.d.ts +0 -0
  394. /package/lib/{statusbar → workspace/statusbar}/SpectaPresentationProgressBar.js +0 -0
  395. /package/lib/{statusbar → workspace/statusbar}/StatusBar.d.ts +0 -0
  396. /package/lib/{toolbar → workspace/toolbar}/index.d.ts +0 -0
  397. /package/lib/{toolbar → workspace/toolbar}/index.js +0 -0
@@ -10,13 +10,15 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { endOfToday, startOfToday } from 'date-fns';
13
- import { useCallback, useEffect, useState } from 'react';
14
- import useIsFirstRender from "../../shared/hooks/useIsFirstRender";
13
+ import { useCallback, useEffect, useRef, useState } from 'react';
15
14
  import { useStacResultsContext } from "../context/StacResultsContext";
16
15
  import { useStacSearch } from "./useStacSearch";
17
- import { GlobalStateDbManager } from "../../store";
18
- import { fetchWithProxies } from "../../tools";
16
+ import useIsFirstRender from "../../../shared/hooks/useIsFirstRender";
17
+ import { GlobalStateDbManager } from "../../../shared/store";
18
+ import { fetchWithProxies } from "../../../tools";
19
19
  const STAC_FILTER_EXTENSION_STATE_KEY = 'jupytergis:stac-filter-extension-state';
20
+ const STAC_COLLECTIONS_CACHE_STATE_KEY = 'jupytergis:stac-collections-cache';
21
+ const STAC_QUERYABLES_CACHE_STATE_KEY = 'jupytergis:stac-queryables-cache';
20
22
  /**
21
23
  * Hook for searching STAC catalogs that support the Filter Extension (CQL2-JSON).
22
24
  * Fetches collections and queryables, and builds filter queries using the STAC Filter Extension.
@@ -25,7 +27,7 @@ export function useStacFilterExtension({ model, baseUrl, limit = 12, }) {
25
27
  const isFirstRender = useIsFirstRender();
26
28
  const { registerBuildQuery, executeQuery } = useStacResultsContext();
27
29
  // Get temporal/spatial filters from useStacSearch
28
- const { startTime, endTime, setStartTime, setEndTime, currentBBox, useWorldBBox, setUseWorldBBox, } = useStacSearch({
30
+ const { startTime, endTime, setStartTime, setEndTime, currentBBox, useWorldBBox, setUseWorldBBox, hasLoadedInitialSearchState, } = useStacSearch({
29
31
  model,
30
32
  });
31
33
  const [queryableFields, setQueryableFields] = useState();
@@ -33,30 +35,132 @@ export function useStacFilterExtension({ model, baseUrl, limit = 12, }) {
33
35
  const [selectedCollection, setSelectedCollection] = useState('');
34
36
  const [selectedQueryables, setSelectedQueryables] = useState({});
35
37
  const [filterOperator, setFilterOperator] = useState('and');
38
+ const hasLoadedInitialFilterStateRef = useRef(false);
39
+ const hasLoadedInitialQueryablesRef = useRef(false);
40
+ /** Last auto-search request; skips duplicate consecutive fetches (React churn). */
41
+ const lastAutoQueryKeyRef = useRef(null);
36
42
  const stateDb = GlobalStateDbManager.getInstance().getStateDb();
43
+ const getCollectionsCacheKey = useCallback(() => `${STAC_COLLECTIONS_CACHE_STATE_KEY}:${baseUrl}`, [baseUrl]);
44
+ const getQueryablesCacheKey = useCallback(() => `${STAC_QUERYABLES_CACHE_STATE_KEY}:${baseUrl}:${selectedCollection}`, [baseUrl, selectedCollection]);
45
+ const updateSelectedQueryables = useCallback((qKey, filter) => {
46
+ setSelectedQueryables(prev => {
47
+ // If filter is null, remove the key entirely
48
+ if (filter === null) {
49
+ const _a = prev, _b = qKey, _ = _a[_b], rest = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
50
+ return rest;
51
+ }
52
+ // If inputValue is undefined but filter exists, keep it (user might be
53
+ // entering value). Only remove if explicitly set to null.
54
+ return Object.assign(Object.assign({}, prev), { [qKey]: filter });
55
+ });
56
+ }, []);
57
+ const handleSelectedCollectionChange = useCallback((nextSelectedCollection) => {
58
+ if (selectedCollection !== '' &&
59
+ nextSelectedCollection !== '' &&
60
+ selectedCollection !== nextSelectedCollection) {
61
+ setSelectedQueryables({});
62
+ setQueryableFields(undefined);
63
+ setFilterOperator('and');
64
+ }
65
+ setSelectedCollection(nextSelectedCollection);
66
+ }, [selectedCollection]);
67
+ const buildQuery = useCallback(() => {
68
+ const st = startTime
69
+ ? startTime.toISOString()
70
+ : startOfToday().toISOString();
71
+ const et = endTime ? endTime.toISOString() : endOfToday().toISOString();
72
+ // Build filter object from selectedQueryables
73
+ const filterConditions = Object.entries(selectedQueryables)
74
+ .filter(([, filter]) => filter.inputValue !== undefined)
75
+ .map(([property, filter]) => {
76
+ var _a, _b;
77
+ // Check if this property is a datetime type
78
+ const queryableField = queryableFields === null || queryableFields === void 0 ? void 0 : queryableFields.find(([key]) => key === property);
79
+ const isDateTime = queryableField &&
80
+ ((_a = queryableField[1]) === null || _a === void 0 ? void 0 : _a.type) === 'string' &&
81
+ ((_b = queryableField[1]) === null || _b === void 0 ? void 0 : _b.format) === 'date-time';
82
+ // For datetime values, wrap in timestamp object; otherwise use value directly
83
+ const value = isDateTime
84
+ ? { timestamp: filter.inputValue }
85
+ : filter.inputValue;
86
+ const condition = {
87
+ op: filter.operator,
88
+ args: [{ property }, value],
89
+ };
90
+ return condition;
91
+ });
92
+ const body = {
93
+ bbox: currentBBox,
94
+ collections: [selectedCollection],
95
+ datetime: `${st}/${et}`,
96
+ limit,
97
+ 'filter-lang': 'cql2-json',
98
+ };
99
+ // Only add filter if there are any conditions
100
+ if (filterConditions.length > 0) {
101
+ body.filter = {
102
+ op: filterOperator,
103
+ args: filterConditions,
104
+ };
105
+ }
106
+ return body;
107
+ }, [
108
+ startTime,
109
+ endTime,
110
+ currentBBox,
111
+ selectedCollection,
112
+ limit,
113
+ selectedQueryables,
114
+ filterOperator,
115
+ queryableFields,
116
+ ]);
117
+ // Register buildQuery with context
118
+ useEffect(() => {
119
+ registerBuildQuery(() => buildQuery());
120
+ }, [registerBuildQuery, buildQuery, baseUrl]);
121
+ const handleSubmit = useCallback(async () => {
122
+ if (!model) {
123
+ return;
124
+ }
125
+ // Build query body and execute query
126
+ const queryBody = buildQuery();
127
+ const searchUrl = baseUrl.endsWith('/')
128
+ ? `${baseUrl}search`
129
+ : `${baseUrl}/search`;
130
+ lastAutoQueryKeyRef.current = JSON.stringify({
131
+ searchUrl,
132
+ queryBody,
133
+ });
134
+ await executeQuery(queryBody, searchUrl);
135
+ }, [model, buildQuery, baseUrl]);
37
136
  // On mount, load saved filter state from StateDB (if present)
38
137
  useEffect(() => {
39
138
  async function loadFilterExtensionStateFromDb() {
40
- const savedFilterState = (await (stateDb === null || stateDb === void 0 ? void 0 : stateDb.fetch(STAC_FILTER_EXTENSION_STATE_KEY)));
41
- if (savedFilterState) {
42
- if (savedFilterState.selectedCollection) {
43
- setSelectedCollection(savedFilterState.selectedCollection);
44
- }
45
- if (savedFilterState.queryableFilters) {
46
- // Convert null back to undefined for inputValue
47
- const restoredFilters = {};
48
- Object.entries(savedFilterState.queryableFilters).forEach(([key, filter]) => {
49
- restoredFilters[key] = {
50
- operator: filter.operator,
51
- inputValue: filter.inputValue === null ? undefined : filter.inputValue,
52
- };
53
- });
54
- setSelectedQueryables(restoredFilters);
55
- }
56
- if (savedFilterState.filterOperator) {
57
- setFilterOperator(savedFilterState.filterOperator);
139
+ hasLoadedInitialFilterStateRef.current = false;
140
+ try {
141
+ const savedFilterState = (await (stateDb === null || stateDb === void 0 ? void 0 : stateDb.fetch(STAC_FILTER_EXTENSION_STATE_KEY)));
142
+ if (savedFilterState) {
143
+ if (savedFilterState.selectedCollection) {
144
+ handleSelectedCollectionChange(savedFilterState.selectedCollection);
145
+ }
146
+ if (savedFilterState.queryableFilters) {
147
+ const restoredFilters = {};
148
+ Object.entries(savedFilterState.queryableFilters).forEach(([key, filter]) => {
149
+ restoredFilters[key] = {
150
+ operator: filter.operator,
151
+ inputValue: filter.inputValue === null ? undefined : filter.inputValue,
152
+ };
153
+ });
154
+ setSelectedQueryables(restoredFilters);
155
+ }
156
+ if (savedFilterState.filterOperator) {
157
+ setFilterOperator(savedFilterState.filterOperator);
158
+ }
58
159
  }
59
160
  }
161
+ finally {
162
+ hasLoadedInitialFilterStateRef.current = true;
163
+ }
60
164
  }
61
165
  loadFilterExtensionStateFromDb();
62
166
  }, [stateDb]);
@@ -84,6 +188,8 @@ export function useStacFilterExtension({ model, baseUrl, limit = 12, }) {
84
188
  }, [selectedCollection, selectedQueryables, filterOperator, stateDb]);
85
189
  // Reset all state when URL changes
86
190
  useEffect(() => {
191
+ lastAutoQueryKeyRef.current = null;
192
+ hasLoadedInitialQueryablesRef.current = false;
87
193
  setQueryableFields(undefined);
88
194
  setCollections([]);
89
195
  setSelectedCollection('');
@@ -96,14 +202,37 @@ export function useStacFilterExtension({ model, baseUrl, limit = 12, }) {
96
202
  return;
97
203
  }
98
204
  const fetchCollections = async () => {
205
+ var _a;
99
206
  if (!baseUrl) {
100
207
  return;
101
208
  }
209
+ const cachedCollections = (await (stateDb === null || stateDb === void 0 ? void 0 : stateDb.fetch(getCollectionsCacheKey())));
210
+ if (cachedCollections && cachedCollections.length > 0) {
211
+ setCollections(cachedCollections);
212
+ if (hasLoadedInitialQueryablesRef.current &&
213
+ selectedCollection === '') {
214
+ handleSelectedCollectionChange(cachedCollections[0].id);
215
+ }
216
+ return;
217
+ }
102
218
  const collectionsUrl = baseUrl.endsWith('/')
103
219
  ? `${baseUrl}collections`
104
220
  : `${baseUrl}/collections`;
105
- const data = await fetchWithProxies(collectionsUrl, model, async (response) => await response.json(), undefined);
106
- const collections = data.collections
221
+ const allCollections = [];
222
+ let nextUrl = collectionsUrl;
223
+ while (nextUrl) {
224
+ const page = await fetchWithProxies(nextUrl, model, async (response) => await response.json(), undefined);
225
+ if (!page) {
226
+ break;
227
+ }
228
+ allCollections.push(...page.collections);
229
+ const currentPageUrl = nextUrl;
230
+ const nextLinkHref = (_a = page.links.find(link => link.rel === 'next')) === null || _a === void 0 ? void 0 : _a.href;
231
+ nextUrl = nextLinkHref
232
+ ? new URL(nextLinkHref, currentPageUrl).toString()
233
+ : null;
234
+ }
235
+ const collections = allCollections
107
236
  .map((collection) => {
108
237
  var _a;
109
238
  return ({
@@ -118,13 +247,23 @@ export function useStacFilterExtension({ model, baseUrl, limit = 12, }) {
118
247
  return titleA.localeCompare(titleB);
119
248
  });
120
249
  setCollections(collections);
250
+ await (stateDb === null || stateDb === void 0 ? void 0 : stateDb.save(getCollectionsCacheKey(), collections));
121
251
  // Set first collection as default if one isn't loaded
122
- if (collections.length > 0 && !(selectedCollection === '')) {
123
- setSelectedCollection(collections[0].id);
252
+ if (hasLoadedInitialQueryablesRef.current &&
253
+ collections.length > 0 &&
254
+ !(selectedCollection === '')) {
255
+ handleSelectedCollectionChange(collections[0].id);
124
256
  }
125
257
  };
126
258
  fetchCollections();
127
- }, [model, baseUrl]);
259
+ }, [
260
+ model,
261
+ baseUrl,
262
+ stateDb,
263
+ selectedCollection,
264
+ getCollectionsCacheKey,
265
+ handleSelectedCollectionChange,
266
+ ]);
128
267
  // for queryables
129
268
  // ! TODO - support multiple collection selections
130
269
  useEffect(() => {
@@ -132,102 +271,46 @@ export function useStacFilterExtension({ model, baseUrl, limit = 12, }) {
132
271
  return;
133
272
  }
134
273
  const fetchQueryables = async () => {
135
- if (!baseUrl) {
274
+ if (!baseUrl || selectedCollection === '') {
275
+ return;
276
+ }
277
+ hasLoadedInitialQueryablesRef.current = false;
278
+ const cachedQueryables = (await (stateDb === null || stateDb === void 0 ? void 0 : stateDb.fetch(getQueryablesCacheKey())));
279
+ if (cachedQueryables !== undefined) {
280
+ setQueryableFields(Object.entries(cachedQueryables));
281
+ hasLoadedInitialQueryablesRef.current = true;
136
282
  return;
137
283
  }
138
284
  const queryablesUrl = baseUrl.endsWith('/')
139
- ? `${baseUrl}queryables`
140
- : `${baseUrl}/queryables`;
285
+ ? `${baseUrl}collections/${encodeURIComponent(selectedCollection)}/queryables`
286
+ : `${baseUrl}/collections/${encodeURIComponent(selectedCollection)}/queryables`;
141
287
  const data = await fetchWithProxies(queryablesUrl, model, async (response) => await response.json(), undefined);
142
- setQueryableFields(Object.entries(data.properties));
288
+ const queryableProperties = data.properties;
289
+ setQueryableFields(Object.entries(queryableProperties));
290
+ await (stateDb === null || stateDb === void 0 ? void 0 : stateDb.save(getQueryablesCacheKey(), queryableProperties));
291
+ hasLoadedInitialQueryablesRef.current = true;
143
292
  };
144
293
  fetchQueryables();
145
- }, [model, baseUrl]);
146
- const updateSelectedQueryables = useCallback((qKey, filter) => {
147
- setSelectedQueryables(prev => {
148
- // If filter is null, remove the key entirely
149
- if (filter === null) {
150
- const _a = prev, _b = qKey, _ = _a[_b], rest = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
151
- return rest;
152
- }
153
- // If inputValue is undefined but filter exists, keep it (user might be entering value)
154
- // Only remove if explicitly set to null
155
- return Object.assign(Object.assign({}, prev), { [qKey]: filter });
156
- });
157
- }, []);
158
- const buildQuery = useCallback(() => {
159
- const st = startTime
160
- ? startTime.toISOString()
161
- : startOfToday().toISOString();
162
- const et = endTime ? endTime.toISOString() : endOfToday().toISOString();
163
- // Build filter object from selectedQueryables
164
- const filterConditions = Object.entries(selectedQueryables)
165
- .filter(([, filter]) => filter.inputValue !== undefined)
166
- .map(([property, filter]) => {
167
- var _a, _b;
168
- // Check if this property is a datetime type
169
- const queryableField = queryableFields === null || queryableFields === void 0 ? void 0 : queryableFields.find(([key]) => key === property);
170
- const isDateTime = queryableField &&
171
- ((_a = queryableField[1]) === null || _a === void 0 ? void 0 : _a.type) === 'string' &&
172
- ((_b = queryableField[1]) === null || _b === void 0 ? void 0 : _b.format) === 'date-time';
173
- // For datetime values, wrap in timestamp object; otherwise use value directly
174
- const value = isDateTime
175
- ? { timestamp: filter.inputValue }
176
- : filter.inputValue;
177
- const condition = {
178
- op: filter.operator,
179
- args: [{ property }, value],
180
- };
181
- return condition;
182
- });
183
- const body = {
184
- bbox: currentBBox,
185
- collections: [selectedCollection],
186
- datetime: `${st}/${et}`,
187
- limit,
188
- 'filter-lang': 'cql2-json',
189
- };
190
- // Only add filter if there are any conditions
191
- if (filterConditions.length > 0) {
192
- body.filter = {
193
- op: filterOperator,
194
- args: filterConditions,
195
- };
196
- }
197
- return body;
198
- }, [
199
- startTime,
200
- endTime,
201
- currentBBox,
202
- selectedCollection,
203
- limit,
204
- selectedQueryables,
205
- filterOperator,
206
- queryableFields,
207
- ]);
208
- // Register buildQuery with context
209
- useEffect(() => {
210
- registerBuildQuery(() => buildQuery());
211
- }, [registerBuildQuery, buildQuery, baseUrl]);
212
- const handleSubmit = useCallback(async () => {
213
- if (!model) {
214
- return;
215
- }
216
- // Build query body and execute query
217
- const queryBody = buildQuery();
218
- const searchUrl = baseUrl.endsWith('/')
219
- ? `${baseUrl}search`
220
- : `${baseUrl}/search`;
221
- await executeQuery(queryBody, searchUrl);
222
- }, [model, executeQuery, buildQuery, baseUrl]);
294
+ }, [model, baseUrl, selectedCollection, stateDb, getQueryablesCacheKey]);
223
295
  // Handle search when filters change
224
296
  useEffect(() => {
225
- if (model && !isFirstRender && selectedCollection !== '') {
297
+ const hasLoadedInitialFilterState = hasLoadedInitialFilterStateRef.current &&
298
+ hasLoadedInitialQueryablesRef.current;
299
+ if (model &&
300
+ !isFirstRender &&
301
+ selectedCollection !== '' &&
302
+ hasLoadedInitialFilterState &&
303
+ hasLoadedInitialSearchState) {
226
304
  const queryBody = buildQuery();
227
305
  const searchUrl = baseUrl.endsWith('/')
228
306
  ? `${baseUrl}search`
229
307
  : `${baseUrl}/search`;
230
- executeQuery(queryBody, searchUrl);
308
+ const autoQueryKey = JSON.stringify({ searchUrl, queryBody });
309
+ if (lastAutoQueryKeyRef.current === autoQueryKey) {
310
+ return;
311
+ }
312
+ lastAutoQueryKeyRef.current = autoQueryKey;
313
+ void executeQuery(queryBody, searchUrl);
231
314
  }
232
315
  }, [
233
316
  model,
@@ -235,18 +318,19 @@ export function useStacFilterExtension({ model, baseUrl, limit = 12, }) {
235
318
  selectedCollection,
236
319
  selectedQueryables,
237
320
  filterOperator,
321
+ queryableFields,
238
322
  startTime,
239
323
  endTime,
240
324
  currentBBox,
241
325
  buildQuery,
242
- executeQuery,
243
326
  baseUrl,
327
+ hasLoadedInitialSearchState,
244
328
  ]);
245
329
  return {
246
330
  queryableFields,
247
331
  collections,
248
332
  selectedCollection,
249
- setSelectedCollection,
333
+ setSelectedCollection: handleSelectedCollectionChange,
250
334
  handleSubmit,
251
335
  startTime,
252
336
  endTime,
@@ -11,6 +11,7 @@ interface IUseStacSearchReturn {
11
11
  setCurrentBBox: (bbox: [number, number, number, number]) => void;
12
12
  useWorldBBox: boolean;
13
13
  setUseWorldBBox: (val: boolean) => void;
14
+ hasLoadedInitialSearchState: boolean;
14
15
  }
15
16
  /**
16
17
  * Base hook for managing STAC search - handles temporal/spatial filters
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useState } from 'react';
2
- import { GlobalStateDbManager } from "../../store";
2
+ import { GlobalStateDbManager } from "../../../shared/store";
3
3
  const STAC_SEARCH_STATE_KEY = 'jupytergis:stac-search-state';
4
4
  /**
5
5
  * Base hook for managing STAC search - handles temporal/spatial filters
@@ -9,22 +9,29 @@ export function useStacSearch({ model, }) {
9
9
  const [endTime, setEndTime] = useState(undefined);
10
10
  const [currentBBox, setCurrentBBox] = useState([-180, -90, 180, 90]);
11
11
  const [useWorldBBox, setUseWorldBBox] = useState(false);
12
+ const [hasLoadedInitialSearchState, setHasLoadedInitialSearchState] = useState(false);
12
13
  const stateDb = GlobalStateDbManager.getInstance().getStateDb();
13
14
  // Load saved state from StateDB on mount
14
15
  useEffect(() => {
15
16
  async function loadStacSearchStateFromDb() {
16
- const savedState = (await (stateDb === null || stateDb === void 0 ? void 0 : stateDb.fetch(STAC_SEARCH_STATE_KEY)));
17
- if (savedState) {
18
- if (savedState.startTime) {
19
- setStartTime(new Date(savedState.startTime));
20
- }
21
- if (savedState.endTime) {
22
- setEndTime(new Date(savedState.endTime));
23
- }
24
- if (savedState.useWorldBBox !== undefined) {
25
- setUseWorldBBox(savedState.useWorldBBox);
17
+ setHasLoadedInitialSearchState(false);
18
+ try {
19
+ const savedState = (await (stateDb === null || stateDb === void 0 ? void 0 : stateDb.fetch(STAC_SEARCH_STATE_KEY)));
20
+ if (savedState) {
21
+ if (savedState.startTime) {
22
+ setStartTime(new Date(savedState.startTime));
23
+ }
24
+ if (savedState.endTime) {
25
+ setEndTime(new Date(savedState.endTime));
26
+ }
27
+ if (savedState.useWorldBBox !== undefined) {
28
+ setUseWorldBBox(savedState.useWorldBBox);
29
+ }
26
30
  }
27
31
  }
32
+ finally {
33
+ setHasLoadedInitialSearchState(true);
34
+ }
28
35
  }
29
36
  loadStacSearchStateFromDb();
30
37
  }, [stateDb]);
@@ -63,5 +70,6 @@ export function useStacSearch({ model, }) {
63
70
  setCurrentBBox,
64
71
  useWorldBBox,
65
72
  setUseWorldBBox,
73
+ hasLoadedInitialSearchState,
66
74
  };
67
75
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,6 +1,7 @@
1
1
  import { IJGISLayer, IJupyterGISModel } from '@jupytergis/schema';
2
2
  import React, { RefObject } from 'react';
3
3
  import type { IStoryViewerPanelHandle } from './StoryViewerPanel';
4
+ import type { IListStorySegmentTransition } from './types/types';
4
5
  interface ISpectaPanelProps {
5
6
  model: IJupyterGISModel;
6
7
  isSpecta: boolean;
@@ -10,6 +11,8 @@ interface ISpectaPanelProps {
10
11
  storyViewerPanelRef: RefObject<IStoryViewerPanelHandle>;
11
12
  addLayer?: (id: string, layer: IJGISLayer, index: number) => Promise<void>;
12
13
  removeLayer?: (id: string) => void;
14
+ /** List stories: segment handoff state for the map stage overlay. */
15
+ onSegmentTransitionChange?: (payload: IListStorySegmentTransition | null) => void;
13
16
  }
14
- export declare function SpectaPanel({ model, isSpecta, isMobile, onSegmentTransitionEnd, containerRef, storyViewerPanelRef, addLayer, removeLayer, }: ISpectaPanelProps): React.JSX.Element;
17
+ export declare function SpectaPanel({ model, isSpecta, isMobile, onSegmentTransitionEnd, containerRef, storyViewerPanelRef, addLayer, removeLayer, onSegmentTransitionChange, }: ISpectaPanelProps): React.JSX.Element;
15
18
  export {};
@@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react';
2
2
  import { SpectaDesktopView } from './components/SpectaDesktopView';
3
3
  import { SpectaMobileView } from './components/SpectaMobileView';
4
4
  import { useStoryMap } from './hooks/useStoryMap';
5
- export function SpectaPanel({ model, isSpecta, isMobile, onSegmentTransitionEnd, containerRef, storyViewerPanelRef, addLayer, removeLayer, }) {
5
+ export function SpectaPanel({ model, isSpecta, isMobile, onSegmentTransitionEnd, containerRef, storyViewerPanelRef, addLayer, removeLayer, onSegmentTransitionChange, }) {
6
6
  const overrideLayerEntriesRef = useRef([]);
7
7
  const segmentContainerRef = useRef(null);
8
8
  const { storyData, currentIndex, setIndex, handlePrev, handleNext, hasPrev, hasNext, activeSlide, layerName, showGradient, } = useStoryMap({
@@ -10,7 +10,6 @@ export function SpectaPanel({ model, isSpecta, isMobile, onSegmentTransitionEnd,
10
10
  overrideLayerEntriesRef,
11
11
  removeLayer,
12
12
  addLayer,
13
- panelRef: isMobile ? undefined : containerRef,
14
13
  isSpecta,
15
14
  });
16
15
  // Notify when segment transition animation ends
@@ -29,7 +28,7 @@ export function SpectaPanel({ model, isSpecta, isMobile, onSegmentTransitionEnd,
29
28
  return () => el.removeEventListener('animationend', handleAnimationEnd);
30
29
  }, [currentIndex, onSegmentTransitionEnd]);
31
30
  if (isMobile) {
32
- return (React.createElement(SpectaMobileView, { model: model, segmentContainerRef: segmentContainerRef, storyData: storyData, currentIndex: currentIndex, activeSlide: activeSlide, layerName: layerName, handlePrev: handlePrev, handleNext: handleNext, hasPrev: hasPrev, hasNext: hasNext, setIndex: setIndex }));
31
+ return (React.createElement(SpectaMobileView, { segmentContainerRef: segmentContainerRef, storyData: storyData, currentIndex: currentIndex, activeSlide: activeSlide, layerName: layerName, handlePrev: handlePrev, handleNext: handleNext, hasPrev: hasPrev, hasNext: hasNext }));
33
32
  }
34
- return (React.createElement(SpectaDesktopView, { model: model, isSpecta: isSpecta, containerRef: containerRef, storyViewerPanelRef: storyViewerPanelRef, segmentContainerRef: segmentContainerRef, storyData: storyData, currentIndex: currentIndex, activeSlide: activeSlide, layerName: layerName, handlePrev: handlePrev, handleNext: handleNext, hasPrev: hasPrev, hasNext: hasNext, showGradient: showGradient, setIndex: setIndex }));
33
+ return (React.createElement(SpectaDesktopView, { model: model, isSpecta: isSpecta, containerRef: containerRef, storyViewerPanelRef: storyViewerPanelRef, segmentContainerRef: segmentContainerRef, storyData: storyData, currentIndex: currentIndex, activeSlide: activeSlide, layerName: layerName, handlePrev: handlePrev, handleNext: handleNext, hasPrev: hasPrev, hasNext: hasNext, showGradient: showGradient, setIndex: setIndex, onSegmentTransitionChange: onSegmentTransitionChange }));
35
34
  }
@@ -3,8 +3,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
3
3
  import jgisSchema from '@jupytergis/schema/lib/schema/project/jgis.json';
4
4
  import React, { useMemo } from 'react';
5
5
  import { CommandIDs } from "../../constants";
6
- import { StoryEditorPropertiesForm } from "../../formbuilder/objectform/StoryEditorForm";
7
6
  import { Button } from "../../shared/components/Button";
7
+ import { StoryEditorPropertiesForm } from "../../shared/formbuilder/objectform/StoryEditorForm";
8
8
  import { deepCopy } from "../../tools";
9
9
  const storyMapSchema = deepCopy(jgisSchema.definitions.jGISStoryMap);
10
10
  const AddStorySegmentButton = ({ model, commands }) => (React.createElement("div", { style: { display: 'flex', justifyContent: 'center' } },
@@ -1,8 +1,13 @@
1
- import { IJGISStoryMap, IJupyterGISModel, IStorySegmentLayer } from '@jupytergis/schema';
1
+ import { IJGISStoryMap, IStorySegmentLayer } from '@jupytergis/schema';
2
2
  import React, { RefObject } from 'react';
3
+ export interface IStoryViewerPanelSegmentNav {
4
+ handlePrev: () => void;
5
+ handleNext: () => void;
6
+ hasPrev: boolean;
7
+ hasNext: boolean;
8
+ }
3
9
  /** Props: story state and callbacks come from useStoryMap in parent (SpectaPanel or SpectaMobileView). */
4
10
  interface IStoryViewerPanelProps {
5
- model: IJupyterGISModel;
6
11
  isSpecta: boolean;
7
12
  isMobile?: boolean;
8
13
  /** Ref for the segment container (SpectaPanel uses it for animationend). */
@@ -11,11 +16,10 @@ interface IStoryViewerPanelProps {
11
16
  currentIndex: number;
12
17
  activeSlide: IStorySegmentLayer['parameters'] | undefined;
13
18
  layerName: string;
14
- handlePrev: () => void;
15
- handleNext: () => void;
16
- hasPrev: boolean;
17
- hasNext: boolean;
18
- setIndex: (index: number) => void;
19
+ /** Omit for list-story overlay; required when segment nav is shown. */
20
+ segmentNav?: IStoryViewerPanelSegmentNav;
21
+ /** Disable fade animation for list stories. */
22
+ disableSegmentAnimation?: boolean;
19
23
  }
20
24
  export interface IStoryViewerPanelHandle {
21
25
  handlePrev: () => void;
@@ -40,8 +44,5 @@ export type StoryNavPlacement = 'below-title' | 'over-image' | 'subtitle-specta'
40
44
  * Story viewer (presentational). Receives story state and callbacks from parent.
41
45
  * Desktop scroll/sentinel/imperative handle live in SpectaDesktopView.
42
46
  */
43
- declare function StoryViewerPanel({ model, isSpecta, isMobile, segmentContainerRef, storyData, currentIndex, activeSlide, layerName, handlePrev, handleNext, hasPrev, hasNext, setIndex, }: IStoryViewerPanelProps): React.JSX.Element;
44
- declare namespace StoryViewerPanel {
45
- var displayName: string;
46
- }
47
+ declare function StoryViewerPanel({ isSpecta, isMobile, segmentContainerRef, storyData, currentIndex, activeSlide, layerName, segmentNav, disableSegmentAnimation, }: IStoryViewerPanelProps): React.JSX.Element;
47
48
  export default StoryViewerPanel;
@@ -0,0 +1,64 @@
1
+ import React from 'react';
2
+ import { STORY_TYPE } from "../../types";
3
+ import StoryContentSection from './components/StoryContentSection';
4
+ import StoryImageSection from './components/StoryImageSection';
5
+ import StoryNavBar from './components/StoryNavBar';
6
+ import StorySubtitleSection from './components/StorySubtitleSection';
7
+ import StoryTitleSection from './components/StoryTitleSection';
8
+ import { useStoryImagePreload } from './hooks/useStoryImagePreload';
9
+ /**
10
+ * Returns which section should render the nav bar, or null if nav should be hidden.
11
+ */
12
+ function getStoryNavPlacement(isSpecta, hasImage, storyType, isMobile) {
13
+ if (storyType === STORY_TYPE.verticalScroll) {
14
+ return null;
15
+ }
16
+ if (storyType === STORY_TYPE.unguided) {
17
+ return isSpecta && !isMobile ? 'subtitle-specta' : null;
18
+ }
19
+ if (storyType === STORY_TYPE.guided) {
20
+ if (isSpecta) {
21
+ return isMobile ? null : 'subtitle-specta';
22
+ }
23
+ return hasImage ? 'over-image' : 'below-title';
24
+ }
25
+ return null;
26
+ }
27
+ /**
28
+ * Story viewer (presentational). Receives story state and callbacks from parent.
29
+ * Desktop scroll/sentinel/imperative handle live in SpectaDesktopView.
30
+ */
31
+ function StoryViewerPanel({ isSpecta, isMobile = false, segmentContainerRef, storyData, currentIndex, activeSlide, layerName, segmentNav, disableSegmentAnimation = false, }) {
32
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
33
+ const imageLoaded = useStoryImagePreload((_a = activeSlide === null || activeSlide === void 0 ? void 0 : activeSlide.content) === null || _a === void 0 ? void 0 : _a.image);
34
+ if (!storyData || ((_b = storyData === null || storyData === void 0 ? void 0 : storyData.storySegments) === null || _b === void 0 ? void 0 : _b.length) === 0) {
35
+ return (React.createElement("div", { style: { padding: '1rem' } },
36
+ React.createElement("p", null, "No Segments available. Add one using the Add Layer menu.")));
37
+ }
38
+ const hasImage = !!(((_c = activeSlide === null || activeSlide === void 0 ? void 0 : activeSlide.content) === null || _c === void 0 ? void 0 : _c.image) && imageLoaded);
39
+ const storyType = (_d = storyData.storyType) !== null && _d !== void 0 ? _d : STORY_TYPE.guided;
40
+ const navPlacement = getStoryNavPlacement(isSpecta, hasImage, storyType, isMobile);
41
+ const navSlot = navPlacement !== null && segmentNav ? (React.createElement(StoryNavBar, { placement: navPlacement, onPrev: segmentNav.handlePrev, onNext: segmentNav.handleNext, hasPrev: segmentNav.hasPrev, hasNext: segmentNav.hasNext })) : null;
42
+ const transitionTime = (_f = (_e = activeSlide === null || activeSlide === void 0 ? void 0 : activeSlide.transition) === null || _e === void 0 ? void 0 : _e.time) !== null && _f !== void 0 ? _f : 0.3;
43
+ const segmentAnimationEnabled = !disableSegmentAnimation;
44
+ const segmentContainerKey = segmentAnimationEnabled
45
+ ? currentIndex
46
+ : undefined;
47
+ const segmentContainerClassName = segmentAnimationEnabled
48
+ ? 'jgis-story-segment-container'
49
+ : 'jgis-story-segment-container jgis-story-segment-container--no-segment-animation';
50
+ const segmentContainerStyle = segmentAnimationEnabled
51
+ ? { animationDuration: `${transitionTime}s` }
52
+ : undefined;
53
+ return (React.createElement("div", { className: storyData.storyType !== STORY_TYPE.verticalScroll
54
+ ? 'jgis-story-viewer-panel'
55
+ : '' },
56
+ React.createElement("div", { ref: segmentContainerRef, key: segmentContainerKey, className: segmentContainerClassName, style: segmentContainerStyle },
57
+ React.createElement("div", { id: "jgis-story-segment-header" },
58
+ React.createElement("h1", { className: "jgis-story-viewer-title" }, layerName !== null && layerName !== void 0 ? layerName : `Slide ${currentIndex + 1}`),
59
+ ((_g = activeSlide === null || activeSlide === void 0 ? void 0 : activeSlide.content) === null || _g === void 0 ? void 0 : _g.image) && imageLoaded ? (React.createElement(StoryImageSection, { imageUrl: activeSlide.content.image, imageLoaded: imageLoaded, layerName: layerName !== null && layerName !== void 0 ? layerName : '', slideNumber: currentIndex, navSlot: navPlacement === 'over-image' ? navSlot : null })) : (React.createElement(StoryTitleSection, { title: (_h = storyData.title) !== null && _h !== void 0 ? _h : '', navSlot: navPlacement === 'below-title' ? navSlot : null })),
60
+ React.createElement(StorySubtitleSection, { title: (_k = (_j = activeSlide === null || activeSlide === void 0 ? void 0 : activeSlide.content) === null || _j === void 0 ? void 0 : _j.title) !== null && _k !== void 0 ? _k : '', navSlot: navPlacement === 'subtitle-specta' ? navSlot : null })),
61
+ React.createElement("div", { id: "jgis-story-segment-content" },
62
+ React.createElement(StoryContentSection, { markdown: (_m = (_l = activeSlide === null || activeSlide === void 0 ? void 0 : activeSlide.content) === null || _l === void 0 ? void 0 : _l.markdown) !== null && _m !== void 0 ? _m : '' })))));
63
+ }
64
+ export default StoryViewerPanel;
@@ -0,0 +1,9 @@
1
+ import { IListStoryScrollTrackSegment, IStorySegmentViewItem } from '../../types/types';
2
+ export declare function storyItem(id: string, index: number, contentMode: 'map' | 'markdown', markdown?: string): IStorySegmentViewItem;
3
+ export interface IListStoryScrollTrackFixtureOptions {
4
+ items: IStorySegmentViewItem[];
5
+ viewportHeight: number;
6
+ mapViewportHeight?: number;
7
+ heightsById?: Readonly<Record<string, number>>;
8
+ }
9
+ export declare function layoutSegments(options: IListStoryScrollTrackFixtureOptions): IListStoryScrollTrackSegment[];