plushie 0.5.0 → 0.6.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/.yardopts +1 -1
- data/AGENTS.md +595 -0
- data/CHANGELOG.md +147 -3
- data/CLAUDE.md +1 -0
- data/README.md +93 -227
- data/Steepfile +46 -2
- data/docs/README.md +56 -0
- data/docs/guides/01-introduction.md +266 -0
- data/docs/guides/02-getting-started.md +472 -0
- data/docs/guides/03-your-first-app.md +516 -0
- data/docs/guides/04-the-development-loop.md +499 -0
- data/docs/guides/05-events.md +548 -0
- data/docs/guides/06-lists-and-inputs.md +605 -0
- data/docs/guides/07-layout.md +530 -0
- data/docs/guides/08-styling.md +599 -0
- data/docs/guides/09-animation.md +516 -0
- data/docs/guides/10-subscriptions.md +470 -0
- data/docs/guides/11-async-and-effects.md +531 -0
- data/docs/guides/12-canvas.md +583 -0
- data/docs/guides/13-custom-widgets.md +705 -0
- data/docs/guides/14-state-management.md +600 -0
- data/docs/guides/15-testing.md +649 -0
- data/docs/guides/16-shared-state.md +567 -0
- data/docs/guides/17-packaging.md +549 -0
- data/docs/reference/accessibility.md +420 -0
- data/docs/reference/animation.md +482 -0
- data/docs/reference/app-lifecycle.md +504 -0
- data/docs/reference/built-in-widgets.md +702 -0
- data/docs/reference/canvas.md +589 -0
- data/docs/reference/commands.md +376 -0
- data/docs/reference/composition-patterns.md +816 -0
- data/docs/reference/configuration.md +302 -0
- data/docs/reference/custom-types.md +203 -0
- data/docs/reference/custom-widgets.md +681 -0
- data/docs/reference/dsl.md +500 -0
- data/docs/reference/events.md +596 -0
- data/docs/reference/native-extension.md +636 -0
- data/docs/reference/rake-tasks.md +440 -0
- data/docs/reference/scoped-ids.md +336 -0
- data/docs/reference/subscriptions.md +248 -0
- data/docs/reference/testing.md +448 -0
- data/docs/reference/themes-and-styling.md +511 -0
- data/docs/reference/versioning.md +174 -0
- data/docs/reference/windows-and-layout.md +692 -0
- data/docs/reference/wire-protocol.md +328 -0
- data/docs/stewardship/README.md +109 -0
- data/docs/stewardship/concurrency-shape.md +208 -0
- data/docs/stewardship/dsl-discipline.md +204 -0
- data/docs/stewardship/elm-invariants.md +196 -0
- data/docs/stewardship/goals-and-non-goals.md +95 -0
- data/docs/stewardship/performance-bar.md +157 -0
- data/docs/stewardship/posture.md +118 -0
- data/docs/stewardship/resilience.md +159 -0
- data/docs/stewardship/roadmap/README.md +20 -0
- data/docs/stewardship/simplicity.md +182 -0
- data/docs/stewardship/test-discipline.md +154 -0
- data/docs/stewardship/triage.md +153 -0
- data/docs/stewardship/trust-model.md +112 -0
- data/examples/README.md +2 -2
- data/examples/async_fetch.rb +2 -2
- data/examples/color_picker.rb +19 -69
- data/examples/counter.rb +4 -4
- data/examples/notes.rb +2 -2
- data/examples/rate_plushie.rb +135 -103
- data/examples/shortcuts.rb +1 -1
- data/examples/widgets/color_picker_widget.rb +254 -27
- data/examples/widgets/star_rating.rb +90 -44
- data/examples/widgets/theme_toggle.rb +79 -33
- data/lib/plushie/animation/sequence.rb +58 -0
- data/lib/plushie/animation/spring.rb +88 -0
- data/lib/plushie/animation/transition.rb +86 -0
- data/lib/plushie/animation/tween.rb +264 -0
- data/lib/plushie/animation.rb +19 -239
- data/lib/plushie/app.rb +8 -1
- data/lib/plushie/binary.rb +45 -10
- data/lib/plushie/bounded_queue.rb +32 -0
- data/lib/plushie/bridge.rb +148 -34
- data/lib/plushie/canvas/shape/group.rb +17 -1
- data/lib/plushie/canvas/shape/rect.rb +7 -2
- data/lib/plushie/canvas/shape/transform.rb +4 -2
- data/lib/plushie/canvas/shape.rb +19 -2
- data/lib/plushie/canvas_widget.rb +508 -0
- data/lib/plushie/cargo_plushie.rb +121 -0
- data/lib/plushie/command/image.rb +78 -0
- data/lib/plushie/command/scroll.rb +51 -0
- data/lib/plushie/command/text.rb +55 -0
- data/lib/plushie/command/window.rb +146 -0
- data/lib/plushie/command/window_query.rb +54 -0
- data/lib/plushie/command.rb +194 -297
- data/lib/plushie/connection.rb +68 -15
- data/lib/plushie/dev_server.rb +35 -8
- data/lib/plushie/effect.rb +170 -0
- data/lib/plushie/encode.rb +32 -12
- data/lib/plushie/event/diagnostic.rb +221 -0
- data/lib/plushie/event/specs.rb +211 -0
- data/lib/plushie/event.rb +253 -162
- data/lib/plushie/key_modifiers.rb +5 -5
- data/lib/plushie/node.rb +9 -5
- data/lib/plushie/protocol/decode.rb +624 -209
- data/lib/plushie/protocol/encode.rb +141 -43
- data/lib/plushie/protocol.rb +3 -3
- data/lib/plushie/rake.rb +69 -62
- data/lib/plushie/renderer_env.rb +14 -5
- data/lib/plushie/renderer_exit.rb +41 -0
- data/lib/plushie/runtime/commands.rb +150 -39
- data/lib/plushie/runtime/subscriptions.rb +34 -17
- data/lib/plushie/runtime/windows.rb +178 -0
- data/lib/plushie/runtime.rb +1076 -73
- data/lib/plushie/selection.rb +4 -4
- data/lib/plushie/subscription.rb +101 -90
- data/lib/plushie/test/case.rb +2 -1
- data/lib/plushie/test/helpers.rb +170 -10
- data/lib/plushie/test/script.rb +1 -1
- data/lib/plushie/test/session.rb +272 -58
- data/lib/plushie/test/session_pool.rb +27 -11
- data/lib/plushie/test/snapshot.rb +18 -0
- data/lib/plushie/test.rb +0 -1
- data/lib/plushie/thread_pool.rb +1 -1
- data/lib/plushie/timer_scheduler.rb +103 -0
- data/lib/plushie/transport/framing.rb +40 -1
- data/lib/plushie/transport/tcp_adapter.rb +7 -0
- data/lib/plushie/tree/diff.rb +208 -0
- data/lib/plushie/tree/search.rb +98 -0
- data/lib/plushie/tree.rb +684 -170
- data/lib/plushie/type/a11y.rb +17 -2
- data/lib/plushie/type/alignment.rb +4 -4
- data/lib/plushie/type/border.rb +16 -1
- data/lib/plushie/type/color.rb +1 -1
- data/lib/plushie/type/font.rb +5 -9
- data/lib/plushie/type/gradient.rb +47 -10
- data/lib/plushie/type/line_height.rb +42 -0
- data/lib/plushie/type/padding.rb +21 -14
- data/lib/plushie/type/style_map.rb +9 -9
- data/lib/plushie/type/theme.rb +71 -0
- data/lib/plushie/ui.rb +222 -156
- data/lib/plushie/undo.rb +46 -12
- data/lib/plushie/version.rb +6 -3
- data/lib/plushie/widget/build.rb +67 -6
- data/lib/plushie/widget/button.rb +9 -52
- data/lib/plushie/widget/canvas.rb +28 -58
- data/lib/plushie/widget/checkbox.rb +26 -45
- data/lib/plushie/widget/column.rb +5 -41
- data/lib/plushie/widget/combo_box.rb +27 -55
- data/lib/plushie/widget/container.rb +11 -49
- data/lib/plushie/widget/floating.rb +10 -47
- data/lib/plushie/widget/grid.rb +14 -52
- data/lib/plushie/widget/image.rb +23 -50
- data/lib/plushie/widget/keyed_column.rb +10 -47
- data/lib/plushie/widget/markdown.rb +18 -47
- data/lib/plushie/widget/native_build.rb +333 -0
- data/lib/plushie/widget/overlay.rb +12 -49
- data/lib/plushie/widget/pane_grid.rb +15 -52
- data/lib/plushie/widget/pick_list.rb +26 -54
- data/lib/plushie/widget/pin.rb +9 -46
- data/lib/plushie/widget/pointer_area.rb +38 -0
- data/lib/plushie/widget/progress_bar.rb +15 -46
- data/lib/plushie/widget/qr_code.rb +15 -44
- data/lib/plushie/widget/radio.rb +22 -53
- data/lib/plushie/widget/responsive.rb +7 -44
- data/lib/plushie/widget/rich_text.rb +68 -35
- data/lib/plushie/widget/row.rb +5 -41
- data/lib/plushie/widget/rule.rb +10 -36
- data/lib/plushie/widget/scrollable.rb +20 -59
- data/lib/plushie/widget/sensor.rb +8 -46
- data/lib/plushie/widget/slider.rb +22 -53
- data/lib/plushie/widget/space.rb +7 -35
- data/lib/plushie/widget/stack.rb +8 -45
- data/lib/plushie/widget/svg.rb +18 -47
- data/lib/plushie/widget/table.rb +62 -54
- data/lib/plushie/widget/text.rb +7 -44
- data/lib/plushie/widget/text_editor.rb +28 -54
- data/lib/plushie/widget/text_input.rb +9 -41
- data/lib/plushie/widget/themer.rb +7 -46
- data/lib/plushie/widget/toggler.rb +22 -50
- data/lib/plushie/widget/tooltip.rb +15 -53
- data/lib/plushie/widget/vertical_slider.rb +20 -52
- data/lib/plushie/widget/window.rb +13 -43
- data/lib/plushie/widget.rb +760 -0
- data/lib/plushie/widget_set.rb +82 -0
- data/lib/plushie.rb +45 -17
- data/sig/base64.rbs +6 -0
- data/sig/msgpack.rbs +13 -0
- data/sig/plushie/animation.rbs +74 -33
- data/sig/plushie/app.rbs +1 -1
- data/sig/plushie/bounded_queue.rbs +13 -0
- data/sig/plushie/bridge.rbs +14 -4
- data/sig/plushie/canvas/shape.rbs +3 -2
- data/sig/plushie/canvas_widget.rbs +55 -0
- data/sig/plushie/cargo_plushie.rbs +11 -0
- data/sig/plushie/command/image.rbs +11 -0
- data/sig/plushie/command/scroll.rbs +10 -0
- data/sig/plushie/command/text.rbs +11 -0
- data/sig/plushie/command/window.rbs +29 -0
- data/sig/plushie/command/window_query.rbs +14 -0
- data/sig/plushie/command.rbs +32 -42
- data/sig/plushie/effect.rbs +31 -0
- data/sig/plushie/encode.rbs +5 -0
- data/sig/plushie/event.rbs +170 -86
- data/sig/plushie/key_modifiers.rbs +1 -0
- data/sig/plushie/node.rbs +9 -2
- data/sig/plushie/protocol.rbs +58 -6
- data/sig/plushie/route.rbs +2 -2
- data/sig/plushie/runtime/windows.rbs +32 -0
- data/sig/plushie/runtime.rbs +100 -6
- data/sig/plushie/subscription.rbs +24 -20
- data/sig/plushie/timer_scheduler.rbs +19 -0
- data/sig/plushie/tree/diff.rbs +13 -0
- data/sig/plushie/tree/search.rbs +12 -0
- data/sig/plushie/tree.rbs +44 -3
- data/sig/plushie/type/a11y.rbs +44 -0
- data/sig/plushie/type/font.rbs +23 -0
- data/sig/plushie/type/gradient.rbs +9 -0
- data/sig/plushie/type/line_height.rbs +10 -0
- data/sig/plushie/ui.rbs +9 -1
- data/sig/plushie/undo.rbs +14 -6
- data/sig/plushie/widget/build.rbs +18 -0
- data/sig/plushie/widget_dsl.rbs +47 -0
- data/sig/plushie/widget_set.rbs +5 -0
- data/sig/plushie.rbs +17 -1
- metadata +104 -26
- data/docs/accessibility.md +0 -489
- data/docs/app-behaviour.md +0 -614
- data/docs/commands.md +0 -882
- data/docs/composition-patterns.md +0 -1037
- data/docs/dsl-internals.md +0 -343
- data/docs/effects.md +0 -108
- data/docs/events.md +0 -653
- data/docs/extensions.md +0 -1791
- data/docs/getting-started.md +0 -237
- data/docs/layout.md +0 -266
- data/docs/running.md +0 -356
- data/docs/scoped-ids.md +0 -200
- data/docs/testing.md +0 -844
- data/docs/theming.md +0 -292
- data/docs/tutorial.md +0 -369
- data/examples/catalog.rb +0 -448
- data/lib/plushie/effects.rb +0 -169
- data/lib/plushie/extension/build.rb +0 -293
- data/lib/plushie/extension.rb +0 -339
- data/lib/plushie/test/event_decoder.rb +0 -118
- data/lib/plushie/widget/mouse_area.rb +0 -72
- data/sig/plushie/effects.rbs +0 -31
- data/sig/plushie/extension.rbs +0 -40
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,150 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
6
6
|
|
|
7
|
+
## [0.6.0] - 2026-05-09
|
|
8
|
+
|
|
9
|
+
Targets plushie-renderer 0.7.1.
|
|
10
|
+
|
|
11
|
+
### Breaking changes
|
|
12
|
+
|
|
13
|
+
- Environment variable `PLUSHIE_SOURCE_PATH` renamed to
|
|
14
|
+
`PLUSHIE_RUST_SOURCE_PATH`. Update shell profiles and CI configs.
|
|
15
|
+
- Constant `Plushie::BINARY_VERSION` renamed to
|
|
16
|
+
`Plushie::PLUSHIE_RUST_VERSION` to match the plushie-rust release
|
|
17
|
+
identifier. Anything referencing the old name needs updating.
|
|
18
|
+
- `Command.async` renamed to `Command.task` for cross-SDK consistency
|
|
19
|
+
(`async` is reserved in Python and Rust). `Command.done` renamed to
|
|
20
|
+
`Command.dispatch` to reflect the "send through update" semantic.
|
|
21
|
+
`Command.widget_commands` renamed to `Command.widget_batch` to match
|
|
22
|
+
the Elixir SDK and disambiguate from the `Plushie::Command` type.
|
|
23
|
+
- Grid widget `columns` prop renamed to `num_columns`.
|
|
24
|
+
- `Command.Image.create_image` and `update_image` no longer accept
|
|
25
|
+
`pixels:`, `width:`, `height:` keyword arguments for raw RGBA data.
|
|
26
|
+
Use the new dedicated `create_image_rgba(handle, width, height, pixels)`
|
|
27
|
+
and `update_image_rgba(handle, width, height, pixels)` constructors
|
|
28
|
+
instead. The blob-data form of `create_image` and `update_image`
|
|
29
|
+
(passing raw binary data directly) is unchanged.
|
|
30
|
+
- Table widget `:selected` and `:striped` props removed; they were
|
|
31
|
+
dead code with no renderer-side effect.
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- `Plushie::CargoPlushie.resolve` helper that locates a usable
|
|
36
|
+
cargo-plushie via `PLUSHIE_RUST_SOURCE_PATH`, falling back to a
|
|
37
|
+
version-matched binary on `PATH`, otherwise raising with
|
|
38
|
+
`cargo install cargo-plushie --version <version> --locked`
|
|
39
|
+
guidance.
|
|
40
|
+
- `docs/versioning.md` documenting the `PLUSHIE_RUST_VERSION` pin and
|
|
41
|
+
SDK-vs-plushie-rust versioning rules.
|
|
42
|
+
- `Event::SessionError` and `Event::SessionClosed` typed variants.
|
|
43
|
+
`SessionError` includes a `code` field carrying the numeric error code
|
|
44
|
+
from the renderer.
|
|
45
|
+
- `Event::Diagnostic` typed variants: `crash`, `update_panicked`,
|
|
46
|
+
`renderer_error`, `protocol_error`, and `unknown`. Previously all
|
|
47
|
+
diagnostics arrived as the generic `Diagnostic` struct; each kind
|
|
48
|
+
now has its own Data class with kind-specific fields.
|
|
49
|
+
- `Plushie::BufferOverflowError` and `Plushie::ProtocolVersionMismatchError`
|
|
50
|
+
typed error classes raised on the matching renderer-side conditions.
|
|
51
|
+
- `Event::Effect` typed per-kind result variants. Effect callbacks now
|
|
52
|
+
receive a typed struct rather than a raw Hash.
|
|
53
|
+
- `RichText::Span` typed Data class for inline text spans.
|
|
54
|
+
- `link_click` events decoded as a typed `:link_click` variant on
|
|
55
|
+
`Event::Widget`.
|
|
56
|
+
- Touch release events carry a `lost` flag when the pointer left the
|
|
57
|
+
window before the release.
|
|
58
|
+
- `Rule` widget `thickness` prop as a direction-agnostic alternative to
|
|
59
|
+
the existing `width`/`height` split.
|
|
60
|
+
- SDK-side event coalescing: high-frequency events declared coalesable
|
|
61
|
+
are deduplicated in the bounded queue before reaching `update`.
|
|
62
|
+
- `Command.dispatch` chain depth is now capped; dispatching beyond the
|
|
63
|
+
limit raises rather than looping indefinitely.
|
|
64
|
+
- `Binary.resolve` falls back to a locally built renderer binary under
|
|
65
|
+
`../plushie-rust/target/{release,debug}/plushie-renderer` when
|
|
66
|
+
`PLUSHIE_RUST_SOURCE_PATH` is set and no explicit path is configured.
|
|
67
|
+
- `rake plushie:preflight` rebuilds the renderer binary from the local
|
|
68
|
+
plushie-rust checkout when `PLUSHIE_RUST_SOURCE_PATH` is set.
|
|
69
|
+
- Negative padding, border width, and border radius values are now
|
|
70
|
+
rejected at build time with an `ArgumentError`.
|
|
71
|
+
|
|
72
|
+
### Fixed
|
|
73
|
+
|
|
74
|
+
- Subscription `key_press` and `key_release` events now read the
|
|
75
|
+
structured key payload (`key`, `modified_key`, `physical_key`,
|
|
76
|
+
`location`, `text`, `repeat`) from the `value` field. The previous
|
|
77
|
+
fallback to top-level message fields read modifiers from the wrong
|
|
78
|
+
location when value was non-Hash and would silently misread future
|
|
79
|
+
shape changes.
|
|
80
|
+
- `animation_frame` and `theme_changed` no longer carry dead fallback
|
|
81
|
+
reads alongside the canonical `value` access; the fallbacks could
|
|
82
|
+
never fire against the real renderer and masked the intended source
|
|
83
|
+
field.
|
|
84
|
+
- `ime_preedit` and `ime_commit` now raise `ArgumentError` when the
|
|
85
|
+
`value` payload is missing or non-Hash, surfacing wire-shape drift
|
|
86
|
+
instead of producing an `Event::Ime` with nil text and cursor.
|
|
87
|
+
- Concurrency bugs in the runtime, bridge, and session pool: a race in
|
|
88
|
+
the timer scheduler, a missing mutex on effect-kind state, and a
|
|
89
|
+
session-pool drain condition that could deadlock under session churn.
|
|
90
|
+
- Cancelled async threads are now properly released; previously a
|
|
91
|
+
cancelled task could hold its thread until the pool was torn down.
|
|
92
|
+
- Effect cancellation events are dispatched to `update` during SDK
|
|
93
|
+
shutdown so apps can clean up transient state.
|
|
94
|
+
- `image_list` and `image_clear` now route through the typed `image_op`
|
|
95
|
+
wire channel rather than a generic command envelope.
|
|
96
|
+
- `default_font` is always encoded as a `{ family: ... }` object; the
|
|
97
|
+
previous path emitted a bare string that the renderer rejected.
|
|
98
|
+
- `window_opened` position fields are now read from top-level `x`/`y`
|
|
99
|
+
keys as the protocol specifies; the previous path read from a nested
|
|
100
|
+
`position` map that does not exist.
|
|
101
|
+
- Effect tag supersession correctly clears the effect-kinds index when
|
|
102
|
+
a new registration replaces an existing one under the same tag.
|
|
103
|
+
- Unknown event families tolerate a missing `window_id` field instead
|
|
104
|
+
of raising a `KeyError`.
|
|
105
|
+
- Wayland-specific environment variables are now forwarded to the
|
|
106
|
+
renderer subprocess.
|
|
107
|
+
- `Plushie.configure { |c| c.log_level = ... }` is now honoured; the
|
|
108
|
+
previous path set the logger level only on the initial connection,
|
|
109
|
+
which was overwritten on restart.
|
|
110
|
+
- Renderer build lookup no longer raises on a missing `_build` directory;
|
|
111
|
+
it falls through to the next resolution step.
|
|
112
|
+
- Runtime event queue is bounded; a stalled app no longer causes
|
|
113
|
+
unbounded memory growth under high-frequency event sources.
|
|
114
|
+
- Widget state callbacks are no longer inherited across unrelated widget
|
|
115
|
+
subclasses defined with `Widget.define`.
|
|
116
|
+
- Effects are cancelled and their callbacks suppressed when the SDK
|
|
117
|
+
shuts down.
|
|
118
|
+
- Timeout error messages include the action and selector for easier
|
|
119
|
+
diagnosis in test output.
|
|
120
|
+
- Widget set override names are validated to prevent accidental
|
|
121
|
+
shadowing of built-in DSL methods.
|
|
122
|
+
- Renderer exit details are sanitised before appearing in error messages
|
|
123
|
+
and logs.
|
|
124
|
+
|
|
125
|
+
### Changed
|
|
126
|
+
|
|
127
|
+
- Native widget builds now delegate workspace generation and
|
|
128
|
+
`cargo build` to [cargo-plushie](https://crates.io/crates/cargo-plushie).
|
|
129
|
+
The Ruby SDK writes a minimal virtual app manifest under
|
|
130
|
+
`_build/plushie-renderer-spec/` and shells out to
|
|
131
|
+
`cargo plushie build`. Widget discovery, [patch.crates-io] forwarding,
|
|
132
|
+
collision checks, and constructor validation now live in
|
|
133
|
+
cargo-plushie and are shared across host SDKs.
|
|
134
|
+
- Native widget crates must now declare
|
|
135
|
+
`[package.metadata.plushie.widget] { type_name, constructor }` in
|
|
136
|
+
their Cargo.toml. cargo-plushie uses that table for discovery.
|
|
137
|
+
- Renderer subprocess environment is now filtered to variables with a
|
|
138
|
+
`PLUSHIE_` prefix plus a small display-server allowlist. Previously
|
|
139
|
+
the full shell environment was forwarded.
|
|
140
|
+
- Per-timer threads replaced with a single `TimerScheduler` thread
|
|
141
|
+
using deadline-based `IO.select`. Timer count no longer scales the
|
|
142
|
+
thread count.
|
|
143
|
+
- Renderer restart backoff parameters, nil-view handling, and frozen
|
|
144
|
+
overlay semantics aligned with the Elixir and other SDKs.
|
|
145
|
+
|
|
146
|
+
### Removed
|
|
147
|
+
|
|
148
|
+
- The checked-in `native/plushie/Cargo.lock` stash. cargo-plushie
|
|
149
|
+
manages the scratch workspace's lock file.
|
|
150
|
+
|
|
7
151
|
## [0.5.0] - 2026-03-23
|
|
8
152
|
|
|
9
153
|
Initial release. Targets plushie-renderer 0.5.0.
|
|
@@ -35,9 +179,9 @@ Initial release. Targets plushie-renderer 0.5.0.
|
|
|
35
179
|
generates Cargo workspace, validates crate paths and constructors,
|
|
36
180
|
detects type name and crate collisions, builds custom renderer binary
|
|
37
181
|
- `Plushie.configure` block for SDK-wide configuration: `binary_path`,
|
|
38
|
-
`source_path`, `build_name`, `
|
|
182
|
+
`source_path`, `build_name`, `widgets`, `widget_config`,
|
|
39
183
|
`test_backend`
|
|
40
|
-
- `
|
|
184
|
+
- `widget_config` runtime configuration passed to native widgets
|
|
41
185
|
via the Settings wire message and `InitCtx`
|
|
42
186
|
- WASM renderer download via `rake plushie:download[wasm]`
|
|
43
187
|
- `PLUSHIE_BIN_FILE` and `PLUSHIE_WASM_DIR` env vars for overriding
|
|
@@ -54,7 +198,7 @@ Initial release. Targets plushie-renderer 0.5.0.
|
|
|
54
198
|
- Minitest and RSpec integration
|
|
55
199
|
- 100% YARD documentation coverage with zero warnings
|
|
56
200
|
- RBS type signatures for all modules
|
|
57
|
-
- GitHub Actions CI workflow (Ruby 3.2 + 3.3 matrix)
|
|
201
|
+
- GitHub Actions CI workflow (Ruby 3.2 + 3.3 + 4.0 matrix)
|
|
58
202
|
- CONTRIBUTING.md with commit conventions and development guide
|
|
59
203
|
- Rake tasks: download, build, run, connect, inspect, script, replay,
|
|
60
204
|
preflight
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
AGENTS.md
|
data/README.md
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
# plushie
|
|
2
2
|
|
|
3
|
-
Build native desktop apps in Ruby. **Pre-1.0**
|
|
3
|
+
Build native desktop apps in Ruby. **[Pre-1.0](#status)**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
[
|
|
9
|
-
|
|
5
|
+
Write your entire application in Ruby (state, events, UI) and get
|
|
6
|
+
native windows on Linux, macOS, and Windows. Available on
|
|
7
|
+
[RubyGems](https://rubygems.org/gems/plushie) as `plushie`. The
|
|
8
|
+
[renderer](https://github.com/plushie-ui/plushie-rust) is built on
|
|
9
|
+
[Iced](https://github.com/iced-rs/iced) and ships as a precompiled
|
|
10
|
+
binary, no Rust toolchain required.
|
|
11
|
+
|
|
12
|
+
SDKs are also available for
|
|
13
|
+
[Elixir](https://github.com/plushie-ui/plushie-elixir),
|
|
14
|
+
[Gleam](https://github.com/plushie-ui/plushie-gleam),
|
|
15
|
+
[Python](https://github.com/plushie-ui/plushie-python), and
|
|
16
|
+
[TypeScript](https://github.com/plushie-ui/plushie-typescript).
|
|
17
|
+
|
|
18
|
+
## Quick start
|
|
10
19
|
|
|
11
20
|
```ruby
|
|
12
21
|
class Counter
|
|
@@ -43,257 +52,114 @@ end
|
|
|
43
52
|
Plushie.run(Counter)
|
|
44
53
|
```
|
|
45
54
|
|
|
46
|
-
|
|
47
|
-
minimal counter to a full widget catalog. For complete project demos,
|
|
48
|
-
including native Rust extensions, see the
|
|
49
|
-
[plushie-demos](https://github.com/plushie-ui/plushie-demos/tree/main/ruby)
|
|
50
|
-
repository.
|
|
51
|
-
|
|
52
|
-
## Getting started
|
|
53
|
-
|
|
54
|
-
Add plushie to your Gemfile:
|
|
55
|
+
Add plushie to your Gemfile and download the renderer:
|
|
55
56
|
|
|
56
|
-
```
|
|
57
|
+
```bash
|
|
58
|
+
# Gemfile
|
|
57
59
|
gem "plushie", "== 0.1.0"
|
|
58
60
|
```
|
|
59
61
|
|
|
60
|
-
Then:
|
|
61
|
-
|
|
62
62
|
```bash
|
|
63
63
|
bundle install
|
|
64
64
|
rake plushie:download # download precompiled renderer binary
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
Requires Ruby 3.2+. The precompiled binary requires no Rust toolchain.
|
|
68
|
-
|
|
69
|
-
### Your first app
|
|
70
|
-
|
|
71
|
-
Create `lib/counter.rb`:
|
|
72
|
-
|
|
73
|
-
```ruby
|
|
74
|
-
require "plushie"
|
|
75
|
-
|
|
76
|
-
class Counter
|
|
77
|
-
include Plushie::App
|
|
78
|
-
|
|
79
|
-
Model = Plushie::Model.define(:count)
|
|
80
|
-
|
|
81
|
-
def init(_opts) = Model.new(count: 0)
|
|
82
|
-
|
|
83
|
-
def update(model, event)
|
|
84
|
-
case event
|
|
85
|
-
in Event::Widget[type: :click, id: "increment"]
|
|
86
|
-
model.with(count: model.count + 1)
|
|
87
|
-
in Event::Widget[type: :click, id: "decrement"]
|
|
88
|
-
model.with(count: model.count - 1)
|
|
89
|
-
else
|
|
90
|
-
model
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def view(model)
|
|
95
|
-
window("main", title: "Counter") do
|
|
96
|
-
column(padding: 16, spacing: 8) do
|
|
97
|
-
text("count", "Count: #{model.count}", size: 20)
|
|
98
|
-
row(spacing: 8) do
|
|
99
|
-
button("increment", "+")
|
|
100
|
-
button("decrement", "-")
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
Plushie.run(Counter)
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
Run it:
|
|
111
|
-
|
|
112
|
-
```bash
|
|
113
65
|
ruby lib/counter.rb
|
|
114
66
|
```
|
|
115
67
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
-
|
|
121
|
-
|
|
122
|
-
- **`update(model, event)`** -- receives the current model and an event,
|
|
123
|
-
returns the new model. Pure function. Return `[model, command]` for
|
|
124
|
-
side effects.
|
|
125
|
-
- **`view(model)`** -- receives the model, returns a UI tree using the
|
|
126
|
-
block DSL. The runtime diffs trees and sends patches to the renderer.
|
|
127
|
-
- **`subscribe(model)`** (optional) -- returns active subscriptions
|
|
128
|
-
(timers, keyboard/mouse events).
|
|
129
|
-
|
|
130
|
-
## Features
|
|
131
|
-
|
|
132
|
-
- **39 built-in widget types** -- buttons, text inputs, sliders, tables,
|
|
133
|
-
markdown, canvas, pane grids, and more.
|
|
134
|
-
- **22 built-in themes** -- light, dark, dracula, nord, catppuccin,
|
|
135
|
-
tokyo night, kanagawa, and more.
|
|
136
|
-
- **Multi-window** -- declare window nodes in your widget tree; the
|
|
137
|
-
framework manages them automatically.
|
|
138
|
-
- **Platform effects** -- native file dialogs, clipboard, OS
|
|
139
|
-
notifications.
|
|
140
|
-
- **Accessibility** -- screen reader support via accesskit.
|
|
141
|
-
- **Live reload** -- `Plushie.run(MyApp, dev: true)` watches lib/ and
|
|
142
|
-
reloads on file changes. Model state is preserved.
|
|
143
|
-
- **Remote rendering** -- native desktop UI for server-side Ruby apps
|
|
144
|
-
over SSH. Your init/update/view code doesn't change.
|
|
145
|
-
- **Widget extensions** -- pure Ruby composites or native Rust-backed
|
|
146
|
-
custom widgets via `include Plushie::Extension`.
|
|
147
|
-
- **Configuration system** -- `Plushie.configure` for binary paths,
|
|
148
|
-
extensions, test backends, and extension runtime config.
|
|
149
|
-
- **WASM renderer** -- `rake plushie:download[wasm]` downloads a WASM
|
|
150
|
-
build of the renderer for browser targets.
|
|
151
|
-
|
|
152
|
-
## Documentation
|
|
153
|
-
|
|
154
|
-
**Guides:**
|
|
155
|
-
|
|
156
|
-
- [Getting started](docs/getting-started.md) -- setup, first app, rake tasks, dev mode
|
|
157
|
-
- [Tutorial: building a todo app](docs/tutorial.md) -- step-by-step walkthrough
|
|
158
|
-
- [App behaviour](docs/app-behaviour.md) -- init, update, view, subscribe callbacks
|
|
159
|
-
- [Layout](docs/layout.md) -- column, row, container, spacing, alignment
|
|
160
|
-
- [Events](docs/events.md) -- widget, keyboard, mouse, window, canvas events
|
|
161
|
-
- [Commands](docs/commands.md) -- async, timers, widget ops, effects, batching
|
|
162
|
-
- [Effects](docs/effects.md) -- file dialogs, clipboard, notifications
|
|
163
|
-
- [Scoped IDs](docs/scoped-ids.md) -- how container nesting scopes widget IDs
|
|
164
|
-
|
|
165
|
-
**Advanced:**
|
|
68
|
+
Requires Ruby 3.2+. The repo includes
|
|
69
|
+
[several other examples](examples/) you can try. For multi-file
|
|
70
|
+
projects (custom widgets, native Rust extensions, real project
|
|
71
|
+
scaffolding), see the
|
|
72
|
+
[plushie-demos](https://github.com/plushie-ui/plushie-demos/tree/main/ruby)
|
|
73
|
+
repo.
|
|
166
74
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
- [Composition patterns](docs/composition-patterns.md) -- tabs, modals, forms, lists
|
|
171
|
-
- [Accessibility](docs/accessibility.md) -- screen reader support, roles, labels
|
|
172
|
-
- [Extensions](docs/extensions.md) -- Ruby composites and native Rust widgets
|
|
173
|
-
- [DSL internals](docs/dsl-internals.md) -- how the UI builder works under the hood
|
|
75
|
+
To add Plushie to your own project, see the
|
|
76
|
+
[getting started guide](docs/getting-started.md), or browse the
|
|
77
|
+
[docs](docs/) for all guides and references.
|
|
174
78
|
|
|
175
|
-
|
|
79
|
+
## How it works
|
|
176
80
|
|
|
177
|
-
|
|
81
|
+
Your Ruby application and the renderer run as two OS processes
|
|
82
|
+
that exchange messages. Think of it like talking to a database,
|
|
83
|
+
except the database is a GPU-accelerated GUI toolkit. The SDK builds
|
|
84
|
+
UI trees and handles events; the renderer draws native windows and
|
|
85
|
+
captures input.
|
|
178
86
|
|
|
179
|
-
|
|
180
|
-
|
|
87
|
+
The SDK diffs each new tree against the previous one and sends only
|
|
88
|
+
the changes. If the renderer crashes, Plushie restarts it and
|
|
89
|
+
re-syncs your state. If your code raises, the SDK reverts to the
|
|
90
|
+
last good state. Neither process can take the other down.
|
|
181
91
|
|
|
182
|
-
|
|
92
|
+
The same protocol works over a local pipe, an SSH connection, or
|
|
93
|
+
any bidirectional byte stream. Your code doesn't need to change.
|
|
183
94
|
|
|
184
|
-
|
|
185
|
-
# test/test_helper.rb
|
|
186
|
-
require "plushie"
|
|
187
|
-
require "plushie/test"
|
|
188
|
-
require "minitest/autorun"
|
|
189
|
-
```
|
|
95
|
+
## Features
|
|
190
96
|
|
|
191
|
-
|
|
97
|
+
- **Elm architecture** - init, update, view. State lives in Ruby,
|
|
98
|
+
pure functions, predictable updates
|
|
99
|
+
- **Block DSL** - nested Ruby blocks build the widget tree with
|
|
100
|
+
natural indentation, no templates or markup
|
|
101
|
+
- **Built-in widgets** - layout, input, display, and interactive
|
|
102
|
+
widgets out of the box
|
|
103
|
+
- **Canvas** - shapes, paths, gradients, transforms, and
|
|
104
|
+
interactive elements for custom 2D drawing
|
|
105
|
+
- **Themes** - dark, light, nord, catppuccin, tokyo night, and
|
|
106
|
+
more, with custom palettes and per-widget style overrides
|
|
107
|
+
- **Animation** - renderer-side transitions, springs, and
|
|
108
|
+
sequences with no wire traffic per frame
|
|
109
|
+
- **Multi-window** - declare windows in your view; the framework
|
|
110
|
+
manages the rest
|
|
111
|
+
- **Platform effects** - native file dialogs, clipboard, OS
|
|
112
|
+
notifications
|
|
113
|
+
- **Accessibility** - keyboard navigation, screen readers, and
|
|
114
|
+
focus management via [AccessKit](https://accesskit.dev)
|
|
115
|
+
- **Custom widgets** - compose existing widgets in pure Ruby,
|
|
116
|
+
draw on the canvas, or extend with native Rust
|
|
117
|
+
- **Hot reload** - `Plushie.run(MyApp, dev: true)` watches lib/
|
|
118
|
+
and reloads on file changes with full state preservation
|
|
119
|
+
- **Remote rendering** - app on a server or embedded device,
|
|
120
|
+
renderer on a display machine over SSH or any byte stream
|
|
121
|
+
- **Fault-tolerant** - renderer crashes auto-recover; app
|
|
122
|
+
exceptions are caught and state reverted
|
|
123
|
+
- **Configuration system** - `Plushie.configure` for binary paths,
|
|
124
|
+
extensions, test backends, and widget runtime config
|
|
125
|
+
- **WASM renderer** - `rake plushie:download[wasm]` for browser
|
|
126
|
+
targets
|
|
127
|
+
|
|
128
|
+
## Testing and automation
|
|
129
|
+
|
|
130
|
+
Tests run through the real renderer binary, not mocks. Interact like
|
|
131
|
+
a user: click, type, find elements, assert on text. All backends
|
|
132
|
+
support concurrent test execution to keep your suite fast as it
|
|
133
|
+
grows. Three interchangeable backends:
|
|
134
|
+
|
|
135
|
+
- **Mock** - millisecond tests, no display server
|
|
136
|
+
- **Headless** - real rendering via
|
|
137
|
+
[tiny-skia](https://github.com/linebender/tiny-skia), supports
|
|
138
|
+
screenshots for pixel regression in CI
|
|
139
|
+
- **Windowed** - real windows with GPU rendering, platform effects,
|
|
140
|
+
real input
|
|
192
141
|
|
|
193
142
|
```ruby
|
|
194
143
|
class CounterTest < Plushie::Test::Case
|
|
195
144
|
app Counter
|
|
196
145
|
|
|
197
146
|
def test_clicking_increment_updates_counter
|
|
198
|
-
click("#
|
|
147
|
+
click("#inc")
|
|
199
148
|
assert_text "#count", "Count: 1"
|
|
200
149
|
end
|
|
201
150
|
end
|
|
202
151
|
```
|
|
203
152
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
Default.
|
|
208
|
-
- **Headless** (`PLUSHIE_TEST_BACKEND=headless`) -- real rendering via
|
|
209
|
-
tiny-skia, no display server. Pixel screenshots.
|
|
210
|
-
- **Windowed** (`PLUSHIE_TEST_BACKEND=windowed`) -- real windows with GPU.
|
|
211
|
-
Needs display server (Xvfb in CI).
|
|
212
|
-
|
|
213
|
-
## How it works
|
|
214
|
-
|
|
215
|
-
Under the hood, a renderer built on iced handles window drawing and
|
|
216
|
-
platform integration. Your Ruby code sends widget trees to the
|
|
217
|
-
renderer over stdin; the renderer draws native windows and sends user
|
|
218
|
-
events back over stdout.
|
|
219
|
-
|
|
220
|
-
You don't need Rust to use plushie. The renderer is a precompiled
|
|
221
|
-
binary, similar to how your app talks to a database without you
|
|
222
|
-
writing C. If you need custom native rendering, the extension system
|
|
223
|
-
lets you write Rust for just those parts.
|
|
224
|
-
|
|
225
|
-
The same protocol works over a local pipe, an SSH connection, or any
|
|
226
|
-
bidirectional byte stream.
|
|
227
|
-
|
|
228
|
-
## State helpers
|
|
229
|
-
|
|
230
|
-
Plushie ships optional state management utilities:
|
|
231
|
-
|
|
232
|
-
- **`Plushie::Animation`** -- easing functions and interpolation
|
|
233
|
-
- **`Plushie::Route`** -- navigation stack for multi-view apps
|
|
234
|
-
- **`Plushie::Selection`** -- single, multi, and range selection
|
|
235
|
-
- **`Plushie::Undo`** -- undo/redo stacks with coalescing
|
|
236
|
-
- **`Plushie::DataQuery`** -- filter, search, sort, paginate collections
|
|
237
|
-
- **`Plushie::State`** -- path-based state with revision tracking
|
|
238
|
-
|
|
239
|
-
## Development
|
|
240
|
-
|
|
241
|
-
```bash
|
|
242
|
-
bundle exec rake # tests + linter + type check
|
|
243
|
-
bundle exec rake test # tests only
|
|
244
|
-
bundle exec rake standard # linter only
|
|
245
|
-
bundle exec rake steep # type check only
|
|
246
|
-
bundle exec rake yard # generate API docs to doc/
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
See [CONTRIBUTING.md](CONTRIBUTING.md) for the full development guide.
|
|
250
|
-
|
|
251
|
-
Rake tasks (add `require "plushie/rake"` to your Rakefile):
|
|
252
|
-
|
|
253
|
-
```bash
|
|
254
|
-
rake plushie:download # download precompiled binary
|
|
255
|
-
rake plushie:download[wasm] # download WASM renderer
|
|
256
|
-
rake plushie:build # build from Rust source (with extensions if configured)
|
|
257
|
-
rake plushie:run[Counter] # run an app
|
|
258
|
-
rake plushie:connect[Counter] # connect to renderer via stdio
|
|
259
|
-
rake plushie:inspect[Counter] # print UI tree as JSON
|
|
260
|
-
rake plushie:script # run .plushie test scripts
|
|
261
|
-
rake plushie:replay[path] # replay a script with real windows
|
|
262
|
-
rake plushie:preflight # run all CI checks
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
Configure the SDK programmatically:
|
|
266
|
-
|
|
267
|
-
```ruby
|
|
268
|
-
Plushie.configure do |config|
|
|
269
|
-
config.binary_path = "/opt/plushie/bin/plushie"
|
|
270
|
-
config.extensions = [MyGauge]
|
|
271
|
-
config.test_backend = :headless
|
|
272
|
-
end
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
## System requirements
|
|
276
|
-
|
|
277
|
-
The precompiled binary has no additional dependencies. To build from
|
|
278
|
-
source, install a Rust toolchain via [rustup](https://rustup.rs/) and
|
|
279
|
-
the platform-specific libraries:
|
|
280
|
-
|
|
281
|
-
- **Linux (Debian/Ubuntu):**
|
|
282
|
-
`sudo apt-get install libxkbcommon-dev libwayland-dev libx11-dev cmake fontconfig pkg-config`
|
|
283
|
-
- **Linux (Arch):**
|
|
284
|
-
`sudo pacman -S libxkbcommon wayland libx11 cmake fontconfig pkgconf`
|
|
285
|
-
- **macOS:** `xcode-select --install`
|
|
286
|
-
- **Windows:**
|
|
287
|
-
[Visual Studio Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/)
|
|
288
|
-
with "Desktop development with C++"
|
|
153
|
+
The same interaction API is available outside Minitest via
|
|
154
|
+
`Plushie::Automation::Session`. Attach to any running app and drive
|
|
155
|
+
it programmatically. Agent-friendly by design.
|
|
289
156
|
|
|
290
|
-
##
|
|
157
|
+
## Status
|
|
291
158
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
| Renderer | [github.com/plushie-ui/plushie](https://github.com/plushie-ui/plushie) |
|
|
159
|
+
Pre-1.0. The core works (built-in widgets, event system, themes,
|
|
160
|
+
multi-window, testing framework, accessibility) but the API is
|
|
161
|
+
still evolving. Pin to an exact version and read the
|
|
162
|
+
[CHANGELOG](CHANGELOG.md) when upgrading.
|
|
297
163
|
|
|
298
164
|
## License
|
|
299
165
|
|
data/Steepfile
CHANGED
|
@@ -1,8 +1,52 @@
|
|
|
1
1
|
# Steepfile
|
|
2
|
+
#
|
|
3
|
+
# Files listed here are type-checked against their RBS declarations.
|
|
4
|
+
# Files with heavy metaprogramming (widget.rb define_method closures,
|
|
5
|
+
# Widget.define class_eval blocks) are excluded because Steep cannot
|
|
6
|
+
# analyze their dynamic method generation.
|
|
2
7
|
target :lib do
|
|
3
8
|
signature "sig"
|
|
4
|
-
|
|
5
|
-
|
|
9
|
+
|
|
10
|
+
# Core modules
|
|
11
|
+
check "lib/plushie/app.rb"
|
|
12
|
+
check "lib/plushie/encode.rb"
|
|
13
|
+
check "lib/plushie/event/specs.rb"
|
|
14
|
+
check "lib/plushie/key_modifiers.rb"
|
|
15
|
+
check "lib/plushie/route.rb"
|
|
16
|
+
check "lib/plushie/selection.rb"
|
|
17
|
+
check "lib/plushie/undo.rb"
|
|
18
|
+
check "lib/plushie/version.rb"
|
|
19
|
+
|
|
20
|
+
# Excluded from checking (RBS declarations retained for consumers):
|
|
21
|
+
#
|
|
22
|
+
# - model.rb: Extensions#with is defined inside a Data.define block;
|
|
23
|
+
# Steep resolves `self` to the enclosing module, not the Data class.
|
|
24
|
+
# - node.rb: Node = Data.define block; same self-resolution issue.
|
|
25
|
+
# - subscription.rb: Sub = Data.define block; same self-resolution issue.
|
|
26
|
+
# - event.rb: Widget/Key/Ime/Window/Modifiers/CommandError/System are
|
|
27
|
+
# all Data.define with block overrides; same self-resolution issue.
|
|
28
|
+
|
|
29
|
+
# Tree (normalization, search, diff)
|
|
30
|
+
check "lib/plushie/tree.rb"
|
|
31
|
+
check "lib/plushie/tree/search.rb"
|
|
32
|
+
check "lib/plushie/tree/diff.rb"
|
|
33
|
+
|
|
34
|
+
# Protocol (decode is the most type-critical)
|
|
35
|
+
check "lib/plushie/protocol.rb"
|
|
36
|
+
check "lib/plushie/protocol/decode.rb"
|
|
37
|
+
|
|
38
|
+
# Runtime
|
|
39
|
+
check "lib/plushie/runtime.rb"
|
|
40
|
+
check "lib/plushie/runtime/commands.rb"
|
|
41
|
+
check "lib/plushie/animation.rb"
|
|
42
|
+
|
|
43
|
+
# Widget build helpers
|
|
44
|
+
check "lib/plushie/widget/build.rb"
|
|
45
|
+
|
|
46
|
+
# Type modules
|
|
47
|
+
check "lib/plushie/type/line_height.rb"
|
|
48
|
+
|
|
6
49
|
library "json"
|
|
7
50
|
library "logger"
|
|
51
|
+
library "securerandom"
|
|
8
52
|
end
|
data/docs/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Documentation
|
|
2
|
+
|
|
3
|
+
## Guides
|
|
4
|
+
|
|
5
|
+
Sequential chapters that build on each other. Start here if you're
|
|
6
|
+
new to Plushie.
|
|
7
|
+
|
|
8
|
+
1. [Introduction](guides/01-introduction.md) - what Plushie is and how it works
|
|
9
|
+
2. [Getting Started](guides/02-getting-started.md) - installation, binary setup, first run
|
|
10
|
+
3. [Your First App](guides/03-your-first-app.md) - building a counter with the Elm architecture
|
|
11
|
+
4. [The Development Loop](guides/04-the-development-loop.md) - hot reload, IRB, debugging
|
|
12
|
+
5. [Events](guides/05-events.md) - widget events, keyboard, pointer, pattern matching
|
|
13
|
+
6. [Lists and Inputs](guides/06-lists-and-inputs.md) - dynamic lists, text inputs, forms
|
|
14
|
+
7. [Layout](guides/07-layout.md) - rows, columns, containers, responsive sizing
|
|
15
|
+
8. [Styling](guides/08-styling.md) - themes, colors, fonts, per-widget style overrides
|
|
16
|
+
9. [Animation and Transitions](guides/09-animation.md) - transitions, springs, tweens, easing
|
|
17
|
+
10. [Subscriptions](guides/10-subscriptions.md) - timers, global key/pointer events, window events
|
|
18
|
+
11. [Async and Effects](guides/11-async-and-effects.md) - tasks, streams, platform effects
|
|
19
|
+
12. [Canvas](guides/12-canvas.md) - shapes, layers, transforms, interactive elements
|
|
20
|
+
13. [Custom Widgets](guides/13-custom-widgets.md) - composing widgets, canvas widgets, native Rust widgets
|
|
21
|
+
14. [State Management](guides/14-state-management.md) - routing, undo/redo, selection, data pipelines
|
|
22
|
+
15. [Testing](guides/15-testing.md) - test framework, backends, selectors, screenshots
|
|
23
|
+
16. [Shared State](guides/16-shared-state.md) - multi-session apps over SSH
|
|
24
|
+
17. [Packaging](guides/17-packaging.md) - publishing a gem and shipping a native renderer
|
|
25
|
+
|
|
26
|
+
## Reference
|
|
27
|
+
|
|
28
|
+
Lookup material organized by topic. Each page is self-contained.
|
|
29
|
+
|
|
30
|
+
- [Accessibility](reference/accessibility.md) - AccessKit integration, roles, labels, keyboard navigation
|
|
31
|
+
- [Animation](reference/animation.md) - transitions, springs, sequences, easing curves, animatable props
|
|
32
|
+
- [App Lifecycle](reference/app-lifecycle.md) - init/update/view callbacks, startup, renderer restart
|
|
33
|
+
- [Built-in Widgets](reference/built-in-widgets.md) - every widget with props, events, and examples
|
|
34
|
+
- [Canvas](reference/canvas.md) - shapes, layers, groups, transforms, clips, gradients
|
|
35
|
+
- [Commands and Effects](reference/commands.md) - async, focus, scroll, window ops, platform effects
|
|
36
|
+
- [Composition Patterns](reference/composition-patterns.md) - reusable components, overlays, navigation, state-helper integration
|
|
37
|
+
- [Configuration](reference/configuration.md) - Plushie.configure, environment variables, runtime options
|
|
38
|
+
- [Custom Types](reference/custom-types.md) - shared prop-type catalog
|
|
39
|
+
- [Custom Widgets](reference/custom-widgets.md) - Widget.define, behavioral widgets, canvas widgets, native crates
|
|
40
|
+
- [DSL](reference/dsl.md) - block DSL mechanics, context stack, auto-IDs, memo caching
|
|
41
|
+
- [Events](reference/events.md) - every event class, widget event taxonomy, pattern-matching cookbook
|
|
42
|
+
- [Native Extensions](reference/native-extension.md) - authoring a Rust widget crate and shipping it alongside a Ruby gem
|
|
43
|
+
- [Rake Tasks](reference/rake-tasks.md) - plushie:download, plushie:build, plushie:run, preflight
|
|
44
|
+
- [Scoped IDs](reference/scoped-ids.md) - ID scoping rules, scope matching, command paths
|
|
45
|
+
- [Subscriptions](reference/subscriptions.md) - timer, keyboard, pointer, window, catch-all subscriptions
|
|
46
|
+
- [Testing](reference/testing.md) - Plushie::Test::Case, RSpec helpers, backends, snapshots, scripts
|
|
47
|
+
- [Themes and Styling](reference/themes-and-styling.md) - built-in themes, custom palettes, style maps, gradients
|
|
48
|
+
- [Versioning](reference/versioning.md) - SDK version, PLUSHIE_RUST_VERSION pinning, Ruby version floor
|
|
49
|
+
- [Windows and Layout](reference/windows-and-layout.md) - window props, layout containers, Length/Padding/Alignment/Border/Shadow
|
|
50
|
+
- [Wire Protocol](reference/wire-protocol.md) - MessagePack/JSONL framing, handshake, session multiplexing
|
|
51
|
+
|
|
52
|
+
## Other resources
|
|
53
|
+
|
|
54
|
+
- [Examples](https://github.com/plushie-ui/plushie-ruby/tree/main/examples) - example apps included in the repo
|
|
55
|
+
- [Changelog](../CHANGELOG.md) - version history and migration notes
|
|
56
|
+
- [Demo apps](https://github.com/plushie-ui/plushie-demos/tree/main/ruby) - multi-file projects with custom widgets and real scaffolding
|