@ggui-ai/ui-visual-tester 0.22.0 → 0.24.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/fixture/fixture-runtime.js +79 -21
- package/package.json +4 -4
|
@@ -20061,11 +20061,20 @@
|
|
|
20061
20061
|
|
|
20062
20062
|
// ../design/dist/interact/trait.js
|
|
20063
20063
|
var import_react = __toESM(require_react(), 1);
|
|
20064
|
+
function frameAttributes(frame) {
|
|
20065
|
+
if (frame === void 0)
|
|
20066
|
+
return {};
|
|
20067
|
+
return {
|
|
20068
|
+
...frame.surface !== void 0 ? { "data-ggui-surface": frame.surface } : {},
|
|
20069
|
+
...frame.bleed === true ? { "data-ggui-bleed": "" } : {}
|
|
20070
|
+
};
|
|
20071
|
+
}
|
|
20064
20072
|
function renderWithTrait(trait, traitProps, root, children) {
|
|
20073
|
+
const marks = frameAttributes(root.frame);
|
|
20065
20074
|
if (trait === void 0) {
|
|
20066
|
-
return (0, import_react.createElement)("div", { className: root.className, style: root.style }, children);
|
|
20075
|
+
return (0, import_react.createElement)("div", { className: root.className, style: root.style, ...marks }, children);
|
|
20067
20076
|
}
|
|
20068
|
-
return (0, import_react.createElement)(trait, { ...traitProps, className: root.className, style: root.style }, children);
|
|
20077
|
+
return (0, import_react.createElement)(trait, { ...traitProps, className: root.className, style: root.style, ...marks }, children);
|
|
20069
20078
|
}
|
|
20070
20079
|
|
|
20071
20080
|
// ../design/dist/primitives/color-slots.js
|
|
@@ -20195,9 +20204,14 @@
|
|
|
20195
20204
|
surface,
|
|
20196
20205
|
style,
|
|
20197
20206
|
className,
|
|
20207
|
+
bleed,
|
|
20198
20208
|
as: Trait,
|
|
20199
20209
|
...traitProps
|
|
20200
20210
|
} = props;
|
|
20211
|
+
const frame = {
|
|
20212
|
+
...surface !== "transparent" ? { surface: surface ?? "default" } : {},
|
|
20213
|
+
...bleed === true ? { bleed: true } : {}
|
|
20214
|
+
};
|
|
20201
20215
|
const resolvedPadding = resolveSpacing(padding);
|
|
20202
20216
|
const resolvedSurface = resolveSurfaceCss(surface ?? "default");
|
|
20203
20217
|
const resolvedOnColor = resolveSurfaceOnColorCss(surface ?? "default");
|
|
@@ -20215,10 +20229,11 @@
|
|
|
20215
20229
|
if (scope !== void 0) {
|
|
20216
20230
|
return renderWithTrait(Trait, traitProps, {
|
|
20217
20231
|
className: className ? `${className} ${scope.className}` : scope.className,
|
|
20218
|
-
style: composedStyle
|
|
20232
|
+
style: composedStyle,
|
|
20233
|
+
frame
|
|
20219
20234
|
}, (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [(0, import_jsx_runtime2.jsx)("style", { children: scope.css }), children] }));
|
|
20220
20235
|
}
|
|
20221
|
-
return renderWithTrait(Trait, traitProps, { className, style: composedStyle }, children);
|
|
20236
|
+
return renderWithTrait(Trait, traitProps, { className, style: composedStyle, frame }, children);
|
|
20222
20237
|
}
|
|
20223
20238
|
|
|
20224
20239
|
// ../design/dist/primitives/Stack.js
|
|
@@ -20315,7 +20330,9 @@
|
|
|
20315
20330
|
// ../design/dist/primitives/Box.js
|
|
20316
20331
|
var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
|
|
20317
20332
|
function Box(props) {
|
|
20318
|
-
const { children, padding, paddingX, paddingY, margin, surface, assetColor, assetSemantic, radius: radius2, style, className, as: Trait, ...traitProps } = props;
|
|
20333
|
+
const { children, padding, paddingX, paddingY, margin, surface, assetColor, assetSemantic, radius: radius2, style, className, bleed, as: Trait, ...traitProps } = props;
|
|
20334
|
+
const markedSurface = surface !== void 0 && surface !== "transparent" ? surface : void 0;
|
|
20335
|
+
const frame = markedSurface === void 0 && bleed !== true ? void 0 : { ...markedSurface !== void 0 ? { surface: markedSurface } : {}, ...bleed === true ? { bleed: true } : {} };
|
|
20319
20336
|
let computedPadding;
|
|
20320
20337
|
if (paddingX !== void 0 || paddingY !== void 0) {
|
|
20321
20338
|
const px = resolveSpacing(paddingX) || "0";
|
|
@@ -20340,10 +20357,11 @@
|
|
|
20340
20357
|
if (scope !== void 0) {
|
|
20341
20358
|
return renderWithTrait(Trait, traitProps, {
|
|
20342
20359
|
className: className ? `${className} ${scope.className}` : scope.className,
|
|
20343
|
-
style: composedStyle
|
|
20360
|
+
style: composedStyle,
|
|
20361
|
+
...frame !== void 0 ? { frame } : {}
|
|
20344
20362
|
}, (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [(0, import_jsx_runtime4.jsx)("style", { children: scope.css }), children] }));
|
|
20345
20363
|
}
|
|
20346
|
-
return renderWithTrait(Trait, traitProps, { className, style: composedStyle }, children);
|
|
20364
|
+
return renderWithTrait(Trait, traitProps, { className, style: composedStyle, ...frame !== void 0 ? { frame } : {} }, children);
|
|
20347
20365
|
}
|
|
20348
20366
|
|
|
20349
20367
|
// ../design/dist/primitives/Divider.js
|
|
@@ -28559,6 +28577,7 @@
|
|
|
28559
28577
|
buildWireConfig: () => buildWireConfig,
|
|
28560
28578
|
connectionSource: () => connectionSource,
|
|
28561
28579
|
useAction: () => useAction,
|
|
28580
|
+
useActionSpent: () => useActionSpent,
|
|
28562
28581
|
useApp: () => useApp,
|
|
28563
28582
|
useAuth: () => useAuth,
|
|
28564
28583
|
useContract: () => useContract,
|
|
@@ -28649,8 +28668,19 @@
|
|
|
28649
28668
|
}, [actionName, dispatch, onDispatchSuppressed]);
|
|
28650
28669
|
}
|
|
28651
28670
|
|
|
28652
|
-
// ../wire/dist/
|
|
28671
|
+
// ../wire/dist/action-spent.js
|
|
28653
28672
|
var import_react35 = __toESM(require_react(), 1);
|
|
28673
|
+
var ActionSpentContext = (0, import_react35.createContext)(null);
|
|
28674
|
+
var noSubscription = () => () => void 0;
|
|
28675
|
+
function useActionSpent(actionName) {
|
|
28676
|
+
const source = (0, import_react35.useContext)(ActionSpentContext);
|
|
28677
|
+
const subscribe = (0, import_react35.useCallback)((listener) => source === null ? noSubscription() : source.subscribe(listener), [source]);
|
|
28678
|
+
const read = (0, import_react35.useCallback)(() => source === null ? false : source.isSpent(actionName), [source, actionName]);
|
|
28679
|
+
return (0, import_react35.useSyncExternalStore)(subscribe, read, read);
|
|
28680
|
+
}
|
|
28681
|
+
|
|
28682
|
+
// ../wire/dist/useGguiContext.js
|
|
28683
|
+
var import_react36 = __toESM(require_react(), 1);
|
|
28654
28684
|
function useGguiContext(slotName) {
|
|
28655
28685
|
const contextName = slotName.length === 0 ? "Context" : slotName.charAt(0).toUpperCase() + slotName.slice(1) + "Context";
|
|
28656
28686
|
const registry = globalThis.__ggui__?.contexts;
|
|
@@ -28658,19 +28688,19 @@
|
|
|
28658
28688
|
if (!ctx) {
|
|
28659
28689
|
throw new Error(`[ggui] useGguiContext('${slotName}'): no Context registered. The contract must declare 'contextSpec.${slotName}' AND the runtime must have synthesized the per-slot React Context at boot. If you see this in production code generated by the LLM, the boilerplate's destructure line drifted from the contract.`);
|
|
28660
28690
|
}
|
|
28661
|
-
return (0,
|
|
28691
|
+
return (0, import_react36.useContext)(ctx);
|
|
28662
28692
|
}
|
|
28663
28693
|
|
|
28664
28694
|
// ../wire/dist/useStream.js
|
|
28665
|
-
var
|
|
28695
|
+
var import_react37 = __toESM(require_react(), 1);
|
|
28666
28696
|
function useStream(channelName) {
|
|
28667
28697
|
const { subscribe } = useWireContext();
|
|
28668
|
-
const [latest, setLatest] = (0,
|
|
28669
|
-
const [all, setAll] = (0,
|
|
28670
|
-
const [isComplete, setIsComplete] = (0,
|
|
28671
|
-
const allRef = (0,
|
|
28698
|
+
const [latest, setLatest] = (0, import_react37.useState)(null);
|
|
28699
|
+
const [all, setAll] = (0, import_react37.useState)([]);
|
|
28700
|
+
const [isComplete, setIsComplete] = (0, import_react37.useState)(false);
|
|
28701
|
+
const allRef = (0, import_react37.useRef)(all);
|
|
28672
28702
|
allRef.current = all;
|
|
28673
|
-
(0,
|
|
28703
|
+
(0, import_react37.useEffect)(() => {
|
|
28674
28704
|
return subscribe(channelName, (delivery) => {
|
|
28675
28705
|
const typed = delivery.payload;
|
|
28676
28706
|
setLatest(typed);
|
|
@@ -28708,7 +28738,7 @@
|
|
|
28708
28738
|
}
|
|
28709
28739
|
|
|
28710
28740
|
// ../wire/dist/useRender.js
|
|
28711
|
-
var
|
|
28741
|
+
var import_react38 = __toESM(require_react(), 1);
|
|
28712
28742
|
|
|
28713
28743
|
// ../wire/dist/connection-store.js
|
|
28714
28744
|
var ConnectionWriterConflictError = class extends Error {
|
|
@@ -28805,7 +28835,7 @@
|
|
|
28805
28835
|
// ../wire/dist/useRender.js
|
|
28806
28836
|
function useRender() {
|
|
28807
28837
|
const { render } = useWireContext();
|
|
28808
|
-
const isConnected = (0,
|
|
28838
|
+
const isConnected = (0, import_react38.useSyncExternalStore)(connectionSource.subscribe, connectionSource.getSnapshot, connectionSource.getSnapshot);
|
|
28809
28839
|
return { sessionId: render.sessionId, isConnected };
|
|
28810
28840
|
}
|
|
28811
28841
|
|
|
@@ -29389,7 +29419,24 @@
|
|
|
29389
29419
|
});
|
|
29390
29420
|
const validateEnvelope = opts.validateEnvelope ?? validateOutboundActionEnvelope;
|
|
29391
29421
|
const spentOneShots = /* @__PURE__ */ new Set();
|
|
29422
|
+
const isSpent = (actionName) => opts.getActiveActionSpec()?.[actionName]?.oneShot === true && (spentOneShots.has(actionName) || opts.getSpentOneShots?.()?.includes(actionName) === true);
|
|
29423
|
+
const spentListeners = /* @__PURE__ */ new Set();
|
|
29424
|
+
const notifySpent = () => {
|
|
29425
|
+
for (const listener of [...spentListeners])
|
|
29426
|
+
listener();
|
|
29427
|
+
};
|
|
29428
|
+
const actionSpent = {
|
|
29429
|
+
isSpent,
|
|
29430
|
+
subscribe: (listener) => {
|
|
29431
|
+
spentListeners.add(listener);
|
|
29432
|
+
return () => {
|
|
29433
|
+
spentListeners.delete(listener);
|
|
29434
|
+
};
|
|
29435
|
+
}
|
|
29436
|
+
};
|
|
29437
|
+
opts.spentInputsChanged?.(notifySpent);
|
|
29392
29438
|
return {
|
|
29439
|
+
actionSpent,
|
|
29393
29440
|
app: opts.app,
|
|
29394
29441
|
render: opts.render,
|
|
29395
29442
|
auth: opts.auth,
|
|
@@ -29399,7 +29446,7 @@
|
|
|
29399
29446
|
if (actionSpec === void 0)
|
|
29400
29447
|
opts.onActionSpecAbsent?.(actionName);
|
|
29401
29448
|
const isOneShot = actionSpec?.[actionName]?.oneShot === true;
|
|
29402
|
-
if (
|
|
29449
|
+
if (isSpent(actionName)) {
|
|
29403
29450
|
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.`);
|
|
29404
29451
|
opts.onDispatchSuppressed?.({
|
|
29405
29452
|
reason: "one-shot-spent",
|
|
@@ -29424,8 +29471,10 @@
|
|
|
29424
29471
|
opts.onViolation(new ClientContractViolationError("outbound-action", result.violations));
|
|
29425
29472
|
return;
|
|
29426
29473
|
}
|
|
29427
|
-
if (isOneShot)
|
|
29474
|
+
if (isOneShot && !spentOneShots.has(actionName)) {
|
|
29428
29475
|
spentOneShots.add(actionName);
|
|
29476
|
+
notifySpent();
|
|
29477
|
+
}
|
|
29429
29478
|
opts.emitEnvelope(envelope);
|
|
29430
29479
|
},
|
|
29431
29480
|
subscribe: (channelName, handler) => {
|
|
@@ -32420,8 +32469,12 @@
|
|
|
32420
32469
|
|
|
32421
32470
|
// ../design/dist/themes/ThemeProvider.js
|
|
32422
32471
|
var import_jsx_runtime58 = __toESM(require_jsx_runtime(), 1);
|
|
32423
|
-
var
|
|
32424
|
-
var ThemeContext = (0,
|
|
32472
|
+
var import_react39 = __toESM(require_react(), 1);
|
|
32473
|
+
var ThemeContext = (0, import_react39.createContext)(null);
|
|
32474
|
+
|
|
32475
|
+
// ../design/dist/rendering/css-tokens.js
|
|
32476
|
+
var EXPANDED_FRAME = { outerRadiusVar: "--ggui-shape-radius-xl", insetPx: 16 };
|
|
32477
|
+
var EXPANDED_FRAME_INNER_RADIUS = `max(0px, calc(var(${EXPANDED_FRAME.outerRadiusVar}) - ${EXPANDED_FRAME.insetPx}px))`;
|
|
32425
32478
|
|
|
32426
32479
|
// ../design/dist/rendering/rewrite-imports.js
|
|
32427
32480
|
var WIRE_EXPORTS = [
|
|
@@ -32436,6 +32489,11 @@
|
|
|
32436
32489
|
"useGguiContext",
|
|
32437
32490
|
"useContract",
|
|
32438
32491
|
"useWireContext",
|
|
32492
|
+
// ggui#1223: a `oneShot` action's spent state, as data. It is served here
|
|
32493
|
+
// one release BEFORE the triad teaches it, because a card that imports a name
|
|
32494
|
+
// its runtime's shim lacks fails at module link. A card generated to use it
|
|
32495
|
+
// must never meet a runtime without it.
|
|
32496
|
+
"useActionSpent",
|
|
32439
32497
|
// Provider component
|
|
32440
32498
|
"GguiWireProvider"
|
|
32441
32499
|
];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ggui-ai/ui-visual-tester",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.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.24.0",
|
|
57
|
+
"@ggui-ai/protocol": "0.24.0",
|
|
58
|
+
"@ggui-ai/wire": "0.24.0"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@playwright/test": "^1.60.0",
|