@adia-ai/web-modules 0.8.44 → 0.8.45
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 +14 -0
- package/billing/billing-overview/billing-overview.class.js +7 -3
- package/billing/invoice-detail/invoice-detail.class.js +6 -3
- package/billing/invoice-history/invoice-history.class.js +6 -3
- package/billing/plan-picker/plan-picker.class.js +6 -3
- package/chat/chat-sidebar/chat-sidebar.js +26 -73
- package/dist/everything.min.js +110 -110
- package/dist/shell/admin-shell.min.css +1 -1
- package/dist/web-modules.min.css +1 -1
- package/dist/web-modules.sheet.js +1 -1
- package/editor/editor-sidebar/editor-sidebar.js +21 -13
- package/package.json +7 -6
- package/shared/sidebar-persist.js +152 -0
- package/shell/admin-shell/css/admin-shell.tokens.css +1 -1
- package/shell/admin-sidebar/admin-sidebar.js +26 -88
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog — @adia-ai/web-modules
|
|
2
2
|
|
|
3
|
+
## [0.8.45] — 2026-08-20
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- **New `shared/sidebar-persist.js` module extracted from the admin/chat sidebars' duplicated collapse/persist mechanics (gh#1767).** `editor-sidebar` kept bespoke (pane-ui delegation).
|
|
7
|
+
- **`for=`-carrying component normalization (gh#1764/#1780) and `RouteController` dedup onto `@adia-ai/web-components`'s `core/controller.js` (gh#1766) ride along — no `web-modules`-local API change.**
|
|
8
|
+
|
|
9
|
+
### Note
|
|
10
|
+
- The headline v0.8.45 work shipped in `@adia-ai/web-components`. See `packages/web-components/CHANGELOG.md#0845--2026-08-20` for details.
|
|
11
|
+
|
|
12
|
+
### Maintenance
|
|
13
|
+
- **`billing/` touched in this release window** (8 file(s), e.g. `billing-overview/billing-overview.class.js`) — carried by the entries above.
|
|
14
|
+
- **`dist/` bundles rebuilt** in this cut's window (1 file(s)) — regenerated from the source changes described above, not independent edits.
|
|
15
|
+
- **`shell/` touched in this release window** (1 file(s), e.g. `admin-sidebar/admin-sidebar.js`) — carried by the entries above.
|
|
16
|
+
|
|
3
17
|
## [0.8.44] — 2026-08-20
|
|
4
18
|
|
|
5
19
|
### Fixed
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
|
|
52
52
|
import { UIElement } from '@adia-ai/web-components/core/element';
|
|
53
53
|
import { untracked } from '@adia-ai/web-components/core/signals';
|
|
54
|
+
import { json } from '@adia-ai/web-components/core/transport';
|
|
54
55
|
|
|
55
56
|
const KNOWN_STATUSES = new Set([
|
|
56
57
|
'active', 'trialing', 'past_due', 'canceled', 'paused',
|
|
@@ -187,9 +188,7 @@ export class UIBillingOverview extends UIElement {
|
|
|
187
188
|
this.loading = true;
|
|
188
189
|
this.removeAttribute('error');
|
|
189
190
|
try {
|
|
190
|
-
const
|
|
191
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
192
|
-
const data = await res.json();
|
|
191
|
+
const data = await json(src);
|
|
193
192
|
if (tag !== this.#loadCount) return;
|
|
194
193
|
this.loading = false;
|
|
195
194
|
const record = data && typeof data === 'object' && data.account
|
|
@@ -214,6 +213,11 @@ export class UIBillingOverview extends UIElement {
|
|
|
214
213
|
// ── Lifecycle ─────────────────────────────────────────────────────
|
|
215
214
|
|
|
216
215
|
connected() {
|
|
216
|
+
// gh#1760 — opt this element out of core/data-stream.js's document-level
|
|
217
|
+
// auto-observer. This composite is the sole owner of `data-stream-src`
|
|
218
|
+
// for itself (hand-rolled `refresh()` above); without this marker, a
|
|
219
|
+
// page that also imports the core barrel double-fetches on connect.
|
|
220
|
+
this.setAttribute('data-stream-managed', 'false');
|
|
217
221
|
this.setAttribute('role', 'region');
|
|
218
222
|
|
|
219
223
|
if (!this.#stamped) {
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
import { UIElement } from '@adia-ai/web-components/core/element';
|
|
31
31
|
import { untracked } from '@adia-ai/web-components/core/signals';
|
|
32
|
+
import { json } from '@adia-ai/web-components/core/transport';
|
|
32
33
|
|
|
33
34
|
const KNOWN_STATUSES = new Set(['draft', 'open', 'paid', 'past-due', 'void']);
|
|
34
35
|
|
|
@@ -177,9 +178,7 @@ export class UIInvoiceDetail extends UIElement {
|
|
|
177
178
|
this.loading = true;
|
|
178
179
|
this.removeAttribute('error');
|
|
179
180
|
try {
|
|
180
|
-
const
|
|
181
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
182
|
-
const data = await res.json();
|
|
181
|
+
const data = await json(src);
|
|
183
182
|
if (tag !== this.#loadCount) return; // stale
|
|
184
183
|
this.loading = false;
|
|
185
184
|
// Allow either {invoice: {...}} envelope or the raw record.
|
|
@@ -212,6 +211,10 @@ export class UIInvoiceDetail extends UIElement {
|
|
|
212
211
|
// ── Lifecycle ─────────────────────────────────────────────────────
|
|
213
212
|
|
|
214
213
|
connected() {
|
|
214
|
+
// gh#1760 — opt out of core/data-stream.js's document-level
|
|
215
|
+
// auto-observer; this composite owns `data-stream-src` itself
|
|
216
|
+
// via the hand-rolled `refresh()` above.
|
|
217
|
+
this.setAttribute('data-stream-managed', 'false');
|
|
215
218
|
this.setAttribute('role', 'region');
|
|
216
219
|
|
|
217
220
|
if (!this.#stamped) {
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
|
|
35
35
|
import { UIElement } from '@adia-ai/web-components/core/element';
|
|
36
36
|
import { untracked } from '@adia-ai/web-components/core/signals';
|
|
37
|
+
import { json } from '@adia-ai/web-components/core/transport';
|
|
37
38
|
|
|
38
39
|
const KNOWN_STATUSES = new Set(['draft', 'open', 'paid', 'past-due', 'void']);
|
|
39
40
|
|
|
@@ -227,9 +228,7 @@ export class InvoiceHistory extends UIElement {
|
|
|
227
228
|
this.setAttribute('loading', '');
|
|
228
229
|
this.removeAttribute('error');
|
|
229
230
|
try {
|
|
230
|
-
const
|
|
231
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
232
|
-
const data = await res.json();
|
|
231
|
+
const data = await json(src);
|
|
233
232
|
if (tag !== this.#loadCount) return; // stale
|
|
234
233
|
this.removeAttribute('loading');
|
|
235
234
|
const list = Array.isArray(data)
|
|
@@ -255,6 +254,10 @@ export class InvoiceHistory extends UIElement {
|
|
|
255
254
|
|
|
256
255
|
connected() {
|
|
257
256
|
super.connected?.();
|
|
257
|
+
// gh#1760 — opt out of core/data-stream.js's document-level
|
|
258
|
+
// auto-observer; this composite owns `data-stream-src` itself
|
|
259
|
+
// via the hand-rolled `refresh()` below.
|
|
260
|
+
this.setAttribute('data-stream-managed', 'false');
|
|
258
261
|
this.setAttribute('role', 'region');
|
|
259
262
|
if (!this.hasAttribute('aria-label') && !this.hasAttribute('aria-labelledby')) {
|
|
260
263
|
this.setAttribute('aria-label', 'Invoice history');
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
|
|
44
44
|
import { UIFormElement } from '@adia-ai/web-components/core/form';
|
|
45
45
|
import { untracked } from '@adia-ai/web-components/core/signals';
|
|
46
|
+
import { json } from '@adia-ai/web-components/core/transport';
|
|
46
47
|
|
|
47
48
|
const KNOWN_CYCLES = new Set(['monthly', 'annual']);
|
|
48
49
|
|
|
@@ -185,9 +186,7 @@ export class PlanPicker extends UIFormElement {
|
|
|
185
186
|
this.setAttribute('loading', '');
|
|
186
187
|
this.removeAttribute('error');
|
|
187
188
|
try {
|
|
188
|
-
const
|
|
189
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
190
|
-
const data = await res.json();
|
|
189
|
+
const data = await json(src);
|
|
191
190
|
if (tag !== this.#loadCount) return; // stale
|
|
192
191
|
this.removeAttribute('loading');
|
|
193
192
|
const list = Array.isArray(data) ? data : (Array.isArray(data?.plans) ? data.plans : []);
|
|
@@ -211,6 +210,10 @@ export class PlanPicker extends UIFormElement {
|
|
|
211
210
|
|
|
212
211
|
connected() {
|
|
213
212
|
super.connected();
|
|
213
|
+
// gh#1760 — opt out of core/data-stream.js's document-level
|
|
214
|
+
// auto-observer; this composite owns `data-stream-src` itself
|
|
215
|
+
// via the hand-rolled `refresh()` above.
|
|
216
|
+
this.setAttribute('data-stream-managed', 'false');
|
|
214
217
|
this.setAttribute('role', 'radiogroup');
|
|
215
218
|
if (!this.hasAttribute('aria-label') && !this.hasAttribute('aria-labelledby')) {
|
|
216
219
|
this.setAttribute('aria-label', 'Choose a plan');
|
|
@@ -37,13 +37,22 @@
|
|
|
37
37
|
* Backwards compat: <chat-shell> still recognizes the legacy
|
|
38
38
|
* `<aside data-sidebar="leading">` shape via :is() selector. New
|
|
39
39
|
* code should prefer <chat-sidebar>.
|
|
40
|
+
*
|
|
41
|
+
* gh#1767 (reactivity review R8b) — collapse()/expand()/toggle() and the
|
|
42
|
+
* localStorage persistence now come from ../../shared/sidebar-persist.js,
|
|
43
|
+
* shared verbatim with <admin-sidebar> (the storage-key PREFIX is this
|
|
44
|
+
* component's own — `adia-chat-sidebar-*` — so no existing user's
|
|
45
|
+
* persisted width resets). See that module's header for why
|
|
46
|
+
* editor-sidebar isn't a third consumer.
|
|
40
47
|
*/
|
|
41
48
|
|
|
42
49
|
import { defineIfFree } from '@adia-ai/web-components/core/register';
|
|
43
50
|
import { UIElement } from '@adia-ai/web-components/core/element';
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
import {
|
|
52
|
+
attachSidebarCollapsePersist,
|
|
53
|
+
SIDEBAR_SNAP_THRESHOLD as SNAP_THRESHOLD,
|
|
54
|
+
SIDEBAR_SNAP_MIN_USABLE as SNAP_MIN_USABLE,
|
|
55
|
+
} from '../../shared/sidebar-persist.js';
|
|
47
56
|
|
|
48
57
|
class ChatSidebar extends UIElement {
|
|
49
58
|
static properties = {
|
|
@@ -57,17 +66,21 @@ class ChatSidebar extends UIElement {
|
|
|
57
66
|
|
|
58
67
|
static template = () => null;
|
|
59
68
|
|
|
60
|
-
// The width the sidebar had before being collapsed — used for restore.
|
|
61
|
-
// Map keyed by sidebar name allows multiple sidebars on one host.
|
|
62
|
-
#previousExpandedWidth = '';
|
|
63
69
|
#resizeCleanups = [];
|
|
64
70
|
#childRO = null;
|
|
71
|
+
// Collapse/expand/toggle/persist mechanics — shared with admin-sidebar
|
|
72
|
+
// (reactivity review R8b, gh#1767); see shared/sidebar-persist.js for
|
|
73
|
+
// why editor-sidebar isn't a third consumer. No `guardZeroWidth` here —
|
|
74
|
+
// chat-sidebar's pre-extraction behavior never guarded a zero-rect
|
|
75
|
+
// connect (unlike admin-sidebar's gh#286 fix), so this stays unguarded
|
|
76
|
+
// too (behavior-preserving, not a bug fix bundled into this extraction).
|
|
77
|
+
#persist = attachSidebarCollapsePersist(this, { prefix: 'adia-chat-sidebar' });
|
|
65
78
|
|
|
66
79
|
connected() {
|
|
67
|
-
this.#restoreFromStorage();
|
|
80
|
+
this.#persist.restoreFromStorage();
|
|
68
81
|
if (this.resizable) this.#setupResizeHandle();
|
|
69
82
|
this.#setupChildResizeObserver();
|
|
70
|
-
this.#syncCollapsedFromWidth();
|
|
83
|
+
this.#persist.syncCollapsedFromWidth();
|
|
71
84
|
}
|
|
72
85
|
|
|
73
86
|
disconnected() {
|
|
@@ -84,68 +97,17 @@ class ChatSidebar extends UIElement {
|
|
|
84
97
|
* Returns the new collapsed value.
|
|
85
98
|
*/
|
|
86
99
|
toggle() {
|
|
87
|
-
|
|
88
|
-
this.expand();
|
|
89
|
-
} else {
|
|
90
|
-
this.collapse();
|
|
91
|
-
}
|
|
92
|
-
return this.collapsed;
|
|
100
|
+
return this.#persist.toggle();
|
|
93
101
|
}
|
|
94
102
|
|
|
95
103
|
/** Collapse to the snap-floor width. Persists to localStorage. */
|
|
96
104
|
collapse() {
|
|
97
|
-
|
|
98
|
-
// Remember current expanded width before collapsing
|
|
99
|
-
const currentWidth = this.style.width || getComputedStyle(this).width;
|
|
100
|
-
if (parseFloat(currentWidth) > SNAP_THRESHOLD) {
|
|
101
|
-
this.#previousExpandedWidth = currentWidth;
|
|
102
|
-
}
|
|
103
|
-
const minW = this.minWidth || getComputedStyle(this).minWidth;
|
|
104
|
-
this.style.width = minW;
|
|
105
|
-
this.#persist(minW);
|
|
106
|
-
this.collapsed = true;
|
|
107
|
-
this.#dispatchToggle(false);
|
|
105
|
+
this.#persist.collapse();
|
|
108
106
|
}
|
|
109
107
|
|
|
110
108
|
/** Restore to the previous expanded width (or default if none). */
|
|
111
109
|
expand() {
|
|
112
|
-
|
|
113
|
-
const restoreWidth = this.#previousExpandedWidth || '';
|
|
114
|
-
this.style.width = restoreWidth;
|
|
115
|
-
this.#persist(restoreWidth);
|
|
116
|
-
this.collapsed = false;
|
|
117
|
-
this.#dispatchToggle(true);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// ── Persistence ──
|
|
121
|
-
|
|
122
|
-
#storageKey() {
|
|
123
|
-
const id = this.name || this.getAttribute('slot') || 'default';
|
|
124
|
-
return `adia-chat-sidebar-${id}`;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
#persist(width) {
|
|
128
|
-
try { localStorage.setItem(this.#storageKey(), width); } catch {}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
#restoreFromStorage() {
|
|
132
|
-
try {
|
|
133
|
-
const saved = localStorage.getItem(this.#storageKey());
|
|
134
|
-
if (!saved) return;
|
|
135
|
-
this.style.width = saved;
|
|
136
|
-
// Only treat as "previous expanded" if actually expanded
|
|
137
|
-
const w = parseFloat(saved);
|
|
138
|
-
if (!isNaN(w) && w > SNAP_THRESHOLD) {
|
|
139
|
-
this.#previousExpandedWidth = saved;
|
|
140
|
-
}
|
|
141
|
-
} catch {}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// ── Reflect [collapsed] from current measured width ──
|
|
145
|
-
|
|
146
|
-
#syncCollapsedFromWidth() {
|
|
147
|
-
const w = this.getBoundingClientRect().width;
|
|
148
|
-
this.collapsed = w <= SNAP_THRESHOLD;
|
|
110
|
+
this.#persist.expand();
|
|
149
111
|
}
|
|
150
112
|
|
|
151
113
|
// ── Resize drag handle ──
|
|
@@ -189,8 +151,8 @@ class ChatSidebar extends UIElement {
|
|
|
189
151
|
this.style.width = `${SNAP_MIN_USABLE}px`;
|
|
190
152
|
}
|
|
191
153
|
|
|
192
|
-
this.#persist(this.style.width);
|
|
193
|
-
this.#syncCollapsedFromWidth();
|
|
154
|
+
this.#persist.persist(this.style.width);
|
|
155
|
+
this.#persist.syncCollapsedFromWidth();
|
|
194
156
|
this.dispatchEvent(new CustomEvent('sidebar-resize', {
|
|
195
157
|
bubbles: true,
|
|
196
158
|
detail: { name: this.name || slot, width: this.getBoundingClientRect().width },
|
|
@@ -220,15 +182,6 @@ class ChatSidebar extends UIElement {
|
|
|
220
182
|
});
|
|
221
183
|
this.#childRO.observe(this);
|
|
222
184
|
}
|
|
223
|
-
|
|
224
|
-
// ── Internal — dispatch the toggle event in a consistent shape ──
|
|
225
|
-
|
|
226
|
-
#dispatchToggle(expanded) {
|
|
227
|
-
this.dispatchEvent(new CustomEvent('sidebar-toggle', {
|
|
228
|
-
bubbles: true,
|
|
229
|
-
detail: { name: this.name || this.getAttribute('slot') || 'default', expanded },
|
|
230
|
-
}));
|
|
231
|
-
}
|
|
232
185
|
}
|
|
233
186
|
|
|
234
187
|
defineIfFree('chat-sidebar', ChatSidebar);
|