@nocturnium/svelte-ide 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/components/editor/CognitiveLoadMeter.svelte +27 -0
  2. package/dist/components/editor/ComplexityHeatLayer.svelte +157 -0
  3. package/dist/components/editor/ComplexityHeatLayer.svelte.d.ts +24 -0
  4. package/dist/components/editor/ComplexityLayer.svelte +325 -109
  5. package/dist/components/editor/ComplexityLayer.svelte.d.ts +13 -0
  6. package/dist/components/editor/ConflictZoneLayer.svelte +22 -15
  7. package/dist/components/editor/CustomEditor.svelte +80 -1
  8. package/dist/components/editor/CustomEditor.svelte.d.ts +3 -1
  9. package/dist/components/editor/EchoCursorLayer.svelte +60 -0
  10. package/dist/components/editor/PluginPreviewSandbox.svelte +43 -9
  11. package/dist/components/editor/PluginPreviewSandbox.svelte.d.ts +4 -4
  12. package/dist/components/editor/core/complexity-analyzer.d.ts +31 -0
  13. package/dist/components/editor/core/complexity-analyzer.js +479 -29
  14. package/dist/components/editor/core/conflict-predictor.d.ts +32 -0
  15. package/dist/components/editor/core/conflict-predictor.js +55 -0
  16. package/dist/components/editor/core/crdt-binding.d.ts +4 -0
  17. package/dist/components/editor/core/crdt-binding.js +34 -9
  18. package/dist/components/editor/core/echo-cursor.d.ts +18 -1
  19. package/dist/components/editor/core/echo-cursor.js +117 -6
  20. package/dist/components/editor/core/extract-function.d.ts +27 -0
  21. package/dist/components/editor/core/extract-function.js +865 -0
  22. package/dist/components/editor/core/index.d.ts +1 -0
  23. package/dist/components/editor/core/index.js +1 -0
  24. package/dist/components/editor/core/state.d.ts +38 -5
  25. package/dist/components/editor/core/state.js +175 -98
  26. package/dist/components/editor/core/timeline.js +6 -1
  27. package/dist/components/editor/editor-find.js +15 -3
  28. package/dist/components/editor/theme.d.ts +8 -0
  29. package/dist/components/editor/theme.js +52 -0
  30. package/dist/services/lsp-client.d.ts +3 -0
  31. package/dist/services/lsp-client.js +86 -14
  32. package/dist/styles/theme.css +4 -1
  33. package/package.json +1 -1
@@ -156,6 +156,20 @@
156
156
  {/if}
157
157
  </div>
158
158
 
159
+ <!-- Always-available screen-reader equivalent of the visual, hover-only per-region
160
+ complexity breakdown. The thermal map and the hover tooltip are decorative/sighted,
161
+ so this exposes the same cognitive-load data to assistive technology. -->
162
+ {#if metrics && highComplexityRegions.length > 0}
163
+ <div class="cognitive-meter__sr-only">
164
+ Overall cognitive complexity {score} out of 100, {levelLabel}. {highComplexityRegions.length}
165
+ high-complexity {highComplexityRegions.length === 1 ? 'region' : 'regions'}:
166
+ {#each highComplexityRegions.slice(0, 8) as region (region.startLine)}
167
+ {region.name || `${region.type} at line ${region.startLine + 1}`}, cognitive complexity
168
+ {region.cognitiveComplexity}, score {region.score} out of 100.
169
+ {/each}
170
+ </div>
171
+ {/if}
172
+
159
173
  <style>
160
174
  .cognitive-meter {
161
175
  display: flex;
@@ -323,4 +337,17 @@
323
337
  color: var(--ide-text-muted, #a8c5d9);
324
338
  line-height: 1.4;
325
339
  }
340
+
341
+ /* Visually hidden, but exposed to assistive technology. */
342
+ .cognitive-meter__sr-only {
343
+ position: absolute;
344
+ width: 1px;
345
+ height: 1px;
346
+ padding: 0;
347
+ margin: -1px;
348
+ overflow: hidden;
349
+ clip: rect(0, 0, 0, 0);
350
+ white-space: nowrap;
351
+ border: 0;
352
+ }
326
353
  </style>
@@ -0,0 +1,157 @@
1
+ <script lang="ts">
2
+ import type { ComplexityMetrics, ComplexityRegion } from './core/complexity-analyzer';
3
+
4
+ interface Props {
5
+ /** Complexity metrics for the current document */
6
+ metrics: ComplexityMetrics | null;
7
+ /** Line height in pixels */
8
+ lineHeight: number;
9
+ /** Gutter width in pixels */
10
+ gutterWidth?: number;
11
+ /** Full height of the scrollable content in pixels */
12
+ totalHeight?: number;
13
+ /** Estimated full scrollable content width in pixels */
14
+ contentWidth?: number;
15
+ /** Minimum score to show heat (default: 50) */
16
+ minScore?: number;
17
+ /** Whether heat rendering is enabled */
18
+ enabled?: boolean;
19
+ /** Region key to briefly emphasize after jump-to-hottest */
20
+ flashRegionKey?: string;
21
+ /** Maps a raw document line to its rendered visual row */
22
+ lineToVisualRow?: (line: number) => number;
23
+ }
24
+
25
+ let {
26
+ metrics,
27
+ lineHeight,
28
+ gutterWidth = 50,
29
+ totalHeight = 0,
30
+ contentWidth = 0,
31
+ minScore = 50,
32
+ enabled = true,
33
+ flashRegionKey = '',
34
+ lineToVisualRow = (line: number) => line
35
+ }: Props = $props();
36
+
37
+ let highlightedRegions = $derived(
38
+ enabled && metrics ? metrics.regions.filter((region) => region.score >= minScore) : []
39
+ );
40
+
41
+ function getRegionKey(region: ComplexityRegion): string {
42
+ return `${region.startLine}:${region.endLine}:${region.name ?? region.type}:${region.score}`;
43
+ }
44
+
45
+ function getColor(score: number): string {
46
+ if (score >= 85) return 'var(--ide-error)';
47
+ if (score >= 70) return 'var(--ide-warning)';
48
+ if (score >= 50) return 'var(--ide-info)';
49
+ return 'var(--ide-success)';
50
+ }
51
+
52
+ function getWashOpacity(score: number): number {
53
+ const normalized = Math.min(1, Math.max(0, score / 100));
54
+ return Number((0.14 + normalized * 0.34).toFixed(3));
55
+ }
56
+
57
+ function getRegionTop(region: ComplexityRegion): number {
58
+ return lineToVisualRow(region.startLine) * lineHeight;
59
+ }
60
+
61
+ function getRegionHeight(region: ComplexityRegion): number {
62
+ const startRow = lineToVisualRow(region.startLine);
63
+ const endRow = Math.max(startRow, lineToVisualRow(region.endLine));
64
+ return Math.max(lineHeight, (endRow - startRow + 1) * lineHeight);
65
+ }
66
+ </script>
67
+
68
+ {#if enabled && highlightedRegions.length > 0}
69
+ <div
70
+ class="complexity-heat"
71
+ aria-hidden="true"
72
+ style="
73
+ height: {totalHeight ? `${totalHeight}px` : '100%'};
74
+ width: {contentWidth ? `${contentWidth}px` : '100%'};
75
+ "
76
+ >
77
+ {#each highlightedRegions as region (getRegionKey(region))}
78
+ <div
79
+ class="complexity-heat__region"
80
+ class:complexity-heat__region--critical={region.score >= 85}
81
+ class:complexity-heat__region--flash={flashRegionKey === getRegionKey(region)}
82
+ style="
83
+ top: {getRegionTop(region)}px;
84
+ left: {gutterWidth}px;
85
+ width: {Math.max(0, contentWidth - gutterWidth)}px;
86
+ height: {getRegionHeight(region)}px;
87
+ --heat-color: {getColor(region.score)};
88
+ --heat-opacity: {getWashOpacity(region.score)};
89
+ "
90
+ ></div>
91
+ {/each}
92
+ </div>
93
+ {/if}
94
+
95
+ <style>
96
+ .complexity-heat {
97
+ position: absolute;
98
+ top: 0;
99
+ left: 0;
100
+ min-width: 100%;
101
+ min-height: 100%;
102
+ pointer-events: none;
103
+ z-index: 0;
104
+ overflow: hidden;
105
+ }
106
+
107
+ .complexity-heat__region {
108
+ position: absolute;
109
+ min-width: calc(100% - var(--editor-gutter-width, 50px));
110
+ background: linear-gradient(
111
+ 90deg,
112
+ color-mix(in srgb, var(--heat-color) 90%, transparent) 0%,
113
+ color-mix(in srgb, var(--heat-color) 38%, transparent) 18%,
114
+ color-mix(in srgb, var(--heat-color) 14%, transparent) 60%,
115
+ transparent 100%
116
+ );
117
+ opacity: var(--heat-opacity);
118
+ mix-blend-mode: screen;
119
+ border-left: 1px solid color-mix(in srgb, var(--heat-color) 35%, transparent);
120
+ box-sizing: border-box;
121
+ -webkit-mask-image: linear-gradient(
122
+ to bottom,
123
+ transparent 0,
124
+ #000 8px,
125
+ #000 calc(100% - 8px),
126
+ transparent 100%
127
+ );
128
+ mask-image: linear-gradient(
129
+ to bottom,
130
+ transparent 0,
131
+ #000 8px,
132
+ #000 calc(100% - 8px),
133
+ transparent 100%
134
+ );
135
+ }
136
+
137
+ .complexity-heat__region--flash {
138
+ animation: complexity-heat-flash 0.9s ease-out 1;
139
+ }
140
+
141
+ @keyframes complexity-heat-flash {
142
+ 0% {
143
+ opacity: min(0.58, calc(var(--heat-opacity) + 0.1));
144
+ box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--heat-color) 65%, transparent);
145
+ }
146
+ 100% {
147
+ opacity: var(--heat-opacity);
148
+ box-shadow: none;
149
+ }
150
+ }
151
+
152
+ @media (prefers-reduced-motion: reduce) {
153
+ .complexity-heat__region--flash {
154
+ animation: none;
155
+ }
156
+ }
157
+ </style>
@@ -0,0 +1,24 @@
1
+ import type { ComplexityMetrics } from './core/complexity-analyzer';
2
+ interface Props {
3
+ /** Complexity metrics for the current document */
4
+ metrics: ComplexityMetrics | null;
5
+ /** Line height in pixels */
6
+ lineHeight: number;
7
+ /** Gutter width in pixels */
8
+ gutterWidth?: number;
9
+ /** Full height of the scrollable content in pixels */
10
+ totalHeight?: number;
11
+ /** Estimated full scrollable content width in pixels */
12
+ contentWidth?: number;
13
+ /** Minimum score to show heat (default: 50) */
14
+ minScore?: number;
15
+ /** Whether heat rendering is enabled */
16
+ enabled?: boolean;
17
+ /** Region key to briefly emphasize after jump-to-hottest */
18
+ flashRegionKey?: string;
19
+ /** Maps a raw document line to its rendered visual row */
20
+ lineToVisualRow?: (line: number) => number;
21
+ }
22
+ declare const ComplexityHeatLayer: import("svelte").Component<Props, {}, "">;
23
+ type ComplexityHeatLayer = ReturnType<typeof ComplexityHeatLayer>;
24
+ export default ComplexityHeatLayer;