@nocturnium/svelte-ide 1.0.0 → 1.0.1
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/README.md +43 -47
- package/dist/components/agents/AgentActivityPanel.svelte +3 -1
- package/dist/components/agents/AgentAvatar.svelte +127 -35
- package/dist/components/agents/AgentCursor.svelte +15 -5
- package/dist/components/agents/AgentPresenceBar.svelte +7 -2
- package/dist/components/ai/AIConversationList.svelte +39 -34
- package/dist/components/ai/AIInlineEdit.svelte +1 -3
- package/dist/components/ai/AIMessage.svelte +5 -5
- package/dist/components/ai/AIMessageActions.svelte +18 -3
- package/dist/components/ai/AIMessageContent.svelte +22 -20
- package/dist/components/ai/AIPanel.svelte +17 -9
- package/dist/components/ai/AISuggestionWidget.svelte +1 -3
- package/dist/components/ai/AIToolCallDisplay.svelte +10 -14
- package/dist/components/core/Badge.svelte +9 -1
- package/dist/components/core/ConnectionStatus.svelte +73 -68
- package/dist/components/core/ErrorBoundary.svelte +56 -56
- package/dist/components/core/ErrorBoundary.svelte.d.ts +5 -5
- package/dist/components/core/Icon.svelte +22 -11
- package/dist/components/core/ResizeHandle.svelte +1 -1
- package/dist/components/core/Tooltip.svelte +1 -7
- package/dist/components/editor/AIFocusLayer.svelte +15 -7
- package/dist/components/editor/Breadcrumbs.svelte +18 -6
- package/dist/components/editor/BreakpointLayer.svelte +51 -60
- package/dist/components/editor/CognitiveLoadMeter.svelte +4 -2
- package/dist/components/editor/CollaborativeEditor.svelte +1 -5
- package/dist/components/editor/CommandPalette.svelte +1 -4
- package/dist/components/editor/ComplexityLayer.svelte +8 -6
- package/dist/components/editor/ConflictZoneLayer.svelte +2 -8
- package/dist/components/editor/ContextLens.svelte +1 -4
- package/dist/components/editor/CustomEditor.svelte +85 -41
- package/dist/components/editor/DebugConsole.svelte +8 -17
- package/dist/components/editor/EchoCursorLayer.svelte +3 -1
- package/dist/components/editor/EditorGutter.svelte +8 -2
- package/dist/components/editor/EditorLines.svelte +6 -3
- package/dist/components/editor/EditorPane.svelte +1 -6
- package/dist/components/editor/EditorSelections.svelte +29 -11
- package/dist/components/editor/FileExplorer.svelte +26 -4
- package/dist/components/editor/FileIcon.svelte +3 -1
- package/dist/components/editor/FindReplace.svelte +16 -4
- package/dist/components/editor/GhostBracketLayer.svelte +2 -2
- package/dist/components/editor/GitBlameLayer.svelte +2 -1
- package/dist/components/editor/InlineDiagnosticsLayer.svelte +4 -13
- package/dist/components/editor/InlineDiffLayer.svelte +18 -9
- package/dist/components/editor/Minimap.svelte +16 -9
- package/dist/components/editor/PluginPreviewSandbox.svelte +3 -2
- package/dist/components/editor/ProblemsPanel.svelte +11 -35
- package/dist/components/editor/QuickActionsMenu.svelte +5 -14
- package/dist/components/editor/SnippetPalette.svelte +11 -12
- package/dist/components/editor/StructureMap.svelte +2 -1
- package/dist/components/editor/SymbolOutline.svelte +14 -19
- package/dist/components/editor/TimelineScrubber.svelte +7 -6
- package/dist/components/editor/core/complexity-analyzer.js +42 -12
- package/dist/components/editor/core/conflict-predictor.js +2 -4
- package/dist/components/editor/core/folding.d.ts +9 -0
- package/dist/components/editor/core/folding.js +40 -5
- package/dist/components/editor/core/multi-cursor.js +4 -8
- package/dist/components/editor/core/navigation.js +2 -6
- package/dist/components/editor/core/quick-actions.js +22 -17
- package/dist/components/editor/core/search.js +2 -6
- package/dist/components/editor/core/semantic-analyzer.js +1 -3
- package/dist/components/editor/core/snippet-manager.js +4 -3
- package/dist/components/editor/core/state.js +2 -2
- package/dist/components/editor/core/timeline.js +1 -3
- package/dist/components/editor/editor-input.js +9 -6
- package/dist/components/editor/editor-multicursor.js +2 -2
- package/dist/components/editor/tokenizer/languages/css.js +146 -24
- package/dist/components/editor/tokenizer/languages/go.js +76 -13
- package/dist/components/editor/tokenizer/languages/javascript.js +210 -29
- package/dist/components/editor/tokenizer/languages/python.js +116 -19
- package/dist/components/editor/tokenizer/languages/svelte.js +20 -7
- package/dist/components/layout/IDELayout.svelte +6 -2
- package/dist/components/layout/StatusBar.svelte +32 -20
- package/dist/components/lsp/AutocompleteWidget.svelte +19 -19
- package/dist/components/lsp/DiagnosticMarker.svelte +61 -52
- package/dist/components/lsp/DiagnosticsPanel.svelte +45 -27
- package/dist/components/lsp/HoverTooltip.svelte +56 -61
- package/dist/components/lsp/LSPEditor.svelte +7 -18
- package/dist/components/lsp/SignatureHelpWidget.svelte +12 -9
- package/dist/components/plugins/PluginCard.svelte +3 -13
- package/dist/components/plugins/PluginProposalForm.svelte +19 -31
- package/dist/components/vfs/LockConflictDialog.svelte +112 -45
- package/dist/components/vfs/LockIndicator.svelte +0 -1
- package/dist/components/vfs/LockOverlay.svelte +53 -53
- package/dist/components/vfs/LockOverlay.svelte.d.ts +5 -5
- package/dist/components/vfs/VersionConflictDialog.svelte +107 -77
- package/dist/services/error-handling.js +1 -7
- package/dist/services/mock-ai.js +9 -7
- package/dist/stores/agents.svelte.js +50 -10
- package/dist/stores/ai.svelte.js +66 -18
- package/dist/stores/collaboration.svelte.js +70 -14
- package/dist/stores/editor.svelte.js +50 -10
- package/dist/stores/plugin.svelte.js +60 -12
- package/dist/stores/vfs.svelte.js +77 -19
- package/dist/styles/theme.css +16 -7
- package/package.json +186 -1
|
@@ -1,3 +1,58 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
// Simple markdown renderer for hover content
|
|
3
|
+
// Handles code blocks, inline code, bold, italic, and links
|
|
4
|
+
function renderMarkdown(text: string): string {
|
|
5
|
+
let html = escapeHtml(text);
|
|
6
|
+
|
|
7
|
+
// Code blocks with language
|
|
8
|
+
html = html.replace(
|
|
9
|
+
/```(\w+)?\n([\s\S]*?)```/g,
|
|
10
|
+
(_, lang, code) =>
|
|
11
|
+
`<pre class="hover-tooltip__code-block" data-lang="${lang || ''}">${code.trim()}</pre>`
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
// Inline code
|
|
15
|
+
html = html.replace(/`([^`]+)`/g, '<code class="hover-tooltip__inline-code">$1</code>');
|
|
16
|
+
|
|
17
|
+
// Bold
|
|
18
|
+
html = html.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
|
|
19
|
+
|
|
20
|
+
// Italic
|
|
21
|
+
html = html.replace(/\*([^*]+)\*/g, '<em>$1</em>');
|
|
22
|
+
|
|
23
|
+
// Links (href is validated; unsafe schemes degrade to plain text)
|
|
24
|
+
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_match, label: string, href: string) => {
|
|
25
|
+
const url = safeUrl(href);
|
|
26
|
+
return url ? `<a href="${url}" target="_blank" rel="noopener">${label}</a>` : label;
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Line breaks
|
|
30
|
+
html = html.replace(/\n/g, '<br>');
|
|
31
|
+
|
|
32
|
+
return html;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function escapeHtml(text: string): string {
|
|
36
|
+
const map: Record<string, string> = {
|
|
37
|
+
'&': '&',
|
|
38
|
+
'<': '<',
|
|
39
|
+
'>': '>',
|
|
40
|
+
'"': '"',
|
|
41
|
+
"'": '''
|
|
42
|
+
};
|
|
43
|
+
return text.replace(/[&<>"']/g, (char) => map[char]);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Whitelist link schemes. Relative/anchor URLs and http(s)/mailto are allowed;
|
|
47
|
+
// anything else (e.g. javascript:, data:, vbscript:) is rejected.
|
|
48
|
+
function safeUrl(url: string): string | null {
|
|
49
|
+
const trimmed = url.trim();
|
|
50
|
+
if (/^(\/|#|\.\/|\.\.\/)/.test(trimmed)) return trimmed;
|
|
51
|
+
if (/^(https?:|mailto:)/i.test(trimmed)) return trimmed;
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
</script>
|
|
55
|
+
|
|
1
56
|
<script lang="ts">
|
|
2
57
|
/**
|
|
3
58
|
* HoverTooltip - LSP hover information display
|
|
@@ -20,13 +75,7 @@
|
|
|
20
75
|
class?: string;
|
|
21
76
|
}
|
|
22
77
|
|
|
23
|
-
let {
|
|
24
|
-
hover,
|
|
25
|
-
position,
|
|
26
|
-
maxWidth = 500,
|
|
27
|
-
onDismiss,
|
|
28
|
-
class: className = ''
|
|
29
|
-
}: Props = $props();
|
|
78
|
+
let { hover, position, maxWidth = 500, onDismiss, class: className = '' }: Props = $props();
|
|
30
79
|
|
|
31
80
|
let tooltipRef: HTMLElement;
|
|
32
81
|
|
|
@@ -124,60 +173,6 @@
|
|
|
124
173
|
</div>
|
|
125
174
|
</div>
|
|
126
175
|
|
|
127
|
-
<script module lang="ts">
|
|
128
|
-
// Simple markdown renderer for hover content
|
|
129
|
-
// Handles code blocks, inline code, bold, italic, and links
|
|
130
|
-
function renderMarkdown(text: string): string {
|
|
131
|
-
let html = escapeHtml(text);
|
|
132
|
-
|
|
133
|
-
// Code blocks with language
|
|
134
|
-
html = html.replace(
|
|
135
|
-
/```(\w+)?\n([\s\S]*?)```/g,
|
|
136
|
-
(_, lang, code) => `<pre class="hover-tooltip__code-block" data-lang="${lang || ''}">${code.trim()}</pre>`
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
// Inline code
|
|
140
|
-
html = html.replace(/`([^`]+)`/g, '<code class="hover-tooltip__inline-code">$1</code>');
|
|
141
|
-
|
|
142
|
-
// Bold
|
|
143
|
-
html = html.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
|
|
144
|
-
|
|
145
|
-
// Italic
|
|
146
|
-
html = html.replace(/\*([^*]+)\*/g, '<em>$1</em>');
|
|
147
|
-
|
|
148
|
-
// Links (href is validated; unsafe schemes degrade to plain text)
|
|
149
|
-
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_match, label: string, href: string) => {
|
|
150
|
-
const url = safeUrl(href);
|
|
151
|
-
return url ? `<a href="${url}" target="_blank" rel="noopener">${label}</a>` : label;
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
// Line breaks
|
|
155
|
-
html = html.replace(/\n/g, '<br>');
|
|
156
|
-
|
|
157
|
-
return html;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function escapeHtml(text: string): string {
|
|
161
|
-
const map: Record<string, string> = {
|
|
162
|
-
'&': '&',
|
|
163
|
-
'<': '<',
|
|
164
|
-
'>': '>',
|
|
165
|
-
'"': '"',
|
|
166
|
-
"'": '''
|
|
167
|
-
};
|
|
168
|
-
return text.replace(/[&<>"']/g, (char) => map[char]);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Whitelist link schemes. Relative/anchor URLs and http(s)/mailto are allowed;
|
|
172
|
-
// anything else (e.g. javascript:, data:, vbscript:) is rejected.
|
|
173
|
-
function safeUrl(url: string): string | null {
|
|
174
|
-
const trimmed = url.trim();
|
|
175
|
-
if (/^(\/|#|\.\/|\.\.\/)/.test(trimmed)) return trimmed;
|
|
176
|
-
if (/^(https?:|mailto:)/i.test(trimmed)) return trimmed;
|
|
177
|
-
return null;
|
|
178
|
-
}
|
|
179
|
-
</script>
|
|
180
|
-
|
|
181
176
|
<style>
|
|
182
177
|
.hover-tooltip {
|
|
183
178
|
position: fixed;
|
|
@@ -12,12 +12,7 @@
|
|
|
12
12
|
import { onMount } from 'svelte';
|
|
13
13
|
import type { EditorPreferences } from '../../types';
|
|
14
14
|
import type { LSPClient } from '../../services/lsp-client';
|
|
15
|
-
import type {
|
|
16
|
-
CompletionItem,
|
|
17
|
-
Hover,
|
|
18
|
-
SignatureHelp,
|
|
19
|
-
Diagnostic
|
|
20
|
-
} from '../../types/lsp';
|
|
15
|
+
import type { CompletionItem, Hover, SignatureHelp, Diagnostic } from '../../types/lsp';
|
|
21
16
|
import type { Cursor } from '../editor/core/multi-cursor';
|
|
22
17
|
import CustomEditor from '../editor/CustomEditor.svelte';
|
|
23
18
|
import AutocompleteWidget from './AutocompleteWidget.svelte';
|
|
@@ -262,15 +257,13 @@
|
|
|
262
257
|
switch (e.key) {
|
|
263
258
|
case 'ArrowUp':
|
|
264
259
|
e.preventDefault();
|
|
265
|
-
completionSelectedIndex =
|
|
266
|
-
? completionSelectedIndex - 1
|
|
267
|
-
: completionItems.length - 1;
|
|
260
|
+
completionSelectedIndex =
|
|
261
|
+
completionSelectedIndex > 0 ? completionSelectedIndex - 1 : completionItems.length - 1;
|
|
268
262
|
return;
|
|
269
263
|
case 'ArrowDown':
|
|
270
264
|
e.preventDefault();
|
|
271
|
-
completionSelectedIndex =
|
|
272
|
-
? completionSelectedIndex + 1
|
|
273
|
-
: 0;
|
|
265
|
+
completionSelectedIndex =
|
|
266
|
+
completionSelectedIndex < completionItems.length - 1 ? completionSelectedIndex + 1 : 0;
|
|
274
267
|
return;
|
|
275
268
|
case 'Enter':
|
|
276
269
|
case 'Tab':
|
|
@@ -369,7 +362,7 @@
|
|
|
369
362
|
const gutterWidth = 50; // Approximate
|
|
370
363
|
|
|
371
364
|
const x = rect.left + gutterWidth + (cursorColumn - 1) * charWidth;
|
|
372
|
-
const y = rect.top +
|
|
365
|
+
const y = rect.top + cursorLine * lineHeight;
|
|
373
366
|
|
|
374
367
|
return { x, y };
|
|
375
368
|
}
|
|
@@ -459,11 +452,7 @@
|
|
|
459
452
|
|
|
460
453
|
<!-- Hover Tooltip -->
|
|
461
454
|
{#if showHover && hoverData}
|
|
462
|
-
<HoverTooltip
|
|
463
|
-
hover={hoverData}
|
|
464
|
-
position={hoverPosition}
|
|
465
|
-
onDismiss={hideHover}
|
|
466
|
-
/>
|
|
455
|
+
<HoverTooltip hover={hoverData} position={hoverPosition} onDismiss={hideHover} />
|
|
467
456
|
{/if}
|
|
468
457
|
|
|
469
458
|
<!-- Signature Help -->
|
|
@@ -18,12 +18,7 @@
|
|
|
18
18
|
class?: string;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
let {
|
|
22
|
-
signatureHelp,
|
|
23
|
-
position,
|
|
24
|
-
onDismiss,
|
|
25
|
-
class: className = ''
|
|
26
|
-
}: Props = $props();
|
|
21
|
+
let { signatureHelp, position, onDismiss, class: className = '' }: Props = $props();
|
|
27
22
|
|
|
28
23
|
let activeSignature = $derived(
|
|
29
24
|
signatureHelp.signatures[signatureHelp.activeSignature ?? 0] as SignatureInformation | undefined
|
|
@@ -52,7 +47,11 @@
|
|
|
52
47
|
return '';
|
|
53
48
|
}
|
|
54
49
|
|
|
55
|
-
function parseSignatureLabel(sig: SignatureInformation): {
|
|
50
|
+
function parseSignatureLabel(sig: SignatureInformation): {
|
|
51
|
+
before: string;
|
|
52
|
+
param: string;
|
|
53
|
+
after: string;
|
|
54
|
+
} {
|
|
56
55
|
const params = sig.parameters;
|
|
57
56
|
if (!params || params.length === 0 || activeParameterIndex >= params.length) {
|
|
58
57
|
return { before: sig.label, param: '', after: '' };
|
|
@@ -116,12 +115,16 @@
|
|
|
116
115
|
{@const parsed = parseSignatureLabel(activeSignature)}
|
|
117
116
|
<div class="signature-help__signature">
|
|
118
117
|
<code class="signature-help__label">
|
|
119
|
-
<span class="signature-help__label-before">{parsed.before}</span><span
|
|
118
|
+
<span class="signature-help__label-before">{parsed.before}</span><span
|
|
119
|
+
class="signature-help__label-param">{parsed.param}</span
|
|
120
|
+
><span class="signature-help__label-after">{parsed.after}</span>
|
|
120
121
|
</code>
|
|
121
122
|
</div>
|
|
122
123
|
|
|
123
124
|
{#if activeSignature.parameters && activeSignature.parameters[activeParameterIndex]}
|
|
124
|
-
{@const paramDoc = getParameterDocumentation(
|
|
125
|
+
{@const paramDoc = getParameterDocumentation(
|
|
126
|
+
activeSignature.parameters[activeParameterIndex]
|
|
127
|
+
)}
|
|
125
128
|
{#if paramDoc}
|
|
126
129
|
<div class="signature-help__param-doc">
|
|
127
130
|
<span class="signature-help__param-name">
|
|
@@ -19,13 +19,7 @@
|
|
|
19
19
|
onUninstall?: () => void;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
let {
|
|
23
|
-
plugin,
|
|
24
|
-
installed = false,
|
|
25
|
-
showStatus = false,
|
|
26
|
-
onInstall,
|
|
27
|
-
onUninstall
|
|
28
|
-
}: Props = $props();
|
|
22
|
+
let { plugin, installed = false, showStatus = false, onInstall, onUninstall }: Props = $props();
|
|
29
23
|
|
|
30
24
|
function getStatusVariant(
|
|
31
25
|
status: PluginStatus
|
|
@@ -72,13 +66,9 @@
|
|
|
72
66
|
</div>
|
|
73
67
|
<div class="plugin-card__actions">
|
|
74
68
|
{#if installed}
|
|
75
|
-
<Button variant="danger" size="xs" onclick={onUninstall}>
|
|
76
|
-
Uninstall
|
|
77
|
-
</Button>
|
|
69
|
+
<Button variant="danger" size="xs" onclick={onUninstall}>Uninstall</Button>
|
|
78
70
|
{:else if plugin.status === 'deployed'}
|
|
79
|
-
<Button variant="primary" size="xs" onclick={onInstall}>
|
|
80
|
-
Install
|
|
81
|
-
</Button>
|
|
71
|
+
<Button variant="primary" size="xs" onclick={onInstall}>Install</Button>
|
|
82
72
|
{/if}
|
|
83
73
|
</div>
|
|
84
74
|
</div>
|
|
@@ -69,7 +69,12 @@
|
|
|
69
69
|
}
|
|
70
70
|
</script>
|
|
71
71
|
|
|
72
|
-
<div
|
|
72
|
+
<div
|
|
73
|
+
class="plugin-form-overlay"
|
|
74
|
+
onclick={onClose}
|
|
75
|
+
onkeydown={(e) => e.key === 'Escape' && onClose()}
|
|
76
|
+
role="presentation"
|
|
77
|
+
>
|
|
73
78
|
<div
|
|
74
79
|
class="plugin-form"
|
|
75
80
|
onclick={(e) => e.stopPropagation()}
|
|
@@ -85,7 +90,13 @@
|
|
|
85
90
|
</Button>
|
|
86
91
|
</div>
|
|
87
92
|
|
|
88
|
-
<form
|
|
93
|
+
<form
|
|
94
|
+
class="plugin-form__content"
|
|
95
|
+
onsubmit={(e) => {
|
|
96
|
+
e.preventDefault();
|
|
97
|
+
handleSubmit();
|
|
98
|
+
}}
|
|
99
|
+
>
|
|
89
100
|
{#if error}
|
|
90
101
|
<div class="plugin-form__error">
|
|
91
102
|
<Icon name="error" size={14} />
|
|
@@ -95,12 +106,7 @@
|
|
|
95
106
|
|
|
96
107
|
<div class="plugin-form__field">
|
|
97
108
|
<label for="name">Name *</label>
|
|
98
|
-
<Input
|
|
99
|
-
id="name"
|
|
100
|
-
bind:value={name}
|
|
101
|
-
placeholder="my-awesome-plugin"
|
|
102
|
-
fullWidth
|
|
103
|
-
/>
|
|
109
|
+
<Input id="name" bind:value={name} placeholder="my-awesome-plugin" fullWidth />
|
|
104
110
|
</div>
|
|
105
111
|
|
|
106
112
|
<div class="plugin-form__field">
|
|
@@ -116,11 +122,7 @@
|
|
|
116
122
|
|
|
117
123
|
<div class="plugin-form__field">
|
|
118
124
|
<label for="category">Category</label>
|
|
119
|
-
<select
|
|
120
|
-
id="category"
|
|
121
|
-
class="plugin-form__select"
|
|
122
|
-
bind:value={category}
|
|
123
|
-
>
|
|
125
|
+
<select id="category" class="plugin-form__select" bind:value={category}>
|
|
124
126
|
{#each categories as cat (cat.value)}
|
|
125
127
|
<option value={cat.value}>{cat.label}</option>
|
|
126
128
|
{/each}
|
|
@@ -129,31 +131,17 @@
|
|
|
129
131
|
|
|
130
132
|
<div class="plugin-form__field">
|
|
131
133
|
<label for="tags">Tags</label>
|
|
132
|
-
<Input
|
|
133
|
-
id="tags"
|
|
134
|
-
bind:value={tags}
|
|
135
|
-
placeholder="comma, separated, tags"
|
|
136
|
-
fullWidth
|
|
137
|
-
/>
|
|
134
|
+
<Input id="tags" bind:value={tags} placeholder="comma, separated, tags" fullWidth />
|
|
138
135
|
</div>
|
|
139
136
|
|
|
140
137
|
<div class="plugin-form__field">
|
|
141
138
|
<label for="author">Author *</label>
|
|
142
|
-
<Input
|
|
143
|
-
id="author"
|
|
144
|
-
bind:value={author}
|
|
145
|
-
placeholder="your@email.com"
|
|
146
|
-
fullWidth
|
|
147
|
-
/>
|
|
139
|
+
<Input id="author" bind:value={author} placeholder="your@email.com" fullWidth />
|
|
148
140
|
</div>
|
|
149
141
|
|
|
150
142
|
<div class="plugin-form__actions">
|
|
151
|
-
<Button variant="ghost" onclick={onClose} disabled={isSubmitting}>
|
|
152
|
-
|
|
153
|
-
</Button>
|
|
154
|
-
<Button variant="primary" type="submit" loading={isSubmitting}>
|
|
155
|
-
Create Proposal
|
|
156
|
-
</Button>
|
|
143
|
+
<Button variant="ghost" onclick={onClose} disabled={isSubmitting}>Cancel</Button>
|
|
144
|
+
<Button variant="primary" type="submit" loading={isSubmitting}>Create Proposal</Button>
|
|
157
145
|
</div>
|
|
158
146
|
</form>
|
|
159
147
|
</div>
|
|
@@ -111,7 +111,14 @@
|
|
|
111
111
|
<!-- Header -->
|
|
112
112
|
<header class="lock-dialog__header">
|
|
113
113
|
<div class="lock-dialog__icon">
|
|
114
|
-
<svg
|
|
114
|
+
<svg
|
|
115
|
+
viewBox="0 0 24 24"
|
|
116
|
+
fill="none"
|
|
117
|
+
stroke="currentColor"
|
|
118
|
+
stroke-width="2"
|
|
119
|
+
stroke-linecap="round"
|
|
120
|
+
stroke-linejoin="round"
|
|
121
|
+
>
|
|
115
122
|
<rect x="3" y="11" width="18" height="11" rx="2" ry="2" />
|
|
116
123
|
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
|
|
117
124
|
</svg>
|
|
@@ -120,11 +127,7 @@
|
|
|
120
127
|
<h2 id="lock-dialog-title">File is Locked</h2>
|
|
121
128
|
<p class="lock-dialog__filename">{fileName}</p>
|
|
122
129
|
</div>
|
|
123
|
-
<button
|
|
124
|
-
class="lock-dialog__close"
|
|
125
|
-
onclick={onClose}
|
|
126
|
-
aria-label="Close dialog"
|
|
127
|
-
>
|
|
130
|
+
<button class="lock-dialog__close" onclick={onClose} aria-label="Close dialog">
|
|
128
131
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
129
132
|
<path d="M18 6 6 18M6 6l12 12" />
|
|
130
133
|
</svg>
|
|
@@ -158,7 +161,14 @@
|
|
|
158
161
|
{/if}
|
|
159
162
|
</div>
|
|
160
163
|
<div class="lock-holder__timer">
|
|
161
|
-
<svg
|
|
164
|
+
<svg
|
|
165
|
+
viewBox="0 0 24 24"
|
|
166
|
+
fill="none"
|
|
167
|
+
stroke="currentColor"
|
|
168
|
+
stroke-width="2"
|
|
169
|
+
width="14"
|
|
170
|
+
height="14"
|
|
171
|
+
>
|
|
162
172
|
<circle cx="12" cy="12" r="10" />
|
|
163
173
|
<polyline points="12 6 12 12 16 14" />
|
|
164
174
|
</svg>
|
|
@@ -170,7 +180,14 @@
|
|
|
170
180
|
<!-- Error message -->
|
|
171
181
|
{#if errorMessage}
|
|
172
182
|
<div class="lock-dialog__error" role="alert">
|
|
173
|
-
<svg
|
|
183
|
+
<svg
|
|
184
|
+
viewBox="0 0 24 24"
|
|
185
|
+
fill="none"
|
|
186
|
+
stroke="currentColor"
|
|
187
|
+
stroke-width="2"
|
|
188
|
+
width="16"
|
|
189
|
+
height="16"
|
|
190
|
+
>
|
|
174
191
|
<circle cx="12" cy="12" r="10" />
|
|
175
192
|
<line x1="12" y1="8" x2="12" y2="12" />
|
|
176
193
|
<line x1="12" y1="16" x2="12.01" y2="16" />
|
|
@@ -183,7 +200,14 @@
|
|
|
183
200
|
<div class="lock-dialog__reassurance">
|
|
184
201
|
{#if pendingChanges > 0}
|
|
185
202
|
<div class="reassurance-item reassurance-item--saved">
|
|
186
|
-
<svg
|
|
203
|
+
<svg
|
|
204
|
+
viewBox="0 0 24 24"
|
|
205
|
+
fill="none"
|
|
206
|
+
stroke="currentColor"
|
|
207
|
+
stroke-width="2"
|
|
208
|
+
width="14"
|
|
209
|
+
height="14"
|
|
210
|
+
>
|
|
187
211
|
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" />
|
|
188
212
|
<polyline points="22 4 12 14.01 9 11.01" />
|
|
189
213
|
</svg>
|
|
@@ -192,7 +216,14 @@
|
|
|
192
216
|
{/if}
|
|
193
217
|
{#if lastSyncDisplay}
|
|
194
218
|
<div class="reassurance-item">
|
|
195
|
-
<svg
|
|
219
|
+
<svg
|
|
220
|
+
viewBox="0 0 24 24"
|
|
221
|
+
fill="none"
|
|
222
|
+
stroke="currentColor"
|
|
223
|
+
stroke-width="2"
|
|
224
|
+
width="14"
|
|
225
|
+
height="14"
|
|
226
|
+
>
|
|
196
227
|
<polyline points="23 4 23 10 17 10" />
|
|
197
228
|
<path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10" />
|
|
198
229
|
</svg>
|
|
@@ -207,11 +238,15 @@
|
|
|
207
238
|
<!-- Safe options row -->
|
|
208
239
|
<div class="action-row action-row--safe">
|
|
209
240
|
{#if onOpenReadOnly}
|
|
210
|
-
<button
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
241
|
+
<button class="action-btn action-btn--safe" onclick={onOpenReadOnly}>
|
|
242
|
+
<svg
|
|
243
|
+
viewBox="0 0 24 24"
|
|
244
|
+
fill="none"
|
|
245
|
+
stroke="currentColor"
|
|
246
|
+
stroke-width="2"
|
|
247
|
+
width="18"
|
|
248
|
+
height="18"
|
|
249
|
+
>
|
|
215
250
|
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" />
|
|
216
251
|
<circle cx="12" cy="12" r="3" />
|
|
217
252
|
</svg>
|
|
@@ -219,11 +254,15 @@
|
|
|
219
254
|
</button>
|
|
220
255
|
{/if}
|
|
221
256
|
{#if onWait}
|
|
222
|
-
<button
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
257
|
+
<button class="action-btn action-btn--safe" onclick={onWait}>
|
|
258
|
+
<svg
|
|
259
|
+
viewBox="0 0 24 24"
|
|
260
|
+
fill="none"
|
|
261
|
+
stroke="currentColor"
|
|
262
|
+
stroke-width="2"
|
|
263
|
+
width="18"
|
|
264
|
+
height="18"
|
|
265
|
+
>
|
|
227
266
|
<circle cx="12" cy="12" r="10" />
|
|
228
267
|
<polyline points="12 6 12 12 16 14" />
|
|
229
268
|
</svg>
|
|
@@ -234,11 +273,15 @@
|
|
|
234
273
|
|
|
235
274
|
<!-- Primary action -->
|
|
236
275
|
{#if onRequestAccess}
|
|
237
|
-
<button
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
276
|
+
<button class="action-btn action-btn--primary" onclick={onRequestAccess}>
|
|
277
|
+
<svg
|
|
278
|
+
viewBox="0 0 24 24"
|
|
279
|
+
fill="none"
|
|
280
|
+
stroke="currentColor"
|
|
281
|
+
stroke-width="2"
|
|
282
|
+
width="18"
|
|
283
|
+
height="18"
|
|
284
|
+
>
|
|
242
285
|
<line x1="22" y1="2" x2="11" y2="13" />
|
|
243
286
|
<polygon points="22 2 15 22 11 13 2 9 22 2" />
|
|
244
287
|
</svg>
|
|
@@ -250,27 +293,30 @@
|
|
|
250
293
|
<!-- Dangerous action (gated) -->
|
|
251
294
|
{#if canForceUnlock && onForceUnlock}
|
|
252
295
|
{#if !showForceSection}
|
|
253
|
-
<button
|
|
254
|
-
class="action-toggle"
|
|
255
|
-
onclick={() => showForceSection = true}
|
|
256
|
-
>
|
|
296
|
+
<button class="action-toggle" onclick={() => (showForceSection = true)}>
|
|
257
297
|
More options...
|
|
258
298
|
</button>
|
|
259
299
|
{:else}
|
|
260
300
|
<div class="force-section">
|
|
261
301
|
<div class="force-warning">
|
|
262
|
-
<svg
|
|
263
|
-
|
|
302
|
+
<svg
|
|
303
|
+
viewBox="0 0 24 24"
|
|
304
|
+
fill="none"
|
|
305
|
+
stroke="currentColor"
|
|
306
|
+
stroke-width="2"
|
|
307
|
+
width="16"
|
|
308
|
+
height="16"
|
|
309
|
+
>
|
|
310
|
+
<path
|
|
311
|
+
d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"
|
|
312
|
+
/>
|
|
264
313
|
<line x1="12" y1="9" x2="12" y2="13" />
|
|
265
314
|
<line x1="12" y1="17" x2="12.01" y2="17" />
|
|
266
315
|
</svg>
|
|
267
316
|
<span>Force unlock may cause data loss for the current editor</span>
|
|
268
317
|
</div>
|
|
269
318
|
<label class="force-confirm">
|
|
270
|
-
<input
|
|
271
|
-
type="checkbox"
|
|
272
|
-
bind:checked={forceUnlockConfirmed}
|
|
273
|
-
/>
|
|
319
|
+
<input type="checkbox" bind:checked={forceUnlockConfirmed} />
|
|
274
320
|
<span>I understand the risks</span>
|
|
275
321
|
</label>
|
|
276
322
|
<button
|
|
@@ -278,7 +324,14 @@
|
|
|
278
324
|
onclick={handleForceUnlock}
|
|
279
325
|
disabled={!forceUnlockConfirmed}
|
|
280
326
|
>
|
|
281
|
-
<svg
|
|
327
|
+
<svg
|
|
328
|
+
viewBox="0 0 24 24"
|
|
329
|
+
fill="none"
|
|
330
|
+
stroke="currentColor"
|
|
331
|
+
stroke-width="2"
|
|
332
|
+
width="18"
|
|
333
|
+
height="18"
|
|
334
|
+
>
|
|
282
335
|
<rect x="3" y="11" width="18" height="11" rx="2" ry="2" />
|
|
283
336
|
<path d="M7 11V7a5 5 0 0 1 9.9-1" />
|
|
284
337
|
</svg>
|
|
@@ -291,9 +344,7 @@
|
|
|
291
344
|
|
|
292
345
|
<!-- Footer -->
|
|
293
346
|
<footer class="lock-dialog__footer">
|
|
294
|
-
<button class="cancel-btn" onclick={onClose}>
|
|
295
|
-
Cancel
|
|
296
|
-
</button>
|
|
347
|
+
<button class="cancel-btn" onclick={onClose}> Cancel </button>
|
|
297
348
|
</footer>
|
|
298
349
|
</div>
|
|
299
350
|
</div>
|
|
@@ -314,8 +365,12 @@
|
|
|
314
365
|
}
|
|
315
366
|
|
|
316
367
|
@keyframes fade-in {
|
|
317
|
-
from {
|
|
318
|
-
|
|
368
|
+
from {
|
|
369
|
+
opacity: 0;
|
|
370
|
+
}
|
|
371
|
+
to {
|
|
372
|
+
opacity: 1;
|
|
373
|
+
}
|
|
319
374
|
}
|
|
320
375
|
|
|
321
376
|
.lock-dialog {
|
|
@@ -324,14 +379,22 @@
|
|
|
324
379
|
background: var(--ide-bg-secondary);
|
|
325
380
|
border: 1px solid var(--ide-border);
|
|
326
381
|
border-radius: var(--ide-radius-xl);
|
|
327
|
-
box-shadow:
|
|
382
|
+
box-shadow:
|
|
383
|
+
var(--ide-shadow-xl),
|
|
384
|
+
0 0 60px rgba(0, 0, 0, 0.3);
|
|
328
385
|
animation: slide-up 0.2s ease-out;
|
|
329
386
|
overflow: hidden;
|
|
330
387
|
}
|
|
331
388
|
|
|
332
389
|
@keyframes slide-up {
|
|
333
|
-
from {
|
|
334
|
-
|
|
390
|
+
from {
|
|
391
|
+
opacity: 0;
|
|
392
|
+
transform: translateY(20px) scale(0.98);
|
|
393
|
+
}
|
|
394
|
+
to {
|
|
395
|
+
opacity: 1;
|
|
396
|
+
transform: translateY(0) scale(1);
|
|
397
|
+
}
|
|
335
398
|
}
|
|
336
399
|
|
|
337
400
|
/* Header */
|
|
@@ -558,7 +621,11 @@
|
|
|
558
621
|
.action-btn--primary {
|
|
559
622
|
flex-direction: column;
|
|
560
623
|
gap: 4px;
|
|
561
|
-
background: linear-gradient(
|
|
624
|
+
background: linear-gradient(
|
|
625
|
+
135deg,
|
|
626
|
+
var(--ide-interactive) 0%,
|
|
627
|
+
var(--ide-interactive-active) 100%
|
|
628
|
+
);
|
|
562
629
|
color: white;
|
|
563
630
|
padding: 14px 16px;
|
|
564
631
|
}
|