Skip to content

Commit 7e81fda

Browse files
committed
update docs
1 parent 8685fb9 commit 7e81fda

4 files changed

Lines changed: 194 additions & 232 deletions

File tree

.github/copilot-instructions.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ Shadow Objects are defined as functions or classes receiving a `ShadowObjectPara
2929

3030
## Project Structure
3131

32-
- Main library: `@packages/shadow-objects/`
33-
- Deployment package: `@spearwolf/shadow-objects`
32+
- **`packages/shadow-objects/`**: The main framework library. Deployment package: `@spearwolf/shadow-objects`.
33+
- **`packages/shae-offscreen-canvas/`**: An offscreen canvas as custom HTML element based on shadow-objects.
34+
- **`packages/shadow-objects-testing/`**: Functional tests.
35+
- **`packages/shadow-objects-e2e/`**: Blackbox / E2E tests.
3436

3537
## Documentation Guidelines
3638

README.md

Lines changed: 65 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,43 +7,81 @@ A reactive entity←component framework that feels home in the shadows 🧛
77
88
## Introduction 👀
99

10-
TODO ..
10+
The **Shadow Objects Framework** is a reactive library designed to decouple business logic and state management from the UI rendering layer. It runs application logic "in the dark" (e.g., in a web worker), mirroring the view hierarchy of your application.
1111

12-
## ⚙️ Local Dev Setup
12+
Key features include:
1313

14-
This is a monorepo based on [nx](https://nx.dev/) and [pnpm](https://pnpm.io/).
14+
- **Decoupled Logic**: Business logic resides in "Shadow Objects" separate from UI components.
15+
- **Entity-Component System**: Mirrors the view hierarchy (DOM) with a tree of Entities.
16+
- **Reactivity**: Built on signals and effects for automatic state synchronization.
17+
- **Context System**: Hierarchical dependency injection similar to React Context.
1518

16-
First, install dependencies with ...
19+
For a detailed deep dive into the architecture and API, please refer to the [**Shadow Objects Documentation**](packages/shadow-objects/README.md).
1720

18-
```sh
19-
$ pnpm install
20-
```
21-
You will also need to install the _playwright_ browser bundles _chromium_ and _firefox_ once in the [./packages/shadow-objects-e2e/](./packages/shadow-objects-e2e/) directory
21+
## 🏗️ Project Structure
2222

23-
```sh
24-
$ cd packages/shadow-objects-e2e
25-
packages/shadow-objects-e2e$ pnpm exec playwright install chromium
26-
packages/shadow-objects-e2e$ pnpm exec playwright install firefox
27-
```
23+
This repository is a monorepo managed with [nx](https://nx.dev/) and [pnpm](https://pnpm.io/).
2824

29-
After that you can build the framework and run all the tests with ..
25+
| Package | Description |
26+
| :--- | :--- |
27+
| **[`shadow-objects`](packages/shadow-objects/)** | The core framework library. |
28+
| **[`shae-offscreen-canvas`](packages/shae-offscreen-canvas/)** | A custom HTML element implementing an **offscreen canvas**, built with shadow-objects. |
29+
| **[`shadow-objects-testing`](packages/shadow-objects-testing/)** | Functional and integration tests for the framework. |
30+
| **[`shadow-objects-e2e`](packages/shadow-objects-e2e/)** | End-to-end tests using [Playwright](https://playwright.dev/). |
3031

31-
```sh
32-
$ pnpm cbt # => clean build test
33-
```
32+
## ⚙️ Development Setup
3433

35-
A first demo can simply be started with `pnpm start`. This is very useful to see if everything works. The demo shows functions from the optional `shae-offscreen-canvas` library.
34+
### Prerequisites
3635

37-
## 📖 Packages
36+
- **Node.js**: >=20.12.2
37+
- **pnpm**: >=9.1.2
3838

39-
| package | description |
40-
|-|-|
41-
| [`shadow-objects`](packages/shadow-objects/) | the main framework |
42-
| [`shae-offscreen-canvas`](packages/shae-offscreen-canvas/) | an **offscreen canvas** as custom html **element** based on shadow-objects |
43-
| [`shadow-objects-testing`](packages/shadow-objects-testing/) | functional tests |
44-
| [`shadow-objects-e2e`](packages/shadow-objects-e2e/) | blackbox / e2e tests |
39+
### Installation
40+
41+
1. **Install dependencies:**
42+
43+
```sh
44+
pnpm install
45+
```
46+
47+
2. **Install Playwright browsers:**
48+
49+
The E2E tests require Playwright browsers to be installed manually.
50+
51+
```sh
52+
cd packages/shadow-objects-e2e
53+
pnpm exec playwright install chromium firefox
54+
cd ../..
55+
```
56+
57+
### Common Tasks
58+
59+
- **Build & Test All:**
60+
Run a clean build and all tests (unit, functional, e2e) across the workspace.
61+
62+
```sh
63+
pnpm cbt
64+
```
65+
*(Alias for `pnpm run-s clean build test`)*
66+
67+
- **Start Demo:**
68+
Launch the `shae-offscreen-canvas` demo to see the framework in action.
69+
70+
```sh
71+
pnpm start
72+
```
73+
74+
- **Run Tests:**
75+
```sh
76+
pnpm test # Run all tests
77+
pnpm test:ci # Run tests excluding E2E (faster)
78+
```
79+
80+
- **Linting:**
81+
```sh
82+
pnpm lint
83+
```
4584

4685
- - -
4786

48-
> 🔎 This project does not currently use a separate issue tracking system; instead, TODO, FIXME, and XXX issues are written directly as comments in the source code, without any further indirection.
49-
> An overview of open issues can be found in [TODO.md](TODO.md).
87+
> 🔎 **Note:** This project tracks tasks directly in the source code using `TODO`, `FIXME`, and `XXX` comments. See [TODO.md](TODO.md) for an auto-generated overview.

packages/shadow-objects/README.md

Lines changed: 125 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
_hi! welcome to .._
21
# Shadow Objects Framework 🧛
32

4-
The **Shadow Objects Framework** is a library for managing application state and logic that runs "in the dark" (in a worker or separate context), mirroring a view hierarchy (like the DOM). It decouples business logic and state management from the UI rendering layer.
3+
The **Shadow Objects Framework** is a reactive library designed to decouple business logic and state management from the UI rendering layer. It runs application logic "in the dark" (e.g., in a web worker), mirroring the view hierarchy of your application.
4+
5+
> [!WARNING]
6+
> 🚀 This is a highly experimental framework that is slowly maturing. Use at your own risk. 🔥
57
68
## Core Concepts
79

@@ -29,77 +31,143 @@ The **Registry** maps **Tokens** to **Shadow Object Constructors**.
2931
- **Routes**: Defines rules for composing multiple Shadow Objects. For example, a token can "route" to other tokens, causing multiple Shadow Objects to be instantiated for a single Entity.
3032
- **Conditional Routing**: Routes can be triggered based on the presence of specific "truthy" properties on the Entity (e.g., `@myProp` routes only if `myProp` is set).
3133

32-
## Lifecycle
34+
---
3335

34-
1. **Creation**: When an Entity is created (e.g., a Web Component connects), the Kernel looks up its Token in the Registry.
35-
2. **Instantiation**: The Kernel instantiates all Shadow Objects associated with that Token (and its routes).
36-
3. **Execution**: The Shadow Object function runs, setting up signals, effects, and context providers.
37-
4. **Updates**:
38-
* **Properties**: When view properties change, the Entity's signals update, triggering any dependent effects in the Shadow Object.
39-
* **Context**: If a parent Entity changes a provided context, child Shadow Objects consuming that context automatically update.
40-
5. **Destruction**: When an Entity is removed or its Token changes, the Kernel destroys the associated Shadow Objects, cleaning up all signals and effects.
36+
## Developer Guide
37+
38+
### 1. Defining Shadow Objects
4139

42-
## API: Writing Shadow Objects
40+
You can define a Shadow Object as a **Function** or a **Class**. Both receive a `ShadowObjectParams` object containing the API methods.
4341

44-
Shadow Objects are defined as functions (or classes) that receive a `ShadowObjectParams` object.
42+
#### Function-based (Recommended)
4543

4644
```typescript
4745
import { ShadowObjectParams } from "@spearwolf/shadow-objects";
4846

4947
export function MyShadowObject({
5048
useProperty,
51-
useProperties,
5249
useContext,
53-
provideContext,
54-
useResource,
5550
createEffect,
56-
on
51+
on,
52+
onDestroy
5753
}: ShadowObjectParams) {
5854

59-
// 1. Read Properties from the View
60-
const getTitle = useProperty("title");
61-
// or bulk access:
62-
const props = useProperties({
63-
title: "title",
64-
isEnabled: "enabled"
55+
// 1. Read Properties
56+
const title = useProperty("title");
57+
58+
// 2. React to changes
59+
createEffect(() => {
60+
console.log("Title is now:", title());
6561
});
6662

67-
// 2. Consume Context from Parents
68-
const getTheme = useContext("theme");
63+
// 3. Handle Lifecycle
64+
onDestroy(() => {
65+
console.log("Shadow Object destroyed");
66+
});
6967

70-
// 3. Manage Resources (Lifecycle)
71-
// Automatically creates/destroys the resource when dependencies change
72-
const myService$ = useResource(() => {
73-
const title = props.title();
74-
if (!title) return;
75-
return new MyService(title);
76-
}, (service) => service.dispose());
68+
// 4. Return public methods (optional)
69+
return {
70+
someMethod() { /* ... */ }
71+
};
72+
}
73+
```
7774

78-
// 4. Provide Context to Children
79-
// Can pass a value or a signal directly
80-
provideContext("myService", myService$);
75+
#### Class-based
8176

82-
// 5. Side Effects
83-
createEffect(() => {
84-
console.log("Title changed to:", props.title());
85-
});
77+
```typescript
78+
import { ShadowObjectParams } from "@spearwolf/shadow-objects";
79+
80+
export class MyShadowObject {
81+
constructor({ useProperty, createEffect, onDestroy }: ShadowObjectParams) {
82+
const title = useProperty("title");
8683

87-
// 6. Event Listeners
88-
on(entity, "some-event", (data) => { /* ... */ });
84+
createEffect(() => {
85+
console.log("Title is now:", title());
86+
});
87+
88+
onDestroy(() => this.cleanup());
89+
}
90+
91+
cleanup() {
92+
console.log("Shadow Object destroyed");
93+
}
8994
}
9095
```
9196

92-
### Key API Methods
97+
### 2. The `ShadowObjectParams` API
98+
99+
The `ShadowObjectParams` object provides all necessary tools to interact with the Entity, the View, and the Context system.
93100

94-
* **`useProperty(name)`**: Returns a signal reader for a specific property on the Entity.
95-
* **`useProperties(map)`**: Returns an object of signal readers for multiple properties.
96-
* **`useContext(name)`**: Returns a signal reader for a value provided by a parent Entity.
97-
* **`provideContext(name, value)`**: Makes a value (or signal) available to descendant Entities.
98-
* **`useResource(factory, cleanup)`**: A helper to create and manage objects that need explicit cleanup (like Three.js objects or subscriptions).
99-
* **`createEffect(callback)`**: Runs a side effect whenever accessed signals change.
100-
* **`createSignal(initialValue)`**: Creates a local reactive state.
101+
| Method | Description |
102+
| :--- | :--- |
103+
| **`useProperty(name)`** | Returns a signal reader for a specific property on the Entity. Updates when the view property changes. |
104+
| **`useProperties(map)`** | Returns an object of signal readers for multiple properties. |
105+
| **`useContext(name)`** | Consumes a context value provided by a parent Entity. |
106+
| **`useParentContext(name)`** | Skips the current Entity and consumes context directly from the parent. |
107+
| **`provideContext(name, value)`** | Provides a context value (or signal) to descendant Entities. |
108+
| **`provideGlobalContext(name, value)`** | Provides a context value globally to all Entities. |
109+
| **`useResource(factory, cleanup)`** | Manages an external resource (e.g., a Three.js object) with automatic cleanup when dependencies change. |
110+
| **`createEffect(callback)`** | Runs a side effect whenever accessed signals change. |
111+
| **`createSignal(initialValue)`** | Creates a local reactive state signal. |
112+
| **`createMemo(factory)`** | Creates a derived signal that updates only when dependencies change. |
113+
| **`on(target, event, callback)`** | Listens for events on the Entity or other event targets. |
114+
| **`once(target, event, callback)`** | Listens for an event exactly once. |
115+
| **`onDestroy(callback)`** | Registers a callback to be executed when the Shadow Object is destroyed. |
101116

102-
## Architecture Diagram
117+
### 3. Registering Shadow Objects
118+
119+
Shadow Objects are organized in **Modules**. A module defines which Tokens map to which Shadow Objects.
120+
121+
```typescript
122+
// my-module.ts
123+
import { MyShadowObject } from "./MyShadowObject";
124+
125+
export default {
126+
// Map tokens to constructors
127+
define: {
128+
"my-component": MyShadowObject,
129+
},
130+
// Define routing rules
131+
routes: {
132+
"my-component": ["mixin-logger", "mixin-analytics"], // Composition
133+
"@debug": ["debug-overlay"], // Conditional routing based on 'debug' property
134+
}
135+
};
136+
```
137+
138+
### 4. View Integration
139+
140+
In your HTML or View layer, you use the provided Web Components to create the Entity hierarchy.
141+
142+
```html
143+
<!-- 1. Initialize the Environment -->
144+
<shae-worker-env src="./my-module.js"></shae-worker-env>
145+
146+
<!-- 2. Create Entities -->
147+
<shae-ent token="my-component">
148+
<!-- Properties -->
149+
<shae-prop name="title" value="Hello World"></shae-prop>
150+
151+
<!-- Nested Entities -->
152+
<shae-ent token="child-component"></shae-ent>
153+
</shae-ent>
154+
```
155+
156+
---
157+
158+
## Architecture & Internals
159+
160+
### Lifecycle
161+
162+
1. **Creation**: When an Entity is created (e.g., `<shae-ent>` connects), the Kernel looks up its Token in the Registry.
163+
2. **Instantiation**: The Kernel instantiates all Shadow Objects associated with that Token (and its routes).
164+
3. **Execution**: The Shadow Object function runs, setting up signals, effects, and context providers.
165+
4. **Updates**:
166+
* **Properties**: When view properties change, the Entity's signals update, triggering any dependent effects in the Shadow Object.
167+
* **Context**: If a parent Entity changes a provided context, child Shadow Objects consuming that context automatically update.
168+
5. **Destruction**: When an Entity is removed or its Token changes, the Kernel destroys the associated Shadow Objects, cleaning up all signals and effects.
169+
170+
### Architecture Diagram
103171

104172
```mermaid
105173
graph TD
@@ -122,3 +190,11 @@ graph TD
122190
Logic -->|Updates| Signals
123191
Signals -->|Triggers| Effects
124192
```
193+
194+
### Further Reading
195+
196+
For deep dives into specific subsystems:
197+
198+
- [**ShadowEnv**](src/view/README.md): The environment wrapper.
199+
- [**ComponentContext**](src/view/ComponentContext.md): Context implementation details.
200+
- [**ViewComponent**](src/view/ViewComponent.md): Base class for view components.

0 commit comments

Comments
 (0)