@itfin/components 1.0.18 → 1.0.22

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 (31) hide show
  1. package/package.json +1 -1
  2. package/src/assets/scss/_variables.scss +6 -5
  3. package/src/assets/scss/components/_dropdown-menu.scss +3 -5
  4. package/src/assets/scss/components/_dropdown-toggle.scss +8 -3
  5. package/src/assets/scss/components/_selected.scss +15 -0
  6. package/src/assets/scss/components/_spinner.scss +4 -3
  7. package/src/assets/scss/components/_states.scss +0 -1
  8. package/src/assets/scss/directives/loading.scss +1 -1
  9. package/src/components/button/Button.vue +7 -5
  10. package/src/components/checkbox/Checkbox.vue +114 -0
  11. package/src/components/checkbox/CheckboxGroup.vue +54 -0
  12. package/src/components/checkbox/index.stories.js +74 -0
  13. package/src/components/datepicker/DatePicker.vue +11 -9
  14. package/src/components/datepicker/DatePickerInline.vue +3 -1
  15. package/src/components/datepicker/DateRangePicker.vue +11 -9
  16. package/src/components/datepicker/MonthPicker.vue +163 -0
  17. package/src/components/datepicker/index.stories.js +5 -0
  18. package/src/components/icon/Icon.vue +1 -1
  19. package/src/components/modal/Modal.vue +6 -2
  20. package/src/components/popover/Popover.vue +1 -1
  21. package/src/components/select/Select.vue +20 -16
  22. package/src/components/select/index.stories.js +8 -1
  23. package/src/components/table/Table.vue +12 -9
  24. package/src/components/text-field/TextField.vue +10 -2
  25. package/src/components/tooltip/Tooltip.vue +39 -0
  26. package/src/components/tooltip/index.stories.js +52 -0
  27. package/src/components/tree/index.stories.js +10 -6
  28. package/src/directives/sticky.js +298 -0
  29. package/src/index.stories.js +0 -25
  30. package/src/components/select/Deselect.vue +0 -3
  31. package/src/components/select/OpenIndicator.vue +0 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itfin/components",
3
- "version": "1.0.18",
3
+ "version": "1.0.22",
4
4
  "main": "dist/itfin-components.umd.js",
5
5
  "unpkg": "dist/itfin-components.common.js",
6
6
  "author": "Vitalii Savchuk <esvit666@gmail.com>",
@@ -24,18 +24,19 @@ $link-color: #0B314F;
24
24
  $input-btn-focus-width: .125rem;
25
25
 
26
26
  $input-bg: #f3f3f3;
27
- $input-border-color: #f3f3f3;
27
+ $input-border-color: rgba(#000, .08);
28
28
  $input-border-radius: 10px;
29
29
  $input-font-family: 'Fira Mono', monospace;
30
30
 
31
- $input-focus-bg: #f9f6e8;
32
- $input-focus-border-color: #f9f6e8;
33
-
34
- $input-focus-box-shadow: none;
31
+ $input-focus-bg: #fff;
32
+ $input-focus-border-color: #fff;
35
33
 
36
34
  $form-label-margin-bottom: .1rem;
37
35
  $input-focus-border: rgb(11 49 79 / 25%);
38
36
 
37
+ $form-check-input-border: 1px solid rgba(#000, .08);
38
+ $form-switch-focus-color: tint-color($primary, 50%);
39
+
39
40
  $modal-backdrop-bg: #fff;
40
41
  $modal-backdrop-opacity: .7;
41
42
  $modal-content-border-radius: 0;
@@ -12,19 +12,17 @@ $min-width: $vs-dropdown-min-width;
12
12
  $max-height: $vs-dropdown-max-height;
13
13
 
14
14
  .vs__dropdown-menu {
15
+ overflow-x: hidden;
16
+ overflow-y: auto;
15
17
  display: block;
16
18
  box-sizing: border-box;
17
19
  position: absolute;
18
- top: calc(100% - #{$border-width}); // -{#$border-width} here ensures the left and right borders of the dropdown appear flush with the toggle.
20
+ top: calc(100% + #{$border-width * 2}); // -{#$border-width} here ensures the left and right borders of the dropdown appear flush with the toggle.
19
21
  left: 0;
20
22
  z-index: $z-index;
21
23
  width: 100%;
22
24
  max-height: $max-height;
23
25
  min-width: $min-width;
24
- overflow-y: auto;
25
- border-top-style: none;
26
- border-top-left-radius: 0;
27
- border-top-right-radius: 0;
28
26
  text-align: left;
29
27
  list-style: none;
30
28
  }
@@ -25,9 +25,17 @@ $border-radius: $vs-border-radius;
25
25
  flex-wrap: wrap;
26
26
  padding: 0 2px 0 0;
27
27
  position: relative;
28
+ flex-shrink: 1;
29
+ overflow: hidden;
30
+ min-height: 26px;
31
+
32
+ .vs--multiple & {
33
+ min-height: 32px;
34
+ }
28
35
  }
29
36
 
30
37
  .vs__actions {
38
+ flex-shrink: 0;
31
39
  display: flex;
32
40
  margin-right: -9px;
33
41
  align-items: center;
@@ -46,7 +54,4 @@ $border-radius: $vs-border-radius;
46
54
  cursor: pointer;
47
55
  }
48
56
  .vs--open .vs__dropdown-toggle {
49
- border-bottom-color: transparent;
50
- border-bottom-left-radius: 0;
51
- border-bottom-right-radius: 0;
52
57
  }
@@ -17,6 +17,10 @@
17
17
  color: #222;
18
18
  background-color: #ccc;
19
19
 
20
+ &.badge {
21
+ padding: 0.1875rem 0.5rem;
22
+ }
23
+
20
24
  @media (prefers-color-scheme: notdark) {
21
25
  background-color: #221;
22
26
  color: $dark-body-color;
@@ -43,6 +47,17 @@
43
47
  .vs__selected {
44
48
  background-color: transparent;
45
49
  border-color: transparent;
50
+ white-space: nowrap;
51
+ overflow: hidden;
52
+ text-overflow: ellipsis;
53
+ }
54
+ .vs__search {
55
+ top: 0;
56
+ position: absolute;
57
+ right: 0;
58
+ left: 0;
59
+ width: 100% !important;
60
+ padding-left: 0 !important;
46
61
  }
47
62
  &.vs--open .vs__selected,
48
63
  &.vs--loading .vs__selected {
@@ -1,15 +1,16 @@
1
1
  /* Loading Spinner */
2
- .itf-select .itf-spinner {
2
+ .itf-select .itf-select__loader {
3
3
  opacity: 0;
4
4
  transform: translateZ(0);
5
5
  transition: opacity .1s;
6
- right: 1rem;
6
+ right: 0.75rem;
7
+ position: absolute;
7
8
  mix-blend-mode: normal;
8
9
  width: 1rem;
9
10
  height: 1rem;
10
11
  }
11
12
 
12
13
  /* Loading Spinner States */
13
- .vs--loading .itf-spinner {
14
+ .vs--loading .itf-select__loader {
14
15
  opacity: 1;
15
16
  }
@@ -21,7 +21,6 @@ $disabled-cursor: $vs-state-disabled-cursor;
21
21
  .vs__open-indicator {
22
22
  cursor: $disabled-cursor;
23
23
  background-color: transparent;
24
- border-color: transparent;
25
24
  }
26
25
  }
27
26
 
@@ -23,7 +23,7 @@
23
23
  animation: spinner 0.7s linear infinite;
24
24
  mix-blend-mode: difference;
25
25
 
26
- &.white {
26
+ &.itf-spinner__white {
27
27
  border-color: rgba(158, 158, 158, 0.29);
28
28
  border-top-color: rgb(155, 155, 155);
29
29
  }
@@ -7,10 +7,11 @@
7
7
  tabindex="0"
8
8
  type="button"
9
9
  :class="{
10
+ [`btn-${color}`]: color,
10
11
  'labeled': labeled,
11
12
  'disabled': disabled || loading,
12
13
  'btn-primary': primary,
13
- 'btn-basic': !primary && !secondary,
14
+ 'btn-basic': !primary && !secondary && !color,
14
15
  'btn-secondary': secondary,
15
16
  'btn-sm': small,
16
17
  'btn-lg': large,
@@ -20,7 +21,7 @@
20
21
  'btn-icon': icon,
21
22
  'loading': loading
22
23
  }">
23
- <div class="itf-spinner" :class="{'white': primary}" v-if="loading"></div>
24
+ <div class="itf-spinner" :class="{'itf-spinner__white': primary}" v-if="loading"></div>
24
25
  <div v-if="loading && loadingText">{{loadingText}}</div>
25
26
  <slot v-else></slot>
26
27
  </button>
@@ -31,11 +32,11 @@
31
32
  @import '~bootstrap/scss/buttons';
32
33
 
33
34
  .itf-button {
35
+ display: inline-flex;
36
+ align-items: center;
37
+
34
38
  & > div {
35
- display: flex;
36
39
  pointer-events: none;
37
- align-items: center;
38
- text-align: left;
39
40
  }
40
41
  .itf-spinner {
41
42
  mix-blend-mode: normal;
@@ -141,6 +142,7 @@ class itfButton extends Vue {
141
142
  @Prop(Boolean) large;
142
143
  @Prop(Boolean) icon;
143
144
  @Prop(String) loadingText;
145
+ @Prop(String) color;
144
146
  @Prop(Boolean) disabled;
145
147
  }
146
148
  </script>
@@ -0,0 +1,114 @@
1
+ <template>
2
+
3
+ <div class="itf-checkbox form-check" :class="{ 'form-switch': this.switch, 'itf-checkbox__large': large, 'itf-checkbox__medium': medium }">
4
+ <input class="form-check-input" :id="id" slot="input" type="checkbox" name="checkbox" v-model="isChecked" :disabled="isDisabled" />
5
+ <label :for="id" slot="label" class="form-check-label">
6
+ {{label}}
7
+ </label>
8
+ </div>
9
+
10
+ </template>
11
+ <style lang="scss">
12
+ @import '../../assets/scss/variables';
13
+
14
+ .itf-checkbox {
15
+ .form-check-input, .form-check-label {
16
+ cursor: pointer;
17
+ }
18
+ &__large {
19
+ padding-left: $form-check-padding-start * 2;
20
+ min-height: 2.5rem;
21
+
22
+ .form-check-label {
23
+ padding-top: 0.25rem;
24
+ }
25
+ .form-check-input {
26
+ margin-top: 0;
27
+ width: $form-check-input-width * 2;
28
+ height: $form-check-input-width * 2;
29
+ margin-left: -$form-check-padding-start * 2;
30
+ border-radius: 0.75rem;
31
+ }
32
+ &.form-switch {
33
+ padding-left: $form-switch-padding-start * 2;
34
+
35
+ .form-check-input {
36
+ width: $form-switch-width * 2;
37
+ margin-left: -$form-switch-padding-start * 2;
38
+ border-radius: 100px;
39
+ }
40
+ }
41
+ }
42
+ &__medium {
43
+ padding-left: $form-check-padding-start * 1.5;
44
+ min-height: 2rem;
45
+
46
+ .form-check-input {
47
+ margin-top: 0;
48
+ width: $form-check-input-width * 1.5;
49
+ height: $form-check-input-width * 1.5;
50
+ margin-left: -$form-check-padding-start * 1.5;
51
+ border-radius: 0.5rem;
52
+ }
53
+ &.form-switch {
54
+ padding-left: $form-switch-padding-start * 1.5;
55
+
56
+ .form-check-input {
57
+ width: $form-switch-width * 1.5;
58
+ margin-left: -$form-switch-padding-start * 1.5;
59
+ border-radius: 100px;
60
+ }
61
+ }
62
+ }
63
+ }
64
+ </style>
65
+ <script>
66
+ import { Vue, Component, Prop, Model, Inject } from 'vue-property-decorator';
67
+
68
+ let globalCheckboxId = 0;
69
+
70
+ export default @Component({
71
+ name: 'itfCheckbox',
72
+ components: {
73
+ }
74
+ })
75
+ class itfCheckbox extends Vue {
76
+ @Inject({ default: null }) checkboxGroup;
77
+
78
+ @Model('input') value;
79
+ @Prop(String) label;
80
+
81
+ @Prop(Boolean) switch;
82
+ @Prop(Boolean) disabled;
83
+ @Prop(Boolean) medium;
84
+ @Prop(Boolean) large;
85
+
86
+ id = '';
87
+
88
+ created() {
89
+ globalCheckboxId += 1;
90
+ this.id = `checkbox${globalCheckboxId}`;
91
+ }
92
+
93
+ get isDisabled() {
94
+ if (this.checkboxGroup) {
95
+ return this.disabled || this.checkboxGroup.isDisabled(this.value);
96
+ }
97
+ return this.disabled;
98
+ }
99
+
100
+ get isChecked() {
101
+ if (this.checkboxGroup) {
102
+ return this.checkboxGroup.isChecked(this.value);
103
+ }
104
+ return this.value;
105
+ }
106
+
107
+ set isChecked(val) {
108
+ if (this.checkboxGroup) {
109
+ this.checkboxGroup.onToggleOption(this.value, val);
110
+ }
111
+ this.$emit('input', val);
112
+ }
113
+ }
114
+ </script>
@@ -0,0 +1,54 @@
1
+ <template>
2
+
3
+ <div>
4
+ <slot />
5
+ </div>
6
+
7
+ </template>
8
+ <style>
9
+
10
+ </style>
11
+ <script>
12
+ import { Vue, Component, Prop, Model, Provide } from 'vue-property-decorator';
13
+
14
+ export default @Component({
15
+ name: 'itfCheckboxGroup'
16
+ })
17
+ class itfCheckboxGroup extends Vue {
18
+ @Provide() checkboxGroup = this;
19
+
20
+ @Model('input', { type: Array, default: () => [] }) value;
21
+
22
+ @Prop(Boolean) disabled;
23
+
24
+ @Prop(String) itemKey;
25
+
26
+ @Prop(Number) max;
27
+
28
+ onToggleOption(value, isChecked) {
29
+ const index = this.getCheckedIndex(value);
30
+ const arr = this.value ? [ ...this.value ] : [];
31
+ if (index !== -1 && isChecked === false) {
32
+ arr.splice(index, 1);
33
+ } else if (isChecked === true) {
34
+ arr.push(value);
35
+ }
36
+ this.$emit('input', arr);
37
+ }
38
+
39
+ getCheckedIndex(value) {
40
+ if (this.itemKey) {
41
+ return this.value && this.value.findIndex(item => item[this.itemKey] === value[this.itemKey]);
42
+ }
43
+ return this.value.indexOf(value);
44
+ }
45
+
46
+ isChecked(value) {
47
+ return this.getCheckedIndex(value) !== -1;
48
+ }
49
+
50
+ isDisabled(value) {
51
+ return this.getCheckedIndex(value) === -1 && (this.max !== 'undefined' && this.value.length >= this.max);
52
+ }
53
+ }
54
+ </script>
@@ -0,0 +1,74 @@
1
+ import { storiesOf } from '@storybook/vue';
2
+ import itfCheckbox from './Checkbox';
3
+ import itfCheckboxGroup from './CheckboxGroup';
4
+ import itfForm from '../form/Form.vue';
5
+ import itfLabel from '../form/Label.vue';
6
+ import itfDatePicker from '../datepicker/DatePicker.vue';
7
+ import itfDateRangePicker from '../datepicker/DateRangePicker.vue';
8
+ import itfApp from '../app/App.vue';
9
+
10
+ storiesOf('Common', module)
11
+ .add('Checkbox', () => ({
12
+ components: {
13
+ itfApp,
14
+ itfCheckbox,
15
+ itfCheckboxGroup,
16
+ itfForm,
17
+ itfLabel,
18
+ itfDatePicker,
19
+ itfDateRangePicker,
20
+ },
21
+ data() {
22
+ return {
23
+ test: false,
24
+ group: []
25
+ }
26
+ },
27
+ methods: {
28
+ },
29
+ template: `<div>
30
+ <p>You need wrap whole application with this tag</p>
31
+
32
+ <h2>Usage</h2>
33
+
34
+ <pre>
35
+
36
+ &lt;itf-datepicker>&lt;/itf-datepicker>
37
+
38
+ &lt;button @click="$showSuccess('Success')">Show success&lt;/button>
39
+ &lt;button @click="$showError('Error')">Show error&lt;/button>
40
+ &lt;button @click="$try(() => { throw new Error('Invalid function'); })">Try function with error&lt;/button>
41
+ </pre>
42
+
43
+ <h2>Example</h2>
44
+
45
+ <itf-form>
46
+ <itf-checkbox label="Test" v-model="test" />
47
+
48
+ <itf-checkbox switch label="Test" v-model="test" />
49
+ {{test}}
50
+
51
+ <itf-checkbox-group v-model="group">
52
+ <itf-checkbox label="Test1" value="1" />
53
+ <itf-checkbox label="Test2" value="2" />
54
+ </itf-checkbox-group>
55
+
56
+ {{group}}
57
+
58
+ <h3>Medium</h3>
59
+ <itf-checkbox medium label="Test" v-model="test" />
60
+
61
+ <itf-checkbox medium switch label="Test" v-model="test" />
62
+
63
+
64
+
65
+ <h3>Large</h3>
66
+ <itf-checkbox large label="Test" v-model="test" />
67
+
68
+ <itf-checkbox large switch label="Test" v-model="test" />
69
+
70
+
71
+
72
+ </itf-form>
73
+ </div>`,
74
+ }));
@@ -22,15 +22,17 @@
22
22
  :lazy="!focused"
23
23
  :placeholder="placeholder"
24
24
  />
25
- <div ref="dropdown" class="itf-datepicker__dropdown">
26
- <itf-date-picker-inline
27
- :value="value"
28
- :start-view="startView"
29
- :only-calendar="onlyCalendar"
30
- :display-format="displayFormat"
31
- :value-format="valueFormat"
32
- @input="selectInlineDate"
33
- ></itf-date-picker-inline>
25
+ <div style="display: none">
26
+ <div ref="dropdown" class="itf-datepicker__dropdown">
27
+ <itf-date-picker-inline
28
+ :value="value"
29
+ :start-view="startView"
30
+ :only-calendar="onlyCalendar"
31
+ :display-format="displayFormat"
32
+ :value-format="valueFormat"
33
+ @input="selectInlineDate"
34
+ ></itf-date-picker-inline>
35
+ </div>
34
36
  </div>
35
37
  </div>
36
38
  </template>
@@ -74,6 +74,7 @@ class itfDatePickerInline extends Vue {
74
74
  @Prop({ type: String, default: 'ISO' }) valueFormat;
75
75
  @Prop({ type: String, default: ITFSettings.defaultDisplayDateFormat }) displayFormat;
76
76
  @Prop({ type: String, default: 'days', validator: (value) => ['days', 'months', 'years'].includes(value) }) startView;
77
+ @Prop({ type: String, default: null, validator: (value) => ['days', 'months', 'years'].includes(value) }) minView;
77
78
  @Prop({ type: Boolean, default: false }) onlyCalendar;
78
79
  @Prop({ type: Boolean, default: false }) range;
79
80
  @Prop({ type: Object, default: () => ({}) }) customDays;
@@ -108,7 +109,8 @@ class itfDatePickerInline extends Vue {
108
109
  locale: localeEn,
109
110
  firstDay: 1,
110
111
  range: this.range,
111
- view: this.valueAsLuxon ? 'days' : this.startView,
112
+ view: (this.valueAsLuxon && !this.minView) ? 'days' : this.startView,
113
+ minView: this.minView,
112
114
  selectedDates: this.valueAsLuxon ? [this.valueAsLuxon.toJSDate()] : [],
113
115
  onSelect: ({ date }) => {
114
116
  if (this.range && !this.calendar.rangeDateTo) {
@@ -43,15 +43,17 @@
43
43
  :placeholder="placeholder"
44
44
  />
45
45
  </div>
46
- <div ref="dropdown" class="itf-datepicker__dropdown">
47
- <itf-date-range-picker-inline
48
- :value="value"
49
- :start-view="startView"
50
- :only-calendar="onlyCalendar"
51
- :display-format="displayFormat"
52
- :value-format="valueFormat"
53
- @input="selectInlineDate"
54
- ></itf-date-range-picker-inline>
46
+ <div style="display: none">
47
+ <div ref="dropdown" class="itf-daterange-picker__dropdown">
48
+ <itf-date-range-picker-inline
49
+ :value="value"
50
+ :start-view="startView"
51
+ :only-calendar="onlyCalendar"
52
+ :display-format="displayFormat"
53
+ :value-format="valueFormat"
54
+ @input="selectInlineDate"
55
+ ></itf-date-range-picker-inline>
56
+ </div>
55
57
  </div>
56
58
  </div>
57
59
  </template>
@@ -0,0 +1,163 @@
1
+ <template>
2
+ <div class="itf-monthpicker" :class="{'with-addon addon-start': prependIcon}">
3
+ <div class="addon" v-if="prependIcon">
4
+ <slot name="addon">
5
+ <itf-icon :name="prependIcon" />
6
+ </slot>
7
+ </div>
8
+ <input
9
+ ref="input"
10
+ readonly
11
+ class="form-control"
12
+ :class="{ 'is-invalid': isInvalid(), 'is-valid': isSuccess() }"
13
+ @focus="onFocus"
14
+ @blur="onBlur"
15
+ :value="displayValue"
16
+ :placeholder="placeholder"
17
+ />
18
+ <div style="display: none">
19
+ <div ref="dropdown" class="itf-monthpicker__dropdown">
20
+ <itf-date-picker-inline
21
+ :value="value"
22
+ start-view="months"
23
+ min-view="months"
24
+ only-calendar
25
+ :display-format="displayFormat"
26
+ :value-format="valueFormat"
27
+ @input="selectInlineDate"
28
+ ></itf-date-picker-inline>
29
+ </div>
30
+ </div>
31
+ </div>
32
+ </template>
33
+ <style lang="scss">
34
+ @import '../../assets/scss/variables';
35
+ @import '../../assets/scss/directives/tooltip';
36
+ @import '../../assets/scss/input-addon';
37
+
38
+ .itf-monthpicker {
39
+ &__dropdown {
40
+ width: max-content;
41
+ border: $input-border-width solid $input-border-color;
42
+ border-radius: $input-border-radius;
43
+ background-color: $body-bg;
44
+ overflow: hidden;
45
+ @if $enable-shadows {
46
+ @include box-shadow($input-box-shadow, $input-btn-focus-box-shadow);
47
+ } @else {
48
+ // Avoid using mixin so we can pass custom focus shadow properly
49
+ box-shadow: $input-btn-focus-box-shadow;
50
+ }
51
+
52
+ @media (prefers-color-scheme: notdark) {
53
+ background-color: $dark-body-bg;
54
+ border-color: $dark-border-color;
55
+ box-shadow: 0 0 0 2px $dark-input-focus-border;
56
+ }
57
+ }
58
+ }
59
+ </style>
60
+ <script>
61
+ import { Vue, Component, Prop, Inject } from 'vue-property-decorator';
62
+ import { DateTime } from 'luxon';
63
+ import tippy from 'tippy.js';
64
+ import itfIcon from '../icon/Icon';
65
+ import itfDatePickerInline from './DatePickerInline.vue';
66
+
67
+ export default @Component({
68
+ name: 'itfMonthPicker',
69
+ components: {
70
+ itfIcon,
71
+ itfDatePickerInline
72
+ },
73
+ })
74
+ class itfMonthPicker extends Vue {
75
+ @Inject({ default: null }) itemLabel;
76
+ @Inject({ default: null }) appendContext;
77
+
78
+ @Prop({ type: String }) value;
79
+ @Prop({ type: String, default: 'ISO' }) valueFormat;
80
+ @Prop({ type: String, default: 'MMMM yyyy' }) displayFormat;
81
+ @Prop({ type: String, default: '' }) placeholder;
82
+ @Prop({ type: String, default: '' }) prependIcon;
83
+
84
+ focused = false;
85
+
86
+ tooltip = null;
87
+
88
+ isInvalid() {
89
+ return this.itemLabel && this.itemLabel.isHasError();
90
+ }
91
+
92
+ isSuccess() {
93
+ return this.itemLabel && this.itemLabel.isHasSuccess();
94
+ }
95
+
96
+ mounted() {
97
+ // якщо в модалці, то контекст модалки, якщо ні, то аплікейшена
98
+ const context = (this.appendContext && this.appendContext()) || document.body;
99
+ this.tooltip = tippy(this.$refs.input, {
100
+ interactiveBorder: 30,
101
+ interactiveDebounce: 75,
102
+ animation: 'scale',
103
+ arrow: true,
104
+ content: this.$refs.dropdown,
105
+ allowHTML: true,
106
+ trigger: 'click',
107
+ interactive: true,
108
+ placement: 'bottom-start',
109
+ appendTo: context
110
+ });
111
+ }
112
+
113
+ get valueAsLuxon() {
114
+ if (!this.value) {
115
+ return null;
116
+ }
117
+ if (this.valueFormat === 'ISO') {
118
+ return DateTime.fromISO(this.value);
119
+ }
120
+ return DateTime.fromFormat(this.value, this.valueFormat);
121
+ }
122
+
123
+ get displayValue() {
124
+ if (!this.valueAsLuxon) {
125
+ return '';
126
+ }
127
+ return this.valueAsLuxon.toFormat(this.displayFormat);
128
+ }
129
+
130
+ updateValue(value, emitEmpty = false) {
131
+ const val = value && DateTime.fromFormat(value, this.displayFormat);
132
+ if (!val || !val.isValid) {
133
+ if (emitEmpty) {
134
+ this.$emit('input', null);
135
+ }
136
+ return;
137
+ }
138
+ this.$emit('input', this.valueFormat === 'ISO' ? val.toISO() : val.toFormat(this.valueFormat));
139
+ }
140
+
141
+ format(date) {
142
+ return DateTime.fromJSDate(date).toFormat(this.displayFormat);
143
+ }
144
+
145
+ parse(str) {
146
+ return DateTime.fromFormat(str, this.displayFormat).toJSDate();
147
+ }
148
+
149
+ onFocus() {
150
+ this.focused = true;
151
+ }
152
+
153
+ onBlur(e) {
154
+ this.focused = false;
155
+ this.updateValue(e.target.value, true);
156
+ }
157
+
158
+ selectInlineDate(date) {
159
+ this.$emit('input', date);
160
+ this.tooltip.hide();
161
+ }
162
+ }
163
+ </script>