@omerdlw/base-framework 2.0.0 → 3.0.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/README.md +4 -1
- package/dist/{chunk-XASQT4CQ.js → chunk-66EYJBIP.js} +47 -27
- package/dist/chunk-66EYJBIP.js.map +1 -0
- package/dist/{chunk-65ZB4QTQ.js → chunk-CYU6SGAL.js} +3 -3
- package/dist/{chunk-65ZB4QTQ.js.map → chunk-CYU6SGAL.js.map} +1 -1
- package/dist/{chunk-6SG7V77J.js → chunk-HHWRTQKQ.js} +100 -67
- package/dist/chunk-HHWRTQKQ.js.map +1 -0
- package/dist/chunk-HLL5EHXC.js +485 -0
- package/dist/chunk-HLL5EHXC.js.map +1 -0
- package/dist/{chunk-3MSK4XGK.js → chunk-JIXBFFRD.js} +258 -405
- package/dist/chunk-JIXBFFRD.js.map +1 -0
- package/dist/{chunk-KKQT46TP.js → chunk-M57SNWXK.js} +8 -6
- package/dist/chunk-M57SNWXK.js.map +1 -0
- package/dist/chunk-RIOKLMYM.js +145 -0
- package/dist/chunk-RIOKLMYM.js.map +1 -0
- package/dist/{chunk-QXR55VVS.js → chunk-TG6NMHXI.js} +241 -162
- package/dist/chunk-TG6NMHXI.js.map +1 -0
- package/dist/index.js +7 -5
- package/dist/modules/ambient/analyze.d.ts +18 -3
- package/dist/modules/ambient/analyze.d.ts.map +1 -1
- package/dist/modules/ambient/dom.d.ts +14 -1
- package/dist/modules/ambient/dom.d.ts.map +1 -1
- package/dist/modules/ambient/hooks.d.ts.map +1 -1
- package/dist/modules/ambient/index.d.ts +2 -2
- package/dist/modules/ambient/index.d.ts.map +1 -1
- package/dist/modules/ambient/index.js +1 -1
- package/dist/modules/ambient/server/index.d.ts +1 -1
- package/dist/modules/ambient/server/index.d.ts.map +1 -1
- package/dist/modules/ambient/server/index.js +2 -2
- package/dist/modules/ambient/server/index.js.map +1 -1
- package/dist/modules/ambient/settings.d.ts +1 -0
- package/dist/modules/ambient/settings.d.ts.map +1 -1
- package/dist/modules/ambient/types.d.ts +13 -0
- package/dist/modules/ambient/types.d.ts.map +1 -1
- package/dist/modules/ambient/worker/index.js +1 -1
- package/dist/modules/context-menu/index.js +4 -3
- package/dist/modules/dock/cards.d.ts +3 -0
- package/dist/modules/dock/cards.d.ts.map +1 -1
- package/dist/modules/dock/constants.d.ts +1 -20
- package/dist/modules/dock/constants.d.ts.map +1 -1
- package/dist/modules/dock/index.js +3 -2
- package/dist/modules/dock/layout.d.ts.map +1 -1
- package/dist/modules/dock/motion.d.ts +6 -0
- package/dist/modules/dock/motion.d.ts.map +1 -1
- package/dist/modules/dock/overlay.d.ts +1 -1
- package/dist/modules/dock/overlay.d.ts.map +1 -1
- package/dist/modules/dock/routing/guards.d.ts +1 -1
- package/dist/modules/dock/routing/navigation.d.ts +7 -4
- package/dist/modules/dock/routing/navigation.d.ts.map +1 -1
- package/dist/modules/dock/runtime/display.d.ts +31 -2
- package/dist/modules/dock/runtime/display.d.ts.map +1 -1
- package/dist/modules/dock/runtime/dock.d.ts +2 -2
- package/dist/modules/dock/runtime/dock.d.ts.map +1 -1
- package/dist/modules/dock/surface/view-model.d.ts.map +1 -1
- package/dist/modules/dock/types.d.ts +9 -27
- package/dist/modules/dock/types.d.ts.map +1 -1
- package/dist/modules/index.d.ts +3 -2
- package/dist/modules/index.d.ts.map +1 -1
- package/dist/modules/index.js +7 -5
- package/dist/modules/loading/context.d.ts.map +1 -1
- package/dist/modules/loading/index.js +1 -1
- package/dist/modules/navigation/constants.d.ts +37 -0
- package/dist/modules/navigation/constants.d.ts.map +1 -0
- package/dist/modules/navigation/context.d.ts +10 -0
- package/dist/modules/navigation/context.d.ts.map +1 -0
- package/dist/modules/navigation/hooks.d.ts +29 -0
- package/dist/modules/navigation/hooks.d.ts.map +1 -0
- package/dist/modules/navigation/index.d.ts +10 -0
- package/dist/modules/navigation/index.d.ts.map +1 -0
- package/dist/modules/navigation/index.js +81 -0
- package/dist/modules/navigation/index.js.map +1 -0
- package/dist/modules/navigation/listeners.d.ts +15 -0
- package/dist/modules/navigation/listeners.d.ts.map +1 -0
- package/dist/modules/navigation/module.d.ts +25 -0
- package/dist/modules/navigation/module.d.ts.map +1 -0
- package/dist/modules/navigation/navigator.d.ts +8 -0
- package/dist/modules/navigation/navigator.d.ts.map +1 -0
- package/dist/modules/navigation/settings.d.ts +10 -0
- package/dist/modules/navigation/settings.d.ts.map +1 -0
- package/dist/modules/navigation/state.d.ts +20 -0
- package/dist/modules/navigation/state.d.ts.map +1 -0
- package/dist/modules/navigation/types.d.ts +168 -0
- package/dist/modules/navigation/types.d.ts.map +1 -0
- package/dist/modules/navigation/utils.d.ts +11 -0
- package/dist/modules/navigation/utils.d.ts.map +1 -0
- package/docs/getting-started.md +2 -0
- package/docs/modules/README.md +5 -1
- package/docs/modules/ambient.md +9 -6
- package/docs/modules/dock.md +13 -11
- package/docs/modules/loading.md +2 -2
- package/docs/modules/navigation.md +216 -0
- package/docs/proposals/navigation.md +209 -0
- package/package.json +6 -1
- package/templates/AGENTS.md +2 -0
- package/dist/chunk-3MSK4XGK.js.map +0 -1
- package/dist/chunk-6SG7V77J.js.map +0 -1
- package/dist/chunk-KKQT46TP.js.map +0 -1
- package/dist/chunk-QXR55VVS.js.map +0 -1
- package/dist/chunk-XASQT4CQ.js.map +0 -1
- package/dist/modules/dock/routing/transactions.d.ts +0 -21
- package/dist/modules/dock/routing/transactions.d.ts.map +0 -1
|
@@ -130,10 +130,12 @@ var DEFAULT_CSS_VAR_NAMES = Object.freeze({
|
|
|
130
130
|
tone: "--ambient-{role}-{tone}"
|
|
131
131
|
});
|
|
132
132
|
var DEFAULT_PROXY = "/api/ambient/proxy?url=";
|
|
133
|
+
var DEFAULT_LINGER_MS = 3e3;
|
|
133
134
|
var createDefaults = () => ({
|
|
134
135
|
analysis: { ...DEFAULT_ANALYSIS },
|
|
135
136
|
cacheLimit: 100,
|
|
136
137
|
cssVars: { ...DEFAULT_CSS_VAR_NAMES, tones: AMBIENT_TONES },
|
|
138
|
+
linger: DEFAULT_LINGER_MS,
|
|
137
139
|
proxy: DEFAULT_PROXY,
|
|
138
140
|
strategy: "auto",
|
|
139
141
|
worker: null
|
|
@@ -148,6 +150,7 @@ function mergeAmbientSettings(base, input) {
|
|
|
148
150
|
analysis: { ...base.analysis, ...input.analysis },
|
|
149
151
|
cacheLimit: input.cacheLimit ?? base.cacheLimit,
|
|
150
152
|
cssVars: { ...base.cssVars, ...input.cssVars },
|
|
153
|
+
linger: input.linger ?? base.linger,
|
|
151
154
|
proxy: input.proxy === void 0 ? base.proxy : input.proxy,
|
|
152
155
|
strategy: input.strategy ?? base.strategy,
|
|
153
156
|
worker: input.worker === void 0 ? base.worker : input.worker
|
|
@@ -238,6 +241,7 @@ function kmeans(points, weights, requested, { iterations = 16, lightnessWeight =
|
|
|
238
241
|
}
|
|
239
242
|
|
|
240
243
|
// src/modules/ambient/analyze.ts
|
|
244
|
+
var AMBIENT_ANALYSIS_VERSION = 2;
|
|
241
245
|
var MIN_CHROMA = 0.022;
|
|
242
246
|
var MIN_PRESENCE = 0.03;
|
|
243
247
|
var MIN_POPULATION = 4e-3;
|
|
@@ -294,26 +298,47 @@ function pickBest(items, score) {
|
|
|
294
298
|
return best;
|
|
295
299
|
}
|
|
296
300
|
var round3 = (value) => Math.round(value * 1e3) / 1e3;
|
|
297
|
-
function
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
+
function skinLikeness({ c, h, l }) {
|
|
302
|
+
return (1 - smoothstep(12, 26, hueDistance(h, 54))) * smoothstep(0.02, 0.035, c) * (1 - smoothstep(0.11, 0.15, c)) * smoothstep(0.26, 0.38, l) * (1 - smoothstep(0.88, 0.95, l));
|
|
303
|
+
}
|
|
304
|
+
var warmth = (h) => 1 - smoothstep(22, 50, hueDistance(h, 42));
|
|
305
|
+
var salience = (color) => 1 - 0.65 * skinLikeness(color);
|
|
306
|
+
var roleChroma = (source, { cap, gain }) => Math.min(
|
|
307
|
+
cap * (1 - 0.3 * warmth(source.h)),
|
|
308
|
+
// A faint tint is raised further, so it still reads as a colour.
|
|
309
|
+
Math.max(source.c * gain, Math.min(0.05, source.c * 1.6)) * (1 - 0.3 * skinLikeness(source))
|
|
310
|
+
);
|
|
311
|
+
var fitTone = (h, l, c) => ({
|
|
312
|
+
c: Math.max(0, Math.min(c, maxChroma(l, h) * 0.96)),
|
|
313
|
+
h,
|
|
314
|
+
l
|
|
315
|
+
});
|
|
316
|
+
function buildSwatch(tone, population, fromImage, minContrast) {
|
|
317
|
+
const room = maxChroma(tone.l, tone.h) * 0.96;
|
|
318
|
+
const rel = room > 0 ? tone.c / room : 0;
|
|
301
319
|
const ramp = {};
|
|
302
320
|
for (const step of AMBIENT_TONES) {
|
|
303
|
-
ramp[step] = formatOklch(toneOf(h, step / 100, rel,
|
|
321
|
+
ramp[step] = formatOklch(toneOf(tone.h, step / 100, rel, Math.max(tone.c, 0.04)));
|
|
304
322
|
}
|
|
305
323
|
return {
|
|
306
324
|
c: round3(tone.c),
|
|
307
325
|
color: formatOklch(tone),
|
|
308
326
|
fromImage,
|
|
309
|
-
h: Math.round(h * 10) / 10,
|
|
327
|
+
h: Math.round(tone.h * 10) / 10,
|
|
310
328
|
l: round3(tone.l),
|
|
311
329
|
on: formatOklch(onColorFor(tone, minContrast)),
|
|
312
|
-
population: round3(
|
|
330
|
+
population: round3(population),
|
|
313
331
|
ramp
|
|
314
332
|
};
|
|
315
333
|
}
|
|
316
|
-
|
|
334
|
+
function roleTone(source, spec, fallback, dilution = 1) {
|
|
335
|
+
if (!source) return fitTone(fallback.h, clamp(fallback.l, spec.min, spec.max), fallback.c);
|
|
336
|
+
return fitTone(
|
|
337
|
+
source.h,
|
|
338
|
+
clamp(source.l, spec.min, spec.max),
|
|
339
|
+
roleChroma(source, spec) * dilution
|
|
340
|
+
);
|
|
341
|
+
}
|
|
317
342
|
function clusterAmbientPixels(pixels, options) {
|
|
318
343
|
const { data, width, height } = pixels;
|
|
319
344
|
const bounds = options.letterbox ? findContentBounds(pixels) : { bottom: height, left: 0, right: width, top: 0 };
|
|
@@ -385,18 +410,23 @@ function clusterAmbientPixels(pixels, options) {
|
|
|
385
410
|
points[i * 3 + 2] = b;
|
|
386
411
|
weights[i] = w * (1 + 5 * Math.sqrt(a * a + b * b));
|
|
387
412
|
});
|
|
388
|
-
const { assignment,
|
|
389
|
-
const
|
|
390
|
-
members.forEach((bin, i) =>
|
|
413
|
+
const { assignment, k } = kmeans(points, weights, budgets[group]);
|
|
414
|
+
const sums = new Float64Array(k * 4);
|
|
415
|
+
members.forEach((bin, i) => {
|
|
416
|
+
for (let channel = 0; channel < 4; channel++) {
|
|
417
|
+
sums[assignment[i] * 4 + channel] += binSums[bin * 4 + channel];
|
|
418
|
+
}
|
|
419
|
+
});
|
|
391
420
|
const index = new Int32Array(k).fill(-1);
|
|
392
421
|
for (let j = 0; j < k; j++) {
|
|
393
|
-
|
|
394
|
-
|
|
422
|
+
const pop = sums[j * 4 + 3];
|
|
423
|
+
if (pop <= 0) continue;
|
|
424
|
+
const lch = labToLch([sums[j * 4] / pop, sums[j * 4 + 1] / pop, sums[j * 4 + 2] / pop]);
|
|
395
425
|
const room = maxChroma(lch.l, lch.h);
|
|
396
426
|
index[j] = clusters.length;
|
|
397
427
|
clusters.push({
|
|
398
428
|
...lch,
|
|
399
|
-
pop: pop
|
|
429
|
+
pop: pop / total,
|
|
400
430
|
rel: room > 0 ? clamp(lch.c / room, 0, 1) : 0,
|
|
401
431
|
rely: reliability(lch.l)
|
|
402
432
|
});
|
|
@@ -404,20 +434,26 @@ function clusterAmbientPixels(pixels, options) {
|
|
|
404
434
|
members.forEach((bin, i) => clusterOfBin[bin] = index[assignment[i]]);
|
|
405
435
|
});
|
|
406
436
|
const regionWeights = AMBIENT_REGIONS.map(() => new Float64Array(clusters.length));
|
|
437
|
+
const regionLab = AMBIENT_REGIONS.map(() => new Float64Array(clusters.length * 3));
|
|
407
438
|
for (let i = 0; i < pixelBins.length; i++) {
|
|
408
439
|
const bin = pixelBins[i];
|
|
409
440
|
if (bin < 0) continue;
|
|
410
441
|
const cluster = clusterOfBin[bin];
|
|
411
442
|
const bits = pixelRegions[i];
|
|
443
|
+
const w = binSums[bin * 4 + 3];
|
|
412
444
|
AMBIENT_REGIONS.forEach((region, r) => {
|
|
413
|
-
if (bits & REGION_BITS[region])
|
|
445
|
+
if (!(bits & REGION_BITS[region])) return;
|
|
446
|
+
regionWeights[r][cluster] += 1;
|
|
447
|
+
for (let channel = 0; channel < 3; channel++) {
|
|
448
|
+
regionLab[r][cluster * 3 + channel] += binSums[bin * 4 + channel] / w;
|
|
449
|
+
}
|
|
414
450
|
});
|
|
415
451
|
}
|
|
416
|
-
return { clusters, meanL, regionWeights };
|
|
452
|
+
return { clusters, meanL, regionLab, regionWeights };
|
|
417
453
|
}
|
|
418
454
|
function analyzeAmbientPixels(pixels, overrides = {}) {
|
|
419
455
|
const options = { ...DEFAULT_ANALYSIS, ...overrides };
|
|
420
|
-
const { clusters, meanL, regionWeights } = clusterAmbientPixels(pixels, options);
|
|
456
|
+
const { clusters, meanL, regionLab, regionWeights } = clusterAmbientPixels(pixels, options);
|
|
421
457
|
const chromatic = clusters.filter(isChromatic);
|
|
422
458
|
const presence = chromatic.reduce(
|
|
423
459
|
(sum, cluster) => sum + cluster.pop * colorfulness(cluster.c) * cluster.rely,
|
|
@@ -426,7 +462,7 @@ function analyzeAmbientPixels(pixels, overrides = {}) {
|
|
|
426
462
|
const neutral = presence < MIN_PRESENCE;
|
|
427
463
|
const dilution = 0.55 + 0.45 * Math.min(1, presence / 0.25);
|
|
428
464
|
const { minContrast, minHueDistance } = options;
|
|
429
|
-
const grey = { h: 0, l: clamp(meanL, 0.3, 0.8) };
|
|
465
|
+
const grey = { c: 0, h: 0, l: clamp(meanL, 0.3, 0.8) };
|
|
430
466
|
const family = /* @__PURE__ */ new Map();
|
|
431
467
|
for (const cluster of chromatic) {
|
|
432
468
|
let share2 = 0;
|
|
@@ -436,69 +472,62 @@ function analyzeAmbientPixels(pixels, overrides = {}) {
|
|
|
436
472
|
family.set(cluster, share2);
|
|
437
473
|
}
|
|
438
474
|
const share = (cluster) => family.get(cluster) ?? cluster.pop;
|
|
439
|
-
const
|
|
440
|
-
|
|
475
|
+
const dominantPick = neutral ? null : pickBest(
|
|
476
|
+
chromatic,
|
|
477
|
+
(cluster) => share(cluster) * cluster.c * cluster.rely * salience(cluster)
|
|
478
|
+
);
|
|
441
479
|
const vividPick = neutral ? null : pickBest(
|
|
442
480
|
chromatic.filter((cluster) => share(cluster) >= MIN_POPULATION),
|
|
443
|
-
(cluster) => cluster.c * cluster.c * Math.pow(share(cluster), 0.3) * cluster.rely
|
|
481
|
+
(cluster) => cluster.c * cluster.c * Math.pow(share(cluster), 0.3) * cluster.rely * salience(cluster)
|
|
444
482
|
);
|
|
445
483
|
const accentPick = pickBest(
|
|
446
484
|
chromatic.filter(
|
|
447
485
|
(cluster) => neutral ? share(cluster) >= 6e-3 && cluster.c >= 0.06 : share(cluster) >= MIN_POPULATION && cluster.c >= 0.035 && (!dominantPick || hueDistance(cluster.h, dominantPick.h) >= minHueDistance)
|
|
448
486
|
),
|
|
449
|
-
(cluster) => Math.pow(share(cluster), 0.6) * cluster.c * cluster.rely
|
|
487
|
+
(cluster) => Math.pow(share(cluster), 0.6) * cluster.c * cluster.rely * salience(cluster)
|
|
450
488
|
);
|
|
451
489
|
const mutedPick = neutral ? null : pickBest(
|
|
452
490
|
chromatic.filter((cluster) => cluster.c <= 0.09),
|
|
453
491
|
(cluster) => share(cluster) * cluster.rely * (1 - cluster.c / 0.12)
|
|
454
492
|
);
|
|
455
493
|
const dominantHue = dominantPick?.h ?? vividPick?.h ?? 0;
|
|
494
|
+
const accentSource = accentPick ?? vividPick;
|
|
456
495
|
const roles = {
|
|
457
496
|
dominant: buildSwatch(
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
cap: 0.22,
|
|
461
|
-
max: 0.74,
|
|
462
|
-
min: 0.42,
|
|
463
|
-
rel: dominantPick ? lift(dominantPick.rel, 0.25, 0.85, 0.9) : 0
|
|
464
|
-
},
|
|
465
|
-
grey,
|
|
497
|
+
roleTone(dominantPick, { cap: 0.2, gain: 1.15, max: 0.74, min: 0.42 }, grey),
|
|
498
|
+
dominantPick ? share(dominantPick) : 0,
|
|
466
499
|
true,
|
|
467
500
|
minContrast
|
|
468
501
|
),
|
|
469
502
|
vibrant: buildSwatch(
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
cap: 0.
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
{ h: dominantHue, l: 0.78 },
|
|
503
|
+
roleTone(
|
|
504
|
+
vividPick,
|
|
505
|
+
{ cap: 0.22, gain: 1.35, max: 0.84, min: 0.62 },
|
|
506
|
+
{ c: 0, h: dominantHue, l: 0.78 },
|
|
507
|
+
dilution
|
|
508
|
+
),
|
|
509
|
+
vividPick ? share(vividPick) : 0,
|
|
478
510
|
true,
|
|
479
511
|
minContrast
|
|
480
512
|
),
|
|
481
513
|
muted: buildSwatch(
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
cap: 0.
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
},
|
|
489
|
-
{ h: dominantHue, l: clamp(meanL, 0.38, 0.66) },
|
|
514
|
+
roleTone(
|
|
515
|
+
mutedPick,
|
|
516
|
+
{ cap: 0.07, gain: 1, max: 0.66, min: 0.38 },
|
|
517
|
+
{ c: dominantPick ? 0.035 : 0, h: dominantHue, l: clamp(meanL, 0.38, 0.66) }
|
|
518
|
+
),
|
|
519
|
+
mutedPick ? share(mutedPick) : 0,
|
|
490
520
|
Boolean(mutedPick) || neutral,
|
|
491
521
|
minContrast
|
|
492
522
|
),
|
|
493
523
|
accent: buildSwatch(
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
cap: 0.
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
{ h: dominantHue, l: 0.72 },
|
|
524
|
+
roleTone(
|
|
525
|
+
accentSource,
|
|
526
|
+
{ cap: 0.22, gain: 1.3, max: 0.8, min: 0.55 },
|
|
527
|
+
{ c: 0, h: dominantHue, l: 0.72 },
|
|
528
|
+
dilution
|
|
529
|
+
),
|
|
530
|
+
accentSource ? share(accentSource) : 0,
|
|
502
531
|
Boolean(accentPick),
|
|
503
532
|
minContrast
|
|
504
533
|
)
|
|
@@ -515,35 +544,39 @@ function analyzeAmbientPixels(pixels, overrides = {}) {
|
|
|
515
544
|
options.shadowLightness - 0.02,
|
|
516
545
|
options.shadowLightness + 0.02
|
|
517
546
|
);
|
|
518
|
-
const shadow = deepSource ? toneOf(deepSource.h, shadowL,
|
|
547
|
+
const shadow = deepSource ? toneOf(deepSource.h, shadowL, clamp(0.3 + 0.7 * deepSource.rel, 0, 0.85), 0.1) : { c: 0, h: 0, l: shadowL };
|
|
519
548
|
const regions = {};
|
|
520
549
|
AMBIENT_REGIONS.forEach((region, r) => {
|
|
521
550
|
const weights = regionWeights[r];
|
|
551
|
+
const lab = regionLab[r];
|
|
522
552
|
let regionTotal = 0;
|
|
523
553
|
let regionL = 0;
|
|
524
554
|
clusters.forEach((cluster, j) => {
|
|
525
555
|
regionTotal += weights[j];
|
|
526
556
|
regionL += cluster.l * weights[j];
|
|
527
557
|
});
|
|
528
|
-
const share2 = (j) => regionTotal > 0 ? weights[j] / regionTotal : 0;
|
|
529
558
|
let strength = 0;
|
|
530
559
|
let pick = null;
|
|
531
560
|
let pickScore = 0;
|
|
532
|
-
clusters.forEach((
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
const
|
|
561
|
+
clusters.forEach((_, j) => {
|
|
562
|
+
const count = weights[j];
|
|
563
|
+
if (count <= 0) return;
|
|
564
|
+
const local = labToLch([lab[j * 3] / count, lab[j * 3 + 1] / count, lab[j * 3 + 2] / count]);
|
|
565
|
+
const rely = reliability(local.l);
|
|
566
|
+
if (local.c < MIN_CHROMA || rely <= 0) return;
|
|
567
|
+
const part = count / regionTotal;
|
|
568
|
+
strength += part * colorfulness(local.c) * rely;
|
|
569
|
+
const score = part * local.c * rely * salience(local);
|
|
536
570
|
if (score > pickScore) {
|
|
537
571
|
pickScore = score;
|
|
538
|
-
pick =
|
|
572
|
+
pick = local;
|
|
539
573
|
}
|
|
540
574
|
});
|
|
541
575
|
const chosen = neutral || strength < MIN_PRESENCE ? null : pick;
|
|
542
|
-
const tone = chosen ?
|
|
576
|
+
const tone = chosen ? fitTone(
|
|
543
577
|
chosen.h,
|
|
544
578
|
clamp(chosen.l, 0.42, 0.72),
|
|
545
|
-
|
|
546
|
-
0.22
|
|
579
|
+
roleChroma(chosen, { cap: 0.18, gain: 1.15 })
|
|
547
580
|
) : {
|
|
548
581
|
c: 0,
|
|
549
582
|
h: 0,
|
|
@@ -572,6 +605,6 @@ function fitSample(width, height, size) {
|
|
|
572
605
|
};
|
|
573
606
|
}
|
|
574
607
|
|
|
575
|
-
export { analyzeAmbientPixels, configureAmbient, contrastRatio, findContentBounds, fitSample, formatOklch, getAmbientSettings, maxChroma, onColorFor, resolveAnalysis, srgbToOklab, toneOf };
|
|
576
|
-
//# sourceMappingURL=chunk-
|
|
577
|
-
//# sourceMappingURL=chunk-
|
|
608
|
+
export { AMBIENT_ANALYSIS_VERSION, analyzeAmbientPixels, configureAmbient, contrastRatio, findContentBounds, fitSample, formatOklch, getAmbientSettings, maxChroma, onColorFor, resolveAnalysis, srgbToOklab, toneOf };
|
|
609
|
+
//# sourceMappingURL=chunk-HHWRTQKQ.js.map
|
|
610
|
+
//# sourceMappingURL=chunk-HHWRTQKQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/modules/ambient/oklab.ts","../src/modules/ambient/settings.ts","../src/modules/ambient/quantize.ts","../src/modules/ambient/analyze.ts"],"names":["round","share"],"mappings":"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","file":"chunk-HHWRTQKQ.js","sourcesContent":["import type { OklchColor } from \"./types\";\n\n// Pure OKLab / OKLCH math shared by the client, the worker and the server.\n// Nothing here touches the DOM or React.\n\nexport type Lab = [l: number, a: number, b: number];\nexport type Rgb = [r: number, g: number, b: number];\n\nconst DEG = Math.PI / 180;\n\nconst LINEAR_LUT = new Float32Array(256);\nfor (let i = 0; i < 256; i++) {\n const v = i / 255;\n LINEAR_LUT[i] = v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);\n}\n\nexport function clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value));\n}\n\nexport function smoothstep(edge0: number, edge1: number, value: number): number {\n const t = clamp((value - edge0) / (edge1 - edge0), 0, 1);\n return t * t * (3 - 2 * t);\n}\n\n/** 8-bit sRGB channels → OKLab. */\nexport function srgbToOklab(r: number, g: number, b: number): Lab {\n const lr = LINEAR_LUT[r & 255];\n const lg = LINEAR_LUT[g & 255];\n const lb = LINEAR_LUT[b & 255];\n\n const l = Math.cbrt(0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb);\n const m = Math.cbrt(0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb);\n const s = Math.cbrt(0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb);\n\n return [\n 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,\n 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,\n ];\n}\n\n/** OKLCH → linear sRGB; channels outside 0–1 mean the colour is out of gamut. */\nexport function oklchToLinearSrgb(l: number, c: number, h: number): Rgb {\n const a = c * Math.cos(h * DEG);\n const b = c * Math.sin(h * DEG);\n const l_ = (l + 0.3963377774 * a + 0.2158037573 * b) ** 3;\n const m_ = (l - 0.1055613458 * a - 0.0638541728 * b) ** 3;\n const s_ = (l - 0.0894841775 * a - 1.291485548 * b) ** 3;\n return [\n 4.0767416621 * l_ - 3.3077115913 * m_ + 0.2309699292 * s_,\n -1.2684380046 * l_ + 2.6097574011 * m_ - 0.3413193965 * s_,\n -0.0041960863 * l_ - 0.7034186147 * m_ + 1.707614701 * s_,\n ];\n}\n\nexport function labToLch([l, a, b]: Lab): OklchColor {\n const c = Math.sqrt(a * a + b * b);\n const h = c < 1e-6 ? 0 : (Math.atan2(b, a) / DEG + 360) % 360;\n return { c, h, l };\n}\n\nconst inGamut = (rgb: Rgb) => rgb.every((v) => v >= -1e-5 && v <= 1 + 1e-5);\n\n/**\n * The most chroma sRGB can show at this lightness and hue (binary search on\n * the gamut boundary). Dark blues and purples have far more room than dark\n * greens or yellows, which is why one fixed chroma never looks right.\n */\nexport function maxChroma(l: number, h: number): number {\n if (l <= 0 || l >= 1) return 0;\n let low = 0;\n let high = 0.4;\n for (let step = 0; step < 18; step++) {\n const middle = (low + high) / 2;\n if (inGamut(oklchToLinearSrgb(l, middle, h))) low = middle;\n else high = middle;\n }\n return low;\n}\n\n/** Share of the available chroma a colour uses (0 grey … 1 on the gamut edge). */\nexport function relativeChroma({ c, h, l }: OklchColor): number {\n const room = maxChroma(l, h);\n return room <= 0 ? 0 : clamp(c / room, 0, 1);\n}\n\nexport function hueDistance(a: number, b: number): number {\n const d = Math.abs(a - b) % 360;\n return d > 180 ? 360 - d : d;\n}\n\n/** WCAG 2 relative luminance of an OKLCH colour (gamut-clipped). */\nexport function luminance({ c, h, l }: OklchColor): number {\n const [r, g, b] = oklchToLinearSrgb(l, c, h).map((v) => clamp(v, 0, 1));\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n\nexport function contrastRatio(a: OklchColor, b: OklchColor): number {\n const la = luminance(a);\n const lb = luminance(b);\n return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);\n}\n\nconst round = (value: number, digits: number) => {\n const factor = 10 ** digits;\n return Math.round(value * factor) / factor;\n};\n\nexport function formatOklch({ c, h, l }: OklchColor): string {\n const chroma = c < 0.0005 ? 0 : c;\n return `oklch(${round(clamp(l, 0, 1), 3).toFixed(3)} ${round(chroma, 3).toFixed(3)} ${round(chroma === 0 ? 0 : h, 1).toFixed(1)})`;\n}\n\n/**\n * A tone of a hue at lightness `l`, using `rel` of the chroma sRGB allows\n * there (never more than `cap`). This keeps a hue's character across a whole\n * ramp: dark tones of blue stay blue instead of collapsing to grey.\n */\nexport function toneOf(\n h: number,\n l: number,\n rel: number,\n cap = 0.3,\n): OklchColor {\n const room = maxChroma(l, h) * 0.96;\n return { c: Math.min(cap, clamp(rel, 0, 1) * room), h, l };\n}\n\n/**\n * Text colour for a background: a near-white or near-black carrying a hint of\n * the background's hue, pushed toward pure white / black until it reaches\n * `minContrast` (WCAG 2 ratio).\n */\nexport function onColorFor(\n background: OklchColor,\n minContrast = 4.5,\n): OklchColor {\n const light = (l: number) => toneOf(background.h, l, 0.12, 0.012);\n const dark = (l: number) => toneOf(background.h, l, 0.35, 0.03);\n const towardLight = contrastRatio(light(0.985), background);\n const towardDark = contrastRatio(dark(0.18), background);\n const useLight = towardLight >= minContrast || towardLight >= towardDark;\n\n for (let step = 0; step <= 12; step++) {\n const candidate = useLight\n ? light(Math.min(1, 0.985 + step * 0.0025))\n : dark(Math.max(0, 0.18 - step * 0.015));\n if (contrastRatio(candidate, background) >= minContrast) return candidate;\n }\n return useLight ? { c: 0, h: 0, l: 1 } : { c: 0, h: 0, l: 0 };\n}\n","import type {\n AmbientAnalysisOptions,\n AmbientCssVarNames,\n AmbientProxy,\n AmbientSettings,\n AmbientSettingsInput,\n AmbientTone,\n} from \"./types\";\n\nexport const AMBIENT_TONES = Object.freeze([\n 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 95,\n] as const) satisfies readonly AmbientTone[];\n\nexport const AMBIENT_ROLES = Object.freeze([\n \"dominant\",\n \"vibrant\",\n \"muted\",\n \"accent\",\n] as const);\n\nexport const AMBIENT_REGIONS = Object.freeze([\n \"top\",\n \"bottom\",\n \"left\",\n \"right\",\n \"center\",\n] as const);\n\nexport const DEFAULT_ANALYSIS: Readonly<AmbientAnalysisOptions> = Object.freeze({\n centerWeight: 0.5,\n clusters: 7,\n letterbox: true,\n minContrast: 4.5,\n minHueDistance: 40,\n sampleSize: 128,\n shadowLightness: 0.16,\n});\n\nexport const DEFAULT_CSS_VAR_NAMES: Readonly<AmbientCssVarNames> = Object.freeze({\n on: \"--ambient-on-{role}\",\n region: \"--ambient-{region}\",\n role: \"--ambient-{role}\",\n shadow: \"--ambient-shadow\",\n tone: \"--ambient-{role}-{tone}\",\n});\n\nexport const DEFAULT_PROXY = \"/api/ambient/proxy?url=\";\n\nexport const DEFAULT_LINGER_MS = 3_000;\n\nconst createDefaults = (): AmbientSettings => ({\n analysis: { ...DEFAULT_ANALYSIS },\n cacheLimit: 100,\n cssVars: { ...DEFAULT_CSS_VAR_NAMES, tones: AMBIENT_TONES },\n linger: DEFAULT_LINGER_MS,\n proxy: DEFAULT_PROXY,\n strategy: \"auto\",\n worker: null,\n});\n\n// Kept on globalThis so every bundled copy of this module (one per package\n// entry) shares one configuration.\nconst SETTINGS_KEY = Symbol.for(\"@omerdlw/base-framework/ambient/settings\");\ntype GlobalWithSettings = typeof globalThis & {\n [SETTINGS_KEY]?: AmbientSettings;\n};\nconst scope = globalThis as GlobalWithSettings;\n\nexport function getAmbientSettings(): AmbientSettings {\n return (scope[SETTINGS_KEY] ??= createDefaults());\n}\n\nexport function mergeAmbientSettings(\n base: AmbientSettings,\n input: AmbientSettingsInput,\n): AmbientSettings {\n return {\n analysis: { ...base.analysis, ...input.analysis },\n cacheLimit: input.cacheLimit ?? base.cacheLimit,\n cssVars: { ...base.cssVars, ...input.cssVars },\n linger: input.linger ?? base.linger,\n proxy: input.proxy === undefined ? base.proxy : input.proxy,\n strategy: input.strategy ?? base.strategy,\n worker: input.worker === undefined ? base.worker : input.worker,\n };\n}\n\n/**\n * Sets the proxy, CSS variable names, extraction strategy, worker and analysis\n * defaults for every ambient theme. Returns a function that restores the\n * previous settings.\n */\nexport function configureAmbient(input: AmbientSettingsInput): () => void {\n const previous = getAmbientSettings();\n const next = mergeAmbientSettings(previous, input);\n scope[SETTINGS_KEY] = next;\n return () => {\n if (scope[SETTINGS_KEY] === next) scope[SETTINGS_KEY] = previous;\n };\n}\n\nexport function resolveAnalysis(\n overrides?: Partial<AmbientAnalysisOptions> | null,\n): AmbientAnalysisOptions {\n return { ...getAmbientSettings().analysis, ...overrides };\n}\n\n/** The URL to retry through, or `null` when no proxy applies. */\nexport function resolveProxyUrl(proxy: AmbientProxy, src: string): string | null {\n if (!proxy || !/^https?:\\/\\//i.test(src)) return null;\n if (typeof proxy === \"function\") return proxy(src);\n const encoded = encodeURIComponent(src);\n return proxy.includes(\"{url}\")\n ? proxy.replace(\"{url}\", encoded)\n : `${proxy}${encoded}`;\n}\n","export interface KMeansResult {\n /** Index of the cluster each point belongs to. */\n assignment: Int32Array;\n /** `k × 3` OKLab centroids. */\n centroids: Float64Array;\n /** Number of clusters actually found (≤ the requested k). */\n k: number;\n}\n\nexport interface KMeansOptions {\n iterations?: number;\n /** Weight of ΔL² against Δa² + Δb²; below 1 favours hue over lightness. */\n lightnessWeight?: number;\n}\n\n/**\n * Weighted k-means in OKLab with deterministic seeding (the heaviest point,\n * then repeatedly the point that is heaviest × furthest from every seed), so\n * the same pixels always give the same palette on the server and the client.\n *\n * `points` holds `n × 3` OKLab values and `weights` one weight per point.\n */\nexport function kmeans(\n points: Float64Array,\n weights: Float64Array,\n requested: number,\n { iterations = 16, lightnessWeight = 0.45 }: KMeansOptions = {},\n): KMeansResult {\n const n = weights.length;\n const assignment = new Int32Array(n);\n const k = Math.max(0, Math.min(requested, n));\n const centroids = new Float64Array(k * 3);\n if (k === 0) return { assignment, centroids, k };\n\n const distance = (i: number, j: number) => {\n const dl = points[i * 3] - centroids[j * 3];\n const da = points[i * 3 + 1] - centroids[j * 3 + 1];\n const db = points[i * 3 + 2] - centroids[j * 3 + 2];\n return lightnessWeight * dl * dl + da * da + db * db;\n };\n\n let first = 0;\n for (let i = 1; i < n; i++) if (weights[i] > weights[first]) first = i;\n centroids.set(points.subarray(first * 3, first * 3 + 3), 0);\n\n const nearest = new Float64Array(n).fill(Infinity);\n let found = 1;\n for (; found < k; found++) {\n let best = -1;\n let bestScore = 0;\n for (let i = 0; i < n; i++) {\n const d = distance(i, found - 1);\n if (d < nearest[i]) nearest[i] = d;\n const score = weights[i] * nearest[i];\n if (score > bestScore) {\n bestScore = score;\n best = i;\n }\n }\n if (best < 0) break; // every remaining point sits on a seed\n centroids.set(points.subarray(best * 3, best * 3 + 3), found * 3);\n }\n\n const sums = new Float64Array(found * 4);\n for (let round = 0; round < iterations; round++) {\n let moved = round === 0;\n for (let i = 0; i < n; i++) {\n let best = 0;\n let bestDistance = Infinity;\n for (let j = 0; j < found; j++) {\n const d = distance(i, j);\n if (d < bestDistance) {\n bestDistance = d;\n best = j;\n }\n }\n if (assignment[i] !== best) {\n assignment[i] = best;\n moved = true;\n }\n }\n if (!moved) break;\n\n sums.fill(0);\n for (let i = 0; i < n; i++) {\n const j = assignment[i] * 4;\n const w = weights[i];\n sums[j] += points[i * 3] * w;\n sums[j + 1] += points[i * 3 + 1] * w;\n sums[j + 2] += points[i * 3 + 2] * w;\n sums[j + 3] += w;\n }\n for (let j = 0; j < found; j++) {\n const w = sums[j * 4 + 3];\n if (w <= 0) continue; // an empty cluster keeps its seed\n centroids[j * 3] = sums[j * 4] / w;\n centroids[j * 3 + 1] = sums[j * 4 + 1] / w;\n centroids[j * 3 + 2] = sums[j * 4 + 2] / w;\n }\n }\n\n return { assignment, centroids: centroids.slice(0, found * 3), k: found };\n}\n","import {\n clamp,\n formatOklch,\n hueDistance,\n labToLch,\n maxChroma,\n onColorFor,\n smoothstep,\n srgbToOklab,\n toneOf,\n} from \"./oklab\";\nimport { kmeans } from \"./quantize\";\nimport { AMBIENT_REGIONS, AMBIENT_TONES, DEFAULT_ANALYSIS } from \"./settings\";\nimport type {\n AmbientAnalysisOptions,\n AmbientPalette,\n AmbientPixels,\n AmbientRamp,\n AmbientRegion,\n AmbientRegionColor,\n AmbientRole,\n AmbientSwatch,\n OklchColor,\n} from \"./types\";\n\n/**\n * Bumped whenever the same pixels would give a different palette. Put it in\n * the key of any palette cache that outlives a deploy (`unstable_cache`, a\n * database), so stored palettes are computed again.\n */\nexport const AMBIENT_ANALYSIS_VERSION = 2;\n\n// Below this chroma a colour reads as grey; its hue is noise.\nconst MIN_CHROMA = 0.022;\n// Below this share of coloured pixels an image is treated as neutral.\nconst MIN_PRESENCE = 0.03;\n// A colour this small still counts as a role when it is vivid enough.\nconst MIN_POPULATION = 0.004;\n\nconst REGION_BITS: Record<AmbientRegion, number> = {\n top: 1,\n bottom: 2,\n left: 4,\n right: 8,\n center: 16,\n};\n\nexport interface Cluster extends OklchColor {\n /** Share of the (centre-weighted) image. */\n pop: number;\n /** Share of the chroma sRGB allows at this lightness and hue. */\n rel: number;\n /** How far the hue can be trusted at this lightness (0–1). */\n rely: number;\n}\n\ninterface Bounds {\n bottom: number;\n left: number;\n right: number;\n top: number;\n}\n\nconst lightnessAt = (data: ArrayLike<number>, index: number) =>\n srgbToOklab(data[index], data[index + 1], data[index + 2])[0];\n\n/**\n * Finds black bars along the edges (letterbox / pillarbox): rows or columns\n * that are uniformly near-black. At most 22% of each side is cut.\n */\nexport function findContentBounds({ data, height, width }: AmbientPixels): Bounds {\n const isBar = (count: number, at: (step: number) => number) => {\n let sum = 0;\n let max = 0;\n let seen = 0;\n for (let step = 0; step < count; step++) {\n const index = at(step);\n if (data[index + 3] < 128) continue;\n const l = lightnessAt(data, index);\n sum += l;\n if (l > max) max = l;\n seen++;\n }\n return seen > 0 && sum / seen < 0.12 && max < 0.2;\n };\n const row = (y: number) => isBar(width, (x) => (y * width + x) * 4);\n const maxRows = Math.floor(height * 0.22);\n const maxColumns = Math.floor(width * 0.22);\n\n let top = 0;\n while (top < maxRows && row(top)) top++;\n let bottom = height;\n while (height - bottom < maxRows && bottom - 1 > top && row(bottom - 1)) bottom--;\n\n const column = (x: number) =>\n isBar(bottom - top, (step) => ((top + step) * width + x) * 4);\n let left = 0;\n while (left < maxColumns && column(left)) left++;\n let right = width;\n while (width - right < maxColumns && right - 1 > left && column(right - 1)) right--;\n\n return { bottom, left, right, top };\n}\n\nconst reliability = (l: number) =>\n smoothstep(0.1, 0.28, l) * (1 - smoothstep(0.9, 0.98, l));\n\nconst colorfulness = (c: number) => smoothstep(MIN_CHROMA, 0.06, c);\n\nconst isChromatic = (cluster: Cluster) =>\n cluster.c >= MIN_CHROMA && cluster.rely > 0;\n\nfunction pickBest<T>(items: T[], score: (item: T) => number): T | null {\n let best: T | null = null;\n let bestScore = 0;\n for (const item of items) {\n const value = score(item);\n if (value > bestScore) {\n bestScore = value;\n best = item;\n }\n }\n return best;\n}\n\nconst round3 = (value: number) => Math.round(value * 1000) / 1000;\n\n/**\n * How much a colour looks like skin, hair, wood or a tungsten-lit wall: the\n * warm, low-chroma band most film frames are full of. It is what a frame\n * shows, rarely its mood.\n */\nexport function skinLikeness({ c, h, l }: OklchColor): number {\n return (\n (1 - smoothstep(12, 26, hueDistance(h, 54))) *\n smoothstep(0.02, 0.035, c) *\n (1 - smoothstep(0.11, 0.15, c)) *\n smoothstep(0.26, 0.38, l) *\n (1 - smoothstep(0.88, 0.95, l))\n );\n}\n\n// Reds and oranges read louder than blues or greens at the same chroma\n// (Helmholtz–Kohlrausch), so they are given less of it.\nconst warmth = (h: number) => 1 - smoothstep(22, 50, hueDistance(h, 42));\n\n// Weight of a colour in the role and region picks: skin still counts, less.\nconst salience = (color: OklchColor) => 1 - 0.65 * skinLikeness(color);\n\ninterface ChromaSpec {\n cap: number;\n gain: number;\n}\n\n/**\n * The chroma a role carries: its source's own, raised by `gain`, held back\n * for skin and warm hues, never above `cap`. Chroma, not a share of the\n * gamut: at mid lightness orange has twice the room teal has, so carrying\n * the share would turn a pale face into a loud orange.\n */\nconst roleChroma = (source: OklchColor, { cap, gain }: ChromaSpec) =>\n Math.min(\n cap * (1 - 0.3 * warmth(source.h)),\n // A faint tint is raised further, so it still reads as a colour.\n Math.max(source.c * gain, Math.min(0.05, source.c * 1.6)) *\n (1 - 0.3 * skinLikeness(source)),\n );\n\n/** `c` at hue `h` and lightness `l`, inside sRGB. */\nconst fitTone = (h: number, l: number, c: number): OklchColor => ({\n c: Math.max(0, Math.min(c, maxChroma(l, h) * 0.96)),\n h,\n l,\n});\n\nfunction buildSwatch(\n tone: OklchColor,\n population: number,\n fromImage: boolean,\n minContrast: number,\n): AmbientSwatch {\n // The ramp keeps the swatch's share of the gamut, so its dark tones stay\n // hued instead of collapsing to grey.\n const room = maxChroma(tone.l, tone.h) * 0.96;\n const rel = room > 0 ? tone.c / room : 0;\n const ramp = {} as AmbientRamp;\n for (const step of AMBIENT_TONES) {\n ramp[step] = formatOklch(toneOf(tone.h, step / 100, rel, Math.max(tone.c, 0.04)));\n }\n return {\n c: round3(tone.c),\n color: formatOklch(tone),\n fromImage,\n h: Math.round(tone.h * 10) / 10,\n l: round3(tone.l),\n on: formatOklch(onColorFor(tone, minContrast)),\n population: round3(population),\n ramp,\n };\n}\n\ninterface RoleSpec extends ChromaSpec {\n max: number;\n min: number;\n}\n\n/** A role's tone from its source cluster, or `fallback` when there is none. */\nfunction roleTone(\n source: Cluster | null,\n spec: RoleSpec,\n fallback: OklchColor,\n dilution = 1,\n): OklchColor {\n if (!source) return fitTone(fallback.h, clamp(fallback.l, spec.min, spec.max), fallback.c);\n return fitTone(\n source.h,\n clamp(source.l, spec.min, spec.max),\n roleChroma(source, spec) * dilution,\n );\n}\n\nexport interface AmbientClustering {\n clusters: Cluster[];\n /** Centre-weighted mean lightness. */\n meanL: number;\n /** Per region, the OKLab sum (`L, a, b` per cluster) of each cluster's pixels. */\n regionLab: Float64Array[];\n /** Per region, the pixel count of each cluster. */\n regionWeights: Float64Array[];\n}\n\n/**\n * Step one of the analysis: the image's colours as OKLab k-means clusters,\n * with each cluster's share of the frame and of each region.\n */\nexport function clusterAmbientPixels(\n pixels: AmbientPixels,\n options: AmbientAnalysisOptions,\n): AmbientClustering {\n const { data, width, height } = pixels;\n const bounds = options.letterbox\n ? findContentBounds(pixels)\n : { bottom: height, left: 0, right: width, top: 0 };\n const boxWidth = Math.max(1, bounds.right - bounds.left);\n const boxHeight = Math.max(1, bounds.bottom - bounds.top);\n\n // 1. Bin pixels by 15-bit RGB, averaging their OKLab values per bin.\n const binOf = new Int32Array(32768).fill(-1);\n const binSums: number[] = [];\n const pixelBins = new Int32Array(boxWidth * boxHeight).fill(-1);\n const pixelRegions = new Uint8Array(boxWidth * boxHeight);\n const sigma2 = 2 * 0.35 * 0.35;\n let total = 0;\n let sumL = 0;\n\n for (let y = bounds.top; y < bounds.bottom; y++) {\n const v = (y - bounds.top + 0.5) / boxHeight;\n for (let x = bounds.left; x < bounds.right; x++) {\n const index = (y * width + x) * 4;\n if (data[index + 3] < 128) continue;\n const r = data[index];\n const g = data[index + 1];\n const b = data[index + 2];\n const [l, a, bb] = srgbToOklab(r, g, b);\n const u = (x - bounds.left + 0.5) / boxWidth;\n const du = (u - 0.5) * 2;\n const dv = (v - 0.5) * 2;\n const weight =\n 1 -\n options.centerWeight +\n 2 * options.centerWeight * Math.exp(-(du * du + dv * dv) / sigma2);\n\n const key = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);\n let bin = binOf[key];\n if (bin < 0) {\n bin = binSums.length / 4;\n binOf[key] = bin;\n binSums.push(0, 0, 0, 0);\n }\n binSums[bin * 4] += l * weight;\n binSums[bin * 4 + 1] += a * weight;\n binSums[bin * 4 + 2] += bb * weight;\n binSums[bin * 4 + 3] += weight;\n total += weight;\n sumL += l * weight;\n\n const local = (y - bounds.top) * boxWidth + (x - bounds.left);\n pixelBins[local] = bin;\n pixelRegions[local] =\n (v < 1 / 3 ? REGION_BITS.top : 0) |\n (v > 2 / 3 ? REGION_BITS.bottom : 0) |\n (u < 1 / 3 ? REGION_BITS.left : 0) |\n (u > 2 / 3 ? REGION_BITS.right : 0) |\n (Math.abs(u - 0.5) < 0.25 && Math.abs(v - 0.5) < 0.25\n ? REGION_BITS.center\n : 0);\n }\n }\n\n const meanL = total > 0 ? sumL / total : 0.5;\n const bins = binSums.length / 4;\n\n // 2. Cluster coloured and grey bins apart, so the greys of a mostly dark\n // poster cannot use up every cluster and swallow its one red coat.\n const groups: [number[], number[]] = [[], []];\n for (let i = 0; i < bins; i++) {\n const w = binSums[i * 4 + 3];\n const a = binSums[i * 4 + 1] / w;\n const b = binSums[i * 4 + 2] / w;\n const coloured =\n Math.sqrt(a * a + b * b) >= MIN_CHROMA && binSums[i * 4] / w >= 0.06;\n groups[coloured ? 0 : 1].push(i);\n }\n const requested = clamp(Math.round(options.clusters), 2, 16);\n const greyClusters =\n groups[0].length === 0 ? requested : groups[1].length === 0 ? 0 : requested >= 8 ? 3 : 2;\n const budgets = [requested - greyClusters, greyClusters];\n\n const clusters: Cluster[] = [];\n const clusterOfBin = new Int32Array(bins).fill(-1);\n groups.forEach((members, group) => {\n if (members.length === 0 || budgets[group] <= 0) return;\n const points = new Float64Array(members.length * 3);\n const weights = new Float64Array(members.length);\n members.forEach((bin, i) => {\n const w = binSums[bin * 4 + 3];\n const a = binSums[bin * 4 + 1] / w;\n const b = binSums[bin * 4 + 2] / w;\n points[i * 3] = binSums[bin * 4] / w;\n points[i * 3 + 1] = a;\n points[i * 3 + 2] = b;\n // Vivid colours pull harder, so a small saturated area keeps its own cluster.\n weights[i] = w * (1 + 5 * Math.sqrt(a * a + b * b));\n });\n const { assignment, k } = kmeans(points, weights, budgets[group]);\n // A cluster's colour is the plain mean of its pixels: the vivid pull that\n // shaped the clusters would tint a face toward the red title beside it.\n const sums = new Float64Array(k * 4);\n members.forEach((bin, i) => {\n for (let channel = 0; channel < 4; channel++) {\n sums[assignment[i] * 4 + channel] += binSums[bin * 4 + channel];\n }\n });\n const index = new Int32Array(k).fill(-1);\n for (let j = 0; j < k; j++) {\n const pop = sums[j * 4 + 3];\n if (pop <= 0) continue;\n const lch = labToLch([sums[j * 4] / pop, sums[j * 4 + 1] / pop, sums[j * 4 + 2] / pop]);\n const room = maxChroma(lch.l, lch.h);\n index[j] = clusters.length;\n clusters.push({\n ...lch,\n pop: pop / total,\n rel: room > 0 ? clamp(lch.c / room, 0, 1) : 0,\n rely: reliability(lch.l),\n });\n }\n members.forEach((bin, i) => (clusterOfBin[bin] = index[assignment[i]]));\n });\n\n // 3. Region shares per cluster, and the OKLab sum of each cluster's pixels\n // in each region: a cluster spanning the frame looks different in parts.\n const regionWeights = AMBIENT_REGIONS.map(() => new Float64Array(clusters.length));\n const regionLab = AMBIENT_REGIONS.map(() => new Float64Array(clusters.length * 3));\n for (let i = 0; i < pixelBins.length; i++) {\n const bin = pixelBins[i];\n if (bin < 0) continue;\n const cluster = clusterOfBin[bin];\n const bits = pixelRegions[i];\n const w = binSums[bin * 4 + 3];\n AMBIENT_REGIONS.forEach((region, r) => {\n if (!(bits & REGION_BITS[region])) return;\n regionWeights[r][cluster] += 1;\n for (let channel = 0; channel < 3; channel++) {\n regionLab[r][cluster * 3 + channel] += binSums[bin * 4 + channel] / w;\n }\n });\n }\n\n return { clusters, meanL, regionLab, regionWeights };\n}\n\n/**\n * The palette of an image: OKLab k-means clusters scored by population ×\n * chroma (skin tones counted less), turned into four roles (each with a tonal\n * ramp and a contrast-safe text colour), five region colours, and the deep\n * `shadow` tone. Roles keep about their source's chroma rather than its share\n * of the gamut, so warm hues are not inflated.\n */\nexport function analyzeAmbientPixels(\n pixels: AmbientPixels,\n overrides: Partial<AmbientAnalysisOptions> = {},\n): AmbientPalette {\n const options = { ...DEFAULT_ANALYSIS, ...overrides };\n const { clusters, meanL, regionLab, regionWeights } = clusterAmbientPixels(pixels, options);\n\n // 4. Roles.\n const chromatic = clusters.filter(isChromatic);\n const presence = chromatic.reduce(\n (sum, cluster) => sum + cluster.pop * colorfulness(cluster.c) * cluster.rely,\n 0,\n );\n const neutral = presence < MIN_PRESENCE;\n // A coloured detail on an almost grey image is kept, but quieter.\n const dilution = 0.55 + 0.45 * Math.min(1, presence / 0.25);\n const { minContrast, minHueDistance } = options;\n const grey = { c: 0, h: 0, l: clamp(meanL, 0.3, 0.8) };\n\n // k-means splits one hue into several lightness levels; a hue's share is\n // that of its whole family (clusters within 20°), so it is not undercounted.\n const family = new Map<Cluster, number>();\n for (const cluster of chromatic) {\n let share = 0;\n for (const other of chromatic) {\n if (hueDistance(cluster.h, other.h) <= 20) share += other.pop;\n }\n family.set(cluster, share);\n }\n const share = (cluster: Cluster) => family.get(cluster) ?? cluster.pop;\n\n const dominantPick = neutral\n ? null\n : pickBest(\n chromatic,\n (cluster) => share(cluster) * cluster.c * cluster.rely * salience(cluster),\n );\n // A grey image keeps a grey `vibrant`: no hue is invented.\n const vividPick = neutral\n ? null\n : pickBest(\n chromatic.filter((cluster) => share(cluster) >= MIN_POPULATION),\n (cluster) =>\n cluster.c *\n cluster.c *\n Math.pow(share(cluster), 0.3) *\n cluster.rely *\n salience(cluster),\n );\n // …but a coloured detail on it (the red coat) becomes the accent.\n const accentPick = pickBest(\n chromatic.filter((cluster) =>\n neutral\n ? share(cluster) >= 0.006 && cluster.c >= 0.06\n : share(cluster) >= MIN_POPULATION &&\n cluster.c >= 0.035 &&\n (!dominantPick || hueDistance(cluster.h, dominantPick.h) >= minHueDistance),\n ),\n (cluster) =>\n Math.pow(share(cluster), 0.6) * cluster.c * cluster.rely * salience(cluster),\n );\n const mutedPick = neutral\n ? null\n : pickBest(\n chromatic.filter((cluster) => cluster.c <= 0.09),\n (cluster) => share(cluster) * cluster.rely * (1 - cluster.c / 0.12),\n );\n\n const dominantHue = dominantPick?.h ?? vividPick?.h ?? 0;\n const accentSource = accentPick ?? vividPick;\n const roles: Record<AmbientRole, AmbientSwatch> = {\n dominant: buildSwatch(\n roleTone(dominantPick, { cap: 0.2, gain: 1.15, max: 0.74, min: 0.42 }, grey),\n dominantPick ? share(dominantPick) : 0,\n true,\n minContrast,\n ),\n vibrant: buildSwatch(\n roleTone(\n vividPick,\n { cap: 0.22, gain: 1.35, max: 0.84, min: 0.62 },\n { c: 0, h: dominantHue, l: 0.78 },\n dilution,\n ),\n vividPick ? share(vividPick) : 0,\n true,\n minContrast,\n ),\n muted: buildSwatch(\n roleTone(\n mutedPick,\n { cap: 0.07, gain: 1, max: 0.66, min: 0.38 },\n { c: dominantPick ? 0.035 : 0, h: dominantHue, l: clamp(meanL, 0.38, 0.66) },\n ),\n mutedPick ? share(mutedPick) : 0,\n Boolean(mutedPick) || neutral,\n minContrast,\n ),\n accent: buildSwatch(\n roleTone(\n accentSource,\n { cap: 0.22, gain: 1.3, max: 0.8, min: 0.55 },\n { c: 0, h: dominantHue, l: 0.72 },\n dilution,\n ),\n accentSource ? share(accentSource) : 0,\n Boolean(accentPick),\n minContrast,\n ),\n };\n\n // 5. `shadow`: the shadows' own hue when they have one, else the dominant's.\n // In the dark, relative chroma says more than chroma: a navy at L 0.14\n // uses most of what sRGB has there.\n const shadowPick = neutral\n ? null\n : pickBest(\n clusters.filter(\n (cluster) => cluster.l <= 0.5 && cluster.c >= 0.02 && cluster.pop >= 0.02,\n ),\n (cluster) => cluster.pop * cluster.rel * smoothstep(0.05, 0.14, cluster.l),\n );\n const deepSource = shadowPick ?? dominantPick;\n const shadowL = clamp(\n options.shadowLightness + (meanL - 0.45) * 0.06,\n options.shadowLightness - 0.02,\n options.shadowLightness + 0.02,\n );\n const shadow = deepSource\n ? toneOf(deepSource.h, shadowL, clamp(0.3 + 0.7 * deepSource.rel, 0, 0.85), 0.1)\n : { c: 0, h: 0, l: shadowL };\n\n // 6. Regions: the most telling colour in each part of the frame, as that\n // part shows it (a cluster's own pixels there, not its frame-wide mean).\n const regions = {} as Record<AmbientRegion, AmbientRegionColor>;\n AMBIENT_REGIONS.forEach((region, r) => {\n const weights = regionWeights[r];\n const lab = regionLab[r];\n let regionTotal = 0;\n let regionL = 0;\n clusters.forEach((cluster, j) => {\n regionTotal += weights[j];\n regionL += cluster.l * weights[j];\n });\n let strength = 0;\n let pick: OklchColor | null = null;\n let pickScore = 0;\n clusters.forEach((_, j) => {\n const count = weights[j];\n if (count <= 0) return;\n const local = labToLch([lab[j * 3] / count, lab[j * 3 + 1] / count, lab[j * 3 + 2] / count]);\n const rely = reliability(local.l);\n if (local.c < MIN_CHROMA || rely <= 0) return;\n const part = count / regionTotal;\n strength += part * colorfulness(local.c) * rely;\n const score = part * local.c * rely * salience(local);\n if (score > pickScore) {\n pickScore = score;\n pick = local;\n }\n });\n const chosen = neutral || strength < MIN_PRESENCE ? null : (pick as OklchColor | null);\n const tone = chosen\n ? fitTone(\n chosen.h,\n clamp(chosen.l, 0.42, 0.72),\n roleChroma(chosen, { cap: 0.18, gain: 1.15 }),\n )\n : {\n c: 0,\n h: 0,\n l: clamp(regionTotal > 0 ? regionL / regionTotal : meanL, 0.3, 0.7),\n };\n regions[region] = {\n c: round3(tone.c),\n color: formatOklch(tone),\n h: Math.round(tone.h * 10) / 10,\n l: round3(tone.l),\n strength: round3(chosen ? clamp(strength, 0, 1) : 0),\n };\n });\n\n return {\n neutral,\n regions,\n roles,\n shadow: formatOklch(shadow),\n };\n}\n\n/** Width and height that fit `width × height` inside `size` on the long side. */\nexport function fitSample(width: number, height: number, size: number) {\n const scale = Math.min(1, size / Math.max(width, height, 1));\n return {\n height: Math.max(1, Math.round(height * scale)),\n width: Math.max(1, Math.round(width * scale)),\n };\n}\n"]}
|