Skip to content

Commit

Permalink
Migrate old jotai stores to new API
Browse files Browse the repository at this point in the history
  • Loading branch information
12joan committed Nov 27, 2023
1 parent f018f8f commit 3a6206c
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 141 deletions.
29 changes: 14 additions & 15 deletions packages/comments/src/stores/comment/CommentProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import React, { ReactNode } from 'react';
import {
createAtomStore,
getJotaiProviderInitialValues,
getNodeString,
JotaiProvider,
Scope,
Value,
} from '@udecode/plate-common';

Expand All @@ -14,24 +11,26 @@ import {
useCommentsSelectors,
} from '../comments/CommentsProvider';

export const SCOPE_COMMENT = Symbol('comment');
export const SCOPE_ACTIVE_COMMENT = Symbol('activeComment');
export const SCOPE_COMMENT = 'comment';
export const SCOPE_ACTIVE_COMMENT = 'activeComment';

export interface CommentStoreState {
id: string;
isMenuOpen: boolean;
editingValue: Value | null;
}

export const { commentStore, useCommentStore } = createAtomStore(
const {
useCommentStore,
CommentProvider: PrimitiveCommentProvider
} = createAtomStore(
{
id: '',
isMenuOpen: false,
editingValue: null,
} as CommentStoreState,
{
name: 'comment',
scope: SCOPE_COMMENT,
}
);

Expand All @@ -43,18 +42,18 @@ export function CommentProvider({
children,
scope,
...props
}: Partial<CommentStoreState> & { children: ReactNode; scope?: Scope }) {
}: Partial<CommentStoreState> & { children: ReactNode; scope?: string }) {
return (
<JotaiProvider
initialValues={getJotaiProviderInitialValues(commentStore, props)}
<PrimitiveCommentProvider
scope={scope ?? SCOPE_COMMENT}
{...props}
>
{children}
</JotaiProvider>
</PrimitiveCommentProvider>
);
}

export const useCommentUser = (scope?: Scope): CommentUser | null => {
export const useCommentUser = (scope?: string): CommentUser | null => {
const commentId = useCommentSelectors().id(scope);
const users = useCommentsSelectors().users();
const comment = useCommentById(commentId);
Expand All @@ -63,7 +62,7 @@ export const useCommentUser = (scope?: Scope): CommentUser | null => {
return users[comment.userId];
};

export const useCommentReplies = (scope?: Scope) => {
export const useCommentReplies = (scope?: string) => {
const commentId = useCommentSelectors().id(scope);
const comments = useCommentsSelectors().comments();

Expand All @@ -81,13 +80,13 @@ export const useCommentReplies = (scope?: Scope) => {
return replies;
};

export const useComment = (scope?: Scope) => {
export const useComment = (scope?: string) => {
const commentId = useCommentSelectors().id(scope);

return useCommentById(commentId);
};

export const useCommentText = (scope?: Scope) => {
export const useCommentText = (scope?: string) => {
const comment = useComment(scope);
if (!comment) return null;

Expand Down
109 changes: 33 additions & 76 deletions packages/comments/src/stores/comments/CommentsProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import React, { createContext, ReactNode, useContext, useMemo } from 'react';
import React, { ReactNode } from 'react';
import {
createAtomStore,
getJotaiProviderInitialValues,
getNodeString,
JotaiProvider,
nanoid,
Value,
WithPartial,
} from '@udecode/plate-common';

import { CommentUser, TComment } from '../../types';

export interface CommentsContext {
export const SCOPE_COMMENTS = 'comments';

export interface CommentsStoreState {
/**
* Id of the current user.
*/
Expand All @@ -22,16 +22,6 @@ export interface CommentsContext {
*/
users: Record<string, CommentUser>;

onCommentAdd: ((value: WithPartial<TComment, 'userId'>) => void) | null;
onCommentUpdate:
| ((value: Pick<TComment, 'id'> & Partial<Omit<TComment, 'id'>>) => void)
| null;
onCommentDelete: ((id: string) => void) | null;
}

export const SCOPE_COMMENTS = Symbol('comments');

export interface CommentsStoreState {
/**
* Comments data.
*/
Expand All @@ -47,10 +37,26 @@ export interface CommentsStoreState {
newValue: Value;

focusTextarea: boolean;

onCommentAdd: ((value: WithPartial<TComment, 'userId'>) => void) | null;
onCommentUpdate:
| ((value: Pick<TComment, 'id'> & Partial<Omit<TComment, 'id'>>) => void)
| null;
onCommentDelete: ((id: string) => void) | null;
}

export const { commentsStore, useCommentsStore } = createAtomStore(
const { commentsStore, useCommentsStore, CommentsProvider: PrimitiveCommentsProvider } = createAtomStore(
{
/**
* Id of the current user.
*/
myUserId: null,

/**
* Users data.
*/
users: {},

/**
* Comments data.
*/
Expand All @@ -66,83 +72,34 @@ export const { commentsStore, useCommentsStore } = createAtomStore(
newValue: [{ type: 'p', children: [{ text: '' }] }],

focusTextarea: false,
} satisfies CommentsStoreState as CommentsStoreState,

onCommentAdd: null,
onCommentUpdate: null,
onCommentDelete: null,
} as CommentsStoreState,
{
name: 'comments',
scope: SCOPE_COMMENTS,
}
);

export const CommentsContext = createContext<CommentsContext>({
myUserId: null,
users: {},
onCommentAdd: null,
onCommentUpdate: null,
onCommentDelete: null,
});

export interface CommentsProviderProps extends Partial<CommentsContext> {
initialComments?: CommentsStoreState['comments'];
children: ReactNode;
}

export function CommentsProvider({
children,
initialComments,
myUserId = null,
users = {},
onCommentAdd = null,
onCommentUpdate = null,
onCommentDelete = null,
}: CommentsProviderProps) {
...props
}: Partial<CommentsStoreState> & { children: ReactNode }) {
return (
<JotaiProvider
initialValues={getJotaiProviderInitialValues(commentsStore, {
comments: initialComments,
})}
<PrimitiveCommentsProvider
scope={SCOPE_COMMENTS}
{...props}
>
<CommentsContext.Provider
value={{
myUserId,
users,
onCommentAdd,
onCommentUpdate,
onCommentDelete,
}}
>
{children}
</CommentsContext.Provider>
</JotaiProvider>
{children}
</PrimitiveCommentsProvider>
);
}

export const useCommentsStates = () => useCommentsStore().use;
export const useCommentsSelectors = () => useCommentsStore().get;
export const useCommentsActions = () => useCommentsStore().set;

export const useCommentsSelectors = () => {
const context = useContext(CommentsContext);

const contextGetters = useMemo(
() =>
Object.fromEntries(
Object.entries(context).map(([key, value]) => [key, () => value])
) as { [K in keyof CommentsContext]: () => CommentsContext[K] },
[context]
);

const storeGetters = useCommentsStore().get;

// Combine getters from context and store
return useMemo(
() => ({
...contextGetters,
...storeGetters,
}),
[contextGetters, storeGetters]
);
};

export const useCommentById = (id?: string | null): TComment | null => {
const comments = useCommentsSelectors().comments();
if (!id) return null;
Expand Down
45 changes: 6 additions & 39 deletions packages/resizable/src/components/ResizeHandle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,49 +5,16 @@ import React, {
useState,
} from 'react';
import {
atom,
createAtomStore,
createPrimitiveComponent,
JotaiProvider,
useAtom,
} from '@udecode/plate-common';

import { ResizeDirection, ResizeEvent } from '../types';
import { isTouchEvent } from '../utils';

export const resizeHandleAtoms = {
onResize: atom<{ fn: any } | null>(null),
};

export const ResizeHandleEffects = ({
onResize,
}: {
onResize?: ResizeHandleOptions['onResize'];
}) => {
const [, setHandleResize] = useAtom(resizeHandleAtoms.onResize);

useEffect(() => {
setHandleResize({ fn: onResize });
}, [onResize, setHandleResize]);

return null;
};

export const ResizeHandleProvider = ({
children,
onResize,
}: {
children: React.ReactNode;
onResize?: ResizeHandleOptions['onResize'];
}) => {
return (
<JotaiProvider
initialValues={[[resizeHandleAtoms.onResize, { fn: onResize }]]}
>
<ResizeHandleEffects onResize={onResize} />
{children}
</JotaiProvider>
);
};
export const { ResizeHandleProvider, useResizeHandleStore } = createAtomStore({
onResize: null as ResizeHandleOptions['onResize'] | null,
}, { name: 'resizeHandle' });

export type ResizeHandleOptions = {
direction?: ResizeDirection;
Expand All @@ -68,8 +35,8 @@ export const useResizeHandleState = ({
onHover,
onHoverEnd,
}: ResizeHandleOptions) => {
const [_onResize] = useAtom(resizeHandleAtoms.onResize);
if (!onResize) onResize = _onResize?.fn;
const _onResize = useResizeHandleStore().get.onResize();
if (!onResize) onResize = _onResize ?? undefined;

const [isResizing, setIsResizing] = useState(false);
const [initialPosition, setInitialPosition] = useState(0);
Expand Down
13 changes: 5 additions & 8 deletions packages/suggestion/src/store/SuggestionProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import React, { ReactNode } from 'react';
import {
createAtomStore,
getJotaiProviderInitialValues,
JotaiProvider,
nanoid,
WithPartial,
} from '@udecode/plate-common';

import { SuggestionUser, TSuggestion } from '../types';

export const SCOPE_SUGGESTION = Symbol('suggestion');
export const SCOPE_SUGGESTION = 'suggestion';

export interface SuggestionStoreState {
/**
Expand Down Expand Up @@ -40,7 +38,7 @@ export interface SuggestionStoreState {
onSuggestionDelete: ((id: string) => void) | null;
}

export const { suggestionStore, useSuggestionStore } = createAtomStore(
const { useSuggestionStore, SuggestionProvider: PrimitiveSuggestionProvider } = createAtomStore(
{
/**
* Id of the current user.
Expand Down Expand Up @@ -70,7 +68,6 @@ export const { suggestionStore, useSuggestionStore } = createAtomStore(
} as SuggestionStoreState,
{
name: 'suggestion',
scope: SCOPE_SUGGESTION,
}
);

Expand All @@ -79,12 +76,12 @@ export function SuggestionProvider({
...props
}: Partial<SuggestionStoreState> & { children: ReactNode }) {
return (
<JotaiProvider
initialValues={getJotaiProviderInitialValues(suggestionStore, props)}
<PrimitiveSuggestionProvider
scope={SCOPE_SUGGESTION}
{...props}
>
{children}
</JotaiProvider>
</PrimitiveSuggestionProvider>
);
}

Expand Down
4 changes: 1 addition & 3 deletions packages/table/src/stores/tableStore.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { useCallback } from 'react';
import { createAtomStore, TElement } from '@udecode/plate-common';

import { ELEMENT_TABLE } from '../createTablePlugin';

export type TableStoreSizeOverrides = Map<number, number>;

export const { tableStore, useTableStore } = createAtomStore(
Expand All @@ -14,7 +12,7 @@ export const { tableStore, useTableStore } = createAtomStore(
selectedCells: null as TElement[] | null,
selectedTable: null as TElement[] | null,
},
{ name: 'table' as const, scope: ELEMENT_TABLE }
{ name: 'table' as const }
);

const useOverrideSizeFactory = (
Expand Down

0 comments on commit 3a6206c

Please sign in to comment.