@kiwa-test/component 0.3.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/dist/index.d.ts CHANGED
@@ -539,8 +539,8 @@ declare const componentFixtures: Record<string, ComponentRender<Record<string, u
539
539
  * any of those runtimes, so the same axis can be replayed against each target.
540
540
  */
541
541
  type ComponentTarget = 'storybook8' | 'playwright-ct' | 'chromatic';
542
- type ComponentAxis = 'rsc-harness' | 'streaming-ssr' | 'view-transitions' | 'form-action-advanced';
543
- type NeutralEventName = 'rsc.render_started' | 'rsc.suspense_boundary' | 'rsc.html_chunk_streamed' | 'rsc.render_completed' | 'ssr.suspense_pending' | 'ssr.error_boundary_captured' | 'ssr.progressive_hydration_started' | 'ssr.selective_hydration_completed' | 'transition.element_started' | 'transition.element_finished' | 'transition.document_started' | 'transition.animation_asserted' | 'form.status_pending' | 'form.optimistic_applied' | 'form.progressive_enhanced' | 'form.action_resolved';
542
+ type ComponentAxis = 'rsc-harness' | 'streaming-ssr' | 'view-transitions' | 'form-action-advanced' | 'react-19-actions' | 'islands-architecture';
543
+ type NeutralEventName = 'rsc.render_started' | 'rsc.suspense_boundary' | 'rsc.html_chunk_streamed' | 'rsc.render_completed' | 'ssr.suspense_pending' | 'ssr.error_boundary_captured' | 'ssr.progressive_hydration_started' | 'ssr.selective_hydration_completed' | 'transition.element_started' | 'transition.element_finished' | 'transition.document_started' | 'transition.animation_asserted' | 'form.status_pending' | 'form.optimistic_applied' | 'form.progressive_enhanced' | 'form.action_resolved' | 'action.state_initialized' | 'action.transition_pending' | 'action.optimistic_committed' | 'action.resolved' | 'islands.registered' | 'islands.hydration_started' | 'islands.interactive_ready' | 'islands.static_boundary_asserted';
544
544
  interface AxisStep<TState extends string> {
545
545
  neutralEvent: NeutralEventName;
546
546
  providerEvent: string;
@@ -645,7 +645,7 @@ declare function startFormActionSession<TForm extends Record<string, unknown>>(i
645
645
  initial: TForm;
646
646
  }): FormActionSession<TForm>;
647
647
  declare function markFormStatusPending<TForm extends Record<string, unknown>>(session: FormActionSession<TForm>, submitter: string): AxisStep<FormActionState>;
648
- declare function applyOptimisticUpdate<TForm extends Record<string, unknown>>(session: FormActionSession<TForm>, patch: Partial<TForm>): AxisStep<FormActionState>;
648
+ declare function applyOptimisticUpdate$1<TForm extends Record<string, unknown>>(session: FormActionSession<TForm>, patch: Partial<TForm>): AxisStep<FormActionState>;
649
649
  declare function enableProgressiveEnhancement<TForm extends Record<string, unknown>>(session: FormActionSession<TForm>, input: {
650
650
  method?: 'post' | 'get';
651
651
  actionUrl: string;
@@ -667,6 +667,57 @@ interface FidelityCoverage {
667
667
  declare const COMPONENT_AXIS_TO_EVENTS: Record<ComponentAxis, NeutralEventName[]>;
668
668
  declare function collectFidelityCoverage(providers?: ComponentTarget[]): FidelityCoverage;
669
669
 
670
+ /**
671
+ * v1.49 react-19-actions axis — useActionState + useOptimistic + useFormStatus
672
+ * を統合した React 19 Actions API の deterministic state machine。
673
+ */
674
+ type ReactActionsState = 'idle' | 'transition-pending' | 'optimistic-committed' | 'resolved';
675
+ interface ReactActionsSession {
676
+ target: ComponentTarget;
677
+ actionId: string;
678
+ state: ReactActionsState;
679
+ pendingCount: number;
680
+ optimisticValues: string[];
681
+ resolvedValue: string | null;
682
+ history: AxisStep<ReactActionsState>[];
683
+ }
684
+ declare function initializeReactActions(input: {
685
+ target: ComponentTarget;
686
+ actionId: string;
687
+ }): ReactActionsSession;
688
+ declare function beginActionTransition(session: ReactActionsSession): AxisStep<ReactActionsState>;
689
+ declare function applyOptimisticUpdate(session: ReactActionsSession, optimisticValue: string): AxisStep<ReactActionsState>;
690
+ declare function resolveAction(session: ReactActionsSession, resolvedValue: string): AxisStep<ReactActionsState>;
691
+
692
+ /**
693
+ * v1.49 islands-architecture axis — Astro / Deno Fresh / Solid Start の
694
+ * Islands architecture (partial hydration + selective interactivity) を
695
+ * target-neutral に扱う state machine。
696
+ */
697
+ type IslandsState = 'idle' | 'registered' | 'hydrating' | 'interactive' | 'static-verified';
698
+ interface IslandSpec {
699
+ islandId: string;
700
+ loadStrategy: 'load' | 'idle' | 'visible' | 'media' | 'only';
701
+ interactiveBoundary: boolean;
702
+ }
703
+ interface IslandsSession {
704
+ target: ComponentTarget;
705
+ routeId: string;
706
+ islands: IslandSpec[];
707
+ state: IslandsState;
708
+ hydratedIslandIds: string[];
709
+ staticBoundaryIds: string[];
710
+ history: AxisStep<IslandsState>[];
711
+ }
712
+ declare function bootstrapIslandsRoute(input: {
713
+ target: ComponentTarget;
714
+ routeId: string;
715
+ }): IslandsSession;
716
+ declare function registerIsland(session: IslandsSession, island: IslandSpec): AxisStep<IslandsState>;
717
+ declare function beginIslandHydration(session: IslandsSession, islandId: string): AxisStep<IslandsState>;
718
+ declare function markIslandInteractive(session: IslandsSession, islandId: string): AxisStep<IslandsState>;
719
+ declare function assertStaticBoundary(session: IslandsSession, boundaryId: string): AxisStep<IslandsState>;
720
+
670
721
  type KiwaTestMode = 'mock' | 'real';
671
722
  interface ResolvedMode {
672
723
  mode: KiwaTestMode;
@@ -677,4 +728,4 @@ declare function resolveMode(provider: ComponentTarget, env?: Record<string, str
677
728
  declare function resolveAllModes(env?: Record<string, string | undefined>): ResolvedMode[];
678
729
  declare function assertMode(provider: ComponentTarget, expected: KiwaTestMode, env?: Record<string, string | undefined>): void;
679
730
 
680
- export { type A11yViolation, type AxisStep, type ButtonArgs, COMPONENT_AXIS_TO_EVENTS, type CanvasElement, type CardArgs, type ChromaticConfig, type ChromaticVisualMock, type ComponentAxis, type ComponentLocator, type ComponentProvider, type ComponentRender, type ComponentTarget, type FidelityCoverage, type FidelityRow, type FormActionSession, type FormActionState, type FormArgs, type FormField, type InputArgs, type KiwaTestMode, type MockEvent, type MockNode, type ModalArgs, type NeutralEventName, type NodeLocator, type NodeOptions, type PlayContext, type PlaywrightCTMock, type ResolvedMode, type RscHarnessSession, type RscHarnessState, type StoryEntry, type StoryMeta, type StoryMountResult, type StoryObj, type StoryParameters, type StoryPlayResult, type StoryRegistry, type StreamingSsrSession, type StreamingSsrState, type ViewTransitionSession, type ViewTransitionState, type VisualBaseline, type VisualDiff, type VisualReviewAction, type VisualReviewEntry, addHandler, appendChild, applyOptimisticUpdate, assertAnimation, assertMode, beginRscRender, buildButton, buildCard, buildForm, buildInput, buildModal, captureErrorBoundary, collectFidelityCoverage, completeRscRender, completeSelectiveHydration, componentFixtures, createCanvas, createChromaticVisualMock, createNode, createPlaywrightCTMock, createStoryRegistry, enableProgressiveEnhancement, enterSuspenseBoundary, failRscRender, findByRole, findByText, finishElementTransition, fireEvent, hashMarkup, markFormStatusPending, markSuspensePending, providerEventName, query, rejectFormAction, renderMarkup, resolveAllModes, resolveFormAction, resolveMode, startDocumentTransition, startElementTransition, startFormActionSession, startProgressiveHydration, startRscHarness, startStreamingSsr, startViewTransitionSession, streamHtmlChunk };
731
+ export { type A11yViolation, type AxisStep, type ButtonArgs, COMPONENT_AXIS_TO_EVENTS, type CanvasElement, type CardArgs, type ChromaticConfig, type ChromaticVisualMock, type ComponentAxis, type ComponentLocator, type ComponentProvider, type ComponentRender, type ComponentTarget, type FidelityCoverage, type FidelityRow, type FormActionSession, type FormActionState, type FormArgs, type FormField, type InputArgs, type IslandSpec, type IslandsSession, type IslandsState, type KiwaTestMode, type MockEvent, type MockNode, type ModalArgs, type NeutralEventName, type NodeLocator, type NodeOptions, type PlayContext, type PlaywrightCTMock, type ReactActionsSession, type ReactActionsState, type ResolvedMode, type RscHarnessSession, type RscHarnessState, type StoryEntry, type StoryMeta, type StoryMountResult, type StoryObj, type StoryParameters, type StoryPlayResult, type StoryRegistry, type StreamingSsrSession, type StreamingSsrState, type ViewTransitionSession, type ViewTransitionState, type VisualBaseline, type VisualDiff, type VisualReviewAction, type VisualReviewEntry, addHandler, appendChild, applyOptimisticUpdate$1 as applyOptimisticUpdate, applyOptimisticUpdate as applyReactActionOptimistic, assertAnimation, assertMode, assertStaticBoundary, beginActionTransition, beginIslandHydration, beginRscRender, bootstrapIslandsRoute, buildButton, buildCard, buildForm, buildInput, buildModal, captureErrorBoundary, collectFidelityCoverage, completeRscRender, completeSelectiveHydration, componentFixtures, createCanvas, createChromaticVisualMock, createNode, createPlaywrightCTMock, createStoryRegistry, enableProgressiveEnhancement, enterSuspenseBoundary, failRscRender, findByRole, findByText, finishElementTransition, fireEvent, hashMarkup, initializeReactActions, markFormStatusPending, markIslandInteractive, markSuspensePending, providerEventName, query, registerIsland, rejectFormAction, renderMarkup, resolveAction, resolveAllModes, resolveFormAction, resolveMode, startDocumentTransition, startElementTransition, startFormActionSession, startProgressiveHydration, startRscHarness, startStreamingSsr, startViewTransitionSession, streamHtmlChunk };
package/dist/index.js CHANGED
@@ -1118,6 +1118,19 @@ var COMPONENT_AXIS_TO_EVENTS = {
1118
1118
  "form.optimistic_applied",
1119
1119
  "form.progressive_enhanced",
1120
1120
  "form.action_resolved"
1121
+ ],
1122
+ // v1.49 advanced III
1123
+ "react-19-actions": [
1124
+ "action.state_initialized",
1125
+ "action.transition_pending",
1126
+ "action.optimistic_committed",
1127
+ "action.resolved"
1128
+ ],
1129
+ "islands-architecture": [
1130
+ "islands.registered",
1131
+ "islands.hydration_started",
1132
+ "islands.interactive_ready",
1133
+ "islands.static_boundary_asserted"
1121
1134
  ]
1122
1135
  };
1123
1136
  function collectFidelityCoverage(providers = ["storybook8", "playwright-ct", "chromatic"]) {
@@ -1137,6 +1150,147 @@ function collectFidelityCoverage(providers = ["storybook8", "playwright-ct", "ch
1137
1150
  return { providers, axes, rows };
1138
1151
  }
1139
1152
 
1153
+ // src/semantics/react-19-actions.ts
1154
+ function emit5(session, neutralEvent, metadata) {
1155
+ const step = {
1156
+ neutralEvent,
1157
+ providerEvent: providerEventName(session.target, neutralEvent),
1158
+ state: session.state,
1159
+ amountCents: 0,
1160
+ metadata: { actionId: session.actionId, ...metadata }
1161
+ };
1162
+ session.history.push(step);
1163
+ return step;
1164
+ }
1165
+ function initializeReactActions(input) {
1166
+ if (input.actionId.length === 0) {
1167
+ throw new Error("initializeReactActions: actionId must not be empty");
1168
+ }
1169
+ const session = {
1170
+ target: input.target,
1171
+ actionId: input.actionId,
1172
+ state: "idle",
1173
+ pendingCount: 0,
1174
+ optimisticValues: [],
1175
+ resolvedValue: null,
1176
+ history: []
1177
+ };
1178
+ emit5(session, "action.state_initialized", { pendingCount: 0 });
1179
+ return session;
1180
+ }
1181
+ function beginActionTransition(session) {
1182
+ if (session.state !== "idle" && session.state !== "resolved") {
1183
+ throw new Error(`beginActionTransition: session is ${session.state}`);
1184
+ }
1185
+ session.state = "transition-pending";
1186
+ session.pendingCount += 1;
1187
+ return emit5(session, "action.transition_pending", {
1188
+ pendingCount: session.pendingCount
1189
+ });
1190
+ }
1191
+ function applyOptimisticUpdate2(session, optimisticValue) {
1192
+ if (session.state !== "transition-pending") {
1193
+ throw new Error(`applyOptimisticUpdate: session is ${session.state}`);
1194
+ }
1195
+ session.state = "optimistic-committed";
1196
+ session.optimisticValues.push(optimisticValue);
1197
+ return emit5(session, "action.optimistic_committed", { optimisticValue });
1198
+ }
1199
+ function resolveAction(session, resolvedValue) {
1200
+ if (session.state !== "transition-pending" && session.state !== "optimistic-committed") {
1201
+ throw new Error(`resolveAction: session is ${session.state}`);
1202
+ }
1203
+ session.state = "resolved";
1204
+ session.resolvedValue = resolvedValue;
1205
+ session.pendingCount = Math.max(0, session.pendingCount - 1);
1206
+ return emit5(session, "action.resolved", {
1207
+ resolvedValue,
1208
+ pendingCount: session.pendingCount,
1209
+ optimisticCount: session.optimisticValues.length
1210
+ });
1211
+ }
1212
+
1213
+ // src/semantics/islands-architecture.ts
1214
+ function emit6(session, neutralEvent, metadata) {
1215
+ const step = {
1216
+ neutralEvent,
1217
+ providerEvent: providerEventName(session.target, neutralEvent),
1218
+ state: session.state,
1219
+ amountCents: 0,
1220
+ metadata: { routeId: session.routeId, ...metadata }
1221
+ };
1222
+ session.history.push(step);
1223
+ return step;
1224
+ }
1225
+ function bootstrapIslandsRoute(input) {
1226
+ if (input.routeId.length === 0) {
1227
+ throw new Error("bootstrapIslandsRoute: routeId must not be empty");
1228
+ }
1229
+ return {
1230
+ target: input.target,
1231
+ routeId: input.routeId,
1232
+ islands: [],
1233
+ state: "idle",
1234
+ hydratedIslandIds: [],
1235
+ staticBoundaryIds: [],
1236
+ history: []
1237
+ };
1238
+ }
1239
+ function registerIsland(session, island) {
1240
+ session.islands.push(island);
1241
+ session.state = "registered";
1242
+ return emit6(session, "islands.registered", {
1243
+ islandId: island.islandId,
1244
+ loadStrategy: island.loadStrategy,
1245
+ interactiveBoundary: island.interactiveBoundary
1246
+ });
1247
+ }
1248
+ function beginIslandHydration(session, islandId) {
1249
+ const island = session.islands.find((i) => i.islandId === islandId);
1250
+ if (!island) {
1251
+ throw new Error(`beginIslandHydration: island ${islandId} not registered`);
1252
+ }
1253
+ if (session.state !== "registered" && session.state !== "hydrating") {
1254
+ throw new Error(`beginIslandHydration: session is ${session.state}`);
1255
+ }
1256
+ session.state = "hydrating";
1257
+ return emit6(session, "islands.hydration_started", {
1258
+ islandId,
1259
+ loadStrategy: island.loadStrategy
1260
+ });
1261
+ }
1262
+ function markIslandInteractive(session, islandId) {
1263
+ if (session.state !== "hydrating") {
1264
+ throw new Error(`markIslandInteractive: session is ${session.state}`);
1265
+ }
1266
+ if (session.hydratedIslandIds.includes(islandId)) {
1267
+ throw new Error(`markIslandInteractive: island ${islandId} already interactive`);
1268
+ }
1269
+ session.hydratedIslandIds.push(islandId);
1270
+ const allHydrated = session.hydratedIslandIds.length === session.islands.filter((i) => i.interactiveBoundary).length;
1271
+ if (allHydrated) {
1272
+ session.state = "interactive";
1273
+ }
1274
+ return emit6(session, "islands.interactive_ready", {
1275
+ islandId,
1276
+ hydratedCount: session.hydratedIslandIds.length,
1277
+ allInteractiveReady: allHydrated
1278
+ });
1279
+ }
1280
+ function assertStaticBoundary(session, boundaryId) {
1281
+ if (session.staticBoundaryIds.includes(boundaryId)) {
1282
+ throw new Error(`assertStaticBoundary: boundary ${boundaryId} already asserted`);
1283
+ }
1284
+ session.staticBoundaryIds.push(boundaryId);
1285
+ if (session.state === "interactive") {
1286
+ session.state = "static-verified";
1287
+ }
1288
+ return emit6(session, "islands.static_boundary_asserted", {
1289
+ boundaryId,
1290
+ staticBoundaryCount: session.staticBoundaryIds.length
1291
+ });
1292
+ }
1293
+
1140
1294
  // src/real-driver.ts
1141
1295
  var TARGET_KEY_ENV = {
1142
1296
  storybook8: "STORYBOOK_URL",
@@ -1174,9 +1328,14 @@ export {
1174
1328
  addHandler,
1175
1329
  appendChild,
1176
1330
  applyOptimisticUpdate,
1331
+ applyOptimisticUpdate2 as applyReactActionOptimistic,
1177
1332
  assertAnimation,
1178
1333
  assertMode,
1334
+ assertStaticBoundary,
1335
+ beginActionTransition,
1336
+ beginIslandHydration,
1179
1337
  beginRscRender,
1338
+ bootstrapIslandsRoute,
1180
1339
  buildButton,
1181
1340
  buildCard,
1182
1341
  buildForm,
@@ -1200,12 +1359,16 @@ export {
1200
1359
  finishElementTransition,
1201
1360
  fireEvent,
1202
1361
  hashMarkup,
1362
+ initializeReactActions,
1203
1363
  markFormStatusPending,
1364
+ markIslandInteractive,
1204
1365
  markSuspensePending,
1205
1366
  providerEventName,
1206
1367
  query,
1368
+ registerIsland,
1207
1369
  rejectFormAction,
1208
1370
  renderMarkup,
1371
+ resolveAction,
1209
1372
  resolveAllModes,
1210
1373
  resolveFormAction,
1211
1374
  resolveMode,