@thatopen/services 0.1.3 → 0.3.0

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 (120) hide show
  1. package/README.md +59 -46
  2. package/dist/built-in/index.d.ts +486 -563
  3. package/dist/cli/lib/npmrc.d.ts +28 -0
  4. package/dist/cli/lib/npmrc.test.d.ts +1 -0
  5. package/dist/cli.js +91 -7
  6. package/dist/core/client.d.ts +10 -0
  7. package/dist/index.cjs.js +2 -2
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.es.js +42 -32
  10. package/dist/types/npm.d.ts +14 -0
  11. package/dist/vite-env.d.ts +1 -1
  12. package/docs/builtin/paths.json +74 -70
  13. package/docs/cli/create.md +28 -28
  14. package/docs/cli/local-server.md +38 -38
  15. package/docs/cli/login.md +32 -32
  16. package/docs/cli/publish.md +31 -31
  17. package/docs/cli/run.md +26 -26
  18. package/docs/cli/serve.md +43 -43
  19. package/docs/cli/swap.md +30 -30
  20. package/package.json +100 -100
  21. package/resources/AGENTS.md +40 -40
  22. package/src/built-in/CDEManager/example.ts +214 -214
  23. package/src/built-in/CDEManager/examples/FileEditing/example.ts +226 -226
  24. package/src/built-in/CDEManager/examples/FileMoves/example.ts +186 -186
  25. package/src/built-in/CDEManager/examples/FileOperations/example.ts +295 -295
  26. package/src/built-in/CDEManager/examples/FileTransfers/example.ts +210 -210
  27. package/src/built-in/CDEManager/examples/FolderManagement/example.ts +230 -230
  28. package/src/built-in/CDEManager/examples/MetadataSchema/example.ts +230 -230
  29. package/src/built-in/CDEManager/examples/MetadataViews/example.ts +166 -166
  30. package/src/built-in/CDEManager/examples/ProjectConfig/example.ts +177 -177
  31. package/src/built-in/UIManager/src/app/example.ts +99 -99
  32. package/src/built-in/UIManager/src/app/examples/AppState/example.ts +142 -142
  33. package/src/built-in/UIManager/src/app/examples/Banner/example.ts +161 -0
  34. package/src/built-in/UIManager/src/app/examples/Contexts/example.ts +125 -125
  35. package/src/built-in/UIManager/src/app/examples/FileDrop/example.ts +126 -0
  36. package/src/built-in/UIManager/src/app/examples/FloatingLayout/example.ts +92 -92
  37. package/src/built-in/UIManager/src/app/examples/Modal/example.ts +165 -0
  38. package/src/built-in/UIManager/src/app/examples/Notifications/example.ts +135 -161
  39. package/src/built-in/UIManager/src/app/examples/Sidebar/example.ts +104 -104
  40. package/src/built-in/index.ts +649 -755
  41. package/src/cli/templates/app/README.md +241 -241
  42. package/src/cli/templates/app/index.html +35 -27
  43. package/src/cli/templates/app/package.json +31 -27
  44. package/src/cli/templates/app/src/app.ts +37 -0
  45. package/src/cli/templates/app/src/assets/tool-placeholder.ts +50 -0
  46. package/src/cli/templates/app/src/bim-components/CloudRunner/index.ts +95 -87
  47. package/src/cli/templates/app/src/bim-components/CloudRunner/src/index.ts +1 -1
  48. package/src/cli/templates/app/src/bim-components/CloudRunner/src/types.ts +5 -5
  49. package/src/cli/templates/app/src/bim-components/index.ts +1 -1
  50. package/src/cli/templates/app/src/globals.ts +1 -0
  51. package/src/cli/templates/app/src/main.ts +340 -56
  52. package/src/cli/templates/app/src/setups/active-tool-hud.ts +69 -0
  53. package/src/cli/templates/app/src/setups/camera-tools.ts +63 -0
  54. package/src/cli/templates/app/src/setups/camera-views.ts +201 -0
  55. package/src/cli/templates/app/src/setups/card-header.ts +35 -0
  56. package/src/cli/templates/app/src/setups/clipper-panel.ts +167 -0
  57. package/src/cli/templates/app/src/setups/clipper-tool.ts +754 -0
  58. package/src/cli/templates/app/src/setups/clipper.ts +75 -0
  59. package/src/cli/templates/app/src/setups/cloud-runner.ts +13 -9
  60. package/src/cli/templates/app/src/setups/commands-panel.ts +239 -0
  61. package/src/cli/templates/app/src/setups/data-table-panel.ts +2224 -0
  62. package/src/cli/templates/app/src/setups/exploded-view.ts +246 -0
  63. package/src/cli/templates/app/src/setups/file-format-icons.ts +95 -0
  64. package/src/cli/templates/app/src/setups/files-panel.ts +1503 -0
  65. package/src/cli/templates/app/src/setups/fps-indicator.ts +63 -0
  66. package/src/cli/templates/app/src/setups/graphics-panel.ts +490 -0
  67. package/src/cli/templates/app/src/setups/helper-panel.ts +88 -0
  68. package/src/cli/templates/app/src/setups/hider.ts +98 -0
  69. package/src/cli/templates/app/src/setups/index.ts +33 -3
  70. package/src/cli/templates/app/src/setups/inspection.ts +136 -0
  71. package/src/cli/templates/app/src/setups/measurement-panel.ts +188 -0
  72. package/src/cli/templates/app/src/setups/measurement-settings-panel.ts +161 -0
  73. package/src/cli/templates/app/src/setups/measurement-tool.ts +570 -0
  74. package/src/cli/templates/app/src/setups/measurements.ts +133 -0
  75. package/src/cli/templates/app/src/setups/model-tree.ts +797 -0
  76. package/src/cli/templates/app/src/setups/navigation-gizmo.ts +316 -0
  77. package/src/cli/templates/app/src/setups/objects-panel.ts +127 -0
  78. package/src/cli/templates/app/src/setups/plans-panel.ts +619 -0
  79. package/src/cli/templates/app/src/setups/properties-panel.ts +1048 -0
  80. package/src/cli/templates/app/src/setups/reality-capture/lib/hidden-tiles-plugin.ts +88 -0
  81. package/src/cli/templates/app/src/setups/reality-capture/lib/point-tile-plugin.ts +166 -0
  82. package/src/cli/templates/app/src/setups/reality-capture/lib/render-frame.ts +31 -0
  83. package/src/cli/templates/app/src/setups/reality-capture/lib/splat-tile-plugin.ts +51 -0
  84. package/src/cli/templates/app/src/setups/reality-capture-viewer.ts +1383 -0
  85. package/src/cli/templates/app/src/setups/right-sidebar.ts +178 -0
  86. package/src/cli/templates/app/src/setups/settings-panel.ts +94 -0
  87. package/src/cli/templates/app/src/setups/styles-panel.ts +110 -0
  88. package/src/cli/templates/app/src/setups/styles.ts +375 -0
  89. package/src/cli/templates/app/src/setups/tool-mode-manager.ts +150 -0
  90. package/src/cli/templates/app/src/setups/tool-mode.ts +23 -0
  91. package/src/cli/templates/app/src/setups/toolbar.ts +229 -0
  92. package/src/cli/templates/app/src/setups/ui-manager.ts +27 -0
  93. package/src/cli/templates/app/src/setups/visibility-toolbar.ts +498 -0
  94. package/src/cli/templates/app/src/setups/walkthrough.ts +528 -0
  95. package/src/cli/templates/app/src/ui-components/app-info-section/index.ts +26 -0
  96. package/src/cli/templates/app/src/ui-components/app-info-section/src/index.ts +1 -0
  97. package/src/cli/templates/app/src/ui-components/app-info-section/src/types.ts +15 -0
  98. package/src/cli/templates/app/src/ui-components/cloud-runner-section/index.ts +37 -0
  99. package/src/cli/templates/app/src/ui-components/cloud-runner-section/src/index.ts +1 -0
  100. package/src/cli/templates/app/src/ui-components/cloud-runner-section/src/types.ts +14 -0
  101. package/src/cli/templates/app/src/ui-components/index.ts +2 -1
  102. package/src/cli/templates/app/tsconfig.json +16 -17
  103. package/src/cli/templates/app/vite.config.js +45 -42
  104. package/src/cli/templates/cloud-component/README.md +205 -205
  105. package/src/cli/templates/cloud-component/_thatopen +5 -5
  106. package/src/cli/templates/cloud-component/declarations.json +4 -4
  107. package/src/cli/templates/cloud-component/package.json +21 -21
  108. package/src/cli/templates/cloud-component/src/main.ts +70 -70
  109. package/src/cli/templates/cloud-component/tsconfig.json +16 -16
  110. package/src/cli/templates/cloud-component/vite.config.js +46 -46
  111. package/src/cli/templates/shared/AGENTS.md +8 -8
  112. package/src/cli/templates/shared/CLAUDE.md +1 -1
  113. package/src/cli/templates/shared/_gitignore +5 -4
  114. package/src/built-in/AppManager/example.ts +0 -86
  115. package/src/built-in/FileList/example.ts +0 -107
  116. package/src/built-in/TabbedNavigation/example.ts +0 -115
  117. package/src/built-in/ViewportsManager/example.ts +0 -106
  118. package/src/cli/templates/app/src/setups/fragments.ts +0 -18
  119. package/src/cli/templates/app/src/setups/ifc-loader.ts +0 -12
  120. package/src/cli/templates/app/src/ui-components/AppPanel/index.ts +0 -160
@@ -0,0 +1,229 @@
1
+ import * as OBC from "@thatopen/components";
2
+ import * as BUI from "@thatopen/ui";
3
+ import { cameraTools } from "./camera-tools";
4
+ import { hider } from "./hider";
5
+ import { clipper } from "./clipper";
6
+ import { lengthMeasurement, areaMeasurement } from "./measurements";
7
+ import type { HelperPanelController } from "./helper-panel";
8
+ import { stylesTool } from "./styles-panel";
9
+
10
+ /**
11
+ * A floating tool palette centered at the BOTTOM-CENTER of the viewport. Built
12
+ * on BUI's native `bim-toolbar` (icon-only `bim-button`s with hover tooltips),
13
+ * placed in a `bim-grid floating` overlay so the bar is interactive while empty
14
+ * areas click through to the 3D scene. Styled to match the cards (dark
15
+ * `bg-base`, rounded, subtle shadow).
16
+ *
17
+ * Tool kinds (the modules' integration contract):
18
+ * - ACTION `{ label, icon, run() }` — fire-and-forget.
19
+ * - MODE `{ label, icon, activate(), deactivate() }` — mutually exclusive:
20
+ * activating one deactivates the current; clicking the active one
21
+ * turns it off.
22
+ * - TOGGLE `{ label, icon, activate(), deactivate(), active?() }` — independent
23
+ * on/off (e.g. ortho).
24
+ * - PANEL `{ label, icon, render(refresh) }` — toggles the bottom-left helper
25
+ * panel showing that tool's content (e.g. Styles). Mutually exclusive
26
+ * among panel tools; INDEPENDENT of viewport modes (opening Styles
27
+ * doesn't cancel an active section/measure mode, and vice versa).
28
+ *
29
+ * Only this file assembles the toolbar; other workers deliver tool controllers
30
+ * (camera here; hider from hider.ts; clipper/measure to be added when ready).
31
+ *
32
+ * @param components engine components
33
+ * @param container the viewport element to overlay
34
+ */
35
+ type ActionTool = {
36
+ kind: "action";
37
+ label: string;
38
+ icon: string;
39
+ run: () => void | Promise<void>;
40
+ };
41
+ type ModeTool = {
42
+ kind: "mode";
43
+ label: string;
44
+ icon: string;
45
+ activate: () => void | Promise<void>;
46
+ deactivate: () => void | Promise<void>;
47
+ };
48
+ type ToggleTool = {
49
+ kind: "toggle";
50
+ label: string;
51
+ icon: string;
52
+ activate: () => void | Promise<void>;
53
+ deactivate: () => void | Promise<void>;
54
+ active?: () => boolean;
55
+ };
56
+ type PanelTool = {
57
+ kind: "panel";
58
+ label: string;
59
+ icon: string;
60
+ render: (refresh: () => void) => unknown;
61
+ };
62
+ type Tool = ActionTool | ModeTool | ToggleTool | PanelTool;
63
+
64
+ export const toolbar = (
65
+ components: OBC.Components,
66
+ container: HTMLElement,
67
+ helper: HelperPanelController, // the left-stack helper card (panel tools drive it)
68
+ ) => {
69
+ const cam = cameraTools(components);
70
+ const vis = hider(components);
71
+ // World for the MODE tools (clipper/measurements need a world + its canvas).
72
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
73
+ const world = [...components.get(OBC.Worlds).list.values()][0] as any;
74
+ // MODE controllers ({ label, icon, activate, deactivate }) — only built when a
75
+ // world exists (it does: the viewport mounts before the toolbar).
76
+ const modeTools: Tool[] = world
77
+ ? [
78
+ { kind: "mode", ...clipper(components, world) },
79
+ { kind: "mode", ...lengthMeasurement(components, world) },
80
+ { kind: "mode", ...areaMeasurement(components, world) },
81
+ ]
82
+ : [];
83
+
84
+ // Groups → rendered as separate toolbar sections (auto-divider between them).
85
+ // Order: [view: fit, ortho] | [tools: section/measure — pending] | [visibility].
86
+ const groups: Tool[][] = [
87
+ [
88
+ { kind: "action", label: "Zoom to fit", icon: cam.fitAll.icon, run: cam.fitAll.run },
89
+ {
90
+ kind: "toggle",
91
+ label: "Orthographic",
92
+ icon: cam.orthoToggle.icon,
93
+ activate: cam.orthoToggle.activate,
94
+ deactivate: cam.orthoToggle.deactivate,
95
+ active: cam.orthoToggle.active,
96
+ },
97
+ ] as Tool[],
98
+ // Mode tools (section / measure) — mutually exclusive.
99
+ modeTools,
100
+ [
101
+ { kind: "action", label: "Hide", icon: "mdi:eye-off-outline", run: vis.hideSelected },
102
+ { kind: "action", label: "Isolate", icon: "mdi:select-search", run: vis.isolateSelected },
103
+ { kind: "action", label: "Show all", icon: "mdi:eye-outline", run: vis.showAll },
104
+ ] as Tool[],
105
+ // Panel tools (open the bottom-left helper). Styles needs a world.
106
+ world
107
+ ? ([{ kind: "panel", ...stylesTool(components, world) }] as Tool[])
108
+ : [],
109
+ ].filter((g) => g.length > 0);
110
+
111
+ // ── Active-state bookkeeping ───────────────────────────────────
112
+ let activeMode: ModeTool | null = null; // mutual exclusion across all modes
113
+ let activePanel: PanelTool | null = null; // exclusive among panel tools
114
+ const onToggle = new Set<ToggleTool>(); // independent toggles that are on
115
+
116
+ const isActive = (t: Tool) =>
117
+ t.kind === "mode"
118
+ ? t === activeMode
119
+ : t.kind === "panel"
120
+ ? t === activePanel
121
+ : t.kind === "toggle"
122
+ ? (t.active ? t.active() : onToggle.has(t))
123
+ : false;
124
+
125
+ const onClick = async (t: Tool) => {
126
+ if (t.kind === "action") {
127
+ await t.run();
128
+ } else if (t.kind === "mode") {
129
+ if (activeMode === t) {
130
+ await t.deactivate();
131
+ activeMode = null;
132
+ } else {
133
+ if (activeMode) await activeMode.deactivate();
134
+ await t.activate();
135
+ activeMode = t;
136
+ }
137
+ } else if (t.kind === "panel") {
138
+ // Toggle the helper panel; exclusive among panel tools, independent of modes.
139
+ if (activePanel === t) {
140
+ activePanel = null;
141
+ helper.clear();
142
+ } else {
143
+ activePanel = t;
144
+ helper.show({
145
+ title: t.label,
146
+ icon: t.icon,
147
+ render: () => t.render(() => helper.refresh()),
148
+ });
149
+ }
150
+ } else {
151
+ const on = isActive(t);
152
+ if (on) {
153
+ await t.deactivate();
154
+ onToggle.delete(t);
155
+ } else {
156
+ await t.activate();
157
+ onToggle.add(t);
158
+ }
159
+ }
160
+ refresh();
161
+ };
162
+
163
+ let tick = 0;
164
+ const refresh = () => barUpdate({ tick: (tick += 1) });
165
+
166
+ const [bar, barUpdate] = BUI.Component.create<HTMLElement, { tick: number }>(
167
+ // Param required: BUI.Component.create returns a single element (not the
168
+ // [element, update] tuple) when the template has arity 0.
169
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
170
+ (_state) => BUI.html`
171
+ <bim-toolbar
172
+ style="
173
+ pointer-events: auto;
174
+ padding: 0.15rem;
175
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
176
+ /* Uniform rhythm: inter-button gap = G; section padding = G/2 so the
177
+ space across a divider (padA + padB) equals the inter-button gap and
178
+ the divider sits centered with equal margins. */
179
+ "
180
+ >
181
+ ${groups.map(
182
+ (group) => BUI.html`
183
+ <bim-toolbar-section label-hidden>
184
+ ${group.map(
185
+ (t) => BUI.html`
186
+ <bim-button
187
+ icon=${t.icon}
188
+ ?active=${isActive(t)}
189
+ @click=${() => onClick(t)}
190
+ style="width: 1.9rem; min-width: 1.9rem; height: 1.9rem;"
191
+ ><bim-tooltip placement="top">${t.label}</bim-tooltip></bim-button>
192
+ `,
193
+ )}
194
+ </bim-toolbar-section>
195
+ `,
196
+ )}
197
+ </bim-toolbar>
198
+ `,
199
+ { tick: 0 },
200
+ );
201
+
202
+ // Floating grid: bar docked bottom-center. Row 1 (1fr) empty filler above;
203
+ // row 2 (auto) holds the bar in the center column, flanked by 1fr columns so
204
+ // it stays horizontally centered. Empty areas click through.
205
+ const grid = BUI.Component.create(() => {
206
+ const onCreated = (element?: Element) => {
207
+ if (!element) return;
208
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
209
+ const g = element as any;
210
+ g.elements = { bar };
211
+ g.layouts = {
212
+ main: {
213
+ template: `
214
+ "fillL fillC fillR" 1fr
215
+ "restL bar restR" auto
216
+ / 1fr auto 1fr
217
+ `,
218
+ },
219
+ };
220
+ g.layout = "main";
221
+ };
222
+ return BUI.html`
223
+ <bim-grid style="padding: 1rem;" ${BUI.ref(onCreated)} floating></bim-grid>
224
+ `;
225
+ });
226
+ container.append(grid);
227
+
228
+ return bar;
229
+ };
@@ -0,0 +1,27 @@
1
+ import * as OBC from "@thatopen/components";
2
+ import * as BUI from "@thatopen/ui";
3
+ import { UIManager } from "@thatopen/services";
4
+ import {
5
+ appInfoSectionTemplate,
6
+ AppInfoSectionState,
7
+ cloudRunnerSectionTemplate,
8
+ CloudRunnerSectionState,
9
+ } from "../ui-components";
10
+
11
+ export type CustomUIs = {
12
+ appInfoSection: { type: BUI.PanelSection; state: AppInfoSectionState };
13
+ cloudRunnerSection: { type: BUI.PanelSection; state: CloudRunnerSectionState };
14
+ };
15
+
16
+ export const getUIManager = (components: OBC.Components) =>
17
+ components.get(UIManager<CustomUIs>);
18
+
19
+ export const uiManager = (components: OBC.Components) => {
20
+ const uis = getUIManager(components);
21
+ uis.registerTemplate("appInfoSection", {
22
+ template: appInfoSectionTemplate,
23
+ });
24
+ uis.registerTemplate("cloudRunnerSection", {
25
+ template: cloudRunnerSectionTemplate,
26
+ });
27
+ };