kempo-ui 0.4.23 → 0.4.25
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.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import e from"./ShadowComponent.js";import{html as t,css as n,render as o}from"../lit-all.min.js";import{boolExists as
|
|
1
|
+
import e from"./ShadowComponent.js";import{html as t,css as n,render as o}from"../lit-all.min.js";import{boolExists as l}from"../utils/propConverters.js";import"./Icon.js";export default class i extends e{static properties={src:{type:String,reflect:!0},alt:{type:String,reflect:!0},fullscreen:{type:Boolean,reflect:!0,converter:l},keyboardControls:{type:Boolean,reflect:!0,attribute:"keyboard-controls",converter:l},global:{type:Boolean,reflect:!0,converter:l}};constructor(){super(),this.src="",this.alt="",this.fullscreen=!1,this.keyboardControls=!0,this.global=!1}handleImageClick=()=>{this.open()};handleImageKeydown=e=>{"Enter"!==e.key||this.fullscreen||this.open()};handleCloseClick=()=>{this.close()};handleOverlayClick=e=>{e.target===e.currentTarget&&this.close()};handlePrevClick=e=>{e.stopPropagation();const t=this.getPrevSibling();t&&(this.close(),t.open())};handleNextClick=e=>{e.stopPropagation();const t=this.getNextSibling();t&&(this.close(),t.open())};handleKeydown=e=>{if("Escape"===e.key)this.close();else if("ArrowLeft"===e.key){const e=this.getPrevSibling();e&&(this.close(),e.open())}else if("ArrowRight"===e.key){const e=this.getNextSibling();e&&(this.close(),e.open())}};connectedCallback(){super.connectedCallback()}disconnectedCallback(){super.disconnectedCallback(),this.keyboardControls&&document.removeEventListener("keydown",this.handleKeydown)}updated(e){if(super.updated(e),e.has("fullscreen")){this.dispatchEvent(new CustomEvent("fullscreenchange",{detail:{fullscreen:this.fullscreen}})),this.dispatchEvent(new CustomEvent(this.fullscreen?"fullscreen":"fullscreenclose")),this.updateNavigationState(),document.body.classList.toggle("no-scroll",this.fullscreen);const e=this.closest("[data-overlay-root]");e&&e.classList.toggle("no-scroll",this.fullscreen),this.keyboardControls&&(this.fullscreen?document.addEventListener("keydown",this.handleKeydown):document.removeEventListener("keydown",this.handleKeydown))}(e.has("src")||e.has("alt"))&&this.handleFullscreenCaption()}firstUpdated(){this.handleFullscreenCaption()}open(){this.fullscreen=!0}close(){this.fullscreen=!1}toggle(){this.fullscreen=!this.fullscreen}static open(e,t=0,n={}){const{keyboardControls:l=!0,onClose:i}=n,s=document.createElement("div");s.style.position="fixed",s.style.top="0",s.style.left="0",s.style.width="0",s.style.height="0",s.style.overflow="hidden",s.style.zIndex="80";const r=e.map(e=>{const t=document.createElement("k-photo-viewer");return t.src=e.src,t.alt=e.alt||"",t.keyboardControls=l,void 0!==e.caption&&("string"==typeof e.caption?t.innerHTML=e.caption:o(e.caption,t)),s.appendChild(t),t});(document.querySelector("[data-overlay-root]")||document.body).appendChild(s);const a=()=>{r.some(e=>e.fullscreen)||(r.forEach(e=>e.removeEventListener("fullscreenclose",a)),s.remove(),i?.())};r.forEach(e=>e.addEventListener("fullscreenclose",a));const c=Math.min(Math.max(t,0),r.length-1);return r[c].open(),r[c]}getPrevSibling(){if(this.global){const e=Array.from(document.getElementsByTagName("k-photo-viewer")),t=e.indexOf(this);return-1===t?null:e[0===t?e.length-1:t-1]}{let e=this.previousElementSibling;for(;e&&"K-PHOTO-VIEWER"!==e.tagName;)e=e.previousElementSibling;if(!e&&this.hasPhotoSiblings())for(e=this.parentElement.lastElementChild;e&&"K-PHOTO-VIEWER"!==e.tagName;)e=e.previousElementSibling;return e}}getNextSibling(){if(this.global){const e=Array.from(document.getElementsByTagName("k-photo-viewer")),t=e.indexOf(this);return-1===t?null:e[t===e.length-1?0:t+1]}{let e=this.nextElementSibling;for(;e&&"K-PHOTO-VIEWER"!==e.tagName;)e=e.nextElementSibling;if(!e&&this.hasPhotoSiblings())for(e=this.parentElement.firstElementChild;e&&"K-PHOTO-VIEWER"!==e.tagName;)e=e.nextElementSibling;return e}}hasPhotoSiblings(){return this.global?document.getElementsByTagName("k-photo-viewer").length>1:Array.from(this.parentElement.children).filter(e=>e!==this&&"K-PHOTO-VIEWER"===e.tagName).length>0}updateNavigationState(){const e=this.fullscreen&&this.hasPhotoSiblings();this.shadowRoot.querySelectorAll(".nav-btn").forEach(t=>{t.style.display=e?"":"none"})}async handleFullscreenCaption(){await this.updateComplete;const e=this.shadowRoot.querySelector('slot[name="fullscreen-caption"]');if(e&&!e.assignedNodes().length){const e=this.shadowRoot.querySelector("slot:not([name])");(e?e.assignedNodes():[]).forEach(e=>{if(e.nodeType===Node.ELEMENT_NODE){const t=e.cloneNode(!0);t.slot="fullscreen-caption",this.appendChild(t)}})}}static styles=n`
|
|
2
2
|
:host {
|
|
3
3
|
display: block;
|
|
4
4
|
}
|
|
@@ -132,4 +132,4 @@ import e from"./ShadowComponent.js";import{html as t,css as n,render as o}from".
|
|
|
132
132
|
</div>
|
|
133
133
|
</div>
|
|
134
134
|
</div>
|
|
135
|
-
`}}customElements.define("k-photo-viewer",
|
|
135
|
+
`}}customElements.define("k-photo-viewer",i);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import e from"./ShadowComponent.js";import{html as t,css as n,render as o}from"../lit-all.min.js";import{boolExists as
|
|
1
|
+
import e from"./ShadowComponent.js";import{html as t,css as n,render as o}from"../lit-all.min.js";import{boolExists as l}from"../utils/propConverters.js";import"./Icon.js";export default class i extends e{static properties={src:{type:String,reflect:!0},alt:{type:String,reflect:!0},fullscreen:{type:Boolean,reflect:!0,converter:l},keyboardControls:{type:Boolean,reflect:!0,attribute:"keyboard-controls",converter:l},global:{type:Boolean,reflect:!0,converter:l}};constructor(){super(),this.src="",this.alt="",this.fullscreen=!1,this.keyboardControls=!0,this.global=!1}handleImageClick=()=>{this.open()};handleImageKeydown=e=>{"Enter"!==e.key||this.fullscreen||this.open()};handleCloseClick=()=>{this.close()};handleOverlayClick=e=>{e.target===e.currentTarget&&this.close()};handlePrevClick=e=>{e.stopPropagation();const t=this.getPrevSibling();t&&(this.close(),t.open())};handleNextClick=e=>{e.stopPropagation();const t=this.getNextSibling();t&&(this.close(),t.open())};handleKeydown=e=>{if("Escape"===e.key)this.close();else if("ArrowLeft"===e.key){const e=this.getPrevSibling();e&&(this.close(),e.open())}else if("ArrowRight"===e.key){const e=this.getNextSibling();e&&(this.close(),e.open())}};connectedCallback(){super.connectedCallback()}disconnectedCallback(){super.disconnectedCallback(),this.keyboardControls&&document.removeEventListener("keydown",this.handleKeydown)}updated(e){if(super.updated(e),e.has("fullscreen")){this.dispatchEvent(new CustomEvent("fullscreenchange",{detail:{fullscreen:this.fullscreen}})),this.dispatchEvent(new CustomEvent(this.fullscreen?"fullscreen":"fullscreenclose")),this.updateNavigationState(),document.body.classList.toggle("no-scroll",this.fullscreen);const e=this.closest("[data-overlay-root]");e&&e.classList.toggle("no-scroll",this.fullscreen),this.keyboardControls&&(this.fullscreen?document.addEventListener("keydown",this.handleKeydown):document.removeEventListener("keydown",this.handleKeydown))}(e.has("src")||e.has("alt"))&&this.handleFullscreenCaption()}firstUpdated(){this.handleFullscreenCaption()}open(){this.fullscreen=!0}close(){this.fullscreen=!1}toggle(){this.fullscreen=!this.fullscreen}static open(e,t=0,n={}){const{keyboardControls:l=!0,onClose:i}=n,s=document.createElement("div");s.style.position="fixed",s.style.top="0",s.style.left="0",s.style.width="0",s.style.height="0",s.style.overflow="hidden",s.style.zIndex="80";const r=e.map(e=>{const t=document.createElement("k-photo-viewer");return t.src=e.src,t.alt=e.alt||"",t.keyboardControls=l,void 0!==e.caption&&("string"==typeof e.caption?t.innerHTML=e.caption:o(e.caption,t)),s.appendChild(t),t});(document.querySelector("[data-overlay-root]")||document.body).appendChild(s);const a=()=>{r.some(e=>e.fullscreen)||(r.forEach(e=>e.removeEventListener("fullscreenclose",a)),s.remove(),i?.())};r.forEach(e=>e.addEventListener("fullscreenclose",a));const c=Math.min(Math.max(t,0),r.length-1);return r[c].open(),r[c]}getPrevSibling(){if(this.global){const e=Array.from(document.getElementsByTagName("k-photo-viewer")),t=e.indexOf(this);return-1===t?null:e[0===t?e.length-1:t-1]}{let e=this.previousElementSibling;for(;e&&"K-PHOTO-VIEWER"!==e.tagName;)e=e.previousElementSibling;if(!e&&this.hasPhotoSiblings())for(e=this.parentElement.lastElementChild;e&&"K-PHOTO-VIEWER"!==e.tagName;)e=e.previousElementSibling;return e}}getNextSibling(){if(this.global){const e=Array.from(document.getElementsByTagName("k-photo-viewer")),t=e.indexOf(this);return-1===t?null:e[t===e.length-1?0:t+1]}{let e=this.nextElementSibling;for(;e&&"K-PHOTO-VIEWER"!==e.tagName;)e=e.nextElementSibling;if(!e&&this.hasPhotoSiblings())for(e=this.parentElement.firstElementChild;e&&"K-PHOTO-VIEWER"!==e.tagName;)e=e.nextElementSibling;return e}}hasPhotoSiblings(){return this.global?document.getElementsByTagName("k-photo-viewer").length>1:Array.from(this.parentElement.children).filter(e=>e!==this&&"K-PHOTO-VIEWER"===e.tagName).length>0}updateNavigationState(){const e=this.fullscreen&&this.hasPhotoSiblings();this.shadowRoot.querySelectorAll(".nav-btn").forEach(t=>{t.style.display=e?"":"none"})}async handleFullscreenCaption(){await this.updateComplete;const e=this.shadowRoot.querySelector('slot[name="fullscreen-caption"]');if(e&&!e.assignedNodes().length){const e=this.shadowRoot.querySelector("slot:not([name])");(e?e.assignedNodes():[]).forEach(e=>{if(e.nodeType===Node.ELEMENT_NODE){const t=e.cloneNode(!0);t.slot="fullscreen-caption",this.appendChild(t)}})}}static styles=n`
|
|
2
2
|
:host {
|
|
3
3
|
display: block;
|
|
4
4
|
}
|
|
@@ -132,4 +132,4 @@ import e from"./ShadowComponent.js";import{html as t,css as n,render as o}from".
|
|
|
132
132
|
</div>
|
|
133
133
|
</div>
|
|
134
134
|
</div>
|
|
135
|
-
`}}customElements.define("k-photo-viewer",
|
|
135
|
+
`}}customElements.define("k-photo-viewer",i);
|
package/package.json
CHANGED
|
@@ -104,7 +104,11 @@ export default class PhotoViewer extends ShadowComponent {
|
|
|
104
104
|
}));
|
|
105
105
|
this.dispatchEvent(new CustomEvent(this.fullscreen ? 'fullscreen' : 'fullscreenclose'));
|
|
106
106
|
this.updateNavigationState();
|
|
107
|
-
|
|
107
|
+
|
|
108
|
+
document.body.classList.toggle('no-scroll', this.fullscreen);
|
|
109
|
+
const overlayRoot = this.closest('[data-overlay-root]');
|
|
110
|
+
if(overlayRoot) overlayRoot.classList.toggle('no-scroll', this.fullscreen);
|
|
111
|
+
|
|
108
112
|
if(this.keyboardControls) {
|
|
109
113
|
if(this.fullscreen) {
|
|
110
114
|
document.addEventListener('keydown', this.handleKeydown);
|
|
@@ -169,7 +173,8 @@ export default class PhotoViewer extends ShadowComponent {
|
|
|
169
173
|
return viewer;
|
|
170
174
|
});
|
|
171
175
|
|
|
172
|
-
document.
|
|
176
|
+
const mountRoot = document.querySelector('[data-overlay-root]') || document.body;
|
|
177
|
+
mountRoot.appendChild(container);
|
|
173
178
|
|
|
174
179
|
const handleClose = () => {
|
|
175
180
|
if(!viewers.some(viewer => viewer.fullscreen)) {
|
|
@@ -831,5 +831,110 @@ export default {
|
|
|
831
831
|
|
|
832
832
|
viewer.close();
|
|
833
833
|
pass('Container has correct z-index elevation');
|
|
834
|
+
},
|
|
835
|
+
|
|
836
|
+
'should mount into document.body by default': async ({pass, fail}) => {
|
|
837
|
+
const viewer = PhotoViewer.open([
|
|
838
|
+
{ src: 'https://picsum.photos/200/300' }
|
|
839
|
+
]);
|
|
840
|
+
await viewer.updateComplete;
|
|
841
|
+
|
|
842
|
+
const container = viewer.parentElement;
|
|
843
|
+
if(container.parentElement !== document.body){
|
|
844
|
+
viewer.close();
|
|
845
|
+
fail('Container should mount into document.body by default');
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
viewer.close();
|
|
850
|
+
pass('Container mounts into document.body by default');
|
|
851
|
+
},
|
|
852
|
+
|
|
853
|
+
'should mount into the nearest [data-overlay-root] when present': async ({pass, fail}) => {
|
|
854
|
+
const root = document.createElement('div');
|
|
855
|
+
root.setAttribute('data-overlay-root', '');
|
|
856
|
+
document.body.appendChild(root);
|
|
857
|
+
|
|
858
|
+
const viewer = PhotoViewer.open([
|
|
859
|
+
{ src: 'https://picsum.photos/200/300' }
|
|
860
|
+
]);
|
|
861
|
+
await viewer.updateComplete;
|
|
862
|
+
|
|
863
|
+
const container = viewer.parentElement;
|
|
864
|
+
const mountedInRoot = container.parentElement === root;
|
|
865
|
+
|
|
866
|
+
viewer.close();
|
|
867
|
+
root.remove();
|
|
868
|
+
|
|
869
|
+
if(!mountedInRoot){
|
|
870
|
+
fail('Container should mount into the [data-overlay-root] element');
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
pass('Container mounts into the [data-overlay-root] element');
|
|
875
|
+
},
|
|
876
|
+
|
|
877
|
+
/*
|
|
878
|
+
Scroll Lock Tests
|
|
879
|
+
*/
|
|
880
|
+
'should add no-scroll to body when opened': async ({pass, fail}) => {
|
|
881
|
+
const { container, viewer } = await createPhotoViewer();
|
|
882
|
+
|
|
883
|
+
viewer.open();
|
|
884
|
+
await viewer.updateComplete;
|
|
885
|
+
|
|
886
|
+
const hasClass = document.body.classList.contains('no-scroll');
|
|
887
|
+
viewer.close();
|
|
888
|
+
await viewer.updateComplete;
|
|
889
|
+
|
|
890
|
+
cleanup(container);
|
|
891
|
+
if(!hasClass){
|
|
892
|
+
fail('document.body should have no-scroll class when fullscreen');
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
pass('document.body gets no-scroll class when opened');
|
|
897
|
+
},
|
|
898
|
+
|
|
899
|
+
'should remove no-scroll from body when closed': async ({pass, fail}) => {
|
|
900
|
+
const { container, viewer } = await createPhotoViewer({ fullscreen: true });
|
|
901
|
+
|
|
902
|
+
viewer.close();
|
|
903
|
+
await viewer.updateComplete;
|
|
904
|
+
|
|
905
|
+
const hasClass = document.body.classList.contains('no-scroll');
|
|
906
|
+
cleanup(container);
|
|
907
|
+
|
|
908
|
+
if(hasClass){
|
|
909
|
+
fail('document.body should not have no-scroll class when closed');
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
pass('document.body loses no-scroll class when closed');
|
|
914
|
+
},
|
|
915
|
+
|
|
916
|
+
'should add no-scroll to the nearest [data-overlay-root] when opened': async ({pass, fail}) => {
|
|
917
|
+
const root = document.createElement('div');
|
|
918
|
+
root.setAttribute('data-overlay-root', '');
|
|
919
|
+
document.body.appendChild(root);
|
|
920
|
+
|
|
921
|
+
const viewer = document.createElement('k-photo-viewer');
|
|
922
|
+
root.appendChild(viewer);
|
|
923
|
+
await viewer.updateComplete;
|
|
924
|
+
|
|
925
|
+
viewer.open();
|
|
926
|
+
await viewer.updateComplete;
|
|
927
|
+
|
|
928
|
+
const hasClass = root.classList.contains('no-scroll');
|
|
929
|
+
viewer.close();
|
|
930
|
+
await viewer.updateComplete;
|
|
931
|
+
root.remove();
|
|
932
|
+
|
|
933
|
+
if(!hasClass){
|
|
934
|
+
fail('[data-overlay-root] should have no-scroll class when a descendant viewer is fullscreen');
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
pass('[data-overlay-root] gets no-scroll class when opened');
|
|
834
939
|
}
|
|
835
940
|
};
|