From 5589a6f801d6b424eb71f784d74e678f239b191f Mon Sep 17 00:00:00 2001 From: Tom Hicks Date: Mon, 17 Mar 2025 15:48:01 +0100 Subject: [PATCH 1/5] Fix various doc examples and add better Filters docs --- docs/Elements/ElementsController.md | 2 +- docs/Layers/Filters.md | 77 ++++++- docs/Layers/LayersController.md | 4 +- docs/Main/FeltController.md | 12 +- docs/Tools/ToolsController.md | 6 +- etc/js-sdk.api.md | 212 +++++++++--------- src/modules/elements/controller.ts | 2 +- src/modules/layers/controller.ts | 6 +- .../{filter.types.ts => filters/types.ts} | 77 ++++++- src/modules/layers/index.ts | 2 +- src/modules/layers/schema.ts | 2 +- src/modules/layers/stats/types.ts | 2 +- src/modules/tools/controller.ts | 6 +- 13 files changed, 274 insertions(+), 136 deletions(-) rename src/modules/layers/{filter.types.ts => filters/types.ts} (59%) diff --git a/docs/Elements/ElementsController.md b/docs/Elements/ElementsController.md index 2c8c9bb..3b1e2f7 100644 --- a/docs/Elements/ElementsController.md +++ b/docs/Elements/ElementsController.md @@ -114,7 +114,7 @@ The requested element group. ### Example ```typescript -felt.getElementGroup("element-group-1"); +const elementGroup = await felt.getElementGroup("element-group-1"); ``` *** diff --git a/docs/Layers/Filters.md b/docs/Layers/Filters.md index 10ef05c..43045dd 100644 --- a/docs/Layers/Filters.md +++ b/docs/Layers/Filters.md @@ -5,6 +5,10 @@ Filters can be used to change which features in a layer are rendered. Filters can be applied to a layer by the `setLayerFilters` method on the Felt controller. +Filters use a tree structure for combining multiple conditions with logical operators. +When combining three or more conditions, you must use proper nesting rather than a flat list. +See the examples below for the correct structure to use when building complex filters. + # Remarks The possible operators are: @@ -26,15 +30,80 @@ The allowed boolean operators are: # Example ```typescript -// a simple filter +// 1. Simple filter: single condition felt.setLayerFilters({ layerId: "layer-1", filters: ["AREA", "gt", 30_000], }); -// compound filters can be constructed using boolean logic: +// 2. Basic compound filter: two conditions with AND +felt.setLayerFilters({ + layerId: "layer-1", + filters: [ + ["AREA", "gt", 30_000], // First condition + "and", // Logic operator + ["COLOR", "eq", "red"] // Second condition + ] +}); + +// 3. Complex filter: three or more conditions require nesting +// ⚠️ IMPORTANT: Filters use a tree structure, not a flat list +felt.setLayerFilters({ + layerId: "layer-1", + filters: [ + ["AREA", "gt", 30_000], // First condition + "and", // First logic operator + [ // Nested group starts + ["COLOR", "eq", "red"], // Second condition + "and", // Second logic operator + ["TYPE", "eq", "residential"] // Third condition + ] // Nested group ends + ] +}); + +// 4. Even more complex: four conditions with proper nesting +// Visual structure: +// AND +// / \ +// condition AND +// / \ +// condition AND +// / \ +// condition condition felt.setLayerFilters({ layerId: "layer-1", - filters: [["AREA", "gt", 30_000], "and", ["COLOR", "eq", "red"]] -}) + filters: [ + ["AREA", "gt", 30_000], // First condition + "and", + [ + ["COLOR", "eq", "red"], // Second condition + "and", + [ + ["TYPE", "eq", "residential"], // Third condition + "and", + ["YEAR", "gt", 2000] // Fourth condition + ] + ] + ] +}); + +// 5. Mixed operators: combining AND and OR +// Visual structure: +// AND +// / \ +// condition OR +// / \ +// condition condition +felt.setLayerFilters({ + layerId: "layer-1", + filters: [ + ["AREA", "gt", 30_000], // Must have large area + "and", + [ + ["COLOR", "eq", "red"], // Must be either red + "or", + ["TYPE", "eq", "residential"] // OR residential type + ] + ] +}); ``` diff --git a/docs/Layers/LayersController.md b/docs/Layers/LayersController.md index 3bc8611..cec1e8c 100644 --- a/docs/Layers/LayersController.md +++ b/docs/Layers/LayersController.md @@ -33,7 +33,7 @@ The requested layer. ### Example ```typescript -const layers = await felt.getLayer({ ids: ["layer-1", "layer-2"] }); +const layer = await felt.getLayer("layer-1"); ``` *** @@ -185,7 +185,7 @@ The requested layer group. ### Example ```typescript -felt.getLayerGroup("layer-group-1"); +const layerGroup = await felt.getLayerGroup("layer-group-1"); ``` *** diff --git a/docs/Main/FeltController.md b/docs/Main/FeltController.md index 2dae863..761e7a9 100644 --- a/docs/Main/FeltController.md +++ b/docs/Main/FeltController.md @@ -127,7 +127,7 @@ The requested element group. ### Example ```typescript -felt.getElementGroup("element-group-1"); +const elementGroup = await felt.getElementGroup("element-group-1"); ``` *** @@ -264,7 +264,7 @@ The requested layer. ### Example ```typescript -const layers = await felt.getLayer({ ids: ["layer-1", "layer-2"] }); +const layer = await felt.getLayer("layer-1"); ``` *** @@ -416,7 +416,7 @@ The requested layer group. ### Example ```typescript -felt.getLayerGroup("layer-group-1"); +const layerGroup = await felt.getLayerGroup("layer-group-1"); ``` *** @@ -993,7 +993,7 @@ Sets the tool to use for drawing elements on the map. ### Example -```ts +```typescript // Set the tool to "marker" felt.setTool("marker"); @@ -1017,7 +1017,7 @@ The current tool, or `null` if no tool is in use. ### Example -```ts +```typescript const tool = await felt.getTool(); // "marker", "polygon", etc. ``` @@ -1044,7 +1044,7 @@ A function to unsubscribe from the listener ### Example -```ts +```typescript const unsubscribe = felt.onToolChange({ handler: tool => console.log(tool), }); diff --git a/docs/Tools/ToolsController.md b/docs/Tools/ToolsController.md index b55c514..2319b48 100644 --- a/docs/Tools/ToolsController.md +++ b/docs/Tools/ToolsController.md @@ -26,7 +26,7 @@ Sets the tool to use for drawing elements on the map. ### Example -```ts +```typescript // Set the tool to "marker" felt.setTool("marker"); @@ -50,7 +50,7 @@ The current tool, or `null` if no tool is in use. ### Example -```ts +```typescript const tool = await felt.getTool(); // "marker", "polygon", etc. ``` @@ -77,7 +77,7 @@ A function to unsubscribe from the listener ### Example -```ts +```typescript const unsubscribe = felt.onToolChange({ handler: tool => console.log(tool), }); diff --git a/etc/js-sdk.api.md b/etc/js-sdk.api.md index 248fa5f..4a0ba83 100644 --- a/etc/js-sdk.api.md +++ b/etc/js-sdk.api.md @@ -4,112 +4,112 @@ ```ts -import { ao as AggregationConfig } from './types-CQwkpLq-.js'; -import { A as AggregationMethod } from './types-CQwkpLq-.js'; -import { Q as CircleElementCreate } from './types-CQwkpLq-.js'; -import { R as CircleElementRead } from './types-CQwkpLq-.js'; -import { U as CircleElementUpdate } from './types-CQwkpLq-.js'; -import { aF as CircleToolSettings } from './types-CQwkpLq-.js'; -import { C as ConfigurableToolType } from './types-CQwkpLq-.js'; -import { E as Element_2 } from './types-CQwkpLq-.js'; -import { d as ElementChangeCallbackParams } from './types-CQwkpLq-.js'; -import { f as ElementCreate } from './types-CQwkpLq-.js'; -import { b as ElementGroup } from './types-CQwkpLq-.js'; -import { e as ElementGroupChangeCallbackParams } from './types-CQwkpLq-.js'; -import { ar as ElementGroupNode } from './types-CQwkpLq-.js'; -import { as as ElementNode } from './types-CQwkpLq-.js'; -import { g as ElementUpdate } from './types-CQwkpLq-.js'; -import { z as EntityNode } from './types-CQwkpLq-.js'; -import { s as Feature } from './types-CQwkpLq-.js'; -import { at as FeatureNode } from './types-CQwkpLq-.js'; -import { B as FeatureSelection } from './types-CQwkpLq-.js'; -import { aw as FeltBoundary } from './types-CQwkpLq-.js'; -import { ax as FeltZoom } from './types-CQwkpLq-.js'; -import { al as FilterExpression } from './types-CQwkpLq-.js'; -import { am as FilterLogicGate } from './types-CQwkpLq-.js'; -import { F as Filters } from './types-CQwkpLq-.js'; -import { an as FilterTernary } from './types-CQwkpLq-.js'; -import { G as Geometry } from './types-CQwkpLq-.js'; -import { c as GetElementGroupsConstraint } from './types-CQwkpLq-.js'; -import { a as GetElementsConstraint } from './types-CQwkpLq-.js'; -import { x as GetLayerCalculationParams } from './types-CQwkpLq-.js'; -import { u as GetLayerCategoriesGroup } from './types-CQwkpLq-.js'; -import { t as GetLayerCategoriesParams } from './types-CQwkpLq-.js'; -import { k as GetLayerGroupsConstraint } from './types-CQwkpLq-.js'; -import { w as GetLayerHistogramBin } from './types-CQwkpLq-.js'; -import { v as GetLayerHistogramParams } from './types-CQwkpLq-.js'; -import { h as GetLayersConstraint } from './types-CQwkpLq-.js'; -import { r as GetRenderedFeaturesConstraint } from './types-CQwkpLq-.js'; -import { W as HighlighterElementCreate } from './types-CQwkpLq-.js'; -import { X as HighlighterElementRead } from './types-CQwkpLq-.js'; -import { Y as HighlighterElementUpdate } from './types-CQwkpLq-.js'; -import { aG as HighlighterToolSettings } from './types-CQwkpLq-.js'; -import { Z as ImageElementCreate } from './types-CQwkpLq-.js'; -import { _ as ImageElementRead } from './types-CQwkpLq-.js'; -import { $ as ImageElementUpdate } from './types-CQwkpLq-.js'; -import { I as InputToolSettings } from './types-CQwkpLq-.js'; -import { J } from './types-CQwkpLq-.js'; -import { ay as LatLng } from './types-CQwkpLq-.js'; -import { L as Layer } from './types-CQwkpLq-.js'; -import { i as LayerChangeCallbackParams } from './types-CQwkpLq-.js'; -import { q as LayerFilters } from './types-CQwkpLq-.js'; -import { j as LayerGroup } from './types-CQwkpLq-.js'; -import { l as LayerGroupChangeCallbackParams } from './types-CQwkpLq-.js'; -import { au as LayerGroupNode } from './types-CQwkpLq-.js'; -import { av as LayerNode } from './types-CQwkpLq-.js'; -import { aj as LayerProcessingStatus } from './types-CQwkpLq-.js'; -import { n as LegendItem } from './types-CQwkpLq-.js'; -import { p as LegendItemChangeCallbackParams } from './types-CQwkpLq-.js'; -import { m as LegendItemIdentifier } from './types-CQwkpLq-.js'; -import { o as LegendItemsConstraint } from './types-CQwkpLq-.js'; -import { az as LineStringGeometry } from './types-CQwkpLq-.js'; -import { aH as LineToolSettings } from './types-CQwkpLq-.js'; -import { a0 as LinkElementRead } from './types-CQwkpLq-.js'; -import { aA as LngLatTuple } from './types-CQwkpLq-.js'; -import { y as MapDetails } from './types-CQwkpLq-.js'; -import { M as MapInteractionEvent } from './types-CQwkpLq-.js'; -import { a1 as MarkerElementCreate } from './types-CQwkpLq-.js'; -import { a2 as MarkerElementRead } from './types-CQwkpLq-.js'; -import { a3 as MarkerElementUpdate } from './types-CQwkpLq-.js'; -import { aI as MarkerToolSettings } from './types-CQwkpLq-.js'; -import { ap as MultiAggregationConfig } from './types-CQwkpLq-.js'; -import { aB as MultiLineStringGeometry } from './types-CQwkpLq-.js'; -import { aC as MultiPolygonGeometry } from './types-CQwkpLq-.js'; -import { a4 as NoteElementCreate } from './types-CQwkpLq-.js'; -import { a5 as NoteElementRead } from './types-CQwkpLq-.js'; -import { a6 as NoteElementUpdate } from './types-CQwkpLq-.js'; -import { aJ as NoteToolSettings } from './types-CQwkpLq-.js'; -import { a7 as PathElementCreate } from './types-CQwkpLq-.js'; -import { a8 as PathElementRead } from './types-CQwkpLq-.js'; -import { a9 as PathElementUpdate } from './types-CQwkpLq-.js'; -import { aK as PinToolSettings } from './types-CQwkpLq-.js'; -import { aa as PlaceElementCreate } from './types-CQwkpLq-.js'; -import { ab as PlaceElementRead } from './types-CQwkpLq-.js'; -import { ac as PlaceElementUpdate } from './types-CQwkpLq-.js'; -import { aL as PlaceFrame } from './types-CQwkpLq-.js'; -import { aM as PlaceSymbol } from './types-CQwkpLq-.js'; -import { aD as PointGeometry } from './types-CQwkpLq-.js'; -import { ad as PolygonElementCreate } from './types-CQwkpLq-.js'; -import { ae as PolygonElementRead } from './types-CQwkpLq-.js'; -import { af as PolygonElementUpdate } from './types-CQwkpLq-.js'; -import { aE as PolygonGeometry } from './types-CQwkpLq-.js'; -import { aN as PolygonToolSettings } from './types-CQwkpLq-.js'; -import { ak as RasterValue } from './types-CQwkpLq-.js'; -import { aO as RouteToolSettings } from './types-CQwkpLq-.js'; -import { K as SetViewportCenterZoomParams } from './types-CQwkpLq-.js'; -import { S as SetVisibilityRequest } from './types-CQwkpLq-.js'; -import { ag as TextElementCreate } from './types-CQwkpLq-.js'; -import { ah as TextElementRead } from './types-CQwkpLq-.js'; -import { ai as TextElementUpdate } from './types-CQwkpLq-.js'; -import { aP as TextToolSettings } from './types-CQwkpLq-.js'; -import { H as ToolSettingsChangeEvent } from './types-CQwkpLq-.js'; -import { D as ToolSettingsMap } from './types-CQwkpLq-.js'; -import { T as ToolType } from './types-CQwkpLq-.js'; -import { aq as ValueConfiguration } from './types-CQwkpLq-.js'; -import { P as ViewportCenterZoom } from './types-CQwkpLq-.js'; -import { N as ViewportConstraints } from './types-CQwkpLq-.js'; -import { O as ViewportFitBoundsParams } from './types-CQwkpLq-.js'; -import { V as ViewportState } from './types-CQwkpLq-.js'; +import { ao as AggregationConfig } from './types-BaxtdUbR.js'; +import { A as AggregationMethod } from './types-BaxtdUbR.js'; +import { Q as CircleElementCreate } from './types-BaxtdUbR.js'; +import { R as CircleElementRead } from './types-BaxtdUbR.js'; +import { U as CircleElementUpdate } from './types-BaxtdUbR.js'; +import { aF as CircleToolSettings } from './types-BaxtdUbR.js'; +import { C as ConfigurableToolType } from './types-BaxtdUbR.js'; +import { E as Element_2 } from './types-BaxtdUbR.js'; +import { d as ElementChangeCallbackParams } from './types-BaxtdUbR.js'; +import { f as ElementCreate } from './types-BaxtdUbR.js'; +import { b as ElementGroup } from './types-BaxtdUbR.js'; +import { e as ElementGroupChangeCallbackParams } from './types-BaxtdUbR.js'; +import { ar as ElementGroupNode } from './types-BaxtdUbR.js'; +import { as as ElementNode } from './types-BaxtdUbR.js'; +import { g as ElementUpdate } from './types-BaxtdUbR.js'; +import { z as EntityNode } from './types-BaxtdUbR.js'; +import { s as Feature } from './types-BaxtdUbR.js'; +import { at as FeatureNode } from './types-BaxtdUbR.js'; +import { B as FeatureSelection } from './types-BaxtdUbR.js'; +import { aw as FeltBoundary } from './types-BaxtdUbR.js'; +import { ax as FeltZoom } from './types-BaxtdUbR.js'; +import { al as FilterExpression } from './types-BaxtdUbR.js'; +import { am as FilterLogicGate } from './types-BaxtdUbR.js'; +import { F as Filters } from './types-BaxtdUbR.js'; +import { an as FilterTernary } from './types-BaxtdUbR.js'; +import { G as Geometry } from './types-BaxtdUbR.js'; +import { c as GetElementGroupsConstraint } from './types-BaxtdUbR.js'; +import { a as GetElementsConstraint } from './types-BaxtdUbR.js'; +import { x as GetLayerCalculationParams } from './types-BaxtdUbR.js'; +import { u as GetLayerCategoriesGroup } from './types-BaxtdUbR.js'; +import { t as GetLayerCategoriesParams } from './types-BaxtdUbR.js'; +import { k as GetLayerGroupsConstraint } from './types-BaxtdUbR.js'; +import { w as GetLayerHistogramBin } from './types-BaxtdUbR.js'; +import { v as GetLayerHistogramParams } from './types-BaxtdUbR.js'; +import { h as GetLayersConstraint } from './types-BaxtdUbR.js'; +import { r as GetRenderedFeaturesConstraint } from './types-BaxtdUbR.js'; +import { W as HighlighterElementCreate } from './types-BaxtdUbR.js'; +import { X as HighlighterElementRead } from './types-BaxtdUbR.js'; +import { Y as HighlighterElementUpdate } from './types-BaxtdUbR.js'; +import { aG as HighlighterToolSettings } from './types-BaxtdUbR.js'; +import { Z as ImageElementCreate } from './types-BaxtdUbR.js'; +import { _ as ImageElementRead } from './types-BaxtdUbR.js'; +import { $ as ImageElementUpdate } from './types-BaxtdUbR.js'; +import { I as InputToolSettings } from './types-BaxtdUbR.js'; +import { J } from './types-BaxtdUbR.js'; +import { ay as LatLng } from './types-BaxtdUbR.js'; +import { L as Layer } from './types-BaxtdUbR.js'; +import { i as LayerChangeCallbackParams } from './types-BaxtdUbR.js'; +import { q as LayerFilters } from './types-BaxtdUbR.js'; +import { j as LayerGroup } from './types-BaxtdUbR.js'; +import { l as LayerGroupChangeCallbackParams } from './types-BaxtdUbR.js'; +import { au as LayerGroupNode } from './types-BaxtdUbR.js'; +import { av as LayerNode } from './types-BaxtdUbR.js'; +import { aj as LayerProcessingStatus } from './types-BaxtdUbR.js'; +import { n as LegendItem } from './types-BaxtdUbR.js'; +import { p as LegendItemChangeCallbackParams } from './types-BaxtdUbR.js'; +import { m as LegendItemIdentifier } from './types-BaxtdUbR.js'; +import { o as LegendItemsConstraint } from './types-BaxtdUbR.js'; +import { az as LineStringGeometry } from './types-BaxtdUbR.js'; +import { aH as LineToolSettings } from './types-BaxtdUbR.js'; +import { a0 as LinkElementRead } from './types-BaxtdUbR.js'; +import { aA as LngLatTuple } from './types-BaxtdUbR.js'; +import { y as MapDetails } from './types-BaxtdUbR.js'; +import { M as MapInteractionEvent } from './types-BaxtdUbR.js'; +import { a1 as MarkerElementCreate } from './types-BaxtdUbR.js'; +import { a2 as MarkerElementRead } from './types-BaxtdUbR.js'; +import { a3 as MarkerElementUpdate } from './types-BaxtdUbR.js'; +import { aI as MarkerToolSettings } from './types-BaxtdUbR.js'; +import { ap as MultiAggregationConfig } from './types-BaxtdUbR.js'; +import { aB as MultiLineStringGeometry } from './types-BaxtdUbR.js'; +import { aC as MultiPolygonGeometry } from './types-BaxtdUbR.js'; +import { a4 as NoteElementCreate } from './types-BaxtdUbR.js'; +import { a5 as NoteElementRead } from './types-BaxtdUbR.js'; +import { a6 as NoteElementUpdate } from './types-BaxtdUbR.js'; +import { aJ as NoteToolSettings } from './types-BaxtdUbR.js'; +import { a7 as PathElementCreate } from './types-BaxtdUbR.js'; +import { a8 as PathElementRead } from './types-BaxtdUbR.js'; +import { a9 as PathElementUpdate } from './types-BaxtdUbR.js'; +import { aK as PinToolSettings } from './types-BaxtdUbR.js'; +import { aa as PlaceElementCreate } from './types-BaxtdUbR.js'; +import { ab as PlaceElementRead } from './types-BaxtdUbR.js'; +import { ac as PlaceElementUpdate } from './types-BaxtdUbR.js'; +import { aL as PlaceFrame } from './types-BaxtdUbR.js'; +import { aM as PlaceSymbol } from './types-BaxtdUbR.js'; +import { aD as PointGeometry } from './types-BaxtdUbR.js'; +import { ad as PolygonElementCreate } from './types-BaxtdUbR.js'; +import { ae as PolygonElementRead } from './types-BaxtdUbR.js'; +import { af as PolygonElementUpdate } from './types-BaxtdUbR.js'; +import { aE as PolygonGeometry } from './types-BaxtdUbR.js'; +import { aN as PolygonToolSettings } from './types-BaxtdUbR.js'; +import { ak as RasterValue } from './types-BaxtdUbR.js'; +import { aO as RouteToolSettings } from './types-BaxtdUbR.js'; +import { K as SetViewportCenterZoomParams } from './types-BaxtdUbR.js'; +import { S as SetVisibilityRequest } from './types-BaxtdUbR.js'; +import { ag as TextElementCreate } from './types-BaxtdUbR.js'; +import { ah as TextElementRead } from './types-BaxtdUbR.js'; +import { ai as TextElementUpdate } from './types-BaxtdUbR.js'; +import { aP as TextToolSettings } from './types-BaxtdUbR.js'; +import { H as ToolSettingsChangeEvent } from './types-BaxtdUbR.js'; +import { D as ToolSettingsMap } from './types-BaxtdUbR.js'; +import { T as ToolType } from './types-BaxtdUbR.js'; +import { aq as ValueConfiguration } from './types-BaxtdUbR.js'; +import { P as ViewportCenterZoom } from './types-BaxtdUbR.js'; +import { N as ViewportConstraints } from './types-BaxtdUbR.js'; +import { O as ViewportFitBoundsParams } from './types-BaxtdUbR.js'; +import { V as ViewportState } from './types-BaxtdUbR.js'; import { z } from 'zod'; export { AggregationConfig } diff --git a/src/modules/elements/controller.ts b/src/modules/elements/controller.ts index afc25a4..f46a2ee 100644 --- a/src/modules/elements/controller.ts +++ b/src/modules/elements/controller.ts @@ -100,7 +100,7 @@ export interface ElementsController { * * @example * ```typescript - * felt.getElementGroup("element-group-1"); + * const elementGroup = await felt.getElementGroup("element-group-1"); * ``` * @returns The requested element group. */ diff --git a/src/modules/layers/controller.ts b/src/modules/layers/controller.ts index 67fc7a9..a7ea1fe 100644 --- a/src/modules/layers/controller.ts +++ b/src/modules/layers/controller.ts @@ -1,6 +1,6 @@ import { listener, method } from "~/lib/interface"; import type { SetVisibilityRequest } from "~/modules/shared/types"; -import type { Filters, LayerFilters } from "./filter.types"; +import type { Filters, LayerFilters } from "./filters/types"; import type { AggregationMethod, GetLayerCalculationParams, @@ -83,7 +83,7 @@ export interface LayersController { * * @example * ```typescript - * const layers = await felt.getLayer({ ids: ["layer-1", "layer-2"] }); + * const layer = await felt.getLayer("layer-1"); * ``` * @returns The requested layer. */ @@ -217,7 +217,7 @@ export interface LayersController { * * @example * ```typescript - * felt.getLayerGroup("layer-group-1"); + * const layerGroup = await felt.getLayerGroup("layer-group-1"); * ``` * @returns The requested layer group. */ diff --git a/src/modules/layers/filter.types.ts b/src/modules/layers/filters/types.ts similarity index 59% rename from src/modules/layers/filter.types.ts rename to src/modules/layers/filters/types.ts index b1e18f5..d887a0f 100644 --- a/src/modules/layers/filter.types.ts +++ b/src/modules/layers/filters/types.ts @@ -83,6 +83,10 @@ const FilterTernarySchema: z.ZodType = z.tuple([ * Filters can be used to change which features in a layer are rendered. Filters can be * applied to a layer by the `setLayerFilters` method on the Felt controller. * + * Filters use a tree structure for combining multiple conditions with logical operators. + * When combining three or more conditions, you must use proper nesting rather than a flat list. + * See the examples below for the correct structure to use when building complex filters. + * * @remarks * The possible operators are: * - `lt`: Less than @@ -100,17 +104,82 @@ const FilterTernarySchema: z.ZodType = z.tuple([ * * @example * ```typescript - * // a simple filter + * // 1. Simple filter: single condition * felt.setLayerFilters({ * layerId: "layer-1", * filters: ["AREA", "gt", 30_000], * }); * - * // compound filters can be constructed using boolean logic: + * // 2. Basic compound filter: two conditions with AND + * felt.setLayerFilters({ + * layerId: "layer-1", + * filters: [ + * ["AREA", "gt", 30_000], // First condition + * "and", // Logic operator + * ["COLOR", "eq", "red"] // Second condition + * ] + * }); + * + * // 3. Complex filter: three or more conditions require nesting + * // ⚠️ IMPORTANT: Filters use a tree structure, not a flat list + * felt.setLayerFilters({ + * layerId: "layer-1", + * filters: [ + * ["AREA", "gt", 30_000], // First condition + * "and", // First logic operator + * [ // Nested group starts + * ["COLOR", "eq", "red"], // Second condition + * "and", // Second logic operator + * ["TYPE", "eq", "residential"] // Third condition + * ] // Nested group ends + * ] + * }); + * + * // 4. Even more complex: four conditions with proper nesting + * // Visual structure: + * // AND + * // / \ + * // condition AND + * // / \ + * // condition AND + * // / \ + * // condition condition * felt.setLayerFilters({ * layerId: "layer-1", - * filters: [["AREA", "gt", 30_000], "and", ["COLOR", "eq", "red"]] - * }) + * filters: [ + * ["AREA", "gt", 30_000], // First condition + * "and", + * [ + * ["COLOR", "eq", "red"], // Second condition + * "and", + * [ + * ["TYPE", "eq", "residential"], // Third condition + * "and", + * ["YEAR", "gt", 2000] // Fourth condition + * ] + * ] + * ] + * }); + * + * // 5. Mixed operators: combining AND and OR + * // Visual structure: + * // AND + * // / \ + * // condition OR + * // / \ + * // condition condition + * felt.setLayerFilters({ + * layerId: "layer-1", + * filters: [ + * ["AREA", "gt", 30_000], // Must have large area + * "and", + * [ + * ["COLOR", "eq", "red"], // Must be either red + * "or", + * ["TYPE", "eq", "residential"] // OR residential type + * ] + * ] + * }); * ``` * * @group Filters diff --git a/src/modules/layers/index.ts b/src/modules/layers/index.ts index 8e68095..1514ae8 100644 --- a/src/modules/layers/index.ts +++ b/src/modules/layers/index.ts @@ -38,7 +38,7 @@ export type { FilterTernary, Filters, LayerFilters, -} from "./filter.types"; +} from "./filters/types"; export type { AggregationConfig, diff --git a/src/modules/layers/schema.ts b/src/modules/layers/schema.ts index 5cf4b7f..d6ae54c 100644 --- a/src/modules/layers/schema.ts +++ b/src/modules/layers/schema.ts @@ -8,7 +8,7 @@ import { } from "~/lib/builders"; import type { zInfer } from "~/lib/utils"; import { SetVisibilityRequestSchema } from "~/modules/shared/types"; -import { FiltersSchema, type LayerFilters } from "./filter.types"; +import { FiltersSchema, type LayerFilters } from "./filters/types"; import { type AggregationMethod, GetLayerCalculationParamsSchema, diff --git a/src/modules/layers/stats/types.ts b/src/modules/layers/stats/types.ts index 7670440..ac1b17f 100644 --- a/src/modules/layers/stats/types.ts +++ b/src/modules/layers/stats/types.ts @@ -9,7 +9,7 @@ import { type PolygonGeometry, } from "~/modules/shared/types"; import type { LayersController } from "../controller"; -import { FiltersSchema, type Filters } from "../filter.types"; +import { FiltersSchema, type Filters } from "../filters/types"; const AggregateMethodSchema = z.enum(["avg", "max", "min", "sum", "median"]); diff --git a/src/modules/tools/controller.ts b/src/modules/tools/controller.ts index b2ed840..527ba59 100644 --- a/src/modules/tools/controller.ts +++ b/src/modules/tools/controller.ts @@ -36,7 +36,7 @@ export interface ToolsController { * @param tool - The tool to set. * * @example - * ```ts + * ```typescript * // Set the tool to "marker" * felt.setTool("marker"); * @@ -52,7 +52,7 @@ export interface ToolsController { * @returns The current tool, or `null` if no tool is in use. * * @example - * ```ts + * ```typescript * const tool = await felt.getTool(); // "marker", "polygon", etc. * ``` */ @@ -64,7 +64,7 @@ export interface ToolsController { * @returns A function to unsubscribe from the listener * * @example - * ```ts + * ```typescript * const unsubscribe = felt.onToolChange({ * handler: tool => console.log(tool), * }); From 648cd695d6f525a0ae82c2cf5bf9d97c0cba5b38 Mon Sep 17 00:00:00 2001 From: Tom Hicks Date: Mon, 17 Mar 2025 16:00:37 +0100 Subject: [PATCH 2/5] Mention FilterTernary --- docs/Layers/Filters.md | 6 +- etc/js-sdk.api.md | 212 ++++++++++++++-------------- src/modules/layers/filters/types.ts | 6 +- 3 files changed, 114 insertions(+), 110 deletions(-) diff --git a/docs/Layers/Filters.md b/docs/Layers/Filters.md index 43045dd..9e16666 100644 --- a/docs/Layers/Filters.md +++ b/docs/Layers/Filters.md @@ -5,8 +5,10 @@ Filters can be used to change which features in a layer are rendered. Filters can be applied to a layer by the `setLayerFilters` method on the Felt controller. -Filters use a tree structure for combining multiple conditions with logical operators. -When combining three or more conditions, you must use proper nesting rather than a flat list. +Filters use a tree structure for combining expressions with logical operators, called a +[FilterTernary](FilterTernary.md). When combining three or more conditions, you must use proper nesting +rather than a flat list. + See the examples below for the correct structure to use when building complex filters. # Remarks diff --git a/etc/js-sdk.api.md b/etc/js-sdk.api.md index 4a0ba83..109c961 100644 --- a/etc/js-sdk.api.md +++ b/etc/js-sdk.api.md @@ -4,112 +4,112 @@ ```ts -import { ao as AggregationConfig } from './types-BaxtdUbR.js'; -import { A as AggregationMethod } from './types-BaxtdUbR.js'; -import { Q as CircleElementCreate } from './types-BaxtdUbR.js'; -import { R as CircleElementRead } from './types-BaxtdUbR.js'; -import { U as CircleElementUpdate } from './types-BaxtdUbR.js'; -import { aF as CircleToolSettings } from './types-BaxtdUbR.js'; -import { C as ConfigurableToolType } from './types-BaxtdUbR.js'; -import { E as Element_2 } from './types-BaxtdUbR.js'; -import { d as ElementChangeCallbackParams } from './types-BaxtdUbR.js'; -import { f as ElementCreate } from './types-BaxtdUbR.js'; -import { b as ElementGroup } from './types-BaxtdUbR.js'; -import { e as ElementGroupChangeCallbackParams } from './types-BaxtdUbR.js'; -import { ar as ElementGroupNode } from './types-BaxtdUbR.js'; -import { as as ElementNode } from './types-BaxtdUbR.js'; -import { g as ElementUpdate } from './types-BaxtdUbR.js'; -import { z as EntityNode } from './types-BaxtdUbR.js'; -import { s as Feature } from './types-BaxtdUbR.js'; -import { at as FeatureNode } from './types-BaxtdUbR.js'; -import { B as FeatureSelection } from './types-BaxtdUbR.js'; -import { aw as FeltBoundary } from './types-BaxtdUbR.js'; -import { ax as FeltZoom } from './types-BaxtdUbR.js'; -import { al as FilterExpression } from './types-BaxtdUbR.js'; -import { am as FilterLogicGate } from './types-BaxtdUbR.js'; -import { F as Filters } from './types-BaxtdUbR.js'; -import { an as FilterTernary } from './types-BaxtdUbR.js'; -import { G as Geometry } from './types-BaxtdUbR.js'; -import { c as GetElementGroupsConstraint } from './types-BaxtdUbR.js'; -import { a as GetElementsConstraint } from './types-BaxtdUbR.js'; -import { x as GetLayerCalculationParams } from './types-BaxtdUbR.js'; -import { u as GetLayerCategoriesGroup } from './types-BaxtdUbR.js'; -import { t as GetLayerCategoriesParams } from './types-BaxtdUbR.js'; -import { k as GetLayerGroupsConstraint } from './types-BaxtdUbR.js'; -import { w as GetLayerHistogramBin } from './types-BaxtdUbR.js'; -import { v as GetLayerHistogramParams } from './types-BaxtdUbR.js'; -import { h as GetLayersConstraint } from './types-BaxtdUbR.js'; -import { r as GetRenderedFeaturesConstraint } from './types-BaxtdUbR.js'; -import { W as HighlighterElementCreate } from './types-BaxtdUbR.js'; -import { X as HighlighterElementRead } from './types-BaxtdUbR.js'; -import { Y as HighlighterElementUpdate } from './types-BaxtdUbR.js'; -import { aG as HighlighterToolSettings } from './types-BaxtdUbR.js'; -import { Z as ImageElementCreate } from './types-BaxtdUbR.js'; -import { _ as ImageElementRead } from './types-BaxtdUbR.js'; -import { $ as ImageElementUpdate } from './types-BaxtdUbR.js'; -import { I as InputToolSettings } from './types-BaxtdUbR.js'; -import { J } from './types-BaxtdUbR.js'; -import { ay as LatLng } from './types-BaxtdUbR.js'; -import { L as Layer } from './types-BaxtdUbR.js'; -import { i as LayerChangeCallbackParams } from './types-BaxtdUbR.js'; -import { q as LayerFilters } from './types-BaxtdUbR.js'; -import { j as LayerGroup } from './types-BaxtdUbR.js'; -import { l as LayerGroupChangeCallbackParams } from './types-BaxtdUbR.js'; -import { au as LayerGroupNode } from './types-BaxtdUbR.js'; -import { av as LayerNode } from './types-BaxtdUbR.js'; -import { aj as LayerProcessingStatus } from './types-BaxtdUbR.js'; -import { n as LegendItem } from './types-BaxtdUbR.js'; -import { p as LegendItemChangeCallbackParams } from './types-BaxtdUbR.js'; -import { m as LegendItemIdentifier } from './types-BaxtdUbR.js'; -import { o as LegendItemsConstraint } from './types-BaxtdUbR.js'; -import { az as LineStringGeometry } from './types-BaxtdUbR.js'; -import { aH as LineToolSettings } from './types-BaxtdUbR.js'; -import { a0 as LinkElementRead } from './types-BaxtdUbR.js'; -import { aA as LngLatTuple } from './types-BaxtdUbR.js'; -import { y as MapDetails } from './types-BaxtdUbR.js'; -import { M as MapInteractionEvent } from './types-BaxtdUbR.js'; -import { a1 as MarkerElementCreate } from './types-BaxtdUbR.js'; -import { a2 as MarkerElementRead } from './types-BaxtdUbR.js'; -import { a3 as MarkerElementUpdate } from './types-BaxtdUbR.js'; -import { aI as MarkerToolSettings } from './types-BaxtdUbR.js'; -import { ap as MultiAggregationConfig } from './types-BaxtdUbR.js'; -import { aB as MultiLineStringGeometry } from './types-BaxtdUbR.js'; -import { aC as MultiPolygonGeometry } from './types-BaxtdUbR.js'; -import { a4 as NoteElementCreate } from './types-BaxtdUbR.js'; -import { a5 as NoteElementRead } from './types-BaxtdUbR.js'; -import { a6 as NoteElementUpdate } from './types-BaxtdUbR.js'; -import { aJ as NoteToolSettings } from './types-BaxtdUbR.js'; -import { a7 as PathElementCreate } from './types-BaxtdUbR.js'; -import { a8 as PathElementRead } from './types-BaxtdUbR.js'; -import { a9 as PathElementUpdate } from './types-BaxtdUbR.js'; -import { aK as PinToolSettings } from './types-BaxtdUbR.js'; -import { aa as PlaceElementCreate } from './types-BaxtdUbR.js'; -import { ab as PlaceElementRead } from './types-BaxtdUbR.js'; -import { ac as PlaceElementUpdate } from './types-BaxtdUbR.js'; -import { aL as PlaceFrame } from './types-BaxtdUbR.js'; -import { aM as PlaceSymbol } from './types-BaxtdUbR.js'; -import { aD as PointGeometry } from './types-BaxtdUbR.js'; -import { ad as PolygonElementCreate } from './types-BaxtdUbR.js'; -import { ae as PolygonElementRead } from './types-BaxtdUbR.js'; -import { af as PolygonElementUpdate } from './types-BaxtdUbR.js'; -import { aE as PolygonGeometry } from './types-BaxtdUbR.js'; -import { aN as PolygonToolSettings } from './types-BaxtdUbR.js'; -import { ak as RasterValue } from './types-BaxtdUbR.js'; -import { aO as RouteToolSettings } from './types-BaxtdUbR.js'; -import { K as SetViewportCenterZoomParams } from './types-BaxtdUbR.js'; -import { S as SetVisibilityRequest } from './types-BaxtdUbR.js'; -import { ag as TextElementCreate } from './types-BaxtdUbR.js'; -import { ah as TextElementRead } from './types-BaxtdUbR.js'; -import { ai as TextElementUpdate } from './types-BaxtdUbR.js'; -import { aP as TextToolSettings } from './types-BaxtdUbR.js'; -import { H as ToolSettingsChangeEvent } from './types-BaxtdUbR.js'; -import { D as ToolSettingsMap } from './types-BaxtdUbR.js'; -import { T as ToolType } from './types-BaxtdUbR.js'; -import { aq as ValueConfiguration } from './types-BaxtdUbR.js'; -import { P as ViewportCenterZoom } from './types-BaxtdUbR.js'; -import { N as ViewportConstraints } from './types-BaxtdUbR.js'; -import { O as ViewportFitBoundsParams } from './types-BaxtdUbR.js'; -import { V as ViewportState } from './types-BaxtdUbR.js'; +import { ao as AggregationConfig } from './types-CB19v92x.js'; +import { A as AggregationMethod } from './types-CB19v92x.js'; +import { Q as CircleElementCreate } from './types-CB19v92x.js'; +import { R as CircleElementRead } from './types-CB19v92x.js'; +import { U as CircleElementUpdate } from './types-CB19v92x.js'; +import { aF as CircleToolSettings } from './types-CB19v92x.js'; +import { C as ConfigurableToolType } from './types-CB19v92x.js'; +import { E as Element_2 } from './types-CB19v92x.js'; +import { d as ElementChangeCallbackParams } from './types-CB19v92x.js'; +import { f as ElementCreate } from './types-CB19v92x.js'; +import { b as ElementGroup } from './types-CB19v92x.js'; +import { e as ElementGroupChangeCallbackParams } from './types-CB19v92x.js'; +import { ar as ElementGroupNode } from './types-CB19v92x.js'; +import { as as ElementNode } from './types-CB19v92x.js'; +import { g as ElementUpdate } from './types-CB19v92x.js'; +import { z as EntityNode } from './types-CB19v92x.js'; +import { s as Feature } from './types-CB19v92x.js'; +import { at as FeatureNode } from './types-CB19v92x.js'; +import { B as FeatureSelection } from './types-CB19v92x.js'; +import { aw as FeltBoundary } from './types-CB19v92x.js'; +import { ax as FeltZoom } from './types-CB19v92x.js'; +import { al as FilterExpression } from './types-CB19v92x.js'; +import { am as FilterLogicGate } from './types-CB19v92x.js'; +import { F as Filters } from './types-CB19v92x.js'; +import { an as FilterTernary } from './types-CB19v92x.js'; +import { G as Geometry } from './types-CB19v92x.js'; +import { c as GetElementGroupsConstraint } from './types-CB19v92x.js'; +import { a as GetElementsConstraint } from './types-CB19v92x.js'; +import { x as GetLayerCalculationParams } from './types-CB19v92x.js'; +import { u as GetLayerCategoriesGroup } from './types-CB19v92x.js'; +import { t as GetLayerCategoriesParams } from './types-CB19v92x.js'; +import { k as GetLayerGroupsConstraint } from './types-CB19v92x.js'; +import { w as GetLayerHistogramBin } from './types-CB19v92x.js'; +import { v as GetLayerHistogramParams } from './types-CB19v92x.js'; +import { h as GetLayersConstraint } from './types-CB19v92x.js'; +import { r as GetRenderedFeaturesConstraint } from './types-CB19v92x.js'; +import { W as HighlighterElementCreate } from './types-CB19v92x.js'; +import { X as HighlighterElementRead } from './types-CB19v92x.js'; +import { Y as HighlighterElementUpdate } from './types-CB19v92x.js'; +import { aG as HighlighterToolSettings } from './types-CB19v92x.js'; +import { Z as ImageElementCreate } from './types-CB19v92x.js'; +import { _ as ImageElementRead } from './types-CB19v92x.js'; +import { $ as ImageElementUpdate } from './types-CB19v92x.js'; +import { I as InputToolSettings } from './types-CB19v92x.js'; +import { J } from './types-CB19v92x.js'; +import { ay as LatLng } from './types-CB19v92x.js'; +import { L as Layer } from './types-CB19v92x.js'; +import { i as LayerChangeCallbackParams } from './types-CB19v92x.js'; +import { q as LayerFilters } from './types-CB19v92x.js'; +import { j as LayerGroup } from './types-CB19v92x.js'; +import { l as LayerGroupChangeCallbackParams } from './types-CB19v92x.js'; +import { au as LayerGroupNode } from './types-CB19v92x.js'; +import { av as LayerNode } from './types-CB19v92x.js'; +import { aj as LayerProcessingStatus } from './types-CB19v92x.js'; +import { n as LegendItem } from './types-CB19v92x.js'; +import { p as LegendItemChangeCallbackParams } from './types-CB19v92x.js'; +import { m as LegendItemIdentifier } from './types-CB19v92x.js'; +import { o as LegendItemsConstraint } from './types-CB19v92x.js'; +import { az as LineStringGeometry } from './types-CB19v92x.js'; +import { aH as LineToolSettings } from './types-CB19v92x.js'; +import { a0 as LinkElementRead } from './types-CB19v92x.js'; +import { aA as LngLatTuple } from './types-CB19v92x.js'; +import { y as MapDetails } from './types-CB19v92x.js'; +import { M as MapInteractionEvent } from './types-CB19v92x.js'; +import { a1 as MarkerElementCreate } from './types-CB19v92x.js'; +import { a2 as MarkerElementRead } from './types-CB19v92x.js'; +import { a3 as MarkerElementUpdate } from './types-CB19v92x.js'; +import { aI as MarkerToolSettings } from './types-CB19v92x.js'; +import { ap as MultiAggregationConfig } from './types-CB19v92x.js'; +import { aB as MultiLineStringGeometry } from './types-CB19v92x.js'; +import { aC as MultiPolygonGeometry } from './types-CB19v92x.js'; +import { a4 as NoteElementCreate } from './types-CB19v92x.js'; +import { a5 as NoteElementRead } from './types-CB19v92x.js'; +import { a6 as NoteElementUpdate } from './types-CB19v92x.js'; +import { aJ as NoteToolSettings } from './types-CB19v92x.js'; +import { a7 as PathElementCreate } from './types-CB19v92x.js'; +import { a8 as PathElementRead } from './types-CB19v92x.js'; +import { a9 as PathElementUpdate } from './types-CB19v92x.js'; +import { aK as PinToolSettings } from './types-CB19v92x.js'; +import { aa as PlaceElementCreate } from './types-CB19v92x.js'; +import { ab as PlaceElementRead } from './types-CB19v92x.js'; +import { ac as PlaceElementUpdate } from './types-CB19v92x.js'; +import { aL as PlaceFrame } from './types-CB19v92x.js'; +import { aM as PlaceSymbol } from './types-CB19v92x.js'; +import { aD as PointGeometry } from './types-CB19v92x.js'; +import { ad as PolygonElementCreate } from './types-CB19v92x.js'; +import { ae as PolygonElementRead } from './types-CB19v92x.js'; +import { af as PolygonElementUpdate } from './types-CB19v92x.js'; +import { aE as PolygonGeometry } from './types-CB19v92x.js'; +import { aN as PolygonToolSettings } from './types-CB19v92x.js'; +import { ak as RasterValue } from './types-CB19v92x.js'; +import { aO as RouteToolSettings } from './types-CB19v92x.js'; +import { K as SetViewportCenterZoomParams } from './types-CB19v92x.js'; +import { S as SetVisibilityRequest } from './types-CB19v92x.js'; +import { ag as TextElementCreate } from './types-CB19v92x.js'; +import { ah as TextElementRead } from './types-CB19v92x.js'; +import { ai as TextElementUpdate } from './types-CB19v92x.js'; +import { aP as TextToolSettings } from './types-CB19v92x.js'; +import { H as ToolSettingsChangeEvent } from './types-CB19v92x.js'; +import { D as ToolSettingsMap } from './types-CB19v92x.js'; +import { T as ToolType } from './types-CB19v92x.js'; +import { aq as ValueConfiguration } from './types-CB19v92x.js'; +import { P as ViewportCenterZoom } from './types-CB19v92x.js'; +import { N as ViewportConstraints } from './types-CB19v92x.js'; +import { O as ViewportFitBoundsParams } from './types-CB19v92x.js'; +import { V as ViewportState } from './types-CB19v92x.js'; import { z } from 'zod'; export { AggregationConfig } diff --git a/src/modules/layers/filters/types.ts b/src/modules/layers/filters/types.ts index d887a0f..86fdef3 100644 --- a/src/modules/layers/filters/types.ts +++ b/src/modules/layers/filters/types.ts @@ -83,8 +83,10 @@ const FilterTernarySchema: z.ZodType = z.tuple([ * Filters can be used to change which features in a layer are rendered. Filters can be * applied to a layer by the `setLayerFilters` method on the Felt controller. * - * Filters use a tree structure for combining multiple conditions with logical operators. - * When combining three or more conditions, you must use proper nesting rather than a flat list. + * Filters use a tree structure for combining expressions with logical operators, called a + * {@link FilterTernary}. When combining three or more conditions, you must use proper nesting + * rather than a flat list. + * * See the examples below for the correct structure to use when building complex filters. * * @remarks From b9b45297b234cb414b9e9185ecbd9591d55bc0bc Mon Sep 17 00:00:00 2001 From: Tom Hicks Date: Mon, 17 Mar 2025 16:02:22 +0100 Subject: [PATCH 3/5] Improve docs for filter ternaries --- docs/Layers/FilterTernary.md | 26 ++++ etc/js-sdk.api.md | 212 ++++++++++++++-------------- src/modules/layers/filters/types.ts | 25 ++++ 3 files changed, 157 insertions(+), 106 deletions(-) diff --git a/docs/Layers/FilterTernary.md b/docs/Layers/FilterTernary.md index 0d69b7a..dc8bc85 100644 --- a/docs/Layers/FilterTernary.md +++ b/docs/Layers/FilterTernary.md @@ -1,3 +1,29 @@ *** > **FilterTernary**: \[[`FilterTernary`](FilterTernary.md) | [`FilterExpression`](FilterExpression.md) | `null` | `boolean`, [`FilterLogicGate`](FilterLogicGate.md), [`FilterTernary`](FilterTernary.md) | [`FilterExpression`](FilterExpression.md) | `null` | `boolean`] + +A `FilterTernary` is a tree structure for combining expressions with logical operators. + +When combining three or more conditions, you must use proper nesting rather than a flat list. + +## Example + +```typescript +// A simple filter with a single condition +const filter = [ + ["AREA", "gt", 30_000], + "and", + ["COLOR", "eq", "red"] +] + +// A complex filter with multiple conditions +const filter = [ + ["AREA", "gt", 30_000], + "and", + [ + ["COLOR", "eq", "red"], + "or", + ["TYPE", "eq", "residential"] + ] +] +``` diff --git a/etc/js-sdk.api.md b/etc/js-sdk.api.md index 109c961..799c0e2 100644 --- a/etc/js-sdk.api.md +++ b/etc/js-sdk.api.md @@ -4,112 +4,112 @@ ```ts -import { ao as AggregationConfig } from './types-CB19v92x.js'; -import { A as AggregationMethod } from './types-CB19v92x.js'; -import { Q as CircleElementCreate } from './types-CB19v92x.js'; -import { R as CircleElementRead } from './types-CB19v92x.js'; -import { U as CircleElementUpdate } from './types-CB19v92x.js'; -import { aF as CircleToolSettings } from './types-CB19v92x.js'; -import { C as ConfigurableToolType } from './types-CB19v92x.js'; -import { E as Element_2 } from './types-CB19v92x.js'; -import { d as ElementChangeCallbackParams } from './types-CB19v92x.js'; -import { f as ElementCreate } from './types-CB19v92x.js'; -import { b as ElementGroup } from './types-CB19v92x.js'; -import { e as ElementGroupChangeCallbackParams } from './types-CB19v92x.js'; -import { ar as ElementGroupNode } from './types-CB19v92x.js'; -import { as as ElementNode } from './types-CB19v92x.js'; -import { g as ElementUpdate } from './types-CB19v92x.js'; -import { z as EntityNode } from './types-CB19v92x.js'; -import { s as Feature } from './types-CB19v92x.js'; -import { at as FeatureNode } from './types-CB19v92x.js'; -import { B as FeatureSelection } from './types-CB19v92x.js'; -import { aw as FeltBoundary } from './types-CB19v92x.js'; -import { ax as FeltZoom } from './types-CB19v92x.js'; -import { al as FilterExpression } from './types-CB19v92x.js'; -import { am as FilterLogicGate } from './types-CB19v92x.js'; -import { F as Filters } from './types-CB19v92x.js'; -import { an as FilterTernary } from './types-CB19v92x.js'; -import { G as Geometry } from './types-CB19v92x.js'; -import { c as GetElementGroupsConstraint } from './types-CB19v92x.js'; -import { a as GetElementsConstraint } from './types-CB19v92x.js'; -import { x as GetLayerCalculationParams } from './types-CB19v92x.js'; -import { u as GetLayerCategoriesGroup } from './types-CB19v92x.js'; -import { t as GetLayerCategoriesParams } from './types-CB19v92x.js'; -import { k as GetLayerGroupsConstraint } from './types-CB19v92x.js'; -import { w as GetLayerHistogramBin } from './types-CB19v92x.js'; -import { v as GetLayerHistogramParams } from './types-CB19v92x.js'; -import { h as GetLayersConstraint } from './types-CB19v92x.js'; -import { r as GetRenderedFeaturesConstraint } from './types-CB19v92x.js'; -import { W as HighlighterElementCreate } from './types-CB19v92x.js'; -import { X as HighlighterElementRead } from './types-CB19v92x.js'; -import { Y as HighlighterElementUpdate } from './types-CB19v92x.js'; -import { aG as HighlighterToolSettings } from './types-CB19v92x.js'; -import { Z as ImageElementCreate } from './types-CB19v92x.js'; -import { _ as ImageElementRead } from './types-CB19v92x.js'; -import { $ as ImageElementUpdate } from './types-CB19v92x.js'; -import { I as InputToolSettings } from './types-CB19v92x.js'; -import { J } from './types-CB19v92x.js'; -import { ay as LatLng } from './types-CB19v92x.js'; -import { L as Layer } from './types-CB19v92x.js'; -import { i as LayerChangeCallbackParams } from './types-CB19v92x.js'; -import { q as LayerFilters } from './types-CB19v92x.js'; -import { j as LayerGroup } from './types-CB19v92x.js'; -import { l as LayerGroupChangeCallbackParams } from './types-CB19v92x.js'; -import { au as LayerGroupNode } from './types-CB19v92x.js'; -import { av as LayerNode } from './types-CB19v92x.js'; -import { aj as LayerProcessingStatus } from './types-CB19v92x.js'; -import { n as LegendItem } from './types-CB19v92x.js'; -import { p as LegendItemChangeCallbackParams } from './types-CB19v92x.js'; -import { m as LegendItemIdentifier } from './types-CB19v92x.js'; -import { o as LegendItemsConstraint } from './types-CB19v92x.js'; -import { az as LineStringGeometry } from './types-CB19v92x.js'; -import { aH as LineToolSettings } from './types-CB19v92x.js'; -import { a0 as LinkElementRead } from './types-CB19v92x.js'; -import { aA as LngLatTuple } from './types-CB19v92x.js'; -import { y as MapDetails } from './types-CB19v92x.js'; -import { M as MapInteractionEvent } from './types-CB19v92x.js'; -import { a1 as MarkerElementCreate } from './types-CB19v92x.js'; -import { a2 as MarkerElementRead } from './types-CB19v92x.js'; -import { a3 as MarkerElementUpdate } from './types-CB19v92x.js'; -import { aI as MarkerToolSettings } from './types-CB19v92x.js'; -import { ap as MultiAggregationConfig } from './types-CB19v92x.js'; -import { aB as MultiLineStringGeometry } from './types-CB19v92x.js'; -import { aC as MultiPolygonGeometry } from './types-CB19v92x.js'; -import { a4 as NoteElementCreate } from './types-CB19v92x.js'; -import { a5 as NoteElementRead } from './types-CB19v92x.js'; -import { a6 as NoteElementUpdate } from './types-CB19v92x.js'; -import { aJ as NoteToolSettings } from './types-CB19v92x.js'; -import { a7 as PathElementCreate } from './types-CB19v92x.js'; -import { a8 as PathElementRead } from './types-CB19v92x.js'; -import { a9 as PathElementUpdate } from './types-CB19v92x.js'; -import { aK as PinToolSettings } from './types-CB19v92x.js'; -import { aa as PlaceElementCreate } from './types-CB19v92x.js'; -import { ab as PlaceElementRead } from './types-CB19v92x.js'; -import { ac as PlaceElementUpdate } from './types-CB19v92x.js'; -import { aL as PlaceFrame } from './types-CB19v92x.js'; -import { aM as PlaceSymbol } from './types-CB19v92x.js'; -import { aD as PointGeometry } from './types-CB19v92x.js'; -import { ad as PolygonElementCreate } from './types-CB19v92x.js'; -import { ae as PolygonElementRead } from './types-CB19v92x.js'; -import { af as PolygonElementUpdate } from './types-CB19v92x.js'; -import { aE as PolygonGeometry } from './types-CB19v92x.js'; -import { aN as PolygonToolSettings } from './types-CB19v92x.js'; -import { ak as RasterValue } from './types-CB19v92x.js'; -import { aO as RouteToolSettings } from './types-CB19v92x.js'; -import { K as SetViewportCenterZoomParams } from './types-CB19v92x.js'; -import { S as SetVisibilityRequest } from './types-CB19v92x.js'; -import { ag as TextElementCreate } from './types-CB19v92x.js'; -import { ah as TextElementRead } from './types-CB19v92x.js'; -import { ai as TextElementUpdate } from './types-CB19v92x.js'; -import { aP as TextToolSettings } from './types-CB19v92x.js'; -import { H as ToolSettingsChangeEvent } from './types-CB19v92x.js'; -import { D as ToolSettingsMap } from './types-CB19v92x.js'; -import { T as ToolType } from './types-CB19v92x.js'; -import { aq as ValueConfiguration } from './types-CB19v92x.js'; -import { P as ViewportCenterZoom } from './types-CB19v92x.js'; -import { N as ViewportConstraints } from './types-CB19v92x.js'; -import { O as ViewportFitBoundsParams } from './types-CB19v92x.js'; -import { V as ViewportState } from './types-CB19v92x.js'; +import { ao as AggregationConfig } from './types-jcotMzEv.js'; +import { A as AggregationMethod } from './types-jcotMzEv.js'; +import { Q as CircleElementCreate } from './types-jcotMzEv.js'; +import { R as CircleElementRead } from './types-jcotMzEv.js'; +import { U as CircleElementUpdate } from './types-jcotMzEv.js'; +import { aF as CircleToolSettings } from './types-jcotMzEv.js'; +import { C as ConfigurableToolType } from './types-jcotMzEv.js'; +import { E as Element_2 } from './types-jcotMzEv.js'; +import { d as ElementChangeCallbackParams } from './types-jcotMzEv.js'; +import { f as ElementCreate } from './types-jcotMzEv.js'; +import { b as ElementGroup } from './types-jcotMzEv.js'; +import { e as ElementGroupChangeCallbackParams } from './types-jcotMzEv.js'; +import { ar as ElementGroupNode } from './types-jcotMzEv.js'; +import { as as ElementNode } from './types-jcotMzEv.js'; +import { g as ElementUpdate } from './types-jcotMzEv.js'; +import { z as EntityNode } from './types-jcotMzEv.js'; +import { s as Feature } from './types-jcotMzEv.js'; +import { at as FeatureNode } from './types-jcotMzEv.js'; +import { B as FeatureSelection } from './types-jcotMzEv.js'; +import { aw as FeltBoundary } from './types-jcotMzEv.js'; +import { ax as FeltZoom } from './types-jcotMzEv.js'; +import { al as FilterExpression } from './types-jcotMzEv.js'; +import { am as FilterLogicGate } from './types-jcotMzEv.js'; +import { F as Filters } from './types-jcotMzEv.js'; +import { an as FilterTernary } from './types-jcotMzEv.js'; +import { G as Geometry } from './types-jcotMzEv.js'; +import { c as GetElementGroupsConstraint } from './types-jcotMzEv.js'; +import { a as GetElementsConstraint } from './types-jcotMzEv.js'; +import { x as GetLayerCalculationParams } from './types-jcotMzEv.js'; +import { u as GetLayerCategoriesGroup } from './types-jcotMzEv.js'; +import { t as GetLayerCategoriesParams } from './types-jcotMzEv.js'; +import { k as GetLayerGroupsConstraint } from './types-jcotMzEv.js'; +import { w as GetLayerHistogramBin } from './types-jcotMzEv.js'; +import { v as GetLayerHistogramParams } from './types-jcotMzEv.js'; +import { h as GetLayersConstraint } from './types-jcotMzEv.js'; +import { r as GetRenderedFeaturesConstraint } from './types-jcotMzEv.js'; +import { W as HighlighterElementCreate } from './types-jcotMzEv.js'; +import { X as HighlighterElementRead } from './types-jcotMzEv.js'; +import { Y as HighlighterElementUpdate } from './types-jcotMzEv.js'; +import { aG as HighlighterToolSettings } from './types-jcotMzEv.js'; +import { Z as ImageElementCreate } from './types-jcotMzEv.js'; +import { _ as ImageElementRead } from './types-jcotMzEv.js'; +import { $ as ImageElementUpdate } from './types-jcotMzEv.js'; +import { I as InputToolSettings } from './types-jcotMzEv.js'; +import { J } from './types-jcotMzEv.js'; +import { ay as LatLng } from './types-jcotMzEv.js'; +import { L as Layer } from './types-jcotMzEv.js'; +import { i as LayerChangeCallbackParams } from './types-jcotMzEv.js'; +import { q as LayerFilters } from './types-jcotMzEv.js'; +import { j as LayerGroup } from './types-jcotMzEv.js'; +import { l as LayerGroupChangeCallbackParams } from './types-jcotMzEv.js'; +import { au as LayerGroupNode } from './types-jcotMzEv.js'; +import { av as LayerNode } from './types-jcotMzEv.js'; +import { aj as LayerProcessingStatus } from './types-jcotMzEv.js'; +import { n as LegendItem } from './types-jcotMzEv.js'; +import { p as LegendItemChangeCallbackParams } from './types-jcotMzEv.js'; +import { m as LegendItemIdentifier } from './types-jcotMzEv.js'; +import { o as LegendItemsConstraint } from './types-jcotMzEv.js'; +import { az as LineStringGeometry } from './types-jcotMzEv.js'; +import { aH as LineToolSettings } from './types-jcotMzEv.js'; +import { a0 as LinkElementRead } from './types-jcotMzEv.js'; +import { aA as LngLatTuple } from './types-jcotMzEv.js'; +import { y as MapDetails } from './types-jcotMzEv.js'; +import { M as MapInteractionEvent } from './types-jcotMzEv.js'; +import { a1 as MarkerElementCreate } from './types-jcotMzEv.js'; +import { a2 as MarkerElementRead } from './types-jcotMzEv.js'; +import { a3 as MarkerElementUpdate } from './types-jcotMzEv.js'; +import { aI as MarkerToolSettings } from './types-jcotMzEv.js'; +import { ap as MultiAggregationConfig } from './types-jcotMzEv.js'; +import { aB as MultiLineStringGeometry } from './types-jcotMzEv.js'; +import { aC as MultiPolygonGeometry } from './types-jcotMzEv.js'; +import { a4 as NoteElementCreate } from './types-jcotMzEv.js'; +import { a5 as NoteElementRead } from './types-jcotMzEv.js'; +import { a6 as NoteElementUpdate } from './types-jcotMzEv.js'; +import { aJ as NoteToolSettings } from './types-jcotMzEv.js'; +import { a7 as PathElementCreate } from './types-jcotMzEv.js'; +import { a8 as PathElementRead } from './types-jcotMzEv.js'; +import { a9 as PathElementUpdate } from './types-jcotMzEv.js'; +import { aK as PinToolSettings } from './types-jcotMzEv.js'; +import { aa as PlaceElementCreate } from './types-jcotMzEv.js'; +import { ab as PlaceElementRead } from './types-jcotMzEv.js'; +import { ac as PlaceElementUpdate } from './types-jcotMzEv.js'; +import { aL as PlaceFrame } from './types-jcotMzEv.js'; +import { aM as PlaceSymbol } from './types-jcotMzEv.js'; +import { aD as PointGeometry } from './types-jcotMzEv.js'; +import { ad as PolygonElementCreate } from './types-jcotMzEv.js'; +import { ae as PolygonElementRead } from './types-jcotMzEv.js'; +import { af as PolygonElementUpdate } from './types-jcotMzEv.js'; +import { aE as PolygonGeometry } from './types-jcotMzEv.js'; +import { aN as PolygonToolSettings } from './types-jcotMzEv.js'; +import { ak as RasterValue } from './types-jcotMzEv.js'; +import { aO as RouteToolSettings } from './types-jcotMzEv.js'; +import { K as SetViewportCenterZoomParams } from './types-jcotMzEv.js'; +import { S as SetVisibilityRequest } from './types-jcotMzEv.js'; +import { ag as TextElementCreate } from './types-jcotMzEv.js'; +import { ah as TextElementRead } from './types-jcotMzEv.js'; +import { ai as TextElementUpdate } from './types-jcotMzEv.js'; +import { aP as TextToolSettings } from './types-jcotMzEv.js'; +import { H as ToolSettingsChangeEvent } from './types-jcotMzEv.js'; +import { D as ToolSettingsMap } from './types-jcotMzEv.js'; +import { T as ToolType } from './types-jcotMzEv.js'; +import { aq as ValueConfiguration } from './types-jcotMzEv.js'; +import { P as ViewportCenterZoom } from './types-jcotMzEv.js'; +import { N as ViewportConstraints } from './types-jcotMzEv.js'; +import { O as ViewportFitBoundsParams } from './types-jcotMzEv.js'; +import { V as ViewportState } from './types-jcotMzEv.js'; import { z } from 'zod'; export { AggregationConfig } diff --git a/src/modules/layers/filters/types.ts b/src/modules/layers/filters/types.ts index 86fdef3..0f2d20b 100644 --- a/src/modules/layers/filters/types.ts +++ b/src/modules/layers/filters/types.ts @@ -51,6 +51,31 @@ const FilterExpressionSchema = z.union([ ]); /** + * A `FilterTernary` is a tree structure for combining expressions with logical operators. + * + * When combining three or more conditions, you must use proper nesting rather than a flat list. + * + * @example + * ```typescript + * // A simple filter with a single condition + * const filter = [ + * ["AREA", "gt", 30_000], + * "and", + * ["COLOR", "eq", "red"] + * ] + * + * // A complex filter with multiple conditions + * const filter = [ + * ["AREA", "gt", 30_000], + * "and", + * [ + * ["COLOR", "eq", "red"], + * "or", + * ["TYPE", "eq", "residential"] + * ] + * ] + * ``` + * * @group Filters */ export type FilterTernary = [ From 61977075e90bee63e7bde27ea51741a4294cc7fb Mon Sep 17 00:00:00 2001 From: Tom Hicks Date: Mon, 17 Mar 2025 16:17:14 +0100 Subject: [PATCH 4/5] Include changelog in docs --- docs/CHANGELOG.md | 38 ++++++++++++++++++++++++++++++++++++ docs/Layers/FilterTernary.md | 2 +- docs/README.md | 4 ++++ typedoc.json | 1 + 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 docs/CHANGELOG.md diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md new file mode 100644 index 0000000..f968448 --- /dev/null +++ b/docs/CHANGELOG.md @@ -0,0 +1,38 @@ +# @feltmaps/js-sdk + +# 1.4.0 + +## Minor Changes + +* 555a25a: Add clearSelection method +* 1f5d950: Add option to pass auth token when embedding + +# 1.3.0 + +## Minor Changes + +* 4bbde62: Allow setting a note to show with layer filters + +# 1.2.0 + +## Minor Changes + +* 7badd4b: Add onMapIdle event +* 41efd53: Add selectFeature method to select feature by layer and feature ID +* 208c492: Add areaQuery param to getRenderedFeatures + +# 1.1.0 + +## Minor Changes + +* 5f607ec: Return style with layers, and allow updating layer styles via setLayerStyle + +## Patch Changes + +* 3a8bec8: Fix API reference link in README + +# 1.0.2 + +## Major Changes + +* Release v1 of Felt JS SDK diff --git a/docs/Layers/FilterTernary.md b/docs/Layers/FilterTernary.md index dc8bc85..937b7da 100644 --- a/docs/Layers/FilterTernary.md +++ b/docs/Layers/FilterTernary.md @@ -6,7 +6,7 @@ A `FilterTernary` is a tree structure for combining expressions with logical ope When combining three or more conditions, you must use proper nesting rather than a flat list. -## Example +# Example ```typescript // A simple filter with a single condition diff --git a/docs/README.md b/docs/README.md index 12488f3..f1f61af 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,5 +1,9 @@ # API Reference +# Documents + +* [CHANGELOG](CHANGELOG.md) + # Modules * [Elements](Elements/README.md) diff --git a/typedoc.json b/typedoc.json index 98f66a1..966c6fd 100644 --- a/typedoc.json +++ b/typedoc.json @@ -10,6 +10,7 @@ "typedoc-plugin-remark", "./customTheme.mjs" ], + "projectDocuments": ["./CHANGELOG.md"], "cleanOutputDir": true, "indexFormat": "list", "parametersFormat": "table", From 48c95fb2253d9b21896d19b4760f50ba02466423 Mon Sep 17 00:00:00 2001 From: Tom Hicks Date: Tue, 18 Mar 2025 14:17:19 +0100 Subject: [PATCH 5/5] Don't reduce changelog and top-level readme heading levels --- customTheme.mjs | 10 +++++++++- docs/CHANGELOG.md | 22 +++++++++++----------- docs/README.md | 4 ++-- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/customTheme.mjs b/customTheme.mjs index e590e10..377b5cd 100644 --- a/customTheme.mjs +++ b/customTheme.mjs @@ -19,7 +19,15 @@ export function load(app) { class MyMarkdownTheme extends MarkdownTheme { render(page, template) { - return super.render(page, template).replace(/^##/gm, "#"); + const defaultValue = super.render(page, template); + if ( + page.filename.endsWith("CHANGELOG.md") || + page.filename.endsWith("docs/README.md") + ) { + return defaultValue; + } else { + return defaultValue.replace(/^##/gm, "#"); + } } getRenderContext(page) { diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index f968448..4d14525 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,38 +1,38 @@ # @feltmaps/js-sdk -# 1.4.0 +## 1.4.0 -## Minor Changes +### Minor Changes * 555a25a: Add clearSelection method * 1f5d950: Add option to pass auth token when embedding -# 1.3.0 +## 1.3.0 -## Minor Changes +### Minor Changes * 4bbde62: Allow setting a note to show with layer filters -# 1.2.0 +## 1.2.0 -## Minor Changes +### Minor Changes * 7badd4b: Add onMapIdle event * 41efd53: Add selectFeature method to select feature by layer and feature ID * 208c492: Add areaQuery param to getRenderedFeatures -# 1.1.0 +## 1.1.0 -## Minor Changes +### Minor Changes * 5f607ec: Return style with layers, and allow updating layer styles via setLayerStyle -## Patch Changes +### Patch Changes * 3a8bec8: Fix API reference link in README -# 1.0.2 +## 1.0.2 -## Major Changes +### Major Changes * Release v1 of Felt JS SDK diff --git a/docs/README.md b/docs/README.md index f1f61af..3948d55 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,10 +1,10 @@ # API Reference -# Documents +## Documents * [CHANGELOG](CHANGELOG.md) -# Modules +## Modules * [Elements](Elements/README.md) * [Interactions](Interactions/README.md)