diff --git a/apps/builder/package.json b/apps/builder/package.json index 537beb159..66dd3e8f0 100644 --- a/apps/builder/package.json +++ b/apps/builder/package.json @@ -84,6 +84,7 @@ "react": "18.2.0", "react-dom": "18.2.0", "react-markdown": "^9.0.1", + "shared-zustand": "2.0.0", "sonner": "1.3.1", "stripe": "12.13.0", "svg-round-corners": "0.4.1", @@ -97,12 +98,17 @@ "devDependencies": { "@chakra-ui/styled-system": "2.9.1", "@playwright/test": "1.41.2", + "@typebot.io/billing": "workspace:*", "@typebot.io/forge": "workspace:*", "@typebot.io/forge-repository": "workspace:*", "@typebot.io/lib": "workspace:*", + "@typebot.io/migrations": "workspace:*", + "@typebot.io/playwright": "workspace:*", "@typebot.io/prisma": "workspace:*", "@typebot.io/radar": "workspace:*", + "@typebot.io/results": "workspace:*", "@typebot.io/schemas": "workspace:*", + "@typebot.io/telemetry": "workspace:*", "@typebot.io/tsconfig": "workspace:*", "@types/canvas-confetti": "1.6.0", "@types/jsonwebtoken": "9.0.2", @@ -121,11 +127,6 @@ "next-runtime-env": "1.6.2", "superjson": "1.12.4", "typescript": "5.3.2", - "zod": "3.22.4", - "@typebot.io/playwright": "workspace:*", - "@typebot.io/billing": "workspace:*", - "@typebot.io/results": "workspace:*", - "@typebot.io/migrations": "workspace:*", - "@typebot.io/telemetry": "workspace:*" + "zod": "3.22.4" } } diff --git a/apps/builder/src/features/graph/hooks/useGroupsStore.ts b/apps/builder/src/features/graph/hooks/useGroupsStore.ts index ad6153f5b..318838c41 100644 --- a/apps/builder/src/features/graph/hooks/useGroupsStore.ts +++ b/apps/builder/src/features/graph/hooks/useGroupsStore.ts @@ -1,7 +1,8 @@ import { createWithEqualityFn } from 'zustand/traditional' import { Coordinates, CoordinatesMap } from '../types' import { Edge, Group, GroupV6 } from '@typebot.io/schemas' -import { persist } from 'zustand/middleware' +import { subscribeWithSelector } from 'zustand/middleware' +import { share } from 'shared-zustand' type Store = { focusedGroups: string[] @@ -21,80 +22,78 @@ type Store = { } export const useGroupsStore = createWithEqualityFn()( - persist( - (set, get) => ({ - focusedGroups: [], - groupsCoordinates: undefined, - groupsInClipboard: undefined, - isDraggingGraph: false, - getGroupsCoordinates: () => get().groupsCoordinates, - focusGroup: (groupId, isShiftKeyPressed) => - set((state) => ({ - focusedGroups: isShiftKeyPressed - ? state.focusedGroups.includes(groupId) - ? state.focusedGroups.filter((id) => id !== groupId) - : [...state.focusedGroups, groupId] - : [groupId], - })), - blurGroups: () => set({ focusedGroups: [] }), - moveFocusedGroups: (delta) => - set(({ focusedGroups, groupsCoordinates }) => ({ - groupsCoordinates: groupsCoordinates - ? { - ...groupsCoordinates, - ...focusedGroups.reduce( - (coords, groupId) => ({ - ...coords, - [groupId]: { - x: Number( - (groupsCoordinates[groupId].x + delta.x).toFixed(2) - ), - y: Number( - (groupsCoordinates[groupId].y + delta.y).toFixed(2) - ), - }, - }), - groupsCoordinates - ), - } - : undefined, - })), - setFocusedGroups: (groupIds) => set({ focusedGroups: groupIds }), - setGroupsCoordinates: (groups) => - set({ - groupsCoordinates: groups - ? groups.reduce( - (coords, group) => ({ + subscribeWithSelector((set, get) => ({ + focusedGroups: [], + groupsCoordinates: undefined, + groupsInClipboard: undefined, + isDraggingGraph: false, + getGroupsCoordinates: () => get().groupsCoordinates, + focusGroup: (groupId, isShiftKeyPressed) => + set((state) => ({ + focusedGroups: isShiftKeyPressed + ? state.focusedGroups.includes(groupId) + ? state.focusedGroups.filter((id) => id !== groupId) + : [...state.focusedGroups, groupId] + : [groupId], + })), + blurGroups: () => set({ focusedGroups: [] }), + moveFocusedGroups: (delta) => + set(({ focusedGroups, groupsCoordinates }) => ({ + groupsCoordinates: groupsCoordinates + ? { + ...groupsCoordinates, + ...focusedGroups.reduce( + (coords, groupId) => ({ ...coords, - [group.id]: { - x: group.graphCoordinates.x, - y: group.graphCoordinates.y, + [groupId]: { + x: Number( + (groupsCoordinates[groupId].x + delta.x).toFixed(2) + ), + y: Number( + (groupsCoordinates[groupId].y + delta.y).toFixed(2) + ), }, }), - {} - ) - : undefined, - }), - updateGroupCoordinates: (groupId, newCoord) => { - set((state) => ({ - groupsCoordinates: { - ...state.groupsCoordinates, - [groupId]: newCoord, - }, - })) - }, - copyGroups: (groups, edges) => - set({ - groupsInClipboard: { - groups, - edges, - }, - }), - setIsDraggingGraph: (isDragging) => set({ isDraggingGraph: isDragging }), - }), - { - name: 'store', - partialize: (state) => ({ groupsInClipboard: state.groupsInClipboard }), - } - ) + groupsCoordinates + ), + } + : undefined, + })), + setFocusedGroups: (groupIds) => set({ focusedGroups: groupIds }), + setGroupsCoordinates: (groups) => + set({ + groupsCoordinates: groups + ? groups.reduce( + (coords, group) => ({ + ...coords, + [group.id]: { + x: group.graphCoordinates.x, + y: group.graphCoordinates.y, + }, + }), + {} + ) + : undefined, + }), + updateGroupCoordinates: (groupId, newCoord) => { + set((state) => ({ + groupsCoordinates: { + ...state.groupsCoordinates, + [groupId]: newCoord, + }, + })) + }, + copyGroups: (groups, edges) => + set({ + groupsInClipboard: { + groups, + edges, + }, + }), + setIsDraggingGraph: (isDragging) => set({ isDraggingGraph: isDragging }), + })) ) + +if ('BroadcastChannel' in globalThis) { + share('groupsInClipboard', useGroupsStore) +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b26731f18..6a910bbd9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -242,6 +242,9 @@ importers: react-markdown: specifier: ^9.0.1 version: 9.0.1(@types/react@18.2.15)(react@18.2.0) + shared-zustand: + specifier: 2.0.0 + version: 2.0.0 sonner: specifier: 1.3.1 version: 1.3.1(react-dom@18.2.0)(react@18.2.0) @@ -20658,6 +20661,10 @@ packages: /setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + /shared-zustand@2.0.0: + resolution: {integrity: sha512-DKBWe2w62wZif79XcUXStBBQ47T4y3XEApueseZ1O3wEsMbamDK01ac0zQNVj4MOH9Z5jesM2oLuug/79LPM1A==} + dev: false + /sharp@0.33.2: resolution: {integrity: sha512-WlYOPyyPDiiM07j/UO+E720ju6gtNtHjEGg5vovUk1Lgxyjm2LFO+37Nt/UI3MMh2l6hxTWQWi7qk3cXJTutcQ==} engines: {libvips: '>=8.15.1', node: ^18.17.0 || ^20.3.0 || >=21.0.0}