@object-ui/fields 0.3.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 (34) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -0
  3. package/dist/fields/src/index.d.ts +143 -0
  4. package/dist/fields/src/widgets/BooleanField.d.ts +2 -0
  5. package/dist/fields/src/widgets/CurrencyField.d.ts +2 -0
  6. package/dist/fields/src/widgets/DateField.d.ts +2 -0
  7. package/dist/fields/src/widgets/EmailField.d.ts +2 -0
  8. package/dist/fields/src/widgets/LookupField.d.ts +6 -0
  9. package/dist/fields/src/widgets/NumberField.d.ts +2 -0
  10. package/dist/fields/src/widgets/PhoneField.d.ts +2 -0
  11. package/dist/fields/src/widgets/RichTextField.d.ts +7 -0
  12. package/dist/fields/src/widgets/SelectField.d.ts +2 -0
  13. package/dist/fields/src/widgets/TextAreaField.d.ts +2 -0
  14. package/dist/fields/src/widgets/TextField.d.ts +2 -0
  15. package/dist/fields/src/widgets/UrlField.d.ts +2 -0
  16. package/dist/fields/src/widgets/types.d.ts +9 -0
  17. package/dist/index.cjs +6 -0
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.js +1060 -0
  20. package/package.json +52 -0
  21. package/src/index.tsx +775 -0
  22. package/src/widgets/BooleanField.tsx +40 -0
  23. package/src/widgets/CurrencyField.tsx +62 -0
  24. package/src/widgets/DateField.tsx +19 -0
  25. package/src/widgets/EmailField.tsx +29 -0
  26. package/src/widgets/LookupField.tsx +186 -0
  27. package/src/widgets/NumberField.tsx +27 -0
  28. package/src/widgets/PhoneField.tsx +29 -0
  29. package/src/widgets/RichTextField.tsx +42 -0
  30. package/src/widgets/SelectField.tsx +38 -0
  31. package/src/widgets/TextAreaField.tsx +41 -0
  32. package/src/widgets/TextField.tsx +36 -0
  33. package/src/widgets/UrlField.tsx +38 -0
  34. package/src/widgets/types.ts +11 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 ObjectQL
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # @object-ui/fields
2
+
3
+ The standard field library and registry for Object UI.
4
+
5
+ ## Features
6
+
7
+ - 📚 **Standard Fields** - Implementation of all ObjectStack protocol fields (Text, Number, Date, Lookup, etc.)
8
+ - 🔌 **Plugin System** - `FieldRegistry` allows registering custom renderers or overriding standard ones.
9
+ - 🛠 **Helpers** - Utilities for schema mapping, validation, and expression evaluation.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @object-ui/fields
15
+ ```
16
+
17
+ ## Field Registry
18
+
19
+ The Field Registry is the core mechanism that allows decoupling view components from specific field implementations.
20
+
21
+ ### Registering a Custom Field
22
+
23
+ You can override standard fields or add new ones:
24
+
25
+ ```tsx
26
+ import { registerFieldRenderer } from '@object-ui/fields';
27
+ import { MyCustomColorPicker } from './MyCustomColorPicker';
28
+
29
+ // Register a new 'color' field type
30
+ registerFieldRenderer('color', MyCustomColorPicker);
31
+ ```
32
+
33
+ ### Using Standard Fields
34
+
35
+ View components use `getCellRenderer` to resolve the correct component for a field type.
36
+
37
+ ```tsx
38
+ import { getCellRenderer } from '@object-ui/fields';
39
+
40
+ const MyGridCell = ({ field, value }) => {
41
+ const Renderer = getCellRenderer(field.type);
42
+ return <Renderer field={field} value={value} />;
43
+ };
44
+ ```
45
+
46
+ ## Standard Field Types
47
+
48
+ Supported types out of the box:
49
+
50
+ - **Basic**: `text`, `textarea`, `number`, `boolean`
51
+ - **Format**: `currency`, `percent`
52
+ - **Date**: `date`, `datetime`, `time`
53
+ - **Selection**: `select`, `lookup`, `master_detail`
54
+ - **Contact**: `email`, `phone`, `url`
55
+ - **Media**: `file`, `image`
56
+ - **System**: `formula`, `summary`, `auto_number`
@@ -0,0 +1,143 @@
1
+ import { default as React } from 'react';
2
+ import { FieldMetadata } from '../../types/src';
3
+ /**
4
+ * Cell renderer props
5
+ */
6
+ export interface CellRendererProps {
7
+ value: any;
8
+ field: FieldMetadata;
9
+ isEditing?: boolean;
10
+ onChange?: (value: any) => void;
11
+ }
12
+ /**
13
+ * Format currency value
14
+ */
15
+ export declare function formatCurrency(value: number, currency?: string): string;
16
+ /**
17
+ * Format percent value
18
+ */
19
+ export declare function formatPercent(value: number, precision?: number): string;
20
+ /**
21
+ * Format date value
22
+ */
23
+ export declare function formatDate(value: string | Date, _format?: string): string;
24
+ /**
25
+ * Format datetime value
26
+ */
27
+ export declare function formatDateTime(value: string | Date): string;
28
+ /**
29
+ * Text field cell renderer
30
+ */
31
+ export declare function TextCellRenderer({ value }: CellRendererProps): React.ReactElement;
32
+ /**
33
+ * Number field cell renderer
34
+ */
35
+ export declare function NumberCellRenderer({ value, field }: CellRendererProps): React.ReactElement;
36
+ /**
37
+ * Currency field cell renderer
38
+ */
39
+ export declare function CurrencyCellRenderer({ value, field }: CellRendererProps): React.ReactElement;
40
+ /**
41
+ * Percent field cell renderer
42
+ */
43
+ export declare function PercentCellRenderer({ value, field }: CellRendererProps): React.ReactElement;
44
+ /**
45
+ * Boolean field cell renderer
46
+ */
47
+ export declare function BooleanCellRenderer({ value }: CellRendererProps): React.ReactElement;
48
+ /**
49
+ * Date field cell renderer
50
+ */
51
+ export declare function DateCellRenderer({ value, field }: CellRendererProps): React.ReactElement;
52
+ /**
53
+ * DateTime field cell renderer
54
+ */
55
+ export declare function DateTimeCellRenderer({ value }: CellRendererProps): React.ReactElement;
56
+ /**
57
+ * Select field cell renderer (with badges)
58
+ */
59
+ export declare function SelectCellRenderer({ value, field }: CellRendererProps): React.ReactElement;
60
+ /**
61
+ * Email field cell renderer
62
+ */
63
+ export declare function EmailCellRenderer({ value }: CellRendererProps): React.ReactElement;
64
+ /**
65
+ * URL field cell renderer
66
+ */
67
+ export declare function UrlCellRenderer({ value }: CellRendererProps): React.ReactElement;
68
+ /**
69
+ * Phone field cell renderer
70
+ */
71
+ export declare function PhoneCellRenderer({ value }: CellRendererProps): React.ReactElement;
72
+ /**
73
+ * File field cell renderer
74
+ */
75
+ export declare function FileCellRenderer({ value, field }: CellRendererProps): React.ReactElement;
76
+ /**
77
+ * Image field cell renderer (with thumbnails)
78
+ */
79
+ export declare function ImageCellRenderer({ value }: CellRendererProps): React.ReactElement;
80
+ /**
81
+ * Lookup/Master-Detail field cell renderer
82
+ */
83
+ export declare function LookupCellRenderer({ value }: CellRendererProps): React.ReactElement;
84
+ /**
85
+ * Formula field cell renderer (read-only)
86
+ */
87
+ export declare function FormulaCellRenderer({ value }: CellRendererProps): React.ReactElement;
88
+ /**
89
+ * User/Owner field cell renderer (with avatars)
90
+ */
91
+ export declare function UserCellRenderer({ value }: CellRendererProps): React.ReactElement;
92
+ /**
93
+ * Register a custom field renderer
94
+ * @param type Field type (e.g. 'text', 'location', 'my-custom-type')
95
+ * @param renderer React component to render the field
96
+ */
97
+ export declare function registerFieldRenderer(type: string, renderer: React.FC<CellRendererProps>): void;
98
+ /**
99
+ * Get the appropriate cell renderer for a field type
100
+ */
101
+ export declare function getCellRenderer(fieldType: string): React.FC<CellRendererProps>;
102
+ /**
103
+ * Map field type to form component type
104
+ *
105
+ * @param fieldType - The ObjectQL field type identifier to convert
106
+ * (for example: `"text"`, `"number"`, `"date"`, `"lookup"`).
107
+ * @returns The normalized form field type string used in the form schema
108
+ * (for example: `"input"`, `"textarea"`, `"date-picker"`, `"select"`).
109
+ */
110
+ export declare function mapFieldTypeToFormType(fieldType: string): string;
111
+ /**
112
+ * Formats file size in bytes to human-readable string
113
+ * @param bytes - File size in bytes (must be non-negative)
114
+ * @returns Formatted string (e.g., "5 MB", "1.5 GB")
115
+ */
116
+ export declare function formatFileSize(bytes: number): string;
117
+ /**
118
+ * Build validation rules from field metadata
119
+ * @param field - Field metadata from ObjectStack
120
+ * @returns Validation rule object compatible with react-hook-form
121
+ */
122
+ export declare function buildValidationRules(field: any): any;
123
+ /**
124
+ * Evaluate a conditional expression for field visibility
125
+ * @param condition - Condition object from field metadata
126
+ * @param formData - Current form values
127
+ * @returns Whether the condition is met
128
+ */
129
+ export declare function evaluateCondition(condition: any, formData: any): boolean;
130
+ export declare function registerFields(): void;
131
+ export * from './widgets/types';
132
+ export * from './widgets/TextField';
133
+ export * from './widgets/NumberField';
134
+ export * from './widgets/BooleanField';
135
+ export * from './widgets/SelectField';
136
+ export * from './widgets/DateField';
137
+ export * from './widgets/EmailField';
138
+ export * from './widgets/PhoneField';
139
+ export * from './widgets/UrlField';
140
+ export * from './widgets/CurrencyField';
141
+ export * from './widgets/TextAreaField';
142
+ export * from './widgets/RichTextField';
143
+ export * from './widgets/LookupField';
@@ -0,0 +1,2 @@
1
+ import { FieldWidgetProps } from './types';
2
+ export declare function BooleanField({ value, onChange, field, readonly, ...props }: FieldWidgetProps<boolean>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import { FieldWidgetProps } from './types';
2
+ export declare function CurrencyField({ value, onChange, field, readonly, errorMessage, ...props }: FieldWidgetProps<number>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import { FieldWidgetProps } from './types';
2
+ export declare function DateField({ value, onChange, field, readonly, ...props }: FieldWidgetProps<string>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import { FieldWidgetProps } from './types';
2
+ export declare function EmailField({ value, onChange, field, readonly, errorMessage, ...props }: FieldWidgetProps<string>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import { FieldWidgetProps } from './types';
2
+ /**
3
+ * Lookup field for selecting related records
4
+ * Supports single and multi-select with search
5
+ */
6
+ export declare function LookupField({ value, onChange, field, readonly }: FieldWidgetProps<any>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import { FieldWidgetProps } from './types';
2
+ export declare function NumberField({ value, onChange, field, readonly, ...props }: FieldWidgetProps<number>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import { FieldWidgetProps } from './types';
2
+ export declare function PhoneField({ value, onChange, field, readonly, errorMessage, ...props }: FieldWidgetProps<string>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,7 @@
1
+ import { FieldWidgetProps } from './types';
2
+ /**
3
+ * Rich text field with markdown/HTML support
4
+ * For now, this is a simple textarea. A full implementation would use
5
+ * a rich text editor like TipTap, Lexical, or Slate.
6
+ */
7
+ export declare function RichTextField({ value, onChange, field, readonly, errorMessage, ...props }: FieldWidgetProps<string>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import { FieldWidgetProps } from './types';
2
+ export declare function SelectField({ value, onChange, field, readonly, ...props }: FieldWidgetProps<string>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import { FieldWidgetProps } from './types';
2
+ export declare function TextAreaField({ value, onChange, field, readonly, errorMessage, ...props }: FieldWidgetProps<string>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import { FieldWidgetProps } from './types';
2
+ export declare function TextField({ value, onChange, field, readonly, ...props }: FieldWidgetProps<string>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import { FieldWidgetProps } from './types';
2
+ export declare function UrlField({ value, onChange, field, readonly, errorMessage, ...props }: FieldWidgetProps<string>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { FieldMetadata } from '../../../types/src';
2
+ export type FieldWidgetProps<T = any> = {
3
+ value: T;
4
+ onChange: (val: T) => void;
5
+ field: FieldMetadata;
6
+ readonly?: boolean;
7
+ className?: string;
8
+ errorMessage?: string;
9
+ };
package/dist/index.cjs ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const z=require("react"),c=require("@object-ui/components"),O=require("lucide-react"),f=require("@object-ui/core");var A={exports:{}},F={};var ce;function Be(){if(ce)return F;ce=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function a(s,l,i){var o=null;if(i!==void 0&&(o=""+i),l.key!==void 0&&(o=""+l.key),"key"in l){i={};for(var d in l)d!=="key"&&(i[d]=l[d])}else i=l;return l=i.ref,{$$typeof:e,type:s,key:o,ref:l!==void 0?l:null,props:i}}return F.Fragment=t,F.jsx=a,F.jsxs=a,F}var k={};var ue;function Le(){return ue||(ue=1,process.env.NODE_ENV!=="production"&&(function(){function e(n){if(n==null)return null;if(typeof n=="function")return n.$$typeof===De?null:n.displayName||n.name||null;if(typeof n=="string")return n;switch(n){case m:return"Fragment";case w:return"Profiler";case y:return"StrictMode";case Ae:return"Suspense";case Pe:return"SuspenseList";case $e:return"Activity"}if(typeof n=="object")switch(typeof n.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),n.$$typeof){case D:return"Portal";case Ee:return n.displayName||"Context";case I:return(n._context.displayName||"Context")+".Consumer";case Se:var u=n.render;return n=n.displayName,n||(n=u.displayName||u.name||"",n=n!==""?"ForwardRef("+n+")":"ForwardRef"),n;case Oe:return u=n.displayName||null,u!==null?u:e(n.type)||"Memo";case U:u=n._payload,n=n._init;try{return e(n(u))}catch{}}return null}function t(n){return""+n}function a(n){try{t(n);var u=!1}catch{u=!0}if(u){u=console;var x=u.error,h=typeof Symbol=="function"&&Symbol.toStringTag&&n[Symbol.toStringTag]||n.constructor.name||"Object";return x.call(u,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",h),t(n)}}function s(n){if(n===m)return"<>";if(typeof n=="object"&&n!==null&&n.$$typeof===U)return"<...>";try{var u=e(n);return u?"<"+u+">":"<...>"}catch{return"<...>"}}function l(){var n=B.A;return n===null?null:n.getOwner()}function i(){return Error("react-stack-top-frame")}function o(n){if(ne.call(n,"key")){var u=Object.getOwnPropertyDescriptor(n,"key").get;if(u&&u.isReactWarning)return!1}return n.key!==void 0}function d(n,u){function x(){ae||(ae=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",u))}x.isReactWarning=!0,Object.defineProperty(n,"key",{get:x,configurable:!0})}function p(){var n=e(this.type);return se[n]||(se[n]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),n=this.props.ref,n!==void 0?n:null}function j(n,u,x,h,S,M){var g=x.ref;return n={$$typeof:E,type:n,key:u,props:x,_owner:h},(g!==void 0?g:null)!==null?Object.defineProperty(n,"ref",{enumerable:!1,get:p}):Object.defineProperty(n,"ref",{enumerable:!1,value:null}),n._store={},Object.defineProperty(n._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(n,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(n,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:S}),Object.defineProperty(n,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:M}),Object.freeze&&(Object.freeze(n.props),Object.freeze(n)),n}function b(n,u,x,h,S,M){var g=u.children;if(g!==void 0)if(h)if(Ie(g)){for(h=0;h<g.length;h++)R(g[h]);Object.freeze&&Object.freeze(g)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else R(g);if(ne.call(u,"key")){g=e(n);var _=Object.keys(u).filter(function(Ue){return Ue!=="key"});h=0<_.length?"{key: someKey, "+_.join(": ..., ")+": ...}":"{key: someKey}",oe[g+h]||(_=0<_.length?"{"+_.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
2
+ let props = %s;
3
+ <%s {...props} />
4
+ React keys must be passed directly to JSX without using spread:
5
+ let props = %s;
6
+ <%s key={someKey} {...props} />`,h,g,_,g),oe[g+h]=!0)}if(g=null,x!==void 0&&(a(x),g=""+x),o(u)&&(a(u.key),g=""+u.key),"key"in u){x={};for(var Y in u)Y!=="key"&&(x[Y]=u[Y])}else x=u;return g&&d(x,typeof n=="function"?n.displayName||n.name||"Unknown":n),j(n,g,x,l(),S,M)}function R(n){v(n)?n._store&&(n._store.validated=1):typeof n=="object"&&n!==null&&n.$$typeof===U&&(n._payload.status==="fulfilled"?v(n._payload.value)&&n._payload.value._store&&(n._payload.value._store.validated=1):n._store&&(n._store.validated=1))}function v(n){return typeof n=="object"&&n!==null&&n.$$typeof===E}var N=z,E=Symbol.for("react.transitional.element"),D=Symbol.for("react.portal"),m=Symbol.for("react.fragment"),y=Symbol.for("react.strict_mode"),w=Symbol.for("react.profiler"),I=Symbol.for("react.consumer"),Ee=Symbol.for("react.context"),Se=Symbol.for("react.forward_ref"),Ae=Symbol.for("react.suspense"),Pe=Symbol.for("react.suspense_list"),Oe=Symbol.for("react.memo"),U=Symbol.for("react.lazy"),$e=Symbol.for("react.activity"),De=Symbol.for("react.client.reference"),B=N.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,ne=Object.prototype.hasOwnProperty,Ie=Array.isArray,L=console.createTask?console.createTask:function(){return null};N={react_stack_bottom_frame:function(n){return n()}};var ae,se={},le=N.react_stack_bottom_frame.bind(N,i)(),ie=L(s(i)),oe={};k.Fragment=m,k.jsx=function(n,u,x){var h=1e4>B.recentlyCreatedOwnerStacks++;return b(n,u,x,!1,h?Error("react-stack-top-frame"):le,h?L(s(n)):ie)},k.jsxs=function(n,u,x){var h=1e4>B.recentlyCreatedOwnerStacks++;return b(n,u,x,!0,h?Error("react-stack-top-frame"):le,h?L(s(n)):ie)}})()),k}var me;function Me(){return me||(me=1,process.env.NODE_ENV==="production"?A.exports=Be():A.exports=Le()),A.exports}var r=Me();function V({value:e,onChange:t,field:a,readonly:s,...l}){if(s)return r.jsx("span",{className:"text-sm",children:e||"-"});const i=a.rows;return i&&i>1?r.jsx(c.Textarea,{value:e||"",onChange:o=>t(o.target.value),placeholder:a.placeholder,disabled:s,className:l.className}):r.jsx(c.Input,{type:a.type==="password"?"password":"text",value:e||"",onChange:o=>t(o.target.value),placeholder:a.placeholder,disabled:s,className:l.className})}function q({value:e,onChange:t,field:a,readonly:s,...l}){if(s)return r.jsx("span",{className:"text-sm",children:e??"-"});const i=a.precision;return r.jsx(c.Input,{type:"number",value:e??"",onChange:o=>{const d=o.target.value;t(d===""?null:Number(d))},placeholder:a.placeholder,disabled:s,step:i?Math.pow(10,-i):"any",className:l.className})}function de({value:e,onChange:t,field:a,readonly:s,...l}){return s?r.jsx("span",{className:"text-sm",children:e?"Yes":"No"}):a.widget==="checkbox"?r.jsxs("div",{className:"flex items-center space-x-2",children:[r.jsx(c.Checkbox,{id:a.name,checked:!!e,onCheckedChange:o=>t(!!o),disabled:s,className:l.className}),r.jsx(c.Label,{htmlFor:a.name,children:a.label})]}):r.jsxs("div",{className:"flex items-center space-x-2",children:[r.jsx(c.Switch,{id:a.name,checked:!!e,onCheckedChange:t,disabled:s,className:l.className}),r.jsx(c.Label,{htmlFor:a.name,children:a.label})]})}function pe({value:e,onChange:t,field:a,readonly:s,...l}){const i=a.options||[];if(s){const o=i.find(d=>d.value===e);return r.jsx("span",{className:"text-sm",children:o?.label||e||"-"})}return r.jsxs(c.Select,{value:e,onValueChange:t,disabled:s,children:[r.jsx(c.SelectTrigger,{className:l.className,children:r.jsx(c.SelectValue,{placeholder:a.placeholder||"Select an option"})}),r.jsx(c.SelectContent,{children:i.map(o=>r.jsx(c.SelectItem,{value:o.value,children:o.label},o.value))})]})}function xe({value:e,onChange:t,field:a,readonly:s,...l}){return s?r.jsx("span",{className:"text-sm",children:e?new Date(e).toLocaleDateString():"-"}):r.jsx(c.Input,{type:"date",value:e||"",onChange:i=>t(i.target.value),disabled:s,className:l.className})}function W({value:e,onChange:t,field:a,readonly:s,errorMessage:l,...i}){return s?e?r.jsx("a",{href:`mailto:${e}`,className:"text-sm text-blue-600 hover:text-blue-800 hover:underline",children:e}):r.jsx("span",{className:"text-sm",children:"-"}):r.jsx(c.Input,{type:"email",value:e||"",onChange:o=>t(o.target.value),placeholder:a.placeholder||"email@example.com",disabled:s,className:i.className,"aria-invalid":!!l})}function G({value:e,onChange:t,field:a,readonly:s,errorMessage:l,...i}){return s?e?r.jsx("a",{href:`tel:${e}`,className:"text-sm text-blue-600 hover:text-blue-800 hover:underline",children:e}):r.jsx("span",{className:"text-sm",children:"-"}):r.jsx(c.Input,{type:"tel",value:e||"",onChange:o=>t(o.target.value),placeholder:a.placeholder||"(555) 123-4567",disabled:s,className:i.className,"aria-invalid":!!l})}function J({value:e,onChange:t,field:a,readonly:s,errorMessage:l,...i}){return s?e?e.startsWith("http://")||e.startsWith("https://")?r.jsx("a",{href:e,target:"_blank",rel:"noopener noreferrer",className:"text-sm text-blue-600 hover:text-blue-800 hover:underline",children:e}):r.jsx("span",{className:"text-sm",children:e}):r.jsx("span",{className:"text-sm",children:"-"}):r.jsx(c.Input,{type:"url",value:e||"",onChange:o=>t(o.target.value),placeholder:a.placeholder||"https://example.com",disabled:s,className:i.className,"aria-invalid":!!l})}function Ye(e,t="USD"){try{return new Intl.NumberFormat("en-US",{style:"currency",currency:t}).format(e)}catch{return`${t} ${e.toFixed(2)}`}}function X({value:e,onChange:t,field:a,readonly:s,errorMessage:l,...i}){const o=a,d=o.currency||"USD",p=o.precision??2;if(s)return e==null?r.jsx("span",{className:"text-sm",children:"-"}):r.jsx("span",{className:"text-sm font-medium tabular-nums",children:Ye(Number(e),d)});const j=b=>{const R=parseFloat(b.target.value);isNaN(R)||t(parseFloat(R.toFixed(p)))};return r.jsxs("div",{className:"relative",children:[r.jsx("span",{className:"absolute left-3 top-1/2 -translate-y-1/2 text-sm text-gray-500",children:d==="USD"?"$":d}),r.jsx(c.Input,{type:"number",value:e??"",onChange:b=>{const R=b.target.value===""?null:parseFloat(b.target.value);t(R)},onBlur:j,placeholder:a.placeholder||"0.00",disabled:s,className:`pl-8 ${i.className||""}`,step:Math.pow(10,-p).toFixed(p),"aria-invalid":!!l})]})}function H({value:e,onChange:t,field:a,readonly:s,errorMessage:l,...i}){if(s)return r.jsx("div",{className:"text-sm whitespace-pre-wrap",children:e||"-"});const o=a,d=o.rows||4,p=o.max_length;return r.jsxs("div",{className:"relative",children:[r.jsx(c.Textarea,{value:e||"",onChange:j=>t(j.target.value),placeholder:a.placeholder,disabled:s,rows:d,maxLength:p,className:i.className,"aria-invalid":!!l}),p&&r.jsxs("div",{className:"absolute bottom-2 right-2 text-xs text-gray-400","aria-live":"polite","aria-label":`Character count: ${(e||"").length} of ${p}`,children:[(e||"").length,"/",p]})]})}function Q({value:e,onChange:t,field:a,readonly:s,errorMessage:l,...i}){if(s)return r.jsx("div",{className:"text-sm prose prose-sm max-w-none",children:e||"-"});const o=a,d=o.rows||8,p=o.format||"markdown";return r.jsxs("div",{className:"space-y-2",children:[r.jsxs("div",{className:"flex items-center justify-between text-xs text-gray-500",children:[r.jsxs("span",{children:["Format: ",p]}),r.jsx("span",{className:"italic",children:"Rich text editor (basic)"})]}),r.jsx(c.Textarea,{value:e||"",onChange:j=>t(j.target.value),placeholder:a.placeholder||"Enter text...",disabled:s,rows:d,className:`font-mono text-sm ${i.className||""}`,"aria-invalid":!!l})]})}function P({value:e,onChange:t,field:a,readonly:s}){const[l,i]=z.useState(!1),[o,d]=z.useState(""),p=a,j=p.options||[],b=p.multiple||!1,R=p.display_field||"label",v=j.filter(m=>m.label.toLowerCase().includes(o.toLowerCase())),N=b?(Array.isArray(e)?e:[]).map(m=>j.find(y=>y.value===m)).filter(Boolean):e?[j.find(m=>m.value===e)].filter(Boolean):[],E=m=>{if(b){const y=Array.isArray(e)?e:[],w=y.includes(m.value);t(w?y.filter(I=>I!==m.value):[...y,m.value])}else t(m.value),i(!1)},D=m=>{if(b){const y=Array.isArray(e)?e:[];t(y.filter(w=>w!==m))}else t(null)};return s?N.length?b?r.jsx("div",{className:"flex flex-wrap gap-1",children:N.map((m,y)=>r.jsx(c.Badge,{variant:"outline",children:m?.[R]||m?.label},y))}):r.jsx("span",{className:"text-sm",children:N[0]?.[R]||N[0]?.label}):r.jsx("span",{className:"text-sm",children:"-"}):r.jsxs("div",{className:"space-y-2",children:[N.length>0&&r.jsx("div",{className:"flex flex-wrap gap-1",children:N.map((m,y)=>r.jsxs(c.Badge,{variant:"outline",className:"gap-1",children:[m?.[R]||m?.label,r.jsx("button",{onClick:()=>D(m?.value),className:"ml-1 hover:text-destructive",type:"button","aria-label":`Remove ${m?.[R]||m?.label}`,children:r.jsx(O.X,{className:"size-3"})})]},y))}),r.jsxs(c.Dialog,{open:l,onOpenChange:i,children:[r.jsx(c.DialogTrigger,{asChild:!0,children:r.jsxs(c.Button,{variant:"outline",className:"w-full justify-start text-left font-normal",type:"button",children:[r.jsx(O.Search,{className:"mr-2 size-4"}),N.length===0?a.placeholder||"Select...":b?`${N.length} selected`:"Change selection"]})}),r.jsxs(c.DialogContent,{className:"max-w-md",children:[r.jsx(c.DialogHeader,{children:r.jsxs(c.DialogTitle,{children:[a.label||"Select"," ",b&&"(multiple)"]})}),r.jsxs("div",{className:"space-y-4",children:[r.jsx(c.Input,{placeholder:"Search...",value:o,onChange:m=>d(m.target.value),className:"w-full"}),r.jsx("div",{className:"max-h-64 overflow-y-auto space-y-1",children:v.length===0?r.jsx("p",{className:"text-sm text-gray-500 text-center py-4",children:"No options found"}):v.map(m=>{const y=b?(Array.isArray(e)?e:[]).includes(m.value):e===m.value;return r.jsxs("button",{onClick:()=>E(m),className:`w-full text-left px-3 py-2 rounded-md text-sm hover:bg-gray-100 flex items-center justify-between ${y?"bg-blue-50 text-blue-700":""}`,type:"button",children:[r.jsx("span",{children:m.label}),y&&r.jsx(c.Badge,{variant:"default",className:"ml-2",children:"Selected"})]},m.value)})})]})]})]})]})}function fe(e,t="USD"){try{return new Intl.NumberFormat("en-US",{style:"currency",currency:t}).format(e)}catch{return`${t} ${e.toFixed(2)}`}}function he(e,t=2){return`${(e*100).toFixed(t)}%`}function ge(e,t){if(!e)return"-";const a=typeof e=="string"?new Date(e):e;return isNaN(a.getTime())?"-":a.toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}function be(e){if(!e)return"-";const t=typeof e=="string"?new Date(e):e;return isNaN(t.getTime())?"-":t.toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}function C({value:e}){return r.jsx("span",{className:"truncate",children:e||"-"})}function je({value:e,field:t}){if(e==null)return r.jsx("span",{children:"-"});const s=t.precision??0,l=typeof e=="number"?e.toFixed(s):e;return r.jsx("span",{className:"tabular-nums",children:l})}function ye({value:e,field:t}){if(e==null)return r.jsx("span",{children:"-"});const s=t.currency||"USD",l=fe(Number(e),s);return r.jsx("span",{className:"tabular-nums font-medium",children:l})}function Ne({value:e,field:t}){if(e==null)return r.jsx("span",{children:"-"});const s=t.precision??2,l=he(Number(e),s);return r.jsx("span",{className:"tabular-nums",children:l})}function Re({value:e}){return r.jsx("div",{className:"flex items-center",children:e?r.jsxs(c.Badge,{variant:"outline",className:"bg-green-50 text-green-700 border-green-200 gap-1",children:[r.jsx(O.Check,{className:"size-3"}),"True"]}):r.jsxs(c.Badge,{variant:"outline",className:"bg-gray-50 text-gray-500 border-gray-200 gap-1",children:[r.jsx(O.X,{className:"size-3"}),"False"]})})}function Ce({value:e,field:t}){const s=ge(e,t.format);return r.jsx("span",{className:"tabular-nums",children:s})}function ve({value:e}){const t=be(e);return r.jsx("span",{className:"tabular-nums text-sm",children:t})}function T({value:e,field:t}){const s=t.options||[];if(!e)return r.jsx("span",{children:"-"});const l=p=>{const j={gray:"bg-gray-100 text-gray-800 border-gray-300",red:"bg-red-100 text-red-800 border-red-300",orange:"bg-orange-100 text-orange-800 border-orange-300",yellow:"bg-yellow-100 text-yellow-800 border-yellow-300",green:"bg-green-100 text-green-800 border-green-300",blue:"bg-blue-100 text-blue-800 border-blue-300",indigo:"bg-indigo-100 text-indigo-800 border-indigo-300",purple:"bg-purple-100 text-purple-800 border-purple-300",pink:"bg-pink-100 text-pink-800 border-pink-300"};return j[p||"blue"]||j.blue};if(Array.isArray(e))return r.jsx("div",{className:"flex flex-wrap gap-1",children:e.map((p,j)=>{const b=s.find(N=>N.value===p),R=b?.label||p,v=l(b?.color);return r.jsx(c.Badge,{variant:"outline",className:v,children:R},j)})});const i=s.find(p=>p.value===e),o=i?.label||e,d=l(i?.color);return r.jsx(c.Badge,{variant:"outline",className:d,children:o})}function _e({value:e}){return e?r.jsx(c.Button,{variant:"link",className:"p-0 h-auto font-normal text-blue-600 hover:text-blue-800",asChild:!0,children:r.jsx("a",{href:`mailto:${e}`,onClick:t=>t.stopPropagation(),children:e})}):r.jsx("span",{children:"-"})}function we({value:e}){return e?r.jsx(c.Button,{variant:"link",className:"p-0 h-auto font-normal text-blue-600 hover:text-blue-800",asChild:!0,children:r.jsx("a",{href:e,target:"_blank",rel:"noopener noreferrer",onClick:t=>t.stopPropagation(),children:e})}):r.jsx("span",{children:"-"})}function Fe({value:e}){return e?r.jsx("a",{href:`tel:${e}`,className:"text-blue-600 hover:text-blue-800",onClick:t=>t.stopPropagation(),children:e}):r.jsx("span",{children:"-"})}function ke({value:e,field:t}){if(!e)return r.jsx("span",{children:"-"});if(t.multiple,Array.isArray(e)){const l=e.length;return r.jsxs("span",{className:"text-sm text-gray-600",children:[l," ",l===1?"file":"files"]})}const s=e.name||e.original_name||"File";return r.jsx("span",{className:"text-sm truncate",children:s})}function Te({value:e}){return e?Array.isArray(e)?r.jsxs("div",{className:"flex -space-x-2",children:[e.slice(0,3).map((t,a)=>r.jsx("img",{src:t.url||"",alt:t.name||`Image ${a+1}`,className:"size-8 rounded-md border-2 border-white object-cover"},a)),e.length>3&&r.jsxs("div",{className:"size-8 rounded-md border-2 border-white bg-gray-100 flex items-center justify-center text-xs font-medium text-gray-600",children:["+",e.length-3]})]}):r.jsx("img",{src:e.url||"",alt:e.name||"Image",className:"size-10 rounded-md object-cover"}):r.jsx("span",{children:"-"})}function te({value:e}){if(!e)return r.jsx("span",{children:"-"});if(Array.isArray(e))return r.jsx("div",{className:"flex flex-wrap gap-1",children:e.map((t,a)=>{const s=t.name||t.label||t._id||String(t);return r.jsx("span",{className:"inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-gray-100 text-gray-800",children:s},a)})});if(typeof e=="object"&&e!==null){const t=e.name||e.label||e._id||"[Object]";return r.jsx("span",{className:"truncate",children:t})}return r.jsx("span",{className:"truncate",children:String(e)})}function Z({value:e}){return r.jsx("span",{className:"text-gray-700 font-mono text-sm",children:e!=null?String(e):"-"})}function K({value:e}){if(!e)return r.jsx("span",{children:"-"});if(Array.isArray(e))return r.jsxs("div",{className:"flex -space-x-2",children:[e.slice(0,3).map((s,l)=>{const i=s.name||s.username||"User",o=i.split(" ").map(d=>d[0]).join("").toUpperCase().slice(0,2);return r.jsx(c.Avatar,{className:"size-8 border-2 border-white",title:i,children:r.jsx(c.AvatarFallback,{className:"bg-blue-500 text-white text-xs",children:o})},l)}),e.length>3&&r.jsx(c.Avatar,{className:"size-8 border-2 border-white",children:r.jsxs(c.AvatarFallback,{className:"bg-gray-200 text-gray-600 text-xs",children:["+",e.length-3]})})]});const t=e.name||e.username||"User",a=t.split(" ").map(s=>s[0]).join("").toUpperCase().slice(0,2);return r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx(c.Avatar,{className:"size-8",children:r.jsx(c.AvatarFallback,{className:"bg-blue-500 text-white text-xs",children:a})}),r.jsx("span",{className:"truncate",children:t})]})}const ee=new Map;function $(e,t){ee.set(e,t)}function ze(e){return ee.has(e)?ee.get(e):{text:C,textarea:C,markdown:C,html:C,number:je,currency:ye,percent:Ne,boolean:Re,date:Ce,datetime:ve,time:C,select:T,lookup:T,master_detail:T,email:_e,url:we,phone:Fe,file:ke,image:Te,formula:Z,summary:Z,auto_number:C,user:K,owner:K,password:()=>r.jsx("span",{children:"••••••"}),location:C,object:()=>r.jsx("span",{className:"text-gray-500 italic",children:"[Object]"}),vector:()=>r.jsx("span",{className:"text-gray-500 italic",children:"[Vector]"}),grid:()=>r.jsx("span",{className:"text-gray-500 italic",children:"[Grid]"})}[e]||C}$("lookup",te);$("master_detail",te);$("select",T);function Ve(e){return{text:"input",textarea:"textarea",markdown:"textarea",html:"textarea",number:"input",currency:"input",percent:"input",date:"date-picker",datetime:"date-picker",time:"input",boolean:"switch",select:"select",lookup:"select",master_detail:"select",email:"input",phone:"input",url:"input",file:"file-upload",image:"file-upload",password:"input",location:"input",formula:"input",summary:"input",auto_number:"input",object:"input",vector:"input",grid:"input"}[e]||"input"}function qe(e){if(e<0||!Number.isFinite(e)||e===0)return"0 B";const t=["B","KB","MB","GB","TB"];let a=e,s=0;for(;a>=1024&&s<t.length-1;)a/=1024,s++;return`${a.toFixed(s>0?1:0)} ${t[s]}`}function We(e){const t={};return e.required&&(t.required=typeof e.required_message=="string"?e.required_message:`${e.label||e.name} is required`),e.min_length&&(t.minLength={value:e.min_length,message:e.min_length_message||`Minimum length is ${e.min_length} characters`}),e.max_length&&(t.maxLength={value:e.max_length,message:e.max_length_message||`Maximum length is ${e.max_length} characters`}),e.min!==void 0&&(t.min={value:e.min,message:e.min_message||`Minimum value is ${e.min}`}),e.max!==void 0&&(t.max={value:e.max,message:e.max_message||`Maximum value is ${e.max}`}),e.pattern&&(t.pattern={value:typeof e.pattern=="string"?new RegExp(e.pattern):e.pattern,message:e.pattern_message||"Invalid format"}),e.type==="email"&&(t.pattern={value:/^[^\s@]+@[^\s@]+\.[^\s@]+$/,message:"Please enter a valid email address"}),e.type==="url"&&(t.pattern={value:/^https?:\/\/.+/,message:"Please enter a valid URL"}),e.validate&&(t.validate=e.validate),Object.keys(t).length>0?t:void 0}function re(e,t){if(!e)return!0;if(e.field&&e.value!==void 0){const a=t[e.field];if(e.operator==="="||e.operator==="==")return a===e.value;if(e.operator==="!=")return a!==e.value;if(e.operator===">")return a>e.value;if(e.operator===">=")return a>=e.value;if(e.operator==="<")return a<e.value;if(e.operator==="<=")return a<=e.value;if(e.operator==="in")return Array.isArray(e.value)&&e.value.includes(a)}return e.and&&Array.isArray(e.and)?e.and.every(a=>re(a,t)):e.or&&Array.isArray(e.or)?e.or.some(a=>re(a,t)):!0}function Ge(){f.ComponentRegistry.register("text",V),f.ComponentRegistry.register("textarea",H),f.ComponentRegistry.register("number",q),f.ComponentRegistry.register("boolean",de),f.ComponentRegistry.register("select",pe),f.ComponentRegistry.register("date",xe),f.ComponentRegistry.register("email",W),f.ComponentRegistry.register("phone",G),f.ComponentRegistry.register("url",J),f.ComponentRegistry.register("currency",X),f.ComponentRegistry.register("markdown",Q),f.ComponentRegistry.register("html",Q),f.ComponentRegistry.register("lookup",P),f.ComponentRegistry.register("master_detail",P),f.ComponentRegistry.register("field:text",V),f.ComponentRegistry.register("field:textarea",H),f.ComponentRegistry.register("field:number",q),f.ComponentRegistry.register("field:email",W),f.ComponentRegistry.register("field:phone",G),f.ComponentRegistry.register("field:url",J),f.ComponentRegistry.register("field:currency",X),f.ComponentRegistry.register("field:lookup",P)}exports.BooleanCellRenderer=Re;exports.BooleanField=de;exports.CurrencyCellRenderer=ye;exports.CurrencyField=X;exports.DateCellRenderer=Ce;exports.DateField=xe;exports.DateTimeCellRenderer=ve;exports.EmailCellRenderer=_e;exports.EmailField=W;exports.FileCellRenderer=ke;exports.FormulaCellRenderer=Z;exports.ImageCellRenderer=Te;exports.LookupCellRenderer=te;exports.LookupField=P;exports.NumberCellRenderer=je;exports.NumberField=q;exports.PercentCellRenderer=Ne;exports.PhoneCellRenderer=Fe;exports.PhoneField=G;exports.RichTextField=Q;exports.SelectCellRenderer=T;exports.SelectField=pe;exports.TextAreaField=H;exports.TextCellRenderer=C;exports.TextField=V;exports.UrlCellRenderer=we;exports.UrlField=J;exports.UserCellRenderer=K;exports.buildValidationRules=We;exports.evaluateCondition=re;exports.formatCurrency=fe;exports.formatDate=ge;exports.formatDateTime=be;exports.formatFileSize=qe;exports.formatPercent=he;exports.getCellRenderer=ze;exports.mapFieldTypeToFormType=Ve;exports.registerFieldRenderer=$;exports.registerFields=Ge;
@@ -0,0 +1,2 @@
1
+ export * from './fields/src/index'
2
+ export {}