@rip-lang/ui 0.3.9 → 0.3.11

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.
package/README.md CHANGED
@@ -75,6 +75,55 @@ export About = component
75
75
  Reactive props via `:=` signal passthrough. Readonly props via `=!`.
76
76
  Children blocks passed as DOM nodes via `@children`.
77
77
 
78
+ ## Props — The `@` Contract
79
+
80
+ The `@` prefix on a member declaration marks it as a **public prop** — settable
81
+ by a parent component. Members without `@` are **private state** and ignore
82
+ any value a parent tries to pass in.
83
+
84
+ ```coffee
85
+ export Drawer = component
86
+ @open := false # public — parent can pass `open: true`
87
+ @breakpoint := 480 # public — parent can pass `breakpoint: 768`
88
+ isRight := false # private — always starts as false
89
+ closing := false # private — always starts as false
90
+
91
+ render
92
+ if open
93
+ div "Drawer is open"
94
+ ```
95
+
96
+ The compiler enforces the boundary:
97
+
98
+ ```javascript
99
+ // @open := false → accepts parent value
100
+ this.open = __state(props.open ?? false);
101
+
102
+ // isRight := false → ignores parent, always uses default
103
+ this.isRight = __state(false);
104
+ ```
105
+
106
+ This works for all member types:
107
+
108
+ | Declaration | Visibility | Meaning |
109
+ |-------------|-----------|---------|
110
+ | `@title := 'Hello'` | Public | Reactive state, settable by parent |
111
+ | `@label =! 'Default'` | Public | Readonly prop, settable by parent |
112
+ | `count := 0` | Private | Reactive state, internal only |
113
+ | `cache =! null` | Private | Readonly, internal only |
114
+ | `total ~= items.length` | — | Computed (always derived, never a prop) |
115
+
116
+ A parent passes props as key-value pairs when using a component:
117
+
118
+ ```coffee
119
+ Drawer open: showDrawer, breakpoint: 768
120
+ div "Content here"
121
+ ```
122
+
123
+ The `@` declarations at the top of a component are its public API. Everything
124
+ else is an implementation detail. No separate type files, no prop validation
125
+ boilerplate — one character that says "this is settable from outside."
126
+
78
127
  ## Render Block Syntax
79
128
 
80
129
  Inside a `render` block, elements are declared by tag name. Classes, attributes,
@@ -160,7 +209,8 @@ The browser loads one file — `rip-ui.min.js` (~52KB Brotli) — which bundles
160
209
  Rip compiler and the pre-compiled UI framework. No runtime compilation of the
161
210
  framework, no extra network requests.
162
211
 
163
- Then `launch()` fetches the app bundle, hydrates the stash, and renders.
212
+ Then `launch()` loads component sources (from a server bundle, static files, or
213
+ inline DOM), hydrates the stash, and renders.
164
214
 
165
215
  ### Browser Execution Contexts
166
216
 
@@ -228,6 +278,66 @@ maps them into a flat `components/` namespace in the bundle — pages go
228
278
  under `components/`, shared components under `components/_lib/`. The `_`
229
279
  prefix tells the router to skip `_lib/` entries when generating routes.
230
280
 
281
+ ## Component Loading Modes
282
+
283
+ `launch()` supports three ways to load component sources, checked in priority
284
+ order. All three produce the same internal bundle format — everything downstream
285
+ (compilation, routing, rendering) works identically regardless of source.
286
+
287
+ ### 1. Static File URLs — `launch components: [...]`
288
+
289
+ Fetch individual `.rip` files as plain text from any static server:
290
+
291
+ ```coffee
292
+ launch components: [
293
+ 'components/index.rip'
294
+ 'components/dashboard.rip'
295
+ 'components/line-chart.rip'
296
+ ]
297
+ ```
298
+
299
+ No server middleware needed. Serve `.rip` files as static text from any HTTP
300
+ server, CDN, or `file://` path. Each URL is fetched individually and compiled
301
+ in the browser.
302
+
303
+ ### 2. Inline DOM — `<script type="text/rip" data-name="...">`
304
+
305
+ Embed component source directly in the HTML page:
306
+
307
+ ```html
308
+ <script type="text/rip" data-name="index">
309
+ export Home = component
310
+ render
311
+ h1 "Hello from inline"
312
+ </script>
313
+
314
+ <script type="text/rip" data-name="counter">
315
+ export Counter = component
316
+ @count := 0
317
+ render
318
+ button @click: (-> count += 1), "#{count}"
319
+ </script>
320
+
321
+ <script type="text/rip">
322
+ { launch } = importRip! '/rip/ui.rip'
323
+ launch()
324
+ </script>
325
+ ```
326
+
327
+ The `data-name` attribute maps to the component filename (`.rip` extension is
328
+ added automatically if omitted). Scripts with `data-name` are collected as
329
+ component sources and are not executed as top-level code.
330
+
331
+ ### 3. Server Bundle (default)
332
+
333
+ When neither `components` nor inline `data-name` scripts are present, `launch()`
334
+ fetches the app bundle from the server at `/{app}/bundle`. This is the default
335
+ mode when using the `ripUI` server middleware.
336
+
337
+ ```coffee
338
+ launch() # fetches /bundle automatically
339
+ ```
340
+
231
341
  ## Server Middleware
232
342
 
233
343
  The `ripUI` middleware registers routes for the framework files, the app
@@ -359,12 +469,46 @@ launch '/app', hash: true
359
469
  This switches from `/about` to `page.html#/about`. Back/forward navigation,
360
470
  direct URL loading, and `href="#/path"` links all work correctly.
361
471
 
362
- ## Static Deployment — `launch bundle:`
472
+ ## Static Deployment
473
+
474
+ For zero-server deployment, use inline `data-name` scripts or a `components`
475
+ URL list. Both work with `rip-ui.min.js` (~52KB Brotli) from a CDN — no
476
+ server middleware needed.
477
+
478
+ **Inline mode** — everything in one HTML file:
479
+
480
+ ```html
481
+ <script type="module" src="dist/rip-ui.min.js"></script>
482
+
483
+ <script type="text/rip" data-name="index">
484
+ export Home = component
485
+ render
486
+ h1 "Hello"
487
+ </script>
488
+
489
+ <script type="text/rip" data-name="about">
490
+ export About = component
491
+ render
492
+ h1 "About"
493
+ </script>
494
+
495
+ <script type="text/rip">
496
+ { launch } = importRip! 'ui.rip'
497
+ launch hash: true
498
+ </script>
499
+ ```
500
+
501
+ **Static files mode** — `.rip` files served from any HTTP server or CDN:
502
+
503
+ ```html
504
+ <script type="module" src="dist/rip-ui.min.js"></script>
505
+ <script type="text/rip">
506
+ { launch } = importRip! 'ui.rip'
507
+ launch components: ['components/index.rip', 'components/about.rip'], hash: true
508
+ </script>
509
+ ```
363
510
 
364
- Inline all components in a single HTML file for zero-server deployment.
365
- Use `rip-ui.min.js` (~52KB Brotli) — a combined bundle with the compiler
366
- and pre-compiled UI framework. No extra network requests, no runtime
367
- compilation of the framework:
511
+ **Explicit bundle** pass a bundle object directly:
368
512
 
369
513
  ```html
370
514
  <script type="module" src="dist/rip-ui.min.js"></script>