vira 31.18.0 → 31.18.2
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/elements/vira-json-form.element.js +195 -147
- package/dist/elements/vira-link.element.js +1 -1
- package/dist/elements/vira-text-area.element.js +1 -0
- package/dist/icons/icon-svgs/16/plus-16.icon.d.ts +8 -0
- package/dist/icons/icon-svgs/{plus-24.icon.js → 16/plus-16.icon.js} +7 -7
- package/dist/icons/index.d.ts +3 -0
- package/dist/icons/index.js +4 -0
- package/package.json +13 -13
- package/dist/icons/icon-svgs/plus-24.icon.d.ts +0 -8
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { assertWrap, check } from '@augment-vir/assert';
|
|
2
2
|
import { omitObjectKeys, wrapInTry } from '@augment-vir/common';
|
|
3
|
-
import { extractEventTarget } from '@augment-vir/web';
|
|
4
3
|
import { css, defineElementEvent, html, listen, nothing } from 'element-vir';
|
|
5
|
-
import {
|
|
4
|
+
import { Plus16Icon, X16Icon } from '../icons/index.js';
|
|
6
5
|
import { viraFontCssVars } from '../styles/font.js';
|
|
7
6
|
import { viraFormCssVars } from '../styles/form-styles.js';
|
|
8
7
|
import { ViraColorVariant, ViraEmphasis, ViraSize } from '../styles/form-variants.js';
|
|
@@ -13,6 +12,7 @@ import { ViraCheckbox } from './vira-checkbox.element.js';
|
|
|
13
12
|
import { ViraError } from './vira-error.element.js';
|
|
14
13
|
import { ViraInput, ViraInputType } from './vira-input.element.js';
|
|
15
14
|
import { ViraSelect } from './vira-select.element.js';
|
|
15
|
+
import { ViraTextArea } from './vira-text-area.element.js';
|
|
16
16
|
/**
|
|
17
17
|
* An editor for arbitrary JSON values, optionally constrained by a standard JSON Schema
|
|
18
18
|
* ({@link ViraJsonSchema}).
|
|
@@ -48,24 +48,10 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
48
48
|
justify-content: flex-end;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
.json-raw-textarea {
|
|
52
|
-
|
|
53
|
-
padding: 10px 12px;
|
|
54
|
-
border: 1px solid ${viraFormCssVars['vira-form-border-color'].value};
|
|
55
|
-
border-radius: ${viraFormCssVars['vira-form-wrapper-radius'].value};
|
|
56
|
-
background-color: ${viraFormCssVars['vira-form-background-color'].value};
|
|
57
|
-
color: ${viraFormCssVars['vira-form-foreground-color'].value};
|
|
51
|
+
${ViraTextArea}.json-raw-textarea {
|
|
52
|
+
width: 100%;
|
|
58
53
|
font-family: ${viraFontCssVars['vira-monospace'].value};
|
|
59
54
|
font-size: ${viraFormCssVars['vira-form-small-text-size'].value};
|
|
60
|
-
box-sizing: border-box;
|
|
61
|
-
width: 100%;
|
|
62
|
-
min-height: 240px;
|
|
63
|
-
resize: vertical;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.json-raw-textarea:focus {
|
|
67
|
-
outline: none;
|
|
68
|
-
border-color: ${viraFormCssVars['vira-form-focus-outline-color'].value};
|
|
69
55
|
}
|
|
70
56
|
|
|
71
57
|
.json-validation-errors {
|
|
@@ -80,73 +66,71 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
80
66
|
}
|
|
81
67
|
|
|
82
68
|
.json-group {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
border: 1px solid ${viraFormCssVars['vira-form-border-color'].value};
|
|
88
|
-
border-radius: ${viraFormCssVars['vira-form-wrapper-radius'].value};
|
|
89
|
-
background-color: ${viraFormCssVars['vira-form-background-color'].value};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
.json-group-header {
|
|
93
|
-
display: flex;
|
|
94
|
-
align-items: center;
|
|
95
|
-
gap: 8px;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
.json-group-header-title {
|
|
99
|
-
flex-grow: 1;
|
|
100
|
-
font-weight: ${viraFormCssVars['vira-form-label-font-weight'].value};
|
|
101
|
-
color: ${viraFormCssVars['vira-form-secondary-body-foreground'].value};
|
|
102
|
-
font-size: ${viraFormCssVars['vira-form-small-text-size'].value};
|
|
69
|
+
border-collapse: separate;
|
|
70
|
+
border-spacing: 0;
|
|
71
|
+
width: 100%;
|
|
72
|
+
box-sizing: border-box;
|
|
103
73
|
}
|
|
104
74
|
|
|
105
|
-
.json-
|
|
106
|
-
|
|
107
|
-
|
|
75
|
+
.json-group-nested {
|
|
76
|
+
margin-top: 4px;
|
|
77
|
+
padding-left: 12px;
|
|
78
|
+
padding-bottom: 8px;
|
|
79
|
+
border-left: 2px solid ${viraFormCssVars['vira-form-border-color'].value};
|
|
80
|
+
border-bottom: 2px solid ${viraFormCssVars['vira-form-border-color'].value};
|
|
108
81
|
}
|
|
109
82
|
|
|
110
|
-
.json-row-primitive {
|
|
111
|
-
|
|
83
|
+
.json-row-primitive > td {
|
|
84
|
+
padding: 4px 8px 4px 0;
|
|
85
|
+
vertical-align: middle;
|
|
112
86
|
}
|
|
113
87
|
|
|
114
|
-
.json-row-
|
|
115
|
-
|
|
88
|
+
.json-row-primitive > td:last-child {
|
|
89
|
+
padding-right: 0;
|
|
116
90
|
}
|
|
117
91
|
|
|
118
|
-
.json-row-label {
|
|
119
|
-
|
|
92
|
+
td.json-row-label {
|
|
93
|
+
text-align: left;
|
|
120
94
|
min-width: 80px;
|
|
95
|
+
white-space: nowrap;
|
|
121
96
|
font-weight: ${viraFormCssVars['vira-form-label-font-weight'].value};
|
|
122
|
-
word-break: break-word;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
.json-row-nested .json-row-label {
|
|
126
|
-
padding-top: 10px;
|
|
127
97
|
}
|
|
128
98
|
|
|
129
|
-
.json-row-editor {
|
|
130
|
-
|
|
131
|
-
min-width: 0;
|
|
132
|
-
display: flex;
|
|
133
|
-
flex-direction: column;
|
|
99
|
+
td.json-row-editor {
|
|
100
|
+
width: 100%;
|
|
134
101
|
}
|
|
135
102
|
|
|
136
|
-
.json-row-editor > * {
|
|
103
|
+
td.json-row-editor > * {
|
|
137
104
|
width: 100%;
|
|
138
105
|
max-width: 100%;
|
|
106
|
+
box-sizing: border-box;
|
|
139
107
|
}
|
|
140
108
|
|
|
141
|
-
.json-row-delete {
|
|
142
|
-
flex-shrink: 0;
|
|
109
|
+
td.json-row-delete {
|
|
143
110
|
width: 24px;
|
|
111
|
+
text-align: center;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.json-row-nested > td {
|
|
115
|
+
padding: 4px 0;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.json-row-nested-header {
|
|
144
119
|
display: flex;
|
|
145
|
-
|
|
120
|
+
align-items: center;
|
|
121
|
+
gap: 8px;
|
|
122
|
+
margin-bottom: 4px;
|
|
146
123
|
}
|
|
147
124
|
|
|
148
|
-
.json-row-nested .json-row-
|
|
149
|
-
|
|
125
|
+
.json-row-nested-header > .json-row-label {
|
|
126
|
+
flex-grow: 1;
|
|
127
|
+
font-weight: ${viraFormCssVars['vira-form-label-font-weight'].value};
|
|
128
|
+
word-break: break-word;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.json-type-tag {
|
|
132
|
+
font-weight: normal;
|
|
133
|
+
color: ${viraFormCssVars['vira-form-secondary-body-foreground'].value};
|
|
150
134
|
}
|
|
151
135
|
|
|
152
136
|
.json-value-with-switcher {
|
|
@@ -174,8 +158,10 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
174
158
|
.json-add-row {
|
|
175
159
|
display: flex;
|
|
176
160
|
align-items: center;
|
|
161
|
+
justify-content: flex-end;
|
|
177
162
|
gap: 6px;
|
|
178
163
|
flex-wrap: wrap;
|
|
164
|
+
padding: 8px 0;
|
|
179
165
|
}
|
|
180
166
|
|
|
181
167
|
.json-add-row ${ViraInput}, .json-add-row ${ViraSelect} {
|
|
@@ -195,12 +181,14 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
195
181
|
}
|
|
196
182
|
|
|
197
183
|
.json-empty-note {
|
|
184
|
+
display: block;
|
|
185
|
+
padding: 4px 0;
|
|
198
186
|
color: ${viraFormCssVars['vira-form-placeholder-color'].value};
|
|
199
187
|
font-style: italic;
|
|
200
188
|
font-size: ${viraFormCssVars['vira-form-small-text-size'].value};
|
|
201
189
|
}
|
|
202
190
|
`,
|
|
203
|
-
render({ inputs, state, dispatch, events, updateState }) {
|
|
191
|
+
render({ inputs, state, dispatch, events, updateState, host }) {
|
|
204
192
|
const isDisabled = !!inputs.isDisabled;
|
|
205
193
|
const resolveContext = createResolveContext(inputs.schema);
|
|
206
194
|
function jsonPrimitiveToString(entry) {
|
|
@@ -397,8 +385,9 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
397
385
|
function renderPlusButton({ isAddDisabled, tooltip, onClick, }) {
|
|
398
386
|
return html `
|
|
399
387
|
<${ViraButton.assign({
|
|
400
|
-
icon:
|
|
401
|
-
color: ViraColorVariant.
|
|
388
|
+
icon: Plus16Icon,
|
|
389
|
+
color: ViraColorVariant.Positive,
|
|
390
|
+
buttonSize: ViraSize.Small,
|
|
402
391
|
isDisabled: isAddDisabled,
|
|
403
392
|
})}
|
|
404
393
|
title=${tooltip}
|
|
@@ -411,7 +400,7 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
411
400
|
></${ViraButton}>
|
|
412
401
|
`;
|
|
413
402
|
}
|
|
414
|
-
function renderObjectAddControl({ pathKey, allowedTypes, canAdd, onAdd, }) {
|
|
403
|
+
function renderObjectAddControl({ pathKey, allowedTypes, canAdd, disabledReason, onAdd, }) {
|
|
415
404
|
if (allowedTypes.length === 0) {
|
|
416
405
|
return nothing;
|
|
417
406
|
}
|
|
@@ -420,7 +409,7 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
420
409
|
const onlyType = assertWrap.isDefined(allowedTypes[0]);
|
|
421
410
|
return renderPlusButton({
|
|
422
411
|
isAddDisabled,
|
|
423
|
-
tooltip: `Add ${viraJsonTypeLabels[onlyType]}`,
|
|
412
|
+
tooltip: isAddDisabled ? disabledReason : `Add ${viraJsonTypeLabels[onlyType]}`,
|
|
424
413
|
onClick: () => onAdd(onlyType),
|
|
425
414
|
});
|
|
426
415
|
}
|
|
@@ -442,7 +431,9 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
442
431
|
></${ViraSelect}>
|
|
443
432
|
${renderPlusButton({
|
|
444
433
|
isAddDisabled,
|
|
445
|
-
tooltip:
|
|
434
|
+
tooltip: isAddDisabled
|
|
435
|
+
? disabledReason
|
|
436
|
+
: `Add ${viraJsonTypeLabels[selectedType]}`,
|
|
446
437
|
onClick: () => onAdd(selectedType),
|
|
447
438
|
})}
|
|
448
439
|
`;
|
|
@@ -502,8 +493,14 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
502
493
|
})}
|
|
503
494
|
`;
|
|
504
495
|
}
|
|
505
|
-
function
|
|
496
|
+
function getNestedTypeLabel(schema, value) {
|
|
497
|
+
const concreteType = getJsonType(value);
|
|
498
|
+
const narrowedSchema = pickBranchForType(schema, concreteType, resolveContext);
|
|
499
|
+
return (getSchemaTitle(narrowedSchema, resolveContext) || viraJsonTypeLabels[concreteType]);
|
|
500
|
+
}
|
|
501
|
+
function renderObjectGroup(path, value, schema) {
|
|
506
502
|
const pathKey = pathToKey(path);
|
|
503
|
+
const isRoot = path.length === 0;
|
|
507
504
|
const requiredKeys = new Set(getRequiredProperties(schema, resolveContext));
|
|
508
505
|
const definedProperties = getDefinedProperties(schema, resolveContext);
|
|
509
506
|
const definedKeys = new Set(Object.keys(definedProperties));
|
|
@@ -529,20 +526,34 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
529
526
|
}
|
|
530
527
|
}
|
|
531
528
|
: undefined;
|
|
529
|
+
if (isChildNested) {
|
|
530
|
+
return html `
|
|
531
|
+
<tr class="json-row-nested">
|
|
532
|
+
<td colspan="3">
|
|
533
|
+
<div class="json-row-nested-header">
|
|
534
|
+
<span class="json-row-label">
|
|
535
|
+
${key}${isRequired ? '*' : ''}
|
|
536
|
+
<span class="json-type-tag">
|
|
537
|
+
: ${getNestedTypeLabel(childSchema, childValue)}
|
|
538
|
+
</span>
|
|
539
|
+
</span>
|
|
540
|
+
${childOnDelete ? renderDeleteButton(childOnDelete) : nothing}
|
|
541
|
+
</div>
|
|
542
|
+
${renderValue(childPath, childValue, childSchema)}
|
|
543
|
+
</td>
|
|
544
|
+
</tr>
|
|
545
|
+
`;
|
|
546
|
+
}
|
|
532
547
|
return html `
|
|
533
|
-
<
|
|
534
|
-
class="json-row
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
? renderDeleteButton(childOnDelete)
|
|
543
|
-
: nothing}
|
|
544
|
-
</span>
|
|
545
|
-
</div>
|
|
548
|
+
<tr class="json-row-primitive">
|
|
549
|
+
<td class="json-row-label">${key}${isRequired ? '*' : ''}</td>
|
|
550
|
+
<td class="json-row-editor">
|
|
551
|
+
${renderValue(childPath, childValue, childSchema)}
|
|
552
|
+
</td>
|
|
553
|
+
<td class="json-row-delete">
|
|
554
|
+
${childOnDelete ? renderDeleteButton(childOnDelete) : nothing}
|
|
555
|
+
</td>
|
|
556
|
+
</tr>
|
|
546
557
|
`;
|
|
547
558
|
});
|
|
548
559
|
const missingDefinedKeys = [...definedKeys].filter((key) => !(key in value));
|
|
@@ -555,8 +566,9 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
555
566
|
return html `
|
|
556
567
|
<${ViraButton.assign({
|
|
557
568
|
text: `"${key}"`,
|
|
558
|
-
icon:
|
|
559
|
-
color: ViraColorVariant.
|
|
569
|
+
icon: Plus16Icon,
|
|
570
|
+
color: ViraColorVariant.Positive,
|
|
571
|
+
buttonSize: ViraSize.Small,
|
|
560
572
|
})}
|
|
561
573
|
${listen('click', () => {
|
|
562
574
|
emitReplaceAt([
|
|
@@ -573,21 +585,27 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
573
585
|
const additionalAllowedTypes = additional.allowed
|
|
574
586
|
? getAllowedJsonTypes(additional.schema, resolveContext)
|
|
575
587
|
: [];
|
|
588
|
+
const arbitraryAddDisabledReason = trimmedPendingKey
|
|
589
|
+
? `Field "${trimmedPendingKey}" already exists.`
|
|
590
|
+
: 'Enter a field name to add.';
|
|
576
591
|
const arbitraryAddRow = additional.allowed && !isDisabled
|
|
577
592
|
? html `
|
|
578
|
-
<
|
|
579
|
-
|
|
593
|
+
<tr>
|
|
594
|
+
<td colspan="3">
|
|
595
|
+
<div class="json-add-row">
|
|
596
|
+
<${ViraInput.assign({
|
|
580
597
|
value: pendingKey,
|
|
581
598
|
placeholder: 'new field name',
|
|
582
599
|
})}
|
|
583
|
-
|
|
600
|
+
${listen(ViraInput.events.valueChange, (event) => {
|
|
584
601
|
setPendingKey(pathKey, event.detail);
|
|
585
602
|
})}
|
|
586
|
-
|
|
587
|
-
|
|
603
|
+
></${ViraInput}>
|
|
604
|
+
${renderObjectAddControl({
|
|
588
605
|
pathKey,
|
|
589
606
|
allowedTypes: additionalAllowedTypes,
|
|
590
607
|
canAdd: canAddArbitraryField,
|
|
608
|
+
disabledReason: arbitraryAddDisabledReason,
|
|
591
609
|
onAdd: (type) => {
|
|
592
610
|
if (!canAddArbitraryField) {
|
|
593
611
|
return;
|
|
@@ -599,33 +617,41 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
599
617
|
clearPending(pathKey);
|
|
600
618
|
},
|
|
601
619
|
})}
|
|
602
|
-
|
|
620
|
+
</div>
|
|
621
|
+
</td>
|
|
622
|
+
</tr>
|
|
603
623
|
`
|
|
604
624
|
: nothing;
|
|
605
|
-
const title = getSchemaTitle(schema, resolveContext) || 'object';
|
|
606
625
|
return html `
|
|
607
|
-
<
|
|
608
|
-
<
|
|
609
|
-
|
|
610
|
-
${onDelete ? renderDeleteButton(onDelete) : nothing}
|
|
611
|
-
</div>
|
|
612
|
-
${rowTemplates.length === 0 && suggestedKeyButtons.length === 0
|
|
626
|
+
<table class="json-group ${isRoot ? '' : 'json-group-nested'}">
|
|
627
|
+
<tbody>
|
|
628
|
+
${rowTemplates.length === 0 && suggestedKeyButtons.length === 0
|
|
613
629
|
? html `
|
|
614
|
-
|
|
615
|
-
|
|
630
|
+
<tr>
|
|
631
|
+
<td colspan="3">
|
|
632
|
+
<span class="json-empty-note">(empty object)</span>
|
|
633
|
+
</td>
|
|
634
|
+
</tr>
|
|
635
|
+
`
|
|
616
636
|
: nothing}
|
|
617
|
-
|
|
618
|
-
|
|
637
|
+
${rowTemplates}
|
|
638
|
+
${suggestedKeyButtons.length > 0
|
|
619
639
|
? html `
|
|
620
|
-
|
|
621
|
-
|
|
640
|
+
<tr>
|
|
641
|
+
<td colspan="3">
|
|
642
|
+
<div class="json-add-row">${suggestedKeyButtons}</div>
|
|
643
|
+
</td>
|
|
644
|
+
</tr>
|
|
645
|
+
`
|
|
622
646
|
: nothing}
|
|
623
|
-
|
|
624
|
-
|
|
647
|
+
${arbitraryAddRow}
|
|
648
|
+
</tbody>
|
|
649
|
+
</table>
|
|
625
650
|
`;
|
|
626
651
|
}
|
|
627
|
-
function renderArrayGroup(path, value, schema
|
|
652
|
+
function renderArrayGroup(path, value, schema) {
|
|
628
653
|
const pathKey = pathToKey(path);
|
|
654
|
+
const isRoot = path.length === 0;
|
|
629
655
|
const newItemSchema = getNewItemSchema(schema, value.length, resolveContext);
|
|
630
656
|
const allowedItemTypes = getAllowedJsonTypes(newItemSchema, resolveContext);
|
|
631
657
|
const rowTemplates = value.map((item, index) => {
|
|
@@ -641,28 +667,43 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
641
667
|
: () => {
|
|
642
668
|
emitDeleteAt(childPath);
|
|
643
669
|
};
|
|
670
|
+
if (isChildNested) {
|
|
671
|
+
return html `
|
|
672
|
+
<tr class="json-row-nested">
|
|
673
|
+
<td colspan="3">
|
|
674
|
+
<div class="json-row-nested-header">
|
|
675
|
+
<span class="json-row-label">
|
|
676
|
+
[${index}]
|
|
677
|
+
<span class="json-type-tag">
|
|
678
|
+
: ${getNestedTypeLabel(childSchema, item)}
|
|
679
|
+
</span>
|
|
680
|
+
</span>
|
|
681
|
+
${childOnDelete ? renderDeleteButton(childOnDelete) : nothing}
|
|
682
|
+
</div>
|
|
683
|
+
${renderValue(childPath, item, childSchema)}
|
|
684
|
+
</td>
|
|
685
|
+
</tr>
|
|
686
|
+
`;
|
|
687
|
+
}
|
|
644
688
|
return html `
|
|
645
|
-
<
|
|
646
|
-
class="json-row
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
? renderDeleteButton(childOnDelete)
|
|
655
|
-
: nothing}
|
|
656
|
-
</span>
|
|
657
|
-
</div>
|
|
689
|
+
<tr class="json-row-primitive">
|
|
690
|
+
<td class="json-row-label">[${index}]</td>
|
|
691
|
+
<td class="json-row-editor">
|
|
692
|
+
${renderValue(childPath, item, childSchema)}
|
|
693
|
+
</td>
|
|
694
|
+
<td class="json-row-delete">
|
|
695
|
+
${childOnDelete ? renderDeleteButton(childOnDelete) : nothing}
|
|
696
|
+
</td>
|
|
697
|
+
</tr>
|
|
658
698
|
`;
|
|
659
699
|
});
|
|
660
|
-
const title = getSchemaTitle(schema, resolveContext) || 'array';
|
|
661
700
|
const addRow = isDisabled
|
|
662
701
|
? nothing
|
|
663
702
|
: html `
|
|
664
|
-
<
|
|
665
|
-
|
|
703
|
+
<tr>
|
|
704
|
+
<td colspan="3">
|
|
705
|
+
<div class="json-add-row">
|
|
706
|
+
${renderArrayAddControl({
|
|
666
707
|
pathKey,
|
|
667
708
|
allowedTypes: allowedItemTypes,
|
|
668
709
|
onAdd: (newValue) => {
|
|
@@ -672,32 +713,36 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
672
713
|
], newValue);
|
|
673
714
|
},
|
|
674
715
|
})}
|
|
675
|
-
|
|
716
|
+
</div>
|
|
717
|
+
</td>
|
|
718
|
+
</tr>
|
|
676
719
|
`;
|
|
677
720
|
return html `
|
|
678
|
-
<
|
|
679
|
-
<
|
|
680
|
-
|
|
681
|
-
${onDelete ? renderDeleteButton(onDelete) : nothing}
|
|
682
|
-
</div>
|
|
683
|
-
${rowTemplates.length === 0
|
|
721
|
+
<table class="json-group ${isRoot ? '' : 'json-group-nested'}">
|
|
722
|
+
<tbody>
|
|
723
|
+
${rowTemplates.length === 0
|
|
684
724
|
? html `
|
|
685
|
-
|
|
686
|
-
|
|
725
|
+
<tr>
|
|
726
|
+
<td colspan="3">
|
|
727
|
+
<span class="json-empty-note">(empty array)</span>
|
|
728
|
+
</td>
|
|
729
|
+
</tr>
|
|
730
|
+
`
|
|
687
731
|
: nothing}
|
|
688
|
-
|
|
689
|
-
|
|
732
|
+
${rowTemplates} ${addRow}
|
|
733
|
+
</tbody>
|
|
734
|
+
</table>
|
|
690
735
|
`;
|
|
691
736
|
}
|
|
692
|
-
function renderValue(path, value, schema
|
|
737
|
+
function renderValue(path, value, schema) {
|
|
693
738
|
const concreteType = getJsonType(value);
|
|
694
739
|
const allowedTypes = getAllowedJsonTypes(schema, resolveContext);
|
|
695
740
|
const narrowedSchema = pickBranchForType(schema, concreteType, resolveContext);
|
|
696
741
|
if (check.isArray(value)) {
|
|
697
|
-
return renderArrayGroup(path, value, narrowedSchema
|
|
742
|
+
return renderArrayGroup(path, value, narrowedSchema);
|
|
698
743
|
}
|
|
699
744
|
else if (check.isObject(value)) {
|
|
700
|
-
return renderObjectGroup(path, value, narrowedSchema
|
|
745
|
+
return renderObjectGroup(path, value, narrowedSchema);
|
|
701
746
|
}
|
|
702
747
|
const editor = renderPrimitive(path, value, narrowedSchema);
|
|
703
748
|
const showSwitcher = !isDisabled &&
|
|
@@ -742,8 +787,10 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
742
787
|
})}
|
|
743
788
|
title=${state.showRaw ? 'Show rich editor' : 'Show raw JSON'}
|
|
744
789
|
${listen('click', () => {
|
|
790
|
+
const goingToRaw = !state.showRaw;
|
|
791
|
+
host.style.minWidth = goingToRaw ? `${host.offsetWidth}px` : '';
|
|
745
792
|
updateState({
|
|
746
|
-
showRaw:
|
|
793
|
+
showRaw: goingToRaw,
|
|
747
794
|
rawDraft: undefined,
|
|
748
795
|
rawError: undefined,
|
|
749
796
|
});
|
|
@@ -755,14 +802,15 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
755
802
|
const rawText = state.rawDraft ?? JSON.stringify(inputs.value, undefined, 4);
|
|
756
803
|
return html `
|
|
757
804
|
${toolbarTemplate}
|
|
758
|
-
|
|
805
|
+
<${ViraTextArea.assign({
|
|
806
|
+
value: rawText,
|
|
807
|
+
disabled: isDisabled,
|
|
808
|
+
disableBrowserHelps: true,
|
|
809
|
+
rows: 12,
|
|
810
|
+
})}
|
|
759
811
|
class="json-raw-textarea"
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
.value=${rawText}
|
|
763
|
-
${listen('input', (event) => {
|
|
764
|
-
const textarea = extractEventTarget(event, HTMLTextAreaElement);
|
|
765
|
-
const text = textarea.value;
|
|
812
|
+
${listen(ViraTextArea.events.valueChange, (event) => {
|
|
813
|
+
const text = event.detail;
|
|
766
814
|
const parsed = wrapInTry(() => JSON.parse(text));
|
|
767
815
|
if (parsed instanceof Error) {
|
|
768
816
|
updateState({
|
|
@@ -778,7 +826,7 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
778
826
|
emitRoot(parsed);
|
|
779
827
|
}
|
|
780
828
|
})}
|
|
781
|
-
|
|
829
|
+
></${ViraTextArea}>
|
|
782
830
|
${state.rawError
|
|
783
831
|
? html `
|
|
784
832
|
<${ViraError}>${state.rawError}</${ViraError}>
|
|
@@ -803,7 +851,7 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
803
851
|
`;
|
|
804
852
|
}
|
|
805
853
|
return html `
|
|
806
|
-
${toolbarTemplate} ${renderValue([], inputs.value, inputs.schema
|
|
854
|
+
${toolbarTemplate} ${renderValue([], inputs.value, inputs.schema)}
|
|
807
855
|
`;
|
|
808
856
|
},
|
|
809
857
|
});
|
|
@@ -112,7 +112,7 @@ export const ViraLink = defineViraElement()({
|
|
|
112
112
|
else {
|
|
113
113
|
const linkUrl = inputs.link
|
|
114
114
|
? inputs.link.url
|
|
115
|
-
: inputs.route.router.createRouteUrl(inputs.route.route);
|
|
115
|
+
: inputs.route.router.createRouteUrl(inputs.route.route).url;
|
|
116
116
|
/** Noopener and noreferrer are needed for security reasons, do not remove! */
|
|
117
117
|
return html `
|
|
118
118
|
<a
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { html } from 'element-vir';
|
|
2
|
-
import { viraIconCssVars } from '
|
|
3
|
-
import { defineIcon } from '
|
|
2
|
+
import { viraIconCssVars } from '../../icon-css-vars.js';
|
|
3
|
+
import { defineIcon } from '../../icon-svg.js';
|
|
4
4
|
/**
|
|
5
5
|
* A plus icon.
|
|
6
6
|
*
|
|
7
7
|
* @category Icon
|
|
8
8
|
* @category SVG
|
|
9
|
-
* @see https://electrovir.github.io/vira/book/icons/
|
|
9
|
+
* @see https://electrovir.github.io/vira/book/icons/plus16icon
|
|
10
10
|
*/
|
|
11
|
-
export const
|
|
12
|
-
name: '
|
|
11
|
+
export const Plus16Icon = defineIcon({
|
|
12
|
+
name: 'Plus16Icon',
|
|
13
13
|
svgTemplate: html `
|
|
14
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="
|
|
14
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
|
15
15
|
<path
|
|
16
|
-
d="
|
|
16
|
+
d="M8 3v10M3 8h10"
|
|
17
17
|
fill="none"
|
|
18
18
|
stroke=${viraIconCssVars['vira-icon-stroke-color'].value}
|
|
19
19
|
stroke-width=${viraIconCssVars['vira-icon-stroke-width'].value}
|
package/dist/icons/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from './icon-svgs/16/chevron-down-16.icon.js';
|
|
|
8
8
|
export * from './icon-svgs/16/chevron-up-16.icon.js';
|
|
9
9
|
export * from './icon-svgs/16/dash-16.icon.js';
|
|
10
10
|
export * from './icon-svgs/16/element-16.icon.js';
|
|
11
|
+
export * from './icon-svgs/16/plus-16.icon.js';
|
|
11
12
|
export * from './icon-svgs/16/upload-16.icon.js';
|
|
12
13
|
export * from './icon-svgs/16/x-16.icon.js';
|
|
13
14
|
export * from './icon-svgs/24/arrow-down-24.icon.js';
|
|
@@ -100,6 +101,7 @@ export declare const allIconsByName: {
|
|
|
100
101
|
readonly Moon24Icon: import("./icon-svg.js").ViraIconSvg;
|
|
101
102
|
readonly Options24Icon: import("./icon-svg.js").ViraIconSvg;
|
|
102
103
|
readonly Pencil24Icon: import("./icon-svg.js").ViraIconSvg;
|
|
104
|
+
readonly Plus16Icon: import("./icon-svg.js").ViraIconSvg;
|
|
103
105
|
readonly Plus24Icon: import("./icon-svg.js").ViraIconSvg;
|
|
104
106
|
readonly Printer24Icon: import("./icon-svg.js").ViraIconSvg;
|
|
105
107
|
readonly Shield24Icon: import("./icon-svg.js").ViraIconSvg;
|
|
@@ -189,6 +191,7 @@ export declare const all16IconsByName: {
|
|
|
189
191
|
readonly ChevronUp16Icon: import("./icon-svg.js").ViraIconSvg;
|
|
190
192
|
readonly Dash16Icon: import("./icon-svg.js").ViraIconSvg;
|
|
191
193
|
readonly Element16Icon: import("./icon-svg.js").ViraIconSvg;
|
|
194
|
+
readonly Plus16Icon: import("./icon-svg.js").ViraIconSvg;
|
|
192
195
|
readonly Upload16Icon: import("./icon-svg.js").ViraIconSvg;
|
|
193
196
|
readonly X16Icon: import("./icon-svg.js").ViraIconSvg;
|
|
194
197
|
};
|
package/dist/icons/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { ChevronDown16Icon } from './icon-svgs/16/chevron-down-16.icon.js';
|
|
|
3
3
|
import { ChevronUp16Icon } from './icon-svgs/16/chevron-up-16.icon.js';
|
|
4
4
|
import { Dash16Icon } from './icon-svgs/16/dash-16.icon.js';
|
|
5
5
|
import { Element16Icon } from './icon-svgs/16/element-16.icon.js';
|
|
6
|
+
import { Plus16Icon } from './icon-svgs/16/plus-16.icon.js';
|
|
6
7
|
import { Upload16Icon } from './icon-svgs/16/upload-16.icon.js';
|
|
7
8
|
import { X16Icon } from './icon-svgs/16/x-16.icon.js';
|
|
8
9
|
import { ArrowDown24Icon } from './icon-svgs/24/arrow-down-24.icon.js';
|
|
@@ -64,6 +65,7 @@ export * from './icon-svgs/16/chevron-down-16.icon.js';
|
|
|
64
65
|
export * from './icon-svgs/16/chevron-up-16.icon.js';
|
|
65
66
|
export * from './icon-svgs/16/dash-16.icon.js';
|
|
66
67
|
export * from './icon-svgs/16/element-16.icon.js';
|
|
68
|
+
export * from './icon-svgs/16/plus-16.icon.js';
|
|
67
69
|
export * from './icon-svgs/16/upload-16.icon.js';
|
|
68
70
|
export * from './icon-svgs/16/x-16.icon.js';
|
|
69
71
|
export * from './icon-svgs/24/arrow-down-24.icon.js';
|
|
@@ -156,6 +158,7 @@ export const allIconsByName = {
|
|
|
156
158
|
Moon24Icon,
|
|
157
159
|
Options24Icon,
|
|
158
160
|
Pencil24Icon,
|
|
161
|
+
Plus16Icon,
|
|
159
162
|
Plus24Icon,
|
|
160
163
|
Printer24Icon,
|
|
161
164
|
Shield24Icon,
|
|
@@ -245,6 +248,7 @@ export const all16IconsByName = {
|
|
|
245
248
|
ChevronUp16Icon,
|
|
246
249
|
Dash16Icon,
|
|
247
250
|
Element16Icon,
|
|
251
|
+
Plus16Icon,
|
|
248
252
|
Upload16Icon,
|
|
249
253
|
X16Icon,
|
|
250
254
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vira",
|
|
3
|
-
"version": "31.18.
|
|
3
|
+
"version": "31.18.2",
|
|
4
4
|
"description": "A simple and highly versatile design system using element-vir.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"design",
|
|
@@ -38,35 +38,35 @@
|
|
|
38
38
|
"test:docs": "virmator docs check"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@augment-vir/assert": "^31.
|
|
42
|
-
"@augment-vir/common": "^31.
|
|
43
|
-
"@augment-vir/web": "^31.
|
|
41
|
+
"@augment-vir/assert": "^31.69.0",
|
|
42
|
+
"@augment-vir/common": "^31.69.0",
|
|
43
|
+
"@augment-vir/web": "^31.69.0",
|
|
44
44
|
"@electrovir/color": "^1.7.9",
|
|
45
|
-
"date-vir": "^8.2
|
|
45
|
+
"date-vir": "^8.3.2",
|
|
46
46
|
"device-navigation": "^4.5.5",
|
|
47
47
|
"json-schema-to-ts": "^3.1.1",
|
|
48
48
|
"lit-css-vars": "^3.6.2",
|
|
49
49
|
"observavir": "^2.3.2",
|
|
50
50
|
"page-active": "^1.0.3",
|
|
51
|
-
"spa-router-vir": "^6.
|
|
52
|
-
"type-fest": "^5.
|
|
51
|
+
"spa-router-vir": "^6.5.0",
|
|
52
|
+
"type-fest": "^5.6.0",
|
|
53
53
|
"typed-event-target": "^4.3.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@augment-vir/test": "^31.
|
|
56
|
+
"@augment-vir/test": "^31.69.0",
|
|
57
57
|
"@web/dev-server-esbuild": "^1.0.5",
|
|
58
58
|
"@web/test-runner": "^0.20.2",
|
|
59
59
|
"@web/test-runner-commands": "^0.9.0",
|
|
60
60
|
"@web/test-runner-playwright": "^0.11.1",
|
|
61
61
|
"@web/test-runner-visual-regression": "^0.10.0",
|
|
62
|
-
"esbuild": "^0.
|
|
62
|
+
"esbuild": "^0.28.0",
|
|
63
63
|
"istanbul-smart-text-reporter": "^1.1.5",
|
|
64
|
-
"lucide-static": "^1.
|
|
65
|
-
"markdown-code-example-inserter": "^3.0.
|
|
64
|
+
"lucide-static": "^1.14.0",
|
|
65
|
+
"markdown-code-example-inserter": "^3.0.5",
|
|
66
66
|
"theme-vir": "^28.25.0",
|
|
67
|
-
"typedoc": "^0.28.
|
|
67
|
+
"typedoc": "^0.28.19",
|
|
68
68
|
"typescript": "5.9.3",
|
|
69
|
-
"vite": "^8.0.
|
|
69
|
+
"vite": "^8.0.10",
|
|
70
70
|
"vite-tsconfig-paths": "^6.1.1"
|
|
71
71
|
},
|
|
72
72
|
"peerDependencies": {
|