@rcarls/rc-app-bar 0.5.0 → 0.7.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.
@@ -0,0 +1,247 @@
1
+ import { css as f, LitElement as S, nothing as x, html as z } from "lit";
2
+ import { property as n, state as c } from "lit/decorators.js";
3
+ import { classMap as d } from "lit/directives/class-map.js";
4
+ import { RafScheduler as T, ScrollObserverController as O, cssZoom as g } from "@rcarls/rc-common";
5
+ const C = f`:host{background:var(--rc-app-bar-bg,Canvas);color:var(--rc-app-bar-color,CanvasText);box-shadow:var(--rc-app-bar-shadow,none);--_rc-app-bar-collapse-distance:0px;--_rc-app-bar-collapse-offset:0px;--rc-app-bar-collapse-progress:0;--_rc-app-bar-edge-size:0px;--_rc-app-bar-expanded-opacity:1;--_rc-app-bar-expanded-size:0px;transition:translate var(--rc-app-bar-transition-duration,.2s) ease;display:block;container-type:inline-size}:host([data-hidden]){translate:0 -100%}#root{grid-template-columns:auto minmax(0,1fr) auto;grid-template-rows:minmax(var(--rc-app-bar-compact-min-height,3rem), auto) 0;align-items:center;column-gap:var(--rc-app-bar-gap,.5em);padding-inline:var(--rc-app-bar-padding-inline,.75em);background:inherit;color:inherit;display:grid}:host([center-symmetric]) #root[data-has-center]{grid-template-columns:var(--_rc-app-bar-edge-size) minmax(0, 1fr) auto minmax(0, 1fr) var(--_rc-app-bar-edge-size)}#leading,#center,#trailing{align-items:center;min-inline-size:0;display:flex}#leading{grid-area:1/1}#title{grid-area:1/2;min-inline-size:0;overflow:clip}#leading.empty+#title{padding-inline-start:var(--rc-app-bar-title-start-padding,0px)}:host(:not([variant=expanded])) #title ::slotted(*),:host([variant=expanded][data-collapsed]) #title ::slotted(*){font-size:var(--rc-app-bar-title-font-size,inherit)}:host([variant=expanded]:not([data-collapsed])) #title ::slotted(*){font-size:var(--rc-app-bar-expanded-title-font-size,inherit)}#center{inline-size:min(100%, var(--rc-app-bar-center-max-inline-size,100%));grid-area:1/2;justify-self:center}#trailing{grid-area:1/3;justify-self:end}:host([center-symmetric]) #root[data-has-center] #center{grid-column:3;inline-size:auto}:host([center-symmetric]) #root[data-has-center] #trailing{grid-column:5}.empty{visibility:hidden;pointer-events:none}:host([variant=expanded]:not([data-collapsed])) #root{grid-template-rows:minmax(var(--rc-app-bar-compact-min-height,3rem), auto) var(--_rc-app-bar-expanded-size)}:host([variant=expanded]:not([data-collapsed])) #title{padding-block:var(--rc-app-bar-expanded-padding-block,.75em);translate:0 var(--_rc-app-bar-collapse-offset);opacity:var(--_rc-app-bar-expanded-opacity);grid-area:2/1/auto/-1;align-self:start}:host([variant=expanded][data-collapsed]) #title{animation:rc-app-bar-title-in var(--rc-app-bar-transition-duration,.2s) ease}#scroll-shadow{inline-size:calc(100% + 2 * var(--rc-app-bar-padding-inline,.75em));margin-inline:calc(var(--rc-app-bar-padding-inline,.75em) * -1);border-block-end:1px solid #0000;grid-area:3/1/auto/-1;align-self:end}:host([data-scrolled]) #scroll-shadow{border-block-end:var(--rc-app-bar-scroll-divider,1px solid GrayText)}@keyframes rc-app-bar-title-in{0%{opacity:0}}@media (prefers-reduced-motion:reduce){:host{transition-duration:0s}:host([variant=expanded][data-collapsed]) #title{animation-duration:70ms}}@container (inline-size<=480px){:host([center-symmetric]) #root[data-has-center]{grid-template-columns:auto 0 minmax(0,1fr) 0 auto}:host([center-symmetric]) #root[data-has-center] #center{justify-content:flex-end;justify-self:stretch;inline-size:auto}}`;
6
+ var w = Object.defineProperty, P = Object.getOwnPropertyDescriptor, o = (u, e, t, s) => {
7
+ for (var l = s > 1 ? void 0 : s ? P(e, t) : e, a = u.length - 1, r; a >= 0; a--)
8
+ (r = u[a]) && (l = (s ? r(e, t, l) : r(l)) || l);
9
+ return s && l && w(e, t, l), l;
10
+ };
11
+ const p = class p extends S {
12
+ constructor() {
13
+ super(...arguments), this.variant = "compact", this.centerSymmetric = !1, this.scrollBehavior = "pinned", this.scrollTarget = null, this.scrollThreshold = 4, this.hideDistance = 32, this._scrolled = void 0, this._hideTravel = 0, this._observedScrolled = !1, this._hasLeading = !1, this._hasCenter = !1, this._hasTrailing = !1, this._collapsed = !1, this._hidden = !1, this._collapseDistanceHostCssPx = 0, this._collapseOffsetHostCssPx = 0, this._collapseProgress = 0, this._reducedMotion = typeof window < "u" ? window.matchMedia("(prefers-reduced-motion: reduce)") : null, this._internals = this.attachInternals(), this._resizeObserver = null, this._hostResizeObserver = null, this._blockSize = 0, this._$geometryTarget = null, this._layoutMeasure = new T(this), this._scroll = new O(this, {
14
+ target: () => this._resolveScrollTarget(),
15
+ threshold: this.scrollThreshold,
16
+ initialEvaluation: "frame",
17
+ disabled: !0,
18
+ onChange: (e) => {
19
+ this._observedScrolled = e, this._syncVisualState(), this.dispatchEvent(
20
+ new CustomEvent("rc-app-bar-scroll", {
21
+ bubbles: !0,
22
+ composed: !0,
23
+ detail: { scrolled: e }
24
+ })
25
+ );
26
+ },
27
+ onScroll: (e, t) => this._onObservedScroll(e, t)
28
+ }), this._onFocusIn = () => {
29
+ this._hideTravel = 0, this._setHidden(!1);
30
+ };
31
+ }
32
+ get scrolled() {
33
+ return this._scrolled ?? this._observedScrolled;
34
+ }
35
+ set scrolled(e) {
36
+ const t = this.scrolled;
37
+ this._scrolled = e, this._syncScrollObserver(), this._syncVisualState(), this.requestUpdate("scrolled", t);
38
+ }
39
+ /** Whether the expanded title row is currently collapsed. */
40
+ get collapsed() {
41
+ return this._collapsed;
42
+ }
43
+ connectedCallback() {
44
+ super.connectedCallback(), this.addEventListener("focusin", this._onFocusIn), this._connectResizeObserver(), this.hasUpdated && (this._queueLayoutMeasure(), this._syncGeometryOutputs());
45
+ }
46
+ disconnectedCallback() {
47
+ super.disconnectedCallback(), this.removeEventListener("focusin", this._onFocusIn), this._resizeObserver?.disconnect(), this._cancelQueuedLayoutMeasure(), this._syncGeometryOutputs();
48
+ }
49
+ willUpdate(e) {
50
+ (e.has("scrollTarget") || e.has("scrollThreshold") || e.has("scrollBehavior")) && this._syncScrollObserver(), (e.has("variant") || e.has("scrollBehavior")) && this._syncVisualState();
51
+ }
52
+ firstUpdated() {
53
+ this._observeLayout(), this._queueLayoutMeasure(), this._syncScrollObserver(), this._syncVisualState(), this._syncGeometryOutputs();
54
+ }
55
+ updated(e) {
56
+ this._observeLayout(), (e.has("variant") || e.has("centerSymmetric") || e.has("_hasLeading") || e.has("_hasCenter") || e.has("_hasTrailing")) && this._queueLayoutMeasure(), (e.has("scrollTarget") || e.has("scrollBehavior")) && this._syncGeometryOutputs(), this._syncStateOutputs();
57
+ }
58
+ _connectResizeObserver() {
59
+ "ResizeObserver" in globalThis && (this._resizeObserver ??= new ResizeObserver(() => this._queueLayoutMeasure()), this._observeLayout());
60
+ }
61
+ _observeLayout() {
62
+ this._resizeObserver && (this._resizeObserver.disconnect(), ["#leading", "#title", "#center", "#trailing"].forEach((e) => {
63
+ const t = this.shadowRoot?.querySelector(e);
64
+ t && this._resizeObserver?.observe(t);
65
+ }));
66
+ }
67
+ _measureLayout() {
68
+ const e = this.shadowRoot?.querySelector("#leading"), t = this.shadowRoot?.querySelector("#title"), s = this.shadowRoot?.querySelector("#trailing");
69
+ if (!e || !t || !s)
70
+ return;
71
+ const a = this.variant === "expanded" && !this._collapsed ? t.offsetHeight : 0, r = a > 0 ? getComputedStyle(t) : null, y = r ? Number.parseFloat(r.paddingBlockStart) : 0, v = r ? Number.parseFloat(r.paddingBlockEnd) : 0, _ = a > 0 ? t.offsetTop : 0;
72
+ if (this.centerSymmetric) {
73
+ const h = Math.max(e.offsetWidth, s.offsetWidth);
74
+ this._setGeometryProperty("--_rc-app-bar-edge-size", `${h}px`);
75
+ }
76
+ if (r) {
77
+ const h = y + v, m = Math.max(a - h, 0), b = Math.max(_, m);
78
+ this._collapseDistanceHostCssPx = a, this._collapseOffsetHostCssPx = _ - (b - m) / 2, this._setGeometryProperty("--_rc-app-bar-collapse-distance", `${a}px`), this._applyCollapseGeometry();
79
+ }
80
+ }
81
+ _queueLayoutMeasure() {
82
+ this._layoutMeasure.schedule(() => this._measureLayout());
83
+ }
84
+ _cancelQueuedLayoutMeasure() {
85
+ this._layoutMeasure.cancel();
86
+ }
87
+ _syncScrollObserver() {
88
+ this._scroll.setOptions({
89
+ threshold: this.scrollThreshold,
90
+ disabled: this._scrolled !== void 0 || this._resolveScrollTarget() === null
91
+ });
92
+ }
93
+ _resolveScrollTarget() {
94
+ const e = this.scrollTarget;
95
+ if (e == null)
96
+ return null;
97
+ if (typeof e != "string")
98
+ return e;
99
+ if (e === "window")
100
+ return window;
101
+ try {
102
+ return this.ownerDocument?.querySelector(e) ?? null;
103
+ } catch {
104
+ return null;
105
+ }
106
+ }
107
+ _onObservedScroll(e, t) {
108
+ if (this._scrolled === void 0) {
109
+ if (this.scrollBehavior === "collapse" && this.variant === "expanded") {
110
+ if (this._collapseDistanceHostCssPx <= 0)
111
+ return;
112
+ const s = this._resolveScrollTarget(), l = s instanceof Element && s !== this.ownerDocument.scrollingElement ? g(s) : 1, a = e * l / g(this);
113
+ let r = Math.min(Math.max(a / this._collapseDistanceHostCssPx, 0), 1);
114
+ this._reducedMotion?.matches ? r = e > this.scrollThreshold ? 1 : 0 : r = r >= 0.999 ? 1 : r, this._setCollapseProgress(r);
115
+ } else
116
+ this._setCollapseProgress(0);
117
+ this.scrollBehavior !== "hide" ? (this._hideTravel = 0, this._setHidden(!1)) : e <= this.scrollThreshold ? (this._hideTravel = 0, this._setHidden(!1)) : this.matches(":focus-within") ? (this._hideTravel = 0, this._setHidden(!1)) : t !== 0 && (this._hideTravel = Math.sign(t) === Math.sign(this._hideTravel) ? this._hideTravel + t : t, Math.abs(this._hideTravel) >= this.hideDistance && this._setHidden(this._hideTravel > 0));
118
+ }
119
+ }
120
+ _syncVisualState() {
121
+ if (this._scrolled === void 0) {
122
+ (this.scrollBehavior !== "collapse" || this.variant !== "expanded") && this._setCollapseProgress(0), this.scrollBehavior !== "hide" && this._setHidden(!1);
123
+ return;
124
+ }
125
+ const e = this.variant === "expanded" && this.scrollBehavior === "collapse";
126
+ this._setCollapseProgress(e && this.scrolled ? 1 : 0), this._setHidden(!1);
127
+ }
128
+ _setCollapseProgress(e) {
129
+ this._collapseProgress = e, this.style.setProperty("--rc-app-bar-collapse-progress", `${e}`), this._applyCollapseGeometry();
130
+ const t = e >= 1;
131
+ t !== this._collapsed && (this._collapsed = t, this.toggleAttribute("data-collapsed", t), this._setCustomState("collapsed", t), this._queueLayoutMeasure());
132
+ }
133
+ _applyCollapseGeometry() {
134
+ const e = this._collapseOffsetHostCssPx * this._collapseProgress, t = this._collapseDistanceHostCssPx * (1 - this._collapseProgress);
135
+ this._setGeometryProperty("--_rc-app-bar-collapse-offset", `${-e}px`), this._setGeometryProperty("--_rc-app-bar-expanded-size", `${t}px`), this._setGeometryProperty("--_rc-app-bar-expanded-opacity", `${1 - this._collapseProgress}`);
136
+ }
137
+ _setGeometryProperty(e, t) {
138
+ this.style.getPropertyValue(e) !== t && this.style.setProperty(e, t);
139
+ }
140
+ _setHidden(e) {
141
+ e !== this._hidden && (this._hidden = e, this.toggleAttribute("data-hidden", e), this._setCustomState("hidden", e), this._writeGeometryOutputs());
142
+ }
143
+ /**
144
+ * Publishes geometry onto the scroll target while the bar can hide, and
145
+ * removes it from a target the bar no longer publishes to.
146
+ */
147
+ _syncGeometryOutputs() {
148
+ const e = this.isConnected && this.scrollBehavior === "hide" ? this._resolveGeometryTarget() : null;
149
+ if (e !== this._$geometryTarget && (this._$geometryTarget?.style.removeProperty("--rc-app-bar-block-size"), this._$geometryTarget?.style.removeProperty("--rc-app-bar-visible-block-size"), this._$geometryTarget = e), !e) {
150
+ this._hostResizeObserver?.disconnect();
151
+ return;
152
+ }
153
+ !this._hostResizeObserver && "ResizeObserver" in globalThis && (this._hostResizeObserver = new ResizeObserver(([t]) => {
154
+ this._blockSize = t?.borderBoxSize?.[0]?.blockSize ?? this._blockSize, this._writeGeometryOutputs();
155
+ })), this._hostResizeObserver?.observe(this), this._writeGeometryOutputs();
156
+ }
157
+ _resolveGeometryTarget() {
158
+ const e = this._resolveScrollTarget();
159
+ return e instanceof HTMLElement ? e : e === null || e instanceof Element ? null : this.ownerDocument.documentElement;
160
+ }
161
+ _writeGeometryOutputs() {
162
+ const e = this._$geometryTarget;
163
+ if (!e)
164
+ return;
165
+ const t = `${this._blockSize}px`;
166
+ e.style.setProperty("--rc-app-bar-block-size", t), e.style.setProperty("--rc-app-bar-visible-block-size", this._hidden ? "0px" : t);
167
+ }
168
+ _syncStateOutputs() {
169
+ this.toggleAttribute("data-scrolled", this.scrolled), this._setCustomState("scrolled", this.scrolled), this.toggleAttribute("data-collapsed", this._collapsed), this.toggleAttribute("data-hidden", this._hidden);
170
+ }
171
+ _setCustomState(e, t) {
172
+ this._internals.states && (t ? this._internals.states.add(e) : this._internals.states.delete(e));
173
+ }
174
+ _onSlotChange(e) {
175
+ const t = e.target, s = t.assignedElements({ flatten: !0 }).length > 0;
176
+ switch (t.name) {
177
+ case "leading":
178
+ this._hasLeading = s;
179
+ break;
180
+ case "center":
181
+ this._hasCenter = s;
182
+ break;
183
+ case "trailing":
184
+ this._hasTrailing = s;
185
+ break;
186
+ }
187
+ this._queueLayoutMeasure();
188
+ }
189
+ render() {
190
+ return z`
191
+ <div id="root" part="root" data-has-center=${this._hasCenter ? "" : x}>
192
+ <div id="leading" part="leading" class=${d({ empty: !this._hasLeading })}>
193
+ <slot name="leading" @slotchange=${this._onSlotChange}></slot>
194
+ </div>
195
+ <div id="title" part="title">
196
+ <slot @slotchange=${this._onSlotChange}></slot>
197
+ </div>
198
+ <div id="center" part="center" class=${d({ empty: !this._hasCenter })}>
199
+ <slot name="center" @slotchange=${this._onSlotChange}></slot>
200
+ </div>
201
+ <div id="trailing" part="trailing" class=${d({ empty: !this._hasTrailing })}>
202
+ <slot name="trailing" @slotchange=${this._onSlotChange}></slot>
203
+ </div>
204
+ <div id="scroll-shadow" part="scroll-shadow"></div>
205
+ </div>
206
+ `;
207
+ }
208
+ };
209
+ p.styles = [C];
210
+ let i = p;
211
+ o([
212
+ n({ type: String, reflect: !0 })
213
+ ], i.prototype, "variant", 2);
214
+ o([
215
+ n({ type: Boolean, attribute: "center-symmetric", reflect: !0 })
216
+ ], i.prototype, "centerSymmetric", 2);
217
+ o([
218
+ n({ type: String, attribute: "scroll-behavior", reflect: !0 })
219
+ ], i.prototype, "scrollBehavior", 2);
220
+ o([
221
+ n({ attribute: "scroll-target" })
222
+ ], i.prototype, "scrollTarget", 2);
223
+ o([
224
+ n({ type: Number, attribute: "scroll-threshold" })
225
+ ], i.prototype, "scrollThreshold", 2);
226
+ o([
227
+ n({ type: Number, attribute: "hide-distance" })
228
+ ], i.prototype, "hideDistance", 2);
229
+ o([
230
+ c()
231
+ ], i.prototype, "_observedScrolled", 2);
232
+ o([
233
+ c()
234
+ ], i.prototype, "_hasLeading", 2);
235
+ o([
236
+ c()
237
+ ], i.prototype, "_hasCenter", 2);
238
+ o([
239
+ c()
240
+ ], i.prototype, "_hasTrailing", 2);
241
+ o([
242
+ n({ attribute: !1 })
243
+ ], i.prototype, "scrolled", 1);
244
+ export {
245
+ i as R
246
+ };
247
+ //# sourceMappingURL=rc-app-bar-DMECo03s.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rc-app-bar-DMECo03s.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 box-shadow: var(--rc-app-bar-shadow, none);\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 /*\n * Split by what actually moves: the host's own transition is translate\n * (the bar hiding/showing on scroll), which is spatial and goes fully to\n * zero. The title's animation is an opacity fade-in, which is effects\n * motion and is kept, just shortened, rather than zeroed along with it\n * the way one shared transition-duration/animation-duration sweep would.\n */\n @media (prefers-reduced-motion: reduce) {\n :host {\n transition-duration: 0s;\n }\n\n :host([variant='expanded'][data-collapsed]) #title {\n animation-duration: 70ms;\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 cssZoom,\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 * A hidden bar reveals itself when focus moves into it and stays visible\n * while it contains focus.\n *\n * With `scroll-behavior=\"hide\"`, the bar also publishes its geometry onto its\n * scroll target, the element it observes (`document.documentElement` for\n * `window`): `--rc-app-bar-block-size` is its measured block size and\n * `--rc-app-bar-visible-block-size` is the same value, or `0px` while hidden.\n * Hiding only translates the bar, so a layout wins the space back by letting\n * the scroll container run under the bar, reserving\n * `var(--rc-app-bar-block-size)` as its block-start padding and scroll\n * padding. Sticky offsets are measured inside that padding, so a sticky\n * descendant pins at `calc(var(--rc-app-bar-visible-block-size) -\n * var(--rc-app-bar-block-size))`, while a fixed descendant of a wrapper\n * without that padding pins at `var(--rc-app-bar-visible-block-size)`. These\n * are read-only outputs: the\n * bar overwrites them on every size or visibility change and removes them\n * when it stops hiding, changes target, or disconnects.\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 hide-distance - With `scroll-behavior=\"hide\"`, how far in px the target must scroll in\n * one direction before the bar hides or reveals. Defaults to `32`.\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-shadow=none] - Bar box shadow\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-block-size - Read-only output on the scroll target in hide mode: the\n * bar's measured block size.\n * @cssprop --rc-app-bar-visible-block-size - Read-only output on the scroll target in hide mode:\n * the bar's block size while shown, `0px` while hidden.\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 /**\n * With `scroll-behavior=\"hide\"`, how far in px the target must scroll in one\n * direction before the bar hides or reveals, so a small reversal while\n * reading or a fling settling does not toggle it. Within `scrollThreshold`\n * of the top the bar always shows.\n */\n @property({ type: Number, attribute: 'hide-distance' })\n hideDistance = 32;\n\n private _scrolled: boolean | undefined = undefined;\n\n /** Signed scroll travel since the last change of direction, in hide mode. */\n private _hideTravel = 0;\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 _collapseDistanceHostCssPx = 0;\n\n private _collapseOffsetHostCssPx = 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 _hostResizeObserver: ResizeObserver | null = null;\n\n private _blockSize = 0;\n\n private _$geometryTarget: HTMLElement | 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 initialEvaluation: 'frame',\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.addEventListener('focusin', this._onFocusIn);\n this._connectResizeObserver();\n\n if (this.hasUpdated) {\n this._queueLayoutMeasure();\n this._syncGeometryOutputs();\n }\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('focusin', this._onFocusIn);\n this._resizeObserver?.disconnect();\n this._cancelQueuedLayoutMeasure();\n this._syncGeometryOutputs();\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 this._syncGeometryOutputs();\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 if (changed.has('scrollTarget') || changed.has('scrollBehavior')) {\n this._syncGeometryOutputs();\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._collapseDistanceHostCssPx = nextDistance;\n this._collapseOffsetHostCssPx = 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(scrollTopCssPx: number, deltaCssPx: number): void {\n if (this._scrolled !== undefined) {\n return;\n }\n\n if (this.scrollBehavior === 'collapse' && this.variant === 'expanded') {\n if (this._collapseDistanceHostCssPx <= 0) {\n return;\n }\n\n const target = this._resolveScrollTarget();\n const targetZoom =\n target instanceof Element && target !== this.ownerDocument.scrollingElement\n ? cssZoom(target)\n : 1;\n const scrollTopHostCssPx = (scrollTopCssPx * targetZoom) / cssZoom(this);\n let progress = Math.min(Math.max(scrollTopHostCssPx / this._collapseDistanceHostCssPx, 0), 1);\n\n if (this._reducedMotion?.matches) {\n progress = scrollTopCssPx > 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 this._hideTravel = 0;\n this._setHidden(false);\n } else if (scrollTopCssPx <= this.scrollThreshold) {\n this._hideTravel = 0;\n this._setHidden(false);\n } else if (this.matches(':focus-within')) {\n this._hideTravel = 0;\n this._setHidden(false);\n } else if (deltaCssPx !== 0) {\n // A change of direction starts the count again.\n this._hideTravel =\n Math.sign(deltaCssPx) === Math.sign(this._hideTravel)\n ? this._hideTravel + deltaCssPx\n : deltaCssPx;\n\n if (Math.abs(this._hideTravel) >= this.hideDistance) {\n this._setHidden(this._hideTravel > 0);\n }\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._collapseOffsetHostCssPx * this._collapseProgress;\n const remainingRow = this._collapseDistanceHostCssPx * (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 /** Reveal the bar and start fresh after focus enters it. */\n private readonly _onFocusIn = (): void => {\n this._hideTravel = 0;\n this._setHidden(false);\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 this._writeGeometryOutputs();\n }\n\n /**\n * Publishes geometry onto the scroll target while the bar can hide, and\n * removes it from a target the bar no longer publishes to.\n */\n private _syncGeometryOutputs(): void {\n const $target =\n this.isConnected && this.scrollBehavior === 'hide' ? this._resolveGeometryTarget() : null;\n\n if ($target !== this._$geometryTarget) {\n this._$geometryTarget?.style.removeProperty('--rc-app-bar-block-size');\n this._$geometryTarget?.style.removeProperty('--rc-app-bar-visible-block-size');\n this._$geometryTarget = $target;\n }\n\n if (!$target) {\n this._hostResizeObserver?.disconnect();\n\n return;\n }\n\n if (!this._hostResizeObserver && 'ResizeObserver' in globalThis) {\n this._hostResizeObserver = new ResizeObserver(([entry]) => {\n this._blockSize = entry?.borderBoxSize?.[0]?.blockSize ?? this._blockSize;\n this._writeGeometryOutputs();\n });\n }\n\n this._hostResizeObserver?.observe(this);\n this._writeGeometryOutputs();\n }\n\n private _resolveGeometryTarget(): HTMLElement | null {\n const target = this._resolveScrollTarget();\n\n if (target instanceof HTMLElement) {\n return target;\n }\n\n // A window or document target scrolls the root element; another element has no style to write.\n return target === null || target instanceof Element ? null : this.ownerDocument.documentElement;\n }\n\n private _writeGeometryOutputs(): void {\n const $target = this._$geometryTarget;\n\n if (!$target) {\n return;\n }\n\n const blockSize = `${this._blockSize}px`;\n\n $target.style.setProperty('--rc-app-bar-block-size', blockSize);\n $target.style.setProperty('--rc-app-bar-visible-block-size', this._hidden ? '0px' : blockSize);\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","scrollTopCssPx","deltaCssPx","targetZoom","cssZoom","scrollTopHostCssPx","progress","collapse","collapsed","offset","remainingRow","name","hidden","$target","entry","blockSize","active","$slot","hasContent","html","nothing","classMap","RCAppBar","__decorateClass","property","state"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { R as e } from "./rc-app-bar-CPkULic-.js";
1
+ import { R as e } from "./rc-app-bar-DMECo03s.js";
2
2
  customElements.get("rc-app-bar") || customElements.define("rc-app-bar", e);
3
3
  export {
4
4
  e as RCAppBar
@@ -1,4 +1,4 @@
1
- import { R as a } from "./rc-app-bar-CPkULic-.js";
1
+ import { R as a } from "./rc-app-bar-DMECo03s.js";
2
2
  export {
3
3
  a as RCAppBar
4
4
  };
@@ -1 +1 @@
1
- export * from './rc-app-bar';
1
+ export * from './rc-app-bar.js';
@@ -30,12 +30,33 @@ export interface RCAppBarScrollDetail {
30
30
  * ElementInternals custom states. These are computed outputs, not settable
31
31
  * attributes.
32
32
  *
33
+ * A hidden bar reveals itself when focus moves into it and stays visible
34
+ * while it contains focus.
35
+ *
36
+ * With `scroll-behavior="hide"`, the bar also publishes its geometry onto its
37
+ * scroll target, the element it observes (`document.documentElement` for
38
+ * `window`): `--rc-app-bar-block-size` is its measured block size and
39
+ * `--rc-app-bar-visible-block-size` is the same value, or `0px` while hidden.
40
+ * Hiding only translates the bar, so a layout wins the space back by letting
41
+ * the scroll container run under the bar, reserving
42
+ * `var(--rc-app-bar-block-size)` as its block-start padding and scroll
43
+ * padding. Sticky offsets are measured inside that padding, so a sticky
44
+ * descendant pins at `calc(var(--rc-app-bar-visible-block-size) -
45
+ * var(--rc-app-bar-block-size))`, while a fixed descendant of a wrapper
46
+ * without that padding pins at `var(--rc-app-bar-visible-block-size)`. These
47
+ * are read-only outputs: the
48
+ * bar overwrites them on every size or visibility change and removes them
49
+ * when it stops hiding, changes target, or disconnects.
50
+ *
33
51
  * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-app-bar rc-app-bar docs}
34
52
  * @see {@link https://m3.material.io/components/top-app-bar/overview Material 3 Top app bar}
35
53
  *
36
54
  * @slot leading - Leading navigation or controls; accepts multiple children
37
55
  * @slot - The single title region; may contain title and subtitle markup
38
- * @slot center - Content kept at the exact horizontal center, such as search
56
+ * @slot center - Content such as search, kept within the flexible middle column between
57
+ * leading and trailing. Fills that column by default, capped and self-centered within it via
58
+ * `--rc-app-bar-center-max-inline-size`; add `center-symmetric` for exact viewport centering
59
+ * regardless of asymmetric leading/trailing content instead.
39
60
  * @slot trailing - Trailing action controls
40
61
  * @fires rc-app-bar-scroll - When observed scroll state crosses the threshold;
41
62
  * `detail: { scrolled }`
@@ -43,16 +64,29 @@ export interface RCAppBarScrollDetail {
43
64
  * @attr scroll-behavior - Visual response to observed scrolling: `pinned`, `collapse`, or `hide`.
44
65
  * @attr scroll-target - CSS selector (or `"window"`) for the scroll container to observe.
45
66
  * @attr scroll-threshold - Scroll offset in px past which the bar is scrolled (strict `>`).
67
+ * @attr hide-distance - With `scroll-behavior="hide"`, how far in px the target must scroll in
68
+ * one direction before the bar hides or reveals. Defaults to `32`.
69
+ * @attr center-symmetric - Opt-in: mirrors leading/trailing edge widths so `slot="center"`
70
+ * content stays exactly viewport-centered. Default: fills the flexible middle column instead,
71
+ * centered within available space once capped by `--rc-app-bar-center-max-inline-size`.
46
72
  * @cssprop [--rc-app-bar-bg=Canvas] - Bar background
47
73
  * @cssprop [--rc-app-bar-color=CanvasText] - Bar text color
74
+ * @cssprop [--rc-app-bar-shadow=none] - Bar box shadow
48
75
  * @cssprop [--rc-app-bar-compact-min-height=3rem] - Compact row minimum height
49
76
  * @cssprop [--rc-app-bar-expanded-padding-block=0.75em] - Expanded title padding
50
77
  * @cssprop [--rc-app-bar-padding-inline=0.75em] - Horizontal padding
51
78
  * @cssprop [--rc-app-bar-gap=0.5em] - Gap between regions
79
+ * @cssprop [--rc-app-bar-center-max-inline-size=100%] - Max width of `slot="center"` content
80
+ * before it centers within the available space instead of filling it. No effect when
81
+ * `center-symmetric` is set.
52
82
  * @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)
53
83
  * @cssprop [--rc-app-bar-transition-duration=200ms] - Endpoint and hide duration
54
84
  * @cssprop [--rc-app-bar-scroll-divider=1px solid GrayText] - Scrolled divider
55
85
  * @cssprop [--rc-app-bar-collapse-progress=0] - Collapse animation progress 0–1; read-only
86
+ * @cssprop --rc-app-bar-block-size - Read-only output on the scroll target in hide mode: the
87
+ * bar's measured block size.
88
+ * @cssprop --rc-app-bar-visible-block-size - Read-only output on the scroll target in hide mode:
89
+ * the bar's block size while shown, `0px` while hidden.
56
90
  * @cssprop [--rc-app-bar-title-font-size] - Compact-row title font size (opt-in; inherits when unset)
57
91
  * @cssprop [--rc-app-bar-expanded-title-font-size] - Expanded-row title font size (opt-in)
58
92
  * @csspart root - The grid container
@@ -66,6 +100,15 @@ export declare class RCAppBar extends LitElement {
66
100
  static styles: import('lit').CSSResult[];
67
101
  /** Structural variant. `expanded` adds a flexible title row. */
68
102
  variant: RCAppBarVariant;
103
+ /**
104
+ * Opt-in: mirrors the leading/trailing edge widths so `slot="center"`
105
+ * content stays exactly viewport-centered regardless of asymmetric side
106
+ * content. Default (absent): center content fills the flexible middle
107
+ * column like a plain title, capped and self-centered within it via
108
+ * `--rc-app-bar-center-max-inline-size` -- centered within the available
109
+ * space between leading and trailing, not mirrored to the viewport.
110
+ */
111
+ centerSymmetric: boolean;
69
112
  /** Visual response to observed scrolling. */
70
113
  scrollBehavior: RCAppBarScrollBehavior;
71
114
  /**
@@ -75,19 +118,31 @@ export declare class RCAppBar extends LitElement {
75
118
  scrollTarget: ScrollObserverTarget | string | null;
76
119
  /** Scroll offset in px past which the bar is scrolled (strict `>`). */
77
120
  scrollThreshold: number;
121
+ /**
122
+ * With `scroll-behavior="hide"`, how far in px the target must scroll in one
123
+ * direction before the bar hides or reveals, so a small reversal while
124
+ * reading or a fling settling does not toggle it. Within `scrollThreshold`
125
+ * of the top the bar always shows.
126
+ */
127
+ hideDistance: number;
78
128
  private _scrolled;
129
+ /** Signed scroll travel since the last change of direction, in hide mode. */
130
+ private _hideTravel;
79
131
  private _observedScrolled;
80
132
  private _hasLeading;
81
133
  private _hasCenter;
82
134
  private _hasTrailing;
83
135
  private _collapsed;
84
136
  private _hidden;
85
- private _collapseDistance;
86
- private _collapseOffsetDistance;
137
+ private _collapseDistanceHostCssPx;
138
+ private _collapseOffsetHostCssPx;
87
139
  private _collapseProgress;
88
140
  private readonly _reducedMotion;
89
141
  private _internals;
90
142
  private _resizeObserver;
143
+ private _hostResizeObserver;
144
+ private _blockSize;
145
+ private _$geometryTarget;
91
146
  private readonly _layoutMeasure;
92
147
  private readonly _scroll;
93
148
  /**
@@ -115,10 +170,19 @@ export declare class RCAppBar extends LitElement {
115
170
  private _setCollapseProgress;
116
171
  private _applyCollapseGeometry;
117
172
  private _setGeometryProperty;
173
+ /** Reveal the bar and start fresh after focus enters it. */
174
+ private readonly _onFocusIn;
118
175
  private _setHidden;
176
+ /**
177
+ * Publishes geometry onto the scroll target while the bar can hide, and
178
+ * removes it from a target the bar no longer publishes to.
179
+ */
180
+ private _syncGeometryOutputs;
181
+ private _resolveGeometryTarget;
182
+ private _writeGeometryOutputs;
119
183
  private _syncStateOutputs;
120
184
  private _setCustomState;
121
185
  private _onSlotChange;
122
- protected render(): import('lit').TemplateResult<1>;
186
+ protected render(): import('lit-html').TemplateResult<1>;
123
187
  }
124
188
  export default RCAppBar;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.5.0",
6
+ "version": "0.7.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,10 @@
45
45
  "test:browser:firefox": "vitest --run --project=firefox"
46
46
  },
47
47
  "dependencies": {
48
- "@rcarls/rc-common": "0.5.0"
48
+ "@rcarls/rc-common": "0.7.0"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@custom-elements-manifest/analyzer": "0.11.0",
52
- "@rcarls/rc-search-bar": "0.5.0",
53
52
  "@vitest/browser-playwright": "4.1.5",
54
53
  "lit": "^3.0.0",
55
54
  "playwright": "^1.56.0",