slack-block-kit 0.1.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 +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/README.md +62 -0
- data/Rakefile +6 -0
- data/bin/console +27 -0
- data/bin/setup +8 -0
- data/examples/slack_template_00.rb +46 -0
- data/examples/slack_template_01.rb +22 -0
- data/examples/slack_template_02.rb +28 -0
- data/examples/slack_template_03.rb +57 -0
- data/examples/slack_template_04.rb +29 -0
- data/examples/slack_template_05.rb +12 -0
- data/examples/slack_template_06.rb +53 -0
- data/examples/slack_template_07.rb +74 -0
- data/examples/slack_template_08.rb +77 -0
- data/examples/slack_template_09.rb +53 -0
- data/lib/slack-block-kit.rb +1 -0
- data/lib/slack/block_kit.rb +38 -0
- data/lib/slack/block_kit/block.rb +41 -0
- data/lib/slack/block_kit/block/actions_block.rb +35 -0
- data/lib/slack/block_kit/block/context_block.rb +30 -0
- data/lib/slack/block_kit/block/divider_block.rb +17 -0
- data/lib/slack/block_kit/block/image_block.rb +44 -0
- data/lib/slack/block_kit/block/section_block.rb +55 -0
- data/lib/slack/block_kit/composition_objects/confirmation_dialog.rb +59 -0
- data/lib/slack/block_kit/composition_objects/filter.rb +38 -0
- data/lib/slack/block_kit/composition_objects/option.rb +57 -0
- data/lib/slack/block_kit/composition_objects/option_group.rb +34 -0
- data/lib/slack/block_kit/composition_objects/text.rb +61 -0
- data/lib/slack/block_kit/element.rb +41 -0
- data/lib/slack/block_kit/element/button_element.rb +48 -0
- data/lib/slack/block_kit/element/channels_select_element.rb +31 -0
- data/lib/slack/block_kit/element/conversations_select_element.rb +43 -0
- data/lib/slack/block_kit/element/date_picker_element.rb +56 -0
- data/lib/slack/block_kit/element/external_select_element.rb +38 -0
- data/lib/slack/block_kit/element/image_element.rb +26 -0
- data/lib/slack/block_kit/element/multi_channels_select_element.rb +38 -0
- data/lib/slack/block_kit/element/multi_conversations_select_element.rb +38 -0
- data/lib/slack/block_kit/element/multi_external_select_element.rb +38 -0
- data/lib/slack/block_kit/element/multi_static_select_element.rb +38 -0
- data/lib/slack/block_kit/element/multi_users_select_element.rb +39 -0
- data/lib/slack/block_kit/element/overflow_element.rb +42 -0
- data/lib/slack/block_kit/element/select_element.rb +45 -0
- data/lib/slack/block_kit/element/static_select_element.rb +46 -0
- data/lib/slack/block_kit/element/users_select_element.rb +24 -0
- data/lib/slack/block_kit/execution_context.rb +64 -0
- data/lib/slack/block_kit/refinements/hash_compact.rb +15 -0
- data/lib/slack/block_kit/type_restricted_array.rb +21 -0
- data/lib/slack/block_kit/version.rb +5 -0
- data/slack-block-kit.gemspec +29 -0
- metadata +166 -0
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Slack
         | 
| 4 | 
            +
              module BlockKit
         | 
| 5 | 
            +
                module CompositionObjects
         | 
| 6 | 
            +
                  class Filter
         | 
| 7 | 
            +
                    using Refinements::HashCompact
         | 
| 8 | 
            +
                    attr_reader :include, :exclude_external_shared_channels, :exclude_bot_users
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    def self.[](hash)
         | 
| 11 | 
            +
                      new.tap do |object|
         | 
| 12 | 
            +
                        hash[:include].each(&object.include.method(:<<))
         | 
| 13 | 
            +
                        object.exclude_external_shared_channels! if hash[:exclude_external_shared_channels]
         | 
| 14 | 
            +
                        object.exclude_bot_users! if hash[:exclude_bot_users]
         | 
| 15 | 
            +
                      end
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    def initialize
         | 
| 19 | 
            +
                      @include = TypeRestrictedArray.new(String)
         | 
| 20 | 
            +
                    end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    def exclude_external_shared_channels!
         | 
| 23 | 
            +
                      @exclude_external_shared_channels = true
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    def exclude_bot_users!
         | 
| 27 | 
            +
                      @exclude_bot_users = true
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    def to_h
         | 
| 31 | 
            +
                      { include: self.include,
         | 
| 32 | 
            +
                        exclude_external_shared_channels: exclude_external_shared_channels,
         | 
| 33 | 
            +
                        exclude_bot_users: exclude_bot_users }.compact
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
            end
         | 
| @@ -0,0 +1,57 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Slack
         | 
| 4 | 
            +
              module BlockKit
         | 
| 5 | 
            +
                module CompositionObjects
         | 
| 6 | 
            +
                  class Option
         | 
| 7 | 
            +
                    using Refinements::HashCompact
         | 
| 8 | 
            +
                    attr_reader :text, :value, :description, :url
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    def self.[](hash)
         | 
| 11 | 
            +
                      new.tap do |object|
         | 
| 12 | 
            +
                        object.text = hash.fetch(:text)
         | 
| 13 | 
            +
                        object.value = hash.fetch(:value)
         | 
| 14 | 
            +
                        object.description = hash[:description] if hash.key?(:description)
         | 
| 15 | 
            +
                        object.url = hash[:url] if hash.key?(:url)
         | 
| 16 | 
            +
                      end
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    def text=(obj)
         | 
| 20 | 
            +
                      raise TypeError, 'text must be a Text Object' unless obj.is_a?(Text)
         | 
| 21 | 
            +
                      raise RangeError, 'text is max 75 characters' unless obj.text.size <= 75
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                      @text = obj
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    def value=(obj)
         | 
| 27 | 
            +
                      raise TypeError, 'value must be a string' unless obj.respond_to?(:to_str)
         | 
| 28 | 
            +
                      raise RangeError, 'value is max 75 characters' unless obj.size <= 75
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                      @value = obj.to_s
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    def description=(obj)
         | 
| 34 | 
            +
                      raise TypeError, 'description must be a Text Object' unless obj.is_a?(Text)
         | 
| 35 | 
            +
                      raise TypeError, 'description must be plain_text' unless obj.type == :plain_text
         | 
| 36 | 
            +
                      raise RangeError, 'description is max 75 characters' unless obj.text.size <= 75
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                      @description = obj
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    def url=(obj)
         | 
| 42 | 
            +
                      raise TypeError, 'url must be a string' unless url.respond_to?(:to_str)
         | 
| 43 | 
            +
                      raise RangeError, 'url is max 3000 characters' unless url.size <= 3000
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                      @url = url.to_s
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                    def to_h
         | 
| 49 | 
            +
                      { text: text.to_h,
         | 
| 50 | 
            +
                        value: value,
         | 
| 51 | 
            +
                        description: description&.to_h,
         | 
| 52 | 
            +
                        url: url }.compact
         | 
| 53 | 
            +
                    end
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
            end
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Slack
         | 
| 4 | 
            +
              module BlockKit
         | 
| 5 | 
            +
                module CompositionObjects
         | 
| 6 | 
            +
                  class OptionGroup
         | 
| 7 | 
            +
                    attr_reader :label, :options
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    def self.[](hash)
         | 
| 10 | 
            +
                      new.tap do |object|
         | 
| 11 | 
            +
                        object.label = hash.fetch(:label)
         | 
| 12 | 
            +
                        hash[:options].each(&object.options.method(:<<))
         | 
| 13 | 
            +
                      end
         | 
| 14 | 
            +
                    end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                    def initialize
         | 
| 17 | 
            +
                      @options = TypeRestrictedArray.new(Option)
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    def label=(obj)
         | 
| 21 | 
            +
                      raise TypeError, 'label must be a Text Object' unless obj.is_a?(Text)
         | 
| 22 | 
            +
                      raise RangeError, 'label is max 75 characters' unless obj.text.size <= 75
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                      @label = obj
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    def to_h
         | 
| 28 | 
            +
                      { label: label.to_h,
         | 
| 29 | 
            +
                        options: options.map(&:to_h) }
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
| @@ -0,0 +1,61 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Slack
         | 
| 4 | 
            +
              module BlockKit
         | 
| 5 | 
            +
                module CompositionObjects
         | 
| 6 | 
            +
                  class Text
         | 
| 7 | 
            +
                    using Refinements::HashCompact
         | 
| 8 | 
            +
                    attr_reader :type, :text, :emoji, :verbatim
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    PLAINTEXT = :plain_text
         | 
| 11 | 
            +
                    MRKDWN = :mrkdwn
         | 
| 12 | 
            +
                    NEWLINE = "\n"
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    def self.[](hash)
         | 
| 15 | 
            +
                      new.tap do |object|
         | 
| 16 | 
            +
                        object.type = hash.keys.find { |key| [PLAINTEXT, MRKDWN].include?(key) }
         | 
| 17 | 
            +
                        raise ArgumentError, 'type must be `plain_text` or `mrkdwn`' unless object.type
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                        object.text = hash[object.type]
         | 
| 20 | 
            +
                        object.emoji! if hash[:emoji]
         | 
| 21 | 
            +
                        object.verbatim! if hash[:verbatim]
         | 
| 22 | 
            +
                      end
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    def empty?
         | 
| 26 | 
            +
                      text&.empty?
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                    def emoji!
         | 
| 30 | 
            +
                      @emoji = true
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    def verbatim!
         | 
| 34 | 
            +
                      @verbatim = true
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                    def type=(type)
         | 
| 38 | 
            +
                      unless [PLAINTEXT, MRKDWN].include?(type.to_sym)
         | 
| 39 | 
            +
                        raise ArgumentError, 'type must be `plain_text` or `mrkdwn`'
         | 
| 40 | 
            +
                      end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                      @type = type.to_sym
         | 
| 43 | 
            +
                    end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                    def text=(text)
         | 
| 46 | 
            +
                      text = text.join(NEWLINE) if text.is_a?(Array)
         | 
| 47 | 
            +
                      raise TypeError, 'text must be a string' unless text.respond_to?(:to_str)
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                      @text = text.to_s
         | 
| 50 | 
            +
                    end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                    def to_h
         | 
| 53 | 
            +
                      { type: type,
         | 
| 54 | 
            +
                        text: text,
         | 
| 55 | 
            +
                        emoji: emoji,
         | 
| 56 | 
            +
                        verbatim: verbatim }.compact
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
            end
         | 
| @@ -0,0 +1,41 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Slack
         | 
| 4 | 
            +
              module BlockKit
         | 
| 5 | 
            +
                class Element
         | 
| 6 | 
            +
                  attr_reader :action_id
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def self.populate(hash, object)
         | 
| 9 | 
            +
                    object.action_id = hash[:action_id] if hash.key?(:action_id)
         | 
| 10 | 
            +
                    raise ArgumentError, "invalid #{name}" unless object.valid?
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  def self.[](hash)
         | 
| 14 | 
            +
                    new.tap { |obj| populate(hash, obj) }
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def action_id=(obj)
         | 
| 18 | 
            +
                    raise TypeError, 'action_id must be a string' unless action_id.respond_to?(:to_str)
         | 
| 19 | 
            +
                    raise RangeError, 'action_id must be max 255 characters' unless action_id.size <= 255
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    @action_id = obj.to_s
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  def type
         | 
| 25 | 
            +
                    @type ||= self.class.name
         | 
| 26 | 
            +
                      .split('::')
         | 
| 27 | 
            +
                      .last.chomp('Element')
         | 
| 28 | 
            +
                      .gsub(/([a-z])([A-Z])/, '\1_\2').downcase
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  def valid?
         | 
| 32 | 
            +
                    true
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  def to_h
         | 
| 36 | 
            +
                    { type: type,
         | 
| 37 | 
            +
                      action_id: action_id }
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
            end
         | 
| @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Slack
         | 
| 4 | 
            +
              module BlockKit
         | 
| 5 | 
            +
                class Element
         | 
| 6 | 
            +
                  class ButtonElement < Element
         | 
| 7 | 
            +
                    using Refinements::HashCompact
         | 
| 8 | 
            +
                    attr_reader :text, :style
         | 
| 9 | 
            +
                    attr_accessor :value
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    def self.populate(hash, object)
         | 
| 12 | 
            +
                      object.text = hash.fetch(:text)
         | 
| 13 | 
            +
                      object.action_id = hash.fetch(:action_id) if hash[:action_id]
         | 
| 14 | 
            +
                      object.style = hash.fetch(:style) if hash[:style]
         | 
| 15 | 
            +
                      object.value = hash.fetch(:value) if hash[:value]
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                      super(hash, object)
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    def valid?
         | 
| 21 | 
            +
                      !@text.empty?
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    def text=(obj)
         | 
| 25 | 
            +
                      raise TypeError, 'text must be a Text Object' unless obj.is_a?(CompositionObjects::Text)
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                      @text = obj
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    def style=(obj)
         | 
| 31 | 
            +
                      unless %i( default primary danger ).include?(obj.to_sym)
         | 
| 32 | 
            +
                        raise ArgumentError, 'style may only be default, primary, or danger'
         | 
| 33 | 
            +
                      end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                      @style = obj.to_sym
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    def to_h
         | 
| 39 | 
            +
                      super.merge(
         | 
| 40 | 
            +
                        text: text.to_h,
         | 
| 41 | 
            +
                        style: style,
         | 
| 42 | 
            +
                        value: value
         | 
| 43 | 
            +
                      ).compact
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
            end
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Slack
         | 
| 4 | 
            +
              module BlockKit
         | 
| 5 | 
            +
                class Element
         | 
| 6 | 
            +
                  class ChannelsSelectElement < SelectElement
         | 
| 7 | 
            +
                    using Refinements::HashCompact
         | 
| 8 | 
            +
                    attr_reader :initial_channel, :response_url_enabled
         | 
| 9 | 
            +
                    attr_writer :initial_channel
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    def self.populate(hash, object)
         | 
| 12 | 
            +
                      object.initial_channel = hash[:initial_channel] if hash.key?(:initial_channel)
         | 
| 13 | 
            +
                      object.response_url_enabled! if hash.key?(:response_url_enabled)
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                      super(hash, object)
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    def response_url_enabled!
         | 
| 19 | 
            +
                      @response_url_enabled = true
         | 
| 20 | 
            +
                    end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    def to_h
         | 
| 23 | 
            +
                      super.merge(
         | 
| 24 | 
            +
                        initial_channel: initial_channel,
         | 
| 25 | 
            +
                        response_url_enabled: response_url_enabled
         | 
| 26 | 
            +
                      ).compact
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         | 
| @@ -0,0 +1,43 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Slack
         | 
| 4 | 
            +
              module BlockKit
         | 
| 5 | 
            +
                class Element
         | 
| 6 | 
            +
                  class ConversationsSelectElement < SelectElement
         | 
| 7 | 
            +
                    using Refinements::HashCompact
         | 
| 8 | 
            +
                    attr_reader :initial_conversation, :response_url_enabled, :filter
         | 
| 9 | 
            +
                    attr_writer :initial_conversation
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    def self.populate(hash, object)
         | 
| 12 | 
            +
                      if hash.key?(:initial_conversation)
         | 
| 13 | 
            +
                        object.initial_conversation = hash[:initial_conversation]
         | 
| 14 | 
            +
                      end
         | 
| 15 | 
            +
                      object.response_url_enabled! if hash.key?(:response_url_enabled)
         | 
| 16 | 
            +
                      object.filter = hash[:filter] if hash.key?(:filter)
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                      super(hash, object)
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    def response_url_enabled!
         | 
| 22 | 
            +
                      @response_url_enabled = true
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    def filter=(obj)
         | 
| 26 | 
            +
                      unless obj.is_a?(CompositionObjects::Filter)
         | 
| 27 | 
            +
                        raise TypeError, 'confirm must be a Filter Object'
         | 
| 28 | 
            +
                      end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                      @filter = obj
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    def to_h
         | 
| 34 | 
            +
                      super.merge(
         | 
| 35 | 
            +
                        initial_conversation: initial_conversation,
         | 
| 36 | 
            +
                        response_url_enabled: response_url_enabled,
         | 
| 37 | 
            +
                        filter: filter&.to_h
         | 
| 38 | 
            +
                      ).compact
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
            end
         | 
| @@ -0,0 +1,56 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Slack
         | 
| 4 | 
            +
              module BlockKit
         | 
| 5 | 
            +
                class Element
         | 
| 6 | 
            +
                  class DatePickerElement < Element
         | 
| 7 | 
            +
                    using Refinements::HashCompact
         | 
| 8 | 
            +
                    attr_reader :initial_date, :placeholder, :confirm
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    def self.populate(hash, object)
         | 
| 11 | 
            +
                      object.placeholder = hash.fetch(:placeholder) if hash[:placeholder]
         | 
| 12 | 
            +
                      object.confirm = hash.fetch(:confirm) if hash[:confirm]
         | 
| 13 | 
            +
                      object.initial_date = hash.fetch(:initial_date) if hash[:initial_date]
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                      super(hash, object)
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    def type
         | 
| 19 | 
            +
                      'datepicker'
         | 
| 20 | 
            +
                    end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    def placeholder=(obj)
         | 
| 23 | 
            +
                      raise TypeError, 'placeholder must be a Text Object' unless obj.is_a?(CompositionObjects::Text)
         | 
| 24 | 
            +
                      raise TypeError, 'placeholder must be plain_text' unless obj.type == :plain_text
         | 
| 25 | 
            +
                      raise RangeError, 'placeholder is max 150 characters' unless obj.text.size <= 150
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                      @placeholder = obj
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    def confirm=(obj)
         | 
| 31 | 
            +
                      unless obj.is_a?(CompositionObjects::ConfirmationDialog)
         | 
| 32 | 
            +
                        raise TypeError, 'confirm must be a ConfirmationDialog Object'
         | 
| 33 | 
            +
                      end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                      @confirm = obj
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    def initial_date=(date)
         | 
| 39 | 
            +
                      date = date.strftime('%Y-%m-%d') if date.is_a?(Time)
         | 
| 40 | 
            +
                      raise TypeError, 'initial_date must be a string' unless date.respond_to?(:to_str)
         | 
| 41 | 
            +
                      raise TypeError, 'initial_date must be YYYY-MM-DD' unless date.match?(/\d{4}-\d{2}-\d{2}/)
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                      @initial_date = date.to_s
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    def to_h
         | 
| 47 | 
            +
                      super.merge(
         | 
| 48 | 
            +
                        initial_date: initial_date,
         | 
| 49 | 
            +
                        placeholder: placeholder&.to_h,
         | 
| 50 | 
            +
                        confirm: confirm&.to_h
         | 
| 51 | 
            +
                      ).compact
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
            end
         | 
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Slack
         | 
| 4 | 
            +
              module BlockKit
         | 
| 5 | 
            +
                class Element
         | 
| 6 | 
            +
                  class ExternalSelectElement < SelectElement
         | 
| 7 | 
            +
                    using Refinements::HashCompact
         | 
| 8 | 
            +
                    attr_reader :initial_option, :min_query_length
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    def self.populate(hash, object)
         | 
| 11 | 
            +
                      object.initial_option = hash[:initial_option] if hash.key?(:initial_option)
         | 
| 12 | 
            +
                      object.min_query_length = hash[:min_query_length] if hash.key?(:min_query_length)
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                      super(hash, object)
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    def initial_option=(obj)
         | 
| 18 | 
            +
                      raise TypeError, 'initial_option must be a Option Object' unless obj.is_a?(CompositionObjects::Option)
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                      @initial_option = obj
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    def min_query_length=(length)
         | 
| 24 | 
            +
                      raise TypeError, 'min_query_length must be an integer' unless length.respond_to?(:to_int)
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                      @min_query_length = length.to_i
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                    def to_h
         | 
| 30 | 
            +
                      super.merge(
         | 
| 31 | 
            +
                        initial_option: initial_option&.to_h,
         | 
| 32 | 
            +
                        min_query_length: min_query_length || 3
         | 
| 33 | 
            +
                      ).compact
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
            end
         |