@page-speed/forms 0.2.3 → 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.
package/dist/inputs.d.ts CHANGED
@@ -580,6 +580,21 @@ interface FileValidationError {
580
580
  error: "type" | "size" | "count";
581
581
  message: string;
582
582
  }
583
+ /**
584
+ * Upload progress tracking per file
585
+ */
586
+ interface FileUploadProgress {
587
+ [fileName: string]: number;
588
+ }
589
+ /**
590
+ * Crop area coordinates
591
+ */
592
+ interface CropArea {
593
+ x: number;
594
+ y: number;
595
+ width: number;
596
+ height: number;
597
+ }
583
598
  /**
584
599
  * FileInput component props
585
600
  */
@@ -618,6 +633,31 @@ interface FileInputProps extends Omit<InputProps<File[]>, "value" | "onChange">
618
633
  * @default true
619
634
  */
620
635
  showPreview?: boolean;
636
+ /**
637
+ * Show upload progress indicators
638
+ * @default true
639
+ */
640
+ showProgress?: boolean;
641
+ /**
642
+ * Upload progress per file (0-100)
643
+ * Consumer should update this during upload
644
+ */
645
+ uploadProgress?: FileUploadProgress;
646
+ /**
647
+ * Enable image cropping for image files
648
+ * @default false
649
+ */
650
+ enableCropping?: boolean;
651
+ /**
652
+ * Crop aspect ratio (width / height)
653
+ * @default Free form (no constraint)
654
+ * @example 16/9, 1, 4/3
655
+ */
656
+ cropAspectRatio?: number;
657
+ /**
658
+ * Crop complete handler - receives cropped blob and original file
659
+ */
660
+ onCropComplete?: (croppedBlob: Blob, originalFile: File) => void;
621
661
  /**
622
662
  * Validation error handler
623
663
  */
@@ -628,7 +668,15 @@ interface FileInputProps extends Omit<InputProps<File[]>, "value" | "onChange">
628
668
  onFileRemove?: (file: File, index: number) => void;
629
669
  }
630
670
  /**
631
- * FileInput component for file selection with validation
671
+ * FileInput component for file selection with validation, progress tracking, and image cropping
672
+ *
673
+ * Features:
674
+ * - Drag-and-drop file upload
675
+ * - File type and size validation
676
+ * - Image preview thumbnails
677
+ * - Upload progress indicators
678
+ * - Image cropping with aspect ratio control
679
+ * - Multiple file support
632
680
  *
633
681
  * @example
634
682
  * ```tsx
@@ -641,11 +689,480 @@ interface FileInputProps extends Omit<InputProps<File[]>, "value" | "onChange">
641
689
  * error={hasError}
642
690
  * />
643
691
  * ```
692
+ *
693
+ * @example
694
+ * ```tsx
695
+ * // With upload progress
696
+ * <FileInput
697
+ * name="photos"
698
+ * accept="image/*"
699
+ * multiple
700
+ * value={files}
701
+ * onChange={setFiles}
702
+ * showProgress
703
+ * uploadProgress={progress}
704
+ * />
705
+ * ```
706
+ *
707
+ * @example
708
+ * ```tsx
709
+ * // With image cropping
710
+ * <FileInput
711
+ * name="avatar"
712
+ * accept="image/*"
713
+ * value={files}
714
+ * onChange={setFiles}
715
+ * enableCropping
716
+ * cropAspectRatio={1}
717
+ * onCropComplete={(blob, file) => {
718
+ * // Handle cropped image
719
+ * }}
720
+ * />
721
+ * ```
644
722
  */
645
723
  declare function FileInput({ name, value, onChange, onBlur, placeholder, disabled, required, error, className, accept, maxSize, // 5MB default
646
- maxFiles, multiple, showPreview, onValidationError, onFileRemove, ...props }: FileInputProps): React.JSX.Element;
724
+ maxFiles, multiple, showPreview, showProgress, uploadProgress, enableCropping, cropAspectRatio, onCropComplete, onValidationError, onFileRemove, ...props }: FileInputProps): React.JSX.Element;
647
725
  declare namespace FileInput {
648
726
  var displayName: string;
649
727
  }
650
728
 
651
- export { Checkbox, CheckboxGroup, type CheckboxGroupOption, type CheckboxGroupProps, type CheckboxProps, FileInput, type FileInputProps, type FileValidationError, Radio, type RadioOption, type RadioProps, Select, type SelectOption, type SelectOptionGroup, type SelectProps, TextArea, type TextAreaProps, TextInput };
729
+ /**
730
+ * DatePicker props interface
731
+ */
732
+ interface DatePickerProps extends Omit<InputProps<Date | null>, "onChange"> {
733
+ /**
734
+ * Change handler - receives selected date or null
735
+ */
736
+ onChange: (date: Date | null) => void;
737
+ /**
738
+ * Placeholder text when no date is selected
739
+ * @default "Select date..."
740
+ */
741
+ placeholder?: string;
742
+ /**
743
+ * Date format for display
744
+ * @default "MM/dd/yyyy"
745
+ */
746
+ format?: string;
747
+ /**
748
+ * Minimum selectable date
749
+ */
750
+ minDate?: Date;
751
+ /**
752
+ * Maximum selectable date
753
+ */
754
+ maxDate?: Date;
755
+ /**
756
+ * Dates that should be disabled
757
+ */
758
+ disabledDates?: Date[];
759
+ /**
760
+ * Function to determine if a date should be disabled
761
+ */
762
+ isDateDisabled?: (date: Date) => boolean;
763
+ /**
764
+ * Show clear button
765
+ * @default true
766
+ */
767
+ clearable?: boolean;
768
+ /**
769
+ * Show calendar icon
770
+ * @default true
771
+ */
772
+ showIcon?: boolean;
773
+ /**
774
+ * Additional native input attributes
775
+ */
776
+ [key: string]: any;
777
+ }
778
+ /**
779
+ * DatePicker - Accessible date selection component with calendar UI
780
+ *
781
+ * A lightweight date picker with calendar popup, keyboard navigation,
782
+ * and error state support. Designed to work seamlessly with useForm and Field components.
783
+ *
784
+ * Features:
785
+ * - Calendar popup with month/year navigation
786
+ * - Full accessibility support (ARIA attributes, keyboard navigation)
787
+ * - Error state styling
788
+ * - Controlled input behavior
789
+ * - Date range constraints (min/max dates)
790
+ * - Disabled dates support
791
+ * - Clearable selection
792
+ * - Custom date format display
793
+ * - Icon display toggle
794
+ * - Click outside to close
795
+ * - Native date input fallback for mobile
796
+ *
797
+ * @example
798
+ * ```tsx
799
+ * const form = useForm({ initialValues: { birthdate: null } });
800
+ *
801
+ * <DatePicker
802
+ * {...form.getFieldProps('birthdate')}
803
+ * placeholder="Select your birthdate"
804
+ * format="MM/dd/yyyy"
805
+ * maxDate={new Date()}
806
+ * clearable
807
+ * showIcon
808
+ * error={!!form.errors.birthdate}
809
+ * />
810
+ * ```
811
+ *
812
+ * @example
813
+ * ```tsx
814
+ * // With date range constraints
815
+ * <DatePicker
816
+ * name="appointment"
817
+ * value={appointmentDate}
818
+ * onChange={setAppointmentDate}
819
+ * minDate={new Date()}
820
+ * maxDate={addDays(new Date(), 90)}
821
+ * isDateDisabled={(date) => date.getDay() === 0 || date.getDay() === 6}
822
+ * />
823
+ * ```
824
+ *
825
+ * Note: This component requires react-day-picker as a peer dependency.
826
+ * Install with: npm install react-day-picker date-fns
827
+ *
828
+ * @see https://opensite.ai/developers/page-speed/forms/date-picker
829
+ */
830
+ declare function DatePicker({ name, value, onChange, onBlur, disabled, required, error, className, placeholder, format, minDate, maxDate, disabledDates, isDateDisabled, clearable, showIcon, ...props }: DatePickerProps): React.JSX.Element;
831
+ declare namespace DatePicker {
832
+ var displayName: string;
833
+ }
834
+
835
+ /**
836
+ * Time value format
837
+ */
838
+ interface TimeValue {
839
+ hour: number;
840
+ minute: number;
841
+ period: "AM" | "PM";
842
+ }
843
+ /**
844
+ * TimePicker props interface
845
+ */
846
+ interface TimePickerProps extends Omit<InputProps<string>, "onChange"> {
847
+ /**
848
+ * Change handler - receives time string in format "HH:mm AM/PM"
849
+ */
850
+ onChange: (time: string) => void;
851
+ /**
852
+ * Placeholder text when no time is selected
853
+ * @default "Select time..."
854
+ */
855
+ placeholder?: string;
856
+ /**
857
+ * Use 24-hour format instead of 12-hour with AM/PM
858
+ * @default false
859
+ */
860
+ use24Hour?: boolean;
861
+ /**
862
+ * Minute step interval (e.g., 15 for 15-minute increments)
863
+ * @default 1
864
+ */
865
+ minuteStep?: number;
866
+ /**
867
+ * Show clear button
868
+ * @default true
869
+ */
870
+ clearable?: boolean;
871
+ /**
872
+ * Show clock icon
873
+ * @default true
874
+ */
875
+ showIcon?: boolean;
876
+ /**
877
+ * Additional native input attributes
878
+ */
879
+ [key: string]: any;
880
+ }
881
+ /**
882
+ * TimePicker - Accessible time selection component with AM/PM support
883
+ *
884
+ * A lightweight time picker with dropdown selection for hours, minutes, and AM/PM period.
885
+ * Designed to work seamlessly with useForm and Field components.
886
+ *
887
+ * Features:
888
+ * - Dropdown selection with hour/minute spinners
889
+ * - 12-hour or 24-hour format support
890
+ * - AM/PM period selector
891
+ * - Configurable minute step intervals
892
+ * - Full accessibility support (ARIA attributes, keyboard navigation)
893
+ * - Error state styling
894
+ * - Controlled input behavior
895
+ * - Clearable selection
896
+ * - Icon display toggle
897
+ * - Click outside to close
898
+ *
899
+ * @example
900
+ * ```tsx
901
+ * const form = useForm({ initialValues: { appointment: '' } });
902
+ *
903
+ * <TimePicker
904
+ * {...form.getFieldProps('appointment')}
905
+ * placeholder="Select time"
906
+ * minuteStep={15}
907
+ * clearable
908
+ * showIcon
909
+ * error={!!form.errors.appointment}
910
+ * />
911
+ * ```
912
+ *
913
+ * @example
914
+ * ```tsx
915
+ * // With 24-hour format
916
+ * <TimePicker
917
+ * name="startTime"
918
+ * value={startTime}
919
+ * onChange={setStartTime}
920
+ * use24Hour
921
+ * minuteStep={30}
922
+ * />
923
+ * ```
924
+ *
925
+ * @see https://opensite.ai/developers/page-speed/forms/time-picker
926
+ */
927
+ declare function TimePicker({ name, value, onChange, onBlur, disabled, required, error, className, placeholder, use24Hour, minuteStep, clearable, showIcon, ...props }: TimePickerProps): React.JSX.Element;
928
+ declare namespace TimePicker {
929
+ var displayName: string;
930
+ }
931
+
932
+ /**
933
+ * Date range value
934
+ */
935
+ interface DateRange {
936
+ start: Date | null;
937
+ end: Date | null;
938
+ }
939
+ /**
940
+ * DateRangePicker props interface
941
+ */
942
+ interface DateRangePickerProps extends Omit<InputProps<DateRange>, "onChange"> {
943
+ /**
944
+ * Change handler - receives date range object
945
+ */
946
+ onChange: (range: DateRange) => void;
947
+ /**
948
+ * Placeholder text when no dates are selected
949
+ * @default "Select date range..."
950
+ */
951
+ placeholder?: string;
952
+ /**
953
+ * Date format for display
954
+ * @default "MM/dd/yyyy"
955
+ */
956
+ format?: string;
957
+ /**
958
+ * Minimum selectable date
959
+ */
960
+ minDate?: Date;
961
+ /**
962
+ * Maximum selectable date
963
+ */
964
+ maxDate?: Date;
965
+ /**
966
+ * Dates that should be disabled
967
+ */
968
+ disabledDates?: Date[];
969
+ /**
970
+ * Function to determine if a date should be disabled
971
+ */
972
+ isDateDisabled?: (date: Date) => boolean;
973
+ /**
974
+ * Show clear button
975
+ * @default true
976
+ */
977
+ clearable?: boolean;
978
+ /**
979
+ * Show calendar icon
980
+ * @default true
981
+ */
982
+ showIcon?: boolean;
983
+ /**
984
+ * Separator between start and end dates
985
+ * @default " - "
986
+ */
987
+ separator?: string;
988
+ /**
989
+ * Additional native input attributes
990
+ */
991
+ [key: string]: any;
992
+ }
993
+ /**
994
+ * DateRangePicker - Accessible date range selection component
995
+ *
996
+ * A lightweight date range picker with calendar popup for selecting start and end dates.
997
+ * Designed to work seamlessly with useForm and Field components.
998
+ *
999
+ * Features:
1000
+ * - Dual calendar view for range selection
1001
+ * - Full accessibility support (ARIA attributes, keyboard navigation)
1002
+ * - Error state styling
1003
+ * - Controlled input behavior
1004
+ * - Date range constraints (min/max dates)
1005
+ * - Disabled dates support
1006
+ * - Clearable selection
1007
+ * - Custom date format display
1008
+ * - Visual range highlighting
1009
+ * - Icon display toggle
1010
+ * - Click outside to close
1011
+ *
1012
+ * @example
1013
+ * ```tsx
1014
+ * const form = useForm({ initialValues: { dateRange: { start: null, end: null } } });
1015
+ *
1016
+ * <DateRangePicker
1017
+ * {...form.getFieldProps('dateRange')}
1018
+ * placeholder="Select date range"
1019
+ * format="MM/dd/yyyy"
1020
+ * clearable
1021
+ * showIcon
1022
+ * error={!!form.errors.dateRange}
1023
+ * />
1024
+ * ```
1025
+ *
1026
+ * @example
1027
+ * ```tsx
1028
+ * // With date constraints
1029
+ * <DateRangePicker
1030
+ * name="vacation"
1031
+ * value={vacationRange}
1032
+ * onChange={setVacationRange}
1033
+ * minDate={new Date()}
1034
+ * maxDate={addDays(new Date(), 365)}
1035
+ * separator=" to "
1036
+ * />
1037
+ * ```
1038
+ *
1039
+ * @see https://opensite.ai/developers/page-speed/forms/date-range-picker
1040
+ */
1041
+ declare function DateRangePicker({ name, value, onChange, onBlur, disabled, required, error, className, placeholder, format, minDate, maxDate, disabledDates, isDateDisabled, clearable, showIcon, separator, ...props }: DateRangePickerProps): React.JSX.Element;
1042
+ declare namespace DateRangePicker {
1043
+ var displayName: string;
1044
+ }
1045
+
1046
+ /**
1047
+ * Editor mode type
1048
+ */
1049
+ type EditorMode = "wysiwyg" | "markdown";
1050
+ /**
1051
+ * Toolbar button configuration
1052
+ */
1053
+ interface ToolbarButton {
1054
+ command: string;
1055
+ icon: string;
1056
+ title: string;
1057
+ action: (editor: HTMLElement) => void;
1058
+ }
1059
+ /**
1060
+ * RichTextEditor props interface
1061
+ */
1062
+ interface RichTextEditorProps extends Omit<InputProps<string>, "onChange"> {
1063
+ /**
1064
+ * Change handler - receives HTML or Markdown content
1065
+ */
1066
+ onChange: (content: string) => void;
1067
+ /**
1068
+ * Editor mode - WYSIWYG or Markdown
1069
+ * @default "wysiwyg"
1070
+ */
1071
+ mode?: EditorMode;
1072
+ /**
1073
+ * Allow mode switching
1074
+ * @default false
1075
+ */
1076
+ allowModeSwitch?: boolean;
1077
+ /**
1078
+ * Placeholder text when editor is empty
1079
+ * @default "Start typing..."
1080
+ */
1081
+ placeholder?: string;
1082
+ /**
1083
+ * Minimum height of editor
1084
+ * @default "200px"
1085
+ */
1086
+ minHeight?: string;
1087
+ /**
1088
+ * Maximum height of editor (enables scrolling)
1089
+ */
1090
+ maxHeight?: string;
1091
+ /**
1092
+ * Show toolbar
1093
+ * @default true
1094
+ */
1095
+ showToolbar?: boolean;
1096
+ /**
1097
+ * Toolbar buttons to display
1098
+ * @default ["bold", "italic", "underline", "heading", "bulletList", "orderedList", "link"]
1099
+ */
1100
+ toolbarButtons?: string[];
1101
+ /**
1102
+ * Additional native input attributes
1103
+ */
1104
+ [key: string]: any;
1105
+ }
1106
+ /**
1107
+ * RichTextEditor - Basic rich text editing component with WYSIWYG and Markdown support
1108
+ *
1109
+ * A lightweight rich text editor with basic formatting capabilities and optional Markdown mode.
1110
+ * Designed to work seamlessly with useForm and Field components.
1111
+ *
1112
+ * Features:
1113
+ * - WYSIWYG editor with contentEditable
1114
+ * - Markdown editor mode
1115
+ * - Configurable toolbar with common formatting options
1116
+ * - Full accessibility support
1117
+ * - Error state styling
1118
+ * - Controlled input behavior
1119
+ * - Custom toolbar configuration
1120
+ * - Mode switching support
1121
+ * - Placeholder text support
1122
+ * - Adjustable height constraints
1123
+ *
1124
+ * Toolbar buttons:
1125
+ * - bold: Bold text (**text**)
1126
+ * - italic: Italic text (*text*)
1127
+ * - underline: Underlined text
1128
+ * - heading: Heading levels (H1-H3)
1129
+ * - bulletList: Unordered list
1130
+ * - orderedList: Ordered list
1131
+ * - link: Insert hyperlink
1132
+ *
1133
+ * @example
1134
+ * ```tsx
1135
+ * const form = useForm({ initialValues: { content: '' } });
1136
+ *
1137
+ * <RichTextEditor
1138
+ * {...form.getFieldProps('content')}
1139
+ * placeholder="Write your content..."
1140
+ * mode="wysiwyg"
1141
+ * allowModeSwitch
1142
+ * showToolbar
1143
+ * minHeight="200px"
1144
+ * maxHeight="500px"
1145
+ * error={!!form.errors.content}
1146
+ * />
1147
+ * ```
1148
+ *
1149
+ * @example
1150
+ * ```tsx
1151
+ * // Markdown mode
1152
+ * <RichTextEditor
1153
+ * name="description"
1154
+ * value={description}
1155
+ * onChange={setDescription}
1156
+ * mode="markdown"
1157
+ * toolbarButtons={["bold", "italic", "heading", "link"]}
1158
+ * />
1159
+ * ```
1160
+ *
1161
+ * @see https://opensite.ai/developers/page-speed/forms/rich-text-editor
1162
+ */
1163
+ declare function RichTextEditor({ name, value, onChange, onBlur, disabled, required, error, className, mode, allowModeSwitch, placeholder, minHeight, maxHeight, showToolbar, toolbarButtons, ...props }: RichTextEditorProps): React.JSX.Element;
1164
+ declare namespace RichTextEditor {
1165
+ var displayName: string;
1166
+ }
1167
+
1168
+ export { Checkbox, CheckboxGroup, type CheckboxGroupOption, type CheckboxGroupProps, type CheckboxProps, type CropArea, DatePicker, type DatePickerProps, type DateRange, DateRangePicker, type DateRangePickerProps, type EditorMode, FileInput, type FileInputProps, type FileUploadProgress, type FileValidationError, Radio, type RadioOption, type RadioProps, RichTextEditor, type RichTextEditorProps, Select, type SelectOption, type SelectOptionGroup, type SelectProps, TextArea, type TextAreaProps, TextInput, TimePicker, type TimePickerProps, type TimeValue, type ToolbarButton };