@ditojs/ui 2.71.0 → 2.73.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ditojs/ui",
3
- "version": "2.71.0",
3
+ "version": "2.73.0",
4
4
  "type": "module",
5
5
  "description": "Dito.js UI is a simple UI library, built with Vue.js for use in Dito.js Admin and elsewhere",
6
6
  "repository": "https://github.com/ditojs/dito/tree/master/packages/ui",
@@ -41,12 +41,12 @@
41
41
  "ie_mob >= 11"
42
42
  ],
43
43
  "dependencies": {
44
- "@ditojs/utils": "^2.71.0",
44
+ "@ditojs/utils": "^2.73.0",
45
45
  "@soda/get-current-script": "^1.0.2"
46
46
  },
47
47
  "devDependencies": {
48
- "@ditojs/build": "^2.71.0",
49
- "vite": "^7.3.0"
48
+ "@ditojs/build": "^2.73.0",
49
+ "vite": "^7.3.1"
50
50
  },
51
- "gitHead": "e5a095c7c44de8b6c84994d744612f0fce19eae2"
51
+ "gitHead": "0afe5ac938419c584db685cddcbd8974ee000d7e"
52
52
  }
@@ -0,0 +1,55 @@
1
+ <template lang="pug">
2
+ button.dito-button(
3
+ :type="type"
4
+ :title="title"
5
+ :disabled="disabled"
6
+ :class="[classes, { 'dito-button--affixed': hasAffixes }]"
7
+ v-bind="attributes"
8
+ )
9
+ .dito-button__prefix(
10
+ v-if="hasAffixes"
11
+ )
12
+ slot(name="prefix")
13
+ .dito-button__text(
14
+ v-if="text || hasAffixes"
15
+ ) {{ text || '' }}
16
+ slot
17
+ .dito-button__suffix(
18
+ v-if="hasAffixes"
19
+ )
20
+ slot(name="suffix")
21
+ </template>
22
+
23
+ <script>
24
+ import { hasSlotContent } from '../utils/vue.js'
25
+
26
+ export default {
27
+ inheritAttrs: false,
28
+
29
+ props: {
30
+ type: { type: String, default: 'button' },
31
+ text: { type: String, default: null },
32
+ title: { type: String, default: null },
33
+ disabled: { type: Boolean, default: false }
34
+ },
35
+
36
+ computed: {
37
+ hasAffixes() {
38
+ return hasSlotContent('prefix') || hasSlotContent('suffix')
39
+ },
40
+
41
+ classes() {
42
+ return this.$attrs.class
43
+ },
44
+
45
+ attributes() {
46
+ const { class: _, ...attributes } = this.$attrs
47
+ return attributes
48
+ }
49
+ },
50
+
51
+ methods: {
52
+ hasSlotContent
53
+ }
54
+ }
55
+ </script>
@@ -1,6 +1,6 @@
1
1
  <!-- Derived from ATUI, and further extended: https://aliqin.github.io/atui/ -->
2
2
  <template lang="pug">
3
- Trigger.dito-date-picker(
3
+ DitoTrigger.dito-date-picker(
4
4
  ref="trigger"
5
5
  v-model:show="showPopup"
6
6
  trigger="focus"
@@ -11,29 +11,28 @@ Trigger.dito-date-picker(
11
11
  v-if="$slots.trigger"
12
12
  name="trigger"
13
13
  )
14
- InputField.dito-date-picker-input(
14
+ DitoInput.dito-date-picker-input(
15
15
  v-else
16
16
  ref="input"
17
17
  v-model="currentText"
18
18
  type="text"
19
- :class="{ 'dito-focus': focused }"
20
- v-bind="{ placeholder, disabled, ...$attrs }"
19
+ v-bind="{ placeholder, disabled, focused, ...$attrs }"
21
20
  @focus="onFocus(true)"
22
21
  @blur="onFocus(false)"
23
22
  @keydown="onKeyDown"
24
23
  @mousedown.stop="onMouseDown(false)"
25
24
  )
26
- template(#before)
27
- slot(name="before")
28
- template(#after)
29
- Icon(
25
+ template(#prefix)
26
+ slot(name="prefix")
27
+ template(#suffix)
28
+ DitoIcon(
30
29
  name="calendar"
31
30
  :disabled="disabled"
32
31
  @mousedown.prevent="onMouseDown(true)"
33
32
  )
34
- slot(name="after")
33
+ slot(name="suffix")
35
34
  template(#popup)
36
- Calendar.dito-date-picker-popup(
35
+ DitoCalendar.dito-date-picker-popup(
37
36
  ref="calendar"
38
37
  v-model="currentValue"
39
38
  v-bind="{ locale, disabledDate }"
@@ -43,17 +42,17 @@ Trigger.dito-date-picker(
43
42
 
44
43
  <script>
45
44
  import { format, defaultFormats } from '@ditojs/utils'
46
- import Trigger from './Trigger.vue'
47
- import Calendar from './Calendar.vue'
48
- import InputField from './InputField.vue'
49
- import Icon from './Icon.vue'
45
+ import DitoTrigger from './DitoTrigger.vue'
46
+ import DitoCalendar from './DitoCalendar.vue'
47
+ import DitoInput from './DitoInput.vue'
48
+ import DitoIcon from './DitoIcon.vue'
50
49
  import { parseDate, getDatePartAtPosition } from '../utils/date.js'
51
50
  import { getSelection, setSelection } from '../utils/selection.js'
52
51
  import { getKeyNavigation } from '../utils/event.js'
53
52
  import { getTarget } from '../utils/trigger.js'
54
53
 
55
54
  export default {
56
- components: { Trigger, Calendar, InputField, Icon },
55
+ components: { DitoTrigger, DitoCalendar, DitoInput, DitoIcon },
57
56
  emits: ['update:modelValue', 'update:show', 'change', 'focus', 'blur'],
58
57
  inheritAttrs: false,
59
58
 
@@ -1,27 +1,28 @@
1
1
  <template lang="pug">
2
2
  .dito-date-time-picker(ref="picker")
3
- .dito-date-time-picker__inner(:class="{ 'dito-focus': focused }")
4
- InputField.dito-date-time-picker__input(
3
+ .dito-date-time-picker__inner(
4
+ :class="{ 'dito-date-time-picker__inner--focus': focused }"
5
+ )
6
+ DitoInput.dito-date-time-picker__input(
5
7
  ref="input"
6
8
  v-model="currentText"
7
9
  type="text"
8
- :class="{ 'dito-focus': focused }"
9
- v-bind="{ placeholder, disabled, ...$attrs }"
10
+ v-bind="{ placeholder, disabled, focused, ...$attrs }"
10
11
  @focus="onFocus(true)"
11
12
  @blur="onFocus(false)"
12
13
  @keydown="onKeyDown"
13
14
  @mousedown.stop="onMouseDown(false)"
14
15
  )
15
- template(#before)
16
- slot(name="before")
17
- template(#after)
18
- Icon(
16
+ template(#prefix)
17
+ slot(name="prefix")
18
+ template(#suffix)
19
+ DitoIcon(
19
20
  name="calendar"
20
21
  :disabled="disabled"
21
22
  @mousedown.prevent="onMouseDown(true)"
22
23
  )
23
- slot(name="after")
24
- DatePicker(
24
+ slot(name="suffix")
25
+ DitoDatePicker(
25
26
  ref="date"
26
27
  v-model="currentValue"
27
28
  v-model:show="showDate"
@@ -31,7 +32,7 @@
31
32
  )
32
33
  template(#trigger)
33
34
  //- Intentionally empty
34
- TimePicker(
35
+ DitoTimePicker(
35
36
  ref="time"
36
37
  v-model="currentValue"
37
38
  v-model:show="showTime"
@@ -45,16 +46,16 @@
45
46
 
46
47
  <script>
47
48
  import { format, defaultFormats, assignDeeply } from '@ditojs/utils'
48
- import InputField from './InputField.vue'
49
- import DatePicker from './DatePicker.vue'
50
- import TimePicker from './TimePicker.vue'
51
- import Icon from './Icon.vue'
49
+ import DitoInput from './DitoInput.vue'
50
+ import DitoDatePicker from './DitoDatePicker.vue'
51
+ import DitoTimePicker from './DitoTimePicker.vue'
52
+ import DitoIcon from './DitoIcon.vue'
52
53
  import { parseDate } from '../utils/date.js'
53
54
  import { getSelection, setSelection } from '../utils/selection.js'
54
55
  import { getKeyNavigation } from '../utils/event.js'
55
56
 
56
57
  export default {
57
- components: { InputField, DatePicker, TimePicker, Icon },
58
+ components: { DitoInput, DitoDatePicker, DitoTimePicker, DitoIcon },
58
59
  emits: ['update:modelValue', 'change', 'focus', 'blur'],
59
60
  inheritAttrs: false,
60
61
 
@@ -1,10 +1,5 @@
1
1
  <template lang="pug">
2
- i.dito-icon(
3
- :class=`{
4
- ['dito-icon--' + name]: true,
5
- 'dito-icon--disabled': disabled
6
- }`
7
- )
2
+ i.dito-icon(:class="classes")
8
3
  </template>
9
4
 
10
5
  <script>
@@ -18,6 +13,16 @@ export default {
18
13
  type: Boolean,
19
14
  default: false
20
15
  }
16
+ },
17
+
18
+ computed: {
19
+ classes() {
20
+ const prefix = 'dito-icon'
21
+ return {
22
+ [`${prefix}--${this.name}`]: true,
23
+ [`${prefix}--disabled`]: this.disabled
24
+ }
25
+ }
21
26
  }
22
27
  }
23
28
  </script>
@@ -40,17 +45,17 @@ export default {
40
45
  }
41
46
 
42
47
  .dito-icon {
48
+ position: relative;
49
+ width: 1em;
50
+ height: 1em;
51
+
43
52
  @at-root .dito-input & {
44
- position: absolute;
45
- inset: $border-width;
46
- left: unset;
47
- width: 2em;
48
53
  font-style: normal;
49
54
  border-radius: $border-radius;
50
55
  color: $color-grey;
51
56
  background: $color-white;
52
57
 
53
- &--disabled {
58
+ &.dito-icon--disabled {
54
59
  color: $color-light;
55
60
  }
56
61
  }
@@ -1,6 +1,9 @@
1
1
  <template lang="pug">
2
- .dito-input(:class="classes")
3
- slot(name="before")
2
+ .dito-input(
3
+ :class="classes"
4
+ @mousedown.prevent="onMouseDown"
5
+ )
6
+ slot(name="prefix")
4
7
  input(
5
8
  :id="id"
6
9
  ref="input"
@@ -16,7 +19,7 @@
16
19
  :aria-label="title"
17
20
  v-bind="attributes"
18
21
  )
19
- slot(name="after")
22
+ slot(name="suffix")
20
23
  </template>
21
24
 
22
25
  <script>
@@ -33,21 +36,25 @@ export default {
33
36
  disabled: { type: Boolean, default: false },
34
37
  readonly: { type: Boolean, default: false },
35
38
  autofocus: { type: Boolean, default: false },
39
+ focused: { type: Boolean, default: false },
36
40
  placeholder: { type: String, default: null },
37
41
  autocomplete: { type: String, default: 'off' }
38
42
  },
39
43
 
40
44
  data() {
41
45
  return {
42
- currentValue: this.modelValue,
43
- hovering: false,
44
- focused: false
46
+ currentValue: this.modelValue
45
47
  }
46
48
  },
47
49
 
48
50
  computed: {
49
51
  classes() {
50
- return this.$attrs.class
52
+ return [
53
+ this.$attrs.class,
54
+ {
55
+ 'dito-input--focus': this.focused
56
+ }
57
+ ]
51
58
  },
52
59
 
53
60
  attributes() {
@@ -88,6 +95,14 @@ export default {
88
95
 
89
96
  blur() {
90
97
  this.input.blur()
98
+ },
99
+
100
+ onMouseDown() {
101
+ // Focus the input when the outer container is clicked, e.g. when clicking
102
+ // on affixes.
103
+ if (!this.disabled && !this.readonly) {
104
+ this.focus()
105
+ }
91
106
  }
92
107
  }
93
108
  }
@@ -97,15 +112,17 @@ export default {
97
112
  @import '../styles/_imports';
98
113
 
99
114
  .dito-input {
100
- display: inline-block;
115
+ display: inline-flex;
116
+ align-items: center;
101
117
 
102
118
  @extend %input;
103
119
 
104
120
  input {
105
121
  // Inherit all styling from .dito-input
106
122
  all: inherit;
123
+ flex: 1;
124
+ min-width: 0;
107
125
  display: inline-block;
108
- width: 100%;
109
126
  border: 0;
110
127
  margin: 0;
111
128
  padding: 0;
@@ -7,7 +7,7 @@
7
7
  template(
8
8
  v-if="total > 0"
9
9
  ) {{ first }} – {{ last }} / {{ total }}
10
- .dito-buttons.dito-buttons-round(
10
+ .dito-buttons.dito-buttons--round(
11
11
  v-if="numPages > 1"
12
12
  )
13
13
  button.dito-button(
@@ -136,13 +136,11 @@ export default {
136
136
 
137
137
  methods: {
138
138
  getButtonClasses(button) {
139
- const classes = {
140
- 'dito-selected': button.active
139
+ const prefix = 'dito-button'
140
+ return {
141
+ [`${prefix}--${button.type}`]: button.type,
142
+ [`${prefix}--active`]: button.active
141
143
  }
142
- if (button.type) {
143
- classes[`dito-button-${button.type}`] = true
144
- }
145
- return classes
146
144
  },
147
145
 
148
146
  onClickButton(button) {
@@ -180,19 +178,19 @@ export default {
180
178
  font-variant-numeric: tabular-nums;
181
179
  padding: 0 0.5em;
182
180
 
183
- &-prev,
184
- &-next {
181
+ &--prev,
182
+ &--next {
185
183
  &::before {
186
184
  @extend %icon-arrow;
187
185
  }
188
186
  }
189
187
 
190
- &-prev::before {
188
+ &--prev::before {
191
189
  transform: scaleX(-1);
192
190
  }
193
191
 
194
- &-ellipsis-prev,
195
- &-ellipsis-next {
192
+ &--ellipsis-prev,
193
+ &--ellipsis-next {
196
194
  background: none;
197
195
  border: 0;
198
196
  padding: 0;
@@ -216,7 +214,7 @@ export default {
216
214
  }
217
215
  }
218
216
 
219
- &-ellipsis-prev::before {
217
+ &--ellipsis-prev::before {
220
218
  transform: scaleX(-1);
221
219
  }
222
220
  }
@@ -3,7 +3,7 @@
3
3
  :class="classes"
4
4
  :style="styles"
5
5
  )
6
- .dito-switch-pane
6
+ .dito-switch__pane
7
7
  input(
8
8
  :id="id"
9
9
  ref="input"
@@ -13,8 +13,8 @@
13
13
  :name="name"
14
14
  :disabled="disabled"
15
15
  )
16
- .dito-switch-button
17
- span.dito-switch-label(
16
+ .dito-switch__button
17
+ span.dito-switch__label(
18
18
  v-if="labels"
19
19
  )
20
20
  slot(
@@ -48,11 +48,12 @@ export default {
48
48
 
49
49
  computed: {
50
50
  classes() {
51
+ const prefix = 'dito-switch'
51
52
  return [
52
53
  this.$attrs.class,
53
54
  {
54
- 'dito-checked': this.checked,
55
- 'dito-disabled': this.disabled
55
+ [`${prefix}--checked`]: this.checked,
56
+ [`${prefix}--disabled`]: this.disabled
56
57
  }
57
58
  ]
58
59
  },
@@ -97,6 +98,8 @@ export default {
97
98
  @import '../styles/_imports';
98
99
 
99
100
  .dito-switch {
101
+ $self: &;
102
+
100
103
  // Use whole multiples of `rem` for sizes and `px` margins/padding along
101
104
  // with `calc()` to end up with even pixel sizes.
102
105
  --switch-width: 4em;
@@ -116,14 +119,14 @@ export default {
116
119
  vertical-align: bottom;
117
120
  @include user-select(none);
118
121
 
119
- .dito-switch-pane {
122
+ &__pane {
120
123
  position: relative;
121
124
  width: var(--width);
122
125
  height: var(--height);
123
126
  }
124
127
 
125
- .dito-switch-pane,
126
- .dito-switch-label {
128
+ &__pane,
129
+ &__label {
127
130
  top: 50%;
128
131
  transform: translateY(-50%);
129
132
  }
@@ -140,7 +143,7 @@ export default {
140
143
  background-color 0.3s;
141
144
  }
142
145
 
143
- .dito-switch-button {
146
+ &__button {
144
147
  --size: calc(var(--height) - 2 * var(--switch-padding));
145
148
 
146
149
  position: absolute;
@@ -155,39 +158,39 @@ export default {
155
158
  transform: translateX(0);
156
159
  }
157
160
 
158
- .dito-switch-button,
159
- .dito-switch-label {
161
+ &__button,
162
+ &__label {
160
163
  pointer-events: none;
161
164
  }
162
165
 
163
- .dito-switch-label {
166
+ &__label {
164
167
  position: absolute;
165
168
  right: var(--label-margin);
166
169
  text-transform: uppercase;
167
170
  color: $color-white;
168
171
  }
169
172
 
170
- &.dito-checked {
173
+ &--checked {
171
174
  input {
172
175
  background: $color-active;
173
176
  }
174
177
 
175
- .dito-switch-button {
178
+ #{$self}__button {
176
179
  transform: translateX(var(--offset));
177
180
  }
178
181
 
179
- .dito-switch-label {
182
+ #{$self}__label {
180
183
  left: var(--label-margin);
181
184
  right: unset;
182
185
  }
183
186
  }
184
187
 
185
- &.dito-disabled {
188
+ &--disabled {
186
189
  @extend %button-disabled;
187
190
  }
188
191
 
189
192
  &:focus-within:not(:hover) {
190
- .dito-switch-button {
193
+ #{$self}__button {
191
194
  box-shadow: $shadow-focus;
192
195
  }
193
196
  }
@@ -1,6 +1,6 @@
1
1
  <!-- Derived from ATUI, and further extended: https://aliqin.github.io/atui/ -->
2
2
  <template lang="pug">
3
- Trigger.dito-time-picker(
3
+ DitoTrigger.dito-time-picker(
4
4
  ref="trigger"
5
5
  v-model:show="showPopup"
6
6
  trigger="focus"
@@ -11,27 +11,26 @@ Trigger.dito-time-picker(
11
11
  v-if="$slots.trigger"
12
12
  name="trigger"
13
13
  )
14
- InputField.dito-time-picker-input(
14
+ DitoInput.dito-time-picker-input(
15
15
  v-else
16
16
  ref="input"
17
17
  v-model="currentText"
18
18
  type="text"
19
- :class="{ 'dito-focus': focused }"
20
- v-bind="{ placeholder, disabled, ...$attrs }"
19
+ v-bind="{ placeholder, disabled, focused, ...$attrs }"
21
20
  @focus="onFocus(true)"
22
21
  @blur="onFocus(false)"
23
22
  @keydown="onKeyDown"
24
23
  @mousedown.stop="onMouseDown(false)"
25
24
  )
26
- template(#before)
27
- slot(name="before")
28
- template(#after)
29
- Icon(
25
+ template(#prefix)
26
+ slot(name="prefix")
27
+ template(#suffix)
28
+ DitoIcon(
30
29
  name="clock"
31
30
  :disabled="disabled"
32
31
  @mousedown.prevent="onMouseDown(true)"
33
32
  )
34
- slot(name="after")
33
+ slot(name="suffix")
35
34
  template(#popup)
36
35
  .dito-time-picker-popup
37
36
  .dito-time-picker-panel
@@ -68,16 +67,16 @@ Trigger.dito-time-picker(
68
67
 
69
68
  <script>
70
69
  import { format, defaultFormats } from '@ditojs/utils'
71
- import Trigger from './Trigger.vue'
72
- import InputField from './InputField.vue'
73
- import Icon from './Icon.vue'
70
+ import DitoTrigger from './DitoTrigger.vue'
71
+ import DitoInput from './DitoInput.vue'
72
+ import DitoIcon from './DitoIcon.vue'
74
73
  import { alterDate, parseDate, getDatePartAtPosition } from '../utils/date.js'
75
74
  import { getSelection, setSelection } from '../utils/selection.js'
76
75
  import { getKeyNavigation } from '../utils/event.js'
77
76
  import { getTarget } from '../utils/trigger.js'
78
77
 
79
78
  export default {
80
- components: { Trigger, InputField, Icon },
79
+ components: { DitoTrigger, DitoInput, DitoIcon },
81
80
  emits: ['update:modelValue', 'update:show', 'change', 'focus', 'blur'],
82
81
  inheritAttrs: false,
83
82
 
@@ -1,9 +1,10 @@
1
- export { default as Calendar } from './Calendar.vue'
2
- export { default as DatePicker } from './DatePicker.vue'
3
- export { default as DateTimePicker } from './DateTimePicker.vue'
4
- export { default as Icon } from './Icon.vue'
5
- export { default as InputField } from './InputField.vue'
6
- export { default as Pagination } from './Pagination.vue'
7
- export { default as SwitchButton } from './SwitchButton.vue'
8
- export { default as TimePicker } from './TimePicker.vue'
9
- export { default as Trigger } from './Trigger.vue'
1
+ export { default as DitoButton } from './DitoButton.vue'
2
+ export { default as DitoCalendar } from './DitoCalendar.vue'
3
+ export { default as DitoDatePicker } from './DitoDatePicker.vue'
4
+ export { default as DitoDateTimePicker } from './DitoDateTimePicker.vue'
5
+ export { default as DitoIcon } from './DitoIcon.vue'
6
+ export { default as DitoInput } from './DitoInput.vue'
7
+ export { default as DitoPagination } from './DitoPagination.vue'
8
+ export { default as DitoSwitch } from './DitoSwitch.vue'
9
+ export { default as DitoTimePicker } from './DitoTimePicker.vue'
10
+ export { default as DitoTrigger } from './DitoTrigger.vue'