venuekit 0.0.0-stage → 0.10.0
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/LICENSE +21 -0
- package/README.md +325 -2
- package/dist/chunk-47ILVPKZ.cjs +1311 -0
- package/dist/chunk-5H5QKXPV.js +1311 -0
- package/dist/index.cjs +180 -0
- package/dist/index.d.cts +256 -0
- package/dist/index.d.ts +256 -0
- package/dist/index.js +180 -0
- package/dist/place-types-CeTjPHTF.d.cts +670 -0
- package/dist/place-types-CeTjPHTF.d.ts +670 -0
- package/dist/react.cjs +5966 -0
- package/dist/react.d.cts +584 -0
- package/dist/react.d.ts +584 -0
- package/dist/react.js +5966 -0
- package/package.json +88 -4
package/dist/react.d.cts
ADDED
|
@@ -0,0 +1,584 @@
|
|
|
1
|
+
import { a as Layout, S as SellableUnit, f as LockViolation, r as PieceKind, w as PlanSummary, v as PlaceTypeOption } from './place-types-CeTjPHTF.cjs';
|
|
2
|
+
import { CSSProperties, ReactElement, ReactNode } from 'react';
|
|
3
|
+
import 'zod';
|
|
4
|
+
|
|
5
|
+
/** Todo el copy del mapa del comprador. Los `{marcadores}` los reemplaza `format`. */
|
|
6
|
+
type Messages = {
|
|
7
|
+
free: string;
|
|
8
|
+
taken: string;
|
|
9
|
+
selected: string;
|
|
10
|
+
held: string;
|
|
11
|
+
row: string;
|
|
12
|
+
seat: string;
|
|
13
|
+
legendFree: string;
|
|
14
|
+
legendMine: string;
|
|
15
|
+
legendTaken: string;
|
|
16
|
+
summaryRow: string;
|
|
17
|
+
summarySeat: string;
|
|
18
|
+
summarySeats: string;
|
|
19
|
+
summaryTable: string;
|
|
20
|
+
summaryPlace: string;
|
|
21
|
+
summaryPlaces: string;
|
|
22
|
+
listAnd: string;
|
|
23
|
+
nothingSelected: string;
|
|
24
|
+
holdNotice: string;
|
|
25
|
+
continueLabel: string;
|
|
26
|
+
maxReached: string;
|
|
27
|
+
takenSeat: string;
|
|
28
|
+
takenTable: string;
|
|
29
|
+
takenPlace: string;
|
|
30
|
+
heldSeat: string;
|
|
31
|
+
conflictSeat: string;
|
|
32
|
+
conflictTable: string;
|
|
33
|
+
conflictPlace: string;
|
|
34
|
+
unassigned: string;
|
|
35
|
+
mapLabel: string;
|
|
36
|
+
zoomIn: string;
|
|
37
|
+
zoomOut: string;
|
|
38
|
+
overviewMapLabel: string;
|
|
39
|
+
overviewList: string;
|
|
40
|
+
soldOut: string;
|
|
41
|
+
soldOutNotice: string;
|
|
42
|
+
/** Embebido sin lista (`hideList`): el nombre del plano apunta a la lista que sigue al lienzo. */
|
|
43
|
+
overviewInlineLabel: string;
|
|
44
|
+
/** Encabezado del mapa entero embebido (`showHint`). */
|
|
45
|
+
overviewHint: string;
|
|
46
|
+
backToMap: string;
|
|
47
|
+
focusHintSeats: string;
|
|
48
|
+
focusHintPlaces: string;
|
|
49
|
+
focusHintTables: string;
|
|
50
|
+
};
|
|
51
|
+
declare const es: Messages;
|
|
52
|
+
declare const en: Messages;
|
|
53
|
+
/** Reemplaza `{clave}` por su valor. Lo que no le pasan, queda como está. */
|
|
54
|
+
declare function format(template: string, vars: Record<string, string | number>): string;
|
|
55
|
+
/**
|
|
56
|
+
* Lo que puede mandar el host. Acepta `undefined` explícito a propósito: una
|
|
57
|
+
* app con `exactOptionalPropertyTypes` apagado escribe `{ x: cond ? a : undefined }`
|
|
58
|
+
* sin pensarlo, y en runtime ya lo ignoramos. Ser estricto acá sólo obliga al
|
|
59
|
+
* host a hacer malabares con el spread.
|
|
60
|
+
*/
|
|
61
|
+
type MessageOverrides = {
|
|
62
|
+
[K in keyof Messages]?: Messages[K] | undefined;
|
|
63
|
+
};
|
|
64
|
+
/** Copy final: es-AR pisado por lo que mande el host. Un `undefined` no pisa nada. */
|
|
65
|
+
declare function mergeMessages(overrides?: MessageOverrides): Messages;
|
|
66
|
+
|
|
67
|
+
type SeatMapPlaceType = {
|
|
68
|
+
ref: string;
|
|
69
|
+
label: string;
|
|
70
|
+
color: string;
|
|
71
|
+
priceLabel?: string;
|
|
72
|
+
};
|
|
73
|
+
type SeatMapProps = {
|
|
74
|
+
layout: Layout;
|
|
75
|
+
placeTypes: SeatMapPlaceType[];
|
|
76
|
+
/** El tipo de lugar que eligió el comprador: el mapa encuadra ahí, el resto se atenúa y no se elige. */
|
|
77
|
+
focusRef: string;
|
|
78
|
+
takenUnitIds: readonly string[];
|
|
79
|
+
heldUnitIds?: readonly string[];
|
|
80
|
+
selection: string[];
|
|
81
|
+
onSelectionChange: (ids: string[]) => void;
|
|
82
|
+
maxSelection?: number;
|
|
83
|
+
/**
|
|
84
|
+
* Lo que el host manda tras un 409: pasan a vendidas, salen de la selección y se avisa.
|
|
85
|
+
* Quedan vendidas mientras el componente esté montado, aunque el host las libere después.
|
|
86
|
+
*/
|
|
87
|
+
conflictUnitIds?: readonly string[];
|
|
88
|
+
/** Total ya formateado por el host. La librería nunca formatea plata. */
|
|
89
|
+
totalLabel?: string;
|
|
90
|
+
holdMinutes?: number;
|
|
91
|
+
onContinue?: () => void;
|
|
92
|
+
continueLabel?: string;
|
|
93
|
+
/** El mapa ES la página: ocupa la pantalla y la barra queda abajo. */
|
|
94
|
+
fill?: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Adentro de una tarjeta del host, que muestra la selección en su propia lista:
|
|
97
|
+
* sin la barra de total y continuar, con un encabezado del sector y el plano
|
|
98
|
+
* sin borde propio. El resto del plano se ve atenuado alrededor.
|
|
99
|
+
*/
|
|
100
|
+
embedded?: boolean;
|
|
101
|
+
/** Embebido: muestra «← Todo el mapa» en el encabezado y lo llama al tocarlo. */
|
|
102
|
+
onBack?: () => void;
|
|
103
|
+
/** Tocaron una zona o un lugar de OTRO tipo de `placeTypes`: el host decide si cambia `focusRef`. */
|
|
104
|
+
onFocusChange?: (ref: string) => void;
|
|
105
|
+
/** Alto fijo del mapa en píxeles. Sin esto, la caja sigue la proporción del plano. */
|
|
106
|
+
height?: number;
|
|
107
|
+
messages?: MessageOverrides;
|
|
108
|
+
className?: string;
|
|
109
|
+
style?: CSSProperties;
|
|
110
|
+
};
|
|
111
|
+
declare function SeatMap(props: SeatMapProps): ReactElement;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Lo elegido en palabras: "Fila C · butacas 7 y 8", "Mesa 4", "Mesa 4 · lugares 2 y 3".
|
|
115
|
+
* Agrupa por fila o por mesa, en el orden en que se eligió cada grupo.
|
|
116
|
+
*/
|
|
117
|
+
declare function selectionSummary(units: SellableUnit[], ids: readonly string[], m: Messages): string;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* CSS del mapa del comprador (`<SeatMap />`). Va en un `<style>` adentro del
|
|
121
|
+
* componente (no hay archivo `.css` que el host tenga que importar, ni efectos
|
|
122
|
+
* al cargar el módulo, que es lo que rompe el SSR). Una sola columna: mapa,
|
|
123
|
+
* leyenda, aviso y barra, igual en el celular y en la computadora.
|
|
124
|
+
*
|
|
125
|
+
* La capa de accesibilidad (`vk-a11y`) es transparente y no recibe punteros:
|
|
126
|
+
* los dedos y el mouse van al lienzo, que sabe distinguir un toque de un
|
|
127
|
+
* arrastre. El teclado y los lectores de pantalla sí llegan a los botones,
|
|
128
|
+
* porque activarlos dispara un click sin pasar por el hit-testing del mouse.
|
|
129
|
+
*
|
|
130
|
+
* **Cómo lo tematiza el host.** Todo lo que se ve sale de las variables de
|
|
131
|
+
* abajo. Se declaran con `:where()`, que tiene especificidad cero, así que
|
|
132
|
+
* una regla común del host las pisa aunque esta hoja se renderice adentro del
|
|
133
|
+
* componente y quede última en el documento (o el host las pasa por `style`):
|
|
134
|
+
*
|
|
135
|
+
* ```css
|
|
136
|
+
* .vk-root {
|
|
137
|
+
* --vk-accent: var(--primary);
|
|
138
|
+
* --vk-bg: var(--card);
|
|
139
|
+
* --vk-fg: var(--foreground);
|
|
140
|
+
* --vk-radius: var(--radius-control);
|
|
141
|
+
* }
|
|
142
|
+
* ```
|
|
143
|
+
*
|
|
144
|
+
* Las que además pinta el lienzo (`--vk-taken`, `--vk-shape`, `--vk-fg`, …)
|
|
145
|
+
* las lee `<VenueCanvas>` con `getComputedStyle` y se las pasa al render, así
|
|
146
|
+
* que el mapa sigue al tema igual que el resto.
|
|
147
|
+
*/
|
|
148
|
+
declare const PICKER_CSS = "\n:where(.vk-root){\n --vk-fg:#0f172a;\n --vk-muted:#64748b;\n --vk-line:#e2e8f0;\n --vk-bg:#ffffff;\n --vk-surface:#f8fafc;\n --vk-accent:#0f172a;\n --vk-accent-fg:#ffffff;\n --vk-radius:8px;\n --vk-radius-lg:12px;\n --vk-font:14px/1.45 system-ui,-apple-system,sans-serif;\n /* S\u00F3lo las dibuja el lienzo (y la leyenda). */\n --vk-taken:#cbd5e1;\n --vk-taken-stroke:#94a3b8;\n --vk-held-stroke:#b45309;\n --vk-shape:#94a3b8;\n --vk-shape-fill:#e2e8f0;\n --vk-unassigned:#9ca3af;\n --vk-zone-alpha:38;\n /* Mapa del comprador: tuya, vendida, numero sobre la butaca y referencias. */\n --vk-zone-alpha-selected:66;\n --vk-mine:#ffffff;\n --vk-sold:#2a2a31;\n --vk-sold-stroke:#3a3a44;\n --vk-sold-fg:#6a6a74;\n --vk-unit-fg:#0b0b0d;\n --vk-landmark:#23232a;\n --vk-landmark-stroke:#34343c;\n --vk-landmark-fg:#d6d6dc;\n}\n.vk-root{display:flex;flex-direction:column;gap:12px;font:var(--vk-font);\n color:var(--vk-fg);background:var(--vk-bg);position:relative;box-sizing:border-box;\n /* Sin alto propio: embebido en la pagina de un host, mide lo que mide su\n contenido. El alto de pantalla completa esta detras de data-fill.\n (Sin acentos graves en este comentario: vive adentro de un template literal\n de TypeScript y cada uno lo cortaria al medio.) */\n }\n.vk-root[data-fill=\"true\"]{height:100vh;height:100dvh;max-height:100dvh}\n.vk-root *{box-sizing:border-box}\n/* El alto sale de la proporcion del plano (--vk-plan-ratio, lo pone el\n componente), acotado para que un plano muy alto no empuje la barra fuera\n de la pantalla ni uno muy apaisado quede en una tira. */\n.vk-map{position:relative;flex:none;width:100%;aspect-ratio:var(--vk-plan-ratio, 3 / 2);\n min-height:300px;max-height:70vh;background:var(--vk-surface);\n border:1px solid var(--vk-line);border-radius:var(--vk-radius-lg);overflow:hidden;touch-action:none}\n.vk-root[data-fill=\"true\"] .vk-map{flex:1;aspect-ratio:auto;min-height:0;max-height:none}\n.vk-canvas{display:block;width:100%;height:100%}\n.vk-a11y{position:absolute;inset:0;pointer-events:none}\n.vk-seat{position:absolute;transform:translate(-50%,-50%);padding:0;margin:0;border:0;background:transparent;\n border-radius:50%;cursor:pointer;color:transparent;overflow:hidden}\n.vk-seat:focus-visible{outline:3px solid var(--vk-accent);outline-offset:2px}\n.vk-zoom{position:absolute;right:8px;bottom:8px;display:flex;flex-direction:column;gap:4px}\n.vk-zoom button{width:36px;height:36px;border:1px solid var(--vk-line);background:var(--vk-bg);\n color:var(--vk-fg);border-radius:var(--vk-radius);font-size:16px;line-height:1;cursor:pointer}\n.vk-type{margin:0;display:flex;align-items:center;gap:8px;font-weight:600}\n.vk-legend{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:6px 16px;\n color:var(--vk-muted);font-size:13px}\n.vk-legend li{display:flex;align-items:center;gap:6px}\n.vk-dot{width:14px;height:14px;border-radius:50%;flex:none;box-sizing:border-box}\n.vk-dot[data-state=\"selected\"]{background:var(--vk-mine);border:3px solid var(--vk-accent)}\n.vk-dot[data-state=\"taken\"]{background:var(--vk-sold);border:1px solid var(--vk-sold-stroke)}\n.vk-cta{border:1px solid var(--vk-accent);background:var(--vk-accent);color:var(--vk-accent-fg);\n border-radius:var(--vk-radius);padding:10px 16px;cursor:pointer;font-size:14px;font-weight:600;min-height:44px}\n.vk-cta:disabled{opacity:.5;cursor:default}\n.vk-bar{flex:none;display:flex;align-items:center;gap:12px;padding:12px;\n border:1px solid var(--vk-line);border-radius:var(--vk-radius-lg);background:var(--vk-bg)}\n.vk-bar-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}\n.vk-bar-summary{font-weight:600}\n.vk-bar-total{font-variant-numeric:tabular-nums}\n.vk-bar-hold{color:var(--vk-muted);font-size:13px}\n.vk-notice{margin:0;padding:8px 12px;border-radius:var(--vk-radius);background:var(--vk-surface);\n border:1px solid var(--vk-line);color:var(--vk-fg);font-size:13px}\n.vk-notice:empty{display:none}\n.vk-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}\n/* El mapa entero: debajo, un boton por entrada (lo que usa el teclado y el lector). */\n.vk-types{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}\n.vk-type-btn{display:flex;align-items:center;gap:10px;width:100%;min-height:48px;padding:10px 14px;\n border:1px solid var(--vk-line);border-radius:var(--vk-radius);background:var(--vk-bg);color:var(--vk-fg);\n font:inherit;text-align:left;cursor:pointer}\n.vk-type-btn:hover{border-color:var(--vk-accent)}\n.vk-type-btn:focus-visible{outline:3px solid var(--vk-accent);outline-offset:2px}\n.vk-type-btn[aria-disabled=\"true\"]{cursor:default;opacity:.55}\n.vk-type-btn[aria-disabled=\"true\"]:hover{border-color:var(--vk-line)}\n.vk-type-name{flex:1;min-width:0;font-weight:600;overflow-wrap:anywhere}\n.vk-type-price{flex:none;font-variant-numeric:tabular-nums;color:var(--vk-muted)}\n.vk-type-out{flex:none;font-size:13px;font-weight:600;color:var(--vk-muted)}\n/* Embebido en una tarjeta del host: sin borde propio, encabezado arriba y leyenda abajo. */\n.vk-root[data-embedded=\"true\"]{gap:0}\n.vk-root[data-embedded=\"true\"] .vk-map{border:0;border-radius:0}\n.vk-root[data-embedded=\"true\"] .vk-legend{padding:12px 16px;border-top:1px solid var(--vk-line)}\n.vk-root[data-embedded=\"true\"] .vk-notice{margin:8px 14px 0}\n.vk-head{margin:0;display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;min-height:52px;padding:8px 14px;\n border-bottom:1px solid var(--vk-line)}\n.vk-back{display:inline-flex;align-items:center;gap:6px;min-height:44px;padding:0 12px;border:1px solid var(--vk-line);\n border-radius:var(--vk-radius);background:transparent;color:var(--vk-fg);font:inherit;cursor:pointer}\n.vk-back:focus-visible{outline:3px solid var(--vk-accent);outline-offset:2px}\n.vk-head-title{display:inline-flex;align-items:center;gap:8px;min-width:0;font-weight:700;overflow-wrap:anywhere}\n.vk-head-hint{min-width:0;color:var(--vk-muted);font-size:13px}\n/* Con hideList la lista sigue para el teclado y el lector, oculta hasta que un boton toma el foco. */\n.vk-types[data-hidden=\"true\"]:not(:focus-within){position:absolute;width:1px;height:1px;margin:-1px;padding:0;\n overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}\n.vk-types[data-hidden=\"true\"]:focus-within{padding:12px 14px;border-top:1px solid var(--vk-line)}\n.vk-type-btn[data-selected=\"true\"]{border-color:var(--vk-accent)}\n";
|
|
149
|
+
|
|
150
|
+
type VenueOverviewPlaceType = {
|
|
151
|
+
ref: string;
|
|
152
|
+
label: string;
|
|
153
|
+
color: string;
|
|
154
|
+
/** Precio ya formateado por el host. La librería nunca formatea plata. */
|
|
155
|
+
priceLabel?: string;
|
|
156
|
+
/** `false` = agotada: se ve atenuada, dice «Agotada» y no se elige. */
|
|
157
|
+
available?: boolean;
|
|
158
|
+
};
|
|
159
|
+
type VenueOverviewProps = {
|
|
160
|
+
layout: Layout;
|
|
161
|
+
placeTypes: VenueOverviewPlaceType[];
|
|
162
|
+
/** Se tocó una zona o un lugar de ese tipo (o su botón de la lista). No elige butacas: eso es `<SeatMap />`. */
|
|
163
|
+
onSelect: (ref: string) => void;
|
|
164
|
+
/**
|
|
165
|
+
* Para usarlo adentro de una tarjeta del host, que ya tiene su lista de entradas:
|
|
166
|
+
* sin la lista de abajo. Los mismos botones quedan para el teclado y el lector,
|
|
167
|
+
* ocultos hasta que uno recibe el foco.
|
|
168
|
+
*/
|
|
169
|
+
hideList?: boolean;
|
|
170
|
+
/** Encabezado con «Tocá un sector para elegirlo…» arriba del mapa. */
|
|
171
|
+
showHint?: boolean;
|
|
172
|
+
/** Tipos con algo elegido: sus zonas se pintan más fuertes. */
|
|
173
|
+
selectedRefs?: readonly string[];
|
|
174
|
+
/** Lugares vendidos, para verlos en miniatura. */
|
|
175
|
+
takenUnitIds?: readonly string[];
|
|
176
|
+
/** Lugares que eligió el comprador, para verlos en miniatura. */
|
|
177
|
+
selectedUnitIds?: readonly string[];
|
|
178
|
+
/** Alto fijo en píxeles. Sin esto, la caja sigue la proporción del plano. */
|
|
179
|
+
height?: number;
|
|
180
|
+
messages?: MessageOverrides;
|
|
181
|
+
className?: string;
|
|
182
|
+
style?: CSSProperties;
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* El mapa entero del lugar, para quien compra: todas las entradas con su color,
|
|
186
|
+
* las generales como zonas con su nombre. Tocar una zona o cualquier lugar de un
|
|
187
|
+
* tipo llama `onSelect(ref)`; lo que no es de ninguna entrada va en gris y no se
|
|
188
|
+
* toca. Debajo, un botón por entrada: el mismo camino para el teclado y el lector,
|
|
189
|
+
* que en el lienzo no tienen a qué apuntar. Con `hideList` esa lista no se ve
|
|
190
|
+
* (el host tiene la suya) pero sigue ahí para el teclado y el lector.
|
|
191
|
+
*/
|
|
192
|
+
declare function VenueOverview(props: VenueOverviewProps): ReactElement;
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Copy del editor, aparte del mapa del comprador.
|
|
196
|
+
*
|
|
197
|
+
* Son dos productos con dos audiencias: el comprador y el productor. Un solo
|
|
198
|
+
* objeto de mensajes obligaría a un host que sólo usa el mapa a cargar —y a
|
|
199
|
+
* traducir— el vocabulario del editor.
|
|
200
|
+
*/
|
|
201
|
+
type DesignerMessages = {
|
|
202
|
+
undo: string;
|
|
203
|
+
redo: string;
|
|
204
|
+
save: string;
|
|
205
|
+
saving: string;
|
|
206
|
+
addTitle: string;
|
|
207
|
+
addHint: string;
|
|
208
|
+
pieceSeatBlock: string;
|
|
209
|
+
pieceRoundTable: string;
|
|
210
|
+
pieceRectTable: string;
|
|
211
|
+
landmarksTitle: string;
|
|
212
|
+
groupAccess: string;
|
|
213
|
+
groupBar: string;
|
|
214
|
+
groupService: string;
|
|
215
|
+
groupStage: string;
|
|
216
|
+
groupSpace: string;
|
|
217
|
+
armedHint: string;
|
|
218
|
+
cancel: string;
|
|
219
|
+
placeAtCentre: string;
|
|
220
|
+
canvasLabel: string;
|
|
221
|
+
zoomIn: string;
|
|
222
|
+
zoomOut: string;
|
|
223
|
+
fitView: string;
|
|
224
|
+
pieceBlockName: string;
|
|
225
|
+
pieceTableName: string;
|
|
226
|
+
seatRemove: string;
|
|
227
|
+
seatRestore: string;
|
|
228
|
+
inspectorTitle: string;
|
|
229
|
+
nothingSelected: string;
|
|
230
|
+
rows: string;
|
|
231
|
+
cols: string;
|
|
232
|
+
shape: string;
|
|
233
|
+
straight: string;
|
|
234
|
+
curved: string;
|
|
235
|
+
editSeats: string;
|
|
236
|
+
seatEditHint: string;
|
|
237
|
+
seatEditDone: string;
|
|
238
|
+
seatEditZoomIn: string;
|
|
239
|
+
tableNumber: string;
|
|
240
|
+
places: string;
|
|
241
|
+
landmarkName: string;
|
|
242
|
+
placeType: string;
|
|
243
|
+
unassigned: string;
|
|
244
|
+
sellWhole: string;
|
|
245
|
+
sellPerPlace: string;
|
|
246
|
+
rotate: string;
|
|
247
|
+
duplicate: string;
|
|
248
|
+
remove: string;
|
|
249
|
+
placeTypesTitle: string;
|
|
250
|
+
notOnPlan: string;
|
|
251
|
+
unassignedPiece: string;
|
|
252
|
+
unassignedPieces: string;
|
|
253
|
+
countSeat: string;
|
|
254
|
+
countSeats: string;
|
|
255
|
+
countTable: string;
|
|
256
|
+
countTables: string;
|
|
257
|
+
countPlace: string;
|
|
258
|
+
countPlaces: string;
|
|
259
|
+
countType: string;
|
|
260
|
+
countTypes: string;
|
|
261
|
+
summaryAnd: string;
|
|
262
|
+
summaryIn: string;
|
|
263
|
+
summaryEmpty: string;
|
|
264
|
+
dismiss: string;
|
|
265
|
+
saveFailed: string;
|
|
266
|
+
close: string;
|
|
267
|
+
summaryTitle: string;
|
|
268
|
+
addHintCompact: string;
|
|
269
|
+
summaryEmptyCompact: string;
|
|
270
|
+
rejectTable: string;
|
|
271
|
+
rejectRow: string;
|
|
272
|
+
rejectMore: string;
|
|
273
|
+
duplicateSeats: string;
|
|
274
|
+
duplicateSeatItem: string;
|
|
275
|
+
duplicateTables: string;
|
|
276
|
+
tableLabelTaken: string;
|
|
277
|
+
firstRow: string;
|
|
278
|
+
firstSeat: string;
|
|
279
|
+
backgroundTitle: string;
|
|
280
|
+
backgroundHint: string;
|
|
281
|
+
backgroundPick: string;
|
|
282
|
+
backgroundSuggested: string;
|
|
283
|
+
backgroundLoading: string;
|
|
284
|
+
backgroundFailed: string;
|
|
285
|
+
backgroundArrange: string;
|
|
286
|
+
backgroundSize: string;
|
|
287
|
+
backgroundOpacity: string;
|
|
288
|
+
backgroundLock: string;
|
|
289
|
+
backgroundRemove: string;
|
|
290
|
+
backgroundWarning: string;
|
|
291
|
+
backgroundEditHint: string;
|
|
292
|
+
backgroundEditHintCompact: string;
|
|
293
|
+
back: string;
|
|
294
|
+
planTitle: string;
|
|
295
|
+
done: string;
|
|
296
|
+
addLandmark: string;
|
|
297
|
+
landmarkSearch: string;
|
|
298
|
+
landmarkNone: string;
|
|
299
|
+
landmarkHint: string;
|
|
300
|
+
typesTitle: string;
|
|
301
|
+
typesHint: string;
|
|
302
|
+
typesEmpty: string;
|
|
303
|
+
typesButton: string;
|
|
304
|
+
typesMissingBadge: string;
|
|
305
|
+
typeMissing: string;
|
|
306
|
+
acceptsSeats: string;
|
|
307
|
+
acceptsWhole: string;
|
|
308
|
+
acceptsPerPlace: string;
|
|
309
|
+
countBlock: string;
|
|
310
|
+
countBlocks: string;
|
|
311
|
+
noBlocks: string;
|
|
312
|
+
noTables: string;
|
|
313
|
+
addBlock: string;
|
|
314
|
+
addAnotherBlock: string;
|
|
315
|
+
addRoundTable: string;
|
|
316
|
+
addSquareTable: string;
|
|
317
|
+
addSharedTable: string;
|
|
318
|
+
addPieceFor: string;
|
|
319
|
+
onPlan: string;
|
|
320
|
+
missingToPublish: string;
|
|
321
|
+
perRow: string;
|
|
322
|
+
rowsLess: string;
|
|
323
|
+
rowsMore: string;
|
|
324
|
+
colsLess: string;
|
|
325
|
+
colsMore: string;
|
|
326
|
+
placesLess: string;
|
|
327
|
+
placesMore: string;
|
|
328
|
+
roundShape: string;
|
|
329
|
+
squareShape: string;
|
|
330
|
+
blockRange: string;
|
|
331
|
+
blockRangeOneRow: string;
|
|
332
|
+
numbering: string;
|
|
333
|
+
numberingTitle: string;
|
|
334
|
+
numberingHint: string;
|
|
335
|
+
numberingTooBig: string;
|
|
336
|
+
numberingFailed: string;
|
|
337
|
+
rowsNamed: string;
|
|
338
|
+
rowsLetters: string;
|
|
339
|
+
rowsNumbers: string;
|
|
340
|
+
startsAt: string;
|
|
341
|
+
seatsTitle: string;
|
|
342
|
+
seatsStartAt: string;
|
|
343
|
+
numberFrom: string;
|
|
344
|
+
fromLeft: string;
|
|
345
|
+
fromRight: string;
|
|
346
|
+
skipRows: string;
|
|
347
|
+
skipRowsPlaceholder: string;
|
|
348
|
+
skipSeats: string;
|
|
349
|
+
skipSeatsPlaceholder: string;
|
|
350
|
+
useEnye: string;
|
|
351
|
+
seatPattern: string;
|
|
352
|
+
patternSequential: string;
|
|
353
|
+
patternOdd: string;
|
|
354
|
+
patternEven: string;
|
|
355
|
+
patternCenter: string;
|
|
356
|
+
patternCenterHint: string;
|
|
357
|
+
centerOddsTo: string;
|
|
358
|
+
centerEvensTo: string;
|
|
359
|
+
result: string;
|
|
360
|
+
resultRange: string;
|
|
361
|
+
resultRangeOneRow: string;
|
|
362
|
+
resultOnSale: string;
|
|
363
|
+
removedOne: string;
|
|
364
|
+
removedMany: string;
|
|
365
|
+
legendOnSale: string;
|
|
366
|
+
legendRemoved: string;
|
|
367
|
+
seatName: string;
|
|
368
|
+
seatNameRemoved: string;
|
|
369
|
+
seatNameSold: string;
|
|
370
|
+
assignTitle: string;
|
|
371
|
+
noPlaceTypes: string;
|
|
372
|
+
capacityCount: string;
|
|
373
|
+
capacityFull: string;
|
|
374
|
+
capacityOver: string;
|
|
375
|
+
trimToCapacity: string;
|
|
376
|
+
trimToCapacityLabel: string;
|
|
377
|
+
trimPartial: string;
|
|
378
|
+
rejectCapacity: string;
|
|
379
|
+
zonesTitle: string;
|
|
380
|
+
zonesHint: string;
|
|
381
|
+
acceptsZone: string;
|
|
382
|
+
countZone: string;
|
|
383
|
+
countZones: string;
|
|
384
|
+
noZones: string;
|
|
385
|
+
addZone: string;
|
|
386
|
+
addAnotherZone: string;
|
|
387
|
+
pieceZone: string;
|
|
388
|
+
zoneWidth: string;
|
|
389
|
+
zoneHeight: string;
|
|
390
|
+
widthLess: string;
|
|
391
|
+
widthMore: string;
|
|
392
|
+
heightLess: string;
|
|
393
|
+
heightMore: string;
|
|
394
|
+
/** Tamaño de un bloque o una mesa respecto del original. */
|
|
395
|
+
pieceSize: string;
|
|
396
|
+
/** "{n} %": el tamaño, como lo lee la persona. */
|
|
397
|
+
pieceSizeValue: string;
|
|
398
|
+
sizeLess: string;
|
|
399
|
+
sizeMore: string;
|
|
400
|
+
/** Nombre accesible de cada manija de las esquinas. `{name}`: la pieza. */
|
|
401
|
+
resizeHandle: string;
|
|
402
|
+
/** Título del panel con varias piezas elegidas. `{n}`: cuántas. */
|
|
403
|
+
selectionCount: string;
|
|
404
|
+
selectionHint: string;
|
|
405
|
+
selectionHintCompact: string;
|
|
406
|
+
alignGroup: string;
|
|
407
|
+
alignLeft: string;
|
|
408
|
+
alignCentreX: string;
|
|
409
|
+
alignRight: string;
|
|
410
|
+
alignTop: string;
|
|
411
|
+
alignCentreY: string;
|
|
412
|
+
alignBottom: string;
|
|
413
|
+
distributeGroup: string;
|
|
414
|
+
distributeX: string;
|
|
415
|
+
distributeY: string;
|
|
416
|
+
sizeGroup: string;
|
|
417
|
+
sameWidth: string;
|
|
418
|
+
sameHeight: string;
|
|
419
|
+
sameSize: string;
|
|
420
|
+
duplicateAll: string;
|
|
421
|
+
removeAll: string;
|
|
422
|
+
};
|
|
423
|
+
declare const designerEs: DesignerMessages;
|
|
424
|
+
declare const designerEn: DesignerMessages;
|
|
425
|
+
type DesignerOverrides = {
|
|
426
|
+
[K in keyof DesignerMessages]?: DesignerMessages[K] | undefined;
|
|
427
|
+
};
|
|
428
|
+
declare function mergeDesignerMessages(overrides?: DesignerOverrides): DesignerMessages;
|
|
429
|
+
|
|
430
|
+
/** Un tipo que el cambio habría pasado de su cupo. `placed`: lo que ya tenía antes del cambio. */
|
|
431
|
+
type CapacityRejection = {
|
|
432
|
+
ref: string;
|
|
433
|
+
label: string;
|
|
434
|
+
capacity: number;
|
|
435
|
+
placed: number;
|
|
436
|
+
};
|
|
437
|
+
/** Por qué no se aplicó un cambio: lo vendido (`violations`) o el cupo de una entrada (`capacity`). */
|
|
438
|
+
type DesignerRejection = {
|
|
439
|
+
violations: LockViolation[];
|
|
440
|
+
capacity?: CapacityRejection[];
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Lo que el host necesita para dibujar su propio panel de entradas al lado del
|
|
445
|
+
* editor (`VenueDesigner.sidePanel`). Lo de leer se calcula acá, sin React,
|
|
446
|
+
* para probarlo en Node; lo que actúa sobre el lienzo lo arma el editor.
|
|
447
|
+
*/
|
|
448
|
+
/** Lo que una entrada ya tiene en el plano. */
|
|
449
|
+
type PlacedCount = {
|
|
450
|
+
/** Lugares a la venta: butacas, mesas enteras o lugares en mesa. */
|
|
451
|
+
units: number;
|
|
452
|
+
/** Zonas marcadas (entradas generales). */
|
|
453
|
+
zones: number;
|
|
454
|
+
/** Piezas: bloques, mesas o zonas. */
|
|
455
|
+
pieces: number;
|
|
456
|
+
};
|
|
457
|
+
type DesignerHostApi = {
|
|
458
|
+
/**
|
|
459
|
+
* Agrega una pieza de esa entrada, ya asignada: en el centro de lo que se ve,
|
|
460
|
+
* sin encimarse, con lo que falta del cupo (bloque de a tramos). La deja
|
|
461
|
+
* elegida y a la vista; en el celular abre su hoja. `null` si la entrada no
|
|
462
|
+
* existe, la pieza no le sirve (un bloque para una mesa) o el cupo está completo.
|
|
463
|
+
*/
|
|
464
|
+
addPiece: (kind: PieceKind, ref: string) => string | null;
|
|
465
|
+
/** Lugares que traería la próxima pieza. 0 = cupo completo (o la entrada no existe). Zonas: 1. */
|
|
466
|
+
nextPieceUnits: (ref: string) => number;
|
|
467
|
+
placed: (ref: string) => PlacedCount;
|
|
468
|
+
/** «30 de 100 lugares»; `null` sin cupo o si es una zona. */
|
|
469
|
+
capacityText: (ref: string) => string | null;
|
|
470
|
+
/** «Ya ubicaste los 100 lugares de Platea» (o cuánto sobra); `null` mientras entre otra pieza. */
|
|
471
|
+
capacityFullText: (ref: string) => string | null;
|
|
472
|
+
/** Cuántos lugares sobran por encima del cupo (el host lo bajó). 0 si ninguno, sin cupo o si la entrada no existe. */
|
|
473
|
+
overCapacity: (ref: string) => number;
|
|
474
|
+
/**
|
|
475
|
+
* «Ajustar»: saca los lugares que sobran empezando por los últimos (última fila del
|
|
476
|
+
* último bloque de esa entrada hacia atrás; mesas enteras, las últimas mesas), en UN
|
|
477
|
+
* paso de deshacer. Nunca toca lo vendido o retenido: si así no alcanza, saca lo que
|
|
478
|
+
* puede (`removed` menor que lo que sobraba; `overCapacity` dice cuánto quedó).
|
|
479
|
+
* `null` si no sobra nada o la entrada no existe.
|
|
480
|
+
*/
|
|
481
|
+
trimToCapacity: (ref: string) => {
|
|
482
|
+
removed: number;
|
|
483
|
+
} | null;
|
|
484
|
+
/** Las entradas numeradas que todavía no tienen nada en el plano, en el orden del host. */
|
|
485
|
+
missingRefs: readonly string[];
|
|
486
|
+
/** Elige una pieza (y la deja a la vista); `null` suelta la selección. */
|
|
487
|
+
select: (id: string | null) => void;
|
|
488
|
+
/** Lleva el lienzo hasta la pieza, sin elegirla. */
|
|
489
|
+
reveal: (id: string) => void;
|
|
490
|
+
/** La entrada de la pieza elegida, para abrir esa tarjeta. `null` sin pieza o sin asignar. */
|
|
491
|
+
selectedRef: string | null;
|
|
492
|
+
summary: PlanSummary;
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
type VenueDesignerProps = {
|
|
496
|
+
/** `null` = empezar en blanco, con el nombre `name`. Un objeto nuevo carga ese plano (se puede deshacer) y lo encuadra. */
|
|
497
|
+
layout: Layout | null;
|
|
498
|
+
name?: string;
|
|
499
|
+
/**
|
|
500
|
+
* Las entradas del evento. Las numeradas guían el armado («Tus entradas numeradas») y dan el color
|
|
501
|
+
* de cada pieza; con `capacitySteps`, el plano nunca pasa su cupo. Las `zone` («Tus entradas
|
|
502
|
+
* generales») se marcan como zonas, opcionales.
|
|
503
|
+
*/
|
|
504
|
+
placeTypes: PlaceTypeOption[];
|
|
505
|
+
/** Unidades vendidas o retenidas: lo que las borraría o renumeraría se rechaza. Moverlas sí se puede. */
|
|
506
|
+
lockedUnitIds?: ReadonlySet<string>;
|
|
507
|
+
onChange?: (layout: Layout) => void;
|
|
508
|
+
/**
|
|
509
|
+
* El botón «Listo» de arriba. Si está, gana sobre `onSave`. Puede ser async:
|
|
510
|
+
* mientras resuelve, el botón espera; si falla, se avisa.
|
|
511
|
+
*/
|
|
512
|
+
onDone?: (layout: Layout) => Promise<void> | void;
|
|
513
|
+
/** Compatibilidad: sin `onDone`, el botón dice «Guardar» y llama a esto. */
|
|
514
|
+
onSave?: (layout: Layout) => Promise<void> | void;
|
|
515
|
+
/** El botón «Volver» de arriba a la izquierda. Sin esto, no hay. */
|
|
516
|
+
onClose?: () => void;
|
|
517
|
+
/**
|
|
518
|
+
* Imagen de fondo para calcar. `onPick` la sube el host y devuelve su URL
|
|
519
|
+
* (o `null` si el productor no eligió nada); la librería no sube archivos.
|
|
520
|
+
* `suggestedSrc`: la imagen del plano del evento, para ofrecerla con un toque.
|
|
521
|
+
*/
|
|
522
|
+
background?: {
|
|
523
|
+
onPick: () => Promise<string | null>;
|
|
524
|
+
suggestedSrc?: string | null;
|
|
525
|
+
};
|
|
526
|
+
/** Los valores por defecto de los tokens `--vk-*`. `"light"` por compatibilidad. */
|
|
527
|
+
theme?: "light" | "dark";
|
|
528
|
+
messages?: DesignerOverrides;
|
|
529
|
+
/**
|
|
530
|
+
* El panel de entradas del host, en lugar de «Tus entradas numeradas»: a la
|
|
531
|
+
* izquierda en la compu y adentro de la hoja «Entradas» en el celular. Recibe
|
|
532
|
+
* lo que necesita para agregar piezas y contar lo ubicado. Pasala estable
|
|
533
|
+
* (`useCallback`): el panel se vuelve a dibujar sólo cuando cambia ella o lo
|
|
534
|
+
* que cuenta `api` (arrastrar una pieza no lo redibuja).
|
|
535
|
+
*/
|
|
536
|
+
sidePanel?: ((api: DesignerHostApi) => ReactNode) | undefined;
|
|
537
|
+
className?: string;
|
|
538
|
+
style?: CSSProperties;
|
|
539
|
+
};
|
|
540
|
+
/**
|
|
541
|
+
* El editor del plano, guiado por las entradas numeradas del evento.
|
|
542
|
+
*
|
|
543
|
+
* Arriba: volver, el nombre, deshacer/rehacer, «+ Referencia», «Imagen de
|
|
544
|
+
* fondo» y «Listo». A la izquierda «Tus entradas numeradas»: cada entrada
|
|
545
|
+
* agrega sus piezas ya asignadas. Al medio el lienzo, con el panel de la pieza
|
|
546
|
+
* elegida flotando junto a ella. «Numeración y pasillos» abre un diálogo con
|
|
547
|
+
* la vista previa del bloque.
|
|
548
|
+
*
|
|
549
|
+
* En un contenedor angosto (el celular) el lienzo ocupa todo: las entradas,
|
|
550
|
+
* la pieza elegida, las referencias y la imagen pasan a hojas desde abajo, y
|
|
551
|
+
* la numeración a una hoja de todo el alto.
|
|
552
|
+
*/
|
|
553
|
+
declare function VenueDesigner(props: VenueDesignerProps): ReactElement;
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* CSS del editor. Mismo criterio que el del mapa: va en un `<style>` adentro
|
|
557
|
+
* del componente, sin archivo `.css` que el host tenga que importar ni efectos
|
|
558
|
+
* al cargar el módulo, que es lo que rompe el SSR.
|
|
559
|
+
*
|
|
560
|
+
* Los tokens se declaran con `:where()` —especificidad cero— así que el host
|
|
561
|
+
* los pisa con una regla común. Comparte los `--vk-*` del mapa: un host que ya
|
|
562
|
+
* tematizó uno no tiene que volver a hacerlo para el otro. `data-theme="dark"`
|
|
563
|
+
* (la prop `theme`) cambia sólo los valores por defecto, con la misma
|
|
564
|
+
* especificidad cero: lo que el host defina sigue ganando.
|
|
565
|
+
*
|
|
566
|
+
* (Sin acentos graves en los comentarios: esto es un template literal y cada
|
|
567
|
+
* uno lo cortaria al medio.)
|
|
568
|
+
*/
|
|
569
|
+
declare const DESIGNER_CSS = "\n:where(.vk-designer){\n --vk-fg:#0f172a; --vk-muted:#64748b; --vk-line:#e2e8f0; --vk-bg:#ffffff;\n --vk-surface:#f8fafc; --vk-panel:#ffffff; --vk-raised:#ffffff; --vk-field:#ffffff;\n --vk-accent:#0f172a; --vk-accent-fg:#ffffff; --vk-primary-bg:var(--vk-accent);\n --vk-danger:#b91c1c; --vk-warn:#b45309; --vk-ok:#047857; --vk-link:var(--vk-accent);\n --vk-seg:#f1f5f9; --vk-seg-on:#ffffff; --vk-canvas:#f8fafc; --vk-canvas-dot:transparent;\n --vk-overlay:rgba(15,23,42,.35); --vk-shadow:0 12px 32px rgba(15,23,42,.18);\n --vk-radius:8px; --vk-radius-lg:12px;\n --vk-font:14px/1.45 system-ui,-apple-system,sans-serif;\n}\n:where(.vk-designer[data-theme=\"dark\"]){\n --vk-fg:#f2f2f3; --vk-muted:#a3a3aa; --vk-line:#26262b; --vk-bg:#0b0b0d;\n --vk-surface:#121215; --vk-panel:#0f0f12; --vk-raised:#1a1a1f; --vk-field:#0b0b0d;\n --vk-accent:#e5482c; --vk-accent-fg:#ffffff; --vk-primary-bg:linear-gradient(90deg,#2f6fe0,#e5482c);\n --vk-danger:#ff8a7a; --vk-warn:#ffb36b; --vk-ok:#6fd3a7; --vk-link:#ff8a6e;\n --vk-seg:#17171b; --vk-seg-on:#2a2a31; --vk-canvas:#141418; --vk-canvas-dot:#2a2a31;\n --vk-overlay:rgba(5,5,7,.8); --vk-shadow:0 16px 40px rgba(0,0,0,.5);\n --vk-shape:#4a4a55; --vk-shape-fill:#2c2c34; --vk-unassigned:#6a6a74;\n --vk-taken:#3a3a44; --vk-taken-stroke:#5a5a66; --vk-held-stroke:#ffb36b;\n --vk-radius:10px; --vk-radius-lg:14px;\n color-scheme:dark;\n}\n:where(.vk-designer){height:100%}\n.vk-designer{display:flex;flex-direction:column;font:var(--vk-font);min-height:0;\n color:var(--vk-fg);background:var(--vk-bg);box-sizing:border-box;min-width:0}\n.vk-designer *{box-sizing:border-box}\n/* Un solo anillo de foco para todo el editor: sin esto, dentro de un panel\n oscuro el foco del navegador se pierde contra el fondo. */\n.vk-designer :focus-visible{outline:2px solid var(--vk-accent);outline-offset:2px}\n.vk-d-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;\n clip:rect(0 0 0 0);white-space:nowrap;border:0}\n.vk-d-ico{flex:none;display:block}\n\n/* Barra de arriba */\n.vk-d-top{position:relative;display:flex;flex-wrap:wrap;align-items:center;gap:10px;\n padding:12px 16px;border-bottom:1px solid var(--vk-line);flex:none}\n.vk-d-name{margin:0;font-size:17px;font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.vk-d-history{display:flex;gap:6px;margin-left:4px}\n.vk-d-actions{display:flex;flex-wrap:wrap;gap:8px;margin-left:auto}\n.vk-d-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;\n border:1px solid var(--vk-line);background:transparent;color:var(--vk-fg);\n border-radius:var(--vk-radius);padding:0 14px;font:inherit;cursor:pointer;min-height:40px}\n.vk-d-btn:disabled,.vk-d-icon-btn:disabled{opacity:.4;cursor:default}\n.vk-d-btn[aria-pressed=\"true\"]{background:var(--vk-accent);color:var(--vk-accent-fg);border-color:var(--vk-accent)}\n.vk-d-primary{border:0;background:var(--vk-primary-bg);color:var(--vk-accent-fg);font-weight:600;padding:0 18px}\n.vk-d-icon-btn{display:inline-flex;align-items:center;justify-content:center;flex:none;width:40px;height:40px;\n padding:0;border:1px solid var(--vk-line);background:transparent;color:var(--vk-fg);border-radius:var(--vk-radius);cursor:pointer}\n.vk-d-danger{color:var(--vk-danger)}\n.vk-d-link{border:0;background:none;padding:4px 0;font:inherit;font-weight:600;color:var(--vk-link);cursor:pointer}\n.vk-d-link:hover{text-decoration:underline}\n\n.vk-d-popover{position:absolute;z-index:20;top:calc(100% + 6px);right:16px;width:360px;max-width:calc(100% - 32px);\n max-height:70vh;overflow:auto;padding:14px;border-radius:var(--vk-radius-lg);border:1px solid var(--vk-line);\n background:var(--vk-raised);color:var(--vk-fg);box-shadow:var(--vk-shadow)}\n.vk-d-popover:focus{outline:none}\n.vk-d-popover-landmarks{width:420px}\n\n.vk-d-notice{display:flex;align-items:center;gap:10px;margin:8px 16px 0;padding:10px 12px;flex:none;\n border-radius:var(--vk-radius);border:1px solid var(--vk-danger);background:var(--vk-surface)}\n.vk-d-notice p{margin:0;flex:1}\n.vk-d-close{border:0;background:none;color:var(--vk-muted);font-size:18px;line-height:1;\n width:32px;height:32px;border-radius:var(--vk-radius);cursor:pointer}\n\n/* Cuerpo: entradas a la izquierda, lienzo al medio */\n.vk-d-body{display:flex;flex:1;min-height:0;min-width:0}\n.vk-d-left{width:340px;flex:none;overflow:auto;border-right:1px solid var(--vk-line);background:var(--vk-panel)}\n\n.vk-d-panel{min-width:0}\n.vk-d-panel-title{margin:0;font-size:17px;font-weight:600}\n.vk-d-hint{margin:4px 0 0;font-size:13px;line-height:1.4;color:var(--vk-muted)}\n.vk-d-group{margin:14px 0 6px;font-size:12px;font-weight:600;color:var(--vk-muted)}\n\n.vk-d-types-panel{display:flex;flex-direction:column;gap:14px;padding:20px;min-height:100%}\n.vk-d-types-head{display:flex;flex-direction:column;gap:2px}\n.vk-d-empty{margin:0;padding:14px;border-radius:var(--vk-radius-lg);border:1px dashed var(--vk-line);color:var(--vk-muted)}\n.vk-d-cards{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px}\n.vk-d-card{display:flex;flex-direction:column;gap:10px;padding:14px;border-radius:var(--vk-radius-lg);\n border:1px solid var(--vk-line);background:var(--vk-surface)}\n.vk-d-card[data-active]{border-color:var(--vk-type);background:color-mix(in srgb,var(--vk-type) 9%,var(--vk-surface))}\n.vk-d-card-head{display:flex;align-items:center;gap:10px}\n.vk-d-dot{flex:none;width:12px;height:12px;border-radius:999px;background:var(--vk-type,var(--vk-muted))}\n.vk-d-card-name{flex:1;min-width:0;font-size:16px;font-weight:600;overflow:hidden;text-overflow:ellipsis}\n.vk-d-ok{font-size:13px;font-weight:600;color:var(--vk-ok);white-space:nowrap}\n.vk-d-missing{font-size:13px;font-weight:600;color:var(--vk-warn);white-space:nowrap}\n.vk-d-card-detail{font-size:13px;color:var(--vk-muted)}\n.vk-d-card-actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}\n.vk-d-add-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:40px;padding:0 8px;white-space:nowrap;font-size:13px;\n border:1px solid color-mix(in srgb,var(--vk-type) 35%,var(--vk-line));border-radius:var(--vk-radius);\n background:color-mix(in srgb,var(--vk-type) 14%,transparent);color:var(--vk-fg);font-family:inherit;font-weight:600;cursor:pointer;overflow:hidden}\n.vk-d-add-btn:hover{background:color-mix(in srgb,var(--vk-type) 24%,transparent)}\n.vk-d-add-btn:disabled{opacity:.45;cursor:default;background:transparent}\n.vk-d-full{margin:0;font-size:13px;color:var(--vk-muted)}\n.vk-d-zones{display:flex;flex-direction:column;gap:10px;padding-top:4px}\n.vk-d-dot-zone{border-radius:3px}\n.vk-d-wide{grid-column:1 / -1}\n.vk-d-types-foot{margin-top:auto;display:flex;flex-direction:column;gap:6px;padding-top:14px;border-top:1px solid var(--vk-line)}\n.vk-d-onplan{display:flex;justify-content:space-between;gap:8px}\n.vk-d-onplan span{color:var(--vk-muted)}\n.vk-d-missing-line{margin:0;font-size:13px;color:var(--vk-warn)}\n.vk-d-warn{margin:4px 0 0;padding:8px 10px;border-radius:var(--vk-radius);background:var(--vk-surface);\n border:1px solid var(--vk-line);font-size:12px;line-height:1.4}\n.vk-d-error{margin:8px 0 0;font-size:13px;color:var(--vk-danger)}\n\n/* Lienzo */\n.vk-d-stage{position:relative;flex:1;min-width:0;min-height:420px;overflow:hidden;touch-action:none;\n background-color:var(--vk-canvas);background-image:radial-gradient(var(--vk-canvas-dot) 1px,transparent 1px);background-size:18px 18px}\n.vk-d-stage[data-armed=\"true\"]{cursor:crosshair}\n.vk-d-stage[data-background-editing=\"true\"]{cursor:move}\n.vk-d-canvas{display:block;width:100%;height:100%;position:absolute;inset:0}\n.vk-d-layer{position:absolute;inset:0;pointer-events:none}\n.vk-d-target{position:absolute;transform:translate(-50%,-50%);padding:0;margin:0;border:0;\n background:transparent;color:transparent;overflow:hidden;border-radius:4px}\n.vk-d-target:focus-visible{outline:3px solid var(--vk-accent);outline-offset:2px}\n.vk-d-handle{position:absolute;z-index:1;width:44px;height:44px;transform:translate(-50%,-50%);padding:0;margin:0;border:0;\n background:transparent;touch-action:none;cursor:nwse-resize}\n.vk-d-handle[data-corner=\"ne\"],.vk-d-handle[data-corner=\"sw\"]{cursor:nesw-resize}\n.vk-d-handle::after{content:\"\";position:absolute;left:50%;top:50%;width:12px;height:12px;transform:translate(-50%,-50%);\n box-sizing:border-box;border-radius:3px;border:2px solid var(--vk-accent);background:var(--vk-raised)}\n.vk-d-handle:focus-visible{outline:3px solid var(--vk-accent);outline-offset:-8px;border-radius:8px}\n.vk-d-banner{position:absolute;z-index:2;top:10px;left:50%;transform:translateX(-50%);\n display:flex;align-items:center;gap:8px;max-width:calc(100% - 20px);\n padding:6px 6px 6px 12px;border-radius:999px;border:1px solid var(--vk-line);\n background:var(--vk-raised);color:var(--vk-fg);font-size:12px;box-shadow:var(--vk-shadow)}\n.vk-d-banner .vk-d-btn{padding:4px 10px;min-height:28px;border-radius:999px;font-size:12px}\n.vk-d-zoom{position:absolute;right:16px;bottom:16px;display:flex;flex-direction:column;gap:6px;z-index:1}\n.vk-d-zoom button{width:40px;height:40px;border:1px solid var(--vk-line);background:var(--vk-surface);\n color:var(--vk-fg);border-radius:var(--vk-radius);font-size:18px;line-height:1;cursor:pointer}\n\n/* Panel de la pieza, flotando junto a ella */\n.vk-d-float{position:absolute;z-index:3;padding:14px;border-radius:var(--vk-radius-lg);\n background:var(--vk-raised);border:1px solid var(--vk-line);box-shadow:var(--vk-shadow);color:var(--vk-fg)}\n.vk-d-inspector{display:flex;flex-direction:column;gap:12px;min-width:0}\n.vk-d-insp-head{display:flex;align-items:center;gap:8px}\n.vk-d-insp-head .vk-d-dot{width:10px;height:10px}\n.vk-d-insp-head .vk-d-icon-btn{width:36px;height:36px}\n.vk-d-insp-title{flex:1;min-width:0;margin:0;font-size:15px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.vk-d-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}\n.vk-d-grid-2{grid-template-columns:repeat(2,minmax(0,1fr))}\n.vk-d-field{display:flex;flex-direction:column;gap:4px;font-size:12px;color:var(--vk-muted);min-width:0}\n.vk-d-field > input,.vk-d-field select,.vk-d-input{border:1px solid var(--vk-line);background:var(--vk-field);\n color:var(--vk-fg);border-radius:var(--vk-radius);padding:0 10px;font:inherit;font-size:14px;min-height:40px;width:100%}\n.vk-d-stepper{display:flex;align-items:center;height:40px;border:1px solid var(--vk-line);border-radius:var(--vk-radius);background:var(--vk-field)}\n.vk-d-stepper button{flex:none;width:34px;height:38px;border:0;background:transparent;color:var(--vk-fg);font-size:16px;cursor:pointer;border-radius:var(--vk-radius)}\n.vk-d-stepper button:disabled{opacity:.35;cursor:default}\n.vk-d-stepper input{flex:1;min-width:0;width:100%;height:38px;border:0;background:transparent;color:var(--vk-fg);\n text-align:center;font:inherit;font-weight:600;font-size:14px}\n.vk-d-stepper-value{flex:1;min-width:0;text-align:center;font-weight:600;font-size:14px;color:var(--vk-fg);white-space:nowrap}\n.vk-d-seg{display:grid;grid-auto-columns:minmax(0,1fr);grid-auto-flow:column;min-height:40px;padding:3px;border-radius:var(--vk-radius);background:var(--vk-seg)}\n.vk-d-seg button{border:0;border-radius:calc(var(--vk-radius) - 2px);background:transparent;color:var(--vk-muted);\n font:inherit;font-size:13px;cursor:pointer;padding:0 6px}\n.vk-d-seg button[aria-pressed=\"true\"]{background:var(--vk-seg-on);color:var(--vk-fg);font-weight:600;box-shadow:0 1px 2px rgba(0,0,0,.12)}\n.vk-d-insp-foot{display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap;font-size:13px}\n.vk-d-assign .vk-d-hint{margin:0 0 6px}\n.vk-d-chips{display:flex;flex-wrap:wrap;gap:6px}\n.vk-d-chip{display:inline-flex;align-items:center;gap:6px;min-height:36px;padding:0 12px;border-radius:999px;\n border:1px solid var(--vk-line);background:var(--vk-surface);color:var(--vk-fg);font:inherit;font-size:13px;cursor:pointer}\n\n/* Referencias */\n.vk-d-search{display:flex;align-items:center;gap:8px;padding:0 10px;border:1px solid var(--vk-line);\n border-radius:var(--vk-radius);background:var(--vk-field);color:var(--vk-muted)}\n.vk-d-search input{flex:1;min-width:0;min-height:40px;border:0;background:transparent;color:var(--vk-fg);font:inherit;outline:none}\n.vk-d-tiles{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(110px,1fr));gap:6px}\n.vk-d-tile{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;width:100%;min-height:76px;\n padding:8px;border:1px solid var(--vk-line);border-radius:var(--vk-radius);background:var(--vk-surface);\n color:var(--vk-fg);font:inherit;font-size:12px;text-align:center;cursor:pointer}\n.vk-d-tile .vk-d-ico{color:var(--vk-muted)}\n.vk-d-tile:hover{border-color:var(--vk-accent)}\n\n/* Imagen de fondo (el control de siempre, adentro de su panel) */\n.vk-d-fields{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:12px}\n.vk-d-field input[type=\"range\"]{border:0;padding:0;background:none;accent-color:var(--vk-accent);min-height:0}\n.vk-d-range-head{display:flex;justify-content:space-between;gap:8px}\n.vk-d-range-head output{color:var(--vk-fg);font-variant-numeric:tabular-nums}\n.vk-d-row{display:flex;flex-wrap:wrap;gap:6px;margin-top:12px}\n\n/* Numeracion y pasillos */\n.vk-d-numbering{display:flex;width:100%;height:100%;min-height:0;color:var(--vk-fg)}\n.vk-d-num-preview{flex:1;min-width:0;display:flex;flex-direction:column;\n background-color:var(--vk-canvas);background-image:radial-gradient(var(--vk-canvas-dot) 1px,transparent 1px);background-size:18px 18px}\n.vk-d-num-head{padding:20px 24px;background:var(--vk-surface);border-bottom:1px solid var(--vk-line)}\n.vk-d-num-title{margin:0;font-size:20px;font-weight:600}\n.vk-d-num-stage{flex:1;min-height:0;overflow:auto;display:flex;flex-direction:column;align-items:center;justify-content:safe center;gap:16px;padding:24px}\n.vk-d-num-grid{display:flex;flex-direction:column;gap:10px}\n.vk-d-num-row{display:flex;align-items:center;gap:10px}\n.vk-d-num-label{width:28px;flex:none;text-align:right;font-size:14px;font-weight:600;color:var(--vk-link)}\n.vk-d-num-seat{flex:none;width:34px;height:34px;border-radius:999px;border:0;padding:0;background:var(--vk-type);\n color:#fff;font:inherit;font-size:12px;font-weight:600;cursor:pointer}\n.vk-d-num-seat[data-removed]{background:transparent;border:2px dashed var(--vk-unassigned,#5a5a66);color:var(--vk-muted)}\n.vk-d-num-seat[data-sold]{cursor:not-allowed;opacity:.55}\n.vk-d-legend{display:flex;gap:18px;font-size:13px;color:var(--vk-muted)}\n.vk-d-legend > span{display:flex;align-items:center;gap:6px}\n.vk-d-legend-dot{width:12px;height:12px;border-radius:999px;background:var(--vk-type)}\n.vk-d-legend-out{background:transparent;border:2px dashed var(--vk-unassigned,#5a5a66)}\n.vk-d-num-side{width:340px;flex:none;border-left:1px solid var(--vk-line);padding:24px;display:flex;flex-direction:column;gap:20px;overflow:auto;background:var(--vk-surface)}\n.vk-d-num-group{display:flex;flex-direction:column;gap:8px}\n.vk-d-num-group .vk-d-field > span,.vk-d-num-group-title{font-size:15px;font-weight:600;color:var(--vk-fg)}\n.vk-d-sub{font-size:13px;color:var(--vk-muted)}\n.vk-d-check{display:flex;align-items:center;gap:8px;min-height:44px;font-size:14px;color:var(--vk-fg);cursor:pointer}\n.vk-d-check input{width:20px;height:20px;margin:0}\n.vk-d-trim{min-height:44px}\n.vk-d-input{min-height:44px;font-size:16px}\n.vk-d-input[aria-invalid=\"true\"]{border-color:var(--vk-danger)}\n.vk-d-result{display:flex;flex-direction:column;gap:6px;padding:14px;border-radius:var(--vk-radius-lg);background:var(--vk-seg);font-size:14px}\n.vk-d-num-actions{margin-top:auto;display:flex;gap:10px}\n.vk-d-num-actions .vk-d-btn{flex:1;min-height:46px}\n\n/* Hojas y dialogos */\n.vk-d-dock{display:contents}\n.vk-d-sheet-root{position:fixed;inset:0;z-index:1000;display:flex;flex-direction:column;justify-content:flex-end}\n.vk-d-sheet-root[hidden]{display:none}\n.vk-d-backdrop{position:absolute;inset:0;background:var(--vk-overlay)}\n.vk-d-sheet{position:relative;max-height:75vh;max-height:75dvh;display:flex;flex-direction:column;\n background:var(--vk-surface);color:var(--vk-fg);border-radius:var(--vk-radius-lg) var(--vk-radius-lg) 0 0;\n box-shadow:var(--vk-shadow);padding-bottom:env(safe-area-inset-bottom)}\n.vk-d-sheet:focus{outline:none}\n.vk-d-sheet-head{display:flex;align-items:center;justify-content:space-between;gap:8px;\n padding:8px 8px 8px 16px;border-bottom:1px solid var(--vk-line)}\n.vk-d-sheet-body{overflow:auto;padding:12px 16px 16px;display:flex;flex-direction:column;gap:12px}\n.vk-d-sheet .vk-d-types-panel{padding:0;min-height:0}\n.vk-d-sheet-root[data-variant=\"full\"] .vk-d-sheet{height:100%;max-height:none;border-radius:0}\n.vk-d-sheet-root[data-variant=\"center\"]{justify-content:center;align-items:center;padding:24px}\n.vk-d-sheet-root[data-variant=\"center\"] .vk-d-sheet{width:min(1040px,100%);height:min(700px,100%);max-height:none;\n border-radius:20px;overflow:hidden;border:1px solid var(--vk-line);padding-bottom:0}\n.vk-d-sheet-root[data-variant=\"full\"] .vk-d-sheet-body,\n.vk-d-sheet-root[data-variant=\"center\"] .vk-d-sheet-body{padding:0;flex:1;min-height:0;overflow:hidden}\n\n/* Celular (contenedor angosto): el lienzo ocupa todo y lo demas va en hojas. */\n.vk-designer[data-layout=\"compact\"] .vk-d-top{padding:8px 10px;gap:6px;flex-wrap:nowrap}\n.vk-designer[data-layout=\"compact\"] .vk-d-name{flex:1;font-size:15px}\n.vk-designer[data-layout=\"compact\"] .vk-d-actions{margin-left:0;flex:none}\n.vk-designer[data-layout=\"compact\"] .vk-d-history{margin-left:0}\n.vk-designer[data-layout=\"compact\"] .vk-d-body{flex-direction:column}\n.vk-designer[data-layout=\"compact\"] .vk-d-stage{min-height:320px}\n.vk-designer[data-layout=\"compact\"] .vk-d-btn,\n.vk-designer[data-layout=\"compact\"] .vk-d-field > input,\n.vk-designer[data-layout=\"compact\"] .vk-d-field select,\n.vk-designer[data-layout=\"compact\"] .vk-d-add-btn,\n.vk-designer[data-layout=\"compact\"] .vk-d-seg,\n.vk-designer[data-layout=\"compact\"] .vk-d-chip{min-height:44px}\n.vk-designer[data-layout=\"compact\"] .vk-d-icon-btn,\n.vk-designer[data-layout=\"compact\"] .vk-d-insp-head .vk-d-icon-btn{width:44px;height:44px}\n.vk-designer[data-layout=\"compact\"] .vk-d-stepper{height:44px}\n.vk-designer[data-layout=\"compact\"] .vk-d-stepper button{width:44px;height:42px}\n.vk-designer[data-layout=\"compact\"] .vk-d-close{min-width:44px;height:44px}\n.vk-designer[data-layout=\"compact\"] .vk-d-banner .vk-d-btn{min-height:44px;padding:4px 14px}\n.vk-designer[data-layout=\"compact\"] .vk-d-zoom{right:10px;bottom:10px}\n.vk-designer[data-layout=\"compact\"] .vk-d-zoom button{width:44px;height:44px}\n.vk-designer[data-layout=\"compact\"] .vk-d-numbering{flex-direction:column;overflow:auto}\n.vk-designer[data-layout=\"compact\"] .vk-d-num-preview{flex:none;min-height:300px}\n.vk-designer[data-layout=\"compact\"] .vk-d-num-side{width:auto;border-left:0;border-top:1px solid var(--vk-line);overflow:visible;padding:16px}\n.vk-designer[data-layout=\"compact\"] .vk-d-num-head{padding:14px 16px}\n.vk-designer[data-layout=\"compact\"] .vk-d-num-actions{position:sticky;bottom:0;padding:10px 0 calc(10px + env(safe-area-inset-bottom));background:var(--vk-surface)}\n.vk-designer[data-layout=\"compact\"] .vk-d-num-title{font-size:17px}\n.vk-designer[data-layout=\"compact\"] .vk-d-num-stage{justify-content:flex-start;align-items:flex-start;padding:16px}\n.vk-d-toolbar{display:flex;gap:8px;padding:8px 10px calc(8px + env(safe-area-inset-bottom));border-top:1px solid var(--vk-line);flex:none}\n.vk-d-toolbar .vk-d-btn{flex:1;padding:0 10px}\n.vk-d-toolbar .vk-d-btn[aria-label]{flex:none;width:48px}\n.vk-d-badge{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:20px;padding:0 6px;\n border-radius:999px;background:var(--vk-warn);color:#1a1206;font-size:12px;font-weight:700}\n.vk-d-arrange{display:flex;flex-direction:column;gap:4px;min-width:0}\n.vk-d-arrange-label{font-size:12px;font-weight:600;color:var(--vk-muted)}\n.vk-d-arrange-btns{display:flex;flex-wrap:wrap;gap:4px}\n.vk-d-dock{flex:none;padding:12px 12px 4px;border-top:1px solid var(--vk-line);background:var(--vk-surface);max-height:45vh;overflow:auto}\n.vk-d-dock .vk-d-arrange-btns{gap:6px}\n.vk-d-stage[data-pan-ready] .vk-d-canvas{cursor:grab}\n.vk-d-stage[data-pan-ready] .vk-d-canvas:active{cursor:grabbing}\n";
|
|
570
|
+
|
|
571
|
+
type UseImageResult = {
|
|
572
|
+
image: HTMLImageElement | null;
|
|
573
|
+
failed: boolean;
|
|
574
|
+
};
|
|
575
|
+
/**
|
|
576
|
+
* Carga una imagen para dibujarla en el lienzo. Sin `crossOrigin`: sólo se
|
|
577
|
+
* dibuja, nunca se leen sus píxeles, así que una imagen de otro dominio sirve
|
|
578
|
+
* igual. Al cambiar `src` vuelve a empezar y no devuelve la anterior.
|
|
579
|
+
*/
|
|
580
|
+
declare function useImage(src: string | null): UseImageResult;
|
|
581
|
+
|
|
582
|
+
declare const VERSION = "0.10.0";
|
|
583
|
+
|
|
584
|
+
export { type CapacityRejection, DESIGNER_CSS, type DesignerHostApi, type DesignerMessages, type DesignerOverrides, type DesignerRejection, type MessageOverrides, type Messages, PICKER_CSS, type PlacedCount, SeatMap, type SeatMapPlaceType, type SeatMapProps, type UseImageResult, VERSION, VenueDesigner, type VenueDesignerProps, VenueOverview, type VenueOverviewPlaceType, type VenueOverviewProps, designerEn, designerEs, en, es, format, mergeDesignerMessages, mergeMessages, selectionSummary, useImage };
|