@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.
- package/CHANGELOG.md +203 -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,407 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ObjectUI
|
|
3
|
-
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
-
*
|
|
5
|
-
* This source code is licensed under the MIT license found in the
|
|
6
|
-
* LICENSE file in the root directory of this source tree.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
10
|
-
import React, { useState } from 'react';
|
|
11
|
-
import {
|
|
12
|
-
TextField,
|
|
13
|
-
NumberField,
|
|
14
|
-
SelectField,
|
|
15
|
-
CurrencyField,
|
|
16
|
-
EmailField,
|
|
17
|
-
TextAreaField,
|
|
18
|
-
BooleanField,
|
|
19
|
-
UrlField,
|
|
20
|
-
} from './index';
|
|
21
|
-
import { FieldMetadata } from '@object-ui/types';
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* **Field Widgets – Edge Cases** from `@object-ui/fields`.
|
|
25
|
-
*
|
|
26
|
-
* Stories that exercise boundary conditions: empty values, overflow text,
|
|
27
|
-
* RTL content, emoji-only input, error states, disabled state, and readonly
|
|
28
|
-
* variants across multiple field types.
|
|
29
|
-
*/
|
|
30
|
-
const meta = {
|
|
31
|
-
title: 'Fields/Edge Cases',
|
|
32
|
-
parameters: {
|
|
33
|
-
layout: 'centered',
|
|
34
|
-
},
|
|
35
|
-
tags: ['autodocs'],
|
|
36
|
-
argTypes: {
|
|
37
|
-
readonly: { control: 'boolean', description: 'Toggle readonly mode' },
|
|
38
|
-
disabled: { control: 'boolean', description: 'Toggle disabled mode' },
|
|
39
|
-
},
|
|
40
|
-
} satisfies Meta;
|
|
41
|
-
|
|
42
|
-
export default meta;
|
|
43
|
-
type Story = StoryObj<any>;
|
|
44
|
-
|
|
45
|
-
// Wrapper to handle state since these are controlled components
|
|
46
|
-
const FieldWrapper = ({
|
|
47
|
-
Component,
|
|
48
|
-
field,
|
|
49
|
-
initialValue,
|
|
50
|
-
readonly = false,
|
|
51
|
-
disabled = false,
|
|
52
|
-
errorMessage,
|
|
53
|
-
}: {
|
|
54
|
-
Component: any;
|
|
55
|
-
field: Partial<FieldMetadata>;
|
|
56
|
-
initialValue?: any;
|
|
57
|
-
readonly?: boolean;
|
|
58
|
-
disabled?: boolean;
|
|
59
|
-
errorMessage?: string;
|
|
60
|
-
}) => {
|
|
61
|
-
const [value, setValue] = useState(initialValue);
|
|
62
|
-
|
|
63
|
-
const fullField = {
|
|
64
|
-
name: 'test_field',
|
|
65
|
-
label: 'Test Field',
|
|
66
|
-
type: 'text',
|
|
67
|
-
...field,
|
|
68
|
-
} as FieldMetadata;
|
|
69
|
-
|
|
70
|
-
return (
|
|
71
|
-
<div className="w-[350px] space-y-2 p-4 border rounded-lg shadow-sm bg-white">
|
|
72
|
-
<div className="flex justify-between items-center mb-2">
|
|
73
|
-
<label className="text-sm font-semibold text-gray-700">{fullField.label}</label>
|
|
74
|
-
{readonly && (
|
|
75
|
-
<span className="text-[10px] bg-slate-100 px-2 py-0.5 rounded text-slate-500 font-medium">
|
|
76
|
-
Read Only
|
|
77
|
-
</span>
|
|
78
|
-
)}
|
|
79
|
-
{disabled && (
|
|
80
|
-
<span className="text-[10px] bg-slate-100 px-2 py-0.5 rounded text-slate-500 font-medium">
|
|
81
|
-
Disabled
|
|
82
|
-
</span>
|
|
83
|
-
)}
|
|
84
|
-
</div>
|
|
85
|
-
|
|
86
|
-
<Component
|
|
87
|
-
value={value}
|
|
88
|
-
onChange={(val: any) => {
|
|
89
|
-
console.log('onChange', val);
|
|
90
|
-
setValue(val);
|
|
91
|
-
}}
|
|
92
|
-
field={fullField}
|
|
93
|
-
readonly={readonly}
|
|
94
|
-
disabled={disabled}
|
|
95
|
-
errorMessage={errorMessage}
|
|
96
|
-
/>
|
|
97
|
-
|
|
98
|
-
{errorMessage && (
|
|
99
|
-
<div className="text-xs text-destructive mt-1">{errorMessage}</div>
|
|
100
|
-
)}
|
|
101
|
-
|
|
102
|
-
{!readonly && (
|
|
103
|
-
<div className="text-xs text-muted-foreground mt-4 pt-2 border-t font-mono overflow-hidden text-ellipsis">
|
|
104
|
-
Value: {JSON.stringify(value)}
|
|
105
|
-
</div>
|
|
106
|
-
)}
|
|
107
|
-
</div>
|
|
108
|
-
);
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
// ---------------------------------------------------------------------------
|
|
112
|
-
// 1. Empty / Null / Undefined Values
|
|
113
|
-
// ---------------------------------------------------------------------------
|
|
114
|
-
|
|
115
|
-
export const EmptyText: Story = {
|
|
116
|
-
name: 'Empty – Text (undefined)',
|
|
117
|
-
render: () => (
|
|
118
|
-
<FieldWrapper
|
|
119
|
-
Component={TextField}
|
|
120
|
-
field={{ label: 'Empty Text', type: 'text', placeholder: 'Type here…' }}
|
|
121
|
-
initialValue={undefined}
|
|
122
|
-
/>
|
|
123
|
-
),
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
export const NullNumber: Story = {
|
|
127
|
-
name: 'Empty – Number (null)',
|
|
128
|
-
render: () => (
|
|
129
|
-
<FieldWrapper
|
|
130
|
-
Component={NumberField}
|
|
131
|
-
field={{ label: 'Null Number', type: 'number', precision: 2 }}
|
|
132
|
-
initialValue={null}
|
|
133
|
-
/>
|
|
134
|
-
),
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
export const EmptySelect: Story = {
|
|
138
|
-
name: 'Empty – Select (empty string)',
|
|
139
|
-
render: () => (
|
|
140
|
-
<FieldWrapper
|
|
141
|
-
Component={SelectField}
|
|
142
|
-
field={{
|
|
143
|
-
label: 'No Selection',
|
|
144
|
-
type: 'select',
|
|
145
|
-
options: [
|
|
146
|
-
{ label: 'Option A', value: 'a' },
|
|
147
|
-
{ label: 'Option B', value: 'b' },
|
|
148
|
-
],
|
|
149
|
-
}}
|
|
150
|
-
initialValue=""
|
|
151
|
-
/>
|
|
152
|
-
),
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
// ---------------------------------------------------------------------------
|
|
156
|
-
// 2. Very Long Strings (overflow handling)
|
|
157
|
-
// ---------------------------------------------------------------------------
|
|
158
|
-
|
|
159
|
-
const LONG_STRING =
|
|
160
|
-
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. '.repeat(20).trim();
|
|
161
|
-
|
|
162
|
-
export const LongText: Story = {
|
|
163
|
-
name: 'Overflow – Long Text',
|
|
164
|
-
render: () => (
|
|
165
|
-
<FieldWrapper
|
|
166
|
-
Component={TextField}
|
|
167
|
-
field={{ label: 'Long Value', type: 'text' }}
|
|
168
|
-
initialValue={LONG_STRING}
|
|
169
|
-
/>
|
|
170
|
-
),
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
export const LongTextArea: Story = {
|
|
174
|
-
name: 'Overflow – Long TextArea',
|
|
175
|
-
render: () => (
|
|
176
|
-
<FieldWrapper
|
|
177
|
-
Component={TextAreaField}
|
|
178
|
-
field={{ label: 'Long TextArea', type: 'textarea', rows: 4 }}
|
|
179
|
-
initialValue={LONG_STRING}
|
|
180
|
-
/>
|
|
181
|
-
),
|
|
182
|
-
};
|
|
183
|
-
|
|
184
|
-
export const LongUrl: Story = {
|
|
185
|
-
name: 'Overflow – Long URL',
|
|
186
|
-
render: () => (
|
|
187
|
-
<FieldWrapper
|
|
188
|
-
Component={UrlField}
|
|
189
|
-
field={{ label: 'Long URL', type: 'url' }}
|
|
190
|
-
initialValue={`https://example.com/${'segment/'.repeat(50)}`}
|
|
191
|
-
/>
|
|
192
|
-
),
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
// ---------------------------------------------------------------------------
|
|
196
|
-
// 3. RTL Text (Arabic)
|
|
197
|
-
// ---------------------------------------------------------------------------
|
|
198
|
-
|
|
199
|
-
export const RTLText: Story = {
|
|
200
|
-
name: 'RTL – Arabic Text',
|
|
201
|
-
render: () => (
|
|
202
|
-
<FieldWrapper
|
|
203
|
-
Component={TextField}
|
|
204
|
-
field={{ label: 'Arabic Input', type: 'text' }}
|
|
205
|
-
initialValue="مرحبا بالعالم — هذا نص عربي طويل لاختبار الاتجاه"
|
|
206
|
-
/>
|
|
207
|
-
),
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
export const RTLTextArea: Story = {
|
|
211
|
-
name: 'RTL – Arabic TextArea',
|
|
212
|
-
render: () => (
|
|
213
|
-
<FieldWrapper
|
|
214
|
-
Component={TextAreaField}
|
|
215
|
-
field={{ label: 'Arabic TextArea', type: 'textarea', rows: 3 }}
|
|
216
|
-
initialValue="هذا نص عربي يمتد على عدة أسطر.\nالسطر الثاني هنا.\nالسطر الثالث."
|
|
217
|
-
/>
|
|
218
|
-
),
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
// ---------------------------------------------------------------------------
|
|
222
|
-
// 4. Emoji-Only Values
|
|
223
|
-
// ---------------------------------------------------------------------------
|
|
224
|
-
|
|
225
|
-
export const EmojiText: Story = {
|
|
226
|
-
name: 'Emoji – Text Field',
|
|
227
|
-
render: () => (
|
|
228
|
-
<FieldWrapper
|
|
229
|
-
Component={TextField}
|
|
230
|
-
field={{ label: 'Emoji Only', type: 'text' }}
|
|
231
|
-
initialValue="🚀🔥✨💯🎉🌍"
|
|
232
|
-
/>
|
|
233
|
-
),
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
export const EmojiEmail: Story = {
|
|
237
|
-
name: 'Emoji – Email Field (invalid)',
|
|
238
|
-
render: () => (
|
|
239
|
-
<FieldWrapper
|
|
240
|
-
Component={EmailField}
|
|
241
|
-
field={{ label: 'Emoji Email', type: 'email' }}
|
|
242
|
-
initialValue="🚀@emoji.com"
|
|
243
|
-
/>
|
|
244
|
-
),
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
// ---------------------------------------------------------------------------
|
|
248
|
-
// 5. Error State (with errorMessage prop)
|
|
249
|
-
// ---------------------------------------------------------------------------
|
|
250
|
-
|
|
251
|
-
export const ErrorText: Story = {
|
|
252
|
-
name: 'Error – Text Field',
|
|
253
|
-
render: () => (
|
|
254
|
-
<FieldWrapper
|
|
255
|
-
Component={TextField}
|
|
256
|
-
field={{ label: 'Name', type: 'text', placeholder: 'Required field' }}
|
|
257
|
-
initialValue=""
|
|
258
|
-
errorMessage="This field is required."
|
|
259
|
-
/>
|
|
260
|
-
),
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
export const ErrorNumber: Story = {
|
|
264
|
-
name: 'Error – Number Field',
|
|
265
|
-
render: () => (
|
|
266
|
-
<FieldWrapper
|
|
267
|
-
Component={NumberField}
|
|
268
|
-
field={{ label: 'Age', type: 'number', precision: 0 }}
|
|
269
|
-
initialValue={-5}
|
|
270
|
-
errorMessage="Value must be a positive number."
|
|
271
|
-
/>
|
|
272
|
-
),
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
export const ErrorSelect: Story = {
|
|
276
|
-
name: 'Error – Select Field',
|
|
277
|
-
render: () => (
|
|
278
|
-
<FieldWrapper
|
|
279
|
-
Component={SelectField}
|
|
280
|
-
field={{
|
|
281
|
-
label: 'Priority',
|
|
282
|
-
type: 'select',
|
|
283
|
-
options: [
|
|
284
|
-
{ label: 'Low', value: 'low' },
|
|
285
|
-
{ label: 'Medium', value: 'medium' },
|
|
286
|
-
{ label: 'High', value: 'high' },
|
|
287
|
-
],
|
|
288
|
-
}}
|
|
289
|
-
initialValue=""
|
|
290
|
-
errorMessage="Please select a priority."
|
|
291
|
-
/>
|
|
292
|
-
),
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
// ---------------------------------------------------------------------------
|
|
296
|
-
// 6. Disabled State
|
|
297
|
-
// ---------------------------------------------------------------------------
|
|
298
|
-
|
|
299
|
-
export const DisabledText: Story = {
|
|
300
|
-
name: 'Disabled – Text Field',
|
|
301
|
-
render: () => (
|
|
302
|
-
<FieldWrapper
|
|
303
|
-
Component={TextField}
|
|
304
|
-
field={{ label: 'Locked Name', type: 'text' }}
|
|
305
|
-
initialValue="Cannot change this"
|
|
306
|
-
disabled={true}
|
|
307
|
-
/>
|
|
308
|
-
),
|
|
309
|
-
};
|
|
310
|
-
|
|
311
|
-
export const DisabledNumber: Story = {
|
|
312
|
-
name: 'Disabled – Number Field',
|
|
313
|
-
render: () => (
|
|
314
|
-
<FieldWrapper
|
|
315
|
-
Component={NumberField}
|
|
316
|
-
field={{ label: 'Locked Qty', type: 'number', precision: 0 }}
|
|
317
|
-
initialValue={100}
|
|
318
|
-
disabled={true}
|
|
319
|
-
/>
|
|
320
|
-
),
|
|
321
|
-
};
|
|
322
|
-
|
|
323
|
-
export const DisabledSelect: Story = {
|
|
324
|
-
name: 'Disabled – Select Field',
|
|
325
|
-
render: () => (
|
|
326
|
-
<FieldWrapper
|
|
327
|
-
Component={SelectField}
|
|
328
|
-
field={{
|
|
329
|
-
label: 'Locked Status',
|
|
330
|
-
type: 'select',
|
|
331
|
-
options: [
|
|
332
|
-
{ label: 'Active', value: 'active' },
|
|
333
|
-
{ label: 'Inactive', value: 'inactive' },
|
|
334
|
-
],
|
|
335
|
-
}}
|
|
336
|
-
initialValue="active"
|
|
337
|
-
disabled={true}
|
|
338
|
-
/>
|
|
339
|
-
),
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
export const DisabledBoolean: Story = {
|
|
343
|
-
name: 'Disabled – Boolean Field',
|
|
344
|
-
render: () => (
|
|
345
|
-
<FieldWrapper
|
|
346
|
-
Component={BooleanField}
|
|
347
|
-
field={{ label: 'Locked Toggle', type: 'boolean' }}
|
|
348
|
-
initialValue={true}
|
|
349
|
-
disabled={true}
|
|
350
|
-
/>
|
|
351
|
-
),
|
|
352
|
-
};
|
|
353
|
-
|
|
354
|
-
// ---------------------------------------------------------------------------
|
|
355
|
-
// 7. Readonly State with Various Field Types
|
|
356
|
-
// ---------------------------------------------------------------------------
|
|
357
|
-
|
|
358
|
-
export const ReadonlyGallery: Story = {
|
|
359
|
-
name: 'Readonly – Multiple Fields',
|
|
360
|
-
render: () => (
|
|
361
|
-
<div className="flex flex-col gap-4">
|
|
362
|
-
<FieldWrapper
|
|
363
|
-
Component={TextField}
|
|
364
|
-
field={{ label: 'Read Only Text', type: 'text' }}
|
|
365
|
-
initialValue="Immutable value"
|
|
366
|
-
readonly={true}
|
|
367
|
-
/>
|
|
368
|
-
<FieldWrapper
|
|
369
|
-
Component={NumberField}
|
|
370
|
-
field={{ label: 'Read Only Number', type: 'number', precision: 2 }}
|
|
371
|
-
initialValue={3.14}
|
|
372
|
-
readonly={true}
|
|
373
|
-
/>
|
|
374
|
-
<FieldWrapper
|
|
375
|
-
Component={CurrencyField}
|
|
376
|
-
field={{ label: 'Read Only Currency', type: 'currency', currency: 'USD', precision: 2 }}
|
|
377
|
-
initialValue={9999.99}
|
|
378
|
-
readonly={true}
|
|
379
|
-
/>
|
|
380
|
-
<FieldWrapper
|
|
381
|
-
Component={SelectField}
|
|
382
|
-
field={{
|
|
383
|
-
label: 'Read Only Select',
|
|
384
|
-
type: 'select',
|
|
385
|
-
options: [
|
|
386
|
-
{ label: 'Active', value: 'active' },
|
|
387
|
-
{ label: 'Archived', value: 'archived' },
|
|
388
|
-
],
|
|
389
|
-
}}
|
|
390
|
-
initialValue="active"
|
|
391
|
-
readonly={true}
|
|
392
|
-
/>
|
|
393
|
-
<FieldWrapper
|
|
394
|
-
Component={BooleanField}
|
|
395
|
-
field={{ label: 'Read Only Boolean', type: 'boolean' }}
|
|
396
|
-
initialValue={false}
|
|
397
|
-
readonly={true}
|
|
398
|
-
/>
|
|
399
|
-
<FieldWrapper
|
|
400
|
-
Component={EmailField}
|
|
401
|
-
field={{ label: 'Read Only Email', type: 'email' }}
|
|
402
|
-
initialValue="admin@example.com"
|
|
403
|
-
readonly={true}
|
|
404
|
-
/>
|
|
405
|
-
</div>
|
|
406
|
-
),
|
|
407
|
-
};
|