@svadmin/lite 0.23.2 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { assertSchemaFormSchema, isSchemaFormNodeVisible, type SchemaFormSchema as JsonSchema } from '@svadmin/core/schema-form';
|
|
2
|
+
import { assertSchemaFormSchema, isSchemaFormNodeVisible, resolveSchemaFormLayout, type SchemaFormLayoutGroup, type SchemaFormSchema as JsonSchema } from '@svadmin/core/schema-form';
|
|
3
3
|
import { useTranslation } from '@svadmin/core/i18n';
|
|
4
4
|
import { encodeSchemaFormArrayAction, schemaFormActionName, schemaFormFieldName } from '../schema-form-data';
|
|
5
5
|
|
|
@@ -95,6 +95,21 @@
|
|
|
95
95
|
return schemaFormFieldName(path);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
function groupsFor(node: JsonSchema): readonly SchemaFormLayoutGroup[] {
|
|
99
|
+
if (resolved.invalid) return [];
|
|
100
|
+
try {
|
|
101
|
+
const plan = resolveSchemaFormLayout(node);
|
|
102
|
+
if (plan.groups.length > 0) return plan.groups;
|
|
103
|
+
} catch {
|
|
104
|
+
// 嵌套节点若超出封闭 schema,退回按字段顺序平铺。
|
|
105
|
+
}
|
|
106
|
+
return [{
|
|
107
|
+
key: '',
|
|
108
|
+
columns: 1,
|
|
109
|
+
fields: Object.keys(node.properties ?? {}).map((key) => ({ key, span: 1 })),
|
|
110
|
+
}];
|
|
111
|
+
}
|
|
112
|
+
|
|
98
113
|
function enumToken(index: number): string {
|
|
99
114
|
return `__json_enum_${index}`;
|
|
100
115
|
}
|
|
@@ -137,9 +152,7 @@
|
|
|
137
152
|
<fieldset class="lite-schema-fieldset">
|
|
138
153
|
<legend>{title}</legend>
|
|
139
154
|
{#if node.description}<p class="lite-schema-description">{node.description}</p>{/if}
|
|
140
|
-
{
|
|
141
|
-
{@render renderField(child, [...path, key], child.title ?? key, node.required?.includes(key) ?? false)}
|
|
142
|
-
{/each}
|
|
155
|
+
{@render renderGroups(node, path)}
|
|
143
156
|
</fieldset>
|
|
144
157
|
{:else if node.type === 'array'}
|
|
145
158
|
{@const items = Array.isArray(current) ? current : []}
|
|
@@ -194,9 +207,32 @@
|
|
|
194
207
|
{/if}
|
|
195
208
|
{/snippet}
|
|
196
209
|
|
|
197
|
-
{
|
|
198
|
-
|
|
210
|
+
{@render renderGroups(schema, [])}
|
|
211
|
+
|
|
212
|
+
{#snippet renderGroups(node: JsonSchema, path: string[])}
|
|
213
|
+
{#each groupsFor(node) as group (group.key)}
|
|
214
|
+
<div class="lite-schema-group" data-svadmin-form-group={group.key}>
|
|
215
|
+
{#if group.title}
|
|
216
|
+
<h3 class="lite-schema-group-title">{group.step !== undefined ? `${group.step}. ${group.title}` : group.title}</h3>
|
|
217
|
+
{#if group.description}<p class="lite-schema-description">{group.description}</p>{/if}
|
|
218
|
+
{/if}
|
|
219
|
+
<div class={group.columns > 1 ? 'lite-schema-row' : 'lite-schema-stack'}>
|
|
220
|
+
{#each group.fields as field (field.key)}
|
|
221
|
+
{@const child = node.properties?.[field.key]}
|
|
222
|
+
{#if child}
|
|
223
|
+
<div
|
|
224
|
+
class="lite-schema-col"
|
|
225
|
+
style:width={group.columns > 1 ? `${Math.min(100, (field.span / group.columns) * 100)}%` : undefined}
|
|
226
|
+
>
|
|
227
|
+
{@render renderField(child, [...path, field.key], child.title ?? field.key, node.required?.includes(field.key) ?? false)}
|
|
228
|
+
</div>
|
|
229
|
+
{/if}
|
|
230
|
+
{/each}
|
|
231
|
+
</div>
|
|
232
|
+
</div>
|
|
199
233
|
{/each}
|
|
234
|
+
{/snippet}
|
|
235
|
+
|
|
200
236
|
<div class="lite-schema-footer">
|
|
201
237
|
<button type="submit" disabled={resolved.invalid} class="lite-btn lite-btn-primary lite-btn-sm">{submitText}</button>
|
|
202
238
|
</div>
|
|
@@ -208,6 +244,12 @@
|
|
|
208
244
|
.lite-schema-form-header { padding-bottom: 8px; border-bottom: 1px solid #E5E6EB; margin-bottom: 12px; font-size: 14px; }
|
|
209
245
|
.lite-schema-fieldset { border: 1px solid #E5E6EB; border-radius: 4px; padding: 12px; margin: 0 0 12px; }
|
|
210
246
|
.lite-schema-field { margin-bottom: 12px; }
|
|
247
|
+
.lite-schema-group { margin-bottom: 12px; }
|
|
248
|
+
.lite-schema-group-title { margin: 0 0 8px; font-size: 12px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: #4E5969; }
|
|
249
|
+
/* IE11 基线:用 inline-block 栅格替代 CSS Grid/flex gap。 */
|
|
250
|
+
.lite-schema-row { font-size: 0; }
|
|
251
|
+
.lite-schema-col { display: inline-block; vertical-align: top; box-sizing: border-box; padding-right: 12px; font-size: 13px; }
|
|
252
|
+
.lite-schema-col:last-child { padding-right: 0; }
|
|
211
253
|
.lite-schema-fieldset > .lite-schema-field:last-child { margin-bottom: 0; }
|
|
212
254
|
.lite-schema-footer { display: flex; justify-content: flex-end; padding-top: 12px; border-top: 1px solid #E5E6EB; }
|
|
213
255
|
.lite-label { display: block; font-size: 12px; color: #4E5969; margin-bottom: 4px; }
|
package/dist/schema-form-data.js
CHANGED
|
@@ -141,9 +141,32 @@ function decodeFields(schema, form, validate) {
|
|
|
141
141
|
if (schema.type !== 'object' && !schema.properties)
|
|
142
142
|
return fail();
|
|
143
143
|
// 控制字段只允许无条件标量,因此可先解码,不依赖属性声明顺序。
|
|
144
|
+
// 组合器条件可能引用多个控制字段(含 equalsField),必须全部预解码。
|
|
145
|
+
function conditionPaths(condition, paths) {
|
|
146
|
+
if (!condition)
|
|
147
|
+
return;
|
|
148
|
+
if (condition.path)
|
|
149
|
+
paths.push([...condition.path]);
|
|
150
|
+
if (condition.equalsField)
|
|
151
|
+
paths.push([...condition.equalsField]);
|
|
152
|
+
for (const child of condition.all ?? [])
|
|
153
|
+
conditionPaths(child, paths);
|
|
154
|
+
for (const child of condition.any ?? [])
|
|
155
|
+
conditionPaths(child, paths);
|
|
156
|
+
conditionPaths(condition.not, paths);
|
|
157
|
+
}
|
|
144
158
|
function collectControllers(node) {
|
|
145
|
-
const
|
|
146
|
-
|
|
159
|
+
const paths = [];
|
|
160
|
+
conditionPaths(node.visibleWhen, paths);
|
|
161
|
+
for (const path of paths)
|
|
162
|
+
collectControllerPath(path);
|
|
163
|
+
for (const child of Object.values(node.properties ?? {}))
|
|
164
|
+
collectControllers(child);
|
|
165
|
+
if (node.items)
|
|
166
|
+
collectControllers(node.items);
|
|
167
|
+
}
|
|
168
|
+
function collectControllerPath(path) {
|
|
169
|
+
if (!controllerValues.has(JSON.stringify(path))) {
|
|
147
170
|
let definition = schema;
|
|
148
171
|
for (const key of path) {
|
|
149
172
|
const next = definition.properties?.[key];
|
|
@@ -167,10 +190,6 @@ function decodeFields(schema, form, validate) {
|
|
|
167
190
|
}
|
|
168
191
|
});
|
|
169
192
|
}
|
|
170
|
-
for (const child of Object.values(node.properties ?? {}))
|
|
171
|
-
collectControllers(child);
|
|
172
|
-
if (node.items)
|
|
173
|
-
collectControllers(node.items);
|
|
174
193
|
}
|
|
175
194
|
collectControllers(schema);
|
|
176
195
|
const result = visit(schema, [], 0);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@svadmin/lite",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "SSR-first lightweight admin UI for @svadmin with optional progressive enhancement",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
58
|
"svelte": "^5.57.1",
|
|
59
|
-
"@svadmin/core": ">=0.34.2 <0.
|
|
59
|
+
"@svadmin/core": ">=0.34.2 <0.75.0",
|
|
60
60
|
"@sveltejs/kit": "^3.0.0",
|
|
61
61
|
"qrcode": "^1.5.4"
|
|
62
62
|
},
|