@tinya-code/gas-admin-ui 0.2.0-alpha.15 → 0.2.0-alpha.17

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 (368) hide show
  1. package/fesm2022/tinya-code-gas-admin-ui-badge-EeCA_l-o.mjs +84 -0
  2. package/fesm2022/tinya-code-gas-admin-ui-badge-EeCA_l-o.mjs.map +1 -0
  3. package/fesm2022/tinya-code-gas-admin-ui-bar-chart-G7sEMSBY.mjs +140 -0
  4. package/fesm2022/tinya-code-gas-admin-ui-bar-chart-G7sEMSBY.mjs.map +1 -0
  5. package/fesm2022/tinya-code-gas-admin-ui-boolean-B2ASKL0E.mjs +113 -0
  6. package/fesm2022/tinya-code-gas-admin-ui-boolean-B2ASKL0E.mjs.map +1 -0
  7. package/fesm2022/tinya-code-gas-admin-ui-button-BQjNW8KB.mjs +163 -0
  8. package/fesm2022/tinya-code-gas-admin-ui-button-BQjNW8KB.mjs.map +1 -0
  9. package/fesm2022/tinya-code-gas-admin-ui-calendar-view-DCY8bj2V.mjs +1027 -0
  10. package/fesm2022/tinya-code-gas-admin-ui-calendar-view-DCY8bj2V.mjs.map +1 -0
  11. package/fesm2022/tinya-code-gas-admin-ui-chart-line-BjdlKHoH.mjs +278 -0
  12. package/fesm2022/tinya-code-gas-admin-ui-chart-line-BjdlKHoH.mjs.map +1 -0
  13. package/fesm2022/tinya-code-gas-admin-ui-color-Dljh_By3.mjs +107 -0
  14. package/fesm2022/tinya-code-gas-admin-ui-color-Dljh_By3.mjs.map +1 -0
  15. package/fesm2022/tinya-code-gas-admin-ui-condition-evaluator-DY2k1M3C.mjs +101 -0
  16. package/fesm2022/tinya-code-gas-admin-ui-condition-evaluator-DY2k1M3C.mjs.map +1 -0
  17. package/fesm2022/tinya-code-gas-admin-ui-currency-BvuF3Z63.mjs +141 -0
  18. package/fesm2022/tinya-code-gas-admin-ui-currency-BvuF3Z63.mjs.map +1 -0
  19. package/fesm2022/tinya-code-gas-admin-ui-data-source.service-96FSbN72.mjs +88 -0
  20. package/fesm2022/tinya-code-gas-admin-ui-data-source.service-96FSbN72.mjs.map +1 -0
  21. package/fesm2022/tinya-code-gas-admin-ui-date-1SJGXZrd.mjs +107 -0
  22. package/fesm2022/tinya-code-gas-admin-ui-date-1SJGXZrd.mjs.map +1 -0
  23. package/fesm2022/tinya-code-gas-admin-ui-display-badge-fwk6sDU7.mjs +140 -0
  24. package/fesm2022/tinya-code-gas-admin-ui-display-badge-fwk6sDU7.mjs.map +1 -0
  25. package/fesm2022/tinya-code-gas-admin-ui-display-date-D7zLiDiG.mjs +119 -0
  26. package/fesm2022/tinya-code-gas-admin-ui-display-date-D7zLiDiG.mjs.map +1 -0
  27. package/fesm2022/tinya-code-gas-admin-ui-display-file-BiIhqvQC.mjs +125 -0
  28. package/fesm2022/tinya-code-gas-admin-ui-display-file-BiIhqvQC.mjs.map +1 -0
  29. package/fesm2022/tinya-code-gas-admin-ui-display-image-C1dhnZi1.mjs +152 -0
  30. package/fesm2022/tinya-code-gas-admin-ui-display-image-C1dhnZi1.mjs.map +1 -0
  31. package/fesm2022/tinya-code-gas-admin-ui-display-list-DOEuUbGe.mjs +211 -0
  32. package/fesm2022/tinya-code-gas-admin-ui-display-list-DOEuUbGe.mjs.map +1 -0
  33. package/fesm2022/tinya-code-gas-admin-ui-display-number-DDMzr4Hn.mjs +116 -0
  34. package/fesm2022/tinya-code-gas-admin-ui-display-number-DDMzr4Hn.mjs.map +1 -0
  35. package/fesm2022/tinya-code-gas-admin-ui-display-text-B8CdVNpv.mjs +111 -0
  36. package/fesm2022/tinya-code-gas-admin-ui-display-text-B8CdVNpv.mjs.map +1 -0
  37. package/fesm2022/tinya-code-gas-admin-ui-dropdown-C3blvmE1.mjs +122 -0
  38. package/fesm2022/tinya-code-gas-admin-ui-dropdown-C3blvmE1.mjs.map +1 -0
  39. package/fesm2022/tinya-code-gas-admin-ui-email-CT_O5ihA.mjs +107 -0
  40. package/fesm2022/tinya-code-gas-admin-ui-email-CT_O5ihA.mjs.map +1 -0
  41. package/fesm2022/tinya-code-gas-admin-ui-empty-state-BMc0QtoT.mjs +109 -0
  42. package/fesm2022/tinya-code-gas-admin-ui-empty-state-BMc0QtoT.mjs.map +1 -0
  43. package/fesm2022/tinya-code-gas-admin-ui-error-mapper.service-DY5y1FjE.mjs +45 -0
  44. package/fesm2022/tinya-code-gas-admin-ui-error-mapper.service-DY5y1FjE.mjs.map +1 -0
  45. package/fesm2022/tinya-code-gas-admin-ui-field-aria-BD1Wiggc.mjs +50 -0
  46. package/fesm2022/tinya-code-gas-admin-ui-field-aria-BD1Wiggc.mjs.map +1 -0
  47. package/fesm2022/tinya-code-gas-admin-ui-field-node-CIK6KNN_.mjs +24 -0
  48. package/fesm2022/tinya-code-gas-admin-ui-field-node-CIK6KNN_.mjs.map +1 -0
  49. package/fesm2022/tinya-code-gas-admin-ui-field-path-B4-FTBGZ.mjs +27 -0
  50. package/fesm2022/tinya-code-gas-admin-ui-field-path-B4-FTBGZ.mjs.map +1 -0
  51. package/fesm2022/tinya-code-gas-admin-ui-file-Dmxioog7.mjs +408 -0
  52. package/fesm2022/tinya-code-gas-admin-ui-file-Dmxioog7.mjs.map +1 -0
  53. package/fesm2022/tinya-code-gas-admin-ui-form-view-CEe7aZ4m.mjs +4516 -0
  54. package/fesm2022/tinya-code-gas-admin-ui-form-view-CEe7aZ4m.mjs.map +1 -0
  55. package/fesm2022/tinya-code-gas-admin-ui-format-badge-CK8ct5Wk.mjs +82 -0
  56. package/fesm2022/tinya-code-gas-admin-ui-format-badge-CK8ct5Wk.mjs.map +1 -0
  57. package/fesm2022/tinya-code-gas-admin-ui-format-boolean-ClzezZz-.mjs +105 -0
  58. package/fesm2022/tinya-code-gas-admin-ui-format-boolean-ClzezZz-.mjs.map +1 -0
  59. package/fesm2022/tinya-code-gas-admin-ui-format-currency-CVmniKml.mjs +65 -0
  60. package/fesm2022/tinya-code-gas-admin-ui-format-currency-CVmniKml.mjs.map +1 -0
  61. package/fesm2022/tinya-code-gas-admin-ui-format-date-Dr1YsDd_.mjs +65 -0
  62. package/fesm2022/tinya-code-gas-admin-ui-format-date-Dr1YsDd_.mjs.map +1 -0
  63. package/fesm2022/tinya-code-gas-admin-ui-format-number-CWCjpI4n.mjs +65 -0
  64. package/fesm2022/tinya-code-gas-admin-ui-format-number-CWCjpI4n.mjs.map +1 -0
  65. package/fesm2022/tinya-code-gas-admin-ui-format-text-DBOgJkH0.mjs +59 -0
  66. package/fesm2022/tinya-code-gas-admin-ui-format-text-DBOgJkH0.mjs.map +1 -0
  67. package/fesm2022/tinya-code-gas-admin-ui-format-thumbnail-PCRvxWKt.mjs +94 -0
  68. package/fesm2022/tinya-code-gas-admin-ui-format-thumbnail-PCRvxWKt.mjs.map +1 -0
  69. package/fesm2022/tinya-code-gas-admin-ui-gap-sorting-iTdy_DYG.mjs +72 -0
  70. package/fesm2022/tinya-code-gas-admin-ui-gap-sorting-iTdy_DYG.mjs.map +1 -0
  71. package/fesm2022/tinya-code-gas-admin-ui-group-h7-O8tt4.mjs +238 -0
  72. package/fesm2022/tinya-code-gas-admin-ui-group-h7-O8tt4.mjs.map +1 -0
  73. package/fesm2022/tinya-code-gas-admin-ui-image-7UhJ7nqI.mjs +416 -0
  74. package/fesm2022/tinya-code-gas-admin-ui-image-7UhJ7nqI.mjs.map +1 -0
  75. package/fesm2022/tinya-code-gas-admin-ui-kanban-view-Dl0Ol5Kb.mjs +439 -0
  76. package/fesm2022/tinya-code-gas-admin-ui-kanban-view-Dl0Ol5Kb.mjs.map +1 -0
  77. package/fesm2022/tinya-code-gas-admin-ui-key-value-nVdgg5at.mjs +513 -0
  78. package/fesm2022/tinya-code-gas-admin-ui-key-value-nVdgg5at.mjs.map +1 -0
  79. package/fesm2022/tinya-code-gas-admin-ui-list-DTtCYS4d.mjs +637 -0
  80. package/fesm2022/tinya-code-gas-admin-ui-list-DTtCYS4d.mjs.map +1 -0
  81. package/fesm2022/tinya-code-gas-admin-ui-metric-card-DnGMQL8l.mjs +127 -0
  82. package/fesm2022/tinya-code-gas-admin-ui-metric-card-DnGMQL8l.mjs.map +1 -0
  83. package/fesm2022/tinya-code-gas-admin-ui-multiselect-PB28e-jl.mjs +251 -0
  84. package/fesm2022/tinya-code-gas-admin-ui-multiselect-PB28e-jl.mjs.map +1 -0
  85. package/fesm2022/tinya-code-gas-admin-ui-notification.service-LjSULER6.mjs +66 -0
  86. package/fesm2022/tinya-code-gas-admin-ui-notification.service-LjSULER6.mjs.map +1 -0
  87. package/fesm2022/tinya-code-gas-admin-ui-number-JNr7glc8.mjs +114 -0
  88. package/fesm2022/tinya-code-gas-admin-ui-number-JNr7glc8.mjs.map +1 -0
  89. package/fesm2022/tinya-code-gas-admin-ui-phone-jR417hPf.mjs +116 -0
  90. package/fesm2022/tinya-code-gas-admin-ui-phone-jR417hPf.mjs.map +1 -0
  91. package/fesm2022/tinya-code-gas-admin-ui-quick-actions-DCQ6emmF.mjs +235 -0
  92. package/fesm2022/tinya-code-gas-admin-ui-quick-actions-DCQ6emmF.mjs.map +1 -0
  93. package/fesm2022/tinya-code-gas-admin-ui-radio-mode-DxvN07DY.mjs +8 -0
  94. package/fesm2022/tinya-code-gas-admin-ui-radio-mode-DxvN07DY.mjs.map +1 -0
  95. package/fesm2022/tinya-code-gas-admin-ui-readonly-text-BL7-4qie.mjs +124 -0
  96. package/fesm2022/tinya-code-gas-admin-ui-readonly-text-BL7-4qie.mjs.map +1 -0
  97. package/fesm2022/tinya-code-gas-admin-ui-record-list-BiZfnd_7.mjs +249 -0
  98. package/fesm2022/tinya-code-gas-admin-ui-record-list-BiZfnd_7.mjs.map +1 -0
  99. package/fesm2022/tinya-code-gas-admin-ui-relation-drawer.service-B0kT8EiW.mjs +39 -0
  100. package/fesm2022/tinya-code-gas-admin-ui-relation-drawer.service-B0kT8EiW.mjs.map +1 -0
  101. package/fesm2022/tinya-code-gas-admin-ui-relation-ykpJ3PYl.mjs +309 -0
  102. package/fesm2022/tinya-code-gas-admin-ui-relation-ykpJ3PYl.mjs.map +1 -0
  103. package/fesm2022/tinya-code-gas-admin-ui-render-registry-B88Pme-y.mjs +576 -0
  104. package/fesm2022/tinya-code-gas-admin-ui-render-registry-B88Pme-y.mjs.map +1 -0
  105. package/fesm2022/tinya-code-gas-admin-ui-rich-select-CIHaOrbU.mjs +161 -0
  106. package/fesm2022/tinya-code-gas-admin-ui-rich-select-CIHaOrbU.mjs.map +1 -0
  107. package/fesm2022/tinya-code-gas-admin-ui-rolldown-runtime-DpJrqANO.mjs +11 -0
  108. package/fesm2022/tinya-code-gas-admin-ui-schema-catalog-D0Pk0wAN.mjs +685 -0
  109. package/fesm2022/tinya-code-gas-admin-ui-schema-catalog-D0Pk0wAN.mjs.map +1 -0
  110. package/fesm2022/tinya-code-gas-admin-ui-seed-DkVZbxPP.mjs +80 -0
  111. package/fesm2022/tinya-code-gas-admin-ui-seed-DkVZbxPP.mjs.map +1 -0
  112. package/fesm2022/tinya-code-gas-admin-ui-select-CDwX9yNO.mjs +296 -0
  113. package/fesm2022/tinya-code-gas-admin-ui-select-CDwX9yNO.mjs.map +1 -0
  114. package/fesm2022/tinya-code-gas-admin-ui-skeleton-DnWK0tcZ.mjs +119 -0
  115. package/fesm2022/tinya-code-gas-admin-ui-skeleton-DnWK0tcZ.mjs.map +1 -0
  116. package/fesm2022/tinya-code-gas-admin-ui-slug-DU58cbiY.mjs +158 -0
  117. package/fesm2022/tinya-code-gas-admin-ui-slug-DU58cbiY.mjs.map +1 -0
  118. package/fesm2022/tinya-code-gas-admin-ui-source-options-B9R4mw8-.mjs +26 -0
  119. package/fesm2022/tinya-code-gas-admin-ui-source-options-B9R4mw8-.mjs.map +1 -0
  120. package/fesm2022/tinya-code-gas-admin-ui-status-progress-DmeG8htE.mjs +205 -0
  121. package/fesm2022/tinya-code-gas-admin-ui-status-progress-DmeG8htE.mjs.map +1 -0
  122. package/fesm2022/tinya-code-gas-admin-ui-string-list-gleasqzD.mjs +432 -0
  123. package/fesm2022/tinya-code-gas-admin-ui-string-list-gleasqzD.mjs.map +1 -0
  124. package/fesm2022/tinya-code-gas-admin-ui-template-interpolator-ewv7CkNX.mjs +36 -0
  125. package/fesm2022/tinya-code-gas-admin-ui-template-interpolator-ewv7CkNX.mjs.map +1 -0
  126. package/fesm2022/tinya-code-gas-admin-ui-text-CUPmL7W_.mjs +107 -0
  127. package/fesm2022/tinya-code-gas-admin-ui-text-CUPmL7W_.mjs.map +1 -0
  128. package/fesm2022/tinya-code-gas-admin-ui-textarea-CGLSIW13.mjs +223 -0
  129. package/fesm2022/tinya-code-gas-admin-ui-textarea-CGLSIW13.mjs.map +1 -0
  130. package/fesm2022/tinya-code-gas-admin-ui-time-BcHzsTWf.mjs +107 -0
  131. package/fesm2022/tinya-code-gas-admin-ui-time-BcHzsTWf.mjs.map +1 -0
  132. package/fesm2022/tinya-code-gas-admin-ui-upload.service-CZPEPCeN.mjs +60 -0
  133. package/fesm2022/tinya-code-gas-admin-ui-upload.service-CZPEPCeN.mjs.map +1 -0
  134. package/fesm2022/tinya-code-gas-admin-ui-url-GO4LZi__.mjs +141 -0
  135. package/fesm2022/tinya-code-gas-admin-ui-url-GO4LZi__.mjs.map +1 -0
  136. package/fesm2022/tinya-code-gas-admin-ui.mjs +4738 -0
  137. package/fesm2022/tinya-code-gas-admin-ui.mjs.map +1 -0
  138. package/package.json +15 -3
  139. package/types/tinya-code-gas-admin-ui.d.ts +3634 -0
  140. package/ng-package.json +0 -7
  141. package/src/lib/actions/action-registry.spec.ts +0 -52
  142. package/src/lib/actions/action-registry.ts +0 -126
  143. package/src/lib/actions/action-service.spec.ts +0 -215
  144. package/src/lib/actions/action-service.ts +0 -87
  145. package/src/lib/actions/descriptors.spec.ts +0 -155
  146. package/src/lib/actions/descriptors.ts +0 -154
  147. package/src/lib/columns/column-cell.ts +0 -33
  148. package/src/lib/columns/column-defaults.spec.ts +0 -99
  149. package/src/lib/columns/column-defaults.ts +0 -84
  150. package/src/lib/columns/column-format.spec.ts +0 -274
  151. package/src/lib/columns/descriptors.ts +0 -113
  152. package/src/lib/columns/format-badge.ts +0 -51
  153. package/src/lib/columns/format-boolean.ts +0 -58
  154. package/src/lib/columns/format-currency.ts +0 -30
  155. package/src/lib/columns/format-date.ts +0 -35
  156. package/src/lib/columns/format-number.ts +0 -32
  157. package/src/lib/columns/format-text.ts +0 -23
  158. package/src/lib/columns/format-thumbnail.ts +0 -63
  159. package/src/lib/core/adapters/firebase-auth.adapter.ts +0 -6
  160. package/src/lib/core/guards/auth.guard.spec.ts +0 -88
  161. package/src/lib/core/guards/auth.guard.ts +0 -48
  162. package/src/lib/core/guards/unsaved-changes.guard.ts +0 -16
  163. package/src/lib/core/interceptors/api-error.interceptor.spec.ts +0 -182
  164. package/src/lib/core/interceptors/api-error.interceptor.ts +0 -87
  165. package/src/lib/core/models/api.model.ts +0 -104
  166. package/src/lib/core/models/schema-descriptions.ts +0 -118
  167. package/src/lib/core/models/schema.model.ts +0 -1097
  168. package/src/lib/core/registry/composition-validator.spec.ts +0 -358
  169. package/src/lib/core/registry/composition-validator.ts +0 -270
  170. package/src/lib/core/registry/field-validators.spec.ts +0 -199
  171. package/src/lib/core/registry/field-validators.ts +0 -440
  172. package/src/lib/core/registry/render-host.spec.ts +0 -208
  173. package/src/lib/core/registry/render-host.ts +0 -646
  174. package/src/lib/core/registry/render-registry.spec.ts +0 -96
  175. package/src/lib/core/registry/render-registry.ts +0 -312
  176. package/src/lib/core/registry/schema-catalog.ts +0 -156
  177. package/src/lib/core/services/api.service.spec.ts +0 -1142
  178. package/src/lib/core/services/api.service.ts +0 -371
  179. package/src/lib/core/services/auth.service.spec.ts +0 -653
  180. package/src/lib/core/services/auth.service.ts +0 -503
  181. package/src/lib/core/services/config.service.spec.ts +0 -121
  182. package/src/lib/core/services/config.service.ts +0 -119
  183. package/src/lib/core/services/data-source.service.spec.ts +0 -179
  184. package/src/lib/core/services/data-source.service.ts +0 -142
  185. package/src/lib/core/services/error-mapper.service.spec.ts +0 -50
  186. package/src/lib/core/services/error-mapper.service.ts +0 -49
  187. package/src/lib/core/services/notification.service.ts +0 -73
  188. package/src/lib/core/services/relation-drawer.service.ts +0 -41
  189. package/src/lib/core/services/theme.service.spec.ts +0 -106
  190. package/src/lib/core/services/theme.service.ts +0 -86
  191. package/src/lib/core/services/transport.spec.ts +0 -198
  192. package/src/lib/core/services/transport.ts +0 -164
  193. package/src/lib/core/services/upload.service.ts +0 -81
  194. package/src/lib/core/testing/categories.schema.ts +0 -125
  195. package/src/lib/core/testing/orders.schema.ts +0 -372
  196. package/src/lib/core/testing/products.schema.ts +0 -258
  197. package/src/lib/core/testing/site.schema.ts +0 -195
  198. package/src/lib/core/testing/test-catalog.ts +0 -21
  199. package/src/lib/core/tokens.ts +0 -112
  200. package/src/lib/core/utils/clipboard.spec.ts +0 -55
  201. package/src/lib/core/utils/clipboard.ts +0 -90
  202. package/src/lib/core/utils/context-resolver.spec.ts +0 -95
  203. package/src/lib/core/utils/context-resolver.ts +0 -101
  204. package/src/lib/core/utils/response-unwrapper.spec.ts +0 -70
  205. package/src/lib/core/utils/response-unwrapper.ts +0 -103
  206. package/src/lib/core/utils/source-options.spec.ts +0 -96
  207. package/src/lib/core/utils/source-options.ts +0 -54
  208. package/src/lib/core/utils/template-interpolator.spec.ts +0 -59
  209. package/src/lib/core/utils/template-interpolator.ts +0 -56
  210. package/src/lib/core/view-navigation/view-navigation.service.spec.ts +0 -207
  211. package/src/lib/core/view-navigation/view-navigation.service.ts +0 -132
  212. package/src/lib/fields/boolean/boolean.descriptor.ts +0 -11
  213. package/src/lib/fields/boolean/boolean.ts +0 -40
  214. package/src/lib/fields/color/color.descriptor.ts +0 -12
  215. package/src/lib/fields/color/color.ts +0 -34
  216. package/src/lib/fields/currency/currency.descriptor.ts +0 -12
  217. package/src/lib/fields/currency/currency.ts +0 -67
  218. package/src/lib/fields/date/date.descriptor.ts +0 -12
  219. package/src/lib/fields/date/date.ts +0 -36
  220. package/src/lib/fields/descriptors.ts +0 -122
  221. package/src/lib/fields/display/display-badge.ts +0 -65
  222. package/src/lib/fields/display/display-date.ts +0 -39
  223. package/src/lib/fields/display/display-defaults.ts +0 -84
  224. package/src/lib/fields/display/display-file.ts +0 -41
  225. package/src/lib/fields/display/display-image.ts +0 -54
  226. package/src/lib/fields/display/display-list.ts +0 -107
  227. package/src/lib/fields/display/display-number.ts +0 -41
  228. package/src/lib/fields/display/display-text.ts +0 -42
  229. package/src/lib/fields/display/display.spec.ts +0 -242
  230. package/src/lib/fields/dropdown/dropdown.descriptor.ts +0 -12
  231. package/src/lib/fields/dropdown/dropdown.ts +0 -45
  232. package/src/lib/fields/email/email.descriptor.ts +0 -12
  233. package/src/lib/fields/email/email.ts +0 -28
  234. package/src/lib/fields/field-aria.ts +0 -60
  235. package/src/lib/fields/field-host/field-host.spec.ts +0 -118
  236. package/src/lib/fields/field-host/field-host.ts +0 -47
  237. package/src/lib/fields/field-node.ts +0 -88
  238. package/src/lib/fields/file/file.descriptor.ts +0 -14
  239. package/src/lib/fields/file/file.spec.ts +0 -134
  240. package/src/lib/fields/file/file.ts +0 -281
  241. package/src/lib/fields/group/group.descriptor.ts +0 -21
  242. package/src/lib/fields/group/group.ts +0 -110
  243. package/src/lib/fields/image/image.descriptor.ts +0 -12
  244. package/src/lib/fields/image/image.spec.ts +0 -117
  245. package/src/lib/fields/image/image.ts +0 -281
  246. package/src/lib/fields/key-value/key-value.descriptor.ts +0 -11
  247. package/src/lib/fields/key-value/key-value.ts +0 -283
  248. package/src/lib/fields/list/list.descriptor.ts +0 -21
  249. package/src/lib/fields/list/list.ts +0 -376
  250. package/src/lib/fields/multiselect/multiselect.descriptor.ts +0 -11
  251. package/src/lib/fields/multiselect/multiselect.spec.ts +0 -142
  252. package/src/lib/fields/multiselect/multiselect.ts +0 -152
  253. package/src/lib/fields/number/number.descriptor.ts +0 -12
  254. package/src/lib/fields/number/number.ts +0 -40
  255. package/src/lib/fields/phone/phone.descriptor.ts +0 -12
  256. package/src/lib/fields/phone/phone.ts +0 -46
  257. package/src/lib/fields/readonly-text/readonly-text.descriptor.ts +0 -12
  258. package/src/lib/fields/readonly-text/readonly-text.ts +0 -58
  259. package/src/lib/fields/relation/relation.descriptor.ts +0 -12
  260. package/src/lib/fields/relation/relation.spec.ts +0 -193
  261. package/src/lib/fields/relation/relation.ts +0 -224
  262. package/src/lib/fields/rich-select/rich-select.descriptor.ts +0 -12
  263. package/src/lib/fields/rich-select/rich-select.ts +0 -175
  264. package/src/lib/fields/select/radio-mode.ts +0 -25
  265. package/src/lib/fields/select/select.descriptor.ts +0 -12
  266. package/src/lib/fields/select/select.spec.ts +0 -162
  267. package/src/lib/fields/select/select.ts +0 -210
  268. package/src/lib/fields/slug/slug.descriptor.ts +0 -19
  269. package/src/lib/fields/slug/slug.ts +0 -67
  270. package/src/lib/fields/string-list/string-list.descriptor.ts +0 -11
  271. package/src/lib/fields/string-list/string-list.ts +0 -222
  272. package/src/lib/fields/text/text.descriptor.ts +0 -12
  273. package/src/lib/fields/text/text.ts +0 -35
  274. package/src/lib/fields/textarea/textarea.descriptor.ts +0 -12
  275. package/src/lib/fields/textarea/textarea.spec.ts +0 -117
  276. package/src/lib/fields/textarea/textarea.ts +0 -126
  277. package/src/lib/fields/time/time.descriptor.ts +0 -12
  278. package/src/lib/fields/time/time.ts +0 -28
  279. package/src/lib/fields/unknown-render/unknown-render.ts +0 -49
  280. package/src/lib/fields/url/url.descriptor.ts +0 -12
  281. package/src/lib/fields/url/url.ts +0 -53
  282. package/src/lib/gas-admin-ui.spec.ts +0 -21
  283. package/src/lib/gas-admin-ui.ts +0 -9
  284. package/src/lib/layouts/descriptors.ts +0 -9
  285. package/src/lib/pages/dashboard/dashboard.ts +0 -167
  286. package/src/lib/pages/detail-view/detail-view.spec.ts +0 -333
  287. package/src/lib/pages/detail-view/detail-view.ts +0 -570
  288. package/src/lib/pages/drawer-form/drawer-form.ts +0 -228
  289. package/src/lib/pages/form-view/form-model.ts +0 -88
  290. package/src/lib/pages/form-view/form-schema.ts +0 -255
  291. package/src/lib/pages/form-view/form-view.ts +0 -1622
  292. package/src/lib/pages/list-view/list-view.formats.spec.ts +0 -214
  293. package/src/lib/pages/list-view/list-view.ts +0 -882
  294. package/src/lib/pages/login/login.spec.ts +0 -109
  295. package/src/lib/pages/login/login.ts +0 -227
  296. package/src/lib/pages/resource-page/resource-page.ts +0 -234
  297. package/src/lib/shared/components/badge/badge.ts +0 -35
  298. package/src/lib/shared/components/button/button.ts +0 -65
  299. package/src/lib/shared/components/confirm-dialog/confirm-dialog.ts +0 -48
  300. package/src/lib/shared/components/copy-button/copy-button.ts +0 -56
  301. package/src/lib/shared/components/copy-share/copy-share.spec.ts +0 -122
  302. package/src/lib/shared/components/copy-share/copy-share.ts +0 -107
  303. package/src/lib/shared/components/drawer/drawer.spec.ts +0 -127
  304. package/src/lib/shared/components/drawer/drawer.ts +0 -172
  305. package/src/lib/shared/components/empty-state/empty-state.ts +0 -30
  306. package/src/lib/shared/components/modal/modal.spec.ts +0 -149
  307. package/src/lib/shared/components/modal/modal.ts +0 -145
  308. package/src/lib/shared/components/post-create-modal/post-create-modal.spec.ts +0 -165
  309. package/src/lib/shared/components/post-create-modal/post-create-modal.ts +0 -159
  310. package/src/lib/shared/components/skeleton/skeleton.ts +0 -31
  311. package/src/lib/shared/components/toast/toast.ts +0 -58
  312. package/src/lib/shared/utils/col-span.ts +0 -25
  313. package/src/lib/shared/utils/condition-evaluator.ts +0 -53
  314. package/src/lib/shared/utils/depends-on.ts +0 -48
  315. package/src/lib/shared/utils/dialog-focus.ts +0 -28
  316. package/src/lib/shared/utils/field-path.ts +0 -49
  317. package/src/lib/shared/utils/gap-sorting.ts +0 -144
  318. package/src/lib/shared/utils/seed.spec.ts +0 -64
  319. package/src/lib/shared/utils/seed.ts +0 -149
  320. package/src/lib/shared/utils/slugify.ts +0 -13
  321. package/src/lib/shared/utils/validators.ts +0 -41
  322. package/src/lib/shell/layout/layout.ts +0 -63
  323. package/src/lib/shell/shell.routes.spec.ts +0 -59
  324. package/src/lib/shell/shell.routes.ts +0 -122
  325. package/src/lib/shell/sidebar/sidebar.ts +0 -139
  326. package/src/lib/shell/theme-toggle/theme-toggle.ts +0 -74
  327. package/src/lib/views/calendar-view/calendar-model.ts +0 -426
  328. package/src/lib/views/calendar-view/calendar-view.spec.ts +0 -557
  329. package/src/lib/views/calendar-view/calendar-view.ts +0 -568
  330. package/src/lib/views/composer/composer-host.spec.ts +0 -301
  331. package/src/lib/views/composer/composer-host.ts +0 -248
  332. package/src/lib/views/composer/composer-imports.spec.ts +0 -54
  333. package/src/lib/views/composer/view-context.spec.ts +0 -117
  334. package/src/lib/views/composer/view-context.ts +0 -109
  335. package/src/lib/views/composer/view-slot.spec.ts +0 -130
  336. package/src/lib/views/composer/view-slot.ts +0 -178
  337. package/src/lib/views/descriptors.ts +0 -46
  338. package/src/lib/views/kanban-view/kanban-model.ts +0 -173
  339. package/src/lib/views/kanban-view/kanban-view.spec.ts +0 -540
  340. package/src/lib/views/kanban-view/kanban-view.ts +0 -327
  341. package/src/lib/widgets/bar-chart/bar-chart.descriptor.ts +0 -17
  342. package/src/lib/widgets/bar-chart/bar-chart.spec.ts +0 -66
  343. package/src/lib/widgets/bar-chart/bar-chart.ts +0 -76
  344. package/src/lib/widgets/chart-line/chart-line.descriptor.ts +0 -17
  345. package/src/lib/widgets/chart-line/chart-line.spec.ts +0 -113
  346. package/src/lib/widgets/chart-line/chart-line.ts +0 -219
  347. package/src/lib/widgets/descriptors.ts +0 -29
  348. package/src/lib/widgets/metric-card/metric-card.descriptor.ts +0 -41
  349. package/src/lib/widgets/metric-card/metric-card.spec.ts +0 -52
  350. package/src/lib/widgets/metric-card/metric-card.ts +0 -48
  351. package/src/lib/widgets/quick-actions/quick-actions.descriptor.ts +0 -13
  352. package/src/lib/widgets/quick-actions/quick-actions.spec.ts +0 -61
  353. package/src/lib/widgets/quick-actions/quick-actions.ts +0 -100
  354. package/src/lib/widgets/record-list/record-list.descriptor.ts +0 -16
  355. package/src/lib/widgets/record-list/record-list.spec.ts +0 -79
  356. package/src/lib/widgets/record-list/record-list.ts +0 -115
  357. package/src/lib/widgets/series.spec.ts +0 -42
  358. package/src/lib/widgets/series.ts +0 -56
  359. package/src/lib/widgets/status-progress/status-progress.descriptor.ts +0 -19
  360. package/src/lib/widgets/status-progress/status-progress.spec.ts +0 -63
  361. package/src/lib/widgets/status-progress/status-progress.ts +0 -104
  362. package/src/lib/widgets/widget-host/widget-host.spec.ts +0 -179
  363. package/src/lib/widgets/widget-host/widget-host.ts +0 -99
  364. package/src/public-api.ts +0 -104
  365. package/tinya-code-gas-admin-ui-0.2.0-alpha.15.tgz +0 -0
  366. package/tsconfig.lib.json +0 -13
  367. package/tsconfig.lib.prod.json +0 -11
  368. package/tsconfig.spec.json +0 -10
@@ -1,228 +0,0 @@
1
- import {
2
- Component,
3
- DestroyRef,
4
- Injector,
5
- OnInit,
6
- computed,
7
- inject,
8
- input,
9
- output,
10
- signal,
11
- } from '@angular/core';
12
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
13
- import { form, submit } from '@angular/forms/signals';
14
- import { firstValueFrom } from 'rxjs';
15
-
16
- import type { FieldSchema, ResourceSchema } from '../../core/models/schema.model';
17
- import { ApiService } from '../../core/services/api.service';
18
- import { ErrorMapperService } from '../../core/services/error-mapper.service';
19
- import { NotificationService } from '../../core/services/notification.service';
20
- import { FieldHost } from '../../fields/field-host/field-host';
21
- import { childTree, type RootTree } from '../../fields/field-node';
22
- import { Button } from '../../shared/components/button/button';
23
- import { Drawer, type DrawerSize } from '../../shared/components/drawer/drawer';
24
- import { Skeleton } from '../../shared/components/skeleton/skeleton';
25
- import { buildFormSchema } from '../form-view/form-schema';
26
- import { buildPayload, seedModel } from '../form-view/form-model';
27
-
28
- /**
29
- * Formulario dentro de un drawer (plan 6.4/6.5, guía §5).
30
- *
31
- * Es deliberadamente más chico que `form-view`: sin pestañas, sin secciones,
32
- * sin borrador y sin resumen de errores. Sirve para abrir 1–3 campos sin
33
- * perder el contexto de la pantalla de la que vino el usuario, y para crear
34
- * un registro desde el dropdown de una relación.
35
- *
36
- * Componente controlado: `open` entra por `input()`, y el padre cierra con
37
- * `close`/`saved`. Nada navega por su cuenta.
38
- */
39
- @Component({
40
- selector: 'app-drawer-form',
41
- imports: [Button, Drawer, FieldHost, Skeleton],
42
- template: `
43
- <app-drawer [open]="open()" [title]="drawerTitle()" [size]="size()" (close)="close.emit()">
44
- @if (status() === 'loading') {
45
- <app-skeleton [lines]="4" />
46
- } @else if (status() === 'error') {
47
- <p role="alert" class="rounded-lg bg-danger/10 px-3 py-2 text-sm text-danger">
48
- {{ loadError() }}
49
- </p>
50
- } @else if (tree(); as formTree) {
51
- @if (generalError()) {
52
- <p
53
- role="alert"
54
- class="mb-4 rounded-lg bg-danger/10 px-3 py-2 text-sm text-danger"
55
- data-drawer-error
56
- >
57
- {{ generalError() }}
58
- </p>
59
- }
60
- @for (field of visibleFields(); track field.key) {
61
- <div class="mb-4">
62
- <app-field-host
63
- [field]="field"
64
- [tree]="formTree"
65
- [exists]="mode() === 'edit'"
66
- [serverErrors]="fieldErrors()"
67
- [resource]="schema().id"
68
- />
69
- </div>
70
- }
71
- }
72
-
73
- <div drawer-actions class="flex justify-end gap-2">
74
- <button app-button variant="outline" type="button" (click)="close.emit()">Cancelar</button>
75
- <button app-button type="button" [loading]="saving()" (click)="save()">Guardar</button>
76
- </div>
77
- </app-drawer>
78
- `,
79
- })
80
- export class DrawerForm implements OnInit {
81
- readonly open = input(false);
82
- readonly schema = input.required<ResourceSchema>();
83
- /** Subconjunto de campos a mostrar. Por defecto, todos los del schema. */
84
- readonly fields = input<readonly FieldSchema[] | undefined>(undefined);
85
- readonly mode = input<'create' | 'edit'>('create');
86
- readonly recordKey = input<string | null>(null);
87
- readonly title = input<string | null>(null);
88
- readonly size = input<DrawerSize>('md');
89
-
90
- /** Registro creado o actualizado, listo para que el padre refresque. */
91
- readonly saved = output<Record<string, unknown>>();
92
- readonly close = output<void>();
93
-
94
- private readonly api = inject(ApiService);
95
- private readonly notifications = inject(NotificationService);
96
- private readonly errorMapper = inject(ErrorMapperService);
97
- private readonly injector = inject(Injector);
98
- private readonly destroyRef = inject(DestroyRef);
99
-
100
- private readonly tree = signal<RootTree | null>(null);
101
- private readonly status = signal<'idle' | 'loading' | 'ready' | 'error'>('idle');
102
- private readonly saving = signal(false);
103
- private readonly generalError = signal('');
104
- private readonly fieldErrors = signal<Record<string, string>>({});
105
- private readonly loadError = signal('');
106
-
107
- readonly visibleFields = computed<readonly FieldSchema[]>(
108
- () => this.fields() ?? this.schema().fields,
109
- );
110
-
111
- readonly drawerTitle = computed(() => {
112
- if (this.title() !== null) {
113
- return this.title() as string;
114
- }
115
- const label = this.schema().label;
116
- return this.mode() === 'create' ? `Crear ${label}` : `Editar ${label}`;
117
- });
118
-
119
- ngOnInit(): void {
120
- // Se construye al montar, NO en un `effect`: `form()` crea un effect
121
- // interno y no puede correr dentro de otro (NG0602). Los padres montan
122
- // este componente bajo un `@if` y fijan los inputs, así que no hace
123
- // falta reaccionar a cambios posteriores.
124
- this.build();
125
- }
126
-
127
- private build(): void {
128
- const schema = this.schema();
129
- const recordKey = this.recordKey();
130
- const schemaFn = buildFormSchema(schema, this.api, recordKey ?? undefined);
131
- const tree = form(signal(seedModel(schema)), schemaFn, { injector: this.injector });
132
-
133
- if (this.mode() === 'create' || recordKey === null) {
134
- this.tree.set(tree);
135
- this.status.set('ready');
136
- return;
137
- }
138
-
139
- // Edición: el valor se pisa con el registro, dejando los defaults de
140
- // los campos que el backend no devuelve.
141
- this.status.set('loading');
142
- this.api
143
- .get<Record<string, unknown>>(schema.endpoint, recordKey)
144
- .pipe(takeUntilDestroyed(this.destroyRef))
145
- .subscribe({
146
- next: (record) => {
147
- tree().value.set({ ...seedModel(schema), ...record });
148
- this.tree.set(tree);
149
- this.status.set('ready');
150
- },
151
- error: (error: unknown) => {
152
- this.loadError.set(this.errorMapper.messageOf(error));
153
- this.status.set('error');
154
- },
155
- });
156
- }
157
-
158
- async save(): Promise<void> {
159
- const tree = this.tree();
160
- const schema = this.schema();
161
- if (tree === null || this.saving()) {
162
- return;
163
- }
164
- this.saving.set(true);
165
- this.generalError.set('');
166
- this.fieldErrors.set({});
167
- try {
168
- const ok = await submit(tree, {
169
- // `null` = sin errores propios: los del backend se pintan aparte.
170
- action: async () => {
171
- await this.persist(tree, schema);
172
- return null;
173
- },
174
- onInvalid: () => this.markTouched(tree),
175
- });
176
- if (!ok || Object.keys(this.fieldErrors()).length > 0 || this.generalError() !== '') {
177
- this.markTouched(tree);
178
- }
179
- } finally {
180
- this.saving.set(false);
181
- }
182
- }
183
-
184
- /**
185
- * Marca como tocado lo que se está mostrando. Se recorre por campo y no
186
- * desde la raíz: `FieldTree<Record<string, unknown>>` se indexa con una
187
- * clave dinámica y `markAsTouched` no compila ahí (`childTree` centraliza
188
- * ese cast). Baja a todos los descendientes, así un `group` queda cubierto.
189
- */
190
- private markTouched(tree: RootTree): void {
191
- for (const field of this.visibleFields()) {
192
- childTree<unknown>(tree, field.key)().markAsTouched();
193
- }
194
- }
195
-
196
- /** create/update; nunca lanza (los errores quedan en las señales). */
197
- private async persist(tree: RootTree, schema: ResourceSchema): Promise<void> {
198
- const payload = buildPayload(schema, tree);
199
- try {
200
- if (this.mode() === 'create') {
201
- const created = await firstValueFrom(
202
- this.api.create<Record<string, unknown>>(schema.endpoint, payload),
203
- );
204
- this.notifications.success('Registro creado.');
205
- this.saved.emit(created ?? {});
206
- this.close.emit();
207
- return;
208
- }
209
- const updated = await firstValueFrom(
210
- this.api.update<Record<string, unknown>>(
211
- schema.endpoint,
212
- this.recordKey() ?? undefined,
213
- payload,
214
- ),
215
- );
216
- this.notifications.success('Registro guardado.');
217
- this.saved.emit(updated ?? {});
218
- this.close.emit();
219
- } catch (error: unknown) {
220
- const mapped = this.errorMapper.map(error);
221
- this.fieldErrors.set(mapped.fields);
222
- const withoutFields = Object.keys(mapped.fields).length === 0;
223
- this.generalError.set(
224
- mapped.general ?? (withoutFields ? this.errorMapper.messageOf(error) : ''),
225
- );
226
- }
227
- }
228
- }
@@ -1,88 +0,0 @@
1
- import type { FieldSchema, ResourceSchema } from '../../core/models/schema.model';
2
- import { childTree, itemTree, listTree, type RootTree } from '../../fields/field-node';
3
- import { seedFields } from '../../shared/utils/seed';
4
-
5
- /**
6
- * Modelo y payload del formulario genérico (Fase 10, ampliado en Fase 11).
7
- *
8
- * - `seedModel` siembra un valor inicial para CADA campo declarado en el
9
- * schema antes de crear el formulario: el árbol de Signal Forms replica la
10
- * forma del modelo, así que un campo ausente no tendría estado (ni valor
11
- * que enviar). La siembra vive en `shared/utils/seed.ts`.
12
- * - `buildPayload` decide qué viaja al backend (base.md §10): solo las claves
13
- * declaradas en el schema, sin los ocultos y sin `positionField` raíz.
14
- */
15
-
16
- /** Valores por defecto del schema, en el mismo orden/shape que el JSON. */
17
- export function seedModel(schema: ResourceSchema): Record<string, unknown> {
18
- return seedFields(schema.fields);
19
- }
20
-
21
- /**
22
- * Payload del guardado: whitelist de `schema.fields`.
23
- *
24
- * - Los campos ocultos (`visibleWhen` falso) no se muestran ni se envían
25
- * (base.md §10): usar `hidden()` garantiza que no aparezcan acá aunque
26
- * tengan valor sembrado — también dentro de `group` y de los ítems de una
27
- * `list` (recursivo).
28
- * - `positionField` del recurso se excluye aunque esté declarado: el orden
29
- * del listado lo gestiona el backend (api.md R3, nunca se expone). El
30
- * `positionField` de los ÍTEMS de una lista sí viaja: el orden local lo
31
- * calcula el front (base.md §8).
32
- * - Los tipos que la UI todavía no edita SÍ viajan: sus valores llegan del
33
- * registro leído, así que reenviarlos evita pisarlos.
34
- */
35
- export function buildPayload(schema: ResourceSchema, root: RootTree): Record<string, unknown> {
36
- const payload: Record<string, unknown> = {};
37
- collectPayload(root, schema.fields, payload, schema.positionField);
38
- return payload;
39
- }
40
-
41
- function collectPayload(
42
- tree: RootTree,
43
- fields: readonly FieldSchema[],
44
- payload: Record<string, unknown>,
45
- excludedKey: string | undefined,
46
- ): void {
47
- for (const field of fields) {
48
- if (excludedKey !== undefined && field.key === excludedKey) {
49
- continue;
50
- }
51
- const state = childTree<unknown>(tree, field.key)();
52
- if (state.hidden()) {
53
- continue;
54
- }
55
- if (field.type === 'group') {
56
- const nested: Record<string, unknown> = {};
57
- collectPayload(
58
- childTree<Record<string, unknown>>(tree, field.key),
59
- field.fields,
60
- nested,
61
- undefined,
62
- );
63
- payload[field.key] = nested;
64
- continue;
65
- }
66
- if (field.type === 'list') {
67
- const items = listTree(tree, field.key);
68
- const raw = (state.value() as Record<string, unknown>[] | null) ?? [];
69
- const list: unknown[] = [];
70
- for (let index = 0; index < raw.length; index++) {
71
- const nested: Record<string, unknown> = {};
72
- collectPayload(itemTree(items, index), field.itemFields, nested, undefined);
73
- // El orden de los ítems viaja con el registro padre (base.md §8): el
74
- // `positionField` no es un campo editable, por eso no está en
75
- // `itemFields` y hay que leerlo del modelo crudo.
76
- const positionKey = field.positionField;
77
- const position = positionKey !== undefined ? raw[index]?.[positionKey] : undefined;
78
- if (positionKey !== undefined && position !== undefined) {
79
- nested[positionKey] = position;
80
- }
81
- list.push(nested);
82
- }
83
- payload[field.key] = list;
84
- continue;
85
- }
86
- payload[field.key] = state.value();
87
- }
88
- }
@@ -1,255 +0,0 @@
1
- import {
2
- applyEach,
3
- disabled,
4
- hidden,
5
- readonly as readonlyRule,
6
- type SchemaFn,
7
- type SchemaPathTree,
8
- } from '@angular/forms/signals';
9
-
10
- import type { FieldSchema, ResourceSchema } from '../../core/models/schema.model';
11
- import type { ApiService } from '../../core/services/api.service';
12
- import {
13
- FIELD_VALIDATORS,
14
- registerEmailRule,
15
- registerUrlRule,
16
- type FieldPath,
17
- type ValidatorContext,
18
- } from '../../core/registry/field-validators';
19
- import { isSupported } from '../../core/registry/render-registry';
20
- import { evaluateCondition } from '../../shared/utils/condition-evaluator';
21
-
22
- /** Ruta de un hijo bajo un path (raíz, grupo o ítem). */
23
- type ChildPath<V> = FieldPath<V>;
24
- /** Ruta raíz del formulario. */
25
- type RootPath = SchemaPathTree<Record<string, unknown>>;
26
- /** Ruta de un campo lista (para `applyEach`). */
27
- type ListPath<V> = FieldPath<V>;
28
-
29
- /**
30
- * Reglas del formulario desde el schema (base.md §4, §6, §9, §10).
31
- *
32
- * Hay DOS clases de reglas y viven en sitios distintos:
33
- *
34
- * 1. **Ciclo de vida** — `visibleWhen`, `readonlyOn`, `hiddenOn`, `dependsOn`:
35
- * decides si el campo se toca, se ve o se manda. Vive acá, con la
36
- * estructura del formulario.
37
- * 2. **Validadores** — obligatoriedad, longitud, patrón, rangos, únicos…:
38
- * vive en `core/registry/field-validators.ts` (F7 + B11), con los MISMOS
39
- * nombres que el back. Este módulo sólo RECORRE ese registro por cada
40
- * campo: añadir un validador es una entrada allá, no un `case` acá.
41
- *
42
- * El schema de Signal Forms recibe el path RAÍZ; las reglas se atan a la ruta
43
- * dinámica de cada campo. El barrido es **recursivo** — un `group` registra
44
- * las reglas de sus hijos bajo su propia ruta y un `list` registra las de
45
- * cada ítem con `applyEach`, de modo que las reglas corran también para los
46
- * ítems que se agregan después.
47
- *
48
- * Solo se generan reglas para los tipos que la UI sabe editar (`isSupported('field', …)`):
49
- * un campo invisible con `required` bloquearía el guardado para siempre.
50
- *
51
- * `api` y `excludeKey` alimentan la validación `unique`: se consulta el
52
- * listado del recurso y se descarta el propio registro (la clave del registro
53
- * en edición, tomada de la ruta).
54
- */
55
- export function buildFormSchema(
56
- schema: ResourceSchema,
57
- api: ApiService,
58
- excludeKey?: string,
59
- ): SchemaFn<Record<string, unknown>> {
60
- return (root) => {
61
- applyRulesToFields(
62
- { schema, api, excludeKey, root, container: root, siblings: schema.fields },
63
- schema.fields,
64
- );
65
- };
66
- }
67
-
68
- /**
69
- * Ámbito de registro de reglas.
70
- *
71
- * - `root` es siempre la raíz del formulario (referencia para condiciones que
72
- * nombran un campo de la raíz, base.md §4: «mismo nivel o registro raíz»).
73
- * - `container` es el nodo del que cuelgan las rutas hijas: la raíz, un
74
- * `group` o un ítem de un `list`.
75
- * - `siblings` son los campos declarados en `container`: si una condición
76
- * nombra a uno de ellos se evalúa contra el contenedor, si no, contra la
77
- * raíz.
78
- */
79
- interface RuleScope {
80
- schema: ResourceSchema;
81
- api: ApiService;
82
- excludeKey: string | undefined;
83
- root: RootPath;
84
- container: object;
85
- siblings: readonly FieldSchema[];
86
- }
87
-
88
- function applyRulesToFields(scope: RuleScope, fields: readonly FieldSchema[]): void {
89
- for (const field of fields) {
90
- if (!isSupported('field', field.type)) {
91
- continue;
92
- }
93
- applyRulesToField(scope, field, pathAt<unknown>(scope.container, field.key));
94
- }
95
- }
96
-
97
- function applyRulesToField(scope: RuleScope, field: FieldSchema, path: ChildPath<unknown>): void {
98
- applyLifecycleRules(scope, field, path);
99
-
100
- // Validadores: el registro manda. Cada entrada decide si el campo la pide
101
- // y ata su regla a ESTA ruta (F7: sin `if` por regla en este módulo).
102
- const ctx: ValidatorContext = {
103
- path,
104
- field,
105
- schema: scope.schema,
106
- api: scope.api,
107
- excludeKey: scope.excludeKey,
108
- };
109
- for (const entry of FIELD_VALIDATORS) {
110
- if (entry.declares(ctx)) {
111
- entry.register(ctx);
112
- }
113
- }
114
-
115
- // Estructura (no es validador): los HIJOS se registran bajo su propia
116
- // ruta, recursivamente, para que las reglas corran también en los ítems
117
- // que el usuario agrega después.
118
- switch (field.type) {
119
- case 'group': {
120
- applyRulesToFields({ ...scope, container: path, siblings: field.fields }, field.fields);
121
- break;
122
- }
123
- case 'list': {
124
- applyEach(path as unknown as ListPath<Record<string, unknown>[]>, (item) =>
125
- applyRulesToFields(
126
- { ...scope, container: item as object, siblings: field.itemFields },
127
- field.itemFields,
128
- ),
129
- );
130
- break;
131
- }
132
- case 'string-list': {
133
- applyEach(path as unknown as ListPath<string[]>, (item) =>
134
- applyStringItemRules(item as ChildPath<string>, field.itemType),
135
- );
136
- break;
137
- }
138
- default:
139
- break;
140
- }
141
- }
142
-
143
- /**
144
- * ¿Aplica `mode` en ESTE contexto de formulario?
145
- *
146
- * Lo comparten `readonlyOn` y `hiddenOn`: `always` vale en todos los modos,
147
- * `create` sólo en alta y `update` sólo en edición. El modo se detecta por
148
- * `scope.excludeKey !== undefined`, que es la señal que ya usaba `readonlyOn`
149
- * (form-view define `mode` a partir de la misma condición).
150
- */
151
- function modeAppliesTo(mode: 'create' | 'update' | 'always', isEdit: boolean): boolean {
152
- return mode === 'always' || (mode === 'update' && isEdit) || (mode === 'create' && !isEdit);
153
- }
154
-
155
- /**
156
- * Ciclo de vida del campo: visibilidad, edición y dependencias (base.md §4).
157
- *
158
- * Aquí NO hay validadores — la obligatoriedad vive en el registro.
159
- * `hidden` además excluye el campo de `dirty`, `invalid` y del payload
160
- * (base.md §10 «Campos ocultos»), y `disabled` lo deja fuera de la
161
- * validación, así un `required` en el hijo no bloquea el guardado mientras
162
- * no haya nada que elegir.
163
- */
164
- function applyLifecycleRules(scope: RuleScope, field: FieldSchema, path: ChildPath<unknown>): void {
165
- if (field.visibleWhen) {
166
- const condition = field.visibleWhen;
167
- hidden(path, {
168
- when: (ctx) =>
169
- !evaluateCondition(condition, ctx.valueOf(conditionPath(scope, condition.field))),
170
- });
171
- }
172
- // Selección dependiente (guía §1, plan 6.6): el hijo no se puede tocar
173
- // hasta que el padre tenga valor.
174
- //
175
- // Acá NO sirve `conditionPath`: eso devuelve el contenedor entero porque
176
- // `evaluateCondition` recibe el objeto de hermanos. Acá se necesita el
177
- // valor concreto del padre.
178
- if (field.dependsOn) {
179
- const parentKey = field.dependsOn;
180
- const isSibling = scope.siblings.some((candidate) => candidate.key === parentKey);
181
- const parent = isSibling ? scope.container : scope.root;
182
- const parentPath = pathAt<unknown>(parent, parentKey);
183
- disabled(path, ({ valueOf }) => isEmptyValue(valueOf(parentPath)));
184
- }
185
- if (field.readonly) {
186
- readonlyRule(path, { when: () => true });
187
- }
188
- if (field.readonlyOn && modeAppliesTo(field.readonlyOn, scope.excludeKey !== undefined)) {
189
- readonlyRule(path, { when: () => true });
190
- }
191
- // Ciclo de vida de la visibilidad — simétrico a `readonlyOn` de arriba.
192
- // `hidden()` deja el campo fuera de la validación y del payload, así que en
193
- // alta un campo que LLENA EL BACK no ocupa la sección ni exige nada: sin
194
- // esto, `ref` y `pin` aparecían vacíos con un "se genera solo al guardar".
195
- if (field.hiddenOn && modeAppliesTo(field.hiddenOn, scope.excludeKey !== undefined)) {
196
- hidden(path, { when: () => true });
197
- }
198
- if (field.readonlyWhen) {
199
- const condition = field.readonlyWhen;
200
- readonlyRule(path, {
201
- when: (ctx) =>
202
- evaluateCondition(condition, ctx.valueOf(conditionPath(scope, condition.field))),
203
- });
204
- }
205
- }
206
-
207
- /** Vacío para el propósito de «el padre todavía no eligió nada». */
208
- function isEmptyValue(value: unknown): boolean {
209
- if (value === undefined || value === null || value === '') {
210
- return true;
211
- }
212
- return Array.isArray(value) && value.length === 0;
213
- }
214
-
215
- /**
216
- * Path contra el que se evalúa una condición: el contenedor si nombra a un
217
- * campo hermano, la raíz si no (base.md §4: «otro campo del mismo nivel o
218
- * del registro raíz»).
219
- */
220
- function conditionPath(scope: RuleScope, key: string): RootPath {
221
- const isSibling = scope.siblings.some((field) => field.key === key);
222
- const target = isSibling ? scope.container : scope.root;
223
- return target as RootPath;
224
- }
225
-
226
- /** Ítems de `string-list`: validan según el tipo declarado (§9: text/url/email). */
227
- function applyStringItemRules(
228
- path: ChildPath<string>,
229
- itemType: 'text' | 'url' | 'email' | undefined,
230
- ): void {
231
- if (itemType === 'email') {
232
- registerEmailRule(path);
233
- }
234
- if (itemType === 'url') {
235
- registerUrlRule(path);
236
- }
237
- }
238
-
239
- /**
240
- * Navegación dinámica sobre el árbol de paths.
241
- *
242
- * Indexar `SchemaPathTree<Record<string, unknown>>` con una clave dinámica
243
- * devuelve `SchemaPath<unknown, …> | undefined`: el `| undefined` es solo una
244
- * consecuencia del index signature, y las reglas con valor concreto (`min`,
245
- * `minLength`, `email`…) exigen afinar el tipo. Los casts de este módulo
246
- * viven acá; los del registro, en `field-validators.ts` (solución reportada
247
- * en plan.md, Fase 10).
248
- */
249
- function pathAt<V>(parent: object, key: string): ChildPath<V> {
250
- const path = (parent as unknown as Record<string, unknown>)[key];
251
- if (path === undefined) {
252
- throw new Error(`El formulario no contiene la ruta "${key}".`);
253
- }
254
- return path as ChildPath<V>;
255
- }