view_component_storybook 0.8.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/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/content_concern.rb +42 -0
- 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 -5
- data/lib/view_component/storybook/controls/control_config.rb +24 -36
- 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 -11
- data/lib/view_component/storybook/controls/multi_options_config.rb +46 -0
- data/lib/view_component/storybook/controls/number_config.rb +9 -9
- data/lib/view_component/storybook/controls/object_config.rb +13 -5
- data/lib/view_component/storybook/controls/options_config.rb +17 -30
- data/lib/view_component/storybook/controls/simple_control_config.rb +48 -0
- data/lib/view_component/storybook/controls/text_config.rb +1 -1
- data/lib/view_component/storybook/controls.rb +5 -1
- data/lib/view_component/storybook/dsl/{controls_dsl.rb → legacy_controls_dsl.rb} +18 -21
- data/lib/view_component/storybook/dsl.rb +1 -2
- data/lib/view_component/storybook/engine.rb +13 -2
- data/lib/view_component/storybook/method_args/component_constructor_args.rb +23 -0
- data/lib/view_component/storybook/method_args/control_method_args.rb +91 -0
- data/lib/view_component/storybook/method_args/dry_initializer_component_constructor_args.rb +45 -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/method_args.rb +17 -0
- data/lib/view_component/storybook/slots/slot.rb +24 -0
- data/lib/view_component/storybook/slots/slot_config.rb +79 -0
- data/lib/view_component/storybook/slots.rb +14 -0
- data/lib/view_component/storybook/stories.rb +60 -10
- data/lib/view_component/storybook/story.rb +18 -0
- data/lib/view_component/storybook/story_config.rb +143 -15
- data/lib/view_component/storybook/tasks/write_stories_json.rake +6 -0
- data/lib/view_component/storybook/version.rb +1 -1
- data/lib/view_component/storybook.rb +25 -0
- metadata +64 -20
- data/lib/view_component/storybook/controls/array_config.rb +0 -36
- data/lib/view_component/storybook/dsl/story_dsl.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0dd708afcf2aa165339b0b1fde82ae610665554e3633c1e50b25509088b43e79
|
4
|
+
data.tar.gz: 950739b2892877a1451c262dc2110d6885a86c740c7fec9cd626a305feb8313d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f9b37292f202ac1c79fd4d31b9ace6b067efff03bf60a6f6a7b44a241ce5661c3669a382d9e549461dfe391d9c77fe0b9b98d33a3a5a47ce821d47e9c26ec7d
|
7
|
+
data.tar.gz: 8e7db14af389ae4d4b2dbcf269269476ac9309c9e518226afedbef769e31f72d32ed44a61382f9830836cab5a4ceba45a701af0a66861de31f928713be9b6c55
|
data/README.md
CHANGED
@@ -1,142 +1,21 @@
|
|
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/) via its [Server](https://github.com/storybookjs/storybook/tree/next/app/server) support.
|
4
4
|
|
5
5
|
## Features
|
6
|
-
* A Ruby DSL for writing Stories describing View Components
|
7
|
-
* A Rails controller backend for Storybook Server compatible with Strobook Controls Addon parameters
|
8
|
-
* Coming Soon: Rake tasks to watch View Components and Stories and trigger Storybook hot reloading
|
9
6
|
|
10
|
-
|
7
|
+
- A Ruby DSL for writing Stories describing View Components
|
8
|
+
- A Rails controller backend for Storybook Server compatible with Storybook Controls Addon parameters
|
9
|
+
- Coming Soon: Rake tasks to watch View Components and Stories and trigger Storybook hot reloading
|
11
10
|
|
12
|
-
|
11
|
+
## Documentation
|
13
12
|
|
14
|
-
|
15
|
-
2. Run `bundle install`.
|
16
|
-
3. Add `require "view_component/storybook/engine"` to `config/application.rb`
|
17
|
-
4. Add `**/*.stories.json` to `.gitignore`
|
18
|
-
|
19
|
-
### Storybook Installation
|
20
|
-
|
21
|
-
1. Add Storybook server as a dev dependedncy. The Storybook Controls addon isn't needed but is strongly recommended
|
22
|
-
```sh
|
23
|
-
yarn add @storybook/server @storybook/addon-controls --dev
|
24
|
-
```
|
25
|
-
2. Add an NPM script to your package.json in order to start the storybook later in this guide
|
26
|
-
```json
|
27
|
-
{
|
28
|
-
"scripts": {
|
29
|
-
"storybook": "start-storybook"
|
30
|
-
}
|
31
|
-
}
|
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
|
-
```javascript
|
35
|
-
module.exports = {
|
36
|
-
stories: ['../test/components/**/*.stories.json'],
|
37
|
-
addons: [
|
38
|
-
'@storybook/addon-controls',
|
39
|
-
],
|
40
|
-
};
|
41
|
-
```
|
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
|
-
```javascript
|
44
|
-
|
45
|
-
export const parameters = {
|
46
|
-
server: {
|
47
|
-
url: `http://localhost:3000/rails/stories`,
|
48
|
-
},
|
49
|
-
};
|
50
|
-
```
|
51
|
-
|
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)
|
54
|
-
|
55
|
-
## Usage
|
56
|
-
|
57
|
-
### Writing Stories
|
58
|
-
|
59
|
-
`ViewComponent::Storybook::Stories` provides a way to preview components in Storybook.
|
60
|
-
|
61
|
-
Suppose our app has a `ButtonComponent` that takes a `button_text` parameter:
|
62
|
-
|
63
|
-
```ruby
|
64
|
-
class ButtonComponent < ViewComponent::Base
|
65
|
-
def initialize(button_text:)
|
66
|
-
@button_text = button_text
|
67
|
-
end
|
68
|
-
end
|
69
|
-
```
|
70
|
-
|
71
|
-
We can write a stories desecibing the `ButtonComponent`
|
72
|
-
|
73
|
-
```ruby
|
74
|
-
class ButtonComponentStories < ViewComponent::Storybook::Stories
|
75
|
-
story(:with_short_text) do
|
76
|
-
controls do
|
77
|
-
text(:button_text, 'OK')
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
story(:with_long_text) do
|
82
|
-
controls do
|
83
|
-
text(:button_text, 'Push Me Please!')
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
```
|
88
|
-
|
89
|
-
### Generating Storybook Stories JSON
|
90
|
-
|
91
|
-
Generate the Storybook JSON stories by tunning the rake task:
|
92
|
-
```sh
|
93
|
-
rake view_component_storybook:write_stories_json
|
94
|
-
```
|
95
|
-
|
96
|
-
### Start the Rails app and Storybook
|
97
|
-
|
98
|
-
In separate shells start the Rails app and Storybook
|
99
|
-
|
100
|
-
```sh
|
101
|
-
rails s
|
102
|
-
```
|
103
|
-
```sh
|
104
|
-
yarn storybook
|
105
|
-
```
|
106
|
-
|
107
|
-
Alternatively you can use tools like [Foreman](https://github.com/ddollar/foreman) to start both Rails and Storybook with one command.
|
108
|
-
|
109
|
-
### Configuration
|
110
|
-
|
111
|
-
By Default ViewComponent::Storybook expects to find stories in the folder `test/components/stories`. This can be configured but setting `stories_path` in `config/applicaion.rb`. For example is you're using RSpec you might set the following configuration:
|
112
|
-
|
113
|
-
```ruby
|
114
|
-
config.view_component_storybook.stories_path = Rails.root.join("spec/components/stories")
|
115
|
-
```
|
116
|
-
|
117
|
-
### The Story DSL
|
118
|
-
|
119
|
-
Coming Soon
|
120
|
-
|
121
|
-
#### Parameters
|
122
|
-
#### Layout
|
123
|
-
#### Controls
|
124
|
-
|
125
|
-
|
126
|
-
## Development
|
127
|
-
|
128
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
129
|
-
|
130
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
13
|
+
See [jonspalmer.github.io/view_component_storybook](https://jonspalmer.github.io/view_component_storybook) for documentation.
|
131
14
|
|
132
15
|
## Contributing
|
133
16
|
|
134
|
-
|
17
|
+
This project is intended to be a safe, welcoming space for collaboration. Contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. We recommend reading the [contributing guide](./docs/CONTRIBUTING.md) as well.
|
135
18
|
|
136
19
|
## License
|
137
20
|
|
138
21
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
139
|
-
|
140
|
-
## Code of Conduct
|
141
|
-
|
142
|
-
Everyone interacting in the ViewComponent::Storybook project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/jonspalmer/view_component_storybook/blob/master/CODE_OF_CONDUCT.md).
|
@@ -8,19 +8,18 @@ module ViewComponent
|
|
8
8
|
prepend_view_path File.expand_path("../../../views", __dir__)
|
9
9
|
prepend_view_path Rails.root.join("app/views") if defined?(Rails.root)
|
10
10
|
|
11
|
-
before_action :
|
11
|
+
before_action :find_story_configs, :find_story_config, only: :show
|
12
12
|
before_action :require_local!, unless: :show_stories?
|
13
13
|
|
14
14
|
content_security_policy(false) if respond_to?(:content_security_policy)
|
15
15
|
|
16
16
|
def show
|
17
|
-
|
17
|
+
params_hash = params.permit!.to_h
|
18
18
|
|
19
|
-
@
|
19
|
+
@story = @story_config.story(params_hash)
|
20
20
|
|
21
|
-
|
21
|
+
layout = @story_config.layout
|
22
22
|
|
23
|
-
layout = @story.layout
|
24
23
|
render layout: layout unless layout.nil?
|
25
24
|
end
|
26
25
|
|
@@ -30,17 +29,17 @@ module ViewComponent
|
|
30
29
|
ViewComponent::Storybook.show_stories
|
31
30
|
end
|
32
31
|
|
33
|
-
def
|
32
|
+
def find_story_configs
|
34
33
|
stories_name = params[:stories]
|
35
|
-
@
|
34
|
+
@story_configs = Stories.find_story_configs(stories_name)
|
36
35
|
|
37
|
-
head :not_found unless @
|
36
|
+
head :not_found unless @story_configs
|
38
37
|
end
|
39
38
|
|
40
|
-
def
|
39
|
+
def find_story_config
|
41
40
|
story_name = params[:story]
|
42
|
-
@
|
43
|
-
head :not_found unless @
|
41
|
+
@story_config = @story_configs.find_story_config(story_name)
|
42
|
+
head :not_found unless @story_config
|
44
43
|
end
|
45
44
|
end
|
46
45
|
end
|
@@ -1 +1,8 @@
|
|
1
|
-
<%= render(@component
|
1
|
+
<%= render(@story.component) do |c| -%>
|
2
|
+
<% @story.slots.each do |slot| -%>
|
3
|
+
<%- slot.call do -%>
|
4
|
+
<%= instance_eval(&slot.content_block) if slot.content_block -%>
|
5
|
+
<%- end -%>
|
6
|
+
<%- end -%>
|
7
|
+
<%- instance_eval(&@story.content_block) if @story.content_block -%>
|
8
|
+
<%- end -%>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
en:
|
2
|
+
activemodel:
|
3
|
+
errors:
|
4
|
+
models:
|
5
|
+
view_component/storybook/method_args/method_args:
|
6
|
+
attributes:
|
7
|
+
args:
|
8
|
+
too_few: expected at least %{min} but found %{count}
|
9
|
+
too_many: expected no more than %{max} but found %{count}
|
10
|
+
kwargs:
|
11
|
+
invalid_arg: "'%{kwarg}' is invalid"
|
12
|
+
invalid: expected keys [%{expected_keys}] but found [%{actual_keys}]
|
13
|
+
view_component/storybook/method_args/control_method_args:
|
14
|
+
attributes:
|
15
|
+
controls:
|
16
|
+
invalid_control: "'%{control_name}' is invalid: (%{control_errors})"
|
17
|
+
view_component/storybook/stories:
|
18
|
+
attributes:
|
19
|
+
story_configs:
|
20
|
+
invalid_story: "'%{story_name}' is invalid: (%{story_errors})"
|
21
|
+
duplicate_stories:
|
22
|
+
one: duplicate story name %{duplicate_names}
|
23
|
+
other: duplicate story names %{duplicate_names}
|
24
|
+
view_component/storybook/story_config:
|
25
|
+
attributes:
|
26
|
+
constructor_args:
|
27
|
+
invalid: "invalid: (%{errors})"
|
28
|
+
view_component/storybook/controls/custom_config:
|
29
|
+
attributes:
|
30
|
+
value_method_args:
|
31
|
+
invalid: "invalid: (%{errors})"
|
32
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module Storybook
|
5
|
+
module ContentConcern
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
attr_reader :content_control, :content_block
|
10
|
+
end
|
11
|
+
|
12
|
+
def content(content = nil, &block)
|
13
|
+
case content
|
14
|
+
when Storybook::Controls::ControlConfig
|
15
|
+
@content_control = content.param(content_param)
|
16
|
+
@content_block = nil
|
17
|
+
when String
|
18
|
+
@content_control = nil
|
19
|
+
@content_block = proc { content }
|
20
|
+
else
|
21
|
+
@content_control = nil
|
22
|
+
@content_block = block
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def resolve_content_block(params)
|
27
|
+
if content_control
|
28
|
+
content = content_control.value_from_params(params)
|
29
|
+
proc { content }
|
30
|
+
else
|
31
|
+
content_block
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def content_param
|
38
|
+
:content
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module Storybook
|
5
|
+
module Controls
|
6
|
+
class BaseOptionsConfig < SimpleControlConfig
|
7
|
+
attr_reader :type, :options, :labels
|
8
|
+
|
9
|
+
validates :type, :options, presence: true
|
10
|
+
|
11
|
+
def initialize(type, options, default_value, labels: nil, param: nil, name: nil)
|
12
|
+
super(default_value, param: param, name: name)
|
13
|
+
@type = type
|
14
|
+
@options = options
|
15
|
+
@labels = labels
|
16
|
+
normalize_options
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_csf_params
|
20
|
+
super.deep_merge(argTypes: { param => { options: options } })
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def csf_control_params
|
26
|
+
labels.nil? ? super : super.merge(labels: labels)
|
27
|
+
end
|
28
|
+
|
29
|
+
def normalize_options
|
30
|
+
return unless options.is_a?(Hash)
|
31
|
+
|
32
|
+
warning = "Hash options is deprecated and will be removed in v1.0.0. Use array options and `labels` instead."
|
33
|
+
ActiveSupport::Deprecation.warn(warning)
|
34
|
+
|
35
|
+
@labels = options.invert
|
36
|
+
@options = options.values
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -3,25 +3,26 @@
|
|
3
3
|
module ViewComponent
|
4
4
|
module Storybook
|
5
5
|
module Controls
|
6
|
-
class BooleanConfig <
|
6
|
+
class BooleanConfig < SimpleControlConfig
|
7
7
|
BOOLEAN_VALUES = [true, false].freeze
|
8
8
|
|
9
|
-
validates :
|
9
|
+
validates :default_value, inclusion: { in: BOOLEAN_VALUES }, unless: -> { default_value.nil? }
|
10
10
|
|
11
11
|
def type
|
12
12
|
:boolean
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
15
|
+
def value_from_params(params)
|
16
|
+
params_value = super(params)
|
17
|
+
if params_value.is_a?(String) && params_value.present?
|
18
|
+
case params_value
|
18
19
|
when "true"
|
19
20
|
true
|
20
21
|
when "false"
|
21
22
|
false
|
22
23
|
end
|
23
24
|
else
|
24
|
-
|
25
|
+
params_value
|
25
26
|
end
|
26
27
|
end
|
27
28
|
end
|
@@ -3,11 +3,11 @@
|
|
3
3
|
module ViewComponent
|
4
4
|
module Storybook
|
5
5
|
module Controls
|
6
|
-
class ColorConfig <
|
6
|
+
class ColorConfig < SimpleControlConfig
|
7
7
|
attr_reader :preset_colors
|
8
8
|
|
9
|
-
def initialize(
|
10
|
-
super(
|
9
|
+
def initialize(default_value, preset_colors: nil, param: nil, name: nil)
|
10
|
+
super(default_value, param: param, name: name)
|
11
11
|
@preset_colors = preset_colors
|
12
12
|
end
|
13
13
|
|
@@ -18,8 +18,7 @@ module ViewComponent
|
|
18
18
|
private
|
19
19
|
|
20
20
|
def csf_control_params
|
21
|
-
|
22
|
-
params.merge(presetColors: preset_colors).compact
|
21
|
+
super.merge(presetColors: preset_colors).compact
|
23
22
|
end
|
24
23
|
end
|
25
24
|
end
|
@@ -6,55 +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_param_names } }, if: :should_validate_params?
|
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
|
-
|
38
|
-
|
39
|
-
# provide extension points for subclasses to vary the value
|
40
|
-
def csf_value
|
41
|
-
value
|
32
|
+
def prefix_param(prefix)
|
33
|
+
param("#{prefix}__#{@param}".to_sym)
|
42
34
|
end
|
43
35
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
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
|
36
|
+
def to_csf_params
|
37
|
+
# :nocov:
|
38
|
+
raise NotImplementedError
|
39
|
+
# :nocov:
|
54
40
|
end
|
55
41
|
|
56
|
-
def
|
57
|
-
|
42
|
+
def value_from_params(params)
|
43
|
+
# :nocov:
|
44
|
+
raise NotImplementedError
|
45
|
+
# :nocov:
|
58
46
|
end
|
59
47
|
end
|
60
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,30 +3,33 @@
|
|
3
3
|
module ViewComponent
|
4
4
|
module Storybook
|
5
5
|
module Controls
|
6
|
-
class DateConfig <
|
7
|
-
def initialize(
|
8
|
-
super(
|
6
|
+
class DateConfig < SimpleControlConfig
|
7
|
+
def initialize(default_value, param: nil, name: nil)
|
8
|
+
super(default_value, param: param, name: name)
|
9
9
|
end
|
10
10
|
|
11
11
|
def type
|
12
12
|
:date
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
15
|
+
def value_from_params(params)
|
16
|
+
params_value = super(params)
|
17
|
+
if params_value.is_a?(String)
|
18
|
+
DateTime.iso8601(params_value)
|
18
19
|
else
|
19
|
-
|
20
|
+
params_value
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
23
24
|
private
|
24
25
|
|
25
26
|
def csf_value
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
case default_value
|
28
|
+
when Date
|
29
|
+
default_value.in_time_zone
|
30
|
+
when Time
|
31
|
+
default_value.iso8601
|
32
|
+
end
|
30
33
|
end
|
31
34
|
end
|
32
35
|
end
|