@ilo-org/twig 1.9.0 → 1.11.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.
- package/README.md +0 -1
- package/dist/components/accordion/accordion.behavior.js +1 -3
- package/dist/components/audioplayer/audioplayer.behavior.js +10 -0
- package/dist/components/audioplayer/audioplayer.component.yml +34 -0
- package/dist/components/audioplayer/audioplayer.twig +103 -0
- package/dist/components/audioplayer/audioplayer.wingsuit.yml +34 -0
- package/dist/components/breadcrumb/breadcrumb.behavior.js +1 -3
- package/dist/components/callout/callout.behavior.js +1 -3
- package/dist/components/fileupload/fileupload.behavior.js +1 -3
- package/dist/components/icon/icon.behavior.js +830 -620
- package/dist/components/linklist/linklist.component.yml +11 -0
- package/dist/components/linklist/linklist.twig +3 -1
- package/dist/components/linklist/linklist.wingsuit.yml +11 -0
- package/dist/components/list/list.component.yml +11 -0
- package/dist/components/list/list.twig +2 -1
- package/dist/components/list/list.wingsuit.yml +11 -0
- package/dist/components/loading/loading.behavior.js +1 -3
- package/dist/components/localnav/localnav.behavior.js +1 -3
- package/dist/components/modal/modal.behavior.js +1 -3
- package/dist/components/nav/desktop/navmenu.twig +2 -3
- package/dist/components/nav/desktop/navsearch.twig +24 -0
- package/dist/components/nav/mobile/mobiledrawer_main.twig +27 -8
- package/dist/components/nav/nav.behavior.js +1 -1
- package/dist/components/nav/nav.component.yml +63 -4
- package/dist/components/nav/nav.twig +3 -1
- package/dist/components/nav/nav.wingsuit.yml +63 -4
- package/dist/components/nav/nav_compact.twig +2 -1
- package/dist/components/nav/nav_complex.twig +2 -2
- package/dist/components/nav/nav_main.twig +135 -0
- package/dist/components/navigation/navigation.behavior.js +1 -3
- package/dist/components/notification/notification.behavior.js +1 -3
- package/dist/components/photogallery/lightbox.twig +28 -0
- package/dist/components/photogallery/lightboxgallery.twig +71 -0
- package/dist/components/photogallery/photogallery.behavior.js +12 -0
- package/dist/components/photogallery/photogallery.component.yml +111 -0
- package/dist/components/photogallery/photogallery.twig +69 -0
- package/dist/components/photogallery/photogallery.wingsuit.yml +111 -0
- package/dist/components/photogallery/photogallery_controls.twig +20 -0
- package/dist/components/photogallery/photogallery_thumbnails.twig +20 -0
- package/dist/components/readmore/readmore.behavior.js +1 -3
- package/dist/components/search/search.behavior.js +1 -3
- package/dist/components/socialmedia/socialmedia.component.yml +20 -0
- package/dist/components/socialmedia/socialmedia.twig +3 -1
- package/dist/components/socialmedia/socialmedia.wingsuit.yml +20 -0
- package/dist/components/table/table.behavior.js +1 -3
- package/dist/components/tableofcontents/tableofcontents.behavior.js +1 -3
- package/dist/components/tabs/tabs.behavior.js +1 -3
- package/dist/styles/components/accordion.css +1 -1
- package/dist/styles/components/audioplayer.css +1 -0
- package/dist/styles/components/blockquote.css +1 -1
- package/dist/styles/components/breadcrumb.css +1 -1
- package/dist/styles/components/button.css +1 -1
- package/dist/styles/components/callout.css +1 -1
- package/dist/styles/components/card.css +1 -1
- package/dist/styles/components/cardgroup.css +1 -1
- package/dist/styles/components/checkbox.css +1 -1
- package/dist/styles/components/container.css +1 -1
- package/dist/styles/components/contextmenu.css +1 -1
- package/dist/styles/components/datacard.css +1 -1
- package/dist/styles/components/datepicker.css +1 -1
- package/dist/styles/components/detailcard.css +1 -1
- package/dist/styles/components/dropdown.css +1 -1
- package/dist/styles/components/empty.css +1 -1
- package/dist/styles/components/factlistcard.css +1 -1
- package/dist/styles/components/featurecard.css +1 -1
- package/dist/styles/components/fieldset.css +1 -1
- package/dist/styles/components/file-upload.css +1 -1
- package/dist/styles/components/footer.css +1 -1
- package/dist/styles/components/form.css +1 -1
- package/dist/styles/components/formcontrol.css +1 -1
- package/dist/styles/components/hero.css +1 -1
- package/dist/styles/components/herocard.css +1 -1
- package/dist/styles/components/image.css +1 -1
- package/dist/styles/components/input.css +1 -1
- package/dist/styles/components/languagetoggle.css +1 -1
- package/dist/styles/components/link.css +1 -1
- package/dist/styles/components/linklist.css +1 -1
- package/dist/styles/components/list.css +1 -1
- package/dist/styles/components/loading.css +1 -1
- package/dist/styles/components/logogrid.css +1 -1
- package/dist/styles/components/modal.css +1 -1
- package/dist/styles/components/multilinkcard.css +1 -1
- package/dist/styles/components/navigation.css +1 -1
- package/dist/styles/components/notification.css +1 -1
- package/dist/styles/components/pagination.css +1 -1
- package/dist/styles/components/profile.css +1 -1
- package/dist/styles/components/promocard.css +1 -1
- package/dist/styles/components/radio.css +1 -1
- package/dist/styles/components/readmore.css +1 -1
- package/dist/styles/components/richtext.css +1 -1
- package/dist/styles/components/scorecard.css +1 -1
- package/dist/styles/components/searchfield.css +1 -1
- package/dist/styles/components/socialmedia.css +1 -1
- package/dist/styles/components/statcard.css +1 -1
- package/dist/styles/components/status.css +1 -1
- package/dist/styles/components/table.css +1 -1
- package/dist/styles/components/tableofcontents.css +1 -1
- package/dist/styles/components/tabs.css +1 -1
- package/dist/styles/components/tag.css +1 -1
- package/dist/styles/components/textarea.css +1 -1
- package/dist/styles/components/textcard.css +1 -1
- package/dist/styles/components/textinput.css +1 -1
- package/dist/styles/components/toggle.css +1 -1
- package/dist/styles/components/tooltip.css +1 -1
- package/dist/styles/components/video.css +1 -1
- package/dist/styles/global.css +1 -1
- package/dist/styles/global.css.map +1 -1
- package/dist/styles/index.css +3 -3
- package/dist/styles/index.css.map +1 -1
- package/dist/styles/monorepo.css +3 -3
- package/dist/styles/monorepo.css.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -5,7 +5,6 @@ This package provides the implementation of the Design System using [Twig](https
|
|
|
5
5
|
- [@ilo-org/themes](./packages/themes)
|
|
6
6
|
- [@ilo-org/fonts](./packages/fonts)
|
|
7
7
|
- [@ilo-org/styles](./packages/styles)
|
|
8
|
-
- [@ilo-org/utils](./packages/utils)
|
|
9
8
|
- [@ilo-org/icons](./packages/icons)
|
|
10
9
|
|
|
11
10
|
## Drupal Integration
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
const FOCUSABLE_SELECTORS=["a","button","input","select","textarea","[tabindex]:not([tabindex='-1'])"];class Accordion{constructor(element){this.element=element;this.multipleExpanded=false;this.init();}init(){this.cacheDomReferences().setupHandlers().enable();return this}cacheDomReferences(){this.accordionItems=this.element.querySelectorAll(".ilo--accordion--item");this.multipleExpanded=this.element.hasAttribute("data-multipleexpanded");this.accordionPanels=this.element.querySelectorAll(".ilo--accordion--panel");this.accordionButtons=this.element.querySelectorAll(".ilo--accordion--button");return this}setupHandlers(){this.collapseSection=this.collapseSection.bind(this);this.expandSection=this.expandSection.bind(this);this.onClick=this.onClick.bind(this);this.updateAccordionItems=this.updateAccordionItems.bind(this);return this}enable(){if(this.accordionButtons.length>0){this.accordionButtons.forEach(button=>{button.addEventListener(d.CLICK,e=>this.onClick(e));});}if(this.accordionPanels.length>0){this.accordionPanels.forEach(panel=>{this.handleTabIndex(panel,"REMOVE");});}return this}onClick(e){this.updateAccordionItems(e.target);return this}updateAccordionItems(panelbutton){const panel=panelbutton.closest(".ilo--accordion--item").querySelector(".ilo--accordion--panel");const isopen=panel.classList.contains("ilo--accordion--panel__open");if(!this.multipleExpanded){this.accordionPanels.forEach(item=>{if(panel!==item){this.collapseSection(item);}});}if(!isopen){this.expandSection(panel);}else {this.collapseSection(panel);}panelbutton.blur();return this}collapseSection(element){element.classList.remove("ilo--accordion--panel__open");element.parentElement.querySelector(".ilo--accordion--button").setAttribute(t.EXPANDED,"false");element.setAttribute(t.HIDDEN,"true");this.handleTabIndex(element,"REMOVE");}expandSection(element){element.parentElement.querySelector(".ilo--accordion--button").setAttribute(t.EXPANDED,"true");element.setAttribute(t.HIDDEN,"false");element.classList.add("ilo--accordion--panel__open");this.handleTabIndex(element,"ADD");}handleTabIndex(element,mode){element.querySelectorAll(FOCUSABLE_SELECTORS.join(", ")).forEach(item=>{if(mode==="ADD"){item.removeAttribute("tabindex");return}item.setAttribute("tabindex","-1");});}}
|
|
4
|
+
const FOCUSABLE_SELECTORS=["a","button","input","select","textarea","[tabindex]:not([tabindex='-1'])"];class Accordion{constructor(element){this.element=element;this.multipleExpanded=false;this.init();}init(){this.cacheDomReferences().setupHandlers().enable();return this}cacheDomReferences(){this.accordionItems=this.element.querySelectorAll(".ilo--accordion--item");this.multipleExpanded=this.element.hasAttribute("data-multipleexpanded");this.accordionPanels=this.element.querySelectorAll(".ilo--accordion--panel");this.accordionButtons=this.element.querySelectorAll(".ilo--accordion--button");return this}setupHandlers(){this.collapseSection=this.collapseSection.bind(this);this.expandSection=this.expandSection.bind(this);this.onClick=this.onClick.bind(this);this.updateAccordionItems=this.updateAccordionItems.bind(this);return this}enable(){if(this.accordionButtons.length>0){this.accordionButtons.forEach(button=>{button.addEventListener("click",e=>this.onClick(e));});}if(this.accordionPanels.length>0){this.accordionPanels.forEach(panel=>{this.handleTabIndex(panel,"REMOVE");});}return this}onClick(e){this.updateAccordionItems(e.target);return this}updateAccordionItems(panelbutton){const panel=panelbutton.closest(".ilo--accordion--item").querySelector(".ilo--accordion--panel");const isopen=panel.classList.contains("ilo--accordion--panel__open");if(!this.multipleExpanded){this.accordionPanels.forEach(item=>{if(panel!==item){this.collapseSection(item);}});}if(!isopen){this.expandSection(panel);}else {this.collapseSection(panel);}panelbutton.blur();return this}collapseSection(element){element.classList.remove("ilo--accordion--panel__open");element.parentElement.querySelector(".ilo--accordion--button").setAttribute("aria-expanded","false");element.setAttribute("aria-hidden","true");this.handleTabIndex(element,"REMOVE");}expandSection(element){element.parentElement.querySelector(".ilo--accordion--button").setAttribute("aria-expanded","true");element.setAttribute("aria-hidden","false");element.classList.add("ilo--accordion--panel__open");this.handleTabIndex(element,"ADD");}handleTabIndex(element,mode){element.querySelectorAll(FOCUSABLE_SELECTORS.join(", ")).forEach(item=>{if(mode==="ADD"){item.removeAttribute("tabindex");return}item.setAttribute("tabindex","-1");});}}
|
|
7
5
|
|
|
8
6
|
Drupal.behaviors.accordion={attach(){Array.prototype.forEach.call(document.querySelectorAll(`[data-loadcomponent="Accordion"]`),element=>{if(!element.dataset.jsProcessed){new Accordion(element);element.dataset.jsProcessed=true;}});}};
|
|
9
7
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
class StatefulComponent{constructor(element,initialState={}){this.element=element;this.initialState=initialState;this.state=this.#setupState(this.initialState);this.stateHandlers=new Map;this.#init();}#init(){this.setupState=this.#setupState.bind(this);this.registerStateHandler=this.registerStateHandler.bind(this);}registerStateHandler(prop,handler){if(!this.stateHandlers.has(prop)){this.stateHandlers.set(prop,[]);}this.stateHandlers.get(prop).push(handler);}#setupState(initialState){if(initialState===void 0)initialState={};return new Proxy(initialState,{set:(target,prop,value)=>{if(value!==target[prop]){target[prop]=value;const handlers=this.stateHandlers.get(prop);if(handlers){handlers.forEach(handler=>handler(value,prop));}}return true}})}}
|
|
5
|
+
|
|
6
|
+
const getTimeString=time=>{const minutes=Math.floor(time/60).toString().padStart(2,"0");const seconds=Math.floor(time%60).toString().padStart(2,"0");return `${minutes}:${seconds}`};const getProgressPercentage=(currentTime,totalTime)=>{if(totalTime===0)return 0;return currentTime/totalTime*100};class AudioPlayer extends StatefulComponent{constructor(element){const initialState={currentTime:0,totalTime:0,playing:false,volume:1};super(element,initialState);this.prefix=this.element.dataset.prefix;this.init();}init(){this.cacheDomReferences().bindEventHandlers().registerStateHandlers();return this}cacheDomReferences(){this.audio=this.element.querySelector(`.${this.prefix}--audio-player--audio`);this.playButton=this.element.querySelector(`.${this.prefix}--audio-player--play-button`);this.skipBackwardButton=this.element.querySelector(`.${this.prefix}--audio-player--skip-backward`);this.skipForwardButton=this.element.querySelector(`.${this.prefix}--audio-player--skip-forward`);this.progressBar=this.element.querySelector(`.${this.prefix}--audio-player--progress-bar`);this.progressComplete=this.element.querySelector(`.${this.prefix}--audio-player--progress-complete`);this.volumeButton=this.element.querySelector(`.${this.prefix}--audio-player--volume-icon`);this.volumeSlider=this.element.querySelector(`.${this.prefix}--audio-player--volume-slider`);this.currentTimeDisplay=this.element.querySelector(`.${this.prefix}--audio-player--duration-played`);this.totalTimeDisplay=this.element.querySelector(`.${this.prefix}--audio-player--duration-total`);this.playIcon=this.element.querySelector(`.${this.prefix}--audio-player--play-icon`);return this}bindEventHandlers(){this.audio.addEventListener("loadedmetadata",()=>{this.state.totalTime=this.audio.duration;});this.audio.addEventListener("timeupdate",()=>{this.state.currentTime=this.audio.currentTime;});this.audio.addEventListener("play",()=>{this.state.playing=true;});this.audio.addEventListener("pause",()=>{this.state.playing=false;});this.audio.addEventListener("ended",()=>{this.state.playing=false;});this.playButton.addEventListener("click",()=>{this.state.playing=!this.state.playing;});this.skipBackwardButton.addEventListener("click",()=>{this.audio.currentTime=Math.max(this.audio.currentTime-15,0);});this.skipForwardButton.addEventListener("click",()=>{this.audio.currentTime=Math.min(this.audio.currentTime+15,this.state.totalTime);});this.volumeButton.addEventListener("click",()=>{if(this.state.volume===0){this.state.volume=1;}else {this.state.volume=0;}});this.volumeSlider.addEventListener("input",event=>{const newVolume=Number(event.target.value)/100;this.state.volume=newVolume;});this.progressBar.addEventListener("click",event=>{const rect=this.progressBar.getBoundingClientRect();const clickX=event.clientX-rect.left;const newTime=clickX/rect.width*this.state.totalTime;this.audio.currentTime=newTime;});return this}registerStateHandlers(){this.registerStateHandler("currentTime",currentTime=>{this.progressComplete.style.setProperty("--progress",`${getProgressPercentage(currentTime,this.state.totalTime)}%`);this.progressBar.setAttribute("aria-valuenow",Math.floor(currentTime));this.currentTimeDisplay.textContent=getTimeString(currentTime);});this.registerStateHandler("totalTime",totalTime=>{this.progressBar.setAttribute("aria-valuemax",Math.floor(totalTime));this.totalTimeDisplay.textContent=getTimeString(totalTime);});this.registerStateHandler("playing",playing=>{if(playing){this.audio.play();}else {this.audio.pause();}this.playButton.setAttribute("aria-label",playing?"Pause":"Play");});this.registerStateHandler("volume",volume=>{this.audio.volume=volume;this.volumeSlider.value=volume*100;this.volumeSlider.style.setProperty("--progress",`${volume*100}%`);this.volumeButton.setAttribute("aria-label",volume===0?"Unmute":"Mute");});return this}}
|
|
7
|
+
|
|
8
|
+
Drupal.behaviors.audioplayer={attach(){Array.prototype.forEach.call(document.querySelectorAll(`[data-loadcomponent="AudioPlayer"]`),element=>{if(!element.dataset.jsProcessed){new AudioPlayer(element);element.dataset.jsProcessed=true;}});}};
|
|
9
|
+
|
|
10
|
+
})();
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
audioplayer:
|
|
2
|
+
namespace: Components/Media
|
|
3
|
+
use: "@components/audioplayer/audioplayer.twig"
|
|
4
|
+
label: Audio Player
|
|
5
|
+
description: A component for playing audio files.
|
|
6
|
+
visibility: storybook
|
|
7
|
+
fields:
|
|
8
|
+
src:
|
|
9
|
+
type: string
|
|
10
|
+
label: Audio source
|
|
11
|
+
description: Path to the audio file
|
|
12
|
+
required: true
|
|
13
|
+
preview: "/audio/audio-example.mp3"
|
|
14
|
+
name:
|
|
15
|
+
type: string
|
|
16
|
+
label: Track name
|
|
17
|
+
description: The name of the audio track
|
|
18
|
+
required: true
|
|
19
|
+
preview: "Sample Track"
|
|
20
|
+
programme:
|
|
21
|
+
type: string
|
|
22
|
+
label: Programme
|
|
23
|
+
description: The name of the programme
|
|
24
|
+
required: true
|
|
25
|
+
preview: "Sample Programme"
|
|
26
|
+
creator:
|
|
27
|
+
type: string
|
|
28
|
+
label: Creator
|
|
29
|
+
description: The name of the creator
|
|
30
|
+
required: true
|
|
31
|
+
preview: "Sample Creator"
|
|
32
|
+
variants:
|
|
33
|
+
default:
|
|
34
|
+
label: Default
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
{% set prefix = prefix|default('ilo') %}
|
|
2
|
+
{% set base_class = 'ilo' ~ "--audio-player" %}
|
|
3
|
+
|
|
4
|
+
<div class="{{base_class}}" data-loadcomponent="AudioPlayer" data-prefix="ilo">
|
|
5
|
+
<div
|
|
6
|
+
role="progressbar"
|
|
7
|
+
tabindex="-1"
|
|
8
|
+
aria-valuenow="0"
|
|
9
|
+
aria-valuemin="0"
|
|
10
|
+
aria-valuemax="100"
|
|
11
|
+
class="{{base_class}}--progress-bar"
|
|
12
|
+
>
|
|
13
|
+
<div
|
|
14
|
+
class="{{base_class}}--progress-complete"
|
|
15
|
+
>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="{{base_class}}--body">
|
|
19
|
+
<div class="{{base_class}}--left">
|
|
20
|
+
<p class="{{base_class}}--track-name">{{ name }}</p>
|
|
21
|
+
<div class="{{base_class}}--track-details">
|
|
22
|
+
<span class="{{base_class}}--track-programme">{{ programme }}</span>
|
|
23
|
+
<span class="{{base_class}}--track-creator">{{ creator }}</span>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
<div class="{{base_class}}--center">
|
|
27
|
+
<button
|
|
28
|
+
class="{{base_class}}--skip-button {{base_class}}--skip-backward"
|
|
29
|
+
aria-label="Rewind 15 seconds"
|
|
30
|
+
>
|
|
31
|
+
{% include "@components/icon/icon.twig" with {
|
|
32
|
+
name: "skip_backward15",
|
|
33
|
+
size: 24,
|
|
34
|
+
prefix: prefix
|
|
35
|
+
} only %}
|
|
36
|
+
</button>
|
|
37
|
+
<button
|
|
38
|
+
class="{{base_class}}--play-button"
|
|
39
|
+
aria-label="Play"
|
|
40
|
+
>
|
|
41
|
+
{% include "@components/icon/icon.twig" with {
|
|
42
|
+
name: "triangle_right",
|
|
43
|
+
size: 32,
|
|
44
|
+
class: base_class ~ "--play-icon",
|
|
45
|
+
prefix: prefix
|
|
46
|
+
} only %}
|
|
47
|
+
{% include "@components/icon/icon.twig" with {
|
|
48
|
+
name: "pause",
|
|
49
|
+
size: 32,
|
|
50
|
+
class: base_class ~ "--pause-icon",
|
|
51
|
+
prefix: prefix
|
|
52
|
+
} only %}
|
|
53
|
+
</button>
|
|
54
|
+
<button
|
|
55
|
+
class="{{base_class}}--skip-button {{base_class}}--skip-forward"
|
|
56
|
+
aria-label="Fast forward 15 seconds"
|
|
57
|
+
>
|
|
58
|
+
{% include "@components/icon/icon.twig" with {
|
|
59
|
+
name: "skip_forward15",
|
|
60
|
+
size: 24,
|
|
61
|
+
prefix: prefix
|
|
62
|
+
} only %}
|
|
63
|
+
</button>
|
|
64
|
+
</div>
|
|
65
|
+
<div class="{{base_class}}--right">
|
|
66
|
+
<div class="{{base_class}}--duration">
|
|
67
|
+
<p class="{{base_class}}--duration-played">00:00</p>
|
|
68
|
+
<p class="{{base_class}}--duration-total">00:00</p>
|
|
69
|
+
</div>
|
|
70
|
+
<div class="{{base_class}}--separator"></div>
|
|
71
|
+
<button
|
|
72
|
+
class="{{base_class}}--volume-icon"
|
|
73
|
+
aria-label="Mute"
|
|
74
|
+
>
|
|
75
|
+
{% include "@components/icon/icon.twig" with {
|
|
76
|
+
name: "sound_on",
|
|
77
|
+
size: 24,
|
|
78
|
+
prefix: prefix,
|
|
79
|
+
class: base_class ~ "--sound-on-icon",
|
|
80
|
+
} only %}
|
|
81
|
+
{% include "@components/icon/icon.twig" with {
|
|
82
|
+
name: "sound_off",
|
|
83
|
+
size: 24,
|
|
84
|
+
prefix: prefix,
|
|
85
|
+
class: base_class ~ "--sound-off-icon",
|
|
86
|
+
} only %}
|
|
87
|
+
</button>
|
|
88
|
+
<input
|
|
89
|
+
type="range"
|
|
90
|
+
class="{{base_class}}--volume-slider"
|
|
91
|
+
value="100"
|
|
92
|
+
min="0"
|
|
93
|
+
max="100"
|
|
94
|
+
step="10"
|
|
95
|
+
/>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
<audio
|
|
99
|
+
class="{{base_class}}--audio"
|
|
100
|
+
src="{{ src }}"
|
|
101
|
+
preload="metadata"
|
|
102
|
+
></audio>
|
|
103
|
+
</div>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
audioplayer:
|
|
2
|
+
namespace: Components/Media
|
|
3
|
+
use: "@components/audioplayer/audioplayer.twig"
|
|
4
|
+
label: Audio Player
|
|
5
|
+
description: A component for playing audio files.
|
|
6
|
+
visibility: storybook
|
|
7
|
+
fields:
|
|
8
|
+
src:
|
|
9
|
+
type: string
|
|
10
|
+
label: Audio source
|
|
11
|
+
description: Path to the audio file
|
|
12
|
+
required: true
|
|
13
|
+
preview: "/audio/audio-example.mp3"
|
|
14
|
+
name:
|
|
15
|
+
type: string
|
|
16
|
+
label: Track name
|
|
17
|
+
description: The name of the audio track
|
|
18
|
+
required: true
|
|
19
|
+
preview: "Sample Track"
|
|
20
|
+
programme:
|
|
21
|
+
type: string
|
|
22
|
+
label: Programme
|
|
23
|
+
description: The name of the programme
|
|
24
|
+
required: true
|
|
25
|
+
preview: "Sample Programme"
|
|
26
|
+
creator:
|
|
27
|
+
type: string
|
|
28
|
+
label: Creator
|
|
29
|
+
description: The name of the creator
|
|
30
|
+
required: true
|
|
31
|
+
preview: "Sample Creator"
|
|
32
|
+
variants:
|
|
33
|
+
default:
|
|
34
|
+
label: Default
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class Breadcrumb{constructor(element){this.element=element;this.prefix=this.element.dataset.prefix;this.init();}init(){this.cacheDomReferences().setupHandlers().enable().onResize();return this}cacheDomReferences(){this.breadcrumbsId=`${this.prefix}--breadcrumb--container`;this.contextAreaClass=`${this.prefix}--breadcrumb--context`;this.contextMenuItemsClass=`${this.prefix}--context-menu`;this.contextCollapseClass=`${this.contextAreaClass}__collapse`;this.contextButtonClass=`${this.contextAreaClass}--button`;this.contextMenuClass=`${this.contextAreaClass}--menu`;this.contextMenuVisibleClass=`${this.contextMenuClass}__visible`;this.breadcrumbs=this.element.querySelector(`#${this.breadcrumbsId}`);this.contextArea=this.element.querySelector(`.${this.contextAreaClass}`);this.contextMenu=this.element.querySelector(`.${this.contextMenuClass}`);this.contextButton=this.element.querySelector(`.${this.contextButtonClass}`);this.breadcrumbsLastLink=this.element.querySelector(`#${this.breadcrumbsId} > li:last-child a`);this.contextMenuItems=this.element.querySelector(`.${this.contextMenuItemsClass}`);this.contextMenuItemFirstLink=this.contextMenuItems.querySelector("li:first-child a");this.contextMenuItemLastLink=this.contextMenuItems.querySelector("li:last-child a");this.breadcrumbsWidth=this.breadcrumbs.offsetWidth;return this}setupHandlers(){this.onResize=this.onResize.bind(this);this.onClick=this.onClick.bind(this);this.contexMenuIsOpen=this.contexMenuIsOpen.bind(this);this.openContextMenu=this.openContextMenu.bind(this);this.closeContextMenu=this.closeContextMenu.bind(this);this.focusBreadcrumbsLastLink=this.focusBreadcrumbsLastLink.bind(this);this.focusContextMenuItemFirstLink=this.focusContextMenuItemFirstLink.bind(this);this.onKeydown=this.onKeydown.bind(this);return this}enable(){window.addEventListener(d.RESIZE,e=>this.onResize(e));if(this.contextButton){this.contextButton.addEventListener(d.CLICK,e=>this.onClick(e));this.element.addEventListener("keydown",e=>this.onKeydown(e));}return this}onClick(e){e.stopPropagation();if(this.contexMenuIsOpen()){this.closeContextMenu();}else {this.openContextMenu();window.addEventListener("click",this.closeContextMenu,{once:true});}return this}onResize(){if(this.contextArea&&this.breadcrumbsWidth){if(this.breadcrumbsWidth>=window.innerWidth/1.5){this.contextArea.classList.add(this.contextCollapseClass);}else {this.contextArea.classList.remove(this.contextCollapseClass);this.closeContextMenu();}}return this}onKeydown(e){if(e.shiftKey){if(e.key.toLowerCase()==="tab"){if(document.activeElement===this.contextMenuItemFirstLink){e.preventDefault();this.contextButton.focus();}}return this}if(e.key.toLowerCase()==="tab"){const contexMenuIsOpen=this.contexMenuIsOpen();if(contexMenuIsOpen){if(document.activeElement===this.contextButton){e.preventDefault();this.focusContextMenuItemFirstLink();return this}if(document.activeElement===this.contextMenuItemLastLink){e.preventDefault();this.focusBreadcrumbsLastLink();this.closeContextMenu();return this}}}return this}positionContextMenu(){const buttonRect=this.contextButton.getBoundingClientRect();const buttonCenterX=buttonRect.left+buttonRect.width/2;const contextMenuItemsWidth=this.contextMenuItems.offsetWidth;const navStart=buttonCenterX-contextMenuItemsWidth/2;const navTop=buttonRect.bottom+16;this.contextMenu.style.left=navStart+"px";this.contextMenu.style.top=navTop+"px";return this}openContextMenu(){this.contextMenu.classList.add(this.contextMenuVisibleClass);this.contextMenu.removeAttribute("hidden");this.contextButton.setAttribute("aria-expanded",true);this.positionContextMenu();return this}closeContextMenu(){this.contextMenu.classList.remove(this.contextMenuVisibleClass);this.contextMenu.setAttribute("hidden","hidden");this.contextButton.setAttribute("aria-expanded",false);}contexMenuIsOpen(){return this.contextMenu.classList.contains(this.contextMenuVisibleClass)}focusContextMenuItemFirstLink(){this.contextMenuItemFirstLink.focus();return this}focusBreadcrumbsLastLink(){this.breadcrumbsLastLink.focus();return this}}
|
|
4
|
+
class Breadcrumb{constructor(element){this.element=element;this.prefix=this.element.dataset.prefix;this.init();}init(){this.cacheDomReferences().setupHandlers().enable().onResize();return this}cacheDomReferences(){this.breadcrumbsId=`${this.prefix}--breadcrumb--container`;this.contextAreaClass=`${this.prefix}--breadcrumb--context`;this.contextMenuItemsClass=`${this.prefix}--context-menu`;this.contextCollapseClass=`${this.contextAreaClass}__collapse`;this.contextButtonClass=`${this.contextAreaClass}--button`;this.contextMenuClass=`${this.contextAreaClass}--menu`;this.contextMenuVisibleClass=`${this.contextMenuClass}__visible`;this.breadcrumbs=this.element.querySelector(`#${this.breadcrumbsId}`);this.contextArea=this.element.querySelector(`.${this.contextAreaClass}`);this.contextMenu=this.element.querySelector(`.${this.contextMenuClass}`);this.contextButton=this.element.querySelector(`.${this.contextButtonClass}`);this.breadcrumbsLastLink=this.element.querySelector(`#${this.breadcrumbsId} > li:last-child a`);this.contextMenuItems=this.element.querySelector(`.${this.contextMenuItemsClass}`);this.contextMenuItemFirstLink=this.contextMenuItems.querySelector("li:first-child a");this.contextMenuItemLastLink=this.contextMenuItems.querySelector("li:last-child a");this.breadcrumbsWidth=this.breadcrumbs.offsetWidth;return this}setupHandlers(){this.onResize=this.onResize.bind(this);this.onClick=this.onClick.bind(this);this.contexMenuIsOpen=this.contexMenuIsOpen.bind(this);this.openContextMenu=this.openContextMenu.bind(this);this.closeContextMenu=this.closeContextMenu.bind(this);this.focusBreadcrumbsLastLink=this.focusBreadcrumbsLastLink.bind(this);this.focusContextMenuItemFirstLink=this.focusContextMenuItemFirstLink.bind(this);this.onKeydown=this.onKeydown.bind(this);return this}enable(){window.addEventListener("resize",e=>this.onResize(e));if(this.contextButton){this.contextButton.addEventListener("click",e=>this.onClick(e));this.element.addEventListener("keydown",e=>this.onKeydown(e));}return this}onClick(e){e.stopPropagation();if(this.contexMenuIsOpen()){this.closeContextMenu();}else {this.openContextMenu();window.addEventListener("click",this.closeContextMenu,{once:true});}return this}onResize(){if(this.contextArea&&this.breadcrumbsWidth){if(this.breadcrumbsWidth>=window.innerWidth/1.5){this.contextArea.classList.add(this.contextCollapseClass);}else {this.contextArea.classList.remove(this.contextCollapseClass);this.closeContextMenu();}}return this}onKeydown(e){if(e.shiftKey){if(e.key.toLowerCase()==="tab"){if(document.activeElement===this.contextMenuItemFirstLink){e.preventDefault();this.contextButton.focus();}}return this}if(e.key.toLowerCase()==="tab"){const contexMenuIsOpen=this.contexMenuIsOpen();if(contexMenuIsOpen){if(document.activeElement===this.contextButton){e.preventDefault();this.focusContextMenuItemFirstLink();return this}if(document.activeElement===this.contextMenuItemLastLink){e.preventDefault();this.focusBreadcrumbsLastLink();this.closeContextMenu();return this}}}return this}positionContextMenu(){const buttonRect=this.contextButton.getBoundingClientRect();const buttonCenterX=buttonRect.left+buttonRect.width/2;const contextMenuItemsWidth=this.contextMenuItems.offsetWidth;const navStart=buttonCenterX-contextMenuItemsWidth/2;const navTop=buttonRect.bottom+16;this.contextMenu.style.left=navStart+"px";this.contextMenu.style.top=navTop+"px";return this}openContextMenu(){this.contextMenu.classList.add(this.contextMenuVisibleClass);this.contextMenu.removeAttribute("hidden");this.contextButton.setAttribute("aria-expanded",true);this.positionContextMenu();return this}closeContextMenu(){this.contextMenu.classList.remove(this.contextMenuVisibleClass);this.contextMenu.setAttribute("hidden","hidden");this.contextButton.setAttribute("aria-expanded",false);}contexMenuIsOpen(){return this.contextMenu.classList.contains(this.contextMenuVisibleClass)}focusContextMenuItemFirstLink(){this.contextMenuItemFirstLink.focus();return this}focusBreadcrumbsLastLink(){this.breadcrumbsLastLink.focus();return this}}
|
|
7
5
|
|
|
8
6
|
Drupal.behaviors.breadcrumb={attach(){Array.prototype.forEach.call(document.querySelectorAll(`[data-loadcomponent="Breadcrumb"]`),element=>{if(!element.dataset.jsProcessed){new Breadcrumb(element);element.dataset.jsProcessed=true;}});}};
|
|
9
7
|
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class Callout{constructor(element){this.element=element;this.toggleLabel="";this.init();}init(){this.cacheDomReferences().setupHandlers().enable();if(!this.toggleOpen&&this.toggleCollapsible){this.calcHeight();}return this}cacheDomReferences(){this.toggle=this.element.querySelector(".ilo--callout--toggle");this.toggleOpen=this.element.classList.value.includes("callout--open");this.toggleCollapsible=this.element.classList.value.includes("callout--collapse");if(this.toggle){this.toggleLabel=this.toggle.querySelector(".ilo--callout--button-text");this.toggleLabelOpen=this.toggle.getAttribute("data-open");this.toggleLabelClosed=this.toggle.getAttribute("data-closed");}this.button=this.element.querySelector(".ilo--button");return this}setupHandlers(){this.onToggle=this.handleToggle.bind(this);this.onClick=this.handleClick.bind(this);return this}enable(){if(this.toggle){this.toggle.addEventListener(d.CLICK,this.onToggle);}if(this.button){this.button.addEventListener(d.CLICK,this.onClick);}return this}calcHeight(){this.header=this.element.querySelector('[class*="--header"]');this.height=this.header.offsetHeight;this.element.style.maxHeight=`${this.height+25}px`;return this}handleClick(){return this}handleToggle(e){e.preventDefault();this.toggleOpen=!this.toggleOpen;const label=this.toggleOpen?this.toggleLabelOpen:this.toggleLabelClosed;this.element.classList.toggle("ilo--callout__open");this.toggleLabel.innerText=label;return this}}
|
|
4
|
+
class Callout{constructor(element){this.element=element;this.toggleLabel="";this.init();}init(){this.cacheDomReferences().setupHandlers().enable();if(!this.toggleOpen&&this.toggleCollapsible){this.calcHeight();}return this}cacheDomReferences(){this.toggle=this.element.querySelector(".ilo--callout--toggle");this.toggleOpen=this.element.classList.value.includes("callout--open");this.toggleCollapsible=this.element.classList.value.includes("callout--collapse");if(this.toggle){this.toggleLabel=this.toggle.querySelector(".ilo--callout--button-text");this.toggleLabelOpen=this.toggle.getAttribute("data-open");this.toggleLabelClosed=this.toggle.getAttribute("data-closed");}this.button=this.element.querySelector(".ilo--button");return this}setupHandlers(){this.onToggle=this.handleToggle.bind(this);this.onClick=this.handleClick.bind(this);return this}enable(){if(this.toggle){this.toggle.addEventListener("click",this.onToggle);}if(this.button){this.button.addEventListener("click",this.onClick);}return this}calcHeight(){this.header=this.element.querySelector('[class*="--header"]');this.height=this.header.offsetHeight;this.element.style.maxHeight=`${this.height+25}px`;return this}handleClick(){return this}handleToggle(e){e.preventDefault();this.toggleOpen=!this.toggleOpen;const label=this.toggleOpen?this.toggleLabelOpen:this.toggleLabelClosed;this.element.classList.toggle("ilo--callout__open");this.toggleLabel.innerText=label;return this}}
|
|
7
5
|
|
|
8
6
|
Drupal.behaviors.callout={attach(){Array.prototype.forEach.call(document.querySelectorAll(`[data-loadcomponent="Callout"]`),element=>{if(!element.dataset.jsProcessed){new Callout(element);element.dataset.jsProcessed=true;}});}};
|
|
9
7
|
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class FileUpload{constructor(element){this.element=element;this.prefix=this.element.dataset.prefix;this.init();}init(){this.cacheDomReferences().setupHandlers().enable();return this}cacheDomReferences(){this.container=this.element.parentElement.parentElement;this.formControl=this.container.parentElement;return this}setupHandlers(){this.onChange=this.onChange.bind(this);return this}enable(){this.element.addEventListener(d.CHANGE,e=>this.onChange(e));return this}formatBytes(bytes,decimals){if(decimals===void 0)decimals=2;if(!+bytes)return "0 Bytes";const k=1024;const dm=decimals<0?0:decimals;const sizes=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"];const i=Math.floor(Math.log(bytes)/Math.log(k));return `${parseFloat((bytes/Math.pow(k,i)).toFixed(dm))} ${sizes[i]}`}onChange(){const fileListClass=`${this.prefix}--file-upload--list`;let fileList=this.formControl.querySelector(`.${fileListClass}`);if(fileList){fileList.remove();}fileList=document.createElement("ul");fileList.classList.add(fileListClass);this.formControl.appendChild(fileList);let files="";[...this.element.files].forEach(file=>{const fileSize=this.formatBytes(file.size);files+=this.template(file.name,fileSize);});fileList.innerHTML=files;return this}template(filename,filesize){return `<li class="ilo--file-upload--list-item">${filename} (${filesize})</li>`}}
|
|
4
|
+
class FileUpload{constructor(element){this.element=element;this.prefix=this.element.dataset.prefix;this.init();}init(){this.cacheDomReferences().setupHandlers().enable();return this}cacheDomReferences(){this.container=this.element.parentElement.parentElement;this.formControl=this.container.parentElement;return this}setupHandlers(){this.onChange=this.onChange.bind(this);return this}enable(){this.element.addEventListener("change",e=>this.onChange(e));return this}formatBytes(bytes,decimals){if(decimals===void 0)decimals=2;if(!+bytes)return "0 Bytes";const k=1024;const dm=decimals<0?0:decimals;const sizes=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"];const i=Math.floor(Math.log(bytes)/Math.log(k));return `${parseFloat((bytes/Math.pow(k,i)).toFixed(dm))} ${sizes[i]}`}onChange(){const fileListClass=`${this.prefix}--file-upload--list`;let fileList=this.formControl.querySelector(`.${fileListClass}`);if(fileList){fileList.remove();}fileList=document.createElement("ul");fileList.classList.add(fileListClass);this.formControl.appendChild(fileList);let files="";[...this.element.files].forEach(file=>{const fileSize=this.formatBytes(file.size);files+=this.template(file.name,fileSize);});fileList.innerHTML=files;return this}template(filename,filesize){return `<li class="ilo--file-upload--list-item">${filename} (${filesize})</li>`}}
|
|
7
5
|
|
|
8
6
|
Drupal.behaviors.fileupload={attach(){Array.prototype.forEach.call(document.querySelectorAll(`[data-loadcomponent="FileUpload"]`),element=>{new FileUpload(element);});}};
|
|
9
7
|
|