@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,570 +0,0 @@
1
- import { Component, computed, inject, input, output, signal } from '@angular/core';
2
- import { toObservable, toSignal } from '@angular/core/rxjs-interop';
3
- import { Router } from '@angular/router';
4
-
5
- import { ViewNavigationService } from '../../core/view-navigation/view-navigation.service';
6
- import { catchError, combineLatest, map, of, switchMap } from 'rxjs';
7
-
8
- import {
9
- LucideArrowLeft,
10
- LucideExternalLink,
11
- LucidePencil,
12
- LucideRotateCw,
13
- LucideTrash2,
14
- } from '@lucide/angular';
15
- import type {
16
- CopyShareAction,
17
- DetailViewSchema,
18
- FieldSchema,
19
- ResourceAction,
20
- ResourceSchema,
21
- TriggerAction,
22
- } from '../../core/models/schema.model';
23
- import {
24
- isShareAction,
25
- isTriggerAction,
26
- resolveShare,
27
- type ResolvedShare,
28
- } from '../../actions/action-registry';
29
- import { ActionService } from '../../actions/action-service';
30
- import { RenderHost } from '../../core/registry/render-host';
31
- import { ApiService } from '../../core/services/api.service';
32
- import { AuthService } from '../../core/services/auth.service';
33
- import { ConfigService } from '../../core/services/config.service';
34
- import { NotificationService } from '../../core/services/notification.service';
35
- import { Button } from '../../shared/components/button/button';
36
- import { CopyShare } from '../../shared/components/copy-share/copy-share';
37
- import { CopyButton } from '../../shared/components/copy-button/copy-button';
38
- import { EmptyState } from '../../shared/components/empty-state/empty-state';
39
- import { Skeleton } from '../../shared/components/skeleton/skeleton';
40
- import { getValue } from '../../shared/utils/field-path';
41
-
42
- type Row = Record<string, unknown>;
43
-
44
- /**
45
- * Estado etiquetado del `get` del registro.
46
- *
47
- * `pending` distingue «todavía viaja» de «terminó sin datos» (sin
48
- * `endpoint.get` contratado o sin key): antes ambos eran `null` y el
49
- * detalle pintaba la fila parcial de la lista como si fuera todo, con los
50
- * campos pesados en `—` que después mutaban solos (cargar ≠ vacío,
51
- * doc/ux-ui-mobile.md §estados de UI).
52
- */
53
- type FetchState =
54
- | { phase: 'pending' }
55
- | { phase: 'done'; data: Row | null }
56
- /** D4: el error ORIGINAL se retiene para diagnóstico (identity intacta). */
57
- | { phase: 'error'; error: unknown };
58
-
59
- /**
60
- * Campo ya resuelto contra el registro, **sin formatear**.
61
- *
62
- * Antes de R4.2 este objeto traía `value` + `kind` + `badgeKind`, que era
63
- * como `detail-view` derivaba a mano qué pintar (`image | badge | text`).
64
- * Hoy sólo aporta agrupación —clave, etiqueta, campo y valor crudo— y el
65
- * pintado lo decide el registro vía `<app-render-host mode="display">`.
66
- */
67
- interface FieldValue {
68
- key: string;
69
- label: string;
70
- /** Campo del schema (o un `text` sintético si la clave no existe). */
71
- field: FieldSchema;
72
- /** Valor crudo del registro. */
73
- raw: unknown;
74
- }
75
-
76
- interface DetailSection {
77
- id: string;
78
- label: string;
79
- fields: FieldValue[];
80
- }
81
-
82
- /**
83
- * Vista de detalle genérica: muestra los campos de un registro en modo lectura.
84
- * Incluye cabecera estilizada, timeline interactivo para listas anidadas
85
- * (como history) y barra de acciones.
86
- *
87
- * **R4.2 · F3 (`refactormotor.md`):** dejó de derivar `kind` a mano y de
88
- * tener plantilla propia de campo. Agrupa (`sections()`, `resolveFieldValue()`,
89
- * el `<dt>`/`<dd>`, el bloque de historial y `hasLargeContent()`) y el valor
90
- * lo pinta el registro con `mode="display"` — la misma tabla por tipo que
91
- * cualquier otra superficie. Lo único que queda por fuera son las secciones
92
- * que no son campos: cabecera, `copy-share` y acciones.
93
- */
94
- @Component({
95
- selector: 'app-detail-view',
96
- imports: [
97
- Button,
98
- CopyShare,
99
- CopyButton,
100
- EmptyState,
101
- LucideArrowLeft,
102
- LucideExternalLink,
103
- LucidePencil,
104
- LucideRotateCw,
105
- LucideTrash2,
106
- RenderHost,
107
- Skeleton,
108
- ],
109
- template: `
110
- <div class="space-y-6">
111
- <!-- ── Cabecera Principal ── -->
112
- <header
113
- class="flex flex-wrap items-start justify-between gap-4 rounded-2xl border border-neutral/15 bg-surface p-6 shadow-xs"
114
- >
115
- <div class="space-y-2">
116
- <div class="flex flex-wrap items-center gap-2.5">
117
- <h1 class="font-display text-2xl font-bold tracking-tight text-neutral-light">
118
- {{ title() }}
119
- </h1>
120
- @for (campo of headerFields(); track campo.key) {
121
- @if (!vacio(campo.raw)) {
122
- <!-- La cabecera siempre mostró los headerFields como chips:
123
- el matiz viaja al host, no un @switch por tipo acá. -->
124
- <app-render-host
125
- mode="display"
126
- [chip]="true"
127
- [type]="campo.field.type"
128
- [config]="campo.field"
129
- [value]="campo.raw"
130
- />
131
- }
132
- }
133
- </div>
134
- <p class="text-sm text-neutral">
135
- {{ schema().label }} · Identificador:
136
- <span class="font-mono font-medium text-neutral-light">{{ recordKey() }}</span>
137
- </p>
138
- </div>
139
-
140
- <div class="flex flex-wrap items-center gap-2.5">
141
- <button app-button variant="outline" type="button" (click)="back.emit()">
142
- <svg lucideArrowLeft size="16" />
143
- Volver
144
- </button>
145
- @if (detail().allowEdit !== false && status() !== 'error') {
146
- <button app-button variant="primary" type="button" (click)="edit.emit(record())">
147
- <svg lucidePencil size="16" />
148
- Editar
149
- </button>
150
- }
151
- @if (detail().allowDelete !== false && status() !== 'error') {
152
- <button app-button variant="danger" type="button" (click)="delete.emit(record())">
153
- <svg lucideTrash2 size="16" />
154
- Eliminar
155
- </button>
156
- }
157
- </div>
158
- </header>
159
-
160
- <!-- ── Acciones Destacadas del Registro (si existen) ── -->
161
- @if (copyShareActions().length > 0 || triggerActions().length > 0) {
162
- <section
163
- class="rounded-2xl border border-primary/25 bg-gradient-to-r from-primary/10 via-primary/5 to-transparent p-5 shadow-xs"
164
- >
165
- <div class="mb-3 flex items-center gap-2">
166
- <svg lucideExternalLink size="16" class="text-primary" />
167
- <h2 class="text-sm font-semibold text-primary">Acciones del Registro</h2>
168
- </div>
169
- <div class="flex flex-col gap-3 sm:flex-row sm:flex-wrap">
170
- @for (action of copyShareActions(); track action.id) {
171
- <div class="flex-1 min-w-[280px]">
172
- @let share = shareOf(action);
173
- <app-copy-share
174
- [url]="share.url"
175
- [shareText]="share.shareText"
176
- [label]="action.label"
177
- />
178
- </div>
179
- }
180
- @for (action of triggerActions(); track action.id) {
181
- <button app-button variant="outline" type="button" (click)="runTrigger(action)">
182
- {{ action.label }}
183
- </button>
184
- }
185
- </div>
186
- </section>
187
- }
188
-
189
- <!-- ── Secciones de Datos ── -->
190
- @switch (status()) {
191
- @case ('loading') {
192
- <!-- Skeleton con la forma de las tarjetas de sección: reserva el
193
- espacio (sin layout jump) y distingue «cargando» de «vacío».
194
- La cabecera y las acciones de arriba sí se pintan ya: son la
195
- fila de la lista, datos reales que no están en disputa. -->
196
- <div aria-busy="true" class="grid grid-cols-1 gap-6 lg:grid-cols-2">
197
- @for (placeholder of [0, 1]; track placeholder) {
198
- <section
199
- class="rounded-2xl border border-neutral/15 bg-surface shadow-xs overflow-hidden"
200
- >
201
- <header class="border-b border-neutral/10 bg-neutral/5 px-5 py-3.5">
202
- <app-skeleton [lines]="1" [height]="14" width="30%" />
203
- </header>
204
- <div class="p-5">
205
- <app-skeleton [lines]="6" [height]="44" />
206
- </div>
207
- </section>
208
- }
209
- </div>
210
- }
211
- @case ('error') {
212
- <app-empty-state
213
- title="No se pudo cargar el registro"
214
- message="Revisa tu conexión e intenta de nuevo."
215
- >
216
- <button app-button variant="outline" type="button" (click)="retry()">
217
- <svg lucideRotateCw size="16" />
218
- Reintentar
219
- </button>
220
- <button app-button variant="outline" type="button" (click)="volverDeError()">
221
- <svg lucideArrowLeft size="16" />
222
- Volver
223
- </button>
224
- </app-empty-state>
225
- }
226
- @case ('ready') {
227
- <div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
228
- @for (section of sections(); track section.id) {
229
- <section
230
- class="rounded-2xl border border-neutral/15 bg-surface shadow-xs overflow-hidden flex flex-col"
231
- [class.lg:col-span-2]="hasLargeContent(section)"
232
- >
233
- <header class="border-b border-neutral/10 bg-neutral/5 px-5 py-3.5">
234
- <h2 class="text-sm font-semibold tracking-wide text-neutral-light uppercase">
235
- {{ section.label }}
236
- </h2>
237
- </header>
238
-
239
- <div class="p-5 flex-1 space-y-4">
240
- <!-- Grid para campos regulares -->
241
- @if (regularFields(section).length > 0) {
242
- <dl class="grid grid-cols-1 gap-x-6 gap-y-4 lg:grid-cols-12">
243
- @for (campo of regularFields(section); track campo.key) {
244
- <div class="space-y-1">
245
- <dt class="col-span-12 sm:col-span-12 lg:col-span-3 text-xs font-medium text-neutral">{{ campo.label }}</dt>
246
- <dd class="col-span-12 sm:col-span-12 lg:col-span-{{ colSpanFor(campo.field.width) }} text-sm font-medium text-neutral-light break-words">
247
- <app-render-host
248
- mode="display"
249
- [type]="campo.field.type"
250
- [config]="campo.field"
251
- [value]="campo.raw"
252
- />
253
- @if (isCopyable(campo.field.type) && campo.raw !== null && campo.raw !== undefined && campo.raw !== '') {
254
- <app-copy-button [value]="campo.raw" />
255
- }
256
- </dd>
257
- </div>
258
- }
259
- </dl>
260
- }
261
-
262
- <!-- Renderizado de listas anidadas (Timeline de eventos / items) -->
263
- @for (campo of listFields(section); track campo.key) {
264
- <div class="pt-2">
265
- <h3 class="mb-3 text-xs font-semibold text-neutral uppercase">
266
- {{ campo.label }}
267
- </h3>
268
- <app-render-host
269
- mode="display"
270
- [type]="campo.field.type"
271
- [config]="campo.field"
272
- [value]="campo.raw"
273
- />
274
- </div>
275
- }
276
- </div>
277
- </section>
278
- }
279
- </div>
280
- }
281
- }
282
- </div>
283
- `,
284
- })
285
- export class DetailView {
286
- private readonly api = inject(ApiService, { optional: true });
287
- private readonly actionService = inject(ActionService);
288
- private readonly auth = inject(AuthService);
289
- // R8.8: el trigger (Regenerar PIN) confirma vía toast y dispara la
290
- // recarga del detalle — el mismo puerto que ya usa list-view.
291
- private readonly router = inject(Router);
292
- private readonly nav = inject(ViewNavigationService);
293
- private readonly notifications = inject(NotificationService);
294
- private readonly configService = inject(ConfigService);
295
-
296
- constructor() {
297
- // Este detalle presenta `<app-copy-share>` sin pasar por `ActionService`:
298
- // si el load del bootstrap falló, el mensaje resolvería a «sólo la
299
- // URL». Reintentamos acá —con la sesión ya iniciada—; `globalConfig` es
300
- // signal, así que `shareOf` se recalcula cuando llega.
301
- void this.configService.ensureLoaded();
302
- }
303
-
304
- readonly schema = input.required<ResourceSchema>();
305
- readonly record = input.required<Row>();
306
-
307
- readonly edit = output<Row>();
308
- readonly back = output<void>();
309
- readonly delete = output<Row>();
310
-
311
- /**
312
- * R8.8: contador que fuerza la relectura del registro. Una acción de
313
- * dominio muta la fila en el back (el PIN regenerado vive en la hoja);
314
- * sin este tick, `toObservable(this.record)` no emite (la referencia no
315
- * cambió) y el detalle mostraría el PIN viejo.
316
- */
317
- private readonly refreshTick = signal(0);
318
-
319
- /**
320
- * Obtiene el registro completo desde el endpoint get si existe.
321
- * Esto asegura que campos pesados o no proyectados en la lista (como fotos, notas o historial)
322
- * se carguen y muestren completos. El resultado va etiquetado (`FetchState`)
323
- * para que la vista sepa distinguir «cargando» de «sin datos» de «error».
324
- */
325
- private readonly fetched = toSignal(
326
- combineLatest([toObservable(this.record), toObservable(this.refreshTick)]).pipe(
327
- switchMap(([rec]) => {
328
- const schema = this.schema();
329
- const key = rec ? String(rec[schema.keyField] ?? '') : '';
330
- const getEndpoint = schema.endpoint?.get;
331
- if (!key || !getEndpoint || typeof this.api?.get !== 'function') {
332
- // Sin get contratado la fila de la lista ES todo lo que hay.
333
- return of<FetchState>({ phase: 'done', data: null });
334
- }
335
- return this.api.get<Row>(schema.endpoint, key).pipe(
336
- map((data): FetchState => ({ phase: 'done', data })),
337
- catchError((error) => of<FetchState>({ phase: 'error', error })),
338
- );
339
- }),
340
- ),
341
- { initialValue: { phase: 'pending' } as FetchState },
342
- );
343
-
344
- /**
345
- * Estados universales del detalle — el mismo trío que `list-view` y
346
- * `form-view`. El skeleton reserva el espacio de las secciones mientras
347
- * viaja el `get` (Apps Script tarda ~1s): sin él, el operador veía una
348
- * pantalla «completa» con campos vacíos que después aparecían solos.
349
- */
350
- protected readonly status = computed<'loading' | 'ready' | 'error'>(() => {
351
- const fetched = this.fetched();
352
- if (fetched.phase === 'pending') return 'loading';
353
- if (fetched.phase === 'error') return 'error';
354
- return 'ready';
355
- });
356
-
357
- /** Reintenta el `get` del registro desde el estado de error. */
358
- protected retry(): void {
359
- this.refreshTick.update((tick) => tick + 1);
360
- }
361
-
362
- /**
363
- * D4 — el error original con IDENTIDAD intacta (no un string mapeado):
364
- * el mensaje mostrado es display-only, el objeto crudo queda aquí para
365
- * diagnóstico. `undefined` cuando no hay fallo de carga.
366
- */
367
- errorDeCarga(): unknown {
368
- const fetched = this.fetched();
369
- return fetched.phase === 'error' ? fetched.error : undefined;
370
- }
371
-
372
- /**
373
- * D4 — «way back» desde el estado de error: emite el `back` (el host
374
- * embebido sigue gestionando su propia vuelta) Y navega por el servicio
375
- * declarado — en la ruta directa (`/:id/:key`) nadie escucha el output,
376
- * y un estado de error sin salida es una pantalla muerta.
377
- */
378
- protected volverDeError(): void {
379
- this.back.emit();
380
- void this.nav.back();
381
- }
382
-
383
- protected readonly effectiveRecord = computed<Row>(() => {
384
- const initial = this.record();
385
- const fetched = this.fetched();
386
- if (
387
- fetched.phase === 'done' &&
388
- fetched.data &&
389
- typeof fetched.data === 'object' &&
390
- Object.keys(fetched.data).length > 0
391
- ) {
392
- return { ...initial, ...fetched.data };
393
- }
394
- return initial;
395
- });
396
-
397
- protected readonly detail = computed<DetailViewSchema>(
398
- () => this.schema().detail ?? { enabled: true },
399
- );
400
-
401
- protected readonly title = computed(() => {
402
- const rec = this.effectiveRecord();
403
- const schema = this.schema();
404
- const raw = rec[schema.titleField];
405
- return raw !== undefined && raw !== null && raw !== '' ? String(raw) : schema.label;
406
- });
407
-
408
- protected readonly recordKey = computed(() => {
409
- const rec = this.effectiveRecord();
410
- const schema = this.schema();
411
- return String(rec[schema.keyField] ?? '—');
412
- });
413
-
414
- protected readonly headerFields = computed<FieldValue[]>(() => {
415
- const headerKeys = this.detail().headerFields ?? [];
416
- return headerKeys
417
- .map((key) => this.resolveFieldValue(key))
418
- .filter((f): f is FieldValue => f !== null);
419
- });
420
-
421
- protected readonly sections = computed<DetailSection[]>(() => {
422
- const schema = this.schema();
423
- const detailConfig = this.detail();
424
-
425
- if (detailConfig.sections && detailConfig.sections.length > 0) {
426
- return detailConfig.sections
427
- .map((sec) => ({
428
- id: sec.id,
429
- label: sec.label,
430
- fields: sec.fields
431
- .map((key) => this.resolveFieldValue(key))
432
- .filter((f): f is FieldValue => f !== null),
433
- }))
434
- .filter((sec) => sec.fields.length > 0);
435
- }
436
-
437
- const layoutSections = schema.layout?.sections ?? [];
438
- const sectionMap = new Map<string, DetailSection>();
439
-
440
- for (const layoutSection of layoutSections) {
441
- sectionMap.set(layoutSection.id, {
442
- id: layoutSection.id,
443
- label: layoutSection.label,
444
- fields: [],
445
- });
446
- }
447
-
448
- const unsectioned: DetailSection = { id: '_unsectioned', label: schema.label, fields: [] };
449
-
450
- for (const field of schema.fields) {
451
- const value = this.resolveFieldValue(field.key);
452
- if (value === null) continue; // R7.5: campo oculto por políticas
453
- if (field.section && sectionMap.has(field.section)) {
454
- sectionMap.get(field.section)!.fields.push(value);
455
- } else {
456
- unsectioned.fields.push(value);
457
- }
458
- }
459
-
460
- const result: DetailSection[] = [];
461
- if (unsectioned.fields.length > 0) result.push(unsectioned);
462
- for (const sec of sectionMap.values()) {
463
- if (sec.fields.length > 0) result.push(sec);
464
- }
465
-
466
- return result;
467
- });
468
-
469
- protected readonly copyShareActions = computed<CopyShareAction[]>(() => {
470
- const actions: ResourceAction[] = this.schema().actions ?? this.detail().actions ?? [];
471
- return actions.filter(isShareAction);
472
- });
473
-
474
- /** R8.8: acciones de dominio del back (trigger) visibles en el detalle. */
475
- protected readonly triggerActions = computed<TriggerAction[]>(() => {
476
- const actions: ResourceAction[] = this.schema().actions ?? this.detail().actions ?? [];
477
- return actions.filter(isTriggerAction);
478
- });
479
-
480
- /**
481
- * R8.8: dispara un `trigger` y, si tocó datos (`reload`), fuerza la
482
- * relectura del registro. La confirmación (si el descriptor la pide) la
483
- * resuelve `actionService.run` — este método no decide por tipo.
484
- */
485
- protected async runTrigger(action: TriggerAction): Promise<void> {
486
- if (!this.api) return; // sin API no hay ruta que disparar
487
- const result = await this.actionService.run(action, {
488
- record: this.effectiveRecord(),
489
- resource: this.schema().id,
490
- api: this.api,
491
- router: this.router,
492
- toast: this.notifications,
493
- user: this.auth.user(),
494
- keyField: this.schema().keyField,
495
- });
496
- if (result.ok && result.reload) {
497
- this.refreshTick.update((tick) => tick + 1);
498
- }
499
- }
500
-
501
- /**
502
- * Agrupación, no formato: devuelve el campo y el valor crudo. El pintado
503
- * es cosa del registro (R4.2).
504
- *
505
- * R7.5: oculta campos según `field.access.read` (sólo UX; el back
506
- * vuelve a filtrar la respuesta).
507
- */
508
- private resolveFieldValue(key: string): FieldValue | null {
509
- const schema = this.schema();
510
- const rec = this.effectiveRecord();
511
- const field = schema.fields.find((f) => f.key === key);
512
- const raw = getValue(rec, key);
513
-
514
- // Una clave que ningún schema declara no tiene descriptor: se resuelve
515
- // como texto crudo, que era exactamente lo que hacía el `default` del
516
- // `formatValue` viejo.
517
- const declarado: FieldSchema = field ?? { key, label: key.replace(/_/g, ' '), type: 'text' };
518
-
519
- // R7.5: ocultar si el usuario no tiene permiso de lectura
520
- if (!this.auth.canReadField(declarado)) {
521
- return null;
522
- }
523
-
524
- return {
525
- key,
526
- label: field?.label ?? declarado.label,
527
- field: declarado,
528
- raw,
529
- };
530
- }
531
-
532
- /**
533
- * Valor vacío con el criterio de siempre (`null`, `undefined`, `''`): ni
534
- * el chip de la cabecera ni el `—` del cuerpo cambian de criterio.
535
- */
536
- protected vacio(valor: unknown): boolean {
537
- return valor === null || valor === undefined || valor === '';
538
- }
539
-
540
- /** Un historial sólo es historial si hay valor que recorrer. */
541
- private esHistorial(campo: FieldValue): boolean {
542
- return campo.field.type === 'list' && !this.vacio(campo.raw);
543
- }
544
-
545
- protected regularFields(section: DetailSection): FieldValue[] {
546
- return section.fields.filter((f) => !this.esHistorial(f));
547
- }
548
-
549
- protected listFields(section: DetailSection): FieldValue[] {
550
- return section.fields.filter((f) => this.esHistorial(f));
551
- }
552
-
553
- protected hasLargeContent(section: DetailSection): boolean {
554
- return section.fields.some((f) => this.esHistorial(f) || f.key === 'description');
555
- }
556
-
557
- protected colSpanFor(width: number | undefined): string {
558
- const w = width ?? 6;
559
- return `lg:col-span-${Math.min(w, 9)}`;
560
- }
561
-
562
- protected isCopyable(type: string): boolean {
563
- return ['text', 'url', 'email', 'phone', 'readonly-text', 'slug', 'color', 'number', 'currency', 'date', 'time'].includes(type);
564
- }
565
-
566
- /** Enlace y mensaje, resueltos por `resolveShare` (R3.10: una sola copia). */
567
- protected shareOf(action: CopyShareAction): ResolvedShare {
568
- return resolveShare(action, this.actionService.vars(this.effectiveRecord()));
569
- }
570
- }