@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,185 +1,185 @@
|
|
|
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
|
+
# 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 +1,39 @@
|
|
|
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
|
+
# 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 +1,44 @@
|
|
|
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
|
+
# 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 +1,24 @@
|
|
|
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.
|
|
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.
|