Skip to content

Commit ce74aaa

Browse files
committed
feat: Update Tiptap component with new Confirming and Error states
- Add Confirming and Error story variations to Tiptap component for enhanced user interaction - Introduce new props for isCreating and isUpdating to Tiptap and TiptapToolbar interfaces - Update Tooltip component to accept additional className props for better styling flexibility - Bump package version to 1.0.213
1 parent c0c211f commit ce74aaa

File tree

6 files changed

+227
-14
lines changed

6 files changed

+227
-14
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@programmer_network/yail",
3-
"version": "1.0.212",
3+
"version": "1.0.213",
44
"description": "Programmer Network's official UI library for React",
55
"author": "Aleksandar Grbic - (https://programmer.network)",
66
"publishConfig": {

src/Components/Inputs/Tiptap/Components/Actions/index.tsx

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,31 @@ const TiptapActions: FC<{
2121
<div className='yl:flex yl:items-center'>
2222
{buttons.includes(TiptapActionsEnum.CANCEL) && (
2323
<Icon
24-
onClick={() => onAction(TiptapActionsEnum.CANCEL)}
24+
onClick={
25+
!isConfirming
26+
? () => onAction(TiptapActionsEnum.CANCEL)
27+
: undefined
28+
}
2529
iconName='IconCloseCircle'
26-
className='yl:w-10 yl:cursor-pointer yl:text-text/30 yl:hover:text-text'
30+
className={classNames("yl:w-10 yl:text-text/20", {
31+
"yl:text-text/30 yl:hover:text-text yl:cursor-pointer":
32+
!isConfirming
33+
})}
2734
/>
2835
)}
2936
{buttons.includes(TiptapActionsEnum.CONFIRM) && (
3037
<Icon
31-
onClick={() => onAction(TiptapActionsEnum.CONFIRM)}
38+
onClick={
39+
!isConfirming
40+
? () => onAction(TiptapActionsEnum.CONFIRM)
41+
: undefined
42+
}
3243
iconName={!isConfirming ? "IconCheck" : "IconSpinner"}
33-
className={classNames(
34-
"yl:w-10 yl:cursor-pointer yl:fill-success",
35-
{
36-
"yl:text-success": !isEditorEmpty
37-
}
38-
)}
44+
className={classNames("yl:w-10", {
45+
" yl:cursor-pointer": !isConfirming,
46+
"yl:text-success": !isEditorEmpty && !isConfirming,
47+
"yl:fill-primary yl:w-7 yl:h-7": isConfirming
48+
})}
3949
/>
4050
)}
4151
</div>

src/Components/Inputs/Tiptap/tiptap.stories.tsx

Lines changed: 188 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Editor } from "@tiptap/core";
2-
import { RefObject, useRef, useState } from "react";
2+
import { RefObject, useEffect, useRef, useState } from "react";
33

44
import Tiptap from ".";
55
import TiptapToHTML from "./TiptapToHTML";
@@ -88,3 +88,190 @@ export const Default = () => {
8888
</div>
8989
);
9090
};
91+
92+
export const Confirming = () => {
93+
const suggestions = {
94+
trigger: "#",
95+
items: () =>
96+
Promise.resolve([
97+
{
98+
label: "Bar Label",
99+
value: "bar"
100+
},
101+
{
102+
label: "Baz Label",
103+
value: "baz"
104+
}
105+
])
106+
};
107+
108+
const toolbarItems = [
109+
TIPTAP_TOOLBAR_ITEMS.BOLD,
110+
TIPTAP_TOOLBAR_ITEMS.HEADING_2,
111+
TIPTAP_TOOLBAR_ITEMS.HEADING_3,
112+
TIPTAP_TOOLBAR_ITEMS.ITALIC,
113+
TIPTAP_TOOLBAR_ITEMS.LINK,
114+
TIPTAP_TOOLBAR_ITEMS.IMAGE,
115+
TIPTAP_TOOLBAR_ITEMS.YOUTUBE,
116+
TIPTAP_TOOLBAR_ITEMS.LIST_ITEM,
117+
TIPTAP_TOOLBAR_ITEMS.UNORDERED_LIST,
118+
TIPTAP_TOOLBAR_ITEMS.ORDERED_LIST,
119+
TIPTAP_TOOLBAR_ITEMS.CODE,
120+
TIPTAP_TOOLBAR_ITEMS.BLOCK_QUOTE,
121+
TIPTAP_TOOLBAR_ITEMS.STRIKE_THROUGH,
122+
TIPTAP_TOOLBAR_ITEMS.CODE_BLOCK
123+
];
124+
125+
const converter = new TiptapToHTML(toolbarItems, suggestions);
126+
127+
const [editorState, setEditorState] = useState<string>("");
128+
129+
const tiptapRef = useRef<TiptapRef>(null);
130+
131+
const onEditorStateChange = ({ editor }: { editor: Editor }) => {
132+
console.log(editor.getJSON());
133+
setEditorState(
134+
converter.generateSanitizedHTML(JSON.stringify(editor.getJSON()))
135+
);
136+
};
137+
138+
useEffect(() => {
139+
// @ts-ignore
140+
tiptapRef.current?.setContent({
141+
type: "doc",
142+
content: [
143+
{
144+
type: "paragraph",
145+
content: [
146+
{
147+
type: "text",
148+
text: "Hello, world!"
149+
}
150+
]
151+
}
152+
]
153+
});
154+
}, []);
155+
156+
return (
157+
<div className='yl:w-full yl:md:w-[768px]'>
158+
<Tiptap
159+
ref={tiptapRef as RefObject<TiptapRef>}
160+
label='Content'
161+
suggestions={suggestions}
162+
toolbarItems={toolbarItems}
163+
actions={{
164+
buttons: [TiptapActionsEnum.CANCEL, TiptapActionsEnum.CONFIRM],
165+
onAction: actionType => alert(actionType),
166+
isConfirming: true
167+
}}
168+
onSetImage={() => {
169+
return new Promise<void>(resolve => {
170+
resolve();
171+
});
172+
}}
173+
onTransaction={({ editor }) => {
174+
onEditorStateChange({ editor });
175+
}}
176+
required={true}
177+
/>
178+
179+
<div
180+
className='yl:mt-8 yl:break-words text-indigo-500'
181+
dangerouslySetInnerHTML={{ __html: editorState }}
182+
></div>
183+
</div>
184+
);
185+
};
186+
187+
export const Error = () => {
188+
const suggestions = {
189+
trigger: "#",
190+
items: () =>
191+
Promise.resolve([
192+
{
193+
label: "Bar Label",
194+
value: "bar"
195+
},
196+
{
197+
label: "Baz Label",
198+
value: "baz"
199+
}
200+
])
201+
};
202+
203+
const toolbarItems = [
204+
TIPTAP_TOOLBAR_ITEMS.BOLD,
205+
TIPTAP_TOOLBAR_ITEMS.HEADING_2,
206+
TIPTAP_TOOLBAR_ITEMS.HEADING_3,
207+
TIPTAP_TOOLBAR_ITEMS.ITALIC,
208+
TIPTAP_TOOLBAR_ITEMS.LINK,
209+
TIPTAP_TOOLBAR_ITEMS.IMAGE,
210+
TIPTAP_TOOLBAR_ITEMS.YOUTUBE,
211+
TIPTAP_TOOLBAR_ITEMS.LIST_ITEM,
212+
TIPTAP_TOOLBAR_ITEMS.UNORDERED_LIST,
213+
TIPTAP_TOOLBAR_ITEMS.ORDERED_LIST,
214+
TIPTAP_TOOLBAR_ITEMS.CODE,
215+
TIPTAP_TOOLBAR_ITEMS.BLOCK_QUOTE,
216+
TIPTAP_TOOLBAR_ITEMS.STRIKE_THROUGH,
217+
TIPTAP_TOOLBAR_ITEMS.CODE_BLOCK
218+
];
219+
220+
const tiptapRef = useRef<TiptapRef>(null);
221+
222+
useEffect(() => {
223+
// @ts-ignore
224+
tiptapRef.current?.setContent({
225+
type: "doc",
226+
content: [
227+
{
228+
type: "paragraph",
229+
content: [
230+
{
231+
type: "text",
232+
text: "Hello, world!"
233+
}
234+
]
235+
}
236+
]
237+
});
238+
}, []);
239+
240+
return (
241+
<div className='yl:w-full yl:md:w-[768px]'>
242+
<Tiptap
243+
ref={tiptapRef as RefObject<TiptapRef>}
244+
label='Content'
245+
suggestions={suggestions}
246+
toolbarItems={toolbarItems}
247+
error='This is an error'
248+
actions={{
249+
buttons: [TiptapActionsEnum.CANCEL, TiptapActionsEnum.CONFIRM],
250+
onAction: actionType => {
251+
if (actionType === TiptapActionsEnum.CONFIRM) {
252+
// @ts-ignore
253+
tiptapRef.current?.setContent({
254+
type: "doc",
255+
content: [
256+
{
257+
type: "paragraph",
258+
content: [
259+
{
260+
type: "text",
261+
text: "Content has been set!"
262+
}
263+
]
264+
}
265+
]
266+
});
267+
} else {
268+
tiptapRef.current?.clearContent();
269+
}
270+
},
271+
isConfirming: false
272+
}}
273+
required={true}
274+
/>
275+
</div>
276+
);
277+
};

src/Components/Inputs/Tiptap/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ export interface TiptapProps {
3333
label?: string;
3434
hint?: string;
3535
required?: boolean;
36+
isCreating?: boolean;
37+
isUpdating?: boolean;
3638
}
3739

3840
export interface TiptapToolbarProps {
@@ -45,6 +47,8 @@ export interface TiptapToolbarProps {
4547
};
4648
editor: Editor;
4749
toolbarItems?: TiptapControls;
50+
isCreating?: boolean;
51+
isUpdating?: boolean;
4852
}
4953

5054
export interface TiptapRef {

src/Components/Tooltip/index.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import classNames from "classnames";
12
import { FC } from "react";
23
import { Tooltip as ReactTooltip } from "react-tooltip";
34
import "react-tooltip/dist/react-tooltip.css";
@@ -9,15 +10,21 @@ const Tooltip: FC<ITooltipProps> = ({
910
children,
1011
id,
1112
place = "top",
12-
delayShow = 0
13+
delayShow = 0,
14+
childrenClassName,
15+
className
1316
}) => {
1417
if (!text) {
1518
return children;
1619
}
1720

1821
return (
1922
<div>
20-
<div data-tooltip-id={id} data-tooltip-delay-show={delayShow}>
23+
<div
24+
data-tooltip-id={id}
25+
data-tooltip-delay-show={delayShow}
26+
className={classNames(childrenClassName)}
27+
>
2128
{children}
2229
</div>
2330
<ReactTooltip
@@ -26,7 +33,10 @@ const Tooltip: FC<ITooltipProps> = ({
2633
content={text as string}
2734
noArrow
2835
opacity={1}
29-
className='yl:border-2 yl:border-primary yl:bg-background yl:text-text yl:z-50'
36+
className={classNames(
37+
"yl:border-2 yl:border-primary yl:bg-background yl:text-text yl:z-50",
38+
className
39+
)}
3040
/>
3141
</div>
3242
);

src/Components/Tooltip/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ export interface ITooltipProps {
66
children: React.ReactNode;
77
place?: "top" | "bottom" | "left" | "right";
88
delayShow?: number;
9+
childrenClassName?: string;
10+
className?: string;
911
}

0 commit comments

Comments
 (0)