goobs-frontend 0.8.11 → 0.8.12

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "goobs-frontend",
3
- "version": "0.8.11",
3
+ "version": "0.8.12",
4
4
  "type": "module",
5
5
  "description": "A comprehensive React-based UI library built on Material-UI, offering a wide range of customizable components including grids, typography, buttons, cards, forms, navigation, pricing tables, steppers, tooltips, accordions, and more. Designed for building responsive and consistent user interfaces with advanced features like form validation, theming, and code syntax highlighting.",
6
6
  "license": "MIT",
@@ -19,17 +19,16 @@
19
19
  "lint": "next lint"
20
20
  },
21
21
  "dependencies": {
22
- "@emotion/cache": "^11.13.5",
23
- "@emotion/react": "^11.13.5",
24
- "@emotion/styled": "^11.13.5",
25
- "@mui/icons-material": "^6.1.10",
26
- "@mui/material": "^6.1.10",
22
+ "@emotion/cache": "^11.14.0",
23
+ "@emotion/react": "^11.14.0",
24
+ "@emotion/styled": "^11.14.0",
25
+ "@mui/icons-material": "^6.2.0",
26
+ "@mui/material": "^6.2.0",
27
27
  "@types/lodash": "^4.17.13",
28
- "@types/react-datepicker": "^7.0.0",
29
28
  "highlight.js": "^11.10.0",
30
29
  "jotai": "^2.10.3",
31
30
  "lodash": "^4.17.21",
32
- "next": "15.0.4",
31
+ "next": "15.1.0",
33
32
  "otplib": "^12.0.1",
34
33
  "react-datepicker": "^7.5.0",
35
34
  "react-qr-code": "^2.0.15",
@@ -39,14 +38,14 @@
39
38
  "slate-react": "^0.112.0"
40
39
  },
41
40
  "devDependencies": {
42
- "@next/eslint-plugin-next": "^15.0.4",
43
- "@types/node": "^22.10.1",
41
+ "@next/eslint-plugin-next": "^15.1.0",
42
+ "@types/node": "^22.10.2",
44
43
  "@types/react": "19.0.1",
45
44
  "@types/react-dom": "^19.0.1",
46
- "@typescript-eslint/eslint-plugin": "^8.17.0",
47
- "@typescript-eslint/parser": "^8.17.0",
45
+ "@typescript-eslint/eslint-plugin": "^8.18.0",
46
+ "@typescript-eslint/parser": "^8.18.0",
48
47
  "eslint": "^9.16.0",
49
- "eslint-config-next": "^15.0.4",
48
+ "eslint-config-next": "^15.1.0",
50
49
  "eslint-config-prettier": "^9.1.0",
51
50
  "eslint-plugin-prettier": "^5.2.1",
52
51
  "prettier": "^3.4.2",
@@ -1,6 +1,6 @@
1
1
  'use client'
2
2
 
3
- import React, { JSX } from 'react'
3
+ import React from 'react'
4
4
  import { styled } from '@mui/material/styles'
5
5
  import MuiAccordion, { AccordionProps } from '@mui/material/Accordion'
6
6
  import MuiAccordionSummary, {
@@ -12,16 +12,16 @@ import MuiAccordionDetails, {
12
12
  import { ExpandMore } from '@mui/icons-material'
13
13
  import { black } from '../../styles/palette'
14
14
 
15
- type CustomAccordionProps = Omit<AccordionProps, 'children'> & {
16
- children: NonNullable<React.ReactNode>
15
+ type CustomAccordionProps = AccordionProps & {
16
+ children: React.ReactNode
17
17
  }
18
18
 
19
- type CustomAccordionSummaryProps = Omit<AccordionSummaryProps, 'children'> & {
20
- children: NonNullable<React.ReactNode>
19
+ type CustomAccordionSummaryProps = AccordionSummaryProps & {
20
+ children: React.ReactNode
21
21
  }
22
22
 
23
- type CustomAccordionDetailsProps = Omit<AccordionDetailsProps, 'children'> & {
24
- children: NonNullable<React.ReactNode>
23
+ type CustomAccordionDetailsProps = AccordionDetailsProps & {
24
+ children: React.ReactNode
25
25
  }
26
26
 
27
27
  const StyledAccordion = styled(MuiAccordion)({
@@ -42,7 +42,7 @@ const StyledAccordionDetails = styled(MuiAccordionDetails)(({ theme }) => ({
42
42
  padding: theme.spacing(2),
43
43
  }))
44
44
 
45
- function Accordion({ children, ...props }: CustomAccordionProps): JSX.Element {
45
+ function Accordion({ children, ...props }: CustomAccordionProps) {
46
46
  return (
47
47
  <StyledAccordion disableGutters {...props}>
48
48
  {children}
@@ -50,10 +50,7 @@ function Accordion({ children, ...props }: CustomAccordionProps): JSX.Element {
50
50
  )
51
51
  }
52
52
 
53
- function AccordionSummary({
54
- children,
55
- ...props
56
- }: CustomAccordionSummaryProps): JSX.Element {
53
+ function AccordionSummary({ children, ...props }: CustomAccordionSummaryProps) {
57
54
  return (
58
55
  <StyledAccordionSummary
59
56
  expandIcon={<ExpandMore sx={{ color: black.main }} />}
@@ -64,10 +61,7 @@ function AccordionSummary({
64
61
  )
65
62
  }
66
63
 
67
- function AccordionDetails({
68
- children,
69
- ...props
70
- }: CustomAccordionDetailsProps): JSX.Element {
64
+ function AccordionDetails({ children, ...props }: CustomAccordionDetailsProps) {
71
65
  return <StyledAccordionDetails {...props}>{children}</StyledAccordionDetails>
72
66
  }
73
67
 
@@ -1,3 +1,5 @@
1
+ // src\components\ComplexTextEditor\SimpleEditor.tsx
2
+
1
3
  import React from 'react'
2
4
  import { Box, TextField } from '@mui/material'
3
5
 
@@ -7,7 +7,7 @@ import { handleBoldClick, handleItalicClick } from '../utils/useMarkdownEditor'
7
7
  import { IconButton, IconButtonProps } from '@mui/material'
8
8
  import { InlineFormat, BlockFormat, AlignmentFormat } from '../types'
9
9
 
10
- interface ToolbarButtonProps extends IconButtonProps {
10
+ export interface ToolbarButtonProps extends IconButtonProps {
11
11
  format?: InlineFormat | BlockFormat | AlignmentFormat
12
12
  children: React.ReactNode
13
13
  editor?: BaseEditor & ReactEditor & HistoryEditor
@@ -6,6 +6,7 @@ import {
6
6
  SelectChangeEvent,
7
7
  Stack,
8
8
  Typography,
9
+ MenuItem,
9
10
  } from '@mui/material'
10
11
  import {
11
12
  Link,
@@ -22,19 +23,15 @@ import {
22
23
  FormatListNumbered,
23
24
  FormatListBulleted,
24
25
  } from '@mui/icons-material'
25
- import {
26
- AlignmentButton,
27
- AlignmentMenuItem,
28
- TextType,
29
- TextTypeMenuItem,
30
- } from '../Rich/index'
31
26
  import { BaseEditor } from 'slate'
32
27
  import { ReactEditor } from 'slate-react'
33
28
  import { HistoryEditor } from 'slate-history'
34
- import { AlignmentFormat } from '@/components/ComplexTextEditor/types'
29
+ import { AlignmentFormat } from '../../types'
35
30
 
36
31
  type CustomEditor = BaseEditor & ReactEditor & HistoryEditor
37
32
 
33
+ export type TextType = 'p' | 'h1' | 'h2' | 'h3'
34
+
38
35
  interface ToolbarMarkdownProps {
39
36
  editor?: CustomEditor
40
37
  handleBoldClick?: () => void
@@ -67,20 +64,8 @@ const ToolbarMarkdown: React.FC<ToolbarMarkdownProps> = ({
67
64
  }
68
65
 
69
66
  return (
70
- <Box
71
- sx={{
72
- display: 'flex',
73
- flexDirection: 'row',
74
- alignItems: 'center',
75
- justifyContent: 'center',
76
- }}
77
- >
78
- <Stack
79
- direction="row"
80
- alignItems="center"
81
- justifyContent="center"
82
- spacing={1}
83
- >
67
+ <Box>
68
+ <Stack direction="row" spacing={1}>
84
69
  {/* undo / redo */}
85
70
  <Box>
86
71
  <ToolbarButton buttonAction="undo" editor={editor}>
@@ -93,12 +78,6 @@ const ToolbarMarkdown: React.FC<ToolbarMarkdownProps> = ({
93
78
  onClick={onSwitchMode}
94
79
  markdownMode={markdownMode}
95
80
  setMarkdown={setMarkdown}
96
- sx={{
97
- fontSize: '14px',
98
- borderRadius: '4px',
99
- color: 'black',
100
- border: '1px solid black',
101
- }}
102
81
  >
103
82
  {switchModeLabel}
104
83
  </ToolbarButton>
@@ -108,145 +87,44 @@ const ToolbarMarkdown: React.FC<ToolbarMarkdownProps> = ({
108
87
  value={textType}
109
88
  onChange={handleTextTypeChange}
110
89
  variant="outlined"
111
- sx={{
112
- p: '8px',
113
- width: '150px',
114
- ':hover': {
115
- backgroundColor: 'rgba(0, 0, 0, 0.04)',
116
- },
117
- ':active': {
118
- backgroundColor: 'rgba(0, 0, 0, 0.04)',
119
- },
120
- '& .MuiSelect-select': { padding: 0 },
121
- height: '34px',
122
- '.MuiOutlinedInput-notchedOutline': { border: '1px solid black' },
123
- '&.Mui-focused .MuiOutlinedInput-notchedOutline': {
124
- border: '1px solid black',
125
- },
126
- }}
127
- MenuProps={{
128
- PaperProps: {
129
- style: {
130
- boxSizing: 'border-box',
131
- width: '150px',
132
- border: '1px solid black',
133
- minWidth: 0,
134
- },
135
- },
136
- }}
137
- renderValue={value => {
138
- if (value === 'p') {
139
- return (
140
- <Box display="flex">
141
- <Typography fontSize="14px">Paragraph Text</Typography>
142
- </Box>
143
- )
144
- } else if (value === 'h1') {
145
- return (
146
- <Box display="flex">
147
- <Typography fontSize="14px">Heading 1</Typography>
148
- </Box>
149
- )
150
- } else if (value === 'h2') {
151
- return (
152
- <Box display="flex">
153
- <Typography fontSize="14px">Heading 2</Typography>
154
- </Box>
155
- )
156
- } else if (value === 'h3') {
157
- return (
158
- <Box display="flex">
159
- <Typography fontSize="14px">Heading 3</Typography>
160
- </Box>
161
- )
162
- } else return <></>
163
- }}
164
90
  >
165
- <TextTypeMenuItem value={'p'}>
166
- <Typography fontSize="14px">Paragraph Text</Typography>
167
- </TextTypeMenuItem>
168
- <TextTypeMenuItem value={'h1'}>
169
- <Typography fontSize="24px">Heading 1</Typography>
170
- </TextTypeMenuItem>
171
- <TextTypeMenuItem value={'h2'}>
172
- <Typography fontSize="20px">Heading 2</Typography>
173
- </TextTypeMenuItem>
174
- <TextTypeMenuItem value={'h3'}>
175
- <Typography fontSize="16px">Heading 3</Typography>
176
- </TextTypeMenuItem>
91
+ <MenuItem value={'p'}>
92
+ <Typography>Paragraph Text</Typography>
93
+ </MenuItem>
94
+ <MenuItem value={'h1'}>
95
+ <Typography>Heading 1</Typography>
96
+ </MenuItem>
97
+ <MenuItem value={'h2'}>
98
+ <Typography>Heading 2</Typography>
99
+ </MenuItem>
100
+ <MenuItem value={'h3'}>
101
+ <Typography>Heading 3</Typography>
102
+ </MenuItem>
177
103
  </Select>
178
104
  {/* alignment dropdown */}
179
105
  <Select
180
106
  value={alignValue}
181
107
  onChange={handleAlignChange}
182
108
  variant="outlined"
183
- sx={{
184
- p: '8px',
185
- ':hover': {
186
- backgroundColor: 'rgba(0, 0, 0, 0.04)',
187
- },
188
- ':active': {
189
- backgroundColor: 'rgba(0, 0, 0, 0.04)',
190
- },
191
- '& .MuiSelect-select': { padding: 0 },
192
- '.MuiOutlinedInput-notchedOutline': { border: 0 },
193
- '&.Mui-focused .MuiOutlinedInput-notchedOutline': {
194
- border: 'none !important',
195
- },
196
- }}
197
- MenuProps={{
198
- PaperProps: {
199
- style: {
200
- minWidth: 0,
201
- },
202
- },
203
- }}
204
- renderValue={value => {
205
- if (value === 'left') {
206
- return (
207
- <Box display="flex">
208
- <FormatAlignLeft fontSize="small" />
209
- </Box>
210
- )
211
- } else if (value === 'center') {
212
- return (
213
- <Box display="flex">
214
- <FormatAlignCenter fontSize="small" />
215
- </Box>
216
- )
217
- } else if (value === 'right') {
218
- return (
219
- <Box display="flex">
220
- <FormatAlignRight fontSize="small" />
221
- </Box>
222
- )
223
- } else return <></>
224
- }}
225
109
  >
226
- <AlignmentMenuItem value={'left'}>
227
- <AlignmentButton format="left" activeBackgroundColor="#E7F5FF">
110
+ <MenuItem value={'left'}>
111
+ <ToolbarButton format="left">
228
112
  <FormatAlignLeft fontSize="small" />
229
- <Typography fontSize={'14px'} mx={1}>
230
- left
231
- </Typography>
232
- </AlignmentButton>
233
- </AlignmentMenuItem>
234
- <AlignmentMenuItem value={'center'}>
235
- <AlignmentButton format="center" activeBackgroundColor="#E7F5FF">
113
+ <Typography>left</Typography>
114
+ </ToolbarButton>
115
+ </MenuItem>
116
+ <MenuItem value={'center'}>
117
+ <ToolbarButton format="center">
236
118
  <FormatAlignCenter fontSize="small" />
237
- <Typography fontSize={'14px'} mx={1}>
238
- center
239
- </Typography>
240
- </AlignmentButton>
241
- </AlignmentMenuItem>
242
- <AlignmentMenuItem value={'right'}>
243
- <AlignmentButton format="right" activeBackgroundColor="#E7F5FF">
119
+ <Typography>center</Typography>
120
+ </ToolbarButton>
121
+ </MenuItem>
122
+ <MenuItem value={'right'}>
123
+ <ToolbarButton format="right">
244
124
  <FormatAlignRight fontSize="small" />
245
- <Typography fontSize={'14px'} mx={1}>
246
- right
247
- </Typography>
248
- </AlignmentButton>
249
- </AlignmentMenuItem>
125
+ <Typography>right</Typography>
126
+ </ToolbarButton>
127
+ </MenuItem>
250
128
  </Select>
251
129
  {/* buttons */}
252
130
  <Box>
@@ -27,7 +27,7 @@ import {
27
27
  import { BaseEditor } from 'slate'
28
28
  import { ReactEditor } from 'slate-react'
29
29
  import { HistoryEditor } from 'slate-history'
30
- import { AlignmentFormat } from '@/components/ComplexTextEditor/types'
30
+ import { AlignmentFormat } from '../../types'
31
31
 
32
32
  type CustomEditor = BaseEditor & ReactEditor & HistoryEditor
33
33
 
@@ -56,19 +56,6 @@ export const TextTypeMenuItem = styled(MenuItem)({
56
56
  },
57
57
  })
58
58
 
59
- export const AlignmentButton = styled(ToolbarButton)({
60
- width: '100%',
61
- borderRadius: 0,
62
- justifyContent: 'flex-start',
63
- '& .MuiTouchRipple-root .MuiTouchRipple-child': {
64
- borderRadius: 0,
65
- backgroundColor: '#E7F5FF',
66
- },
67
- ':hover': {
68
- backgroundColor: '#E7F5FF',
69
- },
70
- })
71
-
72
59
  const Toolbar: React.FC<ToolbarProps> = ({
73
60
  editor,
74
61
  markdownMode,
@@ -234,40 +221,61 @@ const Toolbar: React.FC<ToolbarProps> = ({
234
221
  }}
235
222
  >
236
223
  <AlignmentMenuItem value={'left'}>
237
- <AlignmentButton
224
+ <ToolbarButton
238
225
  format="left"
239
226
  editor={editor}
240
- activeBackgroundColor="#E7F5FF"
227
+ sx={{
228
+ width: '100%',
229
+ borderRadius: 0,
230
+ justifyContent: 'flex-start',
231
+ ':hover': {
232
+ backgroundColor: '#E7F5FF',
233
+ },
234
+ }}
241
235
  >
242
236
  <FormatAlignLeft fontSize="small" />
243
237
  <Typography fontSize={'14px'} mx={1}>
244
238
  left
245
239
  </Typography>
246
- </AlignmentButton>
240
+ </ToolbarButton>
247
241
  </AlignmentMenuItem>
248
242
  <AlignmentMenuItem value={'center'}>
249
- <AlignmentButton
243
+ <ToolbarButton
250
244
  format="center"
251
245
  editor={editor}
252
- activeBackgroundColor="#E7F5FF"
246
+ sx={{
247
+ width: '100%',
248
+ borderRadius: 0,
249
+ justifyContent: 'flex-start',
250
+ ':hover': {
251
+ backgroundColor: '#E7F5FF',
252
+ },
253
+ }}
253
254
  >
254
255
  <FormatAlignCenter fontSize="small" />
255
256
  <Typography fontSize={'14px'} mx={1}>
256
257
  center
257
258
  </Typography>
258
- </AlignmentButton>
259
+ </ToolbarButton>
259
260
  </AlignmentMenuItem>
260
261
  <AlignmentMenuItem value={'right'}>
261
- <AlignmentButton
262
+ <ToolbarButton
262
263
  format="right"
263
264
  editor={editor}
264
- activeBackgroundColor="#E7F5FF"
265
+ sx={{
266
+ width: '100%',
267
+ borderRadius: 0,
268
+ justifyContent: 'flex-start',
269
+ ':hover': {
270
+ backgroundColor: '#E7F5FF',
271
+ },
272
+ }}
265
273
  >
266
274
  <FormatAlignRight fontSize="small" />
267
275
  <Typography fontSize={'14px'} mx={1}>
268
276
  right
269
277
  </Typography>
270
- </AlignmentButton>
278
+ </ToolbarButton>
271
279
  </AlignmentMenuItem>
272
280
  </Select>
273
281
  {/* buttons */}
@@ -1,17 +1,15 @@
1
- import React, { useState } from 'react'
1
+ // src\components\ComplexTextEditor\index.tsx
2
+
3
+ import React, { useState, useEffect } from 'react'
2
4
  import { Box } from '@mui/material'
3
- import { Descendant } from 'slate'
4
- import RichEditor from './RichEditor'
5
- import MarkdownEditor from './MarkdownEditor'
6
5
  import SimpleEditor from './SimpleEditor'
7
6
  import ComplexToolbar, { EditorMode } from './Toolbars/Complex'
8
- import { RichTextEditorTypes } from './types'
9
7
 
10
8
  export type EditorType = 'simple' | 'markdown' | 'rich' | 'complex'
11
9
 
12
10
  export interface ComplexTextEditorProps {
13
- value: Descendant[]
14
- onChange?: () => void
11
+ value: string
12
+ onChange?: (val: string) => void
15
13
  label?: string
16
14
  minRows?: number
17
15
  accordion?: boolean
@@ -23,55 +21,48 @@ const ComplexTextEditor: React.FC<ComplexTextEditorProps> = ({
23
21
  onChange,
24
22
  label,
25
23
  minRows = 5,
26
- accordion = false,
27
24
  editorType = 'complex',
28
25
  }) => {
26
+ // If editorType is complex, start in simple mode
29
27
  const [mode, setMode] = useState<EditorMode>(
30
28
  editorType === 'complex' ? 'simple' : editorType
31
29
  )
32
- const [markdownMode, setMarkdownMode] = useState(false)
33
- const [markdown, setMarkdown] = useState('')
34
- const [simpleText, setSimpleText] = useState('')
30
+ const [simpleText, setSimpleText] = useState(value)
31
+
32
+ useEffect(() => {
33
+ // If the input value changes from outside, update simpleText
34
+ setSimpleText(value)
35
+ }, [value])
35
36
 
36
- const setNewSlateValue = (value: RichTextEditorTypes['CustomElement'][]) => {
37
- // Handle conversion between markdown and rich text
38
- console.log('Converting markdown to rich text:', value)
37
+ const handleSimpleTextChange = (newVal: string) => {
38
+ setSimpleText(newVal)
39
+ if (onChange) {
40
+ onChange(newVal)
41
+ }
39
42
  }
40
43
 
41
44
  const renderEditor = () => {
42
- switch (mode) {
43
- case 'simple':
44
- return (
45
- <SimpleEditor
46
- value={simpleText}
47
- setValue={setSimpleText}
48
- minRows={minRows}
49
- label={label}
50
- />
51
- )
52
- case 'rich':
53
- return (
54
- <RichEditor
55
- value={value}
56
- onChange={onChange}
57
- label={label}
58
- minRows={minRows}
59
- accordion={accordion}
60
- />
61
- )
62
- case 'markdown':
63
- return (
64
- <MarkdownEditor
65
- markdown={markdown}
66
- setMarkdown={setMarkdown}
67
- markdownMode={markdownMode}
68
- setMarkdownMode={setMarkdownMode}
69
- setNewSlateValue={setNewSlateValue}
70
- />
71
- )
72
- default:
73
- return null
45
+ // For now, we only support 'simple' directly. You can expand to 'rich'/'markdown' if needed.
46
+ if (mode === 'simple') {
47
+ return (
48
+ <SimpleEditor
49
+ value={simpleText}
50
+ setValue={handleSimpleTextChange}
51
+ minRows={minRows}
52
+ label={label}
53
+ />
54
+ )
74
55
  }
56
+
57
+ // If you implement other modes (rich, markdown), handle them here.
58
+ return (
59
+ <SimpleEditor
60
+ value={simpleText}
61
+ setValue={handleSimpleTextChange}
62
+ minRows={minRows}
63
+ label={label}
64
+ />
65
+ )
75
66
  }
76
67
 
77
68
  return (
@@ -88,9 +79,9 @@ const ComplexTextEditor: React.FC<ComplexTextEditorProps> = ({
88
79
  <ComplexToolbar
89
80
  mode={mode}
90
81
  setMode={setMode}
91
- markdownMode={markdownMode}
92
- setMarkdownMode={setMarkdownMode}
93
- setMarkdown={setMarkdown}
82
+ markdownMode={false}
83
+ setMarkdownMode={() => {}}
84
+ setMarkdown={() => {}}
94
85
  />
95
86
  )}
96
87
 
@@ -1,6 +1,6 @@
1
1
  'use server'
2
2
 
3
- import { RichTextEditorTypes } from '@/components/ComplexTextEditor/types'
3
+ import { RichTextEditorTypes } from '../types'
4
4
  import React from 'react'
5
5
 
6
6
  // Simple regex patterns to identify bold and italic in markdown
@@ -15,7 +15,7 @@ import {
15
15
  InlineFormat,
16
16
  BlockFormat,
17
17
  AlignmentFormat,
18
- } from '@/components/ComplexTextEditor/types'
18
+ } from '../types'
19
19
 
20
20
  const RichTextEditorConfig: RichTextEditorTypes = {
21
21
  Block: {