@zappie/foundations 0.1.1 → 0.1.2
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/CHANGELOG.md +8 -0
- package/dist/account/index.js +49 -0
- package/dist/account/index.js.map +7 -0
- package/dist/cart/index.js +168 -0
- package/dist/cart/index.js.map +7 -0
- package/dist/fulfilment/address-picker.js +168 -0
- package/dist/fulfilment/address-picker.js.map +7 -0
- package/dist/fulfilment/branch-picker.js +54 -0
- package/dist/fulfilment/branch-picker.js.map +7 -0
- package/dist/fulfilment/schedule.js +146 -0
- package/dist/fulfilment/schedule.js.map +7 -0
- package/dist/fulfilment/switch.js +54 -0
- package/dist/fulfilment/switch.js.map +7 -0
- package/dist/index.js +48 -2114
- package/dist/index.js.map +7 -1
- package/dist/internal/combobox.js +131 -0
- package/dist/internal/combobox.js.map +7 -0
- package/dist/internal/data-attrs.js +8 -0
- package/dist/internal/data-attrs.js.map +7 -0
- package/dist/internal/ids.js +10 -0
- package/dist/internal/ids.js.map +7 -0
- package/dist/{chunk-D3J7S33L.js → internal/slot.js} +13 -6
- package/dist/internal/slot.js.map +7 -0
- package/dist/internal/use-controllable-state.js +29 -0
- package/dist/internal/use-controllable-state.js.map +7 -0
- package/dist/item-form/index.js +13 -0
- package/dist/item-form/index.js.map +7 -0
- package/dist/item-form/option-group.js +268 -0
- package/dist/item-form/option-group.js.map +7 -0
- package/dist/item-form/options.js +30 -0
- package/dist/item-form/options.js.map +7 -0
- package/dist/item-form/quantity.js +131 -0
- package/dist/item-form/quantity.js.map +7 -0
- package/dist/item-form/root.js +151 -0
- package/dist/item-form/root.js.map +7 -0
- package/dist/media/image.js +30 -0
- package/dist/media/image.js.map +7 -0
- package/dist/money.js +20 -0
- package/dist/money.js.map +7 -0
- package/dist/next.js +8 -6
- package/dist/next.js.map +7 -1
- package/dist/otp/input.js +110 -0
- package/dist/otp/input.js.map +7 -0
- package/dist/overlay/engine.js +16 -8
- package/dist/overlay/engine.js.map +7 -1
- package/dist/{chunk-BY2WQGLO.js → overlay/history.js} +9 -4
- package/dist/overlay/history.js.map +7 -0
- package/dist/overlay/react.js +261 -0
- package/dist/overlay/react.js.map +7 -0
- package/dist/payment/methods.js +103 -0
- package/dist/payment/methods.js.map +7 -0
- package/dist/rich-text/banners.js +9 -0
- package/dist/rich-text/banners.js.map +7 -0
- package/dist/rich-text/browser.js +3 -3
- package/dist/rich-text/browser.js.map +7 -1
- package/dist/rich-text/core.js +75 -0
- package/dist/rich-text/core.js.map +7 -0
- package/dist/rich-text/index.js +3 -79
- package/dist/rich-text/index.js.map +7 -1
- package/dist/search/engine.js +93 -0
- package/dist/search/engine.js.map +7 -0
- package/dist/search/index.js +175 -0
- package/dist/search/index.js.map +7 -0
- package/dist/status/hours.js +177 -0
- package/dist/status/hours.js.map +7 -0
- package/dist/status/open-status.js +45 -0
- package/dist/status/open-status.js.map +7 -0
- package/dist/version.js +6 -0
- package/dist/version.js.map +7 -0
- package/package.json +3 -3
- package/dist/chunk-BY2WQGLO.js.map +0 -1
- package/dist/chunk-D3J7S33L.js.map +0 -1
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/item-form/root.tsx
|
|
4
|
+
import {
|
|
5
|
+
previewItem,
|
|
6
|
+
ZappieCartError
|
|
7
|
+
} from "@zappie/sdk";
|
|
8
|
+
import { useCartCatalogue, useZappie } from "@zappie/sdk/react";
|
|
9
|
+
import {
|
|
10
|
+
createContext,
|
|
11
|
+
useCallback,
|
|
12
|
+
useContext,
|
|
13
|
+
useMemo,
|
|
14
|
+
useRef,
|
|
15
|
+
useState
|
|
16
|
+
} from "react";
|
|
17
|
+
import { part } from "../internal/slot.js";
|
|
18
|
+
import { useControllableState } from "../internal/use-controllable-state.js";
|
|
19
|
+
import { jsx } from "react/jsx-runtime";
|
|
20
|
+
var ItemFormStateContext = createContext(null);
|
|
21
|
+
function useItemForm() {
|
|
22
|
+
const value = useContext(ItemFormStateContext);
|
|
23
|
+
if (!value) {
|
|
24
|
+
throw new Error("ItemForm parts require ItemForm.Root");
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
var GroupRegistry = createContext(
|
|
29
|
+
null
|
|
30
|
+
);
|
|
31
|
+
function Root({
|
|
32
|
+
item,
|
|
33
|
+
value,
|
|
34
|
+
defaultValue,
|
|
35
|
+
onValueChange,
|
|
36
|
+
defaultQuantity,
|
|
37
|
+
onAdded,
|
|
38
|
+
onCommit,
|
|
39
|
+
...props
|
|
40
|
+
}) {
|
|
41
|
+
const client = useZappie();
|
|
42
|
+
const menu = useCartCatalogue();
|
|
43
|
+
const [input, setInput] = useControllableState({
|
|
44
|
+
value,
|
|
45
|
+
defaultValue: {
|
|
46
|
+
...defaultValue,
|
|
47
|
+
itemId: item.id,
|
|
48
|
+
quantity: defaultQuantity ?? defaultValue?.quantity ?? item.quantity.min
|
|
49
|
+
},
|
|
50
|
+
onChange: onValueChange
|
|
51
|
+
});
|
|
52
|
+
const registry = useRef(/* @__PURE__ */ new Map());
|
|
53
|
+
const [added, setAdded] = useState(false);
|
|
54
|
+
const [attempted, setAttempted] = useState(false);
|
|
55
|
+
const [failure, setFailure] = useState(null);
|
|
56
|
+
const normalized = useMemo(
|
|
57
|
+
() => ({ ...input, itemId: item.id }),
|
|
58
|
+
[input, item.id]
|
|
59
|
+
);
|
|
60
|
+
const preview = useMemo(
|
|
61
|
+
() => previewItem(item, normalized),
|
|
62
|
+
[item, normalized]
|
|
63
|
+
);
|
|
64
|
+
const validation = useMemo(
|
|
65
|
+
() => client.cart.validate(normalized),
|
|
66
|
+
[client, normalized, menu]
|
|
67
|
+
);
|
|
68
|
+
const issues = failure ?? (attempted && !validation.ok ? validation.issues : []);
|
|
69
|
+
const setValue = useCallback(
|
|
70
|
+
(next) => {
|
|
71
|
+
setAdded(false);
|
|
72
|
+
setFailure(null);
|
|
73
|
+
setInput({ ...next, itemId: item.id });
|
|
74
|
+
},
|
|
75
|
+
[setInput, item.id]
|
|
76
|
+
);
|
|
77
|
+
const setQuantity = useCallback(
|
|
78
|
+
(quantity) => setValue({ ...normalized, quantity }),
|
|
79
|
+
[setValue, normalized]
|
|
80
|
+
);
|
|
81
|
+
const focusIssue = useCallback((errors) => {
|
|
82
|
+
for (const [groupId, element] of registry.current) {
|
|
83
|
+
if (errors.some((issue) => issue.groupId === groupId)) {
|
|
84
|
+
element.focus();
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}, []);
|
|
89
|
+
const add = useCallback(() => {
|
|
90
|
+
const result = client.cart.validate(normalized);
|
|
91
|
+
if (!result.ok) {
|
|
92
|
+
setAttempted(true);
|
|
93
|
+
setFailure(result.issues);
|
|
94
|
+
focusIssue(result.issues);
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
const line = onCommit ? onCommit(normalized) : client.cart.add(item, normalized);
|
|
99
|
+
setAttempted(false);
|
|
100
|
+
setAdded(true);
|
|
101
|
+
onAdded?.(line);
|
|
102
|
+
return line;
|
|
103
|
+
} catch (error) {
|
|
104
|
+
if (error instanceof ZappieCartError) {
|
|
105
|
+
setAttempted(true);
|
|
106
|
+
setFailure([...error.issues]);
|
|
107
|
+
focusIssue([...error.issues]);
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
}, [client, normalized, item, onAdded, onCommit, focusIssue]);
|
|
113
|
+
const context = useMemo(
|
|
114
|
+
() => ({
|
|
115
|
+
item,
|
|
116
|
+
...preview,
|
|
117
|
+
quantity: normalized.quantity ?? item.quantity.min,
|
|
118
|
+
setQuantity,
|
|
119
|
+
issues,
|
|
120
|
+
canAdd: validation.ok && !failure,
|
|
121
|
+
add,
|
|
122
|
+
status: added ? "added" : validation.ok ? "valid" : "incomplete",
|
|
123
|
+
value: normalized,
|
|
124
|
+
setValue
|
|
125
|
+
}),
|
|
126
|
+
[
|
|
127
|
+
item,
|
|
128
|
+
preview,
|
|
129
|
+
normalized,
|
|
130
|
+
setQuantity,
|
|
131
|
+
issues,
|
|
132
|
+
validation.ok,
|
|
133
|
+
failure,
|
|
134
|
+
add,
|
|
135
|
+
added,
|
|
136
|
+
setValue
|
|
137
|
+
]
|
|
138
|
+
);
|
|
139
|
+
return /* @__PURE__ */ jsx(ItemFormStateContext.Provider, { value: context, children: /* @__PURE__ */ jsx(GroupRegistry.Provider, { value: registry.current, children: part("div", props, context, {
|
|
140
|
+
"data-zappie-item": item.id,
|
|
141
|
+
"data-state": issues.length ? "invalid" : "valid",
|
|
142
|
+
"data-sold-out": item.isAvailable ? void 0 : ""
|
|
143
|
+
}) }) });
|
|
144
|
+
}
|
|
145
|
+
export {
|
|
146
|
+
GroupRegistry,
|
|
147
|
+
ItemFormStateContext,
|
|
148
|
+
Root,
|
|
149
|
+
useItemForm
|
|
150
|
+
};
|
|
151
|
+
//# sourceMappingURL=root.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/item-form/root.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\";\nimport {\n previewItem,\n ZappieCartError,\n type CartIssue,\n type CartLine,\n type CartLineInput,\n type Item,\n type Money,\n type OptionGroup,\n} from \"@zappie/sdk\";\nimport { useCartCatalogue, useZappie } from \"@zappie/sdk/react\";\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { part, type PartProps } from \"../internal/slot\";\nimport { useControllableState } from \"../internal/use-controllable-state\";\n/**\n * An SDK option group with the effective rules exposed by the item preview.\n */\nexport type ActiveGroup = OptionGroup;\n/**\n * The current item selection, preview prices, validation issues and actions supplied to item form parts.\n */\nexport type ItemFormContext = {\n item: Item;\n groups: ActiveGroup[];\n quantity: number;\n setQuantity: (quantity: number) => void;\n unitPrice: Money;\n total: Money;\n issues: CartIssue[];\n canAdd: boolean;\n add: () => CartLine | null;\n status: \"incomplete\" | \"valid\" | \"added\";\n value: CartLineInput;\n setValue: (value: CartLineInput) => void;\n};\nexport const ItemFormStateContext = createContext<ItemFormContext | null>(null);\nexport function useItemForm() {\n const value = useContext(ItemFormStateContext);\n if (!value) {\n throw new Error(\"ItemForm parts require ItemForm.Root\");\n }\n return value;\n}\nexport const GroupRegistry = createContext<Map<string, HTMLElement> | null>(\n null,\n);\n/**\n * Item form configuration with controlled or default selections and cart commit callbacks.\n * Supply onCommit to update an existing line instead of adding a new one.\n */\nexport type ItemFormProps = PartProps<ItemFormContext> & {\n item: Item;\n value?: CartLineInput;\n defaultValue?: Partial<CartLineInput>;\n onValueChange?: (value: CartLineInput) => void;\n defaultQuantity?: number;\n onAdded?: (line: CartLine) => void;\n /** Update an existing line through the same validation and focus workflow. */\n onCommit?: (input: CartLineInput) => CartLine;\n};\nexport function Root({\n item,\n value,\n defaultValue,\n onValueChange,\n defaultQuantity,\n onAdded,\n onCommit,\n ...props\n}: ItemFormProps) {\n const client = useZappie();\n const menu = useCartCatalogue();\n const [input, setInput] = useControllableState({\n value,\n defaultValue: {\n ...defaultValue,\n itemId: item.id,\n quantity: defaultQuantity ?? defaultValue?.quantity ?? item.quantity.min,\n },\n onChange: onValueChange,\n });\n const registry = useRef(new Map<string, HTMLElement>());\n const [added, setAdded] = useState(false);\n // Errors show only after the shopper tries to add (PRD 05 5.3), then track live validation.\n const [attempted, setAttempted] = useState(false);\n const [failure, setFailure] = useState<CartIssue[] | null>(null);\n const normalized = useMemo(\n () => ({ ...input, itemId: item.id }),\n [input, item.id],\n );\n const preview = useMemo(\n () => previewItem(item, normalized),\n [item, normalized],\n );\n const validation = useMemo(\n () => client.cart.validate(normalized),\n [client, normalized, menu],\n );\n const issues =\n failure ?? (attempted && !validation.ok ? validation.issues : []);\n const setValue = useCallback(\n (next: CartLineInput) => {\n setAdded(false);\n setFailure(null);\n setInput({ ...next, itemId: item.id });\n },\n [setInput, item.id],\n );\n const setQuantity = useCallback(\n (quantity: number) => setValue({ ...normalized, quantity }),\n [setValue, normalized],\n );\n const focusIssue = useCallback((errors: CartIssue[]) => {\n for (const [groupId, element] of registry.current) {\n if (errors.some((issue) => issue.groupId === groupId)) {\n element.focus();\n break;\n }\n }\n }, []);\n const add = useCallback(() => {\n const result = client.cart.validate(normalized);\n if (!result.ok) {\n setAttempted(true);\n setFailure(result.issues);\n focusIssue(result.issues);\n return null;\n }\n try {\n const line = onCommit\n ? onCommit(normalized)\n : client.cart.add(item, normalized);\n setAttempted(false);\n setAdded(true);\n onAdded?.(line);\n return line;\n } catch (error) {\n if (error instanceof ZappieCartError) {\n setAttempted(true);\n setFailure([...error.issues]);\n focusIssue([...error.issues]);\n return null;\n }\n throw error;\n }\n }, [client, normalized, item, onAdded, onCommit, focusIssue]);\n const context: ItemFormContext = useMemo(\n () => ({\n item,\n ...preview,\n quantity: normalized.quantity ?? item.quantity.min,\n setQuantity,\n issues,\n canAdd: validation.ok && !failure,\n add,\n status: added ? \"added\" : validation.ok ? \"valid\" : \"incomplete\",\n value: normalized,\n setValue,\n }),\n [\n item,\n preview,\n normalized,\n setQuantity,\n issues,\n validation.ok,\n failure,\n add,\n added,\n setValue,\n ],\n );\n return (\n <ItemFormStateContext.Provider value={context}>\n <GroupRegistry.Provider value={registry.current}>\n {part(\"div\", props, context, {\n \"data-zappie-item\": item.id,\n \"data-state\": issues.length ? \"invalid\" : \"valid\",\n \"data-sold-out\": item.isAvailable ? undefined : \"\",\n })}\n </GroupRegistry.Provider>\n </ItemFormStateContext.Provider>\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// src/media/image.tsx
|
|
2
|
+
import { resized, srcSet } from "@zappie/sdk/template";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
function Image({
|
|
5
|
+
src,
|
|
6
|
+
sizes = "100vw",
|
|
7
|
+
priority = false,
|
|
8
|
+
quality,
|
|
9
|
+
mode = "resize",
|
|
10
|
+
alt,
|
|
11
|
+
...props
|
|
12
|
+
}) {
|
|
13
|
+
const responsive = mode === "resize" && /^https?:\/\//.test(src);
|
|
14
|
+
return /* @__PURE__ */ jsx(
|
|
15
|
+
"img",
|
|
16
|
+
{
|
|
17
|
+
...props,
|
|
18
|
+
alt,
|
|
19
|
+
src: responsive ? resized(src, 960, quality) : src,
|
|
20
|
+
...responsive ? { srcSet: srcSet(src, quality), sizes } : {},
|
|
21
|
+
loading: priority ? "eager" : "lazy",
|
|
22
|
+
decoding: priority ? "sync" : "async",
|
|
23
|
+
...priority ? { fetchPriority: "high" } : {}
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
Image
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=image.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/media/image.tsx"],
|
|
4
|
+
"sourcesContent": ["import { resized, srcSet } from \"@zappie/sdk/template\";\nimport type { ImgHTMLAttributes } from \"react\";\n\n/** Props for a responsive storefront image. */\nexport type ImageProps = Omit<\n ImgHTMLAttributes<HTMLImageElement>,\n \"src\" | \"srcSet\"\n> & {\n src: string;\n alt: string;\n sizes?: string;\n priority?: boolean;\n quality?: number;\n mode?: \"resize\" | \"direct\";\n};\n\n/** Render an image through same-origin resizing, or directly when unavailable. */\nexport function Image({\n src,\n sizes = \"100vw\",\n priority = false,\n quality,\n mode = \"resize\",\n alt,\n ...props\n}: ImageProps) {\n const responsive = mode === \"resize\" && /^https?:\\/\\//.test(src);\n return (\n <img\n {...props}\n alt={alt}\n src={responsive ? resized(src, 960, quality) : src}\n {...(responsive ? { srcSet: srcSet(src, quality), sizes } : {})}\n loading={priority ? \"eager\" : \"lazy\"}\n decoding={priority ? \"sync\" : \"async\"}\n {...(priority ? { fetchPriority: \"high\" as const } : {})}\n />\n );\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,SAAS,cAAc;AA4B5B;AAXG,SAAS,MAAM;AAAA,EACpB;AAAA,EACA,QAAQ;AAAA,EACR,WAAW;AAAA,EACX;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA,GAAG;AACL,GAAe;AACb,QAAM,aAAa,SAAS,YAAY,eAAe,KAAK,GAAG;AAC/D,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ;AAAA,MACA,KAAK,aAAa,QAAQ,KAAK,KAAK,OAAO,IAAI;AAAA,MAC9C,GAAI,aAAa,EAAE,QAAQ,OAAO,KAAK,OAAO,GAAG,MAAM,IAAI,CAAC;AAAA,MAC7D,SAAS,WAAW,UAAU;AAAA,MAC9B,UAAU,WAAW,SAAS;AAAA,MAC7B,GAAI,WAAW,EAAE,eAAe,OAAgB,IAAI,CAAC;AAAA;AAAA,EACxD;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/money.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// src/money.tsx
|
|
2
|
+
import {
|
|
3
|
+
format
|
|
4
|
+
} from "@zappie/sdk";
|
|
5
|
+
import { forwardRef } from "react";
|
|
6
|
+
import { part } from "./internal/slot.js";
|
|
7
|
+
var Money = forwardRef(function Money2({ value, formatOptions, ...props }, ref) {
|
|
8
|
+
const formatted = format.money(value, formatOptions);
|
|
9
|
+
return part(
|
|
10
|
+
"data",
|
|
11
|
+
{ ...props, children: props.children ?? formatted },
|
|
12
|
+
{ formatted },
|
|
13
|
+
{ value: String(value.amountMinor) },
|
|
14
|
+
ref
|
|
15
|
+
);
|
|
16
|
+
});
|
|
17
|
+
export {
|
|
18
|
+
Money
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=money.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/money.tsx"],
|
|
4
|
+
"sourcesContent": ["import {\n format,\n type MoneyFormatOptions,\n type Money as MoneyValue,\n} from \"@zappie/sdk\";\nimport { forwardRef } from \"react\";\nimport { part, type PartProps } from \"./internal/slot\";\n/**\n * Render formatted SDK money in a data element, with the minor-unit amount as its value.\n * You can override the content with children or a render function receiving the formatted string.\n */\nexport const Money = forwardRef<\n HTMLElement,\n PartProps<{ formatted: string }> & {\n value: MoneyValue;\n formatOptions?: MoneyFormatOptions;\n }\n>(function Money({ value, formatOptions, ...props }, ref) {\n const formatted = format.money(value, formatOptions);\n return part(\n \"data\",\n { ...props, children: props.children ?? formatted },\n { formatted },\n { value: String(value.amountMinor) },\n ref,\n );\n});\n"],
|
|
5
|
+
"mappings": ";AAAA;AAAA,EACE;AAAA,OAGK;AACP,SAAS,kBAAkB;AAC3B,SAAS,YAA4B;AAK9B,IAAM,QAAQ,WAMnB,SAASA,OAAM,EAAE,OAAO,eAAe,GAAG,MAAM,GAAG,KAAK;AACxD,QAAM,YAAY,OAAO,MAAM,OAAO,aAAa;AACnD,SAAO;AAAA,IACL;AAAA,IACA,EAAE,GAAG,OAAO,UAAU,MAAM,YAAY,UAAU;AAAA,IAClD,EAAE,UAAU;AAAA,IACZ,EAAE,OAAO,OAAO,MAAM,WAAW,EAAE;AAAA,IACnC;AAAA,EACF;AACF,CAAC;",
|
|
6
|
+
"names": ["Money"]
|
|
7
|
+
}
|
package/dist/next.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { LOCATION_EVENT } from './chunk-BY2WQGLO.js';
|
|
3
|
-
export { LOCATION_EVENT as OVERLAY_LOCATION_EVENT } from './chunk-BY2WQGLO.js';
|
|
4
|
-
import { useEffect } from 'react';
|
|
5
2
|
|
|
3
|
+
// src/overlay/next.ts
|
|
4
|
+
import { useEffect } from "react";
|
|
5
|
+
import { LOCATION_EVENT } from "./overlay/history.js";
|
|
6
6
|
var subscribers = 0;
|
|
7
7
|
var uninstall;
|
|
8
8
|
function installShallowHistory() {
|
|
@@ -50,7 +50,9 @@ function installShallowHistory() {
|
|
|
50
50
|
function useNextOverlayBridge() {
|
|
51
51
|
useEffect(installShallowHistory, []);
|
|
52
52
|
}
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
export {
|
|
54
|
+
LOCATION_EVENT as OVERLAY_LOCATION_EVENT,
|
|
55
|
+
installShallowHistory,
|
|
56
|
+
useNextOverlayBridge
|
|
57
|
+
};
|
|
55
58
|
//# sourceMappingURL=next.js.map
|
|
56
|
-
//# sourceMappingURL=next.js.map
|
package/dist/next.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/overlay/next.ts"],
|
|
4
|
+
"sourcesContent": ["\"use client\";\nimport { useEffect } from \"react\";\nimport { LOCATION_EVENT } from \"./history\";\n/**\n * The event overlays re-read the URL on. A host that intercepts `popstate`\n * for its own shallow history (and stops it) must dispatch this too, or open\n * overlays never see Back.\n */\nexport { LOCATION_EVENT as OVERLAY_LOCATION_EVENT };\nlet subscribers = 0;\nlet uninstall: (() => void) | undefined;\n/** Capture same-page shallow moves before Next attempts a server navigation. */\nexport function installShallowHistory() {\n if (typeof window === \"undefined\") {\n return () => {};\n }\n if (subscribers++ === 0) {\n let previous = { base: \"\", pathname: \"\", shallow: false };\n const record = () => {\n previous = {\n base: window.history.state?.__zappieBase ?? window.location.pathname,\n pathname: window.location.pathname,\n shallow: Boolean(window.history.state?.__zappieBase),\n };\n };\n record();\n const onPop = (event: PopStateEvent) => {\n const base = event.state?.__zappieBase ?? window.location.pathname;\n if (\n (Boolean(event.state?.__zappieBase) || previous.shallow) &&\n base === previous.base &&\n window.location.pathname === previous.pathname\n ) {\n event.stopImmediatePropagation();\n record();\n window.dispatchEvent(new Event(LOCATION_EVENT));\n return;\n }\n record();\n };\n window.addEventListener(\"popstate\", onPop, true);\n window.addEventListener(LOCATION_EVENT, record);\n uninstall = () => {\n window.removeEventListener(\"popstate\", onPop, true);\n window.removeEventListener(LOCATION_EVENT, record);\n };\n }\n let released = false;\n return () => {\n if (!released) {\n released = true;\n if (--subscribers === 0) {\n uninstall?.();\n }\n }\n };\n}\n/**\n * Install the shared shallow-history bridge on mount and release it on unmount.\n * Keeps same-page overlay history changes from triggering Next server navigation.\n */\nexport function useNextOverlayBridge() {\n useEffect(installShallowHistory, []);\n}\n"],
|
|
5
|
+
"mappings": ";;;AACA,SAAS,iBAAiB;AAC1B,SAAS,sBAAsB;AAO/B,IAAI,cAAc;AAClB,IAAI;AAEG,SAAS,wBAAwB;AACtC,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,MAAM;AAAA,IAAC;AAAA,EAChB;AACA,MAAI,kBAAkB,GAAG;AACvB,QAAI,WAAW,EAAE,MAAM,IAAI,UAAU,IAAI,SAAS,MAAM;AACxD,UAAM,SAAS,MAAM;AACnB,iBAAW;AAAA,QACT,MAAM,OAAO,QAAQ,OAAO,gBAAgB,OAAO,SAAS;AAAA,QAC5D,UAAU,OAAO,SAAS;AAAA,QAC1B,SAAS,QAAQ,OAAO,QAAQ,OAAO,YAAY;AAAA,MACrD;AAAA,IACF;AACA,WAAO;AACP,UAAM,QAAQ,CAAC,UAAyB;AACtC,YAAM,OAAO,MAAM,OAAO,gBAAgB,OAAO,SAAS;AAC1D,WACG,QAAQ,MAAM,OAAO,YAAY,KAAK,SAAS,YAChD,SAAS,SAAS,QAClB,OAAO,SAAS,aAAa,SAAS,UACtC;AACA,cAAM,yBAAyB;AAC/B,eAAO;AACP,eAAO,cAAc,IAAI,MAAM,cAAc,CAAC;AAC9C;AAAA,MACF;AACA,aAAO;AAAA,IACT;AACA,WAAO,iBAAiB,YAAY,OAAO,IAAI;AAC/C,WAAO,iBAAiB,gBAAgB,MAAM;AAC9C,gBAAY,MAAM;AAChB,aAAO,oBAAoB,YAAY,OAAO,IAAI;AAClD,aAAO,oBAAoB,gBAAgB,MAAM;AAAA,IACnD;AAAA,EACF;AACA,MAAI,WAAW;AACf,SAAO,MAAM;AACX,QAAI,CAAC,UAAU;AACb,iBAAW;AACX,UAAI,EAAE,gBAAgB,GAAG;AACvB,oBAAY;AAAA,MACd;AAAA,IACF;AAAA,EACF;AACF;AAKO,SAAS,uBAAuB;AACrC,YAAU,uBAAuB,CAAC,CAAC;AACrC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/otp/input.tsx
|
|
4
|
+
import {
|
|
5
|
+
forwardRef,
|
|
6
|
+
useEffect,
|
|
7
|
+
useRef
|
|
8
|
+
} from "react";
|
|
9
|
+
import { composeRefs, part } from "../internal/slot.js";
|
|
10
|
+
import { useControllableState } from "../internal/use-controllable-state.js";
|
|
11
|
+
import { jsx } from "react/jsx-runtime";
|
|
12
|
+
function slotAttributes(index, length, value, disabled, update, focus) {
|
|
13
|
+
return {
|
|
14
|
+
type: "text",
|
|
15
|
+
inputMode: "numeric",
|
|
16
|
+
autoComplete: index === 0 ? "one-time-code" : "off",
|
|
17
|
+
"aria-label": `Digit ${index + 1} of ${length}`,
|
|
18
|
+
"data-otp-slot": index,
|
|
19
|
+
value: value[index] ?? "",
|
|
20
|
+
disabled,
|
|
21
|
+
onChange: (event) => update(index, event.target.value),
|
|
22
|
+
onPaste: (event) => {
|
|
23
|
+
event.preventDefault();
|
|
24
|
+
update(index, event.clipboardData.getData("text"));
|
|
25
|
+
},
|
|
26
|
+
onKeyDown: (event) => {
|
|
27
|
+
if (event.key === "Backspace") {
|
|
28
|
+
event.preventDefault();
|
|
29
|
+
const target = value[index] ? index : Math.max(0, index - 1);
|
|
30
|
+
update(target, "");
|
|
31
|
+
focus(target);
|
|
32
|
+
} else if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
|
|
33
|
+
event.preventDefault();
|
|
34
|
+
focus(index + (event.key === "ArrowLeft" ? -1 : 1));
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
onFocus: (event) => event.currentTarget.select()
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
var Input = forwardRef(function Input2({
|
|
41
|
+
length = 6,
|
|
42
|
+
value,
|
|
43
|
+
defaultValue = "",
|
|
44
|
+
onValueChange,
|
|
45
|
+
onComplete,
|
|
46
|
+
disabled = false,
|
|
47
|
+
...props
|
|
48
|
+
}, ref) {
|
|
49
|
+
if (!Number.isInteger(length) || length < 1 || length > 12) {
|
|
50
|
+
throw new RangeError("OTP length must be 1\u201312");
|
|
51
|
+
}
|
|
52
|
+
const [current, setValue] = useControllableState({
|
|
53
|
+
value,
|
|
54
|
+
defaultValue,
|
|
55
|
+
onChange: onValueChange
|
|
56
|
+
});
|
|
57
|
+
const element = useRef(null);
|
|
58
|
+
const previous = useRef("");
|
|
59
|
+
const callback = useRef(onComplete);
|
|
60
|
+
callback.current = onComplete;
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
if (current.length === length && /^\d+$/.test(current) && previous.current !== current) {
|
|
63
|
+
callback.current?.(current);
|
|
64
|
+
}
|
|
65
|
+
previous.current = current;
|
|
66
|
+
}, [current, length]);
|
|
67
|
+
const focus = (index) => element.current?.querySelector(
|
|
68
|
+
`[data-otp-slot="${Math.max(0, Math.min(length - 1, index))}"]`
|
|
69
|
+
)?.focus();
|
|
70
|
+
const update = (index, text) => {
|
|
71
|
+
if (disabled) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const digits = text.replace(/\D/g, "");
|
|
75
|
+
const start = digits.length >= length ? 0 : index;
|
|
76
|
+
const next = (current.slice(0, start) + digits + current.slice(start + Math.max(1, digits.length))).slice(0, length);
|
|
77
|
+
setValue(next);
|
|
78
|
+
if (digits) {
|
|
79
|
+
focus(start + digits.length);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const adopt = useRef(update);
|
|
83
|
+
adopt.current = update;
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
const typed = Array.from(
|
|
86
|
+
element.current?.querySelectorAll("[data-otp-slot]") ?? [],
|
|
87
|
+
(input) => input.value
|
|
88
|
+
).join("");
|
|
89
|
+
if (typed && typed !== current) {
|
|
90
|
+
adopt.current(0, typed);
|
|
91
|
+
}
|
|
92
|
+
}, []);
|
|
93
|
+
const getSlotProps = (index) => slotAttributes(index, length, current, disabled, update, focus);
|
|
94
|
+
const slots = Array.from({ length }, (_, index) => current[index] ?? "");
|
|
95
|
+
return part(
|
|
96
|
+
"div",
|
|
97
|
+
{
|
|
98
|
+
...props,
|
|
99
|
+
children: props.children ?? slots.map((_, index) => /* @__PURE__ */ jsx("input", { ...getSlotProps(index) }, index))
|
|
100
|
+
},
|
|
101
|
+
{ value: current, slots, getSlotProps },
|
|
102
|
+
{ role: "group", "data-disabled": disabled ? "" : void 0 },
|
|
103
|
+
composeRefs(ref, element)
|
|
104
|
+
);
|
|
105
|
+
});
|
|
106
|
+
var Otp = { Input };
|
|
107
|
+
export {
|
|
108
|
+
Otp
|
|
109
|
+
};
|
|
110
|
+
//# sourceMappingURL=input.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/otp/input.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\";\nimport {\n forwardRef,\n useEffect,\n useRef,\n type ChangeEvent,\n type ClipboardEvent,\n type KeyboardEvent,\n} from \"react\";\nimport { composeRefs, part, type PartProps } from \"../internal/slot\";\nimport { useControllableState } from \"../internal/use-controllable-state\";\nexport type OtpState = {\n value: string;\n slots: string[];\n getSlotProps: (index: number) => ReturnType<typeof slotAttributes>;\n};\nfunction slotAttributes(\n index: number,\n length: number,\n value: string,\n disabled: boolean,\n update: (index: number, text: string) => void,\n focus: (index: number) => void,\n) {\n return {\n type: \"text\",\n inputMode: \"numeric\" as const,\n autoComplete: index === 0 ? \"one-time-code\" : \"off\",\n \"aria-label\": `Digit ${index + 1} of ${length}`,\n \"data-otp-slot\": index,\n value: value[index] ?? \"\",\n disabled,\n onChange: (event: ChangeEvent<HTMLInputElement>) =>\n update(index, event.target.value),\n onPaste: (event: ClipboardEvent<HTMLInputElement>) => {\n event.preventDefault();\n update(index, event.clipboardData.getData(\"text\"));\n },\n onKeyDown: (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === \"Backspace\") {\n event.preventDefault();\n const target = value[index] ? index : Math.max(0, index - 1);\n update(target, \"\");\n focus(target);\n } else if (event.key === \"ArrowLeft\" || event.key === \"ArrowRight\") {\n event.preventDefault();\n focus(index + (event.key === \"ArrowLeft\" ? -1 : 1));\n }\n },\n onFocus: (event: { currentTarget: HTMLInputElement }) =>\n event.currentTarget.select(),\n };\n}\nconst Input = forwardRef<\n HTMLElement,\n PartProps<OtpState> & {\n length?: number;\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n onComplete?: (value: string) => void;\n disabled?: boolean;\n }\n>(function Input(\n {\n length = 6,\n value,\n defaultValue = \"\",\n onValueChange,\n onComplete,\n disabled = false,\n ...props\n },\n ref,\n) {\n if (!Number.isInteger(length) || length < 1 || length > 12) {\n throw new RangeError(\"OTP length must be 1\u201312\");\n }\n const [current, setValue] = useControllableState({\n value,\n defaultValue,\n onChange: onValueChange,\n });\n const element = useRef<HTMLElement>(null);\n const previous = useRef(\"\");\n const callback = useRef(onComplete);\n callback.current = onComplete;\n useEffect(() => {\n if (\n current.length === length &&\n /^\\d+$/.test(current) &&\n previous.current !== current\n ) {\n callback.current?.(current);\n }\n previous.current = current;\n }, [current, length]);\n const focus = (index: number) =>\n element.current\n ?.querySelector<HTMLInputElement>(\n `[data-otp-slot=\"${Math.max(0, Math.min(length - 1, index))}\"]`,\n )\n ?.focus();\n const update = (index: number, text: string) => {\n if (disabled) {\n return;\n }\n const digits = text.replace(/\\D/g, \"\");\n const start = digits.length >= length ? 0 : index;\n const next = (\n current.slice(0, start) +\n digits +\n current.slice(start + Math.max(1, digits.length))\n ).slice(0, length);\n setValue(next);\n if (digits) {\n focus(start + digits.length);\n }\n };\n // An SMS code can be autofilled (or typed) before hydration: it sits in the\n // DOM with no change event. Adopt it once the component mounts.\n const adopt = useRef(update);\n adopt.current = update;\n useEffect(() => {\n const typed = Array.from(\n element.current?.querySelectorAll<HTMLInputElement>(\"[data-otp-slot]\") ??\n [],\n (input) => input.value,\n ).join(\"\");\n if (typed && typed !== current) {\n adopt.current(0, typed);\n }\n // Mount only: later edits arrive as change events.\n }, []);\n const getSlotProps = (index: number) =>\n slotAttributes(index, length, current, disabled, update, focus);\n const slots = Array.from({ length }, (_, index) => current[index] ?? \"\");\n return part(\n \"div\",\n {\n ...props,\n children:\n props.children ??\n slots.map((_, index) => <input key={index} {...getSlotProps(index)} />),\n },\n { value: current, slots, getSlotProps },\n { role: \"group\", \"data-disabled\": disabled ? \"\" : undefined },\n composeRefs(ref, element),\n );\n});\n/**\n * A numeric one-time-code input with paste, autofill and keyboard focus handling.\n * Otp.Input defaults to six digits and calls onComplete when a new complete code is entered.\n * You supply code verification.\n */\nexport const Otp = { Input };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Input"]
|
|
7
|
+
}
|
package/dist/overlay/engine.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { partId, part, composeRefs } from '../chunk-D3J7S33L.js';
|
|
3
|
-
import { Dialog } from '@base-ui/react/dialog';
|
|
4
|
-
import { Drawer } from '@base-ui/react/drawer';
|
|
5
|
-
import { createContext, forwardRef, useContext } from 'react';
|
|
6
|
-
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
7
2
|
|
|
3
|
+
// src/overlay/engine.tsx
|
|
4
|
+
import { Dialog } from "@base-ui/react/dialog";
|
|
5
|
+
import { Drawer } from "@base-ui/react/drawer";
|
|
6
|
+
import {
|
|
7
|
+
createContext,
|
|
8
|
+
forwardRef,
|
|
9
|
+
useContext
|
|
10
|
+
} from "react";
|
|
11
|
+
import { composeRefs, part, partId } from "../internal/slot.js";
|
|
12
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
13
|
var PartsContext = createContext(null);
|
|
9
14
|
function useEngineParts() {
|
|
10
15
|
const parts = useContext(PartsContext);
|
|
@@ -166,7 +171,10 @@ var EngineClose = forwardRef(
|
|
|
166
171
|
);
|
|
167
172
|
}
|
|
168
173
|
);
|
|
169
|
-
|
|
170
|
-
|
|
174
|
+
export {
|
|
175
|
+
EngineClose,
|
|
176
|
+
EngineTitle,
|
|
177
|
+
Surface,
|
|
178
|
+
useEngineParts
|
|
179
|
+
};
|
|
171
180
|
//# sourceMappingURL=engine.js.map
|
|
172
|
-
//# sourceMappingURL=engine.js.map
|
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/overlay/engine.tsx"],"names":["EngineTitle","EngineClose"],"mappings":"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","file":"engine.js","sourcesContent":["\"use client\";\n// The overlay engine: the only module that imports Base UI. It loads on first open (or an\n// idle prefetch) so dialog and drawer mechanics stay out of the initial bundle.\nimport { Dialog } from \"@base-ui/react/dialog\";\nimport { Drawer } from \"@base-ui/react/drawer\";\nimport {\n createContext,\n forwardRef,\n useContext,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport { composeRefs, part, partId, type PartProps } from \"../internal/slot\";\n\nexport type Presentation = \"dialog\" | \"drawer\" | \"sheet\";\nexport type SwipeDirection = \"up\" | \"down\" | \"left\" | \"right\";\ntype ChangeDetails = {\n reason: string;\n event: Event;\n cancel: () => void;\n};\nexport type SurfaceProps = {\n open: boolean;\n presentation: Presentation;\n swipeDirection: SwipeDirection;\n /** Ids the trigger points at; caller-supplied ids win. */\n contentId: string;\n titleId?: string | undefined;\n trigger: { current: HTMLElement | null };\n onOpen: () => void;\n onClose: () => void;\n onEscape?: ((event: KeyboardEvent) => void) | undefined;\n onInteractOutside?: ((event: Event) => void) | undefined;\n forceMount?: true | undefined;\n container?: HTMLElement | null | undefined;\n state: unknown;\n contentProps: PartProps<never>;\n contentRef: Ref<HTMLElement>;\n};\ntype Parts = { Title: typeof Dialog.Title; Close: typeof Dialog.Close };\nconst PartsContext = createContext<Parts | null>(null);\nexport function useEngineParts() {\n const parts = useContext(PartsContext);\n if (!parts) {\n throw new Error(\n \"Overlay.Title and Overlay.Close must be inside Overlay.Content\",\n );\n }\n return parts;\n}\n/** Route Base UI's open changes through the URL, letting callbacks cancel a dismissal. */\nfunction changeHandler(props: SurfaceProps) {\n return (open: boolean, details: ChangeDetails) => {\n if (open) {\n props.onOpen();\n return;\n }\n const callback =\n details.reason === \"escape-key\"\n ? (props.onEscape as ((event: Event) => void) | undefined)\n : details.reason === \"outside-press\" || details.reason === \"focus-out\"\n ? props.onInteractOutside\n : undefined;\n callback?.(details.event);\n if (details.event?.defaultPrevented && callback) {\n details.cancel();\n return;\n }\n props.onClose();\n };\n}\nfunction Popup({\n props,\n Component,\n children,\n}: {\n props: SurfaceProps;\n Component: typeof Dialog.Popup;\n children?: ReactNode;\n}) {\n const { contentProps, contentRef, presentation, state } = props;\n const { id: _ownId, ...rest } = contentProps as PartProps<never> & {\n id?: string;\n };\n const id = partId(contentProps as Parameters<typeof partId>[0]);\n return (\n <Component\n id={id ?? props.contentId}\n // Prefer an explicit [data-autofocus] target, else Base UI's first tabbable.\n initialFocus={() =>\n document\n .getElementById(id ?? props.contentId)\n ?.querySelector<HTMLElement>(\"[data-autofocus]\") ?? true\n }\n finalFocus={() => props.trigger.current ?? true}\n render={(baseProps) => {\n const { ref: baseRef, ...base } = baseProps as unknown as Record<\n string,\n unknown\n > & {\n ref?: Ref<HTMLElement>;\n };\n return part(\n \"div\",\n (children === undefined\n ? rest\n : { ...rest, children }) as PartProps<unknown>,\n state,\n {\n ...base,\n \"aria-modal\": true,\n \"data-presentation\": presentation,\n \"data-state\": props.open ? \"open\" : \"closed\",\n },\n composeRefs(baseRef, contentRef),\n );\n }}\n />\n );\n}\nexport function Surface(props: SurfaceProps & { children?: ReactNode }) {\n const { children, forceMount, container, presentation } = props;\n const portal = {\n ...(forceMount ? { keepMounted: true } : {}),\n ...(container !== undefined ? { container } : {}),\n };\n if (presentation === \"dialog\") {\n return (\n <Dialog.Root\n open={props.open}\n onOpenChange={changeHandler(props) as never}\n >\n <PartsContext.Provider\n value={{ Title: Dialog.Title, Close: Dialog.Close }}\n >\n <Dialog.Portal {...portal}>\n {/* Unstyled; templates style [data-zappie-backdrop] with data-state/data-presentation. */}\n <Dialog.Backdrop\n data-zappie-backdrop=\"\"\n data-presentation={presentation}\n data-state={props.open ? \"open\" : \"closed\"}\n />\n <Popup props={props} Component={Dialog.Popup}>\n {children}\n </Popup>\n </Dialog.Portal>\n </PartsContext.Provider>\n </Dialog.Root>\n );\n }\n return (\n <Drawer.Root\n open={props.open}\n onOpenChange={changeHandler(props) as never}\n swipeDirection={props.swipeDirection}\n >\n <PartsContext.Provider\n value={{\n Title: Drawer.Title as typeof Dialog.Title,\n Close: Drawer.Close as typeof Dialog.Close,\n }}\n >\n <Drawer.Portal {...portal}>\n <Drawer.Backdrop\n data-zappie-backdrop=\"\"\n data-presentation={presentation}\n data-state={props.open ? \"open\" : \"closed\"}\n />\n {/* Keeps focused fields visible above the on-screen keyboard in bottom sheets. */}\n <Drawer.VirtualKeyboardProvider>\n <Drawer.Viewport>\n <Popup\n props={props}\n Component={Drawer.Popup as typeof Dialog.Popup}\n >\n {children}\n </Popup>\n </Drawer.Viewport>\n </Drawer.VirtualKeyboardProvider>\n </Drawer.Portal>\n </PartsContext.Provider>\n </Drawer.Root>\n );\n}\n/** Title and Close rendered with whichever engine (dialog or drawer) owns the content. */\ntype EnginePartProps = PartProps<unknown> & {\n id?: string | undefined;\n state: unknown;\n};\nexport const EngineTitle = forwardRef<HTMLElement, EnginePartProps>(\n function EngineTitle({ state, ...props }, ref) {\n const { Title } = useEngineParts();\n const id = partId(props as Parameters<typeof partId>[0]);\n return (\n <Title\n {...(id ? { id } : {})}\n render={(base) => {\n const { ref: baseRef, ...rest } = base as unknown as Record<\n string,\n unknown\n > & {\n ref?: Ref<HTMLElement>;\n };\n return part(\"h2\", props, state, rest, composeRefs(baseRef, ref));\n }}\n />\n );\n },\n);\nexport const EngineClose = forwardRef<HTMLElement, EnginePartProps>(\n function EngineClose({ state, ...props }, ref) {\n const { Close } = useEngineParts();\n return (\n <Close\n render={(base) => {\n const { ref: baseRef, ...rest } = base as unknown as Record<\n string,\n unknown\n > & {\n ref?: Ref<HTMLElement>;\n };\n return part(\n \"button\",\n props,\n state,\n { type: \"button\", ...rest },\n composeRefs(baseRef, ref),\n );\n }}\n />\n );\n },\n);\n"]}
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/overlay/engine.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\";\n// The overlay engine: the only module that imports Base UI. It loads on first open (or an\n// idle prefetch) so dialog and drawer mechanics stay out of the initial bundle.\nimport { Dialog } from \"@base-ui/react/dialog\";\nimport { Drawer } from \"@base-ui/react/drawer\";\nimport {\n createContext,\n forwardRef,\n useContext,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport { composeRefs, part, partId, type PartProps } from \"../internal/slot\";\n\nexport type Presentation = \"dialog\" | \"drawer\" | \"sheet\";\nexport type SwipeDirection = \"up\" | \"down\" | \"left\" | \"right\";\ntype ChangeDetails = {\n reason: string;\n event: Event;\n cancel: () => void;\n};\nexport type SurfaceProps = {\n open: boolean;\n presentation: Presentation;\n swipeDirection: SwipeDirection;\n /** Ids the trigger points at; caller-supplied ids win. */\n contentId: string;\n titleId?: string | undefined;\n trigger: { current: HTMLElement | null };\n onOpen: () => void;\n onClose: () => void;\n onEscape?: ((event: KeyboardEvent) => void) | undefined;\n onInteractOutside?: ((event: Event) => void) | undefined;\n forceMount?: true | undefined;\n container?: HTMLElement | null | undefined;\n state: unknown;\n contentProps: PartProps<never>;\n contentRef: Ref<HTMLElement>;\n};\ntype Parts = { Title: typeof Dialog.Title; Close: typeof Dialog.Close };\nconst PartsContext = createContext<Parts | null>(null);\nexport function useEngineParts() {\n const parts = useContext(PartsContext);\n if (!parts) {\n throw new Error(\n \"Overlay.Title and Overlay.Close must be inside Overlay.Content\",\n );\n }\n return parts;\n}\n/** Route Base UI's open changes through the URL, letting callbacks cancel a dismissal. */\nfunction changeHandler(props: SurfaceProps) {\n return (open: boolean, details: ChangeDetails) => {\n if (open) {\n props.onOpen();\n return;\n }\n const callback =\n details.reason === \"escape-key\"\n ? (props.onEscape as ((event: Event) => void) | undefined)\n : details.reason === \"outside-press\" || details.reason === \"focus-out\"\n ? props.onInteractOutside\n : undefined;\n callback?.(details.event);\n if (details.event?.defaultPrevented && callback) {\n details.cancel();\n return;\n }\n props.onClose();\n };\n}\nfunction Popup({\n props,\n Component,\n children,\n}: {\n props: SurfaceProps;\n Component: typeof Dialog.Popup;\n children?: ReactNode;\n}) {\n const { contentProps, contentRef, presentation, state } = props;\n const { id: _ownId, ...rest } = contentProps as PartProps<never> & {\n id?: string;\n };\n const id = partId(contentProps as Parameters<typeof partId>[0]);\n return (\n <Component\n id={id ?? props.contentId}\n // Prefer an explicit [data-autofocus] target, else Base UI's first tabbable.\n initialFocus={() =>\n document\n .getElementById(id ?? props.contentId)\n ?.querySelector<HTMLElement>(\"[data-autofocus]\") ?? true\n }\n finalFocus={() => props.trigger.current ?? true}\n render={(baseProps) => {\n const { ref: baseRef, ...base } = baseProps as unknown as Record<\n string,\n unknown\n > & {\n ref?: Ref<HTMLElement>;\n };\n return part(\n \"div\",\n (children === undefined\n ? rest\n : { ...rest, children }) as PartProps<unknown>,\n state,\n {\n ...base,\n \"aria-modal\": true,\n \"data-presentation\": presentation,\n \"data-state\": props.open ? \"open\" : \"closed\",\n },\n composeRefs(baseRef, contentRef),\n );\n }}\n />\n );\n}\nexport function Surface(props: SurfaceProps & { children?: ReactNode }) {\n const { children, forceMount, container, presentation } = props;\n const portal = {\n ...(forceMount ? { keepMounted: true } : {}),\n ...(container !== undefined ? { container } : {}),\n };\n if (presentation === \"dialog\") {\n return (\n <Dialog.Root\n open={props.open}\n onOpenChange={changeHandler(props) as never}\n >\n <PartsContext.Provider\n value={{ Title: Dialog.Title, Close: Dialog.Close }}\n >\n <Dialog.Portal {...portal}>\n {/* Unstyled; templates style [data-zappie-backdrop] with data-state/data-presentation. */}\n <Dialog.Backdrop\n data-zappie-backdrop=\"\"\n data-presentation={presentation}\n data-state={props.open ? \"open\" : \"closed\"}\n />\n <Popup props={props} Component={Dialog.Popup}>\n {children}\n </Popup>\n </Dialog.Portal>\n </PartsContext.Provider>\n </Dialog.Root>\n );\n }\n return (\n <Drawer.Root\n open={props.open}\n onOpenChange={changeHandler(props) as never}\n swipeDirection={props.swipeDirection}\n >\n <PartsContext.Provider\n value={{\n Title: Drawer.Title as typeof Dialog.Title,\n Close: Drawer.Close as typeof Dialog.Close,\n }}\n >\n <Drawer.Portal {...portal}>\n <Drawer.Backdrop\n data-zappie-backdrop=\"\"\n data-presentation={presentation}\n data-state={props.open ? \"open\" : \"closed\"}\n />\n {/* Keeps focused fields visible above the on-screen keyboard in bottom sheets. */}\n <Drawer.VirtualKeyboardProvider>\n <Drawer.Viewport>\n <Popup\n props={props}\n Component={Drawer.Popup as typeof Dialog.Popup}\n >\n {children}\n </Popup>\n </Drawer.Viewport>\n </Drawer.VirtualKeyboardProvider>\n </Drawer.Portal>\n </PartsContext.Provider>\n </Drawer.Root>\n );\n}\n/** Title and Close rendered with whichever engine (dialog or drawer) owns the content. */\ntype EnginePartProps = PartProps<unknown> & {\n id?: string | undefined;\n state: unknown;\n};\nexport const EngineTitle = forwardRef<HTMLElement, EnginePartProps>(\n function EngineTitle({ state, ...props }, ref) {\n const { Title } = useEngineParts();\n const id = partId(props as Parameters<typeof partId>[0]);\n return (\n <Title\n {...(id ? { id } : {})}\n render={(base) => {\n const { ref: baseRef, ...rest } = base as unknown as Record<\n string,\n unknown\n > & {\n ref?: Ref<HTMLElement>;\n };\n return part(\"h2\", props, state, rest, composeRefs(baseRef, ref));\n }}\n />\n );\n },\n);\nexport const EngineClose = forwardRef<HTMLElement, EnginePartProps>(\n function EngineClose({ state, ...props }, ref) {\n const { Close } = useEngineParts();\n return (\n <Close\n render={(base) => {\n const { ref: baseRef, ...rest } = base as unknown as Record<\n string,\n unknown\n > & {\n ref?: Ref<HTMLElement>;\n };\n return part(\n \"button\",\n props,\n state,\n { type: \"button\", ...rest },\n composeRefs(baseRef, ref),\n );\n }}\n />\n );\n },\n);\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["EngineTitle", "EngineClose"]
|
|
7
|
+
}
|
|
@@ -91,7 +91,12 @@ function closeOverlay(param, id, options = {}) {
|
|
|
91
91
|
entry && url.searchParams.get(entry.param) === entry.id ? entry : null
|
|
92
92
|
);
|
|
93
93
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
export {
|
|
95
|
+
LOCATION_EVENT,
|
|
96
|
+
closeOverlay,
|
|
97
|
+
getCurrentOverlayEntry,
|
|
98
|
+
locationSnapshot,
|
|
99
|
+
openOverlay,
|
|
100
|
+
subscribeLocation
|
|
101
|
+
};
|
|
102
|
+
//# sourceMappingURL=history.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/overlay/history.ts"],
|
|
4
|
+
"sourcesContent": ["export type OverlayEntry = { param: string; id: string; stack: string[] };\nexport type OverlayQuery = Record<string, string | null | undefined>;\nexport type CloseOptions = {\n fallback?: OverlayQuery | undefined;\n omitParams?: string[] | undefined;\n};\nexport const LOCATION_EVENT = \"zappie:location\";\nexport function getCurrentOverlayEntry(): OverlayEntry | null {\n if (typeof window === \"undefined\") {\n return null;\n }\n const entry = window.history.state?.__zappieOverlay;\n if (\n !entry ||\n typeof entry.param !== \"string\" ||\n typeof entry.id !== \"string\"\n ) {\n return null;\n }\n return {\n param: entry.param,\n id: entry.id,\n stack: Array.isArray(entry.stack)\n ? entry.stack.filter((key: unknown) => typeof key === \"string\")\n : [],\n };\n}\nexport function subscribeLocation(listener: () => void) {\n window.addEventListener(\"popstate\", listener);\n window.addEventListener(LOCATION_EVENT, listener);\n return () => {\n window.removeEventListener(\"popstate\", listener);\n window.removeEventListener(LOCATION_EVENT, listener);\n };\n}\nexport function locationSnapshot() {\n return window.location.search;\n}\nfunction applyQuery(url: URL, query: OverlayQuery) {\n for (const [key, value] of Object.entries(query)) {\n if (value == null) {\n url.searchParams.delete(key);\n } else {\n url.searchParams.set(key, value);\n }\n }\n}\nfunction write(\n type: \"pushState\" | \"replaceState\",\n url: URL,\n overlay: OverlayEntry | null,\n) {\n const state = { ...window.history.state };\n delete state.__zappieOverlay;\n if (overlay) {\n state.__zappieOverlay = overlay;\n }\n state.__zappieBase ??= window.location.pathname;\n if (url.pathname !== window.location.pathname) {\n delete state.__NA;\n delete state.__PRIVATE_NEXTJS_INTERNALS_TREE;\n }\n // Bypass Next's wrapper: shallow overlay writes must not remount the page.\n const prototype = Object.getPrototypeOf(window.history) as History;\n prototype[type].call(window.history, state, \"\", url.href);\n window.dispatchEvent(new Event(LOCATION_EVENT));\n}\nexport function openOverlay(\n param: string,\n id: string,\n query: OverlayQuery = {},\n) {\n const url = new URL(window.location.href);\n applyQuery(url, query);\n url.searchParams.set(param, id);\n if (url.href === window.location.href) {\n return;\n }\n const previous = getCurrentOverlayEntry();\n write(\"pushState\", url, {\n param,\n id,\n stack: [...(previous?.stack ?? []), `${param}:${id}`],\n });\n}\nexport function closeOverlay(\n param: string,\n id?: string,\n options: CloseOptions = {},\n) {\n const url = new URL(window.location.href);\n if (!url.searchParams.has(param)) {\n return;\n }\n const entry = getCurrentOverlayEntry();\n const stack = entry?.stack ?? [];\n const index = id\n ? stack.lastIndexOf(`${param}:${id}`)\n : stack.reduce(\n (found, key, index) => (key.startsWith(`${param}:`) ? index : found),\n -1,\n );\n if (index >= 0) {\n window.history.go(-(stack.length - index));\n return;\n }\n applyQuery(url, options.fallback ?? {});\n if (!options.fallback || !(param in options.fallback)) {\n url.searchParams.delete(param);\n }\n for (const omitted of options.omitParams ?? []) {\n url.searchParams.delete(omitted);\n }\n write(\n \"replaceState\",\n url,\n entry && url.searchParams.get(entry.param) === entry.id ? entry : null,\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["index"]
|
|
7
|
+
}
|