From 9417744d6f398271f2352b92fdbd42ba900c8bb8 Mon Sep 17 00:00:00 2001 From: Jon Palmer <328224+jonspalmer@users.noreply.github.com> Date: Sat, 7 Jan 2023 13:24:35 -0500 Subject: [PATCH] Move all the collections --- lib/view_component/storybook.rb | 6 +- lib/view_component/storybook/collections.rb | 17 ++++ .../collections/controls_collection.rb | 80 +++++++++++++++++++ .../collections/layout_collection.rb | 37 +++++++++ .../collections/parameters_collection.rb | 40 ++++++++++ .../collections/stories_collection.rb | 31 +++++++ .../collections/valid_for_story_concern.rb | 15 ++++ .../storybook/controls_collection.rb | 80 ------------------- lib/view_component/storybook/engine.rb | 2 +- .../storybook/layout_collection.rb | 37 --------- .../storybook/parameters_collection.rb | 40 ---------- lib/view_component/storybook/stories.rb | 6 +- .../storybook/stories_collection.rb | 29 ------- .../controls_collection_spec.rb | 2 +- 14 files changed, 227 insertions(+), 195 deletions(-) create mode 100644 lib/view_component/storybook/collections.rb create mode 100644 lib/view_component/storybook/collections/controls_collection.rb create mode 100644 lib/view_component/storybook/collections/layout_collection.rb create mode 100644 lib/view_component/storybook/collections/parameters_collection.rb create mode 100644 lib/view_component/storybook/collections/stories_collection.rb create mode 100644 lib/view_component/storybook/collections/valid_for_story_concern.rb delete mode 100644 lib/view_component/storybook/controls_collection.rb delete mode 100644 lib/view_component/storybook/layout_collection.rb delete mode 100644 lib/view_component/storybook/parameters_collection.rb delete mode 100644 lib/view_component/storybook/stories_collection.rb rename spec/view_component/storybook/{ => collections}/controls_collection_spec.rb (99%) diff --git a/lib/view_component/storybook.rb b/lib/view_component/storybook.rb index c701bd0..cb84b3e 100644 --- a/lib/view_component/storybook.rb +++ b/lib/view_component/storybook.rb @@ -8,12 +8,10 @@ module Storybook extend ActiveSupport::Autoload autoload :Controls + autoload :Collections autoload :Stories autoload :StoriesParser - autoload :StoriesCollection - autoload :ControlsCollection - autoload :ParametersCollection - autoload :LayoutCollection + autoload :Story autoload :Slots diff --git a/lib/view_component/storybook/collections.rb b/lib/view_component/storybook/collections.rb new file mode 100644 index 0000000..f3b90ae --- /dev/null +++ b/lib/view_component/storybook/collections.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require "active_support/dependencies/autoload" + +module ViewComponent + module Storybook + module Collections + extend ActiveSupport::Autoload + + autoload :ValidForStoryConcern + autoload :StoriesCollection + autoload :ControlsCollection + autoload :ParametersCollection + autoload :LayoutCollection + end + end +end diff --git a/lib/view_component/storybook/collections/controls_collection.rb b/lib/view_component/storybook/collections/controls_collection.rb new file mode 100644 index 0000000..fe2646c --- /dev/null +++ b/lib/view_component/storybook/collections/controls_collection.rb @@ -0,0 +1,80 @@ +# frozen_string_literal: true + +module ViewComponent + module Storybook + module Collections + class ControlsCollection + include Collections::ValidForStoryConcern + + attr_reader :controls + + attr_accessor :code_object + + def initialize + @controls = [] + end + + def add(param, as:, only: nil, except: nil, **opts) + controls << { param: param, as: as, only: only, except: except, **opts } + end + + def for_story(story_name) + # build the controls for the story_name + # pass through a hash to get the last valid control declared for each param + controls.map do |opts| + next unless valid_for_story?(story_name, **opts.slice(:only, :except)) + + param = opts[:param] + unless opts.key?(:default) + opts = opts.merge(default: parse_default(story_name, param)) + end + [param, build_control(param, **opts.except(:param, :only, :except))] + end.compact.to_h.values + end + + private + + def parse_default(story_name, param) + code_method = code_object.meths.find { |m| m.name == story_name } + default_value_parts = code_method.parameters.find { |parts| parts[0].chomp(":") == param.to_s } + return unless default_value_parts + + code_method.instance_eval(default_value_parts[1]) + end + + def build_control(param, as:, **opts) + case as + when :text + Controls::Text.new(param, **opts) + when :boolean + Controls::Boolean.new(param, **opts) + when :number + Controls::Number.new(param, type: :number, **opts) + when :range + Controls::Number.new(param, type: :range, **opts) + when :color + Controls::Color.new(param, **opts) + when :object, :array + Controls::Object.new(param, **opts) + when :select + Controls::Options.new(param, type: :select, **opts) + when :multi_select + Controls::MultiOptions.new(param, type: :'multi-select', **opts) + when :radio + Controls::Options.new(param, type: :radio, **opts) + when :inline_radio + Controls::Options.new(param, type: :'inline-radio', **opts) + when :check + Controls::MultiOptions.new(param, type: :check, **opts) + when :inline_check + Controls::MultiOptions.new(param, type: :'inline-check', **opts) + when :date + Controls::Date.new(param, **opts) + else + raise "Unknonwn control type '#{as}'" + end + end + end + end + end +end diff --git a/lib/view_component/storybook/collections/layout_collection.rb b/lib/view_component/storybook/collections/layout_collection.rb new file mode 100644 index 0000000..ed7fea7 --- /dev/null +++ b/lib/view_component/storybook/collections/layout_collection.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +module ViewComponent + module Storybook + module Collections + class LayoutCollection + include Collections::ValidForStoryConcern + + def initialize + @default = nil + @layouts = [] + end + + def add(layout, only: nil, except: nil) + if only.nil? && except.nil? + @default = layout + else + layouts << { layout: layout, only: only, except: except } + end + end + + # Parameters set for the story method + def for_story(story_name) + story_layout = default + layouts.each do |opts| + story_layout = opts[:layout] if valid_for_story?(story_name, **opts.slice(:only, :except)) + end + story_layout + end + + private + + attr_reader :default, :layouts + end + end + end +end diff --git a/lib/view_component/storybook/collections/parameters_collection.rb b/lib/view_component/storybook/collections/parameters_collection.rb new file mode 100644 index 0000000..53583ea --- /dev/null +++ b/lib/view_component/storybook/collections/parameters_collection.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +module ViewComponent + module Storybook + module Collections + class ParametersCollection + include Collections::ValidForStoryConcern + + def initialize + @all_paramsters = {} + @parameters = [] + end + + def add(params, only: nil, except: nil) + if only.nil? && except.nil? + all_paramsters.merge!(params) + else + parameters << { params: params, only: only, except: except } + end + end + + # Parameters set for all stories + def for_all + all_paramsters + end + + # Parameters set for the story method + def for_story(story_name) + parameters.each_with_object({}) do |opts, accum| + accum.merge!(opts[:params]) if valid_for_story?(story_name, **opts.slice(:only, :except)) + end + end + + private + + attr_reader :all_paramsters, :parameters + end + end + end +end diff --git a/lib/view_component/storybook/collections/stories_collection.rb b/lib/view_component/storybook/collections/stories_collection.rb new file mode 100644 index 0000000..f2d7972 --- /dev/null +++ b/lib/view_component/storybook/collections/stories_collection.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module ViewComponent + module Storybook + module Collections + class StoriesCollection + include Enumerable + + delegate_missing_to :stories + + attr_reader :stories + + def load(code_objects) + @stories = Array(code_objects).map { |obj| StoriesCollection.stories_from_code_object(obj) }.compact + end + + def self.stories_from_code_object(code_object) + klass = code_object.path.constantize + klass.code_object = code_object + klass + end + + def self.stories_class?(klass) + return unless klass.ancestors.include?(ViewComponent::Storybook::Stories) + + !klass.respond_to?(:abstract_class) || klass.abstract_class != true + end + end + end + end +end diff --git a/lib/view_component/storybook/collections/valid_for_story_concern.rb b/lib/view_component/storybook/collections/valid_for_story_concern.rb new file mode 100644 index 0000000..6f8ee0a --- /dev/null +++ b/lib/view_component/storybook/collections/valid_for_story_concern.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module ViewComponent + module Storybook + module Collections + module ValidForStoryConcern + extend ActiveSupport::Concern + + def valid_for_story?(story_name, only:, except:) + (only.nil? || Array.wrap(only).include?(story_name)) && Array.wrap(except).exclude?(story_name) + end + end + end + end +end diff --git a/lib/view_component/storybook/controls_collection.rb b/lib/view_component/storybook/controls_collection.rb deleted file mode 100644 index 06e01dc..0000000 --- a/lib/view_component/storybook/controls_collection.rb +++ /dev/null @@ -1,80 +0,0 @@ -# frozen_string_literal: true - -module ViewComponent - module Storybook - class ControlsCollection - attr_reader :controls - - attr_accessor :code_object - - def initialize - @controls = [] - end - - def add(param, as:, only: nil, except: nil, **opts) - controls << { param: param, as: as, only: only, except: except, **opts } - end - - def for_story(story_name) - # build the controls for the story_name - # pass through a hash to get the last valid control declared for each param - controls.map do |opts| - next unless valid_for_story?(story_name, **opts.slice(:only, :except)) - - param = opts[:param] - unless opts.key?(:default) - opts = opts.merge(default: parse_default(story_name, param)) - end - [param, build_control(param, **opts.except(:param, :only, :except))] - end.compact.to_h.values - end - - private - - def valid_for_story?(story_name, only:, except:) - (only.nil? || Array.wrap(only).include?(story_name)) && Array.wrap(except).exclude?(story_name) - end - - def parse_default(story_name, param) - code_method = code_object.meths.find { |m| m.name == story_name } - default_value_parts = code_method.parameters.find { |parts| parts[0].chomp(":") == param.to_s } - return unless default_value_parts - - code_method.instance_eval(default_value_parts[1]) - end - - def build_control(param, as:, **opts) - case as - when :text - Controls::Text.new(param, **opts) - when :boolean - Controls::Boolean.new(param, **opts) - when :number - Controls::Number.new(param, type: :number, **opts) - when :range - Controls::Number.new(param, type: :range, **opts) - when :color - Controls::Color.new(param, **opts) - when :object, :array - Controls::Object.new(param, **opts) - when :select - Controls::Options.new(param, type: :select, **opts) - when :multi_select - Controls::MultiOptions.new(param, type: :'multi-select', **opts) - when :radio - Controls::Options.new(param, type: :radio, **opts) - when :inline_radio - Controls::Options.new(param, type: :'inline-radio', **opts) - when :check - Controls::MultiOptions.new(param, type: :check, **opts) - when :inline_check - Controls::MultiOptions.new(param, type: :'inline-check', **opts) - when :date - Controls::Date.new(param, **opts) - else - raise "Unknonwn control type '#{as}'" - end - end - end - end -end diff --git a/lib/view_component/storybook/engine.rb b/lib/view_component/storybook/engine.rb index ead3375..00dfb6d 100644 --- a/lib/view_component/storybook/engine.rb +++ b/lib/view_component/storybook/engine.rb @@ -57,7 +57,7 @@ def parser class << self def stories - @stories ||= StoriesCollection.new + @stories ||= Collections::StoriesCollection.new end end end diff --git a/lib/view_component/storybook/layout_collection.rb b/lib/view_component/storybook/layout_collection.rb deleted file mode 100644 index 479433d..0000000 --- a/lib/view_component/storybook/layout_collection.rb +++ /dev/null @@ -1,37 +0,0 @@ -# frozen_string_literal: true - -module ViewComponent - module Storybook - class LayoutCollection - def initialize - @default = nil - @layouts = [] - end - - def add(layout, only: nil, except: nil) - if only.nil? && except.nil? - @default = layout - else - layouts << { layout: layout, only: only, except: except } - end - end - - # Parameters set for the story method - def for_story(story_name) - story_layout = default - layouts.each do |opts| - story_layout = opts[:layout] if valid_for_story?(story_name, **opts.slice(:only, :except)) - end - story_layout - end - - private - - attr_reader :default, :layouts - - def valid_for_story?(story_name, only:, except:) - (only.nil? || Array.wrap(only).include?(story_name)) && Array.wrap(except).exclude?(story_name) - end - end - end -end diff --git a/lib/view_component/storybook/parameters_collection.rb b/lib/view_component/storybook/parameters_collection.rb deleted file mode 100644 index ba404d0..0000000 --- a/lib/view_component/storybook/parameters_collection.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: true - -module ViewComponent - module Storybook - class ParametersCollection - def initialize - @all_paramsters = {} - @parameters = [] - end - - def add(params, only: nil, except: nil) - if only.nil? && except.nil? - all_paramsters.merge!(params) - else - parameters << { params: params, only: only, except: except } - end - end - - # Parameters set for all stories - def for_all - all_paramsters - end - - # Parameters set for the story method - def for_story(story_name) - parameters.each_with_object({}) do |opts, accum| - accum.merge!(opts[:params]) if valid_for_story?(story_name, **opts.slice(:only, :except)) - end - end - - private - - attr_reader :all_paramsters, :parameters - - def valid_for_story?(story_name, only:, except:) - (only.nil? || Array.wrap(only).include?(story_name)) && Array.wrap(except).exclude?(story_name) - end - end - end -end diff --git a/lib/view_component/storybook/stories.rb b/lib/view_component/storybook/stories.rb index 93b173c..3383cf4 100644 --- a/lib/view_component/storybook/stories.rb +++ b/lib/view_component/storybook/stories.rb @@ -92,7 +92,7 @@ def code_object=(object) private def controls - @controls ||= ControlsCollection.new + @controls ||= Collections::ControlsCollection.new end def stories_title @@ -100,11 +100,11 @@ def stories_title end def parameters_collection - @parameters_collection ||= ParametersCollection.new + @parameters_collection ||= Collections::ParametersCollection.new end def layout_collection - @layout_collection ||= LayoutCollection.new + @layout_collection ||= Collections::LayoutCollection.new end def story_names diff --git a/lib/view_component/storybook/stories_collection.rb b/lib/view_component/storybook/stories_collection.rb deleted file mode 100644 index ee475b4..0000000 --- a/lib/view_component/storybook/stories_collection.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -module ViewComponent - module Storybook - class StoriesCollection - include Enumerable - - delegate_missing_to :stories - - attr_reader :stories - - def load(code_objects) - @stories = Array(code_objects).map { |obj| StoriesCollection.stories_from_code_object(obj) }.compact - end - - def self.stories_from_code_object(code_object) - klass = code_object.path.constantize - klass.code_object = code_object - klass - end - - def self.stories_class?(klass) - return unless klass.ancestors.include?(ViewComponent::Storybook::Stories) - - !klass.respond_to?(:abstract_class) || klass.abstract_class != true - end - end - end -end diff --git a/spec/view_component/storybook/controls_collection_spec.rb b/spec/view_component/storybook/collections/controls_collection_spec.rb similarity index 99% rename from spec/view_component/storybook/controls_collection_spec.rb rename to spec/view_component/storybook/collections/controls_collection_spec.rb index 023c5fc..f28cdca 100644 --- a/spec/view_component/storybook/controls_collection_spec.rb +++ b/spec/view_component/storybook/collections/controls_collection_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe ViewComponent::Storybook::ControlsCollection do +RSpec.describe ViewComponent::Storybook::Collections::ControlsCollection do subject do collection = described_class.new # borromw the code_object from Demo::ButtonComponentStories as an example