@galda/cli 0.10.68 → 0.10.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <title>Review completion preview</title>
7
+ <style>
8
+ *{box-sizing:border-box}body{margin:0;background:#f4f5f7;color:#202124;font:14px Inter,ui-sans-serif,system-ui,sans-serif;min-height:100vh;display:grid;place-items:center}
9
+ .stage{width:min(900px,94vw);height:min(720px,88vh);position:relative}.dialog{position:absolute;inset:0;background:#fff;border:1px solid #d9dce2;border-radius:16px;box-shadow:0 24px 70px rgba(22,25,31,.18);overflow:hidden;transition:opacity .2s,transform .2s}.dialog.closed{opacity:0;transform:scale(.985);pointer-events:none}.head{height:58px;border-bottom:1px solid #e7e8eb;display:flex;align-items:center;padding:0 28px;font-weight:700}.content{padding:32px 40px}.label{font:11px ui-monospace,SFMono-Regular,monospace;color:#737780;letter-spacing:.08em;text-transform:uppercase}.title{font-size:24px;margin:9px 0 26px}.line{height:12px;border-radius:3px;background:#eceef1;margin:12px 0}.line.w1{width:82%}.line.w2{width:64%}.line.w3{width:73%}.actions{position:absolute;left:40px;right:40px;bottom:30px;border-top:1px solid #e7e8eb;padding-top:20px;display:flex;gap:10px}.btn{height:38px;border-radius:9px;border:1px solid #d9dce2;background:#fff;padding:0 16px}.btn.ok{background:#202124;color:#fff;border-color:#202124}.replay{position:fixed;right:24px;bottom:24px;height:40px;padding:0 18px;border:0;border-radius:9px;background:#202124;color:#fff;font-weight:650;cursor:pointer}.finish{position:absolute;inset:0;z-index:3;display:grid;place-items:center;overflow:hidden;border-radius:16px;background:rgba(245,247,250,.78);backdrop-filter:blur(3px);animation:fade .95s ease both}.mark{width:104px;height:104px;border-radius:50%;display:grid;place-items:center;background:#18c77a;box-shadow:0 18px 52px rgba(24,199,122,.34);animation:pop .72s cubic-bezier(.2,1.35,.35,1) both}.mark svg{width:56px;height:56px;fill:none;stroke:#fff;stroke-width:3.4;stroke-linecap:round;stroke-linejoin:round}.mark path{stroke-dasharray:70;stroke-dashoffset:70;animation:draw .42s ease .18s forwards}.piece{position:fixed;z-index:4;pointer-events:none;will-change:transform,opacity}@keyframes pop{0%{transform:scale(.45);opacity:0}62%{transform:scale(1.1);opacity:1}100%{transform:scale(1)}}@keyframes draw{to{stroke-dashoffset:0}}@keyframes fade{0%,72%{opacity:1}100%{opacity:0}}@media(prefers-reduced-motion:reduce){.finish,.mark,.mark path{animation:none}.finish{background:transparent}}
10
+ </style>
11
+ </head>
12
+ <body>
13
+ <main class="stage"><section class="dialog" id="dialog"><div class="head">In review</div><div class="content"><div class="label">Request</div><h1 class="title">Improve the approval completion moment</h1><div class="label">What changed</div><div class="line w1"></div><div class="line w2"></div><div class="line w3"></div><div class="actions"><button class="btn ok">Approve</button><button class="btn">Dismiss</button></div></div></section></main>
14
+ <button class="replay" id="replay">Replay</button>
15
+ <script>
16
+ const colors=['#F24E1E','#FF7262','#A259FF','#1ABCFE','#0ACF83','#FFD166'];
17
+ function burst(cx,cy){if(matchMedia('(prefers-reduced-motion: reduce)').matches)return;for(let i=0;i<42;i++){const p=document.createElement('i');p.className='piece';const s=6+Math.random()*6;p.style.cssText=`left:${cx}px;top:${cy}px;width:${s}px;height:${s}px;background:${colors[i%colors.length]};border-radius:${Math.random()<.5?'50%':'2px'};transition:transform .9s cubic-bezier(.15,.7,.3,1),opacity .9s ease .25s`;document.body.appendChild(p);const a=Math.random()*Math.PI*2,d=90+Math.random()*190,dx=Math.cos(a)*d,dy=Math.sin(a)*d*.6+90,rot=(Math.random()<.5?-1:1)*(360+Math.random()*360);requestAnimationFrame(()=>{p.style.transform=`translate(${dx}px,${dy}px) rotate(${rot}deg)`;p.style.opacity='0'});setTimeout(()=>p.remove(),1000)}}
18
+ function play(){document.querySelectorAll('.finish,.piece').forEach(x=>x.remove());const d=document.getElementById('dialog');d.classList.remove('closed');const f=document.createElement('div');f.className='finish';f.innerHTML='<div class="mark"><svg viewBox="0 0 64 64"><path d="M17 33l10 10 21-23"/></svg></div>';document.querySelector('.stage').appendChild(f);const r=f.querySelector('.mark').getBoundingClientRect();burst(r.left+r.width/2,r.top+r.height/2);setTimeout(()=>{f.remove();d.classList.add('closed')},matchMedia('(prefers-reduced-motion: reduce)').matches?350:950)}
19
+ document.getElementById('replay').onclick=play;setTimeout(play,350);
20
+ </script>
21
+ </body></html>
@@ -0,0 +1,34 @@
1
+ import { execFileSync } from 'node:child_process';
2
+
3
+ const MAC_CHROME = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
4
+
5
+ // Chrome updates its app bundle while an older copy can remain open. Launching
6
+ // the newly installed executable during that window aborts inside Chrome and
7
+ // macOS shows a scary "quit unexpectedly" dialog.
8
+ export function chromeUpdatePending(chromePath, {
9
+ platform = process.platform,
10
+ readCurrentVersion = () => execFileSync('/usr/libexec/PlistBuddy', [
11
+ '-c', 'Print:CFBundleShortVersionString',
12
+ '/Applications/Google Chrome.app/Contents/Info.plist',
13
+ ], { encoding: 'utf8' }).trim(),
14
+ readProcesses = () => execFileSync('/bin/ps', ['-axo', 'command='], { encoding: 'utf8' }),
15
+ } = {}) {
16
+ if (platform !== 'darwin' || chromePath !== MAC_CHROME) return false;
17
+ try {
18
+ const current = readCurrentVersion();
19
+ const running = [...readProcesses().matchAll(/Google Chrome Framework\.framework\/Versions\/([^/\s]+)/g)]
20
+ .map((match) => match[1]);
21
+ return running.some((version) => version !== current);
22
+ } catch {
23
+ return false;
24
+ }
25
+ }
26
+
27
+ // Browser tests use this instead of launching the first installed binary
28
+ // directly. Returning null plugs into node:test's existing `skip: !CHROME`
29
+ // behavior, so a Chrome update never becomes a product failure or a macOS
30
+ // crash dialog.
31
+ export function safeChromePath(chromePath, options) {
32
+ if (!chromePath) return null;
33
+ return chromeUpdatePending(chromePath, options) ? null : chromePath;
34
+ }