@vuu-ui/vuu-shell 4.0.0-alpha.24 → 4.0.0-alpha.26

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 (77) hide show
  1. package/package.json +15 -15
  2. package/src/persistence-manager/PersistenceProvider.js +5 -7
  3. package/src/persistence-manager/index.js +1 -3
  4. package/src/workspace-management/LayoutList.js +1 -1
  5. package/src/workspace-management/index.js +1 -8
  6. package/src/workspace-management/useWorkspaceContextMenuItems.js +1 -2
  7. package/types/feature/FeatureErrorBoundary.d.ts +13 -0
  8. package/types/persistence-manager/PersistenceProvider.d.ts +2 -3
  9. package/types/persistence-manager/index.d.ts +1 -3
  10. package/types/src/ShellContextProvider.d.ts +7 -0
  11. package/types/src/app-header/AppHeader.d.ts +6 -0
  12. package/types/src/app-header/index.d.ts +1 -0
  13. package/types/src/application-provider/ApplicationContext.d.ts +11 -0
  14. package/types/src/application-provider/ApplicationProvider.d.ts +17 -0
  15. package/types/src/application-provider/index.d.ts +1 -0
  16. package/types/src/feature/Feature.d.ts +10 -0
  17. package/types/src/feature/FeatureErrorBoundary.d.ts +13 -0
  18. package/types/src/feature/Loader.d.ts +1 -0
  19. package/types/src/feature/index.d.ts +1 -0
  20. package/types/src/feature-and-layout-provider/FeatureAndLayoutProvider.d.ts +19 -0
  21. package/types/src/feature-and-layout-provider/index.d.ts +1 -0
  22. package/types/src/feature-list/FeatureList.d.ts +7 -0
  23. package/types/src/feature-list/index.d.ts +1 -0
  24. package/types/src/get-layout-history.d.ts +8 -0
  25. package/types/src/index.d.ts +14 -0
  26. package/types/src/left-nav/LeftNav.d.ts +14 -0
  27. package/types/src/left-nav/index.d.ts +1 -0
  28. package/types/src/login/LoginPanel.d.ts +6 -0
  29. package/types/src/login/VuuLogo.d.ts +1 -0
  30. package/types/src/persistence-manager/LocalPersistenceManager.d.ts +20 -0
  31. package/types/src/persistence-manager/PersistenceManager.d.ts +71 -0
  32. package/types/src/persistence-manager/PersistenceProvider.d.ts +11 -0
  33. package/types/src/persistence-manager/RemotePersistenceManager.d.ts +25 -0
  34. package/types/src/persistence-manager/StaticPersistenceManager.d.ts +25 -0
  35. package/types/src/persistence-manager/index.d.ts +5 -0
  36. package/types/src/shell-layout-templates/context-panel/ContextPanel.d.ts +13 -0
  37. package/types/src/shell-layout-templates/context-panel/index.d.ts +1 -0
  38. package/types/src/shell-layout-templates/full-height-left-panel/useFullHeightLeftPanel.d.ts +2 -0
  39. package/types/src/shell-layout-templates/index.d.ts +3 -0
  40. package/types/src/shell-layout-templates/inlay-left-panel/useInlayLeftPanel.d.ts +2 -0
  41. package/types/src/shell-layout-templates/left-main-tabs/useLeftMainTabs.d.ts +2 -0
  42. package/types/src/shell-layout-templates/side-panel/SidePanel.d.ts +8 -0
  43. package/types/src/shell-layout-templates/side-panel/index.d.ts +1 -0
  44. package/types/src/shell-layout-templates/simple-content-pane/useSimpleContentPane.d.ts +2 -0
  45. package/types/src/shell-layout-templates/useShellLayout.d.ts +51 -0
  46. package/types/src/shell.d.ts +17 -0
  47. package/types/src/theme-switch/ThemeSwitch.d.ts +8 -0
  48. package/types/src/theme-switch/index.d.ts +1 -0
  49. package/types/src/user-settings/SettingsForm.d.ts +46 -0
  50. package/types/src/user-settings/UserSettingsPanel.d.ts +3 -0
  51. package/types/src/user-settings/index.d.ts +2 -0
  52. package/types/src/workspace-management/LayoutList.d.ts +2 -0
  53. package/types/src/workspace-management/LayoutTile.d.ts +7 -0
  54. package/types/src/workspace-management/SaveLayoutPanel.d.ts +9 -0
  55. package/types/src/workspace-management/WorkspaceProvider.d.ts +52 -0
  56. package/types/src/workspace-management/defaultWorkspaceJSON.d.ts +10 -0
  57. package/types/src/workspace-management/index.d.ts +5 -0
  58. package/types/src/workspace-management/screenshot-utils.d.ts +6 -0
  59. package/types/src/workspace-management/useWorkspaceContextMenuItems.d.ts +5 -0
  60. package/types/user-settings/SettingsForm.d.ts +46 -0
  61. package/types/user-settings/UserSettingsPanel.d.ts +3 -0
  62. package/types/user-settings/index.d.ts +2 -0
  63. package/types/workspace-management/WorkspaceProvider.d.ts +50 -61
  64. package/types/workspace-management/index.d.ts +5 -8
  65. package/types/workspace-management/shell-workspace-components.d.ts +1 -1
  66. package/src/persistence-manager/LocalWorkspacePersistenceService.js +0 -129
  67. package/src/persistence-manager/RemoteWorkspacePersistenceService.js +0 -112
  68. package/src/persistence-manager/WorkspacePersistenceService.js +0 -9
  69. package/src/workspace-management/WorkspaceController.js +0 -73
  70. package/src/workspace-management/WorkspaceHost.js +0 -194
  71. package/src/workspace-management/WorkspacePersistentState.js +0 -67
  72. package/src/workspace-management/WorkspaceProvider.js +0 -730
  73. package/src/workspace-management/WorkspaceRepository.js +0 -127
  74. package/src/workspace-management/WorkspaceStartPanel.css.js +0 -44
  75. package/src/workspace-management/WorkspaceStartPanel.js +0 -34
  76. package/src/workspace-management/workspace-component-registry.js +0 -30
  77. package/src/workspace-management/workspace-schemas.js +0 -257
@@ -1,9 +0,0 @@
1
- class WorkspacePersistenceError extends Error {
2
- operation;
3
- status;
4
- constructor(message, operation, status){
5
- super(message), this.operation = operation, this.status = status;
6
- this.name = "WorkspacePersistenceError";
7
- }
8
- }
9
- export { WorkspacePersistenceError };
@@ -1,73 +0,0 @@
1
- import { GridLayoutDocumentController } from "@vuu-ui/grid-layout";
2
- import { WorkspacePersistentStateStore } from "./WorkspacePersistentState.js";
3
- import { WorkspaceRepository } from "./WorkspaceRepository.js";
4
- import { WORKSPACE_SNAPSHOT_VERSION } from "./workspace-schemas.js";
5
- class WorkspaceController {
6
- definitionId;
7
- documentController;
8
- instanceId;
9
- name;
10
- persistentState;
11
- renderers;
12
- repository;
13
- settingsCodecs;
14
- #disposed = false;
15
- #savingStructure = false;
16
- #onError;
17
- #unsubscribe;
18
- constructor(options){
19
- this.definitionId = options.definitionId;
20
- this.instanceId = options.instanceId;
21
- this.name = options.name;
22
- this.renderers = options.renderers;
23
- this.settingsCodecs = options.settingsCodecs;
24
- this.#onError = options.onError;
25
- this.repository = new WorkspaceRepository(options.service, options.instanceId, void 0 === options.revision ? void 0 : {
26
- revision: options.revision,
27
- snapshot: options.snapshot,
28
- version: 1,
29
- workspaceInstanceId: options.instanceId
30
- });
31
- this.persistentState = new WorkspacePersistentStateStore(options.snapshot.componentState);
32
- this.documentController = new GridLayoutDocumentController(options.snapshot.layout);
33
- this.#unsubscribe = this.persistentState.subscribe(()=>{
34
- if (!this.#savingStructure) this.#save();
35
- });
36
- }
37
- get snapshot() {
38
- const layout = this.documentController.getSnapshot();
39
- if (!layout) throw new Error(`Workspace "${this.instanceId}" has no layout document`);
40
- return {
41
- version: WORKSPACE_SNAPSHOT_VERSION,
42
- layout,
43
- componentState: this.persistentState.getSnapshot()
44
- };
45
- }
46
- handleDocumentChange = (document, change)=>{
47
- if (this.#disposed) return;
48
- this.documentController.replace(document);
49
- this.#savingStructure = true;
50
- try {
51
- for (const componentId of change.removedComponentInstanceIds)this.persistentState.purge(componentId);
52
- } finally{
53
- this.#savingStructure = false;
54
- }
55
- this.#save();
56
- };
57
- rename(name) {
58
- this.name = name;
59
- }
60
- dispose() {
61
- if (!this.#disposed) {
62
- this.#disposed = true;
63
- this.#unsubscribe();
64
- }
65
- return this.repository.dispose();
66
- }
67
- #save() {
68
- if (!this.#disposed) this.repository.save(this.snapshot).catch((cause)=>{
69
- if (!this.#disposed) this.#onError(cause instanceof Error ? cause : new Error("Workspace snapshot persistence failed"));
70
- });
71
- }
72
- }
73
- export { WorkspaceController };
@@ -1,194 +0,0 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
2
- import { GridLayout, GridLayoutProvider } from "@vuu-ui/grid-layout";
3
- import { Tab, Tabstrip } from "@vuu-ui/vuu-ui-controls";
4
- import { useCallback, useRef, useState } from "react";
5
- import { WorkspacePersistentStateProvider, WorkspacePersistentStateStore } from "./WorkspacePersistentState.js";
6
- import { emptyWorkspaceSnapshot, useWorkspace } from "./WorkspaceProvider.js";
7
- import { WorkspaceStartPanel } from "./WorkspaceStartPanel.js";
8
- import { WORKSPACE_SNAPSHOT_VERSION } from "./workspace-schemas.js";
9
- const WorkspaceGrid = ({ active, controller })=>{
10
- const [isEmpty, setIsEmpty] = useState(0 === controller.snapshot.layout.components.length);
11
- const handleDocumentError = useCallback((error)=>{
12
- throw new Error(`Invalid workspace document at ${error.path}: ${error.message}`);
13
- }, []);
14
- const handleDocumentChange = useCallback((document, change)=>{
15
- setIsEmpty(0 === document.components.length);
16
- controller.handleDocumentChange(document, change);
17
- }, [
18
- controller
19
- ]);
20
- return /*#__PURE__*/ jsx("section", {
21
- "aria-hidden": !active,
22
- "aria-labelledby": `${controller.instanceId}-tab`,
23
- className: "vuuWorkspaceHost-workspace",
24
- "data-workspace-instance-id": controller.instanceId,
25
- hidden: !active,
26
- id: controller.instanceId,
27
- role: "tabpanel",
28
- children: /*#__PURE__*/ jsx(WorkspacePersistentStateProvider, {
29
- store: controller.persistentState,
30
- children: /*#__PURE__*/ jsx(GridLayoutProvider, {
31
- componentRenderers: controller.renderers,
32
- document: controller.snapshot.layout,
33
- documentController: controller.documentController,
34
- onDocumentChange: handleDocumentChange,
35
- onDocumentError: handleDocumentError,
36
- settingsCodecs: controller.settingsCodecs,
37
- children: /*#__PURE__*/ jsx(GridLayout, {
38
- id: controller.snapshot.layout.layout.id,
39
- placeholderContent: isEmpty ? /*#__PURE__*/ jsx(WorkspaceStartPanel, {}) : void 0
40
- })
41
- })
42
- })
43
- });
44
- };
45
- const EmptyWorkspaceDropTarget = ()=>{
46
- const { componentRenderers, createWorkspaceFromSnapshot, settingsCodecs } = useWorkspace();
47
- const creating = useRef(false);
48
- const [creationPending, setCreationPending] = useState(false);
49
- const [generation, setGeneration] = useState(0);
50
- const [persistentState, setPersistentState] = useState(()=>new WorkspacePersistentStateStore());
51
- const handleDocumentError = useCallback((error)=>{
52
- throw new Error(`Invalid empty workspace document at ${error.path}: ${error.message}`);
53
- }, []);
54
- const handleDocumentChange = useCallback((document)=>{
55
- if (creating.current || 0 === document.components.length) return;
56
- creating.current = true;
57
- setCreationPending(true);
58
- createWorkspaceFromSnapshot({
59
- componentState: persistentState.getSnapshot(),
60
- layout: document,
61
- version: WORKSPACE_SNAPSHOT_VERSION
62
- }, "Untitled").catch(()=>{
63
- creating.current = false;
64
- setCreationPending(false);
65
- setPersistentState(new WorkspacePersistentStateStore());
66
- setGeneration((current)=>current + 1);
67
- });
68
- }, [
69
- createWorkspaceFromSnapshot,
70
- persistentState
71
- ]);
72
- if (!componentRenderers || !settingsCodecs) return /*#__PURE__*/ jsx("div", {
73
- className: "vuuWorkspaceHost-state",
74
- role: "alert",
75
- children: "Workspace component registries are not configured."
76
- });
77
- if (creationPending) return /*#__PURE__*/ jsx("div", {
78
- className: "vuuWorkspaceHost-empty",
79
- children: /*#__PURE__*/ jsx("div", {
80
- className: "vuuWorkspaceHost-state",
81
- role: "status",
82
- children: "Creating workspace…"
83
- })
84
- });
85
- return /*#__PURE__*/ jsx("div", {
86
- className: "vuuWorkspaceHost-empty",
87
- children: /*#__PURE__*/ jsx(WorkspacePersistentStateProvider, {
88
- store: persistentState,
89
- children: /*#__PURE__*/ jsx(GridLayoutProvider, {
90
- componentRenderers: componentRenderers,
91
- onDocumentChange: handleDocumentChange,
92
- onDocumentError: handleDocumentError,
93
- settingsCodecs: settingsCodecs,
94
- children: /*#__PURE__*/ jsx(GridLayout, {
95
- className: "vuuWorkspaceHost-emptyGrid",
96
- colsAndRows: {
97
- cols: [
98
- "1fr"
99
- ],
100
- rows: [
101
- "1fr"
102
- ]
103
- },
104
- id: emptyWorkspaceSnapshot.layout.layout.id,
105
- placeholderContent: /*#__PURE__*/ jsx(WorkspaceStartPanel, {})
106
- })
107
- }, generation)
108
- })
109
- });
110
- };
111
- const WorkspaceHost = ()=>{
112
- const { activeWorkspaceInstanceId, closeWorkspace, controllers, createWorkspaceFromSnapshot, error, renameWorkspace, selectWorkspace, status } = useWorkspace();
113
- const [tabRevision, setTabRevision] = useState(0);
114
- const activeWorkspaceIndex = controllers.findIndex(({ instanceId })=>instanceId === activeWorkspaceInstanceId);
115
- const handleActiveChange = useCallback((tabIndex)=>{
116
- const controller = controllers[tabIndex];
117
- if (controller) selectWorkspace(controller.instanceId);
118
- }, [
119
- controllers,
120
- selectWorkspace
121
- ]);
122
- const handleCloseTab = useCallback((tabIndex)=>{
123
- const controller = controllers[tabIndex];
124
- if (controller) closeWorkspace(controller.instanceId);
125
- }, [
126
- closeWorkspace,
127
- controllers
128
- ]);
129
- const handleAddTab = useCallback(()=>{
130
- const titles = new Set(controllers.map(({ name })=>name));
131
- let suffix = 1;
132
- let title = "Untitled";
133
- while(titles.has(title)){
134
- suffix += 1;
135
- title = `Untitled ${suffix}`;
136
- }
137
- createWorkspaceFromSnapshot(emptyWorkspaceSnapshot, title).catch(()=>void 0);
138
- }, [
139
- controllers,
140
- createWorkspaceFromSnapshot
141
- ]);
142
- const handleExitEditMode = useCallback((originalTitle, title, _allowDeactivation, tabIndex)=>{
143
- const controller = controllers[tabIndex];
144
- if (controller && title !== originalTitle) renameWorkspace(controller.instanceId, title).catch(()=>{
145
- setTabRevision((revision)=>revision + 1);
146
- });
147
- }, [
148
- controllers,
149
- renameWorkspace
150
- ]);
151
- if ("loading" === status) return /*#__PURE__*/ jsx("div", {
152
- className: "vuuWorkspaceHost-state",
153
- role: "status",
154
- children: "Loading workspaces…"
155
- });
156
- if ("error" === status) return /*#__PURE__*/ jsx("div", {
157
- className: "vuuWorkspaceHost-state",
158
- role: "alert",
159
- children: error?.message ?? "Unable to load workspaces"
160
- });
161
- return /*#__PURE__*/ jsxs("div", {
162
- className: "vuuWorkspaceHost vuu-workspace-tabs",
163
- children: [
164
- /*#__PURE__*/ jsx(Tabstrip, {
165
- activeTabIndex: activeWorkspaceIndex,
166
- allowAddTab: true,
167
- allowCloseTab: true,
168
- allowRenameTab: true,
169
- animateSelectionThumb: false,
170
- "aria-label": "Workspace Tabs",
171
- className: "vuuTabHeader",
172
- onActiveChange: handleActiveChange,
173
- onAddTab: handleAddTab,
174
- onCloseTab: handleCloseTab,
175
- onExitEditMode: handleExitEditMode,
176
- variant: "primary",
177
- children: controllers.map((controller)=>/*#__PURE__*/ jsx(Tab, {
178
- ariaControls: controller.instanceId,
179
- id: `${controller.instanceId}-tab`,
180
- label: controller.name,
181
- onClose: ()=>void closeWorkspace(controller.instanceId)
182
- }, `${controller.instanceId}-${tabRevision}`))
183
- }),
184
- /*#__PURE__*/ jsx("div", {
185
- className: "vuuWorkspaceHost-content",
186
- children: "empty" === status ? /*#__PURE__*/ jsx(EmptyWorkspaceDropTarget, {}) : controllers.map((controller)=>/*#__PURE__*/ jsx(WorkspaceGrid, {
187
- active: controller.instanceId === activeWorkspaceInstanceId,
188
- controller: controller
189
- }, controller.instanceId))
190
- })
191
- ]
192
- });
193
- };
194
- export { WorkspaceHost };
@@ -1,67 +0,0 @@
1
- import { createContext, createElement, useContext, useSyncExternalStore } from "react";
2
- import { cloneWorkspaceValue } from "./workspace-schemas.js";
3
- class WorkspacePersistentStateStore {
4
- #state;
5
- #listeners = new Set();
6
- constructor(initialState = {}){
7
- this.#state = Object.freeze(cloneWorkspaceValue(initialState));
8
- }
9
- getSnapshot = ()=>this.#state;
10
- subscribe = (listener)=>{
11
- this.#listeners.add(listener);
12
- return ()=>this.#listeners.delete(listener);
13
- };
14
- get(componentInstanceId) {
15
- const value = this.#state[componentInstanceId];
16
- return void 0 === value ? void 0 : cloneWorkspaceValue(value);
17
- }
18
- update(componentInstanceId, update) {
19
- if (!componentInstanceId) throw new Error("componentInstanceId must not be empty");
20
- const next = "function" == typeof update ? update(this.get(componentInstanceId)) : update;
21
- const captured = cloneWorkspaceValue(next);
22
- if (!captured.componentType || !Number.isInteger(captured.schemaVersion) || captured.schemaVersion < 1) throw new Error("Component persistent state metadata is invalid");
23
- this.#state = Object.freeze({
24
- ...this.#state,
25
- [componentInstanceId]: captured
26
- });
27
- this.#emit();
28
- }
29
- purge(componentInstanceId) {
30
- if (void 0 === componentInstanceId) {
31
- if (Object.keys(this.#state).length > 0) {
32
- this.#state = Object.freeze({});
33
- this.#emit();
34
- }
35
- return;
36
- }
37
- if (void 0 !== this.#state[componentInstanceId]) {
38
- const { [componentInstanceId]: removed, ...remaining } = this.#state;
39
- this.#state = Object.freeze(remaining);
40
- this.#emit();
41
- }
42
- }
43
- #emit() {
44
- this.#listeners.forEach((listener)=>{
45
- listener();
46
- });
47
- }
48
- }
49
- const WorkspacePersistentStateContext = /*#__PURE__*/ createContext(null);
50
- const WorkspacePersistentStateProvider = ({ children, store })=>/*#__PURE__*/ createElement(WorkspacePersistentStateContext.Provider, {
51
- value: store
52
- }, children);
53
- const useWorkspacePersistentStateStore = ()=>{
54
- const store = useContext(WorkspacePersistentStateContext);
55
- if (!store) throw new Error("useWorkspacePersistentStateStore requires WorkspacePersistentStateProvider");
56
- return store;
57
- };
58
- const useComponentPersistentState = (componentInstanceId)=>{
59
- const store = useWorkspacePersistentStateStore();
60
- const state = useSyncExternalStore(store.subscribe, ()=>store.getSnapshot()[componentInstanceId], ()=>store.getSnapshot()[componentInstanceId]);
61
- return [
62
- state,
63
- (update)=>store.update(componentInstanceId, update),
64
- ()=>store.purge(componentInstanceId)
65
- ];
66
- };
67
- export { WorkspacePersistentStateProvider, WorkspacePersistentStateStore, useComponentPersistentState, useWorkspacePersistentStateStore };