@zappie/foundations 0.1.0 → 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 +35 -0
- package/README.md +30 -253
- 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.d.ts +2 -4
- package/dist/index.js +49 -2113
- 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 +5 -4
- package/dist/chunk-BY2WQGLO.js.map +0 -1
- package/dist/chunk-D3J7S33L.js.map +0 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/internal/ids.ts"],
|
|
4
|
+
"sourcesContent": ["import { useId } from \"react\";\nexport function usePartId(provided?: string) {\n const id = useId();\n return provided ?? `zappie-${id.replace(/[^a-zA-Z0-9_-]/g, \"\")}`;\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,aAAa;AACf,SAAS,UAAU,UAAmB;AAC3C,QAAM,KAAK,MAAM;AACjB,SAAO,YAAY,UAAU,GAAG,QAAQ,mBAAmB,EAAE,CAAC;AAChE;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { Children, isValidElement, cloneElement, createElement } from 'react';
|
|
2
|
-
|
|
3
1
|
// src/internal/slot.tsx
|
|
2
|
+
import {
|
|
3
|
+
Children,
|
|
4
|
+
cloneElement,
|
|
5
|
+
createElement,
|
|
6
|
+
isValidElement
|
|
7
|
+
} from "react";
|
|
4
8
|
function composeRefs(...refs) {
|
|
5
9
|
let cleanups = [];
|
|
6
10
|
return (value) => {
|
|
@@ -75,7 +79,10 @@ function partId(props) {
|
|
|
75
79
|
}
|
|
76
80
|
return void 0;
|
|
77
81
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
export {
|
|
83
|
+
composeRefs,
|
|
84
|
+
mergeProps,
|
|
85
|
+
part,
|
|
86
|
+
partId
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=slot.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/internal/slot.tsx"],
|
|
4
|
+
"sourcesContent": ["import {\n Children,\n cloneElement,\n createElement,\n isValidElement,\n type AllHTMLAttributes,\n type ElementType,\n type ReactElement,\n type ReactNode,\n type Ref,\n} from \"react\";\n/**\n * HTML attributes shared by foundation parts, with optional render-function children.\n * Set asChild to merge the part props and ref into a single child element.\n */\nexport type PartProps<S = Record<string, never>> = Omit<\n AllHTMLAttributes<HTMLElement>,\n \"children\" | \"defaultValue\" | \"value\"\n> & {\n asChild?: boolean;\n children?: ReactNode | ((state: S) => ReactNode);\n};\nexport function composeRefs<T>(...refs: (Ref<T> | undefined)[]): Ref<T> {\n let cleanups: (() => void)[] = [];\n return (value) => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n cleanups = [];\n if (value === null) {\n return;\n }\n for (const ref of refs) {\n if (typeof ref === \"function\") {\n const cleanup = ref(value);\n cleanups.push(\n typeof cleanup === \"function\" ? cleanup : () => ref(null),\n );\n } else if (ref) {\n ref.current = value;\n cleanups.push(() => {\n ref.current = null;\n });\n }\n }\n };\n}\n/** Consumer handlers run first and may cancel the primitive's action. */\nexport function mergeProps(\n base: Record<string, unknown>,\n consumer: Record<string, unknown>,\n) {\n const result = { ...base, ...consumer };\n if (\n typeof base.className === \"string\" &&\n typeof consumer.className === \"string\"\n ) {\n result.className = `${base.className} ${consumer.className}`;\n }\n if (\n base.style &&\n consumer.style &&\n typeof base.style === \"object\" &&\n typeof consumer.style === \"object\"\n ) {\n result.style = { ...base.style, ...consumer.style };\n }\n for (const key of Object.keys(base)) {\n if (\n /^on[A-Z]/.test(key) &&\n typeof base[key] === \"function\" &&\n typeof consumer[key] === \"function\"\n ) {\n result[key] = (event: { defaultPrevented?: boolean }) => {\n (consumer[key] as (event: unknown) => void)(event);\n if (!event.defaultPrevented) {\n (base[key] as (event: unknown) => void)(event);\n }\n };\n }\n }\n return result;\n}\nexport function part<S>(\n tag: ElementType,\n props: PartProps<S>,\n state: S,\n defaults: Record<string, unknown> = {},\n ref?: Ref<HTMLElement>,\n) {\n const { asChild, children, ...dom } = props;\n const content = typeof children === \"function\" ? children(state) : children;\n const merged = mergeProps(defaults, dom);\n if (asChild || (tag === \"input\" && typeof children === \"function\")) {\n const child = Children.only(content);\n if (!isValidElement(child)) {\n throw new Error(\"asChild requires one React element\");\n }\n const element = child as ReactElement<Record<string, unknown>>;\n // React 18 stores ref on the element; React 19 stores it in props.\n const descriptor = Object.getOwnPropertyDescriptor(element, \"ref\");\n const childRef =\n element.props.ref ??\n (descriptor && \"value\" in descriptor ? descriptor.value : undefined);\n return cloneElement(element, {\n ...mergeProps(merged, element.props),\n ref: composeRefs(ref, childRef as Ref<HTMLElement>),\n });\n }\n return createElement(tag, { ...merged, ref }, content);\n}\n/** A part's caller-supplied id, whether passed as a prop or set on its `asChild` element. */\nexport function partId(props: {\n id?: string | undefined;\n asChild?: boolean | undefined;\n children?: unknown;\n}): string | undefined {\n if (props.id) {\n return props.id;\n }\n if (props.asChild && isValidElement(props.children)) {\n const id = (props.children.props as { id?: unknown }).id;\n return typeof id === \"string\" ? id : undefined;\n }\n return undefined;\n}\n"],
|
|
5
|
+
"mappings": ";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAMK;AAYA,SAAS,eAAkB,MAAsC;AACtE,MAAI,WAA2B,CAAC;AAChC,SAAO,CAAC,UAAU;AAChB,eAAW,WAAW,UAAU;AAC9B,cAAQ;AAAA,IACV;AACA,eAAW,CAAC;AACZ,QAAI,UAAU,MAAM;AAClB;AAAA,IACF;AACA,eAAW,OAAO,MAAM;AACtB,UAAI,OAAO,QAAQ,YAAY;AAC7B,cAAM,UAAU,IAAI,KAAK;AACzB,iBAAS;AAAA,UACP,OAAO,YAAY,aAAa,UAAU,MAAM,IAAI,IAAI;AAAA,QAC1D;AAAA,MACF,WAAW,KAAK;AACd,YAAI,UAAU;AACd,iBAAS,KAAK,MAAM;AAClB,cAAI,UAAU;AAAA,QAChB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,WACd,MACA,UACA;AACA,QAAM,SAAS,EAAE,GAAG,MAAM,GAAG,SAAS;AACtC,MACE,OAAO,KAAK,cAAc,YAC1B,OAAO,SAAS,cAAc,UAC9B;AACA,WAAO,YAAY,GAAG,KAAK,SAAS,IAAI,SAAS,SAAS;AAAA,EAC5D;AACA,MACE,KAAK,SACL,SAAS,SACT,OAAO,KAAK,UAAU,YACtB,OAAO,SAAS,UAAU,UAC1B;AACA,WAAO,QAAQ,EAAE,GAAG,KAAK,OAAO,GAAG,SAAS,MAAM;AAAA,EACpD;AACA,aAAW,OAAO,OAAO,KAAK,IAAI,GAAG;AACnC,QACE,WAAW,KAAK,GAAG,KACnB,OAAO,KAAK,GAAG,MAAM,cACrB,OAAO,SAAS,GAAG,MAAM,YACzB;AACA,aAAO,GAAG,IAAI,CAAC,UAA0C;AACvD,QAAC,SAAS,GAAG,EAA+B,KAAK;AACjD,YAAI,CAAC,MAAM,kBAAkB;AAC3B,UAAC,KAAK,GAAG,EAA+B,KAAK;AAAA,QAC/C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AACO,SAAS,KACd,KACA,OACA,OACA,WAAoC,CAAC,GACrC,KACA;AACA,QAAM,EAAE,SAAS,UAAU,GAAG,IAAI,IAAI;AACtC,QAAM,UAAU,OAAO,aAAa,aAAa,SAAS,KAAK,IAAI;AACnE,QAAM,SAAS,WAAW,UAAU,GAAG;AACvC,MAAI,WAAY,QAAQ,WAAW,OAAO,aAAa,YAAa;AAClE,UAAM,QAAQ,SAAS,KAAK,OAAO;AACnC,QAAI,CAAC,eAAe,KAAK,GAAG;AAC1B,YAAM,IAAI,MAAM,oCAAoC;AAAA,IACtD;AACA,UAAM,UAAU;AAEhB,UAAM,aAAa,OAAO,yBAAyB,SAAS,KAAK;AACjE,UAAM,WACJ,QAAQ,MAAM,QACb,cAAc,WAAW,aAAa,WAAW,QAAQ;AAC5D,WAAO,aAAa,SAAS;AAAA,MAC3B,GAAG,WAAW,QAAQ,QAAQ,KAAK;AAAA,MACnC,KAAK,YAAY,KAAK,QAA4B;AAAA,IACpD,CAAC;AAAA,EACH;AACA,SAAO,cAAc,KAAK,EAAE,GAAG,QAAQ,IAAI,GAAG,OAAO;AACvD;AAEO,SAAS,OAAO,OAIA;AACrB,MAAI,MAAM,IAAI;AACZ,WAAO,MAAM;AAAA,EACf;AACA,MAAI,MAAM,WAAW,eAAe,MAAM,QAAQ,GAAG;AACnD,UAAM,KAAM,MAAM,SAAS,MAA2B;AACtD,WAAO,OAAO,OAAO,WAAW,KAAK;AAAA,EACvC;AACA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/internal/use-controllable-state.ts
|
|
2
|
+
import { useCallback, useRef, useState } from "react";
|
|
3
|
+
function useControllableState({
|
|
4
|
+
value,
|
|
5
|
+
defaultValue,
|
|
6
|
+
onChange
|
|
7
|
+
}) {
|
|
8
|
+
const [internal, setInternal] = useState(defaultValue);
|
|
9
|
+
const current = value === void 0 ? internal : value;
|
|
10
|
+
const latest = useRef({ current, onChange, controlled: value !== void 0 });
|
|
11
|
+
latest.current = { current, onChange, controlled: value !== void 0 };
|
|
12
|
+
const set = useCallback((next) => {
|
|
13
|
+
const snapshot = latest.current;
|
|
14
|
+
const resolved = typeof next === "function" ? next(snapshot.current) : next;
|
|
15
|
+
if (Object.is(resolved, snapshot.current)) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (!snapshot.controlled) {
|
|
19
|
+
latest.current.current = resolved;
|
|
20
|
+
setInternal(resolved);
|
|
21
|
+
}
|
|
22
|
+
snapshot.onChange?.(resolved);
|
|
23
|
+
}, []);
|
|
24
|
+
return [current, set];
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
useControllableState
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=use-controllable-state.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/internal/use-controllable-state.ts"],
|
|
4
|
+
"sourcesContent": ["import { useCallback, useRef, useState } from \"react\";\n/**\n * Manage either a supplied value or internal state initialized from defaultValue.\n * The setter accepts a value or updater and calls onChange only when Object.is detects a change.\n *\n * @returns The current value and a stable setter. A defined value keeps state controlled by you.\n */\nexport function useControllableState<T>({\n value,\n defaultValue,\n onChange,\n}: {\n value?: T | undefined;\n defaultValue: T;\n onChange?: ((value: T) => void) | undefined;\n}) {\n const [internal, setInternal] = useState(defaultValue);\n const current = value === undefined ? internal : value;\n const latest = useRef({ current, onChange, controlled: value !== undefined });\n latest.current = { current, onChange, controlled: value !== undefined };\n const set = useCallback((next: T | ((previous: T) => T)) => {\n const snapshot = latest.current;\n const resolved =\n typeof next === \"function\"\n ? (next as (previous: T) => T)(snapshot.current)\n : next;\n if (Object.is(resolved, snapshot.current)) {\n return;\n }\n if (!snapshot.controlled) {\n latest.current.current = resolved;\n setInternal(resolved);\n }\n snapshot.onChange?.(resolved);\n }, []);\n return [current, set] as const;\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,aAAa,QAAQ,gBAAgB;AAOvC,SAAS,qBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,YAAY;AACrD,QAAM,UAAU,UAAU,SAAY,WAAW;AACjD,QAAM,SAAS,OAAO,EAAE,SAAS,UAAU,YAAY,UAAU,OAAU,CAAC;AAC5E,SAAO,UAAU,EAAE,SAAS,UAAU,YAAY,UAAU,OAAU;AACtE,QAAM,MAAM,YAAY,CAAC,SAAmC;AAC1D,UAAM,WAAW,OAAO;AACxB,UAAM,WACJ,OAAO,SAAS,aACX,KAA4B,SAAS,OAAO,IAC7C;AACN,QAAI,OAAO,GAAG,UAAU,SAAS,OAAO,GAAG;AACzC;AAAA,IACF;AACA,QAAI,CAAC,SAAS,YAAY;AACxB,aAAO,QAAQ,UAAU;AACzB,kBAAY,QAAQ;AAAA,IACtB;AACA,aAAS,WAAW,QAAQ;AAAA,EAC9B,GAAG,CAAC,CAAC;AACL,SAAO,CAAC,SAAS,GAAG;AACtB;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// src/item-form/index.ts
|
|
2
|
+
import { Add, Options } from "./options.js";
|
|
3
|
+
import { Root } from "./root.js";
|
|
4
|
+
import { Choice, OptionGroup } from "./option-group.js";
|
|
5
|
+
import { Quantity } from "./quantity.js";
|
|
6
|
+
var ItemForm = { Root, Options, Add };
|
|
7
|
+
export {
|
|
8
|
+
Choice,
|
|
9
|
+
ItemForm,
|
|
10
|
+
OptionGroup,
|
|
11
|
+
Quantity
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/item-form/index.ts"],
|
|
4
|
+
"sourcesContent": ["import { Add, Options } from \"./options\";\nimport { Root } from \"./root\";\n/**\n * Composable item configuration parts for selecting options, validating a line and adding it to the cart.\n * Use ItemForm.Root within your ZappieProvider and place Options and Add inside it.\n */\nexport const ItemForm = { Root, Options, Add };\nexport { Choice, OptionGroup } from \"./option-group\";\nexport { Quantity } from \"./quantity\";\nexport type { QuantityProps, QuantityState } from \"./quantity\";\nexport type { ActiveGroup, ItemFormContext, ItemFormProps } from \"./root\";\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,KAAK,eAAe;AAC7B,SAAS,YAAY;AAMrB,SAAS,QAAQ,mBAAmB;AACpC,SAAS,gBAAgB;AAFlB,IAAM,WAAW,EAAE,MAAM,SAAS,IAAI;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/item-form/option-group.tsx
|
|
4
|
+
import {
|
|
5
|
+
createContext,
|
|
6
|
+
forwardRef,
|
|
7
|
+
memo,
|
|
8
|
+
useContext,
|
|
9
|
+
useMemo,
|
|
10
|
+
useRef
|
|
11
|
+
} from "react";
|
|
12
|
+
import { flag } from "../internal/data-attrs.js";
|
|
13
|
+
import { usePartId } from "../internal/ids.js";
|
|
14
|
+
import { composeRefs, part } from "../internal/slot.js";
|
|
15
|
+
import { GroupRegistry, useItemForm } from "./root.js";
|
|
16
|
+
import { jsx } from "react/jsx-runtime";
|
|
17
|
+
var Context = createContext(null);
|
|
18
|
+
function useGroup() {
|
|
19
|
+
const value = useContext(Context);
|
|
20
|
+
if (!value) {
|
|
21
|
+
throw new Error("Choice and OptionGroup.Input require OptionGroup");
|
|
22
|
+
}
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
var Group = forwardRef(function OptionGroup({ group: supplied, ...props }, ref) {
|
|
26
|
+
const ctx = useItemForm();
|
|
27
|
+
const registry = useContext(GroupRegistry);
|
|
28
|
+
const group = ctx.groups.find((candidate) => candidate.id === supplied.id) ?? supplied;
|
|
29
|
+
const mine = ctx.value.choices?.filter((choice) => choice.groupId === group.id) ?? [];
|
|
30
|
+
const selected = mine.map((choice) => choice.choiceId);
|
|
31
|
+
const quantities = Object.fromEntries(
|
|
32
|
+
mine.map((choice) => [choice.choiceId, choice.quantity ?? 1])
|
|
33
|
+
);
|
|
34
|
+
const invalid = ctx.issues.some((issue) => issue.groupId === group.id);
|
|
35
|
+
const input = ctx.value.inputs?.[group.id] ?? "";
|
|
36
|
+
const latest = useRef({ ctx, group });
|
|
37
|
+
latest.current = { ctx, group };
|
|
38
|
+
const actions = useMemo(
|
|
39
|
+
() => ({
|
|
40
|
+
toggle: (id) => {
|
|
41
|
+
const { ctx: ctx2, group: group2 } = latest.current;
|
|
42
|
+
const choice = group2.choices.find((candidate) => candidate.id === id);
|
|
43
|
+
if (!choice?.isAvailable) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const previous = ctx2.value.choices ?? [];
|
|
47
|
+
const chosen = previous.some(
|
|
48
|
+
(candidate) => candidate.groupId === group2.id && candidate.choiceId === id
|
|
49
|
+
);
|
|
50
|
+
let choices = previous.filter(
|
|
51
|
+
(candidate) => candidate.groupId !== group2.id || group2.selection.max !== 1 && candidate.choiceId !== id
|
|
52
|
+
);
|
|
53
|
+
if (!chosen || group2.selection.max === 1 && group2.required) {
|
|
54
|
+
choices = [
|
|
55
|
+
...choices,
|
|
56
|
+
{
|
|
57
|
+
groupId: group2.id,
|
|
58
|
+
choiceId: id,
|
|
59
|
+
quantity: choice.quantity?.min ?? 1
|
|
60
|
+
}
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
const inputs = { ...ctx2.value.inputs };
|
|
64
|
+
delete inputs[group2.id];
|
|
65
|
+
ctx2.setValue({ ...ctx2.value, choices, inputs });
|
|
66
|
+
},
|
|
67
|
+
setQuantity: (id, quantity) => {
|
|
68
|
+
const { ctx: ctx2, group: group2 } = latest.current;
|
|
69
|
+
const choice = group2.choices.find((candidate) => candidate.id === id);
|
|
70
|
+
if (!choice?.isAvailable || !Number.isInteger(quantity)) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const others = (ctx2.value.choices ?? []).filter(
|
|
74
|
+
(candidate) => candidate.groupId !== group2.id || group2.selection.max !== 1 && candidate.choiceId !== id
|
|
75
|
+
);
|
|
76
|
+
if (quantity <= 0) {
|
|
77
|
+
ctx2.setValue({
|
|
78
|
+
...ctx2.value,
|
|
79
|
+
choices: (ctx2.value.choices ?? []).filter(
|
|
80
|
+
(candidate) => candidate.groupId !== group2.id || candidate.choiceId !== id
|
|
81
|
+
)
|
|
82
|
+
});
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const min = choice.quantity?.min ?? 1;
|
|
86
|
+
const max = choice.quantity?.max ?? 99;
|
|
87
|
+
ctx2.setValue({
|
|
88
|
+
...ctx2.value,
|
|
89
|
+
choices: [
|
|
90
|
+
...others,
|
|
91
|
+
{
|
|
92
|
+
groupId: group2.id,
|
|
93
|
+
choiceId: id,
|
|
94
|
+
quantity: Math.min(max, Math.max(min, quantity))
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
});
|
|
98
|
+
},
|
|
99
|
+
setInput: (value) => {
|
|
100
|
+
const { ctx: ctx2, group: group2 } = latest.current;
|
|
101
|
+
ctx2.setValue({
|
|
102
|
+
...ctx2.value,
|
|
103
|
+
choices: (ctx2.value.choices ?? []).filter(
|
|
104
|
+
(choice) => choice.groupId !== group2.id
|
|
105
|
+
),
|
|
106
|
+
inputs: {
|
|
107
|
+
...ctx2.value.inputs,
|
|
108
|
+
[group2.id]: value.slice(0, group2.input?.maxLength ?? 500)
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}),
|
|
113
|
+
[]
|
|
114
|
+
);
|
|
115
|
+
const selectionKey = JSON.stringify(quantities);
|
|
116
|
+
const state = useMemo(
|
|
117
|
+
() => ({ group, selected, quantities, invalid, input, ...actions }),
|
|
118
|
+
[group, selectionKey, invalid, input, actions]
|
|
119
|
+
);
|
|
120
|
+
const single = group.kind === "select" && group.selection.max === 1;
|
|
121
|
+
return /* @__PURE__ */ jsx(Context.Provider, { value: state, children: part(
|
|
122
|
+
"div",
|
|
123
|
+
props,
|
|
124
|
+
state,
|
|
125
|
+
{
|
|
126
|
+
role: single ? "radiogroup" : "group",
|
|
127
|
+
tabIndex: -1,
|
|
128
|
+
"aria-label": group.name,
|
|
129
|
+
"aria-required": single ? group.required : void 0,
|
|
130
|
+
"aria-invalid": invalid || void 0,
|
|
131
|
+
"data-invalid": flag(invalid),
|
|
132
|
+
"data-state": invalid ? "invalid" : "valid",
|
|
133
|
+
"data-zappie-option-group": group.id,
|
|
134
|
+
onKeyDown: (event) => {
|
|
135
|
+
if (!single || ![
|
|
136
|
+
"ArrowDown",
|
|
137
|
+
"ArrowRight",
|
|
138
|
+
"ArrowUp",
|
|
139
|
+
"ArrowLeft",
|
|
140
|
+
"Home",
|
|
141
|
+
"End"
|
|
142
|
+
].includes(event.key)) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const choices = Array.from(
|
|
146
|
+
event.currentTarget.querySelectorAll(
|
|
147
|
+
'[role="radio"]:not([aria-disabled="true"])'
|
|
148
|
+
)
|
|
149
|
+
);
|
|
150
|
+
if (!choices.length) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const current = choices.indexOf(
|
|
154
|
+
document.activeElement
|
|
155
|
+
);
|
|
156
|
+
const index = event.key === "Home" ? 0 : event.key === "End" ? choices.length - 1 : (current + (event.key === "ArrowUp" || event.key === "ArrowLeft" ? -1 : 1) + choices.length) % choices.length;
|
|
157
|
+
event.preventDefault();
|
|
158
|
+
choices[index]?.focus();
|
|
159
|
+
choices[index]?.click();
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
composeRefs(ref, (node) => {
|
|
163
|
+
if (node) {
|
|
164
|
+
registry.set(group.id, node);
|
|
165
|
+
} else {
|
|
166
|
+
registry.delete(group.id);
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
) });
|
|
170
|
+
});
|
|
171
|
+
var ChoiceView = memo(
|
|
172
|
+
forwardRef(function ChoiceView2({
|
|
173
|
+
choice,
|
|
174
|
+
selected,
|
|
175
|
+
single,
|
|
176
|
+
tabIndex,
|
|
177
|
+
quantity,
|
|
178
|
+
toggleChoice,
|
|
179
|
+
setChoiceQuantity,
|
|
180
|
+
...props
|
|
181
|
+
}, ref) {
|
|
182
|
+
const toggle = () => toggleChoice(choice.id);
|
|
183
|
+
const state = {
|
|
184
|
+
choice,
|
|
185
|
+
selected,
|
|
186
|
+
disabled: !choice.isAvailable,
|
|
187
|
+
toggle,
|
|
188
|
+
quantity,
|
|
189
|
+
min: choice.quantity?.min ?? 1,
|
|
190
|
+
max: choice.quantity?.max ?? 99,
|
|
191
|
+
setQuantity: (next) => setChoiceQuantity(choice.id, next)
|
|
192
|
+
};
|
|
193
|
+
return part(
|
|
194
|
+
"button",
|
|
195
|
+
props,
|
|
196
|
+
state,
|
|
197
|
+
{
|
|
198
|
+
type: "button",
|
|
199
|
+
role: single ? "radio" : "checkbox",
|
|
200
|
+
tabIndex,
|
|
201
|
+
"aria-checked": selected,
|
|
202
|
+
"aria-disabled": !choice.isAvailable,
|
|
203
|
+
disabled: !choice.isAvailable,
|
|
204
|
+
"data-selected": flag(selected),
|
|
205
|
+
"data-sold-out": flag(!choice.isAvailable),
|
|
206
|
+
"data-disabled": flag(!choice.isAvailable),
|
|
207
|
+
"data-state": selected ? "checked" : "unchecked",
|
|
208
|
+
"data-zappie-option": choice.id,
|
|
209
|
+
onClick: toggle
|
|
210
|
+
},
|
|
211
|
+
ref
|
|
212
|
+
);
|
|
213
|
+
})
|
|
214
|
+
);
|
|
215
|
+
var Choice = forwardRef(function Choice2(props, ref) {
|
|
216
|
+
const ctx = useGroup();
|
|
217
|
+
const single = ctx.group.selection.max === 1;
|
|
218
|
+
const selected = ctx.selected.includes(props.choice.id);
|
|
219
|
+
const first = ctx.group.choices.find((choice) => choice.isAvailable);
|
|
220
|
+
const tabIndex = !single || selected || !ctx.selected.length && first?.id === props.choice.id ? 0 : -1;
|
|
221
|
+
return /* @__PURE__ */ jsx(
|
|
222
|
+
ChoiceView,
|
|
223
|
+
{
|
|
224
|
+
...props,
|
|
225
|
+
ref,
|
|
226
|
+
selected,
|
|
227
|
+
single,
|
|
228
|
+
tabIndex,
|
|
229
|
+
quantity: ctx.quantities[props.choice.id] ?? 0,
|
|
230
|
+
toggleChoice: ctx.toggle,
|
|
231
|
+
setChoiceQuantity: ctx.setQuantity
|
|
232
|
+
}
|
|
233
|
+
);
|
|
234
|
+
});
|
|
235
|
+
var Input = forwardRef(
|
|
236
|
+
function Input2(props, ref) {
|
|
237
|
+
const ctx = useGroup();
|
|
238
|
+
const id = usePartId(props.id);
|
|
239
|
+
const toggle = ctx.group.kind === "toggle";
|
|
240
|
+
return part(
|
|
241
|
+
"input",
|
|
242
|
+
props,
|
|
243
|
+
ctx,
|
|
244
|
+
{
|
|
245
|
+
id,
|
|
246
|
+
type: toggle ? "checkbox" : ctx.group.kind === "select" ? "text" : ctx.group.kind,
|
|
247
|
+
value: toggle ? void 0 : ctx.input,
|
|
248
|
+
checked: toggle ? ctx.input === "true" : void 0,
|
|
249
|
+
required: ctx.group.required,
|
|
250
|
+
"aria-label": ctx.group.name,
|
|
251
|
+
"aria-invalid": ctx.invalid || void 0,
|
|
252
|
+
"data-invalid": flag(ctx.invalid),
|
|
253
|
+
maxLength: ctx.group.input?.maxLength ?? 500,
|
|
254
|
+
placeholder: ctx.group.input?.placeholder,
|
|
255
|
+
onChange: (event) => ctx.setInput(
|
|
256
|
+
toggle ? String(event.target.checked) : event.target.value
|
|
257
|
+
)
|
|
258
|
+
},
|
|
259
|
+
ref
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
);
|
|
263
|
+
var OptionGroup2 = Object.assign(Group, { Input });
|
|
264
|
+
export {
|
|
265
|
+
Choice,
|
|
266
|
+
OptionGroup2 as OptionGroup
|
|
267
|
+
};
|
|
268
|
+
//# sourceMappingURL=option-group.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/item-form/option-group.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\";\nimport type {\n Choice as ChoiceModel,\n OptionGroup as GroupModel,\n} from \"@zappie/sdk\";\nimport {\n createContext,\n forwardRef,\n memo,\n useContext,\n useMemo,\n useRef,\n type ChangeEvent,\n type KeyboardEvent,\n} from \"react\";\nimport { flag } from \"../internal/data-attrs\";\nimport { usePartId } from \"../internal/ids\";\nimport { composeRefs, part, type PartProps } from \"../internal/slot\";\nimport { GroupRegistry, useItemForm } from \"./root\";\ntype GroupState = {\n group: GroupModel;\n selected: string[];\n invalid: boolean;\n input: string;\n setInput: (value: string) => void;\n toggle: (id: string) => void;\n quantities: Readonly<Record<string, number>>;\n /** Set a choice's quantity within its bounds. Zero deselects it. A positive value selects it. */\n setQuantity: (id: string, quantity: number) => void;\n};\nconst Context = createContext<GroupState | null>(null);\nfunction useGroup() {\n const value = useContext(Context);\n if (!value) {\n throw new Error(\"Choice and OptionGroup.Input require OptionGroup\");\n }\n return value;\n}\nconst Group = forwardRef<\n HTMLElement,\n PartProps<GroupState> & { group: GroupModel }\n>(function OptionGroup({ group: supplied, ...props }, ref) {\n const ctx = useItemForm();\n const registry = useContext(GroupRegistry)!;\n const group =\n ctx.groups.find((candidate) => candidate.id === supplied.id) ?? supplied;\n const mine =\n ctx.value.choices?.filter((choice) => choice.groupId === group.id) ?? [];\n const selected = mine.map((choice) => choice.choiceId);\n const quantities = Object.fromEntries(\n mine.map((choice) => [choice.choiceId, choice.quantity ?? 1]),\n );\n const invalid = ctx.issues.some((issue) => issue.groupId === group.id);\n const input = ctx.value.inputs?.[group.id] ?? \"\";\n const latest = useRef({ ctx, group });\n latest.current = { ctx, group };\n const actions = useMemo(\n () => ({\n toggle: (id: string) => {\n const { ctx, group } = latest.current;\n const choice = group.choices.find((candidate) => candidate.id === id);\n if (!choice?.isAvailable) {\n return;\n }\n const previous = ctx.value.choices ?? [];\n const chosen = previous.some(\n (candidate) =>\n candidate.groupId === group.id && candidate.choiceId === id,\n );\n let choices = previous.filter(\n (candidate) =>\n candidate.groupId !== group.id ||\n (group.selection.max !== 1 && candidate.choiceId !== id),\n );\n if (!chosen || (group.selection.max === 1 && group.required)) {\n choices = [\n ...choices,\n {\n groupId: group.id,\n choiceId: id,\n quantity: choice.quantity?.min ?? 1,\n },\n ];\n }\n const inputs = { ...ctx.value.inputs };\n delete inputs[group.id];\n ctx.setValue({ ...ctx.value, choices, inputs });\n },\n setQuantity: (id: string, quantity: number) => {\n const { ctx, group } = latest.current;\n const choice = group.choices.find((candidate) => candidate.id === id);\n if (!choice?.isAvailable || !Number.isInteger(quantity)) {\n return;\n }\n const others = (ctx.value.choices ?? []).filter(\n (candidate) =>\n candidate.groupId !== group.id ||\n (group.selection.max !== 1 && candidate.choiceId !== id),\n );\n if (quantity <= 0) {\n ctx.setValue({\n ...ctx.value,\n choices: (ctx.value.choices ?? []).filter(\n (candidate) =>\n candidate.groupId !== group.id || candidate.choiceId !== id,\n ),\n });\n return;\n }\n const min = choice.quantity?.min ?? 1;\n const max = choice.quantity?.max ?? 99;\n ctx.setValue({\n ...ctx.value,\n choices: [\n ...others,\n {\n groupId: group.id,\n choiceId: id,\n quantity: Math.min(max, Math.max(min, quantity)),\n },\n ],\n });\n },\n setInput: (value: string) => {\n const { ctx, group } = latest.current;\n ctx.setValue({\n ...ctx.value,\n choices: (ctx.value.choices ?? []).filter(\n (choice) => choice.groupId !== group.id,\n ),\n inputs: {\n ...ctx.value.inputs,\n [group.id]: value.slice(0, group.input?.maxLength ?? 500),\n },\n });\n },\n }),\n [],\n );\n const selectionKey = JSON.stringify(quantities);\n const state = useMemo(\n () => ({ group, selected, quantities, invalid, input, ...actions }),\n [group, selectionKey, invalid, input, actions],\n );\n const single = group.kind === \"select\" && group.selection.max === 1;\n return (\n <Context.Provider value={state}>\n {part(\n \"div\",\n props,\n state,\n {\n role: single ? \"radiogroup\" : \"group\",\n tabIndex: -1,\n \"aria-label\": group.name,\n \"aria-required\": single ? group.required : undefined,\n \"aria-invalid\": invalid || undefined,\n \"data-invalid\": flag(invalid),\n \"data-state\": invalid ? \"invalid\" : \"valid\",\n \"data-zappie-option-group\": group.id,\n onKeyDown: (event: KeyboardEvent<HTMLElement>) => {\n if (\n !single ||\n ![\n \"ArrowDown\",\n \"ArrowRight\",\n \"ArrowUp\",\n \"ArrowLeft\",\n \"Home\",\n \"End\",\n ].includes(event.key)\n ) {\n return;\n }\n const choices = Array.from(\n event.currentTarget.querySelectorAll<HTMLElement>(\n '[role=\"radio\"]:not([aria-disabled=\"true\"])',\n ),\n );\n if (!choices.length) {\n return;\n }\n const current = choices.indexOf(\n document.activeElement as HTMLElement,\n );\n const index =\n event.key === \"Home\"\n ? 0\n : event.key === \"End\"\n ? choices.length - 1\n : (current +\n (event.key === \"ArrowUp\" || event.key === \"ArrowLeft\"\n ? -1\n : 1) +\n choices.length) %\n choices.length;\n event.preventDefault();\n choices[index]?.focus();\n choices[index]?.click();\n },\n },\n composeRefs(ref, (node) => {\n if (node) {\n registry.set(group.id, node);\n } else {\n registry.delete(group.id);\n }\n }),\n )}\n </Context.Provider>\n );\n});\ntype ChoiceState = {\n choice: ChoiceModel;\n selected: boolean;\n disabled: boolean;\n toggle: () => void;\n /** Selected quantity (0 when unselected) and the choice's bounds. */\n quantity: number;\n min: number;\n max: number;\n setQuantity: (quantity: number) => void;\n};\nconst ChoiceView = memo(\n forwardRef<\n HTMLElement,\n PartProps<ChoiceState> & {\n choice: ChoiceModel;\n selected: boolean;\n single: boolean;\n tabIndex: number;\n quantity: number;\n toggleChoice: (id: string) => void;\n setChoiceQuantity: (id: string, quantity: number) => void;\n }\n >(function ChoiceView(\n {\n choice,\n selected,\n single,\n tabIndex,\n quantity,\n toggleChoice,\n setChoiceQuantity,\n ...props\n },\n ref,\n ) {\n const toggle = () => toggleChoice(choice.id);\n const state = {\n choice,\n selected,\n disabled: !choice.isAvailable,\n toggle,\n quantity,\n min: choice.quantity?.min ?? 1,\n max: choice.quantity?.max ?? 99,\n setQuantity: (next: number) => setChoiceQuantity(choice.id, next),\n };\n return part(\n \"button\",\n props,\n state,\n {\n type: \"button\",\n role: single ? \"radio\" : \"checkbox\",\n tabIndex,\n \"aria-checked\": selected,\n \"aria-disabled\": !choice.isAvailable,\n disabled: !choice.isAvailable,\n \"data-selected\": flag(selected),\n \"data-sold-out\": flag(!choice.isAvailable),\n \"data-disabled\": flag(!choice.isAvailable),\n \"data-state\": selected ? \"checked\" : \"unchecked\",\n \"data-zappie-option\": choice.id,\n onClick: toggle,\n },\n ref,\n );\n }),\n);\n/**\n * Render a selectable option within an OptionGroup, with radio or checkbox semantics.\n * Exposes selection and quantity controls and disables unavailable choices.\n */\nexport const Choice = forwardRef<\n HTMLElement,\n PartProps<ChoiceState> & { choice: ChoiceModel }\n>(function Choice(props, ref) {\n const ctx = useGroup();\n const single = ctx.group.selection.max === 1;\n const selected = ctx.selected.includes(props.choice.id);\n const first = ctx.group.choices.find((choice) => choice.isAvailable);\n const tabIndex =\n !single ||\n selected ||\n (!ctx.selected.length && first?.id === props.choice.id)\n ? 0\n : -1;\n return (\n <ChoiceView\n {...props}\n ref={ref}\n selected={selected}\n single={single}\n tabIndex={tabIndex}\n quantity={ctx.quantities[props.choice.id] ?? 0}\n toggleChoice={ctx.toggle}\n setChoiceQuantity={ctx.setQuantity}\n />\n );\n});\nconst Input = forwardRef<HTMLElement, PartProps<GroupState>>(\n function Input(props, ref) {\n const ctx = useGroup();\n const id = usePartId(props.id);\n const toggle = ctx.group.kind === \"toggle\";\n return part(\n \"input\",\n props,\n ctx,\n {\n id,\n type: toggle\n ? \"checkbox\"\n : ctx.group.kind === \"select\"\n ? \"text\"\n : ctx.group.kind,\n value: toggle ? undefined : ctx.input,\n checked: toggle ? ctx.input === \"true\" : undefined,\n required: ctx.group.required,\n \"aria-label\": ctx.group.name,\n \"aria-invalid\": ctx.invalid || undefined,\n \"data-invalid\": flag(ctx.invalid),\n maxLength: ctx.group.input?.maxLength ?? 500,\n placeholder: ctx.group.input?.placeholder,\n onChange: (event: ChangeEvent<HTMLInputElement>) =>\n ctx.setInput(\n toggle ? String(event.target.checked) : event.target.value,\n ),\n },\n ref,\n );\n },\n);\n/**\n * Group item options with selection rules, validation state and an Input part for typed responses.\n * Use within ItemForm.Root. Use Choice for options and OptionGroup.Input for typed responses.\n */\nexport const OptionGroup = Object.assign(Group, { Input });\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["ctx", "group", "ChoiceView", "Choice", "Input", "OptionGroup"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// src/item-form/options.tsx
|
|
2
|
+
import { forwardRef } from "react";
|
|
3
|
+
import { part } from "../internal/slot.js";
|
|
4
|
+
import { useItemForm } from "./root.js";
|
|
5
|
+
var Options = forwardRef(
|
|
6
|
+
function Options2(props, ref) {
|
|
7
|
+
return part("div", props, useItemForm(), {}, ref);
|
|
8
|
+
}
|
|
9
|
+
);
|
|
10
|
+
var Add = forwardRef(
|
|
11
|
+
function Add2(props, ref) {
|
|
12
|
+
const context = useItemForm();
|
|
13
|
+
return part(
|
|
14
|
+
"button",
|
|
15
|
+
props,
|
|
16
|
+
context,
|
|
17
|
+
{
|
|
18
|
+
type: "button",
|
|
19
|
+
onClick: context.add,
|
|
20
|
+
"data-zappie-action": "add-to-cart"
|
|
21
|
+
},
|
|
22
|
+
ref
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
export {
|
|
27
|
+
Add,
|
|
28
|
+
Options
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=options.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/item-form/options.tsx"],
|
|
4
|
+
"sourcesContent": ["import { forwardRef } from \"react\";\nimport { part, type PartProps } from \"../internal/slot\";\nimport { useItemForm, type ItemFormContext } from \"./root\";\nexport const Options = forwardRef<HTMLElement, PartProps<ItemFormContext>>(\n function Options(props, ref) {\n return part(\"div\", props, useItemForm(), {}, ref);\n },\n);\nexport const Add = forwardRef<HTMLElement, PartProps<ItemFormContext>>(\n function Add(props, ref) {\n const context = useItemForm();\n // Keep invalid configurations actionable so add() can explain and focus errors.\n return part(\n \"button\",\n props,\n context,\n {\n type: \"button\",\n onClick: context.add,\n \"data-zappie-action\": \"add-to-cart\",\n },\n ref,\n );\n },\n);\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,kBAAkB;AAC3B,SAAS,YAA4B;AACrC,SAAS,mBAAyC;AAC3C,IAAM,UAAU;AAAA,EACrB,SAASA,SAAQ,OAAO,KAAK;AAC3B,WAAO,KAAK,OAAO,OAAO,YAAY,GAAG,CAAC,GAAG,GAAG;AAAA,EAClD;AACF;AACO,IAAM,MAAM;AAAA,EACjB,SAASC,KAAI,OAAO,KAAK;AACvB,UAAM,UAAU,YAAY;AAE5B,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS,QAAQ;AAAA,QACjB,sBAAsB;AAAA,MACxB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
|
+
"names": ["Options", "Add"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/item-form/quantity.tsx
|
|
4
|
+
import {
|
|
5
|
+
createContext,
|
|
6
|
+
forwardRef,
|
|
7
|
+
useCallback,
|
|
8
|
+
useContext,
|
|
9
|
+
useMemo
|
|
10
|
+
} from "react";
|
|
11
|
+
import { flag } from "../internal/data-attrs.js";
|
|
12
|
+
import { part } from "../internal/slot.js";
|
|
13
|
+
import { useControllableState } from "../internal/use-controllable-state.js";
|
|
14
|
+
import { jsx } from "react/jsx-runtime";
|
|
15
|
+
var Context = createContext(null);
|
|
16
|
+
function useQuantity() {
|
|
17
|
+
const context = useContext(Context);
|
|
18
|
+
if (!context) {
|
|
19
|
+
throw new Error("Quantity parts require Quantity.Root");
|
|
20
|
+
}
|
|
21
|
+
return context;
|
|
22
|
+
}
|
|
23
|
+
function Root({
|
|
24
|
+
value,
|
|
25
|
+
defaultValue,
|
|
26
|
+
onValueChange,
|
|
27
|
+
min = 1,
|
|
28
|
+
max = 99,
|
|
29
|
+
step = 1,
|
|
30
|
+
disabled = false,
|
|
31
|
+
...props
|
|
32
|
+
}) {
|
|
33
|
+
if (!Number.isFinite(min) || !Number.isFinite(max) || !Number.isFinite(step) || step <= 0 || min > max) {
|
|
34
|
+
throw new RangeError(
|
|
35
|
+
"Quantity requires finite ordered bounds and a positive step"
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
const [current, set] = useControllableState({
|
|
39
|
+
value,
|
|
40
|
+
defaultValue: defaultValue ?? min,
|
|
41
|
+
onChange: onValueChange
|
|
42
|
+
});
|
|
43
|
+
const setValue = useCallback(
|
|
44
|
+
(next) => {
|
|
45
|
+
if (!disabled && Number.isFinite(next)) {
|
|
46
|
+
const last = min + Math.floor((max - min) / step) * step;
|
|
47
|
+
set(
|
|
48
|
+
Math.max(
|
|
49
|
+
min,
|
|
50
|
+
Math.min(last, min + Math.round((next - min) / step) * step)
|
|
51
|
+
)
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
[min, max, step, disabled, set]
|
|
56
|
+
);
|
|
57
|
+
const state = useMemo(
|
|
58
|
+
() => ({ value: current, setValue, min, max, step, disabled }),
|
|
59
|
+
[current, setValue, min, max, step, disabled]
|
|
60
|
+
);
|
|
61
|
+
return /* @__PURE__ */ jsx(Context.Provider, { value: state, children: part("div", props, state, { "data-disabled": flag(disabled) }) });
|
|
62
|
+
}
|
|
63
|
+
function button(direction) {
|
|
64
|
+
return forwardRef(
|
|
65
|
+
function QuantityButton(props, ref) {
|
|
66
|
+
const ctx = useQuantity();
|
|
67
|
+
const disabled = ctx.disabled || (direction < 0 ? ctx.value <= ctx.min : ctx.value + ctx.step > ctx.max);
|
|
68
|
+
return part(
|
|
69
|
+
"button",
|
|
70
|
+
props,
|
|
71
|
+
ctx,
|
|
72
|
+
{
|
|
73
|
+
type: "button",
|
|
74
|
+
disabled,
|
|
75
|
+
"aria-disabled": disabled,
|
|
76
|
+
"data-disabled": flag(disabled),
|
|
77
|
+
onClick: () => ctx.setValue(ctx.value + direction * ctx.step)
|
|
78
|
+
},
|
|
79
|
+
ref
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
var Value = forwardRef(
|
|
85
|
+
function Value2(props, ref) {
|
|
86
|
+
const ctx = useQuantity();
|
|
87
|
+
return part(
|
|
88
|
+
"input",
|
|
89
|
+
props,
|
|
90
|
+
ctx,
|
|
91
|
+
{
|
|
92
|
+
type: "text",
|
|
93
|
+
inputMode: "numeric",
|
|
94
|
+
role: "spinbutton",
|
|
95
|
+
value: String(ctx.value),
|
|
96
|
+
disabled: ctx.disabled,
|
|
97
|
+
"aria-valuenow": ctx.value,
|
|
98
|
+
"aria-valuemin": ctx.min,
|
|
99
|
+
"aria-valuemax": ctx.max,
|
|
100
|
+
onChange: (event) => {
|
|
101
|
+
if (event.target.value.trim()) {
|
|
102
|
+
ctx.setValue(Number(event.target.value));
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
onKeyDown: (event) => {
|
|
106
|
+
const next = {
|
|
107
|
+
ArrowUp: ctx.value + ctx.step,
|
|
108
|
+
ArrowDown: ctx.value - ctx.step,
|
|
109
|
+
Home: ctx.min,
|
|
110
|
+
End: ctx.max
|
|
111
|
+
}[event.key];
|
|
112
|
+
if (next !== void 0) {
|
|
113
|
+
event.preventDefault();
|
|
114
|
+
ctx.setValue(next);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
ref
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
var Quantity = {
|
|
123
|
+
Root,
|
|
124
|
+
Value,
|
|
125
|
+
Increment: button(1),
|
|
126
|
+
Decrement: button(-1)
|
|
127
|
+
};
|
|
128
|
+
export {
|
|
129
|
+
Quantity
|
|
130
|
+
};
|
|
131
|
+
//# sourceMappingURL=quantity.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/item-form/quantity.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\";\nimport {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useMemo,\n type ChangeEvent,\n type KeyboardEvent,\n} from \"react\";\nimport { flag } from \"../internal/data-attrs\";\nimport { part, type PartProps } from \"../internal/slot\";\nimport { useControllableState } from \"../internal/use-controllable-state\";\n/**\n * The current quantity, bounds, step, disabled state and value setter exposed by a quantity control.\n */\nexport type QuantityState = {\n value: number;\n setValue: (value: number) => void;\n min: number;\n max: number;\n step: number;\n disabled: boolean;\n};\nconst Context = createContext<QuantityState | null>(null);\nfunction useQuantity() {\n const context = useContext(Context);\n if (!context) {\n throw new Error(\"Quantity parts require Quantity.Root\");\n }\n return context;\n}\n/**\n * Controlled or default quantity, bounds and change callback for Quantity.Root.\n */\nexport type QuantityProps = PartProps<QuantityState> & {\n value?: number;\n defaultValue?: number;\n onValueChange?: (value: number) => void;\n min?: number;\n max?: number;\n step?: number;\n disabled?: boolean;\n};\nfunction Root({\n value,\n defaultValue,\n onValueChange,\n min = 1,\n max = 99,\n step = 1,\n disabled = false,\n ...props\n}: QuantityProps) {\n if (\n !Number.isFinite(min) ||\n !Number.isFinite(max) ||\n !Number.isFinite(step) ||\n step <= 0 ||\n min > max\n ) {\n throw new RangeError(\n \"Quantity requires finite ordered bounds and a positive step\",\n );\n }\n const [current, set] = useControllableState({\n value,\n defaultValue: defaultValue ?? min,\n onChange: onValueChange,\n });\n const setValue = useCallback(\n (next: number) => {\n if (!disabled && Number.isFinite(next)) {\n const last = min + Math.floor((max - min) / step) * step;\n set(\n Math.max(\n min,\n Math.min(last, min + Math.round((next - min) / step) * step),\n ),\n );\n }\n },\n [min, max, step, disabled, set],\n );\n const state = useMemo(\n () => ({ value: current, setValue, min, max, step, disabled }),\n [current, setValue, min, max, step, disabled],\n );\n return (\n <Context.Provider value={state}>\n {part(\"div\", props, state, { \"data-disabled\": flag(disabled) })}\n </Context.Provider>\n );\n}\nfunction button(direction: -1 | 1) {\n return forwardRef<HTMLElement, PartProps<QuantityState>>(\n function QuantityButton(props, ref) {\n const ctx = useQuantity();\n const disabled =\n ctx.disabled ||\n (direction < 0 ? ctx.value <= ctx.min : ctx.value + ctx.step > ctx.max);\n return part(\n \"button\",\n props,\n ctx,\n {\n type: \"button\",\n disabled,\n \"aria-disabled\": disabled,\n \"data-disabled\": flag(disabled),\n onClick: () => ctx.setValue(ctx.value + direction * ctx.step),\n },\n ref,\n );\n },\n );\n}\nconst Value = forwardRef<HTMLElement, PartProps<QuantityState>>(\n function Value(props, ref) {\n const ctx = useQuantity();\n return part(\n \"input\",\n props,\n ctx,\n {\n type: \"text\",\n inputMode: \"numeric\",\n role: \"spinbutton\",\n value: String(ctx.value),\n disabled: ctx.disabled,\n \"aria-valuenow\": ctx.value,\n \"aria-valuemin\": ctx.min,\n \"aria-valuemax\": ctx.max,\n onChange: (event: ChangeEvent<HTMLInputElement>) => {\n if (event.target.value.trim()) {\n ctx.setValue(Number(event.target.value));\n }\n },\n onKeyDown: (event: KeyboardEvent) => {\n const next = {\n ArrowUp: ctx.value + ctx.step,\n ArrowDown: ctx.value - ctx.step,\n Home: ctx.min,\n End: ctx.max,\n }[event.key];\n if (next !== undefined) {\n event.preventDefault();\n ctx.setValue(next);\n }\n },\n },\n ref,\n );\n },\n);\n/**\n * Composable quantity controls with bounded step changes and keyboard support.\n * Wrap Value, Increment and Decrement in Quantity.Root.\n *\n * @example\n * ```tsx\n * <Quantity.Root min={1} max={10} defaultValue={1}>\n * <Quantity.Decrement>Less</Quantity.Decrement>\n * <Quantity.Value aria-label=\"Quantity\" />\n * <Quantity.Increment>More</Quantity.Increment>\n * </Quantity.Root>\n * ```\n */\nexport const Quantity = {\n Root,\n Value,\n Increment: button(1),\n Decrement: button(-1),\n};\n"],
|
|
5
|
+
"mappings": ";;;AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,SAAS,YAAY;AACrB,SAAS,YAA4B;AACrC,SAAS,4BAA4B;AA6EjC;AAjEJ,IAAM,UAAU,cAAoC,IAAI;AACxD,SAAS,cAAc;AACrB,QAAM,UAAU,WAAW,OAAO;AAClC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,sCAAsC;AAAA,EACxD;AACA,SAAO;AACT;AAaA,SAAS,KAAK;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW;AAAA,EACX,GAAG;AACL,GAAkB;AAChB,MACE,CAAC,OAAO,SAAS,GAAG,KACpB,CAAC,OAAO,SAAS,GAAG,KACpB,CAAC,OAAO,SAAS,IAAI,KACrB,QAAQ,KACR,MAAM,KACN;AACA,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,QAAM,CAAC,SAAS,GAAG,IAAI,qBAAqB;AAAA,IAC1C;AAAA,IACA,cAAc,gBAAgB;AAAA,IAC9B,UAAU;AAAA,EACZ,CAAC;AACD,QAAM,WAAW;AAAA,IACf,CAAC,SAAiB;AAChB,UAAI,CAAC,YAAY,OAAO,SAAS,IAAI,GAAG;AACtC,cAAM,OAAO,MAAM,KAAK,OAAO,MAAM,OAAO,IAAI,IAAI;AACpD;AAAA,UACE,KAAK;AAAA,YACH;AAAA,YACA,KAAK,IAAI,MAAM,MAAM,KAAK,OAAO,OAAO,OAAO,IAAI,IAAI,IAAI;AAAA,UAC7D;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,KAAK,KAAK,MAAM,UAAU,GAAG;AAAA,EAChC;AACA,QAAM,QAAQ;AAAA,IACZ,OAAO,EAAE,OAAO,SAAS,UAAU,KAAK,KAAK,MAAM,SAAS;AAAA,IAC5D,CAAC,SAAS,UAAU,KAAK,KAAK,MAAM,QAAQ;AAAA,EAC9C;AACA,SACE,oBAAC,QAAQ,UAAR,EAAiB,OAAO,OACtB,eAAK,OAAO,OAAO,OAAO,EAAE,iBAAiB,KAAK,QAAQ,EAAE,CAAC,GAChE;AAEJ;AACA,SAAS,OAAO,WAAmB;AACjC,SAAO;AAAA,IACL,SAAS,eAAe,OAAO,KAAK;AAClC,YAAM,MAAM,YAAY;AACxB,YAAM,WACJ,IAAI,aACH,YAAY,IAAI,IAAI,SAAS,IAAI,MAAM,IAAI,QAAQ,IAAI,OAAO,IAAI;AACrE,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN;AAAA,UACA,iBAAiB;AAAA,UACjB,iBAAiB,KAAK,QAAQ;AAAA,UAC9B,SAAS,MAAM,IAAI,SAAS,IAAI,QAAQ,YAAY,IAAI,IAAI;AAAA,QAC9D;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AACA,IAAM,QAAQ;AAAA,EACZ,SAASA,OAAM,OAAO,KAAK;AACzB,UAAM,MAAM,YAAY;AACxB,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,WAAW;AAAA,QACX,MAAM;AAAA,QACN,OAAO,OAAO,IAAI,KAAK;AAAA,QACvB,UAAU,IAAI;AAAA,QACd,iBAAiB,IAAI;AAAA,QACrB,iBAAiB,IAAI;AAAA,QACrB,iBAAiB,IAAI;AAAA,QACrB,UAAU,CAAC,UAAyC;AAClD,cAAI,MAAM,OAAO,MAAM,KAAK,GAAG;AAC7B,gBAAI,SAAS,OAAO,MAAM,OAAO,KAAK,CAAC;AAAA,UACzC;AAAA,QACF;AAAA,QACA,WAAW,CAAC,UAAyB;AACnC,gBAAM,OAAO;AAAA,YACX,SAAS,IAAI,QAAQ,IAAI;AAAA,YACzB,WAAW,IAAI,QAAQ,IAAI;AAAA,YAC3B,MAAM,IAAI;AAAA,YACV,KAAK,IAAI;AAAA,UACX,EAAE,MAAM,GAAG;AACX,cAAI,SAAS,QAAW;AACtB,kBAAM,eAAe;AACrB,gBAAI,SAAS,IAAI;AAAA,UACnB;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAcO,IAAM,WAAW;AAAA,EACtB;AAAA,EACA;AAAA,EACA,WAAW,OAAO,CAAC;AAAA,EACnB,WAAW,OAAO,EAAE;AACtB;",
|
|
6
|
+
"names": ["Value"]
|
|
7
|
+
}
|