@oicl/openbridge-webcomponents 2.0.0-next.172 → 2.0.0-next.173

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.
@@ -20028,6 +20028,43 @@ function deepActiveElement() {
20028
20028
  while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;
20029
20029
  return active;
20030
20030
  }
20031
+ /**
20032
+ * Whether `node` sits inside `root` in the composed tree.
20033
+ *
20034
+ * `Node.contains()` walks the DOM tree, where slotted light-DOM content is a
20035
+ * child of the host and not of the slot — so it answers no for exactly the
20036
+ * content a component projects into itself. This follows `assignedSlot` and
20037
+ * shadow hosts as well.
20038
+ */
20039
+ function composedContains(root, node) {
20040
+ let current = node;
20041
+ while (current) {
20042
+ if (current === root) return true;
20043
+ current = current.assignedSlot ?? current.parentNode ?? (current instanceof ShadowRoot ? current.host : null);
20044
+ }
20045
+ return false;
20046
+ }
20047
+ /**
20048
+ * Moves focus out of `hidden`, to the first fallback that will take it.
20049
+ *
20050
+ * Call it just before a region becomes `inert` or is taken out of the page.
20051
+ * The browser blurs whatever it hides, and focus lands on `<body>` a frame or
20052
+ * two later, so the next Tab press starts from the top of the document instead
20053
+ * of where the user was.
20054
+ *
20055
+ * Each candidate is tried and then checked, rather than inspected first: a
20056
+ * `disabled` button, a hidden one and an element with no tabindex all refuse
20057
+ * focus for different reasons, and the only reliable question is whether focus
20058
+ * actually left.
20059
+ */
20060
+ function releaseFocusBefore(hidden, ...fallbacks) {
20061
+ if (!composedContains(hidden, deepActiveElement())) return;
20062
+ for (const candidate of fallbacks) {
20063
+ if (!candidate) continue;
20064
+ candidate.focus();
20065
+ if (!composedContains(hidden, deepActiveElement())) return;
20066
+ }
20067
+ }
20031
20068
  function isTabbable(element) {
20032
20069
  if (!element.matches(TABBABLE_SELECTOR)) return false;
20033
20070
  if (element.tabIndex < 0) return false;
@@ -70665,6 +70702,9 @@ var accordion_card_default = i$7`* {
70665
70702
 
70666
70703
  :host {
70667
70704
  display: block;
70705
+
70706
+ /* TODO(designer): confirm the expand duration and curve. */
70707
+ --_expand-duration: var(--obc-accordion-expand-duration, 200ms);
70668
70708
  }
70669
70709
 
70670
70710
  .wrapper {
@@ -70681,6 +70721,12 @@ var accordion_card_default = i$7`* {
70681
70721
  align-items: center;
70682
70722
  align-self: stretch;
70683
70723
  height: fit-content;
70724
+ border-radius: var(--ui-components-accordion-border-radius);
70725
+ /* The card surface is what the closing panel slides over; snapping it away
70726
+ would drop the content onto the page background mid-slide. */
70727
+ transition:
70728
+ background-color var(--_expand-duration) ease,
70729
+ box-shadow var(--_expand-duration) ease;
70684
70730
  }
70685
70731
 
70686
70732
  :is(.wrapper .content-button) {
@@ -70768,6 +70814,11 @@ var accordion_card_default = i$7`* {
70768
70814
  padding: 0;
70769
70815
  border: 0;
70770
70816
  overflow: hidden;
70817
+ /* The bottom corners square on open; without this they round again while
70818
+ the panel is still sliding away. */
70819
+ transition:
70820
+ border-radius var(--_expand-duration) ease,
70821
+ box-shadow var(--_expand-duration) ease;
70771
70822
  }
70772
70823
 
70773
70824
  .wrapper .header-container {
@@ -70840,32 +70891,51 @@ var accordion_card_default = i$7`* {
70840
70891
  flex-shrink: 0;
70841
70892
  }
70842
70893
 
70843
- .wrapper.state-expanded .container-content-additional {
70844
- color: var(--element-neutral-color);
70845
- font-family: var(--global-typography-font-family);
70846
- font-weight: var(--global-typography-ui-body-font-weight);
70847
- font-size: var(--global-typography-ui-body-font-size);
70848
- line-height: var(--global-typography-ui-body-line-height);
70849
- font-feature-settings:
70894
+ .wrapper .trailing-icon {
70895
+ transition: transform var(--_expand-duration) ease;
70896
+ }
70897
+
70898
+ .wrapper.state-expanded .trailing-icon {
70899
+ transform: rotate(-180deg);
70900
+ }
70901
+
70902
+ .wrapper .panel {
70903
+ display: grid;
70904
+ /* 0fr to 1fr is the only track that eases to content height in every engine. */
70905
+ grid-template-rows: 0fr;
70906
+ align-self: stretch;
70907
+ transition: grid-template-rows var(--_expand-duration) ease;
70908
+ }
70909
+
70910
+ .wrapper .panel-inner {
70911
+ /* The grid item cannot carry the inset: padding holds the track open at
70912
+ 16px when closed. It clips here, the padding sits one level down. */
70913
+ min-height: 0;
70914
+ overflow: hidden;
70915
+ }
70916
+
70917
+ .wrapper .container-content-additional {
70918
+ color: var(--element-neutral-color);
70919
+ font-family: var(--global-typography-font-family);
70920
+ font-weight: var(--global-typography-ui-body-font-weight);
70921
+ font-size: var(--global-typography-ui-body-font-size);
70922
+ line-height: var(--global-typography-ui-body-line-height);
70923
+ font-feature-settings:
70850
70924
  "liga" off,
70851
70925
  "clig" off,
70852
70926
  "ss04" on;
70853
- display: flex;
70854
- flex-direction: column;
70855
- align-items: center;
70856
- flex: 1 0 0;
70857
- align-self: stretch;
70858
- height: 100%;
70859
- padding: 0 16px 16px 16px;
70927
+ display: flex;
70928
+ flex-direction: column;
70929
+ align-items: center;
70930
+ padding: 0 16px 16px 16px;
70931
+ }
70932
+
70933
+ .wrapper.state-expanded .panel {
70934
+ grid-template-rows: 1fr;
70860
70935
  }
70861
70936
 
70862
70937
  .wrapper.state-expanded .card-container {
70863
- display: flex;
70864
- flex-direction: column;
70865
- align-items: center;
70866
70938
  flex: 1 0 0;
70867
- align-self: stretch;
70868
- border-radius: var(--ui-components-accordion-border-radius);
70869
70939
  background: var(--container-background-color);
70870
70940
  box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.2);
70871
70941
  }
@@ -70971,6 +71041,15 @@ var accordion_card_default = i$7`* {
70971
71041
  .alert.alert-level-diagnostic {
70972
71042
  z-index: 1;
70973
71043
  }
71044
+
71045
+ @media (prefers-reduced-motion: reduce) {
71046
+ .wrapper .panel,
71047
+ .wrapper .card-container,
71048
+ .wrapper .content-button,
71049
+ .wrapper .trailing-icon {
71050
+ transition: none;
71051
+ }
71052
+ }
70974
71053
  `;
70975
71054
  //#endregion
70976
71055
  //#region src/components/accordion-card/accordion-card.ts
@@ -71007,6 +71086,20 @@ var ObcAccordionCard = class ObcAccordionCard extends i$4 {
71007
71086
  cardTitle: this.cardTitle
71008
71087
  } }));
71009
71088
  }
71089
+ /**
71090
+ * Keeps the keyboard somewhere predictable when the panel closes.
71091
+ *
71092
+ * A collapsed panel is `inert`, and the browser drops focus out of anything
71093
+ * it makes inert — onto `<body>`, two frames later. Clicking the header
71094
+ * already leaves focus there; a consumer setting `expanded` while a slotted
71095
+ * control has focus is the case that needs the transfer.
71096
+ */
71097
+ willUpdate(changed) {
71098
+ if (!changed.has("expanded") || this.expanded) return;
71099
+ const panel = this.shadowRoot?.querySelector(".panel");
71100
+ if (!panel) return;
71101
+ releaseFocusBefore(panel, this.shadowRoot?.querySelector(".content-button"), this.shadowRoot?.querySelector(".wrapper"));
71102
+ }
71010
71103
  renderContentMain() {
71011
71104
  return b`
71012
71105
  <div class="header-container">
@@ -71028,17 +71121,20 @@ var ObcAccordionCard = class ObcAccordionCard extends i$4 {
71028
71121
  </div>
71029
71122
  ` : ""}
71030
71123
  <div class="trailing-icon">
71031
- ${this.expanded ? b`<obi-chevron-up-google></obi-chevron-up-google>` : b`<obi-chevron-down-google></obi-chevron-down-google>`}
71124
+ <obi-chevron-down-google></obi-chevron-down-google>
71032
71125
  </div>
71033
71126
  </div>
71034
71127
  </div>
71035
71128
  `;
71036
71129
  }
71037
71130
  renderContentAdditional() {
71038
- if (!this.expanded) return "";
71039
71131
  return b`
71040
- <div class="container-content-additional">
71041
- <slot name="expanded-content"></slot>
71132
+ <div class="panel" id="accordion-content" ?inert=${!this.expanded}>
71133
+ <div class="panel-inner">
71134
+ <div class="container-content-additional">
71135
+ <slot name="expanded-content"></slot>
71136
+ </div>
71137
+ </div>
71042
71138
  </div>
71043
71139
  `;
71044
71140
  }
@@ -71051,6 +71147,7 @@ var ObcAccordionCard = class ObcAccordionCard extends i$4 {
71051
71147
  render() {
71052
71148
  return b`
71053
71149
  <div
71150
+ tabindex="-1"
71054
71151
  class=${e$2({
71055
71152
  wrapper: true,
71056
71153
  "state-expanded": this.expanded,
@@ -71126,6 +71223,11 @@ var accordion_item_default = i$7`* {
71126
71223
  box-sizing: border-box;
71127
71224
  }
71128
71225
 
71226
+ :host {
71227
+ /* TODO(designer): confirm the expand duration and curve. */
71228
+ --_expand-duration: var(--obc-accordion-expand-duration, 200ms);
71229
+ }
71230
+
71129
71231
  .wrapper {
71130
71232
  display: flex;
71131
71233
  flex-direction: column;
@@ -71213,6 +71315,9 @@ var accordion_item_default = i$7`* {
71213
71315
  cursor: pointer;
71214
71316
  overflow: hidden;
71215
71317
  position: relative;
71318
+ /* The bottom corners square on open; without this they round again while
71319
+ the panel is still sliding away. */
71320
+ transition: border-radius var(--_expand-duration) ease;
71216
71321
  }
71217
71322
 
71218
71323
  .content {
@@ -71282,7 +71387,7 @@ var accordion_item_default = i$7`* {
71282
71387
  height: var(--menu-navigation-components-navigation-item-icon-size);
71283
71388
  flex-shrink: 0;
71284
71389
  position: relative;
71285
- transition: transform 0.2s ease;
71390
+ transition: transform var(--_expand-duration) ease;
71286
71391
  }
71287
71392
 
71288
71393
  .divider {
@@ -71299,19 +71404,29 @@ var accordion_item_default = i$7`* {
71299
71404
  transform: rotate(-180deg);
71300
71405
  }
71301
71406
 
71302
- .content-container {
71303
- display: flex;
71304
- flex-direction: column;
71407
+ .panel {
71408
+ display: grid;
71409
+ /* 0fr to 1fr is the only track that eases to content height in every engine. */
71410
+ grid-template-rows: 0fr;
71305
71411
  width: 100%;
71306
- flex-shrink: 0;
71412
+ transition: grid-template-rows var(--_expand-duration) ease;
71307
71413
  }
71308
71414
 
71309
- .wrapper.open-true .content-button {
71310
- border-bottom-left-radius: 0;
71311
- border-bottom-right-radius: 0;
71415
+ .wrapper.open-true .panel {
71416
+ grid-template-rows: 1fr;
71417
+ }
71418
+
71419
+ .panel-inner {
71420
+ /* The grid item cannot carry the frame: its border is left out of the open
71421
+ track and clipped off. It clips here, the frame sits one level down. */
71422
+ min-height: 0;
71423
+ overflow: hidden;
71312
71424
  }
71313
71425
 
71314
- .wrapper.open-true .content-container {
71426
+ .content-container {
71427
+ display: flex;
71428
+ flex-direction: column;
71429
+ width: 100%;
71315
71430
  background: var(--container-background-color);
71316
71431
  border: 1px solid var(--flat-enabled-border-color);
71317
71432
  border-top: none;
@@ -71319,6 +71434,11 @@ var accordion_item_default = i$7`* {
71319
71434
  border-bottom-right-radius: var(--ui-components-accordion-item-border-radius);
71320
71435
  }
71321
71436
 
71437
+ .wrapper.open-true .content-button {
71438
+ border-bottom-left-radius: 0;
71439
+ border-bottom-right-radius: 0;
71440
+ }
71441
+
71322
71442
  .wrapper.state-disabled .content-button {
71323
71443
  cursor: not-allowed;
71324
71444
  }
@@ -71327,6 +71447,14 @@ var accordion_item_default = i$7`* {
71327
71447
  .wrapper.state-disabled .trailing-icon {
71328
71448
  color: var(--element-disabled-color);
71329
71449
  }
71450
+
71451
+ @media (prefers-reduced-motion: reduce) {
71452
+ .panel,
71453
+ .content-button,
71454
+ .trailing-icon {
71455
+ transition: none;
71456
+ }
71457
+ }
71330
71458
  `;
71331
71459
  //#endregion
71332
71460
  //#region src/components/accordion-item/accordion-item.ts
@@ -71346,6 +71474,20 @@ var ObcAccordionItem = class ObcAccordionItem extends i$4 {
71346
71474
  title: this.title
71347
71475
  } }));
71348
71476
  }
71477
+ /**
71478
+ * Keeps the keyboard somewhere predictable when the panel closes.
71479
+ *
71480
+ * A collapsed panel is `inert`, and the browser drops focus out of anything
71481
+ * it makes inert — onto `<body>`, two frames later. Clicking the header
71482
+ * already leaves focus there; a consumer setting `open` while a slotted
71483
+ * control has focus is the case that needs the transfer.
71484
+ */
71485
+ willUpdate(changed) {
71486
+ if (!changed.has("open") || this.open) return;
71487
+ const panel = this.shadowRoot?.querySelector(".panel");
71488
+ if (!panel) return;
71489
+ releaseFocusBefore(panel, this.shadowRoot?.querySelector(".content-button"), this.shadowRoot?.querySelector(".wrapper"));
71490
+ }
71349
71491
  renderContent() {
71350
71492
  return b`
71351
71493
  <div class="content">
@@ -71361,10 +71503,13 @@ var ObcAccordionItem = class ObcAccordionItem extends i$4 {
71361
71503
  `;
71362
71504
  }
71363
71505
  renderExpandedContent() {
71364
- if (!this.open) return "";
71365
71506
  return b`
71366
- <div class="content-container">
71367
- <slot name="expanded-content"></slot>
71507
+ <div class="panel" id="accordion-content" ?inert=${!this.open}>
71508
+ <div class="panel-inner">
71509
+ <div class="content-container">
71510
+ <slot name="expanded-content"></slot>
71511
+ </div>
71512
+ </div>
71368
71513
  </div>
71369
71514
  `;
71370
71515
  }
@@ -71375,6 +71520,7 @@ var ObcAccordionItem = class ObcAccordionItem extends i$4 {
71375
71520
  render() {
71376
71521
  return b`
71377
71522
  <div
71523
+ tabindex="-1"
71378
71524
  class=${e$2({
71379
71525
  wrapper: true,
71380
71526
  "state-disabled": this.disabled,
@@ -71387,6 +71533,7 @@ var ObcAccordionItem = class ObcAccordionItem extends i$4 {
71387
71533
  @click=${this.handleToggle}
71388
71534
  ?disabled=${this.disabled}
71389
71535
  aria-expanded=${this.open}
71536
+ aria-controls="accordion-content"
71390
71537
  >
71391
71538
  ${this.renderContent()}
71392
71539
  </button>