@kiwa-test/component 0.2.0 → 0.4.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/LICENSE +21 -0
- package/dist/index.cjs +666 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +198 -1
- package/dist/index.d.ts +198 -1
- package/dist/index.js +628 -1
- package/dist/index.js.map +1 -1
- package/package.json +18 -12
package/dist/index.cjs
CHANGED
|
@@ -20,25 +20,62 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
COMPONENT_AXIS_TO_EVENTS: () => COMPONENT_AXIS_TO_EVENTS,
|
|
23
24
|
addHandler: () => addHandler,
|
|
24
25
|
appendChild: () => appendChild,
|
|
26
|
+
applyOptimisticUpdate: () => applyOptimisticUpdate,
|
|
27
|
+
applyReactActionOptimistic: () => applyOptimisticUpdate2,
|
|
28
|
+
assertAnimation: () => assertAnimation,
|
|
29
|
+
assertMode: () => assertMode,
|
|
30
|
+
assertStaticBoundary: () => assertStaticBoundary,
|
|
31
|
+
beginActionTransition: () => beginActionTransition,
|
|
32
|
+
beginIslandHydration: () => beginIslandHydration,
|
|
33
|
+
beginRscRender: () => beginRscRender,
|
|
34
|
+
bootstrapIslandsRoute: () => bootstrapIslandsRoute,
|
|
25
35
|
buildButton: () => buildButton,
|
|
26
36
|
buildCard: () => buildCard,
|
|
27
37
|
buildForm: () => buildForm,
|
|
28
38
|
buildInput: () => buildInput,
|
|
29
39
|
buildModal: () => buildModal,
|
|
40
|
+
captureErrorBoundary: () => captureErrorBoundary,
|
|
41
|
+
collectFidelityCoverage: () => collectFidelityCoverage,
|
|
42
|
+
completeRscRender: () => completeRscRender,
|
|
43
|
+
completeSelectiveHydration: () => completeSelectiveHydration,
|
|
30
44
|
componentFixtures: () => componentFixtures,
|
|
31
45
|
createCanvas: () => createCanvas,
|
|
32
46
|
createChromaticVisualMock: () => createChromaticVisualMock,
|
|
33
47
|
createNode: () => createNode,
|
|
34
48
|
createPlaywrightCTMock: () => createPlaywrightCTMock,
|
|
35
49
|
createStoryRegistry: () => createStoryRegistry,
|
|
50
|
+
enableProgressiveEnhancement: () => enableProgressiveEnhancement,
|
|
51
|
+
enterSuspenseBoundary: () => enterSuspenseBoundary,
|
|
52
|
+
failRscRender: () => failRscRender,
|
|
36
53
|
findByRole: () => findByRole,
|
|
37
54
|
findByText: () => findByText,
|
|
55
|
+
finishElementTransition: () => finishElementTransition,
|
|
38
56
|
fireEvent: () => fireEvent,
|
|
39
57
|
hashMarkup: () => hashMarkup,
|
|
58
|
+
initializeReactActions: () => initializeReactActions,
|
|
59
|
+
markFormStatusPending: () => markFormStatusPending,
|
|
60
|
+
markIslandInteractive: () => markIslandInteractive,
|
|
61
|
+
markSuspensePending: () => markSuspensePending,
|
|
62
|
+
providerEventName: () => providerEventName,
|
|
40
63
|
query: () => query,
|
|
41
|
-
|
|
64
|
+
registerIsland: () => registerIsland,
|
|
65
|
+
rejectFormAction: () => rejectFormAction,
|
|
66
|
+
renderMarkup: () => renderMarkup,
|
|
67
|
+
resolveAction: () => resolveAction,
|
|
68
|
+
resolveAllModes: () => resolveAllModes,
|
|
69
|
+
resolveFormAction: () => resolveFormAction,
|
|
70
|
+
resolveMode: () => resolveMode,
|
|
71
|
+
startDocumentTransition: () => startDocumentTransition,
|
|
72
|
+
startElementTransition: () => startElementTransition,
|
|
73
|
+
startFormActionSession: () => startFormActionSession,
|
|
74
|
+
startProgressiveHydration: () => startProgressiveHydration,
|
|
75
|
+
startRscHarness: () => startRscHarness,
|
|
76
|
+
startStreamingSsr: () => startStreamingSsr,
|
|
77
|
+
startViewTransitionSession: () => startViewTransitionSession,
|
|
78
|
+
streamHtmlChunk: () => streamHtmlChunk
|
|
42
79
|
});
|
|
43
80
|
module.exports = __toCommonJS(index_exports);
|
|
44
81
|
|
|
@@ -777,26 +814,653 @@ var componentFixtures = {
|
|
|
777
814
|
Modal: buildModal,
|
|
778
815
|
Card: buildCard
|
|
779
816
|
};
|
|
817
|
+
|
|
818
|
+
// src/semantics/types.ts
|
|
819
|
+
var dialect = {
|
|
820
|
+
storybook8: {
|
|
821
|
+
"rsc.render_started": "storybook.play.start",
|
|
822
|
+
"rsc.suspense_boundary": "storybook.suspense.fallback",
|
|
823
|
+
"rsc.html_chunk_streamed": "storybook.stream.chunk",
|
|
824
|
+
"rsc.render_completed": "storybook.play.done",
|
|
825
|
+
"ssr.suspense_pending": "storybook.suspense.pending",
|
|
826
|
+
"ssr.error_boundary_captured": "storybook.error.boundary",
|
|
827
|
+
"ssr.progressive_hydration_started": "storybook.hydration.progressive",
|
|
828
|
+
"ssr.selective_hydration_completed": "storybook.hydration.selective",
|
|
829
|
+
"transition.element_started": "storybook.transition.element.start",
|
|
830
|
+
"transition.element_finished": "storybook.transition.element.finish",
|
|
831
|
+
"transition.document_started": "storybook.transition.document.start",
|
|
832
|
+
"transition.animation_asserted": "storybook.animation.assert",
|
|
833
|
+
"form.status_pending": "storybook.form.pending",
|
|
834
|
+
"form.optimistic_applied": "storybook.form.optimistic",
|
|
835
|
+
"form.progressive_enhanced": "storybook.form.enhanced",
|
|
836
|
+
"form.action_resolved": "storybook.form.resolved"
|
|
837
|
+
},
|
|
838
|
+
"playwright-ct": {
|
|
839
|
+
"rsc.render_started": "pwct.mount.rsc.start",
|
|
840
|
+
"rsc.suspense_boundary": "pwct.locator.suspense.fallback",
|
|
841
|
+
"rsc.html_chunk_streamed": "pwct.response.chunk",
|
|
842
|
+
"rsc.render_completed": "pwct.mount.rsc.done",
|
|
843
|
+
"ssr.suspense_pending": "pwct.suspense.pending",
|
|
844
|
+
"ssr.error_boundary_captured": "pwct.error.boundary",
|
|
845
|
+
"ssr.progressive_hydration_started": "pwct.hydration.progressive",
|
|
846
|
+
"ssr.selective_hydration_completed": "pwct.hydration.selective",
|
|
847
|
+
"transition.element_started": "pwct.transition.element.start",
|
|
848
|
+
"transition.element_finished": "pwct.transition.element.finish",
|
|
849
|
+
"transition.document_started": "pwct.transition.document.start",
|
|
850
|
+
"transition.animation_asserted": "pwct.animation.assert",
|
|
851
|
+
"form.status_pending": "pwct.form.pending",
|
|
852
|
+
"form.optimistic_applied": "pwct.form.optimistic",
|
|
853
|
+
"form.progressive_enhanced": "pwct.form.enhanced",
|
|
854
|
+
"form.action_resolved": "pwct.form.resolved"
|
|
855
|
+
},
|
|
856
|
+
chromatic: {
|
|
857
|
+
"rsc.render_started": "chromatic.capture.rsc.start",
|
|
858
|
+
"rsc.suspense_boundary": "chromatic.capture.suspense",
|
|
859
|
+
"rsc.html_chunk_streamed": "chromatic.capture.chunk",
|
|
860
|
+
"rsc.render_completed": "chromatic.capture.rsc.done",
|
|
861
|
+
"ssr.suspense_pending": "chromatic.suspense.pending",
|
|
862
|
+
"ssr.error_boundary_captured": "chromatic.error.snapshot",
|
|
863
|
+
"ssr.progressive_hydration_started": "chromatic.hydration.progressive",
|
|
864
|
+
"ssr.selective_hydration_completed": "chromatic.hydration.selective",
|
|
865
|
+
"transition.element_started": "chromatic.transition.element.start",
|
|
866
|
+
"transition.element_finished": "chromatic.transition.element.finish",
|
|
867
|
+
"transition.document_started": "chromatic.transition.document.start",
|
|
868
|
+
"transition.animation_asserted": "chromatic.animation.assert",
|
|
869
|
+
"form.status_pending": "chromatic.form.pending",
|
|
870
|
+
"form.optimistic_applied": "chromatic.form.optimistic",
|
|
871
|
+
"form.progressive_enhanced": "chromatic.form.enhanced",
|
|
872
|
+
"form.action_resolved": "chromatic.form.resolved"
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
function providerEventName(target, neutral) {
|
|
876
|
+
return dialect[target][neutral] ?? neutral;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
// src/semantics/rsc-harness.ts
|
|
880
|
+
function startRscHarness(input) {
|
|
881
|
+
if (input.componentId.length === 0) {
|
|
882
|
+
throw new Error("startRscHarness: componentId must not be empty");
|
|
883
|
+
}
|
|
884
|
+
return {
|
|
885
|
+
target: input.target,
|
|
886
|
+
componentId: input.componentId,
|
|
887
|
+
state: "idle",
|
|
888
|
+
chunks: [],
|
|
889
|
+
suspenseFallback: input.suspenseFallback ?? null,
|
|
890
|
+
history: [],
|
|
891
|
+
error: null
|
|
892
|
+
};
|
|
893
|
+
}
|
|
894
|
+
function beginRscRender(session) {
|
|
895
|
+
if (session.state !== "idle") {
|
|
896
|
+
throw new Error(`beginRscRender: session is ${session.state}, not idle`);
|
|
897
|
+
}
|
|
898
|
+
session.state = "rendering";
|
|
899
|
+
return emit(session, "rsc.render_started", { componentId: session.componentId });
|
|
900
|
+
}
|
|
901
|
+
function enterSuspenseBoundary(session, fallback = session.suspenseFallback ?? '<template data-suspense="pending"></template>') {
|
|
902
|
+
if (session.state !== "rendering") {
|
|
903
|
+
throw new Error(`enterSuspenseBoundary: session is ${session.state}, not rendering`);
|
|
904
|
+
}
|
|
905
|
+
session.state = "suspended";
|
|
906
|
+
session.suspenseFallback = fallback;
|
|
907
|
+
return emit(session, "rsc.suspense_boundary", { fallback });
|
|
908
|
+
}
|
|
909
|
+
function streamHtmlChunk(session, chunk) {
|
|
910
|
+
if (session.state !== "rendering" && session.state !== "suspended" && session.state !== "streaming") {
|
|
911
|
+
throw new Error(`streamHtmlChunk: session is ${session.state}, cannot stream`);
|
|
912
|
+
}
|
|
913
|
+
if (chunk.length === 0) {
|
|
914
|
+
throw new Error("streamHtmlChunk: chunk must not be empty");
|
|
915
|
+
}
|
|
916
|
+
session.state = "streaming";
|
|
917
|
+
session.chunks.push(chunk);
|
|
918
|
+
return emit(session, "rsc.html_chunk_streamed", {
|
|
919
|
+
chunk,
|
|
920
|
+
chunkIndex: session.chunks.length - 1,
|
|
921
|
+
bytes: chunk.length
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
function completeRscRender(session) {
|
|
925
|
+
if (session.state !== "rendering" && session.state !== "suspended" && session.state !== "streaming") {
|
|
926
|
+
throw new Error(`completeRscRender: session is ${session.state}, cannot complete`);
|
|
927
|
+
}
|
|
928
|
+
session.state = "completed";
|
|
929
|
+
return emit(session, "rsc.render_completed", {
|
|
930
|
+
chunkCount: session.chunks.length,
|
|
931
|
+
html: session.chunks.join("")
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
function failRscRender(session, error) {
|
|
935
|
+
if (session.state === "completed") {
|
|
936
|
+
throw new Error("failRscRender: completed session cannot fail");
|
|
937
|
+
}
|
|
938
|
+
session.state = "errored";
|
|
939
|
+
session.error = typeof error === "string" ? error : error.message;
|
|
940
|
+
return emit(session, "ssr.error_boundary_captured", {
|
|
941
|
+
componentId: session.componentId,
|
|
942
|
+
error: session.error
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
function emit(session, neutralEvent, metadata) {
|
|
946
|
+
const step = {
|
|
947
|
+
neutralEvent,
|
|
948
|
+
providerEvent: providerEventName(session.target, neutralEvent),
|
|
949
|
+
state: session.state,
|
|
950
|
+
amountCents: 0,
|
|
951
|
+
metadata: { target: session.target, ...metadata }
|
|
952
|
+
};
|
|
953
|
+
session.history.push(step);
|
|
954
|
+
return step;
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
// src/semantics/streaming-ssr.ts
|
|
958
|
+
function startStreamingSsr(input) {
|
|
959
|
+
if (input.routeId.length === 0) {
|
|
960
|
+
throw new Error("startStreamingSsr: routeId must not be empty");
|
|
961
|
+
}
|
|
962
|
+
return {
|
|
963
|
+
target: input.target,
|
|
964
|
+
routeId: input.routeId,
|
|
965
|
+
state: "idle",
|
|
966
|
+
pendingBoundaries: /* @__PURE__ */ new Set(),
|
|
967
|
+
hydratedBoundaries: /* @__PURE__ */ new Set(),
|
|
968
|
+
errors: [],
|
|
969
|
+
history: []
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
function markSuspensePending(session, boundaryId) {
|
|
973
|
+
assertBoundaryId(boundaryId);
|
|
974
|
+
session.state = "suspense-pending";
|
|
975
|
+
session.pendingBoundaries.add(boundaryId);
|
|
976
|
+
return emit2(session, "ssr.suspense_pending", { boundaryId, pendingCount: session.pendingBoundaries.size });
|
|
977
|
+
}
|
|
978
|
+
function captureErrorBoundary(session, input) {
|
|
979
|
+
assertBoundaryId(input.boundaryId);
|
|
980
|
+
const message = typeof input.error === "string" ? input.error : input.error.message;
|
|
981
|
+
session.state = "error-captured";
|
|
982
|
+
session.errors.push({ boundaryId: input.boundaryId, message });
|
|
983
|
+
if (input.recoverable === false) {
|
|
984
|
+
session.pendingBoundaries.delete(input.boundaryId);
|
|
985
|
+
}
|
|
986
|
+
return emit2(session, "ssr.error_boundary_captured", {
|
|
987
|
+
boundaryId: input.boundaryId,
|
|
988
|
+
message,
|
|
989
|
+
recoverable: input.recoverable ?? true
|
|
990
|
+
});
|
|
991
|
+
}
|
|
992
|
+
function startProgressiveHydration(session, boundaryId) {
|
|
993
|
+
assertBoundaryId(boundaryId);
|
|
994
|
+
if (!session.pendingBoundaries.has(boundaryId)) {
|
|
995
|
+
throw new Error(`startProgressiveHydration: ${boundaryId} is not pending`);
|
|
996
|
+
}
|
|
997
|
+
session.state = "progressive-hydrating";
|
|
998
|
+
return emit2(session, "ssr.progressive_hydration_started", { boundaryId });
|
|
999
|
+
}
|
|
1000
|
+
function completeSelectiveHydration(session, boundaryId) {
|
|
1001
|
+
assertBoundaryId(boundaryId);
|
|
1002
|
+
if (!session.pendingBoundaries.has(boundaryId)) {
|
|
1003
|
+
throw new Error(`completeSelectiveHydration: ${boundaryId} is not pending`);
|
|
1004
|
+
}
|
|
1005
|
+
session.pendingBoundaries.delete(boundaryId);
|
|
1006
|
+
session.hydratedBoundaries.add(boundaryId);
|
|
1007
|
+
session.state = "selective-hydrated";
|
|
1008
|
+
return emit2(session, "ssr.selective_hydration_completed", {
|
|
1009
|
+
boundaryId,
|
|
1010
|
+
hydratedCount: session.hydratedBoundaries.size,
|
|
1011
|
+
remainingPending: session.pendingBoundaries.size
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
function assertBoundaryId(boundaryId) {
|
|
1015
|
+
if (boundaryId.length === 0) {
|
|
1016
|
+
throw new Error("boundaryId must not be empty");
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
function emit2(session, neutralEvent, metadata) {
|
|
1020
|
+
const step = {
|
|
1021
|
+
neutralEvent,
|
|
1022
|
+
providerEvent: providerEventName(session.target, neutralEvent),
|
|
1023
|
+
state: session.state,
|
|
1024
|
+
amountCents: 0,
|
|
1025
|
+
metadata: { target: session.target, routeId: session.routeId, ...metadata }
|
|
1026
|
+
};
|
|
1027
|
+
session.history.push(step);
|
|
1028
|
+
return step;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
// src/semantics/view-transitions.ts
|
|
1032
|
+
function startViewTransitionSession(input) {
|
|
1033
|
+
if (input.transitionId.length === 0) {
|
|
1034
|
+
throw new Error("startViewTransitionSession: transitionId must not be empty");
|
|
1035
|
+
}
|
|
1036
|
+
return {
|
|
1037
|
+
target: input.target,
|
|
1038
|
+
transitionId: input.transitionId,
|
|
1039
|
+
state: "idle",
|
|
1040
|
+
activeElements: /* @__PURE__ */ new Set(),
|
|
1041
|
+
documentTransition: null,
|
|
1042
|
+
assertions: [],
|
|
1043
|
+
history: []
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
1046
|
+
function startElementTransition(session, input) {
|
|
1047
|
+
if (input.elementId.length === 0) {
|
|
1048
|
+
throw new Error("startElementTransition: elementId must not be empty");
|
|
1049
|
+
}
|
|
1050
|
+
session.state = "element-transitioning";
|
|
1051
|
+
session.activeElements.add(input.elementId);
|
|
1052
|
+
return emit3(session, "transition.element_started", input);
|
|
1053
|
+
}
|
|
1054
|
+
function finishElementTransition(session, elementId) {
|
|
1055
|
+
if (!session.activeElements.has(elementId)) {
|
|
1056
|
+
throw new Error(`finishElementTransition: ${elementId} is not active`);
|
|
1057
|
+
}
|
|
1058
|
+
session.activeElements.delete(elementId);
|
|
1059
|
+
session.state = session.activeElements.size === 0 ? "finished" : "element-transitioning";
|
|
1060
|
+
return emit3(session, "transition.element_finished", {
|
|
1061
|
+
elementId,
|
|
1062
|
+
remaining: session.activeElements.size
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
function startDocumentTransition(session, input) {
|
|
1066
|
+
if (input.name.length === 0) {
|
|
1067
|
+
throw new Error("startDocumentTransition: name must not be empty");
|
|
1068
|
+
}
|
|
1069
|
+
session.state = "document-transitioning";
|
|
1070
|
+
session.documentTransition = input.name;
|
|
1071
|
+
return emit3(session, "transition.document_started", input);
|
|
1072
|
+
}
|
|
1073
|
+
function assertAnimation(session, input) {
|
|
1074
|
+
if (input.durationMs < 0) {
|
|
1075
|
+
throw new Error("assertAnimation: durationMs must be >= 0");
|
|
1076
|
+
}
|
|
1077
|
+
session.state = "asserted";
|
|
1078
|
+
session.assertions.push(input.assertionId);
|
|
1079
|
+
return emit3(session, "transition.animation_asserted", {
|
|
1080
|
+
assertionId: input.assertionId,
|
|
1081
|
+
durationMs: input.durationMs,
|
|
1082
|
+
easing: input.easing ?? "linear"
|
|
1083
|
+
});
|
|
1084
|
+
}
|
|
1085
|
+
function emit3(session, neutralEvent, metadata) {
|
|
1086
|
+
const step = {
|
|
1087
|
+
neutralEvent,
|
|
1088
|
+
providerEvent: providerEventName(session.target, neutralEvent),
|
|
1089
|
+
state: session.state,
|
|
1090
|
+
amountCents: 0,
|
|
1091
|
+
metadata: { target: session.target, transitionId: session.transitionId, ...metadata }
|
|
1092
|
+
};
|
|
1093
|
+
session.history.push(step);
|
|
1094
|
+
return step;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
// src/semantics/form-action-advanced.ts
|
|
1098
|
+
function startFormActionSession(input) {
|
|
1099
|
+
if (input.formId.length === 0) {
|
|
1100
|
+
throw new Error("startFormActionSession: formId must not be empty");
|
|
1101
|
+
}
|
|
1102
|
+
return {
|
|
1103
|
+
target: input.target,
|
|
1104
|
+
formId: input.formId,
|
|
1105
|
+
state: "idle",
|
|
1106
|
+
form: { ...input.initial },
|
|
1107
|
+
optimisticPatches: [],
|
|
1108
|
+
enhanced: false,
|
|
1109
|
+
history: [],
|
|
1110
|
+
error: null
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1113
|
+
function markFormStatusPending(session, submitter) {
|
|
1114
|
+
if (session.state === "pending") {
|
|
1115
|
+
throw new Error("markFormStatusPending: form is already pending");
|
|
1116
|
+
}
|
|
1117
|
+
session.state = "pending";
|
|
1118
|
+
return emit4(session, "form.status_pending", { submitter });
|
|
1119
|
+
}
|
|
1120
|
+
function applyOptimisticUpdate(session, patch) {
|
|
1121
|
+
if (session.state !== "pending" && session.state !== "optimistic") {
|
|
1122
|
+
throw new Error(`applyOptimisticUpdate: session is ${session.state}, not pending`);
|
|
1123
|
+
}
|
|
1124
|
+
session.state = "optimistic";
|
|
1125
|
+
session.optimisticPatches.push(patch);
|
|
1126
|
+
session.form = { ...session.form, ...patch };
|
|
1127
|
+
return emit4(session, "form.optimistic_applied", {
|
|
1128
|
+
patchKeys: Object.keys(patch).join(","),
|
|
1129
|
+
patchCount: session.optimisticPatches.length
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
function enableProgressiveEnhancement(session, input) {
|
|
1133
|
+
if (input.actionUrl.length === 0) {
|
|
1134
|
+
throw new Error("enableProgressiveEnhancement: actionUrl must not be empty");
|
|
1135
|
+
}
|
|
1136
|
+
session.enhanced = true;
|
|
1137
|
+
session.state = "enhanced";
|
|
1138
|
+
return emit4(session, "form.progressive_enhanced", {
|
|
1139
|
+
method: input.method ?? "post",
|
|
1140
|
+
actionUrl: input.actionUrl
|
|
1141
|
+
});
|
|
1142
|
+
}
|
|
1143
|
+
function resolveFormAction(session, result) {
|
|
1144
|
+
if (session.state === "idle") {
|
|
1145
|
+
throw new Error("resolveFormAction: action was not submitted");
|
|
1146
|
+
}
|
|
1147
|
+
session.state = "resolved";
|
|
1148
|
+
session.form = { ...session.form, ...result };
|
|
1149
|
+
return emit4(session, "form.action_resolved", {
|
|
1150
|
+
resultKeys: Object.keys(result).join(","),
|
|
1151
|
+
enhanced: session.enhanced
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
1154
|
+
function rejectFormAction(session, error) {
|
|
1155
|
+
if (session.state === "resolved") {
|
|
1156
|
+
throw new Error("rejectFormAction: resolved action cannot reject");
|
|
1157
|
+
}
|
|
1158
|
+
session.state = "rejected";
|
|
1159
|
+
session.error = typeof error === "string" ? error : error.message;
|
|
1160
|
+
return emit4(session, "form.action_resolved", {
|
|
1161
|
+
rejected: true,
|
|
1162
|
+
error: session.error
|
|
1163
|
+
});
|
|
1164
|
+
}
|
|
1165
|
+
function emit4(session, neutralEvent, metadata) {
|
|
1166
|
+
const step = {
|
|
1167
|
+
neutralEvent,
|
|
1168
|
+
providerEvent: providerEventName(session.target, neutralEvent),
|
|
1169
|
+
state: session.state,
|
|
1170
|
+
amountCents: 0,
|
|
1171
|
+
metadata: { target: session.target, formId: session.formId, ...metadata }
|
|
1172
|
+
};
|
|
1173
|
+
session.history.push(step);
|
|
1174
|
+
return step;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
// src/semantics/fidelity.ts
|
|
1178
|
+
var COMPONENT_AXIS_TO_EVENTS = {
|
|
1179
|
+
"rsc-harness": [
|
|
1180
|
+
"rsc.render_started",
|
|
1181
|
+
"rsc.suspense_boundary",
|
|
1182
|
+
"rsc.html_chunk_streamed",
|
|
1183
|
+
"rsc.render_completed"
|
|
1184
|
+
],
|
|
1185
|
+
"streaming-ssr": [
|
|
1186
|
+
"ssr.suspense_pending",
|
|
1187
|
+
"ssr.error_boundary_captured",
|
|
1188
|
+
"ssr.progressive_hydration_started",
|
|
1189
|
+
"ssr.selective_hydration_completed"
|
|
1190
|
+
],
|
|
1191
|
+
"view-transitions": [
|
|
1192
|
+
"transition.element_started",
|
|
1193
|
+
"transition.element_finished",
|
|
1194
|
+
"transition.document_started",
|
|
1195
|
+
"transition.animation_asserted"
|
|
1196
|
+
],
|
|
1197
|
+
"form-action-advanced": [
|
|
1198
|
+
"form.status_pending",
|
|
1199
|
+
"form.optimistic_applied",
|
|
1200
|
+
"form.progressive_enhanced",
|
|
1201
|
+
"form.action_resolved"
|
|
1202
|
+
],
|
|
1203
|
+
// v1.49 advanced III
|
|
1204
|
+
"react-19-actions": [
|
|
1205
|
+
"action.state_initialized",
|
|
1206
|
+
"action.transition_pending",
|
|
1207
|
+
"action.optimistic_committed",
|
|
1208
|
+
"action.resolved"
|
|
1209
|
+
],
|
|
1210
|
+
"islands-architecture": [
|
|
1211
|
+
"islands.registered",
|
|
1212
|
+
"islands.hydration_started",
|
|
1213
|
+
"islands.interactive_ready",
|
|
1214
|
+
"islands.static_boundary_asserted"
|
|
1215
|
+
]
|
|
1216
|
+
};
|
|
1217
|
+
function collectFidelityCoverage(providers = ["storybook8", "playwright-ct", "chromatic"]) {
|
|
1218
|
+
const axes = Object.keys(COMPONENT_AXIS_TO_EVENTS);
|
|
1219
|
+
const rows = [];
|
|
1220
|
+
for (const provider of providers) {
|
|
1221
|
+
for (const axis of axes) {
|
|
1222
|
+
const neutralEvents = COMPONENT_AXIS_TO_EVENTS[axis];
|
|
1223
|
+
rows.push({
|
|
1224
|
+
provider,
|
|
1225
|
+
axis,
|
|
1226
|
+
neutralEvents,
|
|
1227
|
+
providerEvents: neutralEvents.map((event) => providerEventName(provider, event))
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
return { providers, axes, rows };
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
// src/semantics/react-19-actions.ts
|
|
1235
|
+
function emit5(session, neutralEvent, metadata) {
|
|
1236
|
+
const step = {
|
|
1237
|
+
neutralEvent,
|
|
1238
|
+
providerEvent: providerEventName(session.target, neutralEvent),
|
|
1239
|
+
state: session.state,
|
|
1240
|
+
amountCents: 0,
|
|
1241
|
+
metadata: { actionId: session.actionId, ...metadata }
|
|
1242
|
+
};
|
|
1243
|
+
session.history.push(step);
|
|
1244
|
+
return step;
|
|
1245
|
+
}
|
|
1246
|
+
function initializeReactActions(input) {
|
|
1247
|
+
if (input.actionId.length === 0) {
|
|
1248
|
+
throw new Error("initializeReactActions: actionId must not be empty");
|
|
1249
|
+
}
|
|
1250
|
+
const session = {
|
|
1251
|
+
target: input.target,
|
|
1252
|
+
actionId: input.actionId,
|
|
1253
|
+
state: "idle",
|
|
1254
|
+
pendingCount: 0,
|
|
1255
|
+
optimisticValues: [],
|
|
1256
|
+
resolvedValue: null,
|
|
1257
|
+
history: []
|
|
1258
|
+
};
|
|
1259
|
+
emit5(session, "action.state_initialized", { pendingCount: 0 });
|
|
1260
|
+
return session;
|
|
1261
|
+
}
|
|
1262
|
+
function beginActionTransition(session) {
|
|
1263
|
+
if (session.state !== "idle" && session.state !== "resolved") {
|
|
1264
|
+
throw new Error(`beginActionTransition: session is ${session.state}`);
|
|
1265
|
+
}
|
|
1266
|
+
session.state = "transition-pending";
|
|
1267
|
+
session.pendingCount += 1;
|
|
1268
|
+
return emit5(session, "action.transition_pending", {
|
|
1269
|
+
pendingCount: session.pendingCount
|
|
1270
|
+
});
|
|
1271
|
+
}
|
|
1272
|
+
function applyOptimisticUpdate2(session, optimisticValue) {
|
|
1273
|
+
if (session.state !== "transition-pending") {
|
|
1274
|
+
throw new Error(`applyOptimisticUpdate: session is ${session.state}`);
|
|
1275
|
+
}
|
|
1276
|
+
session.state = "optimistic-committed";
|
|
1277
|
+
session.optimisticValues.push(optimisticValue);
|
|
1278
|
+
return emit5(session, "action.optimistic_committed", { optimisticValue });
|
|
1279
|
+
}
|
|
1280
|
+
function resolveAction(session, resolvedValue) {
|
|
1281
|
+
if (session.state !== "transition-pending" && session.state !== "optimistic-committed") {
|
|
1282
|
+
throw new Error(`resolveAction: session is ${session.state}`);
|
|
1283
|
+
}
|
|
1284
|
+
session.state = "resolved";
|
|
1285
|
+
session.resolvedValue = resolvedValue;
|
|
1286
|
+
session.pendingCount = Math.max(0, session.pendingCount - 1);
|
|
1287
|
+
return emit5(session, "action.resolved", {
|
|
1288
|
+
resolvedValue,
|
|
1289
|
+
pendingCount: session.pendingCount,
|
|
1290
|
+
optimisticCount: session.optimisticValues.length
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
// src/semantics/islands-architecture.ts
|
|
1295
|
+
function emit6(session, neutralEvent, metadata) {
|
|
1296
|
+
const step = {
|
|
1297
|
+
neutralEvent,
|
|
1298
|
+
providerEvent: providerEventName(session.target, neutralEvent),
|
|
1299
|
+
state: session.state,
|
|
1300
|
+
amountCents: 0,
|
|
1301
|
+
metadata: { routeId: session.routeId, ...metadata }
|
|
1302
|
+
};
|
|
1303
|
+
session.history.push(step);
|
|
1304
|
+
return step;
|
|
1305
|
+
}
|
|
1306
|
+
function bootstrapIslandsRoute(input) {
|
|
1307
|
+
if (input.routeId.length === 0) {
|
|
1308
|
+
throw new Error("bootstrapIslandsRoute: routeId must not be empty");
|
|
1309
|
+
}
|
|
1310
|
+
return {
|
|
1311
|
+
target: input.target,
|
|
1312
|
+
routeId: input.routeId,
|
|
1313
|
+
islands: [],
|
|
1314
|
+
state: "idle",
|
|
1315
|
+
hydratedIslandIds: [],
|
|
1316
|
+
staticBoundaryIds: [],
|
|
1317
|
+
history: []
|
|
1318
|
+
};
|
|
1319
|
+
}
|
|
1320
|
+
function registerIsland(session, island) {
|
|
1321
|
+
session.islands.push(island);
|
|
1322
|
+
session.state = "registered";
|
|
1323
|
+
return emit6(session, "islands.registered", {
|
|
1324
|
+
islandId: island.islandId,
|
|
1325
|
+
loadStrategy: island.loadStrategy,
|
|
1326
|
+
interactiveBoundary: island.interactiveBoundary
|
|
1327
|
+
});
|
|
1328
|
+
}
|
|
1329
|
+
function beginIslandHydration(session, islandId) {
|
|
1330
|
+
const island = session.islands.find((i) => i.islandId === islandId);
|
|
1331
|
+
if (!island) {
|
|
1332
|
+
throw new Error(`beginIslandHydration: island ${islandId} not registered`);
|
|
1333
|
+
}
|
|
1334
|
+
if (session.state !== "registered" && session.state !== "hydrating") {
|
|
1335
|
+
throw new Error(`beginIslandHydration: session is ${session.state}`);
|
|
1336
|
+
}
|
|
1337
|
+
session.state = "hydrating";
|
|
1338
|
+
return emit6(session, "islands.hydration_started", {
|
|
1339
|
+
islandId,
|
|
1340
|
+
loadStrategy: island.loadStrategy
|
|
1341
|
+
});
|
|
1342
|
+
}
|
|
1343
|
+
function markIslandInteractive(session, islandId) {
|
|
1344
|
+
if (session.state !== "hydrating") {
|
|
1345
|
+
throw new Error(`markIslandInteractive: session is ${session.state}`);
|
|
1346
|
+
}
|
|
1347
|
+
if (session.hydratedIslandIds.includes(islandId)) {
|
|
1348
|
+
throw new Error(`markIslandInteractive: island ${islandId} already interactive`);
|
|
1349
|
+
}
|
|
1350
|
+
session.hydratedIslandIds.push(islandId);
|
|
1351
|
+
const allHydrated = session.hydratedIslandIds.length === session.islands.filter((i) => i.interactiveBoundary).length;
|
|
1352
|
+
if (allHydrated) {
|
|
1353
|
+
session.state = "interactive";
|
|
1354
|
+
}
|
|
1355
|
+
return emit6(session, "islands.interactive_ready", {
|
|
1356
|
+
islandId,
|
|
1357
|
+
hydratedCount: session.hydratedIslandIds.length,
|
|
1358
|
+
allInteractiveReady: allHydrated
|
|
1359
|
+
});
|
|
1360
|
+
}
|
|
1361
|
+
function assertStaticBoundary(session, boundaryId) {
|
|
1362
|
+
if (session.staticBoundaryIds.includes(boundaryId)) {
|
|
1363
|
+
throw new Error(`assertStaticBoundary: boundary ${boundaryId} already asserted`);
|
|
1364
|
+
}
|
|
1365
|
+
session.staticBoundaryIds.push(boundaryId);
|
|
1366
|
+
if (session.state === "interactive") {
|
|
1367
|
+
session.state = "static-verified";
|
|
1368
|
+
}
|
|
1369
|
+
return emit6(session, "islands.static_boundary_asserted", {
|
|
1370
|
+
boundaryId,
|
|
1371
|
+
staticBoundaryCount: session.staticBoundaryIds.length
|
|
1372
|
+
});
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
// src/real-driver.ts
|
|
1376
|
+
var TARGET_KEY_ENV = {
|
|
1377
|
+
storybook8: "STORYBOOK_URL",
|
|
1378
|
+
"playwright-ct": "PLAYWRIGHT_CT_URL",
|
|
1379
|
+
chromatic: "CHROMATIC_TOKEN"
|
|
1380
|
+
};
|
|
1381
|
+
function resolveMode(provider, env = process.env) {
|
|
1382
|
+
const rawMode = env.KIWA_MODE?.toLowerCase();
|
|
1383
|
+
if (rawMode !== void 0 && rawMode !== "real" && rawMode !== "mock") {
|
|
1384
|
+
return { provider, mode: "mock", reason: "invalid-mode" };
|
|
1385
|
+
}
|
|
1386
|
+
if (rawMode !== "real") {
|
|
1387
|
+
return { provider, mode: "mock", reason: "default-mock" };
|
|
1388
|
+
}
|
|
1389
|
+
const keyValue = env[TARGET_KEY_ENV[provider]];
|
|
1390
|
+
if (typeof keyValue !== "string" || keyValue.length === 0) {
|
|
1391
|
+
return { provider, mode: "mock", reason: "missing-key" };
|
|
1392
|
+
}
|
|
1393
|
+
return { provider, mode: "real", reason: "kiwa-mode-real" };
|
|
1394
|
+
}
|
|
1395
|
+
function resolveAllModes(env = process.env) {
|
|
1396
|
+
const providers = ["storybook8", "playwright-ct", "chromatic"];
|
|
1397
|
+
return providers.map((provider) => resolveMode(provider, env));
|
|
1398
|
+
}
|
|
1399
|
+
function assertMode(provider, expected, env = process.env) {
|
|
1400
|
+
const resolved = resolveMode(provider, env);
|
|
1401
|
+
if (resolved.mode !== expected) {
|
|
1402
|
+
throw new Error(
|
|
1403
|
+
`expected ${provider} in ${expected} mode but resolved ${resolved.mode} (${resolved.reason})`
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
780
1407
|
// Annotate the CommonJS export names for ESM import in node:
|
|
781
1408
|
0 && (module.exports = {
|
|
1409
|
+
COMPONENT_AXIS_TO_EVENTS,
|
|
782
1410
|
addHandler,
|
|
783
1411
|
appendChild,
|
|
1412
|
+
applyOptimisticUpdate,
|
|
1413
|
+
applyReactActionOptimistic,
|
|
1414
|
+
assertAnimation,
|
|
1415
|
+
assertMode,
|
|
1416
|
+
assertStaticBoundary,
|
|
1417
|
+
beginActionTransition,
|
|
1418
|
+
beginIslandHydration,
|
|
1419
|
+
beginRscRender,
|
|
1420
|
+
bootstrapIslandsRoute,
|
|
784
1421
|
buildButton,
|
|
785
1422
|
buildCard,
|
|
786
1423
|
buildForm,
|
|
787
1424
|
buildInput,
|
|
788
1425
|
buildModal,
|
|
1426
|
+
captureErrorBoundary,
|
|
1427
|
+
collectFidelityCoverage,
|
|
1428
|
+
completeRscRender,
|
|
1429
|
+
completeSelectiveHydration,
|
|
789
1430
|
componentFixtures,
|
|
790
1431
|
createCanvas,
|
|
791
1432
|
createChromaticVisualMock,
|
|
792
1433
|
createNode,
|
|
793
1434
|
createPlaywrightCTMock,
|
|
794
1435
|
createStoryRegistry,
|
|
1436
|
+
enableProgressiveEnhancement,
|
|
1437
|
+
enterSuspenseBoundary,
|
|
1438
|
+
failRscRender,
|
|
795
1439
|
findByRole,
|
|
796
1440
|
findByText,
|
|
1441
|
+
finishElementTransition,
|
|
797
1442
|
fireEvent,
|
|
798
1443
|
hashMarkup,
|
|
1444
|
+
initializeReactActions,
|
|
1445
|
+
markFormStatusPending,
|
|
1446
|
+
markIslandInteractive,
|
|
1447
|
+
markSuspensePending,
|
|
1448
|
+
providerEventName,
|
|
799
1449
|
query,
|
|
800
|
-
|
|
1450
|
+
registerIsland,
|
|
1451
|
+
rejectFormAction,
|
|
1452
|
+
renderMarkup,
|
|
1453
|
+
resolveAction,
|
|
1454
|
+
resolveAllModes,
|
|
1455
|
+
resolveFormAction,
|
|
1456
|
+
resolveMode,
|
|
1457
|
+
startDocumentTransition,
|
|
1458
|
+
startElementTransition,
|
|
1459
|
+
startFormActionSession,
|
|
1460
|
+
startProgressiveHydration,
|
|
1461
|
+
startRscHarness,
|
|
1462
|
+
startStreamingSsr,
|
|
1463
|
+
startViewTransitionSession,
|
|
1464
|
+
streamHtmlChunk
|
|
801
1465
|
});
|
|
802
1466
|
//# sourceMappingURL=index.cjs.map
|