ngx-blocks-studio 0.0.10 → 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.
- package/README.md +149 -10
- package/fesm2022/ngx-blocks-studio.mjs +1799 -610
- package/fesm2022/ngx-blocks-studio.mjs.map +1 -1
- package/package.json +2 -3
- package/types/ngx-blocks-studio.d.ts +308 -226
package/README.md
CHANGED
|
@@ -1,17 +1,156 @@
|
|
|
1
1
|
# ngx-blocks-studio
|
|
2
2
|
|
|
3
|
-
Angular library for **config-driven routing** and **block-based UIs**. Define routes and component trees in
|
|
3
|
+
Angular library for **config-driven routing** and **block-based UIs**. Define routes and component trees in data; the library resolves components and guards by name and wires inputs, outputs, and cross-block references.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Extended documentation (overview, concepts, registry / block loader / route loader guides, and block-directive patterns) lives in the **`docs/`** folder of the **source repository**—it is not shipped inside the npm package, so browse or clone the repo for full prose and learning paths.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- **Block loader** — Render components from a JSON description. Supports instance refs (e.g. `FormState.firstName`), two-way binding via refs, nested blocks, optional **host directives** (via DirectiveRegistry), and a block registry so blocks can reference each other. Inputs and outputs are validated first (each key must exist on the component or a host directive; invalid keys are warned and skipped), then set/wired on all matching targets. Use full descriptions or reuse definitions by `blockId` with overrides.
|
|
9
|
-
- **Route loader** — Load route configuration from JSON (or a URL). Components and guards are resolved by key; the resulting `Routes` are applied to the router. Config is exposed as signals.
|
|
7
|
+
---
|
|
10
8
|
|
|
11
|
-
##
|
|
9
|
+
## Install
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
```bash
|
|
12
|
+
npm install ngx-blocks-studio
|
|
13
|
+
```
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
**Peer dependencies:** `@angular/common`, `@angular/core`, and `@angular/router` (see `package.json` for supported versions), plus `rxjs`.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Imports
|
|
20
|
+
|
|
21
|
+
Typical entry points:
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import {
|
|
25
|
+
RouteLoader,
|
|
26
|
+
type RouteConfig,
|
|
27
|
+
type RouteConfigs,
|
|
28
|
+
ComponentRegistry,
|
|
29
|
+
GuardRegistry,
|
|
30
|
+
BlockDirective,
|
|
31
|
+
BlockLoaderService,
|
|
32
|
+
BlockDefinitionsRegistry,
|
|
33
|
+
} from 'ngx-blocks-studio';
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Import additional symbols from the same package as needed for your app.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Bootstrap (`main.ts` and `app.config.ts`)
|
|
41
|
+
|
|
42
|
+
`RouteLoader` is **`providedIn: 'root'`**—no extra `providers` entry for it. Start the app with **`bootstrapApplication`**, use an **empty** `provideRouter([])` (the loader replaces the router config), and load routes once at startup—typically in **`provideAppInitializer`** so registration runs before navigation.
|
|
43
|
+
|
|
44
|
+
**`main.ts`**
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { bootstrapApplication } from '@angular/platform-browser';
|
|
48
|
+
import { appConfig } from './app/app.config';
|
|
49
|
+
import { AppComponent } from './app/app.component';
|
|
50
|
+
|
|
51
|
+
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
|
52
|
+
console.error(err)
|
|
53
|
+
);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**`app.config.ts`**
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import { provideHttpClient } from '@angular/common/http';
|
|
60
|
+
import { ApplicationConfig, inject, provideAppInitializer } from '@angular/core';
|
|
61
|
+
import { provideRouter } from '@angular/router';
|
|
62
|
+
import { ComponentRegistry, RouteLoader } from 'ngx-blocks-studio';
|
|
63
|
+
import { HomeComponent } from './home.component';
|
|
64
|
+
|
|
65
|
+
function registerBlocks(): void {
|
|
66
|
+
ComponentRegistry.getInstance().register('HomePage', HomeComponent);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const appConfig: ApplicationConfig = {
|
|
70
|
+
providers: [
|
|
71
|
+
provideHttpClient(), // use when calling RouteLoader.loadRoutesFromUrl(...)
|
|
72
|
+
provideRouter([]),
|
|
73
|
+
provideAppInitializer(() => {
|
|
74
|
+
const routeLoader = inject(RouteLoader);
|
|
75
|
+
registerBlocks();
|
|
76
|
+
return routeLoader.loadRoutes({
|
|
77
|
+
routes: [{ path: 'home', component: 'HomePage', title: 'Home' }],
|
|
78
|
+
defaultRedirect: 'home',
|
|
79
|
+
});
|
|
80
|
+
}),
|
|
81
|
+
],
|
|
82
|
+
};
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Register every **component** and **guard** key used in the config inside `registerBlocks()` (or equivalent) **before** `loadRoutes` resolves. Omit **`provideHttpClient`** if you only use **`loadRoutes`** with in-memory config and never **`loadRoutesFromUrl`**.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Example: register keys and load routes
|
|
90
|
+
|
|
91
|
+
Register every **component** and **guard** key used in your route config, then call `loadRoutes` or `loadRoutesFromUrl`:
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { inject } from '@angular/core';
|
|
95
|
+
import { ComponentRegistry, GuardRegistry, RouteLoader } from 'ngx-blocks-studio';
|
|
96
|
+
|
|
97
|
+
const components = ComponentRegistry.getInstance();
|
|
98
|
+
const guards = GuardRegistry.getInstance();
|
|
99
|
+
|
|
100
|
+
components.register('HomePage', HomeComponent);
|
|
101
|
+
guards.register('auth', authGuardFn);
|
|
102
|
+
|
|
103
|
+
const routeLoader = inject(RouteLoader);
|
|
104
|
+
await routeLoader.loadRoutes({
|
|
105
|
+
routes: [{ path: 'home', component: 'HomePage', title: 'Home' }],
|
|
106
|
+
defaultRedirect: 'home',
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
JSON route files can include `children`, `data`, `title`, and guard arrays (`canActivate`, etc.). After loading, `RouteLoader` exposes the active config via **signals** (`routeConfigFile`, `routeConfig`, …).
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Example: render a block with `[block]`
|
|
115
|
+
|
|
116
|
+
Register the component key, then pass a **block description** and a shared **`BlockRegistry`** so nested blocks and cross-block refs resolve.
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
ComponentRegistry.getInstance().register('MyPanel', MyPanelComponent);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
```html
|
|
123
|
+
<div
|
|
124
|
+
[block]
|
|
125
|
+
[description]="{
|
|
126
|
+
component: 'MyPanel',
|
|
127
|
+
id: 'Panel1',
|
|
128
|
+
inputs: { title: 'Hello' }
|
|
129
|
+
}"
|
|
130
|
+
[blockRegistry]="registry"
|
|
131
|
+
></div>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Example: refs, reuse, services, outputs
|
|
137
|
+
|
|
138
|
+
- **Read-only:** input strings may contain `{{ refPath }}` (e.g. `FormState.name` on the current block, or `OtherBlockId:FormState.name` for another block in the same registry).
|
|
139
|
+
- **Two-way:** the entire input value must be exactly `"[(refPath)]"` (no mixing with literals in the same string).
|
|
140
|
+
- **Reuse:** `{ blockId: 'RegisteredBlock' }` looks up a definition (local map or `BlockDefinitionsRegistry`); optional `blockDefinition` deep-merges overrides. Pass the block **model** via `[model]` or `BlockLoaderService.load(…)`—not via `inputs.model` for `blockInstance.model`.
|
|
141
|
+
- **Services:** `services: [{ id: 'State' }]` is root-first with self fallback; `services: [{ id: 'State', scope: 'self' }]` creates a per-block instance.
|
|
142
|
+
- **Outputs:** map output names to callable ref strings (e.g. `"BlockId:Service.signal.set"`) or objects with `ref`, optional `params`, `then`, and `onError` for async chaining.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## What the library provides
|
|
147
|
+
|
|
148
|
+
- **Registries** — Register components, guards, directives, and services by string key (optional lazy loaders and metadata). Used when resolving route config and block descriptions.
|
|
149
|
+
- **Block loader** — `BlockDirective` / `BlockLoaderService`: render from descriptions or `blockId` references, wire refs and host directives, validate keys against the component and host directives.
|
|
150
|
+
- **Route loader** — `RouteLoader`: build Angular `Routes` from JSON or in-memory `RouteConfigs`, reset the router, expose config as signals.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## API surface (where to look in docs)
|
|
155
|
+
|
|
156
|
+
When you have the repo: **Registry** (registries and metadata), **Block loader** (`BlockDirective`, `BlockLoaderService`, refs, outputs), **Route loader** (`RouteLoader`, `RouteConfig`, JSON loading). The source tree under `projects/blocks-studio/src/lib` matches the public exports.
|