@nitida/asset-client 0.16.2 → 0.16.4
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/AGENTS.md +10 -5
- package/README.md +5 -3
- package/dist/index.cjs +43 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +101 -16
- package/dist/index.d.ts +101 -16
- package/dist/index.js +41 -8
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
- package/src/index.ts +149 -19
- package/src/palette.ts +20 -19
- package/src/slots.ts +5 -5
- package/src/transform.ts +17 -2
package/src/palette.ts
CHANGED
|
@@ -100,8 +100,8 @@ export function relativeLuminance(hex: string): number {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
103
|
+
* WCAG contrast ratio between two luminances: `(L1 + 0.05) / (L2 + 0.05)`,
|
|
104
|
+
* lighter on top. 1 = identical, 21 = black against white.
|
|
105
105
|
*/
|
|
106
106
|
export function contrastRatio(l1: number, l2: number): number {
|
|
107
107
|
const [hi, lo] = l1 >= l2 ? [l1, l2] : [l2, l1];
|
|
@@ -109,37 +109,38 @@ export function contrastRatio(l1: number, l2: number): number {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
/**
|
|
112
|
-
*
|
|
112
|
+
* Black or white — whichever **actually** contrasts more against this
|
|
113
|
+
* background.
|
|
113
114
|
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
115
|
+
* The tie point is NOT `L > 0.5`, which is the threshold most implementations
|
|
116
|
+
* reach for. Equating the two contrast ratios gives it exactly:
|
|
116
117
|
*
|
|
117
118
|
* (1 + 0.05) / (L + 0.05) = (L + 0.05) / 0.05
|
|
118
119
|
* (L + 0.05)² = 0.0525
|
|
119
120
|
* L = 0.1791…
|
|
120
121
|
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
* negro da **7,84:1**. 2,68 no pasa AA ni para texto grande.
|
|
122
|
+
* Between **0.179 and 0.5** a `L > 0.5` test picks WHITE while black contrasts
|
|
123
|
+
* more — a wide band, and exactly where saturated brand colours land. A
|
|
124
|
+
* mid-luminance gold in that band can be handed white at **2.68:1** when black
|
|
125
|
+
* would give **7.84:1**; 2.68 does not pass AA even for large text.
|
|
126
126
|
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
127
|
+
* So this does not swap one threshold for another: it **computes both ratios
|
|
128
|
+
* and returns the winner**. A threshold is a constant somebody has to keep
|
|
129
|
+
* correct; the comparison is correct by construction.
|
|
130
130
|
*
|
|
131
|
-
* ⚠️
|
|
132
|
-
*
|
|
133
|
-
*
|
|
131
|
+
* ⚠️ This picks the BETTER of two — it does not guarantee the result is
|
|
132
|
+
* enough. Over a mid-luminance background the best pair can still land under
|
|
133
|
+
* 4.5:1. Use {@link bestTextContrast} when you need to know: it returns the
|
|
134
|
+
* ratio it achieved.
|
|
134
135
|
*/
|
|
135
136
|
function textColorForHex(hex: string): "#000000" | "#FFFFFF" {
|
|
136
137
|
return bestTextContrast(hex).color;
|
|
137
138
|
}
|
|
138
139
|
|
|
139
140
|
/**
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
141
|
+
* Same choice as the recommended text colour, but it also returns **the ratio
|
|
142
|
+
* it achieved** and whether that passes AA — so a caller can decide with the
|
|
143
|
+
* number in front of them instead of assuming it was enough.
|
|
143
144
|
*/
|
|
144
145
|
export function bestTextContrast(hex: string): {
|
|
145
146
|
color: "#000000" | "#FFFFFF";
|
package/src/slots.ts
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Slots give tenants a way to attach stable, human-readable names
|
|
5
5
|
* ("webapp.wizard.pool-type.icon-1", "storefront.cr.hero-video.landscape_hd_16x9.mp4")
|
|
6
6
|
* to assets they uploaded. Consumers resolve names → AssetDTOs at
|
|
7
|
-
* build / runtime so their source never hardcodes a CDN URL;
|
|
8
|
-
* admin rebinds a slot
|
|
9
|
-
* up the swap on cache refresh.
|
|
7
|
+
* build / runtime so their source never hardcodes a CDN URL; an
|
|
8
|
+
* admin rebinds a slot in the platform console and every consumer
|
|
9
|
+
* picks up the swap on cache refresh.
|
|
10
10
|
*
|
|
11
11
|
* Two layers in this package:
|
|
12
12
|
* - `resolveSlot` / `resolveSlots` — universal (server, edge,
|
|
@@ -67,8 +67,8 @@ let tenantCode: string | null = null;
|
|
|
67
67
|
*
|
|
68
68
|
* configureSlotResolver({
|
|
69
69
|
* endpoint: process.env.AQUIENPZ_URL,
|
|
70
|
-
* apiKey: process.env.
|
|
71
|
-
* tenantCode: "
|
|
70
|
+
* apiKey: process.env.AQUIENPZ_API_KEY, // amk_rt_* — server-only
|
|
71
|
+
* tenantCode: "acme-co",
|
|
72
72
|
* });
|
|
73
73
|
*/
|
|
74
74
|
export function configureSlotResolver(opts: {
|
package/src/transform.ts
CHANGED
|
@@ -262,13 +262,28 @@ export function getVideoTransformUrl(
|
|
|
262
262
|
* if (prefersNativeHls(video)) {
|
|
263
263
|
* video.src = src;
|
|
264
264
|
* } else {
|
|
265
|
-
*
|
|
266
|
-
* const hls = new Hls({ startLevel: -1, testBandwidth: true, abrEwmaDefaultEstimate: 1_000_000 });
|
|
265
|
+
* const hls = new Hls({ capLevelToPlayerSize: false, abrEwmaDefaultEstimate: 5_000_000 });
|
|
267
266
|
* hls.loadSource(src);
|
|
268
267
|
* hls.attachMedia(video);
|
|
269
268
|
* }
|
|
270
269
|
* ```
|
|
271
270
|
*
|
|
271
|
+
* ⚠️ **Do NOT pass `startLevel: -1` with `testBandwidth: true`.** That pair is
|
|
272
|
+
* documented by hls.js as *"forces the player to download a fragment from the
|
|
273
|
+
* lowest level to establish a bandwidth estimate"* — on a clip short enough to
|
|
274
|
+
* be one segment, the probe IS the whole video, and it plays at the bottom
|
|
275
|
+
* rung from first frame to last. (This doc-comment recommended exactly that
|
|
276
|
+
* until 2026-08-18; a 5.042 s 4K asset was measured being delivered at
|
|
277
|
+
* 426x240 because of it.) Leave `startLevel` unset: hls.js then opens on the
|
|
278
|
+
* FIRST level in the manifest, and the server puts the right one there —
|
|
279
|
+
* a mid rung for long video, the top rung for a clip under 18 s, which is the
|
|
280
|
+
* same rung native HLS opens on per RFC 8216 §6.3.4. The ladder decides; the
|
|
281
|
+
* player should not second-guess it.
|
|
282
|
+
*
|
|
283
|
+
* `capLevelToPlayerSize` is worth disabling explicitly: `@videojs/core`
|
|
284
|
+
* defaults it to `true`, which caps quality to the player's rendered pixel box,
|
|
285
|
+
* so a small inline player is pinned to 240p/360p on any connection.
|
|
286
|
+
*
|
|
272
287
|
* On first request the server returns 202 Accepted while a background
|
|
273
288
|
* job transcodes the ladder (typically 1-3 min for a 90 s source);
|
|
274
289
|
* subsequent requests get 302 to the cached master.m3u8. Keep the
|