@kispace-io/gs-lib 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +58 -0
  2. package/bin/map-builder.js +132 -0
  3. package/dist/base-map-builder.d.ts +102 -0
  4. package/dist/base-map-builder.d.ts.map +1 -0
  5. package/dist/gs-gs2ol.d.ts +41 -0
  6. package/dist/gs-gs2ol.d.ts.map +1 -0
  7. package/dist/gs-lib.css +3724 -0
  8. package/dist/gs-lib.d.ts +16 -0
  9. package/dist/gs-lib.d.ts.map +1 -0
  10. package/dist/gs-litns.d.ts +32 -0
  11. package/dist/gs-litns.d.ts.map +1 -0
  12. package/dist/gs-model.d.ts +186 -0
  13. package/dist/gs-model.d.ts.map +1 -0
  14. package/dist/gs-ol-adapters.d.ts +23 -0
  15. package/dist/gs-ol-adapters.d.ts.map +1 -0
  16. package/dist/gs-ol2gs.d.ts +9 -0
  17. package/dist/gs-ol2gs.d.ts.map +1 -0
  18. package/dist/gs-olns.d.ts +22 -0
  19. package/dist/gs-olns.d.ts.map +1 -0
  20. package/dist/index.d.ts +11 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.html +69 -0
  23. package/dist/index.js +104888 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/pwa/assets/icons/192x192.png +0 -0
  26. package/dist/pwa/assets/icons/24x24.png +0 -0
  27. package/dist/pwa/assets/icons/48x48.png +0 -0
  28. package/dist/pwa/assets/icons/512x512.png +0 -0
  29. package/dist/pwa/assets/icons/icon_192.png +0 -0
  30. package/dist/pwa/assets/icons/icon_24.png +0 -0
  31. package/dist/pwa/assets/icons/icon_48.png +0 -0
  32. package/dist/pwa/assets/icons/icon_512.png +0 -0
  33. package/dist/pwa/manifest.json +54 -0
  34. package/dist/pwa/staticwebapp.config.json +6 -0
  35. package/dist/pwa/sw.js +109 -0
  36. package/lib/node-map-builder.ts +200 -0
  37. package/package.json +51 -0
  38. package/public/index.html +69 -0
  39. package/public/pwa/assets/icons/192x192.png +0 -0
  40. package/public/pwa/assets/icons/24x24.png +0 -0
  41. package/public/pwa/assets/icons/48x48.png +0 -0
  42. package/public/pwa/assets/icons/512x512.png +0 -0
  43. package/public/pwa/assets/icons/icon_192.png +0 -0
  44. package/public/pwa/assets/icons/icon_24.png +0 -0
  45. package/public/pwa/assets/icons/icon_48.png +0 -0
  46. package/public/pwa/assets/icons/icon_512.png +0 -0
  47. package/public/pwa/manifest.json +54 -0
  48. package/public/pwa/staticwebapp.config.json +6 -0
  49. package/public/pwa/sw.js +109 -0
  50. package/src/base-map-builder.ts +414 -0
  51. package/src/gs-gs2ol.ts +626 -0
  52. package/src/gs-lib.ts +54 -0
  53. package/src/gs-litns.ts +213 -0
  54. package/src/gs-model.ts +393 -0
  55. package/src/gs-ol-adapters.ts +89 -0
  56. package/src/gs-ol2gs.ts +86 -0
  57. package/src/gs-olns.ts +30 -0
  58. package/src/index.ts +15 -0
  59. package/tsconfig.json +23 -0
@@ -0,0 +1,213 @@
1
+ // Lit namespace module - exports all lit APIs for user modules
2
+ // Lit is required for gs-ol-adapters (uses lit.render) and for user modules
3
+ // WebAwesome is imported here to make it available to user modules (treated as part of lit)
4
+
5
+ // Re-export all Lit APIs from appspace's externals/lit module - single source of truth
6
+ export * from "@kispace-io/appspace/externals/lit-exports";
7
+
8
+ // Import specific items needed for defineComponent and lit namespace object
9
+ import {
10
+ html, css, nothing, svg, LitElement, unsafeCSS,
11
+ when, repeat, keyed, classMap, styleMap, ifDefined,
12
+ guard, cache, unsafeHTML, until, live, createRef, ref, render
13
+ } from "@kispace-io/appspace/externals/lit-exports";
14
+
15
+ // Import WebAwesome components from appspace's externals/webawesome module
16
+ // This maintains a single source of truth - Vite will optimize the build to only include what's needed
17
+ // WebAwesome is treated as part of lit, so it's always available to user modules
18
+ import "@kispace-io/appspace/externals/webawesome";
19
+
20
+ /**
21
+ * Helper function to define a custom web component from a simple function.
22
+ * Converts a render function into a LitElement-based web component.
23
+ * Properties are automatically inferred from the props used in the render function.
24
+ *
25
+ * @param tagName - The custom element tag name (must contain a hyphen)
26
+ * @param renderFn - Function that receives props and returns a Lit template
27
+ * @param options - Optional configuration (props defaults, styles, etc.)
28
+ * @returns The tag name of the registered component
29
+ *
30
+ * @example
31
+ * ```javascript
32
+ * export default function ({lit: {html, css, defineComponent}}) {
33
+ * // Simple component - properties inferred from props usage
34
+ * defineComponent('my-button', (props) => html`
35
+ * <button @click=${props.onClick}>${props.label || 'Click'}</button>
36
+ * `);
37
+ *
38
+ * // Component with default props (auto-converted to properties)
39
+ * defineComponent('my-counter', (props) => html`
40
+ * <div class="counter">Count: ${props.count}</div>
41
+ * `, {
42
+ * props: { count: 0, label: '' }, // Simple object - auto-converted
43
+ * styles: css`
44
+ * .counter { font-weight: bold; }
45
+ * `
46
+ * });
47
+ *
48
+ * // Use the component in your template
49
+ * return () => html`
50
+ * <my-counter count="5"></my-counter>
51
+ * `;
52
+ * }
53
+ * ```
54
+ */
55
+ const defineComponent = (
56
+ tagName: string,
57
+ renderFn: (props: any) => any,
58
+ options?: {
59
+ props?: Record<string, any> | Record<string, { type?: any; reflect?: boolean; attribute?: string | boolean }>;
60
+ styles?: any;
61
+ shadowRootOptions?: ShadowRootInit;
62
+ }
63
+ ): string => {
64
+ if (!tagName.includes('-')) {
65
+ throw new Error(`Custom element tag name must contain a hyphen: ${tagName}`);
66
+ }
67
+
68
+ // Check if already defined
69
+ if (customElements.get(tagName)) {
70
+ return tagName;
71
+ }
72
+
73
+ // Convert simple props object to LitElement property definitions
74
+ const convertPropsToProperties = (props: Record<string, any>): Record<string, any> => {
75
+ const properties: Record<string, any> = {};
76
+
77
+ for (const [key, value] of Object.entries(props)) {
78
+ // If it's already a LitElement property config, use it as-is
79
+ if (value && typeof value === 'object' && ('type' in value || 'reflect' in value || 'attribute' in value)) {
80
+ properties[key] = value;
81
+ } else {
82
+ // Infer type from default value
83
+ const type = value === null || value === undefined ? String
84
+ : typeof value === 'boolean' ? Boolean
85
+ : typeof value === 'number' ? Number
86
+ : typeof value === 'object' ? Object
87
+ : String;
88
+
89
+ properties[key] = {
90
+ type: type,
91
+ // Set default value
92
+ ...(value !== undefined && { value })
93
+ };
94
+ }
95
+ }
96
+
97
+ return properties;
98
+ };
99
+
100
+ // Determine properties from options
101
+ let properties: Record<string, any> = {};
102
+ if (options?.props) {
103
+ properties = convertPropsToProperties(options.props);
104
+ }
105
+
106
+ // Track props accessed during render to auto-create properties
107
+ // This allows properties to be inferred from render function usage
108
+ const accessedProps = new Set<string>();
109
+ const propsProxy = new Proxy({ $this: {} }, {
110
+ get(_target, prop: string) {
111
+ // Track all property accesses except built-ins and $this
112
+ if (typeof prop === 'string' &&
113
+ prop !== '$this' &&
114
+ prop !== 'toJSON' &&
115
+ prop !== 'toString' &&
116
+ prop !== 'valueOf' &&
117
+ !prop.startsWith('Symbol.')) {
118
+ accessedProps.add(prop);
119
+ }
120
+ // Return a safe default value based on common patterns
121
+ return prop.endsWith('Handler') || prop.startsWith('on') ? (() => {}) : '';
122
+ }
123
+ });
124
+
125
+ // Do an initial render to detect accessed props
126
+ // This is safe because we catch all errors and the render function
127
+ // should be pure (no side effects)
128
+ try {
129
+ renderFn(propsProxy);
130
+ } catch {
131
+ // Ignore errors during prop detection - render function might
132
+ // throw if props are required, but that's okay for detection
133
+ }
134
+
135
+ // Add auto-detected props that weren't explicitly defined
136
+ // Default to String type for auto-detected props
137
+ for (const prop of accessedProps) {
138
+ if (!(prop in properties)) {
139
+ properties[prop] = { type: String };
140
+ }
141
+ }
142
+
143
+ class DynamicComponent extends LitElement {
144
+ static properties = properties;
145
+
146
+ static styles = options?.styles;
147
+
148
+ constructor() {
149
+ super();
150
+ // Initialize default values from simple props (not LitElement config objects)
151
+ if (options?.props) {
152
+ for (const [key, value] of Object.entries(options.props)) {
153
+ // Only set default if it's a simple value, not a LitElement property config
154
+ if (value !== undefined && !(value && typeof value === 'object' && ('type' in value || 'reflect' in value || 'attribute' in value))) {
155
+ (this as any)[key] = value;
156
+ }
157
+ }
158
+ }
159
+ }
160
+
161
+ createRenderRoot() {
162
+ if (options?.shadowRootOptions) {
163
+ return this.attachShadow(options.shadowRootOptions);
164
+ }
165
+ return super.createRenderRoot();
166
+ }
167
+
168
+ render() {
169
+ // Create a props object from element properties
170
+ const props: any = {
171
+ $this: this // Element instance - needed for arrow functions which don't have 'this'
172
+ };
173
+
174
+ // Copy all properties to props object
175
+ for (const key of Object.keys(properties)) {
176
+ props[key] = (this as any)[key];
177
+ }
178
+
179
+ // Bind render function to this element so 'this' refers to the element instance
180
+ // Note: 'this' works for regular functions, 'props.$this' works for arrow functions
181
+ return renderFn.call(this, props);
182
+ }
183
+ }
184
+
185
+ // Register the custom element
186
+ customElements.define(tagName, DynamicComponent);
187
+
188
+ return tagName;
189
+ };
190
+
191
+ // Export all lit APIs as a namespace object
192
+ export const lit = {
193
+ html,
194
+ css,
195
+ unsafeCSS,
196
+ svg,
197
+ nothing,
198
+ when,
199
+ repeat,
200
+ keyed,
201
+ classMap,
202
+ styleMap,
203
+ ifDefined,
204
+ guard,
205
+ cache,
206
+ unsafeHTML,
207
+ until,
208
+ live,
209
+ ref,
210
+ createRef,
211
+ defineComponent
212
+ };
213
+
@@ -0,0 +1,393 @@
1
+ import { v4 as uuidv4 } from '@kispace-io/appspace/externals/third-party'
2
+
3
+ export const KEY_LABEL = "label";
4
+ export const KEY_NAME = "name";
5
+ export const KEY_URL = "url";
6
+ export const KEY_FORMAT = "format";
7
+ export const KEY_ICON_PATH = "iconPath";
8
+ export const KEY_STATE = "_state";
9
+ export const KEY_SRC = "src";
10
+ export const KEY_SOURCETYPE = "sourceType"
11
+ export const KEY_ENV = "_env"
12
+ export const KEY_GS_MANAGED = "gsManaged"
13
+ export const KEY_SETTINGS = "settings"
14
+ export const KEY_UUID = "uuid"
15
+ export const KEY_EVENT_SUBSCRIPTIONS = "_eventSubscriptions"
16
+
17
+ export const LAYER_GEOCODED_MARKERS = "geocoded-markers"
18
+
19
+ export interface GsBag {
20
+ [key: string]: any
21
+ }
22
+
23
+ export function ensureUuid<T extends GsState>(obj: T): T {
24
+ if (!obj.uuid) {
25
+ obj.uuid = uuidv4()
26
+ }
27
+ return obj
28
+ }
29
+
30
+ export function ensureUuidsRecursive<T extends GsState>(obj: T): T {
31
+ ensureUuid(obj)
32
+
33
+ if ('geometry' in obj && (obj as any).geometry) {
34
+ ensureUuid((obj as any).geometry)
35
+ }
36
+
37
+ if ('source' in obj && (obj as any).source) {
38
+ const source = (obj as any).source
39
+ ensureUuid(source)
40
+ if (source.features && Array.isArray(source.features)) {
41
+ source.features.forEach((feature: any) => ensureUuidsRecursive(feature))
42
+ }
43
+ }
44
+
45
+ if ('layers' in obj && Array.isArray((obj as any).layers)) {
46
+ (obj as any).layers.forEach((layer: any) => ensureUuidsRecursive(layer))
47
+ }
48
+
49
+ if ('overlays' in obj && Array.isArray((obj as any).overlays)) {
50
+ (obj as any).overlays.forEach((overlay: any) => ensureUuid(overlay))
51
+ }
52
+
53
+ if ('controls' in obj && Array.isArray((obj as any).controls)) {
54
+ (obj as any).controls.forEach((control: any) => ensureUuid(control))
55
+ }
56
+
57
+ if ('interactions' in obj && Array.isArray((obj as any).interactions)) {
58
+ (obj as any).interactions.forEach((interaction: any) => ensureUuid(interaction))
59
+ }
60
+
61
+ if ('view' in obj && (obj as any).view) {
62
+ ensureUuid((obj as any).view)
63
+ }
64
+
65
+ return obj
66
+ }
67
+
68
+ export interface GsState {
69
+ uuid?: string
70
+ state?: GsBag
71
+ }
72
+
73
+ export enum GsSourceType {
74
+ OSM = "OSM", GeoJSON = "GeoJSON", Features = "Features", KML = "KML", GeoTIFF = "GeoTIFF", GPX = "GPX", BM = "BM", WMS = "WMS", WMTS = "WMTS", XYZ = "XYZ"
75
+ }
76
+
77
+ export enum GsLayerType {
78
+ TILE = "TILE", VECTOR = "VECTOR", GROUP = "GROUP"
79
+ }
80
+
81
+ export enum GsGeometryType {
82
+ Point = "Point",
83
+ MultiPoint = "MultiPoint",
84
+ Polygon = "Polygon",
85
+ MultiPolygon = "MultiPolygon",
86
+ LineString = "LineString",
87
+ MultiLineString = "MultiLineString",
88
+ Circle = "Circle",
89
+ LinearRing = "LinearRing"
90
+ }
91
+
92
+ export interface GsGeometry extends GsState {
93
+ type: GsGeometryType,
94
+ coordinates: number[]
95
+ }
96
+
97
+ export interface GsResource {
98
+ }
99
+
100
+ export interface GsIcon extends GsResource {
101
+ src: string
102
+ }
103
+
104
+ export interface GsFeature extends GsState {
105
+ geometry: GsGeometry
106
+ }
107
+
108
+ export interface GsSource extends GsState {
109
+ type: GsSourceType
110
+ url?: string
111
+ features?: GsFeature[]
112
+ }
113
+
114
+ export interface GsLayer extends GsState {
115
+ name?: string
116
+ type: GsLayerType,
117
+ source: GsSource,
118
+ visible?: boolean
119
+ }
120
+
121
+ export interface GsScript extends GsState {
122
+ src: string,
123
+ }
124
+
125
+ export interface GsOverlay extends GsScript {
126
+ position: "bottom-left" | "bottom-center" | "bottom-right" | "center-left" | "center-center" | "center-right" | "top-left" | "top-center" | "top-right",
127
+ }
128
+
129
+ export interface GsControl extends GsScript {
130
+ }
131
+
132
+ export interface GsInteraction extends GsState {
133
+
134
+ }
135
+
136
+ export interface GsView extends GsState {
137
+ center: number[],
138
+ zoom: number,
139
+ projection: string
140
+ }
141
+
142
+ export interface GsStrokeStyle {
143
+ color?: string
144
+ width?: number
145
+ lineDash?: number[]
146
+ lineCap?: 'butt' | 'round' | 'square'
147
+ lineJoin?: 'bevel' | 'round' | 'miter'
148
+ miterLimit?: number
149
+ }
150
+
151
+ export interface GsFillStyle {
152
+ color?: string
153
+ }
154
+
155
+ export interface GsImageStyle {
156
+ type: 'circle' | 'icon' | 'regular-shape'
157
+
158
+ radius?: number
159
+ fill?: GsFillStyle
160
+ stroke?: GsStrokeStyle
161
+
162
+ src?: string
163
+ scale?: number
164
+ anchor?: [number, number]
165
+ anchorXUnits?: 'fraction' | 'pixels'
166
+ anchorYUnits?: 'fraction' | 'pixels'
167
+ anchorOrigin?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right'
168
+ color?: string
169
+ crossOrigin?: string
170
+ offset?: [number, number]
171
+ offsetOrigin?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right'
172
+ size?: [number, number]
173
+
174
+ points?: number
175
+ radius1?: number
176
+ radius2?: number
177
+ angle?: number
178
+
179
+ opacity?: number
180
+ rotation?: number
181
+ rotateWithView?: boolean
182
+ displacement?: [number, number]
183
+ }
184
+
185
+ export interface GsTextStyle {
186
+ text?: string
187
+ font?: string
188
+ maxAngle?: number
189
+ offsetX?: number
190
+ offsetY?: number
191
+ overflow?: boolean
192
+ placement?: 'point' | 'line'
193
+ repeat?: number
194
+ scale?: number
195
+ rotateWithView?: boolean
196
+ rotation?: number
197
+ textAlign?: 'left' | 'center' | 'right' | 'end' | 'start'
198
+ justify?: 'left' | 'center' | 'right'
199
+ textBaseline?: 'bottom' | 'top' | 'middle' | 'alphabetic' | 'hanging' | 'ideographic'
200
+ fill?: GsFillStyle
201
+ stroke?: GsStrokeStyle
202
+ backgroundFill?: GsFillStyle
203
+ backgroundStroke?: GsStrokeStyle
204
+ padding?: [number, number, number, number]
205
+ }
206
+
207
+ export interface GsStyle {
208
+ id?: string
209
+ stroke?: GsStrokeStyle
210
+ fill?: GsFillStyle
211
+ image?: GsImageStyle
212
+ text?: GsTextStyle
213
+ zIndex?: number
214
+ }
215
+
216
+ export interface GsStylesMap {
217
+ [key: string]: GsStyle
218
+ }
219
+
220
+ export const DEFAULT_STYLES: GsStylesMap = {
221
+ 'default-point': {
222
+ id: 'default-point',
223
+ image: {
224
+ type: 'circle',
225
+ radius: 5,
226
+ fill: { color: 'rgba(0, 100, 255, 0.8)' },
227
+ stroke: { color: 'white', width: 2 }
228
+ }
229
+ },
230
+ 'default-line': {
231
+ id: 'default-line',
232
+ stroke: {
233
+ color: 'rgba(0, 100, 255, 0.8)',
234
+ width: 2
235
+ }
236
+ },
237
+ 'default-polygon': {
238
+ id: 'default-polygon',
239
+ fill: { color: 'rgba(0, 100, 255, 0.3)' },
240
+ stroke: {
241
+ color: 'rgba(0, 100, 255, 0.8)',
242
+ width: 2
243
+ }
244
+ },
245
+ 'selection': {
246
+ id: 'selection',
247
+ image: {
248
+ type: 'circle',
249
+ radius: 7,
250
+ fill: { color: 'rgba(255, 255, 0, 0.3)' },
251
+ stroke: { color: 'rgba(255, 255, 0, 1)', width: 3 }
252
+ },
253
+ stroke: {
254
+ color: 'rgba(255, 255, 0, 1)',
255
+ width: 3
256
+ },
257
+ fill: {
258
+ color: 'rgba(255, 255, 0, 0.3)'
259
+ }
260
+ }
261
+ }
262
+
263
+ export interface GsStyleRule {
264
+ id?: string
265
+ condition: {
266
+ geometryType?: GsGeometryType | GsGeometryType[]
267
+ layerName?: string
268
+ property?: {
269
+ key: string
270
+ value?: any
271
+ operator?: 'equals' | 'not-equals' | 'contains' | 'greater-than' | 'less-than' | 'exists'
272
+ }
273
+ }
274
+ styleId: string
275
+ priority?: number
276
+ }
277
+
278
+ export function evaluateStyleRule(rule: GsStyleRule, feature: GsFeature, layerName?: string): boolean {
279
+ const condition = rule.condition
280
+
281
+ if (condition.geometryType) {
282
+ const types = Array.isArray(condition.geometryType) ? condition.geometryType : [condition.geometryType]
283
+ if (!types.includes(feature.geometry.type)) {
284
+ return false
285
+ }
286
+ }
287
+
288
+ if (condition.layerName && condition.layerName !== layerName) {
289
+ return false
290
+ }
291
+
292
+ if (condition.property) {
293
+ const prop = condition.property
294
+ const featureValue = feature.state?.[prop.key]
295
+
296
+ if (!prop.operator || prop.operator === 'exists') {
297
+ return featureValue !== undefined
298
+ }
299
+
300
+ if (prop.operator === 'equals') {
301
+ return featureValue === prop.value
302
+ }
303
+
304
+ if (prop.operator === 'not-equals') {
305
+ return featureValue !== prop.value
306
+ }
307
+
308
+ if (prop.operator === 'contains' && typeof featureValue === 'string' && typeof prop.value === 'string') {
309
+ return featureValue.includes(prop.value)
310
+ }
311
+
312
+ if (prop.operator === 'greater-than' && typeof featureValue === 'number' && typeof prop.value === 'number') {
313
+ return featureValue > prop.value
314
+ }
315
+
316
+ if (prop.operator === 'less-than' && typeof featureValue === 'number' && typeof prop.value === 'number') {
317
+ return featureValue < prop.value
318
+ }
319
+ }
320
+
321
+ return true
322
+ }
323
+
324
+ export function getStyleForFeature(feature: GsFeature, rules: GsStyleRule[], stylesMap: GsStylesMap, layerName?: string): GsStyle | undefined {
325
+ const sortedRules = [...rules].sort((a, b) => (b.priority || 0) - (a.priority || 0))
326
+
327
+ for (const rule of sortedRules) {
328
+ if (evaluateStyleRule(rule, feature, layerName)) {
329
+ return stylesMap[rule.styleId]
330
+ }
331
+ }
332
+
333
+ return undefined
334
+ }
335
+
336
+ export interface GsMap extends GsState {
337
+ view: GsView,
338
+ layers: GsLayer[],
339
+ overlays: GsOverlay[],
340
+ controls: GsControl[],
341
+ interactions: GsInteraction[],
342
+ styles: GsStylesMap,
343
+ styleRules: GsStyleRule[],
344
+ chatHistory: any[]
345
+ }
346
+
347
+ export const DEFAULT_STYLE_RULES: GsStyleRule[] = [
348
+ {
349
+ id: 'default-points',
350
+ condition: {
351
+ geometryType: [GsGeometryType.Point, GsGeometryType.MultiPoint]
352
+ },
353
+ styleId: 'default-point',
354
+ priority: 0
355
+ },
356
+ {
357
+ id: 'default-lines',
358
+ condition: {
359
+ geometryType: [GsGeometryType.LineString, GsGeometryType.MultiLineString]
360
+ },
361
+ styleId: 'default-line',
362
+ priority: 0
363
+ },
364
+ {
365
+ id: 'default-polygons',
366
+ condition: {
367
+ geometryType: [GsGeometryType.Polygon, GsGeometryType.MultiPolygon, GsGeometryType.Circle]
368
+ },
369
+ styleId: 'default-polygon',
370
+ priority: 0
371
+ }
372
+ ]
373
+
374
+ export const DEFAULT_GSMAP = ensureUuid({
375
+ view: ensureUuid({
376
+ center: [0, 0],
377
+ zoom: 0,
378
+ projection: 'EPSG:3857'
379
+ } as GsView),
380
+ layers: [ensureUuid({
381
+ type: GsLayerType.TILE,
382
+ source: ensureUuid({
383
+ type: GsSourceType.OSM
384
+ } as GsSource),
385
+ } as GsLayer)],
386
+ overlays: [] as GsOverlay[],
387
+ controls: [] as GsControl[],
388
+ interactions: [] as GsInteraction[],
389
+ state: {},
390
+ styles: { ...DEFAULT_STYLES },
391
+ styleRules: [...DEFAULT_STYLE_RULES]
392
+ } as GsMap)
393
+
@@ -0,0 +1,89 @@
1
+ import {Map} from "ol";
2
+ import {GsOlControl, GsOlOverlay} from "./gs-gs2ol";
3
+ import {render as litRender} from "@kispace-io/appspace/externals/lit-exports";
4
+
5
+ export class GsOlAdapter<T extends GsOlControl | GsOlOverlay> {
6
+ protected map: Map;
7
+ protected olObject: T;
8
+
9
+ private templateFunction?: Function;
10
+ protected retargetSelector?: string;
11
+
12
+ constructor(olObject: T) {
13
+ this.map = olObject.getMap()!
14
+ this.olObject = olObject
15
+ }
16
+
17
+ public getMap(): any {
18
+ return this.map;
19
+ }
20
+
21
+ public getElement() {
22
+ return this.olObject.getElement();
23
+ }
24
+
25
+ public render(strings?: TemplateStringsArray | Function) {
26
+ if (strings === undefined && this.templateFunction) {
27
+ strings = this.templateFunction()
28
+ } else if (strings instanceof Function) {
29
+ this.templateFunction = strings as Function
30
+ strings = this.templateFunction()
31
+ }
32
+ if (strings) {
33
+ litRender(strings, this.getElement())
34
+ }
35
+ }
36
+
37
+ protected onRendered() {
38
+ }
39
+
40
+ public style(styleJson: any) {
41
+ const style = this.getElement().style
42
+ for (const property in styleJson) {
43
+ const value = styleJson[property]
44
+ style.setProperty(property, value);
45
+ }
46
+ }
47
+ }
48
+
49
+ export class GsControlAdapter extends GsOlAdapter<GsOlControl> {
50
+ public style(styleJson: any) {
51
+ super.style(styleJson)
52
+
53
+ if ("--gs-contribution" in styleJson) {
54
+ this.retargetSelector = styleJson["--gs-contribution"]
55
+ }
56
+ }
57
+
58
+ public rendered() {
59
+ if (this.retargetSelector) {
60
+ const [parentPath, queryString] = this.retargetSelector.split("?");
61
+ const parent = this.map.getTargetElement().querySelector(parentPath) as HTMLElement
62
+ if (parent) {
63
+ const element = this.olObject.getElement()
64
+ if (queryString) {
65
+ const params = new URLSearchParams(queryString);
66
+ const sibling = parent.querySelector(`[name='${params.get("before")}']`) as HTMLElement
67
+ if (sibling) {
68
+ parent.insertBefore(element, sibling)
69
+ }
70
+ } else {
71
+ parent.appendChild(element)
72
+ }
73
+ this.olObject.setTarget(element);
74
+ this.render()
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ export class GsOverlayAdapter extends GsOlAdapter<GsOlOverlay> {
81
+ public show(coords: number[]) {
82
+ this.getElement().style.display = "block"
83
+ this.olObject.setPosition(coords)
84
+ }
85
+
86
+ public hide() {
87
+ this.getElement().style.display = "none"
88
+ }
89
+ }