All changes are gated behind max-md:/md:hidden so the >=768px desktop layout is untouched (verified with lint + build + live checks at 375px). - globals.css: one mobile block — 16px inputs (no iOS auto-zoom), units sidebar stacks above content, wizard item rows become 2-col (text fields full-width, delete button full-width), dd-panels / flow diagram / conv-form stack, larger touch targets - ui/dialog.tsx: dialogs become full-width bottom sheets on mobile (all modals inherit it); desktop keeps the centered dialog - Header: sticky on mobile only + PageLayout bottom clearance - New MobileTabBar: role-aware bottom tabs (office admin/manager, inventory PM, inventory admin); hidden on /wizard - Wizard step 4: TouchSensor (150ms delay) so touch drag works without stealing scroll - JalaliDatePicker: dropdown capped to viewport; bigger day cells and time inputs on mobile - PWA: manifest.webmanifest + 192/512 icons (scripts/gen-pwa-icons.ps1) + theme-color/manifest links in index.html - New docs/mobile-responsive.md documenting the full change set
59 lines
2.6 KiB
PowerShell
59 lines
2.6 KiB
PowerShell
# Generate PWA icons (192px / 512px) — indigo rounded square + white clipboard glyph
|
|
Add-Type -AssemblyName System.Drawing
|
|
Add-Type -AssemblyName System.Drawing.Drawing2D
|
|
|
|
function Make-RoundedRect([float]$x, [float]$y, [float]$w, [float]$h, [float]$r) {
|
|
$p = New-Object System.Drawing.Drawing2D.GraphicsPath
|
|
$d = 2 * $r
|
|
$p.AddArc($x, $y, $d, $d, 180, 90)
|
|
$p.AddArc($x + $w - $d, $y, $d, $d, 270, 90)
|
|
$p.AddArc($x + $w - $d, $y + $h - $d, $d, $d, 0, 90)
|
|
$p.AddArc($x, $y + $h - $d, $d, $d, 90, 90)
|
|
$p.CloseFigure()
|
|
return $p
|
|
}
|
|
|
|
$outDir = "public/icons"
|
|
New-Item -ItemType Directory -Force -Path $outDir | Out-Null
|
|
|
|
foreach ($s in @(192, 512)) {
|
|
$bmp = New-Object System.Drawing.Bitmap($s, $s)
|
|
$g = [System.Drawing.Graphics]::FromImage($bmp)
|
|
$g.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::AntiAlias
|
|
$g.Clear([System.Drawing.Color]::Transparent)
|
|
|
|
$m = [float]($s * 0.055)
|
|
$bg = Make-RoundedRect $m $m ([float]($s - 2 * $m)) ([float]($s - 2 * $m)) ([float]($s * 0.20))
|
|
$indigo = New-Object System.Drawing.SolidBrush ([System.Drawing.Color]::FromArgb(79, 70, 229))
|
|
$g.FillPath($indigo, $bg)
|
|
|
|
# clipboard board (white)
|
|
$bw = [float]($s * 0.56); $bh = [float]($s * 0.62)
|
|
$bx = [float](($s - $bw) / 2); $by = [float]($s * 0.31)
|
|
$board = Make-RoundedRect $bx $by $bw $bh ([float]($s * 0.05))
|
|
$white = New-Object System.Drawing.SolidBrush ([System.Drawing.Color]::White)
|
|
$g.FillPath($white, $board)
|
|
|
|
# clip on top
|
|
$cw = [float]($s * 0.15); $ch = [float]($s * 0.11)
|
|
$cx = [float](($s - $cw) / 2); $cy = [float]($by - $s * 0.085)
|
|
$clip = Make-RoundedRect $cx $cy $cw $ch ([float]($s * 0.03))
|
|
$g.FillPath($white, $clip)
|
|
|
|
# ring holes (indigo)
|
|
$g.FillEllipse($indigo, [float]($cx + $cw * 0.16), [float]($cy + $ch * 0.30), [float]($s * 0.035), [float]($s * 0.035))
|
|
$g.FillEllipse($indigo, [float]($cx + $cw * 0.62), [float]($cy + $ch * 0.30), [float]($s * 0.035), [float]($s * 0.035))
|
|
|
|
# lines on the board
|
|
$slate = New-Object System.Drawing.SolidBrush ([System.Drawing.Color]::FromArgb(148, 163, 184))
|
|
$lh = [float]($s * 0.032)
|
|
$g.FillRectangle($slate, [float]($bx + $s * 0.09), [float]($by + $s * 0.15), [float]($bw - $s * 0.18), $lh)
|
|
$g.FillRectangle($slate, [float]($bx + $s * 0.09), [float]($by + $s * 0.29), [float]($bw - $s * 0.30), $lh)
|
|
$g.FillRectangle($slate, [float]($bx + $s * 0.09), [float]($by + $s * 0.43), [float]($bw - $s * 0.24), $lh)
|
|
|
|
$path = Join-Path $outDir "icon-$s.png"
|
|
$bmp.Save($path, [System.Drawing.Imaging.ImageFormat]::Png)
|
|
$g.Dispose(); $bmp.Dispose()
|
|
Write-Output "saved $path"
|
|
}
|