Skip to content

Commit

Permalink
Merge pull request #5 from tidbcloud/react-component
Browse files Browse the repository at this point in the history
feat: implement react component
  • Loading branch information
baurine authored Jun 13, 2024
2 parents 0a7c85c + f22b1ef commit 970b6e0
Show file tree
Hide file tree
Showing 11 changed files with 276 additions and 12 deletions.
4 changes: 2 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
},
"dependencies": {
"@tidbcloud/tisqleditor-extensions-basic-setup": "workspace:^",
"@tidbcloud/tisqleditor-extensions-sql-parser": "workspace:^",
"@tidbcloud/tisqleditor-extensions-cur-sql": "workspace:^",
"@tidbcloud/tisqleditor-extensions-lang-sql": "workspace:^"
"@tidbcloud/tisqleditor-extensions-lang-sql": "workspace:^",
"@tidbcloud/tisqleditor-extensions-sql-parser": "workspace:^"
}
}
23 changes: 23 additions & 0 deletions packages/core/src/editor-cache.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { SQLEditorInstance } from './editor-instance'

//-------------

export class EditorCache {
cache: Map<string, SQLEditorInstance> = new Map()

addEditor = (editorId: string, editor: SQLEditorInstance) => {
this.cache.set(editorId, editor)
}

getEditor = (editorId: string) => {
return this.cache.get(editorId)
}

deleteEditor = (editorId: string) => {
this.cache.delete(editorId)
}

clearEditors = () => {
this.cache.clear()
}
}
22 changes: 13 additions & 9 deletions packages/core/src/editor-instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,41 +20,43 @@ import {

export class SQLEditorInstance {
constructor(
public editor: EditorView,
public editorId: string,
public editorView: EditorView,
public themeCompartment: Compartment,
public sqlCompartment: Compartment,
public extraData: {}
) {}

changeTheme(theme: Extension) {
if (this.themeCompartment.get(this.editor.state) === theme) return
if (this.themeCompartment.get(this.editorView.state) === theme) return

this.editor.dispatch({
this.editorView.dispatch({
effects: this.themeCompartment.reconfigure(theme)
})
}

changeSQLConfig(sqlConfig: SQLConfig) {
this.editor.dispatch({
this.editorView.dispatch({
effects: this.sqlCompartment.reconfigure(langSql(sqlConfig))
})
}

getAllStatements() {
return getSqlStatements(this.editor.state)
return getSqlStatements(this.editorView.state)
}

getCurStatements() {
return getCurStatements(this.editor.state)
return getCurStatements(this.editorView.state)
}

getNearbyStatement() {
const { from } = this.getCurStatements()[0]
return getNearbyStatement(this.editor.state, from)
return getNearbyStatement(this.editorView.state, from)
}
}

export type CreateSQLEditorOptions = {
editorId: string
doc: string

basicSetupOptions?: BasicSetupOptions
Expand All @@ -67,6 +69,7 @@ export type CreateSQLEditorOptions = {
}

export const createSQLEditorInstance = ({
editorId,
doc,
basicSetupOptions = {},
sqlConfig = {},
Expand Down Expand Up @@ -94,14 +97,15 @@ export const createSQLEditorInstance = ({
curSql(),
extraExts
]
const editor = new EditorView({
const editorView = new EditorView({
state: EditorState.create({
doc,
extensions
})
})
const editorInst = new SQLEditorInstance(
editor,
editorId,
editorView,
themeCompartment,
sqlCompartment,
extraData
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@

export * from './editor-instance'
export * from './editor-cache'
38 changes: 38 additions & 0 deletions packages/react/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "@tidbcloud/tisqleditor-react",
"version": "0.0.1",
"description": "",
"type": "module",
"main": "dist/index.js",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist/*.js",
"dist/*.ts",
"package.json",
"README.md"
],
"scripts": {
"tsc:watch": "tsc --watch",
"rollup:watch": "rollup -c --watch",
"dev": "concurrently --kill-others \"pnpm tsc:watch\" \"pnpm rollup:watch\"",
"build": "tsc && rollup -c"
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"@tidbcloud/tisqleditor": "workspace:^"
},
"devDependencies": {
"@rollup/plugin-typescript": "^11.1.6",
"@types/react": "^18.3.3",
"react": "^18.3.1",
"rollup": "^4.18.0",
"tslib": "^2.6.3",
"typescript": "^5.4.5"
},
"peerDependencies": {
"react": "^18.3.1"
}
}
10 changes: 10 additions & 0 deletions packages/react/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import typescript from '@rollup/plugin-typescript'

export default {
input: 'src/index.ts',
output: {
dir: 'dist',
format: 'es'
},
plugins: [typescript()]
}
46 changes: 46 additions & 0 deletions packages/react/src/editor-cache-context.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { createContext, useContext, useEffect, useMemo, useState } from 'react'
import { EditorCache } from '@tidbcloud/tisqleditor'

type EditorCacheCtxValue = {
cache: EditorCache

activeEditorId: string
setActiveEditorId: (editorId: string) => void
}

const EditorCacheContext = createContext<EditorCacheCtxValue | null>(null)

export const useEditorCacheContext = () => {
const context = useContext(EditorCacheContext)

if (!context) {
throw new Error('useEditorCacheContext must be used within a provider')
}

return context
}

export function EditorCacheProvider(props: { children: React.ReactNode }) {
const [activeEditorId, setActiveEditorId] = useState('')
const cache = useMemo(() => new EditorCache(), [])
const ctxValue = useMemo(
() => ({
cache,
activeEditorId,
setActiveEditorId
}),
[activeEditorId]
)

useEffect(() => {
return () => {
cache.clearEditors()
}
}, [])

return (
<EditorCacheContext.Provider value={ctxValue}>
{props.children}
</EditorCacheContext.Provider>
)
}
2 changes: 2 additions & 0 deletions packages/react/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './editor-cache-context'
export * from './sql-editor'
58 changes: 58 additions & 0 deletions packages/react/src/sql-editor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { useEffect, useLayoutEffect, useRef } from 'react'

import { useEditorCacheContext } from './editor-cache-context'
import {
CreateSQLEditorOptions,
createSQLEditorInstance
} from '@tidbcloud/tisqleditor'

type SQLEditorProps = CreateSQLEditorOptions & {
editorId: string
className?: string
}

export default function SQLEditor({
className,
editorId,
theme,
sqlConfig,
...rest
}: SQLEditorProps) {
const editorContainerRef = useRef<HTMLDivElement>(null)
const cacheCtx = useEditorCacheContext()

useLayoutEffect(() => {
if (!editorContainerRef.current) return

let editorInst = cacheCtx.cache.getEditor(editorId)
if (!editorInst) {
editorInst = createSQLEditorInstance({
editorId,
theme,
sqlConfig,
...rest
})
cacheCtx.cache.addEditor(editorId, editorInst)
}

editorContainerRef.current.appendChild(editorInst.editorView.dom)
editorInst.editorView.focus()

return () => {
if (editorContainerRef.current && editorInst) {
editorContainerRef.current.removeChild(editorInst.editorView.dom)
}
}
}, [editorId])

// use `useLayoutEffect` to avoid flicker
useLayoutEffect(() => {
cacheCtx.cache.getEditor(editorId)?.changeTheme(theme ?? [])
}, [editorId, theme])

useEffect(() => {
cacheCtx.cache.getEditor(editorId)?.changeSQLConfig(sqlConfig ?? {})
}, [editorId, sqlConfig])

return <div className={className} ref={editorContainerRef} />
}
29 changes: 29 additions & 0 deletions packages/react/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,

/* declaration */
"declaration": true,
"emitDeclarationOnly": true,
"outDir": "./dist",

/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
// "noEmit": true,
"jsx": "react-jsx",

/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
}
54 changes: 54 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 970b6e0

Please sign in to comment.