@shardflux/desktop-linux-arm64 0.0.0-stage → 0.1.0-next.4
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.
- package/CHANGELOG.md +7 -0
- package/LICENSE +202 -0
- package/README.md +2 -2
- package/app/manifest.json +1 -0
- package/app/shardflux-desktop +0 -0
- package/app/ui/agents.mjs +21 -0
- package/app/ui/app.mjs +78 -0
- package/app/ui/assets/FragmentMono-OFL.txt +93 -0
- package/app/ui/assets/FragmentMono.ttf +0 -0
- package/app/ui/assets/FunnelDisplay-OFL.txt +93 -0
- package/app/ui/assets/FunnelDisplay.woff2 +0 -0
- package/app/ui/assets/FunnelSans-OFL.txt +93 -0
- package/app/ui/assets/FunnelSans.ttf +0 -0
- package/app/ui/assets/Lucide-LICENSE +15 -0
- package/app/ui/assets/README.md +5 -0
- package/app/ui/assets/claude-mark.png +0 -0
- package/app/ui/assets/onboarding-silk.jpg +0 -0
- package/app/ui/assets/onboarding-wash-warm.webp +0 -0
- package/app/ui/assets/openai-mark.png +0 -0
- package/app/ui/assets/shardflux-icon.png +0 -0
- package/app/ui/assets/shardflux-icon.svg +1 -0
- package/app/ui/assets/shardflux-mark.svg +1 -0
- package/app/ui/assets/shardflux-tray.png +0 -0
- package/app/ui/assets/shardflux-tray.svg +1 -0
- package/app/ui/core.mjs +129 -0
- package/app/ui/icons.mjs +60 -0
- package/app/ui/index.html +1 -0
- package/app/ui/integrations.mjs +35 -0
- package/app/ui/settings.mjs +30 -0
- package/app/ui/style.css +212 -0
- package/app/ui/surfaces.mjs +219 -0
- package/app/ui/tokens.css +149 -0
- package/app/ui/tray.mjs +61 -0
- package/package.json +22 -4
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/* Shardflux design tokens. Source of truth for web and app UI.
|
|
2
|
+
Rules for using them: docs/DESIGN_SYSTEM.md. Values match the approved landing page (v2).
|
|
3
|
+
Dark is the primary theme. The light theme exists for the app (settings, docs, invoices) and printouts. */
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
:root {
|
|
7
|
+
color-scheme: dark;
|
|
8
|
+
|
|
9
|
+
/* surfaces */
|
|
10
|
+
--sf-bg: #0A0A0B; /* page */
|
|
11
|
+
--sf-raise: #111113; /* panels, code, windows */
|
|
12
|
+
--sf-overlay: #1B1C1F; /* menus, popovers, tooltips */
|
|
13
|
+
|
|
14
|
+
/* app top bar: the one light surface in the dark app (marketing nav stays dark) */
|
|
15
|
+
--sf-bar-bg: #F6F4F0;
|
|
16
|
+
--sf-bar-ink: #15161A;
|
|
17
|
+
--sf-bar-muted: #5B6068;
|
|
18
|
+
--sf-bar-line: rgba(21, 22, 26, .10);
|
|
19
|
+
--sf-bar-active: rgba(21, 22, 26, .07);
|
|
20
|
+
|
|
21
|
+
/* glass: summary cards at the top of app pages only (dark theme) */
|
|
22
|
+
--sf-glass-fill: linear-gradient(180deg, rgba(255, 255, 255, .06), rgba(255, 255, 255, .018) 55%, rgba(255, 255, 255, .03));
|
|
23
|
+
--sf-glass-edge: linear-gradient(140deg, rgba(255, 255, 255, .32), rgba(255, 255, 255, .05) 38%, rgba(255, 255, 255, .02) 62%, rgba(255, 255, 255, .16));
|
|
24
|
+
--sf-glass-blur: blur(22px) saturate(170%);
|
|
25
|
+
--sf-glass-shadow: inset 0 1px 0 rgba(255, 255, 255, .12), inset 0 -1px 0 rgba(255, 255, 255, .035), 0 24px 48px -28px rgba(0, 0, 0, .9);
|
|
26
|
+
--sf-glass-glow-cold: #6FB4F0;
|
|
27
|
+
|
|
28
|
+
/* text */
|
|
29
|
+
--sf-ink: #EDEBE7; /* primary text, primary button fill */
|
|
30
|
+
--sf-muted: #8B8F96; /* secondary text, body copy on marketing */
|
|
31
|
+
--sf-dim: #5D6168; /* labels, table headers, disabled */
|
|
32
|
+
|
|
33
|
+
/* lines */
|
|
34
|
+
--sf-line: rgba(237, 235, 231, .09); /* dividers, row rules */
|
|
35
|
+
--sf-line-2: rgba(237, 235, 231, .16); /* panel borders, inputs, ghost buttons */
|
|
36
|
+
--sf-line-3: rgba(237, 235, 231, .34); /* hover on bordered controls */
|
|
37
|
+
|
|
38
|
+
/* the one accent: molten amber. Means "running" and marks the single most important number */
|
|
39
|
+
--sf-molten: #FF8A3D;
|
|
40
|
+
|
|
41
|
+
/* workspace state (text colours; see the state rules) */
|
|
42
|
+
--sf-state-running: var(--sf-molten);
|
|
43
|
+
--sf-state-paused: var(--sf-ink);
|
|
44
|
+
--sf-state-archived: var(--sf-dim);
|
|
45
|
+
--sf-state-starting: var(--sf-muted);
|
|
46
|
+
|
|
47
|
+
/* shard glyph fills for the same states (the glyph needs more contrast steps than text) */
|
|
48
|
+
--sf-glyph-running: var(--sf-molten);
|
|
49
|
+
--sf-glyph-paused: rgba(237, 235, 231, .55);
|
|
50
|
+
--sf-glyph-archived: rgba(237, 235, 231, .16);
|
|
51
|
+
|
|
52
|
+
/* feedback. Never reuse amber for warnings: amber means running */
|
|
53
|
+
--sf-success: #7BC68A;
|
|
54
|
+
--sf-warning: #E9C46A;
|
|
55
|
+
--sf-danger: #F0645A;
|
|
56
|
+
|
|
57
|
+
/* code syntax (inside --sf-raise windows only) */
|
|
58
|
+
--sf-code-keyword: #C6A6F2;
|
|
59
|
+
--sf-code-string: #9FD39A;
|
|
60
|
+
--sf-code-call: #F2C08A;
|
|
61
|
+
--sf-code-comment: #5D6168;
|
|
62
|
+
--sf-code-line-number: #3E4147;
|
|
63
|
+
|
|
64
|
+
/* type */
|
|
65
|
+
--sf-display: "Funnel Display", system-ui, sans-serif;
|
|
66
|
+
--sf-body: "Funnel Sans", system-ui, sans-serif;
|
|
67
|
+
--sf-mono: "Fragment Mono", ui-monospace, Menlo, monospace;
|
|
68
|
+
|
|
69
|
+
/* type scale (px). App UI lives at 13-15; marketing uses the top of the scale */
|
|
70
|
+
--sf-text-11: 11px; /* uppercase mono labels only */
|
|
71
|
+
--sf-text-12: 12.5px;/* table headers, captions */
|
|
72
|
+
--sf-text-13: 13px; /* mono data, small UI */
|
|
73
|
+
--sf-text-14: 14px; /* app body, buttons, nav */
|
|
74
|
+
--sf-text-15: 15px; /* table cells, descriptions */
|
|
75
|
+
--sf-text-17: 17px; /* marketing body */
|
|
76
|
+
--sf-text-20: 20px; /* card and dialog titles */
|
|
77
|
+
--sf-text-26: 26px; /* app page titles */
|
|
78
|
+
--sf-text-44: 44px; /* big numbers */
|
|
79
|
+
--sf-text-52: 52px; /* marketing section headings */
|
|
80
|
+
--sf-text-72: 72px; /* marketing hero only */
|
|
81
|
+
|
|
82
|
+
/* spacing: 4 px base */
|
|
83
|
+
--sf-1: 4px; --sf-2: 8px; --sf-3: 12px; --sf-4: 16px; --sf-5: 20px; --sf-6: 24px;
|
|
84
|
+
--sf-8: 32px; --sf-10: 40px; --sf-12: 48px; --sf-16: 64px; --sf-24: 96px; --sf-35: 140px;
|
|
85
|
+
|
|
86
|
+
/* radii */
|
|
87
|
+
--sf-radius-sm: 4px; /* chips, code inline */
|
|
88
|
+
--sf-radius: 6px; /* buttons, inputs, tabs */
|
|
89
|
+
--sf-radius-lg: 12px; /* panels, windows, dialogs */
|
|
90
|
+
--sf-radius-glass: 16px; /* summary cards */
|
|
91
|
+
|
|
92
|
+
/* layout */
|
|
93
|
+
--sf-max: 1200px;
|
|
94
|
+
--sf-gutter: clamp(20px, 4vw, 48px);
|
|
95
|
+
--sf-header: 64px;
|
|
96
|
+
|
|
97
|
+
/* motion */
|
|
98
|
+
--sf-ease-out: cubic-bezier(.2, .8, .2, 1);
|
|
99
|
+
--sf-ease-in-out: cubic-bezier(.65, 0, .35, 1);
|
|
100
|
+
--sf-fast: 150ms;
|
|
101
|
+
--sf-base: 250ms;
|
|
102
|
+
--sf-slow: 600ms;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* Light theme: app surfaces only (never the marketing site). Same roles, bone paper. */
|
|
106
|
+
:root[data-theme="light"] {
|
|
107
|
+
color-scheme: light;
|
|
108
|
+
--sf-bg: #EDEBE7;
|
|
109
|
+
--sf-raise: #F6F4F0;
|
|
110
|
+
--sf-overlay: #FFFFFF;
|
|
111
|
+
--sf-ink: #15161A;
|
|
112
|
+
--sf-muted: #5B6068;
|
|
113
|
+
--sf-dim: #8A8E94;
|
|
114
|
+
--sf-line: rgba(21, 22, 26, .10);
|
|
115
|
+
--sf-line-2: rgba(21, 22, 26, .18);
|
|
116
|
+
--sf-line-3: rgba(21, 22, 26, .36);
|
|
117
|
+
--sf-molten: #D2691E; /* darker amber keeps contrast on bone */
|
|
118
|
+
--sf-glyph-paused: rgba(21, 22, 26, .55);
|
|
119
|
+
--sf-glyph-archived: rgba(21, 22, 26, .16);
|
|
120
|
+
--sf-success: #2F8A4A;
|
|
121
|
+
--sf-warning: #9A7209;
|
|
122
|
+
--sf-danger: #C8372D;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@media (prefers-reduced-motion: reduce) {
|
|
126
|
+
:root { --sf-fast: 0ms; --sf-base: 0ms; --sf-slow: 0ms; }
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* Summary card. Markup: <div class="sf-glass"> title, figure, bar, context line </div>.
|
|
130
|
+
Put the blurred state glows behind the row, not inside the card. */
|
|
131
|
+
.sf-glass {
|
|
132
|
+
position: relative; overflow: hidden;
|
|
133
|
+
padding: 20px 22px 22px; border-radius: var(--sf-radius-glass);
|
|
134
|
+
display: flex; flex-direction: column; gap: 8px;
|
|
135
|
+
background: var(--sf-glass-fill);
|
|
136
|
+
-webkit-backdrop-filter: var(--sf-glass-blur); backdrop-filter: var(--sf-glass-blur);
|
|
137
|
+
box-shadow: var(--sf-glass-shadow);
|
|
138
|
+
}
|
|
139
|
+
.sf-glass::before {
|
|
140
|
+
content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px; pointer-events: none;
|
|
141
|
+
background: var(--sf-glass-edge);
|
|
142
|
+
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
|
|
143
|
+
-webkit-mask-composite: xor; mask-composite: exclude;
|
|
144
|
+
}
|
|
145
|
+
.sf-glass::after {
|
|
146
|
+
content: ""; position: absolute; left: -20%; top: -60%; width: 90%; height: 120%; pointer-events: none;
|
|
147
|
+
background: radial-gradient(closest-side, rgba(255, 255, 255, .07), transparent); transform: rotate(-12deg);
|
|
148
|
+
}
|
|
149
|
+
.sf-glass > * { position: relative; z-index: 1; }
|
package/app/ui/tray.mjs
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// AgentMenu.swift: the top-bar panel. Approvals, New conversation, the conversations (live, then "N done"), errors,
|
|
2
|
+
// and the ⋯ overflow; each row's ⋯ opens its actions. Geometry and type follow the Mac menu (420 wide, 36 pt rows).
|
|
3
|
+
import {icon,appMark} from './icons.mjs';
|
|
4
|
+
import {escape as e,accountConnected} from './core.mjs';
|
|
5
|
+
export function compactElapsed(since,now=Date.now()){const s=Math.max(0,Math.floor((now-Date.parse(since))/1000));return s<60?`${s}s`:s<3600?`${Math.floor(s/60)}m`:s<86400?`${Math.floor(s/3600)}h`:`${Math.floor(s/86400)}d`;}
|
|
6
|
+
export function installTray({model,host,cli,render,button,registerActions,performAction}){
|
|
7
|
+
const T={done:false,overflow:false,actions:null};model.trayState=T;
|
|
8
|
+
const prior=window.renderSurface;
|
|
9
|
+
const stateLabel={working:'working','needs-you':'needs you','sign-in':'sign in needed',parked:'parked',done:'done'};
|
|
10
|
+
// menuActionLabel: icon in secondary ink, the title, an optional shortcut.
|
|
11
|
+
const item=(title,action,name,shortcut='',extra='')=>`<button class="menu-item" data-action="${action}">${icon(name,13)}<span class="menu-title">${title}</span>${shortcut?`<span class="menu-shortcut">${e(shortcut)}</span>`:''}${extra}</button>`;
|
|
12
|
+
const rule='<div class="menu-rule"></div>';
|
|
13
|
+
function row(r){
|
|
14
|
+
const open=T.actions===r.id;
|
|
15
|
+
return `<div class="session-row ${open?'actions-open':''}" data-row="${e(r.id)}" title="${e(`${r.title} · ${stateLabel[r.state]} · ${r.workspace_key}${r.last_message?`\n${r.last_message}`:''}`)}">
|
|
16
|
+
<button class="session-open" data-action="open:${e(r.reference)}"><span class="state-dot ${r.state}"></span>${appMark(r.app,14)}<span class="session-title ${r.state==='done'?'done':''}">${e(r.title)}</span><span class="session-project">${e(r.project)}</span><span class="session-age">${compactElapsed(r.since)}</span></button>
|
|
17
|
+
<button class="row-tool" data-action="archive:${e(r.id)}" title="Archive conversation" aria-label="Archive conversation">${icon('archive',12)}</button>
|
|
18
|
+
<button class="row-tool ${open?'pressed':''}" data-action="row-actions:${e(r.id)}" title="More actions" aria-label="More actions">${icon('ellipsis',13)}</button></div>`;
|
|
19
|
+
}
|
|
20
|
+
const approvalCount=()=>(model.integrations?.credentials?.length||0)+(model.integrations?.requests?.length||0);
|
|
21
|
+
function approvals(){const i=model.integrations||{};return (i.credentials||[]).map(r=>card(`Sign in to ${e(hostOf(r.site))}`,`Share ${r.fields.map(e).join(' and ')} from your vault.`,`credential:${r.id}`,`deny-credential:${r.id}`,`always-credential:${r.id}`,r.prompt)).join('')+(i.requests||[]).map(r=>card(r.outside?'Access outside conversation':'Device request',e(r.summary),`review:${r.request_id}`,`deny:${r.request_id}`,null,r.summary)).join('');}
|
|
22
|
+
const hostOf=site=>{try{return new URL(site).host;}catch{return site;}};
|
|
23
|
+
// ApprovalCard: lock.shield, the title and two lines, Review… and Deny; a credential adds ⋯ (Always allow for this project).
|
|
24
|
+
function card(title,detail,review,deny,always,help=''){return `<div class="approval-card"><span class="approval-icon">${icon('shield-lock',17)}</span><div class="approval-body"><b>${title}</b><p title="${e(help||'')}">${detail}</p><div class="approval-actions">${button('Review…',review,'glass-button')}${button('Deny',deny,'plain')}<span class="grow"></span>${always?`<button class="more" data-action="approval-more:${always.slice(18)}" title="More approval options" aria-label="More approval options">${icon('ellipsis',14)}</button>`:''}</div></div></div>`;}
|
|
25
|
+
function overflow(){const f=model.integrations?.files?.placeholders||[],update=!!model.settings?.update?.update_available;
|
|
26
|
+
return `<div class="menu-popover overflow" role="menu">${item('Settings…','settings','settings','Ctrl+,')}${item('Check for updates','updates','rotate-cw','',update?'<span class="update-dot"></span>':'')}${rule}${item('Open files','files','folder')}${f.slice(0,5).map((x,i)=>item(`Download ${e(x.path.split('/').at(-1))}`,`download:${i}`,'circle-arrow-down',sizeText(x.size))).join('')}${rule}${item('Quit','quit','circle-x','Ctrl+Q')}</div>`;}
|
|
27
|
+
function rowActions(r){return `<div class="menu-popover row-actions" role="menu"><div class="menu-heading">${e(r.title)}</div>${item('Open',`open:${e(r.reference)}`,'square-arrow-up-right')}${item('New thread on this computer',`thread:${e(r.id)}`,'monitor')}${rule}${item('Archive',`archive:${e(r.id)}`,'archive')}${item('Copy workspace key',`copy-key:${e(r.workspace_key)}`,'copy')}</div>`;}
|
|
28
|
+
// ByteCountFormatter, binary count style: 60,000,000 bytes is 57.2 MB.
|
|
29
|
+
const sizeText=n=>{const units=['bytes','KB','MB','GB','TB'];let i=0,v=n;while(v>=1024&&i<units.length-1){v/=1024;i++;}return `${i<2?Math.round(v):new Intl.NumberFormat(undefined,{maximumFractionDigits:1}).format(v)} ${units[i]}`;};
|
|
30
|
+
function panel(){
|
|
31
|
+
const rows=model.rows||[],live=rows.filter(r=>r.state!=='done'),done=rows.filter(r=>r.state==='done'),signedIn=model.signedIn!==false;
|
|
32
|
+
const selected=rows.find(r=>r.id===T.actions);
|
|
33
|
+
const status=!signedIn?'Sign in to Shardflux to see your conversations here.':model.trayStatus||'';
|
|
34
|
+
const error=model.error||(live.length&&status&&signedIn?status:'');
|
|
35
|
+
const list=!live.length&&!done.length?`<p class="menu-empty">${e(status||'Your conversations will appear here.')}</p>`:
|
|
36
|
+
`<div class="session-list" style="max-height:${Math.max(108,(screen.availHeight||800)-180-approvalCount()*88)}px">${live.map(row).join('')}${done.length?`<button class="done-toggle" data-action="tray-done">${icon(T.done?'chevron-down':'chevron-right',10)}<span>${done.length} done</span></button>${T.done?done.map(row).join(''):''}`:''}</div>`;
|
|
37
|
+
const update=!!model.settings?.update?.update_available;
|
|
38
|
+
return `<section class="menu-panel ${T.overflow?'with-overflow':''} ${selected?'with-actions':''}" style="--placeholders:${Math.min(5,(model.integrations?.files?.placeholders||[]).length)}">
|
|
39
|
+
${approvals()}<button class="new-conversation" data-action="${signedIn?'launcher':'onboarding'}">${icon('plus',13)}<span class="menu-title">New conversation</span><span class="menu-shortcut">Ctrl+N</span></button>${rule}${list}
|
|
40
|
+
${error?`<div class="menu-error">${icon('circle-alert',13)}<div><p>${e(error)}</p>${model.trayStatus&&signedIn?button('Refresh','tray-refresh','bordered'):''}${model.createdKey?button('Open created conversation',`open:${e(model.createdKey)}`,'plain'):''}</div></div>`:''}
|
|
41
|
+
<span class="grow"></span><footer class="menu-foot"><button class="overflow-toggle ${T.overflow?'pressed':''}" data-action="tray-overflow" title="More options" aria-label="${update?'More options, update available':'More options'}">${icon('ellipsis',16)}${update?'<span class="update-dot"></span>':''}</button></footer>
|
|
42
|
+
${T.overflow?`<div class="menu-dismiss" data-action="tray-dismiss"></div>${overflow()}`:selected?`<div class="menu-dismiss" data-action="tray-dismiss"></div>${rowActions(selected)}`:''}</section>`;
|
|
43
|
+
}
|
|
44
|
+
window.renderSurface=()=>{if(model.view!=='tray')return prior();document.querySelector('#app').innerHTML=panel();requestAnimationFrame(()=>{const p=document.querySelector('.menu-panel');if(p)void host('resize',{height:Math.min(760,p.offsetHeight+24)});});};
|
|
45
|
+
registerActions({'tray-refresh':async()=>{await window.sfRefreshTray?.();},'tray-done':()=>{T.done=!T.done;},'tray-overflow':()=>{T.overflow=!T.overflow;T.actions=null;},'tray-dismiss':()=>{T.overflow=false;T.actions=null;}});
|
|
46
|
+
const app=document.querySelector('#app');
|
|
47
|
+
// The row's ⋯ toggles its actions; every other action closes the panel's menus and then the panel, as an NSMenu does.
|
|
48
|
+
app.addEventListener('click',ev=>{if(model.view!=='tray')return;const a=ev.target.closest('[data-action]')?.dataset.action;if(!a)return;
|
|
49
|
+
if(a.startsWith('row-actions:')){ev.stopImmediatePropagation();T.actions=T.actions===a.slice(12)?null:a.slice(12);T.overflow=false;render();return;}
|
|
50
|
+
if(!a.startsWith('tray-')&&!a.startsWith('approval-more:')){T.overflow=false;T.actions=null;void host('hide');}},true);
|
|
51
|
+
// Right-click on a row: its context menu, natively (Open, New thread on this computer, Archive, Copy workspace key).
|
|
52
|
+
app.addEventListener('click',ev=>{if(model.view!=='tray')return;const m=ev.target.closest('[data-action^="approval-more:"]');if(!m)return;ev.stopImmediatePropagation();const r=m.getBoundingClientRect();void host('popup',{x:Math.round(r.right),y:Math.round(r.bottom+2),width:1,height:1,align:'right',items:[{label:'Always allow for this project',action:`always-credential:${m.dataset.action.slice(14)}`}]});},true);
|
|
53
|
+
app.addEventListener('contextmenu',ev=>{if(model.view!=='tray')return;const el=ev.target.closest('[data-row]');ev.preventDefault();if(!el)return;const r=(model.rows||[]).find(r=>r.id===el.dataset.row);if(!r)return;
|
|
54
|
+
void host('popup',{x:Math.round(ev.clientX),y:Math.round(ev.clientY),width:1,height:1,items:[{label:'Open',action:`open:${r.reference}`},{label:'New thread on this computer',action:`thread:${r.id}`},{label:'Archive',action:`archive:${r.id}`},{separator:true},{label:'Copy workspace key',action:`copy-key:${r.workspace_key}`}]});});
|
|
55
|
+
// Updates.swift: the CLI's update check, at start and then every six hours; a newer release puts the dot on ⋯.
|
|
56
|
+
async function checkUpdates(){try{(model.settings??={}).update=await cli(['update','--check','--json']);if(model.view==='tray')render();}catch{}}
|
|
57
|
+
window.sfCheckUpdates=checkUpdates;void checkUpdates();setInterval(checkUpdates,6*3600*1000);
|
|
58
|
+
window.addEventListener('keydown',ev=>{if(model.view!=='tray')return;
|
|
59
|
+
if(ev.key==='Escape'){if(T.overflow||T.actions){T.overflow=false;T.actions=null;render();}else void host('hide');}
|
|
60
|
+
else if(ev.ctrlKey&&!ev.shiftKey&&!ev.altKey&&['n',',','q'].includes(ev.key.toLowerCase())){ev.preventDefault();const a={n:'launcher',',':'settings',q:'quit'}[ev.key.toLowerCase()];T.overflow=false;void host('hide').then(()=>performAction(a));}});
|
|
61
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shardflux/desktop-linux-arm64",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0-next.4",
|
|
4
|
+
"description": "Shardflux desktop app for Ubuntu Linux",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"os": [
|
|
7
|
+
"linux"
|
|
8
|
+
],
|
|
9
|
+
"cpu": [
|
|
10
|
+
"arm64"
|
|
11
|
+
],
|
|
12
|
+
"files": [
|
|
13
|
+
"app",
|
|
14
|
+
"README.md",
|
|
15
|
+
"CHANGELOG.md",
|
|
16
|
+
"LICENSE"
|
|
17
|
+
],
|
|
18
|
+
"exports": {
|
|
19
|
+
"./package.json": "./package.json"
|
|
20
|
+
},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
}
|
|
24
|
+
}
|