Skip to content

Commit 16a89db

Browse files
committed
Add stories for field components and update deps
Added a new Storybook file demonstrating all field widgets from @object-ui/fields. Updated package.json and pnpm-lock.yaml to include @object-ui/fields as a devDependency and synchronized related lockfile changes.
1 parent 83d049a commit 16a89db

File tree

3 files changed

+235
-18
lines changed

3 files changed

+235
-18
lines changed

packages/components/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
"tailwindcss": "^4.1.18"
8888
},
8989
"devDependencies": {
90+
"@object-ui/fields": "workspace:*",
9091
"@storybook/addon-essentials": "^8.6.0",
9192
"@storybook/addon-interactions": "^8.6.0",
9293
"@storybook/addon-links": "^8.6.0",
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
import type { Meta, StoryObj } from '@storybook/react';
2+
import React, { useState } from 'react';
3+
import {
4+
TextField,
5+
CurrencyField,
6+
SelectField,
7+
DateField,
8+
BooleanField,
9+
NumberField,
10+
PercentField,
11+
UrlField,
12+
PhoneField,
13+
EmailField,
14+
PasswordField,
15+
TextAreaField,
16+
AutoNumberField,
17+
LookupField
18+
} from '@object-ui/fields';
19+
import { FieldMetadata } from '@object-ui/types';
20+
21+
/**
22+
* **Field Widgets** from `@object-ui/fields`.
23+
*
24+
* These components handle data formatting, validation, and display logic for specific data types.
25+
* They are typically used within `ObjectForm` or `ObjectGrid` but can be used standalone.
26+
*
27+
* Note: These widgets implement the `FieldWidgetProps` interface.
28+
*/
29+
const meta = {
30+
title: 'Schema/Fields',
31+
parameters: {
32+
layout: 'centered',
33+
},
34+
tags: ['autodocs'],
35+
} satisfies Meta;
36+
37+
export default meta;
38+
type Story = StoryObj<any>;
39+
40+
// Wrapper to handle state since these are controlled components
41+
const FieldWrapper = ({
42+
Component,
43+
field,
44+
initialValue,
45+
readonly = false
46+
}: {
47+
Component: any,
48+
field: Partial<FieldMetadata>,
49+
initialValue?: any,
50+
readonly?: boolean
51+
}) => {
52+
const [value, setValue] = useState(initialValue);
53+
54+
// Ensure field has minimal required props
55+
const fullField = {
56+
name: 'test_field',
57+
label: 'Test Field',
58+
type: 'text',
59+
...field
60+
} as FieldMetadata;
61+
62+
return (
63+
<div className="w-[300px] space-y-2 p-4 border rounded-lg">
64+
<div className="flex justify-between items-center">
65+
<label className="text-sm font-medium">{fullField.label}</label>
66+
{readonly && <span className="text-[10px] bg-gray-100 px-1 rounded">Read Only</span>}
67+
</div>
68+
69+
<Component
70+
value={value}
71+
onChange={(val: any) => {
72+
console.log('onChange', val);
73+
setValue(val);
74+
}}
75+
field={fullField}
76+
readonly={readonly}
77+
/>
78+
79+
{!readonly && (
80+
<div className="text-xs text-muted-foreground mt-4 pt-2 border-t font-mono">
81+
Value: {JSON.stringify(value)}
82+
</div>
83+
)}
84+
</div>
85+
);
86+
};
87+
88+
export const Text: Story = {
89+
render: () => (
90+
<FieldWrapper
91+
Component={TextField}
92+
field={{ label: 'Deal Name', type: 'text', placeholder: 'Enter deal name...' }}
93+
initialValue="Big Enterprise Deal"
94+
/>
95+
)
96+
};
97+
98+
export const TextArea: Story = {
99+
render: () => (
100+
<FieldWrapper
101+
Component={TextAreaField}
102+
field={{ label: 'Description', type: 'textarea', rows: 4 }}
103+
initialValue="This is a multi-line description text area."
104+
/>
105+
)
106+
};
107+
108+
export const Number: Story = {
109+
render: () => (
110+
<FieldWrapper
111+
Component={NumberField}
112+
field={{ label: 'Quantity', type: 'number', scale: 0 }}
113+
initialValue={42}
114+
/>
115+
)
116+
};
117+
118+
export const Currency: Story = {
119+
render: () => (
120+
<FieldWrapper
121+
Component={CurrencyField}
122+
field={{ label: 'Amount', type: 'currency', currency: 'USD', precision: 2 }}
123+
initialValue={1234567.89}
124+
/>
125+
)
126+
};
127+
128+
export const Percent: Story = {
129+
render: () => (
130+
<FieldWrapper
131+
Component={PercentField}
132+
field={{ label: 'Probability', type: 'percent', precision: 2 }}
133+
initialValue={0.75}
134+
/>
135+
)
136+
};
137+
138+
export const Boolean: Story = {
139+
render: () => (
140+
<FieldWrapper
141+
Component={BooleanField}
142+
field={{ label: 'Is Active?', type: 'boolean' }}
143+
initialValue={true}
144+
/>
145+
)
146+
};
147+
148+
export const Date: Story = {
149+
render: () => (
150+
<FieldWrapper
151+
Component={DateField}
152+
field={{ label: 'Close Date', type: 'date' }}
153+
initialValue={new Date().toISOString()}
154+
/>
155+
)
156+
};
157+
158+
export const Select: Story = {
159+
render: () => (
160+
<FieldWrapper
161+
Component={SelectField}
162+
field={{
163+
label: 'Stage',
164+
type: 'select',
165+
options: [
166+
{ label: 'Prospecting', value: 'prospecting' },
167+
{ label: 'Qualification', value: 'qualification' },
168+
{ label: 'Proposal', value: 'proposal' },
169+
{ label: 'Closed Won', value: 'closed_won' },
170+
{ label: 'Closed Lost', value: 'closed_lost' },
171+
]
172+
}}
173+
initialValue="proposal"
174+
/>
175+
)
176+
};
177+
178+
export const Password: Story = {
179+
render: () => (
180+
<FieldWrapper
181+
Component={PasswordField}
182+
field={{ label: 'Secret Key', type: 'password' }}
183+
initialValue="supersecret"
184+
/>
185+
)
186+
};
187+
188+
export const ReadOnly: Story = {
189+
render: () => (
190+
<div className="flex flex-col gap-4">
191+
<FieldWrapper
192+
Component={TextField}
193+
field={{ label: 'Read Only Text', type: 'text' }}
194+
initialValue="You cannot edit this"
195+
readonly={true}
196+
/>
197+
<FieldWrapper
198+
Component={CurrencyField}
199+
field={{ label: 'Read Only Currency', type: 'currency' }}
200+
initialValue={9999.99}
201+
readonly={true}
202+
/>
203+
</div>
204+
)
205+
};

pnpm-lock.yaml

Lines changed: 29 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)