view_component_storybook 0.6.0 → 0.10.1
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/README.md +7 -128
- data/app/controllers/view_component/storybook/stories_controller.rb +10 -11
- data/app/views/view_component/storybook/stories/show.html.erb +8 -1
- data/config/locales/en.yml +32 -0
- data/lib/view_component/storybook.rb +14 -0
- data/lib/view_component/storybook/content_concern.rb +42 -0
- data/lib/view_component/storybook/controls.rb +5 -1
- data/lib/view_component/storybook/controls/base_options_config.rb +41 -0
- data/lib/view_component/storybook/controls/boolean_config.rb +7 -6
- data/lib/view_component/storybook/controls/color_config.rb +4 -6
- data/lib/view_component/storybook/controls/control_config.rb +25 -25
- data/lib/view_component/storybook/controls/controls_helpers.rb +76 -0
- data/lib/view_component/storybook/controls/custom_config.rb +52 -0
- data/lib/view_component/storybook/controls/date_config.rb +14 -13
- data/lib/view_component/storybook/controls/multi_options_config.rb +46 -0
- data/lib/view_component/storybook/controls/number_config.rb +13 -10
- data/lib/view_component/storybook/controls/object_config.rb +13 -7
- data/lib/view_component/storybook/controls/options_config.rb +17 -33
- data/lib/view_component/storybook/controls/simple_control_config.rb +48 -0
- data/lib/view_component/storybook/controls/text_config.rb +1 -3
- data/lib/view_component/storybook/dsl.rb +1 -2
- data/lib/view_component/storybook/dsl/{controls_dsl.rb → legacy_controls_dsl.rb} +19 -22
- data/lib/view_component/storybook/engine.rb +2 -1
- data/lib/view_component/storybook/method_args.rb +16 -0
- data/lib/view_component/storybook/method_args/control_method_args.rb +91 -0
- data/lib/view_component/storybook/method_args/method_args.rb +52 -0
- data/lib/view_component/storybook/method_args/method_parameters_names.rb +97 -0
- data/lib/view_component/storybook/slots.rb +14 -0
- data/lib/view_component/storybook/slots/slot.rb +24 -0
- data/lib/view_component/storybook/slots/slot_config.rb +44 -0
- data/lib/view_component/storybook/stories.rb +60 -14
- data/lib/view_component/storybook/story.rb +18 -0
- data/lib/view_component/storybook/story_config.rb +140 -15
- data/lib/view_component/storybook/tasks/write_stories_json.rake +6 -0
- data/lib/view_component/storybook/version.rb +1 -1
- metadata +64 -23
- data/lib/view_component/storybook/controls/array_config.rb +0 -36
- data/lib/view_component/storybook/dsl/story_dsl.rb +0 -39
@@ -6,43 +6,43 @@ module ViewComponent
|
|
6
6
|
class ControlConfig
|
7
7
|
include ActiveModel::Validations
|
8
8
|
|
9
|
-
|
9
|
+
validates :param, presence: true
|
10
10
|
|
11
|
-
|
12
|
-
validates :param, inclusion: { in: ->(control_config) { control_config.component_params } }, unless: -> { component.nil? }
|
13
|
-
|
14
|
-
def initialize(component, param, value, name: nil)
|
15
|
-
@component = component
|
11
|
+
def initialize(param: nil, name: nil)
|
16
12
|
@param = param
|
17
|
-
@
|
18
|
-
@name = name || param.to_s.humanize.titlecase
|
13
|
+
@name = name
|
19
14
|
end
|
20
15
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
16
|
+
def name(new_name = nil)
|
17
|
+
if new_name.nil?
|
18
|
+
@name ||= param.to_s.humanize.titlecase
|
19
|
+
else
|
20
|
+
@name = new_name
|
21
|
+
self
|
22
|
+
end
|
27
23
|
end
|
28
24
|
|
29
|
-
def
|
30
|
-
param
|
31
|
-
end
|
25
|
+
def param(new_param = nil)
|
26
|
+
return @param if new_param.nil?
|
32
27
|
|
33
|
-
|
34
|
-
|
28
|
+
@param = new_param
|
29
|
+
self
|
35
30
|
end
|
36
31
|
|
37
|
-
|
32
|
+
def prefix_param(prefix)
|
33
|
+
param("#{prefix}__#{@param}".to_sym)
|
34
|
+
end
|
38
35
|
|
39
|
-
|
40
|
-
|
41
|
-
|
36
|
+
def to_csf_params
|
37
|
+
# :nocov:
|
38
|
+
raise NotImplementedError
|
39
|
+
# :nocov:
|
42
40
|
end
|
43
41
|
|
44
|
-
def
|
45
|
-
|
42
|
+
def value_from_params(params)
|
43
|
+
# :nocov:
|
44
|
+
raise NotImplementedError
|
45
|
+
# :nocov:
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module Storybook
|
5
|
+
module Controls
|
6
|
+
module ControlsHelpers
|
7
|
+
def text(default_value)
|
8
|
+
Controls::TextConfig.new(default_value)
|
9
|
+
end
|
10
|
+
|
11
|
+
def boolean(default_value)
|
12
|
+
Controls::BooleanConfig.new(default_value)
|
13
|
+
end
|
14
|
+
|
15
|
+
def number(default_value, min: nil, max: nil, step: nil)
|
16
|
+
Controls::NumberConfig.new(:number, default_value, min: min, max: max, step: step)
|
17
|
+
end
|
18
|
+
|
19
|
+
def range(default_value, min: nil, max: nil, step: nil)
|
20
|
+
Controls::NumberConfig.new(:range, default_value, min: min, max: max, step: step)
|
21
|
+
end
|
22
|
+
|
23
|
+
def color(default_value, preset_colors: nil)
|
24
|
+
Controls::ColorConfig.new(default_value, preset_colors: preset_colors)
|
25
|
+
end
|
26
|
+
|
27
|
+
def object(default_value)
|
28
|
+
Controls::ObjectConfig.new(default_value)
|
29
|
+
end
|
30
|
+
|
31
|
+
def select(options, default_value, labels: nil)
|
32
|
+
Controls::OptionsConfig.new(:select, options, default_value, labels: labels)
|
33
|
+
end
|
34
|
+
|
35
|
+
def multi_select(options, default_value, labels: nil)
|
36
|
+
Controls::MultiOptionsConfig.new(:'multi-select', options, default_value, labels: labels)
|
37
|
+
end
|
38
|
+
|
39
|
+
def radio(options, default_value, labels: nil)
|
40
|
+
Controls::OptionsConfig.new(:radio, options, default_value, labels: labels)
|
41
|
+
end
|
42
|
+
|
43
|
+
def inline_radio(options, default_value, labels: nil)
|
44
|
+
Controls::OptionsConfig.new(:'inline-radio', options, default_value, labels: labels)
|
45
|
+
end
|
46
|
+
|
47
|
+
def check(options, default_value, labels: nil)
|
48
|
+
Controls::MultiOptionsConfig.new(:check, options, default_value, labels: labels)
|
49
|
+
end
|
50
|
+
|
51
|
+
def inline_check(options, default_value)
|
52
|
+
Controls::MultiOptionsConfig.new(:'inline-check', options, default_value)
|
53
|
+
end
|
54
|
+
|
55
|
+
def array(default_value, separator = nil)
|
56
|
+
ActiveSupport::Deprecation.warn("`array` `separator` argument will be removed in v1.0.0.") if separator
|
57
|
+
Controls::ObjectConfig.new(default_value)
|
58
|
+
end
|
59
|
+
|
60
|
+
def date(default_value)
|
61
|
+
Controls::DateConfig.new(default_value)
|
62
|
+
end
|
63
|
+
|
64
|
+
def custom(*args, **kwargs, &block)
|
65
|
+
Controls::CustomConfig.new.with_value(*args, **kwargs, &block)
|
66
|
+
end
|
67
|
+
|
68
|
+
def klazz(value_class, *args, **kwargs)
|
69
|
+
Controls::CustomConfig.new.with_value(*args, **kwargs) do |*a, **kwa|
|
70
|
+
value_class.new(*a, **kwa)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module Storybook
|
5
|
+
module Controls
|
6
|
+
class CustomConfig < ControlConfig
|
7
|
+
attr_reader :value_method_args
|
8
|
+
|
9
|
+
validate :validate_value_method_args
|
10
|
+
|
11
|
+
def with_value(*args, **kwargs, &block)
|
12
|
+
@value_method_args = MethodArgs::ControlMethodArgs.new(block, *args, **kwargs)
|
13
|
+
@value_method_args.with_param_prefix(param)
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def param(new_param = nil)
|
18
|
+
value_method_args.with_param_prefix(new_param) unless new_param.nil?
|
19
|
+
super(new_param)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_csf_params
|
23
|
+
validate!
|
24
|
+
# TODO: Figure out if we can use 'category' with the args table
|
25
|
+
# export default {
|
26
|
+
# argTypes: {
|
27
|
+
# foo: {
|
28
|
+
# table: { category: 'cat', subcategory: 'sub' }
|
29
|
+
# }
|
30
|
+
# }
|
31
|
+
# }
|
32
|
+
value_method_args.controls.reduce({}) do |csf_params, control|
|
33
|
+
csf_params.deep_merge(control.to_csf_params)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def value_from_params(params)
|
38
|
+
value_method_args.call(params)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def validate_value_method_args
|
44
|
+
return if value_method_args.valid?
|
45
|
+
|
46
|
+
value_method_args_errors = value_method_args.errors.full_messages.join(', ')
|
47
|
+
errors.add(:value_method_args, :invalid, errors: value_method_args_errors)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -3,32 +3,33 @@
|
|
3
3
|
module ViewComponent
|
4
4
|
module Storybook
|
5
5
|
module Controls
|
6
|
-
class DateConfig <
|
7
|
-
|
8
|
-
|
9
|
-
def initialize(component, param, value, name: nil)
|
10
|
-
super(component, param, value, name: name)
|
6
|
+
class DateConfig < SimpleControlConfig
|
7
|
+
def initialize(default_value, param: nil, name: nil)
|
8
|
+
super(default_value, param: param, name: name)
|
11
9
|
end
|
12
10
|
|
13
11
|
def type
|
14
12
|
:date
|
15
13
|
end
|
16
14
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
15
|
+
def value_from_params(params)
|
16
|
+
params_value = super(params)
|
17
|
+
if params_value.is_a?(String)
|
18
|
+
DateTime.iso8601(params_value)
|
20
19
|
else
|
21
|
-
|
20
|
+
params_value
|
22
21
|
end
|
23
22
|
end
|
24
23
|
|
25
24
|
private
|
26
25
|
|
27
26
|
def csf_value
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
case default_value
|
28
|
+
when Date
|
29
|
+
default_value.in_time_zone
|
30
|
+
when Time
|
31
|
+
default_value.iso8601
|
32
|
+
end
|
32
33
|
end
|
33
34
|
end
|
34
35
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module Storybook
|
5
|
+
module Controls
|
6
|
+
class MultiOptionsConfig < BaseOptionsConfig
|
7
|
+
TYPES = %i[multi-select check inline-check].freeze
|
8
|
+
|
9
|
+
validates :type, inclusion: { in: TYPES }, unless: -> { type.nil? }
|
10
|
+
validate :validate_default_value, unless: -> { options.nil? || default_value.nil? }
|
11
|
+
|
12
|
+
def initialize(type, options, default_value, labels: nil, param: nil, name: nil)
|
13
|
+
super(type, options, Array.wrap(default_value), labels: labels, param: param, name: name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def value_from_params(params)
|
17
|
+
params_value = super(params)
|
18
|
+
|
19
|
+
if params_value.is_a?(String)
|
20
|
+
params_value = params_value.split(',')
|
21
|
+
params_value = params_value.map(&:to_sym) if symbol_values
|
22
|
+
end
|
23
|
+
params_value
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_csf_params
|
27
|
+
super.deep_merge(argTypes: { param => { options: options } })
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def csf_control_params
|
33
|
+
labels.nil? ? super : super.merge(labels: labels)
|
34
|
+
end
|
35
|
+
|
36
|
+
def symbol_values
|
37
|
+
@symbol_values ||= default_value.first.is_a?(Symbol)
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate_default_value
|
41
|
+
errors.add(:default_value, :inclusion) unless default_value.to_set <= options.to_set
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -3,32 +3,35 @@
|
|
3
3
|
module ViewComponent
|
4
4
|
module Storybook
|
5
5
|
module Controls
|
6
|
-
class NumberConfig <
|
6
|
+
class NumberConfig < SimpleControlConfig
|
7
|
+
TYPES = %i[number range].freeze
|
8
|
+
|
7
9
|
attr_reader :type, :min, :max, :step
|
8
10
|
|
9
|
-
validates :
|
11
|
+
validates :type, presence: true
|
12
|
+
validates :type, inclusion: { in: TYPES }, unless: -> { type.nil? }
|
10
13
|
|
11
|
-
def initialize(type,
|
12
|
-
super(
|
14
|
+
def initialize(type, default_value, min: nil, max: nil, step: nil, param: nil, name: nil)
|
15
|
+
super(default_value, param: param, name: name)
|
13
16
|
@type = type
|
14
17
|
@min = min
|
15
18
|
@max = max
|
16
19
|
@step = step
|
17
20
|
end
|
18
21
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
+
def value_from_params(params)
|
23
|
+
params_value = super(params)
|
24
|
+
if params_value.is_a?(String) && params_value.present?
|
25
|
+
(params_value.to_f % 1) > 0 ? params_value.to_f : params_value.to_i
|
22
26
|
else
|
23
|
-
|
27
|
+
params_value
|
24
28
|
end
|
25
29
|
end
|
26
30
|
|
27
31
|
private
|
28
32
|
|
29
33
|
def csf_control_params
|
30
|
-
|
31
|
-
params.merge(min: min, max: max, step: step).compact
|
34
|
+
super.merge(min: min, max: max, step: step).compact
|
32
35
|
end
|
33
36
|
end
|
34
37
|
end
|
@@ -3,18 +3,24 @@
|
|
3
3
|
module ViewComponent
|
4
4
|
module Storybook
|
5
5
|
module Controls
|
6
|
-
class ObjectConfig <
|
7
|
-
validates :value, presence: true
|
8
|
-
|
6
|
+
class ObjectConfig < SimpleControlConfig
|
9
7
|
def type
|
10
8
|
:object
|
11
9
|
end
|
12
10
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
11
|
+
def value_from_params(params)
|
12
|
+
params_value = super(params)
|
13
|
+
if params_value.is_a?(String)
|
14
|
+
parsed_json = JSON.parse(params_value)
|
15
|
+
if parsed_json.is_a?(Array)
|
16
|
+
parsed_json.map do |item|
|
17
|
+
item.is_a?(Hash) ? item.deep_symbolize_keys : item
|
18
|
+
end
|
19
|
+
else
|
20
|
+
parsed_json.deep_symbolize_keys
|
21
|
+
end
|
16
22
|
else
|
17
|
-
|
23
|
+
params_value
|
18
24
|
end
|
19
25
|
end
|
20
26
|
end
|
@@ -3,49 +3,33 @@
|
|
3
3
|
module ViewComponent
|
4
4
|
module Storybook
|
5
5
|
module Controls
|
6
|
-
class OptionsConfig <
|
6
|
+
class OptionsConfig < BaseOptionsConfig
|
7
|
+
TYPES = %i[select radio inline-radio].freeze
|
7
8
|
|
8
|
-
class << self
|
9
|
-
# support the options being a Hash or an Array. Storybook supports either.
|
10
|
-
def inclusion_in(config)
|
11
|
-
case config.options
|
12
|
-
when Hash
|
13
|
-
config.options.values
|
14
|
-
when Array
|
15
|
-
config.options
|
16
|
-
else
|
17
|
-
[]
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
TYPES = %i[select multi-select radio inline-radio check inline-check].freeze
|
23
|
-
|
24
|
-
attr_reader :type, :options, :symbol_value
|
25
|
-
|
26
|
-
validates :value, :type, :options, presence: true
|
27
9
|
validates :type, inclusion: { in: TYPES }, unless: -> { type.nil? }
|
28
|
-
validates :
|
10
|
+
validates :default_value, inclusion: { in: ->(config) { config.options } }, unless: -> { options.nil? || default_value.nil? }
|
29
11
|
|
30
|
-
def
|
31
|
-
super(
|
32
|
-
|
33
|
-
|
34
|
-
@symbol_value = default_value.is_a?(Symbol)
|
35
|
-
end
|
36
|
-
|
37
|
-
def value_from_param(param)
|
38
|
-
if param.is_a?(String) && symbol_value
|
39
|
-
param.to_sym
|
12
|
+
def value_from_params(params)
|
13
|
+
params_value = super(params)
|
14
|
+
if params_value.is_a?(String) && symbol_value
|
15
|
+
params_value.to_sym
|
40
16
|
else
|
41
|
-
|
17
|
+
params_value
|
42
18
|
end
|
43
19
|
end
|
44
20
|
|
21
|
+
def to_csf_params
|
22
|
+
super.deep_merge(argTypes: { param => { options: options } })
|
23
|
+
end
|
24
|
+
|
45
25
|
private
|
46
26
|
|
47
27
|
def csf_control_params
|
48
|
-
super.merge(
|
28
|
+
labels.nil? ? super : super.merge(labels: labels)
|
29
|
+
end
|
30
|
+
|
31
|
+
def symbol_value
|
32
|
+
@symbol_value ||= default_value.is_a?(Symbol)
|
49
33
|
end
|
50
34
|
end
|
51
35
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module Storybook
|
5
|
+
module Controls
|
6
|
+
##
|
7
|
+
# A simple Control Config maps to one Storybook Control
|
8
|
+
# It has a value and pulls its value from params by key
|
9
|
+
class SimpleControlConfig < ControlConfig
|
10
|
+
attr_reader :default_value
|
11
|
+
|
12
|
+
def initialize(default_value, param: nil, name: nil)
|
13
|
+
super(param: param, name: name)
|
14
|
+
@default_value = default_value
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_csf_params
|
18
|
+
validate!
|
19
|
+
{
|
20
|
+
args: { param => csf_value },
|
21
|
+
argTypes: { param => { control: csf_control_params, name: name } }
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
def value_from_params(params)
|
26
|
+
params.key?(param) ? params[param] : default_value
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# provide extension points for subclasses to vary the value
|
32
|
+
def type
|
33
|
+
# :nocov:
|
34
|
+
raise NotImplementedError
|
35
|
+
# :nocov:
|
36
|
+
end
|
37
|
+
|
38
|
+
def csf_value
|
39
|
+
default_value
|
40
|
+
end
|
41
|
+
|
42
|
+
def csf_control_params
|
43
|
+
{ type: type }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|