@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.
Files changed (140) hide show
  1. package/README.md +24 -263
  2. package/dist/cli/commands/swap.d.ts +3 -0
  3. package/dist/cli/lib/beta.d.ts +2 -0
  4. package/dist/cli/lib/config.d.ts +2 -0
  5. package/dist/cli.js +85 -126
  6. package/dist/core/examples/apps.d.ts +1 -0
  7. package/dist/core/examples/components.d.ts +1 -0
  8. package/dist/core/examples/execution.d.ts +1 -0
  9. package/dist/core/examples/file-metadata.d.ts +1 -0
  10. package/dist/core/examples/files.d.ts +1 -0
  11. package/dist/core/examples/folders.d.ts +1 -0
  12. package/dist/core/examples/hidden-files.d.ts +1 -0
  13. package/dist/core/examples/icons.d.ts +1 -0
  14. package/dist/core/examples/permissions.d.ts +1 -0
  15. package/dist/types/items.d.ts +2 -0
  16. package/docs/builtin/paths.json +54 -0
  17. package/docs/cli/create.md +28 -0
  18. package/docs/cli/local-server.md +38 -0
  19. package/docs/cli/login.md +32 -0
  20. package/docs/cli/paths.json +30 -0
  21. package/docs/cli/publish.md +31 -0
  22. package/docs/cli/run.md +26 -0
  23. package/docs/cli/serve.md +43 -0
  24. package/docs/cli/swap.md +30 -0
  25. package/docs/client/paths.json +38 -0
  26. package/package.json +8 -10
  27. package/resources/AGENTS.md +39 -0
  28. package/src/built-in/AppManager/example.ts +86 -0
  29. package/src/built-in/CDEManager/example.ts +214 -0
  30. package/src/built-in/CDEManager/examples/FileEditing/example.ts +226 -0
  31. package/src/built-in/CDEManager/examples/FileMoves/example.ts +186 -0
  32. package/src/built-in/CDEManager/examples/FileOperations/example.ts +295 -0
  33. package/src/built-in/CDEManager/examples/FileTransfers/example.ts +210 -0
  34. package/src/built-in/CDEManager/examples/FolderManagement/example.ts +230 -0
  35. package/src/built-in/CDEManager/examples/MetadataSchema/example.ts +230 -0
  36. package/src/built-in/CDEManager/examples/MetadataViews/example.ts +166 -0
  37. package/src/built-in/CDEManager/examples/ProjectConfig/example.ts +177 -0
  38. package/src/built-in/FileList/example.ts +107 -0
  39. package/src/built-in/TabbedNavigation/example.ts +115 -0
  40. package/src/built-in/ViewportsManager/example.ts +106 -0
  41. package/src/cli/templates/{shared/app → app}/vite.config.js +42 -23
  42. package/src/cli/templates/{shared/cloud → cloud-component}/vite.config.js +46 -27
  43. package/src/cli/templates/shared/AGENTS.md +8 -30
  44. package/src/cli/templates/shared/CLAUDE.md +1 -1
  45. package/AGENTS.md +0 -86
  46. package/CONTEXT.md +0 -258
  47. package/dist/built-in/index.d.ts +0 -723
  48. package/dist/cli/commands/create-tests.d.ts +0 -3
  49. package/dist/cli/commands/serve-tests.d.ts +0 -3
  50. package/docs/access-backend-data.md +0 -19
  51. package/docs/app-architecture.md +0 -94
  52. package/docs/app-layout.md +0 -139
  53. package/docs/app-wiring.md +0 -123
  54. package/docs/bim-components/coding-conventions.md +0 -128
  55. package/docs/bim-components/element-collections.md +0 -69
  56. package/docs/bim-components/expose-events.md +0 -84
  57. package/docs/bim-components/library-examples.md +0 -28
  58. package/docs/bim-components/observable-collections.md +0 -83
  59. package/docs/bim-components/overview.md +0 -160
  60. package/docs/bim-components/per-frame-updates.md +0 -20
  61. package/docs/bim-components/save-and-restore-state.md +0 -21
  62. package/docs/bim-components/setup-and-cleanup.md +0 -64
  63. package/docs/bim-components/type-conventions.md +0 -49
  64. package/docs/bim-components/user-driven-object-creation.md +0 -56
  65. package/docs/cli-setup.md +0 -54
  66. package/docs/cloud-components.md +0 -74
  67. package/docs/connect-logic-to-ui.md +0 -113
  68. package/docs/previewing.md +0 -45
  69. package/docs/publishing.md +0 -35
  70. package/docs/scaffolding.md +0 -71
  71. package/docs/ui-components/async-actions.md +0 -18
  72. package/docs/ui-components/confirmation-dialog.md +0 -39
  73. package/docs/ui-components/data-table.md +0 -185
  74. package/docs/ui-components/display-text.md +0 -39
  75. package/docs/ui-components/inline-form.md +0 -44
  76. package/docs/ui-components/library-examples.md +0 -24
  77. package/docs/ui-components/overview.md +0 -194
  78. package/docs/ui-components/rendering-patterns.md +0 -129
  79. package/docs/ui-components/sections-layout.md +0 -123
  80. package/docs/update-grid-elements.md +0 -46
  81. package/docs/using-colors.md +0 -32
  82. package/docs/using-icons.md +0 -37
  83. package/src/cli/templates/bim/src/bim-components/CloudRunner/src/index.ts +0 -1
  84. package/src/cli/templates/bim/src/bim-components/CloudRunner/src/types.ts +0 -5
  85. package/src/cli/templates/bim/src/bim-components/index.ts +0 -1
  86. package/src/cli/templates/bim/src/globals.ts +0 -1
  87. package/src/cli/templates/bim/src/setups/index.ts +0 -3
  88. package/src/cli/templates/bim/src/ui-components/app-info-section/index.ts +0 -26
  89. package/src/cli/templates/bim/src/ui-components/app-info-section/src/index.ts +0 -1
  90. package/src/cli/templates/bim/src/ui-components/cloud-runner-section/index.ts +0 -37
  91. package/src/cli/templates/bim/src/ui-components/cloud-runner-section/src/index.ts +0 -1
  92. package/src/cli/templates/bim/src/ui-components/index.ts +0 -2
  93. package/src/cli/templates/bim-beta/CONTEXT.md +0 -241
  94. package/src/cli/templates/bim-beta/package.json +0 -25
  95. package/src/cli/templates/bim-beta/src/app.ts +0 -16
  96. package/src/cli/templates/bim-beta/src/bim-components/CloudRunner/index.ts +0 -91
  97. package/src/cli/templates/bim-beta/src/main.ts +0 -93
  98. package/src/cli/templates/bim-beta/src/setups/cloud-runner.ts +0 -13
  99. package/src/cli/templates/bim-beta/src/setups/ui-manager.ts +0 -27
  100. package/src/cli/templates/bim-beta/src/setups/viewports-manager.ts +0 -22
  101. package/src/cli/templates/bim-beta/src/ui-components/app-info-section/src/types.ts +0 -15
  102. package/src/cli/templates/bim-beta/src/ui-components/cloud-runner-section/src/types.ts +0 -14
  103. package/src/cli/templates/cloud/_thatopen +0 -5
  104. package/src/cli/templates/cloud/package.json +0 -22
  105. package/src/cli/templates/cloud-test/CONTEXT.md +0 -56
  106. package/src/cli/templates/cloud-test/src/main.ts +0 -565
  107. package/src/cli/templates/default/CONTEXT.md +0 -92
  108. package/src/cli/templates/default/package.json +0 -18
  109. package/src/cli/templates/default/src/main.ts +0 -62
  110. package/src/cli/templates/test/CONTEXT.md +0 -53
  111. package/src/cli/templates/test/package.json +0 -25
  112. package/src/cli/templates/test/src/main.ts +0 -955
  113. /package/src/cli/templates/{bim/CONTEXT.md → app/README.md} +0 -0
  114. /package/src/cli/templates/{shared/app → app}/index.html +0 -0
  115. /package/src/cli/templates/{bim → app}/package.json +0 -0
  116. /package/src/cli/templates/{bim → app}/src/app.ts +0 -0
  117. /package/src/cli/templates/{bim → app}/src/bim-components/CloudRunner/index.ts +0 -0
  118. /package/src/cli/templates/{bim-beta → app}/src/bim-components/CloudRunner/src/index.ts +0 -0
  119. /package/src/cli/templates/{bim-beta → app}/src/bim-components/CloudRunner/src/types.ts +0 -0
  120. /package/src/cli/templates/{bim-beta → app}/src/bim-components/index.ts +0 -0
  121. /package/src/cli/templates/{bim-beta → app}/src/globals.ts +0 -0
  122. /package/src/cli/templates/{bim → app}/src/main.ts +0 -0
  123. /package/src/cli/templates/{bim → app}/src/setups/cloud-runner.ts +0 -0
  124. /package/src/cli/templates/{bim-beta → app}/src/setups/index.ts +0 -0
  125. /package/src/cli/templates/{bim → app}/src/setups/ui-manager.ts +0 -0
  126. /package/src/cli/templates/{bim → app}/src/setups/viewports-manager.ts +0 -0
  127. /package/src/cli/templates/{bim-beta → app}/src/ui-components/app-info-section/index.ts +0 -0
  128. /package/src/cli/templates/{bim-beta → app}/src/ui-components/app-info-section/src/index.ts +0 -0
  129. /package/src/cli/templates/{bim → app}/src/ui-components/app-info-section/src/types.ts +0 -0
  130. /package/src/cli/templates/{bim-beta → app}/src/ui-components/cloud-runner-section/index.ts +0 -0
  131. /package/src/cli/templates/{bim-beta → app}/src/ui-components/cloud-runner-section/src/index.ts +0 -0
  132. /package/src/cli/templates/{bim → app}/src/ui-components/cloud-runner-section/src/types.ts +0 -0
  133. /package/src/cli/templates/{bim-beta → app}/src/ui-components/index.ts +0 -0
  134. /package/src/cli/templates/{shared/app → app}/tsconfig.json +0 -0
  135. /package/src/cli/templates/{cloud/CONTEXT.md → cloud-component/README.md} +0 -0
  136. /package/src/cli/templates/{cloud-test → cloud-component}/_thatopen +0 -0
  137. /package/src/cli/templates/{cloud → cloud-component}/declarations.json +0 -0
  138. /package/src/cli/templates/{cloud-test → cloud-component}/package.json +0 -0
  139. /package/src/cli/templates/{cloud → cloud-component}/src/main.ts +0 -0
  140. /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
- ```
@@ -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
@@ -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 |
@@ -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.