vira 31.17.1 → 31.18.1
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/index.d.ts +1 -0
- package/dist/elements/index.js +1 -0
- package/dist/elements/vira-form.element.js +23 -0
- package/dist/elements/vira-json-form.element.d.ts +2 -0
- package/dist/elements/vira-json-form.element.js +54 -17
- package/dist/elements/vira-link.element.js +1 -1
- package/dist/elements/vira-text-area.element.d.ts +47 -0
- package/dist/elements/vira-text-area.element.js +201 -0
- package/dist/util/shared-text-input-logic.d.ts +6 -1
- package/dist/util/shared-text-input-logic.js +2 -2
- package/dist/util/vira-form-fields.d.ts +9 -1
- package/dist/util/vira-form-fields.js +1 -0
- package/package.json +13 -13
package/dist/elements/index.d.ts
CHANGED
package/dist/elements/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { applyRequiredLabel, areFormFieldsValid, ViraFormFieldType, } from '../u
|
|
|
5
5
|
import { ViraCheckbox } from './vira-checkbox.element.js';
|
|
6
6
|
import { ViraInput, ViraInputType } from './vira-input.element.js';
|
|
7
7
|
import { ViraSelect } from './vira-select.element.js';
|
|
8
|
+
import { ViraTextArea } from './vira-text-area.element.js';
|
|
8
9
|
/**
|
|
9
10
|
* A form element.
|
|
10
11
|
*
|
|
@@ -95,6 +96,28 @@ export const ViraForm = defineViraElement()({
|
|
|
95
96
|
></${ViraSelect}>
|
|
96
97
|
`;
|
|
97
98
|
}
|
|
99
|
+
else if (field.type === ViraFormFieldType.TextArea) {
|
|
100
|
+
return html `
|
|
101
|
+
<${ViraTextArea.assign({
|
|
102
|
+
value: field.value || '',
|
|
103
|
+
disabled: inputs.isDisabled || field.isDisabled,
|
|
104
|
+
hasError: field.hasError,
|
|
105
|
+
label: applyRequiredLabel(field.label, !!field.isRequired && !inputs.hideRequiredMarkers),
|
|
106
|
+
placeholder: field.placeholder,
|
|
107
|
+
rows: field.rows,
|
|
108
|
+
preventResize: field.preventResize,
|
|
109
|
+
})}
|
|
110
|
+
${field.testId ? testId(field.testId) : nothing}
|
|
111
|
+
${listen(ViraTextArea.events.valueChange, (event) => {
|
|
112
|
+
dispatch(new events.valueChange({
|
|
113
|
+
key,
|
|
114
|
+
...field,
|
|
115
|
+
value: event.detail,
|
|
116
|
+
}));
|
|
117
|
+
})}
|
|
118
|
+
></${ViraTextArea}>
|
|
119
|
+
`;
|
|
120
|
+
}
|
|
98
121
|
else if (field.type === ViraFormFieldType.Number) {
|
|
99
122
|
return html `
|
|
100
123
|
<${ViraInput.assign({
|
|
@@ -17,6 +17,8 @@ export declare const ViraJsonForm: import("element-vir").DeclarativeElementDefin
|
|
|
17
17
|
pendingTypes: Readonly<Record<string, ViraJsonType>>;
|
|
18
18
|
pendingArrayValues: Readonly<Record<string, JsonValue>>;
|
|
19
19
|
showRaw: boolean;
|
|
20
|
+
rawDraft: string | undefined;
|
|
21
|
+
rawError: string | undefined;
|
|
20
22
|
}, {
|
|
21
23
|
valueChange: import("element-vir").DefineEvent<JsonValue>;
|
|
22
24
|
}, "vira-json-form-", "vira-json-form-", readonly [], readonly []>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { assertWrap, check } from '@augment-vir/assert';
|
|
2
|
-
import { omitObjectKeys } from '@augment-vir/common';
|
|
2
|
+
import { omitObjectKeys, wrapInTry } from '@augment-vir/common';
|
|
3
|
+
import { extractEventTarget } from '@augment-vir/web';
|
|
3
4
|
import { css, defineElementEvent, html, listen, nothing } from 'element-vir';
|
|
4
5
|
import { lucideIcons, X16Icon } from '../icons/index.js';
|
|
5
6
|
import { viraFontCssVars } from '../styles/font.js';
|
|
@@ -29,6 +30,8 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
29
30
|
pendingTypes: {},
|
|
30
31
|
pendingArrayValues: {},
|
|
31
32
|
showRaw: false,
|
|
33
|
+
rawDraft: undefined,
|
|
34
|
+
rawError: undefined,
|
|
32
35
|
};
|
|
33
36
|
},
|
|
34
37
|
styles: css `
|
|
@@ -45,18 +48,24 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
45
48
|
justify-content: flex-end;
|
|
46
49
|
}
|
|
47
50
|
|
|
48
|
-
.json-raw-
|
|
51
|
+
.json-raw-textarea {
|
|
49
52
|
margin: 0;
|
|
50
53
|
padding: 10px 12px;
|
|
51
54
|
border: 1px solid ${viraFormCssVars['vira-form-border-color'].value};
|
|
52
55
|
border-radius: ${viraFormCssVars['vira-form-wrapper-radius'].value};
|
|
53
56
|
background-color: ${viraFormCssVars['vira-form-background-color'].value};
|
|
57
|
+
color: ${viraFormCssVars['vira-form-foreground-color'].value};
|
|
54
58
|
font-family: ${viraFontCssVars['vira-monospace'].value};
|
|
55
59
|
font-size: ${viraFormCssVars['vira-form-small-text-size'].value};
|
|
56
|
-
white-space: pre-wrap;
|
|
57
|
-
word-break: break-word;
|
|
58
|
-
overflow-x: auto;
|
|
59
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};
|
|
60
69
|
}
|
|
61
70
|
|
|
62
71
|
.json-validation-errors {
|
|
@@ -78,6 +87,7 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
78
87
|
border: 1px solid ${viraFormCssVars['vira-form-border-color'].value};
|
|
79
88
|
border-radius: ${viraFormCssVars['vira-form-wrapper-radius'].value};
|
|
80
89
|
background-color: ${viraFormCssVars['vira-form-background-color'].value};
|
|
90
|
+
box-sizing: border-box;
|
|
81
91
|
}
|
|
82
92
|
|
|
83
93
|
.json-group-header {
|
|
@@ -103,7 +113,9 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
103
113
|
}
|
|
104
114
|
|
|
105
115
|
.json-row-nested {
|
|
106
|
-
|
|
116
|
+
flex-direction: column;
|
|
117
|
+
align-items: stretch;
|
|
118
|
+
gap: 4px;
|
|
107
119
|
}
|
|
108
120
|
|
|
109
121
|
.json-row-label {
|
|
@@ -113,10 +125,6 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
113
125
|
word-break: break-word;
|
|
114
126
|
}
|
|
115
127
|
|
|
116
|
-
.json-row-nested .json-row-label {
|
|
117
|
-
padding-top: 10px;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
128
|
.json-row-editor {
|
|
121
129
|
flex-grow: 1;
|
|
122
130
|
min-width: 0;
|
|
@@ -136,10 +144,6 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
136
144
|
justify-content: center;
|
|
137
145
|
}
|
|
138
146
|
|
|
139
|
-
.json-row-nested .json-row-delete {
|
|
140
|
-
padding-top: 4px;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
147
|
.json-value-with-switcher {
|
|
144
148
|
display: flex;
|
|
145
149
|
align-items: center;
|
|
@@ -191,7 +195,7 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
191
195
|
font-size: ${viraFormCssVars['vira-form-small-text-size'].value};
|
|
192
196
|
}
|
|
193
197
|
`,
|
|
194
|
-
render({ inputs, state, dispatch, events, updateState }) {
|
|
198
|
+
render({ inputs, state, dispatch, events, updateState, host }) {
|
|
195
199
|
const isDisabled = !!inputs.isDisabled;
|
|
196
200
|
const resolveContext = createResolveContext(inputs.schema);
|
|
197
201
|
function jsonPrimitiveToString(entry) {
|
|
@@ -733,17 +737,50 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
733
737
|
})}
|
|
734
738
|
title=${state.showRaw ? 'Show rich editor' : 'Show raw JSON'}
|
|
735
739
|
${listen('click', () => {
|
|
740
|
+
const goingToRaw = !state.showRaw;
|
|
741
|
+
host.style.minWidth = goingToRaw ? `${host.offsetWidth}px` : '';
|
|
736
742
|
updateState({
|
|
737
|
-
showRaw:
|
|
743
|
+
showRaw: goingToRaw,
|
|
744
|
+
rawDraft: undefined,
|
|
745
|
+
rawError: undefined,
|
|
738
746
|
});
|
|
739
747
|
})}
|
|
740
748
|
></${ViraButton}>
|
|
741
749
|
</div>
|
|
742
750
|
`;
|
|
743
751
|
if (state.showRaw) {
|
|
752
|
+
const rawText = state.rawDraft ?? JSON.stringify(inputs.value, undefined, 4);
|
|
744
753
|
return html `
|
|
745
754
|
${toolbarTemplate}
|
|
746
|
-
<
|
|
755
|
+
<textarea
|
|
756
|
+
class="json-raw-textarea"
|
|
757
|
+
spellcheck="false"
|
|
758
|
+
?disabled=${isDisabled}
|
|
759
|
+
.value=${rawText}
|
|
760
|
+
${listen('input', (event) => {
|
|
761
|
+
const textarea = extractEventTarget(event, HTMLTextAreaElement);
|
|
762
|
+
const text = textarea.value;
|
|
763
|
+
const parsed = wrapInTry(() => JSON.parse(text));
|
|
764
|
+
if (parsed instanceof Error) {
|
|
765
|
+
updateState({
|
|
766
|
+
rawDraft: text,
|
|
767
|
+
rawError: parsed.message,
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
else {
|
|
771
|
+
updateState({
|
|
772
|
+
rawDraft: text,
|
|
773
|
+
rawError: undefined,
|
|
774
|
+
});
|
|
775
|
+
emitRoot(parsed);
|
|
776
|
+
}
|
|
777
|
+
})}
|
|
778
|
+
></textarea>
|
|
779
|
+
${state.rawError
|
|
780
|
+
? html `
|
|
781
|
+
<${ViraError}>${state.rawError}</${ViraError}>
|
|
782
|
+
`
|
|
783
|
+
: nothing}
|
|
747
784
|
`;
|
|
748
785
|
}
|
|
749
786
|
const validationErrors = validateAgainstSchema(inputs.value, inputs.schema);
|
|
@@ -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
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type PartialWithUndefined } from '@augment-vir/common';
|
|
2
|
+
/**
|
|
3
|
+
* A multi-line text area element with all listeners properly attached. Mirrors the look and feel of
|
|
4
|
+
* {@link ViraInput} but for multi-line text input.
|
|
5
|
+
*
|
|
6
|
+
* @category Input
|
|
7
|
+
* @category Elements
|
|
8
|
+
* @see https://electrovir.github.io/vira/book/elements/vira-text-area
|
|
9
|
+
*/
|
|
10
|
+
export declare const ViraTextArea: import("element-vir").DeclarativeElementDefinition<"vira-text-area", PartialWithUndefined<{
|
|
11
|
+
/** A label that is shown above the text area, if provided. */
|
|
12
|
+
label: string;
|
|
13
|
+
/** If true, applies error styling. */
|
|
14
|
+
hasError: boolean;
|
|
15
|
+
/** Number of visible text rows. Defaults to 4. */
|
|
16
|
+
rows: number;
|
|
17
|
+
/** If true, blocks the user's ability to resize the text area. */
|
|
18
|
+
preventResize: boolean;
|
|
19
|
+
}> & {
|
|
20
|
+
value: string;
|
|
21
|
+
} & PartialWithUndefined<{
|
|
22
|
+
placeholder: string;
|
|
23
|
+
disabled: boolean;
|
|
24
|
+
allowedInputs: string | RegExp;
|
|
25
|
+
blockedInputs: string | RegExp;
|
|
26
|
+
disableBrowserHelps: boolean;
|
|
27
|
+
fitText: boolean;
|
|
28
|
+
attributePassthrough: import("element-vir").AttributeValues;
|
|
29
|
+
}>, {
|
|
30
|
+
/**
|
|
31
|
+
* Used to couple the label and text area together. This is not applied if no label is
|
|
32
|
+
* provided.
|
|
33
|
+
*/
|
|
34
|
+
randomId: string;
|
|
35
|
+
}, {
|
|
36
|
+
/**
|
|
37
|
+
* Fires whenever a user input created a new value. Does not fire if all input letters are
|
|
38
|
+
* filtered out due to input restrictions.
|
|
39
|
+
*/
|
|
40
|
+
valueChange: import("element-vir").DefineEvent<string>;
|
|
41
|
+
/**
|
|
42
|
+
* Fires when inputs are blocked. Useful for showing warnings or error messages to inform
|
|
43
|
+
* the user why their input did not propagate if it was blocked. This does not fire for text
|
|
44
|
+
* that was blocked out of programmatic "value" property assignments.
|
|
45
|
+
*/
|
|
46
|
+
inputBlocked: import("element-vir").DefineEvent<string>;
|
|
47
|
+
}, "vira-text-area-disabled" | "vira-text-area-error" | "vira-text-area-prevent-resize", "vira-text-area-padding-horizontal" | "vira-text-area-padding-vertical", readonly [], readonly []>;
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { randomString } from '@augment-vir/common';
|
|
2
|
+
import { attributes, css, defineElementEvent, html, ifDefined, listen } from 'element-vir';
|
|
3
|
+
import { createFocusStyles } from '../styles/focus.js';
|
|
4
|
+
import { viraFormCssVars } from '../styles/form-styles.js';
|
|
5
|
+
import { viraDisabledStyles } from '../styles/index.js';
|
|
6
|
+
import { noNativeFormStyles } from '../styles/native-styles.js';
|
|
7
|
+
import { defineViraElement } from '../util/define-vira-element.js';
|
|
8
|
+
import { filterTextInputValue, textInputListener, } from '../util/shared-text-input-logic.js';
|
|
9
|
+
/**
|
|
10
|
+
* A multi-line text area element with all listeners properly attached. Mirrors the look and feel of
|
|
11
|
+
* {@link ViraInput} but for multi-line text input.
|
|
12
|
+
*
|
|
13
|
+
* @category Input
|
|
14
|
+
* @category Elements
|
|
15
|
+
* @see https://electrovir.github.io/vira/book/elements/vira-text-area
|
|
16
|
+
*/
|
|
17
|
+
export const ViraTextArea = defineViraElement()({
|
|
18
|
+
tagName: 'vira-text-area',
|
|
19
|
+
cssVars: {
|
|
20
|
+
'vira-text-area-padding-horizontal': '10px',
|
|
21
|
+
'vira-text-area-padding-vertical': '6px',
|
|
22
|
+
},
|
|
23
|
+
styles: ({ hostClasses, cssVars }) => css `
|
|
24
|
+
:host {
|
|
25
|
+
position: relative;
|
|
26
|
+
display: inline-flex;
|
|
27
|
+
width: 320px;
|
|
28
|
+
box-sizing: border-box;
|
|
29
|
+
color: ${viraFormCssVars['vira-form-foreground-color'].value};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
label {
|
|
33
|
+
display: flex;
|
|
34
|
+
flex-direction: column;
|
|
35
|
+
justify-content: flex-start;
|
|
36
|
+
gap: 2px;
|
|
37
|
+
width: 100%;
|
|
38
|
+
max-width: 100%;
|
|
39
|
+
cursor: text;
|
|
40
|
+
|
|
41
|
+
& .text-area-label {
|
|
42
|
+
font-weight: ${viraFormCssVars['vira-form-label-font-weight'].value};
|
|
43
|
+
text-align: left;
|
|
44
|
+
flex-shrink: 0;
|
|
45
|
+
flex-wrap: wrap;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.text-area-wrapper {
|
|
50
|
+
position: relative;
|
|
51
|
+
display: inline-flex;
|
|
52
|
+
width: 100%;
|
|
53
|
+
max-width: 100%;
|
|
54
|
+
box-sizing: border-box;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
textarea {
|
|
58
|
+
${noNativeFormStyles};
|
|
59
|
+
font: inherit;
|
|
60
|
+
cursor: text;
|
|
61
|
+
width: 100%;
|
|
62
|
+
box-sizing: border-box;
|
|
63
|
+
padding: ${cssVars['vira-text-area-padding-vertical'].value}
|
|
64
|
+
${cssVars['vira-text-area-padding-horizontal'].value};
|
|
65
|
+
border-radius: ${viraFormCssVars['vira-form-radius'].value};
|
|
66
|
+
background-color: ${viraFormCssVars['vira-form-background-color'].value};
|
|
67
|
+
border: 1px solid ${viraFormCssVars['vira-form-border-color'].value};
|
|
68
|
+
color: inherit;
|
|
69
|
+
resize: vertical;
|
|
70
|
+
outline: none;
|
|
71
|
+
|
|
72
|
+
&::placeholder {
|
|
73
|
+
color: ${viraFormCssVars['vira-form-placeholder-color'].value};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
&::selection {
|
|
77
|
+
background: ${viraFormCssVars['vira-form-text-selection-color'].value};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
&:focus:focus-visible:not([disabled]) ~ .focus-border {
|
|
81
|
+
${createFocusStyles({
|
|
82
|
+
elementBorderSize: '1px',
|
|
83
|
+
noNesting: true,
|
|
84
|
+
})}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.border-style {
|
|
89
|
+
position: absolute;
|
|
90
|
+
top: 0;
|
|
91
|
+
left: 0;
|
|
92
|
+
width: 100%;
|
|
93
|
+
height: 100%;
|
|
94
|
+
border-radius: ${viraFormCssVars['vira-form-radius'].value};
|
|
95
|
+
z-index: 0;
|
|
96
|
+
pointer-events: none;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
${hostClasses['vira-text-area-prevent-resize'].selector} textarea {
|
|
100
|
+
resize: none;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
${hostClasses['vira-text-area-error'].selector} textarea {
|
|
104
|
+
border-color: ${viraFormCssVars['vira-form-error-color'].value};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
${hostClasses['vira-text-area-disabled'].selector} {
|
|
108
|
+
cursor: not-allowed;
|
|
109
|
+
|
|
110
|
+
& * {
|
|
111
|
+
cursor: not-allowed;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
& > * {
|
|
115
|
+
${viraDisabledStyles};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
& .focus-border {
|
|
119
|
+
display: none;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
`,
|
|
123
|
+
events: {
|
|
124
|
+
/**
|
|
125
|
+
* Fires whenever a user input created a new value. Does not fire if all input letters are
|
|
126
|
+
* filtered out due to input restrictions.
|
|
127
|
+
*/
|
|
128
|
+
valueChange: defineElementEvent(),
|
|
129
|
+
/**
|
|
130
|
+
* Fires when inputs are blocked. Useful for showing warnings or error messages to inform
|
|
131
|
+
* the user why their input did not propagate if it was blocked. This does not fire for text
|
|
132
|
+
* that was blocked out of programmatic "value" property assignments.
|
|
133
|
+
*/
|
|
134
|
+
inputBlocked: defineElementEvent(),
|
|
135
|
+
},
|
|
136
|
+
state() {
|
|
137
|
+
return {
|
|
138
|
+
/**
|
|
139
|
+
* Used to couple the label and text area together. This is not applied if no label is
|
|
140
|
+
* provided.
|
|
141
|
+
*/
|
|
142
|
+
randomId: randomString(32),
|
|
143
|
+
};
|
|
144
|
+
},
|
|
145
|
+
hostClasses: {
|
|
146
|
+
'vira-text-area-disabled': ({ inputs }) => !!inputs.disabled,
|
|
147
|
+
'vira-text-area-error': ({ inputs }) => !!inputs.hasError,
|
|
148
|
+
'vira-text-area-prevent-resize': ({ inputs }) => !!inputs.preventResize || !!inputs.disabled,
|
|
149
|
+
},
|
|
150
|
+
render({ inputs, dispatch, state, events }) {
|
|
151
|
+
const { filtered: filteredValue } = filterTextInputValue({
|
|
152
|
+
value: inputs.value,
|
|
153
|
+
allowed: inputs.allowedInputs,
|
|
154
|
+
blocked: inputs.blockedInputs,
|
|
155
|
+
});
|
|
156
|
+
const textAreaTemplate = html `
|
|
157
|
+
<span class="text-area-wrapper">
|
|
158
|
+
<textarea
|
|
159
|
+
id=${ifDefined(inputs.label ? state.randomId : undefined)}
|
|
160
|
+
aria-label=${ifDefined(inputs.label || undefined)}
|
|
161
|
+
rows=${inputs.rows ?? 4}
|
|
162
|
+
?disabled=${inputs.disabled}
|
|
163
|
+
autocomplete=${ifDefined(inputs.disableBrowserHelps ? 'off' : undefined)}
|
|
164
|
+
autocorrect=${ifDefined(inputs.disableBrowserHelps ? 'off' : undefined)}
|
|
165
|
+
autocapitalize=${ifDefined(inputs.disableBrowserHelps ? 'off' : undefined)}
|
|
166
|
+
spellcheck=${ifDefined(inputs.disableBrowserHelps ? 'false' : undefined)}
|
|
167
|
+
placeholder=${ifDefined(inputs.placeholder || undefined)}
|
|
168
|
+
.value=${filteredValue}
|
|
169
|
+
${listen('input', (event) => {
|
|
170
|
+
textInputListener({
|
|
171
|
+
inputs,
|
|
172
|
+
previousValue: filteredValue,
|
|
173
|
+
event,
|
|
174
|
+
elementConstructor: HTMLTextAreaElement,
|
|
175
|
+
inputBlockedCallback(blockedInput) {
|
|
176
|
+
dispatch(new events.inputBlocked(blockedInput));
|
|
177
|
+
},
|
|
178
|
+
newValueCallback(newValue) {
|
|
179
|
+
dispatch(new events.valueChange(newValue));
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
})}
|
|
183
|
+
${attributes(inputs.attributePassthrough)}
|
|
184
|
+
></textarea>
|
|
185
|
+
|
|
186
|
+
<div class="border-style focus-border"></div>
|
|
187
|
+
</span>
|
|
188
|
+
`;
|
|
189
|
+
if (inputs.label) {
|
|
190
|
+
return html `
|
|
191
|
+
<label for=${state.randomId}>
|
|
192
|
+
<span class="text-area-label">${inputs.label}</span>
|
|
193
|
+
${textAreaTemplate}
|
|
194
|
+
</label>
|
|
195
|
+
`;
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
return textAreaTemplate;
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
});
|
|
@@ -53,11 +53,16 @@ export declare function filterTextInputValue(inputs: IsAllowedInputs): {
|
|
|
53
53
|
*
|
|
54
54
|
* @category Internal
|
|
55
55
|
*/
|
|
56
|
-
export declare function textInputListener({ inputs, previousValue, event, inputBlockedCallback, newValueCallback, }: {
|
|
56
|
+
export declare function textInputListener({ inputs, previousValue, event, elementConstructor, inputBlockedCallback, newValueCallback, }: {
|
|
57
57
|
inputs: SharedTextInputElementInputs;
|
|
58
58
|
/** The value of the input element before this listener fired. */
|
|
59
59
|
previousValue: string;
|
|
60
60
|
event: Event;
|
|
61
|
+
/**
|
|
62
|
+
* The constructor for the underlying native element. Defaults to `HTMLInputElement`, but can be
|
|
63
|
+
* set to `HTMLTextAreaElement` for textarea-based elements.
|
|
64
|
+
*/
|
|
65
|
+
elementConstructor?: typeof HTMLInputElement | typeof HTMLTextAreaElement | undefined;
|
|
61
66
|
inputBlockedCallback: (blockedInput: string) => void;
|
|
62
67
|
newValueCallback: (newValue: string) => void;
|
|
63
68
|
}): void;
|
|
@@ -72,8 +72,8 @@ export function filterTextInputValue(inputs) {
|
|
|
72
72
|
*
|
|
73
73
|
* @category Internal
|
|
74
74
|
*/
|
|
75
|
-
export function textInputListener({ inputs, previousValue, event, inputBlockedCallback, newValueCallback, }) {
|
|
76
|
-
const inputElement = extractEventTarget(event, HTMLInputElement);
|
|
75
|
+
export function textInputListener({ inputs, previousValue, event, elementConstructor, inputBlockedCallback, newValueCallback, }) {
|
|
76
|
+
const inputElement = extractEventTarget(event, elementConstructor || HTMLInputElement);
|
|
77
77
|
/**
|
|
78
78
|
* This is usually a single character, but can be a bunch of characters in some circumstances.
|
|
79
79
|
* For example, when a bunch of characters are pasted, this will be the entire pasted contents.
|
|
@@ -17,7 +17,8 @@ export declare enum ViraFormFieldType {
|
|
|
17
17
|
Email = "email",
|
|
18
18
|
Number = "number",
|
|
19
19
|
Select = "select",
|
|
20
|
-
Checkbox = "checkbox"
|
|
20
|
+
Checkbox = "checkbox",
|
|
21
|
+
TextArea = "text-area"
|
|
21
22
|
}
|
|
22
23
|
/**
|
|
23
24
|
* {@link ViraFormField} properties that are shared between all field types.
|
|
@@ -85,6 +86,13 @@ export type ViraFormField = ({
|
|
|
85
86
|
min: number;
|
|
86
87
|
max: number;
|
|
87
88
|
step: number;
|
|
89
|
+
}> & CommonViraFormFields) | ({
|
|
90
|
+
type: ViraFormFieldType.TextArea;
|
|
91
|
+
value: string | undefined;
|
|
92
|
+
} & PartialWithUndefined<{
|
|
93
|
+
placeholder: string;
|
|
94
|
+
rows: number;
|
|
95
|
+
preventResize: boolean;
|
|
88
96
|
}> & CommonViraFormFields);
|
|
89
97
|
/**
|
|
90
98
|
* A collection of form fields for `ViraForm`.
|
|
@@ -18,6 +18,7 @@ export var ViraFormFieldType;
|
|
|
18
18
|
ViraFormFieldType["Number"] = "number";
|
|
19
19
|
ViraFormFieldType["Select"] = "select";
|
|
20
20
|
ViraFormFieldType["Checkbox"] = "checkbox";
|
|
21
|
+
ViraFormFieldType["TextArea"] = "text-area";
|
|
21
22
|
})(ViraFormFieldType || (ViraFormFieldType = {}));
|
|
22
23
|
/**
|
|
23
24
|
* Appends a `'*'` to a label if it exist sand if it is required.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vira",
|
|
3
|
-
"version": "31.
|
|
3
|
+
"version": "31.18.1",
|
|
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": {
|