@shoplix-ai/block-kit 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/README.md +30 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/money.d.ts +29 -0
- package/dist/money.d.ts.map +1 -1
- package/dist/money.js +141 -1
- package/dist/money.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -52,8 +52,9 @@ written against this package and nothing else from the runtime. It holds:
|
|
|
52
52
|
currency, for display only: the total a buyer sees is always Shopify's),
|
|
53
53
|
`pickLocale` (the buyer's language from the Shop's languages with default
|
|
54
54
|
fallback), `localize` (one string out of a locale object), `textDirection`,
|
|
55
|
-
`imageSourceFor` (the rendition to paint at a given display width),
|
|
56
|
-
`platformWords`, the word catalog below
|
|
55
|
+
`imageSourceFor` (the rendition to paint at a given display width),
|
|
56
|
+
`platformWords`, the word catalog below, and `moneyParts`, `moneyText`,
|
|
57
|
+
`moneyAmount` and `discountPercent`, the money presentation below.
|
|
57
58
|
|
|
58
59
|
## The theme a renderer receives
|
|
59
60
|
|
|
@@ -113,6 +114,33 @@ string sits first in an object. Every language answers every key of
|
|
|
113
114
|
`WORD_KEYS`, which the type system and a test both hold; a word added in
|
|
114
115
|
English and nowhere else does not compile.
|
|
115
116
|
|
|
117
|
+
## How a price is written
|
|
118
|
+
|
|
119
|
+
Display money carries the string the Provider formatted in the buyer's language
|
|
120
|
+
and the decimal amount it was formatted from. **Every figure a block computes
|
|
121
|
+
comes from the amount**: reading a number back out of the formatted string
|
|
122
|
+
assumes the full stop is the decimal mark, which is wrong across most of Europe
|
|
123
|
+
and puts a confident nonsense percentage on a badge.
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
const percent = discountPercent(product.price, product.compareAtPrice);
|
|
127
|
+
const { digits, label } = moneyParts(product.price, language, theme.money);
|
|
128
|
+
const line = moneyText(product.price, language, theme.money);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`theme.money` is the digit style the design chose, and there are two.
|
|
132
|
+
`locale`, the default, draws the string the Provider wrote and no label beside
|
|
133
|
+
it. `latin` writes the digits from the amount in Latin numerals, grouped in
|
|
134
|
+
threes at the currency's own number of decimal places, with the currency's
|
|
135
|
+
short label beside them: how the Gulf commerce apps write a price in an Arabic
|
|
136
|
+
app. Money that carries no amount is drawn as the Provider wrote it, whatever
|
|
137
|
+
the style, so a block never loses a price it cannot restyle.
|
|
138
|
+
|
|
139
|
+
The short label comes from a maintained table of the currencies the platform
|
|
140
|
+
writes its own way, the Gulf currencies in Arabic among them. A currency the
|
|
141
|
+
table does not name takes the symbol the buyer's own language writes for it,
|
|
142
|
+
and the three letter code where the language writes none.
|
|
143
|
+
|
|
116
144
|
## Rows: what the host lays out
|
|
117
145
|
|
|
118
146
|
A Block Type may declare `rows` next to `render`:
|
package/dist/index.d.ts
CHANGED
|
@@ -11,7 +11,8 @@ export { defineCodeBlock, shopBlocks } from './code-block.js';
|
|
|
11
11
|
export type { CodeBlock, CodeBlockModule } from './code-block.js';
|
|
12
12
|
export { CONTRACT_MAJOR, CONTRACT_VERSION } from './version.js';
|
|
13
13
|
export { resolveToken } from './tokens.js';
|
|
14
|
-
export { formatMoney } from './money.js';
|
|
14
|
+
export { discountPercent, formatMoney, moneyAmount, moneyParts, moneyText } from './money.js';
|
|
15
|
+
export type { MoneyParts } from './money.js';
|
|
15
16
|
export { imageSourceFor } from './renditions.js';
|
|
16
17
|
export type { ImageSource } from './renditions.js';
|
|
17
18
|
export { localize, pickLocale, textDirection } from './locale.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7F,YAAY,EACV,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,uBAAuB,EACvB,aAAa,EACb,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,aAAa,EACb,WAAW,EACX,aAAa,GACd,MAAM,eAAe,CAAC;AAEvB,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC/D,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhF,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC9D,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7F,YAAY,EACV,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,uBAAuB,EACvB,aAAa,EACb,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,aAAa,EACb,WAAW,EACX,aAAa,GACd,MAAM,eAAe,CAAC;AAEvB,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC/D,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhF,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC9D,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC9F,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAClE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzE,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ export { defineBinding, defineSettings } from './authoring.js';
|
|
|
5
5
|
export { defineCodeBlock, shopBlocks } from './code-block.js';
|
|
6
6
|
export { CONTRACT_MAJOR, CONTRACT_VERSION } from './version.js';
|
|
7
7
|
export { resolveToken } from './tokens.js';
|
|
8
|
-
export { formatMoney } from './money.js';
|
|
8
|
+
export { discountPercent, formatMoney, moneyAmount, moneyParts, moneyText } from './money.js';
|
|
9
9
|
export { imageSourceFor } from './renditions.js';
|
|
10
10
|
export { localize, pickLocale, textDirection } from './locale.js';
|
|
11
11
|
export { CATALOG_LANGUAGES, WORD_KEYS, platformWords } from './words.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAY7F,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAgB5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAG/D,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG9D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAY7F,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAgB5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAG/D,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG9D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE9F,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAElE,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/money.d.ts
CHANGED
|
@@ -1,6 +1,35 @@
|
|
|
1
|
+
import { type DisplayMoney, type MoneyStyle } from '@shoplix-ai/sdui-schema';
|
|
1
2
|
/**
|
|
2
3
|
* Display-only money, formatted on the device in the buyer's language. The
|
|
3
4
|
* charged price always comes from Shopify checkout, never from this string.
|
|
4
5
|
*/
|
|
5
6
|
export declare function formatMoney(amount: string | number, currencyCode: string, language: string): string | null;
|
|
7
|
+
/** The digits of a price and the short label of its currency, drawn side by side. */
|
|
8
|
+
export interface MoneyParts {
|
|
9
|
+
readonly digits: string;
|
|
10
|
+
readonly label: string;
|
|
11
|
+
}
|
|
12
|
+
/** The number behind display money; null where the Provider recorded none. */
|
|
13
|
+
export declare function moneyAmount(money: DisplayMoney | undefined): number | null;
|
|
14
|
+
/**
|
|
15
|
+
* A price in the two pieces a card lays out itself. Under the latin style the
|
|
16
|
+
* digits are written from the decimal amount and the label is the currency's
|
|
17
|
+
* short one; under every other style, and for money carrying no amount this
|
|
18
|
+
* can be written from, the price stays the one string the Provider wrote and
|
|
19
|
+
* there is no label beside it.
|
|
20
|
+
*
|
|
21
|
+
* The latin style groups in threes with a period decimal whatever grouping the
|
|
22
|
+
* buyer's own language writes, so an Indian English buyer reads 1,234,567.89
|
|
23
|
+
* rather than 12,34,567.89. A merchant wanting the buyer's own grouping takes
|
|
24
|
+
* the locale style.
|
|
25
|
+
*/
|
|
26
|
+
export declare function moneyParts(money: DisplayMoney, language: string, style?: MoneyStyle): MoneyParts;
|
|
27
|
+
/** One price on one line, in the style the theme chose. */
|
|
28
|
+
export declare function moneyText(money: DisplayMoney, language: string, style?: MoneyStyle): string;
|
|
29
|
+
/**
|
|
30
|
+
* The percent off for a badge, from the two decimal amounts of one currency.
|
|
31
|
+
* Null where either side carries no amount, where the currencies differ, or
|
|
32
|
+
* where the saving does not round to a percent worth drawing.
|
|
33
|
+
*/
|
|
34
|
+
export declare function discountPercent(price: DisplayMoney, compareAt: DisplayMoney | undefined): number | null;
|
|
6
35
|
//# sourceMappingURL=money.d.ts.map
|
package/dist/money.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"money.d.ts","sourceRoot":"","sources":["../src/money.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"money.d.ts","sourceRoot":"","sources":["../src/money.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,YAAY,EAEjB,KAAK,UAAU,EAChB,MAAM,yBAAyB,CAAC;AAajC;;;GAGG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAYf;AAoDD,qFAAqF;AACrF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAI1E;AAyCD;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,UAAgC,GACtC,UAAU,CAQZ;AAED,2DAA2D;AAC3D,wBAAgB,SAAS,CACvB,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,UAAgC,GACtC,MAAM,CAGR;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,YAAY,GAAG,SAAS,GAClC,MAAM,GAAG,IAAI,CAOf"}
|
package/dist/money.js
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
|
+
import { DEFAULT_MONEY_STYLE, } from '@shoplix-ai/sdui-schema';
|
|
2
|
+
import { readable } from './locale.js';
|
|
1
3
|
const CURRENCY_CODE = /^[A-Z]{3}$/;
|
|
4
|
+
/** The decimal shape the display contract records an amount in. */
|
|
5
|
+
const DECIMAL = /^\d+(\.\d+)?$/;
|
|
6
|
+
/** A float that can no longer hold the amount's whole part exactly. */
|
|
7
|
+
function representable(value) {
|
|
8
|
+
return Number.isSafeInteger(Math.trunc(value));
|
|
9
|
+
}
|
|
2
10
|
/**
|
|
3
11
|
* Display-only money, formatted on the device in the buyer's language. The
|
|
4
12
|
* charged price always comes from Shopify checkout, never from this string.
|
|
5
13
|
*/
|
|
6
14
|
export function formatMoney(amount, currencyCode, language) {
|
|
7
15
|
const value = typeof amount === 'number' ? amount : Number(amount);
|
|
8
|
-
if (!Number.isFinite(value) || !CURRENCY_CODE.test(currencyCode))
|
|
16
|
+
if (!Number.isFinite(value) || !representable(value) || !CURRENCY_CODE.test(currencyCode)) {
|
|
9
17
|
return null;
|
|
18
|
+
}
|
|
10
19
|
try {
|
|
11
20
|
return new Intl.NumberFormat(language, { style: 'currency', currency: currencyCode }).format(value);
|
|
12
21
|
}
|
|
@@ -14,4 +23,135 @@ export function formatMoney(amount, currencyCode, language) {
|
|
|
14
23
|
return `${amount} ${currencyCode}`;
|
|
15
24
|
}
|
|
16
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* The short label the platform draws beside a price where it wants one of its
|
|
28
|
+
* own: the Gulf currencies in Arabic, whose ICU symbol carries a trailing full
|
|
29
|
+
* stop and direction marks a card does not draw. A currency this table does
|
|
30
|
+
* not name takes the symbol the buyer's own language writes for it, and the
|
|
31
|
+
* three letter code where the language writes none.
|
|
32
|
+
*/
|
|
33
|
+
const CURRENCY_LABELS = {
|
|
34
|
+
AED: { ar: 'د.إ' },
|
|
35
|
+
BHD: { ar: 'د.ب' },
|
|
36
|
+
EGP: { ar: 'ج.م' },
|
|
37
|
+
JOD: { ar: 'د.أ' },
|
|
38
|
+
KWD: { ar: 'د.ك' },
|
|
39
|
+
OMR: { ar: 'ر.ع' },
|
|
40
|
+
QAR: { ar: 'ر.ق' },
|
|
41
|
+
SAR: { ar: 'ر.س' },
|
|
42
|
+
USD: { ar: '$' },
|
|
43
|
+
};
|
|
44
|
+
/** The currencies written with other than two decimal places, by ISO 4217. */
|
|
45
|
+
const CURRENCY_PLACES = {
|
|
46
|
+
BHD: 3,
|
|
47
|
+
CLF: 4,
|
|
48
|
+
CLP: 0,
|
|
49
|
+
DJF: 0,
|
|
50
|
+
GNF: 0,
|
|
51
|
+
IQD: 3,
|
|
52
|
+
ISK: 0,
|
|
53
|
+
JOD: 3,
|
|
54
|
+
JPY: 0,
|
|
55
|
+
KMF: 0,
|
|
56
|
+
KRW: 0,
|
|
57
|
+
KWD: 3,
|
|
58
|
+
LYD: 3,
|
|
59
|
+
OMR: 3,
|
|
60
|
+
PYG: 0,
|
|
61
|
+
RWF: 0,
|
|
62
|
+
TND: 3,
|
|
63
|
+
UGX: 0,
|
|
64
|
+
UYI: 0,
|
|
65
|
+
UYW: 4,
|
|
66
|
+
VND: 0,
|
|
67
|
+
VUV: 0,
|
|
68
|
+
XAF: 0,
|
|
69
|
+
XOF: 0,
|
|
70
|
+
XPF: 0,
|
|
71
|
+
};
|
|
72
|
+
const DEFAULT_PLACES = 2;
|
|
73
|
+
/** The number behind display money; null where the Provider recorded none. */
|
|
74
|
+
export function moneyAmount(money) {
|
|
75
|
+
if (money?.amount === undefined)
|
|
76
|
+
return null;
|
|
77
|
+
const value = Number(money.amount);
|
|
78
|
+
return Number.isFinite(value) && representable(value) ? value : null;
|
|
79
|
+
}
|
|
80
|
+
function symbolOf(currencyCode, language) {
|
|
81
|
+
try {
|
|
82
|
+
const parts = new Intl.NumberFormat(language, {
|
|
83
|
+
style: 'currency',
|
|
84
|
+
currency: currencyCode,
|
|
85
|
+
currencyDisplay: 'narrowSymbol',
|
|
86
|
+
}).formatToParts(0);
|
|
87
|
+
return parts.find((part) => part.type === 'currency')?.value;
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function currencyLabel(currencyCode, language) {
|
|
94
|
+
const named = CURRENCY_LABELS[currencyCode];
|
|
95
|
+
const own = named === undefined ? undefined : readable(named, language, language);
|
|
96
|
+
return own ?? symbolOf(currencyCode, language) ?? currencyCode;
|
|
97
|
+
}
|
|
98
|
+
/** A decimal amount at a currency's own number of places, rounded half up, never through a float. */
|
|
99
|
+
function atPlaces(amount, places) {
|
|
100
|
+
const [whole = '0', fraction = ''] = amount.split('.');
|
|
101
|
+
if (fraction.length <= places) {
|
|
102
|
+
return places === 0 ? whole : `${whole}.${fraction.padEnd(places, '0')}`;
|
|
103
|
+
}
|
|
104
|
+
const carry = Number(fraction[places]) >= 5 ? 1n : 0n;
|
|
105
|
+
const units = (BigInt(`${whole}${fraction.slice(0, places)}`) + carry)
|
|
106
|
+
.toString()
|
|
107
|
+
.padStart(places + 1, '0');
|
|
108
|
+
return places === 0 ? units : `${units.slice(0, -places)}.${units.slice(-places)}`;
|
|
109
|
+
}
|
|
110
|
+
function latinDigits(amount, currencyCode) {
|
|
111
|
+
const written = atPlaces(amount, CURRENCY_PLACES[currencyCode] ?? DEFAULT_PLACES);
|
|
112
|
+
const [whole = '0', fraction] = written.split('.');
|
|
113
|
+
const grouped = whole.replace(/\B(?=(\d{3})+$)/g, ',');
|
|
114
|
+
return fraction === undefined ? grouped : `${grouped}.${fraction}`;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* A price in the two pieces a card lays out itself. Under the latin style the
|
|
118
|
+
* digits are written from the decimal amount and the label is the currency's
|
|
119
|
+
* short one; under every other style, and for money carrying no amount this
|
|
120
|
+
* can be written from, the price stays the one string the Provider wrote and
|
|
121
|
+
* there is no label beside it.
|
|
122
|
+
*
|
|
123
|
+
* The latin style groups in threes with a period decimal whatever grouping the
|
|
124
|
+
* buyer's own language writes, so an Indian English buyer reads 1,234,567.89
|
|
125
|
+
* rather than 12,34,567.89. A merchant wanting the buyer's own grouping takes
|
|
126
|
+
* the locale style.
|
|
127
|
+
*/
|
|
128
|
+
export function moneyParts(money, language, style = DEFAULT_MONEY_STYLE) {
|
|
129
|
+
if (style.digits !== 'latin' || money.amount === undefined || !DECIMAL.test(money.amount)) {
|
|
130
|
+
return { digits: money.formatted, label: '' };
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
digits: latinDigits(money.amount, money.currencyCode),
|
|
134
|
+
label: currencyLabel(money.currencyCode, language),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/** One price on one line, in the style the theme chose. */
|
|
138
|
+
export function moneyText(money, language, style = DEFAULT_MONEY_STYLE) {
|
|
139
|
+
const { digits, label } = moneyParts(money, language, style);
|
|
140
|
+
return label === '' ? digits : `${digits} ${label}`;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* The percent off for a badge, from the two decimal amounts of one currency.
|
|
144
|
+
* Null where either side carries no amount, where the currencies differ, or
|
|
145
|
+
* where the saving does not round to a percent worth drawing.
|
|
146
|
+
*/
|
|
147
|
+
export function discountPercent(price, compareAt) {
|
|
148
|
+
if (compareAt === undefined || compareAt.currencyCode !== price.currencyCode)
|
|
149
|
+
return null;
|
|
150
|
+
const now = moneyAmount(price);
|
|
151
|
+
const was = moneyAmount(compareAt);
|
|
152
|
+
if (now === null || was === null || was <= now)
|
|
153
|
+
return null;
|
|
154
|
+
const percent = Math.round((1 - now / was) * 100);
|
|
155
|
+
return percent === 0 ? null : percent;
|
|
156
|
+
}
|
|
17
157
|
//# sourceMappingURL=money.js.map
|
package/dist/money.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"money.js","sourceRoot":"","sources":["../src/money.ts"],"names":[],"mappings":"AAAA,MAAM,aAAa,GAAG,YAAY,CAAC;AAEnC;;;GAGG;AACH,MAAM,UAAU,WAAW,CACzB,MAAuB,EACvB,YAAoB,EACpB,QAAgB;IAEhB,MAAM,KAAK,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACnE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"money.js","sourceRoot":"","sources":["../src/money.ts"],"names":[],"mappings":"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"}
|
package/dist/version.d.ts
CHANGED
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
* The major is the compatibility line: a Shop package built against another
|
|
5
5
|
* major never meets this runtime, and a major bump is an announced event.
|
|
6
6
|
*/
|
|
7
|
-
export declare const CONTRACT_VERSION = "3.
|
|
7
|
+
export declare const CONTRACT_VERSION = "3.2.0";
|
|
8
8
|
export declare const CONTRACT_MAJOR = 3;
|
|
9
9
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
* The major is the compatibility line: a Shop package built against another
|
|
5
5
|
* major never meets this runtime, and a major bump is an announced event.
|
|
6
6
|
*/
|
|
7
|
-
export const CONTRACT_VERSION = '3.
|
|
7
|
+
export const CONTRACT_VERSION = '3.2.0';
|
|
8
8
|
export const CONTRACT_MAJOR = 3;
|
|
9
9
|
//# sourceMappingURL=version.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shoplix-ai/block-kit",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "The renderer contract every Block Type renderer is written against: what a renderer receives, how a Block Type is registered with its owner, the closed capability set, and the small helpers renderers share. Contract only, no renderers.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"access": "public"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@shoplix-ai/sdui-schema": "1.
|
|
29
|
+
"@shoplix-ai/sdui-schema": "1.10.0"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
32
|
"react": ">=19.0.0"
|