mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-11 20:27:43 +02:00
Popups and Tooltips in full screen mode (#8933)
Signed-off-by: Alexander Platov <alexander.platov@hardcoreeng.com>
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
import PopupInstance from './PopupInstance.svelte'
|
||||
|
||||
export let contentPanel: HTMLElement | undefined = undefined
|
||||
export let fullScreen: boolean = false
|
||||
|
||||
const instances: PopupInstance[] = []
|
||||
|
||||
@@ -26,13 +27,21 @@
|
||||
instances.forEach((p) => p.fitPopupInstance())
|
||||
}
|
||||
|
||||
$: instances.length = $popups.filter((p) => p.dock !== true).length
|
||||
const shouldDisplayPopup = (popup: any): boolean => {
|
||||
return (
|
||||
(fullScreen && document.fullscreenElement != null && popup.element !== 'full-centered') ||
|
||||
(!fullScreen && document.fullscreenElement != null && popup.element === 'full-centered') ||
|
||||
(!fullScreen && document.fullscreenElement == null)
|
||||
)
|
||||
}
|
||||
|
||||
$: instances.length = $popups.filter((p) => p.dock !== true && shouldDisplayPopup(p)).length
|
||||
</script>
|
||||
|
||||
{#if $popups.length > 0}
|
||||
<slot name="popup-header" />
|
||||
{/if}
|
||||
{#each $popups.filter((p) => p.dock !== true) as popup, i (popup.id)}
|
||||
{#each $popups.filter((p) => p.dock !== true && shouldDisplayPopup(p)) as popup, i (popup.id)}
|
||||
<PopupInstance
|
||||
bind:this={instances[i]}
|
||||
is={popup.is}
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
import { capitalizeFirstLetter, formatKey } from '../utils'
|
||||
import { testing } from '..'
|
||||
|
||||
export let fullScreen: boolean = false
|
||||
|
||||
let tooltipHTML: HTMLElement
|
||||
let nubHTML: HTMLElement
|
||||
let dir: TooltipAlignment
|
||||
@@ -64,6 +66,8 @@
|
||||
visibility: 'hidden',
|
||||
classList: ''
|
||||
}
|
||||
const shouldHideTooltip = (): boolean =>
|
||||
(fullScreen && document.fullscreenElement == null) || (!fullScreen && document.fullscreenElement != null)
|
||||
|
||||
const clearStyles = (): void => {
|
||||
shown = false
|
||||
@@ -248,6 +252,7 @@
|
||||
}
|
||||
|
||||
const hideTooltip = (): void => {
|
||||
if (shouldHideTooltip()) return
|
||||
if (tooltipHTML) options.visibility = 'hidden'
|
||||
shown = false
|
||||
closeTooltip()
|
||||
@@ -256,7 +261,7 @@
|
||||
$: shownTooltip = $tooltip.element && tooltipHTML
|
||||
|
||||
const whileShow = (ev: MouseEvent): void => {
|
||||
if (!$tooltip.element) return
|
||||
if (!$tooltip.element || shouldHideTooltip()) return
|
||||
const rectP = tooltipHTML.getBoundingClientRect()
|
||||
rect = $tooltip.element.getBoundingClientRect()
|
||||
const dT: number = dir === 'bottom' && $tooltip.kind !== 'submenu' ? 12 : 0
|
||||
@@ -270,12 +275,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: if (kind === 'submenu') {
|
||||
$: if (kind === 'submenu' && !shouldHideTooltip()) {
|
||||
options = fitSubmenu()
|
||||
} else {
|
||||
} else if (!shouldHideTooltip()) {
|
||||
options = fitTooltip(tooltipHTML, clWidth)
|
||||
}
|
||||
afterUpdate(() => {
|
||||
if (shouldHideTooltip()) return
|
||||
if (kind === 'submenu') {
|
||||
options = fitSubmenu()
|
||||
} else {
|
||||
@@ -287,18 +293,6 @@
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if $tooltip.kind === 'popup'}
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
class="modal-overlay antiOverlay"
|
||||
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
|
||||
on:click|stopPropagation|preventDefault={() => {
|
||||
closeTooltip()
|
||||
}}
|
||||
on:keydown|stopPropagation|preventDefault={() => {}}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<svelte:window
|
||||
bind:innerWidth={docWidth}
|
||||
bind:innerHeight={docHeight}
|
||||
@@ -318,48 +312,8 @@
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{#if $tooltip.component && $tooltip.kind !== 'submenu'}
|
||||
<div
|
||||
class="popup-tooltip {options.classList} {$tooltip.style}"
|
||||
class:testing
|
||||
class:shown
|
||||
class:doublePadding={$tooltip.label}
|
||||
use:resizeObserver={(element) => {
|
||||
clWidth = element.clientWidth
|
||||
options = fitTooltip(tooltipHTML, clWidth)
|
||||
}}
|
||||
style:top={options.top}
|
||||
style:bottom={options.bottom}
|
||||
style:left={options.left}
|
||||
style:right={options.right}
|
||||
style:width={options.width}
|
||||
style:height={options.height}
|
||||
style:transform={options.transform}
|
||||
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
|
||||
bind:this={tooltipHTML}
|
||||
>
|
||||
{#if $tooltip.label}
|
||||
<div class="fs-title mb-4">
|
||||
<Label label={$tooltip.label} params={$tooltip.props ?? {}} />
|
||||
</div>
|
||||
{/if}
|
||||
{#if typeof $tooltip.component === 'string'}
|
||||
<Component
|
||||
is={$tooltip.component}
|
||||
props={$tooltip.props}
|
||||
on:update={onUpdate !== undefined ? onUpdate : async () => {}}
|
||||
/>
|
||||
{:else}
|
||||
<svelte:component
|
||||
this={$tooltip.component}
|
||||
{...$tooltip.props}
|
||||
on:tooltip={(evt) => {
|
||||
$modals = [...$modals.filter((t) => t.type !== 'tooltip'), { ...$tooltip, ...evt.detail }]
|
||||
}}
|
||||
on:update={onUpdate !== undefined ? onUpdate : async () => {}}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if !fullScreen}
|
||||
<svg class="svg-mask">
|
||||
<clipPath id="nub-bg">
|
||||
<path
|
||||
@@ -372,83 +326,142 @@
|
||||
/>
|
||||
</clipPath>
|
||||
</svg>
|
||||
{#if !$tooltip.noArrow}
|
||||
{/if}
|
||||
|
||||
{#if (fullScreen && document.fullscreenElement != null) || (!fullScreen && document.fullscreenElement == null)}
|
||||
{#if $tooltip.kind === 'popup'}
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
bind:this={nubHTML}
|
||||
class="modal-overlay antiOverlay"
|
||||
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
|
||||
class="nub {nubDirection ?? ''}"
|
||||
class:testing
|
||||
class:shown
|
||||
on:click|stopPropagation|preventDefault={() => {
|
||||
closeTooltip()
|
||||
}}
|
||||
on:keydown|stopPropagation|preventDefault={() => {}}
|
||||
/>
|
||||
{/if}
|
||||
{:else if $tooltip.label && $tooltip.kind !== 'submenu'}
|
||||
<div
|
||||
class="tooltip {dir ?? ''} {options.classList}"
|
||||
bind:this={tooltipHTML}
|
||||
style:top={options.top}
|
||||
style:bottom={options.bottom}
|
||||
style:left={options.left}
|
||||
style:right={options.right}
|
||||
style:width={options.width}
|
||||
style:height={options.height}
|
||||
style:max-width={options.maxWidth}
|
||||
style:transform={options.transform}
|
||||
style:visibility={options.visibility}
|
||||
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
|
||||
>
|
||||
<span class="label">
|
||||
<Label label={$tooltip.label} params={$tooltip.props ?? {}} />
|
||||
</span>
|
||||
{#if $tooltip.keys !== undefined}
|
||||
<div class="keys">
|
||||
{#each $tooltip.keys as key, i}
|
||||
{#if i !== 0}
|
||||
<div class="mr-1 ml-1">/</div>
|
||||
{/if}
|
||||
{#each formatKey(key) as k, jj}
|
||||
<div class="key">
|
||||
{#each k as kk, j}
|
||||
{#if j !== 0}
|
||||
+
|
||||
{/if}
|
||||
{capitalizeFirstLetter(kk.trim())}
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
{#if $tooltip.component && $tooltip.kind !== 'submenu'}
|
||||
<div
|
||||
class="popup-tooltip {options.classList} {$tooltip.style}"
|
||||
class:testing
|
||||
class:shown
|
||||
class:doublePadding={$tooltip.label}
|
||||
use:resizeObserver={(element) => {
|
||||
clWidth = element.clientWidth
|
||||
options = fitTooltip(tooltipHTML, clWidth)
|
||||
}}
|
||||
style:top={options.top}
|
||||
style:bottom={options.bottom}
|
||||
style:left={options.left}
|
||||
style:right={options.right}
|
||||
style:width={options.width}
|
||||
style:height={options.height}
|
||||
style:transform={options.transform}
|
||||
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
|
||||
bind:this={tooltipHTML}
|
||||
>
|
||||
{#if $tooltip.label}
|
||||
<div class="fs-title mb-4">
|
||||
<Label label={$tooltip.label} params={$tooltip.props ?? {}} />
|
||||
</div>
|
||||
{/if}
|
||||
{#if typeof $tooltip.component === 'string'}
|
||||
<Component
|
||||
is={$tooltip.component}
|
||||
props={$tooltip.props}
|
||||
on:update={onUpdate !== undefined ? onUpdate : async () => {}}
|
||||
/>
|
||||
{:else}
|
||||
<svelte:component
|
||||
this={$tooltip.component}
|
||||
{...$tooltip.props}
|
||||
on:tooltip={(evt) => {
|
||||
$modals = [...$modals.filter((t) => t.type !== 'tooltip'), { ...$tooltip, ...evt.detail }]
|
||||
}}
|
||||
on:update={onUpdate !== undefined ? onUpdate : async () => {}}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if !$tooltip.noArrow}
|
||||
<div
|
||||
bind:this={nubHTML}
|
||||
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
|
||||
class="nub {nubDirection ?? ''}"
|
||||
class:testing
|
||||
class:shown
|
||||
/>
|
||||
{/if}
|
||||
{:else if $tooltip.label && $tooltip.kind !== 'submenu'}
|
||||
<div
|
||||
class="tooltip {dir ?? ''} {options.classList}"
|
||||
bind:this={tooltipHTML}
|
||||
style:top={options.top}
|
||||
style:bottom={options.bottom}
|
||||
style:left={options.left}
|
||||
style:right={options.right}
|
||||
style:width={options.width}
|
||||
style:height={options.height}
|
||||
style:max-width={options.maxWidth}
|
||||
style:transform={options.transform}
|
||||
style:visibility={options.visibility}
|
||||
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
|
||||
>
|
||||
<span class="label">
|
||||
<Label label={$tooltip.label} params={$tooltip.props ?? {}} />
|
||||
</span>
|
||||
{#if $tooltip.keys !== undefined}
|
||||
<div class="keys">
|
||||
{#each $tooltip.keys as key, i}
|
||||
{#if i !== 0}
|
||||
<div class="mr-1 ml-1">/</div>
|
||||
{/if}
|
||||
{#each formatKey(key) as k, jj}
|
||||
<div class="key">
|
||||
{#each k as kk, j}
|
||||
{#if j !== 0}
|
||||
+
|
||||
{/if}
|
||||
{capitalizeFirstLetter(kk.trim())}
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
{/each}
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{:else if $tooltip.kind === 'submenu'}
|
||||
<div
|
||||
class="submenu-container {dir ?? ''} {options.classList}"
|
||||
use:resizeObserver={(element) => {
|
||||
clWidth = element.clientWidth
|
||||
}}
|
||||
style:top={options.top}
|
||||
style:bottom={options.bottom}
|
||||
style:left={options.left}
|
||||
style:right={options.right}
|
||||
style:width={options.width}
|
||||
style:height={options.height}
|
||||
style:transform={options.transform}
|
||||
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
|
||||
bind:this={tooltipHTML}
|
||||
>
|
||||
{#if typeof $tooltip.component === 'string'}
|
||||
<Component
|
||||
is={$tooltip.component}
|
||||
props={$tooltip.props}
|
||||
on:update={onUpdate !== undefined ? onUpdate : async () => {}}
|
||||
/>
|
||||
{:else}
|
||||
<svelte:component
|
||||
this={$tooltip.component}
|
||||
{...$tooltip.props}
|
||||
on:update={onUpdate !== undefined ? onUpdate : async () => {}}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{:else if $tooltip.kind === 'submenu'}
|
||||
<div
|
||||
class="submenu-container {dir ?? ''} {options.classList}"
|
||||
use:resizeObserver={(element) => {
|
||||
clWidth = element.clientWidth
|
||||
}}
|
||||
style:top={options.top}
|
||||
style:bottom={options.bottom}
|
||||
style:left={options.left}
|
||||
style:right={options.right}
|
||||
style:width={options.width}
|
||||
style:height={options.height}
|
||||
style:transform={options.transform}
|
||||
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
|
||||
bind:this={tooltipHTML}
|
||||
>
|
||||
{#if typeof $tooltip.component === 'string'}
|
||||
<Component
|
||||
is={$tooltip.component}
|
||||
props={$tooltip.props}
|
||||
on:update={onUpdate !== undefined ? onUpdate : async () => {}}
|
||||
/>
|
||||
{:else}
|
||||
<svelte:component
|
||||
this={$tooltip.component}
|
||||
{...$tooltip.props}
|
||||
on:update={onUpdate !== undefined ? onUpdate : async () => {}}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -25,12 +25,12 @@
|
||||
IconMoreV,
|
||||
IconUpOutline,
|
||||
ModernButton,
|
||||
PopupInstance,
|
||||
Popup,
|
||||
SplitButton,
|
||||
eventToHTMLElement,
|
||||
showPopup,
|
||||
type AnySvelteComponent,
|
||||
type CompAndProps
|
||||
TooltipInstance
|
||||
} from '@hcengineering/ui'
|
||||
import view, { Action } from '@hcengineering/view'
|
||||
import { getActions } from '@hcengineering/view-resources'
|
||||
@@ -76,7 +76,6 @@
|
||||
let allowCam: boolean = false
|
||||
const allowShare: boolean = true
|
||||
let allowLeave: boolean = false
|
||||
let popup: CompAndProps | undefined = undefined
|
||||
let noLabel: boolean = false
|
||||
|
||||
$: allowCam = $currentRoom?.type === RoomType.Video
|
||||
@@ -100,50 +99,21 @@
|
||||
await leaveRoom($myInfo, $myOffice)
|
||||
}
|
||||
|
||||
function getPopup (component: AnySvelteComponent, e: MouseEvent, props: any = {}): CompAndProps {
|
||||
return {
|
||||
id: 'fsPopup',
|
||||
is: component,
|
||||
props,
|
||||
element: eventToHTMLElement(e),
|
||||
options: { category: 'popup', overlay: true },
|
||||
close: () => {
|
||||
popup = undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function micSettings (e: MouseEvent): void {
|
||||
if (fullScreen) {
|
||||
popup = getPopup(MicSettingPopup, e)
|
||||
} else {
|
||||
showPopup(MicSettingPopup, {}, eventToHTMLElement(e))
|
||||
}
|
||||
showPopup(MicSettingPopup, {}, eventToHTMLElement(e))
|
||||
}
|
||||
|
||||
function camSettings (e: MouseEvent): void {
|
||||
if (fullScreen) {
|
||||
popup = getPopup(CamSettingPopup, e)
|
||||
} else {
|
||||
showPopup(CamSettingPopup, {}, eventToHTMLElement(e))
|
||||
}
|
||||
showPopup(CamSettingPopup, {}, eventToHTMLElement(e))
|
||||
}
|
||||
|
||||
function shareSettings (e: MouseEvent): void {
|
||||
if (fullScreen) {
|
||||
popup = getPopup(ShareSettingPopup, e)
|
||||
} else {
|
||||
showPopup(ShareSettingPopup, {}, eventToHTMLElement(e))
|
||||
}
|
||||
showPopup(ShareSettingPopup, {}, eventToHTMLElement(e))
|
||||
}
|
||||
|
||||
function setAccess (e: MouseEvent): void {
|
||||
if (isOffice(room) && room.person !== me) return
|
||||
if (fullScreen) {
|
||||
popup = getPopup(RoomAccessPopup, e, { room })
|
||||
} else {
|
||||
showPopup(RoomAccessPopup, { room }, eventToHTMLElement(e))
|
||||
}
|
||||
showPopup(RoomAccessPopup, { room }, eventToHTMLElement(e))
|
||||
}
|
||||
|
||||
const me = getCurrentEmployee()
|
||||
@@ -337,20 +307,9 @@
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="extra">
|
||||
{#if popup && fullScreen}
|
||||
<PopupInstance
|
||||
is={popup.is}
|
||||
props={popup.props}
|
||||
element={popup.element}
|
||||
onClose={popup.onClose}
|
||||
onUpdate={popup.onUpdate}
|
||||
zIndex={1}
|
||||
top={true}
|
||||
close={popup.close}
|
||||
overlay={popup.options.overlay}
|
||||
contentPanel={undefined}
|
||||
{popup}
|
||||
/>
|
||||
{#if fullScreen}
|
||||
<Popup fullScreen />
|
||||
<TooltipInstance fullScreen />
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</ControlBarContainer>
|
||||
|
||||
Reference in New Issue
Block a user