|
1 | 1 | # Designer UX Analysis & Improvement Plan |
2 | 2 |
|
3 | | -> **Last Updated:** February 12, 2026 |
| 3 | +> **Last Updated:** February 16, 2026 |
4 | 4 | > **Package:** `@object-ui/plugin-designer` |
5 | 5 | > **Source:** `packages/plugin-designer/src/` |
6 | 6 |
|
@@ -500,6 +500,377 @@ This is the **most complete** designer: |
500 | 500 |
|
501 | 501 | --- |
502 | 502 |
|
| 503 | +## 10. Field Type Evaluation for Form Designer |
| 504 | + |
| 505 | +> **Last Updated:** February 16, 2026 |
| 506 | +> **Related Packages:** `@object-ui/fields`, `@object-ui/types`, `@object-ui/plugin-designer` |
| 507 | + |
| 508 | +### 10.1 Overview |
| 509 | + |
| 510 | +The `@object-ui/fields` package provides **36 field widget implementations** covering |
| 511 | +text, numeric, date/time, selection, file, contact, computed, and visual field types. |
| 512 | +The `@object-ui/types` package defines **35 typed metadata interfaces** in |
| 513 | +`field-types.ts` plus a `FieldMetadata` union type. However, the designer components |
| 514 | +in `@object-ui/plugin-designer` expose only a **fraction** of these field types to |
| 515 | +users, creating a significant gap between available capabilities and designer UX. |
| 516 | + |
| 517 | +### 10.2 Complete Field Type Inventory |
| 518 | + |
| 519 | +The table below catalogs all field types available in `@object-ui/fields`, their |
| 520 | +corresponding type definitions in `@object-ui/types`, and their current status in |
| 521 | +each designer. |
| 522 | + |
| 523 | +#### Category: Basic Text |
| 524 | + |
| 525 | +| Field Type | Widget File | Type Interface | Cell Renderer | Form Mapper | DataModel | Page Palette | |
| 526 | +|------------|-------------|----------------|---------------|-------------|-----------|--------------| |
| 527 | +| `text` | `TextField.tsx` | `TextFieldMetadata` | `TextCellRenderer` | `field:text` | ✅ Default | `input` | |
| 528 | +| `textarea` | `TextAreaField.tsx` | `TextareaFieldMetadata` | `TextCellRenderer` | `field:textarea` | ❌ | `textarea` | |
| 529 | +| `markdown` | `RichTextField.tsx` | `MarkdownFieldMetadata` | `TextCellRenderer` | `field:markdown` | ❌ | ❌ | |
| 530 | +| `html` | `RichTextField.tsx` | `HtmlFieldMetadata` | `TextCellRenderer` | `field:html` | ❌ | ❌ | |
| 531 | +| `code` | `CodeField.tsx` | `CodeFieldMetadata` | — | — | ❌ | ❌ | |
| 532 | + |
| 533 | +#### Category: Numeric |
| 534 | + |
| 535 | +| Field Type | Widget File | Type Interface | Cell Renderer | Form Mapper | DataModel | Page Palette | |
| 536 | +|------------|-------------|----------------|---------------|-------------|-----------|--------------| |
| 537 | +| `number` | `NumberField.tsx` | `NumberFieldMetadata` | `NumberCellRenderer` | `field:number` | ❌ | ❌ | |
| 538 | +| `currency` | `CurrencyField.tsx` | `CurrencyFieldMetadata` | `CurrencyCellRenderer` | `field:currency` | ❌ | ❌ | |
| 539 | +| `percent` | `PercentField.tsx` | `PercentFieldMetadata` | `PercentCellRenderer` | `field:percent` | ❌ | ❌ | |
| 540 | +| `slider` | `SliderField.tsx` | `SliderFieldMetadata` | — | — | ❌ | ❌ | |
| 541 | +| `rating` | `RatingField.tsx` | `RatingFieldMetadata` | — | — | ❌ | ❌ | |
| 542 | + |
| 543 | +#### Category: Date & Time |
| 544 | + |
| 545 | +| Field Type | Widget File | Type Interface | Cell Renderer | Form Mapper | DataModel | Page Palette | |
| 546 | +|------------|-------------|----------------|---------------|-------------|-----------|--------------| |
| 547 | +| `date` | `DateField.tsx` | `DateFieldMetadata` | `DateCellRenderer` | `field:date` | ❌ | ❌ | |
| 548 | +| `datetime` | `DateTimeField.tsx` | `DateTimeFieldMetadata` | `DateTimeCellRenderer` | `field:datetime` | ✅ (default entity) | ❌ | |
| 549 | +| `time` | `TimeField.tsx` | `TimeFieldMetadata` | `TextCellRenderer` | `field:time` | ❌ | ❌ | |
| 550 | + |
| 551 | +#### Category: Selection & Lookup |
| 552 | + |
| 553 | +| Field Type | Widget File | Type Interface | Cell Renderer | Form Mapper | DataModel | Page Palette | |
| 554 | +|------------|-------------|----------------|---------------|-------------|-----------|--------------| |
| 555 | +| `boolean` | `BooleanField.tsx` | `BooleanFieldMetadata` | `BooleanCellRenderer` | `field:boolean` | ❌ | `checkbox` | |
| 556 | +| `select` | `SelectField.tsx` | `SelectFieldMetadata` | `SelectCellRenderer` | `field:select` | ❌ | `select` | |
| 557 | +| `lookup` | `LookupField.tsx` | `LookupFieldMetadata` | `LookupCellRenderer` | `field:lookup` | ❌ | ❌ | |
| 558 | +| `master_detail` | `MasterDetailField.tsx` | `MasterDetailFieldMetadata` | `LookupCellRenderer` | `field:master_detail` | ❌ | ❌ | |
| 559 | + |
| 560 | +#### Category: Contact & Identity |
| 561 | + |
| 562 | +| Field Type | Widget File | Type Interface | Cell Renderer | Form Mapper | DataModel | Page Palette | |
| 563 | +|------------|-------------|----------------|---------------|-------------|-----------|--------------| |
| 564 | +| `email` | `EmailField.tsx` | `EmailFieldMetadata` | `EmailCellRenderer` | `field:email` | ❌ | ❌ | |
| 565 | +| `phone` | `PhoneField.tsx` | `PhoneFieldMetadata` | `PhoneCellRenderer` | `field:phone` | ❌ | ❌ | |
| 566 | +| `url` | `UrlField.tsx` | `UrlFieldMetadata` | `UrlCellRenderer` | `field:url` | ❌ | ❌ | |
| 567 | +| `password` | `PasswordField.tsx` | `PasswordFieldMetadata` | *(masked)* | `field:password` | ❌ | ❌ | |
| 568 | +| `user` | `UserField.tsx` | `UserFieldMetadata` | `UserCellRenderer` | — | ❌ | ❌ | |
| 569 | +| `avatar` | `AvatarField.tsx` | `AvatarFieldMetadata` | — | — | ❌ | ❌ | |
| 570 | + |
| 571 | +#### Category: File & Media |
| 572 | + |
| 573 | +| Field Type | Widget File | Type Interface | Cell Renderer | Form Mapper | DataModel | Page Palette | |
| 574 | +|------------|-------------|----------------|---------------|-------------|-----------|--------------| |
| 575 | +| `file` | `FileField.tsx` | `FileFieldMetadata` | `FileCellRenderer` | `field:file` | ❌ | ❌ | |
| 576 | +| `image` | `ImageField.tsx` | `ImageFieldMetadata` | `ImageCellRenderer` | `field:image` | ❌ | ❌ | |
| 577 | +| `signature` | `SignatureField.tsx` | `SignatureFieldMetadata` | — | — | ❌ | ❌ | |
| 578 | +| `qrcode` | `QRCodeField.tsx` | `QRCodeFieldMetadata` | — | — | ❌ | ❌ | |
| 579 | + |
| 580 | +#### Category: Location & Address |
| 581 | + |
| 582 | +| Field Type | Widget File | Type Interface | Cell Renderer | Form Mapper | DataModel | Page Palette | |
| 583 | +|------------|-------------|----------------|---------------|-------------|-----------|--------------| |
| 584 | +| `location` | `LocationField.tsx` | `LocationFieldMetadata` | `TextCellRenderer` | `field:location` | ❌ | ❌ | |
| 585 | +| `address` | `AddressField.tsx` | `AddressFieldMetadata` | — | — | ❌ | ❌ | |
| 586 | +| `geolocation` | `GeolocationField.tsx` | `GeolocationFieldMetadata` | — | — | ❌ | ❌ | |
| 587 | + |
| 588 | +#### Category: Computed & Auto-generated |
| 589 | + |
| 590 | +| Field Type | Widget File | Type Interface | Cell Renderer | Form Mapper | DataModel | Page Palette | |
| 591 | +|------------|-------------|----------------|---------------|-------------|-----------|--------------| |
| 592 | +| `formula` | `FormulaField.tsx` | `FormulaFieldMetadata` | `FormulaCellRenderer` | `field:formula` | ❌ | ❌ | |
| 593 | +| `summary` | `SummaryField.tsx` | `SummaryFieldMetadata` | `FormulaCellRenderer` | `field:summary` | ❌ | ❌ | |
| 594 | +| `auto_number` | `AutoNumberField.tsx` | `AutoNumberFieldMetadata` | `TextCellRenderer` | `field:auto_number` | ❌ | ❌ | |
| 595 | + |
| 596 | +#### Category: Complex & Visual |
| 597 | + |
| 598 | +| Field Type | Widget File | Type Interface | Cell Renderer | Form Mapper | DataModel | Page Palette | |
| 599 | +|------------|-------------|----------------|---------------|-------------|-----------|--------------| |
| 600 | +| `object` | `ObjectField.tsx` | `ObjectFieldMetadata` | *[Object]* | — | ❌ | ❌ | |
| 601 | +| `vector` | `VectorField.tsx` | `VectorFieldMetadata` | *[Vector]* | — | ❌ | ❌ | |
| 602 | +| `grid` | `GridField.tsx` | `GridFieldMetadata` | *[Grid]* | — | ❌ | ❌ | |
| 603 | +| `color` | `ColorField.tsx` | `ColorFieldMetadata` | — | — | ❌ | ❌ | |
| 604 | + |
| 605 | +### 10.3 Gap Analysis by Designer |
| 606 | + |
| 607 | +#### DataModelDesigner |
| 608 | + |
| 609 | +**Current state:** When a field is added via `handleAddField` (`DataModelDesigner.tsx:258`), |
| 610 | +the type is hardcoded to `'text'`. The field type is displayed as a plain text label |
| 611 | +(`DataModelDesigner.tsx:712`) but there is **no UI to change the field type** after |
| 612 | +creation. The inline editing mode (`DataModelDesigner.tsx:273–306`) only supports |
| 613 | +editing the field name. |
| 614 | + |
| 615 | +**`DataModelField.type`** in `@object-ui/types` (`designer.ts:156`) is typed as a |
| 616 | +generic `string`, not a union of valid `@object-ui/fields` types. This means: |
| 617 | +- No TypeScript-level validation of field type values |
| 618 | +- No autocomplete assistance for developers |
| 619 | +- No compile-time guarantee that a field type maps to an existing widget |
| 620 | + |
| 621 | +**Key gaps:** |
| 622 | +1. No field type selector dropdown when adding/editing fields |
| 623 | +2. No reuse of `FieldMetadata` union type from `@object-ui/types/field-types.ts` |
| 624 | +3. No visual distinction between field types (icons, colors, badges) |
| 625 | +4. Default entity template only includes `uuid` and `datetime` — no standard business fields |
| 626 | + |
| 627 | +#### PageDesigner |
| 628 | + |
| 629 | +**Current state:** The `DEFAULT_PALETTE` (`PageDesigner.tsx:740–773`) contains 14 |
| 630 | +generic component types across 3 categories (Layout, Form, Data). The Form category |
| 631 | +has only 5 items: `input`, `textarea`, `select`, `checkbox`, `button`. |
| 632 | + |
| 633 | +**Key gaps:** |
| 634 | +1. Form palette uses generic HTML-like type names (`input`, `checkbox`) rather than |
| 635 | + `@object-ui/fields` type names (`text`, `boolean`, `email`, `phone`) |
| 636 | +2. Missing a dedicated **Fields** palette category showcasing all 36 field widgets |
| 637 | +3. No mapping between palette items and `@object-ui/fields` `FieldWidgetProps` interface |
| 638 | +4. No preview rendering using actual field widgets from `@object-ui/fields` |
| 639 | + |
| 640 | +#### ViewDesigner |
| 641 | + |
| 642 | +**Current state:** The ViewDesigner shows field types as plain text badges |
| 643 | +(`ViewDesigner.tsx:533`). It relies on the `availableFields` prop to receive |
| 644 | +`Array<{ name: string; label: string; type: string }>` from the parent. Type display |
| 645 | +is the most complete among designers, but still lacks visual indicators. |
| 646 | + |
| 647 | +**Key gaps:** |
| 648 | +1. Field type badges are plain text with no icons or colors per type |
| 649 | +2. No field type grouping/categorization in the Available Fields panel |
| 650 | +3. No type-specific column configuration (e.g., currency format, date format) |
| 651 | + |
| 652 | +### 10.4 Recommended `DESIGNER_FIELD_TYPES` Constant |
| 653 | + |
| 654 | +A centralized constant should be created to define all available field types for |
| 655 | +designer selection, leveraging the `FieldMetadata` union type from `@object-ui/types`. |
| 656 | + |
| 657 | +**Proposed location:** `packages/plugin-designer/src/constants/fieldTypes.ts` |
| 658 | + |
| 659 | +```typescript |
| 660 | +import type { LucideIcon } from 'lucide-react'; |
| 661 | +import { |
| 662 | + Type, Hash, Calendar, Clock, ToggleLeft, List, |
| 663 | + Link, Mail, Phone, Globe, Lock, File, Image, |
| 664 | + MapPin, Home, Navigation, Calculator, Sigma, Binary, |
| 665 | + User, Palette, Code2, Star, PenTool, QrCode, |
| 666 | + Grid3X3, Braces, Database as DatabaseIcon, SlidersHorizontal, |
| 667 | +} from 'lucide-react'; |
| 668 | + |
| 669 | +export interface DesignerFieldTypeOption { |
| 670 | + /** Field type identifier — matches @object-ui/fields registry key */ |
| 671 | + type: string; |
| 672 | + /** Display label */ |
| 673 | + label: string; |
| 674 | + /** Lucide icon component */ |
| 675 | + icon: LucideIcon; |
| 676 | + /** Category for grouping in palette/dropdown */ |
| 677 | + category: 'text' | 'number' | 'datetime' | 'selection' | 'contact' |
| 678 | + | 'file' | 'location' | 'computed' | 'complex' | 'visual'; |
| 679 | + /** Short description for tooltips */ |
| 680 | + description: string; |
| 681 | +} |
| 682 | + |
| 683 | +export const DESIGNER_FIELD_TYPES: DesignerFieldTypeOption[] = [ |
| 684 | + // Text |
| 685 | + { type: 'text', label: 'Text', icon: Type, category: 'text', |
| 686 | + description: 'Single-line text input' }, |
| 687 | + { type: 'textarea', label: 'Long Text', icon: Type, category: 'text', |
| 688 | + description: 'Multi-line text area' }, |
| 689 | + { type: 'markdown', label: 'Markdown', icon: Code2, category: 'text', |
| 690 | + description: 'Markdown-formatted rich text' }, |
| 691 | + { type: 'html', label: 'Rich Text', icon: Code2, category: 'text', |
| 692 | + description: 'HTML rich text editor' }, |
| 693 | + { type: 'code', label: 'Code', icon: Code2, category: 'text', |
| 694 | + description: 'Code editor with syntax highlighting' }, |
| 695 | + |
| 696 | + // Number |
| 697 | + { type: 'number', label: 'Number', icon: Hash, category: 'number', |
| 698 | + description: 'Numeric input with precision control' }, |
| 699 | + { type: 'currency', label: 'Currency', icon: Hash, category: 'number', |
| 700 | + description: 'Monetary value with currency symbol' }, |
| 701 | + { type: 'percent', label: 'Percent', icon: Hash, category: 'number', |
| 702 | + description: 'Percentage value with progress bar' }, |
| 703 | + { type: 'slider', label: 'Slider', icon: SlidersHorizontal, category: 'number', |
| 704 | + description: 'Numeric range slider' }, |
| 705 | + { type: 'rating', label: 'Rating', icon: Star, category: 'number', |
| 706 | + description: 'Star rating input' }, |
| 707 | + |
| 708 | + // Date & Time |
| 709 | + { type: 'date', label: 'Date', icon: Calendar, category: 'datetime', |
| 710 | + description: 'Date picker' }, |
| 711 | + { type: 'datetime', label: 'Date & Time', icon: Calendar, category: 'datetime', |
| 712 | + description: 'Date and time picker' }, |
| 713 | + { type: 'time', label: 'Time', icon: Clock, category: 'datetime', |
| 714 | + description: 'Time picker' }, |
| 715 | + |
| 716 | + // Selection |
| 717 | + { type: 'boolean', label: 'Boolean', icon: ToggleLeft, category: 'selection', |
| 718 | + description: 'True/false toggle' }, |
| 719 | + { type: 'select', label: 'Select', icon: List, category: 'selection', |
| 720 | + description: 'Dropdown with predefined options' }, |
| 721 | + { type: 'lookup', label: 'Lookup', icon: Link, category: 'selection', |
| 722 | + description: 'Reference to another object' }, |
| 723 | + { type: 'master_detail', label: 'Master-Detail', icon: Link, category: 'selection', |
| 724 | + description: 'Parent-child relationship with cascade delete' }, |
| 725 | + |
| 726 | + // Contact |
| 727 | + { type: 'email', label: 'Email', icon: Mail, category: 'contact', |
| 728 | + description: 'Email address with validation' }, |
| 729 | + { type: 'phone', label: 'Phone', icon: Phone, category: 'contact', |
| 730 | + description: 'Phone number input' }, |
| 731 | + { type: 'url', label: 'URL', icon: Globe, category: 'contact', |
| 732 | + description: 'Web address with validation' }, |
| 733 | + { type: 'password', label: 'Password', icon: Lock, category: 'contact', |
| 734 | + description: 'Masked password input' }, |
| 735 | + { type: 'user', label: 'User', icon: User, category: 'contact', |
| 736 | + description: 'User reference with avatar' }, |
| 737 | + { type: 'avatar', label: 'Avatar', icon: User, category: 'contact', |
| 738 | + description: 'User avatar image' }, |
| 739 | + |
| 740 | + // File & Media |
| 741 | + { type: 'file', label: 'File', icon: File, category: 'file', |
| 742 | + description: 'File upload with type/size validation' }, |
| 743 | + { type: 'image', label: 'Image', icon: Image, category: 'file', |
| 744 | + description: 'Image upload with preview' }, |
| 745 | + { type: 'signature', label: 'Signature', icon: PenTool, category: 'file', |
| 746 | + description: 'Digital signature capture' }, |
| 747 | + { type: 'qrcode', label: 'QR Code', icon: QrCode, category: 'file', |
| 748 | + description: 'QR code generator/scanner' }, |
| 749 | + |
| 750 | + // Location |
| 751 | + { type: 'location', label: 'Location', icon: MapPin, category: 'location', |
| 752 | + description: 'Map-based location picker' }, |
| 753 | + { type: 'address', label: 'Address', icon: Home, category: 'location', |
| 754 | + description: 'Structured address fields' }, |
| 755 | + { type: 'geolocation', label: 'Geolocation', icon: Navigation, category: 'location', |
| 756 | + description: 'GPS coordinates input' }, |
| 757 | + |
| 758 | + // Computed |
| 759 | + { type: 'formula', label: 'Formula', icon: Calculator, category: 'computed', |
| 760 | + description: 'Calculated field from expression' }, |
| 761 | + { type: 'summary', label: 'Summary', icon: Sigma, category: 'computed', |
| 762 | + description: 'Roll-up aggregation from related records' }, |
| 763 | + { type: 'auto_number', label: 'Auto Number', icon: Binary, category: 'computed', |
| 764 | + description: 'Auto-incrementing number' }, |
| 765 | + |
| 766 | + // Complex |
| 767 | + { type: 'object', label: 'Object', icon: Braces, category: 'complex', |
| 768 | + description: 'Nested JSON object' }, |
| 769 | + { type: 'vector', label: 'Vector', icon: DatabaseIcon, category: 'complex', |
| 770 | + description: 'Embedding vector for AI/ML' }, |
| 771 | + { type: 'grid', label: 'Grid', icon: Grid3X3, category: 'complex', |
| 772 | + description: 'Inline sub-table/spreadsheet' }, |
| 773 | + { type: 'color', label: 'Color', icon: Palette, category: 'visual', |
| 774 | + description: 'Color picker' }, |
| 775 | +]; |
| 776 | +``` |
| 777 | + |
| 778 | +### 10.5 Integration Plan per Designer |
| 779 | + |
| 780 | +#### DataModelDesigner — Field Type Selector |
| 781 | + |
| 782 | +Add a `<select>` dropdown next to each field's type display, populated from |
| 783 | +`DESIGNER_FIELD_TYPES`. When a field type is changed, update the entity's field |
| 784 | +array via `pushState()`. |
| 785 | + |
| 786 | +**Implementation points:** |
| 787 | +- Replace the read-only `{field.type}` span (`DataModelDesigner.tsx:712`) with a |
| 788 | + `<select>` element grouped by `category` |
| 789 | +- Add an `onChangeFieldType(entityId, fieldIndex, newType)` handler |
| 790 | +- Show field type icons in the property editor panel when an entity is selected |
| 791 | +- Update the type of `DataModelField.type` in `@object-ui/types/designer.ts` to |
| 792 | + reference the `FieldMetadata` union's type discriminant for type safety |
| 793 | + |
| 794 | +#### PageDesigner — Fields Palette Category |
| 795 | + |
| 796 | +Add a fourth palette category **"Fields"** to `DEFAULT_PALETTE`, populated from |
| 797 | +`DESIGNER_FIELD_TYPES`. Each palette item should map to the corresponding |
| 798 | +`@object-ui/fields` widget via `ComponentRegistry.resolve('field:<type>')`. |
| 799 | + |
| 800 | +**Proposed palette addition:** |
| 801 | +```typescript |
| 802 | +{ |
| 803 | + name: 'fields', |
| 804 | + label: 'Fields', |
| 805 | + items: DESIGNER_FIELD_TYPES.map(ft => ({ |
| 806 | + type: `field:${ft.type}`, |
| 807 | + label: ft.label, |
| 808 | + icon: ft.icon.name, |
| 809 | + defaultSize: { width: 300, height: 60 }, |
| 810 | + defaultProps: { fieldType: ft.type }, |
| 811 | + })), |
| 812 | +} |
| 813 | +``` |
| 814 | + |
| 815 | +**Implementation points:** |
| 816 | +- Import `DESIGNER_FIELD_TYPES` from `./constants/fieldTypes` |
| 817 | +- Render field type icons in palette items |
| 818 | +- When a field palette item is dropped on canvas, the component renders the |
| 819 | + actual field widget from `@object-ui/fields` via `ComponentRegistry` |
| 820 | +- The property editor should expose field-type-specific props (e.g., `currency` |
| 821 | + for currency fields, `options` for select fields) |
| 822 | + |
| 823 | +#### ViewDesigner — Field Type Badges with Icons |
| 824 | + |
| 825 | +Enhance the Available Fields panel (`ViewDesigner.tsx:520–537`) to show field |
| 826 | +type icons from `DESIGNER_FIELD_TYPES` alongside field names, and group fields |
| 827 | +by category. |
| 828 | + |
| 829 | +**Implementation points:** |
| 830 | +- Import field type icons from `DESIGNER_FIELD_TYPES` |
| 831 | +- Replace plain text type badge with icon + colored badge |
| 832 | +- Optionally group available fields by field type category |
| 833 | + |
| 834 | +### 10.6 Type Safety Recommendations |
| 835 | + |
| 836 | +1. **Add `FieldTypeName` type to `@object-ui/types`:** |
| 837 | + ```typescript |
| 838 | + export type FieldTypeName = FieldMetadata['type']; |
| 839 | + // Results in: 'text' | 'textarea' | 'markdown' | 'html' | 'number' | ... |
| 840 | + ``` |
| 841 | + |
| 842 | +2. **Update `DataModelField.type` in `designer.ts`:** |
| 843 | + ```typescript |
| 844 | + import type { FieldTypeName } from './field-types'; |
| 845 | + |
| 846 | + export interface DataModelField { |
| 847 | + name: string; |
| 848 | + label?: string; |
| 849 | + type: FieldTypeName; // Changed from generic `string` |
| 850 | + // ... |
| 851 | + } |
| 852 | + ``` |
| 853 | + |
| 854 | +3. **Update `mapFieldTypeToFormType` in `@object-ui/fields`** to cover all 36 |
| 855 | + field types (currently missing: `color`, `slider`, `rating`, `code`, `avatar`, |
| 856 | + `address`, `geolocation`, `signature`, `qrcode`). |
| 857 | + |
| 858 | +### 10.7 Priority & Phasing |
| 859 | + |
| 860 | +| Priority | Task | Effort | |
| 861 | +|----------|------|--------| |
| 862 | +| 🔴 P0 | Create `DESIGNER_FIELD_TYPES` constant | 0.5 day | |
| 863 | +| 🔴 P0 | Add field type selector dropdown to DataModelDesigner | 1 day | |
| 864 | +| 🟠 P1 | Add Fields palette category to PageDesigner | 1 day | |
| 865 | +| 🟠 P1 | Add `FieldTypeName` type and update `DataModelField` | 0.5 day | |
| 866 | +| 🟡 P2 | Enhance ViewDesigner field type badges with icons | 0.5 day | |
| 867 | +| 🟡 P2 | Complete `mapFieldTypeToFormType` for all 36 types | 0.5 day | |
| 868 | +| 🟢 P3 | Type-specific property editors per field type | 3–5 days | |
| 869 | + |
| 870 | +**Total estimated effort:** 7–9.5 developer days |
| 871 | + |
| 872 | +--- |
| 873 | + |
503 | 874 | ## Appendix A: File Reference Index |
504 | 875 |
|
505 | 876 | | File | Lines | Component | Registration ID | |
|
0 commit comments