polaris_view_components 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +36 -1
  3. data/app/assets/javascripts/polaris.js +15 -2
  4. data/app/components/polaris/button_component.html.erb +1 -1
  5. data/app/components/polaris/button_component.rb +1 -85
  6. data/app/components/polaris/card/section_component.rb +2 -1
  7. data/app/components/polaris/card_component.html.erb +8 -2
  8. data/app/components/polaris/card_component.rb +2 -0
  9. data/app/components/polaris/headless_button.html.erb +22 -0
  10. data/app/components/polaris/headless_button.rb +95 -0
  11. data/app/components/polaris/resource_item_component.html.erb +27 -0
  12. data/app/components/polaris/resource_item_component.rb +75 -0
  13. data/app/components/polaris/resource_list_component.rb +32 -0
  14. data/app/components/polaris/select_component.html.erb +11 -2
  15. data/app/components/polaris/select_component.rb +2 -0
  16. data/app/components/polaris/shopify_navigation_component.rb +33 -13
  17. data/app/components/polaris/skeleton_body_text_component.html.erb +5 -0
  18. data/app/components/polaris/skeleton_body_text_component.rb +15 -0
  19. data/app/components/polaris/tag_component.html.erb +6 -0
  20. data/app/components/polaris/tag_component.rb +35 -0
  21. data/app/components/polaris/text_field_component.html.erb +4 -4
  22. data/app/components/polaris/text_field_component.rb +3 -1
  23. data/app/helpers/polaris/form_builder.rb +43 -7
  24. data/app/helpers/polaris/url_helper.rb +19 -0
  25. data/app/helpers/polaris/view_helper.rb +4 -0
  26. data/app/javascript/polaris/index.js +3 -1
  27. data/app/javascript/polaris/resource_item_controller.js +15 -0
  28. data/app/javascript/polaris/text_field_controller.js +0 -1
  29. data/lib/generators/polaris_view_components/USAGE +5 -0
  30. data/lib/generators/polaris_view_components/install_generator.rb +35 -0
  31. data/lib/generators/polaris_view_components/templates/README +14 -0
  32. data/lib/generators/polaris_view_components/templates/stimulus_index.js +7 -0
  33. data/lib/polaris/view_components/engine.rb +1 -0
  34. data/lib/polaris/view_components/version.rb +1 -1
  35. metadata +17 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 51731f649164d962ee2859f84197a32a55a08a229d3606682fb57fc2eb0bcbe4
4
- data.tar.gz: c543075f3f75725dac65d466ff817587af90541b0e3e4b399eb84f3fc2e03855
3
+ metadata.gz: 75b9c5e7b5a31ce1a5a549b0315fdbefc308206fd89085a19c8feac044f2884f
4
+ data.tar.gz: c858f559b97a7dfe14c6c303d3f7b000ca428ddc12ee603511f03ebe4ad4ffcc
5
5
  SHA512:
6
- metadata.gz: 1b458cf6a17a5ebbd23e2b663a8f9bb52269a3bd68c14fd225dd1a316813a4d8eb88ee7999c8be0099934af21a3b56cf462ddc97348e184a41b245a5359410d5
7
- data.tar.gz: 2dfbe9e93bf4cd04b5ef1752204d691dc560d85cf9f8aa9a7b34fc191b0856b0ba3c511a572260ef690d40cf66cc24032e72f3afcb740c5741a8cfcae3205f56
6
+ metadata.gz: 0577b317bffc512104e90a023eab9d2a674b9f6ce852eb2e8324a77e1723f97029d30545053e29f72ad7da1da14ebb5c2c1f3eee5afa2a50f4ed7bca7afce4b7
7
+ data.tar.gz: 1cfb3676d22713e1e6f5d47a4a521683faa1d5a7bc2f94db6731da47e0834b359bdd7f91670c294b6f20e11445089ad08c51111c226c7f77ba2563f417a9b4d3
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Polaris ViewComponents is an implementation of the Polaris Design System using [ViewComponent](https://github.com/github/view_component).
4
4
 
5
+ ![Polaris ViewComponents](.github/assets/preview.png)
6
+
5
7
  > **This library is under active development. Breaking changes are likely until stable release.**
6
8
 
7
9
  ## Preview
@@ -23,7 +25,12 @@ Render Polaris ViewComponents:
23
25
  In `Gemfile`, add:
24
26
 
25
27
  ```ruby
26
- gem 'polaris_view_components', github: 'baoagency/polaris_view_components', branch: 'main'
28
+ gem 'polaris_view_components'
29
+ ```
30
+
31
+ Run install generator:
32
+ ```bash
33
+ rails generate polaris_view_components:install
27
34
  ```
28
35
 
29
36
  Setup Polaris styles in your layouts `<head>` tag:
@@ -33,6 +40,24 @@ Setup Polaris styles in your layouts `<head>` tag:
33
40
  <%= stylesheet_link_tag 'polaris_view_components' %>
34
41
  ```
35
42
 
43
+ Define Polaris style on your `<body>` tag:
44
+
45
+ ```erb
46
+ <body style="<%= polaris_body_styles %>">
47
+ ```
48
+
49
+ Install NPM package:
50
+ ```bash
51
+ yarn add polaris-view-components
52
+ ```
53
+
54
+ Add to `app/javascript/controllers/index.js`:
55
+ ```javascript
56
+ // Polaris ViewComponents
57
+ import { registerPolarisControllers } from "polaris-view-components"
58
+ registerPolarisControllers(application)
59
+ ```
60
+
36
61
  ## Dependencies
37
62
 
38
63
  In addition to the dependencies declared in the `gemspec`, Polaris ViewComponents assumes the presence of Polaris CSS.
@@ -46,6 +71,16 @@ To get started:
46
71
 
47
72
  It will open demo app with component previews on `localhost:4000`. You can change components and they will be updated on page reload. Component previews located in `demo/test/components/previews`.
48
73
 
74
+ To release gem run:
75
+ ```bash
76
+ script/release
77
+ ```
78
+
79
+ To release npm package run:
80
+ ```bash
81
+ yarn release
82
+ ```
83
+
49
84
  ## License
50
85
 
51
86
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -14,6 +14,19 @@ function _defineProperty(obj, key, value) {
14
14
  return obj;
15
15
  }
16
16
 
17
+ class _class$2 extends Controller {
18
+ open(event) {
19
+ if (this.hasLinkTarget && this.targetNotClickable(event.target)) {
20
+ this.linkTarget.click();
21
+ }
22
+ }
23
+ targetNotClickable(element) {
24
+ return !element.closest("a") && !element.closest("button") && element.nodeName !== "INPUT";
25
+ }
26
+ }
27
+
28
+ _defineProperty(_class$2, "targets", [ "link" ]);
29
+
17
30
  class _class$1 extends Controller {
18
31
  update(event) {
19
32
  const select = event.currentTarget;
@@ -85,7 +98,6 @@ class _class extends Controller {
85
98
  if (isNaN(numericValue)) {
86
99
  return;
87
100
  }
88
- console.log(numericValue, this.stepValue);
89
101
  const decimalPlaces = Math.max(dpl(numericValue), dpl(this.stepValue));
90
102
  const newValue = Math.min(Number(this.maxValue), Math.max(numericValue + steps * this.stepValue, Number(this.minValue)));
91
103
  this.value = String(newValue.toFixed(decimalPlaces));
@@ -106,8 +118,9 @@ _defineProperty(_class, "values", {
106
118
  });
107
119
 
108
120
  function registerPolarisControllers(application) {
121
+ application.register("polaris-resource-item", _class$2);
109
122
  application.register("polaris-select", _class$1);
110
123
  application.register("polaris-text-field", _class);
111
124
  }
112
125
 
113
- export { _class$1 as Select, _class as TextField, registerPolarisControllers };
126
+ export { _class$2 as ResourceItem, _class$1 as Select, _class as TextField, registerPolarisControllers };
@@ -1,4 +1,4 @@
1
- <%= render Polaris::BaseComponent.new(tag: @tag, **dynamic_arguments) do %>
1
+ <%= render Polaris::BaseComponent.new(tag: @tag, **system_arguments) do %>
2
2
  <span class="Polaris-Button__Content">
3
3
  <% if @loading %>
4
4
  <span class="Polaris-Button__Spinner">
@@ -1,90 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Polaris
4
- class ButtonComponent < Polaris::NewComponent
5
- SIZE_DEFAULT = :medium
6
- SIZE_MAPPINGS = {
7
- SIZE_DEFAULT => "",
8
- :slim => "Polaris-Button--sizeSlim",
9
- :large => "Polaris-Button--sizeLarge",
10
- }
11
- SIZE_OPTIONS = SIZE_MAPPINGS.keys
12
-
13
- TEXT_ALIGN_DEFAULT = :default
14
- TEXT_ALIGN_MAPPINGS = {
15
- TEXT_ALIGN_DEFAULT => "",
16
- :left => "Polaris-Button--textAlignLeft",
17
- :center => "Polaris-Button--textAlignCenter",
18
- :right => "Polaris-Button--textAlignRight",
19
- }
20
- TEXT_ALIGN_OPTIONS = TEXT_ALIGN_MAPPINGS.keys
21
-
22
- renders_one :icon, IconComponent
23
-
24
- def initialize(
25
- url: nil,
26
- outline: false,
27
- plain: false,
28
- primary: false,
29
- pressed: false,
30
- monochrome: false,
31
- loading: false,
32
- destructive: false,
33
- disabled: false,
34
- external: false,
35
- full_width: false,
36
- submit: false,
37
- remove_underline: false,
38
- size: SIZE_DEFAULT,
39
- text_align: TEXT_ALIGN_DEFAULT,
40
- **system_arguments
41
- )
42
- @tag = url.present? ? 'a' : 'button'
43
- @text_classes = class_names(
44
- "Polaris-Button__Text",
45
- "Polaris-Button--removeUnderline": plain && monochrome && remove_underline
46
- )
47
- @loading = loading
48
-
49
- @system_arguments = system_arguments
50
- @system_arguments[:type] = submit ? 'submit' : 'button'
51
- if loading
52
- @system_arguments[:disabled] = true
53
- end
54
- if url.present?
55
- @system_arguments.delete(:type)
56
- @system_arguments[:href] = url
57
- @system_arguments[:target] = "_blank" if external
58
- end
59
- if disabled
60
- @system_arguments[:disabled] = disabled
61
- end
62
- @system_arguments[:classes] = class_names(
63
- @system_arguments[:classes],
64
- "Polaris-Button",
65
- SIZE_MAPPINGS[fetch_or_fallback(SIZE_OPTIONS, size, SIZE_DEFAULT)],
66
- TEXT_ALIGN_MAPPINGS[fetch_or_fallback(TEXT_ALIGN_OPTIONS, text_align, TEXT_ALIGN_DEFAULT)],
67
- "Polaris-Button--destructive": destructive,
68
- "Polaris-Button--disabled": disabled || loading,
69
- "Polaris-Button--loading": loading,
70
- "Polaris-Button--fullWidth": full_width,
71
- "Polaris-Button--monochrome": monochrome,
72
- "Polaris-Button--outline": outline,
73
- "Polaris-Button--plain": plain,
74
- "Polaris-Button--primary": primary,
75
- "Polaris-Button--pressed": pressed,
76
- "Polaris-Button--removeUnderline": (plain && monochrome && remove_underline)
77
- )
78
- end
79
-
80
- private
81
-
82
- def dynamic_arguments
83
- @system_arguments[:classes] = class_names(
84
- @system_arguments[:classes],
85
- "Polaris-Button--iconOnly": icon.present? && content.blank?,
86
- )
87
- @system_arguments
88
- end
4
+ class ButtonComponent < HeadlessButton
89
5
  end
90
6
  end
@@ -6,6 +6,7 @@ class Polaris::Card::SectionComponent < Polaris::NewComponent
6
6
  subdued: false,
7
7
  flush: false,
8
8
  full_width: false,
9
+ unstyled: false,
9
10
  actions: [],
10
11
  **system_arguments
11
12
  )
@@ -13,10 +14,10 @@ class Polaris::Card::SectionComponent < Polaris::NewComponent
13
14
  @system_arguments[:tag] = :div
14
15
  @system_arguments[:classes] = class_names(
15
16
  @system_arguments[:classes],
16
- "Polaris-Card__Section",
17
17
  "Polaris-Card__Section--flush": flush,
18
18
  "Polaris-Card__Section--subdued": subdued,
19
19
  "Polaris-Card__Section--fullWidth": full_width,
20
+ "Polaris-Card__Section": !unstyled,
20
21
  )
21
22
 
22
23
  @title = title
@@ -11,8 +11,14 @@
11
11
  <% sections.each do |section| %>
12
12
  <%= section %>
13
13
  <% end %>
14
- <% else %>
15
- <%= render Polaris::Card::SectionComponent.new do %>
14
+ <% end %>
15
+
16
+ <% if content.present? %>
17
+ <% if @sectioned %>
18
+ <%= render Polaris::Card::SectionComponent.new do %>
19
+ <%= content %>
20
+ <% end %>
21
+ <% else %>
16
22
  <%= content %>
17
23
  <% end %>
18
24
  <% end %>
@@ -21,12 +21,14 @@ module Polaris
21
21
  def initialize(
22
22
  title: "",
23
23
  actions: [],
24
+ sectioned: true,
24
25
  subdued: false,
25
26
  footer_action_alignment: FOOTER_ACTION_ALIGNMENT_DEFAULT,
26
27
  **system_arguments
27
28
  )
28
29
  @title = title
29
30
  @actions = actions
31
+ @sectioned = sectioned
30
32
  @footer_action_alignment = footer_action_alignment
31
33
 
32
34
  @system_arguments = system_arguments
@@ -0,0 +1,22 @@
1
+ <span class="Polaris-Button__Content">
2
+ <% if @loading %>
3
+ <span class="Polaris-Button__Spinner">
4
+ <%= polaris_spinner(size: :small) %>
5
+ </span>
6
+ <% end %>
7
+
8
+ <% if icon.present? %>
9
+ <div class="Polaris-Button__Icon">
10
+ <%= icon %>
11
+ </div>
12
+ <% if content.present? %>
13
+ &nbsp;
14
+ <% end %>
15
+ <% end %>
16
+
17
+ <% if content.present? %>
18
+ <div class="<%= @text_classes %>">
19
+ <%= content %>
20
+ </div>
21
+ <% end %>
22
+ </span>
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Polaris
4
+ class HeadlessButton < Polaris::NewComponent
5
+ SIZE_DEFAULT = :medium
6
+ SIZE_MAPPINGS = {
7
+ SIZE_DEFAULT => "",
8
+ :slim => "Polaris-Button--sizeSlim",
9
+ :large => "Polaris-Button--sizeLarge",
10
+ }
11
+ SIZE_OPTIONS = SIZE_MAPPINGS.keys
12
+
13
+ TEXT_ALIGN_DEFAULT = :default
14
+ TEXT_ALIGN_MAPPINGS = {
15
+ TEXT_ALIGN_DEFAULT => "",
16
+ :left => "Polaris-Button--textAlignLeft",
17
+ :center => "Polaris-Button--textAlignCenter",
18
+ :right => "Polaris-Button--textAlignRight",
19
+ }
20
+ TEXT_ALIGN_OPTIONS = TEXT_ALIGN_MAPPINGS.keys
21
+
22
+ renders_one :icon, IconComponent
23
+
24
+ def initialize(
25
+ url: nil,
26
+ outline: false,
27
+ plain: false,
28
+ primary: false,
29
+ pressed: false,
30
+ monochrome: false,
31
+ loading: false,
32
+ destructive: false,
33
+ disabled: false,
34
+ external: false,
35
+ full_width: false,
36
+ submit: false,
37
+ remove_underline: false,
38
+ size: SIZE_DEFAULT,
39
+ text_align: TEXT_ALIGN_DEFAULT,
40
+ **system_arguments
41
+ )
42
+ @tag = url.present? ? 'a' : 'button'
43
+ @text_classes = class_names(
44
+ "Polaris-Button__Text",
45
+ "Polaris-Button--removeUnderline": plain && monochrome && remove_underline
46
+ )
47
+ @loading = loading
48
+
49
+ @system_arguments = system_arguments
50
+ @system_arguments[:type] = submit ? 'submit' : 'button'
51
+ if loading
52
+ @system_arguments[:disabled] = true
53
+ end
54
+ if url.present?
55
+ @system_arguments.delete(:type)
56
+ @system_arguments[:href] = url
57
+ @system_arguments[:target] = "_blank" if external
58
+ end
59
+ if disabled
60
+ @system_arguments[:disabled] = disabled
61
+ end
62
+ @system_arguments[:classes] = class_names(
63
+ @system_arguments[:classes],
64
+ "Polaris-Button",
65
+ SIZE_MAPPINGS[fetch_or_fallback(SIZE_OPTIONS, size, SIZE_DEFAULT)],
66
+ TEXT_ALIGN_MAPPINGS[fetch_or_fallback(TEXT_ALIGN_OPTIONS, text_align, TEXT_ALIGN_DEFAULT)],
67
+ "Polaris-Button--destructive": destructive,
68
+ "Polaris-Button--disabled": disabled || loading,
69
+ "Polaris-Button--loading": loading,
70
+ "Polaris-Button--fullWidth": full_width,
71
+ "Polaris-Button--monochrome": monochrome,
72
+ "Polaris-Button--outline": outline,
73
+ "Polaris-Button--plain": plain,
74
+ "Polaris-Button--primary": primary,
75
+ "Polaris-Button--pressed": pressed,
76
+ "Polaris-Button--removeUnderline": (plain && monochrome && remove_underline)
77
+ )
78
+ end
79
+
80
+ def system_arguments
81
+ @system_arguments[:classes] = class_names(
82
+ @system_arguments[:classes],
83
+ "Polaris-Button--iconOnly": icon.present? && content.blank?,
84
+ )
85
+ @system_arguments
86
+ end
87
+
88
+ def html_options
89
+ options = system_arguments
90
+ options[:class] = options[:classes]
91
+ options.delete(:classes)
92
+ options
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,27 @@
1
+ <%= render(Polaris::BaseComponent.new(**wrapper_arguments)) do %>
2
+ <div class="Polaris-ResourceItem__ItemWrapper">
3
+ <%= render(Polaris::BaseComponent.new(**system_arguments)) do %>
4
+ <% if @url %>
5
+ <a
6
+ class="Polaris-ResourceItem__Link"
7
+ tabindex="0"
8
+ href="<%= @url %>"
9
+ data-polaris-unstyled="true"
10
+ data-polaris-resource-item-target="link"></a>
11
+ <% end %>
12
+
13
+ <%= render(Polaris::BaseComponent.new(**container_arguments)) do %>
14
+ <% if media.present? %>
15
+ <div class="Polaris-ResourceItem__Owned">
16
+ <div class="Polaris-ResourceItem__Media">
17
+ <%= media %>
18
+ </div>
19
+ </div>
20
+ <% end %>
21
+ <div class="Polaris-ResourceItem__Content">
22
+ <%= content %>
23
+ </div>
24
+ <% end %>
25
+ <% end %>
26
+ </div>
27
+ <% end %>
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Polaris
4
+ class ResourceItemComponent < Polaris::NewComponent
5
+ CURSOR_DEFAULT = :default
6
+ CURSOR_OPTIONS = %i[default pointer]
7
+
8
+ ALIGNMENT_DEFAULT = :default
9
+ ALIGNMENT_MAPPINGS = {
10
+ ALIGNMENT_DEFAULT => "",
11
+ center: "Polaris-ResourceItem--alignmentCenter",
12
+ }
13
+ ALIGNMENT_OPTIONS = ALIGNMENT_MAPPINGS.keys
14
+
15
+ renders_one :media
16
+
17
+ def initialize(
18
+ url: nil,
19
+ vertical_alignment: ALIGNMENT_DEFAULT,
20
+ wrapper_arguments: {},
21
+ container_arguments: {},
22
+ **system_arguments
23
+ )
24
+ @url = url
25
+ @vertical_alignment = vertical_alignment
26
+ @wrapper_arguments = wrapper_arguments
27
+ @container_arguments = container_arguments
28
+ @system_arguments = system_arguments
29
+ end
30
+
31
+ def wrapper_arguments
32
+ {
33
+ tag: "li",
34
+ data: {},
35
+ }.deep_merge(@wrapper_arguments).tap do |args|
36
+ args[:classes] = class_names(
37
+ args[:classes],
38
+ "Polaris-ResourceItem__ListItem",
39
+ )
40
+ prepend_option(args[:data], :controller, "polaris-resource-item")
41
+ end
42
+ end
43
+
44
+ def container_arguments
45
+ {
46
+ tag: "div",
47
+ }.deep_merge(@container_arguments).tap do |args|
48
+ args[:classes] = class_names(
49
+ args[:classes],
50
+ "Polaris-ResourceItem__Container",
51
+ ALIGNMENT_MAPPINGS[fetch_or_fallback(ALIGNMENT_OPTIONS, @vertical_alignment, ALIGNMENT_DEFAULT)],
52
+ )
53
+ end
54
+ end
55
+
56
+ def system_arguments
57
+ {
58
+ tag: "div",
59
+ data: {},
60
+ }.deep_merge(@system_arguments).tap do |args|
61
+ args[:classes] = class_names(
62
+ args[:classes],
63
+ "Polaris-ResourceItem",
64
+ )
65
+ prepend_option(args, :style, "cursor: #{cursor};")
66
+ prepend_option(args[:data], :action, "click->polaris-resource-item#open")
67
+ end
68
+ end
69
+
70
+ private
71
+ def cursor
72
+ @url.present? ? "pointer" : "default"
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Polaris
4
+ class ResourceListComponent < Polaris::NewComponent
5
+ def initialize(
6
+ wrapper_arguments: {},
7
+ **system_arguments
8
+ )
9
+ @wrapper_arguments = wrapper_arguments
10
+ @wrapper_arguments[:tag] = "div"
11
+ @wrapper_arguments[:classes] = class_names(
12
+ @wrapper_arguments[:classes],
13
+ "Polaris-ResourceList__ResourceListWrapper",
14
+ )
15
+
16
+ @system_arguments = system_arguments
17
+ @system_arguments[:tag] = "ul"
18
+ @system_arguments[:classes] = class_names(
19
+ @system_arguments[:classes],
20
+ "Polaris-ResourceList",
21
+ )
22
+ end
23
+
24
+ def call
25
+ render(Polaris::BaseComponent.new(**@wrapper_arguments)) do
26
+ render(Polaris::BaseComponent.new(**@system_arguments)) do
27
+ content
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,9 +1,18 @@
1
1
  <%= render Polaris::LabelledComponent.new(**@wrapper_arguments) do %>
2
2
  <%= render Polaris::BaseComponent.new(**@system_arguments) do %>
3
3
  <% if @form.present? && @attribute.present? %>
4
- <%= @form.select(@attribute, options_for_select(@options, @selected), @select_options, @input_options) %>
4
+ <%= @form.select(
5
+ @attribute,
6
+ options_for_select(@options, selected: @selected, disabled: @disabled_options),
7
+ @select_options,
8
+ @input_options,
9
+ ) %>
5
10
  <% else %>
6
- <%= select_tag(@name, options_for_select(@options, @selected), @input_options) %>
11
+ <%= select_tag(
12
+ @name,
13
+ options_for_select(@options, selected: @selected, disabled: @disabled_options),
14
+ @input_options,
15
+ ) %>
7
16
  <% end %>
8
17
 
9
18
  <div
@@ -8,6 +8,7 @@ module Polaris
8
8
  name: nil,
9
9
  options:,
10
10
  selected: nil,
11
+ disabled_options: nil,
11
12
  label: nil,
12
13
  label_hidden: false,
13
14
  label_inline: false,
@@ -26,6 +27,7 @@ module Polaris
26
27
  @name = name
27
28
  @options = options
28
29
  @selected = selected
30
+ @disabled_options = disabled_options
29
31
  @label = label
30
32
  @label_hidden = label_hidden
31
33
  @label_inline = label_inline
@@ -2,9 +2,13 @@
2
2
 
3
3
  module Polaris
4
4
  class ShopifyNavigationComponent < Polaris::NewComponent
5
- renders_many :links, "ShopifyNavigationLinkComponent"
5
+ renders_many :links, -> (**system_arguments) do
6
+ ShopifyNavigationLinkComponent.new(auto_detect_active: @auto_detect_active, **system_arguments)
7
+ end
8
+
9
+ def initialize(auto_detect_active: false, **system_arguments)
10
+ @auto_detect_active = auto_detect_active
6
11
 
7
- def initialize(**system_arguments)
8
12
  @system_arguments = system_arguments
9
13
  @system_arguments[:tag] = "div"
10
14
  @system_arguments[:classes] = class_names(
@@ -18,26 +22,42 @@ module Polaris
18
22
  end
19
23
 
20
24
  class ShopifyNavigationLinkComponent < Polaris::NewComponent
21
- def initialize(url:, active: false, **system_arguments)
25
+ def initialize(url:, auto_detect_active:, active: false, **system_arguments)
26
+ @url = url
27
+ @auto_detect_active = auto_detect_active
28
+ @active = active
22
29
  @system_arguments = system_arguments
23
- @system_arguments[:tag] = "a"
24
- @system_arguments[:href] = url
25
- @system_arguments[:role] = "tab"
26
- @system_arguments["data-polaris-unstyled"] = true
27
- @system_arguments["aria-selected"] = active
28
- @system_arguments[:classes] = class_names(
29
- @system_arguments[:classes],
30
- "shp-Navigation_Link",
31
- )
32
30
  end
33
31
 
34
32
  def call
35
33
  tag.li(class: "shp-Navigation_Item", role: "presentation") do
36
- render(Polaris::BaseComponent.new(**@system_arguments)) do
34
+ render(Polaris::BaseComponent.new(**system_arguments)) do
37
35
  tag.span(class: "shp-Navigation_LinkText") { content }
38
36
  end
39
37
  end
40
38
  end
39
+
40
+ def system_arguments
41
+ {
42
+ tag: "a",
43
+ href: @url,
44
+ role: "tab",
45
+ data: { polaris_unstyled: true },
46
+ aria: {},
47
+ }.deep_merge(@system_arguments).tap do |args|
48
+ args[:aria][:selected] = @active || detect_active(@url)
49
+ args[:classes] = class_names(
50
+ args[:classes],
51
+ "shp-Navigation_Link",
52
+ )
53
+ end
54
+ end
55
+
56
+ def detect_active(url)
57
+ return unless @auto_detect_active
58
+
59
+ request.path.include?(url.split('?').first)
60
+ end
41
61
  end
42
62
  end
43
63
  end
@@ -0,0 +1,5 @@
1
+ <%= render Polaris::BaseComponent.new(**@system_arguments) do %>
2
+ <% @lines.times do %>
3
+ <div class="Polaris-SkeletonBodyText"></div>
4
+ <% end %>
5
+ <% end %>
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Polaris
4
+ class SkeletonBodyTextComponent < Polaris::NewComponent
5
+ def initialize(lines: 3, **system_arguments)
6
+ @lines = lines
7
+ @system_arguments = system_arguments
8
+ @system_arguments[:tag] = "div"
9
+ @system_arguments[:classes] = class_names(
10
+ @system_arguments[:classes],
11
+ "Polaris-SkeletonBodyText__SkeletonBodyTextContainer",
12
+ )
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,6 @@
1
+ <%= render Polaris::BaseComponent.new(**system_arguments) do %>
2
+ <span class="Polaris-TagText">
3
+ <%= content %>
4
+ </span>
5
+ <%= remove_button %>
6
+ <% end %>
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Polaris
4
+ class TagComponent < Polaris::NewComponent
5
+ renders_one :remove_button, lambda { |**system_arguments|
6
+ render Polaris::BaseButton.new(
7
+ classes: "Polaris-Tag__Button",
8
+ disabled: @disabled,
9
+ **system_arguments
10
+ ) do |button|
11
+ polaris_icon(name: "CancelSmallMinor")
12
+ end
13
+ }
14
+
15
+ def initialize(clickable: false, disabled: false, **system_arguments)
16
+ @clickable = clickable
17
+ @disabled = disabled
18
+
19
+ @system_arguments = system_arguments
20
+ end
21
+
22
+ def system_arguments
23
+ @system_arguments.tap do |opts|
24
+ opts[:tag] = @clickable ? "button" : "span"
25
+ opts[:classes] = class_names(
26
+ @system_arguments[:classes],
27
+ "Polaris-Tag",
28
+ "Polaris-Tag--clickable" => @clickable,
29
+ "Polaris-Tag--disabled" => @disabled,
30
+ "Polaris-Tag--removable" => remove_button.present?
31
+ )
32
+ end
33
+ end
34
+ end
35
+ end
@@ -8,9 +8,9 @@
8
8
 
9
9
  <div class="Polaris-Connected__Item Polaris-Connected__Item--primary">
10
10
  <%= render Polaris::BaseComponent.new(**system_arguments) do %>
11
- <% if @prefix.present? %>
11
+ <% if prefix.present? || @prefix.present? %>
12
12
  <div class="Polaris-TextField__Prefix">
13
- <%= @prefix %>
13
+ <%= prefix || @prefix %>
14
14
  </div>
15
15
  <% end %>
16
16
 
@@ -20,9 +20,9 @@
20
20
  <%= public_send(input_tag, @name, @value, input_options) %>
21
21
  <% end %>
22
22
 
23
- <% if @suffix.present? %>
23
+ <% if suffix.present? || @suffix.present? %>
24
24
  <div class="Polaris-TextField__Suffix">
25
- <%= @suffix %>
25
+ <%= suffix || @suffix %>
26
26
  </div>
27
27
  <% end %>
28
28
 
@@ -19,6 +19,8 @@ module Polaris
19
19
 
20
20
  attr_reader :value
21
21
 
22
+ renders_one :prefix
23
+ renders_one :suffix
22
24
  renders_one :connected_left
23
25
  renders_one :connected_right
24
26
 
@@ -143,7 +145,7 @@ module Polaris
143
145
  default_options[:rows] = @rows
144
146
  end
145
147
 
146
- default_options.deep_merge(@input_options).tap do |opts|
148
+ default_options.deep_merge(@input_options).compact.tap do |opts|
147
149
  opts[:class] = class_names(
148
150
  opts[:class],
149
151
  "Polaris-TextField__Input",
@@ -1,16 +1,52 @@
1
1
  module Polaris
2
2
  class FormBuilder < ActionView::Helpers::FormBuilder
3
- def polaris_text_field(method, **options, &block)
4
- options[:error] ||= errors_for(method)
5
- @template.render(
6
- Polaris::TextFieldComponent.new(form: self, attribute: method, **options, &block)
7
- )
3
+ attr_reader :template
4
+
5
+ delegate :render, :pluralize, to: :template
6
+
7
+ def errors_summary
8
+ return if object.blank?
9
+ return unless object.errors.any?
10
+
11
+ model_name = object.class.model_name.human.downcase
12
+
13
+ render Polaris::BannerComponent.new(
14
+ title: "There's #{pluralize(object.errors.count, "error")} with this #{model_name}:",
15
+ status: :critical,
16
+ ) do
17
+ render(Polaris::ListComponent.new) do |list|
18
+ object.errors.each do |error|
19
+ list.item { error.full_message }
20
+ end
21
+ end
22
+ end
8
23
  end
9
24
 
10
- def errors_for(method)
25
+ def error_for(method)
11
26
  return if object.blank?
12
27
  return unless object.errors.key?(method)
13
- object.errors[method].join(', ').html_safe
28
+
29
+ object.errors.full_messages_for(method)&.first
30
+ end
31
+
32
+ def polaris_text_field(method, **options, &block)
33
+ options[:error] ||= error_for(method)
34
+ if options[:error_hidden] && options[:error]
35
+ options[:error] = !!options[:error]
36
+ end
37
+ render Polaris::TextFieldComponent.new(form: self, attribute: method, **options, &block)
38
+ end
39
+
40
+ def polaris_select(method, **options, &block)
41
+ options[:error] ||= error_for(method)
42
+ if options[:error_hidden] && options[:error]
43
+ options[:error] = !!options[:error]
44
+ end
45
+ value = object&.public_send(method)
46
+ if value.present?
47
+ options[:selected] = value
48
+ end
49
+ render Polaris::SelectComponent.new(form: self, attribute: method, **options, &block)
14
50
  end
15
51
  end
16
52
  end
@@ -0,0 +1,19 @@
1
+ module Polaris
2
+ module UrlHelper
3
+ def polaris_button_to(name = nil, options = nil, html_options = nil, &block)
4
+ html_options, options = options, name if block_given?
5
+ options ||= {}
6
+ html_options ||= {}
7
+ html_options[:classes] = html_options[:class]
8
+ html_options.delete(:class)
9
+
10
+ button = Polaris::HeadlessButton.new(submit: true, **html_options)
11
+ button = button.with_content(name) unless block_given?
12
+ content = render(button, &block)
13
+
14
+ button_to(options, button.html_options) do
15
+ content
16
+ end
17
+ end
18
+ end
19
+ end
@@ -30,11 +30,15 @@ module Polaris
30
30
  pagination: "Polaris::PaginationComponent",
31
31
  progress_bar: "Polaris::ProgressBarComponent",
32
32
  radio_button: "Polaris::RadioButtonComponent",
33
+ resource_list: "Polaris::ResourceListComponent",
34
+ resource_item: "Polaris::ResourceItemComponent",
33
35
  select: "Polaris::SelectComponent",
34
36
  shopify_navigation: "Polaris::ShopifyNavigationComponent",
35
37
  stack: "Polaris::StackComponent",
36
38
  subheading: "Polaris::SubheadingComponent",
37
39
  spinner: "Polaris::SpinnerComponent",
40
+ skeleton_body_text: "Polaris::SkeletonBodyTextComponent",
41
+ tag: "Polaris::TagComponent",
38
42
  text_container: "Polaris::TextContainerComponent",
39
43
  text_field: "Polaris::TextFieldComponent",
40
44
  text_style: "Polaris::TextStyleComponent",
@@ -1,9 +1,11 @@
1
+ import ResourceItem from './resource_item_controller'
1
2
  import Select from './select_controller'
2
3
  import TextField from './text_field_controller'
3
4
 
4
- export { Select, TextField }
5
+ export { ResourceItem, Select, TextField }
5
6
 
6
7
  export function registerPolarisControllers(application) {
8
+ application.register('polaris-resource-item', ResourceItem)
7
9
  application.register('polaris-select', Select)
8
10
  application.register('polaris-text-field', TextField)
9
11
  }
@@ -0,0 +1,15 @@
1
+ import { Controller } from 'stimulus'
2
+
3
+ export default class extends Controller {
4
+ static targets = ['link']
5
+
6
+ open(event) {
7
+ if (this.hasLinkTarget && this.targetNotClickable(event.target)) {
8
+ this.linkTarget.click()
9
+ }
10
+ }
11
+
12
+ targetNotClickable(element) {
13
+ return !element.closest('a') && !element.closest('button') && element.nodeName !== "INPUT"
14
+ }
15
+ }
@@ -99,7 +99,6 @@ export default class extends Controller {
99
99
 
100
100
  // Making sure the new value has the same length of decimal places as the
101
101
  // step / value has.
102
- console.log(numericValue, this.stepValue)
103
102
  const decimalPlaces = Math.max(dpl(numericValue), dpl(this.stepValue))
104
103
 
105
104
  const newValue = Math.min(
@@ -0,0 +1,5 @@
1
+ Description:
2
+ Creates or adds import of NPM package to your application + additional installation steps.
3
+
4
+ Example:
5
+ rails generate polaris_view_components:install
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators/active_record'
4
+
5
+ module PolarisViewComponents
6
+ class InstallGenerator < Rails::Generators::Base
7
+ source_root File.expand_path('templates', __dir__)
8
+
9
+ def add_npm_package
10
+ say "Adding NPM package", :green
11
+ run "yarn add polaris-view-components"
12
+ end
13
+
14
+ def add_to_stimulus_controller
15
+ say "Adding import to to Stimulus controller", :green
16
+ dir_path = "app/javascript/controllers"
17
+ empty_directory('app/javascript')
18
+ empty_directory(dir_path)
19
+
20
+ file_path = "#{dir_path}/index.js"
21
+
22
+ unless File.exist?(file_path)
23
+ copy_file 'stimulus_index.js', file_path
24
+ end
25
+
26
+ append_to_file file_path do
27
+ "import { registerPolarisControllers } from 'polaris-view-components'\nregisterPolarisControllers(application)"
28
+ end
29
+ end
30
+
31
+ def show_readme
32
+ readme 'README'
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,14 @@
1
+ ===============================================================================
2
+
3
+ Some manual setup is still required:
4
+
5
+ 1. Setup Polaris styles in your layouts <head> tag:
6
+
7
+ <link rel="stylesheet" href="https://unpkg.com/@shopify/polaris@6.6.0/dist/styles.css" />
8
+ <%= stylesheet_link_tag 'polaris_view_components' %>
9
+
10
+ 2. Define Polaris style on your <body> tag:
11
+
12
+ <body style="<%= polaris_body_styles %>">
13
+
14
+ ===============================================================================
@@ -0,0 +1,7 @@
1
+ import { Application } from 'stimulus'
2
+ import { definitionsFromContext } from 'stimulus/webpack-helpers'
3
+
4
+ const application = Application.start(document.documentElement)
5
+ const context = require.context('.', true, /_controller\.js$/)
6
+ application.load(definitionsFromContext(context))
7
+
@@ -20,6 +20,7 @@ module Polaris
20
20
  initializer "polaris_view_components.helpers" do
21
21
  ActiveSupport.on_load(:action_controller_base) do
22
22
  helper Polaris::ViewHelper
23
+ helper Polaris::UrlHelper
23
24
  helper Polaris::ActionHelper
24
25
  helper Polaris::ConditionalHelper
25
26
  end
@@ -1,5 +1,5 @@
1
1
  module Polaris
2
2
  module ViewComponents
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: polaris_view_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Gamble
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-08-08 00:00:00.000000000 Z
12
+ date: 2021-09-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -503,6 +503,8 @@ files:
503
503
  - app/components/polaris/form_layout_component.html.erb
504
504
  - app/components/polaris/form_layout_component.rb
505
505
  - app/components/polaris/heading_component.rb
506
+ - app/components/polaris/headless_button.html.erb
507
+ - app/components/polaris/headless_button.rb
506
508
  - app/components/polaris/icon_component.html.erb
507
509
  - app/components/polaris/icon_component.rb
508
510
  - app/components/polaris/inline_error_component.html.erb
@@ -530,15 +532,22 @@ files:
530
532
  - app/components/polaris/progress_bar_component.rb
531
533
  - app/components/polaris/radio_button_component.html.erb
532
534
  - app/components/polaris/radio_button_component.rb
535
+ - app/components/polaris/resource_item_component.html.erb
536
+ - app/components/polaris/resource_item_component.rb
537
+ - app/components/polaris/resource_list_component.rb
533
538
  - app/components/polaris/select_component.html.erb
534
539
  - app/components/polaris/select_component.rb
535
540
  - app/components/polaris/shopify_navigation_component.html.erb
536
541
  - app/components/polaris/shopify_navigation_component.rb
542
+ - app/components/polaris/skeleton_body_text_component.html.erb
543
+ - app/components/polaris/skeleton_body_text_component.rb
537
544
  - app/components/polaris/spinner_component.html.erb
538
545
  - app/components/polaris/spinner_component.rb
539
546
  - app/components/polaris/stack_component.html.erb
540
547
  - app/components/polaris/stack_component.rb
541
548
  - app/components/polaris/subheading_component.rb
549
+ - app/components/polaris/tag_component.html.erb
550
+ - app/components/polaris/tag_component.rb
542
551
  - app/components/polaris/text_container_component.rb
543
552
  - app/components/polaris/text_field_component.html.erb
544
553
  - app/components/polaris/text_field_component.rb
@@ -552,11 +561,17 @@ files:
552
561
  - app/helpers/polaris/fetch_or_fallback_helper.rb
553
562
  - app/helpers/polaris/form_builder.rb
554
563
  - app/helpers/polaris/option_helper.rb
564
+ - app/helpers/polaris/url_helper.rb
555
565
  - app/helpers/polaris/view_helper.rb
556
566
  - app/javascript/polaris/index.js
567
+ - app/javascript/polaris/resource_item_controller.js
557
568
  - app/javascript/polaris/select_controller.js
558
569
  - app/javascript/polaris/text_field_controller.js
559
570
  - app/validators/type_validator.rb
571
+ - lib/generators/polaris_view_components/USAGE
572
+ - lib/generators/polaris_view_components/install_generator.rb
573
+ - lib/generators/polaris_view_components/templates/README
574
+ - lib/generators/polaris_view_components/templates/stimulus_index.js
560
575
  - lib/polaris/view_components.rb
561
576
  - lib/polaris/view_components/engine.rb
562
577
  - lib/polaris/view_components/version.rb