@pisell/materials 6.12.39 → 6.12.41

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.
Files changed (37) hide show
  1. package/build/lowcode/assets-daily.json +11 -11
  2. package/build/lowcode/assets-dev.json +2 -2
  3. package/build/lowcode/assets-prod.json +11 -11
  4. package/build/lowcode/meta.js +1 -1
  5. package/build/lowcode/render/default/view.js +32 -32
  6. package/build/lowcode/view.js +32 -32
  7. package/es/components/PisellSelectionFlow/PisellSelectionFlow.d.ts +7 -0
  8. package/es/components/PisellSelectionFlow/PisellSelectionFlow.js +392 -0
  9. package/es/components/PisellSelectionFlow/compiler.d.ts +12 -0
  10. package/es/components/PisellSelectionFlow/compiler.js +174 -0
  11. package/es/components/PisellSelectionFlow/context.d.ts +9 -0
  12. package/es/components/PisellSelectionFlow/context.js +12 -0
  13. package/es/components/PisellSelectionFlow/hooks/useFlowDraft.js +35 -0
  14. package/es/components/PisellSelectionFlow/hooks/useFlowModuleLifecycle.js +236 -0
  15. package/es/components/PisellSelectionFlow/hooks/useFlowNavigation.js +320 -0
  16. package/es/components/PisellSelectionFlow/index.d.ts +4 -0
  17. package/es/components/PisellSelectionFlow/types.d.ts +179 -0
  18. package/es/components/PisellSelectionFlow/types.js +10 -0
  19. package/es/components/PisellSelectionFlow/utils.js +15 -0
  20. package/es/index.d.ts +13 -9
  21. package/es/index.js +5 -1
  22. package/lib/components/PisellSelectionFlow/PisellSelectionFlow.d.ts +7 -0
  23. package/lib/components/PisellSelectionFlow/PisellSelectionFlow.js +394 -0
  24. package/lib/components/PisellSelectionFlow/compiler.d.ts +12 -0
  25. package/lib/components/PisellSelectionFlow/compiler.js +178 -0
  26. package/lib/components/PisellSelectionFlow/context.d.ts +9 -0
  27. package/lib/components/PisellSelectionFlow/context.js +16 -0
  28. package/lib/components/PisellSelectionFlow/hooks/useFlowDraft.js +36 -0
  29. package/lib/components/PisellSelectionFlow/hooks/useFlowModuleLifecycle.js +237 -0
  30. package/lib/components/PisellSelectionFlow/hooks/useFlowNavigation.js +321 -0
  31. package/lib/components/PisellSelectionFlow/index.d.ts +4 -0
  32. package/lib/components/PisellSelectionFlow/types.d.ts +179 -0
  33. package/lib/components/PisellSelectionFlow/types.js +10 -0
  34. package/lib/components/PisellSelectionFlow/utils.js +18 -0
  35. package/lib/index.d.ts +13 -9
  36. package/lib/index.js +15 -2
  37. package/package.json +1 -1
@@ -0,0 +1,7 @@
1
+ import { PisellSelectionFlowProps, SelectionFlowRef } from "./types.js";
2
+ import React from "react";
3
+
4
+ //#region src/components/PisellSelectionFlow/PisellSelectionFlow.d.ts
5
+ declare const _default: <TDraft, TDraftUpdate, TField extends string, TModuleType extends string, TServices = unknown, THostContext = unknown>(props: PisellSelectionFlowProps<TDraft, TDraftUpdate, TField, TModuleType, TServices, THostContext> & React.RefAttributes<SelectionFlowRef<TDraft, TDraftUpdate, TField, TModuleType>>) => React.ReactElement | null;
6
+ //#endregion
7
+ export { _default };
@@ -0,0 +1,392 @@
1
+ import { _objectSpread2 } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js";
2
+ import { SelectionFlowCompileError } from "./types.js";
3
+ import { compileSelectionFlowSteps } from "./compiler.js";
4
+ import { SelectionFlowProvider } from "./context.js";
5
+ import { useFlowDraft } from "./hooks/useFlowDraft.js";
6
+ import { getCompiledStepsFingerprint, getSelectionFlowErrorMessage } from "./utils.js";
7
+ import { useFlowModuleLifecycle } from "./hooks/useFlowModuleLifecycle.js";
8
+ import { useFlowNavigation } from "./hooks/useFlowNavigation.js";
9
+ import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
10
+ //#region src/components/PisellSelectionFlow/PisellSelectionFlow.tsx
11
+ const createUnexpectedCompileError = (error) => {
12
+ return new SelectionFlowCompileError([{
13
+ code: "APPLICABILITY_CHECK_FAILED",
14
+ message: `Selection flow compilation failed: ${getSelectionFlowErrorMessage(error)}`
15
+ }]);
16
+ };
17
+ const SelectionFlow = ({ registry, draftAdapter, steps, initialDraft, initialStepIndex = 0, hostContext, services, children, onDraftChange, onStepChange, onCompiledStepsChange, onValidationFailed, onConfigurationError, onComplete }, ref) => {
18
+ const mountedRef = useRef(true);
19
+ const flowGenerationRef = useRef(0);
20
+ const draftRevisionRef = useRef(0);
21
+ const navigationRevisionRef = useRef(0);
22
+ const transitionPendingRef = useRef(false);
23
+ const processDraftChangeRef = useRef(() => void 0);
24
+ const onDraftChangeRef = useRef(onDraftChange);
25
+ onDraftChangeRef.current = onDraftChange;
26
+ const onCompleteRef = useRef(onComplete);
27
+ onCompleteRef.current = onComplete;
28
+ const { draft, draftRef, updateDraft } = useFlowDraft({
29
+ initialDraft,
30
+ draftAdapter,
31
+ mountedRef,
32
+ draftRevisionRef,
33
+ onDraftChangeRef,
34
+ processDraftChangeRef
35
+ });
36
+ const initialDraftRef = useRef(initialDraft);
37
+ const [moduleState, setModuleStateMap] = useState({});
38
+ const moduleStateRef = useRef(moduleState);
39
+ moduleStateRef.current = moduleState;
40
+ const [moduleData, setModuleDataMap] = useState({});
41
+ const moduleDataRef = useRef(moduleData);
42
+ moduleDataRef.current = moduleData;
43
+ const [currentStepIndex, setCurrentStepIndex] = useState(() => Math.max(0, initialStepIndex));
44
+ const currentStepIndexRef = useRef(currentStepIndex);
45
+ currentStepIndexRef.current = currentStepIndex;
46
+ const currentStepKeyRef = useRef();
47
+ const [isCompleting, setIsCompleting] = useState(false);
48
+ const isCompletingRef = useRef(isCompleting);
49
+ isCompletingRef.current = isCompleting;
50
+ const [completionError, setCompletionError] = useState();
51
+ const [completionReason, setCompletionReason] = useState();
52
+ const completedRef = useRef(false);
53
+ const completionPromiseRef = useRef(null);
54
+ const validatedCompletionRef = useRef(null);
55
+ const moduleHandlesRef = useRef(/* @__PURE__ */ new Map());
56
+ const activeModuleKeysRef = useRef(/* @__PURE__ */ new Set());
57
+ const moduleRevisionRef = useRef(/* @__PURE__ */ new Map());
58
+ const moduleInitializationRef = useRef(/* @__PURE__ */ new Map());
59
+ const moduleDependencyLifecycleRef = useRef(/* @__PURE__ */ new Map());
60
+ const pendingModuleChangeRef = useRef(/* @__PURE__ */ new Map());
61
+ const compiledStepsRef = useRef([]);
62
+ const configurationErrorRef = useRef(null);
63
+ const contextRef = useRef(null);
64
+ const notifiedStepRef = useRef();
65
+ const notifiedCompiledStepsRef = useRef();
66
+ const createRuntimeIssue = useCallback((code, params) => ({
67
+ code,
68
+ params
69
+ }), []);
70
+ useEffect(() => {
71
+ const generation = flowGenerationRef.current + 1;
72
+ flowGenerationRef.current = generation;
73
+ mountedRef.current = true;
74
+ if (generation > 1) {
75
+ const nextModuleState = Object.fromEntries(Object.keys(moduleStateRef.current).map((moduleKey) => [moduleKey, { status: "idle" }]));
76
+ moduleStateRef.current = nextModuleState;
77
+ moduleDataRef.current = {};
78
+ setModuleStateMap(nextModuleState);
79
+ setModuleDataMap({});
80
+ }
81
+ return () => {
82
+ mountedRef.current = false;
83
+ if (flowGenerationRef.current === generation) flowGenerationRef.current += 1;
84
+ navigationRevisionRef.current += 1;
85
+ moduleInitializationRef.current.clear();
86
+ moduleDependencyLifecycleRef.current.clear();
87
+ pendingModuleChangeRef.current.clear();
88
+ moduleHandlesRef.current.clear();
89
+ };
90
+ }, []);
91
+ const commitModuleState = useCallback((moduleKey, nextState) => {
92
+ if (!mountedRef.current) return;
93
+ const previous = moduleStateRef.current[moduleKey];
94
+ if ((previous === null || previous === void 0 ? void 0 : previous.status) === nextState.status && (previous === null || previous === void 0 ? void 0 : previous.message) === nextState.message && (previous === null || previous === void 0 ? void 0 : previous.reason) === nextState.reason && (previous === null || previous === void 0 ? void 0 : previous.error) === nextState.error) return;
95
+ const nextMap = _objectSpread2(_objectSpread2({}, moduleStateRef.current), {}, { [moduleKey]: nextState });
96
+ moduleStateRef.current = nextMap;
97
+ setModuleStateMap(nextMap);
98
+ }, []);
99
+ const setModuleStatus = useCallback((moduleKey, status, message, error) => {
100
+ commitModuleState(moduleKey, {
101
+ status,
102
+ message,
103
+ error
104
+ });
105
+ }, [commitModuleState]);
106
+ const setModuleData = useCallback((moduleKey, value) => {
107
+ if (!mountedRef.current) return;
108
+ const nextMap = _objectSpread2(_objectSpread2({}, moduleDataRef.current), {}, { [moduleKey]: value });
109
+ moduleDataRef.current = nextMap;
110
+ setModuleDataMap(nextMap);
111
+ }, []);
112
+ const clearModuleData = useCallback((moduleKey) => {
113
+ if (!mountedRef.current) return;
114
+ if (!(moduleKey in moduleDataRef.current)) return;
115
+ const nextMap = _objectSpread2({}, moduleDataRef.current);
116
+ delete nextMap[moduleKey];
117
+ moduleDataRef.current = nextMap;
118
+ setModuleDataMap(nextMap);
119
+ }, []);
120
+ const provisionalContext = useMemo(() => ({
121
+ draft,
122
+ updateDraft,
123
+ moduleState,
124
+ setModuleState: commitModuleState,
125
+ setModuleStatus,
126
+ moduleData,
127
+ getModuleData: (moduleKey) => moduleDataRef.current[moduleKey],
128
+ setModuleData,
129
+ clearModuleData,
130
+ steps: [],
131
+ currentStepIndex,
132
+ currentStep: void 0,
133
+ hostContext,
134
+ services
135
+ }), [
136
+ hostContext,
137
+ clearModuleData,
138
+ commitModuleState,
139
+ currentStepIndex,
140
+ draft,
141
+ moduleData,
142
+ moduleState,
143
+ services,
144
+ setModuleData,
145
+ setModuleStatus,
146
+ updateDraft
147
+ ]);
148
+ const compilation = useMemo(() => {
149
+ try {
150
+ return {
151
+ steps: compileSelectionFlowSteps(steps, provisionalContext, initialDraftRef.current, registry, draftAdapter),
152
+ error: null
153
+ };
154
+ } catch (error) {
155
+ return {
156
+ steps: [],
157
+ error: error instanceof SelectionFlowCompileError ? error : createUnexpectedCompileError(error)
158
+ };
159
+ }
160
+ }, [
161
+ draft,
162
+ draftAdapter,
163
+ hostContext,
164
+ registry,
165
+ services,
166
+ steps
167
+ ]);
168
+ const compiledSteps = compilation.steps;
169
+ const configurationError = compilation.error;
170
+ compiledStepsRef.current = compiledSteps;
171
+ configurationErrorRef.current = configurationError;
172
+ let resolvedCurrentStepIndex = Math.min(Math.max(0, currentStepIndex), Math.max(0, compiledSteps.length - 1));
173
+ if (currentStepKeyRef.current) {
174
+ const trackedIndex = compiledSteps.findIndex((step) => step.key === currentStepKeyRef.current);
175
+ if (trackedIndex >= 0) resolvedCurrentStepIndex = trackedIndex;
176
+ else if (compiledSteps.length > 0) {
177
+ const firstReviewIndex = compiledSteps.findIndex((step) => step.modules.some((module) => {
178
+ var _moduleStateRef$curre;
179
+ return ((_moduleStateRef$curre = moduleStateRef.current[module.key]) === null || _moduleStateRef$curre === void 0 ? void 0 : _moduleStateRef$curre.status) !== "ready";
180
+ }));
181
+ resolvedCurrentStepIndex = firstReviewIndex >= 0 ? firstReviewIndex : resolvedCurrentStepIndex;
182
+ }
183
+ }
184
+ const currentStep = compiledSteps[resolvedCurrentStepIndex];
185
+ currentStepIndexRef.current = resolvedCurrentStepIndex;
186
+ currentStepKeyRef.current = currentStep === null || currentStep === void 0 ? void 0 : currentStep.key;
187
+ const contextValue = useMemo(() => _objectSpread2(_objectSpread2({}, provisionalContext), {}, {
188
+ steps: compiledSteps,
189
+ currentStepIndex: resolvedCurrentStepIndex,
190
+ currentStep
191
+ }), [
192
+ compiledSteps,
193
+ currentStep,
194
+ provisionalContext,
195
+ resolvedCurrentStepIndex
196
+ ]);
197
+ contextRef.current = contextValue;
198
+ const getFreshContext = useCallback(() => {
199
+ const current = contextRef.current;
200
+ if (!mountedRef.current || !current) return null;
201
+ return _objectSpread2(_objectSpread2({}, current), {}, {
202
+ draft: draftRef.current,
203
+ moduleState: moduleStateRef.current,
204
+ moduleData: moduleDataRef.current
205
+ });
206
+ }, []);
207
+ useEffect(() => {
208
+ if (!configurationError) return;
209
+ onConfigurationError === null || onConfigurationError === void 0 || onConfigurationError(configurationError);
210
+ }, [configurationError, onConfigurationError]);
211
+ useEffect(() => {
212
+ if (configurationError) return;
213
+ const fingerprint = getCompiledStepsFingerprint(compiledSteps);
214
+ if (notifiedCompiledStepsRef.current === fingerprint) return;
215
+ notifiedCompiledStepsRef.current = fingerprint;
216
+ onCompiledStepsChange === null || onCompiledStepsChange === void 0 || onCompiledStepsChange(compiledSteps);
217
+ }, [
218
+ compiledSteps,
219
+ configurationError,
220
+ onCompiledStepsChange
221
+ ]);
222
+ useEffect(() => {
223
+ if (currentStepIndex === resolvedCurrentStepIndex) return;
224
+ setCurrentStepIndex(resolvedCurrentStepIndex);
225
+ }, [currentStepIndex, resolvedCurrentStepIndex]);
226
+ useEffect(() => {
227
+ if (!currentStep) return;
228
+ const notificationKey = `${resolvedCurrentStepIndex}:${currentStep.key}`;
229
+ if (notifiedStepRef.current === notificationKey) return;
230
+ notifiedStepRef.current = notificationKey;
231
+ onStepChange === null || onStepChange === void 0 || onStepChange(resolvedCurrentStepIndex, currentStep);
232
+ }, [
233
+ currentStep,
234
+ onStepChange,
235
+ resolvedCurrentStepIndex
236
+ ]);
237
+ useEffect(() => {
238
+ const nextMap = _objectSpread2({}, moduleStateRef.current);
239
+ const nextDataMap = _objectSpread2({}, moduleDataRef.current);
240
+ const nextActiveKeys = /* @__PURE__ */ new Set();
241
+ let changed = false;
242
+ let dataChanged = false;
243
+ for (const step of compiledSteps) for (const module of step.modules) {
244
+ nextActiveKeys.add(module.key);
245
+ if (!nextMap[module.key]) {
246
+ nextMap[module.key] = { status: "idle" };
247
+ changed = true;
248
+ }
249
+ }
250
+ activeModuleKeysRef.current.forEach((moduleKey) => {
251
+ if (nextActiveKeys.has(moduleKey)) return;
252
+ moduleRevisionRef.current.set(moduleKey, (moduleRevisionRef.current.get(moduleKey) || 0) + 1);
253
+ moduleInitializationRef.current.delete(moduleKey);
254
+ moduleDependencyLifecycleRef.current.delete(moduleKey);
255
+ pendingModuleChangeRef.current.delete(moduleKey);
256
+ moduleHandlesRef.current.delete(moduleKey);
257
+ if (moduleKey in nextMap) {
258
+ delete nextMap[moduleKey];
259
+ changed = true;
260
+ }
261
+ if (moduleKey in nextDataMap) {
262
+ delete nextDataMap[moduleKey];
263
+ dataChanged = true;
264
+ }
265
+ });
266
+ activeModuleKeysRef.current = nextActiveKeys;
267
+ if (changed) {
268
+ moduleStateRef.current = nextMap;
269
+ setModuleStateMap(nextMap);
270
+ }
271
+ if (dataChanged) {
272
+ moduleDataRef.current = nextDataMap;
273
+ setModuleDataMap(nextDataMap);
274
+ }
275
+ }, [compiledSteps]);
276
+ const { ensureModuleReady } = useFlowModuleLifecycle({
277
+ registry,
278
+ draftAdapter,
279
+ createRuntimeIssue,
280
+ mountedRef,
281
+ flowGenerationRef,
282
+ draftRevisionRef,
283
+ draftRef,
284
+ moduleRevisionRef,
285
+ moduleInitializationRef,
286
+ moduleDependencyLifecycleRef,
287
+ pendingModuleChangeRef,
288
+ compiledStepsRef,
289
+ moduleStateRef,
290
+ processDraftChangeRef,
291
+ commitModuleState,
292
+ getFreshContext,
293
+ currentStep,
294
+ configurationError,
295
+ compiledSteps,
296
+ resolvedCurrentStepIndex,
297
+ draft,
298
+ moduleState
299
+ });
300
+ const { validateCurrentStep, complete, next, back } = useFlowNavigation({
301
+ registry,
302
+ draftAdapter,
303
+ createRuntimeIssue,
304
+ mountedRef,
305
+ moduleStateRef,
306
+ moduleRevisionRef,
307
+ draftRevisionRef,
308
+ flowGenerationRef,
309
+ moduleHandlesRef,
310
+ configurationErrorRef,
311
+ compiledStepsRef,
312
+ currentStepIndexRef,
313
+ currentStepKeyRef,
314
+ validatedCompletionRef,
315
+ navigationRevisionRef,
316
+ transitionPendingRef,
317
+ completedRef,
318
+ completionPromiseRef,
319
+ isCompletingRef,
320
+ draftRef,
321
+ onCompleteRef,
322
+ ensureModuleReady,
323
+ commitModuleState,
324
+ getFreshContext,
325
+ onValidationFailed,
326
+ setCurrentStepIndex,
327
+ setCompletionError,
328
+ setCompletionReason,
329
+ setIsCompleting
330
+ });
331
+ const getState = useCallback(() => {
332
+ const stepIndex = currentStepIndexRef.current;
333
+ return {
334
+ draft: draftRef.current,
335
+ currentStepIndex: stepIndex,
336
+ currentStep: compiledStepsRef.current[stepIndex],
337
+ steps: compiledStepsRef.current,
338
+ moduleState: moduleStateRef.current,
339
+ moduleData: moduleDataRef.current,
340
+ isCompleting: isCompletingRef.current,
341
+ isCompleted: completedRef.current,
342
+ configurationError: configurationErrorRef.current
343
+ };
344
+ }, []);
345
+ useImperativeHandle(ref, () => ({
346
+ next,
347
+ back,
348
+ updateDraft,
349
+ validateCurrentStep,
350
+ complete,
351
+ getState
352
+ }), [
353
+ back,
354
+ complete,
355
+ getState,
356
+ next,
357
+ updateDraft,
358
+ validateCurrentStep
359
+ ]);
360
+ const registerModuleHandle = useCallback((moduleKey, handle) => {
361
+ if (handle) moduleHandlesRef.current.set(moduleKey, handle);
362
+ else moduleHandlesRef.current.delete(moduleKey);
363
+ }, []);
364
+ const getModuleHandle = useCallback((moduleKey) => moduleHandlesRef.current.get(moduleKey), []);
365
+ const controller = {
366
+ draft,
367
+ currentStepIndex: resolvedCurrentStepIndex,
368
+ currentStep,
369
+ steps: compiledSteps,
370
+ moduleState,
371
+ moduleData,
372
+ isCompleting,
373
+ isCompleted: completedRef.current,
374
+ configurationError,
375
+ completionError,
376
+ completionReason,
377
+ context: contextValue,
378
+ updateDraft,
379
+ validateCurrentStep,
380
+ complete,
381
+ next,
382
+ back,
383
+ getState,
384
+ registerModuleHandle,
385
+ getModuleHandle
386
+ };
387
+ return /* @__PURE__ */ React.createElement(SelectionFlowProvider, { value: contextValue }, children(controller));
388
+ };
389
+ const ForwardedSelectionFlow = forwardRef(SelectionFlow);
390
+ ForwardedSelectionFlow.displayName = "PisellSelectionFlow";
391
+ //#endregion
392
+ export { ForwardedSelectionFlow as default };
@@ -0,0 +1,12 @@
1
+ import { CompiledSelectionFlowStep, SelectionFlowContextValue, SelectionFlowDraftAdapter, SelectionFlowModuleAdapter, SelectionFlowModuleRegistry, SelectionFlowStepConfig } from "./types.js";
2
+
3
+ //#region src/components/PisellSelectionFlow/compiler.d.ts
4
+ type AnyAdapter = SelectionFlowModuleAdapter<any, any, string, string, any, any>;
5
+ type AnyRegistry = Record<string, AnyAdapter>;
6
+ declare const resolveFlowModuleAdapter: <TDraft, TDraftUpdate, TField extends string, TModuleType extends string, TServices, THostContext>(registry: SelectionFlowModuleRegistry<TDraft, TDraftUpdate, TField, TModuleType, TServices, THostContext>, type: string) => AnyAdapter;
7
+ declare const hasSelectionDraftFieldValue: <TDraft, TDraftUpdate, TField extends string>(draftAdapter: SelectionFlowDraftAdapter<TDraft, TDraftUpdate, TField>, draft: Readonly<TDraft>, field: TField) => boolean;
8
+ declare const compileSelectionFlowSteps: <TDraft, TDraftUpdate, TField extends string, TModuleType extends string, TServices, THostContext>(steps: readonly SelectionFlowStepConfig<TModuleType>[], context: SelectionFlowContextValue<TDraft, TDraftUpdate, TField, TModuleType, TServices, THostContext>, dependencySeedDraft: Readonly<TDraft>, registry: SelectionFlowModuleRegistry<TDraft, TDraftUpdate, TField, TModuleType, TServices, THostContext>, draftAdapter: SelectionFlowDraftAdapter<TDraft, TDraftUpdate, TField>) => readonly CompiledSelectionFlowStep<TModuleType>[];
9
+ declare const compileSelectionFlow: <TDraft, TDraftUpdate, TField extends string, TModuleType extends string, TServices, THostContext>(steps: readonly SelectionFlowStepConfig<TModuleType>[], context: SelectionFlowContextValue<TDraft, TDraftUpdate, TField, TModuleType, TServices, THostContext>, dependencySeedDraft: Readonly<TDraft>, registry: SelectionFlowModuleRegistry<TDraft, TDraftUpdate, TField, TModuleType, TServices, THostContext>, draftAdapter: SelectionFlowDraftAdapter<TDraft, TDraftUpdate, TField>) => readonly CompiledSelectionFlowStep<TModuleType>[];
10
+ declare const isSelectionModuleType: (registry: AnyRegistry, type: string) => boolean;
11
+ //#endregion
12
+ export { compileSelectionFlow, compileSelectionFlowSteps, hasSelectionDraftFieldValue, isSelectionModuleType, resolveFlowModuleAdapter };
@@ -0,0 +1,174 @@
1
+ import { _objectSpread2 } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js";
2
+ import { SelectionFlowCompileError } from "./types.js";
3
+ //#region src/components/PisellSelectionFlow/compiler.ts
4
+ const resolveFlowModuleAdapter = (registry, type) => registry[type];
5
+ const hasSelectionDraftFieldValue = (draftAdapter, draft, field) => {
6
+ const value = draftAdapter.getFieldValue(draft, field);
7
+ if (value === null || typeof value === "undefined" || value === "") return false;
8
+ return !Array.isArray(value) || value.length > 0;
9
+ };
10
+ const normalizeModule = (input, stepKey, stepIndex, moduleIndex) => {
11
+ const config = typeof input === "string" ? { type: input } : input;
12
+ return _objectSpread2(_objectSpread2({}, config), {}, {
13
+ key: config.key || config.type,
14
+ stepKey,
15
+ stepIndex,
16
+ moduleIndex
17
+ });
18
+ };
19
+ const findCircularRequirements = (modules, registry, draftAdapter, initialDraft) => {
20
+ const providers = /* @__PURE__ */ new Map();
21
+ modules.forEach((module) => {
22
+ var _resolveFlowModuleAda;
23
+ (_resolveFlowModuleAda = resolveFlowModuleAdapter(registry, module.type)) === null || _resolveFlowModuleAda === void 0 || (_resolveFlowModuleAda = _resolveFlowModuleAda.provides) === null || _resolveFlowModuleAda === void 0 || _resolveFlowModuleAda.forEach((field) => {
24
+ providers.set(field, [...providers.get(field) || [], module]);
25
+ });
26
+ });
27
+ const resolved = /* @__PURE__ */ new Set();
28
+ let progressed = true;
29
+ while (progressed) {
30
+ progressed = false;
31
+ for (const module of modules) {
32
+ if (resolved.has(module.key)) continue;
33
+ const adapter = resolveFlowModuleAdapter(registry, module.type);
34
+ if (!((adapter === null || adapter === void 0 ? void 0 : adapter.hardRequires) || []).every((field) => {
35
+ const candidates = (providers.get(field) || []).filter((provider) => provider.key !== module.key);
36
+ if (candidates.length === 0) return hasSelectionDraftFieldValue(draftAdapter, initialDraft, field);
37
+ return candidates.some((provider) => resolved.has(provider.key));
38
+ })) continue;
39
+ resolved.add(module.key);
40
+ progressed = true;
41
+ }
42
+ }
43
+ const unresolved = modules.filter((module) => !resolved.has(module.key));
44
+ if (unresolved.length === 0) return null;
45
+ return unresolved.some((module) => {
46
+ var _resolveFlowModuleAda2;
47
+ return (((_resolveFlowModuleAda2 = resolveFlowModuleAdapter(registry, module.type)) === null || _resolveFlowModuleAda2 === void 0 ? void 0 : _resolveFlowModuleAda2.hardRequires) || []).some((field) => {
48
+ return (providers.get(field) || []).filter((provider) => provider.key !== module.key).length === 0 && !hasSelectionDraftFieldValue(draftAdapter, initialDraft, field);
49
+ });
50
+ }) ? null : unresolved.map((module) => module.type);
51
+ };
52
+ const compileSelectionFlowSteps = (steps, context, dependencySeedDraft, registry, draftAdapter) => {
53
+ const issues = [];
54
+ const stepKeys = /* @__PURE__ */ new Set();
55
+ const moduleKeys = /* @__PURE__ */ new Set();
56
+ const compiledSteps = [];
57
+ steps.forEach((step, sourceStepIndex) => {
58
+ const stepKey = String(step.key || "").trim();
59
+ if (!stepKey || stepKeys.has(stepKey)) issues.push({
60
+ code: "DUPLICATE_STEP_KEY",
61
+ message: stepKey ? `Selection flow contains duplicate step key "${stepKey}".` : "Selection flow step key cannot be empty.",
62
+ stepKey: stepKey || void 0
63
+ });
64
+ else stepKeys.add(stepKey);
65
+ if (!Array.isArray(step.modules) || step.modules.length === 0) {
66
+ issues.push({
67
+ code: "EMPTY_STEP",
68
+ message: `Selection flow step "${stepKey || sourceStepIndex}" has no modules.`,
69
+ stepKey: stepKey || void 0
70
+ });
71
+ return;
72
+ }
73
+ const applicableModules = [];
74
+ step.modules.forEach((input) => {
75
+ const module = normalizeModule(input, stepKey, compiledSteps.length, applicableModules.length);
76
+ const adapter = resolveFlowModuleAdapter(registry, module.type);
77
+ if (!adapter) {
78
+ issues.push({
79
+ code: "UNKNOWN_MODULE",
80
+ message: `Selection module type "${module.type}" is not registered.`,
81
+ stepKey,
82
+ moduleKey: module.key,
83
+ moduleType: module.type
84
+ });
85
+ return;
86
+ }
87
+ if (moduleKeys.has(module.key)) {
88
+ issues.push({
89
+ code: "DUPLICATE_MODULE_KEY",
90
+ message: `Selection flow contains duplicate module key "${module.key}".`,
91
+ stepKey,
92
+ moduleKey: module.key,
93
+ moduleType: module.type
94
+ });
95
+ return;
96
+ }
97
+ moduleKeys.add(module.key);
98
+ try {
99
+ if (adapter.isApplicable && !adapter.isApplicable(context, module)) return;
100
+ } catch (error) {
101
+ issues.push({
102
+ code: "APPLICABILITY_CHECK_FAILED",
103
+ message: `Selection module "${module.type}" applicability check failed: ${error instanceof Error ? error.message : String(error)}`,
104
+ stepKey,
105
+ moduleKey: module.key,
106
+ moduleType: module.type
107
+ });
108
+ return;
109
+ }
110
+ applicableModules.push(_objectSpread2(_objectSpread2({}, module), {}, { moduleIndex: applicableModules.length }));
111
+ });
112
+ if (applicableModules.length === 0) return;
113
+ const index = compiledSteps.length;
114
+ compiledSteps.push(_objectSpread2(_objectSpread2({}, step), {}, {
115
+ key: stepKey,
116
+ index,
117
+ modules: applicableModules.map((module) => _objectSpread2(_objectSpread2({}, module), {}, { stepIndex: index }))
118
+ }));
119
+ });
120
+ const flatModules = compiledSteps.flatMap((step) => [...step.modules]);
121
+ if (flatModules.length === 0 && steps.length === 0) issues.push({
122
+ code: "EMPTY_FLOW",
123
+ message: "Selection flow has no applicable modules."
124
+ });
125
+ const circularPath = findCircularRequirements(flatModules, registry, draftAdapter, dependencySeedDraft);
126
+ if (circularPath) issues.push({
127
+ code: "CIRCULAR_HARD_REQUIREMENT",
128
+ message: `Selection flow contains unresolvable circular hard requirements among: ${circularPath.join(", ")}.`,
129
+ moduleType: circularPath[0]
130
+ });
131
+ const providers = /* @__PURE__ */ new Map();
132
+ flatModules.forEach((module, index) => {
133
+ var _resolveFlowModuleAda3;
134
+ (_resolveFlowModuleAda3 = resolveFlowModuleAdapter(registry, module.type)) === null || _resolveFlowModuleAda3 === void 0 || (_resolveFlowModuleAda3 = _resolveFlowModuleAda3.provides) === null || _resolveFlowModuleAda3 === void 0 || _resolveFlowModuleAda3.forEach((field) => {
135
+ providers.set(field, [...providers.get(field) || [], {
136
+ module,
137
+ index
138
+ }]);
139
+ });
140
+ });
141
+ flatModules.forEach((module, index) => {
142
+ const adapter = resolveFlowModuleAdapter(registry, module.type);
143
+ for (const field of (adapter === null || adapter === void 0 ? void 0 : adapter.hardRequires) || []) {
144
+ const typedField = field;
145
+ const fieldProviders = (providers.get(typedField) || []).filter((provider) => provider.module.key !== module.key);
146
+ if (fieldProviders.length === 0) {
147
+ if (hasSelectionDraftFieldValue(draftAdapter, dependencySeedDraft, typedField)) continue;
148
+ issues.push({
149
+ code: "MISSING_HARD_REQUIREMENT",
150
+ message: `Selection module "${module.type}" requires Draft field "${typedField}", but no earlier module provides it.`,
151
+ stepKey: module.stepKey,
152
+ moduleKey: module.key,
153
+ moduleType: module.type,
154
+ requirementField: typedField
155
+ });
156
+ continue;
157
+ }
158
+ if (!fieldProviders.some((provider) => provider.index < index)) issues.push({
159
+ code: "INVALID_DEPENDENCY_ORDER",
160
+ message: `Selection module "${module.type}" requires Draft field "${typedField}" to be provided before it.`,
161
+ stepKey: module.stepKey,
162
+ moduleKey: module.key,
163
+ moduleType: module.type,
164
+ requirementField: typedField
165
+ });
166
+ }
167
+ });
168
+ if (issues.length > 0) throw new SelectionFlowCompileError(issues);
169
+ return compiledSteps;
170
+ };
171
+ const compileSelectionFlow = compileSelectionFlowSteps;
172
+ const isSelectionModuleType = (registry, type) => Boolean(registry[type]);
173
+ //#endregion
174
+ export { compileSelectionFlow, compileSelectionFlowSteps, hasSelectionDraftFieldValue, isSelectionModuleType, resolveFlowModuleAdapter };
@@ -0,0 +1,9 @@
1
+ import { SelectionFlowContextValue } from "./types.js";
2
+ import React from "react";
3
+
4
+ //#region src/components/PisellSelectionFlow/context.d.ts
5
+ type AnySelectionFlowContext = SelectionFlowContextValue<any, any, string, string, any, any>;
6
+ declare const useSelectionFlowContext: () => AnySelectionFlowContext;
7
+ declare const useTypedSelectionFlowContext: <TDraft, TDraftUpdate, TField extends string, TModuleType extends string, TServices = unknown, THostContext = unknown>() => SelectionFlowContextValue<TDraft, TDraftUpdate, TField, TModuleType, TServices, THostContext>;
8
+ //#endregion
9
+ export { useSelectionFlowContext, useTypedSelectionFlowContext };
@@ -0,0 +1,12 @@
1
+ import React, { createContext, useContext } from "react";
2
+ //#region src/components/PisellSelectionFlow/context.tsx
3
+ const SelectionFlowReactContext = createContext(null);
4
+ const SelectionFlowProvider = ({ value, children }) => /* @__PURE__ */ React.createElement(SelectionFlowReactContext.Provider, { value }, children);
5
+ const useSelectionFlowContext = () => {
6
+ const context = useContext(SelectionFlowReactContext);
7
+ if (!context) throw new Error("useSelectionFlowContext must be used inside PisellSelectionFlow");
8
+ return context;
9
+ };
10
+ const useTypedSelectionFlowContext = () => useSelectionFlowContext();
11
+ //#endregion
12
+ export { SelectionFlowProvider, useSelectionFlowContext, useTypedSelectionFlowContext };
@@ -0,0 +1,35 @@
1
+ import { _objectSpread2 } from "../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js";
2
+ import { useCallback, useRef, useState } from "react";
3
+ //#region src/components/PisellSelectionFlow/hooks/useFlowDraft.ts
4
+ /** 统一管理不可变 Draft 与业务自定义合并策略。 */
5
+ const useFlowDraft = ({ initialDraft, draftAdapter, mountedRef, draftRevisionRef, onDraftChangeRef, processDraftChangeRef }) => {
6
+ const [draft, setDraft] = useState(() => initialDraft);
7
+ const draftRef = useRef(draft);
8
+ draftRef.current = draft;
9
+ return {
10
+ draft,
11
+ draftRef,
12
+ updateDraft: useCallback((update, meta) => {
13
+ var _onDraftChangeRef$cur;
14
+ if (!mountedRef.current) return;
15
+ const previousDraft = draftRef.current;
16
+ const nextDraft = draftAdapter.applyUpdate(previousDraft, update);
17
+ draftRevisionRef.current += 1;
18
+ draftRef.current = nextDraft;
19
+ setDraft(nextDraft);
20
+ (_onDraftChangeRef$cur = onDraftChangeRef.current) === null || _onDraftChangeRef$cur === void 0 || _onDraftChangeRef$cur.call(onDraftChangeRef, nextDraft);
21
+ processDraftChangeRef.current(_objectSpread2({
22
+ previousDraft,
23
+ draft: nextDraft
24
+ }, meta));
25
+ }, [
26
+ draftAdapter,
27
+ draftRevisionRef,
28
+ mountedRef,
29
+ onDraftChangeRef,
30
+ processDraftChangeRef
31
+ ])
32
+ };
33
+ };
34
+ //#endregion
35
+ export { useFlowDraft };