view_component-contrib 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|