@ecomconsult/consentkit 0.5.9 → 0.5.11
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 +32 -14
- package/npm/internal-stub.mjs +1 -1
- package/package.json +1 -1
- package/src/ck-core.js +1 -1
- package/src/ck-debug.js +30 -1
- package/src/ck-ui.js +217 -44
package/README.md
CHANGED
|
@@ -184,9 +184,10 @@ Pass any subset to `init()`. Nested objects merge with the defaults.
|
|
|
184
184
|
| `theme.accent` | `string` | `"#2B50D8"` | Exposed as `--ck-accent` |
|
|
185
185
|
| `theme.font` | `"inherit" \| "system"` | `"inherit"` | v0.5.0. `inherit` takes the host page's font family; `system` restores the pre-0.5.0 system stack. Font *sizes* are fixed either way |
|
|
186
186
|
| `theme.radius` | `{ card, button }` | `{ card: 16, button: 8 }` | v0.5.0. px, clamped 0–32. A bare string or number is the pre-0.5.0 form and still sets the card radius |
|
|
187
|
-
| `theme.buttons` | `{ accept, reject, settings }` | see below | v0.5.0. Per-button appearance.
|
|
187
|
+
| `theme.buttons` | `{ accept, reject, settings }` | see below | v0.5.0. Per-button appearance. A colour you set is painted as set; contrast rules correct only derived colours (v0.5.10) — see [Button appearance](#button-appearance) |
|
|
188
188
|
| `theme.mode` | `"auto" \| "light" \| "dark"` | `"auto"` | `auto` follows `prefers-color-scheme` |
|
|
189
189
|
| `theme.dark` | `{ bg, ink, accent, onAccent }` | built-in | Overrides the dark palette |
|
|
190
|
+
| `theme.light` | `{ onAccent }` | built-in | v0.5.10. The light mirror of `theme.dark`. An `onAccent` set here is the filled buttons' text colour for light mode, painted as given |
|
|
190
191
|
| `texts.policyUrl` | `string` | — | v0.5.0. Cookie policy address. `http(s)` only; anything else is ignored |
|
|
191
192
|
| `texts.detailsAction` | `"policy" \| "settings" \| "hide" \| "declaration"` | see notes | v0.5.0, `declaration` in v0.5.7. What «Learn more» does. Defaults to `policy` when `policyUrl` is set, `settings` when it is not. `policy` or `declaration` without a usable URL falls back to `settings` rather than rendering a dead link |
|
|
192
193
|
| `texts.declarationUrl` | `string` | — | v0.5.7. Address of the cookie declaration page, used by `detailsAction: "declaration"`. `http(s)` only. Filled by the hosted service; the client only reads it |
|
|
@@ -274,23 +275,36 @@ accept is a dark pattern, and consent collected through one is not freely
|
|
|
274
275
|
given, so the config simply cannot express it. `settings` is independent and
|
|
275
276
|
may itself be filled.
|
|
276
277
|
|
|
277
|
-
**
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
278
|
+
**A colour you set is painted as you set it; contrast rules decide only the
|
|
279
|
+
colours you left to us.** Since v0.5.10 the **4.5:1** text rule and the **3:1**
|
|
280
|
+
border rule apply to *derived* values — the automatic text on a filled button,
|
|
281
|
+
the border and text an `outline` button takes from `theme.accent`, the link
|
|
282
|
+
colour read off the accent. A `fg`, `border` or `onAccent` you wrote yourself
|
|
283
|
+
is never repainted, however low it measures: the debug panel reports the ratio
|
|
284
|
+
and warns («контраст 4.32 — ниже рекомендуемых 4.5»), and the choice stays
|
|
285
|
+
yours. Concretely:
|
|
286
|
+
|
|
287
|
+
- a `fg` you set is painted as set and only measured against the fill behind
|
|
288
|
+
it; the *derived* text on a filled button still becomes white or `#161616`,
|
|
289
|
+
whichever contrasts more, when it would fall under 4.5:1;
|
|
290
|
+
- a `border` you set on an `outline` button is painted as set; a border
|
|
291
|
+
*derived* from `theme.accent` is darkened (light card) or lightened (dark
|
|
292
|
+
card) in small steps until it clears 3:1 against the card, so a default theme
|
|
293
|
+
can never produce a button invisible against its own card;
|
|
294
|
+
- an outline button's text, when you did not set one, is that resolved border
|
|
295
|
+
colour put through the same 4.5:1 rule — derived even when the border it came
|
|
296
|
+
from was yours.
|
|
289
297
|
|
|
290
298
|
The card is `#ffffff` in light mode and `#1c1c1e` in dark. A colour the
|
|
291
299
|
arithmetic cannot read — a CSS colour name, an `rgb()` string — is left exactly
|
|
292
300
|
as you wrote it rather than being silently replaced.
|
|
293
301
|
|
|
302
|
+
**The preferences panel follows the banner, with no settings of its own**
|
|
303
|
+
(v0.5.11): «Сохранить выбор» is styled as `accept`, the panel's own accept and
|
|
304
|
+
reject as `settings`, and the floating button takes the `accept` button's fill
|
|
305
|
+
(its border colour when `accept` is `outline`), while the category and service
|
|
306
|
+
switches keep `theme.accent`.
|
|
307
|
+
|
|
294
308
|
The same arithmetic is exposed as pure functions on `ConsentKit._contrast`
|
|
295
309
|
(`relativeLuminance`, `contrastRatio`, `ensureContrast`, `stepToContrast`,
|
|
296
310
|
`resolveButtonStyles`, `resolveRadius`, `resolveFont`, `resolveDetails`,
|
|
@@ -298,7 +312,11 @@ The same arithmetic is exposed as pure functions on `ConsentKit._contrast`
|
|
|
298
312
|
instead of reimplementing them. It is present whenever `src/ck-ui.js` is loaded,
|
|
299
313
|
and it is safe to call in Node — nothing in it touches the DOM. The debug
|
|
300
314
|
panel's **Appearance** section reads it directly and reports each button's
|
|
301
|
-
resolved colours, its contrast ratio, and
|
|
315
|
+
resolved colours, its contrast ratio, and either that a derived value was
|
|
316
|
+
adjusted or that a value you set measures below the recommended floor. Each
|
|
317
|
+
resolved record carries `ratio` and `adjusted`, plus `low` (painted text under
|
|
318
|
+
4.5:1) and, for outline buttons, `borderRatio`, `borderAdjusted` and
|
|
319
|
+
`borderLow` (border under 3:1).
|
|
302
320
|
|
|
303
321
|
### The «Learn more» link
|
|
304
322
|
|
package/npm/internal-stub.mjs
CHANGED
|
@@ -28,7 +28,7 @@ export function undecidedState() {
|
|
|
28
28
|
*/
|
|
29
29
|
export function createStub() {
|
|
30
30
|
const stub = {
|
|
31
|
-
version: '0.5.
|
|
31
|
+
version: '0.5.11',
|
|
32
32
|
config: {},
|
|
33
33
|
init: function () { return undecidedState(); },
|
|
34
34
|
allowed: function (cat) { return cat === 'necessary'; },
|
package/package.json
CHANGED
package/src/ck-core.js
CHANGED
package/src/ck-debug.js
CHANGED
|
@@ -322,6 +322,14 @@
|
|
|
322
322
|
btnAdjusted: 'исправлено автоматически',
|
|
323
323
|
btnOk: 'AA',
|
|
324
324
|
btnFail: 'ниже AA',
|
|
325
|
+
// 0.5.10: a colour the owner set is painted as set, so a low ratio is a
|
|
326
|
+
// WARNING, not a correction. Split around the measured number because it
|
|
327
|
+
// is the whole point of the note — «ниже рекомендуемых» with no reading
|
|
328
|
+
// tells the owner nothing about how far below they are.
|
|
329
|
+
lowTextA: 'контраст ',
|
|
330
|
+
lowTextB: ' — ниже рекомендуемых 4.5, текст может читаться хуже',
|
|
331
|
+
lowBorderA: 'обводка ',
|
|
332
|
+
lowBorderB: ' — ниже 3, кнопка плохо видна',
|
|
325
333
|
secActions: 'Действия',
|
|
326
334
|
reset: 'Сбросить согласие',
|
|
327
335
|
showPrefs: 'Показать настройки',
|
|
@@ -388,6 +396,10 @@
|
|
|
388
396
|
btnAdjusted: 'adjusted automatically',
|
|
389
397
|
btnOk: 'AA',
|
|
390
398
|
btnFail: 'below AA',
|
|
399
|
+
lowTextA: 'contrast ',
|
|
400
|
+
lowTextB: ' — below the recommended 4.5, the text may be harder to read',
|
|
401
|
+
lowBorderA: 'border ',
|
|
402
|
+
lowBorderB: ' — below 3, the button is hard to see',
|
|
391
403
|
secActions: 'Actions',
|
|
392
404
|
reset: 'Reset consent',
|
|
393
405
|
showPrefs: 'Show preferences',
|
|
@@ -459,6 +471,10 @@
|
|
|
459
471
|
btnAdjusted: 'corectat automat',
|
|
460
472
|
btnOk: 'AA',
|
|
461
473
|
btnFail: 'sub AA',
|
|
474
|
+
lowTextA: 'contrast ',
|
|
475
|
+
lowTextB: ' — sub 4.5 recomandat, textul poate fi mai greu de citit',
|
|
476
|
+
lowBorderA: 'contur ',
|
|
477
|
+
lowBorderB: ' — sub 3, butonul se vede greu',
|
|
462
478
|
secActions: 'Acțiuni',
|
|
463
479
|
reset: 'Resetează consimțământul',
|
|
464
480
|
showPrefs: 'Arată setările',
|
|
@@ -1035,7 +1051,8 @@
|
|
|
1035
1051
|
lkTxt = lk.color + ' ' + T.btnOn + ' ' + lk.against +
|
|
1036
1052
|
' · ' + fmtRatio(lk.ratio) +
|
|
1037
1053
|
' ' + ((typeof lk.ratio === 'number' && lk.ratio >= 4.5) ? T.btnOk : T.btnFail) +
|
|
1038
|
-
(lk.adjusted ? ' · ' + T.btnAdjusted : '')
|
|
1054
|
+
(lk.adjusted ? ' · ' + T.btnAdjusted : '') +
|
|
1055
|
+
(lk.low ? ' · ' + T.lowTextA + fmtRatio(lk.ratio) + T.lowTextB : '');
|
|
1039
1056
|
}
|
|
1040
1057
|
|
|
1041
1058
|
sT.appendChild(defs([
|
|
@@ -1062,9 +1079,21 @@
|
|
|
1062
1079
|
(b.variant === 'outline'
|
|
1063
1080
|
? ' · ' + T.btnBorder + ' ' + b.border + ' (' + fmtRatio(b.borderRatio) + ')'
|
|
1064
1081
|
: '')));
|
|
1082
|
+
// «исправлено» only where something WAS in fact replaced. Since
|
|
1083
|
+
// 0.5.10 a colour the owner set is painted as set, and its shortfall
|
|
1084
|
+
// is reported as a plain warning with the measured number instead —
|
|
1085
|
+
// the panel must never claim to have corrected what it left alone.
|
|
1065
1086
|
if (b.adjusted) {
|
|
1066
1087
|
li.appendChild(el('span', { class: 'mut' }, ' · ' + T.btnAdjusted));
|
|
1067
1088
|
}
|
|
1089
|
+
if (b.low) {
|
|
1090
|
+
li.appendChild(el('span', { class: 'mut' },
|
|
1091
|
+
' · ' + T.lowTextA + fmtRatio(b.ratio) + T.lowTextB));
|
|
1092
|
+
}
|
|
1093
|
+
if (b.borderLow) {
|
|
1094
|
+
li.appendChild(el('span', { class: 'mut' },
|
|
1095
|
+
' · ' + T.lowBorderA + fmtRatio(b.borderRatio) + T.lowBorderB));
|
|
1096
|
+
}
|
|
1068
1097
|
uT.appendChild(li);
|
|
1069
1098
|
});
|
|
1070
1099
|
sT.appendChild(uT);
|
package/src/ck-ui.js
CHANGED
|
@@ -420,15 +420,11 @@
|
|
|
420
420
|
'border-color:var(--ck-reject-bd);border-width:var(--ck-reject-bw)}',
|
|
421
421
|
'.ck-btn--settings{background:var(--ck-settings-bg);color:var(--ck-settings-fg);',
|
|
422
422
|
'border-color:var(--ck-settings-bd);border-width:var(--ck-settings-bw)}',
|
|
423
|
-
/*
|
|
423
|
+
/* Unused by the UI since 0.5.11: the preferences panel's footer moved to
|
|
424
|
+
the accept/settings role classes above, so it follows the banner. Kept
|
|
425
|
+
as a compatibility shim for integrator CSS and older inline blocks that
|
|
426
|
+
still name these classes — nothing in this file emits them any more. */
|
|
424
427
|
'.ck-btn--filled{background:var(--ck-accent);border-color:var(--ck-accent);color:var(--ck-on-accent)}',
|
|
425
|
-
/* Live, not a fallback: these paint the preferences panel's own Accept
|
|
426
|
-
all / Reject all. Transparent fill means the LABEL sits on the card, so
|
|
427
|
-
it takes --ck-link like every other accent-coloured text; the BORDER is
|
|
428
|
-
non-text and answers to 3:1, so it keeps the raw accent. The footer's
|
|
429
|
-
background is --ck-soft rather than --ck-bg, but soft is a 5% ink mix of
|
|
430
|
-
the card — the ratio difference is well inside the noise, and a second
|
|
431
|
-
link token per background would break «один код — одни числа». */
|
|
432
428
|
'.ck-btn--outline{background:transparent;border-color:var(--ck-accent);color:var(--ck-link)}',
|
|
433
429
|
'.ck-btn--ghost{min-width:0;border-color:var(--ck-line);color:var(--ck-ink);font-weight:500}',
|
|
434
430
|
|
|
@@ -516,8 +512,12 @@
|
|
|
516
512
|
'.ck-empty{margin:8px 0 0;font-size:13px;color:var(--ck-muted)}',
|
|
517
513
|
|
|
518
514
|
/* ---- floating button ---- */
|
|
515
|
+
/* 0.5.11 — the floating button wears the ACCEPT button's colours, so the
|
|
516
|
+
one control that outlives the banner still reads as the owner's brand.
|
|
517
|
+
Both tokens are resolved once in resolveButtonStyles (`fab`) and only
|
|
518
|
+
read here — «один код — одни числа». */
|
|
519
519
|
'.ck-fab{position:fixed;left:16px;bottom:16px;z-index:2147482999;width:48px;height:48px;',
|
|
520
|
-
'border-radius:50%;border:1px solid var(--ck-line);background:var(--ck-bg);color:var(--ck-
|
|
520
|
+
'border-radius:50%;border:1px solid var(--ck-line);background:var(--ck-fab-bg);color:var(--ck-fab-fg);',
|
|
521
521
|
'display:inline-flex;align-items:center;justify-content:center;padding:0}',
|
|
522
522
|
'.ck-fab svg{width:24px;height:24px;display:block}',
|
|
523
523
|
|
|
@@ -842,10 +842,14 @@
|
|
|
842
842
|
var WHITE = '#ffffff';
|
|
843
843
|
var NEAR_BLACK = '#161616'; // SPEC §1: white or #161616, whichever contrasts more
|
|
844
844
|
|
|
845
|
-
/* SPEC §1, the TEXT rule: keep
|
|
846
|
-
|
|
845
|
+
/* SPEC §1, the TEXT rule: keep `fg` when it clears `min` against bg;
|
|
846
|
+
otherwise swap to white or #161616 — whichever wins. Unreadable input
|
|
847
847
|
(a colour name, rgb(), a missing value) is returned untouched with
|
|
848
|
-
adjusted:false
|
|
848
|
+
adjusted:false rather than guessed at.
|
|
849
|
+
|
|
850
|
+
Since 0.5.10 this is only ever handed a DERIVED colour — resolveButtonStyles
|
|
851
|
+
keeps an explicitly set one out of here entirely — so the swap can no longer
|
|
852
|
+
overwrite something the owner chose. */
|
|
849
853
|
function ensureContrast(fg, bg, min) {
|
|
850
854
|
var floor = typeof min === 'number' && min > 0 ? min : 4.5;
|
|
851
855
|
var have = contrastRatio(fg, bg);
|
|
@@ -861,7 +865,10 @@
|
|
|
861
865
|
against the CARD background, so the button is visible as a button at all.
|
|
862
866
|
Stepwise rather than a jump to black/white: a brand colour that is only
|
|
863
867
|
slightly too pale should stay recognisably the brand colour. Direction is
|
|
864
|
-
chosen by which way there is room to move — away from the card.
|
|
868
|
+
chosen by which way there is room to move — away from the card.
|
|
869
|
+
|
|
870
|
+
Since 0.5.10 only a DERIVED border reaches this: a border the owner set is
|
|
871
|
+
painted as set and merely measured. */
|
|
865
872
|
function stepToContrast(color, bg, min) {
|
|
866
873
|
var floor = typeof min === 'number' && min > 0 ? min : 3;
|
|
867
874
|
var have = contrastRatio(color, bg);
|
|
@@ -891,7 +898,7 @@
|
|
|
891
898
|
|
|
892
899
|
/* Config values are interpolated into the TEXT of a generated stylesheet, so
|
|
893
900
|
an unvalidated value can close the declaration and open rules of its own
|
|
894
|
-
("10px;}.ck-btn--
|
|
901
|
+
("10px;}.ck-btn--reject{display:none" hides "Reject all"). config.theme is
|
|
895
902
|
not trusted input: in standalone mode it comes straight from the embedding
|
|
896
903
|
page or an integrator's admin panel, with no server-side validation
|
|
897
904
|
anywhere in the path. So every value is matched against a strict grammar
|
|
@@ -1221,7 +1228,14 @@
|
|
|
1221
1228
|
числа": nothing recomputes these numbers a second time.
|
|
1222
1229
|
|
|
1223
1230
|
`palette` is optional and lets buildThemeCss pass the ALREADY-RESOLVED
|
|
1224
|
-
accent/card colours for the mode, so a theme.dark.accent is honoured.
|
|
1231
|
+
accent/card colours for the mode, so a theme.dark.accent is honoured.
|
|
1232
|
+
|
|
1233
|
+
OWNER'S RULE (0.5.10): a colour the owner EXPLICITLY SET is painted as set.
|
|
1234
|
+
The >= 4.5 text rule and the >= 3 border rule may only decide colours the
|
|
1235
|
+
owner did NOT choose — the automatic text on a filled button, the border
|
|
1236
|
+
and text derived from the accent on an outline one. A typed colour that
|
|
1237
|
+
falls short is reported (`low` / `borderLow`) so the debug panel and the
|
|
1238
|
+
cabinet can WARN about it, never corrected behind the owner's back. */
|
|
1225
1239
|
function resolveButtonStyles(theme, mode, palette) {
|
|
1226
1240
|
var t = (theme && typeof theme === 'object') ? theme : {};
|
|
1227
1241
|
var base = mode === 'dark' ? DARK : LIGHT;
|
|
@@ -1229,9 +1243,12 @@
|
|
|
1229
1243
|
|
|
1230
1244
|
var cardBg = sanitizeCssValue('color', pal.bg, base.bg);
|
|
1231
1245
|
var accent = sanitizeCssValue('color', pal.accent, base.accent);
|
|
1232
|
-
// theme.dark.onAccent
|
|
1233
|
-
// buttons in that mode.
|
|
1246
|
+
// theme.dark.onAccent / theme.light.onAccent is the GIVEN fg for filled
|
|
1247
|
+
// buttons in that mode. When the owner set it, it counts as an explicit
|
|
1248
|
+
// colour and is painted as set; the built-in default is derived and stays
|
|
1249
|
+
// subject to the >= 4.5 rule.
|
|
1234
1250
|
var onAccent = sanitizeCssValue('color', pal.onAccent, base.onAccent);
|
|
1251
|
+
var onAccentExplicit = pal.onAccentExplicit === true;
|
|
1235
1252
|
|
|
1236
1253
|
var cfg = (t.buttons && typeof t.buttons === 'object') ? t.buttons : {};
|
|
1237
1254
|
|
|
@@ -1254,11 +1271,17 @@
|
|
|
1254
1271
|
};
|
|
1255
1272
|
|
|
1256
1273
|
/* The accent as TEXT on the card. Same >= 4.5 rule, same function, one
|
|
1257
|
-
number: links,
|
|
1258
|
-
|
|
1259
|
-
|
|
1274
|
+
number: links, «Подробнее» and the cookie-table summary all read the
|
|
1275
|
+
token this produces, so none of them can drift from what the debug
|
|
1276
|
+
panel and the cabinet quote. (The floating button left this token in
|
|
1277
|
+
0.5.11 — it now follows the accept button; see `fab` below.) Note the
|
|
1260
1278
|
measurement is against cardBg — an accent that is fine inside a filled
|
|
1261
|
-
button can still be unreadable on the card behind it.
|
|
1279
|
+
button can still be unreadable on the card behind it.
|
|
1280
|
+
|
|
1281
|
+
Still corrected in 0.5.10, deliberately: the ACCENT is the owner's, but
|
|
1282
|
+
the LINK colour is derived from it — nobody typed "links are this
|
|
1283
|
+
colour". The accent itself is never repainted, so the owner still sees
|
|
1284
|
+
the brand colour everywhere they actually chose it. */
|
|
1262
1285
|
var linkRes = ensureContrast(accent, cardBg, 4.5);
|
|
1263
1286
|
|
|
1264
1287
|
var out = {
|
|
@@ -1269,11 +1292,35 @@
|
|
|
1269
1292
|
color: linkRes.color,
|
|
1270
1293
|
ratio: linkRes.ratio,
|
|
1271
1294
|
adjusted: linkRes.adjusted,
|
|
1295
|
+
// A link is always derived, so this is normally false — the rule
|
|
1296
|
+
// already lifted it. It can still be true on a mid-tone custom card
|
|
1297
|
+
// where even the better of white and #161616 falls short of 4.5.
|
|
1298
|
+
low: (typeof linkRes.ratio === 'number' && linkRes.ratio < 4.5),
|
|
1272
1299
|
against: cardBg
|
|
1273
1300
|
},
|
|
1274
1301
|
buttons: {}
|
|
1275
1302
|
};
|
|
1276
1303
|
|
|
1304
|
+
/* "Did the owner explicitly set this colour?" — the gate on the whole
|
|
1305
|
+
0.5.10 rule, and it cannot be a plain `str(c.fg)` test. sanitizeCssValue
|
|
1306
|
+
silently returns the FALLBACK for a hostile or malformed value, so a
|
|
1307
|
+
value that failed the grammar would otherwise be painted as "the owner's
|
|
1308
|
+
choice" with no correction at all — the injected-colour case would lose
|
|
1309
|
+
its contrast check as well as its value. Sanitising against a sentinel
|
|
1310
|
+
tells the two apart: a value that survives is the owner's, anything else
|
|
1311
|
+
falls through to the derived path exactly as before 0.5.10. */
|
|
1312
|
+
var NOT_SET = '\x00';
|
|
1313
|
+
function explicitColor(v) {
|
|
1314
|
+
var got = sanitizeCssValue('color', v, NOT_SET);
|
|
1315
|
+
return got === NOT_SET ? null : got;
|
|
1316
|
+
}
|
|
1317
|
+
// A measured ratio is `null` for a colour the arithmetic cannot read (a CSS
|
|
1318
|
+
// name, an rgb() string). That is "no verdict", not "below the floor", so it
|
|
1319
|
+
// must not raise the warning flag — the panel would print a note with no number.
|
|
1320
|
+
function below(ratio, floor) {
|
|
1321
|
+
return typeof ratio === 'number' && ratio < floor;
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1277
1324
|
for (var i = 0; i < BTN_ROLES.length; i++) {
|
|
1278
1325
|
var role = BTN_ROLES[i];
|
|
1279
1326
|
var c = (cfg[role] && typeof cfg[role] === 'object') ? cfg[role] : {};
|
|
@@ -1283,45 +1330,131 @@
|
|
|
1283
1330
|
var rec;
|
|
1284
1331
|
|
|
1285
1332
|
if (variant === 'filled') {
|
|
1286
|
-
// bg: author's, else the accent
|
|
1287
|
-
// default accent fill, then checked against the resolved bg.
|
|
1333
|
+
// bg: author's, else the accent — always painted as given either way.
|
|
1288
1334
|
var bg = sanitizeCssValue('color', c.bg, accent);
|
|
1289
|
-
var wantFg = sanitizeCssValue('color', c.fg, onAccent);
|
|
1290
|
-
var fgRes = ensureContrast(wantFg, bg, 4.5);
|
|
1291
1335
|
var bd = sanitizeCssValue('color', c.border, bg);
|
|
1336
|
+
// fg: an EXPLICIT colour (the button's own, or an owner-set onAccent
|
|
1337
|
+
// for the mode) is painted as set and only measured. Only the derived
|
|
1338
|
+
// default goes through the >= 4.5 rule.
|
|
1339
|
+
var setFg = explicitColor(c.fg) || (onAccentExplicit ? onAccent : null);
|
|
1340
|
+
var fgColor, fgRatio, fgAdjusted;
|
|
1341
|
+
if (setFg) {
|
|
1342
|
+
fgColor = setFg;
|
|
1343
|
+
fgRatio = contrastRatio(setFg, bg);
|
|
1344
|
+
fgAdjusted = false;
|
|
1345
|
+
} else {
|
|
1346
|
+
var fgRes = ensureContrast(onAccent, bg, 4.5);
|
|
1347
|
+
fgColor = fgRes.color;
|
|
1348
|
+
fgRatio = fgRes.ratio;
|
|
1349
|
+
fgAdjusted = fgRes.adjusted;
|
|
1350
|
+
}
|
|
1292
1351
|
rec = {
|
|
1293
1352
|
variant: 'filled',
|
|
1294
1353
|
bg: bg,
|
|
1295
|
-
fg:
|
|
1354
|
+
fg: fgColor,
|
|
1296
1355
|
border: bd,
|
|
1297
1356
|
borderWidth: bw,
|
|
1298
|
-
ratio:
|
|
1299
|
-
adjusted:
|
|
1357
|
+
ratio: fgRatio,
|
|
1358
|
+
adjusted: fgAdjusted,
|
|
1359
|
+
// Warn-only: true when the PAINTED text falls under 4.5:1 —
|
|
1360
|
+
// usually a typed colour (the owner's own trade-off), but also a
|
|
1361
|
+
// CORRECTED one on a mid-tone fill near #767676, where neither
|
|
1362
|
+
// white nor #161616 reaches 4.5 and the better of the two still fails.
|
|
1363
|
+
low: below(fgRatio, 4.5),
|
|
1300
1364
|
against: bg
|
|
1301
1365
|
};
|
|
1302
1366
|
} else {
|
|
1303
1367
|
// outline: transparent fill, so everything is measured against the CARD.
|
|
1304
|
-
// border
|
|
1305
|
-
// the >=
|
|
1306
|
-
|
|
1307
|
-
var
|
|
1308
|
-
var
|
|
1309
|
-
|
|
1368
|
+
// A border the owner TYPED is painted as typed and only measured; one
|
|
1369
|
+
// DERIVED from the accent is still stepped to >= 3:1 so a default-themed
|
|
1370
|
+
// button cannot vanish into the card.
|
|
1371
|
+
var setBd = explicitColor(c.border);
|
|
1372
|
+
var bdColor, bdRatio, bdAdjusted;
|
|
1373
|
+
if (setBd) {
|
|
1374
|
+
bdColor = setBd;
|
|
1375
|
+
bdRatio = contrastRatio(setBd, cardBg);
|
|
1376
|
+
bdAdjusted = false;
|
|
1377
|
+
} else {
|
|
1378
|
+
var bdRes = stepToContrast(accent, cardBg, 3);
|
|
1379
|
+
bdColor = bdRes.color;
|
|
1380
|
+
bdRatio = bdRes.ratio;
|
|
1381
|
+
bdAdjusted = bdRes.adjusted;
|
|
1382
|
+
}
|
|
1383
|
+
// Text: the owner's when set, otherwise the resolved border colour put
|
|
1384
|
+
// through the >= 4.5 rule — that text is derived even when the border
|
|
1385
|
+
// it came from was typed, so it is still corrected.
|
|
1386
|
+
var setTx = explicitColor(c.fg);
|
|
1387
|
+
var txColor, txRatio, txAdjusted;
|
|
1388
|
+
if (setTx) {
|
|
1389
|
+
txColor = setTx;
|
|
1390
|
+
txRatio = contrastRatio(setTx, cardBg);
|
|
1391
|
+
txAdjusted = false;
|
|
1392
|
+
} else {
|
|
1393
|
+
var txRes = ensureContrast(bdColor, cardBg, 4.5);
|
|
1394
|
+
txColor = txRes.color;
|
|
1395
|
+
txRatio = txRes.ratio;
|
|
1396
|
+
txAdjusted = txRes.adjusted;
|
|
1397
|
+
}
|
|
1310
1398
|
rec = {
|
|
1311
1399
|
variant: 'outline',
|
|
1312
1400
|
bg: sanitizeCssValue('color', c.bg, 'transparent'),
|
|
1313
|
-
fg:
|
|
1314
|
-
border:
|
|
1401
|
+
fg: txColor,
|
|
1402
|
+
border: bdColor,
|
|
1315
1403
|
borderWidth: bw,
|
|
1316
|
-
ratio:
|
|
1317
|
-
adjusted
|
|
1318
|
-
|
|
1319
|
-
borderAdjusted
|
|
1404
|
+
ratio: txRatio,
|
|
1405
|
+
// `adjusted` now tracks the TEXT alone. A typed border that was kept
|
|
1406
|
+
// must not make the row say «исправлено» about a colour nobody
|
|
1407
|
+
// touched; the border reports itself through borderAdjusted.
|
|
1408
|
+
adjusted: txAdjusted,
|
|
1409
|
+
low: below(txRatio, 4.5),
|
|
1410
|
+
borderRatio: bdRatio,
|
|
1411
|
+
borderAdjusted: bdAdjusted,
|
|
1412
|
+
borderLow: below(bdRatio, 3),
|
|
1320
1413
|
against: cardBg
|
|
1321
1414
|
};
|
|
1322
1415
|
}
|
|
1323
1416
|
out.buttons[role] = rec;
|
|
1324
1417
|
}
|
|
1418
|
+
|
|
1419
|
+
/* The floating button (0.5.11). It is a filled circle that outlives the
|
|
1420
|
+
banner, and the owner's rule is that it wears the ACCEPT button's
|
|
1421
|
+
colours — no setting of its own.
|
|
1422
|
+
|
|
1423
|
+
accept FILLED: take its bg/fg verbatim. That inherits the 0.5.10 rule
|
|
1424
|
+
for free — a typed low-contrast fg stays exactly as typed here too, and
|
|
1425
|
+
is reported through `low` rather than corrected.
|
|
1426
|
+
|
|
1427
|
+
accept OUTLINE: there is no fill to borrow, so the button's BORDER
|
|
1428
|
+
colour becomes the circle and the CARD colour becomes the icon — the
|
|
1429
|
+
outline button's two real colours, swapped. Both are derived for the
|
|
1430
|
+
fab (nobody typed "the floating button is this colour"), so the icon
|
|
1431
|
+
goes through the >= 4.5 rule; ensureContrast picks the readable member
|
|
1432
|
+
of the pair, which on a dark border is the card itself and on a pale
|
|
1433
|
+
one steps away from it. When accept's border is itself derived it is
|
|
1434
|
+
already the accent stepped to 3:1, so this is also the accent/on-accent
|
|
1435
|
+
fallback the brief describes. */
|
|
1436
|
+
var acc = out.buttons.accept;
|
|
1437
|
+
if (acc.variant === 'filled') {
|
|
1438
|
+
out.fab = {
|
|
1439
|
+
bg: acc.bg,
|
|
1440
|
+
fg: acc.fg,
|
|
1441
|
+
ratio: acc.ratio,
|
|
1442
|
+
adjusted: acc.adjusted,
|
|
1443
|
+
low: acc.low,
|
|
1444
|
+
against: acc.bg
|
|
1445
|
+
};
|
|
1446
|
+
} else {
|
|
1447
|
+
var fabBg = acc.border;
|
|
1448
|
+
var fabRes = ensureContrast(cardBg, fabBg, 4.5);
|
|
1449
|
+
out.fab = {
|
|
1450
|
+
bg: fabBg,
|
|
1451
|
+
fg: fabRes.color,
|
|
1452
|
+
ratio: fabRes.ratio,
|
|
1453
|
+
adjusted: fabRes.adjusted,
|
|
1454
|
+
low: below(fabRes.ratio, 4.5),
|
|
1455
|
+
against: fabBg
|
|
1456
|
+
};
|
|
1457
|
+
}
|
|
1325
1458
|
return out;
|
|
1326
1459
|
}
|
|
1327
1460
|
|
|
@@ -1346,6 +1479,12 @@
|
|
|
1346
1479
|
// same way as __buttons: one pass per mode, so the light and dark blocks
|
|
1347
1480
|
// each carry their own contrast-checked link colour.
|
|
1348
1481
|
if (p.__link) d.push('--ck-link:' + p.__link.color);
|
|
1482
|
+
// The floating button's pair, resolved from the accept button in the same
|
|
1483
|
+
// pass, so light and dark each carry their own (0.5.11).
|
|
1484
|
+
if (p.__fab) {
|
|
1485
|
+
d.push('--ck-fab-bg:' + p.__fab.bg);
|
|
1486
|
+
d.push('--ck-fab-fg:' + p.__fab.fg);
|
|
1487
|
+
}
|
|
1349
1488
|
var btns = p.__buttons;
|
|
1350
1489
|
if (btns) {
|
|
1351
1490
|
for (var i = 0; i < BTN_ROLES.length; i++) {
|
|
@@ -1381,6 +1520,11 @@
|
|
|
1381
1520
|
function buildThemeCss(cfg) {
|
|
1382
1521
|
var theme = (cfg && cfg.theme) || {};
|
|
1383
1522
|
var dk = (theme.dark && typeof theme.dark === 'object') ? theme.dark : {};
|
|
1523
|
+
// theme.light is the mirror of theme.dark and exists for one value: an
|
|
1524
|
+
// onAccent the owner set for the light mode. Without it a light-mode
|
|
1525
|
+
// filled button had no way to state its text colour once for all three
|
|
1526
|
+
// buttons, and theme.dark could do what theme.light could not.
|
|
1527
|
+
var lt = (theme.light && typeof theme.light === 'object') ? theme.light : {};
|
|
1384
1528
|
|
|
1385
1529
|
var radius = resolveRadius(theme);
|
|
1386
1530
|
var font = resolveFont(theme);
|
|
@@ -1390,6 +1534,11 @@
|
|
|
1390
1534
|
sanitizeCssValue('color', theme.bg, LIGHT.bg),
|
|
1391
1535
|
sanitizeCssValue('color', theme.ink, LIGHT.ink));
|
|
1392
1536
|
if (str(theme.accent)) light.accent = sanitizeCssValue('color', theme.accent, LIGHT.accent);
|
|
1537
|
+
// An onAccent that SURVIVES the grammar is the owner's word on the filled
|
|
1538
|
+
// buttons' text and is painted as given; one that fails it falls back to
|
|
1539
|
+
// the built-in default, which is derived and still gets corrected.
|
|
1540
|
+
var ltOn = sanitizeCssValue('color', lt.onAccent, null);
|
|
1541
|
+
if (ltOn) { light.onAccent = ltOn; light.onAccentExplicit = true; }
|
|
1393
1542
|
|
|
1394
1543
|
// Dark: theme.dark overrides on top of the built-in dark palette.
|
|
1395
1544
|
// A light-only theme.accent deliberately does NOT carry into dark — the
|
|
@@ -1398,7 +1547,8 @@
|
|
|
1398
1547
|
sanitizeCssValue('color', dk.bg, DARK.bg),
|
|
1399
1548
|
sanitizeCssValue('color', dk.ink, DARK.ink));
|
|
1400
1549
|
if (str(dk.accent)) dark.accent = sanitizeCssValue('color', dk.accent, DARK.accent);
|
|
1401
|
-
|
|
1550
|
+
var dkOn = sanitizeCssValue('color', dk.onAccent, null);
|
|
1551
|
+
if (dkOn) { dark.onAccent = dkOn; dark.onAccentExplicit = true; }
|
|
1402
1552
|
|
|
1403
1553
|
// Buttons are resolved per mode against that mode's real card colour, so a
|
|
1404
1554
|
// custom dark card changes the outline border the same way a custom light
|
|
@@ -1407,8 +1557,21 @@
|
|
|
1407
1557
|
var darkBtn = resolveButtonStyles(theme, 'dark', dark);
|
|
1408
1558
|
light.__buttons = lightBtn.buttons;
|
|
1409
1559
|
dark.__buttons = darkBtn.buttons;
|
|
1560
|
+
|
|
1561
|
+
// `--ck-on-accent` paints the text of the remaining filled surfaces that
|
|
1562
|
+
// are not banner buttons — since 0.5.11 that is the blocked-embed
|
|
1563
|
+
// placeholder's button, the panel foot and the floating button having
|
|
1564
|
+
// moved onto the accept button's own tokens. A derived onAccent still has
|
|
1565
|
+
// to pass the >= 4.5 rule against the accent, or a white accent gets white
|
|
1566
|
+
// text (the owner saw exactly that). Done AFTER the buttons are resolved, so
|
|
1567
|
+
// the accept button still records `adjusted:true` for the same correction.
|
|
1568
|
+
// An onAccent the owner set is painted as set — the 0.5.10 rule.
|
|
1569
|
+
if (!light.onAccentExplicit) light.onAccent = ensureContrast(light.onAccent, light.accent, 4.5).color;
|
|
1570
|
+
if (!dark.onAccentExplicit) dark.onAccent = ensureContrast(dark.onAccent, dark.accent, 4.5).color;
|
|
1410
1571
|
light.__link = lightBtn.link;
|
|
1411
1572
|
dark.__link = darkBtn.link;
|
|
1573
|
+
light.__fab = lightBtn.fab;
|
|
1574
|
+
dark.__fab = darkBtn.fab;
|
|
1412
1575
|
|
|
1413
1576
|
var mode = theme.mode;
|
|
1414
1577
|
if (mode !== 'light' && mode !== 'dark') mode = 'auto';
|
|
@@ -1884,11 +2047,21 @@
|
|
|
1884
2047
|
p.appendChild(body);
|
|
1885
2048
|
|
|
1886
2049
|
var foot = el('div', 'ck-panel__foot');
|
|
1887
|
-
|
|
2050
|
+
/* 0.5.11 — the panel follows the BANNER's buttons, with no setting of its
|
|
2051
|
+
own: «Сохранить выбор» is the same role as «Принять всё» and wears the
|
|
2052
|
+
accept class, «Принять всё»/«Отклонить всё» here are secondary and wear
|
|
2053
|
+
the settings («Настроить») class. Reusing the role classes means the
|
|
2054
|
+
filled/outline split stays a VALUE change in the tokens — the panel
|
|
2055
|
+
never picks a class from the resolved variant, so a theme.buttons edit
|
|
2056
|
+
is still applyTheme()-only and signature() still need not see buttons.
|
|
2057
|
+
Panel layout is untouched: `.ck-panel__foot .ck-btn{flex:1 1 150px}`
|
|
2058
|
+
(0,2,0) outranks `.ck-btn{flex:1 1 auto}` and the role classes set no
|
|
2059
|
+
flex of their own. */
|
|
2060
|
+
var save = el('button', 'ck-btn ck-btn--accept', T.save);
|
|
1888
2061
|
save.type = 'button';
|
|
1889
|
-
var acc = el('button', 'ck-btn ck-btn--
|
|
2062
|
+
var acc = el('button', 'ck-btn ck-btn--settings', T.acceptAll);
|
|
1890
2063
|
acc.type = 'button';
|
|
1891
|
-
var rej = el('button', 'ck-btn ck-btn--
|
|
2064
|
+
var rej = el('button', 'ck-btn ck-btn--settings', T.rejectAll);
|
|
1892
2065
|
rej.type = 'button';
|
|
1893
2066
|
|
|
1894
2067
|
save.addEventListener('click', function () { doSave(); });
|