From 13ea206eabaf096d9a595db9b665f893a0f7547d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marina=20L=C3=B3pez?= Date: Mon, 30 Sep 2024 11:46:28 +0200 Subject: [PATCH] chore: allow user to resize modal window --- .../plugins-runtime/src/lib/assets/resize.svg | 1 + .../src/lib/create-modal.spec.ts | 6 +-- libs/plugins-runtime/src/lib/create-modal.ts | 14 ++++-- libs/plugins-runtime/src/lib/drag-handler.ts | 4 +- .../src/lib/modal/plugin-modal.ts | 16 +++++-- .../src/lib/modal/plugin.modal.css | 45 ++++++++++++++++--- 6 files changed, 66 insertions(+), 20 deletions(-) create mode 100644 libs/plugins-runtime/src/lib/assets/resize.svg diff --git a/libs/plugins-runtime/src/lib/assets/resize.svg b/libs/plugins-runtime/src/lib/assets/resize.svg new file mode 100644 index 0000000..bfcebe5 --- /dev/null +++ b/libs/plugins-runtime/src/lib/assets/resize.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libs/plugins-runtime/src/lib/create-modal.spec.ts b/libs/plugins-runtime/src/lib/create-modal.spec.ts index 7cabbce..41b3775 100644 --- a/libs/plugins-runtime/src/lib/create-modal.spec.ts +++ b/libs/plugins-runtime/src/lib/create-modal.spec.ts @@ -44,10 +44,6 @@ describe('createModal', () => { '--modal-block-start', '40px' ); - expect(modal.style.setProperty).toHaveBeenCalledWith( - '--modal-inline-end', - '320px' - ); expect(modal.setAttribute).toHaveBeenCalledWith('title', 'Test Modal'); expect(modal.setAttribute).toHaveBeenCalledWith( @@ -83,7 +79,7 @@ describe('createModal', () => { options ); - const expectedWidth = 680; // 1000 - 320 (initialPosition.inlineEnd) + const expectedWidth = 710; // 1000 - 270 (initialPosition.inlineEnd) const expectedHeight = 760; // 800 - 40 (initialPosition.blockStart) expect(modal.setAttribute).toHaveBeenCalledWith( diff --git a/libs/plugins-runtime/src/lib/create-modal.ts b/libs/plugins-runtime/src/lib/create-modal.ts index 0df0911..6861ac2 100644 --- a/libs/plugins-runtime/src/lib/create-modal.ts +++ b/libs/plugins-runtime/src/lib/create-modal.ts @@ -18,9 +18,16 @@ export function createModal( const defaultWidth = 335; const defaultHeight = 590; + const maxWidth = + (options?.width ?? defaultWidth) > window.innerWidth + ? window.innerWidth - 290 + : options?.width ?? defaultWidth; + const initialPosition = { blockStart: 40, - inlineEnd: 320, + // To be able to resize the element as expected the position must be absolute from the right. + // This value is the length of the window minus the width of the element plus the width of the design tab. + inlineStart: window.innerWidth - maxWidth - 290, }; modal.style.setProperty( @@ -28,11 +35,10 @@ export function createModal( `${initialPosition.blockStart}px` ); modal.style.setProperty( - '--modal-inline-end', - `${initialPosition.inlineEnd}px` + '--modal-inline-start', + `${initialPosition.inlineStart}px` ); - const maxWidth = window.innerWidth - initialPosition.inlineEnd; const maxHeight = window.innerHeight - initialPosition.blockStart; let width = Math.min(options?.width || defaultWidth, maxWidth); let height = Math.min(options?.height || defaultHeight, maxHeight); diff --git a/libs/plugins-runtime/src/lib/drag-handler.ts b/libs/plugins-runtime/src/lib/drag-handler.ts index 4a1dc2e..dad4b2b 100644 --- a/libs/plugins-runtime/src/lib/drag-handler.ts +++ b/libs/plugins-runtime/src/lib/drag-handler.ts @@ -1,4 +1,4 @@ -export const dragHandler = (el: HTMLElement, move?: () => void) => { +export const dragHandler = (el: HTMLElement, target: HTMLElement = el, move?: () => void) => { let currentTranslate = { x: 0, y: 0 }; let initialTranslate = { x: 0, y: 0 }; let initialClientPosition = { x: 0, y: 0 }; @@ -10,7 +10,7 @@ export const dragHandler = (el: HTMLElement, move?: () => void) => { currentTranslate = { x: deltaX, y: deltaY }; - el.style.transform = `translate(${deltaX}px, ${deltaY}px)`; + target.style.transform = `translate(${deltaX}px, ${deltaY}px)`; move?.(); }; diff --git a/libs/plugins-runtime/src/lib/modal/plugin-modal.ts b/libs/plugins-runtime/src/lib/modal/plugin-modal.ts index c13423f..cad1868 100644 --- a/libs/plugins-runtime/src/lib/modal/plugin-modal.ts +++ b/libs/plugins-runtime/src/lib/modal/plugin-modal.ts @@ -12,6 +12,7 @@ export class PluginModalElement extends HTMLElement { } #wrapper: HTMLElement | null = null; + #inner: HTMLElement | null = null; #dragEvents: ReturnType | null = null; setTheme(theme: Theme) { @@ -54,12 +55,20 @@ export class PluginModalElement extends HTMLElement { } this.#wrapper = document.createElement('div'); + this.#inner = document.createElement('div'); + + this.#inner.classList.add('inner'); + this.#wrapper.classList.add('wrapper'); this.#wrapper.style.inlineSize = `${width}px`; + this.#wrapper.style.minInlineSize = `${width}px`; this.#wrapper.style.blockSize = `${height}px`; + this.#wrapper.style.minBlockSize = `${height}px`; + this.#wrapper.style.maxInlineSize = '90vw'; + this.#wrapper.style.maxBlockSize = '90vh'; // move modal to the top - this.#dragEvents = dragHandler(this.#wrapper, () => { + this.#dragEvents = dragHandler(this.#inner, this.#wrapper, () => { this.calculateZIndex(); }); @@ -124,8 +133,9 @@ export class PluginModalElement extends HTMLElement { this.shadowRoot.appendChild(this.#wrapper); - this.#wrapper.appendChild(header); - this.#wrapper.appendChild(iframe); + this.#wrapper.appendChild(this.#inner); + this.#inner.appendChild(header); + this.#inner.appendChild(iframe); const style = document.createElement('style'); style.textContent = modalCss; diff --git a/libs/plugins-runtime/src/lib/modal/plugin.modal.css b/libs/plugins-runtime/src/lib/modal/plugin.modal.css index 195a540..4ac13c4 100644 --- a/libs/plugins-runtime/src/lib/modal/plugin.modal.css +++ b/libs/plugins-runtime/src/lib/modal/plugin.modal.css @@ -25,18 +25,51 @@ color: var(--color-foreground-secondary); } +::-webkit-resizer { + display: none; +} + .wrapper { - box-sizing: border-box; - display: flex; - flex-direction: column; - position: fixed; + position: absolute; inset-block-start: var(--modal-block-start); - inset-inline-end: var(--modal-inline-end); + inset-inline-start: var(--modal-inline-start); z-index: 1000; - padding: 25px; + padding: 10px; border-radius: 15px; border: 2px solid var(--color-background-quaternary); box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.3); + overflow: hidden; + min-inline-size: 25px; + min-block-size: 200px; + resize: both; + &:after { + content: ''; + cursor: se-resize; + inline-size: 1rem; + block-size: 1rem; + background-image: url('../assets/resize.svg'); + background-position: center; + right: 5px; + bottom: 5px; + pointer-events: none; + position: absolute; + } +} + +.inner { + padding: 10px; + cursor: grab; + box-sizing: border-box; + display: flex; + flex-direction: column; + overflow: hidden; + block-size: 100%; + & > * { + flex: 1; + } + & > .header { + flex: 0; + } } .header {