@kerusiweb/react 2.3.0 → 3.1.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 +22 -22
- package/README.md +818 -609
- package/dist/kerusi-seatmap.d.ts +4 -2
- package/dist/kerusi-seatmap.d.ts.map +1 -1
- package/dist/kerusi-seatmap.js +125 -39
- package/dist/kerusi-seatmap.js.map +1 -1
- package/dist/kerusi-section.d.ts +39 -20
- package/dist/kerusi-section.d.ts.map +1 -1
- package/dist/kerusi-section.js +11 -17
- package/dist/kerusi-section.js.map +1 -1
- package/dist/public-api.d.ts +1 -1
- package/dist/public-api.js +1 -1
- package/dist/seat-card.d.ts +36 -0
- package/dist/seat-card.d.ts.map +1 -0
- package/dist/seat-card.js +99 -0
- package/dist/seat-card.js.map +1 -0
- package/dist/types.d.ts +84 -17
- package/dist/types.d.ts.map +1 -1
- package/dist/use-seat-cards.d.ts +55 -0
- package/dist/use-seat-cards.d.ts.map +1 -0
- package/dist/use-seat-cards.js +202 -0
- package/dist/use-seat-cards.js.map +1 -0
- package/dist/use-viewport.d.ts +9 -2
- package/dist/use-viewport.d.ts.map +1 -1
- package/dist/use-viewport.js +22 -4
- package/dist/use-viewport.js.map +1 -1
- package/package.json +52 -52
- package/styles.css +541 -365
package/dist/public-api.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* there, not re-exported here: the document types (`KerusiMap`, `KerusiState`,
|
|
6
6
|
* `KerusiSession`), the conformance validator, the render model
|
|
7
7
|
* (`buildRenderModel`, `RenderMap`, `RenderSeat`), the geometry
|
|
8
|
-
* (`
|
|
8
|
+
* (`computeMapLayout`), and the view helpers (`summarizeSelection`,
|
|
9
9
|
* `seatAriaLabel`, `DEFAULT_KERUSI_COLORS`). This package supplies only what is
|
|
10
10
|
* React's: components, hooks, and their props.
|
|
11
11
|
*
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { RenderSeat, SeatCardAppearance, SeatCardPlacement } from '@kerusiweb/core';
|
|
2
|
+
import type { ReactNode, RefObject } from 'react';
|
|
3
|
+
export interface SeatCardProps {
|
|
4
|
+
kind: 'hover' | 'click';
|
|
5
|
+
/** The card's `id`: a hover card is named by the seat's `aria-describedby`. */
|
|
6
|
+
id: string;
|
|
7
|
+
seat: RenderSeat;
|
|
8
|
+
/** Names a click card's dialog. */
|
|
9
|
+
label: string;
|
|
10
|
+
placement: SeatCardPlacement;
|
|
11
|
+
appearance: SeatCardAppearance;
|
|
12
|
+
className?: string;
|
|
13
|
+
/** The map's root element: the card is positioned in it and kept inside it. */
|
|
14
|
+
rootRef: RefObject<HTMLElement | null>;
|
|
15
|
+
getSeatNode: (seatId: string) => SVGGElement | null;
|
|
16
|
+
/** Moves focus into the card on mount; a click card opened from the keyboard. */
|
|
17
|
+
focusOnOpen?: boolean;
|
|
18
|
+
/** A hover card is hoverable (WCAG 1.4.13): the pointer may enter it. */
|
|
19
|
+
onPointerEnter?: () => void;
|
|
20
|
+
onPointerLeave?: () => void;
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* One seat card: a floating element anchored to a seat.
|
|
25
|
+
*
|
|
26
|
+
* It sits inside the map's root, outside the clipped viewport, so it shows in
|
|
27
|
+
* full screen and inherits the `--kerusi-*` properties set on the map. Where it
|
|
28
|
+
* goes is `placeSeatCard()`'s; this component measures the seat, the card and
|
|
29
|
+
* the root, and re-measures after every render and whenever the root or the card
|
|
30
|
+
* changes size, which is how it follows zoom, pan, maximize and full screen.
|
|
31
|
+
*
|
|
32
|
+
* It sets no colour, no padding and no font: that is the stylesheet's, and then
|
|
33
|
+
* the consumer's (D11).
|
|
34
|
+
*/
|
|
35
|
+
export declare function SeatCard({ kind, id, seat, label, placement, appearance, className, rootRef, getSeatNode, focusOnOpen, onPointerEnter, onPointerLeave, children, }: SeatCardProps): import("react").JSX.Element;
|
|
36
|
+
//# sourceMappingURL=seat-card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seat-card.d.ts","sourceRoot":"","sources":["../src/seat-card.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EAElB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAiB,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEjE,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxB,+EAA+E;IAC/E,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,iBAAiB,CAAC;IAC7B,UAAU,EAAE,kBAAkB,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,OAAO,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACvC,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,WAAW,GAAG,IAAI,CAAC;IACpD,iFAAiF;IACjF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,QAAQ,EAAE,SAAS,CAAC;CACrB;AAKD;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,EAAE,EACF,IAAI,EACJ,KAAK,EACL,SAAS,EACT,UAAU,EACV,SAAS,EACT,OAAO,EACP,WAAW,EACX,WAAmB,EACnB,cAAc,EACd,cAAc,EACd,QAAQ,GACT,EAAE,aAAa,+BAsHf"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cssLengthToPx, placeSeatCard, seatCardClassName, seatCardDataAttributes, } from '@kerusiweb/core';
|
|
3
|
+
import { useLayoutEffect, useRef, useState } from 'react';
|
|
4
|
+
const DEFAULT_OFFSET = 8;
|
|
5
|
+
const DEFAULT_ARROW = 6;
|
|
6
|
+
/**
|
|
7
|
+
* One seat card: a floating element anchored to a seat.
|
|
8
|
+
*
|
|
9
|
+
* It sits inside the map's root, outside the clipped viewport, so it shows in
|
|
10
|
+
* full screen and inherits the `--kerusi-*` properties set on the map. Where it
|
|
11
|
+
* goes is `placeSeatCard()`'s; this component measures the seat, the card and
|
|
12
|
+
* the root, and re-measures after every render and whenever the root or the card
|
|
13
|
+
* changes size, which is how it follows zoom, pan, maximize and full screen.
|
|
14
|
+
*
|
|
15
|
+
* It sets no colour, no padding and no font: that is the stylesheet's, and then
|
|
16
|
+
* the consumer's (D11).
|
|
17
|
+
*/
|
|
18
|
+
export function SeatCard({ kind, id, seat, label, placement, appearance, className, rootRef, getSeatNode, focusOnOpen = false, onPointerEnter, onPointerLeave, children, }) {
|
|
19
|
+
const cardRef = useRef(null);
|
|
20
|
+
const [position, setPosition] = useState(null);
|
|
21
|
+
/** False when the consumer set `--kerusi-seat-card-arrow-size: 0`. */
|
|
22
|
+
const [arrowShown, setArrowShown] = useState(true);
|
|
23
|
+
const measure = () => {
|
|
24
|
+
const root = rootRef.current;
|
|
25
|
+
const card = cardRef.current;
|
|
26
|
+
const seatNode = getSeatNode(seat.id);
|
|
27
|
+
if (!root || !card || !seatNode) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const rootBox = root.getBoundingClientRect();
|
|
31
|
+
const seatBox = seatNode.getBoundingClientRect();
|
|
32
|
+
// `position: absolute` is measured from the root's padding box.
|
|
33
|
+
const originX = rootBox.left + root.clientLeft;
|
|
34
|
+
const originY = rootBox.top + root.clientTop;
|
|
35
|
+
const styles = getComputedStyle(card);
|
|
36
|
+
const fontSizes = {
|
|
37
|
+
root: parseFloat(getComputedStyle(card.ownerDocument.documentElement).fontSize) || 16,
|
|
38
|
+
element: parseFloat(styles.fontSize) || 16,
|
|
39
|
+
};
|
|
40
|
+
const arrowSize = cssLengthToPx(styles.getPropertyValue('--kerusi-seat-card-arrow-size'), DEFAULT_ARROW, fontSizes);
|
|
41
|
+
setArrowShown(arrowSize > 0);
|
|
42
|
+
const next = placeSeatCard({
|
|
43
|
+
seat: {
|
|
44
|
+
x: seatBox.left - originX,
|
|
45
|
+
y: seatBox.top - originY,
|
|
46
|
+
width: seatBox.width,
|
|
47
|
+
height: seatBox.height,
|
|
48
|
+
},
|
|
49
|
+
card: { width: card.offsetWidth, height: card.offsetHeight },
|
|
50
|
+
container: { x: 0, y: 0, width: root.clientWidth, height: root.clientHeight },
|
|
51
|
+
placement,
|
|
52
|
+
offset: cssLengthToPx(styles.getPropertyValue('--kerusi-seat-card-offset'), DEFAULT_OFFSET, fontSizes),
|
|
53
|
+
arrowInset: Math.max(12, arrowSize * 2),
|
|
54
|
+
});
|
|
55
|
+
setPosition((current) => current &&
|
|
56
|
+
current.side === next.side &&
|
|
57
|
+
current.x === next.x &&
|
|
58
|
+
current.y === next.y &&
|
|
59
|
+
current.arrowOffset === next.arrowOffset
|
|
60
|
+
? current
|
|
61
|
+
: next);
|
|
62
|
+
};
|
|
63
|
+
// After every render, before paint: the card is in place when it first shows,
|
|
64
|
+
// and a zoom or pan (which re-renders the map) moves it with the seat.
|
|
65
|
+
useLayoutEffect(measure);
|
|
66
|
+
// A change the render did not announce: the root resized (maximize, full
|
|
67
|
+
// screen, a rotated phone), or the card's own content did.
|
|
68
|
+
useLayoutEffect(() => {
|
|
69
|
+
const root = rootRef.current;
|
|
70
|
+
const card = cardRef.current;
|
|
71
|
+
if (!root || !card || typeof ResizeObserver === 'undefined') {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const observer = new ResizeObserver(() => measure());
|
|
75
|
+
observer.observe(root);
|
|
76
|
+
observer.observe(card);
|
|
77
|
+
return () => observer.disconnect();
|
|
78
|
+
// `measure` closes over props that are stable for as long as the card is this seat's.
|
|
79
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
80
|
+
}, [seat.id, placement]);
|
|
81
|
+
useLayoutEffect(() => {
|
|
82
|
+
if (!focusOnOpen) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const card = cardRef.current;
|
|
86
|
+
if (!card) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const first = card.querySelector('a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])');
|
|
90
|
+
(first ?? card).focus({ preventScroll: true });
|
|
91
|
+
}, [focusOnOpen, seat.id]);
|
|
92
|
+
const style = {
|
|
93
|
+
left: position?.x ?? 0,
|
|
94
|
+
top: position?.y ?? 0,
|
|
95
|
+
'--kerusi-seat-card-arrow-shift': `${position?.arrowOffset ?? 0}px`,
|
|
96
|
+
};
|
|
97
|
+
return (_jsxs("div", { ref: cardRef, id: id, className: seatCardClassName(kind, appearance, className), role: kind === 'hover' ? 'tooltip' : 'dialog', "aria-label": kind === 'click' ? label : undefined, tabIndex: kind === 'click' ? -1 : undefined, "data-placement": position?.side ?? (placement === 'auto' ? 'top' : placement), ...seatCardDataAttributes(seat), style: style, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, children: [_jsx("div", { className: "kerusi-seat-card__body", children: children }), appearance === 'none' || !arrowShown ? null : (_jsx("span", { className: "kerusi-seat-card__arrow", "aria-hidden": "true" }))] }));
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=seat-card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seat-card.js","sourceRoot":"","sources":["../src/seat-card.tsx"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DisallowedReason, KerusiControlStrings, KerusiMap, KerusiSeatContext, KerusiSeatmapColors, KerusiSession, KerusiState, KerusiViewport, KerusiViolation, RenderSeat, SeatAriaStrings, SeatRenderStatus, SeatStyleFn, SeatTypeStyles, SelectionSummary } from '@kerusiweb/core';
|
|
1
|
+
import type { DisallowedReason, HoverCardDelay, KerusiControlStrings, KerusiMap, KerusiSeatCardContext, KerusiSeatContext, KerusiSeatmapColors, KerusiSession, KerusiState, KerusiViewport, KerusiViolation, RenderSeat, SeatAriaStrings, SeatCardAppearance, SeatCardPlacement, SeatClick, SeatRenderStatus, SeatStyleFn, SeatTypeStyles, SelectionSummary } from '@kerusiweb/core';
|
|
2
2
|
import type { CSSProperties, ReactNode } from 'react';
|
|
3
3
|
/** How a document with validation errors is handled. */
|
|
4
4
|
export type ValidationMode =
|
|
@@ -10,11 +10,8 @@ export type ValidationMode =
|
|
|
10
10
|
| 'off';
|
|
11
11
|
/** Per-section rendering overrides, keyed by `Section.id`. */
|
|
12
12
|
export interface SectionRenderOptions {
|
|
13
|
+
/** Leaves the section out. Its space on the canvas stays empty (D4). */
|
|
13
14
|
hidden?: boolean;
|
|
14
|
-
/** Overrides `Section.aspectRatio`. */
|
|
15
|
-
aspectRatio?: string;
|
|
16
|
-
/** Overrides the seat size for this section only. */
|
|
17
|
-
seatSize?: number;
|
|
18
15
|
/** Overrides the localized `Section.label`. */
|
|
19
16
|
label?: string;
|
|
20
17
|
}
|
|
@@ -47,14 +44,29 @@ export interface KerusiSeatmapHandle {
|
|
|
47
44
|
readonly summary: SelectionSummary;
|
|
48
45
|
/** Moves DOM focus to a seat, if it is rendered. */
|
|
49
46
|
focusSeat(seatId: string): void;
|
|
47
|
+
/**
|
|
48
|
+
* Opens the click card for a seat, for example from a search result. No-op
|
|
49
|
+
* without `renderClickCard`, or for a seat that is not rendered.
|
|
50
|
+
*/
|
|
51
|
+
openSeatCard(seatId: string): void;
|
|
52
|
+
/** Closes the click card. */
|
|
53
|
+
closeSeatCard(): void;
|
|
54
|
+
/** The seat whose click card is showing, or `null`. */
|
|
55
|
+
readonly openSeatCardId: string | null;
|
|
50
56
|
/** The current zoom and pan. Fit (`{ zoom: 1, x: 0, y: 0 }`) unless `zoomable`. */
|
|
51
57
|
readonly viewport: KerusiViewport;
|
|
52
58
|
/** Zooms in one step about the centre. No-op unless `zoomable`. */
|
|
53
59
|
zoomIn(): void;
|
|
54
60
|
/** Zooms out one step about the centre. No-op unless `zoomable`. */
|
|
55
61
|
zoomOut(): void;
|
|
56
|
-
/** Back to fit-to-container: the
|
|
62
|
+
/** Back to fit-to-container: the whole canvas. No-op unless `zoomable`. */
|
|
57
63
|
resetZoom(): void;
|
|
64
|
+
/**
|
|
65
|
+
* Zooms to one section: its declared `bounds`, or the box around its seats
|
|
66
|
+
* and elements when it declares none. No-op unless `zoomable`, or for a
|
|
67
|
+
* section that is not rendered.
|
|
68
|
+
*/
|
|
69
|
+
zoomToSection(sectionId: string): void;
|
|
58
70
|
/** Whether the map is currently maximized. */
|
|
59
71
|
readonly maximized: boolean;
|
|
60
72
|
/** Maximizes or restores the map. Maximizing needs `maximizable`. */
|
|
@@ -97,23 +109,24 @@ export interface KerusiSeatmapProps {
|
|
|
97
109
|
/**
|
|
98
110
|
* Draws the inside of every seat yourself. The library keeps the seat's
|
|
99
111
|
* `<g>`, with its role, ARIA state, tab stop, rotation and event handlers, and
|
|
100
|
-
* renders whatever this returns inside it, in
|
|
112
|
+
* renders whatever this returns inside it, in canvas units. Return
|
|
101
113
|
* `ctx.defaultContent` for the stock seat, or add to it. While this is set the
|
|
102
114
|
* library also draws a focus outline over your content, so keyboard focus
|
|
103
115
|
* stays visible whatever you draw.
|
|
104
116
|
*/
|
|
105
117
|
renderSeat?: (ctx: SeatRenderContext) => ReactNode;
|
|
106
|
-
/** Grid cell edge, in viewBox units. */
|
|
107
|
-
seatSize?: number;
|
|
108
|
-
/** Gap between grid cells, in viewBox units. */
|
|
109
|
-
seatGap?: number;
|
|
110
|
-
/** Freeform viewBox width; height follows the section's aspect ratio. */
|
|
111
|
-
freeformBasis?: number;
|
|
112
118
|
/**
|
|
113
|
-
* CSS pixels per
|
|
114
|
-
*
|
|
119
|
+
* CSS pixels per canvas unit, at most: the map never draws wider than
|
|
120
|
+
* `canvas.width × unitScale`, and scales down to a narrower container. The
|
|
121
|
+
* document fixes every seat's size and position (§4.5); this is the only
|
|
122
|
+
* sizing control. Default `1`.
|
|
115
123
|
*/
|
|
116
124
|
unitScale?: number;
|
|
125
|
+
/**
|
|
126
|
+
* Draws each section's label inside the map, at the top-left of its `bounds`.
|
|
127
|
+
* Only sections that declare `bounds` get one; every section's label is its
|
|
128
|
+
* group's accessible name either way. Default `true`.
|
|
129
|
+
*/
|
|
117
130
|
showSectionLabels?: boolean;
|
|
118
131
|
showLegend?: boolean;
|
|
119
132
|
showLegendPrices?: boolean;
|
|
@@ -131,7 +144,11 @@ export interface KerusiSeatmapProps {
|
|
|
131
144
|
* Memoize it — an inline arrow rebuilds the whole render model every render.
|
|
132
145
|
*/
|
|
133
146
|
seatSelectable?: (seat: RenderSeat) => boolean;
|
|
134
|
-
/**
|
|
147
|
+
/**
|
|
148
|
+
* `false` turns selection off. Seats still take clicks, and stay
|
|
149
|
+
* keyboard-reachable, while `onSeatClick` or `renderClickCard` is set (D14).
|
|
150
|
+
* With neither set, a read-only map has no pointer or keyboard interaction.
|
|
151
|
+
*/
|
|
135
152
|
interactive?: boolean;
|
|
136
153
|
/**
|
|
137
154
|
* Revert a lapsed `holdExpires` to available on a ticker (§5.1). Off by
|
|
@@ -159,11 +176,61 @@ export interface KerusiSeatmapProps {
|
|
|
159
176
|
* Memoize it — a new object each render rebuilds the controls' strings.
|
|
160
177
|
*/
|
|
161
178
|
controlStrings?: Partial<KerusiControlStrings>;
|
|
179
|
+
/**
|
|
180
|
+
* Shown while a seat is hovered, anchored to it. Return `null` for no card on
|
|
181
|
+
* this seat. Never shown for touch. With neither card function set, nothing is
|
|
182
|
+
* rendered and the markup is unchanged (D10).
|
|
183
|
+
*
|
|
184
|
+
* A hover card is pointer-only unless `hoverCardOnFocus` is set, so it must not
|
|
185
|
+
* be the only place important information lives.
|
|
186
|
+
*/
|
|
187
|
+
renderHoverCard?: (ctx: KerusiSeatCardContext) => ReactNode;
|
|
188
|
+
/**
|
|
189
|
+
* Opened by a click, tap or Enter/Space on a seat, anchored to it. It stays
|
|
190
|
+
* open until dismissed: `Escape`, a press outside, a second click on the same
|
|
191
|
+
* seat, `ctx.close()`, or another seat's click card opening. Return `null` for
|
|
192
|
+
* no card on this seat.
|
|
193
|
+
*
|
|
194
|
+
* A click on a selectable seat still toggles it. To show details without
|
|
195
|
+
* selecting, turn selection off with `interactive={false}`,
|
|
196
|
+
* `selectableStatuses={[]}` or `seatSelectable`.
|
|
197
|
+
*/
|
|
198
|
+
renderClickCard?: (ctx: KerusiSeatCardContext) => ReactNode;
|
|
199
|
+
/** The side a card prefers; it flips when it would overflow the map. Default `top`. */
|
|
200
|
+
seatCardPlacement?: SeatCardPlacement;
|
|
201
|
+
/** Extra classes on the card element, for Tailwind or a design-system class (D11). */
|
|
202
|
+
seatCardClassName?: string;
|
|
203
|
+
/**
|
|
204
|
+
* `none` drops the card's background, border, padding, shadow and arrow,
|
|
205
|
+
* leaving only positioning, so your content is the card (D11). Default `default`.
|
|
206
|
+
*/
|
|
207
|
+
seatCardAppearance?: SeatCardAppearance;
|
|
208
|
+
/** Milliseconds before a hover card opens and closes. Default `{ open: 150, close: 100 }`. */
|
|
209
|
+
hoverCardDelay?: Partial<HoverCardDelay>;
|
|
210
|
+
/**
|
|
211
|
+
* Also show the hover card when a seat takes keyboard focus (D12). Default
|
|
212
|
+
* `false`. Setting it makes seats keyboard-reachable even on a read-only map.
|
|
213
|
+
*/
|
|
214
|
+
hoverCardOnFocus?: boolean;
|
|
162
215
|
validate?: ValidationMode;
|
|
163
216
|
onSeatSelect?: (event: SeatInteraction) => void;
|
|
164
217
|
onSeatDeselect?: (event: SeatInteraction) => void;
|
|
165
218
|
onSeatDisallowed?: (event: SeatDisallowed) => void;
|
|
166
219
|
onSeatFocus?: (seat: RenderSeat) => void;
|
|
220
|
+
/**
|
|
221
|
+
* The seat under the pointer when it enters a seat, and `null` when it leaves
|
|
222
|
+
* the seat or the map. Not repeated while the pointer moves within a seat.
|
|
223
|
+
* Pointer devices only (mouse and pen), never during a pan or zoom, and
|
|
224
|
+
* unaffected by `interactive` (D10).
|
|
225
|
+
*/
|
|
226
|
+
onSeatHover?: (seat: RenderSeat | null) => void;
|
|
227
|
+
/**
|
|
228
|
+
* Every activation of any seat, whether or not it can be selected: booked,
|
|
229
|
+
* held and blocked seats included. Fires before the selection callbacks, with
|
|
230
|
+
* `selected` as it was before the click. A read-only notification: it cannot
|
|
231
|
+
* cancel or change what the click does (D13).
|
|
232
|
+
*/
|
|
233
|
+
onSeatClick?: (event: SeatClick) => void;
|
|
167
234
|
/** Called whenever the documents change, unless `validate` is `off`. */
|
|
168
235
|
onValidationIssues?: (issues: readonly KerusiViolation[]) => void;
|
|
169
236
|
/** The zoom and pan, whenever they change. For a host that persists or shows them. */
|
|
@@ -171,7 +238,7 @@ export interface KerusiSeatmapProps {
|
|
|
171
238
|
onMaximizedChange?: (maximized: boolean) => void;
|
|
172
239
|
className?: string;
|
|
173
240
|
style?: CSSProperties;
|
|
174
|
-
/** Rendered inside the map's root element, after the
|
|
241
|
+
/** Rendered inside the map's root element, after the map and legend. */
|
|
175
242
|
children?: ReactNode;
|
|
176
243
|
}
|
|
177
244
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACpB,SAAS,EACT,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,cAAc,EACd,eAAe,EACf,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,gBAAgB,EACjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,wDAAwD;AACxD,MAAM,MAAM,cAAc;AACxB,0EAA0E;AACxE,SAAS;AACX,4EAA4E;GAC1E,OAAO;AACT,mEAAmE;GACjE,KAAK,CAAC;AAEV,8DAA8D;AAC9D,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { HoverCardDelay, KerusiSeatCardContext, RenderMap, RenderSeat, SeatAriaStrings, SeatCardAppearance, SeatCardPlacement, SeatClickSource } from '@kerusiweb/core';
|
|
2
|
+
import type { ReactNode, RefObject } from 'react';
|
|
3
|
+
export interface UseSeatCardsOptions {
|
|
4
|
+
rootRef: RefObject<HTMLElement | null>;
|
|
5
|
+
renderMap: RenderMap;
|
|
6
|
+
selection: ReadonlySet<string>;
|
|
7
|
+
locale: string;
|
|
8
|
+
ariaStrings: SeatAriaStrings;
|
|
9
|
+
getSeatNode: (seatId: string) => SVGGElement | null;
|
|
10
|
+
focusSeat: (seatId: string) => void;
|
|
11
|
+
onSeatHover?: (seat: RenderSeat | null) => void;
|
|
12
|
+
renderHoverCard?: (ctx: KerusiSeatCardContext) => ReactNode;
|
|
13
|
+
renderClickCard?: (ctx: KerusiSeatCardContext) => ReactNode;
|
|
14
|
+
placement: SeatCardPlacement;
|
|
15
|
+
className?: string;
|
|
16
|
+
appearance: SeatCardAppearance;
|
|
17
|
+
hoverCardDelay?: Partial<HoverCardDelay>;
|
|
18
|
+
hoverCardOnFocus: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface SeatCards {
|
|
21
|
+
/** Whether seats need pointer listeners at all. */
|
|
22
|
+
tracksPointer: boolean;
|
|
23
|
+
/** Whether seats need focus and blur listeners for a hover card (D12). */
|
|
24
|
+
tracksFocus: boolean;
|
|
25
|
+
/** A click behaviour is configured: `onSeatClick` or a click card (D14). */
|
|
26
|
+
pointer(type: 'enter' | 'leave' | 'move', seatId: string, pointerType: string): void;
|
|
27
|
+
focus(seatId: string): void;
|
|
28
|
+
blur(seatId: string): void;
|
|
29
|
+
/** A pan, pinch or wheel zoom began. */
|
|
30
|
+
gesture(): void;
|
|
31
|
+
/** Opens or closes the click card for an activated seat. */
|
|
32
|
+
activate(seatId: string, source: SeatClickSource): void;
|
|
33
|
+
/** Closes what is open, hover card first. True if a card was showing. */
|
|
34
|
+
dismiss(): boolean;
|
|
35
|
+
openSeatCard(seatId: string): void;
|
|
36
|
+
closeSeatCard(): void;
|
|
37
|
+
/** The seat whose click card is showing. */
|
|
38
|
+
openSeatCardId: string | null;
|
|
39
|
+
/** The seat → card `id` link, for the seat showing a hover card. */
|
|
40
|
+
describedBy: {
|
|
41
|
+
seatId: string;
|
|
42
|
+
id: string;
|
|
43
|
+
} | null;
|
|
44
|
+
/** Both cards, as elements to render inside the map's root. */
|
|
45
|
+
elements: ReactNode;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Seat hover events and the two seat cards (D10).
|
|
49
|
+
*
|
|
50
|
+
* The rules are core's: `reduceSeatHover()` decides what a pointer, a key or a
|
|
51
|
+
* timer means, and `placeSeatCard()` where a card goes. This hook holds the
|
|
52
|
+
* state, runs the one timer the reducer asks for, and renders the cards.
|
|
53
|
+
*/
|
|
54
|
+
export declare function useSeatCards(options: UseSeatCardsOptions): SeatCards;
|
|
55
|
+
//# sourceMappingURL=use-seat-cards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-seat-cards.d.ts","sourceRoot":"","sources":["../src/use-seat-cards.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,SAAS,EACT,UAAU,EACV,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EAGhB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGlD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACvC,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,eAAe,CAAC;IAC7B,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,WAAW,GAAG,IAAI,CAAC;IACpD,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,SAAS,CAAC;IAC5D,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,SAAS,CAAC;IAC5D,SAAS,EAAE,iBAAiB,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,kBAAkB,CAAC;IAC/B,cAAc,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACzC,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,mDAAmD;IACnD,aAAa,EAAE,OAAO,CAAC;IACvB,0EAA0E;IAC1E,WAAW,EAAE,OAAO,CAAC;IACrB,4EAA4E;IAC5E,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACrF,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,wCAAwC;IACxC,OAAO,IAAI,IAAI,CAAC;IAChB,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;IACxD,yEAAyE;IACzE,OAAO,IAAI,OAAO,CAAC;IACnB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,aAAa,IAAI,IAAI,CAAC;IACtB,4CAA4C;IAC5C,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,oEAAoE;IACpE,WAAW,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACnD,+DAA+D;IAC/D,QAAQ,EAAE,SAAS,CAAC;CACrB;AAUD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,SAAS,CAiSpE"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { IDLE_SEAT_HOVER, reduceSeatHover, resolveHoverCardDelay, seatAriaLabel, seatCardId, } from '@kerusiweb/core';
|
|
3
|
+
import { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import { SeatCard } from './seat-card.js';
|
|
5
|
+
/** `null`, `undefined`, `false`, `true`, `''` and `[]` draw nothing. */
|
|
6
|
+
function isEmptyContent(node) {
|
|
7
|
+
if (node === null || node === undefined || typeof node === 'boolean' || node === '') {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
return Array.isArray(node) && node.every(isEmptyContent);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Seat hover events and the two seat cards (D10).
|
|
14
|
+
*
|
|
15
|
+
* The rules are core's: `reduceSeatHover()` decides what a pointer, a key or a
|
|
16
|
+
* timer means, and `placeSeatCard()` where a card goes. This hook holds the
|
|
17
|
+
* state, runs the one timer the reducer asks for, and renders the cards.
|
|
18
|
+
*/
|
|
19
|
+
export function useSeatCards(options) {
|
|
20
|
+
const { rootRef, renderMap, selection, locale, ariaStrings, getSeatNode, focusSeat, renderHoverCard, renderClickCard, placement, className, appearance, hoverCardOnFocus, } = options;
|
|
21
|
+
const prefix = useId();
|
|
22
|
+
const delayOpen = options.hoverCardDelay?.open;
|
|
23
|
+
const delayClose = options.hoverCardDelay?.close;
|
|
24
|
+
const delay = useMemo(() => resolveHoverCardDelay({ open: delayOpen, close: delayClose }), [delayOpen, delayClose]);
|
|
25
|
+
// The latest of everything the long-lived callbacks read.
|
|
26
|
+
const live = useRef({ renderMap, delay, onSeatHover: options.onSeatHover });
|
|
27
|
+
live.current = { renderMap, delay, onSeatHover: options.onSeatHover };
|
|
28
|
+
// --- hover ----------------------------------------------------------------
|
|
29
|
+
const [hover, setHover] = useState(IDLE_SEAT_HOVER);
|
|
30
|
+
const hoverRef = useRef(IDLE_SEAT_HOVER);
|
|
31
|
+
const timer = useRef(undefined);
|
|
32
|
+
const feed = useCallback((event) => {
|
|
33
|
+
const result = reduceSeatHover(hoverRef.current, event, live.current.delay);
|
|
34
|
+
hoverRef.current = result.state;
|
|
35
|
+
setHover(result.state);
|
|
36
|
+
if (result.timer) {
|
|
37
|
+
clearTimeout(timer.current);
|
|
38
|
+
timer.current = undefined;
|
|
39
|
+
if (result.timer.action === 'start') {
|
|
40
|
+
const { kind, ms } = result.timer;
|
|
41
|
+
timer.current = setTimeout(() => feed({ type: 'timer', kind }), ms);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (result.report) {
|
|
45
|
+
const { seatId } = result.report;
|
|
46
|
+
const seat = seatId === null ? null : (live.current.renderMap.seatsById.get(seatId) ?? null);
|
|
47
|
+
if (seatId === null || seat) {
|
|
48
|
+
live.current.onSeatHover?.(seat);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}, []);
|
|
52
|
+
useEffect(() => () => clearTimeout(timer.current), []);
|
|
53
|
+
const tracksPointer = !!options.onSeatHover || !!renderHoverCard;
|
|
54
|
+
const tracksFocus = hoverCardOnFocus && !!renderHoverCard;
|
|
55
|
+
const pointer = useCallback((type, seatId, pointerType) => feed({ type, seatId, pointerType }), [feed]);
|
|
56
|
+
const focus = useCallback((seatId) => feed({ type: 'focus', seatId }), [feed]);
|
|
57
|
+
const blur = useCallback((seatId) => feed({ type: 'blur', seatId }), [feed]);
|
|
58
|
+
const gesture = useCallback(() => feed({ type: 'gesture' }), [feed]);
|
|
59
|
+
// --- click ----------------------------------------------------------------
|
|
60
|
+
const [clickId, setClickId] = useState(null);
|
|
61
|
+
const clickRef = useRef(null);
|
|
62
|
+
clickRef.current = clickId;
|
|
63
|
+
/** Set when the card is opened from the keyboard, so focus moves into it. */
|
|
64
|
+
const [clickFromKeyboard, setClickFromKeyboard] = useState(false);
|
|
65
|
+
/**
|
|
66
|
+
* Closes the click card. Focus goes back to the seat only when it was inside
|
|
67
|
+
* the card, so a press elsewhere on the page keeps the focus it just took.
|
|
68
|
+
*/
|
|
69
|
+
const closeClick = useCallback((restoreFocus) => {
|
|
70
|
+
const current = clickRef.current;
|
|
71
|
+
if (current !== null && restoreFocus) {
|
|
72
|
+
const card = rootRef.current?.querySelector('.kerusi-seat-card--click');
|
|
73
|
+
if (card?.contains(card.ownerDocument.activeElement)) {
|
|
74
|
+
// After the card is gone, so nothing fights the focus move.
|
|
75
|
+
queueMicrotask(() => focusSeat(current));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
setClickId(null);
|
|
79
|
+
setClickFromKeyboard(false);
|
|
80
|
+
}, [rootRef, focusSeat]);
|
|
81
|
+
const activate = useCallback((seatId, source) => {
|
|
82
|
+
if (!renderClickCard) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (clickId === seatId) {
|
|
86
|
+
closeClick(true);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
setClickId(seatId);
|
|
90
|
+
setClickFromKeyboard(source === 'keyboard');
|
|
91
|
+
}, [renderClickCard, clickId, closeClick]);
|
|
92
|
+
const openSeatCard = useCallback((seatId) => {
|
|
93
|
+
if (renderClickCard && live.current.renderMap.seatsById.has(seatId)) {
|
|
94
|
+
setClickId(seatId);
|
|
95
|
+
setClickFromKeyboard(false);
|
|
96
|
+
}
|
|
97
|
+
}, [renderClickCard]);
|
|
98
|
+
const closeSeatCard = useCallback(() => closeClick(true), [closeClick]);
|
|
99
|
+
// --- what is showing ------------------------------------------------------
|
|
100
|
+
const clickSeat = clickId ? renderMap.seatsById.get(clickId) : undefined;
|
|
101
|
+
const hoverSeat = hover.cardId ? renderMap.seatsById.get(hover.cardId) : undefined;
|
|
102
|
+
const contextFor = (seat, trigger, close) => ({ seat, selected: selection.has(seat.id), trigger, close });
|
|
103
|
+
const clickContent = renderClickCard && clickSeat
|
|
104
|
+
? renderClickCard(contextFor(clickSeat, 'click', () => closeClick(true)))
|
|
105
|
+
: null;
|
|
106
|
+
const clickShowing = clickSeat !== undefined && !isEmptyContent(clickContent);
|
|
107
|
+
// A click card open for a seat hides that seat's hover card.
|
|
108
|
+
const hoverContent = renderHoverCard && hoverSeat && hoverSeat.id !== clickId
|
|
109
|
+
? renderHoverCard(contextFor(hoverSeat, hover.cardTrigger === 'focus' ? 'focus' : 'hover', () => feed({ type: 'escape' })))
|
|
110
|
+
: null;
|
|
111
|
+
const hoverShowing = hoverSeat !== undefined && !isEmptyContent(hoverContent);
|
|
112
|
+
// A seat that goes away (a hidden section, a new map) takes its cards with it.
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
if (clickId !== null && !renderMap.seatsById.has(clickId)) {
|
|
115
|
+
closeClick(false);
|
|
116
|
+
}
|
|
117
|
+
if (hover.cardId !== null && !renderMap.seatsById.has(hover.cardId)) {
|
|
118
|
+
feed({ type: 'reset' });
|
|
119
|
+
}
|
|
120
|
+
}, [renderMap, clickId, hover.cardId, closeClick, feed]);
|
|
121
|
+
// A card whose render function is taken away has nothing to show.
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
if (!renderClickCard && clickId !== null) {
|
|
124
|
+
closeClick(false);
|
|
125
|
+
}
|
|
126
|
+
}, [renderClickCard, clickId, closeClick]);
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
if (!tracksPointer && hoverRef.current !== IDLE_SEAT_HOVER) {
|
|
129
|
+
feed({ type: 'reset' });
|
|
130
|
+
}
|
|
131
|
+
}, [tracksPointer, feed]);
|
|
132
|
+
const dismiss = useCallback(() => {
|
|
133
|
+
if (clickId !== null) {
|
|
134
|
+
closeClick(true);
|
|
135
|
+
return clickShowing;
|
|
136
|
+
}
|
|
137
|
+
if (hoverRef.current.cardId !== null || hoverRef.current.pendingId !== null) {
|
|
138
|
+
feed({ type: 'escape' });
|
|
139
|
+
return hoverShowing;
|
|
140
|
+
}
|
|
141
|
+
return false;
|
|
142
|
+
}, [clickId, clickShowing, hoverShowing, closeClick, feed]);
|
|
143
|
+
const anyOpen = clickId !== null || hover.cardId !== null;
|
|
144
|
+
// Escape anywhere dismisses a card, including with focus outside the map: a
|
|
145
|
+
// hover card the pointer opened must be dismissible without moving it (WCAG
|
|
146
|
+
// 1.4.13). The map's own key handling runs first and marks the event handled.
|
|
147
|
+
useEffect(() => {
|
|
148
|
+
if (!anyOpen) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const doc = rootRef.current?.ownerDocument ?? document;
|
|
152
|
+
const onKeyDown = (event) => {
|
|
153
|
+
if (event.key === 'Escape' && !event.defaultPrevented && dismiss()) {
|
|
154
|
+
event.preventDefault();
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
doc.addEventListener('keydown', onKeyDown);
|
|
158
|
+
return () => doc.removeEventListener('keydown', onKeyDown);
|
|
159
|
+
}, [anyOpen, dismiss, rootRef]);
|
|
160
|
+
// A press outside the click card and outside every seat closes it. A press on
|
|
161
|
+
// a seat is that seat's own click, which opens or closes a card by itself.
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
if (clickId === null) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const doc = rootRef.current?.ownerDocument ?? document;
|
|
167
|
+
const onPointerDown = (event) => {
|
|
168
|
+
const target = event.target;
|
|
169
|
+
const root = rootRef.current;
|
|
170
|
+
if (!target || !root) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const inCard = target.closest?.('.kerusi-seat-card--click');
|
|
174
|
+
const onSeat = root.contains(target) && target.closest?.('[data-seat-id]');
|
|
175
|
+
if (!inCard && !onSeat) {
|
|
176
|
+
closeClick(false);
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
doc.addEventListener('pointerdown', onPointerDown, true);
|
|
180
|
+
return () => doc.removeEventListener('pointerdown', onPointerDown, true);
|
|
181
|
+
}, [clickId, closeClick, rootRef]);
|
|
182
|
+
// --- render ---------------------------------------------------------------
|
|
183
|
+
const hoverId = seatCardId(prefix, 'hover');
|
|
184
|
+
const clickCardId = seatCardId(prefix, 'click');
|
|
185
|
+
const elements = (_jsxs(_Fragment, { children: [hoverShowing && hoverSeat && (_jsx(SeatCard, { kind: "hover", id: hoverId, seat: hoverSeat, label: "", placement: placement, appearance: appearance, className: className, rootRef: rootRef, getSeatNode: getSeatNode, onPointerEnter: () => feed({ type: 'card-enter' }), onPointerLeave: () => feed({ type: 'card-leave' }), children: hoverContent }, `hover:${hoverSeat.id}`)), clickShowing && clickSeat && (_jsx(SeatCard, { kind: "click", id: clickCardId, seat: clickSeat, label: seatAriaLabel(clickSeat, locale, ariaStrings), placement: placement, appearance: appearance, className: className, rootRef: rootRef, getSeatNode: getSeatNode, focusOnOpen: clickFromKeyboard, children: clickContent }, `click:${clickSeat.id}`))] }));
|
|
186
|
+
return {
|
|
187
|
+
tracksPointer,
|
|
188
|
+
tracksFocus,
|
|
189
|
+
pointer,
|
|
190
|
+
focus,
|
|
191
|
+
blur,
|
|
192
|
+
gesture,
|
|
193
|
+
activate,
|
|
194
|
+
dismiss,
|
|
195
|
+
openSeatCard,
|
|
196
|
+
closeSeatCard,
|
|
197
|
+
openSeatCardId: clickShowing ? clickId : null,
|
|
198
|
+
describedBy: hoverShowing && hoverSeat ? { seatId: hoverSeat.id, id: hoverId } : null,
|
|
199
|
+
elements,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=use-seat-cards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-seat-cards.js","sourceRoot":"","sources":["../src/use-seat-cards.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,aAAa,EACb,UAAU,GACX,MAAM,iBAAiB,CAAC;AAazB,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjF,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AA6C1C,wEAAwE;AACxE,SAAS,cAAc,CAAC,IAAe;IACrC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;QACpF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,OAA4B;IACvD,MAAM,EACJ,OAAO,EACP,SAAS,EACT,SAAS,EACT,MAAM,EACN,WAAW,EACX,WAAW,EACX,SAAS,EACT,eAAe,EACf,eAAe,EACf,SAAS,EACT,SAAS,EACT,UAAU,EACV,gBAAgB,GACjB,GAAG,OAAO,CAAC;IAEZ,MAAM,MAAM,GAAG,KAAK,EAAE,CAAC;IACvB,MAAM,SAAS,GAAG,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC;IAC/C,MAAM,UAAU,GAAG,OAAO,CAAC,cAAc,EAAE,KAAK,CAAC;IACjD,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,EACnE,CAAC,SAAS,EAAE,UAAU,CAAC,CACxB,CAAC;IAEF,0DAA0D;IAC1D,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5E,IAAI,CAAC,OAAO,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;IAEtE,6EAA6E;IAE7E,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAiB,eAAe,CAAC,CAAC;IACpE,MAAM,QAAQ,GAAG,MAAM,CAAiB,eAAe,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,MAAM,CAA4C,SAAS,CAAC,CAAC;IAE3E,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,KAAqB,EAAE,EAAE;QACjD,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC5E,QAAQ,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC;QAChC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAEvB,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5B,KAAK,CAAC,OAAO,GAAG,SAAS,CAAC;YAC1B,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;gBACpC,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC;gBAClC,KAAK,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC;YACjC,MAAM,IAAI,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;YAC7F,IAAI,MAAM,KAAK,IAAI,IAAI,IAAI,EAAE,CAAC;gBAC5B,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAEvD,MAAM,aAAa,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC,eAAe,CAAC;IACjE,MAAM,WAAW,GAAG,gBAAgB,IAAI,CAAC,CAAC,eAAe,CAAC;IAE1D,MAAM,OAAO,GAAG,WAAW,CACzB,CAAC,IAAgC,EAAE,MAAc,EAAE,WAAmB,EAAE,EAAE,CACxE,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,EACrC,CAAC,IAAI,CAAC,CACP,CAAC;IACF,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,MAAc,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IACvF,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,MAAc,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IACrF,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAErE,6EAA6E;IAE7E,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAC;IAC7C,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,6EAA6E;IAC7E,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAElE;;;OAGG;IACH,MAAM,UAAU,GAAG,WAAW,CAC5B,CAAC,YAAqB,EAAE,EAAE;QACxB,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;QACjC,IAAI,OAAO,KAAK,IAAI,IAAI,YAAY,EAAE,CAAC;YACrC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,aAAa,CAAC,0BAA0B,CAAC,CAAC;YACxE,IAAI,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,EAAE,CAAC;gBACrD,4DAA4D;gBAC5D,cAAc,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;QACD,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC,EACD,CAAC,OAAO,EAAE,SAAS,CAAC,CACrB,CAAC;IAEF,MAAM,QAAQ,GAAG,WAAW,CAC1B,CAAC,MAAc,EAAE,MAAuB,EAAE,EAAE;QAC1C,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;QACD,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;YACvB,UAAU,CAAC,IAAI,CAAC,CAAC;YACjB,OAAO;QACT,CAAC;QACD,UAAU,CAAC,MAAM,CAAC,CAAC;QACnB,oBAAoB,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC;IAC9C,CAAC,EACD,CAAC,eAAe,EAAE,OAAO,EAAE,UAAU,CAAC,CACvC,CAAC;IAEF,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,MAAc,EAAE,EAAE;QACjB,IAAI,eAAe,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACpE,UAAU,CAAC,MAAM,CAAC,CAAC;YACnB,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC,EACD,CAAC,eAAe,CAAC,CAClB,CAAC;IACF,MAAM,aAAa,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAExE,6EAA6E;IAE7E,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACzE,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAEnF,MAAM,UAAU,GAAG,CACjB,IAAgB,EAChB,OAAyC,EACzC,KAAiB,EACM,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAEzF,MAAM,YAAY,GAChB,eAAe,IAAI,SAAS;QAC1B,CAAC,CAAC,eAAe,CAAC,UAAU,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QACzE,CAAC,CAAC,IAAI,CAAC;IACX,MAAM,YAAY,GAAG,SAAS,KAAK,SAAS,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;IAE9E,6DAA6D;IAC7D,MAAM,YAAY,GAChB,eAAe,IAAI,SAAS,IAAI,SAAS,CAAC,EAAE,KAAK,OAAO;QACtD,CAAC,CAAC,eAAe,CACb,UAAU,CAAC,SAAS,EAAE,KAAK,CAAC,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE,CAC5E,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CACzB,CACF;QACH,CAAC,CAAC,IAAI,CAAC;IACX,MAAM,YAAY,GAAG,SAAS,KAAK,SAAS,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;IAE9E,+EAA+E;IAC/E,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,OAAO,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1D,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YACpE,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC;IAEzD,kEAAkE;IAClE,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,eAAe,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACzC,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,EAAE,CAAC,eAAe,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;IAC3C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,aAAa,IAAI,QAAQ,CAAC,OAAO,KAAK,eAAe,EAAE,CAAC;YAC3D,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,EAAE,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,CAAC;IAE1B,MAAM,OAAO,GAAG,WAAW,CAAC,GAAY,EAAE;QACxC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,UAAU,CAAC,IAAI,CAAC,CAAC;YACjB,OAAO,YAAY,CAAC;QACtB,CAAC;QACD,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,IAAI,IAAI,QAAQ,CAAC,OAAO,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;YAC5E,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YACzB,OAAO,YAAY,CAAC;QACtB,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC;IAE5D,MAAM,OAAO,GAAG,OAAO,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC;IAE1D,4EAA4E;IAC5E,4EAA4E;IAC5E,8EAA8E;IAC9E,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QACD,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,aAAa,IAAI,QAAQ,CAAC;QACvD,MAAM,SAAS,GAAG,CAAC,KAAoB,EAAE,EAAE;YACzC,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,gBAAgB,IAAI,OAAO,EAAE,EAAE,CAAC;gBACnE,KAAK,CAAC,cAAc,EAAE,CAAC;YACzB,CAAC;QACH,CAAC,CAAC;QACF,GAAG,CAAC,gBAAgB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAC3C,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,mBAAmB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAC7D,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAEhC,8EAA8E;IAC9E,2EAA2E;IAC3E,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;QACD,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,aAAa,IAAI,QAAQ,CAAC;QACvD,MAAM,aAAa,GAAG,CAAC,KAAmB,EAAE,EAAE;YAC5C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAwB,CAAC;YAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;YAC7B,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;gBACrB,OAAO;YACT,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,0BAA0B,CAAC,CAAC;YAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,gBAAgB,CAAC,CAAC;YAC3E,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;gBACvB,UAAU,CAAC,KAAK,CAAC,CAAC;YACpB,CAAC;QACH,CAAC,CAAC;QACF,GAAG,CAAC,gBAAgB,CAAC,aAAa,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;QACzD,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,mBAAmB,CAAC,aAAa,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;IAC3E,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IAEnC,6EAA6E;IAE7E,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEhD,MAAM,QAAQ,GAAG,CACf,8BACG,YAAY,IAAI,SAAS,IAAI,CAC5B,KAAC,QAAQ,IAEP,IAAI,EAAC,OAAO,EACZ,EAAE,EAAE,OAAO,EACX,IAAI,EAAE,SAAS,EACf,KAAK,EAAC,EAAE,EACR,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,WAAW,EACxB,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,EAClD,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,YAEjD,YAAY,IAbR,SAAS,SAAS,CAAC,EAAE,EAAE,CAcnB,CACZ,EACA,YAAY,IAAI,SAAS,IAAI,CAC5B,KAAC,QAAQ,IAEP,IAAI,EAAC,OAAO,EACZ,EAAE,EAAE,WAAW,EACf,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EACpD,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,iBAAiB,YAE7B,YAAY,IAZR,SAAS,SAAS,CAAC,EAAE,EAAE,CAanB,CACZ,IACA,CACJ,CAAC;IAEF,OAAO;QACL,aAAa;QACb,WAAW;QACX,OAAO;QACP,KAAK;QACL,IAAI;QACJ,OAAO;QACP,QAAQ;QACR,OAAO;QACP,YAAY;QACZ,aAAa;QACb,cAAc,EAAE,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;QAC7C,WAAW,EAAE,YAAY,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI;QACrF,QAAQ;KACT,CAAC;AACJ,CAAC"}
|