@thatopen/services 0.0.4 → 0.0.5
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 +24 -263
- package/dist/cli/commands/swap.d.ts +3 -0
- package/dist/cli/lib/beta.d.ts +2 -0
- package/dist/cli/lib/config.d.ts +2 -0
- package/dist/cli.js +85 -126
- package/dist/core/examples/apps.d.ts +1 -0
- package/dist/core/examples/components.d.ts +1 -0
- package/dist/core/examples/execution.d.ts +1 -0
- package/dist/core/examples/file-metadata.d.ts +1 -0
- package/dist/core/examples/files.d.ts +1 -0
- package/dist/core/examples/folders.d.ts +1 -0
- package/dist/core/examples/hidden-files.d.ts +1 -0
- package/dist/core/examples/icons.d.ts +1 -0
- package/dist/core/examples/permissions.d.ts +1 -0
- package/dist/types/items.d.ts +2 -0
- package/docs/builtin/paths.json +54 -0
- package/docs/cli/create.md +28 -0
- package/docs/cli/local-server.md +38 -0
- package/docs/cli/login.md +32 -0
- package/docs/cli/paths.json +30 -0
- package/docs/cli/publish.md +31 -0
- package/docs/cli/run.md +26 -0
- package/docs/cli/serve.md +43 -0
- package/docs/cli/swap.md +30 -0
- package/docs/client/paths.json +38 -0
- package/package.json +8 -10
- package/resources/AGENTS.md +39 -0
- package/src/built-in/AppManager/example.ts +86 -0
- package/src/built-in/CDEManager/example.ts +214 -0
- package/src/built-in/CDEManager/examples/FileEditing/example.ts +226 -0
- package/src/built-in/CDEManager/examples/FileMoves/example.ts +186 -0
- package/src/built-in/CDEManager/examples/FileOperations/example.ts +295 -0
- package/src/built-in/CDEManager/examples/FileTransfers/example.ts +210 -0
- package/src/built-in/CDEManager/examples/FolderManagement/example.ts +230 -0
- package/src/built-in/CDEManager/examples/MetadataSchema/example.ts +230 -0
- package/src/built-in/CDEManager/examples/MetadataViews/example.ts +166 -0
- package/src/built-in/CDEManager/examples/ProjectConfig/example.ts +177 -0
- package/src/built-in/FileList/example.ts +107 -0
- package/src/built-in/TabbedNavigation/example.ts +115 -0
- package/src/built-in/ViewportsManager/example.ts +106 -0
- package/src/cli/templates/{shared/app → app}/vite.config.js +42 -23
- package/src/cli/templates/{shared/cloud → cloud-component}/vite.config.js +46 -27
- package/src/cli/templates/shared/AGENTS.md +8 -30
- package/src/cli/templates/shared/CLAUDE.md +1 -1
- package/AGENTS.md +0 -86
- package/CONTEXT.md +0 -258
- package/dist/built-in/index.d.ts +0 -723
- package/dist/cli/commands/create-tests.d.ts +0 -3
- package/dist/cli/commands/serve-tests.d.ts +0 -3
- package/docs/access-backend-data.md +0 -19
- package/docs/app-architecture.md +0 -94
- package/docs/app-layout.md +0 -139
- package/docs/app-wiring.md +0 -123
- package/docs/bim-components/coding-conventions.md +0 -128
- package/docs/bim-components/element-collections.md +0 -69
- package/docs/bim-components/expose-events.md +0 -84
- package/docs/bim-components/library-examples.md +0 -28
- package/docs/bim-components/observable-collections.md +0 -83
- package/docs/bim-components/overview.md +0 -160
- package/docs/bim-components/per-frame-updates.md +0 -20
- package/docs/bim-components/save-and-restore-state.md +0 -21
- package/docs/bim-components/setup-and-cleanup.md +0 -64
- package/docs/bim-components/type-conventions.md +0 -49
- package/docs/bim-components/user-driven-object-creation.md +0 -56
- package/docs/cli-setup.md +0 -54
- package/docs/cloud-components.md +0 -74
- package/docs/connect-logic-to-ui.md +0 -113
- package/docs/previewing.md +0 -45
- package/docs/publishing.md +0 -35
- package/docs/scaffolding.md +0 -71
- package/docs/ui-components/async-actions.md +0 -18
- package/docs/ui-components/confirmation-dialog.md +0 -39
- package/docs/ui-components/data-table.md +0 -185
- package/docs/ui-components/display-text.md +0 -39
- package/docs/ui-components/inline-form.md +0 -44
- package/docs/ui-components/library-examples.md +0 -24
- package/docs/ui-components/overview.md +0 -194
- package/docs/ui-components/rendering-patterns.md +0 -129
- package/docs/ui-components/sections-layout.md +0 -123
- package/docs/update-grid-elements.md +0 -46
- package/docs/using-colors.md +0 -32
- package/docs/using-icons.md +0 -37
- package/src/cli/templates/bim/src/bim-components/CloudRunner/src/index.ts +0 -1
- package/src/cli/templates/bim/src/bim-components/CloudRunner/src/types.ts +0 -5
- package/src/cli/templates/bim/src/bim-components/index.ts +0 -1
- package/src/cli/templates/bim/src/globals.ts +0 -1
- package/src/cli/templates/bim/src/setups/index.ts +0 -3
- package/src/cli/templates/bim/src/ui-components/app-info-section/index.ts +0 -26
- package/src/cli/templates/bim/src/ui-components/app-info-section/src/index.ts +0 -1
- package/src/cli/templates/bim/src/ui-components/cloud-runner-section/index.ts +0 -37
- package/src/cli/templates/bim/src/ui-components/cloud-runner-section/src/index.ts +0 -1
- package/src/cli/templates/bim/src/ui-components/index.ts +0 -2
- package/src/cli/templates/bim-beta/CONTEXT.md +0 -241
- package/src/cli/templates/bim-beta/package.json +0 -25
- package/src/cli/templates/bim-beta/src/app.ts +0 -16
- package/src/cli/templates/bim-beta/src/bim-components/CloudRunner/index.ts +0 -91
- package/src/cli/templates/bim-beta/src/main.ts +0 -93
- package/src/cli/templates/bim-beta/src/setups/cloud-runner.ts +0 -13
- package/src/cli/templates/bim-beta/src/setups/ui-manager.ts +0 -27
- package/src/cli/templates/bim-beta/src/setups/viewports-manager.ts +0 -22
- package/src/cli/templates/bim-beta/src/ui-components/app-info-section/src/types.ts +0 -15
- package/src/cli/templates/bim-beta/src/ui-components/cloud-runner-section/src/types.ts +0 -14
- package/src/cli/templates/cloud/_thatopen +0 -5
- package/src/cli/templates/cloud/package.json +0 -22
- package/src/cli/templates/cloud-test/CONTEXT.md +0 -56
- package/src/cli/templates/cloud-test/src/main.ts +0 -565
- package/src/cli/templates/default/CONTEXT.md +0 -92
- package/src/cli/templates/default/package.json +0 -18
- package/src/cli/templates/default/src/main.ts +0 -62
- package/src/cli/templates/test/CONTEXT.md +0 -53
- package/src/cli/templates/test/package.json +0 -25
- package/src/cli/templates/test/src/main.ts +0 -955
- /package/src/cli/templates/{bim/CONTEXT.md → app/README.md} +0 -0
- /package/src/cli/templates/{shared/app → app}/index.html +0 -0
- /package/src/cli/templates/{bim → app}/package.json +0 -0
- /package/src/cli/templates/{bim → app}/src/app.ts +0 -0
- /package/src/cli/templates/{bim → app}/src/bim-components/CloudRunner/index.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/bim-components/CloudRunner/src/index.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/bim-components/CloudRunner/src/types.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/bim-components/index.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/globals.ts +0 -0
- /package/src/cli/templates/{bim → app}/src/main.ts +0 -0
- /package/src/cli/templates/{bim → app}/src/setups/cloud-runner.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/setups/index.ts +0 -0
- /package/src/cli/templates/{bim → app}/src/setups/ui-manager.ts +0 -0
- /package/src/cli/templates/{bim → app}/src/setups/viewports-manager.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/ui-components/app-info-section/index.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/ui-components/app-info-section/src/index.ts +0 -0
- /package/src/cli/templates/{bim → app}/src/ui-components/app-info-section/src/types.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/ui-components/cloud-runner-section/index.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/ui-components/cloud-runner-section/src/index.ts +0 -0
- /package/src/cli/templates/{bim → app}/src/ui-components/cloud-runner-section/src/types.ts +0 -0
- /package/src/cli/templates/{bim-beta → app}/src/ui-components/index.ts +0 -0
- /package/src/cli/templates/{shared/app → app}/tsconfig.json +0 -0
- /package/src/cli/templates/{cloud/CONTEXT.md → cloud-component/README.md} +0 -0
- /package/src/cli/templates/{cloud-test → cloud-component}/_thatopen +0 -0
- /package/src/cli/templates/{cloud → cloud-component}/declarations.json +0 -0
- /package/src/cli/templates/{cloud-test → cloud-component}/package.json +0 -0
- /package/src/cli/templates/{cloud → cloud-component}/src/main.ts +0 -0
- /package/src/cli/templates/{shared/cloud → cloud-component}/tsconfig.json +0 -0
|
@@ -1,113 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
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 +0,0 @@
|
|
|
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 +0,0 @@
|
|
|
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,185 +0,0 @@
|
|
|
1
|
-
# Data Table
|
|
2
|
-
|
|
3
|
-
> **Structural rule:** A `<bim-table>` always lives in its own dedicated UI component (e.g., `collisionsTable`, `elementsTable`). Never define a table inline inside another template such as a `panel-section`. The consuming template receives the table component as an external reference and composes it in.
|
|
4
|
-
|
|
5
|
-
`BUI.Table<TData>` is the standard component for displaying tabular data. `TData` is a record type where each key is a column name and each value is the cell's data type.
|
|
6
|
-
|
|
7
|
-
## Data Type
|
|
8
|
-
|
|
9
|
-
Define a named type following the `{PascalCase(identifier)}Data` convention and export it from `src/types.ts`:
|
|
10
|
-
|
|
11
|
-
```ts
|
|
12
|
-
export type MyComponentTableData = {
|
|
13
|
-
Name: string
|
|
14
|
-
Count: number
|
|
15
|
-
Actions: string // reserved for per-row interaction buttons
|
|
16
|
-
}
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
`Actions: string` is the conventional column for per-row interaction buttons — typed as `string` (placeholder) and rendered via `dataTransform`.
|
|
20
|
-
|
|
21
|
-
Column names follow a casing rule: **PascalCase** for columns displayed to the user (`Name`, `Count`), **camelCase** for internal data columns not meant to be shown (`id`, `modelId`).
|
|
22
|
-
|
|
23
|
-
## Template
|
|
24
|
-
|
|
25
|
-
The table element is created via `BUI.html` and configured imperatively once mounted using `BUI.ref`:
|
|
26
|
-
|
|
27
|
-
```ts
|
|
28
|
-
export const myTableTemplate: BUI.StatefullComponent<MyTableState> = ({ components }) => {
|
|
29
|
-
const onCreated = (e?: Element) => {
|
|
30
|
-
if (!e) return
|
|
31
|
-
const table = e as BUI.Table<MyTableData>
|
|
32
|
-
table.loadFunction = async () => {
|
|
33
|
-
// return BUI.TableGroupData<MyTableData>[]
|
|
34
|
-
}
|
|
35
|
-
table.loadData(true)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return BUI.html`
|
|
39
|
-
<bim-table ${BUI.ref(onCreated)}></bim-table>
|
|
40
|
-
`
|
|
41
|
-
}
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
**For async data** — assign `loadFunction` and call `loadData()`. Passing `true` forces a fresh fetch. `loadData()` does nothing if data already exists — to re-trigger, first reset: `table.data = []`.
|
|
45
|
-
|
|
46
|
-
**For synchronous data** — assign `table.data` directly:
|
|
47
|
-
|
|
48
|
-
```ts
|
|
49
|
-
table.data = items.map(item => ({ data: { Name: item.name, Count: item.count } }))
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### Data Structure
|
|
53
|
-
|
|
54
|
-
```ts
|
|
55
|
-
{
|
|
56
|
-
data: { Name: "Juan", Count: 5 }, // required
|
|
57
|
-
children?: [...] // optional — nested rows
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
The preferred pattern for hierarchical data is a **flat list combined with `groupedBy`**. Reserve `children` for fixed, explicit hierarchies.
|
|
62
|
-
|
|
63
|
-
## Empty State
|
|
64
|
-
|
|
65
|
-
```ts
|
|
66
|
-
return BUI.html`
|
|
67
|
-
<bim-table ${BUI.ref(onCreated)}>
|
|
68
|
-
<div slot="missing-data" style="display: flex; flex-direction: column; align-items: center;">
|
|
69
|
-
<bim-label>No data loaded.</bim-label>
|
|
70
|
-
<bim-button @click=${() => table.loadData()} label="Load Data"></bim-button>
|
|
71
|
-
</div>
|
|
72
|
-
</bim-table>
|
|
73
|
-
`
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## Error State
|
|
77
|
-
|
|
78
|
-
```ts
|
|
79
|
-
return BUI.html`
|
|
80
|
-
<bim-table ${BUI.ref(onCreated)}>
|
|
81
|
-
<div slot="error-loading" style="display: flex; flex-direction: column; align-items: center;">
|
|
82
|
-
<bim-label data-table-element="error-message"></bim-label>
|
|
83
|
-
<bim-button @click=${() => table.loadData()} label="Try Again"></bim-button>
|
|
84
|
-
</div>
|
|
85
|
-
</bim-table>
|
|
86
|
-
`
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
## Column Configuration and dataTransform
|
|
90
|
-
|
|
91
|
-
Column layout, visibility, and `dataTransform` are fixed properties — configure them in `onInstanceCreated`, not in the template.
|
|
92
|
-
|
|
93
|
-
```ts
|
|
94
|
-
table.headersHidden = true
|
|
95
|
-
table.noIndentation = true
|
|
96
|
-
table.columns = [
|
|
97
|
-
"Name",
|
|
98
|
-
"Count",
|
|
99
|
-
{ name: "Actions", width: "auto" },
|
|
100
|
-
]
|
|
101
|
-
table.groupedBy = ["Type"]
|
|
102
|
-
table.preserveStructureOnFilter = true
|
|
103
|
-
|
|
104
|
-
table.dataTransform = {
|
|
105
|
-
Name: (value) => BUI.html`<bim-label>${value}</bim-label>`,
|
|
106
|
-
Actions: (_, rowData) => {
|
|
107
|
-
const { id } = rowData
|
|
108
|
-
if (!id) return _
|
|
109
|
-
return BUI.html`<bim-button @click=${() => doSomething(id)}></bim-button>`
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
> `noIndentation` and `groupedBy` are incompatible.
|
|
115
|
-
|
|
116
|
-
**Column visibility:**
|
|
117
|
-
```ts
|
|
118
|
-
table.visibleColumns = ["Name", "Actions"] // most columns hidden
|
|
119
|
-
table.hiddenColumns = ["id", "extension"] // most columns visible
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
> Everything rendered inside a table lives in the Shadow DOM. CSS classes cannot be applied — all styling must use inline styles.
|
|
123
|
-
|
|
124
|
-
`rowData` can be mutated directly inside a transform:
|
|
125
|
-
|
|
126
|
-
```ts
|
|
127
|
-
table.dataTransform = {
|
|
128
|
-
LoadBearing: (value, rowData) => {
|
|
129
|
-
const onChange = (e: Event) => {
|
|
130
|
-
const input = e.target
|
|
131
|
-
if (!(input instanceof BUI.Checkbox)) return
|
|
132
|
-
rowData.LoadBearing = input.checked
|
|
133
|
-
}
|
|
134
|
-
return BUI.html`<bim-checkbox @change=${onChange} .checked=${value}></bim-checkbox>`
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
## Grouping
|
|
140
|
-
|
|
141
|
-
```ts
|
|
142
|
-
table.groupedBy = ["Discipline", "State"] // apply
|
|
143
|
-
table.groupedBy = [] // clear
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
`groupingTransform` maps column values to arrays defining multi-level hierarchy:
|
|
147
|
-
|
|
148
|
-
```ts
|
|
149
|
-
table.groupingTransform = {
|
|
150
|
-
State: (value) => {
|
|
151
|
-
if (value === "S0") return ["Work in Progress"]
|
|
152
|
-
if (value.includes(".")) return ["Shared States", parentState, value]
|
|
153
|
-
return ["Shared States", value]
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
`BUI.Table.flattenData` flattens a nested group structure — useful for computing aggregate values:
|
|
159
|
-
|
|
160
|
-
```ts
|
|
161
|
-
const children = BUI.Table.flattenData(group.data.children)
|
|
162
|
-
const total = children.reduce((sum, { data }) => sum + (Number(data.Count) || 0), 0)
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
## Row Events (rowcreated)
|
|
166
|
-
|
|
167
|
-
```ts
|
|
168
|
-
const rowHandlers = new WeakMap<Element, { handleClick: () => void }>()
|
|
169
|
-
|
|
170
|
-
table.addEventListener("rowcreated", (e) => {
|
|
171
|
-
if (!("detail" in e)) return
|
|
172
|
-
const { row } = (e as { detail: BUI.RowCreatedEventDetail<MyTableData> }).detail
|
|
173
|
-
|
|
174
|
-
const existing = rowHandlers.get(row)
|
|
175
|
-
if (existing) row.removeEventListener("click", existing.handleClick)
|
|
176
|
-
|
|
177
|
-
const handleClick = () => {
|
|
178
|
-
if (!row.groupData?.data) return
|
|
179
|
-
const { Name } = row.groupData.data
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
rowHandlers.set(row, { handleClick })
|
|
183
|
-
row.addEventListener("click", handleClick)
|
|
184
|
-
})
|
|
185
|
-
```
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# Display Text
|
|
2
|
-
|
|
3
|
-
Always use `<bim-label>` for all text content inside templates.
|
|
4
|
-
|
|
5
|
-
## Static text
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
return BUI.html`<bim-label>Fixed text</bim-label>`
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Dynamic text (template interpolation)
|
|
12
|
-
|
|
13
|
-
```ts
|
|
14
|
-
return BUI.html`<bim-label>${someText}</bim-label>`
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## Updating text imperatively
|
|
18
|
-
|
|
19
|
-
Use `.textContent` to update a `bim-label` from outside the template. Never use `.label` — that property belongs to other components (`bim-button`, `bim-option`, etc.), not to `bim-label`:
|
|
20
|
-
|
|
21
|
-
```ts
|
|
22
|
-
const label = section.querySelector("bim-label")!
|
|
23
|
-
label.textContent = "Updated text" // ✓ correct
|
|
24
|
-
label.label = "Updated text" // ✗ avoid — .label is not a property of bim-label
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## The label attribute belongs to other components
|
|
28
|
-
|
|
29
|
-
`label` is an attribute/property of interactive components that display a text caption alongside an icon or control:
|
|
30
|
-
|
|
31
|
-
```ts
|
|
32
|
-
// ✓ correct — label attribute on button, option, etc.
|
|
33
|
-
BUI.html`<bim-button label="Confirm"></bim-button>`
|
|
34
|
-
BUI.html`<bim-option label="Model A"></bim-option>`
|
|
35
|
-
BUI.html`<bim-text-input label="Name" vertical></bim-text-input>`
|
|
36
|
-
|
|
37
|
-
// ✗ avoid — label is not a property of bim-label
|
|
38
|
-
BUI.html`<bim-label label="Some text"></bim-label>`
|
|
39
|
-
```
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# Inline Form (Context Menu)
|
|
2
|
-
|
|
3
|
-
To let the user create or edit an entity without leaving the current view, place a `<bim-panel-section fixed>` acting as a form inside a `contextMenuTemplate`. The form opens as a popup anchored to the trigger button.
|
|
4
|
-
|
|
5
|
-
```ts
|
|
6
|
-
const onBtnCreated = (e?: Element) => {
|
|
7
|
-
if (!e) return
|
|
8
|
-
const btn = e as BUI.Button
|
|
9
|
-
btn.contextMenuTemplate = () => {
|
|
10
|
-
const onSubmit = async ({ target }: { target: BUI.Button }) => {
|
|
11
|
-
const section = target.parentElement as BUI.PanelSection
|
|
12
|
-
section.valueTransform = {
|
|
13
|
-
name: (value: string) => value.trim(),
|
|
14
|
-
description: (value: string) => value.trim() || undefined,
|
|
15
|
-
}
|
|
16
|
-
const data = section.value as { name: string; description?: string }
|
|
17
|
-
target.loading = true
|
|
18
|
-
await doSomething(data)
|
|
19
|
-
target.loading = false
|
|
20
|
-
BUI.ContextMenu.removeMenus()
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return BUI.html`
|
|
24
|
-
<bim-context-menu style="padding: 0; max-height: none;">
|
|
25
|
-
<bim-panel-section style="width: 16rem;" label="New Item" fixed>
|
|
26
|
-
<bim-text-input vertical name="name" label="Name"></bim-text-input>
|
|
27
|
-
<bim-text-input vertical name="description" type="area" label="Description"></bim-text-input>
|
|
28
|
-
<bim-button @click=${onSubmit} label="Create"></bim-button>
|
|
29
|
-
</bim-panel-section>
|
|
30
|
-
</bim-context-menu>
|
|
31
|
-
`
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return BUI.html`<bim-button ${BUI.ref(onBtnCreated)} label="New Item"></bim-button>`
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Rules
|
|
39
|
-
|
|
40
|
-
- `contextMenuTemplate` must be assigned via `BUI.ref`, never inline in `BUI.html`.
|
|
41
|
-
- Inputs inside the form require the `name` attribute for `section.value` to pick them up.
|
|
42
|
-
- The `<bim-panel-section>` acting as a form always has `fixed` so it can't be collapsed.
|
|
43
|
-
- Use `section.valueTransform` to sanitize or coerce values before reading them.
|
|
44
|
-
- Call `BUI.ContextMenu.removeMenus()` after a successful submit to close the popup.
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# Library Examples
|
|
2
|
-
|
|
3
|
-
Before writing any BUI component implementation, check whether an official example covers the pattern you need. Official examples are the best starting point: they show correct usage of BUI elements, proper rendering patterns, and idiomatic API usage.
|
|
4
|
-
|
|
5
|
-
## How to find an example
|
|
6
|
-
|
|
7
|
-
1. Fetch the `paths.json` below. Do not summarize the response — retain the full JSON in context and use the descriptions to reason about which examples are relevant.
|
|
8
|
-
2. Use the descriptions in the JSON to reason about which examples best match the user's intent. Prefer semantic matching over path name matching — a description may cover what the user needs even if the component name doesn't match exactly.
|
|
9
|
-
3. Only proceed to fetch an example if its description confirms that it directly covers the user's intent, or that it can serve as a building block for composing a new custom component. Do not fetch speculatively.
|
|
10
|
-
4. Construct the full URL: `{base_url}{path_entry}` and fetch the example file to use as your implementation reference.
|
|
11
|
-
|
|
12
|
-
Note that some components have multiple examples for different use cases — `Table` for instance has separate entries for `Searching`, `Grouping`, `ExportingData`, and `DataTransform`. Check all relevant ones.
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## Repository
|
|
17
|
-
|
|
18
|
-
### engine_ui-components
|
|
19
|
-
BUI primitives from `@thatopen/ui` — the `packages/core/` entries.
|
|
20
|
-
|
|
21
|
-
- **paths.json**: `https://raw.githubusercontent.com/ThatOpen/engine_ui-components/refs/heads/main/examples/paths.json`
|
|
22
|
-
- **Base URL**: `https://raw.githubusercontent.com/ThatOpen/engine_ui-components/refs/heads/main/`
|
|
23
|
-
|
|
24
|
-
> The paths.json also contains entries under `packages/obc/` (OBC-connected tables and charts like `SpatialTree`, `ModelsList`, etc.). Those are also valid UI components — feel free to check them if the user needs that kind of structured data display.
|