From 584ce62babfae7151c1d01098e01ab3152b296c0 Mon Sep 17 00:00:00 2001 From: mistic100 Date: Sat, 6 Feb 2021 18:49:36 +0100 Subject: [PATCH] Close #466 : Add typings --- package.json | 1 + src/components/Loader.js | 4 +- src/components/Panel.js | 2 +- src/data/constants.js | 4 +- src/index.js | 28 +- src/services/TextureLoader.js | 3 +- src/types/Animation.d.ts | 35 ++ src/types/PSVError.d.ts | 6 + src/types/Viewer.d.ts | 392 ++++++++++++++++++++ src/types/buttons/AbstractButton.d.ts | 56 +++ src/types/components/AbstractComponent.d.ts | 30 ++ src/types/components/Loader.d.ts | 14 + src/types/components/Navbar.d.ts | 30 ++ src/types/components/Notification.d.ts | 15 + src/types/components/Overlay.d.ts | 22 ++ src/types/components/Panel.d.ts | 21 ++ src/types/components/Tooltip.d.ts | 35 ++ src/types/data/config.d.ts | 6 + src/types/data/constants.d.ts | 73 ++++ src/types/data/system.d.ts | 13 + src/types/index.d.ts | 21 ++ src/types/models.d.ts | 122 ++++++ src/types/plugins/AbstractPlugin.d.ts | 21 ++ src/types/services/DataHelper.d.ts | 69 ++++ src/types/services/TextureLoader.d.ts | 13 + src/types/services/TooltipRenderer.d.ts | 15 + src/types/utils/browser.d.ts | 57 +++ src/types/utils/index.d.ts | 6 + src/types/utils/math.d.ts | 36 ++ src/types/utils/misc.d.ts | 58 +++ src/types/utils/psv.d.ts | 40 ++ src/utils/math.js | 2 +- src/utils/misc.js | 2 +- src/utils/psv.js | 2 +- 34 files changed, 1231 insertions(+), 23 deletions(-) create mode 100644 src/types/Animation.d.ts create mode 100644 src/types/PSVError.d.ts create mode 100644 src/types/Viewer.d.ts create mode 100644 src/types/buttons/AbstractButton.d.ts create mode 100644 src/types/components/AbstractComponent.d.ts create mode 100644 src/types/components/Loader.d.ts create mode 100644 src/types/components/Navbar.d.ts create mode 100644 src/types/components/Notification.d.ts create mode 100644 src/types/components/Overlay.d.ts create mode 100644 src/types/components/Panel.d.ts create mode 100644 src/types/components/Tooltip.d.ts create mode 100644 src/types/data/config.d.ts create mode 100644 src/types/data/constants.d.ts create mode 100644 src/types/data/system.d.ts create mode 100644 src/types/index.d.ts create mode 100644 src/types/models.d.ts create mode 100644 src/types/plugins/AbstractPlugin.d.ts create mode 100644 src/types/services/DataHelper.d.ts create mode 100644 src/types/services/TextureLoader.d.ts create mode 100644 src/types/services/TooltipRenderer.d.ts create mode 100644 src/types/utils/browser.d.ts create mode 100644 src/types/utils/index.d.ts create mode 100644 src/types/utils/math.d.ts create mode 100644 src/types/utils/misc.d.ts create mode 100644 src/types/utils/psv.d.ts diff --git a/package.json b/package.json index 03ebe8469..74825abfb 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "A JavaScript library to display Photo Sphere panoramas", "homepage": "https://photo-sphere-viewer.js.org", "main": "dist/photo-sphere-viewer.js", + "types": "src/types/index.d.ts", "files": [ "src/", "dist/" diff --git a/src/components/Loader.js b/src/components/Loader.js index be592015c..a6c15ff7b 100644 --- a/src/components/Loader.js +++ b/src/components/Loader.js @@ -1,5 +1,5 @@ import { SYSTEM } from '../data/system'; -import { getStyle } from '../utils'; +import { bound, getStyle } from '../utils'; import { AbstractComponent } from './AbstractComponent'; /** @@ -110,7 +110,7 @@ export class Loader extends AbstractComponent { context.arc( this.canvas.width / 2, this.canvas.height / 2, this.canvas.width / 2 - this.prop.tickness / 2, - -Math.PI / 2, value / 100 * 2 * Math.PI - Math.PI / 2 + -Math.PI / 2, bound(value, 0, 100) / 100 * 2 * Math.PI - Math.PI / 2 ); context.stroke(); } diff --git a/src/components/Panel.js b/src/components/Panel.js index 7f83df160..7010b2248 100644 --- a/src/components/Panel.js +++ b/src/components/Panel.js @@ -127,7 +127,7 @@ export class Panel extends AbstractComponent { /** * @summary Shows the panel - * @param {Object} config + * @param {string|Object} config * @param {string} [config.id] * @param {string} config.content * @param {boolean} [config.noMargin=false] diff --git a/src/data/constants.js b/src/data/constants.js index 5711f5ec1..abddd7bdd 100644 --- a/src/data/constants.js +++ b/src/data/constants.js @@ -180,13 +180,13 @@ export const EVENTS = { /** * @event hide-notification * @memberof PSV - * @summary Trigered when the notification is hidden + * @summary Triggered when the notification is hidden */ HIDE_NOTIFICATION : 'hide-notification', /** * @event hide-overlay * @memberof PSV - * @summary Trigered when the overlay is hidden + * @summary Triggered when the overlay is hidden * @param {string} [id] */ HIDE_OVERLAY : 'hide-overlay', diff --git a/src/index.js b/src/index.js index d83c63bb2..752ed9647 100644 --- a/src/index.js +++ b/src/index.js @@ -92,6 +92,20 @@ export { * @property {string} back */ +/** + * @typedef {Object} PSV.PanoData + * @summary Crop information of the panorama + * @property {number} fullWidth + * @property {number} fullHeight + * @property {number} croppedWidth + * @property {number} croppedHeight + * @property {number} croppedX + * @property {number} croppedY + * @property {number} poseHeading + * @property {number} posePitch + * @property {number} poseRoll + */ + /** * @callback PanoDataProvider * @summary Function to compute panorama data once the image is loaded @@ -116,20 +130,6 @@ export { * @property {PSV.PanoData} [panoData] */ -/** - * @typedef {Object} PSV.PanoData - * @summary Crop information of the panorama - * @property {number} fullWidth - * @property {number} fullHeight - * @property {number} croppedWidth - * @property {number} croppedHeight - * @property {number} croppedX - * @property {number} croppedY - * @property {number} poseHeading - * @property {number} posePitch - * @property {number} poseRoll - */ - /** * @typedef {Object} PSV.ClickData * @summary Data of the `click` event diff --git a/src/services/TextureLoader.js b/src/services/TextureLoader.js index 4bac90dff..b790b4d10 100644 --- a/src/services/TextureLoader.js +++ b/src/services/TextureLoader.js @@ -76,6 +76,7 @@ export class TextureLoader extends AbstractService { /** * @summary Cancels current HTTP requests + * @package */ abortLoading() { [...this.requests].forEach(r => r.abort()); @@ -375,7 +376,7 @@ export class TextureLoader extends AbstractService { /** * @summary Preload a panorama file without displaying it - * @param {string} panorama + * @param {string|string[]|PSV.Cubemap} panorama * @returns {Promise} */ preloadPanorama(panorama) { diff --git a/src/types/Animation.d.ts b/src/types/Animation.d.ts new file mode 100644 index 000000000..af6f5cff0 --- /dev/null +++ b/src/types/Animation.d.ts @@ -0,0 +1,35 @@ +export type AnimationOptions = { + properties: { [K: string]: { start: number, end: number } }; + duration: number; + delay?: number; + easing?: string | ((progress: number) => number); + onTick: (properties: { [K: string]: number }, progress: number) => void; +}; + +/** + * @summary Interpolation helper for animations + * @description + * Implements the Promise API with an additional "cancel" and "finally" methods. + * The promise is resolved when the animation is complete and rejected if the animation is cancelled. + */ +export class Animation implements Promise { + + constructor(options: AnimationOptions); + + // @ts-ignore + then(onFulfilled?: (() => void | Animation | PromiseLike) | undefined | null, onRejected?: (() => void | Animation | PromiseLike) | undefined | null): Animation; + + // @ts-ignore + catch(onRejected?: (() => void | Animation | PromiseLike) | undefined | null): Animation; + + // @ts-ignore + finally(onFinally?: (() => void | Animation | PromiseLike) | undefined | null): Animation; + + cancel(); + + /** + * @summary Returns a resolved animation promise + */ + static resolve(): Animation; + +} diff --git a/src/types/PSVError.d.ts b/src/types/PSVError.d.ts new file mode 100644 index 000000000..7300a10b1 --- /dev/null +++ b/src/types/PSVError.d.ts @@ -0,0 +1,6 @@ +/** + * @summary Custom error used in the lib + */ +export class PSVError extends Error { + name: 'PSVError'; +} diff --git a/src/types/Viewer.d.ts b/src/types/Viewer.d.ts new file mode 100644 index 000000000..5ff9766a7 --- /dev/null +++ b/src/types/Viewer.d.ts @@ -0,0 +1,392 @@ +import { Vector3 } from 'three'; +import { Event, EventEmitter } from 'uevent'; +import { Animation } from './Animation'; +import { Loader } from './components/Loader'; +import { Navbar } from './components/Navbar'; +import { Notification } from './components/Notification'; +import { Overlay } from './components/Overlay'; +import { Panel } from './components/Panel'; +import { Tooltip } from './components/Tooltip'; +import { + AnimateOptions, + ClickData, + CssSize, + Cubemap, + ExtendedPosition, + NavbarCustomButton, + PanoData, + PanoDataProvider, + PanoramaOptions, + Position, + Size +} from './models'; +import { AbstractPlugin } from './plugins/AbstractPlugin'; +import { DataHelper } from './services/DataHelper'; +import { TextureLoader } from './services/TextureLoader'; +import { TooltipRenderer } from './services/TooltipRenderer'; + +/** + * @summary Viewer options, see {@link http://photo-sphere-viewer.js.org/guide/config.html} + */ +export type ViewerOptions = { + panorama: string; + container: HTMLElement | string; + caption: string; + loadingImg: string; + loadingTxt: string; + size: Size; + fisheye: boolean; + minFov: number; + maxFov: number; + defaultZoomLvl: number; + defaultLong: number; + defaultLat: number; + sphereCorrection: null, + moveSpeed: number; + zoomButtonIncrement: number; + autorotateDelay: null, + autorotateSpeed: string | number; + autorotateLat: number; + moveInertia: boolean; + mousewheel: boolean; + mousewheelSpeed: number; + mousemove: boolean; + captureCursor: boolean; + mousewheelCtrlKey: boolean; + touchmoveTwoFingers: boolean; + useXmpData: boolean; + panoData: PanoData | PanoDataProvider; + canvasBackground: string; + withCredentials: boolean; + navbar: string | Array, + lang: Record, + keyboard: Record, + plugins: Array, +}; + +/** + * Internal properties of the viewer + */ +export type ViewerProps = { + ready: boolean; + uiRefresh: boolean; + needsUpdate: boolean; + fullscreen: boolean; + isCubemap: boolean; + position: Position, + direction: Vector3, + zoomLvl: number; + vFov: number; + hFov: number; + aspect: number; + moveSpeed: number; + autorotateCb: any; + animationPromise: Animation; + loadingPromise: Promise; + startTimeout: any; + size: Size; + panoData: PanoData; +}; + +/** + * Main class + */ +export class Viewer extends EventEmitter { + + /** + * Configuration holder + */ + readonly config: ViewerOptions; + + /** + * Internal properties + */ + prop: ViewerProps; + + /** + * Top most parent + */ + readonly parent: HTMLElement; + + /** + * Main container + */ + readonly container: HTMLElement; + + /** + * Textures loader + */ + readonly textureLoader: TextureLoader; + + /** + * Utilities to help converting data + */ + readonly dataHelper: DataHelper; + + readonly loader: Loader; + + readonly navbar: Navbar; + + readonly panel: Panel; + + readonly tooltip: TooltipRenderer; + + readonly notification: Notification; + + readonly overlay: Overlay; + + /** + * @throws {PSVError} when the configuration is incorrect + */ + constructor(options: ViewerOptions); + + /** + * @summary Destroys the viewer + * @description The memory used by the ThreeJS context is not totally cleared. This will be fixed as soon as possible. + */ + destroy(); + + /** + * @summary Returns the instance of a plugin if it exists + */ + getPlugin(pluginId: string | typeof AbstractPlugin): AbstractPlugin; + + /** + * @summary Returns the current position of the camera + */ + getPosition(): Position; + + /** + * @summary Returns the current zoom level + */ + getZoomLevel(): number; + + /** + * @summary Returns the current viewer size + */ + getSize(): Size; + + /** + * @summary Checks if the automatic rotation is enabled + */ + isAutorotateEnabled(): boolean; + + /** + * @summary Checks if the viewer is in fullscreen + */ + isFullscreenEnabled(): boolean; + + /** + * @summary Flags the view has changed for the next render + */ + needsUpdate(); + + /** + * @summary Resizes the canvas when the window is resized + */ + autoSize(); + + /** + * @summary Loads a new panorama file + * @description Loads a new panorama file, optionally changing the camera position/zoom and activating the transition animation.
+ * If the "options" parameter is not defined, the camera will not move and the ongoing animation will continue.
+ * If another loading is already in progress it will be aborted. + */ + setPanorama(panorama: string | string[] | Cubemap, options?: PanoramaOptions): Promise; + + /** + * @summary Update options + */ + setOptions(options: Partial); + + /** + * @summary Update options + */ + setOption(option: K, value: ViewerOptions[K]); + + /** + * @summary Starts the automatic rotation + */ + startAutorotate(); + + /** + * @summary Stops the automatic rotation + */ + stopAutorotate(); + + /** + * @summary Starts or stops the automatic rotation + */ + toggleAutorotate(); + + /** + * @summary Displays an error message + */ + showError(message: string); + + /** + * @summary Hides the error message + */ + hideError(); + + /** + * @summary Rotates the view to specific longitude and latitude + */ + rotate(position: ExtendedPosition); + + /** + * @summary Rotates and zooms the view with a smooth animation + */ + animate(options: AnimateOptions): Animation; + + /** + * @summary Stops the ongoing animation + * @description The return value is a Promise because the is no guaranty the animation can be stopped synchronously. + */ + stopAnimation(): Promise; + + /** + * @summary Zooms to a specific level between `max_fov` and `min_fov` + */ + zoom(level: number); + + /** + * @summary Increases the zoom level by 1 + */ + zoomIn(); + + /** + * @summary Decreases the zoom level by 1 + */ + zoomOut(); + + /** + * @summary Resizes the viewer + */ + resize(size: CssSize); + + /** + * @summary Enters the fullscreen mode + */ + enterFullscreen(); + + /** + * @summary Exits the fullscreen mode + */ + exitFullscreen(); + + /** + * @summary Enters or exits the fullscreen mode + */ + toggleFullscreen(); + + /** + * @summary Enables the keyboard controls (done automatically when entering fullscreen) + */ + startKeyboardControl(); + + /** + * @summary Disables the keyboard controls (done automatically when exiting fullscreen) + */ + stopKeyboardControl(); + + /** + * @summary Triggered when the automatic rotation is enabled/disabled + */ + on(e: 'autorotate', cb: (e: Event, enabled: true) => void): this; + /** + * @summary Triggered before a render, used to modify the view + */ + on(e: 'before-render', cb: (e: Event, timestamp: number) => void): this; + /** + * @summary Triggered before a rotate operation, can be cancelled + */ + on(e: 'before-rotate', cb: (e: Event, position: ExtendedPosition) => void): this; + /** + * @summary Triggered when the user clicks on the viewer (everywhere excluding the navbar and the side panel) + */ + on(e: 'click', cb: (e: Event, data: ClickData) => void): this; + /** + * @summary Trigered when the panel is closed + */ + on(e: 'close-panel', cb: (e: Event, id: string | undefined) => void): this; + /** + * @summary Triggered after a call to setOption/setOptions + */ + on(e: 'config-changed', cb: (e: Event, options: string[]) => void): this; + /** + * @summary Triggered when the user double clicks on the viewer. The simple `click` event is always fired before `dblclick` + */ + on(e: 'dblclick', cb: (e: Event, data: ClickData) => void): this; + /** + * @summary Triggered when the fullscreen mode is enabled/disabled + */ + on(e: 'fullscreen-updated', cb: (e: Event, enabled: true) => void): this; + /** + * @summary Called to alter the target position of an animation + */ + on(e: 'get-animate-position', cb: (e: Event, position: Position) => Position): this; + /** + * @summary Called to alter the target position of a rotation + */ + on(e: 'get-rotate-position', cb: (e: Event, position: Position) => Position): this; + /** + * @summary Triggered when the notification is hidden + */ + on(e: 'hide-notification', cb: (e: Event) => void): this; + /** + * @summary Triggered when the overlay is hidden + */ + on(e: 'hide-overlay', cb: (e: Event, id: string | undefined) => void): this; + /** + * @summary Trigered when the tooltip is hidden + */ + on(e: 'hide-tooltip', cb: (e: Event, data: any) => void): this; + /** + * @summary Triggered when the panel is opened + */ + on(e: 'open-panel', cb: (e: Event, id: string | undefined) => void): this; + /** + * @summary Triggered when a panorama image has been loaded + */ + on(e: 'panorama-loaded', cb: (e: Event) => void): this; + /** + * @summary Triggered when the view longitude and/or latitude changes + */ + on(e: 'position-updated', cb: (e: Event, position: Position) => void): this; + + /** + * @summary Triggered when the panorama image has been loaded and the viewer is ready to perform the first render + */ + once(e: 'ready', cb: (e: Event) => void): this; + + /** + * @summary Triggered on each viewer render, **this event is triggered very often** + */ + on(e: 'render', cb: (e: Event) => void): this; + /** + * @summary Trigered when the notification is shown + */ + on(e: 'show-notification', cb: (e: Event) => void): this; + /** + * @summary Trigered when the overlay is shown + */ + on(e: 'show-overlay', cb: (e: Event, id: string | undefined) => void): this; + /** + * @summary Trigered when the tooltip is shown + */ + on(e: 'show-tooltip', cb: (e: Event, data: any, tooltip: Tooltip) => void): this; + /** + * @summary Triggered when the viewer size changes + */ + on(e: 'size-updated', cb: (e: Event, size: Size) => void): this; + /** + * @summary Triggered when all current animations are stopped + */ + on(e: 'stop-all', cb: (e: Event) => void): this; + /** + * @summary Triggered when the zoom level changes + */ + on(e: 'zoom-updated', cb: (e: Event, zoom: number) => void): this; + +} diff --git a/src/types/buttons/AbstractButton.d.ts b/src/types/buttons/AbstractButton.d.ts new file mode 100644 index 000000000..aa617fd91 --- /dev/null +++ b/src/types/buttons/AbstractButton.d.ts @@ -0,0 +1,56 @@ +import { AbstractComponent } from '../components/AbstractComponent'; +import { Navbar } from '../components/Navbar'; + +/** + * @summary Base navbar button class + */ +export class AbstractButton extends AbstractComponent { + + /** + * @summary Unique identifier of the button + */ + static id: string; + + /** + * @summary SVG icon name injected in the button + */ + static icon?: string; + + /** + * @summary SVG icon name injected in the button when it is active + */ + static iconActive?: string; + + constructor(navbar: Navbar, className?: string, collapsable?: boolean); + + /** + * @summary Checks if the button can be displayed + */ + isSupported(): boolean | { initial: boolean, promise: Promise }; + + /** + * @summary Changes the active state of the button + */ + toggleActive(active?: boolean); + + /** + * @summary Disables the button + */ + disable(); + + /** + * @summary Enables the button + */ + enable(); + + /** + * @summary Collapses the button in the navbar menu + */ + collapse(); + + /** + * @summary Uncollapses the button from the navbar menu + */ + uncollapse(); + +} diff --git a/src/types/components/AbstractComponent.d.ts b/src/types/components/AbstractComponent.d.ts new file mode 100644 index 000000000..0a2f9c845 --- /dev/null +++ b/src/types/components/AbstractComponent.d.ts @@ -0,0 +1,30 @@ +import { Viewer } from '../Viewer'; + +/** + * @summary Base component class + */ +export class AbstractComponent { + + constructor(parent: Viewer | AbstractComponent, className?: string); + + /** + * @summary Displays the component + */ + show(options?: any); + + /** + * @summary Hides the component + */ + hide(options?: any); + + /** + * @summary Displays or hides the component + */ + toggle(); + + /** + * @summary Check if the component is visible + */ + isVisible(options?: any): boolean; + +} diff --git a/src/types/components/Loader.d.ts b/src/types/components/Loader.d.ts new file mode 100644 index 000000000..6b2186a5b --- /dev/null +++ b/src/types/components/Loader.d.ts @@ -0,0 +1,14 @@ +import { AbstractComponent } from './AbstractComponent'; + +/** + * @summary Loader class + */ +export class Loader extends AbstractComponent { + + /** + * @summary Sets the loader progression + * @param value + */ + setProgress(value: number); + +} diff --git a/src/types/components/Navbar.d.ts b/src/types/components/Navbar.d.ts new file mode 100644 index 000000000..2a45e21ff --- /dev/null +++ b/src/types/components/Navbar.d.ts @@ -0,0 +1,30 @@ +import { AbstractButton } from '../buttons/AbstractButton'; +import { NavbarCustomButton } from '../models'; +import { AbstractComponent } from './AbstractComponent'; + +/** + * @summary Register a new button available for all viewers + */ +export function registerButton(button: typeof AbstractButton); + +/** + * @summary Navigation bar class + */ +export class Navbar extends AbstractComponent { + + /** + * @summary Change the buttons visible on the navbar + */ + setButtons(buttons: string | Array); + + /** + * @summary Sets the bar caption + */ + setCaption(html: string); + + /** + * @summary Returns a button by its identifier + */ + getButton(id: string): AbstractButton; + +} diff --git a/src/types/components/Notification.d.ts b/src/types/components/Notification.d.ts new file mode 100644 index 000000000..6b040321a --- /dev/null +++ b/src/types/components/Notification.d.ts @@ -0,0 +1,15 @@ +import { AbstractComponent } from './AbstractComponent'; + +export type NotificationOptions = { + content: string; + timeout?: number; +}; + +/** + * @summary Notification class + */ +export class Notification extends AbstractComponent { + + show(config: string | NotificationOptions); + +} diff --git a/src/types/components/Overlay.d.ts b/src/types/components/Overlay.d.ts new file mode 100644 index 000000000..3701e0d08 --- /dev/null +++ b/src/types/components/Overlay.d.ts @@ -0,0 +1,22 @@ +import { AbstractComponent } from './AbstractComponent'; + +export type OverlayOptions = { + id?: string; + image: string; + text: string; + subtext?: string; + dissmisable?: boolean; +}; + +/** + * @summary Overlay class + */ +export class Overlay extends AbstractComponent { + + show(config: string | OverlayOptions); + + hide(id?: string); + + isVisible(id?: string): boolean; + +} diff --git a/src/types/components/Panel.d.ts b/src/types/components/Panel.d.ts new file mode 100644 index 000000000..ac620ac7c --- /dev/null +++ b/src/types/components/Panel.d.ts @@ -0,0 +1,21 @@ +import { AbstractComponent } from './AbstractComponent'; + +export type PanelOptions = { + id?: string; + content: string; + noMargin?: boolean; + clickHandler?: (e: MouseEvent) => {}; +}; + +/** + * @summary Panel class + */ +export class Panel extends AbstractComponent { + + show(config: string | PanelOptions); + + hide(id?: string); + + isVisible(id?: string): boolean; + +} diff --git a/src/types/components/Tooltip.d.ts b/src/types/components/Tooltip.d.ts new file mode 100644 index 000000000..d2386737c --- /dev/null +++ b/src/types/components/Tooltip.d.ts @@ -0,0 +1,35 @@ +import { AbstractComponent } from './AbstractComponent'; + +/** + * Object defining the tooltip position + */ +export type TooltipPosition = { + top: number; + left: number; + position?: string | string[]; + box?: { width: number, height: number }; +}; + +/** + * Object defining the tooltip configuration + */ +export type TooltipOptions = TooltipPosition & { + content: string; + className?: string; + data?: any; +}; + +export class Tooltip extends AbstractComponent { + + /** + * Do not call this method directly, use {@link TooltipRenderer} instead. + */ + show(options: TooltipOptions); + + /** + * @summary Moves the tooltip to a new position + * @throws {PSVError} when the configuration is incorrect + */ + move(position: TooltipPosition); + +} diff --git a/src/types/data/config.d.ts b/src/types/data/config.d.ts new file mode 100644 index 000000000..4a6d644a2 --- /dev/null +++ b/src/types/data/config.d.ts @@ -0,0 +1,6 @@ +import { ViewerOptions } from '../Viewer'; + +/** + * @summary Default options + */ +export const DEFAULTS: ViewerOptions; diff --git a/src/types/data/constants.d.ts b/src/types/data/constants.d.ts new file mode 100644 index 000000000..00fdab7f2 --- /dev/null +++ b/src/types/data/constants.d.ts @@ -0,0 +1,73 @@ +export const CONSTANTS: { + ACTIONS: { + ROTATE_LAT_UP: 'rotateLatitudeUp', + ROTATE_LAT_DOWN: 'rotateLatitudeDown', + ROTATE_LONG_RIGHT: 'rotateLongitudeRight', + ROTATE_LONG_LEFT: 'rotateLongitudeLeft', + ZOOM_IN: 'zoomIn', + ZOOM_OUT: 'zoomOut', + TOGGLE_AUTOROTATE: 'toggleAutorotate', + }; + + EVENTS: { + AUTOROTATE: 'autorotate', + BEFORE_RENDER: 'before-render', + BEFORE_ROTATE: 'before-rotate', + CLICK: 'click', + CLOSE_PANEL: 'close-panel', + CONFIG_CHANGED: 'config-changed', + DOUBLE_CLICK: 'dblclick', + FULLSCREEN_UPDATED: 'fullscreen-updated', + HIDE_NOTIFICATION: 'hide-notification', + HIDE_OVERLAY: 'hide-overlay', + HIDE_TOOLTIP: 'hide-tooltip', + OPEN_PANEL: 'open-panel', + PANORAMA_LOADED: 'panorama-loaded', + POSITION_UPDATED: 'position-updated', + READY: 'ready', + RENDER: 'render', + SHOW_NOTIFICATION: 'show-notification', + SHOW_OVERLAY: 'show-overlay', + SHOW_TOOLTIP: 'show-tooltip', + SIZE_UPDATED: 'size-updated', + STOP_ALL: 'stop-all', + ZOOM_UPDATED: 'zoom-updated', + }; + + CHANGE_EVENTS: { + GET_ANIMATE_POSITION: 'get-animate-position', + GET_ROTATE_POSITION: 'get-rotate-position', + }; + + EASINGS: { + linear: (t: number) => number, + + inQuad: (t: number) => number, + outQuad: (t: number) => number, + inOutQuad: (t: number) => number, + + inCubic: (t: number) => number, + outCubic: (t: number) => number, + inOutCubic: (t: number) => number, + + inQuart: (t: number) => number, + outQuart: (t: number) => number, + inOutQuart: (t: number) => number, + + inQuint: (t: number) => number, + outQuint: (t: number) => number, + inOutQuint: (t: number) => number, + + inSine: (t: number) => number, + outSine: (t: number) => number, + inOutSine: (t: number) => number, + + inExpo: (t: number) => number, + outExpo: (t: number) => number, + inOutExpo: (t: number) => number, + + inCirc: (t: number) => number, + outCirc: (t: number) => number, + inOutCirc: (t: number) => number, + }; +}; diff --git a/src/types/data/system.d.ts b/src/types/data/system.d.ts new file mode 100644 index 000000000..093f87f0a --- /dev/null +++ b/src/types/data/system.d.ts @@ -0,0 +1,13 @@ +/** + * @summary General information about the system + */ +export const SYSTEM: { + loaded: boolean; + pixelRatio: number; + isWebGLSupported: boolean; + maxTextureWidth: number; + mouseWheelEvent: string; + fullscreenEvent: string; + getMaxCanvasWidth: () => number; + isTouchEnabled: Promise; +}; diff --git a/src/types/index.d.ts b/src/types/index.d.ts new file mode 100644 index 000000000..14da6979a --- /dev/null +++ b/src/types/index.d.ts @@ -0,0 +1,21 @@ +export as namespace PhotoSphereViewer; + +export * from './models'; +export * from './data/constants'; +export * from './data/config'; +export * from './data/system'; +export * from './buttons/AbstractButton'; +export * from './plugins/AbstractPlugin'; +export * from './Animation'; +export * from './PSVError'; +export * from './components/Navbar'; +export * from './components/Loader'; +export * from './components/Notification'; +export * from './components/Overlay'; +export * from './components/Panel'; +export * from './components/Tooltip'; +export * from './services/DataHelper'; +export * from './services/TextureLoader'; +export * from './services/TooltipRenderer'; +export * from './Viewer'; +export * from './utils/index'; diff --git a/src/types/models.d.ts b/src/types/models.d.ts new file mode 100644 index 000000000..5e2a36462 --- /dev/null +++ b/src/types/models.d.ts @@ -0,0 +1,122 @@ +/** + * Object defining a point + */ +export type Point = { + x: number; + y: number; +} + +/** + * Object defining a size + */ +export type Size = { + width: number; + height: number; +} + +/** + * Object defining a size in CSS (px, % or auto) + */ +export type CssSize = { + width: string; + height: string; +} + +export type SphereCorrection = { + pan?: number; + tilt?: number; + roll?: number; +} + +/** + * Object defining a spherical position + */ +export type Position = { + longitude: number; + latitude: number; +} + +/** + * Object defining a spherical or texture position + */ +export type ExtendedPosition = Position | Point; + +/** + * Object defining animation options + */ +export type AnimateOptions = ExtendedPosition & { + speed: string | number; + zoom?: number; +}; + +/** + * Object defining a cubemap + */ +export type Cubemap = { + top: string; + right: string; + bottom: string; + left: string; + front: string; + back: string; +}; + +/** + * Crop information of the panorama + */ +export type PanoData = { + fullWidth: number; + fullHeight: number; + croppedWidth: number; + croppedHeight: number; + croppedX: number; + croppedY: number; + poseHeading?: number; + posePitch?: number; + poseRoll?: number; +} + +/** + * Function to compute panorama data once the image is loaded + */ +export type PanoDataProvider = (image: HTMLImageElement) => PanoData; + +/** + * Object defining panorama and animation options + */ +export type PanoramaOptions = AnimateOptions & { + transition?: boolean | number; + showLoader?: boolean; + sphereCorrection?: SphereCorrection; + panoData?: PanoData | PanoDataProvider; +}; + +/** + * Data of the `click` event + */ +export type ClickData = { + rightclick: boolean; + clientX: number; + clientY: number; + viewerX: number; + viewerY: number; + longitude: number; + latitude: number; + textureX?: number; + textureY?: number; + marker?: any; +} + +/** + * Definition of a custom navbar button + */ +export type NavbarCustomButton = { + id?: string; + title?: string; + content?: string; + className?: string; + onClick: () => void; + disabled?: boolean; + visible?: boolean; + collapsable?: boolean; +}; diff --git a/src/types/plugins/AbstractPlugin.d.ts b/src/types/plugins/AbstractPlugin.d.ts new file mode 100644 index 000000000..bc2eeae7b --- /dev/null +++ b/src/types/plugins/AbstractPlugin.d.ts @@ -0,0 +1,21 @@ +import { EventEmitter } from 'uevent'; +import { Viewer } from '../Viewer'; + +/** + * @summary Base plugins class + */ +export class AbstractPlugin extends EventEmitter { + + /** + * @summary Unique identifier of the plugin + */ + static id: string; + + constructor(psv: Viewer); + + /** + * @summary Destroys the plugin + */ + destroy(); + +} diff --git a/src/types/services/DataHelper.d.ts b/src/types/services/DataHelper.d.ts new file mode 100644 index 000000000..4708d454d --- /dev/null +++ b/src/types/services/DataHelper.d.ts @@ -0,0 +1,69 @@ +import { Vector3 } from 'three'; +import { ExtendedPosition, Point, Position, SphereCorrection } from '../models'; + +/** + * @summary Collections of data converters for the current viewer + */ +export class DataHelper { + + /** + * @summary Converts vertical FOV to zoom level + */ + fovToZoomLevel(fov: number): number; + + /** + * @summary Converts zoom level to vertical FOV + */ + zoomLevelToFov(level: number): number; + + /** + * @summary Convert vertical FOV to horizontal FOV + */ + vFovToHFov(vFov: number): number; + + /** + * @summary Converts a speed into a duration from current position to a new position + */ + speedToDuration(value: string | number, angle: number): number; + + /** + * @summary Converts pixel texture coordinates to spherical radians coordinates + */ + textureCoordsToSphericalCoords(point: Point): Position; + + /** + * @summary Converts spherical radians coordinates to pixel texture coordinates + */ + sphericalCoordsToTextureCoords(position: Position): Point; + + /** + * @summary Converts spherical radians coordinates to a THREE.Vector3 + */ + sphericalCoordsToVector3(position: Position): Vector3; + + /** + * @summary Converts a THREE.Vector3 to spherical radians coordinates + */ + vector3ToSphericalCoords(vector: Vector3): Position; + + /** + * @summary Converts position on the viewer to a THREE.Vector3 + */ + viewerCoordsToVector3(point: Point): Vector3; + + /** + * @summary Converts a THREE.Vector3 to position on the viewer + */ + vector3ToViewerCoords(vector: Vector3): Point; + + /** + * @summary Converts x/y to latitude/longitude if present and ensure boundaries + */ + cleanPosition(position: ExtendedPosition): Position; + + /** + * @summary Ensure a SphereCorrection object is valid + */ + cleanSphereCorrection(sphere: SphereCorrection): SphereCorrection; + +} diff --git a/src/types/services/TextureLoader.d.ts b/src/types/services/TextureLoader.d.ts new file mode 100644 index 000000000..3945fce56 --- /dev/null +++ b/src/types/services/TextureLoader.d.ts @@ -0,0 +1,13 @@ +import { Cubemap } from '../models'; + +/** + * @summary Texture loader + */ +export class TextureLoader { + + /** + * @summary Preload a panorama file without displaying it + */ + preloadPanorama(panorama: string | string[] | Cubemap): Promise; + +} diff --git a/src/types/services/TooltipRenderer.d.ts b/src/types/services/TooltipRenderer.d.ts new file mode 100644 index 000000000..00587c7a9 --- /dev/null +++ b/src/types/services/TooltipRenderer.d.ts @@ -0,0 +1,15 @@ +import { Tooltip, TooltipOptions } from '../components/Tooltip'; +import { AbstractComponent } from '../components/AbstractComponent'; + +/** + * @summary Tooltip renderer + */ +export class TooltipRenderer extends AbstractComponent { + + /** + * @summary Displays a tooltip on the viewer + * @throws {PSVError} when the configuration is incorrect + */ + create(config: TooltipOptions): Tooltip; + +} diff --git a/src/types/utils/browser.d.ts b/src/types/utils/browser.d.ts new file mode 100644 index 000000000..459e9c0ff --- /dev/null +++ b/src/types/utils/browser.d.ts @@ -0,0 +1,57 @@ +/** + * @summary Toggles a CSS class + */ +export function toggleClass(element: HTMLElement | SVGElement, className: string, active?: boolean); + +/** + * @summary Adds one or several CSS classes to an element + */ +export function addClasses(element: HTMLElement, className: string); + +/** + * @summary Removes one or several CSS classes to an element + */ +export function removeClasses(element: HTMLElement, className: string); + +/** + * @summary Searches if an element has a particular parent at any level including itself + */ +export function hasParent(el: HTMLElement, parent: HTMLElement): boolean; + +/** + * @summary Gets the closest parent (can by itself) + */ +export function getClosest(el: HTMLElement | SVGElement, selector: string): HTMLElement; + +/** + * @summary Returns the key name of a KeyboardEvent + */ +export function getEventKey(evt: KeyboardEvent): string; + +/** + * @summary Detects if fullscreen is enabled + */ +export function isFullscreenEnabled(elt: HTMLElement): boolean; + +/** + * @summary Enters fullscreen mode + */ +export function requestFullscreen(elt: HTMLElement); + +/** + * @summary Exits fullscreen mode + */ +export function exitFullscreen(); + +/** + * @summary Gets an element style + */ +export function getStyle(elt: HTMLElement, prop: string): any; + +/** + * @summary Normalize mousewheel values accross browsers + * @description From Facebook's Fixed Data Table + * {@link https://github.com/facebookarchive/fixed-data-table/blob/master/src/vendor_upstream/dom/normalizeWheel.js} + * @copyright Facebook + */ +export function normalizeWheel(event: WheelEvent): { spinX: number, spinY: number, pixelX: number, pixelY: number }; diff --git a/src/types/utils/index.d.ts b/src/types/utils/index.d.ts new file mode 100644 index 000000000..71729bc59 --- /dev/null +++ b/src/types/utils/index.d.ts @@ -0,0 +1,6 @@ +export as namespace utils; + +export * from './browser.js'; +export * from './math.js'; +export * from './misc.js'; +export * from './psv.js'; diff --git a/src/types/utils/math.d.ts b/src/types/utils/math.d.ts new file mode 100644 index 000000000..de9db6ff8 --- /dev/null +++ b/src/types/utils/math.d.ts @@ -0,0 +1,36 @@ +import { Point, Position } from '../models'; + +/** + * @summary Ensures that a number is in a given interval + */ +export function bound(x: number, min: number, max: number): number; + +/** + * @summary Checks if a value is an integer + */ +export function isInteger(value: any): boolean; + +/** + * @summary Computes the sum of an array + */ +export function sum(array: number[]): number; + +/** + * @summary Computes the distance between two points + */ +export function distance(p1: Point, p2: Point): number; + +/** + * @summary Compute the shortest offset between two longitudes + */ +export function getShortestArc(from: number, to: number): number; + +/** + * @summary Computes the angle between the current position and a target position + */ +export function getAngle(position1: Position, position2: Position): number; + +/** + * @summary Returns the distance between two points on a sphere of radius one + */ +export function greatArcDistance(p1: number[], p2: number[]): number; diff --git a/src/types/utils/misc.d.ts b/src/types/utils/misc.d.ts new file mode 100644 index 000000000..feb96cfc8 --- /dev/null +++ b/src/types/utils/misc.d.ts @@ -0,0 +1,58 @@ +/** + * @summary Transforms a string to dash-case {@link https://github.com/shahata/dasherize} + */ + +export function dasherize(str: string): string; + +/** + * @summary Returns a function, that, when invoked, will only be triggered at most once during a given window of time. + * @copyright underscore.js - modified by Clément Prévost {@link http://stackoverflow.com/a/27078401} + */ +export function throttle(func: Function, wait: number): Function; + +/** + * @summary Test if an object is a plain object + * @description Test if an object is a plain object, i.e. is constructed + * by the built-in Object constructor and inherits directly from Object.prototype + * or null. Some built-in objects pass the test, e.g. Math which is a plain object + * and some host or exotic objects may pass also. + * {@link http://stackoverflow.com/a/5878101/1207670} + */ +export function isPlainObject(obj: any): boolean; + +/** + * @summary Merges the enumerable attributes of two objects + * @description Replaces arrays and alters the target object. + * @copyright Nicholas Fisher + */ +export function deepmerge(target: object, src: object): object; + +/** + * @summary Deeply clones an object + */ +export function clone(src: object): object; + +/** + * @summery Test of an object is empty + */ +export function isEmpty(obj: object): boolean; + +/** + * @summary Loops over enumerable properties of an object + */ +export function each(object: object, callback: (value: any, key: string) => void); + +/** + * @summary Returns the intersection between two arrays + */ +export function intersect(array1: T[], array2: T[]): T[]; + +/** + * @summary Returns if a valu is null or undefined + */ +export function isNil(val: any): val is null | undefined; + +/** + * @summary Returns the first non null non undefined parameter + */ +export function firstNonNull(...values: any[]): any; diff --git a/src/types/utils/psv.d.ts b/src/types/utils/psv.d.ts new file mode 100644 index 000000000..87364276e --- /dev/null +++ b/src/types/utils/psv.d.ts @@ -0,0 +1,40 @@ +import { ExtendedPosition, Point } from '../models'; + +/** + * @summary Displays a warning in the console + */ +export function logWarn(message: string); + +/** + * @summary Checks if an object is a {PSV.ExtendedPosition}, ie has x/y or longitude/latitude + */ +export function isExtendedPosition(object: any): object is ExtendedPosition; + +/** + * @summary Returns the value of a given attribute in the panorama metadata + */ +export function getXMPValue(data: string, attr: string): number | null; + +/** + * @summary Translate CSS values like "top center" or "10% 50%" as top and left positions + * @description The implementation is as close as possible to the "background-position" specification + * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/background-position} + */ +export function parsePosition(value: string | Point): Point; + +/** + * @summary Parses an speed + * @param speed - The speed, in radians/degrees/revolutions per second/minute + * @returns radians per second + * @throws {PSVError} when the speed cannot be parsed + */ +export function parseSpeed(speed: string | number): number; + +/** + * @summary Parses an angle value in radians or degrees and returns a normalized value in radians + * @param {string|number} angle - eg: 3.14, 3.14rad, 180deg + * @param {boolean} [zeroCenter=false] - normalize between -Pi - Pi instead of 0 - 2*Pi + * @param {boolean} [halfCircle=zeroCenter] - normalize between -Pi/2 - Pi/2 instead of -Pi - Pi + * @throws {PSVError} when the angle cannot be parsed + */ +export function parseAngle(angle: string | number, zeroCenter?: boolean, halfCircle?: boolean): number; diff --git a/src/utils/math.js b/src/utils/math.js index b4323be2b..d99615885 100644 --- a/src/utils/math.js +++ b/src/utils/math.js @@ -83,7 +83,7 @@ export function getAngle(position1, position2) { } /** - * Returns the distance between two points on a sphere of radius one + * @summary Returns the distance between two points on a sphere of radius one * @memberOf PSV.utils * @param {number[]} p1 * @param {number[]} p2 diff --git a/src/utils/misc.js b/src/utils/misc.js index a20e750f4..8bb46013f 100644 --- a/src/utils/misc.js +++ b/src/utils/misc.js @@ -1,5 +1,5 @@ /** - * @summary Transforms a string to dash-case{@link https://github.com/shahata/dasherize} + * @summary Transforms a string to dash-case {@link https://github.com/shahata/dasherize} * @memberOf PSV.utils * @param {string} str * @returns {string} diff --git a/src/utils/psv.js b/src/utils/psv.js index a33ebb083..4f461494c 100644 --- a/src/utils/psv.js +++ b/src/utils/psv.js @@ -66,7 +66,7 @@ const CSS_POSITIONS = { * @memberOf PSV.utils * @description The implementation is as close as possible to the "background-position" specification * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/background-position} - * @param {string|object} value + * @param {string|PSV.Point} value * @returns {PSV.Point} */ export function parsePosition(value) {