fuma 2.1.0 → 2.1.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/dist/_doc/DocExample.svelte +122 -0
- package/dist/_doc/DocExample.svelte.d.ts +10 -0
- package/dist/_doc/DocProps.svelte +61 -0
- package/dist/_doc/DocProps.svelte.d.ts +13 -0
- package/dist/_doc/DocSection.svelte +22 -0
- package/dist/_doc/DocSection.svelte.d.ts +9 -0
- package/dist/_doc/highlight.d.ts +2 -0
- package/dist/_doc/highlight.js +18 -0
- package/dist/_doc/index.d.ts +4 -0
- package/dist/_doc/index.js +3 -0
- package/dist/_doc/parse-props.d.ts +2 -0
- package/dist/_doc/parse-props.js +253 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/input/InputBoolean.svelte +3 -6
- package/dist/input/InputRadio.svelte +1 -1
- package/dist/input/InputSelectNative.svelte +1 -1
- package/dist/input/InputTextarea.svelte +1 -2
- package/dist/input/Issues.svelte +3 -4
- package/dist/input/Issues.svelte.d.ts +2 -2
- package/dist/popover/popover.svelte.js +0 -8
- package/dist/remote/index.d.ts +1 -0
- package/dist/remote/index.js +1 -0
- package/dist/remote/useForm.js +4 -1
- package/dist/search/Spans.svelte +2 -1
- package/dist/state/param.svelte.d.ts +6 -7
- package/dist/state/param.svelte.js +16 -18
- package/dist/ui/drawer/drawerFly.js +1 -1
- package/dist/ui/menu/DropDownMenu.svelte +3 -17
- package/dist/ui/menu/DropDownMenu.svelte.d.ts +0 -3
- package/dist/ui/range/RangePicker.svelte +1 -2
- package/dist/ui/table/Table.svelte +3 -6
- package/dist/ui/table/Table.svelte.d.ts +2 -3
- package/dist/ui/table/TableFieldsEdition.svelte +3 -2
- package/dist/ui/table/TableViewSelect.svelte +5 -13
- package/dist/ui/table/TableViewSelect.svelte.d.ts +0 -5
- package/dist/ui/table/cell/TableCellArray.svelte +1 -1
- package/dist/ui/table/field.d.ts +7 -7
- package/dist/ui/table/head/TableHeadDate.svelte +1 -5
- package/dist/ui/table/head/TableHeadNumber.svelte +0 -1
- package/dist/ui/table/head/TableHeadSelect.svelte +2 -2
- package/dist/validation/zod.js +2 -1
- package/package.json +16 -33
- package/dist/ui/table/type.d.ts +0 -2
- package/dist/ui/table/type.js +0 -1
- /package/dist/{data.d.ts → _doc/data.d.ts} +0 -0
- /package/dist/{data.js → _doc/data.js} +0 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { type Snippet } from 'svelte'
|
|
3
|
+
import { ButtonCopy } from '../ui/copy/index.js'
|
|
4
|
+
import { useMode } from '../ui/mode/useMode.svelte.js'
|
|
5
|
+
import { highlight, transformPackageImports } from './highlight.ts'
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
code,
|
|
9
|
+
title,
|
|
10
|
+
lang = 'svelte',
|
|
11
|
+
preview
|
|
12
|
+
}: {
|
|
13
|
+
code: string
|
|
14
|
+
title?: string
|
|
15
|
+
lang?: string
|
|
16
|
+
preview: Snippet
|
|
17
|
+
} = $props()
|
|
18
|
+
|
|
19
|
+
let mode = $derived(useMode({ light: 'fuma', dark: 'fuma-dark' }))
|
|
20
|
+
let displayCode = $derived(transformPackageImports(code.trim()))
|
|
21
|
+
let highlighted = $derived(highlight(displayCode, lang, mode.current))
|
|
22
|
+
let tab = $state<'preview' | 'code'>('code')
|
|
23
|
+
|
|
24
|
+
let leftWidth = $state(50)
|
|
25
|
+
let isDragging = $state(false)
|
|
26
|
+
let container = $state<HTMLDivElement>()
|
|
27
|
+
|
|
28
|
+
function setTab(t: 'preview' | 'code') {
|
|
29
|
+
tab = t
|
|
30
|
+
if (t === 'code') {
|
|
31
|
+
leftWidth = 70
|
|
32
|
+
} else {
|
|
33
|
+
leftWidth = 30
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function startResize(e: MouseEvent) {
|
|
38
|
+
e.preventDefault()
|
|
39
|
+
isDragging = true
|
|
40
|
+
window.addEventListener('mousemove', onResize)
|
|
41
|
+
window.addEventListener('mouseup', stopResize)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function onResize(e: MouseEvent) {
|
|
45
|
+
if (!isDragging || !container) return
|
|
46
|
+
const rect = container.getBoundingClientRect()
|
|
47
|
+
const x = e.clientX - rect.left
|
|
48
|
+
const percent = (x / rect.width) * 100
|
|
49
|
+
leftWidth = Math.max(20, Math.min(80, percent))
|
|
50
|
+
tab = leftWidth >= 50 ? 'code' : 'preview'
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function stopResize() {
|
|
54
|
+
isDragging = false
|
|
55
|
+
window.removeEventListener('mousemove', onResize)
|
|
56
|
+
window.removeEventListener('mouseup', stopResize)
|
|
57
|
+
}
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
<div class="not-prose my-6 overflow-hidden rounded-lg border">
|
|
61
|
+
<div class="flex items-center gap-2 border-b bg-base-200/50 px-4 py-2">
|
|
62
|
+
<span class="mr-auto text-sm font-semibold text-base-content/70">Example: {title}</span>
|
|
63
|
+
|
|
64
|
+
<div class="tabs-boxed tabs tabs-sm">
|
|
65
|
+
<button class="tab" class:tab-active={tab === 'code'} onclick={() => setTab('code')}>
|
|
66
|
+
Code
|
|
67
|
+
</button>
|
|
68
|
+
<button class="tab" class:tab-active={tab === 'preview'} onclick={() => setTab('preview')}>
|
|
69
|
+
Preview
|
|
70
|
+
</button>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<ButtonCopy value={displayCode} title="Copy code" class="btn btn-square btn-xs" />
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<!-- Mobile: tabs -->
|
|
77
|
+
<div class="md:hidden">
|
|
78
|
+
{#if tab === 'code'}
|
|
79
|
+
<div class="overflow-hidden">
|
|
80
|
+
{#await highlighted then html}
|
|
81
|
+
<div class="overflow-auto text-sm">
|
|
82
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
83
|
+
{@html html}
|
|
84
|
+
</div>
|
|
85
|
+
{/await}
|
|
86
|
+
</div>
|
|
87
|
+
{:else}
|
|
88
|
+
<div class="bg-base-100 p-6">
|
|
89
|
+
{@render preview()}
|
|
90
|
+
</div>
|
|
91
|
+
{/if}
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<!-- Desktop: side by side with resizer -->
|
|
95
|
+
<div class="hidden md:flex" bind:this={container}>
|
|
96
|
+
<div
|
|
97
|
+
class="overflow-hidden {isDragging ? '' : 'transition-[width] duration-300 ease-out'}"
|
|
98
|
+
style="width: {leftWidth}%"
|
|
99
|
+
>
|
|
100
|
+
{#await highlighted then html}
|
|
101
|
+
<div class="overflow-auto text-sm">
|
|
102
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
103
|
+
{@html html}
|
|
104
|
+
</div>
|
|
105
|
+
{/await}
|
|
106
|
+
</div>
|
|
107
|
+
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
|
108
|
+
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
109
|
+
<div
|
|
110
|
+
class="w-1.5 shrink-0 cursor-col-resize bg-base-300 transition-colors hover:bg-primary {isDragging
|
|
111
|
+
? 'bg-primary'
|
|
112
|
+
: ''}"
|
|
113
|
+
onmousedown={startResize}
|
|
114
|
+
role="separator"
|
|
115
|
+
aria-label="Resize"
|
|
116
|
+
tabindex="0"
|
|
117
|
+
></div>
|
|
118
|
+
<div class="min-w-0 flex-1 overflow-auto bg-base-100 p-6">
|
|
119
|
+
{@render preview()}
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type Snippet } from 'svelte';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
code: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
lang?: string;
|
|
6
|
+
preview: Snippet;
|
|
7
|
+
};
|
|
8
|
+
declare const DocExample: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
9
|
+
type DocExample = ReturnType<typeof DocExample>;
|
|
10
|
+
export default DocExample;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
export type PropDef = {
|
|
3
|
+
name: string
|
|
4
|
+
type: string
|
|
5
|
+
default?: string
|
|
6
|
+
required?: boolean
|
|
7
|
+
description?: string
|
|
8
|
+
}
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<script lang="ts">
|
|
12
|
+
let {
|
|
13
|
+
props
|
|
14
|
+
}: {
|
|
15
|
+
props: PropDef[]
|
|
16
|
+
} = $props()
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<div class="not-prose my-6">
|
|
20
|
+
<div class="collapse-arrow collapse rounded-lg border bg-base-100">
|
|
21
|
+
<input type="checkbox" />
|
|
22
|
+
<div class="collapse-title text-sm font-semibold">{props.length} Props</div>
|
|
23
|
+
<div class="collapse-content p-0">
|
|
24
|
+
<div class="overflow-x-auto">
|
|
25
|
+
<table class="table table-zebra table-sm">
|
|
26
|
+
<thead class="bg-base-200/80 text-sm">
|
|
27
|
+
<tr>
|
|
28
|
+
<th>Name</th>
|
|
29
|
+
<th>Type</th>
|
|
30
|
+
<th>Default</th>
|
|
31
|
+
<th>Description</th>
|
|
32
|
+
</tr>
|
|
33
|
+
</thead>
|
|
34
|
+
<tbody>
|
|
35
|
+
{#each props as prop (prop.name)}
|
|
36
|
+
<tr>
|
|
37
|
+
<td class="whitespace-nowrap">
|
|
38
|
+
<code class="font-mono text-sm">{prop.name}</code>
|
|
39
|
+
{#if prop.required}
|
|
40
|
+
<span class="ml-1 badge badge-xs badge-error">required</span>
|
|
41
|
+
{/if}
|
|
42
|
+
</td>
|
|
43
|
+
<td>
|
|
44
|
+
<code class="font-mono text-xs opacity-70">{prop.type}</code>
|
|
45
|
+
</td>
|
|
46
|
+
<td class="text-sm opacity-80">
|
|
47
|
+
{#if prop.default}
|
|
48
|
+
<code class="font-mono text-xs">{prop.default}</code>
|
|
49
|
+
{:else}
|
|
50
|
+
<span class="opacity-50">—</span>
|
|
51
|
+
{/if}
|
|
52
|
+
</td>
|
|
53
|
+
<td class="text-sm">{prop.description ?? ''}</td>
|
|
54
|
+
</tr>
|
|
55
|
+
{/each}
|
|
56
|
+
</tbody>
|
|
57
|
+
</table>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type PropDef = {
|
|
2
|
+
name: string;
|
|
3
|
+
type: string;
|
|
4
|
+
default?: string;
|
|
5
|
+
required?: boolean;
|
|
6
|
+
description?: string;
|
|
7
|
+
};
|
|
8
|
+
type $$ComponentProps = {
|
|
9
|
+
props: PropDef[];
|
|
10
|
+
};
|
|
11
|
+
declare const DocProps: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
12
|
+
type DocProps = ReturnType<typeof DocProps>;
|
|
13
|
+
export default DocProps;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { type Snippet } from 'svelte'
|
|
3
|
+
|
|
4
|
+
let {
|
|
5
|
+
title,
|
|
6
|
+
description,
|
|
7
|
+
children
|
|
8
|
+
}: {
|
|
9
|
+
title?: string
|
|
10
|
+
description?: string
|
|
11
|
+
children: Snippet
|
|
12
|
+
} = $props()
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<section class="mt-2 mb-12">
|
|
16
|
+
<h2 class="mb-2 text-2xl font-bold text-base-content">{title}</h2>
|
|
17
|
+
{#if description}
|
|
18
|
+
<p class="mb-4 text-base-content/70">{description}</p>
|
|
19
|
+
{/if}
|
|
20
|
+
<div class="divider mb-6"></div>
|
|
21
|
+
{@render children()}
|
|
22
|
+
</section>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Snippet } from 'svelte';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
title?: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
children: Snippet;
|
|
6
|
+
};
|
|
7
|
+
declare const DocSection: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
|
+
type DocSection = ReturnType<typeof DocSection>;
|
|
9
|
+
export default DocSection;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { codeToHtml } from 'shiki';
|
|
2
|
+
export function transformPackageImports(code) {
|
|
3
|
+
return code
|
|
4
|
+
.replace(/from\s+['"]\$lib\/index\.ts['"]/g, "from 'fuma'")
|
|
5
|
+
.replace(/from\s+['"]\$lib\/ui\/[^'"]+['"]/g, "from 'fuma/ui'")
|
|
6
|
+
.replace(/from\s+['"]\$lib\/utils\/[^'"]+['"]/g, "from 'fuma/utils'")
|
|
7
|
+
.replace(/from\s+['"]\$lib\/state\/[^'"]+['"]/g, "from 'fuma/state'")
|
|
8
|
+
.replace(/from\s+['"]\$lib\/validation\/[^'"]+['"]/g, "from 'fuma/validation'")
|
|
9
|
+
.replace(/from\s+['"]\$lib\/action\/[^'"]+['"]/g, "from 'fuma/action'")
|
|
10
|
+
.replace(/from\s+['"]\$lib\/server\/[^'"]+['"]/g, "from 'fuma/server'");
|
|
11
|
+
}
|
|
12
|
+
export async function highlight(code, lang = 'svelte', theme = 'dark') {
|
|
13
|
+
return codeToHtml(code, {
|
|
14
|
+
lang,
|
|
15
|
+
theme: theme === 'dark' ? 'github-dark' : 'github-light',
|
|
16
|
+
rootStyle: 'padding: 0.5rem 1rem;'
|
|
17
|
+
});
|
|
18
|
+
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
export function parseProps(source) {
|
|
2
|
+
const script = extractScript(source);
|
|
3
|
+
if (!script)
|
|
4
|
+
return [];
|
|
5
|
+
// Try Svelte 5 $props() first
|
|
6
|
+
const declaration = findPropsDeclaration(script);
|
|
7
|
+
if (declaration) {
|
|
8
|
+
const destructured = parseDestructuring(declaration.destructuring);
|
|
9
|
+
const typed = parseType(declaration.type);
|
|
10
|
+
return mergeToPropDefs(destructured, typed);
|
|
11
|
+
}
|
|
12
|
+
// Fallback to Svelte 3/4 export let syntax
|
|
13
|
+
return parseExportLetProps(script);
|
|
14
|
+
}
|
|
15
|
+
function extractScript(source) {
|
|
16
|
+
const moduleMatch = source.match(/<script\s+lang="ts"\s+module>[\s\S]*?<\/script>/);
|
|
17
|
+
let cleaned = source;
|
|
18
|
+
if (moduleMatch && moduleMatch.index !== undefined) {
|
|
19
|
+
cleaned =
|
|
20
|
+
source.slice(0, moduleMatch.index) + source.slice(moduleMatch.index + moduleMatch[0].length);
|
|
21
|
+
}
|
|
22
|
+
const scriptMatch = cleaned.match(/<script\s+lang="ts"\s*(?:generics="[^"]*")?\s*>([\s\S]*?)<\/script>/);
|
|
23
|
+
if (scriptMatch)
|
|
24
|
+
return scriptMatch[1];
|
|
25
|
+
// Fallback for plain .ts files (no <script> tag)
|
|
26
|
+
if (!cleaned.includes('<script'))
|
|
27
|
+
return cleaned;
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
function findPropsDeclaration(script) {
|
|
31
|
+
const letIndex = script.indexOf('let {');
|
|
32
|
+
if (letIndex === -1)
|
|
33
|
+
return null;
|
|
34
|
+
let i = letIndex + 4;
|
|
35
|
+
let braceDepth = 0;
|
|
36
|
+
let destructuringEnd = -1;
|
|
37
|
+
for (; i < script.length; i++) {
|
|
38
|
+
if (script[i] === '{')
|
|
39
|
+
braceDepth++;
|
|
40
|
+
else if (script[i] === '}') {
|
|
41
|
+
braceDepth--;
|
|
42
|
+
if (braceDepth === 0) {
|
|
43
|
+
destructuringEnd = i;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (destructuringEnd === -1)
|
|
49
|
+
return null;
|
|
50
|
+
const destructuring = script.slice(letIndex + 5, destructuringEnd);
|
|
51
|
+
let j = destructuringEnd + 1;
|
|
52
|
+
while (j < script.length && /\s/.test(script[j]))
|
|
53
|
+
j++;
|
|
54
|
+
let type = null;
|
|
55
|
+
if (script[j] === ':') {
|
|
56
|
+
j++;
|
|
57
|
+
while (j < script.length && /\s/.test(script[j]))
|
|
58
|
+
j++;
|
|
59
|
+
const propsIndex = script.indexOf('= $props()', j);
|
|
60
|
+
if (propsIndex !== -1) {
|
|
61
|
+
type = script.slice(j, propsIndex).trim();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return { destructuring, type };
|
|
65
|
+
}
|
|
66
|
+
function parseDestructuring(str) {
|
|
67
|
+
const props = new Map();
|
|
68
|
+
const items = splitByComma(str);
|
|
69
|
+
for (const item of items) {
|
|
70
|
+
if (item.startsWith('...'))
|
|
71
|
+
continue;
|
|
72
|
+
const eqIndex = findTopLevel(item, ' = ');
|
|
73
|
+
const beforeEq = eqIndex >= 0 ? item.slice(0, eqIndex).trim() : item.trim();
|
|
74
|
+
const defaultValue = eqIndex >= 0 ? item.slice(eqIndex + 3).trim() : undefined;
|
|
75
|
+
const colonIndex = findTopLevel(beforeEq, ': ');
|
|
76
|
+
const name = colonIndex >= 0 ? beforeEq.slice(0, colonIndex).trim() : beforeEq;
|
|
77
|
+
props.set(name, { alias: name, defaultValue });
|
|
78
|
+
}
|
|
79
|
+
return props;
|
|
80
|
+
}
|
|
81
|
+
function parseType(typeStr) {
|
|
82
|
+
const props = new Map();
|
|
83
|
+
if (!typeStr)
|
|
84
|
+
return props;
|
|
85
|
+
const cleaned = removeComments(typeStr);
|
|
86
|
+
const firstBrace = cleaned.indexOf('{');
|
|
87
|
+
if (firstBrace === -1)
|
|
88
|
+
return props;
|
|
89
|
+
let depth = 0;
|
|
90
|
+
let start = -1;
|
|
91
|
+
let end = -1;
|
|
92
|
+
for (let i = 0; i < cleaned.length; i++) {
|
|
93
|
+
if (cleaned[i] === '{') {
|
|
94
|
+
if (depth === 0)
|
|
95
|
+
start = i;
|
|
96
|
+
depth++;
|
|
97
|
+
}
|
|
98
|
+
else if (cleaned[i] === '}') {
|
|
99
|
+
depth--;
|
|
100
|
+
if (depth === 0) {
|
|
101
|
+
end = i;
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (start === -1 || end === -1)
|
|
107
|
+
return props;
|
|
108
|
+
const content = cleaned.slice(start + 1, end);
|
|
109
|
+
return parseTypeObject(content);
|
|
110
|
+
}
|
|
111
|
+
function parseTypeObject(content) {
|
|
112
|
+
const props = new Map();
|
|
113
|
+
const lines = content.split('\n');
|
|
114
|
+
const propStartRegex = /^([a-zA-Z_$][a-zA-Z0-9_$]*)(\??)\s*:\s*(.*)$/;
|
|
115
|
+
let currentName = null;
|
|
116
|
+
let currentOptional = false;
|
|
117
|
+
let currentType = '';
|
|
118
|
+
let currentDescription = '';
|
|
119
|
+
let depth = 0;
|
|
120
|
+
let pendingDescription = '';
|
|
121
|
+
for (let line of lines) {
|
|
122
|
+
line = line.trim();
|
|
123
|
+
if (!line)
|
|
124
|
+
continue;
|
|
125
|
+
const jsdocMatch = line.match(/\/\*\*\s*(.*?)\s*\*\//);
|
|
126
|
+
if (jsdocMatch) {
|
|
127
|
+
pendingDescription = jsdocMatch[1].trim();
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
const commentMatch = line.match(/\/\/\s*(.*)/);
|
|
131
|
+
if (commentMatch) {
|
|
132
|
+
pendingDescription = commentMatch[1].trim();
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
for (const char of line) {
|
|
136
|
+
if (char === '{' || char === '(' || char === '[')
|
|
137
|
+
depth++;
|
|
138
|
+
else if (char === '}' || char === ')' || char === ']')
|
|
139
|
+
depth--;
|
|
140
|
+
}
|
|
141
|
+
const match = line.match(propStartRegex);
|
|
142
|
+
if (match && depth === 0) {
|
|
143
|
+
if (currentName) {
|
|
144
|
+
props.set(currentName, {
|
|
145
|
+
type: currentType.trim(),
|
|
146
|
+
required: !currentOptional,
|
|
147
|
+
description: currentDescription || undefined
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
currentName = match[1];
|
|
151
|
+
currentOptional = match[2] === '?';
|
|
152
|
+
currentType = match[3];
|
|
153
|
+
currentDescription = pendingDescription;
|
|
154
|
+
pendingDescription = '';
|
|
155
|
+
}
|
|
156
|
+
else if (currentName && depth >= 0) {
|
|
157
|
+
currentType += ` ${line}`;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (currentName) {
|
|
161
|
+
props.set(currentName, {
|
|
162
|
+
type: currentType.trim(),
|
|
163
|
+
required: !currentOptional,
|
|
164
|
+
description: currentDescription || undefined
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
return props;
|
|
168
|
+
}
|
|
169
|
+
function parseExportLetProps(script) {
|
|
170
|
+
const defs = [];
|
|
171
|
+
const regex = /export\s+let\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*(?::\s*([^=\n]+))?\s*(?:=\s*([^\n]+))?/g;
|
|
172
|
+
let match = null;
|
|
173
|
+
while (true) {
|
|
174
|
+
match = regex.exec(script);
|
|
175
|
+
if (match === null)
|
|
176
|
+
break;
|
|
177
|
+
const [, name, typeStr, defaultValue] = match;
|
|
178
|
+
defs.push({
|
|
179
|
+
name,
|
|
180
|
+
type: typeStr ? typeStr.trim() : 'unknown',
|
|
181
|
+
default: defaultValue ? defaultValue.trim() : undefined,
|
|
182
|
+
required: !defaultValue
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
return defs;
|
|
186
|
+
}
|
|
187
|
+
function mergeToPropDefs(destructured, typed) {
|
|
188
|
+
const defs = [];
|
|
189
|
+
for (const [name, { defaultValue }] of destructured) {
|
|
190
|
+
const typeInfo = typed.get(name);
|
|
191
|
+
let isRequired = typeInfo?.required ?? false;
|
|
192
|
+
let type = typeInfo?.type ?? 'unknown';
|
|
193
|
+
// Clean up union types starting with |
|
|
194
|
+
if (type.startsWith('| ')) {
|
|
195
|
+
type = type.slice(2).trim();
|
|
196
|
+
}
|
|
197
|
+
if (defaultValue) {
|
|
198
|
+
if (defaultValue.startsWith('$bindable')) {
|
|
199
|
+
// $bindable() means it's bindable but may still be required
|
|
200
|
+
// keep required as-is from type
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
isRequired = false;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
defs.push({
|
|
207
|
+
name,
|
|
208
|
+
type,
|
|
209
|
+
default: defaultValue && !defaultValue.startsWith('$bindable') ? defaultValue : undefined,
|
|
210
|
+
required: isRequired,
|
|
211
|
+
description: typeInfo?.description
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
return defs;
|
|
215
|
+
}
|
|
216
|
+
function splitByComma(str) {
|
|
217
|
+
const items = [];
|
|
218
|
+
let current = '';
|
|
219
|
+
let depth = 0;
|
|
220
|
+
for (const char of str) {
|
|
221
|
+
if (char === '{' || char === '(' || char === '[' || char === '<')
|
|
222
|
+
depth++;
|
|
223
|
+
else if (char === '}' || char === ')' || char === ']' || char === '>')
|
|
224
|
+
depth--;
|
|
225
|
+
else if (char === ',' && depth === 0) {
|
|
226
|
+
if (current.trim())
|
|
227
|
+
items.push(current.trim());
|
|
228
|
+
current = '';
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
current += char;
|
|
232
|
+
}
|
|
233
|
+
if (current.trim())
|
|
234
|
+
items.push(current.trim());
|
|
235
|
+
return items;
|
|
236
|
+
}
|
|
237
|
+
function findTopLevel(str, pattern) {
|
|
238
|
+
let depth = 0;
|
|
239
|
+
for (let i = 0; i <= str.length - pattern.length; i++) {
|
|
240
|
+
const char = str[i];
|
|
241
|
+
if (char === '{' || char === '(' || char === '[' || char === '<')
|
|
242
|
+
depth++;
|
|
243
|
+
else if (char === '}' || char === ')' || char === ']' || char === '>')
|
|
244
|
+
depth--;
|
|
245
|
+
else if (depth === 0 && str.slice(i, i + pattern.length) === pattern) {
|
|
246
|
+
return i;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return -1;
|
|
250
|
+
}
|
|
251
|
+
function removeComments(str) {
|
|
252
|
+
return str.replace(/\/\/.*$/gm, '');
|
|
253
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
export * from './action/index.ts';
|
|
2
|
+
export * from './command/index.ts';
|
|
3
|
+
export * from './input/index.ts';
|
|
4
|
+
export * from './popover/index.ts';
|
|
5
|
+
export * from './remote/index.ts';
|
|
6
|
+
export * from './search/index.ts';
|
|
2
7
|
export * from './state/index.ts';
|
|
3
8
|
export * from './ui/index.ts';
|
|
4
9
|
export * from './utils/index.ts';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
export * from './action/index.ts';
|
|
2
|
+
export * from './command/index.ts';
|
|
3
|
+
export * from './input/index.ts';
|
|
4
|
+
export * from './popover/index.ts';
|
|
5
|
+
export * from './remote/index.ts';
|
|
6
|
+
export * from './search/index.ts';
|
|
2
7
|
export * from './state/index.ts';
|
|
3
8
|
export * from './ui/index.ts';
|
|
4
9
|
export * from './utils/index.ts';
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
checked = $bindable(),
|
|
11
11
|
hint,
|
|
12
12
|
variant = 'checkbox',
|
|
13
|
-
class: klass,
|
|
14
13
|
...props
|
|
15
14
|
}: {
|
|
16
15
|
label: string
|
|
@@ -58,7 +57,8 @@
|
|
|
58
57
|
</div>
|
|
59
58
|
|
|
60
59
|
{#snippet variantCheckbox()}
|
|
61
|
-
|
|
60
|
+
<!-- https://developer.mozilla.org/en-US/docs/Web/CSS/corner-shape -->
|
|
61
|
+
<div class={['h-5 w-5 rounded-full outline', 'bg-base-100']} style="corner-shape: squircle;">
|
|
62
62
|
<div
|
|
63
63
|
class={[
|
|
64
64
|
'squircle grid h-5 w-5 place-content-center',
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
'ease scale-0 opacity-0',
|
|
67
67
|
isChecked && 'scale-[80%] opacity-100'
|
|
68
68
|
]}
|
|
69
|
+
style="corner-shape: squircle"
|
|
69
70
|
>
|
|
70
71
|
<CheckIcon size={18} class={['stroke-base-100']} strokeWidth={4} />
|
|
71
72
|
</div>
|
|
@@ -92,10 +93,6 @@
|
|
|
92
93
|
transition-timing-function: cubic-bezier(0.275, 0.485, 0.515, 1.45);
|
|
93
94
|
transition-duration: 200ms;
|
|
94
95
|
}
|
|
95
|
-
.squircle {
|
|
96
|
-
corner-shape: squircle;
|
|
97
|
-
border-radius: 100%;
|
|
98
|
-
}
|
|
99
96
|
|
|
100
97
|
label:has(input[aria-invalid='true']) {
|
|
101
98
|
--input-color: var(--color-error);
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
<div class="flex flex-col gap-1">
|
|
22
22
|
<span class="label px-3 text-sm">{label}</span>
|
|
23
23
|
<div class="join join-vertical">
|
|
24
|
-
{#each options as option}
|
|
24
|
+
{#each options as option (option.value)}
|
|
25
25
|
{@const { class: klass, ...props } = option}
|
|
26
26
|
<label class="input join-item not-disabled:cursor-pointer not-disabled:hover:bg-base-200">
|
|
27
27
|
{#if option.icon}
|
package/dist/input/Issues.svelte
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type { RemoteFormField } from '@sveltejs/kit'
|
|
2
|
+
import type { RemoteFormField, RemoteFormFieldValue } from '@sveltejs/kit'
|
|
3
3
|
import { slide } from 'svelte/transition'
|
|
4
4
|
|
|
5
5
|
let {
|
|
6
6
|
field
|
|
7
7
|
}: {
|
|
8
|
-
|
|
9
|
-
field: RemoteFormField<any> | undefined
|
|
8
|
+
field: RemoteFormField<RemoteFormFieldValue> | undefined
|
|
10
9
|
} = $props()
|
|
11
10
|
</script>
|
|
12
11
|
|
|
13
12
|
{#if field?.issues()?.length}
|
|
14
13
|
<div class="my-1 flex flex-col text-xs text-error" transition:slide={{ duration: 200 }}>
|
|
15
|
-
{#each field.issues() as issue}
|
|
14
|
+
{#each field.issues() as issue (issue.path)}
|
|
16
15
|
<span>
|
|
17
16
|
{issue.message}
|
|
18
17
|
</span>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { RemoteFormField } from '@sveltejs/kit';
|
|
1
|
+
import type { RemoteFormField, RemoteFormFieldValue } from '@sveltejs/kit';
|
|
2
2
|
type $$ComponentProps = {
|
|
3
|
-
field: RemoteFormField<
|
|
3
|
+
field: RemoteFormField<RemoteFormFieldValue> | undefined;
|
|
4
4
|
};
|
|
5
5
|
declare const Issues: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
6
6
|
type Issues = ReturnType<typeof Issues>;
|