pricing-renderer 0.1.0 → 0.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.
Files changed (175) hide show
  1. package/CHANGELOG.md +133 -0
  2. package/README.md +142 -25
  3. package/THIRD_PARTY_NOTICES.md +84 -6
  4. package/custom-elements.json +233 -3
  5. package/dist/core/apply-selection.d.ts +8 -0
  6. package/dist/core/apply-selection.d.ts.map +1 -0
  7. package/dist/core/apply-selection.js +76 -0
  8. package/dist/core/apply-selection.js.map +1 -0
  9. package/dist/core/breakdown.d.ts +13 -0
  10. package/dist/core/breakdown.d.ts.map +1 -0
  11. package/dist/core/breakdown.js +56 -0
  12. package/dist/core/breakdown.js.map +1 -0
  13. package/dist/core/compare-sides.d.ts +16 -0
  14. package/dist/core/compare-sides.d.ts.map +1 -0
  15. package/dist/core/compare-sides.js +73 -0
  16. package/dist/core/compare-sides.js.map +1 -0
  17. package/dist/core/compare-values.d.ts +13 -0
  18. package/dist/core/compare-values.d.ts.map +1 -0
  19. package/dist/core/compare-values.js +100 -0
  20. package/dist/core/compare-values.js.map +1 -0
  21. package/dist/core/compare.d.ts +7 -0
  22. package/dist/core/compare.d.ts.map +1 -0
  23. package/dist/core/compare.js +301 -0
  24. package/dist/core/compare.js.map +1 -0
  25. package/dist/core/expression.js +2 -2
  26. package/dist/core/expression.js.map +1 -1
  27. package/dist/core/i18n.d.ts.map +1 -1
  28. package/dist/core/i18n.js +136 -2
  29. package/dist/core/i18n.js.map +1 -1
  30. package/dist/core/index.d.ts +9 -2
  31. package/dist/core/index.d.ts.map +1 -1
  32. package/dist/core/index.js +6 -1
  33. package/dist/core/index.js.map +1 -1
  34. package/dist/core/normalize.d.ts.map +1 -1
  35. package/dist/core/normalize.js +70 -9
  36. package/dist/core/normalize.js.map +1 -1
  37. package/dist/core/plan-relation.d.ts +8 -0
  38. package/dist/core/plan-relation.d.ts.map +1 -0
  39. package/dist/core/plan-relation.js +15 -0
  40. package/dist/core/plan-relation.js.map +1 -0
  41. package/dist/core/price-stabilizer.d.ts +3 -0
  42. package/dist/core/price-stabilizer.d.ts.map +1 -0
  43. package/dist/core/price-stabilizer.js +73 -0
  44. package/dist/core/price-stabilizer.js.map +1 -0
  45. package/dist/core/resolve.d.ts +7 -1
  46. package/dist/core/resolve.d.ts.map +1 -1
  47. package/dist/core/resolve.js +66 -21
  48. package/dist/core/resolve.js.map +1 -1
  49. package/dist/core/search-params.d.ts +15 -0
  50. package/dist/core/search-params.d.ts.map +1 -0
  51. package/dist/core/search-params.js +175 -0
  52. package/dist/core/search-params.js.map +1 -0
  53. package/dist/core/selection-change.d.ts +10 -0
  54. package/dist/core/selection-change.d.ts.map +1 -0
  55. package/dist/core/selection-change.js +124 -0
  56. package/dist/core/selection-change.js.map +1 -0
  57. package/dist/core/types.d.ts +209 -0
  58. package/dist/core/types.d.ts.map +1 -1
  59. package/dist/core/units.d.ts +13 -0
  60. package/dist/core/units.d.ts.map +1 -0
  61. package/dist/core/units.js +84 -0
  62. package/dist/core/units.js.map +1 -0
  63. package/dist/core/utils.d.ts.map +1 -1
  64. package/dist/core/utils.js +91 -32
  65. package/dist/core/utils.js.map +1 -1
  66. package/dist/core/view-model.d.ts +3 -1
  67. package/dist/core/view-model.d.ts.map +1 -1
  68. package/dist/core/view-model.js +113 -7
  69. package/dist/core/view-model.js.map +1 -1
  70. package/dist/element/change-review-define.d.ts +4 -0
  71. package/dist/element/change-review-define.d.ts.map +1 -0
  72. package/dist/element/change-review-define.js +17 -0
  73. package/dist/element/change-review-define.js.map +1 -0
  74. package/dist/element/change-review-element.d.ts +53 -0
  75. package/dist/element/change-review-element.d.ts.map +1 -0
  76. package/dist/element/change-review-element.js +104 -0
  77. package/dist/element/change-review-element.js.map +1 -0
  78. package/dist/element/change-review-events.d.ts +10 -0
  79. package/dist/element/change-review-events.d.ts.map +1 -0
  80. package/dist/element/change-review-events.js +2 -0
  81. package/dist/element/change-review-events.js.map +1 -0
  82. package/dist/element/change-review-renderers.d.ts +23 -0
  83. package/dist/element/change-review-renderers.d.ts.map +1 -0
  84. package/dist/element/change-review-renderers.js +391 -0
  85. package/dist/element/change-review-renderers.js.map +1 -0
  86. package/dist/element/cta.d.ts +45 -0
  87. package/dist/element/cta.d.ts.map +1 -0
  88. package/dist/element/cta.js +90 -0
  89. package/dist/element/cta.js.map +1 -0
  90. package/dist/element/current-selection.d.ts +13 -0
  91. package/dist/element/current-selection.d.ts.map +1 -0
  92. package/dist/element/current-selection.js +57 -0
  93. package/dist/element/current-selection.js.map +1 -0
  94. package/dist/element/define-change-review.d.ts +2 -0
  95. package/dist/element/define-change-review.d.ts.map +1 -0
  96. package/dist/element/define-change-review.js +7 -0
  97. package/dist/element/define-change-review.js.map +1 -0
  98. package/dist/element/events.d.ts +32 -6
  99. package/dist/element/events.d.ts.map +1 -1
  100. package/dist/element/hide-sections.d.ts +6 -0
  101. package/dist/element/hide-sections.d.ts.map +1 -0
  102. package/dist/element/hide-sections.js +26 -0
  103. package/dist/element/hide-sections.js.map +1 -0
  104. package/dist/element/index.d.ts +8 -1
  105. package/dist/element/index.d.ts.map +1 -1
  106. package/dist/element/index.js +3 -0
  107. package/dist/element/index.js.map +1 -1
  108. package/dist/element/pricing-renderer-element.d.ts +95 -7
  109. package/dist/element/pricing-renderer-element.d.ts.map +1 -1
  110. package/dist/element/pricing-renderer-element.js +563 -217
  111. package/dist/element/pricing-renderer-element.js.map +1 -1
  112. package/dist/element/renderers.d.ts +49 -4
  113. package/dist/element/renderers.d.ts.map +1 -1
  114. package/dist/element/renderers.js +795 -263
  115. package/dist/element/renderers.js.map +1 -1
  116. package/dist/element/same-input.d.ts +3 -0
  117. package/dist/element/same-input.d.ts.map +1 -0
  118. package/dist/element/same-input.js +56 -0
  119. package/dist/element/same-input.js.map +1 -0
  120. package/dist/react/headless.d.ts +9 -0
  121. package/dist/react/headless.d.ts.map +1 -0
  122. package/dist/react/headless.js +8 -0
  123. package/dist/react/headless.js.map +1 -0
  124. package/dist/react/index.d.ts +54 -4
  125. package/dist/react/index.d.ts.map +1 -1
  126. package/dist/react/index.js +156 -6
  127. package/dist/react/index.js.map +1 -1
  128. package/dist/react/provider.d.ts +17 -0
  129. package/dist/react/provider.d.ts.map +1 -0
  130. package/dist/react/provider.js +38 -0
  131. package/dist/react/provider.js.map +1 -0
  132. package/dist/react/selection-store.d.ts +51 -0
  133. package/dist/react/selection-store.d.ts.map +1 -0
  134. package/dist/react/selection-store.js +239 -0
  135. package/dist/react/selection-store.js.map +1 -0
  136. package/dist/react/slots-types.d.ts +38 -0
  137. package/dist/react/slots-types.d.ts.map +1 -0
  138. package/dist/react/slots-types.js +2 -0
  139. package/dist/react/slots-types.js.map +1 -0
  140. package/dist/react/slots.d.ts +40 -0
  141. package/dist/react/slots.d.ts.map +1 -0
  142. package/dist/react/slots.js +165 -0
  143. package/dist/react/slots.js.map +1 -0
  144. package/dist/react/use-pricing-selection.d.ts +10 -0
  145. package/dist/react/use-pricing-selection.d.ts.map +1 -0
  146. package/dist/react/use-pricing-selection.js +44 -0
  147. package/dist/react/use-pricing-selection.js.map +1 -0
  148. package/dist/react/use-pricing-source.d.ts +34 -0
  149. package/dist/react/use-pricing-source.d.ts.map +1 -0
  150. package/dist/react/use-pricing-source.js +186 -0
  151. package/dist/react/use-pricing-source.js.map +1 -0
  152. package/dist/react/use-renderer-state.d.ts +22 -0
  153. package/dist/react/use-renderer-state.d.ts.map +1 -0
  154. package/dist/react/use-renderer-state.js +112 -0
  155. package/dist/react/use-renderer-state.js.map +1 -0
  156. package/dist/space/index.d.ts +26 -0
  157. package/dist/space/index.d.ts.map +1 -0
  158. package/dist/space/index.js +71 -0
  159. package/dist/space/index.js.map +1 -0
  160. package/dist/styles/base.css +1030 -76
  161. package/dist/styles/theme-minimal.css +103 -0
  162. package/dist/styles/theme.css +22 -3
  163. package/dist/styles/tokens-shadcn.css +40 -0
  164. package/dist/yaml/index.d.ts +2 -0
  165. package/dist/yaml/index.d.ts.map +1 -1
  166. package/dist/yaml/index.js +1 -0
  167. package/dist/yaml/index.js.map +1 -1
  168. package/dist/yaml/load.d.ts.map +1 -1
  169. package/dist/yaml/load.js +106 -17
  170. package/dist/yaml/load.js.map +1 -1
  171. package/dist/yaml/source.d.ts +18 -0
  172. package/dist/yaml/source.d.ts.map +1 -0
  173. package/dist/yaml/source.js +46 -0
  174. package/dist/yaml/source.js.map +1 -0
  175. package/package.json +25 -13
@@ -0,0 +1,44 @@
1
+ 'use client';
2
+ import { useContext, useState, useSyncExternalStore } from 'react';
3
+ import { getPricingRendererConfig, mergePresentationOptions } from '../core/index.js';
4
+ import { PricingRendererContext } from './provider.js';
5
+ import { createSelectionStore } from './selection-store.js';
6
+ // Instance option, then the nearest provider, then the global configuration read at render time;
7
+ // `custom.pricingRenderer` is the lowest presentation layer and the view model applies it.
8
+ function resolveOptions(options, provider) {
9
+ const global = getPricingRendererConfig();
10
+ const presentation = mergePresentationOptions(mergePresentationOptions(mergePresentationOptions(global.presentation, provider?.config?.presentation), provider?.presentation), options.presentation);
11
+ const messages = provider?.messages === undefined
12
+ ? options.messages
13
+ : { ...provider.messages, ...options.messages };
14
+ return {
15
+ ...options,
16
+ locale: options.locale ?? provider?.config?.locale ?? global.locale,
17
+ variablesEnabled: options.variablesEnabled ?? provider?.config?.variablesEnabled ?? global.variablesEnabled,
18
+ messages,
19
+ presentation,
20
+ };
21
+ }
22
+ // A thin layer over a store of its own: the store gets its input during render, and
23
+ // `useSyncExternalStore` reads the cached snapshot, on the server too.
24
+ export function usePricingSelection(pricing, options = {}) {
25
+ const [store] = useState(createSelectionStore);
26
+ const provider = useContext(PricingRendererContext);
27
+ store.setInput(pricing, resolveOptions(options, provider));
28
+ const snapshot = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
29
+ return {
30
+ ...snapshot,
31
+ selectPlan: store.selectPlan,
32
+ toggleAddOn: store.toggleAddOn,
33
+ setVariable: store.setVariable,
34
+ setAddOnQuantity: store.setAddOnQuantity,
35
+ setBillingPeriod: store.setBillingPeriod,
36
+ resetVariables: store.resetVariables,
37
+ confirm: store.confirm,
38
+ cancel: store.cancel,
39
+ apply: store.apply,
40
+ relationOf: store.relationOf,
41
+ compareWithCurrent: store.compareWithCurrent,
42
+ };
43
+ }
44
+ //# sourceMappingURL=use-pricing-selection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-pricing-selection.js","sourceRoot":"","sources":["../../src/react/use-pricing-selection.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AACnE,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAEtF,OAAO,EAAE,sBAAsB,EAAoC,MAAM,eAAe,CAAC;AACzF,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAkB5D,iGAAiG;AACjG,2FAA2F;AAC3F,SAAS,cAAc,CACrB,OAAmC,EACnC,QAAiD;IAEjD,MAAM,MAAM,GAAG,wBAAwB,EAAE,CAAC;IAC1C,MAAM,YAAY,GAAG,wBAAwB,CAC3C,wBAAwB,CACtB,wBAAwB,CAAC,MAAM,CAAC,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAC7E,QAAQ,EAAE,YAAY,CACvB,EACD,OAAO,CAAC,YAAY,CACrB,CAAC;IACF,MAAM,QAAQ,GACZ,QAAQ,EAAE,QAAQ,KAAK,SAAS;QAC9B,CAAC,CAAC,OAAO,CAAC,QAAQ;QAClB,CAAC,CAAC,EAAE,GAAG,QAAQ,CAAC,QAAQ,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IACpD,OAAO;QACL,GAAG,OAAO;QACV,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,QAAQ,EAAE,MAAM,EAAE,MAAM,IAAI,MAAM,CAAC,MAAM;QACnE,gBAAgB,EACd,OAAO,CAAC,gBAAgB,IAAI,QAAQ,EAAE,MAAM,EAAE,gBAAgB,IAAI,MAAM,CAAC,gBAAgB;QAC3F,QAAQ;QACR,YAAY;KACb,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,uEAAuE;AACvE,MAAM,UAAU,mBAAmB,CACjC,OAAsC,EACtC,UAAsC,EAAE;IAExC,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,UAAU,CAAC,sBAAsB,CAAC,CAAC;IACpD,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IAC7F,OAAO;QACL,GAAG,QAAQ;QACX,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;KAC7C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { IPricingLike, NormalizedPricing, NormalizePricingOptions, PricingDiagnostic } from '../core/index.js';
2
+ import type { PricingLoader, PricingRequestOptions } from '../yaml/index.js';
3
+ export type PricingSourceStatus = 'loading' | 'ready' | 'error';
4
+ export interface PricingSourceSnapshot {
5
+ readonly status: PricingSourceStatus;
6
+ readonly pricing: NormalizedPricing | undefined;
7
+ readonly diagnostics: PricingDiagnostic[];
8
+ }
9
+ export interface PricingSourceStoreInput {
10
+ pricing?: IPricingLike | undefined;
11
+ yaml?: string | undefined;
12
+ src?: string | undefined;
13
+ }
14
+ export interface PricingSourceStoreOptions {
15
+ request?: PricingRequestOptions | undefined;
16
+ loadPricing?: PricingLoader | undefined;
17
+ normalizeOptions?: NormalizePricingOptions | undefined;
18
+ }
19
+ export interface SourceStore {
20
+ subscribe(listener: () => void): () => void;
21
+ getSnapshot(): PricingSourceSnapshot;
22
+ setInput(input: PricingSourceStoreInput, options: PricingSourceStoreOptions): void;
23
+ readonly inputVersion: number;
24
+ start(): void;
25
+ stop(): void;
26
+ reload(): void;
27
+ }
28
+ export type UsePricingSourceProps = PricingSourceStoreInput & PricingSourceStoreOptions;
29
+ export interface UsePricingSourceResult extends PricingSourceSnapshot {
30
+ reload: () => void;
31
+ }
32
+ export declare function createSourceStore(): SourceStore;
33
+ export declare function usePricingSource(props: UsePricingSourceProps): UsePricingSourceResult;
34
+ //# sourceMappingURL=use-pricing-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-pricing-source.d.ts","sourceRoot":"","sources":["../../src/react/use-pricing-source.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,EAElB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAG7E,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAEhE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAChD,QAAQ,CAAC,WAAW,EAAE,iBAAiB,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IACnC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,CAAC,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAC5C,WAAW,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACxC,gBAAgB,CAAC,EAAE,uBAAuB,GAAG,SAAS,CAAC;CACxD;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IAC5C,WAAW,IAAI,qBAAqB,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,uBAAuB,EAAE,OAAO,EAAE,yBAAyB,GAAG,IAAI,CAAC;IACnF,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,IAAI,CAAC;IACb,MAAM,IAAI,IAAI,CAAC;CAChB;AAED,MAAM,MAAM,qBAAqB,GAAG,uBAAuB,GAAG,yBAAyB,CAAC;AAExF,MAAM,WAAW,sBAAuB,SAAQ,qBAAqB;IACnE,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AA6CD,wBAAgB,iBAAiB,IAAI,WAAW,CAqI/C;AAMD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,sBAAsB,CAoBrF"}
@@ -0,0 +1,186 @@
1
+ 'use client';
2
+ import { useContext, useEffect, useState, useSyncExternalStore } from 'react';
3
+ import { sameInput } from '../element/same-input.js';
4
+ import { loadPricingSource } from '../yaml/index.js';
5
+ import { filterProviderRequest, PricingRendererContext } from './provider.js';
6
+ // A bound that is not usable falls back to its default, so a provider value of 0, NaN or Infinity
7
+ // cannot disable a limit. 2147483647 ms is the largest delay a timer honours.
8
+ function boundedRequest(request) {
9
+ const defaultMaxBytes = 2097152;
10
+ const defaultTimeoutMs = 15000;
11
+ const maxTimeoutMs = 2147483647;
12
+ const maxBytes = request?.maxBytes;
13
+ const timeoutMs = request?.timeoutMs;
14
+ return {
15
+ ...request,
16
+ maxBytes: typeof maxBytes === 'number' && Number.isFinite(maxBytes) && maxBytes > 0
17
+ ? maxBytes
18
+ : defaultMaxBytes,
19
+ timeoutMs: typeof timeoutMs === 'number' &&
20
+ Number.isFinite(timeoutMs) &&
21
+ timeoutMs > 0 &&
22
+ timeoutMs <= maxTimeoutMs
23
+ ? timeoutMs
24
+ : defaultTimeoutMs,
25
+ };
26
+ }
27
+ // pricing, request and normalizeOptions compare by structure; yaml, src and loadPricing by identity.
28
+ function sameHeld(left, right) {
29
+ return (sameInput(left.pricing, right.pricing) &&
30
+ left.yaml === right.yaml &&
31
+ left.src === right.src &&
32
+ left.loadPricing === right.loadPricing &&
33
+ sameInput(left.request, right.request) &&
34
+ sameInput(left.normalizeOptions, right.normalizeOptions));
35
+ }
36
+ function isRemote(held) {
37
+ return held.pricing === undefined && held.yaml === undefined && Boolean(held.src);
38
+ }
39
+ export function createSourceStore() {
40
+ const listeners = new Set();
41
+ let snapshot = { status: 'loading', pricing: undefined, diagnostics: [] };
42
+ let held;
43
+ let version = 0;
44
+ // Counts the loads and the input changes; a load applies only if no one has counted since it began.
45
+ let sequence = 0;
46
+ let loadState = 'idle';
47
+ let controller;
48
+ // True between start() and stop(): only then does a load have a cleanup that aborts it.
49
+ let active = false;
50
+ function notify() {
51
+ for (const listener of [...listeners])
52
+ listener();
53
+ }
54
+ function resultSnapshot(result) {
55
+ if (result.value !== undefined) {
56
+ return { status: 'ready', pricing: result.value, diagnostics: result.diagnostics };
57
+ }
58
+ return {
59
+ status: snapshot.pricing === undefined ? 'error' : 'ready',
60
+ pricing: snapshot.pricing,
61
+ diagnostics: result.diagnostics,
62
+ };
63
+ }
64
+ function loadingSnapshot() {
65
+ return { status: 'loading', pricing: snapshot.pricing, diagnostics: [] };
66
+ }
67
+ function abortInFlight() {
68
+ controller?.abort();
69
+ controller = undefined;
70
+ }
71
+ function applyInline(current) {
72
+ snapshot = resultSnapshot(loadPricingSource({ pricing: current.pricing, yaml: current.yaml, src: current.src }, current.normalizeOptions ? { normalizeOptions: current.normalizeOptions } : {}));
73
+ }
74
+ function load(current) {
75
+ abortInFlight();
76
+ sequence += 1;
77
+ const token = sequence;
78
+ const own = new AbortController();
79
+ controller = own;
80
+ loadState = 'inflight';
81
+ const pending = loadPricingSource({ src: current.src }, {
82
+ request: boundedRequest(current.request),
83
+ signal: own.signal,
84
+ ...(current.loadPricing ? { loadPricing: current.loadPricing } : {}),
85
+ ...(current.normalizeOptions ? { normalizeOptions: current.normalizeOptions } : {}),
86
+ });
87
+ void Promise.resolve(pending).then((result) => {
88
+ if (token !== sequence)
89
+ return;
90
+ controller = undefined;
91
+ loadState = 'settled';
92
+ snapshot = resultSnapshot(result);
93
+ notify();
94
+ });
95
+ }
96
+ return {
97
+ subscribe(listener) {
98
+ listeners.add(listener);
99
+ return () => {
100
+ listeners.delete(listener);
101
+ };
102
+ },
103
+ getSnapshot() {
104
+ return snapshot;
105
+ },
106
+ setInput(input, options) {
107
+ const next = { ...input, ...options };
108
+ if (held !== undefined && sameHeld(held, next))
109
+ return;
110
+ held = next;
111
+ version += 1;
112
+ // The load in flight is stale at once; stop() still aborts it.
113
+ sequence += 1;
114
+ loadState = 'idle';
115
+ if (isRemote(next))
116
+ snapshot = loadingSnapshot();
117
+ else
118
+ applyInline(next);
119
+ },
120
+ get inputVersion() {
121
+ return version;
122
+ },
123
+ start() {
124
+ active = true;
125
+ if (held === undefined || !isRemote(held) || loadState !== 'idle')
126
+ return;
127
+ if (snapshot.status !== 'loading' || snapshot.diagnostics.length > 0) {
128
+ snapshot = loadingSnapshot();
129
+ notify();
130
+ }
131
+ load(held);
132
+ },
133
+ stop() {
134
+ active = false;
135
+ if (loadState === 'inflight') {
136
+ sequence += 1;
137
+ loadState = 'idle';
138
+ }
139
+ abortInFlight();
140
+ },
141
+ reload() {
142
+ if (held === undefined)
143
+ return;
144
+ if (isRemote(held)) {
145
+ if (!active) {
146
+ // After stop() nothing aborts a new load: the next start() loads instead.
147
+ sequence += 1;
148
+ loadState = 'idle';
149
+ return;
150
+ }
151
+ if (snapshot.status !== 'loading' || snapshot.diagnostics.length > 0) {
152
+ snapshot = loadingSnapshot();
153
+ notify();
154
+ }
155
+ load(held);
156
+ return;
157
+ }
158
+ abortInFlight();
159
+ sequence += 1;
160
+ applyInline(held);
161
+ notify();
162
+ },
163
+ };
164
+ }
165
+ function definedFields(fields) {
166
+ return Object.fromEntries(Object.entries(fields).filter(([, value]) => value !== undefined));
167
+ }
168
+ export function usePricingSource(props) {
169
+ const provider = useContext(PricingRendererContext);
170
+ const [store] = useState(createSourceStore);
171
+ const { pricing, yaml, src, request, loadPricing, normalizeOptions } = props;
172
+ store.setInput(definedFields({ pricing, yaml, src }), definedFields({
173
+ request: request ?? filterProviderRequest(provider?.request, src, provider?.requestOrigins),
174
+ loadPricing: loadPricing ?? provider?.loadPricing,
175
+ normalizeOptions,
176
+ }));
177
+ const snapshot = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
178
+ useEffect(() => {
179
+ store.start();
180
+ return () => {
181
+ store.stop();
182
+ };
183
+ }, [store, store.inputVersion]);
184
+ return { ...snapshot, reload: store.reload };
185
+ }
186
+ //# sourceMappingURL=use-pricing-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-pricing-source.js","sourceRoot":"","sources":["../../src/react/use-pricing-source.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAQ9E,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAyC9E,kGAAkG;AAClG,8EAA8E;AAC9E,SAAS,cAAc,CAAC,OAA0C;IAChE,MAAM,eAAe,GAAG,OAAO,CAAC;IAChC,MAAM,gBAAgB,GAAG,KAAK,CAAC;IAC/B,MAAM,YAAY,GAAG,UAAU,CAAC;IAChC,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,CAAC;IACnC,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,CAAC;IACrC,OAAO;QACL,GAAG,OAAO;QACV,QAAQ,EACN,OAAO,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC;YACvE,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,eAAe;QACrB,SAAS,EACP,OAAO,SAAS,KAAK,QAAQ;YAC7B,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;YAC1B,SAAS,GAAG,CAAC;YACb,SAAS,IAAI,YAAY;YACvB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,gBAAgB;KACvB,CAAC;AACJ,CAAC;AAED,qGAAqG;AACrG,SAAS,QAAQ,CAAC,IAAU,EAAE,KAAW;IACvC,OAAO,CACL,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC;QACtC,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI;QACxB,IAAI,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG;QACtB,IAAI,CAAC,WAAW,KAAK,KAAK,CAAC,WAAW;QACtC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC;QACtC,SAAS,CAAC,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,CAAC,CACzD,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,IAAU;IAC1B,OAAO,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;IACxC,IAAI,QAAQ,GAA0B,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;IACjG,IAAI,IAAsB,CAAC;IAC3B,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,oGAAoG;IACpG,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,SAAS,GAAoC,MAAM,CAAC;IACxD,IAAI,UAAuC,CAAC;IAC5C,wFAAwF;IACxF,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,SAAS,MAAM;QACb,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,SAAS,CAAC;YAAE,QAAQ,EAAE,CAAC;IACpD,CAAC;IAED,SAAS,cAAc,CAAC,MAAoB;QAC1C,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC;QACrF,CAAC;QACD,OAAO;YACL,MAAM,EAAE,QAAQ,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO;YAC1D,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,WAAW,EAAE,MAAM,CAAC,WAAW;SAChC,CAAC;IACJ,CAAC;IAED,SAAS,eAAe;QACtB,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;IAC3E,CAAC;IAED,SAAS,aAAa;QACpB,UAAU,EAAE,KAAK,EAAE,CAAC;QACpB,UAAU,GAAG,SAAS,CAAC;IACzB,CAAC;IAED,SAAS,WAAW,CAAC,OAAa;QAChC,QAAQ,GAAG,cAAc,CACvB,iBAAiB,CACf,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAClE,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAC/D,CAClB,CAAC;IACJ,CAAC;IAED,SAAS,IAAI,CAAC,OAAa;QACzB,aAAa,EAAE,CAAC;QAChB,QAAQ,IAAI,CAAC,CAAC;QACd,MAAM,KAAK,GAAG,QAAQ,CAAC;QACvB,MAAM,GAAG,GAAG,IAAI,eAAe,EAAE,CAAC;QAClC,UAAU,GAAG,GAAG,CAAC;QACjB,SAAS,GAAG,UAAU,CAAC;QACvB,MAAM,OAAO,GAAG,iBAAiB,CAC/B,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EACpB;YACE,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC;YACxC,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpE,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpF,CACF,CAAC;QACF,KAAK,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YAC5C,IAAI,KAAK,KAAK,QAAQ;gBAAE,OAAO;YAC/B,UAAU,GAAG,SAAS,CAAC;YACvB,SAAS,GAAG,SAAS,CAAC;YACtB,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;YAClC,MAAM,EAAE,CAAC;QACX,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,SAAS,CAAC,QAAQ;YAChB,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACxB,OAAO,GAAG,EAAE;gBACV,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC7B,CAAC,CAAC;QACJ,CAAC;QACD,WAAW;YACT,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,QAAQ,CAAC,KAAK,EAAE,OAAO;YACrB,MAAM,IAAI,GAAS,EAAE,GAAG,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC;YAC5C,IAAI,IAAI,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;gBAAE,OAAO;YACvD,IAAI,GAAG,IAAI,CAAC;YACZ,OAAO,IAAI,CAAC,CAAC;YACb,+DAA+D;YAC/D,QAAQ,IAAI,CAAC,CAAC;YACd,SAAS,GAAG,MAAM,CAAC;YACnB,IAAI,QAAQ,CAAC,IAAI,CAAC;gBAAE,QAAQ,GAAG,eAAe,EAAE,CAAC;;gBAC5C,WAAW,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;QACD,IAAI,YAAY;YACd,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,KAAK;YACH,MAAM,GAAG,IAAI,CAAC;YACd,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,SAAS,KAAK,MAAM;gBAAE,OAAO;YAC1E,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS,IAAI,QAAQ,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrE,QAAQ,GAAG,eAAe,EAAE,CAAC;gBAC7B,MAAM,EAAE,CAAC;YACX,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,CAAC;QACD,IAAI;YACF,MAAM,GAAG,KAAK,CAAC;YACf,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;gBAC7B,QAAQ,IAAI,CAAC,CAAC;gBACd,SAAS,GAAG,MAAM,CAAC;YACrB,CAAC;YACD,aAAa,EAAE,CAAC;QAClB,CAAC;QACD,MAAM;YACJ,IAAI,IAAI,KAAK,SAAS;gBAAE,OAAO;YAC/B,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnB,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,0EAA0E;oBAC1E,QAAQ,IAAI,CAAC,CAAC;oBACd,SAAS,GAAG,MAAM,CAAC;oBACnB,OAAO;gBACT,CAAC;gBACD,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS,IAAI,QAAQ,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACrE,QAAQ,GAAG,eAAe,EAAE,CAAC;oBAC7B,MAAM,EAAE,CAAC;gBACX,CAAC;gBACD,IAAI,CAAC,IAAI,CAAC,CAAC;gBACX,OAAO;YACT,CAAC;YACD,aAAa,EAAE,CAAC;YAChB,QAAQ,IAAI,CAAC,CAAC;YACd,WAAW,CAAC,IAAI,CAAC,CAAC;YAClB,MAAM,EAAE,CAAC;QACX,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAmB,MAAS;IAChD,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAM,CAAC;AACpG,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAA4B;IAC3D,MAAM,QAAQ,GAAG,UAAU,CAAC,sBAAsB,CAAC,CAAC;IACpD,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,iBAAiB,CAAC,CAAC;IAC5C,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,GAAG,KAAK,CAAC;IAC7E,KAAK,CAAC,QAAQ,CACZ,aAAa,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EACrC,aAAa,CAAC;QACZ,OAAO,EAAE,OAAO,IAAI,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,cAAc,CAAC;QAC3F,WAAW,EAAE,WAAW,IAAI,QAAQ,EAAE,WAAW;QACjD,gBAAgB;KACjB,CAAC,CACH,CAAC;IACF,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IAC7F,SAAS,CAAC,GAAG,EAAE;QACb,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,OAAO,GAAG,EAAE;YACV,KAAK,CAAC,IAAI,EAAE,CAAC;QACf,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;IAChC,OAAO,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { NormalizedPricing, PricingSelection, ResolvedPricing } from '../core/index.js';
2
+ import type { ApplySelectionResult } from '../element/events.js';
3
+ /** What `usePricingRendererState` returns: the last state the element announced. */
4
+ export interface RendererState {
5
+ pricing: NormalizedPricing;
6
+ selection: PricingSelection;
7
+ resolved: ResolvedPricing;
8
+ applySelection: (input: Partial<PricingSelection>) => ApplySelectionResult | undefined;
9
+ }
10
+ export interface RendererStateStore {
11
+ subscribe: (listener: () => void) => () => void;
12
+ getSnapshot: () => RendererState | undefined;
13
+ getServerSnapshot: () => RendererState | undefined;
14
+ attach: (target: EventTarget | null) => void;
15
+ detach: () => void;
16
+ applySelection: (input: Partial<PricingSelection>) => ApplySelectionResult | undefined;
17
+ }
18
+ export declare function createRendererStateStore(): RendererStateStore;
19
+ export declare function usePricingRendererState(ref: {
20
+ readonly current: EventTarget | null;
21
+ }): RendererState | undefined;
22
+ //# sourceMappingURL=use-renderer-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-renderer-state.d.ts","sourceRoot":"","sources":["../../src/react/use-renderer-state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC7F,OAAO,KAAK,EACV,oBAAoB,EAGrB,MAAM,sBAAsB,CAAC;AAE9B,oFAAoF;AACpF,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,QAAQ,EAAE,eAAe,CAAC;IAC1B,cAAc,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,gBAAgB,CAAC,KAAK,oBAAoB,GAAG,SAAS,CAAC;CACxF;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;IAChD,WAAW,EAAE,MAAM,aAAa,GAAG,SAAS,CAAC;IAC7C,iBAAiB,EAAE,MAAM,aAAa,GAAG,SAAS,CAAC;IACnD,MAAM,EAAE,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;IAC7C,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,cAAc,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,gBAAgB,CAAC,KAAK,oBAAoB,GAAG,SAAS,CAAC;CACxF;AAaD,wBAAgB,wBAAwB,IAAI,kBAAkB,CA0F7D;AAMD,wBAAgB,uBAAuB,CAAC,GAAG,EAAE;IAC3C,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;CACtC,GAAG,aAAa,GAAG,SAAS,CAQ5B"}
@@ -0,0 +1,112 @@
1
+ 'use client';
2
+ import { useEffect, useLayoutEffect, useState, useSyncExternalStore } from 'react';
3
+ // The detail of an event, or undefined when it is missing or not an object.
4
+ function detailOf(event) {
5
+ const detail = event.detail;
6
+ return typeof detail === 'object' && detail !== null ? detail : undefined;
7
+ }
8
+ // every piece of state below belongs to one store instance
9
+ export function createRendererStateStore() {
10
+ const listeners = new Set();
11
+ let target;
12
+ let snapshot;
13
+ const notify = () => {
14
+ for (const listener of [...listeners])
15
+ listener();
16
+ };
17
+ const applySelection = (input) => {
18
+ if (!target || typeof target.applySelection !== 'function')
19
+ return undefined;
20
+ const result = target.applySelection(input);
21
+ if (result.applied && snapshot) {
22
+ snapshot = {
23
+ pricing: snapshot.pricing,
24
+ selection: result.selection,
25
+ resolved: result.resolved,
26
+ applySelection,
27
+ };
28
+ notify();
29
+ }
30
+ return result;
31
+ };
32
+ // The element's events bubble and are composed: one from a nested renderer reaches the listener
33
+ // too, and only the event dispatched on the attached target counts.
34
+ const onReady = (event) => {
35
+ if (event.target !== target)
36
+ return;
37
+ const detail = detailOf(event);
38
+ if (!detail || !detail.pricing)
39
+ return;
40
+ snapshot = {
41
+ pricing: detail.pricing,
42
+ selection: detail.selection,
43
+ resolved: detail.resolved,
44
+ applySelection,
45
+ };
46
+ notify();
47
+ };
48
+ const onChange = (event) => {
49
+ // A change before any pricing-ready since the last attach has no pricing to go with it.
50
+ if (!snapshot || event.target !== target)
51
+ return;
52
+ const detail = detailOf(event);
53
+ if (!detail || !detail.selection)
54
+ return;
55
+ snapshot = {
56
+ pricing: snapshot.pricing,
57
+ selection: detail.selection,
58
+ resolved: detail.resolved,
59
+ applySelection,
60
+ };
61
+ notify();
62
+ };
63
+ const detach = () => {
64
+ if (target) {
65
+ target.removeEventListener('pricing-ready', onReady);
66
+ target.removeEventListener('pricing-selection-change', onChange);
67
+ target = undefined;
68
+ }
69
+ if (snapshot) {
70
+ snapshot = undefined;
71
+ notify();
72
+ }
73
+ };
74
+ const attach = (next) => {
75
+ if (next === null) {
76
+ detach();
77
+ return;
78
+ }
79
+ if (next === target)
80
+ return;
81
+ detach();
82
+ target = next;
83
+ next.addEventListener('pricing-ready', onReady);
84
+ next.addEventListener('pricing-selection-change', onChange);
85
+ };
86
+ return {
87
+ subscribe(listener) {
88
+ listeners.add(listener);
89
+ return () => {
90
+ listeners.delete(listener);
91
+ };
92
+ },
93
+ getSnapshot: () => snapshot,
94
+ getServerSnapshot: () => undefined,
95
+ attach,
96
+ detach,
97
+ applySelection,
98
+ };
99
+ }
100
+ // the client check is evaluated once, at module load,
101
+ // so the hook order stays the same on every render of a process (design.md D7)
102
+ const useClientLayoutEffect = typeof document !== 'undefined' ? useLayoutEffect : useEffect;
103
+ export function usePricingRendererState(ref) {
104
+ const [store] = useState(createRendererStateStore);
105
+ // No dependency list: the ref is read on each commit and the listeners move when it changed.
106
+ useClientLayoutEffect(() => {
107
+ store.attach(ref.current);
108
+ });
109
+ useClientLayoutEffect(() => () => store.detach(), [store]);
110
+ return useSyncExternalStore(store.subscribe, store.getSnapshot, store.getServerSnapshot);
111
+ }
112
+ //# sourceMappingURL=use-renderer-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-renderer-state.js","sourceRoot":"","sources":["../../src/react/use-renderer-state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { PricingSelection } from '../core/index.js';
2
+ export interface SpaceContractLike {
3
+ contractedServices?: Record<string, string>;
4
+ subscriptionPlans?: Record<string, string>;
5
+ subscriptionAddOns?: Record<string, Record<string, number>>;
6
+ usageLevels?: Record<string, Record<string, {
7
+ consumed?: number;
8
+ }>>;
9
+ }
10
+ export interface SpaceSubscription {
11
+ contractedServices: Record<string, string>;
12
+ subscriptionPlans: Record<string, string>;
13
+ subscriptionAddOns: Record<string, Record<string, number>>;
14
+ }
15
+ export interface SpaceSelectionLike {
16
+ planId?: string;
17
+ addOns?: Record<string, {
18
+ selected: boolean;
19
+ quantity: number;
20
+ }>;
21
+ }
22
+ export declare function selectionFromContract(contract: SpaceContractLike, serviceKey: string): Partial<PricingSelection>;
23
+ export declare function subscriptionFromSelection(serviceKey: string, version: string, selection: SpaceSelectionLike): SpaceSubscription;
24
+ export declare function contractedVersion(contract: SpaceContractLike, serviceKey: string): string | undefined;
25
+ export declare function currentUsageFromContract(contract: SpaceContractLike, serviceKey: string): Record<string, number>;
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/space/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,MAAM,WAAW,iBAAiB;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;CACrE;AAED,MAAM,WAAW,iBAAiB;IAChC,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClE;AAoBD,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,iBAAiB,EAC3B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,CAAC,CAiB3B;AAGD,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,kBAAkB,GAC5B,iBAAiB,CAgBnB;AAGD,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,iBAAiB,EAC3B,UAAU,EAAE,MAAM,GACjB,MAAM,GAAG,SAAS,CAGpB;AAGD,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,iBAAiB,EAC3B,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUxB"}
@@ -0,0 +1,71 @@
1
+ // Contract maps come from JSON, so keys such as "constructor", "toString" or "__proto__" are
2
+ // data: they are read as own properties only and written with defineProperty.
3
+ function ownValue(record, key) {
4
+ if (!record || !Object.prototype.hasOwnProperty.call(record, key))
5
+ return undefined;
6
+ return record[key];
7
+ }
8
+ function setOwn(record, key, value) {
9
+ Object.defineProperty(record, key, {
10
+ value,
11
+ enumerable: true,
12
+ writable: true,
13
+ configurable: true,
14
+ });
15
+ }
16
+ // Maps the plan and add-on quantities of one service of a SPACE contract to the input of
17
+ // applySelection. SPACE contracts carry no billing period, so billingPeriod is never set.
18
+ export function selectionFromContract(contract, serviceKey) {
19
+ const result = {};
20
+ const planId = ownValue(contract.subscriptionPlans, serviceKey);
21
+ if (typeof planId === 'string') {
22
+ result.planId = planId;
23
+ }
24
+ const addOns = {};
25
+ const quantities = ownValue(contract.subscriptionAddOns, serviceKey);
26
+ for (const [name, quantity] of Object.entries(quantities ?? {})) {
27
+ if (typeof quantity === 'number' && Number.isFinite(quantity) && quantity > 0) {
28
+ setOwn(addOns, name, { selected: true, quantity });
29
+ }
30
+ }
31
+ if (Object.keys(addOns).length > 0) {
32
+ result.addOns = addOns;
33
+ }
34
+ return result;
35
+ }
36
+ // Builds the SPACE novation body of one service from a reconciled selection.
37
+ export function subscriptionFromSelection(serviceKey, version, selection) {
38
+ const plans = {};
39
+ if (typeof selection.planId === 'string' && selection.planId !== '') {
40
+ setOwn(plans, serviceKey, selection.planId);
41
+ }
42
+ const addOns = {};
43
+ for (const [id, entry] of Object.entries(selection.addOns ?? {})) {
44
+ if (entry?.selected === true && Number.isFinite(entry.quantity) && entry.quantity > 0) {
45
+ setOwn(addOns, id, entry.quantity);
46
+ }
47
+ }
48
+ return {
49
+ contractedServices: { [serviceKey]: version },
50
+ subscriptionPlans: plans,
51
+ subscriptionAddOns: { [serviceKey]: addOns },
52
+ };
53
+ }
54
+ // SPACE stores versions with "." replaced by "_" and clients read them back dotted.
55
+ export function contractedVersion(contract, serviceKey) {
56
+ const stored = ownValue(contract.contractedServices, serviceKey);
57
+ return typeof stored === 'string' ? stored.replaceAll('_', '.') : undefined;
58
+ }
59
+ // Maps the consumed amount of each usage limit of one service.
60
+ export function currentUsageFromContract(contract, serviceKey) {
61
+ const usage = {};
62
+ const levels = ownValue(contract.usageLevels, serviceKey);
63
+ for (const [name, level] of Object.entries(levels ?? {})) {
64
+ const consumed = ownValue(level, 'consumed');
65
+ if (typeof consumed === 'number' && Number.isFinite(consumed) && consumed >= 0) {
66
+ setOwn(usage, name, consumed);
67
+ }
68
+ }
69
+ return usage;
70
+ }
71
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/space/index.ts"],"names":[],"mappings":"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"}