funicular 0.0.1 → 0.2.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 +4 -4
- data/CHANGELOG.md +79 -0
- data/README.md +66 -20
- data/Rakefile +103 -2
- data/demo/keymap_editor.html +582 -0
- data/demo/test_cable.html +179 -0
- data/demo/test_chartjs.html +235 -0
- data/demo/test_component.html +201 -0
- data/demo/test_diff_patch.html +146 -0
- data/demo/test_error_boundary.html +284 -0
- data/demo/test_router.html +257 -0
- data/demo/test_vdom.html +100 -0
- data/demo/tic-tac-toe.html +201 -0
- data/docs/architecture.md +118 -0
- data/exe/funicular +32 -0
- data/lib/funicular/assets/funicular.css +23 -0
- data/lib/funicular/assets/funicular.rb +21 -0
- data/lib/funicular/assets/funicular_debug.css +73 -0
- data/lib/funicular/assets/funicular_debug.js +183 -0
- data/lib/funicular/commands/routes.rb +69 -0
- data/lib/funicular/compiler.rb +143 -0
- data/lib/funicular/configuration.rb +76 -0
- data/lib/funicular/helpers/picoruby_helper.rb +112 -0
- data/lib/funicular/middleware.rb +123 -0
- data/lib/funicular/plugin.rb +147 -0
- data/lib/funicular/railtie.rb +26 -0
- data/lib/funicular/route_parser.rb +137 -0
- data/lib/funicular/schema.rb +167 -0
- data/lib/funicular/ssr/runtime.rb +101 -0
- data/lib/funicular/ssr.rb +51 -0
- data/lib/funicular/testing/node_runner.mjs +293 -0
- data/lib/funicular/testing/node_runner.rb +190 -0
- data/lib/funicular/testing.rb +22 -0
- data/lib/funicular/vendor/picorbc/VERSION +1 -0
- data/lib/funicular/vendor/picorbc/picorbc.js +5283 -0
- data/lib/funicular/vendor/picorbc/picorbc.wasm +0 -0
- data/lib/funicular/vendor/picoruby/VERSION +1 -0
- data/lib/funicular/vendor/picoruby/debug/init.iife.js +130 -0
- data/lib/funicular/vendor/picoruby/debug/picoruby.js +6423 -0
- data/lib/funicular/vendor/picoruby/debug/picoruby.wasm +0 -0
- data/lib/funicular/vendor/picoruby/dist/init.iife.js +130 -0
- data/lib/funicular/vendor/picoruby/dist/picoruby.js +2 -0
- data/lib/funicular/vendor/picoruby/dist/picoruby.wasm +0 -0
- data/lib/funicular/vendor/picoruby-test-node/VERSION +1 -0
- data/lib/funicular/vendor/picoruby-test-node/picoruby.js +6885 -0
- data/lib/funicular/vendor/picoruby-test-node/picoruby.wasm +0 -0
- data/lib/funicular/vendor/picoruby-test-node/picoruby.wasm.map +1 -0
- data/lib/funicular/version.rb +1 -1
- data/lib/funicular.rb +32 -1
- data/lib/generators/funicular/chat/chat_generator.rb +104 -0
- data/lib/generators/funicular/chat/templates/application_cable_channel.rb.tt +4 -0
- data/lib/generators/funicular/chat/templates/application_cable_connection.rb.tt +4 -0
- data/lib/generators/funicular/chat/templates/create_funicular_chat_messages.rb.tt +10 -0
- data/lib/generators/funicular/chat/templates/funicular_chat.css.tt +141 -0
- data/lib/generators/funicular/chat/templates/funicular_chat_channel.rb.tt +5 -0
- data/lib/generators/funicular/chat/templates/funicular_chat_component.rb.tt +135 -0
- data/lib/generators/funicular/chat/templates/funicular_chat_component_picotest.rb.tt +64 -0
- data/lib/generators/funicular/chat/templates/funicular_chat_controller.rb.tt +4 -0
- data/lib/generators/funicular/chat/templates/funicular_chat_message.rb.tt +13 -0
- data/lib/generators/funicular/chat/templates/funicular_chat_messages_controller.rb.tt +23 -0
- data/lib/generators/funicular/chat/templates/initializer.rb.tt +4 -0
- data/lib/generators/funicular/chat/templates/show.html.erb.tt +6 -0
- data/lib/tasks/funicular.rake +218 -0
- data/minitest/fixtures/funicular_app/components/greeting_component.rb +16 -0
- data/minitest/fixtures/funicular_app/initializer.rb +5 -0
- data/minitest/funicular_test.rb +13 -0
- data/minitest/hydration_test.rb +87 -0
- data/minitest/plugin_test.rb +51 -0
- data/minitest/schema_test.rb +106 -0
- data/minitest/ssr_test.rb +94 -0
- data/minitest/test_helper.rb +7 -0
- data/minitest/validations_test.rb +183 -0
- data/mrbgem.rake +16 -0
- data/mrblib/0_validations.rb +206 -0
- data/mrblib/1_validators.rb +180 -0
- data/mrblib/cable.rb +432 -0
- data/mrblib/component.rb +1050 -0
- data/mrblib/debug.rb +208 -0
- data/mrblib/differ.rb +254 -0
- data/mrblib/environment_inquirer.rb +34 -0
- data/mrblib/error_boundary.rb +125 -0
- data/mrblib/file_upload.rb +192 -0
- data/mrblib/form_builder.rb +300 -0
- data/mrblib/funicular.rb +245 -0
- data/mrblib/html_serializer.rb +121 -0
- data/mrblib/http.rb +183 -0
- data/mrblib/model.rb +196 -0
- data/mrblib/patcher.rb +269 -0
- data/mrblib/router.rb +266 -0
- data/mrblib/store.rb +304 -0
- data/mrblib/store_collection.rb +171 -0
- data/mrblib/store_singleton.rb +79 -0
- data/mrblib/styles.rb +83 -0
- data/mrblib/vdom.rb +273 -0
- data/sig/cable.rbs +66 -0
- data/sig/component.rbs +149 -0
- data/sig/debug.rbs +28 -0
- data/sig/differ.rbs +18 -0
- data/sig/environment_iquirer.rbs +10 -0
- data/sig/error_boundary.rbs +14 -0
- data/sig/file_upload.rbs +18 -0
- data/sig/form_builder.rbs +29 -0
- data/sig/funicular.rbs +24 -1
- data/sig/html_serializer.rbs +20 -0
- data/sig/http.rbs +37 -0
- data/sig/model.rbs +28 -0
- data/sig/patcher.rbs +18 -0
- data/sig/router.rbs +44 -0
- data/sig/store.rbs +89 -0
- data/sig/store_collection.rbs +43 -0
- data/sig/store_singleton.rbs +19 -0
- data/sig/styles.rbs +25 -0
- data/sig/validations.rbs +103 -0
- data/sig/vdom.rbs +59 -0
- metadata +154 -8
data/sig/component.rbs
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
module Funicular
|
|
2
|
+
class Component
|
|
3
|
+
class StateAccessor
|
|
4
|
+
def initialize: (Hash[Symbol, untyped] state_hash) -> void
|
|
5
|
+
def []: (Symbol key) -> untyped
|
|
6
|
+
def method_missing: (Symbol method, *untyped args) -> untyped
|
|
7
|
+
def respond_to_missing?: (Symbol method, ?bool include_private) -> bool
|
|
8
|
+
def errors: () -> Hash[Symbol, String]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
HTML_TAGS: Array[String]
|
|
12
|
+
|
|
13
|
+
attr_accessor props: Hash[Symbol, untyped]
|
|
14
|
+
attr_accessor vdom: VDOM::VNode | VDOM::Text | nil
|
|
15
|
+
attr_accessor dom_element: JS::Element
|
|
16
|
+
attr_accessor mounted: bool
|
|
17
|
+
attr_reader refs: Hash[Symbol, JS::Element]
|
|
18
|
+
@event_listeners: Array[Integer]
|
|
19
|
+
@child_components: Array[Component]
|
|
20
|
+
@suspense_data: Hash[Symbol, untyped]
|
|
21
|
+
@suspense_states: Hash[Symbol, Symbol]
|
|
22
|
+
@suspense_errors: Hash[Symbol, untyped]
|
|
23
|
+
@suspense_pending_timers: Array[Integer]
|
|
24
|
+
self.@suspense_definitions: Hash[Symbol, suspense_definition]
|
|
25
|
+
|
|
26
|
+
def initialize: (?Hash[Symbol, untyped] props) -> void
|
|
27
|
+
|
|
28
|
+
# Styles DSL class methods
|
|
29
|
+
def self.styles: () { (StyleBuilder) -> void } -> void
|
|
30
|
+
def self.styles_definitions: () -> Hash[Symbol, Hash[Symbol, untyped]]
|
|
31
|
+
|
|
32
|
+
# Suspense DSL class methods
|
|
33
|
+
# Note: Using untyped for Proc types to avoid instance_exec block type mismatch warnings
|
|
34
|
+
type suspense_definition = { loader: untyped, on_resolve: untyped, min_delay: Integer? }
|
|
35
|
+
def self.use_suspense: (Symbol name, untyped loader, ?on_resolve: untyped, ?min_delay: Integer) -> void
|
|
36
|
+
def self.suspense_definitions: () -> Hash[Symbol, suspense_definition]
|
|
37
|
+
|
|
38
|
+
def state: () -> StateAccessor
|
|
39
|
+
|
|
40
|
+
# Styles DSL instance method
|
|
41
|
+
def s: () -> StyleAccessor
|
|
42
|
+
|
|
43
|
+
# Public API
|
|
44
|
+
def initialize_state: () -> Hash[Symbol, untyped]
|
|
45
|
+
|
|
46
|
+
# Suspense instance methods
|
|
47
|
+
def load_suspense_data: () -> void
|
|
48
|
+
def load_single_suspense: (Symbol name, ?suspense_definition? definition) -> void
|
|
49
|
+
def reload_suspense: (Symbol name) -> void
|
|
50
|
+
def suspense_loading?: (*Symbol names) -> bool
|
|
51
|
+
def suspense_error?: (Symbol name) -> bool
|
|
52
|
+
def suspense_error: (Symbol name) -> untyped
|
|
53
|
+
def suspense: (fallback: ^() -> void, ?error: ^(untyped) -> void) { () -> void } -> void
|
|
54
|
+
|
|
55
|
+
def patch: (Hash[Symbol, untyped] new_state) -> void
|
|
56
|
+
def mount: (JS::Element container) -> void
|
|
57
|
+
def hydrate: (JS::Element dom_element) -> void
|
|
58
|
+
def seed_state: (Hash[untyped, untyped]? state_hash) -> self
|
|
59
|
+
def unmount: () -> void
|
|
60
|
+
def render: () -> (VDOM::VNode | String | Integer | Float | Array[untyped] | nil)
|
|
61
|
+
def bind_events: (JS::Element dom_element, VDOM::VNode | VDOM::Text | nil vnode) -> void
|
|
62
|
+
def build_vdom: () -> (VDOM::VNode | VDOM::Text | nil)
|
|
63
|
+
|
|
64
|
+
# Lifecycle hooks (public, can be overridden in subclasses)
|
|
65
|
+
def component_will_mount: () -> void
|
|
66
|
+
def component_mounted: () -> void
|
|
67
|
+
def component_will_update: () -> void
|
|
68
|
+
def component_updated: () -> void
|
|
69
|
+
def component_will_unmount: () -> void
|
|
70
|
+
def component_unmounted: () -> void
|
|
71
|
+
def component_raised: (Exception e) -> void
|
|
72
|
+
|
|
73
|
+
# Child component helper
|
|
74
|
+
def component: (Class component_class, ?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Component
|
|
75
|
+
|
|
76
|
+
# Rails-style form helper
|
|
77
|
+
def form_for: (Symbol model_key, ?Hash[Symbol, untyped] options) { (FormBuilder) -> void } -> VDOM::Element
|
|
78
|
+
|
|
79
|
+
# Rails-style routing helpers
|
|
80
|
+
def link_to: (String path, ?method: Symbol, ?navigate: bool, **untyped options) { -> untyped } -> VDOM::Element
|
|
81
|
+
def method_missing: (Symbol method, *untyped args) -> untyped
|
|
82
|
+
def respond_to_missing?: (Symbol method, ?bool include_private) -> bool
|
|
83
|
+
|
|
84
|
+
# Transition helpers
|
|
85
|
+
def remove_via: (String element_id, String from, String to, ?duration: Integer) ?{ () -> void } -> void
|
|
86
|
+
def add_via: (String element_id, String from, String to, ?duration: Integer) ?{ () -> void } -> void
|
|
87
|
+
|
|
88
|
+
# Private methods
|
|
89
|
+
private def handle_link_click: (String path) -> void
|
|
90
|
+
private def handle_link_with_method: (String path, Symbol method) -> void
|
|
91
|
+
private def handle_link_response: (HTTP::Response response, String path, Symbol method) -> void
|
|
92
|
+
private def normalize_state_value: (untyped value) -> untyped
|
|
93
|
+
private def re_render: () -> void
|
|
94
|
+
private def normalize_vnode: (untyped value) -> (VDOM::Element | VDOM::Text | VDOM::Component | nil)
|
|
95
|
+
private def add_data_component_attribute: (VDOM::VNode vnode) -> void
|
|
96
|
+
private def collect_refs: (JS::Element dom_element, VDOM::VNode | VDOM::Text | nil vnode, ?Hash[Symbol, JS::Element] refs_map) -> Hash[Symbol, JS::Element]
|
|
97
|
+
private def cleanup_events: () -> void
|
|
98
|
+
private def cleanup_suspense_timers: () -> void
|
|
99
|
+
private def add_child: (untyped child) -> void
|
|
100
|
+
private def collect_child_components: (VDOM::VNode | VDOM::Text | nil vnode) -> void
|
|
101
|
+
private def collect_child_components_recursive: (VDOM::VNode | VDOM::Text | nil vnode, Array[Component] components) -> void
|
|
102
|
+
|
|
103
|
+
# Hydration helpers
|
|
104
|
+
private def hydration_match?: (untyped vnode, untyped dom_element) -> bool
|
|
105
|
+
private def warn_hydration_mismatch: (untyped vnode, untyped dom_element) -> void
|
|
106
|
+
private def full_render_fallback: (VDOM::VNode | VDOM::Text | nil new_vdom, untyped server_dom) -> JS::Element
|
|
107
|
+
private def hydrate_child_components: (untyped vnode, untyped dom_element) -> void
|
|
108
|
+
|
|
109
|
+
# HTML element methods (DSL)
|
|
110
|
+
def div: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
111
|
+
def span: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
112
|
+
def p: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
113
|
+
def a: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
114
|
+
def h1: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
115
|
+
def h2: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
116
|
+
def h3: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
117
|
+
def h4: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
118
|
+
def h5: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
119
|
+
def h6: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
120
|
+
def ul: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
121
|
+
def ol: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
122
|
+
def li: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
123
|
+
def table: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
124
|
+
def thead: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
125
|
+
def tbody: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
126
|
+
def tr: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
127
|
+
def th: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
128
|
+
def td: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
129
|
+
def form: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
130
|
+
def input: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
131
|
+
def textarea: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
132
|
+
def button: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
133
|
+
def select: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
134
|
+
def option: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
135
|
+
def label: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
136
|
+
def header: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
137
|
+
def footer: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
138
|
+
def nav: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
139
|
+
def section: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
140
|
+
def article: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
141
|
+
def aside: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
142
|
+
def img: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
143
|
+
def video: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
144
|
+
def audio: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
145
|
+
def canvas: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
146
|
+
def br: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
147
|
+
def hr: (?Hash[Symbol, untyped] props) ?{ -> untyped } -> VDOM::Element
|
|
148
|
+
end
|
|
149
|
+
end
|
data/sig/debug.rbs
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
$__funicular_debug__: Funicular::Debug
|
|
2
|
+
|
|
3
|
+
module Funicular
|
|
4
|
+
module Debug
|
|
5
|
+
self.@error_registry: Array[Hash[Symbol, untyped]]
|
|
6
|
+
|
|
7
|
+
def self.enabled?: () -> bool
|
|
8
|
+
def self.component_registry: () -> Hash[Integer, Funicular::Component]
|
|
9
|
+
def self.register_component: (Funicular::Component) -> Integer?
|
|
10
|
+
def self.unregister_component: (Integer) -> void
|
|
11
|
+
def self.get_component: (Integer) -> Funicular::Component?
|
|
12
|
+
def self.all_components: () -> Array[Funicular::Component]
|
|
13
|
+
def self.component_tree: () -> String
|
|
14
|
+
def self.get_component_state: (Integer) -> String
|
|
15
|
+
def self.get_component_instance_variables: (Integer) -> String
|
|
16
|
+
def self.expose_to_global: () -> void
|
|
17
|
+
def self.report_error: (ErrorBoundary boundary, Exception error, ?(Hash[Symbol, Component] | nil) error_info) -> Hash[Symbol, untyped]?
|
|
18
|
+
def self.clear_errors: () -> void
|
|
19
|
+
def self.error_list: () -> String
|
|
20
|
+
def self.last_error: () -> Hash[Symbol, untyped]?
|
|
21
|
+
def self.error_count: () -> Integer
|
|
22
|
+
|
|
23
|
+
private def self.error_registry: () -> Array[Hash[Symbol, untyped]]
|
|
24
|
+
private def self.get_state_keys: (Funicular::Component) -> Array[String]
|
|
25
|
+
private def self.get_child_ids: (Funicular::Component) -> Array[Integer]
|
|
26
|
+
private def self.collect_direct_children: (Funicular::VDOM::VNode, Array[Funicular::Component]) -> void
|
|
27
|
+
end
|
|
28
|
+
end
|
data/sig/differ.rbs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Funicular
|
|
2
|
+
module VDOM
|
|
3
|
+
class Differ
|
|
4
|
+
type children_t = Array[child_t]
|
|
5
|
+
def self.diff: (untyped old_node, untyped new_node) -> Array[patch_t]
|
|
6
|
+
|
|
7
|
+
private def self.diff_text: (Text old_node, Text new_node) -> Array[patch_t]
|
|
8
|
+
private def self.diff_element: (Element old_node, Element new_node) -> Array[patch_t]
|
|
9
|
+
private def self.diff_props: (Hash[Symbol, untyped] old_props, Hash[Symbol, untyped] new_props) -> Hash[Symbol, untyped]
|
|
10
|
+
private def self.diff_children: (children_t old_children, children_t new_children) -> Array[patch_t]
|
|
11
|
+
private def self.diff_children_with_keys: (children_t old_children, children_t new_children) -> Array[patch_t]
|
|
12
|
+
private def self.diff_children_by_index: (children_t old_children, children_t new_children) -> Array[patch_t]
|
|
13
|
+
private def self.diff_component: (VDOM::Component old_node, VDOM::Component new_node) -> Array[patch_t]
|
|
14
|
+
|
|
15
|
+
private def self.props_changed_excluding_procs?: (Hash[Symbol, untyped] old_props, Hash[Symbol, untyped] new_props) -> bool
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Funicular
|
|
2
|
+
class ErrorBoundary < Component
|
|
3
|
+
attr_accessor error_caught_during_render: bool?
|
|
4
|
+
|
|
5
|
+
def initialize_state: () -> Hash[Symbol, untyped]
|
|
6
|
+
def catch_error: (Exception error, ?Hash[Symbol, untyped]? error_info) -> bool
|
|
7
|
+
def reset: () -> void
|
|
8
|
+
def render: () -> (VDOM::VNode | String | Integer | Float | Array[untyped] | nil)
|
|
9
|
+
|
|
10
|
+
private def render_fallback: () -> (VDOM::VNode | String)
|
|
11
|
+
private def default_fallback: () -> VDOM::VNode
|
|
12
|
+
private def render_children: () -> VDOM::VNode
|
|
13
|
+
end
|
|
14
|
+
end
|
data/sig/file_upload.rbs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Funicular
|
|
2
|
+
module FileUpload
|
|
3
|
+
self.@callback_counters: Array[Integer]
|
|
4
|
+
|
|
5
|
+
JS_HELPER_CODE: String
|
|
6
|
+
|
|
7
|
+
def self.mount: () -> void
|
|
8
|
+
def self.select_file_with_preview: (String input_id) { (JS::Object? file, String? preview_url) -> void } -> void
|
|
9
|
+
def self.upload_with_formdata: (
|
|
10
|
+
String url,
|
|
11
|
+
?fields: Hash[untyped, untyped],
|
|
12
|
+
?file_field: String?,
|
|
13
|
+
?file: JS::Object?
|
|
14
|
+
) { (Hash[untyped, untyped] result) -> void } -> void
|
|
15
|
+
def self.store_file: (String input_id, ?String storage_key) -> JS::Object?
|
|
16
|
+
def self.retrieve_file: (?String storage_key) -> JS::Object?
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Funicular
|
|
2
|
+
class FormBuilder
|
|
3
|
+
attr_reader component: Component
|
|
4
|
+
attr_reader model_key: Symbol
|
|
5
|
+
attr_reader options: Hash[Symbol, untyped]
|
|
6
|
+
|
|
7
|
+
def initialize: (Component component, Symbol model_key, ?Hash[Symbol, untyped] options) -> void
|
|
8
|
+
|
|
9
|
+
# Field builder methods
|
|
10
|
+
def text_field: (Symbol field_name, ?Hash[Symbol, untyped] options) -> VDOM::Element
|
|
11
|
+
def password_field: (Symbol field_name, ?Hash[Symbol, untyped] options) -> VDOM::Element
|
|
12
|
+
def email_field: (Symbol field_name, ?Hash[Symbol, untyped] options) -> VDOM::Element
|
|
13
|
+
def number_field: (Symbol field_name, ?Hash[Symbol, untyped] options) -> VDOM::Element
|
|
14
|
+
def textarea: (Symbol field_name, ?Hash[Symbol, untyped] options) -> VDOM::Element
|
|
15
|
+
def checkbox: (Symbol field_name, ?Hash[Symbol, untyped] options) -> VDOM::Element
|
|
16
|
+
def select: (Symbol field_name, Array[untyped] choices, ?Hash[Symbol, untyped] options) -> VDOM::Element
|
|
17
|
+
def file_field: (Symbol field_name, ?Hash[Symbol, untyped] options) -> VDOM::Element
|
|
18
|
+
def submit: (?String label, ?Hash[Symbol, untyped] options) -> VDOM::Element
|
|
19
|
+
def label: (Symbol field_name, ?String? text, ?Hash[Symbol, untyped] options) -> VDOM::Element
|
|
20
|
+
|
|
21
|
+
# Generic field builder
|
|
22
|
+
private def build_field: (Symbol field_name, String field_type, Hash[Symbol, untyped] field_options) -> VDOM::Element
|
|
23
|
+
|
|
24
|
+
# Helper methods for nested state access
|
|
25
|
+
private def get_nested_value: (Component::StateAccessor state, String key_path) -> untyped
|
|
26
|
+
private def set_nested_value: (Symbol model_key, String field_key, untyped new_value) -> void
|
|
27
|
+
private def deep_merge_value: (Hash[Symbol, untyped] hash, Array[String] keys, untyped value) -> Hash[Symbol, untyped]
|
|
28
|
+
end
|
|
29
|
+
end
|
data/sig/funicular.rbs
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
module Funicular
|
|
2
2
|
VERSION: String
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
self.@server: bool
|
|
5
|
+
self.@form_builder_config: Hash[Symbol, String]?
|
|
6
|
+
|
|
7
|
+
def self.version: () -> String
|
|
8
|
+
def self.env: () -> EnvironmentInquirer
|
|
9
|
+
def self.env=: (EnvironmentInquirer | String environment) -> EnvironmentInquirer?
|
|
10
|
+
def self.router: () -> Router?
|
|
11
|
+
|
|
12
|
+
# SSR / hydration support
|
|
13
|
+
def self.server?: () -> bool
|
|
14
|
+
def self.server=: (untyped value) -> bool
|
|
15
|
+
def self.window_state: () -> Hash[String, untyped]
|
|
16
|
+
def self.has_ssr_state?: () -> bool
|
|
17
|
+
def self.first_element_child: (JS::Element container_element) -> JS::Element?
|
|
18
|
+
|
|
19
|
+
def self.load_schemas: (Hash[singleton(Model), String] models) ?{ () -> void } -> void
|
|
20
|
+
def self.start: (?singleton(Component)? component_class, ?container: String | JS::Element, ?props: Hash[Symbol, untyped], ?hydrate: bool) ?{ (Router router) -> void } -> (Component | Router | nil)
|
|
21
|
+
def self.configure_forms: () ?{ (Hash[Symbol, String]) -> void } -> void
|
|
22
|
+
def self.form_builder_config: () -> Hash[Symbol, String]?
|
|
23
|
+
def self.form_builder_config=: (Hash[Symbol, String] config) -> Hash[Symbol, String]
|
|
24
|
+
def self.configure_debug: () ?{ (self) -> void } -> void
|
|
25
|
+
def self.export_debug_config: () -> void
|
|
26
|
+
|
|
4
27
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Funicular
|
|
2
|
+
module VDOM
|
|
3
|
+
class HTMLSerializer
|
|
4
|
+
VOID_ELEMENTS: Array[String]
|
|
5
|
+
SKIP_PROPS: Array[Symbol]
|
|
6
|
+
|
|
7
|
+
def self.serialize: (VNode? vnode) -> String
|
|
8
|
+
def render: (VNode? vnode) -> String
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
def render_element: (Element element) -> String
|
|
12
|
+
def render_children: (Array[child_t] children) -> String
|
|
13
|
+
def render_text: (Text text) -> String
|
|
14
|
+
def render_component: (Component component_vnode) -> String
|
|
15
|
+
def serialize_props: (Hash[Symbol, untyped] props) -> String
|
|
16
|
+
def escape_html: (untyped str) -> String
|
|
17
|
+
def escape_attr: (untyped str) -> String
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/sig/http.rbs
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Funicular
|
|
2
|
+
module HTTP
|
|
3
|
+
CACHE_DB_NAME: String
|
|
4
|
+
CACHE_STORE: String
|
|
5
|
+
|
|
6
|
+
self.@cache: IndexedDB::KVS?
|
|
7
|
+
|
|
8
|
+
class Response
|
|
9
|
+
attr_reader data: untyped
|
|
10
|
+
attr_reader status: Integer
|
|
11
|
+
attr_reader ok: bool
|
|
12
|
+
|
|
13
|
+
def initialize: (Integer status, untyped data) -> void
|
|
14
|
+
def error?: () -> bool
|
|
15
|
+
def error_message: () -> String?
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.cache_init!: () -> IndexedDB::KVS
|
|
19
|
+
def self.cache_purge: (String url) -> nil
|
|
20
|
+
def self.cache_clear: () -> nil
|
|
21
|
+
def self.cache_lookup: (String url) -> untyped
|
|
22
|
+
def self.cache_write: (String url, Hash[String, untyped] entry) -> nil
|
|
23
|
+
|
|
24
|
+
def self.get: (String url, ?cache: Integer?) { (Response) -> void } -> void
|
|
25
|
+
def self.post: (String url, ?Hash[untyped, untyped]? body, ?cache: Integer?) { (Response) -> void } -> void
|
|
26
|
+
def self.patch: (String url, ?Hash[untyped, untyped]? body, ?cache: Integer?) { (Response) -> void } -> void
|
|
27
|
+
def self.delete: (String url, ?cache: Integer?) { (Response) -> void } -> void
|
|
28
|
+
def self.put: (String url, ?Hash[untyped, untyped]? body, ?cache: Integer?) { (Response) -> void } -> void
|
|
29
|
+
def self.csrf_token: () -> String?
|
|
30
|
+
|
|
31
|
+
private def self.warn_unsupported_cache: (String verb) -> void
|
|
32
|
+
private def self.now_seconds: () -> Integer
|
|
33
|
+
private def self.cache_hit?: (untyped entry, Integer ttl) -> bool
|
|
34
|
+
private def self.serve_from_cache: (Hash[String, untyped] entry) { (Response) -> void } -> void
|
|
35
|
+
private def self.request: (String method, String url, Hash[untyped, untyped]? body, ?cache: Integer?) { (Response) -> void } -> void
|
|
36
|
+
end
|
|
37
|
+
end
|
data/sig/model.rbs
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Funicular
|
|
2
|
+
class Model
|
|
3
|
+
include Funicular::Model::Validations
|
|
4
|
+
extend Funicular::Model::Validations::ClassMethods
|
|
5
|
+
|
|
6
|
+
attr_reader id: untyped
|
|
7
|
+
@changed_attributes: Hash[String, untyped]
|
|
8
|
+
|
|
9
|
+
def self.schema: () -> Hash[String, Hash[String, untyped]]
|
|
10
|
+
def self.schema=: (Hash[String, Hash[String, untyped]] schema) -> Hash[String, Hash[String, untyped]]
|
|
11
|
+
def self.endpoints: () -> Hash[String, Hash[String, String]]
|
|
12
|
+
def self.endpoints=: (Hash[String, Hash[String, String]] endpoints) -> Hash[String, Hash[String, String]]
|
|
13
|
+
|
|
14
|
+
def initialize: (?Hash[untyped, untyped] attributes) -> void
|
|
15
|
+
def self.load_schema: (Hash[String, untyped] schema_data) -> void
|
|
16
|
+
def self.register_schema_validations: (untyped validations) -> void
|
|
17
|
+
def self.normalize_validation_options: (Symbol | String kind, untyped opts) -> untyped
|
|
18
|
+
|
|
19
|
+
def self.all: (?Hash[untyped, untyped] params) ?{ (Array[Model]? instances, String? error) -> void } -> void
|
|
20
|
+
def self.find: (?untyped id, ?endpoint_name: String, ?model_class: singleton(Model)) ?{ (Model? instance, String? error) -> void } -> void
|
|
21
|
+
def self.create: (Hash[untyped, untyped] attrs, ?model_class: singleton(Model)) ?{ (Model? instance, untyped error) -> void } -> void
|
|
22
|
+
def self.destroy: (?untyped id) ?{ (bool success, untyped result) -> void } -> void
|
|
23
|
+
|
|
24
|
+
def update: (?Hash[untyped, untyped]? attrs) ?{ (bool success, untyped result) -> void } -> void
|
|
25
|
+
def destroy: () ?{ (bool success, untyped result) -> void } -> void
|
|
26
|
+
def reload: () ?{ (Model? instance, String? error) -> void } -> void
|
|
27
|
+
end
|
|
28
|
+
end
|
data/sig/patcher.rbs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Funicular
|
|
2
|
+
module VDOM
|
|
3
|
+
BOOLEAN_ATTRIBUTES: Array[String]
|
|
4
|
+
|
|
5
|
+
class Patcher
|
|
6
|
+
def initialize: (?JS::Element? doc) -> void
|
|
7
|
+
# `apply` accepts any DOM node so text-node patches (e.g. :replace)
|
|
8
|
+
# can recurse into it; Element-only operations are narrowed inside.
|
|
9
|
+
def apply: (JS::Object element, Array[patch_t] patches) -> JS::Object
|
|
10
|
+
|
|
11
|
+
# Accepts JS::Object since callers narrow via is_a?(JS::Element) at runtime
|
|
12
|
+
private def update_props: (JS::Object element, Hash[Symbol, String?] props_patch) -> void
|
|
13
|
+
private def create_element: (untyped vnode) -> JS::Object
|
|
14
|
+
private def unmount_component: (VDOM::VNode vnode) -> void
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
end
|
data/sig/router.rbs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Funicular
|
|
2
|
+
type route_constraints_t = Hash[Symbol, Regexp]
|
|
3
|
+
type route_definition_t = { method: Symbol, path: String, component: singleton(Component), name: String?, pattern_segments: Array[String], constraints: route_constraints_t }
|
|
4
|
+
|
|
5
|
+
# URL helper methods are dynamically generated based on route definitions
|
|
6
|
+
# Example: router.get('/users/:id', to: UserComponent, as: 'user')
|
|
7
|
+
# generates: user_path(id) -> String
|
|
8
|
+
module RouteHelpers
|
|
9
|
+
# Dynamic methods are generated at runtime by Router#generate_url_helper
|
|
10
|
+
# Method signatures depend on route parameters:
|
|
11
|
+
# - No parameters: def helper_name_path: () -> String
|
|
12
|
+
# - With parameters: def helper_name_path: (Integer | String | untyped) -> String
|
|
13
|
+
def method_missing: (Symbol method, *untyped args) -> String
|
|
14
|
+
def respond_to_missing?: (Symbol method, ?bool include_private) -> bool
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class Router
|
|
18
|
+
attr_reader routes: Array[route_definition_t]
|
|
19
|
+
attr_reader current_component: Component?
|
|
20
|
+
attr_reader current_path: String?
|
|
21
|
+
|
|
22
|
+
def initialize: (JS::Element? container) -> void
|
|
23
|
+
def get: (String path, to: singleton(Component), ?as: String?, ?constraints: route_constraints_t?) -> void
|
|
24
|
+
def post: (String path, to: singleton(Component), ?as: String?, ?constraints: route_constraints_t?) -> void
|
|
25
|
+
def put: (String path, to: singleton(Component), ?as: String?, ?constraints: route_constraints_t?) -> void
|
|
26
|
+
def patch: (String path, to: singleton(Component), ?as: String?, ?constraints: route_constraints_t?) -> void
|
|
27
|
+
def delete: (String path, to: singleton(Component), ?as: String?, ?constraints: route_constraints_t?) -> void
|
|
28
|
+
def add_route: (String path, singleton(Component) component_class, ?as: String?, ?constraints: route_constraints_t?) -> void
|
|
29
|
+
def set_default: (String path) -> void
|
|
30
|
+
def match: (String path) -> [singleton(Component)?, Hash[Symbol, untyped]]
|
|
31
|
+
def start: (?hydrate: bool) -> void
|
|
32
|
+
def stop: () -> void
|
|
33
|
+
def navigate: (String path) -> void
|
|
34
|
+
def current_hash_path: () -> String
|
|
35
|
+
def current_location_path: () -> String
|
|
36
|
+
|
|
37
|
+
private def add_route_with_method: (Symbol method, String path, singleton(Component) component_class, String? name, ?route_constraints_t? constraints) -> void
|
|
38
|
+
private def generate_url_helper: (String name, String path_pattern) -> void
|
|
39
|
+
private def extract_param_names: (String path_pattern) -> Array[Symbol]
|
|
40
|
+
private def handle_route_change: () -> void
|
|
41
|
+
private def unmount_current_component: () -> void
|
|
42
|
+
private def find_route: (String path) -> [singleton(Component) | nil, Hash[Symbol, untyped]]
|
|
43
|
+
end
|
|
44
|
+
end
|
data/sig/store.rbs
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
module Funicular
|
|
2
|
+
class Store
|
|
3
|
+
EVENT_REGISTRY: Hash[Symbol, Array[singleton(Funicular::Store)]]
|
|
4
|
+
KVS_POOL: Hash[Array[String], IndexedDB::KVS]
|
|
5
|
+
|
|
6
|
+
class SubscribesTo < Data
|
|
7
|
+
attr_reader channel_name: String
|
|
8
|
+
attr_reader params_proc: ^(Funicular::Store::Scope) -> Hash[Symbol, untyped]
|
|
9
|
+
attr_reader handler_block: Proc
|
|
10
|
+
|
|
11
|
+
def self.new: (String channel_name, ^(Funicular::Store::Scope) -> Hash[Symbol, untyped] params_proc, Proc handler_block) -> instance
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class Subscription
|
|
15
|
+
attr_reader cable_sub: Funicular::Cable::Subscription
|
|
16
|
+
|
|
17
|
+
def initialize: (Funicular::Cable::Subscription cable_sub) -> void
|
|
18
|
+
def unsubscribe: () -> nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class Scope
|
|
22
|
+
attr_reader store_class: singleton(Funicular::Store)
|
|
23
|
+
attr_reader scope_kwargs: Hash[Symbol, untyped]
|
|
24
|
+
|
|
25
|
+
@on_change: Hash[Integer, Proc]
|
|
26
|
+
@next_cb_id: Integer
|
|
27
|
+
@subscription: Funicular::Store::Subscription?
|
|
28
|
+
|
|
29
|
+
def initialize: (singleton(Funicular::Store) store_class, Hash[Symbol, untyped] scope_kwargs) -> void
|
|
30
|
+
def method_missing: (Symbol name, *untyped args) -> untyped
|
|
31
|
+
def respond_to_missing?: (Symbol name, ?bool include_private) -> bool
|
|
32
|
+
def on_change: () { (untyped) -> void } -> Integer
|
|
33
|
+
def off_change: (Integer id) -> nil
|
|
34
|
+
def subscribed?: () -> bool
|
|
35
|
+
def subscription: () -> Funicular::Store::Subscription?
|
|
36
|
+
def subscribe!: () -> Funicular::Store::Subscription
|
|
37
|
+
def unsubscribe!: () -> nil
|
|
38
|
+
|
|
39
|
+
private def storage_key: () -> String
|
|
40
|
+
private def kvs: () -> IndexedDB::KVS
|
|
41
|
+
private def now_seconds: () -> Integer
|
|
42
|
+
private def expired_record?: (untyped rec) -> bool
|
|
43
|
+
private def fire_change: (untyped snapshot) -> void
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
self.@__database: String?
|
|
47
|
+
self.@__kvs_store_name: String?
|
|
48
|
+
self.@__scope_keys: Array[Symbol]?
|
|
49
|
+
self.@__expires_in: Integer?
|
|
50
|
+
self.@__source: untyped
|
|
51
|
+
self.@__belongs_to: Symbol?
|
|
52
|
+
self.@__cable_url: String?
|
|
53
|
+
self.@__cable_binding: SubscribesTo?
|
|
54
|
+
self.@__cleared_handlers: Hash[Symbol, Proc?]?
|
|
55
|
+
self.@__scope_pool: Hash[Hash[Symbol, untyped], Funicular::Store::Scope]?
|
|
56
|
+
self.@__consumer: Funicular::Cable::Consumer?
|
|
57
|
+
|
|
58
|
+
def self.database: (String name) -> String
|
|
59
|
+
def self.kvs_store: (String name) -> String
|
|
60
|
+
def self.scope: (*Symbol keys) -> Array[Symbol]
|
|
61
|
+
def self.expires_in: (Integer seconds) -> Integer
|
|
62
|
+
def self.source: (untyped model_class) -> untyped
|
|
63
|
+
def self.belongs_to: (Symbol name) -> Symbol
|
|
64
|
+
def self.cable_url: (String url) -> String
|
|
65
|
+
def self.subscribes_to: (String channel_name, params: ^(Funicular::Store::Scope) -> Hash[Symbol, untyped]) { (untyped, Funicular::Store::Scope) -> void } -> SubscribesTo
|
|
66
|
+
def self.cleared_on: (*Symbol event_names) ?{ (untyped) -> void } -> void
|
|
67
|
+
|
|
68
|
+
def self.where: (**untyped scope_kwargs) -> Funicular::Store::Scope
|
|
69
|
+
def self.scope_class: () -> singleton(Funicular::Store::Scope)
|
|
70
|
+
|
|
71
|
+
def self.__database: () -> String?
|
|
72
|
+
def self.__kvs_store_name: () -> String?
|
|
73
|
+
def self.__scope_keys: () -> Array[Symbol]?
|
|
74
|
+
def self.__expires_in: () -> Integer?
|
|
75
|
+
def self.__source: () -> untyped
|
|
76
|
+
def self.__belongs_to: () -> Symbol?
|
|
77
|
+
def self.__cable_url: () -> String?
|
|
78
|
+
def self.__cable_binding: () -> SubscribesTo?
|
|
79
|
+
def self.__cleared_handlers: () -> Hash[Symbol, Proc?]?
|
|
80
|
+
def self.__kvs: () -> IndexedDB::KVS
|
|
81
|
+
def self.__consumer: () -> Funicular::Cable::Consumer
|
|
82
|
+
def self.__handle_dispatch: (Symbol event, untyped payload) -> void
|
|
83
|
+
def self.__clear_all!: () -> nil
|
|
84
|
+
|
|
85
|
+
private def self.validate_scope_kwargs!: (Hash[Symbol, untyped] scope_kwargs) -> void
|
|
86
|
+
|
|
87
|
+
def self.dispatch: (Symbol | String event, ?untyped payload) -> nil
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Funicular
|
|
2
|
+
class Store
|
|
3
|
+
class Collection < Funicular::Store
|
|
4
|
+
DEFAULT_KEY_PROC: ^(untyped) -> untyped
|
|
5
|
+
|
|
6
|
+
self.@__limit: Integer?
|
|
7
|
+
self.@__order: Symbol?
|
|
8
|
+
self.@__key_proc: ^(untyped) -> untyped | nil
|
|
9
|
+
|
|
10
|
+
def self.limit: (Integer n) -> Integer
|
|
11
|
+
def self.order: (Symbol direction) -> Symbol
|
|
12
|
+
def self.key: (^(untyped) -> untyped proc) -> (^(untyped) -> untyped)
|
|
13
|
+
def self.scope_class: () -> singleton(Funicular::Store::Collection::Scope)
|
|
14
|
+
|
|
15
|
+
def self.__limit: () -> Integer?
|
|
16
|
+
def self.__order: () -> Symbol?
|
|
17
|
+
def self.__key_proc: () -> (^(untyped) -> untyped | nil)
|
|
18
|
+
|
|
19
|
+
class Scope < Funicular::Store::Scope
|
|
20
|
+
attr_reader store_class: singleton(Funicular::Store::Collection)
|
|
21
|
+
@store_class: singleton(Funicular::Store::Collection)
|
|
22
|
+
|
|
23
|
+
def all: () -> Array[untyped]
|
|
24
|
+
def replace: (untyped arr) -> Array[untyped]
|
|
25
|
+
def append: (untyped item) -> Array[untyped]
|
|
26
|
+
def remove: (untyped id) -> Array[untyped]
|
|
27
|
+
def last: () -> untyped
|
|
28
|
+
def last_id: () -> untyped
|
|
29
|
+
def size: () -> Integer
|
|
30
|
+
def clear: () -> nil
|
|
31
|
+
def expired?: () -> bool
|
|
32
|
+
def same_tail?: (untyped other) -> bool
|
|
33
|
+
|
|
34
|
+
private def key_proc: () -> ^(untyped) -> untyped
|
|
35
|
+
private def cap: (Array[untyped] arr) -> Array[untyped]
|
|
36
|
+
private def append_to: (Array[untyped] arr, untyped item) -> Array[untyped]
|
|
37
|
+
private def read: () -> untyped
|
|
38
|
+
private def write: (Array[untyped] items) -> Hash[String, untyped]
|
|
39
|
+
private def erase: () -> nil
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Funicular
|
|
2
|
+
class Store
|
|
3
|
+
class Singleton < Funicular::Store
|
|
4
|
+
def self.scope_class: () -> singleton(Funicular::Store::Singleton::Scope)
|
|
5
|
+
|
|
6
|
+
class Scope < Funicular::Store::Scope
|
|
7
|
+
def value: () -> untyped
|
|
8
|
+
def value=: (untyped v) -> untyped
|
|
9
|
+
def delete: () -> nil
|
|
10
|
+
def present?: () -> bool
|
|
11
|
+
def expired?: () -> bool
|
|
12
|
+
|
|
13
|
+
private def read: () -> untyped
|
|
14
|
+
private def write: (untyped v) -> Hash[String, untyped]
|
|
15
|
+
private def erase: () -> nil
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
data/sig/styles.rbs
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Funicular
|
|
2
|
+
# StyleValue represents a CSS class string that can be combined with other styles
|
|
3
|
+
class StyleValue
|
|
4
|
+
attr_reader value: String
|
|
5
|
+
def initialize: (String | untyped value) -> void
|
|
6
|
+
def |: (StyleValue | String | nil other) -> StyleValue
|
|
7
|
+
def to_s: () -> String
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# StyleAccessor provides access to defined styles via method calls
|
|
11
|
+
class StyleAccessor
|
|
12
|
+
def initialize: (Hash[Symbol, Hash[Symbol, untyped]] definitions) -> void
|
|
13
|
+
private def method_missing: (Symbol name, *untyped args) -> StyleValue
|
|
14
|
+
private def respond_to_missing?: (Symbol name, ?bool include_private) -> bool
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# StyleBuilder is used to define styles within the styles {} block
|
|
18
|
+
class StyleBuilder
|
|
19
|
+
@definitions: Hash[Symbol, Hash[Symbol, untyped]]
|
|
20
|
+
|
|
21
|
+
def initialize: () -> void
|
|
22
|
+
def to_definitions: () -> Hash[Symbol, Hash[Symbol, untyped]]
|
|
23
|
+
private def method_missing: (Symbol name, *untyped args) -> void
|
|
24
|
+
end
|
|
25
|
+
end
|