yapin.js-client 0.1.0 → 0.1.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/README.md +1 -1
- package/docs/README.md +1 -0
- package/docs/about-page.md +19 -2
- package/docs/configuration.md +36 -2
- package/docs/getting-started.md +1 -1
- package/docs/installer.md +39 -12
- package/docs/ui.md +20 -3
- package/docs/welcome.md +63 -0
- package/package.json +1 -1
- package/src/build/build.js +34 -22
- package/src/build/nsis.js +763 -0
- package/src/config/defaults.js +30 -3
- package/src/config/load.js +9 -1
- package/src/desktop/preload.cjs +3 -1
- package/src/desktop/shim.cjs +60 -11
- package/src/installer/main.js +5 -0
- package/src/installer/nsis.js +75 -0
- package/src/installer/operations.js +23 -18
- package/src/installer/page.js +29 -0
- package/src/installer/processes.js +74 -19
- package/src/runtime/about.js +126 -36
- package/src/runtime/builtin-pages.js +2 -2
- package/src/runtime/client.js +21 -1
- package/src/runtime/onboarding.js +196 -0
- package/src/runtime/ui.js +52 -9
- package/src/shared/constants.js +1 -1
- package/src/shared/icons.js +52 -0
- package/types/index.d.ts +38 -1
- package/types/runtime.d.ts +26 -2
package/src/shared/constants.js
CHANGED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A small built-in icon set, usable anywhere an "icon" option is accepted (page icons, About fields,
|
|
3
|
+
* cards, toasts, dialogs, the welcome and what's new screens…) by name: `icon: 'rocket'`. Each is a
|
|
4
|
+
* plain, stroke-based 24×24 SVG that inherits its colour from CSS (`currentColor`), so it follows
|
|
5
|
+
* whatever text colour it's placed in, in any theme.
|
|
6
|
+
*
|
|
7
|
+
* Anywhere that takes an icon also still takes raw SVG markup, an https/data image URL, or an element;
|
|
8
|
+
* names here are just a shortcut so client apps don't have to carry their own SVGs for common things.
|
|
9
|
+
*/
|
|
10
|
+
export const ICONS = Object.freeze({
|
|
11
|
+
sparkles:
|
|
12
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v4M12 17v4M3 12h4M17 12h4M6.3 6.3l1.8 1.8M15.9 15.9l1.8 1.8M17.7 6.3l-1.8 1.8M8.1 15.9l-1.8 1.8"/><circle cx="12" cy="12" r="2.1"/></svg>',
|
|
13
|
+
rocket:
|
|
14
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 9.5c2-2 3-5 2.6-6.6-1.6-.4-4.6.6-6.6 2.6-1.8 1.8-4.3 5.2-5 7l2.9 3c1.9-.7 5.3-3.2 7-5Z"/><path d="M9 15l-3 3M13.5 6.5l4 4M8 16.5c0 1.5-1 2.5-3.5 3 .5-2.5 1.5-3.5 3-3.5Z"/></svg>',
|
|
15
|
+
puzzle:
|
|
16
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M9 4h3a1.5 1.5 0 0 1 0 3 1.5 1.5 0 0 0 0 3h3a1 1 0 0 1 1 1v3a1.5 1.5 0 0 1-3 0 1.5 1.5 0 0 0-3 0v3a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-3a1.5 1.5 0 0 1 0-3 1.5 1.5 0 0 0 0-3V6a1 1 0 0 1 1-1h3V4Z"/></svg>',
|
|
17
|
+
palette:
|
|
18
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a9 9 0 1 0 0 18c1.1 0 2-.9 2-2 0-.5-.2-1-.5-1.3-.3-.4-.5-.8-.5-1.3 0-1.1.9-2 2-2h2a4 4 0 0 0 4-4c0-4.4-4-7.4-9-7.4Z"/><circle cx="7.5" cy="12" r="1.1" fill="currentColor" stroke="none"/><circle cx="9.5" cy="8" r="1.1" fill="currentColor" stroke="none"/><circle cx="14.5" cy="8" r="1.1" fill="currentColor" stroke="none"/><circle cx="16.5" cy="12" r="1.1" fill="currentColor" stroke="none"/></svg>',
|
|
19
|
+
sliders:
|
|
20
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h7M15 7h5M4 17h11M19 17h1M9 4.5v5M17 14.5v5"/></svg>',
|
|
21
|
+
info:
|
|
22
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 11v5"/><circle cx="12" cy="8" r=".2" fill="currentColor"/></svg>',
|
|
23
|
+
check:
|
|
24
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4.5 12.5l5 5 10-11"/></svg>',
|
|
25
|
+
x: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6 6l12 12M18 6L6 18"/></svg>',
|
|
26
|
+
alertTriangle:
|
|
27
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M12 4 3 20h18L12 4Z"/><path d="M12 10v4"/><circle cx="12" cy="17" r=".2" fill="currentColor"/></svg>',
|
|
28
|
+
alertCircle:
|
|
29
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7.5v5.5"/><circle cx="12" cy="16.5" r=".2" fill="currentColor"/></svg>',
|
|
30
|
+
chevronRight:
|
|
31
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9 5l7 7-7 7"/></svg>',
|
|
32
|
+
megaphone:
|
|
33
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M3 11v2a2 2 0 0 0 2 2h1l9 4V5l-9 4H5a2 2 0 0 0-2 2Z"/><path d="M15 9.5a3.5 3.5 0 0 1 0 5"/></svg>',
|
|
34
|
+
bell:
|
|
35
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M6 10a6 6 0 1 1 12 0c0 3 1 4.5 2 5.5H4c1-1 2-2.5 2-5.5Z"/><path d="M10 19.5a2 2 0 0 0 4 0"/></svg>',
|
|
36
|
+
external:
|
|
37
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M9 5H6a2 2 0 0 0-2 2v11a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2v-3"/><path d="M13 3h8v8"/><path d="M21 3 10 14"/></svg>',
|
|
38
|
+
heart:
|
|
39
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20s-7.5-4.6-9.5-9.3C1.1 7.7 3 4.5 6.4 4.5c2 0 3.4 1.1 4.1 2.3.7-1.2 2.1-2.3 4.1-2.3 3.4 0 5.3 3.2 3.9 6.2C19.5 15.4 12 20 12 20Z"/></svg>',
|
|
40
|
+
copy:
|
|
41
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><rect x="8.5" y="8.5" width="11.5" height="11.5" rx="2"/><path d="M15.5 8.5V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v7.5a2 2 0 0 0 2 2h2.5"/></svg>',
|
|
42
|
+
folder:
|
|
43
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 7a2 2 0 0 1 2-2h4l2 2.5h7a2 2 0 0 1 2 2V17a2 2 0 0 1-2 2h-13a2 2 0 0 1-2-2V7Z"/></svg>',
|
|
44
|
+
shield:
|
|
45
|
+
'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l7 3v5c0 5-3.5 8-7 10-3.5-2-7-5-7-10V6l7-3Z"/><path d="M9 12l2 2 4-4.5"/></svg>',
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
/** Looks up a built-in icon by name (case-insensitive). Returns raw SVG markup, or null. */
|
|
49
|
+
export function builtinIcon(name) {
|
|
50
|
+
if (typeof name !== 'string') return null;
|
|
51
|
+
return ICONS[name] ?? ICONS[name.replace(/-([a-z])/g, (_, c) => c.toUpperCase())] ?? null;
|
|
52
|
+
}
|
package/types/index.d.ts
CHANGED
|
@@ -111,11 +111,42 @@ export interface Config {
|
|
|
111
111
|
title?: string;
|
|
112
112
|
order?: number;
|
|
113
113
|
icon?: string;
|
|
114
|
+
/** Shown in the header card: a built-in icon name, SVG markup, or an https/data image URL. Default: the name's first letter. */
|
|
115
|
+
logo?: string | null;
|
|
114
116
|
intro?: string | null;
|
|
115
|
-
sections?: Record<string, boolean | { title?: string | null; order?: number }>;
|
|
117
|
+
sections?: Record<string, boolean | { title?: string | null; order?: number; layout?: 'rows' | 'chips' | 'header' }>;
|
|
116
118
|
fields?: Record<string, false | string | { label?: string; value?: string; href?: string; copy?: boolean | string; code?: boolean; order?: number; hidden?: boolean }>;
|
|
117
119
|
actions?: Record<string, false>;
|
|
118
120
|
};
|
|
121
|
+
/** A rounded, animated screen shown the first time the client app runs. `false` turns it off entirely. */
|
|
122
|
+
welcome?:
|
|
123
|
+
| false
|
|
124
|
+
| {
|
|
125
|
+
enabled?: boolean;
|
|
126
|
+
/** A built-in icon name ('sparkles', 'rocket', …), SVG markup, or an https/data image URL. */
|
|
127
|
+
icon?: string;
|
|
128
|
+
/** `{name}` and `{version}` are replaced. */
|
|
129
|
+
title?: string;
|
|
130
|
+
subtitle?: string | null;
|
|
131
|
+
steps?: Array<{ icon?: string; title: string; description?: string }>;
|
|
132
|
+
actionLabel?: string;
|
|
133
|
+
dismissible?: boolean;
|
|
134
|
+
dismissLabel?: string;
|
|
135
|
+
};
|
|
136
|
+
/** Shown once after an update, when `entries` has something for the new version. `false` turns it off entirely. */
|
|
137
|
+
whatsNew?:
|
|
138
|
+
| false
|
|
139
|
+
| {
|
|
140
|
+
enabled?: boolean;
|
|
141
|
+
icon?: string;
|
|
142
|
+
/** `{name}` and `{version}` are replaced. */
|
|
143
|
+
title?: string;
|
|
144
|
+
subtitle?: string | null;
|
|
145
|
+
entries?: Array<{ icon?: string; title: string; description?: string }>;
|
|
146
|
+
actionLabel?: string;
|
|
147
|
+
dismissible?: boolean;
|
|
148
|
+
dismissLabel?: string | null;
|
|
149
|
+
};
|
|
119
150
|
badges?: {
|
|
120
151
|
enabled?: boolean;
|
|
121
152
|
sources?: Array<{ id: string; url: string; name?: string; refresh?: string | number; priority?: number }>;
|
|
@@ -153,6 +184,12 @@ export interface Config {
|
|
|
153
184
|
company?: string | null;
|
|
154
185
|
/** A signing command run on the finished .exe, with {file} replaced: 'signtool sign /fd sha256 /a {file}'. */
|
|
155
186
|
sign?: string | null;
|
|
187
|
+
/** Build a setup wizard with NSIS when makensis is found (default true), false for the browser launcher, or makensis's path. */
|
|
188
|
+
nsis?: boolean | string;
|
|
189
|
+
/** A 164×314 .bmp for the wizard's Welcome and Finish pages; default: the accent colour with the logo. */
|
|
190
|
+
sidebar?: string | null;
|
|
191
|
+
/** A 150×57 .bmp for the top of the wizard's other pages; default: the logo on white. */
|
|
192
|
+
header?: string | null;
|
|
156
193
|
};
|
|
157
194
|
};
|
|
158
195
|
}
|
package/types/runtime.d.ts
CHANGED
|
@@ -167,20 +167,40 @@ export interface AboutField {
|
|
|
167
167
|
hidden?: boolean;
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
+
export type AboutLayout = 'rows' | 'chips' | 'header';
|
|
171
|
+
|
|
170
172
|
export interface AboutPage {
|
|
171
173
|
/** id is '<section>.<name>', like 'git.commit' or 'support.discord'. */
|
|
172
174
|
set(id: string, field: AboutField): this;
|
|
173
175
|
get(id: string): (AboutField & { id: string; section: string }) | null;
|
|
174
176
|
remove(id: string): boolean;
|
|
175
177
|
fields(): Array<AboutField & { id: string; section: string }>;
|
|
176
|
-
|
|
178
|
+
/** 'rows' (default), 'chips' (compact pills, for links) or 'header' (the card at the top). */
|
|
179
|
+
section(id: string, options: { title?: string | null; order?: number; layout?: AboutLayout }): this;
|
|
180
|
+
sections(): Array<{ id: string; title: string | null; order: number; layout: AboutLayout }>;
|
|
177
181
|
removeSection(id: string): this;
|
|
178
|
-
action(id: string, options: { label: string; run: (client: Client) => unknown; variant?: 'primary' | 'ghost' | 'danger'; order?: number }): this;
|
|
182
|
+
action(id: string, options: { label: string; icon?: string; run: (client: Client) => unknown; variant?: 'primary' | 'ghost' | 'danger'; order?: number }): this;
|
|
179
183
|
removeAction(id: string): this;
|
|
180
184
|
/** Everything on the page as text, plus enabled plugins, themes and recent errors. */
|
|
181
185
|
debugInfo(): string;
|
|
182
186
|
}
|
|
183
187
|
|
|
188
|
+
// ---------- welcome / what's new ----------
|
|
189
|
+
|
|
190
|
+
export interface OnboardingScreen {
|
|
191
|
+
readonly enabled: boolean;
|
|
192
|
+
/** Shows it right now, regardless of whether it's been seen. */
|
|
193
|
+
show(): () => void;
|
|
194
|
+
/** Marks it seen without showing it. */
|
|
195
|
+
markSeen(): void;
|
|
196
|
+
/** Clears the seen flag so it's shown again next start (or call show() now). */
|
|
197
|
+
reset(): void;
|
|
198
|
+
shouldShow(): boolean;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export interface Welcome extends OnboardingScreen {}
|
|
202
|
+
export interface WhatsNew extends OnboardingScreen {}
|
|
203
|
+
|
|
184
204
|
// ---------- themes ----------
|
|
185
205
|
|
|
186
206
|
export interface ThemeVariable {
|
|
@@ -647,6 +667,10 @@ export declare class Client {
|
|
|
647
667
|
readonly userContent: UserContent;
|
|
648
668
|
/** null when the client app turned the About page off. */
|
|
649
669
|
readonly about: AboutPage | null;
|
|
670
|
+
/** null when the client app turned the welcome screen off. */
|
|
671
|
+
readonly welcome: Welcome | null;
|
|
672
|
+
/** null when the client app turned the what's new screen off. */
|
|
673
|
+
readonly whatsNew: WhatsNew | null;
|
|
650
674
|
reportError(error: unknown, tags?: Record<string, unknown>): void;
|
|
651
675
|
openExternal(url: string): boolean;
|
|
652
676
|
stop(): void;
|