Integrator guide
Esta guía describe cómo integrar el plano en una app Angular. El contrato soportado es un solo camino: el selector upp-konva con una instancia de UppKonvaModel y filas DTO con kind.
- Referencia TypeDoc del modelo
lib/model/: Public model API (menú lateral). - README del paquete, tema y sideEffects: Package README y lab demo.
Los miembros de UppKonvaArea (y del modelo) marcados en el código con @internal son enganches del host o del motor Konva: no entran en la referencia TypeDoc generada con excludeInternal, no se declaran en el .d.ts publicado (stripInternal), y no deben tratarse como contrato en integraciones de producto. La superficie soportada para apps está descrita en esta guía y en los bindings de upp-konva (p. ej. (onSelect) en lugar de resolver ids del lienzo a mano).
1. Módulo y plantilla
1.1. Importar UppKonvaModule
import { NgModule } from '@angular/core';
import { UppKonvaModule } from '@unpispas/upp-konva';
@NgModule({
imports: [UppKonvaModule],
})
export class FloorPlanHostModule {}
1.2. Componente upp-konva
| Binding | Uso |
|---|---|
[model] | Instancia UppKonvaModel (obligatoria). |
[active] | boolean, por defecto true. Con false el lienzo reduce trabajo cuando el plano no hace falta animar o repintar al detalle. |
[theme] | UPPKONVA_LIGHTTHEME | UPPKONVA_DARKTHEME (preset). |
(onChange) | Sin payload; se dispara cuando cambia la lista de figuras a nivel estructural (alta/baja/reemplazo de filas). Enlazalo a onModelChanged del modelo si preferís callback en el TS. |
(onSelect) | Emite las UppKonvaShape vivas seleccionadas en el lienzo. |
<upp-konva
[model]="canvas"
[active]="planVisible"
[theme]="'UPPKONVA_DARKTHEME'"
(onChange)="onStructural()"
(onSelect)="onFigures($event)"
/>
El host expone data-id="upp-konva-integration" para pruebas automáticas.
1.3. Cableado recomendado
- Creá
new UppKonvaModel(initialSource)con unUppKonvaAreaSource(width,height,shapesconkindpor fila). - Asigná
canvas.onModelChangedsi necesitás lógica además del(onChange)del template (el host encadena ambos). - Para multi-selección, suscribite a
canvas.area.onGrouped$(RxJS), no a callbacks en el DTO. - Volcado de datos:
canvas.area.source,canvas.applyAreaFromSource(...),canvas.exportModel(),canvas.importModel(json),canvas.exportToPng().
2. UppKonvaModel (resumen)
| Miembro | Uso |
|---|---|
area | UppKonvaArea viva (misma referencia de por vida). Actualizar: area.source = … o applyAreaFromSource. Incluye area.selectShape(shape | null) para seleccionar en el lienzo una figura de area.shapes o limpiar la selección. |
mode | VIEW | EDIT. |
theme | Preset o null; combinable con [theme]. |
marginPx, viewZoom, pixelRatioMax | Presentación del encuadre (también configurables vía campos opcionales del DTO de sala). |
onModelChanged | Solo cuando cambia la lista estructural de figuras (id + kind en orden). |
exportModel, importModel, exportToPng | Serialización JSON y captura PNG mientras upp-konva está montado. |
pushUndoSnapshot, undo, canUndo | Pila de deshacer en EDIT. |
doDestroy() | Limpieza al destruir el componente o abandonar el modelo. |
Mutar una figura viva in situ (geometría, shapeData, etiquetas) no dispara onModelChanged; usá onUpdated$ de esa figura. Detalle en la referencia TypeDoc bajo Public model API.
3. Qué exporta el barrel desde lib/model/
Todo lo siguiente se importa desde @unpispas/upp-konva:
| Símbolo | Rol |
|---|---|
UppKonvaModel | Raíz del plano cableada a upp-konva. |
UppKonvaArea | Clase del área viva (model.area); static from(source) equivale al constructor interno del modelo. |
UppKonvaGroup | Multi-selección (onGrouped$). |
UppKonvaShape | Clase base abstracta de figuras vivas (geometría, shapeData, streams, remove(), …). |
Tipos DTO y de catálogo: UppKonvaAreaSource, UppKonvaShapeSource, UppKonvaShapeKind, UppKonvaOrientation, UppKonvaDrawMode, UppKonvaEditMode, UppKonvaTheme, UppKonvaAxis, UppKonvaLabelFontSize.
Importante: el barrel público no expone artefactos de stage ni subclases/fábricas internas de figuras. La integración se hace con la abstracción del model.
4. DTO: UppKonvaAreaSource y UppKonvaShapeSource
- Cada fila del array
shapeses unUppKonvaShapeSource:id,kind, geometría (x,y,width,height,rotationen cm y grados), opcionaleslabel,sublabel,zIndex,mode,custom, y bolsadatasegúnkind(ver §5). - El documento JSON versionado lo cubren
exportModel/importModeldesdeUppKonvaModel.
5. Catálogo UppKonvaShapeKind y campo data
Valores de kind (lista cerrada): VERTEX, TABLE, BAR, DOOR, WINDOW, STAIRS, BILLIARD, SOFA, FOOTBALL, GENERIC.
En figuras vivas, los mismos campos viven en shape.shapeData (objeto plano); al persistir, el modelo proyecta ese estado sobre el DTO público en area.source.
5.1. Campos comunes (todas las filas)
| Campo (DTO / vivo) | Uso |
|---|---|
id | Identificador estable de la fila (UUID recomendado). |
kind | Discriminante (en vivo: shape.kind de solo lectura). |
x, y, width, height, rotation | Geometría en cm y grados. |
label, sublabel | Texto del badge en el lienzo si no están vacíos; tras editar in situ usá syncLabelsToStage() en la figura viva. |
zIndex | Orden de pintado (§8). |
custom | Bolsa opaca para la app; puede reenviarse en payloads de selección/actualización. |
5.2. VERTEX
data | Tipo / valores | Uso |
|---|---|---|
sort | number | Orden dentro de la cadena de muro. |
poligon | string | Identificador de cadena; en JSON legacy a veces polygon (el parseo lo normaliza). |
closed | boolean | Si es true en todos los vértices de la misma cadena, el polígono se cierra y rellena. |
5.3. TABLE
data | Tipo / valores | Uso |
|---|---|---|
shape | SQUARE | CIRCLE | Mesa rectangular vs elíptica (CIRCLE = elipse en el bbox). En shapeData tras ciertos volcados del motor puede aparecer también ROUND como sinónimo de variante redonda. |
chairs | number ≥ 0 | Cantidad de sillas; 0 = solo tablero. Si omitís chairs al construir desde wire, el puente puede asumir un default (p. ej. 4). |
Resaltado “atención” en el lienzo (mesa u otra figura cableada): shape.attention = true / lectura shape.attention sobre la UppKonvaShape viva (no suele ir en el DTO UppKonvaShapeSource).
5.4. BAR
data | Tipo / valores | Uso |
|---|---|---|
shape | LINEAR | TOLEFT | TORIGHT | USHAPE | Forma de la barra. |
stoolLeft, stoolFront, stoolRight | number ≥ 0 o omitido | Taburetes por lado. Si omitís la clave, ese lado no lleva taburetes. stoolLeft/stoolRight aplican según la forma (p. ej. TOLEFT, USHAPE). |
En vista, onSelected$ puede traer stool: null = clic en el cuerpo de la barra; número = índice global del taburete.
5.5. DOOR, WINDOW, STAIRS
En el DTO público la variante va en data.shape (el motor la mapea a architectureShape internamente):
kind | data.shape (valores reconocidos) | Default típico |
|---|---|---|
DOOR | TOLEFT | TORIGHT | TOLEFT |
WINDOW | SINGLE | DOUBLE | SINGLE |
STAIRS | SIMPLE | DOUBLE | SNAIL | SIMPLE |
5.6. SOFA
data | Tipo / valores | Uso |
|---|---|---|
shape | LINEAR | TOLEFT | TORIGHT | Chaise recto o retorno en L a izquierda/derecha. |
5.7. GENERIC
data | Tipo / valores | Uso |
|---|---|---|
shape | SQUARE | ROUND | CIRCLE | Mueble genérico rectangular vs redondo (ROUND/CIRCLE → elipse en el bbox). |
5.8. BILLIARD y FOOTBALL
Sin variantes obligatorias en data: podés omitir data o dejarla vacía; la geometría es el bbox (x, y, width, height, rotation).
6. Figuras vivas: UppKonvaShape y shapeData
Las instancias viven en model.area.shapes. La clase base expone geometría (x, y, width, height, rotation), id, kind, label, sublabel, shapeData, onSelected$, onUpdated$, parentArea, remove(), syncPresentationToStage() (tras mutar shapeData sin cambiar geometría global), syncLabelsToStage(), doDestroy().
| Stream | Cuándo |
|---|---|
onSelected$ | Modo VIEW: selección simple en el lienzo (solo 1 elemento). |
onUpdated$ | Modo EDIT: cambios confirmados en el lienzo. |
Payload de streams: objeto con bolsa opcional custom y, en barras, campo opcional stool (como en §5.4).
Para acotar tipos en TypeScript, usar discriminación por shape.kind y leer/validar shape.shapeData según catálogo del kind.
7. Multi-selección: onGrouped$ y UppKonvaGroup
Con dos o más figuras seleccionadas, area.onGrouped$ emite un UppKonvaGroup; con cero o uno, emite null. Es el objeto de producto para alinear barras de herramientas con el lienzo ( selection, align, distribute, etc.). Ver la referencia TypeDoc bajo Public model API.
En selección múltiple, la notificación por figura shape.onSelected$ no se emite para evitar duplicar señal con onGrouped$.
8. Orden de pintado (zIndex)
zIndexnumérico: valores menores se dibujan más abajo. Por defecto0.- A igual
zIndex, el paquete aplica un orden interno estable.
9. Ejemplo mínimo
import { Component } from '@angular/core';
import { UppKonvaModel, type UppKonvaAreaSource } from '@unpispas/upp-konva';
@Component({
selector: 'app-floor-plan-shell',
templateUrl: './floor-plan-shell.component.html',
})
export class FloorPlanShellComponent {
readonly canvas = new UppKonvaModel({
width: 800,
height: 600,
name: 'Sala demo',
shapes: [
{
id: 't-1',
kind: 'TABLE',
x: 200,
y: 200,
width: 120,
height: 80,
rotation: 0,
data: { shape: 'SQUARE', chairs: 4 },
label: 'Mesa 1',
custom: { ticketId: 42 },
},
],
} satisfies UppKonvaAreaSource);
onStructural(): void {
void this.canvas.exportModel();
}
}
<upp-konva [model]="canvas" (onChange)="onStructural()" />
JSON sin modelo vivo
import {
adapterAreaToAreaSource,
areaSourceToAdapterArea,
parseFloorPlanDocument,
serializeFloorPlanDocument,
} from '@unpispas/upp-konva';
const parsed = parseFloorPlanDocument(json);
if (!parsed.ok) {
throw new Error(parsed.message);
}
const model = new UppKonvaModel(adapterAreaToAreaSource(parsed.area));
// Con modelo vivo suele bastar `model.exportModel()`.
const wireJson = serializeFloorPlanDocument(areaSourceToAdapterArea(model.area.source));
parseFloorPlanDocument devuelve UppKonvaWireArea; adapterAreaToAreaSource la convierte al DTO público con kind. serializeFloorPlanDocument espera UppKonvaWireArea (areaSourceToAdapterArea(model.area.source)).
Related
- Public model API — referencia TypeDoc (JSDoc) del modelo y DTO
kind. - Package README — referencia amplia del paquete.
- Host implementation — cableado interno host ↔ stage (mantenimiento).
- Lab demo — demo en el monorepo.
- Overview — alcance del paquete.