diff --git a/resources/themes/backend/assets/css/helpdesk.css b/resources/themes/backend/assets/css/helpdesk.css index 9d32aaa..114f1b5 100755 --- a/resources/themes/backend/assets/css/helpdesk.css +++ b/resources/themes/backend/assets/css/helpdesk.css @@ -2186,3 +2186,104 @@ html:not(.dark) .hd-nav-link.is-active i { max-height: 24px !important; } } + +/* ============================================================ + Legacy Safari / iOS 12 compatibility layer + Keep this at the end so it can provide safe fallbacks for the + modern Tailwind/Flux theme without changing current browsers. + ============================================================ */ +html { + -webkit-text-size-adjust: 100%; + text-size-adjust: 100%; +} +body { + min-height: 100vh; + min-height: -webkit-fill-available; + -webkit-font-smoothing: antialiased; +} +button, +input, +select, +textarea { + font: inherit; +} +button, +a, +input, +select, +textarea { + -webkit-tap-highlight-color: rgba(0,0,0,0); +} + +/* iOS 12 has no flex/grid gap support. These margins are harmless in + modern Safari/Chrome and are cancelled where native gap is available. */ +@supports not (gap: 1rem) { + .hd-btn > * + *, + .hd-action > * + *, + .hd-nav-link > * + * { margin-left: .5rem; } + + .hd-toolbar > * + *, + .hd-dashboard-heading > * + *, + .hd-page-hero > * + * { margin-left: .75rem; } + + @media (max-width: 700px) { + .hd-toolbar > * + *, + .hd-dashboard-heading > * + *, + .hd-page-hero > * + * { + margin-left: 0; + margin-top: .75rem; + } + } +} + +/* Safari 12 fallback before min()/max()/clamp() support. */ +@media (max-width: 1023px) { + .hd-shell-sidebar { + width: 84vw; + max-width: 320px; + } +} + +/* Respect iPhone/iPad safe areas in standalone/full-screen Safari. */ +@supports (padding: env(safe-area-inset-left)) { + .hd-topbar-brand { padding-left: calc(14px + env(safe-area-inset-left)); } + .hd-shell-sidebar { padding-left: env(safe-area-inset-left); } + .hd-shell-main { + padding-left: calc(30px + env(safe-area-inset-left)); + padding-right: calc(30px + env(safe-area-inset-right)); + padding-bottom: calc(34px + env(safe-area-inset-bottom)); + } + @media (max-width: 1023px) { + .hd-shell-main { + padding-left: calc(18px + env(safe-area-inset-left)); + padding-right: calc(18px + env(safe-area-inset-right)); + } + } + @media (max-width: 700px) { + .hd-shell-main { + padding-left: calc(10px + env(safe-area-inset-left)); + padding-right: calc(10px + env(safe-area-inset-right)); + } + } +} + +/* Prevent iOS Safari zooming form controls on focus. */ +@media (max-width: 1023px) { + input, + select, + textarea, + .helpdesk-ticket-form input, + .helpdesk-ticket-form select, + .helpdesk-ticket-form textarea { + font-size: 16px !important; + } +} + +/* Older WebKit needs explicit scrolling momentum on overflow panes. */ +.hd-shell-nav, +.hd-shell-main, +.overflow-auto, +.overflow-y-auto, +.overflow-x-auto { + -webkit-overflow-scrolling: touch; +} diff --git a/resources/themes/backend/assets/js/layout.js b/resources/themes/backend/assets/js/layout.js index 99d220b..9b842b1 100755 --- a/resources/themes/backend/assets/js/layout.js +++ b/resources/themes/backend/assets/js/layout.js @@ -1,56 +1,93 @@ -const STORAGE_KEY = 'helpdesk.sidebar.width'; -const MIN_WIDTH = 220; -const MAX_WIDTH = 420; +/* Helpdesk shell: deliberately ES5-compatible so Safari on iOS 12 can parse it. */ +(function () { + 'use strict'; -function initialiseShell() { - const shell = document.querySelector('[data-hd-shell]'); - const sidebar = document.querySelector('[data-hd-sidebar]'); - const resizer = document.querySelector('[data-hd-sidebar-resizer]'); - if (!shell || !sidebar) return; + var STORAGE_KEY = 'helpdesk.sidebar.width'; + var MIN_WIDTH = 220; + var MAX_WIDTH = 420; - const stored = Number(localStorage.getItem(STORAGE_KEY)); - if (Number.isFinite(stored) && stored >= MIN_WIDTH && stored <= MAX_WIDTH) { - document.documentElement.style.setProperty('--hd-sidebar-width', `${stored}px`); + function each(nodes, callback) { + Array.prototype.forEach.call(nodes || [], callback); } - document.querySelectorAll('[data-hd-sidebar-toggle]').forEach((button) => { - if (button.dataset.hdBound === '1') return; - button.dataset.hdBound = '1'; - button.addEventListener('click', () => document.body.classList.toggle('hd-sidebar-open')); - }); + function setSidebarWidth(width) { + document.documentElement.style.setProperty('--hd-sidebar-width', width + 'px'); + } - sidebar.querySelectorAll('a').forEach((link) => { - link.addEventListener('click', () => document.body.classList.remove('hd-sidebar-open')); - }); + function initialiseShell() { + var shell = document.querySelector('[data-hd-shell]'); + var sidebar = document.querySelector('[data-hd-sidebar]'); + var resizer = document.querySelector('[data-hd-sidebar-resizer]'); + if (!shell || !sidebar) return; - if (!resizer || resizer.dataset.hdBound === '1') return; - resizer.dataset.hdBound = '1'; + try { + var stored = Number(window.localStorage.getItem(STORAGE_KEY)); + if (isFinite(stored) && stored >= MIN_WIDTH && stored <= MAX_WIDTH) setSidebarWidth(stored); + } catch (ignore) {} - resizer.addEventListener('pointerdown', (event) => { - if (window.matchMedia('(max-width: 1023px)').matches) return; - event.preventDefault(); - resizer.setPointerCapture(event.pointerId); - document.body.classList.add('hd-sidebar-resizing'); + each(document.querySelectorAll('[data-hd-sidebar-toggle]'), function (button) { + if (button.getAttribute('data-hd-bound') === '1') return; + button.setAttribute('data-hd-bound', '1'); + button.addEventListener('click', function () { + document.body.classList.toggle('hd-sidebar-open'); + }, false); + }); - const move = (moveEvent) => { - const width = Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, moveEvent.clientX)); - document.documentElement.style.setProperty('--hd-sidebar-width', `${width}px`); - }; - const finish = (upEvent) => { - const value = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--hd-sidebar-width'), 10); - if (Number.isFinite(value)) localStorage.setItem(STORAGE_KEY, String(value)); + each(sidebar.querySelectorAll('a'), function (link) { + if (link.getAttribute('data-hd-close-bound') === '1') return; + link.setAttribute('data-hd-close-bound', '1'); + link.addEventListener('click', function () { + document.body.classList.remove('hd-sidebar-open'); + }, false); + }); + + if (!resizer || resizer.getAttribute('data-hd-bound') === '1') return; + resizer.setAttribute('data-hd-bound', '1'); + + var dragging = false; + + function desktopLayout() { + return window.innerWidth >= 1024; + } + + function move(clientX) { + if (!dragging) return; + var width = Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, clientX)); + setSidebarWidth(width); + } + + function finish() { + if (!dragging) return; + dragging = false; document.body.classList.remove('hd-sidebar-resizing'); - resizer.releasePointerCapture?.(upEvent.pointerId); - resizer.removeEventListener('pointermove', move); - resizer.removeEventListener('pointerup', finish); - resizer.removeEventListener('pointercancel', finish); - }; - resizer.addEventListener('pointermove', move); - resizer.addEventListener('pointerup', finish); - resizer.addEventListener('pointercancel', finish); - }); -} + var value = parseInt(window.getComputedStyle(document.documentElement).getPropertyValue('--hd-sidebar-width'), 10); + try { + if (isFinite(value)) window.localStorage.setItem(STORAGE_KEY, String(value)); + } catch (ignore) {} + } -document.addEventListener('DOMContentLoaded', initialiseShell); -document.addEventListener('livewire:navigated', initialiseShell); -initialiseShell(); + resizer.addEventListener('mousedown', function (event) { + if (!desktopLayout()) return; + event.preventDefault(); + dragging = true; + document.body.classList.add('hd-sidebar-resizing'); + }, false); + document.addEventListener('mousemove', function (event) { move(event.clientX); }, false); + document.addEventListener('mouseup', finish, false); + + resizer.addEventListener('touchstart', function (event) { + if (!desktopLayout() || !event.touches || !event.touches.length) return; + dragging = true; + document.body.classList.add('hd-sidebar-resizing'); + }, { passive: true }); + document.addEventListener('touchmove', function (event) { + if (dragging && event.touches && event.touches.length) move(event.touches[0].clientX); + }, { passive: true }); + document.addEventListener('touchend', finish, false); + document.addEventListener('touchcancel', finish, false); + } + + if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', initialiseShell, false); + else initialiseShell(); + document.addEventListener('livewire:navigated', initialiseShell, false); +}()); diff --git a/resources/themes/backend/views/partials/head.blade.php b/resources/themes/backend/views/partials/head.blade.php index 2a8b8de..9cea570 100644 --- a/resources/themes/backend/views/partials/head.blade.php +++ b/resources/themes/backend/views/partials/head.blade.php @@ -7,7 +7,10 @@ - + + + +