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.
- package/CHANGELOG.md +133 -0
- package/README.md +142 -25
- package/THIRD_PARTY_NOTICES.md +84 -6
- package/custom-elements.json +233 -3
- package/dist/core/apply-selection.d.ts +8 -0
- package/dist/core/apply-selection.d.ts.map +1 -0
- package/dist/core/apply-selection.js +76 -0
- package/dist/core/apply-selection.js.map +1 -0
- package/dist/core/breakdown.d.ts +13 -0
- package/dist/core/breakdown.d.ts.map +1 -0
- package/dist/core/breakdown.js +56 -0
- package/dist/core/breakdown.js.map +1 -0
- package/dist/core/compare-sides.d.ts +16 -0
- package/dist/core/compare-sides.d.ts.map +1 -0
- package/dist/core/compare-sides.js +73 -0
- package/dist/core/compare-sides.js.map +1 -0
- package/dist/core/compare-values.d.ts +13 -0
- package/dist/core/compare-values.d.ts.map +1 -0
- package/dist/core/compare-values.js +100 -0
- package/dist/core/compare-values.js.map +1 -0
- package/dist/core/compare.d.ts +7 -0
- package/dist/core/compare.d.ts.map +1 -0
- package/dist/core/compare.js +301 -0
- package/dist/core/compare.js.map +1 -0
- package/dist/core/expression.js +2 -2
- package/dist/core/expression.js.map +1 -1
- package/dist/core/i18n.d.ts.map +1 -1
- package/dist/core/i18n.js +136 -2
- package/dist/core/i18n.js.map +1 -1
- package/dist/core/index.d.ts +9 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +6 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/normalize.d.ts.map +1 -1
- package/dist/core/normalize.js +70 -9
- package/dist/core/normalize.js.map +1 -1
- package/dist/core/plan-relation.d.ts +8 -0
- package/dist/core/plan-relation.d.ts.map +1 -0
- package/dist/core/plan-relation.js +15 -0
- package/dist/core/plan-relation.js.map +1 -0
- package/dist/core/price-stabilizer.d.ts +3 -0
- package/dist/core/price-stabilizer.d.ts.map +1 -0
- package/dist/core/price-stabilizer.js +73 -0
- package/dist/core/price-stabilizer.js.map +1 -0
- package/dist/core/resolve.d.ts +7 -1
- package/dist/core/resolve.d.ts.map +1 -1
- package/dist/core/resolve.js +66 -21
- package/dist/core/resolve.js.map +1 -1
- package/dist/core/search-params.d.ts +15 -0
- package/dist/core/search-params.d.ts.map +1 -0
- package/dist/core/search-params.js +175 -0
- package/dist/core/search-params.js.map +1 -0
- package/dist/core/selection-change.d.ts +10 -0
- package/dist/core/selection-change.d.ts.map +1 -0
- package/dist/core/selection-change.js +124 -0
- package/dist/core/selection-change.js.map +1 -0
- package/dist/core/types.d.ts +209 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/units.d.ts +13 -0
- package/dist/core/units.d.ts.map +1 -0
- package/dist/core/units.js +84 -0
- package/dist/core/units.js.map +1 -0
- package/dist/core/utils.d.ts.map +1 -1
- package/dist/core/utils.js +91 -32
- package/dist/core/utils.js.map +1 -1
- package/dist/core/view-model.d.ts +3 -1
- package/dist/core/view-model.d.ts.map +1 -1
- package/dist/core/view-model.js +113 -7
- package/dist/core/view-model.js.map +1 -1
- package/dist/element/change-review-define.d.ts +4 -0
- package/dist/element/change-review-define.d.ts.map +1 -0
- package/dist/element/change-review-define.js +17 -0
- package/dist/element/change-review-define.js.map +1 -0
- package/dist/element/change-review-element.d.ts +53 -0
- package/dist/element/change-review-element.d.ts.map +1 -0
- package/dist/element/change-review-element.js +104 -0
- package/dist/element/change-review-element.js.map +1 -0
- package/dist/element/change-review-events.d.ts +10 -0
- package/dist/element/change-review-events.d.ts.map +1 -0
- package/dist/element/change-review-events.js +2 -0
- package/dist/element/change-review-events.js.map +1 -0
- package/dist/element/change-review-renderers.d.ts +23 -0
- package/dist/element/change-review-renderers.d.ts.map +1 -0
- package/dist/element/change-review-renderers.js +391 -0
- package/dist/element/change-review-renderers.js.map +1 -0
- package/dist/element/cta.d.ts +45 -0
- package/dist/element/cta.d.ts.map +1 -0
- package/dist/element/cta.js +90 -0
- package/dist/element/cta.js.map +1 -0
- package/dist/element/current-selection.d.ts +13 -0
- package/dist/element/current-selection.d.ts.map +1 -0
- package/dist/element/current-selection.js +57 -0
- package/dist/element/current-selection.js.map +1 -0
- package/dist/element/define-change-review.d.ts +2 -0
- package/dist/element/define-change-review.d.ts.map +1 -0
- package/dist/element/define-change-review.js +7 -0
- package/dist/element/define-change-review.js.map +1 -0
- package/dist/element/events.d.ts +32 -6
- package/dist/element/events.d.ts.map +1 -1
- package/dist/element/hide-sections.d.ts +6 -0
- package/dist/element/hide-sections.d.ts.map +1 -0
- package/dist/element/hide-sections.js +26 -0
- package/dist/element/hide-sections.js.map +1 -0
- package/dist/element/index.d.ts +8 -1
- package/dist/element/index.d.ts.map +1 -1
- package/dist/element/index.js +3 -0
- package/dist/element/index.js.map +1 -1
- package/dist/element/pricing-renderer-element.d.ts +95 -7
- package/dist/element/pricing-renderer-element.d.ts.map +1 -1
- package/dist/element/pricing-renderer-element.js +563 -217
- package/dist/element/pricing-renderer-element.js.map +1 -1
- package/dist/element/renderers.d.ts +49 -4
- package/dist/element/renderers.d.ts.map +1 -1
- package/dist/element/renderers.js +795 -263
- package/dist/element/renderers.js.map +1 -1
- package/dist/element/same-input.d.ts +3 -0
- package/dist/element/same-input.d.ts.map +1 -0
- package/dist/element/same-input.js +56 -0
- package/dist/element/same-input.js.map +1 -0
- package/dist/react/headless.d.ts +9 -0
- package/dist/react/headless.d.ts.map +1 -0
- package/dist/react/headless.js +8 -0
- package/dist/react/headless.js.map +1 -0
- package/dist/react/index.d.ts +54 -4
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +156 -6
- package/dist/react/index.js.map +1 -1
- package/dist/react/provider.d.ts +17 -0
- package/dist/react/provider.d.ts.map +1 -0
- package/dist/react/provider.js +38 -0
- package/dist/react/provider.js.map +1 -0
- package/dist/react/selection-store.d.ts +51 -0
- package/dist/react/selection-store.d.ts.map +1 -0
- package/dist/react/selection-store.js +239 -0
- package/dist/react/selection-store.js.map +1 -0
- package/dist/react/slots-types.d.ts +38 -0
- package/dist/react/slots-types.d.ts.map +1 -0
- package/dist/react/slots-types.js +2 -0
- package/dist/react/slots-types.js.map +1 -0
- package/dist/react/slots.d.ts +40 -0
- package/dist/react/slots.d.ts.map +1 -0
- package/dist/react/slots.js +165 -0
- package/dist/react/slots.js.map +1 -0
- package/dist/react/use-pricing-selection.d.ts +10 -0
- package/dist/react/use-pricing-selection.d.ts.map +1 -0
- package/dist/react/use-pricing-selection.js +44 -0
- package/dist/react/use-pricing-selection.js.map +1 -0
- package/dist/react/use-pricing-source.d.ts +34 -0
- package/dist/react/use-pricing-source.d.ts.map +1 -0
- package/dist/react/use-pricing-source.js +186 -0
- package/dist/react/use-pricing-source.js.map +1 -0
- package/dist/react/use-renderer-state.d.ts +22 -0
- package/dist/react/use-renderer-state.d.ts.map +1 -0
- package/dist/react/use-renderer-state.js +112 -0
- package/dist/react/use-renderer-state.js.map +1 -0
- package/dist/space/index.d.ts +26 -0
- package/dist/space/index.d.ts.map +1 -0
- package/dist/space/index.js +71 -0
- package/dist/space/index.js.map +1 -0
- package/dist/styles/base.css +1030 -76
- package/dist/styles/theme-minimal.css +103 -0
- package/dist/styles/theme.css +22 -3
- package/dist/styles/tokens-shadcn.css +40 -0
- package/dist/yaml/index.d.ts +2 -0
- package/dist/yaml/index.d.ts.map +1 -1
- package/dist/yaml/index.js +1 -0
- package/dist/yaml/index.js.map +1 -1
- package/dist/yaml/load.d.ts.map +1 -1
- package/dist/yaml/load.js +106 -17
- package/dist/yaml/load.js.map +1 -1
- package/dist/yaml/source.d.ts +18 -0
- package/dist/yaml/source.d.ts.map +1 -0
- package/dist/yaml/source.js +46 -0
- package/dist/yaml/source.js.map +1 -0
- package/package.json +25 -13
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
// `html` is aliased so that the layout of the templates below stays as written.
|
|
2
|
+
import { html as tpl, nothing } from 'lit';
|
|
3
|
+
import { formatCurrency, translate, } from '../core/index.js';
|
|
4
|
+
import { formatUnit } from '../core/units.js';
|
|
5
|
+
// The parts of the review a host can hide. The content sections are deliberately absent: a review
|
|
6
|
+
// without its plan or its price is not a review.
|
|
7
|
+
export const REVIEW_SECTION_NAMES = [
|
|
8
|
+
// For a host whose own heading already names what is being compared.
|
|
9
|
+
'title',
|
|
10
|
+
// The badge that reads a plan change as Upgrade or Downgrade. It follows the declaration order
|
|
11
|
+
// of `pricing.plans`, which is a ladder only inside a subscription: two configurations compared
|
|
12
|
+
// side by side have no such order, and the badge would assert one they do not have.
|
|
13
|
+
'relation',
|
|
14
|
+
// Confirm and Back, for a diff that is not actionable.
|
|
15
|
+
'actions',
|
|
16
|
+
];
|
|
17
|
+
const relationKeys = {
|
|
18
|
+
upgrade: 'pricing.reviewRelationUpgrade',
|
|
19
|
+
downgrade: 'pricing.reviewRelationDowngrade',
|
|
20
|
+
change: 'pricing.reviewRelationChange',
|
|
21
|
+
current: 'pricing.reviewRelationCurrent',
|
|
22
|
+
};
|
|
23
|
+
const relationTones = {
|
|
24
|
+
upgrade: 'success',
|
|
25
|
+
downgrade: 'warning',
|
|
26
|
+
change: 'accent',
|
|
27
|
+
current: undefined,
|
|
28
|
+
};
|
|
29
|
+
const removalKeys = {
|
|
30
|
+
'unavailable-for-plan': 'pricing.reviewRemovedUnavailable',
|
|
31
|
+
'dependency-removed': 'pricing.reviewRemovedDependency',
|
|
32
|
+
'not-in-version': 'pricing.reviewRemovedNotInVersion',
|
|
33
|
+
};
|
|
34
|
+
const differenceKeys = {
|
|
35
|
+
quote: 'pricing.reviewDifferenceQuote',
|
|
36
|
+
currency: 'pricing.reviewDifferenceCurrency',
|
|
37
|
+
};
|
|
38
|
+
const dash = '—';
|
|
39
|
+
// Intl rejects the underscore of a locale such as es_ES.
|
|
40
|
+
function intlLocale(locale) {
|
|
41
|
+
return locale.replace(/_/g, '-');
|
|
42
|
+
}
|
|
43
|
+
function formatNumber(value, locale, options) {
|
|
44
|
+
try {
|
|
45
|
+
return new Intl.NumberFormat(intlLocale(locale), options).format(value);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return String(value);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Mirrors renderValue of the renderer, as text: no value and false are "Not included", unlimited
|
|
52
|
+
// is "Unlimited", numbers use Intl for the locale and carry the unit, text is kept, and arrays and
|
|
53
|
+
// objects are written as JSON.
|
|
54
|
+
export function formatComparedValue(value, messages, locale, unit) {
|
|
55
|
+
switch (value.kind) {
|
|
56
|
+
case 'none':
|
|
57
|
+
return translate(messages, 'pricing.notIncluded');
|
|
58
|
+
case 'unlimited':
|
|
59
|
+
return translate(messages, 'pricing.unlimited');
|
|
60
|
+
case 'boolean':
|
|
61
|
+
return translate(messages, value.value ? 'pricing.included' : 'pricing.notIncluded');
|
|
62
|
+
case 'number': {
|
|
63
|
+
const formatted = formatNumber(value.value, locale);
|
|
64
|
+
if (!unit)
|
|
65
|
+
return formatted;
|
|
66
|
+
return `${formatted} ${formatUnit(unit, value.value, intlLocale(locale))}`;
|
|
67
|
+
}
|
|
68
|
+
case 'text':
|
|
69
|
+
return value.value;
|
|
70
|
+
case 'json':
|
|
71
|
+
return JSON.stringify(value.value);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// The difference of two subtotals with its sign ("+€2", "-€5", "€0"), with the fraction digits of
|
|
75
|
+
// formatCurrency.
|
|
76
|
+
export function formatSignedCurrency(amount, currency, locale = 'en-US') {
|
|
77
|
+
const maximumFractionDigits = amount % 1 === 0 ? 0 : 2;
|
|
78
|
+
const base = { signDisplay: 'exceptZero', maximumFractionDigits };
|
|
79
|
+
try {
|
|
80
|
+
const options = { ...base, style: 'currency', currency };
|
|
81
|
+
return new Intl.NumberFormat(intlLocale(locale), options).format(amount);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return formatNumber(amount, locale, base);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function t(state, key, parameters) {
|
|
88
|
+
return translate(state.messages, key, parameters);
|
|
89
|
+
}
|
|
90
|
+
function arrow(state, before, after) {
|
|
91
|
+
return t(state, 'pricing.reviewChangeArrow', { before, after });
|
|
92
|
+
}
|
|
93
|
+
function badge(text, tone) {
|
|
94
|
+
return tpl `<span data-pr-part="change-badge" data-tone=${tone ?? nothing}>${text}</span>`;
|
|
95
|
+
}
|
|
96
|
+
function reviewSection(state, part, titleKey, body) {
|
|
97
|
+
const titleId = `${state.idPrefix}-${part}`;
|
|
98
|
+
return tpl `<section data-pr-part=${part} aria-labelledby=${titleId}>
|
|
99
|
+
<h3 id=${titleId}>${t(state, titleKey)}</h3>
|
|
100
|
+
${body}
|
|
101
|
+
</section>`;
|
|
102
|
+
}
|
|
103
|
+
function changeRow(name, parts = {}) {
|
|
104
|
+
const { detail, badge: tag, reason, warning } = parts;
|
|
105
|
+
return tpl `<li data-pr-part="change-row">
|
|
106
|
+
<span class="pr-cr-row__name">${name}</span>
|
|
107
|
+
${detail ? tpl `<span class="pr-cr-row__detail">${detail}</span>` : nothing}
|
|
108
|
+
${tag ?? nothing}
|
|
109
|
+
${reason ? tpl `<span class="pr-cr-row__reason">${reason}</span>` : nothing}
|
|
110
|
+
${warning ? tpl `<p class="pr-cr-warning" role="note">${warning}</p>` : nothing}
|
|
111
|
+
</li>`;
|
|
112
|
+
}
|
|
113
|
+
function list(rows) {
|
|
114
|
+
return tpl `<ul>${rows}</ul>`;
|
|
115
|
+
}
|
|
116
|
+
function planName(plan) {
|
|
117
|
+
return plan.name ?? plan.id ?? dash;
|
|
118
|
+
}
|
|
119
|
+
function periodName(period) {
|
|
120
|
+
return period?.label ?? period?.id ?? dash;
|
|
121
|
+
}
|
|
122
|
+
function renderPlan(state) {
|
|
123
|
+
const { plan, relation, version } = state.comparison;
|
|
124
|
+
let name = planName(plan.after);
|
|
125
|
+
if (plan.changed)
|
|
126
|
+
name = arrow(state, planName(plan.before), planName(plan.after));
|
|
127
|
+
let banner = nothing;
|
|
128
|
+
if (version.changed) {
|
|
129
|
+
const text = t(state, 'pricing.reviewVersionChange', {
|
|
130
|
+
before: version.before ?? dash,
|
|
131
|
+
after: version.after ?? dash,
|
|
132
|
+
});
|
|
133
|
+
banner = tpl `<p class="pr-cr-banner">${text}</p>`;
|
|
134
|
+
}
|
|
135
|
+
const relationBadge = state.hiddenSections?.has('relation')
|
|
136
|
+
? nothing
|
|
137
|
+
: badge(t(state, relationKeys[relation]), relationTones[relation]);
|
|
138
|
+
const body = tpl `<div data-pr-part="change-row">
|
|
139
|
+
<span class="pr-cr-row__name">${name}</span>
|
|
140
|
+
${relationBadge}
|
|
141
|
+
</div>
|
|
142
|
+
${banner}`;
|
|
143
|
+
return reviewSection(state, 'review-plan', 'pricing.reviewPlan', body);
|
|
144
|
+
}
|
|
145
|
+
// formatCurrency throws for a locale that Intl rejects; a plain number is the fallback then.
|
|
146
|
+
function formatSubtotal(amount, currency, locale) {
|
|
147
|
+
try {
|
|
148
|
+
return formatCurrency(amount, currency, intlLocale(locale));
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return formatNumber(amount, locale, { maximumFractionDigits: amount % 1 === 0 ? 0 : 2 });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// A subtotal in its currency. A part that requires a quote is named, and a price that is only a
|
|
155
|
+
// quote reads "Contact sales".
|
|
156
|
+
function renderMoney(state, price) {
|
|
157
|
+
const quote = price.requiresQuote;
|
|
158
|
+
let amount = formatSubtotal(price.subtotal, price.currency, state.locale);
|
|
159
|
+
if (quote && price.subtotal === 0)
|
|
160
|
+
amount = t(state, 'pricing.contactSales');
|
|
161
|
+
let partial = nothing;
|
|
162
|
+
if (quote && price.subtotal !== 0) {
|
|
163
|
+
partial = tpl ` <small>${t(state, 'pricing.requiresQuote')}</small>`;
|
|
164
|
+
}
|
|
165
|
+
// What an amount is per: the plan's own unit, the same text the plan card shows. A real
|
|
166
|
+
// billing period is named too; the one invented for a pricing that declares none is not,
|
|
167
|
+
// since "Base" tells the reader nothing the author ever chose.
|
|
168
|
+
let period = nothing;
|
|
169
|
+
if (price.unit) {
|
|
170
|
+
period = tpl ` <small>${t(state, 'pricing.per', { unit: price.unit })}</small>`;
|
|
171
|
+
}
|
|
172
|
+
else if (price.billingPeriod && price.billingPeriod.synthesized !== true) {
|
|
173
|
+
period = tpl ` <small>${price.billingPeriod.label}</small>`;
|
|
174
|
+
}
|
|
175
|
+
return tpl `${amount}${partial}${period}`;
|
|
176
|
+
}
|
|
177
|
+
function renderDifference(state) {
|
|
178
|
+
const { price } = state.comparison;
|
|
179
|
+
if (price.difference === undefined)
|
|
180
|
+
return nothing;
|
|
181
|
+
const signed = formatSignedCurrency(price.difference, price.after.currency, state.locale);
|
|
182
|
+
// The reason the screen exists, so it is marked for the stylesheet and carries its direction.
|
|
183
|
+
// "same" is a real outcome: a plan swap can leave the bill untouched.
|
|
184
|
+
const direction = price.difference > 0 ? 'increase' : price.difference < 0 ? 'decrease' : 'same';
|
|
185
|
+
return tpl `<div data-pr-part="price-difference" data-direction=${direction}>
|
|
186
|
+
<dt>${t(state, 'pricing.reviewPriceDifference')}</dt>
|
|
187
|
+
<dd>${signed}</dd>
|
|
188
|
+
</div>`;
|
|
189
|
+
}
|
|
190
|
+
function renderPrice(state) {
|
|
191
|
+
const { price } = state.comparison;
|
|
192
|
+
let omitted = nothing;
|
|
193
|
+
if (price.differenceOmitted) {
|
|
194
|
+
const text = t(state, differenceKeys[price.differenceOmitted]);
|
|
195
|
+
omitted = tpl `<p class="pr-cr-note">${text}</p>`;
|
|
196
|
+
}
|
|
197
|
+
let billing = nothing;
|
|
198
|
+
if (price.billingPeriodChanged) {
|
|
199
|
+
const text = t(state, 'pricing.reviewBillingChange', {
|
|
200
|
+
before: periodName(price.before.billingPeriod),
|
|
201
|
+
after: periodName(price.after.billingPeriod),
|
|
202
|
+
});
|
|
203
|
+
billing = tpl `<p class="pr-cr-note">${text}</p>`;
|
|
204
|
+
}
|
|
205
|
+
const body = tpl `<dl class="pr-cr-price">
|
|
206
|
+
<div>
|
|
207
|
+
<dt>${t(state, 'pricing.reviewPriceBefore')}</dt>
|
|
208
|
+
<dd>${renderMoney(state, price.before)}</dd>
|
|
209
|
+
</div>
|
|
210
|
+
<div>
|
|
211
|
+
<dt>${t(state, 'pricing.reviewPriceAfter')}</dt>
|
|
212
|
+
<dd>${renderMoney(state, price.after)}</dd>
|
|
213
|
+
</div>
|
|
214
|
+
${renderDifference(state)}
|
|
215
|
+
</dl>
|
|
216
|
+
${omitted}
|
|
217
|
+
${billing}`;
|
|
218
|
+
return reviewSection(state, 'review-price', 'pricing.reviewPrice', body);
|
|
219
|
+
}
|
|
220
|
+
function addOnRow(state, item, labelKey, tone, reason) {
|
|
221
|
+
const detail = item.quantity > 1 ? `× ${formatNumber(item.quantity, state.locale)}` : undefined;
|
|
222
|
+
return changeRow(item.name, { detail, badge: badge(t(state, labelKey), tone), reason });
|
|
223
|
+
}
|
|
224
|
+
function removalReason(state, item) {
|
|
225
|
+
const plan = planName(state.comparison.plan.after);
|
|
226
|
+
return t(state, removalKeys[item.reason], { plan });
|
|
227
|
+
}
|
|
228
|
+
function renderAddOns(state) {
|
|
229
|
+
const { addOns } = state.comparison;
|
|
230
|
+
const added = 'pricing.reviewAddOnAdded';
|
|
231
|
+
const removed = 'pricing.reviewAddOnRemoved';
|
|
232
|
+
const rows = [];
|
|
233
|
+
for (const item of addOns.added)
|
|
234
|
+
rows.push(addOnRow(state, item, added, 'success'));
|
|
235
|
+
for (const item of addOns.removedByUser)
|
|
236
|
+
rows.push(addOnRow(state, item, removed, 'warning'));
|
|
237
|
+
for (const item of addOns.removedByReconciliation) {
|
|
238
|
+
rows.push(addOnRow(state, item, removed, 'warning', removalReason(state, item)));
|
|
239
|
+
}
|
|
240
|
+
for (const item of addOns.quantityChanged) {
|
|
241
|
+
const before = formatNumber(item.before, state.locale);
|
|
242
|
+
const after = formatNumber(item.after, state.locale);
|
|
243
|
+
const detail = t(state, 'pricing.reviewQuantityChange', { before, after });
|
|
244
|
+
rows.push(changeRow(item.name, { detail }));
|
|
245
|
+
}
|
|
246
|
+
if (rows.length === 0)
|
|
247
|
+
return nothing;
|
|
248
|
+
return reviewSection(state, 'review-add-ons', 'pricing.reviewAddOns', list(rows));
|
|
249
|
+
}
|
|
250
|
+
function renderFeatures(state) {
|
|
251
|
+
const { features } = state.comparison;
|
|
252
|
+
const format = (value) => formatComparedValue(value, state.messages, state.locale);
|
|
253
|
+
const gained = badge(t(state, 'pricing.reviewFeatureGained'), 'success');
|
|
254
|
+
const lost = badge(t(state, 'pricing.reviewFeatureLost'), 'warning');
|
|
255
|
+
const changed = badge(t(state, 'pricing.reviewFeatureChanged'), 'accent');
|
|
256
|
+
const rows = [];
|
|
257
|
+
for (const item of features.gained)
|
|
258
|
+
rows.push(changeRow(item.name, { badge: gained }));
|
|
259
|
+
for (const item of features.lost)
|
|
260
|
+
rows.push(changeRow(item.name, { badge: lost }));
|
|
261
|
+
for (const item of features.changed) {
|
|
262
|
+
const detail = arrow(state, format(item.before), format(item.after));
|
|
263
|
+
rows.push(changeRow(item.name, { detail, badge: changed }));
|
|
264
|
+
}
|
|
265
|
+
if (rows.length === 0)
|
|
266
|
+
return nothing;
|
|
267
|
+
return reviewSection(state, 'review-features', 'pricing.reviewFeatures', list(rows));
|
|
268
|
+
}
|
|
269
|
+
function renderLimits(state) {
|
|
270
|
+
const rows = [];
|
|
271
|
+
for (const item of state.comparison.usageLimits.changed) {
|
|
272
|
+
const format = (value) => formatComparedValue(value, state.messages, state.locale, item.unit);
|
|
273
|
+
const moved = arrow(state, format(item.before), format(item.after));
|
|
274
|
+
// The delta is the part a reader scans for, and its sign is the whole message: more of a
|
|
275
|
+
// limit is a gain, less of one is what they are giving up. It carries its direction so the
|
|
276
|
+
// stylesheet can tone it without the reader parsing a minus sign.
|
|
277
|
+
let detail = moved;
|
|
278
|
+
if (item.delta !== undefined) {
|
|
279
|
+
const sign = formatNumber(item.delta, state.locale, { signDisplay: 'exceptZero' });
|
|
280
|
+
const unit = item.unit
|
|
281
|
+
? ` ${formatUnit(item.unit, Math.abs(item.delta), intlLocale(state.locale))}`
|
|
282
|
+
: '';
|
|
283
|
+
const direction = item.delta > 0 ? 'increase' : item.delta < 0 ? 'decrease' : 'same';
|
|
284
|
+
detail = tpl `${moved} <span class="pr-cr-row__delta" data-direction=${direction}
|
|
285
|
+
>(${sign}${unit})</span
|
|
286
|
+
>`;
|
|
287
|
+
}
|
|
288
|
+
let warning;
|
|
289
|
+
if (item.exceedsCurrentUsage && item.currentUsage !== undefined) {
|
|
290
|
+
const usage = format({ kind: 'number', value: item.currentUsage });
|
|
291
|
+
warning = t(state, 'pricing.reviewLimitExceeded', { usage });
|
|
292
|
+
}
|
|
293
|
+
rows.push(changeRow(item.name, { detail, warning }));
|
|
294
|
+
}
|
|
295
|
+
if (rows.length === 0)
|
|
296
|
+
return nothing;
|
|
297
|
+
return reviewSection(state, 'review-limits', 'pricing.reviewLimits', list(rows));
|
|
298
|
+
}
|
|
299
|
+
function renderUnchanged(state) {
|
|
300
|
+
const { addOns, features, usageLimits } = state.comparison;
|
|
301
|
+
const counts = [addOns.unchanged, features.unchanged, usageLimits.unchanged];
|
|
302
|
+
if (counts.every((ids) => ids.length === 0))
|
|
303
|
+
return nothing;
|
|
304
|
+
// Add-ons are left out of this line: what a reader checks here is whether the entitlements
|
|
305
|
+
// they rely on survive the change, and an add-on they did not touch is not news. The section
|
|
306
|
+
// still appears when only add-ons are unchanged, because something did stay the same.
|
|
307
|
+
const [, featureCount = 0, limitCount = 0] = counts.map((ids) => ids.length);
|
|
308
|
+
const summary = t(state, 'pricing.reviewUnchangedSummary', {
|
|
309
|
+
features: formatNumber(featureCount, state.locale),
|
|
310
|
+
limits: formatNumber(limitCount, state.locale),
|
|
311
|
+
});
|
|
312
|
+
const body = tpl `<p>${summary}</p>`;
|
|
313
|
+
return reviewSection(state, 'review-unchanged', 'pricing.reviewUnchanged', body);
|
|
314
|
+
}
|
|
315
|
+
function renderNotices(state) {
|
|
316
|
+
if (state.notices.length === 0)
|
|
317
|
+
return nothing;
|
|
318
|
+
const items = state.notices.map((notice) => tpl `<li class="pr-cr-notice">${notice}</li>`);
|
|
319
|
+
return reviewSection(state, 'review-notices', 'pricing.reviewNotices', list(items));
|
|
320
|
+
}
|
|
321
|
+
function renderError(state) {
|
|
322
|
+
if (state.error === undefined)
|
|
323
|
+
return nothing;
|
|
324
|
+
return tpl `<div class="pr-cr-error" data-pr-part="review-error" role="alert">
|
|
325
|
+
<strong>${t(state, 'pricing.reviewErrorTitle')}</strong>
|
|
326
|
+
${state.error}
|
|
327
|
+
</div>`;
|
|
328
|
+
}
|
|
329
|
+
function renderActions(state) {
|
|
330
|
+
if (state.hiddenSections?.has('actions'))
|
|
331
|
+
return nothing;
|
|
332
|
+
const status = state.pending ? t(state, 'pricing.reviewPending') : nothing;
|
|
333
|
+
const confirm = state.confirmLabel || t(state, 'pricing.reviewConfirm');
|
|
334
|
+
return tpl `<div data-pr-part="change-actions">
|
|
335
|
+
<p class="pr-cr-status" data-pr-part="review-status" role="status">${status}</p>
|
|
336
|
+
<button
|
|
337
|
+
class="pr-button pr-button--secondary"
|
|
338
|
+
data-pr-part="review-back"
|
|
339
|
+
type="button"
|
|
340
|
+
@click=${state.onBack}
|
|
341
|
+
>${t(state, 'pricing.reviewBack')}</button>
|
|
342
|
+
<button
|
|
343
|
+
class="pr-button pr-button--primary"
|
|
344
|
+
data-pr-part="review-confirm"
|
|
345
|
+
type="button"
|
|
346
|
+
aria-disabled=${state.blocked ? 'true' : nothing}
|
|
347
|
+
aria-busy=${state.pending ? 'true' : nothing}
|
|
348
|
+
@click=${state.onConfirm}
|
|
349
|
+
>${confirm}</button>
|
|
350
|
+
</div>`;
|
|
351
|
+
}
|
|
352
|
+
// The sections in the order of design.md, each only when it has content. Nothing changes: a note.
|
|
353
|
+
function renderBody(state) {
|
|
354
|
+
if (state.comparison.relation === 'current') {
|
|
355
|
+
const note = t(state, 'pricing.reviewNoChanges');
|
|
356
|
+
return tpl `<p class="pr-cr-notice" data-pr-part="review-no-changes">${note}</p>`;
|
|
357
|
+
}
|
|
358
|
+
return [
|
|
359
|
+
renderPlan(state),
|
|
360
|
+
renderPrice(state),
|
|
361
|
+
renderAddOns(state),
|
|
362
|
+
renderFeatures(state),
|
|
363
|
+
renderLimits(state),
|
|
364
|
+
renderUnchanged(state),
|
|
365
|
+
];
|
|
366
|
+
}
|
|
367
|
+
// The root with its title, the body, the notices of the host, the alert region and the actions
|
|
368
|
+
// with the status region.
|
|
369
|
+
export function renderChangeReview(state) {
|
|
370
|
+
const titleId = `${state.idPrefix}-title`;
|
|
371
|
+
const title = t(state, 'pricing.reviewTitle');
|
|
372
|
+
// A host that hides the title labels the region with its own heading, so the reference goes with
|
|
373
|
+
// it: aria-labelledby pointing at an absent id leaves the section claiming a name it has not.
|
|
374
|
+
const untitled = state.hiddenSections?.has('title') === true;
|
|
375
|
+
const header = untitled
|
|
376
|
+
? nothing
|
|
377
|
+
: tpl `<header class="pr-cr-header">
|
|
378
|
+
<h2 id=${titleId} data-pr-part="review-title" tabindex="-1">${title}</h2>
|
|
379
|
+
</header>`;
|
|
380
|
+
return tpl `<section
|
|
381
|
+
data-pr-part="change-review"
|
|
382
|
+
aria-labelledby=${untitled ? nothing : titleId}
|
|
383
|
+
>
|
|
384
|
+
${header}
|
|
385
|
+
${renderBody(state)}
|
|
386
|
+
${renderNotices(state)}
|
|
387
|
+
${renderError(state)}
|
|
388
|
+
${renderActions(state)}
|
|
389
|
+
</section>`;
|
|
390
|
+
}
|
|
391
|
+
//# sourceMappingURL=change-review-renderers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-review-renderers.js","sourceRoot":"","sources":["../../src/element/change-review-renderers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type NormalizedPlan, type PricingCta, type PricingViewModel, type SelectionRelation } from '../core/index.js';
|
|
2
|
+
export declare const REVIEW_CHANGE_ACTION_ID = "review-change";
|
|
3
|
+
export declare const CONTACT_SALES_ACTION_ID = "contact-sales";
|
|
4
|
+
/** What the CTAs need to know about the customer's contract and the host's pending work. */
|
|
5
|
+
export interface PricingActionContext {
|
|
6
|
+
/** The current plan id, only when the loaded pricing defines it. */
|
|
7
|
+
currentPlanId?: string;
|
|
8
|
+
pendingActionId?: string;
|
|
9
|
+
}
|
|
10
|
+
/** The summary action, computed by the element and rendered by `renderSummary`. */
|
|
11
|
+
export interface SummaryActionState {
|
|
12
|
+
actionId: typeof REVIEW_CHANGE_ACTION_ID | typeof CONTACT_SALES_ACTION_ID;
|
|
13
|
+
label: string;
|
|
14
|
+
relation: SelectionRelation;
|
|
15
|
+
disabled: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface PlanCtaView {
|
|
18
|
+
actionId: string;
|
|
19
|
+
/** What the button shows. Short: the card already names the plan. */
|
|
20
|
+
label: string;
|
|
21
|
+
/** The full phrase, naming the plan, for a reader who meets the button out of context. */
|
|
22
|
+
ariaLabel?: string;
|
|
23
|
+
/** Expanded and safe; absent for a button. */
|
|
24
|
+
href?: string;
|
|
25
|
+
/** The expanded `href` of the configured CTA, safe or not, for the `pricing-action` detail. */
|
|
26
|
+
eventHref?: string;
|
|
27
|
+
target?: '_self' | '_blank';
|
|
28
|
+
kind: 'primary' | 'secondary';
|
|
29
|
+
metadata?: PricingCta['metadata'];
|
|
30
|
+
/** Set only while the current plan is known. */
|
|
31
|
+
relation?: SelectionRelation;
|
|
32
|
+
/** The current plan's CTA: a button with the `disabled` attribute. */
|
|
33
|
+
disabled: boolean;
|
|
34
|
+
/** `aria-disabled`: any action of the host is pending. */
|
|
35
|
+
ariaDisabled: boolean;
|
|
36
|
+
/** This control is the pending action. */
|
|
37
|
+
pending: boolean;
|
|
38
|
+
}
|
|
39
|
+
export declare function isPendingActionId(pendingActionId: string | undefined, actionId: string): boolean;
|
|
40
|
+
export declare function expandCtaHref(href: string | undefined, planId: string): string | undefined;
|
|
41
|
+
/** The label, link and state of one plan CTA. */
|
|
42
|
+
export declare function planCtaView(viewModel: PricingViewModel, plan: NormalizedPlan, context: PricingActionContext): PlanCtaView;
|
|
43
|
+
/** The summary action for a known current plan and the relation of the selection in effect. */
|
|
44
|
+
export declare function summaryActionState(viewModel: PricingViewModel, relation: SelectionRelation): SummaryActionState;
|
|
45
|
+
//# sourceMappingURL=cta.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cta.d.ts","sourceRoot":"","sources":["../../src/element/cta.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAC;AAG1B,eAAO,MAAM,uBAAuB,kBAAkB,CAAC;AACvD,eAAO,MAAM,uBAAuB,kBAAkB,CAAC;AAEvD,4FAA4F;AAC5F,MAAM,WAAW,oBAAoB;IACnC,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,mFAAmF;AACnF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,uBAAuB,GAAG,OAAO,uBAAuB,CAAC;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+FAA+F;IAC/F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC5B,IAAI,EAAE,SAAS,GAAG,WAAW,CAAC;IAC9B,QAAQ,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;IAClC,gDAAgD;IAChD,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,sEAAsE;IACtE,QAAQ,EAAE,OAAO,CAAC;IAClB,0DAA0D;IAC1D,YAAY,EAAE,OAAO,CAAC;IACtB,0CAA0C;IAC1C,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,iBAAiB,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEhG;AAGD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE1F;AAqBD,iDAAiD;AACjD,wBAAgB,WAAW,CACzB,SAAS,EAAE,gBAAgB,EAC3B,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,oBAAoB,GAC5B,WAAW,CAqDb;AAED,+FAA+F;AAC/F,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,gBAAgB,EAC3B,QAAQ,EAAE,iBAAiB,GAC1B,kBAAkB,CAgBpB"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { formatCurrency, getPlanCta, isSafeLink, translate, } from '../core/index.js';
|
|
2
|
+
import { planRelation } from '../core/plan-relation.js';
|
|
3
|
+
export const REVIEW_CHANGE_ACTION_ID = 'review-change';
|
|
4
|
+
export const CONTACT_SALES_ACTION_ID = 'contact-sales';
|
|
5
|
+
export function isPendingActionId(pendingActionId, actionId) {
|
|
6
|
+
return pendingActionId !== undefined && pendingActionId === actionId;
|
|
7
|
+
}
|
|
8
|
+
// The plan id is encoded here, before the caller checks the safety of the result.
|
|
9
|
+
export function expandCtaHref(href, planId) {
|
|
10
|
+
return href?.split('{planId}').join(encodeURIComponent(planId));
|
|
11
|
+
}
|
|
12
|
+
function relationLabel(viewModel, plan, cta, relation) {
|
|
13
|
+
const price = viewModel.resolved.planPrices[plan.id];
|
|
14
|
+
if (price?.kind === 'label' || price?.kind === 'error') {
|
|
15
|
+
return cta?.labels?.contactSales ?? translate(viewModel.messages, 'pricing.contactSales');
|
|
16
|
+
}
|
|
17
|
+
if (relation === 'upgrade') {
|
|
18
|
+
return cta?.labels?.upgrade ?? translate(viewModel.messages, 'pricing.upgrade');
|
|
19
|
+
}
|
|
20
|
+
if (relation === 'downgrade') {
|
|
21
|
+
return cta?.labels?.downgrade ?? translate(viewModel.messages, 'pricing.downgrade');
|
|
22
|
+
}
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
/** The label, link and state of one plan CTA. */
|
|
26
|
+
export function planCtaView(viewModel, plan, context) {
|
|
27
|
+
const cta = getPlanCta(viewModel.presentation, plan.id);
|
|
28
|
+
const actionId = cta?.id ?? `choose-${plan.id}`;
|
|
29
|
+
const { currentPlanId, pendingActionId } = context;
|
|
30
|
+
const kind = cta?.kind === 'secondary' ? 'secondary' : 'primary';
|
|
31
|
+
// an unsafe expanded link renders as a button
|
|
32
|
+
const eventHref = expandCtaHref(cta?.href, plan.id) || undefined;
|
|
33
|
+
const href = isSafeLink(eventHref) ? eventHref : undefined;
|
|
34
|
+
const base = {
|
|
35
|
+
actionId,
|
|
36
|
+
kind,
|
|
37
|
+
...(cta?.target ? { target: cta.target } : {}),
|
|
38
|
+
...(cta?.metadata ? { metadata: cta.metadata } : {}),
|
|
39
|
+
...(eventHref ? { eventHref } : {}),
|
|
40
|
+
ariaDisabled: pendingActionId !== undefined,
|
|
41
|
+
pending: isPendingActionId(pendingActionId, actionId),
|
|
42
|
+
};
|
|
43
|
+
const defaultLabel = () => cta?.label ?? translate(viewModel.messages, 'pricing.choosePlan', { plan: plan.name });
|
|
44
|
+
if (currentPlanId === undefined) {
|
|
45
|
+
return { ...base, label: defaultLabel(), ...(href ? { href } : {}), disabled: false };
|
|
46
|
+
}
|
|
47
|
+
const relation = planRelation(viewModel.pricing, currentPlanId, plan.id);
|
|
48
|
+
if (relation === 'current') {
|
|
49
|
+
return {
|
|
50
|
+
...base,
|
|
51
|
+
label: cta?.labels?.current ?? translate(viewModel.messages, 'pricing.currentPlanCta'),
|
|
52
|
+
relation,
|
|
53
|
+
disabled: true,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const label = relationLabel(viewModel, plan, cta, relation) ?? defaultLabel();
|
|
57
|
+
// The visible text is short because the card names the plan right above it. A button read on
|
|
58
|
+
// its own still has to say which plan it changes to, so the full phrase lives in aria-label.
|
|
59
|
+
const longKey = relation === 'upgrade'
|
|
60
|
+
? 'pricing.upgradeTo'
|
|
61
|
+
: relation === 'downgrade'
|
|
62
|
+
? 'pricing.downgradeTo'
|
|
63
|
+
: undefined;
|
|
64
|
+
const ariaLabel = longKey
|
|
65
|
+
? translate(viewModel.messages, longKey, { plan: plan.name })
|
|
66
|
+
: undefined;
|
|
67
|
+
return {
|
|
68
|
+
...base,
|
|
69
|
+
label,
|
|
70
|
+
...(ariaLabel && ariaLabel !== label ? { ariaLabel } : {}),
|
|
71
|
+
...(href ? { href } : {}),
|
|
72
|
+
relation,
|
|
73
|
+
disabled: false,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/** The summary action for a known current plan and the relation of the selection in effect. */
|
|
77
|
+
export function summaryActionState(viewModel, relation) {
|
|
78
|
+
const quote = viewModel.resolved.requiresQuote;
|
|
79
|
+
return {
|
|
80
|
+
actionId: quote ? CONTACT_SALES_ACTION_ID : REVIEW_CHANGE_ACTION_ID,
|
|
81
|
+
label: quote
|
|
82
|
+
? translate(viewModel.messages, 'pricing.contactSales')
|
|
83
|
+
: translate(viewModel.messages, 'pricing.reviewChangeCta', {
|
|
84
|
+
total: formatCurrency(viewModel.resolved.subtotal, viewModel.pricing.metadata.currency, viewModel.locale),
|
|
85
|
+
}),
|
|
86
|
+
relation,
|
|
87
|
+
disabled: relation === 'current',
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=cta.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cta.js","sourceRoot":"","sources":["../../src/element/cta.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type NormalizedPricing, type PricingDiagnostic, type PricingSelection } from '../core/index.js';
|
|
2
|
+
/** What the element marks as current, derived from the loaded pricing. */
|
|
3
|
+
export interface CurrentContext {
|
|
4
|
+
/** The current plan id; always a plan id of the pricing. */
|
|
5
|
+
planId: string;
|
|
6
|
+
/** The add-ons still selected after reconciliation on the current plan. */
|
|
7
|
+
addOnIds: ReadonlySet<string>;
|
|
8
|
+
}
|
|
9
|
+
/** The current side of Decision 2 (steps 1 to 4), or `undefined` without a known current plan. */
|
|
10
|
+
export declare function deriveCurrentContext(pricing: NormalizedPricing, current: Partial<PricingSelection> | undefined): CurrentContext | undefined;
|
|
11
|
+
/** One warning per plan id or add-on id of the current selection that the pricing does not define. */
|
|
12
|
+
export declare function currentSelectionDiagnostics(pricing: NormalizedPricing, current: Partial<PricingSelection> | undefined): PricingDiagnostic[];
|
|
13
|
+
//# sourceMappingURL=current-selection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"current-selection.d.ts","sourceRoot":"","sources":["../../src/element/current-selection.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACtB,MAAM,kBAAkB,CAAC;AAE1B,0EAA0E;AAC1E,MAAM,WAAW,cAAc;IAC7B,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC/B;AAKD,kGAAkG;AAGlG,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,SAAS,GAC7C,cAAc,GAAG,SAAS,CAoB5B;AAED,sGAAsG;AACtG,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,SAAS,GAC7C,iBAAiB,EAAE,CAuBrB"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { isRecord, mergeSelection, reconcileSelection, } from '../core/index.js';
|
|
2
|
+
const hasId = (items, id) => items.some((item) => item.id === id);
|
|
3
|
+
/** The current side of Decision 2 (steps 1 to 4), or `undefined` without a known current plan. */
|
|
4
|
+
// Without a known plan, reconciling would use the default plan, which is not the customer's, so no
|
|
5
|
+
// add-on is marked either. Unknown add-on ids are ignored.
|
|
6
|
+
export function deriveCurrentContext(pricing, current) {
|
|
7
|
+
if (!isRecord(current))
|
|
8
|
+
return undefined;
|
|
9
|
+
const planId = typeof current.planId === 'string' ? current.planId : undefined;
|
|
10
|
+
if (planId === undefined || !hasId(pricing.plans, planId))
|
|
11
|
+
return undefined;
|
|
12
|
+
const addOns = {};
|
|
13
|
+
if (isRecord(current.addOns)) {
|
|
14
|
+
for (const [id, entry] of Object.entries(current.addOns)) {
|
|
15
|
+
if (!hasId(pricing.addOns, id) || !isRecord(entry) || typeof entry.selected !== 'boolean') {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
const quantity = typeof entry.quantity === 'number' ? entry.quantity : 0;
|
|
19
|
+
addOns[id] = { selected: entry.selected, quantity };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const { selection } = reconcileSelection(pricing, mergeSelection(pricing, { planId, addOns }));
|
|
23
|
+
const addOnIds = new Set();
|
|
24
|
+
for (const [id, entry] of Object.entries(selection.addOns)) {
|
|
25
|
+
if (entry.selected)
|
|
26
|
+
addOnIds.add(id);
|
|
27
|
+
}
|
|
28
|
+
return { planId, addOnIds };
|
|
29
|
+
}
|
|
30
|
+
/** One warning per plan id or add-on id of the current selection that the pricing does not define. */
|
|
31
|
+
export function currentSelectionDiagnostics(pricing, current) {
|
|
32
|
+
if (!isRecord(current))
|
|
33
|
+
return [];
|
|
34
|
+
const diagnostics = [];
|
|
35
|
+
if (typeof current.planId === 'string' && !hasId(pricing.plans, current.planId)) {
|
|
36
|
+
diagnostics.push({
|
|
37
|
+
code: 'PR_CURRENT_SELECTION_UNKNOWN_PLAN',
|
|
38
|
+
severity: 'warning',
|
|
39
|
+
message: `Unknown plan "${current.planId}" in currentSelection; no plan is marked as current.`,
|
|
40
|
+
path: 'currentSelection.planId',
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
if (isRecord(current.addOns)) {
|
|
44
|
+
for (const id of Object.keys(current.addOns)) {
|
|
45
|
+
if (hasId(pricing.addOns, id))
|
|
46
|
+
continue;
|
|
47
|
+
diagnostics.push({
|
|
48
|
+
code: 'PR_CURRENT_SELECTION_UNKNOWN_ADDON',
|
|
49
|
+
severity: 'warning',
|
|
50
|
+
message: `Unknown add-on "${id}" in currentSelection; it is ignored.`,
|
|
51
|
+
path: `currentSelection.addOns.${id}`,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return diagnostics;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=current-selection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"current-selection.js","sourceRoot":"","sources":["../../src/element/current-selection.ts"],"names":[],"mappings":"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"}
|