Mayo commited on
Commit
7bcdb4e
·
unverified ·
1 Parent(s): fc414a2

fix: ui issue

Browse files
ui/components/canvas/CanvasToolbar.tsx CHANGED
@@ -1,32 +1,38 @@
1
  'use client'
2
 
3
- import { Toolbar, Tooltip } from 'radix-ui'
4
- import { useCanvasCommands } from '@/hooks/useCanvasCommands'
5
 
6
  export function CanvasToolbar() {
7
- const { commands, llmReady } = useCanvasCommands()
 
 
 
 
8
 
9
  return (
10
- <Toolbar.Root className='flex items-center gap-1 border-b border-neutral-200 bg-white px-2 py-1.5 text-xs text-neutral-900'>
11
- {commands.map((item) => (
12
- <Tooltip.Root key={item.label} delayDuration={0}>
13
- <Tooltip.Trigger asChild>
14
- <Toolbar.Button
15
- onClick={item.action}
16
- disabled={item.disabled}
17
- className='rounded border border-neutral-200 bg-white px-2.5 py-1 font-semibold hover:bg-neutral-100 disabled:opacity-40 data-[state=on]:bg-neutral-900 data-[state=on]:text-white'
18
- >
19
- {item.label}
20
- </Toolbar.Button>
21
- </Tooltip.Trigger>
22
- <Tooltip.Content
23
- sideOffset={6}
24
- className='rounded bg-black px-2 py-1 text-xs text-white'
25
  >
26
- Run {item.label.toLowerCase()}
27
- </Tooltip.Content>
28
- </Tooltip.Root>
29
- ))}
 
 
 
 
30
  <span
31
  className={`ml-auto rounded-full px-2 py-1 text-xs ${
32
  llmReady ? 'bg-rose-100 text-rose-700' : 'bg-rose-50 text-rose-400'
 
1
  'use client'
2
 
3
+ import { Toolbar, Slider } from 'radix-ui'
4
+ import { useAppStore, useConfigStore } from '@/lib/store'
5
 
6
  export function CanvasToolbar() {
7
+ const llmReady = useAppStore((state) => state.llmReady)
8
+ const {
9
+ maskConfig: { brushSize },
10
+ setMaskConfig,
11
+ } = useConfigStore()
12
 
13
  return (
14
+ <Toolbar.Root className='flex items-center gap-4 border-b border-neutral-200 bg-white px-3 py-1.5 text-xs text-neutral-900'>
15
+ <div className='flex items-center gap-2'>
16
+ <span className='text-neutral-600'>Brush</span>
17
+ <div className='w-40'>
18
+ <Slider.Root
19
+ className='relative flex h-4 w-full touch-none items-center select-none'
20
+ min={8}
21
+ max={128}
22
+ step={4}
23
+ value={[brushSize]}
24
+ onValueChange={(vals) =>
25
+ setMaskConfig({ brushSize: vals[0] ?? brushSize })
26
+ }
 
 
27
  >
28
+ <Slider.Track className='relative h-1 flex-1 rounded bg-rose-100'>
29
+ <Slider.Range className='absolute h-full rounded bg-rose-400' />
30
+ </Slider.Track>
31
+ <Slider.Thumb className='block h-2.5 w-2.5 rounded-full bg-rose-500' />
32
+ </Slider.Root>
33
+ </div>
34
+ <span className='w-14 text-right tabular-nums'>{brushSize}px</span>
35
+ </div>
36
  <span
37
  className={`ml-auto rounded-full px-2 py-1 text-xs ${
38
  llmReady ? 'bg-rose-100 text-rose-700' : 'bg-rose-50 text-rose-400'
ui/components/canvas/Workspace.tsx CHANGED
@@ -17,7 +17,8 @@ const MASK_CURSOR =
17
  'url(\'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16"%3E%3Ccircle cx="8" cy="8" r="4" stroke="black" stroke-width="1.5" fill="white"/%3E%3C/svg%3E\') 8 8, crosshair'
18
 
19
  export function Workspace() {
20
- const { scale, showSegmentationMask, showInpaintedImage, mode } = useAppStore()
 
21
  const {
22
  document: currentDocument,
23
  selectedBlockIndex,
@@ -99,16 +100,19 @@ export function Workspace() {
99
  >
100
  <Layer>
101
  <Image data={currentDocument.image} />
102
- <Image
103
- data={currentDocument.segment}
104
- visible={showSegmentationMask}
105
- opacity={0.45}
106
- />
107
- <Image
108
- data={currentDocument.inpainted}
109
- visible={showInpaintedImage}
110
- opacity={0.95}
111
- />
 
 
 
112
  </Layer>
113
  <Layer>
114
  <TextBlockAnnotations
 
17
  'url(\'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16"%3E%3Ccircle cx="8" cy="8" r="4" stroke="black" stroke-width="1.5" fill="white"/%3E%3C/svg%3E\') 8 8, crosshair'
18
 
19
  export function Workspace() {
20
+ const { scale, showSegmentationMask, showInpaintedImage, mode } =
21
+ useAppStore()
22
  const {
23
  document: currentDocument,
24
  selectedBlockIndex,
 
100
  >
101
  <Layer>
102
  <Image data={currentDocument.image} />
103
+ {currentDocument?.segment && (
104
+ <Image
105
+ data={currentDocument.segment}
106
+ visible={showSegmentationMask}
107
+ opacity={0.8}
108
+ />
109
+ )}
110
+ {currentDocument.inpainted && (
111
+ <Image
112
+ data={currentDocument.inpainted}
113
+ visible={showInpaintedImage}
114
+ />
115
+ )}
116
  </Layer>
117
  <Layer>
118
  <TextBlockAnnotations
ui/components/panels/MaskControls.tsx CHANGED
@@ -1,6 +1,5 @@
1
  'use client'
2
 
3
- import { useState } from 'react'
4
  import { Separator } from 'radix-ui'
5
  import { useAppStore, useConfigStore } from '@/lib/store'
6
  import {
@@ -18,7 +17,6 @@ export function MaskControls() {
18
  inpaint,
19
  } = useAppStore()
20
  const { inpaintConfig, setInpaintConfig } = useConfigStore()
21
- const [brushSize, setBrushSize] = useState(36)
22
 
23
  return (
24
  <div className='space-y-2 text-xs text-neutral-600'>
@@ -33,14 +31,6 @@ export function MaskControls() {
33
  onChange={setShowInpaintedImage}
34
  />
35
  <Separator.Root className='my-1 h-px bg-neutral-200' />
36
- <SliderField
37
- label='Brush size'
38
- min={8}
39
- max={128}
40
- step={4}
41
- value={brushSize}
42
- onChange={setBrushSize}
43
- />
44
  <div className='grid grid-cols-2 gap-1.5'>
45
  <SliderField
46
  label='Dilate'
 
1
  'use client'
2
 
 
3
  import { Separator } from 'radix-ui'
4
  import { useAppStore, useConfigStore } from '@/lib/store'
5
  import {
 
17
  inpaint,
18
  } = useAppStore()
19
  const { inpaintConfig, setInpaintConfig } = useConfigStore()
 
20
 
21
  return (
22
  <div className='space-y-2 text-xs text-neutral-600'>
 
31
  onChange={setShowInpaintedImage}
32
  />
33
  <Separator.Root className='my-1 h-px bg-neutral-200' />
 
 
 
 
 
 
 
 
34
  <div className='grid grid-cols-2 gap-1.5'>
35
  <SliderField
36
  label='Dilate'
ui/components/panels/TextBlocksPanel.tsx CHANGED
@@ -88,13 +88,12 @@ function BlockCard({ block, index, selected, onChange }: BlockCardProps) {
88
  className='overflow-hidden rounded border border-neutral-200 bg-white/90 text-sm transition data-[selected=true]:border-rose-400 data-[state=open]:shadow-sm'
89
  >
90
  <Accordion.Header>
91
- <Accordion.Trigger className='flex w-full flex-col gap-1 px-3 py-2 text-left transition outline-none data-[state=open]:bg-rose-50'>
92
  <div className='flex items-center justify-between text-xs text-neutral-500'>
93
- <span className='font-semibold text-neutral-800'>
94
- Block {index + 1}
95
- </span>
96
- <span className='text-[11px] tracking-wide text-neutral-400 uppercase'>
97
- Click to edit
98
  </span>
99
  </div>
100
  {!selected && (
 
88
  className='overflow-hidden rounded border border-neutral-200 bg-white/90 text-sm transition data-[selected=true]:border-rose-400 data-[state=open]:shadow-sm'
89
  >
90
  <Accordion.Header>
91
+ <Accordion.Trigger className='flex w-full cursor-pointer flex-col gap-1 px-3 py-2 text-left transition outline-none data-[state=open]:bg-rose-50'>
92
  <div className='flex items-center justify-between text-xs text-neutral-500'>
93
+ <span className='inline-flex items-center gap-2'>
94
+ <span className='rounded-full bg-rose-100 px-2 py-0.5 text-[11px] font-semibold text-rose-700'>
95
+ #{index + 1}
96
+ </span>
 
97
  </span>
98
  </div>
99
  {!selected && (
ui/hooks/useCanvasCommands.ts DELETED
@@ -1,60 +0,0 @@
1
- 'use client'
2
-
3
- import { useCallback, useMemo } from 'react'
4
- import { useAppStore, useConfigStore } from '@/lib/store'
5
-
6
- export type CanvasCommand = {
7
- label: string
8
- action: () => void
9
- disabled: boolean
10
- }
11
-
12
- export function useCanvasCommands() {
13
- const { detect, ocr, inpaint, llmGenerate, documents, llmReady } =
14
- useAppStore()
15
- const { detectConfig, inpaintConfig } = useConfigStore()
16
-
17
- const hasDocument = documents.length > 0
18
-
19
- const runDetect = useCallback(() => {
20
- if (!hasDocument) return
21
- detect(detectConfig.confThreshold, detectConfig.nmsThreshold)
22
- }, [
23
- detect,
24
- detectConfig.confThreshold,
25
- detectConfig.nmsThreshold,
26
- hasDocument,
27
- ])
28
-
29
- const runOcr = useCallback(() => {
30
- if (!hasDocument) return
31
- ocr()
32
- }, [hasDocument, ocr])
33
-
34
- const runInpaint = useCallback(() => {
35
- if (!hasDocument) return
36
- inpaint(inpaintConfig.dilateKernelSize, inpaintConfig.erodeDistance)
37
- }, [
38
- hasDocument,
39
- inpaint,
40
- inpaintConfig.dilateKernelSize,
41
- inpaintConfig.erodeDistance,
42
- ])
43
-
44
- const runTranslate = useCallback(() => {
45
- if (!hasDocument) return
46
- llmGenerate()
47
- }, [hasDocument, llmGenerate])
48
-
49
- const commands = useMemo<CanvasCommand[]>(
50
- () => [
51
- { label: 'Detect', action: runDetect, disabled: !hasDocument },
52
- { label: 'OCR', action: runOcr, disabled: !hasDocument },
53
- { label: 'Inpaint', action: runInpaint, disabled: !hasDocument },
54
- { label: 'Translate', action: runTranslate, disabled: !hasDocument },
55
- ],
56
- [hasDocument, runDetect, runOcr, runInpaint, runTranslate],
57
- )
58
-
59
- return { commands, llmReady }
60
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/lib/store.ts CHANGED
@@ -177,8 +177,12 @@ type ConfigState = {
177
  dilateKernelSize: number
178
  erodeDistance: number
179
  }
 
 
 
180
  setDetectConfig: (config: Partial<ConfigState['detectConfig']>) => void
181
  setInpaintConfig: (config: Partial<ConfigState['inpaintConfig']>) => void
 
182
  }
183
 
184
  export const useConfigStore = create<ConfigState>((set) => ({
@@ -190,6 +194,9 @@ export const useConfigStore = create<ConfigState>((set) => ({
190
  dilateKernelSize: 9,
191
  erodeDistance: 3,
192
  },
 
 
 
193
  setDetectConfig: (config) =>
194
  set((state) => ({
195
  detectConfig: { ...state.detectConfig, ...config },
@@ -198,4 +205,8 @@ export const useConfigStore = create<ConfigState>((set) => ({
198
  set((state) => ({
199
  inpaintConfig: { ...state.inpaintConfig, ...config },
200
  })),
 
 
 
 
201
  }))
 
177
  dilateKernelSize: number
178
  erodeDistance: number
179
  }
180
+ maskConfig: {
181
+ brushSize: number
182
+ }
183
  setDetectConfig: (config: Partial<ConfigState['detectConfig']>) => void
184
  setInpaintConfig: (config: Partial<ConfigState['inpaintConfig']>) => void
185
+ setMaskConfig: (config: Partial<ConfigState['maskConfig']>) => void
186
  }
187
 
188
  export const useConfigStore = create<ConfigState>((set) => ({
 
194
  dilateKernelSize: 9,
195
  erodeDistance: 3,
196
  },
197
+ maskConfig: {
198
+ brushSize: 36,
199
+ },
200
  setDetectConfig: (config) =>
201
  set((state) => ({
202
  detectConfig: { ...state.detectConfig, ...config },
 
205
  set((state) => ({
206
  inpaintConfig: { ...state.inpaintConfig, ...config },
207
  })),
208
+ setMaskConfig: (config) =>
209
+ set((state) => ({
210
+ maskConfig: { ...state.maskConfig, ...config },
211
+ })),
212
  }))