funicular 0.0.1 → 0.1.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 +56 -1
- data/README.md +58 -20
- data/Rakefile +74 -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/README.md +419 -0
- data/docs/advanced-features.md +632 -0
- data/docs/architecture.md +409 -0
- data/docs/components-and-state.md +539 -0
- data/docs/data-fetching.md +528 -0
- data/docs/forms.md +446 -0
- data/docs/rails-integration.md +426 -0
- data/docs/realtime.md +543 -0
- data/docs/routing-and-navigation.md +427 -0
- data/docs/styling.md +285 -0
- data/exe/funicular +32 -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 +135 -0
- data/lib/funicular/configuration.rb +76 -0
- data/lib/funicular/helpers/picoruby_helper.rb +50 -0
- data/lib/funicular/middleware.rb +98 -0
- data/lib/funicular/railtie.rb +26 -0
- data/lib/funicular/route_parser.rb +137 -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 +6404 -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/version.rb +1 -1
- data/lib/funicular.rb +29 -1
- data/lib/tasks/funicular.rake +135 -0
- data/minitest/funicular_test.rb +13 -0
- data/minitest/test_helper.rb +7 -0
- data/mrbgem.rake +15 -0
- data/mrblib/cable.rb +417 -0
- data/mrblib/component.rb +911 -0
- data/mrblib/debug.rb +205 -0
- data/mrblib/differ.rb +244 -0
- data/mrblib/environment_inquirer.rb +34 -0
- data/mrblib/error_boundary.rb +125 -0
- data/mrblib/file_upload.rb +184 -0
- data/mrblib/form_builder.rb +284 -0
- data/mrblib/funicular.rb +156 -0
- data/mrblib/http.rb +89 -0
- data/mrblib/model.rb +146 -0
- data/mrblib/patcher.rb +203 -0
- data/mrblib/router.rb +229 -0
- data/mrblib/styles.rb +83 -0
- data/mrblib/vdom.rb +273 -0
- data/sig/cable.rbs +65 -0
- data/sig/component.rbs +141 -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 +11 -1
- data/sig/http.rbs +22 -0
- data/sig/model.rbs +23 -0
- data/sig/patcher.rbs +15 -0
- data/sig/router.rbs +43 -0
- data/sig/styles.rbs +25 -0
- data/sig/vdom.rbs +59 -0
- metadata +119 -8
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
# Rails Integration
|
|
2
|
+
|
|
3
|
+
This document describes CRubyGem funicular as a Rails plugin.
|
|
4
|
+
|
|
5
|
+
## Seamless Rails integration
|
|
6
|
+
|
|
7
|
+
- Automatic compilation of Ruby files to mruby bytecode (.mrb)
|
|
8
|
+
- Development mode with debug symbols (-g option)
|
|
9
|
+
- Production mode with optimized bytecode (no debug symbols)
|
|
10
|
+
- Auto-recompilation in development when source files change
|
|
11
|
+
- Rails-style routing with `link_to` helper and URL path helpers
|
|
12
|
+
- RESTful HTTP method support (GET, POST, PUT, PATCH, DELETE)
|
|
13
|
+
- Built-in CSRF protection for non-GET requests
|
|
14
|
+
|
|
15
|
+
## Prerequisites
|
|
16
|
+
|
|
17
|
+
Funicular bundles a WebAssembly build of the `picorbc` mruby compiler and
|
|
18
|
+
runs it through Node.js. Make sure Node.js is installed on any machine that
|
|
19
|
+
performs Funicular compilation (your development workstation, CI, and any
|
|
20
|
+
host that runs `assets:precompile`).
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
node --version
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
You do **not** need to install `@picoruby/picorbc` from npm; the gem ships
|
|
27
|
+
with the compiler already vendored.
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
### 1. Add the gem
|
|
32
|
+
|
|
33
|
+
```ruby
|
|
34
|
+
# Gemfile
|
|
35
|
+
gem "funicular"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
bundle install
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 2. Run the install task
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
bundle exec rake funicular:install
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
This runs two sub-tasks:
|
|
49
|
+
|
|
50
|
+
#### `funicular:install:wasm`
|
|
51
|
+
|
|
52
|
+
Copies the PicoRuby.wasm runtime (dist and debug builds) into your Rails app:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
public/
|
|
56
|
+
picoruby/
|
|
57
|
+
dist/ # production build (smaller, no debug symbols)
|
|
58
|
+
init.iife.js
|
|
59
|
+
picoruby.js
|
|
60
|
+
picoruby.wasm
|
|
61
|
+
debug/ # development build (larger, with debug symbols)
|
|
62
|
+
init.iife.js
|
|
63
|
+
picoruby.js
|
|
64
|
+
picoruby.wasm
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The files in `public/picoruby/` should be added to `.gitignore` and
|
|
68
|
+
re-installed after gem updates.
|
|
69
|
+
|
|
70
|
+
#### `funicular:install:debug_assets`
|
|
71
|
+
|
|
72
|
+
Copies the component highlighter stylesheet and script for development use:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
app/assets/
|
|
76
|
+
javascripts/funicular_debug.js
|
|
77
|
+
stylesheets/funicular_debug.css
|
|
78
|
+
config/initializers/funicular.rb
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The generated `config/initializers/funicular.rb` is the place to configure
|
|
82
|
+
which PicoRuby.wasm source `picoruby_include_tag` uses (see below).
|
|
83
|
+
|
|
84
|
+
### 3. Add the script tag to your layout
|
|
85
|
+
|
|
86
|
+
Replace any hardcoded PicoRuby `<script>` tag with the view helper:
|
|
87
|
+
|
|
88
|
+
```erb
|
|
89
|
+
<%# app/views/layouts/application.html.erb %>
|
|
90
|
+
<head>
|
|
91
|
+
...
|
|
92
|
+
<%= picoruby_include_tag %>
|
|
93
|
+
</head>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`picoruby_include_tag` chooses the right build automatically:
|
|
97
|
+
|
|
98
|
+
| Environment | Default source | Path served |
|
|
99
|
+
|---|---|---|
|
|
100
|
+
| development | `:local_debug` | `/picoruby/debug/init.iife.js` |
|
|
101
|
+
| test | `:local_debug` | `/picoruby/debug/init.iife.js` |
|
|
102
|
+
| production | `:local_dist` | `/picoruby/dist/init.iife.js` |
|
|
103
|
+
|
|
104
|
+
You can override the source per environment in `config/initializers/funicular.rb`:
|
|
105
|
+
|
|
106
|
+
```ruby
|
|
107
|
+
Funicular.configure do |config|
|
|
108
|
+
# Use jsDelivr CDN in production instead of self-hosting:
|
|
109
|
+
config.production_source = :cdn
|
|
110
|
+
|
|
111
|
+
# The CDN version defaults to the @picoruby/wasm-wasi version vendored in
|
|
112
|
+
# the gem. Override only if you need a specific version:
|
|
113
|
+
# config.cdn_version = "4.0.0"
|
|
114
|
+
end
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Available sources:
|
|
118
|
+
|
|
119
|
+
| Value | Description |
|
|
120
|
+
|---|---|
|
|
121
|
+
| `:local_debug` | `public/picoruby/debug/init.iife.js` |
|
|
122
|
+
| `:local_dist` | `public/picoruby/dist/init.iife.js` |
|
|
123
|
+
| `:cdn` | `https://cdn.jsdelivr.net/npm/@picoruby/wasm-wasi@<version>/dist/init.iife.js` |
|
|
124
|
+
|
|
125
|
+
You can also override the source for a single tag:
|
|
126
|
+
|
|
127
|
+
```erb
|
|
128
|
+
<%= picoruby_include_tag source: :cdn %>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### 4. (Optional) Add debug assets to your layout
|
|
132
|
+
|
|
133
|
+
```erb
|
|
134
|
+
<% if Rails.env.development? %>
|
|
135
|
+
<%= javascript_include_tag "funicular_debug", "data-turbo-track": "reload" %>
|
|
136
|
+
<%= stylesheet_link_tag "funicular_debug", "data-turbo-track": "reload" %>
|
|
137
|
+
<% end %>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
See [Component Debug Highlighter](#component-debug-highlighter) for details.
|
|
141
|
+
|
|
142
|
+
## Usage
|
|
143
|
+
|
|
144
|
+
### Directory Structure
|
|
145
|
+
|
|
146
|
+
Place your Funicular application files in the following structure:
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
app/funicular/
|
|
150
|
+
models/ # UI models
|
|
151
|
+
user.rb
|
|
152
|
+
session.rb
|
|
153
|
+
components/ # UI components
|
|
154
|
+
login_component.rb
|
|
155
|
+
chat_component.rb
|
|
156
|
+
initializer.rb # Application initialization (optional)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
The `initializer.rb` file (or any file ending with `_initializer.rb`) is loaded last, after all models and components. Use it for application setup code like routing configuration.
|
|
160
|
+
|
|
161
|
+
### Compilation
|
|
162
|
+
|
|
163
|
+
#### Development Mode
|
|
164
|
+
|
|
165
|
+
In development mode, Funicular automatically recompiles your Ruby files when they change. The compiled bytecode includes debug symbols (-g option).
|
|
166
|
+
|
|
167
|
+
To manually compile:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
bundle exec rake funicular:compile
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Output:
|
|
174
|
+
- File: `app/assets/builds/app.mrb`
|
|
175
|
+
- Debug mode: enabled
|
|
176
|
+
- Size: ~19KB (with debug symbols)
|
|
177
|
+
|
|
178
|
+
The compiled file is placed in `app/assets/builds/` so that Rails asset pipeline (Propshaft) can process it and serve it from `public/assets/` with proper cache busting.
|
|
179
|
+
|
|
180
|
+
#### Production Mode
|
|
181
|
+
|
|
182
|
+
In production mode, compile without debug symbols for smaller file size:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
RAILS_ENV=production bundle exec rake funicular:compile
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Output:
|
|
189
|
+
- File: `app/assets/builds/app.mrb`
|
|
190
|
+
- Debug mode: disabled
|
|
191
|
+
- Size: ~16KB (optimized)
|
|
192
|
+
|
|
193
|
+
The compilation task is automatically run before `assets:precompile` in production deployments.
|
|
194
|
+
|
|
195
|
+
### Loading in Views
|
|
196
|
+
|
|
197
|
+
Include the compiled bytecode in your view using the `asset_path` helper. If you have an `initializer.rb` file, it will execute automatically when the mrb file loads:
|
|
198
|
+
|
|
199
|
+
```erb
|
|
200
|
+
<div id="app"></div>
|
|
201
|
+
|
|
202
|
+
<script type="application/x-mrb" src="<%= asset_path('app.mrb') %>"></script>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
The `asset_path` helper ensures that:
|
|
206
|
+
- In development: The file is served from `app/assets/builds/` via Propshaft
|
|
207
|
+
- In production: The file is served from `public/assets/` with a digest hash for cache busting (e.g., `application-abc123.mrb`)
|
|
208
|
+
|
|
209
|
+
Example `app/funicular/initializer.rb`:
|
|
210
|
+
|
|
211
|
+
```ruby
|
|
212
|
+
puts "Funicular Chat App initializing..."
|
|
213
|
+
|
|
214
|
+
# Load all model schemas before starting the app
|
|
215
|
+
Funicular.load_schemas({ User => "user", Session => "session", Channel => "channel" }) do
|
|
216
|
+
# Start the application after all schemas are loaded
|
|
217
|
+
Funicular.start(container: 'app') do |router|
|
|
218
|
+
router.get('/login', to: LoginComponent, as: 'login')
|
|
219
|
+
router.get('/chat/:channel_id', to: ChatComponent, as: 'chat_channel')
|
|
220
|
+
router.get('/settings', to: SettingsComponent, as: 'settings')
|
|
221
|
+
router.delete('/logout', to: LogoutComponent, as: 'logout')
|
|
222
|
+
router.set_default('/login')
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### File Concatenation Order
|
|
228
|
+
|
|
229
|
+
Funicular concatenates files in the following order:
|
|
230
|
+
|
|
231
|
+
1. `app/funicular/models/**/*.rb` (alphabetically)
|
|
232
|
+
2. `app/funicular/components/**/*.rb` (alphabetically)
|
|
233
|
+
3. `app/funicular/initializer.rb` and `app/funicular/*_initializer.rb`
|
|
234
|
+
|
|
235
|
+
This ensures that:
|
|
236
|
+
- Model classes are defined before components that depend on them
|
|
237
|
+
- Components are defined before initialization code that uses them
|
|
238
|
+
|
|
239
|
+
### Routing
|
|
240
|
+
|
|
241
|
+
Funicular provides Rails-style routing with automatic URL helper generation and RESTful HTTP method support.
|
|
242
|
+
|
|
243
|
+
#### Defining Routes
|
|
244
|
+
|
|
245
|
+
Use Rails-style DSL in your `initializer.rb`:
|
|
246
|
+
|
|
247
|
+
```ruby
|
|
248
|
+
Funicular.start(container: 'app') do |router|
|
|
249
|
+
# GET routes with URL helpers
|
|
250
|
+
router.get('/login', to: LoginComponent, as: 'login')
|
|
251
|
+
router.get('/users/:id', to: UserComponent, as: 'user')
|
|
252
|
+
router.get('/users/:id/edit', to: EditUserComponent, as: 'edit_user')
|
|
253
|
+
|
|
254
|
+
# RESTful routes
|
|
255
|
+
router.post('/users', to: CreateUserComponent, as: 'users')
|
|
256
|
+
router.patch('/users/:id', to: UpdateUserComponent, as: 'update_user')
|
|
257
|
+
router.delete('/users/:id', to: DeleteUserComponent, as: 'delete_user')
|
|
258
|
+
|
|
259
|
+
# Set default route
|
|
260
|
+
router.set_default('/login')
|
|
261
|
+
end
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
The `as` option automatically generates URL helper methods (e.g., `login_path`, `user_path`).
|
|
265
|
+
|
|
266
|
+
#### Using URL Helpers
|
|
267
|
+
|
|
268
|
+
URL helpers are automatically available in all components:
|
|
269
|
+
|
|
270
|
+
```ruby
|
|
271
|
+
class UserListComponent < Funicular::Component
|
|
272
|
+
def render
|
|
273
|
+
div do
|
|
274
|
+
# Static path
|
|
275
|
+
link_to login_path do
|
|
276
|
+
span { "Login" }
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Path with parameter from state/props
|
|
280
|
+
state.users.each do |user|
|
|
281
|
+
link_to user_path(user.id) do
|
|
282
|
+
span { user.name }
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# Or pass model object with id method
|
|
287
|
+
link_to edit_user_path(state.current_user) do
|
|
288
|
+
span { "Edit Profile" }
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
#### Using link_to Helper
|
|
296
|
+
|
|
297
|
+
The `link_to` helper creates navigation links with automatic routing:
|
|
298
|
+
|
|
299
|
+
```ruby
|
|
300
|
+
# GET navigation (uses History API)
|
|
301
|
+
link_to settings_path, class: "button" do
|
|
302
|
+
span { "Settings" }
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
# Path with dynamic data
|
|
306
|
+
link_to chat_channel_path(props[:channel]) do
|
|
307
|
+
div(class: "channel-name") { "# #{props[:channel].name}" }
|
|
308
|
+
div(class: "channel-desc") { props[:channel].description }
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# RESTful actions (uses Fetch API)
|
|
312
|
+
link_to user_path(state.user), method: :delete, class: "danger" do
|
|
313
|
+
span { "Delete Account" }
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
# Supported HTTP methods: :get, :post, :put, :patch, :delete
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
#### CSRF Protection
|
|
320
|
+
|
|
321
|
+
Non-GET requests automatically include CSRF tokens from Rails meta tags:
|
|
322
|
+
|
|
323
|
+
```erb
|
|
324
|
+
<!-- In your Rails layout -->
|
|
325
|
+
<head>
|
|
326
|
+
<%= csrf_meta_tags %>
|
|
327
|
+
</head>
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Funicular automatically reads the CSRF token and includes it in `X-CSRF-Token` header for POST, PUT, PATCH, and DELETE requests.
|
|
331
|
+
|
|
332
|
+
#### Viewing Routes
|
|
333
|
+
|
|
334
|
+
Display all defined routes with the Rake task:
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
rake funicular:routes
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Output example:
|
|
341
|
+
|
|
342
|
+
```
|
|
343
|
+
Method Path Component Helper
|
|
344
|
+
----------------------------------------------------------
|
|
345
|
+
GET /login LoginComponent login_path
|
|
346
|
+
GET /chat/:channel_id ChatComponent chat_channel_path
|
|
347
|
+
GET /settings SettingsComponent settings_path
|
|
348
|
+
DELETE /logout LogoutComponent logout_path
|
|
349
|
+
|
|
350
|
+
Total: 4 routes
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
#### Backward Compatibility
|
|
354
|
+
|
|
355
|
+
The old `add_route` method is still supported:
|
|
356
|
+
|
|
357
|
+
```ruby
|
|
358
|
+
# Old style (still works)
|
|
359
|
+
router.add_route('/login', LoginComponent)
|
|
360
|
+
|
|
361
|
+
# With URL helper
|
|
362
|
+
router.add_route('/login', LoginComponent, as: 'login')
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## Rails Asset Pipeline Integration
|
|
366
|
+
|
|
367
|
+
Funicular integrates with Rails' asset pipeline (Propshaft) following Rails best practices:
|
|
368
|
+
|
|
369
|
+
### Directory Structure
|
|
370
|
+
|
|
371
|
+
```
|
|
372
|
+
app/
|
|
373
|
+
funicular/ # Source files (version controlled)
|
|
374
|
+
models/
|
|
375
|
+
components/
|
|
376
|
+
initializer.rb
|
|
377
|
+
assets/
|
|
378
|
+
builds/ # Compiled output (gitignored)
|
|
379
|
+
app.mrb # Generated by funicular:compile
|
|
380
|
+
.keep # Keep directory in git
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Development vs Production
|
|
384
|
+
|
|
385
|
+
**Development:**
|
|
386
|
+
- Files in `app/assets/builds/` are served directly by Propshaft
|
|
387
|
+
- Middleware automatically recompiles when source files change
|
|
388
|
+
- Debug symbols included for better error messages
|
|
389
|
+
|
|
390
|
+
**Production:**
|
|
391
|
+
- `rake assets:precompile` runs `funicular:compile` first
|
|
392
|
+
- Propshaft copies files to `public/assets/` with digest hashes
|
|
393
|
+
- Example: `app.mrb` -> `app-abc123def456.mrb`
|
|
394
|
+
- Debug symbols excluded for smaller file size
|
|
395
|
+
|
|
396
|
+
### Cache Busting
|
|
397
|
+
|
|
398
|
+
Using `asset_path('app.mrb')` in views ensures:
|
|
399
|
+
- Correct path resolution in all environments
|
|
400
|
+
- Automatic cache busting when files change
|
|
401
|
+
- Standard Rails asset handling
|
|
402
|
+
|
|
403
|
+
## Development Tools
|
|
404
|
+
|
|
405
|
+
### Component Debug Highlighter
|
|
406
|
+
|
|
407
|
+
Funicular provides a debug tool that visually highlights components with `data-component` attributes in development mode.
|
|
408
|
+
|
|
409
|
+
`funicular:install` (or `funicular:install:debug_assets`) copies the
|
|
410
|
+
required files and adds them to your layout as shown in [Installation](#installation).
|
|
411
|
+
|
|
412
|
+
#### Features
|
|
413
|
+
|
|
414
|
+
In development mode, components automatically get `data-component` attributes with their class name. The debug tool:
|
|
415
|
+
|
|
416
|
+
- Highlights components with a green/yellow/pink/cyan outline
|
|
417
|
+
```ruby
|
|
418
|
+
# in app/funicular/initializer.rb
|
|
419
|
+
Funicular.debug_color = "pink" # Options: "green", "yellow", "pink", "cyan", or nil to disable
|
|
420
|
+
```
|
|
421
|
+
- Shows a triangle indicator in the bottom-right corner
|
|
422
|
+
- Displays component name and id value (if exists) on hover
|
|
423
|
+
- Does not distort layout (uses `outline` instead of `border`)
|
|
424
|
+
|
|
425
|
+
This helps developers quickly identify which component class renders each part of the UI.
|
|
426
|
+
|