Migración v1 → v2

Guía para quien ya usa ozi-ui v1 y quiere actualizar a la v2.

Principio de la v2: ozi-ui no depende de ninguna biblioteca de terceros. JavaScript puro — jQuery sobrevive únicamente en la capa integrations/ (shims de compatibilidad).

Buena noticia: la mayor parte de tu código no se rompe. Los atributos data-ozi-* y data-zld-*, la API pública (OZI.components.* / window.OziX) y los alias zld* siguen funcionando. Lo que sí cambia está listado abajo.


1. Versiones

El versionado es major +1 por plugin — no una versión única para todos.

Plugin v1 v2
ozi.js (índice) 1.0.7 2.0.0 (OZI.version)
ozi-conf 2.0.x 3.0.0
ozi-loaddata 4.x 5.0.0
ozi-select 5.x 6.0.0
ozi-autocomplete · ozi-editor · ozi-auth · ozi-search · ozi-audio 3.x 4.0.0
ozi-editor-md 1.x 2.0.0
ozi-check · ozi-toggle 2.x 3.0.0
ozi-validate 1.x 2.1.0
ozi-actions · ozi-suggest 1.x 2.0.0
ozi-helpers 1.0.x 1.1.0

El paquete Composer publica 2.0.0. La v1 permanece disponible en el tag v1-final.

composer require ozi-ui/core:^2.0

2. Cero jQuery — qué hacer

Antes (v1): ozi.js distribuía y usaba jQuery; muchos proyectos contaban con el window.$ que "venía incluido".

Después (v2): el núcleo no usa jQuery y no lo carga en el boot. Sigue distribuido en core/jquery-3.7.1.min.js para quien lo necesite.

Acción: si tu app dependía del jQuery que venía con ozi-ui, pasa a incluirlo por tu cuenta:

<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>

3. Contrato de eventos — el cambio más importante

En la v1 los eventos eran dual-dispatch: $(el).trigger() (payload posicional de jQuery) y CustomEvent. En la v2 es solo CustomEvent nativo, con el payload en detail:

detail: { component: 'ozi-select', name: 'uf', value: 'SP', items: [...], source: 'user' }
// source: 'user' (interacción del usuario) | 'api' (setValue programático)

Consumir ozi:change

// ❌ v1 — jQuery posicional
$('[data-ozi-select="uf"]').on('ozi:change', function (e, items, instance, detail) {
    console.log(detail.value);
});

// ✅ v2 — CustomEvent nativo
document.addEventListener('ozi:change', function (e) {
    if (e.detail.component !== 'ozi-select') return;
    console.log(e.detail.name, e.detail.value);   // 'uf', 'SP'
});
<!-- ✅ v2 — Alpine -->
<div x-on:ozi:change="$wire.set('uf', $event.detail.value)"></div>

Cambios de clave en el detail

v1 v2
key name
instance eliminado — usa OZI.components.select.get(el)
ozi-check: source (switch/group/item) levelsource ahora es 'user'|'api'
ozi-search value = query; mantiene query/matched/total
ozi-auth novedad v2 — ahora emite CustomEvent (era solo jQuery)

Todos los componentes pasaron a emitir ozi:init (tras la inicialización) y ozi:destroy.

Compatibilidad sin reescribir (shims)

Si tienes consumidores en el formato posicional de la v1, activa el shim — escucha el CustomEvent y lo re-emite vía jQuery en el formato antiguo. Nada de tu código necesita cambiar.

  • integrations/adapters/ozi-change-v1-compat.shim.jsozi:change posicional
  • integrations/adapters/ozi-check-v1-events.shim.jsoziCheck:initFetched

Los shims son temporales y requieren jQuery. Migra a addEventListener cuando puedas.


4. Descontinuados: ozi-copy y ozi-paste

Fueron eliminados en la v2. Los sustitutos son recetas cortas en Alpine o JS puro — sin dependencia de FontAwesome.

<!-- Sustituto de ozi-copy -->
<button type="button"
        x-data="{ copied: false }"
        @click="navigator.clipboard.writeText('ABC-123').then(() => { copied = true; setTimeout(() => copied = false, 1500) })">
    <span x-text="copied ? '✓ copiado' : 'Copiar'"></span>
</button>

Los plugins v1 siguen disponibles en el tag v1-final.

ozi-audio NO fue descontinuado — sigue en el alcance y fue migrado (v4.0.0).


5. Livewire

El adapter ganó el modo nativo, que respeta los modificadores de wire:model:

<!-- Modo A (preferido): dispatch nativo — respeta .live/.debounce/.lazy -->
<div wire:ignore>
    <div data-ozi-select="uf" data-ozi-livewire-native="#uf-hidden"></div>
</div>
<input id="uf-hidden" type="hidden" wire:model="uf">

<!-- Modo B (compat): component.set() -->
<div data-ozi-select="uf" data-ozi-livewire-model="uf"></div>
  • Anti-loop: el adapter ignora ozi:change con source: 'api' (cambio proveniente del propio Livewire).
  • Re-init tras el morph: es tarea de ozi-hooks — nada que hacer.
  • Guard LW3 × LW4 automático.

6. Temas

El tema es dato: 4 archivos enlazados en el <head> (tokens.css, overrides.css, dark.css, classmap.js). El mismo build JS sirve los 3 temas — solo se cambia oziConf({ theme }).

<link rel="stylesheet" href="/plugins/ozi-ui/themes/tailwind/tokens.css">
<link rel="stylesheet" href="/plugins/ozi-ui/themes/tailwind/overrides.css"><!-- nuevo en la v2 -->
<link rel="stylesheet" href="/plugins/ozi-ui/themes/tailwind/dark.css">
<script>oziConf({ theme: 'tailwind' });</script>

Novedad v2: themes/tailwind/overrides.css, que no existía en la v1. ¿Tema propio? Copia themes/_template/.


7. Alias heredados

Siguen funcionando, con aviso en consola si core.log: true. Serán eliminados en una versión futura:

Alias v1 Usa en la v2
window.oziCore window.OZI
window.oziLoaddata window.oziLoadData
window.OziFrameworks OZI.integrations
window.zldActions(arr) OZI.modules.actions.run(arr)
window.oziValidateContainer(c) OZI.modules.validate.container(c)
zldParseBool / zldGenerateId / … OZI.helpers.*

8. Checklist de migración

  • [ ] Incluir jQuery por tu cuenta si la app dependía del que venía con ozi-ui (§2)
  • [ ] Cambiar los consumidores de ozi:change a addEventListener + e.detail (§3) — o activar el shim
  • [ ] Sustituir ozi-copy/ozi-paste por las recetas Alpine (§4)
  • [ ] (Livewire) evaluar el modo A (data-ozi-livewire-native) para respetar wire:model (§5)
  • [ ] (Tailwind) enlazar el nuevo overrides.css (§6)
  • [ ] Eliminar usos de alias heredados (§7)
  • [ ] Ejecutar la app con oziConf({ core: { log: true } }) para ver los avisos de deprecación

9. Lo que no cambia

  • Atributos data-ozi-* y data-zld-* (markup declarativo)
  • API pública: OZI.components.<nombre> y window.Ozi<Nombre>
  • oziConf({...}), @oziScripts / @oziStyles (Blade), OZI.ready()
  • ozi-loaddata: fetch, destino DOM, recolección, progress, actions — comportamiento idéntico