@swift-food-services/catering-widget 0.1.0-beta.1
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/README.md +227 -0
- package/dist/fonts/IBMPlexMono-400.woff2 +0 -0
- package/dist/fonts/IBMPlexMono-500.woff2 +0 -0
- package/dist/fonts/IBMPlexMono-600.woff2 +0 -0
- package/dist/fonts/IBMPlexMono-700.woff2 +0 -0
- package/dist/index.cjs +12694 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +86 -0
- package/dist/index.d.ts +86 -0
- package/dist/index.mjs +12692 -0
- package/dist/index.mjs.map +1 -0
- package/dist/styles.css +2 -0
- package/package.json +80 -0
package/README.md
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# @swift-food-services/catering-widget
|
|
2
|
+
|
|
3
|
+
The Swift Food catering flow, embeddable in any React app. Restaurant browsing, multi-session order building, contact details, and submission — one component, one CSS file, one publishable key.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install @swift-food-services/catering-widget
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Quick start
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import { CateringWidget } from "@swift-food-services/catering-widget";
|
|
13
|
+
import "@swift-food-services/catering-widget/dist/styles.css";
|
|
14
|
+
|
|
15
|
+
export default function CateringPage() {
|
|
16
|
+
return (
|
|
17
|
+
<CateringWidget
|
|
18
|
+
publishableKey="pk_live_..."
|
|
19
|
+
onOrderComplete={({ orderId }) => {
|
|
20
|
+
window.location.href = `/thanks?order=${orderId}`;
|
|
21
|
+
}}
|
|
22
|
+
/>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Defaults: Swift-hosted backend, `localStorage` persistence, neutral theme.
|
|
28
|
+
|
|
29
|
+
## Requirements
|
|
30
|
+
|
|
31
|
+
- React 18+ and React-DOM 18+ as peer dependencies
|
|
32
|
+
- A publishable key from Swift (see [Getting a publishable key](#getting-a-publishable-key))
|
|
33
|
+
- At least one origin registered with Swift where the widget will load
|
|
34
|
+
|
|
35
|
+
## Props
|
|
36
|
+
|
|
37
|
+
| Prop | Type | Required | Description |
|
|
38
|
+
|---|---|---|---|
|
|
39
|
+
| `publishableKey` | `string` | yes | Your `pk_live_...` or `pk_test_...` key from Swift. |
|
|
40
|
+
| `theme` | `Theme` | no | Primary color, border radius, and font overrides. |
|
|
41
|
+
| `initialData` | `InitialData` | no | Pre-populate event, address, and contact fields. Applied only on first mount. |
|
|
42
|
+
| `stickyTopOffset` | `number` | no | Pixels to offset the widget's internal sticky date/session nav from the top of the viewport. Set this to the height of any sticky/fixed navbar in your host layout so the widget's nav doesn't slide underneath it. Defaults to `0`. |
|
|
43
|
+
| `onReady` | `() => void` | no | Fires when the widget has initialized. |
|
|
44
|
+
| `onOrderComplete` | `(result: OrderCompleteResult) => void` | no | Fires after a successful order submission. |
|
|
45
|
+
| `onError` | `(error: WidgetError) => void` | no | Fires on unrecoverable errors (bad key, network, submit failure). |
|
|
46
|
+
|
|
47
|
+
## Examples
|
|
48
|
+
|
|
49
|
+
### Next.js with router-based navigation
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
"use client";
|
|
53
|
+
import { CateringWidget } from "@swift-food-services/catering-widget";
|
|
54
|
+
import "@swift-food-services/catering-widget/dist/styles.css";
|
|
55
|
+
import { useRouter } from "next/navigation";
|
|
56
|
+
|
|
57
|
+
export default function Page() {
|
|
58
|
+
const router = useRouter();
|
|
59
|
+
return (
|
|
60
|
+
<CateringWidget
|
|
61
|
+
publishableKey={process.env.NEXT_PUBLIC_SWIFT_KEY!}
|
|
62
|
+
onOrderComplete={({ orderId, accessToken }) => {
|
|
63
|
+
router.push(`/orders/${orderId}?token=${accessToken}`);
|
|
64
|
+
}}
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Theming
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
<CateringWidget
|
|
74
|
+
publishableKey="pk_live_..."
|
|
75
|
+
theme={{
|
|
76
|
+
primary: "#0a7ea4",
|
|
77
|
+
radius: "12px",
|
|
78
|
+
font: "\"IBM Plex Mono\", monospace",
|
|
79
|
+
}}
|
|
80
|
+
/>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Pre-filling known event details
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
<CateringWidget
|
|
87
|
+
publishableKey="pk_live_..."
|
|
88
|
+
initialData={{
|
|
89
|
+
eventName: "Alice's Birthday",
|
|
90
|
+
eventDate: "2026-07-12",
|
|
91
|
+
eventTime: "19:00",
|
|
92
|
+
guestCount: 40,
|
|
93
|
+
deliveryAddress: {
|
|
94
|
+
line1: "1 Example Lane",
|
|
95
|
+
city: "London",
|
|
96
|
+
postcode: "E1 6AN",
|
|
97
|
+
},
|
|
98
|
+
contact: { name: "Alice", email: "alice@example.com" },
|
|
99
|
+
}}
|
|
100
|
+
onOrderComplete={/* ... */}
|
|
101
|
+
/>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Every field in `initialData` is optional. Fields remain editable after pre-fill. `initialData` is only applied on first mount — if the user has a half-finished order in progress (persisted in `localStorage`), the persisted state wins.
|
|
105
|
+
|
|
106
|
+
### Offsetting below a host navbar
|
|
107
|
+
|
|
108
|
+
If your page has its own sticky/fixed navbar, pass its height as `stickyTopOffset` so the widget's internal date/session nav pins just below it:
|
|
109
|
+
|
|
110
|
+
```tsx
|
|
111
|
+
<CateringWidget
|
|
112
|
+
publishableKey="pk_live_..."
|
|
113
|
+
stickyTopOffset={64}
|
|
114
|
+
/>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Pass a live value if your navbar resizes (measure it with a ref + `ResizeObserver` and pass the current height). The prop is read on every render, so updates take effect immediately.
|
|
118
|
+
|
|
119
|
+
## Types
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
import {
|
|
123
|
+
CateringWidget,
|
|
124
|
+
type CateringWidgetProps,
|
|
125
|
+
type Theme,
|
|
126
|
+
type InitialData,
|
|
127
|
+
type OrderCompleteResult,
|
|
128
|
+
type OrderSummary,
|
|
129
|
+
type MealSession,
|
|
130
|
+
type MealSessionItem,
|
|
131
|
+
type WidgetError,
|
|
132
|
+
} from "@swift-food-services/catering-widget";
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
See the generated `dist/index.d.ts` for the full shapes — your IDE picks them up automatically.
|
|
136
|
+
|
|
137
|
+
## Callbacks
|
|
138
|
+
|
|
139
|
+
### `onOrderComplete(result)`
|
|
140
|
+
|
|
141
|
+
Fires when an order has been successfully submitted. `result` contains:
|
|
142
|
+
|
|
143
|
+
- `orderId: string` — Swift's order ID.
|
|
144
|
+
- `accessToken: string` — a token the customer can use to view the order on Swift's hosted view page.
|
|
145
|
+
- `summary: OrderSummary` — structured breakdown of the submitted order.
|
|
146
|
+
|
|
147
|
+
### `onError(error)`
|
|
148
|
+
|
|
149
|
+
Fires on errors the widget can't recover from. `error.code` is one of:
|
|
150
|
+
|
|
151
|
+
- `invalid_publishable_key` — the key was rejected by Swift's backend.
|
|
152
|
+
- `session_failed` — the widget session handshake failed.
|
|
153
|
+
- `network_error` — a backend request failed or returned a non-2xx.
|
|
154
|
+
- `submit_failed` — the order submission itself failed.
|
|
155
|
+
- `unknown` — anything else; see `error.cause` for details.
|
|
156
|
+
|
|
157
|
+
## What the widget handles for you
|
|
158
|
+
|
|
159
|
+
- Restaurant browsing and menu exploration
|
|
160
|
+
- Multi-session meal building
|
|
161
|
+
- Contact details and delivery address
|
|
162
|
+
- Promo codes and pricing preview
|
|
163
|
+
- Google Maps address autocomplete
|
|
164
|
+
- Order submission to Swift's API
|
|
165
|
+
- State persistence in `localStorage` (namespaced)
|
|
166
|
+
|
|
167
|
+
## What you're responsible for
|
|
168
|
+
|
|
169
|
+
- Getting a publishable key from Swift.
|
|
170
|
+
- Registering your site's origin(s) with Swift.
|
|
171
|
+
- Rendering `<CateringWidget>` wherever you want the flow to live.
|
|
172
|
+
- Navigating after `onOrderComplete`.
|
|
173
|
+
- Page chrome around the widget.
|
|
174
|
+
|
|
175
|
+
## What you're **not** responsible for
|
|
176
|
+
|
|
177
|
+
- Payment. Swift sends a payment link by email after reviewing the order.
|
|
178
|
+
- Loading Google Maps — the widget handles this internally.
|
|
179
|
+
- Making API calls to Swift.
|
|
180
|
+
- Session or auth management.
|
|
181
|
+
|
|
182
|
+
## Build-time configuration
|
|
183
|
+
|
|
184
|
+
Set `SWIFT_WIDGET_GOOGLE_MAPS_KEY` before building the library so the Maps script loads with the correct key. CI publishes with the production key; local development can use a restricted dev key.
|
|
185
|
+
|
|
186
|
+
## Getting a publishable key
|
|
187
|
+
|
|
188
|
+
Contact Swift at [partners@swiftfood.uk](mailto:partners@swiftfood.uk) with:
|
|
189
|
+
|
|
190
|
+
1. Your company name.
|
|
191
|
+
2. The origin(s) where the widget will be embedded.
|
|
192
|
+
3. A technical contact for integration support.
|
|
193
|
+
|
|
194
|
+
Swift provisions a partner record and returns a publishable key (format: `pk_live_...` or `pk_test_...`) out of band.
|
|
195
|
+
|
|
196
|
+
The key is public (it ships in the browser bundle). Swift's backend validates the key against the request's origin, so a stolen key cannot be used from a non-allowlisted domain.
|
|
197
|
+
|
|
198
|
+
## Troubleshooting
|
|
199
|
+
|
|
200
|
+
**Widget doesn't render / screen is blank**
|
|
201
|
+
Check that you've imported the stylesheet: `import "@swift-food-services/catering-widget/dist/styles.css";`.
|
|
202
|
+
|
|
203
|
+
**Errors mentioning `invalid_publishable_key` or `session_failed`**
|
|
204
|
+
Either the key is wrong, the key is inactive, or your current origin isn't in the allowlist.
|
|
205
|
+
|
|
206
|
+
**Widget works on `localhost` but not in production**
|
|
207
|
+
Your production origin isn't registered. Ask Swift to add it.
|
|
208
|
+
|
|
209
|
+
**TypeScript errors importing types**
|
|
210
|
+
Ensure your `tsconfig.json` has `"moduleResolution": "bundler"` or `"node16"`/`"nodenext"`.
|
|
211
|
+
|
|
212
|
+
## Browser support
|
|
213
|
+
|
|
214
|
+
Modern evergreen browsers (Chrome, Firefox, Safari, Edge) on desktop and mobile.
|
|
215
|
+
|
|
216
|
+
## Versioning
|
|
217
|
+
|
|
218
|
+
`@swift-food-services/catering-widget` follows [semver](https://semver.org/). The public API is everything exported from the package entry — `CateringWidget`, its props, and the re-exported types.
|
|
219
|
+
|
|
220
|
+
## Support
|
|
221
|
+
|
|
222
|
+
- Integration questions: [partners@swiftfood.uk](mailto:partners@swiftfood.uk)
|
|
223
|
+
- Bug reports: include your publishable key prefix (first 8 chars), the browser, and a reproducible example.
|
|
224
|
+
|
|
225
|
+
## License
|
|
226
|
+
|
|
227
|
+
Proprietary. Distributed for use by authorized Swift Food partners only.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|