@energie360/ui-library 0.1.4 → 0.1.6
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/components/card/card.scss +2 -25
- package/components/card-footer/card-footer.scss +5 -0
- package/components/card-footer/u-card-footer.vue +52 -0
- package/components/card-group/card-group.scss +29 -0
- package/components/card-group/u-card-group.vue +66 -0
- package/components/card-header/card-header.scss +1 -5
- package/components/card-section/card-section.scss +13 -0
- package/components/card-section/u-card-section.vue +7 -0
- package/components/tabs/tabs.scss +88 -0
- package/components/tabs/u-tabs.vue +142 -0
- package/dist/layout/split.css +6 -0
- package/dist/layout/split.css.map +1 -1
- package/elements/button/_button-base.scss +1 -1
- package/elements/form-field/form-field-base.scss +1 -1
- package/elements/icon-button/_icon-button-base.scss +1 -4
- package/elements/radio/index.js +1 -0
- package/elements/radio/radio.scss +7 -0
- package/elements/radio/u-radio.vue +33 -0
- package/elements/radio-group/index.js +1 -0
- package/elements/radio-group/radio-group-composables.ts +38 -0
- package/elements/radio-group/radio-group.scss +3 -0
- package/elements/radio-group/u-radio-group.vue +15 -0
- package/elements/select-chip/u-select-chip.vue +15 -21
- package/elements/select-chips/u-select-chips.vue +5 -8
- package/i18n/i18n.ts +5 -0
- package/layout/split/split.scss +5 -0
- package/modules/feedback/feedback-animations.scss +32 -0
- package/modules/feedback/feedback-form.scss +12 -0
- package/modules/feedback/feedback-vote-buttons.scss +73 -0
- package/modules/feedback/feedback.scss +31 -0
- package/modules/feedback/types/feedback.type.ts +33 -0
- package/modules/feedback/u-feedback-close.vue +32 -0
- package/modules/feedback/u-feedback-finish-view.vue +31 -0
- package/modules/feedback/u-feedback-form.vue +16 -0
- package/modules/feedback/u-feedback-vote-buttons.vue +59 -0
- package/modules/feedback/u-feedback.vue +58 -0
- package/modules/footer/footer.scss +13 -16
- package/modules/footer/u-footer.vue +4 -10
- package/package.json +3 -2
- package/utils/dom/dom.js +167 -0
- package/utils/functions/breakpoint.js +11 -0
- package/utils/functions/debounce.js +25 -0
- package/base-style.js +0 -1
- package/components/icon-teaser/icon-teaser.scss +0 -58
- package/components/icon-teaser/u-icon-teaser.vue +0 -35
- package/components/icon-teaser-group/icon-teaser-group.scss +0 -10
- package/components/icon-teaser-group/u-icon-teaser-group.vue +0 -19
- package/utility/utility-text.js +0 -1
package/utils/dom/dom.js
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wrap an element with another element
|
|
3
|
+
*
|
|
4
|
+
* @param {Node} el
|
|
5
|
+
* @param {string} wrapper - Tag name of wrapper element. Can also have a classname (like emmet notation)
|
|
6
|
+
*
|
|
7
|
+
* @returns {Node}
|
|
8
|
+
*/
|
|
9
|
+
export const wrap = (el, wrapper) => {
|
|
10
|
+
const parsedWrapper = wrapper.split('.')
|
|
11
|
+
const wrapperEl = document.createElement(parsedWrapper[0])
|
|
12
|
+
|
|
13
|
+
if (parsedWrapper.length > 1) {
|
|
14
|
+
wrapperEl.className = parsedWrapper.slice(1).join(' ')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
el.parentNode.insertBefore(wrapperEl, el)
|
|
18
|
+
wrapperEl.appendChild(el)
|
|
19
|
+
|
|
20
|
+
return wrapperEl
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get element position relative to document.
|
|
25
|
+
*
|
|
26
|
+
* @param {Node} el
|
|
27
|
+
* @returns {{top: number, left: number, width: number, height: number}}
|
|
28
|
+
*/
|
|
29
|
+
export const getElementPosition = (el) => {
|
|
30
|
+
const elRect = el.getBoundingClientRect()
|
|
31
|
+
const scrollTop = window.scrollY
|
|
32
|
+
const scrollLeft = window.scrollX
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
top: elRect.top + scrollTop,
|
|
36
|
+
left: elRect.left + scrollLeft,
|
|
37
|
+
width: elRect.width,
|
|
38
|
+
height: elRect.height,
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Decode HTML encoded string.
|
|
44
|
+
*
|
|
45
|
+
* @param {string} str
|
|
46
|
+
* @returns {string}
|
|
47
|
+
*/
|
|
48
|
+
export const htmlDecode = (str) => {
|
|
49
|
+
const doc = new DOMParser().parseFromString(str, 'text/html')
|
|
50
|
+
return doc.documentElement.textContent
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const htmlToDocFragment = (str) => {
|
|
54
|
+
const tpl = document.createElement('template')
|
|
55
|
+
tpl.innerHTML = str
|
|
56
|
+
return tpl.content.cloneNode(true)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Reverse order of direct child nodes of given parent.
|
|
61
|
+
*
|
|
62
|
+
* @param {Node} parent
|
|
63
|
+
*/
|
|
64
|
+
export const reverseChildren = (parent) => {
|
|
65
|
+
for (let i = 1; i < parent.childNodes.length; i++) {
|
|
66
|
+
parent.insertBefore(parent.childNodes[i], parent.firstChild)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Check if element is in a slotted element.
|
|
72
|
+
*
|
|
73
|
+
* @param {Element} el
|
|
74
|
+
* @returns {boolean}
|
|
75
|
+
*/
|
|
76
|
+
const isInSlottedElement = (el) => {
|
|
77
|
+
const parentEl = el.parentElement
|
|
78
|
+
|
|
79
|
+
if (parentEl === document.body || !parentEl) {
|
|
80
|
+
return false
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (parentEl.assignedSlot) {
|
|
84
|
+
return true
|
|
85
|
+
} else {
|
|
86
|
+
return isInSlottedElement(parentEl)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
*
|
|
92
|
+
* @param {Element} el
|
|
93
|
+
* @returns {boolean}
|
|
94
|
+
*/
|
|
95
|
+
const isOffsetParent = (el) => {
|
|
96
|
+
const style = getComputedStyle(el)
|
|
97
|
+
return style.position === 'relative' || style.position === 'absolute'
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get the expected offsetParent within nested shadow roots.
|
|
102
|
+
*
|
|
103
|
+
* Because elements are nested in web components or slotted in web components we can't get desired offsetParent.
|
|
104
|
+
*
|
|
105
|
+
* @param {Element} el
|
|
106
|
+
* @returns {Element}
|
|
107
|
+
*/
|
|
108
|
+
export const getOffsetParent = (el) => {
|
|
109
|
+
if (el === document.body) {
|
|
110
|
+
// We arrived at the top.
|
|
111
|
+
// 'body' must be the offsetParent then.
|
|
112
|
+
return el
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const offsetParent = el.offsetParent
|
|
116
|
+
|
|
117
|
+
if (offsetParent === document.body || offsetParent === null) {
|
|
118
|
+
// It's possible that we're a slotted element, in which case we'll always have the potentially 'wrong' offsetParent 'body'.
|
|
119
|
+
// Dig deeper...
|
|
120
|
+
if (el.assignedSlot) {
|
|
121
|
+
// A <slot> doesn't have an offsetParent. Let's use the parentNode.
|
|
122
|
+
const parentElement = el.assignedSlot.parentElement
|
|
123
|
+
|
|
124
|
+
// Handle case where the parent node actually is an offsetParent
|
|
125
|
+
if (isOffsetParent(parentElement)) {
|
|
126
|
+
return parentElement
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return getOffsetParent(el.assignedSlot.parentElement)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (isInSlottedElement(el)) {
|
|
133
|
+
return getOffsetParent(el.parentElement)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (el.getRootNode() instanceof ShadowRoot) {
|
|
137
|
+
// If we're nested in another shadow root we'll also always get 'body' as offsetParent.
|
|
138
|
+
// Check the offsetParent of the current host element.
|
|
139
|
+
return getOffsetParent(el.getRootNode().host)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return offsetParent
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Get offset positions of parent which is not 'static'.
|
|
148
|
+
*
|
|
149
|
+
* @param {Element} el
|
|
150
|
+
* @returns {Object}
|
|
151
|
+
*/
|
|
152
|
+
export const getOffsetParentPosition = (el) => {
|
|
153
|
+
const offsetParent = getOffsetParent(el)
|
|
154
|
+
const elRect = el.getBoundingClientRect()
|
|
155
|
+
const offsetParentRect = offsetParent.getBoundingClientRect()
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
top: elRect.top - offsetParentRect.top,
|
|
159
|
+
left: elRect.left - offsetParentRect.left,
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export const moveChildren = (sourceParent, targetParent) => {
|
|
164
|
+
while (sourceParent.childNodes.length > 0) {
|
|
165
|
+
targetParent.appendChild(sourceParent.childNodes[0])
|
|
166
|
+
}
|
|
167
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { mediaquery } from '@energie360/design-tokens/design-tokens.json'
|
|
2
|
+
|
|
3
|
+
// TODO: return .matches value
|
|
4
|
+
|
|
5
|
+
export const isSmall = () => window.matchMedia(`(max-width: ${mediaquery.breakpoint.s})`)
|
|
6
|
+
|
|
7
|
+
export const isMedium = () => window.matchMedia(`(max-width: ${mediaquery.breakpoint.m})`)
|
|
8
|
+
|
|
9
|
+
export const isLarge = () => window.matchMedia(`(max-width: ${mediaquery.breakpoint.lg})`)
|
|
10
|
+
|
|
11
|
+
export const isXLarge = () => window.matchMedia(`(max-width: ${mediaquery.breakpoint.xl})`)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const debounce = (callback, wait = 200) => {
|
|
2
|
+
let timeoutId = null
|
|
3
|
+
|
|
4
|
+
return function (...args) {
|
|
5
|
+
clearTimeout(timeoutId)
|
|
6
|
+
timeoutId = setTimeout(() => {
|
|
7
|
+
callback.apply(this, args)
|
|
8
|
+
}, wait)
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const debounceRaf = function (fn) {
|
|
13
|
+
let rid
|
|
14
|
+
|
|
15
|
+
return (...args) => {
|
|
16
|
+
if (rid) {
|
|
17
|
+
return
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
rid = window.requestAnimationFrame(() => {
|
|
21
|
+
fn(...args)
|
|
22
|
+
rid = undefined
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
}
|
package/base-style.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import './base/main-base.scss'
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
@use '../../base/abstracts/' as a;
|
|
2
|
-
|
|
3
|
-
.icon-tesaer__content {
|
|
4
|
-
display: flex;
|
|
5
|
-
flex-direction: column;
|
|
6
|
-
row-gap: var(--e-space-2);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
.icon-teaser__image-wrapper {
|
|
10
|
-
margin: 0 auto var(--e-space-6);
|
|
11
|
-
display: flex;
|
|
12
|
-
align-items: center;
|
|
13
|
-
justify-content: center;
|
|
14
|
-
flex: 0 0 auto;
|
|
15
|
-
width: a.rem(120);
|
|
16
|
-
height: a.rem(120);
|
|
17
|
-
border-radius: 100%;
|
|
18
|
-
background-color: var(--e-c-primary-01-50);
|
|
19
|
-
|
|
20
|
-
@include a.bp(m) {
|
|
21
|
-
margin-bottom: var(--e-space-4);
|
|
22
|
-
width: a.rem(96);
|
|
23
|
-
height: a.rem(96);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
img {
|
|
27
|
-
width: a.rem(56);
|
|
28
|
-
height: a.rem(56);
|
|
29
|
-
|
|
30
|
-
@include a.bp(m) {
|
|
31
|
-
width: a.rem(38);
|
|
32
|
-
height: a.rem(38);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
.icon-teaser__title {
|
|
38
|
-
@include a.type(400, strong);
|
|
39
|
-
|
|
40
|
-
text-align: center;
|
|
41
|
-
|
|
42
|
-
@include a.bp(m) {
|
|
43
|
-
@include a.type(300, strong);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
.icon-teaser__description {
|
|
48
|
-
@include a.type(200);
|
|
49
|
-
|
|
50
|
-
margin-top: var(--e-space-3);
|
|
51
|
-
text-align: center;
|
|
52
|
-
|
|
53
|
-
@include a.bp(m) {
|
|
54
|
-
margin-top: var(--e-space-1);
|
|
55
|
-
|
|
56
|
-
@include a.type(100);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { Image } from '../../elements/types.ts'
|
|
3
|
-
|
|
4
|
-
export interface IconTeaser {
|
|
5
|
-
title?: string
|
|
6
|
-
description?: string
|
|
7
|
-
image?: Image
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
defineProps<IconTeaser>()
|
|
11
|
-
</script>
|
|
12
|
-
|
|
13
|
-
<template>
|
|
14
|
-
<div class="icon-teaser">
|
|
15
|
-
<div class="icon-teaser__image-wrapper">
|
|
16
|
-
<slot name="image">
|
|
17
|
-
<img aria-hidden="true" :src="image?.src" :alt="image?.alt" />
|
|
18
|
-
</slot>
|
|
19
|
-
</div>
|
|
20
|
-
|
|
21
|
-
<div class="icon-teaser__content">
|
|
22
|
-
<h2 class="icon-teaser__title">
|
|
23
|
-
<slot name="title">{{ title }}</slot>
|
|
24
|
-
</h2>
|
|
25
|
-
|
|
26
|
-
<p class="icon-teaser__description">
|
|
27
|
-
<slot name="description">{{ description }}</slot>
|
|
28
|
-
</p>
|
|
29
|
-
</div>
|
|
30
|
-
</div>
|
|
31
|
-
</template>
|
|
32
|
-
|
|
33
|
-
<style lang="scss">
|
|
34
|
-
@use './icon-teaser.scss';
|
|
35
|
-
</style>
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import UIconTeaser, { IconTeaser } from '../icon-teaser/u-icon-teaser.vue'
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
items?: IconTeaser[]
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
defineProps<Props>()
|
|
9
|
-
</script>
|
|
10
|
-
|
|
11
|
-
<template>
|
|
12
|
-
<div class="icon-teaser-group">
|
|
13
|
-
<slot><UIconTeaser v-for="(item, idx) in items" :key="idx" v-bind="item"></UIconTeaser></slot>
|
|
14
|
-
</div>
|
|
15
|
-
</template>
|
|
16
|
-
|
|
17
|
-
<style lang="scss">
|
|
18
|
-
@use './icon-teaser-group.scss';
|
|
19
|
-
</style>
|
package/utility/utility-text.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import '../elements/text-link/text-link.scss'
|