@owlmeans/web-payment 0.1.18-rc.10 → 0.1.18-rc.12

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 (111) hide show
  1. package/README.md +30 -1
  2. package/agent-meta/manifest.json +2 -2
  3. package/agent-meta/skills/web-payment/SKILL.md +145 -20
  4. package/build/@/components/ui/card.d.ts +10 -0
  5. package/build/@/components/ui/card.d.ts.map +1 -0
  6. package/build/@/components/ui/card.js +25 -0
  7. package/build/@/components/ui/card.js.map +1 -0
  8. package/build/@/components/ui/progress.d.ts +5 -0
  9. package/build/@/components/ui/progress.d.ts.map +1 -0
  10. package/build/@/components/ui/progress.js +11 -0
  11. package/build/@/components/ui/progress.js.map +1 -0
  12. package/build/@/components/ui/select.d.ts +8 -0
  13. package/build/@/components/ui/select.d.ts.map +1 -0
  14. package/build/@/components/ui/select.js +9 -0
  15. package/build/@/components/ui/select.js.map +1 -0
  16. package/build/capability-list.d.ts +7 -0
  17. package/build/capability-list.d.ts.map +1 -0
  18. package/build/capability-list.js +24 -0
  19. package/build/capability-list.js.map +1 -0
  20. package/build/copy.d.ts +14 -0
  21. package/build/copy.d.ts.map +1 -0
  22. package/build/copy.js +51 -0
  23. package/build/copy.js.map +1 -0
  24. package/build/dialog.d.ts +1 -1
  25. package/build/dialog.d.ts.map +1 -1
  26. package/build/dialog.js +5 -2
  27. package/build/dialog.js.map +1 -1
  28. package/build/entitlement.d.ts +26 -0
  29. package/build/entitlement.d.ts.map +1 -0
  30. package/build/entitlement.js +42 -0
  31. package/build/entitlement.js.map +1 -0
  32. package/build/estimate-cache.d.ts +14 -0
  33. package/build/estimate-cache.d.ts.map +1 -0
  34. package/build/estimate-cache.js +39 -0
  35. package/build/estimate-cache.js.map +1 -0
  36. package/build/estimate-summary.d.ts +56 -0
  37. package/build/estimate-summary.d.ts.map +1 -0
  38. package/build/estimate-summary.js +91 -0
  39. package/build/estimate-summary.js.map +1 -0
  40. package/build/estimate.d.ts +28 -0
  41. package/build/estimate.d.ts.map +1 -0
  42. package/build/estimate.js +67 -0
  43. package/build/estimate.js.map +1 -0
  44. package/build/hooks.d.ts +0 -4
  45. package/build/hooks.d.ts.map +1 -1
  46. package/build/hooks.js +3 -30
  47. package/build/hooks.js.map +1 -1
  48. package/build/i18n/be.json +1 -1
  49. package/build/i18n/de.json +1 -1
  50. package/build/i18n/en.json +1 -1
  51. package/build/i18n/es.json +1 -1
  52. package/build/i18n/pl.json +1 -1
  53. package/build/i18n/ru.json +1 -1
  54. package/build/i18n/uk.json +1 -1
  55. package/build/index.d.ts +7 -0
  56. package/build/index.d.ts.map +1 -1
  57. package/build/index.js +7 -0
  58. package/build/index.js.map +1 -1
  59. package/build/limit-meter.d.ts +7 -0
  60. package/build/limit-meter.d.ts.map +1 -0
  61. package/build/limit-meter.js +26 -0
  62. package/build/limit-meter.js.map +1 -0
  63. package/build/plan-card.d.ts +7 -0
  64. package/build/plan-card.d.ts.map +1 -0
  65. package/build/plan-card.js +29 -0
  66. package/build/plan-card.js.map +1 -0
  67. package/build/poll.d.ts +7 -0
  68. package/build/poll.d.ts.map +1 -0
  69. package/build/poll.js +28 -0
  70. package/build/poll.js.map +1 -0
  71. package/build/selectors.d.ts +18 -0
  72. package/build/selectors.d.ts.map +1 -0
  73. package/build/selectors.js +78 -0
  74. package/build/selectors.js.map +1 -0
  75. package/build/types.d.ts +97 -1
  76. package/build/types.d.ts.map +1 -1
  77. package/package.json +11 -7
  78. package/src/@/components/ui/card.tsx +93 -0
  79. package/src/@/components/ui/progress.tsx +44 -0
  80. package/src/@/components/ui/select.tsx +62 -0
  81. package/src/@/globals.css +10 -0
  82. package/src/capability-list.tsx +50 -0
  83. package/src/copy.tsx +62 -0
  84. package/src/dialog.tsx +5 -2
  85. package/src/entitlement.ts +56 -0
  86. package/src/estimate-cache.ts +40 -0
  87. package/src/estimate-summary.tsx +162 -0
  88. package/src/estimate.ts +93 -0
  89. package/src/hooks.ts +3 -35
  90. package/src/i18n/be.json +1 -1
  91. package/src/i18n/de.json +1 -1
  92. package/src/i18n/en.json +1 -1
  93. package/src/i18n/es.json +1 -1
  94. package/src/i18n/pl.json +1 -1
  95. package/src/i18n/ru.json +1 -1
  96. package/src/i18n/uk.json +1 -1
  97. package/src/index.ts +7 -0
  98. package/src/limit-meter.tsx +55 -0
  99. package/src/plan-card.tsx +67 -0
  100. package/src/poll.ts +27 -0
  101. package/src/selectors.ts +93 -0
  102. package/src/types.ts +118 -1
  103. package/tests/context.ts +9 -0
  104. package/tests/dialog.spec.ts +49 -0
  105. package/tests/entitlement.spec.ts +117 -0
  106. package/tests/estimate-cache.spec.ts +46 -0
  107. package/tests/harness/entitlement.tsx +159 -0
  108. package/tests/harness/estimate-fixtures.ts +48 -0
  109. package/tests/harness/mount.tsx +12 -3
  110. package/tests/i18n.spec.ts +40 -6
  111. package/tests/pieces.spec.ts +134 -0
package/README.md CHANGED
@@ -28,6 +28,35 @@ Checkout redirects the current window by default; pass `useCheckout('_blank')` o
28
28
  is intentional. The dialog uses the consumer's `@/components/ui/*` primitives, semantic theme
29
29
  tokens, integer minor units, and the packaged seven-language `web-payment` resource.
30
30
 
31
+ ## Entitlements
32
+
33
+ `useEntitlementView(ctx.entrypoint(account.entitlements))` polls a served `EntitlementView` and
34
+ revives its ISO dates; `null` means "not known yet", so render paid controls disabled until it
35
+ answers. Read it with `useCapability(view, param)` (`boolean | null`) and `useLimit(view, key)`
36
+ (the limit row plus `exhausted` and a `ratio` clamped to `[0, 1]`). An application that keeps the
37
+ view in its own store uses the pure selectors instead — `capabilityStateOf`, `limitStatusOf`,
38
+ `planStatusLineOf`, `promoInscriptionOf` — and never polls a second time.
39
+
40
+ ```tsx
41
+ const view = useEntitlementView(ctx.entrypoint(account.entitlements))
42
+ const seats = useLimit(view, 'seats')
43
+ const { portal, pending } = usePortal(PortalFlow.Change)
44
+
45
+ {view != null && <>
46
+ <PlanCard plan={view.plan} offer={{ sku: 'pro-monthly', title: 'Pro', priceLabel: '$20 / month' }}
47
+ actionLabel="Change plan" pending={pending}
48
+ onAction={planSku => portal(ctx.entrypoint(account.portal), { body: { planSku } })} />
49
+ {seats != null && <LimitMeter limit={seats} label="Seats" />}
50
+ <CapabilityList capabilities={view.capabilities} labels={{ 'feature:whitelabel': 'White label' }} />
51
+ </>}
52
+ ```
53
+
54
+ `usePortal(flow)` sets `body.flow` on a protocol whose body is a `PortalLinkBody` and sends the
55
+ browser to the returned URL. The pieces take data and callbacks only: titles, prices, labels and
56
+ action copy come from the application; status lines, "N of M", reset dates and promo inscriptions
57
+ come from the packaged `entitlement` strings. They import `@/components/ui/{card,progress,button}`,
58
+ so the consumer provides those primitives and `@radix-ui/react-progress`.
59
+
31
60
  <!-- owlmeans:agent-guidance:start -->
32
61
  ## Agent guidance
33
62
 
@@ -36,7 +65,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
36
65
  your project's skill store (`.agents/skills/`):
37
66
 
38
67
  ```sh
39
- npx @owlmeans/agent-skills@^0.1.18-rc.27
68
+ npx @owlmeans/agent-skills@^0.1.18-rc.29
40
69
  ```
41
70
 
42
71
  The embedded files are version-matched to this package release. Do not edit them
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@owlmeans/web-payment",
4
- "version": "0.1.18-rc.10",
5
- "generatedAt": "2026-09-15T14:02:13.060Z",
4
+ "version": "0.1.18-rc.12",
5
+ "generatedAt": "2026-09-18T19:03:53.990Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -7,13 +7,17 @@ user-invocable: false
7
7
 
8
8
  # @owlmeans/web-payment
9
9
 
10
- **Install:** `bun add @owlmeans/web-payment@^0.1.18-rc.10`
10
+ **Install:** `bun add @owlmeans/web-payment@^0.1.18-rc.12`
11
11
 
12
12
  Public MIT web package paired with `@owlmeans/server-payment`. It incorporates checkout, balance,
13
- entitlement and shallow-auth helpers over the underlying `@owlmeans/client-payment` service.
13
+ entitlement and shallow-auth helpers over the underlying `@owlmeans/client-payment` service, plus
14
+ presentational pieces over the entitlement view of `@owlmeans/payment` (the model itself is the
15
+ `entitlements` skill).
16
+
17
+ ## Protocol-bound hooks
14
18
 
15
19
  Hooks accept `RegisteredEntrypoint<Request, Response>` values. Pass `ctx.entrypoint(protocol)`;
16
- never weaken a protocol to a home-grown callable type or recover its I/O with a generic. Checkout
20
+ never weaken a protocol to a home-grown callable type or recover its I/O with a generic. Call
17
21
  arguments use the protocol's `CallArguments`, so a required body cannot be omitted by the hook.
18
22
 
19
23
  ```typescript
@@ -21,30 +25,151 @@ const { checkout, pending } = useCheckout() // same-window by default
21
25
  await checkout(ctx.entrypoint(account.topUp), { body: { amountMinor } })
22
26
  ```
23
27
 
24
- `useCheckout('_blank')` is the explicit new-tab variant. `openCheckout(url)` defaults to
25
- `window.location.assign`; both are inert when no DOM exists. `usePaymentBalance` polls one protocol,
26
- `useEntitlements` extracts its list, and `useEntitlement` uses the shared payment predicate. `null`
27
- means not known and must render paid controls disabled.
28
+ - `useCheckout('_blank')` is the explicit new-tab variant. `openCheckout(url)` defaults to
29
+ `window.location.assign`; both are inert when no DOM exists.
30
+ - `usePaymentBalance(entry, intervalMs?, deps?)` polls one protocol and keeps the last good answer;
31
+ a failed poll is swallowed, because explicit actions own their errors.
32
+
33
+ ## Entitlement hooks — `null` means unknown
34
+
35
+ | Hook | Answers |
36
+ |---|---|
37
+ | `useEntitlementView(entry, intervalMs = 60_000, deps = [], ...request)` | The polled `EntitlementView`, revived (`reviveEntitlementView`) so every date is a `Date`; `null` until the first answer. Trailing `request` arguments are the protocol's `CallArguments`. |
38
+ | `useCapability(view, param)` | `boolean \| null` — the capability predicate over granted rows; `null` for a null view. |
39
+ | `useLimit(view, key)` | `LimitStatus \| null` — the `LimitView` plus `exhausted` and `ratio`; `null` for a null view or an undeclared key. |
40
+ | `usePortal(flow, target = '_self')` | `{ portal(entry, request?), pending }` — calls a protocol whose body is a `PortalLinkBody` with `body.flow = flow`, then `openCheckout(url, target)`. The caller's arguments omit `flow` (a compile error otherwise); navigation is inert without a DOM. |
41
+
42
+ - **`null` renders paid controls disabled**, never enabled-then-refused. A `false` is an answer;
43
+ `null` is the absence of one.
44
+ - **One poller per view.** An application that keeps the view in its own store (fed once, refreshed
45
+ after the actions that change it) reads it through the pure selectors, not a second
46
+ `useEntitlementView`.
47
+ - Anything read off a view fetched some other way must be revived before a date is used.
48
+
49
+ ## Pure selectors
50
+
51
+ | Selector | Returns |
52
+ |---|---|
53
+ | `capabilityStateOf(view, param)` | `boolean \| null` — what `useCapability` memoizes |
54
+ | `limitStatusOf(limitView)` | `LimitStatus \| null` — `exhausted = remaining < 1` (a `limit: 0` row is exhausted); `ratio = used / limit` clamped to `[0, 1]`, and for a `0` ceiling `1` once anything is used, else `0` |
55
+ | `planStatusLineOf(planView)` | `{ kind, tone, date? }` — first match: `created`/`canceled`/`expired`/`ended` (inactive), `blocked` (critical), `paused` (a `pausedAt`, warning), `suspended` (critical), `trial` (`trialEnd`), `past-due` (warning), `cancel-scheduled` (`periodEnd`, warning), `free`, `renews` (`periodEnd`), `active` |
56
+ | `promoInscriptionOf(promoView)` | `'free-until'` (active, not grandfathered) · `'grandfathered'` (active, grandfathered) · `'ended'` (inactive) · `null` |
57
+
58
+ Use these, plus `capabilityOf` / `limitOf` / `hasLimitRoom` from `@owlmeans/payment`, wherever the
59
+ browser decides something; the server gate uses the same predicates, so a disabled button and a
60
+ 403 cannot disagree.
61
+
62
+ ## Pieces
63
+
64
+ Pieces take data and callbacks only — no protocol calls, no product copy (titles, prices, labels
65
+ and action text come from the application). Every one accepts `className`.
66
+
67
+ | Piece | Props | Renders |
68
+ |---|---|---|
69
+ | `PlanCard` | `plan: EntitlementPlanView`, `offer?: { sku, title, priceLabel, highlight? }`, `current?`, `pending?`, `actionLabel?`, `onAction?(sku)`, `children?` | Title; the status line (with a tone dot) for the entity's own plan, or for an offer only when it is current; a "Current plan" badge; `priceLabel`; children; one action button (outline when current, disabled while `pending`). `current` defaults to `offer.sku === plan.sku`. |
70
+ | `LimitMeter` | `limit: LimitView`, `label`, `showReset? = true`, `compact?` | `used of limit` (with `unit`), a `Progress` bar, "Limit reached" when exhausted, "Resets on …" for a window limit, the promo inscription. `limit: 0` reads "Not included" and draws no bar. |
71
+ | `CapabilityList` | `capabilities: CapabilityView[]`, `labels: Record<param, string>`, `onlyGranted?` | One row per labelled param in view order (duplicate params collapse, granted wins); unlabelled rows are not rendered; ungranted rows are muted; promo inscription under the label. |
72
+
73
+ - **Stable selectors** for tests and styling: `[data-plan-card]` with `data-plan-sku`,
74
+ `data-plan-status` (the line kind), `data-plan-tone`, `data-current`; `[data-plan-status-line]`,
75
+ `[data-plan-current]`, `[data-plan-price]`; `[data-limit-meter]` with `data-limit-key`,
76
+ `data-limit-kind`, `data-included`, `data-exhausted`, and `[data-limit-usage]`,
77
+ `[data-limit-resets]`, `[data-limit-exhausted]`; `[data-capability-list]`, `[data-capability]`
78
+ with `data-granted`; `[data-promo]` carrying the inscription kind.
79
+ - **Dates render as calendar UTC days** (`dateStyle: 'medium'`) in the current language — the
80
+ calendar limit windows count in, so a reset date names the day the counter rolls.
81
+ - Promo copy: "Free until {{date}}", "Included for your plan", "Promotion ended".
28
82
 
29
83
  ## AmountCheckoutDialog
30
84
 
31
- The dialog takes `{ open, onOpenChange, policy, pending, onConfirm }`. It keeps integer minor units,
32
- accepts locale decimal separators and at most two decimals, shows configured presets plus custom
33
- input, and reports below/above-bound errors without clamping. Confirmation is disabled when invalid
34
- or pending.
85
+ The dialog takes `{ open, onOpenChange, policy, pending, onConfirm, estimate? }`. It keeps integer
86
+ minor units, accepts locale decimal separators and at most two decimals, shows configured presets
87
+ plus custom input, and reports below/above-bound errors without clamping. Confirmation is disabled
88
+ when invalid or pending.
35
89
 
36
- It shows net credit value, processing adjustment and pre-tax subtotal from `chargeAmountMinor`, plus
37
- the note that Stripe calculates applicable tax. The policy maximum bounds net credit, not the
38
- adjusted or tax-inclusive debit.
90
+ It shows net credit value, processing adjustment and pre-tax subtotal from `chargeAmountMinor`.
91
+ With no `estimate`, the plain note that Stripe calculates applicable tax; with one, `PriceEstimateSummary`
92
+ renders instead (see below) against the SAME `chargeMinor`, so the country picker and its numbers
93
+ track whatever the buyer has typed. The policy maximum bounds net credit, not the adjusted or
94
+ tax-inclusive debit.
39
95
 
40
- The component imports the consuming app's shadcn primitives from
41
- `@/components/ui/{dialog,input,label,button}` and uses semantic theme tokens. The package carries
42
- standalone copies under `src/@` only so its own build/tests resolve the same alias contract. A
43
- Tailwind v4 consumer scanning package source adds:
96
+ ## Price estimate: a live tax/currency read for any amount
97
+
98
+ ```typescript
99
+ // self-contained (one estimate, its own picker) — the credit dialog:
100
+ const estimate = usePriceEstimate(ctx.entrypoint(account.priceEstimate), { enabled: dialogOpen })
101
+ <AmountCheckoutDialog … estimate={estimate} />
102
+ <PriceEstimateSummary control={estimate} subtotalMinor={planPriceMinor} currency="usd" />
103
+
104
+ // shared (one picker, several estimates) — a plan comparison table:
105
+ const [country, setCountry] = useState('')
106
+ const pro = usePriceEstimate(entry, { enabled, country, onCountryChange: setCountry }, { body: { planSku: 'pro' } })
107
+ const team = usePriceEstimate(entry, { enabled, country, onCountryChange: setCountry }, { body: { planSku: 'team' } })
108
+ <CountrySelect value={country} onChange={setCountry} /> {/* rendered ONCE */}
109
+ <PriceEstimateAmount control={pro} subtotalMinor={proPriceMinor} currency="usd" /> {/* per offer */}
110
+ <PriceEstimateAmount control={team} subtotalMinor={teamPriceMinor} currency="usd" />
111
+ ```
112
+
113
+ - **`usePriceEstimate(entry, { enabled, ttlMs?, country?, onCountryChange? }, ...request)`** calls a
114
+ `PriceEstimateBody` protocol (`@owlmeans/payment`'s `PriceEstimate` response) only while `enabled`,
115
+ and again whenever the country changes — a closed dialog costs nothing. A module-level client
116
+ cache (keyed by the entry's alias, the request body and the country; default TTL 5 min) shares an
117
+ answer across every mounted instance and never caches a rejected fetch. The caller's `request`
118
+ omits `body.country` — the hook owns it — the same way `usePortal`'s omits `flow`.
119
+ - **Uncontrolled** (no `opts.country`): the hook owns the country itself, and the first answer
120
+ whose `source` is `'customer'` preselects it, once.
121
+ - **Controlled** (`opts.country` given): the caller owns the country — several `usePriceEstimate`
122
+ calls can share ONE value (a plan comparison table, one picker, one estimate per offer); the
123
+ hook never preselects on its own, and the returned control's `onCountryChange` calls
124
+ `opts.onCountryChange` instead of an internal setter.
125
+ - **`CountrySelect({ value, onChange, label?, id?, className? })`** is the picker alone —
126
+ `Intl.DisplayNames` + `Intl.Collator` over `@owlmeans/payment`'s `COUNTRY_CODES`, so it lists the
127
+ buyer's language's own country names. Render it once and drive every estimate that shares it.
128
+ - **`PriceEstimateAmount({ control, subtotalMinor, currency, suffix?, className? })`** is the
129
+ numbers alone, no picker: via `estimateOf` re-derived against `subtotalMinor`, a rate row for a
130
+ `taxed` status, an estimated total, and one sentence for every status that leaves no number to
131
+ trust (reverse charge, no tax, "at checkout", "choose a country"). `data-price-estimate` /
132
+ `data-status` are stable test hooks.
133
+ - When the estimate carries `local` (Adaptive Pricing found the country's currency), the tax and
134
+ total show ONLY in that currency, each marked `≈` — never both currencies at once, which would
135
+ read as two different prices for the same line. A short note explains the amount is converted
136
+ at Stripe's current rate and confirmed at checkout. With no `local`, the amounts show in
137
+ `currency` (the integration currency) with no `≈` and no note.
138
+ - **`PriceEstimateSummary`** is `CountrySelect` bound to the control's own `country`/
139
+ `onCountryChange` followed by `PriceEstimateAmount` — the one-estimate composition. Building a
140
+ shared picker composes the two pieces separately instead, one `PriceEstimateAmount` per estimate.
141
+
142
+ ## The `@/components/ui/*` contract
143
+
144
+ Components import the consuming app's shadcn primitives through the app alias:
145
+ `@/components/ui/{button,dialog,input,label,select}` for the dialog and estimate summary and
146
+ `@/components/ui/{card,progress,button}` for the pieces (`Card`, `CardHeader`, `CardTitle`,
147
+ `CardDescription`, `CardContent`, `CardFooter`, `Progress`). The consumer therefore provides those
148
+ files and the peers `@radix-ui/react-progress` / `@radix-ui/react-select` beside the dialog's Radix
149
+ ones. The package carries standalone copies under `src/@` only so its own build and tests resolve
150
+ the same alias; they are never exported. Styling uses semantic theme tokens only (`primary`,
151
+ `muted-foreground`, `destructive`, `border`, `card`).
152
+
153
+ A Tailwind v4 consumer scanning package source adds:
44
154
 
45
155
  ```css
46
156
  @source "../../node_modules/@owlmeans/web-payment/src";
47
157
  ```
48
158
 
49
- All visible strings live in the `web-payment` library resource and must stay present in all seven
50
- languages: `en pl ru be uk es de`.
159
+ ## Strings
160
+
161
+ All visible strings live in the `web-payment` library resource (`lib` namespace) in all seven
162
+ languages — `en pl ru be uk es de` — under three branches: `amount-checkout`, `entitlement`
163
+ (`plan`, `status`, `limit`, `promo`, `capability`) and `estimate` (`country`, `tax-type`, `rate`,
164
+ `total`, `converted-note`, `status`, `loading`, `failed`). A new key lands in every language at once, with
165
+ the same `{{placeholders}}`; the parity spec walks the resources recursively. An application
166
+ overrides a string with `addI18nApp(lng, 'web-payment', data, { ns: LIB_NAMESPACE })`.
167
+
168
+ ## Tests
169
+
170
+ Category D plus unit specs: `bun test ./tests` runs the selector, hook and cache specs (hooks
171
+ rendered with `react-dom/server`, a fake `window` for navigation) and drives chromium through the
172
+ Vite harness, which picks a surface by `?case=` (none = the dialog, `pieces`, `hook`) and, for the
173
+ dialog, an `?estimate=<name>` canned `PriceEstimateControl` fixture (`tests/harness/estimate-fixtures.ts`
174
+ — no server, no Stripe). The harness pre-bundles every runtime dependency in `optimizeDeps.include`;
175
+ one discovered mid-navigation loads a second React and the page throws "Invalid hook call".
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+ declare function Card({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
3
+ declare function CardHeader({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
4
+ declare function CardTitle({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
5
+ declare function CardDescription({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
6
+ declare function CardAction({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
7
+ declare function CardContent({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
8
+ declare function CardFooter({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
9
+ export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent, };
10
+ //# sourceMappingURL=card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../../../src/@/components/ui/card.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,iBAAS,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWjE;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWvE;AAED,iBAAS,SAAS,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQtE;AAED,iBAAS,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQ5E;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWvE;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQxE;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQvE;AAED,OAAO,EACL,IAAI,EACJ,UAAU,EACV,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,WAAW,GACZ,CAAA"}
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from '@/lib/utils';
3
+ function Card({ className, ...props }) {
4
+ return (_jsx("div", { "data-slot": "card", className: cn("bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm", className), ...props }));
5
+ }
6
+ function CardHeader({ className, ...props }) {
7
+ return (_jsx("div", { "data-slot": "card-header", className: cn("@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6", className), ...props }));
8
+ }
9
+ function CardTitle({ className, ...props }) {
10
+ return (_jsx("div", { "data-slot": "card-title", className: cn("leading-none font-semibold", className), ...props }));
11
+ }
12
+ function CardDescription({ className, ...props }) {
13
+ return (_jsx("div", { "data-slot": "card-description", className: cn("text-muted-foreground text-sm", className), ...props }));
14
+ }
15
+ function CardAction({ className, ...props }) {
16
+ return (_jsx("div", { "data-slot": "card-action", className: cn("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className), ...props }));
17
+ }
18
+ function CardContent({ className, ...props }) {
19
+ return (_jsx("div", { "data-slot": "card-content", className: cn("px-6", className), ...props }));
20
+ }
21
+ function CardFooter({ className, ...props }) {
22
+ return (_jsx("div", { "data-slot": "card-footer", className: cn("flex items-center px-6 [.border-t]:pt-6", className), ...props }));
23
+ }
24
+ export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent, };
25
+ //# sourceMappingURL=card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card.js","sourceRoot":"","sources":["../../../../src/@/components/ui/card.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAEhC,SAAS,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IAChE,OAAO,CACL,2BACY,MAAM,EAChB,SAAS,EAAE,EAAE,CACX,mFAAmF,EACnF,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CACX,4JAA4J,EAC5J,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,SAAS,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACrE,OAAO,CACL,2BACY,YAAY,EACtB,SAAS,EAAE,EAAE,CAAC,4BAA4B,EAAE,SAAS,CAAC,KAClD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IAC3E,OAAO,CACL,2BACY,kBAAkB,EAC5B,SAAS,EAAE,EAAE,CAAC,+BAA+B,EAAE,SAAS,CAAC,KACrD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CACX,gEAAgE,EAChE,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACvE,OAAO,CACL,2BACY,cAAc,EACxB,SAAS,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,KAC5B,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CAAC,yCAAyC,EAAE,SAAS,CAAC,KAC/D,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EACL,IAAI,EACJ,UAAU,EACV,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,WAAW,GACZ,CAAA"}
@@ -0,0 +1,5 @@
1
+ import * as React from 'react';
2
+ import * as ProgressPrimitive from '@radix-ui/react-progress';
3
+ declare function Progress({ className, value, ...props }: React.ComponentProps<typeof ProgressPrimitive.Root>): React.JSX.Element;
4
+ export { Progress };
5
+ //# sourceMappingURL=progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../../../src/@/components/ui/progress.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,iBAAiB,MAAM,0BAA0B,CAAA;AAI7D,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,KAAK,EACL,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,iBAAiB,CAAC,IAAI,CAAC,qBA4BrD;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as ProgressPrimitive from '@radix-ui/react-progress';
3
+ import { cn } from '@/lib/utils';
4
+ function Progress({ className, value, ...props }) {
5
+ const indeterminate = value == null;
6
+ return (_jsx(ProgressPrimitive.Root, { "data-slot": "progress", className: cn("bg-primary/20 relative h-2 w-full overflow-hidden rounded-full", className), value: indeterminate ? undefined : value, ...props, children: _jsx(ProgressPrimitive.Indicator, { "data-slot": "progress-indicator", "data-state": indeterminate ? 'indeterminate' : 'determinate', className: cn("bg-primary h-full w-full flex-1 transition-all", indeterminate && "absolute inset-y-0 left-0 w-1/3 animate-[progress-indeterminate_1.5s_linear_infinite]"), style: indeterminate
7
+ ? undefined
8
+ : { transform: `translateX(-${100 - (value || 0)}%)` } }) }));
9
+ }
10
+ export { Progress };
11
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../../../../src/@/components/ui/progress.tsx"],"names":[],"mappings":";AAKA,OAAO,KAAK,iBAAiB,MAAM,0BAA0B,CAAA;AAE7D,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAEhC,SAAS,QAAQ,CAAC,EAChB,SAAS,EACT,KAAK,EACL,GAAG,KAAK,EAC4C;IACpD,MAAM,aAAa,GAAG,KAAK,IAAI,IAAI,CAAA;IAEnC,OAAO,CACL,KAAC,iBAAiB,CAAC,IAAI,iBACX,UAAU,EACpB,SAAS,EAAE,EAAE,CACX,gEAAgE,EAChE,SAAS,CACV,EACD,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,KACpC,KAAK,YAET,KAAC,iBAAiB,CAAC,SAAS,iBAChB,oBAAoB,gBAClB,aAAa,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,aAAa,EAC3D,SAAS,EAAE,EAAE,CACX,gDAAgD,EAChD,aAAa,IAAI,uFAAuF,CACzG,EACD,KAAK,EACH,aAAa;gBACX,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,EAAE,SAAS,EAAE,eAAe,GAAG,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,EAAE,GAE1D,GACqB,CAC1B,CAAA;AACH,CAAC;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
@@ -0,0 +1,8 @@
1
+ import * as React from 'react';
2
+ import * as SelectPrimitive from '@radix-ui/react-select';
3
+ export declare const Select: (props: React.ComponentProps<typeof SelectPrimitive.Root>) => React.JSX.Element;
4
+ export declare const SelectValue: (props: React.ComponentProps<typeof SelectPrimitive.Value>) => React.JSX.Element;
5
+ export declare const SelectTrigger: ({ className, children, ...props }: React.ComponentProps<typeof SelectPrimitive.Trigger>) => React.JSX.Element;
6
+ export declare const SelectContent: ({ className, children, position, ...props }: React.ComponentProps<typeof SelectPrimitive.Content>) => React.JSX.Element;
7
+ export declare const SelectItem: ({ className, children, ...props }: React.ComponentProps<typeof SelectPrimitive.Item>) => React.JSX.Element;
8
+ //# sourceMappingURL=select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../../src/@/components/ui/select.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAA;AAGzD,eAAO,MAAM,MAAM,UAAW,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC,sBAAwC,CAAA;AACvH,eAAO,MAAM,WAAW,UAAW,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,sBAAyC,CAAA;AAE9H,eAAO,MAAM,aAAa,sCAAuC,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,OAAO,CAAC,sBAepH,CAAA;AAED,eAAO,MAAM,aAAa,gDAA4D,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,OAAO,CAAC,sBAsBzI,CAAA;AAED,eAAO,MAAM,UAAU,sCAAuC,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC,sBAa9G,CAAA"}
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as SelectPrimitive from '@radix-ui/react-select';
3
+ import { cn } from '@/lib/utils';
4
+ export const Select = (props) => _jsx(SelectPrimitive.Root, { ...props });
5
+ export const SelectValue = (props) => _jsx(SelectPrimitive.Value, { ...props });
6
+ export const SelectTrigger = ({ className, children, ...props }) => (_jsxs(SelectPrimitive.Trigger, { className: cn('border-input data-[placeholder]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50', 'flex h-9 w-full items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm shadow-xs', 'outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50', className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { asChild: true, children: _jsx("span", { "aria-hidden": "true", className: "text-muted-foreground shrink-0", children: "\u25BE" }) })] }));
7
+ export const SelectContent = ({ className, children, position = 'popper', ...props }) => (_jsx(SelectPrimitive.Portal, { children: _jsxs(SelectPrimitive.Content, { position: position, className: cn('bg-popover text-popover-foreground relative z-50 max-h-96 min-w-[8rem] overflow-y-auto rounded-md border shadow-md', position === 'popper' && 'data-[side=bottom]:translate-y-1 data-[side=top]:-translate-y-1', className), ...props, children: [_jsx(SelectPrimitive.ScrollUpButton, { className: "flex items-center justify-center py-1", children: _jsx("span", { "aria-hidden": "true", children: "\u25B4" }) }), _jsx(SelectPrimitive.Viewport, { className: cn('p-1', position === 'popper' && 'w-full min-w-[var(--radix-select-trigger-width)]'), children: children }), _jsx(SelectPrimitive.ScrollDownButton, { className: "flex items-center justify-center py-1", children: _jsx("span", { "aria-hidden": "true", children: "\u25BE" }) })] }) }));
8
+ export const SelectItem = ({ className, children, ...props }) => (_jsxs(SelectPrimitive.Item, { className: cn('focus:bg-accent focus:text-accent-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50', className), ...props, children: [_jsx("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: _jsx(SelectPrimitive.ItemIndicator, { "aria-hidden": "true", children: "\u2713" }) }), _jsx(SelectPrimitive.ItemText, { children: children })] }));
9
+ //# sourceMappingURL=select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../../../../src/@/components/ui/select.tsx"],"names":[],"mappings":";AACA,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAEhC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,KAAwD,EAAE,EAAE,CAAC,KAAC,eAAe,CAAC,IAAI,OAAK,KAAK,GAAI,CAAA;AACvH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAyD,EAAE,EAAE,CAAC,KAAC,eAAe,CAAC,KAAK,OAAK,KAAK,GAAI,CAAA;AAE9H,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAwD,EAAE,EAAE,CAAC,CACxH,MAAC,eAAe,CAAC,OAAO,IACtB,SAAS,EAAE,EAAE,CACX,4GAA4G,EAC5G,iHAAiH,EACjH,qHAAqH,EACrH,SAAS,CACV,KACG,KAAK,aAER,QAAQ,EACT,KAAC,eAAe,CAAC,IAAI,IAAC,OAAO,kBAC3B,8BAAkB,MAAM,EAAC,SAAS,EAAC,gCAAgC,uBAAS,GACvD,IACC,CAC3B,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,GAAG,QAAQ,EAAE,GAAG,KAAK,EAAwD,EAAE,EAAE,CAAC,CAC7I,KAAC,eAAe,CAAC,MAAM,cACrB,MAAC,eAAe,CAAC,OAAO,IACtB,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,EAAE,CACX,oHAAoH,EACpH,QAAQ,KAAK,QAAQ,IAAI,iEAAiE,EAC1F,SAAS,CACV,KACG,KAAK,aAET,KAAC,eAAe,CAAC,cAAc,IAAC,SAAS,EAAC,uCAAuC,YAC/E,8BAAkB,MAAM,uBAAS,GACF,EACjC,KAAC,eAAe,CAAC,QAAQ,IAAC,SAAS,EAAE,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,QAAQ,IAAI,kDAAkD,CAAC,YACxH,QAAQ,GACgB,EAC3B,KAAC,eAAe,CAAC,gBAAgB,IAAC,SAAS,EAAC,uCAAuC,YACjF,8BAAkB,MAAM,uBAAS,GACA,IACX,GACH,CAC1B,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAqD,EAAE,EAAE,CAAC,CAClH,MAAC,eAAe,CAAC,IAAI,IACnB,SAAS,EAAE,EAAE,CACX,mOAAmO,EACnO,SAAS,CACV,KACG,KAAK,aAET,eAAM,SAAS,EAAC,4DAA4D,YAC1E,KAAC,eAAe,CAAC,aAAa,mBAAa,MAAM,uBAAkC,GAC9E,EACP,KAAC,eAAe,CAAC,QAAQ,cAAE,QAAQ,GAA4B,IAC1C,CACxB,CAAA"}
@@ -0,0 +1,7 @@
1
+ import type { CapabilityListProps } from './types.js';
2
+ /**
3
+ * The capabilities of a view, labelled by the application. A capability without a label is not
4
+ * rendered, so a view may carry grants a screen has nothing to say about.
5
+ */
6
+ export declare const CapabilityList: ({ capabilities, labels, onlyGranted, className }: CapabilityListProps) => import("react").JSX.Element;
7
+ //# sourceMappingURL=capability-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-list.d.ts","sourceRoot":"","sources":["../src/capability-list.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAkBrD;;;GAGG;AACH,eAAO,MAAM,cAAc,qDAA8D,mBAAmB,gCAyB3G,CAAA"}
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { PromoNote, useEntitlementCopy } from './copy.js';
3
+ const classes = (...names) => names.filter(Boolean).join(' ');
4
+ /** One row per param, in view order: granted when any row grants it, the promo of that row. */
5
+ const collapse = (capabilities) => {
6
+ const rows = new Map();
7
+ for (const capability of capabilities) {
8
+ const seen = rows.get(capability.param);
9
+ if (seen == null || (!seen.granted && capability.granted)) {
10
+ rows.set(capability.param, capability);
11
+ }
12
+ }
13
+ return [...rows.values()];
14
+ };
15
+ /**
16
+ * The capabilities of a view, labelled by the application. A capability without a label is not
17
+ * rendered, so a view may carry grants a screen has nothing to say about.
18
+ */
19
+ export const CapabilityList = ({ capabilities, labels, onlyGranted = false, className }) => {
20
+ const copy = useEntitlementCopy();
21
+ const rows = collapse(capabilities).filter(capability => (labels[capability.param] ?? '') !== '' && (!onlyGranted || capability.granted));
22
+ return _jsx("ul", { "data-capability-list": "", className: classes('grid gap-2 text-sm', className), children: rows.map(capability => _jsxs("li", { "data-capability": capability.param, "data-granted": capability.granted ? 'true' : 'false', className: "flex items-start gap-2", children: [_jsx("span", { "aria-hidden": "true", className: classes('mt-0.5 inline-flex size-4 shrink-0 items-center justify-center text-xs font-semibold', capability.granted ? 'text-primary' : 'text-muted-foreground'), children: capability.granted ? '✓' : '–' }), _jsxs("span", { className: "grid gap-0.5", children: [_jsxs("span", { className: capability.granted ? undefined : 'text-muted-foreground', children: [labels[capability.param], _jsx("span", { className: "sr-only", children: ` — ${copy.text(capability.granted ? 'capability.included' : 'capability.not-included')}` })] }), capability.promo != null && _jsx("span", { className: "text-xs", children: _jsx(PromoNote, { promo: capability.promo, copy: copy }) })] })] }, capability.param)) });
23
+ };
24
+ //# sourceMappingURL=capability-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-list.js","sourceRoot":"","sources":["../src/capability-list.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAGzD,MAAM,OAAO,GAAG,CAAC,GAAG,KAA+C,EAAU,EAAE,CAC7E,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAEjC,+FAA+F;AAC/F,MAAM,QAAQ,GAAG,CAAC,YAA8B,EAAoB,EAAE;IACpE,MAAM,IAAI,GAAG,IAAI,GAAG,EAA0B,CAAA;IAC9C,KAAK,MAAM,UAAU,IAAI,YAAY,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;QACvC,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1D,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;QACxC,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,GAAG,KAAK,EAAE,SAAS,EAAuB,EAAE,EAAE;IAC9G,MAAM,IAAI,GAAG,kBAAkB,EAAE,CAAA;IACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CACtD,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,WAAW,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC,CAAA;IAElF,OAAO,qCAAyB,EAAE,EAAC,SAAS,EAAE,OAAO,CAAC,oBAAoB,EAAE,SAAS,CAAC,YACnF,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,iCAEL,UAAU,CAAC,KAAK,kBACnB,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EACnD,SAAS,EAAC,wBAAwB,aAElC,8BAAkB,MAAM,EAAC,SAAS,EAAE,OAAO,CACzC,sFAAsF,EACtF,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,uBAAuB,CAC9D,YAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAQ,EAC1C,gBAAM,SAAS,EAAC,cAAc,aAC5B,gBAAM,SAAS,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,uBAAuB,aACtE,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,EACzB,eAAM,SAAS,EAAC,SAAS,YAAE,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,yBAAyB,CAAC,EAAE,GAAQ,IACvH,EACN,UAAU,CAAC,KAAK,IAAI,IAAI,IAAI,eAAM,SAAS,EAAC,SAAS,YAAC,KAAC,SAAS,IAAC,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,GAAI,GAAO,IAC3G,KAfF,UAAU,CAAC,KAAK,CAgBlB,CAAC,GACH,CAAA;AACP,CAAC,CAAA"}
@@ -0,0 +1,14 @@
1
+ import type { PromoView } from '@owlmeans/payment';
2
+ export interface EntitlementCopy {
3
+ text: (key: string, values?: Record<string, string>) => string;
4
+ day: (date: Date | string | null | undefined) => string;
5
+ count: (value: number) => string;
6
+ }
7
+ /** The `entitlement` branch of the `web-payment` library resource, with locale-aware formatting. */
8
+ export declare const useEntitlementCopy: () => EntitlementCopy;
9
+ /** The inscription of a promo: free until its end, kept for a grandfathered plan, or ended. */
10
+ export declare const PromoNote: ({ promo, copy }: {
11
+ promo?: PromoView;
12
+ copy: EntitlementCopy;
13
+ }) => import("react").JSX.Element | null;
14
+ //# sourceMappingURL=copy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy.d.ts","sourceRoot":"","sources":["../src/copy.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AA8BlD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,MAAM,CAAA;IAC9D,GAAG,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,KAAK,MAAM,CAAA;IACvD,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;CACjC;AAED,oGAAoG;AACpG,eAAO,MAAM,kBAAkB,QAAO,eAUrC,CAAA;AAED,+FAA+F;AAC/F,eAAO,MAAM,SAAS,oBAAqB;IAAE,KAAK,CAAC,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,eAAe,CAAA;CAAE,uCAStF,CAAA"}
package/build/copy.js ADDED
@@ -0,0 +1,51 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import { useI18nLib, useLanguage } from '@owlmeans/client-i18n';
4
+ import { promoInscriptionOf } from './selectors.js';
5
+ /**
6
+ * A calendar date in UTC — the calendar limit windows are counted in, so "resets on" names the day
7
+ * the counter actually rolls. An unparseable date renders as nothing.
8
+ */
9
+ const formatDay = (date, locale) => {
10
+ if (date == null) {
11
+ return '';
12
+ }
13
+ const value = date instanceof Date ? date : new Date(date);
14
+ if (Number.isNaN(value.getTime())) {
15
+ return '';
16
+ }
17
+ try {
18
+ return new Intl.DateTimeFormat(locale, { dateStyle: 'medium', timeZone: 'UTC' }).format(value);
19
+ }
20
+ catch {
21
+ return value.toISOString().slice(0, 10);
22
+ }
23
+ };
24
+ const formatCount = (value, locale) => {
25
+ try {
26
+ return new Intl.NumberFormat(locale).format(value);
27
+ }
28
+ catch {
29
+ return String(value);
30
+ }
31
+ };
32
+ /** The `entitlement` branch of the `web-payment` library resource, with locale-aware formatting. */
33
+ export const useEntitlementCopy = () => {
34
+ const t = useI18nLib('web-payment', 'entitlement');
35
+ const [locale] = useLanguage();
36
+ return useMemo(() => ({
37
+ // React escapes what it renders; i18next escaping on top would print `&#x2F;` for a slash.
38
+ text: (key, values) => t(key, { ...values, interpolation: { escapeValue: false } }),
39
+ day: date => formatDay(date, locale),
40
+ count: value => formatCount(value, locale),
41
+ }), [t, locale]);
42
+ };
43
+ /** The inscription of a promo: free until its end, kept for a grandfathered plan, or ended. */
44
+ export const PromoNote = ({ promo, copy }) => {
45
+ const kind = promoInscriptionOf(promo);
46
+ if (kind == null || promo == null) {
47
+ return null;
48
+ }
49
+ return _jsx("span", { "data-promo": kind, className: kind === 'ended' ? 'text-muted-foreground' : 'text-primary', children: copy.text(`promo.${kind}`, { date: copy.day(promo.until) }) });
50
+ };
51
+ //# sourceMappingURL=copy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy.js","sourceRoot":"","sources":["../src/copy.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAEnD;;;GAGG;AACH,MAAM,SAAS,GAAG,CAAC,IAAsC,EAAE,MAAc,EAAU,EAAE;IACnF,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;QACjB,OAAO,EAAE,CAAA;IACX,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,YAAY,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAA;IAC1D,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QAClC,OAAO,EAAE,CAAA;IACX,CAAC;IACD,IAAI,CAAC;QACH,OAAO,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IAChG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACzC,CAAC;AACH,CAAC,CAAA;AAED,MAAM,WAAW,GAAG,CAAC,KAAa,EAAE,MAAc,EAAU,EAAE;IAC5D,IAAI,CAAC;QACH,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;IACtB,CAAC;AACH,CAAC,CAAA;AAQD,oGAAoG;AACpG,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAoB,EAAE;IACtD,MAAM,CAAC,GAAG,UAAU,CAAC,aAAa,EAAE,aAAa,CAAC,CAAA;IAClD,MAAM,CAAC,MAAM,CAAC,GAAG,WAAW,EAAE,CAAA;IAE9B,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QACpB,2FAA2F;QAC3F,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,GAAG,MAAM,EAAE,aAAa,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC;QACnF,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC;QACpC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC;KAC3C,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAA;AAClB,CAAC,CAAA;AAED,+FAA+F;AAC/F,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,EAAE,KAAK,EAAE,IAAI,EAAgD,EAAE,EAAE;IACzF,MAAM,IAAI,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAA;IACtC,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAClC,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,6BAAkB,IAAI,EAAE,SAAS,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,cAAc,YAClG,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,GACvD,CAAA;AACT,CAAC,CAAA"}
package/build/dialog.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  import type { AmountCheckoutDialogProps } from './types.js';
2
- export declare const AmountCheckoutDialog: ({ open, onOpenChange, policy, pending, onConfirm, }: AmountCheckoutDialogProps) => import("react").JSX.Element;
2
+ export declare const AmountCheckoutDialog: ({ open, onOpenChange, policy, pending, onConfirm, estimate, }: AmountCheckoutDialogProps) => import("react").JSX.Element;
3
3
  //# sourceMappingURL=dialog.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../src/dialog.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAA;AAM3D,eAAO,MAAM,oBAAoB,wDAE9B,yBAAyB,gCAiE3B,CAAA"}
1
+ {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../src/dialog.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAA;AAM3D,eAAO,MAAM,oBAAoB,kEAE9B,yBAAyB,gCAmE3B,CAAA"}
package/build/dialog.js CHANGED
@@ -7,10 +7,11 @@ import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, D
7
7
  import { Input } from '@/components/ui/input';
8
8
  import { Label } from '@/components/ui/label';
9
9
  import { inputAmount, parseAmountMinor } from './amount.js';
10
+ import { PriceEstimateSummary } from './estimate-summary.js';
10
11
  const money = (minor, currency, locale) => new Intl.NumberFormat(locale, {
11
12
  style: 'currency', currency: currency.toUpperCase(), minimumFractionDigits: 2,
12
13
  }).format(minor / 100);
13
- export const AmountCheckoutDialog = ({ open, onOpenChange, policy, pending = false, onConfirm, }) => {
14
+ export const AmountCheckoutDialog = ({ open, onOpenChange, policy, pending = false, onConfirm, estimate, }) => {
14
15
  const t = useI18nLib('web-payment', 'amount-checkout');
15
16
  const [locale] = useLanguage();
16
17
  const [value, setValue] = useState(() => inputAmount(policy.defaultMinor, locale));
@@ -38,6 +39,8 @@ export const AmountCheckoutDialog = ({ open, onOpenChange, policy, pending = fal
38
39
  return _jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { closeLabel: t('close'), children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: t('title') }), _jsx(DialogDescription, { children: t('description') })] }), _jsxs("div", { className: "grid gap-5", children: [_jsx("div", { className: "grid grid-cols-2 gap-2 sm:grid-cols-4", "aria-label": t('presets'), children: policy.presetsMinor.map(preset => _jsx(Button, { type: "button", variant: preset === amountMinor ? 'default' : 'outline', disabled: pending, onClick: () => setValue(inputAmount(preset, locale)), children: money(preset, policy.currency, locale) }, preset)) }), _jsxs("div", { className: "grid gap-2", children: [_jsx(Label, { htmlFor: "payment-amount", children: t('custom') }), _jsx(Input, { id: "payment-amount", inputMode: "decimal", autoComplete: "off", value: value, disabled: pending, "aria-invalid": error != null, "aria-describedby": "payment-amount-help", onChange: event => setValue(event.target.value) }), _jsx("p", { id: "payment-amount-help", className: error == null ? 'text-muted-foreground text-xs' : 'text-destructive text-xs', children: error ?? t('bounds', {
39
40
  minimum: money(policy.minimumMinor, policy.currency, locale),
40
41
  maximum: money(policy.maximumMinor, policy.currency, locale),
41
- }) })] }), _jsxs("dl", { className: "grid grid-cols-[1fr_auto] gap-x-4 gap-y-2 rounded-lg border bg-muted/30 p-4 text-sm", children: [_jsx("dt", { className: "text-muted-foreground", children: t('credits') }), _jsx("dd", { children: valid && amountMinor != null ? money(amountMinor, policy.currency, locale) : '—' }), _jsx("dt", { className: "text-muted-foreground", children: t('adjustment') }), _jsx("dd", { children: valid ? money(adjustmentMinor, policy.currency, locale) : '—' }), _jsx("dt", { className: "font-medium", children: t('subtotal') }), _jsx("dd", { className: "font-medium", children: valid ? money(chargeMinor, policy.currency, locale) : '—' })] }), _jsx("p", { className: "text-muted-foreground text-xs", children: t('tax-note') })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "outline", disabled: pending, onClick: () => onOpenChange(false), children: t('cancel') }), _jsx(Button, { type: "button", disabled: !valid || pending, onClick: () => void submit(), children: pending ? t('pending') : t('continue') })] })] }) });
42
+ }) })] }), _jsxs("dl", { className: "grid grid-cols-[1fr_auto] gap-x-4 gap-y-2 rounded-lg border bg-muted/30 p-4 text-sm", children: [_jsx("dt", { className: "text-muted-foreground", children: t('credits') }), _jsx("dd", { children: valid && amountMinor != null ? money(amountMinor, policy.currency, locale) : '—' }), _jsx("dt", { className: "text-muted-foreground", children: t('adjustment') }), _jsx("dd", { children: valid ? money(adjustmentMinor, policy.currency, locale) : '—' }), _jsx("dt", { className: "font-medium", children: t('subtotal') }), _jsx("dd", { className: "font-medium", children: valid ? money(chargeMinor, policy.currency, locale) : '—' })] }), estimate != null
43
+ ? valid && _jsx(PriceEstimateSummary, { control: estimate, subtotalMinor: chargeMinor, currency: policy.currency })
44
+ : _jsx("p", { className: "text-muted-foreground text-xs", children: t('tax-note') })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "outline", disabled: pending, onClick: () => onOpenChange(false), children: t('cancel') }), _jsx(Button, { type: "button", disabled: !valid || pending, onClick: () => void submit(), children: pending ? t('pending') : t('continue') })] })] }) });
42
45
  };
43
46
  //# sourceMappingURL=dialog.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.js","sourceRoot":"","sources":["../src/dialog.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dialog.js","sourceRoot":"","sources":["../src/dialog.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { CallArguments, RegisteredEntrypoint, RequestShape } from '@owlmeans/entrypoint';
2
+ import type { EntitlementView, PortalFlow, PortalLinkResponse } from '@owlmeans/payment';
3
+ import { type CheckoutTarget } from './service.js';
4
+ import type { LimitStatus, PortalArguments, PortalRequest } from './types.js';
5
+ /**
6
+ * Poll an entitlement-view protocol — `null` until the first answer. The view is revived on the way
7
+ * in (the wire carries ISO strings), so every date in it is a `Date`.
8
+ *
9
+ * An application that already keeps the view in its own store reads it through the pure selectors
10
+ * (`capabilityStateOf`, `limitStatusOf`, `planStatusLineOf`) instead of polling a second time.
11
+ */
12
+ export declare const useEntitlementView: <Request extends RequestShape>(entry: RegisteredEntrypoint<Request, EntitlementView>, intervalMs?: number, deps?: unknown[], ...request: CallArguments<Request>) => EntitlementView | null;
13
+ /** Whether the view grants a capability parameter; `null` while the view is unknown. */
14
+ export declare const useCapability: (view: EntitlementView | null | undefined, param: string) => boolean | null;
15
+ /** One limit of the view with `exhausted` and `ratio`; `null` while unknown or undeclared. */
16
+ export declare const useLimit: (view: EntitlementView | null | undefined, key: string) => LimitStatus | null;
17
+ /**
18
+ * Open a billing-portal flow: `portal(entry, request?)` calls the portal protocol with `body.flow`
19
+ * set to `flow`, then sends the browser to the returned URL (same window by default). Without a DOM
20
+ * the navigation is inert and the response is still returned.
21
+ */
22
+ export declare const usePortal: (flow: PortalFlow, target?: CheckoutTarget) => {
23
+ portal: <Request extends PortalRequest>(entry: RegisteredEntrypoint<Request, PortalLinkResponse>, ...request: PortalArguments<Request>) => Promise<PortalLinkResponse | null>;
24
+ pending: boolean;
25
+ };
26
+ //# sourceMappingURL=entitlement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entitlement.d.ts","sourceRoot":"","sources":["../src/entitlement.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAE7F,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAGxF,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE7E;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAAI,OAAO,SAAS,YAAY,SACtD,oBAAoB,CAAC,OAAO,EAAE,eAAe,CAAC,eACzC,MAAM,SACZ,OAAO,EAAE,cACH,aAAa,CAAC,OAAO,CAAC,KACjC,eAAe,GAAG,IAEpB,CAAA;AAED,wFAAwF;AACxF,eAAO,MAAM,aAAa,SAAU,eAAe,GAAG,IAAI,GAAG,SAAS,SAAS,MAAM,KAAG,OAAO,GAAG,IACpC,CAAA;AAE9D,8FAA8F;AAC9F,eAAO,MAAM,QAAQ,SAAU,eAAe,GAAG,IAAI,GAAG,SAAS,OAAO,MAAM,KAAG,WAAW,GAAG,IAChC,CAAA;AAE/D;;;;GAIG;AACH,eAAO,MAAM,SAAS,SAAU,UAAU,WAAU,cAAc;aAE9B,OAAO,SAAS,aAAa,SACtD,oBAAoB,CAAC,OAAO,EAAE,kBAAkB,CAAC,cAAc,eAAe,CAAC,OAAO,CAAC,KAC7F,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;;CAatC,CAAA"}