@svadmin/lite 0.24.0 → 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
- {#each Object.entries(node.properties ?? {}) as [key, child] (key)}
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
- {#each Object.entries(resolved.invalid ? {} : schema.properties ?? {}) as [key, node] (key)}
198
- {@render renderField(node, [key], node.title ?? key, schema.required?.includes(key) ?? false)}
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@svadmin/lite",
3
- "version": "0.24.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.74.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
  },