@zorgo/next 1.1.7 → 1.3.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/dist/cli.js +344 -1
- package/dist/cli.js.map +1 -0
- package/dist/cli.mjs +344 -1
- package/dist/cli.mjs.map +1 -0
- package/dist/components.d.mts +315 -87
- package/dist/components.d.ts +315 -87
- package/dist/components.js +1216 -820
- package/dist/components.js.map +1 -1
- package/dist/components.mjs +1195 -832
- package/dist/components.mjs.map +1 -1
- package/dist/images.d.mts +36 -0
- package/dist/images.d.ts +36 -0
- package/dist/images.js +62 -0
- package/dist/images.js.map +1 -0
- package/dist/images.mjs +32 -0
- package/dist/images.mjs.map +1 -0
- package/dist/index.d.mts +175 -6
- package/dist/index.d.ts +175 -6
- package/dist/index.js +162 -1
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +162 -1
- package/dist/index.mjs.map +1 -0
- package/dist/item-page.d.mts +151 -0
- package/dist/item-page.d.ts +151 -0
- package/dist/item-page.js +166 -0
- package/dist/item-page.js.map +1 -0
- package/dist/item-page.mjs +129 -0
- package/dist/item-page.mjs.map +1 -0
- package/dist/seo.d.mts +31 -1
- package/dist/seo.d.ts +31 -1
- package/dist/server.js +541 -1
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +504 -1
- package/dist/server.mjs.map +1 -0
- package/dist/slugs.js.map +1 -1
- package/dist/slugs.mjs.map +1 -1
- package/dist/tree/app/components/ClientItemForm.tsx +7 -0
- package/dist/tree/app/components/Header.tsx +3 -0
- package/dist/tree/app/components/ModalRegistry.tsx +3 -2
- package/dist/tree/app/components/index.ts +2 -1
- package/dist/tree/app/globals.css.gen.ts +1 -0
- package/dist/tree/app/menu/[slug]/page.tsx +16 -48
- package/dist/tree/gitignore +1 -0
- package/dist/tree/image-loader.ts +4 -0
- package/dist/tree/next.config.ts +12 -0
- package/package.json +11 -1
- package/dist/cli.d.mts +0 -9
- package/dist/cli.d.ts +0 -9
- package/dist/tree/app/menu/[slug]/ItemCustomizationClient.tsx +0 -18
package/dist/index.d.ts
CHANGED
|
@@ -2,8 +2,45 @@ import * as _stripe_stripe_js from '@stripe/stripe-js';
|
|
|
2
2
|
import { StripeElementsOptions } from '@stripe/stripe-js';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import React__default, { RefObject } from 'react';
|
|
5
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
5
|
import { z } from 'zod';
|
|
6
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* How the section picker draws itself. Closed set — each value needs a renderer,
|
|
10
|
+
* so adding one is a code change (and an `alter type portion_geometry add value`).
|
|
11
|
+
*
|
|
12
|
+
* Section order is fixed per geometry, and consecutive indices must be spatially
|
|
13
|
+
* adjacent so any divisor of the division count partitions cleanly (sections 1–3
|
|
14
|
+
* of 6 are exactly section 1 of 2). Without that, switching a customer from
|
|
15
|
+
* sixths to halves has no defined answer.
|
|
16
|
+
*
|
|
17
|
+
* - `radial` — contiguous arcs from 12 o'clock, counter-clockwise
|
|
18
|
+
* - `grid` — column-major: down the left column, then the next column
|
|
19
|
+
* - `linear` — one end to the other
|
|
20
|
+
* - `count` — equal shares of a countable quantity, no geometry
|
|
21
|
+
*/
|
|
22
|
+
declare const PortionGeometrySchema: z.ZodEnum<{
|
|
23
|
+
radial: "radial";
|
|
24
|
+
grid: "grid";
|
|
25
|
+
linear: "linear";
|
|
26
|
+
count: "count";
|
|
27
|
+
}>;
|
|
28
|
+
type PortionGeometry = z.infer<typeof PortionGeometrySchema>;
|
|
29
|
+
/** A row of `portion_schemes` — a franchise-owned, franchise-named menu entity. */
|
|
30
|
+
declare const PortionSchemeSchema: z.ZodObject<{
|
|
31
|
+
id: z.ZodNumber;
|
|
32
|
+
franchise_id: z.ZodNumber;
|
|
33
|
+
geometry: z.ZodEnum<{
|
|
34
|
+
radial: "radial";
|
|
35
|
+
grid: "grid";
|
|
36
|
+
linear: "linear";
|
|
37
|
+
count: "count";
|
|
38
|
+
}>;
|
|
39
|
+
name: z.ZodString;
|
|
40
|
+
min_divisions: z.ZodDefault<z.ZodNumber>;
|
|
41
|
+
max_divisions: z.ZodNumber;
|
|
42
|
+
}, z.core.$strip>;
|
|
43
|
+
type PortionScheme = z.infer<typeof PortionSchemeSchema>;
|
|
7
44
|
|
|
8
45
|
type LocationStatus = "active" | "permanently_closed";
|
|
9
46
|
interface Location {
|
|
@@ -53,16 +90,27 @@ interface ItemVariant {
|
|
|
53
90
|
components?: Component[];
|
|
54
91
|
base_item_id?: number;
|
|
55
92
|
rules?: Rule[];
|
|
93
|
+
portion_scheme_id?: number | null;
|
|
94
|
+
portion_scheme?: PortionScheme | null;
|
|
56
95
|
display_price?: number;
|
|
57
96
|
active_promo_id?: number;
|
|
58
97
|
}
|
|
98
|
+
interface BaseItemImage {
|
|
99
|
+
image_id: number;
|
|
100
|
+
base_item_id: number;
|
|
101
|
+
alias: string;
|
|
102
|
+
raw_path?: string | null;
|
|
103
|
+
processed_path?: string | null;
|
|
104
|
+
sort_index?: number;
|
|
105
|
+
local_key?: string | null;
|
|
106
|
+
}
|
|
59
107
|
interface MenuItem {
|
|
60
108
|
base_item_id: number;
|
|
61
109
|
category_id: number;
|
|
62
110
|
franchise_id: number;
|
|
63
111
|
name: string;
|
|
64
112
|
per_person?: boolean | null;
|
|
65
|
-
|
|
113
|
+
images?: BaseItemImage[];
|
|
66
114
|
variants: ItemVariant[];
|
|
67
115
|
rules: Rule[];
|
|
68
116
|
description?: string | null;
|
|
@@ -100,6 +148,7 @@ interface Rule {
|
|
|
100
148
|
min_selection: number;
|
|
101
149
|
max_selection?: number;
|
|
102
150
|
included_quantity: number;
|
|
151
|
+
is_portionable?: boolean;
|
|
103
152
|
items?: RuleItem[];
|
|
104
153
|
components?: RuleComponent[];
|
|
105
154
|
}
|
|
@@ -130,14 +179,25 @@ interface CustomizationOption {
|
|
|
130
179
|
selected: boolean;
|
|
131
180
|
disabled: boolean;
|
|
132
181
|
toggle: () => void;
|
|
182
|
+
/** Section this option currently targets; null when editing the whole item. */
|
|
183
|
+
portion?: string | null;
|
|
184
|
+
/** Section indices this option already covers, for shading the picker. */
|
|
185
|
+
coveredSections?: number[];
|
|
186
|
+
/** Already applied to the whole item, so individual sections are moot. */
|
|
187
|
+
coveredWhole?: boolean;
|
|
133
188
|
}
|
|
134
189
|
interface CustomizationRule extends Rule {
|
|
135
190
|
rule_id: number;
|
|
136
191
|
max: number;
|
|
192
|
+
/** Weighted, not a row count: two halves of one topping count as 1. */
|
|
137
193
|
selectedCount: number;
|
|
138
194
|
satisfied: boolean;
|
|
195
|
+
/** "Choose 1. Select up to 5. 1 included" — the rule's limits in words. */
|
|
196
|
+
subtext: string;
|
|
139
197
|
message: () => string | null;
|
|
140
198
|
options: CustomizationOption[];
|
|
199
|
+
/** This rule can be applied per-section under the item's scheme. */
|
|
200
|
+
portionable?: boolean;
|
|
141
201
|
}
|
|
142
202
|
interface OrderItem {
|
|
143
203
|
item_id: number;
|
|
@@ -155,6 +215,7 @@ interface OrderItem {
|
|
|
155
215
|
components?: OrderComponent[];
|
|
156
216
|
selections?: RuleSelection[];
|
|
157
217
|
comments?: string;
|
|
218
|
+
portion_scheme?: PortionScheme | null;
|
|
158
219
|
status?: "removed" | "modified";
|
|
159
220
|
applied_promo_id?: number;
|
|
160
221
|
discount_amount?: number;
|
|
@@ -163,6 +224,7 @@ interface OrderComponent extends Component {
|
|
|
163
224
|
quantity_servings: number;
|
|
164
225
|
upcharge?: number;
|
|
165
226
|
rule_id?: number;
|
|
227
|
+
portion?: string | null;
|
|
166
228
|
}
|
|
167
229
|
interface RuleSelection {
|
|
168
230
|
rule_id: number;
|
|
@@ -177,6 +239,7 @@ interface Selection {
|
|
|
177
239
|
serving_price?: number;
|
|
178
240
|
name: string;
|
|
179
241
|
status?: "removed" | "modified" | "added";
|
|
242
|
+
portion?: string | null;
|
|
180
243
|
component_type_id?: number;
|
|
181
244
|
serving_weight?: number;
|
|
182
245
|
measurement_type?: "weight" | "count";
|
|
@@ -383,7 +446,6 @@ declare function useMenu(): {
|
|
|
383
446
|
items: MenuItem[];
|
|
384
447
|
allItems: MenuItem[];
|
|
385
448
|
categories: Category[];
|
|
386
|
-
getItemImageUrl: (imagePath?: string | null) => string | null;
|
|
387
449
|
};
|
|
388
450
|
/**
|
|
389
451
|
* Seeds a store with prebuilt data (see the app's prebuild script) during the
|
|
@@ -432,11 +494,27 @@ declare function useItemCustomization(baseItemId: number, seed?: OrderItem, edit
|
|
|
432
494
|
unmetRule: CustomizationRule | null;
|
|
433
495
|
canSubmit: boolean;
|
|
434
496
|
submit: () => OrderItem | null;
|
|
497
|
+
portionScheme: {
|
|
498
|
+
id: number;
|
|
499
|
+
franchise_id: number;
|
|
500
|
+
geometry: "radial" | "grid" | "linear" | "count";
|
|
501
|
+
name: string;
|
|
502
|
+
min_divisions: number;
|
|
503
|
+
max_divisions: number;
|
|
504
|
+
} | null;
|
|
505
|
+
placeOption: (ruleId: number, baseKey: string, portion: string | null, max?: number) => void;
|
|
506
|
+
clearOption: (ruleId: number, baseKey: string) => void;
|
|
507
|
+
recutSelections: (next: number) => void;
|
|
435
508
|
quantity: number;
|
|
436
|
-
setQuantity:
|
|
509
|
+
setQuantity: (next: number | ((current: number) => number)) => void;
|
|
437
510
|
comments: string;
|
|
438
511
|
setComments: React.Dispatch<React.SetStateAction<string>>;
|
|
439
|
-
|
|
512
|
+
/**
|
|
513
|
+
* Set a component's servings for the whole item, or for one section when
|
|
514
|
+
* `portion` is given. 0 removes it — "no cheese", or "no cheese on the
|
|
515
|
+
* left half".
|
|
516
|
+
*/
|
|
517
|
+
setComponentServings: (componentId: number, qty: number, portion?: string | null) => void;
|
|
440
518
|
price: number;
|
|
441
519
|
salePrice: number | undefined;
|
|
442
520
|
isEditMode: boolean;
|
|
@@ -1105,4 +1183,95 @@ declare function useFormValues(): Record<string, unknown>;
|
|
|
1105
1183
|
|
|
1106
1184
|
declare function useFormValidity(): boolean;
|
|
1107
1185
|
|
|
1108
|
-
|
|
1186
|
+
declare function parsePortion(portion: string): {
|
|
1187
|
+
index: number;
|
|
1188
|
+
divisions: number;
|
|
1189
|
+
};
|
|
1190
|
+
/** A section's share of the whole. No portion = the whole item = 1. */
|
|
1191
|
+
declare function portionWeight(portion?: string | null): number;
|
|
1192
|
+
/**
|
|
1193
|
+
* Selection keys carry their portion as a suffix: `component:123@1/2`. A bare
|
|
1194
|
+
* key is the whole item, which is what every pre-portion key already is — so
|
|
1195
|
+
* existing state parses unchanged.
|
|
1196
|
+
*/
|
|
1197
|
+
declare function portionKey(baseKey: string, portion?: string | null): string;
|
|
1198
|
+
declare function parsePortionKey(key: string): {
|
|
1199
|
+
baseKey: string;
|
|
1200
|
+
portion: string | null;
|
|
1201
|
+
};
|
|
1202
|
+
/**
|
|
1203
|
+
* A section's share of a whole-item upcharge, in cents. Rounds up, so covering
|
|
1204
|
+
* every section can cost a cent or two more than the whole — which is why a
|
|
1205
|
+
* selection covering everything collapses to a single portion-less row instead.
|
|
1206
|
+
*/
|
|
1207
|
+
declare function splitUpcharge(cents: number, divisions: number): number;
|
|
1208
|
+
/** Every division count a scheme allows, for the picker's cut selector. */
|
|
1209
|
+
declare function divisionsFor(scheme: Pick<PortionScheme, "min_divisions" | "max_divisions">): number[];
|
|
1210
|
+
/**
|
|
1211
|
+
* The one place a section index becomes words. The picker, the cart line, the
|
|
1212
|
+
* receipt and the KDS ticket all call this on the same scheme, so the index is
|
|
1213
|
+
* the only token the UI and the data share.
|
|
1214
|
+
*/
|
|
1215
|
+
declare function portionLabel(portion: string | null | undefined, scheme: Pick<PortionScheme, "geometry">): string;
|
|
1216
|
+
/**
|
|
1217
|
+
* Expand per-section overrides on one keyed entity into one row per section —
|
|
1218
|
+
* how "no cheese on the left half" becomes a 0-serving row for that section and
|
|
1219
|
+
* a normal row for the rest. No overrides, or the same value on every section,
|
|
1220
|
+
* is a single whole-item row (§3 collapse).
|
|
1221
|
+
*/
|
|
1222
|
+
declare function portionRows(baseKey: string, values: Record<string, number>, fallback: number): {
|
|
1223
|
+
portion: string | null;
|
|
1224
|
+
value: number;
|
|
1225
|
+
}[];
|
|
1226
|
+
/** Weighted count of a rule's selections: two halves of one topping count as 1. */
|
|
1227
|
+
declare function selectionWeight(keys: string[]): number;
|
|
1228
|
+
/**
|
|
1229
|
+
* Spend `included_quantity` on selection keys in pick order. A topping is a
|
|
1230
|
+
* topping: it takes one included slot no matter how little of the pizza it covers,
|
|
1231
|
+
* so putting pepperoni on one half never leaves half a free slot behind to
|
|
1232
|
+
* discount everything else — and its rows share that one slot, so two halves of
|
|
1233
|
+
* pepperoni consume one included topping, not two. With no portions this is
|
|
1234
|
+
* exactly the old positional rule (`position < included ? 0 : basePrice`).
|
|
1235
|
+
*/
|
|
1236
|
+
declare function weightedUpcharges(keys: string[], basePriceOf: (baseKey: string) => number, included: number): Map<string, number>;
|
|
1237
|
+
/**
|
|
1238
|
+
* Re-express a portion under a different cut, for when the customer switches
|
|
1239
|
+
* from halves to quarters mid-order. Returns null when neither count divides the
|
|
1240
|
+
* other (halves → thirds), meaning the selection can't be carried over.
|
|
1241
|
+
*/
|
|
1242
|
+
declare function remapPortion(portion: string, nextDivisions: number): string[] | null;
|
|
1243
|
+
/**
|
|
1244
|
+
* Positional section wording, geometry-free — deliberately not `portionLabel`.
|
|
1245
|
+
* Derived words ("Left", "Top left") only exist for a few geometry/division
|
|
1246
|
+
* pairs and need the scheme; a receipt has to say something for every cut.
|
|
1247
|
+
*/
|
|
1248
|
+
declare function sectionLabel(portion?: string | null): string;
|
|
1249
|
+
/** A text glyph for a section, or null when unicode has no character for it. */
|
|
1250
|
+
declare function portionGlyph(portion: string | null | undefined, geometry?: PortionGeometry | null): string | null;
|
|
1251
|
+
interface PortionGroup {
|
|
1252
|
+
portion: string | null;
|
|
1253
|
+
label: string;
|
|
1254
|
+
glyph: string | null;
|
|
1255
|
+
/** The item's rules, each carrying only the selections that land on this section. */
|
|
1256
|
+
selections: RuleSelection[];
|
|
1257
|
+
removals: OrderComponent[];
|
|
1258
|
+
/**
|
|
1259
|
+
* Components present on this section. Whole-item components are the base
|
|
1260
|
+
* recipe — implied by the item's name — so only portioned ones land here,
|
|
1261
|
+
* where "pepperoni on the left" is the whole point of the line.
|
|
1262
|
+
*/
|
|
1263
|
+
additions: OrderComponent[];
|
|
1264
|
+
}
|
|
1265
|
+
/**
|
|
1266
|
+
* One group per covered section: the whole-item group first, then sections in
|
|
1267
|
+
* index order, rules keeping their original order inside each. An item with no
|
|
1268
|
+
* portions anywhere yields exactly one whole-item group, so a surface can render
|
|
1269
|
+
* this unconditionally and show the heading only when `portion_scheme` is set.
|
|
1270
|
+
*
|
|
1271
|
+
* It groups and nothing else — every selection it is handed comes back out. What
|
|
1272
|
+
* counts as worth printing is the surface's call, not this function's.
|
|
1273
|
+
*/
|
|
1274
|
+
declare function groupItemPortions(item: Pick<OrderItem, "selections" | "components" | "portion_scheme">): PortionGroup[];
|
|
1275
|
+
declare function radialSectionPath(index: number, divisions: number, r?: number): string;
|
|
1276
|
+
|
|
1277
|
+
export { type Category, CheckboxField, ClickableField, ConditionalRenderer, type Customer, type CustomizationOption, type CustomizationRule, DateField, DateTime, DateTimeRange, DisclaimerText, DiscreteNumberField, DynamicFormShell, EmailField, FieldError, FieldLabel, GuestCountField, Header, IncrementField, type ItemVariant, type Location, LocationField, type Menu, type MenuItem, NameFields, type Order, type OrderComponent, type OrderItem, PhoneField, Platforms, type PortionGroup, PerPersonSummary as PricePreview, type Promotion, type RecommendationRequest, type RecommendationResult, type RecommendationStrategy, type Rule, type RuleComponent, type RuleItem, type RuleSelection, SectionLabel, type Selection, SliderField, SubmitButton, TextField, type TimeConstraints, TimeField, divisionsFor, groupItemPortions, parsePortion, parsePortionKey, portionGlyph, portionKey, portionLabel, portionRows, portionWeight, radialSectionPath, remapPortion, sectionLabel, selectionWeight, setZorgoBoot, setZorgoPathnameHook, splitUpcharge, useCart, useCateringConfig, useCustomer, useField, useFormStatus, useFormValidity, useFormValues, useHydrateMenu, useHydrateStore, useItemCustomization, useLocation, useMenu, useModal, usePayment, usePromotions, useRecommendations, useRegisterField, weightedUpcharges };
|