@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,58 +0,0 @@
1
- import { Component, input, output } from '@angular/core';
2
- import { LucideCircleCheck, LucideCircleX, LucideInfo, LucideX } from '@lucide/angular';
3
-
4
- export type ToastKind = 'success' | 'error' | 'info';
5
-
6
- /** Estructuralmente idéntico a `core`'s `Toast` — no importa `core`. */
7
- export interface ToastItem {
8
- id: number;
9
- kind: ToastKind;
10
- message: string;
11
- }
12
-
13
- /**
14
- * Contenedor visual de toasts: fijo arriba a la derecha, región `status`
15
- * viva (polite) para que se anuncien los mensajes. Recibe los toasts por
16
- * `input()` desde quien sí tiene `NotificationService` (Fase 7).
17
- */
18
- @Component({
19
- selector: 'app-toast',
20
- imports: [LucideCircleCheck, LucideCircleX, LucideInfo, LucideX],
21
- host: {
22
- class: 'pointer-events-none fixed right-4 top-4 z-50 flex w-full max-w-sm flex-col gap-2',
23
- role: 'status',
24
- 'aria-live': 'polite',
25
- },
26
- template: `
27
- @for (toast of toasts(); track toast.id) {
28
- <div
29
- class="pointer-events-auto flex items-start gap-3 border-l-4 bg-surface-raised p-4 shadow-lg"
30
- [class.border-l-success]="toast.kind === 'success'"
31
- [class.border-l-danger]="toast.kind === 'error'"
32
- [class.border-l-primary]="toast.kind === 'info'"
33
- >
34
- @if (toast.kind === 'success') {
35
- <svg lucideCircleCheck size="18" class="mt-0.5 shrink-0 text-success" />
36
- } @else if (toast.kind === 'error') {
37
- <svg lucideCircleX size="18" class="mt-0.5 shrink-0 text-danger" />
38
- } @else {
39
- <svg lucideInfo size="18" class="mt-0.5 shrink-0 text-primary" />
40
- }
41
- <p class="flex-1 text-sm font-medium">{{ toast.message }}</p>
42
- <button
43
- type="button"
44
- class="flex min-h-11 min-w-11 items-center justify-center rounded text-neutral hover:bg-neutral/10 focus-visible:outline-2 focus-visible:outline-primary lg:min-h-0 lg:min-w-0"
45
- [attr.aria-label]="closeLabel()"
46
- (click)="dismissed.emit(toast.id)"
47
- >
48
- <svg lucideX size="18" />
49
- </button>
50
- </div>
51
- }
52
- `,
53
- })
54
- export class Toast {
55
- readonly toasts = input<ToastItem[]>([]);
56
- readonly closeLabel = input('Cerrar');
57
- readonly dismissed = output<number>();
58
- }
@@ -1,25 +0,0 @@
1
- /**
2
- * Anchos de columna del layout (base.md §4: `width` 1–12).
3
- *
4
- * `sm:col-span-*` como literales: Tailwind v4 solo genera las clases que ve
5
- * en el código, así que no pueden construirse por concatenación.
6
- */
7
- const COL_SPANS: Record<number, string> = {
8
- 1: 'sm:col-span-1',
9
- 2: 'sm:col-span-2',
10
- 3: 'sm:col-span-3',
11
- 4: 'sm:col-span-4',
12
- 5: 'sm:col-span-5',
13
- 6: 'sm:col-span-6',
14
- 7: 'sm:col-span-7',
15
- 8: 'sm:col-span-8',
16
- 9: 'sm:col-span-9',
17
- 10: 'sm:col-span-10',
18
- 11: 'sm:col-span-11',
19
- 12: 'sm:col-span-12',
20
- };
21
-
22
- /** Clase `sm:col-span-*` para el ancho del campo (por defecto: 12). */
23
- export function colSpanClass(width: number | undefined): string {
24
- return COL_SPANS[width ?? 12];
25
- }
@@ -1,53 +0,0 @@
1
- import type { FieldCondition } from '../../core/models/schema.model';
2
-
3
- /**
4
- * Evaluador de condiciones `visibleWhen` / `readonlyWhen` (base.md §4):
5
- * comparaciones simples (igual, distinto, está vacío, contiene) sobre otros
6
- * campos del mismo nivel o del registro raíz.
7
- *
8
- * Nota de arquitectura: la importación de `FieldCondition` es SOLO de tipo
9
- * (se elimina en compilación) — no hay dependencia de runtime con `core`.
10
- */
11
-
12
- /** Resuelve una condición. Se resuelve contra el nivel propio; si la clave
13
- * no existe ahí, contra la raíz del registro. */
14
- export function evaluateCondition(
15
- condition: FieldCondition,
16
- siblingValues: Record<string, unknown>,
17
- rootValues: Record<string, unknown> = {},
18
- ): boolean {
19
- const source = condition.field in siblingValues ? siblingValues : rootValues;
20
- const actual = source[condition.field];
21
- const expected = condition.value;
22
-
23
- switch (condition.operator) {
24
- case 'eq':
25
- return actual === expected;
26
- case 'ne':
27
- return actual !== expected;
28
- case 'empty':
29
- return isEmpty(actual);
30
- case 'contains':
31
- return contains(actual, expected);
32
- }
33
- }
34
-
35
- function isEmpty(value: unknown): boolean {
36
- if (value === undefined || value === null || value === '') {
37
- return true;
38
- }
39
- if (Array.isArray(value)) {
40
- return value.length === 0;
41
- }
42
- return false;
43
- }
44
-
45
- function contains(actual: unknown, expected: unknown): boolean {
46
- if (typeof actual === 'string') {
47
- return actual.includes(String(expected));
48
- }
49
- if (Array.isArray(actual)) {
50
- return actual.includes(expected);
51
- }
52
- return false;
53
- }
@@ -1,48 +0,0 @@
1
- import type { FieldSchema } from '../../core/models/schema.model';
2
- import { seedFieldValue } from './seed';
3
-
4
- /**
5
- * Enlaces de selección dependiente (guía §1, plan 6.6).
6
- *
7
- * `condition-evaluator.ts` sólo RESUELVE condiciones (`visibleWhen` /
8
- * `readonlyWhen`): no resetea nada. Acá se levanta el mapa de «cuando el
9
- * padre cambie, limpiar el hijo» que `form-view` observa con un `effect`.
10
- *
11
- * Alcance: raíz y `group` (contenedores estáticos). Los ítems de un `list`
12
- * se crean y borran mientras se edita y sus rutas no son estables — un
13
- * dependiente dentro de una lista queda sin resetear, así que no se promete.
14
- */
15
- export interface DependsOnLink {
16
- /** Ruta de contenedores desde la raíz: `[]` en la raíz, `['contacto']` en un grupo. */
17
- container: string[];
18
- childKey: string;
19
- parentKey: string;
20
- /** Valor con el que se limpia el hijo (el default del schema). */
21
- resetValue: unknown;
22
- /** Clave estable del enlace para el snapshot de comparación. */
23
- id: string;
24
- }
25
-
26
- export function collectDependsOn(
27
- fields: readonly FieldSchema[],
28
- container: string[] = [],
29
- ): DependsOnLink[] {
30
- const links: DependsOnLink[] = [];
31
- for (const field of fields) {
32
- if (field.type === 'group') {
33
- links.push(...collectDependsOn(field.fields, [...container, field.key]));
34
- continue;
35
- }
36
- if (field.dependsOn === undefined) {
37
- continue;
38
- }
39
- links.push({
40
- container,
41
- childKey: field.key,
42
- parentKey: field.dependsOn,
43
- resetValue: seedFieldValue(field),
44
- id: `${container.join('.')}.${field.key}<-${field.dependsOn}`,
45
- });
46
- }
47
- return links;
48
- }
@@ -1,28 +0,0 @@
1
- /**
2
- * Utilidades de foco para los diálogos (`modal` y `drawer`).
3
- *
4
- * Los dos componentes comparten el mismo contrato: atrapan el Tab dentro del
5
- * panel para que el foco no se pierda detrás del fondo oscuro. Tener el
6
- * selector y el test de visibilidad en un solo sitio evita que los dos
7
- * diálogos diverjan.
8
- */
9
-
10
- /** Candidatos a foco dentro del diálogo (el orden del foco del navegador). */
11
- export const FOCUSABLE =
12
- 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
13
-
14
- /**
15
- * ¿Se puede enfocar este elemento ahora mismo?
16
- *
17
- * No se usa `offsetParent`: en jsdom es siempre `null` y el atrapado del Tab
18
- * quedaría sin opérculo en los tests. `checkVisibility` da la respuesta
19
- * exacta en navegador; si no existe (jsdom), se confía en lo que hay en el
20
- * DOM y sólo se descarta lo marcado `hidden`.
21
- */
22
- export function isVisibleNow(element: HTMLElement): boolean {
23
- if (element.hasAttribute('hidden') || element.closest('[hidden]') !== null) {
24
- return false;
25
- }
26
- const check = (element as { checkVisibility?: (options?: unknown) => boolean }).checkVisibility;
27
- return typeof check !== 'function' || check.call(element);
28
- }
@@ -1,49 +0,0 @@
1
- /**
2
- * Lectura de valores por ruta (ej. `faq[2].answer`, `address.city`) —
3
- * celdas del listado y valores anidados de los singleton (base.md §10).
4
- */
5
-
6
- /** Segmentos de una ruta: claves de objeto y índices de arreglo. */
7
- export type PathSegment = string | number;
8
-
9
- /** `faq[2].answer` → `['faq', 2, 'answer']`. */
10
- export function parsePath(path: string): PathSegment[] {
11
- const segments: PathSegment[] = [];
12
- for (const part of path.split('.')) {
13
- if (part === '') {
14
- continue;
15
- }
16
- const match = /^([^[\]]*)((?:\[\d+\])+)$/.exec(part);
17
- if (match) {
18
- const key = match[1];
19
- if (key !== '') {
20
- segments.push(key);
21
- }
22
- for (const bracket of match[2].matchAll(/\[(\d+)\]/g)) {
23
- segments.push(Number(bracket[1]));
24
- }
25
- } else {
26
- segments.push(part);
27
- }
28
- }
29
- return segments;
30
- }
31
-
32
- /** Lee el valor en `path`; `undefined` si algún tramo no existe. */
33
- export function getValue<T = unknown>(source: unknown, path: string): T | undefined {
34
- let current: unknown = source;
35
- for (const segment of parsePath(path)) {
36
- if (current === null || current === undefined || typeof current !== 'object') {
37
- return undefined;
38
- }
39
- if (typeof segment === 'number') {
40
- if (!Array.isArray(current)) {
41
- return undefined;
42
- }
43
- current = current[segment];
44
- } else {
45
- current = (current as Record<string, unknown>)[segment];
46
- }
47
- }
48
- return current as T;
49
- }
@@ -1,144 +0,0 @@
1
- /**
2
- * Ordenamiento con huecos (base.md §8).
3
- *
4
- * Reglas:
5
- * - Posiciones enteras con separación fija (paso 1000: 1000, 2000, 3000…).
6
- * - Mover entre dos vecinos → punto medio; solo cambia ese elemento.
7
- * - Mover al inicio → la mitad de la posición del primero.
8
- * - Mover al final → la del último + paso.
9
- * - Lista vacía → el paso.
10
- * - Si los vecinos quedan sin espacio (diferencia < 2) → rebalanceo:
11
- * se renumera toda la lista con el paso original conservando el orden
12
- * y luego se aplica el movimiento.
13
- * - Nuevos elementos → última posición + paso.
14
- *
15
- * El usuario nunca ve los números; la UI ordena por `position` ascendente.
16
- */
17
-
18
- /** Separación fija entre posiciones. */
19
- export const GAP = 1000;
20
-
21
- export interface PositionedItem {
22
- key: string;
23
- position: number;
24
- }
25
-
26
- export interface PositionChange {
27
- key: string;
28
- position: number;
29
- }
30
-
31
- export interface ReorderResult {
32
- /** `true` → hubo rebalanceo: `changes` contiene el lote completo renumerado. */
33
- rebalanced: boolean;
34
- /** Cambios a enviar: solo el elemento movido, o el lote completo. */
35
- changes: PositionChange[];
36
- }
37
-
38
- /** Punto medio entre dos vecinos (solo el elemento movido cambia). */
39
- export function moveBetween(prevPosition: number, nextPosition: number): number {
40
- return Math.floor((prevPosition + nextPosition) / 2);
41
- }
42
-
43
- /** Mover al inicio: la mitad de la posición del primero. */
44
- export function moveToStart(firstPosition: number): number {
45
- return Math.floor(firstPosition / 2);
46
- }
47
-
48
- /** Mover al final: la del último + paso. */
49
- export function moveToEnd(lastPosition: number): number {
50
- return lastPosition + GAP;
51
- }
52
-
53
- /** Posición de un elemento nuevo: al final (lista vacía → el paso). */
54
- export function appendPosition(items: PositionedItem[]): number {
55
- const sorted = sortItems(items);
56
- if (sorted.length === 0) {
57
- return GAP;
58
- }
59
- return moveToEnd(sorted[sorted.length - 1].position);
60
- }
61
-
62
- /** ¿Falta espacio para insertar en `targetIndex`? (base.md §8) */
63
- export function needsRebalance(
64
- items: PositionedItem[],
65
- movingKey: string,
66
- targetIndex: number,
67
- ): boolean {
68
- const without = sortItems(items.filter((item) => item.key !== movingKey));
69
- if (without.length === 0) {
70
- return false; // lista vacía → el paso siempre cabe
71
- }
72
- const index = clamp(targetIndex, 0, without.length);
73
- if (index === without.length) {
74
- return false; // al final → +paso siempre cabe
75
- }
76
- if (index === 0) {
77
- const first = without[0];
78
- return first.position - moveToStart(first.position) < 2;
79
- }
80
- const prev = without[index - 1];
81
- const next = without[index];
82
- return next.position - prev.position < 2;
83
- }
84
-
85
- /** Renumera la lista completa con el paso original, conservando el orden. */
86
- export function rebalance(items: PositionedItem[], gap: number = GAP): PositionChange[] {
87
- return sortItems(items).map((item, index) => ({
88
- key: item.key,
89
- position: (index + 1) * gap,
90
- }));
91
- }
92
-
93
- /**
94
- * Calcula el resultado de soltar `movingKey` en `targetIndex`
95
- * (índice que ocupará en la lista SIN el elemento movido, ya ordenada).
96
- */
97
- export function computeMove(
98
- items: PositionedItem[],
99
- movingKey: string,
100
- targetIndex: number,
101
- ): ReorderResult {
102
- const sorted = sortItems(items);
103
- if (!sorted.some((item) => item.key === movingKey)) {
104
- throw new Error(`Elemento no encontrado: ${movingKey}`);
105
- }
106
- const without = sorted.filter((item) => item.key !== movingKey);
107
- const index = clamp(targetIndex, 0, without.length);
108
-
109
- if (needsRebalance(sorted, movingKey, targetIndex)) {
110
- // Renumerar toda la lista y luego aplicar el movimiento.
111
- const renumbered = rebalance(without);
112
- const position = positionFor(renumbered, index);
113
- return {
114
- rebalanced: true,
115
- changes: [...renumbered, { key: movingKey, position }],
116
- };
117
- }
118
-
119
- return {
120
- rebalanced: false,
121
- changes: [{ key: movingKey, position: positionFor(without, index) }],
122
- };
123
- }
124
-
125
- function positionFor(without: PositionChange[], index: number): number {
126
- if (without.length === 0) {
127
- return GAP;
128
- }
129
- if (index === 0) {
130
- return moveToStart(without[0].position);
131
- }
132
- if (index === without.length) {
133
- return moveToEnd(without[without.length - 1].position);
134
- }
135
- return moveBetween(without[index - 1].position, without[index].position);
136
- }
137
-
138
- function sortItems(items: PositionedItem[]): PositionedItem[] {
139
- return [...items].sort((a, b) => a.position - b.position);
140
- }
141
-
142
- function clamp(value: number, min: number, max: number): number {
143
- return Math.min(Math.max(value, min), max);
144
- }
@@ -1,64 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
-
3
- import type { FieldSchema } from '../../core/models/schema.model';
4
- import { register } from '../../core/registry/render-registry';
5
- import { fieldDescriptors } from '../../fields/descriptors';
6
- import { seedValue, type SeedKind } from './seed';
7
-
8
- /**
9
- * D32 · R3.8 — la siembra vive en el descriptor, no en un `switch`.
10
- *
11
- * Tres cosas distintas, ninguna cosmética:
12
- *
13
- * 1. **Oro por descriptor** — cada tipo registrado siembra la forma que su
14
- * `seed` declara. Si alguien cambia `'number'` por `'string'` en un
15
- * descriptor, el tipo empieza a nacer en `''` y este test lo dice antes
16
- * que un formulario en producción.
17
- * 2. **Degradación** — un tipo fuera del catálogo siembra `undefined`, lo
18
- * mismo que hace el render (R1.10): no se pinta, no existe.
19
- * 3. **Fail-loud** — un descriptor registrado *sin* `seed` lanza, en vez de
20
- * sembrar `undefined` en silencio.
21
- *
22
- * El vitest aísla este fichero, así que el descriptor falso registrado en el
23
- * último test no se filtra al resto de la suite.
24
- */
25
- describe('seedValue — siembra declarada por el descriptor', () => {
26
- const FORMA: Record<SeedKind, unknown> = {
27
- string: '',
28
- number: null,
29
- boolean: false,
30
- array: [],
31
- // `group` con `fields: []` siembra un objeto vacío.
32
- recursive: {},
33
- };
34
-
35
- const campos = fieldDescriptors.filter((descriptor) => descriptor.kind === 'field');
36
-
37
- for (const descriptor of campos) {
38
- it(`«${descriptor.type}» siembra la forma «${descriptor.seed}»`, () => {
39
- const campo = {
40
- key: 'k',
41
- label: 'K',
42
- type: descriptor.type,
43
- fields: [],
44
- } as unknown as FieldSchema;
45
- expect(seedValue(campo)).toEqual(FORMA[descriptor.seed as SeedKind]);
46
- });
47
- }
48
-
49
- it('un tipo fuera del catálogo siembra `undefined` y no revienta', () => {
50
- const campo = { key: 'k', label: 'K', type: 'sombrero' } as unknown as FieldSchema;
51
- expect(seedValue(campo)).toBeUndefined();
52
- });
53
-
54
- it('un descriptor sin `seed` lanza en sembrar', () => {
55
- register('field', {
56
- kind: 'field',
57
- type: 'sin-siembra',
58
- since: '1.0',
59
- load: () => Promise.resolve(class Vacia {}),
60
- });
61
- const campo = { key: 'k', label: 'K', type: 'sin-siembra' } as unknown as FieldSchema;
62
- expect(() => seedValue(campo)).toThrow(/no declara `seed`/);
63
- });
64
- });
@@ -1,149 +0,0 @@
1
- import type { FieldSchema, GroupField } from '../../core/models/schema.model';
2
- import { get } from '../../core/registry/render-registry';
3
-
4
- /**
5
- * Forma del valor inicial que siembra un campo (D32 · R3.8).
6
- *
7
- * Son **todos** los valores posibles del dominio: un campo de formulario
8
- * nuevo nace como cadena, número, booleano, lista o como contenedor que
9
- * siembra sus hijos. Si un tipo llegara a necesitar otra forma, ampliar este
10
- * `type` obliga a compilar el `switch` de `seedValue` — que es exactamente
11
- * el fail-loud que la regla 4 pide.
12
- */
13
- export type SeedKind = 'string' | 'number' | 'boolean' | 'array' | 'recursive';
14
-
15
- /**
16
- * Siembra del modelo del formulario: un valor por defecto para CADA campo
17
- * declarado en el schema (base.md §10).
18
- *
19
- * Compartido entre `form-model` (crear/recargar) y los componentes de lista
20
- * (crear ítems nuevos con la forma de sus `itemFields`).
21
- */
22
-
23
- /**
24
- * Valor inicial cuando el schema no declara `default`.
25
- *
26
- * **D32 · ya no despacha por tipo.** El `switch` de 20 ramas que obligaba a
27
- * editar este fichero al añadir un campo — y que §0 contaba como tocar el
28
- * motor — pasa a resolver el nombre que declara el propio descriptor
29
- * (`RenderDescriptor.seed`). «Añadir un tipo» queda en carpeta + manifiesto
30
- * + unión: este archivo no se entera.
31
- *
32
- * Dos salidas distintas, ninguna silenciosa:
33
- *
34
- * · **tipo fuera del catálogo** ⇒ `undefined`, la misma degradación
35
- * controlada que el render (R1.10): el campo no se pinta, así que su
36
- * valor no existe;
37
- * · **descriptor sin `seed`** ⇒ lanza. Es un error de programación que
38
- * `core/registry/contract.spec.ts` detecta en CI antes de llegar acá.
39
- */
40
- export function seedValue(field: FieldSchema): unknown {
41
- const descriptor = get('field', field.type);
42
-
43
- if (!descriptor) {
44
- return undefined;
45
- }
46
- if (!descriptor.seed) {
47
- throw new Error(`[seed] el descriptor de "${field.type}" no declara \`seed\`.`);
48
- }
49
-
50
- switch (descriptor.seed) {
51
- case 'string':
52
- return '';
53
- case 'number':
54
- return null;
55
- case 'boolean':
56
- return false;
57
- case 'array':
58
- return [];
59
- case 'recursive':
60
- return seedHijos(field, descriptor.seed);
61
- }
62
- }
63
-
64
- /**
65
- * Siembra recursiva de un contenedor.
66
- *
67
- * El único `seed` recursivo del catálogo es `group`, pero el registro no lo
68
- * sabe — sólo lleva un nombre. El estrechado se comprueba aquí y **falla
69
- * ruidoso** si algún día un tipo declara `'recursive'` sin traer subcampos.
70
- */
71
- function seedHijos(field: FieldSchema, seed: 'recursive'): unknown {
72
- if (seed !== 'recursive' || !esGrupo(field)) {
73
- throw new Error(`[seed] "${field.type}" declara \`seed: 'recursive'\` pero no trae subcampos.`);
74
- }
75
- return seedFields(field.fields);
76
- }
77
-
78
- /** Estrechado de forma, no de despacho: no decide qué hacer, sólo accede. */
79
- function esGrupo(field: FieldSchema): field is GroupField {
80
- return field.type === 'group';
81
- }
82
-
83
- /** Valor sembrado de un campo, fusionando `default` con la forma del schema. */
84
- export function seedFieldValue(field: FieldSchema): unknown {
85
- if (field.default === undefined) {
86
- return seedValue(field);
87
- }
88
- if (field.type === 'group' && isRecord(field.default)) {
89
- // Un `default` de grupo podría traer claves incompletas: los hijos se
90
- // acceden por árbol, así que la forma completa es obligatoria.
91
- return { ...seedFields(field.fields), ...field.default };
92
- }
93
- if (field.type === 'list' && Array.isArray(field.default)) {
94
- return field.default.map((item) =>
95
- isRecord(item) ? { ...seedFields(field.itemFields), ...item } : item,
96
- );
97
- }
98
- return field.default;
99
- }
100
-
101
- /**
102
- * Siembra recursiva: los `group` anidan sus propios campos. Exportada porque
103
- * la lista crea sus ítems nuevos con la misma forma (`base.md §6`).
104
- */
105
- export function seedFields(fields: readonly FieldSchema[]): Record<string, unknown> {
106
- const model: Record<string, unknown> = {};
107
- for (const field of fields) {
108
- model[field.key] = seedFieldValue(field);
109
- }
110
- return model;
111
- }
112
-
113
- /**
114
- * Fusiona el registro leído con la forma sembrada del schema.
115
- *
116
- * El backend puede omitir claves (p. ej. un ítem guardado antes de que el
117
- * schema agregara un campo): sin esta fusión el árbol no tendría nodo para
118
- * ese campo y `childTree` lanzaría al renderizar. Lo ausente toma su
119
- * `default` y los extras del registro (p. ej. `position` de los ítems) se
120
- * conservan.
121
- */
122
- export function mergeRecord(
123
- fields: readonly FieldSchema[],
124
- record: Record<string, unknown>,
125
- ): Record<string, unknown> {
126
- const merged: Record<string, unknown> = {};
127
- for (const field of fields) {
128
- const incoming = record[field.key];
129
- if (field.type === 'group') {
130
- merged[field.key] = isRecord(incoming)
131
- ? mergeRecord(field.fields, incoming)
132
- : seedFieldValue(field);
133
- continue;
134
- }
135
- if (field.type === 'list') {
136
- const itemSeed = seedFields(field.itemFields);
137
- merged[field.key] = Array.isArray(incoming)
138
- ? incoming.map((item) => (isRecord(item) ? { ...itemSeed, ...item } : item))
139
- : seedFieldValue(field);
140
- continue;
141
- }
142
- merged[field.key] = incoming !== undefined ? incoming : seedFieldValue(field);
143
- }
144
- return merged;
145
- }
146
-
147
- export function isRecord(value: unknown): value is Record<string, unknown> {
148
- return typeof value === 'object' && value !== null && !Array.isArray(value);
149
- }
@@ -1,13 +0,0 @@
1
- /**
2
- * Normaliza texto a slug: minúsculas, sin acentos, separados por guiones.
3
- * Ej.: `Lomo Saltado Ñoño` → `lomo-saltado-nonio`.
4
- */
5
- export function slugify(value: string): string {
6
- return value
7
- .normalize('NFD')
8
- .replace(/[\u0300-\u036f]/g, '')
9
- .toLowerCase()
10
- .trim()
11
- .replace(/[^a-z0-9]+/g, '-')
12
- .replace(/^-+|-+$/g, '');
13
- }
@@ -1,41 +0,0 @@
1
- /**
2
- * Validadores puros sobre valores (base.md §4): longitud por palabras.
3
- * Devuelven `null` cuando el valor es válido o cuando no aplica.
4
- * (Longitud por caracteres, patrón y rango los aplica `@angular/forms/signals`
5
- * vía `form-schema.ts`: `minLengthRule`/`maxLengthRule`/`patternRule`/`minRule`.)
6
- *
7
- * Reglas comunes:
8
- * - Valor vacío (`undefined` / `null` / `''`) → `null`: la obligatoriedad
9
- * la maneja `required` aparte. Solo espacios NO cuenta como vacío.
10
- * - Valores de otro tipo → `null` (no validan aquí; los cubre el campo).
11
- *
12
- * Los mensajes se muestran tal cual bajo el campo (Fase 10), en español.
13
- */
14
-
15
- export function validateMinWords(value: unknown, min: number): string | null {
16
- const words = wordCount(value);
17
- if (words === null) {
18
- return null;
19
- }
20
- return words >= min ? null : `Debe tener al menos ${min} palabras.`;
21
- }
22
-
23
- export function validateMaxWords(value: unknown, max: number): string | null {
24
- const words = wordCount(value);
25
- if (words === null) {
26
- return null;
27
- }
28
- return words <= max ? null : `Como máximo ${max} palabras.`;
29
- }
30
-
31
- function isEmpty(value: unknown): boolean {
32
- return value === undefined || value === null || value === '';
33
- }
34
-
35
- /** Conteo de palabras; `null` si el valor no es texto o está vacío. */
36
- function wordCount(value: unknown): number | null {
37
- if (isEmpty(value) || typeof value !== 'string') {
38
- return null;
39
- }
40
- return value.trim().split(/\s+/).filter(Boolean).length;
41
- }