@seatlayer/vue 0.35.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 +113 -0
- package/dist/index.cjs +171 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +224 -0
- package/dist/index.d.ts +224 -0
- package/dist/index.js +151 -0
- package/dist/index.js.map +1 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SeatLayer
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# @seatlayer/vue
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@seatlayer/vue)
|
|
4
|
+
[](https://www.npmjs.com/package/@seatlayer/vue)
|
|
5
|
+
[](https://vuejs.org/)
|
|
6
|
+
[](../../LICENSE)
|
|
7
|
+
|
|
8
|
+
The official Vue 3 components for SeatLayer reserved seating. Render an
|
|
9
|
+
interactive chart, hold inventory in the browser, and complete the booking from
|
|
10
|
+
your trusted server.
|
|
11
|
+
|
|
12
|
+
[Package on npm](https://www.npmjs.com/package/@seatlayer/vue) ·
|
|
13
|
+
[SeatPicker docs](https://docs.seatlayer.io/buyer-sdk/seat-picker/) ·
|
|
14
|
+
[Live demo](https://app.seatlayer.io/demo/play) ·
|
|
15
|
+
[Website](https://seatlayer.io/developers/)
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @seatlayer/vue
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Requires Vue 3.3 or newer. Components are shipped as render functions, so you
|
|
24
|
+
need no Vue compiler plugin to consume this package.
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```vue
|
|
29
|
+
<script setup lang="ts">
|
|
30
|
+
import { ref } from 'vue';
|
|
31
|
+
import { SeatingChart, type SeatingChartExposed, type SelectedSeat } from '@seatlayer/vue';
|
|
32
|
+
|
|
33
|
+
const chart = ref<SeatingChartExposed | null>(null);
|
|
34
|
+
|
|
35
|
+
function onSelectionChange(seats: SelectedSeat[]) {
|
|
36
|
+
console.log('selected', seats);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function checkout() {
|
|
40
|
+
const held = await chart.value?.hold();
|
|
41
|
+
if (held) await bookOnYourServer(held.holdId);
|
|
42
|
+
}
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<template>
|
|
46
|
+
<SeatingChart
|
|
47
|
+
ref="chart"
|
|
48
|
+
event="ev_9f3a"
|
|
49
|
+
style="width: 100%; height: 520px"
|
|
50
|
+
@selection-change="onSelectionChange"
|
|
51
|
+
@hold="({ holdId }) => bookOnYourServer(holdId)"
|
|
52
|
+
/>
|
|
53
|
+
<button @click="checkout">Continue</button>
|
|
54
|
+
</template>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Props
|
|
58
|
+
|
|
59
|
+
| Prop | Type | Notes |
|
|
60
|
+
| --- | --- | --- |
|
|
61
|
+
| `event` | `string` | **Required.** Changing it rebuilds the chart. |
|
|
62
|
+
| `apiBase` | `string` | Defaults to the public API. |
|
|
63
|
+
| `maxSelection` | `number` | Cap on how many seats a buyer may select. |
|
|
64
|
+
| `publicKey` | `string` | Publishable key, when your integration uses one. |
|
|
65
|
+
| `locale` | `string` | BCP-47 locale for built-in copy. |
|
|
66
|
+
| `currency` | `string` | ISO currency for price formatting. |
|
|
67
|
+
| `colorblindSafe` | `boolean` | Render colorblind-safe seat glyphs. |
|
|
68
|
+
| `seatTooltip` | `boolean` | Set `false` to draw your own popover from `@seat-hover`. |
|
|
69
|
+
| `messages` | `object` | Copy overrides. Read once per rebuild. |
|
|
70
|
+
|
|
71
|
+
Only `event`, `apiBase`, `maxSelection`, `publicKey`, `locale`, `currency` and
|
|
72
|
+
`colorblindSafe` rebuild the canvas. Everything else is read live, so a parent
|
|
73
|
+
re-render never destroys the chart mid-selection.
|
|
74
|
+
|
|
75
|
+
## Events
|
|
76
|
+
|
|
77
|
+
| Event | Payload |
|
|
78
|
+
| --- | --- |
|
|
79
|
+
| `@selection-change` | `SelectedSeat[]` |
|
|
80
|
+
| `@hold` | `HoldResult` |
|
|
81
|
+
| `@hold-restored` | `HoldResult` |
|
|
82
|
+
| `@hold-expired` | — |
|
|
83
|
+
| `@ga-click` | `GAAreaAvailability` |
|
|
84
|
+
| `@error` | `unknown` |
|
|
85
|
+
| `@deck-tap` | `string` (floor id) |
|
|
86
|
+
| `@hint` | `string \| null` — `null` clears the hint |
|
|
87
|
+
| `@seat-hover` | `SeatHoverDetails \| null` — `null` when the pointer leaves |
|
|
88
|
+
|
|
89
|
+
## Imperative API
|
|
90
|
+
|
|
91
|
+
Everything on the template ref, typed as `SeatingChartExposed`:
|
|
92
|
+
|
|
93
|
+
`hold` · `resumeHold` · `getCurrentHold` · `getGAAreas` · `holdGA` ·
|
|
94
|
+
`bestAvailable` · `release` · `releaseLabels` · `getSelection` · `setSeatTier` ·
|
|
95
|
+
`getFloors` · `setFloor` · `setColorblindSafe` · `zoomIn` · `zoomOut` ·
|
|
96
|
+
`zoomToFit`
|
|
97
|
+
|
|
98
|
+
## Also exported
|
|
99
|
+
|
|
100
|
+
- `SeatPickerWidget` — the framework-agnostic one-call modal (`SeatPickerWidget.open()`).
|
|
101
|
+
- `attachPickerFrame` — host-side iframe helper; grows on `seatlayer:height` and
|
|
102
|
+
pins on `seatlayer:fullscreen`.
|
|
103
|
+
|
|
104
|
+
## Related
|
|
105
|
+
|
|
106
|
+
- [`@seatlayer/react`](https://www.npmjs.com/package/@seatlayer/react) — React components
|
|
107
|
+
- [`@seatlayer/angular`](https://www.npmjs.com/package/@seatlayer/angular) — Angular component
|
|
108
|
+
- [`@seatlayer/js`](https://www.npmjs.com/package/@seatlayer/js) — framework-agnostic core
|
|
109
|
+
- [Server SDKs](https://docs.seatlayer.io/server-sdk/install/) — Node.js, Python, PHP, Java, Go, Ruby, .NET
|
|
110
|
+
|
|
111
|
+
## License
|
|
112
|
+
|
|
113
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
SeatPickerWidget: () => import_js2.SeatPicker,
|
|
24
|
+
SeatingChart: () => SeatingChart,
|
|
25
|
+
attachPickerFrame: () => import_js3.attachPickerFrame
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(index_exports);
|
|
28
|
+
|
|
29
|
+
// src/SeatingChart.ts
|
|
30
|
+
var import_vue = require("vue");
|
|
31
|
+
var import_js = require("@seatlayer/js");
|
|
32
|
+
var SeatingChart = (0, import_vue.defineComponent)({
|
|
33
|
+
name: "SeatLayerSeatingChart",
|
|
34
|
+
props: {
|
|
35
|
+
/** Event key to render. Changing it rebuilds the chart. */
|
|
36
|
+
event: { type: String, required: true },
|
|
37
|
+
/** API base URL. Defaults to the public API. */
|
|
38
|
+
apiBase: { type: String, default: void 0 },
|
|
39
|
+
/** Cap on how many seats a buyer may select. */
|
|
40
|
+
maxSelection: { type: Number, default: void 0 },
|
|
41
|
+
/** Publishable key, when your integration uses one. */
|
|
42
|
+
publicKey: { type: String, default: void 0 },
|
|
43
|
+
/** BCP-47 locale for built-in copy. */
|
|
44
|
+
locale: { type: String, default: void 0 },
|
|
45
|
+
/** ISO currency for price formatting. */
|
|
46
|
+
currency: { type: String, default: void 0 },
|
|
47
|
+
/** Render with colorblind-safe seat glyphs. */
|
|
48
|
+
colorblindSafe: { type: Boolean, default: void 0 },
|
|
49
|
+
/** Copy overrides, read once per mount. */
|
|
50
|
+
messages: {
|
|
51
|
+
type: Object,
|
|
52
|
+
default: void 0
|
|
53
|
+
},
|
|
54
|
+
/**
|
|
55
|
+
* Show the built-in seat tooltip. Set false to draw your own popover from
|
|
56
|
+
* the `seat-hover` event.
|
|
57
|
+
*/
|
|
58
|
+
seatTooltip: { type: Boolean, default: void 0 }
|
|
59
|
+
},
|
|
60
|
+
emits: {
|
|
61
|
+
/** The buyer's selection changed. */
|
|
62
|
+
"selection-change": (_seats) => true,
|
|
63
|
+
/** A hold succeeded. */
|
|
64
|
+
hold: (_result) => true,
|
|
65
|
+
/** A previous hold was restored on mount. */
|
|
66
|
+
"hold-restored": (_result) => true,
|
|
67
|
+
/** The active hold lapsed. */
|
|
68
|
+
"hold-expired": () => true,
|
|
69
|
+
/** A GA area was clicked. */
|
|
70
|
+
"ga-click": (_area) => true,
|
|
71
|
+
/** Something failed — a network error, a rejected hold. */
|
|
72
|
+
error: (_error) => true,
|
|
73
|
+
/** A floor deck was tapped in the 3D view. */
|
|
74
|
+
"deck-tap": (_floorId) => true,
|
|
75
|
+
/** A transient hint worth showing the buyer, or `null` to clear it. */
|
|
76
|
+
hint: (_message) => true,
|
|
77
|
+
/** The pointer moved onto a seat, or off one (`null`). */
|
|
78
|
+
"seat-hover": (_details) => true
|
|
79
|
+
},
|
|
80
|
+
setup(props, { emit, expose }) {
|
|
81
|
+
const container = (0, import_vue.ref)(null);
|
|
82
|
+
const chart = (0, import_vue.shallowRef)(null);
|
|
83
|
+
const destroy = () => {
|
|
84
|
+
chart.value?.destroy();
|
|
85
|
+
chart.value = null;
|
|
86
|
+
};
|
|
87
|
+
const build = () => {
|
|
88
|
+
const element = container.value;
|
|
89
|
+
if (!element) return;
|
|
90
|
+
destroy();
|
|
91
|
+
const onSelectionChange = (seats) => emit("selection-change", seats);
|
|
92
|
+
const onHold = (result) => emit("hold", result);
|
|
93
|
+
const onHoldRestored = (result) => emit("hold-restored", result);
|
|
94
|
+
const onHoldExpired = () => emit("hold-expired");
|
|
95
|
+
const onGAClick = (area) => emit("ga-click", area);
|
|
96
|
+
const onError = (error) => emit("error", error);
|
|
97
|
+
const onDeckTap = (floorId) => emit("deck-tap", floorId);
|
|
98
|
+
const onHint = (message) => emit("hint", message);
|
|
99
|
+
const onSeatHover = (details) => emit("seat-hover", details);
|
|
100
|
+
const instance = new import_js.SeatingChart({
|
|
101
|
+
container: element,
|
|
102
|
+
event: props.event,
|
|
103
|
+
apiBase: props.apiBase,
|
|
104
|
+
maxSelection: props.maxSelection,
|
|
105
|
+
publicKey: props.publicKey,
|
|
106
|
+
locale: props.locale,
|
|
107
|
+
currency: props.currency,
|
|
108
|
+
colorblindSafe: props.colorblindSafe,
|
|
109
|
+
messages: props.messages,
|
|
110
|
+
seatTooltip: props.seatTooltip,
|
|
111
|
+
onSelectionChange,
|
|
112
|
+
onHold,
|
|
113
|
+
onHoldRestored,
|
|
114
|
+
onHoldExpired,
|
|
115
|
+
onGAClick,
|
|
116
|
+
onError,
|
|
117
|
+
onDeckTap,
|
|
118
|
+
onHint,
|
|
119
|
+
onSeatHover
|
|
120
|
+
});
|
|
121
|
+
chart.value = instance;
|
|
122
|
+
void instance.render();
|
|
123
|
+
};
|
|
124
|
+
(0, import_vue.watch)(
|
|
125
|
+
() => [
|
|
126
|
+
container.value,
|
|
127
|
+
props.event,
|
|
128
|
+
props.apiBase,
|
|
129
|
+
props.maxSelection,
|
|
130
|
+
props.publicKey,
|
|
131
|
+
props.locale,
|
|
132
|
+
props.currency,
|
|
133
|
+
props.colorblindSafe
|
|
134
|
+
],
|
|
135
|
+
build,
|
|
136
|
+
{ immediate: true, flush: "post" }
|
|
137
|
+
);
|
|
138
|
+
(0, import_vue.onBeforeUnmount)(destroy);
|
|
139
|
+
const exposed = {
|
|
140
|
+
hold: (options) => chart.value?.hold(options) ?? Promise.resolve(null),
|
|
141
|
+
resumeHold: (holdId) => chart.value?.resumeHold(holdId) ?? Promise.resolve(null),
|
|
142
|
+
getCurrentHold: () => chart.value?.getCurrentHold() ?? null,
|
|
143
|
+
getGAAreas: () => chart.value?.getGAAreas() ?? [],
|
|
144
|
+
holdGA: (areaId, qty, options) => chart.value?.holdGA(areaId, qty, options) ?? Promise.resolve(null),
|
|
145
|
+
bestAvailable: (qty, categoryKey) => chart.value?.bestAvailable(qty, categoryKey) ?? Promise.resolve(null),
|
|
146
|
+
release: () => chart.value?.release() ?? Promise.resolve(),
|
|
147
|
+
releaseLabels: (labels) => chart.value?.releaseLabels(labels) ?? Promise.resolve(false),
|
|
148
|
+
getSelection: () => chart.value?.getSelection() ?? [],
|
|
149
|
+
setSeatTier: (seatId, tierId) => chart.value?.setSeatTier(seatId, tierId),
|
|
150
|
+
getFloors: () => chart.value?.getFloors() ?? [],
|
|
151
|
+
setFloor: (floorId) => chart.value?.setFloor(floorId),
|
|
152
|
+
setColorblindSafe: (on) => chart.value?.setColorblindSafe(on),
|
|
153
|
+
zoomIn: () => chart.value?.zoomIn(),
|
|
154
|
+
zoomOut: () => chart.value?.zoomOut(),
|
|
155
|
+
zoomToFit: () => chart.value?.zoomToFit()
|
|
156
|
+
};
|
|
157
|
+
expose(exposed);
|
|
158
|
+
return () => (0, import_vue.h)("div", { ref: container });
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// src/index.ts
|
|
163
|
+
var import_js2 = require("@seatlayer/js");
|
|
164
|
+
var import_js3 = require("@seatlayer/js");
|
|
165
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
166
|
+
0 && (module.exports = {
|
|
167
|
+
SeatPickerWidget,
|
|
168
|
+
SeatingChart,
|
|
169
|
+
attachPickerFrame
|
|
170
|
+
});
|
|
171
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/SeatingChart.ts"],"sourcesContent":["/**\n * @seatlayer/vue — the Vue 3 wrapper for the SeatLayer embed SDK.\n *\n * Components are written as render functions rather than SFCs, so installing\n * this package needs no Vue compiler plugin.\n */\nexport { SeatingChart } from './SeatingChart';\nexport type { SeatingChartExposed } from './SeatingChart';\n\nexport type {\n SelectedSeat,\n HoldResult,\n BestAvailableResult,\n GAAreaAvailability,\n HoldLineItem,\n SeatHoverDetails,\n} from '@seatlayer/js';\n\n// The framework-agnostic widget class — for the one-call modal (SeatPickerWidget.open()).\nexport { SeatPicker as SeatPickerWidget } from '@seatlayer/js';\n\n// Host-side embed helper: grows the iframe on `seatlayer:height` and pins it on\n// `seatlayer:fullscreen`. Vue hosts depend on this package alone, so it has to be\n// reachable here rather than only from @seatlayer/js.\nexport { attachPickerFrame } from '@seatlayer/js';\n","import {\n defineComponent,\n h,\n onBeforeUnmount,\n ref,\n shallowRef,\n watch,\n type PropType,\n type Ref,\n} from 'vue';\nimport {\n SeatingChart as CoreSeatingChart,\n type SeatingChartOptions,\n type SelectedSeat,\n type HoldResult,\n type BestAvailableResult,\n type GAAreaAvailability,\n type SeatHoverDetails,\n} from '@seatlayer/js';\n\n/**\n * What `ref=\"chart\"` gives you — call these to drive the picker from your app.\n *\n * Vue exposes these through `defineExpose`, so a template ref is typed as this\n * rather than as the raw component instance.\n */\nexport interface SeatingChartExposed {\n /** Hold the current selection. Resolves the hold, or `null` on a 409 conflict. */\n hold(options?: { ttlMs?: number }): Promise<HoldResult | null>;\n /** Restore an active hold by its opaque id. */\n resumeHold(holdId: string): Promise<HoldResult | null>;\n /** Current active hold known to the chart. */\n getCurrentHold(): HoldResult | null;\n /** GA areas with live remaining capacity. */\n getGAAreas(): GAAreaAvailability[];\n /** Atomically hold a quantity from one GA area. */\n holdGA(areaId: string, qty: number, options?: { tierId?: string | null; ttlMs?: number }): Promise<HoldResult | null>;\n /** Ask the server for the `qty` best free seats and hold them atomically. */\n bestAvailable(qty: number, categoryKey?: string): Promise<BestAvailableResult | null>;\n /** Release the current hold (if any). */\n release(): Promise<void>;\n /** Release some held labels while keeping the remainder active. */\n releaseLabels(labels: string[]): Promise<boolean>;\n /** The current selection, with prices resolved from the chart categories. */\n getSelection(): SelectedSeat[];\n /** Choose a ticket tier for a selected seat; `null` reverts to the default. */\n setSeatTier(seatId: string, tierId: string | null): void;\n /** Floors of a multi-floor chart. Empty before the first render. */\n getFloors(): { id: string; name: string }[];\n /** Switch the shown floor (2D). No-ops on single-floor charts. */\n setFloor(floorId: string): void;\n /** Toggle colorblind-safe rendering at runtime. */\n setColorblindSafe(on: boolean): void;\n /** Zoom in one step (same increment as the wheel/pinch gesture). */\n zoomIn(): void;\n /** Zoom out one step. */\n zoomOut(): void;\n /** Reset the camera so the whole chart fits the container. */\n zoomToFit(): void;\n}\n\n/**\n * Vue 3 wrapper around the framework-agnostic `@seatlayer/js` SDK.\n *\n * The canvas is created once and torn down on unmount. Only the props that\n * change the chart's identity — `event`, `apiBase`, `maxSelection`, `publicKey`,\n * `locale`, `currency`, `colorblindSafe` — trigger a rebuild; everything else is\n * read live, so a parent re-render never destroys the canvas mid-selection.\n *\n * Written as a render function rather than an SFC so the package builds with\n * plain TypeScript — a consumer needs no Vue compiler plugin to install it.\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { ref } from 'vue';\n * import { SeatingChart, type SeatingChartExposed } from '@seatlayer/vue';\n *\n * const chart = ref<SeatingChartExposed | null>(null);\n * const checkout = async () => {\n * const held = await chart.value?.hold();\n * if (held) await pay(held.holdId);\n * };\n * </script>\n *\n * <template>\n * <SeatingChart ref=\"chart\" event=\"summer-gala\" @selection-change=\"onChange\" />\n * </template>\n * ```\n */\nexport const SeatingChart = defineComponent({\n name: 'SeatLayerSeatingChart',\n\n props: {\n /** Event key to render. Changing it rebuilds the chart. */\n event: { type: String, required: true },\n /** API base URL. Defaults to the public API. */\n apiBase: { type: String, default: undefined },\n /** Cap on how many seats a buyer may select. */\n maxSelection: { type: Number, default: undefined },\n /** Publishable key, when your integration uses one. */\n publicKey: { type: String, default: undefined },\n /** BCP-47 locale for built-in copy. */\n locale: { type: String, default: undefined },\n /** ISO currency for price formatting. */\n currency: { type: String, default: undefined },\n /** Render with colorblind-safe seat glyphs. */\n colorblindSafe: { type: Boolean, default: undefined },\n /** Copy overrides, read once per mount. */\n messages: {\n type: Object as PropType<SeatingChartOptions['messages']>,\n default: undefined,\n },\n /**\n * Show the built-in seat tooltip. Set false to draw your own popover from\n * the `seat-hover` event.\n */\n seatTooltip: { type: Boolean, default: undefined },\n },\n\n emits: {\n /** The buyer's selection changed. */\n 'selection-change': (_seats: SelectedSeat[]) => true,\n /** A hold succeeded. */\n hold: (_result: HoldResult) => true,\n /** A previous hold was restored on mount. */\n 'hold-restored': (_result: HoldResult) => true,\n /** The active hold lapsed. */\n 'hold-expired': () => true,\n /** A GA area was clicked. */\n 'ga-click': (_area: GAAreaAvailability) => true,\n /** Something failed — a network error, a rejected hold. */\n error: (_error: unknown) => true,\n /** A floor deck was tapped in the 3D view. */\n 'deck-tap': (_floorId: string) => true,\n /** A transient hint worth showing the buyer, or `null` to clear it. */\n hint: (_message: string | null) => true,\n /** The pointer moved onto a seat, or off one (`null`). */\n 'seat-hover': (_details: SeatHoverDetails | null) => true,\n },\n\n setup(props, { emit, expose }) {\n const container: Ref<HTMLDivElement | null> = ref(null);\n // shallowRef: the chart owns a canvas and a large scene graph, and making it\n // deeply reactive would have Vue walk all of it on every touch.\n const chart = shallowRef<CoreSeatingChart | null>(null);\n\n const destroy = () => {\n chart.value?.destroy();\n chart.value = null;\n };\n\n const build = () => {\n const element = container.value;\n if (!element) return;\n\n destroy();\n\n // Handlers are bound here rather than inline in the options literal.\n // Inline, TypeScript has to resolve `emit`'s overloads while it is still\n // contextually typing the literal against SeatingChartOptions, and it\n // gives up — collapsing to the last emit signature. Naming them first\n // separates the two inference problems, and reads better besides.\n const onSelectionChange = (seats: SelectedSeat[]) => emit('selection-change', seats);\n const onHold = (result: HoldResult) => emit('hold', result);\n const onHoldRestored = (result: HoldResult) => emit('hold-restored', result);\n const onHoldExpired = () => emit('hold-expired');\n const onGAClick = (area: GAAreaAvailability) => emit('ga-click', area);\n const onError = (error: unknown) => emit('error', error);\n const onDeckTap = (floorId: string) => emit('deck-tap', floorId);\n const onHint = (message: string | null) => emit('hint', message);\n const onSeatHover = (details: SeatHoverDetails | null) => emit('seat-hover', details);\n\n const instance = new CoreSeatingChart({\n container: element,\n event: props.event,\n apiBase: props.apiBase,\n maxSelection: props.maxSelection,\n publicKey: props.publicKey,\n locale: props.locale,\n currency: props.currency,\n colorblindSafe: props.colorblindSafe,\n messages: props.messages,\n seatTooltip: props.seatTooltip,\n onSelectionChange,\n onHold,\n onHoldRestored,\n onHoldExpired,\n onGAClick,\n onError,\n onDeckTap,\n onHint,\n onSeatHover,\n });\n\n chart.value = instance;\n void instance.render();\n };\n\n // `flush: 'post'` so the container element exists on the first run — a\n // pre-flush watcher would fire before the DOM node is attached.\n watch(\n () => [\n container.value,\n props.event,\n props.apiBase,\n props.maxSelection,\n props.publicKey,\n props.locale,\n props.currency,\n props.colorblindSafe,\n ],\n build,\n { immediate: true, flush: 'post' },\n );\n\n onBeforeUnmount(destroy);\n\n const exposed: SeatingChartExposed = {\n hold: (options) => chart.value?.hold(options) ?? Promise.resolve(null),\n resumeHold: (holdId) => chart.value?.resumeHold(holdId) ?? Promise.resolve(null),\n getCurrentHold: () => chart.value?.getCurrentHold() ?? null,\n getGAAreas: () => chart.value?.getGAAreas() ?? [],\n holdGA: (areaId, qty, options) => chart.value?.holdGA(areaId, qty, options) ?? Promise.resolve(null),\n bestAvailable: (qty, categoryKey) =>\n chart.value?.bestAvailable(qty, categoryKey) ?? Promise.resolve(null),\n release: () => chart.value?.release() ?? Promise.resolve(),\n releaseLabels: (labels) => chart.value?.releaseLabels(labels) ?? Promise.resolve(false),\n getSelection: () => chart.value?.getSelection() ?? [],\n setSeatTier: (seatId, tierId) => chart.value?.setSeatTier(seatId, tierId),\n getFloors: () => chart.value?.getFloors() ?? [],\n setFloor: (floorId) => chart.value?.setFloor(floorId),\n setColorblindSafe: (on) => chart.value?.setColorblindSafe(on),\n zoomIn: () => chart.value?.zoomIn(),\n zoomOut: () => chart.value?.zoomOut(),\n zoomToFit: () => chart.value?.zoomToFit(),\n };\n expose(exposed);\n\n return () => h('div', { ref: container });\n },\n});\n"],"mappings":"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","names":["CoreSeatingChart","import_js"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import * as _seatlayer_core from '@seatlayer/core';
|
|
2
|
+
import * as vue from 'vue';
|
|
3
|
+
import { PropType } from 'vue';
|
|
4
|
+
import { SeatingChartOptions, SelectedSeat, HoldResult, GAAreaAvailability, SeatHoverDetails, BestAvailableResult } from '@seatlayer/js';
|
|
5
|
+
export { BestAvailableResult, GAAreaAvailability, HoldLineItem, HoldResult, SeatHoverDetails, SeatPicker as SeatPickerWidget, SelectedSeat, attachPickerFrame } from '@seatlayer/js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* What `ref="chart"` gives you — call these to drive the picker from your app.
|
|
9
|
+
*
|
|
10
|
+
* Vue exposes these through `defineExpose`, so a template ref is typed as this
|
|
11
|
+
* rather than as the raw component instance.
|
|
12
|
+
*/
|
|
13
|
+
interface SeatingChartExposed {
|
|
14
|
+
/** Hold the current selection. Resolves the hold, or `null` on a 409 conflict. */
|
|
15
|
+
hold(options?: {
|
|
16
|
+
ttlMs?: number;
|
|
17
|
+
}): Promise<HoldResult | null>;
|
|
18
|
+
/** Restore an active hold by its opaque id. */
|
|
19
|
+
resumeHold(holdId: string): Promise<HoldResult | null>;
|
|
20
|
+
/** Current active hold known to the chart. */
|
|
21
|
+
getCurrentHold(): HoldResult | null;
|
|
22
|
+
/** GA areas with live remaining capacity. */
|
|
23
|
+
getGAAreas(): GAAreaAvailability[];
|
|
24
|
+
/** Atomically hold a quantity from one GA area. */
|
|
25
|
+
holdGA(areaId: string, qty: number, options?: {
|
|
26
|
+
tierId?: string | null;
|
|
27
|
+
ttlMs?: number;
|
|
28
|
+
}): Promise<HoldResult | null>;
|
|
29
|
+
/** Ask the server for the `qty` best free seats and hold them atomically. */
|
|
30
|
+
bestAvailable(qty: number, categoryKey?: string): Promise<BestAvailableResult | null>;
|
|
31
|
+
/** Release the current hold (if any). */
|
|
32
|
+
release(): Promise<void>;
|
|
33
|
+
/** Release some held labels while keeping the remainder active. */
|
|
34
|
+
releaseLabels(labels: string[]): Promise<boolean>;
|
|
35
|
+
/** The current selection, with prices resolved from the chart categories. */
|
|
36
|
+
getSelection(): SelectedSeat[];
|
|
37
|
+
/** Choose a ticket tier for a selected seat; `null` reverts to the default. */
|
|
38
|
+
setSeatTier(seatId: string, tierId: string | null): void;
|
|
39
|
+
/** Floors of a multi-floor chart. Empty before the first render. */
|
|
40
|
+
getFloors(): {
|
|
41
|
+
id: string;
|
|
42
|
+
name: string;
|
|
43
|
+
}[];
|
|
44
|
+
/** Switch the shown floor (2D). No-ops on single-floor charts. */
|
|
45
|
+
setFloor(floorId: string): void;
|
|
46
|
+
/** Toggle colorblind-safe rendering at runtime. */
|
|
47
|
+
setColorblindSafe(on: boolean): void;
|
|
48
|
+
/** Zoom in one step (same increment as the wheel/pinch gesture). */
|
|
49
|
+
zoomIn(): void;
|
|
50
|
+
/** Zoom out one step. */
|
|
51
|
+
zoomOut(): void;
|
|
52
|
+
/** Reset the camera so the whole chart fits the container. */
|
|
53
|
+
zoomToFit(): void;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Vue 3 wrapper around the framework-agnostic `@seatlayer/js` SDK.
|
|
57
|
+
*
|
|
58
|
+
* The canvas is created once and torn down on unmount. Only the props that
|
|
59
|
+
* change the chart's identity — `event`, `apiBase`, `maxSelection`, `publicKey`,
|
|
60
|
+
* `locale`, `currency`, `colorblindSafe` — trigger a rebuild; everything else is
|
|
61
|
+
* read live, so a parent re-render never destroys the canvas mid-selection.
|
|
62
|
+
*
|
|
63
|
+
* Written as a render function rather than an SFC so the package builds with
|
|
64
|
+
* plain TypeScript — a consumer needs no Vue compiler plugin to install it.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```vue
|
|
68
|
+
* <script setup lang="ts">
|
|
69
|
+
* import { ref } from 'vue';
|
|
70
|
+
* import { SeatingChart, type SeatingChartExposed } from '@seatlayer/vue';
|
|
71
|
+
*
|
|
72
|
+
* const chart = ref<SeatingChartExposed | null>(null);
|
|
73
|
+
* const checkout = async () => {
|
|
74
|
+
* const held = await chart.value?.hold();
|
|
75
|
+
* if (held) await pay(held.holdId);
|
|
76
|
+
* };
|
|
77
|
+
* </script>
|
|
78
|
+
*
|
|
79
|
+
* <template>
|
|
80
|
+
* <SeatingChart ref="chart" event="summer-gala" @selection-change="onChange" />
|
|
81
|
+
* </template>
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
declare const SeatingChart: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
85
|
+
/** Event key to render. Changing it rebuilds the chart. */
|
|
86
|
+
event: {
|
|
87
|
+
type: StringConstructor;
|
|
88
|
+
required: true;
|
|
89
|
+
};
|
|
90
|
+
/** API base URL. Defaults to the public API. */
|
|
91
|
+
apiBase: {
|
|
92
|
+
type: StringConstructor;
|
|
93
|
+
default: undefined;
|
|
94
|
+
};
|
|
95
|
+
/** Cap on how many seats a buyer may select. */
|
|
96
|
+
maxSelection: {
|
|
97
|
+
type: NumberConstructor;
|
|
98
|
+
default: undefined;
|
|
99
|
+
};
|
|
100
|
+
/** Publishable key, when your integration uses one. */
|
|
101
|
+
publicKey: {
|
|
102
|
+
type: StringConstructor;
|
|
103
|
+
default: undefined;
|
|
104
|
+
};
|
|
105
|
+
/** BCP-47 locale for built-in copy. */
|
|
106
|
+
locale: {
|
|
107
|
+
type: StringConstructor;
|
|
108
|
+
default: undefined;
|
|
109
|
+
};
|
|
110
|
+
/** ISO currency for price formatting. */
|
|
111
|
+
currency: {
|
|
112
|
+
type: StringConstructor;
|
|
113
|
+
default: undefined;
|
|
114
|
+
};
|
|
115
|
+
/** Render with colorblind-safe seat glyphs. */
|
|
116
|
+
colorblindSafe: {
|
|
117
|
+
type: BooleanConstructor;
|
|
118
|
+
default: undefined;
|
|
119
|
+
};
|
|
120
|
+
/** Copy overrides, read once per mount. */
|
|
121
|
+
messages: {
|
|
122
|
+
type: PropType<SeatingChartOptions["messages"]>;
|
|
123
|
+
default: undefined;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Show the built-in seat tooltip. Set false to draw your own popover from
|
|
127
|
+
* the `seat-hover` event.
|
|
128
|
+
*/
|
|
129
|
+
seatTooltip: {
|
|
130
|
+
type: BooleanConstructor;
|
|
131
|
+
default: undefined;
|
|
132
|
+
};
|
|
133
|
+
}>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
134
|
+
[key: string]: any;
|
|
135
|
+
}>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
|
|
136
|
+
/** The buyer's selection changed. */
|
|
137
|
+
'selection-change': (_seats: SelectedSeat[]) => true;
|
|
138
|
+
/** A hold succeeded. */
|
|
139
|
+
hold: (_result: HoldResult) => true;
|
|
140
|
+
/** A previous hold was restored on mount. */
|
|
141
|
+
'hold-restored': (_result: HoldResult) => true;
|
|
142
|
+
/** The active hold lapsed. */
|
|
143
|
+
'hold-expired': () => true;
|
|
144
|
+
/** A GA area was clicked. */
|
|
145
|
+
'ga-click': (_area: GAAreaAvailability) => true;
|
|
146
|
+
/** Something failed — a network error, a rejected hold. */
|
|
147
|
+
error: (_error: unknown) => true;
|
|
148
|
+
/** A floor deck was tapped in the 3D view. */
|
|
149
|
+
'deck-tap': (_floorId: string) => true;
|
|
150
|
+
/** A transient hint worth showing the buyer, or `null` to clear it. */
|
|
151
|
+
hint: (_message: string | null) => true;
|
|
152
|
+
/** The pointer moved onto a seat, or off one (`null`). */
|
|
153
|
+
'seat-hover': (_details: SeatHoverDetails | null) => true;
|
|
154
|
+
}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
155
|
+
/** Event key to render. Changing it rebuilds the chart. */
|
|
156
|
+
event: {
|
|
157
|
+
type: StringConstructor;
|
|
158
|
+
required: true;
|
|
159
|
+
};
|
|
160
|
+
/** API base URL. Defaults to the public API. */
|
|
161
|
+
apiBase: {
|
|
162
|
+
type: StringConstructor;
|
|
163
|
+
default: undefined;
|
|
164
|
+
};
|
|
165
|
+
/** Cap on how many seats a buyer may select. */
|
|
166
|
+
maxSelection: {
|
|
167
|
+
type: NumberConstructor;
|
|
168
|
+
default: undefined;
|
|
169
|
+
};
|
|
170
|
+
/** Publishable key, when your integration uses one. */
|
|
171
|
+
publicKey: {
|
|
172
|
+
type: StringConstructor;
|
|
173
|
+
default: undefined;
|
|
174
|
+
};
|
|
175
|
+
/** BCP-47 locale for built-in copy. */
|
|
176
|
+
locale: {
|
|
177
|
+
type: StringConstructor;
|
|
178
|
+
default: undefined;
|
|
179
|
+
};
|
|
180
|
+
/** ISO currency for price formatting. */
|
|
181
|
+
currency: {
|
|
182
|
+
type: StringConstructor;
|
|
183
|
+
default: undefined;
|
|
184
|
+
};
|
|
185
|
+
/** Render with colorblind-safe seat glyphs. */
|
|
186
|
+
colorblindSafe: {
|
|
187
|
+
type: BooleanConstructor;
|
|
188
|
+
default: undefined;
|
|
189
|
+
};
|
|
190
|
+
/** Copy overrides, read once per mount. */
|
|
191
|
+
messages: {
|
|
192
|
+
type: PropType<SeatingChartOptions["messages"]>;
|
|
193
|
+
default: undefined;
|
|
194
|
+
};
|
|
195
|
+
/**
|
|
196
|
+
* Show the built-in seat tooltip. Set false to draw your own popover from
|
|
197
|
+
* the `seat-hover` event.
|
|
198
|
+
*/
|
|
199
|
+
seatTooltip: {
|
|
200
|
+
type: BooleanConstructor;
|
|
201
|
+
default: undefined;
|
|
202
|
+
};
|
|
203
|
+
}>> & Readonly<{
|
|
204
|
+
"onSelection-change"?: ((_seats: _seatlayer_core.PickerSeat[]) => any) | undefined;
|
|
205
|
+
onHold?: ((_result: HoldResult) => any) | undefined;
|
|
206
|
+
"onHold-restored"?: ((_result: HoldResult) => any) | undefined;
|
|
207
|
+
"onHold-expired"?: (() => any) | undefined;
|
|
208
|
+
"onGa-click"?: ((_area: GAAreaAvailability) => any) | undefined;
|
|
209
|
+
onError?: ((_error: unknown) => any) | undefined;
|
|
210
|
+
"onDeck-tap"?: ((_floorId: string) => any) | undefined;
|
|
211
|
+
onHint?: ((_message: string | null) => any) | undefined;
|
|
212
|
+
"onSeat-hover"?: ((_details: SeatHoverDetails | null) => any) | undefined;
|
|
213
|
+
}>, {
|
|
214
|
+
messages: Record<string, string> | undefined;
|
|
215
|
+
apiBase: string;
|
|
216
|
+
maxSelection: number;
|
|
217
|
+
publicKey: string;
|
|
218
|
+
locale: string;
|
|
219
|
+
currency: string;
|
|
220
|
+
colorblindSafe: boolean;
|
|
221
|
+
seatTooltip: boolean;
|
|
222
|
+
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
223
|
+
|
|
224
|
+
export { SeatingChart, type SeatingChartExposed };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import * as _seatlayer_core from '@seatlayer/core';
|
|
2
|
+
import * as vue from 'vue';
|
|
3
|
+
import { PropType } from 'vue';
|
|
4
|
+
import { SeatingChartOptions, SelectedSeat, HoldResult, GAAreaAvailability, SeatHoverDetails, BestAvailableResult } from '@seatlayer/js';
|
|
5
|
+
export { BestAvailableResult, GAAreaAvailability, HoldLineItem, HoldResult, SeatHoverDetails, SeatPicker as SeatPickerWidget, SelectedSeat, attachPickerFrame } from '@seatlayer/js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* What `ref="chart"` gives you — call these to drive the picker from your app.
|
|
9
|
+
*
|
|
10
|
+
* Vue exposes these through `defineExpose`, so a template ref is typed as this
|
|
11
|
+
* rather than as the raw component instance.
|
|
12
|
+
*/
|
|
13
|
+
interface SeatingChartExposed {
|
|
14
|
+
/** Hold the current selection. Resolves the hold, or `null` on a 409 conflict. */
|
|
15
|
+
hold(options?: {
|
|
16
|
+
ttlMs?: number;
|
|
17
|
+
}): Promise<HoldResult | null>;
|
|
18
|
+
/** Restore an active hold by its opaque id. */
|
|
19
|
+
resumeHold(holdId: string): Promise<HoldResult | null>;
|
|
20
|
+
/** Current active hold known to the chart. */
|
|
21
|
+
getCurrentHold(): HoldResult | null;
|
|
22
|
+
/** GA areas with live remaining capacity. */
|
|
23
|
+
getGAAreas(): GAAreaAvailability[];
|
|
24
|
+
/** Atomically hold a quantity from one GA area. */
|
|
25
|
+
holdGA(areaId: string, qty: number, options?: {
|
|
26
|
+
tierId?: string | null;
|
|
27
|
+
ttlMs?: number;
|
|
28
|
+
}): Promise<HoldResult | null>;
|
|
29
|
+
/** Ask the server for the `qty` best free seats and hold them atomically. */
|
|
30
|
+
bestAvailable(qty: number, categoryKey?: string): Promise<BestAvailableResult | null>;
|
|
31
|
+
/** Release the current hold (if any). */
|
|
32
|
+
release(): Promise<void>;
|
|
33
|
+
/** Release some held labels while keeping the remainder active. */
|
|
34
|
+
releaseLabels(labels: string[]): Promise<boolean>;
|
|
35
|
+
/** The current selection, with prices resolved from the chart categories. */
|
|
36
|
+
getSelection(): SelectedSeat[];
|
|
37
|
+
/** Choose a ticket tier for a selected seat; `null` reverts to the default. */
|
|
38
|
+
setSeatTier(seatId: string, tierId: string | null): void;
|
|
39
|
+
/** Floors of a multi-floor chart. Empty before the first render. */
|
|
40
|
+
getFloors(): {
|
|
41
|
+
id: string;
|
|
42
|
+
name: string;
|
|
43
|
+
}[];
|
|
44
|
+
/** Switch the shown floor (2D). No-ops on single-floor charts. */
|
|
45
|
+
setFloor(floorId: string): void;
|
|
46
|
+
/** Toggle colorblind-safe rendering at runtime. */
|
|
47
|
+
setColorblindSafe(on: boolean): void;
|
|
48
|
+
/** Zoom in one step (same increment as the wheel/pinch gesture). */
|
|
49
|
+
zoomIn(): void;
|
|
50
|
+
/** Zoom out one step. */
|
|
51
|
+
zoomOut(): void;
|
|
52
|
+
/** Reset the camera so the whole chart fits the container. */
|
|
53
|
+
zoomToFit(): void;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Vue 3 wrapper around the framework-agnostic `@seatlayer/js` SDK.
|
|
57
|
+
*
|
|
58
|
+
* The canvas is created once and torn down on unmount. Only the props that
|
|
59
|
+
* change the chart's identity — `event`, `apiBase`, `maxSelection`, `publicKey`,
|
|
60
|
+
* `locale`, `currency`, `colorblindSafe` — trigger a rebuild; everything else is
|
|
61
|
+
* read live, so a parent re-render never destroys the canvas mid-selection.
|
|
62
|
+
*
|
|
63
|
+
* Written as a render function rather than an SFC so the package builds with
|
|
64
|
+
* plain TypeScript — a consumer needs no Vue compiler plugin to install it.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```vue
|
|
68
|
+
* <script setup lang="ts">
|
|
69
|
+
* import { ref } from 'vue';
|
|
70
|
+
* import { SeatingChart, type SeatingChartExposed } from '@seatlayer/vue';
|
|
71
|
+
*
|
|
72
|
+
* const chart = ref<SeatingChartExposed | null>(null);
|
|
73
|
+
* const checkout = async () => {
|
|
74
|
+
* const held = await chart.value?.hold();
|
|
75
|
+
* if (held) await pay(held.holdId);
|
|
76
|
+
* };
|
|
77
|
+
* </script>
|
|
78
|
+
*
|
|
79
|
+
* <template>
|
|
80
|
+
* <SeatingChart ref="chart" event="summer-gala" @selection-change="onChange" />
|
|
81
|
+
* </template>
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
declare const SeatingChart: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
85
|
+
/** Event key to render. Changing it rebuilds the chart. */
|
|
86
|
+
event: {
|
|
87
|
+
type: StringConstructor;
|
|
88
|
+
required: true;
|
|
89
|
+
};
|
|
90
|
+
/** API base URL. Defaults to the public API. */
|
|
91
|
+
apiBase: {
|
|
92
|
+
type: StringConstructor;
|
|
93
|
+
default: undefined;
|
|
94
|
+
};
|
|
95
|
+
/** Cap on how many seats a buyer may select. */
|
|
96
|
+
maxSelection: {
|
|
97
|
+
type: NumberConstructor;
|
|
98
|
+
default: undefined;
|
|
99
|
+
};
|
|
100
|
+
/** Publishable key, when your integration uses one. */
|
|
101
|
+
publicKey: {
|
|
102
|
+
type: StringConstructor;
|
|
103
|
+
default: undefined;
|
|
104
|
+
};
|
|
105
|
+
/** BCP-47 locale for built-in copy. */
|
|
106
|
+
locale: {
|
|
107
|
+
type: StringConstructor;
|
|
108
|
+
default: undefined;
|
|
109
|
+
};
|
|
110
|
+
/** ISO currency for price formatting. */
|
|
111
|
+
currency: {
|
|
112
|
+
type: StringConstructor;
|
|
113
|
+
default: undefined;
|
|
114
|
+
};
|
|
115
|
+
/** Render with colorblind-safe seat glyphs. */
|
|
116
|
+
colorblindSafe: {
|
|
117
|
+
type: BooleanConstructor;
|
|
118
|
+
default: undefined;
|
|
119
|
+
};
|
|
120
|
+
/** Copy overrides, read once per mount. */
|
|
121
|
+
messages: {
|
|
122
|
+
type: PropType<SeatingChartOptions["messages"]>;
|
|
123
|
+
default: undefined;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Show the built-in seat tooltip. Set false to draw your own popover from
|
|
127
|
+
* the `seat-hover` event.
|
|
128
|
+
*/
|
|
129
|
+
seatTooltip: {
|
|
130
|
+
type: BooleanConstructor;
|
|
131
|
+
default: undefined;
|
|
132
|
+
};
|
|
133
|
+
}>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
134
|
+
[key: string]: any;
|
|
135
|
+
}>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
|
|
136
|
+
/** The buyer's selection changed. */
|
|
137
|
+
'selection-change': (_seats: SelectedSeat[]) => true;
|
|
138
|
+
/** A hold succeeded. */
|
|
139
|
+
hold: (_result: HoldResult) => true;
|
|
140
|
+
/** A previous hold was restored on mount. */
|
|
141
|
+
'hold-restored': (_result: HoldResult) => true;
|
|
142
|
+
/** The active hold lapsed. */
|
|
143
|
+
'hold-expired': () => true;
|
|
144
|
+
/** A GA area was clicked. */
|
|
145
|
+
'ga-click': (_area: GAAreaAvailability) => true;
|
|
146
|
+
/** Something failed — a network error, a rejected hold. */
|
|
147
|
+
error: (_error: unknown) => true;
|
|
148
|
+
/** A floor deck was tapped in the 3D view. */
|
|
149
|
+
'deck-tap': (_floorId: string) => true;
|
|
150
|
+
/** A transient hint worth showing the buyer, or `null` to clear it. */
|
|
151
|
+
hint: (_message: string | null) => true;
|
|
152
|
+
/** The pointer moved onto a seat, or off one (`null`). */
|
|
153
|
+
'seat-hover': (_details: SeatHoverDetails | null) => true;
|
|
154
|
+
}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
155
|
+
/** Event key to render. Changing it rebuilds the chart. */
|
|
156
|
+
event: {
|
|
157
|
+
type: StringConstructor;
|
|
158
|
+
required: true;
|
|
159
|
+
};
|
|
160
|
+
/** API base URL. Defaults to the public API. */
|
|
161
|
+
apiBase: {
|
|
162
|
+
type: StringConstructor;
|
|
163
|
+
default: undefined;
|
|
164
|
+
};
|
|
165
|
+
/** Cap on how many seats a buyer may select. */
|
|
166
|
+
maxSelection: {
|
|
167
|
+
type: NumberConstructor;
|
|
168
|
+
default: undefined;
|
|
169
|
+
};
|
|
170
|
+
/** Publishable key, when your integration uses one. */
|
|
171
|
+
publicKey: {
|
|
172
|
+
type: StringConstructor;
|
|
173
|
+
default: undefined;
|
|
174
|
+
};
|
|
175
|
+
/** BCP-47 locale for built-in copy. */
|
|
176
|
+
locale: {
|
|
177
|
+
type: StringConstructor;
|
|
178
|
+
default: undefined;
|
|
179
|
+
};
|
|
180
|
+
/** ISO currency for price formatting. */
|
|
181
|
+
currency: {
|
|
182
|
+
type: StringConstructor;
|
|
183
|
+
default: undefined;
|
|
184
|
+
};
|
|
185
|
+
/** Render with colorblind-safe seat glyphs. */
|
|
186
|
+
colorblindSafe: {
|
|
187
|
+
type: BooleanConstructor;
|
|
188
|
+
default: undefined;
|
|
189
|
+
};
|
|
190
|
+
/** Copy overrides, read once per mount. */
|
|
191
|
+
messages: {
|
|
192
|
+
type: PropType<SeatingChartOptions["messages"]>;
|
|
193
|
+
default: undefined;
|
|
194
|
+
};
|
|
195
|
+
/**
|
|
196
|
+
* Show the built-in seat tooltip. Set false to draw your own popover from
|
|
197
|
+
* the `seat-hover` event.
|
|
198
|
+
*/
|
|
199
|
+
seatTooltip: {
|
|
200
|
+
type: BooleanConstructor;
|
|
201
|
+
default: undefined;
|
|
202
|
+
};
|
|
203
|
+
}>> & Readonly<{
|
|
204
|
+
"onSelection-change"?: ((_seats: _seatlayer_core.PickerSeat[]) => any) | undefined;
|
|
205
|
+
onHold?: ((_result: HoldResult) => any) | undefined;
|
|
206
|
+
"onHold-restored"?: ((_result: HoldResult) => any) | undefined;
|
|
207
|
+
"onHold-expired"?: (() => any) | undefined;
|
|
208
|
+
"onGa-click"?: ((_area: GAAreaAvailability) => any) | undefined;
|
|
209
|
+
onError?: ((_error: unknown) => any) | undefined;
|
|
210
|
+
"onDeck-tap"?: ((_floorId: string) => any) | undefined;
|
|
211
|
+
onHint?: ((_message: string | null) => any) | undefined;
|
|
212
|
+
"onSeat-hover"?: ((_details: SeatHoverDetails | null) => any) | undefined;
|
|
213
|
+
}>, {
|
|
214
|
+
messages: Record<string, string> | undefined;
|
|
215
|
+
apiBase: string;
|
|
216
|
+
maxSelection: number;
|
|
217
|
+
publicKey: string;
|
|
218
|
+
locale: string;
|
|
219
|
+
currency: string;
|
|
220
|
+
colorblindSafe: boolean;
|
|
221
|
+
seatTooltip: boolean;
|
|
222
|
+
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
223
|
+
|
|
224
|
+
export { SeatingChart, type SeatingChartExposed };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// src/SeatingChart.ts
|
|
2
|
+
import {
|
|
3
|
+
defineComponent,
|
|
4
|
+
h,
|
|
5
|
+
onBeforeUnmount,
|
|
6
|
+
ref,
|
|
7
|
+
shallowRef,
|
|
8
|
+
watch
|
|
9
|
+
} from "vue";
|
|
10
|
+
import {
|
|
11
|
+
SeatingChart as CoreSeatingChart
|
|
12
|
+
} from "@seatlayer/js";
|
|
13
|
+
var SeatingChart = defineComponent({
|
|
14
|
+
name: "SeatLayerSeatingChart",
|
|
15
|
+
props: {
|
|
16
|
+
/** Event key to render. Changing it rebuilds the chart. */
|
|
17
|
+
event: { type: String, required: true },
|
|
18
|
+
/** API base URL. Defaults to the public API. */
|
|
19
|
+
apiBase: { type: String, default: void 0 },
|
|
20
|
+
/** Cap on how many seats a buyer may select. */
|
|
21
|
+
maxSelection: { type: Number, default: void 0 },
|
|
22
|
+
/** Publishable key, when your integration uses one. */
|
|
23
|
+
publicKey: { type: String, default: void 0 },
|
|
24
|
+
/** BCP-47 locale for built-in copy. */
|
|
25
|
+
locale: { type: String, default: void 0 },
|
|
26
|
+
/** ISO currency for price formatting. */
|
|
27
|
+
currency: { type: String, default: void 0 },
|
|
28
|
+
/** Render with colorblind-safe seat glyphs. */
|
|
29
|
+
colorblindSafe: { type: Boolean, default: void 0 },
|
|
30
|
+
/** Copy overrides, read once per mount. */
|
|
31
|
+
messages: {
|
|
32
|
+
type: Object,
|
|
33
|
+
default: void 0
|
|
34
|
+
},
|
|
35
|
+
/**
|
|
36
|
+
* Show the built-in seat tooltip. Set false to draw your own popover from
|
|
37
|
+
* the `seat-hover` event.
|
|
38
|
+
*/
|
|
39
|
+
seatTooltip: { type: Boolean, default: void 0 }
|
|
40
|
+
},
|
|
41
|
+
emits: {
|
|
42
|
+
/** The buyer's selection changed. */
|
|
43
|
+
"selection-change": (_seats) => true,
|
|
44
|
+
/** A hold succeeded. */
|
|
45
|
+
hold: (_result) => true,
|
|
46
|
+
/** A previous hold was restored on mount. */
|
|
47
|
+
"hold-restored": (_result) => true,
|
|
48
|
+
/** The active hold lapsed. */
|
|
49
|
+
"hold-expired": () => true,
|
|
50
|
+
/** A GA area was clicked. */
|
|
51
|
+
"ga-click": (_area) => true,
|
|
52
|
+
/** Something failed — a network error, a rejected hold. */
|
|
53
|
+
error: (_error) => true,
|
|
54
|
+
/** A floor deck was tapped in the 3D view. */
|
|
55
|
+
"deck-tap": (_floorId) => true,
|
|
56
|
+
/** A transient hint worth showing the buyer, or `null` to clear it. */
|
|
57
|
+
hint: (_message) => true,
|
|
58
|
+
/** The pointer moved onto a seat, or off one (`null`). */
|
|
59
|
+
"seat-hover": (_details) => true
|
|
60
|
+
},
|
|
61
|
+
setup(props, { emit, expose }) {
|
|
62
|
+
const container = ref(null);
|
|
63
|
+
const chart = shallowRef(null);
|
|
64
|
+
const destroy = () => {
|
|
65
|
+
chart.value?.destroy();
|
|
66
|
+
chart.value = null;
|
|
67
|
+
};
|
|
68
|
+
const build = () => {
|
|
69
|
+
const element = container.value;
|
|
70
|
+
if (!element) return;
|
|
71
|
+
destroy();
|
|
72
|
+
const onSelectionChange = (seats) => emit("selection-change", seats);
|
|
73
|
+
const onHold = (result) => emit("hold", result);
|
|
74
|
+
const onHoldRestored = (result) => emit("hold-restored", result);
|
|
75
|
+
const onHoldExpired = () => emit("hold-expired");
|
|
76
|
+
const onGAClick = (area) => emit("ga-click", area);
|
|
77
|
+
const onError = (error) => emit("error", error);
|
|
78
|
+
const onDeckTap = (floorId) => emit("deck-tap", floorId);
|
|
79
|
+
const onHint = (message) => emit("hint", message);
|
|
80
|
+
const onSeatHover = (details) => emit("seat-hover", details);
|
|
81
|
+
const instance = new CoreSeatingChart({
|
|
82
|
+
container: element,
|
|
83
|
+
event: props.event,
|
|
84
|
+
apiBase: props.apiBase,
|
|
85
|
+
maxSelection: props.maxSelection,
|
|
86
|
+
publicKey: props.publicKey,
|
|
87
|
+
locale: props.locale,
|
|
88
|
+
currency: props.currency,
|
|
89
|
+
colorblindSafe: props.colorblindSafe,
|
|
90
|
+
messages: props.messages,
|
|
91
|
+
seatTooltip: props.seatTooltip,
|
|
92
|
+
onSelectionChange,
|
|
93
|
+
onHold,
|
|
94
|
+
onHoldRestored,
|
|
95
|
+
onHoldExpired,
|
|
96
|
+
onGAClick,
|
|
97
|
+
onError,
|
|
98
|
+
onDeckTap,
|
|
99
|
+
onHint,
|
|
100
|
+
onSeatHover
|
|
101
|
+
});
|
|
102
|
+
chart.value = instance;
|
|
103
|
+
void instance.render();
|
|
104
|
+
};
|
|
105
|
+
watch(
|
|
106
|
+
() => [
|
|
107
|
+
container.value,
|
|
108
|
+
props.event,
|
|
109
|
+
props.apiBase,
|
|
110
|
+
props.maxSelection,
|
|
111
|
+
props.publicKey,
|
|
112
|
+
props.locale,
|
|
113
|
+
props.currency,
|
|
114
|
+
props.colorblindSafe
|
|
115
|
+
],
|
|
116
|
+
build,
|
|
117
|
+
{ immediate: true, flush: "post" }
|
|
118
|
+
);
|
|
119
|
+
onBeforeUnmount(destroy);
|
|
120
|
+
const exposed = {
|
|
121
|
+
hold: (options) => chart.value?.hold(options) ?? Promise.resolve(null),
|
|
122
|
+
resumeHold: (holdId) => chart.value?.resumeHold(holdId) ?? Promise.resolve(null),
|
|
123
|
+
getCurrentHold: () => chart.value?.getCurrentHold() ?? null,
|
|
124
|
+
getGAAreas: () => chart.value?.getGAAreas() ?? [],
|
|
125
|
+
holdGA: (areaId, qty, options) => chart.value?.holdGA(areaId, qty, options) ?? Promise.resolve(null),
|
|
126
|
+
bestAvailable: (qty, categoryKey) => chart.value?.bestAvailable(qty, categoryKey) ?? Promise.resolve(null),
|
|
127
|
+
release: () => chart.value?.release() ?? Promise.resolve(),
|
|
128
|
+
releaseLabels: (labels) => chart.value?.releaseLabels(labels) ?? Promise.resolve(false),
|
|
129
|
+
getSelection: () => chart.value?.getSelection() ?? [],
|
|
130
|
+
setSeatTier: (seatId, tierId) => chart.value?.setSeatTier(seatId, tierId),
|
|
131
|
+
getFloors: () => chart.value?.getFloors() ?? [],
|
|
132
|
+
setFloor: (floorId) => chart.value?.setFloor(floorId),
|
|
133
|
+
setColorblindSafe: (on) => chart.value?.setColorblindSafe(on),
|
|
134
|
+
zoomIn: () => chart.value?.zoomIn(),
|
|
135
|
+
zoomOut: () => chart.value?.zoomOut(),
|
|
136
|
+
zoomToFit: () => chart.value?.zoomToFit()
|
|
137
|
+
};
|
|
138
|
+
expose(exposed);
|
|
139
|
+
return () => h("div", { ref: container });
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// src/index.ts
|
|
144
|
+
import { SeatPicker } from "@seatlayer/js";
|
|
145
|
+
import { attachPickerFrame } from "@seatlayer/js";
|
|
146
|
+
export {
|
|
147
|
+
SeatPicker as SeatPickerWidget,
|
|
148
|
+
SeatingChart,
|
|
149
|
+
attachPickerFrame
|
|
150
|
+
};
|
|
151
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/SeatingChart.ts","../src/index.ts"],"sourcesContent":["import {\n defineComponent,\n h,\n onBeforeUnmount,\n ref,\n shallowRef,\n watch,\n type PropType,\n type Ref,\n} from 'vue';\nimport {\n SeatingChart as CoreSeatingChart,\n type SeatingChartOptions,\n type SelectedSeat,\n type HoldResult,\n type BestAvailableResult,\n type GAAreaAvailability,\n type SeatHoverDetails,\n} from '@seatlayer/js';\n\n/**\n * What `ref=\"chart\"` gives you — call these to drive the picker from your app.\n *\n * Vue exposes these through `defineExpose`, so a template ref is typed as this\n * rather than as the raw component instance.\n */\nexport interface SeatingChartExposed {\n /** Hold the current selection. Resolves the hold, or `null` on a 409 conflict. */\n hold(options?: { ttlMs?: number }): Promise<HoldResult | null>;\n /** Restore an active hold by its opaque id. */\n resumeHold(holdId: string): Promise<HoldResult | null>;\n /** Current active hold known to the chart. */\n getCurrentHold(): HoldResult | null;\n /** GA areas with live remaining capacity. */\n getGAAreas(): GAAreaAvailability[];\n /** Atomically hold a quantity from one GA area. */\n holdGA(areaId: string, qty: number, options?: { tierId?: string | null; ttlMs?: number }): Promise<HoldResult | null>;\n /** Ask the server for the `qty` best free seats and hold them atomically. */\n bestAvailable(qty: number, categoryKey?: string): Promise<BestAvailableResult | null>;\n /** Release the current hold (if any). */\n release(): Promise<void>;\n /** Release some held labels while keeping the remainder active. */\n releaseLabels(labels: string[]): Promise<boolean>;\n /** The current selection, with prices resolved from the chart categories. */\n getSelection(): SelectedSeat[];\n /** Choose a ticket tier for a selected seat; `null` reverts to the default. */\n setSeatTier(seatId: string, tierId: string | null): void;\n /** Floors of a multi-floor chart. Empty before the first render. */\n getFloors(): { id: string; name: string }[];\n /** Switch the shown floor (2D). No-ops on single-floor charts. */\n setFloor(floorId: string): void;\n /** Toggle colorblind-safe rendering at runtime. */\n setColorblindSafe(on: boolean): void;\n /** Zoom in one step (same increment as the wheel/pinch gesture). */\n zoomIn(): void;\n /** Zoom out one step. */\n zoomOut(): void;\n /** Reset the camera so the whole chart fits the container. */\n zoomToFit(): void;\n}\n\n/**\n * Vue 3 wrapper around the framework-agnostic `@seatlayer/js` SDK.\n *\n * The canvas is created once and torn down on unmount. Only the props that\n * change the chart's identity — `event`, `apiBase`, `maxSelection`, `publicKey`,\n * `locale`, `currency`, `colorblindSafe` — trigger a rebuild; everything else is\n * read live, so a parent re-render never destroys the canvas mid-selection.\n *\n * Written as a render function rather than an SFC so the package builds with\n * plain TypeScript — a consumer needs no Vue compiler plugin to install it.\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * import { ref } from 'vue';\n * import { SeatingChart, type SeatingChartExposed } from '@seatlayer/vue';\n *\n * const chart = ref<SeatingChartExposed | null>(null);\n * const checkout = async () => {\n * const held = await chart.value?.hold();\n * if (held) await pay(held.holdId);\n * };\n * </script>\n *\n * <template>\n * <SeatingChart ref=\"chart\" event=\"summer-gala\" @selection-change=\"onChange\" />\n * </template>\n * ```\n */\nexport const SeatingChart = defineComponent({\n name: 'SeatLayerSeatingChart',\n\n props: {\n /** Event key to render. Changing it rebuilds the chart. */\n event: { type: String, required: true },\n /** API base URL. Defaults to the public API. */\n apiBase: { type: String, default: undefined },\n /** Cap on how many seats a buyer may select. */\n maxSelection: { type: Number, default: undefined },\n /** Publishable key, when your integration uses one. */\n publicKey: { type: String, default: undefined },\n /** BCP-47 locale for built-in copy. */\n locale: { type: String, default: undefined },\n /** ISO currency for price formatting. */\n currency: { type: String, default: undefined },\n /** Render with colorblind-safe seat glyphs. */\n colorblindSafe: { type: Boolean, default: undefined },\n /** Copy overrides, read once per mount. */\n messages: {\n type: Object as PropType<SeatingChartOptions['messages']>,\n default: undefined,\n },\n /**\n * Show the built-in seat tooltip. Set false to draw your own popover from\n * the `seat-hover` event.\n */\n seatTooltip: { type: Boolean, default: undefined },\n },\n\n emits: {\n /** The buyer's selection changed. */\n 'selection-change': (_seats: SelectedSeat[]) => true,\n /** A hold succeeded. */\n hold: (_result: HoldResult) => true,\n /** A previous hold was restored on mount. */\n 'hold-restored': (_result: HoldResult) => true,\n /** The active hold lapsed. */\n 'hold-expired': () => true,\n /** A GA area was clicked. */\n 'ga-click': (_area: GAAreaAvailability) => true,\n /** Something failed — a network error, a rejected hold. */\n error: (_error: unknown) => true,\n /** A floor deck was tapped in the 3D view. */\n 'deck-tap': (_floorId: string) => true,\n /** A transient hint worth showing the buyer, or `null` to clear it. */\n hint: (_message: string | null) => true,\n /** The pointer moved onto a seat, or off one (`null`). */\n 'seat-hover': (_details: SeatHoverDetails | null) => true,\n },\n\n setup(props, { emit, expose }) {\n const container: Ref<HTMLDivElement | null> = ref(null);\n // shallowRef: the chart owns a canvas and a large scene graph, and making it\n // deeply reactive would have Vue walk all of it on every touch.\n const chart = shallowRef<CoreSeatingChart | null>(null);\n\n const destroy = () => {\n chart.value?.destroy();\n chart.value = null;\n };\n\n const build = () => {\n const element = container.value;\n if (!element) return;\n\n destroy();\n\n // Handlers are bound here rather than inline in the options literal.\n // Inline, TypeScript has to resolve `emit`'s overloads while it is still\n // contextually typing the literal against SeatingChartOptions, and it\n // gives up — collapsing to the last emit signature. Naming them first\n // separates the two inference problems, and reads better besides.\n const onSelectionChange = (seats: SelectedSeat[]) => emit('selection-change', seats);\n const onHold = (result: HoldResult) => emit('hold', result);\n const onHoldRestored = (result: HoldResult) => emit('hold-restored', result);\n const onHoldExpired = () => emit('hold-expired');\n const onGAClick = (area: GAAreaAvailability) => emit('ga-click', area);\n const onError = (error: unknown) => emit('error', error);\n const onDeckTap = (floorId: string) => emit('deck-tap', floorId);\n const onHint = (message: string | null) => emit('hint', message);\n const onSeatHover = (details: SeatHoverDetails | null) => emit('seat-hover', details);\n\n const instance = new CoreSeatingChart({\n container: element,\n event: props.event,\n apiBase: props.apiBase,\n maxSelection: props.maxSelection,\n publicKey: props.publicKey,\n locale: props.locale,\n currency: props.currency,\n colorblindSafe: props.colorblindSafe,\n messages: props.messages,\n seatTooltip: props.seatTooltip,\n onSelectionChange,\n onHold,\n onHoldRestored,\n onHoldExpired,\n onGAClick,\n onError,\n onDeckTap,\n onHint,\n onSeatHover,\n });\n\n chart.value = instance;\n void instance.render();\n };\n\n // `flush: 'post'` so the container element exists on the first run — a\n // pre-flush watcher would fire before the DOM node is attached.\n watch(\n () => [\n container.value,\n props.event,\n props.apiBase,\n props.maxSelection,\n props.publicKey,\n props.locale,\n props.currency,\n props.colorblindSafe,\n ],\n build,\n { immediate: true, flush: 'post' },\n );\n\n onBeforeUnmount(destroy);\n\n const exposed: SeatingChartExposed = {\n hold: (options) => chart.value?.hold(options) ?? Promise.resolve(null),\n resumeHold: (holdId) => chart.value?.resumeHold(holdId) ?? Promise.resolve(null),\n getCurrentHold: () => chart.value?.getCurrentHold() ?? null,\n getGAAreas: () => chart.value?.getGAAreas() ?? [],\n holdGA: (areaId, qty, options) => chart.value?.holdGA(areaId, qty, options) ?? Promise.resolve(null),\n bestAvailable: (qty, categoryKey) =>\n chart.value?.bestAvailable(qty, categoryKey) ?? Promise.resolve(null),\n release: () => chart.value?.release() ?? Promise.resolve(),\n releaseLabels: (labels) => chart.value?.releaseLabels(labels) ?? Promise.resolve(false),\n getSelection: () => chart.value?.getSelection() ?? [],\n setSeatTier: (seatId, tierId) => chart.value?.setSeatTier(seatId, tierId),\n getFloors: () => chart.value?.getFloors() ?? [],\n setFloor: (floorId) => chart.value?.setFloor(floorId),\n setColorblindSafe: (on) => chart.value?.setColorblindSafe(on),\n zoomIn: () => chart.value?.zoomIn(),\n zoomOut: () => chart.value?.zoomOut(),\n zoomToFit: () => chart.value?.zoomToFit(),\n };\n expose(exposed);\n\n return () => h('div', { ref: container });\n },\n});\n","/**\n * @seatlayer/vue — the Vue 3 wrapper for the SeatLayer embed SDK.\n *\n * Components are written as render functions rather than SFCs, so installing\n * this package needs no Vue compiler plugin.\n */\nexport { SeatingChart } from './SeatingChart';\nexport type { SeatingChartExposed } from './SeatingChart';\n\nexport type {\n SelectedSeat,\n HoldResult,\n BestAvailableResult,\n GAAreaAvailability,\n HoldLineItem,\n SeatHoverDetails,\n} from '@seatlayer/js';\n\n// The framework-agnostic widget class — for the one-call modal (SeatPickerWidget.open()).\nexport { SeatPicker as SeatPickerWidget } from '@seatlayer/js';\n\n// Host-side embed helper: grows the iframe on `seatlayer:height` and pins it on\n// `seatlayer:fullscreen`. Vue hosts depend on this package alone, so it has to be\n// reachable here rather than only from @seatlayer/js.\nexport { attachPickerFrame } from '@seatlayer/js';\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@seatlayer/vue",
|
|
3
|
+
"version": "0.35.0",
|
|
4
|
+
"description": "Vue 3 components for the SeatLayer embed SDK — render an interactive seat picker and hold seats.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://docs.seatlayer.io/buyer-sdk/seat-picker/",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/seatlayer/seatlayer-sdk.git",
|
|
10
|
+
"directory": "packages/vue"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/seatlayer/seatlayer-sdk/issues"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "./dist/index.cjs",
|
|
17
|
+
"module": "./dist/index.js",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"import": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"default": "./dist/index.js"
|
|
24
|
+
},
|
|
25
|
+
"require": {
|
|
26
|
+
"types": "./dist/index.d.cts",
|
|
27
|
+
"default": "./dist/index.cjs"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist"
|
|
33
|
+
],
|
|
34
|
+
"sideEffects": false,
|
|
35
|
+
"keywords": [
|
|
36
|
+
"seating",
|
|
37
|
+
"seat-map",
|
|
38
|
+
"seating-chart",
|
|
39
|
+
"seat-picker",
|
|
40
|
+
"seatlayer",
|
|
41
|
+
"vue",
|
|
42
|
+
"vue3",
|
|
43
|
+
"ticketing"
|
|
44
|
+
],
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@seatlayer/js": "0.35.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"vue": ">=3.3.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"tsup": "^8.5.1",
|
|
53
|
+
"typescript": "^5.9.0",
|
|
54
|
+
"vue": "^3.5.13"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "tsup",
|
|
58
|
+
"typecheck": "tsc --noEmit"
|
|
59
|
+
}
|
|
60
|
+
}
|