@object-ui/fields 6.2.2 → 7.0.0

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 (97) hide show
  1. package/CHANGELOG.md +199 -0
  2. package/dist/complex-widgets.test.d.ts +1 -0
  3. package/dist/currency.d.ts +13 -0
  4. package/dist/datetime-widgets.test.d.ts +1 -0
  5. package/dist/field-type-coverage.test.d.ts +1 -0
  6. package/dist/index.cjs +4 -3
  7. package/dist/index.d.ts +300 -2
  8. package/dist/index.js +2460 -1274
  9. package/dist/standard-widgets.test.d.ts +0 -0
  10. package/dist/{packages/fields/src/widgets → widgets}/AddressField.d.ts +2 -1
  11. package/dist/{packages/fields/src/widgets → widgets}/AutoNumberField.d.ts +2 -1
  12. package/dist/{packages/fields/src/widgets → widgets}/AvatarField.d.ts +2 -1
  13. package/dist/{packages/fields/src/widgets → widgets}/BooleanField.d.ts +2 -1
  14. package/dist/widgets/CheckboxesField.d.ts +8 -0
  15. package/dist/{packages/fields/src/widgets → widgets}/CodeField.d.ts +2 -1
  16. package/dist/{packages/fields/src/widgets → widgets}/ColorField.d.ts +2 -1
  17. package/dist/{packages/fields/src/widgets → widgets}/CurrencyField.d.ts +2 -1
  18. package/dist/{packages/fields/src/widgets → widgets}/DateField.d.ts +2 -1
  19. package/dist/{packages/fields/src/widgets → widgets}/DateTimeField.d.ts +2 -1
  20. package/dist/{packages/fields/src/widgets → widgets}/EmailField.d.ts +2 -1
  21. package/dist/{packages/fields/src/widgets → widgets}/FileField.d.ts +2 -1
  22. package/dist/{packages/fields/src/widgets → widgets}/FormulaField.d.ts +2 -1
  23. package/dist/{packages/fields/src/widgets → widgets}/GeolocationField.d.ts +2 -1
  24. package/dist/widgets/GridField.d.ts +123 -0
  25. package/dist/widgets/GridField.test.d.ts +1 -0
  26. package/dist/{packages/fields/src/widgets → widgets}/ImageField.d.ts +2 -1
  27. package/dist/{packages/fields/src/widgets → widgets}/LocationField.d.ts +2 -1
  28. package/dist/{packages/fields/src/widgets → widgets}/LookupField.d.ts +2 -1
  29. package/dist/widgets/MarkdownContent.d.ts +9 -0
  30. package/dist/{packages/fields/src/widgets → widgets}/MasterDetailField.d.ts +2 -1
  31. package/dist/widgets/MultiSelectField.d.ts +9 -0
  32. package/dist/{packages/fields/src/widgets → widgets}/NumberField.d.ts +2 -1
  33. package/dist/{packages/fields/src/widgets → widgets}/ObjectField.d.ts +2 -1
  34. package/dist/{packages/fields/src/widgets → widgets}/PasswordField.d.ts +2 -1
  35. package/dist/{packages/fields/src/widgets → widgets}/PercentField.d.ts +2 -1
  36. package/dist/{packages/fields/src/widgets → widgets}/PhoneField.d.ts +2 -1
  37. package/dist/{packages/fields/src/widgets → widgets}/QRCodeField.d.ts +2 -1
  38. package/dist/widgets/RadioField.d.ts +8 -0
  39. package/dist/{packages/fields/src/widgets → widgets}/RatingField.d.ts +2 -1
  40. package/dist/{packages/fields/src/widgets → widgets}/RecordPickerDialog.d.ts +8 -2
  41. package/dist/{packages/fields/src/widgets → widgets}/RichTextField.d.ts +2 -1
  42. package/dist/{packages/fields/src/widgets → widgets}/SelectField.d.ts +2 -1
  43. package/dist/{packages/fields/src/widgets → widgets}/SignatureField.d.ts +2 -1
  44. package/dist/{packages/fields/src/widgets → widgets}/SliderField.d.ts +2 -1
  45. package/dist/{packages/fields/src/widgets → widgets}/SummaryField.d.ts +2 -1
  46. package/dist/widgets/TagsField.d.ts +8 -0
  47. package/dist/{packages/fields/src/widgets → widgets}/TextAreaField.d.ts +2 -1
  48. package/dist/{packages/fields/src/widgets → widgets}/TextField.d.ts +2 -1
  49. package/dist/{packages/fields/src/widgets → widgets}/TimeField.d.ts +2 -1
  50. package/dist/{packages/fields/src/widgets → widgets}/UrlField.d.ts +2 -1
  51. package/dist/{packages/fields/src/widgets → widgets}/UserField.d.ts +2 -1
  52. package/dist/{packages/fields/src/widgets → widgets}/VectorField.d.ts +2 -1
  53. package/dist/widgets/deriveLookupColumns.d.ts +36 -0
  54. package/dist/widgets/deriveLookupColumns.test.d.ts +1 -0
  55. package/dist/widgets/recentLookups.d.ts +13 -0
  56. package/dist/widgets/recentLookups.test.d.ts +1 -0
  57. package/dist/{packages/fields/src/widgets → widgets}/types.d.ts +1 -1
  58. package/package.json +14 -11
  59. package/src/__tests__/registry-collision.test.ts +91 -0
  60. package/src/__tests__/resolveFieldCurrency.test.ts +20 -0
  61. package/src/coerce-safe-value.test.ts +34 -0
  62. package/src/complex-widgets.test.tsx +58 -7
  63. package/src/currency.ts +14 -0
  64. package/src/field-type-coverage.test.ts +65 -0
  65. package/src/index.tsx +372 -57
  66. package/src/widgets/CheckboxesField.tsx +53 -0
  67. package/src/widgets/CurrencyField.tsx +5 -1
  68. package/src/widgets/GridField.test.tsx +309 -0
  69. package/src/widgets/GridField.tsx +907 -33
  70. package/src/widgets/LookupField.tsx +258 -107
  71. package/src/widgets/MarkdownContent.tsx +19 -0
  72. package/src/widgets/MultiSelectField.tsx +59 -0
  73. package/src/widgets/PercentField.tsx +19 -7
  74. package/src/widgets/RadioField.tsx +41 -0
  75. package/src/widgets/RecordPickerDialog.tsx +22 -18
  76. package/src/widgets/SelectField.tsx +23 -2
  77. package/src/widgets/TagsField.tsx +67 -0
  78. package/src/widgets/deriveLookupColumns.test.ts +74 -0
  79. package/src/widgets/deriveLookupColumns.ts +104 -0
  80. package/src/widgets/recentLookups.test.ts +45 -0
  81. package/src/widgets/recentLookups.ts +47 -0
  82. package/src/widgets/useFieldTranslation.ts +30 -0
  83. package/dist/packages/fields/src/fields-edge-cases.stories.d.ts +0 -45
  84. package/dist/packages/fields/src/fields.stories.d.ts +0 -56
  85. package/dist/packages/fields/src/index.d.ts +0 -286
  86. package/dist/packages/fields/src/record-picker-dialog.stories.d.ts +0 -25
  87. package/dist/packages/fields/src/widgets/GridField.d.ts +0 -7
  88. package/src/fields-edge-cases.stories.tsx +0 -407
  89. package/src/fields.stories.tsx +0 -566
  90. package/src/record-picker-dialog.stories.tsx +0 -160
  91. /package/dist/{packages/fields/src/__tests__/validation-feedback.test.d.ts → __tests__/registry-collision.test.d.ts} +0 -0
  92. /package/dist/{packages/fields/src/complex-widgets.test.d.ts → __tests__/resolveFieldCurrency.test.d.ts} +0 -0
  93. /package/dist/{packages/fields/src/standard-widgets.test.d.ts → __tests__/validation-feedback.test.d.ts} +0 -0
  94. /package/dist/{packages/fields/src/datetime-widgets.test.d.ts → coerce-safe-value.test.d.ts} +0 -0
  95. /package/dist/{packages/fields/src/widgets → widgets}/ImageCropperDialog.d.ts +0 -0
  96. /package/dist/{packages/fields/src/widgets → widgets}/_cell-renderer-bridge.d.ts +0 -0
  97. /package/dist/{packages/fields/src/widgets → widgets}/useFieldTranslation.d.ts +0 -0
package/dist/index.d.ts CHANGED
@@ -1,2 +1,300 @@
1
- export * from './packages/fields/src/index'
2
- export {}
1
+ import { default as React } from 'react';
2
+ import { FieldMetadata } from '@object-ui/types';
3
+ import { resolveFieldCurrency } from './currency';
4
+ /**
5
+ * Heuristic: detect strings that look like opaque foreign-key IDs (e.g. nanoid
6
+ * or BSON ObjectId). Used so we don't display random gibberish to users when
7
+ * a lookup wasn't expanded.
8
+ */
9
+ export declare function isLikelyOpaqueId(v: unknown): boolean;
10
+ /**
11
+ * Cell renderer props
12
+ */
13
+ export interface CellRendererProps {
14
+ value: any;
15
+ field: FieldMetadata;
16
+ isEditing?: boolean;
17
+ onChange?: (value: any) => void;
18
+ }
19
+ /**
20
+ * Coerce a value to a safe primitive for rendering.
21
+ * Handles MongoDB wrapper types ($numberDecimal, $oid, $date), expanded
22
+ * reference objects, and arrays so that no raw object is ever passed as
23
+ * a React child — preventing React error #310.
24
+ */
25
+ export declare function coerceToSafeValue(value: unknown): string | number | boolean | null | undefined;
26
+ export { resolveFieldCurrency };
27
+ export declare function formatCurrency(value: number, currency?: string): string;
28
+ /**
29
+ * Format currency value in compact form for mobile display.
30
+ * E.g., $150,000 → $150K, $1,200,000 → $1.2M
31
+ * When `currency` is undefined, returns a compact number without symbol.
32
+ */
33
+ export declare function formatCompactCurrency(value: number, currency?: string): string;
34
+ /**
35
+ * Format a plain number with thousands separators, no currency symbol.
36
+ * Used as a safe fallback when a currency-typed field has no `currency`
37
+ * configured — we'd rather render `1,234.50` than silently assume USD.
38
+ */
39
+ export declare function formatNumber(value: number, decimals?: number): string;
40
+ /**
41
+ * Format percent value
42
+ * Handles both decimal (0.8 = 80%) and whole number (80 = 80%) inputs.
43
+ */
44
+ export declare function formatPercent(value: number, precision?: number): string;
45
+ /**
46
+ * Humanize a snake_case or kebab-case string into Title Case.
47
+ * Used as fallback label when no explicit option.label exists.
48
+ *
49
+ * Examples:
50
+ * "in_progress" → "In Progress"
51
+ * "high-priority" → "High Priority"
52
+ * "active" → "Active"
53
+ */
54
+ export declare function humanizeLabel(value: string): string;
55
+ /**
56
+ * Format date as relative time (e.g., "2 days ago", "Today", "Overdue 3d")
57
+ */
58
+ export declare function formatRelativeDate(value: string | Date | number): string;
59
+ /**
60
+ * Format date value
61
+ */
62
+ export declare function formatDate(value: string | Date | number, style?: string): string;
63
+ /**
64
+ * Format datetime value
65
+ */
66
+ export declare function formatDateTime(value: string | Date | number): string;
67
+ /**
68
+ * Text field cell renderer
69
+ */
70
+ export declare function TextCellRenderer({ value }: CellRendererProps): React.ReactElement;
71
+ /**
72
+ * Number field cell renderer
73
+ */
74
+ export declare function NumberCellRenderer({ value, field }: CellRendererProps): React.ReactElement;
75
+ /**
76
+ * Currency field cell renderer
77
+ */
78
+ export declare function CurrencyCellRenderer({ value, field }: CellRendererProps): React.ReactElement;
79
+ /**
80
+ * Percent field cell renderer with mini progress bar
81
+ */
82
+ export declare function PercentCellRenderer({ value, field }: CellRendererProps): React.ReactElement;
83
+ /**
84
+ * Boolean field cell renderer (Airtable-style checkbox)
85
+ * Supports semantic rendering for completion fields (green indicator)
86
+ * and warning badge for active/enabled fields when false.
87
+ */
88
+ export declare function BooleanCellRenderer({ value, field }: CellRendererProps): React.ReactElement;
89
+ /**
90
+ * Date field cell renderer
91
+ */
92
+ export declare function DateCellRenderer({ value, field }: CellRendererProps): React.ReactElement;
93
+ /**
94
+ * DateTime field cell renderer (Airtable-style with date and time visually separated)
95
+ */
96
+ export declare function DateTimeCellRenderer({ value }: CellRendererProps): React.ReactElement;
97
+ export declare function getBadgeColorClasses(color?: string, val?: unknown): string;
98
+ /**
99
+ * Resolve a semantic color name (e.g. "red", "green") for a value, suitable
100
+ * for callers that need a raw color token rather than CSS classes (for
101
+ * example, the Gantt renderer paints bars via inline styles).
102
+ *
103
+ * Resolution order: explicit option color → semantic value mapping →
104
+ * deterministic hash fallback. Returns `undefined` only when no value is
105
+ * supplied so the caller can fall back to its own default.
106
+ */
107
+ export declare function getSemanticColorName(color?: string, val?: unknown): string | undefined;
108
+ /**
109
+ * Map a semantic color name to its Tailwind -500 hex value. Used by
110
+ * inline-style consumers (Gantt bars). Falls back to the supplied default
111
+ * (or the platform default blue) when the name is unrecognized.
112
+ */
113
+ export declare function getSemanticHex(name?: string, fallback?: string): string;
114
+ /**
115
+ * Select field cell renderer.
116
+ *
117
+ * Two visual styles, controlled by `field.appearance` (renderer-level option,
118
+ * not part of the `@objectstack/spec` field schema):
119
+ * - `'badge'` (default for spec compatibility): soft-pill colored badge.
120
+ * - `'dot'`: a small colored dot followed by the option label. Used by
121
+ * dense list/grid contexts to keep the table visually quiet — repeated
122
+ * filled badges across many rows create heavy visual noise.
123
+ *
124
+ * Metadata always wins: callers can pass `appearance: 'badge'` on the field
125
+ * descriptor to force the legacy badge in any context.
126
+ */
127
+ export declare function SelectCellRenderer({ value, field }: CellRendererProps): React.ReactElement;
128
+ /**
129
+ * Email field cell renderer
130
+ */
131
+ export declare function EmailCellRenderer({ value }: CellRendererProps): React.ReactElement;
132
+ /**
133
+ * URL field cell renderer
134
+ */
135
+ export declare function UrlCellRenderer({ value }: CellRendererProps): React.ReactElement;
136
+ /**
137
+ * Phone field cell renderer
138
+ */
139
+ export declare function PhoneCellRenderer({ value }: CellRendererProps): React.ReactElement;
140
+ /**
141
+ * File field cell renderer
142
+ */
143
+ export declare function FileCellRenderer({ value, field }: CellRendererProps): React.ReactElement;
144
+ /**
145
+ * Image field cell renderer (with thumbnails)
146
+ */
147
+ export declare function ImageCellRenderer({ value }: CellRendererProps): React.ReactElement;
148
+ /**
149
+ * Lookup/Master-Detail field cell renderer.
150
+ *
151
+ * Display order:
152
+ * 1. Embedded record object (`{ id, name, ... }` from `$expand`) → use its name
153
+ * 2. Static `field.options[]` (e.g. when the lookup is a closed enum) → look up label
154
+ * 3. Fetch-on-demand: when the value is a primitive ID and `field.reference_to`
155
+ * is known, resolve via dataSource and show the related record's display name.
156
+ * Falls back to a muted placeholder while pending and on failure.
157
+ */
158
+ export declare function LookupCellRenderer({ value, field }: CellRendererProps): React.ReactElement;
159
+ /**
160
+ * Formula field cell renderer (read-only)
161
+ */
162
+ export declare function FormulaCellRenderer({ value }: CellRendererProps): React.ReactElement;
163
+ /**
164
+ * User/Owner field cell renderer (with avatars)
165
+ */
166
+ export declare function UserCellRenderer({ value }: CellRendererProps): React.ReactElement;
167
+ /**
168
+ * Register a custom field renderer
169
+ * @param type Field type (e.g. 'text', 'location', 'my-custom-type')
170
+ * @param renderer React component to render the field
171
+ */
172
+ export declare function registerFieldRenderer(type: string, renderer: React.FC<CellRendererProps>): void;
173
+ /**
174
+ * Resolve the canonical cell-renderer key for a field. Accepts either a
175
+ * raw type string (back-compat) or a field-metadata object so that
176
+ * format hints (`format: 'phone'` etc.) can promote a plain `text`
177
+ * field to its richer renderer counterpart.
178
+ */
179
+ export declare function resolveCellRendererType(fieldOrType: string | {
180
+ type?: string;
181
+ format?: string;
182
+ } | null | undefined): string;
183
+ /**
184
+ * Renders structured/embedded values (json, object, composite, record,
185
+ * address, geolocation) as compact, readable JSON. Objects and arrays are
186
+ * stringified; primitives fall through to their string form.
187
+ */
188
+ export declare function JsonCellRenderer({ value }: CellRendererProps): React.ReactElement;
189
+ /**
190
+ * Renders a `color` value as a swatch alongside its hex/string value.
191
+ */
192
+ export declare function ColorSwatchCellRenderer({ value }: CellRendererProps): React.ReactElement;
193
+ /**
194
+ * Renders `markdown` / `richtext` values as formatted GFM markdown (lazy-loaded,
195
+ * sanitized) instead of the raw markup string.
196
+ */
197
+ export declare function MarkdownCellRenderer({ value }: CellRendererProps): React.ReactElement;
198
+ /**
199
+ * Renders an `html` value as sanitized, formatted HTML instead of raw markup.
200
+ */
201
+ export declare function HtmlCellRenderer({ value }: CellRendererProps): React.ReactElement;
202
+ /**
203
+ * Renders a `location`/`geolocation` value as readable coordinates with a pin.
204
+ * Accepts `{ lat, lng }` / `{ latitude, longitude }`, a `"lat,lng"` string,
205
+ * or a `[lat, lng]` array. Falls back to compact JSON for anything else.
206
+ */
207
+ export declare function LocationCellRenderer({ value }: CellRendererProps): React.ReactElement;
208
+ /**
209
+ * Get the appropriate cell renderer for a field type
210
+ */
211
+ export declare function getCellRenderer(fieldType: string): React.FC<CellRendererProps>;
212
+ /**
213
+ * Map field type to form component type
214
+ *
215
+ * @param fieldType - The ObjectQL field type identifier to convert
216
+ * (for example: `"text"`, `"number"`, `"date"`, `"lookup"`).
217
+ * @returns The normalized form field type string used in the form schema
218
+ * (for example: `"input"`, `"textarea"`, `"date-picker"`, `"select"`).
219
+ */
220
+ export declare function mapFieldTypeToFormType(fieldType: string): string;
221
+ /**
222
+ * Formats file size in bytes to human-readable string
223
+ * @param bytes - File size in bytes (must be non-negative)
224
+ * @returns Formatted string (e.g., "5 MB", "1.5 GB")
225
+ */
226
+ export declare function formatFileSize(bytes: number): string;
227
+ /**
228
+ * Build validation rules from field metadata
229
+ * @param field - Field metadata from ObjectStack
230
+ * @returns Validation rule object compatible with react-hook-form
231
+ */
232
+ export declare function buildValidationRules(field: any): any;
233
+ /**
234
+ * Evaluate a conditional expression for field visibility
235
+ * @param condition - Condition object from field metadata
236
+ * @param formData - Current form values
237
+ * @returns Whether the condition is met
238
+ */
239
+ export declare function evaluateCondition(condition: any, formData: any): boolean;
240
+ export declare function registerField(fieldType: string): void;
241
+ /**
242
+ * Register all field types (for backward compatibility)
243
+ * This function auto-registers all field widgets on import.
244
+ *
245
+ * For better tree-shaking, use registerField() to register only needed fields.
246
+ *
247
+ * @example
248
+ * // Register all fields at once
249
+ * registerAllFields();
250
+ */
251
+ export declare function registerAllFields(): void;
252
+ /**
253
+ * Legacy function - kept for backward compatibility
254
+ * @deprecated Use registerAllFields() instead
255
+ */
256
+ export declare function registerFields(): void;
257
+ export * from './widgets/types';
258
+ export * from './widgets/TextField';
259
+ export * from './widgets/NumberField';
260
+ export * from './widgets/BooleanField';
261
+ export * from './widgets/SelectField';
262
+ export * from './widgets/DateField';
263
+ export * from './widgets/DateTimeField';
264
+ export * from './widgets/TimeField';
265
+ export * from './widgets/EmailField';
266
+ export * from './widgets/PhoneField';
267
+ export * from './widgets/UrlField';
268
+ export * from './widgets/CurrencyField';
269
+ export * from './widgets/PercentField';
270
+ export * from './widgets/PasswordField';
271
+ export * from './widgets/TextAreaField';
272
+ export * from './widgets/RichTextField';
273
+ export * from './widgets/LookupField';
274
+ export * from './widgets/RecordPickerDialog';
275
+ export * from './widgets/FileField';
276
+ export * from './widgets/ImageField';
277
+ export { ImageCropperDialog } from './widgets/ImageCropperDialog';
278
+ export type { ImageCropperDialogProps } from './widgets/ImageCropperDialog';
279
+ export * from './widgets/LocationField';
280
+ export * from './widgets/FormulaField';
281
+ export * from './widgets/SummaryField';
282
+ export * from './widgets/AutoNumberField';
283
+ export * from './widgets/UserField';
284
+ export * from './widgets/ObjectField';
285
+ export * from './widgets/VectorField';
286
+ export * from './widgets/GridField';
287
+ export * from './widgets/ColorField';
288
+ export * from './widgets/SliderField';
289
+ export * from './widgets/RatingField';
290
+ export * from './widgets/CodeField';
291
+ export * from './widgets/AvatarField';
292
+ export * from './widgets/AddressField';
293
+ export * from './widgets/GeolocationField';
294
+ export * from './widgets/SignatureField';
295
+ export * from './widgets/QRCodeField';
296
+ export * from './widgets/MasterDetailField';
297
+ export * from './widgets/MultiSelectField';
298
+ export * from './widgets/RadioField';
299
+ export * from './widgets/CheckboxesField';
300
+ export * from './widgets/TagsField';