@adea-ai/ui 0.97.2 → 0.97.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/dist/components/composites/about-dialog/about-dialog.d.ts.map +1 -1
- package/dist/components/composites/about-dialog/about-dialog.js +2 -1
- package/dist/components/composites/about-dialog/about-dialog.js.map +1 -1
- package/dist/components/composites/appearance-editor/appearance-choices.d.ts.map +1 -1
- package/dist/components/composites/appearance-editor/appearance-choices.js +44 -42
- package/dist/components/composites/appearance-editor/appearance-choices.js.map +1 -1
- package/dist/components/composites/appearance-editor/appearance-editor.d.ts.map +1 -1
- package/dist/components/composites/appearance-editor/appearance-editor.js +23 -1
- package/dist/components/composites/appearance-editor/appearance-editor.js.map +1 -1
- package/dist/components/composites/appearance-editor/appearance-rows.d.ts +22 -5
- package/dist/components/composites/appearance-editor/appearance-rows.d.ts.map +1 -1
- package/dist/components/composites/appearance-editor/appearance-rows.js +249 -152
- package/dist/components/composites/appearance-editor/appearance-rows.js.map +1 -1
- package/dist/components/composites/appearance-editor/appearance-types.d.ts +7 -0
- package/dist/components/composites/appearance-editor/appearance-types.d.ts.map +1 -1
- package/dist/components/composites/appearance-editor/theme-preview.d.ts +10 -0
- package/dist/components/composites/appearance-editor/theme-preview.d.ts.map +1 -1
- package/dist/components/composites/appearance-editor/theme-preview.js +61 -12
- package/dist/components/composites/appearance-editor/theme-preview.js.map +1 -1
- package/dist/components/composites/help-center/help-center.d.ts.map +1 -1
- package/dist/components/composites/help-center/help-center.js +3 -2
- package/dist/components/composites/help-center/help-center.js.map +1 -1
- package/dist/components/composites/update-dialog/update-dialog.js +3 -3
- package/dist/components/composites/update-dialog/update-dialog.js.map +1 -1
- package/dist/r/src/components/composites/about-dialog/about-dialog.tsx +6 -1
- package/dist/r/src/components/composites/appearance-editor/appearance-choices.tsx +19 -14
- package/dist/r/src/components/composites/appearance-editor/appearance-editor.tsx +13 -1
- package/dist/r/src/components/composites/appearance-editor/appearance-rows.tsx +270 -160
- package/dist/r/src/components/composites/appearance-editor/appearance-types.ts +7 -0
- package/dist/r/src/components/composites/appearance-editor/theme-preview.tsx +58 -0
- package/dist/r/src/components/composites/help-center/help-center.tsx +3 -2
- package/dist/r/src/components/composites/update-dialog/update-dialog.tsx +3 -3
- package/package.json +1 -1
- package/src/components/composites/about-dialog/about-dialog.tsx +6 -1
- package/src/components/composites/appearance-editor/appearance-choices.tsx +19 -14
- package/src/components/composites/appearance-editor/appearance-editor.tsx +13 -1
- package/src/components/composites/appearance-editor/appearance-rows.tsx +270 -160
- package/src/components/composites/appearance-editor/appearance-types.ts +7 -0
- package/src/components/composites/appearance-editor/theme-preview.tsx +58 -0
- package/src/components/composites/help-center/help-center.tsx +3 -2
- package/src/components/composites/update-dialog/update-dialog.tsx +3 -3
|
@@ -5,8 +5,9 @@ import { For } from "solid-js";
|
|
|
5
5
|
var _tmpl$ = /*#__PURE__*/ template(`<span class="h-[5px] rounded-[3px]">`);
|
|
6
6
|
var _tmpl$2 = /*#__PURE__*/ template(`<span data-theme-miniature aria-hidden=true><span class="flex h-full w-11 shrink-0 flex-col gap-[7px] overflow-hidden px-2 pt-3.5"></span><span class="my-2 mr-2 flex min-w-0 flex-1 flex-col gap-[7px] overflow-hidden rounded-md border border-(--appearance-preview-border) p-2.5">`);
|
|
7
7
|
var _tmpl$3 = /*#__PURE__*/ template(`<span aria-hidden=true><span class="h-full w-1/2 overflow-hidden"></span><span class="h-full w-1/2 overflow-hidden">`);
|
|
8
|
-
var _tmpl$4 = /*#__PURE__*/ template(`<span aria-hidden=true>`);
|
|
9
|
-
var _tmpl$5 = /*#__PURE__*/ template(`<span
|
|
8
|
+
var _tmpl$4 = /*#__PURE__*/ template(`<span data-theme-menu-preview aria-hidden=true><span class="flex w-5 shrink-0 flex-col items-center gap-1.5 border-e border-(--appearance-preview-border) pt-2"><span class="size-1.5 rounded-[3px]"></span><span class="size-1.5 rounded-[3px]"></span><span class="size-1.5 rounded-[3px]"></span></span><span class="m-1 flex min-w-0 flex-1 flex-col gap-1 rounded-md border border-(--appearance-preview-border) p-1.5"><span class="h-1.5 w-8 rounded-full"></span><span class="h-1 w-full rounded-full"></span><span class="h-1 w-3/4 rounded-full"></span><span class="mt-auto flex items-center gap-1"><span class="h-2.5 w-7 rounded-[3px]"></span><span class="h-2.5 w-4 rounded-[3px]"></span><span class="h-2.5 w-4 rounded-[3px]">`);
|
|
9
|
+
var _tmpl$5 = /*#__PURE__*/ template(`<span aria-hidden=true>`);
|
|
10
|
+
var _tmpl$6 = /*#__PURE__*/ template(`<span class="h-full w-1/3">`);
|
|
10
11
|
function Bar(props) {
|
|
11
12
|
return (() => {
|
|
12
13
|
var _el$ = _tmpl$();
|
|
@@ -122,6 +123,54 @@ function ThemeMiniatureSplit(props) {
|
|
|
122
123
|
return _el$5;
|
|
123
124
|
})();
|
|
124
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* The dropdown-item preview: the ThemePreview composition (rail + panel +
|
|
128
|
+
* text bars + action row) at menu scale, so a menu item carries the theme's
|
|
129
|
+
* actual chrome rather than the three-band trigger swatch. `aria-hidden` —
|
|
130
|
+
* the item's accessible name stays the theme name.
|
|
131
|
+
*/
|
|
132
|
+
function ThemeMenuPreview(props) {
|
|
133
|
+
const colors = () => props.theme.colors;
|
|
134
|
+
return (() => {
|
|
135
|
+
var _el$8 = _tmpl$4(), _el$9 = _el$8.firstChild, _el$0 = _el$9.firstChild, _el$1 = _el$0.nextSibling, _el$10 = _el$1.nextSibling, _el$11 = _el$9.nextSibling, _el$12 = _el$11.firstChild, _el$13 = _el$12.nextSibling, _el$14 = _el$13.nextSibling, _el$16 = _el$14.nextSibling.firstChild, _el$17 = _el$16.nextSibling, _el$18 = _el$17.nextSibling;
|
|
136
|
+
effect((_p$) => {
|
|
137
|
+
var _v$8 = cn("flex h-16 w-28 shrink-0 overflow-hidden rounded-md border border-(--appearance-preview-border)", props.class), _v$9 = colors().surface, _v$0 = colors().border, _v$1 = colors().surfaceElevated, _v$10 = colors().accent, _v$11 = colors().surfaceActive, _v$12 = colors().surfaceActive, _v$13 = colors().background, _v$14 = colors().border, _v$15 = colors().text, _v$16 = colors().textMuted, _v$17 = colors().textMuted, _v$18 = colors().accent, _v$19 = colors().error, _v$20 = colors().surfaceActive;
|
|
138
|
+
_v$8 !== _p$.e && className(_el$8, _p$.e = _v$8);
|
|
139
|
+
_v$9 !== _p$.t && setStyleProperty(_el$8, "background-color", _p$.t = _v$9);
|
|
140
|
+
_v$0 !== _p$.a && setStyleProperty(_el$8, "--appearance-preview-border", _p$.a = _v$0);
|
|
141
|
+
_v$1 !== _p$.o && setStyleProperty(_el$9, "background-color", _p$.o = _v$1);
|
|
142
|
+
_v$10 !== _p$.i && setStyleProperty(_el$0, "background-color", _p$.i = _v$10);
|
|
143
|
+
_v$11 !== _p$.n && setStyleProperty(_el$1, "background-color", _p$.n = _v$11);
|
|
144
|
+
_v$12 !== _p$.s && setStyleProperty(_el$10, "background-color", _p$.s = _v$12);
|
|
145
|
+
_v$13 !== _p$.h && setStyleProperty(_el$11, "background-color", _p$.h = _v$13);
|
|
146
|
+
_v$14 !== _p$.r && setStyleProperty(_el$11, "--appearance-preview-border", _p$.r = _v$14);
|
|
147
|
+
_v$15 !== _p$.d && setStyleProperty(_el$12, "background-color", _p$.d = _v$15);
|
|
148
|
+
_v$16 !== _p$.l && setStyleProperty(_el$13, "background-color", _p$.l = _v$16);
|
|
149
|
+
_v$17 !== _p$.u && setStyleProperty(_el$14, "background-color", _p$.u = _v$17);
|
|
150
|
+
_v$18 !== _p$.c && setStyleProperty(_el$16, "background-color", _p$.c = _v$18);
|
|
151
|
+
_v$19 !== _p$.w && setStyleProperty(_el$17, "background-color", _p$.w = _v$19);
|
|
152
|
+
_v$20 !== _p$.m && setStyleProperty(_el$18, "background-color", _p$.m = _v$20);
|
|
153
|
+
return _p$;
|
|
154
|
+
}, {
|
|
155
|
+
e: void 0,
|
|
156
|
+
t: void 0,
|
|
157
|
+
a: void 0,
|
|
158
|
+
o: void 0,
|
|
159
|
+
i: void 0,
|
|
160
|
+
n: void 0,
|
|
161
|
+
s: void 0,
|
|
162
|
+
h: void 0,
|
|
163
|
+
r: void 0,
|
|
164
|
+
d: void 0,
|
|
165
|
+
l: void 0,
|
|
166
|
+
u: void 0,
|
|
167
|
+
c: void 0,
|
|
168
|
+
w: void 0,
|
|
169
|
+
m: void 0
|
|
170
|
+
});
|
|
171
|
+
return _el$8;
|
|
172
|
+
})();
|
|
173
|
+
}
|
|
125
174
|
function PalettePreview(props) {
|
|
126
175
|
const bands = () => [
|
|
127
176
|
props.theme.colors.surface,
|
|
@@ -129,30 +178,30 @@ function PalettePreview(props) {
|
|
|
129
178
|
props.theme.colors.accent
|
|
130
179
|
];
|
|
131
180
|
return (() => {
|
|
132
|
-
var _el$
|
|
133
|
-
insert(_el$
|
|
181
|
+
var _el$19 = _tmpl$5();
|
|
182
|
+
insert(_el$19, createComponent(For, {
|
|
134
183
|
get each() {
|
|
135
184
|
return bands();
|
|
136
185
|
},
|
|
137
186
|
children: (band) => (() => {
|
|
138
|
-
var _el$
|
|
139
|
-
setStyleProperty(_el$
|
|
140
|
-
return _el$
|
|
187
|
+
var _el$20 = _tmpl$6();
|
|
188
|
+
setStyleProperty(_el$20, "background-color", band);
|
|
189
|
+
return _el$20;
|
|
141
190
|
})()
|
|
142
191
|
}));
|
|
143
192
|
effect((_p$) => {
|
|
144
|
-
var _v$
|
|
145
|
-
_v$
|
|
146
|
-
_v$
|
|
193
|
+
var _v$21 = cn("flex h-[18px] w-[30px] shrink-0 overflow-hidden rounded-[5px] border border-(--appearance-preview-border)", props.class), _v$22 = props.theme.colors.border;
|
|
194
|
+
_v$21 !== _p$.e && className(_el$19, _p$.e = _v$21);
|
|
195
|
+
_v$22 !== _p$.t && setStyleProperty(_el$19, "--appearance-preview-border", _p$.t = _v$22);
|
|
147
196
|
return _p$;
|
|
148
197
|
}, {
|
|
149
198
|
e: void 0,
|
|
150
199
|
t: void 0
|
|
151
200
|
});
|
|
152
|
-
return _el$
|
|
201
|
+
return _el$19;
|
|
153
202
|
})();
|
|
154
203
|
}
|
|
155
204
|
//#endregion
|
|
156
|
-
export { PalettePreview, ThemeMiniature, ThemeMiniatureSplit };
|
|
205
|
+
export { PalettePreview, ThemeMenuPreview, ThemeMiniature, ThemeMiniatureSplit };
|
|
157
206
|
|
|
158
207
|
//# sourceMappingURL=theme-preview.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-preview.js","names":["AdeaTheme","For","cn","ThemeMiniatureProps","theme","corners","class","Bar","props","fraction","opacity","color","_el$","_tmpl$","_$effect","_p$","_v$","Math","round","_v$2","_v$3","e","_$setStyleProperty","t","a","undefined","ThemeMiniature","_el$2","_tmpl$2","_el$3","firstChild","_el$4","nextSibling","_$insert","_$createComponent","colors","foreground","_v$4","_v$5","surface","_v$6","background","_v$7","border","_$className","o","ThemeMiniatureSplit","light","dark","_el$5","_tmpl$3","_el$6","_el$7","PalettePreview","bands","accent","_el$8","_tmpl$4","each","children","band","_el$9","_tmpl$5","_v$8","_v$9","_$setStyleProperty","_$createComponent","_$className"],"sources":["../../../../src/components/composites/appearance-editor/theme-preview.tsx"],"sourcesContent":["/*\n * MIT License\n *\n * Copyright (c) 2026 Wing\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n/*\n * Substantially translated from Zeron crates/ui/src/settings/appearance.rs\n * `bar`, `miniature`, `miniature_split`, and `palette_preview`, revision\n * 30a9a9537c5ec96226c87f4bf349b6f77c5dfb59, via Adea's existing\n * packages/ui/src/components/theme-preview.tsx adaptation.\n * Retains the sidebar/pane decomposition, exact bar fractions and opacity,\n * split outer corners, and three-band palette strip. GPUI and Adea's local\n * ThemeVariant are replaced by Solid and the canonical AdeaTheme schema.\n * Dynamic inline colors are theme data; no palette is authored here.\n */\nimport type { AdeaTheme } from '@adea-ai/themes'\nimport { For } from 'solid-js'\nimport { cn } from '#lib/utils'\n\nexport type ThemeMiniatureProps = {\n theme: AdeaTheme\n corners?: 'all' | 'left' | 'right'\n class?: string\n}\n\nfunction Bar(props: { fraction: number; opacity: number; color: string }) {\n return (\n <span\n class=\"h-[5px] rounded-[3px]\"\n style={{\n width: `${Math.round(props.fraction * 100)}%`,\n 'background-color': props.color,\n opacity: props.opacity,\n }}\n />\n )\n}\n\nexport function ThemeMiniature(props: ThemeMiniatureProps) {\n return (\n <span\n data-theme-miniature\n aria-hidden=\"true\"\n class={cn(\n 'flex size-full overflow-hidden',\n {\n 'rounded-md': !props.corners || props.corners === 'all',\n 'rounded-l-md': props.corners === 'left',\n 'rounded-r-md': props.corners === 'right',\n },\n props.class\n )}\n style={{ 'background-color': props.theme.colors.surface }}\n >\n <span class=\"flex h-full w-11 shrink-0 flex-col gap-[7px] overflow-hidden px-2 pt-3.5\">\n <Bar fraction={0.7} opacity={0.34} color={props.theme.colors.foreground} />\n <Bar fraction={1} opacity={0.22} color={props.theme.colors.foreground} />\n <Bar fraction={0.85} opacity={0.22} color={props.theme.colors.foreground} />\n <Bar fraction={1} opacity={0.22} color={props.theme.colors.foreground} />\n </span>\n <span\n class=\"my-2 mr-2 flex min-w-0 flex-1 flex-col gap-[7px] overflow-hidden rounded-md border border-(--appearance-preview-border) p-2.5\"\n style={{\n 'background-color': props.theme.colors.background,\n '--appearance-preview-border': props.theme.colors.border,\n }}\n >\n <Bar fraction={0.62} opacity={0.34} color={props.theme.colors.foreground} />\n <Bar fraction={0.88} opacity={0.22} color={props.theme.colors.foreground} />\n <Bar fraction={0.76} opacity={0.22} color={props.theme.colors.foreground} />\n <Bar fraction={0.52} opacity={0.22} color={props.theme.colors.foreground} />\n </span>\n </span>\n )\n}\n\nexport function ThemeMiniatureSplit(props: { light: AdeaTheme; dark: AdeaTheme; class?: string }) {\n return (\n <span class={cn('flex size-full', props.class)} aria-hidden=\"true\">\n <span class=\"h-full w-1/2 overflow-hidden\">\n <ThemeMiniature theme={props.light} corners=\"left\" />\n </span>\n <span class=\"h-full w-1/2 overflow-hidden\">\n <ThemeMiniature theme={props.dark} corners=\"right\" />\n </span>\n </span>\n )\n}\n\nexport function PalettePreview(props: { theme: AdeaTheme; class?: string }) {\n const bands = () => [\n props.theme.colors.surface,\n props.theme.colors.background,\n props.theme.colors.accent,\n ]\n return (\n <span\n class={cn(\n 'flex h-[18px] w-[30px] shrink-0 overflow-hidden rounded-[5px] border border-(--appearance-preview-border)',\n props.class\n )}\n aria-hidden=\"true\"\n style={{ '--appearance-preview-border': props.theme.colors.border }}\n >\n <For each={bands()}>\n {(band) => <span class=\"h-full w-1/3\" style={{ 'background-color': band }} />}\n </For>\n </span>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"theme-preview.js","names":["AdeaTheme","For","cn","ThemeMiniatureProps","theme","corners","class","Bar","props","fraction","opacity","color","_el$","_tmpl$","_$effect","_p$","_v$","Math","round","_v$2","_v$3","e","_$setStyleProperty","t","a","undefined","ThemeMiniature","_el$2","_tmpl$2","_el$3","firstChild","_el$4","nextSibling","_$insert","_$createComponent","colors","foreground","_v$4","_v$5","surface","_v$6","background","_v$7","border","_$className","o","ThemeMiniatureSplit","light","dark","_el$5","_tmpl$3","_el$6","_el$7","ThemeMenuPreview","_el$8","_tmpl$4","_el$9","_el$0","_el$1","_el$10","_el$11","_el$12","_el$13","_el$14","_el$15","_el$16","_el$17","_el$18","_v$8","_v$9","_v$0","_v$1","surfaceElevated","_v$10","accent","_v$11","surfaceActive","_v$12","_v$13","_v$14","_v$15","text","_v$16","textMuted","_v$17","_v$18","_v$19","error","_v$20","i","n","s","h","r","d","l","u","c","w","m","PalettePreview","bands","_el$19","_tmpl$5","each","children","band","_el$20","_tmpl$6","_v$21","_v$22","_$setStyleProperty","_$createComponent","_$className"],"sources":["../../../../src/components/composites/appearance-editor/theme-preview.tsx"],"sourcesContent":["/*\n * MIT License\n *\n * Copyright (c) 2026 Wing\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n/*\n * Substantially translated from Zeron crates/ui/src/settings/appearance.rs\n * `bar`, `miniature`, `miniature_split`, and `palette_preview`, revision\n * 30a9a9537c5ec96226c87f4bf349b6f77c5dfb59, via Adea's existing\n * packages/ui/src/components/theme-preview.tsx adaptation.\n * Retains the sidebar/pane decomposition, exact bar fractions and opacity,\n * split outer corners, and three-band palette strip. GPUI and Adea's local\n * ThemeVariant are replaced by Solid and the canonical AdeaTheme schema.\n * Dynamic inline colors are theme data; no palette is authored here.\n */\nimport type { AdeaTheme } from '@adea-ai/themes'\nimport { For } from 'solid-js'\nimport { cn } from '#lib/utils'\n\nexport type ThemeMiniatureProps = {\n theme: AdeaTheme\n corners?: 'all' | 'left' | 'right'\n class?: string\n}\n\nfunction Bar(props: { fraction: number; opacity: number; color: string }) {\n return (\n <span\n class=\"h-[5px] rounded-[3px]\"\n style={{\n width: `${Math.round(props.fraction * 100)}%`,\n 'background-color': props.color,\n opacity: props.opacity,\n }}\n />\n )\n}\n\nexport function ThemeMiniature(props: ThemeMiniatureProps) {\n return (\n <span\n data-theme-miniature\n aria-hidden=\"true\"\n class={cn(\n 'flex size-full overflow-hidden',\n {\n 'rounded-md': !props.corners || props.corners === 'all',\n 'rounded-l-md': props.corners === 'left',\n 'rounded-r-md': props.corners === 'right',\n },\n props.class\n )}\n style={{ 'background-color': props.theme.colors.surface }}\n >\n <span class=\"flex h-full w-11 shrink-0 flex-col gap-[7px] overflow-hidden px-2 pt-3.5\">\n <Bar fraction={0.7} opacity={0.34} color={props.theme.colors.foreground} />\n <Bar fraction={1} opacity={0.22} color={props.theme.colors.foreground} />\n <Bar fraction={0.85} opacity={0.22} color={props.theme.colors.foreground} />\n <Bar fraction={1} opacity={0.22} color={props.theme.colors.foreground} />\n </span>\n <span\n class=\"my-2 mr-2 flex min-w-0 flex-1 flex-col gap-[7px] overflow-hidden rounded-md border border-(--appearance-preview-border) p-2.5\"\n style={{\n 'background-color': props.theme.colors.background,\n '--appearance-preview-border': props.theme.colors.border,\n }}\n >\n <Bar fraction={0.62} opacity={0.34} color={props.theme.colors.foreground} />\n <Bar fraction={0.88} opacity={0.22} color={props.theme.colors.foreground} />\n <Bar fraction={0.76} opacity={0.22} color={props.theme.colors.foreground} />\n <Bar fraction={0.52} opacity={0.22} color={props.theme.colors.foreground} />\n </span>\n </span>\n )\n}\n\nexport function ThemeMiniatureSplit(props: { light: AdeaTheme; dark: AdeaTheme; class?: string }) {\n return (\n <span class={cn('flex size-full', props.class)} aria-hidden=\"true\">\n <span class=\"h-full w-1/2 overflow-hidden\">\n <ThemeMiniature theme={props.light} corners=\"left\" />\n </span>\n <span class=\"h-full w-1/2 overflow-hidden\">\n <ThemeMiniature theme={props.dark} corners=\"right\" />\n </span>\n </span>\n )\n}\n\n/**\n * The dropdown-item preview: the ThemePreview composition (rail + panel +\n * text bars + action row) at menu scale, so a menu item carries the theme's\n * actual chrome rather than the three-band trigger swatch. `aria-hidden` —\n * the item's accessible name stays the theme name.\n */\nexport function ThemeMenuPreview(props: { theme: AdeaTheme; class?: string }) {\n const colors = () => props.theme.colors\n return (\n <span\n data-theme-menu-preview\n aria-hidden=\"true\"\n class={cn(\n 'flex h-16 w-28 shrink-0 overflow-hidden rounded-md border border-(--appearance-preview-border)',\n props.class\n )}\n style={{\n 'background-color': colors().surface,\n '--appearance-preview-border': colors().border,\n }}\n >\n <span\n class=\"flex w-5 shrink-0 flex-col items-center gap-1.5 border-e border-(--appearance-preview-border) pt-2\"\n style={{ 'background-color': colors().surfaceElevated }}\n >\n <span class=\"size-1.5 rounded-[3px]\" style={{ 'background-color': colors().accent }} />\n <span\n class=\"size-1.5 rounded-[3px]\"\n style={{ 'background-color': colors().surfaceActive }}\n />\n <span\n class=\"size-1.5 rounded-[3px]\"\n style={{ 'background-color': colors().surfaceActive }}\n />\n </span>\n <span\n class=\"m-1 flex min-w-0 flex-1 flex-col gap-1 rounded-md border border-(--appearance-preview-border) p-1.5\"\n style={{\n 'background-color': colors().background,\n '--appearance-preview-border': colors().border,\n }}\n >\n <span class=\"h-1.5 w-8 rounded-full\" style={{ 'background-color': colors().text }} />\n <span class=\"h-1 w-full rounded-full\" style={{ 'background-color': colors().textMuted }} />\n <span class=\"h-1 w-3/4 rounded-full\" style={{ 'background-color': colors().textMuted }} />\n <span class=\"mt-auto flex items-center gap-1\">\n <span class=\"h-2.5 w-7 rounded-[3px]\" style={{ 'background-color': colors().accent }} />\n <span class=\"h-2.5 w-4 rounded-[3px]\" style={{ 'background-color': colors().error }} />\n <span\n class=\"h-2.5 w-4 rounded-[3px]\"\n style={{ 'background-color': colors().surfaceActive }}\n />\n </span>\n </span>\n </span>\n )\n}\n\nexport function PalettePreview(props: { theme: AdeaTheme; class?: string }) {\n const bands = () => [\n props.theme.colors.surface,\n props.theme.colors.background,\n props.theme.colors.accent,\n ]\n return (\n <span\n class={cn(\n 'flex h-[18px] w-[30px] shrink-0 overflow-hidden rounded-[5px] border border-(--appearance-preview-border)',\n props.class\n )}\n aria-hidden=\"true\"\n style={{ '--appearance-preview-border': props.theme.colors.border }}\n >\n <For each={bands()}>\n {(band) => <span class=\"h-full w-1/3\" style={{ 'background-color': band }} />}\n </For>\n </span>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help-center.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/help-center/help-center.tsx"],"names":[],"mappings":"AAQA,MAAM,MAAM,YAAY,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAA;AACrE,MAAM,MAAM,QAAQ,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAC3E,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,SAAS,YAAY,EAAE,CAAA;IAClC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAA;IAC1B,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,2FAA2F;AAC3F,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"help-center.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/help-center/help-center.tsx"],"names":[],"mappings":"AAQA,MAAM,MAAM,YAAY,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAA;AACrE,MAAM,MAAM,QAAQ,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAC3E,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,SAAS,YAAY,EAAE,CAAA;IAClC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAA;IAC1B,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,2FAA2F;AAC3F,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,kCAqFhD"}
|
|
@@ -7,9 +7,9 @@ import { className, createComponent, effect, insert, memo, template } from "soli
|
|
|
7
7
|
import { ExternalLink } from "lucide-solid";
|
|
8
8
|
import { For, Show, createSignal, onCleanup } from "solid-js";
|
|
9
9
|
//#region src/components/composites/help-center/help-center.tsx
|
|
10
|
-
var _tmpl$ = /*#__PURE__*/ template(`<h2 class="text-base font-semibold text-
|
|
10
|
+
var _tmpl$ = /*#__PURE__*/ template(`<h2 class="text-base font-semibold text-foreground">Keyboard shortcuts`);
|
|
11
11
|
var _tmpl$2 = /*#__PURE__*/ template(`<ul class="flex flex-col gap-3">`);
|
|
12
|
-
var _tmpl$3 = /*#__PURE__*/ template(`<h2 class="text-base font-semibold text-
|
|
12
|
+
var _tmpl$3 = /*#__PURE__*/ template(`<h2 class="text-base font-semibold text-foreground">Project links`);
|
|
13
13
|
var _tmpl$4 = /*#__PURE__*/ template(`<ul class="flex flex-col gap-4">`);
|
|
14
14
|
var _tmpl$5 = /*#__PURE__*/ template(`<div><div class="flex flex-col gap-2"><h1 class="text-xl font-semibold tracking-tight">Help Center</h1><p class="text-sm text-muted-foreground">Keyboard shortcuts and resources for <!>.`);
|
|
15
15
|
var _tmpl$6 = /*#__PURE__*/ template(`<li class="flex flex-wrap items-center justify-between gap-2"><span class=text-sm>`);
|
|
@@ -75,6 +75,7 @@ function HelpCenter(props) {
|
|
|
75
75
|
as: "a",
|
|
76
76
|
variant: "link",
|
|
77
77
|
size: "sm",
|
|
78
|
+
"class": "text-foreground decoration-primary",
|
|
78
79
|
get href() {
|
|
79
80
|
return link.url;
|
|
80
81
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help-center.js","names":["createSignal","For","onCleanup","Show","ExternalLink","cn","ActionButton","Alert","AlertDescription","Card","CardContent","CardHeader","Kbd","KbdGroup","HelpShortcut","label","keys","HelpLink","description","url","HelpCenterProps","appName","shortcuts","links","openExternal","Promise","class","HelpCenter","props","error","setError","disposed","openLink","_el$","_tmpl$5","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$7","_el$6","_$insert","_$createComponent","children","_tmpl$","_el$9","_tmpl$2","each","shortcut","_el$10","_tmpl$6","_el$11","key","_tmpl$3","_el$1","_tmpl$4","link","_el$12","_tmpl$8","as","variant","size","href","target","rel","tooltip","onClick","event","preventDefault","_$memo","when","_el$13","_tmpl$7","role","_$effect","_$className","_$createComponent","_$memo","_$className"],"sources":["../../../../src/components/composites/help-center/help-center.tsx"],"sourcesContent":["import { createSignal, For, onCleanup, Show } from 'solid-js'\nimport { ExternalLink } from 'lucide-solid'\nimport { cn } from '#lib/utils'\nimport { ActionButton } from '../action-button'\nimport { Alert, AlertDescription } from '../../ui/alert'\nimport { Card, CardContent, CardHeader } from '../../ui/card'\nimport { Kbd, KbdGroup } from '../../ui/kbd'\n\nexport type HelpShortcut = { label: string; keys: readonly string[] }\nexport type HelpLink = { label: string; description?: string; url: string }\nexport type HelpCenterProps = {\n appName: string\n shortcuts: readonly HelpShortcut[]\n links: readonly HelpLink[]\n openExternal?: (url: string) => Promise<void>\n class?: string\n}\n\n/** A shared help page: real keyboard shortcuts and the application's project resources. */\nexport function HelpCenter(props: HelpCenterProps) {\n const [error, setError] = createSignal('')\n let disposed = false\n onCleanup(() => {\n disposed = true\n })\n const openLink = async (url: string) => {\n setError('')\n try {\n await props.openExternal?.(url)\n } catch {\n if (!disposed) setError('Could not open this help resource. Please try again.')\n }\n }\n return (\n <div class={cn('flex min-w-0 flex-col gap-5', props.class)}>\n <div class=\"flex flex-col gap-2\">\n <h1 class=\"text-xl font-semibold tracking-tight\">Help Center</h1>\n <p class=\"text-sm text-muted-foreground\">\n Keyboard shortcuts and resources for {props.appName}.\n </p>\n </div>\n <Card>\n <CardHeader>\n <h2 class=\"text-base font-semibold text-
|
|
1
|
+
{"version":3,"file":"help-center.js","names":["createSignal","For","onCleanup","Show","ExternalLink","cn","ActionButton","Alert","AlertDescription","Card","CardContent","CardHeader","Kbd","KbdGroup","HelpShortcut","label","keys","HelpLink","description","url","HelpCenterProps","appName","shortcuts","links","openExternal","Promise","class","HelpCenter","props","error","setError","disposed","openLink","_el$","_tmpl$5","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$7","_el$6","_$insert","_$createComponent","children","_tmpl$","_el$9","_tmpl$2","each","shortcut","_el$10","_tmpl$6","_el$11","key","_tmpl$3","_el$1","_tmpl$4","link","_el$12","_tmpl$8","as","variant","size","href","target","rel","tooltip","onClick","event","preventDefault","_$memo","when","_el$13","_tmpl$7","role","_$effect","_$className","_$createComponent","_$memo","_$className"],"sources":["../../../../src/components/composites/help-center/help-center.tsx"],"sourcesContent":["import { createSignal, For, onCleanup, Show } from 'solid-js'\nimport { ExternalLink } from 'lucide-solid'\nimport { cn } from '#lib/utils'\nimport { ActionButton } from '../action-button'\nimport { Alert, AlertDescription } from '../../ui/alert'\nimport { Card, CardContent, CardHeader } from '../../ui/card'\nimport { Kbd, KbdGroup } from '../../ui/kbd'\n\nexport type HelpShortcut = { label: string; keys: readonly string[] }\nexport type HelpLink = { label: string; description?: string; url: string }\nexport type HelpCenterProps = {\n appName: string\n shortcuts: readonly HelpShortcut[]\n links: readonly HelpLink[]\n openExternal?: (url: string) => Promise<void>\n class?: string\n}\n\n/** A shared help page: real keyboard shortcuts and the application's project resources. */\nexport function HelpCenter(props: HelpCenterProps) {\n const [error, setError] = createSignal('')\n let disposed = false\n onCleanup(() => {\n disposed = true\n })\n const openLink = async (url: string) => {\n setError('')\n try {\n await props.openExternal?.(url)\n } catch {\n if (!disposed) setError('Could not open this help resource. Please try again.')\n }\n }\n return (\n <div class={cn('flex min-w-0 flex-col gap-5', props.class)}>\n <div class=\"flex flex-col gap-2\">\n <h1 class=\"text-xl font-semibold tracking-tight\">Help Center</h1>\n <p class=\"text-sm text-muted-foreground\">\n Keyboard shortcuts and resources for {props.appName}.\n </p>\n </div>\n <Card>\n <CardHeader>\n <h2 class=\"text-base font-semibold text-foreground\">Keyboard shortcuts</h2>\n </CardHeader>\n <CardContent>\n <ul class=\"flex flex-col gap-3\">\n <For each={props.shortcuts}>\n {(shortcut) => (\n <li class=\"flex flex-wrap items-center justify-between gap-2\">\n <span class=\"text-sm\">{shortcut.label}</span>\n <KbdGroup>\n <For each={shortcut.keys}>{(key) => <Kbd>{key}</Kbd>}</For>\n </KbdGroup>\n </li>\n )}\n </For>\n </ul>\n </CardContent>\n </Card>\n <Card>\n <CardHeader>\n <h2 class=\"text-base font-semibold text-foreground\">Project links</h2>\n </CardHeader>\n <CardContent>\n <ul class=\"flex flex-col gap-4\">\n <For each={props.links}>\n {(link) => (\n <li class=\"flex min-w-0 flex-col items-start gap-1\">\n <ActionButton\n as=\"a\"\n variant=\"link\"\n size=\"sm\"\n class=\"text-foreground decoration-primary\"\n href={link.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n tooltip={`Open ${link.label} in your browser.`}\n onClick={(event) => {\n if (props.openExternal) {\n event.preventDefault()\n void openLink(link.url)\n }\n }}\n >\n {link.label}\n <ExternalLink aria-hidden=\"true\" />\n </ActionButton>\n <Show when={link.description}>\n <p class=\"text-sm text-muted-foreground\">{link.description}</p>\n </Show>\n </li>\n )}\n </For>\n </ul>\n </CardContent>\n </Card>\n <Show when={error()}>\n <Alert variant=\"destructive\" role=\"alert\">\n <AlertDescription>{error()}</AlertDescription>\n </Alert>\n </Show>\n </div>\n )\n}\n"],"mappings":"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"}
|
|
@@ -15,9 +15,9 @@ var _tmpl$3 = /*#__PURE__*/ template(`<section class="grid gap-2"aria-label="Upd
|
|
|
15
15
|
var _tmpl$4 = /*#__PURE__*/ template(`<p class="text-foreground flex items-center gap-2 text-sm"role=status> is up to date.`);
|
|
16
16
|
var _tmpl$5 = /*#__PURE__*/ template(`<p class="text-foreground flex items-center gap-2 text-sm"role=status>`);
|
|
17
17
|
var _tmpl$6 = /*#__PURE__*/ template(`<p class="text-foreground rounded-lg border border-destructive/35 bg-destructive-subtle px-3 py-2 text-sm"role=alert>`);
|
|
18
|
-
var _tmpl$7 = /*#__PURE__*/ template(`<div class="flex flex-col gap-2"><div class="flex items-center gap-2"><h2 id=update-release-notes class="text-sm font-semibold text-
|
|
19
|
-
var _tmpl$8 = /*#__PURE__*/ template(`<div class="flex flex-col gap-2"><h2 id=update-changelog class="text-sm font-semibold text-
|
|
20
|
-
var _tmpl$9 = /*#__PURE__*/ template(`<div class="flex min-h-0 flex-col gap-5 overflow-y-auto p-6"><section class="rounded-xl border border-border bg-background/45 p-4"aria-label="Version status"><div class="flex flex-wrap items-start justify-between gap-4"><div class="flex flex-col gap-1"><p class="text-2xs font-semibold tracking-widest text-muted-foreground uppercase">Installed version</p><p class="text-xl font-semibold tracking-tight text-
|
|
18
|
+
var _tmpl$7 = /*#__PURE__*/ template(`<div class="flex flex-col gap-2"><div class="flex items-center gap-2"><h2 id=update-release-notes class="text-sm font-semibold text-foreground">What changed in this release</h2></div><div class="max-h-52 overflow-y-auto rounded-xl border border-border bg-background/45 p-4 font-mono text-xs leading-5 whitespace-pre-wrap text-muted-foreground"role=region aria-labelledby=update-release-notes tabindex=0>`);
|
|
19
|
+
var _tmpl$8 = /*#__PURE__*/ template(`<div class="flex flex-col gap-2"><h2 id=update-changelog class="text-sm font-semibold text-foreground">Installed changelog</h2><p class="text-xs text-muted-foreground">All versions and updates included with this installation.</p><div class="max-h-72 overflow-y-auto rounded-xl border border-border bg-background/45 p-4 font-mono text-xs leading-5 whitespace-pre-wrap text-muted-foreground"role=region aria-labelledby=update-changelog tabindex=0>`);
|
|
20
|
+
var _tmpl$9 = /*#__PURE__*/ template(`<div class="flex min-h-0 flex-col gap-5 overflow-y-auto p-6"><section class="rounded-xl border border-border bg-background/45 p-4"aria-label="Version status"><div class="flex flex-wrap items-start justify-between gap-4"><div class="flex flex-col gap-1"><p class="text-2xs font-semibold tracking-widest text-muted-foreground uppercase">Installed version</p><p class="text-xl font-semibold tracking-tight text-foreground">v</p><p class="text-sm text-muted-foreground">`);
|
|
21
21
|
var _tmpl$0 = /*#__PURE__*/ template(`<img alt class=size-10 aria-hidden=true>`);
|
|
22
22
|
var _tmpl$1 = /*#__PURE__*/ template(`<p class="text-xs text-muted-foreground">Released `);
|
|
23
23
|
function messageText(value) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-dialog.js","names":["createEffect","createMemo","createSignal","onCleanup","onMount","Show","splitProps","Accessor","Check","CircleStop","Download","ExternalLink","LoaderCircle","Monitor","RefreshCw","Sparkles","Badge","Button","ActionButton","Dialog","DialogClose","DialogContent","DialogDescription","DialogFooter","DialogHeader","DialogTitle","DialogTrigger","createDialogFocusRestoration","Progress","cn","formatBytes","formatReleaseDate","plainTextFromMarkdown","UpdatePhase","UpdateState","Readonly","phase","currentVersion","availableVersion","changelog","releaseNotes","releaseDate","downloadedBytes","totalBytes","error","releaseUrl","restartRequired","UpdateAdapter","getStatus","Promise","check","install","expectedVersion","cancel","pollIntervalMs","openExternal","url","isDesktopRuntime","UpdateDialogProps","adapter","appName","appIcon","fallbackVersion","desktopOnlyMessage","open","defaultOpen","onOpenChange","restoreFocusRef","HTMLElement","class","messageText","value","undefined","message","trim","errorMessage","caught","fallback","Error","plainMessage","record","safe","nestedError","isBusy","state","UpdateDialog","props","local","uncontrolledOpen","setUncontrolledOpen","setOpen","next","focusRestoration","desktop","setState","busy","setBusy","setError","checkFailed","setCheckFailed","cancelPending","setCancelPending","lifecycleEpoch","activeOpenEpoch","disposed","loadStatus","isCurrent","status","previous","hasActionableSnapshot","candidate","preservesSnapshot","epoch","failCheck","applyCheckResult","current","checked","active","version","includes","requestInFlight","timer","window","setInterval","Math","max","clearInterval","openRelease","notes","working","triggerLabel","progressValue","min","round","_$createComponent","children","when","as","variant","size","_$memo","onKeyDown","event","KeyboardEvent","key","defaultPrevented","preventDefault","onOpenAutoFocus","currentTarget","focus","preventScroll","onCloseAutoFocus","_el$","_tmpl$","_el$2","firstChild","_$insert","icon","_el$34","_tmpl$0","_$effect","_$setAttribute","_el$3","_tmpl$9","_el$4","_el$5","_el$6","_el$7","_el$8","nextSibling","_el$9","_el$0","type","tooltip","disabled","onClick","_el$1","_tmpl$2","_el$10","_el$11","_el$12","_el$13","_el$15","_el$14","_el$16","_el$17","_el$19","_el$18","released","_el$35","_tmpl$1","_el$36","_el$20","_tmpl$3","_el$21","aria-label","_el$22","_tmpl$4","_el$23","_el$24","_tmpl$5","_el$25","_tmpl$6","_el$26","_tmpl$7","_el$27","_el$28","_el$29","_el$30","_tmpl$8","_el$31","_el$32","_el$33","_$createComponent","_$memo","_$setAttribute"],"sources":["../../../../src/components/composites/update-dialog/update-dialog.tsx"],"sourcesContent":["import {\n createEffect,\n createMemo,\n createSignal,\n onCleanup,\n onMount,\n Show,\n splitProps,\n} from 'solid-js'\nimport type { Accessor } from 'solid-js'\nimport {\n Check,\n CircleStop,\n Download,\n ExternalLink,\n LoaderCircle,\n Monitor,\n RefreshCw,\n Sparkles,\n} from 'lucide-solid'\nimport { Badge } from '../../ui/badge'\nimport { Button } from '../../ui/button'\nimport { ActionButton } from '../action-button'\nimport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from '../../ui/dialog'\nimport { createDialogFocusRestoration } from '../../ui/dialog/dialog'\nimport { Progress } from '../../ui/progress'\nimport { cn } from '#lib/utils'\nimport { formatBytes, formatReleaseDate, plainTextFromMarkdown } from '#lib/version-notes'\n\n/**\n * UpdateDialog.\n *\n * A software-update surface: the installed version, whether a newer release\n * exists, a download that shows its progress, and the release notes for what is\n * about to arrive.\n *\n * The transport is an adapter, because an update is the one thing a component\n * library genuinely cannot implement: it is signed, downloaded and applied by the\n * application's own updater, and the mechanism differs per shell. What *is*\n * general is the phase machine and the way each phase is presented — and that is\n * where the hard-won detail lives:\n *\n * **A refused install answers with a normal payload, not a rejection.** adea's\n * shell returns a status whose phase is `failed` when a download or an extract\n * fails, rather than throwing. Without handling that, clicking install looked like\n * nothing happened at all — the button spun, the phase never changed, and the\n * error sat unread in a field nobody rendered. The `failed` phase after an install\n * is therefore surfaced as an error, explicitly.\n *\n * **Busy is derived from the snapshot as well as from the click.** An update can\n * be downloading while the dialog is open — started before it opened, or by the\n * shell's own poll — so a local `busy` flag alone would offer an enabled Install\n * button mid-download.\n *\n * **Opening the dialog loads status first, then checks.** Status paints the\n * installed version immediately; the check is a network round trip. Doing them in\n * the other order leaves the dialog blank for as long as the check takes, on a\n * dialog whose first question is always \"what am I running?\".\n *\n * **A failed check is not a current result.** A cached `current` status can only\n * be shown as up to date after the latest check succeeds; a failed check remains\n * retryable and suppresses that claim.\n *\n * **Errors are not always `Error`s.** An adapter can reject with a string or a\n * structured safe message. Unknown object fields are never serialized into the\n * UI; a generic fallback is shown instead.\n *\n * The adapter's `isDesktopRuntime` gate exists because an update is a desktop\n * concern: a browser build has no installer, and the honest thing to show is that\n * updates are available in the desktop application rather than a disabled button\n * with no reason.\n */\n\n/** The phase an update is in. The union is the state machine. */\nexport type UpdatePhase =\n | 'idle'\n | 'checking'\n | 'current'\n | 'available'\n | 'downloading'\n | 'installing'\n | 'installed'\n | 'cancelling'\n | 'cancelled'\n | 'unavailable'\n | 'failed'\n\n/** A snapshot of the updater. Every field the dialog renders, and nothing else. */\nexport type UpdateState = Readonly<{\n phase: UpdatePhase\n /** The version currently installed. */\n currentVersion: string\n /** The version that can be installed, when one can. */\n availableVersion?: string | null\n /** A changelog for the installed channel, as markdown. */\n changelog?: string\n /** Notes for the available release, as markdown. */\n releaseNotes?: string | null\n /** The available release's date, as an ISO string. */\n releaseDate?: string | null\n /** Bytes downloaded so far, during `downloading`. */\n downloadedBytes?: number\n /** Total bytes, when the server sent a length. */\n totalBytes?: number | null\n /** Set when `phase` is `failed`, and sometimes when it is not. */\n error?: string | null\n /** A URL for the release's page. */\n releaseUrl?: string | null\n /** True when the application must restart to finish. */\n restartRequired?: boolean\n}>\n\n/**\n * The updater, as the application exposes it. Three calls, each answering with a\n * full snapshot rather than a delta — an updater's state is small, and a snapshot\n * cannot drift from the shell's own view of it.\n */\nexport type UpdateAdapter = Readonly<{\n /** The current state, without contacting the release channel. */\n getStatus(): Promise<UpdateState>\n /** Ask the release channel, and answer with what it found. */\n check(): Promise<UpdateState>\n /**\n * Download and apply `expectedVersion`.\n *\n * The argument is the version the caller believes is available, so the updater\n * can refuse a request that raced a newer release rather than installing the\n * wrong one.\n */\n install(expectedVersion: string): Promise<UpdateState>\n /** Optional native cancellation, available only while work is in flight. */\n cancel?(): Promise<UpdateState>\n /** Enable status polling during native work; omit for push-driven adapters. */\n pollIntervalMs?: number\n /** Route external links through the native shell when needed. */\n openExternal?(url: string): Promise<void>\n /** False in a browser build, where there is no installer to drive. */\n isDesktopRuntime(): boolean\n}>\n\nexport type UpdateDialogProps = {\n adapter: UpdateAdapter\n /** The application's name, used in the title and the copy. */\n appName?: string\n /** The actual desktop application icon, supplied by its host. */\n appIcon?: string\n /** Complete build-time history, also available before the native status arrives. */\n changelog?: string\n /** Shown before the first status arrives, so the dialog is never blank. */\n fallbackVersion?: string\n /** Copy for the adapter's non-desktop case. */\n desktopOnlyMessage?: string\n /** A controlled open state. Omit for the trigger to manage its own. */\n open?: boolean\n /**\n * Start open, uncontrolled — for a caller that opens the dialog because it found\n * something (\"an update is available\") rather than because the user asked. The\n * trigger is still rendered, so the dialog is reachable again after closing.\n */\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n /**\n * Supplies a stable external control to focus when a controlled dialog closes.\n * Useful when a menu or other layer closes before this dialog opens; when omitted,\n * the element focused immediately before the dialog opens is used when available.\n */\n restoreFocusRef?: Accessor<HTMLElement | undefined>\n /** Render only the panel, for a caller that provides its own dialog. */\n class?: string\n}\n\nfunction messageText(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined\n const message = value.trim()\n return message && message !== '[object Object]' ? message : undefined\n}\n\nfunction errorMessage(caught: unknown, fallback: string): string {\n if (caught instanceof Error) return messageText(caught.message) ?? fallback\n const plainMessage = messageText(caught)\n if (plainMessage) return plainMessage\n if (!caught || typeof caught !== 'object') return fallback\n\n const record = caught as { error?: unknown; safe?: unknown }\n const safe = record.safe as { message?: unknown } | null | undefined\n const nestedError = record.error as { safe?: { message?: unknown } | null } | null | undefined\n return messageText(safe?.message) ?? messageText(nestedError?.safe?.message) ?? fallback\n}\n\n/**\n * The phases during which the updater is working. `downloading` and `installing`\n * are included because the shell can be in either while the dialog is open, and\n * offering an enabled Install button during a download is how a double-install\n * happens.\n */\nfunction isBusy(state: UpdateState | null): boolean {\n return (\n state?.phase === 'checking' ||\n state?.phase === 'downloading' ||\n state?.phase === 'installing' ||\n state?.phase === 'cancelling'\n )\n}\n\nexport function UpdateDialog(props: UpdateDialogProps) {\n const [local] = splitProps(props, [\n 'adapter',\n 'appName',\n 'appIcon',\n 'changelog',\n 'fallbackVersion',\n 'desktopOnlyMessage',\n 'open',\n 'defaultOpen',\n 'onOpenChange',\n 'restoreFocusRef',\n 'class',\n ])\n\n const [uncontrolledOpen, setUncontrolledOpen] = createSignal(local.defaultOpen ?? false)\n const open = () => local.open ?? uncontrolledOpen()\n const setOpen = (next: boolean) => {\n if (local.open === undefined) setUncontrolledOpen(next)\n local.onOpenChange?.(next)\n }\n\n const focusRestoration = createDialogFocusRestoration({\n open,\n restoreFocusRef: local.restoreFocusRef,\n })\n\n const appName = () => local.appName ?? 'the application'\n const desktop = () => local.adapter.isDesktopRuntime()\n const [state, setState] = createSignal<UpdateState | null>(null)\n const [busy, setBusy] = createSignal(false)\n const [error, setError] = createSignal('')\n const [checkFailed, setCheckFailed] = createSignal(false)\n const [cancelPending, setCancelPending] = createSignal(false)\n let lifecycleEpoch = 0\n let activeOpenEpoch: number | undefined\n let disposed = false\n\n onCleanup(() => {\n disposed = true\n activeOpenEpoch = undefined\n lifecycleEpoch += 1\n })\n\n const loadStatus = async (isCurrent: () => boolean = () => !disposed) => {\n if (!desktop() || !isCurrent()) return\n try {\n const status = await local.adapter.getStatus()\n const previous = state()\n const hasActionableSnapshot = (candidate: UpdateState | null) =>\n candidate?.phase === 'available' || isBusy(candidate)\n const preservesSnapshot =\n previous?.phase === 'available'\n ? status.phase === 'available' || isBusy(status)\n : isBusy(previous) && isBusy(status)\n if (\n isCurrent() &&\n !(checkFailed() && hasActionableSnapshot(previous) && !preservesSnapshot)\n ) {\n setState(status)\n }\n } catch (caught) {\n if (isCurrent()) setError(errorMessage(caught, 'Version status is unavailable'))\n }\n }\n\n onMount(() => {\n if (desktop() && !open()) {\n const epoch = lifecycleEpoch\n void loadStatus(() => !disposed && lifecycleEpoch === epoch)\n }\n })\n\n const failCheck = (caught: unknown, fallback: string) => {\n const message = errorMessage(caught, fallback)\n setCheckFailed(true)\n setError(message)\n }\n\n const applyCheckResult = (next: UpdateState) => {\n if (next.phase === 'failed') {\n const current = state()\n if (!current) setState(next)\n failCheck(next.error, 'Could not check for updates')\n return\n }\n setState(next)\n setCheckFailed(false)\n setError('')\n }\n\n const check = async () => {\n if (!desktop()) {\n setError(local.desktopOnlyMessage ?? `Update checks are available from the desktop app.`)\n return\n }\n const epoch = activeOpenEpoch\n const isCurrent = () =>\n !disposed &&\n epoch !== undefined &&\n activeOpenEpoch === epoch &&\n lifecycleEpoch === epoch &&\n open()\n if (!isCurrent()) return\n setBusy(true)\n setError('')\n setCheckFailed(false)\n try {\n const checked = await local.adapter.check()\n if (isCurrent()) applyCheckResult(checked)\n } catch (caught) {\n if (isCurrent()) {\n failCheck(caught, 'Could not check for updates')\n await loadStatus(isCurrent)\n }\n } finally {\n if (isCurrent()) setBusy(false)\n }\n }\n\n /**\n * Status first, then the check — and an `active` flag, because the dialog can\n * close while the check is in flight and a late `setState` would write into a\n * disposed scope.\n */\n createEffect(() => {\n if (!open() || !desktop()) {\n setCancelPending(false)\n if (activeOpenEpoch !== undefined) {\n activeOpenEpoch = undefined\n lifecycleEpoch += 1\n }\n return\n }\n const epoch = ++lifecycleEpoch\n activeOpenEpoch = epoch\n let active = true\n const isCurrent = () =>\n active && !disposed && activeOpenEpoch === epoch && lifecycleEpoch === epoch && open()\n onCleanup(() => {\n active = false\n if (activeOpenEpoch === epoch) {\n activeOpenEpoch = undefined\n lifecycleEpoch += 1\n }\n })\n setError('')\n setCheckFailed(false)\n setCancelPending(false)\n setBusy(true)\n void (async () => {\n try {\n const current = await local.adapter.getStatus()\n if (!isCurrent()) return\n setState(current)\n const checked = await local.adapter.check()\n if (isCurrent()) applyCheckResult(checked)\n } catch (caught) {\n if (isCurrent()) failCheck(caught, 'Could not check for updates')\n } finally {\n if (isCurrent()) setBusy(false)\n }\n })()\n })\n\n const install = async () => {\n const version = state()?.availableVersion\n const epoch = activeOpenEpoch\n const isCurrent = () =>\n !disposed &&\n epoch !== undefined &&\n activeOpenEpoch === epoch &&\n lifecycleEpoch === epoch &&\n open()\n if (!version || !isCurrent()) return\n setBusy(true)\n setError('')\n setState((current) =>\n current ? { ...current, phase: 'downloading', downloadedBytes: 0, totalBytes: null } : current\n )\n try {\n const next = await local.adapter.install(version)\n if (!isCurrent()) return\n setState(\n cancelPending() && ['downloading', 'installing'].includes(next.phase)\n ? { ...next, phase: 'cancelling' }\n : next\n )\n // A refused install answers with a normal payload whose phase is `failed`.\n // Without this the click looked like nothing happened.\n if (next.phase === 'failed') {\n setError(errorMessage(next.error, 'Update installation failed'))\n } else {\n setCheckFailed(false)\n }\n } catch (caught) {\n if (!isCurrent()) return\n setError(errorMessage(caught, 'Update installation failed'))\n await loadStatus(isCurrent)\n } finally {\n if (isCurrent()) setBusy(false)\n }\n }\n\n // Poll only an open, active native operation. Epoch ownership prevents a late\n // status response from replacing a reopened dialog's newer snapshot.\n createEffect(() => {\n const phase = state()?.phase\n if (\n !open() ||\n !desktop() ||\n !local.adapter.pollIntervalMs ||\n !['downloading', 'installing', 'cancelling'].includes(phase ?? '')\n )\n return\n const epoch = activeOpenEpoch\n let active = true\n let requestInFlight = false\n const timer = window.setInterval(\n () => {\n if (requestInFlight) return\n requestInFlight = true\n void (async () => {\n try {\n const next = await local.adapter.getStatus()\n if (!active || disposed || !open() || activeOpenEpoch !== epoch) return\n setState(\n cancelPending() && ['downloading', 'installing'].includes(next.phase)\n ? { ...next, phase: 'cancelling' }\n : next\n )\n if (next.phase === 'failed')\n setError(errorMessage(next.error, 'Update installation failed'))\n } catch (caught) {\n if (active && !disposed && activeOpenEpoch === epoch)\n setError(errorMessage(caught, 'Update progress is unavailable'))\n } finally {\n requestInFlight = false\n }\n })()\n },\n Math.max(250, local.adapter.pollIntervalMs)\n )\n onCleanup(() => {\n active = false\n window.clearInterval(timer)\n })\n })\n\n const cancel = async () => {\n if (!local.adapter.cancel || cancelPending() || state()?.phase === 'cancelling') return\n const epoch = activeOpenEpoch\n setError('')\n setCancelPending(true)\n setState((current) => (current ? { ...current, phase: 'cancelling' } : current))\n try {\n const next = await local.adapter.cancel()\n if (!disposed && open() && activeOpenEpoch === epoch) setState(next)\n } catch (caught) {\n if (!disposed && open() && activeOpenEpoch === epoch) {\n setError(errorMessage(caught, 'Could not cancel the update'))\n await loadStatus(() => !disposed && open() && activeOpenEpoch === epoch)\n }\n } finally {\n if (!disposed && open() && activeOpenEpoch === epoch) setCancelPending(false)\n }\n }\n\n const openRelease = async (url: string) => {\n try {\n if (local.adapter.openExternal) await local.adapter.openExternal(url)\n else window.open(url, '_blank', 'noopener,noreferrer')\n } catch (caught) {\n if (!disposed) setError(errorMessage(caught, 'Could not open the release page'))\n }\n }\n\n const changelog = createMemo(() =>\n plainTextFromMarkdown(state()?.changelog || local.changelog || '')\n )\n const notes = () => {\n const value = state()?.releaseNotes\n return value ? plainTextFromMarkdown(value) : ''\n }\n const working = () => busy() || cancelPending() || isBusy(state())\n const isCurrent = () => state()?.phase === 'current' && !error() && !checkFailed() && !working()\n\n const triggerLabel = () => {\n const current = state()\n const fallback = `v${local.fallbackVersion ?? '0.1.0'}`\n if (checkFailed()) return `Version ${current?.currentVersion || fallback} · Retry`\n if (!current) return `${appName()} ${fallback}`\n switch (current.phase) {\n case 'checking':\n return 'Checking for updates…'\n case 'available':\n return current.availableVersion\n ? `Update v${current.availableVersion} available`\n : 'Update available'\n case 'downloading':\n case 'installing':\n return 'Installing update…'\n case 'failed':\n return `Version ${current.currentVersion || fallback} · Retry`\n default:\n return `${appName()} v${current.currentVersion || fallback}`\n }\n }\n\n const progressValue = () => {\n const current = state()\n if (!current?.totalBytes || !current.downloadedBytes) return null\n return Math.min(100, Math.round((current.downloadedBytes / current.totalBytes) * 100))\n }\n\n return (\n <Dialog open={open()} onOpenChange={setOpen}>\n <Show when={local.open === undefined}>\n <DialogTrigger\n as={Button}\n variant=\"ghost\"\n size=\"sm\"\n aria-label=\"Open version and updates\"\n aria-haspopup=\"dialog\"\n >\n <Show when={state()?.phase === 'available'} fallback={<RefreshCw aria-hidden=\"true\" />}>\n <Sparkles aria-hidden=\"true\" />\n </Show>\n {triggerLabel()}\n </DialogTrigger>\n </Show>\n\n <DialogContent\n class={cn('max-w-3xl', local.class)}\n onKeyDown={(event: KeyboardEvent) => {\n // An explanatory tooltip must not consume the popup's close shortcut,\n // including while its exit animation still owns Kobalte's top layer.\n if (event.key === 'Escape' && !event.defaultPrevented) {\n event.preventDefault()\n setOpen(false)\n }\n }}\n onOpenAutoFocus={(event) => {\n focusRestoration.onOpenAutoFocus(event)\n // Start at the readable panel rather than opening an action's tooltip.\n if (!event.defaultPrevented && event.currentTarget instanceof HTMLElement) {\n event.preventDefault()\n event.currentTarget.focus({ preventScroll: true })\n }\n }}\n onCloseAutoFocus={focusRestoration.onCloseAutoFocus}\n >\n <DialogHeader>\n <div class=\"flex items-center gap-3\">\n <Show\n when={local.appIcon}\n fallback={<Monitor class=\"size-10 text-primary\" aria-hidden=\"true\" />}\n >\n {(icon) => <img src={icon()} alt=\"\" class=\"size-10\" aria-hidden=\"true\" />}\n </Show>\n <div>\n <DialogTitle>Version & updates</DialogTitle>\n <DialogDescription>\n Keep {appName()} current and review what changed in each release.\n </DialogDescription>\n </div>\n </div>\n </DialogHeader>\n\n <div class=\"flex min-h-0 flex-col gap-5 overflow-y-auto p-6\">\n <section\n class=\"rounded-xl border border-border bg-background/45 p-4\"\n aria-label=\"Version status\"\n >\n <div class=\"flex flex-wrap items-start justify-between gap-4\">\n <div class=\"flex flex-col gap-1\">\n <p class=\"text-2xs font-semibold tracking-widest text-muted-foreground uppercase\">\n Installed version\n </p>\n <p class=\"text-xl font-semibold tracking-tight text-primary\">\n v{state()?.currentVersion || local.fallbackVersion || '0.1.0'}\n </p>\n <p class=\"text-sm text-muted-foreground\">\n <Show\n when={isCurrent()}\n fallback={\n <Show\n when={state()?.phase === 'available' && state()?.availableVersion}\n fallback={\n state()?.phase === 'unavailable'\n ? 'No signed package is published for this platform.'\n : state()?.phase === 'cancelled'\n ? 'Update cancelled. You can retry when ready.'\n : desktop()\n ? 'Check the release channel for the latest signed build.'\n : (local.desktopOnlyMessage ??\n `Open this dialog inside the desktop app to check for updates.`)\n }\n >\n {`A newer release, v${state()?.availableVersion}, is ready.`}\n </Show>\n }\n >\n You are running the latest release.\n </Show>\n </p>\n </div>\n <ActionButton\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n tooltip=\"Check the release channel for the latest signed app version.\"\n disabled={!desktop() || working()}\n onClick={() => void check()}\n >\n <Show when={working()} fallback={<RefreshCw aria-hidden=\"true\" />}>\n <LoaderCircle class=\"animate-spin\" aria-hidden=\"true\" />\n </Show>\n {checkFailed() ? 'Retry update check' : 'Check latest version'}\n </ActionButton>\n </div>\n </section>\n\n <Show\n when={\n state()?.availableVersion &&\n state()?.phase !== 'installed' &&\n state()?.phase !== 'unavailable'\n }\n >\n <section\n class=\"rounded-xl border border-primary/35 bg-primary-subtle p-4\"\n aria-label=\"Available update\"\n >\n <div class=\"flex flex-wrap items-start justify-between gap-4\">\n <div class=\"flex flex-col gap-1\">\n <p class=\"flex items-center gap-2 text-sm font-semibold\">\n <Sparkles class=\"size-4 text-primary\" aria-hidden=\"true\" />\n Version {state()?.availableVersion}{' '}\n {['downloading', 'installing', 'cancelling'].includes(state()?.phase ?? '')\n ? 'is being prepared'\n : 'is ready'}\n </p>\n <p class=\"text-sm text-muted-foreground\">\n The signed installer is verified before {appName()} restarts.\n </p>\n <Show when={formatReleaseDate(state()?.releaseDate ?? null)}>\n {(released) => (\n <p class=\"text-xs text-muted-foreground\">Released {released()}</p>\n )}\n </Show>\n </div>\n <ActionButton\n type=\"button\"\n size=\"sm\"\n tooltip={`Download the signed update and restart ${appName()}.`}\n disabled={working()}\n onClick={() => void install()}\n >\n <Show when={working()} fallback={<Download aria-hidden=\"true\" />}>\n <LoaderCircle class=\"animate-spin\" aria-hidden=\"true\" />\n </Show>\n Install and restart\n </ActionButton>\n </div>\n </section>\n </Show>\n\n {/*\n Progress with both numbers: a bar alone does not distinguish a stalled\n download from a slow one, and \"12.4 MB of 48.1 MB\" does.\n */}\n <Show\n when={\n state()?.phase === 'downloading' ||\n state()?.phase === 'installing' ||\n state()?.phase === 'cancelling'\n }\n >\n <section class=\"grid gap-2\" aria-label=\"Update progress\">\n <Progress\n value={progressValue() ?? undefined}\n aria-label={\n state()?.phase === 'installing' ? 'Installing update' : 'Downloading update'\n }\n />\n <p class=\"text-xs text-muted-foreground\" role=\"status\">\n <Show\n when={state()?.phase === 'installing'}\n fallback={\n <Show when={progressValue() !== null} fallback=\"Downloading…\">\n {`${formatBytes(state()?.downloadedBytes ?? 0)} of ${formatBytes(\n state()?.totalBytes ?? 0\n )} · ${progressValue()}%`}\n </Show>\n }\n >\n Applying the update…\n </Show>\n </p>\n <Show when={local.adapter.cancel}>\n <ActionButton\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n tooltip=\"Stop the current update download or installation.\"\n disabled={cancelPending() || state()?.phase === 'cancelling'}\n onClick={() => void cancel()}\n >\n <CircleStop aria-hidden=\"true\" />\n {cancelPending() || state()?.phase === 'cancelling'\n ? 'Cancelling…'\n : 'Cancel update'}\n </ActionButton>\n </Show>\n </section>\n </Show>\n\n <Show when={isCurrent()}>\n <p class=\"text-foreground flex items-center gap-2 text-sm\" role=\"status\">\n <Check class=\"size-4 text-success\" aria-hidden=\"true\" />\n {appName()} is up to date.\n </p>\n </Show>\n\n <Show when={state()?.phase === 'installed'}>\n <p class=\"text-foreground flex items-center gap-2 text-sm\" role=\"status\">\n <Check class=\"size-4 text-success\" aria-hidden=\"true\" />\n <Show when={state()?.restartRequired} fallback=\"The update is applied.\">\n Restart {appName()} to finish the update.\n </Show>\n </p>\n </Show>\n\n <Show when={error()}>\n <p\n class=\"text-foreground rounded-lg border border-destructive/35 bg-destructive-subtle px-3 py-2 text-sm\"\n role=\"alert\"\n >\n {error()}\n </p>\n </Show>\n\n <Show when={notes()}>\n <div class=\"flex flex-col gap-2\">\n <div class=\"flex items-center gap-2\">\n <h2 id=\"update-release-notes\" class=\"text-sm font-semibold text-primary\">\n What changed in this release\n </h2>\n <Badge variant=\"subtle\" size=\"sm\">\n v{state()?.availableVersion}\n </Badge>\n </div>\n {/* A long text block with no focusable descendant: it needs its own tab\n stop, named by the heading above it, or a keyboard user cannot\n scroll it (`scrollable-region-focusable`). */}\n <div\n class=\"max-h-52 overflow-y-auto rounded-xl border border-border bg-background/45 p-4 font-mono text-xs leading-5 whitespace-pre-wrap text-muted-foreground\"\n role=\"region\"\n aria-labelledby=\"update-release-notes\"\n tabindex=\"0\"\n >\n {notes()}\n </div>\n </div>\n </Show>\n\n <Show when={changelog()}>\n <div class=\"flex flex-col gap-2\">\n <h2 id=\"update-changelog\" class=\"text-sm font-semibold text-primary\">\n Installed changelog\n </h2>\n <p class=\"text-xs text-muted-foreground\">\n All versions and updates included with this installation.\n </p>\n {/* A long text block with no focusable descendant: it needs its own tab\n stop, named by the heading above it, or a keyboard user cannot\n scroll it (`scrollable-region-focusable`). */}\n <div\n class=\"max-h-72 overflow-y-auto rounded-xl border border-border bg-background/45 p-4 font-mono text-xs leading-5 whitespace-pre-wrap text-muted-foreground\"\n role=\"region\"\n aria-labelledby=\"update-changelog\"\n tabindex=\"0\"\n >\n {changelog()}\n </div>\n </div>\n </Show>\n </div>\n\n <DialogFooter>\n <Show when={state()?.releaseUrl}>\n {(url) => (\n <ActionButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n tooltip=\"Open the release history in your browser.\"\n // `noopener,noreferrer` because the release page is a different\n // origin and must not get a handle on this window.\n onClick={() => void openRelease(url())}\n >\n <ExternalLink aria-hidden=\"true\" />\n View releases\n </ActionButton>\n )}\n </Show>\n <DialogClose as={Button} variant=\"outline\" size=\"sm\">\n Close\n </DialogClose>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"update-dialog.js","names":["createEffect","createMemo","createSignal","onCleanup","onMount","Show","splitProps","Accessor","Check","CircleStop","Download","ExternalLink","LoaderCircle","Monitor","RefreshCw","Sparkles","Badge","Button","ActionButton","Dialog","DialogClose","DialogContent","DialogDescription","DialogFooter","DialogHeader","DialogTitle","DialogTrigger","createDialogFocusRestoration","Progress","cn","formatBytes","formatReleaseDate","plainTextFromMarkdown","UpdatePhase","UpdateState","Readonly","phase","currentVersion","availableVersion","changelog","releaseNotes","releaseDate","downloadedBytes","totalBytes","error","releaseUrl","restartRequired","UpdateAdapter","getStatus","Promise","check","install","expectedVersion","cancel","pollIntervalMs","openExternal","url","isDesktopRuntime","UpdateDialogProps","adapter","appName","appIcon","fallbackVersion","desktopOnlyMessage","open","defaultOpen","onOpenChange","restoreFocusRef","HTMLElement","class","messageText","value","undefined","message","trim","errorMessage","caught","fallback","Error","plainMessage","record","safe","nestedError","isBusy","state","UpdateDialog","props","local","uncontrolledOpen","setUncontrolledOpen","setOpen","next","focusRestoration","desktop","setState","busy","setBusy","setError","checkFailed","setCheckFailed","cancelPending","setCancelPending","lifecycleEpoch","activeOpenEpoch","disposed","loadStatus","isCurrent","status","previous","hasActionableSnapshot","candidate","preservesSnapshot","epoch","failCheck","applyCheckResult","current","checked","active","version","includes","requestInFlight","timer","window","setInterval","Math","max","clearInterval","openRelease","notes","working","triggerLabel","progressValue","min","round","_$createComponent","children","when","as","variant","size","_$memo","onKeyDown","event","KeyboardEvent","key","defaultPrevented","preventDefault","onOpenAutoFocus","currentTarget","focus","preventScroll","onCloseAutoFocus","_el$","_tmpl$","_el$2","firstChild","_$insert","icon","_el$34","_tmpl$0","_$effect","_$setAttribute","_el$3","_tmpl$9","_el$4","_el$5","_el$6","_el$7","_el$8","nextSibling","_el$9","_el$0","type","tooltip","disabled","onClick","_el$1","_tmpl$2","_el$10","_el$11","_el$12","_el$13","_el$15","_el$14","_el$16","_el$17","_el$19","_el$18","released","_el$35","_tmpl$1","_el$36","_el$20","_tmpl$3","_el$21","aria-label","_el$22","_tmpl$4","_el$23","_el$24","_tmpl$5","_el$25","_tmpl$6","_el$26","_tmpl$7","_el$27","_el$28","_el$29","_el$30","_tmpl$8","_el$31","_el$32","_el$33","_$createComponent","_$memo","_$setAttribute"],"sources":["../../../../src/components/composites/update-dialog/update-dialog.tsx"],"sourcesContent":["import {\n createEffect,\n createMemo,\n createSignal,\n onCleanup,\n onMount,\n Show,\n splitProps,\n} from 'solid-js'\nimport type { Accessor } from 'solid-js'\nimport {\n Check,\n CircleStop,\n Download,\n ExternalLink,\n LoaderCircle,\n Monitor,\n RefreshCw,\n Sparkles,\n} from 'lucide-solid'\nimport { Badge } from '../../ui/badge'\nimport { Button } from '../../ui/button'\nimport { ActionButton } from '../action-button'\nimport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from '../../ui/dialog'\nimport { createDialogFocusRestoration } from '../../ui/dialog/dialog'\nimport { Progress } from '../../ui/progress'\nimport { cn } from '#lib/utils'\nimport { formatBytes, formatReleaseDate, plainTextFromMarkdown } from '#lib/version-notes'\n\n/**\n * UpdateDialog.\n *\n * A software-update surface: the installed version, whether a newer release\n * exists, a download that shows its progress, and the release notes for what is\n * about to arrive.\n *\n * The transport is an adapter, because an update is the one thing a component\n * library genuinely cannot implement: it is signed, downloaded and applied by the\n * application's own updater, and the mechanism differs per shell. What *is*\n * general is the phase machine and the way each phase is presented — and that is\n * where the hard-won detail lives:\n *\n * **A refused install answers with a normal payload, not a rejection.** adea's\n * shell returns a status whose phase is `failed` when a download or an extract\n * fails, rather than throwing. Without handling that, clicking install looked like\n * nothing happened at all — the button spun, the phase never changed, and the\n * error sat unread in a field nobody rendered. The `failed` phase after an install\n * is therefore surfaced as an error, explicitly.\n *\n * **Busy is derived from the snapshot as well as from the click.** An update can\n * be downloading while the dialog is open — started before it opened, or by the\n * shell's own poll — so a local `busy` flag alone would offer an enabled Install\n * button mid-download.\n *\n * **Opening the dialog loads status first, then checks.** Status paints the\n * installed version immediately; the check is a network round trip. Doing them in\n * the other order leaves the dialog blank for as long as the check takes, on a\n * dialog whose first question is always \"what am I running?\".\n *\n * **A failed check is not a current result.** A cached `current` status can only\n * be shown as up to date after the latest check succeeds; a failed check remains\n * retryable and suppresses that claim.\n *\n * **Errors are not always `Error`s.** An adapter can reject with a string or a\n * structured safe message. Unknown object fields are never serialized into the\n * UI; a generic fallback is shown instead.\n *\n * The adapter's `isDesktopRuntime` gate exists because an update is a desktop\n * concern: a browser build has no installer, and the honest thing to show is that\n * updates are available in the desktop application rather than a disabled button\n * with no reason.\n */\n\n/** The phase an update is in. The union is the state machine. */\nexport type UpdatePhase =\n | 'idle'\n | 'checking'\n | 'current'\n | 'available'\n | 'downloading'\n | 'installing'\n | 'installed'\n | 'cancelling'\n | 'cancelled'\n | 'unavailable'\n | 'failed'\n\n/** A snapshot of the updater. Every field the dialog renders, and nothing else. */\nexport type UpdateState = Readonly<{\n phase: UpdatePhase\n /** The version currently installed. */\n currentVersion: string\n /** The version that can be installed, when one can. */\n availableVersion?: string | null\n /** A changelog for the installed channel, as markdown. */\n changelog?: string\n /** Notes for the available release, as markdown. */\n releaseNotes?: string | null\n /** The available release's date, as an ISO string. */\n releaseDate?: string | null\n /** Bytes downloaded so far, during `downloading`. */\n downloadedBytes?: number\n /** Total bytes, when the server sent a length. */\n totalBytes?: number | null\n /** Set when `phase` is `failed`, and sometimes when it is not. */\n error?: string | null\n /** A URL for the release's page. */\n releaseUrl?: string | null\n /** True when the application must restart to finish. */\n restartRequired?: boolean\n}>\n\n/**\n * The updater, as the application exposes it. Three calls, each answering with a\n * full snapshot rather than a delta — an updater's state is small, and a snapshot\n * cannot drift from the shell's own view of it.\n */\nexport type UpdateAdapter = Readonly<{\n /** The current state, without contacting the release channel. */\n getStatus(): Promise<UpdateState>\n /** Ask the release channel, and answer with what it found. */\n check(): Promise<UpdateState>\n /**\n * Download and apply `expectedVersion`.\n *\n * The argument is the version the caller believes is available, so the updater\n * can refuse a request that raced a newer release rather than installing the\n * wrong one.\n */\n install(expectedVersion: string): Promise<UpdateState>\n /** Optional native cancellation, available only while work is in flight. */\n cancel?(): Promise<UpdateState>\n /** Enable status polling during native work; omit for push-driven adapters. */\n pollIntervalMs?: number\n /** Route external links through the native shell when needed. */\n openExternal?(url: string): Promise<void>\n /** False in a browser build, where there is no installer to drive. */\n isDesktopRuntime(): boolean\n}>\n\nexport type UpdateDialogProps = {\n adapter: UpdateAdapter\n /** The application's name, used in the title and the copy. */\n appName?: string\n /** The actual desktop application icon, supplied by its host. */\n appIcon?: string\n /** Complete build-time history, also available before the native status arrives. */\n changelog?: string\n /** Shown before the first status arrives, so the dialog is never blank. */\n fallbackVersion?: string\n /** Copy for the adapter's non-desktop case. */\n desktopOnlyMessage?: string\n /** A controlled open state. Omit for the trigger to manage its own. */\n open?: boolean\n /**\n * Start open, uncontrolled — for a caller that opens the dialog because it found\n * something (\"an update is available\") rather than because the user asked. The\n * trigger is still rendered, so the dialog is reachable again after closing.\n */\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n /**\n * Supplies a stable external control to focus when a controlled dialog closes.\n * Useful when a menu or other layer closes before this dialog opens; when omitted,\n * the element focused immediately before the dialog opens is used when available.\n */\n restoreFocusRef?: Accessor<HTMLElement | undefined>\n /** Render only the panel, for a caller that provides its own dialog. */\n class?: string\n}\n\nfunction messageText(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined\n const message = value.trim()\n return message && message !== '[object Object]' ? message : undefined\n}\n\nfunction errorMessage(caught: unknown, fallback: string): string {\n if (caught instanceof Error) return messageText(caught.message) ?? fallback\n const plainMessage = messageText(caught)\n if (plainMessage) return plainMessage\n if (!caught || typeof caught !== 'object') return fallback\n\n const record = caught as { error?: unknown; safe?: unknown }\n const safe = record.safe as { message?: unknown } | null | undefined\n const nestedError = record.error as { safe?: { message?: unknown } | null } | null | undefined\n return messageText(safe?.message) ?? messageText(nestedError?.safe?.message) ?? fallback\n}\n\n/**\n * The phases during which the updater is working. `downloading` and `installing`\n * are included because the shell can be in either while the dialog is open, and\n * offering an enabled Install button during a download is how a double-install\n * happens.\n */\nfunction isBusy(state: UpdateState | null): boolean {\n return (\n state?.phase === 'checking' ||\n state?.phase === 'downloading' ||\n state?.phase === 'installing' ||\n state?.phase === 'cancelling'\n )\n}\n\nexport function UpdateDialog(props: UpdateDialogProps) {\n const [local] = splitProps(props, [\n 'adapter',\n 'appName',\n 'appIcon',\n 'changelog',\n 'fallbackVersion',\n 'desktopOnlyMessage',\n 'open',\n 'defaultOpen',\n 'onOpenChange',\n 'restoreFocusRef',\n 'class',\n ])\n\n const [uncontrolledOpen, setUncontrolledOpen] = createSignal(local.defaultOpen ?? false)\n const open = () => local.open ?? uncontrolledOpen()\n const setOpen = (next: boolean) => {\n if (local.open === undefined) setUncontrolledOpen(next)\n local.onOpenChange?.(next)\n }\n\n const focusRestoration = createDialogFocusRestoration({\n open,\n restoreFocusRef: local.restoreFocusRef,\n })\n\n const appName = () => local.appName ?? 'the application'\n const desktop = () => local.adapter.isDesktopRuntime()\n const [state, setState] = createSignal<UpdateState | null>(null)\n const [busy, setBusy] = createSignal(false)\n const [error, setError] = createSignal('')\n const [checkFailed, setCheckFailed] = createSignal(false)\n const [cancelPending, setCancelPending] = createSignal(false)\n let lifecycleEpoch = 0\n let activeOpenEpoch: number | undefined\n let disposed = false\n\n onCleanup(() => {\n disposed = true\n activeOpenEpoch = undefined\n lifecycleEpoch += 1\n })\n\n const loadStatus = async (isCurrent: () => boolean = () => !disposed) => {\n if (!desktop() || !isCurrent()) return\n try {\n const status = await local.adapter.getStatus()\n const previous = state()\n const hasActionableSnapshot = (candidate: UpdateState | null) =>\n candidate?.phase === 'available' || isBusy(candidate)\n const preservesSnapshot =\n previous?.phase === 'available'\n ? status.phase === 'available' || isBusy(status)\n : isBusy(previous) && isBusy(status)\n if (\n isCurrent() &&\n !(checkFailed() && hasActionableSnapshot(previous) && !preservesSnapshot)\n ) {\n setState(status)\n }\n } catch (caught) {\n if (isCurrent()) setError(errorMessage(caught, 'Version status is unavailable'))\n }\n }\n\n onMount(() => {\n if (desktop() && !open()) {\n const epoch = lifecycleEpoch\n void loadStatus(() => !disposed && lifecycleEpoch === epoch)\n }\n })\n\n const failCheck = (caught: unknown, fallback: string) => {\n const message = errorMessage(caught, fallback)\n setCheckFailed(true)\n setError(message)\n }\n\n const applyCheckResult = (next: UpdateState) => {\n if (next.phase === 'failed') {\n const current = state()\n if (!current) setState(next)\n failCheck(next.error, 'Could not check for updates')\n return\n }\n setState(next)\n setCheckFailed(false)\n setError('')\n }\n\n const check = async () => {\n if (!desktop()) {\n setError(local.desktopOnlyMessage ?? `Update checks are available from the desktop app.`)\n return\n }\n const epoch = activeOpenEpoch\n const isCurrent = () =>\n !disposed &&\n epoch !== undefined &&\n activeOpenEpoch === epoch &&\n lifecycleEpoch === epoch &&\n open()\n if (!isCurrent()) return\n setBusy(true)\n setError('')\n setCheckFailed(false)\n try {\n const checked = await local.adapter.check()\n if (isCurrent()) applyCheckResult(checked)\n } catch (caught) {\n if (isCurrent()) {\n failCheck(caught, 'Could not check for updates')\n await loadStatus(isCurrent)\n }\n } finally {\n if (isCurrent()) setBusy(false)\n }\n }\n\n /**\n * Status first, then the check — and an `active` flag, because the dialog can\n * close while the check is in flight and a late `setState` would write into a\n * disposed scope.\n */\n createEffect(() => {\n if (!open() || !desktop()) {\n setCancelPending(false)\n if (activeOpenEpoch !== undefined) {\n activeOpenEpoch = undefined\n lifecycleEpoch += 1\n }\n return\n }\n const epoch = ++lifecycleEpoch\n activeOpenEpoch = epoch\n let active = true\n const isCurrent = () =>\n active && !disposed && activeOpenEpoch === epoch && lifecycleEpoch === epoch && open()\n onCleanup(() => {\n active = false\n if (activeOpenEpoch === epoch) {\n activeOpenEpoch = undefined\n lifecycleEpoch += 1\n }\n })\n setError('')\n setCheckFailed(false)\n setCancelPending(false)\n setBusy(true)\n void (async () => {\n try {\n const current = await local.adapter.getStatus()\n if (!isCurrent()) return\n setState(current)\n const checked = await local.adapter.check()\n if (isCurrent()) applyCheckResult(checked)\n } catch (caught) {\n if (isCurrent()) failCheck(caught, 'Could not check for updates')\n } finally {\n if (isCurrent()) setBusy(false)\n }\n })()\n })\n\n const install = async () => {\n const version = state()?.availableVersion\n const epoch = activeOpenEpoch\n const isCurrent = () =>\n !disposed &&\n epoch !== undefined &&\n activeOpenEpoch === epoch &&\n lifecycleEpoch === epoch &&\n open()\n if (!version || !isCurrent()) return\n setBusy(true)\n setError('')\n setState((current) =>\n current ? { ...current, phase: 'downloading', downloadedBytes: 0, totalBytes: null } : current\n )\n try {\n const next = await local.adapter.install(version)\n if (!isCurrent()) return\n setState(\n cancelPending() && ['downloading', 'installing'].includes(next.phase)\n ? { ...next, phase: 'cancelling' }\n : next\n )\n // A refused install answers with a normal payload whose phase is `failed`.\n // Without this the click looked like nothing happened.\n if (next.phase === 'failed') {\n setError(errorMessage(next.error, 'Update installation failed'))\n } else {\n setCheckFailed(false)\n }\n } catch (caught) {\n if (!isCurrent()) return\n setError(errorMessage(caught, 'Update installation failed'))\n await loadStatus(isCurrent)\n } finally {\n if (isCurrent()) setBusy(false)\n }\n }\n\n // Poll only an open, active native operation. Epoch ownership prevents a late\n // status response from replacing a reopened dialog's newer snapshot.\n createEffect(() => {\n const phase = state()?.phase\n if (\n !open() ||\n !desktop() ||\n !local.adapter.pollIntervalMs ||\n !['downloading', 'installing', 'cancelling'].includes(phase ?? '')\n )\n return\n const epoch = activeOpenEpoch\n let active = true\n let requestInFlight = false\n const timer = window.setInterval(\n () => {\n if (requestInFlight) return\n requestInFlight = true\n void (async () => {\n try {\n const next = await local.adapter.getStatus()\n if (!active || disposed || !open() || activeOpenEpoch !== epoch) return\n setState(\n cancelPending() && ['downloading', 'installing'].includes(next.phase)\n ? { ...next, phase: 'cancelling' }\n : next\n )\n if (next.phase === 'failed')\n setError(errorMessage(next.error, 'Update installation failed'))\n } catch (caught) {\n if (active && !disposed && activeOpenEpoch === epoch)\n setError(errorMessage(caught, 'Update progress is unavailable'))\n } finally {\n requestInFlight = false\n }\n })()\n },\n Math.max(250, local.adapter.pollIntervalMs)\n )\n onCleanup(() => {\n active = false\n window.clearInterval(timer)\n })\n })\n\n const cancel = async () => {\n if (!local.adapter.cancel || cancelPending() || state()?.phase === 'cancelling') return\n const epoch = activeOpenEpoch\n setError('')\n setCancelPending(true)\n setState((current) => (current ? { ...current, phase: 'cancelling' } : current))\n try {\n const next = await local.adapter.cancel()\n if (!disposed && open() && activeOpenEpoch === epoch) setState(next)\n } catch (caught) {\n if (!disposed && open() && activeOpenEpoch === epoch) {\n setError(errorMessage(caught, 'Could not cancel the update'))\n await loadStatus(() => !disposed && open() && activeOpenEpoch === epoch)\n }\n } finally {\n if (!disposed && open() && activeOpenEpoch === epoch) setCancelPending(false)\n }\n }\n\n const openRelease = async (url: string) => {\n try {\n if (local.adapter.openExternal) await local.adapter.openExternal(url)\n else window.open(url, '_blank', 'noopener,noreferrer')\n } catch (caught) {\n if (!disposed) setError(errorMessage(caught, 'Could not open the release page'))\n }\n }\n\n const changelog = createMemo(() =>\n plainTextFromMarkdown(state()?.changelog || local.changelog || '')\n )\n const notes = () => {\n const value = state()?.releaseNotes\n return value ? plainTextFromMarkdown(value) : ''\n }\n const working = () => busy() || cancelPending() || isBusy(state())\n const isCurrent = () => state()?.phase === 'current' && !error() && !checkFailed() && !working()\n\n const triggerLabel = () => {\n const current = state()\n const fallback = `v${local.fallbackVersion ?? '0.1.0'}`\n if (checkFailed()) return `Version ${current?.currentVersion || fallback} · Retry`\n if (!current) return `${appName()} ${fallback}`\n switch (current.phase) {\n case 'checking':\n return 'Checking for updates…'\n case 'available':\n return current.availableVersion\n ? `Update v${current.availableVersion} available`\n : 'Update available'\n case 'downloading':\n case 'installing':\n return 'Installing update…'\n case 'failed':\n return `Version ${current.currentVersion || fallback} · Retry`\n default:\n return `${appName()} v${current.currentVersion || fallback}`\n }\n }\n\n const progressValue = () => {\n const current = state()\n if (!current?.totalBytes || !current.downloadedBytes) return null\n return Math.min(100, Math.round((current.downloadedBytes / current.totalBytes) * 100))\n }\n\n return (\n <Dialog open={open()} onOpenChange={setOpen}>\n <Show when={local.open === undefined}>\n <DialogTrigger\n as={Button}\n variant=\"ghost\"\n size=\"sm\"\n aria-label=\"Open version and updates\"\n aria-haspopup=\"dialog\"\n >\n <Show when={state()?.phase === 'available'} fallback={<RefreshCw aria-hidden=\"true\" />}>\n <Sparkles aria-hidden=\"true\" />\n </Show>\n {triggerLabel()}\n </DialogTrigger>\n </Show>\n\n <DialogContent\n class={cn('max-w-3xl', local.class)}\n onKeyDown={(event: KeyboardEvent) => {\n // An explanatory tooltip must not consume the popup's close shortcut,\n // including while its exit animation still owns Kobalte's top layer.\n if (event.key === 'Escape' && !event.defaultPrevented) {\n event.preventDefault()\n setOpen(false)\n }\n }}\n onOpenAutoFocus={(event) => {\n focusRestoration.onOpenAutoFocus(event)\n // Start at the readable panel rather than opening an action's tooltip.\n if (!event.defaultPrevented && event.currentTarget instanceof HTMLElement) {\n event.preventDefault()\n event.currentTarget.focus({ preventScroll: true })\n }\n }}\n onCloseAutoFocus={focusRestoration.onCloseAutoFocus}\n >\n <DialogHeader>\n <div class=\"flex items-center gap-3\">\n <Show\n when={local.appIcon}\n fallback={<Monitor class=\"size-10 text-primary\" aria-hidden=\"true\" />}\n >\n {(icon) => <img src={icon()} alt=\"\" class=\"size-10\" aria-hidden=\"true\" />}\n </Show>\n <div>\n <DialogTitle>Version & updates</DialogTitle>\n <DialogDescription>\n Keep {appName()} current and review what changed in each release.\n </DialogDescription>\n </div>\n </div>\n </DialogHeader>\n\n <div class=\"flex min-h-0 flex-col gap-5 overflow-y-auto p-6\">\n <section\n class=\"rounded-xl border border-border bg-background/45 p-4\"\n aria-label=\"Version status\"\n >\n <div class=\"flex flex-wrap items-start justify-between gap-4\">\n <div class=\"flex flex-col gap-1\">\n <p class=\"text-2xs font-semibold tracking-widest text-muted-foreground uppercase\">\n Installed version\n </p>\n <p class=\"text-xl font-semibold tracking-tight text-foreground\">\n v{state()?.currentVersion || local.fallbackVersion || '0.1.0'}\n </p>\n <p class=\"text-sm text-muted-foreground\">\n <Show\n when={isCurrent()}\n fallback={\n <Show\n when={state()?.phase === 'available' && state()?.availableVersion}\n fallback={\n state()?.phase === 'unavailable'\n ? 'No signed package is published for this platform.'\n : state()?.phase === 'cancelled'\n ? 'Update cancelled. You can retry when ready.'\n : desktop()\n ? 'Check the release channel for the latest signed build.'\n : (local.desktopOnlyMessage ??\n `Open this dialog inside the desktop app to check for updates.`)\n }\n >\n {`A newer release, v${state()?.availableVersion}, is ready.`}\n </Show>\n }\n >\n You are running the latest release.\n </Show>\n </p>\n </div>\n <ActionButton\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n tooltip=\"Check the release channel for the latest signed app version.\"\n disabled={!desktop() || working()}\n onClick={() => void check()}\n >\n <Show when={working()} fallback={<RefreshCw aria-hidden=\"true\" />}>\n <LoaderCircle class=\"animate-spin\" aria-hidden=\"true\" />\n </Show>\n {checkFailed() ? 'Retry update check' : 'Check latest version'}\n </ActionButton>\n </div>\n </section>\n\n <Show\n when={\n state()?.availableVersion &&\n state()?.phase !== 'installed' &&\n state()?.phase !== 'unavailable'\n }\n >\n <section\n class=\"rounded-xl border border-primary/35 bg-primary-subtle p-4\"\n aria-label=\"Available update\"\n >\n <div class=\"flex flex-wrap items-start justify-between gap-4\">\n <div class=\"flex flex-col gap-1\">\n <p class=\"flex items-center gap-2 text-sm font-semibold\">\n <Sparkles class=\"size-4 text-primary\" aria-hidden=\"true\" />\n Version {state()?.availableVersion}{' '}\n {['downloading', 'installing', 'cancelling'].includes(state()?.phase ?? '')\n ? 'is being prepared'\n : 'is ready'}\n </p>\n <p class=\"text-sm text-muted-foreground\">\n The signed installer is verified before {appName()} restarts.\n </p>\n <Show when={formatReleaseDate(state()?.releaseDate ?? null)}>\n {(released) => (\n <p class=\"text-xs text-muted-foreground\">Released {released()}</p>\n )}\n </Show>\n </div>\n <ActionButton\n type=\"button\"\n size=\"sm\"\n tooltip={`Download the signed update and restart ${appName()}.`}\n disabled={working()}\n onClick={() => void install()}\n >\n <Show when={working()} fallback={<Download aria-hidden=\"true\" />}>\n <LoaderCircle class=\"animate-spin\" aria-hidden=\"true\" />\n </Show>\n Install and restart\n </ActionButton>\n </div>\n </section>\n </Show>\n\n {/*\n Progress with both numbers: a bar alone does not distinguish a stalled\n download from a slow one, and \"12.4 MB of 48.1 MB\" does.\n */}\n <Show\n when={\n state()?.phase === 'downloading' ||\n state()?.phase === 'installing' ||\n state()?.phase === 'cancelling'\n }\n >\n <section class=\"grid gap-2\" aria-label=\"Update progress\">\n <Progress\n value={progressValue() ?? undefined}\n aria-label={\n state()?.phase === 'installing' ? 'Installing update' : 'Downloading update'\n }\n />\n <p class=\"text-xs text-muted-foreground\" role=\"status\">\n <Show\n when={state()?.phase === 'installing'}\n fallback={\n <Show when={progressValue() !== null} fallback=\"Downloading…\">\n {`${formatBytes(state()?.downloadedBytes ?? 0)} of ${formatBytes(\n state()?.totalBytes ?? 0\n )} · ${progressValue()}%`}\n </Show>\n }\n >\n Applying the update…\n </Show>\n </p>\n <Show when={local.adapter.cancel}>\n <ActionButton\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n tooltip=\"Stop the current update download or installation.\"\n disabled={cancelPending() || state()?.phase === 'cancelling'}\n onClick={() => void cancel()}\n >\n <CircleStop aria-hidden=\"true\" />\n {cancelPending() || state()?.phase === 'cancelling'\n ? 'Cancelling…'\n : 'Cancel update'}\n </ActionButton>\n </Show>\n </section>\n </Show>\n\n <Show when={isCurrent()}>\n <p class=\"text-foreground flex items-center gap-2 text-sm\" role=\"status\">\n <Check class=\"size-4 text-success\" aria-hidden=\"true\" />\n {appName()} is up to date.\n </p>\n </Show>\n\n <Show when={state()?.phase === 'installed'}>\n <p class=\"text-foreground flex items-center gap-2 text-sm\" role=\"status\">\n <Check class=\"size-4 text-success\" aria-hidden=\"true\" />\n <Show when={state()?.restartRequired} fallback=\"The update is applied.\">\n Restart {appName()} to finish the update.\n </Show>\n </p>\n </Show>\n\n <Show when={error()}>\n <p\n class=\"text-foreground rounded-lg border border-destructive/35 bg-destructive-subtle px-3 py-2 text-sm\"\n role=\"alert\"\n >\n {error()}\n </p>\n </Show>\n\n <Show when={notes()}>\n <div class=\"flex flex-col gap-2\">\n <div class=\"flex items-center gap-2\">\n <h2 id=\"update-release-notes\" class=\"text-sm font-semibold text-foreground\">\n What changed in this release\n </h2>\n <Badge variant=\"subtle\" size=\"sm\">\n v{state()?.availableVersion}\n </Badge>\n </div>\n {/* A long text block with no focusable descendant: it needs its own tab\n stop, named by the heading above it, or a keyboard user cannot\n scroll it (`scrollable-region-focusable`). */}\n <div\n class=\"max-h-52 overflow-y-auto rounded-xl border border-border bg-background/45 p-4 font-mono text-xs leading-5 whitespace-pre-wrap text-muted-foreground\"\n role=\"region\"\n aria-labelledby=\"update-release-notes\"\n tabindex=\"0\"\n >\n {notes()}\n </div>\n </div>\n </Show>\n\n <Show when={changelog()}>\n <div class=\"flex flex-col gap-2\">\n <h2 id=\"update-changelog\" class=\"text-sm font-semibold text-foreground\">\n Installed changelog\n </h2>\n <p class=\"text-xs text-muted-foreground\">\n All versions and updates included with this installation.\n </p>\n {/* A long text block with no focusable descendant: it needs its own tab\n stop, named by the heading above it, or a keyboard user cannot\n scroll it (`scrollable-region-focusable`). */}\n <div\n class=\"max-h-72 overflow-y-auto rounded-xl border border-border bg-background/45 p-4 font-mono text-xs leading-5 whitespace-pre-wrap text-muted-foreground\"\n role=\"region\"\n aria-labelledby=\"update-changelog\"\n tabindex=\"0\"\n >\n {changelog()}\n </div>\n </div>\n </Show>\n </div>\n\n <DialogFooter>\n <Show when={state()?.releaseUrl}>\n {(url) => (\n <ActionButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n tooltip=\"Open the release history in your browser.\"\n // `noopener,noreferrer` because the release page is a different\n // origin and must not get a handle on this window.\n onClick={() => void openRelease(url())}\n >\n <ExternalLink aria-hidden=\"true\" />\n View releases\n </ActionButton>\n )}\n </Show>\n <DialogClose as={Button} variant=\"outline\" size=\"sm\">\n Close\n </DialogClose>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n"],"mappings":"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"}
|
|
@@ -117,7 +117,11 @@ export function AboutDialog(props: AboutDialogProps) {
|
|
|
117
117
|
<div class="flex flex-col items-center gap-3 px-6 py-8 text-center">
|
|
118
118
|
<img src={props.appIcon} alt="" class="size-16" aria-hidden="true" />
|
|
119
119
|
<DialogTitle>{props.appName}</DialogTitle>
|
|
120
|
-
|
|
120
|
+
{/* Body text on the dialog's themed surface: primary ink measures
|
|
121
|
+
below AA against the lighter dialog backgrounds across schemes,
|
|
122
|
+
so the version and the source link carry foreground ink and keep
|
|
123
|
+
primary as the link's underline accent (the text-link treatment). */}
|
|
124
|
+
<p class="text-sm text-foreground">{versionLabel()}</p>
|
|
121
125
|
<p class="text-xs text-muted-foreground">{props.copyright}</p>
|
|
122
126
|
<div class="flex flex-wrap items-center justify-center gap-3">
|
|
123
127
|
<ActionButton
|
|
@@ -134,6 +138,7 @@ export function AboutDialog(props: AboutDialogProps) {
|
|
|
134
138
|
as="a"
|
|
135
139
|
variant="link"
|
|
136
140
|
size="sm"
|
|
141
|
+
class="text-foreground decoration-primary"
|
|
137
142
|
href={props.sourceUrl}
|
|
138
143
|
target="_blank"
|
|
139
144
|
rel="noopener noreferrer"
|
|
@@ -93,20 +93,31 @@ export function AccentChoices(props: AppearanceEditorProps) {
|
|
|
93
93
|
disabled={props.saving}
|
|
94
94
|
orientation="horizontal"
|
|
95
95
|
aria-label="Accent"
|
|
96
|
-
|
|
96
|
+
// Two chips in a column beside a 3x2 swatch grid: one line of six
|
|
97
|
+
// swatches plus chips overflows the settings sidebar's control column,
|
|
98
|
+
// and the column keeps both rows of the pair balanced (2 x 28px + gap).
|
|
99
|
+
class="flex items-center gap-3"
|
|
97
100
|
onChange={(accent) =>
|
|
98
101
|
props.onChange({
|
|
99
102
|
accent: accent === 'custom' ? (props.customAccentValue ?? '') : accent,
|
|
100
103
|
})
|
|
101
104
|
}
|
|
102
105
|
>
|
|
103
|
-
<
|
|
104
|
-
<Radio.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
106
|
+
<div class="flex flex-col gap-2">
|
|
107
|
+
<Radio.Item value="theme">
|
|
108
|
+
<Radio.ItemInput />
|
|
109
|
+
<Radio.ItemLabel class="flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs whitespace-nowrap data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary">
|
|
110
|
+
Theme default
|
|
111
|
+
</Radio.ItemLabel>
|
|
112
|
+
</Radio.Item>
|
|
113
|
+
<Radio.Item value="custom">
|
|
114
|
+
<Radio.ItemInput />
|
|
115
|
+
<Radio.ItemLabel class="flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs whitespace-nowrap data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary">
|
|
116
|
+
Custom
|
|
117
|
+
</Radio.ItemLabel>
|
|
118
|
+
</Radio.Item>
|
|
119
|
+
</div>
|
|
120
|
+
<div class="grid grid-cols-3 gap-2">
|
|
110
121
|
<For each={props.accentOptions}>
|
|
111
122
|
{(option) => (
|
|
112
123
|
<Radio.Item
|
|
@@ -133,12 +144,6 @@ export function AccentChoices(props: AppearanceEditorProps) {
|
|
|
133
144
|
)}
|
|
134
145
|
</For>
|
|
135
146
|
</div>
|
|
136
|
-
<Radio.Item value="custom">
|
|
137
|
-
<Radio.ItemInput />
|
|
138
|
-
<Radio.ItemLabel class="flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary">
|
|
139
|
-
Custom
|
|
140
|
-
</Radio.ItemLabel>
|
|
141
|
-
</Radio.Item>
|
|
142
147
|
</Radio>
|
|
143
148
|
)
|
|
144
149
|
}
|