@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,194 +0,0 @@
1
- # UI Component Creation
2
-
3
- Guides and best practices for creating UI components with That Open Engine (BUI/OBC) — panels, tables, dropdowns, buttons, inputs, or any visual element.
4
-
5
- ## Working mode
6
-
7
- Before doing anything else, **read [`./library-examples.md`](./library-examples.md) and fetch the `paths.json` for `engine_ui-components` to understand what BUI components are already available.**
8
-
9
- Only after that, **propose an implementation plan and wait for the user's approval.**
10
-
11
- The proposal must describe:
12
- - Which templates will be created or modified
13
- - What state (`State`) each template will need
14
- - Whether any template needs an `onInstanceCreated` callback
15
- - Whether it composes other existing templates
16
-
17
- Only proceed with changes after the user explicitly confirms the plan. If the scope is unclear, ask first — do not assume.
18
-
19
- ---
20
-
21
- ## Creating a UI Component
22
-
23
- ### Step 1 — Define the component name
24
-
25
- The component name is the source of truth. Everything else derives from it.
26
-
27
- Given a name like *Files Section* or *Models List*, the full naming cascade is:
28
-
29
- | Artifact | Convention | Example |
30
- |---|---|---|
31
- | Folder | kebab-case | `files-section/`, `models-list/` |
32
- | Component identifier | camelCase | `filesSection`, `modelsList` |
33
- | Types prefix | PascalCase | `FilesSection`, `ModelsList` |
34
- | Template function | `{camelCase}Template` | `filesSectionTemplate` |
35
- | Callback | `on{PascalCase}Created` | `onFilesSectionCreated` |
36
-
37
- The identifier suffix describes what the component *is* from the consumer's perspective — typically the BUI element name:
38
-
39
- | Identifier | Root element |
40
- |---|---|
41
- | `filesSection` | `<bim-panel-section>` |
42
- | `collisionsTable` | `<bim-table>` |
43
- | `modelsDropdown` | `<bim-dropdown>` |
44
- | `actionsToolbar` | `<div>` |
45
-
46
- > **Exception:** `<bim-panel-section>` uses the suffix `*Section`, not `*PanelSection`.
47
-
48
- ---
49
-
50
- ### Step 2 — Create the file structure
51
-
52
- Each component lives in its own folder:
53
-
54
- ```
55
- files-section/
56
- index.ts → template, onInstanceCreated (if needed), re-exports ./src
57
- src/
58
- index.ts → re-exports types and support files
59
- types.ts → state types and any supporting types
60
- ```
61
-
62
- The `src/` subfolder holds types and any support files the template needs — helpers, constants, sub-types, etc. If `index.ts` is growing too long, move the extra logic into `src/`.
63
-
64
- ---
65
-
66
- ### Step 3 — Define types in `src/types.ts`
67
-
68
- Every component needs at minimum these types:
69
-
70
- ```ts
71
- import * as OBC from "@thatopen/components"
72
- import * as BUI from "@thatopen/ui"
73
-
74
- export interface FilesSectionState {
75
- components: OBC.Components
76
- // ...additional state
77
- }
78
-
79
- export type FilesSectionComponent = BUI.StatefullComponent<FilesSectionState>
80
- ```
81
-
82
- - **`{ComponentName}State`** — the reactive state passed to the template on every render. Must always include `components: OBC.Components`.
83
- - **`{ComponentName}Component`** — type alias for `BUI.StatefullComponent<{ComponentName}State>`. Used to type the template function.
84
-
85
- Additional types depend on the component. For example, tables also need `{ComponentName}Data` — which must be a `type` alias, not an `interface`, as `BUI.Table<T>` requires a type alias:
86
-
87
- ```ts
88
- // ✗ Avoid — interface does not satisfy BUI.Table<T>
89
- export interface MyTableData { Name: string }
90
-
91
- // ✓ Correct
92
- export type MyTableData = { Name: string }
93
- ```
94
-
95
- #### `components` is the only entry point to the engine
96
-
97
- Inside a template, any engine component must be accessed via `components.get()`. State must never receive component instances directly:
98
-
99
- ```ts
100
- // ✗ Avoid — receiving a component instance directly
101
- const myTemplate = (state: { highlighter: OBF.Highlighter }) => { ... }
102
-
103
- // ✓ Correct — access everything through components
104
- const myTemplate = ({ components }: FilesSectionState) => {
105
- const highlighter = components.get(OBF.Highlighter)
106
- }
107
- ```
108
-
109
- #### How much logic belongs in a template?
110
-
111
- In the ideal case, a template is a thin facade: it reads state from BIM components via `components.get()` and triggers actions on them — nothing more.
112
-
113
- In practice, some UI-level logic is fine to keep in the template:
114
-
115
- - **Local coordination** — passing data from one sub-component to another within the same section
116
- - **Transient UI state** — loading flags, intermediate form values before the user confirms
117
- - **Orchestration** — calling several BIM components in sequence for a single user action
118
-
119
- What doesn't belong in a template is **domain logic**: calculations, data transformations, business rules. If a template starts computing things beyond what's needed to render, that logic belongs in a BIM component instead.
120
-
121
- The guiding question: *does this logic exist because the UI needs it, or because the domain requires it?* If the domain requires it, move it to a BIM component. See [`../connect-logic-to-ui.md`](../connect-logic-to-ui.md) for how UI templates connect to BIM components.
122
-
123
- ---
124
-
125
- ### Step 4 — Implement the template in `index.ts`
126
-
127
- ### Rules
128
-
129
- - **Always prefer BUI components over native HTML elements.** Before using `<select>`, `<input>`, `<button>`, `<dialog>`, etc., use the `paths.json` descriptions fetched in the working mode step to identify what's available. If you need the full list of available elements, fetch https://raw.githubusercontent.com/ThatOpen/engine_ui-components/refs/heads/main/packages/core/src/components/index.ts. Before implementing any BUI component, check [`./library-examples.md`](./library-examples.md) for an official example of the element you're working with — it's the best starting point for correct usage patterns. See [`./rendering-patterns.md`](./rendering-patterns.md) for general rendering patterns. For displaying and updating text dynamically, see [`./display-text.md`](./display-text.md).
130
- - **Never use `<table>`.** The only acceptable element for tabular data is `<bim-table>`. A `<bim-table>` must always be its own standalone UI component — never defined inline inside another template. The consuming template instantiates the table component and composes it in. See [`./data-table.md`](./data-table.md) for how to build a table component.
131
- - **For async actions** (loading states, async button handlers, etc.), see [`./async-actions.md`](./async-actions.md). **Before triggering a destructive or irreversible action**, always ask the user to confirm — see [`./confirmation-dialog.md`](./confirmation-dialog.md).
132
- - **Do not configure element properties inside the template** that a consumer might want to override after instantiation — they will be reset on every render. Use `onInstanceCreated` instead.
133
- - **Never nest sections.** If the user asks to group content, create independent templates — one per section. See [`./sections-layout.md`](./sections-layout.md).
134
-
135
- #### Template
136
-
137
- A `{ComponentName}Component` function that receives the current state and returns a `BUI.html` tagged template. Re-runs on every state update.
138
-
139
- ```ts
140
- export const filesSectionTemplate: FilesSectionComponent = ({ components }) => {
141
- return BUI.html`<bim-panel-section></bim-panel-section>`
142
- }
143
- ```
144
-
145
- #### `onInstanceCreated` — one-time setup
146
-
147
- Called once when an instance is created. Use it for imperative, one-time configuration: event listeners, fixed element properties, etc. For building a create/edit form anchored to a button, see [`./inline-form.md`](./inline-form.md).
148
-
149
- Receives the tuple `[element, updateFn, componentUtils]`:
150
-
151
- - `element` — the created HTML element
152
- - `updateFn` — triggers a re-render with a partial state update
153
- - `componentUtils` — provides `getCurrentState()`, which always returns fresh state. Use it inside closures to avoid stale state captures:
154
-
155
- ```ts
156
- export const onFilesSectionCreated = (
157
- [section, update, { getCurrentState }]: [
158
- BUI.PanelSection,
159
- BUI.UpdateFunction<FilesSectionState>,
160
- BUI.ComponentUtils<FilesSectionState>
161
- ]
162
- ) => {
163
- section.addEventListener("click", () => {
164
- const { components } = getCurrentState() // always fresh state
165
- const highlighter = components.get(OBF.Highlighter)
166
- // ...
167
- })
168
- }
169
- ```
170
-
171
- ---
172
-
173
- ### Step 5 — Export from the barrel
174
-
175
- Re-export the component from the project's barrel index so it's accessible from a single import point:
176
-
177
- ```ts
178
- export * from "./files-section"
179
- ```
180
-
181
- When planning a new UI component, **always consider breaking it into smaller, reusable templates** rather than building a single monolithic one. Discuss the granularity with the developer — but the default stance is to favor small, composable units.
182
-
183
- ---
184
-
185
- ## See also
186
-
187
- - [`./library-examples.md`](./library-examples.md) — Find official usage examples and discover what BUI provides
188
- - [`./data-table.md`](./data-table.md) — Display data in a table, load columns, group rows
189
- - [`./sections-layout.md`](./sections-layout.md) — Organize the layout of a panel section (zones, toolbar, status messages)
190
- - [`./inline-form.md`](./inline-form.md) — Create or edit an entity in a popup form anchored to a button
191
- - [`./confirmation-dialog.md`](./confirmation-dialog.md) — Ask for confirmation before a destructive or irreversible action
192
- - [`./async-actions.md`](./async-actions.md) — Handle an async action with loading state on a button
193
- - [`./rendering-patterns.md`](./rendering-patterns.md) — General rendering patterns (BUI.ref, requestUpdate, data-active)
194
- - [`./display-text.md`](./display-text.md) — Display text, update text dynamically, `bim-label` vs `.label`
@@ -1,129 +0,0 @@
1
- # Rendering Patterns
2
-
3
- Common patterns that apply across all BUI components.
4
-
5
- ## Lit and LitElement
6
-
7
- All components in `@thatopen/ui` are Web Components built with [Lit](https://lit.dev/) and extend `LitElement`. Since `BUI.html` is Lit's `html` tagged template, the full Lit template syntax applies — property bindings, boolean attributes, event listeners, directives, etc.
8
-
9
- ## requestUpdate()
10
-
11
- Reassigning a reactive property (like `table.data`) automatically schedules a re-render. **Mutating a property in place** does not — call `requestUpdate()` manually in those cases:
12
-
13
- ```ts
14
- // Reassignment → automatic update
15
- table.data = newData
16
-
17
- // In-place mutation → manual update required
18
- table.data.push(newRow)
19
- table.requestUpdate()
20
- ```
21
-
22
- ## BUI.ref
23
-
24
- `BUI.ref(callback)` provides an imperative reference to an element inside a `BUI.html` template. The callback is called once the element is mounted in the DOM:
25
-
26
- ```ts
27
- // Initialization
28
- const onTableCreated = (e?: Element) => {
29
- if (!e) return
30
- const table = e as BUI.Table<MyTableData>
31
- table.loadFunction = async () => { ... }
32
- table.loadData(true)
33
- }
34
-
35
- return BUI.html`<bim-table ${BUI.ref(onTableCreated)}></bim-table>`
36
- ```
37
-
38
- ```ts
39
- // Capture
40
- let input: BUI.TextInput | undefined
41
-
42
- const onInputCreated = (e?: Element) => {
43
- if (!(e instanceof BUI.TextInput)) return
44
- input = e
45
- }
46
-
47
- return BUI.html`
48
- <bim-text-input ${BUI.ref(onInputCreated)}></bim-text-input>
49
- <bim-button @click=${() => console.log(input?.value)}></bim-button>
50
- `
51
- ```
52
-
53
- ## Creating Elements
54
-
55
- When an element must be created imperatively outside of `BUI.html`, use `BUI.Component.create` instead of `document.createElement`:
56
-
57
- ```ts
58
- // ✗ Avoid
59
- const button = document.createElement("bim-button")
60
-
61
- // ✓ Correct
62
- const button = BUI.Component.create(() => BUI.html`<bim-button label="Click me"></bim-button>`)
63
- ```
64
-
65
- ## Visual State with data-active
66
-
67
- Use `toggleAttribute("data-active")` to reflect an element's active/inactive state visually:
68
-
69
- ```ts
70
- target.toggleAttribute("data-active") // toggle
71
- target.toggleAttribute("data-active", true) // force active
72
- target.toggleAttribute("data-active", false) // force inactive
73
- ```
74
-
75
- ## Event Handlers
76
-
77
- ```ts
78
- return BUI.html`
79
- <bim-text-input @input=${onSearch}></bim-text-input>
80
- <bim-button @click=${onClick}></bim-button>
81
- `
82
- ```
83
-
84
- ## BUI.Manager.newRandomId()
85
-
86
- Use when a template needs to associate DOM elements by ID. Since templates can be instantiated multiple times, hardcoded IDs would cause collisions:
87
-
88
- ```ts
89
- const inputId = BUI.Manager.newRandomId()
90
-
91
- return BUI.html`
92
- <label for=${inputId}>Name</label>
93
- <input id=${inputId} type="text" />
94
- `
95
- ```
96
-
97
- ## Triggering re-renders from inside a template (update)
98
-
99
- `BUI.StatefullComponent` receives an optional second parameter `update`:
100
-
101
- ```ts
102
- export const myTemplate: BUI.StatefullComponent<MyState> = (state, update) => {
103
- const onAdd = () => {
104
- doSomething()
105
- update() // re-render with same state
106
- update({ count: 5 }) // re-render with partial state change
107
- }
108
- }
109
- ```
110
-
111
- Avoid calling `update` in response to changes that themselves trigger another `update` — this causes an infinite render loop.
112
-
113
- ## Role-based rendering
114
-
115
- When content depends on a user role or any runtime condition, use an optional variable before the `return`:
116
-
117
- ```ts
118
- let actionArea: BUI.TemplateResult | undefined
119
- if (userHasPermission) {
120
- actionArea = BUI.html`<bim-button label="Run Action" @click=${onRun}></bim-button>`
121
- }
122
-
123
- return BUI.html`
124
- <bim-panel-section label="...">
125
- ${content}
126
- ${actionArea}
127
- </bim-panel-section>
128
- `
129
- ```
@@ -1,123 +0,0 @@
1
- # Panel Section Layout
2
-
3
- ## Composition mental model
4
-
5
- A panel section has zones that follow a natural sequence reflecting how the user processes the panel: first they act on the context (controls), then understand the current state (messages), then operate on the selected item (toolbar), then see the data (main content), and finally execute high-impact actions (bottom).
6
-
7
- ```
8
- <bim-panel-section label="..." icon="..." fixed?>
9
- [controls bar] ← search or selector + action buttons
10
- [status messages] ← conditional bim-labels (warn, success, info)
11
- [actions toolbar] ← bim-toolbar when there are many actions on the active item
12
- [main content] ← table, list, or sub-component
13
- [primary actions] ← 1-2 high-impact buttons at the bottom
14
- </bim-panel-section>
15
- ```
16
-
17
- Not all zones are always present. This sequence is a guide, not a mandatory template — if the panel's content breaks that flow in a way that improves the experience, propose the layout that makes the most sense and explain the reasoning.
18
-
19
- ### Forbidden nesting
20
-
21
- Inside a `<bim-panel-section>` it is **never** valid to place:
22
-
23
- - Another `<bim-panel-section>`
24
- - A `<bim-panel>`
25
-
26
- This mistake is most tempting when the user asks to "group" sections. The correct answer is **not** nesting — it is creating independent templates. A template does not decide how it is grouped with others; that is the consumer's responsibility. If the content truly belongs in one section, use the existing internal zones (`controls bar`, `toolbar`, `main content`). If it needs to be split into multiple sections, each section is its own independent template.
27
-
28
- ---
29
-
30
- ## Controls bar
31
-
32
- Always a `<div style="display: flex; gap: 0.5rem;">`. There are two main variants:
33
-
34
- **Search** — when the user filters over a list or table:
35
- ```ts
36
- return BUI.html`
37
- <bim-panel-section label="Elements">
38
- <div style="display: flex; gap: 0.5rem;">
39
- <bim-text-input @input=${onSearch} vertical placeholder="Search..."></bim-text-input>
40
- <bim-button icon=${icons.ADD} @click=${onCreate}></bim-button>
41
- </div>
42
- ${table}
43
- </bim-panel-section>
44
- `
45
- ```
46
-
47
- **Selector** — when the user picks the active item from a dropdown. The gap is tighter (`0.25rem`) because the dropdown already takes most of the width:
48
- ```ts
49
- return BUI.html`
50
- <bim-panel-section label="Proposals">
51
- <div style="display: flex; gap: 0.25rem;">
52
- ${proposalsDropdown}
53
- <bim-button icon=${icons.ADD} @click=${onCreate}></bim-button>
54
- </div>
55
- ${content}
56
- </bim-panel-section>
57
- `
58
- ```
59
-
60
- Action buttons in the controls bar are always icon-only (`icon=` without `label=`). The search `<bim-text-input>` always has `vertical` and `debounce="200"`.
61
-
62
- ---
63
-
64
- ## Status messages
65
-
66
- Conditional `<bim-label>` elements that appear between the controls and the content to communicate the state of the active item — warnings, confirmations, relevant info. Built as optional variables:
67
-
68
- ```ts
69
- let statusMessage: BUI.TemplateResult | undefined
70
- if (item?.status === "sent") {
71
- statusMessage = BUI.html`<bim-label>This item has been sent and can't be modified.</bim-label>`
72
- }
73
-
74
- return BUI.html`
75
- <bim-panel-section label="...">
76
- ${controls}
77
- ${statusMessage}
78
- ${content}
79
- </bim-panel-section>
80
- `
81
- ```
82
-
83
- ---
84
-
85
- ## Actions toolbar
86
-
87
- When there are many actions on the active item (more than 3-4 buttons), use `<bim-toolbar>` with `<bim-toolbar-section>` instead of a plain flex div. The toolbar goes after the status messages and before the main content:
88
-
89
- ```ts
90
- const toolbar = BUI.html`
91
- <bim-toolbar style="border: 1px solid var(--bim-ui_bg-contrast-20);">
92
- <bim-toolbar-section>
93
- ${addItemBtn}
94
- <bim-button style="flex: 0" icon=${icons.SELECT} @click=${onSelect}></bim-button>
95
- <bim-button style="flex: 0" icon=${icons.DELETE} @click=${onDelete}></bim-button>
96
- </bim-toolbar-section>
97
- </bim-toolbar>
98
- `
99
- ```
100
-
101
- Buttons inside the toolbar always have `style="flex: 0"` to prevent them from stretching.
102
-
103
- ---
104
-
105
- ## Conditional content
106
-
107
- When the panel content changes completely based on state (e.g. "select something first" vs. showing data), assign to a variable before the `return`:
108
-
109
- ```ts
110
- let content: BUI.TemplateResult
111
- if (hasSelection) {
112
- content = BUI.html`<bim-table ...></bim-table>`
113
- } else {
114
- content = BUI.html`<bim-label>Select an element to see its data.</bim-label>`
115
- }
116
-
117
- return BUI.html`
118
- <bim-panel-section label="...">
119
- ${controls}
120
- ${content}
121
- </bim-panel-section>
122
- `
123
- ```
@@ -1,46 +0,0 @@
1
- # Update Grid Elements
2
-
3
- ## When to use
4
-
5
- `app.grid.updateComponent` pushes a state update to a specific named grid element. Use it when a BIM component event needs to refresh the state of a template-based section mounted in the grid.
6
-
7
- This is different from `uis.custom.get(...).updateInstances()` — that re-renders all instances of a UIManager template regardless of where they're mounted. `updateComponent` targets a **specific grid slot by name**, which makes it the right choice when the element lives in the grid and you want precise, typed control over what state it receives.
8
-
9
- ---
10
-
11
- ## API
12
-
13
- ```ts
14
- app.grid.updateComponent[componentName](updatedState)
15
- ```
16
-
17
- - **`componentName`** — the element name as declared in the `App` type (e.g. `"qtosSection"`)
18
- - **`updatedState`** — partial state; only the provided fields are merged
19
-
20
- The call is fully typed: the accepted state shape is inferred from the `{ComponentName}GridElement` type in `app.ts`.
21
-
22
- ---
23
-
24
- ## Where to call it
25
-
26
- In a setup file (`setups/{custom}.ts`), in response to a BIM component event:
27
-
28
- ```ts
29
- // setups/qto-manager.ts
30
- export const qtoManager = (components: OBC.Components) => {
31
- const app = getAppManager(components)
32
- const qtoManager = components.get(QtoManager)
33
-
34
- qtoManager.onResultsChanged.add((results) => {
35
- app.grid.updateComponent["qtosSection"]({ results })
36
- })
37
- }
38
- ```
39
-
40
- Never call `updateComponent` from inside a template function — templates receive state passively and should not trigger updates themselves.
41
-
42
- ---
43
-
44
- ## Type safety
45
-
46
- Because `app.grid` is typed via the `App` type in `app.ts`, TypeScript knows which names are valid and what state shape each one accepts. Passing an unknown name or a mismatched state shape produces a type error at the call site.
@@ -1,32 +0,0 @@
1
- # Using Colors
2
-
3
- ## `globals.ts` shape
4
-
5
- ```ts
6
- export const colors = {
7
- GREEN: "#00FF00",
8
- SOFT_BLUE: "#5B8CFF",
9
- }
10
- ```
11
-
12
- **Colors are always stored as full hex codes, including the `#`.** This is required because some systems (like the highlighter) use the string itself as a style identifier in addition to a color value.
13
-
14
- ## Rules
15
-
16
- - No hardcoded inline colors — not in the highlighter, not in palettes, not in any component. Always imported from `globals.ts`.
17
- - Before adding a new color, check whether an existing one already works.
18
-
19
- ## Example: highlighter
20
-
21
- ```ts
22
- const highlighter = components.get(OBF.Highlighter)
23
- if (!highlighter.styles.has(colors.GREEN)) {
24
- highlighter.styles.set(colors.GREEN, {
25
- color: new THREE.Color(colors.GREEN),
26
- renderedFaces: 1,
27
- opacity: 1,
28
- transparent: false,
29
- })
30
- }
31
- highlighter.highlightByID(colors.GREEN, modelIdMap)
32
- ```
@@ -1,37 +0,0 @@
1
- # Using Icons
2
-
3
- ## Icon registry rules
4
-
5
- **All icons in a platform app must be declared in `globals.ts` and accessed through `AppManager`.** This is not optional.
6
-
7
- The flow is always:
8
- 1. Declare the icon in `globals.ts` with a `UPPER_SNAKE_CASE` key
9
- 2. `app.ts` — the `App` type's `icons` field is typed as `(keyof typeof icons)[]`, which means any new key added to the registry is automatically reflected in the type — no manual update needed per icon, but this field must be present in the `App` type
10
- 3. Pass the registry to `app.init()` as `icons: appIcons`
11
- 4. Access icons elsewhere via `app.icons.KEY_NAME` (always through `getAppManager(components)`)
12
-
13
- ```ts
14
- // ✗ Forbidden — inline icon string anywhere in the app
15
- <bim-button icon="ic:round-warning"></bim-button>
16
- grid.layouts = { Viewer: { icon: "ic:round-warning", template: `...` } }
17
-
18
- // ✓ Correct — always via the registry
19
- const app = getAppManager(components)
20
- <bim-button icon=${app.icons.WARNING}></bim-button>
21
- grid.layouts = { Viewer: { icon: app.icons.WARNING, template: `...` } }
22
- ```
23
-
24
- ## Before adding a new icon
25
-
26
- Before declaring a new icon in `globals.ts`, check if an existing one in the registry already serves the purpose. Reuse an existing icon when it communicates the same intent — avoid registry bloat.
27
-
28
- If no existing icon fits, add it to `globals.ts` first — then use it through `app.icons`.
29
-
30
- ## `globals.ts` shape
31
-
32
- ```ts
33
- export const icons = {
34
- WARNING: "ic:round-warning",
35
- COLLISION: "fa7-solid:explosion",
36
- }
37
- ```
@@ -1 +0,0 @@
1
- export * from "./types";
@@ -1,5 +0,0 @@
1
- export interface CloudRunnerStatus {
2
- status: string;
3
- progress: number;
4
- messages: string[];
5
- }
@@ -1 +0,0 @@
1
- export * from "./CloudRunner";
@@ -1 +0,0 @@
1
- export const icons = {};
@@ -1,3 +0,0 @@
1
- export * from "./ui-manager";
2
- export * from "./viewports-manager";
3
- export * from "./cloud-runner";
@@ -1,26 +0,0 @@
1
- import * as BUI from "@thatopen/ui";
2
- import { AppInfoSectionComponent } from "./src";
3
- import { getAppManager } from "../../app";
4
-
5
- export const appInfoSectionTemplate: AppInfoSectionComponent = ({
6
- components,
7
- }) => {
8
- const app = getAppManager(components);
9
-
10
- const fileItems =
11
- app.projectData?.files.map(
12
- (f: { name: string }) => BUI.html`<bim-label>${f.name}</bim-label>`,
13
- ) ?? [];
14
-
15
- return BUI.html`
16
- <bim-panel-section label="App Info" icon="solar:info-circle-bold">
17
- <bim-label>App ID: ${app.client?.context.appId}</bim-label>
18
- <bim-label>Project ID: ${app.client?.context.projectId}</bim-label>
19
- <bim-label>API URL: ${app.client?.context.apiUrl}</bim-label>
20
- <bim-label>Files: ${fileItems.length}</bim-label>
21
- ${fileItems}
22
- </bim-panel-section>
23
- `;
24
- };
25
-
26
- export * from "./src";
@@ -1 +0,0 @@
1
- export * from "./types";
@@ -1,37 +0,0 @@
1
- import * as BUI from "@thatopen/ui";
2
- import { CloudRunner } from "../../bim-components";
3
- import { CloudRunnerSectionComponent } from "./src";
4
-
5
- export const cloudRunnerSectionTemplate: CloudRunnerSectionComponent = ({
6
- components,
7
- }) => {
8
- const runner = components.get(CloudRunner);
9
-
10
- const messageItems = runner.messages.map(
11
- (m) => BUI.html`<bim-label>${m}</bim-label>`,
12
- );
13
-
14
- return BUI.html`
15
- <bim-panel-section label="Cloud Component" icon="solar:code-bold">
16
- <bim-label>Component ID: ${runner.componentId}</bim-label>
17
- <bim-label>Local server: ${runner.localServerUrl}</bim-label>
18
- <div style="display:flex;gap:0.5rem;">
19
- <bim-button
20
- label="Run Local"
21
- icon="solar:play-bold"
22
- @click=${() => runner.run(true)}
23
- ></bim-button>
24
- <bim-button
25
- label="Run Deployed"
26
- icon="solar:cloud-bold-duotone"
27
- @click=${() => runner.run(false)}
28
- ></bim-button>
29
- </div>
30
- <bim-label>${runner.status}</bim-label>
31
- <bim-label>Progress: ${runner.progress}%</bim-label>
32
- ${messageItems}
33
- </bim-panel-section>
34
- `;
35
- };
36
-
37
- export * from "./src";
@@ -1 +0,0 @@
1
- export * from "./types";
@@ -1,2 +0,0 @@
1
- export * from "./app-info-section";
2
- export * from "./cloud-runner-section";