@energie360/ui-library 0.1.16 → 0.1.18

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 (102) hide show
  1. package/components/badge/badge.scss +56 -0
  2. package/components/badge/u-badge.vue +47 -0
  3. package/components/card-contact/card-contact.scss +39 -0
  4. package/components/card-contact/u-card-contact.vue +44 -0
  5. package/components/card-cta-bar/card-cta-bar.scss +4 -0
  6. package/components/card-cta-bar/u-card-cta-bar.vue +24 -0
  7. package/components/card-cta-header/u-card-cta-header.vue +10 -7
  8. package/components/card-footer/u-card-footer.vue +5 -3
  9. package/components/card-group/u-card-group.vue +1 -1
  10. package/components/card-header/card-header.scss +29 -4
  11. package/components/card-header/u-card-header.vue +22 -3
  12. package/components/card-highlight/card-highlight.scss +70 -0
  13. package/components/card-highlight/u-card-highlight.vue +41 -0
  14. package/components/card-info/card-info.scss +40 -0
  15. package/components/card-info/u-card-info.vue +35 -0
  16. package/components/card-price-list/card-price-list.scss +39 -0
  17. package/components/card-price-list/u-card-price-list.vue +37 -0
  18. package/components/card-section/card-section.scss +21 -1
  19. package/components/card-section/u-card-section.vue +9 -1
  20. package/components/data-card/data-card.scss +34 -0
  21. package/components/data-card/u-data-card.vue +49 -0
  22. package/components/data-card-group/data-card-group.scss +12 -0
  23. package/components/data-card-group/u-data-card-group.vue +7 -0
  24. package/components/download-list/download-list.scss +58 -0
  25. package/components/download-list/u-download-list.vue +44 -0
  26. package/components/download-list-item/download-list-item.scss +267 -0
  27. package/components/download-list-item/u-download-list-item.vue +65 -0
  28. package/components/file-upload/file-list.scss +68 -0
  29. package/components/file-upload/file-upload.scss +119 -0
  30. package/components/file-upload/u-file-list.vue +55 -0
  31. package/components/file-upload/u-file-upload.vue +220 -0
  32. package/components/hint/hint.scss +67 -6
  33. package/components/hint/u-hint.vue +11 -1
  34. package/components/index.js +13 -0
  35. package/components/inline-edit/inline-edit.scss +5 -1
  36. package/components/inline-edit/u-inline-edit.vue +21 -12
  37. package/components/progress-avatar/u-progress-avatar.vue +27 -3
  38. package/components/richtext/richtext.scss +9 -2
  39. package/components/richtext/u-richtext.vue +3 -1
  40. package/components/search-group/search-group.scss +59 -0
  41. package/components/search-group/u-search-group.vue +32 -0
  42. package/components/skeleton-loader/skeleton-loader.scss +39 -0
  43. package/components/skeleton-loader/u-skeleton-loader.vue +28 -0
  44. package/components/table/cell-ctas.scss +1 -7
  45. package/components/table/cell-icon-text.scss +15 -4
  46. package/components/table/table-cell.mixins.scss +3 -2
  47. package/components/table/table-cell.scss +5 -0
  48. package/components/table/table-heading.scss +7 -0
  49. package/components/table/u-cell-ctas.vue +15 -6
  50. package/components/table/u-cell-icon-text.vue +13 -5
  51. package/components/table/u-table-cell.vue +3 -1
  52. package/components/table/u-table-heading.vue +2 -1
  53. package/components/tabs/tabs.scss +10 -1
  54. package/components/tabs/u-tabs.vue +64 -25
  55. package/dist/elements/form.css +170 -0
  56. package/dist/elements/form.css.map +1 -0
  57. package/dist/layout/form-grid.css +184 -0
  58. package/dist/layout/form-grid.css.map +1 -0
  59. package/dist/layout/split.css.map +1 -1
  60. package/elements/button/_button-plain-small-spaceless.scss +10 -0
  61. package/elements/button/button.scss +32 -0
  62. package/elements/button/u-button.vue +47 -4
  63. package/elements/form/form.scss +1 -1
  64. package/elements/form-field/form-field-base.scss +4 -0
  65. package/elements/form-field/form-field-prefix-suffix.scss +5 -0
  66. package/elements/select/u-select.vue +6 -6
  67. package/elements/text-field/text-field.scss +15 -0
  68. package/elements/text-field/text-field.types.ts +1 -0
  69. package/elements/text-field/u-text-field.vue +44 -8
  70. package/elements/toggle-switch/toggle-switch-small.scss +10 -0
  71. package/elements/toggle-switch/toggle-switch.scss +25 -21
  72. package/elements/toggle-switch/u-toggle-switch.vue +22 -12
  73. package/i18n/i18n.ts +32 -0
  74. package/layout/container/container.scss +18 -0
  75. package/layout/index.js +4 -0
  76. package/layout/portal/portal.scss +63 -0
  77. package/layout/portal/u-portal.vue +51 -0
  78. package/layout/settings/settings.scss +33 -0
  79. package/layout/settings/u-settings-layout.vue +19 -0
  80. package/layout/tile-grid/tile-grid.scss +13 -0
  81. package/layout/tile-grid/tile-item.scss +31 -0
  82. package/layout/tile-grid/u-tile-grid.vue +7 -0
  83. package/layout/tile-grid/u-tile-item.vue +15 -0
  84. package/modules/content-title/content-title.scss +43 -0
  85. package/modules/content-title/u-content-title.vue +19 -0
  86. package/modules/dialog/_animations.scss +49 -0
  87. package/modules/dialog/dialog.scss +172 -0
  88. package/modules/dialog/u-dialog.vue +139 -0
  89. package/modules/footer/footer.scss +8 -1
  90. package/modules/footer/u-footer.vue +1 -1
  91. package/modules/index.js +3 -0
  92. package/modules/inline-edit-group/u-inline-edit-group.vue +2 -0
  93. package/modules/search-filter/search-filter.scss +106 -0
  94. package/modules/search-filter/u-search-filter.vue +54 -0
  95. package/package.json +3 -1
  96. package/utility/elements/form.scss +1 -0
  97. package/utility/layout/form-grid.scss +1 -0
  98. package/utils/array/intersect.js +7 -0
  99. package/utils/functions/breakpoint.js +4 -9
  100. package/utils/functions/format-bytes.js +17 -0
  101. package/utils/global/mime-types.js +8 -0
  102. package/utils/translations/translate.js +10 -2
@@ -1,8 +1,7 @@
1
1
  @use '../../base/abstracts' as a;
2
2
  @use './wizard';
3
3
 
4
- .richtext {
5
- // Spacing rules
4
+ @mixin richtext-spacing-rules {
6
5
  * + * {
7
6
  margin-top: var(--e-space-3);
8
7
  }
@@ -23,7 +22,9 @@
23
22
  * + ol {
24
23
  margin-top: var(--e-space-6);
25
24
  }
25
+ }
26
26
 
27
+ @mixin richtext-spacing-rules-mobile {
27
28
  @include a.bp(lg) {
28
29
  * + * {
29
30
  margin-top: var(--e-space-2);
@@ -41,6 +42,12 @@
41
42
  margin-top: var(--e-space-10);
42
43
  }
43
44
  }
45
+ }
46
+
47
+ .richtext {
48
+ // Spacing rules
49
+ @include richtext-spacing-rules;
50
+ @include richtext-spacing-rules-mobile;
44
51
 
45
52
  // Element styles
46
53
  h2,
@@ -13,7 +13,9 @@ const classes = ['richtext', { 'richtext--small': small, 'richtext--inverted': i
13
13
  <template>
14
14
  <div v-if="text" :class="classes" v-html="text"></div>
15
15
 
16
- <div v-else :class="classes"><slot></slot></div>
16
+ <div v-else :class="classes">
17
+ <slot />
18
+ </div>
17
19
  </template>
18
20
 
19
21
  <style lang="scss" src="./richtext.scss"></style>
@@ -0,0 +1,59 @@
1
+ @use '../../base/abstracts' as a;
2
+
3
+ @mixin fields-mobile {
4
+ @include a.bp(lg) {
5
+ display: grid;
6
+ grid-template-columns: 1fr 1fr;
7
+
8
+ > * {
9
+ max-width: none;
10
+ }
11
+ }
12
+
13
+ @include a.bp(m) {
14
+ grid-template-columns: 1fr;
15
+ }
16
+ }
17
+
18
+ .search-group__title {
19
+ @include a.type(200, strong);
20
+
21
+ margin-bottom: var(--e-space-3);
22
+ }
23
+
24
+ .search-group + .search-group {
25
+ margin-top: var(--e-space-8);
26
+ }
27
+
28
+ .search-group.wrap {
29
+ .search-group__fields {
30
+ display: grid;
31
+ gap: var(--e-space-6);
32
+ grid-template-columns: repeat(4, 1fr);
33
+
34
+ > * {
35
+ max-width: none;
36
+ }
37
+
38
+ @include fields-mobile;
39
+ }
40
+ }
41
+
42
+ .search-group__fields {
43
+ display: flex;
44
+ gap: var(--e-space-6);
45
+
46
+ > * {
47
+ flex: 1 1 auto;
48
+ max-width: calc(25% - 18px);
49
+ }
50
+
51
+ @include fields-mobile;
52
+ }
53
+
54
+ .search-group__ctas {
55
+ display: flex;
56
+ gap: var(--e-space-6);
57
+ flex-wrap: wrap;
58
+ margin-top: var(--e-space-10);
59
+ }
@@ -0,0 +1,32 @@
1
+ <script setup lang="ts">
2
+ import { onMounted, ref, useTemplateRef } from 'vue'
3
+
4
+ interface Props {
5
+ title?: string
6
+ }
7
+
8
+ defineProps<Props>()
9
+
10
+ const fieldsEl = useTemplateRef('fields')
11
+ const fieldCount = ref(0)
12
+
13
+ onMounted(() => {
14
+ fieldCount.value = fieldsEl.value.children.length
15
+ })
16
+ </script>
17
+
18
+ <template>
19
+ <fieldset :class="['search-group', { wrap: fieldCount > 5 }]">
20
+ <legend v-if="title" class="search-group__title">{{ title }}</legend>
21
+
22
+ <div ref="fields" class="search-group__fields">
23
+ <slot />
24
+ </div>
25
+
26
+ <div v-if="$slots.ctas" class="search-group__ctas">
27
+ <slot name="ctas"></slot>
28
+ </div>
29
+ </fieldset>
30
+ </template>
31
+
32
+ <style scoped scss src="./search-group.scss"></style>
@@ -0,0 +1,39 @@
1
+ @use '../../base/abstracts' as a;
2
+
3
+ @keyframes skeleton-animation {
4
+ 0% {
5
+ background-color: var(--e-c-primary-01-50);
6
+ }
7
+
8
+ 100% {
9
+ background-color: var(--e-c-primary-01-100);
10
+ }
11
+ }
12
+
13
+ @mixin skeleton-base {
14
+ background-color: var(--e-c-primary-01-50);
15
+ border-radius: var(--e-brd-radius-2);
16
+ width: 100%;
17
+ height: 100%;
18
+ animation-name: skeleton-animation;
19
+ animation-duration: var(--e-trs-duration-slower);
20
+ animation-direction: alternate;
21
+ animation-timing-function: ease-in-out;
22
+ animation-iteration-count: infinite;
23
+ }
24
+
25
+ .skeleton-loader.fit {
26
+ @include skeleton-base;
27
+ }
28
+
29
+ .skeleton-loader.table {
30
+ display: flex;
31
+ flex-direction: column;
32
+ row-gap: var(--e-space-2);
33
+
34
+ > div {
35
+ @include skeleton-base;
36
+
37
+ height: a.rem(52);
38
+ }
39
+ }
@@ -0,0 +1,28 @@
1
+ <script setup lang="ts">
2
+ enum SkeletonType {
3
+ fit = 'fit',
4
+ table = 'table',
5
+ }
6
+
7
+ interface Props {
8
+ type?: SkeletonType
9
+ }
10
+
11
+ const { type = SkeletonType.fit } = defineProps<Props>()
12
+ </script>
13
+
14
+ <template>
15
+ <template v-if="type === SkeletonType.table">
16
+ <div :class="['skeleton-loader', type]">
17
+ <div></div>
18
+ <div></div>
19
+ <div></div>
20
+ </div>
21
+ </template>
22
+
23
+ <template v-if="type === SkeletonType.fit">
24
+ <div class="skeleton-loader fit"></div>
25
+ </template>
26
+ </template>
27
+
28
+ <style scoped lang="scss" src="./skeleton-loader.scss"></style>
@@ -2,11 +2,5 @@
2
2
 
3
3
  .cell-ctas {
4
4
  display: flex;
5
- column-gap: var(--e-space-2);
6
-
7
- .button-label {
8
- @include a.bp(m) {
9
- @include a.visually-hidden;
10
- }
11
- }
5
+ column-gap: var(--e-space-4);
12
6
  }
@@ -13,10 +13,21 @@
13
13
  }
14
14
 
15
15
  @include a.type(100);
16
- }
17
16
 
18
- .cell-text {
19
- @include a.bp(m) {
20
- @include a.visually-hidden;
17
+ // Modifiers
18
+ &.hide-text-lg {
19
+ .cell-text {
20
+ @include a.bp(lg) {
21
+ @include a.visually-hidden;
22
+ }
23
+ }
24
+ }
25
+
26
+ &.hide-text-m {
27
+ .cell-text {
28
+ @include a.bp(m) {
29
+ @include a.visually-hidden;
30
+ }
31
+ }
21
32
  }
22
33
  }
@@ -4,8 +4,7 @@
4
4
  display: table-cell;
5
5
  padding: var(--e-space-4);
6
6
  height: a.rem(56);
7
-
8
- @include a.type(100);
7
+ line-height: 0;
9
8
 
10
9
  @include a.bp(m) {
11
10
  height: auto;
@@ -18,6 +17,8 @@
18
17
  }
19
18
 
20
19
  .cell-content {
20
+ @include a.type(100);
21
+
21
22
  display: inline-flex;
22
23
  column-gap: var(--e-space-2);
23
24
  min-height: a.rem(24);
@@ -14,6 +14,11 @@
14
14
  &.text-bold {
15
15
  font-weight: var(--e-type-weight-strong);
16
16
  }
17
+
18
+ // Modifiers
19
+ &.nowrap {
20
+ white-space: nowrap;
21
+ }
17
22
  }
18
23
 
19
24
  .info-tooltip {
@@ -6,3 +6,10 @@
6
6
 
7
7
  @include c.table-cell-base;
8
8
  }
9
+
10
+ .cell-content {
11
+ // Modifiers
12
+ &.nowrap {
13
+ white-space: nowrap;
14
+ }
15
+ }
@@ -4,10 +4,11 @@ import UButton from '../../elements/button/u-button.vue'
4
4
 
5
5
  interface CellCta extends Cta {
6
6
  icon: string
7
+ attr: object
7
8
  }
8
9
 
9
10
  interface Props {
10
- ctas: CellCta[]
11
+ ctas?: CellCta[]
11
12
  }
12
13
 
13
14
  defineProps<Props>()
@@ -16,13 +17,21 @@ defineProps<Props>()
16
17
  <template>
17
18
  <div class="cell-ctas">
18
19
  <template v-for="(cta, idx) in ctas" :key="idx">
19
- <UButton variant="plain" :icon="cta.icon" :href="cta.href" :target="cta.target">
20
- <span class="button-label">{{ cta.label }}</span>
20
+ <UButton
21
+ nowrap
22
+ variant="plain"
23
+ :icon="cta.icon"
24
+ :href="cta.href"
25
+ :target="cta.target"
26
+ v-bind="cta.attr"
27
+ hide-label-m
28
+ >
29
+ {{ cta.label }}
21
30
  </UButton>
22
31
  </template>
32
+
33
+ <slot></slot>
23
34
  </div>
24
35
  </template>
25
36
 
26
- <style scoped lang="scss">
27
- @use './cell-ctas.scss';
28
- </style>
37
+ <style scoped lang="scss" src="./cell-ctas.scss"></style>
@@ -5,19 +5,27 @@ import UIcon from '../../elements/icon/u-icon.vue'
5
5
  interface Props extends TableCellBase {
6
6
  icon: string
7
7
  iconColor?: TableCellIconColor
8
+ hideTextM?: false
9
+ hideTextLg?: false
8
10
  }
9
11
 
10
12
  const { iconColor = TableCellIconColor.grey } = defineProps<Props>()
11
13
  </script>
12
14
 
13
15
  <template>
14
- <div :class="['cell-icon-text', `icon-color-${iconColor}`]">
16
+ <div
17
+ :class="[
18
+ 'cell-icon-text',
19
+ `icon-color-${iconColor}`,
20
+ { 'hide-text-m': hideTextM, 'hide-text-lg': hideTextLg },
21
+ ]"
22
+ >
15
23
  <UIcon :name="icon"></UIcon>
16
24
 
17
- <span class="cell-text">{{ text }}</span>
25
+ <span class="cell-text">
26
+ <slot>{{ text }}</slot>
27
+ </span>
18
28
  </div>
19
29
  </template>
20
30
 
21
- <style scoped lang="scss">
22
- @use './cell-icon-text.scss';
23
- </style>
31
+ <style scoped lang="scss" src="./cell-icon-text.scss"></style>
@@ -6,12 +6,14 @@ import UTooltip from '../tooltip/u-tooltip.vue'
6
6
  interface Props extends TableCellBase {
7
7
  infoText?: string
8
8
  textStyle?: TableCellTextStyle
9
+ nowrap?: boolean
9
10
  }
10
11
 
11
12
  const {
12
13
  textStyle = TableCellTextStyle.normal,
13
14
  hAlign = TableCellHAlign.left,
14
15
  vAlign = TableCellVAlign.center,
16
+ nowrap = false,
15
17
  } = defineProps<Props>()
16
18
  </script>
17
19
 
@@ -20,7 +22,7 @@ const {
20
22
  role="cell"
21
23
  :class="['table-cell', `h-align-${hAlign}`, `v-align-${vAlign}`, { 'has-tooltip': infoText }]"
22
24
  >
23
- <div :class="['cell-content', `text-${textStyle}`]">
25
+ <div :class="['cell-content', `text-${textStyle}`, { nowrap }]">
24
26
  <slot>{{ text }}</slot>
25
27
  </div>
26
28
 
@@ -3,6 +3,7 @@ interface Props {
3
3
  text?: string
4
4
  hAlign?: 'left' | 'center' | 'right'
5
5
  vAlign?: 'top' | 'center' | 'bottom'
6
+ nowrap?: boolean
6
7
  }
7
8
 
8
9
  const { hAlign = 'left', vAlign = 'top' } = defineProps<Props>()
@@ -10,7 +11,7 @@ const { hAlign = 'left', vAlign = 'top' } = defineProps<Props>()
10
11
 
11
12
  <template>
12
13
  <div role="cell" :class="['table-heading', `h-align-${hAlign}`, `v-align-${vAlign}`]">
13
- <div class="cell-content">
14
+ <div :class="['cell-content', { nowrap }]">
14
15
  <slot :text="text">{{ text }}</slot>
15
16
  </div>
16
17
  </div>
@@ -1,4 +1,4 @@
1
- @use '../../base/abstracts/' as a;
1
+ @use '../../base/abstracts' as a;
2
2
 
3
3
  .tabs {
4
4
  $scroll-space: 18px;
@@ -86,3 +86,12 @@
86
86
  width a.$trs-default;
87
87
  }
88
88
  }
89
+
90
+ // Modifiers
91
+ .tabs.no-gradient {
92
+ .tabs__wrapper {
93
+ &::after {
94
+ content: none;
95
+ }
96
+ }
97
+ }
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { useTemplateRef, ref, watch } from 'vue'
2
+ import { useTemplateRef, ref, watch, useSlots } from 'vue'
3
3
  import { getOffsetParentPosition } from '../../utils/dom/dom'
4
4
  import { debounce } from '../../utils/functions/debounce'
5
5
 
@@ -11,14 +11,16 @@ interface Tab {
11
11
 
12
12
  interface Props {
13
13
  activation?: 'manual' | 'automatic'
14
- items: Tab[]
14
+ items?: Tab[]
15
+ noGradient?: boolean
15
16
  }
16
17
 
17
- const { activation = 'manual' } = defineProps<Props>()
18
+ const { items = [], activation = 'manual' } = defineProps<Props>()
18
19
  const emit = defineEmits<{ (e: 'tabFocus', id: string): void }>()
19
20
 
20
21
  const model = defineModel<string>()
21
22
  const activeBarStyles = ref({})
23
+ const slots = useSlots()
22
24
 
23
25
  const tabs = useTemplateRef('tabs')
24
26
  const list = useTemplateRef('list')
@@ -87,7 +89,14 @@ const onResize = debounce(() => {
87
89
  const isActiveTab = (currentTabId: string) => currentTabId === model.value
88
90
 
89
91
  const positionActiveBar = () => {
90
- const activeTabEl = tabs.value.find((item) => item.value === model.value)
92
+ let activeTabEl
93
+
94
+ if (slots.default) {
95
+ activeTabEl = Array.from(list.value.children).find((el) => el.classList.contains('active'))
96
+ } else {
97
+ activeTabEl = tabs.value.find((item) => item.value === model.value)
98
+ }
99
+
91
100
  const activeTabRelPos = getOffsetParentPosition(activeTabEl)
92
101
 
93
102
  activeBarStyles.value = {
@@ -107,36 +116,66 @@ onResize()
107
116
  </script>
108
117
 
109
118
  <template>
110
- <div class="tabs">
119
+ <div :class="['tabs', { 'no-gradient': noGradient }]">
111
120
  <div class="tabs__row">
112
121
  <div class="tabs__col">
113
122
  <div class="tabs__wrapper">
114
123
  <div ref="list" class="tabs__list" role="tablist">
115
- <button
116
- v-for="(item, idx) in items"
117
- :key="idx"
118
- ref="tabs"
119
- :class="{ active: isActiveTab(item.value) }"
120
- :value="item.value"
121
- type="button"
122
- role="tab"
123
- :tabindex="isActiveTab(item.value) ? 0 : -1"
124
- :aria-selected="isActiveTab(item.value)"
125
- v-bind="item.analyticsAttributes || {}"
126
- @click="onTabClick"
127
- @keydown="onTabKeyDown"
128
- >
129
- {{ item.label }}
130
- </button>
131
-
132
- <div class="tabs__active-bar" :style="activeBarStyles"></div>
124
+ <slot>
125
+ <button
126
+ v-for="(item, idx) in items"
127
+ :key="idx"
128
+ ref="tabs"
129
+ :class="{ active: isActiveTab(item.value) }"
130
+ :value="item.value"
131
+ type="button"
132
+ role="tab"
133
+ :tabindex="isActiveTab(item.value) ? 0 : -1"
134
+ :aria-selected="isActiveTab(item.value)"
135
+ v-bind="item.analyticsAttributes || {}"
136
+ @click="onTabClick"
137
+ @keydown="onTabKeyDown"
138
+ >
139
+ {{ item.label }}
140
+ </button>
141
+ </slot>
133
142
  </div>
143
+ <div class="tabs__active-bar" :style="activeBarStyles"></div>
134
144
  </div>
135
145
  </div>
136
146
  </div>
137
147
  </div>
138
148
  </template>
139
149
 
140
- <style lang="scss">
141
- @use './tabs.scss';
150
+ <style scoped lang="scss" src="./tabs.scss"></style>
151
+ <style scoped lang="scss">
152
+ @use '../../base/abstracts' as a;
153
+
154
+ .tabs__list {
155
+ :slotted(a),
156
+ :slotted(button) {
157
+ @include a.type(200, strong);
158
+
159
+ display: block;
160
+ padding: var(--e-space-4);
161
+ text-decoration: none;
162
+ color: var(--e-c-mono-700);
163
+ transition: color a.$trs-default;
164
+ white-space: nowrap;
165
+ outline-offset: -4px;
166
+ cursor: pointer;
167
+
168
+ &.active,
169
+ &:focus,
170
+ &:hover {
171
+ color: var(--e-c-primary-01-700);
172
+ }
173
+
174
+ @include a.bp(lg) {
175
+ @include a.type(100, strong);
176
+
177
+ padding: var(--e-space-2) var(--e-space-3);
178
+ }
179
+ }
180
+ }
142
181
  </style>