mirror of
https://github.com/primefaces/primevue.git
synced 2025-05-09 00:42:36 +00:00
Fixed #3802 - Improve folder structure for nuxt configurations
This commit is contained in:
parent
851950270b
commit
f5fe822afb
563 changed files with 1703 additions and 1095 deletions
108
components/lib/image/Image.d.ts
vendored
Normal file
108
components/lib/image/Image.d.ts
vendored
Normal file
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
*
|
||||
* Displays an image with preview and tranformation options. For multiple image, see Galleria.
|
||||
*
|
||||
* [Live Demo](https://www.primevue.org/image/)
|
||||
*
|
||||
* @module image
|
||||
*
|
||||
*/
|
||||
import { VNode } from 'vue';
|
||||
import { ClassComponent, GlobalComponentConstructor } from '../ts-helpers';
|
||||
|
||||
/**
|
||||
* Defines valid properties in Image component.
|
||||
*/
|
||||
export interface ImageProps {
|
||||
/**
|
||||
* Controls the preview functionality.
|
||||
* @defaultValue false
|
||||
*/
|
||||
preview?: boolean | undefined;
|
||||
/**
|
||||
* Inline style of the image element.
|
||||
*/
|
||||
imageStyle?: any;
|
||||
/**
|
||||
* Style class of the image element.
|
||||
*/
|
||||
imageClass?: any;
|
||||
/**
|
||||
* Custom indicator icon.
|
||||
* @defaultValue pi pi-eye
|
||||
*/
|
||||
indicatorIcon?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines valid slots in Image slots.
|
||||
*/
|
||||
export interface ImageSlots {
|
||||
/**
|
||||
* Custom indicator template.
|
||||
*/
|
||||
indicator(): VNode[];
|
||||
/**
|
||||
* Custom refresh template.
|
||||
*/
|
||||
refresh(): VNode[];
|
||||
/**
|
||||
* Custom undo template.
|
||||
*/
|
||||
undo(): VNode[];
|
||||
/**
|
||||
* Custom zoomout template.
|
||||
*/
|
||||
zoomout(): VNode[];
|
||||
/**
|
||||
* Custom zoomin template.
|
||||
*/
|
||||
zoomin(): VNode[];
|
||||
/**
|
||||
* Custom close template.
|
||||
*/
|
||||
close(): VNode[];
|
||||
}
|
||||
|
||||
export interface ImageEmits {}
|
||||
|
||||
/**
|
||||
* **PrimeVue - Image**
|
||||
*
|
||||
* _Displays an image with preview and tranformation options. For multiple image, see Galleria._
|
||||
*
|
||||
* [Live Demo](https://www.primevue.org/image/)
|
||||
* --- ---
|
||||
* 
|
||||
*
|
||||
* @group Component
|
||||
*
|
||||
*/
|
||||
declare class Image extends ClassComponent<ImageProps, ImageSlots, ImageEmits> {
|
||||
/**
|
||||
* Triggered when the preview overlay is shown.
|
||||
*
|
||||
* @memberof Image
|
||||
*/
|
||||
show(): void;
|
||||
/**
|
||||
* Triggered when the preview overlay is hidden.
|
||||
*
|
||||
* @memberof Image
|
||||
*/
|
||||
hide(): void;
|
||||
/**
|
||||
* Triggered when an error occurs while loading an image file.
|
||||
*
|
||||
* @memberof Image
|
||||
*/
|
||||
error(): void;
|
||||
}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {
|
||||
Image: GlobalComponentConstructor<Image>;
|
||||
}
|
||||
}
|
||||
|
||||
export default Image;
|
52
components/lib/image/Image.spec.js
Normal file
52
components/lib/image/Image.spec.js
Normal file
|
@ -0,0 +1,52 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import PrimeVue from 'primevue/config';
|
||||
import Image from './Image.vue';
|
||||
|
||||
describe('Image.vue', () => {
|
||||
it('should exist', () => {
|
||||
const wrapper = mount(Image, {
|
||||
global: {
|
||||
plugins: [PrimeVue],
|
||||
stubs: {
|
||||
teleport: true
|
||||
}
|
||||
},
|
||||
props: {
|
||||
src: 'images/galleria/galleria1.jpg'
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.find('.p-image.p-component').exists()).toBe(true);
|
||||
expect(wrapper.find('.p-image.p-component img').attributes().src).toBe('images/galleria/galleria1.jpg');
|
||||
});
|
||||
|
||||
it('should preview', async () => {
|
||||
const wrapper = mount(Image, {
|
||||
global: {
|
||||
plugins: [PrimeVue],
|
||||
stubs: {
|
||||
teleport: true
|
||||
}
|
||||
},
|
||||
props: {
|
||||
src: 'images/galleria/galleria1.jpg',
|
||||
preview: true
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.find('.p-image-preview-container').exists()).toBe(true);
|
||||
expect(wrapper.find('.p-image-preview-indicator').exists()).toBe(true);
|
||||
expect(wrapper.find('.p-image-mask').exists()).toBe(false);
|
||||
|
||||
await wrapper.setData({ maskVisible: true });
|
||||
|
||||
expect(wrapper.find('.p-image-mask').exists()).toBe(true);
|
||||
expect(wrapper.find('.p-image-toolbar').exists()).toBe(true);
|
||||
|
||||
await wrapper.setData({ maskVisible: false });
|
||||
|
||||
setTimeout(() => {
|
||||
expect(wrapper.find('.p-image-mask').exists()).toBe(false);
|
||||
}, 25);
|
||||
});
|
||||
});
|
306
components/lib/image/Image.vue
Normal file
306
components/lib/image/Image.vue
Normal file
|
@ -0,0 +1,306 @@
|
|||
<template>
|
||||
<span :class="containerClass" :style="style">
|
||||
<img v-bind="$attrs" :style="imageStyle" :class="imageClass" @error="onError" />
|
||||
<button v-if="preview" ref="previewButton" class="p-image-preview-indicator" @click="onImageClick" v-bind="previewButtonProps">
|
||||
<slot name="indicator">
|
||||
<i :class="['p-image-preview-icon', indicatorIcon]"></i>
|
||||
</slot>
|
||||
</button>
|
||||
<Portal>
|
||||
<div v-if="maskVisible" :ref="maskRef" v-focustrap role="dialog" :class="maskClass" :aria-modal="maskVisible" @click="onMaskClick" @keydown="onMaskKeydown">
|
||||
<div class="p-image-toolbar">
|
||||
<button class="p-image-action p-link" @click="rotateRight" type="button" :aria-label="rightAriaLabel">
|
||||
<slot name="refresh">
|
||||
<i class="pi pi-refresh"></i>
|
||||
</slot>
|
||||
</button>
|
||||
|
||||
<button class="p-image-action p-link" @click="rotateLeft" type="button" :aria-label="leftAriaLabel">
|
||||
<slot name="undo">
|
||||
<i class="pi pi-undo"></i>
|
||||
</slot>
|
||||
</button>
|
||||
|
||||
<button class="p-image-action p-link" @click="zoomOut" type="button" :disabled="zoomDisabled" :aria-label="zoomOutAriaLabel">
|
||||
<slot name="zoomout">
|
||||
<i class="pi pi-search-minus"></i>
|
||||
</slot>
|
||||
</button>
|
||||
|
||||
<button class="p-image-action p-link" @click="zoomIn" type="button" :disabled="zoomDisabled" :aria-label="zoomInAriaLabel">
|
||||
<slot name="zoomin">
|
||||
<i class="pi pi-search-plus"></i>
|
||||
</slot>
|
||||
</button>
|
||||
|
||||
<button class="p-image-action p-link" type="button" @click="hidePreview" :aria-label="closeAriaLabel" autofocus>
|
||||
<slot name="close">
|
||||
<i class="pi pi-times"></i>
|
||||
</slot>
|
||||
</button>
|
||||
</div>
|
||||
<transition name="p-image-preview" @before-enter="onBeforeEnter" @enter="onEnter" @leave="onLeave" @before-leave="onBeforeLeave" @after-leave="onAfterLeave">
|
||||
<div v-if="previewVisible">
|
||||
<img :src="$attrs.src" class="p-image-preview" :style="imagePreviewStyle" @click="onPreviewImageClick" />
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</Portal>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FocusTrap from 'primevue/focustrap';
|
||||
import Portal from 'primevue/portal';
|
||||
import { DomHandler, ZIndexUtils } from 'primevue/utils';
|
||||
|
||||
export default {
|
||||
name: 'Image',
|
||||
inheritAttrs: false,
|
||||
emits: ['show', 'hide', 'error'],
|
||||
props: {
|
||||
preview: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
class: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
style: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
imageStyle: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
imageClass: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
previewButtonProps: {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
indicatorIcon: {
|
||||
type: String,
|
||||
default: 'pi pi-eye'
|
||||
}
|
||||
},
|
||||
mask: null,
|
||||
data() {
|
||||
return {
|
||||
maskVisible: false,
|
||||
previewVisible: false,
|
||||
rotate: 0,
|
||||
scale: 1
|
||||
};
|
||||
},
|
||||
beforeUnmount() {
|
||||
if (this.mask) {
|
||||
ZIndexUtils.clear(this.container);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
maskRef(el) {
|
||||
this.mask = el;
|
||||
},
|
||||
toolbarRef(el) {
|
||||
this.toolbarRef = el;
|
||||
},
|
||||
onImageClick() {
|
||||
if (this.preview) {
|
||||
this.maskVisible = true;
|
||||
setTimeout(() => {
|
||||
this.previewVisible = true;
|
||||
}, 25);
|
||||
}
|
||||
},
|
||||
onPreviewImageClick() {
|
||||
this.previewClick = true;
|
||||
},
|
||||
onMaskClick() {
|
||||
if (!this.previewClick) {
|
||||
this.previewVisible = false;
|
||||
this.rotate = 0;
|
||||
this.scale = 1;
|
||||
}
|
||||
|
||||
this.previewClick = false;
|
||||
},
|
||||
onMaskKeydown(event) {
|
||||
switch (event.code) {
|
||||
case 'Escape':
|
||||
this.onMaskClick();
|
||||
setTimeout(() => {
|
||||
DomHandler.focus(this.$refs.previewButton);
|
||||
}, 25);
|
||||
event.preventDefault();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
onError() {
|
||||
this.$emit('error');
|
||||
},
|
||||
rotateRight() {
|
||||
this.rotate += 90;
|
||||
this.previewClick = true;
|
||||
},
|
||||
rotateLeft() {
|
||||
this.rotate -= 90;
|
||||
this.previewClick = true;
|
||||
},
|
||||
zoomIn() {
|
||||
this.scale = this.scale + 0.1;
|
||||
this.previewClick = true;
|
||||
},
|
||||
zoomOut() {
|
||||
this.scale = this.scale - 0.1;
|
||||
this.previewClick = true;
|
||||
},
|
||||
onBeforeEnter() {
|
||||
ZIndexUtils.set('modal', this.mask, this.$primevue.config.zIndex.modal);
|
||||
},
|
||||
onEnter() {
|
||||
this.focus();
|
||||
this.$emit('show');
|
||||
},
|
||||
onBeforeLeave() {
|
||||
DomHandler.addClass(this.mask, 'p-component-overlay-leave');
|
||||
},
|
||||
onLeave() {
|
||||
this.$emit('hide');
|
||||
},
|
||||
onAfterLeave(el) {
|
||||
ZIndexUtils.clear(el);
|
||||
this.maskVisible = false;
|
||||
},
|
||||
focus() {
|
||||
let focusTarget = this.mask.querySelector('[autofocus]');
|
||||
|
||||
if (focusTarget) {
|
||||
focusTarget.focus();
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return [
|
||||
'p-image p-component',
|
||||
this.class,
|
||||
{
|
||||
'p-image-preview-container': this.preview
|
||||
}
|
||||
];
|
||||
},
|
||||
maskClass() {
|
||||
return ['p-image-mask p-component-overlay p-component-overlay-enter'];
|
||||
},
|
||||
rotateClass() {
|
||||
return 'p-image-preview-rotate-' + this.rotate;
|
||||
},
|
||||
imagePreviewStyle() {
|
||||
return { transform: 'rotate(' + this.rotate + 'deg) scale(' + this.scale + ')' };
|
||||
},
|
||||
zoomDisabled() {
|
||||
return this.scale <= 0.5 || this.scale >= 1.5;
|
||||
},
|
||||
rightAriaLabel() {
|
||||
return this.$primevue.config.locale.aria ? this.$primevue.config.locale.aria.rotateRight : undefined;
|
||||
},
|
||||
leftAriaLabel() {
|
||||
return this.$primevue.config.locale.aria ? this.$primevue.config.locale.aria.rotateLeft : undefined;
|
||||
},
|
||||
zoomInAriaLabel() {
|
||||
return this.$primevue.config.locale.aria ? this.$primevue.config.locale.aria.zoomIn : undefined;
|
||||
},
|
||||
zoomOutAriaLabel() {
|
||||
return this.$primevue.config.locale.aria ? this.$primevue.config.locale.aria.zoomOut : undefined;
|
||||
},
|
||||
closeAriaLabel() {
|
||||
return this.$primevue.config.locale.aria ? this.$primevue.config.locale.aria.close : undefined;
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Portal: Portal
|
||||
},
|
||||
directives: {
|
||||
focustrap: FocusTrap
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.p-image-mask {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.p-image-preview-container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.p-image-preview-indicator {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.p-image-preview-icon {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.p-image-preview-container:hover > .p-image-preview-indicator {
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.p-image-preview-container > img {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.p-image-toolbar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.p-image-action.p-link {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.p-image-preview {
|
||||
transition: transform 0.15s;
|
||||
max-width: 100vw;
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
||||
.p-image-preview-enter-active {
|
||||
transition: all 150ms cubic-bezier(0, 0, 0.2, 1);
|
||||
}
|
||||
.p-image-preview-leave-active {
|
||||
transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.p-image-preview-enter-from,
|
||||
.p-image-preview-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0.7);
|
||||
}
|
||||
</style>
|
9
components/lib/image/package.json
Normal file
9
components/lib/image/package.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"main": "./image.cjs.js",
|
||||
"module": "./image.esm.js",
|
||||
"unpkg": "./image.min.js",
|
||||
"types": "./Image.d.ts",
|
||||
"browser": {
|
||||
"./sfc": "./Image.vue"
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue