aloha-vue 2.74.0 → 2.75.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.
Files changed (166) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/LICENSE +22 -21
  3. package/dist/aloha-vue.css +13594 -13594
  4. package/dist/aloha-vue.css.map +1 -1
  5. package/dist/aloha-vue.es.js +59266 -64918
  6. package/dist/aloha-vue.umd.js +338 -211
  7. package/package.json +27 -34
  8. package/scss/components/ATable.scss +2 -2
  9. package/scss/utils/button.scss +362 -362
  10. package/scss/utils/funktions.scss +162 -162
  11. package/src/AAccordion/AAccordionItem/AAccordionItem.js +235 -230
  12. package/src/ACarousel/ACarousel.js +7 -2
  13. package/src/ADropdown/ADropdown.js +4 -1
  14. package/src/AFilters/AFilterCenter/AFilterCenter.js +5 -1
  15. package/src/AFilters/AFilterCenter/AFilterCenterItem/AFilterCenterItem.js +7 -2
  16. package/src/AFilters/AFiltersHorizontal/AFiltersHorizontal.js +412 -396
  17. package/src/AFilters/AFiltersHorizontal/AFiltersHorizontalFilter/AFiltersHorizontalFilter.js +102 -99
  18. package/src/AFilters/AFiltersHorizontal/compositionAPI/FiltersSavedDeleteAPI.js +108 -108
  19. package/src/AFilters/AFiltersMain/AFiltersMain.js +114 -111
  20. package/src/AFilters/AFiltersSaveModal/compositionAPI/SaveAPI.js +65 -65
  21. package/src/ALinkCopy/ALinkCopy.js +98 -95
  22. package/src/ALinkCopy/compositionAPI/CopyAPI.js +48 -48
  23. package/src/AList/__tests__/AList.test.js +33 -33
  24. package/src/AList/compositionAPI/__tests__/TagAPI.test.js +43 -43
  25. package/src/AMenu/AMenu.js +4 -1
  26. package/src/AMenu/AMenuBreadcrumbs/AMenuBreadcrumbs.js +240 -237
  27. package/src/AMenu/AMenuPanelLink/AMenuPanelLink.js +4 -1
  28. package/src/AMenu/AMenuSearchPanelBreadcrumbs/AMenuSearchPanelBreadcrumbs.js +122 -119
  29. package/src/AModalWizard/AModalWizard.js +58 -53
  30. package/src/AModalWizard/compositionAPI/__tests__/ScrollAPI.test.js +46 -46
  31. package/src/APagination/APaginationPages/APaginationPages.js +15 -4
  32. package/src/ARate/ARate.js +254 -249
  33. package/src/ARate/ARateIcon/ADecimalIcon/ADecimalIcon.js +53 -50
  34. package/src/ARate/ARateIcon/ARateIcon.js +109 -104
  35. package/src/AResizer/AResizer.js +167 -162
  36. package/src/ATable/ATableHeaderTh/compositionAPI/SortAPI.js +172 -167
  37. package/src/ATable/ATableHeaderThAction/ATableHeaderThAction.js +14 -4
  38. package/src/ATable/ATableHeaderThAction/ATableHeaderThActionItem/ATableHeaderThActionItem.js +191 -184
  39. package/src/ATable/ATablePreviewDown/ATablePreviewDown.js +72 -69
  40. package/src/ATable/ATablePreviewRight/ATablePreviewRight.js +265 -258
  41. package/src/ATable/ATableSortingAdditional/ATableSortingAdditional.js +224 -219
  42. package/src/ATable/ATableSortingAdditional/__tests__/ATableSortingAdditional.AttributesAPI.test.js +39 -39
  43. package/src/ATable/ATableSortingAdditional/__tests__/ATableSortingAdditional.ColumnsAPI.test.js +68 -68
  44. package/src/ATable/ATableSortingAdditional/__tests__/ATableSortingAdditional.DropdownAPI.test.js +45 -45
  45. package/src/ATable/ATableSortingAdditional/__tests__/ATableSortingAdditional.FormAPI.test.js +95 -95
  46. package/src/ATable/ATableSortingAdditional/__tests__/ATableSortingAdditional.ModelAPI.test.js +1 -1
  47. package/src/ATable/ATableTd/ATableTd.js +4 -1
  48. package/src/ATable/ATableTdAction/ATableTdAction.js +19 -12
  49. package/src/ATable/ATableTopPanel/ATableTopPanel.js +11 -3
  50. package/src/ATable/ATableTr/ATableTr.js +408 -405
  51. package/src/ATable/__tests__/ATable.HeaderSlot.test.js +102 -97
  52. package/src/ATable/__tests__/ATable.RowIdsAPI.test.js +66 -66
  53. package/src/ATableForm/ATableForm.js +88 -85
  54. package/src/ATableForm/ATableFormCellAction/ATableFormCellAction.js +14 -4
  55. package/src/ATableForm/ATableFormCellDnd/ATableFormCellDnd.js +196 -187
  56. package/src/ATableForm/ATableFormRow/compositionAPI/EditAPI.js +104 -104
  57. package/src/ATableForm/__tests__/ATableForm.DragAndDropAPI.test.js +200 -212
  58. package/src/ATableForm/__tests__/ATableForm.ListView.test.js +134 -174
  59. package/src/ATableForm/compositionAPI/IconsAPI.js +24 -21
  60. package/src/AVerticalScroll/AVerticalScroll.js +182 -177
  61. package/src/AWizard/AWizard.js +26 -21
  62. package/src/AWizard/AWizardStep/AWizardStep.js +275 -270
  63. package/src/AWizard/compositionAPI/__tests__/ChangeStepAPI.test.js +32 -32
  64. package/src/AWizard/compositionAPI/__tests__/LocalAPI.test.js +55 -55
  65. package/src/PuxDatepicker/PuxDatepickerCalendarPanel/PuxDatepickerCalendarPanel.js +646 -648
  66. package/src/PuxDatepicker/panel/PanelDate/PanelDate.js +300 -301
  67. package/src/PuxDatepicker/panel/PanelMonth/PanelMonth.js +148 -149
  68. package/src/PuxDatepicker/panel/PanelTime/PanelTime.js +256 -257
  69. package/src/PuxDatepicker/panel/PanelYear/PanelYear.js +136 -137
  70. package/src/PuxDatepicker/utils/index.js +100 -100
  71. package/src/compositionAPI/AHttpAPI.js +593 -593
  72. package/src/compositionAPI/__tests__/AHttpAPI.test.js +42 -42
  73. package/src/filters/__tests__/filterBoolean.test.js +38 -38
  74. package/src/filters/__tests__/filterCapitalize.test.js +38 -38
  75. package/src/filters/__tests__/filterCurrency.test.js +21 -21
  76. package/src/filters/__tests__/filterDate.test.js +42 -42
  77. package/src/filters/__tests__/filterDefaultForEmpty.test.js +24 -24
  78. package/src/filters/__tests__/filterEmail.test.js +42 -42
  79. package/src/filters/__tests__/filterEscapeHtml.test.js +45 -45
  80. package/src/filters/__tests__/filterFileSize.test.js +45 -45
  81. package/src/filters/__tests__/filterFloat.test.js +74 -74
  82. package/src/filters/__tests__/filterJson.test.js +74 -74
  83. package/src/filters/__tests__/filterKeyValue.test.js +50 -50
  84. package/src/filters/__tests__/filterLimitTo.test.js +39 -39
  85. package/src/filters/__tests__/filterLink.test.js +41 -41
  86. package/src/filters/__tests__/filterList.test.js +149 -149
  87. package/src/filters/__tests__/filterLowerCase.test.js +38 -38
  88. package/src/filters/__tests__/filterMask.test.js +80 -80
  89. package/src/filters/__tests__/filterPropertyByValue.test.js +27 -27
  90. package/src/filters/__tests__/filterSearchHighlight.test.js +129 -129
  91. package/src/filters/__tests__/filterUpperCase.test.js +38 -38
  92. package/src/filters/__tests__/filterValueByCondition.test.js +3 -3
  93. package/src/filters/filterJson.js +39 -39
  94. package/src/filters/filterValueByCondition.js +2 -2
  95. package/src/plugins/AAlertPlugin.js +16 -5
  96. package/src/plugins/AMultiselectOrderedPlugin.js +88 -81
  97. package/src/plugins/ASelectPlugin.js +12 -10
  98. package/src/ui/ACheckbox/ACheckbox.js +82 -79
  99. package/src/ui/ADatepicker/compositionAPI/EventsAPI.js +297 -297
  100. package/src/ui/ADatepicker/utils/index.js +76 -76
  101. package/src/ui/ADatepickerAlt/ADatepicker.js +912 -912
  102. package/src/ui/ADatepickerAlt/utils/index.js +98 -98
  103. package/src/ui/AFieldset/__tests__/AFieldset.ClassColumn.test.js +113 -114
  104. package/src/ui/AFormElementBtnClear/AFormElementBtnClear.js +4 -1
  105. package/src/ui/AInputCurrency/AInputCurrency.js +20 -15
  106. package/src/ui/AInputCurrency/__tests__/AInputCurrency.ModelAPI.test.js +73 -73
  107. package/src/ui/AInputNumber/AInputNumber.js +17 -12
  108. package/src/ui/AJson/AJson.js +12 -3
  109. package/src/ui/AJson/compositionAPI/JsonAPI.js +116 -116
  110. package/src/ui/ALabel/__tests__/ALabel.IdAPI.test.js +42 -42
  111. package/src/ui/ALabel/__tests__/ALabel.LabelAPI.test.js +33 -33
  112. package/src/ui/ARadio/ARadio.js +80 -77
  113. package/src/ui/ASelect/ASelect.js +390 -383
  114. package/src/ui/ASelect/ASelectElement/ASelectElement.js +179 -176
  115. package/src/ui/ASelect/ASelectValueCloseable/ASelectValueCloseable.js +143 -141
  116. package/src/ui/ASelect/__tests__/SelectedFirstAPI.test.js +101 -101
  117. package/src/ui/ASelect/__tests__/SelectedVisibleAPI.test.js +98 -98
  118. package/src/ui/ASlider/compositionAPI/SliderAPI.js +23 -23
  119. package/src/ui/AValidatedJson/AValidatedJson.js +4 -1
  120. package/src/ui/AValidatedJson/AValidatedJsonItem/AValidatedJsonItem.js +308 -298
  121. package/src/ui/compositionApi/UiCollapseAPI.js +68 -63
  122. package/src/ui/compositionApi/UiInputAutofillAPI.js +41 -41
  123. package/src/ui/compositionApi/__tests__/UIDataGroupAPI.test.js +106 -106
  124. package/src/ui/compositionApi/__tests__/UIExcludeRenderAttributesAPI.test.js +39 -39
  125. package/src/ui/compositionApi/__tests__/UiDataWithKeyIdAndLabelAPI.test.js +128 -128
  126. package/src/ui/compositionApi/__tests__/UiSearchAPI.test.js +71 -71
  127. package/src/utils/EventBus.js +51 -8
  128. package/src/utils/__tests__/EventBus.test.js +138 -0
  129. package/src/utils/__tests__/utils.aOrderBy.test.js +1 -1
  130. package/src/utils/__tests__/utils.aSortBy.test.js +1 -1
  131. package/src/utils/__tests__/utils.getTotalNestedCount.test.js +56 -56
  132. package/src/utils/__tests__/utils.isArrayOfArrays.test.js +44 -44
  133. package/src/utils/__tests__/utils.isArrayOfStrings.test.js +36 -36
  134. package/src/utils/__tests__/utilsArray.aFirst.test.js +1 -1
  135. package/src/utils/__tests__/utilsArray.aLast.test.js +1 -1
  136. package/src/utils/__tests__/utilsLang.isArguments.test.js +1 -1
  137. package/src/utils/__tests__/utilsLang.isArray.test.js +1 -1
  138. package/src/utils/__tests__/utilsLang.isArrayBuffer.test.js +1 -1
  139. package/src/utils/__tests__/utilsLang.isBoolean.test.js +1 -1
  140. package/src/utils/__tests__/utilsLang.isBuffer.test.js +1 -1
  141. package/src/utils/__tests__/utilsLang.isDate.test.js +1 -1
  142. package/src/utils/__tests__/utilsLang.isElement.test.js +5 -3
  143. package/src/utils/__tests__/utilsLang.isError.test.js +1 -1
  144. package/src/utils/__tests__/utilsLang.isFinite.test.js +1 -1
  145. package/src/utils/__tests__/utilsLang.isFunction.test.js +1 -1
  146. package/src/utils/__tests__/utilsLang.isInteger.test.js +1 -1
  147. package/src/utils/__tests__/utilsLang.isMap.test.js +1 -1
  148. package/src/utils/__tests__/utilsLang.isNaN.test.js +1 -1
  149. package/src/utils/__tests__/utilsLang.isNil.test.js +1 -1
  150. package/src/utils/__tests__/utilsLang.isNull.test.js +1 -1
  151. package/src/utils/__tests__/utilsLang.isNumber.test.js +1 -1
  152. package/src/utils/__tests__/utilsLang.isObject.test.js +1 -1
  153. package/src/utils/__tests__/utilsLang.isObjectLike.test.js +5 -3
  154. package/src/utils/__tests__/utilsLang.isPlainObject.test.js +3 -2
  155. package/src/utils/__tests__/utilsLang.isPromise.test.js +5 -2
  156. package/src/utils/__tests__/utilsLang.isRegExp.test.js +1 -1
  157. package/src/utils/__tests__/utilsLang.isSet.test.js +1 -1
  158. package/src/utils/__tests__/utilsLang.isString.test.js +1 -1
  159. package/src/utils/__tests__/utilsLang.isSymbol.test.js +5 -3
  160. package/src/utils/__tests__/utilsLang.isUndefined.test.js +1 -1
  161. package/src/utils/__tests__/utilsLang.isWeakMap.test.js +1 -1
  162. package/src/utils/__tests__/utilsLang.isWeakSet.test.js +1 -1
  163. package/src/utils/__tests__/utilsMath.isEven.test.js +43 -43
  164. package/src/utils/__tests__/utilsMath.isOdd.test.js +43 -43
  165. package/src/utils/__tests__/utilsUi.isModelForFilterNotEmpty.test.js +65 -65
  166. package/src/utils/autosize.js +1 -1
@@ -1,912 +1,912 @@
1
- /* eslint vue/component-api-style: off */
2
- import {
3
- h,
4
- ref,
5
- withDirectives,
6
- } from "vue";
7
-
8
- import ADatepickerCalendarPanel from "./ADatepickerCalendarPanel/ADatepickerCalendarPanel";
9
- import ADatepickerIcon from "./ADatepickerIcon/ADatepickerIcon";
10
- import AErrorsText from "../AErrorsText/AErrorsText";
11
- import ALabel from "../ALabel/ALabel";
12
-
13
- import UiAPI from "../compositionApi/UiAPI";
14
- import UiInputAutofillAPI from "../compositionApi/UiInputAutofillAPI";
15
- import UiStyleHideAPI from "../compositionApi/UiStyleHideAPI";
16
-
17
- import AKeysCode from "../../const/AKeysCode";
18
- import ASafeHtml from "../../directives/ASafeHtml";
19
- import Languages from "./locale/languages";
20
- import UiMixinProps from "../mixins/UiMixinProps";
21
- import moment from "moment";
22
- import {
23
- formatDate,
24
- isDateObject,
25
- isPlainObject,
26
- isValidDate,
27
- isValidRangeDate,
28
- parseDate,
29
- throttle,
30
- } from "./utils";
31
- import {
32
- transformDate,
33
- } from "./utils/transform";
34
-
35
-
36
- // @vue/component
37
- export default {
38
- name: "ADatepicker",
39
- mixins: [
40
- UiMixinProps,
41
- ],
42
- props: {
43
- modelValue: {
44
- type: [String, Number, Boolean, Array, Object, Date, Function, Symbol],
45
- default: undefined,
46
- },
47
- valueType: {
48
- default: "format",
49
- validator: function(value) {
50
- return ["timestamp", "format", "date"].indexOf(value) !== -1 || isPlainObject(value);
51
- },
52
- },
53
- placeholder: {
54
- type: String,
55
- default: null,
56
- },
57
- lang: {
58
- type: String,
59
- default: "de",
60
- required: false,
61
- },
62
- languages: {
63
- type: Object,
64
- default: undefined,
65
- required: false,
66
- },
67
- format: {
68
- type: [String, Object],
69
- default: "DD.MM.YYYY",
70
- },
71
- dateFormat: {
72
- type: String, // format the time header and date tooltip
73
- default: undefined,
74
- },
75
- type: {
76
- type: String,
77
- default: "date", // ["date", "datetime"] zendy added "month", "year", mxie added "time"
78
- },
79
- range: {
80
- type: Boolean,
81
- default: false,
82
- },
83
- rangeSeparator: {
84
- type: String,
85
- default: "~",
86
- },
87
- width: {
88
- type: [String, Number],
89
- default: null,
90
- },
91
- confirmText: {
92
- type: String,
93
- default: "OK",
94
- },
95
- confirm: {
96
- type: Boolean,
97
- default: false,
98
- },
99
- editable: {
100
- type: Boolean,
101
- default: true,
102
- },
103
- disabled: {
104
- type: Boolean,
105
- default: false,
106
- },
107
- clearable: {
108
- type: Boolean,
109
- default: true,
110
- },
111
- shortcuts: {
112
- type: [Boolean, Array],
113
- default: true,
114
- },
115
- inputName: {
116
- type: String,
117
- default: "date",
118
- },
119
- inputClass: {
120
- type: [String, Number, Boolean, Array, Object, Date, Function, Symbol],
121
- default: "pux_datepicker__input",
122
- },
123
- inputAttr: {
124
- type: Object,
125
- required: false,
126
- default: () => ({}),
127
- },
128
- appendToBody: {
129
- type: Boolean,
130
- default: false,
131
- },
132
- popupStyle: {
133
- type: Object,
134
- default: undefined,
135
- },
136
- iconDay: {
137
- type: [Number, String],
138
- default: undefined,
139
- },
140
- isLabelFloat: {
141
- type: Boolean,
142
- required: false,
143
- default: false,
144
- },
145
- formatSave: {
146
- type: String,
147
- required: false,
148
- default: "YYYY-MM-DD",
149
- },
150
- },
151
- emits: [
152
- "blur",
153
- "change",
154
- "clear",
155
- "confirm",
156
- "focus",
157
- "input",
158
- "inputError",
159
- "changeCalendarMonth",
160
- "changeCalendarYear",
161
- ],
162
- setup(props, context) {
163
- const {
164
- componentStyleHide,
165
- } = UiStyleHideAPI(props);
166
-
167
- const {
168
- ariaDescribedbyLocal,
169
- changeModel,
170
- clearModel,
171
- errorsId,
172
- helpTextId,
173
- htmlIdLocal,
174
- isErrors,
175
- isModel,
176
- onBlur,
177
- onFocus,
178
- } = UiAPI(props, context);
179
-
180
- const inputRef = ref(undefined);
181
- const {
182
- isAutofill,
183
- } = UiInputAutofillAPI({ inputRef });
184
-
185
- const blur = () => {
186
- inputRef.value && inputRef.value.blur();
187
- };
188
-
189
- return {
190
- componentStyleHide,
191
-
192
- ariaDescribedbyLocal,
193
- changeModel,
194
- clearModel,
195
- errorsId,
196
- helpTextId,
197
- htmlIdLocal,
198
- isErrors,
199
- isModel,
200
- onBlur,
201
- onFocus,
202
-
203
- blur,
204
- inputRef,
205
- isAutofill,
206
- };
207
- },
208
- data() {
209
- return {
210
- currentValue: this.range ? [null, null] : null,
211
- userInput: null,
212
- popupVisible: false,
213
- position: {},
214
- };
215
- },
216
- computed: {
217
- transform() {
218
- const type = this.valueType;
219
- if (isPlainObject(type)) {
220
- return { ...transformDate.date, ...type };
221
- }
222
- if (type === "format") {
223
- return {
224
- value2date: this.parse.bind(this),
225
- date2value: this.stringify.bind(this),
226
- };
227
- }
228
- return transformDate[type] || transformDate.date;
229
- },
230
-
231
- languagesLocal() {
232
- if (isPlainObject(this.languages)) {
233
- return {
234
- ...Languages,
235
- ...this.languages,
236
- };
237
- }
238
- return Languages;
239
- },
240
-
241
- currentLanguage() {
242
- return this.languagesLocal[this.lang];
243
- },
244
-
245
- innerPlaceholder() {
246
- if (typeof this.placeholder === "string") {
247
- return this.placeholder;
248
- }
249
- if (this.range) {
250
- return this.currentLanguage.placeholder.dateRange;
251
- }
252
- if (this.type === "time") {
253
- return this.currentLanguage.placeholder.time;
254
- }
255
- return this.currentLanguage.placeholder.date;
256
- },
257
-
258
- text() {
259
- if (this.userInput !== null) {
260
- return this.userInput;
261
- }
262
- const {
263
- value2date,
264
- } = this.transform;
265
- if (!this.range) {
266
- return this.isValidValueText(this.modelValue)
267
- ? this.stringify(this.value2dateText(this.modelValue))
268
- : "";
269
- }
270
- return this.isValidRangeValue(this.modelValue)
271
- ? `${ this.stringify(value2date(this.modelValue[0])) } ${ this.rangeSeparator } ${ this.stringify(value2date(this.modelValue[1])) }`
272
- : "";
273
- },
274
-
275
- computedWidth() {
276
- if (typeof this.width === "number" || (typeof this.width === "string" && /^\d+$/.test(this.width))) {
277
- return this.width + "px";
278
- }
279
- return this.width;
280
- },
281
-
282
- showClearIcon() {
283
- return !this.disabled && this.clearable && (this.range ? this.isValidRangeValue(this.modelValue) : this.isValidValue(this.modelValue));
284
- },
285
-
286
- innerType() {
287
- return String(this.type).toLowerCase();
288
- },
289
-
290
- innerShortcuts() {
291
- if (Array.isArray(this.shortcuts)) {
292
- return this.shortcuts;
293
- }
294
- if (this.shortcuts === false) {
295
- return [];
296
- }
297
- const pickers = this.currentLanguage.pickers;
298
- const arr = [
299
- {
300
- text: pickers[0],
301
- onClick(self) {
302
- self.currentValue = [new Date(), new Date(Date.now() + 3600 * 1000 * 24 * 7)];
303
- self.updateDate(true);
304
- },
305
- },
306
- {
307
- text: pickers[1],
308
- onClick(self) {
309
- self.currentValue = [new Date(), new Date(Date.now() + 3600 * 1000 * 24 * 30)];
310
- self.updateDate(true);
311
- },
312
- },
313
- {
314
- text: pickers[2],
315
- onClick(self) {
316
- self.currentValue = [new Date(Date.now() - 3600 * 1000 * 24 * 7), new Date()];
317
- self.updateDate(true);
318
- },
319
- },
320
- {
321
- text: pickers[3],
322
- onClick(self) {
323
- self.currentValue = [new Date(Date.now() - 3600 * 1000 * 24 * 30), new Date()];
324
- self.updateDate(true);
325
- },
326
- },
327
- ];
328
- return arr;
329
- },
330
-
331
- innerDateFormat() {
332
- if (this.dateFormat) {
333
- return this.dateFormat;
334
- }
335
- if (typeof this.format !== "string") {
336
- return "YYYY-MM-DD";
337
- }
338
- if (this.innerType === "date") {
339
- return this.format;
340
- }
341
- return this.format.replace(/[Hh]+.*[msSaAZ]|\[.*?\]/g, "").trim() || "YYYY-MM-DD";
342
- },
343
-
344
- innerPopupStyle() {
345
- return { ...this.position, ...this.popupStyle };
346
- },
347
-
348
- idForPanel() {
349
- return `${ this.id }_panel`;
350
- },
351
-
352
- idsForPanelRange() {
353
- return [
354
- `${ this.idForPanel }_0`,
355
- `${ this.idForPanel }_1`,
356
- ];
357
- },
358
-
359
- ariaHiddenForCalendar() {
360
- return `${ !this.popupVisible }`;
361
- },
362
-
363
- ariaExpandedForCalendar() {
364
- return `${ this.popupVisible }`;
365
- },
366
-
367
- idForCalendar() {
368
- return `${ this.id }_calendar`;
369
- },
370
- },
371
- watch: {
372
- value: {
373
- immediate: true,
374
- handler: "handleValueChange",
375
- },
376
-
377
- popupVisible(val) {
378
- if (val) {
379
- this.initCalendar();
380
- } else {
381
- this.userInput = null;
382
- this.blur();
383
- }
384
- },
385
- },
386
- mounted() {
387
- if (this.appendToBody) {
388
- this.popupElm = this.$refs.calendar;
389
- document.body.appendChild(this.popupElm);
390
- }
391
- // clickoutside close popup
392
- let mousedownTarget;
393
- this._bindDocmentMousedown = evt => {
394
- mousedownTarget = evt.target;
395
- };
396
- this._bindDocumentMouseup = evt => {
397
- const mouseupTarget = evt.target;
398
- const el = this.$el;
399
- const { popupElm } = this;
400
- if (
401
- !mousedownTarget ||
402
- !mouseupTarget ||
403
- el.contains(mousedownTarget) ||
404
- el.contains(mouseupTarget) ||
405
- (popupElm && (popupElm.contains(mousedownTarget) || popupElm.contains(mouseupTarget)))
406
- ) {
407
- return;
408
- }
409
- mousedownTarget = null;
410
- this.closePopup();
411
- };
412
- this._startEvt = "mousedown";
413
- this._endEvt = "mouseup";
414
- if ("ontouchend" in document) {
415
- this._startEvt = "touchstart";
416
- this._endEvt = "touchend";
417
- }
418
- document.addEventListener(this._startEvt, this._bindDocmentMousedown);
419
- document.addEventListener(this._endEvt, this._bindDocumentMouseup);
420
-
421
- this._displayPopup = throttle(() => {
422
- if (this.popupVisible) {
423
- this.displayPopup();
424
- }
425
- }, 200);
426
- window.addEventListener("resize", this._displayPopup);
427
- window.addEventListener("scroll", this._displayPopup);
428
- },
429
- beforeUnmount() {
430
- if (this.popupElm && this.popupElm.parentNode === document.body) {
431
- document.body.removeChild(this.popupElm);
432
- }
433
- document.removeEventListener(this._startEvt, this._bindDocmentMousedown);
434
- document.removeEventListener(this._endEvt, this._bindDocumentMouseup);
435
- window.removeEventListener("resize", this._displayPopup);
436
- window.removeEventListener("scroll", this._displayPopup);
437
- },
438
- methods: {
439
- initCalendar() {
440
- this.handleValueChange(this.modelValue);
441
- this.displayPopup();
442
- },
443
-
444
- stringify(date) {
445
- return (isPlainObject(this.format) && typeof this.format.stringify === "function")
446
- ? this.format.stringify(date)
447
- : formatDate(date, this.format);
448
- },
449
-
450
- parse(value) {
451
- return (isPlainObject(this.format) && typeof this.format.parse === "function")
452
- ? this.format.parse(value)
453
- : parseDate(value, this.format, this.formatSave);
454
- },
455
-
456
- isValidValue(value) {
457
- const { value2date } = this.transform;
458
- return isValidDate(value2date(value));
459
- },
460
-
461
- isValidRangeValue(value) {
462
- const { value2date } = this.transform;
463
- return Array.isArray(value) && value.length === 2 && this.isValidValue(value[0]) &&
464
- this.isValidValue(value[1]) && (value2date(value[1]).getTime() >= value2date(value[0]).getTime());
465
- },
466
-
467
- dateEqual(a, b) {
468
- return isDateObject(a) && isDateObject(b) && a.getTime() === b.getTime();
469
- },
470
-
471
- rangeEqual(a, b) {
472
- return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((item, index) => this.dateEqual(item, b[index]));
473
- },
474
-
475
- selectRange(range) {
476
- if (typeof range.onClick === "function") {
477
- const close = range.onClick(this);
478
- if (close !== false) {
479
- this.closePopup();
480
- }
481
- } else {
482
- this.currentValue = [new Date(range.start), new Date(range.end)];
483
- this.updateDate(true);
484
- this.closePopup();
485
- }
486
- },
487
-
488
- clearDate($event) {
489
- if ($event) {
490
- $event.stopPropagation();
491
- }
492
- const date = this.range ? [null, null] : null;
493
- this.currentValue = date;
494
- this.updateDate(true);
495
- this.$emit("clear");
496
- },
497
-
498
- confirmDate() {
499
- const valid = this.range ? isValidRangeDate(this.currentValue) : isValidDate(this.currentValue);
500
- if (valid) {
501
- this.updateDate(true);
502
- }
503
- this.emitDate("confirm");
504
- this.closePopup();
505
- },
506
-
507
- updateDate(confirm = false) {
508
- if ((this.confirm && !confirm) || this.disabled) {
509
- return false;
510
- }
511
- const equal = this.range ? this.rangeEqual(this.modelValue, this.currentValue) : this.dateEqual(this.modelValue, this.currentValue);
512
- if (equal) {
513
- return false;
514
- }
515
- this.emitDate("change");
516
- return true;
517
- },
518
-
519
- emitDate(eventName) {
520
- const { date2value } = this.transform;
521
- const value = this.range
522
- ? this.currentValue.map(date2value)
523
- : formatDate(this.currentValue, this.formatSave);
524
- this.changeModel({
525
- model: value,
526
- });
527
- this.$emit(eventName, value);
528
- },
529
-
530
- handleValueChange(value) {
531
- const { value2date } = this.transform;
532
- if (this.range) {
533
- this.currentValue = this.isValidRangeValue(value) ? value.map(value2date) : [null, null];
534
- } else {
535
- this.currentValue = this.isValidValue(value) ? value2date(value) : null;
536
- }
537
- },
538
-
539
- selectDate(date) {
540
- this.currentValue = date;
541
- this.updateDate() && this.closePopup();
542
- this.setCloseFocus();
543
- },
544
-
545
- selectStartDate(date) {
546
- this.currentValue[0] = date;
547
- if (this.currentValue[1]) {
548
- this.updateDate();
549
- }
550
- },
551
-
552
- selectEndDate(date) {
553
- this.currentValue[1] = date;
554
- if (this.currentValue[0]) {
555
- this.updateDate();
556
- }
557
- },
558
-
559
- selectTime(time, close) {
560
- this.currentValue = time;
561
- this.updateDate() && close && this.closePopup();
562
- if (close) {
563
- this.setCloseFocus();
564
- }
565
- },
566
-
567
- selectStartTime(time) {
568
- this.selectStartDate(time);
569
- },
570
-
571
- selectEndTime(time) {
572
- this.selectEndDate(time);
573
- },
574
-
575
- showPopup() {
576
- if (this.disabled) {
577
- return;
578
- }
579
- this.popupVisible = true;
580
- },
581
-
582
- closePopup(isSetFocusByClose) {
583
- this.popupVisible = false;
584
- if (isSetFocusByClose) {
585
- this.setCloseFocus();
586
- }
587
- },
588
-
589
- getPopupSize(element) {
590
- const originalDisplay = element.style.display;
591
- const originalVisibility = element.style.visibility;
592
- element.style.display = "block";
593
- element.style.visibility = "hidden";
594
- const styles = window.getComputedStyle(element);
595
- const width = element.offsetWidth + parseInt(styles.marginLeft) + parseInt(styles.marginRight);
596
- const height = element.offsetHeight + parseInt(styles.marginTop) + parseInt(styles.marginBottom);
597
- const result = { width, height };
598
- element.style.display = originalDisplay;
599
- element.style.visibility = originalVisibility;
600
- return result;
601
- },
602
-
603
- displayPopup() {
604
- const dw = document.documentElement.clientWidth;
605
- const dh = document.documentElement.clientHeight;
606
- const InputRect = this.$refs.inputRef.getBoundingClientRect();
607
- const PopupRect = this._popupRect || (this._popupRect = this.getPopupSize(this.$refs.calendar));
608
- const position = {};
609
- let offsetRelativeToInputX = 0;
610
- let offsetRelativeToInputY = 0;
611
- if (this.appendToBody) {
612
- offsetRelativeToInputX = window.pageXOffset + InputRect.left;
613
- offsetRelativeToInputY = window.pageYOffset + InputRect.top;
614
- }
615
- if (
616
- dw - InputRect.left < PopupRect.width &&
617
- InputRect.right < PopupRect.width
618
- ) {
619
- position.left = offsetRelativeToInputX - InputRect.left + 1 + "px";
620
- } else if (InputRect.left + InputRect.width / 2 <= dw / 2) {
621
- position.left = offsetRelativeToInputX + "px";
622
- } else {
623
- position.left = offsetRelativeToInputX + InputRect.width - PopupRect.width + "px";
624
- }
625
- if (
626
- InputRect.top <= PopupRect.height &&
627
- dh - InputRect.bottom <= PopupRect.height
628
- ) {
629
- position.top = offsetRelativeToInputY + dh - InputRect.top - PopupRect.height + "px";
630
- } else if (InputRect.top + InputRect.height / 2 <= dh / 2) {
631
- position.top = offsetRelativeToInputY + InputRect.height + "px";
632
- } else {
633
- position.top = offsetRelativeToInputY - PopupRect.height + "px";
634
- }
635
- if (position.top !== this.position.top || position.left !== this.position.left) {
636
- this.position = position;
637
- }
638
- },
639
-
640
- handleBlur(event) {
641
- this.$emit("blur", event);
642
- },
643
-
644
- handleFocus(event) {
645
- if (!this.popupVisible) {
646
- this.showPopup();
647
- }
648
- this.$emit("focus", event);
649
- },
650
-
651
- handleKeydown($event) {
652
- const KEY_CODE = $event.keyCode;
653
- if (KEY_CODE === AKeysCode.tab || KEY_CODE === AKeysCode.enter) {
654
- // ie emit the watch before the change event
655
- this.handleChange();
656
- this.userInput = null;
657
- this.closePopup();
658
- } else if (KEY_CODE === AKeysCode.arrowUp || KEY_CODE === AKeysCode.arrowDown) {
659
- this.setFocusToPanel();
660
- $event.stopPropagation();
661
- $event.preventDefault();
662
- }
663
- },
664
-
665
- handleInput(event) {
666
- this.userInput = event.target.value;
667
- },
668
-
669
- handleChange() {
670
- if (this.editable && this.userInput !== null) {
671
- let value = this.text;
672
- const checkDate = this.$refs.calendarPanel.isDisabledTime;
673
- if (!value) {
674
- this.clearDate();
675
- return;
676
- }
677
- if (this.range) {
678
- const range = value.split(` ${ this.rangeSeparator } `);
679
- if (range.length === 2) {
680
- const start = this.parse(range[0]);
681
- const end = this.parse(range[1]);
682
- if (start && end && !checkDate(start, null, end) && !checkDate(end, start, null)) {
683
- this.currentValue = [start, end];
684
- this.updateDate(true);
685
- this.closePopup();
686
- return;
687
- }
688
- }
689
- } else {
690
- if (this.type === "time") {
691
- value = `${ moment().format("DD.MM.YYYY") } ${ value }`;
692
- }
693
- const date = this.parse(value);
694
- if (date && !checkDate(date, null, null)) {
695
- this.currentValue = date;
696
- this.updateDate(true);
697
- this.closePopup();
698
- return;
699
- }
700
- }
701
- this.$emit("inputError", value);
702
- }
703
- },
704
-
705
- setFocusToPanel() {
706
- this.$refs.calendarPanel.setFocusToActivePanelFromParent();
707
- },
708
-
709
- setCloseFocus() {
710
- this.$refs.focusByClose && this.$refs.focusByClose.focus();
711
- },
712
-
713
- isValidValueText(value) {
714
- return !!parseDate(value, this.format, this.formatSave);
715
- },
716
-
717
- value2dateText(value) {
718
- let dateValue = null;
719
- try {
720
- dateValue = moment(value, this.formatSave) || null;
721
- } catch (e) {
722
-
723
- }
724
- if (dateValue && dateValue.isValid && !dateValue.isValid()) {
725
- dateValue = null;
726
- }
727
- return dateValue;
728
- },
729
- },
730
- render() {
731
- return this.isRender && h("div", {
732
- style: this.componentStyleHide,
733
- }, [
734
- h("div", {
735
- class: ["a_form_element__parent", {
736
- a_form_element__parent_float: this.isLabelFloat,
737
- a_form_element__parent_not_empty: this.isModel || this.isAutofill,
738
- }],
739
- }, [
740
- this.label && h(ALabel, {
741
- id: this.htmlIdLocal,
742
- extra: this.extra,
743
- label: this.label,
744
- labelClass: this.labelClass,
745
- required: this.required,
746
- type: this.type,
747
- isLabelFloat: this.isLabelFloat,
748
- }),
749
- h("div", {
750
- class: "a_form_element",
751
- }, [
752
- h("div", {
753
- class: ["pux_datepicker", {
754
- pux_datepicker_range: this.range,
755
- disabled: this.disabled,
756
- }],
757
- style: { width: this.computedWidth },
758
- onMousedown: this.showPopup,
759
- onTouchstart: this.showPopup,
760
- }, [
761
- h("div", {
762
- class: "pux_datepicker__input_wrapper",
763
- role: "application",
764
- }, [
765
- h("input", {
766
- ref: "inputRef",
767
- id: this.htmlIdLocal,
768
- class: [
769
- "a_form_control pux_datepicker__input",
770
- this.inputClass,
771
- {
772
- a_form_control_invalid: this.isErrors,
773
- },
774
- ],
775
- name: this.inputName,
776
- type: "text",
777
- autocomplete: "off",
778
- disabled: this.disabled,
779
- readonly: !this.editable,
780
- value: this.text,
781
- placeholder: this.innerPlaceholder,
782
- ariaHaspopup: true,
783
- "aria-owns": this.idForCalendar,
784
- ...this.inputAttr,
785
- onKeydown: this.handleKeydown,
786
- onFocus: this.handleFocus,
787
- onBlur: this.handleBlur,
788
- onInput: this.handleInput,
789
- onChange: this.handleChange,
790
- }),
791
- this.showClearIcon && h("span", {
792
- class: "pux_datepicker__input_wrapper__append pux_datepicker__input_wrapper__clear_wrapper",
793
- ariaHidden: true,
794
- onMousedown: this.clearDate,
795
- }, [
796
- h("i", {
797
- class: "pux_datepicker__input__icon pux_datepicker__input__clear_icon",
798
- }),
799
- ]),
800
- h("span", {
801
- class: "pux_datepicker__input_wrapper__append",
802
- }, [
803
- h(ADatepickerIcon),
804
- ]),
805
- ]),
806
- h("div", {
807
- ref: "calendar",
808
- id: this.idForCalendar,
809
- class: "pux_datepicker__popup",
810
- ariaHidden: this.ariaHiddenForCalendar,
811
- ariaExpanded: this.ariaExpandedForCalendar,
812
- style: [this.innerPopupStyle, !this.popupVisible ? "display: none;" : ""],
813
- }, [
814
- !!(this.range && this.innerShortcuts.length) && h("div", {
815
- class: "pux_datepicker__shortcuts_wrapper",
816
- }, [
817
- this.innerShortcuts.map((range, index) => {
818
- return h("button", {
819
- key: index,
820
- class: "pux_datepicker__shortcuts_wrapper__shortcuts",
821
- type: "button",
822
- onClick: () => this.selectRange(range),
823
- }, range.text);
824
- }),
825
- ]),
826
- !this.range ?
827
- h(ADatepickerCalendarPanel, {
828
- ref: "calendarPanel",
829
- id: this.idForPanel,
830
- index: -1,
831
- type: this.innerType,
832
- dateFormat: this.innerDateFormat,
833
- value: this.currentValue,
834
- visible: this.popupVisible,
835
- currentLanguage: this.currentLanguage,
836
- onSelectDate: this.selectDate,
837
- onSelectTime: this.selectTime,
838
- onClosePopup: this.closePopup,
839
- }) :
840
- h("div", {
841
- class: "pux_datepicker__range_wrapper",
842
- }, [
843
- h(ADatepickerCalendarPanel, {
844
- ref: "calendarPanel",
845
- id: this.idsForPanelRange[0],
846
- style: "box-shadow: 1px 0 rgba(0, 0, 0, .1);",
847
- index: 0,
848
- type: this.innerType,
849
- dateFormat: this.innerDateFormat,
850
- value: this.currentValue[0],
851
- endAt: this.currentValue[1],
852
- startAt: null,
853
- visible: this.popupVisible,
854
- currentLanguage: this.currentLanguage,
855
- onSelectDate: this.selectStartDate,
856
- onSelectTime: this.selectStartTime,
857
- onClosePopup: this.closePopup,
858
- }),
859
- h(ADatepickerCalendarPanel, {
860
- ref: "calendarPanel2",
861
- id: this.idsForPanelRange[1],
862
- index: 1,
863
- type: this.innerType,
864
- dateFormat: this.innerDateFormat,
865
- value: this.currentValue[1],
866
- endAt: null,
867
- startAt: this.currentValue[0],
868
- visible: this.popupVisible,
869
- currentLanguage: this.currentLanguage,
870
- onSelectDate: this.selectEndDate,
871
- onSelectTime: this.selectEndTime,
872
- onClosePopup: this.closePopup,
873
- }),
874
- ]),
875
- this.confirm && h("div", {
876
- class: "pux_datepicker__footer",
877
- }, [
878
- h("button", {
879
- class: "pux_datepicker__footer__btn pux_datepicker__footer__btn_confirm",
880
- type: "button",
881
- onClick: this.confirmDate,
882
- }, this.confirmText),
883
- ]),
884
- ]),
885
- h("div", {
886
- ref: "focusByClose",
887
- tabindex: -1,
888
- }),
889
- ]),
890
-
891
- /*
892
- * this.isClearButtonLocal && h(AFormElementBtnClear, {
893
- * disabled: this.disabled,
894
- * clearButtonClass: this.clearButtonClass,
895
- * onClear: this.clearModel,
896
- * }),
897
- */
898
- ]),
899
- this.helpText && withDirectives(h("div", {
900
- id: this.helpTextId,
901
- class: "a_form_element__help_text",
902
- }), [
903
- [ASafeHtml, this.helpText],
904
- ]),
905
- this.isErrors && h(AErrorsText, {
906
- id: this.errorsId,
907
- errors: this.errors,
908
- }),
909
- ]),
910
- ]);
911
- },
912
- };
1
+ /* eslint vue/component-api-style: off */
2
+ import {
3
+ h,
4
+ ref,
5
+ withDirectives,
6
+ } from "vue";
7
+
8
+ import ADatepickerCalendarPanel from "./ADatepickerCalendarPanel/ADatepickerCalendarPanel";
9
+ import ADatepickerIcon from "./ADatepickerIcon/ADatepickerIcon";
10
+ import AErrorsText from "../AErrorsText/AErrorsText";
11
+ import ALabel from "../ALabel/ALabel";
12
+
13
+ import UiAPI from "../compositionApi/UiAPI";
14
+ import UiInputAutofillAPI from "../compositionApi/UiInputAutofillAPI";
15
+ import UiStyleHideAPI from "../compositionApi/UiStyleHideAPI";
16
+
17
+ import AKeysCode from "../../const/AKeysCode";
18
+ import ASafeHtml from "../../directives/ASafeHtml";
19
+ import Languages from "./locale/languages";
20
+ import UiMixinProps from "../mixins/UiMixinProps";
21
+ import moment from "moment";
22
+ import {
23
+ formatDate,
24
+ isDateObject,
25
+ isPlainObject,
26
+ isValidDate,
27
+ isValidRangeDate,
28
+ parseDate,
29
+ throttle,
30
+ } from "./utils";
31
+ import {
32
+ transformDate,
33
+ } from "./utils/transform";
34
+
35
+
36
+ // @vue/component
37
+ export default {
38
+ name: "ADatepicker",
39
+ mixins: [
40
+ UiMixinProps,
41
+ ],
42
+ props: {
43
+ modelValue: {
44
+ type: [String, Number, Boolean, Array, Object, Date, Function, Symbol],
45
+ default: undefined,
46
+ },
47
+ valueType: {
48
+ default: "format",
49
+ validator: function(value) {
50
+ return ["timestamp", "format", "date"].indexOf(value) !== -1 || isPlainObject(value);
51
+ },
52
+ },
53
+ placeholder: {
54
+ type: String,
55
+ default: null,
56
+ },
57
+ lang: {
58
+ type: String,
59
+ default: "de",
60
+ required: false,
61
+ },
62
+ languages: {
63
+ type: Object,
64
+ default: undefined,
65
+ required: false,
66
+ },
67
+ format: {
68
+ type: [String, Object],
69
+ default: "DD.MM.YYYY",
70
+ },
71
+ dateFormat: {
72
+ type: String, // format the time header and date tooltip
73
+ default: undefined,
74
+ },
75
+ type: {
76
+ type: String,
77
+ default: "date", // ["date", "datetime"] zendy added "month", "year", mxie added "time"
78
+ },
79
+ range: {
80
+ type: Boolean,
81
+ default: false,
82
+ },
83
+ rangeSeparator: {
84
+ type: String,
85
+ default: "~",
86
+ },
87
+ width: {
88
+ type: [String, Number],
89
+ default: null,
90
+ },
91
+ confirmText: {
92
+ type: String,
93
+ default: "OK",
94
+ },
95
+ confirm: {
96
+ type: Boolean,
97
+ default: false,
98
+ },
99
+ editable: {
100
+ type: Boolean,
101
+ default: true,
102
+ },
103
+ disabled: {
104
+ type: Boolean,
105
+ default: false,
106
+ },
107
+ clearable: {
108
+ type: Boolean,
109
+ default: true,
110
+ },
111
+ shortcuts: {
112
+ type: [Boolean, Array],
113
+ default: true,
114
+ },
115
+ inputName: {
116
+ type: String,
117
+ default: "date",
118
+ },
119
+ inputClass: {
120
+ type: [String, Number, Boolean, Array, Object, Date, Function, Symbol],
121
+ default: "pux_datepicker__input",
122
+ },
123
+ inputAttr: {
124
+ type: Object,
125
+ required: false,
126
+ default: () => ({}),
127
+ },
128
+ appendToBody: {
129
+ type: Boolean,
130
+ default: false,
131
+ },
132
+ popupStyle: {
133
+ type: Object,
134
+ default: undefined,
135
+ },
136
+ iconDay: {
137
+ type: [Number, String],
138
+ default: undefined,
139
+ },
140
+ isLabelFloat: {
141
+ type: Boolean,
142
+ required: false,
143
+ default: false,
144
+ },
145
+ formatSave: {
146
+ type: String,
147
+ required: false,
148
+ default: "YYYY-MM-DD",
149
+ },
150
+ },
151
+ emits: [
152
+ "blur",
153
+ "change",
154
+ "clear",
155
+ "confirm",
156
+ "focus",
157
+ "input",
158
+ "inputError",
159
+ "changeCalendarMonth",
160
+ "changeCalendarYear",
161
+ ],
162
+ setup(props, context) {
163
+ const {
164
+ componentStyleHide,
165
+ } = UiStyleHideAPI(props);
166
+
167
+ const {
168
+ ariaDescribedbyLocal,
169
+ changeModel,
170
+ clearModel,
171
+ errorsId,
172
+ helpTextId,
173
+ htmlIdLocal,
174
+ isErrors,
175
+ isModel,
176
+ onBlur,
177
+ onFocus,
178
+ } = UiAPI(props, context);
179
+
180
+ const inputRef = ref(undefined);
181
+ const {
182
+ isAutofill,
183
+ } = UiInputAutofillAPI({ inputRef });
184
+
185
+ const blur = () => {
186
+ inputRef.value && inputRef.value.blur();
187
+ };
188
+
189
+ return {
190
+ componentStyleHide,
191
+
192
+ ariaDescribedbyLocal,
193
+ changeModel,
194
+ clearModel,
195
+ errorsId,
196
+ helpTextId,
197
+ htmlIdLocal,
198
+ isErrors,
199
+ isModel,
200
+ onBlur,
201
+ onFocus,
202
+
203
+ blur,
204
+ inputRef,
205
+ isAutofill,
206
+ };
207
+ },
208
+ data() {
209
+ return {
210
+ currentValue: this.range ? [null, null] : null,
211
+ userInput: null,
212
+ popupVisible: false,
213
+ position: {},
214
+ };
215
+ },
216
+ computed: {
217
+ transform() {
218
+ const type = this.valueType;
219
+ if (isPlainObject(type)) {
220
+ return { ...transformDate.date, ...type };
221
+ }
222
+ if (type === "format") {
223
+ return {
224
+ value2date: this.parse.bind(this),
225
+ date2value: this.stringify.bind(this),
226
+ };
227
+ }
228
+ return transformDate[type] || transformDate.date;
229
+ },
230
+
231
+ languagesLocal() {
232
+ if (isPlainObject(this.languages)) {
233
+ return {
234
+ ...Languages,
235
+ ...this.languages,
236
+ };
237
+ }
238
+ return Languages;
239
+ },
240
+
241
+ currentLanguage() {
242
+ return this.languagesLocal[this.lang];
243
+ },
244
+
245
+ innerPlaceholder() {
246
+ if (typeof this.placeholder === "string") {
247
+ return this.placeholder;
248
+ }
249
+ if (this.range) {
250
+ return this.currentLanguage.placeholder.dateRange;
251
+ }
252
+ if (this.type === "time") {
253
+ return this.currentLanguage.placeholder.time;
254
+ }
255
+ return this.currentLanguage.placeholder.date;
256
+ },
257
+
258
+ text() {
259
+ if (this.userInput !== null) {
260
+ return this.userInput;
261
+ }
262
+ const {
263
+ value2date,
264
+ } = this.transform;
265
+ if (!this.range) {
266
+ return this.isValidValueText(this.modelValue)
267
+ ? this.stringify(this.value2dateText(this.modelValue))
268
+ : "";
269
+ }
270
+ return this.isValidRangeValue(this.modelValue)
271
+ ? `${ this.stringify(value2date(this.modelValue[0])) } ${ this.rangeSeparator } ${ this.stringify(value2date(this.modelValue[1])) }`
272
+ : "";
273
+ },
274
+
275
+ computedWidth() {
276
+ if (typeof this.width === "number" || (typeof this.width === "string" && /^\d+$/.test(this.width))) {
277
+ return this.width + "px";
278
+ }
279
+ return this.width;
280
+ },
281
+
282
+ showClearIcon() {
283
+ return !this.disabled && this.clearable && (this.range ? this.isValidRangeValue(this.modelValue) : this.isValidValue(this.modelValue));
284
+ },
285
+
286
+ innerType() {
287
+ return String(this.type).toLowerCase();
288
+ },
289
+
290
+ innerShortcuts() {
291
+ if (Array.isArray(this.shortcuts)) {
292
+ return this.shortcuts;
293
+ }
294
+ if (this.shortcuts === false) {
295
+ return [];
296
+ }
297
+ const pickers = this.currentLanguage.pickers;
298
+ const arr = [
299
+ {
300
+ text: pickers[0],
301
+ onClick(self) {
302
+ self.currentValue = [new Date(), new Date(Date.now() + 3600 * 1000 * 24 * 7)];
303
+ self.updateDate(true);
304
+ },
305
+ },
306
+ {
307
+ text: pickers[1],
308
+ onClick(self) {
309
+ self.currentValue = [new Date(), new Date(Date.now() + 3600 * 1000 * 24 * 30)];
310
+ self.updateDate(true);
311
+ },
312
+ },
313
+ {
314
+ text: pickers[2],
315
+ onClick(self) {
316
+ self.currentValue = [new Date(Date.now() - 3600 * 1000 * 24 * 7), new Date()];
317
+ self.updateDate(true);
318
+ },
319
+ },
320
+ {
321
+ text: pickers[3],
322
+ onClick(self) {
323
+ self.currentValue = [new Date(Date.now() - 3600 * 1000 * 24 * 30), new Date()];
324
+ self.updateDate(true);
325
+ },
326
+ },
327
+ ];
328
+ return arr;
329
+ },
330
+
331
+ innerDateFormat() {
332
+ if (this.dateFormat) {
333
+ return this.dateFormat;
334
+ }
335
+ if (typeof this.format !== "string") {
336
+ return "YYYY-MM-DD";
337
+ }
338
+ if (this.innerType === "date") {
339
+ return this.format;
340
+ }
341
+ return this.format.replace(/[Hh]+.*[msSaAZ]|\[.*?\]/g, "").trim() || "YYYY-MM-DD";
342
+ },
343
+
344
+ innerPopupStyle() {
345
+ return { ...this.position, ...this.popupStyle };
346
+ },
347
+
348
+ idForPanel() {
349
+ return `${ this.id }_panel`;
350
+ },
351
+
352
+ idsForPanelRange() {
353
+ return [
354
+ `${ this.idForPanel }_0`,
355
+ `${ this.idForPanel }_1`,
356
+ ];
357
+ },
358
+
359
+ ariaHiddenForCalendar() {
360
+ return `${ !this.popupVisible }`;
361
+ },
362
+
363
+ ariaExpandedForCalendar() {
364
+ return `${ this.popupVisible }`;
365
+ },
366
+
367
+ idForCalendar() {
368
+ return `${ this.id }_calendar`;
369
+ },
370
+ },
371
+ watch: {
372
+ value: {
373
+ immediate: true,
374
+ handler: "handleValueChange",
375
+ },
376
+
377
+ popupVisible(val) {
378
+ if (val) {
379
+ this.initCalendar();
380
+ } else {
381
+ this.userInput = null;
382
+ this.blur();
383
+ }
384
+ },
385
+ },
386
+ mounted() {
387
+ if (this.appendToBody) {
388
+ this.popupElm = this.$refs.calendar;
389
+ document.body.appendChild(this.popupElm);
390
+ }
391
+ // clickoutside close popup
392
+ let mousedownTarget;
393
+ this._bindDocmentMousedown = evt => {
394
+ mousedownTarget = evt.target;
395
+ };
396
+ this._bindDocumentMouseup = evt => {
397
+ const mouseupTarget = evt.target;
398
+ const el = this.$el;
399
+ const { popupElm } = this;
400
+ if (
401
+ !mousedownTarget ||
402
+ !mouseupTarget ||
403
+ el.contains(mousedownTarget) ||
404
+ el.contains(mouseupTarget) ||
405
+ (popupElm && (popupElm.contains(mousedownTarget) || popupElm.contains(mouseupTarget)))
406
+ ) {
407
+ return;
408
+ }
409
+ mousedownTarget = null;
410
+ this.closePopup();
411
+ };
412
+ this._startEvt = "mousedown";
413
+ this._endEvt = "mouseup";
414
+ if ("ontouchend" in document) {
415
+ this._startEvt = "touchstart";
416
+ this._endEvt = "touchend";
417
+ }
418
+ document.addEventListener(this._startEvt, this._bindDocmentMousedown);
419
+ document.addEventListener(this._endEvt, this._bindDocumentMouseup);
420
+
421
+ this._displayPopup = throttle(() => {
422
+ if (this.popupVisible) {
423
+ this.displayPopup();
424
+ }
425
+ }, 200);
426
+ window.addEventListener("resize", this._displayPopup);
427
+ window.addEventListener("scroll", this._displayPopup);
428
+ },
429
+ beforeUnmount() {
430
+ if (this.popupElm && this.popupElm.parentNode === document.body) {
431
+ document.body.removeChild(this.popupElm);
432
+ }
433
+ document.removeEventListener(this._startEvt, this._bindDocmentMousedown);
434
+ document.removeEventListener(this._endEvt, this._bindDocumentMouseup);
435
+ window.removeEventListener("resize", this._displayPopup);
436
+ window.removeEventListener("scroll", this._displayPopup);
437
+ },
438
+ methods: {
439
+ initCalendar() {
440
+ this.handleValueChange(this.modelValue);
441
+ this.displayPopup();
442
+ },
443
+
444
+ stringify(date) {
445
+ return (isPlainObject(this.format) && typeof this.format.stringify === "function")
446
+ ? this.format.stringify(date)
447
+ : formatDate(date, this.format);
448
+ },
449
+
450
+ parse(value) {
451
+ return (isPlainObject(this.format) && typeof this.format.parse === "function")
452
+ ? this.format.parse(value)
453
+ : parseDate(value, this.format, this.formatSave);
454
+ },
455
+
456
+ isValidValue(value) {
457
+ const { value2date } = this.transform;
458
+ return isValidDate(value2date(value));
459
+ },
460
+
461
+ isValidRangeValue(value) {
462
+ const { value2date } = this.transform;
463
+ return Array.isArray(value) && value.length === 2 && this.isValidValue(value[0]) &&
464
+ this.isValidValue(value[1]) && (value2date(value[1]).getTime() >= value2date(value[0]).getTime());
465
+ },
466
+
467
+ dateEqual(a, b) {
468
+ return isDateObject(a) && isDateObject(b) && a.getTime() === b.getTime();
469
+ },
470
+
471
+ rangeEqual(a, b) {
472
+ return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((item, index) => this.dateEqual(item, b[index]));
473
+ },
474
+
475
+ selectRange(range) {
476
+ if (typeof range.onClick === "function") {
477
+ const close = range.onClick(this);
478
+ if (close !== false) {
479
+ this.closePopup();
480
+ }
481
+ } else {
482
+ this.currentValue = [new Date(range.start), new Date(range.end)];
483
+ this.updateDate(true);
484
+ this.closePopup();
485
+ }
486
+ },
487
+
488
+ clearDate($event) {
489
+ if ($event) {
490
+ $event.stopPropagation();
491
+ }
492
+ const date = this.range ? [null, null] : null;
493
+ this.currentValue = date;
494
+ this.updateDate(true);
495
+ this.$emit("clear");
496
+ },
497
+
498
+ confirmDate() {
499
+ const valid = this.range ? isValidRangeDate(this.currentValue) : isValidDate(this.currentValue);
500
+ if (valid) {
501
+ this.updateDate(true);
502
+ }
503
+ this.emitDate("confirm");
504
+ this.closePopup();
505
+ },
506
+
507
+ updateDate(confirm = false) {
508
+ if ((this.confirm && !confirm) || this.disabled) {
509
+ return false;
510
+ }
511
+ const equal = this.range ? this.rangeEqual(this.modelValue, this.currentValue) : this.dateEqual(this.modelValue, this.currentValue);
512
+ if (equal) {
513
+ return false;
514
+ }
515
+ this.emitDate("change");
516
+ return true;
517
+ },
518
+
519
+ emitDate(eventName) {
520
+ const { date2value } = this.transform;
521
+ const value = this.range
522
+ ? this.currentValue.map(date2value)
523
+ : formatDate(this.currentValue, this.formatSave);
524
+ this.changeModel({
525
+ model: value,
526
+ });
527
+ this.$emit(eventName, value);
528
+ },
529
+
530
+ handleValueChange(value) {
531
+ const { value2date } = this.transform;
532
+ if (this.range) {
533
+ this.currentValue = this.isValidRangeValue(value) ? value.map(value2date) : [null, null];
534
+ } else {
535
+ this.currentValue = this.isValidValue(value) ? value2date(value) : null;
536
+ }
537
+ },
538
+
539
+ selectDate(date) {
540
+ this.currentValue = date;
541
+ this.updateDate() && this.closePopup();
542
+ this.setCloseFocus();
543
+ },
544
+
545
+ selectStartDate(date) {
546
+ this.currentValue[0] = date;
547
+ if (this.currentValue[1]) {
548
+ this.updateDate();
549
+ }
550
+ },
551
+
552
+ selectEndDate(date) {
553
+ this.currentValue[1] = date;
554
+ if (this.currentValue[0]) {
555
+ this.updateDate();
556
+ }
557
+ },
558
+
559
+ selectTime(time, close) {
560
+ this.currentValue = time;
561
+ this.updateDate() && close && this.closePopup();
562
+ if (close) {
563
+ this.setCloseFocus();
564
+ }
565
+ },
566
+
567
+ selectStartTime(time) {
568
+ this.selectStartDate(time);
569
+ },
570
+
571
+ selectEndTime(time) {
572
+ this.selectEndDate(time);
573
+ },
574
+
575
+ showPopup() {
576
+ if (this.disabled) {
577
+ return;
578
+ }
579
+ this.popupVisible = true;
580
+ },
581
+
582
+ closePopup(isSetFocusByClose) {
583
+ this.popupVisible = false;
584
+ if (isSetFocusByClose) {
585
+ this.setCloseFocus();
586
+ }
587
+ },
588
+
589
+ getPopupSize(element) {
590
+ const originalDisplay = element.style.display;
591
+ const originalVisibility = element.style.visibility;
592
+ element.style.display = "block";
593
+ element.style.visibility = "hidden";
594
+ const styles = window.getComputedStyle(element);
595
+ const width = element.offsetWidth + parseInt(styles.marginLeft) + parseInt(styles.marginRight);
596
+ const height = element.offsetHeight + parseInt(styles.marginTop) + parseInt(styles.marginBottom);
597
+ const result = { width, height };
598
+ element.style.display = originalDisplay;
599
+ element.style.visibility = originalVisibility;
600
+ return result;
601
+ },
602
+
603
+ displayPopup() {
604
+ const dw = document.documentElement.clientWidth;
605
+ const dh = document.documentElement.clientHeight;
606
+ const InputRect = this.$refs.inputRef.getBoundingClientRect();
607
+ const PopupRect = this._popupRect || (this._popupRect = this.getPopupSize(this.$refs.calendar));
608
+ const position = {};
609
+ let offsetRelativeToInputX = 0;
610
+ let offsetRelativeToInputY = 0;
611
+ if (this.appendToBody) {
612
+ offsetRelativeToInputX = window.pageXOffset + InputRect.left;
613
+ offsetRelativeToInputY = window.pageYOffset + InputRect.top;
614
+ }
615
+ if (
616
+ dw - InputRect.left < PopupRect.width &&
617
+ InputRect.right < PopupRect.width
618
+ ) {
619
+ position.left = offsetRelativeToInputX - InputRect.left + 1 + "px";
620
+ } else if (InputRect.left + InputRect.width / 2 <= dw / 2) {
621
+ position.left = offsetRelativeToInputX + "px";
622
+ } else {
623
+ position.left = offsetRelativeToInputX + InputRect.width - PopupRect.width + "px";
624
+ }
625
+ if (
626
+ InputRect.top <= PopupRect.height &&
627
+ dh - InputRect.bottom <= PopupRect.height
628
+ ) {
629
+ position.top = offsetRelativeToInputY + dh - InputRect.top - PopupRect.height + "px";
630
+ } else if (InputRect.top + InputRect.height / 2 <= dh / 2) {
631
+ position.top = offsetRelativeToInputY + InputRect.height + "px";
632
+ } else {
633
+ position.top = offsetRelativeToInputY - PopupRect.height + "px";
634
+ }
635
+ if (position.top !== this.position.top || position.left !== this.position.left) {
636
+ this.position = position;
637
+ }
638
+ },
639
+
640
+ handleBlur(event) {
641
+ this.$emit("blur", event);
642
+ },
643
+
644
+ handleFocus(event) {
645
+ if (!this.popupVisible) {
646
+ this.showPopup();
647
+ }
648
+ this.$emit("focus", event);
649
+ },
650
+
651
+ handleKeydown($event) {
652
+ const KEY_CODE = $event.keyCode;
653
+ if (KEY_CODE === AKeysCode.tab || KEY_CODE === AKeysCode.enter) {
654
+ // ie emit the watch before the change event
655
+ this.handleChange();
656
+ this.userInput = null;
657
+ this.closePopup();
658
+ } else if (KEY_CODE === AKeysCode.arrowUp || KEY_CODE === AKeysCode.arrowDown) {
659
+ this.setFocusToPanel();
660
+ $event.stopPropagation();
661
+ $event.preventDefault();
662
+ }
663
+ },
664
+
665
+ handleInput(event) {
666
+ this.userInput = event.target.value;
667
+ },
668
+
669
+ handleChange() {
670
+ if (this.editable && this.userInput !== null) {
671
+ let value = this.text;
672
+ const checkDate = this.$refs.calendarPanel.isDisabledTime;
673
+ if (!value) {
674
+ this.clearDate();
675
+ return;
676
+ }
677
+ if (this.range) {
678
+ const range = value.split(` ${ this.rangeSeparator } `);
679
+ if (range.length === 2) {
680
+ const start = this.parse(range[0]);
681
+ const end = this.parse(range[1]);
682
+ if (start && end && !checkDate(start, null, end) && !checkDate(end, start, null)) {
683
+ this.currentValue = [start, end];
684
+ this.updateDate(true);
685
+ this.closePopup();
686
+ return;
687
+ }
688
+ }
689
+ } else {
690
+ if (this.type === "time") {
691
+ value = `${ moment().format("DD.MM.YYYY") } ${ value }`;
692
+ }
693
+ const date = this.parse(value);
694
+ if (date && !checkDate(date, null, null)) {
695
+ this.currentValue = date;
696
+ this.updateDate(true);
697
+ this.closePopup();
698
+ return;
699
+ }
700
+ }
701
+ this.$emit("inputError", value);
702
+ }
703
+ },
704
+
705
+ setFocusToPanel() {
706
+ this.$refs.calendarPanel.setFocusToActivePanelFromParent();
707
+ },
708
+
709
+ setCloseFocus() {
710
+ this.$refs.focusByClose && this.$refs.focusByClose.focus();
711
+ },
712
+
713
+ isValidValueText(value) {
714
+ return !!parseDate(value, this.format, this.formatSave);
715
+ },
716
+
717
+ value2dateText(value) {
718
+ let dateValue = null;
719
+ try {
720
+ dateValue = moment(value, this.formatSave) || null;
721
+ } catch(e) {
722
+
723
+ }
724
+ if (dateValue && dateValue.isValid && !dateValue.isValid()) {
725
+ dateValue = null;
726
+ }
727
+ return dateValue;
728
+ },
729
+ },
730
+ render() {
731
+ return this.isRender && h("div", {
732
+ style: this.componentStyleHide,
733
+ }, [
734
+ h("div", {
735
+ class: ["a_form_element__parent", {
736
+ a_form_element__parent_float: this.isLabelFloat,
737
+ a_form_element__parent_not_empty: this.isModel || this.isAutofill,
738
+ }],
739
+ }, [
740
+ this.label && h(ALabel, {
741
+ id: this.htmlIdLocal,
742
+ extra: this.extra,
743
+ label: this.label,
744
+ labelClass: this.labelClass,
745
+ required: this.required,
746
+ type: this.type,
747
+ isLabelFloat: this.isLabelFloat,
748
+ }),
749
+ h("div", {
750
+ class: "a_form_element",
751
+ }, [
752
+ h("div", {
753
+ class: ["pux_datepicker", {
754
+ pux_datepicker_range: this.range,
755
+ disabled: this.disabled,
756
+ }],
757
+ style: { width: this.computedWidth },
758
+ onMousedown: this.showPopup,
759
+ onTouchstart: this.showPopup,
760
+ }, [
761
+ h("div", {
762
+ class: "pux_datepicker__input_wrapper",
763
+ role: "application",
764
+ }, [
765
+ h("input", {
766
+ ref: "inputRef",
767
+ id: this.htmlIdLocal,
768
+ class: [
769
+ "a_form_control pux_datepicker__input",
770
+ this.inputClass,
771
+ {
772
+ a_form_control_invalid: this.isErrors,
773
+ },
774
+ ],
775
+ name: this.inputName,
776
+ type: "text",
777
+ autocomplete: "off",
778
+ disabled: this.disabled,
779
+ readonly: !this.editable,
780
+ value: this.text,
781
+ placeholder: this.innerPlaceholder,
782
+ ariaHaspopup: true,
783
+ "aria-owns": this.idForCalendar,
784
+ ...this.inputAttr,
785
+ onKeydown: this.handleKeydown,
786
+ onFocus: this.handleFocus,
787
+ onBlur: this.handleBlur,
788
+ onInput: this.handleInput,
789
+ onChange: this.handleChange,
790
+ }),
791
+ this.showClearIcon && h("span", {
792
+ class: "pux_datepicker__input_wrapper__append pux_datepicker__input_wrapper__clear_wrapper",
793
+ ariaHidden: true,
794
+ onMousedown: this.clearDate,
795
+ }, [
796
+ h("i", {
797
+ class: "pux_datepicker__input__icon pux_datepicker__input__clear_icon",
798
+ }),
799
+ ]),
800
+ h("span", {
801
+ class: "pux_datepicker__input_wrapper__append",
802
+ }, [
803
+ h(ADatepickerIcon),
804
+ ]),
805
+ ]),
806
+ h("div", {
807
+ ref: "calendar",
808
+ id: this.idForCalendar,
809
+ class: "pux_datepicker__popup",
810
+ ariaHidden: this.ariaHiddenForCalendar,
811
+ ariaExpanded: this.ariaExpandedForCalendar,
812
+ style: [this.innerPopupStyle, !this.popupVisible ? "display: none;" : ""],
813
+ }, [
814
+ !!(this.range && this.innerShortcuts.length) && h("div", {
815
+ class: "pux_datepicker__shortcuts_wrapper",
816
+ }, [
817
+ this.innerShortcuts.map((range, index) => {
818
+ return h("button", {
819
+ key: index,
820
+ class: "pux_datepicker__shortcuts_wrapper__shortcuts",
821
+ type: "button",
822
+ onClick: () => this.selectRange(range),
823
+ }, range.text);
824
+ }),
825
+ ]),
826
+ !this.range ?
827
+ h(ADatepickerCalendarPanel, {
828
+ ref: "calendarPanel",
829
+ id: this.idForPanel,
830
+ index: -1,
831
+ type: this.innerType,
832
+ dateFormat: this.innerDateFormat,
833
+ value: this.currentValue,
834
+ visible: this.popupVisible,
835
+ currentLanguage: this.currentLanguage,
836
+ onSelectDate: this.selectDate,
837
+ onSelectTime: this.selectTime,
838
+ onClosePopup: this.closePopup,
839
+ }) :
840
+ h("div", {
841
+ class: "pux_datepicker__range_wrapper",
842
+ }, [
843
+ h(ADatepickerCalendarPanel, {
844
+ ref: "calendarPanel",
845
+ id: this.idsForPanelRange[0],
846
+ style: "box-shadow: 1px 0 rgba(0, 0, 0, .1);",
847
+ index: 0,
848
+ type: this.innerType,
849
+ dateFormat: this.innerDateFormat,
850
+ value: this.currentValue[0],
851
+ endAt: this.currentValue[1],
852
+ startAt: null,
853
+ visible: this.popupVisible,
854
+ currentLanguage: this.currentLanguage,
855
+ onSelectDate: this.selectStartDate,
856
+ onSelectTime: this.selectStartTime,
857
+ onClosePopup: this.closePopup,
858
+ }),
859
+ h(ADatepickerCalendarPanel, {
860
+ ref: "calendarPanel2",
861
+ id: this.idsForPanelRange[1],
862
+ index: 1,
863
+ type: this.innerType,
864
+ dateFormat: this.innerDateFormat,
865
+ value: this.currentValue[1],
866
+ endAt: null,
867
+ startAt: this.currentValue[0],
868
+ visible: this.popupVisible,
869
+ currentLanguage: this.currentLanguage,
870
+ onSelectDate: this.selectEndDate,
871
+ onSelectTime: this.selectEndTime,
872
+ onClosePopup: this.closePopup,
873
+ }),
874
+ ]),
875
+ this.confirm && h("div", {
876
+ class: "pux_datepicker__footer",
877
+ }, [
878
+ h("button", {
879
+ class: "pux_datepicker__footer__btn pux_datepicker__footer__btn_confirm",
880
+ type: "button",
881
+ onClick: this.confirmDate,
882
+ }, this.confirmText),
883
+ ]),
884
+ ]),
885
+ h("div", {
886
+ ref: "focusByClose",
887
+ tabindex: -1,
888
+ }),
889
+ ]),
890
+
891
+ /*
892
+ * this.isClearButtonLocal && h(AFormElementBtnClear, {
893
+ * disabled: this.disabled,
894
+ * clearButtonClass: this.clearButtonClass,
895
+ * onClear: this.clearModel,
896
+ * }),
897
+ */
898
+ ]),
899
+ this.helpText && withDirectives(h("div", {
900
+ id: this.helpTextId,
901
+ class: "a_form_element__help_text",
902
+ }), [
903
+ [ASafeHtml, this.helpText],
904
+ ]),
905
+ this.isErrors && h(AErrorsText, {
906
+ id: this.errorsId,
907
+ errors: this.errors,
908
+ }),
909
+ ]),
910
+ ]);
911
+ },
912
+ };