glimmer-dsl-web 0.0.7 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -34,7 +34,6 @@ module Glimmer
34
34
  @selector = selector
35
35
  @listener = listener
36
36
  @js_listener = lambda do |js_event|
37
- # TODO wrap event with a Ruby Event object before passing to listener
38
37
  event = EventProxy.new(js_event: js_event, listener: self)
39
38
  result = listener.call(event)
40
39
  result = true if result.nil?
@@ -0,0 +1,223 @@
1
+ # Copyright (c) 2023-2024 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer-dsl-web'
23
+
24
+ Address = Struct.new(:full_name, :street, :street2, :city, :state, :zip_code, keyword_init: true) do
25
+ STATES = {
26
+ "AK"=>"Alaska",
27
+ "AL"=>"Alabama",
28
+ "AR"=>"Arkansas",
29
+ "AS"=>"American Samoa",
30
+ "AZ"=>"Arizona",
31
+ "CA"=>"California",
32
+ "CO"=>"Colorado",
33
+ "CT"=>"Connecticut",
34
+ "DC"=>"District of Columbia",
35
+ "DE"=>"Delaware",
36
+ "FL"=>"Florida",
37
+ "GA"=>"Georgia",
38
+ "GU"=>"Guam",
39
+ "HI"=>"Hawaii",
40
+ "IA"=>"Iowa",
41
+ "ID"=>"Idaho",
42
+ "IL"=>"Illinois",
43
+ "IN"=>"Indiana",
44
+ "KS"=>"Kansas",
45
+ "KY"=>"Kentucky",
46
+ "LA"=>"Louisiana",
47
+ "MA"=>"Massachusetts",
48
+ "MD"=>"Maryland",
49
+ "ME"=>"Maine",
50
+ "MI"=>"Michigan",
51
+ "MN"=>"Minnesota",
52
+ "MO"=>"Missouri",
53
+ "MS"=>"Mississippi",
54
+ "MT"=>"Montana",
55
+ "NC"=>"North Carolina",
56
+ "ND"=>"North Dakota",
57
+ "NE"=>"Nebraska",
58
+ "NH"=>"New Hampshire",
59
+ "NJ"=>"New Jersey",
60
+ "NM"=>"New Mexico",
61
+ "NV"=>"Nevada",
62
+ "NY"=>"New York",
63
+ "OH"=>"Ohio",
64
+ "OK"=>"Oklahoma",
65
+ "OR"=>"Oregon",
66
+ "PA"=>"Pennsylvania",
67
+ "PR"=>"Puerto Rico",
68
+ "RI"=>"Rhode Island",
69
+ "SC"=>"South Carolina",
70
+ "SD"=>"South Dakota",
71
+ "TN"=>"Tennessee",
72
+ "TX"=>"Texas",
73
+ "UT"=>"Utah",
74
+ "VA"=>"Virginia",
75
+ "VI"=>"Virgin Islands",
76
+ "VT"=>"Vermont",
77
+ "WA"=>"Washington",
78
+ "WI"=>"Wisconsin",
79
+ "WV"=>"West Virginia",
80
+ "WY"=>"Wyoming"
81
+ }
82
+
83
+ def state_code
84
+ STATES.invert[state]
85
+ end
86
+
87
+ def state_code=(value)
88
+ self.state = STATES[value]
89
+ end
90
+
91
+ def summary
92
+ to_h.values.map(&:to_s).reject(&:empty?).join(', ')
93
+ end
94
+ end
95
+
96
+ # AddressForm Glimmer Web Component (View component)
97
+ #
98
+ # Including Glimmer::Web::Component makes this class a View component and automatically
99
+ # generates a new Glimmer GUI DSL keyword that matches the lowercase underscored version
100
+ # of the name of the class. AddressForm generates address_form keyword, which can be used
101
+ # elsewhere in Glimmer GUI DSL code as done inside AddressPage below.
102
+ class AddressForm
103
+ include Glimmer::Web::Component
104
+
105
+ option :address
106
+
107
+ # Optionally, you can execute code before rendering markup.
108
+ # This is useful for pre-setup of variables (e.g. Models) that you would use in the markup.
109
+ #
110
+ # before_render do
111
+ # end
112
+
113
+ # Optionally, you can execute code after rendering markup.
114
+ # This is useful for post-setup of extra Model listeners that would interact with the
115
+ # markup elements and expect them to be rendered already.
116
+ #
117
+ # after_render do
118
+ # end
119
+
120
+ # markup block provides the content of the
121
+ markup {
122
+ div {
123
+ div(style: 'display: grid; grid-auto-columns: 80px 260px;') { |address_div|
124
+ label('Full Name: ', for: 'full-name-field')
125
+ input(id: 'full-name-field') {
126
+ value <=> [address, :full_name]
127
+ }
128
+
129
+ @somelabel = label('Street: ', for: 'street-field')
130
+ input(id: 'street-field') {
131
+ value <=> [address, :street]
132
+ }
133
+
134
+ label('Street 2: ', for: 'street2-field')
135
+ textarea(id: 'street2-field') {
136
+ value <=> [address, :street2]
137
+ }
138
+
139
+ label('City: ', for: 'city-field')
140
+ input(id: 'city-field') {
141
+ value <=> [address, :city]
142
+ }
143
+
144
+ label('State: ', for: 'state-field')
145
+ select(id: 'state-field') {
146
+ Address::STATES.each do |state_code, state|
147
+ option(value: state_code) { state }
148
+ end
149
+
150
+ value <=> [address, :state_code]
151
+ }
152
+
153
+ label('Zip Code: ', for: 'zip-code-field')
154
+ input(id: 'zip-code-field', type: 'number', min: '0', max: '99999') {
155
+ value <=> [address, :zip_code,
156
+ on_write: :to_s,
157
+ ]
158
+ }
159
+
160
+ style {
161
+ <<~CSS
162
+ #{address_div.selector} * {
163
+ margin: 5px;
164
+ }
165
+ #{address_div.selector} input, #{address_div.selector} select {
166
+ grid-column: 2;
167
+ }
168
+ CSS
169
+ }
170
+ }
171
+
172
+ div(style: 'margin: 5px') {
173
+ inner_text <= [address, :summary,
174
+ computed_by: address.members + ['state_code'],
175
+ ]
176
+ }
177
+ }
178
+ }
179
+ end
180
+
181
+ # AddressPage Glimmer Web Component (View component)
182
+ #
183
+ # This View component represents the main page being rendered,
184
+ # as done by its `render` class method below
185
+ class AddressPage
186
+ include Glimmer::Web::Component
187
+
188
+ before_render do
189
+ @shipping_address = Address.new(
190
+ full_name: 'Johnny Doe',
191
+ street: '3922 Park Ave',
192
+ street2: 'PO BOX 8382',
193
+ city: 'San Diego',
194
+ state: 'California',
195
+ zip_code: '91913',
196
+ )
197
+ @billing_address = Address.new(
198
+ full_name: 'John C Doe',
199
+ street: '123 Main St',
200
+ street2: 'Apartment 3C',
201
+ city: 'San Diego',
202
+ state: 'California',
203
+ zip_code: '91911',
204
+ )
205
+ end
206
+
207
+ markup {
208
+ div {
209
+ h1('Shipping Address')
210
+
211
+ address_form(address: @shipping_address)
212
+
213
+ h1('Billing Address')
214
+
215
+ address_form(address: @billing_address)
216
+ }
217
+ }
218
+ end
219
+
220
+ Document.ready? do
221
+ # renders a top-level (root) AddressPage component
222
+ AddressPage.render
223
+ end
@@ -0,0 +1,141 @@
1
+ # Copyright (c) 2023-2024 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer-dsl-web'
23
+
24
+ class Address
25
+ attr_accessor :text
26
+ attr_reader :name, :street, :city, :state, :zip
27
+
28
+ def name=(value)
29
+ @name = value
30
+ update_text
31
+ end
32
+
33
+ def street=(value)
34
+ @street = value
35
+ update_text
36
+ end
37
+
38
+ def city=(value)
39
+ @city = value
40
+ update_text
41
+ end
42
+
43
+ def state=(value)
44
+ @state = value
45
+ update_text
46
+ end
47
+
48
+ def zip=(value)
49
+ @zip = value
50
+ update_text
51
+ end
52
+
53
+ private
54
+
55
+ def update_text
56
+ self.text = [name, street, city, state, zip].compact.reject(&:empty?).join(', ')
57
+ end
58
+ end
59
+
60
+ class User
61
+ attr_accessor :addresses
62
+ attr_reader :address_count
63
+
64
+ def initialize
65
+ @address_count = 1
66
+ @addresses = []
67
+ update_addresses
68
+ end
69
+
70
+ def address_count=(value)
71
+ value = [[1, value.to_i].max, 3].min
72
+ @address_count = value
73
+ update_addresses
74
+ end
75
+
76
+ private
77
+
78
+ def update_addresses
79
+ address_count_change = address_count - addresses.size
80
+ if address_count_change > 0
81
+ address_count_change.times { addresses << Address.new }
82
+ else
83
+ address_count_change.abs.times { addresses.pop }
84
+ end
85
+ end
86
+ end
87
+
88
+ @user = User.new
89
+
90
+ include Glimmer
91
+
92
+ Document.ready? do
93
+ div {
94
+ div {
95
+ label('Number of addresses: ', for: 'address-count-field')
96
+ input(id: 'address-count-field', type: 'number', min: 1, max: 3) {
97
+ value <=> [@user, :address_count]
98
+ }
99
+ }
100
+
101
+ div {
102
+ # Content Data-Binding is used to dynamically (re)generate content of div
103
+ # based on changes to @user.addresses, replacing older content on every change
104
+ content(@user, :addresses) do
105
+ @user.addresses.each do |address|
106
+ div {
107
+ div(style: 'display: grid; grid-auto-columns: 80px 280px;') { |address_div|
108
+ [:name, :street, :city, :state, :zip].each do |attribute|
109
+ label(attribute.to_s.capitalize, for: "#{attribute}-field")
110
+ input(id: "#{attribute}-field", type: 'text') {
111
+ value <=> [address, attribute]
112
+ }
113
+ end
114
+
115
+ div(style: 'grid-column: 1 / span 2;') {
116
+ inner_text <= [address, :text]
117
+ }
118
+
119
+ style {
120
+ <<~CSS
121
+ #{address_div.selector} {
122
+ margin: 10px 0;
123
+ }
124
+ #{address_div.selector} * {
125
+ margin: 5px;
126
+ }
127
+ #{address_div.selector} label {
128
+ grid-column: 1;
129
+ }
130
+ #{address_div.selector} input, #{address_div.selector} select {
131
+ grid-column: 2;
132
+ }
133
+ CSS
134
+ }
135
+ }
136
+ }
137
+ end
138
+ end
139
+ }
140
+ }.render
141
+ end
@@ -26,7 +26,11 @@ GLIMMER_DSL_OPAL_LIB = File.join(GLIMMER_DSL_OPAL_ROOT, 'lib')
26
26
 
27
27
  $LOAD_PATH.unshift(GLIMMER_DSL_OPAL_LIB)
28
28
 
29
- if RUBY_ENGINE == 'opal'
29
+ if RUBY_ENGINE != 'opal'
30
+ require 'opal-rails'
31
+ require 'opal-async'
32
+ require 'opal-jquery'
33
+ else
30
34
  # GLIMMER_DSL_OPAL_MISSING = File.join(GLIMMER_DSL_OPAL_ROOT, 'lib', 'glimmer-dsl-opal', 'missing')
31
35
 
32
36
  # $LOAD_PATH.unshift(GLIMMER_DSL_OPAL_MISSING) # missing Ruby classes/methods
@@ -75,7 +79,7 @@ if RUBY_ENGINE == 'opal'
75
79
  require 'glimmer-dsl-xml'
76
80
  require 'glimmer-dsl-css'
77
81
 
78
- Glimmer::Config.loop_max_count = 150 # TODO consider disabling if preferred
82
+ Glimmer::Config.loop_max_count = 50 # TODO consider disabling if preferred
79
83
 
80
84
  original_logger_level = Glimmer::Config.logger.level
81
85
  Glimmer::Config.logger = Glimmer::Config::OpalLogger.new(STDOUT)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-dsl-web
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-02 00:00:00.000000000 Z
11
+ date: 2024-01-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 2.4.1
19
+ version: 2.7.6
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 2.4.1
26
+ version: 2.7.6
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: glimmer-dsl-xml
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +52,34 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 1.2.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: opal
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 1.4.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 1.4.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: opal-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 2.0.2
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 2.0.2
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: opal-async
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +94,20 @@ dependencies:
66
94
  - - "~>"
67
95
  - !ruby/object:Gem::Version
68
96
  version: 1.4.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: opal-jquery
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.4.6
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.4.6
69
111
  - !ruby/object:Gem::Dependency
70
112
  name: to_collection
71
113
  requirement: !ruby/object:Gem::Requirement
@@ -188,34 +230,6 @@ dependencies:
188
230
  - - "~>"
189
231
  - !ruby/object:Gem::Version
190
232
  version: 0.8.0.alpha2
191
- - !ruby/object:Gem::Dependency
192
- name: opal-rails
193
- requirement: !ruby/object:Gem::Requirement
194
- requirements:
195
- - - "~>"
196
- - !ruby/object:Gem::Version
197
- version: 1.1.2
198
- type: :development
199
- prerelease: false
200
- version_requirements: !ruby/object:Gem::Requirement
201
- requirements:
202
- - - "~>"
203
- - !ruby/object:Gem::Version
204
- version: 1.1.2
205
- - !ruby/object:Gem::Dependency
206
- name: opal-jquery
207
- requirement: !ruby/object:Gem::Requirement
208
- requirements:
209
- - - "~>"
210
- - !ruby/object:Gem::Version
211
- version: 0.4.4
212
- type: :development
213
- prerelease: false
214
- version_requirements: !ruby/object:Gem::Requirement
215
- requirements:
216
- - - "~>"
217
- - !ruby/object:Gem::Version
218
- version: 0.4.4
219
233
  description: Glimmer DSL for Web (Ruby in the Browser Web GUI Frontend Library) -
220
234
  Enables frontend GUI development with Ruby by adopting a DSL that follows web-like
221
235
  HTML syntax, enabling the transfer of HTML/CSS/JS skills to Ruby frontend development.
@@ -239,6 +253,8 @@ files:
239
253
  - lib/glimmer-dsl-web/ext/date.rb
240
254
  - lib/glimmer-dsl-web/ext/exception.rb
241
255
  - lib/glimmer-dsl-web/samples/hello/hello_button.rb
256
+ - lib/glimmer-dsl-web/samples/hello/hello_component.rb
257
+ - lib/glimmer-dsl-web/samples/hello/hello_content_data_binding.rb
242
258
  - lib/glimmer-dsl-web/samples/hello/hello_data_binding.rb
243
259
  - lib/glimmer-dsl-web/samples/hello/hello_form.rb
244
260
  - lib/glimmer-dsl-web/samples/hello/hello_input_date_time.rb
@@ -247,6 +263,8 @@ files:
247
263
  - lib/glimmer/config/opal_logger.rb
248
264
  - lib/glimmer/data_binding/element_binding.rb
249
265
  - lib/glimmer/dsl/web/bind_expression.rb
266
+ - lib/glimmer/dsl/web/component_expression.rb
267
+ - lib/glimmer/dsl/web/content_data_binding_expression.rb
250
268
  - lib/glimmer/dsl/web/data_binding_expression.rb
251
269
  - lib/glimmer/dsl/web/dsl.rb
252
270
  - lib/glimmer/dsl/web/element_expression.rb
@@ -258,6 +276,7 @@ files:
258
276
  - lib/glimmer/dsl/web/shine_data_binding_expression.rb
259
277
  - lib/glimmer/util/proc_tracker.rb
260
278
  - lib/glimmer/web.rb
279
+ - lib/glimmer/web/component.rb
261
280
  - lib/glimmer/web/element_proxy.rb
262
281
  - lib/glimmer/web/event_proxy.rb
263
282
  - lib/glimmer/web/listener_proxy.rb