easy-forms-core 1.0.5 → 1.0.6

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/easy-form.js CHANGED
@@ -62,7 +62,11 @@ var SchemaParser = class {
62
62
  "array",
63
63
  "group",
64
64
  "row",
65
- "custom"
65
+ "custom",
66
+ "quantity",
67
+ "accordion-select",
68
+ "image-grid-select",
69
+ "otp"
66
70
  ];
67
71
  if (!validTypes.includes(field.type)) {
68
72
  throw new Error(
@@ -72,6 +76,8 @@ var SchemaParser = class {
72
76
  switch (field.type) {
73
77
  case "select":
74
78
  case "radio":
79
+ case "accordion-select":
80
+ case "image-grid-select":
75
81
  if (!("options" in field) || !field.options || field.options.length === 0) {
76
82
  throw new Error(
77
83
  `Field "${field.name}" de tipo ${field.type} debe tener options`
@@ -117,15 +123,41 @@ var SchemaParser = class {
117
123
  }
118
124
  break;
119
125
  case "select":
126
+ case "accordion-select":
127
+ case "image-grid-select":
120
128
  if (!("multiple" in field)) {
121
129
  defaults.multiple = false;
122
130
  }
131
+ if (field.type === "image-grid-select") {
132
+ if (!("columns" in field)) {
133
+ defaults.columns = 3;
134
+ }
135
+ if (!("imageSize" in field)) {
136
+ defaults.imageSize = "medium";
137
+ }
138
+ }
123
139
  break;
124
140
  case "file":
125
141
  if (!("multiple" in field)) {
126
142
  defaults.multiple = false;
127
143
  }
128
144
  break;
145
+ case "quantity":
146
+ if (!("min" in field)) {
147
+ defaults.min = 0;
148
+ }
149
+ if (!("step" in field)) {
150
+ defaults.step = 1;
151
+ }
152
+ break;
153
+ case "otp":
154
+ if (!("length" in field)) {
155
+ defaults.length = 6;
156
+ }
157
+ if (!("numeric" in field)) {
158
+ defaults.numeric = true;
159
+ }
160
+ break;
129
161
  }
130
162
  return { ...defaults, ...field };
131
163
  }
@@ -372,6 +404,249 @@ function getBaseStyles(colors) {
372
404
  .easy-form-array-remove:hover {
373
405
  opacity: 0.9;
374
406
  }
407
+ /* Quantity Input */
408
+ .easy-form-quantity-container {
409
+ display: flex;
410
+ flex-direction: column;
411
+ }
412
+ .easy-form-quantity-wrapper {
413
+ display: flex;
414
+ align-items: center;
415
+ gap: 0.5rem;
416
+ }
417
+ .easy-form-quantity-btn {
418
+ width: 2.5rem;
419
+ height: 2.5rem;
420
+ display: flex;
421
+ align-items: center;
422
+ justify-content: center;
423
+ background: var(--easy-form-primary);
424
+ color: white;
425
+ border: none;
426
+ border-radius: 4px;
427
+ font-size: 1.25rem;
428
+ font-weight: bold;
429
+ cursor: pointer;
430
+ transition: all 0.2s ease;
431
+ user-select: none;
432
+ }
433
+ .easy-form-quantity-btn:hover:not(.disabled) {
434
+ opacity: 0.9;
435
+ transform: scale(1.05);
436
+ }
437
+ .easy-form-quantity-btn.disabled {
438
+ opacity: 0.5;
439
+ cursor: not-allowed;
440
+ }
441
+ .easy-form-quantity-input {
442
+ flex: 1;
443
+ text-align: center;
444
+ max-width: 100px;
445
+ }
446
+ /* Accordion Select */
447
+ .easy-form-accordion-select-container {
448
+ display: flex;
449
+ flex-direction: column;
450
+ gap: 0.5rem;
451
+ }
452
+ .easy-form-accordion-item {
453
+ border: 1px solid var(--easy-form-border);
454
+ border-radius: 4px;
455
+ overflow: hidden;
456
+ transition: all 0.2s ease;
457
+ }
458
+ .easy-form-accordion-item.selected {
459
+ border-color: var(--easy-form-primary);
460
+ box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.1);
461
+ }
462
+ .easy-form-accordion-header {
463
+ display: flex;
464
+ align-items: center;
465
+ justify-content: space-between;
466
+ padding: 0.75rem 1rem;
467
+ cursor: pointer;
468
+ background: var(--easy-form-background);
469
+ transition: background 0.2s ease;
470
+ }
471
+ .easy-form-accordion-header:hover {
472
+ background: rgba(0, 0, 0, 0.02);
473
+ }
474
+ .easy-form-accordion-header-content {
475
+ display: flex;
476
+ align-items: center;
477
+ gap: 0.75rem;
478
+ flex: 1;
479
+ }
480
+ .easy-form-accordion-indicator {
481
+ width: 20px;
482
+ height: 20px;
483
+ border: 2px solid var(--easy-form-border);
484
+ display: flex;
485
+ align-items: center;
486
+ justify-content: center;
487
+ flex-shrink: 0;
488
+ transition: all 0.2s ease;
489
+ }
490
+ .easy-form-accordion-indicator.radio {
491
+ border-radius: 50%;
492
+ }
493
+ .easy-form-accordion-indicator.checkbox {
494
+ border-radius: 4px;
495
+ }
496
+ .easy-form-accordion-indicator.checked {
497
+ background: var(--easy-form-primary);
498
+ border-color: var(--easy-form-primary);
499
+ color: white;
500
+ }
501
+ .easy-form-accordion-indicator.checked.radio::after {
502
+ content: '';
503
+ width: 8px;
504
+ height: 8px;
505
+ background: white;
506
+ border-radius: 50%;
507
+ }
508
+ .easy-form-accordion-indicator.checked.checkbox::after {
509
+ content: '\u2713';
510
+ font-size: 12px;
511
+ color: white;
512
+ }
513
+ .easy-form-accordion-label {
514
+ font-weight: 500;
515
+ color: var(--easy-form-text);
516
+ }
517
+ .easy-form-accordion-arrow {
518
+ transition: transform 0.2s ease;
519
+ color: var(--easy-form-secondary);
520
+ }
521
+ .easy-form-accordion-content {
522
+ max-height: 0;
523
+ overflow: hidden;
524
+ transition: max-height 0.3s ease;
525
+ padding: 0 1rem;
526
+ }
527
+ .easy-form-accordion-item.open .easy-form-accordion-content {
528
+ padding: 1rem;
529
+ }
530
+ .easy-form-accordion-description {
531
+ color: var(--easy-form-secondary);
532
+ font-size: 0.875rem;
533
+ margin: 0;
534
+ }
535
+ /* Image Grid Select */
536
+ .easy-form-image-grid-container {
537
+ display: grid;
538
+ gap: 1rem;
539
+ }
540
+ .easy-form-image-grid-item {
541
+ position: relative;
542
+ border: 2px solid var(--easy-form-border);
543
+ border-radius: 8px;
544
+ overflow: hidden;
545
+ cursor: pointer;
546
+ transition: all 0.2s ease;
547
+ background: var(--easy-form-background);
548
+ }
549
+ .easy-form-image-grid-item:hover {
550
+ border-color: var(--easy-form-primary);
551
+ transform: translateY(-2px);
552
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
553
+ }
554
+ .easy-form-image-grid-item.selected {
555
+ border-color: var(--easy-form-primary);
556
+ box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.2);
557
+ }
558
+ .easy-form-image-grid-image-container {
559
+ position: relative;
560
+ width: 100%;
561
+ aspect-ratio: 1;
562
+ overflow: hidden;
563
+ background: #f5f5f5;
564
+ }
565
+ .easy-form-image-grid-image {
566
+ width: 100%;
567
+ height: 100%;
568
+ object-fit: cover;
569
+ }
570
+ .easy-form-image-grid-placeholder {
571
+ width: 100%;
572
+ height: 100%;
573
+ display: flex;
574
+ align-items: center;
575
+ justify-content: center;
576
+ background: var(--easy-form-secondary);
577
+ color: white;
578
+ font-size: 2rem;
579
+ font-weight: bold;
580
+ }
581
+ .easy-form-image-grid-indicator {
582
+ position: absolute;
583
+ top: 0.5rem;
584
+ right: 0.5rem;
585
+ width: 24px;
586
+ height: 24px;
587
+ border: 2px solid white;
588
+ background: var(--easy-form-primary);
589
+ border-radius: 50%;
590
+ display: flex;
591
+ align-items: center;
592
+ justify-content: center;
593
+ color: white;
594
+ font-size: 12px;
595
+ opacity: 0;
596
+ transition: opacity 0.2s ease;
597
+ }
598
+ .easy-form-image-grid-item.selected .easy-form-image-grid-indicator {
599
+ opacity: 1;
600
+ }
601
+ .easy-form-image-grid-indicator.checkbox {
602
+ border-radius: 4px;
603
+ }
604
+ .easy-form-image-grid-label {
605
+ padding: 0.75rem;
606
+ text-align: center;
607
+ font-weight: 500;
608
+ color: var(--easy-form-text);
609
+ }
610
+ .easy-form-image-grid-description {
611
+ padding: 0 0.75rem 0.75rem;
612
+ font-size: 0.875rem;
613
+ color: var(--easy-form-secondary);
614
+ text-align: center;
615
+ }
616
+ .easy-form-image-grid-small {
617
+ grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
618
+ }
619
+ .easy-form-image-grid-medium {
620
+ grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
621
+ }
622
+ .easy-form-image-grid-large {
623
+ grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
624
+ }
625
+ /* OTP Input */
626
+ .easy-form-otp-container {
627
+ display: flex;
628
+ gap: 0.5rem;
629
+ justify-content: center;
630
+ align-items: center;
631
+ }
632
+ .easy-form-otp-input {
633
+ width: 3rem;
634
+ height: 3rem;
635
+ text-align: center;
636
+ font-size: 1.5rem;
637
+ font-weight: bold;
638
+ border: 2px solid var(--easy-form-border);
639
+ border-radius: 4px;
640
+ transition: all 0.2s ease;
641
+ }
642
+ .easy-form-otp-input:focus {
643
+ border-color: var(--easy-form-primary);
644
+ outline: none;
645
+ box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
646
+ }
647
+ .easy-form-otp-input:invalid {
648
+ border-color: var(--easy-form-error);
649
+ }
375
650
  `;
376
651
  }
377
652
  function getThemeSpecificStyles(theme, colors) {
@@ -2470,6 +2745,452 @@ var FileInput = class extends BaseInput {
2470
2745
  }
2471
2746
  };
2472
2747
 
2748
+ // src/components/inputs/quantity-input.ts
2749
+ var QuantityInput = class extends BaseInput {
2750
+ render() {
2751
+ const container = document.createElement("div");
2752
+ container.className = "easy-form-quantity-container";
2753
+ const quantityField = this.field;
2754
+ const min = quantityField.min ?? 0;
2755
+ const max = quantityField.max ?? void 0;
2756
+ const step = quantityField.step ?? 1;
2757
+ const currentValue = this.value ?? min;
2758
+ const inputWrapper = document.createElement("div");
2759
+ inputWrapper.className = "easy-form-quantity-wrapper";
2760
+ const decrementBtn = document.createElement("button");
2761
+ decrementBtn.type = "button";
2762
+ decrementBtn.className = "easy-form-quantity-btn easy-form-quantity-decrement";
2763
+ decrementBtn.textContent = "\u2212";
2764
+ decrementBtn.setAttribute("aria-label", "Decrementar");
2765
+ if (currentValue <= min) {
2766
+ decrementBtn.disabled = true;
2767
+ decrementBtn.classList.add("disabled");
2768
+ }
2769
+ const input = document.createElement("input");
2770
+ input.type = "number";
2771
+ input.value = String(currentValue);
2772
+ input.min = String(min);
2773
+ if (max !== void 0) {
2774
+ input.max = String(max);
2775
+ }
2776
+ input.step = String(step);
2777
+ input.className = "easy-form-quantity-input";
2778
+ this.applyCommonProps(input);
2779
+ const incrementBtn = document.createElement("button");
2780
+ incrementBtn.type = "button";
2781
+ incrementBtn.className = "easy-form-quantity-btn easy-form-quantity-increment";
2782
+ incrementBtn.textContent = "+";
2783
+ incrementBtn.setAttribute("aria-label", "Incrementar");
2784
+ if (max !== void 0 && currentValue >= max) {
2785
+ incrementBtn.disabled = true;
2786
+ incrementBtn.classList.add("disabled");
2787
+ }
2788
+ decrementBtn.addEventListener("click", () => {
2789
+ const newValue = Math.max(min, Number(input.value) - step);
2790
+ input.value = String(newValue);
2791
+ this.onChange(newValue);
2792
+ updateButtons();
2793
+ });
2794
+ incrementBtn.addEventListener("click", () => {
2795
+ const newValue = max !== void 0 ? Math.min(max, Number(input.value) + step) : Number(input.value) + step;
2796
+ input.value = String(newValue);
2797
+ this.onChange(newValue);
2798
+ updateButtons();
2799
+ });
2800
+ input.addEventListener("input", (e) => {
2801
+ const target = e.target;
2802
+ let numValue = Number(target.value);
2803
+ if (isNaN(numValue)) {
2804
+ numValue = min;
2805
+ }
2806
+ if (numValue < min) {
2807
+ numValue = min;
2808
+ }
2809
+ if (max !== void 0 && numValue > max) {
2810
+ numValue = max;
2811
+ }
2812
+ target.value = String(numValue);
2813
+ this.onChange(numValue);
2814
+ updateButtons();
2815
+ });
2816
+ input.addEventListener("blur", () => {
2817
+ this.onBlur();
2818
+ });
2819
+ const updateButtons = () => {
2820
+ const value = Number(input.value);
2821
+ decrementBtn.disabled = value <= min;
2822
+ decrementBtn.classList.toggle("disabled", value <= min);
2823
+ if (max !== void 0) {
2824
+ incrementBtn.disabled = value >= max;
2825
+ incrementBtn.classList.toggle("disabled", value >= max);
2826
+ } else {
2827
+ incrementBtn.disabled = false;
2828
+ incrementBtn.classList.remove("disabled");
2829
+ }
2830
+ };
2831
+ inputWrapper.appendChild(decrementBtn);
2832
+ inputWrapper.appendChild(input);
2833
+ inputWrapper.appendChild(incrementBtn);
2834
+ container.appendChild(inputWrapper);
2835
+ return this.createFieldContainer(container);
2836
+ }
2837
+ };
2838
+
2839
+ // src/components/inputs/accordion-select-input.ts
2840
+ var AccordionSelectInput = class extends BaseInput {
2841
+ constructor() {
2842
+ super(...arguments);
2843
+ this.openAccordion = null;
2844
+ }
2845
+ render() {
2846
+ const container = document.createElement("div");
2847
+ container.className = "easy-form-accordion-select-container";
2848
+ const accordionField = this.field;
2849
+ const selectedValue = this.value ?? null;
2850
+ accordionField.options.forEach((option, index) => {
2851
+ const optionValue = typeof option === "string" ? option : option.value;
2852
+ const optionLabel = typeof option === "string" ? option : option.label;
2853
+ const optionDescription = typeof option === "object" && "description" in option && option.description ? option.description : void 0;
2854
+ const accordionItem = document.createElement("div");
2855
+ accordionItem.className = "easy-form-accordion-item";
2856
+ accordionItem.setAttribute("data-value", String(optionValue));
2857
+ if (selectedValue === optionValue || Array.isArray(selectedValue) && selectedValue.includes(optionValue)) {
2858
+ accordionItem.classList.add("selected");
2859
+ if (!accordionField.multiple) {
2860
+ this.openAccordion = String(optionValue);
2861
+ }
2862
+ }
2863
+ const header = document.createElement("div");
2864
+ header.className = "easy-form-accordion-header";
2865
+ header.setAttribute("role", "button");
2866
+ header.setAttribute("tabindex", "0");
2867
+ header.setAttribute("aria-expanded", "false");
2868
+ const headerContent = document.createElement("div");
2869
+ headerContent.className = "easy-form-accordion-header-content";
2870
+ const indicator = document.createElement("div");
2871
+ indicator.className = "easy-form-accordion-indicator";
2872
+ if (accordionField.multiple) {
2873
+ indicator.classList.add("checkbox");
2874
+ if (Array.isArray(selectedValue) && selectedValue.includes(optionValue)) {
2875
+ indicator.classList.add("checked");
2876
+ }
2877
+ } else {
2878
+ indicator.classList.add("radio");
2879
+ if (selectedValue === optionValue) {
2880
+ indicator.classList.add("checked");
2881
+ }
2882
+ }
2883
+ const label = document.createElement("span");
2884
+ label.className = "easy-form-accordion-label";
2885
+ label.textContent = optionLabel;
2886
+ const arrow = document.createElement("span");
2887
+ arrow.className = "easy-form-accordion-arrow";
2888
+ arrow.textContent = "\u25BC";
2889
+ headerContent.appendChild(indicator);
2890
+ headerContent.appendChild(label);
2891
+ header.appendChild(headerContent);
2892
+ header.appendChild(arrow);
2893
+ const content = document.createElement("div");
2894
+ content.className = "easy-form-accordion-content";
2895
+ if (optionDescription) {
2896
+ const description = document.createElement("p");
2897
+ description.className = "easy-form-accordion-description";
2898
+ description.textContent = optionDescription;
2899
+ content.appendChild(description);
2900
+ }
2901
+ if (typeof option === "object" && "content" in option && option.content) {
2902
+ const customContent = document.createElement("div");
2903
+ customContent.className = "easy-form-accordion-custom-content";
2904
+ if (typeof option.content === "string") {
2905
+ customContent.innerHTML = option.content;
2906
+ } else if (option.content instanceof HTMLElement) {
2907
+ customContent.appendChild(option.content);
2908
+ }
2909
+ content.appendChild(customContent);
2910
+ }
2911
+ accordionItem.appendChild(header);
2912
+ accordionItem.appendChild(content);
2913
+ const toggleAccordion = () => {
2914
+ const isOpen = accordionItem.classList.contains("open");
2915
+ if (!accordionField.multiple) {
2916
+ container.querySelectorAll(".easy-form-accordion-item").forEach((item) => {
2917
+ if (item !== accordionItem) {
2918
+ item.classList.remove("open");
2919
+ const otherHeader = item.querySelector(".easy-form-accordion-header");
2920
+ const otherContent = item.querySelector(".easy-form-accordion-content");
2921
+ const otherArrow = item.querySelector(".easy-form-accordion-arrow");
2922
+ if (otherHeader) otherHeader.setAttribute("aria-expanded", "false");
2923
+ if (otherContent) otherContent.style.maxHeight = null;
2924
+ if (otherArrow) otherArrow.style.transform = "rotate(0deg)";
2925
+ }
2926
+ });
2927
+ }
2928
+ if (isOpen) {
2929
+ accordionItem.classList.remove("open");
2930
+ header.setAttribute("aria-expanded", "false");
2931
+ content.style.maxHeight = null;
2932
+ arrow.style.transform = "rotate(0deg)";
2933
+ this.openAccordion = null;
2934
+ } else {
2935
+ accordionItem.classList.add("open");
2936
+ header.setAttribute("aria-expanded", "true");
2937
+ content.style.maxHeight = content.scrollHeight + "px";
2938
+ arrow.style.transform = "rotate(180deg)";
2939
+ this.openAccordion = String(optionValue);
2940
+ }
2941
+ };
2942
+ const selectOption = () => {
2943
+ if (accordionField.multiple) {
2944
+ const currentValues = Array.isArray(selectedValue) ? [...selectedValue] : [];
2945
+ const index2 = currentValues.indexOf(optionValue);
2946
+ if (index2 > -1) {
2947
+ currentValues.splice(index2, 1);
2948
+ accordionItem.classList.remove("selected");
2949
+ indicator.classList.remove("checked");
2950
+ } else {
2951
+ currentValues.push(optionValue);
2952
+ accordionItem.classList.add("selected");
2953
+ indicator.classList.add("checked");
2954
+ }
2955
+ this.onChange(currentValues.length > 0 ? currentValues : null);
2956
+ } else {
2957
+ container.querySelectorAll(".easy-form-accordion-item").forEach((item) => {
2958
+ item.classList.remove("selected");
2959
+ const itemIndicator = item.querySelector(".easy-form-accordion-indicator");
2960
+ if (itemIndicator) itemIndicator.classList.remove("checked");
2961
+ });
2962
+ accordionItem.classList.add("selected");
2963
+ indicator.classList.add("checked");
2964
+ this.onChange(optionValue);
2965
+ }
2966
+ };
2967
+ header.addEventListener("click", (e) => {
2968
+ e.stopPropagation();
2969
+ selectOption();
2970
+ toggleAccordion();
2971
+ });
2972
+ header.addEventListener("keydown", (e) => {
2973
+ if (e.key === "Enter" || e.key === " ") {
2974
+ e.preventDefault();
2975
+ selectOption();
2976
+ toggleAccordion();
2977
+ }
2978
+ });
2979
+ if (selectedValue === optionValue || Array.isArray(selectedValue) && selectedValue.includes(optionValue)) {
2980
+ if (!accordionField.multiple || accordionField.autoExpand) {
2981
+ setTimeout(() => {
2982
+ accordionItem.classList.add("open");
2983
+ header.setAttribute("aria-expanded", "true");
2984
+ content.style.maxHeight = content.scrollHeight + "px";
2985
+ arrow.style.transform = "rotate(180deg)";
2986
+ }, 0);
2987
+ }
2988
+ }
2989
+ container.appendChild(accordionItem);
2990
+ });
2991
+ return this.createFieldContainer(container);
2992
+ }
2993
+ };
2994
+
2995
+ // src/components/inputs/image-grid-select-input.ts
2996
+ var ImageGridSelectInput = class extends BaseInput {
2997
+ render() {
2998
+ const container = document.createElement("div");
2999
+ container.className = "easy-form-image-grid-container";
3000
+ const imageGridField = this.field;
3001
+ const selectedValue = this.value ?? null;
3002
+ const columns = imageGridField.columns ?? 3;
3003
+ const imageSize = imageGridField.imageSize ?? "medium";
3004
+ container.style.gridTemplateColumns = `repeat(${columns}, 1fr)`;
3005
+ container.style.gap = imageGridField.gap ?? "1rem";
3006
+ imageGridField.options.forEach((option) => {
3007
+ const optionValue = typeof option === "string" ? option : option.value;
3008
+ const optionLabel = typeof option === "string" ? option : option.label;
3009
+ const optionImage = typeof option === "object" && "image" in option && option.image ? option.image : void 0;
3010
+ const optionDescription = typeof option === "object" && "description" in option && option.description ? option.description : void 0;
3011
+ const gridItem = document.createElement("div");
3012
+ gridItem.className = `easy-form-image-grid-item easy-form-image-grid-${imageSize}`;
3013
+ gridItem.setAttribute("data-value", String(optionValue));
3014
+ gridItem.setAttribute("role", "button");
3015
+ gridItem.setAttribute("tabindex", "0");
3016
+ gridItem.setAttribute("aria-label", optionLabel);
3017
+ if (selectedValue === optionValue || Array.isArray(selectedValue) && selectedValue.includes(optionValue)) {
3018
+ gridItem.classList.add("selected");
3019
+ }
3020
+ const imageContainer = document.createElement("div");
3021
+ imageContainer.className = "easy-form-image-grid-image-container";
3022
+ if (optionImage) {
3023
+ const img = document.createElement("img");
3024
+ img.src = optionImage;
3025
+ img.alt = optionLabel;
3026
+ img.className = "easy-form-image-grid-image";
3027
+ imageContainer.appendChild(img);
3028
+ } else {
3029
+ const placeholder = document.createElement("div");
3030
+ placeholder.className = "easy-form-image-grid-placeholder";
3031
+ placeholder.textContent = optionLabel.charAt(0).toUpperCase();
3032
+ imageContainer.appendChild(placeholder);
3033
+ }
3034
+ const indicator = document.createElement("div");
3035
+ indicator.className = "easy-form-image-grid-indicator";
3036
+ if (imageGridField.multiple) {
3037
+ indicator.classList.add("checkbox");
3038
+ if (Array.isArray(selectedValue) && selectedValue.includes(optionValue)) {
3039
+ indicator.classList.add("checked");
3040
+ indicator.innerHTML = "\u2713";
3041
+ }
3042
+ } else {
3043
+ indicator.classList.add("radio");
3044
+ if (selectedValue === optionValue) {
3045
+ indicator.classList.add("checked");
3046
+ indicator.innerHTML = "\u25CF";
3047
+ }
3048
+ }
3049
+ imageContainer.appendChild(indicator);
3050
+ const label = document.createElement("div");
3051
+ label.className = "easy-form-image-grid-label";
3052
+ label.textContent = optionLabel;
3053
+ if (optionDescription) {
3054
+ const description = document.createElement("div");
3055
+ description.className = "easy-form-image-grid-description";
3056
+ description.textContent = optionDescription;
3057
+ gridItem.appendChild(description);
3058
+ }
3059
+ gridItem.appendChild(imageContainer);
3060
+ gridItem.appendChild(label);
3061
+ const selectOption = () => {
3062
+ if (imageGridField.multiple) {
3063
+ const currentValues = Array.isArray(selectedValue) ? [...selectedValue] : [];
3064
+ const index = currentValues.indexOf(optionValue);
3065
+ if (index > -1) {
3066
+ currentValues.splice(index, 1);
3067
+ gridItem.classList.remove("selected");
3068
+ indicator.classList.remove("checked");
3069
+ indicator.innerHTML = "";
3070
+ } else {
3071
+ currentValues.push(optionValue);
3072
+ gridItem.classList.add("selected");
3073
+ indicator.classList.add("checked");
3074
+ indicator.innerHTML = "\u2713";
3075
+ }
3076
+ this.onChange(currentValues.length > 0 ? currentValues : null);
3077
+ } else {
3078
+ container.querySelectorAll(".easy-form-image-grid-item").forEach((item) => {
3079
+ item.classList.remove("selected");
3080
+ const itemIndicator = item.querySelector(".easy-form-image-grid-indicator");
3081
+ if (itemIndicator) {
3082
+ itemIndicator.classList.remove("checked");
3083
+ itemIndicator.innerHTML = "";
3084
+ }
3085
+ });
3086
+ gridItem.classList.add("selected");
3087
+ indicator.classList.add("checked");
3088
+ indicator.innerHTML = "\u25CF";
3089
+ this.onChange(optionValue);
3090
+ }
3091
+ };
3092
+ gridItem.addEventListener("click", selectOption);
3093
+ gridItem.addEventListener("keydown", (e) => {
3094
+ if (e.key === "Enter" || e.key === " ") {
3095
+ e.preventDefault();
3096
+ selectOption();
3097
+ }
3098
+ });
3099
+ gridItem.addEventListener("blur", () => {
3100
+ this.onBlur();
3101
+ });
3102
+ container.appendChild(gridItem);
3103
+ });
3104
+ return this.createFieldContainer(container);
3105
+ }
3106
+ };
3107
+
3108
+ // src/components/inputs/otp-input.ts
3109
+ var OTPInput = class extends BaseInput {
3110
+ constructor() {
3111
+ super(...arguments);
3112
+ this.inputs = [];
3113
+ }
3114
+ render() {
3115
+ const container = document.createElement("div");
3116
+ container.className = "easy-form-otp-container";
3117
+ const otpField = this.field;
3118
+ const length = otpField.length ?? 6;
3119
+ const value = this.value ?? "";
3120
+ const valueString = String(value).padStart(length, "").slice(0, length);
3121
+ for (let i = 0; i < length; i++) {
3122
+ const input = document.createElement("input");
3123
+ input.type = "text";
3124
+ input.inputMode = "numeric";
3125
+ input.maxLength = 1;
3126
+ input.className = "easy-form-otp-input";
3127
+ input.setAttribute("aria-label", `C\xF3digo d\xEDgito ${i + 1}`);
3128
+ if (valueString[i]) {
3129
+ input.value = valueString[i];
3130
+ }
3131
+ this.applyCommonProps(input);
3132
+ input.id = `${this.getFieldId()}-${i}`;
3133
+ const currentIndex = i;
3134
+ input.addEventListener("input", (e) => {
3135
+ const target = e.target;
3136
+ const inputValue = target.value.replace(/[^0-9]/g, "");
3137
+ target.value = inputValue;
3138
+ if (inputValue && currentIndex < length - 1) {
3139
+ this.inputs[currentIndex + 1].focus();
3140
+ }
3141
+ this.updateOTPValue();
3142
+ });
3143
+ input.addEventListener("keydown", (e) => {
3144
+ const target = e.target;
3145
+ if (e.key === "Backspace" && !target.value && currentIndex > 0) {
3146
+ this.inputs[currentIndex - 1].focus();
3147
+ this.inputs[currentIndex - 1].value = "";
3148
+ this.updateOTPValue();
3149
+ }
3150
+ if (e.key === "ArrowLeft" && currentIndex > 0) {
3151
+ e.preventDefault();
3152
+ this.inputs[currentIndex - 1].focus();
3153
+ }
3154
+ if (e.key === "ArrowRight" && currentIndex < length - 1) {
3155
+ e.preventDefault();
3156
+ this.inputs[currentIndex + 1].focus();
3157
+ }
3158
+ });
3159
+ input.addEventListener("paste", (e) => {
3160
+ e.preventDefault();
3161
+ const pastedData = (e.clipboardData || window.clipboardData).getData("text");
3162
+ const digits = pastedData.replace(/[^0-9]/g, "").slice(0, length);
3163
+ for (let j = 0; j < digits.length && currentIndex + j < length; j++) {
3164
+ this.inputs[currentIndex + j].value = digits[j];
3165
+ }
3166
+ const nextEmptyIndex = Math.min(currentIndex + digits.length, length - 1);
3167
+ this.inputs[nextEmptyIndex].focus();
3168
+ this.updateOTPValue();
3169
+ });
3170
+ input.addEventListener("focus", (e) => {
3171
+ const target = e.target;
3172
+ target.select();
3173
+ });
3174
+ input.addEventListener("blur", () => {
3175
+ this.onBlur();
3176
+ });
3177
+ this.inputs.push(input);
3178
+ container.appendChild(input);
3179
+ }
3180
+ return this.createFieldContainer(container);
3181
+ }
3182
+ updateOTPValue() {
3183
+ const otpValue = this.inputs.map((input) => input.value).join("");
3184
+ const otpField = this.field;
3185
+ const finalValue = otpValue.length === this.inputs.length ? otpValue : null;
3186
+ if (otpField.numeric && finalValue) {
3187
+ this.onChange(Number(finalValue));
3188
+ } else {
3189
+ this.onChange(finalValue);
3190
+ }
3191
+ }
3192
+ };
3193
+
2473
3194
  // src/components/inputs/index.ts
2474
3195
  function createInput(field, value, error, onChange, onBlur) {
2475
3196
  switch (field.type) {
@@ -2493,6 +3214,14 @@ function createInput(field, value, error, onChange, onBlur) {
2493
3214
  return new DateInput(field, value, error, onChange, onBlur).render();
2494
3215
  case "file":
2495
3216
  return new FileInput(field, value, error, onChange, onBlur).render();
3217
+ case "quantity":
3218
+ return new QuantityInput(field, value, error, onChange, onBlur).render();
3219
+ case "accordion-select":
3220
+ return new AccordionSelectInput(field, value, error, onChange, onBlur).render();
3221
+ case "image-grid-select":
3222
+ return new ImageGridSelectInput(field, value, error, onChange, onBlur).render();
3223
+ case "otp":
3224
+ return new OTPInput(field, value, error, onChange, onBlur).render();
2496
3225
  default:
2497
3226
  const div = document.createElement("div");
2498
3227
  div.textContent = `Tipo de campo no soportado: ${field.type}`;