@fayz-ai/plugin-forms 0.9.0 → 0.9.2

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.
Files changed (82) hide show
  1. package/README.md +3 -3
  2. package/dist/{FormBuilder-7SWZQKFN.js → FormBuilder-YHJHF6HZ.js} +4 -4
  3. package/dist/{FormBuilder-7SWZQKFN.js.map → FormBuilder-YHJHF6HZ.js.map} +1 -1
  4. package/dist/{chunk-W2ZNJGQC.js → chunk-RBLXIKWB.js} +221 -8
  5. package/dist/chunk-RBLXIKWB.js.map +1 -0
  6. package/dist/components/AddDocumentDropdown.d.ts +1 -1
  7. package/dist/components/AddDocumentDropdown.d.ts.map +1 -1
  8. package/dist/components/DocumentFormDialog.d.ts.map +1 -1
  9. package/dist/components/DocumentSkeleton.d.ts +21 -0
  10. package/dist/components/DocumentSkeleton.d.ts.map +1 -0
  11. package/dist/components/FormRenderer.d.ts.map +1 -1
  12. package/dist/components/FormViewer.d.ts.map +1 -1
  13. package/dist/{CustomFormsContext.d.ts → context.d.ts} +1 -1
  14. package/dist/context.d.ts.map +1 -0
  15. package/dist/data/mock.d.ts.map +1 -1
  16. package/dist/data/supabase.d.ts.map +1 -1
  17. package/dist/data/types.d.ts +4 -1
  18. package/dist/data/types.d.ts.map +1 -1
  19. package/dist/index.d.ts +1 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +174 -17
  22. package/dist/index.js.map +1 -1
  23. package/dist/lib/agent-tools.d.ts.map +1 -0
  24. package/dist/lib/document-types.d.ts.map +1 -0
  25. package/dist/lib/html-text.d.ts +21 -0
  26. package/dist/lib/html-text.d.ts.map +1 -0
  27. package/dist/lib/print.d.ts.map +1 -1
  28. package/dist/lib/timeline-source.d.ts +10 -0
  29. package/dist/lib/timeline-source.d.ts.map +1 -0
  30. package/dist/locales/en.d.ts.map +1 -1
  31. package/dist/locales/pt-BR.d.ts.map +1 -1
  32. package/dist/migrations/index.d.ts +1 -0
  33. package/dist/migrations/index.d.ts.map +1 -1
  34. package/dist/store.d.ts +5 -1
  35. package/dist/store.d.ts.map +1 -1
  36. package/dist/types.d.ts +13 -0
  37. package/dist/types.d.ts.map +1 -1
  38. package/dist/views/TemplateListView.d.ts.map +1 -1
  39. package/package.json +5 -7
  40. package/dist/CustomFormsContext.d.ts.map +0 -1
  41. package/dist/agent-tools.d.ts.map +0 -1
  42. package/dist/chunk-W2ZNJGQC.js.map +0 -1
  43. package/dist/document-types.d.ts.map +0 -1
  44. package/src/CustomFormsContext.tsx +0 -28
  45. package/src/agent-tools.ts +0 -73
  46. package/src/components/AddDocumentDropdown.tsx +0 -92
  47. package/src/components/BuilderCanvas.tsx +0 -87
  48. package/src/components/BuilderField.tsx +0 -81
  49. package/src/components/DocumentFormDialog.tsx +0 -155
  50. package/src/components/DocumentList.tsx +0 -254
  51. package/src/components/FieldConfigDialog.tsx +0 -243
  52. package/src/components/FieldPalette.tsx +0 -81
  53. package/src/components/FormBuilder.tsx +0 -427
  54. package/src/components/FormRenderer.tsx +0 -256
  55. package/src/components/FormViewer.tsx +0 -94
  56. package/src/components/PersonDocumentsWidget.tsx +0 -229
  57. package/src/components/TemplateSelector.tsx +0 -91
  58. package/src/config.ts +0 -43
  59. package/src/data/index.ts +0 -3
  60. package/src/data/mock.ts +0 -193
  61. package/src/data/supabase.ts +0 -408
  62. package/src/data/tables.ts +0 -7
  63. package/src/data/types.ts +0 -33
  64. package/src/document-types.ts +0 -51
  65. package/src/index.ts +0 -234
  66. package/src/lib/person-fields.ts +0 -67
  67. package/src/lib/print.ts +0 -207
  68. package/src/lib/tenant.ts +0 -9
  69. package/src/locales/en.ts +0 -95
  70. package/src/locales/index.ts +0 -7
  71. package/src/locales/pt-BR.ts +0 -95
  72. package/src/migrations/000_plg_rename.sql +0 -21
  73. package/src/migrations/001_frm_base.sql +0 -174
  74. package/src/migrations/002_document_archetype.sql +0 -223
  75. package/src/migrations/003_agent_rpcs.sql +0 -174
  76. package/src/migrations/index.ts +0 -610
  77. package/src/store.ts +0 -167
  78. package/src/types.ts +0 -217
  79. package/src/views/CustomFormsSettingsTab.tsx +0 -105
  80. package/src/views/TemplateListView.tsx +0 -174
  81. /package/dist/{agent-tools.d.ts → lib/agent-tools.d.ts} +0 -0
  82. /package/dist/{document-types.d.ts → lib/document-types.d.ts} +0 -0
@@ -1,243 +0,0 @@
1
- import React, { useState, useEffect } from 'react'
2
- import { Plus, Trash2 } from 'lucide-react'
3
- import {
4
- Sheet,
5
- SheetContent,
6
- SheetHeader,
7
- SheetTitle,
8
- SheetBody,
9
- SheetFooter,
10
- } from '@fayz-ai/ui'
11
- import { Button } from '@fayz-ai/ui'
12
- import { Input } from '@fayz-ai/ui'
13
- import {
14
- Select,
15
- SelectContent,
16
- SelectItem,
17
- SelectTrigger,
18
- SelectValue,
19
- } from '@fayz-ai/ui'
20
- import { useTranslation } from '@fayz-ai/core'
21
- import type { FormFieldDef } from '../types'
22
- import { FIELD_TYPES } from './FieldPalette'
23
- import { PERSON_FIELD_OPTIONS } from '../lib/person-fields'
24
-
25
- /** Field types that can be auto-filled from a person record. */
26
- const MAPPABLE_TYPES = ['text', 'memo', 'richtext', 'date']
27
- const MAP_NONE = '__none__'
28
-
29
- const SIZE_OPTIONS = [
30
- { span: 3, label: '1/4' },
31
- { span: 4, label: '1/3' },
32
- { span: 6, label: '1/2' },
33
- { span: 8, label: '2/3' },
34
- { span: 9, label: '3/4' },
35
- { span: 12, label: 'Full' },
36
- ]
37
-
38
- interface FieldConfigDrawerProps {
39
- field: FormFieldDef | null
40
- onSave: (updated: FormFieldDef) => void
41
- /** Live update without closing — used for visual changes like colSpan */
42
- onUpdate?: (updated: FormFieldDef) => void
43
- onClose: () => void
44
- }
45
-
46
- export function FieldConfigDrawer({ field, onSave, onUpdate, onClose }: FieldConfigDrawerProps) {
47
- const t = useTranslation()
48
- const [label, setLabel] = useState('')
49
- const [placeholder, setPlaceholder] = useState('')
50
- const [required, setRequired] = useState(false)
51
- const [colSpan, setColSpan] = useState(12)
52
- const [options, setOptions] = useState<Array<{ label: string; value: string }>>([])
53
- const [map, setMap] = useState<string>('')
54
-
55
- // Sync state when field changes
56
- useEffect(() => {
57
- if (!field) return
58
- setLabel(field.label)
59
- setPlaceholder(field.placeholder ?? '')
60
- setRequired(field.required ?? false)
61
- setColSpan(field.colSpan)
62
- setOptions(field.options ?? [])
63
- setMap(field.map ?? '')
64
- }, [field?.id])
65
-
66
- if (!field) return null
67
-
68
- const hasOptions = ['select', 'radio', 'tags'].includes(field.type)
69
- const canMap = MAPPABLE_TYPES.includes(field.type)
70
- const fieldTypeDef = FIELD_TYPES.find((ft) => ft.type === field.type)
71
- const Icon = fieldTypeDef?.icon
72
-
73
- const handleSave = () => {
74
- onSave({
75
- ...field,
76
- label,
77
- placeholder: placeholder || undefined,
78
- required,
79
- colSpan: Math.max(1, Math.min(12, colSpan)),
80
- options: hasOptions ? options.filter((o) => o.label.trim()) : field.options,
81
- map: canMap && map ? map : undefined,
82
- })
83
- }
84
-
85
- const addOption = () => {
86
- setOptions([...options, { label: '', value: '' }])
87
- }
88
-
89
- const updateOption = (index: number, newLabel: string) => {
90
- const updated = [...options]
91
- updated[index] = { label: newLabel, value: newLabel.toLowerCase().replace(/\s+/g, '_') }
92
- setOptions(updated)
93
- }
94
-
95
- const removeOption = (index: number) => {
96
- setOptions(options.filter((_, i) => i !== index))
97
- }
98
-
99
- return (
100
- <Sheet open={!!field} onOpenChange={(open) => { if (!open) onClose() }}>
101
- <SheetContent className="w-80 sm:w-96" overlay="none">
102
- <SheetHeader>
103
- <SheetTitle className="flex items-center gap-2 text-sm">
104
- {Icon && <Icon className="h-4 w-4 text-muted-foreground" />}
105
- {t(`customForms.fieldType.${field.type}`)}
106
- </SheetTitle>
107
- </SheetHeader>
108
-
109
- <SheetBody className="space-y-4 py-4">
110
- {/* Label */}
111
- <div className="space-y-1.5">
112
- <label className="text-xs font-medium">{t('customForms.builder.fieldLabel')}</label>
113
- <Input
114
- value={label}
115
- onChange={(e) => setLabel(e.target.value)}
116
- className="h-9 text-sm"
117
- autoFocus
118
- />
119
- </div>
120
-
121
- {/* Placeholder */}
122
- {!['title', 'checkbox', 'image', 'gallery'].includes(field.type) && (
123
- <div className="space-y-1.5">
124
- <label className="text-xs font-medium">{t('customForms.builder.fieldPlaceholder')}</label>
125
- <Input
126
- value={placeholder}
127
- onChange={(e) => setPlaceholder(e.target.value)}
128
- className="h-9 text-sm"
129
- />
130
- </div>
131
- )}
132
-
133
- {/* Column span — visual skeleton selector */}
134
- <div className="space-y-2">
135
- <label className="text-xs font-medium">{t('customForms.builder.colSpan')}</label>
136
- <div className="grid grid-cols-3 gap-2">
137
- {SIZE_OPTIONS.map((opt) => (
138
- <button
139
- key={opt.span}
140
- onClick={() => {
141
- setColSpan(opt.span)
142
- if (onUpdate && field) {
143
- onUpdate({ ...field, colSpan: opt.span })
144
- }
145
- }}
146
- className={`group relative rounded-lg border-2 p-2 transition-all ${
147
- colSpan === opt.span
148
- ? 'border-primary bg-primary/5'
149
- : 'border-border hover:border-primary/30'
150
- }`}
151
- >
152
- {/* Mini 12-col skeleton preview */}
153
- <div className="flex gap-px h-3 mb-1.5">
154
- <div
155
- className={`rounded-sm ${colSpan === opt.span ? 'bg-primary/60' : 'bg-muted-foreground/30 group-hover:bg-primary/30'}`}
156
- style={{ width: `${(opt.span / 12) * 100}%` }}
157
- />
158
- {opt.span < 12 && (
159
- <div
160
- className="rounded-sm bg-muted/60"
161
- style={{ width: `${((12 - opt.span) / 12) * 100}%` }}
162
- />
163
- )}
164
- </div>
165
- <span className={`text-[10px] font-medium ${colSpan === opt.span ? 'text-primary' : 'text-muted-foreground'}`}>
166
- {opt.label}
167
- </span>
168
- </button>
169
- ))}
170
- </div>
171
- </div>
172
-
173
- {/* Required */}
174
- {field.type !== 'title' && (
175
- <label className="flex items-center gap-2 cursor-pointer">
176
- <input
177
- type="checkbox"
178
- checked={required}
179
- onChange={(e) => setRequired(e.target.checked)}
180
- className="rounded border-input accent-primary"
181
- />
182
- <span className="text-sm">{t('customForms.builder.fieldRequired')}</span>
183
- </label>
184
- )}
185
-
186
- {/* Auto-fill from person record */}
187
- {canMap && (
188
- <div className="space-y-1.5">
189
- <label className="text-xs font-medium">{t('customForms.builder.mapToPerson')}</label>
190
- <Select
191
- value={map || MAP_NONE}
192
- onValueChange={(v) => setMap(v === MAP_NONE ? '' : v)}
193
- >
194
- <SelectTrigger className="h-9 text-sm">
195
- <SelectValue />
196
- </SelectTrigger>
197
- <SelectContent>
198
- <SelectItem value={MAP_NONE}>{t('customForms.builder.mapNone')}</SelectItem>
199
- {PERSON_FIELD_OPTIONS.map((opt) => (
200
- <SelectItem key={opt.value} value={opt.value}>
201
- {t(opt.labelKey)}
202
- </SelectItem>
203
- ))}
204
- </SelectContent>
205
- </Select>
206
- <p className="text-[10px] text-muted-foreground">{t('customForms.builder.mapHint')}</p>
207
- </div>
208
- )}
209
-
210
- {/* Options */}
211
- {hasOptions && (
212
- <div className="space-y-2">
213
- <label className="text-xs font-medium">{t('customForms.builder.fieldOptions')}</label>
214
- {options.map((opt, i) => (
215
- <div key={i} className="flex items-center gap-2">
216
- <Input
217
- value={opt.label}
218
- onChange={(e) => updateOption(i, e.target.value)}
219
- placeholder={`Option ${i + 1}`}
220
- className="h-8 text-sm flex-1"
221
- />
222
- <button onClick={() => removeOption(i)} className="p-1 hover:bg-destructive/10 rounded">
223
- <Trash2 className="h-3.5 w-3.5 text-destructive" />
224
- </button>
225
- </div>
226
- ))}
227
- <Button variant="outline" size="sm" onClick={addOption} className="h-8 text-xs w-full">
228
- <Plus className="h-3 w-3 mr-1" />
229
- {t('customForms.builder.addOption')}
230
- </Button>
231
- </div>
232
- )}
233
- </SheetBody>
234
-
235
- <SheetFooter className="pt-4 border-t">
236
- <Button size="sm" onClick={handleSave} className="w-full">
237
- OK
238
- </Button>
239
- </SheetFooter>
240
- </SheetContent>
241
- </Sheet>
242
- )
243
- }
@@ -1,81 +0,0 @@
1
- import React from 'react'
2
- import { useDraggable } from '@dnd-kit/core'
3
- import {
4
- Heading, Type, AlignLeft, FileEdit, CalendarDays,
5
- ChevronDown, CircleDot, Tags, CheckSquare,
6
- Image, GalleryHorizontalEnd, Receipt,
7
- } from 'lucide-react'
8
- import { useTranslation } from '@fayz-ai/core'
9
- import type { FormFieldType } from '../types'
10
-
11
- export interface FieldTypeItem {
12
- type: FormFieldType
13
- icon: React.ElementType
14
- }
15
-
16
- export const DEFAULT_COL_SPAN: Record<string, number> = {
17
- title: 12,
18
- memo: 12,
19
- richtext: 12,
20
- gallery: 12,
21
- budget: 12,
22
- image: 6,
23
- text: 6,
24
- date: 4,
25
- select: 6,
26
- radio: 6,
27
- tags: 8,
28
- checkbox: 4,
29
- }
30
-
31
- export const FIELD_TYPES: FieldTypeItem[] = [
32
- { type: 'title', icon: Heading },
33
- { type: 'text', icon: Type },
34
- { type: 'memo', icon: AlignLeft },
35
- { type: 'richtext', icon: FileEdit },
36
- { type: 'date', icon: CalendarDays },
37
- { type: 'select', icon: ChevronDown },
38
- { type: 'radio', icon: CircleDot },
39
- { type: 'tags', icon: Tags },
40
- { type: 'checkbox', icon: CheckSquare },
41
- { type: 'image', icon: Image },
42
- { type: 'gallery', icon: GalleryHorizontalEnd },
43
- { type: 'budget', icon: Receipt },
44
- ]
45
-
46
- function DraggableFieldType({ item }: { item: FieldTypeItem }) {
47
- const t = useTranslation()
48
- const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
49
- id: `palette-${item.type}`,
50
- data: { source: 'palette', fieldType: item.type },
51
- })
52
-
53
- const Icon = item.icon
54
-
55
- return (
56
- <button
57
- ref={setNodeRef}
58
- {...listeners}
59
- {...attributes}
60
- className={`flex items-center gap-2 w-full px-3 py-2 rounded-lg border bg-card text-sm font-medium transition-all hover:shadow-sm hover:border-primary/30 cursor-grab active:cursor-grabbing ${isDragging ? 'opacity-30' : ''}`}
61
- >
62
- <Icon className="h-4 w-4 text-muted-foreground shrink-0" />
63
- <span className="truncate">{t(`customForms.fieldType.${item.type}`)}</span>
64
- </button>
65
- )
66
- }
67
-
68
- export function FieldPalette() {
69
- const t = useTranslation()
70
-
71
- return (
72
- <div className="w-44 shrink-0 space-y-1.5">
73
- <p className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground px-1 mb-2">
74
- {t('customForms.builder.fields')}
75
- </p>
76
- {FIELD_TYPES.map((item) => (
77
- <DraggableFieldType key={item.type} item={item} />
78
- ))}
79
- </div>
80
- )
81
- }