@lapismd/design-core 0.1.0 → 0.1.2
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/CHANGELOG.md +22 -0
- package/README.md +1 -1
- package/package.json +12 -8
- package/spec/src/styling-and-themes.md +9 -9
- package/src/shared/ai/chat.css +2 -1
- package/src/shared/ai/composer-input/ComposerInput.svelte +3 -2
- package/src/shared/ai/experimental/reaction-bar/ReactionBar.svelte +1 -1
- package/src/shared/ai/tool-calls/ToolCalls.svelte +1 -1
- package/src/shared/ai/trigger-menu.ts +2 -3
- package/src/shared/diff/file-diff/FileDiff.svelte +5 -8
- package/src/shared/diff/file-listing/FileListingViewModeToggle.css +42 -5
- package/src/shared/diff/merge-editor/MergeEditor.svelte +2 -7
- package/src/shared/filter/filter-query/filters.ts +2 -2
- package/src/shared/filter/filter-query/parser.ts +9 -8
- package/src/shared/filter/power-search/PowerSearch.svelte +1 -1
- package/src/shared/filter/search-filter-bar/SearchFilterBar.svelte +2 -2
- package/src/shared/filter/search-filter-bar/SearchFilterInput.svelte +1 -1
- package/src/shared/filter/search-filter-bar/SearchFilterPredicateEditor.svelte +1 -1
- package/src/shared/filter/search-filter-bar/search-filter-syntax.ts +1 -1
- package/src/shared/forms/autocomplete-input/AutocompleteInput.svelte +19 -7
- package/src/shared/shadcn/command/command-dialog.svelte +1 -1
- package/src/shared/shadcn/command/command-group.svelte +3 -1
- package/src/shared/shadcn/command-view/command-view.svelte +1 -6
- package/src/shared/shadcn/dropdown-menu/dropdown-menu-checkbox-item.svelte +0 -691
- package/src/shared/shadcn/dropdown-menu/dropdown-menu-content.svelte +691 -0
- package/src/shared/shadcn/dropdown-menu/dropdown-menu-radio-group.svelte +1 -1
- package/src/shared/shadcn/scroll-area/scroll-area.svelte +2 -0
- package/src/shared/shadcn/spinner/spinner.svelte +3 -3
- package/src/shared/shell/app-shell/AppShell.demo.css +37 -0
- package/src/shared/shell/app-shell/AppShellBodyContent.svelte +5 -1
- package/src/shared/shell/app-shell/AppShellBodySidebar.svelte +5 -1
- package/src/shared/shell/app-shell/AppShellMobilePanelSelector.svelte +1 -1
- package/src/shared/shell/app-shell/app-shell-controller.svelte.ts +23 -9
- package/src/shared/shell/app-shell/examples/AppShellBodyDemo.svelte +4 -0
- package/src/shared/shell/app-shell/examples/AppShellCompleteDemo.svelte +1 -0
- package/src/shared/shell/app-shell/examples/AppShellConversationDemo.svelte +1 -0
- package/src/shared/shell/app-shell/examples/AppShellExamples.css +521 -0
- package/src/shared/shell/app-shell/examples/AppShellFilesSidebarDemo.svelte +1 -0
- package/src/shared/shell/app-shell/examples/AppShellMarkdownDocumentDemo.svelte +6 -1
- package/src/shared/shell/app-shell/examples/AppShellMarkdownFilesDemo.svelte +1 -0
- package/src/shared/shell/app-shell/examples/AppShellModeSwitchDemo.svelte +1 -0
- package/src/shared/shell/app-shell/examples/AppShellProjectSidebarDemo.svelte +1 -0
- package/src/shared/shell/app-shell/examples/AppShellSidebarDemo.svelte +1 -0
- package/src/shared/shell/app-shell/examples/AppShellToolbarDemo.svelte +1 -0
- package/src/shared/workspace/menu/WorkspaceContextMenuItems.svelte +2 -1
- package/src/shared/workspace/menu/WorkspaceMenuItems.svelte +2 -1
- package/src/shared/workspace/problems/ProblemsQuickFix.svelte +1 -4
- package/src/shared/workspace/settings/AppSettingsContent.svelte +6 -0
- package/src/shared/workspace/settings/AppSettingsNavigation.svelte +7 -0
- package/src/shared/workspace/settings/CopyableValue.svelte +81 -0
- package/src/shared/workspace/settings/DeclarativeSettingsSection.svelte +20 -0
- package/src/shared/workspace/settings/WorkspaceSettingField.svelte +110 -41
- package/src/shared/workspace/settings/WorkspaceSettingMultiSelect.svelte +7 -6
- package/src/shared/workspace/settings/WorkspaceSettingObjectTable.svelte +187 -23
- package/src/shared/workspace/settings/WorkspaceSettingSelect.svelte +29 -29
- package/src/shared/workspace/settings/WorkspaceSettings.css +190 -4
- package/src/shared/workspace/settings/WorkspaceSettingsStoryCustomField.svelte +2 -2
- package/src/shared/workspace/settings/WorkspaceSettingsStoryCustomPage.svelte +13 -0
- package/src/shared/workspace/settings/WorkspaceSettingsSurface.svelte +50 -0
- package/src/shared/workspace/settings/configuration.ts +5 -0
- package/src/shared/workspace/settings/copyable-value.ts +10 -0
- package/src/shared/workspace/settings/index.ts +5 -0
- package/src/shared/workspace/settings/settings-controller.svelte.ts +349 -15
- package/src/shared/workspace/settings/types.ts +90 -8
- package/src/storybook/app-shell-reference/AppShellTwoExpandedSidebarsReference.css +25 -0
- package/src/storybook/app-shell-reference/AppShellTwoExpandedSidebarsReference.svelte +48 -0
- package/src/storybook/app-shell-reference/index.ts +1 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onDestroy } from "svelte";
|
|
3
|
+
import { Button } from "@lapismd/design-core/shadcn/button";
|
|
4
|
+
import WorkspaceIcon from "../icon/WorkspaceIcon.svelte";
|
|
5
|
+
import { shortenCopyableValue } from "./copyable-value.js";
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
value,
|
|
9
|
+
label = "value",
|
|
10
|
+
emptyLabel = "None",
|
|
11
|
+
leadingCharacters = 8,
|
|
12
|
+
trailingCharacters = 4,
|
|
13
|
+
class: className,
|
|
14
|
+
testId,
|
|
15
|
+
}: {
|
|
16
|
+
value?: string | null;
|
|
17
|
+
label?: string;
|
|
18
|
+
emptyLabel?: string;
|
|
19
|
+
leadingCharacters?: number;
|
|
20
|
+
trailingCharacters?: number;
|
|
21
|
+
class?: string;
|
|
22
|
+
testId?: string;
|
|
23
|
+
} = $props();
|
|
24
|
+
|
|
25
|
+
let copied = $state(false);
|
|
26
|
+
let failed = $state(false);
|
|
27
|
+
let resetTimer: ReturnType<typeof setTimeout> | undefined;
|
|
28
|
+
let displayValue = $derived(
|
|
29
|
+
value
|
|
30
|
+
? shortenCopyableValue(value, leadingCharacters, trailingCharacters)
|
|
31
|
+
: emptyLabel,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
onDestroy(() => {
|
|
35
|
+
if (resetTimer) clearTimeout(resetTimer);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
async function copy(): Promise<void> {
|
|
39
|
+
if (!value) return;
|
|
40
|
+
copied = false;
|
|
41
|
+
failed = false;
|
|
42
|
+
try {
|
|
43
|
+
const clipboard = globalThis.navigator?.clipboard;
|
|
44
|
+
if (!clipboard?.writeText) throw new Error("Clipboard is unavailable");
|
|
45
|
+
await clipboard.writeText(value);
|
|
46
|
+
copied = true;
|
|
47
|
+
} catch {
|
|
48
|
+
failed = true;
|
|
49
|
+
}
|
|
50
|
+
if (resetTimer) clearTimeout(resetTimer);
|
|
51
|
+
resetTimer = setTimeout(() => {
|
|
52
|
+
copied = false;
|
|
53
|
+
failed = false;
|
|
54
|
+
}, 1_500);
|
|
55
|
+
}
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
{#if value}
|
|
59
|
+
<Button
|
|
60
|
+
class={["ui-workspace-copyable-value", className].filter(Boolean).join(" ")}
|
|
61
|
+
variant="ghost"
|
|
62
|
+
size="xs"
|
|
63
|
+
aria-label={`Copy full ${label}: ${value}`}
|
|
64
|
+
title={`Copy full ${label}`}
|
|
65
|
+
data-testid={testId}
|
|
66
|
+
data-copied={copied || undefined}
|
|
67
|
+
data-copy-failed={failed || undefined}
|
|
68
|
+
onclick={() => void copy()}
|
|
69
|
+
>
|
|
70
|
+
<code>{displayValue}</code>
|
|
71
|
+
<WorkspaceIcon
|
|
72
|
+
name={copied ? "check" : failed ? "triangle-alert" : "copy"}
|
|
73
|
+
/>
|
|
74
|
+
</Button>
|
|
75
|
+
{:else}
|
|
76
|
+
<span
|
|
77
|
+
class={["ui-workspace-copyable-value__empty", className]
|
|
78
|
+
.filter(Boolean)
|
|
79
|
+
.join(" ")}>{displayValue}</span
|
|
80
|
+
>
|
|
81
|
+
{/if}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import AppSettingsRoot from "./AppSettingsRoot.svelte";
|
|
3
|
+
import AppSettingsSection from "./AppSettingsSection.svelte";
|
|
4
|
+
import type { WorkspaceSettingsController } from "./settings-controller.svelte.js";
|
|
5
|
+
import type { WorkspaceSettingsSection } from "./types.js";
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
controller,
|
|
9
|
+
section,
|
|
10
|
+
class: className = "",
|
|
11
|
+
}: {
|
|
12
|
+
controller: WorkspaceSettingsController;
|
|
13
|
+
section: WorkspaceSettingsSection;
|
|
14
|
+
class?: string;
|
|
15
|
+
} = $props();
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<AppSettingsRoot {controller} class={className}>
|
|
19
|
+
<AppSettingsSection {section} />
|
|
20
|
+
</AppSettingsRoot>
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
import WorkspaceSettingObjectTable from "./WorkspaceSettingObjectTable.svelte";
|
|
22
22
|
import WorkspaceSettingSelect from "./WorkspaceSettingSelect.svelte";
|
|
23
23
|
import WorkspaceSettingToggleTable from "./WorkspaceSettingToggleTable.svelte";
|
|
24
|
+
import CopyableValue from "./CopyableValue.svelte";
|
|
24
25
|
|
|
25
26
|
let {
|
|
26
27
|
controller,
|
|
@@ -31,7 +32,12 @@
|
|
|
31
32
|
} = $props();
|
|
32
33
|
|
|
33
34
|
let value = $derived(controller.get(field.id));
|
|
34
|
-
let error = $derived(controller.
|
|
35
|
+
let error = $derived(controller.getError(field.id));
|
|
36
|
+
let busy = $derived(controller.isBusy(field.id));
|
|
37
|
+
let actionResult = $derived(controller.getActionResult(field.id));
|
|
38
|
+
let controlDisabled = $derived(
|
|
39
|
+
field.disabled === true || field.readOnly === true,
|
|
40
|
+
);
|
|
35
41
|
let options = $state<WorkspaceSettingOption[]>([]);
|
|
36
42
|
let optionRequest = 0;
|
|
37
43
|
let keyValueOptions = $derived.by(() => {
|
|
@@ -100,7 +106,8 @@
|
|
|
100
106
|
return field.type === "key-value" ||
|
|
101
107
|
field.type === "object-array" ||
|
|
102
108
|
field.type === "object-grid" ||
|
|
103
|
-
field.type === "object-map"
|
|
109
|
+
field.type === "object-map" ||
|
|
110
|
+
(field.type === "custom" && field.presentation === "full-width")
|
|
104
111
|
? "stacked"
|
|
105
112
|
: "row";
|
|
106
113
|
}
|
|
@@ -123,7 +130,7 @@
|
|
|
123
130
|
const next = { ...current };
|
|
124
131
|
delete next[currentKey];
|
|
125
132
|
next[nextKey] = nextValue;
|
|
126
|
-
controller.
|
|
133
|
+
void controller.set(field.id, next);
|
|
127
134
|
}
|
|
128
135
|
|
|
129
136
|
function nextKey(field: WorkspaceKeyValueSetting) {
|
|
@@ -180,17 +187,17 @@
|
|
|
180
187
|
<Switch
|
|
181
188
|
id={`setting-${field.id}`}
|
|
182
189
|
checked={value === true}
|
|
183
|
-
disabled={
|
|
184
|
-
onCheckedChange={(checked) => controller.
|
|
190
|
+
disabled={controlDisabled}
|
|
191
|
+
onCheckedChange={(checked) => void controller.set(field.id, checked)}
|
|
185
192
|
/>
|
|
186
193
|
{:else if field.type === "string" && field.presentation === "icon"}
|
|
187
194
|
<WorkspaceIconPicker
|
|
188
195
|
id={`setting-${field.id}`}
|
|
189
196
|
value={String(value ?? "")}
|
|
190
|
-
disabled={
|
|
197
|
+
disabled={controlDisabled}
|
|
191
198
|
placeholder={field.placeholder ?? "Select an icon"}
|
|
192
199
|
ariaLabel={field.title}
|
|
193
|
-
onValueChange={(next) => controller.
|
|
200
|
+
onValueChange={(next) => void controller.set(field.id, next)}
|
|
194
201
|
/>
|
|
195
202
|
{:else if field.type === "string" && field.presentation === "textarea"}
|
|
196
203
|
<Textarea
|
|
@@ -198,30 +205,30 @@
|
|
|
198
205
|
rows={1}
|
|
199
206
|
value={String(value ?? "")}
|
|
200
207
|
placeholder={field.placeholder}
|
|
201
|
-
disabled={
|
|
208
|
+
disabled={controlDisabled}
|
|
202
209
|
aria-invalid={Boolean(error)}
|
|
203
210
|
oninput={(event) =>
|
|
204
|
-
controller.
|
|
211
|
+
void controller.set(field.id, event.currentTarget.value)}
|
|
205
212
|
/>
|
|
206
213
|
{:else if field.type === "string" && (field.presentation === "combobox" || field.optionsSource)}
|
|
207
214
|
<WorkspaceSettingSelect
|
|
208
215
|
id={`setting-${field.id}`}
|
|
209
216
|
items={options}
|
|
210
217
|
value={String(value ?? field.default)}
|
|
211
|
-
disabled={
|
|
218
|
+
disabled={controlDisabled}
|
|
212
219
|
ariaLabel={field.title}
|
|
213
220
|
placeholder={field.placeholder}
|
|
214
|
-
onValueChange={(next: string) => controller.
|
|
221
|
+
onValueChange={(next: string) => void controller.set(field.id, next)}
|
|
215
222
|
/>
|
|
216
223
|
{:else if field.type === "string" && field.presentation === "password"}
|
|
217
224
|
<PasswordInput
|
|
218
225
|
id={`setting-${field.id}`}
|
|
219
226
|
value={String(value ?? "")}
|
|
220
227
|
placeholder={field.placeholder}
|
|
221
|
-
disabled={
|
|
228
|
+
disabled={controlDisabled}
|
|
222
229
|
aria-invalid={Boolean(error)}
|
|
223
230
|
oninput={(event) =>
|
|
224
|
-
controller.
|
|
231
|
+
void controller.set(field.id, event.currentTarget.value)}
|
|
225
232
|
/>
|
|
226
233
|
{:else if field.type === "string"}
|
|
227
234
|
<Input
|
|
@@ -239,10 +246,10 @@
|
|
|
239
246
|
: "text"}
|
|
240
247
|
value={String(value ?? "")}
|
|
241
248
|
placeholder={field.placeholder}
|
|
242
|
-
disabled={
|
|
249
|
+
disabled={controlDisabled}
|
|
243
250
|
aria-invalid={Boolean(error)}
|
|
244
251
|
oninput={(event) =>
|
|
245
|
-
controller.
|
|
252
|
+
void controller.set(field.id, event.currentTarget.value)}
|
|
246
253
|
/>
|
|
247
254
|
{:else if (field.type === "number" || field.type === "integer") && field.minimum !== undefined && field.maximum !== undefined}
|
|
248
255
|
<div class="ui-workspace-setting-range">
|
|
@@ -253,9 +260,10 @@
|
|
|
253
260
|
min={field.minimum}
|
|
254
261
|
max={field.maximum}
|
|
255
262
|
step={field.step ?? (field.type === "integer" ? 1 : 0.1)}
|
|
256
|
-
disabled={
|
|
263
|
+
disabled={controlDisabled}
|
|
257
264
|
aria-label={field.title}
|
|
258
|
-
onValueChange={(next: number) =>
|
|
265
|
+
onValueChange={(next: number) =>
|
|
266
|
+
void controller.set(field.id, next)}
|
|
259
267
|
/>
|
|
260
268
|
<output for={`setting-${field.id}`}
|
|
261
269
|
>{Number(value ?? field.default)}</output
|
|
@@ -269,18 +277,18 @@
|
|
|
269
277
|
min={field.minimum}
|
|
270
278
|
max={field.maximum}
|
|
271
279
|
step={field.step ?? (field.type === "integer" ? 1 : "any")}
|
|
272
|
-
disabled={
|
|
280
|
+
disabled={controlDisabled}
|
|
273
281
|
onchange={(event) =>
|
|
274
|
-
controller.
|
|
282
|
+
void controller.set(field.id, event.currentTarget.valueAsNumber)}
|
|
275
283
|
/>
|
|
276
284
|
{:else if field.type === "enum"}
|
|
277
285
|
<WorkspaceSettingSelect
|
|
278
286
|
id={`setting-${field.id}`}
|
|
279
287
|
items={options}
|
|
280
288
|
value={String(value ?? field.default)}
|
|
281
|
-
disabled={
|
|
289
|
+
disabled={controlDisabled}
|
|
282
290
|
ariaLabel={field.title}
|
|
283
|
-
onValueChange={(next: string) => controller.
|
|
291
|
+
onValueChange={(next: string) => void controller.set(field.id, next)}
|
|
284
292
|
/>
|
|
285
293
|
{:else if field.type === "multi-enum"}
|
|
286
294
|
<WorkspaceSettingSelect
|
|
@@ -292,10 +300,11 @@
|
|
|
292
300
|
(entry): entry is string => typeof entry === "string",
|
|
293
301
|
)
|
|
294
302
|
: field.default}
|
|
295
|
-
disabled={
|
|
303
|
+
disabled={controlDisabled}
|
|
296
304
|
ariaLabel={field.title}
|
|
297
305
|
placeholder="Select options..."
|
|
298
|
-
onValueChange={(next: string[]) =>
|
|
306
|
+
onValueChange={(next: string[]) =>
|
|
307
|
+
void controller.set(field.id, next)}
|
|
299
308
|
/>
|
|
300
309
|
{:else if field.type === "list"}
|
|
301
310
|
<WorkspaceSettingList
|
|
@@ -303,19 +312,26 @@
|
|
|
303
312
|
label={field.title}
|
|
304
313
|
itemLabels={field.itemLabels}
|
|
305
314
|
value={Array.isArray(value) ? value : []}
|
|
306
|
-
disabled={
|
|
315
|
+
disabled={controlDisabled}
|
|
307
316
|
maximumItems={field.maximumItems}
|
|
308
|
-
onValueChange={(next) => controller.
|
|
317
|
+
onValueChange={(next) => void controller.set(field.id, next)}
|
|
309
318
|
/>
|
|
310
319
|
{:else if field.type === "object-array" || field.type === "object-grid"}
|
|
311
320
|
<WorkspaceSettingObjectTable
|
|
312
321
|
label={field.title}
|
|
313
322
|
properties={field.properties}
|
|
314
323
|
value={value ?? field.default}
|
|
315
|
-
disabled={
|
|
324
|
+
disabled={controlDisabled}
|
|
316
325
|
minimumItems={field.minimumItems}
|
|
317
326
|
maximumItems={field.maximumItems}
|
|
318
|
-
|
|
327
|
+
rowKey={field.rowKey}
|
|
328
|
+
reorderable={field.reorderable}
|
|
329
|
+
allowAdd={field.allowAdd}
|
|
330
|
+
allowRemove={field.allowRemove}
|
|
331
|
+
stateRevision={controller.sourceRevision}
|
|
332
|
+
addLabel={field.addLabel}
|
|
333
|
+
rowActions={field.rowActions}
|
|
334
|
+
onValueChange={(next) => void controller.set(field.id, next)}
|
|
319
335
|
/>
|
|
320
336
|
{:else if field.type === "object-map"}
|
|
321
337
|
<WorkspaceSettingObjectTable
|
|
@@ -323,8 +339,8 @@
|
|
|
323
339
|
properties={field.properties}
|
|
324
340
|
mode="map"
|
|
325
341
|
value={value ?? field.default}
|
|
326
|
-
disabled={
|
|
327
|
-
onValueChange={(next) => controller.
|
|
342
|
+
disabled={controlDisabled}
|
|
343
|
+
onValueChange={(next) => void controller.set(field.id, next)}
|
|
328
344
|
/>
|
|
329
345
|
{:else if field.type === "key-value"}
|
|
330
346
|
<div class="ui-workspace-setting-key-value">
|
|
@@ -370,7 +386,7 @@
|
|
|
370
386
|
onclick={() => {
|
|
371
387
|
const next = { ...keyValue(field) };
|
|
372
388
|
delete next[key];
|
|
373
|
-
controller.
|
|
389
|
+
void controller.set(field.id, next);
|
|
374
390
|
}}
|
|
375
391
|
>
|
|
376
392
|
<WorkspaceIcon name="trash-2" />
|
|
@@ -383,20 +399,62 @@
|
|
|
383
399
|
<WorkspaceSettingAddButton
|
|
384
400
|
label={field.addLabel ?? "Add entry"}
|
|
385
401
|
onclick={() =>
|
|
386
|
-
controller.
|
|
402
|
+
void controller.set(field.id, {
|
|
387
403
|
...keyValue(field),
|
|
388
404
|
[nextKey(field)]: keyValueOptions[0]?.value ?? "",
|
|
389
405
|
})}
|
|
390
406
|
/>
|
|
391
407
|
</div>
|
|
408
|
+
{:else if field.type === "output"}
|
|
409
|
+
{#if field.presentation === "copyable"}
|
|
410
|
+
<CopyableValue
|
|
411
|
+
value={value == null ? null : String(value)}
|
|
412
|
+
label={field.copyLabel ?? field.title}
|
|
413
|
+
emptyLabel={field.emptyLabel}
|
|
414
|
+
leadingCharacters={field.leadingCharacters}
|
|
415
|
+
trailingCharacters={field.trailingCharacters}
|
|
416
|
+
/>
|
|
417
|
+
{:else}
|
|
418
|
+
<output
|
|
419
|
+
id={`setting-${field.id}`}
|
|
420
|
+
class="ui-workspace-setting-output"
|
|
421
|
+
data-presentation={field.presentation ?? "text"}
|
|
422
|
+
>
|
|
423
|
+
{#if field.presentation === "code"}
|
|
424
|
+
<code
|
|
425
|
+
>{value == null
|
|
426
|
+
? (field.emptyLabel ?? "None")
|
|
427
|
+
: String(value)}</code
|
|
428
|
+
>
|
|
429
|
+
{:else}
|
|
430
|
+
{value == null ? (field.emptyLabel ?? "None") : String(value)}
|
|
431
|
+
{/if}
|
|
432
|
+
</output>
|
|
433
|
+
{/if}
|
|
392
434
|
{:else if field.type === "custom"}
|
|
393
|
-
{@const CustomComponent = field.
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
435
|
+
{@const CustomComponent = field.adapter
|
|
436
|
+
? controller.resolveCustomAdapter(field.id, field.adapter)?.component
|
|
437
|
+
: field.component}
|
|
438
|
+
{#if CustomComponent}
|
|
439
|
+
<CustomComponent
|
|
440
|
+
id={field.id}
|
|
441
|
+
{field}
|
|
442
|
+
{value}
|
|
443
|
+
disabled={controlDisabled}
|
|
444
|
+
readOnly={field.readOnly}
|
|
445
|
+
{busy}
|
|
446
|
+
{error}
|
|
447
|
+
setValue={(next) => controller.set(field.id, next)}
|
|
448
|
+
update={(next) => controller.update(field.id, next)}
|
|
449
|
+
/>
|
|
450
|
+
{:else}
|
|
451
|
+
<Alert.Root class="ui-workspace-setting-unsupported">
|
|
452
|
+
<Alert.Title>Unavailable custom field</Alert.Title>
|
|
453
|
+
<Alert.Description>
|
|
454
|
+
The adapter for this setting is not registered.
|
|
455
|
+
</Alert.Description>
|
|
456
|
+
</Alert.Root>
|
|
457
|
+
{/if}
|
|
400
458
|
{:else if field.type === "unsupported"}
|
|
401
459
|
<Alert.Root class="ui-workspace-setting-unsupported">
|
|
402
460
|
<Alert.Title>Unsupported setting</Alert.Title>
|
|
@@ -410,7 +468,8 @@
|
|
|
410
468
|
<Button
|
|
411
469
|
id={`setting-${field.id}`}
|
|
412
470
|
variant={field.variant ?? "outline"}
|
|
413
|
-
disabled={field.
|
|
471
|
+
disabled={controller.isDisabled(field.id) || busy}
|
|
472
|
+
aria-busy={busy}
|
|
414
473
|
onclick={() => controller.runAction(field.id)}
|
|
415
474
|
>
|
|
416
475
|
{#if field.icon}<WorkspaceIcon name={field.icon} />{/if}
|
|
@@ -418,14 +477,24 @@
|
|
|
418
477
|
</Button>
|
|
419
478
|
{/if}
|
|
420
479
|
|
|
421
|
-
{#if field.type
|
|
480
|
+
{#if field.type === "action" && actionResult}
|
|
481
|
+
<p
|
|
482
|
+
class="ui-workspace-setting-action-result"
|
|
483
|
+
data-tone={actionResult.tone}
|
|
484
|
+
role={actionResult.tone === "error" ? "alert" : "status"}
|
|
485
|
+
>
|
|
486
|
+
{actionResult.message}
|
|
487
|
+
</p>
|
|
488
|
+
{/if}
|
|
489
|
+
|
|
490
|
+
{#if field.type !== "action" && field.type !== "output" && "default" in field && field.default !== undefined}
|
|
422
491
|
<Button
|
|
423
492
|
class="ui-workspace-setting-restore"
|
|
424
493
|
variant="ghost"
|
|
425
494
|
size="icon-sm"
|
|
426
495
|
aria-label={`Restore ${field.title} default`}
|
|
427
496
|
title="Restore default"
|
|
428
|
-
disabled={
|
|
497
|
+
disabled={controlDisabled}
|
|
429
498
|
onclick={() => controller.restoreDefault(field.id)}
|
|
430
499
|
>
|
|
431
500
|
<WorkspaceIcon name="rotate-ccw" />
|
|
@@ -85,7 +85,9 @@
|
|
|
85
85
|
dataUiComponent="workspace-setting-multiselect"
|
|
86
86
|
data-ui-part="trigger"
|
|
87
87
|
>
|
|
88
|
-
<span class="ui-workspace-setting-select__value"
|
|
88
|
+
<span class="ui-workspace-setting-select__value"
|
|
89
|
+
>{triggerContent}</span
|
|
90
|
+
>
|
|
89
91
|
<span data-ui-part="chevron">
|
|
90
92
|
<WorkspaceIcon name="chevrons-up-down" />
|
|
91
93
|
</span>
|
|
@@ -100,17 +102,16 @@
|
|
|
100
102
|
data-ui-component="workspace-setting-multiselect"
|
|
101
103
|
data-ui-part="content"
|
|
102
104
|
>
|
|
103
|
-
<CommandView.Root
|
|
104
|
-
shouldFilter={false}
|
|
105
|
-
label={ariaLabel ?? placeholder}
|
|
106
|
-
>
|
|
105
|
+
<CommandView.Root shouldFilter={false} label={ariaLabel ?? placeholder}>
|
|
107
106
|
<CommandView.Input
|
|
108
107
|
bind:value={query}
|
|
109
108
|
placeholder="Search options..."
|
|
110
109
|
autocomplete="off"
|
|
111
110
|
spellcheck="false"
|
|
112
111
|
/>
|
|
113
|
-
<CommandView.List
|
|
112
|
+
<CommandView.List
|
|
113
|
+
aria-label={ariaLabel ? `${ariaLabel} options` : "Options"}
|
|
114
|
+
>
|
|
114
115
|
<CommandView.Empty>No options found.</CommandView.Empty>
|
|
115
116
|
{#if filtered.length > 0}
|
|
116
117
|
<CommandView.Group>
|