@thatopen/services 0.0.2 → 0.0.3
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/AGENTS.md +86 -76
- package/dist/cli.js +10 -1
- package/docs/access-backend-data.md +19 -19
- package/docs/app-architecture.md +94 -94
- package/docs/app-layout.md +139 -139
- package/docs/app-wiring.md +123 -123
- package/docs/bim-components/coding-conventions.md +128 -128
- package/docs/bim-components/element-collections.md +69 -69
- package/docs/bim-components/expose-events.md +84 -84
- package/docs/bim-components/library-examples.md +28 -28
- package/docs/bim-components/observable-collections.md +83 -83
- package/docs/bim-components/overview.md +160 -160
- package/docs/bim-components/per-frame-updates.md +20 -20
- package/docs/bim-components/save-and-restore-state.md +21 -21
- package/docs/bim-components/setup-and-cleanup.md +64 -64
- package/docs/bim-components/type-conventions.md +49 -49
- package/docs/bim-components/user-driven-object-creation.md +56 -56
- package/docs/cli-setup.md +54 -54
- package/docs/cloud-components.md +74 -74
- package/docs/connect-logic-to-ui.md +113 -113
- package/docs/previewing.md +45 -45
- package/docs/publishing.md +35 -35
- package/docs/scaffolding.md +71 -54
- package/docs/ui-components/async-actions.md +18 -18
- package/docs/ui-components/confirmation-dialog.md +39 -39
- package/docs/ui-components/data-table.md +185 -185
- package/docs/ui-components/display-text.md +39 -39
- package/docs/ui-components/inline-form.md +44 -44
- package/docs/ui-components/library-examples.md +24 -24
- package/docs/ui-components/overview.md +194 -194
- package/docs/ui-components/rendering-patterns.md +129 -129
- package/docs/ui-components/sections-layout.md +123 -123
- package/docs/update-grid-elements.md +46 -46
- package/docs/using-colors.md +32 -32
- package/docs/using-icons.md +37 -37
- package/package.json +2 -2
- package/src/cli/templates/bim/CONTEXT.md +1 -4
- package/src/cli/templates/bim/package.json +0 -1
- package/src/cli/templates/bim/src/main.ts +1 -2
- package/src/cli/templates/bim-beta/CONTEXT.md +241 -0
- package/src/cli/templates/bim-beta/package.json +25 -0
- package/src/cli/templates/bim-beta/src/app.ts +16 -0
- package/src/cli/templates/bim-beta/src/bim-components/CloudRunner/index.ts +91 -0
- package/src/cli/templates/bim-beta/src/bim-components/CloudRunner/src/index.ts +1 -0
- package/src/cli/templates/bim-beta/src/bim-components/CloudRunner/src/types.ts +5 -0
- package/src/cli/templates/bim-beta/src/bim-components/index.ts +1 -0
- package/src/cli/templates/bim-beta/src/globals.ts +1 -0
- package/src/cli/templates/bim-beta/src/main.ts +89 -0
- package/src/cli/templates/bim-beta/src/setups/cloud-runner.ts +13 -0
- package/src/cli/templates/bim-beta/src/setups/index.ts +3 -0
- package/src/cli/templates/bim-beta/src/setups/ui-manager.ts +27 -0
- package/src/cli/templates/bim-beta/src/setups/viewports-manager.ts +22 -0
- package/src/cli/templates/bim-beta/src/ui-components/app-info-section/index.ts +26 -0
- package/src/cli/templates/bim-beta/src/ui-components/app-info-section/src/index.ts +1 -0
- package/src/cli/templates/bim-beta/src/ui-components/app-info-section/src/types.ts +15 -0
- package/src/cli/templates/bim-beta/src/ui-components/cloud-runner-section/index.ts +37 -0
- package/src/cli/templates/bim-beta/src/ui-components/cloud-runner-section/src/index.ts +1 -0
- package/src/cli/templates/bim-beta/src/ui-components/cloud-runner-section/src/types.ts +14 -0
- package/src/cli/templates/bim-beta/src/ui-components/index.ts +2 -0
- package/src/cli/templates/cloud/CONTEXT.md +205 -205
- package/src/cli/templates/cloud/src/main.ts +70 -70
- package/src/cli/templates/shared/AGENTS.md +30 -23
- package/src/cli/templates/shared/CLAUDE.md +1 -1
|
@@ -1,113 +1,113 @@
|
|
|
1
|
-
# Connect Logic to UI
|
|
2
|
-
|
|
3
|
-
Setup files are the bridge between custom BIM components (logic) and the platform UI. This is where event subscriptions, UI sync, and component wiring live — not in the component itself.
|
|
4
|
-
|
|
5
|
-
## Structure
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
setups/
|
|
9
|
-
├── index.ts → barrel (always present)
|
|
10
|
-
├── ui-manager.ts → fixed boilerplate (always present)
|
|
11
|
-
└── {custom}.ts → one per custom BIM component
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
One file per component being initialized. Each file exports a single function that receives `components: OBC.Components`.
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## `setups/ui-manager.ts` — Fixed boilerplate
|
|
19
|
-
|
|
20
|
-
This is where all UI templates get registered in the platform (see the UI-component guide in `docs/`: [./ui-components/overview.md](./ui-components/overview.md)). The file always has this shape — the content changes (which templates are registered), but the structure never does.
|
|
21
|
-
|
|
22
|
-
### `CustomUIs` type
|
|
23
|
-
|
|
24
|
-
Maps every UI template to its element type and state. Add one entry per registered template:
|
|
25
|
-
|
|
26
|
-
```ts
|
|
27
|
-
export type CustomUIs = {
|
|
28
|
-
filesSection: { type: BUI.PanelSection; state: FilesSectionState }
|
|
29
|
-
collisionsTable: { type: BUI.Table<CollisionsTableData>; state: CollisionsTableState }
|
|
30
|
-
// one entry per registered template
|
|
31
|
-
}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### `getUIManager` — typed accessor
|
|
35
|
-
|
|
36
|
-
The typed accessor for `UIManager`. Defined here because `CustomUIs` lives here. Used everywhere else in `setups/` to interact with the UI registry — never access `UIManager` directly:
|
|
37
|
-
|
|
38
|
-
```ts
|
|
39
|
-
export const getUIManager = (components: OBC.Components) =>
|
|
40
|
-
components.get(UIManager<CustomUIs>)
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
`getUIManager` is the **only** valid way to access `UIManager` in an app. Never use `components.get(UIManager)` directly — it drops the `CustomUIs` type parameter and loses all type information about the registered templates.
|
|
44
|
-
|
|
45
|
-
```ts
|
|
46
|
-
// ✗ Avoid — loses the CustomUIs type
|
|
47
|
-
const uis = components.get(UIManager)
|
|
48
|
-
|
|
49
|
-
// ✓ Correct — fully typed
|
|
50
|
-
const uis = getUIManager(components)
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### `uiManager` setup function
|
|
54
|
-
|
|
55
|
-
Registers each template and its optional `onInstanceCreated` callback, exported from the UI component:
|
|
56
|
-
|
|
57
|
-
```ts
|
|
58
|
-
export const uiManager = (components: OBC.Components) => {
|
|
59
|
-
const uis = getUIManager(components)
|
|
60
|
-
uis.registerTemplate("filesSection", {
|
|
61
|
-
template: filesSectionTemplate,
|
|
62
|
-
onInstanceCreated: onFilesSectionCreated
|
|
63
|
-
})
|
|
64
|
-
uis.registerTemplate("collisionsTable", {
|
|
65
|
-
template: collisionsTableTemplate
|
|
66
|
-
})
|
|
67
|
-
}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### Composing UI components
|
|
71
|
-
|
|
72
|
-
Templates can embed other registered components by creating instances via `uis.custom.get()`:
|
|
73
|
-
|
|
74
|
-
```ts
|
|
75
|
-
export const filesSectionTemplate: FilesSectionComponent = (state) => {
|
|
76
|
-
const uis = state.components.get(UIManager)
|
|
77
|
-
const [modelsList] = uis.custom.get("modelsList").create(state)
|
|
78
|
-
return BUI.html`
|
|
79
|
-
<bim-panel-section label="Files">
|
|
80
|
-
${modelsList}
|
|
81
|
-
</bim-panel-section>
|
|
82
|
-
`
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### Keeping UIs in sync with `updateInstances()`
|
|
87
|
-
|
|
88
|
-
To push a state update to all existing instances of a template, call `updateInstances()` from within a setup file — typically in response to engine events:
|
|
89
|
-
|
|
90
|
-
```ts
|
|
91
|
-
const updateUIs = () => uis.custom.get("modelsList").updateInstances()
|
|
92
|
-
fragments.list.onItemSet.add(updateUIs)
|
|
93
|
-
fragments.list.onItemDeleted.add(updateUIs)
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
---
|
|
97
|
-
|
|
98
|
-
## Custom setup files
|
|
99
|
-
|
|
100
|
-
Each setup file is the bridge between a custom BIM component and the platform (see the BIM-component guide in `docs/`: [./bim-components/overview.md](./bim-components/overview.md)). This is where wiring lands: event listeners, UI updates, and configuration go here — not in the component's constructor.
|
|
101
|
-
|
|
102
|
-
```ts
|
|
103
|
-
// setups/qto-manager.ts
|
|
104
|
-
export const qtoManager = (components: OBC.Components) => {
|
|
105
|
-
const uis = getUIManager(components)
|
|
106
|
-
const qtoManager = components.get(QtoManager)
|
|
107
|
-
|
|
108
|
-
qtoManager.onStateChanged.add((states) => {
|
|
109
|
-
if (!states.includes("value")) return
|
|
110
|
-
uis.custom.get("qtosTable").updateInstances()
|
|
111
|
-
})
|
|
112
|
-
}
|
|
113
|
-
```
|
|
1
|
+
# Connect Logic to UI
|
|
2
|
+
|
|
3
|
+
Setup files are the bridge between custom BIM components (logic) and the platform UI. This is where event subscriptions, UI sync, and component wiring live — not in the component itself.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
setups/
|
|
9
|
+
├── index.ts → barrel (always present)
|
|
10
|
+
├── ui-manager.ts → fixed boilerplate (always present)
|
|
11
|
+
└── {custom}.ts → one per custom BIM component
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
One file per component being initialized. Each file exports a single function that receives `components: OBC.Components`.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## `setups/ui-manager.ts` — Fixed boilerplate
|
|
19
|
+
|
|
20
|
+
This is where all UI templates get registered in the platform (see the UI-component guide in `docs/`: [./ui-components/overview.md](./ui-components/overview.md)). The file always has this shape — the content changes (which templates are registered), but the structure never does.
|
|
21
|
+
|
|
22
|
+
### `CustomUIs` type
|
|
23
|
+
|
|
24
|
+
Maps every UI template to its element type and state. Add one entry per registered template:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
export type CustomUIs = {
|
|
28
|
+
filesSection: { type: BUI.PanelSection; state: FilesSectionState }
|
|
29
|
+
collisionsTable: { type: BUI.Table<CollisionsTableData>; state: CollisionsTableState }
|
|
30
|
+
// one entry per registered template
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### `getUIManager` — typed accessor
|
|
35
|
+
|
|
36
|
+
The typed accessor for `UIManager`. Defined here because `CustomUIs` lives here. Used everywhere else in `setups/` to interact with the UI registry — never access `UIManager` directly:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
export const getUIManager = (components: OBC.Components) =>
|
|
40
|
+
components.get(UIManager<CustomUIs>)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`getUIManager` is the **only** valid way to access `UIManager` in an app. Never use `components.get(UIManager)` directly — it drops the `CustomUIs` type parameter and loses all type information about the registered templates.
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
// ✗ Avoid — loses the CustomUIs type
|
|
47
|
+
const uis = components.get(UIManager)
|
|
48
|
+
|
|
49
|
+
// ✓ Correct — fully typed
|
|
50
|
+
const uis = getUIManager(components)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### `uiManager` setup function
|
|
54
|
+
|
|
55
|
+
Registers each template and its optional `onInstanceCreated` callback, exported from the UI component:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
export const uiManager = (components: OBC.Components) => {
|
|
59
|
+
const uis = getUIManager(components)
|
|
60
|
+
uis.registerTemplate("filesSection", {
|
|
61
|
+
template: filesSectionTemplate,
|
|
62
|
+
onInstanceCreated: onFilesSectionCreated
|
|
63
|
+
})
|
|
64
|
+
uis.registerTemplate("collisionsTable", {
|
|
65
|
+
template: collisionsTableTemplate
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Composing UI components
|
|
71
|
+
|
|
72
|
+
Templates can embed other registered components by creating instances via `uis.custom.get()`:
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
export const filesSectionTemplate: FilesSectionComponent = (state) => {
|
|
76
|
+
const uis = state.components.get(UIManager)
|
|
77
|
+
const [modelsList] = uis.custom.get("modelsList").create(state)
|
|
78
|
+
return BUI.html`
|
|
79
|
+
<bim-panel-section label="Files">
|
|
80
|
+
${modelsList}
|
|
81
|
+
</bim-panel-section>
|
|
82
|
+
`
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Keeping UIs in sync with `updateInstances()`
|
|
87
|
+
|
|
88
|
+
To push a state update to all existing instances of a template, call `updateInstances()` from within a setup file — typically in response to engine events:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
const updateUIs = () => uis.custom.get("modelsList").updateInstances()
|
|
92
|
+
fragments.list.onItemSet.add(updateUIs)
|
|
93
|
+
fragments.list.onItemDeleted.add(updateUIs)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Custom setup files
|
|
99
|
+
|
|
100
|
+
Each setup file is the bridge between a custom BIM component and the platform (see the BIM-component guide in `docs/`: [./bim-components/overview.md](./bim-components/overview.md)). This is where wiring lands: event listeners, UI updates, and configuration go here — not in the component's constructor.
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
// setups/qto-manager.ts
|
|
104
|
+
export const qtoManager = (components: OBC.Components) => {
|
|
105
|
+
const uis = getUIManager(components)
|
|
106
|
+
const qtoManager = components.get(QtoManager)
|
|
107
|
+
|
|
108
|
+
qtoManager.onStateChanged.add((states) => {
|
|
109
|
+
if (!states.includes("value")) return
|
|
110
|
+
uis.custom.get("qtosTable").updateInstances()
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
```
|
package/docs/previewing.md
CHANGED
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
# Previewing Apps During Development
|
|
2
|
-
|
|
3
|
-
That Open Platform apps can only be previewed correctly within the platform context — opening `localhost:4000` directly in the browser will just bring the app bundle. The app must be loaded from inside a project on the platform as it gives context.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Step 1: Start the dev server
|
|
8
|
-
|
|
9
|
-
In the project root, run:
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
npm run dev
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
This invokes `thatopen serve` under the hood — the same CLI installed during setup. It performs a special build and serves the bundle on **port 4000**. Keep this process running throughout your development session.
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## Step 2: Open the app in the platform
|
|
20
|
-
|
|
21
|
-
Once the dev server is running:
|
|
22
|
-
|
|
23
|
-
1. Go to [https://dev.platform.thatopen.com](https://dev.platform.thatopen.com) and enter a project. If no project exists yet, create one first.
|
|
24
|
-
2. In the project sidebar, click **Local App**.
|
|
25
|
-
3. Click **Get Started**.
|
|
26
|
-
|
|
27
|
-
The platform will load the locally-running app from port 4000 and render it inside the project context, with full access to its models, data, and users.
|
|
28
|
-
|
|
29
|
-
The resulting URL follows this pattern:
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
https://dev.platform.thatopen.com/dashboard/projects/{projectId}/apps/local-app
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
where `{projectId}` is the ID of the project. Bookmark this URL to return quickly during development.
|
|
36
|
-
|
|
37
|
-
> The dev server must be running before opening this URL. If the bundle is not being served on port 4000, the platform will fail to load the app.
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
## When to read this guide
|
|
42
|
-
|
|
43
|
-
- When you want to see, run, or preview the app
|
|
44
|
-
- When you have run `npm run dev` and don't know what to do next
|
|
45
|
-
- When the app is not showing up in the platform
|
|
1
|
+
# Previewing Apps During Development
|
|
2
|
+
|
|
3
|
+
That Open Platform apps can only be previewed correctly within the platform context — opening `localhost:4000` directly in the browser will just bring the app bundle. The app must be loaded from inside a project on the platform as it gives context.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Step 1: Start the dev server
|
|
8
|
+
|
|
9
|
+
In the project root, run:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm run dev
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
This invokes `thatopen serve` under the hood — the same CLI installed during setup. It performs a special build and serves the bundle on **port 4000**. Keep this process running throughout your development session.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Step 2: Open the app in the platform
|
|
20
|
+
|
|
21
|
+
Once the dev server is running:
|
|
22
|
+
|
|
23
|
+
1. Go to [https://dev.platform.thatopen.com](https://dev.platform.thatopen.com) and enter a project. If no project exists yet, create one first.
|
|
24
|
+
2. In the project sidebar, click **Local App**.
|
|
25
|
+
3. Click **Get Started**.
|
|
26
|
+
|
|
27
|
+
The platform will load the locally-running app from port 4000 and render it inside the project context, with full access to its models, data, and users.
|
|
28
|
+
|
|
29
|
+
The resulting URL follows this pattern:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
https://dev.platform.thatopen.com/dashboard/projects/{projectId}/apps/local-app
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
where `{projectId}` is the ID of the project. Bookmark this URL to return quickly during development.
|
|
36
|
+
|
|
37
|
+
> The dev server must be running before opening this URL. If the bundle is not being served on port 4000, the platform will fail to load the app.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## When to read this guide
|
|
42
|
+
|
|
43
|
+
- When you want to see, run, or preview the app
|
|
44
|
+
- When you have run `npm run dev` and don't know what to do next
|
|
45
|
+
- When the app is not showing up in the platform
|
package/docs/publishing.md
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
# Publishing an App
|
|
2
|
-
|
|
3
|
-
Publishing to the That Open Platform is a two-step process: authenticate first, then publish.
|
|
4
|
-
|
|
5
|
-
## Step 1: Authenticate
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
thatopen login
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
This stores credentials globally at `~/.thatopen/config.json`. Authentication persists across sessions — you only need to do this once per machine.
|
|
12
|
-
|
|
13
|
-
**Options:**
|
|
14
|
-
|
|
15
|
-
| Flag | Purpose |
|
|
16
|
-
|---|---|
|
|
17
|
-
| `--token <token>` | Non-interactive login (CI, scripts) |
|
|
18
|
-
| `--local` | Store credentials in the project directory (`.thatopen`) instead of globally |
|
|
19
|
-
|
|
20
|
-
## Step 2: Publish
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
thatopen publish
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
This builds the app and uploads it to the platform. The command handles the build step automatically unless told otherwise.
|
|
27
|
-
|
|
28
|
-
**Common options:**
|
|
29
|
-
|
|
30
|
-
| Flag | Purpose |
|
|
31
|
-
|---|---|
|
|
32
|
-
| `--name <name>` | Override the published app name |
|
|
33
|
-
| `--version-tag <tag>` | Tag the release (e.g. `v1.2.0`) |
|
|
34
|
-
| `--skip-build` | Skip the build step if the bundle is already built |
|
|
35
|
-
| `--app-id <id>` | Publish to a specific existing app |
|
|
1
|
+
# Publishing an App
|
|
2
|
+
|
|
3
|
+
Publishing to the That Open Platform is a two-step process: authenticate first, then publish.
|
|
4
|
+
|
|
5
|
+
## Step 1: Authenticate
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
thatopen login
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This stores credentials globally at `~/.thatopen/config.json`. Authentication persists across sessions — you only need to do this once per machine.
|
|
12
|
+
|
|
13
|
+
**Options:**
|
|
14
|
+
|
|
15
|
+
| Flag | Purpose |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `--token <token>` | Non-interactive login (CI, scripts) |
|
|
18
|
+
| `--local` | Store credentials in the project directory (`.thatopen`) instead of globally |
|
|
19
|
+
|
|
20
|
+
## Step 2: Publish
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
thatopen publish
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
This builds the app and uploads it to the platform. The command handles the build step automatically unless told otherwise.
|
|
27
|
+
|
|
28
|
+
**Common options:**
|
|
29
|
+
|
|
30
|
+
| Flag | Purpose |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `--name <name>` | Override the published app name |
|
|
33
|
+
| `--version-tag <tag>` | Tag the release (e.g. `v1.2.0`) |
|
|
34
|
+
| `--skip-build` | Skip the build step if the bundle is already built |
|
|
35
|
+
| `--app-id <id>` | Publish to a specific existing app |
|
package/docs/scaffolding.md
CHANGED
|
@@ -1,54 +1,71 @@
|
|
|
1
|
-
# Scaffolding a New App
|
|
2
|
-
|
|
3
|
-
When starting a new platform app from scratch, **always use the CLI to scaffold the project — never create the files manually.** The CLI produces the exact project structure these docs describe, correctly configured and with dependencies installed. Writing the scaffold by hand defeats the purpose of the tool and risks inconsistencies.
|
|
4
|
-
|
|
5
|
-
## Command
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
thatopen create <app-name>
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
Use `.` as the name to scaffold in the current directory:
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
thatopen create .
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
This copies the template files into the target directory and runs `npm install` automatically.
|
|
18
|
-
|
|
19
|
-
## Templates
|
|
20
|
-
|
|
21
|
-
Pass `--template <name>` to choose a template. The default is `bim`.
|
|
22
|
-
|
|
23
|
-
| Template | When to use |
|
|
24
|
-
|---|---|
|
|
25
|
-
| `bim` (default) | Standard BIM viewer app
|
|
26
|
-
| `
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
1
|
+
# Scaffolding a New App
|
|
2
|
+
|
|
3
|
+
When starting a new platform app from scratch, **always use the CLI to scaffold the project — never create the files manually.** The CLI produces the exact project structure these docs describe, correctly configured and with dependencies installed. Writing the scaffold by hand defeats the purpose of the tool and risks inconsistencies.
|
|
4
|
+
|
|
5
|
+
## Command
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
thatopen create <app-name>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Use `.` as the name to scaffold in the current directory:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
thatopen create .
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This copies the template files into the target directory and runs `npm install` automatically.
|
|
18
|
+
|
|
19
|
+
## Templates
|
|
20
|
+
|
|
21
|
+
Pass `--template <name>` to choose a template. The default is `bim`.
|
|
22
|
+
|
|
23
|
+
| Template | When to use |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `bim` (default) | Standard BIM viewer app on the public engine libraries. |
|
|
26
|
+
| `bim-beta` | Same as `bim` but on the private **beta** engine libraries (`@thatopen-platform/*-beta`) — the line the platform currently runs. Use this for founding members (see below). |
|
|
27
|
+
| `default` | Minimal shell — just shows platform context. Use only when you explicitly want to start from scratch without any viewer. |
|
|
28
|
+
|
|
29
|
+
If no template is specified, use `bim`.
|
|
30
|
+
|
|
31
|
+
## Beta libraries (founding members) — use the `bim-beta` template
|
|
32
|
+
|
|
33
|
+
**Before scaffolding, ask the user whether they have beta access** and want the latest engine
|
|
34
|
+
libraries. If so, scaffold with the `bim-beta` template:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
thatopen create <app-name> -t bim-beta
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`bim-beta` is the `bim` viewer wired directly to the private `@thatopen-platform/*-beta` packages —
|
|
41
|
+
the **same library line the platform currently runs**. Prefer it whenever the user has beta access:
|
|
42
|
+
the public `bim` template uses older libraries that can error at runtime against a beta platform.
|
|
43
|
+
|
|
44
|
+
Founding members have **permanent** beta access. The beta packages are private, so the user must
|
|
45
|
+
have their beta access token configured in npm, or `npm install` will fail with a 401/403.
|
|
46
|
+
|
|
47
|
+
## What the scaffold produces
|
|
48
|
+
|
|
49
|
+
The `bim` template generates the full structure described in the **Project Structure** section of [./app-architecture.md](./app-architecture.md):
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
src/
|
|
53
|
+
├── bim-components/
|
|
54
|
+
├── ui-components/
|
|
55
|
+
├── setups/
|
|
56
|
+
├── app.ts
|
|
57
|
+
├── globals.ts
|
|
58
|
+
└── main.ts
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
All platform built-ins (`AppManager`, `UIManager`, `ViewportsManager`) are already wired up in the generated `main.ts`. There is nothing to manually wire at the entry point — just extend from there.
|
|
62
|
+
|
|
63
|
+
## Starting the dev server
|
|
64
|
+
|
|
65
|
+
After scaffolding, start the local dev server:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
thatopen serve
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
This launches an esbuild watch process that rebundles on every file change and serves the app with live reload. No configuration needed.
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
# Async Actions
|
|
2
|
-
|
|
3
|
-
## Async button handler
|
|
4
|
-
|
|
5
|
-
When a button triggers an async operation, set `target.loading = true` at the start and `false` when done — including in error paths:
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
const onClick = async ({ target }: { target: BUI.Button }) => {
|
|
9
|
-
target.loading = true
|
|
10
|
-
try {
|
|
11
|
-
await doSomething()
|
|
12
|
-
} finally {
|
|
13
|
-
target.loading = false
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
Always restore `target.loading = false` in error paths. If an exception is thrown and loading is not reset, the button stays stuck in the loading state.
|
|
1
|
+
# Async Actions
|
|
2
|
+
|
|
3
|
+
## Async button handler
|
|
4
|
+
|
|
5
|
+
When a button triggers an async operation, set `target.loading = true` at the start and `false` when done — including in error paths:
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
const onClick = async ({ target }: { target: BUI.Button }) => {
|
|
9
|
+
target.loading = true
|
|
10
|
+
try {
|
|
11
|
+
await doSomething()
|
|
12
|
+
} finally {
|
|
13
|
+
target.loading = false
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Always restore `target.loading = false` in error paths. If an exception is thrown and loading is not reset, the button stays stuck in the loading state.
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
# Confirmation Dialog
|
|
2
|
-
|
|
3
|
-
The standard way to ask the user to confirm a destructive or irreversible action is a `contextMenuTemplate` on a `bim-button`. The menu opens lazily when clicked and contains Confirm / Cancel buttons.
|
|
4
|
-
|
|
5
|
-
## Setup
|
|
6
|
-
|
|
7
|
-
`contextMenuTemplate` must always be assigned via `BUI.ref` — never inline in `BUI.html`:
|
|
8
|
-
|
|
9
|
-
```ts
|
|
10
|
-
const onBtnCreated = (e?: Element) => {
|
|
11
|
-
if (!e) return
|
|
12
|
-
const btn = e as BUI.Button
|
|
13
|
-
btn.contextMenuTemplate = () => {
|
|
14
|
-
const onConfirm = async ({ target }: { target: BUI.Button }) => {
|
|
15
|
-
target.loading = true
|
|
16
|
-
await doSomething()
|
|
17
|
-
target.loading = false
|
|
18
|
-
BUI.ContextMenu.removeMenus()
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const onCancel = () => {
|
|
22
|
-
BUI.ContextMenu.removeMenus()
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return BUI.html`
|
|
26
|
-
<bim-context-menu>
|
|
27
|
-
<bim-button @click=${onConfirm} label="Confirm"></bim-button>
|
|
28
|
-
<bim-button @click=${onCancel} label="Cancel"></bim-button>
|
|
29
|
-
</bim-context-menu>
|
|
30
|
-
`
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return BUI.html`<bim-button ${BUI.ref(onBtnCreated)} icon="delete"></bim-button>`
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Closing the menu
|
|
38
|
-
|
|
39
|
-
Call `BUI.ContextMenu.removeMenus()` after the action completes (or is cancelled) to dismiss the popup. Without it, the menu stays open after the user clicks.
|
|
1
|
+
# Confirmation Dialog
|
|
2
|
+
|
|
3
|
+
The standard way to ask the user to confirm a destructive or irreversible action is a `contextMenuTemplate` on a `bim-button`. The menu opens lazily when clicked and contains Confirm / Cancel buttons.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
`contextMenuTemplate` must always be assigned via `BUI.ref` — never inline in `BUI.html`:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
const onBtnCreated = (e?: Element) => {
|
|
11
|
+
if (!e) return
|
|
12
|
+
const btn = e as BUI.Button
|
|
13
|
+
btn.contextMenuTemplate = () => {
|
|
14
|
+
const onConfirm = async ({ target }: { target: BUI.Button }) => {
|
|
15
|
+
target.loading = true
|
|
16
|
+
await doSomething()
|
|
17
|
+
target.loading = false
|
|
18
|
+
BUI.ContextMenu.removeMenus()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const onCancel = () => {
|
|
22
|
+
BUI.ContextMenu.removeMenus()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return BUI.html`
|
|
26
|
+
<bim-context-menu>
|
|
27
|
+
<bim-button @click=${onConfirm} label="Confirm"></bim-button>
|
|
28
|
+
<bim-button @click=${onCancel} label="Cancel"></bim-button>
|
|
29
|
+
</bim-context-menu>
|
|
30
|
+
`
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return BUI.html`<bim-button ${BUI.ref(onBtnCreated)} icon="delete"></bim-button>`
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Closing the menu
|
|
38
|
+
|
|
39
|
+
Call `BUI.ContextMenu.removeMenus()` after the action completes (or is cancelled) to dismiss the popup. Without it, the menu stays open after the user clicks.
|