@open-pioneer/result-list 0.1.0 → 0.2.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @open-pioneer/result-list
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 520a97b: Add `ZoomOptions` prop in map package
8
+ - 48bdf81: Add highlight functionality
9
+ - 8e764ce: Zoom to features loaded into the result-list
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies [520a97b]
14
+ - @open-pioneer/map@0.5.0
15
+
3
16
  ## 0.1.0
4
17
 
5
18
  ### Minor Changes
@@ -1 +1 @@
1
- {"version":3,"file":"useSetupTable.js","sources":["useSetupTable.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { BaseFeature } from \"@open-pioneer/map\";\nimport { useEvent } from \"@open-pioneer/react-utils\";\nimport {\n RowSelectionState,\n SortingState,\n Updater,\n getCoreRowModel,\n getSortedRowModel,\n useReactTable\n} from \"@tanstack/react-table\";\nimport { useMemo, useState } from \"react\";\nimport { DataTableProps } from \"./DataTable\";\n\nexport function useSetupTable<Data extends BaseFeature>(props: DataTableProps<Data>) {\n const { data, columns, onSelectionChange: onSelectionChange } = props;\n const [sorting, setSorting] = useState<SortingState>([]);\n const [rowSelection, setRowSelection] = useState<RowSelectionState>({});\n\n // Only sort by columns which actually exist\n const actualSort = useMemo(() => {\n return sorting.filter((sort) => columns.some((c) => c.id === sort.id));\n }, [sorting, columns]);\n\n const updateSelection = useEvent((updaterOrValue: Updater<RowSelectionState>) => {\n const newSelection = applyUpdate(rowSelection, updaterOrValue);\n if (newSelection === rowSelection) {\n return;\n }\n\n setRowSelection(newSelection);\n if (onSelectionChange) {\n const rowsById = table.getCoreRowModel().rowsById;\n const selectedFeatures: BaseFeature[] = [];\n for (const rowId of Object.keys(newSelection)) {\n if (!newSelection[rowId]) {\n continue;\n }\n\n const row = rowsById[rowId];\n if (!row) {\n continue;\n }\n\n selectedFeatures.push(row.original);\n }\n\n onSelectionChange({\n features: selectedFeatures,\n getFeatureIds: () => {\n return selectedFeatures.map((feature: BaseFeature) => feature.id);\n }\n });\n }\n });\n\n const table = useReactTable({\n columns: columns,\n data,\n getRowId(feature) {\n return String(feature.id);\n },\n columnResizeMode: \"onChange\",\n getCoreRowModel: getCoreRowModel(),\n enableRowSelection: true,\n onRowSelectionChange: updateSelection,\n onSortingChange: setSorting,\n getSortedRowModel: getSortedRowModel(),\n state: {\n sorting: actualSort,\n rowSelection\n }\n });\n\n return { table, sorting, rowSelection };\n}\n\nfunction applyUpdate<T>(current: T, updaterOrValue: Updater<T>): T {\n if (typeof updaterOrValue === \"function\") {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (updaterOrValue as any)(current);\n }\n return updaterOrValue;\n}\n"],"names":[],"mappings":";;;;AAeO,SAAS,cAAwC,KAA6B,EAAA;AACjF,EAAA,MAAM,EAAE,IAAA,EAAM,OAAS,EAAA,iBAAA,EAAyC,GAAA,KAAA,CAAA;AAChE,EAAA,MAAM,CAAC,OAAS,EAAA,UAAU,CAAI,GAAA,QAAA,CAAuB,EAAE,CAAA,CAAA;AACvD,EAAA,MAAM,CAAC,YAAc,EAAA,eAAe,CAAI,GAAA,QAAA,CAA4B,EAAE,CAAA,CAAA;AAGtE,EAAM,MAAA,UAAA,GAAa,QAAQ,MAAM;AAC7B,IAAA,OAAO,OAAQ,CAAA,MAAA,CAAO,CAAC,IAAA,KAAS,OAAQ,CAAA,IAAA,CAAK,CAAC,CAAA,KAAM,CAAE,CAAA,EAAA,KAAO,IAAK,CAAA,EAAE,CAAC,CAAA,CAAA;AAAA,GACtE,EAAA,CAAC,OAAS,EAAA,OAAO,CAAC,CAAA,CAAA;AAErB,EAAM,MAAA,eAAA,GAAkB,QAAS,CAAA,CAAC,cAA+C,KAAA;AAC7E,IAAM,MAAA,YAAA,GAAe,WAAY,CAAA,YAAA,EAAc,cAAc,CAAA,CAAA;AAC7D,IAAA,IAAI,iBAAiB,YAAc,EAAA;AAC/B,MAAA,OAAA;AAAA,KACJ;AAEA,IAAA,eAAA,CAAgB,YAAY,CAAA,CAAA;AAC5B,IAAA,IAAI,iBAAmB,EAAA;AACnB,MAAM,MAAA,QAAA,GAAW,KAAM,CAAA,eAAA,EAAkB,CAAA,QAAA,CAAA;AACzC,MAAA,MAAM,mBAAkC,EAAC,CAAA;AACzC,MAAA,KAAA,MAAW,KAAS,IAAA,MAAA,CAAO,IAAK,CAAA,YAAY,CAAG,EAAA;AAC3C,QAAI,IAAA,CAAC,YAAa,CAAA,KAAK,CAAG,EAAA;AACtB,UAAA,SAAA;AAAA,SACJ;AAEA,QAAM,MAAA,GAAA,GAAM,SAAS,KAAK,CAAA,CAAA;AAC1B,QAAA,IAAI,CAAC,GAAK,EAAA;AACN,UAAA,SAAA;AAAA,SACJ;AAEA,QAAiB,gBAAA,CAAA,IAAA,CAAK,IAAI,QAAQ,CAAA,CAAA;AAAA,OACtC;AAEA,MAAkB,iBAAA,CAAA;AAAA,QACd,QAAU,EAAA,gBAAA;AAAA,QACV,eAAe,MAAM;AACjB,UAAA,OAAO,gBAAiB,CAAA,GAAA,CAAI,CAAC,OAAA,KAAyB,QAAQ,EAAE,CAAA,CAAA;AAAA,SACpE;AAAA,OACH,CAAA,CAAA;AAAA,KACL;AAAA,GACH,CAAA,CAAA;AAED,EAAA,MAAM,QAAQ,aAAc,CAAA;AAAA,IACxB,OAAA;AAAA,IACA,IAAA;AAAA,IACA,SAAS,OAAS,EAAA;AACd,MAAO,OAAA,MAAA,CAAO,QAAQ,EAAE,CAAA,CAAA;AAAA,KAC5B;AAAA,IACA,gBAAkB,EAAA,UAAA;AAAA,IAClB,iBAAiB,eAAgB,EAAA;AAAA,IACjC,kBAAoB,EAAA,IAAA;AAAA,IACpB,oBAAsB,EAAA,eAAA;AAAA,IACtB,eAAiB,EAAA,UAAA;AAAA,IACjB,mBAAmB,iBAAkB,EAAA;AAAA,IACrC,KAAO,EAAA;AAAA,MACH,OAAS,EAAA,UAAA;AAAA,MACT,YAAA;AAAA,KACJ;AAAA,GACH,CAAA,CAAA;AAED,EAAO,OAAA,EAAE,KAAO,EAAA,OAAA,EAAS,YAAa,EAAA,CAAA;AAC1C,CAAA;AAEA,SAAS,WAAA,CAAe,SAAY,cAA+B,EAAA;AAC/D,EAAI,IAAA,OAAO,mBAAmB,UAAY,EAAA;AAEtC,IAAA,OAAQ,eAAuB,OAAO,CAAA,CAAA;AAAA,GAC1C;AACA,EAAO,OAAA,cAAA,CAAA;AACX;;;;"}
1
+ {"version":3,"file":"useSetupTable.js","sources":["useSetupTable.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { BaseFeature } from \"@open-pioneer/map\";\nimport { useEvent } from \"@open-pioneer/react-utils\";\nimport {\n RowSelectionState,\n SortingState,\n Updater,\n getCoreRowModel,\n getSortedRowModel,\n useReactTable\n} from \"@tanstack/react-table\";\nimport { useMemo, useState } from \"react\";\nimport { DataTableProps } from \"./DataTable\";\n\nexport function useSetupTable<Data extends BaseFeature>(props: DataTableProps<Data>) {\n const { data, columns, onSelectionChange: onSelectionChange } = props;\n const [sorting, setSorting] = useState<SortingState>([]);\n const [rowSelection, setRowSelection] = useState<RowSelectionState>({});\n\n // Only sort by columns which actually exist\n const actualSort = useMemo(() => {\n return sorting.filter((sort) => columns.some((c) => c.id === sort.id));\n }, [sorting, columns]);\n\n const updateSelection = useEvent((updaterOrValue: Updater<RowSelectionState>) => {\n const newSelection = applyUpdate(rowSelection, updaterOrValue);\n if (newSelection === rowSelection) {\n return;\n }\n\n setRowSelection(newSelection);\n\n if (onSelectionChange) {\n const rowsById = table.getCoreRowModel().rowsById;\n const selectedFeatures: BaseFeature[] = [];\n for (const rowId of Object.keys(newSelection)) {\n if (!newSelection[rowId]) {\n continue;\n }\n\n const row = rowsById[rowId];\n if (!row) {\n continue;\n }\n\n selectedFeatures.push(row.original);\n }\n\n onSelectionChange({\n features: selectedFeatures,\n getFeatureIds: () => {\n return selectedFeatures.map((feature: BaseFeature) => feature.id);\n }\n });\n }\n });\n\n const table = useReactTable({\n columns: columns,\n data,\n getRowId(feature) {\n return String(feature.id);\n },\n columnResizeMode: \"onChange\",\n getCoreRowModel: getCoreRowModel(),\n enableRowSelection: true,\n onRowSelectionChange: updateSelection,\n onSortingChange: setSorting,\n getSortedRowModel: getSortedRowModel(),\n state: {\n sorting: actualSort,\n rowSelection\n }\n });\n\n return { table, sorting, rowSelection };\n}\n\nfunction applyUpdate<T>(current: T, updaterOrValue: Updater<T>): T {\n if (typeof updaterOrValue === \"function\") {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (updaterOrValue as any)(current);\n }\n return updaterOrValue;\n}\n"],"names":[],"mappings":";;;;AAeO,SAAS,cAAwC,KAA6B,EAAA;AACjF,EAAA,MAAM,EAAE,IAAA,EAAM,OAAS,EAAA,iBAAA,EAAyC,GAAA,KAAA,CAAA;AAChE,EAAA,MAAM,CAAC,OAAS,EAAA,UAAU,CAAI,GAAA,QAAA,CAAuB,EAAE,CAAA,CAAA;AACvD,EAAA,MAAM,CAAC,YAAc,EAAA,eAAe,CAAI,GAAA,QAAA,CAA4B,EAAE,CAAA,CAAA;AAGtE,EAAM,MAAA,UAAA,GAAa,QAAQ,MAAM;AAC7B,IAAA,OAAO,OAAQ,CAAA,MAAA,CAAO,CAAC,IAAA,KAAS,OAAQ,CAAA,IAAA,CAAK,CAAC,CAAA,KAAM,CAAE,CAAA,EAAA,KAAO,IAAK,CAAA,EAAE,CAAC,CAAA,CAAA;AAAA,GACtE,EAAA,CAAC,OAAS,EAAA,OAAO,CAAC,CAAA,CAAA;AAErB,EAAM,MAAA,eAAA,GAAkB,QAAS,CAAA,CAAC,cAA+C,KAAA;AAC7E,IAAM,MAAA,YAAA,GAAe,WAAY,CAAA,YAAA,EAAc,cAAc,CAAA,CAAA;AAC7D,IAAA,IAAI,iBAAiB,YAAc,EAAA;AAC/B,MAAA,OAAA;AAAA,KACJ;AAEA,IAAA,eAAA,CAAgB,YAAY,CAAA,CAAA;AAE5B,IAAA,IAAI,iBAAmB,EAAA;AACnB,MAAM,MAAA,QAAA,GAAW,KAAM,CAAA,eAAA,EAAkB,CAAA,QAAA,CAAA;AACzC,MAAA,MAAM,mBAAkC,EAAC,CAAA;AACzC,MAAA,KAAA,MAAW,KAAS,IAAA,MAAA,CAAO,IAAK,CAAA,YAAY,CAAG,EAAA;AAC3C,QAAI,IAAA,CAAC,YAAa,CAAA,KAAK,CAAG,EAAA;AACtB,UAAA,SAAA;AAAA,SACJ;AAEA,QAAM,MAAA,GAAA,GAAM,SAAS,KAAK,CAAA,CAAA;AAC1B,QAAA,IAAI,CAAC,GAAK,EAAA;AACN,UAAA,SAAA;AAAA,SACJ;AAEA,QAAiB,gBAAA,CAAA,IAAA,CAAK,IAAI,QAAQ,CAAA,CAAA;AAAA,OACtC;AAEA,MAAkB,iBAAA,CAAA;AAAA,QACd,QAAU,EAAA,gBAAA;AAAA,QACV,eAAe,MAAM;AACjB,UAAA,OAAO,gBAAiB,CAAA,GAAA,CAAI,CAAC,OAAA,KAAyB,QAAQ,EAAE,CAAA,CAAA;AAAA,SACpE;AAAA,OACH,CAAA,CAAA;AAAA,KACL;AAAA,GACH,CAAA,CAAA;AAED,EAAA,MAAM,QAAQ,aAAc,CAAA;AAAA,IACxB,OAAA;AAAA,IACA,IAAA;AAAA,IACA,SAAS,OAAS,EAAA;AACd,MAAO,OAAA,MAAA,CAAO,QAAQ,EAAE,CAAA,CAAA;AAAA,KAC5B;AAAA,IACA,gBAAkB,EAAA,UAAA;AAAA,IAClB,iBAAiB,eAAgB,EAAA;AAAA,IACjC,kBAAoB,EAAA,IAAA;AAAA,IACpB,oBAAsB,EAAA,eAAA;AAAA,IACtB,eAAiB,EAAA,UAAA;AAAA,IACjB,mBAAmB,iBAAkB,EAAA;AAAA,IACrC,KAAO,EAAA;AAAA,MACH,OAAS,EAAA,UAAA;AAAA,MACT,YAAA;AAAA,KACJ;AAAA,GACH,CAAA,CAAA;AAED,EAAO,OAAA,EAAE,KAAO,EAAA,OAAA,EAAS,YAAa,EAAA,CAAA;AAC1C,CAAA;AAEA,SAAS,WAAA,CAAe,SAAY,cAA+B,EAAA;AAC/D,EAAI,IAAA,OAAO,mBAAmB,UAAY,EAAA;AAEtC,IAAA,OAAQ,eAAuB,OAAO,CAAA,CAAA;AAAA,GAC1C;AACA,EAAO,OAAA,cAAA,CAAA;AACX;;;;"}
package/README.md CHANGED
@@ -4,11 +4,11 @@ This package provides a UI component to display features and their attributes.
4
4
 
5
5
  ## Usage
6
6
 
7
- To add the package to your app, import `ResultList` from `@open-pioneer/result-list`.
7
+ To add the package to your app, import `ResultList` from `@open-pioneer/result-list`. Furthermore, the Id of the currently used map is required.
8
8
 
9
9
  ```tsx
10
10
  import { ResultList } from "@open-pioneer/result-list";
11
- <ResultList input={input} />;
11
+ <ResultList mapId={mapId} input={input} />;
12
12
  ```
13
13
 
14
14
  The following section describes how to define the `input` parameter.
@@ -99,6 +99,29 @@ const columns = [
99
99
  ];
100
100
  ```
101
101
 
102
+ ### Configuring highlighting of data
103
+
104
+ The optional property `enableHighlight` determines whether data in the results list should be highlighted in the map or not. The default value is `true`.
105
+ The default style can be overridden using the optional `highlightOptions` property. `highlightOptions` must conform to the TypeScript interface `HighlightOptions`. Please note that the highlighting of the result-list can be obscured by highlights from other packages (e.g. selection).
106
+
107
+ ```tsx
108
+ import { ResultList } from "@open-pioneer/result-list";
109
+ const ownHighlightStyle = {
110
+ "Polygon": [
111
+ new Style({
112
+ stroke: new Stroke({
113
+ color: "#ff0000",
114
+ width: 3
115
+ }),
116
+ fill: new Fill({
117
+ color: "rgba(51, 171, 71,0.35)"
118
+ })
119
+ })
120
+ ]
121
+ };
122
+ <ResultList mapId={mapId} input={input} highlightOptions={ownHighlightStyle} />;
123
+ ```
124
+
102
125
  ### Selection
103
126
 
104
127
  Users can select (and deselect) individual features by clicking on the checkbox at the beginning of a row.
@@ -109,7 +132,7 @@ A checkbox in the header of the table allows to select (or deselect) _all_ featu
109
132
  ​The `ResultList` supports listening to selection changes via the optional property `onSelectionChange`.
110
133
  An event handler function can be passed that will be invoked whenever the user changes the selection.
111
134
 
112
- ```ts
135
+ ```tsx
113
136
  import { ResultList } from "@open-pioneer/result-list";
114
137
 
115
138
  const selectionChangeListener = useCallback((event: ResultListSelectionChangeEvent) => {
@@ -117,7 +140,7 @@ const selectionChangeListener = useCallback((event: ResultListSelectionChangeEve
117
140
  console.log("selection changed", event.features);
118
141
  }, []);
119
142
 
120
- <ResultList input={input} onSelectionChange={selectionChangeListener}/>
143
+ <ResultList mapId={mapId} input={input} onSelectionChange={selectionChangeListener} />;
121
144
  ```
122
145
 
123
146
  ### Track selected features
@@ -133,7 +156,7 @@ const selectionChangeListener = useCallback((event: ResultListSelectionChangeEve
133
156
  // event.getFeatureIds()
134
157
  }, []);
135
158
 
136
- <ResultList input={input} onSelectionChange={selectionChangeListener} />;
159
+ <ResultList mapId={mapId} input={input} onSelectionChange={selectionChangeListener} />;
137
160
  ```
138
161
 
139
162
  ### Sorting data
@@ -212,7 +235,7 @@ Configure the `viewPadding` on the associated `MapContainer` when the result lis
212
235
  borderColor="trails.500"
213
236
  zIndex={1}
214
237
  >
215
- <ResultList key={resultListKey} input={resultListInput} />
238
+ <ResultList key={resultListKey} mapId={mapId} input={resultListInput} />
216
239
  </Box>
217
240
  ```
218
241
 
@@ -228,6 +251,7 @@ To force the result list to throw away its existing state, use React's `key` pro
228
251
  to throw away existing state. React will create a new component behind the scenes
229
252
  with entirely new state. */
230
253
  key={resultListKey}
254
+ mapId={mapId}
231
255
  input={resultListInput}
232
256
  />
233
257
  ```
package/ResultList.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { BaseFeature } from "@open-pioneer/map";
1
+ import { BaseFeature, HighlightOptions, HighlightZoomOptions } from "@open-pioneer/map";
2
2
  import { CommonComponentProps } from "@open-pioneer/react-utils";
3
3
  import { FC, ReactNode } from "react";
4
4
  import { FormatNumberOptions } from "@formatjs/intl";
@@ -110,15 +110,31 @@ export interface ResultListProps extends CommonComponentProps {
110
110
  /**
111
111
  * The id of the map.
112
112
  */
113
- mapId?: string;
113
+ mapId: string;
114
114
  /**
115
115
  * Describes the data rendered by the component.
116
116
  */
117
117
  input: ResultListInput;
118
118
  /**
119
- * This handler is called whenever the user has changed the selected features in the result-list
119
+ * This handler is called whenever the user has changed the selected features in the result-list.
120
120
  */
121
121
  onSelectionChange?: (event: ResultListSelectionChangeEvent) => void;
122
+ /**
123
+ * Specifies if the map should zoom to features when they are loaded into the result-list. Defaults to true.
124
+ */
125
+ enableZoom?: boolean;
126
+ /**
127
+ * Should data be highlighted in the map. Default true.
128
+ */
129
+ enableHighlight?: boolean;
130
+ /**
131
+ * Optional styling option
132
+ */
133
+ highlightOptions?: HighlightOptions;
134
+ /**
135
+ * Optional zooming options
136
+ */
137
+ highlightZoomOptions?: HighlightZoomOptions;
122
138
  }
123
139
  /**
124
140
  * A component that displays a set of features as a list.
package/ResultList.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { Box } from '@open-pioneer/chakra-integration';
3
+ import { useMapModel } from '@open-pioneer/map';
3
4
  import { useCommonComponentProps } from '@open-pioneer/react-utils';
4
5
  import { useIntl } from './_virtual/_virtual-pioneer-module_react-hooks.js';
5
- import { useRef, useMemo, useState, useEffect } from 'react';
6
+ import { useRef, useMemo, useEffect, useState } from 'react';
6
7
  import { DataTable } from './DataTable/DataTable.js';
7
8
  import { createColumns } from './DataTable/createColumns.js';
8
9
 
@@ -10,9 +11,15 @@ const ResultList = (props) => {
10
11
  const { containerProps } = useCommonComponentProps("result-list", props);
11
12
  const intl = useIntl();
12
13
  const {
14
+ mapId,
13
15
  input: { data, columns, formatOptions },
14
- onSelectionChange
16
+ onSelectionChange,
17
+ enableZoom = true,
18
+ highlightZoomOptions,
19
+ enableHighlight = true,
20
+ highlightOptions
15
21
  } = props;
22
+ const { map } = useMapModel(mapId);
16
23
  if (columns.length === 0) {
17
24
  throw Error("No columns were defined. The result list cannot be displayed.");
18
25
  }
@@ -27,6 +34,18 @@ const ResultList = (props) => {
27
34
  }),
28
35
  [columns, intl, tableWidth, formatOptions]
29
36
  );
37
+ useEffect(() => {
38
+ if (!map) {
39
+ return;
40
+ }
41
+ if (enableZoom) {
42
+ map.zoom(data, highlightZoomOptions);
43
+ }
44
+ if (enableHighlight) {
45
+ const highlight = map.highlight(data, highlightOptions);
46
+ return () => highlight.destroy();
47
+ }
48
+ }, [map, data, highlightZoomOptions, enableZoom, enableHighlight, highlightOptions]);
30
49
  return /* @__PURE__ */ jsx(Box, { ...containerProps, height: "100%", overflowY: "auto", ref: containerRef, children: /* @__PURE__ */ jsx(
31
50
  DataTable,
32
51
  {
package/ResultList.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ResultList.js","sources":["ResultList.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Box } from \"@open-pioneer/chakra-integration\";\nimport { BaseFeature } from \"@open-pioneer/map\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { FC, ReactNode, RefObject, useEffect, useMemo, useRef, useState } from \"react\";\nimport { DataTable } from \"./DataTable/DataTable\";\nimport { createColumns } from \"./DataTable/createColumns\";\nimport { FormatNumberOptions } from \"@formatjs/intl\";\n\n/**\n * Configures a column in the result list component.\n *\n * A column typically renders a property from the underlying feature.\n */\nexport interface ResultColumn {\n /**\n * Use this option to define an explicit column id.\n * This can be helpful to track your column when it moves in the table (for example, the sort order can be maintained).\n *\n * If this is not defined, {@link propertyName} will serve as a fallback.\n * If that is also not defined, the column index will be used instead.\n *\n * It is recommended to specify an id, if no {@link propertyName} has been set, because the\n * column index fallback is not advised.\n */\n id?: string;\n\n /**\n * The display name of this column.\n *\n * If no `displayName` has been configured, {@link propertyName} will serve as a fallback value.\n * If `propertyName` is also undefined, no column header will be rendered at all.\n */\n displayName?: string;\n\n /**\n * The width of this column, in pixels.\n */\n width?: number;\n\n /**\n * The property name to render.\n *\n * The value is expected to be available as `feature.properties[propertyName]`.\n *\n * See also {@link getPropertyValue}.\n */\n propertyName?: string;\n\n /**\n * Define this function to return a custom property value for this column.\n *\n * This can be used to create derived columns (by combining multiple properties into one value)\n * or to create columns for property that don't exist directly on the feature.\n *\n * The return value of this function will be rendered by the table.\n */\n getPropertyValue?: (feature: BaseFeature) => unknown;\n\n /** Custom render function to render a table cell in this column. */\n renderCell?: (context: RenderCellContext) => ReactNode;\n}\n\n/**\n * The arguments passed to {@link ResultColumn.renderCell | renderCell}.\n */\nexport interface RenderCellContext {\n /**\n * The feature in this row.\n */\n feature: BaseFeature;\n\n /**\n * The value of this column.\n * May be undefined if neither `propertyName` nor `getPropertyValue` was specified on the column.\n */\n value: unknown;\n}\n\n/**\n * To specify the format of cell values if they are of number or date type.\n */\nexport interface FormatOptions {\n /**\n * To specify the format of number type values\n */\n numberOptions?: FormatNumberOptions;\n /**\n * To specify the format of date type values\n */\n dateOptions?: Intl.DateTimeFormatOptions;\n}\n\n/**\n * Configures the result list's content.\n */\nexport interface ResultListInput {\n /**\n * Configures the columns shown by the result list.\n */\n columns: ResultColumn[];\n\n /**\n * The data shown by the result list component.\n * Every feature will be rendered as an individual row.\n */\n data: BaseFeature[];\n\n /**\n * Optional formatOptions to specify the `numberOptions` for number type values and\n * `dateOptions` to specify the format of date type values\n */\n formatOptions?: FormatOptions;\n}\n\n/**\n * Emitted when the selection within the ResultList changes.\n */\nexport interface ResultListSelectionChangeEvent {\n features: BaseFeature[];\n getFeatureIds: () => (number | string)[];\n}\n\n/**\n * Properties supported by the {@link ResultList} component.\n */\nexport interface ResultListProps extends CommonComponentProps {\n /**\n * The id of the map.\n */\n mapId?: string;\n\n /**\n * Describes the data rendered by the component.\n */\n input: ResultListInput;\n\n /**\n * This handler is called whenever the user has changed the selected features in the result-list\n */\n onSelectionChange?: (event: ResultListSelectionChangeEvent) => void;\n}\n\n/**\n * A component that displays a set of features as a list.\n */\nexport const ResultList: FC<ResultListProps> = (props) => {\n const { containerProps } = useCommonComponentProps(\"result-list\", props);\n const intl = useIntl();\n const {\n input: { data, columns, formatOptions },\n onSelectionChange\n } = props;\n if (columns.length === 0) {\n throw Error(\"No columns were defined. The result list cannot be displayed.\");\n }\n\n const containerRef = useRef<HTMLDivElement>(null);\n const tableWidth = useTableWidth(containerRef);\n const dataTableColumns = useMemo(\n () =>\n createColumns({\n columns: columns,\n intl: intl,\n tableWidth: tableWidth,\n formatOptions: formatOptions\n }),\n [columns, intl, tableWidth, formatOptions]\n );\n\n return (\n <Box {...containerProps} height=\"100%\" overflowY=\"auto\" ref={containerRef}>\n <DataTable\n columns={dataTableColumns}\n data={data}\n onSelectionChange={onSelectionChange}\n />\n </Box>\n );\n};\n\nfunction useTableWidth(tableRef: RefObject<HTMLDivElement> | null) {\n const [tableWidth, setTableWidth] = useState<number>();\n\n useEffect(() => {\n if (!tableRef?.current) return;\n const resizeObserver = new ResizeObserver((event) => {\n // Depending on the layout, you may need to swap inlineSize with blockSize\n // https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry/contentBoxSize\n const width = event[0]?.contentBoxSize[0]?.inlineSize;\n if (width != null) {\n setTableWidth(width);\n }\n });\n resizeObserver.observe(tableRef.current);\n return () => resizeObserver.disconnect();\n }, [tableRef]);\n return tableWidth;\n}\n"],"names":[],"mappings":";;;;;;;;AAoJa,MAAA,UAAA,GAAkC,CAAC,KAAU,KAAA;AACtD,EAAA,MAAM,EAAE,cAAA,EAAmB,GAAA,uBAAA,CAAwB,eAAe,KAAK,CAAA,CAAA;AACvE,EAAA,MAAM,OAAO,OAAQ,EAAA,CAAA;AACrB,EAAM,MAAA;AAAA,IACF,KAAO,EAAA,EAAE,IAAM,EAAA,OAAA,EAAS,aAAc,EAAA;AAAA,IACtC,iBAAA;AAAA,GACA,GAAA,KAAA,CAAA;AACJ,EAAI,IAAA,OAAA,CAAQ,WAAW,CAAG,EAAA;AACtB,IAAA,MAAM,MAAM,+DAA+D,CAAA,CAAA;AAAA,GAC/E;AAEA,EAAM,MAAA,YAAA,GAAe,OAAuB,IAAI,CAAA,CAAA;AAChD,EAAM,MAAA,UAAA,GAAa,cAAc,YAAY,CAAA,CAAA;AAC7C,EAAA,MAAM,gBAAmB,GAAA,OAAA;AAAA,IACrB,MACI,aAAc,CAAA;AAAA,MACV,OAAA;AAAA,MACA,IAAA;AAAA,MACA,UAAA;AAAA,MACA,aAAA;AAAA,KACH,CAAA;AAAA,IACL,CAAC,OAAA,EAAS,IAAM,EAAA,UAAA,EAAY,aAAa,CAAA;AAAA,GAC7C,CAAA;AAEA,EACI,uBAAA,GAAA,CAAC,OAAK,GAAG,cAAA,EAAgB,QAAO,MAAO,EAAA,SAAA,EAAU,MAAO,EAAA,GAAA,EAAK,YACzD,EAAA,QAAA,kBAAA,GAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACG,OAAS,EAAA,gBAAA;AAAA,MACT,IAAA;AAAA,MACA,iBAAA;AAAA,KAAA;AAAA,GAER,EAAA,CAAA,CAAA;AAER,EAAA;AAEA,SAAS,cAAc,QAA4C,EAAA;AAC/D,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,QAAiB,EAAA,CAAA;AAErD,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,IAAI,CAAC,QAAU,EAAA,OAAA;AAAS,MAAA,OAAA;AACxB,IAAA,MAAM,cAAiB,GAAA,IAAI,cAAe,CAAA,CAAC,KAAU,KAAA;AAGjD,MAAA,MAAM,QAAQ,KAAM,CAAA,CAAC,CAAG,EAAA,cAAA,CAAe,CAAC,CAAG,EAAA,UAAA,CAAA;AAC3C,MAAA,IAAI,SAAS,IAAM,EAAA;AACf,QAAA,aAAA,CAAc,KAAK,CAAA,CAAA;AAAA,OACvB;AAAA,KACH,CAAA,CAAA;AACD,IAAe,cAAA,CAAA,OAAA,CAAQ,SAAS,OAAO,CAAA,CAAA;AACvC,IAAO,OAAA,MAAM,eAAe,UAAW,EAAA,CAAA;AAAA,GAC3C,EAAG,CAAC,QAAQ,CAAC,CAAA,CAAA;AACb,EAAO,OAAA,UAAA,CAAA;AACX;;;;"}
1
+ {"version":3,"file":"ResultList.js","sources":["ResultList.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Box } from \"@open-pioneer/chakra-integration\";\nimport {\n BaseFeature,\n HighlightOptions,\n HighlightZoomOptions,\n useMapModel\n} from \"@open-pioneer/map\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { FC, ReactNode, RefObject, useEffect, useMemo, useRef, useState } from \"react\";\nimport { DataTable } from \"./DataTable/DataTable\";\nimport { createColumns } from \"./DataTable/createColumns\";\nimport { FormatNumberOptions } from \"@formatjs/intl\";\n\n/**\n * Configures a column in the result list component.\n *\n * A column typically renders a property from the underlying feature.\n */\nexport interface ResultColumn {\n /**\n * Use this option to define an explicit column id.\n * This can be helpful to track your column when it moves in the table (for example, the sort order can be maintained).\n *\n * If this is not defined, {@link propertyName} will serve as a fallback.\n * If that is also not defined, the column index will be used instead.\n *\n * It is recommended to specify an id, if no {@link propertyName} has been set, because the\n * column index fallback is not advised.\n */\n id?: string;\n\n /**\n * The display name of this column.\n *\n * If no `displayName` has been configured, {@link propertyName} will serve as a fallback value.\n * If `propertyName` is also undefined, no column header will be rendered at all.\n */\n displayName?: string;\n\n /**\n * The width of this column, in pixels.\n */\n width?: number;\n\n /**\n * The property name to render.\n *\n * The value is expected to be available as `feature.properties[propertyName]`.\n *\n * See also {@link getPropertyValue}.\n */\n propertyName?: string;\n\n /**\n * Define this function to return a custom property value for this column.\n *\n * This can be used to create derived columns (by combining multiple properties into one value)\n * or to create columns for property that don't exist directly on the feature.\n *\n * The return value of this function will be rendered by the table.\n */\n getPropertyValue?: (feature: BaseFeature) => unknown;\n\n /** Custom render function to render a table cell in this column. */\n renderCell?: (context: RenderCellContext) => ReactNode;\n}\n\n/**\n * The arguments passed to {@link ResultColumn.renderCell | renderCell}.\n */\nexport interface RenderCellContext {\n /**\n * The feature in this row.\n */\n feature: BaseFeature;\n\n /**\n * The value of this column.\n * May be undefined if neither `propertyName` nor `getPropertyValue` was specified on the column.\n */\n value: unknown;\n}\n\n/**\n * To specify the format of cell values if they are of number or date type.\n */\nexport interface FormatOptions {\n /**\n * To specify the format of number type values\n */\n numberOptions?: FormatNumberOptions;\n /**\n * To specify the format of date type values\n */\n dateOptions?: Intl.DateTimeFormatOptions;\n}\n\n/**\n * Configures the result list's content.\n */\nexport interface ResultListInput {\n /**\n * Configures the columns shown by the result list.\n */\n columns: ResultColumn[];\n\n /**\n * The data shown by the result list component.\n * Every feature will be rendered as an individual row.\n */\n data: BaseFeature[];\n\n /**\n * Optional formatOptions to specify the `numberOptions` for number type values and\n * `dateOptions` to specify the format of date type values\n */\n formatOptions?: FormatOptions;\n}\n\n/**\n * Emitted when the selection within the ResultList changes.\n */\nexport interface ResultListSelectionChangeEvent {\n features: BaseFeature[];\n getFeatureIds: () => (number | string)[];\n}\n\n/**\n * Properties supported by the {@link ResultList} component.\n */\nexport interface ResultListProps extends CommonComponentProps {\n /**\n * The id of the map.\n */\n mapId: string;\n\n /**\n * Describes the data rendered by the component.\n */\n input: ResultListInput;\n\n /**\n * This handler is called whenever the user has changed the selected features in the result-list.\n */\n onSelectionChange?: (event: ResultListSelectionChangeEvent) => void;\n\n /**\n * Specifies if the map should zoom to features when they are loaded into the result-list. Defaults to true.\n */\n enableZoom?: boolean;\n\n /**\n * Should data be highlighted in the map. Default true.\n */\n enableHighlight?: boolean;\n\n /**\n * Optional styling option\n */\n highlightOptions?: HighlightOptions;\n\n /**\n * Optional zooming options\n */\n highlightZoomOptions?: HighlightZoomOptions;\n}\n\n/**\n * A component that displays a set of features as a list.\n */\nexport const ResultList: FC<ResultListProps> = (props) => {\n const { containerProps } = useCommonComponentProps(\"result-list\", props);\n const intl = useIntl();\n const {\n mapId,\n input: { data, columns, formatOptions },\n onSelectionChange,\n enableZoom = true,\n highlightZoomOptions,\n enableHighlight = true,\n highlightOptions\n } = props;\n\n const { map } = useMapModel(mapId);\n\n if (columns.length === 0) {\n throw Error(\"No columns were defined. The result list cannot be displayed.\");\n }\n\n const containerRef = useRef<HTMLDivElement>(null);\n const tableWidth = useTableWidth(containerRef);\n const dataTableColumns = useMemo(\n () =>\n createColumns({\n columns: columns,\n intl: intl,\n tableWidth: tableWidth,\n formatOptions: formatOptions\n }),\n [columns, intl, tableWidth, formatOptions]\n );\n\n useEffect(() => {\n if (!map) {\n return;\n }\n if (enableZoom) {\n map.zoom(data, highlightZoomOptions);\n }\n\n if (enableHighlight) {\n const highlight = map.highlight(data, highlightOptions);\n return () => highlight.destroy();\n }\n }, [map, data, highlightZoomOptions, enableZoom, enableHighlight, highlightOptions]);\n\n return (\n <Box {...containerProps} height=\"100%\" overflowY=\"auto\" ref={containerRef}>\n <DataTable\n columns={dataTableColumns}\n data={data}\n onSelectionChange={onSelectionChange}\n />\n </Box>\n );\n};\n\nfunction useTableWidth(tableRef: RefObject<HTMLDivElement> | null) {\n const [tableWidth, setTableWidth] = useState<number>();\n\n useEffect(() => {\n if (!tableRef?.current) return;\n const resizeObserver = new ResizeObserver((event) => {\n // Depending on the layout, you may need to swap inlineSize with blockSize\n // https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry/contentBoxSize\n const width = event[0]?.contentBoxSize[0]?.inlineSize;\n if (width != null) {\n setTableWidth(width);\n }\n });\n resizeObserver.observe(tableRef.current);\n return () => resizeObserver.disconnect();\n }, [tableRef]);\n return tableWidth;\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@open-pioneer/result-list",
4
- "version": "0.1.0",
4
+ "version": "0.2.0",
5
5
  "description": "This package provides a UI component to display features and their attributes.",
6
6
  "keywords": [
7
7
  "open-pioneer-trails"
@@ -22,8 +22,8 @@
22
22
  "classnames": "^2.3.2",
23
23
  "@chakra-ui/icons": "^2.1.1",
24
24
  "@tanstack/react-table": "^8.11.6",
25
- "@open-pioneer/map": "^0.4.0",
26
- "@open-pioneer/react-utils": "^0.2.2"
25
+ "@open-pioneer/react-utils": "^0.2.2",
26
+ "@open-pioneer/map": "^0.5.0"
27
27
  },
28
28
  "exports": {
29
29
  "./package.json": "./package.json",