@superrouteca/smap 1.1.2 → 1.1.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superrouteca/smap",
3
- "version": "1.1.2",
3
+ "version": "1.1.6",
4
4
  "description": "sMap for the web: maps from Superroute's sMap service, the Web SDK (map view) and the JS client (tokens, nearest node, styles, tiles).",
5
5
  "license": "MIT",
6
6
  "author": "Goodneo Solutions",
package/types/smap.d.cts CHANGED
@@ -292,10 +292,45 @@ export interface MapOptions {
292
292
  popup?: PopupOptions;
293
293
  /** Shown while a popup's content is a pending promise (HTML string or DOM node; default pulsing dots). */
294
294
  popupLoading?: string | Node;
295
+ /** Map tools: the starting state, where the tools control sits (or false for none) and its labels. */
296
+ tools?: ToolsOptions;
295
297
  /** Every other option goes to the rendering engine. */
296
298
  [engineOption: string]: unknown;
297
299
  }
298
300
 
301
+ /** A corner of the map, or 'none' for an element that stays where the page put it. */
302
+ export type ToolPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'none';
303
+ /** The tools the SDK makes by name. */
304
+ export type ToolKind = 'navigation' | 'geolocate' | 'fullscreen' | 'scale' | 'zoom' | 'compass' | 'locate';
305
+ export interface ToolOptions {
306
+ /** Shown on the tool's button in the tools control and read by screen readers. */
307
+ label?: string;
308
+ position?: ToolPosition;
309
+ /** Options of a kind's engine control (e.g. `{ showCompass: false }` for navigation). */
310
+ options?: Record<string, unknown>;
311
+ }
312
+ /** A data-layer tool: one or more layer ids (yours, or the basemap's) shown and hidden with the tool. */
313
+ export interface ToolLayers { layer: string | string[] }
314
+ export interface ToolsOptions {
315
+ /** Ids of the tools hidden from the start. */
316
+ hidden?: string[];
317
+ /**
318
+ * Where the tools control sits: 'toolbar' (the default) is the last button of the map's toolbar, the corner holding
319
+ * the navigation control (top left without one), kept last when controls join it later; a corner places it there;
320
+ * false leaves it out.
321
+ */
322
+ control?: 'toolbar' | Exclude<ToolPosition, 'none'> | false;
323
+ /** The tools control's texts (English by default). */
324
+ labels?: { button?: string; showAll?: string; hideAll?: string };
325
+ }
326
+ export interface ToolState { id: string; label: string; visible: boolean }
327
+ export interface ToolsChangeEvent {
328
+ /** Ids of the registered tools that are hidden now. */
329
+ hidden: string[];
330
+ /** The tool switched, or null when every tool was switched at once. */
331
+ changed: string | null;
332
+ }
333
+
299
334
  /** addData: how the file is read, then the options of addPoints / addLines / addPolygons for its parts. */
300
335
  export type DataOptions = ReadOptions & PointOptions & LineOptions & PolygonOptions;
301
336
 
@@ -497,6 +532,30 @@ export declare class Map {
497
532
  closePopup(): this;
498
533
  setAutoZoom(on: boolean): this;
499
534
  autoZoom(): boolean;
535
+ /**
536
+ * Registers a tool floating on the map: a page element, an engine control, or a kind the SDK makes; or data layers
537
+ * (`{ layer: 'stops' }`, `{ layer: ['stops', 'stop-labels'] }`) whose layout visibility follows the tool, a layer
538
+ * added later under a hidden tool's id starting hidden and an id without a layer left alone. Adding an id again
539
+ * replaces the first. The map data credit, the sMap badge and the tools control are never tools.
540
+ */
541
+ addTool(id: string, target: HTMLElement | { onAdd(map: any): HTMLElement; onRemove?(map: any): void } | ToolKind | ToolLayers, options?: ToolOptions): this;
542
+ /** Removes a tool: an engine control leaves the map, a page element is shown again where the page put it. */
543
+ removeTool(id: string): this;
544
+ /** Shows or hides one tool; a hidden tool keeps its state. */
545
+ setToolVisible(id: string, visible: boolean): this;
546
+ /** Shows or hides every tool. */
547
+ setToolsVisible(visible: boolean): this;
548
+ /** The tools in the order added. */
549
+ tools(): ToolState[];
550
+ /** Called after every change; the SDK keeps no state itself. */
551
+ onToolsChange(handler: (event: ToolsChangeEvent) => void): this;
552
+ offToolsChange(handler: (event: ToolsChangeEvent) => void): this;
553
+ /**
554
+ * A plan editor on this map (OPEN-ROUTE-EDIT E10): the plan drawn as layers `<id>:legs`, `<id>:starts`, `<id>:stops`
555
+ * and `<id>:unassigned`, stops dragged within and between routes, and the ready-made panel as the map tool
556
+ * `<id>-editor` (unless `panel: false`). Every edit is a plan.* call of the Open Platform.
557
+ */
558
+ planEditor(options: MapPlanEditorOptions): MapPlanEditor;
500
559
  on(type: string, ...args: any[]): this;
501
560
  off(type: string, ...args: any[]): this;
502
561
  once(type: string, ...args: any[]): any;
@@ -566,6 +625,366 @@ export declare class PMTilesArchive {
566
625
  /** Registers deck.gl's map overlay module (`@deck.gl/mapbox`) for addDeckLayer. */
567
626
  export declare function useDeck(module: { MapboxOverlay: any } | { default: { MapboxOverlay: any } }): any;
568
627
 
628
+ // ------------------------------------------------------------------ plan editor (OPEN-ROUTE-EDIT E10)
629
+
630
+ /**
631
+ * The answer of `POST /v1/plan/token`, which your own server calls with its API token (never the browser). The
632
+ * provider may hand it on as it is; `expires_at` decides when the editor asks again.
633
+ */
634
+ export interface PlanTokenAnswer {
635
+ /** `sr_pet_…`, sent as `Authorization: Bearer sr_pet_…`. */
636
+ access_token: string;
637
+ token_type?: 'Bearer';
638
+ expires_in?: number;
639
+ /** ISO 8601 with offset; the editor asks for a new token 30 s before it. */
640
+ expires_at?: string;
641
+ scopes?: string[];
642
+ origins?: string[] | null;
643
+ }
644
+ /**
645
+ * How plan calls are authorised, always as `Authorization: Bearer …`: a short-lived plan editor token from your own
646
+ * server (asked again 30 s before its `expires_at` and once after a 401 `SESSION_EXPIRED`), or a map key (`smk_…`)
647
+ * with plan editing switched on. Any other refusal (`SESSION_REVOKED`, `TOKEN_INVALID`, 403 `NOT_AUTHORIZED`) is
648
+ * raised as an error with its `reason`.
649
+ */
650
+ export type PlanCredentials =
651
+ | { token: () => string | PlanTokenAnswer | { data: PlanTokenAnswer } | Promise<string | PlanTokenAnswer | { data: PlanTokenAnswer }> }
652
+ | { key: string };
653
+
654
+ /** A location: `{ lat, lng }` (as the plan calls take it) or `[lng, lat]`. */
655
+ export type PlanLocation = { lat: number; lng: number } | [number, number];
656
+
657
+ export interface PlanVehicle {
658
+ id: string;
659
+ start?: PlanLocation | null;
660
+ end?: PlanLocation | null;
661
+ return_to_start?: boolean | null;
662
+ capacity?: unknown;
663
+ skills?: string[];
664
+ time_window?: unknown;
665
+ max_tasks?: number | null;
666
+ max_distance_meters?: number | null;
667
+ max_travel_time_seconds?: number | null;
668
+ [field: string]: unknown;
669
+ }
670
+ export interface PlanJob {
671
+ id: string;
672
+ location: PlanLocation;
673
+ service_seconds?: number | null;
674
+ amount?: unknown;
675
+ skills?: string[];
676
+ time_windows?: unknown;
677
+ [field: string]: unknown;
678
+ }
679
+ export interface PlanRoute { vehicle_id: string; stops: string[]; reverse?: boolean }
680
+ /** A plan as the plan calls take it. */
681
+ export interface Plan {
682
+ vehicles: PlanVehicle[];
683
+ jobs: PlanJob[];
684
+ routes: PlanRoute[];
685
+ region?: 'NA' | 'EU' | 'AU' | 'ASIA' | string;
686
+ profile?: 'car' | 'van' | 'truck' | 'bike' | 'foot' | 'motorcycle' | string;
687
+ /** ISO 8601 with offset. */
688
+ departed_at?: string;
689
+ }
690
+ /** The plan as the editor holds it: routes in driving order (one per vehicle) and every job on no route. */
691
+ export interface PlanState extends Plan { unassigned: string[] }
692
+
693
+ export interface PlanViolation { rule: string; message?: string; [field: string]: unknown }
694
+ export interface PricedStop {
695
+ type: 'start' | 'job' | 'end';
696
+ id?: string;
697
+ sequence?: number;
698
+ reachable?: boolean;
699
+ arrival?: string | null;
700
+ leg_distance_meters?: number | null;
701
+ leg_duration_seconds?: number | null;
702
+ /** Encoded polyline (precision 5) of the hop into this stop. */
703
+ leg_geometry?: string | null;
704
+ violations?: PlanViolation[];
705
+ [field: string]: unknown;
706
+ }
707
+ export interface PricedRoute {
708
+ vehicle_id: string;
709
+ stop_count: number;
710
+ task_count: number;
711
+ distance_meters: number;
712
+ duration_seconds: number;
713
+ service_seconds?: number;
714
+ waiting_seconds?: number;
715
+ departure?: string;
716
+ completion?: string;
717
+ unreachable_legs: number;
718
+ violations: PlanViolation[];
719
+ violation_count: number;
720
+ stops: PricedStop[];
721
+ }
722
+ export interface PlanSummary { routes: number; tasks: number; distance_meters: number; duration_seconds: number; unreachable_legs: number; violations: number }
723
+ /** The plan's prices and judgement as the last answer gave them. */
724
+ export interface PlanResult { routes: PricedRoute[]; summary: PlanSummary | null }
725
+
726
+ export interface InsertChoice {
727
+ feasible: boolean;
728
+ vehicle_id: string;
729
+ position: number;
730
+ after?: string | null;
731
+ added_distance_meters: number;
732
+ added_duration_seconds: number;
733
+ added_waiting_seconds?: number;
734
+ arrival?: string | null;
735
+ waiting_seconds?: number;
736
+ service_start?: string | null;
737
+ violations?: PlanViolation[];
738
+ }
739
+ /** One inserted job: whether it was placed, the positions answered (best first) and which one it is at. */
740
+ export interface InsertChoices { job: string; placed: boolean; reason?: 'no_vehicle' | 'no_feasible_position'; choices: InsertChoice[]; chosen: number | null }
741
+
742
+ export type PlanEditKind = 'set' | 'recost' | 'resequence' | 'move' | 'remove' | 'insert' | 'refine' | 'undo' | 'redo' | 'lock' | 'choices' | 'error';
743
+ export interface PlanChangeEvent {
744
+ kind: PlanEditKind;
745
+ plan: PlanState | null;
746
+ result: PlanResult | null;
747
+ /** What the call answered about the edit (`move`, `removed`, `insert`, `refine`, `resequence` of the answer). */
748
+ answer: unknown;
749
+ /** True while the plan drawn has not been priced yet (an edit on its way). */
750
+ pending: boolean;
751
+ canUndo: boolean;
752
+ canRedo: boolean;
753
+ }
754
+ export interface PlanEditorError extends Error {
755
+ status: number;
756
+ /** The Open Platform's error code (`VALIDATION_FAILED`, `SESSION_EXPIRED`, `NOT_AUTHORIZED`, …); never localized. */
757
+ code: string | null;
758
+ details: unknown;
759
+ /** Why, where the service says (`expired`, `key_revoked`, `entitlements_changed`, `origin_not_allowed`, `plan_editing_off`, …). */
760
+ reason: string | null;
761
+ }
762
+ export interface PlanSnapshotEvent {
763
+ /** `opened`, `failed` (calls go on without one), or the X-Plan-Matrix of an answer: `used`, `expired`, `unavailable`, `mismatch`. */
764
+ status: 'opened' | 'failed' | 'used' | 'expired' | 'unavailable' | 'mismatch';
765
+ matrix: string | null;
766
+ expires_at?: string | null;
767
+ node?: string | null;
768
+ error?: unknown;
769
+ }
770
+ export interface PlanPreview { routes: PlanRoute[]; result: PlanResult }
771
+ /** An edit's outcome; null when a newer edit cancelled it. */
772
+ export interface PlanEditOutcome { kind: string; plan: PlanState; result: PlanResult; answer: unknown }
773
+ export interface PlanEditorState {
774
+ plan: PlanState | null;
775
+ result: PlanResult | null;
776
+ busy: boolean;
777
+ error: { kind: string; status: number; code: string | null; message: string; reason: string | null } | null;
778
+ canUndo: boolean;
779
+ canRedo: boolean;
780
+ choices: InsertChoices[] | null;
781
+ locked: string[];
782
+ last: { kind: string; answer: unknown } | null;
783
+ preview: PlanPreview | null;
784
+ }
785
+
786
+ export interface PlanEditorOptions {
787
+ credentials: PlanCredentials;
788
+ /**
789
+ * A native app's identity, sent as `X-SMap-App` (and `X-SMap-App-Cert`): `android:<package>` with its certificate,
790
+ * `apple:<bundle id>` or `windows:<id>`. Pages leave it out: the browser's Origin names them.
791
+ */
792
+ app?: string | { id: string; cert?: string };
793
+ /** The Open Platform, `https://open.superroute.ca` by default. */
794
+ baseUrl?: string;
795
+ /** The fetch to use (the page's by default). */
796
+ fetch?: typeof fetch;
797
+ /** The starting plan. */
798
+ plan?: Plan;
799
+ /** Used when the plan names none. */
800
+ region?: string;
801
+ profile?: string;
802
+ /** Open and use a distance snapshot (default true). */
803
+ snapshot?: boolean;
804
+ /** Ask for each leg's line, for drawing (default true). */
805
+ geometry?: boolean;
806
+ /** Positions offered per inserted job, 1-10 (default 3). */
807
+ insertLimit?: number;
808
+ /** What insert ranks by (the service's default: duration). */
809
+ objective?: 'duration' | 'distance';
810
+ }
811
+
812
+ export interface PlanEditorEvents {
813
+ change: PlanChangeEvent;
814
+ busy: { busy: boolean };
815
+ error: { error: PlanEditorError; kind: string };
816
+ snapshot: PlanSnapshotEvent;
817
+ /** A preview's prices, or null when it is cleared. */
818
+ preview: PlanPreview | null;
819
+ destroy: null;
820
+ }
821
+
822
+ /** The plan editor's state and calls, without a map (the map layer and the panel build on it). */
823
+ export declare class PlanEditor {
824
+ constructor(options: PlanEditorOptions);
825
+ /** Replaces the plan; the history starts again from it and it is priced (plan.recost). */
826
+ setPlan(plan: Plan): Promise<PlanEditOutcome | null>;
827
+ /** The plan in the shape it is sent, with `unassigned`. */
828
+ getPlan(): PlanState | null;
829
+ getResult(): PlanResult | null;
830
+ state(): PlanEditorState;
831
+ /** Gives a route a new driving order (plan.resequence): every stop of the route once. */
832
+ resequence(vehicleId: string, stops: string[]): Promise<PlanEditOutcome | null>;
833
+ /** Moves stops to a vehicle's route at `position` (from 1, counted without them; omitted: last) (plan.move). */
834
+ move(stops: string | string[], vehicleId: string, position?: number | null): Promise<PlanEditOutcome | null>;
835
+ /** Takes stops off their routes (plan.remove). */
836
+ remove(stops: string | string[]): Promise<PlanEditOutcome | null>;
837
+ /** A stop dropped before the stop at `position` of a route as drawn: a resequence within its route, a move otherwise. */
838
+ dropStop(stopId: string, vehicleId: string, position: number): Promise<PlanEditOutcome | null>;
839
+ /** Inserts new jobs, or places unassigned jobs given by id, at their cheapest positions (plan.insert). */
840
+ insert(jobs: PlanJob | string | Array<PlanJob | string>, options?: { limit?: number; objective?: 'duration' | 'distance'; nearest?: number }): Promise<PlanEditOutcome | null>;
841
+ /** The positions the last insert answered. */
842
+ choices(): InsertChoices[] | null;
843
+ clearChoices(): this;
844
+ /** Puts an inserted job at another of its answered positions (plan.move). */
845
+ choose(jobId: string, index: number): Promise<PlanEditOutcome | null>;
846
+ /** Re-orders chosen routes around the locked stops (plan.refine); kept only when better. */
847
+ refine(options?: { vehicleIds?: string[]; freeze?: string[] }): Promise<PlanEditOutcome | null>;
848
+ /** Prices the plan again as it is (plan.recost). */
849
+ recost(): Promise<PlanEditOutcome | null>;
850
+ /** Locked stops stay on their route, in their order, when routes are refined. */
851
+ lock(stops: string | string[]): this;
852
+ unlock(stops: string | string[]): this;
853
+ locked(): string[];
854
+ isLocked(stopId: string): boolean;
855
+ undo(): Promise<PlanResult | PlanEditOutcome | null>;
856
+ redo(): Promise<PlanResult | PlanEditOutcome | null>;
857
+ canUndo(): boolean;
858
+ canRedo(): boolean;
859
+ isBusy(): boolean;
860
+ /** Prices other routes without changing the plan (plan.recost); a newer preview cancels the one before. */
861
+ preview(routes: PlanRoute[]): Promise<PlanPreview | null>;
862
+ clearPreview(): this;
863
+ on<K extends keyof PlanEditorEvents>(type: K, handler: (event: PlanEditorEvents[K]) => void): this;
864
+ off<K extends keyof PlanEditorEvents>(type: K, handler: (event: PlanEditorEvents[K]) => void): this;
865
+ /** Cancels its calls, closes its snapshot, and removes its map layers and panel. */
866
+ destroy(): void;
867
+ }
868
+
869
+ /** The panel's text keys; `labels` replaces any of them. */
870
+ export type PlanTextKey = 'editor' | 'busy' | 'undo' | 'redo' | 'refine' | 'total' | 'distance' | 'drivingTime' | 'stops' |
871
+ 'violations' | 'unreachable' | 'unassigned' | 'noStops' | 'place' | 'remove' | 'lock' | 'unlock' | 'choicesFor' | 'choice' |
872
+ 'added' | 'arrival' | 'choose' | 'chosen' | 'close' | 'notPlaced' | 'preview' | 'refined' | 'notRefined' | 'error' |
873
+ 'pending' | 'km' | 'hours' | 'minutes' | 'rule.capacity' | 'rule.max_tasks' | 'rule.max_distance' |
874
+ 'rule.max_travel_time' | 'rule.vehicle_time_window' | 'rule.skills' | 'rule.time_window' | 'rule.unreachable';
875
+ /** The panel's languages. */
876
+ export type PlanLanguage = 'en' | 'zh-Hans' | 'zh-Hant' | 'de' | 'es' | 'fr' | 'it' | 'nl' | 'pt' | 'sr' | 'hu' | 'pl' | 'sk' | 'cs';
877
+
878
+ export interface MapPlanEditorOptions extends PlanEditorOptions {
879
+ /** Prefix of the layer ids (default 'plan'). */
880
+ id?: string;
881
+ /** Route colours, one per vehicle in the plan's order (repeated). */
882
+ colors?: string[];
883
+ /** Price the drop target while a stop is dragged (default true). */
884
+ preview?: boolean;
885
+ /** The panel's language (default the map's); any BCP-47 tag, English when none of the 14 fits. */
886
+ language?: string;
887
+ /** Own texts by key, over the panel's. */
888
+ labels?: Partial<Record<PlanTextKey, string>>;
889
+ /** The ready-made panel (default true): false for none, or where it sits and its tool label. */
890
+ panel?: boolean | { position?: Exclude<ToolPosition, 'none'>; label?: string; id?: string; className?: string; labels?: Partial<Record<PlanTextKey, string>> };
891
+ }
892
+
893
+ /** A plan editor on a map, with its layers and (unless turned off) its panel. */
894
+ export interface MapPlanEditor extends PlanEditor {
895
+ /** The ready-made panel; null with `panel: false` or before the map has its engine. */
896
+ panel: { element: HTMLElement; setLanguage(language: string): void; render(): void; destroy(): void } | null;
897
+ layer: { remove(): void; features(): { legs: GeoJSONFeature[]; stops: GeoJSONFeature[]; unassigned: GeoJSONFeature[]; starts: GeoJSONFeature[] } };
898
+ }
899
+
900
+ /** The panel's texts in each of its 14 languages. */
901
+ export declare const planTexts: Record<PlanLanguage, Record<PlanTextKey, string>>;
902
+
903
+ /** A feature the plan editor draws; `properties.kind` says which. */
904
+ export interface PlanFeature {
905
+ type: 'Feature';
906
+ geometry: { type: 'Point'; coordinates: [number, number] } | { type: 'LineString'; coordinates: Array<[number, number]> };
907
+ properties: {
908
+ /** The `id` the features were made for (the layer prefix). */
909
+ smap_plan: string;
910
+ kind: 'leg' | 'stop' | 'start' | 'unassigned';
911
+ /** A stop's or job's id. */
912
+ id?: string;
913
+ vehicle_id?: string;
914
+ /** A stop's place in its route from 1; a leg's: the stop it leads to (past the last stop: the end). */
915
+ position?: number;
916
+ /** A stop's number as drawn. */
917
+ label?: string;
918
+ color: string;
919
+ /** A stop's border: dark red with a violation, near black when locked, otherwise its route's colour. */
920
+ border?: string;
921
+ locked?: boolean;
922
+ violated?: boolean;
923
+ };
924
+ }
925
+ /** The features of a plan, one list per layer. */
926
+ export interface PlanFeatures { legs: PlanFeature[]; stops: PlanFeature[]; unassigned: PlanFeature[]; starts: PlanFeature[] }
927
+ /** Where a dropped stop goes: before the stop at `position` of the vehicle's route as drawn (past the last: after it). */
928
+ export interface PlanDropTarget { vehicle_id: string; position: number }
929
+ /** A drop as an edit: a new order within the stop's route, or a move to another route (position null: last). */
930
+ export type PlanDropEdit = { kind: 'resequence'; vehicle_id: string; stops: string[] } | { kind: 'move'; vehicle_id: string; position: number | null };
931
+ /** A stop dragged on a map, with the preview of its target (see planEditorParts.planDrag). */
932
+ export interface PlanDrag {
933
+ /** The pointer went down on a stop or an unassigned job (`point` in pixels, for the drag threshold). */
934
+ start(stopId: string, point?: { x: number; y: number }): void;
935
+ /** The pointer moved: the features under it (any objects with the features' `properties`). Answers the target. */
936
+ move(hits: Array<{ properties?: Record<string, unknown> }>, point?: { x: number; y: number }): PlanDropTarget | null;
937
+ /** The pointer was released: drops the stop on the target under `hits`, or on the last target when none are given. */
938
+ end(hits?: Array<{ properties?: Record<string, unknown> }> | null): Promise<PlanEditOutcome | null>;
939
+ cancel(): void;
940
+ /** The stop being dragged, or null. */
941
+ dragging(): string | null;
942
+ /** True once the pointer moved past the threshold. */
943
+ moved(): boolean;
944
+ target(): PlanDropTarget | null;
945
+ }
946
+ /** The ready-made panel. */
947
+ export interface PlanPanel { element: HTMLElement; setLanguage(language: string): void; render(): void; destroy(): void }
948
+ export interface PlanPanelOptions {
949
+ /** Any BCP-47 tag; English when none of the 14 fits. */
950
+ language?: string;
951
+ labels?: Partial<Record<PlanTextKey, string>>;
952
+ document?: Document;
953
+ colors?: string[];
954
+ className?: string;
955
+ }
956
+ /**
957
+ * The parts a plan editor on another map library is built from (the tool adapters use them): the features to draw,
958
+ * where a drop lands, a drag with its preview, and the panel with its stylesheet.
959
+ */
960
+ export interface PlanEditorParts {
961
+ /** The features of the editor's plan, each marked with `smap_plan: id`. */
962
+ planFeatures(editor: PlanEditor, id: string, colors?: string[]): PlanFeatures;
963
+ /** Where a drop on these features goes: before a stop, into a leg, or first after a start; null: nowhere. */
964
+ dropTarget(hits: Array<{ properties?: Record<string, unknown> }>, draggedId: string): PlanDropTarget | null;
965
+ /** The edit a drop makes on these routes; null when nothing changes. */
966
+ dropEdit(routes: PlanRoute[], stopId: string, vehicleId: string, position: number): PlanDropEdit | null;
967
+ /** The editor's routes after the drop (for editor.preview); null when nothing changes. */
968
+ dropRoutes(editor: PlanEditor, stopId: string, target: PlanDropTarget | null): PlanRoute[] | null;
969
+ /** The features within `tolerance` pixels of a point, nearest first (points 12 px, lines 8 px by default). */
970
+ featuresAt(features: PlanFeatures | PlanFeature[], project: (lngLat: [number, number]) => { x: number; y: number }, point: { x: number; y: number }, options?: { tolerance?: number }): PlanFeature[];
971
+ /** A drag of a stop: the threshold (4 px), the preview of its target after `previewMs` (250) and the drop. */
972
+ planDrag(editor: PlanEditor, options?: { preview?: boolean; previewMs?: number; threshold?: number }): PlanDrag;
973
+ createPanel(editor: PlanEditor, options?: PlanPanelOptions): PlanPanel;
974
+ /** Adds the panel's stylesheet (the `.smap-plan-*` rules of smap.css) to a document once. */
975
+ injectCss(doc: Document): void;
976
+ /** The panel's texts in a language, with own texts over them. */
977
+ textsFor(language: string, labels?: Partial<Record<PlanTextKey, string>>): Record<PlanTextKey, string>;
978
+ /** The panel's language for a BCP-47 tag. */
979
+ panelLanguage(tag: string): PlanLanguage;
980
+ /** An encoded polyline (precision 5) as [[lng, lat], …]. */
981
+ decodePolyline(text: string, precision?: number): Array<[number, number]>;
982
+ /** The route colours, one per vehicle in the plan's order (repeated). */
983
+ colors: string[];
984
+ }
985
+ /** The parts of the plan editor for bindings on other map libraries. */
986
+ export declare const planEditorParts: PlanEditorParts;
987
+
569
988
  declare const sMap: {
570
989
  Map: typeof Map;
571
990
  version: string;
@@ -584,5 +1003,8 @@ declare const sMap: {
584
1003
  parseWmtsCapabilities: typeof parseWmtsCapabilities;
585
1004
  PMTilesArchive: typeof PMTilesArchive;
586
1005
  useDeck: typeof useDeck;
1006
+ PlanEditor: typeof PlanEditor;
1007
+ planTexts: typeof planTexts;
1008
+ planEditorParts: typeof planEditorParts;
587
1009
  };
588
1010
  export default sMap;