@pixpilot/formily-shadcn 0.9.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/README.md +102 -1
  2. package/dist/components/array-base/components/array-item-label.cjs +1 -1
  3. package/dist/components/array-base/components/array-item-label.js +1 -1
  4. package/dist/components/checkbox.d.ts +2 -2
  5. package/dist/components/column.d.ts +2 -2
  6. package/dist/components/context/context.d.cts +1 -1
  7. package/dist/components/context/context.d.ts +1 -1
  8. package/dist/components/context/form-context.d.cts +52 -19
  9. package/dist/components/context/form-context.d.ts +52 -19
  10. package/dist/components/context/index.d.cts +1 -1
  11. package/dist/components/context/index.d.ts +1 -1
  12. package/dist/components/date-picker.d.cts +3 -3
  13. package/dist/components/date-picker.d.ts +3 -3
  14. package/dist/components/file-upload/file-upload-inline.d.cts +8 -8
  15. package/dist/components/file-upload/file-upload-inline.d.ts +8 -8
  16. package/dist/components/file-upload/file-upload.d.cts +8 -8
  17. package/dist/components/file-upload/file-upload.d.ts +8 -8
  18. package/dist/components/file-upload/use-file-upload-feedback.cjs +2 -2
  19. package/dist/components/file-upload/use-file-upload-feedback.js +2 -2
  20. package/dist/components/form-grid.d.cts +2 -2
  21. package/dist/components/form-grid.d.ts +2 -2
  22. package/dist/components/form-item/base-form-item.cjs +85 -0
  23. package/dist/components/form-item/base-form-item.d.cts +2 -0
  24. package/dist/components/form-item/base-form-item.d.ts +2 -0
  25. package/dist/components/form-item/base-form-item.js +80 -0
  26. package/dist/components/form-item/connected-form-item.cjs +47 -0
  27. package/dist/components/form-item/connected-form-item.d.cts +13 -0
  28. package/dist/components/form-item/connected-form-item.d.ts +13 -0
  29. package/dist/components/form-item/connected-form-item.js +44 -0
  30. package/dist/components/form-item/form-item-description-popover.cjs +42 -0
  31. package/dist/components/form-item/form-item-description-popover.js +37 -0
  32. package/dist/components/form-item/form-item-label.cjs +29 -0
  33. package/dist/components/form-item/form-item-label.js +25 -0
  34. package/dist/components/form-item/form-item-types.d.cts +23 -0
  35. package/dist/components/form-item/form-item-types.d.ts +23 -0
  36. package/dist/components/form-item/form-item.cjs +2 -0
  37. package/dist/components/form-item/form-item.d.cts +4 -0
  38. package/dist/components/form-item/form-item.d.ts +4 -0
  39. package/dist/components/form-item/form-item.js +2 -0
  40. package/dist/components/form-item/index.cjs +3 -0
  41. package/dist/components/form-item/index.d.cts +4 -0
  42. package/dist/components/form-item/index.d.ts +4 -0
  43. package/dist/components/form-item/index.js +3 -0
  44. package/dist/components/form-item/spacing-config.cjs +24 -0
  45. package/dist/components/form-item/spacing-config.js +23 -0
  46. package/dist/components/form-items-container.cjs +3 -5
  47. package/dist/components/form-items-container.js +3 -5
  48. package/dist/components/form.cjs +5 -14
  49. package/dist/components/form.d.cts +4 -7
  50. package/dist/components/form.d.ts +2 -5
  51. package/dist/components/form.js +5 -14
  52. package/dist/components/icon-picker.cjs +2 -2
  53. package/dist/components/icon-picker.d.cts +3 -3
  54. package/dist/components/icon-picker.d.ts +3 -3
  55. package/dist/components/icon-picker.js +2 -2
  56. package/dist/components/input.d.cts +2 -2
  57. package/dist/components/input.d.ts +2 -2
  58. package/dist/components/json-schema-form-renderer/index.cjs +4 -0
  59. package/dist/components/json-schema-form-renderer/index.d.cts +5 -0
  60. package/dist/components/json-schema-form-renderer/index.d.ts +5 -0
  61. package/dist/components/json-schema-form-renderer/index.js +4 -0
  62. package/dist/components/json-schema-form-renderer/json-schema-form-basic.cjs +35 -0
  63. package/dist/components/json-schema-form-renderer/json-schema-form-basic.d.cts +14 -0
  64. package/dist/components/json-schema-form-renderer/json-schema-form-basic.d.ts +14 -0
  65. package/dist/components/json-schema-form-renderer/json-schema-form-basic.js +32 -0
  66. package/dist/components/json-schema-form-renderer/json-schema-form-extended.cjs +35 -0
  67. package/dist/components/json-schema-form-renderer/json-schema-form-extended.d.cts +14 -0
  68. package/dist/components/json-schema-form-renderer/json-schema-form-extended.d.ts +14 -0
  69. package/dist/components/json-schema-form-renderer/json-schema-form-extended.js +32 -0
  70. package/dist/components/json-schema-form-renderer/json-schema-form-renderer.cjs +57 -0
  71. package/dist/components/json-schema-form-renderer/json-schema-form-renderer.d.cts +7 -0
  72. package/dist/components/json-schema-form-renderer/json-schema-form-renderer.d.ts +7 -0
  73. package/dist/components/json-schema-form-renderer/json-schema-form-renderer.js +51 -0
  74. package/dist/components/json-schema-form-renderer/json-schema-form.cjs +36 -0
  75. package/dist/components/json-schema-form-renderer/json-schema-form.d.cts +14 -0
  76. package/dist/components/json-schema-form-renderer/json-schema-form.d.ts +14 -0
  77. package/dist/components/json-schema-form-renderer/json-schema-form.js +33 -0
  78. package/dist/components/json-schema-form-renderer/types.d.cts +23 -0
  79. package/dist/components/json-schema-form-renderer/types.d.ts +23 -0
  80. package/dist/components/number-input.d.cts +2 -2
  81. package/dist/components/number-input.d.ts +2 -2
  82. package/dist/components/object-container.cjs +42 -9
  83. package/dist/components/object-container.js +43 -10
  84. package/dist/components/radio.d.cts +2 -2
  85. package/dist/components/radio.d.ts +2 -2
  86. package/dist/components/rich-text-editor.cjs +1 -1
  87. package/dist/components/rich-text-editor.js +1 -1
  88. package/dist/components/row.d.cts +2 -2
  89. package/dist/components/row.d.ts +2 -2
  90. package/dist/components/schema-field/index.d.cts +3 -3
  91. package/dist/components/schema-field/index.d.ts +3 -3
  92. package/dist/components/schema-field/index.js +3 -3
  93. package/dist/components/schema-field/schema-field-basics.cjs +67 -24
  94. package/dist/components/schema-field/schema-field-basics.d.cts +283 -198
  95. package/dist/components/schema-field/schema-field-basics.d.ts +283 -198
  96. package/dist/components/schema-field/schema-field-basics.js +65 -23
  97. package/dist/components/schema-field/schema-field-extended.cjs +23 -8
  98. package/dist/components/schema-field/schema-field-extended.d.cts +442 -307
  99. package/dist/components/schema-field/schema-field-extended.d.ts +442 -307
  100. package/dist/components/schema-field/schema-field-extended.js +23 -9
  101. package/dist/components/schema-field/schema-field.cjs +23 -8
  102. package/dist/components/schema-field/schema-field.d.cts +338 -237
  103. package/dist/components/schema-field/schema-field.d.ts +338 -237
  104. package/dist/components/schema-field/schema-field.js +23 -9
  105. package/dist/components/separator.d.ts +2 -2
  106. package/dist/components/slider.d.cts +2 -2
  107. package/dist/components/slider.d.ts +2 -2
  108. package/dist/components/switch.d.ts +2 -2
  109. package/dist/components/tags-input-inline.d.cts +2 -2
  110. package/dist/components/tags-input-inline.d.ts +2 -2
  111. package/dist/components/textarea.d.ts +2 -2
  112. package/dist/hooks/index.js +1 -1
  113. package/dist/hooks/use-form-context.cjs +5 -0
  114. package/dist/hooks/use-form-context.js +5 -1
  115. package/dist/hooks/use-label.cjs +9 -2
  116. package/dist/hooks/use-label.js +9 -2
  117. package/dist/index.cjs +17 -6
  118. package/dist/index.d.cts +14 -6
  119. package/dist/index.d.ts +14 -6
  120. package/dist/index.js +11 -6
  121. package/dist/types/form-item.d.cts +5 -0
  122. package/dist/types/form-item.d.ts +5 -0
  123. package/dist/types/form.d.cts +0 -6
  124. package/dist/types/form.d.ts +0 -6
  125. package/dist/utils/extract-components.cjs +11 -0
  126. package/dist/utils/extract-components.js +10 -0
  127. package/dist/utils/extract-fields-decorators.cjs +37 -0
  128. package/dist/utils/extract-fields-decorators.js +36 -0
  129. package/dist/utils/index.cjs +2 -0
  130. package/dist/utils/index.js +3 -1
  131. package/dist/utils/resolve-responsive-space.cjs +45 -89
  132. package/dist/utils/resolve-responsive-space.js +42 -83
  133. package/dist/utils/transform-schema.cjs +9 -2
  134. package/dist/utils/transform-schema.js +9 -2
  135. package/dist/utils/validate-schema-components.cjs +45 -0
  136. package/dist/utils/validate-schema-components.js +43 -0
  137. package/package.json +4 -3
  138. package/dist/components/form-item.cjs +0 -118
  139. package/dist/components/form-item.d.cts +0 -22
  140. package/dist/components/form-item.d.ts +0 -22
  141. package/dist/components/form-item.js +0 -112
  142. package/dist/components/json-schema-form-renderer.cjs +0 -31
  143. package/dist/components/json-schema-form-renderer.d.cts +0 -15
  144. package/dist/components/json-schema-form-renderer.d.ts +0 -15
  145. package/dist/components/json-schema-form-renderer.js +0 -27
@@ -10,74 +10,44 @@ const densitySpaceMap = {
10
10
  comfortable: "lg"
11
11
  };
12
12
  /**
13
- * Space to Tailwind space-y class mapping
14
- * Converts space values to actual Tailwind utilities
13
+ * Space-Y spacing configuration
14
+ * Controls vertical spacing between form items
15
15
  */
16
- const spaceClassMap = {
17
- sm: "space-y-3",
18
- md: "space-y-4",
19
- lg: "space-y-6"
16
+ const spaceYConfig = {
17
+ fixed: {
18
+ sm: "space-y-3",
19
+ md: "space-y-4",
20
+ lg: "space-y-6"
21
+ },
22
+ responsive: "space-y-3 md:space-y-4 lg:space-y-6"
20
23
  };
21
24
  /**
22
- * Space to Tailwind gap class mapping
23
- * Converts space values to gap utilities for grid/flex containers
25
+ * Gap-Y spacing configuration
26
+ * Controls vertical gaps in containers
24
27
  */
25
- const gapClassMap = {
26
- sm: "gap-y-3",
27
- md: "gap-y-4",
28
- lg: "gap-y-6"
28
+ const gapYConfig = {
29
+ fixed: {
30
+ sm: "gap-y-3",
31
+ md: "gap-y-4",
32
+ lg: "gap-y-6"
33
+ },
34
+ responsive: "gap-y-3 md:gap-y-4 lg:gap-y-6"
29
35
  };
30
36
  /**
31
- * Responsive breakpoint classes for responsive density mode
32
- * - Mobile (default): compact (space-y-3)
33
- * - Tablet (md:): normal (space-y-4)
34
- * - Desktop (lg:): comfortable (space-y-6)
35
- */
36
- const autoResponsiveSpaceClasses = "space-y-3 md:space-y-4 lg:space-y-6";
37
- /**
38
- * Responsive breakpoint classes for responsive density mode using gap
39
- * - Mobile (default): compact (gap-y-3)
40
- * - Tablet (md:): normal (gap-y-4)
41
- * - Desktop (lg:): comfortable (gap-y-6)
42
- */
43
- const autoResponsiveGapClasses = "gap-y-3 md:gap-y-4 lg:gap-y-6";
44
- /**
45
- * Checks if density is responsive mode
46
- *
47
- * @param density - Density value
48
- * @returns true if density is 'responsive'
49
- */
50
- function isResponsiveDensity(density) {
51
- return density === "responsive";
52
- }
53
- /**
54
- * Resolves responsive space value from FormSpace configuration
55
- * Priority:
56
- * 1. If responsive is set → use it (ignore density)
57
- * 2. If density is 'responsive' → return undefined (handled separately with responsive classes)
58
- * 3. If only other density is set → use density-based mapping
59
- * 4. Default to undefined (responsive mode)
60
- *
61
- * @param formSpace - FormSpace configuration
62
- * @returns Space value ('sm' | 'md' | 'lg') or undefined for responsive mode
63
- */
64
- function resolveResponsiveSpace(formSpace) {
65
- if (!formSpace) return;
66
- if (formSpace.responsive) return formSpace.responsive.desktop || formSpace.responsive.tablet || formSpace.responsive.mobile || "lg";
67
- if (isResponsiveDensity(formSpace.density)) return;
68
- if (formSpace.density && !isResponsiveDensity(formSpace.density)) return densitySpaceMap[formSpace.density];
69
- }
70
- /**
71
- * Gets the Tailwind class for a given space value
37
+ * Resolves spacing class based on density and spacing configuration
38
+ * Generic utility that works with any spacing config
72
39
  *
73
- * @param space - Space value
74
- * @returns Tailwind utility class
40
+ * @param density - Density value ('compact' | 'normal' | 'comfortable' | 'responsive')
41
+ * @param config - Spacing configuration with fixed and responsive classes
42
+ * @returns Tailwind utility class(es)
75
43
  */
76
- function getSpaceClass(space) {
77
- return spaceClassMap[space];
44
+ function resolveSpacingClass(density, config) {
45
+ if (!density || density === "responsive") return config.responsive;
46
+ const space = densitySpaceMap[density];
47
+ return config.fixed[space];
78
48
  }
79
49
  /**
80
- * Resolves responsive space and returns the Tailwind class(es)
50
+ * Resolves responsive space and returns the Tailwind space-y class(es)
81
51
  * For responsive density, returns responsive breakpoint classes
82
52
  * For fixed density, returns single space class
83
53
  *
@@ -85,25 +55,10 @@ function getSpaceClass(space) {
85
55
  * @returns Tailwind utility class(es)
86
56
  */
87
57
  function resolveResponsiveSpaceClass(formSpace) {
88
- if (!formSpace || isResponsiveDensity(formSpace.density)) return autoResponsiveSpaceClasses;
89
- if (formSpace.responsive && !isResponsiveDensity(formSpace.density)) {
90
- const space$1 = resolveResponsiveSpace(formSpace);
91
- return space$1 ? getSpaceClass(space$1) : autoResponsiveSpaceClasses;
92
- }
93
- const space = resolveResponsiveSpace(formSpace);
94
- return space ? getSpaceClass(space) : autoResponsiveSpaceClasses;
58
+ return resolveSpacingClass(formSpace?.density, spaceYConfig);
95
59
  }
96
60
  /**
97
- * Gets the Tailwind gap class for a given space value
98
- *
99
- * @param space - Space value
100
- * @returns Tailwind utility gap class
101
- */
102
- function getGapClass(space) {
103
- return gapClassMap[space];
104
- }
105
- /**
106
- * Resolves responsive space and returns the Tailwind gap class(es)
61
+ * Resolves responsive space and returns the Tailwind gap-y class(es)
107
62
  * For responsive density, returns responsive breakpoint classes
108
63
  * For fixed density, returns single gap class
109
64
  *
@@ -111,21 +66,22 @@ function getGapClass(space) {
111
66
  * @returns Tailwind utility gap class(es)
112
67
  */
113
68
  function resolveResponsiveGapClass(formSpace) {
114
- if (!formSpace || isResponsiveDensity(formSpace.density)) return autoResponsiveGapClasses;
115
- if (formSpace.responsive && !isResponsiveDensity(formSpace.density)) {
116
- const space$1 = resolveResponsiveSpace(formSpace);
117
- return space$1 ? getGapClass(space$1) : autoResponsiveGapClasses;
118
- }
119
- const space = resolveResponsiveSpace(formSpace);
120
- return space ? getGapClass(space) : autoResponsiveGapClasses;
69
+ return resolveSpacingClass(formSpace?.density, gapYConfig);
121
70
  }
71
+ /**
72
+ * Deprecated: Use resolveSpacingClass instead
73
+ * @deprecated
74
+ */
75
+ const autoResponsiveSpaceClasses = spaceYConfig.responsive;
76
+ /**
77
+ * Deprecated: Use resolveSpacingClass instead
78
+ * @deprecated
79
+ */
80
+ const autoResponsiveGapClasses = gapYConfig.responsive;
122
81
 
123
82
  //#endregion
124
- exports.autoResponsiveGapClasses = autoResponsiveGapClasses;
125
- exports.autoResponsiveSpaceClasses = autoResponsiveSpaceClasses;
126
- exports.getGapClass = getGapClass;
127
- exports.getSpaceClass = getSpaceClass;
128
- exports.isResponsiveDensity = isResponsiveDensity;
83
+ exports.gapYConfig = gapYConfig;
129
84
  exports.resolveResponsiveGapClass = resolveResponsiveGapClass;
130
- exports.resolveResponsiveSpace = resolveResponsiveSpace;
131
- exports.resolveResponsiveSpaceClass = resolveResponsiveSpaceClass;
85
+ exports.resolveResponsiveSpaceClass = resolveResponsiveSpaceClass;
86
+ exports.resolveSpacingClass = resolveSpacingClass;
87
+ exports.spaceYConfig = spaceYConfig;
@@ -9,74 +9,44 @@ const densitySpaceMap = {
9
9
  comfortable: "lg"
10
10
  };
11
11
  /**
12
- * Space to Tailwind space-y class mapping
13
- * Converts space values to actual Tailwind utilities
12
+ * Space-Y spacing configuration
13
+ * Controls vertical spacing between form items
14
14
  */
15
- const spaceClassMap = {
16
- sm: "space-y-3",
17
- md: "space-y-4",
18
- lg: "space-y-6"
15
+ const spaceYConfig = {
16
+ fixed: {
17
+ sm: "space-y-3",
18
+ md: "space-y-4",
19
+ lg: "space-y-6"
20
+ },
21
+ responsive: "space-y-3 md:space-y-4 lg:space-y-6"
19
22
  };
20
23
  /**
21
- * Space to Tailwind gap class mapping
22
- * Converts space values to gap utilities for grid/flex containers
24
+ * Gap-Y spacing configuration
25
+ * Controls vertical gaps in containers
23
26
  */
24
- const gapClassMap = {
25
- sm: "gap-y-3",
26
- md: "gap-y-4",
27
- lg: "gap-y-6"
27
+ const gapYConfig = {
28
+ fixed: {
29
+ sm: "gap-y-3",
30
+ md: "gap-y-4",
31
+ lg: "gap-y-6"
32
+ },
33
+ responsive: "gap-y-3 md:gap-y-4 lg:gap-y-6"
28
34
  };
29
35
  /**
30
- * Responsive breakpoint classes for responsive density mode
31
- * - Mobile (default): compact (space-y-3)
32
- * - Tablet (md:): normal (space-y-4)
33
- * - Desktop (lg:): comfortable (space-y-6)
34
- */
35
- const autoResponsiveSpaceClasses = "space-y-3 md:space-y-4 lg:space-y-6";
36
- /**
37
- * Responsive breakpoint classes for responsive density mode using gap
38
- * - Mobile (default): compact (gap-y-3)
39
- * - Tablet (md:): normal (gap-y-4)
40
- * - Desktop (lg:): comfortable (gap-y-6)
41
- */
42
- const autoResponsiveGapClasses = "gap-y-3 md:gap-y-4 lg:gap-y-6";
43
- /**
44
- * Checks if density is responsive mode
45
- *
46
- * @param density - Density value
47
- * @returns true if density is 'responsive'
48
- */
49
- function isResponsiveDensity(density) {
50
- return density === "responsive";
51
- }
52
- /**
53
- * Resolves responsive space value from FormSpace configuration
54
- * Priority:
55
- * 1. If responsive is set → use it (ignore density)
56
- * 2. If density is 'responsive' → return undefined (handled separately with responsive classes)
57
- * 3. If only other density is set → use density-based mapping
58
- * 4. Default to undefined (responsive mode)
59
- *
60
- * @param formSpace - FormSpace configuration
61
- * @returns Space value ('sm' | 'md' | 'lg') or undefined for responsive mode
62
- */
63
- function resolveResponsiveSpace(formSpace) {
64
- if (!formSpace) return;
65
- if (formSpace.responsive) return formSpace.responsive.desktop || formSpace.responsive.tablet || formSpace.responsive.mobile || "lg";
66
- if (isResponsiveDensity(formSpace.density)) return;
67
- if (formSpace.density && !isResponsiveDensity(formSpace.density)) return densitySpaceMap[formSpace.density];
68
- }
69
- /**
70
- * Gets the Tailwind class for a given space value
36
+ * Resolves spacing class based on density and spacing configuration
37
+ * Generic utility that works with any spacing config
71
38
  *
72
- * @param space - Space value
73
- * @returns Tailwind utility class
39
+ * @param density - Density value ('compact' | 'normal' | 'comfortable' | 'responsive')
40
+ * @param config - Spacing configuration with fixed and responsive classes
41
+ * @returns Tailwind utility class(es)
74
42
  */
75
- function getSpaceClass(space) {
76
- return spaceClassMap[space];
43
+ function resolveSpacingClass(density, config) {
44
+ if (!density || density === "responsive") return config.responsive;
45
+ const space = densitySpaceMap[density];
46
+ return config.fixed[space];
77
47
  }
78
48
  /**
79
- * Resolves responsive space and returns the Tailwind class(es)
49
+ * Resolves responsive space and returns the Tailwind space-y class(es)
80
50
  * For responsive density, returns responsive breakpoint classes
81
51
  * For fixed density, returns single space class
82
52
  *
@@ -84,25 +54,10 @@ function getSpaceClass(space) {
84
54
  * @returns Tailwind utility class(es)
85
55
  */
86
56
  function resolveResponsiveSpaceClass(formSpace) {
87
- if (!formSpace || isResponsiveDensity(formSpace.density)) return autoResponsiveSpaceClasses;
88
- if (formSpace.responsive && !isResponsiveDensity(formSpace.density)) {
89
- const space$1 = resolveResponsiveSpace(formSpace);
90
- return space$1 ? getSpaceClass(space$1) : autoResponsiveSpaceClasses;
91
- }
92
- const space = resolveResponsiveSpace(formSpace);
93
- return space ? getSpaceClass(space) : autoResponsiveSpaceClasses;
57
+ return resolveSpacingClass(formSpace?.density, spaceYConfig);
94
58
  }
95
59
  /**
96
- * Gets the Tailwind gap class for a given space value
97
- *
98
- * @param space - Space value
99
- * @returns Tailwind utility gap class
100
- */
101
- function getGapClass(space) {
102
- return gapClassMap[space];
103
- }
104
- /**
105
- * Resolves responsive space and returns the Tailwind gap class(es)
60
+ * Resolves responsive space and returns the Tailwind gap-y class(es)
106
61
  * For responsive density, returns responsive breakpoint classes
107
62
  * For fixed density, returns single gap class
108
63
  *
@@ -110,14 +65,18 @@ function getGapClass(space) {
110
65
  * @returns Tailwind utility gap class(es)
111
66
  */
112
67
  function resolveResponsiveGapClass(formSpace) {
113
- if (!formSpace || isResponsiveDensity(formSpace.density)) return autoResponsiveGapClasses;
114
- if (formSpace.responsive && !isResponsiveDensity(formSpace.density)) {
115
- const space$1 = resolveResponsiveSpace(formSpace);
116
- return space$1 ? getGapClass(space$1) : autoResponsiveGapClasses;
117
- }
118
- const space = resolveResponsiveSpace(formSpace);
119
- return space ? getGapClass(space) : autoResponsiveGapClasses;
68
+ return resolveSpacingClass(formSpace?.density, gapYConfig);
120
69
  }
70
+ /**
71
+ * Deprecated: Use resolveSpacingClass instead
72
+ * @deprecated
73
+ */
74
+ const autoResponsiveSpaceClasses = spaceYConfig.responsive;
75
+ /**
76
+ * Deprecated: Use resolveSpacingClass instead
77
+ * @deprecated
78
+ */
79
+ const autoResponsiveGapClasses = gapYConfig.responsive;
121
80
 
122
81
  //#endregion
123
- export { autoResponsiveGapClasses, autoResponsiveSpaceClasses, getGapClass, getSpaceClass, isResponsiveDensity, resolveResponsiveGapClass, resolveResponsiveSpace, resolveResponsiveSpaceClass };
82
+ export { gapYConfig, resolveResponsiveGapClass, resolveResponsiveSpaceClass, resolveSpacingClass, spaceYConfig };
@@ -26,15 +26,22 @@ const inputSchemaMap = {
26
26
  },
27
27
  object: { "x-component": "ObjectContainer" }
28
28
  };
29
- function transformSchema(schema) {
29
+ function transformSchema(schema, fieldsDecorators) {
30
30
  (0, json_schema_traverse.default)(schema, {
31
31
  allKeys: true,
32
32
  cb: (currentSchema) => {
33
33
  const { type } = currentSchema;
34
+ const xComponent = currentSchema["x-component"];
34
35
  if (typeof type === "string" && type in inputSchemaMap) {
35
36
  const mapping = inputSchemaMap[type];
36
37
  if (currentSchema["x-component"] == null) currentSchema["x-component"] = mapping["x-component"];
37
- if (!["Hidden", "hidden"].includes(currentSchema["x-component"])) currentSchema["x-decorator"] = mapping["x-decorator"];
38
+ }
39
+ if (!["Hidden", "hidden"].includes(currentSchema["x-component"])) {
40
+ if (currentSchema["x-decorator"] == null) {
41
+ const userDecorator = xComponent != null && fieldsDecorators != null && fieldsDecorators[xComponent] != null ? fieldsDecorators[xComponent] : null;
42
+ if (userDecorator != null) currentSchema["x-decorator"] = userDecorator;
43
+ else if (typeof type === "string" && type in inputSchemaMap) currentSchema["x-decorator"] = inputSchemaMap[type]["x-decorator"];
44
+ }
38
45
  }
39
46
  }
40
47
  });
@@ -24,15 +24,22 @@ const inputSchemaMap = {
24
24
  },
25
25
  object: { "x-component": "ObjectContainer" }
26
26
  };
27
- function transformSchema(schema) {
27
+ function transformSchema(schema, fieldsDecorators) {
28
28
  traverse(schema, {
29
29
  allKeys: true,
30
30
  cb: (currentSchema) => {
31
31
  const { type } = currentSchema;
32
+ const xComponent = currentSchema["x-component"];
32
33
  if (typeof type === "string" && type in inputSchemaMap) {
33
34
  const mapping = inputSchemaMap[type];
34
35
  if (currentSchema["x-component"] == null) currentSchema["x-component"] = mapping["x-component"];
35
- if (!["Hidden", "hidden"].includes(currentSchema["x-component"])) currentSchema["x-decorator"] = mapping["x-decorator"];
36
+ }
37
+ if (!["Hidden", "hidden"].includes(currentSchema["x-component"])) {
38
+ if (currentSchema["x-decorator"] == null) {
39
+ const userDecorator = xComponent != null && fieldsDecorators != null && fieldsDecorators[xComponent] != null ? fieldsDecorators[xComponent] : null;
40
+ if (userDecorator != null) currentSchema["x-decorator"] = userDecorator;
41
+ else if (typeof type === "string" && type in inputSchemaMap) currentSchema["x-decorator"] = inputSchemaMap[type]["x-decorator"];
42
+ }
36
43
  }
37
44
  }
38
45
  });
@@ -0,0 +1,45 @@
1
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
+ let json_schema_traverse = require("json-schema-traverse");
3
+ json_schema_traverse = require_rolldown_runtime.__toESM(json_schema_traverse);
4
+
5
+ //#region src/utils/validate-schema-components.ts
6
+ /**
7
+ * Validates schema components against the provided React components.
8
+ *
9
+ * For x-component and x-decorator references, they must match a component key
10
+ * in the provided components object.
11
+ *
12
+ * Throws an error if:
13
+ * - An x-component reference doesn't match any available component key
14
+ * - An x-decorator reference doesn't match any available component key
15
+ *
16
+ * @param schema - The ISchema to validate
17
+ * @param components - Record of available React components (includes both components and decorators)
18
+ * @throws {Error} If validation fails
19
+ *
20
+ * @example
21
+ * const components = { Input, NumberInput, Checkbox, FormItem };
22
+ * validateSchemaComponents(schema, components);
23
+ */
24
+ function validateSchemaComponents(schema, components) {
25
+ const componentKeys = Object.keys(components);
26
+ const errors = [];
27
+ (0, json_schema_traverse.default)(schema, {
28
+ allKeys: true,
29
+ cb: (currentSchema, jsonPointer) => {
30
+ const current = currentSchema;
31
+ const xComponent = current["x-component"];
32
+ const xDecorator = current["x-decorator"];
33
+ if (xComponent != null && typeof xComponent === "string") {
34
+ if (!componentKeys.includes(xComponent)) errors.push(`Component '${xComponent}' at path '${jsonPointer}' is not registered in the provided components.`);
35
+ }
36
+ if (xDecorator != null && typeof xDecorator === "string") {
37
+ if (!componentKeys.includes(xDecorator)) errors.push(`Decorator '${xDecorator}' at path '${jsonPointer}' is not registered in the provided components.`);
38
+ }
39
+ }
40
+ });
41
+ if (errors.length > 0) throw new Error(`Schema validation failed:\n${errors.join("\n")}`);
42
+ }
43
+
44
+ //#endregion
45
+ exports.validateSchemaComponents = validateSchemaComponents;
@@ -0,0 +1,43 @@
1
+ import traverse from "json-schema-traverse";
2
+
3
+ //#region src/utils/validate-schema-components.ts
4
+ /**
5
+ * Validates schema components against the provided React components.
6
+ *
7
+ * For x-component and x-decorator references, they must match a component key
8
+ * in the provided components object.
9
+ *
10
+ * Throws an error if:
11
+ * - An x-component reference doesn't match any available component key
12
+ * - An x-decorator reference doesn't match any available component key
13
+ *
14
+ * @param schema - The ISchema to validate
15
+ * @param components - Record of available React components (includes both components and decorators)
16
+ * @throws {Error} If validation fails
17
+ *
18
+ * @example
19
+ * const components = { Input, NumberInput, Checkbox, FormItem };
20
+ * validateSchemaComponents(schema, components);
21
+ */
22
+ function validateSchemaComponents(schema, components) {
23
+ const componentKeys = Object.keys(components);
24
+ const errors = [];
25
+ traverse(schema, {
26
+ allKeys: true,
27
+ cb: (currentSchema, jsonPointer) => {
28
+ const current = currentSchema;
29
+ const xComponent = current["x-component"];
30
+ const xDecorator = current["x-decorator"];
31
+ if (xComponent != null && typeof xComponent === "string") {
32
+ if (!componentKeys.includes(xComponent)) errors.push(`Component '${xComponent}' at path '${jsonPointer}' is not registered in the provided components.`);
33
+ }
34
+ if (xDecorator != null && typeof xDecorator === "string") {
35
+ if (!componentKeys.includes(xDecorator)) errors.push(`Decorator '${xDecorator}' at path '${jsonPointer}' is not registered in the provided components.`);
36
+ }
37
+ }
38
+ });
39
+ if (errors.length > 0) throw new Error(`Schema validation failed:\n${errors.join("\n")}`);
40
+ }
41
+
42
+ //#endregion
43
+ export { validateSchemaComponents };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pixpilot/formily-shadcn",
3
3
  "type": "module",
4
- "version": "0.9.1",
4
+ "version": "0.11.0",
5
5
  "description": "Formily integration for shadcn/ui components",
6
6
  "author": "m.doaie <m.doaie@hotmail.com>",
7
7
  "license": "MIT",
@@ -35,6 +35,7 @@
35
35
  "@iconify-json/fa": "^1.2.2",
36
36
  "@iconify-json/mdi": "^1.2.3",
37
37
  "@iconify/react": "^6.0.2",
38
+ "@pixpilot/env": "^0.2.1",
38
39
  "@pixpilot/string": "^2.3.0",
39
40
  "json-schema-traverse": "^1.0.0",
40
41
  "lucide-react": "^0.554.0",
@@ -53,10 +54,10 @@
53
54
  "react-dom": "19.2.0",
54
55
  "tsdown": "^0.15.12",
55
56
  "typescript": "^5.9.3",
56
- "@internal/eslint-config": "0.3.0",
57
57
  "@internal/prettier-config": "0.0.1",
58
- "@internal/tsconfig": "0.1.0",
58
+ "@internal/eslint-config": "0.3.0",
59
59
  "@internal/tsdown-config": "0.1.0",
60
+ "@internal/tsconfig": "0.1.0",
60
61
  "@internal/vitest-config": "0.1.0"
61
62
  },
62
63
  "prettier": "@internal/prettier-config",
@@ -1,118 +0,0 @@
1
- const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
- const require_use_form_context = require('../hooks/use-form-context.cjs');
3
- const require_use_label = require('../hooks/use-label.cjs');
4
- require('../hooks/index.cjs');
5
- let __formily_react = require("@formily/react");
6
- __formily_react = require_rolldown_runtime.__toESM(__formily_react);
7
- let react = require("react");
8
- react = require_rolldown_runtime.__toESM(react);
9
- let react_jsx_runtime = require("react/jsx-runtime");
10
- react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
11
- let __pixpilot_shadcn = require("@pixpilot/shadcn");
12
- __pixpilot_shadcn = require_rolldown_runtime.__toESM(__pixpilot_shadcn);
13
- let __formily_core = require("@formily/core");
14
- __formily_core = require_rolldown_runtime.__toESM(__formily_core);
15
-
16
- //#region src/components/form-item.tsx
17
- const BaseFormItem = ({ className, children, label, description, asterisk, feedbackStatus, feedbackText, labelPlacement = "top",...props }) => {
18
- const field = (0, __formily_react.useField)();
19
- const fieldProps = field?.componentProps ?? {};
20
- const effectiveLabel = require_use_label.useLabel(label);
21
- const { itemProps } = require_use_form_context.useFormContext();
22
- const { className: itemPropsClassName } = itemProps || {};
23
- const effectiveLabelPlacement = fieldProps.labelPlacement ?? labelPlacement;
24
- const id = field?.componentProps?.id ?? `form-${field?.address?.toString()?.replace(/\./gu, "-")}`;
25
- const descriptionId = react.default.useId();
26
- const feedbackId = react.default.useId();
27
- const ariaDescribedBy = [description != null ? descriptionId : void 0, feedbackText != null ? feedbackId : void 0].filter(Boolean).join(" ");
28
- const labelElement = effectiveLabel != null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
29
- htmlFor: id,
30
- "data-slot": "form-label",
31
- "data-error": Boolean(feedbackStatus === "error"),
32
- className: (0, __pixpilot_shadcn.cn)("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", feedbackStatus === "error" && "text-destructive", (effectiveLabelPlacement === "end" || effectiveLabelPlacement === "start") && "shrink-0"),
33
- children: [effectiveLabel, asterisk && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
34
- className: "text-destructive ml-1",
35
- "aria-label": "required",
36
- children: "*"
37
- })]
38
- });
39
- const inputElement = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
40
- className: "relative",
41
- children: react.default.isValidElement(children) ? react.default.cloneElement(children, {
42
- id,
43
- "aria-describedby": ariaDescribedBy || void 0,
44
- "aria-invalid": feedbackStatus === "error" ? "true" : void 0
45
- }) : children
46
- });
47
- const contentElement = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
48
- effectiveLabelPlacement === "top" && labelElement,
49
- description != null && effectiveLabelPlacement === "top" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
50
- id: descriptionId,
51
- className: "text-muted-foreground text-[0.8rem]",
52
- children: description
53
- }),
54
- (effectiveLabelPlacement === "start" || effectiveLabelPlacement === "end") && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
55
- className: (0, __pixpilot_shadcn.cn)("flex items-center gap-2", effectiveLabelPlacement === "start" && "flex-row"),
56
- children: [
57
- effectiveLabelPlacement === "start" && labelElement,
58
- inputElement,
59
- effectiveLabelPlacement === "end" && labelElement
60
- ]
61
- }),
62
- effectiveLabelPlacement === "top" && inputElement,
63
- description != null && (effectiveLabelPlacement === "start" || effectiveLabelPlacement === "end") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
64
- id: descriptionId,
65
- className: "text-muted-foreground text-[0.8rem]",
66
- children: description
67
- })
68
- ] });
69
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
70
- "data-slot": "form-item",
71
- className: (0, __pixpilot_shadcn.cn)("flex flex-col gap-2", itemPropsClassName, className),
72
- ...props,
73
- children: [contentElement, Boolean(feedbackText) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
74
- id: feedbackId,
75
- className: (0, __pixpilot_shadcn.cn)("text-[0.8rem]", feedbackStatus === "error" && "text-destructive font-medium", feedbackStatus === "warning" && "text-amber-600", feedbackStatus === "success" && "text-green-600"),
76
- children: typeof feedbackText === "string" ? feedbackText.split("\n").map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.default.Fragment, { children: [line, index < feedbackText.split("\n").length - 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {})] }, index)) : feedbackText
77
- })]
78
- });
79
- };
80
- /**
81
- * FormItem component connected to Formily field state
82
- * Automatically maps field validation state to component props
83
- */
84
- const FormItem = (0, __formily_react.connect)(BaseFormItem, (0, __formily_react.mapProps)((props, field) => {
85
- if ((0, __formily_core.isVoidField)(field)) return {
86
- label: field.title ?? props.label,
87
- description: props.description ?? field.description,
88
- asterisk: props.asterisk
89
- };
90
- const takeFeedbackStatus = () => {
91
- if (field.validating) return void 0;
92
- if (field.selfErrors?.length) return "error";
93
- if (field.selfWarnings?.length) return "warning";
94
- if (field.selfSuccesses?.length) return "success";
95
- };
96
- const takeFeedbackText = () => {
97
- if (field.validating) return void 0;
98
- if (props.feedbackText != null) return props.feedbackText;
99
- if (field.selfErrors?.length) return field.selfErrors.join(", ");
100
- if (field.selfWarnings?.length) return field.selfWarnings.join(", ");
101
- if (field.selfSuccesses?.length) return field.selfSuccesses.join(", ");
102
- };
103
- const takeAsterisk = () => {
104
- if (field.required && field.pattern !== "readPretty") return true;
105
- if ("asterisk" in props) return Boolean(props.asterisk);
106
- return false;
107
- };
108
- return {
109
- label: props.label ?? field.title,
110
- description: props.description ?? field.description,
111
- feedbackStatus: takeFeedbackStatus(),
112
- feedbackText: takeFeedbackText(),
113
- asterisk: takeAsterisk()
114
- };
115
- }));
116
-
117
- //#endregion
118
- exports.FormItem = FormItem;
@@ -1,22 +0,0 @@
1
- import { SyncReactNode } from "../types/react.cjs";
2
- import React from "react";
3
-
4
- //#region src/components/form-item.d.ts
5
- type LabelPlacement = 'top' | 'bottom' | 'start' | 'end';
6
- interface FormItemProps extends React.ComponentProps<'div'> {
7
- label?: SyncReactNode;
8
- description?: SyncReactNode;
9
- asterisk?: boolean;
10
- feedbackStatus?: 'error' | 'warning' | 'success';
11
- feedbackText?: SyncReactNode;
12
- labelPlacement?: LabelPlacement;
13
- }
14
- /**
15
- * FormItem component connected to Formily field state
16
- * Automatically maps field validation state to component props
17
- */
18
- declare const FormItem: React.ForwardRefExoticComponent<Omit<Partial<FormItemProps & {
19
- children?: React.ReactNode | undefined;
20
- }>, "ref"> & React.RefAttributes<unknown>>;
21
- //#endregion
22
- export { FormItem, FormItemProps };
@@ -1,22 +0,0 @@
1
- import { SyncReactNode } from "../types/react.js";
2
- import React from "react";
3
-
4
- //#region src/components/form-item.d.ts
5
- type LabelPlacement = 'top' | 'bottom' | 'start' | 'end';
6
- interface FormItemProps extends React.ComponentProps<'div'> {
7
- label?: SyncReactNode;
8
- description?: SyncReactNode;
9
- asterisk?: boolean;
10
- feedbackStatus?: 'error' | 'warning' | 'success';
11
- feedbackText?: SyncReactNode;
12
- labelPlacement?: LabelPlacement;
13
- }
14
- /**
15
- * FormItem component connected to Formily field state
16
- * Automatically maps field validation state to component props
17
- */
18
- declare const FormItem: React.ForwardRefExoticComponent<Omit<Partial<FormItemProps & {
19
- children?: React.ReactNode | undefined;
20
- }>, "ref"> & React.RefAttributes<unknown>>;
21
- //#endregion
22
- export { FormItem, FormItemProps };