arckode-ui 0.2.2 → 0.2.3

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,19 @@ Cambios entre versiones publicadas. Sigue [keepachangelog](https://keepachangelo
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.2.3] — 2026-05-23
8
+
9
+ ### Fixed
10
+ - **Skills**: eliminada ambigüedad en el patrón de store. El patrón DEFAULT es ahora
11
+ signals al top-level del módulo (más limpio, sin traps). `useStore()` dentro de
12
+ callbacks queda como fallback explícito solo para cross-store dependency.
13
+ - **Skills**: eliminada ambigüedad en comunicación hijo→padre. `emit + @event` es el
14
+ DEFAULT explícito. Callback como prop tiene criterio concreto: solo para primitivos
15
+ genéricos (Button, Input) sin semántica de negocio.
16
+ - Versión en `§14` del SKILL principal actualizada de `v0.1.1` a `v0.2.2`.
17
+ - Mismas correcciones aplicadas en `skills/SKILL.md` y `skills/components/SKILL.md`
18
+ (los sub-skills distribuidos con el paquete npm).
19
+
7
20
  ## [0.2.2] — 2026-05-23
8
21
 
9
22
  ### Fixed
@@ -94,7 +107,8 @@ Cambios entre versiones publicadas. Sigue [keepachangelog](https://keepachangelo
94
107
  - TypeScript declarations no se generaban (`vite-plugin-dts` faltaba) —
95
108
  arreglado en `0.2.2`.
96
109
 
97
- [Unreleased]: https://gitlab.com/underworf/arckode-ui/-/compare/v0.2.2...HEAD
110
+ [Unreleased]: https://gitlab.com/underworf/arckode-ui/-/compare/v0.2.3...HEAD
111
+ [0.2.3]: https://gitlab.com/underworf/arckode-ui/-/compare/v0.2.2...v0.2.3
98
112
  [0.2.2]: https://gitlab.com/underworf/arckode-ui/-/compare/v0.2.1...v0.2.2
99
113
  [0.2.1]: https://gitlab.com/underworf/arckode-ui/-/compare/v0.2.0...v0.2.1
100
114
  [0.2.0]: https://gitlab.com/underworf/arckode-ui/-/compare/v0.1.1...v0.2.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arckode-ui",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "description": "Frontend framework con .ark SFCs, signals, file-system router y analyzer estático con sugerencias concretas de fix. Diseñado para máxima predictibilidad de output de IA.",
6
6
  "keywords": [
package/skills/SKILL.md CHANGED
@@ -625,81 +625,60 @@ export default defineComponent({
625
625
 
626
626
  ## 7. STORE — estado global compartido
627
627
 
628
+ ### DEFAULT — signals declarados fuera del defineStore
629
+
630
+ Usar SIEMPRE este patrón. Los signals viven al top-level del módulo y se pasan al store.
631
+ Es TS-friendly, testeable, y no tiene traps de auto-referencia.
632
+
628
633
  ```typescript
629
634
  // stores/user.store.ts
630
635
  import { defineStore, signal, computed } from 'arckode-ui'
631
636
 
632
637
  interface UserDTO { id: string; name: string }
633
638
 
639
+ // signals al top-level — accesibles directamente en getters/actions sin llamar useStore()
640
+ const current = signal<UserDTO | null>(null)
641
+ const loading = signal(false)
642
+ const isLoggedIn = computed(() => current.value !== null)
643
+
634
644
  export const useUserStore = defineStore('user', {
635
- state: {
636
- current: signal<UserDTO | null>(null),
637
- loading: signal(false),
638
- },
639
- getters: {
640
- isLoggedIn: computed(() => useUserStore().state.current.value !== null),
641
- },
645
+ state: { current, loading },
646
+ getters: { isLoggedIn },
642
647
  actions: {
643
648
  async login(email: string, password: string) {
644
- const store = useUserStore()
645
- store.state.loading.value = true
649
+ loading.value = true
646
650
  // ...
647
651
  },
648
- logout() { useUserStore().state.current.value = null },
652
+ logout() { current.value = null },
649
653
  },
650
654
  })
651
655
  ```
652
656
 
653
- ### Trap conocido del store — `useStore()` dentro de getters/actions
654
-
655
- El patrón `useUserStore()` dentro de getters/actions FUNCIONA porque cuando esos
656
- callbacks se ejecutan, el registry del store YA tiene la instancia registrada.
657
- Pero hay dos cosas a saber:
658
-
659
- 1. **NO lo llames durante la DEFINICIÓN del objeto** — solo dentro del callback.
660
- Si lo llamás afuera, el registry todavía no tiene la instancia y devuelve `undefined`
661
- o tira error.
662
-
663
- ```typescript
664
- // ❌ MAL: useStore() en evaluación del valor del state
665
- export const useStore = defineStore('x', {
666
- state: {
667
- current: useStore().getters.somethingElse, // ← infinite loop / crash
668
- },
669
- })
670
-
671
- // BIEN: useStore() solo dentro del callback (computed/function)
672
- export const useStore = defineStore('x', {
673
- state: { current: signal(null) },
674
- getters: {
675
- label: computed(() => useStore().state.current.value ?? 'anonymous'),
676
- },
677
- })
678
- ```
679
-
680
- 2. **Pattern alternativo más limpio**: declarar los signals fuera del defineStore
681
- y referenciarlos directo. Evita el `useStore()` en absoluto:
682
-
683
- ```typescript
684
- // signals al top-level del módulo
685
- const current = signal<UserDTO | null>(null)
686
- const loading = signal(false)
687
- const isLoggedIn = computed(() => current.value !== null)
688
-
689
- export const useUserStore = defineStore('user', {
690
- state: { current, loading },
691
- getters: { isLoggedIn },
692
- actions: {
693
- async login(...) { loading.value = true; /* ... */ },
694
- logout() { current.value = null },
695
- },
696
- })
697
- ```
698
-
699
- Esta forma es más TS-friendly (no requiere casts dentro de callbacks), más
700
- testeable (los signals son inspeccionables sin invocar el store) y más legible.
701
-
702
- Uso en componente:
657
+ ### SI EL DEFAULT FALLA — `useStore()` dentro de getters/actions
658
+
659
+ Cuándo usarlo: cuando un getter/action necesita acceder al state de OTRO store
660
+ (cross-store dependency). Llamar `useOtroStore()` dentro del callback, nunca en la definición.
661
+
662
+ ```typescript
663
+ // cross-store: OK dentro del callback
664
+ actions: {
665
+ syncWithCart() {
666
+ const cart = useCartStore() // ← dentro del callback, no en la definición
667
+ current.value = cart.state.owner.value
668
+ },
669
+ },
670
+ ```
671
+
672
+ ⚠ **NUNCA** llamar `useStore()` fuera de un callback (nivel raíz del objeto state/getters/actions).
673
+ ```typescript
674
+ // ❌ MAL: useStore() en la definición del state — crash, registry vacío
675
+ export const useStore = defineStore('x', {
676
+ state: { ref: useStore().state.something },
677
+ })
678
+ ```
679
+
680
+ ### Uso en componente
681
+
703
682
  ```typescript
704
683
  const userStore = useUserStore()
705
684
  return {
@@ -709,8 +688,6 @@ return {
709
688
  }
710
689
  ```
711
690
 
712
- **Patrón clave:** dentro de getters/actions, llamar `useUserStore()` para acceder al state. Es feo pero es la API real verificada en tests.
713
-
714
691
  ---
715
692
 
716
693
  ## 8. SERVICE — HTTP
@@ -122,7 +122,8 @@ Detalles:
122
122
  - El nombre del evento debe estar en `emits: []` (sino warning runtime)
123
123
  - Eventos en kebab-case obligatorio
124
124
 
125
- **Patrón alternativo (callback como prop):** sigue funcionando, útil cuando el child no tiene "ownership" del evento conceptualmente:
125
+ **SI EL DEFAULT FALLA — callback como prop:** usar solo cuando el hijo es un primitivo genérico
126
+ (Button, Input) que no tiene semántica de negocio y el padre necesita pasarle una función directamente.
126
127
  ```html
127
128
  <TaskForm :onSubmit="actions.handleCreate" :onCancel="actions.closeModal" />
128
129
  ```