@tallyui/components 3.1.0 → 3.2.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.d.ts +4 -2
- package/dist/index.js +5 -5
- package/package.json +9 -9
- package/src/sale/discount-form.tsx +3 -2
- package/src/sale/parked-sales.tsx +6 -4
- package/src/sale/price-form.tsx +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1358,17 +1358,19 @@ declare function OrdersList({ orders, onRetry, formatDate, footer, stuck }: {
|
|
|
1358
1358
|
stuck?: OutboxState['stuck'];
|
|
1359
1359
|
}): react_jsx_runtime.JSX.Element;
|
|
1360
1360
|
|
|
1361
|
-
/** Pass `useParkedSales(drafts)`'s `parked` and `discard
|
|
1361
|
+
/** Pass `useParkedSales(drafts)`'s `parked` and `discard`, or your own parked store's list and handlers (`onPark`, `onResume`, `onDiscard`) with the same results. */
|
|
1362
1362
|
interface ParkedSalesProps {
|
|
1363
1363
|
sale: ReturnType<typeof useSale>;
|
|
1364
1364
|
parked: ParkedOrderSummary[];
|
|
1365
1365
|
onDiscard: (id: string) => Promise<void>;
|
|
1366
|
+
onPark?: () => Promise<string | null>;
|
|
1367
|
+
onResume?: (id: string) => Promise<string | null>;
|
|
1366
1368
|
currency: string;
|
|
1367
1369
|
open: boolean;
|
|
1368
1370
|
onOpenChange: (open: boolean) => void;
|
|
1369
1371
|
hour12?: boolean;
|
|
1370
1372
|
}
|
|
1371
|
-
declare function ParkedSales({ sale, parked, onDiscard, currency, open, onOpenChange, hour12 }: ParkedSalesProps): JSX.Element;
|
|
1373
|
+
declare function ParkedSales({ sale, parked, onDiscard, onPark, onResume, currency, open, onOpenChange, hour12 }: ParkedSalesProps): JSX.Element;
|
|
1372
1374
|
|
|
1373
1375
|
interface POSLayoutProps extends Omit<ViewProps, 'children'> {
|
|
1374
1376
|
browseSlot: ReactNode;
|
package/dist/index.js
CHANGED
|
@@ -3978,7 +3978,7 @@ function parseDiscount(type, text, currency) {
|
|
|
3978
3978
|
if (!/^-?\d+(\.\d+)?$/.test(trimmed)) return "Enter a number.";
|
|
3979
3979
|
const value = Number(trimmed);
|
|
3980
3980
|
if (value <= 0) return "Enter a discount above 0.";
|
|
3981
|
-
const digits = type === "percentage" ? 2 :
|
|
3981
|
+
const digits = type === "percentage" ? 2 : minorUnitDigits7(currency);
|
|
3982
3982
|
if ((trimmed.split(".")[1]?.length ?? 0) > digits) return digits ? `Use at most ${digits} decimal places.` : "Use a whole amount.";
|
|
3983
3983
|
if (type === "percentage") return value > 100 ? "A percentage can be at most 100." : { type, value };
|
|
3984
3984
|
const money = moneyFromDecimalString2(trimmed, currency);
|
|
@@ -4068,7 +4068,7 @@ function parsePrice(text, currency) {
|
|
|
4068
4068
|
if (!trimmed) return "Enter a price.";
|
|
4069
4069
|
if (!/^-?\d+(\.\d+)?$/.test(trimmed)) return "Enter a number.";
|
|
4070
4070
|
if (Number(trimmed) < 0) return "Enter a price of 0 or more.";
|
|
4071
|
-
const digits =
|
|
4071
|
+
const digits = minorUnitDigits8(currency);
|
|
4072
4072
|
if ((trimmed.split(".")[1]?.length ?? 0) > digits) return digits ? `Use at most ${digits} decimal places.` : "Use a whole amount.";
|
|
4073
4073
|
return moneyFromDecimalString3(trimmed, currency)?.amount ?? "Enter a number.";
|
|
4074
4074
|
}
|
|
@@ -4752,7 +4752,7 @@ import { useState as useState22 } from "react";
|
|
|
4752
4752
|
import { ScrollView as ScrollView14, useWindowDimensions as useWindowDimensions3, View as View62 } from "react-native";
|
|
4753
4753
|
import { formatMoney as formatMoney16 } from "@tallyui/core";
|
|
4754
4754
|
import { Fragment as Fragment9, jsx as jsx97, jsxs as jsxs56 } from "react/jsx-runtime";
|
|
4755
|
-
function ParkedSales({ sale, parked, onDiscard, currency, open, onOpenChange, hour12 }) {
|
|
4755
|
+
function ParkedSales({ sale, parked, onDiscard, onPark, onResume, currency, open, onOpenChange, hour12 }) {
|
|
4756
4756
|
const { height: windowHeight } = useWindowDimensions3();
|
|
4757
4757
|
const maxHeight = Math.max(280, windowHeight - 64);
|
|
4758
4758
|
const [confirming, setConfirming] = useState22(null);
|
|
@@ -4777,7 +4777,7 @@ function ParkedSales({ sale, parked, onDiscard, currency, open, onOpenChange, ho
|
|
|
4777
4777
|
testID: "parked-sales-park",
|
|
4778
4778
|
accessibilityLabel: "Park this sale",
|
|
4779
4779
|
disabled: sale.order.lineItems.length === 0,
|
|
4780
|
-
onPress: () => attempt(async () => setError(await sale.park() ?? "")),
|
|
4780
|
+
onPress: () => attempt(async () => setError(await (onPark ?? sale.park)() ?? "")),
|
|
4781
4781
|
children: /* @__PURE__ */ jsx97(Text, { children: "Park this sale" })
|
|
4782
4782
|
}
|
|
4783
4783
|
),
|
|
@@ -4816,7 +4816,7 @@ function ParkedSales({ sale, parked, onDiscard, currency, open, onOpenChange, ho
|
|
|
4816
4816
|
testID: `parked-resume-${row.id}`,
|
|
4817
4817
|
accessibilityLabel: "Resume parked sale",
|
|
4818
4818
|
onPress: () => attempt(async () => {
|
|
4819
|
-
const refusal = await sale.resume(row.id);
|
|
4819
|
+
const refusal = await (onResume ?? ((id) => sale.resume(id)))(row.id);
|
|
4820
4820
|
if (refusal === null) onOpenChange(false);
|
|
4821
4821
|
else setError(refusal);
|
|
4822
4822
|
}),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tallyui/components",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Universal POS UI components for Tally UI",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -27,22 +27,22 @@
|
|
|
27
27
|
"directory": "packages/components"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"@tallyui/core": "^3.
|
|
31
|
-
"@tallyui/primitives": "^3.
|
|
32
|
-
"@tallyui/theme": "^3.
|
|
30
|
+
"@tallyui/core": "^3.2.0",
|
|
31
|
+
"@tallyui/primitives": "^3.2.0",
|
|
32
|
+
"@tallyui/theme": "^3.2.0",
|
|
33
33
|
"react": ">=18",
|
|
34
34
|
"react-native": ">=0.74",
|
|
35
35
|
"react-native-svg": ">=15"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"class-variance-authority": "^0.7.1",
|
|
39
|
-
"@tallyui/pos": "3.
|
|
39
|
+
"@tallyui/pos": "3.2.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@tallyui/connector-medusa": "3.
|
|
43
|
-
"@tallyui/connector-vendure": "3.
|
|
44
|
-
"@tallyui/connector-woocommerce": "3.
|
|
45
|
-
"@tallyui/mock-api": "3.
|
|
42
|
+
"@tallyui/connector-medusa": "3.2.0",
|
|
43
|
+
"@tallyui/connector-vendure": "3.2.0",
|
|
44
|
+
"@tallyui/connector-woocommerce": "3.2.0",
|
|
45
|
+
"@tallyui/mock-api": "3.2.0",
|
|
46
46
|
"@types/react": ">=18",
|
|
47
47
|
"react": "^19.2.4",
|
|
48
48
|
"react-native-svg": "15.12.1",
|
|
@@ -13,8 +13,9 @@ export function parseDiscount(type: Discount['type'], text: string, currency: st
|
|
|
13
13
|
if (!/^-?\d+(\.\d+)?$/.test(trimmed)) return 'Enter a number.';
|
|
14
14
|
const value = Number(trimmed);
|
|
15
15
|
if (value <= 0) return 'Enter a discount above 0.';
|
|
16
|
-
//
|
|
17
|
-
|
|
16
|
+
// Percentages take 2 decimals; a fixed amount takes the currency's own exponent.
|
|
17
|
+
// "1,000" or "1.000" with more digits than allowed is refused, never read as 1.
|
|
18
|
+
const digits = type === 'percentage' ? 2 : minorUnitDigits(currency);
|
|
18
19
|
if ((trimmed.split('.')[1]?.length ?? 0) > digits) return digits ? `Use at most ${digits} decimal places.` : 'Use a whole amount.';
|
|
19
20
|
if (type === 'percentage') return value > 100 ? 'A percentage can be at most 100.' : { type, value };
|
|
20
21
|
const money = moneyFromDecimalString(trimmed, currency);
|
|
@@ -9,18 +9,20 @@ import { XIcon } from '../ui/icon/x-icon';
|
|
|
9
9
|
import { Text } from '../ui/text';
|
|
10
10
|
import { formatStockSyncTime } from './catalogue';
|
|
11
11
|
|
|
12
|
-
/** Pass `useParkedSales(drafts)`'s `parked` and `discard
|
|
12
|
+
/** Pass `useParkedSales(drafts)`'s `parked` and `discard`, or your own parked store's list and handlers (`onPark`, `onResume`, `onDiscard`) with the same results. */
|
|
13
13
|
export interface ParkedSalesProps {
|
|
14
14
|
sale: ReturnType<typeof useSale>;
|
|
15
15
|
parked: ParkedOrderSummary[];
|
|
16
16
|
onDiscard: (id: string) => Promise<void>;
|
|
17
|
+
onPark?: () => Promise<string | null>;
|
|
18
|
+
onResume?: (id: string) => Promise<string | null>;
|
|
17
19
|
currency: string;
|
|
18
20
|
open: boolean;
|
|
19
21
|
onOpenChange: (open: boolean) => void;
|
|
20
22
|
hour12?: boolean;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
export function ParkedSales({ sale, parked, onDiscard, currency, open, onOpenChange, hour12 }: ParkedSalesProps): JSX.Element {
|
|
25
|
+
export function ParkedSales({ sale, parked, onDiscard, onPark, onResume, currency, open, onOpenChange, hour12 }: ParkedSalesProps): JSX.Element {
|
|
24
26
|
const { height: windowHeight } = useWindowDimensions();
|
|
25
27
|
const maxHeight = Math.max(280, windowHeight - 64);
|
|
26
28
|
const [confirming, setConfirming] = useState<string | null>(null);
|
|
@@ -49,7 +51,7 @@ export function ParkedSales({ sale, parked, onDiscard, currency, open, onOpenCha
|
|
|
49
51
|
<ScrollView className="flex-1" contentContainerClassName="gap-3">
|
|
50
52
|
<Button testID="parked-sales-park" accessibilityLabel="Park this sale"
|
|
51
53
|
disabled={sale.order.lineItems.length === 0}
|
|
52
|
-
onPress={() => attempt(async () => setError((await sale.park()) ?? ''))}>
|
|
54
|
+
onPress={() => attempt(async () => setError((await (onPark ?? sale.park)()) ?? ''))}>
|
|
53
55
|
<Text>Park this sale</Text>
|
|
54
56
|
</Button>
|
|
55
57
|
{!!error && <Text testID="parked-sales-error" className="text-destructive">{error}</Text>}
|
|
@@ -81,7 +83,7 @@ export function ParkedSales({ sale, parked, onDiscard, currency, open, onOpenCha
|
|
|
81
83
|
<View className="flex-row gap-2">
|
|
82
84
|
<Button testID={`parked-resume-${row.id}`} accessibilityLabel="Resume parked sale"
|
|
83
85
|
onPress={() => attempt(async () => {
|
|
84
|
-
const refusal = await sale.resume(row.id);
|
|
86
|
+
const refusal = await (onResume ?? ((id) => sale.resume(id)))(row.id);
|
|
85
87
|
if (refusal === null) onOpenChange(false);
|
|
86
88
|
else setError(refusal);
|
|
87
89
|
})}>
|
package/src/sale/price-form.tsx
CHANGED
|
@@ -9,7 +9,7 @@ export function parsePrice(text: string, currency: string): number | string {
|
|
|
9
9
|
if (!trimmed) return 'Enter a price.';
|
|
10
10
|
if (!/^-?\d+(\.\d+)?$/.test(trimmed)) return 'Enter a number.';
|
|
11
11
|
if (Number(trimmed) < 0) return 'Enter a price of 0 or more.';
|
|
12
|
-
const digits =
|
|
12
|
+
const digits = minorUnitDigits(currency);
|
|
13
13
|
if ((trimmed.split('.')[1]?.length ?? 0) > digits) return digits ? `Use at most ${digits} decimal places.` : 'Use a whole amount.';
|
|
14
14
|
return moneyFromDecimalString(trimmed, currency)?.amount ?? 'Enter a number.';
|
|
15
15
|
}
|