block-kit 1.0.1 → 1.0.3
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 +6 -2
- data/lib/block_kit/base.rb +2 -2
- data/lib/block_kit/composition/option.rb +5 -1
- data/lib/block_kit/composition/overflow_option.rb +1 -1
- data/lib/block_kit/composition/slack_file.rb +2 -2
- data/lib/block_kit/composition/text.rb +4 -0
- data/lib/block_kit/composition/trigger.rb +1 -1
- data/lib/block_kit/elements/base.rb +4 -0
- data/lib/block_kit/elements/base_button.rb +4 -0
- data/lib/block_kit/elements/multi_select.rb +4 -0
- data/lib/block_kit/elements/number_input.rb +3 -3
- data/lib/block_kit/elements/select.rb +4 -0
- data/lib/block_kit/layout/base.rb +4 -0
- data/lib/block_kit/surfaces/base.rb +4 -0
- data/lib/block_kit/surfaces/modal.rb +16 -0
- data/lib/block_kit/version.rb +1 -1
- metadata +2 -3
- data/lib/block_kit/concerns/dsl_generation.rb +0 -76
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 033e781b6f1656644ae2038ad1c4d1575f9fe1e9179da732127edb43895612c7
|
4
|
+
data.tar.gz: dbb788025b21764ec964ccfa6c7b2409f47990e64990e62dde1d96ab11e28dd5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9fac2d8adf017f7fcdb109ad1c55f011668c5ec3d2e716d895aaaf38e95d46846b8b7c7a78989e7c8cd40f2ec3a05bf3448d9f9332465757bf7ebe512a55caf
|
7
|
+
data.tar.gz: 777df84ebe6aa32be0ff508d52138bda2546fa5ce0ba60a00aa255637ae3274e78f89382a7cb7dbc70cbbbf91dee43fa937477c30e48aa88ead22e7ebe96dce9
|
data/README.md
CHANGED
@@ -18,7 +18,7 @@ gem install block-kit
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
-
Blocks can be built individually or as a surface or collection of blocks, which each block able to initialize with a simple Hash
|
21
|
+
Blocks can be built individually or as a surface or collection of blocks, which each block able to initialize with a simple Hash of attributes or via a block-based DSL. For example, each of the following declarations would result in the same `section` block:
|
22
22
|
|
23
23
|
```ruby
|
24
24
|
require "block-kit"
|
@@ -180,4 +180,8 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
180
180
|
|
181
181
|
## Code of Conduct
|
182
182
|
|
183
|
-
Everyone interacting in the
|
183
|
+
Everyone interacting in the project's codebase, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/davidcelis/block-kit/blob/main/CODE_OF_CONDUCT.md).
|
184
|
+
|
185
|
+
## Acknowledgements
|
186
|
+
|
187
|
+
Special thanks to [FireHydrant](https://firehydrant.com) for allowing me to build the initial version on the job (and therefore sponsoring the project)!
|
data/lib/block_kit/base.rb
CHANGED
@@ -29,8 +29,8 @@ module BlockKit
|
|
29
29
|
attribute_fixers[:base] << {name: method_name, dangerous: dangerous}
|
30
30
|
end
|
31
31
|
|
32
|
-
def self.inherited(
|
33
|
-
|
32
|
+
def self.inherited(subclass)
|
33
|
+
subclass.attribute_fixers = attribute_fixers.deep_dup
|
34
34
|
end
|
35
35
|
|
36
36
|
def initialize(attributes = {})
|
@@ -23,7 +23,11 @@ module BlockKit
|
|
23
23
|
fixes :value, truncate: {maximum: MAX_VALUE_LENGTH, dangerous: true}
|
24
24
|
|
25
25
|
validates :description, presence: true, length: {maximum: MAX_DESCRIPTION_LENGTH}, allow_nil: true
|
26
|
-
fixes :description, truncate: {maximum: MAX_DESCRIPTION_LENGTH}, null_value: [:blank]
|
26
|
+
fixes :description, truncate: {maximum: MAX_DESCRIPTION_LENGTH}, null_value: {error_types: [:blank]}
|
27
|
+
|
28
|
+
def self.inherited(subclass)
|
29
|
+
subclass.attribute_fixers = attribute_fixers.deep_dup
|
30
|
+
end
|
27
31
|
|
28
32
|
def initial?
|
29
33
|
!!initial
|
@@ -11,7 +11,7 @@ module BlockKit
|
|
11
11
|
|
12
12
|
attribute :url, :string
|
13
13
|
validates :url, presence: true, format: {with: URI::DEFAULT_PARSER.make_regexp, message: "is not a valid URI", allow_blank: true}, length: {maximum: MAX_URL_LENGTH}, allow_nil: true
|
14
|
-
fixes :url, truncate: {maximum: MAX_URL_LENGTH, dangerous: true, omission: ""}, null_value: [:blank]
|
14
|
+
fixes :url, truncate: {maximum: MAX_URL_LENGTH, dangerous: true, omission: ""}, null_value: {error_types: [:blank]}
|
15
15
|
|
16
16
|
def as_json(*)
|
17
17
|
super.merge(url: url).compact
|
@@ -13,10 +13,10 @@ module BlockKit
|
|
13
13
|
attribute :url, :string
|
14
14
|
|
15
15
|
validates :id, presence: true, format: {with: /\AF[A-Z0-9]{8,}\z/, allow_blank: true}, allow_nil: true
|
16
|
-
fixes :id, null_value: [:blank]
|
16
|
+
fixes :id, null_value: {error_types: [:blank]}
|
17
17
|
|
18
18
|
validates :url, presence: true, length: {maximum: MAX_URL_LENGTH}, format: {with: URI::DEFAULT_PARSER.make_regexp(%w[http https]), message: "is not a valid URI", allow_blank: true}, allow_nil: true
|
19
|
-
fixes :url, null_value: [:blank]
|
19
|
+
fixes :url, null_value: {error_types: [:blank]}
|
20
20
|
|
21
21
|
validate :id_or_url_present
|
22
22
|
|
@@ -14,7 +14,7 @@ module BlockKit
|
|
14
14
|
|
15
15
|
validates :url, presence: true, length: {maximum: MAX_URL_LENGTH}, format: {with: URI::DEFAULT_PARSER.make_regexp(%w[http https]), message: "is not a valid URI", allow_blank: true}
|
16
16
|
validates :customizable_input_parameters, presence: true, "block_kit/validators/associated": true, allow_nil: true
|
17
|
-
fixes :customizable_input_parameters, null_value: [:blank]
|
17
|
+
fixes :customizable_input_parameters, null_value: {error_types: [:blank]}
|
18
18
|
|
19
19
|
dsl_method :customizable_input_parameters, as: :customizable_input_parameter, required_fields: [:name, :value], yields: false
|
20
20
|
|
@@ -9,6 +9,10 @@ module BlockKit
|
|
9
9
|
validates :action_id, presence: true, length: {maximum: MAX_ACTION_ID_LENGTH}, allow_nil: true
|
10
10
|
fixes :action_id, truncate: {maximum: MAX_ACTION_ID_LENGTH, dangerous: true, omission: ""}, null_value: {error_types: [:blank]}
|
11
11
|
|
12
|
+
def self.inherited(subclass)
|
13
|
+
subclass.attribute_fixers = attribute_fixers.deep_dup
|
14
|
+
end
|
15
|
+
|
12
16
|
def initialize(attributes = {})
|
13
17
|
raise NotImplementedError, "#{self.class} is an abstract class and can't be instantiated." if instance_of?(Base)
|
14
18
|
|
@@ -27,6 +27,10 @@ module BlockKit
|
|
27
27
|
validates :accessibility_label, presence: true, length: {maximum: MAX_ACCESSIBILITY_LABEL_LENGTH}, allow_nil: true
|
28
28
|
fixes :accessibility_label, truncate: {maximum: MAX_ACCESSIBILITY_LABEL_LENGTH}, null_value: {error_types: [:blank]}
|
29
29
|
|
30
|
+
def self.inherited(subclass)
|
31
|
+
subclass.attribute_fixers = attribute_fixers.deep_dup
|
32
|
+
end
|
33
|
+
|
30
34
|
def initialize(attributes = {})
|
31
35
|
raise NotImplementedError, "#{self.class} is an abstract class and can't be instantiated." if instance_of?(BaseButton)
|
32
36
|
|
@@ -7,6 +7,10 @@ module BlockKit
|
|
7
7
|
validates :max_selected_items, presence: true, numericality: {only_integer: true, greater_than: 0}, allow_nil: true
|
8
8
|
fixes :max_selected_items, null_value: {error_types: [:greater_than]}
|
9
9
|
|
10
|
+
def self.inherited(subclass)
|
11
|
+
subclass.attribute_fixers = attribute_fixers.deep_dup
|
12
|
+
end
|
13
|
+
|
10
14
|
def initialize(attributes = {})
|
11
15
|
raise NotImplementedError, "#{self.class} is an abstract class and can't be instantiated." if instance_of?(MultiSelect)
|
12
16
|
|
@@ -42,9 +42,9 @@ module BlockKit
|
|
42
42
|
def as_json(*)
|
43
43
|
super.merge(
|
44
44
|
is_decimal_allowed: is_decimal_allowed,
|
45
|
-
initial_value: initial_value.respond_to?(:to_digits) ? initial_value.to_digits : initial_value&.
|
46
|
-
min_value: min_value.respond_to?(:to_digits) ? min_value.to_digits : min_value&.
|
47
|
-
max_value: max_value.respond_to?(:to_digits) ? max_value.to_digits : max_value&.
|
45
|
+
initial_value: initial_value.respond_to?(:to_digits) ? initial_value.to_digits : initial_value&.to_s,
|
46
|
+
min_value: min_value.respond_to?(:to_digits) ? min_value.to_digits : min_value&.to_s,
|
47
|
+
max_value: max_value.respond_to?(:to_digits) ? max_value.to_digits : max_value&.to_s
|
48
48
|
).compact
|
49
49
|
end
|
50
50
|
end
|
@@ -8,6 +8,10 @@ module BlockKit
|
|
8
8
|
include Concerns::HasPlaceholder
|
9
9
|
include Concerns::PlainTextEmojiAssignment.new(:placeholder)
|
10
10
|
|
11
|
+
def self.inherited(subclass)
|
12
|
+
subclass.attribute_fixers = attribute_fixers.deep_dup
|
13
|
+
end
|
14
|
+
|
11
15
|
def initialize(attributes = {})
|
12
16
|
raise NotImplementedError, "#{self.class} is an abstract class and can't be instantiated." if instance_of?(Select)
|
13
17
|
|
@@ -9,6 +9,10 @@ module BlockKit
|
|
9
9
|
validates :block_id, presence: true, length: {maximum: MAX_BLOCK_ID_LENGTH}, allow_nil: true
|
10
10
|
fixes :block_id, truncate: {maximum: MAX_BLOCK_ID_LENGTH, dangerous: true, omission: ""}, null_value: {error_types: [:blank]}
|
11
11
|
|
12
|
+
def self.inherited(subclass)
|
13
|
+
subclass.attribute_fixers = attribute_fixers.deep_dup
|
14
|
+
end
|
15
|
+
|
12
16
|
def initialize(attributes = {})
|
13
17
|
raise NotImplementedError, "#{self.class} is an abstract class and can't be instantiated." if instance_of?(Base)
|
14
18
|
|
@@ -45,6 +45,10 @@ module BlockKit
|
|
45
45
|
dsl_method :blocks, as: :section, type: Layout::Section
|
46
46
|
dsl_method :blocks, as: :video, type: Layout::Video, required_fields: [:alt_text, :title, :thumbnail_url, :video_url], yields: false
|
47
47
|
|
48
|
+
def self.inherited(subclass)
|
49
|
+
subclass.attribute_fixers = attribute_fixers.deep_dup
|
50
|
+
end
|
51
|
+
|
48
52
|
def initialize(attributes = {})
|
49
53
|
raise NotImplementedError, "#{self.class} is an abstract class and can't be instantiated." if instance_of?(Base)
|
50
54
|
|
@@ -50,7 +50,9 @@ module BlockKit
|
|
50
50
|
fixes :close, truncate: {maximum: MAX_BUTTON_LENGTH}, null_value: {error_types: [:blank]}
|
51
51
|
|
52
52
|
validates :submit, presence: true, length: {maximum: MAX_BUTTON_LENGTH}, allow_nil: true
|
53
|
+
validate :submit_present_if_contains_input
|
53
54
|
fixes :submit, truncate: {maximum: MAX_BUTTON_LENGTH}, null_value: {error_types: [:blank]}
|
55
|
+
fix :add_default_submit_button
|
54
56
|
|
55
57
|
def initialize(attributes = {})
|
56
58
|
attributes = attributes.with_indifferent_access
|
@@ -69,6 +71,20 @@ module BlockKit
|
|
69
71
|
submit_disabled: submit_disabled
|
70
72
|
).compact
|
71
73
|
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def submit_present_if_contains_input
|
78
|
+
errors.add(:submit, "can't be blank when blocks contain input elements") if contains_input? && submit.blank?
|
79
|
+
end
|
80
|
+
|
81
|
+
def add_default_submit_button
|
82
|
+
self.submit = "Submit" if contains_input? && submit.blank?
|
83
|
+
end
|
84
|
+
|
85
|
+
def contains_input?
|
86
|
+
blocks.any? { |block| block.is_a?(Layout::Input) }
|
87
|
+
end
|
72
88
|
end
|
73
89
|
end
|
74
90
|
end
|
data/lib/block_kit/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: block-kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Celis
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-04-
|
10
|
+
date: 2025-04-24 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: activemodel
|
@@ -72,7 +72,6 @@ files:
|
|
72
72
|
- lib/block_kit/concerns/confirmable.rb
|
73
73
|
- lib/block_kit/concerns/conversation_selection.rb
|
74
74
|
- lib/block_kit/concerns/dispatchable.rb
|
75
|
-
- lib/block_kit/concerns/dsl_generation.rb
|
76
75
|
- lib/block_kit/concerns/external.rb
|
77
76
|
- lib/block_kit/concerns/focusable_on_load.rb
|
78
77
|
- lib/block_kit/concerns/has_initial_option.rb
|
@@ -1,76 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module BlockKit
|
4
|
-
module Concerns
|
5
|
-
module DSLGeneration
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
|
8
|
-
class_methods do
|
9
|
-
private
|
10
|
-
|
11
|
-
def dsl_method(attribute, as: nil, type: nil, required_fields: [], mutually_exclusive_fields: [], yields: true)
|
12
|
-
type ||= attribute_types[attribute.to_s]
|
13
|
-
type = Types::Generic.of_type(type) if type.is_a?(Class) && type < BlockKit::Base
|
14
|
-
raise ArgumentError, "attribute #{attribute} does not exist" if type.instance_of?(ActiveModel::Type::Value)
|
15
|
-
|
16
|
-
is_array_attribute = false
|
17
|
-
|
18
|
-
if type.instance_of?(Types::Array)
|
19
|
-
is_array_attribute = true
|
20
|
-
type = type.item_type
|
21
|
-
end
|
22
|
-
|
23
|
-
is_array_attribute ||= attribute_types[attribute.to_s].type == :array
|
24
|
-
|
25
|
-
fields = type.block_class.attribute_names.map(&:to_sym)
|
26
|
-
plain_text_fields = type.block_class.attribute_types.select { |_, v| v.respond_to?(:block_class) && v.block_class == Composition::PlainText }.keys.map(&:to_sym)
|
27
|
-
|
28
|
-
define_method(as || attribute) do |args = {}, &block|
|
29
|
-
args = args.symbolize_keys
|
30
|
-
|
31
|
-
# Return the existing attribute if no args or block are passed and we're not in a custom-named method
|
32
|
-
return super() if args.blank? && block.nil? && as.nil?
|
33
|
-
|
34
|
-
if (missing_required_fields = (required_fields - args.keys)) && missing_required_fields.any?
|
35
|
-
message = "missing keyword#{"s" if missing_required_fields.size > 1}: #{missing_required_fields.map(&:inspect).join(", ")}"
|
36
|
-
raise ArgumentError, message
|
37
|
-
end
|
38
|
-
|
39
|
-
unknown_fields = (args.keys - fields)
|
40
|
-
unknown_fields.delete(:emoji) if plain_text_fields.any?
|
41
|
-
|
42
|
-
if unknown_fields.any?
|
43
|
-
message = "unknown keyword#{"s" if unknown_fields.size > 1}: #{unknown_fields.map(&:inspect).join(", ")}"
|
44
|
-
raise ArgumentError, message
|
45
|
-
end
|
46
|
-
|
47
|
-
mutually_exclusive = mutually_exclusive_fields & args.keys
|
48
|
-
if mutually_exclusive.length > 1
|
49
|
-
message = "mutually exclusive keywords: #{mutually_exclusive.map(&:inspect).join(", ")}"
|
50
|
-
raise ArgumentError, message
|
51
|
-
end
|
52
|
-
|
53
|
-
new_value = if is_array_attribute
|
54
|
-
public_send(:"#{attribute}=", []) if public_send(attribute).nil?
|
55
|
-
public_send(attribute) << type.cast(args)
|
56
|
-
public_send(attribute).last
|
57
|
-
else
|
58
|
-
public_send(:"#{attribute}=", type.cast(args))
|
59
|
-
public_send(attribute)
|
60
|
-
end
|
61
|
-
|
62
|
-
plain_text_fields.each do |field|
|
63
|
-
next unless args.key?(field)
|
64
|
-
|
65
|
-
new_value.public_send(field).emoji = args[:emoji] if args.key?(:emoji)
|
66
|
-
end
|
67
|
-
|
68
|
-
block&.call(new_value) if yields
|
69
|
-
|
70
|
-
self
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|