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

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,21 +0,0 @@
1
- import { ComponentFixture, TestBed } from '@angular/core/testing';
2
- import { GasAdminUi } from './gas-admin-ui';
3
-
4
- describe('GasAdminUi', () => {
5
- let component: GasAdminUi;
6
- let fixture: ComponentFixture<GasAdminUi>;
7
-
8
- beforeEach(async () => {
9
- await TestBed.configureTestingModule({
10
- imports: [GasAdminUi],
11
- }).compileComponents();
12
-
13
- fixture = TestBed.createComponent(GasAdminUi);
14
- component = fixture.componentInstance;
15
- await fixture.whenStable();
16
- });
17
-
18
- it('should create', () => {
19
- expect(component).toBeTruthy();
20
- });
21
- });
@@ -1,9 +0,0 @@
1
- import { Component } from '@angular/core';
2
-
3
- @Component({
4
- imports: [],
5
- selector: 'gas-gas-admin-ui',
6
- styles: ``,
7
- template: ` <p>gas-admin-ui works!</p> `,
8
- })
9
- export class GasAdminUi {}
@@ -1,9 +0,0 @@
1
- import type { LayoutDescriptor } from '../core/registry/render-registry';
2
-
3
- export const layoutDescriptors: readonly LayoutDescriptor[] = [
4
- { kind: 'layout', type: 'grid', since: '9.2' },
5
- { kind: 'layout', type: 'tabs', since: '9.2' },
6
- { kind: 'layout', type: 'sections', since: '9.2' },
7
- { kind: 'layout', type: 'steps', since: '9.2' },
8
- { kind: 'layout', type: 'columns', since: '9.2' },
9
- ];
@@ -1,167 +0,0 @@
1
- import { Component, computed, inject, input, resource } from '@angular/core';
2
- import { toObservable, toSignal } from '@angular/core/rxjs-interop';
3
- import { catchError, of, switchMap } from 'rxjs';
4
-
5
- import type { DataSource, ResourceSchema, WidgetSchema } from '../../core/models/schema.model';
6
- import { ApiService } from '../../core/services/api.service';
7
- import { DataSourceService, type SourceRow } from '../../core/services/data-source.service';
8
- import { EmptyState } from '../../shared/components/empty-state/empty-state';
9
- import { WidgetHost } from '../../widgets/widget-host/widget-host';
10
-
11
- /**
12
- * Panel de métricas — tercer `kind` del registry (refactormotor.md F4).
13
- *
14
- * Sólo lectura: no hay CRUD y los datos llegan de un endpoint declarativo
15
- * (Etapa 2, S4). Los widgets se declaran en `widgets` del schema — no en
16
- * `fields`, porque un KPI no es un campo (ver `ResourceSchema.widgets`).
17
- *
18
- * Dos formas de dato, la que declare cada widget (F8 · R6.5):
19
- *
20
- * - **payload**: el `key` del widget es su clave en la respuesta del
21
- * endpoint; `source: { kind: 'payload' }` lee la respuesta entera.
22
- * - **fuente declarada** (`source: { resource, view?, params? }`): el widget
23
- * pide sus filas al `DataSourceService` y deja de depender de que un
24
- * handler haya armado `data[key]`. Acá se piden TODAS juntas, así que un
25
- * panel con seis fuentes iguales hace una vuelta, no seis (la caché del
26
- * servicio es compartida con relations y selects).
27
- */
28
- @Component({
29
- selector: 'app-dashboard',
30
- imports: [EmptyState, WidgetHost],
31
- template: `
32
- <header class="mb-6">
33
- <h1 class="font-display text-2xl font-semibold">{{ schema().labelPlural }}</h1>
34
- <p class="text-sm text-neutral">Dashboard · {{ widgets().length }} widgets</p>
35
- </header>
36
-
37
- @if (falloFuentes()) {
38
- <!-- Degradación visible (F9): sin este aviso el fallo de una fuente
39
- se confundiría con «el panel no tiene datos». -->
40
- <p class="mb-4 text-sm text-danger" role="alert">
41
- No se pudieron cargar los datos de algunos widgets.
42
- </p>
43
- }
44
-
45
- @if (widgets().length === 0) {
46
- <app-empty-state
47
- title="Sin widgets declarados"
48
- message="Los widgets se declaran en la propiedad widgets del schema del dashboard."
49
- />
50
- } @else {
51
- <div class="grid grid-cols-12 gap-4">
52
- @for (widget of widgets(); track widget.key) {
53
- <app-widget-host [widget]="widget" [data]="datum(widget)" [loading]="cargando()" />
54
- }
55
- </div>
56
- }
57
- `,
58
- })
59
- export class Dashboard {
60
- private readonly api = inject(ApiService, { optional: true });
61
- private readonly ds = inject(DataSourceService);
62
-
63
- /** Descriptor del dashboard (lo resuelve `ResourcePage` contra el registry). */
64
- readonly schema = input.required<ResourceSchema>();
65
-
66
- /**
67
- * Respuesta del endpoint de métricas indexada por `key` de widget.
68
- * Si se pasa explícitamente (como en tests con fixtures), se usa directamente;
69
- * de lo contrario se obtienen los datos de forma reactiva desde el endpoint `get`.
70
- */
71
- readonly data = input<Record<string, unknown> | null>(null);
72
-
73
- private readonly fetchedData = toSignal(
74
- toObservable(this.schema).pipe(
75
- switchMap((schema) => {
76
- const getEndpoint = schema.endpoint?.get;
77
- // `of({})` = SIN get contratado: ya hay respuesta (vacía). El
78
- // `null` inicial del signal en cambio marca «todavía viaja».
79
- if (!getEndpoint || !this.api) return of<Record<string, unknown>>({});
80
- return this.api
81
- .request<Record<string, unknown>>('GET', getEndpoint)
82
- .pipe(catchError(() => of<Record<string, unknown>>({})));
83
- }),
84
- ),
85
- { initialValue: null },
86
- );
87
-
88
- protected readonly effectiveData = computed<Record<string, unknown>>(() => {
89
- const override = this.data();
90
- if (override !== null && override !== undefined) return override;
91
- return this.fetchedData() ?? {};
92
- });
93
-
94
- protected readonly widgets = computed(() => this.schema().widgets ?? []);
95
-
96
- // ── Fuentes declaradas (F8 · R6.5) ──────────────────────────────────────
97
-
98
- /**
99
- * Claves de los widgets con fuente declarada, en una cadena: es el
100
- * `params` del `resource` y sólo cambia cuando cambia el panel. `''`
101
- * (ninguna fuente) ⇒ `undefined` ⇒ el resource queda idle y no pide nada.
102
- */
103
- private readonly clavesFuente = computed(() =>
104
- this.widgets()
105
- .map((widget) => (esFuente(widget.source) ? widget.key : ''))
106
- .filter((key) => key !== '')
107
- .join('|'),
108
- );
109
-
110
- /**
111
- * Filas de todos los widgets con `source`, pedidas de una sola vez.
112
- *
113
- * Cada fila queda bajo `widget.key`, que es el mismo contrato de lectura
114
- * que tiene el payload: `datum()` devuelve filas cuando hay fuente y la
115
- * clave de siempre cuando no, y el descriptor del widget traduce la forma
116
- * que necesita.
117
- */
118
- private readonly fuentes = resource({
119
- params: () => (this.clavesFuente() === '' ? undefined : this.clavesFuente()),
120
- loader: async () => {
121
- const filas: Record<string, SourceRow[]> = {};
122
- for (const widget of this.widgets()) {
123
- if (!esFuente(widget.source)) continue;
124
- filas[widget.key] = await this.ds.rows(widget.source);
125
- }
126
- return filas;
127
- },
128
- });
129
-
130
- /** ¿Alguna fuente del panel falló? (`status()` no tira; `value()` sí.) */
131
- protected readonly falloFuentes = computed(() => this.fuentes.status() === 'error');
132
-
133
- /**
134
- * Estado de carga del panel — mientras dure, cada tarjeta reserva su
135
- * espacio con skeleton (`cargar ≠ vacío`, doc/ux-ui-mobile.md §estados).
136
- * Cubre LOS dos caminos de dato: el payload (`null` inicial = sin
137
- * respuesta todavía) y las fuentes declaradas (`resource` en loading;
138
- * con params vacíos queda idle, que NO es carga).
139
- */
140
- protected readonly cargando = computed(() => {
141
- const payloadViaja = this.data() === null && this.fetchedData() === null;
142
- const fuentesViajan = this.fuentes.status() === 'loading';
143
- return payloadViaja || fuentesViajan;
144
- });
145
-
146
- /** `null` explícito cuando la clave no vino: el widget muestra su vacío. */
147
- protected datum(widget: WidgetSchema): unknown {
148
- // Fuente declarada: el dato son SUS filas, no una clave del payload.
149
- if (esFuente(widget.source)) {
150
- // `value()` del resource TIRA en estado error (contract de Angular):
151
- // se mira el estado antes de leerlo. En carga devuelve `null` igual
152
- // que el camino de payload, que también arranca vacío.
153
- return this.fuentes.status() === 'error'
154
- ? null
155
- : (this.fuentes.value()?.[widget.key] ?? null);
156
- }
157
- const allData = this.effectiveData();
158
- // `source` lo declara el schema: el orquestador no sabe qué tipo es
159
- // ni qué claves compone cada widget.
160
- return widget.source?.kind === 'payload' ? allData : (allData[widget.key] ?? null);
161
- }
162
- }
163
-
164
- /** ¿Este widget declara una fuente (`{ resource, … }`) y no el payload? */
165
- function esFuente(source: WidgetSchema['source']): source is DataSource {
166
- return source !== undefined && source !== null && 'resource' in source;
167
- }
@@ -1,333 +0,0 @@
1
- import { ComponentFixture, TestBed } from '@angular/core/testing';
2
- import { provideRouter, Router } from '@angular/router';
3
- import { NEVER, of, throwError } from 'rxjs';
4
- import { describe, expect, it, beforeEach, vi } from 'vitest';
5
-
6
- import type { ResourceSchema } from '../../core/models/schema.model';
7
- import { ActionService } from '../../actions/action-service';
8
- import { ApiService } from '../../core/services/api.service';
9
- import { API_URL } from '../../core/tokens';
10
- import { DetailView } from './detail-view';
11
-
12
- describe('DetailView', () => {
13
- let fixture: ComponentFixture<DetailView>;
14
-
15
- const mockSchema: ResourceSchema = {
16
- id: 'orders',
17
- label: 'Pedido',
18
- labelPlural: 'Pedidos',
19
- kind: 'collection',
20
- endpoint: { list: '/admin/orders', get: '/admin/orders/{key}' },
21
- keyField: 'ref',
22
- titleField: 'customer_name',
23
- listColumns: [],
24
- fields: [
25
- { key: 'ref', label: 'Referencia', type: 'text' },
26
- { key: 'customer_name', label: 'Cliente', type: 'text' },
27
- { key: 'pickup_date', label: 'Fecha Retiro', type: 'date' },
28
- {
29
- key: 'status',
30
- label: 'Estado',
31
- type: 'select',
32
- options: [
33
- { value: 'PENDIENTE', label: 'Pendiente' },
34
- { value: 'ENTREGADO', label: 'Entregado' },
35
- ],
36
- },
37
- ],
38
- detail: {
39
- enabled: true,
40
- headerFields: ['ref', 'status'],
41
- allowEdit: true,
42
- allowDelete: false,
43
- },
44
- };
45
-
46
- const mockRecord = {
47
- ref: 'ORD-42',
48
- customer_name: 'Ana García',
49
- pickup_date: '2026-10-10',
50
- status: 'PENDIENTE',
51
- };
52
-
53
- const getSpy = vi.fn();
54
-
55
- beforeEach(async () => {
56
- getSpy.mockReset();
57
- getSpy.mockImplementation(() => of(null));
58
- await TestBed.configureTestingModule({
59
- imports: [DetailView],
60
- providers: [
61
- {
62
- provide: ApiService,
63
- useValue: {
64
- get: getSpy,
65
- request: () => of(null),
66
- },
67
- },
68
- // `AuthService` pide `API_URL` (convención de specs, R7.5)
69
- { provide: API_URL, useValue: '/api' },
70
- // R8.8: `DetailView` inyecta `Router` (trigger → confirmación +
71
- // ruta) — convención de list-view.quick-edit.spec.
72
- provideRouter([]),
73
- ],
74
- }).compileComponents();
75
- fixture = TestBed.createComponent(DetailView);
76
- });
77
-
78
- /**
79
- * Monta la vista y espera los display del registro.
80
- *
81
- * `fixture.whenStable()` no basta: el `load()` de cada descriptor es un
82
- * `import()` ajeno al rastreo de Angular. Se espera acotadamente mientras
83
- * quede algún `<app-skeleton>`; si un componente nunca monta, la espera se
84
- * agota y falla la aserción del test (acotación, no espera infinita).
85
- */
86
- async function montar(fixture: ComponentFixture<DetailView>): Promise<void> {
87
- fixture.detectChanges();
88
- await fixture.whenStable();
89
- for (
90
- let intento = 0;
91
- intento < 100 && fixture.nativeElement.querySelector('app-skeleton');
92
- intento++
93
- ) {
94
- fixture.detectChanges();
95
- await new Promise((resolve) => setTimeout(resolve, 1));
96
- }
97
- fixture.detectChanges();
98
- }
99
-
100
- it('1. renderiza la cabecera con el título del registro y los badges de headerFields', async () => {
101
- fixture.componentRef.setInput('schema', mockSchema);
102
- fixture.componentRef.setInput('record', mockRecord);
103
- await montar(fixture);
104
-
105
- const root = fixture.nativeElement as HTMLElement;
106
- expect(root.querySelector('h1')?.textContent?.trim()).toBe('Ana García');
107
- // badge de ref y status en la cabecera
108
- expect(root.textContent).toContain('ORD-42');
109
- expect(root.textContent).toContain('Pendiente');
110
- // Los headerFields salen como chips (R4.2): `ref` en neutral y
111
- // `status` en la clase de estado que ya usaba la ficha.
112
- const cabeceras = root.querySelectorAll('header app-badge');
113
- expect(cabeceras.length, 'deben ser 2 los chips de la cabecera').toBe(2);
114
- expect(cabeceras[0].className).toContain('bg-neutral');
115
- expect(cabeceras[1].className).toContain('bg-accent/20');
116
- });
117
-
118
- it('2. renderiza las secciones de campos con sus valores', async () => {
119
- fixture.componentRef.setInput('schema', mockSchema);
120
- fixture.componentRef.setInput('record', mockRecord);
121
- await montar(fixture);
122
-
123
- const root = fixture.nativeElement as HTMLElement;
124
- expect(root.textContent).toContain('Ana García');
125
- expect(root.textContent).toContain('2026');
126
- // label del campo
127
- expect(root.textContent).toContain('Referencia');
128
- expect(root.textContent).toContain('Cliente');
129
- });
130
-
131
- it('3. emite el evento edit al hacer clic en el botón Editar', () => {
132
- fixture.componentRef.setInput('schema', mockSchema);
133
- fixture.componentRef.setInput('record', mockRecord);
134
- fixture.detectChanges();
135
-
136
- let emitted: Record<string, unknown> | null = null;
137
- fixture.componentInstance.edit.subscribe((rec) => {
138
- emitted = rec as Record<string, unknown>;
139
- });
140
-
141
- const root = fixture.nativeElement as HTMLElement;
142
- const editBtn = Array.from(root.querySelectorAll<HTMLButtonElement>('button[app-button]')).find(
143
- (b) => b.textContent?.trim().includes('Editar'),
144
- );
145
- expect(editBtn, 'debe existir el botón Editar').toBeDefined();
146
- editBtn!.click();
147
- fixture.detectChanges();
148
-
149
- expect(emitted).toEqual(mockRecord);
150
- });
151
-
152
- it('4. emite el evento back al hacer clic en el botón Volver', () => {
153
- fixture.componentRef.setInput('schema', mockSchema);
154
- fixture.componentRef.setInput('record', mockRecord);
155
- fixture.detectChanges();
156
-
157
- let emitted = false;
158
- fixture.componentInstance.back.subscribe(() => {
159
- emitted = true;
160
- });
161
-
162
- const root = fixture.nativeElement as HTMLElement;
163
- const backBtn = Array.from(root.querySelectorAll<HTMLButtonElement>('button[app-button]')).find(
164
- (b) => b.textContent?.trim().includes('Volver'),
165
- );
166
- expect(backBtn, 'debe existir el botón Volver').toBeDefined();
167
- backBtn!.click();
168
- fixture.detectChanges();
169
-
170
- expect(emitted).toBe(true);
171
- });
172
-
173
- it('5. renderiza secciones de historial (tipo list) cuando existen', async () => {
174
- const listSchema: ResourceSchema = {
175
- ...mockSchema,
176
- fields: [
177
- ...mockSchema.fields,
178
- {
179
- key: 'history',
180
- label: 'Historial',
181
- type: 'list',
182
- itemFields: [
183
- { key: 'action', label: 'Acción', type: 'text' },
184
- { key: 'detail', label: 'Detalle', type: 'text' },
185
- ],
186
- },
187
- ],
188
- };
189
- const recordWithHistory = {
190
- ...mockRecord,
191
- history: [{ action: 'PEDIDO_CREADO', detail: 'Pedido registrado' }],
192
- };
193
- fixture.componentRef.setInput('schema', listSchema);
194
- fixture.componentRef.setInput('record', recordWithHistory);
195
- await montar(fixture);
196
-
197
- const root = fixture.nativeElement as HTMLElement;
198
- expect(root.textContent).toContain('Pedido registrado');
199
- });
200
-
201
- it('6. R8.8: renderiza el botón de un trigger y lo dispara vía actionService', async () => {
202
- const triggerSchema: ResourceSchema = {
203
- ...mockSchema,
204
- actions: [
205
- {
206
- id: 'regenerate_pin',
207
- type: 'trigger',
208
- name: 'regenerate-pin',
209
- label: 'Regenerar PIN',
210
- },
211
- ],
212
- };
213
- fixture.componentRef.setInput('schema', triggerSchema);
214
- fixture.componentRef.setInput('record', mockRecord);
215
- await montar(fixture);
216
-
217
- const root = fixture.nativeElement as HTMLElement;
218
- const triggerBtn = Array.from(
219
- root.querySelectorAll<HTMLButtonElement>('button[app-button]'),
220
- ).find((b) => b.textContent?.trim() === 'Regenerar PIN');
221
- expect(triggerBtn, 'debe existir el botón Regenerar PIN').toBeDefined();
222
-
223
- // El clic delega en actionService.run (la confirmación y la ruta son
224
- // cosa del descriptor, no de la vista — R3.11).
225
- const runSpy = vi
226
- .spyOn(TestBed.inject(ActionService), 'run')
227
- .mockResolvedValue({ ok: true, reload: true });
228
- triggerBtn!.click();
229
- fixture.detectChanges();
230
- await fixture.whenStable();
231
-
232
- expect(runSpy).toHaveBeenCalledTimes(1);
233
- const [action, request] = runSpy.mock.calls[0];
234
- expect(action).toMatchObject({ id: 'regenerate_pin', name: 'regenerate-pin' });
235
- expect(request.resource).toBe('orders');
236
- expect(request.keyField).toBe('ref');
237
- });
238
-
239
- it('7. mientras viaja el get, reserva el espacio con skeleton (cargar ≠ vacío)', () => {
240
- // Regresión del «renderizado completo pero vacío»: con el get lento
241
- // (Apps Script ~1s) el detalle pintaba la fila parcial con los campos
242
- // pesados en `—`. Ahora la región de secciones queda en busy con
243
- // skeletons con la forma de las tarjetas.
244
- getSpy.mockImplementation(() => NEVER);
245
-
246
- fixture.componentRef.setInput('schema', mockSchema);
247
- fixture.componentRef.setInput('record', mockRecord);
248
- fixture.detectChanges();
249
-
250
- const root = fixture.nativeElement as HTMLElement;
251
- expect(root.querySelector('[aria-busy="true"] app-skeleton'), 'skeleton visible').toBeTruthy();
252
- // Las etiquetas de las secciones NO se pintan hasta que llegue el registro.
253
- expect(root.textContent).not.toContain('Fecha Retiro');
254
- // La cabecera sí: son datos reales de la fila de la lista.
255
- expect(root.textContent).toContain('ORD-42');
256
- });
257
-
258
- it('8. estado de error: ofrece reintento y al reintentar pinta el registro', async () => {
259
- getSpy.mockImplementationOnce(() => throwError(() => new Error('500')));
260
- getSpy.mockImplementationOnce(() => of({ ...mockRecord, pickup_date: '2026-10-12' }));
261
-
262
- fixture.componentRef.setInput('schema', mockSchema);
263
- fixture.componentRef.setInput('record', mockRecord);
264
- await montar(fixture);
265
-
266
- const root = fixture.nativeElement as HTMLElement;
267
- expect(root.textContent).toContain('No se pudo cargar el registro');
268
-
269
- const retryBtn = Array.from(
270
- root.querySelectorAll<HTMLButtonElement>('button[app-button]'),
271
- ).find((b) => b.textContent?.trim().includes('Reintentar'));
272
- expect(retryBtn, 'debe existir el botón Reintentar').toBeDefined();
273
- retryBtn!.click();
274
- await montar(fixture);
275
-
276
- // El date se pinta formateado por render-host, no en crudo.
277
- expect(root.textContent).toContain('12 oct. 2026');
278
- expect(root.textContent).not.toContain('No se pudo cargar el registro');
279
- });
280
-
281
- // ── R9.9 · D4 — target load error recovery ──
282
-
283
- it('9. D4: el estado de error ofrece «Volver» junto a «Reintentar» y navega de vuelta', async () => {
284
- getSpy.mockImplementationOnce(() => throwError(() => new Error('boom')));
285
- fixture.componentRef.setInput('schema', mockSchema);
286
- fixture.componentRef.setInput('record', mockRecord);
287
- await montar(fixture);
288
-
289
- const root = fixture.nativeElement as HTMLElement;
290
- expect(root.textContent).toContain('No se pudo cargar el registro');
291
- // El estado de error es un `app-empty-state` con ambas salidas DENTRO
292
- // (el header también tiene «Volver», así que se busca dentro del slot).
293
- const volver = Array.from(
294
- root.querySelectorAll<HTMLButtonElement>('app-empty-state button[app-button]'),
295
- ).find((b) => b.textContent?.trim().includes('Volver'));
296
- expect(volver, 'debe existir el botón Volver en el estado de error').toBeDefined();
297
-
298
- const router = TestBed.inject(Router);
299
- const navegar = vi.spyOn(router, 'navigate');
300
- volver!.click();
301
- await fixture.whenStable();
302
- expect(navegar).toHaveBeenCalled();
303
- });
304
-
305
- it('10. D4: la cabecera oculta Editar/Eliminar mientras el registro está en error', async () => {
306
- getSpy.mockImplementationOnce(() => throwError(() => new Error('boom')));
307
- fixture.componentRef.setInput('schema', mockSchema);
308
- fixture.componentRef.setInput('record', mockRecord);
309
- await montar(fixture);
310
-
311
- const root = fixture.nativeElement as HTMLElement;
312
- expect(root.textContent).toContain('No se pudo cargar el registro');
313
- expect(root.textContent).not.toContain('Editar');
314
- // Reintentar ⇒ éxito ⇒ la acción vuelve a existir
315
- getSpy.mockImplementationOnce(() => of({ ...mockRecord }));
316
- Array.from(root.querySelectorAll<HTMLButtonElement>('button[app-button]'))
317
- .find((b) => b.textContent?.trim().includes('Reintentar'))!
318
- .click();
319
- await montar(fixture);
320
- expect((fixture.nativeElement as HTMLElement).textContent).toContain('Editar');
321
- });
322
-
323
- it('11. D4: el error original queda retenido con identidad intacta (diagnóstico)', async () => {
324
- const fallo = new Error('boom de red');
325
- getSpy.mockImplementationOnce(() => throwError(() => fallo));
326
- fixture.componentRef.setInput('schema', mockSchema);
327
- fixture.componentRef.setInput('record', mockRecord);
328
- await montar(fixture);
329
-
330
- // Identity assert: el MISMO objeto, no una copia ni un string mapeado.
331
- expect(fixture.componentInstance.errorDeCarga()).toBe(fallo);
332
- });
333
- });