rapidoc 9.3.2 → 9.3.4

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.
Files changed (47) hide show
  1. package/.github/workflow/words.yaml +22 -0
  2. package/dist/index.html +1 -1
  3. package/dist/index.html.gz +0 -0
  4. package/dist/rapidoc-min.js +857 -738
  5. package/dist/rapidoc-min.js.LICENSE.txt +9 -10
  6. package/dist/rapidoc-min.js.LICENSE.txt.gz +0 -0
  7. package/dist/rapidoc-min.js.gz +0 -0
  8. package/dist/rapidoc-min.js.map +1 -1
  9. package/dist/rapidoc-min.js.map.gz +0 -0
  10. package/dist/rapidoc.js +9341 -25092
  11. package/dist/report.html +5 -4
  12. package/index.html +2 -3
  13. package/package.json +20 -19
  14. package/src/components/api-request.js +344 -154
  15. package/src/components/api-response.js +16 -12
  16. package/src/components/json-tree.js +17 -12
  17. package/src/components/schema-table.js +50 -42
  18. package/src/components/schema-tree.js +56 -53
  19. package/src/components/tag-input.js +7 -4
  20. package/src/json-schema-viewer.js +1 -2
  21. package/src/rapidoc-mini.js +1 -3
  22. package/src/rapidoc.js +112 -45
  23. package/src/styles/endpoint-styles.js +1 -1
  24. package/src/styles/font-styles.js +1 -1
  25. package/src/styles/info-styles.js +2 -1
  26. package/src/styles/input-styles.js +2 -16
  27. package/src/styles/nav-styles.js +57 -10
  28. package/src/styles/schema-styles.js +27 -15
  29. package/src/styles/tab-styles.js +1 -0
  30. package/src/templates/callback-template.js +6 -7
  31. package/src/templates/code-samples-template.js +1 -0
  32. package/src/templates/components-template.js +3 -5
  33. package/src/templates/endpoint-template.js +41 -27
  34. package/src/templates/expanded-endpoint-template.js +63 -13
  35. package/src/templates/focused-endpoint-template.js +4 -1
  36. package/src/templates/header-template.js +2 -2
  37. package/src/templates/json-schema-viewer-template.js +2 -1
  38. package/src/templates/main-body-template.js +19 -18
  39. package/src/templates/navbar-template.js +98 -81
  40. package/src/templates/overview-template.js +1 -1
  41. package/src/templates/security-scheme-template.js +48 -25
  42. package/src/templates/server-template.js +1 -1
  43. package/src/utils/common-utils.js +2 -5
  44. package/src/utils/schema-utils.js +208 -83
  45. package/src/utils/spec-parser.js +1 -0
  46. package/src/utils/theme.js +11 -5
  47. package/webpack.config.js +2 -1
@@ -6,12 +6,12 @@ export default class TagInput extends LitElement {
6
6
  let tagItemTmpl = '';
7
7
  if (Array.isArray(this.value)) {
8
8
  tagItemTmpl = html`${this.value
9
- .filter((v) => v.trim() !== '')
9
+ .filter((v) => typeof v === 'string' && v.trim() !== '')
10
10
  .map((v) => html`<span class='tag'>${v}</span>`)
11
11
  }`;
12
12
  }
13
13
  return html`
14
- <div class='tags' tabindex="0">
14
+ <div class='tags'>
15
15
  ${tagItemTmpl}
16
16
  <input type="text" class='editor' @paste="${(e) => this.afterPaste(e)}" @keydown="${this.afterKeyDown}" @blur="${this.onBlur}" placeholder="${this.placeholder || ''}">
17
17
  </div>
@@ -84,7 +84,7 @@ export default class TagInput extends LitElement {
84
84
 
85
85
  static get styles() {
86
86
  return [css`
87
- .tags{
87
+ .tags {
88
88
  display:flex;
89
89
  flex-wrap: wrap;
90
90
  outline: none;
@@ -110,7 +110,7 @@ export default class TagInput extends LitElement {
110
110
  .tag:hover ~ #cursor {
111
111
  display: block;
112
112
  }
113
- .editor{
113
+ .editor {
114
114
  flex:1;
115
115
  border:1px solid transparent;
116
116
  color:var(--fg);
@@ -121,6 +121,9 @@ export default class TagInput extends LitElement {
121
121
  background:transparent;
122
122
  font-size: calc(var(--font-size-small) + 1px);
123
123
  }
124
+ .editor:focus-visible {
125
+ outline: 1px solid;
126
+ }
124
127
  .editor::placeholder {
125
128
  color: var(--placeholder-color);
126
129
  opacity:1;
@@ -229,7 +229,6 @@ export default class JsonSchemaViewer extends LitElement {
229
229
  if (!this.allowSearch || !'true, false,'.includes(`${this.allowSearch},`)) { this.allowSearch = 'true'; }
230
230
  if (!this.schemaExpandLevel || this.schemaExpandLevel < 1) { this.schemaExpandLevel = 99999; }
231
231
  if (!this.schemaDescriptionExpanded || !'true, false,'.includes(`${this.schemaDescriptionExpanded},`)) { this.schemaDescriptionExpanded = 'false'; }
232
- if (!this.responseAreaHeight) { this.responseAreaHeight = '300px'; }
233
232
  if (!this.fontSize || !'default, large, largest,'.includes(`${this.fontSize},`)) { this.fontSize = 'default'; }
234
233
  if (!this.matchType || !'includes regex'.includes(this.matchType)) { this.matchType = 'includes'; }
235
234
  if (!this.allowSchemaDescriptionExpandToggle || !'true, false,'.includes(`${this.allowSchemaDescriptionExpandToggle},`)) { this.allowSchemaDescriptionExpandToggle = 'true'; }
@@ -260,7 +259,7 @@ export default class JsonSchemaViewer extends LitElement {
260
259
  super.attributeChangedCallback(name, oldVal, newVal);
261
260
  }
262
261
 
263
- onSepcUrlChange() {
262
+ onSpecUrlChange() {
264
263
  this.setAttribute('spec-url', this.shadowRoot.getElementById('spec-url').value);
265
264
  }
266
265
 
@@ -51,7 +51,6 @@ export default class RapiDocMini extends LitElement {
51
51
  responseAreaHeight: { type: String, attribute: 'response-area-height' },
52
52
  showSummaryWhenCollapsed: { type: String, attribute: 'show-summary-when-collapsed' },
53
53
  fillRequestFieldsWithExample: { type: String, attribute: 'fill-request-fields-with-example' },
54
- useSummaryToListExamples: { type: String, attribute: 'use-summary-to-list-example' },
55
54
  persistAuth: { type: String, attribute: 'persist-auth' },
56
55
 
57
56
  // Schema Styles
@@ -170,7 +169,6 @@ export default class RapiDocMini extends LitElement {
170
169
  if (!this.schemaExpandLevel || this.schemaExpandLevel < 1) { this.schemaExpandLevel = 99999; }
171
170
  if (!this.schemaDescriptionExpanded || !'true, false,'.includes(`${this.schemaDescriptionExpanded},`)) { this.schemaDescriptionExpanded = 'false'; }
172
171
  if (!this.fillRequestFieldsWithExample || !'true, false,'.includes(`${this.fillRequestFieldsWithExample},`)) { this.fillRequestFieldsWithExample = 'true'; }
173
- if (!this.useSummaryToListExamples || !'true, false,'.includes(`${this.useSummaryToListExamples},`)) { this.useSummaryToListExamples = 'false'; }
174
172
  if (!this.persistAuth || !'true, false,'.includes(`${this.persistAuth},`)) { this.persistAuth = 'false'; }
175
173
  if (!this.responseAreaHeight) { this.responseAreaHeight = '300px'; }
176
174
 
@@ -266,7 +264,7 @@ export default class RapiDocMini extends LitElement {
266
264
  super.attributeChangedCallback(name, oldVal, newVal);
267
265
  }
268
266
 
269
- onSepcUrlChange() {
267
+ onSpecUrlChange() {
270
268
  this.setAttribute('spec-url', this.shadowRoot.getElementById('spec-url').value);
271
269
  }
272
270
 
package/src/rapidoc.js CHANGED
@@ -38,7 +38,9 @@ export default class RapiDoc extends LitElement {
38
38
  threshold: 0,
39
39
  };
40
40
  this.showSummaryWhenCollapsed = true;
41
- this.isIntersectionObserverActive = true;
41
+ // Will activate intersection observer only after spec load and hash analyze
42
+ // to scroll to the proper element without being reverted by observer behavior
43
+ this.isIntersectionObserverActive = false;
42
44
  this.intersectionObserver = new IntersectionObserver((entries) => { this.onIntersect(entries); }, intersectionObserverOptions);
43
45
  }
44
46
 
@@ -63,7 +65,6 @@ export default class RapiDoc extends LitElement {
63
65
  defaultSchemaTab: { type: String, attribute: 'default-schema-tab' },
64
66
  responseAreaHeight: { type: String, attribute: 'response-area-height' },
65
67
  fillRequestFieldsWithExample: { type: String, attribute: 'fill-request-fields-with-example' },
66
- useSummaryToListExamples: { type: String, attribute: 'use-summary-to-list-example' },
67
68
  persistAuth: { type: String, attribute: 'persist-auth' },
68
69
  onNavTagClick: { type: String, attribute: 'on-nav-tag-click' },
69
70
 
@@ -88,6 +89,7 @@ export default class RapiDoc extends LitElement {
88
89
  showInfo: { type: String, attribute: 'show-info' },
89
90
  allowAuthentication: { type: String, attribute: 'allow-authentication' },
90
91
  allowTry: { type: String, attribute: 'allow-try' },
92
+ showCurlBeforeTry: { type: String, attribute: 'show-curl-before-try' },
91
93
  allowSpecUrlLoad: { type: String, attribute: 'allow-spec-url-load' },
92
94
  allowSpecFileLoad: { type: String, attribute: 'allow-spec-file-load' },
93
95
  allowSpecFileDownload: { type: String, attribute: 'allow-spec-file-download' },
@@ -117,6 +119,8 @@ export default class RapiDoc extends LitElement {
117
119
  navHoverBgColor: { type: String, attribute: 'nav-hover-bg-color' },
118
120
  navHoverTextColor: { type: String, attribute: 'nav-hover-text-color' },
119
121
  navAccentColor: { type: String, attribute: 'nav-accent-color' },
122
+ navAccentTextColor: { type: String, attribute: 'nav-accent-text-color' },
123
+ navActiveItemMarker: { type: String, attribute: 'nav-active-item-marker' },
120
124
  navItemSpacing: { type: String, attribute: 'nav-item-spacing' },
121
125
  showMethodInNavBar: { type: String, attribute: 'show-method-in-nav-bar' },
122
126
  usePathInNavBar: { type: String, attribute: 'use-path-in-nav-bar' },
@@ -163,13 +167,14 @@ export default class RapiDoc extends LitElement {
163
167
  background-color:var(--bg);
164
168
  font-family:var(--font-regular);
165
169
  }
166
- .body {
170
+ :where(button, input[type="checkbox"], [tabindex="0"]):focus-visible { box-shadow: var(--focus-shadow); }
171
+ :where(input[type="text"], input[type="password"], select, textarea):focus-visible { border-color: var(--primary-color); }
172
+ .body {
167
173
  display:flex;
168
174
  height:100%;
169
175
  width:100%;
170
176
  overflow:hidden;
171
177
  }
172
-
173
178
  .main-content {
174
179
  margin:0;
175
180
  padding: 0;
@@ -283,11 +288,21 @@ export default class RapiDoc extends LitElement {
283
288
  height: 36px;
284
289
  animation: spin 2s linear infinite;
285
290
  }
286
- .expanded-endpoint-body{
291
+ .expanded-endpoint-body {
287
292
  position: relative;
288
293
  padding: 6px 0px;
289
294
  }
290
- .expanded-endpoint-body.deprecated{ filter:opacity(0.6); }
295
+ .expanded-endpoint-body .tag-description {
296
+ background: var(--code-bg);
297
+ border-radius: var(--border-radius);
298
+ transition: max-height .2s ease-out;
299
+ }
300
+ .expanded-endpoint-body .tag-icon {
301
+ transition: transform .2s ease-out;
302
+ }
303
+ .expanded-endpoint-body .tag-icon.expanded {
304
+ transform: rotate(180deg);
305
+ }
291
306
  .divider {
292
307
  border-top: 2px solid var(--border-color);
293
308
  margin: 24px 0;
@@ -346,6 +361,9 @@ export default class RapiDoc extends LitElement {
346
361
  border-radius: 4px 0 0 4px;
347
362
  color: #000;
348
363
  }
364
+ .colored-block .nav-method.as-colored-block {
365
+ outline: 1px solid;
366
+ }
349
367
 
350
368
  .nav-method.as-colored-block.get { background-color: var(--blue); }
351
369
  .nav-method.as-colored-block.put { background-color: var(--orange); }
@@ -439,7 +457,7 @@ export default class RapiDoc extends LitElement {
439
457
  }
440
458
 
441
459
  if (!this.layout || !'row, column,'.includes(`${this.layout},`)) { this.layout = 'row'; }
442
- if (!this.renderStyle || !'read, view, focused,'.includes(`${this.renderStyle},`)) { this.renderStyle = 'read'; }
460
+ if (!this.renderStyle || !'read, view, focused,'.includes(`${this.renderStyle},`)) { this.renderStyle = 'focused'; }
443
461
  if (!this.schemaStyle || !'tree, table,'.includes(`${this.schemaStyle},`)) { this.schemaStyle = 'tree'; }
444
462
  if (!this.theme || !'light, dark,'.includes(`${this.theme},`)) {
445
463
  this.theme = (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches) ? 'light' : 'dark';
@@ -451,23 +469,14 @@ export default class RapiDoc extends LitElement {
451
469
  }
452
470
  if (!this.schemaExpandLevel || this.schemaExpandLevel < 1) { this.schemaExpandLevel = 99999; }
453
471
  if (!this.schemaDescriptionExpanded || !'true, false,'.includes(`${this.schemaDescriptionExpanded},`)) { this.schemaDescriptionExpanded = 'false'; }
454
- const writeMethodsWithBody = ['post', 'put', 'patch'];
455
- if (!this.schemaHideReadOnly) {
456
- this.schemaHideReadOnly = writeMethodsWithBody;
457
- } else if (this.schemaHideReadOnly !== 'never') {
458
- this.schemaHideReadOnly = writeMethodsWithBody.filter((value) => this.schemaHideReadOnly.includes(value));
459
- if (this.schemaHideReadOnly.length === 0) {
460
- this.schemaHideReadOnly = writeMethodsWithBody;
461
- }
462
- }
463
- this.schemaHideReadOnly += ['get', 'head', 'delete', 'options'];
464
- this.schemaHideWriteOnly = this.schemaHideWriteOnly !== 'never';
472
+
473
+ if (!this.schemaHideReadOnly || !'default, never,'.includes(`${this.schemaHideReadOnly},`)) { this.schemaHideReadOnly = 'default'; }
474
+ if (!this.schemaHideWriteOnly || !'default, never,'.includes(`${this.schemaHideWriteOnly},`)) { this.schemaHideWriteOnly = 'default'; }
475
+
465
476
  if (!this.fillRequestFieldsWithExample || !'true, false,'.includes(`${this.fillRequestFieldsWithExample},`)) { this.fillRequestFieldsWithExample = 'true'; }
466
- if (!this.useSummaryToListExamples || !'true, false,'.includes(`${this.useSummaryToListExamples},`)) { this.useSummaryToListExamples = 'false'; }
467
477
  if (!this.persistAuth || !'true, false,'.includes(`${this.persistAuth},`)) { this.persistAuth = 'false'; }
468
- if (!this.onNavTagClick || !'expand-collapse, show-description,'.includes(`${this.onNavTagClick},`)) { this.onNavTagClick = 'expand-collapse'; }
469
478
  if (!this.responseAreaHeight) {
470
- this.responseAreaHeight = '300px';
479
+ this.responseAreaHeight = '400px';
471
480
  }
472
481
 
473
482
  if (!this.allowSearch || !'true, false,'.includes(`${this.allowSearch},`)) { this.allowSearch = 'true'; }
@@ -484,11 +493,14 @@ export default class RapiDoc extends LitElement {
484
493
  if (!this.sortTags || !'true, false,'.includes(`${this.sortTags},`)) { this.sortTags = 'false'; }
485
494
  if (!this.generateMissingTags || !'true, false,'.includes(`${this.generateMissingTags},`)) { this.generateMissingTags = 'false'; }
486
495
  if (!this.sortEndpointsBy || !'method, path, summary, none,'.includes(`${this.sortEndpointsBy},`)) { this.sortEndpointsBy = 'path'; }
496
+
497
+ if (!this.onNavTagClick || !'expand-collapse, show-description,'.includes(`${this.onNavTagClick},`)) { this.onNavTagClick = 'expand-collapse'; }
487
498
  if (!this.navItemSpacing || !'compact, relaxed, default,'.includes(`${this.navItemSpacing},`)) { this.navItemSpacing = 'default'; }
488
499
  if (!this.showMethodInNavBar || !'false, as-plain-text, as-colored-text, as-colored-block,'.includes(`${this.showMethodInNavBar},`)) { this.showMethodInNavBar = 'false'; }
489
500
  if (!this.usePathInNavBar || !'true, false,'.includes(`${this.usePathInNavBar},`)) { this.usePathInNavBar = 'false'; }
490
- if (!this.fontSize || !'default, large, largest,'.includes(`${this.fontSize},`)) { this.fontSize = 'default'; }
501
+ if (!this.navActiveItemMarker || !'left-bar, colored-block'.includes(`${this.navActiveItemMarker},`)) { this.navActiveItemMarker = 'left-bar'; }
491
502
 
503
+ if (!this.fontSize || !'default, large, largest,'.includes(`${this.fontSize},`)) { this.fontSize = 'default'; }
492
504
  if (!this.showInfo || !'true, false,'.includes(`${this.showInfo},`)) { this.showInfo = 'true'; }
493
505
  if (!this.allowServerSelection || !'true, false,'.includes(`${this.allowServerSelection},`)) { this.allowServerSelection = 'true'; }
494
506
  if (!this.allowAuthentication || !'true, false,'.includes(`${this.allowAuthentication},`)) { this.allowAuthentication = 'true'; }
@@ -515,9 +527,7 @@ export default class RapiDoc extends LitElement {
515
527
  });
516
528
 
517
529
  window.addEventListener('hashchange', () => {
518
- const regEx = new RegExp(`^${this.routePrefix}`, 'i');
519
- const elementId = window.location.hash.replace(regEx, '');
520
- this.scrollTo(elementId);
530
+ this.scrollToPath(this.getElementIDFromURL());
521
531
  }, true);
522
532
  }
523
533
 
@@ -561,7 +571,7 @@ export default class RapiDoc extends LitElement {
561
571
  await this.loadSpec(newVal);
562
572
  // If goto-path is provided and no location-hash is present then try to scroll there
563
573
  if (this.gotoPath && !window.location.hash) {
564
- this.scrollTo(this.gotoPath);
574
+ this.scrollToPath(this.gotoPath);
565
575
  }
566
576
  }, 0);
567
577
  }
@@ -630,11 +640,11 @@ export default class RapiDoc extends LitElement {
630
640
  super.attributeChangedCallback(name, oldVal, newVal);
631
641
  }
632
642
 
633
- onSepcUrlChange() {
643
+ onSpecUrlChange() {
634
644
  this.setAttribute('spec-url', this.shadowRoot.getElementById('spec-url').value);
635
645
  }
636
646
 
637
- onSepcFileChange(e) {
647
+ onSpecFileChange(e) {
638
648
  this.setAttribute('spec-file', this.shadowRoot.getElementById('spec-file').value);
639
649
  const specFile = e.target.files[0];
640
650
  const reader = new FileReader();
@@ -763,20 +773,60 @@ export default class RapiDoc extends LitElement {
763
773
  this.observeExpandedContent(); // This will auto-highlight the selected nav-item in read-mode
764
774
  }
765
775
 
776
+ this.isIntersectionObserverActive = true;
777
+
766
778
  // On first time Spec load, try to navigate to location hash if provided
767
- const locationHash = window.location.hash?.substring(1);
768
- if (locationHash) {
769
- const regEx = new RegExp(`^${this.routePrefix}`, 'i');
770
- const elementId = window.location.hash.replace(regEx, '');
779
+ const elementId = this.getElementIDFromURL();
780
+
781
+ if (elementId) {
771
782
  if (this.renderStyle === 'view') {
772
783
  this.expandAndGotoOperation(elementId, true, true);
773
784
  } else {
774
- this.scrollTo(elementId);
785
+ this.scrollToPath(elementId);
775
786
  }
776
787
  } else if (this.renderStyle === 'focused') {
777
- const defaultElementId = this.showInfo ? 'overview' : this.resolvedSpec.tags[0]?.paths[0];
778
- this.scrollTo(defaultElementId);
788
+ // If goto-path is provided and no location-hash is present then try to scroll to default element
789
+ if (!this.gotoPath) {
790
+ const defaultElementId = this.showInfo ? 'overview' : this.resolvedSpec.tags[0]?.paths[0];
791
+ this.scrollToPath(defaultElementId);
792
+ }
793
+ }
794
+ }
795
+
796
+ /**
797
+ * Return the URL from where is served the RapiDoc component, removing any hash and route prefix
798
+ */
799
+ getComponentBaseURL() {
800
+ const { href } = window.location;
801
+
802
+ // Remove end of string # or /
803
+ const cleanRouterPrefix = this.routePrefix.replace(/(#|\/)$/, '');
804
+
805
+ if (!cleanRouterPrefix) {
806
+ return href.split('#')[0];
779
807
  }
808
+
809
+ const indexOfRoutePrefix = href.lastIndexOf(cleanRouterPrefix);
810
+
811
+ if (indexOfRoutePrefix === -1) {
812
+ return href;
813
+ }
814
+
815
+ return href.slice(0, indexOfRoutePrefix);
816
+ }
817
+
818
+ /**
819
+ * From the URL return the ID of the element whether it is in the hash or if used a router prefix without a hash
820
+ */
821
+ getElementIDFromURL() {
822
+ const baseURL = this.getComponentBaseURL();
823
+ const elementId = window.location.href.replace(baseURL + this.routePrefix, '');
824
+ return elementId;
825
+ }
826
+
827
+ replaceHistoryState(hashId) {
828
+ const baseURL = this.getComponentBaseURL();
829
+ window.history.replaceState(null, null, `${baseURL}${this.routePrefix || '#'}${hashId}`);
780
830
  }
781
831
 
782
832
  expandAndGotoOperation(elementId, scrollToElement = true) {
@@ -812,7 +862,7 @@ export default class RapiDoc extends LitElement {
812
862
  if (gotoEl) {
813
863
  gotoEl.scrollIntoView({ behavior: 'auto', block: 'start' });
814
864
  if (this.updateRoute === 'true') {
815
- window.history.replaceState(null, null, `${this.routePrefix || '#'}${tmpElementId}`);
865
+ this.replaceHistoryState(tmpElementId);
816
866
  }
817
867
  }
818
868
  }, isExpandingNeeded ? 150 : 0);
@@ -843,6 +893,7 @@ export default class RapiDoc extends LitElement {
843
893
  if (this.isIntersectionObserverActive === false) {
844
894
  return;
845
895
  }
896
+
846
897
  entries.forEach((entry) => {
847
898
  if (entry.isIntersecting && entry.intersectionRatio > 0) {
848
899
  const oldNavEl = this.shadowRoot.querySelector('.nav-bar-tag.active, .nav-bar-path.active, .nav-bar-info.active, .nav-bar-h1.active, .nav-bar-h2.active, .operations.active');
@@ -851,14 +902,18 @@ export default class RapiDoc extends LitElement {
851
902
  // Add active class in the new element
852
903
  if (newNavEl) {
853
904
  if (this.updateRoute === 'true') {
854
- window.history.replaceState(null, null, `${window.location.href.split('#')[0]}${this.routePrefix || '#'}${entry.target.id}`);
905
+ this.replaceHistoryState(entry.target.id);
855
906
  }
856
907
  newNavEl.scrollIntoView({ behavior: 'auto', block: 'center' });
857
908
  newNavEl.classList.add('active');
909
+ newNavEl.part.add('section-navbar-active-item');
858
910
  }
911
+
859
912
  // Remove active class from previous element
860
- if (oldNavEl) {
913
+ // if it is different from the new one (edge case on loading in read render style)
914
+ if (oldNavEl && oldNavEl !== newNavEl) {
861
915
  oldNavEl.classList.remove('active');
916
+ oldNavEl.part.remove('section-navbar-active-item');
862
917
  }
863
918
  }
864
919
  });
@@ -888,19 +943,28 @@ export default class RapiDoc extends LitElement {
888
943
  *
889
944
  */
890
945
  async scrollToEventTarget(event, scrollNavItemToView = true) {
891
- const navEl = event.currentTarget;
946
+ if (!(event.type === 'click' || (event.type === 'keyup' && event.keyCode === 13))) {
947
+ return;
948
+ }
949
+ const navEl = event.target;
892
950
  if (!navEl.dataset.contentId) {
893
951
  return;
894
952
  }
895
953
  this.isIntersectionObserverActive = false;
896
- this.scrollTo(navEl.dataset.contentId, true, scrollNavItemToView);
954
+ if (this.renderStyle === 'focused') {
955
+ const requestEl = this.shadowRoot.querySelector('api-request');
956
+ if (requestEl) {
957
+ requestEl.beforeNavigationFocusedMode();
958
+ }
959
+ }
960
+ this.scrollToPath(navEl.dataset.contentId, true, scrollNavItemToView);
897
961
  setTimeout(() => {
898
962
  this.isIntersectionObserverActive = true;
899
963
  }, 300);
900
964
  }
901
965
 
902
966
  // Public Method (scrolls to a given path and highlights the left-nav selection)
903
- async scrollTo(elementId, expandPath = true, scrollNavItemToView = true) {
967
+ async scrollToPath(elementId, expandPath = true, scrollNavItemToView = true) {
904
968
  if (this.renderStyle === 'focused') {
905
969
  // for focused mode update this.focusedElementId to update the rendering, else it wont find the needed html elements
906
970
  // focusedElementId will get validated in the template
@@ -923,7 +987,7 @@ export default class RapiDoc extends LitElement {
923
987
  if (this.renderStyle === 'focused') {
924
988
  const requestEl = this.shadowRoot.querySelector('api-request');
925
989
  if (requestEl) {
926
- requestEl.resetRequestBodySelection();
990
+ requestEl.afterNavigationFocusedMode();
927
991
  }
928
992
  const responseEl = this.shadowRoot.querySelector('api-response');
929
993
  if (responseEl) {
@@ -933,7 +997,7 @@ export default class RapiDoc extends LitElement {
933
997
 
934
998
  // Update Location Hash
935
999
  if (this.updateRoute === 'true') {
936
- window.history.replaceState(null, null, `${this.routePrefix || '#'}${elementId}`);
1000
+ this.replaceHistoryState(elementId);
937
1001
  }
938
1002
 
939
1003
  // Update NavBar View and Styles
@@ -947,8 +1011,11 @@ export default class RapiDoc extends LitElement {
947
1011
  const oldNavEl = this.shadowRoot.querySelector('.nav-bar-tag.active, .nav-bar-path.active, .nav-bar-info.active, .nav-bar-h1.active, .nav-bar-h2.active, .operations.active');
948
1012
  if (oldNavEl) {
949
1013
  oldNavEl.classList.remove('active');
1014
+ oldNavEl.part.remove('active');
1015
+ oldNavEl.part.remove('section-navbar-active-item');
950
1016
  }
951
1017
  newNavEl.classList.add('active'); // must add the class after scrolling
1018
+ newNavEl.part.add('section-navbar-active-item');
952
1019
  // this.requestUpdate();
953
1020
  }
954
1021
  }
@@ -987,8 +1054,8 @@ export default class RapiDoc extends LitElement {
987
1054
  } else {
988
1055
  searchInputEl = eventTargetEl.closest('.advanced-search-options').querySelector('input[type=text]');
989
1056
  }
990
- const searcOptions = [...eventTargetEl.closest('.advanced-search-options').querySelectorAll('input:checked')].map((v) => v.id);
991
- this.advancedSearchMatches = advancedSearch(searchInputEl.value, this.resolvedSpec.tags, searcOptions);
1057
+ const searchOptions = [...eventTargetEl.closest('.advanced-search-options').querySelectorAll('input:checked')].map((v) => v.id);
1058
+ this.advancedSearchMatches = advancedSearch(searchInputEl.value, this.resolvedSpec.tags, searchOptions);
992
1059
  }, delay);
993
1060
  }
994
1061
  }
@@ -130,7 +130,7 @@ export default css`
130
130
  border: 2px solid var(--yellow);
131
131
  }
132
132
 
133
- .req-resp-container{
133
+ .req-resp-container {
134
134
  display: flex;
135
135
  margin-top:16px;
136
136
  align-items: stretch;
@@ -40,7 +40,7 @@ export default css`
40
40
  .blue-text {color: var(--blue)}
41
41
  .multiline {
42
42
  overflow: scroll;
43
- max-height: var(--resp-area-height, 300px);
43
+ max-height: var(--resp-area-height, 400px);
44
44
  color: var(--fg3);
45
45
  }
46
46
  .method-fg.put { color: var(--orange); }
@@ -2,7 +2,8 @@ import { css } from 'lit';
2
2
 
3
3
  export default css`
4
4
  #api-info {
5
- font-size:calc(var(--font-size-regular) - 1px);margin-top:8px
5
+ font-size: calc(var(--font-size-regular) - 1px);
6
+ margin-top: 8px;
6
7
  margin-left: -15px;
7
8
  }
8
9
 
@@ -105,15 +105,6 @@ input[type="password"]::placeholder {
105
105
  opacity:1;
106
106
  }
107
107
 
108
- select:focus,
109
- textarea:focus,
110
- input[type="text"]:focus,
111
- input[type="password"]:focus,
112
- textarea:active,
113
- input[type="text"]:active,
114
- input[type="password"]:active {
115
- border:1px solid var(--primary-color);
116
- }
117
108
 
118
109
  input[type="file"]{
119
110
  font-family: var(--font-regular);
@@ -167,10 +158,6 @@ textarea::-webkit-scrollbar-thumb {
167
158
  margin-bottom:2px;
168
159
  }
169
160
 
170
- input[type="checkbox"]:focus{
171
- outline:0;
172
- }
173
-
174
161
  /* Toggle Body */
175
162
  input[type="checkbox"] {
176
163
  appearance: none;
@@ -203,7 +190,7 @@ input[type="checkbox"]:after {
203
190
 
204
191
  /* Toggle Body - Checked */
205
192
  input[type="checkbox"]:checked {
206
- box-shadow: inset 0 0 0 13px var(--green);
193
+ background-color: var(--green);
207
194
  border-color: var(--green);
208
195
  }
209
196
  /* Toggle Thumb - Checked*/
@@ -212,5 +199,4 @@ input[type="checkbox"]:checked:after {
212
199
  left: 16px;
213
200
  right: 1px;
214
201
  transition: border .25s, left .15s .25s, right .25s .175s;
215
- }
216
- `;
202
+ }`;
@@ -1,6 +1,20 @@
1
1
  import { css } from 'lit';
2
2
 
3
3
  export default css`
4
+ .nav-bar-info:focus-visible,
5
+ .nav-bar-tag:focus-visible,
6
+ .nav-bar-path:focus-visible {
7
+ outline: 1px solid;
8
+ box-shadow: none;
9
+ outline-offset: -4px;
10
+ }
11
+ .nav-bar-expand-all:focus-visible,
12
+ .nav-bar-collapse-all:focus-visible,
13
+ .nav-bar-tag-icon:focus-visible {
14
+ outline: 1px solid;
15
+ box-shadow: none;
16
+ outline-offset: 2px;
17
+ }
4
18
  .nav-bar {
5
19
  width:0;
6
20
  height:100%;
@@ -35,6 +49,26 @@ export default css`
35
49
  .nav-bar.read .nav-bar-tag-icon {
36
50
  display:none;
37
51
  }
52
+ .nav-bar-paths-under-tag {
53
+ overflow:hidden;
54
+ transition: max-height .2s ease-out, visibility .3s;
55
+ }
56
+ .collapsed .nav-bar-paths-under-tag {
57
+ visibility: hidden;
58
+ }
59
+
60
+ .nav-bar-expand-all {
61
+ transform: rotate(90deg);
62
+ cursor:pointer;
63
+ margin-right:10px;
64
+ }
65
+ .nav-bar-collapse-all {
66
+ transform: rotate(270deg);
67
+ cursor:pointer;
68
+ }
69
+ .nav-bar-expand-all:hover, .nav-bar-collapse-all:hover {
70
+ color: var(--primary-color);
71
+ }
38
72
 
39
73
  .nav-bar-tag-icon {
40
74
  color: var(--nav-text-color);
@@ -43,9 +77,6 @@ export default css`
43
77
  .nav-bar-tag-icon:hover {
44
78
  color:var(--nav-hover-text-color);
45
79
  }
46
- .nav-bar.focused .nav-bar-tag-and-paths.collapsed .nav-bar-paths-under-tag {
47
- display:none;
48
- }
49
80
  .nav-bar.focused .nav-bar-tag-and-paths.collapsed .nav-bar-tag-icon::after {
50
81
  content: '⌵';
51
82
  width:16px;
@@ -89,7 +120,12 @@ export default css`
89
120
  .nav-bar-tag,
90
121
  .nav-bar-path {
91
122
  display:flex;
92
- cursor:pointer;
123
+ cursor: pointer;
124
+ width: 100%;
125
+ border: none;
126
+ border-radius:4px;
127
+ color: var(--nav-text-color);
128
+ background: transparent;
93
129
  border-left:4px solid transparent;
94
130
  }
95
131
 
@@ -130,16 +166,27 @@ export default css`
130
166
  }
131
167
  .nav-bar-h2 {margin-left:12px;}
132
168
 
133
- .nav-bar-h1.active,
134
- .nav-bar-h2.active,
135
- .nav-bar-info.active,
136
- .nav-bar-tag.active,
137
- .nav-bar-path.active,
138
- .nav-bar-section.operations.active {
169
+ .nav-bar-h1.left-bar.active,
170
+ .nav-bar-h2.left-bar.active,
171
+ .nav-bar-info.left-bar.active,
172
+ .nav-bar-tag.left-bar.active,
173
+ .nav-bar-path.left-bar.active,
174
+ .nav-bar-section.left-bar.operations.active {
139
175
  border-left:4px solid var(--nav-accent-color);
140
176
  color:var(--nav-hover-text-color);
141
177
  }
142
178
 
179
+ .nav-bar-h1.colored-block.active,
180
+ .nav-bar-h2.colored-block.active,
181
+ .nav-bar-info.colored-block.active,
182
+ .nav-bar-tag.colored-block.active,
183
+ .nav-bar-path.colored-block.active,
184
+ .nav-bar-section.colored-block.operations.active {
185
+ background-color: var(--nav-accent-color);
186
+ color: var(--nav-accent-text-color);
187
+ border-radius: 0;
188
+ }
189
+
143
190
  .nav-bar-h1:hover,
144
191
  .nav-bar-h2:hover,
145
192
  .nav-bar-info:hover,