@seatschart/vue 0.0.0-stage → 0.2.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 +134 -2
- package/dist/Designer.d.ts +65 -0
- package/dist/Designer.d.ts.map +1 -0
- package/dist/Designer.js +45 -0
- package/dist/EventManager.d.ts +44 -0
- package/dist/EventManager.d.ts.map +1 -0
- package/dist/EventManager.js +38 -0
- package/dist/SeatChart.d.ts +164 -0
- package/dist/SeatChart.d.ts.map +1 -0
- package/dist/SeatChart.js +68 -0
- package/dist/define.d.ts +15 -0
- package/dist/define.d.ts.map +1 -0
- package/dist/define.js +24 -0
- package/dist/host-core.d.ts +125 -0
- package/dist/host-core.d.ts.map +1 -0
- package/dist/host-core.js +292 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/package.json +51 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SeatsChart
|
|
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
CHANGED
|
@@ -1,3 +1,135 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @seatschart/vue
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Vue 3 components for SeatsChart: the buyer seat chart, the Event Manager and the map designer. They are thin wrappers
|
|
4
|
+
over the script-tag host API of [`@seatschart/embed`](https://www.npmjs.com/package/@seatschart/embed) (`SeatsChart`,
|
|
5
|
+
`SeatsChartEventManager`, `SeatsChartDesigner`): same options, seats.io-compatible callback names and the same
|
|
6
|
+
commands. Works with Nuxt: nothing touches `window` at import and the iframe is created on mount only.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install @seatschart/vue @seatschart/embed
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Vue 3.3 or newer.
|
|
15
|
+
|
|
16
|
+
## Buyer seat chart
|
|
17
|
+
|
|
18
|
+
`token` is a short-lived buyer JWT minted by your server with the API key (`POST /api/viewer-tokens`). Never pass an
|
|
19
|
+
API key or a secret to the browser.
|
|
20
|
+
|
|
21
|
+
```vue
|
|
22
|
+
<script setup lang="ts">
|
|
23
|
+
import { ref } from "vue";
|
|
24
|
+
import { SeatChart, useSeatChart } from "@seatschart/vue";
|
|
25
|
+
|
|
26
|
+
const props = defineProps<{ eventId: string; jwt: string }>();
|
|
27
|
+
const chart = useSeatChart(); // typed template ref (SeatChartHandle | null)
|
|
28
|
+
const cart = ref<string[]>([]);
|
|
29
|
+
const maxSeats = ref(4);
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<template>
|
|
33
|
+
<SeatChart
|
|
34
|
+
ref="chart"
|
|
35
|
+
class="seat-map"
|
|
36
|
+
web-base="https://your-tenant.seatschart.com"
|
|
37
|
+
:event="props.eventId"
|
|
38
|
+
:token="props.jwt"
|
|
39
|
+
language="pt"
|
|
40
|
+
:height="640"
|
|
41
|
+
:max-selected-objects="maxSeats"
|
|
42
|
+
:object-color="{ byStatus: { locked: '#f59e0b' } }"
|
|
43
|
+
:settings3d="{ lightPreset: 'exteriorSunset' }"
|
|
44
|
+
@chart-rendered="(e) => console.log('ready', e.objectCount)"
|
|
45
|
+
@object-selected="(e) => cart.push(e.label)"
|
|
46
|
+
@object-deselected="(e) => (cart = cart.filter((l) => l !== e.label))"
|
|
47
|
+
@session-hold="(e) => console.log('hold token', e.holdToken)"
|
|
48
|
+
@hold-failed="(e) => console.error(e.objectIds, e.message)"
|
|
49
|
+
/>
|
|
50
|
+
<button type="button" @click="chart?.clearSelection()">Clear</button>
|
|
51
|
+
<button type="button" @click="chart?.selectBestAvailable({ number: 2, categories: ['VIP'] })">Best 2 VIP</button>
|
|
52
|
+
<button type="button" @click="chart?.showViewFromSeat(cart[0] ?? '')">View from seat</button>
|
|
53
|
+
</template>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
- **Props** are the `SeatsChart` options of `@seatschart/embed` (`event`, `token`, `webBase`, `parentOrigin`,
|
|
57
|
+
`channel`, `channelKey(s)`, `holdToken`, `pricing`, `language`, `theme`, `defaultRenderer`, …) and every declarative
|
|
58
|
+
renderer option (`objectColor`, `objectLabel`, `tooltip`, `maxSelectedObjects`, `legend`, `filterControls`,
|
|
59
|
+
`settings3d`, …). The chart `style` option (`{ font, cornerRadius, buttonShape }`) is **`chart-style`**: `class` and
|
|
60
|
+
`style` style the wrapper `<div data-seatschart-chart>`; `class-name` styles the iframe.
|
|
61
|
+
- **Reactive updates**: values are compared, not identities (nested changes count). Declarative options and `pricing`
|
|
62
|
+
are applied live with `changeConfig` (no reload); `height`, `title` and `class-name` update the iframe in place; any
|
|
63
|
+
other prop re-renders the iframe and the hold session continues.
|
|
64
|
+
- **Events**: every chart callback, kebab-case without `on`: `@object-selected`, `@object-clicked`,
|
|
65
|
+
`@hold-succeeded`, `@hold-confirmed`, `@selection-invalid`, `@best-available-selected`, `@floor-changed`,
|
|
66
|
+
`@full-screen-opened`, `@hold-created` (`SEATSCHART_RESERVATION_SUCCESS`), … (payloads as in `@seatschart/embed`).
|
|
67
|
+
- **Host-drawn prompts**: a `@places-prompt`, `@ticket-type-prompt` or `@places-with-ticket-types-prompt` handler
|
|
68
|
+
switches that viewer prompt to your page; it gets `(params, confirm, cancel)`.
|
|
69
|
+
- **Template ref** (`SeatChartHandle`): every `SeatsChart` command — `selectObjects`, `deselectObjects`,
|
|
70
|
+
`clearSelection`, `trySelectObjects`, `selectBestAvailable`, `changeConfig`, `setFilters`, `zoomToObjects`,
|
|
71
|
+
`zoomToSection`, `goToFloor`, `showViewFromSeat`, `getHoldToken`, `releaseHoldToken`, `exportImage`, … Each resolves
|
|
72
|
+
once the chart rendered and rejects with `ChartCommandError`. Also `selectedObjects`, `holdToken`, `chart` (the
|
|
73
|
+
`SeatsChart` instance), `getIframe()` and `rerender()`.
|
|
74
|
+
- **Cleanup**: unmounting removes the iframe and its message listener; pending commands reject.
|
|
75
|
+
|
|
76
|
+
## Event Manager (back office)
|
|
77
|
+
|
|
78
|
+
```vue
|
|
79
|
+
<script setup lang="ts">
|
|
80
|
+
import { EventManager, useEventManager } from "@seatschart/vue";
|
|
81
|
+
const manager = useEventManager();
|
|
82
|
+
</script>
|
|
83
|
+
|
|
84
|
+
<template>
|
|
85
|
+
<EventManager
|
|
86
|
+
ref="manager"
|
|
87
|
+
web-base="https://your-tenant.seatschart.com"
|
|
88
|
+
:event="eventId"
|
|
89
|
+
:token="managerEmbedToken"
|
|
90
|
+
mode="select"
|
|
91
|
+
color-scheme="auto"
|
|
92
|
+
:max-selected-objects="8"
|
|
93
|
+
@selection-changed="(objects) => (cart = objects.map((o) => o.label))"
|
|
94
|
+
/>
|
|
95
|
+
<button type="button" @click="manager?.setHighlightedObjects(['A-1'])">Highlight A-1</button>
|
|
96
|
+
</template>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Selectability rules, `max-selected-objects`, `selected-objects`, `order`, `filters`, `language` and `color-scheme`
|
|
100
|
+
change live (`changeConfig`); `mode`, `event` or `token` re-render the iframe. The ref has every
|
|
101
|
+
`SeatsChartEventManager` command (`listSelectedObjects`, `selectObjects`, `listOrderChanges`, `zoomToObjects`, …).
|
|
102
|
+
|
|
103
|
+
## Designer
|
|
104
|
+
|
|
105
|
+
```vue
|
|
106
|
+
<script setup lang="ts">
|
|
107
|
+
import { Designer, useDesigner } from "@seatschart/vue";
|
|
108
|
+
const designer = useDesigner();
|
|
109
|
+
</script>
|
|
110
|
+
|
|
111
|
+
<template>
|
|
112
|
+
<Designer
|
|
113
|
+
ref="designer"
|
|
114
|
+
web-base="https://your-tenant.seatschart.com"
|
|
115
|
+
:token="designerEmbedToken"
|
|
116
|
+
:chart-id="chartId"
|
|
117
|
+
mode="safe"
|
|
118
|
+
canvas-color-scheme="dark"
|
|
119
|
+
@chart-updated="(id) => (saved = true)"
|
|
120
|
+
@exit-requested="router.back()"
|
|
121
|
+
/>
|
|
122
|
+
<button type="button" @click="designer?.publish('Summer layout')">Publish</button>
|
|
123
|
+
</template>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Without `chart-id` the designer creates a chart (`@chart-created`). The Exit button shows only with an
|
|
127
|
+
`@exit-requested` handler. `language`, `color-scheme`, `canvas-color-scheme`, `mode` and `safe-mode-options` change
|
|
128
|
+
live. The ref has `save()`, `publish(note?)`, `getState()`, `changeConfig()` and `chartId`.
|
|
129
|
+
|
|
130
|
+
## Documentation
|
|
131
|
+
|
|
132
|
+
- [Embed guide](https://github.com/seatschart/seatschart-prod/blob/main/docs/locales/en/README.md) and
|
|
133
|
+
[Quickstart](https://github.com/seatschart/seatschart-prod/blob/main/docs/locales/en/QUICKSTART.md)
|
|
134
|
+
- Every option, callback and command: `@seatschart/embed` (`SeatsChartConfig`, `SeatsChartEventManagerConfig`,
|
|
135
|
+
`SeatsChartDesignerConfig`).
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { type ShallowRef } from "vue";
|
|
2
|
+
import type { DesignerCallbacks, DesignerMode, SeatsChartDesigner, SeatsChartDesignerConfig } from "@seatschart/embed";
|
|
3
|
+
import { EmbedBinding, type DesignerCallbackKey, type DesignerCommands, type DesignerConfigKey } from "./host-core.js";
|
|
4
|
+
import { type CallbackEmits } from "./define.js";
|
|
5
|
+
/** `<Designer>` props: the `SeatsChartDesigner` config (seats.io `SeatingChartDesigner` names) without the container. */
|
|
6
|
+
export type DesignerProps = {
|
|
7
|
+
[K in DesignerConfigKey]?: SeatsChartDesignerConfig[K];
|
|
8
|
+
} & {
|
|
9
|
+
/** seats.io `onExitRequested` (`@exit-requested`): the Exit button shows only when a handler is set. */
|
|
10
|
+
onExitRequested?: () => void;
|
|
11
|
+
};
|
|
12
|
+
type DesignerEventKey = Exclude<DesignerCallbackKey, "onExitRequested">;
|
|
13
|
+
/** Every designer callback as an event: `onChartUpdated` → `@chart-updated` (same arguments). */
|
|
14
|
+
export type DesignerEmits = CallbackEmits<DesignerCallbacks, DesignerEventKey>;
|
|
15
|
+
/** Template ref API: every `SeatsChartDesigner` command (each waits for the designer to render). */
|
|
16
|
+
export type DesignerHandle = DesignerCommands & {
|
|
17
|
+
/** The underlying `SeatsChartDesigner` (null before mount / after unmount). */
|
|
18
|
+
readonly designer: SeatsChartDesigner | null;
|
|
19
|
+
/** The chart being edited (the created one when no `chartId` was given; null until known). */
|
|
20
|
+
readonly chartId: string | null;
|
|
21
|
+
readonly mode: DesignerMode | null;
|
|
22
|
+
getIframe: () => HTMLIFrameElement | null;
|
|
23
|
+
/** Re-create the iframe with the current props (keeps the chart created inside the designer). */
|
|
24
|
+
rerender: () => void;
|
|
25
|
+
};
|
|
26
|
+
export declare function createDesignerHandle(binding: EmbedBinding<SeatsChartDesigner>): DesignerHandle;
|
|
27
|
+
/**
|
|
28
|
+
* The embedded SeatsChart map designer. Without `chartId` it creates a chart (`@chart-created`). `language`,
|
|
29
|
+
* `colorScheme`, `canvasColorScheme`, `mode` and `safeModeOptions` are applied live with `changeConfig`; other changes
|
|
30
|
+
* re-render the iframe. `token` is a short-lived designer embed token from your backend — never a secret key.
|
|
31
|
+
*/
|
|
32
|
+
export declare const Designer: import("vue").DefineSetupFnComponent<DesignerProps, DesignerEmits, {}, {
|
|
33
|
+
canvasColorScheme?: "auto" | "dark" | "light" | undefined;
|
|
34
|
+
chartId?: string | undefined;
|
|
35
|
+
chartKey?: string | undefined;
|
|
36
|
+
className?: string | undefined;
|
|
37
|
+
colorScheme?: "auto" | "dark" | "light" | undefined;
|
|
38
|
+
features?: import("@seatschart/embed").DesignerFeatureGates | undefined;
|
|
39
|
+
height?: string | number | undefined;
|
|
40
|
+
language?: "ar" | "az" | "bn" | "de" | "en" | "es" | "fa" | "fr" | "gu" | "hi" | "id" | "it" | "ja" | "kk" | "kn" | "ko" | "ml" | "mr" | "ms" | "nl" | "pl" | "ps" | "pt" | "ru" | "ta" | "te" | "th" | "tr" | "uk" | "ur" | "vi" | "zh" | undefined;
|
|
41
|
+
mode?: "normal" | "readOnly" | "safe" | undefined;
|
|
42
|
+
openDraftDrawing?: boolean | undefined;
|
|
43
|
+
openLatestDrawing?: boolean | undefined;
|
|
44
|
+
parentOrigin?: string | undefined;
|
|
45
|
+
safeModeOptions?: import("@seatschart/embed").DesignerSafeModeOptions | undefined;
|
|
46
|
+
timeoutMs?: number | undefined;
|
|
47
|
+
title?: string | undefined;
|
|
48
|
+
token?: string | undefined;
|
|
49
|
+
webBase?: string | undefined;
|
|
50
|
+
} & {
|
|
51
|
+
/** seats.io `onExitRequested` (`@exit-requested`): the Exit button shows only when a handler is set. */
|
|
52
|
+
onExitRequested?: () => void;
|
|
53
|
+
} & {
|
|
54
|
+
onActionRefused?: ((event: import("@seatschart/embed").DesignerActionRefused) => any) | undefined;
|
|
55
|
+
onChartCreated?: ((chartId: string, event: import("@seatschart/embed").DesignerChartCreated) => any) | undefined;
|
|
56
|
+
onChartPublished?: ((chartId: string, event: import("@seatschart/embed").DesignerChartPublished) => any) | undefined;
|
|
57
|
+
onChartUpdated?: ((chartId: string, event: import("@seatschart/embed").DesignerChartUpdated) => any) | undefined;
|
|
58
|
+
onDesignerRendered?: ((designer: SeatsChartDesigner, event: import("@seatschart/embed").DesignerRendered) => any) | undefined;
|
|
59
|
+
onDesignerRenderingFailed?: ((designer: SeatsChartDesigner, event: import("@seatschart/embed").DesignerRenderingFailed) => any) | undefined;
|
|
60
|
+
onError?: ((error: import("@seatschart/embed").DesignerErrorInfo) => any) | undefined;
|
|
61
|
+
}, import("vue").PublicProps>;
|
|
62
|
+
/** A typed template ref for `<Designer ref="designer">`. */
|
|
63
|
+
export declare function useDesigner(): ShallowRef<DesignerHandle | null>;
|
|
64
|
+
export {};
|
|
65
|
+
//# sourceMappingURL=Designer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Designer.d.ts","sourceRoot":"","sources":["../src/Designer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqE,KAAK,UAAU,EAAE,MAAM,KAAK,CAAC;AACzG,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AACvH,OAAO,EAKL,YAAY,EAEZ,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EAEvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAA2C,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAE1F,yHAAyH;AACzH,MAAM,MAAM,aAAa,GAAG;KAAG,CAAC,IAAI,iBAAiB,CAAC,CAAC,EAAE,wBAAwB,CAAC,CAAC,CAAC;CAAE,GAAG;IACvF,wGAAwG;IACxG,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;CAC9B,CAAC;AAEF,KAAK,gBAAgB,GAAG,OAAO,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,CAAC;AAExE,iGAAiG;AACjG,MAAM,MAAM,aAAa,GAAG,aAAa,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;AAE/E,oGAAoG;AACpG,MAAM,MAAM,cAAc,GAAG,gBAAgB,GAAG;IAC9C,+EAA+E;IAC/E,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC7C,8FAA8F;IAC9F,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,MAAM,iBAAiB,GAAG,IAAI,CAAC;IAC1C,iGAAiG;IACjG,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAIF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,CAAC,kBAAkB,CAAC,GAAG,cAAc,CAW9F;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;IAzCnB,wGAAwG;sBACtF,MAAM,IAAI;;;;;;;;;6BA8D7B,CAAC;AAEF,4DAA4D;AAC5D,wBAAgB,WAAW,IAAI,UAAU,CAAC,cAAc,GAAG,IAAI,CAAC,CAE/D"}
|
package/dist/Designer.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { defineComponent, h, onBeforeUnmount, onMounted, shallowRef, watch } from "vue";
|
|
2
|
+
import { DESIGNER_CALLBACKS, DESIGNER_COMMANDS, DESIGNER_KEYS, DESIGNER_KIND, EmbedBinding, delegateCommands, } from "./host-core.js";
|
|
3
|
+
import { emitForwarders, eventNames, pickOptions } from "./define.js";
|
|
4
|
+
const EVENT_CALLBACKS = DESIGNER_CALLBACKS.filter((key) => key !== "onExitRequested");
|
|
5
|
+
export function createDesignerHandle(binding) {
|
|
6
|
+
const handle = {
|
|
7
|
+
...delegateCommands(() => binding.current, DESIGNER_COMMANDS, binding.label),
|
|
8
|
+
getIframe: () => binding.current?.getIframe() ?? null,
|
|
9
|
+
rerender: () => binding.rerender(),
|
|
10
|
+
};
|
|
11
|
+
return Object.defineProperties(handle, {
|
|
12
|
+
designer: { enumerable: true, get: () => binding.current },
|
|
13
|
+
chartId: { enumerable: true, get: () => binding.current?.chartId ?? null },
|
|
14
|
+
mode: { enumerable: true, get: () => binding.current?.mode ?? null },
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The embedded SeatsChart map designer. Without `chartId` it creates a chart (`@chart-created`). `language`,
|
|
19
|
+
* `colorScheme`, `canvasColorScheme`, `mode` and `safeModeOptions` are applied live with `changeConfig`; other changes
|
|
20
|
+
* re-render the iframe. `token` is a short-lived designer embed token from your backend — never a secret key.
|
|
21
|
+
*/
|
|
22
|
+
export const Designer = defineComponent((props, { emit, expose }) => {
|
|
23
|
+
const container = shallowRef(null);
|
|
24
|
+
const binding = new EmbedBinding(DESIGNER_KIND);
|
|
25
|
+
const forwarders = emitForwarders(EVENT_CALLBACKS, emit);
|
|
26
|
+
const exit = () => props.onExitRequested?.();
|
|
27
|
+
const config = () => ({
|
|
28
|
+
...pickOptions(props, DESIGNER_KEYS),
|
|
29
|
+
...forwarders,
|
|
30
|
+
// Its presence shows the Exit button (adding or removing the handler re-renders the designer).
|
|
31
|
+
...(props.onExitRequested !== undefined ? { onExitRequested: exit } : {}),
|
|
32
|
+
});
|
|
33
|
+
onMounted(() => {
|
|
34
|
+
if (container.value !== null)
|
|
35
|
+
binding.mount(container.value, config());
|
|
36
|
+
});
|
|
37
|
+
watch(config, (next) => binding.update(next), { deep: true });
|
|
38
|
+
onBeforeUnmount(() => binding.destroy());
|
|
39
|
+
expose(createDesignerHandle(binding));
|
|
40
|
+
return () => h("div", { ref: container, "data-seatschart-designer": "" });
|
|
41
|
+
}, { name: "Designer", props: [...DESIGNER_KEYS, "onExitRequested"], emits: eventNames(EVENT_CALLBACKS) });
|
|
42
|
+
/** A typed template ref for `<Designer ref="designer">`. */
|
|
43
|
+
export function useDesigner() {
|
|
44
|
+
return shallowRef(null);
|
|
45
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type ShallowRef } from "vue";
|
|
2
|
+
import type { EventManagerCallbacks, EventManagerMode, SeatsChartEventManager, SeatsChartEventManagerConfig } from "@seatschart/embed";
|
|
3
|
+
import { EmbedBinding, type EventManagerCallbackKey, type EventManagerCommands, type EventManagerConfigKey } from "./host-core.js";
|
|
4
|
+
import { type CallbackEmits } from "./define.js";
|
|
5
|
+
/** `<EventManager>` props: the `SeatsChartEventManager` config (seats.io `EventManager` names) without the container. */
|
|
6
|
+
export type EventManagerProps = {
|
|
7
|
+
[K in EventManagerConfigKey]?: SeatsChartEventManagerConfig[K];
|
|
8
|
+
};
|
|
9
|
+
/** Every manager callback as an event: `onSelectionChanged` → `@selection-changed` (same payload). */
|
|
10
|
+
export type EventManagerEmits = CallbackEmits<EventManagerCallbacks, EventManagerCallbackKey>;
|
|
11
|
+
/** Template ref API: every `SeatsChartEventManager` command (each waits for the manager to render). */
|
|
12
|
+
export type EventManagerHandle = EventManagerCommands & {
|
|
13
|
+
/** The underlying `SeatsChartEventManager` (null before mount / after unmount). */
|
|
14
|
+
readonly manager: SeatsChartEventManager | null;
|
|
15
|
+
/** Ids of the selected objects, synchronously. */
|
|
16
|
+
readonly selectedObjects: string[];
|
|
17
|
+
readonly mode: EventManagerMode | null;
|
|
18
|
+
getIframe: () => HTMLIFrameElement | null;
|
|
19
|
+
/** Re-create the iframe with the current props (the selection is cleared). */
|
|
20
|
+
rerender: () => void;
|
|
21
|
+
};
|
|
22
|
+
export declare function createEventManagerHandle(binding: EmbedBinding<SeatsChartEventManager>): EventManagerHandle;
|
|
23
|
+
/**
|
|
24
|
+
* The embedded SeatsChart Event Manager (back office). Selectability rules, `maxSelectedObjects`, `selectedObjects`,
|
|
25
|
+
* `order`, `filters`, `language` and `colorScheme` are applied live with `changeConfig`; other changes re-render the
|
|
26
|
+
* iframe. `token` is a short-lived manager embed token from your backend — never a secret key.
|
|
27
|
+
*/
|
|
28
|
+
export declare const EventManager: import("vue").DefineSetupFnComponent<EventManagerProps, EventManagerEmits, {}, EventManagerProps & {
|
|
29
|
+
onChartRendered?: ((event: import("@seatschart/embed").EventManagerRendered) => any) | undefined;
|
|
30
|
+
onChartRenderingFailed?: ((event: import("@seatschart/embed").EventManagerRenderingFailed) => any) | undefined;
|
|
31
|
+
onError?: ((error: import("@seatschart/embed").EventManagerErrorInfo) => any) | undefined;
|
|
32
|
+
onEventManagerRendered?: ((event: import("@seatschart/embed").EventManagerRendered) => any) | undefined;
|
|
33
|
+
onModeChanged?: ((mode: "createOrder" | "editOrder" | "filter" | "history" | "manageCategories" | "manageChannels" | "manageForSale" | "manageListings" | "manageObjectStatuses" | "manageTableBooking" | "salesRules" | "select" | "static") => any) | undefined;
|
|
34
|
+
onObjectDeselected?: ((object: import("@seatschart/embed").EventManagerObject) => any) | undefined;
|
|
35
|
+
onObjectSelected?: ((object: import("@seatschart/embed").EventManagerObject) => any) | undefined;
|
|
36
|
+
onOrderChanged?: ((changes: import("@seatschart/embed").OrderChange[]) => any) | undefined;
|
|
37
|
+
onSelectionChanged?: ((objects: import("@seatschart/embed").EventManagerObject[]) => any) | undefined;
|
|
38
|
+
onSelectionInvalid?: ((event: import("@seatschart/embed").EventManagerSelectionInvalid) => any) | undefined;
|
|
39
|
+
onSubmitFailed?: ((event: import("@seatschart/embed").EventManagerSubmitFailed) => any) | undefined;
|
|
40
|
+
onSubmitSucceeded?: ((event: import("@seatschart/embed").EventManagerSubmitSucceeded) => any) | undefined;
|
|
41
|
+
}, import("vue").PublicProps>;
|
|
42
|
+
/** A typed template ref for `<EventManager ref="manager">`. */
|
|
43
|
+
export declare function useEventManager(): ShallowRef<EventManagerHandle | null>;
|
|
44
|
+
//# sourceMappingURL=EventManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventManager.d.ts","sourceRoot":"","sources":["../src/EventManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqE,KAAK,UAAU,EAAE,MAAM,KAAK,CAAC;AACzG,OAAO,KAAK,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AACvI,OAAO,EAKL,YAAY,EAEZ,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC3B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAA2C,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAE1F,yHAAyH;AACzH,MAAM,MAAM,iBAAiB,GAAG;KAAG,CAAC,IAAI,qBAAqB,CAAC,CAAC,EAAE,4BAA4B,CAAC,CAAC,CAAC;CAAE,CAAC;AAEnG,sGAAsG;AACtG,MAAM,MAAM,iBAAiB,GAAG,aAAa,CAAC,qBAAqB,EAAE,uBAAuB,CAAC,CAAC;AAE9F,uGAAuG;AACvG,MAAM,MAAM,kBAAkB,GAAG,oBAAoB,GAAG;IACtD,mFAAmF;IACnF,QAAQ,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAChD,kDAAkD;IAClD,QAAQ,CAAC,eAAe,EAAE,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACvC,SAAS,EAAE,MAAM,iBAAiB,GAAG,IAAI,CAAC;IAC1C,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAEF,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,YAAY,CAAC,sBAAsB,CAAC,GAAG,kBAAkB,CAW1G;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;6BAgBxB,CAAC;AAEF,+DAA+D;AAC/D,wBAAgB,eAAe,IAAI,UAAU,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAEvE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { defineComponent, h, onBeforeUnmount, onMounted, shallowRef, watch } from "vue";
|
|
2
|
+
import { EVENT_MANAGER_CALLBACKS, EVENT_MANAGER_COMMANDS, EVENT_MANAGER_KEYS, EVENT_MANAGER_KIND, EmbedBinding, delegateCommands, } from "./host-core.js";
|
|
3
|
+
import { emitForwarders, eventNames, pickOptions } from "./define.js";
|
|
4
|
+
export function createEventManagerHandle(binding) {
|
|
5
|
+
const handle = {
|
|
6
|
+
...delegateCommands(() => binding.current, EVENT_MANAGER_COMMANDS, binding.label),
|
|
7
|
+
getIframe: () => binding.current?.getIframe() ?? null,
|
|
8
|
+
rerender: () => binding.rerender(),
|
|
9
|
+
};
|
|
10
|
+
return Object.defineProperties(handle, {
|
|
11
|
+
manager: { enumerable: true, get: () => binding.current },
|
|
12
|
+
selectedObjects: { enumerable: true, get: () => binding.current?.selectedObjects ?? [] },
|
|
13
|
+
mode: { enumerable: true, get: () => binding.current?.mode ?? null },
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The embedded SeatsChart Event Manager (back office). Selectability rules, `maxSelectedObjects`, `selectedObjects`,
|
|
18
|
+
* `order`, `filters`, `language` and `colorScheme` are applied live with `changeConfig`; other changes re-render the
|
|
19
|
+
* iframe. `token` is a short-lived manager embed token from your backend — never a secret key.
|
|
20
|
+
*/
|
|
21
|
+
export const EventManager = defineComponent((props, { emit, expose }) => {
|
|
22
|
+
const container = shallowRef(null);
|
|
23
|
+
const binding = new EmbedBinding(EVENT_MANAGER_KIND);
|
|
24
|
+
const forwarders = emitForwarders(EVENT_MANAGER_CALLBACKS, emit);
|
|
25
|
+
const config = () => ({ ...pickOptions(props, EVENT_MANAGER_KEYS), ...forwarders });
|
|
26
|
+
onMounted(() => {
|
|
27
|
+
if (container.value !== null)
|
|
28
|
+
binding.mount(container.value, config());
|
|
29
|
+
});
|
|
30
|
+
watch(config, (next) => binding.update(next), { deep: true });
|
|
31
|
+
onBeforeUnmount(() => binding.destroy());
|
|
32
|
+
expose(createEventManagerHandle(binding));
|
|
33
|
+
return () => h("div", { ref: container, "data-seatschart-event-manager": "" });
|
|
34
|
+
}, { name: "EventManager", props: [...EVENT_MANAGER_KEYS], emits: eventNames(EVENT_MANAGER_CALLBACKS) });
|
|
35
|
+
/** A typed template ref for `<EventManager ref="manager">`. */
|
|
36
|
+
export function useEventManager() {
|
|
37
|
+
return shallowRef(null);
|
|
38
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { type ShallowRef } from "vue";
|
|
2
|
+
import { type SeatsChart, type SeatsChartConfig, type SeatsChartPromptCallbacks } from "@seatschart/embed";
|
|
3
|
+
import { EmbedBinding, type ChartCallbackKey, type ChartCommands, type ChartConfigKey } from "./host-core.js";
|
|
4
|
+
import { type CallbackEmits } from "./define.js";
|
|
5
|
+
/**
|
|
6
|
+
* `<SeatChart>` options: every `SeatsChart` option of `@seatschart/embed` (seats.io renderer names) except the
|
|
7
|
+
* container. The chart `style` option (font, corner radius, button shape) is `chartStyle`, so the `style` and `class`
|
|
8
|
+
* attributes keep styling the wrapper element.
|
|
9
|
+
*/
|
|
10
|
+
export type SeatChartOptions = {
|
|
11
|
+
[K in Exclude<ChartConfigKey, "style">]?: SeatsChartConfig[K];
|
|
12
|
+
} & {
|
|
13
|
+
/** The chart's `style` option (`{ font, cornerRadius, buttonShape }`), not CSS. */
|
|
14
|
+
chartStyle?: SeatsChartConfig["style"];
|
|
15
|
+
};
|
|
16
|
+
/** `<SeatChart>` props: the options plus the host-drawn prompts (`@places-prompt`, …), which switch the matching viewer prompt to the host page. */
|
|
17
|
+
export type SeatChartProps = SeatChartOptions & SeatsChartPromptCallbacks;
|
|
18
|
+
/** The chart callbacks (seats.io names) the events mirror. */
|
|
19
|
+
export type SeatChartCallbacks = Pick<SeatsChartConfig, ChartCallbackKey>;
|
|
20
|
+
/** Every chart callback as an event: `onObjectSelected` → `@object-selected` (same payload). */
|
|
21
|
+
export type SeatChartEmits = CallbackEmits<SeatChartCallbacks, ChartCallbackKey>;
|
|
22
|
+
/** Template ref API: every `SeatsChart` command (each waits for the chart to render) plus the live state. */
|
|
23
|
+
export type SeatChartHandle = ChartCommands & {
|
|
24
|
+
/** The underlying `SeatsChart` instance (null before mount / after unmount). */
|
|
25
|
+
readonly chart: SeatsChart | null;
|
|
26
|
+
/** Seats.io `selectedObjects`: ids of the selected objects, synchronously. */
|
|
27
|
+
readonly selectedObjects: string[];
|
|
28
|
+
/** Current hold token, synchronously (null before a session exists). */
|
|
29
|
+
readonly holdToken: string | null;
|
|
30
|
+
getIframe: () => HTMLIFrameElement | null;
|
|
31
|
+
/** Re-create the iframe with the current props; an active hold session continues. */
|
|
32
|
+
rerender: () => void;
|
|
33
|
+
};
|
|
34
|
+
export declare function createSeatChartHandle(binding: EmbedBinding<SeatsChart>): SeatChartHandle;
|
|
35
|
+
/**
|
|
36
|
+
* The SeatsChart buyer seat map (sandboxed viewer iframe). Props map to the `SeatsChart` loader options; changes to
|
|
37
|
+
* declarative options (colours, labels, caps, pricing, prompts, `settings3d`, …) are applied live with
|
|
38
|
+
* `changeConfig`, other changes re-render the iframe (the hold session continues). Every chart callback is an event.
|
|
39
|
+
* `token` is a short-lived buyer JWT from your backend — never an API key.
|
|
40
|
+
*/
|
|
41
|
+
export declare const SeatChart: import("vue").DefineSetupFnComponent<SeatChartProps, SeatChartEmits, {}, {
|
|
42
|
+
accessibilityFilter?: ("aisle" | "companion" | "hearing" | "hideLimitedLegroom" | "hideLimitedView" | "hideVertigo" | "liftUpArmrests" | "plusSize" | "semiAmbulatory" | "wheelchair")[] | undefined;
|
|
43
|
+
activeFloor?: string | undefined;
|
|
44
|
+
allowFullscreen?: boolean | undefined;
|
|
45
|
+
availableCategories?: string[] | undefined;
|
|
46
|
+
backgroundColor?: string | number | undefined;
|
|
47
|
+
canGoBack?: boolean | undefined;
|
|
48
|
+
channel?: string | undefined;
|
|
49
|
+
channelKey?: string | undefined;
|
|
50
|
+
channelKeys?: string[] | undefined;
|
|
51
|
+
className?: string | undefined;
|
|
52
|
+
currency?: string | undefined;
|
|
53
|
+
defaultRenderer?: "2d" | "3d" | undefined;
|
|
54
|
+
event?: string | undefined;
|
|
55
|
+
events?: string[] | undefined;
|
|
56
|
+
filterControls?: boolean | import("@seatschart/embed").FilterControlsConfig | undefined;
|
|
57
|
+
fitTo?: import("@seatschart/embed").ChartFitTo | undefined;
|
|
58
|
+
form?: string | HTMLFormElement | undefined;
|
|
59
|
+
fullScreenTarget?: import("@seatschart/embed").FullScreenTarget | undefined;
|
|
60
|
+
gestureHandling?: import("@seatschart/embed").GestureHandling | undefined;
|
|
61
|
+
height?: string | number | undefined;
|
|
62
|
+
hideSectionsNotForSale?: boolean | undefined;
|
|
63
|
+
holdToken?: string | undefined;
|
|
64
|
+
holdTokenInputName?: string | undefined;
|
|
65
|
+
isObjectVisible?: import("@seatschart/embed").ObjectOverrides<boolean> | undefined;
|
|
66
|
+
language?: "ar" | "az" | "bn" | "de" | "en" | "es" | "fa" | "fr" | "gu" | "hi" | "id" | "it" | "ja" | "kk" | "kn" | "ko" | "ml" | "mr" | "ms" | "nl" | "pl" | "ps" | "pt" | "ru" | "ta" | "te" | "th" | "tr" | "uk" | "ur" | "vi" | "zh" | undefined;
|
|
67
|
+
legend?: import("@seatschart/embed").LegendConfig | undefined;
|
|
68
|
+
loading?: import("@seatschart/embed").ChartLoadingConfig | undefined;
|
|
69
|
+
lockActiveFloor?: boolean | undefined;
|
|
70
|
+
maxSelectedObjects?: number | import("@seatschart/embed").MaxSelectedObjectsConfig | undefined;
|
|
71
|
+
messages?: Record<string, string> | undefined;
|
|
72
|
+
minimumSelectedPlaces?: number | undefined;
|
|
73
|
+
mode?: import("@seatschart/embed").ChartMode | undefined;
|
|
74
|
+
multiSelectEnabled?: boolean | undefined;
|
|
75
|
+
numberOfPlacesToSelect?: number | undefined;
|
|
76
|
+
objectColor?: import("@seatschart/embed").ObjectOverrides<string> | undefined;
|
|
77
|
+
objectIcon?: import("@seatschart/embed").ObjectOverrides<"ban" | "bolt" | "check" | "eye" | "heart" | "info" | "star" | "tag"> | undefined;
|
|
78
|
+
objectLabel?: import("@seatschart/embed").ObjectOverrides<string> | undefined;
|
|
79
|
+
objectPopover?: import("@seatschart/embed").ObjectPopoverConfig | undefined;
|
|
80
|
+
objectWithoutCategorySelectable?: boolean | undefined;
|
|
81
|
+
objectWithoutPricingSelectable?: boolean | undefined;
|
|
82
|
+
parentOrigin?: string | undefined;
|
|
83
|
+
partySize?: number | import("@seatschart/embed").PartySizeConfig | undefined;
|
|
84
|
+
priceFormatter?: import("@seatschart/embed").PriceFormatterSpec | undefined;
|
|
85
|
+
pricing?: unknown;
|
|
86
|
+
prompts?: import("@seatschart/embed").ChartPromptsConfig | undefined;
|
|
87
|
+
publicKey?: string | undefined;
|
|
88
|
+
resaleListings?: import("@seatschart/embed").ResaleListingsConfig | undefined;
|
|
89
|
+
season?: string | undefined;
|
|
90
|
+
sectionColor?: import("@seatschart/embed").ObjectOverrides<string> | undefined;
|
|
91
|
+
selectableObjects?: string[] | undefined;
|
|
92
|
+
selectedObjects?: import("@seatschart/embed").ChartObjectRefInput[] | undefined;
|
|
93
|
+
selectedObjectsInputName?: string | undefined;
|
|
94
|
+
selectionModes?: import("@seatschart/embed").BuyerSelectionMode[] | undefined;
|
|
95
|
+
selectionValidators?: import("@seatschart/embed").SelectionValidatorsConfig | undefined;
|
|
96
|
+
session?: import("@seatschart/embed").SessionMode | undefined;
|
|
97
|
+
sessionMode?: import("@seatschart/embed").SessionMode | undefined;
|
|
98
|
+
settings3d?: import("@seatschart/embed").Settings3dConfig | undefined;
|
|
99
|
+
showFilterControls?: boolean | undefined;
|
|
100
|
+
showFloorElevator?: boolean | undefined;
|
|
101
|
+
showFullScreenButton?: boolean | undefined;
|
|
102
|
+
showLegend?: boolean | undefined;
|
|
103
|
+
showMinimap?: boolean | undefined;
|
|
104
|
+
showObjectPopover?: boolean | undefined;
|
|
105
|
+
showSeatLabels?: boolean | undefined;
|
|
106
|
+
showSectionContents?: import("@seatschart/embed").ShowSectionContents | undefined;
|
|
107
|
+
showSectionPricingOverlay?: boolean | undefined;
|
|
108
|
+
showSurroundings?: boolean | undefined;
|
|
109
|
+
showZoomOutButton?: boolean | undefined;
|
|
110
|
+
statusPalette?: "accessible" | "standard" | undefined;
|
|
111
|
+
theme?: "auto" | "dark" | "light" | undefined;
|
|
112
|
+
timeoutMs?: number | undefined;
|
|
113
|
+
title?: string | undefined;
|
|
114
|
+
token?: string | undefined;
|
|
115
|
+
tooltip?: import("@seatschart/embed").TooltipConfig | undefined;
|
|
116
|
+
transparent?: boolean | undefined;
|
|
117
|
+
unavailableCategories?: string[] | undefined;
|
|
118
|
+
webBase?: string | undefined;
|
|
119
|
+
workspaceKey?: string | undefined;
|
|
120
|
+
} & {
|
|
121
|
+
/** The chart's `style` option (`{ font, cornerRadius, buttonShape }`), not CSS. */
|
|
122
|
+
chartStyle?: SeatsChartConfig["style"];
|
|
123
|
+
} & SeatsChartPromptCallbacks & {
|
|
124
|
+
onAccessibilityFilterChanged?: ((event: import("@seatschart/embed").ChartAccessibilityFilterChanged) => any) | undefined;
|
|
125
|
+
onBestAvailableFailed?: ((event: import("@seatschart/embed").ChartBestAvailableFailed) => any) | undefined;
|
|
126
|
+
onBestAvailableSelected?: ((event: import("@seatschart/embed").ChartBestAvailableSelected) => any) | undefined;
|
|
127
|
+
onBestAvailableSelectionFailed?: ((event: import("@seatschart/embed").ChartBestAvailableFailed) => any) | undefined;
|
|
128
|
+
onChartRendered?: ((event: import("@seatschart/embed").ChartRendered) => any) | undefined;
|
|
129
|
+
onChartRenderingFailed?: ((event: import("@seatschart/embed").ChartRenderingFailed) => any) | undefined;
|
|
130
|
+
onChartRerenderingStarted?: ((event: import("@seatschart/embed").ChartRerendering) => any) | undefined;
|
|
131
|
+
onFilteredCategoriesChanged?: ((event: import("@seatschart/embed").ChartFilteredCategoriesChanged) => any) | undefined;
|
|
132
|
+
onFiltersChanged?: ((event: import("@seatschart/embed").ChartFiltersChanged) => any) | undefined;
|
|
133
|
+
onFloorChanged?: ((event: import("@seatschart/embed").ChartFloorChanged) => any) | undefined;
|
|
134
|
+
onFullScreenClosed?: ((event: import("@seatschart/embed").ChartFullScreenClosed) => any) | undefined;
|
|
135
|
+
onFullScreenOpened?: ((event: import("@seatschart/embed").ChartFullScreenOpened) => any) | undefined;
|
|
136
|
+
onFullScreenRequest?: ((event: import("@seatschart/embed").ChartFullScreenRequest) => any) | undefined;
|
|
137
|
+
onHoldCallsComplete?: ((event: import("@seatschart/embed").ChartHoldSettled) => any) | undefined;
|
|
138
|
+
onHoldCallsInProgress?: ((event: import("@seatschart/embed").ChartHoldPending) => any) | undefined;
|
|
139
|
+
onHoldConfirmed?: ((event: import("@seatschart/embed").ChartHoldConfirmed) => any) | undefined;
|
|
140
|
+
onHoldCreated?: ((payload: import("@seatschart/embed").EmbedReservationPayload) => any) | undefined;
|
|
141
|
+
onHoldFailed?: ((event: import("@seatschart/embed").ChartHoldFailed) => any) | undefined;
|
|
142
|
+
onHoldSucceeded?: ((event: import("@seatschart/embed").ChartHoldSucceeded) => any) | undefined;
|
|
143
|
+
onHoldTokenExpired?: ((event: import("@seatschart/embed").ChartSessionExpired) => any) | undefined;
|
|
144
|
+
onObjectClicked?: ((event: import("@seatschart/embed").ChartObjectClicked) => any) | undefined;
|
|
145
|
+
onObjectDeselected?: ((event: import("@seatschart/embed").ChartObjectDeselected) => any) | undefined;
|
|
146
|
+
onObjectHovered?: ((event: import("@seatschart/embed").ChartObjectHovered) => any) | undefined;
|
|
147
|
+
onObjectMouseOut?: ((event: import("@seatschart/embed").ChartObjectUnhovered) => any) | undefined;
|
|
148
|
+
onObjectMouseOver?: ((event: import("@seatschart/embed").ChartObjectHovered) => any) | undefined;
|
|
149
|
+
onObjectSelected?: ((event: import("@seatschart/embed").ChartObjectSelected) => any) | undefined;
|
|
150
|
+
onObjectStatusChanged?: ((event: import("@seatschart/embed").ChartObjectStatusChanged) => any) | undefined;
|
|
151
|
+
onObjectUnhovered?: ((event: import("@seatschart/embed").ChartObjectUnhovered) => any) | undefined;
|
|
152
|
+
onPromptRequest?: ((event: import("@seatschart/embed").ChartPromptRequest) => any) | undefined;
|
|
153
|
+
onReleaseHoldFailed?: ((event: import("@seatschart/embed").ChartReleaseFailed) => any) | undefined;
|
|
154
|
+
onReleaseHoldSucceeded?: ((event: import("@seatschart/embed").ChartReleaseSucceeded) => any) | undefined;
|
|
155
|
+
onSelectedObjectBooked?: ((event: import("@seatschart/embed").ChartHoldConfirmed) => any) | undefined;
|
|
156
|
+
onSelectedObjectUnavailable?: ((event: import("@seatschart/embed").ChartSelectionLost) => any) | undefined;
|
|
157
|
+
onSelectionInvalid?: ((event: import("@seatschart/embed").ChartSelectionInvalid) => any) | undefined;
|
|
158
|
+
onSelectionValid?: ((event: import("@seatschart/embed").ChartSelectionValid) => any) | undefined;
|
|
159
|
+
onSessionHold?: ((event: import("@seatschart/embed").ChartSessionHold) => any) | undefined;
|
|
160
|
+
onSessionInitialized?: ((event: import("@seatschart/embed").ChartSessionInitialized) => any) | undefined;
|
|
161
|
+
}, import("vue").PublicProps>;
|
|
162
|
+
/** A typed template ref for `<SeatChart ref="chart">` (`const chart = useSeatChart()` in `<script setup>`). */
|
|
163
|
+
export declare function useSeatChart(): ShallowRef<SeatChartHandle | null>;
|
|
164
|
+
//# sourceMappingURL=SeatChart.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SeatChart.d.ts","sourceRoot":"","sources":["../src/SeatChart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqE,KAAK,UAAU,EAAE,MAAM,KAAK,CAAC;AACzG,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,EAC/B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAKL,YAAY,EAGZ,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,cAAc,EAEpB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAA2C,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAE1F;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG;KAAG,CAAC,IAAI,OAAO,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC;CAAE,GAAG;IACjG,mFAAmF;IACnF,UAAU,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;CACxC,CAAC;AAEF,oJAAoJ;AACpJ,MAAM,MAAM,cAAc,GAAG,gBAAgB,GAAG,yBAAyB,CAAC;AAE1E,8DAA8D;AAC9D,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;AAE1E,gGAAgG;AAChG,MAAM,MAAM,cAAc,GAAG,aAAa,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC;AAEjF,6GAA6G;AAC7G,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG;IAC5C,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IAClC,8EAA8E;IAC9E,QAAQ,CAAC,eAAe,EAAE,MAAM,EAAE,CAAC;IACnC,wEAAwE;IACxE,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,SAAS,EAAE,MAAM,iBAAiB,GAAG,IAAI,CAAC;IAC1C,qFAAqF;IACrF,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAIF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,CAAC,UAAU,CAAC,GAAG,eAAe,CAWxF;AAED;;;;;GAKG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA/CpB,mFAAmF;iBACtE,gBAAgB,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BAmFvC,CAAC;AAEF,+GAA+G;AAC/G,wBAAgB,YAAY,IAAI,UAAU,CAAC,eAAe,GAAG,IAAI,CAAC,CAEjE"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { defineComponent, h, onBeforeUnmount, onMounted, shallowRef, watch } from "vue";
|
|
2
|
+
import { promptsForCallbacks, } from "@seatschart/embed";
|
|
3
|
+
import { CHART_CALLBACKS, CHART_COMMANDS, CHART_CONFIG_KEYS, CHART_KIND, EmbedBinding, PROMPT_CALLBACKS, delegateCommands, } from "./host-core.js";
|
|
4
|
+
import { emitForwarders, eventNames, pickOptions } from "./define.js";
|
|
5
|
+
const OPTION_KEYS = CHART_CONFIG_KEYS.map((key) => (key === "style" ? "chartStyle" : key));
|
|
6
|
+
export function createSeatChartHandle(binding) {
|
|
7
|
+
const handle = {
|
|
8
|
+
...delegateCommands(() => binding.current, CHART_COMMANDS, binding.label),
|
|
9
|
+
getIframe: () => binding.current?.getIframe() ?? null,
|
|
10
|
+
rerender: () => binding.rerender(),
|
|
11
|
+
};
|
|
12
|
+
return Object.defineProperties(handle, {
|
|
13
|
+
chart: { enumerable: true, get: () => binding.current },
|
|
14
|
+
selectedObjects: { enumerable: true, get: () => binding.current?.selectedObjects ?? [] },
|
|
15
|
+
holdToken: { enumerable: true, get: () => binding.current?.holdToken ?? null },
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The SeatsChart buyer seat map (sandboxed viewer iframe). Props map to the `SeatsChart` loader options; changes to
|
|
20
|
+
* declarative options (colours, labels, caps, pricing, prompts, `settings3d`, …) are applied live with
|
|
21
|
+
* `changeConfig`, other changes re-render the iframe (the hold session continues). Every chart callback is an event.
|
|
22
|
+
* `token` is a short-lived buyer JWT from your backend — never an API key.
|
|
23
|
+
*/
|
|
24
|
+
export const SeatChart = defineComponent((props, { emit, expose }) => {
|
|
25
|
+
const container = shallowRef(null);
|
|
26
|
+
const binding = new EmbedBinding(CHART_KIND);
|
|
27
|
+
const forwarders = emitForwarders(CHART_CALLBACKS, emit);
|
|
28
|
+
// A set prompt handler switches its viewer prompt to the host (adding / removing one re-renders the chart). The
|
|
29
|
+
// forwarder reads the latest handler when a prompt arrives.
|
|
30
|
+
const promptForwarders = {};
|
|
31
|
+
for (const key of PROMPT_CALLBACKS) {
|
|
32
|
+
promptForwarders[key] = (params, confirm, cancel) => {
|
|
33
|
+
const handler = props[key];
|
|
34
|
+
if (handler === undefined)
|
|
35
|
+
cancel();
|
|
36
|
+
else
|
|
37
|
+
handler(params, confirm, cancel);
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const config = () => {
|
|
41
|
+
const options = pickOptions(props, OPTION_KEYS);
|
|
42
|
+
if (options.chartStyle !== undefined)
|
|
43
|
+
options.style = options.chartStyle;
|
|
44
|
+
delete options.chartStyle;
|
|
45
|
+
// Same merge as the loader, so a live `prompts` patch keeps the prompts the handlers switched on.
|
|
46
|
+
const hostPrompts = { ...(props.prompts ?? {}), ...promptsForCallbacks(props) };
|
|
47
|
+
if (Object.keys(hostPrompts).length > 0)
|
|
48
|
+
options.prompts = hostPrompts;
|
|
49
|
+
else
|
|
50
|
+
delete options.prompts;
|
|
51
|
+
for (const key of PROMPT_CALLBACKS)
|
|
52
|
+
if (props[key] !== undefined)
|
|
53
|
+
options[key] = promptForwarders[key];
|
|
54
|
+
return { ...options, ...forwarders };
|
|
55
|
+
};
|
|
56
|
+
onMounted(() => {
|
|
57
|
+
if (container.value !== null)
|
|
58
|
+
binding.mount(container.value, config());
|
|
59
|
+
});
|
|
60
|
+
watch(config, (next) => binding.update(next), { deep: true });
|
|
61
|
+
onBeforeUnmount(() => binding.destroy());
|
|
62
|
+
expose(createSeatChartHandle(binding));
|
|
63
|
+
return () => h("div", { ref: container, "data-seatschart-chart": "" });
|
|
64
|
+
}, { name: "SeatChart", props: [...OPTION_KEYS, ...PROMPT_CALLBACKS], emits: eventNames(CHART_CALLBACKS) });
|
|
65
|
+
/** A typed template ref for `<SeatChart ref="chart">` (`const chart = useSeatChart()` in `<script setup>`). */
|
|
66
|
+
export function useSeatChart() {
|
|
67
|
+
return shallowRef(null);
|
|
68
|
+
}
|
package/dist/define.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type EmbedConfig, type EventNameOf } from "./host-core.js";
|
|
2
|
+
type Args<F> = F extends (...args: infer A) => unknown ? A : never;
|
|
3
|
+
/** `{ onObjectSelected?: (e: E) => void }` → `{ objectSelected: (e: E) => true }` (typed Vue emits). */
|
|
4
|
+
export type CallbackEmits<C, K extends keyof C & string> = {
|
|
5
|
+
[N in EventNameOf<K>]: (...args: Args<NonNullable<C[`on${Capitalize<N>}` & keyof C]>>) => true;
|
|
6
|
+
};
|
|
7
|
+
/** Vue event names of these callbacks (`onObjectSelected` → `objectSelected`). */
|
|
8
|
+
export declare function eventNames(callbacks: readonly string[]): string[];
|
|
9
|
+
type Emit = (event: string, ...args: unknown[]) => void;
|
|
10
|
+
/** One stable function per callback that re-emits its arguments as the matching component event. */
|
|
11
|
+
export declare function emitForwarders(callbacks: readonly string[], emit: Emit): EmbedConfig;
|
|
12
|
+
/** Copy the option props that are set. */
|
|
13
|
+
export declare function pickOptions(props: Readonly<Record<string, unknown>>, keys: readonly string[]): EmbedConfig;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=define.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE/E,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,KAAK,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC;AAEnE,wGAAwG;AACxG,MAAM,MAAM,aAAa,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,IAAI;KACxD,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI;CAC/F,CAAC;AAEF,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAEjE;AAED,KAAK,IAAI,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;AAExD,oGAAoG;AACpG,wBAAgB,cAAc,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,GAAG,WAAW,CAOpF;AAED,0CAA0C;AAC1C,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,CAO1G"}
|
package/dist/define.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { eventName } from "./host-core.js";
|
|
2
|
+
/** Vue event names of these callbacks (`onObjectSelected` → `objectSelected`). */
|
|
3
|
+
export function eventNames(callbacks) {
|
|
4
|
+
return callbacks.map((key) => eventName(key));
|
|
5
|
+
}
|
|
6
|
+
/** One stable function per callback that re-emits its arguments as the matching component event. */
|
|
7
|
+
export function emitForwarders(callbacks, emit) {
|
|
8
|
+
const out = {};
|
|
9
|
+
for (const key of callbacks) {
|
|
10
|
+
const name = eventName(key);
|
|
11
|
+
out[key] = (...args) => emit(name, ...args);
|
|
12
|
+
}
|
|
13
|
+
return out;
|
|
14
|
+
}
|
|
15
|
+
/** Copy the option props that are set. */
|
|
16
|
+
export function pickOptions(props, keys) {
|
|
17
|
+
const out = {};
|
|
18
|
+
for (const key of keys) {
|
|
19
|
+
const value = props[key];
|
|
20
|
+
if (value !== undefined)
|
|
21
|
+
out[key] = value;
|
|
22
|
+
}
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-agnostic glue between a component and one `@seatschart/embed` host instance (`SeatsChart`,
|
|
3
|
+
* `SeatsChartEventManager` or `SeatsChartDesigner`). This file is identical in `@seatschart/vue` and
|
|
4
|
+
* `@seatschart/angular` (a unit test keeps the two copies in step): the wrappers only map framework props, events
|
|
5
|
+
* and lifecycle onto it, every embed behaviour (iframe, origin checks, commands, sessions) stays in the embed.
|
|
6
|
+
*
|
|
7
|
+
* Prop updates are compared by value with what the instance last received, then applied the cheapest correct way:
|
|
8
|
+
* iframe attributes in place, live keys through `changeConfig` (no reload), other keys through `rerender(config)`
|
|
9
|
+
* (the hold session / the created chart is kept), mount-only keys by re-creating the instance.
|
|
10
|
+
*/
|
|
11
|
+
import { DESIGNER_CALLBACKS, EVENT_MANAGER_CALLBACKS, SeatsChart, SeatsChartDesigner, SeatsChartEventManager, type SeatsChartConfig, type SeatsChartDesignerConfig, type SeatsChartEventManagerConfig } from "@seatschart/embed";
|
|
12
|
+
/** Every buyer chart option a component accepts as a prop / input (the host config keys first). */
|
|
13
|
+
export declare const CHART_CONFIG_KEYS: readonly ["objectColor", "objectLabel", "tooltip", "priceFormatter", "numberOfPlacesToSelect", "maxSelectedObjects", "showSectionContents", "showMinimap", "showSurroundings", "sessionMode", "selectionValidators", "accessibilityFilter", "mode", "prompts", "objectWithoutPricingSelectable", "fitTo", "loading", "messages", "selectedObjects", "gestureHandling", "selectionModes", "showSeatLabels", "minimumSelectedPlaces", "sectionColor", "objectIcon", "isObjectVisible", "hideSectionsNotForSale", "selectableObjects", "objectWithoutCategorySelectable", "showSectionPricingOverlay", "showObjectPopover", "showFilterControls", "showLegend", "showZoomOutButton", "showFullScreenButton", "fullScreenTarget", "canGoBack", "resaleListings", "partySize", "style", "objectPopover", "legend", "filterControls", "activeFloor", "lockActiveFloor", "showFloorElevator", "settings3d", "webBase", "event", "events", "publicKey", "workspaceKey", "token", "parentOrigin", "channel", "channelKey", "channelKeys", "session", "season", "language", "multiSelectEnabled", "holdToken", "availableCategories", "unavailableCategories", "currency", "theme", "statusPalette", "transparent", "backgroundColor", "pricing", "defaultRenderer", "height", "title", "className", "allowFullscreen", "timeoutMs", "holdTokenInputName", "selectedObjectsInputName", "form"];
|
|
14
|
+
export type ChartConfigKey = (typeof CHART_CONFIG_KEYS)[number];
|
|
15
|
+
/** Chart callbacks (seats.io names) forwarded as component events. */
|
|
16
|
+
export declare const CHART_CALLBACKS: readonly ["onObjectSelected", "onObjectDeselected", "onSessionHold", "onHoldSucceeded", "onHoldCallsInProgress", "onHoldCallsComplete", "onHoldConfirmed", "onReleaseHoldSucceeded", "onReleaseHoldFailed", "onSelectedObjectUnavailable", "onChartRerenderingStarted", "onPromptRequest", "onHoldTokenExpired", "onChartRendered", "onChartRenderingFailed", "onObjectClicked", "onObjectHovered", "onObjectUnhovered", "onHoldFailed", "onSelectionInvalid", "onSelectionValid", "onObjectStatusChanged", "onBestAvailableSelected", "onBestAvailableFailed", "onFilteredCategoriesChanged", "onAccessibilityFilterChanged", "onFiltersChanged", "onSessionInitialized", "onFloorChanged", "onFullScreenOpened", "onFullScreenClosed", "onFullScreenRequest", "onObjectMouseOver", "onObjectMouseOut", "onBestAvailableSelectionFailed", "onSelectedObjectBooked", "onHoldCreated"];
|
|
17
|
+
export type ChartCallbackKey = (typeof CHART_CALLBACKS)[number];
|
|
18
|
+
/** Host-drawn prompts: registering one switches the matching viewer prompt to the host. */
|
|
19
|
+
export declare const PROMPT_CALLBACKS: readonly ["onPlacesPrompt", "onTicketTypePrompt", "onPlacesWithTicketTypesPrompt"];
|
|
20
|
+
export type PromptCallbackKey = (typeof PROMPT_CALLBACKS)[number];
|
|
21
|
+
export declare const EVENT_MANAGER_KEYS: readonly ["isObjectSelectable", "unavailableObjectsSelectable", "selectableObjects", "selectedObjects", "maxSelectedObjects", "order", "filters", "webBase", "event", "eventId", "token", "mode", "language", "colorScheme", "parentOrigin", "height", "title", "className", "timeoutMs"];
|
|
22
|
+
export type EventManagerConfigKey = (typeof EVENT_MANAGER_KEYS)[number];
|
|
23
|
+
export { EVENT_MANAGER_CALLBACKS };
|
|
24
|
+
export type EventManagerCallbackKey = (typeof EVENT_MANAGER_CALLBACKS)[number];
|
|
25
|
+
export declare const DESIGNER_KEYS: readonly ["webBase", "chartId", "chartKey", "token", "mode", "safeModeOptions", "features", "language", "colorScheme", "canvasColorScheme", "openDraftDrawing", "openLatestDrawing", "parentOrigin", "height", "title", "className", "timeoutMs"];
|
|
26
|
+
export type DesignerConfigKey = (typeof DESIGNER_KEYS)[number];
|
|
27
|
+
export { DESIGNER_CALLBACKS };
|
|
28
|
+
export type DesignerCallbackKey = (typeof DESIGNER_CALLBACKS)[number];
|
|
29
|
+
type Assert<T extends true> = T;
|
|
30
|
+
type Covers<All, Listed> = [Exclude<All, Listed>] extends [never] ? true : false;
|
|
31
|
+
/** Compile-time guard: a new embed option or callback must be mapped by the wrappers. */
|
|
32
|
+
export type ConfigKeysCovered = [
|
|
33
|
+
Assert<Covers<keyof SeatsChartConfig, ChartConfigKey | ChartCallbackKey | PromptCallbackKey | "divId" | "container">>,
|
|
34
|
+
Assert<Covers<keyof SeatsChartEventManagerConfig, EventManagerConfigKey | EventManagerCallbackKey | "divId" | "container">>,
|
|
35
|
+
Assert<Covers<keyof SeatsChartDesignerConfig, DesignerConfigKey | DesignerCallbackKey | "divId" | "container">>
|
|
36
|
+
];
|
|
37
|
+
/** `"onObjectSelected"` → `"objectSelected"` (Vue event / Angular output name). */
|
|
38
|
+
export type EventNameOf<K> = K extends `on${infer N}` ? Uncapitalize<N> : never;
|
|
39
|
+
/** `onObjectSelected` → `objectSelected`. */
|
|
40
|
+
export declare function eventName<K extends string>(callback: K): EventNameOf<K>;
|
|
41
|
+
type PromiseMethods<T> = {
|
|
42
|
+
[K in keyof T]-?: T[K] extends (...args: never[]) => Promise<unknown> ? K : never;
|
|
43
|
+
}[keyof T];
|
|
44
|
+
/** Every promise command of `SeatsChart` (each waits for the chart to render; rejects with `ChartCommandError`). */
|
|
45
|
+
export declare const CHART_COMMANDS: readonly ["whenReady", "request", "selectObjects", "deselectObjects", "clearSelection", "listSelectedObjects", "selectBestAvailable", "findObject", "listCategories", "setFilteredCategories", "clearFilteredCategories", "setFilters", "clearFilters", "highlightObjects", "clearHighlights", "zoomToObjects", "zoomToSelectedObjects", "zoomToSection", "zoomToFilteredCategories", "resetView", "goToFloor", "listFloors", "goToAllFloorsView", "getReportBySelectability", "getReportBySelectabilityGroupedBy", "getHoldToken", "startNewSession", "releaseHoldToken", "isObjectInChannel", "showViewFromSeat", "trySelectObjects", "doSelectObjects", "selectCategories", "deselectCategories", "listZones", "setSpotlight", "setSpotlightObjects", "setSpotlightOnSelection", "clearSpotlight", "clearSpotlightObjects", "pulse", "unpulse", "resolvePrompt", "exportImage", "setPricing", "changeConfig"];
|
|
46
|
+
export type ChartCommands = Pick<SeatsChart, (typeof CHART_COMMANDS)[number]>;
|
|
47
|
+
/** Every promise command of `SeatsChartEventManager` (seats.io `EventManager` methods). */
|
|
48
|
+
export declare const EVENT_MANAGER_COMMANDS: readonly ["whenReady", "request", "listSelectedObjects", "selectObjects", "doSelectObjects", "trySelectObjects", "deselectObjects", "clearSelection", "setHighlightedObjects", "clearHighlightedObjects", "listOrderChanges", "zoomToObjects", "zoomToSelectedObjects", "changeConfig"];
|
|
49
|
+
export type EventManagerCommands = Pick<SeatsChartEventManager, (typeof EVENT_MANAGER_COMMANDS)[number]>;
|
|
50
|
+
/** Every promise command of `SeatsChartDesigner`. */
|
|
51
|
+
export declare const DESIGNER_COMMANDS: readonly ["whenReady", "request", "save", "publish", "getState", "changeConfig"];
|
|
52
|
+
export type DesignerCommands = Pick<SeatsChartDesigner, (typeof DESIGNER_COMMANDS)[number]>;
|
|
53
|
+
/** Compile-time guard: a new embed command must be exposed by the wrappers. */
|
|
54
|
+
export type CommandsCovered = [
|
|
55
|
+
Assert<Covers<PromiseMethods<SeatsChart>, (typeof CHART_COMMANDS)[number]>>,
|
|
56
|
+
Assert<Covers<PromiseMethods<SeatsChartEventManager>, (typeof EVENT_MANAGER_COMMANDS)[number]>>,
|
|
57
|
+
Assert<Covers<PromiseMethods<SeatsChartDesigner>, (typeof DESIGNER_COMMANDS)[number]>>
|
|
58
|
+
];
|
|
59
|
+
/**
|
|
60
|
+
* Methods that forward to the current instance (re-created instances included). Before mount and after unmount
|
|
61
|
+
* they reject with `ChartCommandError` ("… is not mounted.") instead of throwing.
|
|
62
|
+
*/
|
|
63
|
+
export declare function delegateCommands<I extends object, K extends keyof I & string>(current: () => I | null, names: readonly K[], label: string): Pick<I, K>;
|
|
64
|
+
/** Run one promise command on the instance (rejects with `ChartCommandError` without one). */
|
|
65
|
+
export declare function runCommand(instance: object | null, name: string, label: string, args: readonly unknown[]): Promise<unknown>;
|
|
66
|
+
/**
|
|
67
|
+
* Order-independent fingerprint of a prop value: plain objects and arrays by value (reactive proxies included),
|
|
68
|
+
* functions as "a function", other objects (a form element) by identity. `undefined` = not set.
|
|
69
|
+
*/
|
|
70
|
+
export declare function valueKey(value: unknown): string | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Deep copy of plain objects and arrays (reactive proxies become plain data the embed can post to the iframe);
|
|
73
|
+
* functions and other objects are kept as they are.
|
|
74
|
+
*/
|
|
75
|
+
export declare function toPlain<T>(value: T): T;
|
|
76
|
+
/** What every embed host instance offers the binding. */
|
|
77
|
+
export type EmbedInstance = {
|
|
78
|
+
render(): unknown;
|
|
79
|
+
destroy(): void;
|
|
80
|
+
getIframe(): HTMLIFrameElement | null;
|
|
81
|
+
};
|
|
82
|
+
export type EmbedConfig = Record<string, unknown>;
|
|
83
|
+
export type EmbedKind<I extends EmbedInstance> = {
|
|
84
|
+
/** "Seat chart", "Event Manager", "Designer" (error messages). */
|
|
85
|
+
label: string;
|
|
86
|
+
create: (config: EmbedConfig & {
|
|
87
|
+
container: HTMLElement;
|
|
88
|
+
}) => I;
|
|
89
|
+
rerender: (instance: I, config: EmbedConfig) => void;
|
|
90
|
+
changeConfig: (instance: I, patch: EmbedConfig, config: EmbedConfig) => Promise<unknown>;
|
|
91
|
+
/** Keys applied live through `changeConfig`. */
|
|
92
|
+
liveKeys: ReadonlySet<string>;
|
|
93
|
+
/** Keys read when the instance is created (a change re-creates it). */
|
|
94
|
+
mountKeys: ReadonlySet<string>;
|
|
95
|
+
defaultHeight: number;
|
|
96
|
+
defaultTitle: string;
|
|
97
|
+
};
|
|
98
|
+
export type BindingAction = "none" | "frame" | "changeConfig" | "rerender" | "remount";
|
|
99
|
+
/** One mounted embed instance driven by component props. */
|
|
100
|
+
export declare class EmbedBinding<I extends EmbedInstance> {
|
|
101
|
+
private readonly kind;
|
|
102
|
+
private instance;
|
|
103
|
+
private container;
|
|
104
|
+
private config;
|
|
105
|
+
private applied;
|
|
106
|
+
constructor(kind: EmbedKind<I>);
|
|
107
|
+
/** The live embed instance (null before mount / after unmount). */
|
|
108
|
+
get current(): I | null;
|
|
109
|
+
get label(): string;
|
|
110
|
+
/** Create the instance in `container` and render it (browser only). */
|
|
111
|
+
mount(container: HTMLElement, config: EmbedConfig): void;
|
|
112
|
+
/** Apply new props; returns what was done (tests and diagnostics). */
|
|
113
|
+
update(next: EmbedConfig): BindingAction;
|
|
114
|
+
/** Re-create the iframe with the current props (seats.io `rerender()`). */
|
|
115
|
+
rerender(): void;
|
|
116
|
+
/** Remove the iframe and every listener. */
|
|
117
|
+
destroy(): void;
|
|
118
|
+
private remember;
|
|
119
|
+
private remount;
|
|
120
|
+
private applyFrame;
|
|
121
|
+
}
|
|
122
|
+
export declare const CHART_KIND: EmbedKind<SeatsChart>;
|
|
123
|
+
export declare const EVENT_MANAGER_KIND: EmbedKind<SeatsChartEventManager>;
|
|
124
|
+
export declare const DESIGNER_KIND: EmbedKind<SeatsChartDesigner>;
|
|
125
|
+
//# sourceMappingURL=host-core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-core.d.ts","sourceRoot":"","sources":["../src/host-core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-agnostic glue between a component and one `@seatschart/embed` host instance (`SeatsChart`,
|
|
3
|
+
* `SeatsChartEventManager` or `SeatsChartDesigner`). This file is identical in `@seatschart/vue` and
|
|
4
|
+
* `@seatschart/angular` (a unit test keeps the two copies in step): the wrappers only map framework props, events
|
|
5
|
+
* and lifecycle onto it, every embed behaviour (iframe, origin checks, commands, sessions) stays in the embed.
|
|
6
|
+
*
|
|
7
|
+
* Prop updates are compared by value with what the instance last received, then applied the cheapest correct way:
|
|
8
|
+
* iframe attributes in place, live keys through `changeConfig` (no reload), other keys through `rerender(config)`
|
|
9
|
+
* (the hold session / the created chart is kept), mount-only keys by re-creating the instance.
|
|
10
|
+
*/
|
|
11
|
+
import { CHART_EVENT_CALLBACKS, ChartCommandError, DESIGNER_CALLBACKS, DESIGNER_PATCH_KEYS, EVENT_MANAGER_CALLBACKS, EVENT_MANAGER_CONFIG_KEYS, HOST_CONFIG_KEYS, SeatsChart, SeatsChartDesigner, SeatsChartEventManager, } from "@seatschart/embed";
|
|
12
|
+
// --- Prop / callback names ------------------------------------------------------------------------------------
|
|
13
|
+
/** Loader options of the buyer chart that are not declarative host config keys. */
|
|
14
|
+
const CHART_LOADER_KEYS = [
|
|
15
|
+
"webBase", "event", "events", "publicKey", "workspaceKey", "token", "parentOrigin", "channel", "channelKey",
|
|
16
|
+
"channelKeys", "session", "season", "language", "multiSelectEnabled", "holdToken", "availableCategories",
|
|
17
|
+
"unavailableCategories", "currency", "theme", "statusPalette", "transparent", "backgroundColor", "pricing",
|
|
18
|
+
"defaultRenderer", "height", "title", "className", "allowFullscreen", "timeoutMs", "holdTokenInputName",
|
|
19
|
+
"selectedObjectsInputName", "form",
|
|
20
|
+
];
|
|
21
|
+
/** Every buyer chart option a component accepts as a prop / input (the host config keys first). */
|
|
22
|
+
export const CHART_CONFIG_KEYS = [...HOST_CONFIG_KEYS, ...CHART_LOADER_KEYS];
|
|
23
|
+
/** Chart callbacks (seats.io names) forwarded as component events. */
|
|
24
|
+
export const CHART_CALLBACKS = [...CHART_EVENT_CALLBACKS, "onHoldCreated"];
|
|
25
|
+
/** Host-drawn prompts: registering one switches the matching viewer prompt to the host. */
|
|
26
|
+
export const PROMPT_CALLBACKS = ["onPlacesPrompt", "onTicketTypePrompt", "onPlacesWithTicketTypesPrompt"];
|
|
27
|
+
export const EVENT_MANAGER_KEYS = [
|
|
28
|
+
...EVENT_MANAGER_CONFIG_KEYS, "webBase", "event", "eventId", "token", "mode", "language", "colorScheme",
|
|
29
|
+
"parentOrigin", "height", "title", "className", "timeoutMs",
|
|
30
|
+
];
|
|
31
|
+
export { EVENT_MANAGER_CALLBACKS };
|
|
32
|
+
export const DESIGNER_KEYS = [
|
|
33
|
+
"webBase", "chartId", "chartKey", "token", "mode", "safeModeOptions", "features", "language", "colorScheme",
|
|
34
|
+
"canvasColorScheme", "openDraftDrawing", "openLatestDrawing", "parentOrigin", "height", "title", "className",
|
|
35
|
+
"timeoutMs",
|
|
36
|
+
];
|
|
37
|
+
export { DESIGNER_CALLBACKS };
|
|
38
|
+
/** `onObjectSelected` → `objectSelected`. */
|
|
39
|
+
export function eventName(callback) {
|
|
40
|
+
const name = callback.startsWith("on") ? callback.slice(2) : callback;
|
|
41
|
+
return (name.charAt(0).toLowerCase() + name.slice(1));
|
|
42
|
+
}
|
|
43
|
+
/** Every promise command of `SeatsChart` (each waits for the chart to render; rejects with `ChartCommandError`). */
|
|
44
|
+
export const CHART_COMMANDS = [
|
|
45
|
+
"whenReady", "request", "selectObjects", "deselectObjects", "clearSelection", "listSelectedObjects",
|
|
46
|
+
"selectBestAvailable", "findObject", "listCategories", "setFilteredCategories", "clearFilteredCategories",
|
|
47
|
+
"setFilters", "clearFilters", "highlightObjects", "clearHighlights", "zoomToObjects", "zoomToSelectedObjects",
|
|
48
|
+
"zoomToSection", "zoomToFilteredCategories", "resetView", "goToFloor", "listFloors", "goToAllFloorsView",
|
|
49
|
+
"getReportBySelectability", "getReportBySelectabilityGroupedBy", "getHoldToken", "startNewSession",
|
|
50
|
+
"releaseHoldToken", "isObjectInChannel", "showViewFromSeat", "trySelectObjects", "doSelectObjects",
|
|
51
|
+
"selectCategories", "deselectCategories", "listZones", "setSpotlight", "setSpotlightObjects",
|
|
52
|
+
"setSpotlightOnSelection", "clearSpotlight", "clearSpotlightObjects", "pulse", "unpulse", "resolvePrompt",
|
|
53
|
+
"exportImage", "setPricing", "changeConfig",
|
|
54
|
+
];
|
|
55
|
+
/** Every promise command of `SeatsChartEventManager` (seats.io `EventManager` methods). */
|
|
56
|
+
export const EVENT_MANAGER_COMMANDS = [
|
|
57
|
+
"whenReady", "request", "listSelectedObjects", "selectObjects", "doSelectObjects", "trySelectObjects",
|
|
58
|
+
"deselectObjects", "clearSelection", "setHighlightedObjects", "clearHighlightedObjects", "listOrderChanges",
|
|
59
|
+
"zoomToObjects", "zoomToSelectedObjects", "changeConfig",
|
|
60
|
+
];
|
|
61
|
+
/** Every promise command of `SeatsChartDesigner`. */
|
|
62
|
+
export const DESIGNER_COMMANDS = [
|
|
63
|
+
"whenReady", "request", "save", "publish", "getState", "changeConfig",
|
|
64
|
+
];
|
|
65
|
+
/**
|
|
66
|
+
* Methods that forward to the current instance (re-created instances included). Before mount and after unmount
|
|
67
|
+
* they reject with `ChartCommandError` ("… is not mounted.") instead of throwing.
|
|
68
|
+
*/
|
|
69
|
+
export function delegateCommands(current, names, label) {
|
|
70
|
+
const out = {};
|
|
71
|
+
for (const name of names)
|
|
72
|
+
out[name] = (...args) => runCommand(current(), name, label, args);
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
/** Run one promise command on the instance (rejects with `ChartCommandError` without one). */
|
|
76
|
+
export function runCommand(instance, name, label, args) {
|
|
77
|
+
if (instance === null)
|
|
78
|
+
return Promise.reject(new ChartCommandError(`${label} is not mounted.`, name));
|
|
79
|
+
const method = instance[name];
|
|
80
|
+
return method.apply(instance, [...args]);
|
|
81
|
+
}
|
|
82
|
+
// --- Value comparison -------------------------------------------------------------------------------------------
|
|
83
|
+
function isPlainObject(value) {
|
|
84
|
+
const proto = Object.getPrototypeOf(value);
|
|
85
|
+
return proto === Object.prototype || proto === null;
|
|
86
|
+
}
|
|
87
|
+
const identities = new WeakMap();
|
|
88
|
+
let lastIdentity = 0;
|
|
89
|
+
/**
|
|
90
|
+
* Order-independent fingerprint of a prop value: plain objects and arrays by value (reactive proxies included),
|
|
91
|
+
* functions as "a function", other objects (a form element) by identity. `undefined` = not set.
|
|
92
|
+
*/
|
|
93
|
+
export function valueKey(value) {
|
|
94
|
+
if (value === undefined)
|
|
95
|
+
return undefined;
|
|
96
|
+
if (typeof value === "function")
|
|
97
|
+
return "ƒ";
|
|
98
|
+
if (value === null || typeof value !== "object")
|
|
99
|
+
return typeof value === "string" ? JSON.stringify(value) : String(value);
|
|
100
|
+
if (Array.isArray(value))
|
|
101
|
+
return `[${value.map((item) => valueKey(item) ?? "u").join(",")}]`;
|
|
102
|
+
if (!isPlainObject(value)) {
|
|
103
|
+
let id = identities.get(value);
|
|
104
|
+
if (id === undefined) {
|
|
105
|
+
id = ++lastIdentity;
|
|
106
|
+
identities.set(value, id);
|
|
107
|
+
}
|
|
108
|
+
return `#${id}`;
|
|
109
|
+
}
|
|
110
|
+
const record = value;
|
|
111
|
+
const parts = [];
|
|
112
|
+
for (const key of Object.keys(record).sort()) {
|
|
113
|
+
const item = valueKey(record[key]);
|
|
114
|
+
if (item !== undefined)
|
|
115
|
+
parts.push(`${JSON.stringify(key)}:${item}`);
|
|
116
|
+
}
|
|
117
|
+
return `{${parts.join(",")}}`;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Deep copy of plain objects and arrays (reactive proxies become plain data the embed can post to the iframe);
|
|
121
|
+
* functions and other objects are kept as they are.
|
|
122
|
+
*/
|
|
123
|
+
export function toPlain(value) {
|
|
124
|
+
if (value === null || typeof value !== "object")
|
|
125
|
+
return value;
|
|
126
|
+
if (Array.isArray(value))
|
|
127
|
+
return value.map((item) => toPlain(item));
|
|
128
|
+
if (!isPlainObject(value))
|
|
129
|
+
return value;
|
|
130
|
+
const out = {};
|
|
131
|
+
for (const [key, item] of Object.entries(value))
|
|
132
|
+
out[key] = toPlain(item);
|
|
133
|
+
return out;
|
|
134
|
+
}
|
|
135
|
+
/** Iframe attributes updated in place (no reload). */
|
|
136
|
+
const FRAME_KEYS = new Set(["height", "title", "className"]);
|
|
137
|
+
/** One mounted embed instance driven by component props. */
|
|
138
|
+
export class EmbedBinding {
|
|
139
|
+
constructor(kind) {
|
|
140
|
+
this.kind = kind;
|
|
141
|
+
this.instance = null;
|
|
142
|
+
this.container = null;
|
|
143
|
+
this.config = {};
|
|
144
|
+
this.applied = new Map();
|
|
145
|
+
}
|
|
146
|
+
/** The live embed instance (null before mount / after unmount). */
|
|
147
|
+
get current() {
|
|
148
|
+
return this.instance;
|
|
149
|
+
}
|
|
150
|
+
get label() {
|
|
151
|
+
return this.kind.label;
|
|
152
|
+
}
|
|
153
|
+
/** Create the instance in `container` and render it (browser only). */
|
|
154
|
+
mount(container, config) {
|
|
155
|
+
if (this.instance !== null)
|
|
156
|
+
return;
|
|
157
|
+
this.container = container;
|
|
158
|
+
this.remember(config);
|
|
159
|
+
const instance = this.kind.create({ ...this.config, container });
|
|
160
|
+
this.instance = instance;
|
|
161
|
+
instance.render();
|
|
162
|
+
}
|
|
163
|
+
/** Apply new props; returns what was done (tests and diagnostics). */
|
|
164
|
+
update(next) {
|
|
165
|
+
const previous = this.applied;
|
|
166
|
+
const before = this.config;
|
|
167
|
+
this.remember(next);
|
|
168
|
+
const instance = this.instance;
|
|
169
|
+
if (instance === null)
|
|
170
|
+
return "none";
|
|
171
|
+
const changed = [];
|
|
172
|
+
for (const key of new Set([...previous.keys(), ...this.applied.keys()])) {
|
|
173
|
+
if (previous.get(key) !== this.applied.get(key))
|
|
174
|
+
changed.push(key);
|
|
175
|
+
}
|
|
176
|
+
if (changed.length === 0)
|
|
177
|
+
return "none";
|
|
178
|
+
if (changed.some((key) => this.kind.mountKeys.has(key))) {
|
|
179
|
+
this.remount();
|
|
180
|
+
return "remount";
|
|
181
|
+
}
|
|
182
|
+
if (changed.some((key) => !this.kind.liveKeys.has(key) && !FRAME_KEYS.has(key))) {
|
|
183
|
+
// Keys that disappeared are passed as undefined so the instance forgets them.
|
|
184
|
+
const config = { ...this.config };
|
|
185
|
+
for (const key of Object.keys(before))
|
|
186
|
+
if (!(key in config))
|
|
187
|
+
config[key] = undefined;
|
|
188
|
+
this.kind.rerender(instance, config);
|
|
189
|
+
return "rerender";
|
|
190
|
+
}
|
|
191
|
+
let action = "none";
|
|
192
|
+
if (changed.some((key) => FRAME_KEYS.has(key))) {
|
|
193
|
+
this.applyFrame(instance.getIframe());
|
|
194
|
+
action = "frame";
|
|
195
|
+
}
|
|
196
|
+
const patch = {};
|
|
197
|
+
for (const key of changed)
|
|
198
|
+
if (this.kind.liveKeys.has(key))
|
|
199
|
+
patch[key] = this.config[key] ?? null;
|
|
200
|
+
if (Object.keys(patch).length > 0) {
|
|
201
|
+
void this.kind.changeConfig(instance, patch, this.config).catch((error) => {
|
|
202
|
+
// A patch still waiting when the instance goes away is moot.
|
|
203
|
+
if (this.instance === instance)
|
|
204
|
+
console.warn(`[SeatsChart] ${this.kind.label}: config not applied:`, error);
|
|
205
|
+
});
|
|
206
|
+
action = "changeConfig";
|
|
207
|
+
}
|
|
208
|
+
return action;
|
|
209
|
+
}
|
|
210
|
+
/** Re-create the iframe with the current props (seats.io `rerender()`). */
|
|
211
|
+
rerender() {
|
|
212
|
+
if (this.instance !== null)
|
|
213
|
+
this.kind.rerender(this.instance, { ...this.config });
|
|
214
|
+
}
|
|
215
|
+
/** Remove the iframe and every listener. */
|
|
216
|
+
destroy() {
|
|
217
|
+
this.instance?.destroy();
|
|
218
|
+
this.instance = null;
|
|
219
|
+
this.container = null;
|
|
220
|
+
}
|
|
221
|
+
remember(config) {
|
|
222
|
+
const plain = {};
|
|
223
|
+
const applied = new Map();
|
|
224
|
+
for (const [key, value] of Object.entries(config)) {
|
|
225
|
+
if (value === undefined)
|
|
226
|
+
continue;
|
|
227
|
+
plain[key] = toPlain(value);
|
|
228
|
+
const fingerprint = valueKey(value);
|
|
229
|
+
if (fingerprint !== undefined)
|
|
230
|
+
applied.set(key, fingerprint);
|
|
231
|
+
}
|
|
232
|
+
this.config = plain;
|
|
233
|
+
this.applied = applied;
|
|
234
|
+
}
|
|
235
|
+
remount() {
|
|
236
|
+
const container = this.container;
|
|
237
|
+
this.instance?.destroy();
|
|
238
|
+
this.instance = null;
|
|
239
|
+
if (container !== null)
|
|
240
|
+
this.mount(container, this.config);
|
|
241
|
+
}
|
|
242
|
+
applyFrame(iframe) {
|
|
243
|
+
if (iframe === null)
|
|
244
|
+
return;
|
|
245
|
+
const { height, title, className } = this.config;
|
|
246
|
+
const h = typeof height === "number" || typeof height === "string" ? height : this.kind.defaultHeight;
|
|
247
|
+
iframe.style.height = typeof h === "number" ? `${h}px` : h;
|
|
248
|
+
iframe.title = typeof title === "string" ? title : this.kind.defaultTitle;
|
|
249
|
+
iframe.className = typeof className === "string" ? className : "";
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
// --- The three embeds -------------------------------------------------------------------------------------------
|
|
253
|
+
export const CHART_KIND = {
|
|
254
|
+
label: "Seat chart",
|
|
255
|
+
create: (config) => new SeatsChart(config),
|
|
256
|
+
rerender: (chart, config) => {
|
|
257
|
+
chart.rerender(config);
|
|
258
|
+
},
|
|
259
|
+
changeConfig: (chart, patch, config) => {
|
|
260
|
+
// Host pricing follows the chart's sales channel.
|
|
261
|
+
const withChannel = "pricing" in patch && typeof config.channel === "string" ? { ...patch, channel: config.channel } : patch;
|
|
262
|
+
return chart.changeConfig(withChannel);
|
|
263
|
+
},
|
|
264
|
+
liveKeys: new Set([...HOST_CONFIG_KEYS, "pricing"]),
|
|
265
|
+
mountKeys: new Set(["timeoutMs", "holdTokenInputName", "selectedObjectsInputName", "form"]),
|
|
266
|
+
defaultHeight: 640,
|
|
267
|
+
defaultTitle: "Seat map",
|
|
268
|
+
};
|
|
269
|
+
export const EVENT_MANAGER_KIND = {
|
|
270
|
+
label: "Event Manager",
|
|
271
|
+
create: (config) => new SeatsChartEventManager(config),
|
|
272
|
+
rerender: (manager, config) => {
|
|
273
|
+
manager.rerender(config);
|
|
274
|
+
},
|
|
275
|
+
changeConfig: (manager, patch) => manager.changeConfig(patch),
|
|
276
|
+
liveKeys: new Set([...EVENT_MANAGER_CONFIG_KEYS, "language", "colorScheme"]),
|
|
277
|
+
mountKeys: new Set(["timeoutMs"]),
|
|
278
|
+
defaultHeight: 760,
|
|
279
|
+
defaultTitle: "Event Manager",
|
|
280
|
+
};
|
|
281
|
+
export const DESIGNER_KIND = {
|
|
282
|
+
label: "Designer",
|
|
283
|
+
create: (config) => new SeatsChartDesigner(config),
|
|
284
|
+
rerender: (designer, config) => {
|
|
285
|
+
designer.rerender(config);
|
|
286
|
+
},
|
|
287
|
+
changeConfig: (designer, patch) => designer.changeConfig(patch),
|
|
288
|
+
liveKeys: new Set(DESIGNER_PATCH_KEYS),
|
|
289
|
+
mountKeys: new Set(["timeoutMs"]),
|
|
290
|
+
defaultHeight: 800,
|
|
291
|
+
defaultTitle: "Seating chart designer",
|
|
292
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { SeatChart, createSeatChartHandle, useSeatChart, type SeatChartCallbacks, type SeatChartHandle, type SeatChartOptions, type SeatChartEmits, type SeatChartProps, } from "./SeatChart.js";
|
|
2
|
+
export { EventManager, createEventManagerHandle, useEventManager, type EventManagerHandle, type EventManagerProps, type EventManagerEmits, } from "./EventManager.js";
|
|
3
|
+
export { Designer, createDesignerHandle, useDesigner, type DesignerHandle, type DesignerProps, type DesignerEmits, } from "./Designer.js";
|
|
4
|
+
export { CHART_CALLBACKS, CHART_COMMANDS, CHART_CONFIG_KEYS, DESIGNER_COMMANDS, DESIGNER_KEYS, EVENT_MANAGER_COMMANDS, EVENT_MANAGER_KEYS, EmbedBinding, eventName, type BindingAction, type ChartCommands, type DesignerCommands, type EventManagerCommands, } from "./host-core.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,qBAAqB,EACrB,YAAY,EACZ,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,cAAc,GACpB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,YAAY,EACZ,wBAAwB,EACxB,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,QAAQ,EACR,oBAAoB,EACpB,WAAW,EACX,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,sBAAsB,EACtB,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,GAC1B,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { SeatChart, createSeatChartHandle, useSeatChart, } from "./SeatChart.js";
|
|
2
|
+
export { EventManager, createEventManagerHandle, useEventManager, } from "./EventManager.js";
|
|
3
|
+
export { Designer, createDesignerHandle, useDesigner, } from "./Designer.js";
|
|
4
|
+
export { CHART_CALLBACKS, CHART_COMMANDS, CHART_CONFIG_KEYS, DESIGNER_COMMANDS, DESIGNER_KEYS, EVENT_MANAGER_COMMANDS, EVENT_MANAGER_KEYS, EmbedBinding, eventName, } from "./host-core.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,53 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seatschart/vue",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Vue 3 components for SeatsChart seat maps: buyer chart, Event Manager and designer embeds",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/seatschart/seatschart-prod.git"
|
|
10
|
+
},
|
|
11
|
+
"main": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"README.md"
|
|
22
|
+
],
|
|
23
|
+
"keywords": [
|
|
24
|
+
"seatschart",
|
|
25
|
+
"seats",
|
|
26
|
+
"vue",
|
|
27
|
+
"nuxt",
|
|
28
|
+
"embed",
|
|
29
|
+
"ticketing"
|
|
30
|
+
],
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsc -p tsconfig.json",
|
|
36
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
37
|
+
"test": "bun test src",
|
|
38
|
+
"prepublishOnly": "bun run build"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"vue": ">=3.3.0"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@seatschart/embed": "^0.6.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@happy-dom/global-registrator": "^21.0.4",
|
|
48
|
+
"happy-dom": "^21.0.4",
|
|
49
|
+
"typescript": "^7.0.2",
|
|
50
|
+
"vue": "^3.5.44"
|
|
51
|
+
},
|
|
52
|
+
"sideEffects": false
|
|
53
|
+
}
|