@ggui-ai/ui-visual-tester 0.20.0 → 0.22.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/dist/prime-inputs.d.ts.map +1 -1
- package/dist/prime-inputs.js +44 -21
- package/fixture/fixture-runtime.js +79 -39
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prime-inputs.d.ts","sourceRoot":"","sources":["../src/prime-inputs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prime-inputs.d.ts","sourceRoot":"","sources":["../src/prime-inputs.ts"],"names":[],"mappings":"AA2EA,wBAAgB,cAAc,CAAC,EAAE,EAAE,gBAAgB,GAAG,mBAAmB,GAAG,MAAM,CAmCjF;AAED,iHAAiH;AACjH,wBAAgB,cAAc,CAAC,EAAE,EAAE,gBAAgB,GAAG,mBAAmB,GAAG,iBAAiB,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAYlH;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CA0CrD"}
|
package/dist/prime-inputs.js
CHANGED
|
@@ -7,6 +7,23 @@
|
|
|
7
7
|
// SAME way — one typed-values table, no divergence. Pure DOM + Date only (no
|
|
8
8
|
// Playwright), so it is safe to import into the lightweight happy-dom check
|
|
9
9
|
// worker via the `@ggui-ai/ui-visual-tester/prime-inputs` subpath.
|
|
10
|
+
//
|
|
11
|
+
// Realm rule (ggui#1187 follow-up): every constructor this module needs —
|
|
12
|
+
// `HTMLInputElement`, `HTMLTextAreaElement`, `HTMLSelectElement`, `Event` —
|
|
13
|
+
// is read from the ROOT'S OWN window (`ownerDocument.defaultView`), never
|
|
14
|
+
// from ambient globals. The check worker installs happy-dom's `window` and
|
|
15
|
+
// `document` on `globalThis` without the element constructors, so an
|
|
16
|
+
// `instanceof HTMLInputElement` there is a `ReferenceError`, not a `false`;
|
|
17
|
+
// a browser page or vitest's happy-dom environment happens to have them.
|
|
18
|
+
// One code path, every realm.
|
|
19
|
+
/** The realm an element lives in. A detached document has none — that is a caller error, reported as one. */
|
|
20
|
+
function realmOf(el) {
|
|
21
|
+
const view = el.ownerDocument.defaultView;
|
|
22
|
+
if (view === null) {
|
|
23
|
+
throw new Error('primeInputs: the element is not attached to a window (ownerDocument.defaultView is null) — a detached document has no constructors to prime with');
|
|
24
|
+
}
|
|
25
|
+
return view;
|
|
26
|
+
}
|
|
10
27
|
// #1040: date-like types too — a wizard's first step is routinely gated on one ("preferred follow-up
|
|
11
28
|
// date"), and a Next that never enables hides every step behind it from the probe.
|
|
12
29
|
const TEXT_LIKE_INPUT_TYPES = new Set([
|
|
@@ -52,7 +69,7 @@ function isoWeekOf(y, m, d) {
|
|
|
52
69
|
return `${date.getUTCFullYear()}-W${pad2(week)}`;
|
|
53
70
|
}
|
|
54
71
|
export function sampleValueFor(el) {
|
|
55
|
-
if (!(el instanceof HTMLInputElement))
|
|
72
|
+
if (!(el instanceof realmOf(el).HTMLInputElement))
|
|
56
73
|
return 'probe'; // a textarea has no type to switch on
|
|
57
74
|
switch (el.type) {
|
|
58
75
|
case 'number':
|
|
@@ -90,18 +107,19 @@ export function sampleValueFor(el) {
|
|
|
90
107
|
}
|
|
91
108
|
/** Set a value the way React notices it: through the prototype's native setter, then an input + change event. */
|
|
92
109
|
export function setNativeValue(el, value) {
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
110
|
+
const view = realmOf(el);
|
|
111
|
+
const proto = el instanceof view.HTMLTextAreaElement
|
|
112
|
+
? view.HTMLTextAreaElement.prototype
|
|
113
|
+
: el instanceof view.HTMLSelectElement
|
|
114
|
+
? view.HTMLSelectElement.prototype
|
|
115
|
+
: view.HTMLInputElement.prototype;
|
|
98
116
|
const setter = Object.getOwnPropertyDescriptor(proto, 'value')?.set;
|
|
99
117
|
if (setter)
|
|
100
118
|
setter.call(el, value);
|
|
101
119
|
else
|
|
102
120
|
el.value = value;
|
|
103
|
-
el.dispatchEvent(new Event('input', { bubbles: true }));
|
|
104
|
-
el.dispatchEvent(new Event('change', { bubbles: true }));
|
|
121
|
+
el.dispatchEvent(new view.Event('input', { bubbles: true }));
|
|
122
|
+
el.dispatchEvent(new view.Event('change', { bubbles: true }));
|
|
105
123
|
}
|
|
106
124
|
/**
|
|
107
125
|
* The generic minimum a user does before pressing Send / Submit / Complete
|
|
@@ -111,12 +129,13 @@ export function setNativeValue(el, value) {
|
|
|
111
129
|
* Returns how many controls were primed.
|
|
112
130
|
*/
|
|
113
131
|
export function primeInputs(root) {
|
|
132
|
+
const view = realmOf(root);
|
|
114
133
|
let primed = 0;
|
|
115
|
-
const editable = (el) => !el.disabled && !
|
|
134
|
+
const editable = (el) => !el.disabled && !el.readOnly;
|
|
116
135
|
for (const el of Array.from(root.querySelectorAll('input, textarea'))) {
|
|
117
|
-
if (!(el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) || !editable(el))
|
|
136
|
+
if (!(el instanceof view.HTMLInputElement || el instanceof view.HTMLTextAreaElement) || !editable(el))
|
|
118
137
|
continue;
|
|
119
|
-
if (el instanceof HTMLInputElement && !TEXT_LIKE_INPUT_TYPES.has(el.type))
|
|
138
|
+
if (el instanceof view.HTMLInputElement && !TEXT_LIKE_INPUT_TYPES.has(el.type))
|
|
120
139
|
continue;
|
|
121
140
|
if (el.value.trim().length > 0)
|
|
122
141
|
continue;
|
|
@@ -125,7 +144,7 @@ export function primeInputs(root) {
|
|
|
125
144
|
primed += 1;
|
|
126
145
|
}
|
|
127
146
|
for (const el of Array.from(root.querySelectorAll('select'))) {
|
|
128
|
-
if (!(el instanceof HTMLSelectElement) || el.disabled)
|
|
147
|
+
if (!(el instanceof view.HTMLSelectElement) || el.disabled)
|
|
129
148
|
continue;
|
|
130
149
|
const current = el.options[el.selectedIndex];
|
|
131
150
|
if (current !== undefined && current.value.trim().length > 0)
|
|
@@ -136,17 +155,21 @@ export function primeInputs(root) {
|
|
|
136
155
|
setNativeValue(el, first.value);
|
|
137
156
|
primed += 1;
|
|
138
157
|
}
|
|
158
|
+
// Radios: one pick per named group; an unnamed radio is its own group.
|
|
159
|
+
// Grouping is done in JS (by `name` equality), not by re-querying with the
|
|
160
|
+
// name interpolated into a selector — no `CSS.escape`, no realm dependency.
|
|
161
|
+
const radios = Array.from(root.querySelectorAll('input[type="radio"]')).filter((m) => m instanceof view.HTMLInputElement);
|
|
139
162
|
const seenGroups = new Set();
|
|
140
|
-
for (const el of
|
|
141
|
-
if (
|
|
163
|
+
for (const el of radios) {
|
|
164
|
+
if (el.disabled)
|
|
142
165
|
continue;
|
|
143
|
-
const group = el.name
|
|
144
|
-
if (
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
166
|
+
const group = el.name;
|
|
167
|
+
if (group !== '') {
|
|
168
|
+
if (seenGroups.has(group))
|
|
169
|
+
continue;
|
|
170
|
+
seenGroups.add(group);
|
|
171
|
+
}
|
|
172
|
+
const members = group !== '' ? radios.filter((m) => m.name === group) : [el];
|
|
150
173
|
if (members.some((m) => m.checked))
|
|
151
174
|
continue;
|
|
152
175
|
const first = members.find((m) => !m.disabled);
|
|
@@ -20580,14 +20580,29 @@
|
|
|
20580
20580
|
easeInOut: "cubic-bezier(0.4, 0, 0.2, 1)",
|
|
20581
20581
|
spring: "cubic-bezier(0.175, 0.885, 0.32, 1.275)"
|
|
20582
20582
|
};
|
|
20583
|
+
var motionVar = {
|
|
20584
|
+
duration: {
|
|
20585
|
+
fast: "var(--ggui-motion-duration-fast)",
|
|
20586
|
+
base: "var(--ggui-motion-duration-base)",
|
|
20587
|
+
slow: "var(--ggui-motion-duration-slow)"
|
|
20588
|
+
},
|
|
20589
|
+
easing: {
|
|
20590
|
+
/** The system's ease-in-out — the default for colour, border and size changes. */
|
|
20591
|
+
standard: "var(--ggui-motion-easing-standard)",
|
|
20592
|
+
/** The decelerating arrival — transforms and entrances. */
|
|
20593
|
+
emphasized: "var(--ggui-motion-easing-emphasized)",
|
|
20594
|
+
/** The accelerating departure. */
|
|
20595
|
+
exit: "var(--ggui-motion-easing-exit)"
|
|
20596
|
+
}
|
|
20597
|
+
};
|
|
20583
20598
|
var transition = {
|
|
20584
20599
|
none: "none",
|
|
20585
|
-
fast: `${duration.fast} ${easing.
|
|
20586
|
-
normal: `${duration.
|
|
20587
|
-
slow: `${duration.slow} ${easing.
|
|
20588
|
-
colors: `color ${duration.
|
|
20589
|
-
opacity: `opacity ${duration.
|
|
20590
|
-
transform: `transform ${duration.
|
|
20600
|
+
fast: `${motionVar.duration.fast} ${motionVar.easing.standard}`,
|
|
20601
|
+
normal: `${motionVar.duration.base} ${motionVar.easing.standard}`,
|
|
20602
|
+
slow: `${motionVar.duration.slow} ${motionVar.easing.standard}`,
|
|
20603
|
+
colors: `color ${motionVar.duration.base} ${motionVar.easing.standard}, background-color ${motionVar.duration.base} ${motionVar.easing.standard}, border-color ${motionVar.duration.base} ${motionVar.easing.standard}`,
|
|
20604
|
+
opacity: `opacity ${motionVar.duration.base} ${motionVar.easing.standard}`,
|
|
20605
|
+
transform: `transform ${motionVar.duration.base} ${motionVar.easing.emphasized}`
|
|
20591
20606
|
};
|
|
20592
20607
|
|
|
20593
20608
|
// ../design/dist/primitives/Button.js
|
|
@@ -20663,7 +20678,7 @@
|
|
|
20663
20678
|
cursor: isDisabled ? "not-allowed" : "pointer",
|
|
20664
20679
|
opacity: isDisabled ? 0.5 : 1,
|
|
20665
20680
|
width: fullWidth ? "100%" : void 0,
|
|
20666
|
-
transition: `background-color ${duration.
|
|
20681
|
+
transition: `background-color ${motionVar.duration.base} ${motionVar.easing.standard}, box-shadow ${motionVar.duration.base} ${motionVar.easing.standard}, opacity ${motionVar.duration.base} ${motionVar.easing.standard}`,
|
|
20667
20682
|
boxShadow: "var(--ggui-shape-shadow-sm, 0 1px 2px rgba(0,0,0,0.05))",
|
|
20668
20683
|
...style
|
|
20669
20684
|
}, ...rest, children: loading ? (0, import_jsx_runtime8.jsx)(Spinner, { size: 16, tone: "inherit" }) : (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [leftIcon, children, rightIcon] }) });
|
|
@@ -20708,7 +20723,7 @@
|
|
|
20708
20723
|
border: `1px solid ${hasError ? "var(--ggui-color-error-500, #ef4444)" : "var(--ggui-color-outline, #d4d4d8)"}`,
|
|
20709
20724
|
backgroundColor: disabled ? "var(--ggui-color-sunken, #fafafa)" : "var(--ggui-color-sunken, #ffffff)",
|
|
20710
20725
|
color: "var(--ggui-color-onContainer, #18181b)",
|
|
20711
|
-
transition: `border-color ${duration.
|
|
20726
|
+
transition: `border-color ${motionVar.duration.base} ${motionVar.easing.standard}, box-shadow ${motionVar.duration.base} ${motionVar.easing.standard}`,
|
|
20712
20727
|
boxSizing: "border-box"
|
|
20713
20728
|
}, ...rest }), hasMessage && (0, import_jsx_runtime9.jsx)("span", { id: messageId, role: hasError ? "alert" : void 0, style: {
|
|
20714
20729
|
fontSize: "var(--ggui-font-size-xs, 12px)",
|
|
@@ -20744,7 +20759,7 @@
|
|
|
20744
20759
|
color: "var(--ggui-color-onContainer, #18181b)",
|
|
20745
20760
|
fontSize: "var(--ggui-font-size-sm, 14px)",
|
|
20746
20761
|
fontFamily: "inherit",
|
|
20747
|
-
transition: `border-color ${duration.
|
|
20762
|
+
transition: `border-color ${motionVar.duration.base} ${motionVar.easing.standard}, box-shadow ${motionVar.duration.base} ${motionVar.easing.standard}`,
|
|
20748
20763
|
boxSizing: "border-box",
|
|
20749
20764
|
resize: autoResize ? "none" : "vertical"
|
|
20750
20765
|
}, ...rest }), (0, import_jsx_runtime10.jsxs)("div", { style: { display: "flex", justifyContent: "space-between" }, children: [hasMessage && (0, import_jsx_runtime10.jsx)("span", { id: messageId, role: hasError ? "alert" : void 0, style: {
|
|
@@ -20789,7 +20804,7 @@
|
|
|
20789
20804
|
backgroundPosition: "right 12px center",
|
|
20790
20805
|
paddingRight: "36px",
|
|
20791
20806
|
boxSizing: "border-box",
|
|
20792
|
-
transition: `border-color ${duration.
|
|
20807
|
+
transition: `border-color ${motionVar.duration.base} ${motionVar.easing.standard}, box-shadow ${motionVar.duration.base} ${motionVar.easing.standard}`
|
|
20793
20808
|
}, ...rest, children: [placeholder && (0, import_jsx_runtime11.jsx)("option", { value: "", disabled: true, children: placeholder }), options.map((opt) => (0, import_jsx_runtime11.jsx)("option", { value: opt.value, disabled: opt.disabled, children: opt.label }, opt.value))] }), hasMessage && (0, import_jsx_runtime11.jsx)("span", { id: messageId, role: hasError ? "alert" : void 0, style: {
|
|
20794
20809
|
fontSize: "var(--ggui-font-size-xs, 12px)",
|
|
20795
20810
|
color: hasError ? "var(--ggui-color-error-500, #ef4444)" : "var(--ggui-color-onSunken, #52525b)"
|
|
@@ -20831,7 +20846,7 @@
|
|
|
20831
20846
|
display: "flex",
|
|
20832
20847
|
alignItems: "center",
|
|
20833
20848
|
justifyContent: "center",
|
|
20834
|
-
transition:
|
|
20849
|
+
transition: `all ${motionVar.duration.base} ${motionVar.easing.standard}`
|
|
20835
20850
|
}, children: (checked || indeterminate) && (0, import_jsx_runtime12.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", style: { color: "var(--ggui-color-onPrimary, #ffffff)" }, children: indeterminate ? (0, import_jsx_runtime12.jsx)("path", { d: "M2.5 6H9.5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) : (0, import_jsx_runtime12.jsx)("path", { d: "M2.5 6L5 8.5L9.5 3.5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] }), (label || description) && (0, import_jsx_runtime12.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "2px" }, children: [label && (0, import_jsx_runtime12.jsx)("span", { style: {
|
|
20836
20851
|
fontSize: "var(--ggui-font-size-sm, 14px)",
|
|
20837
20852
|
fontWeight: "var(--ggui-font-weight-medium, 500)",
|
|
@@ -20873,7 +20888,7 @@
|
|
|
20873
20888
|
borderRadius: "9999px",
|
|
20874
20889
|
backgroundColor: checked ? "var(--ggui-color-primary-600, #0284c7)" : "var(--ggui-color-outline, #d4d4d8)",
|
|
20875
20890
|
position: "relative",
|
|
20876
|
-
transition: `background-color ${duration.
|
|
20891
|
+
transition: `background-color ${motionVar.duration.base} ${motionVar.easing.standard}, box-shadow ${motionVar.duration.base} ${motionVar.easing.standard}`,
|
|
20877
20892
|
flexShrink: 0,
|
|
20878
20893
|
outline: "none",
|
|
20879
20894
|
boxShadow: focused ? "0 0 0 3px var(--ggui-color-primary-200, #bae6fd)" : void 0
|
|
@@ -20885,7 +20900,7 @@
|
|
|
20885
20900
|
position: "absolute",
|
|
20886
20901
|
top: (config.height - config.knob) / 2,
|
|
20887
20902
|
left: checked ? config.width - config.knob - (config.height - config.knob) / 2 : (config.height - config.knob) / 2,
|
|
20888
|
-
transition: `left ${duration.
|
|
20903
|
+
transition: `left ${motionVar.duration.base} ${motionVar.easing.standard}`,
|
|
20889
20904
|
boxShadow: "var(--ggui-shape-shadow-sm, 0 1px 2px rgba(0,0,0,0.05))"
|
|
20890
20905
|
} }) }), label && (0, import_jsx_runtime13.jsx)("span", { style: {
|
|
20891
20906
|
fontSize: "var(--ggui-font-size-sm, 14px)",
|
|
@@ -20943,7 +20958,7 @@
|
|
|
20943
20958
|
display: "flex",
|
|
20944
20959
|
alignItems: "center",
|
|
20945
20960
|
justifyContent: "center",
|
|
20946
|
-
transition:
|
|
20961
|
+
transition: `all ${motionVar.duration.base} ${motionVar.easing.standard}`
|
|
20947
20962
|
}, children: isSelected && (0, import_jsx_runtime14.jsx)("div", { style: {
|
|
20948
20963
|
width: "8px",
|
|
20949
20964
|
height: "8px",
|
|
@@ -20991,7 +21006,7 @@
|
|
|
20991
21006
|
height: "6px",
|
|
20992
21007
|
borderRadius: "3px",
|
|
20993
21008
|
backgroundColor: disabled ? "var(--ggui-color-outline, #d4d4d8)" : "var(--ggui-color-primary-600, #0284c7)",
|
|
20994
|
-
transition:
|
|
21009
|
+
transition: `width ${motionVar.duration.fast} ${motionVar.easing.standard}`
|
|
20995
21010
|
} }), (0, import_jsx_runtime15.jsx)("input", { id: sliderId, type: "range", min, max, step, value, onChange: (e) => onChange?.(Number(e.target.value)), disabled, "aria-labelledby": label ? labelId : void 0, "aria-label": label ? void 0 : "Slider", "aria-valuenow": value, "aria-valuemin": min, "aria-valuemax": max, style: {
|
|
20996
21011
|
position: "absolute",
|
|
20997
21012
|
width: "100%",
|
|
@@ -21009,7 +21024,7 @@
|
|
|
21009
21024
|
backgroundColor: "#ffffff",
|
|
21010
21025
|
border: `2px solid ${disabled ? "var(--ggui-color-outline, #d4d4d8)" : "var(--ggui-color-primary-600, #0284c7)"}`,
|
|
21011
21026
|
boxShadow: "var(--ggui-shape-shadow-sm, 0 1px 2px rgba(0,0,0,0.05))",
|
|
21012
|
-
transition:
|
|
21027
|
+
transition: `left ${motionVar.duration.fast} ${motionVar.easing.standard}`,
|
|
21013
21028
|
pointerEvents: "none"
|
|
21014
21029
|
} })] })] });
|
|
21015
21030
|
}
|
|
@@ -21237,7 +21252,7 @@
|
|
|
21237
21252
|
height: "100%",
|
|
21238
21253
|
borderRadius: height / 2,
|
|
21239
21254
|
backgroundColor: barColor,
|
|
21240
|
-
transition: indeterminate ? "none" :
|
|
21255
|
+
transition: indeterminate ? "none" : `width ${motionVar.duration.slow} ${motionVar.easing.standard}`,
|
|
21241
21256
|
...indeterminate ? {
|
|
21242
21257
|
width: "30%",
|
|
21243
21258
|
animation: "ggui-progress-indeterminate 1.5s ease-in-out infinite"
|
|
@@ -25869,7 +25884,7 @@
|
|
|
25869
25884
|
color: linkColor,
|
|
25870
25885
|
textDecoration: underlineStyle,
|
|
25871
25886
|
cursor: "pointer",
|
|
25872
|
-
transition:
|
|
25887
|
+
transition: `color ${motionVar.duration.base} ${motionVar.easing.standard}`,
|
|
25873
25888
|
...style
|
|
25874
25889
|
}, onMouseEnter: (e) => {
|
|
25875
25890
|
if (underline === "hover") {
|
|
@@ -26029,7 +26044,7 @@
|
|
|
26029
26044
|
cursor: col.sortable ? "pointer" : "default"
|
|
26030
26045
|
}, children: (0, import_jsx_runtime25.jsxs)("span", { style: { display: "inline-flex", alignItems: "center" }, children: [col.header, col.sortable && sortIndicator(sortKey === col.key, sortDirection)] }) }, col.key)) }) }), (0, import_jsx_runtime25.jsx)("tbody", { children: data.map((row, rowIndex) => (0, import_jsx_runtime25.jsx)("tr", { onMouseEnter: hoverable ? () => setHoveredRow(rowIndex) : void 0, onMouseLeave: hoverable ? () => setHoveredRow(null) : void 0, style: {
|
|
26031
26046
|
backgroundColor: hoverable && hoveredRow === rowIndex ? "var(--ggui-color-sunken, #fafafa)" : striped && rowIndex % 2 === 1 ? "var(--ggui-color-sunken, #fafafa)" : "transparent",
|
|
26032
|
-
transition:
|
|
26047
|
+
transition: `background-color ${motionVar.duration.fast} ${motionVar.easing.standard}`
|
|
26033
26048
|
}, children: columns.map((col) => (0, import_jsx_runtime25.jsx)("td", { style: {
|
|
26034
26049
|
padding: cellPadding,
|
|
26035
26050
|
textAlign: col.align || "left",
|
|
@@ -26103,7 +26118,7 @@
|
|
|
26103
26118
|
background: "none",
|
|
26104
26119
|
border: "none",
|
|
26105
26120
|
fontWeight: isActive ? "var(--ggui-font-weight-semibold, 600)" : "var(--ggui-font-weight-medium, 500)",
|
|
26106
|
-
transition: `color ${duration.
|
|
26121
|
+
transition: `color ${motionVar.duration.base} ${motionVar.easing.standard}, background-color ${motionVar.duration.base} ${motionVar.easing.standard}, border-color ${motionVar.duration.base} ${motionVar.easing.standard}`,
|
|
26107
26122
|
whiteSpace: "nowrap",
|
|
26108
26123
|
flex: fullWidth ? 1 : void 0,
|
|
26109
26124
|
justifyContent: fullWidth ? "center" : void 0
|
|
@@ -26397,7 +26412,7 @@
|
|
|
26397
26412
|
var import_jsx_runtime28 = __toESM(require_jsx_runtime(), 1);
|
|
26398
26413
|
var import_react18 = __toESM(require_react(), 1);
|
|
26399
26414
|
var chevron = (expanded) => (0, import_jsx_runtime28.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 20 20", fill: "currentColor", "aria-hidden": "true", style: {
|
|
26400
|
-
transition: `transform ${duration.
|
|
26415
|
+
transition: `transform ${motionVar.duration.base} ${motionVar.easing.standard}`,
|
|
26401
26416
|
transform: expanded ? "rotate(180deg)" : "rotate(0deg)",
|
|
26402
26417
|
flexShrink: 0
|
|
26403
26418
|
}, children: (0, import_jsx_runtime28.jsx)("path", { fillRule: "evenodd", d: "M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z", clipRule: "evenodd" }) });
|
|
@@ -26470,7 +26485,7 @@
|
|
|
26470
26485
|
fontWeight: "var(--ggui-font-weight-medium, 500)",
|
|
26471
26486
|
color: "var(--ggui-color-onContainer, #18181b)",
|
|
26472
26487
|
textAlign: "left",
|
|
26473
|
-
transition: `background-color ${duration.fast} ${easing.
|
|
26488
|
+
transition: `background-color ${motionVar.duration.fast} ${motionVar.easing.standard}`
|
|
26474
26489
|
}, children: [(0, import_jsx_runtime28.jsx)("span", { children: item.title }), chevron(isExpanded)] }) }), (0, import_jsx_runtime28.jsx)("div", { id: `${uniqueId}-panel-${item.key}`, role: "region", "aria-labelledby": `${uniqueId}-header-${item.key}`, hidden: !isExpanded, style: {
|
|
26475
26490
|
overflow: "hidden"
|
|
26476
26491
|
}, children: isExpanded && (0, import_jsx_runtime28.jsx)("div", { style: {
|
|
@@ -26644,7 +26659,7 @@
|
|
|
26644
26659
|
fontWeight: active ? fontWeight.medium : fontWeight.normal,
|
|
26645
26660
|
textAlign: "left",
|
|
26646
26661
|
cursor: disabled ? "not-allowed" : "pointer",
|
|
26647
|
-
transition:
|
|
26662
|
+
transition: `background-color ${motionVar.duration.fast} ${motionVar.easing.standard}`,
|
|
26648
26663
|
...style
|
|
26649
26664
|
}, onMouseEnter: (e) => {
|
|
26650
26665
|
if (!disabled && !active) {
|
|
@@ -26962,7 +26977,7 @@
|
|
|
26962
26977
|
fontWeight: active ? fontWeight.medium : fontWeight.normal,
|
|
26963
26978
|
cursor: disabled ? "not-allowed" : "pointer",
|
|
26964
26979
|
opacity: disabled ? 0.5 : 1,
|
|
26965
|
-
transition:
|
|
26980
|
+
transition: `all ${motionVar.duration.fast} ${motionVar.easing.standard}`
|
|
26966
26981
|
}, children: page });
|
|
26967
26982
|
return (0, import_jsx_runtime36.jsxs)("nav", { "aria-label": "Pagination", className, style: {
|
|
26968
26983
|
display: "flex",
|
|
@@ -27030,7 +27045,7 @@
|
|
|
27030
27045
|
justifyContent: "center",
|
|
27031
27046
|
flexShrink: 0,
|
|
27032
27047
|
boxSizing: "border-box",
|
|
27033
|
-
transition:
|
|
27048
|
+
transition: `background-color ${motionVar.duration.base} ${motionVar.easing.standard}, border-color ${motionVar.duration.base} ${motionVar.easing.standard}, color ${motionVar.duration.base} ${motionVar.easing.standard}`,
|
|
27034
27049
|
...markerStyles[state]
|
|
27035
27050
|
}, children: state === "completed" ? (0, import_jsx_runtime39.jsx)(Icon, { name: "check", size: 16, tone: "inherit" }) : (0, import_jsx_runtime39.jsx)(Text, { is: "span", size: "sm", weight: "semibold", tone: "inherit", children: index + 1 }) });
|
|
27036
27051
|
}
|
|
@@ -29381,6 +29396,8 @@
|
|
|
29381
29396
|
...opts.onDispatchSuppressed !== void 0 ? { onDispatchSuppressed: opts.onDispatchSuppressed } : {},
|
|
29382
29397
|
dispatch: (actionName, data) => {
|
|
29383
29398
|
const actionSpec = opts.getActiveActionSpec();
|
|
29399
|
+
if (actionSpec === void 0)
|
|
29400
|
+
opts.onActionSpecAbsent?.(actionName);
|
|
29384
29401
|
const isOneShot = actionSpec?.[actionName]?.oneShot === true;
|
|
29385
29402
|
if (isOneShot && spentOneShots.has(actionName)) {
|
|
29386
29403
|
console.warn(`[ggui] dispatch('${actionName}') suppressed: this action is declared oneShot and already fired for this render. A second gesture is NOT sent to the agent \u2014 the submitted control is spent for the render's lifetime. If the action is meant to repeat, remove \`oneShot\` from its contract entry.`);
|
|
@@ -29561,6 +29578,14 @@
|
|
|
29561
29578
|
"--ggui-font-weight-normal",
|
|
29562
29579
|
"--ggui-font-weight-semibold",
|
|
29563
29580
|
"--ggui-letter-spacing-heading",
|
|
29581
|
+
"--ggui-motion-duration-base",
|
|
29582
|
+
"--ggui-motion-duration-fast",
|
|
29583
|
+
"--ggui-motion-duration-slow",
|
|
29584
|
+
"--ggui-motion-easing-emphasized",
|
|
29585
|
+
"--ggui-motion-easing-exit",
|
|
29586
|
+
"--ggui-motion-easing-standard",
|
|
29587
|
+
"--ggui-scrim-opacity",
|
|
29588
|
+
"--ggui-scrim-tint",
|
|
29564
29589
|
"--ggui-shape-radius-control",
|
|
29565
29590
|
"--ggui-shape-radius-full",
|
|
29566
29591
|
"--ggui-shape-radius-lg",
|
|
@@ -32534,6 +32559,7 @@
|
|
|
32534
32559
|
"duration",
|
|
32535
32560
|
"easing",
|
|
32536
32561
|
"transition",
|
|
32562
|
+
"motionVar",
|
|
32537
32563
|
"keyframes",
|
|
32538
32564
|
"thinkingAnimation",
|
|
32539
32565
|
"thinkingKeyframes",
|
|
@@ -32795,6 +32821,13 @@
|
|
|
32795
32821
|
}
|
|
32796
32822
|
|
|
32797
32823
|
// src/prime-inputs.ts
|
|
32824
|
+
function realmOf(el) {
|
|
32825
|
+
const view = el.ownerDocument.defaultView;
|
|
32826
|
+
if (view === null) {
|
|
32827
|
+
throw new Error("primeInputs: the element is not attached to a window (ownerDocument.defaultView is null) \u2014 a detached document has no constructors to prime with");
|
|
32828
|
+
}
|
|
32829
|
+
return view;
|
|
32830
|
+
}
|
|
32798
32831
|
var TEXT_LIKE_INPUT_TYPES = /* @__PURE__ */ new Set([
|
|
32799
32832
|
"text",
|
|
32800
32833
|
"email",
|
|
@@ -32833,7 +32866,7 @@
|
|
|
32833
32866
|
return `${date.getUTCFullYear()}-W${pad2(week)}`;
|
|
32834
32867
|
}
|
|
32835
32868
|
function sampleValueFor(el) {
|
|
32836
|
-
if (!(el instanceof HTMLInputElement)) return "probe";
|
|
32869
|
+
if (!(el instanceof realmOf(el).HTMLInputElement)) return "probe";
|
|
32837
32870
|
switch (el.type) {
|
|
32838
32871
|
case "number":
|
|
32839
32872
|
return "1";
|
|
@@ -32869,25 +32902,27 @@
|
|
|
32869
32902
|
}
|
|
32870
32903
|
}
|
|
32871
32904
|
function setNativeValue(el, value) {
|
|
32872
|
-
const
|
|
32905
|
+
const view = realmOf(el);
|
|
32906
|
+
const proto = el instanceof view.HTMLTextAreaElement ? view.HTMLTextAreaElement.prototype : el instanceof view.HTMLSelectElement ? view.HTMLSelectElement.prototype : view.HTMLInputElement.prototype;
|
|
32873
32907
|
const setter = Object.getOwnPropertyDescriptor(proto, "value")?.set;
|
|
32874
32908
|
if (setter) setter.call(el, value);
|
|
32875
32909
|
else el.value = value;
|
|
32876
|
-
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
32877
|
-
el.dispatchEvent(new Event("change", { bubbles: true }));
|
|
32910
|
+
el.dispatchEvent(new view.Event("input", { bubbles: true }));
|
|
32911
|
+
el.dispatchEvent(new view.Event("change", { bubbles: true }));
|
|
32878
32912
|
}
|
|
32879
32913
|
function primeInputs(root) {
|
|
32914
|
+
const view = realmOf(root);
|
|
32880
32915
|
let primed = 0;
|
|
32881
|
-
const editable = (el) => !el.disabled && !
|
|
32916
|
+
const editable = (el) => !el.disabled && !el.readOnly;
|
|
32882
32917
|
for (const el of Array.from(root.querySelectorAll("input, textarea"))) {
|
|
32883
|
-
if (!(el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) || !editable(el)) continue;
|
|
32884
|
-
if (el instanceof HTMLInputElement && !TEXT_LIKE_INPUT_TYPES.has(el.type)) continue;
|
|
32918
|
+
if (!(el instanceof view.HTMLInputElement || el instanceof view.HTMLTextAreaElement) || !editable(el)) continue;
|
|
32919
|
+
if (el instanceof view.HTMLInputElement && !TEXT_LIKE_INPUT_TYPES.has(el.type)) continue;
|
|
32885
32920
|
if (el.value.trim().length > 0) continue;
|
|
32886
32921
|
setNativeValue(el, sampleValueFor(el));
|
|
32887
32922
|
if (el.value.trim().length > 0) primed += 1;
|
|
32888
32923
|
}
|
|
32889
32924
|
for (const el of Array.from(root.querySelectorAll("select"))) {
|
|
32890
|
-
if (!(el instanceof HTMLSelectElement) || el.disabled) continue;
|
|
32925
|
+
if (!(el instanceof view.HTMLSelectElement) || el.disabled) continue;
|
|
32891
32926
|
const current = el.options[el.selectedIndex];
|
|
32892
32927
|
if (current !== void 0 && current.value.trim().length > 0) continue;
|
|
32893
32928
|
const first = Array.from(el.options).find((o) => o.value.trim().length > 0 && !o.disabled);
|
|
@@ -32895,13 +32930,18 @@
|
|
|
32895
32930
|
setNativeValue(el, first.value);
|
|
32896
32931
|
primed += 1;
|
|
32897
32932
|
}
|
|
32933
|
+
const radios = Array.from(root.querySelectorAll('input[type="radio"]')).filter(
|
|
32934
|
+
(m) => m instanceof view.HTMLInputElement
|
|
32935
|
+
);
|
|
32898
32936
|
const seenGroups = /* @__PURE__ */ new Set();
|
|
32899
|
-
for (const el of
|
|
32900
|
-
if (
|
|
32901
|
-
const group = el.name
|
|
32902
|
-
if (
|
|
32903
|
-
|
|
32904
|
-
|
|
32937
|
+
for (const el of radios) {
|
|
32938
|
+
if (el.disabled) continue;
|
|
32939
|
+
const group = el.name;
|
|
32940
|
+
if (group !== "") {
|
|
32941
|
+
if (seenGroups.has(group)) continue;
|
|
32942
|
+
seenGroups.add(group);
|
|
32943
|
+
}
|
|
32944
|
+
const members = group !== "" ? radios.filter((m) => m.name === group) : [el];
|
|
32905
32945
|
if (members.some((m) => m.checked)) continue;
|
|
32906
32946
|
const first = members.find((m) => !m.disabled);
|
|
32907
32947
|
if (first === void 0) continue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ggui-ai/ui-visual-tester",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "Behavioral validator for ggui-generated component code. Renders a component in real Chromium via Playwright, clicks each action declared in its contract, and verifies the action actually does something — mutating bound state or dispatching to the agent. Catches buttons wired to no-op handlers that structural validators miss. Playwright is an optional peer dependency, injected by the caller.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ggui",
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"react": "^19.0.0",
|
|
55
55
|
"react-dom": "^19.0.0",
|
|
56
|
-
"@ggui-ai/design": "0.
|
|
57
|
-
"@ggui-ai/protocol": "0.
|
|
58
|
-
"@ggui-ai/wire": "0.
|
|
56
|
+
"@ggui-ai/design": "0.22.0",
|
|
57
|
+
"@ggui-ai/protocol": "0.22.0",
|
|
58
|
+
"@ggui-ai/wire": "0.22.0"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@playwright/test": "^1.60.0",
|