@structured-field/widget-editor 1.2.2 → 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 +51 -0
- package/dist/structured-widget-editor.css +1 -1
- package/dist/structured-widget-editor.esm.js +470 -125
- package/dist/structured-widget-editor.esm.js.map +1 -1
- package/dist/structured-widget-editor.iife.js +5 -5
- package/dist/structured-widget-editor.js +4 -4
- package/dist/structured-widget-editor.js.map +1 -1
- package/package.json +8 -2
- package/src/SchemaForm.vue +20 -13
- package/src/editors/DateEditor.vue +95 -0
- package/src/editors/ObjectEditor.vue +49 -18
- package/src/editors/RelationEditor.vue +1 -1
- package/src/editors/SchemaEditor.vue +8 -2
- package/src/editors/SelectEditor.vue +28 -5
- package/src/index.js +2 -0
- package/src/layout.js +116 -0
- package/src/scss/components/layout.scss +76 -0
- package/src/scss/main.scss +1 -0
- package/src/utils.js +18 -0
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)}}}
|