@rcarls/rc-app-bar 0.6.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,136 @@
1
1
  # @rcarls/rc-app-bar
2
2
 
3
+ ## 0.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 8d6edf2: With `scroll-behavior="hide"`, `rc-app-bar` now publishes read-only geometry onto its scroll
8
+ target: `--rc-app-bar-block-size`, its measured block size, and
9
+ `--rc-app-bar-visible-block-size`, the same value or `0px` while hidden. Hiding only translates
10
+ the bar, so a layout can now give its space back: stack the bar over the scroll container,
11
+ reserve the block size as the container's block-start padding and scroll padding, and pin
12
+ sticky content at the visible size minus the block size, since sticky offsets are measured
13
+ inside that padding. The bar removes both values when it stops hiding, changes
14
+ target, or disconnects.
15
+
16
+ The Material design guide documents this recipe and the compact-height patterns for landscape
17
+ phones: app bars that hide on scroll, side sheets instead of modal bottom sheets, full-screen
18
+ task dialogs, media capped by the pane's height, and single-row sticky chips.
19
+
20
+ - 079e025: Standardize component styling contracts for the breaking 0.7 release.
21
+
22
+ BREAKING CHANGE: Rename the Markdown editor's `--rme-*` properties to
23
+ `--rc-markdown-editor-*`, `--rc-app-bar-background` to `--rc-app-bar-bg`,
24
+ `--rc-textarea-radius` to `--rc-textarea-border-radius`, the transfer-list
25
+ `--rc-transfer-list-panel-*` properties to `--rc-transfer-list-listbox-*`,
26
+ `--rc-chip-group-webkit-scrollbar-display` to
27
+ `--rc-chip-group-scrollbar-display`, and `--rc-text` to `--rc-field-text`.
28
+ Compatibility aliases are intentionally not provided.
29
+
30
+ BREAKING CHANGE: Replace `--rc-select-chip-padding-inline` and
31
+ `--rc-combobox-chip-padding-inline` with explicit `*-padding-inline-start` and
32
+ `*-padding-inline-end` tokens. Generated removable chips now reserve the full
33
+ remove target and its edge offset, so their indicator cannot overlap label text.
34
+
35
+ Add canonical app-bar elevation, transfer-list listbox radius, and textarea
36
+ line-action tokens. Add logical `rc-chip` inline-padding properties so themes
37
+ can implement Material's icon-aware spacing without overriding authored child
38
+ styles. Make `rc-field` consume the shared semantic token layer,
39
+ and place the `rc-chip` and `rc-search-bar` light-DOM structural styles in the
40
+ `rc-base` cascade layer so normal consumer rules override them.
41
+
42
+ Prevent decorative, `aria-hidden` trailing list content from intercepting a
43
+ whole-row action target, and keep segmented-list item geometry from leaking
44
+ into nested standard lists.
45
+
46
+ Remove unused Material navigation-rail toggle tokens and obsolete list-item
47
+ theme tokens. Register the segmented-button private theme seam and enforce
48
+ token ownership, documentation, removed-name, selector-budget, and cascade
49
+ layer contracts through the component architecture audit.
50
+
51
+ - 6e548d9: Several components handle `prefers-reduced-motion: reduce` in their own
52
+ shadow styles, outside a theme's reach, and refine it the same way the theme
53
+ layer already does: spatial motion (`translate`, `scale`, `transform`,
54
+ `inline-size`, `block-size`) goes fully to zero, while effects motion (color,
55
+ opacity) shortens instead of disappearing.
56
+
57
+ `rc-app-bar` zeros its host's hide/show `translate` but shortens the
58
+ expanded title's fade-in. `rc-disclosure` keeps its panel's expand/collapse
59
+ zeroed, but its summary/content backstop for a theme-added transition now
60
+ shortens instead of zeroing it outright. `rc-list-item`'s row and
61
+ state-layer transition only color and opacity, so the whole sweep shortens.
62
+ `rc-fab-menu`'s popup mixes `scale` with opacity/overlay/display under one
63
+ shared duration; reduced motion now zeros the scale and shortens the rest.
64
+ `rc-switch`'s thumb mixes background-color with inline-size/block-size/
65
+ transform the same way; the icons and track, which each transition only one
66
+ kind of property, needed only the zero-or-shorten call. `rc-fab`'s
67
+ scroll-reveal is opacity/visibility only with no time-based duration to
68
+ shorten in its scroll-linked path, so reduced motion narrows the scroll
69
+ window instead of collapsing it to zero; its JS-transition fallback path
70
+ shortens the same fade rather than removing it. `rc-progress`'s determinate
71
+ fill transition, previously unguarded under reduced motion, is now zeroed;
72
+ its indeterminate loop, a continuous sweep with no meaningful shortened
73
+ form, stays fully stopped rather than shortened.
74
+
75
+ ### Patch Changes
76
+
77
+ - 6f1df83: A bar with `scroll-behavior="hide"` now hides or reveals only after its scroll target travels
78
+ `hide-distance` (32px by default) in one direction. It used to reveal on any upward scroll, so a
79
+ 1px reversal while reading or as a fling settled brought it back. Near the top it still always
80
+ shows. A hidden bar reveals itself when focus moves into it and stays visible until focus leaves.
81
+ - b0a63ef: Calculate expanded app-bar collapse progress in the bar's CSS coordinate space
82
+ when its scroll target and the bar have different effective CSS zoom.
83
+ - 5c006de: Ship component CSS minified. Package builds now run the CSS in Lit `css` styles
84
+ and light-DOM structural styles through Lightning CSS, removing comments and
85
+ whitespace while keeping source maps that resolve to each template. Rendered
86
+ styles are unchanged.
87
+
88
+ `@rcarls/rc-common` adds `cssText`, an identity tag that marks a plain CSS
89
+ string for minification. `rc-chip`, `rc-disclosure`, and `rc-accordion` now
90
+ depend on `@rcarls/rc-common` for it.
91
+
92
+ - a6553ff: Batch layout sampling into a shared animation-frame read phase so mounting a
93
+ large component route no longer alternates forced layout reads with component
94
+ writes. Closed anchored popups now skip placement work until they open, while
95
+ scroller boundaries, carousel positioning, flow state, and opted-in initial
96
+ scroll observation settle before the next paint.
97
+
98
+ Add `RafScheduler.schedulePhased()`, live `AnchorController.disabled` getters,
99
+ and the `ScrollObserverController.initialEvaluation` timing option.
100
+
101
+ - Updated dependencies [e3dfa59]
102
+ - Updated dependencies [50d5610]
103
+ - Updated dependencies [9ee769c]
104
+ - Updated dependencies [1179f24]
105
+ - Updated dependencies [595fe37]
106
+ - Updated dependencies [38cd00c]
107
+ - Updated dependencies [5c006de]
108
+ - Updated dependencies [a6553ff]
109
+ - Updated dependencies [2205478]
110
+ - Updated dependencies [4341311]
111
+ - Updated dependencies [899bb5e]
112
+ - Updated dependencies [25fcfe0]
113
+ - Updated dependencies [51f6403]
114
+ - Updated dependencies [9caca6b]
115
+ - Updated dependencies [b764a3c]
116
+ - Updated dependencies [54d9ead]
117
+ - Updated dependencies [b9175e9]
118
+ - Updated dependencies [c8b762b]
119
+ - Updated dependencies [55e1e7f]
120
+ - Updated dependencies [f1ca82d]
121
+ - Updated dependencies [b87f27b]
122
+ - Updated dependencies [32ebead]
123
+ - Updated dependencies [bfefedd]
124
+ - Updated dependencies [c130173]
125
+ - Updated dependencies [11680b6]
126
+ - Updated dependencies [223d36c]
127
+ - Updated dependencies [7b91a44]
128
+ - Updated dependencies [aa04ead]
129
+ - Updated dependencies [ac65b5b]
130
+ - Updated dependencies [afcfef8]
131
+ - Updated dependencies [11ef1ad]
132
+ - @rcarls/rc-common@0.7.0
133
+
3
134
  ## 0.6.0
4
135
 
5
136
  ### Minor Changes
package/README.md CHANGED
@@ -59,10 +59,54 @@ Scroll behaviors are exclusive:
59
59
  - `collapse` continuously shrinks an expanded title row over its measured
60
60
  height, then keeps the compact row visible.
61
61
  - `hide` hides the complete bar while scrolling down past `scroll-threshold`
62
- and reveals it when scrolling up or returning near the top.
62
+ and reveals it when scrolling up, returning near the top, or when focus
63
+ moves into the bar, so keyboard focus never lands off screen. The bar stays
64
+ visible while it contains focus. It hides or reveals only after the target
65
+ scrolls `hide-distance` (32px by default) in
66
+ one direction, so small reversals while reading or as a fling settles leave
67
+ it as it is.
63
68
 
64
69
  The component never consumes, stops, or rewrites the document's scroll.
65
70
 
71
+ `hide` only translates the bar, so on its own it frees no layout space. While
72
+ hiding, the bar publishes read-only geometry onto its scroll target:
73
+ `--rc-app-bar-block-size` (its measured block size) and
74
+ `--rc-app-bar-visible-block-size` (the same, or `0px` while hidden). Let the
75
+ scroll container run under the bar and reserve that size, so content scrolls
76
+ behind the bar and fills its space while it is hidden:
77
+
78
+ ```css
79
+ .screen {
80
+ display: grid;
81
+ grid-template: 'stack' 1fr / 1fr;
82
+ }
83
+
84
+ .screen > header,
85
+ .screen > .content {
86
+ grid-area: stack;
87
+ }
88
+
89
+ .screen > header {
90
+ z-index: 1;
91
+ align-self: start;
92
+ }
93
+
94
+ .content {
95
+ overflow-y: auto;
96
+ padding-block-start: var(--rc-app-bar-block-size, 4rem);
97
+ scroll-padding-block-start: var(--rc-app-bar-block-size, 4rem);
98
+ }
99
+
100
+ .content .sticky-filters {
101
+ position: sticky;
102
+ /* Sticky offsets are measured inside the scroller's padding. */
103
+ inset-block-start: calc(
104
+ var(--rc-app-bar-visible-block-size, 4rem) - var(--rc-app-bar-block-size, 4rem)
105
+ );
106
+ transition: inset-block-start 200ms ease;
107
+ }
108
+ ```
109
+
66
110
  ## Center-slot composition
67
111
 
68
112
  The optional `center` slot, useful for desktop controls or an
@@ -210,6 +254,7 @@ rc-app-bar.glass::part(root) {
210
254
  | --------------------------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
211
255
  | `--rc-app-bar-bg` | `Canvas` | Bar background |
212
256
  | `--rc-app-bar-color` | `CanvasText` | Bar text color |
257
+ | `--rc-app-bar-shadow` | `none` | Bar box shadow |
213
258
  | `--rc-app-bar-compact-min-height` | `3rem` | Compact row minimum height |
214
259
  | `--rc-app-bar-expanded-padding-block` | `0.75em` | Expanded title block padding |
215
260
  | `--rc-app-bar-padding-inline` | `0.75em` | Horizontal padding |
@@ -46,7 +46,7 @@
46
46
  "declarations": [
47
47
  {
48
48
  "kind": "class",
49
- "description": "App bar modeled after the Material 3 Top app bar, with leading, title, center, trailing\nregions and optional scroll behavior.\n\nThe element carries no landmark role. Consumers provide all controls and\nicons, and wrap page-level instances in `<header>` when a banner landmark is\nappropriate.\n\nScrolled state is dual-mode. Uncontrolled: set `scrollTarget` (or the\n`scroll-target` selector attribute) and the bar observes the container.\nControlled: assign `scrolled`; assigning `undefined` releases observation.\nHost writes are silent.\n\nEnvironment-driven state (scrolled, collapsed, hidden) is exposed as\n`data-scrolled`, `data-collapsed`, and `data-hidden` attributes with\nequivalent `:state(scrolled)`, `:state(collapsed)`, and `:state(hidden)`\nElementInternals custom states. These are computed outputs, not settable\nattributes.",
49
+ "description": "App bar modeled after the Material 3 Top app bar, with leading, title, center, trailing\nregions and optional scroll behavior.\n\nThe element carries no landmark role. Consumers provide all controls and\nicons, and wrap page-level instances in `<header>` when a banner landmark is\nappropriate.\n\nScrolled state is dual-mode. Uncontrolled: set `scrollTarget` (or the\n`scroll-target` selector attribute) and the bar observes the container.\nControlled: assign `scrolled`; assigning `undefined` releases observation.\nHost writes are silent.\n\nEnvironment-driven state (scrolled, collapsed, hidden) is exposed as\n`data-scrolled`, `data-collapsed`, and `data-hidden` attributes with\nequivalent `:state(scrolled)`, `:state(collapsed)`, and `:state(hidden)`\nElementInternals custom states. These are computed outputs, not settable\nattributes.\n\nA hidden bar reveals itself when focus moves into it and stays visible\nwhile it contains focus.\n\nWith `scroll-behavior=\"hide\"`, the bar also publishes its geometry onto its\nscroll 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.\nHiding only translates the bar, so a layout wins the space back by letting\nthe scroll container run under the bar, reserving\n`var(--rc-app-bar-block-size)` as its block-start padding and scroll\npadding. Sticky offsets are measured inside that padding, so a sticky\ndescendant pins at `calc(var(--rc-app-bar-visible-block-size) -\nvar(--rc-app-bar-block-size))`, while a fixed descendant of a wrapper\nwithout that padding pins at `var(--rc-app-bar-visible-block-size)`. These\nare read-only outputs: the\nbar overwrites them on every size or visibility change and removes them\nwhen it stops hiding, changes target, or disconnects.",
50
50
  "name": "RCAppBar",
51
51
  "cssProperties": [
52
52
  {
@@ -59,6 +59,11 @@
59
59
  "name": "--rc-app-bar-color",
60
60
  "default": "CanvasText"
61
61
  },
62
+ {
63
+ "description": "Bar box shadow",
64
+ "name": "--rc-app-bar-shadow",
65
+ "default": "none"
66
+ },
62
67
  {
63
68
  "description": "Compact row minimum height",
64
69
  "name": "--rc-app-bar-compact-min-height",
@@ -104,6 +109,14 @@
104
109
  "name": "--rc-app-bar-collapse-progress",
105
110
  "default": "0"
106
111
  },
112
+ {
113
+ "description": "Read-only output on the scroll target in hide mode: the bar's measured block size.",
114
+ "name": "--rc-app-bar-block-size"
115
+ },
116
+ {
117
+ "description": "Read-only output on the scroll target in hide mode: the bar's block size while shown, `0px` while hidden.",
118
+ "name": "--rc-app-bar-visible-block-size"
119
+ },
107
120
  {
108
121
  "description": "Compact-row title font size (opt-in; inherits when unset)",
109
122
  "name": "--rc-app-bar-title-font-size"
@@ -211,6 +224,16 @@
211
224
  "description": "Scroll offset in px past which the bar is scrolled (strict `>`).",
212
225
  "attribute": "scroll-threshold"
213
226
  },
227
+ {
228
+ "kind": "field",
229
+ "name": "hideDistance",
230
+ "type": {
231
+ "text": "number"
232
+ },
233
+ "default": "32",
234
+ "description": "With `scroll-behavior=\"hide\"`, how far in px the target must scroll in one\ndirection before the bar hides or reveals, so a small reversal while\nreading or a fling settling does not toggle it. Within `scrollThreshold`\nof the top the bar always shows.",
235
+ "attribute": "hide-distance"
236
+ },
214
237
  {
215
238
  "kind": "field",
216
239
  "name": "_scrolled",
@@ -220,6 +243,16 @@
220
243
  "privacy": "private",
221
244
  "default": "undefined"
222
245
  },
246
+ {
247
+ "kind": "field",
248
+ "name": "_hideTravel",
249
+ "type": {
250
+ "text": "number"
251
+ },
252
+ "privacy": "private",
253
+ "default": "0",
254
+ "description": "Signed scroll travel since the last change of direction, in hide mode."
255
+ },
223
256
  {
224
257
  "kind": "field",
225
258
  "name": "_observedScrolled",
@@ -276,7 +309,7 @@
276
309
  },
277
310
  {
278
311
  "kind": "field",
279
- "name": "_collapseDistance",
312
+ "name": "_collapseDistanceHostCssPx",
280
313
  "type": {
281
314
  "text": "number"
282
315
  },
@@ -285,7 +318,7 @@
285
318
  },
286
319
  {
287
320
  "kind": "field",
288
- "name": "_collapseOffsetDistance",
321
+ "name": "_collapseOffsetHostCssPx",
289
322
  "type": {
290
323
  "text": "number"
291
324
  },
@@ -321,6 +354,33 @@
321
354
  "privacy": "private",
322
355
  "default": "null"
323
356
  },
357
+ {
358
+ "kind": "field",
359
+ "name": "_hostResizeObserver",
360
+ "type": {
361
+ "text": "ResizeObserver | null"
362
+ },
363
+ "privacy": "private",
364
+ "default": "null"
365
+ },
366
+ {
367
+ "kind": "field",
368
+ "name": "_blockSize",
369
+ "type": {
370
+ "text": "number"
371
+ },
372
+ "privacy": "private",
373
+ "default": "0"
374
+ },
375
+ {
376
+ "kind": "field",
377
+ "name": "_$geometryTarget",
378
+ "type": {
379
+ "text": "HTMLElement | null"
380
+ },
381
+ "privacy": "private",
382
+ "default": "null"
383
+ },
324
384
  {
325
385
  "kind": "field",
326
386
  "name": "_layoutMeasure",
@@ -333,7 +393,7 @@
333
393
  "name": "_scroll",
334
394
  "privacy": "private",
335
395
  "readonly": true,
336
- "default": "new ScrollObserverController(this, { target: () => this._resolveScrollTarget(), threshold: this.scrollThreshold, disabled: true, onChange: (scrolled) => { this._observedScrolled = scrolled; this._syncVisualState(); this.dispatchEvent( new CustomEvent<RCAppBarScrollDetail>('rc-app-bar-scroll', { bubbles: true, composed: true, detail: { scrolled }, }), ); }, onScroll: (scrollTop, delta) => this._onObservedScroll(scrollTop, delta), })"
396
+ "default": "new ScrollObserverController(this, { target: () => this._resolveScrollTarget(), threshold: this.scrollThreshold, initialEvaluation: 'frame', disabled: true, onChange: (scrolled) => { this._observedScrolled = scrolled; this._syncVisualState(); this.dispatchEvent( new CustomEvent<RCAppBarScrollDetail>('rc-app-bar-scroll', { bubbles: true, composed: true, detail: { scrolled }, }), ); }, onScroll: (scrollTop, delta) => this._onObservedScroll(scrollTop, delta), })"
337
397
  },
338
398
  {
339
399
  "kind": "field",
@@ -433,13 +493,13 @@
433
493
  },
434
494
  "parameters": [
435
495
  {
436
- "name": "scrollTop",
496
+ "name": "scrollTopCssPx",
437
497
  "type": {
438
498
  "text": "number"
439
499
  }
440
500
  },
441
501
  {
442
- "name": "delta",
502
+ "name": "deltaCssPx",
443
503
  "type": {
444
504
  "text": "number"
445
505
  }
@@ -508,6 +568,13 @@
508
568
  }
509
569
  ]
510
570
  },
571
+ {
572
+ "kind": "field",
573
+ "name": "_onFocusIn",
574
+ "privacy": "private",
575
+ "readonly": true,
576
+ "description": "Reveal the bar and start fresh after focus enters it."
577
+ },
511
578
  {
512
579
  "kind": "method",
513
580
  "name": "_setHidden",
@@ -526,6 +593,37 @@
526
593
  }
527
594
  ]
528
595
  },
596
+ {
597
+ "kind": "method",
598
+ "name": "_syncGeometryOutputs",
599
+ "privacy": "private",
600
+ "return": {
601
+ "type": {
602
+ "text": "void"
603
+ }
604
+ },
605
+ "description": "Publishes geometry onto the scroll target while the bar can hide, and\nremoves it from a target the bar no longer publishes to."
606
+ },
607
+ {
608
+ "kind": "method",
609
+ "name": "_resolveGeometryTarget",
610
+ "privacy": "private",
611
+ "return": {
612
+ "type": {
613
+ "text": "HTMLElement | null"
614
+ }
615
+ }
616
+ },
617
+ {
618
+ "kind": "method",
619
+ "name": "_writeGeometryOutputs",
620
+ "privacy": "private",
621
+ "return": {
622
+ "type": {
623
+ "text": "void"
624
+ }
625
+ }
626
+ },
529
627
  {
530
628
  "kind": "method",
531
629
  "name": "_syncStateOutputs",
@@ -622,6 +720,15 @@
622
720
  "default": "4",
623
721
  "fieldName": "scrollThreshold"
624
722
  },
723
+ {
724
+ "description": "With `scroll-behavior=\"hide\"`, how far in px the target must scroll in one\ndirection before the bar hides or reveals, so a small reversal while\nreading or a fling settling does not toggle it. Within `scrollThreshold`\nof the top the bar always shows.",
725
+ "name": "hide-distance",
726
+ "type": {
727
+ "text": "number"
728
+ },
729
+ "default": "32",
730
+ "fieldName": "hideDistance"
731
+ },
625
732
  {
626
733
  "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
734
  "name": "center-symmetric",
@@ -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