@kerusiweb/react 2.3.0 → 3.0.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 +641 -609
- package/dist/kerusi-seatmap.d.ts +4 -2
- package/dist/kerusi-seatmap.d.ts.map +1 -1
- package/dist/kerusi-seatmap.js +30 -27
- package/dist/kerusi-seatmap.js.map +1 -1
- package/dist/kerusi-section.d.ts +16 -20
- package/dist/kerusi-section.d.ts.map +1 -1
- package/dist/kerusi-section.js +9 -15
- 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/types.d.ts +19 -15
- package/dist/types.d.ts.map +1 -1
- package/dist/use-viewport.d.ts +3 -1
- package/dist/use-viewport.d.ts.map +1 -1
- package/dist/use-viewport.js +16 -1
- package/dist/use-viewport.js.map +1 -1
- package/package.json +52 -52
- package/styles.css +371 -365
package/styles.css
CHANGED
|
@@ -1,365 +1,371 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* @kerusiweb/react — the one stylesheet the package ships.
|
|
3
|
-
*
|
|
4
|
-
* import '@kerusiweb/react/styles.css';
|
|
5
|
-
*
|
|
6
|
-
* It owns layout, opacity, cursor, paint order and the focus ring, and nothing
|
|
7
|
-
* else. Every colour is bound inline by the components instead, because a
|
|
8
|
-
* `var(--kerusi-selected-bg, …)` written here would carry the *library* default
|
|
9
|
-
* as its fallback and silently skip the `colors` prop tier — only the
|
|
10
|
-
* TypeScript side can resolve that one. See `cssVar()` in @kerusiweb/core for
|
|
11
|
-
* the three tiers and their precedence.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
/* --- the map ------------------------------------------------------------- */
|
|
15
|
-
|
|
16
|
-
.kerusi-seatmap {
|
|
17
|
-
display: flex;
|
|
18
|
-
flex-direction: column;
|
|
19
|
-
gap: 1.25rem;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
width: 100%;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
.
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
.
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
stroke:
|
|
297
|
-
stroke-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
1
|
+
/*
|
|
2
|
+
* @kerusiweb/react — the one stylesheet the package ships.
|
|
3
|
+
*
|
|
4
|
+
* import '@kerusiweb/react/styles.css';
|
|
5
|
+
*
|
|
6
|
+
* It owns layout, opacity, cursor, paint order and the focus ring, and nothing
|
|
7
|
+
* else. Every colour is bound inline by the components instead, because a
|
|
8
|
+
* `var(--kerusi-selected-bg, …)` written here would carry the *library* default
|
|
9
|
+
* as its fallback and silently skip the `colors` prop tier — only the
|
|
10
|
+
* TypeScript side can resolve that one. See `cssVar()` in @kerusiweb/core for
|
|
11
|
+
* the three tiers and their precedence.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/* --- the map ------------------------------------------------------------- */
|
|
15
|
+
|
|
16
|
+
.kerusi-seatmap {
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-direction: column;
|
|
19
|
+
gap: 1.25rem;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* A section's label, drawn inside the map at the top-left of its bounds (D5).
|
|
23
|
+
Its size comes from the section's seat size, so it scales with the map. */
|
|
24
|
+
.kerusi-section-label {
|
|
25
|
+
font-family: inherit;
|
|
26
|
+
font-weight: 600;
|
|
27
|
+
letter-spacing: 0.04em;
|
|
28
|
+
text-transform: uppercase;
|
|
29
|
+
opacity: 0.75;
|
|
30
|
+
pointer-events: none;
|
|
31
|
+
user-select: none;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Visually hidden, still announced. */
|
|
35
|
+
.kerusi-sr-only {
|
|
36
|
+
position: absolute;
|
|
37
|
+
width: 1px;
|
|
38
|
+
height: 1px;
|
|
39
|
+
margin: -1px;
|
|
40
|
+
padding: 0;
|
|
41
|
+
overflow: hidden;
|
|
42
|
+
clip: rect(0 0 0 0);
|
|
43
|
+
clip-path: inset(50%);
|
|
44
|
+
white-space: nowrap;
|
|
45
|
+
border: 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* --- the drawing: one svg, a group per section ---------------------------- */
|
|
49
|
+
|
|
50
|
+
/* The viewBox is the document's canvas and carries its proportions; CSS only
|
|
51
|
+
decides how wide it gets. */
|
|
52
|
+
.kerusi-seatmap__svg {
|
|
53
|
+
display: block;
|
|
54
|
+
width: 100%;
|
|
55
|
+
height: auto;
|
|
56
|
+
max-width: 100%;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.kerusi-seat {
|
|
60
|
+
cursor: pointer;
|
|
61
|
+
outline: none;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.kerusi-seat--unselectable {
|
|
65
|
+
cursor: not-allowed;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.kerusi-seat__label,
|
|
69
|
+
.kerusi-element__label {
|
|
70
|
+
pointer-events: none;
|
|
71
|
+
user-select: none;
|
|
72
|
+
font-family: inherit;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* A selected seat's number is stroked with the core colour and painted stroke
|
|
76
|
+
first, so the halo sits behind the glyphs and knocks the occupant figure out
|
|
77
|
+
from under them. Only the ordering lives here: the colour and width are bound
|
|
78
|
+
inline, for the reason at the top of this file. */
|
|
79
|
+
.kerusi-seat__label {
|
|
80
|
+
paint-order: stroke;
|
|
81
|
+
stroke-linejoin: round;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* No `transition: fill` here, deliberately. Every fill is a
|
|
85
|
+
`var(--kerusi-*, …)` substitution, and Chromium cannot transition a paint
|
|
86
|
+
property to a variable-derived value — the transition never advances and the
|
|
87
|
+
seat keeps its previous color for good, so a selected seat would never turn
|
|
88
|
+
selected. That covers the core's fill and the label's halo stroke too.
|
|
89
|
+
Correct color beats a 120ms fade. */
|
|
90
|
+
|
|
91
|
+
/* Drawn over the seat's own type-colour fill, so a held or booked seat still
|
|
92
|
+
recedes even though its hue no longer changes. Fill colour is bound inline;
|
|
93
|
+
opacity is the only thing this rule owns. */
|
|
94
|
+
.kerusi-seat__wash {
|
|
95
|
+
pointer-events: none;
|
|
96
|
+
opacity: 0.5;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* The bright plate inside a selected seat's frame. Colour is bound inline;
|
|
100
|
+
this rule only keeps it out of hit-testing, so a click still lands on the
|
|
101
|
+
seat group. */
|
|
102
|
+
.kerusi-seat__core {
|
|
103
|
+
pointer-events: none;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* Fill/stroke colour is bound inline per variant; these rules only set the
|
|
107
|
+
weight each variant reads at. Solid = settled (yours, or sold); hollow = a
|
|
108
|
+
hold still in progress. */
|
|
109
|
+
.kerusi-seat__occupant {
|
|
110
|
+
pointer-events: none;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* Lighter than the other variants: this one is a dark mark on a bright plate,
|
|
114
|
+
and a dark mark reads heavier than a light one at the same opacity. Kept as
|
|
115
|
+
texture so it does not compete with the number sitting on top of it. */
|
|
116
|
+
.kerusi-seat__occupant--selected {
|
|
117
|
+
opacity: 0.2;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.kerusi-seat__occupant--booked {
|
|
121
|
+
opacity: 0.55;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.kerusi-seat__occupant--held {
|
|
125
|
+
opacity: 0.75;
|
|
126
|
+
stroke-linecap: round;
|
|
127
|
+
stroke-linejoin: round;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/* The number competes with the silhouette behind it. */
|
|
131
|
+
.kerusi-seat--selected .kerusi-seat__label {
|
|
132
|
+
font-weight: 600;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* The focus ring is drawn on the seat box so it follows a rotated seat. It is
|
|
136
|
+
a separate mark from the selected frame — it strokes the outermost path, so a
|
|
137
|
+
focused selected seat shows both.
|
|
138
|
+
|
|
139
|
+
Two levels of fallback, so this token keeps the same precedence as every
|
|
140
|
+
other one: a `--kerusi-focus-ring` from the consumer's stylesheet wins;
|
|
141
|
+
otherwise `--kerusi-focus-ring-input`, which the component writes on the
|
|
142
|
+
`<svg>` from the `colors` prop; otherwise the inherited text color. */
|
|
143
|
+
.kerusi-seat:focus-visible .kerusi-seat__box {
|
|
144
|
+
stroke: var(--kerusi-focus-ring, var(--kerusi-focus-ring-input, currentColor));
|
|
145
|
+
stroke-width: 2.5;
|
|
146
|
+
paint-order: stroke;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* With a custom seat template the library cannot assume a `.kerusi-seat__box`
|
|
150
|
+
exists, so it draws this outline of the seat's body over the custom content
|
|
151
|
+
instead (the stock seat never renders it). Same colour chain as the ring
|
|
152
|
+
above; the stroke is centred on the outline because there is no fill of its
|
|
153
|
+
own to sit behind. */
|
|
154
|
+
.kerusi-seat__focus {
|
|
155
|
+
fill: none;
|
|
156
|
+
stroke: none;
|
|
157
|
+
pointer-events: none;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.kerusi-seat:focus-visible .kerusi-seat__focus {
|
|
161
|
+
stroke: var(--kerusi-focus-ring, var(--kerusi-focus-ring-input, currentColor));
|
|
162
|
+
stroke-width: 2.5;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.kerusi-element__void {
|
|
166
|
+
stroke-width: 1;
|
|
167
|
+
stroke-dasharray: 4 3;
|
|
168
|
+
opacity: 0.7;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/* --- the legend ---------------------------------------------------------- */
|
|
172
|
+
|
|
173
|
+
.kerusi-legend {
|
|
174
|
+
display: flex;
|
|
175
|
+
flex-wrap: wrap;
|
|
176
|
+
gap: 1.5rem;
|
|
177
|
+
font-size: 0.85rem;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.kerusi-legend__block {
|
|
181
|
+
display: flex;
|
|
182
|
+
flex-direction: column;
|
|
183
|
+
gap: 0.4rem;
|
|
184
|
+
min-width: 0;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.kerusi-legend__heading {
|
|
188
|
+
margin: 0;
|
|
189
|
+
font-size: 0.72rem;
|
|
190
|
+
font-weight: 600;
|
|
191
|
+
letter-spacing: 0.06em;
|
|
192
|
+
text-transform: uppercase;
|
|
193
|
+
opacity: 0.65;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.kerusi-legend__list {
|
|
197
|
+
display: flex;
|
|
198
|
+
flex-wrap: wrap;
|
|
199
|
+
gap: 0.35rem 0.9rem;
|
|
200
|
+
margin: 0;
|
|
201
|
+
padding: 0;
|
|
202
|
+
list-style: none;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.kerusi-legend__item {
|
|
206
|
+
display: inline-flex;
|
|
207
|
+
align-items: center;
|
|
208
|
+
gap: 0.4rem;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.kerusi-legend__swatch {
|
|
212
|
+
display: inline-block;
|
|
213
|
+
flex: none;
|
|
214
|
+
width: 0.85rem;
|
|
215
|
+
height: 0.85rem;
|
|
216
|
+
border-radius: 3px;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/* The seat glyph carries its own corner radius in the viewBox. */
|
|
220
|
+
.kerusi-legend__swatch--glyph {
|
|
221
|
+
border-radius: 0;
|
|
222
|
+
overflow: visible;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/* Mirrors `.kerusi-seat__occupant--*` on the map, so the key matches what it
|
|
226
|
+
is keying. Fill/stroke colour is bound inline; these set the weight. */
|
|
227
|
+
.kerusi-legend__occupant--selected {
|
|
228
|
+
opacity: 0.2;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.kerusi-legend__occupant--booked {
|
|
232
|
+
opacity: 0.55;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.kerusi-legend__occupant--held {
|
|
236
|
+
opacity: 0.75;
|
|
237
|
+
stroke-linecap: round;
|
|
238
|
+
stroke-linejoin: round;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.kerusi-legend__price {
|
|
242
|
+
opacity: 0.7;
|
|
243
|
+
font-variant-numeric: tabular-nums;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/* --- zoom, pan and maximize -------------------------------------------------
|
|
247
|
+
Everything below applies only when `zoomable` or `maximizable` is on; a plain
|
|
248
|
+
map renders none of these elements. Colours are bound inline from the
|
|
249
|
+
`--kerusi-*` tokens, so this file owns layout, motion and the focus ring.
|
|
250
|
+
The same rules as the Angular component's stylesheet. */
|
|
251
|
+
|
|
252
|
+
/* Same column the map sits in without the wrapper, so turning a feature on
|
|
253
|
+
does not move anything. */
|
|
254
|
+
.kerusi-seatmap__stage {
|
|
255
|
+
display: flex;
|
|
256
|
+
flex-direction: column;
|
|
257
|
+
gap: 1.25rem;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.kerusi-toolbar {
|
|
261
|
+
display: flex;
|
|
262
|
+
gap: 0.35rem;
|
|
263
|
+
align-self: flex-end;
|
|
264
|
+
/* Stays put under a maximized map's scrolling stage. */
|
|
265
|
+
flex: none;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.kerusi-control {
|
|
269
|
+
display: inline-flex;
|
|
270
|
+
align-items: center;
|
|
271
|
+
justify-content: center;
|
|
272
|
+
box-sizing: border-box;
|
|
273
|
+
/* 44px: a comfortable touch target on the phones this exists for. */
|
|
274
|
+
width: 2.75rem;
|
|
275
|
+
height: 2.75rem;
|
|
276
|
+
padding: 0;
|
|
277
|
+
border: 1px solid;
|
|
278
|
+
border-radius: 0.4rem;
|
|
279
|
+
font: inherit;
|
|
280
|
+
cursor: pointer;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/* `aria-disabled`, not `disabled`: a disabled button drops out of the tab order,
|
|
284
|
+
and pressing "zoom in" until the ceiling would throw focus away mid-press. */
|
|
285
|
+
.kerusi-control[aria-disabled='true'] {
|
|
286
|
+
opacity: 0.45;
|
|
287
|
+
cursor: default;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.kerusi-control svg {
|
|
291
|
+
width: 1.4rem;
|
|
292
|
+
height: 1.4rem;
|
|
293
|
+
fill: none;
|
|
294
|
+
stroke: currentColor;
|
|
295
|
+
stroke-width: 2;
|
|
296
|
+
stroke-linecap: round;
|
|
297
|
+
stroke-linejoin: round;
|
|
298
|
+
pointer-events: none;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.kerusi-control:focus-visible,
|
|
302
|
+
.kerusi-viewport:focus-visible {
|
|
303
|
+
outline: 2px solid var(--kerusi-focus-ring, var(--kerusi-focus-ring-input, currentColor));
|
|
304
|
+
outline-offset: 2px;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/* A window onto the map. `clip` rather than `hidden`: a hidden box can still be
|
|
308
|
+
scrolled by the browser when a seat inside takes focus, which would fight the
|
|
309
|
+
transform; a clipped one cannot be scrolled at all. */
|
|
310
|
+
.kerusi-viewport {
|
|
311
|
+
position: relative;
|
|
312
|
+
overflow: hidden;
|
|
313
|
+
overflow: clip;
|
|
314
|
+
user-select: none;
|
|
315
|
+
-webkit-user-select: none;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/* The same column the map sits in outside a viewport. */
|
|
319
|
+
.kerusi-viewport__content {
|
|
320
|
+
display: flex;
|
|
321
|
+
flex-direction: column;
|
|
322
|
+
gap: 1.25rem;
|
|
323
|
+
transform-origin: 0 0;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/* Only for a button, key or reveal. A finger or wheel moves the map directly, and
|
|
327
|
+
easing behind it would feel like lag. */
|
|
328
|
+
.kerusi-viewport__content--animated {
|
|
329
|
+
transition: transform 160ms ease-out;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
@media (prefers-reduced-motion: reduce) {
|
|
333
|
+
.kerusi-viewport__content--animated {
|
|
334
|
+
transition: none;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/* Maximized: the map fills the screen. This is the whole feature on iPhone,
|
|
339
|
+
which has no element full screen; elsewhere native full screen is requested
|
|
340
|
+
on top. `Canvas` / `CanvasText` and the backdrop come from inline styles. */
|
|
341
|
+
.kerusi-seatmap--maximized {
|
|
342
|
+
position: fixed;
|
|
343
|
+
inset: 0;
|
|
344
|
+
z-index: var(--kerusi-maximized-z-index, 1000);
|
|
345
|
+
box-sizing: border-box;
|
|
346
|
+
padding: 0.75rem;
|
|
347
|
+
gap: 0.5rem;
|
|
348
|
+
overflow: hidden;
|
|
349
|
+
overscroll-behavior: contain;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.kerusi-seatmap--maximized .kerusi-seatmap__stage {
|
|
353
|
+
flex: 1 1 auto;
|
|
354
|
+
min-height: 0;
|
|
355
|
+
gap: 0.5rem;
|
|
356
|
+
/* A map that is not zoomable has no viewport to pan, so it scrolls instead. */
|
|
357
|
+
overflow: auto;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.kerusi-seatmap--maximized .kerusi-viewport {
|
|
361
|
+
flex: 1 1 auto;
|
|
362
|
+
min-height: 0;
|
|
363
|
+
container-type: size;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/* Fit the whole canvas to the screen: as wide as the viewport allows, or as
|
|
367
|
+
wide as its height allows at the canvas's proportions, whichever is less.
|
|
368
|
+
`--kerusi-canvas-aspect` is the canvas's width over its height, set inline. */
|
|
369
|
+
.kerusi-seatmap--maximized .kerusi-viewport__content {
|
|
370
|
+
width: min(100cqw, 100cqh * var(--kerusi-canvas-aspect, 1));
|
|
371
|
+
}
|