@energie360/ui-library 0.1.15 → 0.1.17

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 (58) hide show
  1. package/components/card-info/card-info.scss +40 -0
  2. package/components/card-info/u-card-info.vue +35 -0
  3. package/components/index.js +1 -0
  4. package/components/inline-edit/inline-edit.scss +5 -1
  5. package/components/inline-edit/u-inline-edit.vue +21 -12
  6. package/components/navigation-panel-tile/navigation-panel-tile.scss +1 -1
  7. package/components/navigation-panel-tile/u-navigation-panel-tile.vue +17 -13
  8. package/components/richtext/_wizard.scss +26 -0
  9. package/components/richtext/richtext.scss +11 -3
  10. package/components/richtext/u-richtext.vue +3 -1
  11. package/dist/elements/form.css +170 -0
  12. package/dist/elements/form.css.map +1 -0
  13. package/dist/layout/form-grid.css +184 -0
  14. package/dist/layout/form-grid.css.map +1 -0
  15. package/elements/checkbox/checkbox.scss +150 -0
  16. package/elements/checkbox/u-checkbox.vue +42 -0
  17. package/elements/form/form.scss +1 -1
  18. package/elements/form-field/form-field-prefix-suffix.scss +5 -0
  19. package/elements/index.js +3 -0
  20. package/elements/radio/radio.scss +91 -2
  21. package/elements/radio/u-radio.vue +6 -3
  22. package/elements/radio-group/radio-group.scss +28 -0
  23. package/elements/radio-group/u-radio-group.vue +23 -3
  24. package/elements/select-chip/select-chip.scss +1 -0
  25. package/elements/select-chip/u-select-chip.vue +2 -2
  26. package/elements/select-chips/select-chips.scss +18 -0
  27. package/elements/select-chips/u-select-chips.vue +16 -3
  28. package/elements/select-tile/select-tile.scss +205 -0
  29. package/elements/select-tile/u-select-tile.vue +53 -0
  30. package/elements/select-tiles/select-tiles.scss +32 -0
  31. package/elements/select-tiles/u-select-tiles.vue +31 -0
  32. package/elements/text-field/u-text-field.vue +22 -5
  33. package/elements/toggle-switch/toggle-switch.scss +14 -4
  34. package/elements/toggle-switch/u-toggle-switch.vue +23 -20
  35. package/layout/index.js +2 -0
  36. package/layout/portal/portal.scss +35 -0
  37. package/layout/portal/u-portal.vue +22 -0
  38. package/layout/settings/settings.scss +33 -0
  39. package/layout/settings/u-settings-layout.vue +19 -0
  40. package/modules/dialog/_animations.scss +49 -0
  41. package/modules/dialog/dialog.scss +168 -0
  42. package/modules/dialog/u-dialog.vue +134 -0
  43. package/modules/index.js +4 -0
  44. package/modules/inline-edit-group/u-inline-edit-group.vue +2 -0
  45. package/modules/navigation-panel/navigation-panel.scss +1 -0
  46. package/modules/progress-indicator/progress-indicator.scss +84 -0
  47. package/modules/progress-indicator/u-progress-indicator.vue +34 -0
  48. package/modules/toast/toast-message.scss +67 -0
  49. package/modules/toast/toast.scss +14 -0
  50. package/modules/toast/u-toast-message.vue +46 -0
  51. package/modules/toast/u-toast.vue +26 -0
  52. package/modules/toast/useToast.ts +40 -0
  53. package/package.json +2 -1
  54. package/utility/elements/form.scss +1 -0
  55. package/utility/layout/form-grid.scss +1 -0
  56. package/wizard/index.js +1 -0
  57. package/wizard/wizard-outro/u-wizard-outro.vue +49 -0
  58. package/wizard/wizard-outro/wizard-outro.scss +56 -0
@@ -0,0 +1,53 @@
1
+ <script setup lang="ts">
2
+ import UIcon from '../icon/u-icon.vue'
3
+ import { useRadio } from '../radio-group/radio-group-composables'
4
+
5
+ interface Props {
6
+ name: string
7
+ label: string
8
+ text: string
9
+ disabled?: boolean
10
+ value: string
11
+ icon: string
12
+ radio?: boolean
13
+ provideKey?: string
14
+ }
15
+
16
+ const { disabled = false, radio = false, provideKey = 'select-tile-group' } = defineProps<Props>()
17
+
18
+ const model = defineModel<string>()
19
+ const { onChange } = useRadio({ model, provideKey })
20
+ </script>
21
+
22
+ <template>
23
+ <label :class="['select-tile', { checked: model === value, disabled }]">
24
+ <div v-if="radio" class="select-tile__radio-wrapper">
25
+ <span class="select-tile__radio-symbol"></span>
26
+ </div>
27
+
28
+ <div class="select-tile__content">
29
+ <!-- ICON -->
30
+ <div v-if="icon" class="select-tile__icon-wrapper">
31
+ <UIcon :name="icon" :width="40" :height="40" />
32
+ </div>
33
+
34
+ <!-- LABEL -->
35
+ <div class="select-tile__label-wrapper">
36
+ <slot name="label">
37
+ {{ label }}
38
+ </slot>
39
+ </div>
40
+
41
+ <!-- TEXT -->
42
+ <div class="select-tile__text-wrapper">
43
+ <p>{{ text }}</p>
44
+ </div>
45
+ </div>
46
+
47
+ <div class="select-tile__input-wrapper">
48
+ <input type="radio" :name :value :disabled @change="onChange" />
49
+ </div>
50
+ </label>
51
+ </template>
52
+
53
+ <style scoped style="scss" src="./select-tile.scss"></style>
@@ -0,0 +1,32 @@
1
+ @use '../../base/abstracts/' as a;
2
+
3
+ .select-tiles {
4
+ &.error {
5
+ .select-tiles__error-message {
6
+ display: block;
7
+ }
8
+ }
9
+ }
10
+
11
+ .select-tiles__items {
12
+ display: grid;
13
+ grid-template-columns: repeat(2, 1fr);
14
+ grid-gap: var(--e-space-10);
15
+
16
+ @include a.bp(lg) {
17
+ grid-gap: var(--e-space-4);
18
+ }
19
+
20
+ @include a.bp(m) {
21
+ display: flex;
22
+ flex-direction: column;
23
+ }
24
+ }
25
+
26
+ .select-tiles__error-message {
27
+ @include a.type(50, strong);
28
+
29
+ display: none;
30
+ margin-top: var(--e-space-1);
31
+ color: var(--e-c-signal-03-700);
32
+ }
@@ -0,0 +1,31 @@
1
+ <script setup lang="ts">
2
+ import { useRadioGroup } from '../radio-group/radio-group-composables'
3
+
4
+ interface Props {
5
+ error?: boolean
6
+ errorMessage?: string
7
+ }
8
+
9
+ defineProps<Props>()
10
+
11
+ const model = defineModel<string>()
12
+
13
+ useRadioGroup({
14
+ model,
15
+ provideKey: 'select-tile-group',
16
+ })
17
+ </script>
18
+
19
+ <template>
20
+ <div :class="['select-tiles', { error }]">
21
+ <div class="select-tiles__items">
22
+ <slot></slot>
23
+ </div>
24
+
25
+ <div class="select-tiles__error-message">
26
+ <slot name="error-message">{{ errorMessage }}</slot>
27
+ </div>
28
+ </div>
29
+ </template>
30
+
31
+ <style scoped style="scss" src="./select-tiles.scss"></style>
@@ -37,7 +37,7 @@ const input = useTemplateRef('input')
37
37
  const isFocused = ref(false)
38
38
  const isHovering = ref(false)
39
39
  const hasValue = ref(false) // only needed for input type 'search'
40
- const forceFloatLabel = ref(false)
40
+ const forceFloatLabel = ref(type === TextFieldTypes.date) // input-type 'date' doesn't support placeholder.
41
41
 
42
42
  const spacer = '.&nbsp;'
43
43
 
@@ -122,15 +122,16 @@ watch(
122
122
  'has-error': error,
123
123
  'show-help-text': hasHelpText,
124
124
  },
125
+ type,
125
126
  ]"
126
127
  @mouseenter="onHover"
127
128
  @mouseleave="onHoverOut"
128
129
  >
129
130
  <div class="wrapper">
130
131
  <div class="label">
131
- <slot name="label">
132
- <label :for="inputId">{{ label }}</label>
133
- </slot>
132
+ <label :for="inputId">
133
+ <slot name="label">{{ label }}</slot>
134
+ </label>
134
135
  </div>
135
136
 
136
137
  <div class="control">
@@ -145,6 +146,7 @@ watch(
145
146
  :readonly
146
147
  :placeholder
147
148
  :required
149
+ v-bind="$attrs"
148
150
  @input="onInput"
149
151
  @focus="onFocus"
150
152
  @focusout="$emit('focusout', $event.target)"
@@ -172,6 +174,11 @@ watch(
172
174
  <span v-if="type === TextFieldTypes.date" class="suffix-icon">
173
175
  <UIcon name="calendar"></UIcon>
174
176
  </span>
177
+
178
+ <!-- ACTION -->
179
+ <span v-if="!!slots.action" class="suffix-action custom-action">
180
+ <slot name="action"></slot>
181
+ </span>
175
182
  </div>
176
183
 
177
184
  <div class="help-text">
@@ -189,6 +196,16 @@ watch(
189
196
  </div>
190
197
  </template>
191
198
 
199
+ <style scoped lang="scss" src="./text-field.scss"></style>
200
+
192
201
  <style scoped lang="scss">
193
- @use './text-field.scss';
202
+ .suffix-action.custom-action {
203
+ :slotted(button) {
204
+ cursor: pointer;
205
+ }
206
+
207
+ :slotted(.icon) {
208
+ color: var(--e-c-secondary-05-700);
209
+ }
210
+ }
194
211
  </style>
@@ -17,6 +17,7 @@
17
17
  // So that the focus works nicely.
18
18
  position: absolute;
19
19
  inset: 0;
20
+ border-radius: calc(var(--height) / 2);
20
21
  }
21
22
  }
22
23
 
@@ -87,6 +88,12 @@
87
88
  }
88
89
 
89
90
  // States
91
+ &.error {
92
+ .toggle-switch__error-text {
93
+ display: block;
94
+ }
95
+ }
96
+
90
97
  &.checked {
91
98
  .toggle-switch__toggle {
92
99
  background-color: var(--e-c-primary-01-900);
@@ -141,9 +148,12 @@
141
148
  background-color: var(--e-c-mono-50);
142
149
  }
143
150
  }
151
+ }
152
+
153
+ .toggle-switch__error-text {
154
+ @include a.type(50, strong);
144
155
 
145
- // // TODO: Do we need readonly styles here?
146
- // &.readonly {
147
- // //
148
- // }
156
+ display: none;
157
+ margin-top: var(--e-space-1);
158
+ color: var(--e-c-signal-03-700);
149
159
  }
@@ -6,10 +6,9 @@ import { getTranslation } from '../../utils/translations/translate'
6
6
  export interface ToggleSwitch {
7
7
  name: string
8
8
  label?: string
9
- required?: boolean
10
9
  disabled?: boolean
11
- readonly?: boolean
12
- value?: string
10
+ error: boolean
11
+ errorMessage?: string
13
12
  variant?: 'normal' | 'small'
14
13
  labelPosition?: 'left' | 'right'
15
14
  }
@@ -18,8 +17,8 @@ const {
18
17
  variant = 'big',
19
18
  labelPosition = 'right',
20
19
  disabled = false,
21
- readonly = false,
22
- required = false,
20
+ errorMessage = '',
21
+ error,
23
22
  } = defineProps<ToggleSwitch>()
24
23
 
25
24
  const model = defineModel<boolean>({ default: false })
@@ -35,7 +34,7 @@ const checkIcon = computed(() => iconsMap[variant][1])
35
34
  const classes = computed(() => ({
36
35
  checked: model.value,
37
36
  disabled,
38
- readonly,
37
+ error,
39
38
  [`toggle-switch--${variant}`]: variant,
40
39
  [`label-${labelPosition}`]: labelPosition,
41
40
  }))
@@ -45,24 +44,28 @@ const classes = computed(() => ({
45
44
  <div :class="['toggle-switch', classes]">
46
45
  <label class="toggle-switch__wrapper">
47
46
  <span class="toggle-switch__toggle">
48
- <span class="toggle-switch__text yes" :aria-hidden="model.value ? 'false' : 'true'">{{
49
- getTranslation('yes')
50
- }}</span>
51
- <span class="toggle-switch__text no" :aria-hidden="model.value ? 'true' : 'false'">{{
52
- getTranslation('no')
53
- }}</span>
47
+ <span class="toggle-switch__text yes" :aria-hidden="model ? 'false' : 'true'">
48
+ {{ getTranslation('yes') }}
49
+ </span>
50
+ <span class="toggle-switch__text no" :aria-hidden="model ? 'true' : 'false'">
51
+ {{ getTranslation('no') }}
52
+ </span>
54
53
  <span class="toggle-switch__handle">
55
- <UIcon :name="model.value ? checkIcon : uncheckIcon" custom-size />
54
+ <UIcon :name="model ? checkIcon : uncheckIcon" custom-size />
56
55
  </span>
57
56
  </span>
58
- {{ label }}
59
- <slot name="input"
60
- ><input v-model="model" type="checkbox" :name :required :disabled :readonly :value
61
- /></slot>
57
+
58
+ <slot name="label">{{ label }}</slot>
59
+
60
+ <slot name="input">
61
+ <input v-model="model" type="checkbox" :name :disabled v-bind="$attrs" />
62
+ </slot>
62
63
  </label>
64
+
65
+ <div class="toggle-switch__error-text">
66
+ <slot name="error-message">{{ errorMessage }}</slot>
67
+ </div>
63
68
  </div>
64
69
  </template>
65
70
 
66
- <style lang="scss">
67
- @use './toggle-switch.scss';
68
- </style>
71
+ <style scoped lang="scss" src="./toggle-switch.scss"></style>
@@ -0,0 +1,2 @@
1
+ export { default as USettingsLayout } from './settings/u-settings-layout.vue'
2
+ export { default as UPortalLayout } from './portal/u-portal.vue'
@@ -0,0 +1,35 @@
1
+ @use '../../base/abstracts' as a;
2
+
3
+ .portal {
4
+ display: flex;
5
+ height: 100vh;
6
+ }
7
+
8
+ .portal__top-navigation {
9
+ display: none;
10
+ }
11
+
12
+ .portal__main {
13
+ flex: 1 1 auto;
14
+ display: flex;
15
+ flex-direction: column;
16
+ overflow: auto;
17
+ }
18
+
19
+ .portal__footer {
20
+ margin-top: auto;
21
+ }
22
+
23
+ @include a.bp(lg) {
24
+ .portal {
25
+ flex-direction: column;
26
+ }
27
+
28
+ .portal__top-navigation {
29
+ display: block;
30
+ }
31
+
32
+ .portal__side-navigation {
33
+ display: none;
34
+ }
35
+ }
@@ -0,0 +1,22 @@
1
+ <template>
2
+ <div class="portal">
3
+ <div class="portal__side-navigation">
4
+ <slot name="side-navigation"></slot>
5
+ </div>
6
+
7
+ <div class="portal__top-navigation">
8
+ <slot name="top-navigation"></slot>
9
+ </div>
10
+
11
+ <div class="portal__main">
12
+ <slot></slot>
13
+
14
+ <div class="portal__footer">
15
+ <slot name="footer"></slot>
16
+ </div>
17
+ </div>
18
+ </div>
19
+ </template>
20
+
21
+ <script setup lang="ts"></script>
22
+ <style scoped lang="scss" src="./portal.scss"></style>
@@ -0,0 +1,33 @@
1
+ @use '../../base/abstracts' as a;
2
+
3
+ .settings-layout {
4
+ display: grid;
5
+ grid-template-columns: auto a.rem(320);
6
+ grid-template-rows: repeat(2, auto);
7
+ grid-column-gap: var(--e-space-24);
8
+ grid-row-gap: var(--e-space-12);
9
+ padding: var(--e-space-10);
10
+
11
+ @include a.bp(lg) {
12
+ display: flex;
13
+ flex-direction: column;
14
+ row-gap: var(--e-space-6);
15
+ padding: var(--e-space-6) var(--e-space-5) var(--e-space-10);
16
+ }
17
+ }
18
+
19
+ .settings-layout__header {
20
+ grid-area: 1 / 1 / 2 / 3;
21
+ }
22
+
23
+ .settings-layout__main {
24
+ grid-area: 2 / 1 / 3 / 2;
25
+ }
26
+
27
+ .settings-layout__aside {
28
+ grid-area: 2 / 2 / 3 / 3;
29
+ }
30
+
31
+ .settings-layout__title {
32
+ @include a.type(500, strong);
33
+ }
@@ -0,0 +1,19 @@
1
+ <template>
2
+ <div class="settings-layout">
3
+ <div class="settings-layout__header">
4
+ <h1 class="settings-layout__title">
5
+ <slot name="title"></slot>
6
+ </h1>
7
+ </div>
8
+
9
+ <div class="settings-layout__main">
10
+ <slot name="main"></slot>
11
+ </div>
12
+
13
+ <aside class="settings-layout__aside">
14
+ <slot name="aside"></slot>
15
+ </aside>
16
+ </div>
17
+ </template>
18
+
19
+ <style scoped lang="scss" src="./settings.scss"></style>
@@ -0,0 +1,49 @@
1
+ @keyframes fade-in {
2
+ 0% {
3
+ opacity: 0;
4
+ display: none;
5
+ }
6
+
7
+ 100% {
8
+ opacity: 1;
9
+ display: flex;
10
+ }
11
+ }
12
+
13
+ @keyframes fade-in-backdrop {
14
+ 0% {
15
+ background-color: transparent;
16
+ }
17
+
18
+ 100% {
19
+ background-color: var(--e-c-mono-900);
20
+ }
21
+ }
22
+
23
+ @keyframes slide-in {
24
+ 0% {
25
+ opacity: 1;
26
+ transform: translateY(100%);
27
+ display: none;
28
+ }
29
+
30
+ 100% {
31
+ opacity: 1;
32
+ transform: translateY(0);
33
+ display: flex;
34
+ }
35
+ }
36
+
37
+ @keyframes slide-out {
38
+ 0% {
39
+ opacity: 1;
40
+ transform: translateY(0);
41
+ display: flex;
42
+ }
43
+
44
+ 100% {
45
+ opacity: 1;
46
+ transform: translateY(100%);
47
+ display: none;
48
+ }
49
+ }
@@ -0,0 +1,168 @@
1
+ // TODO: Styles have been copied from 'news'. Refactor when possible.
2
+ @use '../../base/abstracts' as a;
3
+ @use './animations';
4
+
5
+ .dialog-container {
6
+ --overflow-gradient-height: var(--e-space-10);
7
+
8
+ padding: 0;
9
+ border: 0;
10
+ max-height: 100vh;
11
+ max-width: 100vw;
12
+ width: 100%;
13
+ height: 100%;
14
+ background-color: transparent;
15
+ justify-content: center;
16
+ align-items: center;
17
+ overflow: hidden;
18
+
19
+ &[open] {
20
+ display: flex;
21
+ animation: fade-in var(--e-trs-duration-faster) var(--e-trs-easing-default);
22
+ }
23
+
24
+ &[open]::backdrop {
25
+ background-color: var(--e-c-mono-900);
26
+ opacity: 0.4;
27
+ animation: fade-in-backdrop var(--e-trs-duration-faster) var(--e-trs-easing-default);
28
+ }
29
+
30
+ &.has-header-image {
31
+ .dialog__header-image-container {
32
+ display: flex;
33
+ }
34
+ }
35
+
36
+ &.has-content-image {
37
+ .dialog__content-image {
38
+ display: block;
39
+ }
40
+ }
41
+ }
42
+
43
+ .dialog {
44
+ display: flex;
45
+ flex-direction: column;
46
+ background-color: var(--e-c-mono-00);
47
+ overflow: auto;
48
+ scrollbar-width: none;
49
+ border-radius: var(--e-brd-radius-3);
50
+ padding: var(--e-space-7) var(--e-space-7) 0;
51
+ height: a.rem(670);
52
+ max-height: 80vh;
53
+ max-width: a.rem(480);
54
+ width: 100%;
55
+
56
+ * + .dialog__content-image {
57
+ margin-top: var(--e-space-5);
58
+ }
59
+
60
+ @include a.bp(m) {
61
+ max-width: none;
62
+ height: auto;
63
+ min-height: a.rem(440);
64
+ padding-left: var(--e-space-5);
65
+ padding-right: var(--e-space-5);
66
+ }
67
+ }
68
+
69
+ .dialog__header-image-container {
70
+ display: none;
71
+ justify-content: center;
72
+ height: a.rem(184);
73
+ margin-bottom: var(--e-space-8);
74
+
75
+ img {
76
+ object-fit: contain;
77
+ }
78
+ }
79
+
80
+ .dialog__content-container {
81
+ margin-bottom: auto;
82
+ }
83
+
84
+ .content-title {
85
+ @include a.type(500, strong);
86
+
87
+ @include a.bp(m) {
88
+ @include a.type(300, strong);
89
+ }
90
+ }
91
+
92
+ .content-title + .content-text {
93
+ margin-top: var(--e-space-2);
94
+
95
+ @include a.bp(m) {
96
+ margin-top: var(--e-space-1);
97
+ }
98
+ }
99
+
100
+ .dialog__content-image {
101
+ display: none;
102
+
103
+ img {
104
+ width: 100%;
105
+ }
106
+ }
107
+
108
+ .cta-container {
109
+ position: sticky;
110
+ display: flex;
111
+ flex-direction: column;
112
+ bottom: 0;
113
+ margin-top: var(--overflow-gradient-height);
114
+ padding: var(--e-space-8) var(--e-space-1) var(--e-space-7);
115
+ background-color: var(--e-c-mono-00);
116
+
117
+ &::after {
118
+ content: '';
119
+ position: absolute;
120
+ top: calc(var(--overflow-gradient-height) * -1);
121
+ left: 0;
122
+ width: 100%;
123
+ height: var(--overflow-gradient-height);
124
+ background-image: linear-gradient(0deg, rgb(255 255 255 / 100%) 0%, rgb(255 255 255 / 0%) 100%);
125
+ }
126
+
127
+ @include a.bp(m) {
128
+ padding: var(--e-space-8) 0 var(--e-space-7);
129
+ }
130
+ }
131
+
132
+ // MOBILE "MODAL" Variant
133
+ .dialog-container.modal {
134
+ @include a.bp(m) {
135
+ padding-left: a.rem(a.$container-edge-m);
136
+ padding-right: a.rem(a.$container-edge-m);
137
+ }
138
+
139
+ @include a.bp(s) {
140
+ padding-left: a.rem(a.$container-edge-s);
141
+ padding-right: a.rem(a.$container-edge-s);
142
+ }
143
+ }
144
+
145
+ // MOBILE "SLIDE-OUT" Variant
146
+ .dialog-container.slideout {
147
+ @include a.bp(m) {
148
+ align-items: flex-end;
149
+
150
+ // Closing animation
151
+ animation: slide-out var(--e-trs-duration-faster) var(--e-trs-easing-default);
152
+
153
+ &[open] {
154
+ display: flex;
155
+ animation: slide-in var(--e-trs-duration-fast) var(--e-trs-easing-default);
156
+ }
157
+
158
+ .dialog {
159
+ border-bottom-left-radius: 0;
160
+ border-bottom-right-radius: 0;
161
+ max-height: 90vh;
162
+ }
163
+ }
164
+ }
165
+
166
+ body:has(.dialog[open]) {
167
+ overflow: hidden;
168
+ }