@rcarls/rc-app-bar 0.4.2 → 0.6.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 +37 -0
- package/README.md +46 -21
- package/dist/custom-elements.json +32 -2
- package/dist/{rc-app-bar-C9IC9WXj.js → rc-app-bar-C728WmdN.js} +83 -44
- package/dist/rc-app-bar-C728WmdN.js.map +1 -0
- package/dist/rc-app-bar-define.js +1 -1
- package/dist/rc-app-bar.js +1 -1
- package/dist/types/packages/rc-app-bar/src/index.d.ts +1 -1
- package/dist/types/packages/rc-app-bar/src/rc-app-bar.d.ts +20 -1
- package/package.json +3 -3
- package/dist/rc-app-bar-C9IC9WXj.js.map +0 -1
- package/dist/types/packages/rc-app-bar/src/rc-app-bar.test.d.ts +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# @rcarls/rc-app-bar
|
|
2
2
|
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- b6f52a2: Change the default `slot="center"` layout: it now fills the flexible space
|
|
8
|
+
between leading and trailing, capped by the new
|
|
9
|
+
`--rc-app-bar-center-max-inline-size` before it centers within available
|
|
10
|
+
space instead of continuing to stretch, rather than always mirroring the
|
|
11
|
+
leading/trailing edges to stay exactly viewport-centered. Add the new
|
|
12
|
+
`center-symmetric` attribute to keep the previous behavior (exact
|
|
13
|
+
viewport-centering regardless of asymmetric leading/trailing widths).
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- b6f52a2: Defer app-bar layout measurements to animation frames, group geometry reads
|
|
18
|
+
before style writes, and remeasure when symmetric centering changes live.
|
|
19
|
+
- Updated dependencies [6683eb9]
|
|
20
|
+
- Updated dependencies [ee7ba6c]
|
|
21
|
+
- Updated dependencies [30eb232]
|
|
22
|
+
- @rcarls/rc-common@0.6.0
|
|
23
|
+
|
|
24
|
+
## 0.5.0
|
|
25
|
+
|
|
26
|
+
### Minor Changes
|
|
27
|
+
|
|
28
|
+
- d440edc: Add `--rc-app-bar-title-start-padding`, applied only when the leading slot is
|
|
29
|
+
empty. Per the M3 Top App Bar spec, a headline with no navigation icon should
|
|
30
|
+
align with the start margin of the content below the bar, not the bar's own
|
|
31
|
+
edge padding (which is calibrated for the leading icon button's touch
|
|
32
|
+
target). Defaults to `0px` (no behavior change for existing consumers).
|
|
33
|
+
|
|
34
|
+
### Patch Changes
|
|
35
|
+
|
|
36
|
+
- Updated dependencies [4ae2ef0]
|
|
37
|
+
- Updated dependencies [689340c]
|
|
38
|
+
- @rcarls/rc-common@0.5.0
|
|
39
|
+
|
|
3
40
|
## 0.4.2
|
|
4
41
|
|
|
5
42
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# `@rcarls/rc-app-bar`
|
|
2
2
|
|
|
3
|
-
App bar modeled after the
|
|
3
|
+
App bar modeled after the
|
|
4
|
+
[Material 3 Top app bar](https://m3.material.io/components/top-app-bar/overview),
|
|
5
|
+
with leading, title, center, trailing regions and optional scroll behavior.
|
|
4
6
|
|
|
5
7
|
Docs: [https://richardcarls.github.io/rc-webcomponents/components/rc-app-bar](https://richardcarls.github.io/rc-webcomponents/components/rc-app-bar).
|
|
6
8
|
|
|
@@ -41,11 +43,7 @@ duplicated while the bar changes layout.
|
|
|
41
43
|
comes from the title content rather than a Material-specific fixed size.
|
|
42
44
|
|
|
43
45
|
```html
|
|
44
|
-
<rc-app-bar
|
|
45
|
-
variant="expanded"
|
|
46
|
-
scroll-behavior="collapse"
|
|
47
|
-
scroll-target="#content"
|
|
48
|
-
>
|
|
46
|
+
<rc-app-bar variant="expanded" scroll-behavior="collapse" scroll-target="#content">
|
|
49
47
|
<button slot="leading" aria-label="Back">←</button>
|
|
50
48
|
<div>
|
|
51
49
|
<strong>Slow-Roasted Tomato Pasta</strong>
|
|
@@ -65,14 +63,14 @@ Scroll behaviors are exclusive:
|
|
|
65
63
|
|
|
66
64
|
The component never consumes, stops, or rewrites the document's scroll.
|
|
67
65
|
|
|
68
|
-
##
|
|
66
|
+
## Center-slot composition
|
|
69
67
|
|
|
70
|
-
The optional `center` slot
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
The optional `center` slot, useful for desktop controls or an
|
|
69
|
+
[`rc-search-bar`](../rc-search-bar/), fills the flexible space between leading
|
|
70
|
+
and trailing by default:
|
|
73
71
|
|
|
74
72
|
```html
|
|
75
|
-
<rc-app-bar>
|
|
73
|
+
<rc-app-bar style="--rc-app-bar-center-max-inline-size: 32rem;">
|
|
76
74
|
<button slot="leading">Back</button>
|
|
77
75
|
<span>Recipes</span>
|
|
78
76
|
<rc-search-bar slot="center" placeholder="Search recipes">
|
|
@@ -82,6 +80,28 @@ desktop controls or an [`rc-search-bar`](../rc-search-bar/):
|
|
|
82
80
|
</rc-app-bar>
|
|
83
81
|
```
|
|
84
82
|
|
|
83
|
+
Uncapped, it stretches edge-to-edge like any other content in that space. Set
|
|
84
|
+
`--rc-app-bar-center-max-inline-size` and it centers within the available
|
|
85
|
+
space once it hits that width instead of continuing to stretch (centered
|
|
86
|
+
between wherever leading ends and trailing begins, not on the bar's own
|
|
87
|
+
viewport midpoint).
|
|
88
|
+
|
|
89
|
+
For a control that must sit at the bar's exact geometric midpoint regardless
|
|
90
|
+
of asymmetric leading/trailing widths, add `center-symmetric`:
|
|
91
|
+
|
|
92
|
+
```html
|
|
93
|
+
<rc-app-bar center-symmetric>
|
|
94
|
+
<button slot="leading">Long leading label</button>
|
|
95
|
+
<span>Recipes</span>
|
|
96
|
+
<rc-search-bar slot="center">...</rc-search-bar>
|
|
97
|
+
<button slot="trailing" aria-label="Account">Account</button>
|
|
98
|
+
</rc-app-bar>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
This mirrors the leading/trailing edge widths so the center slot stays
|
|
102
|
+
viewport-centered even when the two sides differ, at the cost of extra reserved
|
|
103
|
+
space on whichever side is narrower.
|
|
104
|
+
|
|
85
105
|
Title and center content may coexist. The title is constrained before it can
|
|
86
106
|
overlap the centered content. Without center content, the title uses all space
|
|
87
107
|
between leading and trailing controls; consumers may apply
|
|
@@ -186,16 +206,21 @@ rc-app-bar.glass::part(root) {
|
|
|
186
206
|
|
|
187
207
|
### CSS custom properties
|
|
188
208
|
|
|
189
|
-
| Property
|
|
190
|
-
|
|
|
191
|
-
| `--rc-app-bar-bg`
|
|
192
|
-
| `--rc-app-bar-color`
|
|
193
|
-
| `--rc-app-bar-compact-min-height`
|
|
194
|
-
| `--rc-app-bar-expanded-padding-block`
|
|
195
|
-
| `--rc-app-bar-padding-inline`
|
|
196
|
-
| `--rc-app-bar-gap`
|
|
197
|
-
| `--rc-app-bar-
|
|
198
|
-
| `--rc-app-bar-
|
|
209
|
+
| Property | Default | Description |
|
|
210
|
+
| --------------------------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
211
|
+
| `--rc-app-bar-bg` | `Canvas` | Bar background |
|
|
212
|
+
| `--rc-app-bar-color` | `CanvasText` | Bar text color |
|
|
213
|
+
| `--rc-app-bar-compact-min-height` | `3rem` | Compact row minimum height |
|
|
214
|
+
| `--rc-app-bar-expanded-padding-block` | `0.75em` | Expanded title block padding |
|
|
215
|
+
| `--rc-app-bar-padding-inline` | `0.75em` | Horizontal padding |
|
|
216
|
+
| `--rc-app-bar-gap` | `0.5em` | Gap between regions |
|
|
217
|
+
| `--rc-app-bar-center-max-inline-size` | `100%` | Max width of `slot="center"` content before it centers within the available space instead of filling it. No effect when `center-symmetric` is set. |
|
|
218
|
+
| `--rc-app-bar-title-start-padding` | `0px` | Extra title inline-start padding when the leading slot is empty |
|
|
219
|
+
| `--rc-app-bar-transition-duration` | `200ms` | Endpoint and hide transition duration |
|
|
220
|
+
| `--rc-app-bar-scroll-divider` | `1px solid GrayText` | Scrolled separator border |
|
|
221
|
+
| `--rc-app-bar-collapse-progress` | `0` | Read-only collapse animation progress from 0 through 1 |
|
|
222
|
+
| `--rc-app-bar-title-font-size` | unset | Optional compact-row title font size; inherits when unset |
|
|
223
|
+
| `--rc-app-bar-expanded-title-font-size` | unset | Optional expanded-row title font size; inherits when unset |
|
|
199
224
|
|
|
200
225
|
### CSS parts
|
|
201
226
|
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"name": "*",
|
|
36
36
|
"declaration": {
|
|
37
37
|
"name": "*",
|
|
38
|
-
"module": "src/rc-app-bar"
|
|
38
|
+
"module": "src/rc-app-bar.js"
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
]
|
|
@@ -79,6 +79,16 @@
|
|
|
79
79
|
"name": "--rc-app-bar-gap",
|
|
80
80
|
"default": "0.5em"
|
|
81
81
|
},
|
|
82
|
+
{
|
|
83
|
+
"description": "Max width of `slot=\"center\"` content before it centers within the available space instead of filling it. No effect when `center-symmetric` is set.",
|
|
84
|
+
"name": "--rc-app-bar-center-max-inline-size",
|
|
85
|
+
"default": "100%"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"description": "Extra title inline-start padding used only when the leading slot is empty (M3: align with content below when there's no navigation icon)",
|
|
89
|
+
"name": "--rc-app-bar-title-start-padding",
|
|
90
|
+
"default": "0px"
|
|
91
|
+
},
|
|
82
92
|
{
|
|
83
93
|
"description": "Endpoint and hide duration",
|
|
84
94
|
"name": "--rc-app-bar-transition-duration",
|
|
@@ -139,7 +149,7 @@
|
|
|
139
149
|
"name": ""
|
|
140
150
|
},
|
|
141
151
|
{
|
|
142
|
-
"description": "Content kept
|
|
152
|
+
"description": "Content such as search, kept within the flexible middle column between leading and trailing. Fills that column by default, capped and self-centered within it via `--rc-app-bar-center-max-inline-size`; add `center-symmetric` for exact viewport centering regardless of asymmetric leading/trailing content instead.",
|
|
143
153
|
"name": "center"
|
|
144
154
|
},
|
|
145
155
|
{
|
|
@@ -159,6 +169,17 @@
|
|
|
159
169
|
"attribute": "variant",
|
|
160
170
|
"reflects": true
|
|
161
171
|
},
|
|
172
|
+
{
|
|
173
|
+
"kind": "field",
|
|
174
|
+
"name": "centerSymmetric",
|
|
175
|
+
"type": {
|
|
176
|
+
"text": "boolean"
|
|
177
|
+
},
|
|
178
|
+
"default": "false",
|
|
179
|
+
"description": "Opt-in: mirrors the leading/trailing edge widths so `slot=\"center\"`\ncontent stays exactly viewport-centered regardless of asymmetric side\ncontent. Default (absent): center content fills the flexible middle\ncolumn like a plain title, capped and self-centered within it via\n`--rc-app-bar-center-max-inline-size` -- centered within the available\nspace between leading and trailing, not mirrored to the viewport.",
|
|
180
|
+
"attribute": "center-symmetric",
|
|
181
|
+
"reflects": true
|
|
182
|
+
},
|
|
162
183
|
{
|
|
163
184
|
"kind": "field",
|
|
164
185
|
"name": "scrollBehavior",
|
|
@@ -600,6 +621,15 @@
|
|
|
600
621
|
},
|
|
601
622
|
"default": "4",
|
|
602
623
|
"fieldName": "scrollThreshold"
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
"description": "Opt-in: mirrors the leading/trailing edge widths so `slot=\"center\"`\ncontent stays exactly viewport-centered regardless of asymmetric side\ncontent. Default (absent): center content fills the flexible middle\ncolumn like a plain title, capped and self-centered within it via\n`--rc-app-bar-center-max-inline-size` -- centered within the available\nspace between leading and trailing, not mirrored to the viewport.",
|
|
627
|
+
"name": "center-symmetric",
|
|
628
|
+
"type": {
|
|
629
|
+
"text": "boolean"
|
|
630
|
+
},
|
|
631
|
+
"default": "false",
|
|
632
|
+
"fieldName": "centerSymmetric"
|
|
603
633
|
}
|
|
604
634
|
],
|
|
605
635
|
"superclass": {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { css as
|
|
1
|
+
import { css as b, LitElement as v, nothing as x, html as w } from "lit";
|
|
2
2
|
import { property as n, state as c } from "lit/decorators.js";
|
|
3
|
-
import { classMap as
|
|
4
|
-
import { RafScheduler as
|
|
5
|
-
const
|
|
3
|
+
import { classMap as h } from "lit/directives/class-map.js";
|
|
4
|
+
import { RafScheduler as S, ScrollObserverController as C } from "@rcarls/rc-common";
|
|
5
|
+
const z = b`
|
|
6
6
|
:host {
|
|
7
7
|
display: block;
|
|
8
8
|
container-type: inline-size;
|
|
@@ -34,7 +34,15 @@ const w = f`
|
|
|
34
34
|
color: inherit;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
/*
|
|
38
|
+
* Opt-in: mirrors the leading/trailing edges (measured in JS — see
|
|
39
|
+
* _measureLayout) so center content stays exactly viewport-centered
|
|
40
|
+
* regardless of asymmetric side content. The default (this attribute
|
|
41
|
+
* absent) instead falls through to the plain 3-column grid above, same as
|
|
42
|
+
* a bare title — #center just fills the flexible middle column, capped
|
|
43
|
+
* and self-centered within it via --rc-app-bar-center-max-inline-size.
|
|
44
|
+
*/
|
|
45
|
+
:host([center-symmetric]) #root[data-has-center] {
|
|
38
46
|
grid-template-columns:
|
|
39
47
|
var(--_rc-app-bar-edge-size)
|
|
40
48
|
minmax(0, 1fr)
|
|
@@ -63,6 +71,15 @@ const w = f`
|
|
|
63
71
|
overflow: clip;
|
|
64
72
|
}
|
|
65
73
|
|
|
74
|
+
/* M3: without a navigation icon, the headline aligns with the start
|
|
75
|
+
* margin of the content below the bar, not the bar's own edge padding
|
|
76
|
+
* (which is calibrated for the icon button's touch target, not bare
|
|
77
|
+
* text). Only applies when the leading slot is genuinely empty — the
|
|
78
|
+
* adjacent #leading.empty marker already exists for the .empty class. */
|
|
79
|
+
#leading.empty + #title {
|
|
80
|
+
padding-inline-start: var(--rc-app-bar-title-start-padding, 0px);
|
|
81
|
+
}
|
|
82
|
+
|
|
66
83
|
/* Compact-row title: all non-expanded states and the collapsed endpoint. */
|
|
67
84
|
:host(:not([variant='expanded'])) #title ::slotted(*),
|
|
68
85
|
:host([variant='expanded'][data-collapsed]) #title ::slotted(*) {
|
|
@@ -78,6 +95,16 @@ const w = f`
|
|
|
78
95
|
grid-column: 2;
|
|
79
96
|
grid-row: 1;
|
|
80
97
|
justify-self: center;
|
|
98
|
+
/*
|
|
99
|
+
* Default (uncapped): 100% of the flexible column, i.e. fills it
|
|
100
|
+
* edge-to-edge, same as any other content in that column. Once a
|
|
101
|
+
* consumer sets --rc-app-bar-center-max-inline-size below the column's
|
|
102
|
+
* own width, this centers within the leftover space instead -- deliberately
|
|
103
|
+
* not written as justify-self: stretch plus max-inline-size, which falls
|
|
104
|
+
* back to start-alignment once the max-width constraint applies rather
|
|
105
|
+
* than centering.
|
|
106
|
+
*/
|
|
107
|
+
inline-size: min(100%, var(--rc-app-bar-center-max-inline-size, 100%));
|
|
81
108
|
}
|
|
82
109
|
|
|
83
110
|
#trailing {
|
|
@@ -86,11 +113,12 @@ const w = f`
|
|
|
86
113
|
justify-self: end;
|
|
87
114
|
}
|
|
88
115
|
|
|
89
|
-
#root[data-has-center] #center {
|
|
116
|
+
:host([center-symmetric]) #root[data-has-center] #center {
|
|
90
117
|
grid-column: 3;
|
|
118
|
+
inline-size: auto;
|
|
91
119
|
}
|
|
92
120
|
|
|
93
|
-
#root[data-has-center] #trailing {
|
|
121
|
+
:host([center-symmetric]) #root[data-has-center] #trailing {
|
|
94
122
|
grid-column: 5;
|
|
95
123
|
}
|
|
96
124
|
|
|
@@ -115,8 +143,7 @@ const w = f`
|
|
|
115
143
|
}
|
|
116
144
|
|
|
117
145
|
:host([variant='expanded'][data-collapsed]) #title {
|
|
118
|
-
animation: rc-app-bar-title-in var(--rc-app-bar-transition-duration, 200ms)
|
|
119
|
-
ease;
|
|
146
|
+
animation: rc-app-bar-title-in var(--rc-app-bar-transition-duration, 200ms) ease;
|
|
120
147
|
}
|
|
121
148
|
|
|
122
149
|
#scroll-shadow {
|
|
@@ -147,9 +174,11 @@ const w = f`
|
|
|
147
174
|
}
|
|
148
175
|
|
|
149
176
|
/*
|
|
150
|
-
* Narrow-viewport fallback for
|
|
177
|
+
* Narrow-viewport fallback for center-symmetric mode only -- the default
|
|
178
|
+
* (center-symmetric absent) never needs this, its plain 3-column grid
|
|
179
|
+
* already behaves this way at every width.
|
|
151
180
|
*
|
|
152
|
-
* The
|
|
181
|
+
* The center-symmetric grid forces both outer columns to
|
|
153
182
|
* --_rc-app-bar-edge-size px (= max of leading/trailing widths) so that the
|
|
154
183
|
* center slot stays perfectly symmetric. On screens ≤ 480 px that symmetry
|
|
155
184
|
* can push the total width past the viewport. Below the threshold:
|
|
@@ -161,24 +190,25 @@ const w = f`
|
|
|
161
190
|
* trailing) are unchanged, so no JS or placement CSS needs to change.
|
|
162
191
|
*/
|
|
163
192
|
@container (max-inline-size: 480px) {
|
|
164
|
-
#root[data-has-center] {
|
|
193
|
+
:host([center-symmetric]) #root[data-has-center] {
|
|
165
194
|
grid-template-columns: auto 0 minmax(0, 1fr) 0 auto;
|
|
166
195
|
}
|
|
167
196
|
|
|
168
|
-
#root[data-has-center] #center {
|
|
197
|
+
:host([center-symmetric]) #root[data-has-center] #center {
|
|
169
198
|
justify-self: stretch;
|
|
170
199
|
justify-content: flex-end;
|
|
200
|
+
inline-size: auto;
|
|
171
201
|
}
|
|
172
202
|
}
|
|
173
203
|
`;
|
|
174
|
-
var
|
|
175
|
-
for (var s = a > 1 ? void 0 : a ?
|
|
176
|
-
(
|
|
177
|
-
return a && s &&
|
|
204
|
+
var O = Object.defineProperty, M = Object.getOwnPropertyDescriptor, i = (u, e, t, a) => {
|
|
205
|
+
for (var s = a > 1 ? void 0 : a ? M(e, t) : e, l = u.length - 1, o; l >= 0; l--)
|
|
206
|
+
(o = u[l]) && (s = (a ? o(e, t, s) : o(s)) || s);
|
|
207
|
+
return a && s && O(e, t, s), s;
|
|
178
208
|
};
|
|
179
|
-
const
|
|
209
|
+
const p = class p extends v {
|
|
180
210
|
constructor() {
|
|
181
|
-
super(...arguments), this.variant = "compact", this.scrollBehavior = "pinned", this.scrollTarget = null, this.scrollThreshold = 4, this._scrolled = void 0, this._observedScrolled = !1, this._hasLeading = !1, this._hasCenter = !1, this._hasTrailing = !1, this._collapsed = !1, this._hidden = !1, this._collapseDistance = 0, this._collapseOffsetDistance = 0, this._collapseProgress = 0, this._reducedMotion = typeof window < "u" ? window.matchMedia("(prefers-reduced-motion: reduce)") : null, this._internals = this.attachInternals(), this._resizeObserver = null, this._layoutMeasure = new
|
|
211
|
+
super(...arguments), this.variant = "compact", this.centerSymmetric = !1, this.scrollBehavior = "pinned", this.scrollTarget = null, this.scrollThreshold = 4, this._scrolled = void 0, this._observedScrolled = !1, this._hasLeading = !1, this._hasCenter = !1, this._hasTrailing = !1, this._collapsed = !1, this._hidden = !1, this._collapseDistance = 0, this._collapseOffsetDistance = 0, this._collapseProgress = 0, this._reducedMotion = typeof window < "u" ? window.matchMedia("(prefers-reduced-motion: reduce)") : null, this._internals = this.attachInternals(), this._resizeObserver = null, this._layoutMeasure = new S(this), this._scroll = new C(this, {
|
|
182
212
|
target: () => this._resolveScrollTarget(),
|
|
183
213
|
threshold: this.scrollThreshold,
|
|
184
214
|
disabled: !0,
|
|
@@ -206,7 +236,7 @@ const h = class h extends v {
|
|
|
206
236
|
return this._collapsed;
|
|
207
237
|
}
|
|
208
238
|
connectedCallback() {
|
|
209
|
-
super.connectedCallback(), this._connectResizeObserver();
|
|
239
|
+
super.connectedCallback(), this._connectResizeObserver(), this.hasUpdated && this._queueLayoutMeasure();
|
|
210
240
|
}
|
|
211
241
|
disconnectedCallback() {
|
|
212
242
|
super.disconnectedCallback(), this._resizeObserver?.disconnect(), this._cancelQueuedLayoutMeasure();
|
|
@@ -215,10 +245,10 @@ const h = class h extends v {
|
|
|
215
245
|
(e.has("scrollTarget") || e.has("scrollThreshold") || e.has("scrollBehavior")) && this._syncScrollObserver(), (e.has("variant") || e.has("scrollBehavior")) && this._syncVisualState();
|
|
216
246
|
}
|
|
217
247
|
firstUpdated() {
|
|
218
|
-
this._observeLayout(), this.
|
|
248
|
+
this._observeLayout(), this._queueLayoutMeasure(), this._syncScrollObserver(), this._syncVisualState();
|
|
219
249
|
}
|
|
220
250
|
updated(e) {
|
|
221
|
-
this._observeLayout(), (e.has("variant") || e.has("_hasLeading") || e.has("_hasCenter") || e.has("_hasTrailing")) && this.
|
|
251
|
+
this._observeLayout(), (e.has("variant") || e.has("centerSymmetric") || e.has("_hasLeading") || e.has("_hasCenter") || e.has("_hasTrailing")) && this._queueLayoutMeasure(), this._syncStateOutputs();
|
|
222
252
|
}
|
|
223
253
|
_connectResizeObserver() {
|
|
224
254
|
"ResizeObserver" in globalThis && (this._resizeObserver ??= new ResizeObserver(() => this._queueLayoutMeasure()), this._observeLayout());
|
|
@@ -231,14 +261,16 @@ const h = class h extends v {
|
|
|
231
261
|
}
|
|
232
262
|
_measureLayout() {
|
|
233
263
|
const e = this.shadowRoot?.querySelector("#leading"), t = this.shadowRoot?.querySelector("#title"), a = this.shadowRoot?.querySelector("#trailing");
|
|
234
|
-
if (!e || !t || !a)
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
264
|
+
if (!e || !t || !a)
|
|
265
|
+
return;
|
|
266
|
+
const l = this.variant === "expanded" && !this._collapsed ? t.offsetHeight : 0, o = l > 0 ? getComputedStyle(t) : null, _ = o ? Number.parseFloat(o.paddingBlockStart) : 0, y = o ? Number.parseFloat(o.paddingBlockEnd) : 0, m = l > 0 ? t.offsetTop : 0;
|
|
267
|
+
if (this.centerSymmetric) {
|
|
268
|
+
const d = Math.max(e.offsetWidth, a.offsetWidth);
|
|
269
|
+
this._setGeometryProperty("--_rc-app-bar-edge-size", `${d}px`);
|
|
270
|
+
}
|
|
271
|
+
if (o) {
|
|
272
|
+
const d = _ + y, g = Math.max(l - d, 0), f = Math.max(m, g);
|
|
273
|
+
this._collapseDistance = l, this._collapseOffsetDistance = m - (f - g) / 2, this._setGeometryProperty("--_rc-app-bar-collapse-distance", `${l}px`), this._applyCollapseGeometry();
|
|
242
274
|
}
|
|
243
275
|
}
|
|
244
276
|
_queueLayoutMeasure() {
|
|
@@ -255,9 +287,12 @@ const h = class h extends v {
|
|
|
255
287
|
}
|
|
256
288
|
_resolveScrollTarget() {
|
|
257
289
|
const e = this.scrollTarget;
|
|
258
|
-
if (e == null)
|
|
259
|
-
|
|
260
|
-
if (e
|
|
290
|
+
if (e == null)
|
|
291
|
+
return null;
|
|
292
|
+
if (typeof e != "string")
|
|
293
|
+
return e;
|
|
294
|
+
if (e === "window")
|
|
295
|
+
return window;
|
|
261
296
|
try {
|
|
262
297
|
return this.ownerDocument?.querySelector(e) ?? null;
|
|
263
298
|
} catch {
|
|
@@ -267,7 +302,8 @@ const h = class h extends v {
|
|
|
267
302
|
_onObservedScroll(e, t) {
|
|
268
303
|
if (this._scrolled === void 0) {
|
|
269
304
|
if (this.scrollBehavior === "collapse" && this.variant === "expanded") {
|
|
270
|
-
if (this._collapseDistance <= 0)
|
|
305
|
+
if (this._collapseDistance <= 0)
|
|
306
|
+
return;
|
|
271
307
|
const a = this._collapseDistance;
|
|
272
308
|
let s = Math.min(Math.max(e / a, 0), 1);
|
|
273
309
|
this._reducedMotion?.matches ? s = e > this.scrollThreshold ? 1 : 0 : s = s >= 0.999 ? 1 : s, this._setCollapseProgress(s);
|
|
@@ -287,7 +323,7 @@ const h = class h extends v {
|
|
|
287
323
|
_setCollapseProgress(e) {
|
|
288
324
|
this._collapseProgress = e, this.style.setProperty("--rc-app-bar-collapse-progress", `${e}`), this._applyCollapseGeometry();
|
|
289
325
|
const t = e >= 1;
|
|
290
|
-
t !== this._collapsed && (this._collapsed = t, this.toggleAttribute("data-collapsed", t), this._setCustomState("collapsed", t), this.
|
|
326
|
+
t !== this._collapsed && (this._collapsed = t, this.toggleAttribute("data-collapsed", t), this._setCustomState("collapsed", t), this._queueLayoutMeasure());
|
|
291
327
|
}
|
|
292
328
|
_applyCollapseGeometry() {
|
|
293
329
|
const e = this._collapseOffsetDistance * this._collapseProgress, t = this._collapseDistance * (1 - this._collapseProgress);
|
|
@@ -318,21 +354,21 @@ const h = class h extends v {
|
|
|
318
354
|
this._hasTrailing = a;
|
|
319
355
|
break;
|
|
320
356
|
}
|
|
321
|
-
|
|
357
|
+
this._queueLayoutMeasure();
|
|
322
358
|
}
|
|
323
359
|
render() {
|
|
324
|
-
return
|
|
325
|
-
<div id="root" part="root" data-has-center=${this._hasCenter ? "" :
|
|
326
|
-
<div id="leading" part="leading" class=${
|
|
360
|
+
return w`
|
|
361
|
+
<div id="root" part="root" data-has-center=${this._hasCenter ? "" : x}>
|
|
362
|
+
<div id="leading" part="leading" class=${h({ empty: !this._hasLeading })}>
|
|
327
363
|
<slot name="leading" @slotchange=${this._onSlotChange}></slot>
|
|
328
364
|
</div>
|
|
329
365
|
<div id="title" part="title">
|
|
330
366
|
<slot @slotchange=${this._onSlotChange}></slot>
|
|
331
367
|
</div>
|
|
332
|
-
<div id="center" part="center" class=${
|
|
368
|
+
<div id="center" part="center" class=${h({ empty: !this._hasCenter })}>
|
|
333
369
|
<slot name="center" @slotchange=${this._onSlotChange}></slot>
|
|
334
370
|
</div>
|
|
335
|
-
<div id="trailing" part="trailing" class=${
|
|
371
|
+
<div id="trailing" part="trailing" class=${h({ empty: !this._hasTrailing })}>
|
|
336
372
|
<slot name="trailing" @slotchange=${this._onSlotChange}></slot>
|
|
337
373
|
</div>
|
|
338
374
|
<div id="scroll-shadow" part="scroll-shadow"></div>
|
|
@@ -340,11 +376,14 @@ const h = class h extends v {
|
|
|
340
376
|
`;
|
|
341
377
|
}
|
|
342
378
|
};
|
|
343
|
-
|
|
344
|
-
let r =
|
|
379
|
+
p.styles = [z];
|
|
380
|
+
let r = p;
|
|
345
381
|
i([
|
|
346
382
|
n({ type: String, reflect: !0 })
|
|
347
383
|
], r.prototype, "variant", 2);
|
|
384
|
+
i([
|
|
385
|
+
n({ type: Boolean, attribute: "center-symmetric", reflect: !0 })
|
|
386
|
+
], r.prototype, "centerSymmetric", 2);
|
|
348
387
|
i([
|
|
349
388
|
n({ type: String, attribute: "scroll-behavior", reflect: !0 })
|
|
350
389
|
], r.prototype, "scrollBehavior", 2);
|
|
@@ -372,4 +411,4 @@ i([
|
|
|
372
411
|
export {
|
|
373
412
|
r as R
|
|
374
413
|
};
|
|
375
|
-
//# sourceMappingURL=rc-app-bar-
|
|
414
|
+
//# sourceMappingURL=rc-app-bar-C728WmdN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rc-app-bar-C728WmdN.js","sources":["../src/rc-app-bar.styles.ts","../src/rc-app-bar.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const appBarStyles = css`\n :host {\n display: block;\n container-type: inline-size;\n background: var(--rc-app-bar-bg, Canvas);\n color: var(--rc-app-bar-color, CanvasText);\n --_rc-app-bar-collapse-distance: 0px;\n --_rc-app-bar-collapse-offset: 0px;\n --rc-app-bar-collapse-progress: 0;\n --_rc-app-bar-edge-size: 0px;\n --_rc-app-bar-expanded-opacity: 1;\n --_rc-app-bar-expanded-size: 0px;\n transition: translate var(--rc-app-bar-transition-duration, 200ms) ease;\n }\n\n :host([data-hidden]) {\n translate: 0 -100%;\n }\n\n #root {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto;\n grid-template-rows:\n minmax(var(--rc-app-bar-compact-min-height, 3rem), auto)\n 0;\n align-items: center;\n column-gap: var(--rc-app-bar-gap, 0.5em);\n padding-inline: var(--rc-app-bar-padding-inline, 0.75em);\n background: inherit;\n color: inherit;\n }\n\n /*\n * Opt-in: mirrors the leading/trailing edges (measured in JS — see\n * _measureLayout) so center content stays exactly viewport-centered\n * regardless of asymmetric side content. The default (this attribute\n * absent) instead falls through to the plain 3-column grid above, same as\n * a bare title — #center just fills the flexible middle column, capped\n * and self-centered within it via --rc-app-bar-center-max-inline-size.\n */\n :host([center-symmetric]) #root[data-has-center] {\n grid-template-columns:\n var(--_rc-app-bar-edge-size)\n minmax(0, 1fr)\n auto\n minmax(0, 1fr)\n var(--_rc-app-bar-edge-size);\n }\n\n #leading,\n #center,\n #trailing {\n display: flex;\n align-items: center;\n min-inline-size: 0;\n }\n\n #leading {\n grid-column: 1;\n grid-row: 1;\n }\n\n #title {\n grid-column: 2;\n grid-row: 1;\n min-inline-size: 0;\n overflow: clip;\n }\n\n /* M3: without a navigation icon, the headline aligns with the start\n * margin of the content below the bar, not the bar's own edge padding\n * (which is calibrated for the icon button's touch target, not bare\n * text). Only applies when the leading slot is genuinely empty — the\n * adjacent #leading.empty marker already exists for the .empty class. */\n #leading.empty + #title {\n padding-inline-start: var(--rc-app-bar-title-start-padding, 0px);\n }\n\n /* Compact-row title: all non-expanded states and the collapsed endpoint. */\n :host(:not([variant='expanded'])) #title ::slotted(*),\n :host([variant='expanded'][data-collapsed]) #title ::slotted(*) {\n font-size: var(--rc-app-bar-title-font-size, inherit);\n }\n\n /* Expanded-row title: only while uncollapsed. */\n :host([variant='expanded']:not([data-collapsed])) #title ::slotted(*) {\n font-size: var(--rc-app-bar-expanded-title-font-size, inherit);\n }\n\n #center {\n grid-column: 2;\n grid-row: 1;\n justify-self: center;\n /*\n * Default (uncapped): 100% of the flexible column, i.e. fills it\n * edge-to-edge, same as any other content in that column. Once a\n * consumer sets --rc-app-bar-center-max-inline-size below the column's\n * own width, this centers within the leftover space instead -- deliberately\n * not written as justify-self: stretch plus max-inline-size, which falls\n * back to start-alignment once the max-width constraint applies rather\n * than centering.\n */\n inline-size: min(100%, var(--rc-app-bar-center-max-inline-size, 100%));\n }\n\n #trailing {\n grid-column: 3;\n grid-row: 1;\n justify-self: end;\n }\n\n :host([center-symmetric]) #root[data-has-center] #center {\n grid-column: 3;\n inline-size: auto;\n }\n\n :host([center-symmetric]) #root[data-has-center] #trailing {\n grid-column: 5;\n }\n\n .empty {\n visibility: hidden;\n pointer-events: none;\n }\n\n :host([variant='expanded']:not([data-collapsed])) #root {\n grid-template-rows:\n minmax(var(--rc-app-bar-compact-min-height, 3rem), auto)\n var(--_rc-app-bar-expanded-size);\n }\n\n :host([variant='expanded']:not([data-collapsed])) #title {\n grid-column: 1 / -1;\n grid-row: 2;\n align-self: start;\n padding-block: var(--rc-app-bar-expanded-padding-block, 0.75em);\n translate: 0 var(--_rc-app-bar-collapse-offset);\n opacity: var(--_rc-app-bar-expanded-opacity);\n }\n\n :host([variant='expanded'][data-collapsed]) #title {\n animation: rc-app-bar-title-in var(--rc-app-bar-transition-duration, 200ms) ease;\n }\n\n #scroll-shadow {\n grid-column: 1 / -1;\n grid-row: 3;\n align-self: end;\n inline-size: calc(100% + 2 * var(--rc-app-bar-padding-inline, 0.75em));\n margin-inline: calc(var(--rc-app-bar-padding-inline, 0.75em) * -1);\n border-block-end: 1px solid transparent;\n }\n\n :host([data-scrolled]) #scroll-shadow {\n border-block-end: var(--rc-app-bar-scroll-divider, 1px solid GrayText);\n }\n\n @keyframes rc-app-bar-title-in {\n from {\n opacity: 0;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host,\n :host([variant='expanded'][data-collapsed]) #title {\n transition-duration: 0s;\n animation-duration: 0s;\n }\n }\n\n /*\n * Narrow-viewport fallback for center-symmetric mode only -- the default\n * (center-symmetric absent) never needs this, its plain 3-column grid\n * already behaves this way at every width.\n *\n * The center-symmetric grid forces both outer columns to\n * --_rc-app-bar-edge-size px (= max of leading/trailing widths) so that the\n * center slot stays perfectly symmetric. On screens ≤ 480 px that symmetry\n * can push the total width past the viewport. Below the threshold:\n * - leading and trailing size to their natural content width (auto)\n * - the center slot takes all remaining space (minmax(0, 1fr))\n * - the two inner spacer columns collapse to 0\n *\n * Grid column assignments (1 leading / 2 spacer / 3 center / 4 spacer / 5\n * trailing) are unchanged, so no JS or placement CSS needs to change.\n */\n @container (max-inline-size: 480px) {\n :host([center-symmetric]) #root[data-has-center] {\n grid-template-columns: auto 0 minmax(0, 1fr) 0 auto;\n }\n\n :host([center-symmetric]) #root[data-has-center] #center {\n justify-self: stretch;\n justify-content: flex-end;\n inline-size: auto;\n }\n }\n`;\n\nexport default appBarStyles;\n","import { LitElement, html, nothing, type PropertyValues } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\n\nimport {\n RafScheduler,\n ScrollObserverController,\n type ScrollObserverTarget,\n} from '@rcarls/rc-common';\n\nimport appBarStyles from './rc-app-bar.styles.js';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'rc-app-bar': RCAppBar;\n }\n}\n\nexport type RCAppBarVariant = 'compact' | 'expanded';\n\nexport type RCAppBarScrollBehavior = 'pinned' | 'collapse' | 'hide';\n\nexport interface RCAppBarScrollDetail {\n /** Whether the observed scroll target is past the threshold. */\n scrolled: boolean;\n}\n\n/**\n * App bar modeled after the Material 3 Top app bar, with leading, title, center, trailing\n * regions and optional scroll behavior.\n *\n * The element carries no landmark role. Consumers provide all controls and\n * icons, and wrap page-level instances in `<header>` when a banner landmark is\n * appropriate.\n *\n * Scrolled state is dual-mode. Uncontrolled: set `scrollTarget` (or the\n * `scroll-target` selector attribute) and the bar observes the container.\n * Controlled: assign `scrolled`; assigning `undefined` releases observation.\n * Host writes are silent.\n *\n * Environment-driven state (scrolled, collapsed, hidden) is exposed as\n * `data-scrolled`, `data-collapsed`, and `data-hidden` attributes with\n * equivalent `:state(scrolled)`, `:state(collapsed)`, and `:state(hidden)`\n * ElementInternals custom states. These are computed outputs, not settable\n * attributes.\n *\n * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-app-bar rc-app-bar docs}\n * @see {@link https://m3.material.io/components/top-app-bar/overview Material 3 Top app bar}\n *\n * @slot leading - Leading navigation or controls; accepts multiple children\n * @slot - The single title region; may contain title and subtitle markup\n * @slot center - Content such as search, kept within the flexible middle column between\n * leading and trailing. Fills that column by default, capped and self-centered within it via\n * `--rc-app-bar-center-max-inline-size`; add `center-symmetric` for exact viewport centering\n * regardless of asymmetric leading/trailing content instead.\n * @slot trailing - Trailing action controls\n * @fires rc-app-bar-scroll - When observed scroll state crosses the threshold;\n * `detail: { scrolled }`\n * @attr variant - Structural variant. `expanded` adds a flexible title row.\n * @attr scroll-behavior - Visual response to observed scrolling: `pinned`, `collapse`, or `hide`.\n * @attr scroll-target - CSS selector (or `\"window\"`) for the scroll container to observe.\n * @attr scroll-threshold - Scroll offset in px past which the bar is scrolled (strict `>`).\n * @attr center-symmetric - Opt-in: mirrors leading/trailing edge widths so `slot=\"center\"`\n * content stays exactly viewport-centered. Default: fills the flexible middle column instead,\n * centered within available space once capped by `--rc-app-bar-center-max-inline-size`.\n * @cssprop [--rc-app-bar-bg=Canvas] - Bar background\n * @cssprop [--rc-app-bar-color=CanvasText] - Bar text color\n * @cssprop [--rc-app-bar-compact-min-height=3rem] - Compact row minimum height\n * @cssprop [--rc-app-bar-expanded-padding-block=0.75em] - Expanded title padding\n * @cssprop [--rc-app-bar-padding-inline=0.75em] - Horizontal padding\n * @cssprop [--rc-app-bar-gap=0.5em] - Gap between regions\n * @cssprop [--rc-app-bar-center-max-inline-size=100%] - Max width of `slot=\"center\"` content\n * before it centers within the available space instead of filling it. No effect when\n * `center-symmetric` is set.\n * @cssprop [--rc-app-bar-title-start-padding=0px] - Extra title inline-start padding used only when the leading slot is empty (M3: align with content below when there's no navigation icon)\n * @cssprop [--rc-app-bar-transition-duration=200ms] - Endpoint and hide duration\n * @cssprop [--rc-app-bar-scroll-divider=1px solid GrayText] - Scrolled divider\n * @cssprop [--rc-app-bar-collapse-progress=0] - Collapse animation progress 0–1; read-only\n * @cssprop [--rc-app-bar-title-font-size] - Compact-row title font size (opt-in; inherits when unset)\n * @cssprop [--rc-app-bar-expanded-title-font-size] - Expanded-row title font size (opt-in)\n * @csspart root - The grid container\n * @csspart leading - Wrapper around the leading slot\n * @csspart title - Wrapper around the single title slot\n * @csspart center - Wrapper around the centered slot\n * @csspart trailing - Wrapper around the trailing slot\n * @csspart scroll-shadow - Scrolled-state separator\n */\nexport class RCAppBar extends LitElement {\n static styles = [appBarStyles];\n\n /** Structural variant. `expanded` adds a flexible title row. */\n @property({ type: String, reflect: true })\n variant: RCAppBarVariant = 'compact';\n\n /**\n * Opt-in: mirrors the leading/trailing edge widths so `slot=\"center\"`\n * content stays exactly viewport-centered regardless of asymmetric side\n * content. Default (absent): center content fills the flexible middle\n * column like a plain title, capped and self-centered within it via\n * `--rc-app-bar-center-max-inline-size` -- centered within the available\n * space between leading and trailing, not mirrored to the viewport.\n */\n @property({ type: Boolean, attribute: 'center-symmetric', reflect: true })\n centerSymmetric = false;\n\n /** Visual response to observed scrolling. */\n @property({ type: String, attribute: 'scroll-behavior', reflect: true })\n scrollBehavior: RCAppBarScrollBehavior = 'pinned';\n\n /**\n * Scroll container to observe. The attribute accepts a CSS selector or\n * `window`; the property also accepts an element, document, or window.\n */\n @property({ attribute: 'scroll-target' })\n scrollTarget: ScrollObserverTarget | string | null = null;\n\n /** Scroll offset in px past which the bar is scrolled (strict `>`). */\n @property({ type: Number, attribute: 'scroll-threshold' })\n scrollThreshold = 4;\n\n private _scrolled: boolean | undefined = undefined;\n\n @state()\n private _observedScrolled = false;\n\n @state()\n private _hasLeading = false;\n\n @state()\n private _hasCenter = false;\n\n @state()\n private _hasTrailing = false;\n\n private _collapsed = false;\n\n private _hidden = false;\n\n private _collapseDistance = 0;\n\n private _collapseOffsetDistance = 0;\n\n private _collapseProgress = 0;\n\n private readonly _reducedMotion =\n typeof window !== 'undefined' ? window.matchMedia('(prefers-reduced-motion: reduce)') : null;\n\n private _internals = this.attachInternals();\n\n private _resizeObserver: ResizeObserver | null = null;\n\n private readonly _layoutMeasure = new RafScheduler(this);\n\n private readonly _scroll = new ScrollObserverController(this, {\n target: () => this._resolveScrollTarget(),\n threshold: this.scrollThreshold,\n disabled: true,\n onChange: (scrolled) => {\n this._observedScrolled = scrolled;\n this._syncVisualState();\n\n this.dispatchEvent(\n new CustomEvent<RCAppBarScrollDetail>('rc-app-bar-scroll', {\n bubbles: true,\n composed: true,\n detail: { scrolled },\n }),\n );\n },\n onScroll: (scrollTop, delta) => this._onObservedScroll(scrollTop, delta),\n });\n\n /**\n * Whether the bar is past its scroll threshold. Host writes are silent and\n * controlled; assigning `undefined` releases observation.\n */\n @property({ attribute: false })\n get scrolled(): boolean {\n return this._scrolled ?? this._observedScrolled;\n }\n\n set scrolled(value: boolean | undefined) {\n const oldValue = this.scrolled;\n\n this._scrolled = value;\n this._syncScrollObserver();\n this._syncVisualState();\n this.requestUpdate('scrolled', oldValue);\n }\n\n /** Whether the expanded title row is currently collapsed. */\n get collapsed(): boolean {\n return this._collapsed;\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this._connectResizeObserver();\n\n if (this.hasUpdated) {\n this._queueLayoutMeasure();\n }\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._resizeObserver?.disconnect();\n this._cancelQueuedLayoutMeasure();\n }\n\n protected override willUpdate(changed: PropertyValues<this>): void {\n if (\n changed.has('scrollTarget') ||\n changed.has('scrollThreshold') ||\n changed.has('scrollBehavior')\n ) {\n this._syncScrollObserver();\n }\n\n if (changed.has('variant') || changed.has('scrollBehavior')) {\n this._syncVisualState();\n }\n }\n\n protected override firstUpdated(): void {\n this._observeLayout();\n this._queueLayoutMeasure();\n this._syncScrollObserver();\n this._syncVisualState();\n }\n\n protected override updated(changed: PropertyValues): void {\n this._observeLayout();\n\n if (\n changed.has('variant') ||\n changed.has('centerSymmetric') ||\n changed.has('_hasLeading') ||\n changed.has('_hasCenter') ||\n changed.has('_hasTrailing')\n ) {\n this._queueLayoutMeasure();\n }\n\n this._syncStateOutputs();\n }\n\n private _connectResizeObserver(): void {\n if (!('ResizeObserver' in globalThis)) {\n return;\n }\n\n this._resizeObserver ??= new ResizeObserver(() => this._queueLayoutMeasure());\n this._observeLayout();\n }\n\n private _observeLayout(): void {\n if (!this._resizeObserver) {\n return;\n }\n\n this._resizeObserver.disconnect();\n\n ['#leading', '#title', '#center', '#trailing'].forEach((selector) => {\n const $element = this.shadowRoot?.querySelector<HTMLElement>(selector);\n\n if ($element) {\n this._resizeObserver?.observe($element);\n }\n });\n }\n\n private _measureLayout(): void {\n const $leading = this.shadowRoot?.querySelector<HTMLElement>('#leading');\n const $title = this.shadowRoot?.querySelector<HTMLElement>('#title');\n const $trailing = this.shadowRoot?.querySelector<HTMLElement>('#trailing');\n\n if (!$leading || !$title || !$trailing) {\n return;\n }\n\n const shouldMeasureCollapse = this.variant === 'expanded' && !this._collapsed;\n const nextDistance = shouldMeasureCollapse ? $title.offsetHeight : 0;\n const titleStyle = nextDistance > 0 ? getComputedStyle($title) : null;\n // Resolve live computed-style values before the first inline geometry write.\n const paddingBlockStart = titleStyle ? Number.parseFloat(titleStyle.paddingBlockStart) : 0;\n const paddingBlockEnd = titleStyle ? Number.parseFloat(titleStyle.paddingBlockEnd) : 0;\n const compactHeight = nextDistance > 0 ? $title.offsetTop : 0;\n\n // Only meaningful for center-symmetric mode's mirrored-edge grid; skip\n // the reads entirely otherwise.\n if (this.centerSymmetric) {\n const edgeSize = Math.max($leading.offsetWidth, $trailing.offsetWidth);\n\n this._setGeometryProperty('--_rc-app-bar-edge-size', `${edgeSize}px`);\n }\n\n if (titleStyle) {\n const padding = paddingBlockStart + paddingBlockEnd;\n const contentHeight = Math.max(nextDistance - padding, 0);\n const endpointCompactHeight = Math.max(compactHeight, contentHeight);\n\n this._collapseDistance = nextDistance;\n this._collapseOffsetDistance = compactHeight - (endpointCompactHeight - contentHeight) / 2;\n this._setGeometryProperty('--_rc-app-bar-collapse-distance', `${nextDistance}px`);\n this._applyCollapseGeometry();\n }\n }\n\n private _queueLayoutMeasure(): void {\n this._layoutMeasure.schedule(() => this._measureLayout());\n }\n\n private _cancelQueuedLayoutMeasure(): void {\n this._layoutMeasure.cancel();\n }\n\n private _syncScrollObserver(): void {\n this._scroll.setOptions({\n threshold: this.scrollThreshold,\n disabled: this._scrolled !== undefined || this._resolveScrollTarget() === null,\n });\n }\n\n private _resolveScrollTarget(): ScrollObserverTarget | null {\n const target = this.scrollTarget;\n\n if (target === null || target === undefined) {\n return null;\n }\n\n if (typeof target !== 'string') {\n return target;\n }\n\n if (target === 'window') {\n return window;\n }\n\n try {\n return this.ownerDocument?.querySelector(target) ?? null;\n } catch {\n return null;\n }\n }\n\n private _onObservedScroll(scrollTop: number, delta: number): void {\n if (this._scrolled !== undefined) {\n return;\n }\n\n if (this.scrollBehavior === 'collapse' && this.variant === 'expanded') {\n if (this._collapseDistance <= 0) {\n return;\n }\n\n const distance = this._collapseDistance;\n let progress = Math.min(Math.max(scrollTop / distance, 0), 1);\n\n if (this._reducedMotion?.matches) {\n progress = scrollTop > this.scrollThreshold ? 1 : 0;\n } else {\n progress = progress >= 0.999 ? 1 : progress;\n }\n\n this._setCollapseProgress(progress);\n } else {\n this._setCollapseProgress(0);\n }\n\n if (this.scrollBehavior === 'hide') {\n if (scrollTop <= this.scrollThreshold || delta < 0) {\n this._setHidden(false);\n } else if (delta > 0) {\n this._setHidden(true);\n }\n } else {\n this._setHidden(false);\n }\n }\n\n private _syncVisualState(): void {\n if (this._scrolled === undefined) {\n if (this.scrollBehavior !== 'collapse' || this.variant !== 'expanded') {\n this._setCollapseProgress(0);\n }\n\n if (this.scrollBehavior !== 'hide') {\n this._setHidden(false);\n }\n\n return;\n }\n\n const collapse = this.variant === 'expanded' && this.scrollBehavior === 'collapse';\n\n this._setCollapseProgress(collapse && this.scrolled ? 1 : 0);\n this._setHidden(false);\n }\n\n private _setCollapseProgress(progress: number): void {\n this._collapseProgress = progress;\n this.style.setProperty('--rc-app-bar-collapse-progress', `${progress}`);\n this._applyCollapseGeometry();\n\n const collapsed = progress >= 1;\n\n if (collapsed === this._collapsed) {\n return;\n }\n\n this._collapsed = collapsed;\n this.toggleAttribute('data-collapsed', collapsed);\n this._setCustomState('collapsed', collapsed);\n this._queueLayoutMeasure();\n }\n\n private _applyCollapseGeometry(): void {\n const offset = this._collapseOffsetDistance * this._collapseProgress;\n const remainingRow = this._collapseDistance * (1 - this._collapseProgress);\n\n this._setGeometryProperty('--_rc-app-bar-collapse-offset', `${-offset}px`);\n this._setGeometryProperty('--_rc-app-bar-expanded-size', `${remainingRow}px`);\n this._setGeometryProperty('--_rc-app-bar-expanded-opacity', `${1 - this._collapseProgress}`);\n }\n\n private _setGeometryProperty(name: string, value: string): void {\n if (this.style.getPropertyValue(name) === value) {\n return;\n }\n\n this.style.setProperty(name, value);\n }\n\n private _setHidden(hidden: boolean): void {\n if (hidden === this._hidden) {\n return;\n }\n\n this._hidden = hidden;\n this.toggleAttribute('data-hidden', hidden);\n this._setCustomState('hidden', hidden);\n }\n\n private _syncStateOutputs(): void {\n this.toggleAttribute('data-scrolled', this.scrolled);\n this._setCustomState('scrolled', this.scrolled);\n this.toggleAttribute('data-collapsed', this._collapsed);\n this.toggleAttribute('data-hidden', this._hidden);\n }\n\n private _setCustomState(name: string, active: boolean): void {\n if (!this._internals.states) {\n return;\n }\n\n if (active) {\n this._internals.states.add(name);\n } else {\n this._internals.states.delete(name);\n }\n }\n\n private _onSlotChange(e: Event): void {\n const $slot = e.target as HTMLSlotElement;\n const hasContent = $slot.assignedElements({ flatten: true }).length > 0;\n\n switch ($slot.name) {\n case 'leading':\n this._hasLeading = hasContent;\n break;\n\n case 'center':\n this._hasCenter = hasContent;\n break;\n\n case 'trailing':\n this._hasTrailing = hasContent;\n break;\n }\n\n this._queueLayoutMeasure();\n }\n\n protected override render() {\n return html`\n <div id=\"root\" part=\"root\" data-has-center=${this._hasCenter ? '' : nothing}>\n <div id=\"leading\" part=\"leading\" class=${classMap({ empty: !this._hasLeading })}>\n <slot name=\"leading\" @slotchange=${this._onSlotChange}></slot>\n </div>\n <div id=\"title\" part=\"title\">\n <slot @slotchange=${this._onSlotChange}></slot>\n </div>\n <div id=\"center\" part=\"center\" class=${classMap({ empty: !this._hasCenter })}>\n <slot name=\"center\" @slotchange=${this._onSlotChange}></slot>\n </div>\n <div id=\"trailing\" part=\"trailing\" class=${classMap({ empty: !this._hasTrailing })}>\n <slot name=\"trailing\" @slotchange=${this._onSlotChange}></slot>\n </div>\n <div id=\"scroll-shadow\" part=\"scroll-shadow\"></div>\n </div>\n `;\n }\n}\n\nexport default RCAppBar;\n"],"names":["appBarStyles","css","_RCAppBar","LitElement","RafScheduler","ScrollObserverController","scrolled","scrollTop","delta","value","oldValue","changed","selector","$element","$leading","$title","$trailing","nextDistance","titleStyle","paddingBlockStart","paddingBlockEnd","compactHeight","edgeSize","padding","contentHeight","endpointCompactHeight","target","distance","progress","collapse","collapsed","offset","remainingRow","name","hidden","active","$slot","hasContent","html","nothing","classMap","RCAppBar","__decorateClass","property","state"],"mappings":"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"}
|
package/dist/rc-app-bar.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './rc-app-bar';
|
|
1
|
+
export * from './rc-app-bar.js';
|
|
@@ -35,7 +35,10 @@ export interface RCAppBarScrollDetail {
|
|
|
35
35
|
*
|
|
36
36
|
* @slot leading - Leading navigation or controls; accepts multiple children
|
|
37
37
|
* @slot - The single title region; may contain title and subtitle markup
|
|
38
|
-
* @slot center - Content kept
|
|
38
|
+
* @slot center - Content such as search, kept within the flexible middle column between
|
|
39
|
+
* leading and trailing. Fills that column by default, capped and self-centered within it via
|
|
40
|
+
* `--rc-app-bar-center-max-inline-size`; add `center-symmetric` for exact viewport centering
|
|
41
|
+
* regardless of asymmetric leading/trailing content instead.
|
|
39
42
|
* @slot trailing - Trailing action controls
|
|
40
43
|
* @fires rc-app-bar-scroll - When observed scroll state crosses the threshold;
|
|
41
44
|
* `detail: { scrolled }`
|
|
@@ -43,12 +46,19 @@ export interface RCAppBarScrollDetail {
|
|
|
43
46
|
* @attr scroll-behavior - Visual response to observed scrolling: `pinned`, `collapse`, or `hide`.
|
|
44
47
|
* @attr scroll-target - CSS selector (or `"window"`) for the scroll container to observe.
|
|
45
48
|
* @attr scroll-threshold - Scroll offset in px past which the bar is scrolled (strict `>`).
|
|
49
|
+
* @attr center-symmetric - Opt-in: mirrors leading/trailing edge widths so `slot="center"`
|
|
50
|
+
* content stays exactly viewport-centered. Default: fills the flexible middle column instead,
|
|
51
|
+
* centered within available space once capped by `--rc-app-bar-center-max-inline-size`.
|
|
46
52
|
* @cssprop [--rc-app-bar-bg=Canvas] - Bar background
|
|
47
53
|
* @cssprop [--rc-app-bar-color=CanvasText] - Bar text color
|
|
48
54
|
* @cssprop [--rc-app-bar-compact-min-height=3rem] - Compact row minimum height
|
|
49
55
|
* @cssprop [--rc-app-bar-expanded-padding-block=0.75em] - Expanded title padding
|
|
50
56
|
* @cssprop [--rc-app-bar-padding-inline=0.75em] - Horizontal padding
|
|
51
57
|
* @cssprop [--rc-app-bar-gap=0.5em] - Gap between regions
|
|
58
|
+
* @cssprop [--rc-app-bar-center-max-inline-size=100%] - Max width of `slot="center"` content
|
|
59
|
+
* before it centers within the available space instead of filling it. No effect when
|
|
60
|
+
* `center-symmetric` is set.
|
|
61
|
+
* @cssprop [--rc-app-bar-title-start-padding=0px] - Extra title inline-start padding used only when the leading slot is empty (M3: align with content below when there's no navigation icon)
|
|
52
62
|
* @cssprop [--rc-app-bar-transition-duration=200ms] - Endpoint and hide duration
|
|
53
63
|
* @cssprop [--rc-app-bar-scroll-divider=1px solid GrayText] - Scrolled divider
|
|
54
64
|
* @cssprop [--rc-app-bar-collapse-progress=0] - Collapse animation progress 0–1; read-only
|
|
@@ -65,6 +75,15 @@ export declare class RCAppBar extends LitElement {
|
|
|
65
75
|
static styles: import('lit').CSSResult[];
|
|
66
76
|
/** Structural variant. `expanded` adds a flexible title row. */
|
|
67
77
|
variant: RCAppBarVariant;
|
|
78
|
+
/**
|
|
79
|
+
* Opt-in: mirrors the leading/trailing edge widths so `slot="center"`
|
|
80
|
+
* content stays exactly viewport-centered regardless of asymmetric side
|
|
81
|
+
* content. Default (absent): center content fills the flexible middle
|
|
82
|
+
* column like a plain title, capped and self-centered within it via
|
|
83
|
+
* `--rc-app-bar-center-max-inline-size` -- centered within the available
|
|
84
|
+
* space between leading and trailing, not mirrored to the viewport.
|
|
85
|
+
*/
|
|
86
|
+
centerSymmetric: boolean;
|
|
68
87
|
/** Visual response to observed scrolling. */
|
|
69
88
|
scrollBehavior: RCAppBarScrollBehavior;
|
|
70
89
|
/**
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.6.0",
|
|
7
7
|
"description": "App bar modeled after the Material 3 Top app bar, with leading, title, center, trailing regions and optional scroll behavior.",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -45,11 +45,11 @@
|
|
|
45
45
|
"test:browser:firefox": "vitest --run --project=firefox"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@rcarls/rc-common": "0.
|
|
48
|
+
"@rcarls/rc-common": "0.6.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@custom-elements-manifest/analyzer": "0.11.0",
|
|
52
|
-
"@rcarls/rc-search-bar": "0.
|
|
52
|
+
"@rcarls/rc-search-bar": "0.6.0",
|
|
53
53
|
"@vitest/browser-playwright": "4.1.5",
|
|
54
54
|
"lit": "^3.0.0",
|
|
55
55
|
"playwright": "^1.56.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rc-app-bar-C9IC9WXj.js","sources":["../src/rc-app-bar.styles.ts","../src/rc-app-bar.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const appBarStyles = css`\n :host {\n display: block;\n container-type: inline-size;\n background: var(--rc-app-bar-bg, Canvas);\n color: var(--rc-app-bar-color, CanvasText);\n --_rc-app-bar-collapse-distance: 0px;\n --_rc-app-bar-collapse-offset: 0px;\n --rc-app-bar-collapse-progress: 0;\n --_rc-app-bar-edge-size: 0px;\n --_rc-app-bar-expanded-opacity: 1;\n --_rc-app-bar-expanded-size: 0px;\n transition: translate var(--rc-app-bar-transition-duration, 200ms) ease;\n }\n\n :host([data-hidden]) {\n translate: 0 -100%;\n }\n\n #root {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr) auto;\n grid-template-rows:\n minmax(var(--rc-app-bar-compact-min-height, 3rem), auto)\n 0;\n align-items: center;\n column-gap: var(--rc-app-bar-gap, 0.5em);\n padding-inline: var(--rc-app-bar-padding-inline, 0.75em);\n background: inherit;\n color: inherit;\n }\n\n #root[data-has-center] {\n grid-template-columns:\n var(--_rc-app-bar-edge-size)\n minmax(0, 1fr)\n auto\n minmax(0, 1fr)\n var(--_rc-app-bar-edge-size);\n }\n\n #leading,\n #center,\n #trailing {\n display: flex;\n align-items: center;\n min-inline-size: 0;\n }\n\n #leading {\n grid-column: 1;\n grid-row: 1;\n }\n\n #title {\n grid-column: 2;\n grid-row: 1;\n min-inline-size: 0;\n overflow: clip;\n }\n\n /* Compact-row title: all non-expanded states and the collapsed endpoint. */\n :host(:not([variant='expanded'])) #title ::slotted(*),\n :host([variant='expanded'][data-collapsed]) #title ::slotted(*) {\n font-size: var(--rc-app-bar-title-font-size, inherit);\n }\n\n /* Expanded-row title: only while uncollapsed. */\n :host([variant='expanded']:not([data-collapsed])) #title ::slotted(*) {\n font-size: var(--rc-app-bar-expanded-title-font-size, inherit);\n }\n\n #center {\n grid-column: 2;\n grid-row: 1;\n justify-self: center;\n }\n\n #trailing {\n grid-column: 3;\n grid-row: 1;\n justify-self: end;\n }\n\n #root[data-has-center] #center {\n grid-column: 3;\n }\n\n #root[data-has-center] #trailing {\n grid-column: 5;\n }\n\n .empty {\n visibility: hidden;\n pointer-events: none;\n }\n\n :host([variant='expanded']:not([data-collapsed])) #root {\n grid-template-rows:\n minmax(var(--rc-app-bar-compact-min-height, 3rem), auto)\n var(--_rc-app-bar-expanded-size);\n }\n\n :host([variant='expanded']:not([data-collapsed])) #title {\n grid-column: 1 / -1;\n grid-row: 2;\n align-self: start;\n padding-block: var(--rc-app-bar-expanded-padding-block, 0.75em);\n translate: 0 var(--_rc-app-bar-collapse-offset);\n opacity: var(--_rc-app-bar-expanded-opacity);\n }\n\n :host([variant='expanded'][data-collapsed]) #title {\n animation: rc-app-bar-title-in var(--rc-app-bar-transition-duration, 200ms)\n ease;\n }\n\n #scroll-shadow {\n grid-column: 1 / -1;\n grid-row: 3;\n align-self: end;\n inline-size: calc(100% + 2 * var(--rc-app-bar-padding-inline, 0.75em));\n margin-inline: calc(var(--rc-app-bar-padding-inline, 0.75em) * -1);\n border-block-end: 1px solid transparent;\n }\n\n :host([data-scrolled]) #scroll-shadow {\n border-block-end: var(--rc-app-bar-scroll-divider, 1px solid GrayText);\n }\n\n @keyframes rc-app-bar-title-in {\n from {\n opacity: 0;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n :host,\n :host([variant='expanded'][data-collapsed]) #title {\n transition-duration: 0s;\n animation-duration: 0s;\n }\n }\n\n /*\n * Narrow-viewport fallback for the center-slot layout.\n *\n * The default data-has-center grid forces both outer columns to\n * --_rc-app-bar-edge-size px (= max of leading/trailing widths) so that the\n * center slot stays perfectly symmetric. On screens ≤ 480 px that symmetry\n * can push the total width past the viewport. Below the threshold:\n * - leading and trailing size to their natural content width (auto)\n * - the center slot takes all remaining space (minmax(0, 1fr))\n * - the two inner spacer columns collapse to 0\n *\n * Grid column assignments (1 leading / 2 spacer / 3 center / 4 spacer / 5\n * trailing) are unchanged, so no JS or placement CSS needs to change.\n */\n @container (max-inline-size: 480px) {\n #root[data-has-center] {\n grid-template-columns: auto 0 minmax(0, 1fr) 0 auto;\n }\n\n #root[data-has-center] #center {\n justify-self: stretch;\n justify-content: flex-end;\n }\n }\n`;\n\nexport default appBarStyles;\n","import { LitElement, html, nothing, type PropertyValues } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\n\nimport {\n RafScheduler,\n ScrollObserverController,\n type ScrollObserverTarget,\n} from '@rcarls/rc-common';\n\nimport appBarStyles from './rc-app-bar.styles';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'rc-app-bar': RCAppBar;\n }\n}\n\nexport type RCAppBarVariant = 'compact' | 'expanded';\n\nexport type RCAppBarScrollBehavior = 'pinned' | 'collapse' | 'hide';\n\nexport interface RCAppBarScrollDetail {\n /** Whether the observed scroll target is past the threshold. */\n scrolled: boolean;\n}\n\n/**\n * App bar modeled after the Material 3 Top app bar, with leading, title, center, trailing\n * regions and optional scroll behavior.\n *\n * The element carries no landmark role. Consumers provide all controls and\n * icons, and wrap page-level instances in `<header>` when a banner landmark is\n * appropriate.\n *\n * Scrolled state is dual-mode. Uncontrolled: set `scrollTarget` (or the\n * `scroll-target` selector attribute) and the bar observes the container.\n * Controlled: assign `scrolled`; assigning `undefined` releases observation.\n * Host writes are silent.\n *\n * Environment-driven state (scrolled, collapsed, hidden) is exposed as\n * `data-scrolled`, `data-collapsed`, and `data-hidden` attributes with\n * equivalent `:state(scrolled)`, `:state(collapsed)`, and `:state(hidden)`\n * ElementInternals custom states. These are computed outputs, not settable\n * attributes.\n *\n * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-app-bar rc-app-bar docs}\n * @see {@link https://m3.material.io/components/top-app-bar/overview Material 3 Top app bar}\n *\n * @slot leading - Leading navigation or controls; accepts multiple children\n * @slot - The single title region; may contain title and subtitle markup\n * @slot center - Content kept at the exact horizontal center, such as search\n * @slot trailing - Trailing action controls\n * @fires rc-app-bar-scroll - When observed scroll state crosses the threshold;\n * `detail: { scrolled }`\n * @attr variant - Structural variant. `expanded` adds a flexible title row.\n * @attr scroll-behavior - Visual response to observed scrolling: `pinned`, `collapse`, or `hide`.\n * @attr scroll-target - CSS selector (or `\"window\"`) for the scroll container to observe.\n * @attr scroll-threshold - Scroll offset in px past which the bar is scrolled (strict `>`).\n * @cssprop [--rc-app-bar-bg=Canvas] - Bar background\n * @cssprop [--rc-app-bar-color=CanvasText] - Bar text color\n * @cssprop [--rc-app-bar-compact-min-height=3rem] - Compact row minimum height\n * @cssprop [--rc-app-bar-expanded-padding-block=0.75em] - Expanded title padding\n * @cssprop [--rc-app-bar-padding-inline=0.75em] - Horizontal padding\n * @cssprop [--rc-app-bar-gap=0.5em] - Gap between regions\n * @cssprop [--rc-app-bar-transition-duration=200ms] - Endpoint and hide duration\n * @cssprop [--rc-app-bar-scroll-divider=1px solid GrayText] - Scrolled divider\n * @cssprop [--rc-app-bar-collapse-progress=0] - Collapse animation progress 0–1; read-only\n * @cssprop [--rc-app-bar-title-font-size] - Compact-row title font size (opt-in; inherits when unset)\n * @cssprop [--rc-app-bar-expanded-title-font-size] - Expanded-row title font size (opt-in)\n * @csspart root - The grid container\n * @csspart leading - Wrapper around the leading slot\n * @csspart title - Wrapper around the single title slot\n * @csspart center - Wrapper around the centered slot\n * @csspart trailing - Wrapper around the trailing slot\n * @csspart scroll-shadow - Scrolled-state separator\n */\nexport class RCAppBar extends LitElement {\n static styles = [appBarStyles];\n\n /** Structural variant. `expanded` adds a flexible title row. */\n @property({ type: String, reflect: true })\n variant: RCAppBarVariant = 'compact';\n\n /** Visual response to observed scrolling. */\n @property({ type: String, attribute: 'scroll-behavior', reflect: true })\n scrollBehavior: RCAppBarScrollBehavior = 'pinned';\n\n /**\n * Scroll container to observe. The attribute accepts a CSS selector or\n * `window`; the property also accepts an element, document, or window.\n */\n @property({ attribute: 'scroll-target' })\n scrollTarget: ScrollObserverTarget | string | null = null;\n\n /** Scroll offset in px past which the bar is scrolled (strict `>`). */\n @property({ type: Number, attribute: 'scroll-threshold' })\n scrollThreshold = 4;\n\n private _scrolled: boolean | undefined = undefined;\n\n @state()\n private _observedScrolled = false;\n\n @state()\n private _hasLeading = false;\n\n @state()\n private _hasCenter = false;\n\n @state()\n private _hasTrailing = false;\n\n private _collapsed = false;\n\n private _hidden = false;\n\n private _collapseDistance = 0;\n\n private _collapseOffsetDistance = 0;\n\n private _collapseProgress = 0;\n\n private readonly _reducedMotion =\n typeof window !== 'undefined' ? window.matchMedia('(prefers-reduced-motion: reduce)') : null;\n\n private _internals = this.attachInternals();\n\n private _resizeObserver: ResizeObserver | null = null;\n\n private readonly _layoutMeasure = new RafScheduler(this);\n\n private readonly _scroll = new ScrollObserverController(this, {\n target: () => this._resolveScrollTarget(),\n threshold: this.scrollThreshold,\n disabled: true,\n onChange: (scrolled) => {\n this._observedScrolled = scrolled;\n this._syncVisualState();\n this.dispatchEvent(\n new CustomEvent<RCAppBarScrollDetail>('rc-app-bar-scroll', {\n bubbles: true,\n composed: true,\n detail: { scrolled },\n }),\n );\n },\n onScroll: (scrollTop, delta) => this._onObservedScroll(scrollTop, delta),\n });\n\n /**\n * Whether the bar is past its scroll threshold. Host writes are silent and\n * controlled; assigning `undefined` releases observation.\n */\n @property({ attribute: false })\n get scrolled(): boolean {\n return this._scrolled ?? this._observedScrolled;\n }\n set scrolled(value: boolean | undefined) {\n const oldValue = this.scrolled;\n\n this._scrolled = value;\n this._syncScrollObserver();\n this._syncVisualState();\n this.requestUpdate('scrolled', oldValue);\n }\n\n /** Whether the expanded title row is currently collapsed. */\n get collapsed(): boolean {\n return this._collapsed;\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this._connectResizeObserver();\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._resizeObserver?.disconnect();\n this._cancelQueuedLayoutMeasure();\n }\n\n protected override willUpdate(changed: PropertyValues<this>): void {\n if (\n changed.has('scrollTarget') ||\n changed.has('scrollThreshold') ||\n changed.has('scrollBehavior')\n ) {\n this._syncScrollObserver();\n }\n\n if (changed.has('variant') || changed.has('scrollBehavior')) {\n this._syncVisualState();\n }\n }\n\n protected override firstUpdated(): void {\n this._observeLayout();\n this._measureLayout();\n this._syncScrollObserver();\n this._syncVisualState();\n }\n\n protected override updated(changed: PropertyValues): void {\n this._observeLayout();\n if (\n changed.has('variant') ||\n changed.has('_hasLeading') ||\n changed.has('_hasCenter') ||\n changed.has('_hasTrailing')\n ) {\n this._measureLayout();\n }\n this._syncStateOutputs();\n }\n\n private _connectResizeObserver(): void {\n if (!('ResizeObserver' in globalThis)) return;\n\n this._resizeObserver ??= new ResizeObserver(() => this._queueLayoutMeasure());\n this._observeLayout();\n }\n\n private _observeLayout(): void {\n if (!this._resizeObserver) return;\n\n this._resizeObserver.disconnect();\n ['#leading', '#title', '#center', '#trailing'].forEach((selector) => {\n const $element = this.shadowRoot?.querySelector<HTMLElement>(selector);\n if ($element) this._resizeObserver?.observe($element);\n });\n }\n\n private _measureLayout(): void {\n const $leading = this.shadowRoot?.querySelector<HTMLElement>('#leading');\n const $title = this.shadowRoot?.querySelector<HTMLElement>('#title');\n const $trailing = this.shadowRoot?.querySelector<HTMLElement>('#trailing');\n if (!$leading || !$title || !$trailing) return;\n\n const edgeSize = Math.max($leading.offsetWidth, $trailing.offsetWidth);\n this._setGeometryProperty('--_rc-app-bar-edge-size', `${edgeSize}px`);\n\n if (this.variant === 'expanded' && !this._collapsed) {\n const nextDistance = $title.offsetHeight;\n if (nextDistance > 0) {\n const titleStyle = getComputedStyle($title);\n const padding =\n Number.parseFloat(titleStyle.paddingBlockStart) +\n Number.parseFloat(titleStyle.paddingBlockEnd);\n const contentHeight = Math.max($title.offsetHeight - padding, 0);\n const compactHeight = $title.offsetTop;\n const endpointCompactHeight = Math.max(compactHeight, contentHeight);\n\n this._collapseDistance = nextDistance;\n this._collapseOffsetDistance = compactHeight - (endpointCompactHeight - contentHeight) / 2;\n this._setGeometryProperty('--_rc-app-bar-collapse-distance', `${nextDistance}px`);\n this._applyCollapseGeometry();\n }\n }\n }\n\n private _queueLayoutMeasure(): void {\n this._layoutMeasure.schedule(() => this._measureLayout());\n }\n\n private _cancelQueuedLayoutMeasure(): void {\n this._layoutMeasure.cancel();\n }\n\n private _syncScrollObserver(): void {\n this._scroll.setOptions({\n threshold: this.scrollThreshold,\n disabled: this._scrolled !== undefined || this._resolveScrollTarget() === null,\n });\n }\n\n private _resolveScrollTarget(): ScrollObserverTarget | null {\n const target = this.scrollTarget;\n if (target === null || target === undefined) return null;\n\n if (typeof target !== 'string') return target;\n if (target === 'window') return window;\n\n try {\n return this.ownerDocument?.querySelector(target) ?? null;\n } catch {\n return null;\n }\n }\n\n private _onObservedScroll(scrollTop: number, delta: number): void {\n if (this._scrolled !== undefined) return;\n\n if (this.scrollBehavior === 'collapse' && this.variant === 'expanded') {\n if (this._collapseDistance <= 0) return;\n\n const distance = this._collapseDistance;\n let progress = Math.min(Math.max(scrollTop / distance, 0), 1);\n if (this._reducedMotion?.matches) {\n progress = scrollTop > this.scrollThreshold ? 1 : 0;\n } else {\n progress = progress >= 0.999 ? 1 : progress;\n }\n this._setCollapseProgress(progress);\n } else {\n this._setCollapseProgress(0);\n }\n\n if (this.scrollBehavior === 'hide') {\n if (scrollTop <= this.scrollThreshold || delta < 0) {\n this._setHidden(false);\n } else if (delta > 0) {\n this._setHidden(true);\n }\n } else {\n this._setHidden(false);\n }\n }\n\n private _syncVisualState(): void {\n if (this._scrolled === undefined) {\n if (this.scrollBehavior !== 'collapse' || this.variant !== 'expanded') {\n this._setCollapseProgress(0);\n }\n if (this.scrollBehavior !== 'hide') this._setHidden(false);\n\n return;\n }\n\n const collapse = this.variant === 'expanded' && this.scrollBehavior === 'collapse';\n this._setCollapseProgress(collapse && this.scrolled ? 1 : 0);\n this._setHidden(false);\n }\n\n private _setCollapseProgress(progress: number): void {\n this._collapseProgress = progress;\n this.style.setProperty('--rc-app-bar-collapse-progress', `${progress}`);\n this._applyCollapseGeometry();\n\n const collapsed = progress >= 1;\n if (collapsed === this._collapsed) return;\n\n this._collapsed = collapsed;\n this.toggleAttribute('data-collapsed', collapsed);\n this._setCustomState('collapsed', collapsed);\n this._measureLayout();\n }\n\n private _applyCollapseGeometry(): void {\n const offset = this._collapseOffsetDistance * this._collapseProgress;\n const remainingRow = this._collapseDistance * (1 - this._collapseProgress);\n\n this._setGeometryProperty('--_rc-app-bar-collapse-offset', `${-offset}px`);\n this._setGeometryProperty('--_rc-app-bar-expanded-size', `${remainingRow}px`);\n this._setGeometryProperty('--_rc-app-bar-expanded-opacity', `${1 - this._collapseProgress}`);\n }\n\n private _setGeometryProperty(name: string, value: string): void {\n if (this.style.getPropertyValue(name) === value) return;\n\n this.style.setProperty(name, value);\n }\n\n private _setHidden(hidden: boolean): void {\n if (hidden === this._hidden) return;\n\n this._hidden = hidden;\n this.toggleAttribute('data-hidden', hidden);\n this._setCustomState('hidden', hidden);\n }\n\n private _syncStateOutputs(): void {\n this.toggleAttribute('data-scrolled', this.scrolled);\n this._setCustomState('scrolled', this.scrolled);\n this.toggleAttribute('data-collapsed', this._collapsed);\n this.toggleAttribute('data-hidden', this._hidden);\n }\n\n private _setCustomState(name: string, active: boolean): void {\n if (!this._internals.states) return;\n\n if (active) {\n this._internals.states.add(name);\n } else {\n this._internals.states.delete(name);\n }\n }\n\n private _onSlotChange(e: Event): void {\n const $slot = e.target as HTMLSlotElement;\n const hasContent = $slot.assignedElements({ flatten: true }).length > 0;\n\n switch ($slot.name) {\n case 'leading':\n this._hasLeading = hasContent;\n break;\n\n case 'center':\n this._hasCenter = hasContent;\n break;\n\n case 'trailing':\n this._hasTrailing = hasContent;\n break;\n }\n\n queueMicrotask(() => this._measureLayout());\n }\n\n protected override render() {\n return html`\n <div id=\"root\" part=\"root\" data-has-center=${this._hasCenter ? '' : nothing}>\n <div id=\"leading\" part=\"leading\" class=${classMap({ empty: !this._hasLeading })}>\n <slot name=\"leading\" @slotchange=${this._onSlotChange}></slot>\n </div>\n <div id=\"title\" part=\"title\">\n <slot @slotchange=${this._onSlotChange}></slot>\n </div>\n <div id=\"center\" part=\"center\" class=${classMap({ empty: !this._hasCenter })}>\n <slot name=\"center\" @slotchange=${this._onSlotChange}></slot>\n </div>\n <div id=\"trailing\" part=\"trailing\" class=${classMap({ empty: !this._hasTrailing })}>\n <slot name=\"trailing\" @slotchange=${this._onSlotChange}></slot>\n </div>\n <div id=\"scroll-shadow\" part=\"scroll-shadow\"></div>\n </div>\n `;\n }\n}\n\nexport default RCAppBar;\n"],"names":["appBarStyles","css","_RCAppBar","LitElement","RafScheduler","ScrollObserverController","scrolled","scrollTop","delta","value","oldValue","changed","selector","$element","$leading","$title","$trailing","edgeSize","nextDistance","titleStyle","padding","contentHeight","compactHeight","endpointCompactHeight","target","distance","progress","collapse","collapsed","offset","remainingRow","name","hidden","active","$slot","hasContent","html","nothing","classMap","RCAppBar","__decorateClass","property","state"],"mappings":"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"}
|
|
File without changes
|