@encorekit/web-sdk 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -95
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/umd/encore.min.js +1 -1
- package/dist/umd/encore.min.js.map +1 -1
- package/package.json +1 -1
- package/types/analytics/events.d.ts +7 -28
- package/types/analytics/events.d.ts.map +1 -1
- package/types/api/APIClient.d.ts +10 -6
- package/types/api/APIClient.d.ts.map +1 -1
- package/types/api/models.d.ts +8 -3
- package/types/api/models.d.ts.map +1 -1
- package/types/core/Configuration.d.ts +0 -4
- package/types/core/Configuration.d.ts.map +1 -1
- package/types/core/Encore.d.ts +8 -33
- package/types/core/Encore.d.ts.map +1 -1
- package/types/core/PlacementBuilder.d.ts +7 -31
- package/types/core/PlacementBuilder.d.ts.map +1 -1
- package/types/core/useCase.d.ts +54 -13
- package/types/core/useCase.d.ts.map +1 -1
- package/types/core/version.d.ts +1 -1
- package/types/types.d.ts +85 -272
- package/types/types.d.ts.map +1 -1
- package/types/ui/OfferCarousel.d.ts +59 -1
- package/types/ui/OfferCarousel.d.ts.map +1 -1
- package/types/ui/RewardActions.d.ts +60 -0
- package/types/ui/RewardActions.d.ts.map +1 -0
- package/types/ui/RewardCard.d.ts +49 -0
- package/types/ui/RewardCard.d.ts.map +1 -0
- package/types/ui/RewardConfetti.d.ts +46 -0
- package/types/ui/RewardConfetti.d.ts.map +1 -0
- package/types/ui/RewardLayout.d.ts +55 -0
- package/types/ui/RewardLayout.d.ts.map +1 -0
- package/types/ui/brandTint.d.ts +61 -0
- package/types/ui/brandTint.d.ts.map +1 -0
- package/types/ui/styles.d.ts +86 -0
- package/types/ui/styles.d.ts.map +1 -1
- package/types/utils/text.d.ts +24 -0
- package/types/utils/text.d.ts.map +1 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reward offer card — the tile the Figma's `streaksCarousel` hero shows.
|
|
3
|
+
*
|
|
4
|
+
* A DIFFERENT card from `OfferCard`, not a variant of it. OfferCard is a wide banner
|
|
5
|
+
* image over a merchant row with its own Claim button; this is a 210×260 portrait
|
|
6
|
+
* tile — pill, icon, advertiser, offer line — centred on a wash of the advertiser's
|
|
7
|
+
* colour. They share no element, so expressing this as more flags on OfferCard would
|
|
8
|
+
* have meant a component that renders two unrelated layouts and a churn-intervention
|
|
9
|
+
* card one boolean away from the reward one. Separate file, separate class names:
|
|
10
|
+
* the churn path cannot reach a single line of this.
|
|
11
|
+
*
|
|
12
|
+
* NOT a renderer. Web has no SDUI engine; every value below is read off the Figma by
|
|
13
|
+
* hand (frame 18304:2399, node 18304:3383) and tracked here:
|
|
14
|
+
*
|
|
15
|
+
* card 210×260, radius 24, tint@10% over white
|
|
16
|
+
* shadow 0 4px 12px rgba(0,0,0,.09), 0 4px 12px rgba(0,0,0,.02),
|
|
17
|
+
* 0 4px 74px rgba(0,0,0,.06)
|
|
18
|
+
* pill top 43, white, radius 16, pad 4/10, 14 / medium
|
|
19
|
+
* icon top 84, 72×72, radius 18
|
|
20
|
+
* name top 176, 18 / semibold, tracking -0.18
|
|
21
|
+
* offer top 201, 14 / regular, tracking -0.28
|
|
22
|
+
*
|
|
23
|
+
* The Figma's Audible orange is NOT hardcoded — offers are remote and arbitrary. See
|
|
24
|
+
* `brandTint.ts` for how the wash is derived per offer.
|
|
25
|
+
*/
|
|
26
|
+
import type { OfferModel as Offer } from '../api/models';
|
|
27
|
+
/**
|
|
28
|
+
* Copy the card hard-codes, mirroring `RewardActions`' REWARD_COPY.
|
|
29
|
+
*
|
|
30
|
+
* The badge is SDK-owned rather than per-offer because no field carries it: the
|
|
31
|
+
* contract has no badge/category on `Creative`, and the Figma's own cards disagree
|
|
32
|
+
* with each other (a "Free 30 days trial" pill above a "50% discount for 3 month"
|
|
33
|
+
* line). It is overridable for the same reason the trust line is — a publisher whose
|
|
34
|
+
* reward is not a trial must not be stuck asserting one.
|
|
35
|
+
*/
|
|
36
|
+
export declare const REWARD_CARD_COPY: {
|
|
37
|
+
readonly badge: "Free trial";
|
|
38
|
+
};
|
|
39
|
+
export interface RewardCardOptions {
|
|
40
|
+
/** Overrides the badge pill. Blank/absent keeps the variant's copy. */
|
|
41
|
+
badgeText?: string;
|
|
42
|
+
}
|
|
43
|
+
export declare class RewardCard {
|
|
44
|
+
#private;
|
|
45
|
+
constructor(options?: RewardCardOptions);
|
|
46
|
+
render(offer: Offer): HTMLElement;
|
|
47
|
+
destroy(): void;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=RewardCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RewardCard.d.ts","sourceRoot":"","sources":["../../src/ui/RewardCard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,UAAU,IAAI,KAAK,EAAE,MAAM,eAAe,CAAC;AAMzD;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB;;CAEnB,CAAC;AAEX,MAAM,WAAW,iBAAiB;IAChC,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,UAAU;;gBAMT,OAAO,GAAE,iBAAsB;IAI3C,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,WAAW;IA2GjC,OAAO,IAAI,IAAI;CAKhB"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reward confetti — the variant's celebration layer.
|
|
3
|
+
*
|
|
4
|
+
* `streaksCarousel.json` opens the sheet with a `confetti` burst that web never had:
|
|
5
|
+
*
|
|
6
|
+
* intensity 22 particle count
|
|
7
|
+
* duration 2.0 seconds, then the layer removes itself
|
|
8
|
+
* originY 0.0 emitted from the TOP edge, falling down
|
|
9
|
+
* scatter 46 horizontal spread, in points, around each particle's origin
|
|
10
|
+
* scatterHeight 0.3 origins spread over the top 30% of the sheet
|
|
11
|
+
* style maxWidth/maxHeight infinity, ignoresSafeArea — full-bleed
|
|
12
|
+
*
|
|
13
|
+
* Hand-rolled on a single 2D canvas: the SDK ships zero runtime dependencies, and a
|
|
14
|
+
* confetti library would be several KB for 22 rectangles falling for two seconds.
|
|
15
|
+
*
|
|
16
|
+
* Purely decorative and entirely optional. It is `aria-hidden`, it takes no pointer
|
|
17
|
+
* events, it is skipped outright under `prefers-reduced-motion`, and every entry
|
|
18
|
+
* point is guarded — an environment without a 2D context (jsdom, a locked-down
|
|
19
|
+
* browser) simply gets no confetti rather than an exception on a host page.
|
|
20
|
+
*/
|
|
21
|
+
/** The variant's values, named so tests can assert parity by symbol. */
|
|
22
|
+
export declare const CONFETTI_SPEC: {
|
|
23
|
+
readonly intensity: 22;
|
|
24
|
+
readonly durationMs: 2000;
|
|
25
|
+
readonly originY: 0;
|
|
26
|
+
readonly scatter: 46;
|
|
27
|
+
readonly scatterHeight: 0.3;
|
|
28
|
+
};
|
|
29
|
+
export declare class RewardConfetti {
|
|
30
|
+
#private;
|
|
31
|
+
/**
|
|
32
|
+
* True when the burst should be skipped entirely.
|
|
33
|
+
*
|
|
34
|
+
* `prefers-reduced-motion` is a hard skip, not a slowdown: falling confetti is
|
|
35
|
+
* exactly the large-area motion the setting exists to suppress, and the sheet
|
|
36
|
+
* loses nothing functional without it.
|
|
37
|
+
*/
|
|
38
|
+
static shouldSkip(): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Mount the burst inside `host` and start it. Returns silently if confetti cannot
|
|
41
|
+
* run; the caller never has to branch.
|
|
42
|
+
*/
|
|
43
|
+
start(host: HTMLElement): void;
|
|
44
|
+
destroy(): void;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=RewardConfetti.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RewardConfetti.d.ts","sourceRoot":"","sources":["../../src/ui/RewardConfetti.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,wEAAwE;AACxE,eAAO,MAAM,aAAa;;;;;;CAMhB,CAAC;AAkCX,qBAAa,cAAc;;IASzB;;;;;;OAMG;IACH,MAAM,CAAC,UAAU,IAAI,OAAO;IAU5B;;;OAGG;IACH,KAAK,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAmI9B,OAAO,IAAI,IAAI;CAWhB"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reward chrome — the composition `useCase: 'rewardUsers'` renders.
|
|
3
|
+
*
|
|
4
|
+
* Pure chrome around the unchanged OfferCarousel: a status block (success check +
|
|
5
|
+
* headline + subheadline) above the offers. A pure render function rather than a
|
|
6
|
+
* component class: the chrome is static content with no events, no listeners, and no
|
|
7
|
+
* state — the carousel keeps its own lifecycle and is passed in as a ready element.
|
|
8
|
+
*
|
|
9
|
+
* The `thankyou` class names are deliberately UNCHANGED from when this chrome was
|
|
10
|
+
* also reachable as a publisher-selectable `layout: 'thankYou'` (retired in 3.0.0).
|
|
11
|
+
* They are internal style hooks, not public API, and renaming them would churn the
|
|
12
|
+
* whole visual system — including the `--reward` parity rules that track the native
|
|
13
|
+
* SDKs' `streaksCarousel.json` type scale — for no behavioural gain.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* The id given to the status heading so the dialog's accessible name can point at
|
|
17
|
+
* the chrome's real primary heading (the carousel's own header is suppressed in this
|
|
18
|
+
* composition, so it is not available as a fallback `aria-labelledby` target).
|
|
19
|
+
*/
|
|
20
|
+
export declare const REWARD_TITLE_ID: string;
|
|
21
|
+
export interface RewardLayoutOptions {
|
|
22
|
+
/** Resolved headline. Required in practice — it is the dialog's accessible name. */
|
|
23
|
+
title?: string;
|
|
24
|
+
/** Resolved subheadline. Omitted (never `''`) when nothing resolved. */
|
|
25
|
+
subtitle?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Status icon above the headline. Defaults to `'none'`, matching the native
|
|
28
|
+
* variant — see `PlacementOptions.statusIcon`. `'success'` opts into a
|
|
29
|
+
* green-circle check.
|
|
30
|
+
*/
|
|
31
|
+
statusIcon?: 'success' | 'none';
|
|
32
|
+
/**
|
|
33
|
+
* A ready-built action block placed directly under the carousel — the trust line
|
|
34
|
+
* and the single bottom CTA pair (see RewardActions). The variant puts the CTA
|
|
35
|
+
* stack last in the sheet, and nothing renders below it there.
|
|
36
|
+
*
|
|
37
|
+
* An ELEMENT, not a config object, on purpose: this module is a pure render
|
|
38
|
+
* function with no events, no listeners and no state, and the action block is all
|
|
39
|
+
* three. Taking it pre-built keeps the ownership boundary — RewardActions owns its
|
|
40
|
+
* listeners and its teardown; this function only positions it.
|
|
41
|
+
*/
|
|
42
|
+
actions?: HTMLElement;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Compose the reward sheet: status (optional check → title → subtitle) → carousel.
|
|
46
|
+
*
|
|
47
|
+
* All host-supplied copy is set via textContent (text-only, injection-safe).
|
|
48
|
+
*
|
|
49
|
+
* The check is OPT-IN (`statusIcon: 'success'`) and off by default, matching the
|
|
50
|
+
* native reward variant, which renders no checkmark at all. It is `aria-hidden`
|
|
51
|
+
* either way, so its presence never affects the dialog's accessible name — that
|
|
52
|
+
* always comes from the title below.
|
|
53
|
+
*/
|
|
54
|
+
export declare function renderRewardLayout(carouselElement: HTMLElement, options?: RewardLayoutOptions): HTMLElement;
|
|
55
|
+
//# sourceMappingURL=RewardLayout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RewardLayout.d.ts","sourceRoot":"","sources":["../../src/ui/RewardLayout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH;;;;GAIG;AACH,eAAO,MAAM,eAAe,QAAwB,CAAC;AAErD,MAAM,WAAW,mBAAmB;IAClC,oFAAoF;IACpF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAChC;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAQD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,eAAe,EAAE,WAAW,EAC5B,OAAO,GAAE,mBAAwB,GAChC,WAAW,CA8Cb"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-offer brand tint for the reward card.
|
|
3
|
+
*
|
|
4
|
+
* The Figma renders each card on a wash of the advertiser's own colour — Audible's
|
|
5
|
+
* card is `rgba(255,159,43,0.1)` over white. `streaksCarousel.json` binds that as
|
|
6
|
+
* `offerDominantColor`.
|
|
7
|
+
*
|
|
8
|
+
* THERE IS NO API FIELD BEHIND THAT BINDING, on any platform. iOS and Android compute
|
|
9
|
+
* it from the logo at render time; the contract carries no colour on `Creative`,
|
|
10
|
+
* `Organization` or `Campaign`. So sampling the icon is not a web workaround for a
|
|
11
|
+
* missing field — it IS the canonical implementation, and this module is web's copy
|
|
12
|
+
* of it. Native's rule, verbatim: *"the dominant color used in the icon that is not
|
|
13
|
+
* straight black or straight white."*
|
|
14
|
+
*
|
|
15
|
+
* Two tiers, and the first one always succeeds. Native is single-tier; web needs the
|
|
16
|
+
* extra one because it has a failure mode native does not — a cross-origin logo whose
|
|
17
|
+
* host sends no CORS headers can never be read into a canvas at all.
|
|
18
|
+
*
|
|
19
|
+
* 1. `fallbackTint` — synchronous, deterministic, from the offer's identity. Every
|
|
20
|
+
* card has a tint from its first frame; a card is never briefly untinted and
|
|
21
|
+
* never depends on the network.
|
|
22
|
+
* 2. `sampleLogoTint` — asynchronous, upgrades tier 1 to the real brand colour when
|
|
23
|
+
* the logo is readable. Resolves `null` on ANY failure and never throws.
|
|
24
|
+
*
|
|
25
|
+
* Tier 2 needs a CORS-clean image, and `crossOrigin = 'anonymous'` makes a
|
|
26
|
+
* non-CORS server fail the load OUTRIGHT rather than merely tainting the canvas.
|
|
27
|
+
* That is why this samples a SEPARATE `Image`, never the one on screen: the card's
|
|
28
|
+
* own <img> is loaded without `crossOrigin` so it always renders, and a sampling
|
|
29
|
+
* failure costs a tint upgrade rather than the logo itself.
|
|
30
|
+
*/
|
|
31
|
+
/** How much of the tint the card background gets — the Figma's 0.1 over white. */
|
|
32
|
+
export declare const CARD_TINT_ALPHA = 0.1;
|
|
33
|
+
/**
|
|
34
|
+
* The synchronous tier. Always returns a usable colour.
|
|
35
|
+
*
|
|
36
|
+
* Keyed on the advertiser NAME first so every creative from one advertiser tints
|
|
37
|
+
* identically — the card shows the advertiser, so two Audible offers reading as two
|
|
38
|
+
* different brands would be wrong. Falls back through title to id, which are never
|
|
39
|
+
* both empty.
|
|
40
|
+
*/
|
|
41
|
+
export declare function fallbackTint(seed: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* Reduce RGBA pixels to the dominant non-black, non-white colour, or `null` when the
|
|
44
|
+
* image has none.
|
|
45
|
+
*
|
|
46
|
+
* Split out from the canvas plumbing and exported so the rule that actually matters —
|
|
47
|
+
* paper and ink are excluded, greys lose to colour, a monochrome logo yields nothing —
|
|
48
|
+
* is unit-testable. jsdom has no 2D context, so it is unreachable through
|
|
49
|
+
* `extractDominantColor` in tests.
|
|
50
|
+
*
|
|
51
|
+
* @internal exported for tests only.
|
|
52
|
+
*/
|
|
53
|
+
export declare function dominantColorFromPixels(data: Uint8ClampedArray): string | null;
|
|
54
|
+
/**
|
|
55
|
+
* Try to read the advertiser's colour off its logo. Resolves `null` on every failure
|
|
56
|
+
* path — a missing URL, a CORS refusal, a decode error, a timeout, a greyscale logo,
|
|
57
|
+
* or an environment without canvas. Never rejects and never throws: a tint upgrade is
|
|
58
|
+
* the least important thing on the sheet, and an SDK must not crash a host page for it.
|
|
59
|
+
*/
|
|
60
|
+
export declare function sampleLogoTint(url: string | undefined): Promise<string | null>;
|
|
61
|
+
//# sourceMappingURL=brandTint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brandTint.d.ts","sourceRoot":"","sources":["../../src/ui/brandTint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAIH,kFAAkF;AAClF,eAAO,MAAM,eAAe,MAAM,CAAC;AA2InC;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGjD;AA4BD;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,CAuC9E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmC9E"}
|
package/types/ui/styles.d.ts
CHANGED
|
@@ -11,6 +11,92 @@ export declare const BREAKPOINTS: {
|
|
|
11
11
|
readonly TABLET: "1023px";
|
|
12
12
|
readonly DESKTOP: "1024px";
|
|
13
13
|
};
|
|
14
|
+
/**
|
|
15
|
+
* REWARD_VISUAL_NOTES — why the reward block in the stylesheet below looks the way
|
|
16
|
+
* it does. Deliberately a JS comment and NOT a CSS one.
|
|
17
|
+
*
|
|
18
|
+
* The stylesheet is one big template literal, so every `/* … *\/` inside it is STRING
|
|
19
|
+
* CONTENT that terser cannot strip and every user downloads. This file's house style
|
|
20
|
+
* is long prose; in the literal that prose is payload. Keep in-literal comments to a
|
|
21
|
+
* terse line or two and put the reasoning here, where it is free. (Trimming this
|
|
22
|
+
* block's CSS prose cut 3.9KB of raw bundle — it had been 46% of the whole
|
|
23
|
+
* stylesheet delta.)
|
|
24
|
+
*
|
|
25
|
+
* SOURCE OF TRUTH. The interaction model tracks `streaksCarousel.json`; the visuals
|
|
26
|
+
* track Figma frame 18304:2399 (393×852). Where they disagree the Figma wins — see
|
|
27
|
+
* the PR for the itemised list. Web has no SDUI engine, so every value is hand-tracked.
|
|
28
|
+
*
|
|
29
|
+
* SHEET BACKGROUND, three layers, top-most first:
|
|
30
|
+
* 1. The Figma's radial glow — a 346px circle of #B728F5 @ 12%, Gaussian-blurred
|
|
31
|
+
* (stdDeviation 102), centred at (189, −38), just above the top edge. Rendered
|
|
32
|
+
* as a soft radial rather than a real blur: a filter would cost a full-surface
|
|
33
|
+
* repaint for what is a completely static wash.
|
|
34
|
+
* 2. The variant's accent wash — its four stops, 0.14 → 0.05 → 0 → 0.
|
|
35
|
+
* 3. The variant's base canvas — surface → surface → background → background.
|
|
36
|
+
* Layers 2 and 3 are the variant's two stacked full-bleed gradients. Alpha is only
|
|
37
|
+
* ever composited against layer 3, never the host page's backdrop: an accent tint
|
|
38
|
+
* over an unknown ground is what rendered near-black in night mode (backend #426).
|
|
39
|
+
*
|
|
40
|
+
* TEXT COLOUR stays on theme tokens rather than the Figma's #292D32 / #051E34. The
|
|
41
|
+
* variant's own dark-mode note is explicit that every mode-derived colour must remain
|
|
42
|
+
* a token, and a hardcoded light-mode hex in a mode-reactive layer is exactly bug
|
|
43
|
+
* #426/#427. Figma hexes are used only for the brand wash, which is not mode-derived.
|
|
44
|
+
* The subheadline ships at 0.55 rather than the Figma's 0.50 because the variant
|
|
45
|
+
* specifies 0.55 for secondary copy to clear WCAG AA at this size — on a contrast
|
|
46
|
+
* question the variant wins.
|
|
47
|
+
*
|
|
48
|
+
* THE NEIGHBOUR TREATMENT IS MEASURED, NOT GUESSED. A neighbour's card body samples
|
|
49
|
+
* #F9F9F9 against a #F2F2F2 ground, and its icon matches at the same ratio — that is
|
|
50
|
+
* white at 55%. So it is opacity 0.55 + scale 0.95 + translateY(11px) with NO
|
|
51
|
+
* grayscale/saturate filter; the "desaturated" look is just opacity over a light
|
|
52
|
+
* ground. That is also the fast choice: opacity composites on the GPU and holds 60fps
|
|
53
|
+
* through a drag, where a filter repaints every card every frame.
|
|
54
|
+
*
|
|
55
|
+
* CARD BODY is tint@10% over white — measured #FFF5E9 against Audible's #FF9F2B,
|
|
56
|
+
* exactly white + 10%. The two radial layers add the deeper wash the Figma carries at
|
|
57
|
+
* the right and bottom edges (its decorative vector), derived from the same tint so
|
|
58
|
+
* any advertiser colour works. See `brandTint.ts` for where the tint comes from.
|
|
59
|
+
*
|
|
60
|
+
* DESKTOP WIDTH. The design is a 393-wide phone frame; on the desktop modal
|
|
61
|
+
* (max-width 800) the content column holds 393 and centres, so the hero keeps its
|
|
62
|
+
* proportions instead of stranding a 210px card in an 800px sheet. The background
|
|
63
|
+
* stays full-bleed — only the content column is constrained. Content sits at
|
|
64
|
+
* z-index 1 so it clears the confetti canvas, matching the variant's zStack order
|
|
65
|
+
* (gradients → confetti → content).
|
|
66
|
+
*/
|
|
67
|
+
/**
|
|
68
|
+
* The reward sheet's brand pair, read off the Figma (frame 18304:2399).
|
|
69
|
+
*
|
|
70
|
+
* `#B728F5 → #6515ED` is the primary CTA's gradient (node 18304:2417, 98.22°), and
|
|
71
|
+
* `#B728F5` is also the active dot and the radial glow behind the header — one accent
|
|
72
|
+
* for the whole surface, which is why it is one variable rather than three literals.
|
|
73
|
+
*
|
|
74
|
+
* NOT `--encore-primary-color`. `streaksCarousel.json` fills this CTA with a FLAT
|
|
75
|
+
* `accent` (the publisher's brand colour) at `cornerRadius: 12`; the Figma shows this
|
|
76
|
+
* gradient at a full pill. The Figma is the target, so the gradient ships — see the
|
|
77
|
+
* PR for the divergence. Exposed as custom properties on the reward root so the pair
|
|
78
|
+
* stays overridable if that decision is revisited.
|
|
79
|
+
*/
|
|
80
|
+
export declare const REWARD_BRAND = "#B728F5";
|
|
81
|
+
export declare const REWARD_BRAND_DEEP = "#6515ED";
|
|
82
|
+
/** Inactive dot ink, Figma 18304:3072 — `#6A6D81` at 30%. */
|
|
83
|
+
export declare const REWARD_DOT_COLOR = "#6A6D81";
|
|
84
|
+
/**
|
|
85
|
+
* Reward hero carousel geometry (Figma: hero 210×260 centred in a 393 frame, ~10px
|
|
86
|
+
* between card edges, neighbours peeking at both edges).
|
|
87
|
+
*
|
|
88
|
+
* Shared as constants because three separate rules have to agree on them: the card
|
|
89
|
+
* itself, the scroll container's centring padding (`50% - CARD_WIDTH/2`), and the
|
|
90
|
+
* arrows' vertical offset (`CARDS_PAD_Y + CARD_HEIGHT/2`). Drifting any one of them
|
|
91
|
+
* apart silently de-centres the hero.
|
|
92
|
+
*/
|
|
93
|
+
export declare const REWARD_CARD_GEOMETRY: {
|
|
94
|
+
readonly width: 210;
|
|
95
|
+
readonly height: 260;
|
|
96
|
+
readonly gap: 10;
|
|
97
|
+
/** Vertical breathing room in the scroll container, so the card shadow is not clipped. */
|
|
98
|
+
readonly padY: 26;
|
|
99
|
+
};
|
|
14
100
|
/**
|
|
15
101
|
* CSS custom properties for theming
|
|
16
102
|
*/
|
package/types/ui/styles.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/ui/styles.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/ui/styles.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,eAAO,MAAM,OAAO;;;CAGV,CAAC;AAGX,eAAO,MAAM,WAAW;;;;CAId,CAAC;AAEX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,YAAY,CAAC;AACtC,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAC3C,6DAA6D;AAC7D,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAE1C;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB;;;;IAI/B,0FAA0F;;CAElF,CAAC;AAEX;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA8qDD;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,GAAE,cAAmB,GAAG,IAAI,CAgB7D;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,IAAI,CAMnC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAUvD;AAED;;GAEG;AACH,wBAAgB,EAAE,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAE/C;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE7C"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Small text helpers shared across the core and UI layers.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* First value that is a non-blank string once trimmed, else `undefined` —
|
|
6
|
+
* the copy-priority primitive for tiered overrides (per-call > backend > default).
|
|
7
|
+
*
|
|
8
|
+
* Exists because neither operator expresses this. `??` treats `' '` as a real
|
|
9
|
+
* value, so a whitespace-only override would win its slot and render an empty
|
|
10
|
+
* headline (taking `aria-labelledby` with it) or an empty subtitle. `||` behaves
|
|
11
|
+
* correctly but trips `prefer-nullish-coalescing`, whose autofix converts it to
|
|
12
|
+
* `??` and reintroduces precisely that bug — so the rule's suggested fix is
|
|
13
|
+
* actively wrong on this shape. A named helper states the rule once and keeps
|
|
14
|
+
* every call site honest.
|
|
15
|
+
*
|
|
16
|
+
* Returning `undefined` rather than `''` is what lets callers OMIT a slot instead
|
|
17
|
+
* of filling it with an empty value — for the header that is the difference
|
|
18
|
+
* between rendering no subtitle node and rendering a blank one that still takes
|
|
19
|
+
* layout space and is announced as an empty element. The reward CARD uses the same
|
|
20
|
+
* property to drop its offer line rather than render an empty node that would still
|
|
21
|
+
* consume its 4px gap.
|
|
22
|
+
*/
|
|
23
|
+
export declare function firstNonBlank(...values: (string | null | undefined)[]): string | undefined;
|
|
24
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/utils/text.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,GAAG,MAAM,EAAE,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,GAAG,MAAM,GAAG,SAAS,CAM1F"}
|