@structured-field/widget-editor 1.3.0 → 1.4.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.
package/README.md CHANGED
@@ -182,6 +182,8 @@ The search endpoint should return:
182
182
 
183
183
  Query parameters sent: `_q` (search term), `page` (pagination).
184
184
 
185
+ For styling, the editor root exposes state classes: `sf-relation-multiple` when the field accepts multiple values, and `sf-relation-open` while the autocomplete dropdown is visible.
186
+
185
187
  ## Editors
186
188
 
187
189
  | Schema type | Editor | Description |
@@ -197,6 +199,55 @@ Query parameters sent: `_q` (search term), `page` (pagination).
197
199
  | `oneOf + discriminator` | UnionEditor | Type selector |
198
200
  | `relation` | RelationEditor | Autocomplete with search |
199
201
 
202
+ ## Multicolumn layout
203
+
204
+ Object fields flow into a responsive multicolumn layout: every field gets an intrinsic **size token** from its schema, and columns emerge naturally from the available width at each nesting level (no media queries — the layout adapts to the actual container, so it works in narrow admin inlines and nested fieldsets alike). Visual order always equals schema/DOM order.
205
+
206
+ | Token | flex-basis | Assigned to |
207
+ |---|---|---|
208
+ | `xs` | `8rem` | boolean, integer, number |
209
+ | `sm` | `12rem` | date, compact enums/choices (≤8 options, short labels), strings with `maxLength ≤ 40` |
210
+ | `md` | `18rem` | plain strings, date-time, single relations, wide enums |
211
+ | `lg` | `26rem` | multiple relations |
212
+ | `full` | 100% | objects, arrays, unions, JSON, textareas (`format: 'textarea'` or `maxLength > 255`), custom editors |
213
+
214
+ Nullable scalars are bumped one tier (`xs → sm`, `sm → md`) to make room for the inline null-clear button. `const` / discriminator fields render as hidden cells and leave no gap.
215
+
216
+ ### Per-field overrides
217
+
218
+ Schema authors can override the heuristic with a `layout` keyword on any property — from pydantic, pass it via `json_schema_extra`:
219
+
220
+ ```python
221
+ class Book(BaseModel):
222
+ isbn: str = Field(json_schema_extra={"layout": "sm"})
223
+ summary: str = Field(json_schema_extra={"layout": {"size": "full", "break": "before"}})
224
+ ```
225
+
226
+ - `layout: '<token>'` — shorthand for `{ size: '<token>' }`.
227
+ - `layout.size` — one of `xs | sm | md | lg | full`.
228
+ - `layout.break` — `'before' | 'after' | 'both'`: force a row break before and/or after the field. `'after'` breaks before the next *visible* field (hidden const fields are skipped).
229
+ - Invalid values are silently ignored and the heuristic applies.
230
+ - Caveat: on a multi-branch union **without** a discriminator (e.g. `Union[int, str]`), the widget collapses to the first branch and outer keywords — `layout` included — are dropped; put the hint inside the first branch or add a discriminator. `Optional[T]` fields are unaffected (sibling keys are carried through the nullable collapse).
231
+ - A `layout` size on a `const` / hidden field is ignored — hidden fields never occupy a cell.
232
+
233
+ Custom-editor matches default to `full` (their rendering is unpredictable); override with the schema `layout` hint or a `layout` key on the `customEditors` entry itself.
234
+
235
+ ### Theming the layout
236
+
237
+ The basis tokens and the checkbox row height are read from CSS custom properties, so embedders can retune density without touching the bundle:
238
+
239
+ ```css
240
+ .structured-field-editor {
241
+ --sf-basis-xs: 7rem;
242
+ --sf-basis-sm: 11rem;
243
+ --sf-basis-md: 16rem;
244
+ --sf-basis-lg: 24rem;
245
+ --sf-control-height: 30px;
246
+ }
247
+ ```
248
+
249
+ Browsers without flex `gap` support (pre-2021) automatically keep the original single-column layout.
250
+
200
251
  ## Custom Editors
201
252
 
202
253
  You can override the editor used for any field by passing a `customEditors` array to `SchemaForm`. Each entry defines a `match` condition and the `component` to render when that condition is true. Overrides are evaluated **before** the built-in resolution logic, in order — the first match wins.
@@ -1 +1 @@
1
- .structured-field-editor{width:100%;border-radius:4px;font-size:.8125rem}.structured-field-editor *,.structured-field-editor *::before,.structured-field-editor *::after{box-sizing:border-box}.structured-field-editor .sf-label{display:block;font-weight:600;margin-bottom:4px;text-transform:capitalize;color:var(--body-quiet-color, #666);font-size:.8125rem}.structured-field-editor .sf-label.required::after{content:" *";color:var(--error-fg, #ba2121)}.structured-field-editor .sf-input{display:block;width:100%;padding:6px 8px;border:1px solid var(--border-color, #ccc);border-radius:4px;background:var(--body-bg, #fff);color:var(--body-fg, #333);font-size:.8125rem;font-family:inherit;transition:border-color .15s}.structured-field-editor .sf-input:focus{outline:none;border-color:var(--primary, #79aec8);box-shadow:0 0 0 2px rgba(121,174,200,.2)}.structured-field-editor .sf-textarea{resize:vertical;min-height:60px}.structured-field-editor .sf-select{appearance:none;cursor:pointer;padding-right:28px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='12' height='12'%3E%3Cpath fill='%23888' d='M12 15L5 8h14z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 8px center;background-size:12px 12px}.structured-field-editor .sf-checkbox{margin-right:6px;accent-color:var(--primary, #79aec8)}.structured-field-editor .sf-checkbox-label{display:flex;align-items:center;font-weight:normal;cursor:pointer;padding:6px 0}.structured-field-editor .sf-btn{display:inline-flex;align-items:center;gap:4px;padding:4px 12px;background:var(--object-tools-bg, #888);color:var(--object-tools-fg, #fff);font-weight:400;font-size:.6875rem;text-transform:uppercase;letter-spacing:.5px;border-radius:15px;border:none;cursor:pointer;transition:background-color .15s}.structured-field-editor .sf-btn:hover{background-color:var(--object-tools-hover-bg, #666)}.structured-field-editor .sf-btn i{font-size:.6rem}.structured-field-editor .sf-btn-sm{padding:2px 8px;font-size:.625rem}.structured-field-editor .sf-btn-add{background:var(--object-tools-bg, #888);color:var(--object-tools-fg, #fff)}.structured-field-editor .sf-btn-danger{background:var(--delete-button-bg, #ba2121);color:var(--delete-button-fg, #fff)}.structured-field-editor .sf-btn-danger:hover{background:#a41515}.structured-field-editor .sf-error{color:var(--error-fg, #ba2121);font-size:.75rem;margin-top:2px}.structured-field-editor .errors .sf-input{border-color:var(--error-fg, #ba2121)}.structured-field-editor .errorlist{margin:4px 0 0 0;padding:0;list-style:none;color:var(--error-fg, #ba2121);font-size:.75rem}.structured-field-editor .errorlist li{padding:2px 0}.form-row{overflow:visible !important}.structured-field-editor .sf-field{margin-bottom:12px}.structured-field-editor .sf-field-boolean{margin-bottom:8px}.structured-field-editor .sf-object:not(.sf-object-root){border:1px solid var(--border-color, #ccc);border-radius:4px;padding:12px;margin-bottom:12px;background:var(--body-bg, #fff)}.structured-field-editor .sf-object:not(.sf-object-root).sf-object-collapsed{padding:0}.structured-field-editor .sf-object-title{display:flex;align-items:center;gap:6px;font-weight:600;font-size:.8125rem;color:var(--body-fg, #333);text-transform:capitalize;padding:0 4px}.structured-field-editor .sf-object-title-text{flex-shrink:0}.structured-field-editor .sf-object-summary{font-weight:400;font-size:.75rem;color:var(--body-quiet-color, #888);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:240px}.structured-field-editor .sf-collapse-btn{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;padding:0;border:none;background:rgba(0,0,0,0);cursor:pointer;color:var(--body-quiet-color, #888);border-radius:3px;flex-shrink:0}.structured-field-editor .sf-collapse-btn:hover{background:var(--darkened-bg, #f0f0f0);color:var(--body-fg, #333)}.structured-field-editor .sf-object-fields{display:flex;flex-direction:column}.structured-field-editor .sf-array{margin-bottom:12px}.structured-field-editor .sf-array-header{display:flex;align-items:center;gap:8px;margin-bottom:8px}.structured-field-editor .sf-array-header .sf-label{margin-bottom:0}.structured-field-editor .sf-array-collapse-toggle{margin-left:auto;display:inline-flex;align-items:center;cursor:pointer;color:var(--body-quiet-color, #aaa);line-height:0}.structured-field-editor .sf-array-collapse-toggle:hover{color:var(--body-fg, #333)}.structured-field-editor .sf-array-count{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:20px;padding:0 6px;background:var(--darkened-bg, #f0f0f0);border-radius:10px;font-size:.6875rem;font-weight:600;color:var(--body-quiet-color, #666)}.structured-field-editor .sf-array-items{display:flex;flex-direction:column;gap:8px}.structured-field-editor .sf-array-item{border:1px solid var(--border-color, #ccc);border-radius:4px;background:var(--darkened-bg, #f8f8f8);overflow:visible;position:relative}.structured-field-editor .sf-array-item[draggable=true]{cursor:grab}.structured-field-editor .sf-array-item.sf-dragging{opacity:.4}.structured-field-editor .sf-array-item.sf-drag-over{outline:2px solid var(--primary-color, #3b82f6);outline-offset:-2px}.structured-field-editor .sf-array-item-header{display:flex;align-items:center;justify-content:space-between;padding:4px 8px;background:var(--darkened-bg, #f0f0f0);border-bottom:1px solid var(--border-color, #ccc);border-radius:4px 4px 0 0}.structured-field-editor .sf-array-item-left{display:flex;align-items:center;gap:6px}.structured-field-editor .sf-drag-handle{display:inline-flex;align-items:center;color:var(--body-quiet-color, #aaa);cursor:grab;padding:0 2px;line-height:0}.structured-field-editor .sf-drag-handle:active{cursor:grabbing}.structured-field-editor .sf-drag-handle:hover{color:var(--body-fg, #555)}.structured-field-editor .sf-array-item-index{font-size:.6875rem;font-weight:600;color:var(--body-quiet-color, #666)}.structured-field-editor .sf-array-item-actions{display:flex;gap:4px}.structured-field-editor .sf-array-item-body{padding:10px}.structured-field-editor .sf-array-item-body>.sf-object.sf-object-root,.structured-field-editor .sf-array-item-body>.sf-object:not(.sf-object-root){border:none;padding:0;margin:0;background:rgba(0,0,0,0)}.structured-field-editor .sf-null-badge{display:inline-block;font-size:.65rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--body-quiet-color, #888);background:var(--darkened-bg, #f0f0f0);border:1px solid var(--border-color, #ccc);border-radius:3px;padding:1px 5px;vertical-align:middle;margin-left:4px}.structured-field-editor .sf-input-row{display:flex;align-items:stretch;gap:4px}.structured-field-editor .sf-input-row .sf-input{flex:1;min-width:0}.structured-field-editor .sf-boolean-row{display:flex;align-items:center;gap:6px}.structured-field-editor .sf-null-clear-btn{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;padding:0;border:1px solid var(--border-color, #ccc);border-radius:4px;background:rgba(0,0,0,0);cursor:pointer;color:var(--body-quiet-color, #888);font-size:.75rem;line-height:1;align-self:center}.structured-field-editor .sf-null-clear-btn:hover{background:var(--error-bg, #fff2f2);border-color:var(--error-fg, #ba2121);color:var(--error-fg, #ba2121)}.structured-field-editor .sf-nullable{margin-bottom:12px}.structured-field-editor .sf-nullable-header{display:flex;align-items:center;gap:8px;margin-bottom:4px}.structured-field-editor .sf-nullable-header .sf-label{margin-bottom:0}.structured-field-editor .sf-nullable-body{padding-left:0}.structured-field-editor .sf-nullable-body:not(:empty){border:1px solid var(--border-color, #ccc);border-radius:4px;padding:12px;margin-top:4px;background:var(--body-bg, #fff)}.structured-field-editor .sf-field-json .sf-json-editor{position:relative;border:1px solid var(--border-color, #ccc);border-radius:4px;overflow:hidden}.structured-field-editor .sf-field-json .sf-json-editor.sf-json-error{border-color:var(--error-fg, #ba2121)}.structured-field-editor .sf-field-json .sf-json-toolbar{display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:4px 6px;background:var(--darkened-bg, #f8f8f8);border-bottom:1px solid var(--border-color, #ccc)}.structured-field-editor .sf-field-json .sf-json-error-msg{font-size:.72rem;color:var(--error-fg, #ba2121);flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.structured-field-editor .sf-field-json .sf-json-format-btn{flex-shrink:0}.structured-field-editor .sf-field-json .sf-json-ace-container{width:100%;font-size:.8rem}.structured-field-editor .sf-field-json .sf-json-ace-container .ace_editor{font-family:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,monospace !important;font-size:.8rem !important}.structured-field-editor .sf-field-json .sf-json-textarea-fallback{width:100%;min-height:120px;font-family:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,monospace;font-size:.8rem;border:none;border-radius:0;resize:vertical}.structured-field-editor .sf-union{margin-bottom:12px}.structured-field-editor .sf-union-body{border:1px solid var(--border-color, #ccc);border-radius:4px;padding:12px;margin-top:8px;background:var(--body-bg, #fff)}.structured-field-editor .sf-union-body>.sf-object{border:none;padding:0;margin:0;background:rgba(0,0,0,0)}.structured-field-editor .sf-relation{position:relative}.structured-field-editor .sf-relation-wrapper{display:flex;flex-direction:column;gap:6px}.structured-field-editor .sf-relation-selected{display:flex;flex-wrap:wrap;gap:6px}.structured-field-editor .sf-relation-selected:empty{display:none}.structured-field-editor .sf-relation-tag{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;background:var(--darkened-bg, #f0f0f0);border:1px solid var(--border-color, #ccc);border-radius:4px;font-size:.8125rem;color:var(--body-fg, #333);max-width:100%}.structured-field-editor .sf-relation-tag-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.structured-field-editor .sf-relation-tag-remove{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;padding:0;border:none;border-radius:50%;background:rgba(0,0,0,0);color:var(--body-quiet-color, #666);cursor:pointer;font-size:.6875rem;flex-shrink:0;transition:color .15s,background .15s}.structured-field-editor .sf-relation-tag-remove:hover{color:var(--error-fg, #ba2121);background:rgba(186,33,33,.1)}.structured-field-editor .sf-relation-search{position:relative}.structured-field-editor .sf-relation-input{padding-left:28px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23999' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:8px center;background-size:14px}.structured-field-editor .sf-relation-dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;max-height:240px;overflow-y:auto;background:var(--body-bg, #fff);border:1px solid var(--border-color, #ccc);border-top:none;border-radius:0 0 4px 4px;box-shadow:0 4px 12px rgba(0,0,0,.1)}.structured-field-editor .sf-relation-dropdown-item{padding:8px 12px;cursor:pointer;font-size:.8125rem;color:var(--body-fg, #333);transition:background .1s;border-bottom:1px solid var(--hairline-color, #eee)}.structured-field-editor .sf-relation-dropdown-item:last-child{border-bottom:none}.structured-field-editor .sf-relation-dropdown-item:hover,.structured-field-editor .sf-relation-dropdown-item.highlighted{background:var(--selected-bg, #e4e4e4)}.structured-field-editor .sf-relation-dropdown-empty{padding:12px;text-align:center;color:var(--body-quiet-color, #999);font-size:.8125rem;font-style:italic}.structured-field-editor .sf-relation-dropdown-more{padding:8px 12px;text-align:center;cursor:pointer;font-size:.75rem;color:var(--link-fg, #417690);font-weight:600;border-top:1px solid var(--hairline-color, #eee);transition:background .1s}.structured-field-editor .sf-relation-dropdown-more:hover{background:var(--darkened-bg, #f0f0f0)}
1
+ .structured-field-editor{width:100%;border-radius:4px;font-size:.8125rem}.structured-field-editor *,.structured-field-editor *::before,.structured-field-editor *::after{box-sizing:border-box}.structured-field-editor .sf-label{display:block;font-weight:600;margin-bottom:4px;text-transform:capitalize;color:var(--body-quiet-color, #666);font-size:.8125rem}.structured-field-editor .sf-label.required::after{content:" *";color:var(--error-fg, #ba2121)}.structured-field-editor .sf-input{display:block;width:100%;padding:6px 8px;border:1px solid var(--border-color, #ccc);border-radius:4px;background:var(--body-bg, #fff);color:var(--body-fg, #333);font-size:.8125rem;font-family:inherit;transition:border-color .15s}.structured-field-editor .sf-input:focus{outline:none;border-color:var(--primary, #79aec8);box-shadow:0 0 0 2px rgba(121,174,200,.2)}.structured-field-editor .sf-textarea{resize:vertical;min-height:60px}.structured-field-editor .sf-select{appearance:none;cursor:pointer;padding-right:28px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='12' height='12'%3E%3Cpath fill='%23888' d='M12 15L5 8h14z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 8px center;background-size:12px 12px}.structured-field-editor .sf-checkbox{margin-right:6px;accent-color:var(--primary, #79aec8)}.structured-field-editor .sf-checkbox-label{display:flex;align-items:center;font-weight:normal;cursor:pointer;padding:6px 0}.structured-field-editor .sf-btn{display:inline-flex;align-items:center;gap:4px;padding:4px 12px;background:var(--object-tools-bg, #888);color:var(--object-tools-fg, #fff);font-weight:400;font-size:.6875rem;text-transform:uppercase;letter-spacing:.5px;border-radius:15px;border:none;cursor:pointer;transition:background-color .15s}.structured-field-editor .sf-btn:hover{background-color:var(--object-tools-hover-bg, #666)}.structured-field-editor .sf-btn i{font-size:.6rem}.structured-field-editor .sf-btn-sm{padding:2px 8px;font-size:.625rem}.structured-field-editor .sf-btn-add{background:var(--object-tools-bg, #888);color:var(--object-tools-fg, #fff)}.structured-field-editor .sf-btn-danger{background:var(--delete-button-bg, #ba2121);color:var(--delete-button-fg, #fff)}.structured-field-editor .sf-btn-danger:hover{background:#a41515}.structured-field-editor .sf-error{color:var(--error-fg, #ba2121);font-size:.75rem;margin-top:2px}.structured-field-editor .errors .sf-input{border-color:var(--error-fg, #ba2121)}.structured-field-editor .errorlist{margin:4px 0 0 0;padding:0;list-style:none;color:var(--error-fg, #ba2121);font-size:.75rem}.structured-field-editor .errorlist li{padding:2px 0}.form-row{overflow:visible !important}.structured-field-editor .sf-field{margin-bottom:12px}.structured-field-editor .sf-field-boolean{margin-bottom:8px}.structured-field-editor .sf-object:not(.sf-object-root){border:1px solid var(--border-color, #ccc);border-radius:4px;padding:12px;margin-bottom:12px;background:var(--body-bg, #fff)}.structured-field-editor .sf-object:not(.sf-object-root).sf-object-collapsed{padding:0}.structured-field-editor .sf-object-title{display:flex;align-items:center;gap:6px;font-weight:600;font-size:.8125rem;color:var(--body-fg, #333);text-transform:capitalize;padding:0 4px}.structured-field-editor .sf-object-title-text{flex-shrink:0}.structured-field-editor .sf-object-summary{font-weight:400;font-size:.75rem;color:var(--body-quiet-color, #888);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:240px}.structured-field-editor .sf-collapse-btn{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;padding:0;border:none;background:rgba(0,0,0,0);cursor:pointer;color:var(--body-quiet-color, #888);border-radius:3px;flex-shrink:0}.structured-field-editor .sf-collapse-btn:hover{background:var(--darkened-bg, #f0f0f0);color:var(--body-fg, #333)}.structured-field-editor .sf-object-fields{display:flex;flex-direction:column}.structured-field-editor .sf-array{margin-bottom:12px}.structured-field-editor .sf-array-header{display:flex;align-items:center;gap:8px;margin-bottom:8px}.structured-field-editor .sf-array-header .sf-label{margin-bottom:0}.structured-field-editor .sf-array-collapse-toggle{margin-left:auto;display:inline-flex;align-items:center;cursor:pointer;color:var(--body-quiet-color, #aaa);line-height:0}.structured-field-editor .sf-array-collapse-toggle:hover{color:var(--body-fg, #333)}.structured-field-editor .sf-array-count{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:20px;padding:0 6px;background:var(--darkened-bg, #f0f0f0);border-radius:10px;font-size:.6875rem;font-weight:600;color:var(--body-quiet-color, #666)}.structured-field-editor .sf-array-items{display:flex;flex-direction:column;gap:8px}.structured-field-editor .sf-array-item{border:1px solid var(--border-color, #ccc);border-radius:4px;background:var(--darkened-bg, #f8f8f8);overflow:visible;position:relative}.structured-field-editor .sf-array-item[draggable=true]{cursor:grab}.structured-field-editor .sf-array-item.sf-dragging{opacity:.4}.structured-field-editor .sf-array-item.sf-drag-over{outline:2px solid var(--primary-color, #3b82f6);outline-offset:-2px}.structured-field-editor .sf-array-item-header{display:flex;align-items:center;justify-content:space-between;padding:4px 8px;background:var(--darkened-bg, #f0f0f0);border-bottom:1px solid var(--border-color, #ccc);border-radius:4px 4px 0 0}.structured-field-editor .sf-array-item-left{display:flex;align-items:center;gap:6px}.structured-field-editor .sf-drag-handle{display:inline-flex;align-items:center;color:var(--body-quiet-color, #aaa);cursor:grab;padding:0 2px;line-height:0}.structured-field-editor .sf-drag-handle:active{cursor:grabbing}.structured-field-editor .sf-drag-handle:hover{color:var(--body-fg, #555)}.structured-field-editor .sf-array-item-index{font-size:.6875rem;font-weight:600;color:var(--body-quiet-color, #666)}.structured-field-editor .sf-array-item-actions{display:flex;gap:4px}.structured-field-editor .sf-array-item-body{padding:10px}.structured-field-editor .sf-array-item-body>.sf-object.sf-object-root,.structured-field-editor .sf-array-item-body>.sf-object:not(.sf-object-root){border:none;padding:0;margin:0;background:rgba(0,0,0,0)}.structured-field-editor .sf-null-badge{display:inline-block;font-size:.65rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--body-quiet-color, #888);background:var(--darkened-bg, #f0f0f0);border:1px solid var(--border-color, #ccc);border-radius:3px;padding:1px 5px;vertical-align:middle;margin-left:4px}.structured-field-editor .sf-input-row{display:flex;align-items:stretch;gap:4px}.structured-field-editor .sf-input-row .sf-input{flex:1;min-width:0}.structured-field-editor .sf-boolean-row{display:flex;align-items:center;gap:6px}.structured-field-editor .sf-null-clear-btn{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;padding:0;border:1px solid var(--border-color, #ccc);border-radius:4px;background:rgba(0,0,0,0);cursor:pointer;color:var(--body-quiet-color, #888);font-size:.75rem;line-height:1;align-self:center}.structured-field-editor .sf-null-clear-btn:hover{background:var(--error-bg, #fff2f2);border-color:var(--error-fg, #ba2121);color:var(--error-fg, #ba2121)}.structured-field-editor .sf-nullable{margin-bottom:12px}.structured-field-editor .sf-nullable-header{display:flex;align-items:center;gap:8px;margin-bottom:4px}.structured-field-editor .sf-nullable-header .sf-label{margin-bottom:0}.structured-field-editor .sf-nullable-body{padding-left:0}.structured-field-editor .sf-nullable-body:not(:empty){border:1px solid var(--border-color, #ccc);border-radius:4px;padding:12px;margin-top:4px;background:var(--body-bg, #fff)}.structured-field-editor .sf-field-json .sf-json-editor{position:relative;border:1px solid var(--border-color, #ccc);border-radius:4px;overflow:hidden}.structured-field-editor .sf-field-json .sf-json-editor.sf-json-error{border-color:var(--error-fg, #ba2121)}.structured-field-editor .sf-field-json .sf-json-toolbar{display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:4px 6px;background:var(--darkened-bg, #f8f8f8);border-bottom:1px solid var(--border-color, #ccc)}.structured-field-editor .sf-field-json .sf-json-error-msg{font-size:.72rem;color:var(--error-fg, #ba2121);flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.structured-field-editor .sf-field-json .sf-json-format-btn{flex-shrink:0}.structured-field-editor .sf-field-json .sf-json-ace-container{width:100%;font-size:.8rem}.structured-field-editor .sf-field-json .sf-json-ace-container .ace_editor{font-family:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,monospace !important;font-size:.8rem !important}.structured-field-editor .sf-field-json .sf-json-textarea-fallback{width:100%;min-height:120px;font-family:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,monospace;font-size:.8rem;border:none;border-radius:0;resize:vertical}.structured-field-editor .sf-union{margin-bottom:12px}.structured-field-editor .sf-union-body{border:1px solid var(--border-color, #ccc);border-radius:4px;padding:12px;margin-top:8px;background:var(--body-bg, #fff)}.structured-field-editor .sf-union-body>.sf-object{border:none;padding:0;margin:0;background:rgba(0,0,0,0)}.structured-field-editor .sf-relation{position:relative}.structured-field-editor .sf-relation-wrapper{display:flex;flex-direction:column;gap:6px}.structured-field-editor .sf-relation-selected{display:flex;flex-wrap:wrap;gap:6px}.structured-field-editor .sf-relation-selected:empty{display:none}.structured-field-editor .sf-relation-tag{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;background:var(--darkened-bg, #f0f0f0);border:1px solid var(--border-color, #ccc);border-radius:4px;font-size:.8125rem;color:var(--body-fg, #333);max-width:100%}.structured-field-editor .sf-relation-tag-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.structured-field-editor .sf-relation-tag-remove{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;padding:0;border:none;border-radius:50%;background:rgba(0,0,0,0);color:var(--body-quiet-color, #666);cursor:pointer;font-size:.6875rem;flex-shrink:0;transition:color .15s,background .15s}.structured-field-editor .sf-relation-tag-remove:hover{color:var(--error-fg, #ba2121);background:rgba(186,33,33,.1)}.structured-field-editor .sf-relation-search{position:relative}.structured-field-editor .sf-relation-input{padding-left:28px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23999' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:8px center;background-size:14px}.structured-field-editor .sf-relation-dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;max-height:240px;overflow-y:auto;background:var(--body-bg, #fff);border:1px solid var(--border-color, #ccc);border-top:none;border-radius:0 0 4px 4px;box-shadow:0 4px 12px rgba(0,0,0,.1)}.structured-field-editor .sf-relation-dropdown-item{padding:8px 12px;cursor:pointer;font-size:.8125rem;color:var(--body-fg, #333);transition:background .1s;border-bottom:1px solid var(--hairline-color, #eee)}.structured-field-editor .sf-relation-dropdown-item:last-child{border-bottom:none}.structured-field-editor .sf-relation-dropdown-item:hover,.structured-field-editor .sf-relation-dropdown-item.highlighted{background:var(--selected-bg, #e4e4e4)}.structured-field-editor .sf-relation-dropdown-empty{padding:12px;text-align:center;color:var(--body-quiet-color, #999);font-size:.8125rem;font-style:italic}.structured-field-editor .sf-relation-dropdown-more{padding:8px 12px;text-align:center;cursor:pointer;font-size:.75rem;color:var(--link-fg, #417690);font-weight:600;border-top:1px solid var(--hairline-color, #eee);transition:background .1s}.structured-field-editor .sf-relation-dropdown-more:hover{background:var(--darkened-bg, #f0f0f0)}.structured-field-editor .sf-cell{min-width:0}.structured-field-editor .sf-cell-hidden{display:none}@supports(inset: 0){.structured-field-editor .sf-object-fields{flex-flow:row wrap;column-gap:16px;align-items:flex-start}.structured-field-editor .sf-flow-break{flex-basis:100%;height:0}.structured-field-editor .sf-cell-xs{flex:1 1 var(--sf-basis-xs, 8rem)}.structured-field-editor .sf-cell-sm{flex:1 1 var(--sf-basis-sm, 12rem)}.structured-field-editor .sf-cell-md{flex:1 1 var(--sf-basis-md, 18rem)}.structured-field-editor .sf-cell-lg{flex:1 1 var(--sf-basis-lg, 26rem)}.structured-field-editor .sf-cell-full{flex:1 1 100%}.structured-field-editor .sf-cell>.sf-field-boolean{margin-bottom:12px}.structured-field-editor .sf-cell-bool{align-self:flex-end}.structured-field-editor .sf-cell-bool .sf-boolean-row{min-height:var(--sf-control-height, 30px)}@supports selector(:has(*)){.structured-field-editor .sf-object-fields:has(.errorlist)>.sf-cell-bool{align-self:flex-start}.structured-field-editor .sf-object-fields:has(.errorlist)>.sf-cell-bool>.sf-field-boolean{padding-top:calc(1.1375rem + 4px)}}}
@@ -8023,6 +8023,121 @@ function hasConditionals(schema) {
8023
8023
  return false;
8024
8024
  }
8025
8025
 
8026
+ // Field-size classification for the multicolumn flow layout.
8027
+ // Sizes are flex-basis tokens (see scss/components/layout.scss), not column
8028
+ // counts: columns emerge from how many cells fit the container's width.
8029
+ // Invariant: visual order === DOM order === tab order. Never reorder cells.
8030
+
8031
+ const SIZES = ['xs', 'sm', 'md', 'lg', 'full'];
8032
+ const BREAKS = ['before', 'after', 'both'];
8033
+
8034
+ // Schema-author hint: `layout: 'sm'` or `layout: { size: 'sm', break: 'before' }`.
8035
+ // Invalid hints are silently ignored so a typo degrades to the heuristic.
8036
+ function normalizeLayoutHint(layout) {
8037
+ if (typeof layout === 'string') {
8038
+ return { size: SIZES.includes(layout) ? layout : null, break: null };
8039
+ }
8040
+ if (layout && typeof layout === 'object' && !Array.isArray(layout)) {
8041
+ return {
8042
+ size: SIZES.includes(layout.size) ? layout.size : null,
8043
+ break: BREAKS.includes(layout.break) ? layout.break : null,
8044
+ };
8045
+ }
8046
+ return { size: null, break: null };
8047
+ }
8048
+
8049
+ // Nullable scalars carry the inline null-clear button (~30px of chrome), and
8050
+ // datetime-local needs its full width — one tier of slack keeps them usable.
8051
+ const NULLABLE_BUMP = { xs: 'sm', sm: 'md' };
8052
+
8053
+ function bumpNullable(size, schema) {
8054
+ return schema._nullable ? (NULLABLE_BUMP[size] || size) : size;
8055
+ }
8056
+
8057
+ function choiceSize(labels, schema) {
8058
+ const compact = labels.length <= 8 && labels.every((l) => String(l ?? '').length <= 12);
8059
+ return bumpNullable(compact ? 'sm' : 'md', schema);
8060
+ }
8061
+
8062
+ // Shared with SchemaEditor: past this depth everything renders StringEditor.
8063
+ const MAX_DEPTH = 12;
8064
+
8065
+ // Intrinsic size of a RESOLVED schema node.
8066
+ // Returns 'xs' | 'sm' | 'md' | 'lg' | 'full' | 'hidden'.
8067
+ // Hidden routing (const / single-string-enum) is authoritative: a size hint
8068
+ // on a field that renders HiddenEditor would only produce an empty cell.
8069
+ function fieldSize(schema) {
8070
+ if (!schema || typeof schema !== 'object') return 'full';
8071
+ const intrinsic = intrinsicSize(schema);
8072
+ if (intrinsic === 'hidden') return 'hidden';
8073
+ return normalizeLayoutHint(schema.layout).size || intrinsic;
8074
+ }
8075
+
8076
+ // The branch order mirrors SchemaEditor.editorComponent — keep them in sync.
8077
+ function intrinsicSize(schema) {
8078
+ if (schema.type === 'relation') return schema.multiple ? 'lg' : 'md';
8079
+ if (schema.oneOf && schema.discriminator) return 'full';
8080
+ if (isChoiceOneOf(schema.oneOf)) {
8081
+ return choiceSize(schema.oneOf.map((o) => o.title ?? o.const), schema);
8082
+ }
8083
+ if ('const' in schema) return 'hidden';
8084
+ if (schema.enum && schema.enum.length === 1 && schema.type === 'string') return 'hidden';
8085
+ // Covers ObjectEditor, JsonEditor, ArrayEditor and NullableEditor containers.
8086
+ if (schema.type === 'object' || schema.type === 'array') return 'full';
8087
+ if (schema.enum) return choiceSize(schema.enum, schema);
8088
+ if (schema.type === 'boolean') return bumpNullable('xs', schema);
8089
+ if (schema.type === 'number' || schema.type === 'integer') return bumpNullable('xs', schema);
8090
+ if (schema.type === 'string') {
8091
+ if (schema.format === 'date') return bumpNullable('sm', schema);
8092
+ if (schema.format === 'date-time') return bumpNullable('md', schema);
8093
+ // Mirrors StringEditor.isLong (textarea rendering).
8094
+ if (schema.format === 'textarea' || schema.maxLength > 255) return 'full';
8095
+ if (schema.maxLength > 0 && schema.maxLength <= 40) return bumpNullable('sm', schema);
8096
+ return 'md';
8097
+ }
8098
+ return 'full';
8099
+ }
8100
+
8101
+ // Builds the cell list for an object's properties: resolved schema, wrapper
8102
+ // classes and row-break flags. `break: 'after'` marks the NEXT visible field;
8103
+ // hidden fields neither consume nor emit a pending break.
8104
+ // Custom-editor matches default to 'full' (we can't predict their rendering)
8105
+ // unless the schema hint or the override's own `layout` says otherwise.
8106
+ function layoutCells(properties, { resolveSchema, customEditors = [], basePath = [] } = {}) {
8107
+ const cells = [];
8108
+ let pendingBreak = false;
8109
+ // Mirrors SchemaEditor: the depth guard runs before custom-editor overrides,
8110
+ // and past it every field (const included) renders a visible StringEditor.
8111
+ const pastMaxDepth = basePath.length + 1 > MAX_DEPTH;
8112
+ for (const [key, raw] of Object.entries(properties || {})) {
8113
+ const schema = resolveSchema ? resolveSchema(raw) : raw;
8114
+ const hint = normalizeLayoutHint(schema.layout);
8115
+ const override = !pastMaxDepth
8116
+ && customEditors.find((o) => o.match && o.match(schema, [...basePath, key]));
8117
+ let size;
8118
+ if (pastMaxDepth) {
8119
+ size = 'md';
8120
+ } else if (override) {
8121
+ size = hint.size || normalizeLayoutHint(override.layout).size || 'full';
8122
+ } else {
8123
+ size = fieldSize(schema);
8124
+ }
8125
+ const classes = ['sf-cell', `sf-cell-${size}`];
8126
+ // Only the plain-boolean shape reaches the label-less BooleanEditor;
8127
+ // boolean enums / choice oneOfs render SelectEditor (which has a label).
8128
+ const isCheckbox = schema.type === 'boolean' && !override && !pastMaxDepth
8129
+ && !schema.enum && !schema.oneOf && !('const' in schema);
8130
+ let breakBefore = false;
8131
+ if (size !== 'hidden') {
8132
+ if (isCheckbox) classes.push('sf-cell-bool');
8133
+ breakBefore = pendingBreak || hint.break === 'before' || hint.break === 'both';
8134
+ pendingBreak = hint.break === 'after' || hint.break === 'both';
8135
+ }
8136
+ cells.push({ key, schema, classes: classes.join(' '), breakBefore });
8137
+ }
8138
+ return cells;
8139
+ }
8140
+
8026
8141
  var script$8 = {
8027
8142
  name: 'ObjectEditor',
8028
8143
  beforeCreate() {
@@ -8030,6 +8145,9 @@ var script$8 = {
8030
8145
  this.$options.components.SchemaEditor = script$1;
8031
8146
  this.$options.components.SfIcon = script$9;
8032
8147
  },
8148
+ inject: {
8149
+ customEditors: { default: () => () => [] },
8150
+ },
8033
8151
  props: {
8034
8152
  schema: { type: Object, required: true },
8035
8153
  modelValue: { default: () => ({}) },
@@ -8056,6 +8174,13 @@ var script$8 = {
8056
8174
  if (!hasConditionals(this.schema)) return this.schema;
8057
8175
  return applyConditionals(this.schema, this.modelValue || {}, this.form?.resolveSchema);
8058
8176
  },
8177
+ cells() {
8178
+ return layoutCells(this.effectiveSchema.properties, {
8179
+ resolveSchema: this.form?.resolveSchema,
8180
+ customEditors: this.customEditors(),
8181
+ basePath: this.path,
8182
+ });
8183
+ },
8059
8184
  summary() {
8060
8185
  const val = this.modelValue || {};
8061
8186
  const parts = [];
@@ -8118,14 +8243,24 @@ const _hoisted_1$6 = {
8118
8243
  class: "sf-object sf-object-root"
8119
8244
  };
8120
8245
  const _hoisted_2$5 = { class: "sf-object-fields" };
8121
- const _hoisted_3$5 = { class: "sf-object-title" };
8122
- const _hoisted_4$4 = ["aria-label"];
8123
- const _hoisted_5$4 = { class: "sf-object-title-text" };
8124
- const _hoisted_6$3 = {
8246
+ const _hoisted_3$5 = {
8247
+ key: 0,
8248
+ class: "sf-flow-break",
8249
+ "aria-hidden": "true"
8250
+ };
8251
+ const _hoisted_4$4 = { class: "sf-object-title" };
8252
+ const _hoisted_5$4 = ["aria-label"];
8253
+ const _hoisted_6$3 = { class: "sf-object-title-text" };
8254
+ const _hoisted_7$2 = {
8125
8255
  key: 0,
8126
8256
  class: "sf-object-summary"
8127
8257
  };
8128
- const _hoisted_7$2 = { class: "sf-object-fields" };
8258
+ const _hoisted_8$2 = { class: "sf-object-fields" };
8259
+ const _hoisted_9$2 = {
8260
+ key: 0,
8261
+ class: "sf-flow-break",
8262
+ "aria-hidden": "true"
8263
+ };
8129
8264
 
8130
8265
  function render$7(_ctx, _cache, $props, $setup, $data, $options) {
8131
8266
  const _component_SchemaEditor = resolveComponent("SchemaEditor");
@@ -8134,15 +8269,25 @@ function render$7(_ctx, _cache, $props, $setup, $data, $options) {
8134
8269
  return ($options.isRoot)
8135
8270
  ? (openBlock(), createElementBlock("div", _hoisted_1$6, [
8136
8271
  createBaseVNode("div", _hoisted_2$5, [
8137
- (openBlock(true), createElementBlock(Fragment, null, renderList(($options.effectiveSchema.properties || {}), (propSchema, key) => {
8138
- return (openBlock(), createBlock(_component_SchemaEditor, {
8139
- key: key,
8140
- schema: $props.form.resolveSchema(propSchema),
8141
- "model-value": ($props.modelValue || {})[key],
8142
- path: [...$props.path, key],
8143
- form: $props.form,
8144
- "onUpdate:modelValue": $event => ($options.onChildChange(key, $event))
8145
- }, null, 8 /* PROPS */, ["schema", "model-value", "path", "form", "onUpdate:modelValue"]))
8272
+ (openBlock(true), createElementBlock(Fragment, null, renderList($options.cells, (cell) => {
8273
+ return (openBlock(), createElementBlock(Fragment, {
8274
+ key: cell.key
8275
+ }, [
8276
+ (cell.breakBefore)
8277
+ ? (openBlock(), createElementBlock("div", _hoisted_3$5))
8278
+ : createCommentVNode("v-if", true),
8279
+ createBaseVNode("div", {
8280
+ class: normalizeClass(cell.classes)
8281
+ }, [
8282
+ createVNode(_component_SchemaEditor, {
8283
+ schema: cell.schema,
8284
+ "model-value": ($props.modelValue || {})[cell.key],
8285
+ path: [...$props.path, cell.key],
8286
+ form: $props.form,
8287
+ "onUpdate:modelValue": $event => ($options.onChildChange(cell.key, $event))
8288
+ }, null, 8 /* PROPS */, ["schema", "model-value", "path", "form", "onUpdate:modelValue"])
8289
+ ], 2 /* CLASS */)
8290
+ ], 64 /* STABLE_FRAGMENT */))
8146
8291
  }), 128 /* KEYED_FRAGMENT */))
8147
8292
  ])
8148
8293
  ]))
@@ -8150,7 +8295,7 @@ function render$7(_ctx, _cache, $props, $setup, $data, $options) {
8150
8295
  key: 1,
8151
8296
  class: normalizeClass(["sf-object", { 'sf-object-collapsed': $data.collapsed }])
8152
8297
  }, [
8153
- createBaseVNode("legend", _hoisted_3$5, [
8298
+ createBaseVNode("legend", _hoisted_4$4, [
8154
8299
  createBaseVNode("button", {
8155
8300
  type: "button",
8156
8301
  class: "sf-collapse-btn",
@@ -8161,22 +8306,32 @@ function render$7(_ctx, _cache, $props, $setup, $data, $options) {
8161
8306
  name: $data.collapsed ? 'chevron-down' : 'chevron-up',
8162
8307
  size: 12
8163
8308
  }, null, 8 /* PROPS */, ["name"])
8164
- ], 8 /* PROPS */, _hoisted_4$4),
8165
- createBaseVNode("span", _hoisted_5$4, toDisplayString($options.title), 1 /* TEXT */),
8309
+ ], 8 /* PROPS */, _hoisted_5$4),
8310
+ createBaseVNode("span", _hoisted_6$3, toDisplayString($options.title), 1 /* TEXT */),
8166
8311
  ($data.collapsed && $options.summary)
8167
- ? (openBlock(), createElementBlock("span", _hoisted_6$3, toDisplayString($options.summary), 1 /* TEXT */))
8312
+ ? (openBlock(), createElementBlock("span", _hoisted_7$2, toDisplayString($options.summary), 1 /* TEXT */))
8168
8313
  : createCommentVNode("v-if", true)
8169
8314
  ]),
8170
- withDirectives(createBaseVNode("div", _hoisted_7$2, [
8171
- (openBlock(true), createElementBlock(Fragment, null, renderList(($options.effectiveSchema.properties || {}), (propSchema, key) => {
8172
- return (openBlock(), createBlock(_component_SchemaEditor, {
8173
- key: key,
8174
- schema: $props.form.resolveSchema(propSchema),
8175
- "model-value": ($props.modelValue || {})[key],
8176
- path: [...$props.path, key],
8177
- form: $props.form,
8178
- "onUpdate:modelValue": $event => ($options.onChildChange(key, $event))
8179
- }, null, 8 /* PROPS */, ["schema", "model-value", "path", "form", "onUpdate:modelValue"]))
8315
+ withDirectives(createBaseVNode("div", _hoisted_8$2, [
8316
+ (openBlock(true), createElementBlock(Fragment, null, renderList($options.cells, (cell) => {
8317
+ return (openBlock(), createElementBlock(Fragment, {
8318
+ key: cell.key
8319
+ }, [
8320
+ (cell.breakBefore)
8321
+ ? (openBlock(), createElementBlock("div", _hoisted_9$2))
8322
+ : createCommentVNode("v-if", true),
8323
+ createBaseVNode("div", {
8324
+ class: normalizeClass(cell.classes)
8325
+ }, [
8326
+ createVNode(_component_SchemaEditor, {
8327
+ schema: cell.schema,
8328
+ "model-value": ($props.modelValue || {})[cell.key],
8329
+ path: [...$props.path, cell.key],
8330
+ form: $props.form,
8331
+ "onUpdate:modelValue": $event => ($options.onChildChange(cell.key, $event))
8332
+ }, null, 8 /* PROPS */, ["schema", "model-value", "path", "form", "onUpdate:modelValue"])
8333
+ ], 2 /* CLASS */)
8334
+ ], 64 /* STABLE_FRAGMENT */))
8180
8335
  }), 128 /* KEYED_FRAGMENT */))
8181
8336
  ], 512 /* NEED_PATCH */), [
8182
8337
  [vShow, !$data.collapsed]
@@ -8849,7 +9004,7 @@ function render$3(_ctx, _cache, $props, $setup, $data, $options) {
8849
9004
  const _component_SfIcon = resolveComponent("SfIcon");
8850
9005
 
8851
9006
  return (openBlock(), createElementBlock("div", {
8852
- class: normalizeClass(["sf-field sf-relation", { errors: $options.fieldErrors.length }]),
9007
+ class: normalizeClass(["sf-field sf-relation", { errors: $options.fieldErrors.length, 'sf-relation-multiple': $data.isMultiple, 'sf-relation-open': $data.dropdownVisible }]),
8853
9008
  ref: "root"
8854
9009
  }, [
8855
9010
  createBaseVNode("span", {
@@ -9196,8 +9351,6 @@ var script$2 = {
9196
9351
 
9197
9352
  script$2.__file = "src/editors/WebComponentWrapper.vue";
9198
9353
 
9199
- const MAX_DEPTH = 12;
9200
-
9201
9354
  var script$1 = {
9202
9355
  name: 'SchemaEditor',
9203
9356
  components: {
@@ -9607,5 +9760,5 @@ function registerCustomElement(tagName = 'schema-form') {
9607
9760
  }
9608
9761
  }
9609
9762
 
9610
- export { script$7 as ArrayEditor, BaseEditorElement, script$d as BooleanEditor, script$c as DateEditor, script$a as HiddenEditor, script$6 as NullableEditor, script$e as NumberEditor, script$8 as ObjectEditor, script$4 as RelationEditor, script$1 as SchemaEditor, script as SchemaForm, SchemaFormElement, script$b as SelectEditor, script$f as StringEditor, script$5 as UnionEditor, script$2 as WebComponentWrapper, applyConditionals, hasConditionals, matchesSchema, registerCustomElement };
9763
+ export { script$7 as ArrayEditor, BaseEditorElement, script$d as BooleanEditor, script$c as DateEditor, script$a as HiddenEditor, script$6 as NullableEditor, script$e as NumberEditor, script$8 as ObjectEditor, script$4 as RelationEditor, script$1 as SchemaEditor, script as SchemaForm, SchemaFormElement, script$b as SelectEditor, script$f as StringEditor, script$5 as UnionEditor, script$2 as WebComponentWrapper, applyConditionals, fieldSize, hasConditionals, layoutCells, matchesSchema, normalizeLayoutHint, registerCustomElement };
9611
9764
  //# sourceMappingURL=structured-widget-editor.esm.js.map