openproject-primer_view_components 0.89.2 → 0.91.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -0
- data/app/assets/javascripts/primer_view_components.js +1 -1
- data/app/assets/javascripts/primer_view_components.js.map +1 -1
- data/app/assets/styles/primer_view_components.css +1 -1
- data/app/assets/styles/primer_view_components.css.map +1 -1
- data/app/components/primer/alpha/action_bar.css.map +1 -1
- data/app/components/primer/alpha/action_bar.pcss +0 -3
- data/app/components/primer/alpha/action_list.css.map +1 -1
- data/app/components/primer/alpha/action_list.pcss +0 -2
- data/app/components/primer/alpha/auto_complete.css +1 -1
- data/app/components/primer/alpha/auto_complete.css.json +2 -4
- data/app/components/primer/alpha/auto_complete.css.map +1 -1
- data/app/components/primer/alpha/auto_complete.pcss +3 -10
- data/app/components/primer/alpha/banner.css.map +1 -1
- data/app/components/primer/alpha/banner.pcss +0 -1
- data/app/components/primer/alpha/button_marketing.css.map +1 -1
- data/app/components/primer/alpha/button_marketing.pcss +4 -4
- data/app/components/primer/alpha/layout.css +1 -1
- data/app/components/primer/alpha/layout.css.map +1 -1
- data/app/components/primer/alpha/layout.pcss +3 -1
- data/app/components/primer/alpha/menu.css.map +1 -1
- data/app/components/primer/alpha/menu.pcss +0 -6
- data/app/components/primer/alpha/segmented_control.css.map +1 -1
- data/app/components/primer/alpha/segmented_control.pcss +0 -2
- data/app/components/primer/alpha/tab_nav.css.map +1 -1
- data/app/components/primer/alpha/tab_nav.pcss +0 -5
- data/app/components/primer/alpha/text_field.css +1 -1
- data/app/components/primer/alpha/text_field.css.json +2 -1
- data/app/components/primer/alpha/text_field.css.map +1 -1
- data/app/components/primer/alpha/text_field.pcss +14 -7
- data/app/components/primer/alpha/toggle_switch.css +1 -1
- data/app/components/primer/alpha/toggle_switch.css.map +1 -1
- data/app/components/primer/alpha/toggle_switch.pcss +8 -6
- data/app/components/primer/alpha/tree_view/sub_tree_node.rb +2 -2
- data/app/components/primer/alpha/tree_view.css.map +1 -1
- data/app/components/primer/alpha/tree_view.pcss +1 -0
- data/app/components/primer/alpha/underline_nav.css.map +1 -1
- data/app/components/primer/alpha/underline_nav.pcss +0 -3
- data/app/components/primer/base_component.rb +1 -0
- data/app/components/primer/beta/blankslate.css +1 -1
- data/app/components/primer/beta/blankslate.css.map +1 -1
- data/app/components/primer/beta/blankslate.pcss +2 -53
- data/app/components/primer/beta/breadcrumbs.css +1 -1
- data/app/components/primer/beta/breadcrumbs.css.json +2 -1
- data/app/components/primer/beta/breadcrumbs.css.map +1 -1
- data/app/components/primer/beta/breadcrumbs.pcss +6 -5
- data/app/components/primer/beta/button.css.map +1 -1
- data/app/components/primer/beta/button.pcss +0 -1
- data/app/components/primer/beta/popover.css +1 -1
- data/app/components/primer/beta/popover.css.json +22 -16
- data/app/components/primer/beta/popover.css.map +1 -1
- data/app/components/primer/beta/popover.pcss +132 -101
- data/app/components/primer/beta/state.css.map +1 -1
- data/app/components/primer/beta/state.pcss +0 -1
- data/app/components/primer/beta/subhead.css.map +1 -1
- data/app/components/primer/beta/subhead.pcss +0 -2
- data/app/components/primer/beta/timeline_item.css.map +1 -1
- data/app/components/primer/beta/timeline_item.pcss +0 -5
- data/app/components/primer/beta/truncate.css.map +1 -1
- data/app/components/primer/beta/truncate.pcss +0 -1
- data/app/components/primer/component.rb +16 -0
- data/app/components/primer/open_project/border_box/collapsible_header.css.map +1 -1
- data/app/components/primer/open_project/border_box/collapsible_header.html.erb +1 -1
- data/app/components/primer/open_project/border_box/collapsible_header.pcss +3 -1
- data/app/components/primer/open_project/border_box/collapsible_header.rb +10 -9
- data/app/components/primer/open_project/border_grid.css +1 -1
- data/app/components/primer/open_project/border_grid.css.map +1 -1
- data/app/components/primer/open_project/border_grid.pcss +11 -9
- data/app/components/primer/open_project/collapsible.d.ts +1 -1
- data/app/components/primer/open_project/collapsible.js +8 -4
- data/app/components/primer/open_project/collapsible.ts +10 -4
- data/app/components/primer/open_project/collapsible_section.html.erb +6 -10
- data/app/components/primer/open_project/collapsible_section.rb +8 -0
- data/app/components/primer/open_project/filterable_tree_view.css.map +1 -1
- data/app/components/primer/open_project/filterable_tree_view.pcss +2 -0
- data/app/components/primer/open_project/page_header.css.map +1 -1
- data/app/components/primer/open_project/page_header.pcss +2 -0
- data/app/components/primer/open_project/pagination.css +1 -1
- data/app/components/primer/open_project/pagination.css.map +1 -1
- data/app/components/primer/open_project/pagination.pcss +4 -1
- data/app/components/primer/open_project/side_panel/section.css +1 -1
- data/app/components/primer/open_project/side_panel/section.css.map +1 -1
- data/app/components/primer/open_project/side_panel/section.pcss +3 -3
- data/app/controllers/primer/view_components/tree_view_items_controller.rb +2 -1
- data/app/lib/primer/forms/dsl/input.rb +5 -1
- data/app/lib/primer/safe_href_helper.rb +36 -0
- data/app/views/primer/view_components/tree_view_items/async_alpha.html_fragment.erb +4 -4
- data/lib/primer/static/generate_previews.rb +1 -1
- data/lib/primer/view_components/version.rb +2 -2
- data/previews/primer/alpha/tree_view_preview/async_alpha.html.erb +2 -2
- data/previews/primer/alpha/tree_view_preview/async_form_input.html.erb +16 -0
- data/previews/primer/alpha/tree_view_preview.rb +13 -2
- data/previews/primer/open_project/collapsible_section_preview/with_link_in_title.html.erb +6 -0
- data/previews/primer/open_project/collapsible_section_preview.rb +9 -0
- data/static/classes.json +21 -0
- data/static/classnames.cjs +507 -0
- data/static/classnames.d.ts +2 -0
- data/static/classnames.js +509 -0
- data/static/info_arch.json +26 -0
- data/static/previews.json +2404 -2378
- metadata +9 -3
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {attr, target, targets} from '@github/catalyst'
|
|
2
2
|
|
|
3
|
-
// eslint-disable-next-line custom-elements/expose-class-on-global
|
|
4
3
|
export abstract class CollapsibleElement extends HTMLElement {
|
|
5
4
|
@target arrowDown: Element
|
|
6
5
|
@target arrowUp: Element
|
|
@@ -11,12 +10,19 @@ export abstract class CollapsibleElement extends HTMLElement {
|
|
|
11
10
|
|
|
12
11
|
toggleViaKeyboard(event: KeyboardEvent) {
|
|
13
12
|
if (event.code === 'Enter' || event.code === 'Space') {
|
|
14
|
-
|
|
15
|
-
this.toggle()
|
|
13
|
+
this.toggle(event)
|
|
16
14
|
}
|
|
17
15
|
}
|
|
18
16
|
|
|
19
|
-
toggle() {
|
|
17
|
+
toggle(event?: Event) {
|
|
18
|
+
if (
|
|
19
|
+
event &&
|
|
20
|
+
event.target instanceof Element &&
|
|
21
|
+
!event.target.closest('[data-collapsible-toggle]') &&
|
|
22
|
+
event.target.closest('a, button')
|
|
23
|
+
)
|
|
24
|
+
return
|
|
25
|
+
event?.preventDefault()
|
|
20
26
|
this.collapsed = !this.collapsed
|
|
21
27
|
}
|
|
22
28
|
|
|
@@ -2,23 +2,19 @@
|
|
|
2
2
|
<%= render(Primer::OpenProject::FlexLayout.new) do |flex| %>
|
|
3
3
|
<%= flex.with_row(classes: "CollapsibleSection--triggerArea",
|
|
4
4
|
id: @title_id,
|
|
5
|
-
|
|
6
|
-
role: "button",
|
|
7
|
-
data: {
|
|
8
|
-
action: "click:collapsible-section#toggle keydown:collapsible-section#toggleViaKeyboard",
|
|
9
|
-
target: "collapsible-section.triggerElement"
|
|
10
|
-
},
|
|
11
|
-
aria: { expanded: !@collapsed, controls: @content_id }) do %>
|
|
5
|
+
data: { action: "click:collapsible-section#toggle" }) do %>
|
|
12
6
|
<%= render(Primer::OpenProject::FlexLayout.new(display: :flex, align_items: :center)) do |header| %>
|
|
13
|
-
<%= header.with_column do %>
|
|
7
|
+
<%= header.with_column(id: @heading_id) do %>
|
|
14
8
|
<%= title %>
|
|
15
9
|
<% end %>
|
|
16
10
|
<%= header.with_column do %>
|
|
17
11
|
<%= caption %>
|
|
18
12
|
<% end %>
|
|
19
13
|
<%= header.with_column do %>
|
|
20
|
-
<%= render(Primer::Beta::
|
|
21
|
-
|
|
14
|
+
<%= render(Primer::Beta::Button.new(**@toggle_button_arguments)) do %>
|
|
15
|
+
<%= render(Primer::Beta::Octicon.new(icon: "chevron-up", hidden: @collapsed, data: { target: "collapsible-section.arrowUp" })) %>
|
|
16
|
+
<%= render(Primer::Beta::Octicon.new(icon: "chevron-down", hidden: !@collapsed, data: { target: "collapsible-section.arrowDown" })) %>
|
|
17
|
+
<% end %>
|
|
22
18
|
<% end %>
|
|
23
19
|
<%= header.with_column(flex: 1, text_align: :right) do %>
|
|
24
20
|
<%= additional_information %>
|
|
@@ -53,6 +53,7 @@ module Primer
|
|
|
53
53
|
def initialize(id: self.class.generate_id, collapsed: false, **system_arguments)
|
|
54
54
|
@title_id = "#{id}-title"
|
|
55
55
|
@content_id = "#{id}-content"
|
|
56
|
+
@heading_id = "#{id}-heading"
|
|
56
57
|
@collapsed = collapsed
|
|
57
58
|
|
|
58
59
|
@system_arguments = deny_tag_argument(**system_arguments)
|
|
@@ -66,6 +67,13 @@ module Primer
|
|
|
66
67
|
|
|
67
68
|
@system_arguments[:data] ||= {}
|
|
68
69
|
@system_arguments[:data][:collapsed] = true if @collapsed
|
|
70
|
+
|
|
71
|
+
@toggle_button_arguments = {
|
|
72
|
+
scheme: :invisible,
|
|
73
|
+
type: :button,
|
|
74
|
+
data: { target: "collapsible-section.triggerElement", "collapsible-toggle": "" },
|
|
75
|
+
aria: { expanded: !@collapsed, controls: @content_id, labelledby: @heading_id }
|
|
76
|
+
}
|
|
69
77
|
end
|
|
70
78
|
|
|
71
79
|
private
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["filterable_tree_view.pcss"],"names":[],"mappings":"AAYA,qBACE,YAAa,CACb,qBAAsB,CACtB,eAAgB,CAChB,kBACF,CAEA,0BACE,MAAO,CACP,YACF,CAEA,iCACE,MAAO,CACP,YAAa,CACb,eACF,CAGA,
|
|
1
|
+
{"version":3,"sources":["filterable_tree_view.pcss"],"names":[],"mappings":"AAYA,qBACE,YAAa,CACb,qBAAsB,CACtB,eAAgB,CAChB,kBACF,CAEA,0BACE,MAAO,CACP,YACF,CAEA,iCACE,MAAO,CACP,YAAa,CACb,eACF,CAGA,wDAEE,8CACF,CAIA,0BAEE,8CAA+C,CAC/C,aACF,CAGA,mCACE,YACF,CAIA,sEACE,aACF,CAEA,uIAEE,YACF","file":"filterable_tree_view.css","sourcesContent":["/* CSS for FilterableTreeView */\n\n/* Scroll layout\n *\n * The filterable-tree-view element itself acts as a flex column container.\n * The toolbar (input, segmented control, checkbox) is fixed at the top.\n * Only the tree area scrolls. The consumer is responsible for setting a\n * height or max-height on the filterable-tree-view element (or its parent)\n * to activate scrolling.\n */\n\n/* stylelint-disable-next-line selector-max-type */\nfilterable-tree-view {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n max-height: inherit;\n}\n\n.FilterableTreeViewLayout {\n flex: 1;\n min-height: 0;\n}\n\n.FilterableTreeViewTreeContainer {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n}\n\n/* Highlight style for CSS Custom Highlight API */\n::highlight(primer-filterable-tree-view-search-results) {\n /* stylelint-disable-next-line primer/no-display-colors, primer/colors -- intentional yellow search-match highlight; no Primer semantic token exists for this */\n background-color: var(--display-yellow-scale-2);\n}\n\n/* Fallback: <mark> elements used when CSS Custom Highlight API is unavailable */\n/* stylelint-disable-next-line selector-max-type */\nfilterable-tree-view mark {\n /* stylelint-disable-next-line primer/no-display-colors, primer/colors -- intentional yellow search-match highlight; no Primer semantic token exists for this */\n background-color: var(--display-yellow-scale-2);\n color: inherit;\n}\n\n/* Loading skeleton */\n.FilterableTreeViewLoadingSkeleton {\n display: none;\n}\n\n/* stylelint-disable selector-no-qualifying-type */\n/* stylelint-disable selector-max-type */\nfilterable-tree-view[data-loading] .FilterableTreeViewLoadingSkeleton {\n display: block;\n}\n\nfilterable-tree-view[data-loading] tree-view,\nfilterable-tree-view[data-loading] [data-target~=\"filterable-tree-view.noResultsMessage\"] {\n display: none;\n}\n"]}
|
|
@@ -30,12 +30,14 @@ filterable-tree-view {
|
|
|
30
30
|
|
|
31
31
|
/* Highlight style for CSS Custom Highlight API */
|
|
32
32
|
::highlight(primer-filterable-tree-view-search-results) {
|
|
33
|
+
/* stylelint-disable-next-line primer/no-display-colors, primer/colors -- intentional yellow search-match highlight; no Primer semantic token exists for this */
|
|
33
34
|
background-color: var(--display-yellow-scale-2);
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
/* Fallback: <mark> elements used when CSS Custom Highlight API is unavailable */
|
|
37
38
|
/* stylelint-disable-next-line selector-max-type */
|
|
38
39
|
filterable-tree-view mark {
|
|
40
|
+
/* stylelint-disable-next-line primer/no-display-colors, primer/colors -- intentional yellow search-match highlight; no Primer semantic token exists for this */
|
|
39
41
|
background-color: var(--display-yellow-scale-2);
|
|
40
42
|
color: inherit;
|
|
41
43
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["page_header.pcss"],"names":[],"mappings":"AAEA,YACE,YAAa,CACb,iCAAkC,CAClC,iCAAkC,CAClC,oEAAqE,CACrE,gBACF,CAEA,wBACE,kBAAmB,CACnB,gBAAiB,CACjB,eACF,CAEA,uBAME,gCACF,CAEA,4CARE,YAAa,CACb,aAAc,CACd,wBAAyB,CACzB,kBAAmB,CACnB,gCAUF,CAEA,kBACE,uCAAwC,CACxC,aACF,CAEA,yBACE,sCACF,CAGA,wBACE,sCAAuC,CACvC,0BAA2B,CAC3B,WACF,
|
|
1
|
+
{"version":3,"sources":["page_header.pcss"],"names":[],"mappings":"AAEA,YACE,YAAa,CACb,iCAAkC,CAClC,iCAAkC,CAClC,oEAAqE,CACrE,gBACF,CAEA,wBACE,kBAAmB,CACnB,gBAAiB,CACjB,eACF,CAEA,uBAME,gCACF,CAEA,4CARE,YAAa,CACb,aAAc,CACd,wBAAyB,CACzB,kBAAmB,CACnB,gCAUF,CAEA,kBACE,uCAAwC,CACxC,aACF,CAEA,yBACE,sCACF,CAGA,wBACE,sCAAuC,CACvC,0BAA2B,CAC3B,WACF,CAGA,4CAEE,iCAA0B,CAA1B,yBACF,CAEA,sBACE,aACF,CAEA,yCACE,qBACF,CAEA,gDACE,iCACF,CAEA,oBACE,wBAAyB,CACzB,YAAa,CACb,kBACF,CAEA,wBACE,aAAc,CACd,UACF,CAEA,0BACE,6BAA8B,CAC9B,+BACF,CAEA,uBACE,aACF,CAGA,uCACE,iDACE,YACF,CACF,CAIE,+CAEE,qCACF,CAEA,8CACE,gCACF","file":"page_header.css","sourcesContent":["/* OP PageHeader */\n\n.PageHeader {\n display: flex;\n padding-bottom: var(--base-size-8);\n margin-bottom: var(--base-size-16);\n border-bottom: var(--borderWidth-thin) solid var(--borderColor-muted);\n flex-flow: column;\n}\n\n.PageHeader--withTabNav {\n border-bottom: none;\n padding-bottom: 0;\n margin-bottom: 0;\n}\n\n.PageHeader-contextBar {\n display: flex;\n flex-flow: row;\n justify-content: flex-end;\n align-items: center;\n margin-bottom: var(--base-size-8);\n height: var(--control-small-size);\n}\n\n.PageHeader-titleBar {\n display: flex;\n flex-flow: row;\n justify-content: flex-end;\n align-items: center; /* Keep back button vertically aligned. */\n margin-bottom: var(--base-size-8);\n}\n\n.PageHeader-title {\n font-size: var(--text-title-size-medium);\n flex: 1 1 auto;\n}\n\n.PageHeader-title--large {\n font-size: var(--text-title-size-large);\n}\n\n/* One-liner of supporting text */\n.PageHeader-description {\n font-size: var(--text-body-size-medium);\n color: var(--fgColor-muted);\n flex: 1 auto;\n}\n\n/* stylelint-disable-next-line selector-max-type -- description holds rich text; links can only be targeted by the `a` type selector */\n.PageHeader-description--underlined-links a {\n /* Ensure the accessibility is met, given that the description is written in light grey */\n text-decoration: underline;\n}\n\n.PageHeader-tabNavBar {\n overflow: auto;\n}\n\n.PageHeader-tabNavBar .PageHeader-tabNav {\n min-width: max-content;\n}\n\n.PageHeader--withTabNav .PageHeader-description {\n margin-bottom: var(--base-size-16);\n}\n\n.PageHeader-actions {\n justify-content: flex-end;\n display: flex;\n align-items: center;\n}\n\n.PageHeader-breadcrumbs {\n display: block;\n width: 100%;\n}\n\n.PageHeader-leadingAction {\n margin-top: var(--base-size-2); /* to center align with label */\n margin-right: var(--base-size-4);\n}\n\n.PageHeader-parentLink {\n flex: 1 1 auto;\n}\n\n/* Hide the context bar on desktop when no breadcrumb is visible */\n@media screen and (min-width: 543.98px) {\n .PageHeader--noBreadcrumb .PageHeader-contextBar {\n display: none;\n }\n}\n\n/* Match the title bar and actions height with the toggle menu button for proper vertical alignment */\n.PageHeader--noBreadcrumb {\n & .PageHeader-titleBar {\n /* stylelint-disable-next-line primer/typography -- control size var intentionally matches the toggle-menu button height for vertical alignment */\n line-height: var(--control-small-size);\n }\n\n & .PageHeader-actions {\n height: var(--control-small-size);\n }\n}"]}
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
flex: 1 auto;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
/* stylelint-disable-next-line selector-max-type -- description holds rich text; links can only be targeted by the `a` type selector */
|
|
50
51
|
.PageHeader-description--underlined-links a {
|
|
51
52
|
/* Ensure the accessibility is met, given that the description is written in light grey */
|
|
52
53
|
text-decoration: underline;
|
|
@@ -94,6 +95,7 @@
|
|
|
94
95
|
/* Match the title bar and actions height with the toggle menu button for proper vertical alignment */
|
|
95
96
|
.PageHeader--noBreadcrumb {
|
|
96
97
|
& .PageHeader-titleBar {
|
|
98
|
+
/* stylelint-disable-next-line primer/typography -- control size var intentionally matches the toggle-menu button height for vertical alignment */
|
|
97
99
|
line-height: var(--control-small-size);
|
|
98
100
|
}
|
|
99
101
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.Page{min-width:var(--base-size-32);height:var(--base-size-32);padding:var(--base-size-8) var(--base-size-6);margin-right:var(--base-size-4);color:var(--fgColor-default);white-space:nowrap;vertical-align:middle;cursor:pointer;border-radius:var(--borderRadius-medium
|
|
1
|
+
.Page{min-width:var(--base-size-32);height:var(--base-size-32);padding:var(--base-size-8) var(--base-size-6);margin-right:var(--base-size-4);color:var(--fgColor-default);white-space:nowrap;vertical-align:middle;cursor:pointer;border-radius:var(--borderRadius-medium);transition:background-color .2s cubic-bezier(.3,0,.5,1);display:inline-flex;align-items:center;justify-content:center}.Page[rel=next]>svg,.Page[rel=prev]>svg{height:var(--base-size-16);width:var(--base-size-16)}.Page[rel=prev]>svg{margin-inline-end:var(--base-size-4)}.Page[rel=next]>svg{margin-inline-start:var(--base-size-4)}.Page:last-child{margin-right:0}.Page:focus,.Page:hover{-webkit-text-decoration:none;text-decoration:none;background-color:var(--control-transparent-bgColor-hover);outline:0;transition-duration:.1s}.Page:focus-visible{outline:2px solid var(--bgColor-accent-emphasis)}.Page:active{border-color:var(--borderColor-muted)}.Page[rel=next],.Page[rel=prev]{color:var(--fgColor-accent)}.Page[aria-current],.Page[aria-current]:hover{color:var(--fgColor-onEmphasis);background-color:var(--bgColor-accent-emphasis);border-color:#0000}.Page[aria-current]:focus-visible{outline:2px solid var(--bgColor-accent-emphasis);box-shadow:inset 0 0 0 var(--base-size-2) var(--fgColor-onEmphasis)}.Page[aria-hidden],.Page[aria-hidden]:hover,.Page[role=presentation],.Page[role=presentation]:hover{color:var(--fgColor-disabled);cursor:default;background-color:initial}.PaginationContainer{margin:var(--base-size-16) 0;text-align:center}@media (max-width:543.98px){.Page:not([rel=prev]):not([rel=next]){display:none}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["pagination.pcss"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["pagination.pcss"],"names":[],"mappings":"AAEA,MACE,6BAA8B,CAC9B,0BAA2B,CAC3B,6CAA8C,CAC9C,+BAAgC,CAChC,4BAA6B,CAC7B,kBAAmB,CACnB,qBAAsB,CACtB,cAAe,CACf,wCAAyC,CACzC,uDAA8D,CAC9D,mBAAoB,CACpB,kBAAmB,CACnB,sBACF,CAEA,wCAEE,0BAA2B,CAC3B,yBACF,CAEA,oBACE,oCACF,CAEA,oBACE,sCACF,CAEA,iBACE,cACF,CAEA,wBAEE,4BAAqB,CAArB,oBAAqB,CACrB,yDAA0D,CAC1D,SAAU,CACV,uBACF,CAEA,oBACE,gDACF,CAEA,aACE,qCACF,CAEA,gCAEE,2BACF,CAEA,8CAEE,+BAAgC,CAChC,+CAAgD,CAChD,kBACF,CAEA,kCACE,gDAAiD,CAEjD,mEACF,CAEA,oGAIE,6BAA8B,CAC9B,cAAe,CACf,wBACF,CAEA,qBACE,4BAA6B,CAC7B,iBACF,CAEA,4BACE,sCACE,YACF,CACF","file":"pagination.css","sourcesContent":["/* stylelint-disable selector-max-type -- pagination arrows are styled via `.Page[rel] > svg`; the svg icon can only be targeted by its type selector */\n\n.Page {\n min-width: var(--base-size-32);\n height: var(--base-size-32);\n padding: var(--base-size-8) var(--base-size-6);\n margin-right: var(--base-size-4);\n color: var(--fgColor-default);\n white-space: nowrap;\n vertical-align: middle;\n cursor: pointer;\n border-radius: var(--borderRadius-medium);\n transition: background-color 0.2s cubic-bezier(0.3, 0, 0.5, 1);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.Page[rel='prev'] > svg,\n.Page[rel='next'] > svg {\n height: var(--base-size-16);\n width: var(--base-size-16);\n}\n\n.Page[rel='prev'] > svg {\n margin-inline-end: var(--base-size-4);\n}\n\n.Page[rel='next'] > svg {\n margin-inline-start: var(--base-size-4);\n}\n\n.Page:last-child {\n margin-right: 0;\n}\n\n.Page:hover,\n.Page:focus {\n text-decoration: none;\n background-color: var(--control-transparent-bgColor-hover);\n outline: 0;\n transition-duration: 0.1s;\n}\n\n.Page:focus-visible {\n outline: 2px solid var(--bgColor-accent-emphasis);\n}\n\n.Page:active {\n border-color: var(--borderColor-muted);\n}\n\n.Page[rel='prev'],\n.Page[rel='next'] {\n color: var(--fgColor-accent);\n}\n\n.Page[aria-current],\n.Page[aria-current]:hover {\n color: var(--fgColor-onEmphasis);\n background-color: var(--bgColor-accent-emphasis);\n border-color: transparent;\n}\n\n.Page[aria-current]:focus-visible {\n outline: 2px solid var(--bgColor-accent-emphasis);\n /* stylelint-disable-next-line primer/box-shadow -- custom focus-ring built from Primer size/color primitives; no single Primer box-shadow token matches */\n box-shadow: inset 0 0 0 var(--base-size-2) var(--fgColor-onEmphasis);\n}\n\n.Page[aria-hidden],\n.Page[aria-hidden]:hover,\n.Page[role='presentation'],\n.Page[role='presentation']:hover {\n color: var(--fgColor-disabled);\n cursor: default;\n background-color: transparent;\n}\n\n.PaginationContainer {\n margin: var(--base-size-16) 0;\n text-align: center;\n}\n\n@media (max-width: 543.98px){\n .Page:not([rel='prev']):not([rel='next']) {\n display: none;\n }\n}\n"]}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/* stylelint-disable selector-max-type -- pagination arrows are styled via `.Page[rel] > svg`; the svg icon can only be targeted by its type selector */
|
|
2
|
+
|
|
1
3
|
.Page {
|
|
2
4
|
min-width: var(--base-size-32);
|
|
3
5
|
height: var(--base-size-32);
|
|
@@ -7,7 +9,7 @@
|
|
|
7
9
|
white-space: nowrap;
|
|
8
10
|
vertical-align: middle;
|
|
9
11
|
cursor: pointer;
|
|
10
|
-
border-radius: var(--borderRadius-medium
|
|
12
|
+
border-radius: var(--borderRadius-medium);
|
|
11
13
|
transition: background-color 0.2s cubic-bezier(0.3, 0, 0.5, 1);
|
|
12
14
|
display: inline-flex;
|
|
13
15
|
align-items: center;
|
|
@@ -62,6 +64,7 @@
|
|
|
62
64
|
|
|
63
65
|
.Page[aria-current]:focus-visible {
|
|
64
66
|
outline: 2px solid var(--bgColor-accent-emphasis);
|
|
67
|
+
/* stylelint-disable-next-line primer/box-shadow -- custom focus-ring built from Primer size/color primitives; no single Primer box-shadow token matches */
|
|
65
68
|
box-shadow: inset 0 0 0 var(--base-size-2) var(--fgColor-onEmphasis);
|
|
66
69
|
}
|
|
67
70
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.SidePanel-sectionHeader{display:flex;align-items:center;height:32px;margin-bottom:
|
|
1
|
+
.SidePanel-sectionHeader{display:flex;align-items:center;height:32px;margin-bottom:var(--base-size-8)}.SidePanel-sectionCounter{margin-left:var(--base-size-8)}.SidePanel-sectionAction{justify-content:right;flex:1;display:flex}.SidePanel-sectionContent,.SidePanel-sectionDescription{margin-top:0}:is(.SidePanel-sectionContent,.SidePanel-sectionDescription):not(:last-child){margin-bottom:var(--base-size-16)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["section.pcss"],"names":[],"mappings":"AAEA,yBACE,YAAa,CACb,kBAAmB,CACnB,WAAY,CACZ,
|
|
1
|
+
{"version":3,"sources":["section.pcss"],"names":[],"mappings":"AAEA,yBACE,YAAa,CACb,kBAAmB,CACnB,WAAY,CACZ,gCACF,CAEA,0BACE,8BACF,CAEA,yBACE,qBAAsB,CACtB,MAAO,CACP,YACF,CAEA,wDAEE,YAKF,CAHE,8EACE,iCACF","file":"section.css","sourcesContent":["/* CSS for OpenProject::SidePanel::Section */\n\n.SidePanel-sectionHeader {\n display: flex;\n align-items: center;\n height: 32px;\n margin-bottom: var(--base-size-8);\n}\n\n.SidePanel-sectionCounter {\n margin-left: var(--base-size-8);\n}\n\n.SidePanel-sectionAction {\n justify-content: right;\n flex: 1;\n display: flex;\n}\n\n.SidePanel-sectionContent,\n.SidePanel-sectionDescription {\n margin-top: 0;\n\n &:not(:last-child) {\n margin-bottom: var(--base-size-16);\n }\n}\n"]}
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
display: flex;
|
|
5
5
|
align-items: center;
|
|
6
6
|
height: 32px;
|
|
7
|
-
margin-bottom:
|
|
7
|
+
margin-bottom: var(--base-size-8);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
.SidePanel-sectionCounter {
|
|
11
|
-
margin-left:
|
|
11
|
+
margin-left: var(--base-size-8);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
.SidePanel-sectionAction {
|
|
@@ -22,6 +22,6 @@
|
|
|
22
22
|
margin-top: 0;
|
|
23
23
|
|
|
24
24
|
&:not(:last-child) {
|
|
25
|
-
margin-bottom:
|
|
25
|
+
margin-bottom: var(--base-size-16);
|
|
26
26
|
}
|
|
27
27
|
}
|
|
@@ -76,7 +76,6 @@ module Primer
|
|
|
76
76
|
@input_arguments = system_arguments
|
|
77
77
|
@input_arguments.delete(:id) unless @input_arguments[:id].present?
|
|
78
78
|
@label_arguments = @input_arguments.delete(:label_arguments) || {}
|
|
79
|
-
@label_arguments[:for] = id if id.present?
|
|
80
79
|
|
|
81
80
|
@label_arguments[:class] = class_names(
|
|
82
81
|
@label_arguments[:class],
|
|
@@ -121,6 +120,11 @@ module Primer
|
|
|
121
120
|
end
|
|
122
121
|
# rubocop:enable Style/IfUnlessModifier
|
|
123
122
|
|
|
123
|
+
# Only set `for` when the id is known. Otherwise leave it unset so
|
|
124
|
+
# Rails generates the scoped id for both label and input; passing
|
|
125
|
+
# `for: nil` would suppress that and drop the association.
|
|
126
|
+
@label_arguments[:for] = @input_arguments[:id] if @input_arguments[:id].present?
|
|
127
|
+
|
|
124
128
|
# Whether or not to wrap the component in a FormControl, which renders a
|
|
125
129
|
# label above and validation message beneath the input.
|
|
126
130
|
@form_control = @input_arguments.delete(:form_control) { true }
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Primer::SafeHrefHelper
|
|
4
|
+
#
|
|
5
|
+
# Detects unsafe URI schemes (e.g. `javascript:`) in `href` values so they can
|
|
6
|
+
# be neutralized before being rendered into HTML attributes. Without this check,
|
|
7
|
+
# a caller that forwards untrusted input into a component's `href:` argument can
|
|
8
|
+
# trigger XSS when the user clicks the rendered anchor.
|
|
9
|
+
module Primer
|
|
10
|
+
# :nodoc:
|
|
11
|
+
module SafeHrefHelper
|
|
12
|
+
# URI schemes that can execute script in the browser and are never valid
|
|
13
|
+
# destinations for a Primer-rendered link.
|
|
14
|
+
DISALLOWED_HREF_SCHEMES = %w[javascript vbscript].freeze
|
|
15
|
+
|
|
16
|
+
# Returns true when `href` starts with a disallowed URI scheme.
|
|
17
|
+
#
|
|
18
|
+
# Mirrors browser URL parsing by stripping ASCII whitespace and control
|
|
19
|
+
# characters (including tab/CR/LF) before extracting the scheme. This
|
|
20
|
+
# prevents bypasses such as `j\tavascript:...`, ` JaVaScRiPt:...`, or a
|
|
21
|
+
# leading null byte, all of which browsers happily execute.
|
|
22
|
+
def self.unsafe_href?(href)
|
|
23
|
+
return false if href.nil?
|
|
24
|
+
|
|
25
|
+
normalized = href.to_s.gsub(/[\u0000-\u0020]/, "")
|
|
26
|
+
scheme = normalized[/\A([a-z][a-z0-9+\-.]*):/i, 1]
|
|
27
|
+
return false unless scheme
|
|
28
|
+
|
|
29
|
+
DISALLOWED_HREF_SCHEMES.include?(scheme.downcase)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def unsafe_href?(href)
|
|
33
|
+
SafeHrefHelper.unsafe_href?(href)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
<%= render(Primer::Alpha::TreeView::SubTree.new(path: ["primer"], node_variant: :div)) do |tree| %>
|
|
2
|
-
<% tree.with_sub_tree(label: "alpha") do |sub_tree| %>
|
|
2
|
+
<% tree.with_sub_tree(label: "alpha", select_variant: select_variant, select_strategy: :self) do |sub_tree| %>
|
|
3
3
|
<% sub_tree.with_leading_visual_icons do |icons| %>
|
|
4
4
|
<% icons.with_expanded_icon(icon: :"file-directory-open-fill", color: :accent) %>
|
|
5
5
|
<% icons.with_collapsed_icon(icon: :"file-directory-fill", color: :accent) %>
|
|
6
6
|
<% end %>
|
|
7
7
|
|
|
8
|
-
<% sub_tree.with_sub_tree(label: "action_menu", expanded: action_menu_expanded) do |sub_tree| %>
|
|
8
|
+
<% sub_tree.with_sub_tree(label: "action_menu", expanded: action_menu_expanded, select_variant: select_variant, select_strategy: :self) do |sub_tree| %>
|
|
9
9
|
<% sub_tree.with_leading_visual_icons do |icons| %>
|
|
10
10
|
<% icons.with_expanded_icon(icon: :"file-directory-open-fill", color: :accent) %>
|
|
11
11
|
<% icons.with_collapsed_icon(icon: :"file-directory-fill", color: :accent) %>
|
|
12
12
|
<% end %>
|
|
13
13
|
|
|
14
|
-
<% sub_tree.with_leaf(label: "group.rb") do |item| %>
|
|
14
|
+
<% sub_tree.with_leaf(label: "group.rb", select_variant: select_variant) do |item| %>
|
|
15
15
|
<% item.with_leading_visual_icon(icon: :file) %>
|
|
16
16
|
<% end %>
|
|
17
17
|
|
|
18
|
-
<% sub_tree.with_leaf(label: "heading.rb") do |item| %>
|
|
18
|
+
<% sub_tree.with_leaf(label: "heading.rb", select_variant: select_variant) do |item| %>
|
|
19
19
|
<% item.with_leading_visual_icon(icon: :file) %>
|
|
20
20
|
<% end %>
|
|
21
21
|
<% end %>
|
|
@@ -10,7 +10,7 @@ module Primer
|
|
|
10
10
|
module GeneratePreviews
|
|
11
11
|
class << self
|
|
12
12
|
def call
|
|
13
|
-
Lookbook.previews.filter_map do |preview|
|
|
13
|
+
Lookbook.previews.sort_by(&:lookup_path).filter_map do |preview|
|
|
14
14
|
next if preview.preview_class == Primer::FormsPreview
|
|
15
15
|
next if Primer::Accessibility.ignore_preview?(preview.preview_class)
|
|
16
16
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<div style="max-width: 400px">
|
|
2
2
|
<%= render(Primer::Alpha::TreeView.new) do |tree_view| %>
|
|
3
|
-
<% tree_view.with_sub_tree(label: "primer") do |sub_tree| %>
|
|
3
|
+
<% tree_view.with_sub_tree(label: "primer", select_variant: select_variant, select_strategy: :self) do |sub_tree| %>
|
|
4
4
|
<% sub_tree.with_leading_visual_icons do |icons| %>
|
|
5
5
|
<% icons.with_expanded_icon(icon: :"file-directory-open-fill", color: :accent) %>
|
|
6
6
|
<% icons.with_collapsed_icon(icon: :"file-directory-fill", color: :accent) %>
|
|
7
7
|
<% end %>
|
|
8
8
|
|
|
9
|
-
<% sub_tree.with_loading_skeleton(src: primer_view_components.tree_view_items_async_alpha_path(action_menu_expanded: action_menu_expanded)) %>
|
|
9
|
+
<% sub_tree.with_loading_skeleton(src: primer_view_components.tree_view_items_async_alpha_path(action_menu_expanded: action_menu_expanded, select_variant: select_variant)) %>
|
|
10
10
|
<% end %>
|
|
11
11
|
<% end %>
|
|
12
12
|
</div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<%= form_with(url: primer_view_components.generic_form_submission_path(format: :json)) do |f| %>
|
|
2
|
+
<%= render(Primer::Alpha::Stack.new) do %>
|
|
3
|
+
<%= render(Primer::Alpha::TreeView.new(form_arguments: { builder: f, name: "folder_structure" })) do |tree| %>
|
|
4
|
+
<% tree.with_sub_tree(label: "primer", select_variant: select_variant, select_strategy: :self) do |sub_tree| %>
|
|
5
|
+
<% sub_tree.with_leading_visual_icons do |icons| %>
|
|
6
|
+
<% icons.with_expanded_icon(icon: :"file-directory-open-fill", color: :accent) %>
|
|
7
|
+
<% icons.with_collapsed_icon(icon: :"file-directory-fill", color: :accent) %>
|
|
8
|
+
<% end %>
|
|
9
|
+
|
|
10
|
+
<% sub_tree.with_loading_skeleton(src: primer_view_components.tree_view_items_async_alpha_path(select_variant: select_variant)) %>
|
|
11
|
+
<% end %>
|
|
12
|
+
<% end %>
|
|
13
|
+
|
|
14
|
+
<%= render(Primer::Alpha::SubmitButton.new(name: :submit, label: "Submit")) %>
|
|
15
|
+
<% end %>
|
|
16
|
+
<% end %>
|
|
@@ -114,9 +114,11 @@ module Primer
|
|
|
114
114
|
# @label Async alpha
|
|
115
115
|
#
|
|
116
116
|
# @param action_menu_expanded [Boolean] toggle
|
|
117
|
-
|
|
117
|
+
# @param select_variant [Symbol] select [none, single, multiple]
|
|
118
|
+
def async_alpha(action_menu_expanded: false, select_variant: :none)
|
|
118
119
|
render_with_template(locals: {
|
|
119
|
-
action_menu_expanded: coerce_bool(action_menu_expanded)
|
|
120
|
+
action_menu_expanded: coerce_bool(action_menu_expanded),
|
|
121
|
+
select_variant: select_variant.to_sym
|
|
120
122
|
})
|
|
121
123
|
end
|
|
122
124
|
|
|
@@ -197,6 +199,15 @@ module Primer
|
|
|
197
199
|
})
|
|
198
200
|
end
|
|
199
201
|
|
|
202
|
+
# @label Async form input
|
|
203
|
+
# @hidden
|
|
204
|
+
# @param select_variant [Symbol] select [single, multiple]
|
|
205
|
+
def async_form_input(select_variant: :single)
|
|
206
|
+
render_with_template(locals: {
|
|
207
|
+
select_variant: select_variant.to_sym
|
|
208
|
+
})
|
|
209
|
+
end
|
|
210
|
+
|
|
200
211
|
# @label Doubled paths
|
|
201
212
|
# @hidden
|
|
202
213
|
def doubled_path
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<%= render(Primer::OpenProject::CollapsibleSection.new) do |section| %>
|
|
2
|
+
<% section.with_title { render(Primer::Beta::Link.new(href: "#")) { "Feedback" } } %>
|
|
3
|
+
<% section.with_collapsible_content do %>
|
|
4
|
+
<%= render(Primer::Alpha::Banner.new(mb: 3)) { "Please take one minute to answer this question" } %>
|
|
5
|
+
<% end %>
|
|
6
|
+
<% end %>
|
|
@@ -52,6 +52,15 @@ module Primer
|
|
|
52
52
|
locals: { }
|
|
53
53
|
)
|
|
54
54
|
end
|
|
55
|
+
|
|
56
|
+
# @label With link in title
|
|
57
|
+
# @hidden
|
|
58
|
+
def with_link_in_title
|
|
59
|
+
render_with_template(
|
|
60
|
+
template: "primer/open_project/collapsible_section_preview/with_link_in_title",
|
|
61
|
+
locals: { }
|
|
62
|
+
)
|
|
63
|
+
end
|
|
55
64
|
end
|
|
56
65
|
end
|
|
57
66
|
end
|
data/static/classes.json
CHANGED
|
@@ -560,6 +560,9 @@
|
|
|
560
560
|
"Popover-message": [
|
|
561
561
|
"Primer::Beta::Popover"
|
|
562
562
|
],
|
|
563
|
+
"Popover-message--bottom": [
|
|
564
|
+
"Primer::Beta::Popover"
|
|
565
|
+
],
|
|
563
566
|
"Popover-message--bottom-left": [
|
|
564
567
|
"Primer::Beta::Popover"
|
|
565
568
|
],
|
|
@@ -569,9 +572,27 @@
|
|
|
569
572
|
"Popover-message--large": [
|
|
570
573
|
"Primer::Beta::Popover"
|
|
571
574
|
],
|
|
575
|
+
"Popover-message--left": [
|
|
576
|
+
"Primer::Beta::Popover"
|
|
577
|
+
],
|
|
578
|
+
"Popover-message--left-bottom": [
|
|
579
|
+
"Primer::Beta::Popover"
|
|
580
|
+
],
|
|
581
|
+
"Popover-message--left-top": [
|
|
582
|
+
"Primer::Beta::Popover"
|
|
583
|
+
],
|
|
572
584
|
"Popover-message--no-caret": [
|
|
573
585
|
"Primer::Beta::Popover"
|
|
574
586
|
],
|
|
587
|
+
"Popover-message--right": [
|
|
588
|
+
"Primer::Beta::Popover"
|
|
589
|
+
],
|
|
590
|
+
"Popover-message--right-bottom": [
|
|
591
|
+
"Primer::Beta::Popover"
|
|
592
|
+
],
|
|
593
|
+
"Popover-message--right-top": [
|
|
594
|
+
"Primer::Beta::Popover"
|
|
595
|
+
],
|
|
575
596
|
"Popover-message--top-left": [
|
|
576
597
|
"Primer::Beta::Popover"
|
|
577
598
|
],
|