line-message-builder 0.6.1 → 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.
@@ -3,31 +3,151 @@
3
3
  module Line
4
4
  module Message
5
5
  module Builder
6
- # The container class is main container to manage messages.
7
- class Container < Base
6
+ # The `Container` class is the top-level entry point for constructing a batch
7
+ # of LINE messages using the builder DSL. It acts as a holder for one or
8
+ # more individual message objects (such as {Text} or {Flex} messages).
9
+ #
10
+ # When you use `Line::Message::Builder.with {}`, you are operating within
11
+ # the context of a `Container` instance. This container allows you to define
12
+ # multiple messages that can be sent together in a single API call to LINE,
13
+ # although the LINE API typically expects an array of message objects,
14
+ # which this container helps to build.
15
+ #
16
+ # Each message added to the container can also have its own quick reply.
17
+ #
18
+ # @example Building multiple messages
19
+ # message_payload = Line::Message::Builder.with do |root|
20
+ # root.text "Hello, this is the first message!"
21
+ # root.flex alt_text: "This is a Flex Message" do |flex_builder|
22
+ # flex_builder.bubble do |bubble|
23
+ # bubble.body do |body|
24
+ # body.text "This is a Flex Message body."
25
+ # end
26
+ # end
27
+ # end
28
+ # end.build # => Returns an array of message hashes
29
+ #
30
+ # @see Base
31
+ # @see Text
32
+ # @see Flex::Builder
33
+ # @see QuickReply
34
+ class Container
35
+ # @!attribute [r] context
36
+ # @return [Context] The context object, which can hold external data or
37
+ # helper methods accessible within the builder blocks.
8
38
  attr_reader :context
9
39
 
10
- def initialize(context: nil, &)
11
- @messages = []
40
+ # Initializes a new message container.
41
+ # This is typically not called directly but through `Line::Message::Builder.with`.
42
+ # The provided block is instance-eval'd, allowing DSL methods like
43
+ # {#text} and {#flex} to be called directly on the container instance.
44
+ #
45
+ # @param context [Object, nil] An optional context object that can be used
46
+ # to share data or helper methods within the builder block. It's wrapped
47
+ # in a {Context} object.
48
+ # @param mode [Symbol] The mode to use for building messages. Can be either
49
+ # `:api` (default) for direct LINE Messaging API format or `:sdkv2` for
50
+ # LINE Bot SDK v2 compatible format.
51
+ # @param block [Proc] A block containing DSL calls to define messages
52
+ # (e.g., `text "Hello"`, `flex { ... }`).
53
+ def initialize(context: nil, mode: :api, &block)
54
+ @messages = [] # Initializes an empty array to store message objects
55
+ @context = Context.new(context, mode:)
12
56
 
13
- super
57
+ instance_eval(&block) if ::Kernel.block_given?
14
58
  end
15
59
 
60
+ # Creates a new {Text} message and adds it to this container.
61
+ #
62
+ # @param text [String] The text content of the message.
63
+ # @param options [Hash] Additional options for the text message,
64
+ # such as `:quick_reply`. See {Text#initialize}.
65
+ # @param block [Proc, nil] An optional block that will be instance-eval'd
66
+ # in the context of the new {Text} message instance. This can be used
67
+ # to add a quick reply to the text message.
68
+ # @return [Text] The newly created {Text} message object.
69
+ #
70
+ # @example
71
+ # root.text "Hello, world!" do
72
+ # quick_reply do
73
+ # button action: :message, label: "Hi!", text: "Hi!"
74
+ # end
75
+ # end
16
76
  def text(text, **options, &)
17
77
  @messages << Text.new(text, context: context, **options, &)
18
78
  end
19
79
 
80
+ # Creates a new {Flex::Builder} for constructing a Flex Message and adds it
81
+ # to this container. The block is mandatory and is used to define the
82
+ # content of the Flex Message using the Flex Message DSL.
83
+ #
84
+ # @param options [Hash] Options for the Flex Message, primarily `:alt_text`.
85
+ # See {Flex::Builder#initialize}. It's important to provide `alt_text`.
86
+ # @param block [Proc] A block that will be instance-eval'd in the context
87
+ # of the new {Flex::Builder} instance. This block is used to define the
88
+ # structure and content of the Flex Message (e.g., bubbles, carousels).
89
+ # @return [Flex::Builder] The newly created {Flex::Builder} object.
90
+ # @raise [ArgumentError] if `alt_text` is not provided in options (validation
91
+ # is typically within Flex::Builder).
92
+ #
93
+ # @example
94
+ # root.flex alt_text: "Important information" do |fb|
95
+ # fb.bubble do |bubble|
96
+ # bubble.header { |h| h.text "Header" }
97
+ # bubble.body { |b| b.text "Body" }
98
+ # end
99
+ # end
20
100
  def flex(**options, &)
21
101
  @messages << Flex::Builder.new(context: context, **options, &)
22
102
  end
23
103
 
104
+ # Converts all messages held by this container into their hash representations.
105
+ # This method iterates over each message object (e.g., {Text}, {Flex::Builder})
106
+ # stored in the container and calls its `to_h` method. The result is an
107
+ # array of hashes, where each hash represents a single LINE message object
108
+ # ready for JSON serialization and sending to the LINE Messaging API.
109
+ #
110
+ # @return [Array<Hash>] An array of message objects, each represented as a hash.
111
+ # This is the format expected by the LINE API for the `messages` field
112
+ # in a request body.
24
113
  def build
25
114
  @messages.map(&:to_h)
26
115
  end
27
116
 
117
+ # Converts the array of message hashes (obtained from {#build}) into a
118
+ # JSON string. This is a convenience method for serializing the messages
119
+ # payload.
120
+ #
121
+ # @param args [Object] Optional arguments that are passed along to `to_json`
122
+ # method of the underlying array.
123
+ # @return [String] A JSON string representing the array of message objects.
28
124
  def to_json(*args)
29
125
  build.to_json(*args)
30
126
  end
127
+
128
+ # Checks if a method is defined in the context object.
129
+ # This is part of Ruby's method_missing mechanism.
130
+ #
131
+ # @param method_name [Symbol] The name of the method being checked
132
+ # @param include_private [Boolean] Whether to include private methods
133
+ # @return [Boolean] True if the method exists in the context, false otherwise
134
+ def respond_to_missing?(method_name, include_private = false)
135
+ context.respond_to?(method_name, include_private) || super
136
+ end
137
+
138
+ # Delegates method calls to the context object if they exist there.
139
+ # This allows helper methods defined in the context to be called directly
140
+ # from within the builder DSL.
141
+ #
142
+ # @param method_name [Symbol] The name of the method being called
143
+ # @param args [Array] The arguments passed to the method
144
+ # @return [Object] The result of calling the method on the context
145
+ # @raise [NoMethodError] If the method doesn't exist in the context
146
+ def method_missing(method_name, ...)
147
+ return context.send(method_name, ...) if context.respond_to?(method_name)
148
+
149
+ super
150
+ end
31
151
  end
32
152
  end
33
153
  end
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Line
4
+ module Message
5
+ module Builder
6
+ # The `Context` class is a crucial component of the `Line::Message::Builder`
7
+ # DSL, enabling a flexible and dynamic environment for message construction.
8
+ # It acts as a wrapper around an optional user-provided context object and
9
+ # manages a separate hash of "assigns" (local variables for the DSL).
10
+ #
11
+ # The primary purposes of the `Context` are:
12
+ # 1. **To provide access to helper methods**: If a user passes a context object
13
+ # (e.g., a Rails view context, a presenter, or any custom object) during
14
+ # builder initialization (`Line::Message::Builder.with(my_helper_object)`),
15
+ # methods defined on `my_helper_object` become directly callable within
16
+ # the DSL blocks.
17
+ # 2. **To allow local data storage (`assigns`)**: The `assigns` hash allows
18
+ # for setting and retrieving temporary data that can be shared across
19
+ # different parts of a complex message construction block, without needing
20
+ # to pass it explicitly or pollute the user-provided context.
21
+ #
22
+ # Method calls within the DSL that are not defined on the builder objects
23
+ # themselves are resolved by `Context` in the following order:
24
+ # - First, it checks if the method name corresponds to a key in the `assigns` hash.
25
+ # - If not found in `assigns`, it checks if the wrapped user-context object
26
+ # responds to the method.
27
+ # - If neither, the call proceeds up the normal Ruby method lookup chain.
28
+ #
29
+ # This mechanism allows for a clean and powerful way to integrate external logic
30
+ # and data into the message building process.
31
+ #
32
+ # @example Using a custom context
33
+ # class MyHelpers
34
+ # def current_user_name
35
+ # "Alice"
36
+ # end
37
+ # end
38
+ #
39
+ # helpers = MyHelpers.new
40
+ # Line::Message::Builder.with(helpers) do |root|
41
+ # # `current_user_name` is resolved from `helpers` by Context
42
+ # root.text "Hello, #{current_user_name}!"
43
+ #
44
+ # # Using assigns
45
+ # assigns[:item_count] = 5
46
+ # root.text "You have #{assigns[:item_count]} items."
47
+ # end
48
+ class Context
49
+ # @!attribute assigns
50
+ # A hash for storing arbitrary data that can be accessed within the
51
+ # builder DSL. This is useful for temporary variables or shared state
52
+ # during message construction.
53
+ # @return [Hash] The hash of assigned values.
54
+ # @example
55
+ # context.assigns[:user_id] = 123
56
+ # puts context.assigns[:user_id] # => 123
57
+ attr_accessor :assigns
58
+
59
+ # @!attribute [r] mode
60
+ # The mode in which the builder is operating. This affects how messages
61
+ # are formatted in the final output.
62
+ # @return [Symbol] Either `:api` for direct LINE Messaging API format
63
+ # or `:sdkv2` for LINE Bot SDK v2 compatible format.
64
+ attr_reader :mode
65
+
66
+ # Initializes a new Context object.
67
+ #
68
+ # @param context [Object, nil] An optional object whose methods will be made
69
+ # available within the DSL. If `nil`, only `assigns` and standard
70
+ # builder methods will be available.
71
+ # @param mode [Symbol] The mode of the context, which can be `:api` (default)
72
+ # for direct LINE Messaging API format or `:sdkv2` for LINE Bot SDK v2
73
+ # compatible format.
74
+ def initialize(context, mode: :api)
75
+ @context = context
76
+ @assigns = {}
77
+ @mode = mode
78
+ end
79
+
80
+ # Part of Ruby's dynamic method dispatch. It's overridden here to declare
81
+ # that instances of `Context` can respond to methods that are either:
82
+ # 1. Keys in the `@assigns` hash.
83
+ # 2. Methods to which the wrapped `@context` object responds.
84
+ #
85
+ # This ensures that `respond_to?` behaves consistently with how
86
+ # `method_missing` resolves method calls.
87
+ #
88
+ # @param method_name [Symbol] The name of the method being queried.
89
+ # @param include_private [Boolean] Whether to include private methods in
90
+ # the check.
91
+ # @return [Boolean] `true` if the context can handle the method,
92
+ # `false` otherwise.
93
+ # @!visibility private
94
+ def respond_to_missing?(method_name, include_private = false)
95
+ @assigns.key?(method_name) ||
96
+ @context.respond_to?(method_name, include_private) || # Check @context directly
97
+ super
98
+ end
99
+
100
+ # Handles calls to methods not explicitly defined on the `Context` class.
101
+ # The resolution order is:
102
+ # 1. If `method_name` is a key in the `@assigns` hash, its value is returned.
103
+ # 2. If the wrapped `@context` object responds to `method_name`, the call
104
+ # is delegated to `@context`.
105
+ # 3. Otherwise, `super` is called, allowing the standard Ruby method
106
+ # lookup to continue (which will likely result in a `NoMethodError`
107
+ # if the method is truly undefined).
108
+ #
109
+ # This is the core mechanism that allows DSL blocks to seamlessly access
110
+ # data from `assigns` or methods from the user-provided context.
111
+ #
112
+ # @param method_name [Symbol] The name of the invoked method.
113
+ # @param ... [Object] Arguments passed to the method.
114
+ # @return [Object, nil] The value from `@assigns`, the result of the
115
+ # delegated call to `@context`, or raises `NoMethodError` via `super`.
116
+ # @raise [NoMethodError] If the method is not found in `assigns` or
117
+ # on the wrapped context.
118
+ # @!visibility private
119
+ def method_missing(method_name, ...)
120
+ return @assigns[method_name] if @assigns.key?(method_name)
121
+ # Check @context directly
122
+ return @context.public_send(method_name, ...) if @context.respond_to?(method_name)
123
+
124
+ super
125
+ end
126
+
127
+ # Checks if the current mode is set to SDK v2 compatibility.
128
+ #
129
+ # @return [Boolean] `true` if the mode is `:sdkv2`, `false` otherwise.
130
+ # @example
131
+ # if context.sdkv2?
132
+ # # Format message for LINE Bot SDK v2
133
+ # else
134
+ # # Format message for direct API use
135
+ # end
136
+ def sdkv2?
137
+ mode == :sdkv2
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -4,16 +4,61 @@ module Line
4
4
  module Message
5
5
  module Builder
6
6
  module Flex
7
- # The action DSL for flex components.
7
+ # The `Actionable` module provides a DSL for defining an action that can be
8
+ # triggered when a user interacts with certain Flex Message components
9
+ # (e.g., a {Button} component, or an entire {Bubble} or {Box} component
10
+ # if it's made tappable).
11
+ #
12
+ # When a component includes this module, it gains methods like {#message}
13
+ # and {#postback} to associate a specific LINE action with itself. The
14
+ # chosen action is stored in the `action` attribute.
15
+ #
16
+ # @!attribute [r] action
17
+ # @return [Actions::Message, Actions::Postback, nil] The action object
18
+ # associated with this component. `nil` if no action is defined.
19
+ #
20
+ # @see Line::Message::Builder::Actions::Message
21
+ # @see Line::Message::Builder::Actions::Postback
22
+ # @see https://developers.line.biz/en/reference/messaging-api/#action-objects
8
23
  module Actionable
24
+ # @!visibility private
25
+ # Automatically adds an `attr_reader :action` to the class that includes
26
+ # this module.
27
+ # @param base [Class] The class including this module.
9
28
  def self.included(base)
10
29
  base.attr_reader :action
11
30
  end
12
31
 
32
+ # Defines a message action for the component.
33
+ # When the component is tapped, a message with the given `text` is sent
34
+ # from the user to the chat.
35
+ #
36
+ # @param text [String] The text of the message to send.
37
+ # @param options [Hash] Additional options for the message action,
38
+ # such as `:label`. See {Actions::Message#initialize}.
39
+ # @param block [Proc, nil] An optional block, though not typically used
40
+ # directly for message actions here.
41
+ # @return [Actions::Message] The created message action object.
42
+ #
43
+ # @example Setting a message action on a button
44
+ # button_component.message "Hello User!", label: "Send Greeting"
13
45
  def message(text, **options, &)
14
46
  @action = Actions::Message.new(text, context: context, **options, &)
15
47
  end
16
48
 
49
+ # Defines a postback action for the component.
50
+ # When the component is tapped, a postback event with the given `data`
51
+ # is sent to the bot's webhook.
52
+ #
53
+ # @param data [String] The data payload for the postback event.
54
+ # @param options [Hash] Additional options for the postback action,
55
+ # such as `:label` or `:display_text`. See {Actions::Postback#initialize}.
56
+ # @param block [Proc, nil] An optional block, though not typically used
57
+ # directly for postback actions here.
58
+ # @return [Actions::Postback] The created postback action object.
59
+ #
60
+ # @example Setting a postback action on a button
61
+ # button_component.postback "action=buy&item_id=123", label: "Buy Item"
17
62
  def postback(data, **options, &)
18
63
  @action = Actions::Postback.new(data, context: context, **options, &)
19
64
  end
@@ -4,65 +4,182 @@ module Line
4
4
  module Message
5
5
  module Builder
6
6
  module Flex
7
- # The box is a component for the Flex message.
7
+ # Represents a "box" component in a LINE Flex Message.
8
+ #
9
+ # A box is a fundamental layout container that arranges its child components
10
+ # (`contents`) in a specified direction (`layout`: horizontal, vertical, or
11
+ # baseline). It can hold various other components like text, images, buttons,
12
+ # or even nested boxes, allowing for complex layouts.
13
+ #
14
+ # Boxes have numerous properties to control their appearance and the
15
+ # arrangement of their children, such as padding, margin, spacing between
16
+ # items, justification, and alignment.
17
+ #
18
+ # A box can also have an `action` associated with it, making the entire
19
+ # box area tappable.
20
+ #
21
+ # @example Creating a horizontal box with two text components
22
+ # Line::Message::Builder.with do |root|
23
+ # root.flex alt_text: "Box example" do |flex|
24
+ # flex.bubble do |bubble|
25
+ # bubble.body do |body_box| # body_box is an instance of Flex::Box
26
+ # body_box.layout :horizontal
27
+ # body_box.spacing :md
28
+ # body_box.text "Item 1"
29
+ # body_box.text "Item 2"
30
+ # end
31
+ # end
32
+ # end
33
+ # end
34
+ #
35
+ # @see https://developers.line.biz/en/reference/messaging-api/#box
36
+ # @see Actionable For making the box tappable.
37
+ # @see HasPartial For including reusable component groups.
38
+ # @see Position::Padding For padding properties.
39
+ # @see Position::Margin For margin properties.
40
+ # @see Position::Offset For offset properties.
41
+ # @see Size::Flex For flex sizing property.
8
42
  class Box < Line::Message::Builder::Base
9
- include Actionable
10
- include Position::Padding
11
- include Position::Margin
12
- include Position::Offset
13
- include Size::Flex
43
+ include HasPartial # Allows including predefined partial component sets.
44
+ include Actionable # Enables defining an action for the entire box.
45
+ include Position::Padding # Adds padding options like `padding_all`, `padding_top`, etc.
46
+ include Position::Margin # Adds `margin` option.
47
+ include Position::Offset # Adds offset options like `offset_top`, `offset_start`, etc.
48
+ include Size::Flex # Adds `flex` option for controlling size within a parent box.
14
49
 
50
+ # @!attribute [r] contents
51
+ # @return [Array<Base>] An array holding the child components (e.g.,
52
+ # {Text}, {Image}, nested {Box} instances) of this box.
15
53
  attr_reader :contents
16
54
 
55
+ # Specifies the arrangement of child components.
56
+ # @!method layout(value)
57
+ # @param value [Symbol] `:horizontal` (default), `:vertical`, or `:baseline`.
58
+ # @return [Symbol] The current layout.
17
59
  option :layout, default: :horizontal, validator: Validators::Enum.new(
18
60
  :horizontal, :vertical, :baseline
19
61
  )
62
+
63
+ # Horizontal alignment of content in a horizontal box; vertical alignment in a vertical box.
64
+ # @!method justify_content(value)
65
+ # @param value [Symbol, nil] E.g., `:flex_start`, `:center`, `:flex_end`,
66
+ # `:space_between`, `:space_around`, `:space_evenly`.
67
+ # @return [Symbol, nil] The current justify_content value.
20
68
  option :justify_content, default: nil, validator: Validators::Enum.new(
21
69
  :flex_start, :center, :flex_end, :space_between, :space_around, :space_evenly
22
70
  )
71
+
72
+ # Vertical alignment of content in a horizontal box; horizontal alignment in a vertical box.
73
+ # @!method align_items(value)
74
+ # @param value [Symbol, nil] E.g., `:flex_start`, `:center`, `:flex_end`.
75
+ # @return [Symbol, nil] The current align_items value.
23
76
  option :align_items, default: nil, validator: Validators::Enum.new(
24
77
  :flex_start, :center, :flex_end
25
78
  )
79
+
80
+ # Specifies the minimum spacing between components.
81
+ # Not applicable if `layout` is `:baseline` or if the box contains only one component.
82
+ # @!method spacing(value)
83
+ # @param value [String, Symbol, nil] E.g., `"md"`, `:lg`, `"10px"`.
84
+ # Keywords: `:none`, `:xs`, `:sm`, `:md`, `:lg`, `:xl`, `:xxl`.
85
+ # @return [String, Symbol, nil] The current spacing value.
26
86
  option :spacing, default: nil, validator: Validators::Size.new(:pixel, :keyword)
87
+
88
+ # Width of the box. Can be a percentage or pixel value.
89
+ # @!method width(value)
90
+ # @param value [String, nil] E.g., `"100px"`, `"50%"`.
91
+ # @return [String, nil] The current width.
27
92
  option :width, default: nil, validator: Validators::Size.new(:pixel, :percentage)
93
+
94
+ # Maximum width of the box.
95
+ # @!method max_width(value)
96
+ # @param value [String, nil] E.g., `"100px"`, `"50%"`.
97
+ # @return [String, nil] The current maximum width.
28
98
  option :max_width, default: nil, validator: Validators::Size.new(:pixel, :percentage)
99
+
100
+ # Height of the box.
101
+ # @!method height(value)
102
+ # @param value [String, nil] E.g., `"100px"`, `"50%"`.
103
+ # @return [String, nil] The current height.
29
104
  option :height, default: nil, validator: Validators::Size.new(:pixel, :percentage)
105
+
106
+ # Maximum height of the box.
107
+ # @!method max_height(value)
108
+ # @param value [String, nil] E.g., `"100px"`, `"50%"`.
109
+ # @return [String, nil] The current maximum height.
30
110
  option :max_height, default: nil, validator: Validators::Size.new(:pixel, :percentage)
31
111
 
112
+ # Initializes a new Flex Message Box component.
113
+ # The provided block is instance-eval'd, allowing DSL methods for adding
114
+ # child components (e.g., {#text}, {#button}, nested {#box}) to be called.
115
+ #
116
+ # @param context [Object, nil] An optional context for the builder.
117
+ # @param options [Hash] A hash of options to set instance variables.
118
+ # Corresponds to the `option` definitions in this class and included modules.
119
+ # @param block [Proc, nil] A block to define the contents of this box.
32
120
  def initialize(context: nil, **options, &)
33
- @contents = []
34
-
35
- super
121
+ @contents = [] # Holds child components
122
+ super # Calls Base#initialize, sets options, and evals block
36
123
  end
37
124
 
125
+ # Adds a nested Flex {Box} component to this box's contents.
126
+ #
127
+ # @param options [Hash] Options for the nested box. See {Box#initialize}.
128
+ # @param block [Proc] A block to define the contents of the nested box.
129
+ # @return [Flex::Box] The newly created nested Box object.
38
130
  def box(**options, &)
39
131
  @contents << Flex::Box.new(context: context, **options, &)
40
132
  end
41
133
 
134
+ # Adds a Flex {Text} component to this box's contents.
135
+ #
136
+ # @param text [String] The text content.
137
+ # @param options [Hash] Options for the text component. See {Text#initialize}.
138
+ # @param block [Proc, nil] An optional block for the text component (e.g., for an action).
139
+ # @return [Flex::Text] The newly created Text object.
42
140
  def text(text, **options, &)
43
141
  @contents << Flex::Text.new(text, context: context, **options, &)
44
142
  end
45
143
 
144
+ # Adds a Flex {Button} component to this box's contents.
145
+ #
146
+ # @param options [Hash] Options for the button component. See {Button#initialize}.
147
+ # @param block [Proc] A block to define the button's action and properties.
148
+ # @return [Flex::Button] The newly created Button object.
46
149
  def button(**options, &)
47
150
  @contents << Flex::Button.new(context: context, **options, &)
48
151
  end
49
152
 
153
+ # Adds a Flex {Image} component to this box's contents.
154
+ #
155
+ # @param url [String] The URL of the image.
156
+ # @param options [Hash] Options for the image component. See {Image#initialize}.
157
+ # @param block [Proc, nil] An optional block for the image component (e.g., for an action).
158
+ # @return [Flex::Image] The newly created Image object.
50
159
  def image(url, **options, &)
51
160
  @contents << Flex::Image.new(url, context: context, **options, &)
52
161
  end
53
162
 
54
- def to_h # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
163
+ def to_h
55
164
  raise RequiredError, "layout is required" if layout.nil?
56
165
 
166
+ return to_sdkv2 if context.sdkv2?
167
+
168
+ to_api
169
+ end
170
+
171
+ private
172
+
173
+ def to_api # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
57
174
  {
58
175
  type: "box",
59
176
  layout: layout,
60
- # Position
177
+ # Position & Layout
61
178
  justifyContent: justify_content,
62
179
  alignItems: align_items,
63
180
  spacing: spacing,
64
181
  # Position::Padding
65
- paddingAll: padding,
182
+ paddingAll: padding || padding_all,
66
183
  paddingTop: padding_top,
67
184
  paddingBottom: padding_bottom,
68
185
  paddingStart: padding_start,
@@ -82,8 +199,44 @@ module Line
82
199
  maxHeight: max_height,
83
200
  # Size::Flex
84
201
  flex: flex,
202
+ # Contents & Action
203
+ contents: contents.map(&:to_h),
204
+ action: action&.to_h # From Actionable module
205
+ }.compact
206
+ end
207
+
208
+ def to_sdkv2 # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
209
+ {
210
+ type: "box",
211
+ layout: layout,
212
+ # Position & Layout
213
+ justify_content: justify_content,
214
+ align_items: align_items,
215
+ spacing: spacing,
216
+ # Position::Padding
217
+ padding_all: padding || padding_all,
218
+ padding_top: padding_top,
219
+ padding_bottom: padding_bottom,
220
+ padding_start: padding_start,
221
+ padding_end: padding_end,
222
+ # Position::Margin
223
+ margin: margin,
224
+ # Position::Offset
225
+ position: position,
226
+ offset_top: offset_top,
227
+ offset_bottom: offset_bottom,
228
+ offset_start: offset_start,
229
+ offset_end: offset_end,
230
+ # Size
231
+ width: width,
232
+ max_width: max_width,
233
+ height: height,
234
+ max_height: max_height,
235
+ # Size::Flex
236
+ flex: flex,
237
+ # Contents & Action
85
238
  contents: contents.map(&:to_h),
86
- action: action&.to_h
239
+ action: action&.to_h # From Actionable module
87
240
  }.compact
88
241
  end
89
242
  end