@monetize.software/sdk 3.0.0-alpha.4 → 3.0.0-alpha.5

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.
Files changed (128) hide show
  1. package/dist/chunks/PaywallUI-BD5hRY2P.js +26 -0
  2. package/dist/chunks/PaywallUI-BD5hRY2P.js.map +1 -0
  3. package/dist/chunks/PaywallUI-D7lp-bC5.js +3206 -0
  4. package/dist/chunks/PaywallUI-D7lp-bC5.js.map +1 -0
  5. package/dist/chunks/ar-BCHXVoE2.js +114 -0
  6. package/dist/chunks/ar-BCHXVoE2.js.map +1 -0
  7. package/dist/chunks/ar-CsJNZJSr.js +2 -0
  8. package/dist/chunks/ar-CsJNZJSr.js.map +1 -0
  9. package/dist/chunks/cs-B5NqpTW_.js +110 -0
  10. package/dist/chunks/cs-B5NqpTW_.js.map +1 -0
  11. package/dist/chunks/cs-BydWUC0e.js +2 -0
  12. package/dist/chunks/cs-BydWUC0e.js.map +1 -0
  13. package/dist/chunks/da-BJrGZ3LD.js +110 -0
  14. package/dist/chunks/da-BJrGZ3LD.js.map +1 -0
  15. package/dist/chunks/da-DNhiAQnh.js +2 -0
  16. package/dist/chunks/da-DNhiAQnh.js.map +1 -0
  17. package/dist/chunks/de-H8ztFOie.js +2 -0
  18. package/dist/chunks/de-H8ztFOie.js.map +1 -0
  19. package/dist/chunks/de-aepBKwsb.js +130 -0
  20. package/dist/chunks/de-aepBKwsb.js.map +1 -0
  21. package/dist/chunks/el-DRfoadtI.js +2 -0
  22. package/dist/chunks/el-DRfoadtI.js.map +1 -0
  23. package/dist/chunks/el-DTLQoX2D.js +114 -0
  24. package/dist/chunks/el-DTLQoX2D.js.map +1 -0
  25. package/dist/chunks/es-CLutF-D_.js +130 -0
  26. package/dist/chunks/es-CLutF-D_.js.map +1 -0
  27. package/dist/chunks/es-GlaYesNR.js +2 -0
  28. package/dist/chunks/es-GlaYesNR.js.map +1 -0
  29. package/dist/chunks/fi-BIHFyScH.js +2 -0
  30. package/dist/chunks/fi-BIHFyScH.js.map +1 -0
  31. package/dist/chunks/fi-DZ4csxqk.js +110 -0
  32. package/dist/chunks/fi-DZ4csxqk.js.map +1 -0
  33. package/dist/chunks/fr-BtZILUNZ.js +2 -0
  34. package/dist/chunks/fr-BtZILUNZ.js.map +1 -0
  35. package/dist/chunks/fr-jJU1SSpj.js +130 -0
  36. package/dist/chunks/fr-jJU1SSpj.js.map +1 -0
  37. package/dist/chunks/he-D9obGPNj.js +114 -0
  38. package/dist/chunks/he-D9obGPNj.js.map +1 -0
  39. package/dist/chunks/he-vSDRE4Nn.js +2 -0
  40. package/dist/chunks/he-vSDRE4Nn.js.map +1 -0
  41. package/dist/chunks/hi-B90FsnP6.js +2 -0
  42. package/dist/chunks/hi-B90FsnP6.js.map +1 -0
  43. package/dist/chunks/hi-pM8SQwZ3.js +114 -0
  44. package/dist/chunks/hi-pM8SQwZ3.js.map +1 -0
  45. package/dist/chunks/hu-DWVFODsS.js +2 -0
  46. package/dist/chunks/hu-DWVFODsS.js.map +1 -0
  47. package/dist/chunks/hu-E0m9WgbD.js +110 -0
  48. package/dist/chunks/hu-E0m9WgbD.js.map +1 -0
  49. package/dist/chunks/id-C6poPvby.js +110 -0
  50. package/dist/chunks/id-C6poPvby.js.map +1 -0
  51. package/dist/chunks/id-Ce2gzMVT.js +2 -0
  52. package/dist/chunks/id-Ce2gzMVT.js.map +1 -0
  53. package/dist/chunks/it-B2RSFyVd.js +130 -0
  54. package/dist/chunks/it-B2RSFyVd.js.map +1 -0
  55. package/dist/chunks/it-u-Gu44bl.js +2 -0
  56. package/dist/chunks/it-u-Gu44bl.js.map +1 -0
  57. package/dist/chunks/ja-CM-VgVG6.js +134 -0
  58. package/dist/chunks/ja-CM-VgVG6.js.map +1 -0
  59. package/dist/chunks/ja-CQy8RaRa.js +2 -0
  60. package/dist/chunks/ja-CQy8RaRa.js.map +1 -0
  61. package/dist/chunks/ko-BRnb7vJ7.js +2 -0
  62. package/dist/chunks/ko-BRnb7vJ7.js.map +1 -0
  63. package/dist/chunks/ko-C451fA21.js +134 -0
  64. package/dist/chunks/ko-C451fA21.js.map +1 -0
  65. package/dist/chunks/nl-CJelco6J.js +2 -0
  66. package/dist/chunks/nl-CJelco6J.js.map +1 -0
  67. package/dist/chunks/nl-DzQfJPo2.js +130 -0
  68. package/dist/chunks/nl-DzQfJPo2.js.map +1 -0
  69. package/dist/chunks/no-B51be8KT.js +110 -0
  70. package/dist/chunks/no-B51be8KT.js.map +1 -0
  71. package/dist/chunks/no-BwTjSZ4K.js +2 -0
  72. package/dist/chunks/no-BwTjSZ4K.js.map +1 -0
  73. package/dist/chunks/pl-5rTEkvfY.js +110 -0
  74. package/dist/chunks/pl-5rTEkvfY.js.map +1 -0
  75. package/dist/chunks/pl-kO82vcjb.js +2 -0
  76. package/dist/chunks/pl-kO82vcjb.js.map +1 -0
  77. package/dist/chunks/pt-CsJzaSjg.js +2 -0
  78. package/dist/chunks/pt-CsJzaSjg.js.map +1 -0
  79. package/dist/chunks/pt-JwqffZ9u.js +130 -0
  80. package/dist/chunks/pt-JwqffZ9u.js.map +1 -0
  81. package/dist/chunks/ro-BE_wJ1td.js +110 -0
  82. package/dist/chunks/ro-BE_wJ1td.js.map +1 -0
  83. package/dist/chunks/ro-ue15Ina4.js +2 -0
  84. package/dist/chunks/ro-ue15Ina4.js.map +1 -0
  85. package/dist/chunks/ru-B1iMOhX0.js +2 -0
  86. package/dist/chunks/ru-B1iMOhX0.js.map +1 -0
  87. package/dist/chunks/ru-BviATvLb.js +124 -0
  88. package/dist/chunks/ru-BviATvLb.js.map +1 -0
  89. package/dist/chunks/sv-CkNYpUVy.js +2 -0
  90. package/dist/chunks/sv-CkNYpUVy.js.map +1 -0
  91. package/dist/chunks/sv-DabGF9WL.js +110 -0
  92. package/dist/chunks/sv-DabGF9WL.js.map +1 -0
  93. package/dist/chunks/th-BiF-bNo0.js +114 -0
  94. package/dist/chunks/th-BiF-bNo0.js.map +1 -0
  95. package/dist/chunks/th-Cu80HK4y.js +2 -0
  96. package/dist/chunks/th-Cu80HK4y.js.map +1 -0
  97. package/dist/chunks/tr-B7c0afXV.js +2 -0
  98. package/dist/chunks/tr-B7c0afXV.js.map +1 -0
  99. package/dist/chunks/tr-xZuly8X8.js +110 -0
  100. package/dist/chunks/tr-xZuly8X8.js.map +1 -0
  101. package/dist/chunks/uk-BO106B0H.js +2 -0
  102. package/dist/chunks/uk-BO106B0H.js.map +1 -0
  103. package/dist/chunks/uk-KlkAaHuy.js +124 -0
  104. package/dist/chunks/uk-KlkAaHuy.js.map +1 -0
  105. package/dist/chunks/vi-BVCeumNE.js +110 -0
  106. package/dist/chunks/vi-BVCeumNE.js.map +1 -0
  107. package/dist/chunks/vi-CZ6ow40D.js +2 -0
  108. package/dist/chunks/vi-CZ6ow40D.js.map +1 -0
  109. package/dist/chunks/zh-BhP80WI1.js +2 -0
  110. package/dist/chunks/zh-BhP80WI1.js.map +1 -0
  111. package/dist/chunks/zh-C_ghwmqi.js +134 -0
  112. package/dist/chunks/zh-C_ghwmqi.js.map +1 -0
  113. package/dist/core.cjs +1 -1
  114. package/dist/core.cjs.map +1 -1
  115. package/dist/core.d.ts +81 -5
  116. package/dist/core.js +209 -171
  117. package/dist/core.js.map +1 -1
  118. package/dist/index.cjs +1 -1
  119. package/dist/index.d.ts +81 -5
  120. package/dist/index.js +1 -1
  121. package/dist/ui.cjs +1 -1
  122. package/dist/ui.d.ts +81 -5
  123. package/dist/ui.js +1 -1
  124. package/package.json +1 -1
  125. package/dist/chunks/PaywallUI-2bwf2scV.js +0 -2277
  126. package/dist/chunks/PaywallUI-2bwf2scV.js.map +0 -1
  127. package/dist/chunks/PaywallUI-Bu51__PT.js +0 -26
  128. package/dist/chunks/PaywallUI-Bu51__PT.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./core.cjs"),r=require("./chunks/PaywallUI-Bu51__PT.js");exports.ApiClient=e.ApiClient;exports.ApiGatewayClient=e.ApiGatewayClient;exports.AuthClient=e.AuthClient;exports.BillingClient=e.BillingClient;exports.EventTracker=e.EventTracker;exports.PaywallError=e.PaywallError;exports.QuotaExceededError=e.QuotaExceededError;exports.SDK_VERSION=e.SDK_VERSION;exports.STORAGE_KEYS=e.STORAGE_KEYS;exports.createStorage=e.createStorage;exports.ensureVisitorId=e.ensureVisitorId;exports.generateVisitorId=e.generateVisitorId;exports.PaywallUI=r.PaywallUI;exports.blockRegistry=r.blockRegistry;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./core.cjs"),r=require("./chunks/PaywallUI-BD5hRY2P.js");exports.ApiClient=e.ApiClient;exports.ApiGatewayClient=e.ApiGatewayClient;exports.AuthClient=e.AuthClient;exports.BillingClient=e.BillingClient;exports.EventTracker=e.EventTracker;exports.PaywallError=e.PaywallError;exports.QuotaExceededError=e.QuotaExceededError;exports.SDK_VERSION=e.SDK_VERSION;exports.STORAGE_KEYS=e.STORAGE_KEYS;exports.createStorage=e.createStorage;exports.ensureVisitorId=e.ensureVisitorId;exports.generateVisitorId=e.generateVisitorId;exports.PaywallUI=r.PaywallUI;exports.blockRegistry=r.blockRegistry;
2
2
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.ts CHANGED
@@ -460,6 +460,18 @@ export declare class AuthClient {
460
460
  private readAnonRefreshToken;
461
461
  private writeAnonRefreshToken;
462
462
  private clearAnonRefreshToken;
463
+ /**
464
+ * Last-used auth method + email — для UI бейджа "Last used" и pre-fill'а
465
+ * email-инпута. Storage paywall-scoped, поэтому переключение между
466
+ * пейволами на одном host'е не пересекает данные. Чтение всегда возвращает
467
+ * объект — отсутствующие поля = null. */
468
+ getLastLogin(): Promise<LastLogin | null>;
469
+ /** Запись method и email атомарно (для email/password flows — оба известны
470
+ * на момент signin/signup'а). OAuth-flows используют раздельные
471
+ * recordLastLoginMethod (до popup) и recordLastLoginEmail (после exchange). */
472
+ private recordLastLogin;
473
+ private recordLastLoginMethod;
474
+ private recordLastLoginEmail;
463
475
  /**
464
476
  * Читает stable visitor_id из storage если он там уже есть. НЕ генерит:
465
477
  * AuthClient может быть инстанцирован раньше BillingClient, а синтетический
@@ -982,6 +994,18 @@ export declare interface Identity {
982
994
  anonymousId?: string;
983
995
  }
984
996
 
997
+ export declare interface LastLogin {
998
+ method: LastLoginMethod;
999
+ email: string | null;
1000
+ }
1001
+
1002
+ /** Метод, которым юзер залогинился в последний раз на этом пейволе.
1003
+ * Хранится per-paywall в storage и используется UI чтобы:
1004
+ * - предзаполнить email-инпут last-known email'ом;
1005
+ * - подсветить ту же OAuth-кнопку / email-форму бейджем "Last used".
1006
+ * `email` — email/password forms (signin или signup → confirm). */
1007
+ export declare type LastLoginMethod = OAuthProvider | 'email';
1008
+
985
1009
  export declare interface Layout {
986
1010
  type: 'modal';
987
1011
  blocks: LayoutBlock[];
@@ -997,9 +1021,13 @@ export declare type LayoutBlock = {
997
1021
  } | {
998
1022
  type: 'price_grid';
999
1023
  priceIds?: string[];
1000
- /** Раскладка карточек цен. `vertical` (default) — стек сверху вниз;
1001
- * `horizontal` — ряд side-by-side. v2-аналог `view: 'default' | 'telegram'`. */
1002
- view?: 'vertical' | 'horizontal';
1024
+ /** Раскладка карточек цен:
1025
+ * - `vertical` (default) стек карточек сверху вниз;
1026
+ * - `compact` компактный список (одна строка на цену, без карточки,
1027
+ * с разделителем); v2-аналог `view: 'telegram'`;
1028
+ * - `horizontal` — несколько карточек рядом в ряд; v2-only с момента
1029
+ * SDK 3.0 (legacy не показывает выбор этой опции в админке). */
1030
+ view?: 'vertical' | 'compact' | 'horizontal';
1003
1031
  /** ID цены, которая помечается лейблом «популярный план». v2-аналог
1004
1032
  * пары `price_label_id` + `price_label`. */
1005
1033
  popular_price_id?: string;
@@ -1008,7 +1036,10 @@ export declare type LayoutBlock = {
1008
1036
  popular_label?: string;
1009
1037
  } | {
1010
1038
  type: 'cta_button';
1011
- label: string;
1039
+ /** Текст на кнопке. Если не задан — рендерер сам подберёт по
1040
+ * selected price'у и `trial_days`: "Start N-Day Free Trial",
1041
+ * "Get Lifetime Access", "Get Monthly Plan" и т.п. */
1042
+ label?: string;
1012
1043
  action: 'checkout' | 'close';
1013
1044
  priceId?: string;
1014
1045
  } | {
@@ -1027,8 +1058,23 @@ export declare type LayoutBlock = {
1027
1058
  /** Скрывать панель, если юзер уже залогинен. По умолчанию true.
1028
1059
  * false — показываем "Signed in as ... [Sign out]" даже после логина. */
1029
1060
  hide_when_authenticated?: boolean;
1030
- /** Заголовок над формой (h2). Если опущензаголовок не рендерится. */
1061
+ /** Кастомный заголовок над формой. Если заданотображается вместо
1062
+ * дефолтного (определяется по mode'у — "Welcome back!" / "Welcome!" /
1063
+ * "Forgot password?" / ...). Без `submit_label` также используется как
1064
+ * submit-лейбл для signin (например `heading="Restore Purchases"` →
1065
+ * submit тоже "Restore Purchases"). Длинные heading (типа "Войдите,
1066
+ * чтобы продолжить покупку") в кнопку влезают плохо — задай
1067
+ * `submit_label` отдельно. */
1031
1068
  heading?: string;
1069
+ /** Подпись под заголовком. Если опущен — подставляется default-текст
1070
+ * для текущего mode'а. Передай пустую строку чтобы скрыть подпись. */
1071
+ subheading?: string;
1072
+ /** Явный текст submit-кнопки. Имеет приоритет над heading-эхо. Нужен
1073
+ * для интентов с длинным descriptive heading'ом (preauth: "Войдите,
1074
+ * чтобы продолжить покупку" — кнопка только "Войти"). Для коротких
1075
+ * action-headings (restore: "Restore Purchases") опускай — эхо
1076
+ * даёт правильный UX. */
1077
+ submit_label?: string;
1032
1078
  } | {
1033
1079
  /** Список фич/преимуществ продукта. v2-аналог `features_list` + `features_view`.
1034
1080
  * До 5 элементов — рендерим как чек-лист с заголовком и описанием. */
@@ -1065,6 +1111,22 @@ export declare type LayoutBlock = {
1065
1111
  /** Иконка слева от заголовка. По умолчанию `dollar_shield` —
1066
1112
  * зелёный shield с долларом (legacy-вид). `none` — без иконки. */
1067
1113
  icon?: 'dollar_shield' | 'none';
1114
+ } | {
1115
+ /** Urgency-баннер с countdown'ом до конца offer'а. Берёт первый offer
1116
+ * из `bootstrap.offers` с валидным `expires_at` или `duration_minutes`.
1117
+ * Авто-скрывается по истечении, чтобы не показывать "0d 0h 0m 0s".
1118
+ * Размещение — обычно первый блок в layout (над heading). */
1119
+ type: 'offer_banner';
1120
+ /** ID конкретного offer'а из bootstrap.offers. Если не задано — берётся
1121
+ * первый offer с активным таймером. */
1122
+ offer_id?: string;
1123
+ /** Текст слева от countdown'а. Если опущен — берётся `offer.label`,
1124
+ * иначе fallback "Limited-time offer". К нему дописывается процент:
1125
+ * "{title} {discount_percent}%" если discount задан. */
1126
+ title?: string;
1127
+ /** В превью админки — игнорировать expired-state, всё равно показывать
1128
+ * banner с нулями. Прод-режим — false (banner исчезает). */
1129
+ force?: boolean;
1068
1130
  };
1069
1131
 
1070
1132
  /** Локализационные оверрайды для одного языка. Накатываются поверх дефолтного
@@ -1256,7 +1318,15 @@ declare interface PaywallEventPayloads {
1256
1318
  export declare interface PaywallOffer {
1257
1319
  id: string;
1258
1320
  discount_percent: number | null;
1321
+ /** Абсолютная expiration date (ISO 8601). Если задана — countdown отсчитывает
1322
+ * до этого момента, по истечении offer считается истёкшим. */
1259
1323
  expires_at: string | null;
1324
+ /** Относительный таймер: сколько минут offer живёт **от первого просмотра
1325
+ * пейвола** данным юзером. Старт хранится в clientStorage под ключом
1326
+ * `pw-offer-{id}-start`, по истечении — auto-cleanup. Используется, когда
1327
+ * бэк хочет показывать "remaining time" без жёсткой server-time, а считать
1328
+ * относительно сессии юзера. expires_at имеет приоритет если задано. */
1329
+ duration_minutes?: number | null;
1260
1330
  price_id: string | null;
1261
1331
  label?: string | null;
1262
1332
  }
@@ -1648,6 +1718,12 @@ export declare interface PaywallUser {
1648
1718
  started_at: string | null;
1649
1719
  expires_at: string | null;
1650
1720
  } | null;
1721
+ /** Был ли у юзера хотя бы один trial по этому пейволу когда-либо (включая
1722
+ * истёкшие и отменённые). Anti-abuse флаг для UI: CtaButton скрывает
1723
+ * "Start N-Day Free Trial" если true. Серверный enforcement в
1724
+ * `/start-checkout` дублирует — даже если UI обмануть, бэк не отдаст
1725
+ * trial_days в Stripe/Paddle. */
1726
+ had_previous_trial: boolean;
1651
1727
  }
1652
1728
 
1653
1729
  export declare interface PaywallUserPurchase {
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ApiClient as t, ApiGatewayClient as a, AuthClient as i, BillingClient as l, EventTracker as o, PaywallError as n, QuotaExceededError as E, SDK_VERSION as s, STORAGE_KEYS as S, createStorage as c, ensureVisitorId as d, generateVisitorId as g } from "./core.js";
2
- import { P as y, b as A } from "./chunks/PaywallUI-2bwf2scV.js";
2
+ import { P as y, b as A } from "./chunks/PaywallUI-D7lp-bC5.js";
3
3
  export {
4
4
  t as ApiClient,
5
5
  a as ApiGatewayClient,
package/dist/ui.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./chunks/PaywallUI-Bu51__PT.js");exports.PaywallUI=e.PaywallUI;exports.blockRegistry=e.blockRegistry;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./chunks/PaywallUI-BD5hRY2P.js");exports.PaywallUI=e.PaywallUI;exports.blockRegistry=e.blockRegistry;
2
2
  //# sourceMappingURL=ui.cjs.map
package/dist/ui.d.ts CHANGED
@@ -446,6 +446,18 @@ declare class AuthClient {
446
446
  private readAnonRefreshToken;
447
447
  private writeAnonRefreshToken;
448
448
  private clearAnonRefreshToken;
449
+ /**
450
+ * Last-used auth method + email — для UI бейджа "Last used" и pre-fill'а
451
+ * email-инпута. Storage paywall-scoped, поэтому переключение между
452
+ * пейволами на одном host'е не пересекает данные. Чтение всегда возвращает
453
+ * объект — отсутствующие поля = null. */
454
+ getLastLogin(): Promise<LastLogin | null>;
455
+ /** Запись method и email атомарно (для email/password flows — оба известны
456
+ * на момент signin/signup'а). OAuth-flows используют раздельные
457
+ * recordLastLoginMethod (до popup) и recordLastLoginEmail (после exchange). */
458
+ private recordLastLogin;
459
+ private recordLastLoginMethod;
460
+ private recordLastLoginEmail;
449
461
  /**
450
462
  * Читает stable visitor_id из storage если он там уже есть. НЕ генерит:
451
463
  * AuthClient может быть инстанцирован раньше BillingClient, а синтетический
@@ -921,6 +933,18 @@ declare interface Identity {
921
933
  anonymousId?: string;
922
934
  }
923
935
 
936
+ declare interface LastLogin {
937
+ method: LastLoginMethod;
938
+ email: string | null;
939
+ }
940
+
941
+ /** Метод, которым юзер залогинился в последний раз на этом пейволе.
942
+ * Хранится per-paywall в storage и используется UI чтобы:
943
+ * - предзаполнить email-инпут last-known email'ом;
944
+ * - подсветить ту же OAuth-кнопку / email-форму бейджем "Last used".
945
+ * `email` — email/password forms (signin или signup → confirm). */
946
+ declare type LastLoginMethod = OAuthProvider | 'email';
947
+
924
948
  declare interface Layout {
925
949
  type: 'modal';
926
950
  blocks: LayoutBlock[];
@@ -936,9 +960,13 @@ declare type LayoutBlock = {
936
960
  } | {
937
961
  type: 'price_grid';
938
962
  priceIds?: string[];
939
- /** Раскладка карточек цен. `vertical` (default) — стек сверху вниз;
940
- * `horizontal` — ряд side-by-side. v2-аналог `view: 'default' | 'telegram'`. */
941
- view?: 'vertical' | 'horizontal';
963
+ /** Раскладка карточек цен:
964
+ * - `vertical` (default) стек карточек сверху вниз;
965
+ * - `compact` компактный список (одна строка на цену, без карточки,
966
+ * с разделителем); v2-аналог `view: 'telegram'`;
967
+ * - `horizontal` — несколько карточек рядом в ряд; v2-only с момента
968
+ * SDK 3.0 (legacy не показывает выбор этой опции в админке). */
969
+ view?: 'vertical' | 'compact' | 'horizontal';
942
970
  /** ID цены, которая помечается лейблом «популярный план». v2-аналог
943
971
  * пары `price_label_id` + `price_label`. */
944
972
  popular_price_id?: string;
@@ -947,7 +975,10 @@ declare type LayoutBlock = {
947
975
  popular_label?: string;
948
976
  } | {
949
977
  type: 'cta_button';
950
- label: string;
978
+ /** Текст на кнопке. Если не задан — рендерер сам подберёт по
979
+ * selected price'у и `trial_days`: "Start N-Day Free Trial",
980
+ * "Get Lifetime Access", "Get Monthly Plan" и т.п. */
981
+ label?: string;
951
982
  action: 'checkout' | 'close';
952
983
  priceId?: string;
953
984
  } | {
@@ -966,8 +997,23 @@ declare type LayoutBlock = {
966
997
  /** Скрывать панель, если юзер уже залогинен. По умолчанию true.
967
998
  * false — показываем "Signed in as ... [Sign out]" даже после логина. */
968
999
  hide_when_authenticated?: boolean;
969
- /** Заголовок над формой (h2). Если опущензаголовок не рендерится. */
1000
+ /** Кастомный заголовок над формой. Если заданотображается вместо
1001
+ * дефолтного (определяется по mode'у — "Welcome back!" / "Welcome!" /
1002
+ * "Forgot password?" / ...). Без `submit_label` также используется как
1003
+ * submit-лейбл для signin (например `heading="Restore Purchases"` →
1004
+ * submit тоже "Restore Purchases"). Длинные heading (типа "Войдите,
1005
+ * чтобы продолжить покупку") в кнопку влезают плохо — задай
1006
+ * `submit_label` отдельно. */
970
1007
  heading?: string;
1008
+ /** Подпись под заголовком. Если опущен — подставляется default-текст
1009
+ * для текущего mode'а. Передай пустую строку чтобы скрыть подпись. */
1010
+ subheading?: string;
1011
+ /** Явный текст submit-кнопки. Имеет приоритет над heading-эхо. Нужен
1012
+ * для интентов с длинным descriptive heading'ом (preauth: "Войдите,
1013
+ * чтобы продолжить покупку" — кнопка только "Войти"). Для коротких
1014
+ * action-headings (restore: "Restore Purchases") опускай — эхо
1015
+ * даёт правильный UX. */
1016
+ submit_label?: string;
971
1017
  } | {
972
1018
  /** Список фич/преимуществ продукта. v2-аналог `features_list` + `features_view`.
973
1019
  * До 5 элементов — рендерим как чек-лист с заголовком и описанием. */
@@ -1004,6 +1050,22 @@ declare type LayoutBlock = {
1004
1050
  /** Иконка слева от заголовка. По умолчанию `dollar_shield` —
1005
1051
  * зелёный shield с долларом (legacy-вид). `none` — без иконки. */
1006
1052
  icon?: 'dollar_shield' | 'none';
1053
+ } | {
1054
+ /** Urgency-баннер с countdown'ом до конца offer'а. Берёт первый offer
1055
+ * из `bootstrap.offers` с валидным `expires_at` или `duration_minutes`.
1056
+ * Авто-скрывается по истечении, чтобы не показывать "0d 0h 0m 0s".
1057
+ * Размещение — обычно первый блок в layout (над heading). */
1058
+ type: 'offer_banner';
1059
+ /** ID конкретного offer'а из bootstrap.offers. Если не задано — берётся
1060
+ * первый offer с активным таймером. */
1061
+ offer_id?: string;
1062
+ /** Текст слева от countdown'а. Если опущен — берётся `offer.label`,
1063
+ * иначе fallback "Limited-time offer". К нему дописывается процент:
1064
+ * "{title} {discount_percent}%" если discount задан. */
1065
+ title?: string;
1066
+ /** В превью админки — игнорировать expired-state, всё равно показывать
1067
+ * banner с нулями. Прод-режим — false (banner исчезает). */
1068
+ force?: boolean;
1007
1069
  };
1008
1070
 
1009
1071
  /** Локализационные оверрайды для одного языка. Накатываются поверх дефолтного
@@ -1195,7 +1257,15 @@ declare interface PaywallEventPayloads {
1195
1257
  declare interface PaywallOffer {
1196
1258
  id: string;
1197
1259
  discount_percent: number | null;
1260
+ /** Абсолютная expiration date (ISO 8601). Если задана — countdown отсчитывает
1261
+ * до этого момента, по истечении offer считается истёкшим. */
1198
1262
  expires_at: string | null;
1263
+ /** Относительный таймер: сколько минут offer живёт **от первого просмотра
1264
+ * пейвола** данным юзером. Старт хранится в clientStorage под ключом
1265
+ * `pw-offer-{id}-start`, по истечении — auto-cleanup. Используется, когда
1266
+ * бэк хочет показывать "remaining time" без жёсткой server-time, а считать
1267
+ * относительно сессии юзера. expires_at имеет приоритет если задано. */
1268
+ duration_minutes?: number | null;
1199
1269
  price_id: string | null;
1200
1270
  label?: string | null;
1201
1271
  }
@@ -1587,6 +1657,12 @@ declare interface PaywallUser {
1587
1657
  started_at: string | null;
1588
1658
  expires_at: string | null;
1589
1659
  } | null;
1660
+ /** Был ли у юзера хотя бы один trial по этому пейволу когда-либо (включая
1661
+ * истёкшие и отменённые). Anti-abuse флаг для UI: CtaButton скрывает
1662
+ * "Start N-Day Free Trial" если true. Серверный enforcement в
1663
+ * `/start-checkout` дублирует — даже если UI обмануть, бэк не отдаст
1664
+ * trial_days в Stripe/Paddle. */
1665
+ had_previous_trial: boolean;
1590
1666
  }
1591
1667
 
1592
1668
  declare interface PaywallUserPurchase {
package/dist/ui.js CHANGED
@@ -1,4 +1,4 @@
1
- import { P as o, b as r } from "./chunks/PaywallUI-2bwf2scV.js";
1
+ import { P as o, b as r } from "./chunks/PaywallUI-D7lp-bC5.js";
2
2
  export {
3
3
  o as PaywallUI,
4
4
  r as blockRegistry
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monetize.software/sdk",
3
- "version": "3.0.0-alpha.4",
3
+ "version": "3.0.0-alpha.5",
4
4
  "description": "Monetize SDK — bundled billing client and paywall render engine for web and Chrome extensions",
5
5
  "type": "module",
6
6
  "sideEffects": false,