@warkypublic/svelix 0.2.1 → 0.2.3
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 +10 -2
- package/dist/components/Boxer/Boxer.svelte +11 -0
- package/dist/components/Boxer/types.d.ts +2 -0
- package/dist/components/ContentEditor/index.d.ts +12 -0
- package/dist/components/ContentEditor/index.js +12 -0
- package/dist/components/FormerControllers/CheckBoxCtrl.svelte +77 -0
- package/dist/components/FormerControllers/CheckBoxCtrl.svelte.d.ts +11 -0
- package/dist/components/FormerControllers/FileInputCtrl.svelte +106 -0
- package/dist/components/FormerControllers/FileInputCtrl.svelte.d.ts +9 -0
- package/dist/components/FormerControllers/InlineWrapper.svelte +2 -2
- package/dist/components/FormerControllers/JsonCtrl/JsonCtrl.svelte +61 -0
- package/dist/components/FormerControllers/JsonCtrl/JsonCtrl.svelte.d.ts +8 -0
- package/dist/components/FormerControllers/JsonCtrl/JsonCtrlEditorDialog.svelte +72 -0
- package/dist/components/FormerControllers/JsonCtrl/JsonCtrlEditorDialog.svelte.d.ts +9 -0
- package/dist/components/FormerControllers/JsonCtrl/JsonCtrlMonaco.svelte +45 -0
- package/dist/components/FormerControllers/JsonCtrl/JsonCtrlMonaco.svelte.d.ts +8 -0
- package/dist/components/FormerControllers/JsonCtrl/index.d.ts +1 -0
- package/dist/components/FormerControllers/JsonCtrl/index.js +1 -0
- package/dist/components/FormerControllers/index.d.ts +3 -0
- package/dist/components/FormerControllers/index.js +3 -0
- package/dist/components/Icons/IconEye.svelte +6 -0
- package/dist/components/Icons/IconEye.svelte.d.ts +7 -0
- package/dist/components/Icons/index.d.ts +1 -0
- package/dist/components/Icons/index.js +1 -0
- package/dist/components/Icons/strings.d.ts +1 -0
- package/dist/components/Icons/strings.js +1 -0
- package/llm/FORMER_CONTROLLERS.md +190 -0
- package/llm/README.md +4 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -32,8 +32,11 @@ import { Button, Former, Gridler } from '@warkypublic/svelix';
|
|
|
32
32
|
| `ButtonCtrl`, `IconButtonCtrl` | Button and icon-button form controls |
|
|
33
33
|
| `TextInputCtrl`, `TextAreaCtrl`, `PasswordInputCtrl` | Text input controls |
|
|
34
34
|
| `NumberInputCtrl`, `NativeSelectCtrl` | Number and select controls |
|
|
35
|
-
| `
|
|
36
|
-
| `
|
|
35
|
+
| `CheckBoxCtrl`, `SwitchCtrl` | Checkbox and toggle controls; `CheckBoxCtrl` supports checkbox or switch presentation and boolean, integer, or string values |
|
|
36
|
+
| `FileInputCtrl` | Single-file picker with a compact file-type or image thumbnail, filename, and size |
|
|
37
|
+
| `JsonCtrl` | JSON editor control with a dialog editor and preview |
|
|
38
|
+
| `DateTimeCtrl` | Date/time picker control |
|
|
39
|
+
| `CtrlFieldShell`, `InlineWrapper` | Field shell and inline layout wrapper for form controls |
|
|
37
40
|
|
|
38
41
|
### Data Grids
|
|
39
42
|
| Export | Description |
|
|
@@ -59,6 +62,10 @@ import { Button, Former, Gridler } from '@warkypublic/svelix';
|
|
|
59
62
|
| Export | Description |
|
|
60
63
|
|---|---|
|
|
61
64
|
| `ContentEditor` | Rich content editor (Carta Markdown + Monaco) |
|
|
65
|
+
| `TextEditor`, `MarkdownViewer`, `MonacoEditor` | Text, Markdown, and code editing components |
|
|
66
|
+
| `CollaboraEditor`, `Office365Editor` | Office document editor integrations |
|
|
67
|
+
| `ImageViewer`, `AudioPlayer`, `VideoPlayer`, `PdfViewer` | File media and PDF viewers |
|
|
68
|
+
| `EmailViewer`, `ZipViewer`, `UnknownFile` | Fallback file viewers |
|
|
62
69
|
|
|
63
70
|
### Trees
|
|
64
71
|
| Export | Description |
|
|
@@ -98,6 +105,7 @@ Extended architecture and implementation docs are published with the package und
|
|
|
98
105
|
node_modules/@warkypublic/svelix/llm/README.md
|
|
99
106
|
node_modules/@warkypublic/svelix/llm/ARCHITECTURE.md
|
|
100
107
|
node_modules/@warkypublic/svelix/llm/COMPONENT_GUIDE.md
|
|
108
|
+
node_modules/@warkypublic/svelix/llm/FORMER_CONTROLLERS.md
|
|
101
109
|
```
|
|
102
110
|
|
|
103
111
|
## Development
|
|
@@ -405,6 +405,9 @@ function onOptionPointerDown(e, index) {
|
|
|
405
405
|
function syncInsideDialogFlag() {
|
|
406
406
|
insideDialog = !!anchorEl?.closest("dialog, [role=\"dialog\"]");
|
|
407
407
|
}
|
|
408
|
+
function isSvgIcon(value) {
|
|
409
|
+
return value?.trimStart?.().startsWith?.("<svg");
|
|
410
|
+
}
|
|
408
411
|
// Public API via bind:this
|
|
409
412
|
export function clear() {
|
|
410
413
|
onClear();
|
|
@@ -625,6 +628,14 @@ $effect(() => {
|
|
|
625
628
|
type="checkbox"
|
|
626
629
|
/>
|
|
627
630
|
{/if}
|
|
631
|
+
{#if item?.icon}
|
|
632
|
+
{#if isSvgIcon(item.icon)}
|
|
633
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
634
|
+
<span class="size-4 flex items-center shrink-0">{@html item.icon}</span>
|
|
635
|
+
{:else}
|
|
636
|
+
<span class="shrink-0">{item.icon}</span>
|
|
637
|
+
{/if}
|
|
638
|
+
{/if}
|
|
628
639
|
<span>{item?.label}</span>
|
|
629
640
|
</div>
|
|
630
641
|
{/each}
|
|
@@ -42,6 +42,8 @@ export type BoxerItem = {
|
|
|
42
42
|
[key: string]: any;
|
|
43
43
|
label: string;
|
|
44
44
|
value: any;
|
|
45
|
+
/** Optional icon rendered before the label in the dropdown list. Accepts an SVG string (rendered raw) or plain text/emoji. */
|
|
46
|
+
icon?: string;
|
|
45
47
|
};
|
|
46
48
|
export interface BoxerProps {
|
|
47
49
|
/** Server adapter (ResolveSpec or HeaderSpec). Automatically sets `dataSource` to `'server'` when provided. */
|
|
@@ -1,2 +1,14 @@
|
|
|
1
1
|
export { default as ContentEditor } from './ContentEditor.svelte';
|
|
2
|
+
export { default as AudioPlayer } from './subcomponents/AudioPlayer.svelte';
|
|
3
|
+
export { default as CollaboraEditor } from './subcomponents/CollaboraEditor.svelte';
|
|
4
|
+
export { default as EmailViewer } from './subcomponents/EmailViewer.svelte';
|
|
5
|
+
export { default as ImageViewer } from './subcomponents/ImageViewer.svelte';
|
|
6
|
+
export { default as MarkdownViewer } from './subcomponents/MarkdownViewer.svelte';
|
|
7
|
+
export { default as MonacoEditor } from './subcomponents/MonacoEditor.svelte';
|
|
8
|
+
export { default as Office365Editor } from './subcomponents/Office365Editor.svelte';
|
|
9
|
+
export { default as PdfViewer } from './subcomponents/PdfViewer.svelte';
|
|
10
|
+
export { default as TextEditor } from './subcomponents/TextEditor.svelte';
|
|
11
|
+
export { default as UnknownFile } from './subcomponents/UnknownFile.svelte';
|
|
12
|
+
export { default as VideoPlayer } from './subcomponents/VideoPlayer.svelte';
|
|
13
|
+
export { default as ZipViewer } from './subcomponents/ZipViewer.svelte';
|
|
2
14
|
export * from './types.js';
|
|
@@ -1,2 +1,14 @@
|
|
|
1
1
|
export { default as ContentEditor } from './ContentEditor.svelte';
|
|
2
|
+
export { default as AudioPlayer } from './subcomponents/AudioPlayer.svelte';
|
|
3
|
+
export { default as CollaboraEditor } from './subcomponents/CollaboraEditor.svelte';
|
|
4
|
+
export { default as EmailViewer } from './subcomponents/EmailViewer.svelte';
|
|
5
|
+
export { default as ImageViewer } from './subcomponents/ImageViewer.svelte';
|
|
6
|
+
export { default as MarkdownViewer } from './subcomponents/MarkdownViewer.svelte';
|
|
7
|
+
export { default as MonacoEditor } from './subcomponents/MonacoEditor.svelte';
|
|
8
|
+
export { default as Office365Editor } from './subcomponents/Office365Editor.svelte';
|
|
9
|
+
export { default as PdfViewer } from './subcomponents/PdfViewer.svelte';
|
|
10
|
+
export { default as TextEditor } from './subcomponents/TextEditor.svelte';
|
|
11
|
+
export { default as UnknownFile } from './subcomponents/UnknownFile.svelte';
|
|
12
|
+
export { default as VideoPlayer } from './subcomponents/VideoPlayer.svelte';
|
|
13
|
+
export { default as ZipViewer } from './subcomponents/ZipViewer.svelte';
|
|
2
14
|
export * from './types.js';
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<script lang="ts">import { makeFieldId } from "./utils";
|
|
2
|
+
let { checked = $bindable(false), dataFormat = "boolean", disabled, error, label, name, onchange, required, sid, tooltip, type = "checkbox" } = $props();
|
|
3
|
+
const id = $derived(makeFieldId(name, sid));
|
|
4
|
+
const errorId = $derived(`${id}-error`);
|
|
5
|
+
const inputChecked = $derived(toBoolean(checked, dataFormat));
|
|
6
|
+
function toBoolean(value, format) {
|
|
7
|
+
if (format === "integer") return value === 1;
|
|
8
|
+
if (format === "string") {
|
|
9
|
+
return typeof value === "string" && [
|
|
10
|
+
"1",
|
|
11
|
+
"true",
|
|
12
|
+
"yes"
|
|
13
|
+
].includes(value.trim().toLowerCase());
|
|
14
|
+
}
|
|
15
|
+
return value === true;
|
|
16
|
+
}
|
|
17
|
+
function formatValue(value) {
|
|
18
|
+
if (dataFormat === "integer") return value ? 1 : 0;
|
|
19
|
+
if (dataFormat === "string") return value ? "true" : "false";
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
function handleChange(event) {
|
|
23
|
+
checked = formatValue(event.currentTarget.checked);
|
|
24
|
+
onchange?.(checked);
|
|
25
|
+
}
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<div class="flex flex-col gap-1" title={tooltip}>
|
|
29
|
+
{#if type === 'switch'}
|
|
30
|
+
<label class="flex w-fit cursor-pointer items-center gap-2" for={id}>
|
|
31
|
+
<input
|
|
32
|
+
{id}
|
|
33
|
+
{disabled}
|
|
34
|
+
{name}
|
|
35
|
+
{required}
|
|
36
|
+
aria-describedby={error ? errorId : undefined}
|
|
37
|
+
aria-invalid={!!error}
|
|
38
|
+
aria-checked={inputChecked}
|
|
39
|
+
checked={inputChecked}
|
|
40
|
+
class="peer sr-only"
|
|
41
|
+
role="switch"
|
|
42
|
+
type="checkbox"
|
|
43
|
+
onchange={handleChange}
|
|
44
|
+
/>
|
|
45
|
+
<span
|
|
46
|
+
aria-hidden="true"
|
|
47
|
+
class="flex h-6 w-10 items-center rounded-full bg-surface-300-700 p-0.5 transition-colors peer-checked:[&>span]:translate-x-4 peer-checked:bg-primary-500 peer-disabled:cursor-not-allowed peer-disabled:opacity-50 peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-primary-500"
|
|
48
|
+
>
|
|
49
|
+
<span class="size-5 rounded-full bg-surface-50 transition-transform"></span>
|
|
50
|
+
</span>
|
|
51
|
+
{#if label}
|
|
52
|
+
<span class="label text-sm">{label}{#if required}<span class="text-error-500">*</span>{/if}</span>
|
|
53
|
+
{/if}
|
|
54
|
+
</label>
|
|
55
|
+
{:else}
|
|
56
|
+
<div class="flex items-center gap-2">
|
|
57
|
+
<input
|
|
58
|
+
{id}
|
|
59
|
+
{disabled}
|
|
60
|
+
{name}
|
|
61
|
+
{required}
|
|
62
|
+
aria-describedby={error ? errorId : undefined}
|
|
63
|
+
aria-invalid={!!error}
|
|
64
|
+
checked={inputChecked}
|
|
65
|
+
class="checkbox"
|
|
66
|
+
type="checkbox"
|
|
67
|
+
onchange={handleChange}
|
|
68
|
+
/>
|
|
69
|
+
{#if label}
|
|
70
|
+
<label class="label text-sm" for={id}>{label}{#if required}<span class="text-error-500">*</span>{/if}</label>
|
|
71
|
+
{/if}
|
|
72
|
+
</div>
|
|
73
|
+
{/if}
|
|
74
|
+
{#if error}
|
|
75
|
+
<p class="text-error-500 text-xs" id={errorId}>{error}</p>
|
|
76
|
+
{/if}
|
|
77
|
+
</div>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CtrlBaseProps } from './types';
|
|
2
|
+
export type CheckBoxCtrlValue = boolean | 0 | 1 | string | null;
|
|
3
|
+
export interface Props extends Omit<CtrlBaseProps, 'placeholder'> {
|
|
4
|
+
checked?: CheckBoxCtrlValue;
|
|
5
|
+
dataFormat?: 'boolean' | 'integer' | 'string';
|
|
6
|
+
onchange?: (checked: CheckBoxCtrlValue) => void;
|
|
7
|
+
type?: 'checkbox' | 'switch';
|
|
8
|
+
}
|
|
9
|
+
declare const CheckBoxCtrl: import("svelte").Component<Props, {}, "checked">;
|
|
10
|
+
type CheckBoxCtrl = ReturnType<typeof CheckBoxCtrl>;
|
|
11
|
+
export default CheckBoxCtrl;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
<script lang="ts">import CtrlFieldShell from "./CtrlFieldShell.svelte";
|
|
2
|
+
import { makeFieldId } from "./utils";
|
|
3
|
+
let { accept, disabled, error, label, name, onchange, required, sid, tooltip, value = $bindable(null) } = $props();
|
|
4
|
+
let imageUrl = $state(null);
|
|
5
|
+
const id = $derived(makeFieldId(name, sid));
|
|
6
|
+
const isImage = $derived(value?.type.startsWith("image/") ?? false);
|
|
7
|
+
const fileType = $derived(getFileType(value));
|
|
8
|
+
$effect(() => {
|
|
9
|
+
if (!value || !isImage) {
|
|
10
|
+
imageUrl = null;
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const url = URL.createObjectURL(value);
|
|
14
|
+
imageUrl = url;
|
|
15
|
+
return () => URL.revokeObjectURL(url);
|
|
16
|
+
});
|
|
17
|
+
function handleChange(event) {
|
|
18
|
+
value = event.currentTarget.files?.[0] ?? null;
|
|
19
|
+
onchange?.(value);
|
|
20
|
+
}
|
|
21
|
+
function getFileType(file) {
|
|
22
|
+
if (!file) return "FILE";
|
|
23
|
+
if (file.type.startsWith("image/")) return "IMG";
|
|
24
|
+
if (file.type.startsWith("video/")) return "VID";
|
|
25
|
+
if (file.type.startsWith("audio/")) return "AUD";
|
|
26
|
+
if (file.type === "application/pdf") return "PDF";
|
|
27
|
+
const extension = file.name.split(".").pop()?.toLowerCase();
|
|
28
|
+
if ([
|
|
29
|
+
"doc",
|
|
30
|
+
"docx",
|
|
31
|
+
"odt",
|
|
32
|
+
"rtf"
|
|
33
|
+
].includes(extension ?? "")) return "DOC";
|
|
34
|
+
if ([
|
|
35
|
+
"xls",
|
|
36
|
+
"xlsx",
|
|
37
|
+
"ods",
|
|
38
|
+
"csv"
|
|
39
|
+
].includes(extension ?? "")) return "SHEET";
|
|
40
|
+
if ([
|
|
41
|
+
"ppt",
|
|
42
|
+
"pptx",
|
|
43
|
+
"odp"
|
|
44
|
+
].includes(extension ?? "")) return "SLIDE";
|
|
45
|
+
if ([
|
|
46
|
+
"zip",
|
|
47
|
+
"rar",
|
|
48
|
+
"7z",
|
|
49
|
+
"tar",
|
|
50
|
+
"gz"
|
|
51
|
+
].includes(extension ?? "")) return "ZIP";
|
|
52
|
+
if ([
|
|
53
|
+
"txt",
|
|
54
|
+
"md",
|
|
55
|
+
"json",
|
|
56
|
+
"xml",
|
|
57
|
+
"yaml",
|
|
58
|
+
"yml",
|
|
59
|
+
"js",
|
|
60
|
+
"ts",
|
|
61
|
+
"css",
|
|
62
|
+
"html"
|
|
63
|
+
].includes(extension ?? "")) {
|
|
64
|
+
return "TEXT";
|
|
65
|
+
}
|
|
66
|
+
return extension?.slice(0, 5).toUpperCase() || "FILE";
|
|
67
|
+
}
|
|
68
|
+
function formatSize(bytes) {
|
|
69
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
70
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
71
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
72
|
+
}
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<CtrlFieldShell {error} {id} {label} {required} {tooltip}>
|
|
76
|
+
<div class="flex min-w-0 items-center gap-3 rounded-container-token border border-surface-200-800 bg-surface-50-900 p-2">
|
|
77
|
+
<input {accept} {disabled} {id} {name} {required} class="sr-only" type="file" onchange={handleChange} />
|
|
78
|
+
{#if imageUrl && value}
|
|
79
|
+
<img alt={`Preview of ${value.name}`} class="size-9 shrink-0 rounded object-cover" src={imageUrl} />
|
|
80
|
+
{:else}
|
|
81
|
+
<div
|
|
82
|
+
aria-label={`${fileType} file preview`}
|
|
83
|
+
class="flex size-9 shrink-0 items-center justify-center rounded bg-primary-100-900 text-center text-[10px] font-bold tracking-wide text-primary-700-300"
|
|
84
|
+
role="img"
|
|
85
|
+
>
|
|
86
|
+
{fileType}
|
|
87
|
+
</div>
|
|
88
|
+
{/if}
|
|
89
|
+
<div class="min-w-0 flex-1">
|
|
90
|
+
{#if value}
|
|
91
|
+
<p class="truncate text-sm font-medium" title={value.name}>{value.name}</p>
|
|
92
|
+
<p class="text-xs text-surface-500-400">{formatSize(value.size)}</p>
|
|
93
|
+
{:else}
|
|
94
|
+
<p class="truncate text-sm text-surface-500-400">No file selected</p>
|
|
95
|
+
{/if}
|
|
96
|
+
</div>
|
|
97
|
+
<label
|
|
98
|
+
class="btn preset-outlined-primary-500 shrink-0"
|
|
99
|
+
class:cursor-not-allowed={disabled}
|
|
100
|
+
class:opacity-50={disabled}
|
|
101
|
+
for={id}
|
|
102
|
+
>
|
|
103
|
+
{value ? 'Replace file' : 'Choose file'}
|
|
104
|
+
</label>
|
|
105
|
+
</div>
|
|
106
|
+
</CtrlFieldShell>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CtrlBaseProps } from './types';
|
|
2
|
+
export interface Props extends Omit<CtrlBaseProps, 'placeholder'> {
|
|
3
|
+
accept?: string;
|
|
4
|
+
onchange?: (value: File | null) => void;
|
|
5
|
+
value?: File | null;
|
|
6
|
+
}
|
|
7
|
+
declare const FileInputCtrl: import("svelte").Component<Props, {}, "value">;
|
|
8
|
+
type FileInputCtrl = ReturnType<typeof FileInputCtrl>;
|
|
9
|
+
export default FileInputCtrl;
|
|
@@ -16,13 +16,13 @@ const showWarningIcon = $derived(!error && !!required && isEmpty);
|
|
|
16
16
|
<div class="flex flex-nowrap gap-0">
|
|
17
17
|
{#if labelWidth && (label || promptArea)}
|
|
18
18
|
<div
|
|
19
|
-
class="flex items-center px-3
|
|
19
|
+
class="flex items-center px-3 bg-primary-100-900 text-primary-950-50 select-none"
|
|
20
20
|
style:min-width={labelWidth}
|
|
21
21
|
>
|
|
22
22
|
{#if promptArea}
|
|
23
23
|
{@render promptArea()}
|
|
24
24
|
{:else if typeof label === 'string'}
|
|
25
|
-
<span class="inline-flex items-center gap-1.5 text-xs font-medium
|
|
25
|
+
<span class="inline-flex items-center gap-1.5 text-xs font-medium">
|
|
26
26
|
{label}{#if required && isEmpty}<span class="text-error-500">*</span>{/if}
|
|
27
27
|
{#if showErrorIcon}
|
|
28
28
|
<IconAlertCircle size={14} class="text-error-500" />
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<script lang="ts">import CtrlFieldShell from "../CtrlFieldShell.svelte";
|
|
2
|
+
import { makeFieldId } from "../utils";
|
|
3
|
+
import { iconEyeSvg } from "../../Icons/strings";
|
|
4
|
+
import JsonCtrlEditorDialog from "./JsonCtrlEditorDialog.svelte";
|
|
5
|
+
let { disabled, error, label, name, onchange, required, sid, tooltip, value = $bindable(undefined) } = $props();
|
|
6
|
+
const id = $derived(makeFieldId(name, sid));
|
|
7
|
+
let dialogOpen = $state(false);
|
|
8
|
+
const preview = $derived.by(() => {
|
|
9
|
+
if (value === undefined) return {
|
|
10
|
+
text: "Empty",
|
|
11
|
+
empty: true
|
|
12
|
+
};
|
|
13
|
+
try {
|
|
14
|
+
const text = JSON.stringify(value);
|
|
15
|
+
return {
|
|
16
|
+
text: text.length > 80 ? `${text.slice(0, 80)}…` : text,
|
|
17
|
+
empty: false
|
|
18
|
+
};
|
|
19
|
+
} catch {
|
|
20
|
+
return {
|
|
21
|
+
text: "(unserializable)",
|
|
22
|
+
empty: true
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
function openDialog() {
|
|
27
|
+
if (disabled) return;
|
|
28
|
+
dialogOpen = true;
|
|
29
|
+
}
|
|
30
|
+
function handleSave(parsed) {
|
|
31
|
+
value = parsed;
|
|
32
|
+
onchange?.(parsed);
|
|
33
|
+
}
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<CtrlFieldShell {error} {id} {label} {required} {tooltip}>
|
|
37
|
+
<button
|
|
38
|
+
{id}
|
|
39
|
+
{disabled}
|
|
40
|
+
class="input flex items-center justify-between gap-2 text-left"
|
|
41
|
+
class:input-error={!!error}
|
|
42
|
+
type="button"
|
|
43
|
+
onclick={openDialog}
|
|
44
|
+
>
|
|
45
|
+
<code
|
|
46
|
+
class="truncate text-xs font-mono"
|
|
47
|
+
class:text-surface-500={preview.empty}
|
|
48
|
+
>{preview.text}</code>
|
|
49
|
+
<span class="shrink-0 flex items-center" aria-hidden="true">
|
|
50
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
51
|
+
{@html iconEyeSvg}
|
|
52
|
+
</span>
|
|
53
|
+
</button>
|
|
54
|
+
</CtrlFieldShell>
|
|
55
|
+
|
|
56
|
+
<JsonCtrlEditorDialog
|
|
57
|
+
bind:open={dialogOpen}
|
|
58
|
+
{label}
|
|
59
|
+
{value}
|
|
60
|
+
onsave={handleSave}
|
|
61
|
+
/>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CtrlBaseProps } from '../types';
|
|
2
|
+
export interface Props extends CtrlBaseProps {
|
|
3
|
+
onchange?: (value: unknown) => void;
|
|
4
|
+
value?: unknown;
|
|
5
|
+
}
|
|
6
|
+
declare const JsonCtrl: import("svelte").Component<Props, {}, "value">;
|
|
7
|
+
type JsonCtrl = ReturnType<typeof JsonCtrl>;
|
|
8
|
+
export default JsonCtrl;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<script lang="ts">import { Dialog, Portal } from "@skeletonlabs/skeleton-svelte";
|
|
2
|
+
import { createOverlayZIndex } from "../../Former/formerOverlayHelpers.svelte";
|
|
3
|
+
import JsonCtrlMonaco from "./JsonCtrlMonaco.svelte";
|
|
4
|
+
let { label, open = $bindable(false), value, onsave } = $props();
|
|
5
|
+
let draftText = $state("");
|
|
6
|
+
let parseError = $state(undefined);
|
|
7
|
+
let wasOpen = false;
|
|
8
|
+
$effect(() => {
|
|
9
|
+
if (open && !wasOpen) {
|
|
10
|
+
draftText = JSON.stringify(value ?? null, null, 2);
|
|
11
|
+
parseError = undefined;
|
|
12
|
+
}
|
|
13
|
+
wasOpen = open;
|
|
14
|
+
});
|
|
15
|
+
const overlayZ = createOverlayZIndex("dialog", () => open);
|
|
16
|
+
function handleSave() {
|
|
17
|
+
try {
|
|
18
|
+
const parsed = draftText.trim() === "" ? null : JSON.parse(draftText);
|
|
19
|
+
parseError = undefined;
|
|
20
|
+
onsave?.(parsed);
|
|
21
|
+
open = false;
|
|
22
|
+
} catch (err) {
|
|
23
|
+
parseError = err instanceof Error ? err.message : "Invalid JSON";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function handleCancel() {
|
|
27
|
+
open = false;
|
|
28
|
+
}
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<Dialog
|
|
32
|
+
open={open}
|
|
33
|
+
onOpenChange={(e) => {
|
|
34
|
+
open = e.open;
|
|
35
|
+
}}
|
|
36
|
+
closeOnInteractOutside={false}
|
|
37
|
+
modal
|
|
38
|
+
>
|
|
39
|
+
<Portal>
|
|
40
|
+
<Dialog.Backdrop
|
|
41
|
+
class="fixed inset-0 bg-black/50 backdrop-blur-sm"
|
|
42
|
+
style={`z-index:${overlayZ.backdropZ};`}
|
|
43
|
+
/>
|
|
44
|
+
<Dialog.Positioner class="fixed inset-0 flex" style={`z-index:${overlayZ.contentZ};`}>
|
|
45
|
+
<Dialog.Content class="bg-surface-100-900 shadow-2xl w-full h-full flex flex-col overflow-hidden">
|
|
46
|
+
<header class="flex items-center justify-between px-6 pt-5 pb-4 border-b border-surface-300-600 shrink-0">
|
|
47
|
+
<Dialog.Title class="text-lg font-semibold">{label ? `Edit ${label}` : 'Edit JSON'}</Dialog.Title>
|
|
48
|
+
<Dialog.CloseTrigger class="btn-icon btn-icon-sm preset-tonal" aria-label="Close dialog" onclick={handleCancel}>
|
|
49
|
+
✕
|
|
50
|
+
</Dialog.CloseTrigger>
|
|
51
|
+
</header>
|
|
52
|
+
|
|
53
|
+
<div class="flex-1 min-h-0 overflow-hidden p-4">
|
|
54
|
+
<JsonCtrlMonaco value={draftText} onchange={(text) => (draftText = text)} height="100%" />
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
{#if parseError}
|
|
58
|
+
<p class="text-error-500 text-xs px-6 pb-2" role="alert">{parseError}</p>
|
|
59
|
+
{/if}
|
|
60
|
+
|
|
61
|
+
<div class="flex items-center justify-end gap-2 p-4 border-t border-surface-300-600 shrink-0">
|
|
62
|
+
<button class="btn preset-filled-secondary-500" type="button" onclick={handleCancel}>
|
|
63
|
+
✕ Cancel
|
|
64
|
+
</button>
|
|
65
|
+
<button class="btn preset-filled-primary-500" type="button" onclick={handleSave}>
|
|
66
|
+
💾 Save
|
|
67
|
+
</button>
|
|
68
|
+
</div>
|
|
69
|
+
</Dialog.Content>
|
|
70
|
+
</Dialog.Positioner>
|
|
71
|
+
</Portal>
|
|
72
|
+
</Dialog>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface Props {
|
|
2
|
+
label?: string;
|
|
3
|
+
open?: boolean;
|
|
4
|
+
value?: unknown;
|
|
5
|
+
onsave?: (value: unknown) => void;
|
|
6
|
+
}
|
|
7
|
+
declare const JsonCtrlEditorDialog: import("svelte").Component<Props, {}, "open">;
|
|
8
|
+
type JsonCtrlEditorDialog = ReturnType<typeof JsonCtrlEditorDialog>;
|
|
9
|
+
export default JsonCtrlEditorDialog;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script lang="ts">import { onMount } from "svelte";
|
|
2
|
+
import * as monaco from "monaco-editor";
|
|
3
|
+
import { watchSkeletonDarkMode } from "../../ContentEditor/utils";
|
|
4
|
+
let { value, height = "320px", onchange } = $props();
|
|
5
|
+
let container = $state(undefined);
|
|
6
|
+
let editor;
|
|
7
|
+
let changeGuard = false;
|
|
8
|
+
let isDark = $state(false);
|
|
9
|
+
onMount(() => {
|
|
10
|
+
const stopWatchingTheme = watchSkeletonDarkMode(container, (nextIsDark) => {
|
|
11
|
+
isDark = nextIsDark;
|
|
12
|
+
});
|
|
13
|
+
if (!container) return;
|
|
14
|
+
editor = monaco.editor.create(container, {
|
|
15
|
+
value,
|
|
16
|
+
language: "json",
|
|
17
|
+
theme: isDark ? "vs-dark" : "vs",
|
|
18
|
+
automaticLayout: true,
|
|
19
|
+
minimap: { enabled: false }
|
|
20
|
+
});
|
|
21
|
+
const createdEditor = editor;
|
|
22
|
+
createdEditor.onDidChangeModelContent(() => {
|
|
23
|
+
if (changeGuard) return;
|
|
24
|
+
onchange?.(createdEditor.getValue());
|
|
25
|
+
});
|
|
26
|
+
return () => {
|
|
27
|
+
stopWatchingTheme();
|
|
28
|
+
editor?.dispose();
|
|
29
|
+
editor = undefined;
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
// Sync external value changes (e.g. dialog re-opened with different data) into the editor.
|
|
33
|
+
$effect(() => {
|
|
34
|
+
const next = value;
|
|
35
|
+
if (!editor || editor.getValue() === next) return;
|
|
36
|
+
changeGuard = true;
|
|
37
|
+
editor.setValue(next);
|
|
38
|
+
changeGuard = false;
|
|
39
|
+
});
|
|
40
|
+
$effect(() => {
|
|
41
|
+
monaco.editor.setTheme(isDark ? "vs-dark" : "vs");
|
|
42
|
+
});
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<div bind:this={container} style="width: 100%; height: {height};"></div>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface Props {
|
|
2
|
+
value: string;
|
|
3
|
+
height?: string;
|
|
4
|
+
onchange?: (text: string) => void;
|
|
5
|
+
}
|
|
6
|
+
declare const JsonCtrlMonaco: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type JsonCtrlMonaco = ReturnType<typeof JsonCtrlMonaco>;
|
|
8
|
+
export default JsonCtrlMonaco;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as JsonCtrl } from './JsonCtrl.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as JsonCtrl } from './JsonCtrl.svelte';
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export { default as ButtonCtrl } from './ButtonCtrl.svelte';
|
|
2
|
+
export { default as CheckBoxCtrl } from './CheckBoxCtrl.svelte';
|
|
2
3
|
export { default as CtrlFieldShell } from './CtrlFieldShell.svelte';
|
|
3
4
|
export { DateTimeCtrl } from './DateTimeCtrl/index';
|
|
5
|
+
export { default as FileInputCtrl } from './FileInputCtrl.svelte';
|
|
4
6
|
export { default as IconButtonCtrl } from './IconButtonCtrl.svelte';
|
|
5
7
|
export { default as InlineWrapper } from './InlineWrapper.svelte';
|
|
8
|
+
export { JsonCtrl } from './JsonCtrl/index';
|
|
6
9
|
export { default as NativeSelectCtrl } from './NativeSelectCtrl.svelte';
|
|
7
10
|
export { default as NumberInputCtrl } from './NumberInputCtrl.svelte';
|
|
8
11
|
export { default as PasswordInputCtrl } from './PasswordInputCtrl.svelte';
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export { default as ButtonCtrl } from './ButtonCtrl.svelte';
|
|
2
|
+
export { default as CheckBoxCtrl } from './CheckBoxCtrl.svelte';
|
|
2
3
|
export { default as CtrlFieldShell } from './CtrlFieldShell.svelte';
|
|
3
4
|
export { DateTimeCtrl } from './DateTimeCtrl/index';
|
|
5
|
+
export { default as FileInputCtrl } from './FileInputCtrl.svelte';
|
|
4
6
|
export { default as IconButtonCtrl } from './IconButtonCtrl.svelte';
|
|
5
7
|
export { default as InlineWrapper } from './InlineWrapper.svelte';
|
|
8
|
+
export { JsonCtrl } from './JsonCtrl/index';
|
|
6
9
|
export { default as NativeSelectCtrl } from './NativeSelectCtrl.svelte';
|
|
7
10
|
export { default as NumberInputCtrl } from './NumberInputCtrl.svelte';
|
|
8
11
|
export { default as PasswordInputCtrl } from './PasswordInputCtrl.svelte';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<script lang="ts">const { size = 16, class: cls = "" } = $props();
|
|
2
|
+
</script>
|
|
3
|
+
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class={cls} aria-hidden="true">
|
|
4
|
+
<path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z"/>
|
|
5
|
+
<circle cx="12" cy="12" r="3"/>
|
|
6
|
+
</svg>
|
|
@@ -4,6 +4,7 @@ export { default as IconAlertTriangle } from './IconAlertTriangle.svelte';
|
|
|
4
4
|
export { default as IconCamera } from './IconCamera.svelte';
|
|
5
5
|
export { default as IconClose } from './IconClose.svelte';
|
|
6
6
|
export { default as IconEdit } from './IconEdit.svelte';
|
|
7
|
+
export { default as IconEye } from './IconEye.svelte';
|
|
7
8
|
export { default as IconFilter } from './IconFilter.svelte';
|
|
8
9
|
export { default as IconSearch } from './IconSearch.svelte';
|
|
9
10
|
export { default as IconSort } from './IconSort.svelte';
|
|
@@ -4,6 +4,7 @@ export { default as IconAlertTriangle } from './IconAlertTriangle.svelte';
|
|
|
4
4
|
export { default as IconCamera } from './IconCamera.svelte';
|
|
5
5
|
export { default as IconClose } from './IconClose.svelte';
|
|
6
6
|
export { default as IconEdit } from './IconEdit.svelte';
|
|
7
|
+
export { default as IconEye } from './IconEye.svelte';
|
|
7
8
|
export { default as IconFilter } from './IconFilter.svelte';
|
|
8
9
|
export { default as IconSearch } from './IconSearch.svelte';
|
|
9
10
|
export { default as IconSort } from './IconSort.svelte';
|
|
@@ -9,3 +9,4 @@ export declare const iconFilterSvg = "<svg width=\"16\" height=\"16\" viewBox=\"
|
|
|
9
9
|
export declare const iconCameraSvg = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex-shrink:0\" aria-hidden=\"true\"><path d=\"M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z\"/><circle cx=\"12\" cy=\"13\" r=\"3\"/></svg>";
|
|
10
10
|
export declare const iconSortAscSvg = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\" style=\"flex-shrink:0\" aria-hidden=\"true\"><path d=\"M7 14l5-5 5 5H7z\"/></svg>";
|
|
11
11
|
export declare const iconSortDescSvg = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\" style=\"flex-shrink:0\" aria-hidden=\"true\"><path d=\"M7 10l5 5 5-5H7z\"/></svg>";
|
|
12
|
+
export declare const iconEyeSvg = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"flex-shrink:0\" aria-hidden=\"true\"><path d=\"M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></svg>";
|
|
@@ -13,3 +13,4 @@ export const iconFilterSvg = `<svg ${F}><path d="M3 5a1 1 0 0 1 1-1h16a1 1 0 0 1
|
|
|
13
13
|
export const iconCameraSvg = `<svg ${S}><path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"/><circle cx="12" cy="13" r="3"/></svg>`;
|
|
14
14
|
export const iconSortAscSvg = `<svg ${F}><path d="M7 14l5-5 5 5H7z"/></svg>`;
|
|
15
15
|
export const iconSortDescSvg = `<svg ${F}><path d="M7 10l5 5 5-5H7z"/></svg>`;
|
|
16
|
+
export const iconEyeSvg = `<svg ${S}><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>`;
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Svelix Components Quick Reference
|
|
2
|
+
|
|
3
|
+
This reference lists every Svelte component exported from the package root. Import components
|
|
4
|
+
from `@warkypublic/svelix`; adapters, stores, utility functions, and types are documented in
|
|
5
|
+
[ARCHITECTURE.md](./ARCHITECTURE.md) and [COMPONENT_GUIDE.md](./COMPONENT_GUIDE.md).
|
|
6
|
+
|
|
7
|
+
## Import Pattern
|
|
8
|
+
|
|
9
|
+
```svelte
|
|
10
|
+
<script lang="ts">
|
|
11
|
+
import {
|
|
12
|
+
Button,
|
|
13
|
+
CheckBoxCtrl,
|
|
14
|
+
FileInputCtrl,
|
|
15
|
+
Former,
|
|
16
|
+
JsonCtrl,
|
|
17
|
+
TextInputCtrl,
|
|
18
|
+
VTree
|
|
19
|
+
} from '@warkypublic/svelix';
|
|
20
|
+
</script>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Form Controllers
|
|
24
|
+
|
|
25
|
+
Most field controllers accept `label`, `name`, `disabled`, `error`, `required`, `sid`, and
|
|
26
|
+
`tooltip`. Use `bind:value` or `bind:checked` when the component supports it. Use `onchange`
|
|
27
|
+
when form state needs to be updated manually.
|
|
28
|
+
|
|
29
|
+
| Component | Use |
|
|
30
|
+
|---|---|
|
|
31
|
+
| `TextInputCtrl` | Single-line text input; set `type` for email, URL, and other native input types. |
|
|
32
|
+
| `TextAreaCtrl` | Multi-line text input; set `rows` as needed. |
|
|
33
|
+
| `PasswordInputCtrl` | Password input with a visibility toggle. |
|
|
34
|
+
| `NumberInputCtrl` | Numeric input with `min`, `max`, and `step`. |
|
|
35
|
+
| `NativeSelectCtrl` | Native select; `options` accepts strings or `{ label, value }` objects. |
|
|
36
|
+
| `DateTimeCtrl` | Date, time, or datetime picker; configure `mode`, constraints, and formats. |
|
|
37
|
+
| `CheckBoxCtrl` | Checkbox or switch with boolean, integer, or string serialization. |
|
|
38
|
+
| `SwitchCtrl` | Basic boolean checkbox-style toggle. |
|
|
39
|
+
| `FileInputCtrl` | Single-file picker with file-type/image preview, name, and size. |
|
|
40
|
+
| `JsonCtrl` | JSON value preview with a dialog editor. |
|
|
41
|
+
| `ButtonCtrl` | Form action button. |
|
|
42
|
+
| `IconButtonCtrl` | Compact icon action button. |
|
|
43
|
+
| `CtrlFieldShell` | Label, required marker, tooltip, and error wrapper for custom controls. |
|
|
44
|
+
| `InlineWrapper` | Places a field with optional left and right content in an inline row. |
|
|
45
|
+
|
|
46
|
+
## CheckBoxCtrl
|
|
47
|
+
|
|
48
|
+
`CheckBoxCtrl` renders a checkbox by default. Set `type="switch"` for a switch presentation.
|
|
49
|
+
The bound `checked` value uses `dataFormat="boolean"` by default.
|
|
50
|
+
|
|
51
|
+
```svelte
|
|
52
|
+
<script lang="ts">
|
|
53
|
+
let enabled = $state(false);
|
|
54
|
+
let published = $state<0 | 1 | null>(null);
|
|
55
|
+
let verified = $state<string | null>(null);
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<CheckBoxCtrl bind:checked={enabled} label="Enable notifications" name="notifications" />
|
|
59
|
+
|
|
60
|
+
<CheckBoxCtrl
|
|
61
|
+
bind:checked={published}
|
|
62
|
+
dataFormat="integer"
|
|
63
|
+
label="Published"
|
|
64
|
+
name="published"
|
|
65
|
+
type="switch"
|
|
66
|
+
/>
|
|
67
|
+
|
|
68
|
+
<CheckBoxCtrl
|
|
69
|
+
bind:checked={verified}
|
|
70
|
+
dataFormat="string"
|
|
71
|
+
label="Verified"
|
|
72
|
+
name="verified"
|
|
73
|
+
/>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Formats:
|
|
77
|
+
|
|
78
|
+
- `boolean`: reads and writes `true` / `false`.
|
|
79
|
+
- `integer`: reads `1`, `0`, or `null`; writes `1` / `0` after user interaction.
|
|
80
|
+
- `string`: reads `1`, `true`, `yes`, `0`, `false`, `no`, or `null` case-insensitively; writes
|
|
81
|
+
`"true"` / `"false"` after user interaction.
|
|
82
|
+
|
|
83
|
+
## FileInputCtrl
|
|
84
|
+
|
|
85
|
+
`FileInputCtrl` manages one `File`. Its compact row shows an image thumbnail or file-type badge,
|
|
86
|
+
the filename and size, and a choose/replace button.
|
|
87
|
+
|
|
88
|
+
```svelte
|
|
89
|
+
<script lang="ts">
|
|
90
|
+
let attachment = $state<File | null>(null);
|
|
91
|
+
</script>
|
|
92
|
+
|
|
93
|
+
<FileInputCtrl
|
|
94
|
+
bind:value={attachment}
|
|
95
|
+
accept="image/*,application/pdf"
|
|
96
|
+
label="Attachment"
|
|
97
|
+
name="attachment"
|
|
98
|
+
required
|
|
99
|
+
/>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Use `onchange={(file) => { ... }}` when the selected file must be copied into external form
|
|
103
|
+
state. `value` is `File | null`.
|
|
104
|
+
|
|
105
|
+
## JsonCtrl
|
|
106
|
+
|
|
107
|
+
`JsonCtrl` displays a compact JSON preview and opens a dialog editor. Bind arbitrary JSON-safe
|
|
108
|
+
data through `value`.
|
|
109
|
+
|
|
110
|
+
```svelte
|
|
111
|
+
<script lang="ts">
|
|
112
|
+
let metadata = $state<unknown>({ status: 'draft' });
|
|
113
|
+
</script>
|
|
114
|
+
|
|
115
|
+
<JsonCtrl bind:value={metadata} label="Metadata" name="metadata" />
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Use `onchange={(value) => { ... }}` when updating parent form state manually.
|
|
119
|
+
|
|
120
|
+
## Form Containers
|
|
121
|
+
|
|
122
|
+
| Component | Use |
|
|
123
|
+
|---|---|
|
|
124
|
+
| `Former` | Form state and CRUD lifecycle container. Supply fields through its `children` snippet. |
|
|
125
|
+
| `FormerModal` | `Former` rendered in a modal. |
|
|
126
|
+
| `FormerDrawer` | `Former` rendered in a side drawer. |
|
|
127
|
+
| `FormerButtonArea` | Standard save, delete, cancel, and keep-open action area. |
|
|
128
|
+
|
|
129
|
+
Use `bind:values`, `request`, `onAPICall`, and the `children(state)` snippet with `Former`.
|
|
130
|
+
For state helpers, use `createFormerState`; for data adapters, use `FormerResolveSpecAPI` or
|
|
131
|
+
`FormerRestHeadSpecAPI`.
|
|
132
|
+
|
|
133
|
+
## Content Editors And Viewers
|
|
134
|
+
|
|
135
|
+
`ContentEditor` selects a viewer/editor from `filename` and `contentType`. Use a subcomponent
|
|
136
|
+
directly only when the file type is already known.
|
|
137
|
+
|
|
138
|
+
| Component | Use |
|
|
139
|
+
|---|---|
|
|
140
|
+
| `ContentEditor` | Routes a file to the appropriate editor or viewer. |
|
|
141
|
+
| `TextEditor` | Plain text editing. |
|
|
142
|
+
| `MarkdownViewer` | Markdown display/editing with Carta. |
|
|
143
|
+
| `MonacoEditor` | Source-code editing with Monaco. |
|
|
144
|
+
| `CollaboraEditor` | Collabora office-document integration. |
|
|
145
|
+
| `Office365Editor` | Office 365 document integration. |
|
|
146
|
+
| `ImageViewer` | Image display. |
|
|
147
|
+
| `AudioPlayer` | Audio playback. |
|
|
148
|
+
| `VideoPlayer` | Video playback. |
|
|
149
|
+
| `PdfViewer` | PDF display. |
|
|
150
|
+
| `EmailViewer` | Email-file fallback viewer. |
|
|
151
|
+
| `ZipViewer` | Archive-file fallback viewer. |
|
|
152
|
+
| `UnknownFile` | Metadata and binary-header fallback viewer. |
|
|
153
|
+
|
|
154
|
+
## Data And Selection Components
|
|
155
|
+
|
|
156
|
+
| Component | Use |
|
|
157
|
+
|---|---|
|
|
158
|
+
| `Gridler` | Canvas-backed grid for large data sets, selection, editing, sorting, and filtering. |
|
|
159
|
+
| `GridlerFull` | Full grid workflow with paging, searching, menus, and Former integration. |
|
|
160
|
+
| `SvarkGrid` | SVAR grid alternative with column mapping and context menus. |
|
|
161
|
+
| `CardGrid` | Filterable and sortable card collection. |
|
|
162
|
+
| `DefaultCard` | Default card renderer for `CardGrid`. |
|
|
163
|
+
| `CardGridFilterPanel` | Filter controls for `CardGrid`. |
|
|
164
|
+
| `Boxer` | Lookup/select field backed by client or server data. |
|
|
165
|
+
| `BoxerTarget` | Renders a selected Boxer value target. |
|
|
166
|
+
| `VTree` | Virtualized hierarchical tree. |
|
|
167
|
+
|
|
168
|
+
Use the corresponding `*ResolveSpecAdapter` or `*RestHeaderSpecAdapter` only when connecting
|
|
169
|
+
`Gridler`, `SvarkGrid`, or `Boxer` to a supported data source.
|
|
170
|
+
|
|
171
|
+
## Layout, Feedback, And Utilities
|
|
172
|
+
|
|
173
|
+
| Component | Use |
|
|
174
|
+
|---|---|
|
|
175
|
+
| `Button` | General-purpose base button. |
|
|
176
|
+
| `Portal` | Renders children outside the current DOM subtree. |
|
|
177
|
+
| `ErrorBoundary` | Displays a fallback when child rendering fails. |
|
|
178
|
+
| `BetterMenu` | Enhanced menu/dropdown control. |
|
|
179
|
+
| `MenuRenderer` | Renders BetterMenu items when composing a custom menu. |
|
|
180
|
+
| `GlobalStateStoreProvider` | Provides the global state store to descendants. |
|
|
181
|
+
| `CaptureScreenshotComponent` | UI component for screenshot capture. |
|
|
182
|
+
|
|
183
|
+
Use `createBetterMenuStore`, `useGlobalStateStoreContext`, `CaptureScreen`, and `overlayStack`
|
|
184
|
+
for their related non-component APIs.
|
|
185
|
+
|
|
186
|
+
## Icons
|
|
187
|
+
|
|
188
|
+
The package exports `IconAdd`, `IconAlertCircle`, `IconAlertTriangle`, `IconCamera`, `IconClose`,
|
|
189
|
+
`IconEdit`, `IconEye`, `IconFilter`, `IconSearch`, `IconSort`, and `IconTrash`. Each is a Svelte
|
|
190
|
+
component that accepts `size` and `class` props.
|
package/llm/README.md
CHANGED
|
@@ -7,6 +7,7 @@ This folder contains AI-readable documentation that ships with the package.
|
|
|
7
7
|
- [ARCHITECTURE.md](./ARCHITECTURE.md)
|
|
8
8
|
- [SETUP.md](./SETUP.md)
|
|
9
9
|
- [COMPONENT_GUIDE.md](./COMPONENT_GUIDE.md)
|
|
10
|
+
- [FORMER_CONTROLLERS.md](./FORMER_CONTROLLERS.md) - quick reference for public components and controls
|
|
10
11
|
- [IMPLEMENTATION_PLAN.md](./IMPLEMENTATION_PLAN.md)
|
|
11
12
|
- [ROADMAP.md](./ROADMAP.md)
|
|
12
13
|
- [ESLINT_GUIDE.md](./ESLINT_GUIDE.md)
|
|
@@ -118,5 +119,7 @@ When `@warkypublic/svelix` is installed, this documentation is available at:
|
|
|
118
119
|
- `node_modules/@warkypublic/svelix/llm/README.md`
|
|
119
120
|
- `node_modules/@warkypublic/svelix/llm/ARCHITECTURE.md`
|
|
120
121
|
- `node_modules/@warkypublic/svelix/llm/SETUP.md`
|
|
122
|
+
- `node_modules/@warkypublic/svelix/llm/FORMER_CONTROLLERS.md`
|
|
121
123
|
|
|
122
|
-
Package subpath access is
|
|
124
|
+
Package subpath access is exported for `@warkypublic/svelix/llm/*`, including the direct
|
|
125
|
+
`@warkypublic/svelix/llm/components` and `@warkypublic/svelix/llm/former-controllers` references.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@warkypublic/svelix",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Svelte 5 component library with Skeleton UI and Tailwind CSS",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"exports": {
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
"svelte": "./dist/index.js"
|
|
10
10
|
},
|
|
11
11
|
"./llm": "./llm/README.md",
|
|
12
|
+
"./llm/components": "./llm/FORMER_CONTROLLERS.md",
|
|
13
|
+
"./llm/former-controllers": "./llm/FORMER_CONTROLLERS.md",
|
|
12
14
|
"./llm/*": "./llm/*",
|
|
13
15
|
"./css/tailwind-source.css": "./dist/css/tailwind-source.css",
|
|
14
16
|
"./css/*.css": "./dist/css/*.css",
|