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