view_component_storybook 0.2.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 156bff92fe14404e71b45c20a0b989efaa70f0c1e01212c91f8db51a9b6399a4
4
- data.tar.gz: fd5cc132d285d64bde3e742fcde2266cc4656ac67de921e54111d9d9ff0af93b
3
+ metadata.gz: 4e8c8a3875d64fe89649af8851324d2a07bd40868065abce8b57cf848cbeb5d3
4
+ data.tar.gz: 554f43665400373ba30b9bc6e307285843b67d3760e5957e0088fa2ba53b325e
5
5
  SHA512:
6
- metadata.gz: 6dabe9bacc42870ad37ef82a8960ed926481a9e3b68bdf6e58c2f09ba89757ede25be1564c45efcdee99a814e5c69d0fda5d29a73573f67fb42587ea8a886a04
7
- data.tar.gz: 78f94f84257b7b1ccebe85e38157bc37bc779c54cccee0909008d5e8d933f88934dabcb225fc9f2e45c4c108d2965cc0bdf2395e8b0b04d758c9afc18fb971d5
6
+ metadata.gz: 398124fee399213bea34acf3aef434877eb01d0c76d9d6f127f5d5493981ecf5ac1f0ddc94ad9850354f6ec3629f1a9e5ca6005b57208abd39d045026415abbd
7
+ data.tar.gz: 31a4a06293f40d19e575243a61cb61e1cff2bd7646da950c01de20f8edd73d1179970a7700064a8ee15cbcd3a73b2060f525bdbf427baeaddc9f9bd9ee6b7ebe
data/README.md CHANGED
@@ -1,26 +1,26 @@
1
1
  # ViewComponent::Storybook
2
2
 
3
- The ViewComponent::Storybook gem provides Ruby api for writing stories describing [View Components](https://github.com/github/view_component) and allowing them to be previewed and tested in [Storybook](https://github.com/storybookjs/storybook/)
3
+ The ViewComponent::Storybook gem provides Ruby api for writing stories describing [View Components](https://github.com/github/view_component) and allowing them to be previewed and tested in [Storybook](https://github.com/storybookjs/storybook/)
4
4
 
5
5
  ## Features
6
6
  * A Ruby DSL for writing Stories describing View Components
7
- * A Rails controller backend for Storybook Server compatible with most Strobook Knobs Addon parameters
7
+ * A Rails controller backend for Storybook Server compatible with Strobook Controls Addon parameters
8
8
  * Coming Soon: Rake tasks to watch View Components and Stories and trigger Storybook hot reloading
9
9
 
10
10
  ## Installation
11
11
 
12
- ### Gem Installation
12
+ ### Gem Installation
13
13
 
14
14
  1. Add the `view_component_storybook` gem, to your Gemfile: `gem 'view_component_storybook'`
15
15
  2. Run `bundle install`.
16
- 3. Add `require "view_component_storybook/engine"` to `config/application.rb`
16
+ 3. Add `require "view_component/storybook/engine"` to `config/application.rb`
17
17
  4. Add `**/*.stories.json` to `.gitignore`
18
18
 
19
19
  ### Storybook Installation
20
20
 
21
- 1. Add Storybook server as a dev dependedncy. The Storybook Knobs addon isn't needed but is strongly recommended
21
+ 1. Add Storybook server as a dev dependedncy. The Storybook Controls addon isn't needed but is strongly recommended
22
22
  ```sh
23
- yarn add @storybook/server @storybook/addon-knobs --dev
23
+ yarn add @storybook/server @storybook/addon-controls --dev
24
24
  ```
25
25
  2. Add an NPM script to your package.json in order to start the storybook later in this guide
26
26
  ```json
@@ -29,29 +29,28 @@ The ViewComponent::Storybook gem provides Ruby api for writing stories describin
29
29
  "storybook": "start-storybook"
30
30
  }
31
31
  }
32
- ```
33
- 3. Create the .storybook/main.js file to configure Storybook to find the json stories the gem creates. Also configure the knobs addon:
32
+ ```
33
+ 3. Create the .storybook/main.js file to configure Storybook to find the json stories the gem creates. Also configure the Controls addon:
34
34
  ```javascript
35
35
  module.exports = {
36
36
  stories: ['../test/components/**/*.stories.json'],
37
37
  addons: [
38
- '@storybook/addon-knobs',
38
+ '@storybook/addon-controls',
39
39
  ],
40
40
  };
41
41
  ```
42
42
  4. Create the .storybook/preview.js file to configure Storybook with the Rails application url to call for the html content of the stories
43
43
  ```javascript
44
- import { addParameters } from '@storybook/server';
45
44
 
46
- addParameters({
45
+ export const parameters = {
47
46
  server: {
48
47
  url: `http://localhost:3000/rails/stories`,
49
48
  },
50
- });
49
+ };
51
50
  ```
52
-
53
51
 
54
- Note: `@storybook/server` will be part of the upcoming Storybook 6.0 release. Until that is released you'll need to use an [alpha release](https://github.com/storybookjs/storybook/releases/tag/v6.0.0-alpha.32)
52
+
53
+ Note: `@storybook/server` will be part of the upcoming Storybook 6.0 release. Until that is released you'll need to use an [rc release](https://github.com/storybookjs/storybook/releases/tag/v6.0.0-rc.14)
55
54
 
56
55
  ## Usage
57
56
 
@@ -74,13 +73,13 @@ We can write a stories desecibing the `ButtonComponent`
74
73
  ```ruby
75
74
  class ButtonComponentStories < ViewComponent::Storybook::Stories
76
75
  story(:with_short_text) do
77
- knobs do
76
+ controls do
78
77
  text(:button_text, 'OK')
79
78
  end
80
79
  end
81
80
 
82
81
  story(:with_long_text) do
83
- knobs do
82
+ controls do
84
83
  text(:button_text, 'Push Me Please!')
85
84
  end
86
85
  end
@@ -121,7 +120,7 @@ Coming Soon
121
120
 
122
121
  #### Parameters
123
122
  #### Layout
124
- #### Knobs
123
+ #### Controls
125
124
 
126
125
 
127
126
  ## Development
@@ -2,13 +2,12 @@
2
2
 
3
3
  require "active_model"
4
4
  require "active_support/dependencies/autoload"
5
- require "view_component/storybook/engine"
6
5
 
7
6
  module ViewComponent
8
7
  module Storybook
9
8
  extend ActiveSupport::Autoload
10
9
 
11
- autoload :Knobs
10
+ autoload :Controls
12
11
  autoload :Stories
13
12
  autoload :StoryConfig
14
13
  autoload :Dsl
@@ -4,11 +4,13 @@ require "active_support/dependencies/autoload"
4
4
 
5
5
  module ViewComponent
6
6
  module Storybook
7
- module Knobs
7
+ module Controls
8
8
  extend ActiveSupport::Autoload
9
9
 
10
- autoload :KnobConfig
11
- autoload :SimpleConfig
10
+ autoload :ControlConfig
11
+ autoload :TextConfig
12
+ autoload :BooleanConfig
13
+ autoload :ColorConfig
12
14
  autoload :NumberConfig
13
15
  autoload :OptionsConfig
14
16
  autoload :ArrayConfig
@@ -2,21 +2,17 @@
2
2
 
3
3
  module ViewComponent
4
4
  module Storybook
5
- module Knobs
6
- class ArrayConfig < KnobConfig
5
+ module Controls
6
+ class ArrayConfig < ControlConfig
7
7
  attr_reader :separator
8
8
 
9
- validates :value, :separator, presence: true
9
+ validates :separator, presence: true
10
10
 
11
- def initialize(component, param, value, separator = ",", name: nil, group_id: nil)
12
- super(component, param, value, name: name, group_id: group_id)
11
+ def initialize(component, param, value, separator = ",", name: nil)
12
+ super(component, param, value, name: name)
13
13
  @separator = separator
14
14
  end
15
15
 
16
- def to_csf_params
17
- super.merge(value: value, separator: separator)
18
- end
19
-
20
16
  def type
21
17
  :array
22
18
  end
@@ -28,6 +24,12 @@ module ViewComponent
28
24
  super(param)
29
25
  end
30
26
  end
27
+
28
+ private
29
+
30
+ def csf_control_params
31
+ super.merge(separator: separator)
32
+ end
31
33
  end
32
34
  end
33
35
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ViewComponent
4
+ module Storybook
5
+ module Controls
6
+ class BooleanConfig < ControlConfig
7
+ BOOLEAN_VALUES = [true, false].freeze
8
+
9
+ validates :value, inclusion: { in: BOOLEAN_VALUES }, unless: -> { value.nil? }
10
+
11
+ def type
12
+ :boolean
13
+ end
14
+
15
+ def value_from_param(param)
16
+ if param.is_a?(String) && param.present?
17
+ case param
18
+ when "true"
19
+ true
20
+ when "false"
21
+ false
22
+ end
23
+ else
24
+ super(param)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ViewComponent
4
+ module Storybook
5
+ module Controls
6
+ class ColorConfig < ControlConfig
7
+ attr_reader :preset_colors
8
+
9
+ def initialize(component, param, value, name: nil, preset_colors: nil)
10
+ super(component, param, value, name: name)
11
+ @preset_colors = preset_colors
12
+ end
13
+
14
+ def type
15
+ :color
16
+ end
17
+
18
+ private
19
+
20
+ def csf_control_params
21
+ params = super
22
+ params.merge(presetColors: preset_colors).compact
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ViewComponent
4
+ module Storybook
5
+ module Controls
6
+ class ControlConfig
7
+ include ActiveModel::Validations
8
+
9
+ attr_reader :component, :param, :value, :name
10
+
11
+ validates :component, :param, presence: true
12
+ validates :param, inclusion: { in: ->(control_config) { control_config.component_param_names } }, if: :should_validate_params?
13
+
14
+ def initialize(component, param, value, name: nil)
15
+ @component = component
16
+ @param = param
17
+ @value = value
18
+ @name = name || param.to_s.humanize.titlecase
19
+ end
20
+
21
+ def to_csf_params
22
+ validate!
23
+ {
24
+ args: { param => csf_value },
25
+ argTypes: { param => { control: csf_control_params, name: name } }
26
+ }
27
+ end
28
+
29
+ def value_from_param(param)
30
+ param
31
+ end
32
+
33
+ def component_param_names
34
+ @component_param_names ||= component_params&.map(&:last)
35
+ end
36
+
37
+ private
38
+
39
+ # provide extension points for subclasses to vary the value
40
+ def csf_value
41
+ value
42
+ end
43
+
44
+ def csf_control_params
45
+ { type: type }
46
+ end
47
+
48
+ def component_accepts_kwargs?
49
+ component_params.map(&:first).include?(:keyrest)
50
+ end
51
+
52
+ def component_params
53
+ @component_params ||= component.instance_method(:initialize).parameters
54
+ end
55
+
56
+ def should_validate_params?
57
+ component.present? && !component_accepts_kwargs?
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -2,21 +2,10 @@
2
2
 
3
3
  module ViewComponent
4
4
  module Storybook
5
- module Knobs
6
- class DateConfig < KnobConfig
7
- validates :value, presence: true
8
-
9
- def initialize(component, param, value, name: nil, group_id: nil)
10
- super(component, param, value, name: name, group_id: group_id)
11
- end
12
-
13
- def to_csf_params
14
- csf_params = super
15
- params_value = value
16
- params_value = params_value.in_time_zone if params_value.is_a?(Date)
17
- params_value = params_value.iso8601 if params_value.is_a?(Time)
18
- csf_params[:value] = params_value
19
- csf_params
5
+ module Controls
6
+ class DateConfig < ControlConfig
7
+ def initialize(component, param, value, name: nil)
8
+ super(component, param, value, name: name)
20
9
  end
21
10
 
22
11
  def type
@@ -30,6 +19,15 @@ module ViewComponent
30
19
  super(param)
31
20
  end
32
21
  end
22
+
23
+ private
24
+
25
+ def csf_value
26
+ params_value = value
27
+ params_value = params_value.in_time_zone if params_value.is_a?(Date)
28
+ params_value = params_value.iso8601 if params_value.is_a?(Time)
29
+ params_value
30
+ end
33
31
  end
34
32
  end
35
33
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ViewComponent
4
+ module Storybook
5
+ module Controls
6
+ class NumberConfig < ControlConfig
7
+ TYPES = %i[number range].freeze
8
+
9
+ attr_reader :type, :min, :max, :step
10
+
11
+ validates :type, presence: true
12
+ validates :type, inclusion: { in: TYPES }, unless: -> { type.nil? }
13
+
14
+ def initialize(type, component, param, value, min: nil, max: nil, step: nil, name: nil)
15
+ super(component, param, value, name: name)
16
+ @type = type
17
+ @min = min
18
+ @max = max
19
+ @step = step
20
+ end
21
+
22
+ def value_from_param(param)
23
+ if param.is_a?(String) && param.present?
24
+ (param.to_f % 1) > 0 ? param.to_f : param.to_i
25
+ else
26
+ super(param)
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def csf_control_params
33
+ params = super
34
+ params.merge(min: min, max: max, step: step).compact
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -2,17 +2,15 @@
2
2
 
3
3
  module ViewComponent
4
4
  module Storybook
5
- module Knobs
6
- class ObjectConfig < KnobConfig
7
- validates :value, presence: true
8
-
5
+ module Controls
6
+ class ObjectConfig < ControlConfig
9
7
  def type
10
8
  :object
11
9
  end
12
10
 
13
11
  def value_from_param(param)
14
12
  if param.is_a?(String)
15
- JSON.parse(param).symbolize_keys
13
+ JSON.parse(param).deep_symbolize_keys
16
14
  else
17
15
  super(param)
18
16
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ViewComponent
4
+ module Storybook
5
+ module Controls
6
+ class OptionsConfig < ControlConfig
7
+ class << self
8
+ # support the options being a Hash or an Array. Storybook supports either.
9
+ def inclusion_in(config)
10
+ case config.options
11
+ when Hash
12
+ config.options.values
13
+ when Array
14
+ config.options
15
+ end
16
+ end
17
+ end
18
+
19
+ TYPES = %i[select multi-select radio inline-radio check inline-check].freeze
20
+
21
+ attr_reader :type, :options, :symbol_value
22
+
23
+ validates :type, :options, presence: true
24
+ validates :type, inclusion: { in: TYPES }, unless: -> { type.nil? }
25
+ validates :value, inclusion: { in: method(:inclusion_in) }, unless: -> { options.nil? || value.nil? }
26
+
27
+ def initialize(type, component, param, options, default_value, name: nil)
28
+ super(component, param, default_value, name: name)
29
+ @type = type
30
+ @options = options
31
+ @symbol_value = default_value.is_a?(Symbol)
32
+ end
33
+
34
+ def value_from_param(param)
35
+ if param.is_a?(String) && symbol_value
36
+ param.to_sym
37
+ else
38
+ super(param)
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def csf_control_params
45
+ super.merge(options: options)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ViewComponent
4
+ module Storybook
5
+ module Controls
6
+ class TextConfig < ControlConfig
7
+ def type
8
+ :text
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -8,7 +8,7 @@ module ViewComponent
8
8
  extend ActiveSupport::Autoload
9
9
 
10
10
  autoload :StoryDsl
11
- autoload :KnobsDsl
11
+ autoload :ControlsDsl
12
12
  end
13
13
  end
14
14
  end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ViewComponent
4
+ module Storybook
5
+ module Dsl
6
+ class ControlsDsl
7
+ attr_reader :component, :controls
8
+
9
+ def initialize(component)
10
+ @component = component
11
+ @controls = []
12
+ end
13
+
14
+ def text(param, value, name: nil)
15
+ controls << Controls::TextConfig.new(component, param, value, name: name)
16
+ end
17
+
18
+ def boolean(param, value, name: nil)
19
+ controls << Controls::BooleanConfig.new(component, param, value, name: name)
20
+ end
21
+
22
+ def number(param, value, name: nil, min: nil, max: nil, step: nil)
23
+ controls << Controls::NumberConfig.new(:number, component, param, value, name: name, min: min, max: max, step: step)
24
+ end
25
+
26
+ def range(param, value, name: nil, min: nil, max: nil, step: nil)
27
+ controls << Controls::NumberConfig.new(:range, component, param, value, name: name, min: min, max: max, step: step)
28
+ end
29
+
30
+ def color(param, value, name: nil, preset_colors: nil)
31
+ controls << Controls::ColorConfig.new(component, param, value, name: name, preset_colors: preset_colors)
32
+ end
33
+
34
+ def object(param, value, name: nil)
35
+ controls << Controls::ObjectConfig.new(component, param, value, name: name)
36
+ end
37
+
38
+ def select(param, options, value, name: nil)
39
+ controls << Controls::OptionsConfig.new(:select, component, param, options, value, name: name)
40
+ end
41
+
42
+ def multi_select(param, options, value, name: nil)
43
+ controls << Controls::OptionsConfig.new(:'multi-select', component, param, options, value, name: name)
44
+ end
45
+
46
+ def radio(param, options, value, name: nil)
47
+ controls << Controls::OptionsConfig.new(:radio, component, param, options, value, name: name)
48
+ end
49
+
50
+ def inline_radio(param, options, value, name: nil)
51
+ controls << Controls::OptionsConfig.new(:'inline-radio', component, param, options, value, name: name)
52
+ end
53
+
54
+ def check(param, options, value, name: nil)
55
+ controls << Controls::OptionsConfig.new(:check, component, param, options, value, name: name)
56
+ end
57
+
58
+ def inline_check(param, options, value, name: nil)
59
+ controls << Controls::OptionsConfig.new(:'inline-check', component, param, options, value, name: name)
60
+ end
61
+
62
+ def array(param, value, separator = ",", name: nil)
63
+ controls << Controls::ArrayConfig.new(component, param, value, separator, name: name)
64
+ end
65
+
66
+ def date(param, value, name: nil)
67
+ controls << Controls::DateConfig.new(component, param, value, name: name)
68
+ end
69
+
70
+ def respond_to_missing?(_method, *)
71
+ true
72
+ end
73
+
74
+ def method_missing(method, *args)
75
+ value = args.first
76
+ control_method = case value
77
+ when Date
78
+ :date
79
+ when Array
80
+ :array
81
+ when Hash
82
+ :object
83
+ when Numeric
84
+ :number
85
+ when TrueClass, FalseClass
86
+ :boolean
87
+ when String
88
+ :text
89
+ end
90
+ if control_method
91
+ send(control_method, method, *args)
92
+ else
93
+ super
94
+ end
95
+ end
96
+
97
+ Controls = ViewComponent::Storybook::Controls
98
+ end
99
+ end
100
+ end
101
+ end
@@ -12,10 +12,10 @@ module ViewComponent
12
12
  @story_config.parameters = params
13
13
  end
14
14
 
15
- def knobs(&block)
16
- knobs_dsl = KnobsDsl.new(story_config.component)
17
- knobs_dsl.instance_eval(&block)
18
- @story_config.knobs = knobs_dsl.knobs
15
+ def controls(&block)
16
+ controls_dsl = ControlsDsl.new(story_config.component)
17
+ controls_dsl.instance_eval(&block)
18
+ @story_config.controls = controls_dsl.controls
19
19
  end
20
20
 
21
21
  def layout(layout)
@@ -26,17 +26,14 @@ module ViewComponent
26
26
  end
27
27
 
28
28
  def to_csf_params
29
- stories_csf = story_configs.map(&:to_csf_params)
30
-
31
29
  csf_params = { title: title }
32
- csf_params[:addons] = ["knobs"] if stories_csf.any? { |csf| csf.key?(:knobs) }
33
30
  csf_params[:parameters] = parameters if parameters.present?
34
31
  csf_params[:stories] = story_configs.map(&:to_csf_params)
35
32
  csf_params
36
33
  end
37
34
 
38
35
  def write_csf_json
39
- json_path = File.join(ViewComponent::Storybook.stories_path, "#{stories_name}.stories.json")
36
+ json_path = File.join(stories_path, "#{stories_name}.stories.json")
40
37
  File.open(json_path, "w") do |f|
41
38
  f.write(JSON.pretty_generate(to_csf_params))
42
39
  end
@@ -84,8 +81,6 @@ module ViewComponent
84
81
 
85
82
  def default_component
86
83
  name.chomp("Stories").constantize
87
- rescue StandardError
88
- nil
89
84
  end
90
85
 
91
86
  def load_stories
@@ -96,10 +91,6 @@ module ViewComponent
96
91
  Storybook.stories_path
97
92
  end
98
93
 
99
- def show_stories
100
- Storybook.show_stories
101
- end
102
-
103
94
  def story_id(name)
104
95
  "#{stories_name}/#{name.to_s.parameterize}".underscore
105
96
  end
@@ -6,28 +6,30 @@ module ViewComponent
6
6
  include ActiveModel::Validations
7
7
 
8
8
  attr_reader :id, :name, :component
9
- attr_accessor :knobs, :parameters, :layout, :content_block
9
+ attr_accessor :controls, :parameters, :layout, :content_block
10
10
 
11
11
  def initialize(id, name, component, layout)
12
12
  @id = id
13
13
  @name = name
14
14
  @component = component
15
15
  @layout = layout
16
- @knobs = []
16
+ @controls = []
17
17
  end
18
18
 
19
19
  def to_csf_params
20
20
  csf_params = { name: name, parameters: { server: { id: id } } }
21
21
  csf_params.deep_merge!(parameters: parameters) if parameters.present?
22
- csf_params[:knobs] = knobs.map(&:to_csf_params) if knobs.present?
22
+ controls.each do |control|
23
+ csf_params.deep_merge!(control.to_csf_params)
24
+ end
23
25
  csf_params
24
26
  end
25
27
 
26
28
  def values_from_params(params)
27
- knobs.map do |knob|
28
- value = knob.value_from_param(params[knob.param])
29
- value = knob.value if value.nil? # nil only not falsey
30
- [knob.param, value]
29
+ controls.map do |control|
30
+ value = control.value_from_param(params[control.param])
31
+ value = control.value if value.nil? # nil only not falsey
32
+ [control.param, value]
31
33
  end.to_h
32
34
  end
33
35
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ViewComponent
4
4
  module Storybook
5
- VERSION = "0.2.0"
5
+ VERSION = "0.8.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: view_component_storybook
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Palmer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-25 00:00:00.000000000 Z
11
+ date: 2021-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: view_component
@@ -100,42 +100,42 @@ dependencies:
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '0.81'
103
+ version: '1.9'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '0.81'
110
+ version: '1.9'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: rubocop-rails
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: 2.4.2
117
+ version: 2.9.1
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: 2.4.2
124
+ version: 2.9.1
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: rubocop-rspec
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '1.38'
131
+ version: '2.1'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '1.38'
138
+ version: '2.1'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: simplecov
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +150,20 @@ dependencies:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
152
  version: 0.18.5
153
+ - !ruby/object:Gem::Dependency
154
+ name: simplecov-console
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '0.9'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '0.9'
153
167
  description: Generate Storybook CSF JSON for rendering Rails View Components in Storybook
154
168
  email:
155
169
  - 328224+jonspalmer@users.noreply.github.com
@@ -162,18 +176,20 @@ files:
162
176
  - app/controllers/view_component/storybook/stories_controller.rb
163
177
  - app/views/view_component/storybook/stories/show.html.erb
164
178
  - lib/view_component/storybook.rb
179
+ - lib/view_component/storybook/controls.rb
180
+ - lib/view_component/storybook/controls/array_config.rb
181
+ - lib/view_component/storybook/controls/boolean_config.rb
182
+ - lib/view_component/storybook/controls/color_config.rb
183
+ - lib/view_component/storybook/controls/control_config.rb
184
+ - lib/view_component/storybook/controls/date_config.rb
185
+ - lib/view_component/storybook/controls/number_config.rb
186
+ - lib/view_component/storybook/controls/object_config.rb
187
+ - lib/view_component/storybook/controls/options_config.rb
188
+ - lib/view_component/storybook/controls/text_config.rb
165
189
  - lib/view_component/storybook/dsl.rb
166
- - lib/view_component/storybook/dsl/knobs_dsl.rb
190
+ - lib/view_component/storybook/dsl/controls_dsl.rb
167
191
  - lib/view_component/storybook/dsl/story_dsl.rb
168
192
  - lib/view_component/storybook/engine.rb
169
- - lib/view_component/storybook/knobs.rb
170
- - lib/view_component/storybook/knobs/array_config.rb
171
- - lib/view_component/storybook/knobs/date_config.rb
172
- - lib/view_component/storybook/knobs/knob_config.rb
173
- - lib/view_component/storybook/knobs/number_config.rb
174
- - lib/view_component/storybook/knobs/object_config.rb
175
- - lib/view_component/storybook/knobs/options_config.rb
176
- - lib/view_component/storybook/knobs/simple_config.rb
177
193
  - lib/view_component/storybook/stories.rb
178
194
  - lib/view_component/storybook/story_config.rb
179
195
  - lib/view_component/storybook/tasks/write_stories_json.rake
@@ -193,7 +209,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
193
209
  requirements:
194
210
  - - ">="
195
211
  - !ruby/object:Gem::Version
196
- version: 2.3.0
212
+ version: 2.4.0
197
213
  required_rubygems_version: !ruby/object:Gem::Requirement
198
214
  requirements:
199
215
  - - ">="
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ViewComponent
4
- module Storybook
5
- module Dsl
6
- class KnobsDsl
7
- attr_reader :component, :knobs
8
-
9
- def initialize(component)
10
- @component = component
11
- @knobs = []
12
- end
13
-
14
- def text(param, value, group_id: nil, name: nil)
15
- knobs << Knobs::SimpleConfig.new(:text, component, param, value, group_id: group_id, name: name)
16
- end
17
-
18
- def boolean(param, value, group_id: nil, name: nil)
19
- knobs << Knobs::SimpleConfig.new(:boolean, component, param, value, group_id: group_id, name: name)
20
- end
21
-
22
- def number(param, value, options = {}, group_id: nil, name: nil)
23
- knobs << Knobs::NumberConfig.new(component, param, value, options, group_id: group_id, name: name)
24
- end
25
-
26
- def color(param, value, group_id: nil, name: nil)
27
- knobs << Knobs::SimpleConfig.new(:color, component, param, value, group_id: group_id, name: name)
28
- end
29
-
30
- def object(param, value, group_id: nil, name: nil)
31
- knobs << Knobs::ObjectConfig.new(component, param, value, group_id: group_id, name: name)
32
- end
33
-
34
- def select(param, options, value, group_id: nil, name: nil)
35
- knobs << Knobs::OptionsConfig.new(:select, component, param, options, value, group_id: group_id, name: name)
36
- end
37
-
38
- def radios(param, options, value, group_id: nil, name: nil)
39
- knobs << Knobs::OptionsConfig.new(:radios, component, param, options, value, group_id: group_id, name: name)
40
- end
41
-
42
- def array(param, value, separator = ",", group_id: nil, name: nil)
43
- knobs << Knobs::ArrayConfig.new(component, param, value, separator, group_id: group_id, name: name)
44
- end
45
-
46
- def date(param, value, group_id: nil, name: nil)
47
- knobs << Knobs::DateConfig.new(component, param, value, group_id: group_id, name: name)
48
- end
49
-
50
- def respond_to_missing?(_method)
51
- true
52
- end
53
-
54
- def method_missing(method, *args)
55
- value = args.first
56
- knob_method = case value
57
- when Date
58
- :date
59
- when Array
60
- :array
61
- when Hash
62
- :object
63
- when Numeric
64
- :number
65
- when TrueClass, FalseClass
66
- :boolean
67
- when String
68
- :text
69
- end
70
- if knob_method
71
- send(knob_method, method, *args)
72
- else
73
- super
74
- end
75
- end
76
-
77
- Knobs = ViewComponent::Storybook::Knobs
78
- end
79
- end
80
- end
81
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ViewComponent
4
- module Storybook
5
- module Knobs
6
- class KnobConfig
7
- include ActiveModel::Validations
8
-
9
- attr_reader :component, :param, :value, :name, :group_id
10
-
11
- validates :component, :param, presence: true
12
- validates :param, inclusion: { in: ->(knob_config) { knob_config.component_params } }, unless: -> { component.nil? }
13
-
14
- def initialize(component, param, value, name: nil, group_id: nil)
15
- @component = component
16
- @param = param
17
- @value = value
18
- @name = name || param.to_s.humanize.titlecase
19
- @group_id = group_id
20
- end
21
-
22
- def to_csf_params
23
- validate!
24
- params = { type: type, param: param, name: name, value: value }
25
- params[:group_id] = group_id if group_id
26
- params
27
- end
28
-
29
- def value_from_param(param)
30
- param
31
- end
32
-
33
- def component_params
34
- @component_params ||= component && component.instance_method(:initialize).parameters.map(&:last)
35
- end
36
- end
37
- end
38
- end
39
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ViewComponent
4
- module Storybook
5
- module Knobs
6
- class NumberConfig < KnobConfig
7
- attr_reader :options
8
-
9
- validates :value, presence: true
10
-
11
- def initialize(component, param, value, options = {}, name: nil, group_id: nil)
12
- super(component, param, value, name: name, group_id: group_id)
13
- @options = options
14
- end
15
-
16
- def type
17
- :number
18
- end
19
-
20
- def to_csf_params
21
- params = super
22
- params[:options] = options unless options.empty?
23
- params
24
- end
25
-
26
- def value_from_param(param)
27
- if param.is_a?(String) && param.present?
28
- (param.to_f % 1) > 0 ? param.to_f : param.to_i
29
- else
30
- super(param)
31
- end
32
- end
33
- end
34
- end
35
- end
36
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ViewComponent
4
- module Storybook
5
- module Knobs
6
- class OptionsConfig < KnobConfig
7
- TYPES = %i[select radios].freeze
8
-
9
- attr_reader :type, :options
10
-
11
- validates :value, :type, :options, presence: true
12
- validates :type, inclusion: { in: TYPES }, unless: -> { type.nil? }
13
- validates :value, inclusion: { in: ->(config) { config.options.values } }, unless: -> { options.nil? || value.nil? }
14
-
15
- def initialize(type, component, param, options, default_value, name: nil, group_id: nil)
16
- super(component, param, default_value, name: name, group_id: group_id)
17
- @type = type
18
- @options = options
19
- end
20
-
21
- def to_csf_params
22
- super.merge(options: options)
23
- end
24
- end
25
- end
26
- end
27
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ViewComponent
4
- module Storybook
5
- module Knobs
6
- class SimpleConfig < KnobConfig
7
- TYPES = %i[text boolean color].freeze
8
- BOOLEAN_VALUES = [true, false].freeze
9
-
10
- attr_reader :type
11
-
12
- validates :value, presence: true, unless: -> { type == :boolean }
13
- validates :value, inclusion: { in: BOOLEAN_VALUES }, if: -> { type == :boolean }
14
-
15
- validates :type, presence: true
16
- validates :type, inclusion: { in: TYPES }, unless: -> { type.nil? }
17
-
18
- def initialize(type, component, param, value, name: nil, group_id: nil)
19
- super(component, param, value, name: name, group_id: group_id)
20
- @type = type
21
- end
22
-
23
- def value_from_param(param)
24
- if type == :boolean && param.is_a?(String) && param.present?
25
- case param
26
- when "true"
27
- true
28
- when "false"
29
- false
30
- end
31
- else
32
- super(param)
33
- end
34
- end
35
- end
36
- end
37
- end
38
- end