@object-ui/fields 6.2.3 → 7.1.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 +203 -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
@@ -1,160 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react';
2
- import React, { useState } from 'react';
3
- import { RecordPickerDialog } from './widgets/RecordPickerDialog';
4
- import type { DataSource } from '@object-ui/types';
5
-
6
- /**
7
- * **RecordPickerDialog** — Enterprise-grade record picker for lookup fields.
8
- *
9
- * Features: skeleton loading, sticky table header, column sort,
10
- * keyboard navigation, page jump, inline filter bar, column resize,
11
- * and responsive layout.
12
- */
13
- const meta = {
14
- title: 'Fields/RecordPickerDialog',
15
- component: RecordPickerDialog,
16
- parameters: {
17
- layout: 'centered',
18
- },
19
- tags: ['autodocs'],
20
- } satisfies Meta<typeof RecordPickerDialog>;
21
-
22
- export default meta;
23
- type Story = StoryObj<typeof RecordPickerDialog>;
24
-
25
- /* ------------------------------------------------------------------ */
26
- /* Mock data used by all stories */
27
- /* ------------------------------------------------------------------ */
28
-
29
- const MOCK_ORDERS = [
30
- { id: '1', order_number: 'ORD-2024-001', amount: 15459.99, status: 'Paid', order_date: '2024-01-15' },
31
- { id: '2', order_number: 'ORD-2024-002', amount: 289.50, status: 'Pending', order_date: '2024-01-18' },
32
- { id: '3', order_number: 'ORD-2024-003', amount: 5549.99, status: 'Shipped', order_date: '2024-02-05' },
33
- { id: '4', order_number: 'ORD-2024-004', amount: 42500.00, status: 'Delivered', order_date: '2024-02-20' },
34
- { id: '5', order_number: 'ORD-2024-005', amount: 1250.00, status: 'Draft', order_date: '2024-03-01' },
35
- { id: '6', order_number: 'ORD-2024-006', amount: 8999.94, status: 'Paid', order_date: '2024-03-15' },
36
- { id: '7', order_number: 'ORD-2024-007', amount: 3200.00, status: 'Shipped', order_date: '2024-04-02' },
37
- { id: '8', order_number: 'ORD-2024-008', amount: 750.00, status: 'Pending', order_date: '2024-04-10' },
38
- { id: '9', order_number: 'ORD-2024-009', amount: 19800.00, status: 'Delivered', order_date: '2024-04-22' },
39
- { id: '10', order_number: 'ORD-2024-010', amount: 4500.00, status: 'Paid', order_date: '2024-05-01' },
40
- { id: '11', order_number: 'ORD-2024-011', amount: 670.00, status: 'Draft', order_date: '2024-05-08' },
41
- { id: '12', order_number: 'ORD-2024-012', amount: 12345.67, status: 'Shipped', order_date: '2024-05-15' },
42
- ];
43
-
44
- /** Simulate async DataSource.find with pagination + search */
45
- function createMockDataSource(): DataSource {
46
- return {
47
- find: async (_objectName: string, params: any) => {
48
- await new Promise(r => setTimeout(r, 400)); // simulate latency
49
- let data = [...MOCK_ORDERS];
50
-
51
- // Search filter
52
- if (params?.$search) {
53
- const q = params.$search.toLowerCase();
54
- data = data.filter(
55
- r =>
56
- r.order_number.toLowerCase().includes(q) ||
57
- r.status.toLowerCase().includes(q),
58
- );
59
- }
60
-
61
- // Sort
62
- if (params?.$orderby) {
63
- const entries = Object.entries(params.$orderby);
64
- if (entries.length > 0) {
65
- const [field, dir] = entries[0] as [string, string];
66
- data.sort((a: any, b: any) => {
67
- if (a[field] < b[field]) return dir === 'asc' ? -1 : 1;
68
- if (a[field] > b[field]) return dir === 'asc' ? 1 : -1;
69
- return 0;
70
- });
71
- }
72
- }
73
-
74
- const total = data.length;
75
- const skip = params?.$skip ?? 0;
76
- const top = params?.$top ?? 10;
77
- return { data: data.slice(skip, skip + top), total };
78
- },
79
- findOne: async () => null,
80
- create: async () => ({}),
81
- update: async () => ({}),
82
- delete: async () => ({}),
83
- } as unknown as DataSource;
84
- }
85
-
86
- /* ------------------------------------------------------------------ */
87
- /* Story wrapper — opens the dialog inside a button toggle */
88
- /* ------------------------------------------------------------------ */
89
-
90
- function DialogDemo(props: Partial<React.ComponentProps<typeof RecordPickerDialog>>) {
91
- const [open, setOpen] = useState(true);
92
- const [selected, setSelected] = useState<any>(undefined);
93
- const ds = React.useMemo(() => createMockDataSource(), []);
94
-
95
- return (
96
- <div className="flex flex-col items-center gap-4 p-6">
97
- <button
98
- className="rounded-md bg-primary px-4 py-2 text-sm text-primary-foreground shadow"
99
- onClick={() => setOpen(true)}
100
- type="button"
101
- >
102
- Open Record Picker
103
- </button>
104
- {selected && (
105
- <p className="text-sm text-muted-foreground">
106
- Selected: <code className="font-mono text-foreground">{JSON.stringify(selected)}</code>
107
- </p>
108
- )}
109
- <RecordPickerDialog
110
- open={open}
111
- onOpenChange={setOpen}
112
- title="Order"
113
- dataSource={ds}
114
- objectName="orders"
115
- columns={[
116
- { field: 'order_number', label: 'Order Number' },
117
- { field: 'amount', label: 'Amount' },
118
- { field: 'status', label: 'Status' },
119
- { field: 'order_date', label: 'Order Date' },
120
- ]}
121
- displayField="order_number"
122
- pageSize={5}
123
- onSelect={(v: any) => setSelected(v)}
124
- {...props}
125
- />
126
- </div>
127
- );
128
- }
129
-
130
- /* ------------------------------------------------------------------ */
131
- /* Stories */
132
- /* ------------------------------------------------------------------ */
133
-
134
- /** Default single-select dialog with 4 columns, pagination, and search. */
135
- export const Default: Story = {
136
- render: () => <DialogDemo />,
137
- };
138
-
139
- /** Multi-select mode with confirm/cancel footer. */
140
- export const MultiSelect: Story = {
141
- render: () => <DialogDemo multiple />,
142
- };
143
-
144
- /** With inline filter columns for interactive filtering. */
145
- export const WithFilters: Story = {
146
- render: () => (
147
- <DialogDemo
148
- filterColumns={[
149
- { field: 'status', label: 'Status', type: 'select', options: [
150
- { label: 'Paid', value: 'Paid' },
151
- { label: 'Pending', value: 'Pending' },
152
- { label: 'Shipped', value: 'Shipped' },
153
- { label: 'Delivered', value: 'Delivered' },
154
- { label: 'Draft', value: 'Draft' },
155
- ]},
156
- { field: 'order_number', label: 'Order Number', type: 'text' },
157
- ]}
158
- />
159
- ),
160
- };