@object-ui/fields 6.2.3 → 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.
- package/CHANGELOG.md +188 -0
- package/dist/complex-widgets.test.d.ts +1 -0
- package/dist/currency.d.ts +13 -0
- package/dist/datetime-widgets.test.d.ts +1 -0
- package/dist/field-type-coverage.test.d.ts +1 -0
- package/dist/index.cjs +4 -3
- package/dist/index.d.ts +300 -2
- package/dist/index.js +2460 -1274
- package/dist/standard-widgets.test.d.ts +0 -0
- package/dist/{packages/fields/src/widgets → widgets}/AddressField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/AutoNumberField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/AvatarField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/BooleanField.d.ts +2 -1
- package/dist/widgets/CheckboxesField.d.ts +8 -0
- package/dist/{packages/fields/src/widgets → widgets}/CodeField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/ColorField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/CurrencyField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/DateField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/DateTimeField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/EmailField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/FileField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/FormulaField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/GeolocationField.d.ts +2 -1
- package/dist/widgets/GridField.d.ts +123 -0
- package/dist/widgets/GridField.test.d.ts +1 -0
- package/dist/{packages/fields/src/widgets → widgets}/ImageField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/LocationField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/LookupField.d.ts +2 -1
- package/dist/widgets/MarkdownContent.d.ts +9 -0
- package/dist/{packages/fields/src/widgets → widgets}/MasterDetailField.d.ts +2 -1
- package/dist/widgets/MultiSelectField.d.ts +9 -0
- package/dist/{packages/fields/src/widgets → widgets}/NumberField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/ObjectField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/PasswordField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/PercentField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/PhoneField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/QRCodeField.d.ts +2 -1
- package/dist/widgets/RadioField.d.ts +8 -0
- package/dist/{packages/fields/src/widgets → widgets}/RatingField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/RecordPickerDialog.d.ts +8 -2
- package/dist/{packages/fields/src/widgets → widgets}/RichTextField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/SelectField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/SignatureField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/SliderField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/SummaryField.d.ts +2 -1
- package/dist/widgets/TagsField.d.ts +8 -0
- package/dist/{packages/fields/src/widgets → widgets}/TextAreaField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/TextField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/TimeField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/UrlField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/UserField.d.ts +2 -1
- package/dist/{packages/fields/src/widgets → widgets}/VectorField.d.ts +2 -1
- package/dist/widgets/deriveLookupColumns.d.ts +36 -0
- package/dist/widgets/deriveLookupColumns.test.d.ts +1 -0
- package/dist/widgets/recentLookups.d.ts +13 -0
- package/dist/widgets/recentLookups.test.d.ts +1 -0
- package/dist/{packages/fields/src/widgets → widgets}/types.d.ts +1 -1
- package/package.json +14 -11
- package/src/__tests__/registry-collision.test.ts +91 -0
- package/src/__tests__/resolveFieldCurrency.test.ts +20 -0
- package/src/coerce-safe-value.test.ts +34 -0
- package/src/complex-widgets.test.tsx +58 -7
- package/src/currency.ts +14 -0
- package/src/field-type-coverage.test.ts +65 -0
- package/src/index.tsx +372 -57
- package/src/widgets/CheckboxesField.tsx +53 -0
- package/src/widgets/CurrencyField.tsx +5 -1
- package/src/widgets/GridField.test.tsx +309 -0
- package/src/widgets/GridField.tsx +907 -33
- package/src/widgets/LookupField.tsx +258 -107
- package/src/widgets/MarkdownContent.tsx +19 -0
- package/src/widgets/MultiSelectField.tsx +59 -0
- package/src/widgets/PercentField.tsx +19 -7
- package/src/widgets/RadioField.tsx +41 -0
- package/src/widgets/RecordPickerDialog.tsx +22 -18
- package/src/widgets/SelectField.tsx +23 -2
- package/src/widgets/TagsField.tsx +67 -0
- package/src/widgets/deriveLookupColumns.test.ts +74 -0
- package/src/widgets/deriveLookupColumns.ts +104 -0
- package/src/widgets/recentLookups.test.ts +45 -0
- package/src/widgets/recentLookups.ts +47 -0
- package/src/widgets/useFieldTranslation.ts +30 -0
- package/dist/packages/fields/src/fields-edge-cases.stories.d.ts +0 -45
- package/dist/packages/fields/src/fields.stories.d.ts +0 -56
- package/dist/packages/fields/src/index.d.ts +0 -286
- package/dist/packages/fields/src/record-picker-dialog.stories.d.ts +0 -25
- package/dist/packages/fields/src/widgets/GridField.d.ts +0 -7
- package/src/fields-edge-cases.stories.tsx +0 -407
- package/src/fields.stories.tsx +0 -566
- package/src/record-picker-dialog.stories.tsx +0 -160
- /package/dist/{packages/fields/src/__tests__/validation-feedback.test.d.ts → __tests__/registry-collision.test.d.ts} +0 -0
- /package/dist/{packages/fields/src/complex-widgets.test.d.ts → __tests__/resolveFieldCurrency.test.d.ts} +0 -0
- /package/dist/{packages/fields/src/standard-widgets.test.d.ts → __tests__/validation-feedback.test.d.ts} +0 -0
- /package/dist/{packages/fields/src/datetime-widgets.test.d.ts → coerce-safe-value.test.d.ts} +0 -0
- /package/dist/{packages/fields/src/widgets → widgets}/ImageCropperDialog.d.ts +0 -0
- /package/dist/{packages/fields/src/widgets → widgets}/_cell-renderer-bridge.d.ts +0 -0
- /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
|
-
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dist/{packages/fields/src/datetime-widgets.test.d.ts → coerce-safe-value.test.d.ts}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|