@wix/patterns-fields 1.81.0 → 1.83.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 (239) hide show
  1. package/dist/cjs/components/address/input/address-input.st.css.js +3 -3
  2. package/dist/cjs/components/address/input/address-input.st.css.js.map +1 -1
  3. package/dist/cjs/components/audio/actions/actions-menu/actions-menu.st.css.js +3 -3
  4. package/dist/cjs/components/audio/actions/actions-menu/actions-menu.st.css.js.map +1 -1
  5. package/dist/cjs/components/audio/audio-field/form-audio-field.st.css.js +4 -4
  6. package/dist/cjs/components/audio/audio-field/form-audio-field.st.css.js.map +1 -1
  7. package/dist/cjs/components/audio/audio-player/audio-player.st.css.js +2 -2
  8. package/dist/cjs/components/audio/audio-player/audio-player.st.css.js.map +1 -1
  9. package/dist/cjs/components/color-view/cell-color-view.st.css.js +3 -3
  10. package/dist/cjs/components/color-view/cell-color-view.st.css.js.map +1 -1
  11. package/dist/cjs/components/color-view/color-view.st.css.js +4 -4
  12. package/dist/cjs/components/color-view/color-view.st.css.js.map +1 -1
  13. package/dist/cjs/components/datetime-input/date-time-input.js +11 -6
  14. package/dist/cjs/components/datetime-input/date-time-input.js.map +1 -1
  15. package/dist/cjs/components/delete-dialog/delete-dialog.st.css.js +3 -3
  16. package/dist/cjs/components/delete-dialog/delete-dialog.st.css.js.map +1 -1
  17. package/dist/cjs/components/document/form-document-field.st.css.js +7 -7
  18. package/dist/cjs/components/document/form-document-field.st.css.js.map +1 -1
  19. package/dist/cjs/components/exclamation/exclamation.st.css.js +5 -5
  20. package/dist/cjs/components/exclamation/exclamation.st.css.js.map +1 -1
  21. package/dist/cjs/components/field-validation-settings/field-validation-settings-input.js +450 -0
  22. package/dist/cjs/components/field-validation-settings/field-validation-settings-input.js.map +1 -0
  23. package/dist/cjs/components/field-validation-settings/field-validation-settings.uni.driver.js +24 -0
  24. package/dist/cjs/components/field-validation-settings/field-validation-settings.uni.driver.js.map +1 -0
  25. package/dist/cjs/components/field-validation-settings/index.js +16 -0
  26. package/dist/cjs/components/field-validation-settings/index.js.map +1 -0
  27. package/dist/cjs/components/highlighted-text/highlighted-text.st.css.js +5 -5
  28. package/dist/cjs/components/highlighted-text/highlighted-text.st.css.js.map +1 -1
  29. package/dist/cjs/components/image/thumbnail-replace-overlay.st.css.js +3 -3
  30. package/dist/cjs/components/image/thumbnail-replace-overlay.st.css.js.map +1 -1
  31. package/dist/cjs/components/index.js +6 -0
  32. package/dist/cjs/components/index.js.map +1 -1
  33. package/dist/cjs/components/media-control/cell-media-edit-shell.st.css.js +2 -2
  34. package/dist/cjs/components/media-control/cell-media-edit-shell.st.css.js.map +1 -1
  35. package/dist/cjs/components/media-control/paste-url-button.st.css.js +4 -4
  36. package/dist/cjs/components/media-control/paste-url-button.st.css.js.map +1 -1
  37. package/dist/cjs/components/media-gallery/form-media-gallery-field.st.css.js +10 -10
  38. package/dist/cjs/components/media-gallery/form-media-gallery-field.st.css.js.map +1 -1
  39. package/dist/cjs/components/media-image/media-image.st.css.js +4 -4
  40. package/dist/cjs/components/media-image/media-image.st.css.js.map +1 -1
  41. package/dist/cjs/components/media-image/overlays/overlay.st.css.js +3 -3
  42. package/dist/cjs/components/media-image/overlays/overlay.st.css.js.map +1 -1
  43. package/dist/cjs/components/media-loader/media-loader.st.css.js +3 -3
  44. package/dist/cjs/components/media-loader/media-loader.st.css.js.map +1 -1
  45. package/dist/cjs/components/media-tag/web-media-tag/media-tag.st.css.js +2 -2
  46. package/dist/cjs/components/media-tag/web-media-tag/media-tag.st.css.js.map +1 -1
  47. package/dist/cjs/components/multi-document/cell-multi-document-edit.st.css.js +3 -3
  48. package/dist/cjs/components/multi-document/cell-multi-document-edit.st.css.js.map +1 -1
  49. package/dist/cjs/components/multi-document/multi-document-input/form-multi-document.st.css.js +5 -5
  50. package/dist/cjs/components/multi-document/multi-document-input/form-multi-document.st.css.js.map +1 -1
  51. package/dist/cjs/components/reference/cell-multi-reference-input.st.css.js +2 -2
  52. package/dist/cjs/components/reference/cell-multi-reference-input.st.css.js.map +1 -1
  53. package/dist/cjs/components/reference/cell-reference-input.st.css.js +3 -3
  54. package/dist/cjs/components/reference/cell-reference-input.st.css.js.map +1 -1
  55. package/dist/cjs/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.js +4 -4
  56. package/dist/cjs/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.js.map +1 -1
  57. package/dist/cjs/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.js +3 -3
  58. package/dist/cjs/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.js.map +1 -1
  59. package/dist/cjs/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.js +2 -2
  60. package/dist/cjs/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.js.map +1 -1
  61. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.js +3 -3
  62. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.js.map +1 -1
  63. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.js +3 -3
  64. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.js.map +1 -1
  65. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/toggle-fullscreen-button/toggle-fullscreen-button.st.css.js +2 -2
  66. package/dist/cjs/components/rich-content/rich-content-input/rich-content-common/toggle-fullscreen-button/toggle-fullscreen-button.st.css.js.map +1 -1
  67. package/dist/cjs/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.js +7 -7
  68. package/dist/cjs/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.js.map +1 -1
  69. package/dist/cjs/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.js +5 -5
  70. package/dist/cjs/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.js.map +1 -1
  71. package/dist/cjs/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.js +4 -4
  72. package/dist/cjs/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.js.map +1 -1
  73. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.js +18 -18
  74. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.js.map +1 -1
  75. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.js +4 -4
  76. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.js.map +1 -1
  77. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.js +18 -18
  78. package/dist/cjs/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.js.map +1 -1
  79. package/dist/cjs/components/text/text-view.st.css.js +3 -3
  80. package/dist/cjs/components/text/text-view.st.css.js.map +1 -1
  81. package/dist/cjs/exports/unidriver.js +3 -1
  82. package/dist/cjs/exports/unidriver.js.map +1 -1
  83. package/dist/cjs/exports/validations.js +7 -0
  84. package/dist/cjs/exports/validations.js.map +1 -1
  85. package/dist/cjs/styles.global.css +1 -1
  86. package/dist/cjs/types/validation.js.map +1 -1
  87. package/dist/cjs/validations/field-validation-settings.js +110 -0
  88. package/dist/cjs/validations/field-validation-settings.js.map +1 -0
  89. package/dist/cjs/validations/field-validation-settings.spec.js +209 -0
  90. package/dist/cjs/validations/field-validation-settings.spec.js.map +1 -0
  91. package/dist/esm/components/address/input/address-input.st.css.js +2 -2
  92. package/dist/esm/components/audio/actions/actions-menu/actions-menu.st.css.js +2 -2
  93. package/dist/esm/components/audio/audio-field/form-audio-field.st.css.js +2 -2
  94. package/dist/esm/components/audio/audio-field/form-audio-field.st.css.js.map +1 -1
  95. package/dist/esm/components/audio/audio-player/audio-player.st.css.js +2 -2
  96. package/dist/esm/components/color-view/cell-color-view.st.css.js +2 -2
  97. package/dist/esm/components/color-view/color-view.st.css.js +2 -2
  98. package/dist/esm/components/color-view/color-view.st.css.js.map +1 -1
  99. package/dist/esm/components/datetime-input/date-time-input.js +6 -1
  100. package/dist/esm/components/datetime-input/date-time-input.js.map +1 -1
  101. package/dist/esm/components/delete-dialog/delete-dialog.st.css.js +2 -2
  102. package/dist/esm/components/document/form-document-field.st.css.js +2 -2
  103. package/dist/esm/components/exclamation/exclamation.st.css.js +2 -2
  104. package/dist/esm/components/exclamation/exclamation.st.css.js.map +1 -1
  105. package/dist/esm/components/field-validation-settings/field-validation-settings-input.js +121 -0
  106. package/dist/esm/components/field-validation-settings/field-validation-settings-input.js.map +1 -0
  107. package/dist/esm/components/field-validation-settings/field-validation-settings.uni.driver.js +20 -0
  108. package/dist/esm/components/field-validation-settings/field-validation-settings.uni.driver.js.map +1 -0
  109. package/dist/esm/components/field-validation-settings/index.js +3 -0
  110. package/dist/esm/components/field-validation-settings/index.js.map +1 -0
  111. package/dist/esm/components/highlighted-text/highlighted-text.st.css.js +3 -3
  112. package/dist/esm/components/highlighted-text/highlighted-text.st.css.js.map +1 -1
  113. package/dist/esm/components/image/thumbnail-replace-overlay.st.css.js +2 -2
  114. package/dist/esm/components/image/thumbnail-replace-overlay.st.css.js.map +1 -1
  115. package/dist/esm/components/index.js +1 -0
  116. package/dist/esm/components/index.js.map +1 -1
  117. package/dist/esm/components/media-control/cell-media-edit-shell.st.css.js +2 -2
  118. package/dist/esm/components/media-control/paste-url-button.st.css.js +2 -2
  119. package/dist/esm/components/media-control/paste-url-button.st.css.js.map +1 -1
  120. package/dist/esm/components/media-gallery/form-media-gallery-field.st.css.js +2 -2
  121. package/dist/esm/components/media-image/media-image.st.css.js +3 -3
  122. package/dist/esm/components/media-image/overlays/overlay.st.css.js +2 -2
  123. package/dist/esm/components/media-image/overlays/overlay.st.css.js.map +1 -1
  124. package/dist/esm/components/media-loader/media-loader.st.css.js +2 -2
  125. package/dist/esm/components/media-tag/web-media-tag/media-tag.st.css.js +2 -2
  126. package/dist/esm/components/multi-document/cell-multi-document-edit.st.css.js +2 -2
  127. package/dist/esm/components/multi-document/cell-multi-document-edit.st.css.js.map +1 -1
  128. package/dist/esm/components/multi-document/multi-document-input/form-multi-document.st.css.js +2 -2
  129. package/dist/esm/components/reference/cell-multi-reference-input.st.css.js +2 -2
  130. package/dist/esm/components/reference/cell-reference-input.st.css.js +2 -2
  131. package/dist/esm/components/reference/cell-reference-input.st.css.js.map +1 -1
  132. package/dist/esm/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.js +2 -2
  133. package/dist/esm/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.js +2 -2
  134. package/dist/esm/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.js.map +1 -1
  135. package/dist/esm/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.js +2 -2
  136. package/dist/esm/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.js +2 -2
  137. package/dist/esm/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.js +2 -2
  138. package/dist/esm/components/rich-content/rich-content-input/rich-content-common/toggle-fullscreen-button/toggle-fullscreen-button.st.css.js +2 -2
  139. package/dist/esm/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.js +2 -2
  140. package/dist/esm/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.js +2 -2
  141. package/dist/esm/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.js +2 -2
  142. package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.js +2 -2
  143. package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.js.map +1 -1
  144. package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.js +2 -2
  145. package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.js.map +1 -1
  146. package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.js +2 -2
  147. package/dist/esm/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.js.map +1 -1
  148. package/dist/esm/components/text/text-view.st.css.js +2 -2
  149. package/dist/esm/exports/unidriver.js +1 -0
  150. package/dist/esm/exports/unidriver.js.map +1 -1
  151. package/dist/esm/exports/validations.js +1 -0
  152. package/dist/esm/exports/validations.js.map +1 -1
  153. package/dist/esm/styles.global.css +1 -1
  154. package/dist/esm/validations/field-validation-settings.js +98 -0
  155. package/dist/esm/validations/field-validation-settings.js.map +1 -0
  156. package/dist/esm/validations/field-validation-settings.spec.js +132 -0
  157. package/dist/esm/validations/field-validation-settings.spec.js.map +1 -0
  158. package/dist/types/components/audio/audio-field/form-audio-field.st.css.d.ts.map +1 -1
  159. package/dist/types/components/color-view/color-view.st.css.d.ts.map +1 -1
  160. package/dist/types/components/datetime-input/date-time-input.d.ts.map +1 -1
  161. package/dist/types/components/exclamation/exclamation.st.css.d.ts.map +1 -1
  162. package/dist/types/components/field-validation-settings/field-validation-settings-input.d.ts +8 -0
  163. package/dist/types/components/field-validation-settings/field-validation-settings-input.d.ts.map +1 -0
  164. package/dist/types/components/field-validation-settings/field-validation-settings.uni.driver.d.ts +307 -0
  165. package/dist/types/components/field-validation-settings/field-validation-settings.uni.driver.d.ts.map +1 -0
  166. package/dist/types/components/field-validation-settings/index.d.ts +3 -0
  167. package/dist/types/components/field-validation-settings/index.d.ts.map +1 -0
  168. package/dist/types/components/highlighted-text/highlighted-text.st.css.d.ts.map +1 -1
  169. package/dist/types/components/image/thumbnail-replace-overlay.st.css.d.ts.map +1 -1
  170. package/dist/types/components/index.d.ts +1 -0
  171. package/dist/types/components/index.d.ts.map +1 -1
  172. package/dist/types/components/media-control/paste-url-button.st.css.d.ts.map +1 -1
  173. package/dist/types/components/media-image/overlays/overlay.st.css.d.ts.map +1 -1
  174. package/dist/types/components/multi-document/cell-multi-document-edit.st.css.d.ts.map +1 -1
  175. package/dist/types/components/reference/cell-reference-input.st.css.d.ts.map +1 -1
  176. package/dist/types/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.d.ts.map +1 -1
  177. package/dist/types/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.d.ts.map +1 -1
  178. package/dist/types/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.d.ts.map +1 -1
  179. package/dist/types/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.d.ts.map +1 -1
  180. package/dist/types/exports/unidriver.d.ts +1 -0
  181. package/dist/types/exports/unidriver.d.ts.map +1 -1
  182. package/dist/types/exports/validations.d.ts +1 -0
  183. package/dist/types/exports/validations.d.ts.map +1 -1
  184. package/dist/types/types/validation.d.ts +67 -1
  185. package/dist/types/types/validation.d.ts.map +1 -1
  186. package/dist/types/validations/field-validation-settings.d.ts +10 -0
  187. package/dist/types/validations/field-validation-settings.d.ts.map +1 -0
  188. package/dist/types/validations/field-validation-settings.spec.d.ts +2 -0
  189. package/dist/types/validations/field-validation-settings.spec.d.ts.map +1 -0
  190. package/package.json +6 -6
  191. package/src/__tests__/components/datetime-input/date-time-input.spec.tsx +99 -0
  192. package/src/__tests__/components/field-validation-settings/field-validation-settings-input.spec.tsx +366 -0
  193. package/src/__tests__/exports/field-validation-settings.spec.ts +27 -0
  194. package/src/components/address/input/address-input.st.css.ts +2 -2
  195. package/src/components/audio/actions/actions-menu/actions-menu.st.css.ts +2 -2
  196. package/src/components/audio/audio-field/form-audio-field.st.css.ts +2 -2
  197. package/src/components/audio/audio-player/audio-player.st.css.ts +2 -2
  198. package/src/components/color-view/cell-color-view.st.css.ts +2 -2
  199. package/src/components/color-view/color-view.st.css.ts +2 -2
  200. package/src/components/datetime-input/date-time-input.tsx +8 -1
  201. package/src/components/delete-dialog/delete-dialog.st.css.ts +2 -2
  202. package/src/components/document/form-document-field.st.css.ts +2 -2
  203. package/src/components/exclamation/exclamation.st.css.ts +2 -2
  204. package/src/components/field-validation-settings/field-validation-settings-input.tsx +384 -0
  205. package/src/components/field-validation-settings/field-validation-settings.uni.driver.ts +60 -0
  206. package/src/components/field-validation-settings/index.ts +2 -0
  207. package/src/components/highlighted-text/highlighted-text.st.css.ts +3 -3
  208. package/src/components/image/thumbnail-replace-overlay.st.css.ts +2 -2
  209. package/src/components/index.ts +1 -0
  210. package/src/components/media-control/cell-media-edit-shell.st.css.ts +2 -2
  211. package/src/components/media-control/paste-url-button.st.css.ts +2 -2
  212. package/src/components/media-gallery/form-media-gallery-field.st.css.ts +2 -2
  213. package/src/components/media-image/media-image.st.css.ts +3 -3
  214. package/src/components/media-image/overlays/overlay.st.css.ts +2 -2
  215. package/src/components/media-loader/media-loader.st.css.ts +2 -2
  216. package/src/components/media-tag/web-media-tag/media-tag.st.css.ts +2 -2
  217. package/src/components/multi-document/cell-multi-document-edit.st.css.ts +2 -2
  218. package/src/components/multi-document/multi-document-input/form-multi-document.st.css.ts +2 -2
  219. package/src/components/reference/cell-multi-reference-input.st.css.ts +2 -2
  220. package/src/components/reference/cell-reference-input.st.css.ts +2 -2
  221. package/src/components/rich-content/rich-content-input/default-value-input/rich-content-default-value-input.st.css.ts +2 -2
  222. package/src/components/rich-content/rich-content-input/form-input/rich-content-form-input.st.css.ts +2 -2
  223. package/src/components/rich-content/rich-content-input/form-read-only-input/rich-content-form-read-only-input.st.css.ts +2 -2
  224. package/src/components/rich-content/rich-content-input/rich-content-common/fullscreen-modal/fullscreen-modal.st.css.ts +2 -2
  225. package/src/components/rich-content/rich-content-input/rich-content-common/publish-loader/publish-loader.st.css.ts +2 -2
  226. package/src/components/rich-content/rich-content-input/rich-content-common/toggle-fullscreen-button/toggle-fullscreen-button.st.css.ts +2 -2
  227. package/src/components/rich-content/rich-content-input/rich-content-editor/rich-content-editor.st.css.ts +2 -2
  228. package/src/components/rich-content/rich-content-input/rich-content-editor/rich-content-toolbar.st.css.ts +2 -2
  229. package/src/components/rich-content/rich-content-input/rich-content-viewer/rich-content-viewer.st.css.ts +2 -2
  230. package/src/components/rich-text/rich-text-input/rich-text-editor/rich-editor.st.css.ts +2 -2
  231. package/src/components/rich-text/rich-text-input/rich-text-editor/rich-text-editor.st.css.ts +2 -2
  232. package/src/components/rich-text/rich-text-input/rich-text-editor/toolbar/toolbar.st.css.ts +2 -2
  233. package/src/components/text/text-view.st.css.ts +2 -2
  234. package/src/exports/unidriver.ts +1 -0
  235. package/src/exports/validations.ts +2 -0
  236. package/src/styles.global.css +1 -1
  237. package/src/types/validation.ts +77 -1
  238. package/src/validations/field-validation-settings.spec.ts +180 -0
  239. package/src/validations/field-validation-settings.ts +144 -0
@@ -11,5 +11,71 @@ export type CharactersLimitValidationRule = {
11
11
  export type SpecificValuesValidationRule = {
12
12
  specificValues: SpecificValue[];
13
13
  };
14
- export type DataValidationRules = Partial<RequiredValidationRule & CharactersLimitValidationRule & SpecificValuesValidationRule>;
14
+ export type PatternValidationRule = {
15
+ pattern: string;
16
+ };
17
+ export interface RequiredFieldValidationRuleConfig {
18
+ type: 'required';
19
+ label: string;
20
+ tooltip: string;
21
+ }
22
+ export interface CharactersLimitFieldValidationRuleConfig {
23
+ type: 'charactersLimit';
24
+ label: string;
25
+ tooltip: string;
26
+ minLabel: string;
27
+ maxLabel: string;
28
+ separator: string;
29
+ outOfBoundsError(min: number, max: number): string;
30
+ maxBelowMinError: string;
31
+ }
32
+ export interface SpecificValuesFieldValidationRuleConfig {
33
+ type: 'specificValues';
34
+ label: string;
35
+ tooltip: string;
36
+ blankError: string;
37
+ duplicateError: string;
38
+ addButton: string;
39
+ removeButton: string;
40
+ exclusiveRulesExplanation: string;
41
+ }
42
+ export interface PatternFieldValidationRuleConfig {
43
+ type: 'pattern';
44
+ label: string;
45
+ tooltip: string;
46
+ inputLabel: string;
47
+ invalidError: string;
48
+ }
49
+ export type FieldValidationRuleConfig = RequiredFieldValidationRuleConfig | CharactersLimitFieldValidationRuleConfig | SpecificValuesFieldValidationRuleConfig | PatternFieldValidationRuleConfig;
50
+ export type FieldValidationRule = FieldValidationRuleConfig['type'];
51
+ export interface FieldValidationSettingsValue {
52
+ required?: boolean;
53
+ charactersLimit?: {
54
+ min?: number;
55
+ max?: number;
56
+ };
57
+ specificValues?: SpecificValue[];
58
+ pattern?: string;
59
+ }
60
+ export type FieldValidationViolation = {
61
+ rule: 'charactersLimit';
62
+ type: 'outOfBounds';
63
+ bound: 'min' | 'max';
64
+ min: number;
65
+ max: number;
66
+ } | {
67
+ rule: 'charactersLimit';
68
+ type: 'maxBelowMin';
69
+ } | {
70
+ rule: 'specificValues';
71
+ type: 'blank' | 'duplicate';
72
+ optionId: string;
73
+ } | {
74
+ rule: 'specificValues' | 'charactersLimit' | 'pattern';
75
+ type: 'exclusiveRules';
76
+ } | {
77
+ rule: 'pattern';
78
+ type: 'invalidPattern';
79
+ };
80
+ export type DataValidationRules = Partial<RequiredValidationRule & CharactersLimitValidationRule & SpecificValuesValidationRule & PatternValidationRule>;
15
81
  //# sourceMappingURL=validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/types/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,eAAe,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,cAAc,EAAE,aAAa,EAAE,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,OAAO,CACvC,sBAAsB,GACpB,6BAA6B,GAC7B,4BAA4B,CAC/B,CAAC"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/types/validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { FieldValidationRule, FieldValidationSettingsValue, FieldValidationViolation } from '../types/validation';
2
+ export interface FieldValidationSettingsOptions {
3
+ /** Whether `specificValues` rejects `charactersLimit`/`pattern` on the same
4
+ * field. Callers that let a field carry both (e.g. a stored
5
+ * `stringLengthRange` alongside `specificValues`) should pass `false`. */
6
+ exclusiveSpecificValues?: boolean;
7
+ }
8
+ export declare const getFieldValidationSettingsViolations: (value: FieldValidationSettingsValue, supportedRules?: readonly FieldValidationRule[], { exclusiveSpecificValues }?: FieldValidationSettingsOptions) => FieldValidationViolation[];
9
+ export declare const hasFieldValidationSettingsError: (value: FieldValidationSettingsValue, supportedRules?: readonly FieldValidationRule[], options?: FieldValidationSettingsOptions) => boolean;
10
+ //# sourceMappingURL=field-validation-settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-validation-settings.d.ts","sourceRoot":"","sources":["../../../src/validations/field-validation-settings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,4BAA4B,EAC5B,wBAAwB,EACzB,MAAM,qBAAqB,CAAC;AA4B7B,MAAM,WAAW,8BAA8B;IAC7C;;+EAE2E;IAC3E,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,eAAO,MAAM,oCAAoC,GAC/C,OAAO,4BAA4B,EACnC,iBAAiB,SAAS,mBAAmB,EAAE,EAC/C,8BAAoC,8BAAmC,KACtE,wBAAwB,EA4F1B,CAAC;AAEF,eAAO,MAAM,+BAA+B,GAC1C,OAAO,4BAA4B,EACnC,iBAAiB,SAAS,mBAAmB,EAAE,EAC/C,UAAU,8BAA8B,YAGvC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=field-validation-settings.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-validation-settings.spec.d.ts","sourceRoot":"","sources":["../../../src/validations/field-validation-settings.spec.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/patterns-fields",
3
- "version": "1.81.0",
3
+ "version": "1.83.0",
4
4
  "license": "UNLICENSED",
5
5
  "author": {
6
6
  "name": "Kobi",
@@ -124,7 +124,7 @@
124
124
  "@wix/atlas": "^1.0.35",
125
125
  "@wix/data": "^1.0.323",
126
126
  "@wix/media": "^1.0.231",
127
- "@wix/patterns-fields-utils": "1.62.0",
127
+ "@wix/patterns-fields-utils": "1.64.0",
128
128
  "@wix/rich-content": "1.0.37",
129
129
  "@wix/sdk": "^1.17.2",
130
130
  "@wix/wix-ui-icons-common": "^3.189.0",
@@ -152,8 +152,8 @@
152
152
  "@types/lodash": "^4.17.20",
153
153
  "@types/react": "^16.14.68",
154
154
  "@wix/babel-cli": "^1.11.0",
155
- "@wix/bex-core": "2.359.0",
156
- "@wix/design-system": "^1.314.0",
155
+ "@wix/bex-core": "2.361.0",
156
+ "@wix/design-system": "^1.319.0",
157
157
  "@wix/eslint-config-yoshi": "^6.74.0",
158
158
  "@wix/jest-yoshi-preset": "^6.74.0",
159
159
  "@wix/wix-data-items-common": "^1.0.270",
@@ -168,7 +168,7 @@
168
168
  },
169
169
  "peerDependencies": {
170
170
  "@wix/bex-core": "^2.284.0",
171
- "@wix/design-system": "^1.314.0",
171
+ "@wix/design-system": "^1.319.0",
172
172
  "mobx": "^6.1.8",
173
173
  "react": "^16.8.0 || ^18.0.0",
174
174
  "react-dom": "^16.8.0 || ^18.0.0"
@@ -212,5 +212,5 @@
212
212
  "optional": true
213
213
  }
214
214
  },
215
- "falconPackageHash": "7f3ac142c92989cd0bc2506f1510478c1b2edc0c549e190447a20f49"
215
+ "falconPackageHash": "7c94817351adcc8e6c284b0541c9e5f48d7e507e54b6247373bee947"
216
216
  }
@@ -0,0 +1,99 @@
1
+ import '../../../testkit/test-polyfills';
2
+
3
+ import React from 'react';
4
+ import { fireEvent, render } from '@testing-library/react';
5
+
6
+ import { ControlledDateTimeInput } from '../../../components/datetime-input/date-time-input';
7
+ import { PatternsFieldsTestProvider } from '../../../testkit/patterns-fields-test-provider';
8
+
9
+ const DATA_HOOK = 'date-time';
10
+
11
+ const renderInput = (onBlur: () => void) =>
12
+ render(
13
+ <ControlledDateTimeInput
14
+ data={null}
15
+ onChange={jest.fn()}
16
+ onBlur={onBlur}
17
+ dataHook={DATA_HOOK}
18
+ />,
19
+ { wrapper: PatternsFieldsTestProvider },
20
+ );
21
+
22
+ const blurTo = (relatedTarget: Node | null) => {
23
+ const wrapper = document.querySelector(`[data-hook="${DATA_HOOK}"]`)!;
24
+ fireEvent.blur(wrapper, { relatedTarget });
25
+ };
26
+
27
+ describe('ControlledDateTimeInput blur handling', () => {
28
+ it('does not call onBlur when focus moves into the calendar popover', () => {
29
+ const onBlur = jest.fn();
30
+ renderInput(onBlur);
31
+
32
+ const calendar = document.createElement('div');
33
+ calendar.setAttribute('data-hook', 'date-picker-calendar-date-time-date');
34
+ document.body.append(calendar);
35
+
36
+ blurTo(calendar);
37
+
38
+ expect(onBlur).not.toHaveBeenCalled();
39
+ });
40
+
41
+ it('does not call onBlur when focus moves into the mobile drawer fallback', () => {
42
+ const onBlur = jest.fn();
43
+ renderInput(onBlur);
44
+
45
+ const drawer = document.createElement('div');
46
+ drawer.setAttribute('role', 'dialog');
47
+ document.body.append(drawer);
48
+
49
+ blurTo(drawer);
50
+
51
+ expect(onBlur).not.toHaveBeenCalled();
52
+ });
53
+
54
+ it('does not call onBlur when focus moves into the time dropdown', () => {
55
+ const onBlur = jest.fn();
56
+ renderInput(onBlur);
57
+
58
+ const dropdown = document.createElement('div');
59
+ dropdown.setAttribute('data-hook', 'TimeInput-dropdown');
60
+ const option = document.createElement('div');
61
+ dropdown.append(option);
62
+ document.body.append(dropdown);
63
+
64
+ blurTo(option);
65
+
66
+ expect(onBlur).not.toHaveBeenCalled();
67
+ });
68
+
69
+ it('calls onBlur when focus leaves to an unrelated element', () => {
70
+ const onBlur = jest.fn();
71
+ renderInput(onBlur);
72
+
73
+ const outside = document.createElement('button');
74
+ document.body.append(outside);
75
+
76
+ blurTo(outside);
77
+
78
+ expect(onBlur).toHaveBeenCalledTimes(1);
79
+ });
80
+
81
+ it('calls onBlur when focus leaves the document entirely', () => {
82
+ const onBlur = jest.fn();
83
+ renderInput(onBlur);
84
+
85
+ blurTo(null);
86
+
87
+ expect(onBlur).toHaveBeenCalledTimes(1);
88
+ });
89
+
90
+ it('does not call onBlur when focus moves between the date and time inputs', () => {
91
+ const onBlur = jest.fn();
92
+ renderInput(onBlur);
93
+
94
+ const timeInput = document.querySelector('[data-hook="date-time-time"] input')!;
95
+ blurTo(timeInput);
96
+
97
+ expect(onBlur).not.toHaveBeenCalled();
98
+ });
99
+ });
@@ -0,0 +1,366 @@
1
+ import '../../../testkit/test-polyfills';
2
+
3
+ import React, { useState } from 'react';
4
+ import { render } from '@testing-library/react';
5
+ import { uniTestkitFactoryCreator } from '@wix/wix-ui-test-utils/testing-library';
6
+ import { FieldValidationSettingsInput } from '../../../components/field-validation-settings';
7
+ import { FieldValidationSettingsUniDriver } from '../../../components/field-validation-settings/field-validation-settings.uni.driver';
8
+ import { PatternsFieldsTestProvider } from '../../../testkit/patterns-fields-test-provider';
9
+ import type {
10
+ FieldValidationRuleConfig,
11
+ FieldValidationSettingsValue,
12
+ } from '../../../types/validation';
13
+
14
+ const testkitFactory = uniTestkitFactoryCreator(
15
+ FieldValidationSettingsUniDriver,
16
+ );
17
+
18
+ const requiredRule: FieldValidationRuleConfig = {
19
+ type: 'required',
20
+ label: 'Required',
21
+ tooltip: 'Required tooltip',
22
+ };
23
+
24
+ const charactersLimitRule: FieldValidationRuleConfig = {
25
+ type: 'charactersLimit',
26
+ label: 'Character limit',
27
+ tooltip: 'Character limit tooltip',
28
+ minLabel: 'Minimum',
29
+ maxLabel: 'Maximum',
30
+ separator: 'and',
31
+ outOfBoundsError: (min, max) => `Enter a value from ${min} to ${max}.`,
32
+ maxBelowMinError: 'Maximum must not be below minimum.',
33
+ };
34
+
35
+ const specificValuesRule: FieldValidationRuleConfig = {
36
+ type: 'specificValues',
37
+ label: 'Specific values',
38
+ tooltip: 'Specific values tooltip',
39
+ blankError: 'Enter a value.',
40
+ duplicateError: 'Values must be unique.',
41
+ addButton: 'Add value',
42
+ removeButton: 'Remove value',
43
+ exclusiveRulesExplanation: 'Disable the active rule first.',
44
+ };
45
+
46
+ const patternRule: FieldValidationRuleConfig = {
47
+ type: 'pattern',
48
+ label: 'Pattern',
49
+ tooltip: 'Pattern tooltip',
50
+ inputLabel: 'Regular expression',
51
+ invalidError: 'Enter a valid regular expression.',
52
+ };
53
+
54
+ const allRules = [
55
+ requiredRule,
56
+ charactersLimitRule,
57
+ specificValuesRule,
58
+ patternRule,
59
+ ];
60
+
61
+ const ruleCombinations = Array.from(
62
+ { length: 2 ** allRules.length },
63
+ (_entry, mask) => allRules.filter((_rule, index) => mask & (1 << index)),
64
+ );
65
+
66
+ interface RenderInputOptions {
67
+ rules?: readonly FieldValidationRuleConfig[];
68
+ readOnly?: boolean;
69
+ invalid?: boolean;
70
+ }
71
+
72
+ const renderInput = (
73
+ initialData: FieldValidationSettingsValue,
74
+ { rules = allRules, readOnly, invalid }: RenderInputOptions = {},
75
+ ) => {
76
+ const onChange = jest.fn<void, [FieldValidationSettingsValue]>();
77
+
78
+ const TestInput = () => {
79
+ const [data, setData] = useState(initialData);
80
+ return (
81
+ <FieldValidationSettingsInput
82
+ dataHook="validation"
83
+ data={data}
84
+ rules={rules}
85
+ readOnly={readOnly}
86
+ invalid={invalid}
87
+ onChange={(nextData) => {
88
+ onChange(nextData);
89
+ setData(nextData);
90
+ }}
91
+ />
92
+ );
93
+ };
94
+
95
+ const result = render(<TestInput />, { wrapper: PatternsFieldsTestProvider });
96
+
97
+ return {
98
+ ...result,
99
+ driver: testkitFactory({
100
+ wrapper: result.container,
101
+ dataHook: 'validation',
102
+ }),
103
+ onChange,
104
+ };
105
+ };
106
+
107
+ describe('FieldValidationSettingsInput', () => {
108
+ it.each(ruleCombinations)(
109
+ 'renders exactly the configured rule combination: %j',
110
+ async (...rules) => {
111
+ const { driver } = renderInput({}, { rules });
112
+ const configuredTypes = rules.map(({ type }) => type);
113
+
114
+ expect(await driver.getRequiredToggle().exists()).toBe(
115
+ configuredTypes.includes('required'),
116
+ );
117
+ expect(await driver.getCharactersLimitToggle().exists()).toBe(
118
+ configuredTypes.includes('charactersLimit'),
119
+ );
120
+ expect(await driver.getSpecificValuesToggle().exists()).toBe(
121
+ configuredTypes.includes('specificValues'),
122
+ );
123
+ expect(await driver.getPatternToggle().exists()).toBe(
124
+ configuredTypes.includes('pattern'),
125
+ );
126
+ },
127
+ );
128
+
129
+ it('renders only configured rules in caller order', async () => {
130
+ const { container, driver } = renderInput(
131
+ {},
132
+ { rules: [patternRule, requiredRule] },
133
+ );
134
+ const text = container.textContent ?? '';
135
+
136
+ expect(text.indexOf('Pattern')).toBeLessThan(text.indexOf('Required'));
137
+ expect(await driver.getPatternToggle().exists()).toBe(true);
138
+ expect(await driver.getRequiredToggle().exists()).toBe(true);
139
+ expect(await driver.getCharactersLimitToggle().exists()).toBe(false);
140
+ expect(await driver.getSpecificValuesToggle().exists()).toBe(false);
141
+ });
142
+
143
+ it('does not explain exclusivity when no conflicting rule is configured', async () => {
144
+ const { driver } = renderInput(
145
+ { specificValues: [] },
146
+ { rules: [specificValuesRule] },
147
+ );
148
+
149
+ expect(await driver.hasExclusiveRulesExplanation()).toBe(false);
150
+ });
151
+
152
+ it('ignores hidden rule values when disabling visible rules', async () => {
153
+ const { driver } = renderInput(
154
+ { specificValues: [] },
155
+ { rules: [charactersLimitRule] },
156
+ );
157
+
158
+ expect(await driver.getCharactersLimitToggle().isDisabled()).toBe(false);
159
+ });
160
+
161
+ it('preserves a minimum of zero while required makes it invalid and valid again', async () => {
162
+ const { driver, onChange } = renderInput({
163
+ required: false,
164
+ charactersLimit: { min: 0 },
165
+ });
166
+
167
+ await driver.getRequiredToggle().click();
168
+ expect(onChange).toHaveBeenLastCalledWith({
169
+ required: true,
170
+ charactersLimit: { min: 0 },
171
+ });
172
+ expect(await driver.getMinCharactersInput().hasStatus('error')).toBe(true);
173
+ expect(await driver.getMinCharactersInput().getStatusMessage()).toBe(
174
+ 'Enter a value from 1 to 256000.',
175
+ );
176
+
177
+ await driver.getRequiredToggle().click();
178
+ expect(onChange).toHaveBeenLastCalledWith({
179
+ required: false,
180
+ charactersLimit: { min: 0 },
181
+ });
182
+ expect(await driver.getMinCharactersInput().hasStatus('error')).toBe(false);
183
+ });
184
+
185
+ it('keeps invalid character drafts and shows their specific errors', async () => {
186
+ const { driver, onChange } = renderInput({
187
+ charactersLimit: { min: -1, max: 0 },
188
+ });
189
+
190
+ expect(await driver.getMinCharactersInput().getStatusMessage()).toBe(
191
+ 'Enter a value from 0 to 256000.',
192
+ );
193
+ expect(await driver.getMaxCharactersInput().getStatusMessage()).toBe(
194
+ 'Enter a value from 1 to 256000.',
195
+ );
196
+ expect(onChange).not.toHaveBeenCalled();
197
+ });
198
+
199
+ it('shows a maximum-below-minimum error without changing the draft', async () => {
200
+ const { driver, onChange } = renderInput({
201
+ charactersLimit: { min: 20, max: 2 },
202
+ });
203
+
204
+ expect(await driver.getMaxCharactersInput().getStatusMessage()).toBe(
205
+ 'Maximum must not be below minimum.',
206
+ );
207
+ expect(onChange).not.toHaveBeenCalled();
208
+ });
209
+
210
+ it('highlights only the invalid character bound', async () => {
211
+ const { driver } = renderInput({
212
+ charactersLimit: { min: -1, max: 20 },
213
+ });
214
+
215
+ expect(await driver.getMinCharactersInput().hasStatus('error')).toBe(true);
216
+ expect(await driver.getMaxCharactersInput().hasStatus('error')).toBe(false);
217
+ });
218
+
219
+ it('enables and disables character limits without changing required', async () => {
220
+ const { driver, onChange } = renderInput({});
221
+
222
+ await driver.getCharactersLimitToggle().click();
223
+ expect(onChange).toHaveBeenLastCalledWith({ charactersLimit: {} });
224
+ await driver.getCharactersLimitToggle().click();
225
+ expect(onChange).toHaveBeenLastCalledWith({ charactersLimit: undefined });
226
+ });
227
+
228
+ it('edits both character bounds through the controlled value', async () => {
229
+ const { driver, onChange } = renderInput({ charactersLimit: {} });
230
+
231
+ await driver.getMinCharactersInput().enterText('2');
232
+ expect(onChange).toHaveBeenLastCalledWith({
233
+ charactersLimit: { min: 2 },
234
+ });
235
+
236
+ await driver.getMaxCharactersInput().enterText('20');
237
+ expect(onChange).toHaveBeenLastCalledWith({
238
+ charactersLimit: { min: 2, max: 20 },
239
+ });
240
+ });
241
+
242
+ it('adds, edits, and removes specific values without replacing their IDs', async () => {
243
+ const { driver, onChange } = renderInput({ specificValues: [] });
244
+
245
+ await driver.getAddSpecificValueButton().click();
246
+ const added = onChange.mock.calls[0][0];
247
+ expect(added.specificValues?.[0]).toEqual({
248
+ id: expect.any(String),
249
+ value: '',
250
+ });
251
+
252
+ await driver.getSpecificValueInput(0).enterText('First');
253
+ const edited = onChange.mock.calls[1][0];
254
+ expect(edited.specificValues?.[0]).toEqual({
255
+ id: added.specificValues?.[0].id,
256
+ value: 'First',
257
+ });
258
+
259
+ await driver.getRemoveSpecificValueButton(0).click();
260
+ expect(onChange).toHaveBeenLastCalledWith({ specificValues: [] });
261
+ });
262
+
263
+ it('shows blank and duplicate specific-value errors', async () => {
264
+ const { driver } = renderInput({
265
+ specificValues: [
266
+ { id: 'blank', value: ' ' },
267
+ { id: 'first', value: 'One' },
268
+ { id: 'duplicate', value: ' One ' },
269
+ ],
270
+ });
271
+
272
+ expect(await driver.getSpecificValueInput(0).getStatusMessage()).toBe(
273
+ 'Enter a value.',
274
+ );
275
+ expect(await driver.getSpecificValueInput(2).getStatusMessage()).toBe(
276
+ 'Values must be unique.',
277
+ );
278
+ });
279
+
280
+ it('disables only inactive rules that conflict with character limits', async () => {
281
+ const { driver } = renderInput({ charactersLimit: {} });
282
+
283
+ expect(await driver.getCharactersLimitToggle().isDisabled()).toBe(false);
284
+ expect(await driver.getSpecificValuesToggle().isDisabled()).toBe(true);
285
+ expect(await driver.getPatternToggle().isDisabled()).toBe(false);
286
+ expect(await driver.hasExclusiveRulesExplanation()).toBe(true);
287
+ });
288
+
289
+ it('disables only inactive rules that conflict with specific values', async () => {
290
+ const { driver } = renderInput({ specificValues: [] });
291
+
292
+ expect(await driver.getSpecificValuesToggle().isDisabled()).toBe(false);
293
+ expect(await driver.getCharactersLimitToggle().isDisabled()).toBe(true);
294
+ expect(await driver.getPatternToggle().isDisabled()).toBe(true);
295
+ });
296
+
297
+ it('keeps active conflicting rules enabled so loaded data can be repaired', async () => {
298
+ const { driver, onChange } = renderInput({
299
+ charactersLimit: {},
300
+ specificValues: [],
301
+ pattern: '^value$',
302
+ });
303
+
304
+ expect(await driver.getCharactersLimitToggle().isDisabled()).toBe(false);
305
+ expect(await driver.getSpecificValuesToggle().isDisabled()).toBe(false);
306
+ expect(await driver.getPatternToggle().isDisabled()).toBe(false);
307
+
308
+ await driver.getSpecificValuesToggle().click();
309
+ expect(onChange).toHaveBeenLastCalledWith({
310
+ charactersLimit: {},
311
+ specificValues: undefined,
312
+ pattern: '^value$',
313
+ });
314
+ });
315
+
316
+ it('enables, edits, validates, and disables a string pattern', async () => {
317
+ const { driver, onChange } = renderInput({});
318
+
319
+ await driver.getPatternToggle().click();
320
+ expect(onChange).toHaveBeenLastCalledWith({ pattern: '' });
321
+
322
+ await driver.getPatternInput().enterText('[');
323
+ expect(onChange).toHaveBeenLastCalledWith({ pattern: '[' });
324
+ expect(await driver.getPatternInput().getStatusMessage()).toBe(
325
+ 'Enter a valid regular expression.',
326
+ );
327
+
328
+ await driver.getPatternToggle().click();
329
+ expect(onChange).toHaveBeenLastCalledWith({ pattern: undefined });
330
+ });
331
+
332
+ it('disables every interactive control when read only', async () => {
333
+ const { driver } = renderInput(
334
+ {
335
+ required: true,
336
+ charactersLimit: { min: 2, max: 20 },
337
+ specificValues: [{ id: 'one', value: 'One' }],
338
+ pattern: '^value$',
339
+ },
340
+ { readOnly: true },
341
+ );
342
+
343
+ expect(await driver.getRequiredToggle().isDisabled()).toBe(true);
344
+ expect(await driver.getCharactersLimitToggle().isDisabled()).toBe(true);
345
+ expect(await driver.getMinCharactersInput().isDisabled()).toBe(true);
346
+ expect(await driver.getMaxCharactersInput().isDisabled()).toBe(true);
347
+ expect(await driver.getSpecificValuesToggle().isDisabled()).toBe(true);
348
+ expect(await driver.getSpecificValueInput(0).isDisabled()).toBe(true);
349
+ expect(await driver.getAddSpecificValueButton().isDisabled()).toBe(true);
350
+ expect(
351
+ await driver.getRemoveSpecificValueButton(0).isButtonDisabled(),
352
+ ).toBe(true);
353
+ expect(await driver.getPatternToggle().isDisabled()).toBe(true);
354
+ expect(await driver.getPatternInput().isDisabled()).toBe(true);
355
+ });
356
+
357
+ it('applies unattributed aggregate invalid styling without inventing an error message', async () => {
358
+ const { driver } = renderInput(
359
+ { charactersLimit: { min: 2, max: 20 } },
360
+ { rules: [charactersLimitRule], invalid: true },
361
+ );
362
+
363
+ expect(await driver.getMinCharactersInput().hasStatus('error')).toBe(true);
364
+ expect(await driver.getMaxCharactersInput().hasStatus('error')).toBe(true);
365
+ });
366
+ });
@@ -0,0 +1,27 @@
1
+ import {
2
+ FieldValidationSettingsInput,
3
+ getFieldValidationSettingsViolations,
4
+ hasFieldValidationSettingsError,
5
+ } from '../../index';
6
+ import type {
7
+ FieldValidationRuleConfig,
8
+ FieldValidationSettingsValue,
9
+ } from '../../index';
10
+ import { FieldValidationSettingsUniDriver } from '../../exports/unidriver';
11
+
12
+ describe('field validation settings public exports', () => {
13
+ it('exports the component, pure helpers, types, and UniDriver', () => {
14
+ const rules: readonly FieldValidationRuleConfig[] = [
15
+ { type: 'required', label: 'Required', tooltip: 'Required tooltip' },
16
+ ];
17
+ const value: FieldValidationSettingsValue = { required: true };
18
+
19
+ expect(FieldValidationSettingsInput).toBeDefined();
20
+ expect(FieldValidationSettingsUniDriver).toBeDefined();
21
+ expect(getFieldValidationSettingsViolations(value)).toEqual([]);
22
+ expect(hasFieldValidationSettingsError(value)).toBe(false);
23
+ expect(rules).toEqual([
24
+ { type: 'required', label: 'Required', tooltip: 'Required tooltip' },
25
+ ]);
26
+ });
27
+ });
@@ -5,7 +5,7 @@ import { classesRuntime, statesRuntime } from "../../../stylable-esm-runtime.js"
5
5
 
6
6
 
7
7
 
8
- var _namespace_ = "addressinput1467036950";
8
+ var _namespace_ = "addressinput1375149515";
9
9
  var _style_ = classesRuntime.bind(null, _namespace_);
10
10
 
11
11
  export var cssStates = statesRuntime.bind(null, _namespace_);
@@ -13,7 +13,7 @@ export var style: import("@stylable/runtime").STFunction = _style_;
13
13
  export var st: import("@stylable/runtime").STFunction = _style_;
14
14
 
15
15
  export var namespace = _namespace_;
16
- export var classes = {"root":"addressinput1467036950__root","tableAddressInput":"addressinput1467036950__tableAddressInput"};
16
+ export var classes = {"root":"addressinput1375149515__root","tableAddressInput":"addressinput1375149515__tableAddressInput"};
17
17
  export var keyframes = {};
18
18
  export var layers = {};
19
19
  export var containers = {};
@@ -5,7 +5,7 @@ import { classesRuntime, statesRuntime } from "../../../../stylable-esm-runtime.
5
5
 
6
6
 
7
7
 
8
- var _namespace_ = "actionsmenu1437673280";
8
+ var _namespace_ = "actionsmenu3707053799";
9
9
  var _style_ = classesRuntime.bind(null, _namespace_);
10
10
 
11
11
  export var cssStates = statesRuntime.bind(null, _namespace_);
@@ -13,7 +13,7 @@ export var style: import("@stylable/runtime").STFunction = _style_;
13
13
  export var st: import("@stylable/runtime").STFunction = _style_;
14
14
 
15
15
  export var namespace = _namespace_;
16
- export var classes = {"root":"actionsmenu1437673280__root","action":"actionsmenu1437673280__action"};
16
+ export var classes = {"root":"actionsmenu3707053799__root","action":"actionsmenu3707053799__action"};
17
17
  export var keyframes = {};
18
18
  export var layers = {};
19
19
  export var containers = {};