view_component-contrib 0.0.1 → 0.1.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 +4 -0
- data/README.md +453 -21
- data/app/templates/install/application_view_component.rb +2 -0
- data/app/templates/install/application_view_component_preview.rb +3 -0
- data/app/templates/install/builder.rb +24 -0
- data/app/templates/install/class_for.rb +3 -0
- data/app/templates/install/generator.rb +275 -0
- data/app/templates/install/identifier.rb +7 -0
- data/app/templates/install/index.js +2 -0
- data/app/templates/install/index.stimulus.js +20 -0
- data/app/templates/install/initializer.rb +16 -0
- data/app/templates/install/postcss-modules.js +13 -0
- data/app/templates/install/template.rb +133 -0
- data/app/views/view_component_contrib/preview.html.erb +7 -0
- data/lib/view_component-contrib.rb +1 -2
- data/lib/view_component_contrib.rb +17 -0
- data/lib/view_component_contrib/base.rb +9 -0
- data/lib/view_component_contrib/preview.rb +11 -0
- data/lib/view_component_contrib/preview/abstract.rb +22 -0
- data/lib/view_component_contrib/preview/base.rb +68 -0
- data/lib/view_component_contrib/preview/default_template.rb +42 -0
- data/lib/view_component_contrib/preview/sidecarable.rb +25 -0
- data/lib/view_component_contrib/translation_helper.rb +45 -0
- data/lib/view_component_contrib/version.rb +5 -0
- data/lib/view_component_contrib/wrapped_helper.rb +10 -0
- data/lib/view_component_contrib/wrapper_component.rb +40 -0
- metadata +101 -10
- data/lib/view_component/contrib/railtie.rb +0 -8
- data/lib/view_component/contrib/version.rb +0 -7
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ruby-next/language/setup"
|
4
|
+
RubyNext::Language.setup_gem_load_path
|
5
|
+
|
6
|
+
module ViewComponentContrib
|
7
|
+
APP_PATH = File.expand_path(File.join(__dir__, "../app"))
|
8
|
+
|
9
|
+
autoload :TranslationHelper, "view_component_contrib/translation_helper"
|
10
|
+
autoload :WrapperComponent, "view_component_contrib/wrapper_component"
|
11
|
+
autoload :WrappedHelper, "view_component_contrib/wrapped_helper"
|
12
|
+
|
13
|
+
autoload :Base, "view_component_contrib/base"
|
14
|
+
autoload :Preview, "view_component_contrib/preview"
|
15
|
+
end
|
16
|
+
|
17
|
+
require "view_component_contrib/version"
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponentContrib
|
4
|
+
module Preview
|
5
|
+
autoload :Base, "view_component_contrib/preview/base"
|
6
|
+
|
7
|
+
autoload :Abstract, "view_component_contrib/preview/abstract"
|
8
|
+
autoload :DefaultTemplate, "view_component_contrib/preview/default_template"
|
9
|
+
autoload :Sidecarable, "view_component_contrib/preview/sidecarable"
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponentContrib
|
4
|
+
module Preview
|
5
|
+
# Adds `abstract_class` accessor and exclude abstract
|
6
|
+
# preview classes from index
|
7
|
+
module Abstract
|
8
|
+
def self.extended(base)
|
9
|
+
base.singleton_class.prepend(ClassMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
attr_accessor :abstract_class
|
14
|
+
alias_method :abstract_class?, :abstract_class
|
15
|
+
|
16
|
+
def all
|
17
|
+
super.reject(&:abstract_class?)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponentContrib
|
4
|
+
module Preview
|
5
|
+
# First, enable abstract classes (if not already extended)
|
6
|
+
unless ViewComponent::Preview.singleton_class.is_a?(ViewComponentContrib::Preview::Abstract)
|
7
|
+
ViewComponent::Preview.extend ViewComponentContrib::Preview::Abstract
|
8
|
+
end
|
9
|
+
|
10
|
+
# Base view component class with extensions already included
|
11
|
+
class Base < ViewComponent::Preview
|
12
|
+
self.abstract_class = true
|
13
|
+
|
14
|
+
include DefaultTemplate
|
15
|
+
|
16
|
+
DEFAULT_CONTAINER_CLASS = ""
|
17
|
+
|
18
|
+
class << self
|
19
|
+
# Support layout inheritance
|
20
|
+
def inherited(child)
|
21
|
+
child.layout(@layout) if defined?(@layout)
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_writer :container_class
|
26
|
+
|
27
|
+
def container_class
|
28
|
+
return @container_class if defined?(@container_class)
|
29
|
+
|
30
|
+
@container_class =
|
31
|
+
if superclass.respond_to?(:container_class)
|
32
|
+
superclass.container_class
|
33
|
+
else
|
34
|
+
DEFAULT_CONTAINER_CLASS
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def render_args(...)
|
39
|
+
super.tap do |res|
|
40
|
+
res[:locals] ||= {}
|
41
|
+
build_component_instance(res[:locals])
|
42
|
+
res[:locals][:container_class] ||= container_class
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def build_component_instance(locals)
|
49
|
+
return locals unless locals[:component].nil?
|
50
|
+
locals[:component] = name.sub(/Preview$/, "Component").safe_constantize&.new
|
51
|
+
rescue => e
|
52
|
+
locals[:component] = nil
|
53
|
+
locals[:error] = e.message
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Shortcut for render_with_template(locals: ...)
|
58
|
+
def render_with(**locals)
|
59
|
+
render_with_template(locals: locals)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Shortcut for render_with_template(locals: {component: ...})
|
63
|
+
def render_component(component)
|
64
|
+
render_with(component: component)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponentContrib
|
4
|
+
module Preview
|
5
|
+
module DefaultTemplate
|
6
|
+
DEFAULT_TEMPLATE = "view_component_contrib/preview"
|
7
|
+
|
8
|
+
def self.included(base)
|
9
|
+
base.singleton_class.prepend(ClassMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
attr_writer :default_preview_template
|
14
|
+
|
15
|
+
def default_preview_template
|
16
|
+
return @default_preview_template if defined?(@default_preview_template)
|
17
|
+
|
18
|
+
@default_preview_template =
|
19
|
+
if superclass.respond_to?(:default_preview_template)
|
20
|
+
superclass.default_preview_template
|
21
|
+
else
|
22
|
+
DEFAULT_TEMPLATE
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def preview_example_template_path(...)
|
27
|
+
super
|
28
|
+
rescue ViewComponent::PreviewTemplateError
|
29
|
+
has_preview_template = preview_paths.find do |path|
|
30
|
+
Dir.glob(File.join(path, preview_name, "preview.html.*")).any?
|
31
|
+
end
|
32
|
+
|
33
|
+
has_preview_template ? File.join(preview_name, "preview") : DEFAULT_TEMPLATE
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
ActiveSupport.on_load(:view_component) do
|
41
|
+
ViewComponent::Base.preview_paths << File.join(ViewComponentContrib::APP_PATH, "views")
|
42
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponentContrib
|
4
|
+
module Preview
|
5
|
+
module Sidecarable
|
6
|
+
PREVIEW_GLOB = "**/preview.rb"
|
7
|
+
|
8
|
+
def self.extended(base)
|
9
|
+
base.singleton_class.prepend(ClassMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def load_previews
|
14
|
+
Array(preview_paths).each do |preview_path|
|
15
|
+
Dir["#{preview_path}/#{PREVIEW_GLOB}"].sort.each { |file| require_dependency file }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def preview_name
|
20
|
+
name.chomp("::Preview").underscore
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponentContrib
|
4
|
+
module TranslationHelper
|
5
|
+
DEFAULT_NAMESPACE = "view_components"
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.extend ClassMethods
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
attr_writer :i18n_namespace
|
13
|
+
|
14
|
+
def i18n_namespace
|
15
|
+
return @i18n_namespace if defined?(@i18n_namespace)
|
16
|
+
|
17
|
+
@i18n_namespace =
|
18
|
+
if superclass.respond_to?(:i18n_namespace)
|
19
|
+
superclass.i18n_namespace
|
20
|
+
else
|
21
|
+
DEFAULT_NAMESPACE
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def i18n_scope
|
26
|
+
return @i18n_scope if defined?(@i18n_scope)
|
27
|
+
|
28
|
+
@i18n_scope = name.sub("::Component", "").underscore.split("/")
|
29
|
+
end
|
30
|
+
|
31
|
+
def i18n_scope=(val)
|
32
|
+
raise ArgumentError, "Must be array" unless val.is_a?(Array)
|
33
|
+
|
34
|
+
@i18n_scope = val.dup.freeze
|
35
|
+
end
|
36
|
+
|
37
|
+
def virtual_path
|
38
|
+
@contrib_virtual_path ||= [
|
39
|
+
i18n_namespace,
|
40
|
+
*i18n_scope
|
41
|
+
].join(".")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponentContrib
|
4
|
+
# WrapperComponent allwows to wrap any component with a custom HTML code.
|
5
|
+
# The whole wrapper is only rendered when the child component.render? returns true.
|
6
|
+
# Thus, wrapper could be used to conditionally render the outer html for components without
|
7
|
+
# conditionals in templates.
|
8
|
+
class WrapperComponent < ViewComponent::Base
|
9
|
+
class DoubleRenderError < StandardError
|
10
|
+
def initialize(component)
|
11
|
+
super("A child component could only be rendered once within a wrapper: #{component}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :component_instance
|
16
|
+
|
17
|
+
delegate :render?, to: :component_instance
|
18
|
+
|
19
|
+
def initialize(component)
|
20
|
+
@component_instance = component
|
21
|
+
end
|
22
|
+
|
23
|
+
# Simply return the contents of the block passed to #render_component.
|
24
|
+
# (Alias couldn't be used here 'cause ViewComponent check for the method presence when
|
25
|
+
# choosing between #call and a template.)
|
26
|
+
def call
|
27
|
+
content
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns rendered child component
|
31
|
+
# The name component is chosen for convienent usage in templates,
|
32
|
+
# so we can simply call `= wrapper.component` in the place where we're going
|
33
|
+
# to put the component
|
34
|
+
def component
|
35
|
+
raise DoubleRenderError, component_instance if @rendered
|
36
|
+
|
37
|
+
@rendered = component_instance.render_in(view_context).html_safe
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: view_component-contrib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vladimir Dementyev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-04-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: view_component
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: ruby-next-core
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.12.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.12.0
|
13
41
|
- !ruby/object:Gem::Dependency
|
14
42
|
name: bundler
|
15
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -24,6 +52,20 @@ dependencies:
|
|
24
52
|
- - ">="
|
25
53
|
- !ruby/object:Gem::Version
|
26
54
|
version: '1.15'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: capybara
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
27
69
|
- !ruby/object:Gem::Dependency
|
28
70
|
name: combustion
|
29
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,33 +81,61 @@ dependencies:
|
|
39
81
|
- !ruby/object:Gem::Version
|
40
82
|
version: '1.1'
|
41
83
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
84
|
+
name: minitest
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '5.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '5.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: minitest-focus
|
43
99
|
requirement: !ruby/object:Gem::Requirement
|
44
100
|
requirements:
|
45
101
|
- - ">="
|
46
102
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
103
|
+
version: '0'
|
48
104
|
type: :development
|
49
105
|
prerelease: false
|
50
106
|
version_requirements: !ruby/object:Gem::Requirement
|
51
107
|
requirements:
|
52
108
|
- - ">="
|
53
109
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
110
|
+
version: '0'
|
55
111
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
112
|
+
name: minitest-reporters
|
57
113
|
requirement: !ruby/object:Gem::Requirement
|
58
114
|
requirements:
|
59
115
|
- - ">="
|
60
116
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
117
|
+
version: '0'
|
62
118
|
type: :development
|
63
119
|
prerelease: false
|
64
120
|
version_requirements: !ruby/object:Gem::Requirement
|
65
121
|
requirements:
|
66
122
|
- - ">="
|
67
123
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rake
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '13.0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '13.0'
|
69
139
|
description: A collection of extensions and developer tools for ViewComponent
|
70
140
|
email:
|
71
141
|
- dementiev.vm@gmail.com
|
@@ -76,9 +146,30 @@ files:
|
|
76
146
|
- CHANGELOG.md
|
77
147
|
- LICENSE.txt
|
78
148
|
- README.md
|
149
|
+
- app/templates/install/application_view_component.rb
|
150
|
+
- app/templates/install/application_view_component_preview.rb
|
151
|
+
- app/templates/install/builder.rb
|
152
|
+
- app/templates/install/class_for.rb
|
153
|
+
- app/templates/install/generator.rb
|
154
|
+
- app/templates/install/identifier.rb
|
155
|
+
- app/templates/install/index.js
|
156
|
+
- app/templates/install/index.stimulus.js
|
157
|
+
- app/templates/install/initializer.rb
|
158
|
+
- app/templates/install/postcss-modules.js
|
159
|
+
- app/templates/install/template.rb
|
160
|
+
- app/views/view_component_contrib/preview.html.erb
|
79
161
|
- lib/view_component-contrib.rb
|
80
|
-
- lib/
|
81
|
-
- lib/
|
162
|
+
- lib/view_component_contrib.rb
|
163
|
+
- lib/view_component_contrib/base.rb
|
164
|
+
- lib/view_component_contrib/preview.rb
|
165
|
+
- lib/view_component_contrib/preview/abstract.rb
|
166
|
+
- lib/view_component_contrib/preview/base.rb
|
167
|
+
- lib/view_component_contrib/preview/default_template.rb
|
168
|
+
- lib/view_component_contrib/preview/sidecarable.rb
|
169
|
+
- lib/view_component_contrib/translation_helper.rb
|
170
|
+
- lib/view_component_contrib/version.rb
|
171
|
+
- lib/view_component_contrib/wrapped_helper.rb
|
172
|
+
- lib/view_component_contrib/wrapper_component.rb
|
82
173
|
homepage: http://github.com/palkan/view_component-contrib
|
83
174
|
licenses:
|
84
175
|
- MIT
|