@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 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), and
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';
@@ -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;AACzC,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"}
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;AACzC,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"}
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
@@ -1 +1 @@
1
- {"version":3,"file":"money.d.ts","sourceRoot":"","sources":["../src/money.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAUf"}
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;QAAE,OAAO,IAAI,CAAC;IAC9E,IAAI,CAAC;QACH,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC,MAAM,CAC1F,KAAK,CACN,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,MAAM,IAAI,YAAY,EAAE,CAAC;IACrC,CAAC;AACH,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.1.0";
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.1.0';
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.1.0",
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.9.0"
29
+ "@shoplix-ai/sdui-schema": "1.10.0"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "react": ">=19.0.0"