quasar-ui-danx 0.4.9 → 0.4.10
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/danx.es.js +5745 -5699
- package/dist/danx.es.js.map +1 -1
- package/dist/danx.umd.js +7 -7
- package/dist/danx.umd.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/ActionTable/Form/Fields/FieldLabel.vue +18 -15
- package/src/components/ActionTable/Form/Fields/LabelValueBlock.vue +44 -15
- package/src/components/ActionTable/Form/Fields/MultiKeywordField.vue +12 -13
- package/src/components/ActionTable/Form/Fields/NumberField.vue +41 -55
- package/src/components/ActionTable/Form/Fields/SelectField.vue +4 -3
- package/src/components/ActionTable/Form/Fields/TextField.vue +31 -12
- package/src/helpers/formats.ts +79 -9
- package/src/helpers/utils.ts +2 -0
- package/src/styles/quasar-reset.scss +2 -0
- package/src/styles/themes/danx/forms.scss +1 -19
- package/src/types/fields.d.ts +10 -9
package/package.json
CHANGED
@@ -1,27 +1,30 @@
|
|
1
1
|
<template>
|
2
|
-
<
|
2
|
+
<div class="dx-field-label">
|
3
3
|
<slot>
|
4
|
-
|
5
|
-
|
4
|
+
<div class="dx-field-label-text">
|
5
|
+
<div class="dx-field-label-label">
|
6
|
+
{{ label }}
|
7
|
+
</div>
|
8
|
+
<div
|
9
|
+
v-if="name"
|
10
|
+
class="dx-field-label-name"
|
11
|
+
>
|
12
|
+
({{ name }})
|
13
|
+
</div>
|
14
|
+
</div>
|
6
15
|
</slot>
|
7
16
|
<span
|
8
|
-
v-if="
|
17
|
+
v-if="required"
|
9
18
|
class="dx-field-required"
|
10
|
-
>{{ requiredLabel }}</span>
|
11
|
-
</
|
19
|
+
>{{ requiredLabel || "*" }}</span>
|
20
|
+
</div>
|
12
21
|
</template>
|
13
22
|
|
14
23
|
<script setup lang="ts">
|
15
|
-
|
16
|
-
import { FormField } from "../../../../types";
|
17
|
-
|
18
|
-
const props = defineProps<{
|
19
|
-
field?: FormField;
|
24
|
+
defineProps<{
|
20
25
|
label?: string;
|
21
|
-
|
26
|
+
name?: string;
|
22
27
|
required?: boolean;
|
28
|
+
requiredLabel?: string;
|
23
29
|
}>();
|
24
|
-
|
25
|
-
const labelText = computed(() => props.label || props.field?.label);
|
26
|
-
const requiredLabel = computed(() => props.field?.required_group || (props.required || props.field?.required ? "*" : ""));
|
27
30
|
</script>
|
@@ -1,22 +1,51 @@
|
|
1
1
|
<template>
|
2
2
|
<div>
|
3
|
-
<div class="text-xs font-bold">
|
4
|
-
|
5
|
-
|
3
|
+
<div class="text-xs font-bold">
|
4
|
+
{{ label }}
|
5
|
+
</div>
|
6
|
+
<div :class="valueClass">
|
7
|
+
<a
|
8
|
+
v-if="url"
|
9
|
+
target="_blank"
|
10
|
+
:href="url"
|
11
|
+
:class="valueClass"
|
12
|
+
>
|
13
|
+
<slot>{{ formattedValue }}</slot>
|
14
|
+
</a>
|
15
|
+
<template v-else>
|
16
|
+
<slot>{{ formattedValue }}</slot>
|
17
|
+
</template>
|
6
18
|
</div>
|
7
19
|
</div>
|
8
20
|
</template>
|
9
|
-
<script setup>
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
+
<script setup lang="ts">
|
22
|
+
import { computed } from "vue";
|
23
|
+
import { fBoolean, fNumber } from "../../../../helpers";
|
24
|
+
|
25
|
+
export interface LabelValueBlockProps {
|
26
|
+
label: string;
|
27
|
+
value: string | number | boolean;
|
28
|
+
url?: string;
|
29
|
+
dense?: boolean;
|
30
|
+
nowrap?: boolean;
|
31
|
+
}
|
32
|
+
|
33
|
+
const props = withDefaults(defineProps<LabelValueBlockProps>(), {
|
34
|
+
value: "",
|
35
|
+
url: ""
|
36
|
+
});
|
37
|
+
|
38
|
+
const valueClass = computed(() => ({ "mt-2": !props.dense, "mt-1": props.dense, "text-no-wrap": props.nowrap }));
|
39
|
+
const formattedValue = computed(() => {
|
40
|
+
switch (typeof props.value) {
|
41
|
+
case "boolean":
|
42
|
+
return fBoolean(props.value);
|
43
|
+
|
44
|
+
case "number":
|
45
|
+
return fNumber(props.value);
|
46
|
+
|
47
|
+
default:
|
48
|
+
return props.value || "-";
|
49
|
+
}
|
21
50
|
});
|
22
51
|
</script>
|
@@ -12,7 +12,6 @@
|
|
12
12
|
:field="field"
|
13
13
|
:no-label="!field.label"
|
14
14
|
label-class="text-xs font-bold text-zinc-800"
|
15
|
-
parent-class="tight-label"
|
16
15
|
input-class="!py-0"
|
17
16
|
dense
|
18
17
|
type="textarea"
|
@@ -29,29 +28,29 @@ import TextField from "./TextField";
|
|
29
28
|
|
30
29
|
const emit = defineEmits(["update:model-value"]);
|
31
30
|
const props = defineProps({
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
31
|
+
modelValue: {
|
32
|
+
type: [String, Number, Object],
|
33
|
+
default: ""
|
34
|
+
},
|
35
|
+
field: {
|
36
|
+
type: Object,
|
37
|
+
default: null
|
38
|
+
}
|
40
39
|
});
|
41
40
|
|
42
41
|
const selectedFieldName = ref(props.field.defaultOption);
|
43
42
|
const searchList = computed(() => props.modelValue && props.modelValue[selectedFieldName.value]);
|
44
43
|
const textInput = ref(formatModelValue());
|
45
44
|
function onChange() {
|
46
|
-
|
47
|
-
|
45
|
+
textInput.value = textInput.value?.replace(/\n/g, ",").replace(/,{2,}/g, ",") || "";
|
46
|
+
emit("update:model-value", textInput.value ? { [selectedFieldName.value]: textInput.value.split(",") } : undefined);
|
48
47
|
}
|
49
48
|
|
50
49
|
function formatModelValue() {
|
51
|
-
|
50
|
+
return Array.isArray(searchList.value) ? searchList.value?.join(",") : "";
|
52
51
|
}
|
53
52
|
|
54
53
|
watch(() => props.modelValue, () => {
|
55
|
-
|
54
|
+
textInput.value = formatModelValue();
|
56
55
|
});
|
57
56
|
</script>
|
@@ -1,72 +1,49 @@
|
|
1
1
|
<template>
|
2
|
-
<
|
3
|
-
class="dx-number-field
|
4
|
-
|
2
|
+
<TextField
|
3
|
+
class="dx-number-field"
|
4
|
+
v-bind="$props"
|
5
5
|
:model-value="numberVal"
|
6
|
-
:data-testid="'number-field-' + fieldOptions.id"
|
7
|
-
:placeholder="fieldOptions.placeholder"
|
8
|
-
outlined
|
9
|
-
dense
|
10
|
-
inputmode="numeric"
|
11
|
-
:input-class="inputClass"
|
12
6
|
@update:model-value="onInput"
|
13
|
-
|
14
|
-
<template #prepend>
|
15
|
-
<FieldLabel
|
16
|
-
:field="fieldOptions"
|
17
|
-
:show-name="showName"
|
18
|
-
/>
|
19
|
-
</template>
|
20
|
-
</QInput>
|
7
|
+
/>
|
21
8
|
</template>
|
22
9
|
|
23
|
-
<script setup>
|
10
|
+
<script setup lang="ts">
|
24
11
|
import { useDebounceFn } from "@vueuse/core";
|
25
|
-
import {
|
12
|
+
import { nextTick, ref, watch } from "vue";
|
26
13
|
import { fNumber } from "../../../../helpers";
|
27
|
-
import
|
14
|
+
import { AnyObject, TextFieldProps } from "../../../../types";
|
15
|
+
import TextField from "./TextField";
|
28
16
|
|
29
17
|
const emit = defineEmits(["update:model-value", "update"]);
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
},
|
47
|
-
inputClass: {
|
48
|
-
type: [String, Object],
|
49
|
-
default: ""
|
50
|
-
},
|
51
|
-
delay: {
|
52
|
-
type: Number,
|
53
|
-
default: 1000
|
54
|
-
},
|
55
|
-
hidePrependLabel: Boolean,
|
56
|
-
currency: Boolean,
|
57
|
-
showName: Boolean
|
18
|
+
|
19
|
+
export interface NumberFieldProps extends TextFieldProps {
|
20
|
+
precision?: number;
|
21
|
+
delay?: number;
|
22
|
+
currency?: boolean;
|
23
|
+
min?: number;
|
24
|
+
max?: number;
|
25
|
+
}
|
26
|
+
|
27
|
+
const props = withDefaults(defineProps<NumberFieldProps>(), {
|
28
|
+
modelValue: "",
|
29
|
+
precision: 2,
|
30
|
+
label: undefined,
|
31
|
+
delay: 1000,
|
32
|
+
min: undefined,
|
33
|
+
max: undefined
|
58
34
|
});
|
59
35
|
|
60
36
|
const numberVal = ref(format(props.modelValue));
|
61
|
-
watch(() => props.modelValue, () => numberVal.value = format(props.modelValue));
|
62
37
|
|
63
|
-
|
38
|
+
watch(() => props.modelValue, () => numberVal.value = format(props.modelValue));
|
64
39
|
|
65
40
|
function format(number) {
|
66
41
|
if (!number && number !== 0 && number !== "0") return number;
|
67
42
|
|
43
|
+
if (props.type === "number") return number;
|
44
|
+
|
68
45
|
const minimumFractionDigits = Math.min(props.precision, ("" + number).split(".")[1]?.length || 0);
|
69
|
-
let options = {
|
46
|
+
let options: AnyObject = {
|
70
47
|
minimumFractionDigits
|
71
48
|
};
|
72
49
|
|
@@ -80,14 +57,15 @@ function format(number) {
|
|
80
57
|
return fNumber(number, options);
|
81
58
|
}
|
82
59
|
|
83
|
-
const onUpdateDebounced = useDebounceFn((val) => emit("update", val), props.delay);
|
60
|
+
const onUpdateDebounced = useDebounceFn((val: number | string | undefined) => emit("update", val), props.delay);
|
84
61
|
|
85
62
|
function onInput(value) {
|
86
|
-
let number =
|
63
|
+
let number: number | undefined = undefined;
|
87
64
|
|
88
65
|
// Prevent invalid characters
|
89
66
|
if (value.match(/[^\d.,$]/)) {
|
90
67
|
const oldVal = numberVal.value;
|
68
|
+
|
91
69
|
// XXX: To get QInput to show only the value we want
|
92
70
|
numberVal.value += " ";
|
93
71
|
return nextTick(() => numberVal.value = oldVal);
|
@@ -95,11 +73,19 @@ function onInput(value) {
|
|
95
73
|
|
96
74
|
if (value !== "") {
|
97
75
|
value = value.replace(/[^\d.]/g, "");
|
98
|
-
number =
|
76
|
+
number = +value;
|
77
|
+
|
78
|
+
if (props.min) {
|
79
|
+
number = Math.max(number, props.min);
|
80
|
+
}
|
81
|
+
if (props.max) {
|
82
|
+
number = Math.min(number, props.max);
|
83
|
+
}
|
84
|
+
|
85
|
+
console.log("formattinged", number, value);
|
99
86
|
numberVal.value = format(number);
|
100
87
|
}
|
101
88
|
|
102
|
-
number = number === "" ? undefined : number;
|
103
89
|
emit("update:model-value", number);
|
104
90
|
|
105
91
|
// Delay the change event, so we only see the value after the user has finished
|
@@ -37,8 +37,8 @@
|
|
37
37
|
<template #selected>
|
38
38
|
<div
|
39
39
|
v-if="$props.multiple"
|
40
|
-
class="flex gap-y-1 overflow-hidden"
|
41
|
-
:class="{'flex-nowrap gap-y-0': chipLimit === 1, [selectionClass]: true}"
|
40
|
+
class="flex gap-y-1 overflow-hidden dx-selected-label"
|
41
|
+
:class="{'flex-nowrap gap-y-0': chipLimit === 1, 'dx-selected-chips': chipOptions.length > 0, [selectionClass]: true}"
|
42
42
|
>
|
43
43
|
<template v-if="chipOptions.length > 0">
|
44
44
|
<QChip
|
@@ -62,6 +62,7 @@
|
|
62
62
|
<div
|
63
63
|
v-else
|
64
64
|
:class="selectionClass"
|
65
|
+
class="dx-selected-label"
|
65
66
|
>
|
66
67
|
{{ selectedLabel }}
|
67
68
|
</div>
|
@@ -254,8 +255,8 @@ function onUpdate(value) {
|
|
254
255
|
|
255
256
|
value = value === "__null__" ? null : value;
|
256
257
|
|
257
|
-
emit("update", value);
|
258
258
|
emit("update:model-value", value);
|
259
|
+
emit("update", value);
|
259
260
|
}
|
260
261
|
|
261
262
|
/** XXX: This tells us when we should apply the filter. QSelect likes to trigger a new filter everytime you open the dropdown
|
@@ -1,15 +1,21 @@
|
|
1
1
|
<template>
|
2
2
|
<div>
|
3
3
|
<FieldLabel
|
4
|
-
|
4
|
+
v-if="!prependLabel"
|
5
5
|
:label="label"
|
6
|
-
:
|
6
|
+
:required="required"
|
7
|
+
:required-label="requiredLabel"
|
7
8
|
:class="labelClass"
|
8
|
-
:value="readonly ? modelValue : ''"
|
9
9
|
/>
|
10
|
-
<
|
10
|
+
<div
|
11
|
+
v-if="readonly"
|
12
|
+
class="dx-text-field-readonly-value"
|
13
|
+
>
|
14
|
+
{{ modelValue }}
|
15
|
+
</div>
|
16
|
+
<template v-else>
|
11
17
|
<QInput
|
12
|
-
:placeholder="
|
18
|
+
:placeholder="placeholder || (placeholder === '' ? '' : `Enter ${label}`)"
|
13
19
|
outlined
|
14
20
|
dense
|
15
21
|
:readonly="readonly"
|
@@ -17,18 +23,31 @@
|
|
17
23
|
:disable="disabled"
|
18
24
|
:label-slot="!noLabel"
|
19
25
|
:input-class="inputClass"
|
20
|
-
:class="
|
26
|
+
:class="{'dx-input-prepend-label': prependLabel}"
|
21
27
|
stack-label
|
22
28
|
:type="type"
|
23
29
|
:model-value="modelValue"
|
24
|
-
:maxlength="allowOverMax ? undefined :
|
30
|
+
:maxlength="allowOverMax ? undefined : maxLength"
|
25
31
|
:debounce="debounce"
|
26
32
|
@keydown.enter="$emit('submit')"
|
27
33
|
@update:model-value="$emit('update:model-value', $event)"
|
28
|
-
|
34
|
+
>
|
35
|
+
<template
|
36
|
+
v-if="prependLabel"
|
37
|
+
#prepend
|
38
|
+
>
|
39
|
+
<FieldLabel
|
40
|
+
class="dx-prepended-label"
|
41
|
+
:label="label"
|
42
|
+
:required="required"
|
43
|
+
:required-label="requiredLabel"
|
44
|
+
:class="labelClass"
|
45
|
+
/>
|
46
|
+
</template>
|
47
|
+
</QInput>
|
29
48
|
<MaxLengthCounter
|
30
|
-
:length="modelValue
|
31
|
-
:max-length="
|
49
|
+
:length="(modelValue + '').length || 0"
|
50
|
+
:max-length="maxLength"
|
32
51
|
/>
|
33
52
|
</template>
|
34
53
|
</div>
|
@@ -46,9 +65,9 @@ withDefaults(defineProps<TextFieldProps>(), {
|
|
46
65
|
type: "text",
|
47
66
|
label: "",
|
48
67
|
labelClass: "",
|
49
|
-
parentClass: "",
|
50
68
|
inputClass: "",
|
51
69
|
maxLength: null,
|
52
|
-
debounce: 0
|
70
|
+
debounce: 0,
|
71
|
+
placeholder: null
|
53
72
|
});
|
54
73
|
</script>
|
package/src/helpers/formats.ts
CHANGED
@@ -29,10 +29,9 @@ export function remoteDateTime(dateTimeString: string) {
|
|
29
29
|
}
|
30
30
|
|
31
31
|
/**
|
32
|
-
*
|
33
|
-
* @returns {DateTime|*}
|
32
|
+
* Parses a date string into a Luxon DateTime object
|
34
33
|
*/
|
35
|
-
export function parseDateTime(dateTime: string | DateTime) {
|
34
|
+
export function parseDateTime(dateTime: string | DateTime | null): DateTime {
|
36
35
|
if (typeof dateTime === "string") {
|
37
36
|
dateTime = dateTime.replace("T", " ").replace(/\//g, "-");
|
38
37
|
return DateTime.fromSQL(dateTime);
|
@@ -91,8 +90,8 @@ export function fDateTime(
|
|
91
90
|
dateTime: string | DateTime | null = null,
|
92
91
|
{ format = "M/d/yy h:mma", empty = "- -" }: fDateOptions = {}
|
93
92
|
) {
|
94
|
-
const formatted =
|
95
|
-
return
|
93
|
+
const formatted = parseDateTime(dateTime).toFormat(format).toLowerCase();
|
94
|
+
return ["Invalid DateTime", "invalid datetime"].includes(formatted) ? empty : formatted;
|
96
95
|
}
|
97
96
|
|
98
97
|
/**
|
@@ -151,16 +150,87 @@ export function fCurrency(amount: number, options?: object) {
|
|
151
150
|
}).format(amount);
|
152
151
|
}
|
153
152
|
|
153
|
+
/**
|
154
|
+
* Formats an amount into USD currency format without cents
|
155
|
+
*/
|
156
|
+
export function fCurrencyNoCents(amount: number, options?: object) {
|
157
|
+
return fCurrency(amount, {
|
158
|
+
maximumFractionDigits: 0,
|
159
|
+
...options
|
160
|
+
});
|
161
|
+
}
|
162
|
+
|
154
163
|
/**
|
155
164
|
* Formats a number into a human-readable format
|
156
|
-
* @param number
|
157
|
-
* @param options
|
158
|
-
* @returns {string}
|
159
165
|
*/
|
160
|
-
export function fNumber(number: number, options
|
166
|
+
export function fNumber(number: number, options?: object) {
|
161
167
|
return new Intl.NumberFormat("en-US", options).format(number);
|
162
168
|
}
|
163
169
|
|
170
|
+
/**
|
171
|
+
* Formats a currency into a shorthand human-readable format (ie: $1.2M or $5K)
|
172
|
+
*/
|
173
|
+
export function fShortCurrency(value: string | number, options?: { round: boolean }) {
|
174
|
+
return "$" + fShortNumber(value, options);
|
175
|
+
}
|
176
|
+
|
177
|
+
/**
|
178
|
+
* Formats a number into a shorthand human-readable format (ie: 1.2M or 5K)
|
179
|
+
*/
|
180
|
+
export function fShortNumber(value: string | number, options?: { round: boolean }) {
|
181
|
+
const shorts = [
|
182
|
+
{ pow: 3, unit: "K" },
|
183
|
+
{ pow: 6, unit: "M" },
|
184
|
+
{ pow: 9, unit: "B" },
|
185
|
+
{ pow: 12, unit: "T" },
|
186
|
+
{ pow: 15, unit: "Q" }
|
187
|
+
];
|
188
|
+
|
189
|
+
let n = Math.round(+value);
|
190
|
+
|
191
|
+
const short = shorts.find(({ pow }) => Math.pow(10, pow) < n && Math.pow(10, pow + 3) > n) || null;
|
192
|
+
|
193
|
+
if (short) {
|
194
|
+
n = n / Math.pow(10, short.pow);
|
195
|
+
return options?.round
|
196
|
+
? n + short.unit
|
197
|
+
: n.toFixed(n > 100 ? 0 : 1) + short.unit;
|
198
|
+
}
|
199
|
+
|
200
|
+
return n;
|
201
|
+
}
|
202
|
+
|
203
|
+
/**
|
204
|
+
* Formats a number into a human-readable size format (ie: 1.2MB or 5KB)
|
205
|
+
*/
|
206
|
+
export function fShortSize(value: string | number) {
|
207
|
+
const powers = [
|
208
|
+
{ pow: 0, unit: "B" },
|
209
|
+
{ pow: 10, unit: "KB" },
|
210
|
+
{ pow: 20, unit: "MB" },
|
211
|
+
{ pow: 30, unit: "GB" },
|
212
|
+
{ pow: 40, unit: "TB" },
|
213
|
+
{ pow: 50, unit: "PB" },
|
214
|
+
{ pow: 60, unit: "EB" },
|
215
|
+
{ pow: 70, unit: "ZB" },
|
216
|
+
{ pow: 80, unit: "YB" }
|
217
|
+
];
|
218
|
+
|
219
|
+
const n = Math.round(+value);
|
220
|
+
const power = powers.find((p, i) => {
|
221
|
+
const nextPower = powers[i + 1];
|
222
|
+
return !nextPower || n < Math.pow(2, nextPower.pow + 10);
|
223
|
+
}) || powers[powers.length - 1];
|
224
|
+
|
225
|
+
const div = Math.pow(2, power.pow);
|
226
|
+
|
227
|
+
return Math.round(n / div) + " " + power.unit;
|
228
|
+
}
|
229
|
+
|
230
|
+
export function fBoolean(value: boolean) {
|
231
|
+
return value ? "Yes" : "No";
|
232
|
+
}
|
233
|
+
|
164
234
|
/**
|
165
235
|
* Truncates the string by removing chars from the middle of the string
|
166
236
|
* @param str
|
package/src/helpers/utils.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
.dx-field-label {
|
2
|
-
@apply text-xs
|
2
|
+
@apply text-xs mb-1.5 flex items-center space-x-1;
|
3
3
|
|
4
4
|
.dx-field-required {
|
5
5
|
@apply text-red-900 ml-0.5 bottom-1 relative;
|
@@ -10,22 +10,4 @@
|
|
10
10
|
.q-field__label {
|
11
11
|
@apply text-sm text-gray-700;
|
12
12
|
}
|
13
|
-
|
14
|
-
&.dx-number-field {
|
15
|
-
&.dx-prepend-label {
|
16
|
-
@apply text-xs text-black font-normal;
|
17
|
-
}
|
18
|
-
|
19
|
-
&.dx-no-prepend-label {
|
20
|
-
@apply w-32;
|
21
|
-
|
22
|
-
.q-field__native {
|
23
|
-
@apply bg-white text-right;
|
24
|
-
}
|
25
|
-
|
26
|
-
.q-field__prepend {
|
27
|
-
padding: 0;
|
28
|
-
}
|
29
|
-
}
|
30
|
-
}
|
31
13
|
}
|
package/src/types/fields.d.ts
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
import { QInputProps } from "quasar";
|
2
|
-
import { FormField } from "./forms";
|
3
2
|
|
4
3
|
export interface TextFieldProps {
|
5
|
-
modelValue?: string
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
4
|
+
modelValue?: string | number;
|
5
|
+
type?: QInputProps["type"];
|
6
|
+
label?: string;
|
7
|
+
required?: boolean;
|
8
|
+
requiredLabel?: string;
|
9
|
+
prependLabel?: boolean;
|
10
|
+
placeholder?: string;
|
11
|
+
labelClass?: string | object;
|
12
|
+
inputClass?: string | object;
|
13
|
+
allowOverMax?: boolean;
|
13
14
|
maxLength?: number;
|
14
15
|
autogrow?: boolean;
|
15
16
|
noLabel?: boolean;
|