aloha-vue 1.0.284 → 1.0.286

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.
@@ -91,6 +91,13 @@ export default {
91
91
  },
92
92
  label: "Input",
93
93
  },
94
+ {
95
+ id: "input-number",
96
+ to: {
97
+ name: "PageInputNumber",
98
+ },
99
+ label: "Input number",
100
+ },
94
101
  {
95
102
  id: "json",
96
103
  label: "JSON",
@@ -149,6 +149,11 @@ const ROUTES = [
149
149
  name: "PageWizard",
150
150
  component: () => import(/* webpackChunkName: "PageWizard" */ "../views/PageWizard/PageWizard.vue"),
151
151
  },
152
+ {
153
+ path: "/input-number",
154
+ name: "PageInputNumber",
155
+ component: () => import(/* webpackChunkName: "PageInputNumber" */ "../views/PageInputNumber/PageInputNumber.vue"),
156
+ },
152
157
  {
153
158
  path: "/group-button-dropdown",
154
159
  name: "PageGroupButtonDropdown",
@@ -0,0 +1,20 @@
1
+ import AInputNumber from "../../../../src/ui/AInputNumber/AInputNumber";
2
+
3
+ export default {
4
+ name: "PageInputNumber",
5
+ components: {
6
+ AInputNumber,
7
+ },
8
+ data() {
9
+ return {
10
+ model1: 10,
11
+ model2: 11.2,
12
+ model3: undefined,
13
+ };
14
+ },
15
+ methods: {
16
+ changeModel1(arg) {
17
+ console.log("arg", arg);
18
+ },
19
+ },
20
+ };
@@ -0,0 +1,42 @@
1
+ div
2
+ h1 Form element
3
+ h2 Input number
4
+ a-input-number(
5
+ id="input1"
6
+ v-model="model1"
7
+ type="number"
8
+ label="Input 1"
9
+ :required="true"
10
+ :step="0.1"
11
+ errors="not valid"
12
+ )
13
+ div model1: {{ model1 }}
14
+
15
+ input(
16
+ type="number"
17
+ )
18
+ //h2 Textarea
19
+ //a-textarea(
20
+ // id="textarea1"
21
+ // v-model="model2"
22
+ // type="text"
23
+ // label="Textarea 1"
24
+ // :required="true"
25
+ // :is-scalable="true"
26
+ //)
27
+ //div model2:
28
+ //pre {{ model2 }}
29
+ //
30
+ //h2 Textarea 2
31
+ // a-textarea(
32
+ // id="textarea3"
33
+ // v-model="model3"
34
+ // type="text"
35
+ // label="Textarea 2"
36
+ // :required="true"
37
+ // )
38
+ // div model3:
39
+ // pre {{ model3 }}
40
+ button.a_btn.a_btn_primary() Temp
41
+
42
+
@@ -0,0 +1,2 @@
1
+ <template lang="pug" src="./PageInputNumber.pug"></template>
2
+ <script src="./PageInputNumber.js"></script>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "aloha-vue",
3
3
  "description": "Project aloha",
4
- "version": "1.0.284",
4
+ "version": "1.0.286",
5
5
  "author": "Ilia Brykin",
6
6
  "scripts": {
7
7
  "build-icons": "node scriptsNode/iconsSvgToJs.js bootstrap3 && node scriptsNode/iconsSvgToJs.js bootstrap-1-9-1"
@@ -139,6 +139,16 @@ export default {
139
139
  required: false,
140
140
  default: undefined,
141
141
  },
142
+ tag: {
143
+ type: String,
144
+ required: false,
145
+ default: "button",
146
+ },
147
+ tabindex: {
148
+ type: [Number, String],
149
+ required: false,
150
+ default: undefined,
151
+ },
142
152
  },
143
153
  emits: [
144
154
  "click",
@@ -172,7 +182,7 @@ export default {
172
182
  };
173
183
  },
174
184
  render() {
175
- return h("button", {
185
+ return h(this.tag, {
176
186
  ...this.attributes,
177
187
  id: this.id,
178
188
  class: [
@@ -183,6 +193,7 @@ export default {
183
193
  },
184
194
  ],
185
195
  type: this.type,
196
+ tabindex: this.tabindex,
186
197
  disabled: this.disabled,
187
198
  ariaDisabled: this.ariaDisabled,
188
199
  onClick: this.onClick,
@@ -1,10 +1,13 @@
1
1
  export default {
2
- tab: 9,
3
- enter: 13,
4
- space: 32,
2
+ arrowDown: 40,
5
3
  arrowLeft: 37,
6
- arrowUp: 38,
7
4
  arrowRight: 39,
8
- arrowDown: 40,
5
+ arrowUp: 38,
6
+ e: 69,
7
+ enter: 13,
9
8
  escape: 27,
9
+ minus: 109,
10
+ plus: 107,
11
+ space: 32,
12
+ tab: 9,
10
13
  };
@@ -0,0 +1,40 @@
1
+ .a_form_element_number_controls {
2
+ display: inline-flex;
3
+ align-items: stretch;
4
+ .a_btn_group {
5
+ border-top-left-radius: 0;
6
+ border-bottom-left-radius: 0;
7
+ > .aloha_btn {
8
+ --a_btn_border_color: #ced4da;
9
+ &:first-child {
10
+ margin-left: calc(-1 * var(--a_btn_border_width, var(--a_border_width)));
11
+ }
12
+ &:not(:last-child) {
13
+ border-top-left-radius: 0;
14
+ border-bottom-left-radius: 0;
15
+ }
16
+ }
17
+ }
18
+ .a_input_number {
19
+ border-top-right-radius: 0;
20
+ border-bottom-right-radius: 0;
21
+ }
22
+ }
23
+
24
+ .a_form_element__parent_invalid {
25
+ .a_form_element_number_controls .a_btn_group > .aloha_btn {
26
+ --a_btn_border_color: var(--a_form_element_error_color);
27
+ }
28
+ }
29
+
30
+ .a_input_number {
31
+ height: 100%;
32
+ -webkit-appearance: none;
33
+ -moz-appearance: textfield;
34
+ &::-webkit-inner-spin-button,
35
+ &::-webkit-outer-spin-button {
36
+ margin: 0;
37
+ -webkit-appearance: none;
38
+ }
39
+ line-height: 1;
40
+ }
@@ -21,6 +21,7 @@
21
21
  @import "components/AWizard";
22
22
  @import "components/AGroupButtonDropdown";
23
23
  @import "components/AFormElement/ATextarea";
24
+ @import "components/ui/AInputNumber";
24
25
 
25
26
  .a_dropdown__caret {
26
27
  margin: 0;
@@ -0,0 +1,316 @@
1
+ import {
2
+ h,
3
+ ref,
4
+ toRef, watch,
5
+ withDirectives,
6
+ } from "vue";
7
+
8
+ import AButton from "../../AButton/AButton";
9
+ import AErrorsText from "../AErrorsText/AErrorsText";
10
+ import AFormElementBtnClear from "../../AFormElement/AFormElementBtnClear/AFormElementBtnClear";
11
+ import AIcon from "../../AIcon/AIcon";
12
+ import ALabel from "../ALabel/ALabel";
13
+
14
+ import ASafeHtml from "../../directives/ASafeHtml";
15
+
16
+ import UiClearButtonMixinProps from "../mixins/UiClearButtonMixinProps";
17
+ import UiMixinProps from "../mixins/UiMixinProps";
18
+
19
+ import UiAPI from "../compositionApi/UiAPI";
20
+ import UiInputAutofillAPI from "../compositionApi/UiInputAutofillAPI";
21
+ import UiClearButtonAPI from "../compositionApi/UiClearButtonAPI";
22
+ import UiStyleHideAPI from "../compositionApi/UiStyleHideAPI";
23
+ import ModelAPI from "./compositionAPI/ModelAPI";
24
+ import IncreaseDecreaseAPI from "./compositionAPI/IncreaseDecreaseAPI";
25
+ import VerifyAPI from "./compositionAPI/VerifyAPI";
26
+ import InputEventsAPI from "./compositionAPI/InputEventsAPI";
27
+ import { isNumber } from "lodash-es";
28
+
29
+ export default {
30
+ name: "AInputNumber",
31
+ mixins: [
32
+ UiClearButtonMixinProps,
33
+ UiMixinProps,
34
+ ],
35
+ props: {
36
+ max: {
37
+ type: Number,
38
+ required: false,
39
+ default: undefined,
40
+ },
41
+ min: {
42
+ type: Number,
43
+ required: false,
44
+ default: undefined,
45
+ },
46
+ type: {
47
+ type: String,
48
+ required: false,
49
+ default: "number",
50
+ validator: value => ["number", "float", "integer", "float-positiv", "integer-positiv"].indexOf(value) !== -1,
51
+ },
52
+ iconPrepend: {
53
+ type: String,
54
+ required: false,
55
+ default: undefined,
56
+ },
57
+ modelUndefined: {
58
+ required: false,
59
+ default: undefined,
60
+ },
61
+ step: {
62
+ type: Number,
63
+ required: false,
64
+ default: 1,
65
+ },
66
+ precision: {
67
+ type: Number,
68
+ validator: value => value >= 0 && value === Number.parseInt(`${ value }`, 10),
69
+ },
70
+ controlsType: {
71
+ type: String,
72
+ required: false,
73
+ default: "plus-minus",
74
+ validator: value => ["plus-minus", "arrows"].indexOf(value) !== -1,
75
+ // TODO: "arrows",
76
+ },
77
+ stepStrictly: {
78
+ type: Boolean,
79
+ required: false,
80
+ },
81
+ readonly: {
82
+ type: Boolean,
83
+ required: false,
84
+ },
85
+ eAllowed: {
86
+ type: Boolean,
87
+ required: false,
88
+ },
89
+ },
90
+ setup(props, context) {
91
+ const {
92
+ componentStyleHide,
93
+ } = UiStyleHideAPI(props);
94
+
95
+ const {
96
+ ariaDescribedbyLocal,
97
+ changeModel,
98
+ clearModel,
99
+ errorsId,
100
+ helpTextId,
101
+ htmlIdLocal,
102
+ isErrors,
103
+ isModel,
104
+ onBlur,
105
+ onFocus,
106
+ } = UiAPI(props, context);
107
+
108
+ const {
109
+ isClearButtonLocal,
110
+ } = UiClearButtonAPI(props, {
111
+ isModel,
112
+ });
113
+
114
+ const inputRef = ref(undefined);
115
+ const disabled = toRef(props, "disabled");
116
+ const onInput = $event => {
117
+ if (disabled.value) {
118
+ return;
119
+ }
120
+ const value = $event.target.value;
121
+ changeModel({
122
+ model: +value,
123
+ });
124
+ };
125
+
126
+ const {
127
+ isAutofill,
128
+ } = UiInputAutofillAPI({ inputRef });
129
+
130
+ const {
131
+ ensurePrecision,
132
+ verifyValue,
133
+ } = VerifyAPI(props, {
134
+ changeModel,
135
+ });
136
+
137
+ const {
138
+ currentValue,
139
+ displayValue,
140
+ setCurrentValue,
141
+ userInput,
142
+ } = ModelAPI(props, {
143
+ verifyValue,
144
+ changeModel,
145
+ });
146
+
147
+ const {
148
+ increase,
149
+ decrease,
150
+ } = IncreaseDecreaseAPI(props, {
151
+ currentValue,
152
+ displayValue,
153
+ ensurePrecision,
154
+ setCurrentValue,
155
+ });
156
+
157
+ const {
158
+ handleInput,
159
+ handleInputChange,
160
+ handleKeydown,
161
+ onBlurNumber,
162
+ } = InputEventsAPI(props, {
163
+ currentValue,
164
+ decrease,
165
+ displayValue,
166
+ increase,
167
+ inputRef,
168
+ onBlur,
169
+ setCurrentValue,
170
+ userInput,
171
+ });
172
+
173
+ watch(
174
+ () => props.modelValue,
175
+ value => {
176
+ const userInputLocal = verifyValue(userInput.value);
177
+ const newValue = verifyValue(value, true);
178
+ if (!isNumber(userInputLocal) && (!userInputLocal || userInputLocal !== newValue)) {
179
+ currentValue.value = newValue;
180
+ userInput.value = null;
181
+ }
182
+ },
183
+ { immediate: true }
184
+ );
185
+
186
+ return {
187
+ currentValue,
188
+ handleInput,
189
+ handleInputChange,
190
+ handleKeydown,
191
+ ariaDescribedbyLocal,
192
+ clearModel,
193
+ componentStyleHide,
194
+ displayValue,
195
+ errorsId,
196
+ helpTextId,
197
+ htmlIdLocal,
198
+ inputRef,
199
+ isAutofill,
200
+ isClearButtonLocal,
201
+ isErrors,
202
+ isModel,
203
+ onBlurNumber,
204
+ onFocus,
205
+ onInput,
206
+ increase,
207
+ decrease,
208
+ userInput,
209
+ };
210
+ },
211
+ render() {
212
+ return this.isRender && h("div", {
213
+ style: this.componentStyleHide,
214
+ }, [
215
+ h("div", {
216
+ class: ["a_form_element__parent", {
217
+ a_form_element__parent_float: this.isLabelFloat,
218
+ a_form_element__parent_not_empty: this.isModel || this.isAutofill,
219
+ a_form_element__parent_float_has_icon_prepend: this.iconPrepend,
220
+ a_form_element__parent_invalid: this.isErrors,
221
+ }],
222
+ }, [
223
+ this.label && h(ALabel, {
224
+ id: this.htmlIdLocal,
225
+ label: this.label,
226
+ labelClass: this.labelClass,
227
+ required: this.required,
228
+ type: this.type,
229
+ isLabelFloat: this.isLabelFloat,
230
+ }),
231
+ h("div", {
232
+ class: [
233
+ "a_form_element_number",
234
+ {
235
+ a_form_element_number_controls: this.controlsType,
236
+ },
237
+ ],
238
+ }, [
239
+ h("div", {
240
+ class: "a_form_element",
241
+ }, [
242
+ this.iconPrepend && h(AIcon, {
243
+ icon: this.iconPrepend,
244
+ class: "a_input__icon_prepend",
245
+ }),
246
+ h("input", {
247
+ ref: "inputRef",
248
+ id: this.htmlIdLocal,
249
+ value: this.displayValue,
250
+ type: "number",
251
+ class: [
252
+ "a_form_control a_input a_input_number",
253
+ this.inputClass,
254
+ {
255
+ a_form_element_with_btn_close: this.isClearButtonLocal,
256
+ a_form_control_invalid: this.isErrors,
257
+ },
258
+ ],
259
+ min: this.min,
260
+ max: this.max,
261
+ step: this.step,
262
+ disabled: this.disabled,
263
+ ariaRequired: this.required,
264
+ ariaInvalid: this.isErrors,
265
+ "aria-describedby": this.ariaDescribedbyLocal,
266
+ ...this.inputAttributes,
267
+ onInput: this.handleInput,
268
+ onChange: this.handleInputChange,
269
+ onKeydown: this.handleKeydown,
270
+ onFocus: this.onFocus,
271
+ onBlur: this.onBlurNumber,
272
+ }),
273
+ this.isClearButtonLocal && h(AFormElementBtnClear, {
274
+ disabled: this.disabled,
275
+ clearButtonClass: this.clearButtonClass,
276
+ onClear: this.clearModel,
277
+ }),
278
+ ]),
279
+ this.controlsType === "plus-minus" && h("div", {
280
+ class: "a_btn_group",
281
+ }, [
282
+ h(AButton, {
283
+ class: "a_btn a_btn_outline_secondary",
284
+ iconLeft: "Minus",
285
+ tabindex: -1,
286
+ attributes: {
287
+ role: "button",
288
+ },
289
+ onClick: this.decrease,
290
+ }),
291
+ h(AButton, {
292
+ class: "a_btn a_btn_outline_secondary",
293
+ iconLeft: "Plus",
294
+ tabindex: -1,
295
+ attributes: {
296
+ role: "button",
297
+ },
298
+ onClick: this.increase,
299
+ }),
300
+ ]),
301
+ ]),
302
+
303
+ this.helpText && withDirectives(h("div", {
304
+ id: this.helpTextId,
305
+ class: "a_form_element__help_text",
306
+ }), [
307
+ [ASafeHtml, this.helpText],
308
+ ]),
309
+ this.isErrors && h(AErrorsText, {
310
+ id: this.errorsId,
311
+ errors: this.errors,
312
+ }),
313
+ ]),
314
+ ]);
315
+ },
316
+ };
@@ -0,0 +1,52 @@
1
+ import {
2
+ computed, ref,
3
+ toRef,
4
+ } from "vue";
5
+
6
+ import {
7
+ isNumber,
8
+ } from "lodash-es";
9
+
10
+ export default function IncreaseDecreaseAPI(props, {
11
+ currentValue = ref(0),
12
+ displayValue = computed(() => ""),
13
+ ensurePrecision = () => {},
14
+ setCurrentValue = () => {},
15
+ }) {
16
+ const disabled = toRef(props, "disabled");
17
+ const modelValue = toRef(props, "modelValue");
18
+ const max = toRef(props, "max");
19
+ const min = toRef(props, "min");
20
+ const readonly = toRef(props, "readonly");
21
+
22
+ const minDisabled = computed(() => {
23
+ return isNumber(modelValue.value) && modelValue.value <= min.value;
24
+ });
25
+
26
+ const maxDisabled = computed(() => {
27
+ return isNumber(modelValue.value) && modelValue.value >= max.value;
28
+ });
29
+
30
+ const increase = () => {
31
+ if (readonly.value || disabled.value || maxDisabled.value) {
32
+ return;
33
+ }
34
+ const value = Number(displayValue.value) || 0;
35
+ const newValue = ensurePrecision({ value, currentValue: currentValue.value });
36
+ setCurrentValue(newValue);
37
+ };
38
+
39
+ const decrease = () => {
40
+ if (readonly.value || disabled.value || minDisabled.value) {
41
+ return;
42
+ }
43
+ const value = Number(displayValue.value) || 0;
44
+ const newValue = ensurePrecision({ value, currentValue: currentValue.value, coefficient: -1 });
45
+ setCurrentValue(newValue);
46
+ };
47
+
48
+ return {
49
+ increase,
50
+ decrease,
51
+ };
52
+ }