@softwarity/geojson-editor 1.0.24 → 1.0.25

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.
@@ -11,10 +11,15 @@
11
11
  }
12
12
 
13
13
  :host {
14
+ /* Color scheme - inherits from parent, falls back to system preference if not set */
15
+ color-scheme: inherit;
16
+
17
+ /* Layout variables (internal only) */
14
18
  --line-height: 19.5px;
15
19
  --gutter-width: 50px;
16
20
  --editor-padding-y: 8px;
17
21
  --editor-padding-x: 12px;
22
+
18
23
  display: flex;
19
24
  flex-direction: column;
20
25
  position: relative;
@@ -39,7 +44,7 @@
39
44
  position: relative;
40
45
  width: 100%;
41
46
  flex: 1;
42
- background: var(--bg-color, #fff);
47
+ background: var(--geojson-editor-bg-color, light-dark(#fff, #2b2b2b));
43
48
  display: flex;
44
49
  overflow: hidden;
45
50
  }
@@ -47,8 +52,8 @@
47
52
  /* ========== Gutter ========== */
48
53
  .gutter {
49
54
  width: var(--gutter-width);
50
- background: var(--gutter-bg, #f0f0f0);
51
- border-right: 1px solid var(--gutter-border, #e0e0e0);
55
+ background: var(--geojson-editor-gutter-bg, light-dark(#f0f0f0, #313335));
56
+ border-right: 1px solid var(--geojson-editor-gutter-border, light-dark(#e0e0e0, #3c3f41));
52
57
  overflow: hidden;
53
58
  flex-shrink: 0;
54
59
  position: relative;
@@ -90,12 +95,12 @@
90
95
  top: 0;
91
96
  bottom: 0;
92
97
  width: 3px;
93
- background: var(--error-color, #dc3545);
98
+ background: var(--geojson-editor-error-color, light-dark(#dc3545, #ff6b68));
94
99
  }
95
100
 
96
101
  .line-number {
97
102
  font-size: 11px;
98
- color: var(--gutter-text, #999);
103
+ color: var(--geojson-editor-gutter-text, light-dark(#999, #606366));
99
104
  user-select: none;
100
105
  min-width: 20px;
101
106
  text-align: right;
@@ -118,7 +123,7 @@
118
123
  flex-shrink: 0;
119
124
  background: transparent;
120
125
  border: none;
121
- color: var(--json-punct, #a9b7c6);
126
+ color: var(--geojson-editor-json-punct, light-dark(#000, #a9b7c6));
122
127
  font-size: 10px;
123
128
  display: flex;
124
129
  align-items: center;
@@ -178,7 +183,7 @@
178
183
  padding: var(--editor-padding-y) var(--editor-padding-x);
179
184
  overscroll-behavior: contain; /* Prevent scroll chaining to parent */
180
185
  scrollbar-width: thin;
181
- scrollbar-color: var(--control-border, #c0c0c0) var(--control-bg, #e8e8e8);
186
+ scrollbar-color: var(--geojson-editor-control-border, light-dark(#c0c0c0, #5a5a5a)) var(--geojson-editor-control-bg, light-dark(#e8e8e8, #3c3f41));
182
187
  }
183
188
 
184
189
  /* Scroll content - defines total scrollable height */
@@ -209,7 +214,7 @@
209
214
  position: absolute;
210
215
  width: 2px;
211
216
  height: 1em;
212
- background: var(--caret-color, #000);
217
+ background: var(--geojson-editor-caret-color, light-dark(#000, #bbb));
213
218
  top: 0.15em;
214
219
  pointer-events: none;
215
220
  animation: cursor-blink 1s step-end infinite;
@@ -237,7 +242,7 @@
237
242
  position: absolute;
238
243
  height: 100%;
239
244
  top: 0;
240
- background: var(--selection-color, rgba(51, 153, 255, 0.3));
245
+ background: var(--geojson-editor-selection-color, light-dark(rgba(51, 153, 255, 0.3), rgba(51, 153, 255, 0.4)));
241
246
  pointer-events: none;
242
247
  z-index: 0;
243
248
  }
@@ -259,47 +264,47 @@
259
264
  }
260
265
 
261
266
  /* ========== Syntax Highlighting ========== */
262
- .json-key { color: var(--json-key, #660e7a); }
263
- .json-string { color: var(--json-string, #008000); }
264
- .json-number { color: var(--json-number, #00f); }
265
- .json-boolean, .json-null { color: var(--json-boolean, #000080); }
266
- .json-punctuation { color: var(--json-punct, #000); }
267
- .json-error { color: var(--json-error, #f00); }
267
+ .json-key { color: var(--geojson-editor-json-key, light-dark(#660e7a, #9876aa)); }
268
+ .json-string { color: var(--geojson-editor-json-string, light-dark(#008000, #6a8759)); }
269
+ .json-number { color: var(--geojson-editor-json-number, light-dark(#00f, #6897bb)); }
270
+ .json-boolean, .json-null { color: var(--geojson-editor-json-boolean, light-dark(#000080, #cc7832)); }
271
+ .json-punctuation { color: var(--geojson-editor-json-punct, light-dark(#000, #a9b7c6)); }
272
+ .json-error { color: var(--geojson-editor-json-error, light-dark(#f00, #ff6b68)); }
268
273
 
269
- .geojson-key { color: var(--geojson-key, #660e7a); font-weight: 600; }
270
- .geojson-type { color: var(--geojson-type, #008000); font-weight: 600; }
271
- .geojson-type-invalid { color: var(--geojson-type-invalid, #f00); font-weight: 600; }
274
+ .geojson-key { color: var(--geojson-editor-geojson-key, light-dark(#660e7a, #9876aa)); font-weight: 600; }
275
+ .geojson-type { color: var(--geojson-editor-geojson-type, light-dark(#008000, #6a8759)); font-weight: 600; }
276
+ .geojson-type-invalid { color: var(--geojson-editor-geojson-type-invalid, light-dark(#f00, #ff6b68)); font-weight: 600; }
272
277
 
273
278
  /* Collapsed node styling */
274
279
  .collapsed-bracket-array,
275
280
  .collapsed-bracket-object {
276
- color: var(--json-punct, #000);
281
+ color: var(--geojson-editor-json-punct, light-dark(#000, #a9b7c6));
277
282
  }
278
283
  .collapsed-bracket-array::after,
279
284
  .collapsed-bracket-object::after {
280
285
  content: '…';
281
- color: var(--json-punct, #888);
286
+ color: var(--geojson-editor-json-punct, light-dark(#000, #a9b7c6));
282
287
  }
283
288
 
284
289
  /* ========== Prefix/Suffix ========== */
285
290
  .prefix-wrapper, .suffix-wrapper {
286
291
  display: flex;
287
292
  flex-shrink: 0;
288
- background: var(--bg-color, #fff);
293
+ background: var(--geojson-editor-bg-color, light-dark(#fff, #2b2b2b));
289
294
  }
290
295
 
291
296
  .prefix-gutter, .suffix-gutter {
292
297
  width: var(--gutter-width);
293
- background: var(--gutter-bg, #f0f0f0);
294
- border-right: 1px solid var(--gutter-border, #e0e0e0);
298
+ background: var(--geojson-editor-gutter-bg, light-dark(#f0f0f0, #313335));
299
+ border-right: 1px solid var(--geojson-editor-gutter-border, light-dark(#e0e0e0, #3c3f41));
295
300
  flex-shrink: 0;
296
301
  }
297
302
 
298
303
  .editor-prefix, .editor-suffix {
299
304
  flex: 1;
300
305
  padding: 4px 12px;
301
- color: var(--text-color, #000);
302
- background: var(--bg-color, #fff);
306
+ color: var(--geojson-editor-text-color, light-dark(#000, #a9b7c6));
307
+ background: var(--geojson-editor-bg-color, light-dark(#fff, #2b2b2b));
303
308
  user-select: none;
304
309
  white-space: pre-wrap;
305
310
  word-wrap: break-word;
@@ -316,7 +321,7 @@
316
321
  transform: translateY(-50%);
317
322
  background: transparent;
318
323
  border: none;
319
- color: var(--text-color, #000);
324
+ color: var(--geojson-editor-text-color, light-dark(#000, #a9b7c6));
320
325
  opacity: 0.15;
321
326
  cursor: pointer;
322
327
  font-size: 0.7rem;
@@ -339,8 +344,8 @@
339
344
  top: 2rem;
340
345
  right: 0.5rem;
341
346
  z-index: 1000;
342
- background: var(--bg-color, #ffffff);
343
- border: 1px solid var(--gutter-border, #e0e0e0);
347
+ background: var(--geojson-editor-bg-color, light-dark(#fff, #2b2b2b));
348
+ border: 1px solid var(--geojson-editor-gutter-border, light-dark(#e0e0e0, #3c3f41));
344
349
  border-radius: 6px;
345
350
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
346
351
  padding: 12px 16px;
@@ -356,13 +361,13 @@
356
361
  .info-popup-title {
357
362
  font-weight: bold;
358
363
  font-size: 13px;
359
- color: var(--text-color, #000000);
364
+ color: var(--geojson-editor-text-color, light-dark(#000, #a9b7c6));
360
365
  margin-bottom: 4px;
361
366
  }
362
367
  .info-popup-version {
363
368
  display: block;
364
369
  font-size: 11px;
365
- color: var(--text-color, #000000);
370
+ color: var(--geojson-editor-text-color, light-dark(#000, #a9b7c6));
366
371
  opacity: 0.6;
367
372
  margin-bottom: 8px;
368
373
  text-decoration: none;
@@ -373,7 +378,7 @@
373
378
  }
374
379
  .info-popup-copyright {
375
380
  font-size: 10px;
376
- color: var(--text-color, #000000);
381
+ color: var(--geojson-editor-text-color, light-dark(#000, #a9b7c6));
377
382
  opacity: 0.5;
378
383
  }
379
384
 
@@ -384,7 +389,7 @@
384
389
  transform: translateY(-50%);
385
390
  background: transparent;
386
391
  border: none;
387
- color: var(--text-color, #000);
392
+ color: var(--geojson-editor-text-color, light-dark(#000, #a9b7c6));
388
393
  opacity: 0.3;
389
394
  cursor: pointer;
390
395
  font-size: 0.65rem;
@@ -413,7 +418,7 @@
413
418
  .error-nav-btn {
414
419
  background: transparent;
415
420
  border: none;
416
- color: var(--error-color, #dc3545);
421
+ color: var(--geojson-editor-error-color, light-dark(#dc3545, #ff6b68));
417
422
  cursor: pointer;
418
423
  font-size: 8px;
419
424
  width: 16px;
@@ -429,7 +434,7 @@
429
434
  opacity: 1;
430
435
  }
431
436
  .error-count {
432
- color: var(--error-color, #dc3545);
437
+ color: var(--geojson-editor-error-color, light-dark(#dc3545, #ff6b68));
433
438
  font-size: 11px;
434
439
  min-width: 20px;
435
440
  text-align: center;
@@ -437,9 +442,9 @@
437
442
 
438
443
  /* ========== Scrollbar ========== */
439
444
  .viewport::-webkit-scrollbar { width: 10px; height: 10px; }
440
- .viewport::-webkit-scrollbar-track { background: var(--control-bg, #e8e8e8); }
441
- .viewport::-webkit-scrollbar-thumb { background: var(--control-border, #c0c0c0); border-radius: 5px; }
442
- .viewport::-webkit-scrollbar-thumb:hover { background: var(--control-color, #000080); }
445
+ .viewport::-webkit-scrollbar-track { background: var(--geojson-editor-control-bg, light-dark(#e8e8e8, #3c3f41)); }
446
+ .viewport::-webkit-scrollbar-thumb { background: var(--geojson-editor-control-border, light-dark(#c0c0c0, #5a5a5a)); border-radius: 5px; }
447
+ .viewport::-webkit-scrollbar-thumb:hover { background: var(--geojson-editor-control-color, light-dark(#000080, #cc7832)); }
443
448
 
444
449
  /* ========== Inline Controls (using ::before pseudo-elements) ========== */
445
450
 
@@ -464,24 +469,24 @@
464
469
  .json-color:hover::before,
465
470
  .json-boolean:hover::before {
466
471
  transform: translateY(-50%) scale(1.2);
467
- border-color: var(--control-color, #000080);
472
+ border-color: var(--geojson-editor-control-color, light-dark(#000080, #cc7832));
468
473
  }
469
474
 
470
475
  /* Color swatch specific styles */
471
476
  .json-color::before {
472
477
  background-color: var(--swatch-color);
473
- border: 1px solid var(--json-punct, #a9b7c6);
478
+ border: 1px solid var(--geojson-editor-json-punct, light-dark(#000, #a9b7c6));
474
479
  }
475
480
 
476
481
  /* Boolean checkbox specific styles */
477
482
  .json-boolean::before {
478
- border: 1.5px solid var(--control-border, #c0c0c0);
483
+ border: 1.5px solid var(--geojson-editor-control-border, light-dark(#c0c0c0, #5a5a5a));
479
484
  background: transparent;
480
485
  }
481
486
  .json-bool-true::before {
482
487
  content: '✔';
483
- border-color: var(--control-color, #000080);
484
- color: var(--control-color, #000080);
488
+ border-color: var(--geojson-editor-control-color, light-dark(#000080, #cc7832));
489
+ color: var(--geojson-editor-control-color, light-dark(#000080, #cc7832));
485
490
  font-size: 8px;
486
491
  display: flex;
487
492
  align-items: center;
@@ -496,7 +501,7 @@
496
501
  left: 0;
497
502
  top: 3px;
498
503
  font-size: 10px;
499
- color: var(--control-color, #000080);
504
+ color: var(--geojson-editor-control-color, light-dark(#000080, #cc7832));
500
505
  opacity: 0.6;
501
506
  cursor: pointer;
502
507
  z-index: 1;
@@ -4,8 +4,7 @@ import type { Feature } from 'geojson';
4
4
 
5
5
  // ========== Imports from extracted modules ==========
6
6
  import type {
7
- SetOptions,
8
- ThemeSettings
7
+ SetOptions
9
8
  } from './types.js';
10
9
 
11
10
  import type {
@@ -35,19 +34,18 @@ import {
35
34
  RE_BRACKET_POS,
36
35
  RE_IS_WORD_CHAR,
37
36
  RE_ATTR_AND_BOOL_VALUE,
38
- RE_TO_KEBAB,
39
37
  RE_OPEN_BRACES,
40
38
  RE_CLOSE_BRACES,
41
39
  RE_OPEN_BRACKETS,
42
40
  RE_CLOSE_BRACKET
43
41
  } from './constants.js';
44
42
 
45
- import { createElement, countBrackets, parseSelectorToHostRule } from './utils.js';
43
+ import { createElement, countBrackets } from './utils.js';
46
44
  import { validateGeoJSON, normalizeToFeatures } from './validation.js';
47
45
  import { highlightSyntax, namedColorToHex, isNamedColor } from './syntax-highlighter.js';
48
46
 
49
47
  // Re-export public types
50
- export type { SetOptions, ThemeConfig, ThemeSettings } from './types.js';
48
+ export type { SetOptions } from './types.js';
51
49
 
52
50
  // Alias for minification
53
51
  const _ce = createElement;
@@ -94,8 +92,6 @@ class GeoJsonEditor extends HTMLElement {
94
92
  private renderTimer: ReturnType<typeof setTimeout> | undefined = undefined;
95
93
  private inputTimer: ReturnType<typeof setTimeout> | undefined = undefined;
96
94
 
97
- // ========== Theme ==========
98
- themes: ThemeSettings = { dark: {}, light: {} };
99
95
 
100
96
  // ========== Undo/Redo History ==========
101
97
  private _undoStack: EditorSnapshot[] = [];
@@ -116,6 +112,7 @@ class GeoJsonEditor extends HTMLElement {
116
112
  private _contextMapFirstLine: string | undefined = undefined;
117
113
  private _contextMapLastLine: string | undefined = undefined;
118
114
  private _errorLinesCache: Set<number> | null = null;
115
+ private _lastCursorFeatureIndex: number | null = null; // For current-feature event deduplication
119
116
 
120
117
  // ========== Cached DOM Elements ==========
121
118
  private _viewport: HTMLElement | null = null;
@@ -440,7 +437,7 @@ class GeoJsonEditor extends HTMLElement {
440
437
 
441
438
  // ========== Observed Attributes ==========
442
439
  static get observedAttributes() {
443
- return ['readonly', 'value', 'placeholder', 'dark-selector', 'internal-add-shortcut'];
440
+ return ['readonly', 'value', 'placeholder', 'internal-add-shortcut'];
444
441
  }
445
442
 
446
443
  // ========== Lifecycle ==========
@@ -449,7 +446,6 @@ class GeoJsonEditor extends HTMLElement {
449
446
  this._cacheElements();
450
447
  this.setupEventListeners();
451
448
  this.updatePrefixSuffix();
452
- this.updateThemeCSS();
453
449
 
454
450
  if (this.value) {
455
451
  this.setValue(this.value);
@@ -484,9 +480,6 @@ class GeoJsonEditor extends HTMLElement {
484
480
  case 'placeholder':
485
481
  this.updatePlaceholderContent();
486
482
  break;
487
- case 'dark-selector':
488
- this.updateThemeCSS();
489
- break;
490
483
  }
491
484
  }
492
485
 
@@ -697,12 +690,16 @@ class GeoJsonEditor extends HTMLElement {
697
690
  editorWrapper.classList.add('focused');
698
691
  this._invalidateRenderCache(); // Force re-render to show cursor
699
692
  this.scheduleRender();
693
+ // Emit current feature on focus (force to always emit on focus gain)
694
+ this._emitCurrentFeature(true);
700
695
  });
701
696
 
702
697
  hiddenTextarea.addEventListener('blur', () => {
703
698
  editorWrapper.classList.remove('focused');
704
699
  this._invalidateRenderCache(); // Force re-render to hide cursor
705
700
  this.scheduleRender();
701
+ // Emit null on blur
702
+ this._emitCurrentFeatureNull();
706
703
  });
707
704
 
708
705
  // Scroll handling
@@ -1324,11 +1321,16 @@ class GeoJsonEditor extends HTMLElement {
1324
1321
 
1325
1322
  linesContainer.innerHTML = '';
1326
1323
  linesContainer.appendChild(fragment);
1327
-
1324
+
1328
1325
  // Render gutter with same range
1329
1326
  this.renderGutter(startIndex, endIndex);
1327
+
1328
+ // Emit current-feature event if feature changed (only when editor is focused)
1329
+ if (this._editorWrapper?.classList.contains('focused')) {
1330
+ this._emitCurrentFeature();
1331
+ }
1330
1332
  }
1331
-
1333
+
1332
1334
  /**
1333
1335
  * Insert cursor element at the specified column position
1334
1336
  * Uses absolute positioning to avoid affecting text layout
@@ -2757,7 +2759,14 @@ class GeoJsonEditor extends HTMLElement {
2757
2759
  // Try to parse as GeoJSON and normalize
2758
2760
  let pastedFeatureCount = 0;
2759
2761
  try {
2760
- const parsed = JSON.parse(text);
2762
+ // First try direct parse (single Feature, Feature[], or FeatureCollection)
2763
+ let parsed;
2764
+ try {
2765
+ parsed = JSON.parse(text);
2766
+ } catch {
2767
+ // If direct parse fails, try wrapping with [] (for "feature, feature" format from editor copy)
2768
+ parsed = JSON.parse('[' + text + ']');
2769
+ }
2761
2770
  const features = normalizeToFeatures(parsed);
2762
2771
  pastedFeatureCount = features.length;
2763
2772
  // Valid GeoJSON - insert formatted features
@@ -3532,6 +3541,51 @@ class GeoJsonEditor extends HTMLElement {
3532
3541
  }
3533
3542
  }
3534
3543
 
3544
+ /**
3545
+ * Emit current-feature event when cursor moves to a different feature
3546
+ * Only emits when the feature changes (not on every cursor move)
3547
+ * @param force - If true, emit even if feature hasn't changed (used on focus)
3548
+ */
3549
+ private _emitCurrentFeature(force: boolean = false): void {
3550
+ const featureIndex = this._getFeatureIndexForLine(this.cursorLine);
3551
+
3552
+ // Only emit if feature changed (unless forced)
3553
+ if (!force && featureIndex === this._lastCursorFeatureIndex) return;
3554
+ this._lastCursorFeatureIndex = featureIndex;
3555
+
3556
+ if (featureIndex === -1) {
3557
+ // Cursor is not in a feature
3558
+ this.dispatchEvent(new CustomEvent('current-feature', {
3559
+ detail: null,
3560
+ bubbles: true,
3561
+ composed: true
3562
+ }));
3563
+ } else {
3564
+ // Get the feature at cursor
3565
+ const features = this._parseFeatures();
3566
+ const feature = features[featureIndex] || null;
3567
+
3568
+ this.dispatchEvent(new CustomEvent('current-feature', {
3569
+ detail: feature,
3570
+ bubbles: true,
3571
+ composed: true
3572
+ }));
3573
+ }
3574
+ }
3575
+
3576
+ /**
3577
+ * Emit current-feature with null (used on blur)
3578
+ * Always emits to ensure map is cleared when editor loses focus
3579
+ */
3580
+ private _emitCurrentFeatureNull(): void {
3581
+ this._lastCursorFeatureIndex = null;
3582
+ this.dispatchEvent(new CustomEvent('current-feature', {
3583
+ detail: null,
3584
+ bubbles: true,
3585
+ composed: true
3586
+ }));
3587
+ }
3588
+
3535
3589
  // ========== UI Updates ==========
3536
3590
 
3537
3591
  updateReadonly() {
@@ -3573,74 +3627,6 @@ class GeoJsonEditor extends HTMLElement {
3573
3627
  if (this._editorSuffix) this._editorSuffix.textContent = this.suffix;
3574
3628
  }
3575
3629
 
3576
- // ========== Theme ==========
3577
-
3578
- updateThemeCSS() {
3579
- const darkSelector = this.getAttribute('dark-selector') || '.dark';
3580
- const darkRule = parseSelectorToHostRule(darkSelector);
3581
-
3582
- let themeStyle = this._id('theme-styles') as HTMLStyleElement;
3583
- if (!themeStyle) {
3584
- themeStyle = _ce('style') as HTMLStyleElement;
3585
- themeStyle.id = 'theme-styles';
3586
- this.shadowRoot!.insertBefore(themeStyle, this.shadowRoot!.firstChild);
3587
- }
3588
-
3589
- const darkDefaults = {
3590
- bgColor: '#2b2b2b',
3591
- textColor: '#a9b7c6',
3592
- caretColor: '#bbb',
3593
- gutterBg: '#313335',
3594
- gutterBorder: '#3c3f41',
3595
- gutterText: '#606366',
3596
- jsonKey: '#9876aa',
3597
- jsonString: '#6a8759',
3598
- jsonNumber: '#6897bb',
3599
- jsonBoolean: '#cc7832',
3600
- jsonNull: '#cc7832',
3601
- jsonPunct: '#a9b7c6',
3602
- jsonError: '#ff6b68',
3603
- controlColor: '#cc7832',
3604
- controlBg: '#3c3f41',
3605
- controlBorder: '#5a5a5a',
3606
- geojsonKey: '#9876aa',
3607
- geojsonType: '#6a8759',
3608
- geojsonTypeInvalid: '#ff6b68',
3609
- jsonKeyInvalid: '#ff6b68'
3610
- };
3611
-
3612
- RE_TO_KEBAB.lastIndex = 0;
3613
- const toKebab = (str: string) => str.replace(RE_TO_KEBAB, '-$1').toLowerCase();
3614
- const generateVars = (obj: Record<string, string | undefined>) => Object.entries(obj)
3615
- .filter((entry): entry is [string, string] => entry[1] !== undefined)
3616
- .map(([k, v]) => `--${toKebab(k)}: ${v};`)
3617
- .join('\n ');
3618
-
3619
- const lightVars = generateVars(this.themes.light as Record<string, string | undefined> || {});
3620
- const darkTheme = { ...darkDefaults, ...this.themes.dark };
3621
- const darkVars = generateVars(darkTheme as Record<string, string | undefined>);
3622
-
3623
- let css = lightVars ? `:host {\n ${lightVars}\n }\n` : '';
3624
- css += `${darkRule} {\n ${darkVars}\n }`;
3625
-
3626
- themeStyle.textContent = css;
3627
- }
3628
-
3629
- setTheme(theme: ThemeSettings): void {
3630
- if (theme.dark) this.themes.dark = { ...this.themes.dark, ...theme.dark };
3631
- if (theme.light) this.themes.light = { ...this.themes.light, ...theme.light };
3632
- this.updateThemeCSS();
3633
- }
3634
-
3635
- resetTheme(): void {
3636
- this.themes = { dark: {}, light: {} };
3637
- this.updateThemeCSS();
3638
- }
3639
-
3640
- getTheme(): ThemeSettings {
3641
- return { ...this.themes };
3642
- }
3643
-
3644
3630
  /**
3645
3631
  * Find all collapsible ranges using the mappings built by _rebuildNodeIdMappings
3646
3632
  * This method only READS the existing mappings, it doesn't create new IDs
@@ -4066,6 +4052,10 @@ class GeoJsonEditor extends HTMLElement {
4066
4052
  this.lines = [];
4067
4053
  this.collapsedNodes.clear();
4068
4054
  this.hiddenFeatures.clear();
4055
+ this.cursorLine = 0;
4056
+ this.cursorColumn = 0;
4057
+ this.selectionStart = null;
4058
+ this.selectionEnd = null;
4069
4059
  this.updateModel();
4070
4060
  this.scheduleRender();
4071
4061
  this.updatePlaceholderVisibility();
package/src/types.ts CHANGED
@@ -16,33 +16,3 @@ export interface SetOptions {
16
16
  */
17
17
  collapsed?: string[] | ((feature: Feature | null, index: number) => string[]);
18
18
  }
19
-
20
- /** Theme configuration */
21
- export interface ThemeConfig {
22
- bgColor?: string;
23
- textColor?: string;
24
- caretColor?: string;
25
- gutterBg?: string;
26
- gutterBorder?: string;
27
- gutterText?: string;
28
- jsonKey?: string;
29
- jsonString?: string;
30
- jsonNumber?: string;
31
- jsonBoolean?: string;
32
- jsonNull?: string;
33
- jsonPunct?: string;
34
- jsonError?: string;
35
- controlColor?: string;
36
- controlBg?: string;
37
- controlBorder?: string;
38
- geojsonKey?: string;
39
- geojsonType?: string;
40
- geojsonTypeInvalid?: string;
41
- jsonKeyInvalid?: string;
42
- }
43
-
44
- /** Theme settings for dark and light modes */
45
- export interface ThemeSettings {
46
- dark?: ThemeConfig;
47
- light?: ThemeConfig;
48
- }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * GitHub Theme for @softwarity/geojson-editor
3
+ *
4
+ * Clean theme inspired by GitHub's code styling.
5
+ *
6
+ * Usage:
7
+ * <link rel="stylesheet" href="themes/github.css">
8
+ * <geojson-editor></geojson-editor>
9
+ */
10
+
11
+ :root {
12
+ /* Editor background and text */
13
+ --geojson-editor-bg-color: light-dark(#ffffff, #0d1117);
14
+ --geojson-editor-text-color: light-dark(#24292f, #c9d1d9);
15
+ --geojson-editor-caret-color: light-dark(#24292f, #c9d1d9);
16
+
17
+ /* Gutter (line numbers area) */
18
+ --geojson-editor-gutter-bg: light-dark(#f6f8fa, #161b22);
19
+ --geojson-editor-gutter-border: light-dark(#d0d7de, #30363d);
20
+ --geojson-editor-gutter-text: light-dark(#8c959f, #6e7681);
21
+
22
+ /* JSON syntax highlighting */
23
+ --geojson-editor-json-key: light-dark(#0550ae, #79c0ff);
24
+ --geojson-editor-json-string: light-dark(#0a3069, #a5d6ff);
25
+ --geojson-editor-json-number: light-dark(#0550ae, #79c0ff);
26
+ --geojson-editor-json-boolean: light-dark(#cf222e, #ff7b72);
27
+ --geojson-editor-json-punct: light-dark(#24292f, #c9d1d9);
28
+ --geojson-editor-json-error: light-dark(#cf222e, #ff7b72);
29
+
30
+ /* GeoJSON-specific */
31
+ --geojson-editor-geojson-key: light-dark(#8250df, #d2a8ff);
32
+ --geojson-editor-geojson-type: light-dark(#116329, #7ee787);
33
+ --geojson-editor-geojson-type-invalid: light-dark(#cf222e, #ff7b72);
34
+
35
+ /* Controls (checkboxes, color swatches) */
36
+ --geojson-editor-control-color: light-dark(#0550ae, #79c0ff);
37
+ --geojson-editor-control-bg: light-dark(#f6f8fa, #21262d);
38
+ --geojson-editor-control-border: light-dark(#d0d7de, #30363d);
39
+
40
+ /* Selection and errors */
41
+ --geojson-editor-selection-color: light-dark(rgba(5, 80, 174, 0.2), rgba(56, 139, 253, 0.3));
42
+ --geojson-editor-error-color: light-dark(#cf222e, #ff7b72);
43
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Monokai Theme for @softwarity/geojson-editor
3
+ *
4
+ * Classic dark theme inspired by Monokai color scheme.
5
+ *
6
+ * Usage:
7
+ * <link rel="stylesheet" href="themes/monokai.css">
8
+ * <geojson-editor></geojson-editor>
9
+ */
10
+
11
+ :root {
12
+ /* Editor background and text */
13
+ --geojson-editor-bg-color: light-dark(#fafafa, #272822);
14
+ --geojson-editor-text-color: light-dark(#49483e, #f8f8f2);
15
+ --geojson-editor-caret-color: light-dark(#49483e, #f8f8f0);
16
+
17
+ /* Gutter (line numbers area) */
18
+ --geojson-editor-gutter-bg: light-dark(#f0f0f0, #3e3d32);
19
+ --geojson-editor-gutter-border: light-dark(#e0e0e0, #49483e);
20
+ --geojson-editor-gutter-text: light-dark(#999, #75715e);
21
+
22
+ /* JSON syntax highlighting */
23
+ --geojson-editor-json-key: light-dark(#f92672, #f92672);
24
+ --geojson-editor-json-string: light-dark(#718c00, #e6db74);
25
+ --geojson-editor-json-number: light-dark(#ae81ff, #ae81ff);
26
+ --geojson-editor-json-boolean: light-dark(#66d9ef, #66d9ef);
27
+ --geojson-editor-json-punct: light-dark(#49483e, #f8f8f2);
28
+ --geojson-editor-json-error: light-dark(#f92672, #f92672);
29
+
30
+ /* GeoJSON-specific */
31
+ --geojson-editor-geojson-key: light-dark(#f92672, #a6e22e);
32
+ --geojson-editor-geojson-type: light-dark(#718c00, #e6db74);
33
+ --geojson-editor-geojson-type-invalid: light-dark(#f92672, #f92672);
34
+
35
+ /* Controls (checkboxes, color swatches) */
36
+ --geojson-editor-control-color: light-dark(#66d9ef, #66d9ef);
37
+ --geojson-editor-control-bg: light-dark(#e8e8e8, #3e3d32);
38
+ --geojson-editor-control-border: light-dark(#c0c0c0, #75715e);
39
+
40
+ /* Selection and errors */
41
+ --geojson-editor-selection-color: light-dark(rgba(174, 129, 255, 0.2), rgba(174, 129, 255, 0.3));
42
+ --geojson-editor-error-color: light-dark(#f92672, #f92672);
43
+ }