hr-design-system-handlebars 1.124.9 → 1.125.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 (23) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/assets/index.css +3 -3
  3. package/dist/assets/js/alpine.js +1 -0
  4. package/dist/assets/js/components/appBanner/appBanner.alpine.js +32 -23
  5. package/dist/assets/js/components/appBanner/nativeAppBanner.alpine.js +44 -0
  6. package/dist/assets/js/components/external-service/dataWrapperContentRefresher.subfeature.js +73 -65
  7. package/dist/assets/js/components/external-service/dataWrapperNoResponsiveIframe.subfeature.js +50 -72
  8. package/dist/assets/js/components/external-service/externalServiceDs.feature.js +119 -149
  9. package/dist/views/components/appBanner/nativeAppBanner.hbs +27 -0
  10. package/dist/views/components/external-service/external_service_with_datapolicy_check.hbs +1 -1
  11. package/dist/views_static/components/appBanner/nativeAppBanner.hbs +27 -0
  12. package/dist/views_static/components/external-service/external_service_with_datapolicy_check.hbs +1 -1
  13. package/package.json +1 -1
  14. package/src/assets/js/alpine.js +1 -0
  15. package/src/stories/views/components/appBanner/appBanner.alpine.js +32 -23
  16. package/src/stories/views/components/appBanner/appBanner.mdx +3 -4
  17. package/src/stories/views/components/appBanner/appBanner.stories.js +17 -6
  18. package/src/stories/views/components/appBanner/nativeAppBanner.alpine.js +44 -0
  19. package/src/stories/views/components/appBanner/nativeAppBanner.hbs +27 -0
  20. package/src/stories/views/components/external-service/dataWrapperContentRefresher.subfeature.js +73 -65
  21. package/src/stories/views/components/external-service/dataWrapperNoResponsiveIframe.subfeature.js +50 -72
  22. package/src/stories/views/components/external-service/externalServiceDs.feature.js +119 -149
  23. package/src/stories/views/components/external-service/external_service_with_datapolicy_check.hbs +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,27 @@
1
+ # v1.125.0 (Tue Dec 16 2025)
2
+
3
+ #### 🚀 Enhancement
4
+
5
+ - Recycle/external service js [#1330](https://github.com/mumprod/hr-design-system-handlebars/pull/1330) ([@szuelch](https://github.com/szuelch))
6
+
7
+ #### Authors: 1
8
+
9
+ - [@szuelch](https://github.com/szuelch)
10
+
11
+ ---
12
+
13
+ # v1.124.10 (Tue Dec 16 2025)
14
+
15
+ #### 🐛 Bug Fix
16
+
17
+ - Dpe 3046 b [#1329](https://github.com/mumprod/hr-design-system-handlebars/pull/1329) ([@vascoeduardo](https://github.com/vascoeduardo))
18
+
19
+ #### Authors: 1
20
+
21
+ - Vasco ([@vascoeduardo](https://github.com/vascoeduardo))
22
+
23
+ ---
24
+
1
25
  # v1.124.9 (Mon Dec 15 2025)
2
26
 
3
27
  #### 🐛 Bug Fix
@@ -3906,7 +3906,7 @@ article #commentList {
3906
3906
  border-bottom-color: var(--color-secondary-ds);
3907
3907
  }
3908
3908
  .counter-reset {
3909
- counter-reset: cnt1765814559948;
3909
+ counter-reset: cnt1765891425916;
3910
3910
  }
3911
3911
  .animate-delay-100 {
3912
3912
  --tw-animate-delay: 100ms;
@@ -4367,7 +4367,7 @@ html { scroll-behavior: smooth; }
4367
4367
  --tw-ring-color: rgba(255, 255, 255, 0.5);
4368
4368
  }
4369
4369
  .-ordered {
4370
- counter-increment: cnt1765814559948 1;
4370
+ counter-increment: cnt1765891425916 1;
4371
4371
  }
4372
4372
  .-ordered::before {
4373
4373
  position: absolute;
@@ -4385,7 +4385,7 @@ html { scroll-behavior: smooth; }
4385
4385
  --tw-text-opacity: 1;
4386
4386
  color: rgba(0, 0, 0, 1);
4387
4387
  color: rgba(0, 0, 0, var(--tw-text-opacity));
4388
- content: counter(cnt1765814559948);
4388
+ content: counter(cnt1765891425916);
4389
4389
  }
4390
4390
  /*! ****************************/
4391
4391
  /*! DataPolicy stuff */
@@ -14,6 +14,7 @@ import dropdown from 'components/site_header/dropdown.alpine'
14
14
  AsyncAlpine.init(Alpine)
15
15
  .data('podcastPlayer', () => import('components/podcast/podcast_player.alpine.js'))
16
16
  .data('appBanner', () => import('components/appBanner/appBanner.alpine.js'))
17
+ .data('nativeAppBanner', () => import('components/appBanner/nativeAppBanner.alpine.js'))
17
18
  .data('slider', () =>
18
19
  import('components/horizontal_scroll_container/horizontal_scroll_container.alpine.js')
19
20
  )
@@ -4,38 +4,47 @@ export default function appBanner() {
4
4
  return {
5
5
  showBanner: false,
6
6
  deferredPrompt: null,
7
+ isAndroid: /Android/i.test(navigator.userAgent),
8
+ packageId: "de.hr.hessenschau",
7
9
  init: function () {
8
- window.addEventListener('beforeinstallprompt', (e) => {
9
- // Prevent Chrome 67 and earlier from automatically showing the prompt
10
- e.preventDefault();
11
- // Stash the event so it can be triggered later.
12
- this.deferredPrompt = e;
13
- // Update UI notify the user they can add to home screen
10
+
11
+ if(this.isAndroid){
14
12
  this.showBanner = true;
15
- });
13
+ }
14
+
16
15
  if(window.IS_STORYBOOK){ this.showBanner = true;}
17
16
  },
18
17
  installClickHandler: function(){
19
- if(this.deferredPrompt){
20
- this.deferredPrompt.prompt();
21
- // Wait for the user to respond to the prompt
22
- this.deferredPrompt.userChoice
23
- .then((choiceResult) => {
24
- if (choiceResult.outcome === 'accepted') {
25
- uxAction('installNativeApp::promt::accepted');
26
- console.log('User accepted the A2HS prompt');
27
- } else {
28
- uxAction('installNativeApp::promt::dismissed');
29
- console.log('User dismissed the A2HS prompt');
30
- }
31
- this.deferredPrompt = null;
32
- });
33
- }
18
+ this.openPlayStore()
34
19
  this.showBanner = false
35
20
  },
36
21
  closeClickHandler: function(){
37
- uxAction('installNativeApp::bannerClosed');
22
+ uxAction('appBanner::bannerClosed');
38
23
  this.showBanner = false
24
+ },
25
+ openPlayStore: function() {
26
+ let fallbackTriggered = false;
27
+
28
+ const fallback = () => {
29
+ if (fallbackTriggered) return;
30
+ fallbackTriggered = true;
31
+
32
+ window.open(`https://play.google.com/store/apps/details?id=${this.packageId}`, "googlePlayStore");
33
+
34
+ };
35
+
36
+ document.addEventListener('visibilitychange', () => {
37
+ if (document.hidden) {
38
+ // App switch happened → cancel fallback
39
+ fallbackTriggered = true;
40
+ }
41
+ }, { once: true });
42
+
43
+ window.location.href =
44
+ `intent://details?id=${this.packageId}` +
45
+ `#Intent;scheme=market;package=com.android.vending;end`;
46
+
47
+ setTimeout(fallback, 700);
39
48
  }
40
49
  }
41
50
  }
@@ -0,0 +1,44 @@
1
+ import { uxAction } from 'base/tracking/pianoHelper.subfeature'
2
+
3
+ export default function nativeAppBanner() {
4
+ return {
5
+ showBanner: false,
6
+ deferredPrompt: null,
7
+ isAndroid: /Android/i.test(navigator.userAgent),
8
+ init: function () {
9
+ window.addEventListener('beforeinstallprompt', (e) => {
10
+ // Prevent Chrome 67 and earlier from automatically showing the prompt
11
+ e.preventDefault();
12
+ // Stash the event so it can be triggered later.
13
+ this.deferredPrompt = e;
14
+ // Update UI notify the user they can add to home screen
15
+ if(this.isAndroid){
16
+ this.showBanner = true;
17
+ }
18
+ });
19
+ if(window.IS_STORYBOOK){ this.showBanner = true;}
20
+ },
21
+ installClickHandler: function(){
22
+ if(this.deferredPrompt){
23
+ this.deferredPrompt.prompt();
24
+ // Wait for the user to respond to the prompt
25
+ this.deferredPrompt.userChoice
26
+ .then((choiceResult) => {
27
+ if (choiceResult.outcome === 'accepted') {
28
+ uxAction('nativeAppBanner::promt::accepted');
29
+ console.log('User accepted the A2HS prompt');
30
+ } else {
31
+ uxAction('nativeAppBanner::promt::dismissed');
32
+ console.log('User dismissed the A2HS prompt');
33
+ }
34
+ this.deferredPrompt = null;
35
+ });
36
+ }
37
+ this.showBanner = false
38
+ },
39
+ closeClickHandler: function(){
40
+ uxAction('nativeAppBanner::bannerClosed');
41
+ this.showBanner = false
42
+ }
43
+ }
44
+ }
@@ -1,88 +1,95 @@
1
-
2
- const DataWrapperContentRefresher = function (context, id, refreshIntervall, webcomponent, datapolicy) {
3
- const { element: rootElement } = context
1
+ const DataWrapperContentRefresher = function ({
2
+ rootElement,
3
+ id,
4
+ refreshIntervall,
5
+ isWebcomponent,
6
+ datapolicy,
7
+ }) {
4
8
  let remainingTime
5
9
  let timer
6
- let uniqueID = id
7
10
  let intervall = refreshIntervall
8
11
  let container
9
- let script
12
+ let script
10
13
  let iframeRefresh
11
-
12
- if (webcomponent) {
13
- container = document.getElementById('datawrapper-chart-' + uniqueID)
14
- script = document.getElementById('datawrapper-component-js')
15
- }
16
- else{
17
- iframeRefresh = document.getElementById('datawrapper-chart-' + uniqueID)
14
+
15
+ if (isWebcomponent) {
16
+ container = document.getElementById(`datawrapper-chart-${id}`)
17
+ script = document.getElementById('datawrapper-component-js')
18
+ } else {
19
+ iframeRefresh = document.getElementById(`datawrapper-chart-${id}`)
18
20
  }
19
-
21
+
20
22
  const createRefresher = function () {
21
- console.log("Refresher bauen")
22
- let divCounter = document.createElement('div')
23
+ console.log('Refresher bauen')
24
+ const divCounter = document.createElement('div')
25
+ divCounter.id = 'counter' + id
26
+ Object.assign(divCounter.style, {
27
+ backgroundColor: '#006dc1',
28
+ color: '#fff',
29
+ fontSize: '12px',
30
+ padding: '8px',
31
+ borderRadius: '0 0 4px 4px',
32
+ })
33
+
23
34
  let divOverlay = document.createElement('div')
35
+ divOverlay.id = 'overlay' + id
36
+ Object.assign(divOverlay.style, {
37
+ position: 'absolute',
38
+ top: '0',
39
+ display: 'none',
40
+ alignItems: 'center',
41
+ justifyContent: 'center',
42
+ backgroundColor: '#d8e9f6',
43
+ width: '100%',
44
+ height: 'calc(100% - 36px)',
45
+ })
46
+
24
47
  let divTextOverlay = document.createElement('div')
25
- divOverlay.id = 'overlay' + uniqueID
26
- divOverlay.style.position = 'absolute'
27
- divOverlay.style.top = '0'
28
- divOverlay.style.display = 'none'
29
- divOverlay.style.alignItems = 'center'
30
- divOverlay.style.justifyContent = 'center'
31
- divOverlay.style.backgroundColor = '#fff'
32
- divOverlay.style.width = '100%'
33
- divOverlay.style.height = 'calc(100% - 36px)'
34
- divOverlay.style.backgroundColor = '#d8e9f6'
35
48
  divTextOverlay.innerHTML = 'Lade Inhalt neu...'
36
- divTextOverlay.style.backgroundColor = '#005293'
37
- divTextOverlay.style.padding = '8px'
38
- divTextOverlay.style.color = '#fff'
39
- divTextOverlay.style.fontWeight = '800'
40
- divTextOverlay.style.fontFamily = 'RobotoSlab'
41
- divTextOverlay.style.borderRadius = '6px 6px 6px 6px'
49
+ Object.assign(divTextOverlay.style, {
50
+ backgroundColor: '#005293',
51
+ padding: '8px',
52
+ color: '#fff',
53
+ fontWeight: '800',
54
+ fontFamily: 'RobotoSlab',
55
+ borderRadius: '6px',
56
+ })
57
+
42
58
  divOverlay.appendChild(divTextOverlay)
43
- divCounter.id = 'counter' + uniqueID
44
- divCounter.style.backgroundColor = '#006dc1'
45
- divCounter.style.color = '#fff'
46
- divCounter.style.fontSize = '12px'
47
- divCounter.style.padding = '8px'
48
- divCounter.style.borderRadius = '0 0 4px 4px'
49
-
59
+
50
60
  rootElement.style.position = 'relative'
51
- if(!datapolicy) {
52
- rootElement.appendChild(divCounter)
53
- rootElement.appendChild(divOverlay)
54
- startCountdown()
55
- }
56
- else {
57
- rootElement.removeChild(divCounter)
58
- rootElement.removeChild(divOverlay)
59
- stopCountdown()
61
+
62
+ if (!datapolicy) {
63
+ rootElement.appendChild(divCounter)
64
+ rootElement.appendChild(divOverlay)
65
+ startCountdown()
66
+ } else {
67
+ rootElement.removeChild(divCounter)
68
+ rootElement.removeChild(divOverlay)
69
+ stopCountdown()
60
70
  }
61
71
  }
62
72
 
63
73
  const refreshIframe = function () {
64
74
  console.log('Reload')
65
- if(webcomponent) {
75
+ if (isWebcomponent) {
66
76
  container.style.opacity = '0'
67
77
  script.src = script.src.split('?')[0] + '?_=' + new Date().getTime()
68
- }
69
- else{
78
+ } else {
70
79
  iframeRefresh.style.opacity = '0'
71
- iframeRefresh.src =
72
- iframeRefresh.src.split('?')[0] + '?_=' + new Date().getTime()
80
+ iframeRefresh.src = iframeRefresh.src.split('?')[0] + '?_=' + new Date().getTime()
73
81
  }
74
82
  clearInterval(timer)
75
83
  }
76
84
  const startCountdown = function () {
77
85
  remainingTime = Number(intervall)
78
86
  setTimeout(function () {
79
- if(webcomponent) {
80
- container.style.opacity = '1'
81
- }
82
- else{
87
+ if (isWebcomponent) {
88
+ container.style.opacity = '1'
89
+ } else {
83
90
  iframeRefresh.style.opacity = '1'
84
91
  }
85
- document.getElementById('overlay' + uniqueID).style.display = 'none'
92
+ document.getElementById('overlay' + id).style.display = 'none'
86
93
  }, 1000)
87
94
  timer = setInterval(function () {
88
95
  checkTimer()
@@ -92,33 +99,34 @@ const DataWrapperContentRefresher = function (context, id, refreshIntervall, web
92
99
  clearInterval(timer)
93
100
  }
94
101
  const checkTimer = function () {
95
- if(document.getElementById('counter' + uniqueID) !== null) {
102
+ if (document.getElementById('counter' + id) !== null) {
96
103
  if (remainingTime >= 0) {
97
- document.getElementById('counter' + uniqueID).innerHTML =
104
+ document.getElementById('counter' + id).innerHTML =
98
105
  'Dieser Inhalt wird automatisch aktualisiert in ' +
99
106
  secondsToTimeString(remainingTime) +
100
107
  ' Min.'
101
108
  remainingTime -= 1
102
109
  if (remainingTime == -1) {
103
- document.getElementById('overlay' + uniqueID).style.display = 'flex'
104
- document.getElementById('counter' + uniqueID).innerHTML =
110
+ document.getElementById('overlay' + id).style.display = 'flex'
111
+ document.getElementById('counter' + id).innerHTML =
105
112
  'Zeitintervall wird neu gestartet...'
106
113
  }
107
114
  } else {
108
115
  refreshIframe()
109
116
  startCountdown()
110
117
  }
111
- }else{
112
- console.log("Element wurde entfernt")
118
+ } else {
119
+ console.log('Element wurde entfernt')
113
120
  clearInterval(timer)
114
121
  }
115
122
  }
123
+
116
124
  const secondsToTimeString = function (seconds) {
117
125
  return new Date(seconds * 1000).toISOString().substr(14, 5)
118
126
  }
119
127
  return {
120
- createRefresher: createRefresher
128
+ createRefresher: createRefresher,
121
129
  }
122
130
  }
123
131
 
124
- export default DataWrapperContentRefresher
132
+ export default DataWrapperContentRefresher
@@ -1,83 +1,61 @@
1
- const DataWrapperNoResponsiveIframe = function (context, configAR, configFixedHeight, id, embedCode, lazyLoad) {
2
-
3
- const { element: rootElement } = context
4
- let aspectRatio = configAR
5
- let fixedHeight = configFixedHeight
6
- let uniqueId = id
7
-
1
+ const DataWrapperNoResponsiveIframe = function ({
2
+ rootElement,
3
+ aspectRatio,
4
+ fixedHeight,
5
+ id,
6
+ embedCode,
7
+ lazyLoad,
8
+ }) {
8
9
  const createNoResponsiveIframe = function () {
9
-
10
-
11
- var parentDiv = document.createElement('div')
12
- //Auflösen nach Tailwind-Klassen //copytext__scrollWrapper
13
- parentDiv.className = '!h-full'
14
- var div = document.createElement('div')
15
- //Keine Aspect-Ratio ausgewählt aber eine feste Höhe
16
-
17
- console.log(aspectRatio)
18
- console.log(configAR)
19
- if (aspectRatio === undefined) {
10
+ const parentDiv = document.createElement('div')
11
+ //Auflösen nach Tailwind-Klassen //copytext__scrollWrapper
12
+ parentDiv.className = '!h-full'
13
+ const div = document.createElement('div')
14
+ //Keine Aspect-Ratio ausgewählt aber eine feste Höhe
15
+ if (aspectRatio === undefined) {
20
16
  //Auflösen nach Tailwind-Klassen //noaspect_datawrapper_cdn
21
17
  div.className = 'relative overflow-hidden w-0 border-0 !min-w-full'
22
18
  div.style.height = fixedHeight + 'px'
23
19
  div.style.width = '100%'
24
- }
25
- // Aspect-Ratio ausgewählt
26
- else {
27
- //ar-- in Tailwind-Klassen
28
- let tailwindCSS
29
- switch(aspectRatio){
30
- case '100':
31
- tailwindCSS = "ar-1-1"
32
- break;
33
- case '16x9':
34
- tailwindCSS = "ar-16-9"
35
- break;
36
- case '9x16':
37
- tailwindCSS = "ar-9-16"
38
- break;
39
- case '16x7':
40
- tailwindCSS = "ar-16-7"
41
- break;
42
- case '7x16':
43
- tailwindCSS = "ar-7-16"
44
- break;
45
- case '4x3':
46
- tailwindCSS = "ar-4-3"
47
- break;
48
- case '100x27':
49
- tailwindCSS = "ar-100-27"
50
- break;
51
- default:
52
- tailwindCSS = "ar-16-9"
53
- }
54
-
55
- div.className = tailwindCSS + " w-full sm480:h-full h-[560px]"
56
- }
57
- var iframe = document.createElement('iframe')
20
+ }
21
+ // Aspect-Ratio ausgewählt
22
+ else {
23
+ //ar-- in Tailwind-Klassen
24
+ const aspectRatiosToCssClasses = {
25
+ '100': 'ar-1-1',
26
+ '16x9': 'ar-16-9',
27
+ '9x16': 'ar-9-16',
28
+ '16x7': 'ar-16-7',
29
+ '7x16': 'ar-7-16',
30
+ '4x3': 'ar-4-3',
31
+ '100x27': 'ar-100-27',
32
+ }
33
+ const tailwindCSS = aspectRatiosToCssClasses[aspectRatio] || 'ar-16-9'
34
+ div.className = `${tailwindCSS} w-full sm480:h-full h-[560px]`
35
+ }
36
+ var iframe = document.createElement('iframe')
58
37
 
59
- //Auflösen nach Tailwind-Klassen //ar_iframe datawrapper_cdn
60
- iframe.setAttribute('class', 'border-0 top-0 left-0 w-full h-full overflow-y-hidden')
61
- iframe.setAttribute('id', 'i_frame')
62
- iframe.setAttribute('data-isloaded', '0')
63
- iframe.setAttribute('webkitallowfullscreen', '')
64
- iframe.setAttribute('mozallowfullscreen', '')
65
- iframe.setAttribute('allowfullscreen', '')
66
- iframe.setAttribute('scrolling', 'no')
67
- iframe.setAttribute('frameborder', '0')
68
- iframe.src = embedCode
69
- iframe.id = 'datawrapper-chart-' + uniqueId
70
- if (lazyLoad) {
71
- iframe.loading = "lazy";
72
- }
73
-
74
- div.appendChild(iframe)
75
- parentDiv.appendChild(div)
76
- rootElement.appendChild(parentDiv)
38
+ //Auflösen nach Tailwind-Klassen //ar_iframe datawrapper_cdn
39
+ iframe.className = 'border-0 top-0 left-0 w-full h-full overflow-y-hidden'
40
+ iframe.id = 'datawrapper-chart-' + id
41
+ iframe.setAttribute('data-isloaded', '0')
42
+ iframe.setAttribute('webkitallowfullscreen', '')
43
+ iframe.setAttribute('mozallowfullscreen', '')
44
+ iframe.setAttribute('allowfullscreen', '')
45
+ iframe.setAttribute('scrolling', 'no')
46
+ iframe.setAttribute('frameborder', '0')
47
+ iframe.src = embedCode
48
+ if (lazyLoad) {
49
+ iframe.loading = 'lazy'
50
+ }
51
+
52
+ div.appendChild(iframe)
53
+ parentDiv.appendChild(div)
54
+ rootElement.appendChild(parentDiv)
77
55
  }
78
56
  return {
79
- createNoResponsiveIframe: createNoResponsiveIframe
57
+ createNoResponsiveIframe: createNoResponsiveIframe,
80
58
  }
81
59
  }
82
60
 
83
- export default DataWrapperNoResponsiveIframe
61
+ export default DataWrapperNoResponsiveIframe