openproject-primer_view_components 0.18.1 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +61 -0
  3. data/app/assets/javascripts/app/components/primer/alpha/action_bar_element.d.ts +3 -2
  4. data/app/assets/javascripts/app/components/primer/alpha/action_menu/action_menu_element.d.ts +20 -0
  5. data/app/assets/javascripts/app/components/primer/beta/nav_list.d.ts +0 -11
  6. data/app/assets/javascripts/app/components/primer/beta/nav_list_group_element.d.ts +19 -0
  7. data/app/assets/javascripts/app/components/primer/primer.d.ts +2 -0
  8. data/app/assets/javascripts/app/components/primer/scrollable_region.d.ts +13 -0
  9. data/app/assets/javascripts/primer_view_components.js +1 -1
  10. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  11. data/app/assets/styles/primer_view_components.css +1 -1
  12. data/app/assets/styles/primer_view_components.css.map +1 -1
  13. data/app/components/primer/alpha/action_bar.css +1 -1
  14. data/app/components/primer/alpha/action_bar.css.map +1 -1
  15. data/app/components/primer/alpha/action_bar.pcss +8 -6
  16. data/app/components/primer/alpha/action_bar_element.d.ts +3 -2
  17. data/app/components/primer/alpha/action_bar_element.js +80 -97
  18. data/app/components/primer/alpha/action_bar_element.ts +84 -89
  19. data/app/components/primer/alpha/action_list/item.rb +13 -1
  20. data/app/components/primer/alpha/action_list.css +1 -1
  21. data/app/components/primer/alpha/action_list.css.json +1 -0
  22. data/app/components/primer/alpha/action_list.css.map +1 -1
  23. data/app/components/primer/alpha/action_list.pcss +3 -1
  24. data/app/components/primer/alpha/action_list.rb +5 -4
  25. data/app/components/primer/alpha/action_menu/action_menu_element.d.ts +20 -0
  26. data/app/components/primer/alpha/action_menu/action_menu_element.js +92 -15
  27. data/app/components/primer/alpha/action_menu/action_menu_element.ts +115 -13
  28. data/app/components/primer/alpha/action_menu/group.rb +23 -0
  29. data/app/components/primer/alpha/action_menu/heading.rb +17 -0
  30. data/app/components/primer/alpha/action_menu/list.html.erb +1 -0
  31. data/app/components/primer/alpha/action_menu/list.rb +62 -51
  32. data/app/components/primer/alpha/action_menu/list_wrapper.rb +40 -0
  33. data/app/components/primer/alpha/action_menu.rb +38 -1
  34. data/app/components/primer/alpha/banner.html.erb +1 -1
  35. data/app/components/primer/alpha/banner.rb +5 -1
  36. data/app/components/primer/alpha/dialog.html.erb +3 -1
  37. data/app/components/primer/alpha/dialog.rb +5 -1
  38. data/app/components/primer/alpha/layout.css +1 -1
  39. data/app/components/primer/alpha/layout.css.map +1 -1
  40. data/app/components/primer/alpha/modal_dialog.ts +1 -1
  41. data/app/components/primer/alpha/overlay.css +1 -1
  42. data/app/components/primer/alpha/overlay.css.json +4 -2
  43. data/app/components/primer/alpha/overlay.css.map +1 -1
  44. data/app/components/primer/alpha/overlay.pcss +12 -2
  45. data/app/components/primer/alpha/text_field.css +1 -1
  46. data/app/components/primer/alpha/text_field.css.map +1 -1
  47. data/app/components/primer/alpha/text_field.pcss +4 -3
  48. data/app/components/primer/alpha/tool_tip.js +22 -5
  49. data/app/components/primer/alpha/tool_tip.ts +24 -5
  50. data/app/components/primer/alpha/underline_nav.css +1 -1
  51. data/app/components/primer/alpha/underline_nav.css.map +1 -1
  52. data/app/components/primer/base_component.rb +20 -18
  53. data/app/components/primer/beta/auto_complete/auto_complete.html.erb +1 -7
  54. data/app/components/primer/beta/auto_complete/item.rb +1 -1
  55. data/app/components/primer/beta/auto_complete.rb +6 -1
  56. data/app/components/primer/beta/base_button.rb +2 -3
  57. data/app/components/primer/beta/blankslate.css +1 -1
  58. data/app/components/primer/beta/blankslate.css.map +1 -1
  59. data/app/components/primer/beta/blankslate.pcss +3 -3
  60. data/app/components/primer/beta/button.css +1 -1
  61. data/app/components/primer/beta/button.css.json +9 -8
  62. data/app/components/primer/beta/button.css.map +1 -1
  63. data/app/components/primer/beta/button.pcss +15 -11
  64. data/app/components/primer/beta/nav_list/group.html.erb +7 -5
  65. data/app/components/primer/beta/nav_list/group.rb +2 -2
  66. data/app/components/primer/beta/nav_list.d.ts +0 -11
  67. data/app/components/primer/beta/nav_list.js +2 -85
  68. data/app/components/primer/beta/nav_list.ts +1 -85
  69. data/app/components/primer/beta/nav_list_group_element.d.ts +19 -0
  70. data/app/components/primer/beta/nav_list_group_element.js +108 -0
  71. data/app/components/primer/beta/nav_list_group_element.ts +97 -0
  72. data/app/components/primer/beta/relative_time.rb +4 -4
  73. data/app/components/primer/component.rb +3 -0
  74. data/app/components/primer/primer.d.ts +2 -0
  75. data/app/components/primer/primer.js +2 -0
  76. data/app/components/primer/primer.ts +2 -0
  77. data/app/components/primer/scrollable_region.d.ts +13 -0
  78. data/app/components/primer/scrollable_region.js +52 -0
  79. data/app/components/primer/scrollable_region.ts +48 -0
  80. data/app/lib/primer/experimental_render_helpers.rb +32 -0
  81. data/app/lib/primer/experimental_slot_helpers.rb +30 -0
  82. data/lib/primer/classify/utilities.rb +3 -4
  83. data/lib/primer/view_components/version.rb +2 -2
  84. data/lib/primer/yard/lookbook_pages_backend.rb +2 -2
  85. data/previews/primer/alpha/action_menu_preview/in_scroll_container.html.erb +11 -0
  86. data/previews/primer/alpha/action_menu_preview.rb +80 -7
  87. data/previews/primer/alpha/banner_preview.rb +3 -2
  88. data/previews/primer/alpha/dialog_preview/with_auto_complete.html.erb +8 -0
  89. data/previews/primer/alpha/dialog_preview.rb +17 -0
  90. data/previews/primer/beta/blankslate_preview/inside_flex_container.html.erb +6 -0
  91. data/previews/primer/beta/blankslate_preview.rb +3 -0
  92. data/previews/primer/beta/nav_list_preview.rb +10 -1
  93. data/static/arguments.json +92 -1
  94. data/static/audited_at.json +4 -1
  95. data/static/classes.json +3 -0
  96. data/static/constants.json +9 -0
  97. data/static/info_arch.json +256 -52
  98. data/static/previews.json +52 -0
  99. data/static/statuses.json +3 -0
  100. metadata +19 -2
@@ -1,44 +1,9 @@
1
1
  /* eslint-disable custom-elements/expose-class-on-global */
2
- import {controller, target, targets} from '@github/catalyst'
2
+ import {controller, targets} from '@github/catalyst'
3
3
 
4
4
  @controller
5
5
  export class NavListElement extends HTMLElement {
6
6
  @targets items: HTMLElement[]
7
- @target showMoreItem: HTMLElement
8
- @targets focusMarkers: HTMLElement[]
9
-
10
- connectedCallback(): void {
11
- this.setShowMoreItemState()
12
- }
13
-
14
- get showMoreDisabled(): boolean {
15
- return this.showMoreItem.hasAttribute('aria-disabled')
16
- }
17
-
18
- set showMoreDisabled(value: boolean) {
19
- if (value) {
20
- this.showMoreItem.setAttribute('aria-disabled', 'true')
21
- } else {
22
- this.showMoreItem.removeAttribute('aria-disabled')
23
- }
24
- this.showMoreItem.classList.toggle('disabled', value)
25
- }
26
-
27
- set currentPage(value: number) {
28
- this.showMoreItem.setAttribute('data-current-page', value.toString())
29
- }
30
-
31
- get currentPage(): number {
32
- return parseInt(this.showMoreItem.getAttribute('data-current-page') as string) || 1
33
- }
34
-
35
- get totalPages(): number {
36
- return parseInt(this.showMoreItem.getAttribute('data-total-pages') as string) || 1
37
- }
38
-
39
- get paginationSrc(): string {
40
- return this.showMoreItem.getAttribute('src') || ''
41
- }
42
7
 
43
8
  selectItemById(itemId: string | null): boolean {
44
9
  if (!itemId) return false
@@ -134,55 +99,6 @@ export class NavListElement extends HTMLElement {
134
99
  e.stopPropagation()
135
100
  }
136
101
 
137
- private async showMore(e: Event) {
138
- e.preventDefault()
139
- if (this.showMoreDisabled) return
140
- this.showMoreDisabled = true
141
- let html
142
- try {
143
- const paginationURL = new URL(this.paginationSrc, window.location.origin)
144
- this.currentPage++
145
- paginationURL.searchParams.append('page', this.currentPage.toString())
146
- const response = await fetch(paginationURL)
147
- if (!response.ok) return
148
- html = await response.text()
149
- if (this.currentPage === this.totalPages) {
150
- this.showMoreItem.hidden = true
151
- }
152
- } catch (err) {
153
- // Ignore network errors
154
- this.showMoreDisabled = false
155
- this.currentPage--
156
- return
157
- }
158
- const fragment = this.#parseHTML(document, html)
159
- fragment?.querySelector('li > a')?.setAttribute('data-targets', 'nav-list.focusMarkers')
160
- const listId = (e.target as HTMLElement).closest('button')!.getAttribute('data-list-id')!
161
- const list = document.getElementById(listId)!
162
- list.append(fragment)
163
- this.focusMarkers.pop()?.focus()
164
- this.showMoreDisabled = false
165
- }
166
-
167
- private setShowMoreItemState() {
168
- if (!this.showMoreItem) {
169
- return
170
- }
171
-
172
- if (this.currentPage < this.totalPages) {
173
- this.showMoreItem.hidden = false
174
- } else {
175
- this.showMoreItem.hidden = true
176
- }
177
- }
178
-
179
- #parseHTML(document: Document, html: string): DocumentFragment {
180
- const template = document.createElement('template')
181
- // eslint-disable-next-line github/no-inner-html
182
- template.innerHTML = html
183
- return document.importNode(template.content, true)
184
- }
185
-
186
102
  #findSelectedNavItemById(itemId: string): HTMLElement | null {
187
103
  // First we compare the selected link to data-item-id for each nav item
188
104
  for (const navItem of this.items) {
@@ -0,0 +1,19 @@
1
+ export declare class NavListGroupElement extends HTMLElement {
2
+ #private;
3
+ showMoreItem: HTMLElement;
4
+ focusMarkers: HTMLElement[];
5
+ connectedCallback(): void;
6
+ get showMoreDisabled(): boolean;
7
+ set showMoreDisabled(value: boolean);
8
+ set currentPage(value: number);
9
+ get currentPage(): number;
10
+ get totalPages(): number;
11
+ get paginationSrc(): string;
12
+ private showMore;
13
+ private setShowMoreItemState;
14
+ }
15
+ declare global {
16
+ interface Window {
17
+ NavListGroupElement: typeof NavListGroupElement;
18
+ }
19
+ }
@@ -0,0 +1,108 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _NavListGroupElement_instances, _NavListGroupElement_parseHTML;
13
+ import { controller, target, targets } from '@github/catalyst';
14
+ let NavListGroupElement = class NavListGroupElement extends HTMLElement {
15
+ constructor() {
16
+ super(...arguments);
17
+ _NavListGroupElement_instances.add(this);
18
+ }
19
+ connectedCallback() {
20
+ this.setShowMoreItemState();
21
+ }
22
+ get showMoreDisabled() {
23
+ return this.showMoreItem.hasAttribute('aria-disabled');
24
+ }
25
+ set showMoreDisabled(value) {
26
+ if (value) {
27
+ this.showMoreItem.setAttribute('aria-disabled', 'true');
28
+ }
29
+ else {
30
+ this.showMoreItem.removeAttribute('aria-disabled');
31
+ }
32
+ this.showMoreItem.classList.toggle('disabled', value);
33
+ }
34
+ set currentPage(value) {
35
+ this.showMoreItem.setAttribute('data-current-page', value.toString());
36
+ }
37
+ get currentPage() {
38
+ return parseInt(this.showMoreItem.getAttribute('data-current-page')) || 1;
39
+ }
40
+ get totalPages() {
41
+ return parseInt(this.showMoreItem.getAttribute('data-total-pages')) || 1;
42
+ }
43
+ get paginationSrc() {
44
+ return this.showMoreItem.getAttribute('src') || '';
45
+ }
46
+ async showMore(e) {
47
+ var _a, _b;
48
+ e.preventDefault();
49
+ if (this.showMoreDisabled)
50
+ return;
51
+ this.showMoreDisabled = true;
52
+ let html;
53
+ try {
54
+ const paginationURL = new URL(this.paginationSrc, window.location.origin);
55
+ this.currentPage++;
56
+ paginationURL.searchParams.append('page', this.currentPage.toString());
57
+ const response = await fetch(paginationURL);
58
+ if (!response.ok)
59
+ return;
60
+ html = await response.text();
61
+ if (this.currentPage === this.totalPages) {
62
+ this.showMoreItem.hidden = true;
63
+ }
64
+ }
65
+ catch (err) {
66
+ // Ignore network errors
67
+ this.showMoreDisabled = false;
68
+ this.currentPage--;
69
+ return;
70
+ }
71
+ const fragment = __classPrivateFieldGet(this, _NavListGroupElement_instances, "m", _NavListGroupElement_parseHTML).call(this, document, html);
72
+ (_a = fragment === null || fragment === void 0 ? void 0 : fragment.querySelector('li > a')) === null || _a === void 0 ? void 0 : _a.setAttribute('data-targets', 'nav-list-group.focusMarkers');
73
+ const listId = e.target.closest('button').getAttribute('data-list-id');
74
+ const list = document.getElementById(listId);
75
+ list.append(fragment);
76
+ (_b = this.focusMarkers.pop()) === null || _b === void 0 ? void 0 : _b.focus();
77
+ this.showMoreDisabled = false;
78
+ }
79
+ setShowMoreItemState() {
80
+ if (!this.showMoreItem) {
81
+ return;
82
+ }
83
+ if (this.currentPage < this.totalPages) {
84
+ this.showMoreItem.hidden = false;
85
+ }
86
+ else {
87
+ this.showMoreItem.hidden = true;
88
+ }
89
+ }
90
+ };
91
+ _NavListGroupElement_instances = new WeakSet();
92
+ _NavListGroupElement_parseHTML = function _NavListGroupElement_parseHTML(document, html) {
93
+ const template = document.createElement('template');
94
+ // eslint-disable-next-line github/no-inner-html
95
+ template.innerHTML = html;
96
+ return document.importNode(template.content, true);
97
+ };
98
+ __decorate([
99
+ target
100
+ ], NavListGroupElement.prototype, "showMoreItem", void 0);
101
+ __decorate([
102
+ targets
103
+ ], NavListGroupElement.prototype, "focusMarkers", void 0);
104
+ NavListGroupElement = __decorate([
105
+ controller
106
+ ], NavListGroupElement);
107
+ export { NavListGroupElement };
108
+ window.NavListGroupElement = NavListGroupElement;
@@ -0,0 +1,97 @@
1
+ import {controller, target, targets} from '@github/catalyst'
2
+
3
+ @controller
4
+ export class NavListGroupElement extends HTMLElement {
5
+ @target showMoreItem: HTMLElement
6
+ @targets focusMarkers: HTMLElement[]
7
+
8
+ connectedCallback(): void {
9
+ this.setShowMoreItemState()
10
+ }
11
+
12
+ get showMoreDisabled(): boolean {
13
+ return this.showMoreItem.hasAttribute('aria-disabled')
14
+ }
15
+
16
+ set showMoreDisabled(value: boolean) {
17
+ if (value) {
18
+ this.showMoreItem.setAttribute('aria-disabled', 'true')
19
+ } else {
20
+ this.showMoreItem.removeAttribute('aria-disabled')
21
+ }
22
+ this.showMoreItem.classList.toggle('disabled', value)
23
+ }
24
+
25
+ set currentPage(value: number) {
26
+ this.showMoreItem.setAttribute('data-current-page', value.toString())
27
+ }
28
+
29
+ get currentPage(): number {
30
+ return parseInt(this.showMoreItem.getAttribute('data-current-page') as string) || 1
31
+ }
32
+
33
+ get totalPages(): number {
34
+ return parseInt(this.showMoreItem.getAttribute('data-total-pages') as string) || 1
35
+ }
36
+
37
+ get paginationSrc(): string {
38
+ return this.showMoreItem.getAttribute('src') || ''
39
+ }
40
+
41
+ private async showMore(e: Event) {
42
+ e.preventDefault()
43
+ if (this.showMoreDisabled) return
44
+ this.showMoreDisabled = true
45
+ let html
46
+ try {
47
+ const paginationURL = new URL(this.paginationSrc, window.location.origin)
48
+ this.currentPage++
49
+ paginationURL.searchParams.append('page', this.currentPage.toString())
50
+ const response = await fetch(paginationURL)
51
+ if (!response.ok) return
52
+ html = await response.text()
53
+ if (this.currentPage === this.totalPages) {
54
+ this.showMoreItem.hidden = true
55
+ }
56
+ } catch (err) {
57
+ // Ignore network errors
58
+ this.showMoreDisabled = false
59
+ this.currentPage--
60
+ return
61
+ }
62
+ const fragment = this.#parseHTML(document, html)
63
+ fragment?.querySelector('li > a')?.setAttribute('data-targets', 'nav-list-group.focusMarkers')
64
+ const listId = (e.target as HTMLElement).closest('button')!.getAttribute('data-list-id')!
65
+ const list = document.getElementById(listId)!
66
+ list.append(fragment)
67
+ this.focusMarkers.pop()?.focus()
68
+ this.showMoreDisabled = false
69
+ }
70
+
71
+ private setShowMoreItemState() {
72
+ if (!this.showMoreItem) {
73
+ return
74
+ }
75
+
76
+ if (this.currentPage < this.totalPages) {
77
+ this.showMoreItem.hidden = false
78
+ } else {
79
+ this.showMoreItem.hidden = true
80
+ }
81
+ }
82
+
83
+ #parseHTML(document: Document, html: string): DocumentFragment {
84
+ const template = document.createElement('template')
85
+ // eslint-disable-next-line github/no-inner-html
86
+ template.innerHTML = html
87
+ return document.importNode(template.content, true)
88
+ }
89
+ }
90
+
91
+ declare global {
92
+ interface Window {
93
+ NavListGroupElement: typeof NavListGroupElement
94
+ }
95
+ }
96
+
97
+ window.NavListGroupElement = NavListGroupElement
@@ -52,7 +52,7 @@ module Primer
52
52
 
53
53
  MONTH_DEFAULT = nil
54
54
  MONTH_MAPPINGS = {
55
- DAY_DEFAULT => nil,
55
+ MONTH_DEFAULT => nil,
56
56
  :numeric => "numeric",
57
57
  :two_digit => "2-digit",
58
58
  :short => "short",
@@ -63,7 +63,7 @@ module Primer
63
63
 
64
64
  YEAR_DEFAULT = nil
65
65
  YEAR_MAPPINGS = {
66
- DAY_DEFAULT => nil,
66
+ YEAR_DEFAULT => nil,
67
67
  :numeric => "numeric",
68
68
  :two_digit => "2-digit"
69
69
  }.freeze
@@ -71,7 +71,7 @@ module Primer
71
71
 
72
72
  TIMEZONENAME_DEFAULT = nil
73
73
  TIMEZONE_MAPPINGS = {
74
- DAY_DEFAULT => nil,
74
+ TIMEZONENAME_DEFAULT => nil,
75
75
  :long => "long",
76
76
  :short => "short",
77
77
  :short_offset => "shortOffset",
@@ -131,7 +131,7 @@ module Primer
131
131
  @system_arguments[:hour] = fetch_or_fallback(HOUR_OPTIONS, hour, HOUR_DEFAULT) if hour.present?
132
132
  @system_arguments[:weekday] = fetch_or_fallback(WEEKDAY_OPTIONS, weekday, WEEKDAY_DEFAULT) if weekday.present?
133
133
  @system_arguments[:day] = fetch_or_fallback(DAY_OPTIONS, day, DAY_DEFAULT) if day.present?
134
- @system_arguments[:month] = fetch_or_fallback(MONTH_DEFAULT, month, MONTH_DEFAULT) if month.present?
134
+ @system_arguments[:month] = fetch_or_fallback(MONTH_OPTIONS, month, MONTH_DEFAULT) if month.present?
135
135
  @system_arguments[:year] = fetch_or_fallback(YEAR_OPTIONS, year, YEAR_DEFAULT) if year.present?
136
136
  @system_arguments[:"time-zone-name"] = fetch_or_fallback(TIMEZONENAME_OPTIONS, time_zone_name, TIMEZONENAME_DEFAULT) if time_zone_name.present?
137
137
  @system_arguments[:threshold] = threshold if threshold.present?
@@ -16,6 +16,9 @@ module Primer
16
16
  include ViewComponent::PolymorphicSlots
17
17
  end
18
18
 
19
+ include ExperimentalRenderHelpers
20
+ include ExperimentalSlotHelpers
21
+
19
22
  include AttributesHelper
20
23
  include ClassNameHelper
21
24
  include FetchOrFallbackHelper
@@ -3,9 +3,11 @@ import './alpha/action_bar_element';
3
3
  import './alpha/dropdown';
4
4
  import './anchored_position';
5
5
  import './focus_group';
6
+ import './scrollable_region';
6
7
  import './alpha/image_crop';
7
8
  import './alpha/modal_dialog';
8
9
  import './beta/nav_list';
10
+ import './beta/nav_list_group_element';
9
11
  import './alpha/segmented_control';
10
12
  import './alpha/toggle_switch';
11
13
  import './alpha/tool_tip';
@@ -3,9 +3,11 @@ import './alpha/action_bar_element';
3
3
  import './alpha/dropdown';
4
4
  import './anchored_position';
5
5
  import './focus_group';
6
+ import './scrollable_region';
6
7
  import './alpha/image_crop';
7
8
  import './alpha/modal_dialog';
8
9
  import './beta/nav_list';
10
+ import './beta/nav_list_group_element';
9
11
  import './alpha/segmented_control';
10
12
  import './alpha/toggle_switch';
11
13
  import './alpha/tool_tip';
@@ -3,9 +3,11 @@ import './alpha/action_bar_element'
3
3
  import './alpha/dropdown'
4
4
  import './anchored_position'
5
5
  import './focus_group'
6
+ import './scrollable_region'
6
7
  import './alpha/image_crop'
7
8
  import './alpha/modal_dialog'
8
9
  import './beta/nav_list'
10
+ import './beta/nav_list_group_element'
9
11
  import './alpha/segmented_control'
10
12
  import './alpha/toggle_switch'
11
13
  import './alpha/tool_tip'
@@ -0,0 +1,13 @@
1
+ export declare class ScrollableRegionElement extends HTMLElement {
2
+ hasOverflow: boolean;
3
+ labelledBy: string;
4
+ observer: ResizeObserver;
5
+ connectedCallback(): void;
6
+ disconnectedCallback(): void;
7
+ attributeChangedCallback(name: string): void;
8
+ }
9
+ declare global {
10
+ interface Window {
11
+ ScrollableRegionElement: typeof ScrollableRegionElement;
12
+ }
13
+ }
@@ -0,0 +1,52 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { controller, attr } from '@github/catalyst';
8
+ let ScrollableRegionElement = class ScrollableRegionElement extends HTMLElement {
9
+ constructor() {
10
+ super(...arguments);
11
+ this.hasOverflow = false;
12
+ this.labelledBy = '';
13
+ }
14
+ connectedCallback() {
15
+ this.style.overflow = 'auto';
16
+ this.observer = new ResizeObserver(entries => {
17
+ for (const entry of entries) {
18
+ this.hasOverflow =
19
+ entry.target.scrollHeight > entry.target.clientHeight || entry.target.scrollWidth > entry.target.clientWidth;
20
+ }
21
+ });
22
+ this.observer.observe(this);
23
+ }
24
+ disconnectedCallback() {
25
+ this.observer.disconnect();
26
+ }
27
+ attributeChangedCallback(name) {
28
+ if (name === 'data-has-overflow') {
29
+ if (this.hasOverflow) {
30
+ this.setAttribute('aria-labelledby', this.labelledBy);
31
+ this.setAttribute('role', 'region');
32
+ this.setAttribute('tabindex', '0');
33
+ }
34
+ else {
35
+ this.removeAttribute('aria-labelledby');
36
+ this.removeAttribute('role');
37
+ this.removeAttribute('tabindex');
38
+ }
39
+ }
40
+ }
41
+ };
42
+ __decorate([
43
+ attr
44
+ ], ScrollableRegionElement.prototype, "hasOverflow", void 0);
45
+ __decorate([
46
+ attr
47
+ ], ScrollableRegionElement.prototype, "labelledBy", void 0);
48
+ ScrollableRegionElement = __decorate([
49
+ controller
50
+ ], ScrollableRegionElement);
51
+ export { ScrollableRegionElement };
52
+ window.ScrollableRegionElement = ScrollableRegionElement;
@@ -0,0 +1,48 @@
1
+ import {controller, attr} from '@github/catalyst'
2
+
3
+ @controller
4
+ export class ScrollableRegionElement extends HTMLElement {
5
+ @attr hasOverflow = false
6
+ @attr labelledBy = ''
7
+
8
+ observer: ResizeObserver
9
+
10
+ connectedCallback() {
11
+ this.style.overflow = 'auto'
12
+
13
+ this.observer = new ResizeObserver(entries => {
14
+ for (const entry of entries) {
15
+ this.hasOverflow =
16
+ entry.target.scrollHeight > entry.target.clientHeight || entry.target.scrollWidth > entry.target.clientWidth
17
+ }
18
+ })
19
+
20
+ this.observer.observe(this)
21
+ }
22
+
23
+ disconnectedCallback() {
24
+ this.observer.disconnect()
25
+ }
26
+
27
+ attributeChangedCallback(name: string) {
28
+ if (name === 'data-has-overflow') {
29
+ if (this.hasOverflow) {
30
+ this.setAttribute('aria-labelledby', this.labelledBy)
31
+ this.setAttribute('role', 'region')
32
+ this.setAttribute('tabindex', '0')
33
+ } else {
34
+ this.removeAttribute('aria-labelledby')
35
+ this.removeAttribute('role')
36
+ this.removeAttribute('tabindex')
37
+ }
38
+ }
39
+ }
40
+ }
41
+
42
+ declare global {
43
+ interface Window {
44
+ ScrollableRegionElement: typeof ScrollableRegionElement
45
+ }
46
+ }
47
+
48
+ window.ScrollableRegionElement = ScrollableRegionElement
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ # :nodoc:
5
+ module ExperimentalRenderHelpers
6
+ def self.included(base)
7
+ base.include(InstanceMethods)
8
+ end
9
+
10
+ # :nodoc:
11
+ module InstanceMethods
12
+ def evaluate_block(*args, **kwargs, &block)
13
+ # Prevent double renders by using the capture method on the component
14
+ # that originally received the block.
15
+ #
16
+ # Handle blocks that originate from C code such as `&:method` by checking
17
+ # source_location. Such blocks don't allow access to their receiver.
18
+ return unless block
19
+
20
+ return yield(*args, **kwargs) if block&.source_location.nil?
21
+
22
+ block_context = block.binding.receiver
23
+
24
+ if block_context.class < ActionView::Base
25
+ block_context.capture(*args, &block)
26
+ else
27
+ capture(*args, &block)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ # :nodoc:
5
+ module ExperimentalSlotHelpers
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ # :nodoc:
11
+ module ClassMethods
12
+ def add_polymorphic_slot_type(slot_name:, type:, callable:)
13
+ slot_def = registered_slots[slot_name]
14
+ raise "Unknown slot '#{slot_name}'" unless slot_def
15
+
16
+ poly_def = define_slot(
17
+ type,
18
+ collection: slot_def[:collection],
19
+ callable: callable
20
+ )
21
+
22
+ registered_slots[slot_name][:renderable_hash][type] = poly_def
23
+
24
+ define_method(:"with_#{type}") do |**system_arguments, &block|
25
+ set_slot(slot_name, poly_def, **system_arguments, &block)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -27,7 +27,9 @@ module Primer
27
27
  "^height" => "h",
28
28
  "^color-bg" => "bg",
29
29
  "^color-border" => "border_color",
30
- "^color-fg" => "color"
30
+ "^color-fg" => "color",
31
+ "^f" => "font_size",
32
+ "^rounded" => "border_radius"
31
33
  }.freeze
32
34
 
33
35
  SUPPORTED_KEY_CACHE = Hash.new { |h, k| h[k] = !UTILITIES[k].nil? }
@@ -91,9 +93,6 @@ module Primer
91
93
 
92
94
  # Extract hash from classes ie. "mr-1 mb-2 foo" => { mr: 1, mb: 2, classes: "foo" }
93
95
  def classes_to_hash(classes)
94
- # This method is too slow to run in production
95
- return { classes: classes } unless validate_class_names?
96
-
97
96
  obj = {}
98
97
  classes = classes.split
99
98
  # Loop through all classes supplied and reject ones we find a match for
@@ -5,8 +5,8 @@ module Primer
5
5
  module ViewComponents
6
6
  module VERSION
7
7
  MAJOR = 0
8
- MINOR = 18
9
- PATCH = 1
8
+ MINOR = 20
9
+ PATCH = 0
10
10
 
11
11
  STRING = [MAJOR, MINOR, PATCH].join(".")
12
12
  end
@@ -218,8 +218,8 @@ module Primer
218
218
  path, <<~ERB
219
219
  #{YAML.dump(frontmatter)}
220
220
  ---
221
- <%= @page.data[:description_md] %>
222
- <%= @page.data[:args_md] %>
221
+ <%= @page.data[:description_md].html_safe %>
222
+ <%= @page.data[:args_md].html_safe %>
223
223
  ERB
224
224
  )
225
225
  end
@@ -0,0 +1,11 @@
1
+ <div style="height: 400px"></div>
2
+
3
+ <div style="position: relative">
4
+ <%= render Primer::Alpha::ActionMenu.new(anchor_align: :end) do |c| %>
5
+ <% c.with_show_button { "Edit" } %>
6
+ <% c.with_item(tag: :button, type: "button", label: "Rename") %>
7
+ <% c.with_item(tag: :button, type: "button", scheme: :danger, label: "Remove") %>
8
+ <% end %>
9
+ </div>
10
+
11
+ <div style="height: 1400px"></div>