overplay 4.0.0 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/LICENSE +3 -0
- package/README.md +6 -3
- package/dist/overplay.esm.js +96 -30
- package/dist/overplay.esm.js.map +1 -1
- package/dist/overplay.iife.js +1 -1
- package/dist/overplay.iife.js.map +1 -1
- package/dist/overplay.umd.js +1 -1
- package/dist/overplay.umd.js.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.2.0 — 2026-10-17
|
|
4
|
+
|
|
5
|
+
- Widget Settings has two tabs: **General** (panel, notifications and the shortcut) and **Appearance** (theme, pins and the comments button).
|
|
6
|
+
- Opening the sidebar with the shortcut no longer shows a focus ring on the Settings button. Focus moves to the panel; Tab still reaches every button.
|
|
7
|
+
- Website: new pages **How It Works** and **MCP Server** in the header. The MCP Server page lists all 20 MCP tools by permission. The New pill on the landing page opens it.
|
|
8
|
+
- Website: Pricing, Docs, How It Works and MCP Server share one page header (label, title, text, buttons).
|
|
9
|
+
- Dashboard: the usage bars on Plan & Billing use the full width. Team rows no longer push the arrow out of the card on hover, and Teams in the sidebar has a two-people icon.
|
|
10
|
+
|
|
11
|
+
## 4.1.0 — 2026-10-17
|
|
12
|
+
|
|
13
|
+
- New default shortcut to open and close comments: **Alt+C** (**Option+C** on Mac). It works on any keyboard layout. Alt+Shift+C still works, but on Windows Alt+Shift can switch the keyboard language. Settings shows Option on Mac. Set `keyboardShortcut` to keep another key.
|
|
14
|
+
- The update notice in the sidebar footer now offers a prompt for your coding agent: Show Prompt and Copy Prompt. The prompt updates the package, reads the release notes, clears the bundler cache (Vite, Next.js, Nuxt and others) and restarts the dev server. A version bump alone often kept serving the old widget.
|
|
15
|
+
- The update notice no longer shows for the script tag, which loads the server's copy and updates by itself.
|
|
16
|
+
- Dashboard: on the Projects page each team is a panel with its name, project count and New Project button. Project tiles use the brand blue.
|
|
17
|
+
- Website: the MCP section shows a short chat in which a coding agent reads yesterday's comments, fixes one and replies.
|
|
18
|
+
- The public source moves to [github.com/artemsvit/Overplay-Community](https://github.com/artemsvit/Overplay-Community): the widget and the Community server. Links on the site and in the package point there.
|
|
19
|
+
|
|
3
20
|
## 4.0.0 — 2026-10-17
|
|
4
21
|
|
|
5
22
|
The package and code now use the Overplay name everywhere. This release has breaking changes.
|
package/LICENSE
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
+
This license covers the Overplay widget (the `overplay` npm package) and every file outside
|
|
4
|
+
`service/`. The service in `service/` uses the Functional Source License: see service/LICENSE.md.
|
|
5
|
+
|
|
3
6
|
Copyright (c) 2026 Overplay contributors
|
|
4
7
|
|
|
5
8
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
12
|
<a href="https://www.npmjs.com/package/overplay"><img src="https://img.shields.io/npm/v/overplay?color=575ce5" alt="npm version"></a>
|
|
13
|
-
<a href="./LICENSE"><img src="https://img.shields.io/badge/license-MIT-575ce5" alt="MIT license"></a>
|
|
13
|
+
<a href="./LICENSE"><img src="https://img.shields.io/badge/widget-MIT-575ce5" alt="Widget: MIT license"></a> <a href="./service/LICENSE.md"><img src="https://img.shields.io/badge/service-FSL--1.1--MIT-575ce5" alt="Service: FSL-1.1-MIT license"></a>
|
|
14
14
|
<a href="https://overplay.app/"><img src="https://img.shields.io/badge/cloud-overplay.app-575ce5" alt="Cloud"></a>
|
|
15
15
|
</p>
|
|
16
16
|
|
|
@@ -110,7 +110,7 @@ Read the [self-hosting guide](docs/SELF_HOSTING.md).
|
|
|
110
110
|
|
|
111
111
|
| Key | Action |
|
|
112
112
|
| --- | --- |
|
|
113
|
-
| <kbd>Alt</kbd> + <kbd>
|
|
113
|
+
| <kbd>Alt</kbd> + <kbd>C</kbd> (<kbd>Option</kbd> + <kbd>C</kbd> on Mac) | Open or close the widget |
|
|
114
114
|
| <kbd>Esc</kbd> | Cancel |
|
|
115
115
|
| <kbd>Enter</kbd> | Place a pin on the focused element |
|
|
116
116
|
|
|
@@ -132,7 +132,10 @@ The hosted service (Cloudflare Worker + D1) is in [`service/`](service/README.md
|
|
|
132
132
|
|
|
133
133
|
## License
|
|
134
134
|
|
|
135
|
-
[MIT](./LICENSE)
|
|
135
|
+
- **Widget** (the `overplay` npm package: `src/`, `dist/`): [MIT](./LICENSE). Use it on any site, free.
|
|
136
|
+
- **Service** (Cloud and Community: everything in `service/`): [Functional Source License 1.1, MIT Future License](./service/LICENSE.md) (FSL-1.1-MIT). You may run Community for free, for your own company and your clients, and change it. You may not offer it as a competing paid or hosted product. Two years after each release, that release becomes MIT.
|
|
137
|
+
|
|
138
|
+
Code published before this change keeps the MIT license it was published under.
|
|
136
139
|
|
|
137
140
|
## Connect a coding agent
|
|
138
141
|
|
package/dist/overplay.esm.js
CHANGED
|
@@ -421,6 +421,10 @@ function matchesShortcut(event, shortcut) {
|
|
|
421
421
|
const code = /^[a-z]$/.test(shortcut.key) ? `Key${shortcut.key.toUpperCase()}` : /^\d$/.test(shortcut.key) ? `Digit${shortcut.key}` : "";
|
|
422
422
|
return event.key.toLowerCase() === shortcut.key || !!code && event.code === code;
|
|
423
423
|
}
|
|
424
|
+
function shortcutLabel(value, mac) {
|
|
425
|
+
const names = mac ? { alt: "Option", option: "Option", meta: "Cmd", cmd: "Cmd", ctrl: "Control", control: "Control" } : { alt: "Alt", option: "Alt", meta: "Meta", cmd: "Meta", ctrl: "Ctrl", control: "Ctrl" };
|
|
426
|
+
return value.toLowerCase().split("+").map((part) => part.trim()).filter(Boolean).map((part) => names[part] ?? (part.length === 1 ? part.toUpperCase() : part[0].toUpperCase() + part.slice(1))).join(" + ");
|
|
427
|
+
}
|
|
424
428
|
function newId() {
|
|
425
429
|
if (typeof crypto.randomUUID === "function") return crypto.randomUUID();
|
|
426
430
|
const bytes = crypto.getRandomValues(new Uint8Array(16));
|
|
@@ -470,10 +474,26 @@ function newActivity(comments, seen, selfId) {
|
|
|
470
474
|
function sameComments(a, b) {
|
|
471
475
|
return a.length === b.length && JSON.stringify(a) === JSON.stringify(b);
|
|
472
476
|
}
|
|
473
|
-
const version = "4.
|
|
477
|
+
const version = "4.2.0";
|
|
474
478
|
const VERSION = version;
|
|
475
479
|
const PACKAGE = "overplay";
|
|
476
|
-
|
|
480
|
+
function updatePrompt(current, latest) {
|
|
481
|
+
return `Update the Overplay widget in this project from version ${current} to ${latest}.
|
|
482
|
+
|
|
483
|
+
Steps:
|
|
484
|
+
1. Find the package manager (look for package-lock.json, pnpm-lock.yaml, yarn.lock or bun.lockb) and update the package "${PACKAGE}" to ${latest}:
|
|
485
|
+
npm install ${PACKAGE}@${latest} (or: pnpm add ${PACKAGE}@${latest}, yarn add ${PACKAGE}@${latest}, bun add ${PACKAGE}@${latest})
|
|
486
|
+
2. Read the release notes from ${current} to ${latest}: https://github.com/artemsvit/Overplay-Community/blob/main/CHANGELOG.md
|
|
487
|
+
If a release lists breaking changes, update our code to match. Keep serverUrl, projectId and the other options as they are.
|
|
488
|
+
3. Stop the dev server and clear the bundler cache, so the old widget is not served again:
|
|
489
|
+
- Vite: delete node_modules/.vite
|
|
490
|
+
- Next.js: delete .next
|
|
491
|
+
- Nuxt: delete .nuxt and node_modules/.cache
|
|
492
|
+
- Other tools (webpack, Parcel, Astro, SvelteKit): delete node_modules/.cache, .parcel-cache, .astro or .svelte-kit if they exist.
|
|
493
|
+
4. Start the dev server again and tell me to hard-reload the browser (Cmd+Shift+R or Ctrl+Shift+R).
|
|
494
|
+
5. Run the project's type check and build, and fix any errors.
|
|
495
|
+
6. When you finish, list the files you changed. The update is done when the widget no longer shows "Version ${latest} is available".`;
|
|
496
|
+
}
|
|
477
497
|
function isNewer(latest, current) {
|
|
478
498
|
const parse = (v) => {
|
|
479
499
|
var _a;
|
|
@@ -572,6 +592,8 @@ const paths = {
|
|
|
572
592
|
arrow: "M12 19V5m-6 6 6-6 6 6",
|
|
573
593
|
refresh: "M20.5 12a8.5 8.5 0 1 1-2.6-6.1L20.5 8.5M20.5 3.5v5h-5",
|
|
574
594
|
open: "M7 17 17 7M9 7h8v8",
|
|
595
|
+
copy: "M9 9h11v11H9zM5 15H4V4h11v1",
|
|
596
|
+
sparkle: "M10 3.5c.6 3.9 2.6 5.9 6.5 6.5-3.9.6-5.9 2.6-6.5 6.5-.6-3.9-2.6-5.9-6.5-6.5 3.9-.6 5.9-2.6 6.5-6.5ZM18 14.5c.3 1.9 1.1 2.7 3 3-1.9.3-2.7 1.1-3 3-.3-1.9-1.1-2.7-3-3 1.9-.3 2.7-1.1 3-3Z",
|
|
575
597
|
trash: "M3 6h18M9 6V4h6v2M5 6l1 14h12l1-14M10 10v6m4-6v6",
|
|
576
598
|
pin: "M12 21s7-6 7-13A7 7 0 0 0 5 8c0 7 7 13 7 13ZM12 6v4M10 8h4",
|
|
577
599
|
search: "m21 21-5-5M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0Z",
|
|
@@ -671,6 +693,10 @@ const tokens = {
|
|
|
671
693
|
warning: "#745320",
|
|
672
694
|
"warning-soft": "#fff8e8",
|
|
673
695
|
"warning-line": "#ebd59f",
|
|
696
|
+
// AI: a light violet that marks AI features, such as the AI Install prompt. Never for buttons.
|
|
697
|
+
ai: "#6d4fe0",
|
|
698
|
+
"ai-soft": "#f6f3ff",
|
|
699
|
+
"ai-line": "#e3dbff",
|
|
674
700
|
// Shape. Buttons and chips are pills; cards and windows have soft corners; big page panels have 26px.
|
|
675
701
|
"radius-sm": "6px",
|
|
676
702
|
radius: "10px",
|
|
@@ -710,6 +736,9 @@ const darkTokens = {
|
|
|
710
736
|
warning: "#efc56e",
|
|
711
737
|
"warning-soft": "#2f2718",
|
|
712
738
|
"warning-line": "#57472a",
|
|
739
|
+
ai: "#a994ff",
|
|
740
|
+
"ai-soft": "#1d1a2c",
|
|
741
|
+
"ai-line": "#3b3263",
|
|
713
742
|
"shadow-sm": "0 0 0 1px #ffffff14,0 1px 2px #00000066",
|
|
714
743
|
shadow: "0 1px 3px #00000066,0 16px 40px -12px #000000b3"
|
|
715
744
|
};
|
|
@@ -752,7 +781,7 @@ const styles = `
|
|
|
752
781
|
.menu-note{display:flex;align-items:center;gap:2px;margin:4px 0 0;padding:8px 10px 4px;border-top:1px solid var(--cw-line);font-size:12px;color:var(--cw-muted)}
|
|
753
782
|
.footer{justify-content:space-between}
|
|
754
783
|
.footer-note{font-size:13px;color:var(--cw-muted)}
|
|
755
|
-
.settings-body{flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;padding:4px 20px 12px}
|
|
784
|
+
.panel:focus{outline:0}.settings-tabs{grid-template-columns:1fr 1fr;margin:0 0 12px}.settings-body{flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;padding:4px 20px 12px}
|
|
756
785
|
.setting-group{padding:14px 0 6px}
|
|
757
786
|
.setting-group+.setting-group{border-top:1px solid var(--cw-line)}
|
|
758
787
|
.setting-group h3{margin:0 0 6px;font-size:12px;font-weight:650;letter-spacing:1.1px;text-transform:uppercase;color:var(--cw-muted)}
|
|
@@ -801,7 +830,7 @@ const styles = `
|
|
|
801
830
|
.anchor-status .quiet{display:inline-flex;align-items:center;gap:6px;margin-top:10px;padding:6px 11px 6px 9px;font-size:13px;font-weight:600}.anchor-status .quiet svg{width:15px;height:15px;flex-shrink:0}
|
|
802
831
|
@media(max-width:600px){.panel,.panel.left{inset:0;width:auto;border:0}.panel.placing{visibility:hidden}.panel.behind{visibility:hidden}.launcher{right:16px;bottom:16px}.notice,.notice.beside-panel,.notice.beside-panel.left{left:50%;bottom:24px;width:calc(100vw - 32px);font-size:13px}.compose-hint{display:none}.compose-bar{justify-content:flex-end}.toasts,.toasts.left,.toasts.beside-panel,.toasts.beside-panel.left{left:16px;right:16px;width:auto;max-width:none;bottom:82px}.toasts.top,.toasts.beside-panel.top{top:82px;bottom:auto}.toasts.beside-panel{display:none}.head{padding-top:18px}}
|
|
803
832
|
.popover.moving{visibility:hidden;pointer-events:none}
|
|
804
|
-
.update-bar{display:grid;grid-template-columns:30px 1fr auto;align-items:start;gap:4px 12px;padding:14px 12px 16px 20px;background:var(--cw-accent-soft);border-top-color:var(--cw-accent-line)}.update-icon{display:grid;place-items:center;width:30px;height:30px;border-radius:9px;background:var(--cw-surface);color:var(--cw-accent);box-shadow:var(--cw-shadow-sm)}.update-icon svg{width:16px;height:16px}.update-text{display:flex;flex-direction:column;gap:1px;min-width:0;color:var(--cw-muted);font-size:12.5px;line-height:1.45}.update-text strong{color:var(--cw-ink);font-size:13px;font-weight:650}.update-
|
|
833
|
+
.update-bar{display:grid;grid-template-columns:30px 1fr auto;align-items:start;gap:4px 12px;padding:14px 12px 16px 20px;background:var(--cw-accent-soft);border-top-color:var(--cw-accent-line)}.update-icon{display:grid;place-items:center;width:30px;height:30px;border-radius:9px;background:var(--cw-surface);color:var(--cw-accent);box-shadow:var(--cw-shadow-sm)}.update-icon svg{width:16px;height:16px}.update-text{display:flex;flex-direction:column;gap:1px;min-width:0;color:var(--cw-muted);font-size:12.5px;line-height:1.45}.update-text strong{color:var(--cw-ink);font-size:13px;font-weight:650}.update-actions{grid-column:2/-1;display:flex;flex-wrap:wrap;gap:8px;margin:8px 8px 0 0}.update-actions .quiet{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;font-size:13px;font-weight:600;border-radius:var(--cw-radius-pill)}.update-actions svg{width:14px;height:14px}.update-toggle svg{color:var(--cw-ai)}.update-prompt{grid-column:1/-1;margin:10px 8px 0 0;max-height:220px;overflow:auto;padding:10px 12px;border:1px solid var(--cw-ai-line);border-radius:10px;background:linear-gradient(135deg,var(--cw-ai-soft),var(--cw-surface));color:var(--cw-ink);font:11.5px/1.55 ui-monospace,SFMono-Regular,Menlo,monospace;white-space:pre-wrap;overflow-wrap:anywhere;user-select:text;-webkit-user-select:text}.update-prompt:focus-visible{outline:2px solid var(--cw-accent);outline-offset:2px}
|
|
805
834
|
@media(max-width:600px){.search input{font-size:16px}.select{max-width:100%}}
|
|
806
835
|
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important;scroll-behavior:auto!important}}
|
|
807
836
|
`;
|
|
@@ -1667,6 +1696,8 @@ class Overlay {
|
|
|
1667
1696
|
__publicField(this, "settingsCache", null);
|
|
1668
1697
|
/** A newer npm version, found when the sidebar first opens. See checkForUpdate(). */
|
|
1669
1698
|
__publicField(this, "update", null);
|
|
1699
|
+
__publicField(this, "updatePromptOpen", false);
|
|
1700
|
+
__publicField(this, "settingsTab", "general");
|
|
1670
1701
|
__publicField(this, "updateChecked", false);
|
|
1671
1702
|
/** The page margin we replaced to make room for the sidebar, restored when it closes. */
|
|
1672
1703
|
__publicField(this, "pushed", null);
|
|
@@ -1884,13 +1915,13 @@ class Overlay {
|
|
|
1884
1915
|
});
|
|
1885
1916
|
});
|
|
1886
1917
|
var _a, _b, _c;
|
|
1887
|
-
this.config = { primaryColor: "#0068f9", position: "bottom-right", keyboardShortcut: "alt+
|
|
1918
|
+
this.config = { primaryColor: "#0068f9", position: "bottom-right", keyboardShortcut: "alt+c", enableKeyboardShortcuts: true, ...config };
|
|
1888
1919
|
if (!/^#[0-9a-f]{3}([0-9a-f]{3})?$/i.test(this.config.primaryColor ?? "")) {
|
|
1889
1920
|
throw new Error("primaryColor must be a 3- or 6-digit hex color.");
|
|
1890
1921
|
}
|
|
1891
1922
|
if (this.config.theme !== void 0 && !THEMES.includes(this.config.theme)) throw new Error('theme must be "light", "dark" or "system".');
|
|
1892
1923
|
this.shortcut = parseShortcut(this.config.keyboardShortcut ?? "");
|
|
1893
|
-
if (this.config.enableKeyboardShortcuts && !this.shortcut) throw new Error('keyboardShortcut must be a key such as "alt+
|
|
1924
|
+
if (this.config.enableKeyboardShortcuts && !this.shortcut) throw new Error('keyboardShortcut must be a key such as "alt+c".');
|
|
1894
1925
|
const project = config.projectId || location.hostname || "default";
|
|
1895
1926
|
this.identityKey = `overplay:${project}:user`;
|
|
1896
1927
|
this.launcherKey = `overplay:${project}:launcher`;
|
|
@@ -2229,7 +2260,11 @@ ${this.currentPage()}`;
|
|
|
2229
2260
|
this.visible = true;
|
|
2230
2261
|
this.render();
|
|
2231
2262
|
this.trackLayoutMotion();
|
|
2232
|
-
|
|
2263
|
+
const panel = this.shadow.querySelector(".panel");
|
|
2264
|
+
if (panel) {
|
|
2265
|
+
panel.tabIndex = -1;
|
|
2266
|
+
panel.focus({ preventScroll: true });
|
|
2267
|
+
} else (_a = this.shadow.querySelector(".launcher")) == null ? void 0 : _a.focus();
|
|
2233
2268
|
this.checkForUpdate();
|
|
2234
2269
|
}
|
|
2235
2270
|
hide() {
|
|
@@ -2727,7 +2762,9 @@ ${this.currentPage()}`;
|
|
|
2727
2762
|
* Only development hosts check by default: that is where the person reading the notice can run npm.
|
|
2728
2763
|
*/
|
|
2729
2764
|
checkForUpdate() {
|
|
2730
|
-
|
|
2765
|
+
var _a;
|
|
2766
|
+
const scriptTag = typeof ((_a = globalThis.Overplay) == null ? void 0 : _a.init) === "function";
|
|
2767
|
+
if (this.updateChecked || !(this.config.updateNotice ?? (developmentHost(location.hostname) && !scriptTag))) return;
|
|
2731
2768
|
this.updateChecked = true;
|
|
2732
2769
|
void latestVersion().then((latest) => {
|
|
2733
2770
|
if (this.destroyed || !latest || !isNewer(latest, VERSION)) return;
|
|
@@ -2740,19 +2777,24 @@ ${this.currentPage()}`;
|
|
|
2740
2777
|
});
|
|
2741
2778
|
}
|
|
2742
2779
|
async copyUpdate() {
|
|
2780
|
+
const prompt = updatePrompt(VERSION, this.update ?? "latest");
|
|
2743
2781
|
let copied = false;
|
|
2744
2782
|
try {
|
|
2745
|
-
await navigator.clipboard.writeText(
|
|
2783
|
+
await navigator.clipboard.writeText(prompt);
|
|
2746
2784
|
copied = true;
|
|
2747
2785
|
} catch {
|
|
2748
2786
|
}
|
|
2787
|
+
if (!copied) {
|
|
2788
|
+
this.updatePromptOpen = true;
|
|
2789
|
+
this.render();
|
|
2790
|
+
}
|
|
2749
2791
|
this.toast({
|
|
2750
2792
|
kind: "comment",
|
|
2751
2793
|
commentId: "",
|
|
2752
|
-
author: copied ?
|
|
2753
|
-
text: copied ?
|
|
2794
|
+
author: copied ? "Update prompt copied" : "Copy the prompt below",
|
|
2795
|
+
text: copied ? "Paste it into your coding agent. It updates the package, clears the cache and restarts the dev server." : "Select the prompt text and copy it."
|
|
2754
2796
|
}, true);
|
|
2755
|
-
this.announce(copied ? "Update
|
|
2797
|
+
this.announce(copied ? "Update prompt copied." : "Select the prompt text to copy it.");
|
|
2756
2798
|
}
|
|
2757
2799
|
/** "Later" hides the notice until the next version comes out. */
|
|
2758
2800
|
dismissUpdate() {
|
|
@@ -3468,6 +3510,10 @@ ${this.currentPage()}`;
|
|
|
3468
3510
|
return empty;
|
|
3469
3511
|
}
|
|
3470
3512
|
/** A new npm version is the one thing left at the bottom. The account and settings live in the header. */
|
|
3513
|
+
/**
|
|
3514
|
+
* The update notice: an AI prompt that updates the package, clears the bundler cache and restarts the dev
|
|
3515
|
+
* server. A version bump alone often keeps serving the old widget.
|
|
3516
|
+
*/
|
|
3471
3517
|
footer() {
|
|
3472
3518
|
if (!this.update) return null;
|
|
3473
3519
|
const footer = element("div", "footer update-bar");
|
|
@@ -3475,16 +3521,24 @@ ${this.currentPage()}`;
|
|
|
3475
3521
|
const mark = element("span", "update-icon");
|
|
3476
3522
|
mark.append(icon("refresh"));
|
|
3477
3523
|
const text = element("div", "update-text");
|
|
3478
|
-
text.append(element("strong", "", `Version ${this.update} is available`), element("span", "", `You have ${VERSION}.
|
|
3479
|
-
const
|
|
3480
|
-
const
|
|
3481
|
-
|
|
3482
|
-
|
|
3524
|
+
text.append(element("strong", "", `Version ${this.update} is available`), element("span", "", `You have ${VERSION}. Give this prompt to your coding agent to update.`));
|
|
3525
|
+
const actions = element("div", "update-actions");
|
|
3526
|
+
const show = button(this.updatePromptOpen ? "Hide Prompt" : "Show Prompt", "quiet update-toggle", () => {
|
|
3527
|
+
this.updatePromptOpen = !this.updatePromptOpen;
|
|
3528
|
+
this.render();
|
|
3529
|
+
}, "sparkle");
|
|
3530
|
+
show.setAttribute("aria-expanded", String(this.updatePromptOpen));
|
|
3531
|
+
const copy = button("Copy Prompt", "quiet update", () => {
|
|
3483
3532
|
void this.copyUpdate();
|
|
3484
|
-
});
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3533
|
+
}, "copy");
|
|
3534
|
+
actions.append(show, copy);
|
|
3535
|
+
footer.append(mark, text, button("Hide until the next version", "icon-button", () => this.dismissUpdate(), "close"), actions);
|
|
3536
|
+
if (this.updatePromptOpen) {
|
|
3537
|
+
const prompt = element("pre", "update-prompt", updatePrompt(VERSION, this.update));
|
|
3538
|
+
prompt.tabIndex = 0;
|
|
3539
|
+
prompt.setAttribute("aria-label", "Update prompt for your coding agent");
|
|
3540
|
+
footer.append(prompt);
|
|
3541
|
+
}
|
|
3488
3542
|
return footer;
|
|
3489
3543
|
}
|
|
3490
3544
|
messageHeader(name, timestamp, url, via, words2 = []) {
|
|
@@ -3637,14 +3691,26 @@ ${this.currentPage()}`;
|
|
|
3637
3691
|
}
|
|
3638
3692
|
/** Display choices for this project. Each person has their own, saved in this browser. */
|
|
3639
3693
|
settingsView() {
|
|
3640
|
-
var _a;
|
|
3641
3694
|
const view = this.view("Settings", "settings");
|
|
3642
3695
|
view.append(this.detailHeading("Settings", "Your choices for this project. Other people keep their own."));
|
|
3643
3696
|
const current = this.settings, body = element("div", "settings-body");
|
|
3644
|
-
const
|
|
3697
|
+
const tabs = element("div", "tabs settings-tabs");
|
|
3698
|
+
tabs.setAttribute("role", "group");
|
|
3699
|
+
tabs.setAttribute("aria-label", "Settings section");
|
|
3700
|
+
for (const [id, label2] of [["general", "General"], ["appearance", "Appearance"]]) {
|
|
3701
|
+
const tab = button(label2, "tab", () => {
|
|
3702
|
+
this.settingsTab = id;
|
|
3703
|
+
this.render();
|
|
3704
|
+
});
|
|
3705
|
+
tab.setAttribute("aria-pressed", String(this.settingsTab === id));
|
|
3706
|
+
tab.dataset.focus = `settings-tab-${id}`;
|
|
3707
|
+
tabs.append(tab);
|
|
3708
|
+
}
|
|
3709
|
+
body.append(tabs);
|
|
3710
|
+
const section = (title, tab) => {
|
|
3645
3711
|
const group = element("section", "setting-group");
|
|
3646
3712
|
group.append(element("h3", "", title));
|
|
3647
|
-
body.append(group);
|
|
3713
|
+
if (tab === this.settingsTab) body.append(group);
|
|
3648
3714
|
return group;
|
|
3649
3715
|
};
|
|
3650
3716
|
const row = (group, label2, hint, control) => {
|
|
@@ -3680,9 +3746,9 @@ ${this.currentPage()}`;
|
|
|
3680
3746
|
control.addEventListener("click", () => this.setSetting(name, !on));
|
|
3681
3747
|
return control;
|
|
3682
3748
|
};
|
|
3683
|
-
const look = section("
|
|
3749
|
+
const look = section("Theme", "appearance");
|
|
3684
3750
|
row(look, "Theme", current.theme === "system" ? "Follows your device" : "", choice("theme", "Theme", [["light", "Light"], ["dark", "Dark"], ["system", "System"]]));
|
|
3685
|
-
const pins = section("Pins");
|
|
3751
|
+
const pins = section("Pins", "appearance");
|
|
3686
3752
|
const sample = element("div", `pin-sample${current.pinSize === "small" ? " small" : ""}${current.resolvedPins === "gray" ? " resolved-gray" : ""}`);
|
|
3687
3753
|
sample.setAttribute("aria-hidden", "true");
|
|
3688
3754
|
sample.style.setProperty("--cw-accent", this.pinColor());
|
|
@@ -3706,7 +3772,7 @@ ${this.currentPage()}`;
|
|
|
3706
3772
|
row(pins, "Resolved pins", "", choice("resolvedPins", "Resolved pins", [["green", "Green"], ["gray", "Gray"]]));
|
|
3707
3773
|
row(pins, "Size", "", choice("pinSize", "Pin size", [["regular", "Regular"], ["small", "Small"]]));
|
|
3708
3774
|
row(pins, "Label", "", choice("pinLabel", "Pin label", [["number", "Number"], ["initials", "Initials"]]));
|
|
3709
|
-
const floating = section("Comments button");
|
|
3775
|
+
const floating = section("Comments button", "appearance");
|
|
3710
3776
|
const buttonSample = element("div", "launcher-sample");
|
|
3711
3777
|
buttonSample.setAttribute("aria-hidden", "true");
|
|
3712
3778
|
const mini = element("span", "launcher-mini");
|
|
@@ -3728,7 +3794,7 @@ ${this.currentPage()}`;
|
|
|
3728
3794
|
}
|
|
3729
3795
|
const buttonHint = current.buttonColor === "default" ? "Dark. Takes the site color while open." : current.buttonColor === "site" ? "The color of this site" : PIN_COLORS[current.buttonColor].label;
|
|
3730
3796
|
row(floating, "Color", buttonHint, buttonSwatches).classList.add("wide");
|
|
3731
|
-
const panel = section("Panel");
|
|
3797
|
+
const panel = section("Panel", "general");
|
|
3732
3798
|
const open = element("div", "segmented");
|
|
3733
3799
|
open.setAttribute("role", "group");
|
|
3734
3800
|
open.setAttribute("aria-label", "Open comments");
|
|
@@ -3742,9 +3808,9 @@ ${this.currentPage()}`;
|
|
|
3742
3808
|
}
|
|
3743
3809
|
row(panel, "Open comments", "", open);
|
|
3744
3810
|
row(panel, "Push the page aside", "The open panel does not cover the page.", toggle("pushContent", "Push the page aside"));
|
|
3745
|
-
const alerts = section("Notifications and keys");
|
|
3811
|
+
const alerts = section("Notifications and keys", "general");
|
|
3746
3812
|
row(alerts, "New activity", "Show a short notice when others comment or reply.", toggle("notifications", "Show new activity"));
|
|
3747
|
-
const keys = (
|
|
3813
|
+
const keys = shortcutLabel(this.config.keyboardShortcut ?? "", /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent));
|
|
3748
3814
|
row(alerts, "Keyboard shortcut", this.shortcut ? `${keys} opens and closes comments.` : "This site has no shortcut.", toggle("shortcut", "Keyboard shortcut", !this.shortcut));
|
|
3749
3815
|
const foot = element("div", "settings-foot");
|
|
3750
3816
|
foot.append(element("span", "", "Saved in this browser"), button("Reset to Defaults", "quiet", () => this.resetSettings()));
|