view_component_storybook 0.2.0 → 0.8.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 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