@medicine-wheel/app 0.4.3 → 0.4.5

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.
@@ -32,6 +32,7 @@ import {
32
32
  persistGraphLayoutStore,
33
33
  saveNamedGraphLayout,
34
34
  selectGraphLayout,
35
+ upsertActiveGraphLayout,
35
36
  upsertCurrentGraphLayout,
36
37
  type GraphLayoutStore,
37
38
  } from "@/lib/graph-layout-storage";
@@ -187,19 +188,23 @@ export default function GraphPage() {
187
188
 
188
189
  const handleNodePositionsChange = useCallback(
189
190
  (positions: MWGraphNodePositions) => {
190
- saveLayoutStore(upsertCurrentGraphLayout(layoutStoreRef.current, positions));
191
+ saveLayoutStore(upsertActiveGraphLayout(layoutStoreRef.current, positions));
191
192
  },
192
193
  [saveLayoutStore],
193
194
  );
194
195
 
195
196
  const saveNamedLayout = useCallback(() => {
196
- const name = layoutName.trim();
197
+ const active = getActiveGraphLayout(layoutStoreRef.current);
198
+ const name =
199
+ layoutName.trim() ||
200
+ (active.id !== CURRENT_GRAPH_LAYOUT_ID ? active.name : "");
201
+
197
202
  if (!name) {
198
203
  toast.error("Name the disposition first");
199
204
  return;
200
205
  }
201
206
 
202
- const positions = getActiveGraphLayout(layoutStoreRef.current).positions;
207
+ const positions = active.positions;
203
208
  if (Object.keys(positions).length === 0) {
204
209
  toast.error("Move a node before saving");
205
210
  return;
@@ -329,7 +334,11 @@ export default function GraphPage() {
329
334
  onKeyDown={(event) => {
330
335
  if (event.key === "Enter") saveNamedLayout();
331
336
  }}
332
- placeholder="Name disposition"
337
+ placeholder={
338
+ activeLayout.id === CURRENT_GRAPH_LAYOUT_ID
339
+ ? "Name disposition"
340
+ : activeLayout.name
341
+ }
333
342
  className="min-w-0 flex-1 rounded-md border border-white/10 bg-white/5 px-3 py-2 text-sm text-white placeholder:text-gray-500"
334
343
  />
335
344
  <button
@@ -219,6 +219,42 @@ export function upsertCurrentGraphLayout(
219
219
  };
220
220
  }
221
221
 
222
+ export function upsertActiveGraphLayout(
223
+ store: GraphLayoutStore,
224
+ positions: MWGraphNodePositions,
225
+ updatedAt: string = nowIso(),
226
+ ): GraphLayoutStore {
227
+ const activeLayout = getActiveGraphLayout(store);
228
+ const mergedPositions = sanitizeGraphPositions({
229
+ ...activeLayout.positions,
230
+ ...positions,
231
+ });
232
+ const updatedLayout: GraphLayoutDisposition = {
233
+ ...activeLayout,
234
+ positions: mergedPositions,
235
+ updatedAt,
236
+ nodeCount: Object.keys(mergedPositions).length,
237
+ };
238
+
239
+ if (updatedLayout.id === CURRENT_GRAPH_LAYOUT_ID) {
240
+ const savedLayouts = store.layouts.filter((layout) => layout.id !== CURRENT_GRAPH_LAYOUT_ID);
241
+
242
+ return {
243
+ version: GRAPH_LAYOUT_STORE_VERSION,
244
+ activeLayoutId: CURRENT_GRAPH_LAYOUT_ID,
245
+ layouts: [updatedLayout, ...savedLayouts],
246
+ };
247
+ }
248
+
249
+ return {
250
+ version: GRAPH_LAYOUT_STORE_VERSION,
251
+ activeLayoutId: updatedLayout.id,
252
+ layouts: store.layouts.map((layout) =>
253
+ layout.id === updatedLayout.id ? updatedLayout : layout,
254
+ ),
255
+ };
256
+ }
257
+
222
258
  export function saveNamedGraphLayout(
223
259
  store: GraphLayoutStore,
224
260
  name: string,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@medicine-wheel/app",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "description": "Medicine Wheel — Interactive visual layer for Indigenous relational research with Four Directions, ceremonies, and narrative arcs",
5
5
  "bin": {
6
6
  "mw": "dist/cli/mw.js",
@@ -74,24 +74,24 @@
74
74
  "release:major": "npm run version:major && npm run publish:all && npm run release:commit"
75
75
  },
76
76
  "dependencies": {
77
- "@medicine-wheel/ceremony-protocol": "^0.4.3",
78
- "@medicine-wheel/community-review": "^0.4.3",
79
- "@medicine-wheel/consent-lifecycle": "^0.4.3",
80
- "@medicine-wheel/data-store": "^0.4.3",
81
- "@medicine-wheel/data-store-postgres": "^0.4.3",
82
- "@medicine-wheel/fire-keeper": "^0.4.3",
83
- "@medicine-wheel/graph-viz": "^0.4.3",
84
- "@medicine-wheel/importance-unit": "^0.4.3",
85
- "@medicine-wheel/mcp": "^4.4.2",
86
- "@medicine-wheel/narrative-engine": "^0.4.3",
87
- "@medicine-wheel/ontology-core": "^0.4.3",
88
- "@medicine-wheel/prompt-decomposition": "^0.4.3",
89
- "@medicine-wheel/relational-index": "^0.4.3",
90
- "@medicine-wheel/relational-query": "^0.4.3",
91
- "@medicine-wheel/session-reader": "^0.4.3",
92
- "@medicine-wheel/storage-provider": "^0.4.3",
93
- "@medicine-wheel/transformation-tracker": "^0.4.3",
94
- "@medicine-wheel/ui-components": "^0.4.3",
77
+ "@medicine-wheel/ceremony-protocol": "^0.4.5",
78
+ "@medicine-wheel/community-review": "^0.4.5",
79
+ "@medicine-wheel/consent-lifecycle": "^0.4.5",
80
+ "@medicine-wheel/data-store": "^0.4.5",
81
+ "@medicine-wheel/data-store-postgres": "^0.4.5",
82
+ "@medicine-wheel/fire-keeper": "^0.4.5",
83
+ "@medicine-wheel/graph-viz": "^0.4.5",
84
+ "@medicine-wheel/importance-unit": "^0.4.5",
85
+ "@medicine-wheel/mcp": "^4.4.5",
86
+ "@medicine-wheel/narrative-engine": "^0.4.5",
87
+ "@medicine-wheel/ontology-core": "^0.4.5",
88
+ "@medicine-wheel/prompt-decomposition": "^0.4.5",
89
+ "@medicine-wheel/relational-index": "^0.4.5",
90
+ "@medicine-wheel/relational-query": "^0.4.5",
91
+ "@medicine-wheel/session-reader": "^0.4.5",
92
+ "@medicine-wheel/storage-provider": "^0.4.5",
93
+ "@medicine-wheel/transformation-tracker": "^0.4.5",
94
+ "@medicine-wheel/ui-components": "^0.4.5",
95
95
  "@neondatabase/serverless": "^0.10.0",
96
96
  "clsx": "^2.1.1",
97
97
  "lucide-react": "^0.475.0",