@awes-io/ui 2.98.2 → 2.100.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 (34) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/assets/css/components/_index.css +1 -0
  3. package/assets/css/components/action-button.css +15 -1
  4. package/assets/css/components/description.css +1 -7
  5. package/assets/css/components/layout-menu.css +0 -4
  6. package/assets/css/components/layout.css +12 -4
  7. package/assets/css/components/nav.css +22 -1
  8. package/assets/css/components/page-header.css +83 -10
  9. package/assets/css/components/page-single.css +5 -33
  10. package/assets/css/components/page.css +25 -15
  11. package/assets/css/components/select.css +2 -2
  12. package/assets/css/components/text-field.css +16 -0
  13. package/assets/css/components/toggle-show-aside.css +81 -0
  14. package/assets/css/typography.css +2 -2
  15. package/assets/js/icons/mono.js +2 -2
  16. package/assets/js/styles.js +11 -11
  17. package/components/1_atoms/AwActionCard.vue +8 -1
  18. package/components/1_atoms/AwInput.vue +15 -1
  19. package/components/1_atoms/AwSelectNative.vue +1 -1
  20. package/components/1_atoms/AwTag.vue +5 -0
  21. package/components/2_molecules/_AwSelectFakeInput.vue +1 -1
  22. package/components/3_organisms/AwToggleShowAside.vue +190 -0
  23. package/components/4_pages/AwPage.vue +85 -30
  24. package/components/4_pages/AwPageMenuButtons.vue +50 -28
  25. package/components/4_pages/AwPageSingle.vue +1 -28
  26. package/components/4_pages/_AwPageHeader.vue +34 -2
  27. package/components/5_layouts/_AwLayoutMenu.vue +48 -7
  28. package/components/5_layouts/_AwMobileMenuItem.vue +7 -5
  29. package/components/5_layouts/_AwNav.vue +76 -70
  30. package/components/_config.js +20 -1
  31. package/directives/tooltip.js +31 -29
  32. package/mixins/page.js +58 -0
  33. package/package.json +2 -2
  34. package/tailwind/container.js +3 -1
@@ -130,15 +130,29 @@ export default {
130
130
  )
131
131
  return false
132
132
  }
133
+ },
134
+
135
+ theme: {
136
+ type: String,
137
+ default: ''
133
138
  }
134
139
  },
135
140
 
136
141
  computed: {
137
142
  elClasses() {
138
143
  let base = this.$options._config.baseClass
144
+ const theme = String(this.theme)
139
145
 
140
146
  return {
141
- base,
147
+ base: [
148
+ base,
149
+ {
150
+ [`${base}--page`]: theme.includes('page'),
151
+ [`${base}--uncolor-prefix`]: theme.includes(
152
+ 'uncolor-prefix'
153
+ )
154
+ }
155
+ ],
142
156
  el: `${base}__element`,
143
157
  label: `${base}__label`,
144
158
  labelRequired: `${base}__label--required`,
@@ -30,7 +30,7 @@
30
30
  </label>
31
31
 
32
32
  <div class="aw-text-field__caret pl-2 pr-4">
33
- <AwIcon name="triangle-d" size="12" />
33
+ <AwIcon name="awesio/triangle" />
34
34
  </div>
35
35
  </div>
36
36
 
@@ -30,6 +30,11 @@ export default {
30
30
  text: {
31
31
  type: String,
32
32
  required: true
33
+ },
34
+
35
+ icon: {
36
+ type: String,
37
+ default: null
33
38
  }
34
39
  },
35
40
 
@@ -23,7 +23,7 @@
23
23
  <slot name="prefix">{{ prefix }}</slot>
24
24
  </span>
25
25
 
26
- <span class="block relative w-full">
26
+ <span class="block relative w-full min-w-0">
27
27
  <span
28
28
  class="aw-text-field__element aw-text-field__element--fake"
29
29
  tabindex="0"
@@ -0,0 +1,190 @@
1
+ <template>
2
+ <div
3
+ class="aw-toggle-show-aside"
4
+ :class="{
5
+ 'aw-toggle-show-aside--hide':
6
+ !isShown && !isShownOnMouse && !isShownOnBtn,
7
+ 'aw-toggle-show-aside--reverse': reverse,
8
+ 'aw-toggle-show-aside--shadow':
9
+ (!isShown && isShownOnMouse) || (!isShown && isShownOnBtn)
10
+ }"
11
+ >
12
+ <div class="aw-toggle-show-aside__btn-wrapper">
13
+ <button
14
+ v-tooltip="
15
+ isAttachedKeyListener && isVisibleTooltip
16
+ ? {
17
+ content: $t(
18
+ `${isShown ? 'Collapse' : 'Expand'} {key}`,
19
+ {
20
+ key: toggleKeyHTML
21
+ }
22
+ ),
23
+ placement: reverse ? 'left' : 'right',
24
+ flip: false
25
+ }
26
+ : null
27
+ "
28
+ class="aw-toggle-show-aside__arrow-btn"
29
+ @click="onClickToggleShown"
30
+ @mouseenter="onMouseEnterBtn"
31
+ @mouseleave="onMouseLeaveBtn"
32
+ >
33
+ <AwIconSystemMono
34
+ class="aw-toggle-show-aside__arrow-btn-icon"
35
+ :class="{
36
+ 'aw-toggle-show-aside__arrow-btn-icon--reverse': !isShown
37
+ }"
38
+ :name="reverse ? 'angle-r' : 'angle'"
39
+ size="16"
40
+ />
41
+ </button>
42
+ </div>
43
+
44
+ <div
45
+ class="w-full h-full overflow-hidden"
46
+ @mousemove="onMouseEnterShowSubmenu"
47
+ @mouseleave="onMouseLeaveHideSubmenu"
48
+ >
49
+ <slot v-if="isShown || isShownOnMouse || isShownOnBtn" />
50
+ </div>
51
+ </div>
52
+ </template>
53
+
54
+ <script>
55
+ import { conf } from '@AwUtils/component'
56
+ import { AwToggleShowAside as _config } from '@AwConfig'
57
+ import { toggleEvents } from '@AwUtils/events'
58
+
59
+ export default {
60
+ name: 'AwToggleShowAside',
61
+
62
+ _config,
63
+
64
+ props: {
65
+ name: {
66
+ type: String,
67
+ required: true
68
+ },
69
+
70
+ reverse: Boolean,
71
+
72
+ isAttachedKeyListener: {
73
+ type: Boolean,
74
+ default() {
75
+ return conf(this, 'isAttachedKeyListener')
76
+ }
77
+ },
78
+
79
+ options: {
80
+ type: Object,
81
+ default() {
82
+ return conf(this, 'options')
83
+ }
84
+ }
85
+ },
86
+
87
+ data: () => ({
88
+ isShown: true,
89
+ isShownOnMouse: false,
90
+ isShownOnBtn: false,
91
+ isVisibleTooltip: true
92
+ }),
93
+
94
+ computed: {
95
+ toggleKey() {
96
+ return this.reverse ? ']' : '['
97
+ },
98
+
99
+ toggleKeyHTML() {
100
+ return '<kbd>' + this.toggleKey + '</kbd>'
101
+ }
102
+ },
103
+
104
+ watch: {
105
+ isAttachedKeyListener: {
106
+ handler: 'toggleKeyListener',
107
+ immediate: true
108
+ }
109
+ },
110
+
111
+ beforeMount() {
112
+ let state = localStorage.getItem(this.name)
113
+
114
+ if (!state) {
115
+ localStorage.setItem(this.name, 'true')
116
+ } else {
117
+ this.isShown = state.toLowerCase() === 'true'
118
+ }
119
+ },
120
+
121
+ beforeDestroy() {
122
+ if (this.isAttachedKeyListener) {
123
+ this.toggleKeyListener(false)
124
+ }
125
+ },
126
+
127
+ methods: {
128
+ toggleKeyListener(enable = false) {
129
+ toggleEvents(
130
+ window,
131
+ [['keydown', this.onKeyDownToggleShown]],
132
+ enable
133
+ )
134
+ },
135
+
136
+ toggleShown() {
137
+ this.isShown = !this.isShown
138
+
139
+ if (!this.isShown) {
140
+ this.isShownOnBtn = false
141
+ }
142
+
143
+ localStorage.setItem(this.name, `${this.isShown}`)
144
+
145
+ this.$emit('toggle', this.isShown)
146
+ },
147
+
148
+ onClickToggleShown($event) {
149
+ this.isVisibleTooltip = false
150
+ this.toggleShown()
151
+
152
+ setTimeout(() => {
153
+ this.isVisibleTooltip = true
154
+ }, 0)
155
+ },
156
+
157
+ onKeyDownToggleShown(event) {
158
+ if (event.key === this.toggleKey) {
159
+ this.toggleShown()
160
+ }
161
+ },
162
+
163
+ onMouseEnterShowSubmenu() {
164
+ clearTimeout(this._mouseTm)
165
+
166
+ this._mouseTm = setTimeout(() => {
167
+ this.isShownOnMouse = true
168
+ }, this.options.showTimeout)
169
+ },
170
+
171
+ onMouseLeaveHideSubmenu() {
172
+ clearTimeout(this._mouseTm)
173
+
174
+ this._mouseTm = setTimeout(() => {
175
+ this.isShownOnMouse = false
176
+ }, this.options.hideTimeout)
177
+ },
178
+
179
+ onMouseEnterBtn() {
180
+ if (this.isShownOnMouse) {
181
+ this.isShownOnBtn = true
182
+ }
183
+ },
184
+
185
+ onMouseLeaveBtn() {
186
+ this.isShownOnBtn = false
187
+ }
188
+ }
189
+ }
190
+ </script>
@@ -1,32 +1,61 @@
1
1
  <template>
2
- <div class="aw-page">
3
- <div
4
- class="aw-page__heading"
5
- :class="{
6
- 'aw-page__heading--sticky': stickyHeader
7
- }"
8
- >
2
+ <div
3
+ class="aw-page"
4
+ :style="{
5
+ '--page-buttons-bottom': _hideBottomBar ? null : '3.5rem'
6
+ }"
7
+ >
8
+ <div class="aw-page__heading">
9
9
  <slot name="heading" v-bind="{ titleTag, title, breadcrumb }">
10
- <AwPageHeadline
10
+ <AwPageHeader
11
+ ref="header"
12
+ :primary="!isDesktop && isHeaderStuck"
13
+ :title="_title"
14
+ :hide-title="!isDesktop && !isHeaderStuck"
15
+ :container="container"
16
+ :is-stuck="isHeaderStuck && !isDesktop"
17
+ hide-menu
18
+ class="aw-page__header"
19
+ :class="{
20
+ 'aw-page__header--is-empty':
21
+ !isHeaderStuck &&
22
+ !isDesktop &&
23
+ !$scopedSlots['buttons'] &&
24
+ !$scopedSlots['after-breadcrumb'] &&
25
+ !$scopedSlots['headline-breadcrumb'] &&
26
+ !backUrl &&
27
+ !isMenuToggler
28
+ }"
11
29
  :style="{
12
- '--page-buttons-bottom': _hideBottomBar
13
- ? null
14
- : '3.5rem'
30
+ '--breadcrumb-width':
31
+ backUrl || isMenuToggler ? '2.5rem' : '0px'
15
32
  }"
16
- :title="_title"
17
- :breadcrumb="breadcrumb"
18
- :breadcrumb-menu="breadcrumbMenu"
19
- :buttons-breakpoint="buttonsBreakpoint"
20
- :container="headerContainer || container"
21
- :title-centered="titleCentered || stickyHeader"
22
33
  >
23
- <template
24
- v-for="(index, name) in $scopedSlots"
25
- v-slot:[name]="data"
26
- >
27
- <slot :name="name" v-bind="data"></slot>
34
+ <template #breadcrumbs>
35
+ <slot name="headline-breadcrumb">
36
+ <AwButton
37
+ v-if="backUrl || isMenuToggler"
38
+ :color="
39
+ isDesktop || !isHeaderStuck
40
+ ? 'mono'
41
+ : 'mono-light'
42
+ "
43
+ :href="backUrl || '/more'"
44
+ :aria-label="breadcrumb?.title ?? $t('Back')"
45
+ >
46
+ <template #icon>
47
+ <AwIconSystemMono name="arrow" />
48
+ </template>
49
+ </AwButton>
50
+ </slot>
51
+
52
+ <slot name="after-breadcrumb" />
53
+ </template>
54
+
55
+ <template #default>
56
+ <slot name="buttons"></slot>
28
57
  </template>
29
- </AwPageHeadline>
58
+ </AwPageHeader>
30
59
  </slot>
31
60
 
32
61
  <!-- subnav -->
@@ -55,9 +84,20 @@
55
84
  >
56
85
  <!-- eslint-disable prettier/prettier -->
57
86
  <div :class="[containerClass, { 'aw-page__grid': hasAside }]">
87
+ <div class="aw-page__mobile-title" aria-hidden="true">
88
+ {{ _title }}
89
+ </div>
90
+
91
+ <div
92
+ ref="topScrollMark"
93
+ class="aw-page__top-scroll-mark"
94
+ aria-hidden="true"
95
+ ></div>
96
+
58
97
  <div v-if="hasAside">
59
98
  <slot />
60
99
  </div>
100
+
61
101
  <slot v-else></slot>
62
102
 
63
103
  <div v-if="hasAside">
@@ -117,7 +157,7 @@
117
157
  import { pathOr } from 'rambdax'
118
158
  import pageMixin from '@AwMixins/page'
119
159
  import AwBottomBar from '@AwOrganisms/AwBottomBar.vue'
120
- import AwPageHeadline from '@AwPages/_AwPageHeadline.vue'
160
+ import { conf } from '@AwUtils/component'
121
161
 
122
162
  export default {
123
163
  name: 'AwPage',
@@ -126,7 +166,7 @@ export default {
126
166
 
127
167
  components: {
128
168
  AwBottomBar,
129
- AwPageHeadline
169
+ AwPageHeader: () => import('@AwPages/_AwPageHeader.vue')
130
170
  },
131
171
 
132
172
  props: {
@@ -154,10 +194,6 @@ export default {
154
194
  default: null
155
195
  },
156
196
 
157
- stickyHeader: Boolean,
158
-
159
- titleCentered: Boolean,
160
-
161
197
  // Disable mobile bottom menu
162
198
  hideBottomBar: {
163
199
  type: Boolean,
@@ -178,11 +214,30 @@ export default {
178
214
  data() {
179
215
  return {
180
216
  isFullscreen: false,
181
- isFakeFullscreen: false
217
+ isFakeFullscreen: false,
218
+ isHeaderStuck: false
219
+ }
220
+ },
221
+
222
+ provide() {
223
+ return {
224
+ teleportButtonsTo: '.aw-page'
182
225
  }
183
226
  },
184
227
 
185
228
  computed: {
229
+ isMenuToggler() {
230
+ return (
231
+ !this.backUrl &&
232
+ !this.$screen.lg &&
233
+ this.breadcrumbMenu !== false
234
+ )
235
+ },
236
+
237
+ isDesktop() {
238
+ return this.$screen[this.buttonsBreakpoint] || false
239
+ },
240
+
186
241
  _hideBottomBar() {
187
242
  return this.hideBottomBar === null
188
243
  ? this._hasBreadcrumb
@@ -38,36 +38,38 @@
38
38
  </AwFlow>
39
39
 
40
40
  <!-- fixed button -->
41
- <div
41
+ <Teleport
42
42
  v-if="!isExpanded && splitButtons.fixed"
43
- class="aw-page-menu-buttons__fixed-btns"
43
+ :to="teleportButtonsTo"
44
44
  >
45
- <AwButton
46
- v-for="({ listeners, tooltip, ...attrs },
47
- i) in splitButtons.fixed"
48
- :key="i"
49
- v-tooltip="tooltip"
50
- v-bind="attrs"
51
- auto-width
52
- v-on="listeners"
53
- >
54
- <template #icon="{ icon }">
55
- <AwIcon :name="icon" />
56
- </template>
57
-
58
- <template #default="{ text }">
59
- <span
60
- v-if="text"
61
- class="aw-page-menu-buttons__fixed-btn-text truncate"
62
- :class="{
63
- 'aw-page-menu-buttons__fixed-btn-text--expanded': isInTopPosition
64
- }"
65
- >
66
- {{ text }}
67
- </span>
68
- </template>
69
- </AwButton>
70
- </div>
45
+ <div class="aw-page-menu-buttons__fixed-btns">
46
+ <AwButton
47
+ v-for="({ listeners, tooltip, ...attrs },
48
+ i) in splitButtons.fixed"
49
+ :key="i"
50
+ v-tooltip="tooltip"
51
+ v-bind="attrs"
52
+ auto-width
53
+ v-on="listeners"
54
+ >
55
+ <template #icon="{ icon }">
56
+ <AwIcon :name="icon" />
57
+ </template>
58
+
59
+ <template #default="{ text }">
60
+ <span
61
+ v-if="text"
62
+ class="aw-page-menu-buttons__fixed-btn-text truncate"
63
+ :class="{
64
+ 'aw-page-menu-buttons__fixed-btn-text--expanded': isInTopPosition
65
+ }"
66
+ >
67
+ {{ text }}
68
+ </span>
69
+ </template>
70
+ </AwButton>
71
+ </div>
72
+ </Teleport>
71
73
  </div>
72
74
  </template>
73
75
 
@@ -85,6 +87,10 @@ const toIconButton = (props) => ({
85
87
  export default {
86
88
  name: 'AwPageMenuButtons',
87
89
 
90
+ components: {
91
+ Teleport: () => import('vue2-teleport')
92
+ },
93
+
88
94
  props: {
89
95
  items: {
90
96
  type: Array,
@@ -96,6 +102,11 @@ export default {
96
102
  default: 'lg'
97
103
  },
98
104
 
105
+ teleportFixedTo: {
106
+ type: String,
107
+ default: 'body'
108
+ },
109
+
99
110
  /* max window scroll when fixed buttons expanded */
100
111
  /* pass -1 to collapse button eventually */
101
112
  expandOffset: {
@@ -118,7 +129,18 @@ export default {
118
129
  }
119
130
  },
120
131
 
132
+ inject: {
133
+ injectedTeleportButtonsTo: {
134
+ from: 'teleportButtonsTo',
135
+ default: ''
136
+ }
137
+ },
138
+
121
139
  computed: {
140
+ teleportButtonsTo() {
141
+ return this.injectedTeleportButtonsTo || this.teleportButtonsTo
142
+ },
143
+
122
144
  isExpanded() {
123
145
  return (
124
146
  this.breakpoint === 'default' || this.$screen[this.breakpoint]
@@ -7,8 +7,8 @@
7
7
  :title="_title"
8
8
  :hide-title="!isDesktop && !isHeaderStuck"
9
9
  :hide-menu="hideMenu"
10
+ :is-stuck="isHeaderStuck"
10
11
  class="aw-page-single__header"
11
- :class="{ 'aw-page-single__header--is-stuck': isHeaderStuck }"
12
12
  >
13
13
  <template #breadcrumbs>
14
14
  <slot name="breadcrumb">
@@ -174,7 +174,6 @@ export default {
174
174
 
175
175
  data() {
176
176
  return {
177
- isHeaderStuck: false,
178
177
  isActionButtonStuck: false
179
178
  }
180
179
  },
@@ -211,25 +210,6 @@ export default {
211
210
  }
212
211
  },
213
212
 
214
- watch: {
215
- isDesktop() {
216
- if (this.$options.$observer) {
217
- this.$nextTick(() => {
218
- this._disableScrollWatcher()
219
- this._initScrollWatcher()
220
- })
221
- }
222
- }
223
- },
224
-
225
- mounted() {
226
- this._initScrollWatcher()
227
- },
228
-
229
- beforeDestroy() {
230
- this._disableScrollWatcher()
231
- },
232
-
233
213
  methods: {
234
214
  _initScrollWatcher() {
235
215
  if (this.$options.$observer) return
@@ -252,13 +232,6 @@ export default {
252
232
 
253
233
  this.$options.$observer.observe(topScrollMark)
254
234
  this.$options.$observer.observe(bottomScrollMark)
255
- },
256
-
257
- _disableScrollWatcher() {
258
- if (!this.$options.$observer) return
259
-
260
- this.$options.$observer.disconnect()
261
- this.$options.$observer = null
262
235
  }
263
236
  }
264
237
  }
@@ -1,5 +1,13 @@
1
1
  <template>
2
- <div class="aw-page-header" :class="{ 'aw-page-header--primary': primary }">
2
+ <div
3
+ class="aw-page-header"
4
+ :class="{
5
+ 'aw-page-header--primary': primary,
6
+ 'aw-page-header--is-stuck': isStuck,
7
+ 'aw-page-header--container': container !== 'full'
8
+ }"
9
+ :style="{ '--header-container-width': headerContainerWidth }"
10
+ >
3
11
  <div class="aw-page-header__breadcrumbs">
4
12
  <slot name="breadcrumbs"> </slot>
5
13
  </div>
@@ -48,16 +56,40 @@ export default {
48
56
  default: ''
49
57
  },
50
58
 
59
+ container: {
60
+ type: String,
61
+ default: 'full'
62
+ },
63
+
51
64
  hideTitle: Boolean,
52
65
 
53
66
  hideMenu: Boolean,
54
67
 
55
- primary: Boolean
68
+ primary: Boolean,
69
+
70
+ isStuck: Boolean
56
71
  },
57
72
 
58
73
  computed: {
59
74
  showProgress() {
60
75
  return isType('Number', this.progress)
76
+ },
77
+
78
+ headerContainerWidth() {
79
+ let name = ''
80
+
81
+ switch (this.container) {
82
+ case 'default':
83
+ name = '--container-width'
84
+ break
85
+ case 'small':
86
+ name = '--container-small-width'
87
+ break
88
+ }
89
+
90
+ return name
91
+ ? `var(${name}, calc(100% + 2 * var(--header-padding-horizontal)))`
92
+ : null
61
93
  }
62
94
  }
63
95
  }