isomorfeus-preact 10.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +62 -0
  3. data/lib/browser/delegate_native.rb +70 -0
  4. data/lib/browser/element.rb +176 -0
  5. data/lib/browser/element/canvas.rb +17 -0
  6. data/lib/browser/element/media.rb +78 -0
  7. data/lib/browser/event.rb +92 -0
  8. data/lib/browser/event_target.rb +39 -0
  9. data/lib/browser/file_list.rb +125 -0
  10. data/lib/browser/iterable.rb +15 -0
  11. data/lib/isomorfeus-preact.rb +109 -0
  12. data/lib/isomorfeus/preact/config.rb +189 -0
  13. data/lib/isomorfeus/preact/memcached_component_cache.rb +19 -0
  14. data/lib/isomorfeus/preact/redis_component_cache.rb +19 -0
  15. data/lib/isomorfeus/preact/thread_local_component_cache.rb +17 -0
  16. data/lib/isomorfeus/preact_view_helper.rb +188 -0
  17. data/lib/isomorfeus/props/validate_hash_proxy.rb +186 -0
  18. data/lib/isomorfeus/props/validator.rb +159 -0
  19. data/lib/isomorfeus/top_level.rb +101 -0
  20. data/lib/isomorfeus/top_level_ssr.rb +27 -0
  21. data/lib/isomorfeus_preact/lucid_app/api.rb +22 -0
  22. data/lib/isomorfeus_preact/lucid_app/base.rb +7 -0
  23. data/lib/isomorfeus_preact/lucid_app/mixin.rb +16 -0
  24. data/lib/isomorfeus_preact/lucid_app/native_component_constructor.rb +91 -0
  25. data/lib/isomorfeus_preact/lucid_component/api.rb +68 -0
  26. data/lib/isomorfeus_preact/lucid_component/app_store_proxy.rb +37 -0
  27. data/lib/isomorfeus_preact/lucid_component/base.rb +7 -0
  28. data/lib/isomorfeus_preact/lucid_component/class_store_proxy.rb +44 -0
  29. data/lib/isomorfeus_preact/lucid_component/initializer.rb +14 -0
  30. data/lib/isomorfeus_preact/lucid_component/instance_store_proxy.rb +44 -0
  31. data/lib/isomorfeus_preact/lucid_component/mixin.rb +15 -0
  32. data/lib/isomorfeus_preact/lucid_component/native_component_constructor.rb +84 -0
  33. data/lib/isomorfeus_preact/lucid_component/styles_api.rb +31 -0
  34. data/lib/isomorfeus_preact/lucid_component/styles_wrapper.rb +40 -0
  35. data/lib/isomorfeus_preact/lucid_func/base.rb +7 -0
  36. data/lib/isomorfeus_preact/lucid_func/initializer.rb +11 -0
  37. data/lib/isomorfeus_preact/lucid_func/mixin.rb +12 -0
  38. data/lib/isomorfeus_preact/lucid_func/native_component_constructor.rb +55 -0
  39. data/lib/isomorfeus_preact/preact/function_component/api.rb +123 -0
  40. data/lib/isomorfeus_preact/preact/function_component/base.rb +9 -0
  41. data/lib/isomorfeus_preact/preact/function_component/initializer.rb +10 -0
  42. data/lib/isomorfeus_preact/preact/function_component/mixin.rb +12 -0
  43. data/lib/isomorfeus_preact/preact/function_component/native_component_constructor.rb +48 -0
  44. data/lib/lucid_app/context.rb +24 -0
  45. data/lib/lucid_prop_declaration/mixin.rb +126 -0
  46. data/lib/preact.rb +309 -0
  47. data/lib/preact/component/api.rb +124 -0
  48. data/lib/preact/component/base.rb +9 -0
  49. data/lib/preact/component/callbacks.rb +102 -0
  50. data/lib/preact/component/elements.rb +64 -0
  51. data/lib/preact/component/initializer.rb +11 -0
  52. data/lib/preact/component/mixin.rb +15 -0
  53. data/lib/preact/component/native_component_constructor.rb +65 -0
  54. data/lib/preact/component/params.rb +18 -0
  55. data/lib/preact/component/props.rb +55 -0
  56. data/lib/preact/component/resolution.rb +97 -0
  57. data/lib/preact/component/state.rb +58 -0
  58. data/lib/preact/context_wrapper.rb +46 -0
  59. data/lib/preact/native_constant_wrapper.rb +29 -0
  60. data/lib/preact/options.rb +98 -0
  61. data/lib/preact/ref.rb +17 -0
  62. data/lib/preact/version.rb +3 -0
  63. metadata +301 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 13b90ee4e21a35010f09bd42df69605cf21b69711e4ed3bca34491bfbd4b5f7e
4
+ data.tar.gz: fcf859d2ce2b23fc7e13a1b5683abf518b76c7dcc6ad0e851f7211c734488cc6
5
+ SHA512:
6
+ metadata.gz: cee323f1256c8e6f33602f67f458f3eb19ffe258bb1f347aabbc149ef7616fa4461dfd6e2145a15a07654c000145cca09b0c24b1cf541a0463adeb3c06b234e5
7
+ data.tar.gz: fab521f06e5c088906957790849881a094323b3dda84581d5679b871fd4fa4bd549851409b4df28979ecc12f86d400d278cad30436ebbc5185e8a50774ddbb2b
data/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # isomorfeus-preact
2
+
3
+ Develop React components for Opal Ruby along with very easy to use and advanced React-Redux Components.
4
+
5
+ ## Community and Support
6
+ At the [Isomorfeus Framework Project](http://isomorfeus.com)
7
+
8
+ ## Versioning and Compatibility
9
+ isomorfeus-preact version follows the React version which features and API it implements.
10
+
11
+ ### React
12
+ Isomorfeus-preact 10.5.x implements features and the API of Preact 10.5.y and should be used with Preact 10.5.y
13
+
14
+ ## Documentation
15
+
16
+ - [Installation](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/installation.md)
17
+
18
+ Because isomorfeus-preact follows closely the Preact principles/implementation/API and Documentation, most things of the official Preact documentation
19
+ apply, but in the Ruby way, see:
20
+ - [https://preactjs.com/guide/v10/getting-started](https://preactjs.com/guide/v10/getting-started)
21
+
22
+ Component Types:
23
+ - [Class Component](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/class_component.md)
24
+ - [Function and Memo Component](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/function_component.md)
25
+ - [Lucid App, Lucid Component](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/lucid_component.md)
26
+ - [Lucid Func (for use with Hooks)](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/lucid_func_component.md)
27
+ - [React Javascript Components and React Elements](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/javascript_component.md)
28
+
29
+ Which component to use?
30
+ - Usually LucidApp and LucidComponent along with some imported javascript components.
31
+ - For MaterialUI LucidMaterial::App and LucidMaterial::Component along with some imported javascript components.
32
+
33
+ Specific to Class, Lucid and LucidMaterial Components:
34
+ - [Events](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/events.md)
35
+ - [Lifecycle Callbacks](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/lifecycle_callbacks.md)
36
+ - [Props](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/props.md)
37
+ - [State](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/state.md)
38
+
39
+ For all Components:
40
+ - [Accessibility](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/accessibility.md)
41
+ - [Render Blocks](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/render_blocks.md)
42
+ - [Rendering HTML or SVG Elements](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/rendering_elements.md)
43
+
44
+ Special React Features:
45
+ - [Context](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/context.md)
46
+ - [Fragments](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/fragments.md)
47
+ - [Refs](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/refs.md)
48
+
49
+ Other Features:
50
+ - [Hot Module Reloading](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/hot_module_relaoding.md)
51
+ - [Server Side Rendering](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/server_side_rendering.md)
52
+ - [Using Wouter as Router](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/wouter.md)
53
+ - [Isomorfeus Helpers](https://github.com/isomorfeus/isomorfeus-preact/blob/master/ruby/docs/isomorfeus_helpers.md)
54
+
55
+ ### Development Tools
56
+ The Preact Devtools allow for analyzing, debugging and profiling components. A very helpful toolset and working very nice with isomorfeus-preact:
57
+ [https://preactjs.github.io/preact-devtools/](https://preactjs.github.io/preact-devtools/)
58
+
59
+ ### Specs and Benchmarks
60
+ - clone repo
61
+ - `bundle install`
62
+ - `rake`
@@ -0,0 +1,70 @@
1
+ module Browser
2
+ module DelegateNative
3
+ # Provides a default initializer. This should be overridden in all but the
4
+ # simplest cases.
5
+ def initialize native
6
+ @native = native
7
+ end
8
+
9
+ # Fall back to native properties. If the message sent to this element is not
10
+ # recognized, it checks to see if it is a property of the native element. It
11
+ # also checks for variations of the message name, such as:
12
+ #
13
+ # :supported? => [:supported, :isSupported]
14
+ #
15
+ # If a property with the specified message name is found and it is a
16
+ # function, that function is invoked with `args`. Otherwise, the property
17
+ # is returned as is.
18
+ def method_missing message, *args, &block
19
+ property_name = property_for_message(message)
20
+ property = `#@native[#{property_name}]`
21
+
22
+ # translate setting a property
23
+ if message.end_with? '='
24
+ return `#@native[#{property_name}] = args[0]`
25
+ end
26
+
27
+ # If the native element doesn't have this property, bubble it up
28
+ super unless `#{property_name} in #@native`
29
+
30
+ if `property === false`
31
+ return false
32
+ elsif `typeof(property) === 'number' && isNaN(property)`
33
+ return nil
34
+ else
35
+ property = `property == null ? nil : property`
36
+ end
37
+
38
+ # If it's a method, call it. Otherwise, return it.
39
+ if `typeof(property) === 'function'`
40
+ `property.apply(#@native, args)`
41
+ else
42
+ property
43
+ end
44
+ end
45
+
46
+ def respond_to_missing? message, include_all
47
+ return true if message.end_with? '='
48
+ return true if property_for_message(message)
49
+
50
+ false
51
+ end
52
+
53
+ def property_for_message message
54
+ camel_cased_message = message
55
+ .gsub(/_\w/) { |match| `match[1]`.upcase }
56
+ .sub(/=$/, '')
57
+
58
+ # translate `supported?` to `supported` or `isSupported`
59
+ if message.end_with? '?'
60
+ camel_cased_message = camel_cased_message.chop
61
+ property_type = `typeof(#@native[camel_cased_message])`
62
+ if property_type == 'undefined'
63
+ camel_cased_message = "is#{camel_cased_message[0].upcase}#{camel_cased_message[1..-1]}"
64
+ end
65
+ end
66
+
67
+ camel_cased_message
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,176 @@
1
+ module Browser
2
+ autoload :FileList, 'browser/file_list'
3
+ autoload :Iterable, 'browser/iterable'
4
+
5
+ # Wrap a native DOM element
6
+ class Element
7
+ include EventTarget
8
+ include DelegateNative
9
+
10
+ @tags = Hash.new(self)
11
+
12
+ def self.element *tags, &block
13
+ tags.each do |tag|
14
+ @tags
15
+ .fetch(tag) { @tags[tag] = const_set(tag.capitalize, Class.new(self)) }
16
+ .class_exec(&block)
17
+ end
18
+ end
19
+
20
+ def self.new(native)
21
+ element = @tags[`(#{native}.tagName || '')`.downcase].allocate
22
+ element.initialize native
23
+ element
24
+ end
25
+
26
+ # @param native [JS] The native DOM element to wrap
27
+ def initialize native
28
+ @native = native
29
+ end
30
+
31
+ # Replace all child elements with the given element
32
+ #
33
+ # @param element [Browser::Element] The Browser element with which to replace
34
+ # this element's contents
35
+ def inner_dom= element
36
+ clear
37
+ append element
38
+ end
39
+
40
+ # The contents of this element as an HTML string
41
+ #
42
+ # @return [String] the HTML representation of this element's contents
43
+ def inner_html
44
+ `#@native.innerHTML`
45
+ end
46
+
47
+ # Use the supplied HTML string to replace this element's contents
48
+ #
49
+ # @param html [String] the HTML with which to replace this elements contents
50
+ def inner_html= html
51
+ `#@native.innerHTML = html`
52
+ end
53
+
54
+ # This element's direct child elements
55
+ #
56
+ # @return [Array<Browser::Element>] list of this element's children
57
+ def children
58
+ elements = []
59
+
60
+ %x{
61
+ var children = #@native.children;
62
+ for(var i = 0; i < children.length; i++) {
63
+ elements[i] = #{Element.new(`children[i]`)};
64
+ }
65
+ }
66
+
67
+ elements
68
+ end
69
+
70
+ # Determine whether this element has any contents
71
+ #
72
+ # @return [Boolean] true if the element has no children, false otherwise
73
+ def empty?
74
+ `#@native.children.length === 0`
75
+ end
76
+
77
+ # Remove all contents from this element. After this call, `empty?` will
78
+ # return `true`.
79
+ #
80
+ # @return [Browser::Element] self
81
+ def clear
82
+ if %w(input textarea).include? type
83
+ `#@native.value = null`
84
+ else
85
+ children.each do |child|
86
+ remove_child child
87
+ end
88
+ end
89
+
90
+ self
91
+ end
92
+
93
+ # Remove the specified child element
94
+ #
95
+ # @param child [Browser::Element] the child element to remove
96
+ def remove_child child
97
+ `#@native.removeChild(child['native'] ? child['native'] : child)`
98
+ end
99
+
100
+ # This element's type. For example: "div", "span", "p"
101
+ #
102
+ # @return [String] the HTML tag name for this element
103
+ def type
104
+ `#@native.nodeName`.downcase
105
+ end
106
+
107
+ # Append the specified element as a child element
108
+ #
109
+ # @param element [Browser::Element, JS] the element to insert
110
+ def append node
111
+ `#@native.appendChild(node['native'] ? node['native'] : node)`
112
+ self
113
+ end
114
+
115
+ # Methods for <input /> elements
116
+
117
+ # A checkbox's checked status
118
+ #
119
+ # @return [Boolean] true if the checkbox is checked, false otherwise
120
+ def checked?
121
+ `!!#@native.checked`
122
+ end
123
+
124
+ # Get the currently selected file for this input. This is only useful for
125
+ # file inputs without the `multiple` property set.
126
+ #
127
+ # @return [Browser::File] the file selected by the user
128
+ def file
129
+ files.first
130
+ end
131
+
132
+ # Get the currently selected files for this input. This is only useful for
133
+ # file inputs with the `multiple` property set.
134
+ #
135
+ # @return [Browser::FileList] the currently selected files for this input
136
+ def files
137
+ FileList.new(`#@native.files`)
138
+ end
139
+
140
+ # Determine whether this is the same element
141
+ #
142
+ # @return [boolean] true if the element is the same, false otherwise
143
+ def ==(other)
144
+ `#@native === #{other.to_n}`
145
+ end
146
+
147
+ # Set the specified attribute to the specified value
148
+ def []= attribute, value
149
+ `#@native.setAttribute(#{attribute}, #{value})`
150
+ end
151
+
152
+ # Return the specified attribute
153
+ #
154
+ # @return [String] the value for the specified attribute
155
+ def [] attribute
156
+ `#@native.getAttribute(#{attribute})`
157
+ end
158
+
159
+ def query_selector selector
160
+ result = super
161
+
162
+ Element.new(result) if result
163
+ end
164
+
165
+ def query_selector_all selector
166
+ Iterable.new(super).map { |element| Element.new(element) }
167
+ end
168
+
169
+ # The native representation of this element.
170
+ #
171
+ # @return [JS] the native element wrapped by this object.
172
+ def to_n
173
+ @native
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,17 @@
1
+ module Browser
2
+ class Element
3
+ element :canvas do
4
+ def context(type='2d')
5
+ Context.new(`#@native.getContext(#{type})`)
6
+ end
7
+
8
+ class Context
9
+ include DelegateNative
10
+
11
+ def initialize native
12
+ @native = native
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,78 @@
1
+ module Browser
2
+ class Element
3
+ element :video, :audio do
4
+ def buffered
5
+ TimeRanges.new(`#@native.buffered`)
6
+ end
7
+
8
+ def played
9
+ TimeRanges.new(`#@native.played`)
10
+ end
11
+
12
+ def seekable
13
+ TimeRanges.new(`#@native.seekable`)
14
+ end
15
+
16
+ def network_state
17
+ case `#@native.networkState`
18
+ when `HTMLMediaElement.NETWORK_EMPTY` then :no_data
19
+ when `HTMLMediaElement.NETWORK_IDLE` then :idle
20
+ when `HTMLMediaElement.NETWORK_LOADING` then :loading
21
+ when `HTMLMediaElement.NETWORK_NO_SOURCE` then :no_source
22
+ end
23
+ end
24
+ end
25
+
26
+ element :video do
27
+ def fullscreen
28
+ fullscreen = %w(
29
+ requestFullScreen
30
+ requestFullscreen
31
+ webkitRequestFullScreen
32
+ webkitRequestFullscreen
33
+ mozRequestFullScreen
34
+ msRequestFullscreen
35
+ ).find { |prop| `!!#@native[prop]` }
36
+
37
+ if fullscreen
38
+ `#@native[fullscreen]()`
39
+ else
40
+ warn "[#{self.class}] Cannot determine the method to full-screen a video"
41
+ super
42
+ end
43
+ end
44
+ alias request_fullscreen fullscreen
45
+ end
46
+
47
+ class TimeRanges
48
+ include Enumerable
49
+
50
+ def initialize native
51
+ @native = native
52
+ end
53
+
54
+ def to_n
55
+ @native
56
+ end
57
+
58
+ def each
59
+ `#@native.length`.times do |i|
60
+ yield TimeRange.new(`#@native.start(i)`, `#@native.end(i)`)
61
+ end
62
+
63
+ self
64
+ end
65
+ end
66
+
67
+ class TimeRange
68
+ attr_reader :start, :end
69
+
70
+ def initialize start, _end
71
+ @start = start
72
+ @end = _end
73
+ end
74
+
75
+ alias begin start
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,92 @@
1
+ module Browser
2
+ # Wrapper for JS events
3
+ class Event
4
+ # @param [JS] the native event to wrap
5
+ def initialize native
6
+ @native = native
7
+ end
8
+
9
+ # Prevent the runtime from executing this event's default behavior. For
10
+ # example, prevent navigation after clicking a link.
11
+ #
12
+ # @return [Browser::Event] self
13
+ def prevent
14
+ `#@native.preventDefault()`
15
+ self
16
+ end
17
+
18
+ # Prevent the runtime from bubbling this event up the hierarchy. This is
19
+ # typically used to keep an event local to the element on which it was
20
+ # triggered, such as keeping a click event on a button from unintentionally
21
+ # triggering a handler on a parent element.
22
+ #
23
+ # @return self
24
+ def stop_propagation
25
+ `#@native.stopPropagation()`
26
+ self
27
+ end
28
+
29
+ # @return [Boolean] true if `prevent` has been called on this event, false
30
+ # otherwise
31
+ def prevented?
32
+ `#@native.defaultPrevented`
33
+ end
34
+
35
+ # @return [Boolean] true if the Meta/Command/Windows key was pressed when
36
+ # this event fired, false otherwise
37
+ def meta?
38
+ `#@native.metaKey`
39
+ end
40
+
41
+ # @return [Boolean] true if the Shift key was pressed when this event fired,
42
+ # false otherwise
43
+ def shift?
44
+ `#@native.shiftKey`
45
+ end
46
+
47
+ # @return [Boolean] true if the Ctrl key was pressed when this event fired,
48
+ # false otherwise
49
+ def ctrl?
50
+ `#@native.ctrlKey`
51
+ end
52
+
53
+ # @return [Boolean] true if the Alt key was pressed when this event fired,
54
+ # false otherwise
55
+ def alt?
56
+ `#@native.altKey`
57
+ end
58
+
59
+ # The target for this event
60
+ #
61
+ # @return [Browser::Element] the element on which this event was triggered
62
+ # @todo Handle non-DOM events here
63
+ def target
64
+ Element.new(`#@native.target`)
65
+ end
66
+
67
+ # @return [Numeric] the key code associated with this event. Only useful for
68
+ # keyboard-based events.
69
+ def code
70
+ `#@native.keyCode`
71
+ end
72
+
73
+ # Return properties on the event not covered by Ruby methods.
74
+ def method_missing name, *args
75
+ property = name.gsub(/_[a-z]/) { |match| match[-1, 1].upcase }
76
+ value = `#@native[property]`
77
+
78
+ if `!!value && #{Proc === value}`
79
+ value.call(*args)
80
+ elsif `value == null`
81
+ nil
82
+ else
83
+ value
84
+ end
85
+ end
86
+
87
+ # @return [JS] the native event wrapped by this object.
88
+ def to_n
89
+ @native
90
+ end
91
+ end
92
+ end