@0001-labs/design-system-1 0.3.0 → 0.3.2
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/DS1/0-face/constraint-panel.ts +27 -6
- package/DS1/0-face/constraint-site.ts +3 -2
- package/DS1/0-face/constraints.ts +27 -0
- package/DS1/0-face/define.ts +1 -1
- package/DS1/0-face/fault-lines.ts +159 -0
- package/DS1/0-face/generated/toast-assets.ts +1 -1
- package/DS1/1-root/card.css +2 -2
- package/DS1/1-root/cjk.css +1 -1
- package/DS1/1-root/component-tokens.css +12 -0
- package/DS1/1-root/context.css +1 -1
- package/DS1/1-root/controls.css +8 -8
- package/DS1/1-root/document.css +2 -2
- package/DS1/1-root/empty.css +2 -2
- package/DS1/1-root/figures.css +2 -2
- package/DS1/1-root/fonts/Inter-LICENSE.md +91 -2
- package/DS1/1-root/fonts.css +5 -4
- package/DS1/1-root/footer.css +2 -2
- package/DS1/1-root/header.css +5 -4
- package/DS1/1-root/inter-arrows.css +11 -0
- package/DS1/1-root/notice.css +2 -2
- package/DS1/1-root/one.css +5 -4
- package/DS1/1-root/progress.css +3 -3
- package/DS1/1-root/prose.css +5 -5
- package/DS1/1-root/row.css +1 -1
- package/DS1/1-root/table.css +1 -1
- package/DS1/1-root/text.css +5 -5
- package/DS1/2-core/chart/chart.css +1 -1
- package/DS1/2-core/ds-avatar.ts +47 -8
- package/DS1/2-core/styles/ds-activity.css +1 -1
- package/DS1/2-core/styles/ds-avatar.css +1 -1
- package/DS1/2-core/styles/ds-badge.css +1 -1
- package/DS1/2-core/styles/ds-button-host.css +3 -2
- package/DS1/2-core/styles/ds-button-split.css +1 -1
- package/DS1/2-core/styles/ds-button.css +5 -4
- package/DS1/2-core/styles/ds-composer.css +1 -1
- package/DS1/2-core/styles/ds-image.css +1 -1
- package/DS1/2-core/styles/ds-input.css +3 -3
- package/DS1/2-core/styles/ds-number.css +1 -1
- package/DS1/2-core/styles/ds-radio.css +1 -1
- package/DS1/2-core/styles/ds-tag.css +3 -2
- package/DS1/2-core/styles/ds-text.css +5 -5
- package/DS1/2-core/styles/ds-toast.css +1 -1
- package/DS1/2-core/styles/ds-token.css +1 -1
- package/DS1/2-core/styles/ds-tooltip.css +1 -1
- package/DS1/3-unit/context-trigger.ts +29 -2
- package/DS1/3-unit/ds-form.ts +2 -1
- package/DS1/3-unit/ds-table.ts +2 -1
- package/DS1/3-unit/styles/ds-calendar.css +4 -4
- package/DS1/3-unit/styles/ds-list.css +1 -1
- package/DS1/3-unit/styles/ds-matrix.css +2 -2
- package/DS1/3-unit/styles/ds-menu.css +1 -1
- package/DS1/3-unit/styles/ds-select.css +1 -1
- package/DS1/3-unit/styles/ds-sidebar.css +1 -1
- package/DS1/3-unit/styles/ds-table-of-contents.css +1 -1
- package/DS1/3-unit/styles/ds-token-field.css +1 -1
- package/DS1/4-page/ds-container.ts +2 -1
- package/DS1/4-page/styles/ds-overlay.css +1 -1
- package/DS1/4-page/styles/ds-page.css +1 -1
- package/DS1/4-page/styles/ds-panel.css +1 -1
- package/dist/0-face/constraint-panel.d.ts.map +1 -1
- package/dist/0-face/constraint-panel.js +28 -6
- package/dist/0-face/constraint-site.d.ts +1 -0
- package/dist/0-face/constraint-site.d.ts.map +1 -1
- package/dist/0-face/constraint-site.js +3 -2
- package/dist/0-face/constraints.d.ts.map +1 -1
- package/dist/0-face/constraints.js +27 -0
- package/dist/0-face/define.js +1 -1
- package/dist/0-face/fault-lines.d.ts +20 -0
- package/dist/0-face/fault-lines.d.ts.map +1 -0
- package/dist/0-face/fault-lines.js +172 -0
- package/dist/0-face/generated/toast-assets.d.ts.map +1 -1
- package/dist/0-face/generated/toast-assets.js +1 -1
- package/dist/2-core/ds-avatar.d.ts +5 -0
- package/dist/2-core/ds-avatar.d.ts.map +1 -1
- package/dist/2-core/ds-avatar.js +53 -9
- package/dist/3-unit/context-trigger.d.ts.map +1 -1
- package/dist/3-unit/context-trigger.js +32 -2
- package/dist/3-unit/ds-form.d.ts.map +1 -1
- package/dist/3-unit/ds-form.js +2 -1
- package/dist/3-unit/ds-table.d.ts.map +1 -1
- package/dist/3-unit/ds-table.js +2 -1
- package/dist/4-page/ds-container.d.ts.map +1 -1
- package/dist/4-page/ds-container.js +2 -1
- package/dist/design-system-1.bundle.js +406 -66
- package/dist/design-system-1.bundle.js.map +1 -1
- package/dist/design-system-1.bundle.min.js +3388 -3136
- package/dist/design-system-1.bundle.min.js.map +1 -1
- package/dist/design-system-1.css +1 -1
- package/dist/feedback.js +1 -1
- package/dist/feedback.js.map +1 -1
- package/package.json +6 -4
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
align-self: center;
|
|
78
78
|
overflow: hidden;
|
|
79
79
|
padding-inline: calc(4px * var(--ds-sf));
|
|
80
|
-
font: 400 var(--ds-type-size-default) / var(--ds-type-lineheight-default) var(--ds-typeface-regular);
|
|
80
|
+
font: 400 var(--ds-type-size-default) / var(--ds-type-lineheight-default) "Inter Arrows", var(--ds-typeface-regular);
|
|
81
81
|
letter-spacing: var(--ds-type-letterspacing-default);
|
|
82
82
|
white-space: nowrap;
|
|
83
83
|
text-align: center;
|
|
@@ -29,8 +29,9 @@
|
|
|
29
29
|
padding-inline: var(--_tag-padding, calc(4px * var(--ds-sf, 1)));
|
|
30
30
|
border-radius: var(--_tag-radius, var(--ds-radius));
|
|
31
31
|
background: var(--ds-tag-background, light-dark(color-mix(in srgb, var(--ds-tag-accent, var(--ds-grey, #7a7a7a)) 28%, white), color-mix(in srgb, var(--ds-tag-accent, var(--ds-grey, #7a7a7a)) 20%, var(--ds-black, #2a2a2a))));
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
/* Tint the dark-mode ink: raw grey/accent colours cannot meet 4.5:1 on this fill. */
|
|
33
|
+
color: var(--ds-tag-color, light-dark(color-mix(in srgb, var(--ds-tag-accent, var(--ds-grey, #7a7a7a)) 45%, black), color-mix(in srgb, var(--ds-tag-accent, var(--ds-grey, #7a7a7a)) 30%, white)));
|
|
34
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular);
|
|
34
35
|
font-feature-settings: var(--ds-font-features);
|
|
35
36
|
font-size: var(--_tag-font-size, var(--ds-type-size-default));
|
|
36
37
|
line-height: var(--_tag-height, var(--ds-control-height));
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
align-items: center;
|
|
11
11
|
justify-content: flex-start;
|
|
12
12
|
height: var(--ds-control-height);
|
|
13
|
-
font-family: var(--ds-typeface-regular);
|
|
13
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular);
|
|
14
14
|
font-size: var(--ds-type-size-default);
|
|
15
15
|
font-weight: var(--ds-type-weight-default);
|
|
16
16
|
line-height: var(--ds-type-lineheight-default);
|
|
@@ -26,17 +26,17 @@
|
|
|
26
26
|
:host([hidden]) { display: none !important; }
|
|
27
27
|
|
|
28
28
|
:host([data-language="ja"]) {
|
|
29
|
-
font-family: var(--ds-typeface-regular-jp, var(--typeface-regular-jp));
|
|
29
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular-jp, var(--typeface-regular-jp));
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
:host([data-language="zh"]),
|
|
33
33
|
:host([data-language="zh-hant"]) {
|
|
34
|
-
font-family: var(--ds-typeface-regular-zh-hant, var(--typeface-regular-zh-hant));
|
|
34
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular-zh-hant, var(--typeface-regular-zh-hant));
|
|
35
35
|
font-weight: var(--ds-type-weight-default, 400);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
:host([data-language="zh-hans"]) {
|
|
39
|
-
font-family: var(--ds-typeface-regular-zh-hans, var(--typeface-regular-zh-hans));
|
|
39
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular-zh-hans, var(--typeface-regular-zh-hans));
|
|
40
40
|
font-weight: var(--ds-type-weight-default, 400);
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
min-width: 0;
|
|
55
55
|
max-width: 100%;
|
|
56
56
|
overflow: var(--ds-text-overflow, hidden);
|
|
57
|
-
font-family: var(--ds-typeface-regular);
|
|
57
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular);
|
|
58
58
|
font-feature-settings: var(--ds-font-features);
|
|
59
59
|
font-size: var(--ds-type-size-default);
|
|
60
60
|
font-weight: var(--ds-type-weight-default);
|
|
@@ -59,7 +59,7 @@ ol[data-x="center"] { left: 50%; transform: translateX(-50%); }
|
|
|
59
59
|
border-radius: var(--ds-radius);
|
|
60
60
|
background: var(--ds-toast-background);
|
|
61
61
|
color: var(--ds-toast-color);
|
|
62
|
-
font-family: var(--ds-typeface-regular);
|
|
62
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular);
|
|
63
63
|
font-feature-settings: var(--ds-font-features);
|
|
64
64
|
font-size: var(--ds-type-size-default);
|
|
65
65
|
line-height: var(--ds-control-height);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
@import "../../1-root/component-metrics.css";
|
|
2
2
|
:host { display: inline-flex; max-width: 100%; min-width: 0; vertical-align: middle; }
|
|
3
3
|
:host([hidden]) { display: none !important; }
|
|
4
|
-
.frame { display: flex; align-items: center; box-sizing: border-box; max-width: 100%; min-width: 0; height: var(--ds-row-height); padding-inline-start: calc(4px * var(--ds-sf)); background: var(--ds-fill); color: var(--ds-text-color); border-radius: var(--ds-radius); font-family: var(--ds-typeface-regular); font-size: var(--ds-type-size-default); line-height: var(--ds-type-lineheight-default); letter-spacing: var(--ds-type-letterspacing-default); }
|
|
4
|
+
.frame { display: flex; align-items: center; box-sizing: border-box; max-width: 100%; min-width: 0; height: var(--ds-row-height); padding-inline-start: calc(4px * var(--ds-sf)); background: var(--ds-fill); color: var(--ds-text-color); border-radius: var(--ds-radius); font-family: "Inter Arrows", var(--ds-typeface-regular); font-size: var(--ds-type-size-default); line-height: var(--ds-type-lineheight-default); letter-spacing: var(--ds-type-letterspacing-default); }
|
|
5
5
|
.copy { display: flex; align-items: baseline; gap: calc(4px * var(--ds-sf)); min-width: 0; padding-inline: calc(4px * var(--ds-sf)); }
|
|
6
6
|
.copy > span, small { overflow: hidden; text-overflow: clip; white-space: nowrap; min-width: 0; }
|
|
7
7
|
/* Cut words fade over their last square, never an ellipsis (0-face/cut-fade.ts marks them). */
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
border-radius: calc(4px * var(--ds-sf, var(--sf, 1)));
|
|
27
27
|
background: var(--ds-tooltip-background, light-dark(var(--ds-black, var(--black)), var(--ds-white, var(--white))));
|
|
28
28
|
color: var(--ds-tooltip-color, light-dark(var(--ds-white, var(--white)), var(--ds-black, var(--black))));
|
|
29
|
-
font-family: var(--ds-typeface-regular, var(--typeface-regular));
|
|
29
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular, var(--typeface-regular));
|
|
30
30
|
font-size: calc(14px * var(--ds-sf, var(--sf, 1)));
|
|
31
31
|
line-height: calc(16px * var(--ds-sf, var(--sf, 1)));
|
|
32
32
|
font-weight: 400;
|
|
@@ -29,6 +29,7 @@ export function bindContextMenuTrigger(
|
|
|
29
29
|
let suppressed: HTMLElement | null = null;
|
|
30
30
|
let release: ReturnType<typeof setTimeout> | undefined;
|
|
31
31
|
let disposed = false;
|
|
32
|
+
let mousePress: { event: PointerEvent; path: EventTarget[]; target: EventTarget | null } | undefined;
|
|
32
33
|
if (aria) trigger.setAttribute("aria-haspopup", "menu");
|
|
33
34
|
if (selection) trigger.classList.add("ds-context-trigger");
|
|
34
35
|
const enabled = (control: HTMLElement) => control.isConnected &&
|
|
@@ -48,6 +49,7 @@ export function bindContextMenuTrigger(
|
|
|
48
49
|
release = setTimeout(clearSuppression, 1000);
|
|
49
50
|
};
|
|
50
51
|
const cancel = () => {
|
|
52
|
+
mousePress = undefined;
|
|
51
53
|
clearTimeout(timer); timer = undefined; point = undefined;
|
|
52
54
|
doc.removeEventListener("pointermove", move);
|
|
53
55
|
doc.removeEventListener("pointerup", cancel);
|
|
@@ -56,10 +58,28 @@ export function bindContextMenuTrigger(
|
|
|
56
58
|
};
|
|
57
59
|
const context = (event: MouseEvent) => {
|
|
58
60
|
if (event.defaultPrevented) return;
|
|
59
|
-
|
|
61
|
+
// Settling a transform on pointerdown can move another row beneath the
|
|
62
|
+
// pointer before Chromium hit-tests contextmenu. Keep the initiating row.
|
|
63
|
+
const pressed = mousePress;
|
|
64
|
+
mousePress = undefined;
|
|
65
|
+
const followsPress = pressed && event.button === 2 && Math.hypot(event.clientX - pressed.event.clientX, event.clientY - pressed.event.clientY) <= 10;
|
|
66
|
+
// Native events lose their composed path after dispatch. Delegated and
|
|
67
|
+
// shadow-root controls still need the original path and unretargeted target.
|
|
68
|
+
const gesture = followsPress ? new Proxy(pressed.event, {
|
|
69
|
+
get(target, key) {
|
|
70
|
+
if (key === "composedPath") return () => pressed.path;
|
|
71
|
+
if (key === "target") return pressed.target;
|
|
72
|
+
const value = Reflect.get(target, key, target);
|
|
73
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
74
|
+
},
|
|
75
|
+
}) : event;
|
|
76
|
+
// Adopted controls retain their creating realm’s prototype; ownerDocument
|
|
77
|
+
// alone cannot choose an instanceof constructor. Containment stays authoritative.
|
|
78
|
+
if (gesture !== event && (typeof (gesture.target as Node | null)?.nodeType !== "number" || !trigger.contains(gesture.target as Node))) return;
|
|
79
|
+
const control = resolve(gesture); if (!control || !enabled(control)) return;
|
|
60
80
|
cancel();
|
|
61
81
|
if (suppressed === control) { event.preventDefault(); return; }
|
|
62
|
-
if (open({ x: event.clientX, y: event.clientY }, control,
|
|
82
|
+
if (open({ x: event.clientX, y: event.clientY }, control, gesture) === false) return;
|
|
63
83
|
event.preventDefault();
|
|
64
84
|
if (selection && event.button === 0) arm(control);
|
|
65
85
|
};
|
|
@@ -88,6 +108,11 @@ export function bindContextMenuTrigger(
|
|
|
88
108
|
if (open(at, control, event) !== false) arm(control);
|
|
89
109
|
}, LONG_PRESS);
|
|
90
110
|
};
|
|
111
|
+
const rememberMouse = (event: PointerEvent) => {
|
|
112
|
+
mousePress = !event.defaultPrevented && event.pointerType === "mouse" && event.button === 2 ? { event, path: event.composedPath(), target: event.target } : undefined;
|
|
113
|
+
};
|
|
114
|
+
trigger.addEventListener("pointerdown", rememberMouse, true);
|
|
115
|
+
trigger.addEventListener("pointercancel", cancel, true);
|
|
91
116
|
trigger.addEventListener("contextmenu", context);
|
|
92
117
|
trigger.addEventListener("keydown", key);
|
|
93
118
|
trigger.addEventListener("pointerdown", press);
|
|
@@ -98,6 +123,8 @@ export function bindContextMenuTrigger(
|
|
|
98
123
|
trigger.removeEventListener("contextmenu", context);
|
|
99
124
|
trigger.removeEventListener("keydown", key);
|
|
100
125
|
trigger.removeEventListener("pointerdown", press);
|
|
126
|
+
trigger.removeEventListener("pointerdown", rememberMouse, true);
|
|
127
|
+
trigger.removeEventListener("pointercancel", cancel, true);
|
|
101
128
|
if (aria) {
|
|
102
129
|
if (previousAria === null) trigger.removeAttribute("aria-haspopup"); else trigger.setAttribute("aria-haspopup", previousAria);
|
|
103
130
|
}
|
package/DS1/3-unit/ds-form.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { define } from "../0-face/define";
|
|
1
2
|
// ds-form.ts
|
|
2
3
|
// Form component for handling form submissions and validation
|
|
3
4
|
|
|
@@ -338,7 +339,7 @@ export class Form extends LitElement {
|
|
|
338
339
|
}
|
|
339
340
|
}
|
|
340
341
|
|
|
341
|
-
|
|
342
|
+
define("ds-form", Form);
|
|
342
343
|
|
|
343
344
|
declare global {
|
|
344
345
|
interface HTMLElementTagNameMap {
|
package/DS1/3-unit/ds-table.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { define } from "../0-face/define";
|
|
1
2
|
// ds-table.ts
|
|
2
3
|
// A data table: rows one square high on hairlines, drawn from data with the
|
|
3
4
|
// same rules as a native `<table class="ds-table">` (1-root/table.css). With
|
|
@@ -498,7 +499,7 @@ function text(value: unknown): string {
|
|
|
498
499
|
return typeof value === "number" ? value.toLocaleString() : String(value);
|
|
499
500
|
}
|
|
500
501
|
|
|
501
|
-
|
|
502
|
+
define("ds-table", DsTable);
|
|
502
503
|
|
|
503
504
|
declare global {
|
|
504
505
|
interface HTMLElementTagNameMap {
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
display: inline-block;
|
|
50
50
|
vertical-align: top;
|
|
51
51
|
color: var(--ds-text-color);
|
|
52
|
-
font-family: var(--ds-typeface-regular);
|
|
52
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular);
|
|
53
53
|
font-feature-settings: var(--ds-font-features);
|
|
54
54
|
font-size: var(--ds-type-size-default);
|
|
55
55
|
font-weight: var(--ds-type-weight-default);
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
flex: 1 1 auto;
|
|
81
81
|
min-width: 0;
|
|
82
82
|
overflow: hidden;
|
|
83
|
-
font-family: var(--ds-typeface-medium, var(--ds-typeface-regular));
|
|
83
|
+
font-family: "Inter Arrows", var(--ds-typeface-medium, var(--ds-typeface-regular));
|
|
84
84
|
text-overflow: clip;
|
|
85
85
|
white-space: nowrap;
|
|
86
86
|
}
|
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
background: transparent;
|
|
145
145
|
color: var(--ds-text-color);
|
|
146
146
|
font: inherit;
|
|
147
|
-
font-family: var(--ds-typeface-medium, var(--ds-typeface-regular));
|
|
147
|
+
font-family: "Inter Arrows", var(--ds-typeface-medium, var(--ds-typeface-regular));
|
|
148
148
|
line-height: var(--ds-control-height);
|
|
149
149
|
letter-spacing: inherit;
|
|
150
150
|
cursor: pointer;
|
|
@@ -321,7 +321,7 @@
|
|
|
321
321
|
white-space: nowrap;
|
|
322
322
|
}
|
|
323
323
|
.weekday-name[data-today] { color: var(--ds-calendar-today); }
|
|
324
|
-
.week-number { font-family: var(--ds-typeface-compressed); }
|
|
324
|
+
.week-number { font-family: "Inter Arrows", var(--ds-typeface-compressed); }
|
|
325
325
|
.day.outside .date-line { justify-content: flex-start; }
|
|
326
326
|
|
|
327
327
|
/* A compact day: the date centred in its square, in the ink; with events,
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
padding-top: calc(4px * var(--ds-sf));
|
|
39
39
|
overflow: hidden;
|
|
40
40
|
color: var(--ds-list-heading-color, var(--ds-text-color-muted));
|
|
41
|
-
font-family: var(--ds-typeface-regular);
|
|
41
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular);
|
|
42
42
|
font-feature-settings: var(--ds-font-features);
|
|
43
43
|
font-size: var(--ds-type-size-default);
|
|
44
44
|
font-weight: var(--ds-type-weight-default);
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
display: block;
|
|
15
15
|
min-width: 0;
|
|
16
16
|
color: var(--ds-text-color);
|
|
17
|
-
font-family: var(--ds-typeface-regular);
|
|
17
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular);
|
|
18
18
|
font-feature-settings: var(--ds-font-features);
|
|
19
19
|
font-size: var(--ds-type-size-default);
|
|
20
20
|
font-weight: var(--ds-type-weight-default);
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
border-inline-end: 1px solid var(--ds-paper);
|
|
51
51
|
background: var(--ds-matrix-colour);
|
|
52
52
|
color: var(--ds-slate);
|
|
53
|
-
font-family: var(--ds-typeface-medium, var(--ds-typeface-regular));
|
|
53
|
+
font-family: "Inter Arrows", var(--ds-typeface-medium, var(--ds-typeface-regular));
|
|
54
54
|
}
|
|
55
55
|
.group > span {
|
|
56
56
|
position: absolute;
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
background: var(--ds-paper);
|
|
32
32
|
color: var(--ds-text-color);
|
|
33
33
|
box-shadow: none;
|
|
34
|
-
font-family: var(--ds-typeface-regular);
|
|
34
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular);
|
|
35
35
|
font-feature-settings: var(--ds-font-features);
|
|
36
36
|
font-size: var(--ds-type-size-default);
|
|
37
37
|
line-height: var(--ds-type-lineheight-default);
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
corner-shape: var(--ds-corner-shape, round) !important;
|
|
41
41
|
background: var(--ds-input-background) !important;
|
|
42
42
|
color: var(--ds-input-color) !important;
|
|
43
|
-
font-family: var(--ds-typeface-regular) !important;
|
|
43
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular) !important;
|
|
44
44
|
font-size: var(--ds-type-size-default) !important;
|
|
45
45
|
font-weight: var(--ds-type-weight-default) !important;
|
|
46
46
|
letter-spacing: var(--ds-type-letterspacing-default) !important;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
min-width: 0;
|
|
9
9
|
min-height: 0;
|
|
10
10
|
color: var(--ds-text-color);
|
|
11
|
-
font-family: var(--ds-typeface-regular);
|
|
11
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular);
|
|
12
12
|
font-feature-settings: var(--ds-font-features);
|
|
13
13
|
font-size: var(--ds-type-size-default);
|
|
14
14
|
font-weight: var(--ds-type-weight-default);
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
width: var(--ds-toc-width, calc(12 * var(--ds-unit)));
|
|
5
5
|
max-width: 100%;
|
|
6
6
|
color: var(--ds-text-color);
|
|
7
|
-
font-family: var(--ds-typeface-regular);
|
|
7
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular);
|
|
8
8
|
font-size: var(--ds-type-size-default);
|
|
9
9
|
font-weight: var(--ds-type-weight-default);
|
|
10
10
|
line-height: var(--ds-type-lineheight-default);
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
.frame:focus-within { outline: 1px solid var(--ds-focus-ring); outline-offset: -1px; }
|
|
6
6
|
slot { display: contents; }
|
|
7
7
|
.entry { display: flex; align-items: center; flex: 1 1 calc(8 * var(--ds-unit)); min-width: min(100%, calc(4 * var(--ds-unit))); max-width: 100%; height: var(--ds-row-height); }
|
|
8
|
-
::slotted(input) { box-sizing: border-box !important; flex: 1 1 0 !important; width: 0 !important; min-width: 0 !important; max-width: 100% !important; height: var(--ds-row-height) !important; margin: 0 !important; padding: 0 calc(4px * var(--ds-sf)) !important; border: 0 !important; border-radius: 0 !important; background: transparent !important; color: var(--ds-text-color) !important; font-family: var(--ds-typeface-regular) !important; font-size: var(--ds-type-size-default) !important; line-height: var(--ds-type-lineheight-default) !important; letter-spacing: var(--ds-type-letterspacing-default) !important; outline: none !important; box-shadow: none !important; }
|
|
8
|
+
::slotted(input) { box-sizing: border-box !important; flex: 1 1 0 !important; width: 0 !important; min-width: 0 !important; max-width: 100% !important; height: var(--ds-row-height) !important; margin: 0 !important; padding: 0 calc(4px * var(--ds-sf)) !important; border: 0 !important; border-radius: 0 !important; background: transparent !important; color: var(--ds-text-color) !important; font-family: "Inter Arrows", var(--ds-typeface-regular) !important; font-size: var(--ds-type-size-default) !important; line-height: var(--ds-type-lineheight-default) !important; letter-spacing: var(--ds-type-letterspacing-default) !important; outline: none !important; box-shadow: none !important; }
|
|
9
9
|
::slotted(input:disabled) { opacity: .5; }
|
|
10
10
|
::slotted(ds-token) { max-width: 100%; }
|
|
11
11
|
ds-button { flex: 0 0 auto; --ds-button-width: var(--ds-row-height); --ds-button-height: var(--ds-row-height); }
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { define } from "../0-face/define";
|
|
1
2
|
// ds-container.ts
|
|
2
3
|
// Container component with responsive width constraints
|
|
3
4
|
|
|
@@ -19,7 +20,7 @@ export class Container extends LitElement {
|
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
define("ds-container", Container);
|
|
23
24
|
|
|
24
25
|
declare global {
|
|
25
26
|
interface HTMLElementTagNameMap {
|
|
@@ -17,7 +17,7 @@ ds-overlay > dialog {
|
|
|
17
17
|
box-shadow: none;
|
|
18
18
|
overflow: var(--ds-overlay-overflow, auto);
|
|
19
19
|
overscroll-behavior: contain;
|
|
20
|
-
font-family: var(--ds-typeface-regular);
|
|
20
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular);
|
|
21
21
|
font-feature-settings: var(--ds-font-features);
|
|
22
22
|
font-size: var(--ds-type-size-default);
|
|
23
23
|
font-weight: var(--ds-type-weight-default);
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
container-type: inline-size;
|
|
23
23
|
min-width: 0;
|
|
24
24
|
color: var(--ds-text-color);
|
|
25
|
-
font-family: var(--ds-typeface-regular);
|
|
25
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular);
|
|
26
26
|
font-feature-settings: var(--ds-font-features);
|
|
27
27
|
font-size: var(--ds-type-size-default);
|
|
28
28
|
line-height: var(--ds-type-lineheight-default);
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
min-height: 0;
|
|
11
11
|
background: var(--ds-paper);
|
|
12
12
|
color: var(--ds-text-color);
|
|
13
|
-
font-family: var(--ds-typeface-regular);
|
|
13
|
+
font-family: "Inter Arrows", var(--ds-typeface-regular);
|
|
14
14
|
font-feature-settings: var(--ds-font-features);
|
|
15
15
|
font-size: var(--ds-type-size-default);
|
|
16
16
|
line-height: var(--ds-type-lineheight-default);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constraint-panel.d.ts","sourceRoot":"","sources":["../../DS1/0-face/constraint-panel.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"constraint-panel.d.ts","sourceRoot":"","sources":["../../DS1/0-face/constraint-panel.ts"],"names":[],"mappings":"AACA,OAAO,EAAsB,KAAK,UAAU,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAKlF,8EAA8E;AAC9E,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB;kBAuSf,MAAM,GAAG,MAAM;;;;;;oBAjLI,UAAU;;EAkNlD;AAED,4HAA4H;AAC5H,eAAO,MAAM,gBAAgB,aAAa,CAAC;AAiB3C;;;;GAIG;AACH,eAAO,MAAM,WAAW,eACiD,CAAC;AAE1E,mHAAmH;AACnH,wBAAgB,gBAAgB,CAAC,MAAM,SAAyB,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAIxF;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CA4C7C"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { paintFaultLines } from './fault-lines';
|
|
1
2
|
import { measureConstraints } from './constraints';
|
|
2
|
-
import {
|
|
3
|
+
import { VIEWPORT_WIDTHS, checkSite, findSitePages, inspectInFrame, ruleLine, summarizePages, summarizeRules } from './constraint-site';
|
|
3
4
|
// appendChild, not append: a Worker project's types redefine append for its HTML rewriter.
|
|
4
5
|
/** The presses of C, each within 800ms of the last, that toggle the panel. */
|
|
5
6
|
export const CONSTRAINT_PRESSES = 5;
|
|
@@ -35,7 +36,8 @@ export function createConstraintPanel() {
|
|
|
35
36
|
--danger: var(--ds-danger-color, light-dark(#de0331, #ff5f5f));
|
|
36
37
|
}
|
|
37
38
|
:host([hidden]) { display: none !important; }
|
|
38
|
-
.
|
|
39
|
+
.fault-lines { z-index: 0 !important; }
|
|
40
|
+
.rings { z-index: 1; position: absolute; inset: 0; overflow: hidden; }
|
|
39
41
|
.frames { position: absolute; width: 0; height: 0; overflow: hidden; }
|
|
40
42
|
.ring {
|
|
41
43
|
position: absolute;
|
|
@@ -57,6 +59,7 @@ export function createConstraintPanel() {
|
|
|
57
59
|
text-align: center;
|
|
58
60
|
}
|
|
59
61
|
aside {
|
|
62
|
+
z-index: 2;
|
|
60
63
|
position: absolute;
|
|
61
64
|
inset-block: 0;
|
|
62
65
|
inset-inline-end: 0;
|
|
@@ -103,14 +106,18 @@ export function createConstraintPanel() {
|
|
|
103
106
|
.code b { color: var(--danger); font-weight: 400; }
|
|
104
107
|
.rule { color: var(--muted); }
|
|
105
108
|
p { margin: 0; }
|
|
109
|
+
:host([data-lines-only]) aside { inset-block: 0 auto; width: auto; padding: calc(var(--u) / 2); }
|
|
110
|
+
:host([data-lines-only]) aside > :not(header), :host([data-lines-only]) header > :not([data-lines], [data-close]) { display: none; }
|
|
111
|
+
:host([data-lines-only]) header { margin: 0; }
|
|
106
112
|
@media print { :host { display: none !important; } }
|
|
107
|
-
</style><div class="rings"></div><div class="frames"></div><aside aria-label="Constraints">
|
|
108
|
-
<header><strong>Constraints</strong><button type="button" data-run>Page</button><button type="button" data-site>Site</button><button type="button" data-close aria-label="Close">Close</button></header>
|
|
109
|
-
<p data-status aria-live="polite"></p>
|
|
113
|
+
</style><svg class="fault-lines" aria-hidden="true"></svg><div class="rings"></div><div class="frames"></div><aside aria-label="Constraints">
|
|
114
|
+
<header><strong>Constraints</strong><button type="button" data-run>Page</button><button type="button" data-site>Site</button><button type="button" data-lines>Lines</button><button type="button" data-close aria-label="Close">Close</button></header>
|
|
115
|
+
<p data-status aria-live="polite"></p><p class="rule">Fault lines: dashed reference · red drift</p>
|
|
110
116
|
<ol data-findings></ol>
|
|
111
117
|
<section data-rules hidden><h3>Rules</h3><ol></ol></section>
|
|
112
118
|
<section data-pages hidden><h3>Pages</h3><ol></ol></section>
|
|
113
119
|
</aside>`;
|
|
120
|
+
const faultLines = shadow.querySelector('.fault-lines');
|
|
114
121
|
const rings = shadow.querySelector('.rings');
|
|
115
122
|
const list = shadow.querySelector('[data-findings]');
|
|
116
123
|
const rulesSection = shadow.querySelector('[data-rules]');
|
|
@@ -120,6 +127,9 @@ export function createConstraintPanel() {
|
|
|
120
127
|
const status = shadow.querySelector('[data-status]');
|
|
121
128
|
const title = shadow.querySelector('strong');
|
|
122
129
|
const frames = shadow.querySelector('.frames');
|
|
130
|
+
const linesButton = shadow.querySelector('[data-lines]');
|
|
131
|
+
const setLinesOnly = (enabled) => { panel.toggleAttribute('data-lines-only', enabled); linesButton.textContent = enabled ? 'Results' : 'Lines'; };
|
|
132
|
+
linesButton.addEventListener('click', () => setLinesOnly(!panel.hasAttribute('data-lines-only')));
|
|
123
133
|
const siteButton = shadow.querySelector('[data-site]');
|
|
124
134
|
let site = null;
|
|
125
135
|
let findings = [];
|
|
@@ -127,6 +137,7 @@ export function createConstraintPanel() {
|
|
|
127
137
|
let frame = 0;
|
|
128
138
|
const place = () => {
|
|
129
139
|
frame = 0;
|
|
140
|
+
paintFaultLines(document, faultLines);
|
|
130
141
|
rings.replaceChildren(...findings.map(({ element }, index) => {
|
|
131
142
|
const rect = element.getBoundingClientRect();
|
|
132
143
|
const ring = document.createElement('div');
|
|
@@ -141,6 +152,8 @@ export function createConstraintPanel() {
|
|
|
141
152
|
};
|
|
142
153
|
const schedule = () => { if (!frame)
|
|
143
154
|
frame = requestAnimationFrame(place); };
|
|
155
|
+
const layoutChanges = new MutationObserver(schedule);
|
|
156
|
+
const sizeChanges = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(schedule);
|
|
144
157
|
const stopSite = () => {
|
|
145
158
|
site?.abort();
|
|
146
159
|
site = null;
|
|
@@ -274,7 +287,7 @@ export function createConstraintPanel() {
|
|
|
274
287
|
title.textContent = 'Constraints';
|
|
275
288
|
status.textContent = 'Finding the pages…';
|
|
276
289
|
const pages = await findSitePages();
|
|
277
|
-
const widths = `${
|
|
290
|
+
const widths = `${VIEWPORT_WIDTHS.slice(0, -1).join(', ')} and ${VIEWPORT_WIDTHS[VIEWPORT_WIDTHS.length - 1]}px`;
|
|
278
291
|
let broken = 0;
|
|
279
292
|
const results = await checkSite({
|
|
280
293
|
pages,
|
|
@@ -302,16 +315,25 @@ export function createConstraintPanel() {
|
|
|
302
315
|
if (!panel.isConnected)
|
|
303
316
|
document.body.appendChild(panel);
|
|
304
317
|
panel.hidden = false;
|
|
318
|
+
setLinesOnly(window.innerWidth < 640);
|
|
305
319
|
if (mode === 'site')
|
|
306
320
|
void runSite();
|
|
307
321
|
else
|
|
308
322
|
run();
|
|
323
|
+
layoutChanges.observe(document.body, { subtree: true, childList: true, attributes: true, attributeFilter: ['style', 'class', 'hidden', 'data-ds-fault-lines', 'data-ds-fault-axis'] });
|
|
324
|
+
sizeChanges?.observe(document.body);
|
|
309
325
|
window.addEventListener('scroll', schedule, { passive: true, capture: true });
|
|
310
326
|
window.addEventListener('resize', schedule);
|
|
311
327
|
};
|
|
312
328
|
const hide = () => {
|
|
313
329
|
stopSite();
|
|
314
330
|
panel.hidden = true;
|
|
331
|
+
if (frame)
|
|
332
|
+
cancelAnimationFrame(frame);
|
|
333
|
+
frame = 0;
|
|
334
|
+
faultLines.replaceChildren();
|
|
335
|
+
layoutChanges.disconnect();
|
|
336
|
+
sizeChanges?.disconnect();
|
|
315
337
|
window.removeEventListener('scroll', schedule, { capture: true });
|
|
316
338
|
window.removeEventListener('resize', schedule);
|
|
317
339
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Constraint } from './constraints';
|
|
2
2
|
/** The narrowest phone still sold, the common ones and the widest. */
|
|
3
3
|
export declare const PHONE_WIDTHS: number[];
|
|
4
|
+
export declare const VIEWPORT_WIDTHS: number[];
|
|
4
5
|
/** Pages checked side by side, each in its own frame. */
|
|
5
6
|
export declare const PAGES_AT_ONCE = 3;
|
|
6
7
|
/** A rule broken on a page at a width, said in words, since the element stays in its frame. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constraint-site.d.ts","sourceRoot":"","sources":["../../DS1/0-face/constraint-site.ts"],"names":[],"mappings":"AAKA,OAAO,EAAmC,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAGjF,sEAAsE;AACtE,eAAO,MAAM,YAAY,UAAuB,CAAC;AACjD,yDAAyD;AACzD,eAAO,MAAM,aAAa,IAAI,CAAC;AAE/B,+FAA+F;AAC/F,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAC7G,0GAA0G;AAC1G,MAAM,MAAM,SAAS,GAAG;IAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC;AACtF,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpF,4FAA4F;AAC5F,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAIxD;AAED,+GAA+G;AAC/G,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAUlE;AAED,uGAAuG;AACvG,wBAAsB,aAAa,CAAC,IAAI,GAAE,QAAmB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAahF;AAID;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"constraint-site.d.ts","sourceRoot":"","sources":["../../DS1/0-face/constraint-site.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@ import { constraints, measureConstraints } from './constraints';
|
|
|
7
7
|
import { calculateScalingFactor, defaultScalingConfig } from './scaling';
|
|
8
8
|
/** The narrowest phone still sold, the common ones and the widest. */
|
|
9
9
|
export const PHONE_WIDTHS = [320, 375, 393, 430];
|
|
10
|
+
export const VIEWPORT_WIDTHS = [...PHONE_WIDTHS, 768, 1024, 1440];
|
|
10
11
|
/** Pages checked side by side, each in its own frame. */
|
|
11
12
|
export const PAGES_AT_ONCE = 3;
|
|
12
13
|
/** An element as a person finds it: its tag, id and classes, and the start of its words. */
|
|
@@ -52,7 +53,7 @@ const wait = (ms) => new Promise(done => setTimeout(done, ms));
|
|
|
52
53
|
* order of `widths`. The page reflows at each width without loading again. The address carries `ph=out`,
|
|
53
54
|
* the analytics opt-out most trackers honour, so the check counts no visits.
|
|
54
55
|
*/
|
|
55
|
-
export async function inspectInFrame(host, url, widths =
|
|
56
|
+
export async function inspectInFrame(host, url, widths = VIEWPORT_WIDTHS, height = 844) {
|
|
56
57
|
const frame = document.createElement('iframe');
|
|
57
58
|
frame.setAttribute('aria-hidden', 'true');
|
|
58
59
|
frame.tabIndex = -1;
|
|
@@ -106,7 +107,7 @@ export function checkPage(page) {
|
|
|
106
107
|
* each width as it comes. Stops starting pages when `signal` aborts. Whatever the pages store in this
|
|
107
108
|
* browser while they are checked is put back afterwards.
|
|
108
109
|
*/
|
|
109
|
-
export async function checkSite({ pages, widths =
|
|
110
|
+
export async function checkSite({ pages, widths = VIEWPORT_WIDTHS, inspect, onResult, signal, atOnce = PAGES_AT_ONCE }) {
|
|
110
111
|
const kept = storedNow();
|
|
111
112
|
const results = [];
|
|
112
113
|
const total = pages.length * widths.length;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constraints.d.ts","sourceRoot":"","sources":["../../DS1/0-face/constraints.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"constraints.d.ts","sourceRoot":"","sources":["../../DS1/0-face/constraints.ts"],"names":[],"mappings":"AAgBA;+GAC+G;AAC/G,MAAM,MAAM,OAAO,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAE9E,MAAM,MAAM,UAAU,GAAG;IACvB,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,gGAAgG;IAChG,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,4EAA4E;IAC5E,OAAO,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,EAAE,CAAC;IACzC,uGAAuG;IACvG,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACtC,KAAK,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,MAAM,CAAC;CACrC,CAAC;AA6EF,eAAO,MAAM,WAAW,EAAE,UAAU,EA0JnC,CAAC;AAEF,qDAAqD;AACrD,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,UAAqB,GAAG,CAAC,OAAO,GAAG;IAAE,UAAU,EAAE,UAAU,CAAA;CAAE,CAAC,EAAE,CAExG;AAED,iHAAiH;AACjH,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,UAAqB,GAAG;IAAE,UAAU,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,EAAE,CAAA;CAAE,EAAE,CAEnI;AAED,qEAAqE;AACrE,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,WAGxC,CAAC;AAEF,qFAAqF;AACrF,wBAAgB,WAAW,CAAC,IAAI,GAAE,UAAU,EAAgB,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,EAAE,CAOtF;AAED,eAAO,MAAM,UAAU,wGAAwG,CAAC;AAChI,eAAO,MAAM,QAAQ,6BAA6B,CAAC;AAEnD,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,GAAE,UAAU,EAAgB,GAAG,MAAM,CAQnE"}
|
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
import { faultLineGrids, inspectFaultLines } from './fault-lines';
|
|
1
2
|
import { labelledButtons, inspectButtonLabels } from './button-label';
|
|
2
3
|
import { inspectTextContrast, measureTextContrast } from "./text-contrast";
|
|
3
4
|
import { inspectWordWrap, wordHeaders } from './word-wrap';
|
|
5
|
+
/** The actual initial, including a component nested in another open shadow root. */
|
|
6
|
+
function isAvatarInitial(element) {
|
|
7
|
+
for (let parent = element; parent; parent = parent.assignedSlot ?? parent.parentElement ?? parent.getRootNode().host ?? null) {
|
|
8
|
+
if (parent.matches('ds-avatar, .ds-avatar'))
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
4
13
|
/** A pixel either way is the same place. */
|
|
5
14
|
const near = (a, b) => Math.abs(a - b) <= 1;
|
|
6
15
|
const px = (n) => `${Math.round(n)}px`;
|
|
@@ -68,6 +77,14 @@ function rows(found) {
|
|
|
68
77
|
return groups.filter(row => row.length > 1);
|
|
69
78
|
}
|
|
70
79
|
export const constraints = [
|
|
80
|
+
{
|
|
81
|
+
code: 'page.fault-lines',
|
|
82
|
+
rule: 'Fault lines keep related card and control grids aligned across the whole page, with matching track edges and gaps at every checked viewport width.',
|
|
83
|
+
why: 'Compare separate sections in the same alignment family; responsive layouts may change together, while unrelated groups and intentional exceptions remain independent.',
|
|
84
|
+
components: ['ds-page'],
|
|
85
|
+
check: { file: 'tests/fault-lines.test.ts', test: 'fault lines catch shifted tracks and unequal gaps across sections at each viewport' },
|
|
86
|
+
measures: ['alignment group', 'alignment groups'], count: root => faultLineGrids(root).length, inspect: inspectFaultLines,
|
|
87
|
+
},
|
|
71
88
|
{
|
|
72
89
|
code: 'select.hug',
|
|
73
90
|
rule: 'Select and date-picker triggers use hug sizing, never fill sizing or growing to occupy the available row.',
|
|
@@ -111,6 +128,16 @@ export const constraints = [
|
|
|
111
128
|
count: root => measureTextContrast(root).length,
|
|
112
129
|
inspect: inspectTextContrast,
|
|
113
130
|
},
|
|
131
|
+
{
|
|
132
|
+
code: 'avatar.initial-contrast',
|
|
133
|
+
rule: 'Avatar initials have at least 4.5:1 contrast against their rendered fill, including after a theme or identity colour changes.',
|
|
134
|
+
why: 'Check each initial inside the avatar’s shadow root and in overlapping groups; decorative initials still need to be readable. Explicit ink overrides must pass too.',
|
|
135
|
+
components: ['ds-avatar'],
|
|
136
|
+
check: { file: 'tests/avatar-contrast.test.ts', test: 'avatar initials stay readable after theme and CSS-variable changes, and the avatar constraint catches overrides' },
|
|
137
|
+
measures: ['avatar initial', 'avatar initials'],
|
|
138
|
+
count: root => measureTextContrast(root).filter(result => isAvatarInitial(result.element)).length,
|
|
139
|
+
inspect: root => inspectTextContrast(root).filter(finding => isAvatarInitial(finding.element)),
|
|
140
|
+
},
|
|
114
141
|
{
|
|
115
142
|
code: 'card.media-level',
|
|
116
143
|
rule: "A card's picture stands on the card's foot, a square below the words at least, so the pictures of cards side by side stand on one level whatever the words above them.",
|
package/dist/0-face/define.js
CHANGED
|
@@ -5,7 +5,7 @@ export function define(name, element) {
|
|
|
5
5
|
const type = element;
|
|
6
6
|
const prototype = element.prototype;
|
|
7
7
|
const original = prototype.createRenderRoot;
|
|
8
|
-
if (original) {
|
|
8
|
+
if (original && typeof document !== 'undefined') {
|
|
9
9
|
const definingDocument = document;
|
|
10
10
|
prototype.createRenderRoot = function () {
|
|
11
11
|
var _a;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Finding } from './constraints';
|
|
2
|
+
type Grid = {
|
|
3
|
+
element: Element;
|
|
4
|
+
family: string | null;
|
|
5
|
+
axis: 'x' | 'y';
|
|
6
|
+
lines: number[];
|
|
7
|
+
gaps: number[];
|
|
8
|
+
crossGap?: number;
|
|
9
|
+
internalDrift: boolean;
|
|
10
|
+
start: number;
|
|
11
|
+
end: number;
|
|
12
|
+
};
|
|
13
|
+
/** Related grids opt in by name; unlabelled card grids are candidates for human review. */
|
|
14
|
+
export declare function faultLineGrids(root: ParentNode): Grid[];
|
|
15
|
+
/** Fault lines compare rendered tracks across separate sections, in the current viewport. */
|
|
16
|
+
export declare function inspectFaultLines(root: ParentNode): Finding[];
|
|
17
|
+
/** The same rendered geometry as the checker, painted without affecting layout or hit testing. */
|
|
18
|
+
export declare function paintFaultLines(root: ParentNode, layer: SVGSVGElement): void;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=fault-lines.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fault-lines.d.ts","sourceRoot":"","sources":["../../DS1/0-face/fault-lines.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAe7C,KAAK,IAAI,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,GAAG,GAAG,GAAG,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjL,2FAA2F;AAC3F,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,EAAE,CA2BvD;AAWD,6FAA6F;AAC7F,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,EAAE,CAkB7D;AAGD,kGAAkG;AAClG,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CA+E5E"}
|