@page-speed/forms 0.2.2 → 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.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var React6 = require('react');
3
+ var React7 = require('react');
4
4
 
5
5
  function _interopNamespace(e) {
6
6
  if (e && e.__esModule) return e;
@@ -20,7 +20,7 @@ function _interopNamespace(e) {
20
20
  return Object.freeze(n);
21
21
  }
22
22
 
23
- var React6__namespace = /*#__PURE__*/_interopNamespace(React6);
23
+ var React7__namespace = /*#__PURE__*/_interopNamespace(React7);
24
24
 
25
25
  // src/inputs/TextInput.tsx
26
26
  function TextInput({
@@ -45,7 +45,7 @@ function TextInput({
45
45
  const baseClassName = "text-input";
46
46
  const errorClassName = error ? "text-input--error" : "";
47
47
  const combinedClassName = `${baseClassName} ${errorClassName} ${className}`.trim();
48
- return /* @__PURE__ */ React6__namespace.createElement(
48
+ return /* @__PURE__ */ React7__namespace.createElement(
49
49
  "input",
50
50
  {
51
51
  type,
@@ -91,7 +91,7 @@ function TextArea({
91
91
  const baseClassName = "textarea";
92
92
  const errorClassName = error ? "textarea--error" : "";
93
93
  const combinedClassName = `${baseClassName} ${errorClassName} ${className}`.trim();
94
- return /* @__PURE__ */ React6__namespace.createElement(
94
+ return /* @__PURE__ */ React7__namespace.createElement(
95
95
  "textarea",
96
96
  {
97
97
  name,
@@ -128,8 +128,8 @@ function Checkbox({
128
128
  label,
129
129
  ...props
130
130
  }) {
131
- const inputRef = React6__namespace.useRef(null);
132
- React6__namespace.useEffect(() => {
131
+ const inputRef = React7__namespace.useRef(null);
132
+ React7__namespace.useEffect(() => {
133
133
  if (inputRef.current) {
134
134
  inputRef.current.indeterminate = indeterminate;
135
135
  }
@@ -143,7 +143,7 @@ function Checkbox({
143
143
  const baseClassName = "checkbox";
144
144
  const errorClassName = error ? "checkbox--error" : "";
145
145
  const combinedClassName = `${baseClassName} ${errorClassName} ${className}`.trim();
146
- const checkbox = /* @__PURE__ */ React6__namespace.createElement(
146
+ const checkbox = /* @__PURE__ */ React7__namespace.createElement(
147
147
  "input",
148
148
  {
149
149
  ref: inputRef,
@@ -162,7 +162,7 @@ function Checkbox({
162
162
  }
163
163
  );
164
164
  if (label) {
165
- return /* @__PURE__ */ React6__namespace.createElement("label", { className: "checkbox-label" }, checkbox, /* @__PURE__ */ React6__namespace.createElement("span", { className: "checkbox-label-text" }, label));
165
+ return /* @__PURE__ */ React7__namespace.createElement("label", { className: "checkbox-label" }, checkbox, /* @__PURE__ */ React7__namespace.createElement("span", { className: "checkbox-label-text" }, label));
166
166
  }
167
167
  return checkbox;
168
168
  }
@@ -218,7 +218,7 @@ function CheckboxGroup({
218
218
  const layoutClassName = `checkbox-group--${layout}`;
219
219
  const combinedClassName = `${baseClassName} ${errorClassName} ${layoutClassName} ${className}`.trim();
220
220
  const maxReached = Boolean(maxSelections && value.length >= maxSelections);
221
- return /* @__PURE__ */ React6__namespace.createElement(
221
+ return /* @__PURE__ */ React7__namespace.createElement(
222
222
  "div",
223
223
  {
224
224
  className: combinedClassName,
@@ -231,9 +231,9 @@ function CheckboxGroup({
231
231
  gridTemplateColumns: `repeat(${gridColumns}, 1fr)`
232
232
  } : void 0
233
233
  },
234
- label && /* @__PURE__ */ React6__namespace.createElement("div", { className: "checkbox-group-label" }, label),
235
- description && /* @__PURE__ */ React6__namespace.createElement("div", { className: "checkbox-group-description" }, description),
236
- /* @__PURE__ */ React6__namespace.createElement("div", { className: "checkbox-options" }, showSelectAll && enabledOptions.length > 0 && /* @__PURE__ */ React6__namespace.createElement("label", { className: "checkbox-option checkbox-option--select-all" }, /* @__PURE__ */ React6__namespace.createElement(
234
+ label && /* @__PURE__ */ React7__namespace.createElement("div", { className: "checkbox-group-label" }, label),
235
+ description && /* @__PURE__ */ React7__namespace.createElement("div", { className: "checkbox-group-description" }, description),
236
+ /* @__PURE__ */ React7__namespace.createElement("div", { className: "checkbox-options" }, showSelectAll && enabledOptions.length > 0 && /* @__PURE__ */ React7__namespace.createElement("label", { className: "checkbox-option checkbox-option--select-all" }, /* @__PURE__ */ React7__namespace.createElement(
237
237
  "input",
238
238
  {
239
239
  type: "checkbox",
@@ -249,18 +249,18 @@ function CheckboxGroup({
249
249
  className: "checkbox-input",
250
250
  "aria-label": selectAllLabel
251
251
  }
252
- ), /* @__PURE__ */ React6__namespace.createElement("div", { className: "checkbox-content" }, /* @__PURE__ */ React6__namespace.createElement("span", { className: "checkbox-label" }, selectAllLabel))), options.map((option) => {
252
+ ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "checkbox-content" }, /* @__PURE__ */ React7__namespace.createElement("span", { className: "checkbox-label" }, selectAllLabel))), options.map((option) => {
253
253
  const isChecked = value.includes(option.value);
254
254
  const isDisabled = disabled || option.disabled || maxReached && !isChecked;
255
255
  const checkboxId = `${name}-${option.value}`;
256
- return /* @__PURE__ */ React6__namespace.createElement(
256
+ return /* @__PURE__ */ React7__namespace.createElement(
257
257
  "label",
258
258
  {
259
259
  key: option.value,
260
260
  className: `checkbox-option ${isDisabled ? "checkbox-option--disabled" : ""}`,
261
261
  htmlFor: checkboxId
262
262
  },
263
- /* @__PURE__ */ React6__namespace.createElement(
263
+ /* @__PURE__ */ React7__namespace.createElement(
264
264
  "input",
265
265
  {
266
266
  type: "checkbox",
@@ -276,7 +276,7 @@ function CheckboxGroup({
276
276
  "aria-describedby": option.description ? `${checkboxId}-description` : props["aria-describedby"]
277
277
  }
278
278
  ),
279
- /* @__PURE__ */ React6__namespace.createElement("div", { className: "checkbox-content" }, renderOption ? renderOption(option) : /* @__PURE__ */ React6__namespace.createElement(React6__namespace.Fragment, null, /* @__PURE__ */ React6__namespace.createElement("span", { className: "checkbox-label" }, option.label), option.description && /* @__PURE__ */ React6__namespace.createElement(
279
+ /* @__PURE__ */ React7__namespace.createElement("div", { className: "checkbox-content" }, renderOption ? renderOption(option) : /* @__PURE__ */ React7__namespace.createElement(React7__namespace.Fragment, null, /* @__PURE__ */ React7__namespace.createElement("span", { className: "checkbox-label" }, option.label), option.description && /* @__PURE__ */ React7__namespace.createElement(
280
280
  "span",
281
281
  {
282
282
  className: "checkbox-description",
@@ -286,7 +286,7 @@ function CheckboxGroup({
286
286
  )))
287
287
  );
288
288
  })),
289
- (minSelections || maxSelections) && /* @__PURE__ */ React6__namespace.createElement("div", { className: "checkbox-group-feedback", "aria-live": "polite" }, minSelections && value.length < minSelections && /* @__PURE__ */ React6__namespace.createElement("span", { className: "checkbox-group-feedback-min" }, "Select at least ", minSelections, " option", minSelections !== 1 ? "s" : ""), maxSelections && /* @__PURE__ */ React6__namespace.createElement("span", { className: "checkbox-group-feedback-max" }, value.length, "/", maxSelections, " selected"))
289
+ (minSelections || maxSelections) && /* @__PURE__ */ React7__namespace.createElement("div", { className: "checkbox-group-feedback", "aria-live": "polite" }, minSelections && value.length < minSelections && /* @__PURE__ */ React7__namespace.createElement("span", { className: "checkbox-group-feedback-min" }, "Select at least ", minSelections, " option", minSelections !== 1 ? "s" : ""), maxSelections && /* @__PURE__ */ React7__namespace.createElement("span", { className: "checkbox-group-feedback-max" }, value.length, "/", maxSelections, " selected"))
290
290
  );
291
291
  }
292
292
  CheckboxGroup.displayName = "CheckboxGroup";
@@ -339,7 +339,7 @@ function Radio({
339
339
  const errorClassName = error ? "radio-group--error" : "";
340
340
  const layoutClassName = `radio-group--${layout}`;
341
341
  const combinedClassName = `${baseClassName} ${errorClassName} ${layoutClassName} ${className}`.trim();
342
- return /* @__PURE__ */ React6__namespace.createElement(
342
+ return /* @__PURE__ */ React7__namespace.createElement(
343
343
  "div",
344
344
  {
345
345
  className: combinedClassName,
@@ -349,19 +349,19 @@ function Radio({
349
349
  "aria-required": required || props["aria-required"],
350
350
  "aria-label": typeof label === "string" ? label : props["aria-label"]
351
351
  },
352
- label && /* @__PURE__ */ React6__namespace.createElement("div", { className: "radio-group-label" }, label),
353
- /* @__PURE__ */ React6__namespace.createElement("div", { className: "radio-options" }, options.map((option, index) => {
352
+ label && /* @__PURE__ */ React7__namespace.createElement("div", { className: "radio-group-label" }, label),
353
+ /* @__PURE__ */ React7__namespace.createElement("div", { className: "radio-options" }, options.map((option, index) => {
354
354
  const isChecked = value === option.value;
355
355
  const isDisabled = disabled || option.disabled;
356
356
  const radioId = `${name}-${option.value}`;
357
- return /* @__PURE__ */ React6__namespace.createElement(
357
+ return /* @__PURE__ */ React7__namespace.createElement(
358
358
  "label",
359
359
  {
360
360
  key: option.value,
361
361
  className: `radio-option ${isDisabled ? "radio-option--disabled" : ""}`,
362
362
  htmlFor: radioId
363
363
  },
364
- /* @__PURE__ */ React6__namespace.createElement(
364
+ /* @__PURE__ */ React7__namespace.createElement(
365
365
  "input",
366
366
  {
367
367
  type: "radio",
@@ -378,7 +378,7 @@ function Radio({
378
378
  "aria-describedby": option.description ? `${radioId}-description` : props["aria-describedby"]
379
379
  }
380
380
  ),
381
- /* @__PURE__ */ React6__namespace.createElement("div", { className: "radio-content" }, /* @__PURE__ */ React6__namespace.createElement("span", { className: "radio-label" }, option.label), option.description && /* @__PURE__ */ React6__namespace.createElement(
381
+ /* @__PURE__ */ React7__namespace.createElement("div", { className: "radio-content" }, /* @__PURE__ */ React7__namespace.createElement("span", { className: "radio-label" }, option.label), option.description && /* @__PURE__ */ React7__namespace.createElement(
382
382
  "span",
383
383
  {
384
384
  className: "radio-description",
@@ -410,19 +410,19 @@ function Select({
410
410
  renderOption,
411
411
  ...props
412
412
  }) {
413
- const [isOpen, setIsOpen] = React6__namespace.useState(false);
414
- const [searchQuery, setSearchQuery] = React6__namespace.useState("");
415
- const [focusedIndex, setFocusedIndex] = React6__namespace.useState(-1);
416
- const selectRef = React6__namespace.useRef(null);
417
- const searchInputRef = React6__namespace.useRef(null);
413
+ const [isOpen, setIsOpen] = React7__namespace.useState(false);
414
+ const [searchQuery, setSearchQuery] = React7__namespace.useState("");
415
+ const [focusedIndex, setFocusedIndex] = React7__namespace.useState(-1);
416
+ const selectRef = React7__namespace.useRef(null);
417
+ const searchInputRef = React7__namespace.useRef(null);
418
418
  const dropdownId = `${name}-dropdown`;
419
- const allOptions = React6__namespace.useMemo(() => {
419
+ const allOptions = React7__namespace.useMemo(() => {
420
420
  if (optionGroups.length > 0) {
421
421
  return optionGroups.flatMap((group) => group.options);
422
422
  }
423
423
  return options;
424
424
  }, [options, optionGroups]);
425
- const filteredOptions = React6__namespace.useMemo(() => {
425
+ const filteredOptions = React7__namespace.useMemo(() => {
426
426
  if (!searchQuery.trim()) {
427
427
  return allOptions;
428
428
  }
@@ -432,7 +432,7 @@ function Select({
432
432
  return label.toLowerCase().includes(query);
433
433
  });
434
434
  }, [allOptions, searchQuery]);
435
- const selectedOption = React6__namespace.useMemo(() => {
435
+ const selectedOption = React7__namespace.useMemo(() => {
436
436
  return allOptions.find((opt) => opt.value === value);
437
437
  }, [allOptions, value]);
438
438
  const handleSelect = (optionValue) => {
@@ -536,7 +536,7 @@ function Select({
536
536
  const handleBlur = () => {
537
537
  onBlur?.();
538
538
  };
539
- React6__namespace.useEffect(() => {
539
+ React7__namespace.useEffect(() => {
540
540
  const handleClickOutside = (event) => {
541
541
  if (selectRef.current && !selectRef.current.contains(event.target)) {
542
542
  setIsOpen(false);
@@ -557,7 +557,7 @@ function Select({
557
557
  const disabledClassName = disabled ? "select--disabled" : "";
558
558
  const openClassName = isOpen ? "select--open" : "";
559
559
  const combinedClassName = `${baseClassName} ${errorClassName} ${disabledClassName} ${openClassName} ${className}`.trim();
560
- return /* @__PURE__ */ React6__namespace.createElement(
560
+ return /* @__PURE__ */ React7__namespace.createElement(
561
561
  "div",
562
562
  {
563
563
  ref: selectRef,
@@ -565,7 +565,7 @@ function Select({
565
565
  onKeyDown: handleKeyDown,
566
566
  onBlur: handleBlur
567
567
  },
568
- /* @__PURE__ */ React6__namespace.createElement(
568
+ /* @__PURE__ */ React7__namespace.createElement(
569
569
  "select",
570
570
  {
571
571
  name,
@@ -578,10 +578,10 @@ function Select({
578
578
  tabIndex: -1,
579
579
  style: { display: "none" }
580
580
  },
581
- /* @__PURE__ */ React6__namespace.createElement("option", { value: "" }, "Select..."),
582
- allOptions.map((option) => /* @__PURE__ */ React6__namespace.createElement("option", { key: option.value, value: option.value }, typeof option.label === "string" ? option.label : option.value))
581
+ /* @__PURE__ */ React7__namespace.createElement("option", { value: "" }, "Select..."),
582
+ allOptions.map((option) => /* @__PURE__ */ React7__namespace.createElement("option", { key: option.value, value: option.value }, typeof option.label === "string" ? option.label : option.value))
583
583
  ),
584
- /* @__PURE__ */ React6__namespace.createElement(
584
+ /* @__PURE__ */ React7__namespace.createElement(
585
585
  "div",
586
586
  {
587
587
  className: "select-trigger",
@@ -595,8 +595,8 @@ function Select({
595
595
  "aria-disabled": disabled,
596
596
  tabIndex: disabled ? -1 : 0
597
597
  },
598
- /* @__PURE__ */ React6__namespace.createElement("span", { className: "select-value" }, selectedOption ? renderOption ? renderOption(selectedOption) : selectedOption.label : /* @__PURE__ */ React6__namespace.createElement("span", { className: "select-placeholder" }, placeholder)),
599
- /* @__PURE__ */ React6__namespace.createElement("div", { className: "select-icons" }, loading && /* @__PURE__ */ React6__namespace.createElement("span", { className: "select-loading" }, "\u23F3"), clearable && value && !disabled && !loading && /* @__PURE__ */ React6__namespace.createElement(
598
+ /* @__PURE__ */ React7__namespace.createElement("span", { className: "select-value" }, selectedOption ? renderOption ? renderOption(selectedOption) : selectedOption.label : /* @__PURE__ */ React7__namespace.createElement("span", { className: "select-placeholder" }, placeholder)),
599
+ /* @__PURE__ */ React7__namespace.createElement("div", { className: "select-icons" }, loading && /* @__PURE__ */ React7__namespace.createElement("span", { className: "select-loading" }, "\u23F3"), clearable && value && !disabled && !loading && /* @__PURE__ */ React7__namespace.createElement(
600
600
  "button",
601
601
  {
602
602
  type: "button",
@@ -606,9 +606,9 @@ function Select({
606
606
  tabIndex: -1
607
607
  },
608
608
  "\u2715"
609
- ), /* @__PURE__ */ React6__namespace.createElement("span", { className: "select-arrow", "aria-hidden": "true" }, isOpen ? "\u25B2" : "\u25BC"))
609
+ ), /* @__PURE__ */ React7__namespace.createElement("span", { className: "select-arrow", "aria-hidden": "true" }, isOpen ? "\u25B2" : "\u25BC"))
610
610
  ),
611
- isOpen && /* @__PURE__ */ React6__namespace.createElement("div", { id: dropdownId, className: "select-dropdown", role: "listbox" }, searchable && /* @__PURE__ */ React6__namespace.createElement("div", { className: "select-search" }, /* @__PURE__ */ React6__namespace.createElement(
611
+ isOpen && /* @__PURE__ */ React7__namespace.createElement("div", { id: dropdownId, className: "select-dropdown", role: "listbox" }, searchable && /* @__PURE__ */ React7__namespace.createElement("div", { className: "select-search" }, /* @__PURE__ */ React7__namespace.createElement(
612
612
  "input",
613
613
  {
614
614
  ref: searchInputRef,
@@ -620,19 +620,19 @@ function Select({
620
620
  onClick: (e) => e.stopPropagation(),
621
621
  "aria-label": "Search options"
622
622
  }
623
- )), /* @__PURE__ */ React6__namespace.createElement("div", { className: "select-options" }, filteredOptions.length === 0 ? /* @__PURE__ */ React6__namespace.createElement("div", { className: "select-no-options" }, "No options found") : optionGroups.length > 0 ? (
623
+ )), /* @__PURE__ */ React7__namespace.createElement("div", { className: "select-options" }, filteredOptions.length === 0 ? /* @__PURE__ */ React7__namespace.createElement("div", { className: "select-no-options" }, "No options found") : optionGroups.length > 0 ? (
624
624
  // Render grouped options
625
625
  optionGroups.map((group, groupIndex) => {
626
626
  const groupOptions = group.options.filter(
627
627
  (opt) => filteredOptions.includes(opt)
628
628
  );
629
629
  if (groupOptions.length === 0) return null;
630
- return /* @__PURE__ */ React6__namespace.createElement("div", { key: groupIndex, className: "select-optgroup" }, /* @__PURE__ */ React6__namespace.createElement("div", { className: "select-optgroup-label" }, group.label), groupOptions.map((option) => {
630
+ return /* @__PURE__ */ React7__namespace.createElement("div", { key: groupIndex, className: "select-optgroup" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "select-optgroup-label" }, group.label), groupOptions.map((option) => {
631
631
  const globalIndex = filteredOptions.indexOf(option);
632
632
  const isSelected = value === option.value;
633
633
  const isFocused = globalIndex === focusedIndex;
634
634
  const isDisabled = option.disabled;
635
- return /* @__PURE__ */ React6__namespace.createElement(
635
+ return /* @__PURE__ */ React7__namespace.createElement(
636
636
  "div",
637
637
  {
638
638
  key: option.value,
@@ -652,7 +652,7 @@ function Select({
652
652
  const isSelected = value === option.value;
653
653
  const isFocused = index === focusedIndex;
654
654
  const isDisabled = option.disabled;
655
- return /* @__PURE__ */ React6__namespace.createElement(
655
+ return /* @__PURE__ */ React7__namespace.createElement(
656
656
  "div",
657
657
  {
658
658
  key: option.value,
@@ -685,13 +685,23 @@ function FileInput({
685
685
  maxFiles = 1,
686
686
  multiple = false,
687
687
  showPreview = true,
688
+ showProgress = true,
689
+ uploadProgress = {},
690
+ enableCropping = false,
691
+ cropAspectRatio,
692
+ onCropComplete,
688
693
  onValidationError,
689
694
  onFileRemove,
690
695
  ...props
691
696
  }) {
692
- const inputRef = React6__namespace.useRef(null);
693
- const [dragActive, setDragActive] = React6__namespace.useState(false);
694
- const validateFile = React6__namespace.useCallback(
697
+ const inputRef = React7__namespace.useRef(null);
698
+ const [dragActive, setDragActive] = React7__namespace.useState(false);
699
+ const [cropperOpen, setCropperOpen] = React7__namespace.useState(false);
700
+ const [imageToCrop, setImageToCrop] = React7__namespace.useState(null);
701
+ const [crop, setCrop] = React7__namespace.useState({ x: 0, y: 0 });
702
+ const [zoom, setZoom] = React7__namespace.useState(1);
703
+ const [croppedAreaPixels, setCroppedAreaPixels] = React7__namespace.useState(null);
704
+ const validateFile = React7__namespace.useCallback(
695
705
  (file) => {
696
706
  if (accept) {
697
707
  const acceptedTypes = accept.split(",").map((t) => t.trim());
@@ -726,7 +736,7 @@ function FileInput({
726
736
  },
727
737
  [accept, maxSize]
728
738
  );
729
- const handleFiles = React6__namespace.useCallback(
739
+ const handleFiles = React7__namespace.useCallback(
730
740
  (fileList) => {
731
741
  if (!fileList || fileList.length === 0) return;
732
742
  const newFiles = Array.from(fileList);
@@ -753,14 +763,110 @@ function FileInput({
753
763
  onValidationError(validationErrors);
754
764
  }
755
765
  if (validFiles.length > 0 && totalFiles <= maxFiles) {
756
- const updatedFiles = multiple ? [...value, ...validFiles] : validFiles;
757
- onChange(updatedFiles.slice(0, maxFiles));
766
+ const firstImage = validFiles.find((f) => f.type.startsWith("image/"));
767
+ if (enableCropping && firstImage && !multiple) {
768
+ const previewUrl = URL.createObjectURL(firstImage);
769
+ setImageToCrop({ file: firstImage, url: previewUrl });
770
+ setCropperOpen(true);
771
+ } else {
772
+ const updatedFiles = multiple ? [...value, ...validFiles] : validFiles;
773
+ onChange(updatedFiles.slice(0, maxFiles));
774
+ }
758
775
  }
759
776
  if (inputRef.current) {
760
777
  inputRef.current.value = "";
761
778
  }
762
779
  },
763
- [value, onChange, validateFile, maxFiles, multiple, onValidationError]
780
+ [value, onChange, validateFile, maxFiles, multiple, enableCropping, onValidationError]
781
+ );
782
+ const createCroppedImage = React7__namespace.useCallback(
783
+ async (imageUrl, cropArea) => {
784
+ return new Promise((resolve, reject) => {
785
+ const image = new Image();
786
+ image.onload = () => {
787
+ const canvas = document.createElement("canvas");
788
+ const ctx = canvas.getContext("2d");
789
+ if (!ctx) {
790
+ reject(new Error("Failed to get canvas context"));
791
+ return;
792
+ }
793
+ canvas.width = cropArea.width;
794
+ canvas.height = cropArea.height;
795
+ ctx.drawImage(
796
+ image,
797
+ cropArea.x,
798
+ cropArea.y,
799
+ cropArea.width,
800
+ cropArea.height,
801
+ 0,
802
+ 0,
803
+ cropArea.width,
804
+ cropArea.height
805
+ );
806
+ canvas.toBlob((blob) => {
807
+ if (blob) {
808
+ resolve(blob);
809
+ } else {
810
+ reject(new Error("Failed to create blob from canvas"));
811
+ }
812
+ }, "image/jpeg", 0.95);
813
+ };
814
+ image.onerror = () => {
815
+ reject(new Error("Failed to load image"));
816
+ };
817
+ image.src = imageUrl;
818
+ });
819
+ },
820
+ []
821
+ );
822
+ const handleCropSave = React7__namespace.useCallback(async () => {
823
+ if (!imageToCrop || !croppedAreaPixels) return;
824
+ try {
825
+ const croppedBlob = await createCroppedImage(
826
+ imageToCrop.url,
827
+ croppedAreaPixels
828
+ );
829
+ if (onCropComplete) {
830
+ onCropComplete(croppedBlob, imageToCrop.file);
831
+ }
832
+ const croppedFile = new File(
833
+ [croppedBlob],
834
+ imageToCrop.file.name,
835
+ { type: "image/jpeg" }
836
+ );
837
+ const updatedFiles = multiple ? [...value, croppedFile] : [croppedFile];
838
+ onChange(updatedFiles);
839
+ setCropperOpen(false);
840
+ URL.revokeObjectURL(imageToCrop.url);
841
+ setImageToCrop(null);
842
+ setCrop({ x: 0, y: 0 });
843
+ setZoom(1);
844
+ setCroppedAreaPixels(null);
845
+ } catch (error2) {
846
+ console.error("Failed to crop image:", error2);
847
+ }
848
+ }, [imageToCrop, croppedAreaPixels, createCroppedImage, onCropComplete, value, onChange, multiple]);
849
+ const handleCropCancel = React7__namespace.useCallback(() => {
850
+ if (imageToCrop) {
851
+ URL.revokeObjectURL(imageToCrop.url);
852
+ }
853
+ setCropperOpen(false);
854
+ setImageToCrop(null);
855
+ setCrop({ x: 0, y: 0 });
856
+ setZoom(1);
857
+ setCroppedAreaPixels(null);
858
+ }, [imageToCrop]);
859
+ const onCropChange = React7__namespace.useCallback((crop2) => {
860
+ setCrop(crop2);
861
+ }, []);
862
+ const onZoomChange = React7__namespace.useCallback((zoom2) => {
863
+ setZoom(zoom2);
864
+ }, []);
865
+ const onCropCompleteInternal = React7__namespace.useCallback(
866
+ (_, croppedAreaPixels2) => {
867
+ setCroppedAreaPixels(croppedAreaPixels2);
868
+ },
869
+ []
764
870
  );
765
871
  const handleChange = (e) => {
766
872
  handleFiles(e.target.files);
@@ -773,6 +879,12 @@ function FileInput({
773
879
  onFileRemove(fileToRemove, index);
774
880
  }
775
881
  };
882
+ const handleCrop = (file) => {
883
+ if (!file.type.startsWith("image/")) return;
884
+ const previewUrl = URL.createObjectURL(file);
885
+ setImageToCrop({ file, url: previewUrl });
886
+ setCropperOpen(true);
887
+ };
776
888
  const handleDrag = (e) => {
777
889
  e.preventDefault();
778
890
  e.stopPropagation();
@@ -811,7 +923,7 @@ function FileInput({
811
923
  }
812
924
  return null;
813
925
  };
814
- React6__namespace.useEffect(() => {
926
+ React7__namespace.useEffect(() => {
815
927
  return () => {
816
928
  value.forEach((file) => {
817
929
  const previewUrl = getPreviewUrl(file);
@@ -819,14 +931,17 @@ function FileInput({
819
931
  URL.revokeObjectURL(previewUrl);
820
932
  }
821
933
  });
934
+ if (imageToCrop) {
935
+ URL.revokeObjectURL(imageToCrop.url);
936
+ }
822
937
  };
823
- }, [value]);
938
+ }, [value, imageToCrop]);
824
939
  const baseClassName = "file-input";
825
940
  const errorClassName = error ? "file-input--error" : "";
826
941
  const dragClassName = dragActive ? "file-input--drag-active" : "";
827
942
  const disabledClassName = disabled ? "file-input--disabled" : "";
828
943
  const combinedClassName = `${baseClassName} ${errorClassName} ${dragClassName} ${disabledClassName} ${className}`.trim();
829
- return /* @__PURE__ */ React6__namespace.createElement("div", { className: combinedClassName }, /* @__PURE__ */ React6__namespace.createElement(
944
+ return /* @__PURE__ */ React7__namespace.createElement("div", { className: combinedClassName }, /* @__PURE__ */ React7__namespace.createElement(
830
945
  "input",
831
946
  {
832
947
  ref: inputRef,
@@ -844,7 +959,7 @@ function FileInput({
844
959
  "aria-required": required || props["aria-required"],
845
960
  style: { display: "none" }
846
961
  }
847
- ), /* @__PURE__ */ React6__namespace.createElement(
962
+ ), /* @__PURE__ */ React7__namespace.createElement(
848
963
  "div",
849
964
  {
850
965
  className: "file-input__dropzone",
@@ -859,7 +974,7 @@ function FileInput({
859
974
  "aria-label": placeholder,
860
975
  "aria-disabled": disabled
861
976
  },
862
- /* @__PURE__ */ React6__namespace.createElement("div", { className: "file-input__dropzone-content" }, /* @__PURE__ */ React6__namespace.createElement(
977
+ /* @__PURE__ */ React7__namespace.createElement("div", { className: "file-input__dropzone-content" }, /* @__PURE__ */ React7__namespace.createElement(
863
978
  "svg",
864
979
  {
865
980
  className: "file-input__icon",
@@ -873,13 +988,13 @@ function FileInput({
873
988
  strokeLinejoin: "round",
874
989
  "aria-hidden": "true"
875
990
  },
876
- /* @__PURE__ */ React6__namespace.createElement("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
877
- /* @__PURE__ */ React6__namespace.createElement("polyline", { points: "17 8 12 3 7 8" }),
878
- /* @__PURE__ */ React6__namespace.createElement("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
879
- ), /* @__PURE__ */ React6__namespace.createElement("p", { className: "file-input__placeholder" }, value.length > 0 ? `${value.length} file(s) selected` : placeholder), accept && /* @__PURE__ */ React6__namespace.createElement("p", { className: "file-input__hint" }, "Accepted: ", accept), maxSize && /* @__PURE__ */ React6__namespace.createElement("p", { className: "file-input__hint" }, "Max size: ", formatFileSize(maxSize)))
880
- ), value.length > 0 && /* @__PURE__ */ React6__namespace.createElement("ul", { className: "file-input__list", role: "list" }, value.map((file, index) => {
991
+ /* @__PURE__ */ React7__namespace.createElement("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
992
+ /* @__PURE__ */ React7__namespace.createElement("polyline", { points: "17 8 12 3 7 8" }),
993
+ /* @__PURE__ */ React7__namespace.createElement("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
994
+ ), /* @__PURE__ */ React7__namespace.createElement("p", { className: "file-input__placeholder" }, value.length > 0 ? `${value.length} file(s) selected` : placeholder), accept && /* @__PURE__ */ React7__namespace.createElement("p", { className: "file-input__hint" }, "Accepted: ", accept), maxSize && /* @__PURE__ */ React7__namespace.createElement("p", { className: "file-input__hint" }, "Max size: ", formatFileSize(maxSize)))
995
+ ), value.length > 0 && /* @__PURE__ */ React7__namespace.createElement("ul", { className: "file-input__list", role: "list" }, value.map((file, index) => {
881
996
  const previewUrl = showPreview ? getPreviewUrl(file) : null;
882
- return /* @__PURE__ */ React6__namespace.createElement("li", { key: `${file.name}-${index}`, className: "file-input__item" }, previewUrl && /* @__PURE__ */ React6__namespace.createElement(
997
+ return /* @__PURE__ */ React7__namespace.createElement("li", { key: `${file.name}-${index}`, className: "file-input__item" }, previewUrl && /* @__PURE__ */ React7__namespace.createElement(
883
998
  "img",
884
999
  {
885
1000
  src: previewUrl,
@@ -888,7 +1003,46 @@ function FileInput({
888
1003
  width: "48",
889
1004
  height: "48"
890
1005
  }
891
- ), /* @__PURE__ */ React6__namespace.createElement("div", { className: "file-input__details" }, /* @__PURE__ */ React6__namespace.createElement("span", { className: "file-input__filename" }, file.name), /* @__PURE__ */ React6__namespace.createElement("span", { className: "file-input__filesize" }, formatFileSize(file.size))), /* @__PURE__ */ React6__namespace.createElement(
1006
+ ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "file-input__details" }, /* @__PURE__ */ React7__namespace.createElement("span", { className: "file-input__filename" }, file.name), /* @__PURE__ */ React7__namespace.createElement("span", { className: "file-input__filesize" }, formatFileSize(file.size)), showProgress && uploadProgress[file.name] !== void 0 && /* @__PURE__ */ React7__namespace.createElement("div", { className: "file-input__progress" }, /* @__PURE__ */ React7__namespace.createElement(
1007
+ "div",
1008
+ {
1009
+ className: "file-input__progress-bar",
1010
+ style: { width: `${uploadProgress[file.name]}%` },
1011
+ role: "progressbar",
1012
+ "aria-valuenow": uploadProgress[file.name],
1013
+ "aria-valuemin": 0,
1014
+ "aria-valuemax": 100,
1015
+ "aria-label": `Upload progress: ${uploadProgress[file.name]}%`
1016
+ }
1017
+ ), /* @__PURE__ */ React7__namespace.createElement("span", { className: "file-input__progress-text" }, uploadProgress[file.name], "%"))), enableCropping && file.type.startsWith("image/") && /* @__PURE__ */ React7__namespace.createElement(
1018
+ "button",
1019
+ {
1020
+ type: "button",
1021
+ onClick: (e) => {
1022
+ e.stopPropagation();
1023
+ handleCrop(file);
1024
+ },
1025
+ disabled,
1026
+ className: "file-input__crop",
1027
+ "aria-label": `Crop ${file.name}`
1028
+ },
1029
+ /* @__PURE__ */ React7__namespace.createElement(
1030
+ "svg",
1031
+ {
1032
+ width: "20",
1033
+ height: "20",
1034
+ viewBox: "0 0 24 24",
1035
+ fill: "none",
1036
+ stroke: "currentColor",
1037
+ strokeWidth: "2",
1038
+ strokeLinecap: "round",
1039
+ strokeLinejoin: "round",
1040
+ "aria-hidden": "true"
1041
+ },
1042
+ /* @__PURE__ */ React7__namespace.createElement("path", { d: "M6.13 1L6 16a2 2 0 0 0 2 2h15" }),
1043
+ /* @__PURE__ */ React7__namespace.createElement("path", { d: "M1 6.13L16 6a2 2 0 0 1 2 2v15" })
1044
+ )
1045
+ ), /* @__PURE__ */ React7__namespace.createElement(
892
1046
  "button",
893
1047
  {
894
1048
  type: "button",
@@ -900,7 +1054,7 @@ function FileInput({
900
1054
  className: "file-input__remove",
901
1055
  "aria-label": `Remove ${file.name}`
902
1056
  },
903
- /* @__PURE__ */ React6__namespace.createElement(
1057
+ /* @__PURE__ */ React7__namespace.createElement(
904
1058
  "svg",
905
1059
  {
906
1060
  width: "20",
@@ -913,20 +1067,1077 @@ function FileInput({
913
1067
  strokeLinejoin: "round",
914
1068
  "aria-hidden": "true"
915
1069
  },
916
- /* @__PURE__ */ React6__namespace.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
917
- /* @__PURE__ */ React6__namespace.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1070
+ /* @__PURE__ */ React7__namespace.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1071
+ /* @__PURE__ */ React7__namespace.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
918
1072
  )
919
1073
  ));
920
- })));
1074
+ })), cropperOpen && imageToCrop && /* @__PURE__ */ React7__namespace.createElement("div", { className: "file-input-cropper-modal" }, /* @__PURE__ */ React7__namespace.createElement(
1075
+ "div",
1076
+ {
1077
+ className: "file-input-cropper-overlay",
1078
+ onClick: handleCropCancel,
1079
+ "aria-label": "Close cropper"
1080
+ }
1081
+ ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "file-input-cropper-container" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "file-input-cropper-header" }, /* @__PURE__ */ React7__namespace.createElement("h3", { className: "file-input-cropper-title" }, "Crop Image"), /* @__PURE__ */ React7__namespace.createElement(
1082
+ "button",
1083
+ {
1084
+ type: "button",
1085
+ className: "file-input-cropper-close",
1086
+ onClick: handleCropCancel,
1087
+ "aria-label": "Close"
1088
+ },
1089
+ "\u2715"
1090
+ )), /* @__PURE__ */ React7__namespace.createElement("div", { className: "file-input-cropper-content" }, /* @__PURE__ */ React7__namespace.createElement(
1091
+ "div",
1092
+ {
1093
+ className: "file-input-cropper-image-container",
1094
+ onMouseDown: (e) => {
1095
+ e.preventDefault();
1096
+ const startX = e.clientX - crop.x;
1097
+ const startY = e.clientY - crop.y;
1098
+ const handleMouseMove = (moveEvent) => {
1099
+ onCropChange({
1100
+ x: moveEvent.clientX - startX,
1101
+ y: moveEvent.clientY - startY
1102
+ });
1103
+ };
1104
+ const handleMouseUp = () => {
1105
+ document.removeEventListener("mousemove", handleMouseMove);
1106
+ document.removeEventListener("mouseup", handleMouseUp);
1107
+ };
1108
+ document.addEventListener("mousemove", handleMouseMove);
1109
+ document.addEventListener("mouseup", handleMouseUp);
1110
+ }
1111
+ },
1112
+ /* @__PURE__ */ React7__namespace.createElement(
1113
+ "img",
1114
+ {
1115
+ src: imageToCrop.url,
1116
+ alt: "Crop preview",
1117
+ className: "file-input-cropper-image",
1118
+ style: {
1119
+ transform: `translate(${crop.x}px, ${crop.y}px) scale(${zoom})`
1120
+ },
1121
+ draggable: false,
1122
+ onLoad: (e) => {
1123
+ const img = e.currentTarget;
1124
+ const containerWidth = 600;
1125
+ const containerHeight = 400;
1126
+ const cropWidth = cropAspectRatio ? Math.min(containerWidth * 0.8, containerHeight * 0.8 * cropAspectRatio) : containerWidth * 0.8;
1127
+ const cropHeight = cropAspectRatio ? cropWidth / cropAspectRatio : containerHeight * 0.8;
1128
+ const scale = zoom;
1129
+ const imgWidth = img.naturalWidth;
1130
+ const imgHeight = img.naturalHeight;
1131
+ const centerX = containerWidth / 2;
1132
+ const centerY = containerHeight / 2;
1133
+ const cropX = (centerX - crop.x - cropWidth / 2) / scale;
1134
+ const cropY = (centerY - crop.y - cropHeight / 2) / scale;
1135
+ onCropCompleteInternal(null, {
1136
+ x: Math.max(0, cropX),
1137
+ y: Math.max(0, cropY),
1138
+ width: Math.min(cropWidth / scale, imgWidth),
1139
+ height: Math.min(cropHeight / scale, imgHeight)
1140
+ });
1141
+ }
1142
+ }
1143
+ ),
1144
+ /* @__PURE__ */ React7__namespace.createElement(
1145
+ "div",
1146
+ {
1147
+ className: "file-input-cropper-overlay-box",
1148
+ style: {
1149
+ width: cropAspectRatio ? `${Math.min(80, 80 * cropAspectRatio)}%` : "80%",
1150
+ aspectRatio: cropAspectRatio ? String(cropAspectRatio) : void 0
1151
+ }
1152
+ },
1153
+ /* @__PURE__ */ React7__namespace.createElement("div", { className: "file-input-cropper-grid" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "file-input-cropper-grid-line" }), /* @__PURE__ */ React7__namespace.createElement("div", { className: "file-input-cropper-grid-line" }))
1154
+ )
1155
+ ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "file-input-cropper-controls" }, /* @__PURE__ */ React7__namespace.createElement("label", { htmlFor: "zoom-slider", className: "file-input-cropper-label" }, "Zoom: ", zoom.toFixed(1), "x"), /* @__PURE__ */ React7__namespace.createElement(
1156
+ "input",
1157
+ {
1158
+ id: "zoom-slider",
1159
+ type: "range",
1160
+ min: "1",
1161
+ max: "3",
1162
+ step: "0.1",
1163
+ value: zoom,
1164
+ onChange: (e) => onZoomChange(parseFloat(e.target.value)),
1165
+ className: "file-input-cropper-slider",
1166
+ "aria-label": "Zoom level"
1167
+ }
1168
+ ))), /* @__PURE__ */ React7__namespace.createElement("div", { className: "file-input-cropper-footer" }, /* @__PURE__ */ React7__namespace.createElement(
1169
+ "button",
1170
+ {
1171
+ type: "button",
1172
+ className: "file-input-cropper-button file-input-cropper-button--cancel",
1173
+ onClick: handleCropCancel
1174
+ },
1175
+ "Cancel"
1176
+ ), /* @__PURE__ */ React7__namespace.createElement(
1177
+ "button",
1178
+ {
1179
+ type: "button",
1180
+ className: "file-input-cropper-button file-input-cropper-button--save",
1181
+ onClick: handleCropSave
1182
+ },
1183
+ "Save"
1184
+ )))));
921
1185
  }
922
1186
  FileInput.displayName = "FileInput";
1187
+ function formatDate(date, format) {
1188
+ if (!date) return "";
1189
+ const d = new Date(date);
1190
+ const month = String(d.getMonth() + 1).padStart(2, "0");
1191
+ const day = String(d.getDate()).padStart(2, "0");
1192
+ const year = d.getFullYear();
1193
+ return format.replace("MM", month).replace("dd", day).replace("yyyy", String(year)).replace("yy", String(year).slice(2));
1194
+ }
1195
+ function parseDate(dateString, format) {
1196
+ if (!dateString) return null;
1197
+ try {
1198
+ if (format === "MM/dd/yyyy" || format === "MM-dd-yyyy") {
1199
+ const parts = dateString.split(/[/-]/);
1200
+ if (parts.length === 3) {
1201
+ const month = parseInt(parts[0], 10) - 1;
1202
+ const day = parseInt(parts[1], 10);
1203
+ const year = parseInt(parts[2], 10);
1204
+ const date2 = new Date(year, month, day);
1205
+ if (!isNaN(date2.getTime())) {
1206
+ return date2;
1207
+ }
1208
+ }
1209
+ }
1210
+ const date = new Date(dateString);
1211
+ return isNaN(date.getTime()) ? null : date;
1212
+ } catch {
1213
+ return null;
1214
+ }
1215
+ }
1216
+ function isDateInArray(date, dates) {
1217
+ const dateStr = date.toDateString();
1218
+ return dates.some((d) => d.toDateString() === dateStr);
1219
+ }
1220
+ function DatePicker({
1221
+ name,
1222
+ value,
1223
+ onChange,
1224
+ onBlur,
1225
+ disabled = false,
1226
+ required = false,
1227
+ error = false,
1228
+ className = "",
1229
+ placeholder = "Select date...",
1230
+ format = "MM/dd/yyyy",
1231
+ minDate,
1232
+ maxDate,
1233
+ disabledDates = [],
1234
+ isDateDisabled,
1235
+ clearable = true,
1236
+ showIcon = true,
1237
+ ...props
1238
+ }) {
1239
+ const [isOpen, setIsOpen] = React7__namespace.useState(false);
1240
+ const [inputValue, setInputValue] = React7__namespace.useState("");
1241
+ const [selectedMonth, setSelectedMonth] = React7__namespace.useState(value || /* @__PURE__ */ new Date());
1242
+ const containerRef = React7__namespace.useRef(null);
1243
+ const inputRef = React7__namespace.useRef(null);
1244
+ React7__namespace.useEffect(() => {
1245
+ setInputValue(formatDate(value, format));
1246
+ if (value) {
1247
+ setSelectedMonth(value);
1248
+ }
1249
+ }, [value, format]);
1250
+ const handleDateSelect = (date) => {
1251
+ onChange(date);
1252
+ setIsOpen(false);
1253
+ onBlur?.();
1254
+ };
1255
+ const handleInputChange = (e) => {
1256
+ const newValue = e.target.value;
1257
+ setInputValue(newValue);
1258
+ const parsedDate = parseDate(newValue, format);
1259
+ if (parsedDate && !isNaN(parsedDate.getTime())) {
1260
+ onChange(parsedDate);
1261
+ } else if (newValue === "") {
1262
+ onChange(null);
1263
+ }
1264
+ };
1265
+ const handleClear = (e) => {
1266
+ e.stopPropagation();
1267
+ onChange(null);
1268
+ setInputValue("");
1269
+ inputRef.current?.focus();
1270
+ };
1271
+ const handleToggle = () => {
1272
+ if (disabled) return;
1273
+ setIsOpen(!isOpen);
1274
+ };
1275
+ const isDisabled = (date) => {
1276
+ if (minDate && date < minDate) return true;
1277
+ if (maxDate && date > maxDate) return true;
1278
+ if (isDateInArray(date, disabledDates)) return true;
1279
+ if (isDateDisabled && isDateDisabled(date)) return true;
1280
+ return false;
1281
+ };
1282
+ React7__namespace.useEffect(() => {
1283
+ const handleClickOutside = (event) => {
1284
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
1285
+ setIsOpen(false);
1286
+ onBlur?.();
1287
+ }
1288
+ };
1289
+ if (isOpen) {
1290
+ document.addEventListener("mousedown", handleClickOutside);
1291
+ return () => {
1292
+ document.removeEventListener("mousedown", handleClickOutside);
1293
+ };
1294
+ }
1295
+ }, [isOpen, onBlur]);
1296
+ const renderCalendar = () => {
1297
+ const year = selectedMonth.getFullYear();
1298
+ const month = selectedMonth.getMonth();
1299
+ const daysInMonth = new Date(year, month + 1, 0).getDate();
1300
+ const firstDayOfMonth = new Date(year, month, 1).getDay();
1301
+ const days = [];
1302
+ for (let i = 0; i < firstDayOfMonth; i++) {
1303
+ days.push(null);
1304
+ }
1305
+ for (let day = 1; day <= daysInMonth; day++) {
1306
+ days.push(new Date(year, month, day));
1307
+ }
1308
+ const monthNames = [
1309
+ "January",
1310
+ "February",
1311
+ "March",
1312
+ "April",
1313
+ "May",
1314
+ "June",
1315
+ "July",
1316
+ "August",
1317
+ "September",
1318
+ "October",
1319
+ "November",
1320
+ "December"
1321
+ ];
1322
+ const handlePrevMonth = () => {
1323
+ setSelectedMonth(new Date(year, month - 1, 1));
1324
+ };
1325
+ const handleNextMonth = () => {
1326
+ setSelectedMonth(new Date(year, month + 1, 1));
1327
+ };
1328
+ return /* @__PURE__ */ React7__namespace.createElement("div", { className: "datepicker-calendar", role: "grid", "aria-label": "Calendar" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "datepicker-calendar-header" }, /* @__PURE__ */ React7__namespace.createElement(
1329
+ "button",
1330
+ {
1331
+ type: "button",
1332
+ className: "datepicker-calendar-nav",
1333
+ onClick: handlePrevMonth,
1334
+ "aria-label": "Previous month"
1335
+ },
1336
+ "\u2190"
1337
+ ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "datepicker-calendar-month" }, monthNames[month], " ", year), /* @__PURE__ */ React7__namespace.createElement(
1338
+ "button",
1339
+ {
1340
+ type: "button",
1341
+ className: "datepicker-calendar-nav",
1342
+ onClick: handleNextMonth,
1343
+ "aria-label": "Next month"
1344
+ },
1345
+ "\u2192"
1346
+ )), /* @__PURE__ */ React7__namespace.createElement("div", { className: "datepicker-calendar-weekdays" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7__namespace.createElement("div", { key: day, className: "datepicker-calendar-weekday" }, day))), /* @__PURE__ */ React7__namespace.createElement("div", { className: "datepicker-calendar-days" }, days.map((date, index) => {
1347
+ if (!date) {
1348
+ return /* @__PURE__ */ React7__namespace.createElement("div", { key: `empty-${index}`, className: "datepicker-calendar-day datepicker-calendar-day--empty" });
1349
+ }
1350
+ const isSelected = value && date.toDateString() === value.toDateString();
1351
+ const isToday = date.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
1352
+ const disabled2 = isDisabled(date);
1353
+ return /* @__PURE__ */ React7__namespace.createElement(
1354
+ "button",
1355
+ {
1356
+ key: date.toISOString(),
1357
+ type: "button",
1358
+ className: `datepicker-calendar-day ${isSelected ? "datepicker-calendar-day--selected" : ""} ${isToday ? "datepicker-calendar-day--today" : ""} ${disabled2 ? "datepicker-calendar-day--disabled" : ""}`,
1359
+ onClick: () => !disabled2 && handleDateSelect(date),
1360
+ disabled: disabled2,
1361
+ "aria-label": formatDate(date, format)
1362
+ },
1363
+ date.getDate()
1364
+ );
1365
+ })));
1366
+ };
1367
+ const baseClassName = "datepicker";
1368
+ const errorClassName = error ? "datepicker--error" : "";
1369
+ const disabledClassName = disabled ? "datepicker--disabled" : "";
1370
+ const openClassName = isOpen ? "datepicker--open" : "";
1371
+ const combinedClassName = `${baseClassName} ${errorClassName} ${disabledClassName} ${openClassName} ${className}`.trim();
1372
+ return /* @__PURE__ */ React7__namespace.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7__namespace.createElement(
1373
+ "input",
1374
+ {
1375
+ type: "hidden",
1376
+ name,
1377
+ value: value ? value.toISOString() : ""
1378
+ }
1379
+ ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "datepicker-input-wrapper" }, showIcon && /* @__PURE__ */ React7__namespace.createElement("span", { className: "datepicker-icon", "aria-hidden": "true" }, /* @__PURE__ */ React7__namespace.createElement(
1380
+ "svg",
1381
+ {
1382
+ xmlns: "http://www.w3.org/2000/svg",
1383
+ width: "18",
1384
+ height: "18",
1385
+ viewBox: "0 0 24 24",
1386
+ fill: "none",
1387
+ stroke: "currentColor",
1388
+ strokeLinecap: "round",
1389
+ strokeLinejoin: "round",
1390
+ strokeWidth: "2"
1391
+ },
1392
+ /* @__PURE__ */ React7__namespace.createElement("path", { d: "M8 2v4m8-4v4m5 8V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8M3 10h18m-5 10l2 2l4-4" })
1393
+ )), /* @__PURE__ */ React7__namespace.createElement(
1394
+ "input",
1395
+ {
1396
+ ref: inputRef,
1397
+ type: "text",
1398
+ className: "datepicker-input",
1399
+ value: inputValue,
1400
+ onChange: handleInputChange,
1401
+ onClick: handleToggle,
1402
+ onBlur,
1403
+ disabled,
1404
+ required,
1405
+ placeholder,
1406
+ "aria-invalid": error || props["aria-invalid"] ? "true" : "false",
1407
+ "aria-describedby": props["aria-describedby"],
1408
+ "aria-required": required || props["aria-required"],
1409
+ readOnly: true
1410
+ }
1411
+ ), clearable && value && !disabled && /* @__PURE__ */ React7__namespace.createElement(
1412
+ "button",
1413
+ {
1414
+ type: "button",
1415
+ className: "datepicker-clear",
1416
+ onClick: handleClear,
1417
+ "aria-label": "Clear date",
1418
+ tabIndex: -1
1419
+ },
1420
+ "\u2715"
1421
+ )), isOpen && !disabled && /* @__PURE__ */ React7__namespace.createElement("div", { className: "datepicker-dropdown" }, renderCalendar()));
1422
+ }
1423
+ DatePicker.displayName = "DatePicker";
1424
+ function parseTimeString(timeStr, use24Hour) {
1425
+ if (!timeStr) return null;
1426
+ try {
1427
+ if (use24Hour) {
1428
+ const [hourStr, minuteStr] = timeStr.split(":");
1429
+ const hour24 = parseInt(hourStr, 10);
1430
+ const minute = parseInt(minuteStr, 10);
1431
+ if (isNaN(hour24) || isNaN(minute)) return null;
1432
+ if (hour24 < 0 || hour24 > 23) return null;
1433
+ if (minute < 0 || minute > 59) return null;
1434
+ const period = hour24 >= 12 ? "PM" : "AM";
1435
+ const hour = hour24 === 0 ? 12 : hour24 > 12 ? hour24 - 12 : hour24;
1436
+ return { hour, minute, period };
1437
+ } else {
1438
+ const match = timeStr.match(/^(\d{1,2}):(\d{2})\s*(AM|PM)$/i);
1439
+ if (!match) return null;
1440
+ const hour = parseInt(match[1], 10);
1441
+ const minute = parseInt(match[2], 10);
1442
+ const period = match[3].toUpperCase();
1443
+ if (hour < 1 || hour > 12) return null;
1444
+ if (minute < 0 || minute > 59) return null;
1445
+ return { hour, minute, period };
1446
+ }
1447
+ } catch {
1448
+ return null;
1449
+ }
1450
+ }
1451
+ function formatTimeValue(time, use24Hour) {
1452
+ if (!time) return "";
1453
+ if (use24Hour) {
1454
+ let hour24 = time.hour;
1455
+ if (time.period === "PM" && time.hour !== 12) {
1456
+ hour24 = time.hour + 12;
1457
+ } else if (time.period === "AM" && time.hour === 12) {
1458
+ hour24 = 0;
1459
+ }
1460
+ return `${String(hour24).padStart(2, "0")}:${String(time.minute).padStart(2, "0")}`;
1461
+ } else {
1462
+ return `${time.hour}:${String(time.minute).padStart(2, "0")} ${time.period}`;
1463
+ }
1464
+ }
1465
+ function TimePicker({
1466
+ name,
1467
+ value,
1468
+ onChange,
1469
+ onBlur,
1470
+ disabled = false,
1471
+ required = false,
1472
+ error = false,
1473
+ className = "",
1474
+ placeholder = "Select time...",
1475
+ use24Hour = false,
1476
+ minuteStep = 1,
1477
+ clearable = true,
1478
+ showIcon = true,
1479
+ ...props
1480
+ }) {
1481
+ const [isOpen, setIsOpen] = React7__namespace.useState(false);
1482
+ const [timeValue, setTimeValue] = React7__namespace.useState(null);
1483
+ const containerRef = React7__namespace.useRef(null);
1484
+ const inputRef = React7__namespace.useRef(null);
1485
+ React7__namespace.useEffect(() => {
1486
+ const parsed = parseTimeString(value, use24Hour);
1487
+ setTimeValue(parsed);
1488
+ }, [value, use24Hour]);
1489
+ const handleHourChange = (hour) => {
1490
+ const newTime = {
1491
+ hour,
1492
+ minute: timeValue?.minute || 0,
1493
+ period: timeValue?.period || "AM"
1494
+ };
1495
+ setTimeValue(newTime);
1496
+ onChange(formatTimeValue(newTime, use24Hour));
1497
+ };
1498
+ const handleMinuteChange = (minute) => {
1499
+ const newTime = {
1500
+ hour: timeValue?.hour || 12,
1501
+ minute,
1502
+ period: timeValue?.period || "AM"
1503
+ };
1504
+ setTimeValue(newTime);
1505
+ onChange(formatTimeValue(newTime, use24Hour));
1506
+ };
1507
+ const handlePeriodChange = (period) => {
1508
+ const newTime = {
1509
+ hour: timeValue?.hour || 12,
1510
+ minute: timeValue?.minute || 0,
1511
+ period
1512
+ };
1513
+ setTimeValue(newTime);
1514
+ onChange(formatTimeValue(newTime, use24Hour));
1515
+ };
1516
+ const handleClear = (e) => {
1517
+ e.stopPropagation();
1518
+ onChange("");
1519
+ setTimeValue(null);
1520
+ inputRef.current?.focus();
1521
+ };
1522
+ const handleToggle = () => {
1523
+ if (disabled) return;
1524
+ setIsOpen(!isOpen);
1525
+ };
1526
+ React7__namespace.useEffect(() => {
1527
+ const handleClickOutside = (event) => {
1528
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
1529
+ setIsOpen(false);
1530
+ onBlur?.();
1531
+ }
1532
+ };
1533
+ if (isOpen) {
1534
+ document.addEventListener("mousedown", handleClickOutside);
1535
+ return () => {
1536
+ document.removeEventListener("mousedown", handleClickOutside);
1537
+ };
1538
+ }
1539
+ }, [isOpen, onBlur]);
1540
+ const hours = React7__namespace.useMemo(() => {
1541
+ if (use24Hour) {
1542
+ return Array.from({ length: 24 }, (_, i) => i);
1543
+ } else {
1544
+ return Array.from({ length: 12 }, (_, i) => i + 1);
1545
+ }
1546
+ }, [use24Hour]);
1547
+ const minutes = React7__namespace.useMemo(() => {
1548
+ const mins = [];
1549
+ for (let i = 0; i < 60; i += minuteStep) {
1550
+ mins.push(i);
1551
+ }
1552
+ return mins;
1553
+ }, [minuteStep]);
1554
+ const baseClassName = "timepicker";
1555
+ const errorClassName = error ? "timepicker--error" : "";
1556
+ const disabledClassName = disabled ? "timepicker--disabled" : "";
1557
+ const openClassName = isOpen ? "timepicker--open" : "";
1558
+ const combinedClassName = `${baseClassName} ${errorClassName} ${disabledClassName} ${openClassName} ${className}`.trim();
1559
+ const displayValue = formatTimeValue(timeValue, use24Hour);
1560
+ return /* @__PURE__ */ React7__namespace.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7__namespace.createElement(
1561
+ "input",
1562
+ {
1563
+ type: "hidden",
1564
+ name,
1565
+ value
1566
+ }
1567
+ ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "timepicker-input-wrapper" }, showIcon && /* @__PURE__ */ React7__namespace.createElement("span", { className: "timepicker-icon", "aria-hidden": "true" }, /* @__PURE__ */ React7__namespace.createElement(
1568
+ "svg",
1569
+ {
1570
+ xmlns: "http://www.w3.org/2000/svg",
1571
+ width: "18",
1572
+ height: "18",
1573
+ viewBox: "0 0 24 24",
1574
+ fill: "none",
1575
+ stroke: "currentColor",
1576
+ strokeLinecap: "round",
1577
+ strokeLinejoin: "round",
1578
+ strokeWidth: "2"
1579
+ },
1580
+ /* @__PURE__ */ React7__namespace.createElement("circle", { cx: "12", cy: "12", r: "10" }),
1581
+ /* @__PURE__ */ React7__namespace.createElement("path", { d: "M12 6v6l4 2" })
1582
+ )), /* @__PURE__ */ React7__namespace.createElement(
1583
+ "input",
1584
+ {
1585
+ ref: inputRef,
1586
+ type: "text",
1587
+ className: "timepicker-input",
1588
+ value: displayValue,
1589
+ onClick: handleToggle,
1590
+ onBlur,
1591
+ disabled,
1592
+ required,
1593
+ placeholder,
1594
+ "aria-invalid": error || props["aria-invalid"] ? "true" : "false",
1595
+ "aria-describedby": props["aria-describedby"],
1596
+ "aria-required": required || props["aria-required"],
1597
+ readOnly: true
1598
+ }
1599
+ ), clearable && value && !disabled && /* @__PURE__ */ React7__namespace.createElement(
1600
+ "button",
1601
+ {
1602
+ type: "button",
1603
+ className: "timepicker-clear",
1604
+ onClick: handleClear,
1605
+ "aria-label": "Clear time",
1606
+ tabIndex: -1
1607
+ },
1608
+ "\u2715"
1609
+ )), isOpen && !disabled && /* @__PURE__ */ React7__namespace.createElement("div", { className: "timepicker-dropdown" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "timepicker-selectors" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "timepicker-column" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "timepicker-column-label" }, use24Hour ? "Hour" : "Hour"), /* @__PURE__ */ React7__namespace.createElement("div", { className: "timepicker-column-options" }, hours.map((hour) => {
1610
+ const displayHour = use24Hour ? hour : hour;
1611
+ const isSelected = use24Hour ? timeValue?.hour === (hour === 0 ? 12 : hour > 12 ? hour - 12 : hour) && timeValue?.period === (hour >= 12 ? "PM" : "AM") : timeValue?.hour === hour;
1612
+ return /* @__PURE__ */ React7__namespace.createElement(
1613
+ "button",
1614
+ {
1615
+ key: hour,
1616
+ type: "button",
1617
+ className: `timepicker-option ${isSelected ? "timepicker-option--selected" : ""}`,
1618
+ onClick: () => {
1619
+ if (use24Hour) {
1620
+ const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
1621
+ const period = hour >= 12 ? "PM" : "AM";
1622
+ const newTime = {
1623
+ hour: hour12,
1624
+ minute: timeValue?.minute || 0,
1625
+ period
1626
+ };
1627
+ setTimeValue(newTime);
1628
+ onChange(formatTimeValue(newTime, use24Hour));
1629
+ } else {
1630
+ handleHourChange(hour);
1631
+ }
1632
+ },
1633
+ "aria-label": `${String(displayHour).padStart(2, "0")} hours`
1634
+ },
1635
+ String(displayHour).padStart(2, "0")
1636
+ );
1637
+ }))), /* @__PURE__ */ React7__namespace.createElement("div", { className: "timepicker-column" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "timepicker-column-label" }, "Minute"), /* @__PURE__ */ React7__namespace.createElement("div", { className: "timepicker-column-options" }, minutes.map((minute) => {
1638
+ const isSelected = timeValue?.minute === minute;
1639
+ return /* @__PURE__ */ React7__namespace.createElement(
1640
+ "button",
1641
+ {
1642
+ key: minute,
1643
+ type: "button",
1644
+ className: `timepicker-option ${isSelected ? "timepicker-option--selected" : ""}`,
1645
+ onClick: () => handleMinuteChange(minute),
1646
+ "aria-label": `${String(minute).padStart(2, "0")} minutes`
1647
+ },
1648
+ String(minute).padStart(2, "0")
1649
+ );
1650
+ }))), !use24Hour && /* @__PURE__ */ React7__namespace.createElement("div", { className: "timepicker-column timepicker-column--period" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "timepicker-column-label" }, "Period"), /* @__PURE__ */ React7__namespace.createElement("div", { className: "timepicker-column-options" }, /* @__PURE__ */ React7__namespace.createElement(
1651
+ "button",
1652
+ {
1653
+ type: "button",
1654
+ className: `timepicker-option ${timeValue?.period === "AM" ? "timepicker-option--selected" : ""}`,
1655
+ onClick: () => handlePeriodChange("AM")
1656
+ },
1657
+ "AM"
1658
+ ), /* @__PURE__ */ React7__namespace.createElement(
1659
+ "button",
1660
+ {
1661
+ type: "button",
1662
+ className: `timepicker-option ${timeValue?.period === "PM" ? "timepicker-option--selected" : ""}`,
1663
+ onClick: () => handlePeriodChange("PM")
1664
+ },
1665
+ "PM"
1666
+ ))))));
1667
+ }
1668
+ TimePicker.displayName = "TimePicker";
1669
+ function formatDate2(date, format) {
1670
+ if (!date) return "";
1671
+ const d = new Date(date);
1672
+ const month = String(d.getMonth() + 1).padStart(2, "0");
1673
+ const day = String(d.getDate()).padStart(2, "0");
1674
+ const year = d.getFullYear();
1675
+ return format.replace("MM", month).replace("dd", day).replace("yyyy", String(year)).replace("yy", String(year).slice(2));
1676
+ }
1677
+ function isDateInArray2(date, dates) {
1678
+ const dateStr = date.toDateString();
1679
+ return dates.some((d) => d.toDateString() === dateStr);
1680
+ }
1681
+ function isDateInRange(date, start, end) {
1682
+ if (!start || !end) return false;
1683
+ const time = date.getTime();
1684
+ return time >= start.getTime() && time <= end.getTime();
1685
+ }
1686
+ function DateRangePicker({
1687
+ name,
1688
+ value = { start: null, end: null },
1689
+ onChange,
1690
+ onBlur,
1691
+ disabled = false,
1692
+ required = false,
1693
+ error = false,
1694
+ className = "",
1695
+ placeholder = "Select date range...",
1696
+ format = "MM/dd/yyyy",
1697
+ minDate,
1698
+ maxDate,
1699
+ disabledDates = [],
1700
+ isDateDisabled,
1701
+ clearable = true,
1702
+ showIcon = true,
1703
+ separator = " - ",
1704
+ ...props
1705
+ }) {
1706
+ const [isOpen, setIsOpen] = React7__namespace.useState(false);
1707
+ const [selectedMonth, setSelectedMonth] = React7__namespace.useState(value.start || /* @__PURE__ */ new Date());
1708
+ const [rangeStart, setRangeStart] = React7__namespace.useState(value.start);
1709
+ const [rangeEnd, setRangeEnd] = React7__namespace.useState(value.end);
1710
+ const [hoverDate, setHoverDate] = React7__namespace.useState(null);
1711
+ const containerRef = React7__namespace.useRef(null);
1712
+ React7__namespace.useEffect(() => {
1713
+ setRangeStart(value.start);
1714
+ setRangeEnd(value.end);
1715
+ if (value.start) {
1716
+ setSelectedMonth(value.start);
1717
+ }
1718
+ }, [value]);
1719
+ const handleDateSelect = (date) => {
1720
+ if (!rangeStart || rangeStart && rangeEnd) {
1721
+ setRangeStart(date);
1722
+ setRangeEnd(null);
1723
+ onChange({ start: date, end: null });
1724
+ } else {
1725
+ if (date < rangeStart) {
1726
+ setRangeStart(date);
1727
+ setRangeEnd(rangeStart);
1728
+ onChange({ start: date, end: rangeStart });
1729
+ setIsOpen(false);
1730
+ } else {
1731
+ setRangeEnd(date);
1732
+ onChange({ start: rangeStart, end: date });
1733
+ setIsOpen(false);
1734
+ }
1735
+ }
1736
+ onBlur?.();
1737
+ };
1738
+ const handleClear = (e) => {
1739
+ e.stopPropagation();
1740
+ onChange({ start: null, end: null });
1741
+ setRangeStart(null);
1742
+ setRangeEnd(null);
1743
+ };
1744
+ const handleToggle = () => {
1745
+ if (disabled) return;
1746
+ setIsOpen(!isOpen);
1747
+ };
1748
+ const isDisabled = (date) => {
1749
+ if (minDate && date < minDate) return true;
1750
+ if (maxDate && date > maxDate) return true;
1751
+ if (isDateInArray2(date, disabledDates)) return true;
1752
+ if (isDateDisabled && isDateDisabled(date)) return true;
1753
+ return false;
1754
+ };
1755
+ React7__namespace.useEffect(() => {
1756
+ const handleClickOutside = (event) => {
1757
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
1758
+ setIsOpen(false);
1759
+ onBlur?.();
1760
+ }
1761
+ };
1762
+ if (isOpen) {
1763
+ document.addEventListener("mousedown", handleClickOutside);
1764
+ return () => {
1765
+ document.removeEventListener("mousedown", handleClickOutside);
1766
+ };
1767
+ }
1768
+ }, [isOpen, onBlur]);
1769
+ const renderCalendar = () => {
1770
+ const year = selectedMonth.getFullYear();
1771
+ const month = selectedMonth.getMonth();
1772
+ const daysInMonth = new Date(year, month + 1, 0).getDate();
1773
+ const firstDayOfMonth = new Date(year, month, 1).getDay();
1774
+ const days = [];
1775
+ for (let i = 0; i < firstDayOfMonth; i++) {
1776
+ days.push(null);
1777
+ }
1778
+ for (let day = 1; day <= daysInMonth; day++) {
1779
+ days.push(new Date(year, month, day));
1780
+ }
1781
+ const monthNames = [
1782
+ "January",
1783
+ "February",
1784
+ "March",
1785
+ "April",
1786
+ "May",
1787
+ "June",
1788
+ "July",
1789
+ "August",
1790
+ "September",
1791
+ "October",
1792
+ "November",
1793
+ "December"
1794
+ ];
1795
+ const handlePrevMonth = () => {
1796
+ setSelectedMonth(new Date(year, month - 1, 1));
1797
+ };
1798
+ const handleNextMonth = () => {
1799
+ setSelectedMonth(new Date(year, month + 1, 1));
1800
+ };
1801
+ return /* @__PURE__ */ React7__namespace.createElement("div", { className: "daterangepicker-calendar", role: "grid", "aria-label": "Calendar" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "daterangepicker-calendar-header" }, /* @__PURE__ */ React7__namespace.createElement(
1802
+ "button",
1803
+ {
1804
+ type: "button",
1805
+ className: "daterangepicker-calendar-nav",
1806
+ onClick: handlePrevMonth,
1807
+ "aria-label": "Previous month"
1808
+ },
1809
+ "\u2190"
1810
+ ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "daterangepicker-calendar-month" }, monthNames[month], " ", year), /* @__PURE__ */ React7__namespace.createElement(
1811
+ "button",
1812
+ {
1813
+ type: "button",
1814
+ className: "daterangepicker-calendar-nav",
1815
+ onClick: handleNextMonth,
1816
+ "aria-label": "Next month"
1817
+ },
1818
+ "\u2192"
1819
+ )), /* @__PURE__ */ React7__namespace.createElement("div", { className: "daterangepicker-calendar-weekdays" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7__namespace.createElement("div", { key: day, className: "daterangepicker-calendar-weekday" }, day))), /* @__PURE__ */ React7__namespace.createElement("div", { className: "daterangepicker-calendar-days" }, days.map((date, index) => {
1820
+ if (!date) {
1821
+ return /* @__PURE__ */ React7__namespace.createElement("div", { key: `empty-${index}`, className: "daterangepicker-calendar-day daterangepicker-calendar-day--empty" });
1822
+ }
1823
+ const isStart = rangeStart && date.toDateString() === rangeStart.toDateString();
1824
+ const isEnd = rangeEnd && date.toDateString() === rangeEnd.toDateString();
1825
+ const isInRange = rangeStart && rangeEnd && isDateInRange(date, rangeStart, rangeEnd);
1826
+ const isInHoverRange = rangeStart && !rangeEnd && hoverDate && (date >= rangeStart && date <= hoverDate || date <= rangeStart && date >= hoverDate);
1827
+ const isToday = date.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
1828
+ const disabled2 = isDisabled(date);
1829
+ return /* @__PURE__ */ React7__namespace.createElement(
1830
+ "button",
1831
+ {
1832
+ key: date.toISOString(),
1833
+ type: "button",
1834
+ className: `daterangepicker-calendar-day ${isStart || isEnd ? "daterangepicker-calendar-day--selected" : ""} ${isInRange || isInHoverRange ? "daterangepicker-calendar-day--in-range" : ""} ${isToday ? "daterangepicker-calendar-day--today" : ""} ${disabled2 ? "daterangepicker-calendar-day--disabled" : ""}`,
1835
+ onClick: () => !disabled2 && handleDateSelect(date),
1836
+ onMouseEnter: () => setHoverDate(date),
1837
+ onMouseLeave: () => setHoverDate(null),
1838
+ disabled: disabled2,
1839
+ "aria-label": formatDate2(date, format)
1840
+ },
1841
+ date.getDate()
1842
+ );
1843
+ })));
1844
+ };
1845
+ const baseClassName = "daterangepicker";
1846
+ const errorClassName = error ? "daterangepicker--error" : "";
1847
+ const disabledClassName = disabled ? "daterangepicker--disabled" : "";
1848
+ const openClassName = isOpen ? "daterangepicker--open" : "";
1849
+ const combinedClassName = `${baseClassName} ${errorClassName} ${disabledClassName} ${openClassName} ${className}`.trim();
1850
+ const displayValue = rangeStart && rangeEnd ? `${formatDate2(rangeStart, format)}${separator}${formatDate2(rangeEnd, format)}` : rangeStart ? formatDate2(rangeStart, format) : "";
1851
+ return /* @__PURE__ */ React7__namespace.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7__namespace.createElement(
1852
+ "input",
1853
+ {
1854
+ type: "hidden",
1855
+ name: `${name}[start]`,
1856
+ value: rangeStart ? rangeStart.toISOString() : ""
1857
+ }
1858
+ ), /* @__PURE__ */ React7__namespace.createElement(
1859
+ "input",
1860
+ {
1861
+ type: "hidden",
1862
+ name: `${name}[end]`,
1863
+ value: rangeEnd ? rangeEnd.toISOString() : ""
1864
+ }
1865
+ ), /* @__PURE__ */ React7__namespace.createElement("div", { className: "daterangepicker-input-wrapper" }, showIcon && /* @__PURE__ */ React7__namespace.createElement("span", { className: "daterangepicker-icon", "aria-hidden": "true" }, /* @__PURE__ */ React7__namespace.createElement(
1866
+ "svg",
1867
+ {
1868
+ xmlns: "http://www.w3.org/2000/svg",
1869
+ width: "18",
1870
+ height: "18",
1871
+ viewBox: "0 0 24 24",
1872
+ fill: "none",
1873
+ stroke: "currentColor",
1874
+ strokeLinecap: "round",
1875
+ strokeLinejoin: "round",
1876
+ strokeWidth: "2"
1877
+ },
1878
+ /* @__PURE__ */ React7__namespace.createElement("path", { d: "M8 2v4m8-4v4m5 8V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8M3 10h18m-5 10l2 2l4-4" })
1879
+ )), /* @__PURE__ */ React7__namespace.createElement(
1880
+ "input",
1881
+ {
1882
+ type: "text",
1883
+ className: "daterangepicker-input",
1884
+ value: displayValue,
1885
+ onClick: handleToggle,
1886
+ onBlur,
1887
+ disabled,
1888
+ required,
1889
+ placeholder,
1890
+ "aria-invalid": error || props["aria-invalid"] ? "true" : "false",
1891
+ "aria-describedby": props["aria-describedby"],
1892
+ "aria-required": required || props["aria-required"],
1893
+ readOnly: true
1894
+ }
1895
+ ), clearable && (rangeStart || rangeEnd) && !disabled && /* @__PURE__ */ React7__namespace.createElement(
1896
+ "button",
1897
+ {
1898
+ type: "button",
1899
+ className: "daterangepicker-clear",
1900
+ onClick: handleClear,
1901
+ "aria-label": "Clear date range",
1902
+ tabIndex: -1
1903
+ },
1904
+ "\u2715"
1905
+ )), isOpen && !disabled && /* @__PURE__ */ React7__namespace.createElement("div", { className: "daterangepicker-dropdown" }, renderCalendar(), rangeStart && !rangeEnd && /* @__PURE__ */ React7__namespace.createElement("div", { className: "daterangepicker-hint" }, "Select end date")));
1906
+ }
1907
+ DateRangePicker.displayName = "DateRangePicker";
1908
+ function htmlToMarkdown(html) {
1909
+ let markdown = html;
1910
+ markdown = markdown.replace(/<strong>(.*?)<\/strong>/g, "**$1**");
1911
+ markdown = markdown.replace(/<b>(.*?)<\/b>/g, "**$1**");
1912
+ markdown = markdown.replace(/<em>(.*?)<\/em>/g, "*$1*");
1913
+ markdown = markdown.replace(/<i>(.*?)<\/i>/g, "*$1*");
1914
+ markdown = markdown.replace(/<u>(.*?)<\/u>/g, "<u>$1</u>");
1915
+ markdown = markdown.replace(/<h1>(.*?)<\/h1>/g, "# $1\n");
1916
+ markdown = markdown.replace(/<h2>(.*?)<\/h2>/g, "## $1\n");
1917
+ markdown = markdown.replace(/<h3>(.*?)<\/h3>/g, "### $1\n");
1918
+ markdown = markdown.replace(/<a href="(.*?)">(.*?)<\/a>/g, "[$2]($1)");
1919
+ markdown = markdown.replace(/<ul>(.*?)<\/ul>/gs, (_match, content) => {
1920
+ return content.replace(/<li>(.*?)<\/li>/g, "- $1\n");
1921
+ });
1922
+ markdown = markdown.replace(/<ol>(.*?)<\/ol>/gs, (_match, content) => {
1923
+ let counter = 1;
1924
+ return content.replace(/<li>(.*?)<\/li>/g, () => {
1925
+ return `${counter++}. $1
1926
+ `;
1927
+ });
1928
+ });
1929
+ markdown = markdown.replace(/<p>(.*?)<\/p>/g, "$1\n\n");
1930
+ markdown = markdown.replace(/<br\s*\/?>/g, "\n");
1931
+ markdown = markdown.replace(/\n{3,}/g, "\n\n").trim();
1932
+ return markdown;
1933
+ }
1934
+ function markdownToHtml(markdown) {
1935
+ let html = markdown;
1936
+ html = html.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
1937
+ html = html.replace(/^### (.*?)$/gm, "<h3>$1</h3>");
1938
+ html = html.replace(/^## (.*?)$/gm, "<h2>$1</h2>");
1939
+ html = html.replace(/^# (.*?)$/gm, "<h1>$1</h1>");
1940
+ html = html.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>");
1941
+ html = html.replace(/\*(.*?)\*/g, "<em>$1</em>");
1942
+ html = html.replace(/\[(.*?)\]\((.*?)\)/g, '<a href="$2">$1</a>');
1943
+ html = html.replace(/^- (.*?)$/gm, "<li>$1</li>");
1944
+ html = html.replace(/(<li>.*?<\/li>\n?)+/gs, "<ul>$&</ul>");
1945
+ html = html.replace(/^\d+\. (.*?)$/gm, "<li>$1</li>");
1946
+ html = html.replace(/^(?!<[h|ul|ol|li])(.+)$/gm, "<p>$1</p>");
1947
+ html = html.replace(/\n/g, "<br>");
1948
+ return html;
1949
+ }
1950
+ function RichTextEditor({
1951
+ name,
1952
+ value = "",
1953
+ onChange,
1954
+ onBlur,
1955
+ disabled = false,
1956
+ required = false,
1957
+ error = false,
1958
+ className = "",
1959
+ mode = "wysiwyg",
1960
+ allowModeSwitch = false,
1961
+ placeholder = "Start typing...",
1962
+ minHeight = "200px",
1963
+ maxHeight,
1964
+ showToolbar = true,
1965
+ toolbarButtons = ["bold", "italic", "underline", "heading", "bulletList", "orderedList", "link"],
1966
+ ...props
1967
+ }) {
1968
+ const [currentMode, setCurrentMode] = React7__namespace.useState(mode);
1969
+ const [content, setContent] = React7__namespace.useState(value);
1970
+ const editorRef = React7__namespace.useRef(null);
1971
+ const textareaRef = React7__namespace.useRef(null);
1972
+ React7__namespace.useEffect(() => {
1973
+ setContent(value);
1974
+ if (currentMode === "wysiwyg" && editorRef.current) {
1975
+ editorRef.current.innerHTML = value;
1976
+ }
1977
+ }, [value, currentMode]);
1978
+ const handleWysiwygChange = () => {
1979
+ if (editorRef.current) {
1980
+ const newContent = editorRef.current.innerHTML;
1981
+ setContent(newContent);
1982
+ onChange(newContent);
1983
+ }
1984
+ };
1985
+ const handleMarkdownChange = (e) => {
1986
+ const newContent = e.target.value;
1987
+ setContent(newContent);
1988
+ onChange(newContent);
1989
+ };
1990
+ const execCommand = (command, value2) => {
1991
+ document.execCommand(command, false, value2);
1992
+ editorRef.current?.focus();
1993
+ handleWysiwygChange();
1994
+ };
1995
+ const handleModeToggle = () => {
1996
+ const newMode = currentMode === "wysiwyg" ? "markdown" : "wysiwyg";
1997
+ if (newMode === "markdown") {
1998
+ const markdown = htmlToMarkdown(content);
1999
+ setContent(markdown);
2000
+ onChange(markdown);
2001
+ } else {
2002
+ const html = markdownToHtml(content);
2003
+ setContent(html);
2004
+ onChange(html);
2005
+ if (editorRef.current) {
2006
+ editorRef.current.innerHTML = html;
2007
+ }
2008
+ }
2009
+ setCurrentMode(newMode);
2010
+ };
2011
+ const toolbarConfig = {
2012
+ bold: {
2013
+ command: "bold",
2014
+ icon: "B",
2015
+ title: "Bold",
2016
+ action: () => execCommand("bold")
2017
+ },
2018
+ italic: {
2019
+ command: "italic",
2020
+ icon: "I",
2021
+ title: "Italic",
2022
+ action: () => execCommand("italic")
2023
+ },
2024
+ underline: {
2025
+ command: "underline",
2026
+ icon: "U",
2027
+ title: "Underline",
2028
+ action: () => execCommand("underline")
2029
+ },
2030
+ heading: {
2031
+ command: "heading",
2032
+ icon: "H",
2033
+ title: "Heading",
2034
+ action: () => execCommand("formatBlock", "<h2>")
2035
+ },
2036
+ bulletList: {
2037
+ command: "bulletList",
2038
+ icon: "\u2022",
2039
+ title: "Bullet List",
2040
+ action: () => execCommand("insertUnorderedList")
2041
+ },
2042
+ orderedList: {
2043
+ command: "orderedList",
2044
+ icon: "1.",
2045
+ title: "Numbered List",
2046
+ action: () => execCommand("insertOrderedList")
2047
+ },
2048
+ link: {
2049
+ command: "link",
2050
+ icon: "\u{1F517}",
2051
+ title: "Insert Link",
2052
+ action: () => {
2053
+ const url = window.prompt("Enter URL:");
2054
+ if (url) {
2055
+ execCommand("createLink", url);
2056
+ }
2057
+ }
2058
+ }
2059
+ };
2060
+ const baseClassName = "richtexteditor";
2061
+ const errorClassName = error ? "richtexteditor--error" : "";
2062
+ const disabledClassName = disabled ? "richtexteditor--disabled" : "";
2063
+ const modeClassName = `richtexteditor--${currentMode}`;
2064
+ const combinedClassName = `${baseClassName} ${errorClassName} ${disabledClassName} ${modeClassName} ${className}`.trim();
2065
+ const editorStyle = {
2066
+ minHeight,
2067
+ maxHeight,
2068
+ overflowY: maxHeight ? "auto" : void 0
2069
+ };
2070
+ return /* @__PURE__ */ React7__namespace.createElement("div", { className: combinedClassName }, /* @__PURE__ */ React7__namespace.createElement("input", { type: "hidden", name, value: content }), showToolbar && /* @__PURE__ */ React7__namespace.createElement("div", { className: "richtexteditor-toolbar" }, /* @__PURE__ */ React7__namespace.createElement("div", { className: "richtexteditor-toolbar-buttons" }, toolbarButtons.map((buttonName) => {
2071
+ const button = toolbarConfig[buttonName];
2072
+ if (!button) return null;
2073
+ return /* @__PURE__ */ React7__namespace.createElement(
2074
+ "button",
2075
+ {
2076
+ key: buttonName,
2077
+ type: "button",
2078
+ className: "richtexteditor-toolbar-button",
2079
+ onClick: () => editorRef.current && button.action(editorRef.current),
2080
+ title: button.title,
2081
+ disabled: disabled || currentMode === "markdown",
2082
+ "aria-label": button.title
2083
+ },
2084
+ button.icon
2085
+ );
2086
+ })), allowModeSwitch && /* @__PURE__ */ React7__namespace.createElement(
2087
+ "button",
2088
+ {
2089
+ type: "button",
2090
+ className: "richtexteditor-mode-toggle",
2091
+ onClick: handleModeToggle,
2092
+ disabled,
2093
+ title: `Switch to ${currentMode === "wysiwyg" ? "Markdown" : "WYSIWYG"}`,
2094
+ "aria-label": `Switch to ${currentMode === "wysiwyg" ? "Markdown" : "WYSIWYG"}`
2095
+ },
2096
+ currentMode === "wysiwyg" ? "MD" : "WYSIWYG"
2097
+ )), /* @__PURE__ */ React7__namespace.createElement("div", { className: "richtexteditor-editor", style: editorStyle }, currentMode === "wysiwyg" ? /* @__PURE__ */ React7__namespace.createElement(
2098
+ "div",
2099
+ {
2100
+ ref: editorRef,
2101
+ className: "richtexteditor-content",
2102
+ role: "textbox",
2103
+ contentEditable: !disabled,
2104
+ onInput: handleWysiwygChange,
2105
+ onBlur,
2106
+ "data-placeholder": placeholder,
2107
+ "aria-invalid": error || props["aria-invalid"] ? "true" : "false",
2108
+ "aria-describedby": props["aria-describedby"],
2109
+ "aria-required": required || props["aria-required"],
2110
+ suppressContentEditableWarning: true
2111
+ }
2112
+ ) : /* @__PURE__ */ React7__namespace.createElement(
2113
+ "textarea",
2114
+ {
2115
+ ref: textareaRef,
2116
+ className: "richtexteditor-markdown",
2117
+ value: content,
2118
+ onChange: handleMarkdownChange,
2119
+ onBlur,
2120
+ disabled,
2121
+ required,
2122
+ placeholder,
2123
+ "aria-invalid": error || props["aria-invalid"] ? "true" : "false",
2124
+ "aria-describedby": props["aria-describedby"],
2125
+ "aria-required": required || props["aria-required"]
2126
+ }
2127
+ )));
2128
+ }
2129
+ RichTextEditor.displayName = "RichTextEditor";
923
2130
 
924
2131
  exports.Checkbox = Checkbox;
925
2132
  exports.CheckboxGroup = CheckboxGroup;
2133
+ exports.DatePicker = DatePicker;
2134
+ exports.DateRangePicker = DateRangePicker;
926
2135
  exports.FileInput = FileInput;
927
2136
  exports.Radio = Radio;
2137
+ exports.RichTextEditor = RichTextEditor;
928
2138
  exports.Select = Select;
929
2139
  exports.TextArea = TextArea;
930
2140
  exports.TextInput = TextInput;
2141
+ exports.TimePicker = TimePicker;
931
2142
  //# sourceMappingURL=inputs.cjs.map
932
2143
  //# sourceMappingURL=inputs.cjs.map