@aparte/core 0.16.4 → 0.16.5
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/composer/aparte-composer-input.d.ts +8 -0
- package/dist/components/composer/aparte-composer-input.d.ts.map +1 -1
- package/dist/components/split/aparte-split.d.ts +5 -1
- package/dist/components/split/aparte-split.d.ts.map +1 -1
- package/dist/components/viewport/aparte-chat-viewport.d.ts +30 -0
- package/dist/components/viewport/aparte-chat-viewport.d.ts.map +1 -1
- package/dist/custom-elements.json +5572 -5485
- package/dist/generated/element-attributes.d.ts +2 -0
- package/dist/generated/element-attributes.d.ts.map +1 -1
- package/dist/index.css +108 -41
- package/dist/index.js +116 -15
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -200,6 +200,8 @@ export interface AparteSplitAttributes {
|
|
|
200
200
|
disabled?: boolean;
|
|
201
201
|
/** The seam's accessible name. Defaults to the locale's `splitHandleLabel`. */
|
|
202
202
|
label?: string;
|
|
203
|
+
/** Show one pane — the one `pane` names — whatever the width: the seam and the other pane are gone, as under the breakpoint. For a host that decides itself when a second pane exists (a preview with nothing to preview yet). `collapsed` is not this: it folds the primary pane to `--aparte-split-min` and keeps the seam. The CSS route, `.aparte-split--only-start` / `--only-end`, is the same state for a host that owns its breakpoints. */
|
|
204
|
+
single?: boolean;
|
|
203
205
|
/** Written BY the element while one pane is shown. Read-only; style against it. */
|
|
204
206
|
'data-stacked'?: boolean;
|
|
205
207
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element-attributes.d.ts","sourceRoot":"","sources":["../../src/generated/element-attributes.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"element-attributes.d.ts","sourceRoot":"","sources":["../../src/generated/element-attributes.ts"],"names":[],"mappings":"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"}
|
package/dist/index.css
CHANGED
|
@@ -596,7 +596,11 @@ aparte-chat {
|
|
|
596
596
|
The eight text sizes were px and are rem now, like the rest of the typography:
|
|
597
597
|
identical at a 16px root, and following the reader's setting elsewhere. */
|
|
598
598
|
--aparte-message-gap: var(--aparte-space-6);
|
|
599
|
-
|
|
599
|
+
/* Split, because the action bar's offset below a message is computed from the
|
|
600
|
+
vertical half (#56) — a shorthand cannot be read by parts. */
|
|
601
|
+
--aparte-message-padding-block: var(--aparte-space-8);
|
|
602
|
+
--aparte-message-padding-inline: var(--aparte-space-6);
|
|
603
|
+
--aparte-message-padding: var(--aparte-message-padding-block) var(--aparte-message-padding-inline);
|
|
600
604
|
--aparte-message-content-padding: var(--aparte-space-5) var(--aparte-space-7);
|
|
601
605
|
--aparte-action-bar-gap: var(--aparte-space-2);
|
|
602
606
|
--aparte-branch-picker-gap: var(--aparte-space-2);
|
|
@@ -1030,6 +1034,10 @@ aparte-conversation-list {
|
|
|
1030
1034
|
* <button class="aparte-btn aparte-btn--surface">1 / 2</button>
|
|
1031
1035
|
* <button class="aparte-btn aparte-btn--surface">›</button>
|
|
1032
1036
|
* </div>
|
|
1037
|
+
* <div class="aparte-btn-group" role="group" aria-label="View">
|
|
1038
|
+
* <button class="aparte-btn aparte-btn--primary aparte-btn--outline" aria-pressed="true">Chat</button>
|
|
1039
|
+
* <button class="aparte-btn aparte-btn--primary aparte-btn--outline" aria-pressed="false">Preview</button>
|
|
1040
|
+
* </div>
|
|
1033
1041
|
*
|
|
1034
1042
|
* An intent on its own is a ghost — the quietest form, and the one a chat uses most.
|
|
1035
1043
|
* Add a fill when the button has to carry more weight.
|
|
@@ -1037,7 +1045,9 @@ aparte-conversation-list {
|
|
|
1037
1045
|
* `.aparte-btn-group` fuses adjacent buttons into ONE control: the inner corners
|
|
1038
1046
|
* drop, the shared borders overlap, and only the group's ends keep the radius. Give
|
|
1039
1047
|
* the wrapper `role="group"` and a name — visually one control, it should read as
|
|
1040
|
-
* one too.
|
|
1048
|
+
* one too. A SEGMENTED control is the same group with one segment selected: mark it
|
|
1049
|
+
* `aria-pressed="true"` (or `aria-selected="true"` under `role="tablist"`) and it is
|
|
1050
|
+
* painted solid in the group's intent, at rest — not only under the pointer.
|
|
1041
1051
|
*
|
|
1042
1052
|
* This layer is NEUTRAL: it is what a UI library offers, not a summary of what this
|
|
1043
1053
|
* repo happens to use. A variant nothing wears still ships, because the plugin that
|
|
@@ -1242,12 +1252,23 @@ aparte-conversation-list {
|
|
|
1242
1252
|
outline-offset: var(--aparte-btn-focus-offset);
|
|
1243
1253
|
}
|
|
1244
1254
|
|
|
1245
|
-
/* Toggled — a disclosure that is open, a toggle that is on. */
|
|
1255
|
+
/* Toggled — a disclosure that is open, a toggle that is on, a tab that is current. */
|
|
1246
1256
|
.aparte-btn[aria-expanded='true'],
|
|
1247
|
-
.aparte-btn[aria-pressed='true']
|
|
1257
|
+
.aparte-btn[aria-pressed='true'],
|
|
1258
|
+
.aparte-btn[aria-selected='true'] {
|
|
1248
1259
|
background: var(--aparte-btn-bg-toggled);
|
|
1249
1260
|
color: var(--aparte-btn-color-toggled);
|
|
1250
1261
|
}
|
|
1262
|
+
/* On a coloured fill the toggled wash must be DEEPER than the hover wash (22 %), or the
|
|
1263
|
+
pointer reads as the state and the state reads as nothing — measured on a dark
|
|
1264
|
+
`Chat | Preview` group, where `--aparte-btn-bg-toggled` (surface-2) sits a hair from
|
|
1265
|
+
surface-1 and the selected segment showed as an empty outline until hovered (#53). */
|
|
1266
|
+
.aparte-btn--outline[aria-pressed='true'],
|
|
1267
|
+
.aparte-btn--soft[aria-pressed='true'],
|
|
1268
|
+
.aparte-btn--outline[aria-selected='true'],
|
|
1269
|
+
.aparte-btn--soft[aria-selected='true'] {
|
|
1270
|
+
background: color-mix(in srgb, var(--aparte-btn-intent) 30%, transparent);
|
|
1271
|
+
}
|
|
1251
1272
|
|
|
1252
1273
|
/* Busy is NOT disabled: it stays focusable, and the app is what swaps the icon for a
|
|
1253
1274
|
spinner. Only the cursor changes here. */
|
|
@@ -1294,6 +1315,24 @@ aparte-conversation-list {
|
|
|
1294
1315
|
.aparte-btn-group > .aparte-btn:not(:first-child) { margin-inline-start: calc(var(--aparte-border-width) * -1); }
|
|
1295
1316
|
.aparte-btn-group > .aparte-btn:hover,
|
|
1296
1317
|
.aparte-btn-group > .aparte-btn:focus-visible { z-index: var(--aparte-z-raised); }
|
|
1318
|
+
/* The selected segment. Solid in the group's intent, whatever fill the segments wear:
|
|
1319
|
+
a segmented control has exactly one thing to say at rest, and a wash could not say
|
|
1320
|
+
it on dark (#53). `--surface` ignores the intent, so its groups select in neutral.
|
|
1321
|
+
Hover leaves it alone — the pointer must never be what makes selection legible. */
|
|
1322
|
+
.aparte-btn-group > .aparte-btn[aria-pressed='true'],
|
|
1323
|
+
.aparte-btn-group > .aparte-btn[aria-selected='true'],
|
|
1324
|
+
.aparte-btn-group > .aparte-btn[aria-current] {
|
|
1325
|
+
background: var(--aparte-btn-intent);
|
|
1326
|
+
border-color: var(--aparte-btn-intent);
|
|
1327
|
+
color: var(--aparte-btn-on-intent);
|
|
1328
|
+
z-index: var(--aparte-z-raised);
|
|
1329
|
+
}
|
|
1330
|
+
.aparte-btn-group > .aparte-btn[aria-pressed='true']:hover:not(:disabled),
|
|
1331
|
+
.aparte-btn-group > .aparte-btn[aria-selected='true']:hover:not(:disabled),
|
|
1332
|
+
.aparte-btn-group > .aparte-btn[aria-current]:hover:not(:disabled) {
|
|
1333
|
+
background: var(--aparte-btn-intent);
|
|
1334
|
+
filter: none;
|
|
1335
|
+
}
|
|
1297
1336
|
|
|
1298
1337
|
/* In forced-colors the UA repaints everything and drops backgrounds, so a solid button
|
|
1299
1338
|
loses the only thing marking it as the primary action. A border survives. */
|
|
@@ -4549,7 +4588,10 @@ aparte-chat-viewport[framework-managed] {
|
|
|
4549
4588
|
overscroll-behavior: contain;
|
|
4550
4589
|
display: flex;
|
|
4551
4590
|
flex-direction: column;
|
|
4552
|
-
gap
|
|
4591
|
+
/* No flex gap — each bubble carries the distance to the next as its own padding,
|
|
4592
|
+
inside its contained box, where an older message's action bar floats (#56;
|
|
4593
|
+
the rationale is on `.aparte-messages-wrapper` in bubble.css). */
|
|
4594
|
+
gap: 0;
|
|
4553
4595
|
padding: var(--aparte-viewport-padding);
|
|
4554
4596
|
/* No bottom padding: a sticky child is clamped to its parent's CONTENT box, so
|
|
4555
4597
|
clearance carried as padding held the scroll button `padding + spacer` above
|
|
@@ -4583,11 +4625,10 @@ aparte-chat-viewport.aparte-viewport--framework::after,
|
|
|
4583
4625
|
aparte-chat-viewport[framework-managed]::after {
|
|
4584
4626
|
content: '';
|
|
4585
4627
|
flex: 0 0 calc(var(--aparte-viewport-padding) + var(--aparte-fw-spacer, 0px) + var(--aparte-bottom-inset, 0px));
|
|
4586
|
-
/*
|
|
4587
|
-
the
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
margin-block-start: calc(var(--aparte-message-gap) * -1);
|
|
4628
|
+
/* The column has no `gap` any more (each bubble carries its own), so this item pays
|
|
4629
|
+
none — the negative margin that used to cancel it would now eat the last bubble's
|
|
4630
|
+
padding. (History: with a gap, an EMPTY transcript was 8px taller than its box and
|
|
4631
|
+
grew a scrollbar beside the welcome state.) */
|
|
4591
4632
|
}
|
|
4592
4633
|
|
|
4593
4634
|
aparte-chat-viewport.aparte-viewport--framework::-webkit-scrollbar {
|
|
@@ -4730,7 +4771,11 @@ aparte-chat[overlay-composer][center-empty][data-empty] > aparte-chat-viewport,
|
|
|
4730
4771
|
.aparte-messages-wrapper {
|
|
4731
4772
|
display: flex;
|
|
4732
4773
|
flex-direction: column;
|
|
4733
|
-
gap:
|
|
4774
|
+
/* No flex gap: the space between two turns is each bubble's own padding-block-end
|
|
4775
|
+
(below), so that it lies INSIDE the bubble's contained box — where the action
|
|
4776
|
+
bar of an older message floats (#56). A flex gap is outside every box, and the
|
|
4777
|
+
bubble's paint containment clipped anything placed there. */
|
|
4778
|
+
gap: 0;
|
|
4734
4779
|
padding: var(--aparte-viewport-padding);
|
|
4735
4780
|
}
|
|
4736
4781
|
|
|
@@ -4753,6 +4798,10 @@ aparte-chat-bubble {
|
|
|
4753
4798
|
contain: layout style paint;
|
|
4754
4799
|
content-visibility: auto;
|
|
4755
4800
|
contain-intrinsic-size: auto 320px;
|
|
4801
|
+
/* The distance to the next turn, carried by the bubble rather than by the list's
|
|
4802
|
+
`gap`, so it is part of this box: an older message's action bar floats over it
|
|
4803
|
+
(#56). Same token, same distance — nothing moved. */
|
|
4804
|
+
padding-block-end: var(--aparte-message-gap);
|
|
4756
4805
|
}
|
|
4757
4806
|
|
|
4758
4807
|
.aparte-message {
|
|
@@ -4799,6 +4848,9 @@ aparte-chat-bubble {
|
|
|
4799
4848
|
.aparte-body {
|
|
4800
4849
|
flex: 1;
|
|
4801
4850
|
min-width: 0;
|
|
4851
|
+
/* The containing block of a floating footer: the bar starts where the text starts
|
|
4852
|
+
and sits under it, whichever way the avatar column is laid out. */
|
|
4853
|
+
position: relative;
|
|
4802
4854
|
}
|
|
4803
4855
|
|
|
4804
4856
|
/* The message bubble — the surface fills ONLY the content (segments + text).
|
|
@@ -4866,11 +4918,22 @@ aparte-chat-bubble:last-of-type .aparte-message[data-role="assistant"]:not(.apar
|
|
|
4866
4918
|
* Measured (UI audit 2026-08-28, §8.3 #7): 103px between the text of one turn and the
|
|
4867
4919
|
* text of the next, and 34 of them were this footer — 28px of buttons nobody could
|
|
4868
4920
|
* see plus its margin, under EVERY message, so that the bar could appear on hover
|
|
4869
|
-
* without moving anything. The market floats it instead
|
|
4870
|
-
*
|
|
4871
|
-
*
|
|
4872
|
-
*
|
|
4873
|
-
*
|
|
4921
|
+
* without moving anything. The market floats it instead, BELOW the message, in the
|
|
4922
|
+
* space that already separates two turns: that is where ChatGPT and Claude put it,
|
|
4923
|
+
* and it takes no height because the space is already there.
|
|
4924
|
+
*
|
|
4925
|
+
* It floated top-right first (#56), over the header row's empty end, for one reason:
|
|
4926
|
+
* the bubble is a paint-containment boundary (`content-visibility`), and the space
|
|
4927
|
+
* between two bubbles was the list's flex `gap` — outside every box — so a bar
|
|
4928
|
+
* placed under the text was clipped. The gap is the bubble's own padding-block-end
|
|
4929
|
+
* now (see `aparte-chat-bubble` above), inside its box. The bar hangs from the
|
|
4930
|
+
* content column's bottom edge by `message padding-block + gap`: 16 + 12 = 28px at
|
|
4931
|
+
* the default density, 24 + 18 = 42px at the comfortable one, and the bar is 24px on
|
|
4932
|
+
* these messages — it overlaps padding, never text. The distance between turns is
|
|
4933
|
+
* what it was. A narrow container (responsive.css) shrinks the padding to 12 + 8 = 20:
|
|
4934
|
+
* 4px of the bar reach the last line's leading, under glyphs that do not descend that
|
|
4935
|
+
* far; and a narrow container is mostly a coarse pointer, where this block does not
|
|
4936
|
+
* apply.
|
|
4874
4937
|
*
|
|
4875
4938
|
* Three footers stay in the flow. The last assistant message: its bar is always on
|
|
4876
4939
|
* show, under the reply, where every chat puts it. A message whose branch picker is
|
|
@@ -4878,38 +4941,27 @@ aparte-chat-bubble:last-of-type .aparte-message[data-role="assistant"]:not(.apar
|
|
|
4878
4941
|
* picker must stay in view. And every message under a pointer that cannot hover, or
|
|
4879
4942
|
* that is coarse — `(hover: hover) and (pointer: fine)`, because the two features are
|
|
4880
4943
|
* independent and a TV remote reports both hover and coarse; responsive.css gives a
|
|
4881
|
-
* coarse pointer a 44px bar in the flow, and floated
|
|
4882
|
-
*
|
|
4883
|
-
*
|
|
4884
|
-
* The bar's place depends on the header row: 8px from the top, it fills the empty end
|
|
4885
|
-
* of the "Assistant · 12:34" line and clears the text by the header's height. A host
|
|
4886
|
-
* that hides `.aparte-header` moves that line away and should move the bar too
|
|
4887
|
-
* (`.aparte-footer { top: … }`), or keep it in the flow.
|
|
4944
|
+
* coarse pointer a 44px bar in the flow, and floated under the text a 44px bar would
|
|
4945
|
+
* cover the next turn.
|
|
4888
4946
|
*
|
|
4889
4947
|
* Invisible but NOT inert, on purpose. `opacity: 0` keeps the bar hit-testable, so a
|
|
4890
|
-
* drag-select started
|
|
4891
|
-
*
|
|
4892
|
-
*
|
|
4893
|
-
*
|
|
4894
|
-
*
|
|
4948
|
+
* drag-select started under a message begins on a button nobody sees — a review
|
|
4949
|
+
* flagged it, and `pointer-events: none` until `:hover` was tried. It made the bar
|
|
4950
|
+
* unreachable to anything that clicks without hovering first: Playwright (which
|
|
4951
|
+
* hit-tests the point before it moves the mouse — the header "intercepted" the edit
|
|
4952
|
+
* button on four projects), and with it voice control and switch access, which
|
|
4895
4953
|
* synthesise a click the same way. A control only a hover can enable is a control
|
|
4896
|
-
* some users cannot reach; a phantom button
|
|
4954
|
+
* some users cannot reach; a phantom button in the space between two turns is not. */
|
|
4897
4955
|
@media (hover: hover) and (pointer: fine) {
|
|
4898
4956
|
aparte-chat-bubble:not(:last-of-type) .aparte-message:not([data-branches]) .aparte-footer,
|
|
4899
4957
|
aparte-chat-bubble:last-of-type .aparte-message[data-role="user"]:not([data-branches]) .aparte-footer {
|
|
4900
4958
|
position: absolute;
|
|
4901
|
-
|
|
4902
|
-
inset-
|
|
4959
|
+
inset-inline-start: 0;
|
|
4960
|
+
inset-block-end: calc(-1 * (var(--aparte-message-padding-block) + var(--aparte-message-gap)));
|
|
4903
4961
|
margin: 0;
|
|
4904
4962
|
z-index: 1;
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
aparte-chat-bubble:not(:last-of-type) .aparte-message:not([data-branches]) .aparte-action-bar,
|
|
4908
|
-
aparte-chat-bubble:last-of-type .aparte-message[data-role="user"]:not([data-branches]) .aparte-action-bar {
|
|
4909
|
-
background: var(--aparte-surface-1);
|
|
4910
|
-
border: var(--aparte-border-width) solid var(--aparte-border);
|
|
4911
|
-
border-radius: var(--aparte-radius-md);
|
|
4912
|
-
box-shadow: var(--aparte-popover-shadow);
|
|
4963
|
+
/* Smaller than the last reply's 28px: this one lives in the padding. */
|
|
4964
|
+
--aparte-action-bar-btn-size: 24px;
|
|
4913
4965
|
}
|
|
4914
4966
|
}
|
|
4915
4967
|
|
|
@@ -5449,11 +5501,18 @@ aparte-composer-input .aparte-ci-editor {
|
|
|
5449
5501
|
caret-color: var(--aparte-text);
|
|
5450
5502
|
}
|
|
5451
5503
|
|
|
5452
|
-
/* Placeholder via CSS
|
|
5504
|
+
/* Placeholder via CSS. It never wraps: a `::before` counts in `scrollHeight`, and the
|
|
5505
|
+
auto-grow measured it once in a box that had no width yet — "Type a message…" folded
|
|
5506
|
+
over a dozen lines and the editor came up ~300 px tall while empty (#55). A
|
|
5507
|
+
placeholder longer than the box is clipped, which is what every native input does. */
|
|
5453
5508
|
aparte-composer-input .aparte-ci-editor:empty::before {
|
|
5454
5509
|
content: attr(data-placeholder);
|
|
5455
5510
|
color: var(--aparte-input-placeholder);
|
|
5456
5511
|
pointer-events: none;
|
|
5512
|
+
white-space: nowrap;
|
|
5513
|
+
overflow: hidden;
|
|
5514
|
+
text-overflow: ellipsis;
|
|
5515
|
+
display: block;
|
|
5457
5516
|
}
|
|
5458
5517
|
|
|
5459
5518
|
aparte-composer-input .aparte-ci-editor[aria-disabled="true"] {
|
|
@@ -7262,6 +7321,7 @@ aparte-split[orientation='vertical'] .aparte-split__scrim,
|
|
|
7262
7321
|
Not "position: 100% and a zero-size handle": that leaves a focusable separator of
|
|
7263
7322
|
no width sitting in the tab order. */
|
|
7264
7323
|
aparte-split[data-stacked],
|
|
7324
|
+
aparte-split[single],
|
|
7265
7325
|
.aparte-split--only-start,
|
|
7266
7326
|
.aparte-split--only-end {
|
|
7267
7327
|
grid-template-columns: minmax(0, 1fr);
|
|
@@ -7269,17 +7329,23 @@ aparte-split[data-stacked],
|
|
|
7269
7329
|
}
|
|
7270
7330
|
|
|
7271
7331
|
aparte-split[data-stacked] > .aparte-split__handle,
|
|
7332
|
+
aparte-split[single] > .aparte-split__handle,
|
|
7272
7333
|
.aparte-split--only-start > .aparte-split__handle,
|
|
7273
7334
|
.aparte-split--only-end > .aparte-split__handle {
|
|
7274
7335
|
display: none;
|
|
7275
7336
|
}
|
|
7276
7337
|
|
|
7338
|
+
/* `single` is the host's word for the same state (#54): one pane, whatever the width,
|
|
7339
|
+
the one `pane` names. Same rules as the breakpoint's, so the element reads both the
|
|
7340
|
+
same way. */
|
|
7277
7341
|
aparte-split[data-stacked]:not([pane='end']) > :nth-child(3),
|
|
7342
|
+
aparte-split[single]:not([pane='end']) > :nth-child(3),
|
|
7278
7343
|
.aparte-split--only-start > :nth-child(3) {
|
|
7279
7344
|
display: none;
|
|
7280
7345
|
}
|
|
7281
7346
|
|
|
7282
7347
|
aparte-split[data-stacked][pane='end'] > :nth-child(1),
|
|
7348
|
+
aparte-split[single][pane='end'] > :nth-child(1),
|
|
7283
7349
|
.aparte-split--only-end > :nth-child(1) {
|
|
7284
7350
|
display: none;
|
|
7285
7351
|
}
|
|
@@ -7578,7 +7644,8 @@ aparte-split[disabled] > .aparte-split__handle:hover {
|
|
|
7578
7644
|
without container-query support keep the wide defaults. */
|
|
7579
7645
|
@container (max-width: 520px) {
|
|
7580
7646
|
.aparte-message {
|
|
7581
|
-
--aparte-message-padding: var(--aparte-space-6)
|
|
7647
|
+
--aparte-message-padding-block: var(--aparte-space-6);
|
|
7648
|
+
--aparte-message-padding-inline: var(--aparte-space-4);
|
|
7582
7649
|
--aparte-message-gap: var(--aparte-space-4);
|
|
7583
7650
|
}
|
|
7584
7651
|
|
package/dist/index.js
CHANGED
|
@@ -2311,6 +2311,24 @@ class AparteChatViewport extends HTMLElement {
|
|
|
2311
2311
|
/** How long after a scroll of ours we keep re-anchoring while the layout churns.
|
|
2312
2312
|
* Not `readonly`: a test shortens it to run past the window's end in a few frames. */
|
|
2313
2313
|
_settleWindowMs = 400;
|
|
2314
|
+
/**
|
|
2315
|
+
* Until when a smooth scroll of ours is in flight (#57). A user send glides to the
|
|
2316
|
+
* bottom with `scrollTo({ behavior: 'smooth' })`; the assistant placeholder and the
|
|
2317
|
+
* first tokens used to land INSIDE that glide through the streaming path — an instant
|
|
2318
|
+
* `scrollTop = scrollHeight` plus the settle chain — and an instant write cancels a
|
|
2319
|
+
* running smooth scroll in every engine. Measured before the fix: five instant writes
|
|
2320
|
+
* in the send's own frame (the spacer recalculation scrolls synchronously, the
|
|
2321
|
+
* mutation observer queues another), so there never was a glide to cut — the view
|
|
2322
|
+
* teleported. While this deadline is ahead, every bottom-pin RE-TARGETS the glide
|
|
2323
|
+
* (a second smooth `scrollTo` is continuous) instead of writing `scrollTop`; the
|
|
2324
|
+
* browser's `scrollend` closes it early where supported. Streaming is instant again
|
|
2325
|
+
* after that, as it must be to keep up with token bursts.
|
|
2326
|
+
*/
|
|
2327
|
+
_glideUntil = 0;
|
|
2328
|
+
/** The glide's budget when `scrollend` is not there to close it: Chromium's smooth scroll over a viewport takes ~300–500 ms. */
|
|
2329
|
+
_glideWindowMs = 450;
|
|
2330
|
+
/** Armed with each glide: when the window closes, a view still short of the bottom is pinned. */
|
|
2331
|
+
_glideSettleTimer = null;
|
|
2314
2332
|
/** Deadline of the settle in flight (0 = none). Pushed forward, never stacked. */
|
|
2315
2333
|
_settleUntil = 0;
|
|
2316
2334
|
_settleRafId = null;
|
|
@@ -2347,6 +2365,7 @@ class AparteChatViewport extends HTMLElement {
|
|
|
2347
2365
|
constructor() {
|
|
2348
2366
|
super();
|
|
2349
2367
|
this._handleScroll = this._handleScroll.bind(this);
|
|
2368
|
+
this._handleScrollEnd = this._handleScrollEnd.bind(this);
|
|
2350
2369
|
}
|
|
2351
2370
|
connectedCallback() {
|
|
2352
2371
|
if (this.hasAttribute("framework-managed")) this._frameworkManagedDOM = true;
|
|
@@ -2727,9 +2746,12 @@ class AparteChatViewport extends HTMLElement {
|
|
|
2727
2746
|
}
|
|
2728
2747
|
this._pruneRenderedBubbles();
|
|
2729
2748
|
this._syncBusy();
|
|
2730
|
-
this._recalculateSpacer();
|
|
2731
2749
|
if (message.role === "user") {
|
|
2732
2750
|
this._isAutoScrollEnabled = true;
|
|
2751
|
+
this._smoothScrollToBottom();
|
|
2752
|
+
}
|
|
2753
|
+
this._recalculateSpacer();
|
|
2754
|
+
if (message.role === "user") {
|
|
2733
2755
|
requestAnimationFrame(() => {
|
|
2734
2756
|
if (this._isAutoScrollEnabled) this._smoothScrollToBottom();
|
|
2735
2757
|
});
|
|
@@ -3081,16 +3103,9 @@ class AparteChatViewport extends HTMLElement {
|
|
|
3081
3103
|
}
|
|
3082
3104
|
_autoScroll() {
|
|
3083
3105
|
if (this._isAutoScrollEnabled) {
|
|
3084
|
-
|
|
3085
|
-
this.
|
|
3086
|
-
|
|
3087
|
-
if (this._isAutoScrollEnabled) this._smoothScrollToBottom();
|
|
3088
|
-
});
|
|
3089
|
-
} else {
|
|
3090
|
-
requestAnimationFrame(() => {
|
|
3091
|
-
if (this._isAutoScrollEnabled) this._scrollToBottom();
|
|
3092
|
-
});
|
|
3093
|
-
}
|
|
3106
|
+
requestAnimationFrame(() => {
|
|
3107
|
+
if (this._isAutoScrollEnabled) this._scrollToBottom();
|
|
3108
|
+
});
|
|
3094
3109
|
}
|
|
3095
3110
|
this._pruneRenderedBubbles();
|
|
3096
3111
|
}
|
|
@@ -3234,6 +3249,14 @@ class AparteChatViewport extends HTMLElement {
|
|
|
3234
3249
|
if (!inGutter) return;
|
|
3235
3250
|
}
|
|
3236
3251
|
this._readerInputAt = performance.now();
|
|
3252
|
+
if (this._gliding() && this._container) {
|
|
3253
|
+
this._glideUntil = 0;
|
|
3254
|
+
if (e.type === "wheel" || e.type === "touchmove") {
|
|
3255
|
+
this._ownScrollAt = performance.now();
|
|
3256
|
+
const here = this._container.scrollTop;
|
|
3257
|
+
this._container.scrollTop = here;
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3237
3260
|
};
|
|
3238
3261
|
_onBranchNavigate = (e) => {
|
|
3239
3262
|
const evt = e;
|
|
@@ -3242,6 +3265,7 @@ class AparteChatViewport extends HTMLElement {
|
|
|
3242
3265
|
};
|
|
3243
3266
|
_setupEventListeners() {
|
|
3244
3267
|
this._container?.addEventListener("scroll", this._handleScroll, { passive: true });
|
|
3268
|
+
this._container?.addEventListener("scrollend", this._handleScrollEnd, { passive: true });
|
|
3245
3269
|
for (const type of ["wheel", "touchmove", "pointerdown", "keydown"]) {
|
|
3246
3270
|
this._container?.addEventListener(type, this._noteReaderInput, { passive: true });
|
|
3247
3271
|
}
|
|
@@ -3275,8 +3299,16 @@ class AparteChatViewport extends HTMLElement {
|
|
|
3275
3299
|
this._overlayObserver.observe(this._overlayRoot, { childList: true });
|
|
3276
3300
|
this._updateOverlayInset();
|
|
3277
3301
|
}
|
|
3278
|
-
this._mutationObserver = new MutationObserver(() => {
|
|
3302
|
+
this._mutationObserver = new MutationObserver((mutations) => {
|
|
3279
3303
|
if (this._frameworkManagedDOM) this._keepScrollButtonLast();
|
|
3304
|
+
if (this._isAutoScrollEnabled && !this._gliding()) {
|
|
3305
|
+
const added = mutations.flatMap((m2) => Array.from(m2.addedNodes)).filter((n2) => n2 instanceof Element && n2.tagName === "APARTE-CHAT-BUBBLE");
|
|
3306
|
+
const only = added.length === 1 ? added[0] : void 0;
|
|
3307
|
+
if (only && only.getAttribute("data-role") === "user" && only.parentElement) {
|
|
3308
|
+
const bubbles = only.parentElement.querySelectorAll("aparte-chat-bubble");
|
|
3309
|
+
if (bubbles[bubbles.length - 1] === only) this._smoothScrollOnce = true;
|
|
3310
|
+
}
|
|
3311
|
+
}
|
|
3280
3312
|
if (this._isAutoScrollEnabled) {
|
|
3281
3313
|
requestAnimationFrame(() => {
|
|
3282
3314
|
if (this._isAutoScrollEnabled) this._scrollToBottom();
|
|
@@ -3352,10 +3384,41 @@ class AparteChatViewport extends HTMLElement {
|
|
|
3352
3384
|
}
|
|
3353
3385
|
_scrollToBottom() {
|
|
3354
3386
|
if (!this._container) return;
|
|
3387
|
+
if (this._smoothScrollOnce) {
|
|
3388
|
+
this._smoothScrollOnce = false;
|
|
3389
|
+
this._smoothScrollToBottom();
|
|
3390
|
+
return;
|
|
3391
|
+
}
|
|
3392
|
+
if (this._gliding()) {
|
|
3393
|
+
this._retargetGlide();
|
|
3394
|
+
return;
|
|
3395
|
+
}
|
|
3355
3396
|
this._ownScrollAt = performance.now();
|
|
3356
3397
|
this._container.scrollTop = this._container.scrollHeight;
|
|
3357
3398
|
this._settleAtBottom();
|
|
3358
3399
|
}
|
|
3400
|
+
_gliding() {
|
|
3401
|
+
return performance.now() < this._glideUntil;
|
|
3402
|
+
}
|
|
3403
|
+
/** A second smooth `scrollTo` is continuous where an instant write is a cut. */
|
|
3404
|
+
_retargetGlide() {
|
|
3405
|
+
if (!this._container) return;
|
|
3406
|
+
this._ownScrollAt = performance.now();
|
|
3407
|
+
this._container.scrollTo({ top: this._container.scrollHeight, behavior: "smooth" });
|
|
3408
|
+
}
|
|
3409
|
+
/**
|
|
3410
|
+
* The browser says a scroll came to rest — the glide is over ONLY if it rested at the
|
|
3411
|
+
* bottom. WebKit fires `scrollend` when a smooth scroll is REPLACED by another (our own
|
|
3412
|
+
* re-target), 45–60 ms into the glide and hundreds of pixels short; taken at its word,
|
|
3413
|
+
* that closed the window and the next pin was the cut this guard exists to prevent
|
|
3414
|
+
* (react-webkit and vanilla-webkit, 2 of 2). Short of the bottom, the budget keeps
|
|
3415
|
+
* bounding the window.
|
|
3416
|
+
*/
|
|
3417
|
+
_handleScrollEnd() {
|
|
3418
|
+
if (!this._container) return;
|
|
3419
|
+
const max = this._container.scrollHeight - this._container.clientHeight;
|
|
3420
|
+
if (max - this._container.scrollTop <= 1) this._glideUntil = 0;
|
|
3421
|
+
}
|
|
3359
3422
|
/**
|
|
3360
3423
|
* Confirm over the next few frames that we actually reached the bottom.
|
|
3361
3424
|
*
|
|
@@ -3401,7 +3464,7 @@ class AparteChatViewport extends HTMLElement {
|
|
|
3401
3464
|
return;
|
|
3402
3465
|
}
|
|
3403
3466
|
const max = this._container.scrollHeight - this._container.clientHeight;
|
|
3404
|
-
if (max - this._container.scrollTop > 1) {
|
|
3467
|
+
if (max - this._container.scrollTop > 1 && !this._gliding()) {
|
|
3405
3468
|
this._ownScrollAt = performance.now();
|
|
3406
3469
|
this._container.scrollTop = max;
|
|
3407
3470
|
}
|
|
@@ -3414,7 +3477,15 @@ class AparteChatViewport extends HTMLElement {
|
|
|
3414
3477
|
if (!this._container) return;
|
|
3415
3478
|
this._ownScrollAt = performance.now();
|
|
3416
3479
|
if (typeof this._container.scrollTo === "function" && !this._prefersReducedMotion()) {
|
|
3480
|
+
this._glideUntil = performance.now() + this._glideWindowMs;
|
|
3417
3481
|
this._container.scrollTo({ top: this._container.scrollHeight, behavior: "smooth" });
|
|
3482
|
+
if (this._glideSettleTimer !== null) clearTimeout(this._glideSettleTimer);
|
|
3483
|
+
this._glideSettleTimer = setTimeout(() => {
|
|
3484
|
+
this._glideSettleTimer = null;
|
|
3485
|
+
if (!this._container || !this._isAutoScrollEnabled || this._gliding()) return;
|
|
3486
|
+
const max = this._container.scrollHeight - this._container.clientHeight;
|
|
3487
|
+
if (max - this._container.scrollTop > 1) this._scrollToBottom();
|
|
3488
|
+
}, this._glideWindowMs + 16);
|
|
3418
3489
|
} else {
|
|
3419
3490
|
this._container.scrollTop = this._container.scrollHeight;
|
|
3420
3491
|
}
|
|
@@ -3530,6 +3601,11 @@ class AparteChatViewport extends HTMLElement {
|
|
|
3530
3601
|
}
|
|
3531
3602
|
_cleanup() {
|
|
3532
3603
|
this._container?.removeEventListener("scroll", this._handleScroll);
|
|
3604
|
+
this._container?.removeEventListener("scrollend", this._handleScrollEnd);
|
|
3605
|
+
if (this._glideSettleTimer !== null) {
|
|
3606
|
+
clearTimeout(this._glideSettleTimer);
|
|
3607
|
+
this._glideSettleTimer = null;
|
|
3608
|
+
}
|
|
3533
3609
|
for (const type of ["wheel", "touchmove", "pointerdown", "keydown"]) {
|
|
3534
3610
|
this._container?.removeEventListener(type, this._noteReaderInput);
|
|
3535
3611
|
}
|
|
@@ -4041,6 +4117,14 @@ class AparteComposerInput extends HTMLElement {
|
|
|
4041
4117
|
_editor = null;
|
|
4042
4118
|
_maxHeight = 200;
|
|
4043
4119
|
_minHeight = 44;
|
|
4120
|
+
/**
|
|
4121
|
+
* Re-measures the editor when its WIDTH changes (#55). The three fixed instants
|
|
4122
|
+
* (connect, next frame, fonts.ready) all miss the same case: a box not yet laid
|
|
4123
|
+
* out — the placeholder wraps in a 0 px column, `scrollHeight` reads ~300 px, and
|
|
4124
|
+
* that became the inline height until the first keystroke. Width is the variable
|
|
4125
|
+
* none of them watched.
|
|
4126
|
+
*/
|
|
4127
|
+
_resizeObserver = null;
|
|
4044
4128
|
_unsubscribes = [];
|
|
4045
4129
|
// Bound handlers
|
|
4046
4130
|
_onInput = this._handleInput.bind(this);
|
|
@@ -4061,6 +4145,10 @@ class AparteComposerInput extends HTMLElement {
|
|
|
4061
4145
|
this._editor?.addEventListener("paste", this._onPaste);
|
|
4062
4146
|
this._connectToRoot();
|
|
4063
4147
|
this._scheduleInitialReflow();
|
|
4148
|
+
if (this._editor && typeof ResizeObserver === "function") {
|
|
4149
|
+
this._resizeObserver = new ResizeObserver(() => this._adjustHeight());
|
|
4150
|
+
this._resizeObserver.observe(this._editor);
|
|
4151
|
+
}
|
|
4064
4152
|
this._unsubscribes.push(subscribeConfigChange(this, () => this._updatePlaceholder()));
|
|
4065
4153
|
}
|
|
4066
4154
|
disconnectedCallback() {
|
|
@@ -4069,6 +4157,8 @@ class AparteComposerInput extends HTMLElement {
|
|
|
4069
4157
|
this._editor?.removeEventListener("focus", this._onFocus);
|
|
4070
4158
|
this._editor?.removeEventListener("blur", this._onBlur);
|
|
4071
4159
|
this._editor?.removeEventListener("paste", this._onPaste);
|
|
4160
|
+
this._resizeObserver?.disconnect();
|
|
4161
|
+
this._resizeObserver = null;
|
|
4072
4162
|
this._unsubscribes.forEach((fn) => fn());
|
|
4073
4163
|
this._unsubscribes = [];
|
|
4074
4164
|
}
|
|
@@ -6133,7 +6223,7 @@ function toPercent(raw, fallback) {
|
|
|
6133
6223
|
}
|
|
6134
6224
|
class AparteSplit extends HTMLElement {
|
|
6135
6225
|
static get observedAttributes() {
|
|
6136
|
-
return ["position", "orientation", "primary", "collapsed", "breakpoint", "pane", "disabled", "label"];
|
|
6226
|
+
return ["position", "orientation", "primary", "collapsed", "breakpoint", "pane", "disabled", "label", "single"];
|
|
6137
6227
|
}
|
|
6138
6228
|
_handle = null;
|
|
6139
6229
|
_scrim = null;
|
|
@@ -6244,7 +6334,14 @@ class AparteSplit extends HTMLElement {
|
|
|
6244
6334
|
* alone would measure a one-track grid and commit `position="100"`.
|
|
6245
6335
|
*/
|
|
6246
6336
|
get stacked() {
|
|
6247
|
-
return this.hasAttribute("data-stacked") || this.classList.contains("aparte-split--only-start") || this.classList.contains("aparte-split--only-end");
|
|
6337
|
+
return this.hasAttribute("data-stacked") || this.hasAttribute("single") || this.classList.contains("aparte-split--only-start") || this.classList.contains("aparte-split--only-end");
|
|
6338
|
+
}
|
|
6339
|
+
/** One pane on demand, whatever the width (#54). Reflected. */
|
|
6340
|
+
get single() {
|
|
6341
|
+
return this.hasAttribute("single");
|
|
6342
|
+
}
|
|
6343
|
+
set single(value) {
|
|
6344
|
+
this.toggleAttribute("single", value);
|
|
6248
6345
|
}
|
|
6249
6346
|
// ─── Public API ───────────────────────────────────────────────────────
|
|
6250
6347
|
/** Fold the primary pane to its minimum, remembering the size it had. */
|
|
@@ -6375,6 +6472,10 @@ class AparteSplit extends HTMLElement {
|
|
|
6375
6472
|
if (this.disabled && this._dragging) this._endDrag("pointer", this._dragStartPercent);
|
|
6376
6473
|
this._stampHandle();
|
|
6377
6474
|
return;
|
|
6475
|
+
case "single":
|
|
6476
|
+
if (this.single && this._dragging) this._endDrag("pointer", this._dragStartPercent);
|
|
6477
|
+
this._stampHandle();
|
|
6478
|
+
return;
|
|
6378
6479
|
case "breakpoint":
|
|
6379
6480
|
this._watchBreakpoint();
|
|
6380
6481
|
return;
|