@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.
Files changed (63) hide show
  1. package/AGENTS.md +86 -76
  2. package/dist/cli.js +10 -1
  3. package/docs/access-backend-data.md +19 -19
  4. package/docs/app-architecture.md +94 -94
  5. package/docs/app-layout.md +139 -139
  6. package/docs/app-wiring.md +123 -123
  7. package/docs/bim-components/coding-conventions.md +128 -128
  8. package/docs/bim-components/element-collections.md +69 -69
  9. package/docs/bim-components/expose-events.md +84 -84
  10. package/docs/bim-components/library-examples.md +28 -28
  11. package/docs/bim-components/observable-collections.md +83 -83
  12. package/docs/bim-components/overview.md +160 -160
  13. package/docs/bim-components/per-frame-updates.md +20 -20
  14. package/docs/bim-components/save-and-restore-state.md +21 -21
  15. package/docs/bim-components/setup-and-cleanup.md +64 -64
  16. package/docs/bim-components/type-conventions.md +49 -49
  17. package/docs/bim-components/user-driven-object-creation.md +56 -56
  18. package/docs/cli-setup.md +54 -54
  19. package/docs/cloud-components.md +74 -74
  20. package/docs/connect-logic-to-ui.md +113 -113
  21. package/docs/previewing.md +45 -45
  22. package/docs/publishing.md +35 -35
  23. package/docs/scaffolding.md +71 -54
  24. package/docs/ui-components/async-actions.md +18 -18
  25. package/docs/ui-components/confirmation-dialog.md +39 -39
  26. package/docs/ui-components/data-table.md +185 -185
  27. package/docs/ui-components/display-text.md +39 -39
  28. package/docs/ui-components/inline-form.md +44 -44
  29. package/docs/ui-components/library-examples.md +24 -24
  30. package/docs/ui-components/overview.md +194 -194
  31. package/docs/ui-components/rendering-patterns.md +129 -129
  32. package/docs/ui-components/sections-layout.md +123 -123
  33. package/docs/update-grid-elements.md +46 -46
  34. package/docs/using-colors.md +32 -32
  35. package/docs/using-icons.md +37 -37
  36. package/package.json +2 -2
  37. package/src/cli/templates/bim/CONTEXT.md +1 -4
  38. package/src/cli/templates/bim/package.json +0 -1
  39. package/src/cli/templates/bim/src/main.ts +1 -2
  40. package/src/cli/templates/bim-beta/CONTEXT.md +241 -0
  41. package/src/cli/templates/bim-beta/package.json +25 -0
  42. package/src/cli/templates/bim-beta/src/app.ts +16 -0
  43. package/src/cli/templates/bim-beta/src/bim-components/CloudRunner/index.ts +91 -0
  44. package/src/cli/templates/bim-beta/src/bim-components/CloudRunner/src/index.ts +1 -0
  45. package/src/cli/templates/bim-beta/src/bim-components/CloudRunner/src/types.ts +5 -0
  46. package/src/cli/templates/bim-beta/src/bim-components/index.ts +1 -0
  47. package/src/cli/templates/bim-beta/src/globals.ts +1 -0
  48. package/src/cli/templates/bim-beta/src/main.ts +93 -0
  49. package/src/cli/templates/bim-beta/src/setups/cloud-runner.ts +13 -0
  50. package/src/cli/templates/bim-beta/src/setups/index.ts +3 -0
  51. package/src/cli/templates/bim-beta/src/setups/ui-manager.ts +27 -0
  52. package/src/cli/templates/bim-beta/src/setups/viewports-manager.ts +22 -0
  53. package/src/cli/templates/bim-beta/src/ui-components/app-info-section/index.ts +26 -0
  54. package/src/cli/templates/bim-beta/src/ui-components/app-info-section/src/index.ts +1 -0
  55. package/src/cli/templates/bim-beta/src/ui-components/app-info-section/src/types.ts +15 -0
  56. package/src/cli/templates/bim-beta/src/ui-components/cloud-runner-section/index.ts +37 -0
  57. package/src/cli/templates/bim-beta/src/ui-components/cloud-runner-section/src/index.ts +1 -0
  58. package/src/cli/templates/bim-beta/src/ui-components/cloud-runner-section/src/types.ts +14 -0
  59. package/src/cli/templates/bim-beta/src/ui-components/index.ts +2 -0
  60. package/src/cli/templates/cloud/CONTEXT.md +205 -205
  61. package/src/cli/templates/cloud/src/main.ts +70 -70
  62. package/src/cli/templates/shared/AGENTS.md +30 -23
  63. 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.