mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-23 19:44:59 +03:00
Replace Modal with Popup (#119)
Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
parent
97798f0097
commit
f57711e9e9
@ -16,12 +16,12 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Component from './Component.svelte'
|
import Component from './Component.svelte'
|
||||||
import type { AnySvelteComponent, AnyComponent } from '../types'
|
import type { AnySvelteComponent, AnyComponent, PopupAlignment } from '../types'
|
||||||
import { closePopup } from '..'
|
import { closePopup } from '..'
|
||||||
|
|
||||||
export let is: AnyComponent | AnySvelteComponent
|
export let is: AnyComponent | AnySvelteComponent
|
||||||
export let props: object
|
export let props: object
|
||||||
export let element: HTMLElement | undefined
|
export let element: PopupAlignment | undefined
|
||||||
export let onClose: (result: any) => void | undefined
|
export let onClose: (result: any) => void | undefined
|
||||||
export let zIndex: number
|
export let zIndex: number
|
||||||
|
|
||||||
@ -37,6 +37,7 @@ function close(ev: CustomEvent) {
|
|||||||
$: {
|
$: {
|
||||||
if (modalHTML) {
|
if (modalHTML) {
|
||||||
if (element) {
|
if (element) {
|
||||||
|
if (typeof element !== 'string') {
|
||||||
const rect = element.getBoundingClientRect()
|
const rect = element.getBoundingClientRect()
|
||||||
if (rect.top > document.body.clientHeight - rect.bottom) {
|
if (rect.top > document.body.clientHeight - rect.bottom) {
|
||||||
modalHTML.style.bottom = `calc(${document.body.clientHeight - rect.top}px + .75rem)`
|
modalHTML.style.bottom = `calc(${document.body.clientHeight - rect.top}px + .75rem)`
|
||||||
@ -48,16 +49,20 @@ $: {
|
|||||||
} else {
|
} else {
|
||||||
modalHTML.style.left = rect.left + 'px'
|
modalHTML.style.left = rect.left + 'px'
|
||||||
}
|
}
|
||||||
} else {
|
} else if (element === 'right') {
|
||||||
modalHTML.style.top = '4rem'
|
modalHTML.style.top = '4rem'
|
||||||
modalHTML.style.bottom = '4rem'
|
modalHTML.style.bottom = '4rem'
|
||||||
modalHTML.style.right = '4rem'
|
modalHTML.style.right = '4rem'
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
modalHTML.style.top = '50%'
|
||||||
|
modalHTML.style.left = '50%'
|
||||||
|
modalHTML.style.transform = 'translate(-50%, -50%)'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<div class="popup" bind:this={modalHTML} style={`z-index: ${zIndex + 1};`}>
|
<div class="popup" bind:this={modalHTML} style={`z-index: ${zIndex + 1};`}>
|
||||||
{#if typeof(is) === 'string'}
|
{#if typeof(is) === 'string'}
|
||||||
<Component is={is} props={props} on:close={close}/>
|
<Component is={is} props={props} on:close={close}/>
|
||||||
|
@ -61,7 +61,7 @@ export { default as IconComments } from './components/icons/Comments.svelte'
|
|||||||
|
|
||||||
export * from './utils'
|
export * from './utils'
|
||||||
|
|
||||||
import type { AnySvelteComponent, AnyComponent } from './types'
|
import type { AnySvelteComponent, AnyComponent, PopupAlignment } from './types'
|
||||||
import { writable } from 'svelte/store'
|
import { writable } from 'svelte/store'
|
||||||
|
|
||||||
export function createApp (target: HTMLElement): SvelteComponent {
|
export function createApp (target: HTMLElement): SvelteComponent {
|
||||||
@ -71,7 +71,7 @@ export function createApp (target: HTMLElement): SvelteComponent {
|
|||||||
interface CompAndProps {
|
interface CompAndProps {
|
||||||
is: AnySvelteComponent | AnyComponent | undefined
|
is: AnySvelteComponent | AnyComponent | undefined
|
||||||
props: any
|
props: any
|
||||||
element?: HTMLElement
|
element?: PopupAlignment
|
||||||
onClose?: (result: any) => void
|
onClose?: (result: any) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,17 +80,9 @@ export const store = writable<CompAndProps>({
|
|||||||
props: {},
|
props: {},
|
||||||
})
|
})
|
||||||
|
|
||||||
export function showModal (component: AnySvelteComponent | AnyComponent, props: any, element?: HTMLElement): void {
|
|
||||||
store.set({ is: component, props, element: element })
|
|
||||||
}
|
|
||||||
|
|
||||||
export function closeModal (): void {
|
|
||||||
store.set({ is: undefined, props: {}, element: undefined })
|
|
||||||
}
|
|
||||||
|
|
||||||
export const popupstore = writable<CompAndProps[]>([])
|
export const popupstore = writable<CompAndProps[]>([])
|
||||||
|
|
||||||
export function showPopup (component: AnySvelteComponent | AnyComponent, props: any, element?: HTMLElement, onClose?: (result: any) => void): void {
|
export function showPopup (component: AnySvelteComponent | AnyComponent, props: any, element?: PopupAlignment, onClose?: (result: any) => void): void {
|
||||||
popupstore.update(popups => {
|
popupstore.update(popups => {
|
||||||
popups.push({ is: component, props, element, onClose })
|
popups.push({ is: component, props, element, onClose })
|
||||||
return popups
|
return popups
|
||||||
|
@ -53,3 +53,5 @@ export interface Tab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type TabModel = Tab[]
|
export type TabModel = Tab[]
|
||||||
|
|
||||||
|
export type PopupAlignment = HTMLElement | 'right'
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
import type { Ref, Space, Doc } from '@anticrm/core'
|
import type { Ref, Space, Doc } from '@anticrm/core'
|
||||||
import { generateId } from '@anticrm/core'
|
import { generateId } from '@anticrm/core'
|
||||||
import { EditBox, Button, CircleButton, Grid, Label, showModal, Link, showPopup } from '@anticrm/ui'
|
import { EditBox, Button, CircleButton, Grid, Label, Link, showPopup } from '@anticrm/ui'
|
||||||
import type { AnyComponent } from '@anticrm/ui'
|
import type { AnyComponent } from '@anticrm/ui'
|
||||||
import { getClient } from '@anticrm/presentation'
|
import { getClient } from '@anticrm/presentation'
|
||||||
|
|
||||||
@ -117,7 +117,7 @@
|
|||||||
on:dragleave={ () => { dragover = false } }
|
on:dragleave={ () => { dragover = false } }
|
||||||
on:drop|preventDefault|stopPropagation={drop}>
|
on:drop|preventDefault|stopPropagation={drop}>
|
||||||
<div class="flex-row-center main-content">
|
<div class="flex-row-center main-content">
|
||||||
<div class="avatar" on:click|stopPropagation={() => showModal(AvatarEditor, { label: 'Profile photo' })}><User /></div>
|
<div class="avatar" on:click|stopPropagation={() => showPopup(AvatarEditor, { label: 'Profile photo' })}><User /></div>
|
||||||
<div class="flex-col">
|
<div class="flex-col">
|
||||||
<div class="name">
|
<div class="name">
|
||||||
<EditBox placeholder="John" bind:value={newValue.firstName} on:input={isChanged} focus={create}/>
|
<EditBox placeholder="John" bind:value={newValue.firstName} on:input={isChanged} focus={create}/>
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import type { Ref, Space, Doc } from '@anticrm/core'
|
import type { Ref, Space, Doc } from '@anticrm/core'
|
||||||
import { Dialog, Tabs } from '@anticrm/ui'
|
import { Tabs } from '@anticrm/ui'
|
||||||
import { getClient } from '@anticrm/presentation'
|
import { getClient } from '@anticrm/presentation'
|
||||||
import type { Candidate } from '@anticrm/recruit'
|
import type { Candidate } from '@anticrm/recruit'
|
||||||
import DialogHeader from './DialogHeader.svelte'
|
import DialogHeader from './DialogHeader.svelte'
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
|
||||||
function onClick(object: Doc) {
|
function onClick(object: Doc) {
|
||||||
showPopup(open, { object, space })
|
showPopup(open, { object, space }, 'right')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
<!--
|
|
||||||
// Copyright © 2020 Anticrm Platform Contributors.
|
|
||||||
//
|
|
||||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License. You may
|
|
||||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
//
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
-->
|
|
||||||
<script lang="ts">
|
|
||||||
import { store as modal } from '@anticrm/ui'
|
|
||||||
import { Component } from '@anticrm/ui'
|
|
||||||
|
|
||||||
let modalHTML: HTMLElement
|
|
||||||
let modalOHTML: HTMLElement
|
|
||||||
|
|
||||||
function close () {
|
|
||||||
modalHTML.style.animationDirection = modalOHTML.style.animationDirection = 'reverse'
|
|
||||||
modalHTML.style.animationDuration = modalOHTML.style.animationDuration = '.2s'
|
|
||||||
modal.set({ is: undefined, props: {}, element: undefined })
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleKeydown (ev: KeyboardEvent) {
|
|
||||||
if (ev.key === 'Escape' && $modal.is) {
|
|
||||||
close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStyle (element: HTMLElement | undefined) {
|
|
||||||
if (element) {
|
|
||||||
const rect = element.getBoundingClientRect()
|
|
||||||
return `top: ${rect.top + rect.height + 2}px; left: ${rect.left}px;`
|
|
||||||
} else {
|
|
||||||
return 'top: 50%; left: 50%; transform: translate(-50%, -50%);'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<svelte:window on:keydown={handleKeydown} />
|
|
||||||
|
|
||||||
{#if $modal.is}
|
|
||||||
<div class="modal" class:top-arrow={$modal.element} bind:this={modalHTML} style={getStyle($modal.element)}>
|
|
||||||
{#if typeof($modal.is) === 'string'}
|
|
||||||
<Component is={$modal.is} props={$modal.props} on:close={close}/>
|
|
||||||
{:else}
|
|
||||||
<svelte:component this={$modal.is} {...$modal.props} on:close={close} />
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
<div bind:this={modalOHTML} class="modal-overlay" />
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
@keyframes show {
|
|
||||||
from { opacity: 0; filter: blur(3px); }
|
|
||||||
99% { opacity: 1; filter: blur(0px); }
|
|
||||||
to { filter: none; }
|
|
||||||
}
|
|
||||||
@keyframes showOverlay {
|
|
||||||
from { backdrop-filter: blur(0px); }
|
|
||||||
to { backdrop-filter: blur(1px); }
|
|
||||||
}
|
|
||||||
.modal {
|
|
||||||
position: fixed;
|
|
||||||
background: transparent;
|
|
||||||
z-index: 1001;
|
|
||||||
animation: show .2s ease-in-out forwards;
|
|
||||||
}
|
|
||||||
.modal-overlay {
|
|
||||||
z-index: 1000;
|
|
||||||
background: rgba(0, 0, 0, .5);
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
animation: showOverlay .2s ease-in-out forwards;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -26,7 +26,6 @@
|
|||||||
import workbench from '@anticrm/workbench'
|
import workbench from '@anticrm/workbench'
|
||||||
|
|
||||||
import Navigator from './Navigator.svelte'
|
import Navigator from './Navigator.svelte'
|
||||||
import Modal from './Modal.svelte'
|
|
||||||
import SpaceHeader from './SpaceHeader.svelte'
|
import SpaceHeader from './SpaceHeader.svelte'
|
||||||
import SpaceView from './SpaceView.svelte'
|
import SpaceView from './SpaceView.svelte'
|
||||||
|
|
||||||
@ -92,7 +91,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- <div class="aside"><Chat thread/></div> -->
|
<!-- <div class="aside"><Chat thread/></div> -->
|
||||||
</div>
|
</div>
|
||||||
<Modal />
|
|
||||||
<Popup />
|
<Popup />
|
||||||
{:else}
|
{:else}
|
||||||
No client
|
No client
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
import { IconAdd } from '@anticrm/ui'
|
import { IconAdd } from '@anticrm/ui'
|
||||||
import { getClient, createQuery } from '@anticrm/presentation'
|
import { getClient, createQuery } from '@anticrm/presentation'
|
||||||
import { showModal } from '@anticrm/ui'
|
import { showPopup } from '@anticrm/ui'
|
||||||
|
|
||||||
import { classIcon } from '../../utils'
|
import { classIcon } from '../../utils'
|
||||||
|
|
||||||
@ -42,7 +42,7 @@
|
|||||||
label: model.addSpaceLabel,
|
label: model.addSpaceLabel,
|
||||||
icon: IconAdd,
|
icon: IconAdd,
|
||||||
action: async (): Promise<void> => {
|
action: async (): Promise<void> => {
|
||||||
showModal(model.createComponent, {})
|
showPopup(model.createComponent, {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user