@thatopen/services 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +86 -76
- package/dist/cli.js +10 -1
- package/docs/access-backend-data.md +19 -19
- package/docs/app-architecture.md +94 -94
- package/docs/app-layout.md +139 -139
- package/docs/app-wiring.md +123 -123
- package/docs/bim-components/coding-conventions.md +128 -128
- package/docs/bim-components/element-collections.md +69 -69
- package/docs/bim-components/expose-events.md +84 -84
- package/docs/bim-components/library-examples.md +28 -28
- package/docs/bim-components/observable-collections.md +83 -83
- package/docs/bim-components/overview.md +160 -160
- package/docs/bim-components/per-frame-updates.md +20 -20
- package/docs/bim-components/save-and-restore-state.md +21 -21
- package/docs/bim-components/setup-and-cleanup.md +64 -64
- package/docs/bim-components/type-conventions.md +49 -49
- package/docs/bim-components/user-driven-object-creation.md +56 -56
- package/docs/cli-setup.md +54 -54
- package/docs/cloud-components.md +74 -74
- package/docs/connect-logic-to-ui.md +113 -113
- package/docs/previewing.md +45 -45
- package/docs/publishing.md +35 -35
- package/docs/scaffolding.md +71 -54
- package/docs/ui-components/async-actions.md +18 -18
- package/docs/ui-components/confirmation-dialog.md +39 -39
- package/docs/ui-components/data-table.md +185 -185
- package/docs/ui-components/display-text.md +39 -39
- package/docs/ui-components/inline-form.md +44 -44
- package/docs/ui-components/library-examples.md +24 -24
- package/docs/ui-components/overview.md +194 -194
- package/docs/ui-components/rendering-patterns.md +129 -129
- package/docs/ui-components/sections-layout.md +123 -123
- package/docs/update-grid-elements.md +46 -46
- package/docs/using-colors.md +32 -32
- package/docs/using-icons.md +37 -37
- package/package.json +2 -2
- package/src/cli/templates/bim/CONTEXT.md +1 -4
- package/src/cli/templates/bim/package.json +0 -1
- package/src/cli/templates/bim/src/main.ts +1 -2
- package/src/cli/templates/bim-beta/CONTEXT.md +241 -0
- package/src/cli/templates/bim-beta/package.json +25 -0
- package/src/cli/templates/bim-beta/src/app.ts +16 -0
- package/src/cli/templates/bim-beta/src/bim-components/CloudRunner/index.ts +91 -0
- package/src/cli/templates/bim-beta/src/bim-components/CloudRunner/src/index.ts +1 -0
- package/src/cli/templates/bim-beta/src/bim-components/CloudRunner/src/types.ts +5 -0
- package/src/cli/templates/bim-beta/src/bim-components/index.ts +1 -0
- package/src/cli/templates/bim-beta/src/globals.ts +1 -0
- package/src/cli/templates/bim-beta/src/main.ts +93 -0
- package/src/cli/templates/bim-beta/src/setups/cloud-runner.ts +13 -0
- package/src/cli/templates/bim-beta/src/setups/index.ts +3 -0
- package/src/cli/templates/bim-beta/src/setups/ui-manager.ts +27 -0
- package/src/cli/templates/bim-beta/src/setups/viewports-manager.ts +22 -0
- package/src/cli/templates/bim-beta/src/ui-components/app-info-section/index.ts +26 -0
- package/src/cli/templates/bim-beta/src/ui-components/app-info-section/src/index.ts +1 -0
- package/src/cli/templates/bim-beta/src/ui-components/app-info-section/src/types.ts +15 -0
- package/src/cli/templates/bim-beta/src/ui-components/cloud-runner-section/index.ts +37 -0
- package/src/cli/templates/bim-beta/src/ui-components/cloud-runner-section/src/index.ts +1 -0
- package/src/cli/templates/bim-beta/src/ui-components/cloud-runner-section/src/types.ts +14 -0
- package/src/cli/templates/bim-beta/src/ui-components/index.ts +2 -0
- package/src/cli/templates/cloud/CONTEXT.md +205 -205
- package/src/cli/templates/cloud/src/main.ts +70 -70
- package/src/cli/templates/shared/AGENTS.md +30 -23
- package/src/cli/templates/shared/CLAUDE.md +1 -1
|
@@ -1,123 +1,123 @@
|
|
|
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
|
+
# 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 +1,46 @@
|
|
|
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
|
+
# 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.
|
package/docs/using-colors.md
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
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
|
+
# 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
|
+
```
|
package/docs/using-icons.md
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
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
|
+
# 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
|
+
```
|
package/package.json
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"access": "public"
|
|
16
16
|
},
|
|
17
17
|
"private": false,
|
|
18
|
-
"version": "0.0.
|
|
18
|
+
"version": "0.0.4",
|
|
19
19
|
"main": "dist/index.cjs.js",
|
|
20
20
|
"module": "dist/index.es.js",
|
|
21
21
|
"types": "dist/index.d.ts",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"build:lib": "tsc && vite build",
|
|
38
38
|
"test": "vitest run",
|
|
39
39
|
"test:watch": "vitest",
|
|
40
|
-
"build:cli": "vite build --config vite.config.cli.mts
|
|
40
|
+
"build:cli": "vite build --config vite.config.cli.mts",
|
|
41
41
|
"preview": "vite preview",
|
|
42
42
|
"test:ui": "vite --config test/vite.config.mts",
|
|
43
43
|
"test:cli-build-app": "npm run build:cli && node test/setup-test-app.mjs",
|
|
@@ -44,7 +44,6 @@ Always use `npm run dev` which runs `thatopen serve` under the hood.
|
|
|
44
44
|
| `@thatopen/components-front` | `OBF` | Front-end BIM components (Highlighter, measurements, etc.) |
|
|
45
45
|
| `@thatopen/fragments` | `FRAGS` | Fragment geometry format |
|
|
46
46
|
| `@thatopen/ui` | `BUI` | UI web components (`<bim-panel>`, `<bim-grid>`, etc.) |
|
|
47
|
-
| `@thatopen/ui-obc` | `CUI` | Pre-built OBC UI tables (used by ModelsPanel) |
|
|
48
47
|
| `three` | `THREE` | 3D rendering engine |
|
|
49
48
|
| `@thatopen/services` | `EngineServicesClient` | Platform API client + built-in components |
|
|
50
49
|
|
|
@@ -99,7 +98,7 @@ const client = PlatformClient.fromPlatformContext();
|
|
|
99
98
|
|
|
100
99
|
// Creates OBC.Components, inits BUI, loads built-ins, calls components.init()
|
|
101
100
|
const { components } = await client.setup(
|
|
102
|
-
{ OBC, OBF, BUI,
|
|
101
|
+
{ OBC, OBF, BUI, THREE, FRAGS },
|
|
103
102
|
AppManager, ViewportsManager,
|
|
104
103
|
);
|
|
105
104
|
|
|
@@ -125,7 +124,6 @@ await client.initBuiltInComponent(AppManager, components);
|
|
|
125
124
|
| ViewportsManager | `{ OBC, BUI, THREE, FRAGS }` | — |
|
|
126
125
|
| LoadModelButton | `{ OBC, BUI }` | — |
|
|
127
126
|
| ModelsDropdown | `{ OBC, BUI }` | — |
|
|
128
|
-
| ModelsPanel | `{ OBC, BUI, CUI }` | `@thatopen/ui-obc` |
|
|
129
127
|
| ViewerToolbar | `{ OBC, OBF, BUI, THREE }` | `@thatopen/components-front` |
|
|
130
128
|
| ColorsPalette | `{ OBC, OBF, BUI }` | `@thatopen/components-front` |
|
|
131
129
|
| ClashesList | `{ OBC, OBF, BUI, THREE }` | `@thatopen/components-front` |
|
|
@@ -145,7 +143,6 @@ await client.initBuiltInComponent(AppManager, components);
|
|
|
145
143
|
import * as OBC from "@thatopen/components";
|
|
146
144
|
import * as OBF from "@thatopen/components-front"; // needed for Toolbar, Highlighters, Clashes, etc.
|
|
147
145
|
import * as BUI from "@thatopen/ui";
|
|
148
|
-
import * as CUI from "@thatopen/ui-obc"; // needed for ModelsPanel
|
|
149
146
|
import * as THREE from "three";
|
|
150
147
|
import * as FRAGS from "@thatopen/fragments";
|
|
151
148
|
import * as MARKERJS from "@markerjs/markerjs3"; // needed for ScreenshotAnnotator
|
|
@@ -3,7 +3,6 @@ import * as OBC from "@thatopen/components";
|
|
|
3
3
|
import * as OBF from "@thatopen/components-front";
|
|
4
4
|
import * as FRAGS from "@thatopen/fragments";
|
|
5
5
|
import * as BUI from "@thatopen/ui";
|
|
6
|
-
import * as CUI from "@thatopen/ui-obc";
|
|
7
6
|
import * as MARKERJS from "@markerjs/markerjs3"
|
|
8
7
|
import {
|
|
9
8
|
PlatformClient,
|
|
@@ -26,7 +25,7 @@ async function main() {
|
|
|
26
25
|
// First argument: library globals used by the engine.
|
|
27
26
|
// Subsequent arguments: platform built-in components to initialise.
|
|
28
27
|
const { components } = await client.setup<OBC.Components>(
|
|
29
|
-
{ OBC, OBF, BUI,
|
|
28
|
+
{ OBC, OBF, BUI, THREE, FRAGS, MARKERJS },
|
|
30
29
|
{ uuid: ViewportsManager.uuid },
|
|
31
30
|
{ uuid: AppManager.uuid },
|
|
32
31
|
{ uuid: UIManager.uuid },
|