@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,219 +0,0 @@
1
- import { Component, OnDestroy, computed, effect, input, viewChild } from '@angular/core';
2
- import type { ElementRef } from '@angular/core';
3
- import {
4
- CategoryScale,
5
- Chart,
6
- LineController,
7
- LineElement,
8
- LinearScale,
9
- PointElement,
10
- Tooltip,
11
- type ChartConfiguration,
12
- } from 'chart.js';
13
-
14
- import { Skeleton } from '../../shared/components/skeleton/skeleton';
15
- import type { BarDatum } from '../bar-chart/bar-chart';
16
-
17
- // Chart.js usa registro explícito en vez de `chart.js/auto`: sólo entra lo que
18
- // esta serie necesita (sin DoughnutController, sin Filler, sin Legend).
19
- Chart.register(CategoryScale, LineController, LineElement, LinearScale, PointElement, Tooltip);
20
-
21
- /**
22
- * Serie temporal con Chart.js (viabilidad B2.1).
23
- *
24
- * La librería —61,4 K gz medidos— sólo se arrastra con ESTE componente y se
25
- * descarga en su propio chunk: el descriptor del widget la trae con
26
- * `import('./chart-line')` y es esa llamada la que hace que esbuild la
27
- * aparte del bundle inicial (aquí se importa estáticamente, así que ningún
28
- * `@defer` de otro fichero podría separarla).
29
- *
30
- * El `@defer (on viewport)` de abajo cumple el otro objetivo y vive aquí, y
31
- * no en un host: el chunk llega con el panel, pero el lienzo y la instancia
32
- * de `Chart` sólo se crean cuando el gráfico entra en pantalla. Un host no
33
- * puede decidir eso — desde R3.6 el motor no conoce ningún tipo concreto
34
- * (R3.6 · `doc/plan-refactor-motor.md`).
35
- *
36
- * La condición `on viewport` necesita `IntersectionObserver`, que jsdom no
37
- * trae: los tests configuran `DeferBlockBehavior.Manual` y pintan el bloque
38
- * a mano, igual que hacía `widget-host.spec`.
39
- */
40
- @Component({
41
- selector: 'app-chart-line',
42
- imports: [Skeleton],
43
- template: `
44
- <div class="rounded-lg border border-neutral/20 bg-surface p-4">
45
- <p class="mb-3 text-sm text-neutral">{{ label() }}</p>
46
-
47
- @if (data().length === 0) {
48
- <p class="text-sm text-neutral/60" data-testid="empty">Sin datos.</p>
49
- } @else {
50
- <div aria-live="polite" aria-atomic="true">
51
- @defer (on viewport) {
52
- <div role="img" [attr.aria-label]="summary()" class="relative h-32">
53
- <canvas #canvas class="absolute inset-0 h-full w-full"></canvas>
54
- </div>
55
- } @placeholder {
56
- <div class="relative h-32" aria-hidden="true">
57
- <svg
58
- viewBox="0 0 100 40"
59
- preserveAspectRatio="none"
60
- class="absolute inset-0 h-full w-full text-primary"
61
- >
62
- <polyline
63
- fill="none"
64
- stroke="currentColor"
65
- stroke-width="2"
66
- vector-effect="non-scaling-stroke"
67
- [attr.points]="sparkPoints()"
68
- />
69
- </svg>
70
- </div>
71
- } @loading {
72
- <app-skeleton [lines]="3" [height]="24" />
73
- } @error {
74
- <p class="text-sm text-neutral/60" data-testid="chart-error">
75
- No se pudo cargar el gráfico.
76
- </p>
77
- }
78
- </div>
79
- }
80
- </div>
81
- `,
82
- })
83
- export class ChartLine implements OnDestroy {
84
- /** Título del gráfico. */
85
- readonly label = input.required<string>();
86
- /** Series a dibujar; vacío ⇒ estado «Sin datos». */
87
- readonly data = input<BarDatum[]>([]);
88
- /** Sufijo de las cifras del eje («unidades», «S/»). */
89
- readonly unit = input('');
90
-
91
- /**
92
- * Opcional y no `required`: el lienzo sólo existe una vez completado el
93
- * `@defer`, así que el `effect` de abajo se re-ejecuta solo al aparecer y
94
- * dibuja en ese momento. Un `viewChild.required` reventaría en el primer
95
- * ciclo, cuando el bloque todavía está en placeholder.
96
- */
97
- private readonly canvas = viewChild<ElementRef<HTMLCanvasElement>>('canvas');
98
-
99
- private chart: Chart<'line'> | null = null;
100
-
101
- constructor() {
102
- effect(() => {
103
- const lienzo = this.canvas();
104
- this.data();
105
- this.label();
106
- this.unit();
107
-
108
- if (lienzo) {
109
- this.render(lienzo.nativeElement);
110
- } else {
111
- // Sin lienzo (sin datos, o el bloque aún en placeholder) no hay nada
112
- // que mantener vivo: una instancia huérfana seguiría redibujando.
113
- this.destroy();
114
- }
115
- });
116
- }
117
-
118
- ngOnDestroy(): void {
119
- this.destroy();
120
- }
121
-
122
- protected readonly summary = computed(() => {
123
- const rows = this.data();
124
- if (rows.length === 0) {
125
- return 'Sin datos.';
126
- }
127
- const unit = this.unit();
128
- const first = rows[0];
129
- const last = rows[rows.length - 1];
130
- const delta = last.value - first.value;
131
- const trend = delta > 0 ? 'sube' : delta < 0 ? 'baja' : 'se mantiene';
132
- return (
133
- `Serie de ${rows.length} puntos, de ${first.label} (${first.value}${unit}) ` +
134
- `a ${last.label} (${last.value}${unit}): ${trend}.`
135
- );
136
- });
137
-
138
- /** Miniatura del placeholder: la misma serie, dibujada con SVG y sin JS. */
139
- protected readonly sparkPoints = computed(() => {
140
- const rows = this.data();
141
- if (rows.length === 0) {
142
- return '';
143
- }
144
- const max = Math.max(0, ...rows.map((row) => row.value));
145
- const last = rows.length - 1;
146
- return rows
147
- .map((row, index) => {
148
- const x = last === 0 ? 50 : (index / last) * 100;
149
- const y = max === 0 ? 40 : 40 - (row.value / max) * 36;
150
- return `${x.toFixed(2)},${y.toFixed(2)}`;
151
- })
152
- .join(' ');
153
- });
154
-
155
- private render(canvas: HTMLCanvasElement): void {
156
- const rows = this.data();
157
-
158
- // Sin datos no hay lienzo en el template: crear un `Chart` sobre él
159
- // reventaría (y el `@if` ya se lo habría llevado por delante).
160
- if (rows.length === 0) {
161
- this.destroy();
162
- return;
163
- }
164
-
165
- const config: ChartConfiguration<'line'> = {
166
- type: 'line',
167
- data: {
168
- labels: rows.map((row) => row.label),
169
- datasets: [
170
- {
171
- label: this.label(),
172
- data: rows.map((row) => row.value),
173
- borderColor: this.cssColor('--color-primary'),
174
- borderWidth: 2,
175
- pointRadius: 3,
176
- pointHoverRadius: 5,
177
- tension: 0.35,
178
- },
179
- ],
180
- },
181
- options: {
182
- responsive: true,
183
- maintainAspectRatio: false,
184
- plugins: {
185
- legend: { display: false },
186
- tooltip: { enabled: true, mode: 'index', intersect: false },
187
- },
188
- scales: {
189
- x: { grid: { display: false } },
190
- y: {
191
- beginAtZero: true,
192
- ticks: {
193
- callback: (value) =>
194
- typeof value === 'number' ? `${value}${this.unit()}` : String(value),
195
- },
196
- },
197
- },
198
- },
199
- };
200
-
201
- this.destroy();
202
- this.chart = new Chart<'line'>(canvas, config);
203
- }
204
-
205
- private destroy(): void {
206
- this.chart?.destroy();
207
- this.chart = null;
208
- }
209
-
210
- /**
211
- * Chart.js pinta en el lienzo y NO entiende `var(--…)`, así que el token se
212
- * resuelve en tiempo de dibujo. Se lee en cada render —no al arrancar—
213
- * porque el modo oscuro sobre-escribe `--color-primary` (`styles/theme.css`).
214
- */
215
- private cssColor(token: string): string {
216
- const value = getComputedStyle(document.documentElement).getPropertyValue(token).trim();
217
- return value || '#1d69f0';
218
- }
219
- }
@@ -1,29 +0,0 @@
1
- import type { RenderDescriptor } from '../core/registry/render-registry';
2
-
3
- import { descriptor as barChartDescriptor } from './bar-chart/bar-chart.descriptor';
4
- import { descriptor as chartLineDescriptor } from './chart-line/chart-line.descriptor';
5
- import { descriptor as metricCardDescriptor } from './metric-card/metric-card.descriptor';
6
- import { descriptor as quickActionsDescriptor } from './quick-actions/quick-actions.descriptor';
7
- import { descriptor as recordListDescriptor } from './record-list/record-list.descriptor';
8
- import { descriptor as statusProgressDescriptor } from './status-progress/status-progress.descriptor';
9
-
10
- /**
11
- * Manifiesto de descriptores de widget (R3.6 · registro único de render).
12
- *
13
- * Mismo criterio que `fields/descriptors.ts`: una línea por tipo y el
14
- * registro los recoge al importar este módulo. Es la **única** lista manual
15
- * del catálogo de widgets — `import.meta.glob` no sobrevive a `ng build`
16
- * (D9-1), así que se mantiene el «registro manual de una línea».
17
- *
18
- * Añadir un widget ⇒ crear la carpeta + su `.descriptor.ts` + una línea
19
- * acá. **Ningún host se toca** (R3.8): si el componente sigue la forma
20
- * estándar `{widget, data}` ni siquiera hay que escribir `inputs`.
21
- */
22
- export const widgetDescriptors: readonly RenderDescriptor[] = [
23
- barChartDescriptor,
24
- chartLineDescriptor,
25
- metricCardDescriptor,
26
- quickActionsDescriptor,
27
- recordListDescriptor,
28
- statusProgressDescriptor,
29
- ];
@@ -1,41 +0,0 @@
1
- import type { MetricCardWidget } from '../../core/models/schema.model';
2
- import type { RenderDescriptor } from '../../core/registry/render-registry';
3
-
4
- /**
5
- * El dato de un KPI es un ESCALAR y puede llegar de dos formas:
6
- *
7
- * - **payload**: `data[widget.key]` ya es la cifra (la resuelve el handler
8
- * del panel);
9
- * - **fuente declarada** (F8 · R6.5): una vista con `aggregate` devuelve
10
- * `[{ value: … }]` y la cifra es ese `value`.
11
- *
12
- * Cualquier otra forma ⇒ `null`, que `MetricCard` pinta como vacío. Se
13
- * traduce acá, en el borde — el componente no debería saber de dónde salió
14
- * el número.
15
- */
16
- function valorDeKpi(data: unknown): number | string | null {
17
- if (Array.isArray(data)) {
18
- const first = data[0];
19
- if (typeof first !== 'object' || first === null) return null;
20
- const value = (first as { value?: unknown }).value;
21
- return value === undefined || value === null ? null : (value as number | string);
22
- }
23
- if (data === undefined) return null;
24
- return data as number | string | null;
25
- }
26
-
27
- /** Descriptor del widget `metric-card` (R3.6). */
28
- export const descriptor: RenderDescriptor = {
29
- kind: 'widget',
30
- type: 'metric-card',
31
- since: '1.0',
32
- load: () => import('./metric-card').then((module) => module.MetricCard),
33
- surfaces: ['display'],
34
- // El KPI no recibe el widget entero: sólo vive de su rótulo, del dato y de
35
- // la nota al pie. Pasa el dato ya traducido — `MetricCard` distingue el
36
- // `0` de un vacío, y el `0` de un agregado llega como `[{ value: 0 }]`.
37
- inputs: (config, extras) => {
38
- const cfg = config as MetricCardWidget;
39
- return { label: cfg.label, value: valorDeKpi(extras.data), hint: cfg.hint ?? '' };
40
- },
41
- };
@@ -1,52 +0,0 @@
1
- import { ComponentFixture, TestBed } from '@angular/core/testing';
2
-
3
- import { MetricCard } from './metric-card';
4
-
5
- describe('MetricCard', () => {
6
- let fixture: ComponentFixture<MetricCard>;
7
-
8
- const root = (): HTMLElement => fixture.nativeElement as HTMLElement;
9
- const value = (): HTMLElement | null => root().querySelector('[data-testid="value"]');
10
- const empty = (): HTMLElement | null => root().querySelector('[data-testid="value-empty"]');
11
-
12
- beforeEach(async () => {
13
- await TestBed.configureTestingModule({ imports: [MetricCard] }).compileComponents();
14
- fixture = TestBed.createComponent(MetricCard);
15
- fixture.componentRef.setInput('label', 'Pendientes');
16
- });
17
-
18
- it('renderiza la etiqueta y la cifra', () => {
19
- fixture.componentRef.setInput('value', 3);
20
- fixture.detectChanges();
21
-
22
- expect(root().textContent).toContain('Pendientes');
23
- expect(value()?.textContent?.trim()).toBe('3');
24
- expect(empty()).toBeNull();
25
- });
26
-
27
- it('value null ⇒ estado vacío con el placeholder', () => {
28
- fixture.componentRef.setInput('value', null);
29
- fixture.detectChanges();
30
-
31
- expect(empty()).not.toBeNull();
32
- expect(value()).toBeNull();
33
- });
34
-
35
- it('0 es un valor, no un vacío', () => {
36
- fixture.componentRef.setInput('value', 0);
37
- fixture.detectChanges();
38
-
39
- expect(value()?.textContent?.trim()).toBe('0');
40
- expect(empty()).toBeNull();
41
- });
42
-
43
- it('sin hint no pinta la línea secundaria', () => {
44
- fixture.componentRef.setInput('value', 3);
45
- fixture.detectChanges();
46
- expect(root().textContent).not.toContain('hint');
47
-
48
- fixture.componentRef.setInput('hint', 'de 12 totales');
49
- fixture.detectChanges();
50
- expect(root().textContent).toContain('de 12 totales');
51
- });
52
- });
@@ -1,48 +0,0 @@
1
- import { Component, computed, input } from '@angular/core';
2
-
3
- /**
4
- * KPI de una cifra suelta («3 pendientes»).
5
- *
6
- * Cero dependencias: es sólo presentación — el valor lo trae el
7
- * orquestador del panel desde el endpoint de métricas.
8
- *
9
- * Sin `icon`: el schema no tiene hoy un registro de nombres de icono
10
- * (los Lucide se importan estáticamente), así que un `icon?: string` no
11
- * podría resolverse declarativamente. Se añade cuando exista ese registro.
12
- */
13
- @Component({
14
- selector: 'app-metric-card',
15
- template: `
16
- <article class="rounded-lg border border-neutral/20 bg-surface p-4">
17
- <p class="text-sm text-neutral">{{ label() }}</p>
18
-
19
- @if (empty()) {
20
- <p class="font-display text-3xl font-semibold text-neutral/40" data-testid="value-empty">
21
- —
22
- </p>
23
- } @else {
24
- <p class="font-display text-3xl font-semibold" data-testid="value">{{ display() }}</p>
25
- }
26
-
27
- @if (hint()) {
28
- <p class="mt-1 text-xs text-neutral">{{ hint() }}</p>
29
- }
30
- </article>
31
- `,
32
- })
33
- export class MetricCard {
34
- /** Rótulo del KPI. */
35
- readonly label = input.required<string>();
36
- /** Cifra a mostrar; `null`/`undefined` ⇒ estado vacío. */
37
- readonly value = input<unknown>(null);
38
- /** Texto secundario estático bajo la cifra. */
39
- readonly hint = input('');
40
-
41
- /** `0` es un valor, no un vacío: sólo `null`/`undefined` vacían la tarjeta. */
42
- protected readonly empty = computed(() => this.value() === null || this.value() === undefined);
43
-
44
- protected readonly display = computed(() => {
45
- const value = this.value();
46
- return typeof value === 'number' ? new Intl.NumberFormat('es-PE').format(value) : String(value);
47
- });
48
- }
@@ -1,13 +0,0 @@
1
- import type { RenderDescriptor } from '../../core/registry/render-registry';
2
-
3
- /** Descriptor del widget `quick-actions` (R3.6). */
4
- export const descriptor: RenderDescriptor = {
5
- kind: 'widget',
6
- type: 'quick-actions',
7
- since: '1.0',
8
- load: () => import('./quick-actions').then((module) => module.QuickActions),
9
- surfaces: ['display'],
10
- // El único widget sin dato: sus botones salen todos del schema. Por eso no
11
- // recibe `data` — `ngComponentOutletInputs` no admite inputs inexistentes.
12
- inputs: (config) => ({ widget: config }),
13
- };
@@ -1,61 +0,0 @@
1
- import { provideRouter } from '@angular/router';
2
- import { ComponentFixture, TestBed } from '@angular/core/testing';
3
- import { describe, expect, it, beforeEach } from 'vitest';
4
-
5
- import type { QuickActionsWidget } from '../../core/models/schema.model';
6
- import { QuickActions } from './quick-actions';
7
-
8
- describe('QuickActions', () => {
9
- let fixture: ComponentFixture<QuickActions>;
10
-
11
- const widget: QuickActionsWidget = {
12
- type: 'quick-actions',
13
- key: 'acciones_rapidas',
14
- label: 'Accesos Directos',
15
- actions: [
16
- { label: 'Nuevo Pedido', icon: 'plus', navigateTo: '/admin/orders?action=create' },
17
- { label: 'Configuración', icon: 'settings', navigateTo: '/admin/pickpass' },
18
- { label: 'Guía Externa', icon: 'external', navigateTo: 'https://ejemplo.com/guia' },
19
- ],
20
- };
21
-
22
- beforeEach(async () => {
23
- await TestBed.configureTestingModule({
24
- imports: [QuickActions],
25
- providers: [provideRouter([])],
26
- }).compileComponents();
27
- fixture = TestBed.createComponent(QuickActions);
28
- });
29
-
30
- it('1. renderiza todas las acciones declaradas con sus textos', () => {
31
- fixture.componentRef.setInput('widget', widget);
32
- fixture.detectChanges();
33
-
34
- const root = fixture.nativeElement as HTMLElement;
35
- expect(root.textContent).toContain('Accesos Directos');
36
- expect(root.textContent).toContain('Nuevo Pedido');
37
- expect(root.textContent).toContain('Configuración');
38
- expect(root.textContent).toContain('Guía Externa');
39
- });
40
-
41
- it('2. genera enlaces internos con routerLink', () => {
42
- fixture.componentRef.setInput('widget', widget);
43
- fixture.detectChanges();
44
-
45
- const root = fixture.nativeElement as HTMLElement;
46
- const links = root.querySelectorAll('a');
47
- expect(links.length).toBe(3);
48
- expect(links[0].getAttribute('href')).toBe('/admin/orders?action=create');
49
- expect(links[1].getAttribute('href')).toBe('/admin/pickpass');
50
- });
51
-
52
- it('3. genera enlaces externos con target blank y rel noopener', () => {
53
- fixture.componentRef.setInput('widget', widget);
54
- fixture.detectChanges();
55
-
56
- const root = fixture.nativeElement as HTMLElement;
57
- const links = root.querySelectorAll('a');
58
- expect(links[2].getAttribute('href')).toBe('https://ejemplo.com/guia');
59
- expect(links[2].getAttribute('target')).toBe('_blank');
60
- });
61
- });
@@ -1,100 +0,0 @@
1
- import { Component, input } from '@angular/core';
2
- import { RouterLink } from '@angular/router';
3
- import {
4
- LucideExternalLink,
5
- LucideFileText,
6
- LucidePlus,
7
- LucideSettings,
8
- LucideZap,
9
- } from '@lucide/angular';
10
-
11
- import type { QuickActionsWidget } from '../../core/models/schema.model';
12
- import { parseNavigationUrl, type ParsedRoute } from '../../core/utils/template-interpolator';
13
-
14
- const BUTTON_CLASSES: Record<string, string> = {
15
- primary:
16
- 'bg-primary text-surface hover:bg-primary/90 font-medium px-4 py-2.5 rounded-lg inline-flex items-center gap-2 text-sm transition-colors',
17
- outline:
18
- 'border border-neutral/40 bg-surface text-neutral hover:bg-neutral/10 font-medium px-4 py-2.5 rounded-lg inline-flex items-center gap-2 text-sm transition-colors',
19
- secondary:
20
- 'bg-neutral/10 text-neutral-light hover:bg-neutral/20 font-medium px-4 py-2.5 rounded-lg inline-flex items-center gap-2 text-sm transition-colors',
21
- };
22
-
23
- /**
24
- * Grid de accesos directos y atajos operativos para el Dashboard.
25
- */
26
- @Component({
27
- selector: 'app-quick-actions',
28
- imports: [RouterLink, LucidePlus, LucideSettings, LucideFileText, LucideExternalLink, LucideZap],
29
- template: `
30
- <article class="flex h-full flex-col rounded-xl border border-neutral/20 bg-surface p-4">
31
- <h2 class="mb-3 text-sm font-semibold text-neutral-light">{{ widget().label }}</h2>
32
-
33
- <div class="grid flex-1 grid-cols-1 gap-2.5 sm:grid-cols-2">
34
- @for (action of widget().actions; track action.label) {
35
- @if (isExternal(action.navigateTo)) {
36
- <a
37
- [href]="action.navigateTo"
38
- target="_blank"
39
- rel="noopener noreferrer"
40
- [class]="buttonClass(action.variant)"
41
- >
42
- @switch (action.icon) {
43
- @case ('plus') {
44
- <svg lucidePlus size="16" class="shrink-0" />
45
- }
46
- @case ('settings') {
47
- <svg lucideSettings size="16" class="shrink-0" />
48
- }
49
- @case ('document') {
50
- <svg lucideFileText size="16" class="shrink-0" />
51
- }
52
- @default {
53
- <svg lucideExternalLink size="16" class="shrink-0" />
54
- }
55
- }
56
- <span class="truncate">{{ action.label }}</span>
57
- </a>
58
- } @else {
59
- <a
60
- [routerLink]="parseRoute(action.navigateTo).path"
61
- [queryParams]="parseRoute(action.navigateTo).queryParams"
62
- [class]="buttonClass(action.variant)"
63
- >
64
- @switch (action.icon) {
65
- @case ('plus') {
66
- <svg lucidePlus size="16" class="shrink-0" />
67
- }
68
- @case ('settings') {
69
- <svg lucideSettings size="16" class="shrink-0" />
70
- }
71
- @case ('document') {
72
- <svg lucideFileText size="16" class="shrink-0" />
73
- }
74
- @default {
75
- <svg lucideZap size="16" class="shrink-0" />
76
- }
77
- }
78
- <span class="truncate">{{ action.label }}</span>
79
- </a>
80
- }
81
- }
82
- </div>
83
- </article>
84
- `,
85
- })
86
- export class QuickActions {
87
- readonly widget = input.required<QuickActionsWidget>();
88
-
89
- protected isExternal(url: string): boolean {
90
- return /^https?:\/\//i.test(url);
91
- }
92
-
93
- protected parseRoute(url: string): ParsedRoute {
94
- return parseNavigationUrl(url);
95
- }
96
-
97
- protected buttonClass(variant?: string): string {
98
- return BUTTON_CLASSES[variant || 'secondary'] || BUTTON_CLASSES['secondary'];
99
- }
100
- }
@@ -1,16 +0,0 @@
1
- import type { RenderDescriptor } from '../../core/registry/render-registry';
2
-
3
- /** Descriptor del widget `record-list` (R3.6). */
4
- export const descriptor: RenderDescriptor = {
5
- kind: 'widget',
6
- type: 'record-list',
7
- since: '1.0',
8
- load: () => import('./record-list').then((module) => module.RecordList),
9
- surfaces: ['display'],
10
- // `RecordList` dibuja filas: fuera de un array no hay nada que listar, y un
11
- // objeto suelto no debe colarse como si fuera una única fila.
12
- inputs: (config, extras) => ({
13
- widget: config,
14
- data: Array.isArray(extras.data) ? (extras.data as Record<string, unknown>[]) : null,
15
- }),
16
- };
@@ -1,79 +0,0 @@
1
- import { provideRouter } from '@angular/router';
2
- import { ComponentFixture, TestBed } from '@angular/core/testing';
3
- import { describe, expect, it, beforeEach } from 'vitest';
4
-
5
- import type { RecordListWidget } from '../../core/models/schema.model';
6
- import { RecordList } from './record-list';
7
-
8
- describe('RecordList', () => {
9
- let fixture: ComponentFixture<RecordList>;
10
-
11
- const widget: RecordListWidget = {
12
- type: 'record-list',
13
- key: 'pedidos_pendientes',
14
- label: 'Pedidos que Requieren Atención',
15
- columns: ['ref', 'customer_name', 'status'],
16
- action: {
17
- label: 'Ver Ficha',
18
- routeTemplate: '/admin/orders?id={ref}',
19
- },
20
- };
21
-
22
- beforeEach(async () => {
23
- await TestBed.configureTestingModule({
24
- imports: [RecordList],
25
- providers: [provideRouter([])],
26
- }).compileComponents();
27
- fixture = TestBed.createComponent(RecordList);
28
- });
29
-
30
- it('1. renderiza las filas y columnas declaradas', () => {
31
- const data = [
32
- { ref: 'ORD-001', customer_name: 'Cliente Uno', status: 'PENDIENTE' },
33
- { ref: 'ORD-002', customer_name: 'Cliente Dos', status: 'PENDIENTE' },
34
- ];
35
-
36
- fixture.componentRef.setInput('widget', widget);
37
- fixture.componentRef.setInput('data', data);
38
- fixture.detectChanges();
39
-
40
- const root = fixture.nativeElement as HTMLElement;
41
- expect(root.textContent).toContain('Pedidos que Requieren Atención');
42
- expect(root.textContent).toContain('ORD-001');
43
- expect(root.textContent).toContain('Cliente Uno');
44
- expect(root.textContent).toContain('ORD-002');
45
- expect(root.textContent).toContain('Cliente Dos');
46
- });
47
-
48
- it('2. renderiza estado vacío cuando no hay datos', () => {
49
- fixture.componentRef.setInput('widget', widget);
50
- fixture.componentRef.setInput('data', []);
51
- fixture.detectChanges();
52
-
53
- const root = fixture.nativeElement as HTMLElement;
54
- expect(root.textContent).toContain('Sin registros pendientes');
55
- });
56
-
57
- it('3. genera el enlace de acción con la ruta interpolada', () => {
58
- const data = [{ ref: 'ORD-777', customer_name: 'Carlos', status: 'PENDIENTE' }];
59
-
60
- fixture.componentRef.setInput('widget', widget);
61
- fixture.componentRef.setInput('data', data);
62
- fixture.detectChanges();
63
-
64
- const root = fixture.nativeElement as HTMLElement;
65
- const link = root.querySelector('a');
66
- expect(link).not.toBeNull();
67
- expect(link?.getAttribute('href')).toBe('/admin/orders?id=ORD-777');
68
- expect(link?.textContent?.trim()).toBe('Ver Ficha');
69
- });
70
-
71
- it('4. maneja datos nulos sin romper', () => {
72
- fixture.componentRef.setInput('widget', widget);
73
- fixture.componentRef.setInput('data', null);
74
- fixture.detectChanges();
75
-
76
- const root = fixture.nativeElement as HTMLElement;
77
- expect(root.textContent).toContain('Sin registros pendientes');
78
- });
79
- });