@tallyui/components 3.3.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1848,10 +1848,158 @@ function ProductGrid({
1848
1848
  ] });
1849
1849
  }
1850
1850
 
1851
- // src/product/product-list.tsx
1852
- import { ScrollView as ScrollView2, View as View20 } from "react-native";
1851
+ // src/product/view-toggle.tsx
1852
+ import { Pressable as Pressable8, Text as Text11, View as View20 } from "react-native";
1853
1853
  import { cn as cn43 } from "@tallyui/theme";
1854
- import { jsx as jsx46, jsxs as jsxs10 } from "react/jsx-runtime";
1854
+ import { jsx as jsx46 } from "react/jsx-runtime";
1855
+ function ViewToggle({ value, onChange, labels, className, ...viewProps }) {
1856
+ return /* @__PURE__ */ jsx46(
1857
+ View20,
1858
+ {
1859
+ ...viewProps,
1860
+ role: "radiogroup",
1861
+ accessibilityLabel: "View",
1862
+ testID: "view-toggle",
1863
+ className: cn43("flex-row self-start overflow-hidden rounded-md border border-border", className),
1864
+ children: ["grid", "table"].map((view) => {
1865
+ const selected = value === view;
1866
+ const label = labels?.[view] ?? (view === "grid" ? "Grid" : "Table");
1867
+ return /* @__PURE__ */ jsx46(
1868
+ Pressable8,
1869
+ {
1870
+ role: "radio",
1871
+ "aria-checked": selected,
1872
+ testID: `view-toggle-${view}`,
1873
+ accessibilityLabel: label,
1874
+ onPress: () => {
1875
+ if (!selected) onChange(view);
1876
+ },
1877
+ className: cn43("px-3 py-2", selected ? "bg-primary" : "bg-card"),
1878
+ children: /* @__PURE__ */ jsx46(Text11, { className: cn43("text-sm font-medium", selected ? "text-primary-foreground" : "text-foreground"), children: label })
1879
+ },
1880
+ view
1881
+ );
1882
+ })
1883
+ }
1884
+ );
1885
+ }
1886
+
1887
+ // src/product/product-table.tsx
1888
+ import { useMemo, useState as useState3 } from "react";
1889
+ import { FlatList as FlatList2, Pressable as Pressable9, View as View21 } from "react-native";
1890
+ import { useProductTraits as useProductTraits7, useTraitContext as useTraitContext2, useStockOverlaid } from "@tallyui/core";
1891
+ import { productSortValue, sortProducts } from "@tallyui/pos";
1892
+ import { cn as cn44 } from "@tallyui/theme";
1893
+ import { jsx as jsx47, jsxs as jsxs10 } from "react/jsx-runtime";
1894
+ var INITIAL_ROWS2 = 8;
1895
+ var BATCH_ROWS2 = 8;
1896
+ var WINDOW_SIZE2 = 5;
1897
+ function defaultProductColumns(traits, context, options) {
1898
+ const columns = [
1899
+ { id: "name", header: "Name", flex: 3, render: (doc) => /* @__PURE__ */ jsx47(ProductTitle, { doc, numberOfLines: 2 }) },
1900
+ { id: "sku", header: "SKU", flex: 1, render: (doc) => /* @__PURE__ */ jsx47(ProductSku, { doc }) },
1901
+ { id: "barcode", header: "Barcode", flex: 1, render: (doc) => /* @__PURE__ */ jsx47(Text, { children: traits.getBarcode(doc) ?? "\u2014" }) },
1902
+ { id: "price", header: "Price", flex: 1, render: (doc) => /* @__PURE__ */ jsx47(ProductPrice, { doc, currencySymbol: options?.currencySymbol }) },
1903
+ { id: "stock", header: "Stock", flex: 1, render: (doc) => /* @__PURE__ */ jsx47(ProductStockBadge, { doc, showQuantity: true, showAsOf: false }) },
1904
+ { id: "category", header: "Category", flex: 2, render: (doc) => /* @__PURE__ */ jsx47(Text, { children: traits.getCategoryNames(doc).join(", ") || "\u2014" }) }
1905
+ ];
1906
+ return columns.map((column) => ({
1907
+ ...column,
1908
+ sortValue: (doc) => productSortValue(doc, column.id, traits, context)
1909
+ }));
1910
+ }
1911
+ function useDefaultProductColumns(options) {
1912
+ const traits = useProductTraits7();
1913
+ const context = useTraitContext2();
1914
+ const currencySymbol4 = options?.currencySymbol;
1915
+ return useMemo(() => defaultProductColumns(traits, context, { currencySymbol: currencySymbol4 }), [traits, context, currencySymbol4]);
1916
+ }
1917
+ function ProductTable({
1918
+ items,
1919
+ columns,
1920
+ sort,
1921
+ defaultSort = null,
1922
+ onSortChange,
1923
+ sortItems = true,
1924
+ onSelect,
1925
+ searchSlot,
1926
+ filterSlot,
1927
+ emptyState,
1928
+ showUnsellable = false,
1929
+ currencySymbol: currencySymbol4,
1930
+ className,
1931
+ ...viewProps
1932
+ }) {
1933
+ let traits;
1934
+ try {
1935
+ traits = useProductTraits7();
1936
+ } catch {
1937
+ traits = void 0;
1938
+ }
1939
+ const context = useTraitContext2();
1940
+ const resolvedColumns = useMemo(() => columns ?? (traits ? defaultProductColumns(traits, context, { currencySymbol: currencySymbol4 }) : []), [columns, traits, context, currencySymbol4]);
1941
+ const [internalSort, setInternalSort] = useState3(defaultSort);
1942
+ const activeSort = sort === void 0 ? internalSort : sort;
1943
+ const visibleItems = showUnsellable || !traits ? items : items.filter((item) => traits.isSellable(item));
1944
+ const overlaidItems = useStockOverlaid(visibleItems);
1945
+ const rows = sortItems ? sortProducts(
1946
+ [...overlaidItems],
1947
+ activeSort,
1948
+ (doc, field) => resolvedColumns.find((column) => column.id === field)?.sortValue?.(doc)
1949
+ ) : overlaidItems;
1950
+ const changeSort = (id) => {
1951
+ const next = activeSort?.field !== id ? { field: id, dir: "asc" } : activeSort.dir === "asc" ? { field: id, dir: "desc" } : null;
1952
+ if (sort === void 0) setInternalSort(next);
1953
+ onSortChange?.(next);
1954
+ };
1955
+ return /* @__PURE__ */ jsxs10(VStack, { space: "none", className: cn44("flex-1", className), ...viewProps, children: [
1956
+ searchSlot && /* @__PURE__ */ jsx47(View21, { className: "px-3 py-2", children: searchSlot }),
1957
+ filterSlot && /* @__PURE__ */ jsx47(View21, { className: "px-3 pb-2", children: filterSlot }),
1958
+ rows.length ? /* @__PURE__ */ jsxs10(Table, { className: "flex-1", children: [
1959
+ /* @__PURE__ */ jsx47(TableHeader, { children: /* @__PURE__ */ jsx47(TableRow, { children: resolvedColumns.map((column) => /* @__PURE__ */ jsx47(
1960
+ TableHead,
1961
+ {
1962
+ style: { flex: column.flex ?? 1 },
1963
+ ...column.sortValue ? { "aria-sort": activeSort?.field === column.id ? activeSort.dir === "asc" ? "ascending" : "descending" : "none" } : {},
1964
+ children: column.sortValue ? /* @__PURE__ */ jsx47(
1965
+ Pressable9,
1966
+ {
1967
+ accessibilityRole: "button",
1968
+ accessibilityLabel: "Sort by " + column.header,
1969
+ testID: "product-table-sort-" + column.id,
1970
+ onPress: () => changeSort(column.id),
1971
+ children: /* @__PURE__ */ jsxs10(Text, { children: [
1972
+ column.header,
1973
+ activeSort?.field === column.id ? activeSort.dir === "asc" ? " \u25B2" : " \u25BC" : ""
1974
+ ] })
1975
+ }
1976
+ ) : /* @__PURE__ */ jsx47(Text, { children: column.header })
1977
+ },
1978
+ column.id
1979
+ )) }) }),
1980
+ /* @__PURE__ */ jsx47(TableBody, { className: "flex-1", children: /* @__PURE__ */ jsx47(
1981
+ FlatList2,
1982
+ {
1983
+ data: rows,
1984
+ keyExtractor: (item, index) => String(item.id ?? index),
1985
+ initialNumToRender: INITIAL_ROWS2,
1986
+ maxToRenderPerBatch: BATCH_ROWS2,
1987
+ windowSize: WINDOW_SIZE2,
1988
+ renderItem: ({ item, index }) => {
1989
+ const key = String(item.id ?? index);
1990
+ const row = /* @__PURE__ */ jsx47(TableRow, { testID: onSelect ? void 0 : "product-row-" + key, children: resolvedColumns.map((column) => /* @__PURE__ */ jsx47(TableCell, { style: { flex: column.flex ?? 1 }, children: column.render(item) }, column.id)) });
1991
+ return onSelect ? /* @__PURE__ */ jsx47(Pressable9, { accessibilityRole: "button", testID: "product-row-" + key, onPress: () => onSelect(item), children: row }) : row;
1992
+ }
1993
+ }
1994
+ ) })
1995
+ ] }) : emptyState ?? null
1996
+ ] });
1997
+ }
1998
+
1999
+ // src/product/product-list.tsx
2000
+ import { ScrollView as ScrollView2, View as View22 } from "react-native";
2001
+ import { cn as cn45 } from "@tallyui/theme";
2002
+ import { jsx as jsx48, jsxs as jsxs11 } from "react/jsx-runtime";
1855
2003
  function ProductList({
1856
2004
  items,
1857
2005
  renderItem,
@@ -1862,17 +2010,17 @@ function ProductList({
1862
2010
  ...viewProps
1863
2011
  }) {
1864
2012
  const hasItems = items.length > 0;
1865
- return /* @__PURE__ */ jsxs10(View20, { className: cn43("flex-1", className), ...viewProps, children: [
1866
- searchSlot && /* @__PURE__ */ jsx46(View20, { className: "px-3 py-2", children: searchSlot }),
1867
- filterSlot && /* @__PURE__ */ jsx46(View20, { className: "px-3 pb-2", children: filterSlot }),
1868
- hasItems ? /* @__PURE__ */ jsx46(ScrollView2, { className: "flex-1", children: items.map((item, index) => /* @__PURE__ */ jsx46(View20, { className: "border-b border-border", children: renderItem(item, index) }, item.id ?? index)) }) : emptyState ?? null
2013
+ return /* @__PURE__ */ jsxs11(View22, { className: cn45("flex-1", className), ...viewProps, children: [
2014
+ searchSlot && /* @__PURE__ */ jsx48(View22, { className: "px-3 py-2", children: searchSlot }),
2015
+ filterSlot && /* @__PURE__ */ jsx48(View22, { className: "px-3 pb-2", children: filterSlot }),
2016
+ hasItems ? /* @__PURE__ */ jsx48(ScrollView2, { className: "flex-1", children: items.map((item, index) => /* @__PURE__ */ jsx48(View22, { className: "border-b border-border", children: renderItem(item, index) }, item.id ?? index)) }) : emptyState ?? null
1869
2017
  ] });
1870
2018
  }
1871
2019
 
1872
2020
  // src/product/category-nav.tsx
1873
- import { Pressable as Pressable8, ScrollView as ScrollView3, Text as Text11, View as View21 } from "react-native";
1874
- import { cn as cn44 } from "@tallyui/theme";
1875
- import { jsx as jsx47 } from "react/jsx-runtime";
2021
+ import { Pressable as Pressable10, ScrollView as ScrollView3, Text as Text12, View as View23 } from "react-native";
2022
+ import { cn as cn46 } from "@tallyui/theme";
2023
+ import { jsx as jsx49 } from "react/jsx-runtime";
1876
2024
  function CategoryNav({
1877
2025
  categories,
1878
2026
  selectedId,
@@ -1884,18 +2032,21 @@ function CategoryNav({
1884
2032
  const isHorizontal = orientation === "horizontal";
1885
2033
  const content = categories.map((cat) => {
1886
2034
  const active = cat.id === selectedId;
1887
- return /* @__PURE__ */ jsx47(
1888
- Pressable8,
2035
+ return /* @__PURE__ */ jsx49(
2036
+ Pressable10,
1889
2037
  {
2038
+ testID: `category-nav-${cat.id}`,
2039
+ role: "radio",
2040
+ "aria-checked": active,
1890
2041
  onPress: () => onSelect(cat.id),
1891
- className: cn44(
1892
- "rounded-full px-3 py-1.5",
2042
+ className: cn46(
2043
+ "rounded-md px-3 py-1.5",
1893
2044
  active ? "bg-primary" : "bg-muted"
1894
2045
  ),
1895
- children: /* @__PURE__ */ jsx47(
1896
- Text11,
2046
+ children: /* @__PURE__ */ jsx49(
2047
+ Text12,
1897
2048
  {
1898
- className: cn44(
2049
+ className: cn46(
1899
2050
  "text-sm font-medium",
1900
2051
  active ? "text-primary-foreground" : "text-foreground"
1901
2052
  ),
@@ -1907,25 +2058,27 @@ function CategoryNav({
1907
2058
  );
1908
2059
  });
1909
2060
  if (isHorizontal) {
1910
- return /* @__PURE__ */ jsx47(
2061
+ return /* @__PURE__ */ jsx49(
1911
2062
  ScrollView3,
1912
2063
  {
1913
2064
  horizontal: true,
1914
2065
  showsHorizontalScrollIndicator: false,
1915
2066
  contentContainerClassName: "flex-row gap-2 px-3 py-2",
1916
2067
  className,
2068
+ role: "radiogroup",
2069
+ accessibilityLabel: "Categories",
1917
2070
  ...viewProps,
1918
2071
  children: content
1919
2072
  }
1920
2073
  );
1921
2074
  }
1922
- return /* @__PURE__ */ jsx47(View21, { className: cn44("gap-1 p-2", className), ...viewProps, children: content });
2075
+ return /* @__PURE__ */ jsx49(View23, { className: cn46("gap-1 p-2", className), role: "radiogroup", accessibilityLabel: "Categories", ...viewProps, children: content });
1923
2076
  }
1924
2077
 
1925
2078
  // src/product/product-variant-picker.tsx
1926
- import { Pressable as Pressable9, Text as Text12, View as View22 } from "react-native";
1927
- import { cn as cn45 } from "@tallyui/theme";
1928
- import { jsx as jsx48, jsxs as jsxs11 } from "react/jsx-runtime";
2079
+ import { Pressable as Pressable11, Text as Text13, View as View24 } from "react-native";
2080
+ import { cn as cn47 } from "@tallyui/theme";
2081
+ import { jsx as jsx50, jsxs as jsxs12 } from "react/jsx-runtime";
1929
2082
  function ProductVariantPicker({
1930
2083
  options,
1931
2084
  selected = {},
@@ -1936,22 +2089,22 @@ function ProductVariantPicker({
1936
2089
  const handleSelect = (optionName, value) => {
1937
2090
  onSelect?.({ ...selected, [optionName]: value });
1938
2091
  };
1939
- return /* @__PURE__ */ jsx48(View22, { className: cn45("gap-3", className), ...viewProps, children: options.map((option) => /* @__PURE__ */ jsxs11(View22, { className: "gap-1.5", children: [
1940
- /* @__PURE__ */ jsx48(Text12, { className: "text-xs font-semibold text-muted-foreground", children: option.name }),
1941
- /* @__PURE__ */ jsx48(View22, { className: "flex-row flex-wrap gap-2", children: option.values.map((value) => {
2092
+ return /* @__PURE__ */ jsx50(View24, { className: cn47("gap-3", className), ...viewProps, children: options.map((option) => /* @__PURE__ */ jsxs12(View24, { className: "gap-1.5", children: [
2093
+ /* @__PURE__ */ jsx50(Text13, { className: "text-xs font-semibold text-muted-foreground", children: option.name }),
2094
+ /* @__PURE__ */ jsx50(View24, { className: "flex-row flex-wrap gap-2", children: option.values.map((value) => {
1942
2095
  const active = selected[option.name] === value;
1943
- return /* @__PURE__ */ jsx48(
1944
- Pressable9,
2096
+ return /* @__PURE__ */ jsx50(
2097
+ Pressable11,
1945
2098
  {
1946
2099
  onPress: () => handleSelect(option.name, value),
1947
- className: cn45(
2100
+ className: cn47(
1948
2101
  "rounded-lg border px-3 py-1.5",
1949
2102
  active ? "border-primary bg-primary/10" : "border-border bg-card"
1950
2103
  ),
1951
- children: /* @__PURE__ */ jsx48(
1952
- Text12,
2104
+ children: /* @__PURE__ */ jsx50(
2105
+ Text13,
1953
2106
  {
1954
- className: cn45(
2107
+ className: cn47(
1955
2108
  "text-sm font-medium",
1956
2109
  active ? "text-primary" : "text-foreground"
1957
2110
  ),
@@ -1967,22 +2120,22 @@ function ProductVariantPicker({
1967
2120
 
1968
2121
  // src/cart/cart-line.tsx
1969
2122
  import { formatMoney as formatMoney2 } from "@tallyui/core";
1970
- import { cn as cn46 } from "@tallyui/theme";
1971
- import { jsx as jsx49, jsxs as jsxs12 } from "react/jsx-runtime";
2123
+ import { cn as cn48 } from "@tallyui/theme";
2124
+ import { jsx as jsx51, jsxs as jsxs13 } from "react/jsx-runtime";
1972
2125
  function CartLine({ name, quantity, unitPrice, lineTotal, locale, className, ...props }) {
1973
- return /* @__PURE__ */ jsxs12(HStack, { className: cn46("px-3 py-2.5", className), ...props, children: [
1974
- /* @__PURE__ */ jsxs12(VStack, { space: "none", className: "flex-1 gap-0.5", children: [
1975
- /* @__PURE__ */ jsx49(Text, { className: "text-sm font-medium", numberOfLines: 1, children: name }),
1976
- /* @__PURE__ */ jsx49(Text, { className: "text-xs text-muted-foreground", children: `${formatMoney2(unitPrice, locale) ?? "\u2014"} \xD7 ${quantity}` })
2126
+ return /* @__PURE__ */ jsxs13(HStack, { className: cn48("px-3 py-2.5", className), ...props, children: [
2127
+ /* @__PURE__ */ jsxs13(VStack, { space: "none", className: "flex-1 gap-0.5", children: [
2128
+ /* @__PURE__ */ jsx51(Text, { className: "text-sm font-medium", numberOfLines: 1, children: name }),
2129
+ /* @__PURE__ */ jsx51(Text, { className: "text-xs text-muted-foreground", children: `${formatMoney2(unitPrice, locale) ?? "\u2014"} \xD7 ${quantity}` })
1977
2130
  ] }),
1978
- /* @__PURE__ */ jsx49(Text, { className: "text-sm font-semibold", children: formatMoney2(lineTotal, locale) ?? "\u2014" })
2131
+ /* @__PURE__ */ jsx51(Text, { className: "text-sm font-semibold", children: formatMoney2(lineTotal, locale) ?? "\u2014" })
1979
2132
  ] });
1980
2133
  }
1981
2134
 
1982
2135
  // src/cart/cart-total.tsx
1983
2136
  import { formatMoney as formatMoney3 } from "@tallyui/core";
1984
- import { cn as cn47 } from "@tallyui/theme";
1985
- import { jsx as jsx50, jsxs as jsxs13 } from "react/jsx-runtime";
2137
+ import { cn as cn49 } from "@tallyui/theme";
2138
+ import { jsx as jsx52, jsxs as jsxs14 } from "react/jsx-runtime";
1986
2139
  function CartTotal({
1987
2140
  subtotal,
1988
2141
  taxLines,
@@ -1993,33 +2146,33 @@ function CartTotal({
1993
2146
  className,
1994
2147
  ...props
1995
2148
  }) {
1996
- return /* @__PURE__ */ jsxs13(VStack, { space: "none", className: cn47("gap-1.5 px-3 py-3", className), ...props, children: [
1997
- /* @__PURE__ */ jsxs13(HStack, { space: "none", className: "justify-between", children: [
1998
- /* @__PURE__ */ jsx50(Text, { className: "text-sm text-muted-foreground", children: "Subtotal" }),
1999
- /* @__PURE__ */ jsx50(Text, { className: "text-sm", children: formatMoney3(subtotal, locale) ?? "\u2014" })
2149
+ return /* @__PURE__ */ jsxs14(VStack, { space: "none", className: cn49("gap-1.5 px-3 py-3", className), ...props, children: [
2150
+ /* @__PURE__ */ jsxs14(HStack, { space: "none", className: "justify-between", children: [
2151
+ /* @__PURE__ */ jsx52(Text, { className: "text-sm text-muted-foreground", children: "Subtotal" }),
2152
+ /* @__PURE__ */ jsx52(Text, { className: "text-sm", children: formatMoney3(subtotal, locale) ?? "\u2014" })
2000
2153
  ] }),
2001
- discount && discount.amount > 0 && /* @__PURE__ */ jsxs13(HStack, { space: "none", className: "justify-between", children: [
2002
- /* @__PURE__ */ jsx50(Text, { className: "text-sm text-muted-foreground", children: "Discount" }),
2003
- /* @__PURE__ */ jsxs13(Text, { className: "text-sm", children: [
2154
+ discount && discount.amount > 0 && /* @__PURE__ */ jsxs14(HStack, { space: "none", className: "justify-between", children: [
2155
+ /* @__PURE__ */ jsx52(Text, { className: "text-sm text-muted-foreground", children: "Discount" }),
2156
+ /* @__PURE__ */ jsxs14(Text, { className: "text-sm", children: [
2004
2157
  "\u2212",
2005
2158
  formatMoney3(discount, locale) ?? "\u2014"
2006
2159
  ] })
2007
2160
  ] }),
2008
- taxLines?.map((line, index) => /* @__PURE__ */ jsxs13(HStack, { space: "none", className: "justify-between", children: [
2009
- /* @__PURE__ */ jsx50(Text, { className: "text-sm text-muted-foreground", children: taxInclusive ? `incl. ${line.label}` : line.label }),
2010
- /* @__PURE__ */ jsx50(Text, { className: "text-sm", children: formatMoney3(line.amount, locale) ?? "\u2014" })
2161
+ taxLines?.map((line, index) => /* @__PURE__ */ jsxs14(HStack, { space: "none", className: "justify-between", children: [
2162
+ /* @__PURE__ */ jsx52(Text, { className: "text-sm text-muted-foreground", children: taxInclusive ? `incl. ${line.label}` : line.label }),
2163
+ /* @__PURE__ */ jsx52(Text, { className: "text-sm", children: formatMoney3(line.amount, locale) ?? "\u2014" })
2011
2164
  ] }, index)),
2012
- /* @__PURE__ */ jsxs13(HStack, { space: "none", className: "mt-1.5 justify-between border-t border-border pt-2", children: [
2013
- /* @__PURE__ */ jsx50(Text, { className: "font-bold", children: "Total" }),
2014
- /* @__PURE__ */ jsx50(Text, { className: "font-bold", children: formatMoney3(total, locale) ?? "\u2014" })
2165
+ /* @__PURE__ */ jsxs14(HStack, { space: "none", className: "mt-1.5 justify-between border-t border-border pt-2", children: [
2166
+ /* @__PURE__ */ jsx52(Text, { className: "font-bold", children: "Total" }),
2167
+ /* @__PURE__ */ jsx52(Text, { className: "font-bold", children: formatMoney3(total, locale) ?? "\u2014" })
2015
2168
  ] })
2016
2169
  ] });
2017
2170
  }
2018
2171
 
2019
2172
  // src/cart/cart-panel.tsx
2020
- import { ScrollView as ScrollView4, View as View23 } from "react-native";
2021
- import { cn as cn48 } from "@tallyui/theme";
2022
- import { jsx as jsx51, jsxs as jsxs14 } from "react/jsx-runtime";
2173
+ import { ScrollView as ScrollView4, View as View25 } from "react-native";
2174
+ import { cn as cn50 } from "@tallyui/theme";
2175
+ import { jsx as jsx53, jsxs as jsxs15 } from "react/jsx-runtime";
2023
2176
  function defaultKey(item, index) {
2024
2177
  const id = item?.id;
2025
2178
  return typeof id === "string" || typeof id === "number" ? String(id) : String(index);
@@ -2036,36 +2189,36 @@ function CartPanel({
2036
2189
  ...props
2037
2190
  }) {
2038
2191
  const hasItems = items.length > 0;
2039
- return /* @__PURE__ */ jsxs14(VStack, { space: "none", className: cn48("flex-1 min-h-0", className), ...props, children: [
2040
- header && /* @__PURE__ */ jsx51(View23, { className: "border-b border-border px-3 py-2", children: header }),
2041
- /* @__PURE__ */ jsxs14(ScrollView4, { className: "flex-1 min-h-0", contentContainerClassName: "flex-grow", children: [
2042
- hasItems ? items.map((item, index) => /* @__PURE__ */ jsx51(View23, { children: renderItem(item, index) }, keyExtractor ? keyExtractor(item, index) : defaultKey(item, index))) : emptyState ?? null,
2192
+ return /* @__PURE__ */ jsxs15(VStack, { space: "none", className: cn50("flex-1 min-h-0", className), ...props, children: [
2193
+ header && /* @__PURE__ */ jsx53(View25, { className: "border-b border-border px-3 py-2", children: header }),
2194
+ /* @__PURE__ */ jsxs15(ScrollView4, { className: "flex-1 min-h-0", contentContainerClassName: "flex-grow", children: [
2195
+ hasItems ? items.map((item, index) => /* @__PURE__ */ jsx53(View25, { children: renderItem(item, index) }, keyExtractor ? keyExtractor(item, index) : defaultKey(item, index))) : emptyState ?? null,
2043
2196
  afterItems
2044
2197
  ] }),
2045
- footer && /* @__PURE__ */ jsx51(View23, { className: "border-t border-border px-3 py-2", children: footer })
2198
+ footer && /* @__PURE__ */ jsx53(View25, { className: "border-t border-border px-3 py-2", children: footer })
2046
2199
  ] });
2047
2200
  }
2048
2201
 
2049
2202
  // src/cart/discount-badge.tsx
2050
- import { Text as Text13, View as View24 } from "react-native";
2051
- import { cn as cn49 } from "@tallyui/theme";
2052
- import { jsx as jsx52 } from "react/jsx-runtime";
2203
+ import { Text as Text14, View as View26 } from "react-native";
2204
+ import { cn as cn51 } from "@tallyui/theme";
2205
+ import { jsx as jsx54 } from "react/jsx-runtime";
2053
2206
  function DiscountBadge({ label, className, ...viewProps }) {
2054
- return /* @__PURE__ */ jsx52(
2055
- View24,
2207
+ return /* @__PURE__ */ jsx54(
2208
+ View26,
2056
2209
  {
2057
- className: cn49("flex-row items-center self-start gap-1 rounded-md bg-sale/15 px-1.5 py-0.5", className),
2210
+ className: cn51("flex-row items-center self-start gap-1 rounded-md bg-sale/15 px-1.5 py-0.5", className),
2058
2211
  ...viewProps,
2059
- children: /* @__PURE__ */ jsx52(Text13, { className: "text-xs font-semibold text-sale", children: label })
2212
+ children: /* @__PURE__ */ jsx54(Text14, { className: "text-xs font-semibold text-sale", children: label })
2060
2213
  }
2061
2214
  );
2062
2215
  }
2063
2216
 
2064
2217
  // src/cart/cart-note-input.tsx
2065
- import { useState as useState3 } from "react";
2066
- import { Pressable as Pressable10, Text as Text14, TextInput as TextInput4, View as View25 } from "react-native";
2067
- import { cn as cn50 } from "@tallyui/theme";
2068
- import { jsx as jsx53 } from "react/jsx-runtime";
2218
+ import { useState as useState4 } from "react";
2219
+ import { Pressable as Pressable12, Text as Text15, TextInput as TextInput4, View as View27 } from "react-native";
2220
+ import { cn as cn52 } from "@tallyui/theme";
2221
+ import { jsx as jsx55 } from "react/jsx-runtime";
2069
2222
  function CartNoteInput({
2070
2223
  value,
2071
2224
  onChangeText,
@@ -2073,19 +2226,19 @@ function CartNoteInput({
2073
2226
  className,
2074
2227
  ...viewProps
2075
2228
  }) {
2076
- const [expanded, setExpanded] = useState3(value.length > 0);
2229
+ const [expanded, setExpanded] = useState4(value.length > 0);
2077
2230
  if (!expanded) {
2078
- return /* @__PURE__ */ jsx53(
2079
- Pressable10,
2231
+ return /* @__PURE__ */ jsx55(
2232
+ Pressable12,
2080
2233
  {
2081
2234
  onPress: () => setExpanded(true),
2082
- className: cn50("flex-row items-center gap-1.5 px-3 py-2", className),
2235
+ className: cn52("flex-row items-center gap-1.5 px-3 py-2", className),
2083
2236
  ...viewProps,
2084
- children: /* @__PURE__ */ jsx53(Text14, { className: "text-xs text-primary", children: "Add note" })
2237
+ children: /* @__PURE__ */ jsx55(Text15, { className: "text-xs text-primary", children: "Add note" })
2085
2238
  }
2086
2239
  );
2087
2240
  }
2088
- return /* @__PURE__ */ jsx53(View25, { className: cn50("px-3 py-2", className), ...viewProps, children: /* @__PURE__ */ jsx53(
2241
+ return /* @__PURE__ */ jsx55(View27, { className: cn52("px-3 py-2", className), ...viewProps, children: /* @__PURE__ */ jsx55(
2089
2242
  TextInput4,
2090
2243
  {
2091
2244
  value,
@@ -2099,20 +2252,20 @@ function CartNoteInput({
2099
2252
  }
2100
2253
 
2101
2254
  // src/cart/cart-line-actions.tsx
2102
- import { Pressable as Pressable11, Text as Text15, View as View26 } from "react-native";
2103
- import { cn as cn51 } from "@tallyui/theme";
2104
- import { jsx as jsx54, jsxs as jsxs15 } from "react/jsx-runtime";
2255
+ import { Pressable as Pressable13, Text as Text16, View as View28 } from "react-native";
2256
+ import { cn as cn53 } from "@tallyui/theme";
2257
+ import { jsx as jsx56, jsxs as jsxs16 } from "react/jsx-runtime";
2105
2258
  function CartLineActions({ children, actions, className, ...viewProps }) {
2106
- return /* @__PURE__ */ jsxs15(View26, { className: cn51("flex-row items-center", className), ...viewProps, children: [
2107
- /* @__PURE__ */ jsx54(View26, { className: "flex-1", children }),
2108
- /* @__PURE__ */ jsx54(View26, { className: "flex-row gap-1 px-2", children: actions.map((action) => /* @__PURE__ */ jsxs15(
2109
- Pressable11,
2259
+ return /* @__PURE__ */ jsxs16(View28, { className: cn53("flex-row items-center", className), ...viewProps, children: [
2260
+ /* @__PURE__ */ jsx56(View28, { className: "flex-1", children }),
2261
+ /* @__PURE__ */ jsx56(View28, { className: "flex-row gap-1 px-2", children: actions.map((action) => /* @__PURE__ */ jsxs16(
2262
+ Pressable13,
2110
2263
  {
2111
2264
  onPress: action.onPress,
2112
2265
  className: "rounded-md px-2 py-1.5",
2113
2266
  children: [
2114
2267
  action.iconSlot,
2115
- /* @__PURE__ */ jsx54(Text15, { className: cn51("text-xs font-medium", action.color ?? "text-destructive"), children: action.label })
2268
+ /* @__PURE__ */ jsx56(Text16, { className: cn53("text-xs font-medium", action.color ?? "text-destructive"), children: action.label })
2116
2269
  ]
2117
2270
  },
2118
2271
  action.id
@@ -2121,21 +2274,21 @@ function CartLineActions({ children, actions, className, ...viewProps }) {
2121
2274
  }
2122
2275
 
2123
2276
  // src/input/search-input.tsx
2124
- import { useId, useState as useState4 } from "react";
2125
- import { TextInput as TextInput5, View as View27 } from "react-native";
2277
+ import { useId, useState as useState5 } from "react";
2278
+ import { TextInput as TextInput5, View as View29 } from "react-native";
2126
2279
  import { Label as Label3 } from "@tallyui/primitives";
2127
- import { cn as cn52 } from "@tallyui/theme";
2128
- import { jsx as jsx55, jsxs as jsxs16 } from "react/jsx-runtime";
2280
+ import { cn as cn54 } from "@tallyui/theme";
2281
+ import { jsx as jsx57, jsxs as jsxs17 } from "react/jsx-runtime";
2129
2282
  function SearchInput({ value, onChangeText, className, placeholder = "Search...", style, onFocus, onBlur, ...props }) {
2130
2283
  const labelId = useId();
2131
- const [focused, setFocused] = useState4(false);
2132
- return /* @__PURE__ */ jsxs16(HStack, { space: "sm", className: cn52(
2284
+ const [focused, setFocused] = useState5(false);
2285
+ return /* @__PURE__ */ jsxs17(HStack, { space: "sm", className: cn54(
2133
2286
  "rounded-lg border bg-card px-3 py-2.5",
2134
2287
  focused ? "border-ring" : "border-border",
2135
2288
  className
2136
2289
  ), children: [
2137
- /* @__PURE__ */ jsx55(Label3.Root, { nativeID: labelId, asChild: true, children: /* @__PURE__ */ jsx55(View27, { "aria-hidden": true, className: "text-muted-foreground", children: /* @__PURE__ */ jsx55(SearchIcon, { size: 16 }) }) }),
2138
- /* @__PURE__ */ jsx55(
2290
+ /* @__PURE__ */ jsx57(Label3.Root, { nativeID: labelId, asChild: true, children: /* @__PURE__ */ jsx57(View29, { "aria-hidden": true, className: "text-muted-foreground", children: /* @__PURE__ */ jsx57(SearchIcon, { size: 16 }) }) }),
2291
+ /* @__PURE__ */ jsx57(
2139
2292
  TextInput5,
2140
2293
  {
2141
2294
  role: "searchbox",
@@ -2161,39 +2314,39 @@ function SearchInput({ value, onChangeText, className, placeholder = "Search..."
2161
2314
  }
2162
2315
 
2163
2316
  // src/input/filter-chip.tsx
2164
- import { useMemo } from "react";
2165
- import { Pressable as Pressable12, ScrollView as ScrollView5 } from "react-native";
2317
+ import { useMemo as useMemo2 } from "react";
2318
+ import { Pressable as Pressable14, ScrollView as ScrollView5 } from "react-native";
2166
2319
  import { ToggleGroup as ToggleGroup3 } from "@tallyui/primitives";
2167
- import { cn as cn53 } from "@tallyui/theme";
2168
- import { jsx as jsx56 } from "react/jsx-runtime";
2320
+ import { cn as cn55 } from "@tallyui/theme";
2321
+ import { jsx as jsx58 } from "react/jsx-runtime";
2169
2322
  function FilterChip({ label, active, onPress, className }) {
2170
- const value = useMemo(() => active ? [label] : [], [active, label]);
2171
- return /* @__PURE__ */ jsx56(
2323
+ const value = useMemo2(() => active ? [label] : [], [active, label]);
2324
+ return /* @__PURE__ */ jsx58(
2172
2325
  ToggleGroup3.Root,
2173
2326
  {
2174
2327
  type: "multiple",
2175
2328
  value,
2176
2329
  onValueChange: () => onPress(),
2177
- children: /* @__PURE__ */ jsx56(ToggleGroup3.Item, { value: label, asChild: true, children: /* @__PURE__ */ jsx56(
2178
- Pressable12,
2330
+ children: /* @__PURE__ */ jsx58(ToggleGroup3.Item, { value: label, asChild: true, children: /* @__PURE__ */ jsx58(
2331
+ Pressable14,
2179
2332
  {
2180
- className: cn53(
2333
+ className: cn55(
2181
2334
  "rounded-full px-3 py-1.5",
2182
2335
  active ? "bg-primary" : "bg-accent",
2183
2336
  className
2184
2337
  ),
2185
- children: /* @__PURE__ */ jsx56(Text, { className: cn53("text-xs font-semibold", active ? "text-primary-foreground" : "text-muted-foreground"), children: label })
2338
+ children: /* @__PURE__ */ jsx58(Text, { className: cn55("text-xs font-semibold", active ? "text-primary-foreground" : "text-muted-foreground"), children: label })
2186
2339
  }
2187
2340
  ) })
2188
2341
  }
2189
2342
  );
2190
2343
  }
2191
2344
  function FilterChipGroup({ chips, onChipPress, className, ...viewProps }) {
2192
- const activeValues = useMemo(
2345
+ const activeValues = useMemo2(
2193
2346
  () => chips.filter((c) => c.active).map((c) => c.label),
2194
2347
  [chips]
2195
2348
  );
2196
- const labelToIndex = useMemo(() => {
2349
+ const labelToIndex = useMemo2(() => {
2197
2350
  const map = /* @__PURE__ */ new Map();
2198
2351
  chips.forEach((chip, i) => map.set(chip.label, i));
2199
2352
  return map;
@@ -2207,28 +2360,28 @@ function FilterChipGroup({ chips, onChipPress, className, ...viewProps }) {
2207
2360
  if (index !== void 0) onChipPress(index);
2208
2361
  }
2209
2362
  }
2210
- return /* @__PURE__ */ jsx56(
2363
+ return /* @__PURE__ */ jsx58(
2211
2364
  ToggleGroup3.Root,
2212
2365
  {
2213
2366
  type: "multiple",
2214
2367
  value: activeValues,
2215
2368
  onValueChange: handleValueChange,
2216
2369
  asChild: true,
2217
- children: /* @__PURE__ */ jsx56(
2370
+ children: /* @__PURE__ */ jsx58(
2218
2371
  ScrollView5,
2219
2372
  {
2220
2373
  horizontal: true,
2221
2374
  showsHorizontalScrollIndicator: false,
2222
- contentContainerClassName: cn53("flex-row gap-2", className),
2375
+ contentContainerClassName: cn55("flex-row gap-2", className),
2223
2376
  ...viewProps,
2224
- children: chips.map((chip) => /* @__PURE__ */ jsx56(ToggleGroup3.Item, { value: chip.label, asChild: true, children: /* @__PURE__ */ jsx56(
2225
- Pressable12,
2377
+ children: chips.map((chip) => /* @__PURE__ */ jsx58(ToggleGroup3.Item, { value: chip.label, asChild: true, children: /* @__PURE__ */ jsx58(
2378
+ Pressable14,
2226
2379
  {
2227
- className: cn53(
2380
+ className: cn55(
2228
2381
  "rounded-full px-3 py-1.5",
2229
2382
  chip.active ? "bg-primary" : "bg-accent"
2230
2383
  ),
2231
- children: /* @__PURE__ */ jsx56(Text, { className: cn53("text-xs font-semibold", chip.active ? "text-primary-foreground" : "text-muted-foreground"), children: chip.label })
2384
+ children: /* @__PURE__ */ jsx58(Text, { className: cn55("text-xs font-semibold", chip.active ? "text-primary-foreground" : "text-muted-foreground"), children: chip.label })
2232
2385
  }
2233
2386
  ) }, chip.label))
2234
2387
  }
@@ -2238,10 +2391,10 @@ function FilterChipGroup({ chips, onChipPress, className, ...viewProps }) {
2238
2391
  }
2239
2392
 
2240
2393
  // src/input/quantity-stepper.tsx
2241
- import { useState as useState5 } from "react";
2242
- import { Pressable as Pressable13, Text as Text16, View as View28 } from "react-native";
2243
- import { cn as cn54 } from "@tallyui/theme";
2244
- import { jsx as jsx57, jsxs as jsxs17 } from "react/jsx-runtime";
2394
+ import { useState as useState6 } from "react";
2395
+ import { Pressable as Pressable15, Text as Text17, View as View30 } from "react-native";
2396
+ import { cn as cn56 } from "@tallyui/theme";
2397
+ import { jsx as jsx59, jsxs as jsxs18 } from "react/jsx-runtime";
2245
2398
  function QuantityStepper({
2246
2399
  defaultQuantity = 1,
2247
2400
  quantity: controlledQuantity,
@@ -2251,37 +2404,37 @@ function QuantityStepper({
2251
2404
  className,
2252
2405
  ...viewProps
2253
2406
  }) {
2254
- const [internalQuantity, setInternalQuantity] = useState5(defaultQuantity);
2407
+ const [internalQuantity, setInternalQuantity] = useState6(defaultQuantity);
2255
2408
  const quantity = controlledQuantity ?? internalQuantity;
2256
2409
  const handleChange = (next) => {
2257
2410
  if (next < min || next > max) return;
2258
2411
  if (controlledQuantity === void 0) setInternalQuantity(next);
2259
2412
  onChangeQuantity?.(next);
2260
2413
  };
2261
- return /* @__PURE__ */ jsxs17(View28, { className: cn54("flex-row items-center gap-2", className), ...viewProps, children: [
2262
- /* @__PURE__ */ jsx57(
2263
- Pressable13,
2414
+ return /* @__PURE__ */ jsxs18(View30, { className: cn56("flex-row items-center gap-2", className), ...viewProps, children: [
2415
+ /* @__PURE__ */ jsx59(
2416
+ Pressable15,
2264
2417
  {
2265
2418
  onPress: () => handleChange(quantity - 1),
2266
2419
  disabled: quantity <= min,
2267
- className: cn54(
2420
+ className: cn56(
2268
2421
  "h-8 w-8 items-center justify-center rounded-lg",
2269
2422
  quantity <= min ? "bg-muted/50" : "bg-muted"
2270
2423
  ),
2271
- children: /* @__PURE__ */ jsx57(Text16, { className: cn54("text-base font-semibold", quantity <= min ? "text-muted-foreground" : "text-foreground"), children: "\u2212" })
2424
+ children: /* @__PURE__ */ jsx59(Text17, { className: cn56("text-base font-semibold", quantity <= min ? "text-muted-foreground" : "text-foreground"), children: "\u2212" })
2272
2425
  }
2273
2426
  ),
2274
- /* @__PURE__ */ jsx57(Text16, { className: "min-w-[2rem] text-center text-base font-semibold text-foreground", children: quantity }),
2275
- /* @__PURE__ */ jsx57(
2276
- Pressable13,
2427
+ /* @__PURE__ */ jsx59(Text17, { className: "min-w-[2rem] text-center text-base font-semibold text-foreground", children: quantity }),
2428
+ /* @__PURE__ */ jsx59(
2429
+ Pressable15,
2277
2430
  {
2278
2431
  onPress: () => handleChange(quantity + 1),
2279
2432
  disabled: quantity >= max,
2280
- className: cn54(
2433
+ className: cn56(
2281
2434
  "h-8 w-8 items-center justify-center rounded-lg",
2282
2435
  quantity >= max ? "bg-muted/50" : "bg-muted"
2283
2436
  ),
2284
- children: /* @__PURE__ */ jsx57(Text16, { className: cn54("text-base font-semibold", quantity >= max ? "text-muted-foreground" : "text-foreground"), children: "+" })
2437
+ children: /* @__PURE__ */ jsx59(Text17, { className: cn56("text-base font-semibold", quantity >= max ? "text-muted-foreground" : "text-foreground"), children: "+" })
2285
2438
  }
2286
2439
  )
2287
2440
  ] });
@@ -2289,36 +2442,36 @@ function QuantityStepper({
2289
2442
 
2290
2443
  // src/customer/customer-card.tsx
2291
2444
  import { useCustomerTraits } from "@tallyui/core";
2292
- import { cn as cn55 } from "@tallyui/theme";
2293
- import { jsx as jsx58, jsxs as jsxs18 } from "react/jsx-runtime";
2445
+ import { cn as cn57 } from "@tallyui/theme";
2446
+ import { jsx as jsx60, jsxs as jsxs19 } from "react/jsx-runtime";
2294
2447
  function CustomerCardFromContext(props) {
2295
2448
  const traits = useCustomerTraits();
2296
- return traits ? /* @__PURE__ */ jsx58(CustomerCard, { ...props, traits }) : null;
2449
+ return traits ? /* @__PURE__ */ jsx60(CustomerCard, { ...props, traits }) : null;
2297
2450
  }
2298
2451
  function CustomerCard({ doc, traits, className, ...props }) {
2299
- if (!traits) return /* @__PURE__ */ jsx58(CustomerCardFromContext, { doc, className, ...props });
2452
+ if (!traits) return /* @__PURE__ */ jsx60(CustomerCardFromContext, { doc, className, ...props });
2300
2453
  const name = traits.getName(doc);
2301
2454
  const email = traits.getEmail(doc);
2302
2455
  const address = traits.getAddressSummary(doc);
2303
- return /* @__PURE__ */ jsxs18(VStack, { space: "none", className: cn55("gap-0.5", className), ...props, children: [
2304
- /* @__PURE__ */ jsx58(Text, { className: "text-sm font-semibold", children: name }),
2305
- email && /* @__PURE__ */ jsx58(Text, { className: "text-xs text-muted-foreground", children: email }),
2306
- address && /* @__PURE__ */ jsx58(Text, { className: "text-xs text-muted-foreground", children: address })
2456
+ return /* @__PURE__ */ jsxs19(VStack, { space: "none", className: cn57("gap-0.5", className), ...props, children: [
2457
+ /* @__PURE__ */ jsx60(Text, { className: "text-sm font-semibold", children: name }),
2458
+ email && /* @__PURE__ */ jsx60(Text, { className: "text-xs text-muted-foreground", children: email }),
2459
+ address && /* @__PURE__ */ jsx60(Text, { className: "text-xs text-muted-foreground", children: address })
2307
2460
  ] });
2308
2461
  }
2309
2462
 
2310
2463
  // src/customer/customer-select.tsx
2311
- import { useState as useState6 } from "react";
2312
- import { Pressable as Pressable14, ScrollView as ScrollView6, View as View29 } from "react-native";
2464
+ import { useState as useState7 } from "react";
2465
+ import { Pressable as Pressable16, ScrollView as ScrollView6, View as View31 } from "react-native";
2313
2466
  import { Select as Select2 } from "@tallyui/primitives";
2314
2467
  import { useCustomerTraits as useCustomerTraits2 } from "@tallyui/core";
2315
- import { cn as cn56 } from "@tallyui/theme";
2316
- import { jsx as jsx59, jsxs as jsxs19 } from "react/jsx-runtime";
2468
+ import { cn as cn58 } from "@tallyui/theme";
2469
+ import { jsx as jsx61, jsxs as jsxs20 } from "react/jsx-runtime";
2317
2470
  function CustomerSelect(props) {
2318
- return props.traits ? /* @__PURE__ */ jsx59(CustomerSelectView, { ...props }) : /* @__PURE__ */ jsx59(CustomerSelectFromContext, { ...props });
2471
+ return props.traits ? /* @__PURE__ */ jsx61(CustomerSelectView, { ...props }) : /* @__PURE__ */ jsx61(CustomerSelectFromContext, { ...props });
2319
2472
  }
2320
2473
  function CustomerSelectFromContext(props) {
2321
- return /* @__PURE__ */ jsx59(CustomerSelectView, { ...props, traits: useCustomerTraits2() });
2474
+ return /* @__PURE__ */ jsx61(CustomerSelectView, { ...props, traits: useCustomerTraits2() });
2322
2475
  }
2323
2476
  function CustomerSelectView({
2324
2477
  customers,
@@ -2331,7 +2484,7 @@ function CustomerSelectView({
2331
2484
  traits,
2332
2485
  ...props
2333
2486
  }) {
2334
- const [search, setSearch] = useState6("");
2487
+ const [search, setSearch] = useState7("");
2335
2488
  const selectedOption = selected && traits ? { value: traits.getId(selected), label: traits.getName(selected) } : void 0;
2336
2489
  const customerById = /* @__PURE__ */ new Map();
2337
2490
  if (traits) {
@@ -2343,14 +2496,14 @@ function CustomerSelectView({
2343
2496
  const doc = customerById.get(option.value);
2344
2497
  if (doc) onSelect(doc);
2345
2498
  }
2346
- return /* @__PURE__ */ jsx59(
2499
+ return /* @__PURE__ */ jsx61(
2347
2500
  Select2.Root,
2348
2501
  {
2349
2502
  value: selectedOption,
2350
2503
  onValueChange: handleValueChange,
2351
2504
  defaultOpen: true,
2352
- children: /* @__PURE__ */ jsxs19(VStack, { space: "sm", className: cn56(className), ...props, children: [
2353
- showSearch && /* @__PURE__ */ jsx59(
2505
+ children: /* @__PURE__ */ jsxs20(VStack, { space: "sm", className: cn58(className), ...props, children: [
2506
+ showSearch && /* @__PURE__ */ jsx61(
2354
2507
  SearchInput,
2355
2508
  {
2356
2509
  value: search,
@@ -2363,18 +2516,18 @@ function CustomerSelectView({
2363
2516
  accessibilityLabel: "Search customers"
2364
2517
  }
2365
2518
  ),
2366
- selected && traits && /* @__PURE__ */ jsx59(Select2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx59(View29, { className: "rounded-lg border border-primary bg-primary/5 px-3 py-2", children: /* @__PURE__ */ jsx59(CustomerCard, { doc: selected, traits }) }) }),
2367
- customers.length > 0 && /* @__PURE__ */ jsx59(Select2.Content, { asChild: true, forceMount: true, disablePositioningStyle: true, children: /* @__PURE__ */ jsx59(ScrollView6, { className: "max-h-60", children: customers.map((customer, index) => {
2519
+ selected && traits && /* @__PURE__ */ jsx61(Select2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx61(View31, { className: "rounded-lg border border-primary bg-primary/5 px-3 py-2", children: /* @__PURE__ */ jsx61(CustomerCard, { doc: selected, traits }) }) }),
2520
+ customers.length > 0 && /* @__PURE__ */ jsx61(Select2.Content, { asChild: true, forceMount: true, disablePositioningStyle: true, children: /* @__PURE__ */ jsx61(ScrollView6, { className: "max-h-60", children: customers.map((customer, index) => {
2368
2521
  const id = traits?.getId(customer) ?? String(index);
2369
2522
  const label = traits?.getName(customer) ?? "";
2370
2523
  const email = traits?.getEmail(customer);
2371
- return /* @__PURE__ */ jsx59(
2524
+ return /* @__PURE__ */ jsx61(
2372
2525
  Select2.Item,
2373
2526
  {
2374
2527
  value: id,
2375
2528
  label,
2376
2529
  asChild: true,
2377
- children: /* @__PURE__ */ jsx59(Pressable14, { accessibilityLabel: email ? `${label}, ${email}` : label, className: "border-b border-border px-3 py-2", children: /* @__PURE__ */ jsx59(CustomerCard, { doc: customer, traits }) })
2530
+ children: /* @__PURE__ */ jsx61(Pressable16, { accessibilityLabel: email ? `${label}, ${email}` : label, className: "border-b border-border px-3 py-2", children: /* @__PURE__ */ jsx61(CustomerCard, { doc: customer, traits }) })
2378
2531
  },
2379
2532
  id
2380
2533
  );
@@ -2385,18 +2538,18 @@ function CustomerSelectView({
2385
2538
  }
2386
2539
 
2387
2540
  // src/customer/customer-form.tsx
2388
- import { Pressable as Pressable15, Text as Text17, TextInput as TextInput6, View as View30 } from "react-native";
2389
- import { cn as cn57 } from "@tallyui/theme";
2390
- import { jsx as jsx60, jsxs as jsxs20 } from "react/jsx-runtime";
2541
+ import { Pressable as Pressable17, Text as Text18, TextInput as TextInput6, View as View32 } from "react-native";
2542
+ import { cn as cn59 } from "@tallyui/theme";
2543
+ import { jsx as jsx62, jsxs as jsxs21 } from "react/jsx-runtime";
2391
2544
  function FormField({
2392
2545
  label,
2393
2546
  value,
2394
2547
  onChangeText,
2395
2548
  ...props
2396
2549
  }) {
2397
- return /* @__PURE__ */ jsxs20(View30, { className: "gap-1", children: [
2398
- /* @__PURE__ */ jsx60(Text17, { className: "text-xs font-medium text-muted-foreground", children: label }),
2399
- /* @__PURE__ */ jsx60(
2550
+ return /* @__PURE__ */ jsxs21(View32, { className: "gap-1", children: [
2551
+ /* @__PURE__ */ jsx62(Text18, { className: "text-xs font-medium text-muted-foreground", children: label }),
2552
+ /* @__PURE__ */ jsx62(
2400
2553
  TextInput6,
2401
2554
  {
2402
2555
  value,
@@ -2417,22 +2570,22 @@ function CustomerForm({
2417
2570
  className,
2418
2571
  ...viewProps
2419
2572
  }) {
2420
- return /* @__PURE__ */ jsxs20(View30, { className: cn57("gap-3 p-4", className), ...viewProps, children: [
2421
- /* @__PURE__ */ jsxs20(View30, { className: "flex-row gap-3", children: [
2422
- /* @__PURE__ */ jsx60(View30, { className: "flex-1", children: /* @__PURE__ */ jsx60(FormField, { label: "First Name", value: values.firstName, onChangeText: (v) => onChangeField("firstName", v), placeholder: "First name" }) }),
2423
- /* @__PURE__ */ jsx60(View30, { className: "flex-1", children: /* @__PURE__ */ jsx60(FormField, { label: "Last Name", value: values.lastName, onChangeText: (v) => onChangeField("lastName", v), placeholder: "Last name" }) })
2573
+ return /* @__PURE__ */ jsxs21(View32, { className: cn59("gap-3 p-4", className), ...viewProps, children: [
2574
+ /* @__PURE__ */ jsxs21(View32, { className: "flex-row gap-3", children: [
2575
+ /* @__PURE__ */ jsx62(View32, { className: "flex-1", children: /* @__PURE__ */ jsx62(FormField, { label: "First Name", value: values.firstName, onChangeText: (v) => onChangeField("firstName", v), placeholder: "First name" }) }),
2576
+ /* @__PURE__ */ jsx62(View32, { className: "flex-1", children: /* @__PURE__ */ jsx62(FormField, { label: "Last Name", value: values.lastName, onChangeText: (v) => onChangeField("lastName", v), placeholder: "Last name" }) })
2424
2577
  ] }),
2425
- /* @__PURE__ */ jsx60(FormField, { label: "Email", value: values.email, onChangeText: (v) => onChangeField("email", v), placeholder: "email@example.com", keyboardType: "email-address" }),
2426
- /* @__PURE__ */ jsx60(FormField, { label: "Phone", value: values.phone, onChangeText: (v) => onChangeField("phone", v), placeholder: "Phone number", keyboardType: "phone-pad" }),
2427
- showAddress && /* @__PURE__ */ jsx60(FormField, { label: "Address", value: values.address, onChangeText: (v) => onChangeField("address", v), placeholder: "Street address", multiline: true }),
2428
- onSubmit && /* @__PURE__ */ jsx60(Pressable15, { onPress: onSubmit, className: "items-center rounded-lg bg-primary px-4 py-3", children: /* @__PURE__ */ jsx60(Text17, { className: "text-sm font-semibold text-primary-foreground", children: submitLabel }) })
2578
+ /* @__PURE__ */ jsx62(FormField, { label: "Email", value: values.email, onChangeText: (v) => onChangeField("email", v), placeholder: "email@example.com", keyboardType: "email-address" }),
2579
+ /* @__PURE__ */ jsx62(FormField, { label: "Phone", value: values.phone, onChangeText: (v) => onChangeField("phone", v), placeholder: "Phone number", keyboardType: "phone-pad" }),
2580
+ showAddress && /* @__PURE__ */ jsx62(FormField, { label: "Address", value: values.address, onChangeText: (v) => onChangeField("address", v), placeholder: "Street address", multiline: true }),
2581
+ onSubmit && /* @__PURE__ */ jsx62(Pressable17, { onPress: onSubmit, className: "items-center rounded-lg bg-primary px-4 py-3", children: /* @__PURE__ */ jsx62(Text18, { className: "text-sm font-semibold text-primary-foreground", children: submitLabel }) })
2429
2582
  ] });
2430
2583
  }
2431
2584
 
2432
2585
  // src/customer/customer-order-history.tsx
2433
- import { ScrollView as ScrollView7, Text as Text18, View as View31 } from "react-native";
2434
- import { cn as cn58 } from "@tallyui/theme";
2435
- import { jsx as jsx61, jsxs as jsxs21 } from "react/jsx-runtime";
2586
+ import { ScrollView as ScrollView7, Text as Text19, View as View33 } from "react-native";
2587
+ import { cn as cn60 } from "@tallyui/theme";
2588
+ import { jsx as jsx63, jsxs as jsxs22 } from "react/jsx-runtime";
2436
2589
  function CustomerOrderHistory({
2437
2590
  orders,
2438
2591
  renderItem,
@@ -2440,31 +2593,31 @@ function CustomerOrderHistory({
2440
2593
  className,
2441
2594
  ...viewProps
2442
2595
  }) {
2443
- return /* @__PURE__ */ jsxs21(View31, { className: cn58("flex-1", className), ...viewProps, children: [
2444
- /* @__PURE__ */ jsx61(Text18, { className: "px-3 py-2 text-xs font-semibold text-muted-foreground", children: "Order History" }),
2445
- orders.length > 0 ? /* @__PURE__ */ jsx61(ScrollView7, { contentContainerClassName: "gap-2 px-3 pb-3", children: orders.map((order, index) => /* @__PURE__ */ jsx61(View31, { children: renderItem(order, index) }, order.id ?? index)) }) : emptyState ?? null
2596
+ return /* @__PURE__ */ jsxs22(View33, { className: cn60("flex-1", className), ...viewProps, children: [
2597
+ /* @__PURE__ */ jsx63(Text19, { className: "px-3 py-2 text-xs font-semibold text-muted-foreground", children: "Order History" }),
2598
+ orders.length > 0 ? /* @__PURE__ */ jsx63(ScrollView7, { contentContainerClassName: "gap-2 px-3 pb-3", children: orders.map((order, index) => /* @__PURE__ */ jsx63(View33, { children: renderItem(order, index) }, order.id ?? index)) }) : emptyState ?? null
2446
2599
  ] });
2447
2600
  }
2448
2601
 
2449
2602
  // src/customer/customer-picker.tsx
2450
- import { useEffect, useRef, useState as useState7 } from "react";
2451
- import { Pressable as Pressable16, Text as Text19, TextInput as TextInput7, View as View32 } from "react-native";
2603
+ import { useEffect, useRef, useState as useState8 } from "react";
2604
+ import { Pressable as Pressable18, Text as Text20, TextInput as TextInput7, View as View34 } from "react-native";
2452
2605
  import { customerTraits, CustomerServiceError, ConnectorUnauthorizedError } from "@tallyui/core";
2453
- import { cn as cn59 } from "@tallyui/theme";
2454
- import { jsx as jsx62, jsxs as jsxs22 } from "react/jsx-runtime";
2606
+ import { cn as cn61 } from "@tallyui/theme";
2607
+ import { jsx as jsx64, jsxs as jsxs23 } from "react/jsx-runtime";
2455
2608
  var EMAIL_MAX = 254;
2456
2609
  var EMAIL_SHAPE = /^[^\s@\u0000]+@[^\s@\u0000]+\.[^\s@\u0000]+$/u;
2457
2610
  function CustomerPicker({ search, create, selected, onSelect, onError, online, debounceMs = 250, className }) {
2458
- const [query, setQuery] = useState7("");
2459
- const [customers, setCustomers] = useState7([]);
2460
- const [error, setError] = useState7(null);
2461
- const [showForm, setShowForm] = useState7(false);
2462
- const [creating, setCreating] = useState7(false);
2463
- const [values, setValues] = useState7({ firstName: "", lastName: "", email: "", phone: "", address: "" });
2611
+ const [query, setQuery] = useState8("");
2612
+ const [customers, setCustomers] = useState8([]);
2613
+ const [error, setError] = useState8(null);
2614
+ const [showForm, setShowForm] = useState8(false);
2615
+ const [creating, setCreating] = useState8(false);
2616
+ const [values, setValues] = useState8({ firstName: "", lastName: "", email: "", phone: "", address: "" });
2464
2617
  const sequence = useRef(0);
2465
2618
  const searchRef = useRef(search);
2466
2619
  searchRef.current = search;
2467
- const [noResults, setNoResults] = useState7(false);
2620
+ const [noResults, setNoResults] = useState8(false);
2468
2621
  function handleError(error2) {
2469
2622
  if (error2 instanceof CustomerServiceError) {
2470
2623
  setError(error2.code === "network" ? "Couldn't reach the store. Try again." : error2.code === "server" ? "The store couldn't do that. Try again." : error2.message);
@@ -2519,13 +2672,13 @@ function CustomerPicker({ search, create, selected, onSelect, onError, online, d
2519
2672
  setCreating(false);
2520
2673
  }
2521
2674
  }
2522
- return /* @__PURE__ */ jsxs22(View32, { className: cn59("gap-3", className), children: [
2523
- selected && /* @__PURE__ */ jsxs22(View32, { children: [
2524
- /* @__PURE__ */ jsx62(CustomerCard, { doc: selected, traits: customerTraits }),
2525
- /* @__PURE__ */ jsx62(Pressable16, { accessibilityRole: "button", className: "items-center rounded-lg border border-border px-4 py-3", onPress: () => onSelect(null), children: /* @__PURE__ */ jsx62(Text19, { className: "text-sm font-semibold text-foreground", children: "Remove customer" }) })
2675
+ return /* @__PURE__ */ jsxs23(View34, { className: cn61("gap-3", className), children: [
2676
+ selected && /* @__PURE__ */ jsxs23(View34, { children: [
2677
+ /* @__PURE__ */ jsx64(CustomerCard, { doc: selected, traits: customerTraits }),
2678
+ /* @__PURE__ */ jsx64(Pressable18, { accessibilityRole: "button", className: "items-center rounded-lg border border-border px-4 py-3", onPress: () => onSelect(null), children: /* @__PURE__ */ jsx64(Text20, { className: "text-sm font-semibold text-foreground", children: "Remove customer" }) })
2526
2679
  ] }),
2527
- /* @__PURE__ */ jsx62(Text19, { className: "text-xs font-medium text-muted-foreground", children: "Search customers" }),
2528
- /* @__PURE__ */ jsx62(
2680
+ /* @__PURE__ */ jsx64(Text20, { className: "text-xs font-medium text-muted-foreground", children: "Search customers" }),
2681
+ /* @__PURE__ */ jsx64(
2529
2682
  TextInput7,
2530
2683
  {
2531
2684
  accessibilityLabel: "Search customers",
@@ -2537,10 +2690,10 @@ function CustomerPicker({ search, create, selected, onSelect, onError, online, d
2537
2690
  placeholder: "Name or email"
2538
2691
  }
2539
2692
  ),
2540
- !online && /* @__PURE__ */ jsx62(Text19, { className: "text-sm text-muted-foreground", children: "Connect to search or add customers." }),
2541
- noResults && /* @__PURE__ */ jsx62(Text19, { className: "text-sm text-muted-foreground", children: "No customers found." }),
2542
- error && /* @__PURE__ */ jsx62(Text19, { accessibilityRole: "alert", className: "text-sm text-destructive", children: error }),
2543
- /* @__PURE__ */ jsx62(
2693
+ !online && /* @__PURE__ */ jsx64(Text20, { className: "text-sm text-muted-foreground", children: "Connect to search or add customers." }),
2694
+ noResults && /* @__PURE__ */ jsx64(Text20, { className: "text-sm text-muted-foreground", children: "No customers found." }),
2695
+ error && /* @__PURE__ */ jsx64(Text20, { accessibilityRole: "alert", className: "text-sm text-destructive", children: error }),
2696
+ /* @__PURE__ */ jsx64(
2544
2697
  CustomerSelect,
2545
2698
  {
2546
2699
  customers,
@@ -2553,18 +2706,18 @@ function CustomerPicker({ search, create, selected, onSelect, onError, online, d
2553
2706
  }
2554
2707
  }
2555
2708
  ),
2556
- create && /* @__PURE__ */ jsx62(
2557
- Pressable16,
2709
+ create && /* @__PURE__ */ jsx64(
2710
+ Pressable18,
2558
2711
  {
2559
2712
  accessibilityRole: "button",
2560
2713
  disabled: !online || creating,
2561
2714
  onPress: () => setShowForm(true),
2562
- className: cn59("items-center rounded-lg border border-border px-4 py-3", (!online || creating) && "opacity-50"),
2563
- children: /* @__PURE__ */ jsx62(Text19, { className: "text-sm font-semibold text-foreground", children: "New customer" })
2715
+ className: cn61("items-center rounded-lg border border-border px-4 py-3", (!online || creating) && "opacity-50"),
2716
+ children: /* @__PURE__ */ jsx64(Text20, { className: "text-sm font-semibold text-foreground", children: "New customer" })
2564
2717
  }
2565
2718
  ),
2566
- showForm && /* @__PURE__ */ jsxs22(View32, { children: [
2567
- /* @__PURE__ */ jsx62(
2719
+ showForm && /* @__PURE__ */ jsxs23(View34, { children: [
2720
+ /* @__PURE__ */ jsx64(
2568
2721
  CustomerForm,
2569
2722
  {
2570
2723
  values,
@@ -2572,19 +2725,19 @@ function CustomerPicker({ search, create, selected, onSelect, onError, online, d
2572
2725
  onChangeField: (field, value) => setValues((current) => ({ ...current, [field]: value }))
2573
2726
  }
2574
2727
  ),
2575
- /* @__PURE__ */ jsxs22(View32, { className: "flex-row gap-3", children: [
2576
- /* @__PURE__ */ jsx62(
2577
- Pressable16,
2728
+ /* @__PURE__ */ jsxs23(View34, { className: "flex-row gap-3", children: [
2729
+ /* @__PURE__ */ jsx64(
2730
+ Pressable18,
2578
2731
  {
2579
2732
  accessibilityRole: "button",
2580
2733
  disabled: !online || creating || !values.email.trim(),
2581
2734
  onPress: submit,
2582
- className: cn59("items-center rounded-lg bg-primary px-4 py-3", (!online || creating || !values.email.trim()) && "opacity-50"),
2583
- children: /* @__PURE__ */ jsx62(Text19, { className: "text-sm font-semibold text-primary-foreground", children: "Save Customer" })
2735
+ className: cn61("items-center rounded-lg bg-primary px-4 py-3", (!online || creating || !values.email.trim()) && "opacity-50"),
2736
+ children: /* @__PURE__ */ jsx64(Text20, { className: "text-sm font-semibold text-primary-foreground", children: "Save Customer" })
2584
2737
  }
2585
2738
  ),
2586
- /* @__PURE__ */ jsx62(
2587
- Pressable16,
2739
+ /* @__PURE__ */ jsx64(
2740
+ Pressable18,
2588
2741
  {
2589
2742
  accessibilityRole: "button",
2590
2743
  className: "items-center rounded-lg border border-border px-4 py-3",
@@ -2592,7 +2745,7 @@ function CustomerPicker({ search, create, selected, onSelect, onError, online, d
2592
2745
  setShowForm(false);
2593
2746
  setValues({ firstName: "", lastName: "", email: "", phone: "", address: "" });
2594
2747
  },
2595
- children: /* @__PURE__ */ jsx62(Text19, { className: "text-sm font-semibold text-foreground", children: "Cancel" })
2748
+ children: /* @__PURE__ */ jsx64(Text20, { className: "text-sm font-semibold text-foreground", children: "Cancel" })
2596
2749
  }
2597
2750
  )
2598
2751
  ] })
@@ -2601,40 +2754,40 @@ function CustomerPicker({ search, create, selected, onSelect, onError, online, d
2601
2754
  }
2602
2755
 
2603
2756
  // src/checkout/payment-method-card.tsx
2604
- import { Pressable as Pressable17, View as View33 } from "react-native";
2605
- import { cn as cn60 } from "@tallyui/theme";
2606
- import { jsx as jsx63, jsxs as jsxs23 } from "react/jsx-runtime";
2757
+ import { Pressable as Pressable19, View as View35 } from "react-native";
2758
+ import { cn as cn62 } from "@tallyui/theme";
2759
+ import { jsx as jsx65, jsxs as jsxs24 } from "react/jsx-runtime";
2607
2760
  function PaymentMethodCard({ label, selected, onPress, icon, className, ...props }) {
2608
- return /* @__PURE__ */ jsx63(Pressable17, { onPress, ...props, children: /* @__PURE__ */ jsxs23(
2761
+ return /* @__PURE__ */ jsx65(Pressable19, { onPress, ...props, children: /* @__PURE__ */ jsxs24(
2609
2762
  HStack,
2610
2763
  {
2611
- className: cn60(
2764
+ className: cn62(
2612
2765
  "rounded-lg border px-4 py-3",
2613
2766
  selected ? "border-primary bg-primary/5" : "border-border bg-card",
2614
2767
  className
2615
2768
  ),
2616
2769
  children: [
2617
- icon && /* @__PURE__ */ jsx63(View33, { children: icon }),
2618
- /* @__PURE__ */ jsx63(Text, { className: cn60("flex-1 text-sm font-medium", selected ? "text-primary" : ""), children: label }),
2619
- selected && /* @__PURE__ */ jsx63(View33, { className: "h-5 w-5 items-center justify-center rounded-full bg-primary", children: /* @__PURE__ */ jsx63(Text, { className: "text-xs text-primary-foreground", children: "\u2713" }) })
2770
+ icon && /* @__PURE__ */ jsx65(View35, { children: icon }),
2771
+ /* @__PURE__ */ jsx65(Text, { className: cn62("flex-1 text-sm font-medium", selected ? "text-primary" : ""), children: label }),
2772
+ selected && /* @__PURE__ */ jsx65(View35, { className: "h-5 w-5 items-center justify-center rounded-full bg-primary", children: /* @__PURE__ */ jsx65(Text, { className: "text-xs text-primary-foreground", children: "\u2713" }) })
2620
2773
  ]
2621
2774
  }
2622
2775
  ) });
2623
2776
  }
2624
2777
 
2625
2778
  // src/checkout/order-summary-line.tsx
2626
- import { cn as cn61 } from "@tallyui/theme";
2627
- import { jsx as jsx64, jsxs as jsxs24 } from "react/jsx-runtime";
2779
+ import { cn as cn63 } from "@tallyui/theme";
2780
+ import { jsx as jsx66, jsxs as jsxs25 } from "react/jsx-runtime";
2628
2781
  function OrderSummaryLine({ label, amount, bold = false, className, ...props }) {
2629
- return /* @__PURE__ */ jsxs24(HStack, { space: "none", className: cn61("justify-between", className), ...props, children: [
2630
- /* @__PURE__ */ jsx64(Text, { className: cn61("text-sm", bold ? "font-bold" : "text-muted-foreground"), children: label }),
2631
- /* @__PURE__ */ jsx64(Text, { className: cn61("text-sm", bold && "font-bold"), children: amount })
2782
+ return /* @__PURE__ */ jsxs25(HStack, { space: "none", className: cn63("justify-between", className), ...props, children: [
2783
+ /* @__PURE__ */ jsx66(Text, { className: cn63("text-sm", bold ? "font-bold" : "text-muted-foreground"), children: label }),
2784
+ /* @__PURE__ */ jsx66(Text, { className: cn63("text-sm", bold && "font-bold"), children: amount })
2632
2785
  ] });
2633
2786
  }
2634
2787
 
2635
2788
  // src/checkout/payment-selector.tsx
2636
- import { cn as cn62 } from "@tallyui/theme";
2637
- import { jsx as jsx65 } from "react/jsx-runtime";
2789
+ import { cn as cn64 } from "@tallyui/theme";
2790
+ import { jsx as jsx67 } from "react/jsx-runtime";
2638
2791
  function PaymentSelector({
2639
2792
  methods,
2640
2793
  selected,
@@ -2642,7 +2795,7 @@ function PaymentSelector({
2642
2795
  className,
2643
2796
  ...props
2644
2797
  }) {
2645
- return /* @__PURE__ */ jsx65(VStack, { space: "sm", className: cn62(className), ...props, children: methods.map((method) => /* @__PURE__ */ jsx65(
2798
+ return /* @__PURE__ */ jsx67(VStack, { space: "sm", className: cn64(className), ...props, children: methods.map((method) => /* @__PURE__ */ jsx67(
2646
2799
  PaymentMethodCard,
2647
2800
  {
2648
2801
  label: method.label,
@@ -2655,9 +2808,9 @@ function PaymentSelector({
2655
2808
  }
2656
2809
 
2657
2810
  // src/checkout/order-summary.tsx
2658
- import { View as View34 } from "react-native";
2659
- import { cn as cn63 } from "@tallyui/theme";
2660
- import { jsx as jsx66, jsxs as jsxs25 } from "react/jsx-runtime";
2811
+ import { View as View36 } from "react-native";
2812
+ import { cn as cn65 } from "@tallyui/theme";
2813
+ import { jsx as jsx68, jsxs as jsxs26 } from "react/jsx-runtime";
2661
2814
  function OrderSummary({
2662
2815
  subtotal,
2663
2816
  tax,
@@ -2669,34 +2822,34 @@ function OrderSummary({
2669
2822
  className,
2670
2823
  ...props
2671
2824
  }) {
2672
- return /* @__PURE__ */ jsxs25(VStack, { space: "none", className: cn63("gap-1.5 px-3 py-3", className), ...props, children: [
2673
- header && /* @__PURE__ */ jsx66(View34, { className: "mb-2", children: header }),
2674
- /* @__PURE__ */ jsx66(OrderSummaryLine, { label: "Subtotal", amount: subtotal }),
2675
- tax && /* @__PURE__ */ jsx66(OrderSummaryLine, { label: taxLabel, amount: tax }),
2676
- /* @__PURE__ */ jsx66(OrderSummaryLine, { label: "Total", amount: total, bold: true }),
2677
- payments && payments.length > 0 && /* @__PURE__ */ jsx66(VStack, { space: "none", className: "mt-2 gap-1.5 border-t border-border pt-2", children: payments.map((payment) => /* @__PURE__ */ jsx66(OrderSummaryLine, { label: payment.label, amount: payment.amount }, payment.label)) }),
2678
- footer && /* @__PURE__ */ jsx66(View34, { className: "mt-2", children: footer })
2825
+ return /* @__PURE__ */ jsxs26(VStack, { space: "none", className: cn65("gap-1.5 px-3 py-3", className), ...props, children: [
2826
+ header && /* @__PURE__ */ jsx68(View36, { className: "mb-2", children: header }),
2827
+ /* @__PURE__ */ jsx68(OrderSummaryLine, { label: "Subtotal", amount: subtotal }),
2828
+ tax && /* @__PURE__ */ jsx68(OrderSummaryLine, { label: taxLabel, amount: tax }),
2829
+ /* @__PURE__ */ jsx68(OrderSummaryLine, { label: "Total", amount: total, bold: true }),
2830
+ payments && payments.length > 0 && /* @__PURE__ */ jsx68(VStack, { space: "none", className: "mt-2 gap-1.5 border-t border-border pt-2", children: payments.map((payment) => /* @__PURE__ */ jsx68(OrderSummaryLine, { label: payment.label, amount: payment.amount }, payment.label)) }),
2831
+ footer && /* @__PURE__ */ jsx68(View36, { className: "mt-2", children: footer })
2679
2832
  ] });
2680
2833
  }
2681
2834
 
2682
2835
  // src/checkout/change-display.tsx
2683
- import { Text as Text20, View as View35 } from "react-native";
2836
+ import { Text as Text21, View as View37 } from "react-native";
2684
2837
  import { formatMoney as formatMoney4 } from "@tallyui/core";
2685
- import { cn as cn64 } from "@tallyui/theme";
2686
- import { jsx as jsx67, jsxs as jsxs26 } from "react/jsx-runtime";
2838
+ import { cn as cn66 } from "@tallyui/theme";
2839
+ import { jsx as jsx69, jsxs as jsxs27 } from "react/jsx-runtime";
2687
2840
  function ChangeDisplay({ change, locale, className, ...viewProps }) {
2688
- return /* @__PURE__ */ jsxs26(View35, { className: cn64("items-center gap-1 rounded-xl bg-muted p-4", className), ...viewProps, children: [
2689
- /* @__PURE__ */ jsx67(Text20, { className: "text-sm text-muted-foreground", children: "Change Due" }),
2690
- /* @__PURE__ */ jsx67(Text20, { className: "text-3xl font-bold text-success", children: formatMoney4(change, locale) ?? "\u2014" })
2841
+ return /* @__PURE__ */ jsxs27(View37, { className: cn66("items-center gap-1 rounded-xl bg-muted p-4", className), ...viewProps, children: [
2842
+ /* @__PURE__ */ jsx69(Text21, { className: "text-sm text-muted-foreground", children: "Change Due" }),
2843
+ /* @__PURE__ */ jsx69(Text21, { className: "text-3xl font-bold text-success", children: formatMoney4(change, locale) ?? "\u2014" })
2691
2844
  ] });
2692
2845
  }
2693
2846
 
2694
2847
  // src/checkout/cash-tendered.tsx
2695
- import { useEffect as useEffect2, useRef as useRef2, useState as useState8 } from "react";
2696
- import { Pressable as Pressable18, Text as Text21, TextInput as TextInput8, View as View36 } from "react-native";
2848
+ import { useEffect as useEffect2, useRef as useRef2, useState as useState9 } from "react";
2849
+ import { Pressable as Pressable20, Text as Text22, TextInput as TextInput8, View as View38 } from "react-native";
2697
2850
  import { formatMoney as formatMoney5, minorUnitDigits as minorUnitDigits2, moneyFromDecimalString } from "@tallyui/core";
2698
- import { cn as cn65 } from "@tallyui/theme";
2699
- import { jsx as jsx68, jsxs as jsxs27 } from "react/jsx-runtime";
2851
+ import { cn as cn67 } from "@tallyui/theme";
2852
+ import { jsx as jsx70, jsxs as jsxs28 } from "react/jsx-runtime";
2700
2853
  function defaultQuickAmounts(total) {
2701
2854
  const unit = 10 ** minorUnitDigits2(total.currency);
2702
2855
  const amounts = [
@@ -2717,13 +2870,13 @@ function CashTendered({
2717
2870
  className,
2718
2871
  ...viewProps
2719
2872
  }) {
2720
- const [internalAmount, setInternalAmount] = useState8(defaultAmount ?? total);
2873
+ const [internalAmount, setInternalAmount] = useState9(defaultAmount ?? total);
2721
2874
  const amount = controlledAmount ?? internalAmount;
2722
2875
  const buttons = quickAmounts ?? defaultQuickAmounts(total);
2723
2876
  const digits = minorUnitDigits2(amount.currency);
2724
2877
  const amountText = String(Math.abs(amount.amount)).padStart(digits + 1, "0");
2725
2878
  const decimal2 = (amount.amount < 0 ? "-" : "") + (digits ? `${amountText.slice(0, -digits)}.${amountText.slice(-digits)}` : amountText);
2726
- const [text, setText] = useState8(decimal2);
2879
+ const [text, setText] = useState9(decimal2);
2727
2880
  const lastTextAmount = useRef2(amount);
2728
2881
  useEffect2(() => {
2729
2882
  if (amount.amount !== lastTextAmount.current.amount || amount.currency !== lastTextAmount.current.currency) {
@@ -2735,20 +2888,20 @@ function CashTendered({
2735
2888
  if (controlledAmount === void 0) setInternalAmount(value);
2736
2889
  onChangeAmount?.(value);
2737
2890
  };
2738
- return /* @__PURE__ */ jsxs27(View36, { className: cn65("gap-3", className), ...viewProps, children: [
2739
- /* @__PURE__ */ jsx68(Text21, { className: "text-sm font-semibold text-foreground", children: "Cash Tendered" }),
2740
- /* @__PURE__ */ jsx68(View36, { className: "flex-row flex-wrap gap-2", children: buttons.map((val) => /* @__PURE__ */ jsx68(
2741
- Pressable18,
2891
+ return /* @__PURE__ */ jsxs28(View38, { className: cn67("gap-3", className), ...viewProps, children: [
2892
+ /* @__PURE__ */ jsx70(Text22, { className: "text-sm font-semibold text-foreground", children: "Cash Tendered" }),
2893
+ /* @__PURE__ */ jsx70(View38, { className: "flex-row flex-wrap gap-2", children: buttons.map((val) => /* @__PURE__ */ jsx70(
2894
+ Pressable20,
2742
2895
  {
2743
2896
  onPress: () => handleChange(val),
2744
- className: cn65(
2897
+ className: cn67(
2745
2898
  "rounded-lg border px-4 py-2",
2746
2899
  amount.amount === val.amount && amount.currency === val.currency ? "border-primary bg-primary" : "border-input bg-card"
2747
2900
  ),
2748
- children: /* @__PURE__ */ jsx68(
2749
- Text21,
2901
+ children: /* @__PURE__ */ jsx70(
2902
+ Text22,
2750
2903
  {
2751
- className: cn65(
2904
+ className: cn67(
2752
2905
  "text-sm font-semibold",
2753
2906
  amount.amount === val.amount && amount.currency === val.currency ? "text-primary-foreground" : "text-foreground"
2754
2907
  ),
@@ -2758,7 +2911,7 @@ function CashTendered({
2758
2911
  },
2759
2912
  `${val.currency}:${val.amount}`
2760
2913
  )) }),
2761
- /* @__PURE__ */ jsx68(
2914
+ /* @__PURE__ */ jsx70(
2762
2915
  TextInput8,
2763
2916
  {
2764
2917
  value: text,
@@ -2780,9 +2933,9 @@ function CashTendered({
2780
2933
  }
2781
2934
 
2782
2935
  // src/checkout/receipt-preview.tsx
2783
- import { Text as Text22, View as View37 } from "react-native";
2784
- import { cn as cn66 } from "@tallyui/theme";
2785
- import { jsx as jsx69, jsxs as jsxs28 } from "react/jsx-runtime";
2936
+ import { Text as Text23, View as View39 } from "react-native";
2937
+ import { cn as cn68 } from "@tallyui/theme";
2938
+ import { jsx as jsx71, jsxs as jsxs29 } from "react/jsx-runtime";
2786
2939
  function ReceiptPreview({
2787
2940
  items,
2788
2941
  subtotal,
@@ -2794,42 +2947,42 @@ function ReceiptPreview({
2794
2947
  className,
2795
2948
  ...viewProps
2796
2949
  }) {
2797
- return /* @__PURE__ */ jsxs28(View37, { className: cn66("rounded-lg border border-border bg-card p-4", className), ...viewProps, children: [
2798
- headerSlot && /* @__PURE__ */ jsx69(View37, { className: "mb-3 items-center border-b border-dashed border-border pb-3", children: headerSlot }),
2799
- /* @__PURE__ */ jsx69(View37, { className: "gap-1", children: items.map((item, i) => /* @__PURE__ */ jsxs28(View37, { className: "flex-row justify-between", children: [
2800
- /* @__PURE__ */ jsxs28(Text22, { className: "flex-1 text-sm text-foreground", children: [
2950
+ return /* @__PURE__ */ jsxs29(View39, { className: cn68("rounded-lg border border-border bg-card p-4", className), ...viewProps, children: [
2951
+ headerSlot && /* @__PURE__ */ jsx71(View39, { className: "mb-3 items-center border-b border-dashed border-border pb-3", children: headerSlot }),
2952
+ /* @__PURE__ */ jsx71(View39, { className: "gap-1", children: items.map((item, i) => /* @__PURE__ */ jsxs29(View39, { className: "flex-row justify-between", children: [
2953
+ /* @__PURE__ */ jsxs29(Text23, { className: "flex-1 text-sm text-foreground", children: [
2801
2954
  item.name,
2802
2955
  " x",
2803
2956
  item.quantity
2804
2957
  ] }),
2805
- /* @__PURE__ */ jsx69(Text22, { className: "text-sm text-foreground", children: item.total })
2958
+ /* @__PURE__ */ jsx71(Text23, { className: "text-sm text-foreground", children: item.total })
2806
2959
  ] }, i)) }),
2807
- /* @__PURE__ */ jsxs28(View37, { className: "mt-3 gap-1 border-t border-dashed border-border pt-3", children: [
2808
- /* @__PURE__ */ jsxs28(View37, { className: "flex-row justify-between", children: [
2809
- /* @__PURE__ */ jsx69(Text22, { className: "text-sm text-muted-foreground", children: "Subtotal" }),
2810
- /* @__PURE__ */ jsx69(Text22, { className: "text-sm text-foreground", children: subtotal })
2960
+ /* @__PURE__ */ jsxs29(View39, { className: "mt-3 gap-1 border-t border-dashed border-border pt-3", children: [
2961
+ /* @__PURE__ */ jsxs29(View39, { className: "flex-row justify-between", children: [
2962
+ /* @__PURE__ */ jsx71(Text23, { className: "text-sm text-muted-foreground", children: "Subtotal" }),
2963
+ /* @__PURE__ */ jsx71(Text23, { className: "text-sm text-foreground", children: subtotal })
2811
2964
  ] }),
2812
- /* @__PURE__ */ jsxs28(View37, { className: "flex-row justify-between", children: [
2813
- /* @__PURE__ */ jsx69(Text22, { className: "text-sm text-muted-foreground", children: "Tax" }),
2814
- /* @__PURE__ */ jsx69(Text22, { className: "text-sm text-foreground", children: tax })
2965
+ /* @__PURE__ */ jsxs29(View39, { className: "flex-row justify-between", children: [
2966
+ /* @__PURE__ */ jsx71(Text23, { className: "text-sm text-muted-foreground", children: "Tax" }),
2967
+ /* @__PURE__ */ jsx71(Text23, { className: "text-sm text-foreground", children: tax })
2815
2968
  ] }),
2816
- /* @__PURE__ */ jsxs28(View37, { className: "flex-row justify-between border-t border-border pt-1", children: [
2817
- /* @__PURE__ */ jsx69(Text22, { className: "text-sm font-bold text-foreground", children: "Total" }),
2818
- /* @__PURE__ */ jsx69(Text22, { className: "text-sm font-bold text-foreground", children: total })
2969
+ /* @__PURE__ */ jsxs29(View39, { className: "flex-row justify-between border-t border-border pt-1", children: [
2970
+ /* @__PURE__ */ jsx71(Text23, { className: "text-sm font-bold text-foreground", children: "Total" }),
2971
+ /* @__PURE__ */ jsx71(Text23, { className: "text-sm font-bold text-foreground", children: total })
2819
2972
  ] })
2820
2973
  ] }),
2821
- payments && payments.length > 0 && /* @__PURE__ */ jsx69(View37, { className: "mt-3 gap-1 border-t border-dashed border-border pt-3", children: payments.map((p, i) => /* @__PURE__ */ jsxs28(View37, { className: "flex-row justify-between", children: [
2822
- /* @__PURE__ */ jsx69(Text22, { className: "text-sm text-muted-foreground", children: p.method }),
2823
- /* @__PURE__ */ jsx69(Text22, { className: "text-sm text-foreground", children: p.amount })
2974
+ payments && payments.length > 0 && /* @__PURE__ */ jsx71(View39, { className: "mt-3 gap-1 border-t border-dashed border-border pt-3", children: payments.map((p, i) => /* @__PURE__ */ jsxs29(View39, { className: "flex-row justify-between", children: [
2975
+ /* @__PURE__ */ jsx71(Text23, { className: "text-sm text-muted-foreground", children: p.method }),
2976
+ /* @__PURE__ */ jsx71(Text23, { className: "text-sm text-foreground", children: p.amount })
2824
2977
  ] }, i)) }),
2825
- footerSlot && /* @__PURE__ */ jsx69(View37, { className: "mt-3 items-center border-t border-dashed border-border pt-3", children: footerSlot })
2978
+ footerSlot && /* @__PURE__ */ jsx71(View39, { className: "mt-3 items-center border-t border-dashed border-border pt-3", children: footerSlot })
2826
2979
  ] });
2827
2980
  }
2828
2981
 
2829
2982
  // src/order/order-status-badge.tsx
2830
- import { Text as Text23, View as View38 } from "react-native";
2831
- import { cn as cn67 } from "@tallyui/theme";
2832
- import { jsx as jsx70, jsxs as jsxs29 } from "react/jsx-runtime";
2983
+ import { Text as Text24, View as View40 } from "react-native";
2984
+ import { cn as cn69 } from "@tallyui/theme";
2985
+ import { jsx as jsx72, jsxs as jsxs30 } from "react/jsx-runtime";
2833
2986
  var STATUS_CONFIG = {
2834
2987
  pending: { label: "Pending", badge: "bg-warning/15", dot: "bg-warning", text: "text-foreground" },
2835
2988
  processing: { label: "Processing", badge: "bg-info/15", dot: "bg-info", text: "text-foreground" },
@@ -2839,23 +2992,23 @@ var STATUS_CONFIG = {
2839
2992
  };
2840
2993
  function OrderStatusBadge({ status, className, ...viewProps }) {
2841
2994
  const config = STATUS_CONFIG[status] ?? STATUS_CONFIG.pending;
2842
- return /* @__PURE__ */ jsxs29(
2843
- View38,
2995
+ return /* @__PURE__ */ jsxs30(
2996
+ View40,
2844
2997
  {
2845
- className: cn67("flex-row items-center self-start gap-1.5 rounded-xl px-2 py-1", config.badge, className),
2998
+ className: cn69("flex-row items-center self-start gap-1.5 rounded-xl px-2 py-1", config.badge, className),
2846
2999
  ...viewProps,
2847
3000
  children: [
2848
- /* @__PURE__ */ jsx70(View38, { className: cn67("h-1.5 w-1.5 rounded-full", config.dot) }),
2849
- /* @__PURE__ */ jsx70(Text23, { className: cn67("text-xs font-semibold", config.text), children: config.label })
3001
+ /* @__PURE__ */ jsx72(View40, { className: cn69("h-1.5 w-1.5 rounded-full", config.dot) }),
3002
+ /* @__PURE__ */ jsx72(Text24, { className: cn69("text-xs font-semibold", config.text), children: config.label })
2850
3003
  ]
2851
3004
  }
2852
3005
  );
2853
3006
  }
2854
3007
 
2855
3008
  // src/order/order-card.tsx
2856
- import { Pressable as Pressable19, Text as Text24, View as View39 } from "react-native";
2857
- import { cn as cn68 } from "@tallyui/theme";
2858
- import { jsx as jsx71, jsxs as jsxs30 } from "react/jsx-runtime";
3009
+ import { Pressable as Pressable21, Text as Text25, View as View41 } from "react-native";
3010
+ import { cn as cn70 } from "@tallyui/theme";
3011
+ import { jsx as jsx73, jsxs as jsxs31 } from "react/jsx-runtime";
2859
3012
  function OrderCard({
2860
3013
  orderNumber,
2861
3014
  date,
@@ -2866,24 +3019,24 @@ function OrderCard({
2866
3019
  className,
2867
3020
  ...viewProps
2868
3021
  }) {
2869
- const Wrapper = onPress ? Pressable19 : View39;
2870
- return /* @__PURE__ */ jsxs30(
3022
+ const Wrapper = onPress ? Pressable21 : View41;
3023
+ return /* @__PURE__ */ jsxs31(
2871
3024
  Wrapper,
2872
3025
  {
2873
3026
  onPress,
2874
- className: cn68("gap-2 rounded-lg border border-border bg-card p-3", className),
3027
+ className: cn70("gap-2 rounded-lg border border-border bg-card p-3", className),
2875
3028
  ...viewProps,
2876
3029
  children: [
2877
- /* @__PURE__ */ jsxs30(View39, { className: "flex-row items-center justify-between", children: [
2878
- /* @__PURE__ */ jsx71(Text24, { className: "text-sm font-semibold text-foreground", children: orderNumber }),
2879
- /* @__PURE__ */ jsx71(OrderStatusBadge, { status })
3030
+ /* @__PURE__ */ jsxs31(View41, { className: "flex-row items-center justify-between", children: [
3031
+ /* @__PURE__ */ jsx73(Text25, { className: "text-sm font-semibold text-foreground", children: orderNumber }),
3032
+ /* @__PURE__ */ jsx73(OrderStatusBadge, { status })
2880
3033
  ] }),
2881
- /* @__PURE__ */ jsxs30(View39, { className: "flex-row items-center justify-between", children: [
2882
- /* @__PURE__ */ jsxs30(View39, { className: "gap-0.5", children: [
2883
- /* @__PURE__ */ jsx71(Text24, { className: "text-xs text-muted-foreground", children: date }),
2884
- customerName && /* @__PURE__ */ jsx71(Text24, { className: "text-xs text-muted-foreground", children: customerName })
3034
+ /* @__PURE__ */ jsxs31(View41, { className: "flex-row items-center justify-between", children: [
3035
+ /* @__PURE__ */ jsxs31(View41, { className: "gap-0.5", children: [
3036
+ /* @__PURE__ */ jsx73(Text25, { className: "text-xs text-muted-foreground", children: date }),
3037
+ customerName && /* @__PURE__ */ jsx73(Text25, { className: "text-xs text-muted-foreground", children: customerName })
2885
3038
  ] }),
2886
- /* @__PURE__ */ jsx71(Text24, { className: "text-sm font-semibold text-foreground", children: total })
3039
+ /* @__PURE__ */ jsx73(Text25, { className: "text-sm font-semibold text-foreground", children: total })
2887
3040
  ] })
2888
3041
  ]
2889
3042
  }
@@ -2891,9 +3044,9 @@ function OrderCard({
2891
3044
  }
2892
3045
 
2893
3046
  // src/order/order-list.tsx
2894
- import { ScrollView as ScrollView8, View as View40 } from "react-native";
2895
- import { cn as cn69 } from "@tallyui/theme";
2896
- import { jsx as jsx72, jsxs as jsxs31 } from "react/jsx-runtime";
3047
+ import { ScrollView as ScrollView8, View as View42 } from "react-native";
3048
+ import { cn as cn71 } from "@tallyui/theme";
3049
+ import { jsx as jsx74, jsxs as jsxs32 } from "react/jsx-runtime";
2897
3050
  function OrderList({
2898
3051
  items,
2899
3052
  renderItem,
@@ -2903,16 +3056,16 @@ function OrderList({
2903
3056
  ...viewProps
2904
3057
  }) {
2905
3058
  const hasItems = items.length > 0;
2906
- return /* @__PURE__ */ jsxs31(View40, { className: cn69("flex-1", className), ...viewProps, children: [
2907
- headerSlot && /* @__PURE__ */ jsx72(View40, { className: "px-3 py-2", children: headerSlot }),
2908
- hasItems ? /* @__PURE__ */ jsx72(ScrollView8, { contentContainerClassName: "gap-2 p-3", children: items.map((item, index) => /* @__PURE__ */ jsx72(View40, { children: renderItem(item, index) }, item.id ?? index)) }) : emptyState ?? null
3059
+ return /* @__PURE__ */ jsxs32(View42, { className: cn71("flex-1", className), ...viewProps, children: [
3060
+ headerSlot && /* @__PURE__ */ jsx74(View42, { className: "px-3 py-2", children: headerSlot }),
3061
+ hasItems ? /* @__PURE__ */ jsx74(ScrollView8, { contentContainerClassName: "gap-2 p-3", children: items.map((item, index) => /* @__PURE__ */ jsx74(View42, { children: renderItem(item, index) }, item.id ?? index)) }) : emptyState ?? null
2909
3062
  ] });
2910
3063
  }
2911
3064
 
2912
3065
  // src/order/order-detail.tsx
2913
- import { ScrollView as ScrollView9, Text as Text25, View as View41 } from "react-native";
2914
- import { cn as cn70 } from "@tallyui/theme";
2915
- import { jsx as jsx73, jsxs as jsxs32 } from "react/jsx-runtime";
3066
+ import { ScrollView as ScrollView9, Text as Text26, View as View43 } from "react-native";
3067
+ import { cn as cn72 } from "@tallyui/theme";
3068
+ import { jsx as jsx75, jsxs as jsxs33 } from "react/jsx-runtime";
2916
3069
  function OrderDetail({
2917
3070
  orderNumber,
2918
3071
  status,
@@ -2926,47 +3079,47 @@ function OrderDetail({
2926
3079
  className,
2927
3080
  ...viewProps
2928
3081
  }) {
2929
- return /* @__PURE__ */ jsx73(ScrollView9, { className: cn70("flex-1", className), ...viewProps, children: /* @__PURE__ */ jsxs32(View41, { className: "gap-4 p-4", children: [
2930
- /* @__PURE__ */ jsxs32(View41, { className: "flex-row items-center justify-between", children: [
2931
- /* @__PURE__ */ jsx73(Text25, { className: "text-lg font-bold text-foreground", children: orderNumber }),
2932
- /* @__PURE__ */ jsx73(OrderStatusBadge, { status })
3082
+ return /* @__PURE__ */ jsx75(ScrollView9, { className: cn72("flex-1", className), ...viewProps, children: /* @__PURE__ */ jsxs33(View43, { className: "gap-4 p-4", children: [
3083
+ /* @__PURE__ */ jsxs33(View43, { className: "flex-row items-center justify-between", children: [
3084
+ /* @__PURE__ */ jsx75(Text26, { className: "text-lg font-bold text-foreground", children: orderNumber }),
3085
+ /* @__PURE__ */ jsx75(OrderStatusBadge, { status })
2933
3086
  ] }),
2934
- customerSlot && /* @__PURE__ */ jsx73(View41, { className: "border-b border-border pb-3", children: customerSlot }),
2935
- /* @__PURE__ */ jsxs32(View41, { className: "gap-1", children: [
2936
- /* @__PURE__ */ jsx73(Text25, { className: "text-xs font-semibold text-muted-foreground", children: "Items" }),
2937
- lineItems.map((item, i) => /* @__PURE__ */ jsxs32(View41, { className: "flex-row items-center justify-between py-1", children: [
2938
- /* @__PURE__ */ jsxs32(Text25, { className: "flex-1 text-sm text-foreground", children: [
3087
+ customerSlot && /* @__PURE__ */ jsx75(View43, { className: "border-b border-border pb-3", children: customerSlot }),
3088
+ /* @__PURE__ */ jsxs33(View43, { className: "gap-1", children: [
3089
+ /* @__PURE__ */ jsx75(Text26, { className: "text-xs font-semibold text-muted-foreground", children: "Items" }),
3090
+ lineItems.map((item, i) => /* @__PURE__ */ jsxs33(View43, { className: "flex-row items-center justify-between py-1", children: [
3091
+ /* @__PURE__ */ jsxs33(Text26, { className: "flex-1 text-sm text-foreground", children: [
2939
3092
  item.name,
2940
3093
  " x",
2941
3094
  item.quantity
2942
3095
  ] }),
2943
- /* @__PURE__ */ jsx73(Text25, { className: "text-sm text-foreground", children: item.total })
3096
+ /* @__PURE__ */ jsx75(Text26, { className: "text-sm text-foreground", children: item.total })
2944
3097
  ] }, i))
2945
3098
  ] }),
2946
- /* @__PURE__ */ jsxs32(View41, { className: "gap-1 border-t border-border pt-3", children: [
2947
- /* @__PURE__ */ jsxs32(View41, { className: "flex-row justify-between", children: [
2948
- /* @__PURE__ */ jsx73(Text25, { className: "text-sm text-muted-foreground", children: "Subtotal" }),
2949
- /* @__PURE__ */ jsx73(Text25, { className: "text-sm text-foreground", children: subtotal })
3099
+ /* @__PURE__ */ jsxs33(View43, { className: "gap-1 border-t border-border pt-3", children: [
3100
+ /* @__PURE__ */ jsxs33(View43, { className: "flex-row justify-between", children: [
3101
+ /* @__PURE__ */ jsx75(Text26, { className: "text-sm text-muted-foreground", children: "Subtotal" }),
3102
+ /* @__PURE__ */ jsx75(Text26, { className: "text-sm text-foreground", children: subtotal })
2950
3103
  ] }),
2951
- /* @__PURE__ */ jsxs32(View41, { className: "flex-row justify-between", children: [
2952
- /* @__PURE__ */ jsx73(Text25, { className: "text-sm text-muted-foreground", children: "Tax" }),
2953
- /* @__PURE__ */ jsx73(Text25, { className: "text-sm text-foreground", children: tax })
3104
+ /* @__PURE__ */ jsxs33(View43, { className: "flex-row justify-between", children: [
3105
+ /* @__PURE__ */ jsx75(Text26, { className: "text-sm text-muted-foreground", children: "Tax" }),
3106
+ /* @__PURE__ */ jsx75(Text26, { className: "text-sm text-foreground", children: tax })
2954
3107
  ] }),
2955
- /* @__PURE__ */ jsxs32(View41, { className: "flex-row justify-between pt-1", children: [
2956
- /* @__PURE__ */ jsx73(Text25, { className: "text-sm font-bold text-foreground", children: "Total" }),
2957
- /* @__PURE__ */ jsx73(Text25, { className: "text-sm font-bold text-foreground", children: total })
3108
+ /* @__PURE__ */ jsxs33(View43, { className: "flex-row justify-between pt-1", children: [
3109
+ /* @__PURE__ */ jsx75(Text26, { className: "text-sm font-bold text-foreground", children: "Total" }),
3110
+ /* @__PURE__ */ jsx75(Text26, { className: "text-sm font-bold text-foreground", children: total })
2958
3111
  ] })
2959
3112
  ] }),
2960
- paymentSlot && /* @__PURE__ */ jsx73(View41, { className: "border-t border-border pt-3", children: paymentSlot }),
2961
- footerSlot && /* @__PURE__ */ jsx73(View41, { className: "border-t border-border pt-3", children: footerSlot })
3113
+ paymentSlot && /* @__PURE__ */ jsx75(View43, { className: "border-t border-border pt-3", children: paymentSlot }),
3114
+ footerSlot && /* @__PURE__ */ jsx75(View43, { className: "border-t border-border pt-3", children: footerSlot })
2962
3115
  ] }) });
2963
3116
  }
2964
3117
 
2965
3118
  // src/register/cash-count-input.tsx
2966
- import { useState as useState9 } from "react";
2967
- import { Text as Text26, View as View42 } from "react-native";
2968
- import { cn as cn71 } from "@tallyui/theme";
2969
- import { jsx as jsx74, jsxs as jsxs33 } from "react/jsx-runtime";
3119
+ import { useState as useState10 } from "react";
3120
+ import { Text as Text27, View as View44 } from "react-native";
3121
+ import { cn as cn73 } from "@tallyui/theme";
3122
+ import { jsx as jsx76, jsxs as jsxs34 } from "react/jsx-runtime";
2970
3123
  var DEFAULT_DENOMINATIONS = [
2971
3124
  { label: "$100", value: 100 },
2972
3125
  { label: "$50", value: 50 },
@@ -2988,7 +3141,7 @@ function CashCountInput({
2988
3141
  className,
2989
3142
  ...viewProps
2990
3143
  }) {
2991
- const [internalCounts, setInternalCounts] = useState9(defaultCounts ?? {});
3144
+ const [internalCounts, setInternalCounts] = useState10(defaultCounts ?? {});
2992
3145
  const counts = controlledCounts ?? internalCounts;
2993
3146
  const total = denominations2.reduce(
2994
3147
  (sum, d) => sum + d.value * (counts[d.value] ?? 0),
@@ -3004,10 +3157,10 @@ function CashCountInput({
3004
3157
  );
3005
3158
  onChangeTotal?.(newTotal);
3006
3159
  };
3007
- return /* @__PURE__ */ jsxs33(View42, { className: cn71("gap-2", className), ...viewProps, children: [
3008
- denominations2.map((d) => /* @__PURE__ */ jsxs33(View42, { className: "flex-row items-center justify-between px-3 py-1", children: [
3009
- /* @__PURE__ */ jsx74(Text26, { className: "w-16 text-sm font-medium text-foreground", children: d.label }),
3010
- /* @__PURE__ */ jsx74(
3160
+ return /* @__PURE__ */ jsxs34(View44, { className: cn73("gap-2", className), ...viewProps, children: [
3161
+ denominations2.map((d) => /* @__PURE__ */ jsxs34(View44, { className: "flex-row items-center justify-between px-3 py-1", children: [
3162
+ /* @__PURE__ */ jsx76(Text27, { className: "w-16 text-sm font-medium text-foreground", children: d.label }),
3163
+ /* @__PURE__ */ jsx76(
3011
3164
  QuantityStepper,
3012
3165
  {
3013
3166
  quantity: counts[d.value] ?? 0,
@@ -3015,9 +3168,9 @@ function CashCountInput({
3015
3168
  onChangeQuantity: (qty) => handleCountChange(d.value, qty)
3016
3169
  }
3017
3170
  ),
3018
- /* @__PURE__ */ jsx74(Text26, { className: "w-20 text-right text-sm text-muted-foreground", children: (d.value * (counts[d.value] ?? 0)).toFixed(2) })
3171
+ /* @__PURE__ */ jsx76(Text27, { className: "w-20 text-right text-sm text-muted-foreground", children: (d.value * (counts[d.value] ?? 0)).toFixed(2) })
3019
3172
  ] }, d.value)),
3020
- /* @__PURE__ */ jsx74(View42, { className: "border-t border-border px-3 pt-2", children: /* @__PURE__ */ jsxs33(Text26, { className: "text-right text-base font-bold text-foreground", children: [
3173
+ /* @__PURE__ */ jsx76(View44, { className: "border-t border-border px-3 pt-2", children: /* @__PURE__ */ jsxs34(Text27, { className: "text-right text-base font-bold text-foreground", children: [
3021
3174
  "Total: ",
3022
3175
  total.toFixed(2)
3023
3176
  ] }) })
@@ -3025,9 +3178,9 @@ function CashCountInput({
3025
3178
  }
3026
3179
 
3027
3180
  // src/register/register-summary.tsx
3028
- import { Text as Text27, View as View43 } from "react-native";
3029
- import { cn as cn72 } from "@tallyui/theme";
3030
- import { jsx as jsx75, jsxs as jsxs34 } from "react/jsx-runtime";
3181
+ import { Text as Text28, View as View45 } from "react-native";
3182
+ import { cn as cn74 } from "@tallyui/theme";
3183
+ import { jsx as jsx77, jsxs as jsxs35 } from "react/jsx-runtime";
3031
3184
  function RegisterSummary({
3032
3185
  expectedCash,
3033
3186
  actualCash,
@@ -3038,37 +3191,37 @@ function RegisterSummary({
3038
3191
  ...viewProps
3039
3192
  }) {
3040
3193
  const discrepancy = actualCash - expectedCash;
3041
- return /* @__PURE__ */ jsxs34(View43, { className: cn72("gap-4 rounded-lg border border-border bg-card p-4", className), ...viewProps, children: [
3194
+ return /* @__PURE__ */ jsxs35(View45, { className: cn74("gap-4 rounded-lg border border-border bg-card p-4", className), ...viewProps, children: [
3042
3195
  headerSlot,
3043
- /* @__PURE__ */ jsxs34(View43, { className: "gap-2", children: [
3044
- /* @__PURE__ */ jsx75(Text27, { className: "text-xs font-semibold text-muted-foreground", children: "Cash Drawer" }),
3045
- /* @__PURE__ */ jsxs34(View43, { className: "flex-row justify-between", children: [
3046
- /* @__PURE__ */ jsx75(Text27, { className: "text-sm text-foreground", children: "Expected" }),
3047
- /* @__PURE__ */ jsx75(Text27, { className: "text-sm text-foreground", children: expectedCash.toFixed(2) })
3196
+ /* @__PURE__ */ jsxs35(View45, { className: "gap-2", children: [
3197
+ /* @__PURE__ */ jsx77(Text28, { className: "text-xs font-semibold text-muted-foreground", children: "Cash Drawer" }),
3198
+ /* @__PURE__ */ jsxs35(View45, { className: "flex-row justify-between", children: [
3199
+ /* @__PURE__ */ jsx77(Text28, { className: "text-sm text-foreground", children: "Expected" }),
3200
+ /* @__PURE__ */ jsx77(Text28, { className: "text-sm text-foreground", children: expectedCash.toFixed(2) })
3048
3201
  ] }),
3049
- /* @__PURE__ */ jsxs34(View43, { className: "flex-row justify-between", children: [
3050
- /* @__PURE__ */ jsx75(Text27, { className: "text-sm text-foreground", children: "Actual" }),
3051
- /* @__PURE__ */ jsx75(Text27, { className: "text-sm text-foreground", children: actualCash.toFixed(2) })
3202
+ /* @__PURE__ */ jsxs35(View45, { className: "flex-row justify-between", children: [
3203
+ /* @__PURE__ */ jsx77(Text28, { className: "text-sm text-foreground", children: "Actual" }),
3204
+ /* @__PURE__ */ jsx77(Text28, { className: "text-sm text-foreground", children: actualCash.toFixed(2) })
3052
3205
  ] }),
3053
- /* @__PURE__ */ jsxs34(View43, { className: "flex-row justify-between border-t border-border pt-1", children: [
3054
- /* @__PURE__ */ jsx75(Text27, { className: "text-sm font-semibold text-foreground", children: "Discrepancy" }),
3055
- /* @__PURE__ */ jsxs34(Text27, { className: cn72("text-sm font-semibold", discrepancy === 0 ? "text-success" : "text-destructive"), children: [
3206
+ /* @__PURE__ */ jsxs35(View45, { className: "flex-row justify-between border-t border-border pt-1", children: [
3207
+ /* @__PURE__ */ jsx77(Text28, { className: "text-sm font-semibold text-foreground", children: "Discrepancy" }),
3208
+ /* @__PURE__ */ jsxs35(Text28, { className: cn74("text-sm font-semibold", discrepancy === 0 ? "text-success" : "text-destructive"), children: [
3056
3209
  discrepancy >= 0 ? "" : "-",
3057
3210
  Math.abs(discrepancy).toFixed(2)
3058
3211
  ] })
3059
3212
  ] })
3060
3213
  ] }),
3061
- transactions.length > 0 && /* @__PURE__ */ jsxs34(View43, { className: "gap-2", children: [
3062
- /* @__PURE__ */ jsx75(Text27, { className: "text-xs font-semibold text-muted-foreground", children: "Transactions" }),
3063
- transactions.map((t) => /* @__PURE__ */ jsxs34(View43, { className: "flex-row items-center justify-between", children: [
3064
- /* @__PURE__ */ jsxs34(View43, { className: "gap-0.5", children: [
3065
- /* @__PURE__ */ jsx75(Text27, { className: "text-sm text-foreground", children: t.method }),
3066
- /* @__PURE__ */ jsxs34(Text27, { className: "text-xs text-muted-foreground", children: [
3214
+ transactions.length > 0 && /* @__PURE__ */ jsxs35(View45, { className: "gap-2", children: [
3215
+ /* @__PURE__ */ jsx77(Text28, { className: "text-xs font-semibold text-muted-foreground", children: "Transactions" }),
3216
+ transactions.map((t) => /* @__PURE__ */ jsxs35(View45, { className: "flex-row items-center justify-between", children: [
3217
+ /* @__PURE__ */ jsxs35(View45, { className: "gap-0.5", children: [
3218
+ /* @__PURE__ */ jsx77(Text28, { className: "text-sm text-foreground", children: t.method }),
3219
+ /* @__PURE__ */ jsxs35(Text28, { className: "text-xs text-muted-foreground", children: [
3067
3220
  t.count,
3068
3221
  " transactions"
3069
3222
  ] })
3070
3223
  ] }),
3071
- /* @__PURE__ */ jsx75(Text27, { className: "text-sm font-semibold text-foreground", children: t.total.toFixed(2) })
3224
+ /* @__PURE__ */ jsx77(Text28, { className: "text-sm font-semibold text-foreground", children: t.total.toFixed(2) })
3072
3225
  ] }, t.method))
3073
3226
  ] }),
3074
3227
  footerSlot
@@ -3076,9 +3229,9 @@ function RegisterSummary({
3076
3229
  }
3077
3230
 
3078
3231
  // src/register/register-open-close.tsx
3079
- import { Pressable as Pressable20, Text as Text28, View as View44 } from "react-native";
3080
- import { cn as cn73 } from "@tallyui/theme";
3081
- import { jsx as jsx76, jsxs as jsxs35 } from "react/jsx-runtime";
3232
+ import { Pressable as Pressable22, Text as Text29, View as View46 } from "react-native";
3233
+ import { cn as cn75 } from "@tallyui/theme";
3234
+ import { jsx as jsx78, jsxs as jsxs36 } from "react/jsx-runtime";
3082
3235
  function RegisterOpenClose({
3083
3236
  isOpen,
3084
3237
  onOpen,
@@ -3089,20 +3242,20 @@ function RegisterOpenClose({
3089
3242
  className,
3090
3243
  ...viewProps
3091
3244
  }) {
3092
- return /* @__PURE__ */ jsxs35(View44, { className: cn73("gap-4 p-4", className), ...viewProps, children: [
3093
- /* @__PURE__ */ jsx76(Text28, { className: "text-lg font-bold text-foreground", children: isOpen ? "Close Register" : "Open Register" }),
3094
- isOpen && expectedBalance != null && /* @__PURE__ */ jsxs35(View44, { className: "flex-row justify-between rounded-lg bg-muted px-3 py-2", children: [
3095
- /* @__PURE__ */ jsx76(Text28, { className: "text-sm text-muted-foreground", children: "Expected Balance" }),
3096
- /* @__PURE__ */ jsx76(Text28, { className: "text-sm font-semibold text-foreground", children: expectedBalance.toFixed(2) })
3245
+ return /* @__PURE__ */ jsxs36(View46, { className: cn75("gap-4 p-4", className), ...viewProps, children: [
3246
+ /* @__PURE__ */ jsx78(Text29, { className: "text-lg font-bold text-foreground", children: isOpen ? "Close Register" : "Open Register" }),
3247
+ isOpen && expectedBalance != null && /* @__PURE__ */ jsxs36(View46, { className: "flex-row justify-between rounded-lg bg-muted px-3 py-2", children: [
3248
+ /* @__PURE__ */ jsx78(Text29, { className: "text-sm text-muted-foreground", children: "Expected Balance" }),
3249
+ /* @__PURE__ */ jsx78(Text29, { className: "text-sm font-semibold text-foreground", children: expectedBalance.toFixed(2) })
3097
3250
  ] }),
3098
- cashCountSlot && /* @__PURE__ */ jsx76(View44, { children: cashCountSlot }),
3099
- notesSlot && /* @__PURE__ */ jsx76(View44, { children: notesSlot }),
3100
- /* @__PURE__ */ jsx76(
3101
- Pressable20,
3251
+ cashCountSlot && /* @__PURE__ */ jsx78(View46, { children: cashCountSlot }),
3252
+ notesSlot && /* @__PURE__ */ jsx78(View46, { children: notesSlot }),
3253
+ /* @__PURE__ */ jsx78(
3254
+ Pressable22,
3102
3255
  {
3103
3256
  onPress: isOpen ? onClose : onOpen,
3104
3257
  className: "items-center rounded-lg bg-primary px-4 py-3",
3105
- children: /* @__PURE__ */ jsx76(Text28, { className: "text-sm font-semibold text-primary-foreground", children: isOpen ? "Close Register" : "Open Register" })
3258
+ children: /* @__PURE__ */ jsx78(Text29, { className: "text-sm font-semibold text-primary-foreground", children: isOpen ? "Close Register" : "Open Register" })
3106
3259
  }
3107
3260
  )
3108
3261
  ] });
@@ -3110,46 +3263,46 @@ function RegisterOpenClose({
3110
3263
 
3111
3264
  // src/register/register-picker.tsx
3112
3265
  import { ScrollView as ScrollView10 } from "react-native";
3113
- import { jsx as jsx77, jsxs as jsxs36 } from "react/jsx-runtime";
3266
+ import { jsx as jsx79, jsxs as jsxs37 } from "react/jsx-runtime";
3114
3267
  function RegisterPicker({ registers, onPick, className }) {
3115
- return /* @__PURE__ */ jsxs36(Card, { testID: "register-picker", className, children: [
3116
- /* @__PURE__ */ jsx77(CardHeader, { children: /* @__PURE__ */ jsx77(CardTitle, { children: "Choose a register" }) }),
3117
- /* @__PURE__ */ jsx77(CardContent, { children: /* @__PURE__ */ jsxs36(ScrollView10, { children: [
3118
- registers.map((register) => /* @__PURE__ */ jsx77(
3268
+ return /* @__PURE__ */ jsxs37(Card, { testID: "register-picker", className, children: [
3269
+ /* @__PURE__ */ jsx79(CardHeader, { children: /* @__PURE__ */ jsx79(CardTitle, { children: "Choose a register" }) }),
3270
+ /* @__PURE__ */ jsx79(CardContent, { children: /* @__PURE__ */ jsxs37(ScrollView10, { children: [
3271
+ registers.map((register) => /* @__PURE__ */ jsx79(
3119
3272
  Button,
3120
3273
  {
3121
3274
  testID: `register-picker-row-${register.id}`,
3122
3275
  variant: "ghost",
3123
3276
  className: "h-auto min-h-11 items-start justify-start py-2",
3124
3277
  onPress: () => onPick(register.id),
3125
- children: /* @__PURE__ */ jsxs36(VStack, { space: "none", children: [
3126
- /* @__PURE__ */ jsx77(Text, { numberOfLines: 1, children: register.name }),
3127
- /* @__PURE__ */ jsx77(Text, { testID: `register-picker-row-${register.id}-status`, className: "text-muted-foreground text-sm", children: "Not opened" })
3278
+ children: /* @__PURE__ */ jsxs37(VStack, { space: "none", children: [
3279
+ /* @__PURE__ */ jsx79(Text, { numberOfLines: 1, children: register.name }),
3280
+ /* @__PURE__ */ jsx79(Text, { testID: `register-picker-row-${register.id}-status`, className: "text-muted-foreground text-sm", children: "Not opened" })
3128
3281
  ] })
3129
3282
  },
3130
3283
  register.id
3131
3284
  )),
3132
- registers.length === 0 && /* @__PURE__ */ jsx77(Text, { testID: "register-picker-empty", className: "text-muted-foreground p-4", children: "No registers are set up for this store yet." })
3285
+ registers.length === 0 && /* @__PURE__ */ jsx79(Text, { testID: "register-picker-empty", className: "text-muted-foreground p-4", children: "No registers are set up for this store yet." })
3133
3286
  ] }) })
3134
3287
  ] });
3135
3288
  }
3136
3289
 
3137
3290
  // src/register/open-register-card.tsx
3138
- import { useState as useState10 } from "react";
3139
- import { View as View45 } from "react-native";
3291
+ import { useState as useState11 } from "react";
3292
+ import { View as View47 } from "react-native";
3140
3293
  import { parseMinor, validAmount } from "@tallyui/pos";
3141
3294
  import { currencySymbol, formatMoney as formatMoney6, minorUnitDigits as minorUnitDigits3 } from "@tallyui/core";
3142
- import { cn as cn74 } from "@tallyui/theme";
3143
- import { jsx as jsx78, jsxs as jsxs37 } from "react/jsx-runtime";
3295
+ import { cn as cn76 } from "@tallyui/theme";
3296
+ import { jsx as jsx80, jsxs as jsxs38 } from "react/jsx-runtime";
3144
3297
  var AMOUNT_LABEL_ID = "open-register-amount-label";
3145
3298
  function OpenRegisterCard({ register, currency, configuredFloatMinor, className }) {
3146
3299
  const digits = minorUnitDigits3(currency);
3147
3300
  const lastCountedMinor = register.lastClosure?.counted?.cash ?? null;
3148
3301
  const expectedFloatMinor = configuredFloatMinor ?? lastCountedMinor ?? null;
3149
- const [enteredAmount, setEnteredAmount] = useState10(null);
3302
+ const [enteredAmount, setEnteredAmount] = useState11(null);
3150
3303
  const amount = enteredAmount ?? (expectedFloatMinor != null ? decimal(expectedFloatMinor, digits) : "");
3151
- const [busy, setBusy] = useState10(false);
3152
- const [error, setError] = useState10("");
3304
+ const [busy, setBusy] = useState11(false);
3305
+ const [error, setError] = useState11("");
3153
3306
  const valid = validAmount(amount, digits);
3154
3307
  const countedMinor = valid ? parseMinor(amount, digits) : NaN;
3155
3308
  const open = async () => {
@@ -3165,10 +3318,10 @@ function OpenRegisterCard({ register, currency, configuredFloatMinor, className
3165
3318
  }
3166
3319
  };
3167
3320
  const amountLabel = `Cash in the drawer to start (${currencySymbol(currency)})`;
3168
- return /* @__PURE__ */ jsxs37(View45, { testID: "open-register-card", className: cn74("bg-card gap-3 rounded-md p-4", className), children: [
3169
- /* @__PURE__ */ jsx78(Text, { className: "text-lg font-semibold", children: "Open register" }),
3170
- /* @__PURE__ */ jsx78(Label, { testID: "open-register-amount-label", nativeID: AMOUNT_LABEL_ID, children: amountLabel }),
3171
- /* @__PURE__ */ jsx78(Input, { children: /* @__PURE__ */ jsx78(
3321
+ return /* @__PURE__ */ jsxs38(View47, { testID: "open-register-card", className: cn76("bg-card gap-3 rounded-md p-4", className), children: [
3322
+ /* @__PURE__ */ jsx80(Text, { className: "text-lg font-semibold", children: "Open register" }),
3323
+ /* @__PURE__ */ jsx80(Label, { testID: "open-register-amount-label", nativeID: AMOUNT_LABEL_ID, children: amountLabel }),
3324
+ /* @__PURE__ */ jsx80(Input, { children: /* @__PURE__ */ jsx80(
3172
3325
  Input.Field,
3173
3326
  {
3174
3327
  testID: "open-register-amount",
@@ -3179,40 +3332,40 @@ function OpenRegisterCard({ register, currency, configuredFloatMinor, className
3179
3332
  accessibilityLabelledBy: AMOUNT_LABEL_ID
3180
3333
  }
3181
3334
  ) }),
3182
- configuredFloatMinor != null && /* @__PURE__ */ jsx78(
3335
+ configuredFloatMinor != null && /* @__PURE__ */ jsx80(
3183
3336
  Button,
3184
3337
  {
3185
3338
  testID: "open-register-chip-configured",
3186
3339
  variant: "outline",
3187
3340
  className: "min-h-11",
3188
3341
  onPress: () => setEnteredAmount(decimal(configuredFloatMinor, digits)),
3189
- children: /* @__PURE__ */ jsxs37(Text, { children: [
3342
+ children: /* @__PURE__ */ jsxs38(Text, { children: [
3190
3343
  "Use the configured float (",
3191
3344
  formatMoney6({ amount: configuredFloatMinor, currency }),
3192
3345
  ")"
3193
3346
  ] })
3194
3347
  }
3195
3348
  ),
3196
- lastCountedMinor != null && /* @__PURE__ */ jsx78(
3349
+ lastCountedMinor != null && /* @__PURE__ */ jsx80(
3197
3350
  Button,
3198
3351
  {
3199
3352
  testID: "open-register-chip-last",
3200
3353
  variant: "outline",
3201
3354
  className: "min-h-11",
3202
3355
  onPress: () => setEnteredAmount(decimal(lastCountedMinor, digits)),
3203
- children: /* @__PURE__ */ jsxs37(Text, { children: [
3356
+ children: /* @__PURE__ */ jsxs38(Text, { children: [
3204
3357
  "Use the last counted cash (",
3205
3358
  formatMoney6({ amount: lastCountedMinor, currency }),
3206
3359
  ")"
3207
3360
  ] })
3208
3361
  }
3209
3362
  ),
3210
- expectedFloatMinor !== null && valid && countedMinor !== expectedFloatMinor && /* @__PURE__ */ jsxs37(Text, { testID: "opening-variance", children: [
3363
+ expectedFloatMinor !== null && valid && countedMinor !== expectedFloatMinor && /* @__PURE__ */ jsxs38(Text, { testID: "opening-variance", children: [
3211
3364
  formatMoney6({ amount: countedMinor - expectedFloatMinor, currency }),
3212
3365
  " vs the expected float"
3213
3366
  ] }),
3214
- !!error && /* @__PURE__ */ jsx78(Text, { className: "text-destructive", children: error }),
3215
- /* @__PURE__ */ jsx78(Button, { testID: "open-register-button", className: "min-h-14", disabled: busy || !valid, onPress: open, children: /* @__PURE__ */ jsx78(Text, { children: busy ? "Opening\u2026" : "Open register" }) })
3367
+ !!error && /* @__PURE__ */ jsx80(Text, { className: "text-destructive", children: error }),
3368
+ /* @__PURE__ */ jsx80(Button, { testID: "open-register-button", className: "min-h-14", disabled: busy || !valid, onPress: open, children: /* @__PURE__ */ jsx80(Text, { children: busy ? "Opening\u2026" : "Open register" }) })
3216
3369
  ] });
3217
3370
  }
3218
3371
  function decimal(minor, digits) {
@@ -3221,8 +3374,8 @@ function decimal(minor, digits) {
3221
3374
  }
3222
3375
 
3223
3376
  // src/register/register-bar.tsx
3224
- import { Pressable as Pressable21, View as View46 } from "react-native";
3225
- import { cn as cn75 } from "@tallyui/theme";
3377
+ import { Pressable as Pressable23, View as View48 } from "react-native";
3378
+ import { cn as cn77 } from "@tallyui/theme";
3226
3379
 
3227
3380
  // src/register/register-bar.helpers.ts
3228
3381
  function describeRegisterBarPill({
@@ -3245,7 +3398,7 @@ function describeRegisterBarPill({
3245
3398
  }
3246
3399
 
3247
3400
  // src/register/register-bar.tsx
3248
- import { jsx as jsx79, jsxs as jsxs38 } from "react/jsx-runtime";
3401
+ import { jsx as jsx81, jsxs as jsxs39 } from "react/jsx-runtime";
3249
3402
  function RegisterBar({
3250
3403
  register,
3251
3404
  registerId,
@@ -3266,10 +3419,10 @@ function RegisterBar({
3266
3419
  sessionsOn: enabled,
3267
3420
  closing
3268
3421
  });
3269
- return /* @__PURE__ */ jsxs38(HStack, { testID: "register-bar", className: cn75("bg-card border-border h-12 border-b px-3", className), children: [
3270
- /* @__PURE__ */ jsx79(View46, { className: "min-w-0 flex-1 shrink", children: multiRegister && registerId !== null && /* @__PURE__ */ jsx79(Text, { testID: "register-bar-name", numberOfLines: 1, children: registerName }) }),
3271
- pill && (onPressPill ? /* @__PURE__ */ jsx79(Pressable21, { testID: "register-bar-pill", accessibilityRole: "button", accessibilityLabel: pill, onPress: onPressPill, children: /* @__PURE__ */ jsx79(Badge, { label: pill, variant: "warning" }) }) : /* @__PURE__ */ jsx79(Badge, { testID: "register-bar-pill", label: pill, variant: "warning" })),
3272
- (session || lastClosure) && /* @__PURE__ */ jsx79(
3422
+ return /* @__PURE__ */ jsxs39(HStack, { testID: "register-bar", className: cn77("bg-card border-border h-12 border-b px-3", className), children: [
3423
+ /* @__PURE__ */ jsx81(View48, { className: "min-w-0 flex-1 shrink", children: multiRegister && registerId !== null && /* @__PURE__ */ jsx81(Text, { testID: "register-bar-name", numberOfLines: 1, children: registerName }) }),
3424
+ pill && (onPressPill ? /* @__PURE__ */ jsx81(Pressable23, { testID: "register-bar-pill", accessibilityRole: "button", accessibilityLabel: pill, onPress: onPressPill, children: /* @__PURE__ */ jsx81(Badge, { label: pill, variant: "warning" }) }) : /* @__PURE__ */ jsx81(Badge, { testID: "register-bar-pill", label: pill, variant: "warning" })),
3425
+ (session || lastClosure) && /* @__PURE__ */ jsx81(
3273
3426
  Button,
3274
3427
  {
3275
3428
  variant: "ghost",
@@ -3277,17 +3430,17 @@ function RegisterBar({
3277
3430
  testID: "register-bar-open-panel",
3278
3431
  accessibilityLabel: "Open register panel",
3279
3432
  onPress: onOpenPanel,
3280
- children: /* @__PURE__ */ jsx79(Text, { className: overdue ? "text-warning" : void 0, children: "Register \u203A" })
3433
+ children: /* @__PURE__ */ jsx81(Text, { className: overdue ? "text-warning" : void 0, children: "Register \u203A" })
3281
3434
  }
3282
3435
  )
3283
3436
  ] });
3284
3437
  }
3285
3438
 
3286
3439
  // src/register/movement-sheet.tsx
3287
- import { useRef as useRef3, useState as useState11 } from "react";
3440
+ import { useRef as useRef3, useState as useState12 } from "react";
3288
3441
  import { movementFieldError, normalizeAmount, parseMinor as parseMinor2 } from "@tallyui/pos";
3289
3442
  import { currencySymbol as currencySymbol2, minorUnitDigits as minorUnitDigits4 } from "@tallyui/core";
3290
- import { Fragment as Fragment3, jsx as jsx80, jsxs as jsxs39 } from "react/jsx-runtime";
3443
+ import { Fragment as Fragment3, jsx as jsx82, jsxs as jsxs40 } from "react/jsx-runtime";
3291
3444
  var LABELS = {
3292
3445
  paid_in: "Paid in",
3293
3446
  paid_out: "Paid out",
@@ -3297,11 +3450,11 @@ var AMOUNT_LABEL_ID2 = "movement-amount-label";
3297
3450
  var REASON_LABEL_ID = "movement-reason-label";
3298
3451
  function MovementSheet({ register, type, currency, onDone, onOpenChange, onOpenDrawer }) {
3299
3452
  const digits = minorUnitDigits4(currency);
3300
- const [amount, setAmount] = useState11("");
3301
- const [reason, setReason] = useState11("");
3302
- const [busy, setBusy] = useState11(false);
3453
+ const [amount, setAmount] = useState12("");
3454
+ const [reason, setReason] = useState12("");
3455
+ const [busy, setBusy] = useState12(false);
3303
3456
  const busyRef = useRef3(false);
3304
- const [error, setError] = useState11("");
3457
+ const [error, setError] = useState12("");
3305
3458
  const invalid = movementFieldError({ type, amount, reason });
3306
3459
  const confirm = async () => {
3307
3460
  if (invalid || busyRef.current) return;
@@ -3323,11 +3476,11 @@ function MovementSheet({ register, type, currency, onDone, onOpenChange, onOpenD
3323
3476
  setBusy(false);
3324
3477
  }
3325
3478
  };
3326
- return /* @__PURE__ */ jsx80(Dialog, { open: true, onOpenChange, children: /* @__PURE__ */ jsxs39(DialogContent, { testID: "movement-sheet", children: [
3327
- /* @__PURE__ */ jsx80(DialogTitle, { children: LABELS[type] }),
3328
- type !== "no_sale" && /* @__PURE__ */ jsxs39(Fragment3, { children: [
3329
- /* @__PURE__ */ jsx80(Label, { testID: "movement-amount-label", nativeID: AMOUNT_LABEL_ID2, children: `Amount (${currencySymbol2(currency)})` }),
3330
- /* @__PURE__ */ jsx80(Input, { children: /* @__PURE__ */ jsx80(
3479
+ return /* @__PURE__ */ jsx82(Dialog, { open: true, onOpenChange, children: /* @__PURE__ */ jsxs40(DialogContent, { testID: "movement-sheet", children: [
3480
+ /* @__PURE__ */ jsx82(DialogTitle, { children: LABELS[type] }),
3481
+ type !== "no_sale" && /* @__PURE__ */ jsxs40(Fragment3, { children: [
3482
+ /* @__PURE__ */ jsx82(Label, { testID: "movement-amount-label", nativeID: AMOUNT_LABEL_ID2, children: `Amount (${currencySymbol2(currency)})` }),
3483
+ /* @__PURE__ */ jsx82(Input, { children: /* @__PURE__ */ jsx82(
3331
3484
  Input.Field,
3332
3485
  {
3333
3486
  testID: "movement-amount",
@@ -3339,8 +3492,8 @@ function MovementSheet({ register, type, currency, onDone, onOpenChange, onOpenD
3339
3492
  }
3340
3493
  ) })
3341
3494
  ] }),
3342
- /* @__PURE__ */ jsx80(Label, { testID: "movement-reason-label", nativeID: REASON_LABEL_ID, children: "Reason" }),
3343
- /* @__PURE__ */ jsx80(Input, { children: /* @__PURE__ */ jsx80(
3495
+ /* @__PURE__ */ jsx82(Label, { testID: "movement-reason-label", nativeID: REASON_LABEL_ID, children: "Reason" }),
3496
+ /* @__PURE__ */ jsx82(Input, { children: /* @__PURE__ */ jsx82(
3344
3497
  Input.Field,
3345
3498
  {
3346
3499
  testID: "movement-reason",
@@ -3351,20 +3504,20 @@ function MovementSheet({ register, type, currency, onDone, onOpenChange, onOpenD
3351
3504
  accessibilityLabelledBy: REASON_LABEL_ID
3352
3505
  }
3353
3506
  ) }),
3354
- !!error && /* @__PURE__ */ jsx80(Text, { className: "text-destructive", children: error }),
3355
- !!invalid && /* @__PURE__ */ jsx80(Text, { testID: "movement-invalid", className: "text-muted-foreground", children: invalid === "amount" ? "Enter a valid amount." : "Enter a reason." }),
3356
- /* @__PURE__ */ jsx80(Button, { testID: "movement-confirm", disabled: !!invalid || busy, onPress: confirm, children: /* @__PURE__ */ jsx80(Text, { children: busy ? "Recording\u2026" : "Record" }) })
3507
+ !!error && /* @__PURE__ */ jsx82(Text, { className: "text-destructive", children: error }),
3508
+ !!invalid && /* @__PURE__ */ jsx82(Text, { testID: "movement-invalid", className: "text-muted-foreground", children: invalid === "amount" ? "Enter a valid amount." : "Enter a reason." }),
3509
+ /* @__PURE__ */ jsx82(Button, { testID: "movement-confirm", disabled: !!invalid || busy, onPress: confirm, children: /* @__PURE__ */ jsx82(Text, { children: busy ? "Recording\u2026" : "Record" }) })
3357
3510
  ] }) });
3358
3511
  }
3359
3512
 
3360
3513
  // src/register/register-panel.tsx
3361
- import { useState as useState13 } from "react";
3362
- import { ScrollView as ScrollView12, useWindowDimensions as useWindowDimensions2, View as View48 } from "react-native";
3514
+ import { useState as useState14 } from "react";
3515
+ import { ScrollView as ScrollView12, useWindowDimensions as useWindowDimensions2, View as View50 } from "react-native";
3363
3516
  import { formatMoney as formatMoney8 } from "@tallyui/core";
3364
3517
 
3365
3518
  // src/register/register-count.tsx
3366
- import { useEffect as useEffect3, useRef as useRef4, useState as useState12 } from "react";
3367
- import { Platform, Pressable as Pressable22, ScrollView as ScrollView11, useWindowDimensions, View as View47 } from "react-native";
3519
+ import { useEffect as useEffect3, useRef as useRef4, useState as useState13 } from "react";
3520
+ import { Platform, Pressable as Pressable24, ScrollView as ScrollView11, useWindowDimensions, View as View49 } from "react-native";
3368
3521
  import {
3369
3522
  closeNeedsApproval,
3370
3523
  countVariance,
@@ -3376,8 +3529,8 @@ import {
3376
3529
  varianceText
3377
3530
  } from "@tallyui/pos";
3378
3531
  import { currencySymbol as currencySymbol3, formatMoney as formatMoney7, minorUnitDigits as minorUnitDigits5 } from "@tallyui/core";
3379
- import { cn as cn76 } from "@tallyui/theme";
3380
- import { jsx as jsx81, jsxs as jsxs40 } from "react/jsx-runtime";
3532
+ import { cn as cn78 } from "@tallyui/theme";
3533
+ import { jsx as jsx83, jsxs as jsxs41 } from "react/jsx-runtime";
3381
3534
  var AMOUNT_LABEL_ID3 = "count-amount-label";
3382
3535
  var APPROVAL_REQUIRED_TEXT = "Manager approval needed. Ask a manager to approve, or count again.";
3383
3536
  function varianceWord(key) {
@@ -3408,8 +3561,8 @@ function DenominationTile({ value, count: count2, currency, onAdd }) {
3408
3561
  timer.current = void 0;
3409
3562
  };
3410
3563
  useEffect3(() => stop, []);
3411
- return /* @__PURE__ */ jsxs40(
3412
- Pressable22,
3564
+ return /* @__PURE__ */ jsxs41(
3565
+ Pressable24,
3413
3566
  {
3414
3567
  testID: `den-tile-${value}`,
3415
3568
  accessibilityRole: "button",
@@ -3430,8 +3583,8 @@ function DenominationTile({ value, count: count2, currency, onAdd }) {
3430
3583
  if (!held.current) onAdd(1);
3431
3584
  },
3432
3585
  children: [
3433
- /* @__PURE__ */ jsx81(Text, { className: "text-sm tabular-nums", numberOfLines: 1, children: label }),
3434
- /* @__PURE__ */ jsx81(Text, { testID: `den-count-${value}`, className: "bg-background min-w-6 rounded-full px-1.5 text-center text-xs tabular-nums", children: count2 })
3586
+ /* @__PURE__ */ jsx83(Text, { className: "text-sm tabular-nums", numberOfLines: 1, children: label }),
3587
+ /* @__PURE__ */ jsx83(Text, { testID: `den-count-${value}`, className: "bg-background min-w-6 rounded-full px-1.5 text-center text-xs tabular-nums", children: count2 })
3435
3588
  ]
3436
3589
  }
3437
3590
  );
@@ -3442,18 +3595,18 @@ function RegisterCount({ register, currency, approve, className }) {
3442
3595
  const faces = denominations[currency] ?? denominations.default;
3443
3596
  const { width } = useWindowDimensions();
3444
3597
  const columns = width < 480 ? 3 : 4;
3445
- const [pieces, setPieces] = useState12({});
3446
- const [cashText, setCashText] = useState12(
3598
+ const [pieces, setPieces] = useState13({});
3599
+ const [cashText, setCashText] = useState13(
3447
3600
  () => session?.counted?.cash != null ? minorToDecimal(session.counted.cash, digits) : ""
3448
3601
  );
3449
- const [others, setOthers] = useState12(
3602
+ const [others, setOthers] = useState13(
3450
3603
  () => Object.fromEntries(
3451
3604
  Object.entries(session?.counted ?? {}).filter(([method]) => method !== "cash").map(([method, minor]) => [method, minorToDecimal(minor, digits)])
3452
3605
  )
3453
3606
  );
3454
- const [busy, setBusy] = useState12(false);
3455
- const [error, setError] = useState12("");
3456
- const [refusal, setRefusal] = useState12("");
3607
+ const [busy, setBusy] = useState13(false);
3608
+ const [error, setError] = useState13("");
3609
+ const [refusal, setRefusal] = useState13("");
3457
3610
  const usingTiles = Object.keys(pieces).length > 0;
3458
3611
  const tilesTotal = denominationTotal(pieces);
3459
3612
  const displayAmount = usingTiles ? minorToDecimal(tilesTotal, digits) : cashText;
@@ -3501,11 +3654,11 @@ function RegisterCount({ register, currency, approve, className }) {
3501
3654
  void attempt(() => actions.closeSession({ counted }));
3502
3655
  };
3503
3656
  if (!session) return null;
3504
- return /* @__PURE__ */ jsxs40(View47, { testID: "register-count", className: cn76("bg-card flex-1 rounded-md", className), children: [
3505
- /* @__PURE__ */ jsxs40(ScrollView11, { className: "flex-1", contentContainerClassName: "gap-3 p-4", children: [
3506
- /* @__PURE__ */ jsx81(Text, { className: "min-h-11 text-lg font-semibold", children: "Count the drawer" }),
3507
- /* @__PURE__ */ jsx81(Label, { testID: "count-amount-label", nativeID: AMOUNT_LABEL_ID3, children: `Cash counted (${currencySymbol3(currency)})` }),
3508
- /* @__PURE__ */ jsx81(Input, { children: /* @__PURE__ */ jsx81(
3657
+ return /* @__PURE__ */ jsxs41(View49, { testID: "register-count", className: cn78("bg-card flex-1 rounded-md", className), children: [
3658
+ /* @__PURE__ */ jsxs41(ScrollView11, { className: "flex-1", contentContainerClassName: "gap-3 p-4", children: [
3659
+ /* @__PURE__ */ jsx83(Text, { className: "min-h-11 text-lg font-semibold", children: "Count the drawer" }),
3660
+ /* @__PURE__ */ jsx83(Label, { testID: "count-amount-label", nativeID: AMOUNT_LABEL_ID3, children: `Cash counted (${currencySymbol3(currency)})` }),
3661
+ /* @__PURE__ */ jsx83(Input, { children: /* @__PURE__ */ jsx83(
3509
3662
  Input.Field,
3510
3663
  {
3511
3664
  testID: "count-amount",
@@ -3519,16 +3672,16 @@ function RegisterCount({ register, currency, approve, className }) {
3519
3672
  accessibilityLabelledBy: AMOUNT_LABEL_ID3
3520
3673
  }
3521
3674
  ) }),
3522
- !blind && valid && /* @__PURE__ */ jsx81(Text, { testID: "count-variance", className: "min-h-11 tabular-nums", children: `Expected ${formatMoney7({ amount: expected.cash ?? 0, currency })} \xB7 ${varianceText(
3675
+ !blind && valid && /* @__PURE__ */ jsx83(Text, { testID: "count-variance", className: "min-h-11 tabular-nums", children: `Expected ${formatMoney7({ amount: expected.cash ?? 0, currency })} \xB7 ${varianceText(
3523
3676
  variance,
3524
3677
  digits,
3525
3678
  (major) => formatMoney7({ amount: Math.round(major * 10 ** digits), currency }) ?? "",
3526
3679
  varianceWord
3527
3680
  )}` }),
3528
- /* @__PURE__ */ jsxs40(View47, { testID: "count-denominations", className: "gap-2", children: [
3529
- Array.from({ length: Math.ceil(faces.length / columns) }, (_, row) => /* @__PURE__ */ jsx81(View47, { className: "flex-row gap-2", children: Array.from({ length: columns }, (_2, column) => {
3681
+ /* @__PURE__ */ jsxs41(View49, { testID: "count-denominations", className: "gap-2", children: [
3682
+ Array.from({ length: Math.ceil(faces.length / columns) }, (_, row) => /* @__PURE__ */ jsx83(View49, { className: "flex-row gap-2", children: Array.from({ length: columns }, (_2, column) => {
3530
3683
  const value = faces[row * columns + column];
3531
- return value ? /* @__PURE__ */ jsx81(
3684
+ return value ? /* @__PURE__ */ jsx83(
3532
3685
  DenominationTile,
3533
3686
  {
3534
3687
  value,
@@ -3537,9 +3690,9 @@ function RegisterCount({ register, currency, approve, className }) {
3537
3690
  onAdd: (n) => addPieces(value, n)
3538
3691
  },
3539
3692
  value
3540
- ) : /* @__PURE__ */ jsx81(View47, { className: "flex-1" }, column);
3693
+ ) : /* @__PURE__ */ jsx83(View49, { className: "flex-1" }, column);
3541
3694
  }) }, row)),
3542
- /* @__PURE__ */ jsx81(
3695
+ /* @__PURE__ */ jsx83(
3543
3696
  Button,
3544
3697
  {
3545
3698
  testID: "count-clear",
@@ -3549,16 +3702,16 @@ function RegisterCount({ register, currency, approve, className }) {
3549
3702
  setPieces({});
3550
3703
  setCashText(minorToDecimal(0, digits));
3551
3704
  },
3552
- children: /* @__PURE__ */ jsx81(Text, { children: "Clear" })
3705
+ children: /* @__PURE__ */ jsx83(Text, { children: "Clear" })
3553
3706
  }
3554
3707
  )
3555
3708
  ] }),
3556
3709
  otherMethods.map((method) => {
3557
3710
  const labelId = `count-tender-${method}-label`;
3558
3711
  const label = `${tenderLabel(method)} counted (${currencySymbol3(currency)})`;
3559
- return /* @__PURE__ */ jsxs40(View47, { className: "gap-2", children: [
3560
- /* @__PURE__ */ jsx81(Label, { testID: labelId, nativeID: labelId, children: label }),
3561
- /* @__PURE__ */ jsx81(Input, { children: /* @__PURE__ */ jsx81(
3712
+ return /* @__PURE__ */ jsxs41(View49, { className: "gap-2", children: [
3713
+ /* @__PURE__ */ jsx83(Label, { testID: labelId, nativeID: labelId, children: label }),
3714
+ /* @__PURE__ */ jsx83(Input, { children: /* @__PURE__ */ jsx83(
3562
3715
  Input.Field,
3563
3716
  {
3564
3717
  testID: `count-tender-${method}`,
@@ -3571,11 +3724,11 @@ function RegisterCount({ register, currency, approve, className }) {
3571
3724
  ) })
3572
3725
  ] }, method);
3573
3726
  }),
3574
- !!refusal && /* @__PURE__ */ jsx81(Text, { testID: "count-manager-line", className: "text-warning min-h-11", children: refusal }),
3575
- !!error && /* @__PURE__ */ jsx81(Text, { testID: "count-error", className: "text-destructive min-h-11", children: error })
3727
+ !!refusal && /* @__PURE__ */ jsx83(Text, { testID: "count-manager-line", className: "text-warning min-h-11", children: refusal }),
3728
+ !!error && /* @__PURE__ */ jsx83(Text, { testID: "count-error", className: "text-destructive min-h-11", children: error })
3576
3729
  ] }),
3577
- /* @__PURE__ */ jsxs40(View47, { className: "gap-2 border-t border-border p-4", children: [
3578
- /* @__PURE__ */ jsx81(
3730
+ /* @__PURE__ */ jsxs41(View49, { className: "gap-2 border-t border-border p-4", children: [
3731
+ /* @__PURE__ */ jsx83(
3579
3732
  Button,
3580
3733
  {
3581
3734
  testID: "count-back",
@@ -3583,17 +3736,17 @@ function RegisterCount({ register, currency, approve, className }) {
3583
3736
  className: "min-h-11",
3584
3737
  disabled: busy,
3585
3738
  onPress: () => attempt(actions.backToSelling),
3586
- children: /* @__PURE__ */ jsx81(Text, { children: "Back to selling" })
3739
+ children: /* @__PURE__ */ jsx83(Text, { children: "Back to selling" })
3587
3740
  }
3588
3741
  ),
3589
- /* @__PURE__ */ jsx81(
3742
+ /* @__PURE__ */ jsx83(
3590
3743
  Button,
3591
3744
  {
3592
3745
  testID: "count-close",
3593
3746
  className: "min-h-14",
3594
3747
  disabled: !valid || otherTendersInvalid || busy,
3595
3748
  onPress: onClose,
3596
- children: /* @__PURE__ */ jsx81(Text, { children: busy ? "Closing\u2026" : "Close register" })
3749
+ children: /* @__PURE__ */ jsx83(Text, { children: busy ? "Closing\u2026" : "Close register" })
3597
3750
  }
3598
3751
  )
3599
3752
  ] })
@@ -3601,16 +3754,16 @@ function RegisterCount({ register, currency, approve, className }) {
3601
3754
  }
3602
3755
 
3603
3756
  // src/register/register-panel.tsx
3604
- import { jsx as jsx82, jsxs as jsxs41 } from "react/jsx-runtime";
3757
+ import { jsx as jsx84, jsxs as jsxs42 } from "react/jsx-runtime";
3605
3758
  var DIALOG_VERTICAL_MARGIN = 64;
3606
3759
  function RegisterPanel({ register, currency, registerName, open, onOpenChange, className }) {
3607
3760
  const { session, expected, salesCount, blind, movements, lastClosure, actions } = register;
3608
3761
  const otherTenders = Object.entries(expected).filter(([method, amount]) => method !== "cash" && amount !== 0);
3609
3762
  const { height: windowHeight } = useWindowDimensions2();
3610
3763
  const maxHeight = Math.max(280, windowHeight - DIALOG_VERTICAL_MARGIN);
3611
- const [movementType, setMovementType] = useState13(null);
3612
- const [expanded, setExpanded] = useState13(false);
3613
- const [error, setError] = useState13("");
3764
+ const [movementType, setMovementType] = useState14(null);
3765
+ const [expanded, setExpanded] = useState14(false);
3766
+ const [error, setError] = useState14("");
3614
3767
  const attempt = async (action) => {
3615
3768
  try {
3616
3769
  await action();
@@ -3622,25 +3775,25 @@ function RegisterPanel({ register, currency, registerName, open, onOpenChange, c
3622
3775
  const activeMovements = movements.filter(
3623
3776
  (row) => row.type !== "void" && !row.voided_by && !movements.some((entry) => entry.voids === row.id)
3624
3777
  );
3625
- return /* @__PURE__ */ jsx82(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs41(
3778
+ return /* @__PURE__ */ jsx84(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs42(
3626
3779
  DialogContent,
3627
3780
  {
3628
3781
  testID: "register-panel",
3629
3782
  className: `flex-col overflow-hidden ${className ?? ""}`,
3630
3783
  style: { maxHeight },
3631
3784
  children: [
3632
- /* @__PURE__ */ jsxs41(View48, { className: "flex-row items-center justify-between gap-2", children: [
3633
- /* @__PURE__ */ jsx82(DialogTitle, { testID: "register-panel-amount", children: registerName ?? "Register" }),
3634
- /* @__PURE__ */ jsx82(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx82(IconButton, { variant: "ghost", size: "sm", testID: "register-panel-dismiss", accessibilityLabel: "Close panel", children: /* @__PURE__ */ jsx82(XIcon, { size: 16 }) }) })
3785
+ /* @__PURE__ */ jsxs42(View50, { className: "flex-row items-center justify-between gap-2", children: [
3786
+ /* @__PURE__ */ jsx84(DialogTitle, { testID: "register-panel-amount", children: registerName ?? "Register" }),
3787
+ /* @__PURE__ */ jsx84(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx84(IconButton, { variant: "ghost", size: "sm", testID: "register-panel-dismiss", accessibilityLabel: "Close panel", children: /* @__PURE__ */ jsx84(XIcon, { size: 16 }) }) })
3635
3788
  ] }),
3636
- /* @__PURE__ */ jsxs41(Text, { testID: "register-panel-sales-count", children: [
3789
+ /* @__PURE__ */ jsxs42(Text, { testID: "register-panel-sales-count", children: [
3637
3790
  salesCount,
3638
3791
  " sale",
3639
3792
  salesCount === 1 ? "" : "s",
3640
3793
  " this session"
3641
3794
  ] }),
3642
- /* @__PURE__ */ jsxs41(ScrollView12, { testID: "register-panel-body", className: "flex-1", contentContainerClassName: "gap-3", children: [
3643
- /* @__PURE__ */ jsx82(View48, { className: "flex-row gap-2", children: ["paid_in", "paid_out", "no_sale"].map((type) => /* @__PURE__ */ jsx82(
3795
+ /* @__PURE__ */ jsxs42(ScrollView12, { testID: "register-panel-body", className: "flex-1", contentContainerClassName: "gap-3", children: [
3796
+ /* @__PURE__ */ jsx84(View50, { className: "flex-row gap-2", children: ["paid_in", "paid_out", "no_sale"].map((type) => /* @__PURE__ */ jsx84(
3644
3797
  Button,
3645
3798
  {
3646
3799
  testID: `register-panel-${type.replace("_", "-")}`,
@@ -3648,40 +3801,40 @@ function RegisterPanel({ register, currency, registerName, open, onOpenChange, c
3648
3801
  variant: "outline",
3649
3802
  disabled: session?.status !== "open",
3650
3803
  onPress: () => setMovementType(type),
3651
- children: /* @__PURE__ */ jsx82(Text, { children: type === "paid_in" ? "Paid in" : type === "paid_out" ? "Paid out" : "No sale" })
3804
+ children: /* @__PURE__ */ jsx84(Text, { children: type === "paid_in" ? "Paid in" : type === "paid_out" ? "Paid out" : "No sale" })
3652
3805
  },
3653
3806
  type
3654
3807
  )) }),
3655
- !blind && /* @__PURE__ */ jsxs41(View48, { testID: "register-panel-expected", className: "gap-1", children: [
3656
- /* @__PURE__ */ jsx82(Text, { className: "text-muted-foreground text-sm font-semibold", children: "Expected in the drawer" }),
3657
- Object.entries(expected).filter(([method]) => method === "cash").map(([method, amount]) => /* @__PURE__ */ jsxs41(View48, { className: "min-h-11 flex-row items-center justify-between", children: [
3658
- /* @__PURE__ */ jsx82(Text, { children: tenderLabel("cash") }),
3659
- /* @__PURE__ */ jsx82(Text, { className: "tabular-nums", children: formatMoney8({ amount, currency }) })
3808
+ !blind && /* @__PURE__ */ jsxs42(View50, { testID: "register-panel-expected", className: "gap-1", children: [
3809
+ /* @__PURE__ */ jsx84(Text, { className: "text-muted-foreground text-sm font-semibold", children: "Expected in the drawer" }),
3810
+ Object.entries(expected).filter(([method]) => method === "cash").map(([method, amount]) => /* @__PURE__ */ jsxs42(View50, { className: "min-h-11 flex-row items-center justify-between", children: [
3811
+ /* @__PURE__ */ jsx84(Text, { children: tenderLabel("cash") }),
3812
+ /* @__PURE__ */ jsx84(Text, { className: "tabular-nums", children: formatMoney8({ amount, currency }) })
3660
3813
  ] }, method))
3661
3814
  ] }),
3662
- !blind && otherTenders.length > 0 && /* @__PURE__ */ jsxs41(View48, { testID: "register-panel-other-tenders", className: "gap-1", children: [
3663
- /* @__PURE__ */ jsx82(Text, { className: "text-muted-foreground text-sm font-semibold", children: "Other tenders" }),
3664
- otherTenders.map(([method, amount]) => /* @__PURE__ */ jsxs41(View48, { className: "min-h-11 flex-row items-center justify-between", children: [
3665
- /* @__PURE__ */ jsx82(Text, { children: tenderLabel(method) }),
3666
- /* @__PURE__ */ jsx82(Text, { className: "tabular-nums", children: formatMoney8({ amount, currency }) })
3815
+ !blind && otherTenders.length > 0 && /* @__PURE__ */ jsxs42(View50, { testID: "register-panel-other-tenders", className: "gap-1", children: [
3816
+ /* @__PURE__ */ jsx84(Text, { className: "text-muted-foreground text-sm font-semibold", children: "Other tenders" }),
3817
+ otherTenders.map(([method, amount]) => /* @__PURE__ */ jsxs42(View50, { className: "min-h-11 flex-row items-center justify-between", children: [
3818
+ /* @__PURE__ */ jsx84(Text, { children: tenderLabel(method) }),
3819
+ /* @__PURE__ */ jsx84(Text, { className: "tabular-nums", children: formatMoney8({ amount, currency }) })
3667
3820
  ] }, method))
3668
3821
  ] }),
3669
- /* @__PURE__ */ jsx82(
3822
+ /* @__PURE__ */ jsx84(
3670
3823
  Button,
3671
3824
  {
3672
3825
  testID: "register-panel-movements",
3673
3826
  variant: "ghost",
3674
3827
  className: "min-h-11",
3675
3828
  onPress: () => setExpanded(!expanded),
3676
- children: /* @__PURE__ */ jsx82(Text, { children: "Paid in / out" })
3829
+ children: /* @__PURE__ */ jsx84(Text, { children: "Paid in / out" })
3677
3830
  }
3678
3831
  ),
3679
- expanded && activeMovements.map((row) => /* @__PURE__ */ jsxs41(View48, { className: "min-h-11 flex-row items-center gap-2", children: [
3680
- /* @__PURE__ */ jsxs41(Text, { testID: `movement-row-${row.id}`, className: "flex-1", children: [
3832
+ expanded && activeMovements.map((row) => /* @__PURE__ */ jsxs42(View50, { className: "min-h-11 flex-row items-center gap-2", children: [
3833
+ /* @__PURE__ */ jsxs42(Text, { testID: `movement-row-${row.id}`, className: "flex-1", children: [
3681
3834
  row.type === "paid_in" ? "Paid in" : row.type === "paid_out" ? "Paid out" : "No sale",
3682
3835
  !blind ? ` \xB7 ${formatMoney8({ amount: row.amountMinor, currency })} \xB7 ${row.reason}` : ""
3683
3836
  ] }),
3684
- /* @__PURE__ */ jsx82(
3837
+ /* @__PURE__ */ jsx84(
3685
3838
  Button,
3686
3839
  {
3687
3840
  variant: "ghost",
@@ -3689,12 +3842,12 @@ function RegisterPanel({ register, currency, registerName, open, onOpenChange, c
3689
3842
  testID: `movement-void-${row.id}`,
3690
3843
  disabled: session?.status !== "open",
3691
3844
  onPress: () => attempt(() => actions.voidMovement(row.id)),
3692
- children: /* @__PURE__ */ jsx82(Text, { children: "Undo" })
3845
+ children: /* @__PURE__ */ jsx84(Text, { children: "Undo" })
3693
3846
  }
3694
3847
  )
3695
3848
  ] }, row.id)),
3696
- !!error && /* @__PURE__ */ jsx82(Text, { className: "text-destructive", children: error }),
3697
- /* @__PURE__ */ jsx82(
3849
+ !!error && /* @__PURE__ */ jsx84(Text, { className: "text-destructive", children: error }),
3850
+ /* @__PURE__ */ jsx84(
3698
3851
  Button,
3699
3852
  {
3700
3853
  testID: "register-panel-close",
@@ -3705,11 +3858,11 @@ function RegisterPanel({ register, currency, registerName, open, onOpenChange, c
3705
3858
  await actions.startCounting();
3706
3859
  onOpenChange(false);
3707
3860
  }),
3708
- children: /* @__PURE__ */ jsx82(Text, { children: "Close register" })
3861
+ children: /* @__PURE__ */ jsx84(Text, { children: "Close register" })
3709
3862
  }
3710
3863
  )
3711
3864
  ] }),
3712
- movementType && /* @__PURE__ */ jsx82(
3865
+ movementType && /* @__PURE__ */ jsx84(
3713
3866
  MovementSheet,
3714
3867
  {
3715
3868
  register,
@@ -3727,9 +3880,9 @@ function RegisterPanel({ register, currency, registerName, open, onOpenChange, c
3727
3880
  }
3728
3881
 
3729
3882
  // src/register/register-column.tsx
3730
- import { useState as useState14 } from "react";
3731
- import { View as View49 } from "react-native";
3732
- import { Fragment as Fragment4, jsx as jsx83, jsxs as jsxs42 } from "react/jsx-runtime";
3883
+ import { useState as useState15 } from "react";
3884
+ import { View as View51 } from "react-native";
3885
+ import { Fragment as Fragment4, jsx as jsx85, jsxs as jsxs43 } from "react/jsx-runtime";
3733
3886
  function RegisterColumn({
3734
3887
  register,
3735
3888
  registerId,
@@ -3741,30 +3894,30 @@ function RegisterColumn({
3741
3894
  cartEmpty,
3742
3895
  children
3743
3896
  }) {
3744
- const [finishing, setFinishing] = useState14(false);
3897
+ const [finishing, setFinishing] = useState15(false);
3745
3898
  if (registerId === null) {
3746
- return /* @__PURE__ */ jsx83(RegisterPicker, { registers, onPick, className: "flex-1" });
3899
+ return /* @__PURE__ */ jsx85(RegisterPicker, { registers, onPick, className: "flex-1" });
3747
3900
  }
3748
3901
  if (register.session?.status === "closed") {
3749
- return register.closing && !finishing ? /* @__PURE__ */ jsx83(Fragment4, { children: countSlot }) : /* @__PURE__ */ jsx83(FinishClose, { register, busy: finishing, setBusy: setFinishing });
3902
+ return register.closing && !finishing ? /* @__PURE__ */ jsx85(Fragment4, { children: countSlot }) : /* @__PURE__ */ jsx85(FinishClose, { register, busy: finishing, setBusy: setFinishing });
3750
3903
  }
3751
3904
  if (!register.session) {
3752
- return /* @__PURE__ */ jsx83(OpenRegisterCard, { register, currency, configuredFloatMinor, className: "flex-1" });
3905
+ return /* @__PURE__ */ jsx85(OpenRegisterCard, { register, currency, configuredFloatMinor, className: "flex-1" });
3753
3906
  }
3754
3907
  if (register.session.status === "counting") {
3755
- return /* @__PURE__ */ jsx83(Fragment4, { children: countSlot });
3908
+ return /* @__PURE__ */ jsx85(Fragment4, { children: countSlot });
3756
3909
  }
3757
- return /* @__PURE__ */ jsxs42(View49, { testID: "register-column", className: "flex-1", children: [
3758
- register.overdue && cartEmpty && /* @__PURE__ */ jsxs42(View49, { testID: "register-column-overdue", className: "bg-warning/10 flex-row items-center justify-between gap-2 px-3 py-2", children: [
3759
- /* @__PURE__ */ jsx83(Text, { className: "flex-1", children: "This register is overdue for closing." }),
3760
- /* @__PURE__ */ jsx83(
3910
+ return /* @__PURE__ */ jsxs43(View51, { testID: "register-column", className: "flex-1", children: [
3911
+ register.overdue && cartEmpty && /* @__PURE__ */ jsxs43(View51, { testID: "register-column-overdue", className: "bg-warning/10 flex-row items-center justify-between gap-2 px-3 py-2", children: [
3912
+ /* @__PURE__ */ jsx85(Text, { className: "flex-1", children: "This register is overdue for closing." }),
3913
+ /* @__PURE__ */ jsx85(
3761
3914
  Button,
3762
3915
  {
3763
3916
  testID: "register-column-close-overdue",
3764
3917
  variant: "outline",
3765
3918
  className: "min-h-11",
3766
3919
  onPress: () => register.actions.startCounting(),
3767
- children: /* @__PURE__ */ jsx83(Text, { children: "Close register" })
3920
+ children: /* @__PURE__ */ jsx85(Text, { children: "Close register" })
3768
3921
  }
3769
3922
  )
3770
3923
  ] }),
@@ -3772,7 +3925,7 @@ function RegisterColumn({
3772
3925
  ] });
3773
3926
  }
3774
3927
  function FinishClose({ register, busy, setBusy }) {
3775
- const [error, setError] = useState14("");
3928
+ const [error, setError] = useState15("");
3776
3929
  const finish = async () => {
3777
3930
  setBusy(true);
3778
3931
  setError("");
@@ -3784,19 +3937,19 @@ function FinishClose({ register, busy, setBusy }) {
3784
3937
  setBusy(false);
3785
3938
  }
3786
3939
  };
3787
- return /* @__PURE__ */ jsxs42(View49, { testID: "register-column-finish-close", className: "flex-1 gap-3 p-4", children: [
3788
- /* @__PURE__ */ jsx83(Text, { children: "The last close didn't finish." }),
3789
- /* @__PURE__ */ jsx83(Button, { testID: "register-column-finish-close-button", nativeID: "register-column-finish-close-button", disabled: busy, onPress: finish, children: /* @__PURE__ */ jsx83(Text, { children: "Finish closing" }) }),
3790
- !!error && /* @__PURE__ */ jsx83(Text, { testID: "register-column-finish-close-error", className: "text-destructive", children: error })
3940
+ return /* @__PURE__ */ jsxs43(View51, { testID: "register-column-finish-close", className: "flex-1 gap-3 p-4", children: [
3941
+ /* @__PURE__ */ jsx85(Text, { children: "The last close didn't finish." }),
3942
+ /* @__PURE__ */ jsx85(Button, { testID: "register-column-finish-close-button", nativeID: "register-column-finish-close-button", disabled: busy, onPress: finish, children: /* @__PURE__ */ jsx85(Text, { children: "Finish closing" }) }),
3943
+ !!error && /* @__PURE__ */ jsx85(Text, { testID: "register-column-finish-close-error", className: "text-destructive", children: error })
3791
3944
  ] });
3792
3945
  }
3793
3946
 
3794
3947
  // src/register/closure-sheet.tsx
3795
- import { useEffect as useEffect4, useRef as useRef5, useState as useState15 } from "react";
3796
- import { AccessibilityInfo, Animated, View as View50 } from "react-native";
3948
+ import { useEffect as useEffect4, useRef as useRef5, useState as useState16 } from "react";
3949
+ import { AccessibilityInfo, Animated, View as View52 } from "react-native";
3797
3950
  import { countVariance as countVariance2, TAX_ROUNDING_MIXED_NOTE, varianceText as varianceText2 } from "@tallyui/pos";
3798
3951
  import { formatMoney as formatMoney9, minorUnitDigits as minorUnitDigits6 } from "@tallyui/core";
3799
- import { jsx as jsx84, jsxs as jsxs43 } from "react/jsx-runtime";
3952
+ import { jsx as jsx86, jsxs as jsxs44 } from "react/jsx-runtime";
3800
3953
  function useCompletionMotion() {
3801
3954
  const opacity = useRef5(new Animated.Value(0)).current;
3802
3955
  const scale = useRef5(new Animated.Value(0.6)).current;
@@ -3824,8 +3977,8 @@ function ClosureSheet({ register, currency, onPrint, onDone }) {
3824
3977
  const { lastClosure: closure, blind } = register;
3825
3978
  const digits = minorUnitDigits6(currency);
3826
3979
  const { opacity, scale } = useCompletionMotion();
3827
- const [busy, setBusy] = useState15(false);
3828
- const [error, setError] = useState15("");
3980
+ const [busy, setBusy] = useState16(false);
3981
+ const [error, setError] = useState16("");
3829
3982
  if (!closure) return null;
3830
3983
  const methods = Object.keys(closure.counted);
3831
3984
  const approvedByName = closure.breakdowns.approved_by_name;
@@ -3843,34 +3996,34 @@ function ClosureSheet({ register, currency, onPrint, onDone }) {
3843
3996
  setBusy(false);
3844
3997
  }
3845
3998
  };
3846
- return /* @__PURE__ */ jsx84(
3999
+ return /* @__PURE__ */ jsx86(
3847
4000
  Dialog,
3848
4001
  {
3849
4002
  open: true,
3850
4003
  onOpenChange: (open) => {
3851
4004
  if (!open) onDone();
3852
4005
  },
3853
- children: /* @__PURE__ */ jsxs43(DialogContent, { testID: "closure-sheet", children: [
3854
- /* @__PURE__ */ jsx84(
4006
+ children: /* @__PURE__ */ jsxs44(DialogContent, { testID: "closure-sheet", children: [
4007
+ /* @__PURE__ */ jsx86(
3855
4008
  Animated.View,
3856
4009
  {
3857
4010
  testID: "closure-check",
3858
4011
  style: { opacity, transform: [{ scale }] },
3859
4012
  className: "bg-success/10 h-10 w-10 items-center justify-center rounded-full",
3860
- children: /* @__PURE__ */ jsx84(Text, { className: "text-success text-lg font-bold", accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants", children: "\u2713" })
4013
+ children: /* @__PURE__ */ jsx86(Text, { className: "text-success text-lg font-bold", accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants", children: "\u2713" })
3861
4014
  }
3862
4015
  ),
3863
- /* @__PURE__ */ jsx84(DialogTitle, { testID: "closure-title", children: "Register closed" }),
3864
- /* @__PURE__ */ jsx84(Text, { testID: "closure-number", className: "text-muted-foreground min-h-11", children: `Closure #${closure.number}` }),
3865
- !blind && /* @__PURE__ */ jsx84(View50, { testID: "closure-figures", className: "gap-3", children: methods.map((method) => {
4016
+ /* @__PURE__ */ jsx86(DialogTitle, { testID: "closure-title", children: "Register closed" }),
4017
+ /* @__PURE__ */ jsx86(Text, { testID: "closure-number", className: "text-muted-foreground min-h-11", children: `Closure #${closure.number}` }),
4018
+ !blind && /* @__PURE__ */ jsx86(View52, { testID: "closure-figures", className: "gap-3", children: methods.map((method) => {
3866
4019
  const countedMinor = closure.counted[method] ?? 0;
3867
4020
  const expectedMinor = closure.expected[method] ?? 0;
3868
4021
  const varianceMinor = closure.variance[method] ?? countVariance2(countedMinor, expectedMinor);
3869
- return /* @__PURE__ */ jsxs43(View50, { className: "gap-1", children: [
3870
- /* @__PURE__ */ jsx84(Text, { className: "text-muted-foreground text-xs font-semibold", children: tenderLabel(method) }),
3871
- /* @__PURE__ */ jsx84(Text, { testID: `closure-counted-${method}`, className: "min-h-11 tabular-nums", children: `Counted ${formatMoney9({ amount: countedMinor, currency })}` }),
3872
- /* @__PURE__ */ jsx84(Text, { testID: `closure-expected-${method}`, className: "min-h-11 tabular-nums", children: `Expected ${formatMoney9({ amount: expectedMinor, currency })}` }),
3873
- /* @__PURE__ */ jsx84(Text, { testID: `closure-variance-${method}`, className: "min-h-11 tabular-nums", children: varianceText2(
4022
+ return /* @__PURE__ */ jsxs44(View52, { className: "gap-1", children: [
4023
+ /* @__PURE__ */ jsx86(Text, { className: "text-muted-foreground text-xs font-semibold", children: tenderLabel(method) }),
4024
+ /* @__PURE__ */ jsx86(Text, { testID: `closure-counted-${method}`, className: "min-h-11 tabular-nums", children: `Counted ${formatMoney9({ amount: countedMinor, currency })}` }),
4025
+ /* @__PURE__ */ jsx86(Text, { testID: `closure-expected-${method}`, className: "min-h-11 tabular-nums", children: `Expected ${formatMoney9({ amount: expectedMinor, currency })}` }),
4026
+ /* @__PURE__ */ jsx86(Text, { testID: `closure-variance-${method}`, className: "min-h-11 tabular-nums", children: varianceText2(
3874
4027
  varianceMinor,
3875
4028
  digits,
3876
4029
  (major) => formatMoney9({ amount: Math.round(major * 10 ** digits), currency }) ?? "",
@@ -3878,51 +4031,51 @@ function ClosureSheet({ register, currency, onPrint, onDone }) {
3878
4031
  ) })
3879
4032
  ] }, method);
3880
4033
  }) }),
3881
- !!approvedBy && /* @__PURE__ */ jsxs43(Text, { testID: "closure-approved-by", children: [
4034
+ !!approvedBy && /* @__PURE__ */ jsxs44(Text, { testID: "closure-approved-by", children: [
3882
4035
  "Approved by ",
3883
4036
  approvedBy
3884
4037
  ] }),
3885
- closure.breakdowns.tax_rounding_mixed === true && /* @__PURE__ */ jsx84(Text, { testID: "closure-tax-rounding-mixed", className: "text-muted-foreground", children: TAX_ROUNDING_MIXED_NOTE }),
3886
- !!error && /* @__PURE__ */ jsx84(Text, { testID: "closure-print-error", className: "text-destructive", children: error }),
3887
- !blind && !!onPrint && /* @__PURE__ */ jsx84(Button, { testID: "closure-print", className: "min-h-14", disabled: busy, onPress: print, children: /* @__PURE__ */ jsx84(Text, { children: busy ? "Printing\u2026" : "Print the Z report" }) }),
3888
- /* @__PURE__ */ jsx84(Button, { testID: "closure-done", variant: "outline", className: "min-h-14", onPress: onDone, children: /* @__PURE__ */ jsx84(Text, { children: "Done" }) })
4038
+ closure.breakdowns.tax_rounding_mixed === true && /* @__PURE__ */ jsx86(Text, { testID: "closure-tax-rounding-mixed", className: "text-muted-foreground", children: TAX_ROUNDING_MIXED_NOTE }),
4039
+ !!error && /* @__PURE__ */ jsx86(Text, { testID: "closure-print-error", className: "text-destructive", children: error }),
4040
+ !blind && !!onPrint && /* @__PURE__ */ jsx86(Button, { testID: "closure-print", className: "min-h-14", disabled: busy, onPress: print, children: /* @__PURE__ */ jsx86(Text, { children: busy ? "Printing\u2026" : "Print the Z report" }) }),
4041
+ /* @__PURE__ */ jsx86(Button, { testID: "closure-done", variant: "outline", className: "min-h-14", onPress: onDone, children: /* @__PURE__ */ jsx86(Text, { children: "Done" }) })
3889
4042
  ] })
3890
4043
  }
3891
4044
  );
3892
4045
  }
3893
4046
 
3894
4047
  // src/settings/settings-row.tsx
3895
- import { Text as Text29, View as View51 } from "react-native";
3896
- import { cn as cn77 } from "@tallyui/theme";
3897
- import { jsx as jsx85, jsxs as jsxs44 } from "react/jsx-runtime";
4048
+ import { Text as Text30, View as View53 } from "react-native";
4049
+ import { cn as cn79 } from "@tallyui/theme";
4050
+ import { jsx as jsx87, jsxs as jsxs45 } from "react/jsx-runtime";
3898
4051
  function SettingsRow({ label, description, action, className, ...viewProps }) {
3899
- return /* @__PURE__ */ jsxs44(View51, { className: cn77("flex-row items-center gap-3 px-4 py-3", className), ...viewProps, children: [
3900
- /* @__PURE__ */ jsxs44(View51, { className: "flex-1 gap-0.5", children: [
3901
- /* @__PURE__ */ jsx85(Text29, { className: "text-sm font-medium text-foreground", children: label }),
3902
- description && /* @__PURE__ */ jsx85(Text29, { className: "text-xs text-muted-foreground", children: description })
4052
+ return /* @__PURE__ */ jsxs45(View53, { className: cn79("flex-row items-center gap-3 px-4 py-3", className), ...viewProps, children: [
4053
+ /* @__PURE__ */ jsxs45(View53, { className: "flex-1 gap-0.5", children: [
4054
+ /* @__PURE__ */ jsx87(Text30, { className: "text-sm font-medium text-foreground", children: label }),
4055
+ description && /* @__PURE__ */ jsx87(Text30, { className: "text-xs text-muted-foreground", children: description })
3903
4056
  ] }),
3904
- action && /* @__PURE__ */ jsx85(View51, { children: action })
4057
+ action && /* @__PURE__ */ jsx87(View53, { children: action })
3905
4058
  ] });
3906
4059
  }
3907
4060
 
3908
4061
  // src/settings/settings-group.tsx
3909
- import { Text as Text30, View as View52 } from "react-native";
3910
- import { cn as cn78 } from "@tallyui/theme";
3911
- import { jsx as jsx86, jsxs as jsxs45 } from "react/jsx-runtime";
4062
+ import { Text as Text31, View as View54 } from "react-native";
4063
+ import { cn as cn80 } from "@tallyui/theme";
4064
+ import { jsx as jsx88, jsxs as jsxs46 } from "react/jsx-runtime";
3912
4065
  function SettingsGroup({ title, description, children, className, ...viewProps }) {
3913
- return /* @__PURE__ */ jsxs45(View52, { className: cn78("gap-1", className), ...viewProps, children: [
3914
- /* @__PURE__ */ jsxs45(View52, { className: "px-4 py-2", children: [
3915
- /* @__PURE__ */ jsx86(Text30, { className: "text-sm font-semibold text-foreground", children: title }),
3916
- description && /* @__PURE__ */ jsx86(Text30, { className: "text-xs text-muted-foreground", children: description })
4066
+ return /* @__PURE__ */ jsxs46(View54, { className: cn80("gap-1", className), ...viewProps, children: [
4067
+ /* @__PURE__ */ jsxs46(View54, { className: "px-4 py-2", children: [
4068
+ /* @__PURE__ */ jsx88(Text31, { className: "text-sm font-semibold text-foreground", children: title }),
4069
+ description && /* @__PURE__ */ jsx88(Text31, { className: "text-xs text-muted-foreground", children: description })
3917
4070
  ] }),
3918
- /* @__PURE__ */ jsx86(View52, { className: "rounded-lg border border-border bg-card", children })
4071
+ /* @__PURE__ */ jsx88(View54, { className: "rounded-lg border border-border bg-card", children })
3919
4072
  ] });
3920
4073
  }
3921
4074
 
3922
4075
  // src/settings/connector-status.tsx
3923
- import { Text as Text31, View as View53 } from "react-native";
3924
- import { cn as cn79 } from "@tallyui/theme";
3925
- import { jsx as jsx87, jsxs as jsxs46 } from "react/jsx-runtime";
4076
+ import { Text as Text32, View as View55 } from "react-native";
4077
+ import { cn as cn81 } from "@tallyui/theme";
4078
+ import { jsx as jsx89, jsxs as jsxs47 } from "react/jsx-runtime";
3926
4079
  function defaultFormatUnsold(count2, stale) {
3927
4080
  return `${count2} ${count2 === 1 ? "product" : "products"} not sold in this channel${stale ? " (last check failed)" : ""}`;
3928
4081
  }
@@ -3944,33 +4097,34 @@ function ConnectorStatus({
3944
4097
  ...viewProps
3945
4098
  }) {
3946
4099
  const config = STATUS_CONFIG2[status];
3947
- return /* @__PURE__ */ jsxs46(View53, { className: cn79("gap-2 rounded-lg border border-border bg-card p-3", className), ...viewProps, children: [
3948
- /* @__PURE__ */ jsxs46(View53, { className: "flex-row items-center justify-between", children: [
3949
- /* @__PURE__ */ jsx87(Text31, { className: "text-sm font-semibold text-foreground", children: name }),
3950
- /* @__PURE__ */ jsxs46(View53, { className: "flex-row items-center gap-1.5", children: [
3951
- /* @__PURE__ */ jsx87(View53, { className: cn79("h-2 w-2 rounded-full", config.dot) }),
3952
- /* @__PURE__ */ jsx87(Text31, { className: cn79("text-xs font-medium", config.text), children: config.label })
4100
+ return /* @__PURE__ */ jsxs47(View55, { className: cn81("gap-2 rounded-lg border border-border bg-card p-3", className), ...viewProps, children: [
4101
+ /* @__PURE__ */ jsxs47(View55, { className: "flex-row items-center justify-between", children: [
4102
+ /* @__PURE__ */ jsx89(Text32, { className: "text-sm font-semibold text-foreground", children: name }),
4103
+ /* @__PURE__ */ jsxs47(View55, { className: "flex-row items-center gap-1.5", children: [
4104
+ /* @__PURE__ */ jsx89(View55, { className: cn81("h-2 w-2 rounded-full", config.dot) }),
4105
+ /* @__PURE__ */ jsx89(Text32, { className: cn81("text-xs font-medium", config.text), children: config.label })
3953
4106
  ] })
3954
4107
  ] }),
3955
- lastSync && /* @__PURE__ */ jsxs46(Text31, { className: "text-xs text-muted-foreground", children: [
4108
+ lastSync && /* @__PURE__ */ jsxs47(Text32, { className: "text-xs text-muted-foreground", children: [
3956
4109
  "Last sync: ",
3957
4110
  lastSync
3958
4111
  ] }),
3959
- error && /* @__PURE__ */ jsx87(Text31, { className: "text-xs text-destructive", children: error }),
3960
- !!unsoldCount && /* @__PURE__ */ jsx87(Text31, { className: cn79("text-xs", unsoldStale ? "text-muted-foreground" : "text-warning"), children: formatUnsold(unsoldCount, !!unsoldStale) })
4112
+ error && /* @__PURE__ */ jsx89(Text32, { className: "text-xs text-destructive", children: error }),
4113
+ !!unsoldCount && /* @__PURE__ */ jsx89(Text32, { className: cn81("text-xs", unsoldStale ? "text-muted-foreground" : "text-warning"), children: formatUnsold(unsoldCount, !!unsoldStale) })
3961
4114
  ] });
3962
4115
  }
3963
4116
 
3964
4117
  // src/sale/cart.tsx
3965
- import { useState as useState18 } from "react";
3966
- import { Pressable as Pressable25, Text as Text34, View as View56 } from "react-native";
4118
+ import { useState as useState20 } from "react";
4119
+ import { Pressable as Pressable28, Text as Text36, View as View59 } from "react-native";
4120
+ import { formatMoney as formatMoney12 } from "@tallyui/core";
3967
4121
  import { buildReceiptData } from "@tallyui/pos";
3968
4122
 
3969
4123
  // src/sale/discount-form.tsx
3970
- import { useState as useState16 } from "react";
3971
- import { Pressable as Pressable23, Text as Text32, TextInput as TextInput9, View as View54 } from "react-native";
4124
+ import { useState as useState17 } from "react";
4125
+ import { Pressable as Pressable25, Text as Text33, TextInput as TextInput9, View as View56 } from "react-native";
3972
4126
  import { formatMoney as formatMoney10, minorUnitDigits as minorUnitDigits7, moneyFromDecimalString as moneyFromDecimalString2 } from "@tallyui/core";
3973
- import { jsx as jsx88, jsxs as jsxs47 } from "react/jsx-runtime";
4127
+ import { jsx as jsx90, jsxs as jsxs48 } from "react/jsx-runtime";
3974
4128
  function parseDiscount(type, text, currency) {
3975
4129
  const raw = text.trim();
3976
4130
  const trimmed = raw.split(",").length === 2 ? raw.replace(",", ".") : raw;
@@ -3987,30 +4141,30 @@ function parseDiscount(type, text, currency) {
3987
4141
  var discountLabel = (discount, currency) => discount.type === "percentage" ? `${discount.value}%` : formatMoney10({ amount: discount.amountMinor, currency }) ?? String(discount.amountMinor);
3988
4142
  var button = "rounded-md border border-border px-3 py-2 min-h-11 items-center justify-center";
3989
4143
  function DiscountForm({ title, currency, onApply, onClose }) {
3990
- const [type, setType] = useState16("percentage");
3991
- const [text, setText] = useState16("");
3992
- const [error, setError] = useState16(null);
4144
+ const [type, setType] = useState17("percentage");
4145
+ const [text, setText] = useState17("");
4146
+ const [error, setError] = useState17(null);
3993
4147
  function apply() {
3994
4148
  const parsed = parseDiscount(type, text, currency);
3995
4149
  const refused = typeof parsed === "string" ? parsed : onApply(parsed);
3996
4150
  setError(refused);
3997
4151
  if (refused === null) onClose();
3998
4152
  }
3999
- return /* @__PURE__ */ jsxs47(View54, { role: "group", accessibilityLabel: title, className: "gap-2 px-3 py-2", children: [
4000
- /* @__PURE__ */ jsx88(Text32, { className: "font-semibold text-foreground", children: title }),
4001
- /* @__PURE__ */ jsxs47(View54, { className: "flex-row gap-2", children: [
4002
- ["percentage", "fixed"].map((option) => /* @__PURE__ */ jsx88(
4003
- Pressable23,
4153
+ return /* @__PURE__ */ jsxs48(View56, { role: "group", accessibilityLabel: title, className: "gap-2 px-3 py-2", children: [
4154
+ /* @__PURE__ */ jsx90(Text33, { className: "font-semibold text-foreground", children: title }),
4155
+ /* @__PURE__ */ jsxs48(View56, { className: "flex-row gap-2", children: [
4156
+ ["percentage", "fixed"].map((option) => /* @__PURE__ */ jsx90(
4157
+ Pressable25,
4004
4158
  {
4005
4159
  accessibilityRole: "button",
4006
4160
  accessibilityState: { selected: type === option },
4007
4161
  onPress: () => setType(option),
4008
4162
  className: `${button} ${type === option ? "bg-primary" : "bg-card"}`,
4009
- children: /* @__PURE__ */ jsx88(Text32, { className: type === option ? "text-primary-foreground" : "text-foreground", children: option === "percentage" ? "Percent" : "Amount" })
4163
+ children: /* @__PURE__ */ jsx90(Text33, { className: type === option ? "text-primary-foreground" : "text-foreground", children: option === "percentage" ? "Percent" : "Amount" })
4010
4164
  },
4011
4165
  option
4012
4166
  )),
4013
- /* @__PURE__ */ jsx88(
4167
+ /* @__PURE__ */ jsx90(
4014
4168
  TextInput9,
4015
4169
  {
4016
4170
  accessibilityLabel: "Discount value",
@@ -4023,16 +4177,16 @@ function DiscountForm({ title, currency, onApply, onClose }) {
4023
4177
  }
4024
4178
  )
4025
4179
  ] }),
4026
- error ? /* @__PURE__ */ jsx88(Text32, { accessibilityRole: "alert", className: "text-destructive", children: error }) : null,
4027
- /* @__PURE__ */ jsxs47(View54, { className: "flex-row gap-2", children: [
4028
- /* @__PURE__ */ jsx88(Pressable23, { accessibilityRole: "button", onPress: apply, className: `${button} bg-primary`, children: /* @__PURE__ */ jsx88(Text32, { className: "font-semibold text-primary-foreground", children: "Apply" }) }),
4029
- /* @__PURE__ */ jsx88(Pressable23, { accessibilityRole: "button", onPress: onClose, className: `${button} bg-card`, children: /* @__PURE__ */ jsx88(Text32, { className: "text-foreground", children: "Cancel" }) })
4180
+ error ? /* @__PURE__ */ jsx90(Text33, { accessibilityRole: "alert", className: "text-destructive", children: error }) : null,
4181
+ /* @__PURE__ */ jsxs48(View56, { className: "flex-row gap-2", children: [
4182
+ /* @__PURE__ */ jsx90(Pressable25, { accessibilityRole: "button", onPress: apply, className: `${button} bg-primary`, children: /* @__PURE__ */ jsx90(Text33, { className: "font-semibold text-primary-foreground", children: "Apply" }) }),
4183
+ /* @__PURE__ */ jsx90(Pressable25, { accessibilityRole: "button", onPress: onClose, className: `${button} bg-card`, children: /* @__PURE__ */ jsx90(Text33, { className: "text-foreground", children: "Cancel" }) })
4030
4184
  ] })
4031
4185
  ] });
4032
4186
  }
4033
4187
  function DiscountChips({ discounts, currency, onRemove, prefix, amounts = [] }) {
4034
4188
  if (!discounts.length) return null;
4035
- return /* @__PURE__ */ jsx88(View54, { className: "flex-row flex-wrap gap-2 px-3", children: discounts.map((discount) => {
4189
+ return /* @__PURE__ */ jsx90(View56, { className: "flex-row flex-wrap gap-2 px-3", children: discounts.map((discount) => {
4036
4190
  const amount = amounts.find((row) => row.discountId === discount.id)?.amountMinor;
4037
4191
  const own = discountLabel(discount, currency);
4038
4192
  const label = [
@@ -4040,16 +4194,16 @@ function DiscountChips({ discounts, currency, onRemove, prefix, amounts = [] })
4040
4194
  amount === void 0 ? prefix ? `\u2212${own}` : own : discount.type === "percentage" ? own : null,
4041
4195
  amount === void 0 ? null : `\u2212${formatMoney10({ amount, currency })}`
4042
4196
  ].filter(Boolean).join(" ");
4043
- return /* @__PURE__ */ jsxs47(
4044
- Pressable23,
4197
+ return /* @__PURE__ */ jsxs48(
4198
+ Pressable25,
4045
4199
  {
4046
4200
  accessibilityRole: "button",
4047
4201
  accessibilityLabel: `Remove discount ${label}`,
4048
4202
  onPress: () => onRemove(discount.id),
4049
4203
  className: "min-h-11 flex-row items-center gap-1",
4050
4204
  children: [
4051
- /* @__PURE__ */ jsx88(DiscountBadge, { label, className: "self-center" }),
4052
- /* @__PURE__ */ jsx88(Text32, { className: "text-muted-foreground", children: "\u2715" })
4205
+ /* @__PURE__ */ jsx90(DiscountBadge, { label, className: "self-center" }),
4206
+ /* @__PURE__ */ jsx90(Text33, { className: "text-muted-foreground", children: "\u2715" })
4053
4207
  ]
4054
4208
  },
4055
4209
  discount.id
@@ -4058,10 +4212,10 @@ function DiscountChips({ discounts, currency, onRemove, prefix, amounts = [] })
4058
4212
  }
4059
4213
 
4060
4214
  // src/sale/price-form.tsx
4061
- import { useState as useState17 } from "react";
4062
- import { Pressable as Pressable24, Text as Text33, TextInput as TextInput10, View as View55 } from "react-native";
4215
+ import { useState as useState18 } from "react";
4216
+ import { Pressable as Pressable26, Text as Text34, TextInput as TextInput10, View as View57 } from "react-native";
4063
4217
  import { formatMoney as formatMoney11, minorUnitDigits as minorUnitDigits8, moneyFromDecimalString as moneyFromDecimalString3 } from "@tallyui/core";
4064
- import { jsx as jsx89, jsxs as jsxs48 } from "react/jsx-runtime";
4218
+ import { jsx as jsx91, jsxs as jsxs49 } from "react/jsx-runtime";
4065
4219
  function parsePrice(text, currency) {
4066
4220
  const raw = text.trim();
4067
4221
  const trimmed = raw.split(",").length === 2 ? raw.replace(",", ".") : raw;
@@ -4074,9 +4228,9 @@ function parsePrice(text, currency) {
4074
4228
  }
4075
4229
  var button2 = "rounded-md border border-border px-3 py-2 min-h-11 items-center justify-center";
4076
4230
  function PriceForm({ lineName, currency, currentMinor, onApply, onClose }) {
4077
- const [text, setText] = useState17("");
4078
- const [reason, setReason] = useState17("");
4079
- const [error, setError] = useState17(null);
4231
+ const [text, setText] = useState18("");
4232
+ const [reason, setReason] = useState18("");
4233
+ const [error, setError] = useState18(null);
4080
4234
  const title = `Price for ${lineName}`;
4081
4235
  function apply() {
4082
4236
  const parsed = parsePrice(text, currency);
@@ -4084,10 +4238,10 @@ function PriceForm({ lineName, currency, currentMinor, onApply, onClose }) {
4084
4238
  setError(refused);
4085
4239
  if (refused === null) onClose();
4086
4240
  }
4087
- return /* @__PURE__ */ jsxs48(View55, { testID: "price-form", role: "group", accessibilityLabel: title, className: "gap-2 px-3 py-2", children: [
4088
- /* @__PURE__ */ jsx89(Text33, { className: "font-semibold text-foreground", children: title }),
4089
- /* @__PURE__ */ jsx89(Text33, { className: "text-muted-foreground", children: formatMoney11({ amount: currentMinor, currency }) }),
4090
- /* @__PURE__ */ jsx89(
4241
+ return /* @__PURE__ */ jsxs49(View57, { testID: "price-form", role: "group", accessibilityLabel: title, className: "gap-2 px-3 py-2", children: [
4242
+ /* @__PURE__ */ jsx91(Text34, { className: "font-semibold text-foreground", children: title }),
4243
+ /* @__PURE__ */ jsx91(Text34, { className: "text-muted-foreground", children: formatMoney11({ amount: currentMinor, currency }) }),
4244
+ /* @__PURE__ */ jsx91(
4091
4245
  TextInput10,
4092
4246
  {
4093
4247
  testID: "price-input",
@@ -4100,7 +4254,7 @@ function PriceForm({ lineName, currency, currentMinor, onApply, onClose }) {
4100
4254
  className: "min-w-0 rounded-md border border-border bg-background px-3 py-2 text-foreground"
4101
4255
  }
4102
4256
  ),
4103
- /* @__PURE__ */ jsx89(
4257
+ /* @__PURE__ */ jsx91(
4104
4258
  TextInput10,
4105
4259
  {
4106
4260
  testID: "price-reason",
@@ -4111,25 +4265,121 @@ function PriceForm({ lineName, currency, currentMinor, onApply, onClose }) {
4111
4265
  className: "min-w-0 rounded-md border border-border bg-background px-3 py-2 text-foreground"
4112
4266
  }
4113
4267
  ),
4114
- error ? /* @__PURE__ */ jsx89(Text33, { testID: "price-error", accessibilityRole: "alert", className: "text-destructive", children: error }) : null,
4115
- /* @__PURE__ */ jsxs48(View55, { className: "flex-row gap-2", children: [
4116
- /* @__PURE__ */ jsx89(Pressable24, { testID: "price-apply", accessibilityRole: "button", onPress: apply, className: `${button2} bg-primary`, children: /* @__PURE__ */ jsx89(Text33, { className: "font-semibold text-primary-foreground", children: "Apply" }) }),
4117
- /* @__PURE__ */ jsx89(Pressable24, { testID: "price-cancel", accessibilityRole: "button", onPress: onClose, className: `${button2} bg-card`, children: /* @__PURE__ */ jsx89(Text33, { className: "text-foreground", children: "Cancel" }) })
4268
+ error ? /* @__PURE__ */ jsx91(Text34, { testID: "price-error", accessibilityRole: "alert", className: "text-destructive", children: error }) : null,
4269
+ /* @__PURE__ */ jsxs49(View57, { className: "flex-row gap-2", children: [
4270
+ /* @__PURE__ */ jsx91(Pressable26, { testID: "price-apply", accessibilityRole: "button", onPress: apply, className: `${button2} bg-primary`, children: /* @__PURE__ */ jsx91(Text34, { className: "font-semibold text-primary-foreground", children: "Apply" }) }),
4271
+ /* @__PURE__ */ jsx91(Pressable26, { testID: "price-cancel", accessibilityRole: "button", onPress: onClose, className: `${button2} bg-card`, children: /* @__PURE__ */ jsx91(Text34, { className: "text-foreground", children: "Cancel" }) })
4272
+ ] })
4273
+ ] });
4274
+ }
4275
+
4276
+ // src/sale/charge-form.tsx
4277
+ import { useState as useState19 } from "react";
4278
+ import { Pressable as Pressable27, Text as Text35, TextInput as TextInput11, View as View58 } from "react-native";
4279
+ import { Fragment as Fragment5, jsx as jsx92, jsxs as jsxs50 } from "react/jsx-runtime";
4280
+ var button3 = "rounded-md border border-border px-3 py-2 min-h-11 items-center justify-center";
4281
+ function ChargeForm({ currency, lineTax, taxClasses, shippingTaxFromStore, onApply, onClose }) {
4282
+ const [kind, setKind] = useState19("fee");
4283
+ const [name, setName] = useState19("");
4284
+ const [text, setText] = useState19("");
4285
+ const [noTax, setNoTax] = useState19(false);
4286
+ const [taxClass, setTaxClass] = useState19("");
4287
+ const [error, setError] = useState19(null);
4288
+ const storeShipping = kind === "shipping" && shippingTaxFromStore;
4289
+ function apply() {
4290
+ const parsed = parsePrice(text, currency);
4291
+ const refused = !name.trim() ? "Enter a name." : typeof parsed === "string" ? parsed : onApply({
4292
+ kind,
4293
+ name: name.trim(),
4294
+ amountMinor: parsed,
4295
+ taxStatus: !storeShipping && lineTax?.none && noTax ? "none" : void 0,
4296
+ taxClass: !storeShipping && lineTax?.classes && taxClasses?.length ? taxClass || void 0 : void 0
4297
+ });
4298
+ setError(refused);
4299
+ if (refused === null) onClose();
4300
+ }
4301
+ return /* @__PURE__ */ jsxs50(View58, { testID: "charge-form", role: "group", accessibilityLabel: "Add charge", className: "gap-2 px-3 py-2", children: [
4302
+ /* @__PURE__ */ jsx92(Text35, { className: "font-semibold text-foreground", children: "Add charge" }),
4303
+ /* @__PURE__ */ jsx92(View58, { className: "flex-row gap-2", children: ["fee", "shipping", "custom"].map((option) => /* @__PURE__ */ jsx92(
4304
+ Pressable27,
4305
+ {
4306
+ accessibilityRole: "button",
4307
+ accessibilityState: { selected: kind === option },
4308
+ "aria-selected": kind === option,
4309
+ onPress: () => setKind(option),
4310
+ className: `${button3} ${kind === option ? "bg-primary" : "bg-card"}`,
4311
+ children: /* @__PURE__ */ jsx92(Text35, { className: kind === option ? "text-primary-foreground" : "text-foreground", children: option === "fee" ? "Fee" : option === "shipping" ? "Shipping" : "Custom item" })
4312
+ },
4313
+ option
4314
+ )) }),
4315
+ /* @__PURE__ */ jsx92(
4316
+ TextInput11,
4317
+ {
4318
+ accessibilityLabel: "Name",
4319
+ placeholder: "Name",
4320
+ value: name,
4321
+ onChangeText: setName,
4322
+ className: "min-w-0 rounded-md border border-border bg-background px-3 py-2 text-foreground"
4323
+ }
4324
+ ),
4325
+ /* @__PURE__ */ jsx92(
4326
+ TextInput11,
4327
+ {
4328
+ accessibilityLabel: "Amount",
4329
+ value: text,
4330
+ onChangeText: setText,
4331
+ onSubmitEditing: apply,
4332
+ inputMode: "decimal",
4333
+ placeholder: currency,
4334
+ className: "min-w-0 rounded-md border border-border bg-background px-3 py-2 text-foreground"
4335
+ }
4336
+ ),
4337
+ storeShipping ? /* @__PURE__ */ jsx92(Text35, { className: "text-muted-foreground", children: "Shipping is taxed at the store's shipping tax class." }) : /* @__PURE__ */ jsxs50(Fragment5, { children: [
4338
+ lineTax?.none ? /* @__PURE__ */ jsx92(
4339
+ Pressable27,
4340
+ {
4341
+ accessibilityRole: "switch",
4342
+ accessibilityLabel: "No tax",
4343
+ accessibilityState: { checked: noTax },
4344
+ "aria-checked": noTax,
4345
+ onPress: () => setNoTax(!noTax),
4346
+ className: `${button3} ${noTax ? "bg-primary" : "bg-card"}`,
4347
+ children: /* @__PURE__ */ jsx92(Text35, { className: noTax ? "text-primary-foreground" : "text-foreground", children: "No tax" })
4348
+ }
4349
+ ) : null,
4350
+ lineTax?.classes && taxClasses?.length ? /* @__PURE__ */ jsx92(View58, { role: "group", accessibilityLabel: "Tax class", className: "flex-row flex-wrap gap-2", children: [{ id: "", label: "No class" }, ...taxClasses].map((option) => /* @__PURE__ */ jsx92(
4351
+ Pressable27,
4352
+ {
4353
+ accessibilityRole: "button",
4354
+ accessibilityState: { selected: taxClass === option.id },
4355
+ "aria-selected": taxClass === option.id,
4356
+ onPress: () => setTaxClass(option.id),
4357
+ className: `${button3} ${taxClass === option.id ? "bg-primary" : "bg-card"}`,
4358
+ children: /* @__PURE__ */ jsx92(Text35, { className: taxClass === option.id ? "text-primary-foreground" : "text-foreground", children: option.label })
4359
+ },
4360
+ option.id
4361
+ )) }) : null
4362
+ ] }),
4363
+ error ? /* @__PURE__ */ jsx92(Text35, { accessibilityRole: "alert", className: "text-destructive", children: error }) : null,
4364
+ /* @__PURE__ */ jsxs50(View58, { className: "flex-row gap-2", children: [
4365
+ /* @__PURE__ */ jsx92(Pressable27, { accessibilityRole: "button", onPress: apply, className: `${button3} bg-primary`, children: /* @__PURE__ */ jsx92(Text35, { className: "font-semibold text-primary-foreground", children: "Apply" }) }),
4366
+ /* @__PURE__ */ jsx92(Pressable27, { accessibilityRole: "button", onPress: onClose, className: `${button3} bg-card`, children: /* @__PURE__ */ jsx92(Text35, { className: "text-foreground", children: "Cancel" }) })
4118
4367
  ] })
4119
4368
  ] });
4120
4369
  }
4121
4370
 
4122
4371
  // src/sale/cart.tsx
4123
- import { Fragment as Fragment5, jsx as jsx90, jsxs as jsxs49 } from "react/jsx-runtime";
4124
- function Cart({ sale, taxLabel = (ratePpm) => `Tax ${ratePpm / 1e4}%`, canEditPrice = false, onPriceChange }) {
4372
+ import { Fragment as Fragment6, jsx as jsx93, jsxs as jsxs51 } from "react/jsx-runtime";
4373
+ function Cart({ sale, taxLabel = (ratePpm) => `Tax ${ratePpm / 1e4}%`, canEditPrice = false, onPriceChange, taxClasses }) {
4125
4374
  const { order } = sale;
4126
4375
  const money = (amount) => ({ amount, currency: order.currency });
4127
4376
  const { totals } = buildReceiptData(order, { storeName: "" });
4128
4377
  const taxRows = totals.taxLines.map((line) => ({ label: taxLabel(line.ratePpm), amount: money(line.amountMinor) }));
4129
4378
  const display = (lineId) => order.display.lines.find((line) => line.lineId === lineId);
4130
4379
  const orderAmounts = order.discounts.length === 1 ? [{ discountId: order.discounts[0].id, amountMinor: order.display.orderDiscountMinor }] : [];
4131
- const [form, setForm] = useState18(null);
4132
- const discountForm = (lineId, title) => form?.type === "discount" && form.lineId === lineId ? /* @__PURE__ */ jsx90(
4380
+ const [form, setForm] = useState20(null);
4381
+ const chargesOffered = (sale.capabilities?.orderCreate ?? 0) >= 5;
4382
+ const discountForm = (lineId, title) => form?.type === "discount" && form.lineId === lineId ? /* @__PURE__ */ jsx93(
4133
4383
  DiscountForm,
4134
4384
  {
4135
4385
  title,
@@ -4140,11 +4390,11 @@ function Cart({ sale, taxLabel = (ratePpm) => `Tax ${ratePpm / 1e4}%`, canEditPr
4140
4390
  lineId ?? "order"
4141
4391
  ) : null;
4142
4392
  const pay = `min-h-12 flex-1 justify-center rounded-md bg-primary px-4 py-3 ${!order.lineItems.length ? "opacity-50" : ""}`;
4143
- const renderItem = (line) => /* @__PURE__ */ jsxs49(Fragment5, { children: [
4144
- /* @__PURE__ */ jsx90(CartLineActions, { actions: [
4393
+ const renderItem = (line) => /* @__PURE__ */ jsxs51(Fragment6, { children: [
4394
+ /* @__PURE__ */ jsx93(CartLineActions, { actions: [
4145
4395
  { id: "discount", label: "Discount", color: "text-primary", onPress: () => setForm({ type: "discount", lineId: line.id }) },
4146
4396
  ...canEditPrice ? [{ id: "price", label: "Price", color: "text-primary", onPress: () => setForm({ type: "price", lineId: line.id }) }] : []
4147
- ], children: /* @__PURE__ */ jsx90(
4397
+ ], children: /* @__PURE__ */ jsx93(
4148
4398
  CartLine,
4149
4399
  {
4150
4400
  name: line.name,
@@ -4153,41 +4403,41 @@ function Cart({ sale, taxLabel = (ratePpm) => `Tax ${ratePpm / 1e4}%`, canEditPr
4153
4403
  lineTotal: money(display(line.id).amountMinor)
4154
4404
  }
4155
4405
  ) }),
4156
- /* @__PURE__ */ jsx90(DiscountChips, { discounts: line.discounts, amounts: display(line.id).discounts, currency: order.currency, onRemove: sale.removeDiscount }),
4157
- /* @__PURE__ */ jsxs49(View56, { className: "flex-row gap-4 px-3 py-2", children: [
4158
- /* @__PURE__ */ jsx90(
4159
- Pressable25,
4406
+ /* @__PURE__ */ jsx93(DiscountChips, { discounts: line.discounts, amounts: display(line.id).discounts, currency: order.currency, onRemove: sale.removeDiscount }),
4407
+ /* @__PURE__ */ jsxs51(View59, { className: "flex-row gap-4 px-3 py-2", children: [
4408
+ /* @__PURE__ */ jsx93(
4409
+ Pressable28,
4160
4410
  {
4161
4411
  accessibilityRole: "button",
4162
4412
  accessibilityLabel: `Decrease ${line.name}`,
4163
4413
  onPress: () => sale.setQuantity(line.id, line.quantity - 1),
4164
4414
  className: "rounded-md border border-border bg-card px-3 py-2 min-h-11 min-w-11 items-center justify-center",
4165
- children: /* @__PURE__ */ jsx90(Text34, { className: "text-center text-foreground", children: "\u2212" })
4415
+ children: /* @__PURE__ */ jsx93(Text36, { className: "text-center text-foreground", children: "\u2212" })
4166
4416
  }
4167
4417
  ),
4168
- /* @__PURE__ */ jsx90(
4169
- Pressable25,
4418
+ /* @__PURE__ */ jsx93(
4419
+ Pressable28,
4170
4420
  {
4171
4421
  accessibilityRole: "button",
4172
4422
  accessibilityLabel: `Increase ${line.name}`,
4173
4423
  onPress: () => sale.setQuantity(line.id, line.quantity + 1),
4174
4424
  className: "rounded-md border border-border bg-card px-3 py-2 min-h-11 min-w-11 items-center justify-center",
4175
- children: /* @__PURE__ */ jsx90(Text34, { className: "text-center text-foreground", children: "+" })
4425
+ children: /* @__PURE__ */ jsx93(Text36, { className: "text-center text-foreground", children: "+" })
4176
4426
  }
4177
4427
  ),
4178
- /* @__PURE__ */ jsx90(
4179
- Pressable25,
4428
+ /* @__PURE__ */ jsx93(
4429
+ Pressable28,
4180
4430
  {
4181
4431
  accessibilityRole: "button",
4182
4432
  accessibilityLabel: `Remove ${line.name}`,
4183
4433
  onPress: () => sale.remove(line.id),
4184
4434
  className: "rounded-md border border-border bg-card px-3 py-2 min-h-11 min-w-11 items-center justify-center",
4185
- children: /* @__PURE__ */ jsx90(Text34, { className: "text-center text-foreground", children: "Remove" })
4435
+ children: /* @__PURE__ */ jsx93(Text36, { className: "text-center text-foreground", children: "Remove" })
4186
4436
  }
4187
4437
  )
4188
4438
  ] }),
4189
4439
  discountForm(line.id, `Discount on ${line.name}`),
4190
- canEditPrice && form?.type === "price" && form.lineId === line.id ? /* @__PURE__ */ jsx90(
4440
+ canEditPrice && form?.type === "price" && form.lineId === line.id ? /* @__PURE__ */ jsx93(
4191
4441
  PriceForm,
4192
4442
  {
4193
4443
  lineName: line.name,
@@ -4204,36 +4454,76 @@ function Cart({ sale, taxLabel = (ratePpm) => `Tax ${ratePpm / 1e4}%`, canEditPr
4204
4454
  line.id
4205
4455
  ) : null
4206
4456
  ] });
4207
- return /* @__PURE__ */ jsx90(
4457
+ return /* @__PURE__ */ jsx93(
4208
4458
  CartPanel,
4209
4459
  {
4210
4460
  dataSet: { print: "hide" },
4211
4461
  items: order.lineItems,
4212
4462
  renderItem,
4213
- emptyState: /* @__PURE__ */ jsx90(Text34, { testID: "cart-empty", className: "px-3 py-2 text-muted-foreground", children: "Scan or tap a product to start a sale." }),
4214
- afterItems: order.lineItems.length ? /* @__PURE__ */ jsxs49(View56, { className: "gap-3 px-3 py-2", children: [
4215
- /* @__PURE__ */ jsx90(
4216
- DiscountChips,
4217
- {
4218
- discounts: order.discounts,
4219
- amounts: orderAmounts,
4220
- currency: order.currency,
4221
- onRemove: sale.removeDiscount,
4222
- prefix: "Order discount"
4223
- }
4224
- ),
4225
- form?.lineId === null ? discountForm(null, "Order discount") : /* @__PURE__ */ jsx90(
4226
- Pressable25,
4227
- {
4228
- accessibilityRole: "button",
4229
- onPress: () => setForm({ type: "discount", lineId: null }),
4230
- className: "self-start rounded-md border border-border bg-card px-4 py-2 min-h-11 justify-center",
4231
- children: /* @__PURE__ */ jsx90(Text34, { className: "text-foreground", children: "Order discount" })
4232
- }
4233
- )
4234
- ] }) : void 0,
4235
- footer: /* @__PURE__ */ jsxs49(View56, { testID: "cart-footer", className: "gap-3 pb-4", children: [
4236
- /* @__PURE__ */ jsx90(
4463
+ emptyState: /* @__PURE__ */ jsx93(Text36, { testID: "cart-empty", className: "px-3 py-2 text-muted-foreground", children: "Scan or tap a product to start a sale." }),
4464
+ afterItems: /* @__PURE__ */ jsxs51(Fragment6, { children: [
4465
+ ["fees", "shipping"].map((kind) => order[kind]?.map((charge, index) => /* @__PURE__ */ jsxs51(View59, { testID: `cart-${kind === "fees" ? "fee" : "shipping"}-${index}`, className: "flex-row items-center gap-3 px-3 py-2", children: [
4466
+ /* @__PURE__ */ jsx93(Text36, { className: "flex-1 text-foreground", children: charge.name }),
4467
+ /* @__PURE__ */ jsx93(Text36, { className: "text-foreground", children: formatMoney12(money(order.display[kind].find((row) => row.id === charge.id).amountMinor)) }),
4468
+ /* @__PURE__ */ jsx93(
4469
+ Pressable28,
4470
+ {
4471
+ accessibilityRole: "button",
4472
+ accessibilityLabel: `Remove ${charge.name}`,
4473
+ onPress: () => kind === "fees" ? sale.removeFee(charge.id) : sale.removeShipping(charge.id),
4474
+ className: "rounded-md border border-border bg-card px-3 py-2 min-h-11 items-center justify-center",
4475
+ children: /* @__PURE__ */ jsx93(Text36, { className: "text-foreground", children: "Remove" })
4476
+ }
4477
+ )
4478
+ ] }, charge.id))),
4479
+ order.lineItems.length || chargesOffered ? /* @__PURE__ */ jsxs51(View59, { className: "gap-3 px-3 py-2", children: [
4480
+ order.lineItems.length ? /* @__PURE__ */ jsxs51(Fragment6, { children: [
4481
+ /* @__PURE__ */ jsx93(
4482
+ DiscountChips,
4483
+ {
4484
+ discounts: order.discounts,
4485
+ amounts: orderAmounts,
4486
+ currency: order.currency,
4487
+ onRemove: sale.removeDiscount,
4488
+ prefix: "Order discount"
4489
+ }
4490
+ ),
4491
+ form?.type === "discount" && form.lineId === null ? discountForm(null, "Order discount") : /* @__PURE__ */ jsx93(
4492
+ Pressable28,
4493
+ {
4494
+ accessibilityRole: "button",
4495
+ onPress: () => setForm({ type: "discount", lineId: null }),
4496
+ className: "self-start rounded-md border border-border bg-card px-4 py-2 min-h-11 justify-center",
4497
+ children: /* @__PURE__ */ jsx93(Text36, { className: "text-foreground", children: "Order discount" })
4498
+ }
4499
+ )
4500
+ ] }) : null,
4501
+ chargesOffered ? form?.type === "charge" ? /* @__PURE__ */ jsx93(
4502
+ ChargeForm,
4503
+ {
4504
+ currency: order.currency,
4505
+ lineTax: sale.capabilities?.lineTax,
4506
+ taxClasses,
4507
+ shippingTaxFromStore: sale.capabilities?.taxRounding?.granularity === "woocommerce",
4508
+ onClose: () => setForm(null),
4509
+ onApply: ({ kind, name, amountMinor, taxStatus, taxClass }) => {
4510
+ const result = kind === "custom" ? sale.addCustomLine({ name, priceMinor: amountMinor, taxStatus, taxClass }) : kind === "fee" ? sale.addFee({ name, amountMinor, taxStatus, taxClass }) : sale.addShipping({ name, amountMinor, taxStatus, taxClass });
4511
+ return typeof result === "string" ? result : null;
4512
+ }
4513
+ }
4514
+ ) : /* @__PURE__ */ jsx93(
4515
+ Pressable28,
4516
+ {
4517
+ accessibilityRole: "button",
4518
+ onPress: () => setForm({ type: "charge" }),
4519
+ className: "self-start rounded-md border border-border bg-card px-4 py-2 min-h-11 justify-center",
4520
+ children: /* @__PURE__ */ jsx93(Text36, { className: "text-foreground", children: "Add charge" })
4521
+ }
4522
+ ) : null
4523
+ ] }) : null
4524
+ ] }),
4525
+ footer: /* @__PURE__ */ jsxs51(View59, { testID: "cart-footer", className: "gap-3 pb-4", children: [
4526
+ /* @__PURE__ */ jsx93(
4237
4527
  CartTotal,
4238
4528
  {
4239
4529
  subtotal: money(totals.subtotalMinor),
@@ -4243,10 +4533,10 @@ function Cart({ sale, taxLabel = (ratePpm) => `Tax ${ratePpm / 1e4}%`, canEditPr
4243
4533
  taxInclusive: totals.taxInclusive
4244
4534
  }
4245
4535
  ),
4246
- sale.error ? /* @__PURE__ */ jsx90(Text34, { accessibilityRole: "alert", className: "text-destructive", children: sale.error }) : null,
4247
- /* @__PURE__ */ jsxs49(View56, { className: "flex-row gap-3", children: [
4248
- /* @__PURE__ */ jsx90(Pressable25, { accessibilityRole: "button", disabled: !order.lineItems.length, onPress: () => sale.startTender("cash"), className: pay, children: /* @__PURE__ */ jsx90(Text34, { className: "text-center font-semibold text-primary-foreground", children: "Cash" }) }),
4249
- /* @__PURE__ */ jsx90(Pressable25, { accessibilityRole: "button", disabled: !order.lineItems.length, onPress: () => sale.startTender("external"), className: pay, children: /* @__PURE__ */ jsx90(Text34, { className: "text-center font-semibold text-primary-foreground", children: "Card terminal" }) })
4536
+ sale.error ? /* @__PURE__ */ jsx93(Text36, { accessibilityRole: "alert", className: "text-destructive", children: sale.error }) : null,
4537
+ /* @__PURE__ */ jsxs51(View59, { className: "flex-row gap-3", children: [
4538
+ /* @__PURE__ */ jsx93(Pressable28, { accessibilityRole: "button", disabled: !order.lineItems.length, onPress: () => sale.startTender("cash"), className: pay, children: /* @__PURE__ */ jsx93(Text36, { className: "text-center font-semibold text-primary-foreground", children: "Cash" }) }),
4539
+ /* @__PURE__ */ jsx93(Pressable28, { accessibilityRole: "button", disabled: !order.lineItems.length, onPress: () => sale.startTender("external"), className: pay, children: /* @__PURE__ */ jsx93(Text36, { className: "text-center font-semibold text-primary-foreground", children: "Card terminal" }) })
4250
4540
  ] })
4251
4541
  ] })
4252
4542
  }
@@ -4254,17 +4544,17 @@ function Cart({ sale, taxLabel = (ratePpm) => `Tax ${ratePpm / 1e4}%`, canEditPr
4254
4544
  }
4255
4545
 
4256
4546
  // src/sale/cart-bar.tsx
4257
- import { Pressable as Pressable26, Text as Text35 } from "react-native";
4258
- import { formatMoney as formatMoney12 } from "@tallyui/core";
4547
+ import { Pressable as Pressable29, Text as Text37 } from "react-native";
4548
+ import { formatMoney as formatMoney13 } from "@tallyui/core";
4259
4549
  import { buildReceiptData as buildReceiptData2 } from "@tallyui/pos";
4260
- import { jsx as jsx91, jsxs as jsxs50 } from "react/jsx-runtime";
4550
+ import { jsx as jsx94, jsxs as jsxs52 } from "react/jsx-runtime";
4261
4551
  function CartBar({ sale, onOpen }) {
4262
4552
  const { order } = sale;
4263
4553
  const count2 = order.lineItems.reduce((sum, line) => sum + line.quantity, 0);
4264
- const total = formatMoney12({ amount: buildReceiptData2(order, { storeName: "" }).totals.totalMinor, currency: order.currency });
4554
+ const total = formatMoney13({ amount: buildReceiptData2(order, { storeName: "" }).totals.totalMinor, currency: order.currency });
4265
4555
  const items = `${count2} ${count2 === 1 ? "item" : "items"}`;
4266
- return /* @__PURE__ */ jsxs50(
4267
- Pressable26,
4556
+ return /* @__PURE__ */ jsxs52(
4557
+ Pressable29,
4268
4558
  {
4269
4559
  accessibilityRole: "button",
4270
4560
  accessibilityLabel: count2 ? `Open cart, ${items}, ${total}` : "Cart is empty",
@@ -4272,8 +4562,8 @@ function CartBar({ sale, onOpen }) {
4272
4562
  onPress: onOpen,
4273
4563
  className: `min-h-14 mx-3 mb-3 flex-row items-center justify-between rounded-md bg-primary px-4 py-3 ${count2 ? "" : "opacity-50"}`,
4274
4564
  children: [
4275
- /* @__PURE__ */ jsx91(Text35, { className: "font-bold text-primary-foreground", children: count2 ? `Cart \xB7 ${items}` : "Cart is empty" }),
4276
- count2 ? /* @__PURE__ */ jsxs50(Text35, { className: "font-bold text-primary-foreground", children: [
4565
+ /* @__PURE__ */ jsx94(Text37, { className: "font-bold text-primary-foreground", children: count2 ? `Cart \xB7 ${items}` : "Cart is empty" }),
4566
+ count2 ? /* @__PURE__ */ jsxs52(Text37, { className: "font-bold text-primary-foreground", children: [
4277
4567
  total,
4278
4568
  " \u203A"
4279
4569
  ] }) : null
@@ -4283,17 +4573,17 @@ function CartBar({ sale, onOpen }) {
4283
4573
  }
4284
4574
 
4285
4575
  // src/sale/tender.tsx
4286
- import { Pressable as Pressable27, Text as Text36, TextInput as TextInput11, View as View57 } from "react-native";
4287
- import { formatMoney as formatMoney13 } from "@tallyui/core";
4288
- import { Fragment as Fragment6, jsx as jsx92, jsxs as jsxs51 } from "react/jsx-runtime";
4576
+ import { Pressable as Pressable30, Text as Text38, TextInput as TextInput12, View as View60 } from "react-native";
4577
+ import { formatMoney as formatMoney14 } from "@tallyui/core";
4578
+ import { Fragment as Fragment7, jsx as jsx95, jsxs as jsxs53 } from "react/jsx-runtime";
4289
4579
  var REFERENCE_MAX = 255;
4290
4580
  function Tender({ sale }) {
4291
4581
  const { order, stage } = sale;
4292
4582
  if (stage.kind !== "tender") return null;
4293
4583
  const money = (amount) => ({ amount, currency: order.currency });
4294
- return /* @__PURE__ */ jsxs51(View57, { dataSet: { print: "hide" }, className: "gap-4 p-4", children: [
4295
- stage.method === "cash" ? /* @__PURE__ */ jsxs51(Fragment6, { children: [
4296
- /* @__PURE__ */ jsx92(
4584
+ return /* @__PURE__ */ jsxs53(View60, { dataSet: { print: "hide" }, className: "gap-4 p-4", children: [
4585
+ stage.method === "cash" ? /* @__PURE__ */ jsxs53(Fragment7, { children: [
4586
+ /* @__PURE__ */ jsx95(
4297
4587
  CashTendered,
4298
4588
  {
4299
4589
  total: money(order.totalMinor),
@@ -4301,19 +4591,19 @@ function Tender({ sale }) {
4301
4591
  onChangeAmount: (amount) => sale.setTender({ method: "cash", amountMinor: amount.amount })
4302
4592
  }
4303
4593
  ),
4304
- /* @__PURE__ */ jsx92(ChangeDisplay, { change: money(order.changeDueMinor) }),
4305
- order.balanceDueMinor > 0 ? /* @__PURE__ */ jsxs51(Text36, { className: "text-foreground", children: [
4594
+ /* @__PURE__ */ jsx95(ChangeDisplay, { change: money(order.changeDueMinor) }),
4595
+ order.balanceDueMinor > 0 ? /* @__PURE__ */ jsxs53(Text38, { className: "text-foreground", children: [
4306
4596
  "Balance due: ",
4307
- formatMoney13(money(order.balanceDueMinor))
4597
+ formatMoney14(money(order.balanceDueMinor))
4308
4598
  ] }) : null,
4309
- /* @__PURE__ */ jsx92(Pressable27, { accessibilityRole: "button", disabled: order.balanceDueMinor > 0, onPress: sale.complete, className: `rounded-md bg-primary px-4 py-3 ${order.balanceDueMinor > 0 ? "opacity-50" : ""}`, children: /* @__PURE__ */ jsx92(Text36, { className: "text-center font-semibold text-primary-foreground", children: "Complete sale" }) })
4310
- ] }) : /* @__PURE__ */ jsxs51(Fragment6, { children: [
4311
- /* @__PURE__ */ jsxs51(Text36, { className: "text-foreground", children: [
4599
+ /* @__PURE__ */ jsx95(Pressable30, { accessibilityRole: "button", disabled: order.balanceDueMinor > 0, onPress: sale.complete, className: `rounded-md bg-primary px-4 py-3 ${order.balanceDueMinor > 0 ? "opacity-50" : ""}`, children: /* @__PURE__ */ jsx95(Text38, { className: "text-center font-semibold text-primary-foreground", children: "Complete sale" }) })
4600
+ ] }) : /* @__PURE__ */ jsxs53(Fragment7, { children: [
4601
+ /* @__PURE__ */ jsxs53(Text38, { className: "text-foreground", children: [
4312
4602
  "Card terminal: ",
4313
- formatMoney13(money(order.totalMinor))
4603
+ formatMoney14(money(order.totalMinor))
4314
4604
  ] }),
4315
- /* @__PURE__ */ jsx92(
4316
- TextInput11,
4605
+ /* @__PURE__ */ jsx95(
4606
+ TextInput12,
4317
4607
  {
4318
4608
  accessibilityLabel: "Terminal reference",
4319
4609
  placeholder: "Terminal reference",
@@ -4323,30 +4613,30 @@ function Tender({ sale }) {
4323
4613
  className: "rounded-md border border-border px-3 py-2 text-foreground"
4324
4614
  }
4325
4615
  ),
4326
- /* @__PURE__ */ jsx92(Pressable27, { accessibilityRole: "button", onPress: sale.complete, className: "rounded-md bg-primary px-4 py-3", children: /* @__PURE__ */ jsx92(Text36, { className: "text-center font-semibold text-primary-foreground", children: "Payment approved on terminal" }) })
4616
+ /* @__PURE__ */ jsx95(Pressable30, { accessibilityRole: "button", onPress: sale.complete, className: "rounded-md bg-primary px-4 py-3", children: /* @__PURE__ */ jsx95(Text38, { className: "text-center font-semibold text-primary-foreground", children: "Payment approved on terminal" }) })
4327
4617
  ] }),
4328
- sale.error ? /* @__PURE__ */ jsx92(Text36, { accessibilityRole: "alert", className: "text-destructive", children: sale.error }) : null,
4329
- sale.canContinue ? /* @__PURE__ */ jsxs51(Fragment6, { children: [
4330
- /* @__PURE__ */ jsx92(Text36, { className: "text-foreground", children: "This sale is stored and will be sent. Continue to the next sale." }),
4331
- /* @__PURE__ */ jsx92(Pressable27, { accessibilityRole: "button", onPress: () => sale.continueSale(), className: "rounded-md bg-primary px-4 py-3", children: /* @__PURE__ */ jsx92(Text36, { className: "text-center font-semibold text-primary-foreground", children: "Continue" }) })
4618
+ sale.error ? /* @__PURE__ */ jsx95(Text38, { accessibilityRole: "alert", className: "text-destructive", children: sale.error }) : null,
4619
+ sale.canContinue ? /* @__PURE__ */ jsxs53(Fragment7, { children: [
4620
+ /* @__PURE__ */ jsx95(Text38, { className: "text-foreground", children: "This sale is stored and will be sent. Continue to the next sale." }),
4621
+ /* @__PURE__ */ jsx95(Pressable30, { accessibilityRole: "button", onPress: () => sale.continueSale(), className: "rounded-md bg-primary px-4 py-3", children: /* @__PURE__ */ jsx95(Text38, { className: "text-center font-semibold text-primary-foreground", children: "Continue" }) })
4332
4622
  ] }) : null,
4333
- /* @__PURE__ */ jsx92(Pressable27, { accessibilityRole: "button", onPress: sale.cancelTender, className: "rounded-md border border-border bg-card px-4 py-3", children: /* @__PURE__ */ jsx92(Text36, { className: "text-center text-foreground", children: "Back" }) })
4623
+ /* @__PURE__ */ jsx95(Pressable30, { accessibilityRole: "button", onPress: sale.cancelTender, className: "rounded-md border border-border bg-card px-4 py-3", children: /* @__PURE__ */ jsx95(Text38, { className: "text-center text-foreground", children: "Back" }) })
4334
4624
  ] });
4335
4625
  }
4336
4626
 
4337
4627
  // src/sale/split-tender.tsx
4338
- import { useState as useState19 } from "react";
4339
- import { Pressable as Pressable28, Text as Text37, TextInput as TextInput12, View as View58 } from "react-native";
4340
- import { formatMoney as formatMoney14, minorUnitDigits as minorUnitDigits9 } from "@tallyui/core";
4341
- import { Fragment as Fragment7, jsx as jsx93, jsxs as jsxs52 } from "react/jsx-runtime";
4628
+ import { useState as useState21 } from "react";
4629
+ import { Pressable as Pressable31, Text as Text39, TextInput as TextInput13, View as View61 } from "react-native";
4630
+ import { formatMoney as formatMoney15, minorUnitDigits as minorUnitDigits9 } from "@tallyui/core";
4631
+ import { Fragment as Fragment8, jsx as jsx96, jsxs as jsxs54 } from "react/jsx-runtime";
4342
4632
  function SplitTender({ sale }) {
4343
4633
  const { order, stage } = sale;
4344
- const [method, setMethod] = useState19("cash");
4345
- const [amount, setAmount] = useState19(null);
4346
- const [reference, setReference] = useState19("");
4347
- const [error, setError] = useState19(null);
4634
+ const [method, setMethod] = useState21("cash");
4635
+ const [amount, setAmount] = useState21(null);
4636
+ const [reference, setReference] = useState21("");
4637
+ const [error, setError] = useState21(null);
4348
4638
  if (stage.kind !== "tender") return null;
4349
- const money = (value) => formatMoney14({ amount: value, currency: order.currency });
4639
+ const money = (value) => formatMoney15({ amount: value, currency: order.currency });
4350
4640
  const digits = minorUnitDigits9(order.currency);
4351
4641
  const amountText = amount ?? (order.balanceDueMinor / 10 ** digits).toFixed(digits);
4352
4642
  const incomplete = order.balanceDueMinor > 0 || order.payments.length === 0;
@@ -4369,59 +4659,59 @@ function SplitTender({ sale }) {
4369
4659
  setReference("");
4370
4660
  setAmount(null);
4371
4661
  }
4372
- return /* @__PURE__ */ jsxs52(View58, { dataSet: { print: "hide" }, className: "gap-4 p-4", children: [
4373
- /* @__PURE__ */ jsxs52(View58, { testID: "split-tender-summary", className: "gap-2", children: [
4374
- /* @__PURE__ */ jsxs52(Text37, { className: "text-foreground", children: [
4662
+ return /* @__PURE__ */ jsxs54(View61, { dataSet: { print: "hide" }, className: "gap-4 p-4", children: [
4663
+ /* @__PURE__ */ jsxs54(View61, { testID: "split-tender-summary", className: "gap-2", children: [
4664
+ /* @__PURE__ */ jsxs54(Text39, { className: "text-foreground", children: [
4375
4665
  "Total: ",
4376
4666
  money(order.totalMinor)
4377
4667
  ] }),
4378
- /* @__PURE__ */ jsxs52(Text37, { className: "text-foreground", children: [
4668
+ /* @__PURE__ */ jsxs54(Text39, { className: "text-foreground", children: [
4379
4669
  "Paid: ",
4380
4670
  money(order.paidMinor)
4381
4671
  ] }),
4382
- /* @__PURE__ */ jsxs52(Text37, { className: "text-foreground", children: [
4672
+ /* @__PURE__ */ jsxs54(Text39, { className: "text-foreground", children: [
4383
4673
  "Remaining: ",
4384
4674
  money(order.balanceDueMinor)
4385
4675
  ] }),
4386
- order.changeDueMinor > 0 ? /* @__PURE__ */ jsxs52(Text37, { className: "text-foreground", children: [
4676
+ order.changeDueMinor > 0 ? /* @__PURE__ */ jsxs54(Text39, { className: "text-foreground", children: [
4387
4677
  "Change: ",
4388
4678
  money(order.changeDueMinor)
4389
4679
  ] }) : null
4390
4680
  ] }),
4391
- /* @__PURE__ */ jsx93(View58, { testID: "split-tender-list", className: "gap-2", children: order.payments.map((payment) => /* @__PURE__ */ jsxs52(View58, { testID: `split-tender-row-${payment.id}`, className: "gap-2", children: [
4392
- /* @__PURE__ */ jsxs52(Text37, { className: "text-foreground", children: [
4681
+ /* @__PURE__ */ jsx96(View61, { testID: "split-tender-list", className: "gap-2", children: order.payments.map((payment) => /* @__PURE__ */ jsxs54(View61, { testID: `split-tender-row-${payment.id}`, className: "gap-2", children: [
4682
+ /* @__PURE__ */ jsxs54(Text39, { className: "text-foreground", children: [
4393
4683
  tenderLabel(payment.method),
4394
4684
  " ",
4395
4685
  money(payment.amountMinor)
4396
4686
  ] }),
4397
- payment.reference ? /* @__PURE__ */ jsx93(Text37, { className: "text-foreground", children: payment.reference }) : null,
4398
- /* @__PURE__ */ jsx93(
4399
- Pressable28,
4687
+ payment.reference ? /* @__PURE__ */ jsx96(Text39, { className: "text-foreground", children: payment.reference }) : null,
4688
+ /* @__PURE__ */ jsx96(
4689
+ Pressable31,
4400
4690
  {
4401
4691
  testID: `split-tender-remove-${payment.id}`,
4402
4692
  accessibilityRole: "button",
4403
4693
  accessibilityLabel: "Remove tender",
4404
4694
  onPress: () => sale.removeTender(payment.id),
4405
4695
  className: "rounded-md border border-border bg-card px-4 py-3",
4406
- children: /* @__PURE__ */ jsx93(Text37, { className: "text-center text-foreground", children: "Remove" })
4696
+ children: /* @__PURE__ */ jsx96(Text39, { className: "text-center text-foreground", children: "Remove" })
4407
4697
  }
4408
4698
  )
4409
4699
  ] }, payment.id)) }),
4410
- /* @__PURE__ */ jsxs52(View58, { testID: "split-tender-add", className: "gap-2", children: [
4411
- /* @__PURE__ */ jsx93(View58, { className: "flex-row gap-2", children: ["cash", "external"].map((value) => /* @__PURE__ */ jsx93(
4412
- Pressable28,
4700
+ /* @__PURE__ */ jsxs54(View61, { testID: "split-tender-add", className: "gap-2", children: [
4701
+ /* @__PURE__ */ jsx96(View61, { className: "flex-row gap-2", children: ["cash", "external"].map((value) => /* @__PURE__ */ jsx96(
4702
+ Pressable31,
4413
4703
  {
4414
4704
  testID: `split-tender-method-${value === "cash" ? "cash" : "card"}`,
4415
4705
  accessibilityRole: "button",
4416
4706
  accessibilityState: { selected: method === value },
4417
4707
  onPress: () => setMethod(value),
4418
4708
  className: `rounded-md border border-border px-4 py-3 ${method === value ? "bg-primary" : "bg-card"}`,
4419
- children: /* @__PURE__ */ jsx93(Text37, { className: `text-center ${method === value ? "text-primary-foreground" : "text-foreground"}`, children: tenderLabel(value) })
4709
+ children: /* @__PURE__ */ jsx96(Text39, { className: `text-center ${method === value ? "text-primary-foreground" : "text-foreground"}`, children: tenderLabel(value) })
4420
4710
  },
4421
4711
  value
4422
4712
  )) }),
4423
- /* @__PURE__ */ jsx93(
4424
- TextInput12,
4713
+ /* @__PURE__ */ jsx96(
4714
+ TextInput13,
4425
4715
  {
4426
4716
  testID: "split-tender-amount",
4427
4717
  accessibilityLabel: "Tender amount",
@@ -4431,8 +4721,8 @@ function SplitTender({ sale }) {
4431
4721
  className: "rounded-md border border-border px-3 py-2 text-foreground"
4432
4722
  }
4433
4723
  ),
4434
- method === "external" ? /* @__PURE__ */ jsx93(
4435
- TextInput12,
4724
+ method === "external" ? /* @__PURE__ */ jsx96(
4725
+ TextInput13,
4436
4726
  {
4437
4727
  testID: "split-tender-reference",
4438
4728
  accessibilityLabel: "Terminal reference",
@@ -4443,36 +4733,48 @@ function SplitTender({ sale }) {
4443
4733
  className: "rounded-md border border-border px-3 py-2 text-foreground"
4444
4734
  }
4445
4735
  ) : null,
4446
- error ? /* @__PURE__ */ jsx93(Text37, { testID: "split-tender-error", accessibilityRole: "alert", className: "text-destructive", children: error }) : null,
4447
- /* @__PURE__ */ jsx93(Pressable28, { testID: "split-tender-add-button", accessibilityRole: "button", onPress: add, className: "rounded-md bg-primary px-4 py-3", children: /* @__PURE__ */ jsx93(Text37, { className: "text-center font-semibold text-primary-foreground", children: "Add" }) })
4736
+ error ? /* @__PURE__ */ jsx96(Text39, { testID: "split-tender-error", accessibilityRole: "alert", className: "text-destructive", children: error }) : null,
4737
+ /* @__PURE__ */ jsx96(Pressable31, { testID: "split-tender-add-button", accessibilityRole: "button", onPress: add, className: "rounded-md bg-primary px-4 py-3", children: /* @__PURE__ */ jsx96(Text39, { className: "text-center font-semibold text-primary-foreground", children: "Add" }) })
4448
4738
  ] }),
4449
- /* @__PURE__ */ jsx93(
4450
- Pressable28,
4739
+ /* @__PURE__ */ jsx96(
4740
+ Pressable31,
4451
4741
  {
4452
4742
  testID: "split-tender-complete",
4453
4743
  accessibilityRole: "button",
4454
4744
  disabled: incomplete,
4455
4745
  onPress: sale.complete,
4456
4746
  className: `rounded-md bg-primary px-4 py-3 ${incomplete ? "opacity-50" : ""}`,
4457
- children: /* @__PURE__ */ jsx93(Text37, { className: "text-center font-semibold text-primary-foreground", children: "Complete sale" })
4747
+ children: /* @__PURE__ */ jsx96(Text39, { className: "text-center font-semibold text-primary-foreground", children: "Complete sale" })
4458
4748
  }
4459
4749
  ),
4460
- sale.error ? /* @__PURE__ */ jsx93(Text37, { accessibilityRole: "alert", className: "text-destructive", children: sale.error }) : null,
4461
- sale.canContinue ? /* @__PURE__ */ jsxs52(Fragment7, { children: [
4462
- /* @__PURE__ */ jsx93(Text37, { className: "text-foreground", children: "This sale is stored and will be sent. Continue to the next sale." }),
4463
- /* @__PURE__ */ jsx93(Pressable28, { accessibilityRole: "button", onPress: () => sale.continueSale(), className: "rounded-md bg-primary px-4 py-3", children: /* @__PURE__ */ jsx93(Text37, { className: "text-center font-semibold text-primary-foreground", children: "Continue" }) })
4750
+ sale.error ? /* @__PURE__ */ jsx96(Text39, { accessibilityRole: "alert", className: "text-destructive", children: sale.error }) : null,
4751
+ sale.canContinue ? /* @__PURE__ */ jsxs54(Fragment8, { children: [
4752
+ /* @__PURE__ */ jsx96(Text39, { className: "text-foreground", children: "This sale is stored and will be sent. Continue to the next sale." }),
4753
+ /* @__PURE__ */ jsx96(Pressable31, { accessibilityRole: "button", onPress: () => sale.continueSale(), className: "rounded-md bg-primary px-4 py-3", children: /* @__PURE__ */ jsx96(Text39, { className: "text-center font-semibold text-primary-foreground", children: "Continue" }) })
4464
4754
  ] }) : null,
4465
- /* @__PURE__ */ jsx93(Pressable28, { accessibilityRole: "button", onPress: sale.cancelTender, className: "rounded-md border border-border bg-card px-4 py-3", children: /* @__PURE__ */ jsx93(Text37, { className: "text-center text-foreground", children: "Back" }) })
4755
+ /* @__PURE__ */ jsx96(Pressable31, { accessibilityRole: "button", onPress: sale.cancelTender, className: "rounded-md border border-border bg-card px-4 py-3", children: /* @__PURE__ */ jsx96(Text39, { className: "text-center text-foreground", children: "Back" }) })
4466
4756
  ] });
4467
4757
  }
4468
4758
 
4469
4759
  // src/sale/catalogue.tsx
4470
- import { useEffect as useEffect5, useMemo as useMemo2, useState as useState20 } from "react";
4471
- import { Pressable as Pressable29, Text as Text38, View as View59 } from "react-native";
4472
- import { useStockOverlaid, useStockOverlayAsOf } from "@tallyui/core";
4473
- import { catalogueEntries, findEntryByCode, searchProducts, variantPriceLabel } from "@tallyui/pos";
4474
- import { jsx as jsx94, jsxs as jsxs53 } from "react/jsx-runtime";
4475
- var MIN_TILE_WIDTH = 160;
4760
+ import { useEffect as useEffect5, useMemo as useMemo3, useRef as useRef6, useState as useState22 } from "react";
4761
+ import { Pressable as Pressable32, Text as Text40, View as View62 } from "react-native";
4762
+ import { useStockOverlaid as useStockOverlaid2, useStockOverlayAsOf } from "@tallyui/core";
4763
+ import {
4764
+ catalogueEntries,
4765
+ findEntryByCode,
4766
+ searchProducts,
4767
+ variantPriceLabel,
4768
+ sortProducts as sortProducts2,
4769
+ productSortValue as productSortValue2,
4770
+ catalogueViewReducer,
4771
+ normalizeCatalogueViewState,
4772
+ resolveGridColumns,
4773
+ DEFAULT_CATALOGUE_VIEW_STATE,
4774
+ listCategories,
4775
+ inCategory
4776
+ } from "@tallyui/pos";
4777
+ import { jsx as jsx97, jsxs as jsxs55 } from "react/jsx-runtime";
4476
4778
  var STOCK_LABEL = {
4477
4779
  in_stock: "In Stock",
4478
4780
  out_of_stock: "Out of Stock",
@@ -4490,20 +4792,98 @@ function laterOf(a, b) {
4490
4792
  if (!b) return a;
4491
4793
  return a.getTime() >= b.getTime() ? a : b;
4492
4794
  }
4493
- function Catalogue({ products, traits, currency, onSelect, statusText, statusAccessory, lastSyncedAt, loading, pullError, lastStockCheckAt, hour12, minCodeLength }) {
4795
+ function Catalogue({
4796
+ products,
4797
+ traits,
4798
+ currency,
4799
+ onSelect,
4800
+ statusText,
4801
+ statusAccessory,
4802
+ lastSyncedAt,
4803
+ loading,
4804
+ pullError,
4805
+ lastStockCheckAt,
4806
+ hour12,
4807
+ minCodeLength,
4808
+ viewState,
4809
+ defaultViewState,
4810
+ loadViewState,
4811
+ saveViewState,
4812
+ onViewStateError,
4813
+ onStateChange,
4814
+ showViewToggle = false,
4815
+ items,
4816
+ onQueryChange,
4817
+ showCategoryNav = false,
4818
+ categories
4819
+ }) {
4820
+ const [initial] = useState22(() => {
4821
+ const state2 = normalizeCatalogueViewState({ ...DEFAULT_CATALOGUE_VIEW_STATE, ...defaultViewState });
4822
+ if (viewState !== void 0 || !loadViewState) return { state: state2 };
4823
+ try {
4824
+ const value = loadViewState();
4825
+ if (value instanceof Promise) return { state: state2, pending: value };
4826
+ const loaded = normalizeCatalogueViewState(value, state2);
4827
+ return { state: loaded, loaded };
4828
+ } catch (error) {
4829
+ return { state: state2, failed: true, error };
4830
+ }
4831
+ });
4832
+ const [internalState, setInternalState] = useState22(initial.state);
4833
+ const state = viewState ?? internalState;
4834
+ const cashierChanged = useRef6(false);
4835
+ useEffect5(() => {
4836
+ let mounted = true;
4837
+ if (initial.loaded) onStateChange?.(initial.loaded);
4838
+ if (initial.failed) onViewStateError?.(initial.error);
4839
+ initial.pending?.then((value) => {
4840
+ if (!mounted || cashierChanged.current) return;
4841
+ const loaded = normalizeCatalogueViewState(value, initial.state);
4842
+ setInternalState(loaded);
4843
+ onStateChange?.(loaded);
4844
+ }, (error) => {
4845
+ if (mounted) onViewStateError?.(error);
4846
+ });
4847
+ return () => {
4848
+ mounted = false;
4849
+ };
4850
+ }, [initial]);
4851
+ function changeState(action) {
4852
+ const next = catalogueViewReducer(state, action);
4853
+ if (next === state) return;
4854
+ cashierChanged.current = true;
4855
+ if (viewState !== void 0) {
4856
+ onStateChange?.(next);
4857
+ return;
4858
+ }
4859
+ setInternalState(next);
4860
+ onStateChange?.(next);
4861
+ try {
4862
+ Promise.resolve(saveViewState?.(next)).catch((error) => onViewStateError?.(error));
4863
+ } catch (error) {
4864
+ onViewStateError?.(error);
4865
+ }
4866
+ }
4494
4867
  const isLoading = loading ?? (lastSyncedAt === null && pullError == null);
4495
- const shown = useStockOverlaid(products);
4868
+ const shown = useStockOverlaid2(products);
4869
+ const categoryList = useMemo3(() => categories ?? listCategories(shown, traits), [categories, shown, traits]);
4870
+ const activeCategory = showCategoryNav ? categoryList.find((category) => category.id === state.categoryId) : void 0;
4871
+ const suppliedItems = useStockOverlaid2(items ?? products);
4496
4872
  const overlayAsOf = useStockOverlayAsOf();
4497
4873
  const parsedOverlayAsOf = overlayAsOf ? new Date(overlayAsOf) : void 0;
4498
4874
  const validOverlayAsOf = parsedOverlayAsOf && !isNaN(parsedOverlayAsOf.getTime()) ? parsedOverlayAsOf : void 0;
4499
4875
  const stockAsOf = laterOf(laterOf(lastStockCheckAt, validOverlayAsOf), lastSyncedAt);
4500
- const [query, setQuery] = useState20("");
4501
- const [chooserId, setChooserId] = useState20(null);
4502
- const [width, setWidth] = useState20(0);
4503
- const columns = Math.max(2, Math.min(6, Math.floor((width - 8) / (MIN_TILE_WIDTH + 8))));
4504
- const entries = useMemo2(() => catalogueEntries(shown, traits, { currency }), [shown, traits, currency]);
4505
- const results = useMemo2(() => searchProducts(shown, query, traits), [shown, query, traits]);
4506
- const choices = useMemo2(() => chooserId === null ? [] : entries.filter((entry) => traits.getId(entry.product) === chooserId), [entries, chooserId, traits]);
4876
+ const [query, setQuery] = useState22("");
4877
+ const [chooserId, setChooserId] = useState22(null);
4878
+ const [width, setWidth] = useState22(0);
4879
+ const columns = resolveGridColumns(state.gridColumns, width);
4880
+ const entries = useMemo3(() => catalogueEntries(shown, traits, { currency }), [shown, traits, currency]);
4881
+ const results = useMemo3(() => {
4882
+ if (items !== void 0) return suppliedItems;
4883
+ const filtered = searchProducts(activeCategory ? shown.filter((doc) => inCategory(doc, activeCategory.id, traits)) : shown, query, traits);
4884
+ return state.sort ? sortProducts2(filtered, state.sort, (doc, field) => productSortValue2(doc, field, traits, { currency })) : filtered;
4885
+ }, [items, suppliedItems, shown, query, traits, state.sort, currency, showCategoryNav, activeCategory]);
4886
+ const choices = useMemo3(() => chooserId === null ? [] : entries.filter((entry) => traits.getId(entry.product) === chooserId), [entries, chooserId, traits]);
4507
4887
  useEffect5(() => {
4508
4888
  if (chooserId !== null && choices.length === 0) setChooserId(null);
4509
4889
  }, [chooserId, choices]);
@@ -4511,13 +4891,22 @@ function Catalogue({ products, traits, currency, onSelect, statusText, statusAcc
4511
4891
  onSelect(entry);
4512
4892
  setChooserId(null);
4513
4893
  }
4514
- return /* @__PURE__ */ jsxs53(View59, { className: "flex-1", onLayout: (event) => setWidth(event.nativeEvent.layout.width), children: [
4515
- /* @__PURE__ */ jsxs53(View59, { className: "gap-2 border-b border-border bg-card px-4 pb-3 pt-3", children: [
4516
- /* @__PURE__ */ jsx94(
4894
+ function selectProduct(product) {
4895
+ const variants = entries.filter((entry) => traits.getId(entry.product) === traits.getId(product));
4896
+ if (variants.length === 1) select(variants[0]);
4897
+ else setChooserId(traits.getId(product));
4898
+ }
4899
+ const emptyState = /* @__PURE__ */ jsx97(Text40, { className: "mt-10 text-center text-sm text-muted-foreground", children: query.trim() ? `No products match "${query.trim()}".` : activeCategory ? `No products in ${activeCategory.name}.` : isLoading ? "Loading products\u2026" : "No products yet." });
4900
+ return /* @__PURE__ */ jsxs55(View62, { className: "flex-1", onLayout: (event) => setWidth(event.nativeEvent.layout.width), children: [
4901
+ /* @__PURE__ */ jsxs55(View62, { className: "gap-2 border-b border-border bg-card px-4 pb-3 pt-3", children: [
4902
+ /* @__PURE__ */ jsx97(
4517
4903
  SearchInput,
4518
4904
  {
4519
4905
  value: query,
4520
- onChangeText: setQuery,
4906
+ onChangeText: (text) => {
4907
+ setQuery(text);
4908
+ onQueryChange?.(text);
4909
+ },
4521
4910
  placeholder: "Search or scan barcode / SKU",
4522
4911
  autoFocus: true,
4523
4912
  onSubmitEditing: () => {
@@ -4530,25 +4919,34 @@ function Catalogue({ products, traits, currency, onSelect, statusText, statusAcc
4530
4919
  }
4531
4920
  }
4532
4921
  ),
4533
- statusText || statusAccessory ? /* @__PURE__ */ jsxs53(View59, { testID: "catalogue-status-row", className: "flex-row items-center gap-2", children: [
4534
- statusText ? /* @__PURE__ */ jsxs53(Text38, { className: "flex-1 text-xs text-muted-foreground", numberOfLines: statusAccessory ? 1 : void 0, children: [
4922
+ statusText || statusAccessory || showViewToggle ? /* @__PURE__ */ jsxs55(View62, { testID: "catalogue-status-row", className: "flex-row items-center gap-2", children: [
4923
+ statusText ? /* @__PURE__ */ jsxs55(Text40, { className: "flex-1 text-xs text-muted-foreground", numberOfLines: statusAccessory ? 1 : void 0, children: [
4535
4924
  statusText,
4536
4925
  query.trim() ? ` \xB7 ${results.length.toLocaleString()} matching` : ""
4537
4926
  ] }) : null,
4538
- statusAccessory
4927
+ statusAccessory,
4928
+ showViewToggle ? /* @__PURE__ */ jsx97(ViewToggle, { value: state.view, onChange: (view) => changeState({ type: "setView", view }) }) : null
4539
4929
  ] }) : null,
4540
- choices.length > 0 ? /* @__PURE__ */ jsxs53(View59, { accessibilityLabel: "Choose variant", className: "gap-2", children: [
4541
- choices.map((entry) => /* @__PURE__ */ jsxs53(
4542
- Pressable29,
4930
+ showCategoryNav ? /* @__PURE__ */ jsx97(
4931
+ CategoryNav,
4932
+ {
4933
+ categories: [{ id: "", name: "All products" }, ...categoryList],
4934
+ selectedId: activeCategory?.id ?? "",
4935
+ onSelect: (id) => changeState({ type: "setCategory", categoryId: id === "" ? null : id })
4936
+ }
4937
+ ) : null,
4938
+ choices.length > 0 ? /* @__PURE__ */ jsxs55(View62, { accessibilityLabel: "Choose variant", className: "gap-2", children: [
4939
+ choices.map((entry) => /* @__PURE__ */ jsxs55(
4940
+ Pressable32,
4543
4941
  {
4544
4942
  accessibilityRole: "button",
4545
4943
  onPress: () => select(entry),
4546
4944
  className: "gap-1 rounded-md border border-border p-3",
4547
4945
  children: [
4548
- /* @__PURE__ */ jsx94(Text38, { className: "font-semibold text-foreground", children: entry.variant.title }),
4549
- /* @__PURE__ */ jsx94(Text38, { className: "text-muted-foreground", children: entry.variant.sku }),
4550
- /* @__PURE__ */ jsx94(Text38, { className: "text-foreground", children: variantPriceLabel(entry.variant, currency) }),
4551
- /* @__PURE__ */ jsxs53(Text38, { className: "text-muted-foreground", children: [
4946
+ /* @__PURE__ */ jsx97(Text40, { className: "font-semibold text-foreground", children: entry.variant.title }),
4947
+ /* @__PURE__ */ jsx97(Text40, { className: "text-muted-foreground", children: entry.variant.sku }),
4948
+ /* @__PURE__ */ jsx97(Text40, { className: "text-foreground", children: variantPriceLabel(entry.variant, currency) }),
4949
+ /* @__PURE__ */ jsxs55(Text40, { className: "text-muted-foreground", children: [
4552
4950
  STOCK_LABEL[entry.variant.stock.status],
4553
4951
  " \xB7 ",
4554
4952
  stockAsOf ? `as of ${formatStockSyncTime(stockAsOf, void 0, hour12)}` : "not yet synced"
@@ -4557,10 +4955,20 @@ function Catalogue({ products, traits, currency, onSelect, statusText, statusAcc
4557
4955
  },
4558
4956
  entry.variant.id
4559
4957
  )),
4560
- /* @__PURE__ */ jsx94(Pressable29, { accessibilityRole: "button", onPress: () => setChooserId(null), className: "rounded-md border border-border bg-card px-4 py-3", children: /* @__PURE__ */ jsx94(Text38, { className: "text-center text-foreground", children: "Cancel" }) })
4958
+ /* @__PURE__ */ jsx97(Pressable32, { accessibilityRole: "button", onPress: () => setChooserId(null), className: "rounded-md border border-border bg-card px-4 py-3", children: /* @__PURE__ */ jsx97(Text40, { className: "text-center text-foreground", children: "Cancel" }) })
4561
4959
  ] }) : null
4562
4960
  ] }),
4563
- /* @__PURE__ */ jsx94(
4961
+ state.view === "table" ? /* @__PURE__ */ jsx97(
4962
+ ProductTable,
4963
+ {
4964
+ items: results,
4965
+ sort: state.sort,
4966
+ onSortChange: (sort) => changeState({ type: "setSort", sort }),
4967
+ sortItems: false,
4968
+ onSelect: selectProduct,
4969
+ emptyState
4970
+ }
4971
+ ) : /* @__PURE__ */ jsx97(
4564
4972
  ProductGrid,
4565
4973
  {
4566
4974
  items: results,
@@ -4569,18 +4977,14 @@ function Catalogue({ products, traits, currency, onSelect, statusText, statusAcc
4569
4977
  // TallyUI's ProductCard has no children slot, so the tile is composed directly here
4570
4978
  // (same structure/classes as ProductCard) to add the stock badge as a fourth child,
4571
4979
  // inside the card and centred with the rest, rather than adding a slot to ProductCard (out of scope for TV6b).
4572
- /* @__PURE__ */ jsx94(Pressable29, { accessibilityRole: "button", testID: `product-tile-${traits.getName(product)}`, onPress: () => {
4573
- const variants = entries.filter((entry) => entry.product === product);
4574
- if (variants.length === 1) select(variants[0]);
4575
- else setChooserId(traits.getId(product));
4576
- }, children: /* @__PURE__ */ jsxs53(VStack, { space: "sm", className: "items-center rounded-lg border border-border bg-card p-3", children: [
4577
- /* @__PURE__ */ jsx94(ProductImage, { doc: product, size: 80, className: "rounded-md" }),
4578
- /* @__PURE__ */ jsx94(ProductTitle, { doc: product, className: "text-sm", numberOfLines: 2 }),
4579
- /* @__PURE__ */ jsx94(ProductPrice, { doc: product }),
4580
- /* @__PURE__ */ jsx94(ProductStockBadge, { doc: product, showAsOf: false, className: "self-center" })
4980
+ /* @__PURE__ */ jsx97(Pressable32, { accessibilityRole: "button", testID: `product-tile-${traits.getName(product)}`, onPress: () => selectProduct(product), children: /* @__PURE__ */ jsxs55(VStack, { space: "sm", className: "items-center rounded-lg border border-border bg-card p-3", children: [
4981
+ /* @__PURE__ */ jsx97(ProductImage, { doc: product, size: 80, className: "rounded-md" }),
4982
+ /* @__PURE__ */ jsx97(ProductTitle, { doc: product, className: "text-sm", numberOfLines: 2 }),
4983
+ /* @__PURE__ */ jsx97(ProductPrice, { doc: product }),
4984
+ /* @__PURE__ */ jsx97(ProductStockBadge, { doc: product, showAsOf: false, className: "self-center" })
4581
4985
  ] }) })
4582
4986
  ),
4583
- emptyState: /* @__PURE__ */ jsx94(Text38, { className: "mt-10 text-center text-sm text-muted-foreground", children: query.trim() ? `No products match "${query.trim()}".` : isLoading ? "Loading products\u2026" : "No products yet." })
4987
+ emptyState
4584
4988
  }
4585
4989
  )
4586
4990
  ] });
@@ -4588,8 +4992,8 @@ function Catalogue({ products, traits, currency, onSelect, statusText, statusAcc
4588
4992
 
4589
4993
  // src/sale/receipt.tsx
4590
4994
  import { useEffect as useEffect6 } from "react";
4591
- import { Pressable as Pressable30, Text as Text39, View as View60 } from "react-native";
4592
- import { formatMoney as formatMoney15 } from "@tallyui/core";
4995
+ import { Pressable as Pressable33, Text as Text41, View as View63 } from "react-native";
4996
+ import { formatMoney as formatMoney16 } from "@tallyui/core";
4593
4997
  import { buildReceiptData as buildReceiptData3 } from "@tallyui/pos";
4594
4998
 
4595
4999
  // src/sale/print-style.ts
@@ -4609,7 +5013,7 @@ function orderReference(order) {
4609
5013
  }
4610
5014
 
4611
5015
  // src/sale/receipt.tsx
4612
- import { Fragment as Fragment8, jsx as jsx95, jsxs as jsxs54 } from "react/jsx-runtime";
5016
+ import { Fragment as Fragment9, jsx as jsx98, jsxs as jsxs56 } from "react/jsx-runtime";
4613
5017
  var defaultFormatDate = (iso) => new Intl.DateTimeFormat(void 0, { dateStyle: "medium", timeStyle: "short" }).format(new Date(iso));
4614
5018
  function Receipt({
4615
5019
  order,
@@ -4629,37 +5033,39 @@ function Receipt({
4629
5033
  cashier,
4630
5034
  register: registerId
4631
5035
  });
4632
- const money = (amount) => formatMoney15({ amount, currency: receipt.currency }) ?? "";
4633
- const row = (label, amount, bold = false, key) => /* @__PURE__ */ jsxs54(View60, { accessibilityLabel: `${label}: ${amount}`, className: "flex-row justify-between gap-4", children: [
4634
- /* @__PURE__ */ jsx95(Text39, { className: `text-foreground ${bold ? "font-semibold" : ""}`, children: label }),
4635
- /* @__PURE__ */ jsx95(Text39, { className: `text-right text-foreground ${bold ? "font-semibold" : ""}`, children: amount })
5036
+ const money = (amount) => formatMoney16({ amount, currency: receipt.currency }) ?? "";
5037
+ const row = (label, amount, bold = false, key) => /* @__PURE__ */ jsxs56(View63, { accessibilityLabel: `${label}: ${amount}`, className: "flex-row justify-between gap-4", children: [
5038
+ /* @__PURE__ */ jsx98(Text41, { className: `text-foreground ${bold ? "font-semibold" : ""}`, children: label }),
5039
+ /* @__PURE__ */ jsx98(Text41, { className: `text-right text-foreground ${bold ? "font-semibold" : ""}`, children: amount })
4636
5040
  ] }, key);
4637
5041
  const { totals } = receipt;
4638
5042
  const lineDiscountMinor = totals.discountMinor - receipt.orderDiscountMinor;
4639
5043
  const taxRows = totals.taxLines.map((line, index) => row(`${totals.taxInclusive ? "incl. " : ""}${taxLabel(line.ratePpm)}`, money(line.amountMinor), false, index));
4640
- return /* @__PURE__ */ jsxs54(Fragment8, { children: [
4641
- topInset > 0 ? /* @__PURE__ */ jsx95(View60, { dataSet: { print: "hide" }, style: { height: topInset, flexShrink: 0 } }) : null,
4642
- /* @__PURE__ */ jsxs54(View60, { className: "w-full max-w-md self-center gap-3 p-4 bg-card", children: [
4643
- /* @__PURE__ */ jsx95(Text39, { className: "text-lg font-semibold text-foreground", children: receipt.header.storeName }),
4644
- receipt.header.storeAddress ? /* @__PURE__ */ jsx95(Text39, { className: "text-muted-foreground", children: receipt.header.storeAddress }) : null,
4645
- /* @__PURE__ */ jsx95(Text39, { testID: "receipt-order", className: "text-foreground", children: posOrder ? `Order ${orderReference(posOrder)}` : `Order ${receipt.header.orderNumber.slice(-8)} (draft)` }),
4646
- /* @__PURE__ */ jsx95(Text39, { className: "text-muted-foreground", children: formatDate(posOrder?.createdAt ?? receipt.header.date) }),
4647
- /* @__PURE__ */ jsxs54(Text39, { className: "text-muted-foreground", children: [
5044
+ return /* @__PURE__ */ jsxs56(Fragment9, { children: [
5045
+ topInset > 0 ? /* @__PURE__ */ jsx98(View63, { dataSet: { print: "hide" }, style: { height: topInset, flexShrink: 0 } }) : null,
5046
+ /* @__PURE__ */ jsxs56(View63, { className: "w-full max-w-md self-center gap-3 p-4 bg-card", children: [
5047
+ /* @__PURE__ */ jsx98(Text41, { className: "text-lg font-semibold text-foreground", children: receipt.header.storeName }),
5048
+ receipt.header.storeAddress ? /* @__PURE__ */ jsx98(Text41, { className: "text-muted-foreground", children: receipt.header.storeAddress }) : null,
5049
+ /* @__PURE__ */ jsx98(Text41, { testID: "receipt-order", className: "text-foreground", children: posOrder ? `Order ${orderReference(posOrder)}` : `Order ${receipt.header.orderNumber.slice(-8)} (draft)` }),
5050
+ /* @__PURE__ */ jsx98(Text41, { className: "text-muted-foreground", children: formatDate(posOrder?.createdAt ?? receipt.header.date) }),
5051
+ /* @__PURE__ */ jsxs56(Text41, { className: "text-muted-foreground", children: [
4648
5052
  "Cashier: ",
4649
5053
  receipt.header.cashier
4650
5054
  ] }),
4651
- receipt.header.customer && /* @__PURE__ */ jsxs54(Text39, { className: "text-muted-foreground", children: [
5055
+ receipt.header.customer && /* @__PURE__ */ jsxs56(Text41, { className: "text-muted-foreground", children: [
4652
5056
  "Customer: ",
4653
5057
  receipt.header.customer
4654
5058
  ] }),
4655
- receipt.lineItems.map((line, index) => /* @__PURE__ */ jsxs54(View60, { children: [
4656
- /* @__PURE__ */ jsx95(Text39, { className: "text-foreground", children: line.name }),
5059
+ receipt.lineItems.map((line, index) => /* @__PURE__ */ jsxs56(View63, { children: [
5060
+ /* @__PURE__ */ jsx98(Text41, { className: "text-foreground", children: line.name }),
4657
5061
  row(`${line.quantity} \xD7 ${money(line.unitPriceMinor)}`, money(line.displayAmountMinor)),
4658
- line.displayDiscounts.map((discount, i) => /* @__PURE__ */ jsx95(View60, { className: "pl-4", children: row(`${discountLabel(
5062
+ line.displayDiscounts.map((discount, i) => /* @__PURE__ */ jsx98(View63, { className: "pl-4", children: row(`${discountLabel(
4659
5063
  order.lineItems[index].discounts[i],
4660
5064
  receipt.currency
4661
5065
  )} off`, `\u2212${money(discount.amountMinor)}`) }, i))
4662
5066
  ] }, index)),
5067
+ receipt.fees.map((charge, index) => row(charge.name, money(charge.amountMinor), false, index)),
5068
+ receipt.shipping.map((charge, index) => row(charge.name, money(charge.amountMinor), false, index)),
4663
5069
  row("Subtotal", money(totals.subtotalMinor)),
4664
5070
  lineDiscountMinor > 0 ? row("Line discounts", `\u2212${money(lineDiscountMinor)}`) : null,
4665
5071
  receipt.orderDiscountMinor > 0 ? row("Order discount", `\u2212${money(receipt.orderDiscountMinor)}`) : null,
@@ -4672,19 +5078,19 @@ function Receipt({
4672
5078
  index
4673
5079
  )),
4674
5080
  row("Change", money(receipt.changeDueMinor)),
4675
- /* @__PURE__ */ jsxs54(View60, { dataSet: { print: "hide" }, className: "flex-row gap-4", children: [
4676
- /* @__PURE__ */ jsx95(Pressable30, { accessibilityRole: "button", onPress: () => {
5081
+ /* @__PURE__ */ jsxs56(View63, { dataSet: { print: "hide" }, className: "flex-row gap-4", children: [
5082
+ /* @__PURE__ */ jsx98(Pressable33, { accessibilityRole: "button", onPress: () => {
4677
5083
  if (typeof window !== "undefined" && typeof window.print === "function") window.print();
4678
- }, className: "rounded-md border border-border bg-card px-4 py-3", children: /* @__PURE__ */ jsx95(Text39, { className: "text-center text-foreground", children: "Print receipt" }) }),
4679
- /* @__PURE__ */ jsx95(Pressable30, { accessibilityRole: "button", onPress: newSale, className: "rounded-md bg-primary px-4 py-3", children: /* @__PURE__ */ jsx95(Text39, { className: "text-center font-semibold text-primary-foreground", children: "New sale" }) })
5084
+ }, className: "rounded-md border border-border bg-card px-4 py-3", children: /* @__PURE__ */ jsx98(Text41, { className: "text-center text-foreground", children: "Print receipt" }) }),
5085
+ /* @__PURE__ */ jsx98(Pressable33, { accessibilityRole: "button", onPress: newSale, className: "rounded-md bg-primary px-4 py-3", children: /* @__PURE__ */ jsx98(Text41, { className: "text-center font-semibold text-primary-foreground", children: "New sale" }) })
4680
5086
  ] })
4681
5087
  ] })
4682
5088
  ] });
4683
5089
  }
4684
5090
 
4685
5091
  // src/sale/sync-status.tsx
4686
- import { useEffect as useEffect7, useRef as useRef6, useState as useState21 } from "react";
4687
- import { AccessibilityInfo as AccessibilityInfo2, Platform as Platform3, Text as Text40, View as View61 } from "react-native";
5092
+ import { useEffect as useEffect7, useRef as useRef7, useState as useState23 } from "react";
5093
+ import { AccessibilityInfo as AccessibilityInfo2, Platform as Platform3, Text as Text42, View as View64 } from "react-native";
4688
5094
 
4689
5095
  // src/sale/since-text.ts
4690
5096
  function sinceText(clock) {
@@ -4693,7 +5099,7 @@ function sinceText(clock) {
4693
5099
  }
4694
5100
 
4695
5101
  // src/sale/sync-status.tsx
4696
- import { Fragment as Fragment9, jsx as jsx96, jsxs as jsxs55 } from "react/jsx-runtime";
5102
+ import { Fragment as Fragment10, jsx as jsx99, jsxs as jsxs57 } from "react/jsx-runtime";
4697
5103
  var PULL_NOTICE_TEXT = {
4698
5104
  unauthorized: {
4699
5105
  line: () => "Products aren't updating: this till needs to sign in to the online store again.",
@@ -4735,7 +5141,7 @@ var SALES_REFUSED = "The online store refused the last send. This till will try
4735
5141
  var TILL_UPDATES_REFUSED = "The online store refused the last send. This till will try again with the next till update, or when the app is reopened.";
4736
5142
  var count = (n, noun) => `${n} ${noun}${n === 1 ? "" : "s"}`;
4737
5143
  function useAnnounceOnIos(...texts) {
4738
- const announced = useRef6(texts);
5144
+ const announced = useRef7(texts);
4739
5145
  useEffect7(() => {
4740
5146
  const changed = texts.filter((text, index) => text && text !== announced.current[index]);
4741
5147
  announced.current = texts;
@@ -4745,7 +5151,7 @@ function useAnnounceOnIos(...texts) {
4745
5151
  function SyncStatus({ state, registerState, pluginName = "the POS plugin", pullNotice }) {
4746
5152
  const updates = registerState?.pending ?? 0;
4747
5153
  const outbox = state.pending === 0 && registerState?.pending ? registerState : state;
4748
- const [now, setNow] = useState21(Date.now);
5154
+ const [now, setNow] = useState23(Date.now);
4749
5155
  useEffect7(() => {
4750
5156
  setNow(Date.now());
4751
5157
  if (!outbox.nextAttemptAt) return;
@@ -4769,24 +5175,24 @@ function SyncStatus({ state, registerState, pluginName = "the POS plugin", pullN
4769
5175
  const notice = pullNotice && text && { line: text.line(pluginName), detail: text.detail(pullNotice, pluginName) };
4770
5176
  useAnnounceOnIos(notice?.line, spoken);
4771
5177
  const oneDetail = pullNotice?.code === "missing_plugin" && !!backendMissing;
4772
- return /* @__PURE__ */ jsxs55(View61, { children: [
4773
- notice ? /* @__PURE__ */ jsxs55(Fragment9, { children: [
4774
- /* @__PURE__ */ jsx96(Text40, { accessibilityLiveRegion: "polite", className: "px-4 py-2 text-xs text-muted-foreground", children: notice.line }),
4775
- oneDetail ? null : /* @__PURE__ */ jsx96(Text40, { className: "px-4 pb-2 text-xs text-muted-foreground", children: notice.detail })
5178
+ return /* @__PURE__ */ jsxs57(View64, { children: [
5179
+ notice ? /* @__PURE__ */ jsxs57(Fragment10, { children: [
5180
+ /* @__PURE__ */ jsx99(Text42, { accessibilityLiveRegion: "polite", className: "px-4 py-2 text-xs text-muted-foreground", children: notice.line }),
5181
+ oneDetail ? null : /* @__PURE__ */ jsx99(Text42, { className: "px-4 pb-2 text-xs text-muted-foreground", children: notice.detail })
4776
5182
  ] }) : null,
4777
- /* @__PURE__ */ jsx96(Text40, { accessibilityLabel: spoken, accessibilityLiveRegion: "polite", className: "px-4 py-2 text-xs text-muted-foreground", children: spoken }),
4778
- doing ? /* @__PURE__ */ jsx96(Text40, { className: "px-4 pb-2 text-xs text-muted-foreground", children: doing }) : null,
4779
- refused ? /* @__PURE__ */ jsx96(Text40, { className: "px-4 pb-2 text-xs text-muted-foreground", children: REFUSED_DETAIL }) : null,
4780
- oneDetail && notice ? /* @__PURE__ */ jsx96(Text40, { className: "px-4 pb-2 text-xs text-muted-foreground", children: notice.detail }) : backendMissing ? /* @__PURE__ */ jsx96(Text40, { className: "px-4 pb-2 text-xs text-muted-foreground", children: BACKEND_MISSING_DETAIL.replace("{pluginName}", () => pluginName).replace("{lastTime}", () => upToDate ? " the last time it checked" : "") }) : null
5183
+ /* @__PURE__ */ jsx99(Text42, { accessibilityLabel: spoken, accessibilityLiveRegion: "polite", className: "px-4 py-2 text-xs text-muted-foreground", children: spoken }),
5184
+ doing ? /* @__PURE__ */ jsx99(Text42, { className: "px-4 pb-2 text-xs text-muted-foreground", children: doing }) : null,
5185
+ refused ? /* @__PURE__ */ jsx99(Text42, { className: "px-4 pb-2 text-xs text-muted-foreground", children: REFUSED_DETAIL }) : null,
5186
+ oneDetail && notice ? /* @__PURE__ */ jsx99(Text42, { className: "px-4 pb-2 text-xs text-muted-foreground", children: notice.detail }) : backendMissing ? /* @__PURE__ */ jsx99(Text42, { className: "px-4 pb-2 text-xs text-muted-foreground", children: BACKEND_MISSING_DETAIL.replace("{pluginName}", () => pluginName).replace("{lastTime}", () => upToDate ? " the last time it checked" : "") }) : null
4781
5187
  ] });
4782
5188
  }
4783
5189
 
4784
5190
  // src/sale/orders-list.tsx
4785
- import { useEffect as useEffect8, useRef as useRef7, useState as useState22 } from "react";
4786
- import { Pressable as Pressable31, ScrollView as ScrollView13, Text as Text41, View as View62 } from "react-native";
4787
- import { formatMoney as formatMoney16, knownWarnings } from "@tallyui/core";
5191
+ import { useEffect as useEffect8, useRef as useRef8, useState as useState24 } from "react";
5192
+ import { Pressable as Pressable34, ScrollView as ScrollView13, Text as Text43, View as View65 } from "react-native";
5193
+ import { formatMoney as formatMoney17, knownWarnings } from "@tallyui/core";
4788
5194
  import { needsAttention } from "@tallyui/pos";
4789
- import { jsx as jsx97, jsxs as jsxs56 } from "react/jsx-runtime";
5195
+ import { jsx as jsx100, jsxs as jsxs58 } from "react/jsx-runtime";
4790
5196
  var STATUS_LABEL = { pending: "Waiting to sync", applied: "Synced", rejected: "Not accepted" };
4791
5197
  var FIGURE_LABELS = /* @__PURE__ */ new Map([["subtotalMinor", "Subtotal"], ["taxMinor", "Tax"], ["discountMinor", "Discount"]]);
4792
5198
  var REFUSAL_SENTENCES = /* @__PURE__ */ new Map([
@@ -4809,27 +5215,27 @@ function defaultFormatDate2(iso) {
4809
5215
  return Number.isNaN(date.getTime()) ? iso : new Intl.DateTimeFormat(void 0, { dateStyle: "medium", timeStyle: "short" }).format(date);
4810
5216
  }
4811
5217
  function OrdersList({ orders, onRetry, formatDate = defaultFormatDate2, footer, stuck }) {
4812
- const retrying = useRef7(/* @__PURE__ */ new Set());
4813
- const [retryingIds, setRetryingIds] = useState22(/* @__PURE__ */ new Set());
4814
- const [expanded, setExpanded] = useState22(/* @__PURE__ */ new Set());
5218
+ const retrying = useRef8(/* @__PURE__ */ new Set());
5219
+ const [retryingIds, setRetryingIds] = useState24(/* @__PURE__ */ new Set());
5220
+ const [expanded, setExpanded] = useState24(/* @__PURE__ */ new Set());
4815
5221
  useEffect8(() => {
4816
5222
  for (const id of retrying.current) {
4817
5223
  if (!orders.some((order) => order.id === id && order.syncStatus === "rejected")) retrying.current.delete(id);
4818
5224
  }
4819
5225
  setRetryingIds(new Set(retrying.current));
4820
5226
  }, [orders]);
4821
- return /* @__PURE__ */ jsxs56(ScrollView13, { className: "flex-1 bg-background p-4", children: [
4822
- [{ title: "Needs attention", orders: needsAttention(orders, { stuckCommandIds: stuck?.commandIds }) }, { title: "Recent", orders }].filter((section) => section.title === "Recent" || section.orders.length > 0).map((section) => /* @__PURE__ */ jsxs56(View62, { className: "mb-6 gap-3", children: [
4823
- /* @__PURE__ */ jsx97(Text41, { accessibilityRole: "header", className: "text-xl font-semibold text-foreground", children: section.title }),
4824
- section.title === "Recent" && orders.length === 0 ? /* @__PURE__ */ jsx97(Text41, { testID: "orders-empty", className: "text-muted-foreground", children: "No sales yet. Completed sales appear here." }) : null,
5227
+ return /* @__PURE__ */ jsxs58(ScrollView13, { className: "flex-1 bg-background p-4", children: [
5228
+ [{ title: "Needs attention", orders: needsAttention(orders, { stuckCommandIds: stuck?.commandIds }) }, { title: "Recent", orders }].filter((section) => section.title === "Recent" || section.orders.length > 0).map((section) => /* @__PURE__ */ jsxs58(View65, { className: "mb-6 gap-3", children: [
5229
+ /* @__PURE__ */ jsx100(Text43, { accessibilityRole: "header", className: "text-xl font-semibold text-foreground", children: section.title }),
5230
+ section.title === "Recent" && orders.length === 0 ? /* @__PURE__ */ jsx100(Text43, { testID: "orders-empty", className: "text-muted-foreground", children: "No sales yet. Completed sales appear here." }) : null,
4825
5231
  section.orders.map((order) => {
4826
5232
  const count2 = order.lines.reduce((sum, line) => sum + line.quantity, 0);
4827
5233
  const key = `${section.title}:${order.id}`;
4828
5234
  const isExpanded = expanded.has(key);
4829
5235
  const stuckEntry = order.syncStatus === "pending" ? stuck?.orders.find((entry) => entry.commandId === order.commandId) : void 0;
4830
- return /* @__PURE__ */ jsxs56(View62, { className: "gap-1 rounded-md border border-border bg-card p-3", children: [
4831
- /* @__PURE__ */ jsxs56(
4832
- Pressable31,
5236
+ return /* @__PURE__ */ jsxs58(View65, { className: "gap-1 rounded-md border border-border bg-card p-3", children: [
5237
+ /* @__PURE__ */ jsxs58(
5238
+ Pressable34,
4833
5239
  {
4834
5240
  accessibilityRole: "button",
4835
5241
  "aria-expanded": isExpanded,
@@ -4843,26 +5249,26 @@ function OrdersList({ orders, onRetry, formatDate = defaultFormatDate2, footer,
4843
5249
  return next;
4844
5250
  }),
4845
5251
  children: [
4846
- /* @__PURE__ */ jsx97(Text41, { className: "text-foreground", children: `Order ${orderReference(order)} \xB7 ${count2} ${count2 === 1 ? "item" : "items"}` }),
4847
- /* @__PURE__ */ jsxs56(Text41, { className: "text-muted-foreground", children: [
5252
+ /* @__PURE__ */ jsx100(Text43, { className: "text-foreground", children: `Order ${orderReference(order)} \xB7 ${count2} ${count2 === 1 ? "item" : "items"}` }),
5253
+ /* @__PURE__ */ jsxs58(Text43, { className: "text-muted-foreground", children: [
4848
5254
  formatDate(order.createdAt),
4849
5255
  " \xB7 ",
4850
- formatMoney16({ amount: order.totalMinor, currency: order.currency }),
5256
+ formatMoney17({ amount: order.totalMinor, currency: order.currency }),
4851
5257
  " \xB7 ",
4852
5258
  STATUS_LABEL[order.syncStatus]
4853
5259
  ] })
4854
5260
  ]
4855
5261
  }
4856
5262
  ),
4857
- isExpanded ? /* @__PURE__ */ jsxs56(View62, { testID: `order-detail-${order.id}`, className: "mt-1 gap-1 border-t border-border pt-2", children: [
4858
- order.lines.map((line) => /* @__PURE__ */ jsx97(Text41, { className: "text-foreground", children: `${line.quantity} \xD7 ${line.name}` }, line.id)),
4859
- order.payments.map((payment) => /* @__PURE__ */ jsx97(Text41, { className: "text-muted-foreground", children: `${payment.method === "cash" ? "Cash" : "Card terminal"} ${formatMoney16({ amount: payment.amountMinor, currency: order.currency })}${payment.reference ? ` \xB7 ${payment.reference}` : ""}` }, payment.id))
5263
+ isExpanded ? /* @__PURE__ */ jsxs58(View65, { testID: `order-detail-${order.id}`, className: "mt-1 gap-1 border-t border-border pt-2", children: [
5264
+ order.lines.map((line) => /* @__PURE__ */ jsx100(Text43, { className: "text-foreground", children: `${line.quantity} \xD7 ${line.name}` }, line.id)),
5265
+ order.payments.map((payment) => /* @__PURE__ */ jsx100(Text43, { className: "text-muted-foreground", children: `${payment.method === "cash" ? "Cash" : "Card terminal"} ${formatMoney17({ amount: payment.amountMinor, currency: order.currency })}${payment.reference ? ` \xB7 ${payment.reference}` : ""}` }, payment.id))
4860
5266
  ] }) : null,
4861
- stuckEntry ? /* @__PURE__ */ jsx97(Text41, { className: "text-destructive", children: `Hasn't reached the online store since ${sinceText(stuckEntry)}.` }) : null,
4862
- order.syncStatus === "rejected" ? /* @__PURE__ */ jsx97(Text41, { className: "text-destructive", children: refusalSentence(order.error?.code) }) : null,
4863
- order.lateSessionId !== void 0 ? /* @__PURE__ */ jsx97(Text41, { className: "text-foreground", children: "Taken after the register closed. It is not in that register's closure." }) : null,
4864
- order.localWarnings?.map((warning, index) => /* @__PURE__ */ jsx97(Text41, { className: "text-foreground", children: warning.code === "customer_omitted" ? `The customer's ${warning.field} couldn't be sent to the store, so the order isn't linked to them.` : "The terminal's payment reference couldn't be kept; the payment is recorded without it." }, index)),
4865
- section.title === "Needs attention" && order.syncStatus === "rejected" && order.error?.code !== "idempotency_mismatch" ? /* @__PURE__ */ jsx97(Pressable31, { accessibilityRole: "button", disabled: retryingIds.has(order.id), onPress: async () => {
5267
+ stuckEntry ? /* @__PURE__ */ jsx100(Text43, { className: "text-destructive", children: `Hasn't reached the online store since ${sinceText(stuckEntry)}.` }) : null,
5268
+ order.syncStatus === "rejected" ? /* @__PURE__ */ jsx100(Text43, { className: "text-destructive", children: refusalSentence(order.error?.code) }) : null,
5269
+ order.lateSessionId !== void 0 ? /* @__PURE__ */ jsx100(Text43, { className: "text-foreground", children: "Taken after the register closed. It is not in that register's closure." }) : null,
5270
+ order.localWarnings?.map((warning, index) => /* @__PURE__ */ jsx100(Text43, { className: "text-foreground", children: warning.code === "customer_omitted" ? `The customer's ${warning.field} couldn't be sent to the store, so the order isn't linked to them.` : "The terminal's payment reference couldn't be kept; the payment is recorded without it." }, index)),
5271
+ section.title === "Needs attention" && order.syncStatus === "rejected" && order.error?.code !== "idempotency_mismatch" ? /* @__PURE__ */ jsx100(Pressable34, { accessibilityRole: "button", disabled: retryingIds.has(order.id), onPress: async () => {
4866
5272
  if (retrying.current.has(order.id)) return;
4867
5273
  retrying.current.add(order.id);
4868
5274
  setRetryingIds(new Set(retrying.current));
@@ -4870,8 +5276,8 @@ function OrdersList({ orders, onRetry, formatDate = defaultFormatDate2, footer,
4870
5276
  retrying.current.delete(order.id);
4871
5277
  setRetryingIds(new Set(retrying.current));
4872
5278
  }
4873
- }, className: "rounded-md bg-primary px-4 py-2", children: /* @__PURE__ */ jsx97(Text41, { className: "text-center font-semibold text-primary-foreground", children: "Retry" }) }) : null,
4874
- knownWarnings(order.warnings).map((warning, index) => /* @__PURE__ */ jsx97(View62, { className: "border-l-4 border-warning pl-2", children: /* @__PURE__ */ jsx97(Text41, { className: "text-foreground", children: warning.code === "insufficient_stock" ? `Stock short by ${warning.quantity} for ${order.lines.find((line) => line.variantId === warning.variantId)?.name}` : warning.code === "tax_rate_mismatch" ? `Tax at ${(warning.ratePpm / 1e4).toLocaleString(void 0, { maximumFractionDigits: 4 })}%: store ${formatMoney16({ amount: warning.serverMinor, currency: order.currency })} vs POS ${formatMoney16({ amount: warning.expectedMinor, currency: order.currency })}` : warning.code === "customer_ignored" ? `The online store didn't recognise the customer on this sale, so it was saved as a guest sale. Customer id: ${warning.customerId}.` : warning.code === "figures_mismatch" ? `The online store worked out different figures for this sale. ${warning.fields.map(({ field, tillMinor, serverMinor }) => `${FIGURE_LABELS.get(field) ?? field}: till ${formatMoney16({ amount: tillMinor, currency: order.currency })}, store ${formatMoney16({ amount: serverMinor, currency: order.currency })}.`).join(" ")}` : warning.bridgeMinor !== void 0 ? `Store calculated ${formatMoney16({ amount: warning.serverMinor, currency: order.currency })}; a rounding line of ${warning.bridgeMinor > 0 ? "+" : ""}${formatMoney16({ amount: warning.bridgeMinor, currency: order.currency })} brought it to ${formatMoney16({ amount: warning.expectedMinor, currency: order.currency })}` : `Store total ${formatMoney16({ amount: warning.serverMinor, currency: order.currency })} vs POS ${formatMoney16({ amount: warning.expectedMinor, currency: order.currency })}` }) }, index))
5279
+ }, className: "rounded-md bg-primary px-4 py-2", children: /* @__PURE__ */ jsx100(Text43, { className: "text-center font-semibold text-primary-foreground", children: "Retry" }) }) : null,
5280
+ knownWarnings(order.warnings).map((warning, index) => /* @__PURE__ */ jsx100(View65, { className: "border-l-4 border-warning pl-2", children: /* @__PURE__ */ jsx100(Text43, { className: "text-foreground", children: warning.code === "insufficient_stock" ? `Stock short by ${warning.quantity} for ${order.lines.find((line) => line.variantId === warning.variantId)?.name}` : warning.code === "tax_rate_mismatch" ? `Tax at ${(warning.ratePpm / 1e4).toLocaleString(void 0, { maximumFractionDigits: 4 })}%: store ${formatMoney17({ amount: warning.serverMinor, currency: order.currency })} vs POS ${formatMoney17({ amount: warning.expectedMinor, currency: order.currency })}` : warning.code === "customer_ignored" ? `The online store didn't recognise the customer on this sale, so it was saved as a guest sale. Customer id: ${warning.customerId}.` : warning.code === "figures_mismatch" ? `The online store worked out different figures for this sale. ${warning.fields.map(({ field, tillMinor, serverMinor }) => `${FIGURE_LABELS.get(field) ?? field}: till ${formatMoney17({ amount: tillMinor, currency: order.currency })}, store ${formatMoney17({ amount: serverMinor, currency: order.currency })}.`).join(" ")}` : warning.bridgeMinor !== void 0 ? `Store calculated ${formatMoney17({ amount: warning.serverMinor, currency: order.currency })}; a rounding line of ${warning.bridgeMinor > 0 ? "+" : ""}${formatMoney17({ amount: warning.bridgeMinor, currency: order.currency })} brought it to ${formatMoney17({ amount: warning.expectedMinor, currency: order.currency })}` : `Store total ${formatMoney17({ amount: warning.serverMinor, currency: order.currency })} vs POS ${formatMoney17({ amount: warning.expectedMinor, currency: order.currency })}` }) }, index))
4875
5281
  ] }, order.id);
4876
5282
  })
4877
5283
  ] }, section.title)),
@@ -4880,15 +5286,15 @@ function OrdersList({ orders, onRetry, formatDate = defaultFormatDate2, footer,
4880
5286
  }
4881
5287
 
4882
5288
  // src/sale/parked-sales.tsx
4883
- import { useState as useState23 } from "react";
4884
- import { ScrollView as ScrollView14, useWindowDimensions as useWindowDimensions3, View as View63 } from "react-native";
4885
- import { formatMoney as formatMoney17 } from "@tallyui/core";
4886
- import { Fragment as Fragment10, jsx as jsx98, jsxs as jsxs57 } from "react/jsx-runtime";
5289
+ import { useState as useState25 } from "react";
5290
+ import { ScrollView as ScrollView14, useWindowDimensions as useWindowDimensions3, View as View66 } from "react-native";
5291
+ import { formatMoney as formatMoney18 } from "@tallyui/core";
5292
+ import { Fragment as Fragment11, jsx as jsx101, jsxs as jsxs59 } from "react/jsx-runtime";
4887
5293
  function ParkedSales({ sale, parked, onDiscard, onPark, onResume, currency, open, onOpenChange, hour12 }) {
4888
5294
  const { height: windowHeight } = useWindowDimensions3();
4889
5295
  const maxHeight = Math.max(280, windowHeight - 64);
4890
- const [confirming, setConfirming] = useState23(null);
4891
- const [error, setError] = useState23("");
5296
+ const [confirming, setConfirming] = useState25(null);
5297
+ const [error, setError] = useState25("");
4892
5298
  const attempt = async (action) => {
4893
5299
  setError("");
4894
5300
  try {
@@ -4897,28 +5303,28 @@ function ParkedSales({ sale, parked, onDiscard, onPark, onResume, currency, open
4897
5303
  setError(String(e));
4898
5304
  }
4899
5305
  };
4900
- return /* @__PURE__ */ jsx98(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs57(DialogContent, { testID: "parked-sales", className: "flex-col overflow-hidden", style: { maxHeight }, children: [
4901
- /* @__PURE__ */ jsxs57(View63, { className: "flex-row items-center justify-between gap-2", children: [
4902
- /* @__PURE__ */ jsx98(DialogTitle, { children: "Parked sales" }),
4903
- /* @__PURE__ */ jsx98(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx98(IconButton, { variant: "ghost", size: "sm", testID: "parked-sales-dismiss", accessibilityLabel: "Close panel", children: /* @__PURE__ */ jsx98(XIcon, { size: 16 }) }) })
5306
+ return /* @__PURE__ */ jsx101(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs59(DialogContent, { testID: "parked-sales", className: "flex-col overflow-hidden", style: { maxHeight }, children: [
5307
+ /* @__PURE__ */ jsxs59(View66, { className: "flex-row items-center justify-between gap-2", children: [
5308
+ /* @__PURE__ */ jsx101(DialogTitle, { children: "Parked sales" }),
5309
+ /* @__PURE__ */ jsx101(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx101(IconButton, { variant: "ghost", size: "sm", testID: "parked-sales-dismiss", accessibilityLabel: "Close panel", children: /* @__PURE__ */ jsx101(XIcon, { size: 16 }) }) })
4904
5310
  ] }),
4905
- /* @__PURE__ */ jsxs57(ScrollView14, { className: "flex-1", contentContainerClassName: "gap-3", children: [
4906
- /* @__PURE__ */ jsx98(
5311
+ /* @__PURE__ */ jsxs59(ScrollView14, { className: "flex-1", contentContainerClassName: "gap-3", children: [
5312
+ /* @__PURE__ */ jsx101(
4907
5313
  Button,
4908
5314
  {
4909
5315
  testID: "parked-sales-park",
4910
5316
  accessibilityLabel: "Park this sale",
4911
5317
  disabled: sale.order.lineItems.length === 0,
4912
5318
  onPress: () => attempt(async () => setError(await (onPark ?? sale.park)() ?? "")),
4913
- children: /* @__PURE__ */ jsx98(Text, { children: "Park this sale" })
5319
+ children: /* @__PURE__ */ jsx101(Text, { children: "Park this sale" })
4914
5320
  }
4915
5321
  ),
4916
- !!error && /* @__PURE__ */ jsx98(Text, { testID: "parked-sales-error", className: "text-destructive", children: error }),
4917
- parked.length === 0 && /* @__PURE__ */ jsx98(Text, { testID: "parked-sales-empty", children: "No parked sales." }),
4918
- parked.map((row) => /* @__PURE__ */ jsx98(View63, { testID: `parked-row-${row.id}`, className: "gap-2 rounded-md border border-border p-3", children: confirming === row.id ? /* @__PURE__ */ jsxs57(Fragment10, { children: [
4919
- /* @__PURE__ */ jsx98(Text, { children: "Discard this parked sale?" }),
4920
- /* @__PURE__ */ jsxs57(View63, { className: "flex-row gap-2", children: [
4921
- /* @__PURE__ */ jsx98(
5322
+ !!error && /* @__PURE__ */ jsx101(Text, { testID: "parked-sales-error", className: "text-destructive", children: error }),
5323
+ parked.length === 0 && /* @__PURE__ */ jsx101(Text, { testID: "parked-sales-empty", children: "No parked sales." }),
5324
+ parked.map((row) => /* @__PURE__ */ jsx101(View66, { testID: `parked-row-${row.id}`, className: "gap-2 rounded-md border border-border p-3", children: confirming === row.id ? /* @__PURE__ */ jsxs59(Fragment11, { children: [
5325
+ /* @__PURE__ */ jsx101(Text, { children: "Discard this parked sale?" }),
5326
+ /* @__PURE__ */ jsxs59(View66, { className: "flex-row gap-2", children: [
5327
+ /* @__PURE__ */ jsx101(
4922
5328
  Button,
4923
5329
  {
4924
5330
  testID: `parked-discard-confirm-${row.id}`,
@@ -4927,22 +5333,22 @@ function ParkedSales({ sale, parked, onDiscard, onPark, onResume, currency, open
4927
5333
  await onDiscard(row.id);
4928
5334
  setConfirming(null);
4929
5335
  }),
4930
- children: /* @__PURE__ */ jsx98(Text, { children: "Discard" })
5336
+ children: /* @__PURE__ */ jsx101(Text, { children: "Discard" })
4931
5337
  }
4932
5338
  ),
4933
- /* @__PURE__ */ jsx98(Button, { testID: `parked-discard-cancel-${row.id}`, variant: "outline", onPress: () => setConfirming(null), children: /* @__PURE__ */ jsx98(Text, { children: "Cancel" }) })
5339
+ /* @__PURE__ */ jsx101(Button, { testID: `parked-discard-cancel-${row.id}`, variant: "outline", onPress: () => setConfirming(null), children: /* @__PURE__ */ jsx101(Text, { children: "Cancel" }) })
4934
5340
  ] })
4935
- ] }) : /* @__PURE__ */ jsxs57(Fragment10, { children: [
4936
- /* @__PURE__ */ jsx98(Text, { children: formatStockSyncTime(new Date(row.parkedAt), void 0, hour12) }),
4937
- /* @__PURE__ */ jsxs57(Text, { children: [
5341
+ ] }) : /* @__PURE__ */ jsxs59(Fragment11, { children: [
5342
+ /* @__PURE__ */ jsx101(Text, { children: formatStockSyncTime(new Date(row.parkedAt), void 0, hour12) }),
5343
+ /* @__PURE__ */ jsxs59(Text, { children: [
4938
5344
  row.itemCount,
4939
5345
  " ",
4940
5346
  row.itemCount === 1 ? "item" : "items"
4941
5347
  ] }),
4942
- /* @__PURE__ */ jsx98(Text, { children: formatMoney17({ amount: row.totalMinor, currency }) }),
4943
- !!row.customerName && /* @__PURE__ */ jsx98(Text, { children: row.customerName }),
4944
- /* @__PURE__ */ jsxs57(View63, { className: "flex-row gap-2", children: [
4945
- /* @__PURE__ */ jsx98(
5348
+ /* @__PURE__ */ jsx101(Text, { children: formatMoney18({ amount: row.totalMinor, currency }) }),
5349
+ !!row.customerName && /* @__PURE__ */ jsx101(Text, { children: row.customerName }),
5350
+ /* @__PURE__ */ jsxs59(View66, { className: "flex-row gap-2", children: [
5351
+ /* @__PURE__ */ jsx101(
4946
5352
  Button,
4947
5353
  {
4948
5354
  testID: `parked-resume-${row.id}`,
@@ -4952,17 +5358,17 @@ function ParkedSales({ sale, parked, onDiscard, onPark, onResume, currency, open
4952
5358
  if (refusal === null) onOpenChange(false);
4953
5359
  else setError(refusal);
4954
5360
  }),
4955
- children: /* @__PURE__ */ jsx98(Text, { children: "Resume" })
5361
+ children: /* @__PURE__ */ jsx101(Text, { children: "Resume" })
4956
5362
  }
4957
5363
  ),
4958
- /* @__PURE__ */ jsx98(
5364
+ /* @__PURE__ */ jsx101(
4959
5365
  Button,
4960
5366
  {
4961
5367
  testID: `parked-discard-${row.id}`,
4962
5368
  accessibilityLabel: "Discard parked sale",
4963
5369
  variant: "outline",
4964
5370
  onPress: () => setConfirming(row.id),
4965
- children: /* @__PURE__ */ jsx98(Text, { children: "Discard" })
5371
+ children: /* @__PURE__ */ jsx101(Text, { children: "Discard" })
4966
5372
  }
4967
5373
  )
4968
5374
  ] })
@@ -4972,10 +5378,10 @@ function ParkedSales({ sale, parked, onDiscard, onPark, onResume, currency, open
4972
5378
  }
4973
5379
 
4974
5380
  // src/layout/pos-layout.tsx
4975
- import { useState as useState24 } from "react";
4976
- import { Pressable as Pressable32, Text as Text42, View as View64, useWindowDimensions as useWindowDimensions4 } from "react-native";
4977
- import { cn as cn80 } from "@tallyui/theme";
4978
- import { Fragment as Fragment11, jsx as jsx99, jsxs as jsxs58 } from "react/jsx-runtime";
5381
+ import { useState as useState26 } from "react";
5382
+ import { Pressable as Pressable35, Text as Text44, View as View67, useWindowDimensions as useWindowDimensions4 } from "react-native";
5383
+ import { cn as cn82 } from "@tallyui/theme";
5384
+ import { Fragment as Fragment12, jsx as jsx102, jsxs as jsxs60 } from "react/jsx-runtime";
4979
5385
  function POSLayout({
4980
5386
  browseSlot,
4981
5387
  cartSlot,
@@ -4987,40 +5393,40 @@ function POSLayout({
4987
5393
  }) {
4988
5394
  const { width } = useWindowDimensions4();
4989
5395
  const layout = layoutProp ?? (width >= breakpoint ? "split" : "stacked");
4990
- const [activeTab, setActiveTab] = useState24("browse");
4991
- return /* @__PURE__ */ jsxs58(View64, { className: cn80("flex-1 bg-bg", className), ...viewProps, children: [
4992
- headerSlot && /* @__PURE__ */ jsx99(View64, { className: "border-b border-border", children: headerSlot }),
4993
- layout === "split" ? /* @__PURE__ */ jsxs58(View64, { className: "flex-1 flex-row", children: [
4994
- /* @__PURE__ */ jsx99(View64, { className: "flex-[3]", children: browseSlot }),
4995
- /* @__PURE__ */ jsx99(View64, { className: "flex-[2] border-l border-border", children: cartSlot })
4996
- ] }) : /* @__PURE__ */ jsxs58(Fragment11, { children: [
4997
- /* @__PURE__ */ jsxs58(View64, { className: "flex-row border-b border-border", children: [
4998
- /* @__PURE__ */ jsx99(
4999
- Pressable32,
5396
+ const [activeTab, setActiveTab] = useState26("browse");
5397
+ return /* @__PURE__ */ jsxs60(View67, { className: cn82("flex-1 bg-bg", className), ...viewProps, children: [
5398
+ headerSlot && /* @__PURE__ */ jsx102(View67, { className: "border-b border-border", children: headerSlot }),
5399
+ layout === "split" ? /* @__PURE__ */ jsxs60(View67, { className: "flex-1 flex-row", children: [
5400
+ /* @__PURE__ */ jsx102(View67, { className: "flex-[3]", children: browseSlot }),
5401
+ /* @__PURE__ */ jsx102(View67, { className: "flex-[2] border-l border-border", children: cartSlot })
5402
+ ] }) : /* @__PURE__ */ jsxs60(Fragment12, { children: [
5403
+ /* @__PURE__ */ jsxs60(View67, { className: "flex-row border-b border-border", children: [
5404
+ /* @__PURE__ */ jsx102(
5405
+ Pressable35,
5000
5406
  {
5001
5407
  onPress: () => setActiveTab("browse"),
5002
- className: cn80("flex-1 py-3", activeTab === "browse" && "border-b-2 border-primary"),
5003
- children: /* @__PURE__ */ jsx99(Text42, { className: cn80("text-center text-sm font-semibold", activeTab === "browse" ? "text-primary" : "text-muted-foreground"), children: "Browse" })
5408
+ className: cn82("flex-1 py-3", activeTab === "browse" && "border-b-2 border-primary"),
5409
+ children: /* @__PURE__ */ jsx102(Text44, { className: cn82("text-center text-sm font-semibold", activeTab === "browse" ? "text-primary" : "text-muted-foreground"), children: "Browse" })
5004
5410
  }
5005
5411
  ),
5006
- /* @__PURE__ */ jsx99(
5007
- Pressable32,
5412
+ /* @__PURE__ */ jsx102(
5413
+ Pressable35,
5008
5414
  {
5009
5415
  onPress: () => setActiveTab("cart"),
5010
- className: cn80("flex-1 py-3", activeTab === "cart" && "border-b-2 border-primary"),
5011
- children: /* @__PURE__ */ jsx99(Text42, { className: cn80("text-center text-sm font-semibold", activeTab === "cart" ? "text-primary" : "text-muted-foreground"), children: "Cart" })
5416
+ className: cn82("flex-1 py-3", activeTab === "cart" && "border-b-2 border-primary"),
5417
+ children: /* @__PURE__ */ jsx102(Text44, { className: cn82("text-center text-sm font-semibold", activeTab === "cart" ? "text-primary" : "text-muted-foreground"), children: "Cart" })
5012
5418
  }
5013
5419
  )
5014
5420
  ] }),
5015
- /* @__PURE__ */ jsx99(View64, { className: "flex-1", children: activeTab === "browse" ? browseSlot : cartSlot })
5421
+ /* @__PURE__ */ jsx102(View67, { className: "flex-1", children: activeTab === "browse" ? browseSlot : cartSlot })
5016
5422
  ] })
5017
5423
  ] });
5018
5424
  }
5019
5425
 
5020
5426
  // src/layout/checkout-layout.tsx
5021
- import { ScrollView as ScrollView15, View as View65, useWindowDimensions as useWindowDimensions5 } from "react-native";
5022
- import { cn as cn81 } from "@tallyui/theme";
5023
- import { jsx as jsx100, jsxs as jsxs59 } from "react/jsx-runtime";
5427
+ import { ScrollView as ScrollView15, View as View68, useWindowDimensions as useWindowDimensions5 } from "react-native";
5428
+ import { cn as cn83 } from "@tallyui/theme";
5429
+ import { jsx as jsx103, jsxs as jsxs61 } from "react/jsx-runtime";
5024
5430
  function CheckoutLayout({
5025
5431
  summarySlot,
5026
5432
  paymentSlot,
@@ -5032,12 +5438,12 @@ function CheckoutLayout({
5032
5438
  }) {
5033
5439
  const { width } = useWindowDimensions5();
5034
5440
  const layout = layoutProp ?? (width >= breakpoint ? "split" : "stacked");
5035
- return /* @__PURE__ */ jsxs59(View65, { className: cn81("flex-1 bg-bg", className), ...viewProps, children: [
5036
- headerSlot && /* @__PURE__ */ jsx100(View65, { className: "border-b border-border", children: headerSlot }),
5037
- layout === "split" ? /* @__PURE__ */ jsxs59(View65, { className: "flex-1 flex-row", children: [
5038
- /* @__PURE__ */ jsx100(View65, { className: "flex-1 border-r border-border", children: summarySlot }),
5039
- /* @__PURE__ */ jsx100(View65, { className: "flex-1", children: paymentSlot })
5040
- ] }) : /* @__PURE__ */ jsx100(ScrollView15, { className: "flex-1", children: /* @__PURE__ */ jsxs59(View65, { className: "gap-4 p-4", children: [
5441
+ return /* @__PURE__ */ jsxs61(View68, { className: cn83("flex-1 bg-bg", className), ...viewProps, children: [
5442
+ headerSlot && /* @__PURE__ */ jsx103(View68, { className: "border-b border-border", children: headerSlot }),
5443
+ layout === "split" ? /* @__PURE__ */ jsxs61(View68, { className: "flex-1 flex-row", children: [
5444
+ /* @__PURE__ */ jsx103(View68, { className: "flex-1 border-r border-border", children: summarySlot }),
5445
+ /* @__PURE__ */ jsx103(View68, { className: "flex-1", children: paymentSlot })
5446
+ ] }) : /* @__PURE__ */ jsx103(ScrollView15, { className: "flex-1", children: /* @__PURE__ */ jsxs61(View68, { className: "gap-4 p-4", children: [
5041
5447
  summarySlot,
5042
5448
  paymentSlot
5043
5449
  ] }) })
@@ -5045,10 +5451,10 @@ function CheckoutLayout({
5045
5451
  }
5046
5452
 
5047
5453
  // src/layout/settings-layout.tsx
5048
- import { useState as useState25 } from "react";
5049
- import { Pressable as Pressable33, Text as Text43, View as View66, useWindowDimensions as useWindowDimensions6 } from "react-native";
5050
- import { cn as cn82 } from "@tallyui/theme";
5051
- import { jsx as jsx101, jsxs as jsxs60 } from "react/jsx-runtime";
5454
+ import { useState as useState27 } from "react";
5455
+ import { Pressable as Pressable36, Text as Text45, View as View69, useWindowDimensions as useWindowDimensions6 } from "react-native";
5456
+ import { cn as cn84 } from "@tallyui/theme";
5457
+ import { jsx as jsx104, jsxs as jsxs62 } from "react/jsx-runtime";
5052
5458
  function SettingsLayout({
5053
5459
  navSlot,
5054
5460
  contentSlot,
@@ -5060,26 +5466,26 @@ function SettingsLayout({
5060
5466
  }) {
5061
5467
  const { width } = useWindowDimensions6();
5062
5468
  const layout = layoutProp ?? (width >= breakpoint ? "split" : "stacked");
5063
- const [showNav, setShowNav] = useState25(false);
5064
- return /* @__PURE__ */ jsxs60(View66, { className: cn82("flex-1 bg-bg", className), ...viewProps, children: [
5065
- headerSlot && /* @__PURE__ */ jsx101(View66, { className: "border-b border-border", children: headerSlot }),
5066
- layout === "split" ? /* @__PURE__ */ jsxs60(View66, { className: "flex-1 flex-row", children: [
5067
- /* @__PURE__ */ jsx101(View66, { className: "w-64 border-r border-border", children: navSlot }),
5068
- /* @__PURE__ */ jsx101(View66, { className: "flex-1", children: contentSlot })
5069
- ] }) : /* @__PURE__ */ jsx101(View66, { className: "flex-1", children: showNav ? /* @__PURE__ */ jsxs60(View66, { className: "flex-1", children: [
5469
+ const [showNav, setShowNav] = useState27(false);
5470
+ return /* @__PURE__ */ jsxs62(View69, { className: cn84("flex-1 bg-bg", className), ...viewProps, children: [
5471
+ headerSlot && /* @__PURE__ */ jsx104(View69, { className: "border-b border-border", children: headerSlot }),
5472
+ layout === "split" ? /* @__PURE__ */ jsxs62(View69, { className: "flex-1 flex-row", children: [
5473
+ /* @__PURE__ */ jsx104(View69, { className: "w-64 border-r border-border", children: navSlot }),
5474
+ /* @__PURE__ */ jsx104(View69, { className: "flex-1", children: contentSlot })
5475
+ ] }) : /* @__PURE__ */ jsx104(View69, { className: "flex-1", children: showNav ? /* @__PURE__ */ jsxs62(View69, { className: "flex-1", children: [
5070
5476
  navSlot,
5071
- /* @__PURE__ */ jsx101(Pressable33, { onPress: () => setShowNav(false), className: "border-t border-border p-3", children: /* @__PURE__ */ jsx101(Text43, { className: "text-center text-sm font-medium text-primary", children: "Done" }) })
5072
- ] }) : /* @__PURE__ */ jsxs60(View66, { className: "flex-1", children: [
5073
- /* @__PURE__ */ jsx101(Pressable33, { onPress: () => setShowNav(true), className: "border-b border-border px-4 py-2", children: /* @__PURE__ */ jsx101(Text43, { className: "text-sm font-medium text-primary", children: "Menu" }) }),
5477
+ /* @__PURE__ */ jsx104(Pressable36, { onPress: () => setShowNav(false), className: "border-t border-border p-3", children: /* @__PURE__ */ jsx104(Text45, { className: "text-center text-sm font-medium text-primary", children: "Done" }) })
5478
+ ] }) : /* @__PURE__ */ jsxs62(View69, { className: "flex-1", children: [
5479
+ /* @__PURE__ */ jsx104(Pressable36, { onPress: () => setShowNav(true), className: "border-b border-border px-4 py-2", children: /* @__PURE__ */ jsx104(Text45, { className: "text-sm font-medium text-primary", children: "Menu" }) }),
5074
5480
  contentSlot
5075
5481
  ] }) })
5076
5482
  ] });
5077
5483
  }
5078
5484
 
5079
5485
  // src/layout/live-tab-screen.tsx
5080
- import { Pressable as Pressable34, Text as Text44, View as View67 } from "react-native";
5081
- import { cn as cn83 } from "@tallyui/theme";
5082
- import { jsx as jsx102, jsxs as jsxs61 } from "react/jsx-runtime";
5486
+ import { Pressable as Pressable37, Text as Text46, View as View70 } from "react-native";
5487
+ import { cn as cn85 } from "@tallyui/theme";
5488
+ import { jsx as jsx105, jsxs as jsxs63 } from "react/jsx-runtime";
5083
5489
  function LiveTabScreen({
5084
5490
  state,
5085
5491
  onUseHere,
@@ -5096,21 +5502,21 @@ function LiveTabScreen({
5096
5502
  const body = state === "parked" ? parkedBody : blockedBody;
5097
5503
  const buttonLabel = state === "parked" ? useHereLabel : reloadLabel;
5098
5504
  const onPress = state === "parked" ? onUseHere : onReload;
5099
- return /* @__PURE__ */ jsxs61(View67, { className: cn83("flex-1 items-center justify-center gap-4 bg-bg p-6", className), ...viewProps, children: [
5100
- /* @__PURE__ */ jsx102(Text44, { className: "text-center text-lg font-bold text-foreground", children: parkedTitle }),
5101
- /* @__PURE__ */ jsx102(Text44, { className: "text-center text-sm text-muted-foreground", children: body }),
5102
- /* @__PURE__ */ jsx102(Pressable34, { onPress, className: "items-center rounded-lg bg-primary px-4 py-3", children: /* @__PURE__ */ jsx102(Text44, { className: "text-sm font-semibold text-primary-foreground", children: buttonLabel }) })
5505
+ return /* @__PURE__ */ jsxs63(View70, { className: cn85("flex-1 items-center justify-center gap-4 bg-bg p-6", className), ...viewProps, children: [
5506
+ /* @__PURE__ */ jsx105(Text46, { className: "text-center text-lg font-bold text-foreground", children: parkedTitle }),
5507
+ /* @__PURE__ */ jsx105(Text46, { className: "text-center text-sm text-muted-foreground", children: body }),
5508
+ /* @__PURE__ */ jsx105(Pressable37, { onPress, className: "items-center rounded-lg bg-primary px-4 py-3", children: /* @__PURE__ */ jsx105(Text46, { className: "text-sm font-semibold text-primary-foreground", children: buttonLabel }) })
5103
5509
  ] });
5104
5510
  }
5105
5511
 
5106
5512
  // src/layout/store-settings-choice-screen.tsx
5107
- import { useState as useState26 } from "react";
5108
- import { Pressable as Pressable35, Text as Text45, View as View68 } from "react-native";
5109
- import { cn as cn84 } from "@tallyui/theme";
5110
- import { jsx as jsx103, jsxs as jsxs62 } from "react/jsx-runtime";
5513
+ import { useState as useState28 } from "react";
5514
+ import { Pressable as Pressable38, Text as Text47, View as View71 } from "react-native";
5515
+ import { cn as cn86 } from "@tallyui/theme";
5516
+ import { jsx as jsx106, jsxs as jsxs64 } from "react/jsx-runtime";
5111
5517
  function useSectionSelection(options, initialValue) {
5112
5518
  const preset = options.length === 1 ? options[0].value : options.find((o) => o.value === initialValue)?.value;
5113
- return useState26(preset);
5519
+ return useState28(preset);
5114
5520
  }
5115
5521
  function defaultCountryName(code, locale) {
5116
5522
  try {
@@ -5156,41 +5562,41 @@ function StoreSettingsChoiceScreen({
5156
5562
  else if (initial?.channel !== void 0) choice.channel = initial.channel;
5157
5563
  onSubmit(choice);
5158
5564
  };
5159
- return /* @__PURE__ */ jsxs62(View68, { className: cn84("w-full max-w-[560px] flex-1 self-center gap-6 bg-bg p-6", className), ...viewProps, children: [
5160
- /* @__PURE__ */ jsxs62(View68, { className: "gap-2", children: [
5161
- /* @__PURE__ */ jsx103(Text45, { className: "text-lg font-bold text-foreground", children: title }),
5162
- /* @__PURE__ */ jsx103(Text45, { className: "text-sm text-muted-foreground", children: body })
5565
+ return /* @__PURE__ */ jsxs64(View71, { className: cn86("w-full max-w-[560px] flex-1 self-center gap-6 bg-bg p-6", className), ...viewProps, children: [
5566
+ /* @__PURE__ */ jsxs64(View71, { className: "gap-2", children: [
5567
+ /* @__PURE__ */ jsx106(Text47, { className: "text-lg font-bold text-foreground", children: title }),
5568
+ /* @__PURE__ */ jsx106(Text47, { className: "text-sm text-muted-foreground", children: body })
5163
5569
  ] }),
5164
- showRegions && /* @__PURE__ */ jsx103(ChoiceSection, { label: regionLabel, options: regionOptions, selected: region, onSelect: setRegion }),
5165
- showCountries && /* @__PURE__ */ jsx103(ChoiceSection, { label: countryLabel, options: countryOptions, selected: country, onSelect: setCountry }),
5166
- showChannels && /* @__PURE__ */ jsx103(ChoiceSection, { label: channelLabel, options: channelOptions, selected: channel, onSelect: setChannel }),
5167
- /* @__PURE__ */ jsx103(
5168
- Pressable35,
5570
+ showRegions && /* @__PURE__ */ jsx106(ChoiceSection, { label: regionLabel, options: regionOptions, selected: region, onSelect: setRegion }),
5571
+ showCountries && /* @__PURE__ */ jsx106(ChoiceSection, { label: countryLabel, options: countryOptions, selected: country, onSelect: setCountry }),
5572
+ showChannels && /* @__PURE__ */ jsx106(ChoiceSection, { label: channelLabel, options: channelOptions, selected: channel, onSelect: setChannel }),
5573
+ /* @__PURE__ */ jsx106(
5574
+ Pressable38,
5169
5575
  {
5170
5576
  onPress: handleSubmit,
5171
5577
  disabled: !complete,
5172
- className: cn84("items-center rounded-lg bg-primary px-4 py-3", !complete && "opacity-50"),
5173
- children: /* @__PURE__ */ jsx103(Text45, { className: "text-sm font-semibold text-primary-foreground", children: submitLabel })
5578
+ className: cn86("items-center rounded-lg bg-primary px-4 py-3", !complete && "opacity-50"),
5579
+ children: /* @__PURE__ */ jsx106(Text47, { className: "text-sm font-semibold text-primary-foreground", children: submitLabel })
5174
5580
  }
5175
5581
  )
5176
5582
  ] });
5177
5583
  }
5178
5584
  function ChoiceSection({ label, options, selected, onSelect }) {
5179
- return /* @__PURE__ */ jsxs62(View68, { className: "gap-1.5", children: [
5180
- /* @__PURE__ */ jsx103(Text45, { className: "text-xs font-semibold text-muted-foreground", children: label }),
5181
- /* @__PURE__ */ jsx103(View68, { className: "rounded-lg border border-border", children: options.map((option, index) => {
5585
+ return /* @__PURE__ */ jsxs64(View71, { className: "gap-1.5", children: [
5586
+ /* @__PURE__ */ jsx106(Text47, { className: "text-xs font-semibold text-muted-foreground", children: label }),
5587
+ /* @__PURE__ */ jsx106(View71, { className: "rounded-lg border border-border", children: options.map((option, index) => {
5182
5588
  const checked = option.value === selected;
5183
- return /* @__PURE__ */ jsxs62(
5184
- Pressable35,
5589
+ return /* @__PURE__ */ jsxs64(
5590
+ Pressable38,
5185
5591
  {
5186
5592
  onPress: () => onSelect(option.value),
5187
5593
  accessibilityRole: "radio",
5188
5594
  "aria-checked": checked,
5189
5595
  testID: `choice-option-${option.value}`,
5190
- className: cn84("flex-row items-center gap-3 px-4 py-3", index > 0 && "border-t border-border", checked && "bg-primary/10"),
5596
+ className: cn86("flex-row items-center gap-3 px-4 py-3", index > 0 && "border-t border-border", checked && "bg-primary/10"),
5191
5597
  children: [
5192
- /* @__PURE__ */ jsx103(View68, { className: "h-4 w-4 items-center justify-center rounded-full border border-primary", children: checked && /* @__PURE__ */ jsx103(View68, { testID: `choice-option-${option.value}-dot`, className: "h-2.5 w-2.5 rounded-full bg-primary" }) }),
5193
- /* @__PURE__ */ jsx103(Text45, { className: cn84("text-sm", checked ? "font-semibold text-primary" : "text-foreground"), children: option.label })
5598
+ /* @__PURE__ */ jsx106(View71, { className: "h-4 w-4 items-center justify-center rounded-full border border-primary", children: checked && /* @__PURE__ */ jsx106(View71, { testID: `choice-option-${option.value}-dot`, className: "h-2.5 w-2.5 rounded-full bg-primary" }) }),
5599
+ /* @__PURE__ */ jsx106(Text47, { className: cn86("text-sm", checked ? "font-semibold text-primary" : "text-foreground"), children: option.label })
5194
5600
  ]
5195
5601
  },
5196
5602
  option.value
@@ -5236,6 +5642,7 @@ export {
5236
5642
  Catalogue,
5237
5643
  CategoryNav,
5238
5644
  ChangeDisplay,
5645
+ ChargeForm,
5239
5646
  Checkbox,
5240
5647
  CheckoutLayout,
5241
5648
  ClosureSheet,
@@ -5334,6 +5741,7 @@ export {
5334
5741
  ProductPrice,
5335
5742
  ProductSku,
5336
5743
  ProductStockBadge,
5744
+ ProductTable,
5337
5745
  ProductTitle,
5338
5746
  ProductVariantPicker,
5339
5747
  Progress,
@@ -5394,6 +5802,7 @@ export {
5394
5802
  TooltipContent,
5395
5803
  TooltipTrigger,
5396
5804
  VStack,
5805
+ ViewToggle,
5397
5806
  XIcon,
5398
5807
  avatarVariants,
5399
5808
  badgeTextVariants,
@@ -5401,6 +5810,7 @@ export {
5401
5810
  buttonTextVariants,
5402
5811
  buttonVariants,
5403
5812
  createSvgIcon,
5813
+ defaultProductColumns,
5404
5814
  describeRegisterBarPill,
5405
5815
  discountLabel,
5406
5816
  formatStockSyncTime,
@@ -5416,6 +5826,7 @@ export {
5416
5826
  toastVariants,
5417
5827
  toggleTextVariants,
5418
5828
  toggleVariants,
5829
+ useDefaultProductColumns,
5419
5830
  useInputContext,
5420
5831
  vstackVariants
5421
5832
  };