@timeax/digital-service-engine 0.0.4 → 0.0.5
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/react/index.cjs +1914 -2
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +247 -169
- package/dist/react/index.d.ts +247 -169
- package/dist/react/index.js +1898 -1
- package/dist/react/index.js.map +1 -1
- package/dist/workspace/index.cjs.map +1 -1
- package/dist/workspace/index.js.map +1 -1
- package/package.json +1 -1
package/dist/react/index.cjs
CHANGED
|
@@ -32,18 +32,33 @@ var react_exports = {};
|
|
|
32
32
|
__export(react_exports, {
|
|
33
33
|
CanvasAPI: () => CanvasAPI,
|
|
34
34
|
EventBus: () => EventBus,
|
|
35
|
+
FallbackAddCandidatesDialog: () => FallbackAddCandidatesDialog,
|
|
36
|
+
FallbackAddRegistrationDialog: () => FallbackAddRegistrationDialog,
|
|
37
|
+
FallbackDetailsPanel: () => FallbackDetailsPanel,
|
|
38
|
+
FallbackEditor: () => FallbackEditor,
|
|
39
|
+
FallbackEditorHeader: () => FallbackEditorHeader,
|
|
40
|
+
FallbackEditorProvider: () => FallbackEditorProvider,
|
|
41
|
+
FallbackRegistrationsPanel: () => FallbackRegistrationsPanel,
|
|
42
|
+
FallbackServiceSidebar: () => FallbackServiceSidebar,
|
|
43
|
+
FallbackSettingsPanel: () => FallbackSettingsPanel,
|
|
35
44
|
FormProvider: () => FormProvider,
|
|
36
45
|
OrderFlowProvider: () => OrderFlowProvider,
|
|
37
46
|
Provider: () => Provider,
|
|
47
|
+
VirtualServiceList: () => VirtualServiceList,
|
|
38
48
|
Wrapper: () => Wrapper,
|
|
39
49
|
createInputRegistry: () => createInputRegistry,
|
|
40
50
|
registerEntries: () => registerEntries,
|
|
41
51
|
resolveInputDescriptor: () => resolveInputDescriptor,
|
|
52
|
+
useActiveFallbackRegistrations: () => useActiveFallbackRegistrations,
|
|
53
|
+
useEligibleServiceList: () => useEligibleServiceList,
|
|
54
|
+
useFallbackEditor: () => useFallbackEditor,
|
|
55
|
+
useFallbackEditorContext: () => useFallbackEditorContext,
|
|
42
56
|
useFormApi: () => useFormApi,
|
|
43
57
|
useInputs: () => useInputs,
|
|
44
58
|
useOptionalFormApi: () => useOptionalFormApi,
|
|
45
59
|
useOrderFlow: () => useOrderFlow,
|
|
46
|
-
useOrderFlowContext: () => useOrderFlowContext
|
|
60
|
+
useOrderFlowContext: () => useOrderFlowContext,
|
|
61
|
+
usePrimaryServiceList: () => usePrimaryServiceList
|
|
47
62
|
});
|
|
48
63
|
module.exports = __toCommonJS(react_exports);
|
|
49
64
|
|
|
@@ -3173,6 +3188,58 @@ function bindIdsToArray(bind) {
|
|
|
3173
3188
|
if (!bind) return [];
|
|
3174
3189
|
return Array.isArray(bind) ? bind.slice() : [bind];
|
|
3175
3190
|
}
|
|
3191
|
+
function getEligibleFallbacks(params) {
|
|
3192
|
+
var _a, _b, _c, _d, _e, _f;
|
|
3193
|
+
const s = { ...DEFAULT_SETTINGS, ...(_a = params.settings) != null ? _a : {} };
|
|
3194
|
+
const { primary, nodeId, tagId, services } = params;
|
|
3195
|
+
const fb = (_b = params.fallbacks) != null ? _b : {};
|
|
3196
|
+
const excludes = new Set(((_c = params.exclude) != null ? _c : []).map(String));
|
|
3197
|
+
excludes.add(String(primary));
|
|
3198
|
+
const unique = (_d = params.unique) != null ? _d : true;
|
|
3199
|
+
const lists = [];
|
|
3200
|
+
if (nodeId && ((_e = fb.nodes) == null ? void 0 : _e[nodeId])) lists.push(fb.nodes[nodeId]);
|
|
3201
|
+
if ((_f = fb.global) == null ? void 0 : _f[primary]) lists.push(fb.global[primary]);
|
|
3202
|
+
if (!lists.length) return [];
|
|
3203
|
+
const primaryRate = rateOf(services, primary);
|
|
3204
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3205
|
+
const eligible = [];
|
|
3206
|
+
for (const list of lists) {
|
|
3207
|
+
for (const cand of list) {
|
|
3208
|
+
const key = String(cand);
|
|
3209
|
+
if (excludes.has(key)) continue;
|
|
3210
|
+
if (unique && seen.has(key)) continue;
|
|
3211
|
+
seen.add(key);
|
|
3212
|
+
const cap = getCap(services, cand);
|
|
3213
|
+
if (!cap) continue;
|
|
3214
|
+
if (!passesRate(s.ratePolicy, primaryRate, cap.rate)) continue;
|
|
3215
|
+
if (s.requireConstraintFit && tagId) {
|
|
3216
|
+
const ok = satisfiesTagConstraints(
|
|
3217
|
+
tagId,
|
|
3218
|
+
{ props: params.props, services },
|
|
3219
|
+
cap
|
|
3220
|
+
);
|
|
3221
|
+
if (!ok) continue;
|
|
3222
|
+
}
|
|
3223
|
+
eligible.push(cand);
|
|
3224
|
+
}
|
|
3225
|
+
}
|
|
3226
|
+
if (s.selectionStrategy === "cheapest") {
|
|
3227
|
+
eligible.sort((a, b) => {
|
|
3228
|
+
var _a2, _b2;
|
|
3229
|
+
const ra = (_a2 = rateOf(services, a)) != null ? _a2 : Infinity;
|
|
3230
|
+
const rb = (_b2 = rateOf(services, b)) != null ? _b2 : Infinity;
|
|
3231
|
+
return ra - rb;
|
|
3232
|
+
});
|
|
3233
|
+
}
|
|
3234
|
+
if (typeof params.limit === "number" && params.limit >= 0) {
|
|
3235
|
+
return eligible.slice(0, params.limit);
|
|
3236
|
+
}
|
|
3237
|
+
return eligible;
|
|
3238
|
+
}
|
|
3239
|
+
function getFallbackRegistrationInfo(props, nodeId) {
|
|
3240
|
+
const { primary, tagContexts } = primaryForNode(props, nodeId);
|
|
3241
|
+
return { primary, tagContexts };
|
|
3242
|
+
}
|
|
3176
3243
|
|
|
3177
3244
|
// src/utils/prune-fallbacks.ts
|
|
3178
3245
|
function pruneInvalidNodeFallbacks(props, services, settings) {
|
|
@@ -3861,6 +3928,347 @@ function resolveMinMax(servicesList, services) {
|
|
|
3861
3928
|
return { min: min != null ? min : 1, ...max !== void 0 ? { max } : {} };
|
|
3862
3929
|
}
|
|
3863
3930
|
|
|
3931
|
+
// src/core/fallback-editor.ts
|
|
3932
|
+
function createFallbackEditor(options = {}) {
|
|
3933
|
+
var _a, _b;
|
|
3934
|
+
const original = cloneFallbacks(options.fallbacks);
|
|
3935
|
+
let current = cloneFallbacks(options.fallbacks);
|
|
3936
|
+
const props = options.props;
|
|
3937
|
+
const services = (_a = options.services) != null ? _a : {};
|
|
3938
|
+
const settings = (_b = options.settings) != null ? _b : {};
|
|
3939
|
+
function state() {
|
|
3940
|
+
return {
|
|
3941
|
+
original: cloneFallbacks(original),
|
|
3942
|
+
current: cloneFallbacks(current),
|
|
3943
|
+
changed: !sameFallbacks(original, current)
|
|
3944
|
+
};
|
|
3945
|
+
}
|
|
3946
|
+
function value() {
|
|
3947
|
+
return cloneFallbacks(current);
|
|
3948
|
+
}
|
|
3949
|
+
function reset() {
|
|
3950
|
+
current = cloneFallbacks(original);
|
|
3951
|
+
return state();
|
|
3952
|
+
}
|
|
3953
|
+
function get(serviceId) {
|
|
3954
|
+
var _a2, _b2;
|
|
3955
|
+
const out = [];
|
|
3956
|
+
for (const [primary, list] of Object.entries((_a2 = current.global) != null ? _a2 : {})) {
|
|
3957
|
+
if (String(primary) !== String(serviceId)) continue;
|
|
3958
|
+
out.push({
|
|
3959
|
+
scope: "global",
|
|
3960
|
+
primary,
|
|
3961
|
+
services: [...list != null ? list : []]
|
|
3962
|
+
});
|
|
3963
|
+
}
|
|
3964
|
+
if (!props) return out;
|
|
3965
|
+
for (const [nodeId, list] of Object.entries((_b2 = current.nodes) != null ? _b2 : {})) {
|
|
3966
|
+
const info = getFallbackRegistrationInfo(props, nodeId);
|
|
3967
|
+
if (String(info.primary) !== String(serviceId)) continue;
|
|
3968
|
+
out.push({
|
|
3969
|
+
scope: "node",
|
|
3970
|
+
scopeId: nodeId,
|
|
3971
|
+
primary: info.primary,
|
|
3972
|
+
services: [...list != null ? list : []]
|
|
3973
|
+
});
|
|
3974
|
+
}
|
|
3975
|
+
return out;
|
|
3976
|
+
}
|
|
3977
|
+
function getScope(context) {
|
|
3978
|
+
var _a2, _b2, _c, _d;
|
|
3979
|
+
if (context.scope === "global") {
|
|
3980
|
+
return [...(_b2 = (_a2 = current.global) == null ? void 0 : _a2[context.primary]) != null ? _b2 : []];
|
|
3981
|
+
}
|
|
3982
|
+
return [...(_d = (_c = current.nodes) == null ? void 0 : _c[context.nodeId]) != null ? _d : []];
|
|
3983
|
+
}
|
|
3984
|
+
function check(context, candidates) {
|
|
3985
|
+
var _a2, _b2;
|
|
3986
|
+
const normalized = normalizeCandidateList(
|
|
3987
|
+
candidates != null ? candidates : getScope(context),
|
|
3988
|
+
true
|
|
3989
|
+
);
|
|
3990
|
+
if (context.scope === "node" && !props) {
|
|
3991
|
+
return {
|
|
3992
|
+
context,
|
|
3993
|
+
allowed: [],
|
|
3994
|
+
rejected: normalized.map((candidate) => ({
|
|
3995
|
+
candidate,
|
|
3996
|
+
ok: false,
|
|
3997
|
+
reasons: ["missing_service_props"]
|
|
3998
|
+
})),
|
|
3999
|
+
warnings: ["missing_service_props"]
|
|
4000
|
+
};
|
|
4001
|
+
}
|
|
4002
|
+
const tempFallbacks = cloneFallbacks(current);
|
|
4003
|
+
if (context.scope === "global") {
|
|
4004
|
+
(_a2 = tempFallbacks.global) != null ? _a2 : tempFallbacks.global = {};
|
|
4005
|
+
if (normalized.length)
|
|
4006
|
+
tempFallbacks.global[context.primary] = normalized;
|
|
4007
|
+
else delete tempFallbacks.global[context.primary];
|
|
4008
|
+
} else {
|
|
4009
|
+
(_b2 = tempFallbacks.nodes) != null ? _b2 : tempFallbacks.nodes = {};
|
|
4010
|
+
if (normalized.length)
|
|
4011
|
+
tempFallbacks.nodes[context.nodeId] = normalized;
|
|
4012
|
+
else delete tempFallbacks.nodes[context.nodeId];
|
|
4013
|
+
}
|
|
4014
|
+
if (!props) {
|
|
4015
|
+
if (context.scope !== "global") {
|
|
4016
|
+
return {
|
|
4017
|
+
context,
|
|
4018
|
+
allowed: [],
|
|
4019
|
+
rejected: normalized.map((candidate) => ({
|
|
4020
|
+
candidate,
|
|
4021
|
+
ok: false,
|
|
4022
|
+
reasons: ["missing_service_props"]
|
|
4023
|
+
})),
|
|
4024
|
+
warnings: ["missing_service_props"]
|
|
4025
|
+
};
|
|
4026
|
+
}
|
|
4027
|
+
const rejected2 = [];
|
|
4028
|
+
const allowed2 = [];
|
|
4029
|
+
for (const candidate of normalized) {
|
|
4030
|
+
const reasons = [];
|
|
4031
|
+
if (String(candidate) === String(context.primary)) {
|
|
4032
|
+
reasons.push("self_reference");
|
|
4033
|
+
}
|
|
4034
|
+
if (reasons.length) {
|
|
4035
|
+
rejected2.push({ candidate, ok: false, reasons });
|
|
4036
|
+
} else {
|
|
4037
|
+
allowed2.push(candidate);
|
|
4038
|
+
}
|
|
4039
|
+
}
|
|
4040
|
+
return {
|
|
4041
|
+
context,
|
|
4042
|
+
primary: context.primary,
|
|
4043
|
+
allowed: allowed2,
|
|
4044
|
+
rejected: rejected2,
|
|
4045
|
+
warnings: []
|
|
4046
|
+
};
|
|
4047
|
+
}
|
|
4048
|
+
const fakeProps = {
|
|
4049
|
+
...props,
|
|
4050
|
+
fallbacks: tempFallbacks
|
|
4051
|
+
};
|
|
4052
|
+
const diags = collectFailedFallbacks(fakeProps, services, {
|
|
4053
|
+
...settings,
|
|
4054
|
+
mode: "dev"
|
|
4055
|
+
});
|
|
4056
|
+
const scoped = diags.filter((d) => {
|
|
4057
|
+
if (context.scope === "global") {
|
|
4058
|
+
return d.scope === "global" && String(d.primary) === String(context.primary);
|
|
4059
|
+
}
|
|
4060
|
+
return d.scope === "node" && String(d.nodeId) === String(context.nodeId);
|
|
4061
|
+
});
|
|
4062
|
+
const rejected = normalized.map((candidate) => {
|
|
4063
|
+
const reasons = scoped.filter((d) => String(d.candidate) === String(candidate)).map((d) => mapDiagReason(d.reason));
|
|
4064
|
+
return {
|
|
4065
|
+
candidate,
|
|
4066
|
+
ok: reasons.length === 0,
|
|
4067
|
+
reasons
|
|
4068
|
+
};
|
|
4069
|
+
}).filter((row) => !row.ok);
|
|
4070
|
+
const allowed = normalized.filter(
|
|
4071
|
+
(candidate) => !rejected.some(
|
|
4072
|
+
(r) => String(r.candidate) === String(candidate)
|
|
4073
|
+
)
|
|
4074
|
+
);
|
|
4075
|
+
const info = context.scope === "global" ? { ok: true, primary: context.primary } : getNodeRegistrationInfo(props, context.nodeId);
|
|
4076
|
+
const primary = (info == null ? void 0 : info.ok) ? info.primary : void 0;
|
|
4077
|
+
return {
|
|
4078
|
+
context,
|
|
4079
|
+
primary,
|
|
4080
|
+
allowed,
|
|
4081
|
+
rejected,
|
|
4082
|
+
warnings: []
|
|
4083
|
+
};
|
|
4084
|
+
}
|
|
4085
|
+
function add(context, candidate, options2) {
|
|
4086
|
+
return addMany(context, [candidate], options2);
|
|
4087
|
+
}
|
|
4088
|
+
function addMany(context, candidates, options2) {
|
|
4089
|
+
const existing = getScope(context);
|
|
4090
|
+
const merged = [...existing];
|
|
4091
|
+
const insertAt = typeof (options2 == null ? void 0 : options2.index) === "number" ? clamp(options2.index, 0, merged.length) : void 0;
|
|
4092
|
+
const incoming = normalizeCandidateList(candidates, true).filter(
|
|
4093
|
+
(id) => !merged.some((x) => String(x) === String(id))
|
|
4094
|
+
);
|
|
4095
|
+
if (insertAt === void 0) {
|
|
4096
|
+
merged.push(...incoming);
|
|
4097
|
+
} else {
|
|
4098
|
+
merged.splice(insertAt, 0, ...incoming);
|
|
4099
|
+
}
|
|
4100
|
+
return replace(context, merged, options2);
|
|
4101
|
+
}
|
|
4102
|
+
function remove(context, candidate) {
|
|
4103
|
+
const next = getScope(context).filter(
|
|
4104
|
+
(id) => String(id) !== String(candidate)
|
|
4105
|
+
);
|
|
4106
|
+
return writeScope(context, next);
|
|
4107
|
+
}
|
|
4108
|
+
function replace(context, candidates, options2) {
|
|
4109
|
+
const strict = !!(options2 == null ? void 0 : options2.strict);
|
|
4110
|
+
const normalized = normalizeCandidateList(candidates, true);
|
|
4111
|
+
const checked = check(context, normalized);
|
|
4112
|
+
const next = strict ? checked.allowed : normalized;
|
|
4113
|
+
return writeScope(context, next);
|
|
4114
|
+
}
|
|
4115
|
+
function clear(context) {
|
|
4116
|
+
return writeScope(context, []);
|
|
4117
|
+
}
|
|
4118
|
+
function eligible(context, opt) {
|
|
4119
|
+
if (!props) return [];
|
|
4120
|
+
if (context.scope === "global") {
|
|
4121
|
+
return getEligibleFallbacks({
|
|
4122
|
+
primary: context.primary,
|
|
4123
|
+
services,
|
|
4124
|
+
fallbacks: current,
|
|
4125
|
+
settings,
|
|
4126
|
+
props,
|
|
4127
|
+
exclude: opt == null ? void 0 : opt.exclude,
|
|
4128
|
+
unique: opt == null ? void 0 : opt.unique,
|
|
4129
|
+
limit: opt == null ? void 0 : opt.limit
|
|
4130
|
+
});
|
|
4131
|
+
}
|
|
4132
|
+
const info = getFallbackRegistrationInfo(props, context.nodeId);
|
|
4133
|
+
if (!info.primary) return [];
|
|
4134
|
+
return getEligibleFallbacks({
|
|
4135
|
+
primary: info.primary,
|
|
4136
|
+
nodeId: context.nodeId,
|
|
4137
|
+
tagId: info.tagContexts[0],
|
|
4138
|
+
services,
|
|
4139
|
+
fallbacks: current,
|
|
4140
|
+
settings,
|
|
4141
|
+
props,
|
|
4142
|
+
exclude: opt == null ? void 0 : opt.exclude,
|
|
4143
|
+
unique: opt == null ? void 0 : opt.unique,
|
|
4144
|
+
limit: opt == null ? void 0 : opt.limit
|
|
4145
|
+
});
|
|
4146
|
+
}
|
|
4147
|
+
function writeScope(context, nextList) {
|
|
4148
|
+
var _a2, _b2;
|
|
4149
|
+
const next = cloneFallbacks(current);
|
|
4150
|
+
if (context.scope === "global") {
|
|
4151
|
+
(_a2 = next.global) != null ? _a2 : next.global = {};
|
|
4152
|
+
if (nextList.length) {
|
|
4153
|
+
next.global[context.primary] = [...nextList];
|
|
4154
|
+
} else {
|
|
4155
|
+
delete next.global[context.primary];
|
|
4156
|
+
if (!Object.keys(next.global).length) delete next.global;
|
|
4157
|
+
}
|
|
4158
|
+
} else {
|
|
4159
|
+
(_b2 = next.nodes) != null ? _b2 : next.nodes = {};
|
|
4160
|
+
if (nextList.length) {
|
|
4161
|
+
next.nodes[context.nodeId] = [...nextList];
|
|
4162
|
+
} else {
|
|
4163
|
+
delete next.nodes[context.nodeId];
|
|
4164
|
+
if (!Object.keys(next.nodes).length) delete next.nodes;
|
|
4165
|
+
}
|
|
4166
|
+
}
|
|
4167
|
+
current = next;
|
|
4168
|
+
return state();
|
|
4169
|
+
}
|
|
4170
|
+
return {
|
|
4171
|
+
state,
|
|
4172
|
+
value,
|
|
4173
|
+
reset,
|
|
4174
|
+
get,
|
|
4175
|
+
getScope,
|
|
4176
|
+
check,
|
|
4177
|
+
add,
|
|
4178
|
+
addMany,
|
|
4179
|
+
remove,
|
|
4180
|
+
replace,
|
|
4181
|
+
clear,
|
|
4182
|
+
eligible
|
|
4183
|
+
};
|
|
4184
|
+
}
|
|
4185
|
+
function cloneFallbacks(input) {
|
|
4186
|
+
return {
|
|
4187
|
+
...(input == null ? void 0 : input.nodes) ? { nodes: cloneRecordArray(input.nodes) } : {},
|
|
4188
|
+
...(input == null ? void 0 : input.global) ? { global: cloneRecordArray(input.global) } : {}
|
|
4189
|
+
};
|
|
4190
|
+
}
|
|
4191
|
+
function cloneRecordArray(input) {
|
|
4192
|
+
const out = {};
|
|
4193
|
+
for (const [k, v] of Object.entries(input)) out[k] = [...v != null ? v : []];
|
|
4194
|
+
return out;
|
|
4195
|
+
}
|
|
4196
|
+
function sameFallbacks(a, b) {
|
|
4197
|
+
return JSON.stringify(a != null ? a : {}) === JSON.stringify(b != null ? b : {});
|
|
4198
|
+
}
|
|
4199
|
+
function normalizeCandidateList(input, preserveOrder) {
|
|
4200
|
+
const out = [];
|
|
4201
|
+
for (const item of input != null ? input : []) {
|
|
4202
|
+
if (!isValidServiceIdRef(item)) continue;
|
|
4203
|
+
const exists = out.some((x) => String(x) === String(item));
|
|
4204
|
+
if (exists) continue;
|
|
4205
|
+
out.push(item);
|
|
4206
|
+
}
|
|
4207
|
+
return preserveOrder ? out : out;
|
|
4208
|
+
}
|
|
4209
|
+
function isValidServiceIdRef(value) {
|
|
4210
|
+
return typeof value === "number" && Number.isFinite(value) || typeof value === "string" && value.trim().length > 0;
|
|
4211
|
+
}
|
|
4212
|
+
function clamp(n, min, max) {
|
|
4213
|
+
return Math.max(min, Math.min(max, n));
|
|
4214
|
+
}
|
|
4215
|
+
function getNodeRegistrationInfo(props, nodeId) {
|
|
4216
|
+
const tag = props.filters.find((t) => t.id === nodeId);
|
|
4217
|
+
if (tag) {
|
|
4218
|
+
if (!isValidServiceIdRef(tag.service_id)) {
|
|
4219
|
+
return { ok: false, reasons: ["no_primary"] };
|
|
4220
|
+
}
|
|
4221
|
+
return {
|
|
4222
|
+
ok: true,
|
|
4223
|
+
primary: tag.service_id,
|
|
4224
|
+
tagContexts: [tag.id]
|
|
4225
|
+
};
|
|
4226
|
+
}
|
|
4227
|
+
const hit = findOptionOwner(props.fields, nodeId);
|
|
4228
|
+
if (!hit) {
|
|
4229
|
+
return { ok: false, reasons: ["node_not_found"] };
|
|
4230
|
+
}
|
|
4231
|
+
if (!isValidServiceIdRef(hit.option.service_id)) {
|
|
4232
|
+
return { ok: false, reasons: ["no_primary"] };
|
|
4233
|
+
}
|
|
4234
|
+
return {
|
|
4235
|
+
ok: true,
|
|
4236
|
+
primary: hit.option.service_id,
|
|
4237
|
+
tagContexts: bindIdsToArray2(hit.field.bind_id)
|
|
4238
|
+
};
|
|
4239
|
+
}
|
|
4240
|
+
function findOptionOwner(fields, optionId) {
|
|
4241
|
+
var _a;
|
|
4242
|
+
for (const field of fields) {
|
|
4243
|
+
for (const option of (_a = field.options) != null ? _a : []) {
|
|
4244
|
+
if (option.id === optionId) return { field, option };
|
|
4245
|
+
}
|
|
4246
|
+
}
|
|
4247
|
+
return null;
|
|
4248
|
+
}
|
|
4249
|
+
function bindIdsToArray2(v) {
|
|
4250
|
+
if (Array.isArray(v)) return v.filter(Boolean);
|
|
4251
|
+
return v ? [v] : [];
|
|
4252
|
+
}
|
|
4253
|
+
function mapDiagReason(reason) {
|
|
4254
|
+
switch (String(reason)) {
|
|
4255
|
+
case "unknown_service":
|
|
4256
|
+
return "unknown_service";
|
|
4257
|
+
case "no_primary":
|
|
4258
|
+
return "no_primary";
|
|
4259
|
+
case "rate_violation":
|
|
4260
|
+
return "rate_violation";
|
|
4261
|
+
case "constraint_mismatch":
|
|
4262
|
+
return "constraint_mismatch";
|
|
4263
|
+
case "cycle":
|
|
4264
|
+
return "cycle";
|
|
4265
|
+
case "no_tag_context":
|
|
4266
|
+
return "no_tag_context";
|
|
4267
|
+
default:
|
|
4268
|
+
return "node_not_found";
|
|
4269
|
+
}
|
|
4270
|
+
}
|
|
4271
|
+
|
|
3864
4272
|
// src/core/policy.ts
|
|
3865
4273
|
var ALLOWED_SCOPES = /* @__PURE__ */ new Set([
|
|
3866
4274
|
"global",
|
|
@@ -9855,21 +10263,1525 @@ function registerEntries(registry) {
|
|
|
9855
10263
|
})
|
|
9856
10264
|
);
|
|
9857
10265
|
}
|
|
10266
|
+
|
|
10267
|
+
// src/react/fallback-editor/useFallbackEditor.ts
|
|
10268
|
+
var import_react10 = __toESM(require("react"), 1);
|
|
10269
|
+
|
|
10270
|
+
// src/react/fallback-editor/FallbackEditorProvider.tsx
|
|
10271
|
+
var import_react9 = __toESM(require("react"), 1);
|
|
10272
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
10273
|
+
var FallbackEditorContext = import_react9.default.createContext(null);
|
|
10274
|
+
function FallbackEditorProvider({
|
|
10275
|
+
children,
|
|
10276
|
+
fallbacks,
|
|
10277
|
+
props,
|
|
10278
|
+
snapshot,
|
|
10279
|
+
primaryServices,
|
|
10280
|
+
eligibleServices,
|
|
10281
|
+
settings: initialSettings,
|
|
10282
|
+
initialServiceId,
|
|
10283
|
+
initialTab = "registrations",
|
|
10284
|
+
onSettingsChange,
|
|
10285
|
+
onSave,
|
|
10286
|
+
onValidate,
|
|
10287
|
+
onReset
|
|
10288
|
+
}) {
|
|
10289
|
+
const [settings, setSettings] = import_react9.default.useState(
|
|
10290
|
+
initialSettings != null ? initialSettings : {}
|
|
10291
|
+
);
|
|
10292
|
+
const [settingsSaving, setSettingsSaving] = import_react9.default.useState(false);
|
|
10293
|
+
const [headerSaving, setHeaderSaving] = import_react9.default.useState(false);
|
|
10294
|
+
const [headerValidating, setHeaderValidating] = import_react9.default.useState(false);
|
|
10295
|
+
const [headerResetting, setHeaderResetting] = import_react9.default.useState(false);
|
|
10296
|
+
const [version, setVersion] = import_react9.default.useState(0);
|
|
10297
|
+
const [activeServiceId, setActiveServiceId] = import_react9.default.useState(initialServiceId);
|
|
10298
|
+
const [activeTab, setActiveTab] = import_react9.default.useState(initialTab);
|
|
10299
|
+
import_react9.default.useEffect(() => {
|
|
10300
|
+
setSettings(initialSettings != null ? initialSettings : {});
|
|
10301
|
+
}, [initialSettings]);
|
|
10302
|
+
const resolvedPrimaryServices = import_react9.default.useMemo(
|
|
10303
|
+
() => primaryServices != null ? primaryServices : {},
|
|
10304
|
+
[primaryServices]
|
|
10305
|
+
);
|
|
10306
|
+
const resolvedEligibleServices = import_react9.default.useMemo(
|
|
10307
|
+
() => {
|
|
10308
|
+
var _a;
|
|
10309
|
+
return (_a = eligibleServices != null ? eligibleServices : primaryServices) != null ? _a : {};
|
|
10310
|
+
},
|
|
10311
|
+
[eligibleServices, primaryServices]
|
|
10312
|
+
);
|
|
10313
|
+
const editorRef = import_react9.default.useRef(null);
|
|
10314
|
+
const buildEditor = import_react9.default.useCallback(
|
|
10315
|
+
(next) => {
|
|
10316
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
10317
|
+
const currentValue = (_a = editorRef.current) == null ? void 0 : _a.value();
|
|
10318
|
+
editorRef.current = createFallbackEditor({
|
|
10319
|
+
fallbacks: (_d = (_c = (_b = next == null ? void 0 : next.fallbacks) != null ? _b : currentValue) != null ? _c : fallbacks) != null ? _d : {},
|
|
10320
|
+
props: (_e = next == null ? void 0 : next.props) != null ? _e : props,
|
|
10321
|
+
snapshot: (_f = next == null ? void 0 : next.snapshot) != null ? _f : snapshot,
|
|
10322
|
+
services: (_g = next == null ? void 0 : next.services) != null ? _g : resolvedEligibleServices,
|
|
10323
|
+
settings: (_h = next == null ? void 0 : next.settings) != null ? _h : settings
|
|
10324
|
+
});
|
|
10325
|
+
setVersion((v) => v + 1);
|
|
10326
|
+
},
|
|
10327
|
+
[fallbacks, props, snapshot, resolvedEligibleServices, settings]
|
|
10328
|
+
);
|
|
10329
|
+
if (!editorRef.current) {
|
|
10330
|
+
editorRef.current = createFallbackEditor({
|
|
10331
|
+
fallbacks: fallbacks != null ? fallbacks : {},
|
|
10332
|
+
props,
|
|
10333
|
+
snapshot,
|
|
10334
|
+
services: resolvedEligibleServices,
|
|
10335
|
+
settings
|
|
10336
|
+
});
|
|
10337
|
+
}
|
|
10338
|
+
import_react9.default.useEffect(() => {
|
|
10339
|
+
buildEditor({
|
|
10340
|
+
fallbacks: fallbacks != null ? fallbacks : {},
|
|
10341
|
+
props,
|
|
10342
|
+
snapshot,
|
|
10343
|
+
services: resolvedEligibleServices,
|
|
10344
|
+
settings
|
|
10345
|
+
});
|
|
10346
|
+
}, [fallbacks, props, snapshot, resolvedEligibleServices, buildEditor]);
|
|
10347
|
+
const editor = editorRef.current;
|
|
10348
|
+
const bump = import_react9.default.useCallback(() => {
|
|
10349
|
+
setVersion((v) => v + 1);
|
|
10350
|
+
}, []);
|
|
10351
|
+
const syncAfterMutation = import_react9.default.useCallback(() => {
|
|
10352
|
+
bump();
|
|
10353
|
+
}, [bump]);
|
|
10354
|
+
const reset = import_react9.default.useCallback(() => {
|
|
10355
|
+
editor.reset();
|
|
10356
|
+
syncAfterMutation();
|
|
10357
|
+
}, [editor, syncAfterMutation]);
|
|
10358
|
+
const add = import_react9.default.useCallback(
|
|
10359
|
+
(context, candidate, options) => {
|
|
10360
|
+
const next = editor.add(context, candidate, options);
|
|
10361
|
+
syncAfterMutation();
|
|
10362
|
+
return next;
|
|
10363
|
+
},
|
|
10364
|
+
[editor, syncAfterMutation]
|
|
10365
|
+
);
|
|
10366
|
+
const addMany = import_react9.default.useCallback(
|
|
10367
|
+
(context, candidates, options) => {
|
|
10368
|
+
const next = editor.addMany(context, candidates, options);
|
|
10369
|
+
syncAfterMutation();
|
|
10370
|
+
return next;
|
|
10371
|
+
},
|
|
10372
|
+
[editor, syncAfterMutation]
|
|
10373
|
+
);
|
|
10374
|
+
const remove = import_react9.default.useCallback(
|
|
10375
|
+
(context, candidate) => {
|
|
10376
|
+
const next = editor.remove(context, candidate);
|
|
10377
|
+
syncAfterMutation();
|
|
10378
|
+
return next;
|
|
10379
|
+
},
|
|
10380
|
+
[editor, syncAfterMutation]
|
|
10381
|
+
);
|
|
10382
|
+
const replace = import_react9.default.useCallback(
|
|
10383
|
+
(context, candidates, options) => {
|
|
10384
|
+
const next = editor.replace(context, candidates, options);
|
|
10385
|
+
syncAfterMutation();
|
|
10386
|
+
return next;
|
|
10387
|
+
},
|
|
10388
|
+
[editor, syncAfterMutation]
|
|
10389
|
+
);
|
|
10390
|
+
const clear = import_react9.default.useCallback(
|
|
10391
|
+
(context) => {
|
|
10392
|
+
const next = editor.clear(context);
|
|
10393
|
+
syncAfterMutation();
|
|
10394
|
+
return next;
|
|
10395
|
+
},
|
|
10396
|
+
[editor, syncAfterMutation]
|
|
10397
|
+
);
|
|
10398
|
+
const saveSettings = import_react9.default.useCallback(
|
|
10399
|
+
async (next) => {
|
|
10400
|
+
setSettingsSaving(true);
|
|
10401
|
+
try {
|
|
10402
|
+
const resolved = onSettingsChange ? await onSettingsChange(next) : next;
|
|
10403
|
+
const finalSettings = resolved != null ? resolved : next;
|
|
10404
|
+
setSettings(finalSettings);
|
|
10405
|
+
buildEditor({
|
|
10406
|
+
settings: finalSettings,
|
|
10407
|
+
fallbacks: editor.value()
|
|
10408
|
+
});
|
|
10409
|
+
return finalSettings;
|
|
10410
|
+
} finally {
|
|
10411
|
+
setSettingsSaving(false);
|
|
10412
|
+
}
|
|
10413
|
+
},
|
|
10414
|
+
[onSettingsChange, buildEditor, editor]
|
|
10415
|
+
);
|
|
10416
|
+
const saveFallbacks = import_react9.default.useCallback(async () => {
|
|
10417
|
+
const next = editor.value();
|
|
10418
|
+
setHeaderSaving(true);
|
|
10419
|
+
try {
|
|
10420
|
+
const resolved = onSave ? await onSave(next) : next;
|
|
10421
|
+
if (resolved) {
|
|
10422
|
+
buildEditor({ fallbacks: resolved });
|
|
10423
|
+
}
|
|
10424
|
+
return resolved;
|
|
10425
|
+
} finally {
|
|
10426
|
+
setHeaderSaving(false);
|
|
10427
|
+
}
|
|
10428
|
+
}, [editor, onSave, buildEditor]);
|
|
10429
|
+
const validateFallbacks2 = import_react9.default.useCallback(async () => {
|
|
10430
|
+
const next = editor.value();
|
|
10431
|
+
setHeaderValidating(true);
|
|
10432
|
+
try {
|
|
10433
|
+
if (onValidate) {
|
|
10434
|
+
await onValidate(next);
|
|
10435
|
+
}
|
|
10436
|
+
} finally {
|
|
10437
|
+
setHeaderValidating(false);
|
|
10438
|
+
}
|
|
10439
|
+
}, [editor, onValidate]);
|
|
10440
|
+
const resetEditor = import_react9.default.useCallback(async () => {
|
|
10441
|
+
setHeaderResetting(true);
|
|
10442
|
+
try {
|
|
10443
|
+
editor.reset();
|
|
10444
|
+
syncAfterMutation();
|
|
10445
|
+
if (onReset) {
|
|
10446
|
+
await onReset();
|
|
10447
|
+
}
|
|
10448
|
+
} finally {
|
|
10449
|
+
setHeaderResetting(false);
|
|
10450
|
+
}
|
|
10451
|
+
}, [editor, syncAfterMutation, onReset]);
|
|
10452
|
+
const value = import_react9.default.useMemo(() => editor.value(), [editor, version]);
|
|
10453
|
+
const state = import_react9.default.useMemo(() => editor.state(), [editor, version]);
|
|
10454
|
+
const ctx = import_react9.default.useMemo(
|
|
10455
|
+
() => ({
|
|
10456
|
+
editor,
|
|
10457
|
+
version,
|
|
10458
|
+
serviceProps: props,
|
|
10459
|
+
snapshot,
|
|
10460
|
+
primaryServices: resolvedPrimaryServices,
|
|
10461
|
+
eligibleServices: resolvedEligibleServices,
|
|
10462
|
+
activeServiceId,
|
|
10463
|
+
setActiveServiceId,
|
|
10464
|
+
activeTab,
|
|
10465
|
+
setActiveTab,
|
|
10466
|
+
state,
|
|
10467
|
+
value,
|
|
10468
|
+
settings,
|
|
10469
|
+
settingsSaving,
|
|
10470
|
+
headerSaving,
|
|
10471
|
+
headerValidating,
|
|
10472
|
+
headerResetting,
|
|
10473
|
+
saveSettings,
|
|
10474
|
+
saveFallbacks,
|
|
10475
|
+
validateFallbacks: validateFallbacks2,
|
|
10476
|
+
resetEditor,
|
|
10477
|
+
reset,
|
|
10478
|
+
get: editor.get,
|
|
10479
|
+
getScope: editor.getScope,
|
|
10480
|
+
check: editor.check,
|
|
10481
|
+
eligible: editor.eligible,
|
|
10482
|
+
add,
|
|
10483
|
+
addMany,
|
|
10484
|
+
remove,
|
|
10485
|
+
replace,
|
|
10486
|
+
clear
|
|
10487
|
+
}),
|
|
10488
|
+
[
|
|
10489
|
+
editor,
|
|
10490
|
+
version,
|
|
10491
|
+
props,
|
|
10492
|
+
snapshot,
|
|
10493
|
+
resolvedPrimaryServices,
|
|
10494
|
+
resolvedEligibleServices,
|
|
10495
|
+
activeServiceId,
|
|
10496
|
+
activeTab,
|
|
10497
|
+
state,
|
|
10498
|
+
value,
|
|
10499
|
+
settings,
|
|
10500
|
+
settingsSaving,
|
|
10501
|
+
headerSaving,
|
|
10502
|
+
headerValidating,
|
|
10503
|
+
headerResetting,
|
|
10504
|
+
saveSettings,
|
|
10505
|
+
saveFallbacks,
|
|
10506
|
+
validateFallbacks2,
|
|
10507
|
+
resetEditor,
|
|
10508
|
+
reset,
|
|
10509
|
+
add,
|
|
10510
|
+
addMany,
|
|
10511
|
+
remove,
|
|
10512
|
+
replace,
|
|
10513
|
+
clear
|
|
10514
|
+
]
|
|
10515
|
+
);
|
|
10516
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FallbackEditorContext.Provider, { value: ctx, children });
|
|
10517
|
+
}
|
|
10518
|
+
function useFallbackEditorContext() {
|
|
10519
|
+
const ctx = import_react9.default.useContext(FallbackEditorContext);
|
|
10520
|
+
if (!ctx) {
|
|
10521
|
+
throw new Error(
|
|
10522
|
+
"useFallbackEditorContext must be used inside FallbackEditorProvider"
|
|
10523
|
+
);
|
|
10524
|
+
}
|
|
10525
|
+
return ctx;
|
|
10526
|
+
}
|
|
10527
|
+
|
|
10528
|
+
// src/react/fallback-editor/useFallbackEditor.ts
|
|
10529
|
+
function useFallbackEditor() {
|
|
10530
|
+
return useFallbackEditorContext();
|
|
10531
|
+
}
|
|
10532
|
+
function useActiveFallbackRegistrations() {
|
|
10533
|
+
const { activeServiceId, get, version } = useFallbackEditorContext();
|
|
10534
|
+
return import_react10.default.useMemo(() => {
|
|
10535
|
+
if (activeServiceId === void 0 || activeServiceId === null)
|
|
10536
|
+
return [];
|
|
10537
|
+
return get(activeServiceId);
|
|
10538
|
+
}, [activeServiceId, get, version]);
|
|
10539
|
+
}
|
|
10540
|
+
function usePrimaryServiceList() {
|
|
10541
|
+
const { primaryServices, version } = useFallbackEditorContext();
|
|
10542
|
+
return import_react10.default.useMemo(() => {
|
|
10543
|
+
return Object.values(primaryServices != null ? primaryServices : {});
|
|
10544
|
+
}, [primaryServices, version]);
|
|
10545
|
+
}
|
|
10546
|
+
function useEligibleServiceList() {
|
|
10547
|
+
const { eligibleServices, version } = useFallbackEditorContext();
|
|
10548
|
+
return import_react10.default.useMemo(() => {
|
|
10549
|
+
return Object.values(eligibleServices != null ? eligibleServices : {});
|
|
10550
|
+
}, [eligibleServices, version]);
|
|
10551
|
+
}
|
|
10552
|
+
|
|
10553
|
+
// src/react/fallback-editor/FallbackEditor.tsx
|
|
10554
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
10555
|
+
function FallbackEditor({
|
|
10556
|
+
className,
|
|
10557
|
+
fallbacks,
|
|
10558
|
+
props,
|
|
10559
|
+
snapshot,
|
|
10560
|
+
primaryServices,
|
|
10561
|
+
eligibleServices,
|
|
10562
|
+
settings,
|
|
10563
|
+
initialServiceId,
|
|
10564
|
+
onSettingsChange,
|
|
10565
|
+
onSave,
|
|
10566
|
+
onValidate,
|
|
10567
|
+
onReset
|
|
10568
|
+
}) {
|
|
10569
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
10570
|
+
FallbackEditorProvider,
|
|
10571
|
+
{
|
|
10572
|
+
fallbacks,
|
|
10573
|
+
props,
|
|
10574
|
+
snapshot,
|
|
10575
|
+
primaryServices,
|
|
10576
|
+
eligibleServices,
|
|
10577
|
+
settings,
|
|
10578
|
+
initialServiceId,
|
|
10579
|
+
onSettingsChange,
|
|
10580
|
+
onSave,
|
|
10581
|
+
onValidate,
|
|
10582
|
+
onReset,
|
|
10583
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FallbackEditorInner, { className })
|
|
10584
|
+
}
|
|
10585
|
+
);
|
|
10586
|
+
}
|
|
10587
|
+
function FallbackEditorInner({ className }) {
|
|
10588
|
+
const {
|
|
10589
|
+
activeTab,
|
|
10590
|
+
setActiveTab,
|
|
10591
|
+
activeServiceId,
|
|
10592
|
+
saveFallbacks,
|
|
10593
|
+
validateFallbacks: validateFallbacks2,
|
|
10594
|
+
resetEditor,
|
|
10595
|
+
headerSaving,
|
|
10596
|
+
headerValidating,
|
|
10597
|
+
headerResetting
|
|
10598
|
+
} = useFallbackEditor();
|
|
10599
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
10600
|
+
"div",
|
|
10601
|
+
{
|
|
10602
|
+
className: [
|
|
10603
|
+
"min-h-screen bg-zinc-100 p-4 text-zinc-900 dark:bg-zinc-950 dark:text-zinc-100",
|
|
10604
|
+
className
|
|
10605
|
+
].filter(Boolean).join(" "),
|
|
10606
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-auto flex max-w-7xl flex-col gap-4", children: [
|
|
10607
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
10608
|
+
FallbackEditorHeader,
|
|
10609
|
+
{
|
|
10610
|
+
onReset: resetEditor,
|
|
10611
|
+
onValidate: validateFallbacks2,
|
|
10612
|
+
onSave: saveFallbacks,
|
|
10613
|
+
resetting: headerResetting,
|
|
10614
|
+
validating: headerValidating,
|
|
10615
|
+
saving: headerSaving
|
|
10616
|
+
}
|
|
10617
|
+
),
|
|
10618
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "grid gap-4 xl:grid-cols-[300px_minmax(0,1fr)_360px]", children: [
|
|
10619
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FallbackServiceSidebar, {}),
|
|
10620
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex min-h-0 flex-col gap-4", children: [
|
|
10621
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap items-start justify-between gap-4", children: [
|
|
10622
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
|
|
10623
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { className: "text-lg font-semibold text-zinc-900 dark:text-zinc-100", children: activeServiceId !== void 0 ? `Service #${String(activeServiceId)}` : "No service selected" }),
|
|
10624
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mt-1 text-sm text-zinc-500 dark:text-zinc-400", children: "Edit fallback registrations and inspect validation." })
|
|
10625
|
+
] }),
|
|
10626
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex gap-2", children: [
|
|
10627
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
10628
|
+
TabButton,
|
|
10629
|
+
{
|
|
10630
|
+
active: activeTab === "registrations",
|
|
10631
|
+
onClick: () => setActiveTab("registrations"),
|
|
10632
|
+
children: "Registrations"
|
|
10633
|
+
}
|
|
10634
|
+
),
|
|
10635
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
10636
|
+
TabButton,
|
|
10637
|
+
{
|
|
10638
|
+
active: activeTab === "settings",
|
|
10639
|
+
onClick: () => setActiveTab("settings"),
|
|
10640
|
+
children: "Settings"
|
|
10641
|
+
}
|
|
10642
|
+
)
|
|
10643
|
+
] })
|
|
10644
|
+
] }) }),
|
|
10645
|
+
activeTab === "registrations" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FallbackRegistrationsPanel, {}) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FallbackSettingsPanel, {})
|
|
10646
|
+
] }),
|
|
10647
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FallbackDetailsPanel, {})
|
|
10648
|
+
] })
|
|
10649
|
+
] })
|
|
10650
|
+
}
|
|
10651
|
+
);
|
|
10652
|
+
}
|
|
10653
|
+
function TabButton({
|
|
10654
|
+
active,
|
|
10655
|
+
onClick,
|
|
10656
|
+
children
|
|
10657
|
+
}) {
|
|
10658
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
10659
|
+
"button",
|
|
10660
|
+
{
|
|
10661
|
+
type: "button",
|
|
10662
|
+
onClick,
|
|
10663
|
+
className: [
|
|
10664
|
+
"rounded-xl px-3 py-2 text-sm font-medium transition",
|
|
10665
|
+
active ? "bg-blue-600 text-white" : "border border-zinc-300 bg-white text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-200 dark:hover:bg-zinc-800"
|
|
10666
|
+
].join(" "),
|
|
10667
|
+
children
|
|
10668
|
+
}
|
|
10669
|
+
);
|
|
10670
|
+
}
|
|
10671
|
+
|
|
10672
|
+
// src/react/fallback-editor/VirtualServiceList.tsx
|
|
10673
|
+
var import_react17 = __toESM(require("react"), 1);
|
|
10674
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
10675
|
+
function VirtualServiceList({
|
|
10676
|
+
items,
|
|
10677
|
+
selected,
|
|
10678
|
+
onToggle,
|
|
10679
|
+
height = 420,
|
|
10680
|
+
rowHeight = 52,
|
|
10681
|
+
emptyText = "No services found."
|
|
10682
|
+
}) {
|
|
10683
|
+
const [scrollTop, setScrollTop] = import_react17.default.useState(0);
|
|
10684
|
+
const total = items.length;
|
|
10685
|
+
const visibleCount = Math.ceil(height / rowHeight);
|
|
10686
|
+
const overscan = 8;
|
|
10687
|
+
const start = Math.max(0, Math.floor(scrollTop / rowHeight) - overscan);
|
|
10688
|
+
const end = Math.min(total, start + visibleCount + overscan * 2);
|
|
10689
|
+
const visible = items.slice(start, end);
|
|
10690
|
+
if (total === 0) {
|
|
10691
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
10692
|
+
"div",
|
|
10693
|
+
{
|
|
10694
|
+
className: "flex items-center justify-center rounded-xl border border-zinc-200 bg-zinc-50 text-sm text-zinc-500 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-400",
|
|
10695
|
+
style: { height },
|
|
10696
|
+
children: emptyText
|
|
10697
|
+
}
|
|
10698
|
+
);
|
|
10699
|
+
}
|
|
10700
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
10701
|
+
"div",
|
|
10702
|
+
{
|
|
10703
|
+
className: "overflow-auto rounded-xl border border-zinc-200 dark:border-zinc-800",
|
|
10704
|
+
style: { height },
|
|
10705
|
+
onScroll: (e) => setScrollTop(e.currentTarget.scrollTop),
|
|
10706
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "relative", style: { height: total * rowHeight }, children: visible.map((item, i) => {
|
|
10707
|
+
var _a, _b;
|
|
10708
|
+
const index = start + i;
|
|
10709
|
+
const key = String(item.id);
|
|
10710
|
+
const checked = selected.has(key);
|
|
10711
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
10712
|
+
"button",
|
|
10713
|
+
{
|
|
10714
|
+
type: "button",
|
|
10715
|
+
onClick: () => onToggle(item.id),
|
|
10716
|
+
className: "absolute left-0 right-0 flex items-center justify-between border-b border-zinc-100 bg-white px-3 text-left hover:bg-zinc-50 dark:border-zinc-800 dark:bg-zinc-900 dark:hover:bg-zinc-800",
|
|
10717
|
+
style: {
|
|
10718
|
+
top: index * rowHeight,
|
|
10719
|
+
height: rowHeight
|
|
10720
|
+
},
|
|
10721
|
+
children: [
|
|
10722
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "min-w-0", children: [
|
|
10723
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "truncate text-sm font-medium text-zinc-900 dark:text-zinc-100", children: [
|
|
10724
|
+
"#",
|
|
10725
|
+
String(item.id),
|
|
10726
|
+
" \xB7",
|
|
10727
|
+
" ",
|
|
10728
|
+
(_a = item.name) != null ? _a : "Unnamed"
|
|
10729
|
+
] }),
|
|
10730
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mt-0.5 text-xs text-zinc-500 dark:text-zinc-400", children: [
|
|
10731
|
+
(_b = item.platform) != null ? _b : "Unknown",
|
|
10732
|
+
typeof item.rate === "number" ? ` \xB7 rate ${item.rate}` : ""
|
|
10733
|
+
] })
|
|
10734
|
+
] }),
|
|
10735
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
10736
|
+
"input",
|
|
10737
|
+
{
|
|
10738
|
+
type: "checkbox",
|
|
10739
|
+
checked,
|
|
10740
|
+
readOnly: true,
|
|
10741
|
+
className: "h-4 w-4 rounded border-zinc-300"
|
|
10742
|
+
}
|
|
10743
|
+
)
|
|
10744
|
+
]
|
|
10745
|
+
},
|
|
10746
|
+
key
|
|
10747
|
+
);
|
|
10748
|
+
}) })
|
|
10749
|
+
}
|
|
10750
|
+
);
|
|
10751
|
+
}
|
|
10752
|
+
|
|
10753
|
+
// src/react/fallback-editor/FallbackDetailsPanel.tsx
|
|
10754
|
+
var import_react18 = __toESM(require("react"), 1);
|
|
10755
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
10756
|
+
function FallbackDetailsPanel() {
|
|
10757
|
+
var _a, _b, _c, _d, _e, _f;
|
|
10758
|
+
const { activeServiceId, state, settings } = useFallbackEditor();
|
|
10759
|
+
const services = usePrimaryServiceList();
|
|
10760
|
+
const service = import_react18.default.useMemo(
|
|
10761
|
+
() => services.find((s) => String(s.id) === String(activeServiceId)),
|
|
10762
|
+
[services, activeServiceId]
|
|
10763
|
+
);
|
|
10764
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("aside", { className: "flex min-h-0 flex-col gap-4", children: [
|
|
10765
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
10766
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Primary service info" }),
|
|
10767
|
+
!service ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "mt-3 text-sm text-zinc-500 dark:text-zinc-400", children: "No service selected." }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "mt-3 space-y-2 text-sm", children: [
|
|
10768
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Detail, { label: "ID", value: String(service.id) }),
|
|
10769
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
10770
|
+
Detail,
|
|
10771
|
+
{
|
|
10772
|
+
label: "Name",
|
|
10773
|
+
value: (_a = service.name) != null ? _a : "Unnamed"
|
|
10774
|
+
}
|
|
10775
|
+
),
|
|
10776
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
10777
|
+
Detail,
|
|
10778
|
+
{
|
|
10779
|
+
label: "Platform",
|
|
10780
|
+
value: (_b = service.platform) != null ? _b : "\u2014"
|
|
10781
|
+
}
|
|
10782
|
+
),
|
|
10783
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
10784
|
+
Detail,
|
|
10785
|
+
{
|
|
10786
|
+
label: "Rate",
|
|
10787
|
+
value: typeof service.rate === "number" ? String(service.rate) : "\u2014"
|
|
10788
|
+
}
|
|
10789
|
+
),
|
|
10790
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
10791
|
+
Detail,
|
|
10792
|
+
{
|
|
10793
|
+
label: "Changed",
|
|
10794
|
+
value: state.changed ? "yes" : "no"
|
|
10795
|
+
}
|
|
10796
|
+
)
|
|
10797
|
+
] })
|
|
10798
|
+
] }),
|
|
10799
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
10800
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Active policy" }),
|
|
10801
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "mt-3 space-y-2 text-sm", children: [
|
|
10802
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
10803
|
+
Detail,
|
|
10804
|
+
{
|
|
10805
|
+
label: "Constraint fit",
|
|
10806
|
+
value: settings.requireConstraintFit ? "enabled" : "disabled"
|
|
10807
|
+
}
|
|
10808
|
+
),
|
|
10809
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
10810
|
+
Detail,
|
|
10811
|
+
{
|
|
10812
|
+
label: "Rate policy",
|
|
10813
|
+
value: ((_c = settings.ratePolicy) == null ? void 0 : _c.kind) === "within_pct" ? `within_pct (${settings.ratePolicy.pct}%)` : ((_d = settings.ratePolicy) == null ? void 0 : _d.kind) === "at_least_pct_lower" ? `at_least_pct_lower (${settings.ratePolicy.pct}%)` : "lte_primary"
|
|
10814
|
+
}
|
|
10815
|
+
),
|
|
10816
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
10817
|
+
Detail,
|
|
10818
|
+
{
|
|
10819
|
+
label: "Strategy",
|
|
10820
|
+
value: (_e = settings.selectionStrategy) != null ? _e : "priority"
|
|
10821
|
+
}
|
|
10822
|
+
),
|
|
10823
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Detail, { label: "Mode", value: (_f = settings.mode) != null ? _f : "strict" })
|
|
10824
|
+
] })
|
|
10825
|
+
] }),
|
|
10826
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
10827
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Current payload" }),
|
|
10828
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { className: "mt-3 overflow-auto rounded-xl bg-zinc-950 p-3 text-xs text-zinc-100", children: JSON.stringify(state.current, null, 2) })
|
|
10829
|
+
] })
|
|
10830
|
+
] });
|
|
10831
|
+
}
|
|
10832
|
+
function Detail({ label, value }) {
|
|
10833
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-start justify-between gap-4", children: [
|
|
10834
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-zinc-500 dark:text-zinc-400", children: label }),
|
|
10835
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-right text-zinc-900 dark:text-zinc-100", children: value })
|
|
10836
|
+
] });
|
|
10837
|
+
}
|
|
10838
|
+
|
|
10839
|
+
// src/react/fallback-editor/FallbackEditorHeader.tsx
|
|
10840
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
10841
|
+
function FallbackEditorHeader({
|
|
10842
|
+
onReset,
|
|
10843
|
+
onValidate,
|
|
10844
|
+
onSave,
|
|
10845
|
+
resetting = false,
|
|
10846
|
+
validating = false,
|
|
10847
|
+
saving = false
|
|
10848
|
+
}) {
|
|
10849
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col gap-3 rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900 md:flex-row md:items-center md:justify-between", children: [
|
|
10850
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
10851
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h1", { className: "text-lg font-semibold text-zinc-900 dark:text-zinc-100", children: "Fallback Editor" }),
|
|
10852
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "mt-1 text-sm text-zinc-500 dark:text-zinc-400", children: "Manage global and node-scoped fallback registrations with live validation hints." })
|
|
10853
|
+
] }),
|
|
10854
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-wrap gap-2", children: [
|
|
10855
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
10856
|
+
"button",
|
|
10857
|
+
{
|
|
10858
|
+
type: "button",
|
|
10859
|
+
onClick: onReset,
|
|
10860
|
+
disabled: resetting,
|
|
10861
|
+
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 hover:bg-zinc-50 disabled:cursor-not-allowed disabled:opacity-60 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
10862
|
+
children: resetting ? "Resetting..." : "Reset"
|
|
10863
|
+
}
|
|
10864
|
+
),
|
|
10865
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
10866
|
+
"button",
|
|
10867
|
+
{
|
|
10868
|
+
type: "button",
|
|
10869
|
+
onClick: onValidate,
|
|
10870
|
+
disabled: validating,
|
|
10871
|
+
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 hover:bg-zinc-50 disabled:cursor-not-allowed disabled:opacity-60 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
10872
|
+
children: validating ? "Validating..." : "Validate"
|
|
10873
|
+
}
|
|
10874
|
+
),
|
|
10875
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
10876
|
+
"button",
|
|
10877
|
+
{
|
|
10878
|
+
type: "button",
|
|
10879
|
+
onClick: onSave,
|
|
10880
|
+
disabled: saving,
|
|
10881
|
+
className: "rounded-xl bg-blue-600 px-3 py-2 text-sm font-medium text-white hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-60",
|
|
10882
|
+
children: saving ? "Saving..." : "Save"
|
|
10883
|
+
}
|
|
10884
|
+
)
|
|
10885
|
+
] })
|
|
10886
|
+
] });
|
|
10887
|
+
}
|
|
10888
|
+
|
|
10889
|
+
// src/react/fallback-editor/FallbackSettingsPanel.tsx
|
|
10890
|
+
var import_react19 = __toESM(require("react"), 1);
|
|
10891
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
10892
|
+
function FallbackSettingsPanel() {
|
|
10893
|
+
var _a, _b, _c;
|
|
10894
|
+
const { settings, saveSettings, settingsSaving } = useFallbackEditorContext();
|
|
10895
|
+
const [draft, setDraft] = import_react19.default.useState(settings);
|
|
10896
|
+
const [error, setError] = import_react19.default.useState(null);
|
|
10897
|
+
const [saved, setSaved] = import_react19.default.useState(false);
|
|
10898
|
+
import_react19.default.useEffect(() => {
|
|
10899
|
+
setDraft(settings);
|
|
10900
|
+
setSaved(false);
|
|
10901
|
+
setError(null);
|
|
10902
|
+
}, [settings]);
|
|
10903
|
+
const changed = JSON.stringify(draft != null ? draft : {}) !== JSON.stringify(settings != null ? settings : {});
|
|
10904
|
+
async function handleSave() {
|
|
10905
|
+
setError(null);
|
|
10906
|
+
setSaved(false);
|
|
10907
|
+
try {
|
|
10908
|
+
await saveSettings(draft);
|
|
10909
|
+
setSaved(true);
|
|
10910
|
+
} catch (err) {
|
|
10911
|
+
setError(
|
|
10912
|
+
err instanceof Error ? err.message : "Failed to save fallback settings."
|
|
10913
|
+
);
|
|
10914
|
+
}
|
|
10915
|
+
}
|
|
10916
|
+
function setRatePolicy(next) {
|
|
10917
|
+
setDraft((prev) => ({
|
|
10918
|
+
...prev,
|
|
10919
|
+
ratePolicy: next
|
|
10920
|
+
}));
|
|
10921
|
+
}
|
|
10922
|
+
const ratePolicy = (_a = draft.ratePolicy) != null ? _a : { kind: "lte_primary" };
|
|
10923
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
10924
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "mb-4 flex items-start justify-between gap-3", children: [
|
|
10925
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
|
|
10926
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Fallback settings" }),
|
|
10927
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: "These settings can be persisted by the host and returned into the editor." })
|
|
10928
|
+
] }),
|
|
10929
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
10930
|
+
"button",
|
|
10931
|
+
{
|
|
10932
|
+
type: "button",
|
|
10933
|
+
onClick: handleSave,
|
|
10934
|
+
disabled: !changed || settingsSaving,
|
|
10935
|
+
className: [
|
|
10936
|
+
"rounded-xl px-3 py-2 text-sm font-medium transition",
|
|
10937
|
+
!changed || settingsSaving ? "cursor-not-allowed bg-zinc-200 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-500" : "bg-blue-600 text-white hover:bg-blue-700"
|
|
10938
|
+
].join(" "),
|
|
10939
|
+
children: settingsSaving ? "Saving..." : "Save settings"
|
|
10940
|
+
}
|
|
10941
|
+
)
|
|
10942
|
+
] }),
|
|
10943
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "space-y-4", children: [
|
|
10944
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
10945
|
+
SettingRow,
|
|
10946
|
+
{
|
|
10947
|
+
title: "Require constraint fit",
|
|
10948
|
+
hint: "Reject or warn when a candidate does not match effective tag constraints.",
|
|
10949
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
10950
|
+
"button",
|
|
10951
|
+
{
|
|
10952
|
+
type: "button",
|
|
10953
|
+
onClick: () => setDraft((prev) => ({
|
|
10954
|
+
...prev,
|
|
10955
|
+
requireConstraintFit: !(prev == null ? void 0 : prev.requireConstraintFit)
|
|
10956
|
+
})),
|
|
10957
|
+
className: [
|
|
10958
|
+
"inline-flex items-center gap-2 rounded-full border px-3 py-2 text-sm",
|
|
10959
|
+
draft.requireConstraintFit ? "border-green-300 bg-green-50 text-green-700 dark:border-green-900/50 dark:bg-green-950/30 dark:text-green-300" : "border-zinc-300 bg-white text-zinc-600 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-300"
|
|
10960
|
+
].join(" "),
|
|
10961
|
+
children: [
|
|
10962
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: draft.requireConstraintFit ? "Enabled" : "Disabled" }),
|
|
10963
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
10964
|
+
"span",
|
|
10965
|
+
{
|
|
10966
|
+
className: [
|
|
10967
|
+
"h-2.5 w-2.5 rounded-full",
|
|
10968
|
+
draft.requireConstraintFit ? "bg-green-500" : "bg-zinc-400"
|
|
10969
|
+
].join(" ")
|
|
10970
|
+
}
|
|
10971
|
+
)
|
|
10972
|
+
]
|
|
10973
|
+
}
|
|
10974
|
+
)
|
|
10975
|
+
}
|
|
10976
|
+
),
|
|
10977
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
10978
|
+
SettingRow,
|
|
10979
|
+
{
|
|
10980
|
+
title: "Rate policy",
|
|
10981
|
+
hint: "Controls how fallback service rates are compared against the primary service.",
|
|
10982
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-2 md:items-end", children: [
|
|
10983
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
10984
|
+
"select",
|
|
10985
|
+
{
|
|
10986
|
+
value: ratePolicy.kind,
|
|
10987
|
+
onChange: (e) => {
|
|
10988
|
+
const kind = e.target.value;
|
|
10989
|
+
if (kind === "lte_primary") {
|
|
10990
|
+
setRatePolicy({ kind: "lte_primary" });
|
|
10991
|
+
return;
|
|
10992
|
+
}
|
|
10993
|
+
if (kind === "within_pct") {
|
|
10994
|
+
setRatePolicy({
|
|
10995
|
+
kind: "within_pct",
|
|
10996
|
+
pct: ratePolicy.kind === "within_pct" || ratePolicy.kind === "at_least_pct_lower" ? ratePolicy.pct : 10
|
|
10997
|
+
});
|
|
10998
|
+
return;
|
|
10999
|
+
}
|
|
11000
|
+
setRatePolicy({
|
|
11001
|
+
kind: "at_least_pct_lower",
|
|
11002
|
+
pct: ratePolicy.kind === "within_pct" || ratePolicy.kind === "at_least_pct_lower" ? ratePolicy.pct : 10
|
|
11003
|
+
});
|
|
11004
|
+
},
|
|
11005
|
+
className: "w-56 rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100",
|
|
11006
|
+
children: [
|
|
11007
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "lte_primary", children: "lte_primary" }),
|
|
11008
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "within_pct", children: "within_pct" }),
|
|
11009
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "at_least_pct_lower", children: "at_least_pct_lower" })
|
|
11010
|
+
]
|
|
11011
|
+
}
|
|
11012
|
+
),
|
|
11013
|
+
(ratePolicy.kind === "within_pct" || ratePolicy.kind === "at_least_pct_lower") && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
11014
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
11015
|
+
"input",
|
|
11016
|
+
{
|
|
11017
|
+
type: "number",
|
|
11018
|
+
min: 0,
|
|
11019
|
+
step: "0.01",
|
|
11020
|
+
value: ratePolicy.pct,
|
|
11021
|
+
onChange: (e) => {
|
|
11022
|
+
const pct = Number(e.target.value || 0);
|
|
11023
|
+
if (ratePolicy.kind === "within_pct") {
|
|
11024
|
+
setRatePolicy({
|
|
11025
|
+
kind: "within_pct",
|
|
11026
|
+
pct
|
|
11027
|
+
});
|
|
11028
|
+
return;
|
|
11029
|
+
}
|
|
11030
|
+
setRatePolicy({
|
|
11031
|
+
kind: "at_least_pct_lower",
|
|
11032
|
+
pct
|
|
11033
|
+
});
|
|
11034
|
+
},
|
|
11035
|
+
className: "w-32 rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100"
|
|
11036
|
+
}
|
|
11037
|
+
),
|
|
11038
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "%" })
|
|
11039
|
+
] })
|
|
11040
|
+
] })
|
|
11041
|
+
}
|
|
11042
|
+
),
|
|
11043
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
11044
|
+
SettingRow,
|
|
11045
|
+
{
|
|
11046
|
+
title: "Selection strategy",
|
|
11047
|
+
hint: "How valid fallback candidates are ordered in previews.",
|
|
11048
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
11049
|
+
"select",
|
|
11050
|
+
{
|
|
11051
|
+
value: (_b = draft.selectionStrategy) != null ? _b : "priority",
|
|
11052
|
+
onChange: (e) => setDraft((prev) => ({
|
|
11053
|
+
...prev,
|
|
11054
|
+
selectionStrategy: e.target.value
|
|
11055
|
+
})),
|
|
11056
|
+
className: "w-48 rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100",
|
|
11057
|
+
children: [
|
|
11058
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "priority", children: "priority" }),
|
|
11059
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "cheapest", children: "cheapest" })
|
|
11060
|
+
]
|
|
11061
|
+
}
|
|
11062
|
+
)
|
|
11063
|
+
}
|
|
11064
|
+
),
|
|
11065
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
11066
|
+
SettingRow,
|
|
11067
|
+
{
|
|
11068
|
+
title: "Mode",
|
|
11069
|
+
hint: "Use strict for enforced filtering, dev for advisory feedback.",
|
|
11070
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
11071
|
+
"select",
|
|
11072
|
+
{
|
|
11073
|
+
value: (_c = draft.mode) != null ? _c : "strict",
|
|
11074
|
+
onChange: (e) => setDraft((prev) => ({
|
|
11075
|
+
...prev,
|
|
11076
|
+
mode: e.target.value
|
|
11077
|
+
})),
|
|
11078
|
+
className: "w-48 rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100",
|
|
11079
|
+
children: [
|
|
11080
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "strict", children: "strict" }),
|
|
11081
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "dev", children: "dev" })
|
|
11082
|
+
]
|
|
11083
|
+
}
|
|
11084
|
+
)
|
|
11085
|
+
}
|
|
11086
|
+
)
|
|
11087
|
+
] }),
|
|
11088
|
+
saved && !error ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-4 rounded-xl border border-green-200 bg-green-50 px-3 py-2 text-sm text-green-700 dark:border-green-900/50 dark:bg-green-950/20 dark:text-green-300", children: "Settings saved." }) : null,
|
|
11089
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-4 rounded-xl border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700 dark:border-red-900/50 dark:bg-red-950/20 dark:text-red-300", children: error }) : null
|
|
11090
|
+
] });
|
|
11091
|
+
}
|
|
11092
|
+
function SettingRow({
|
|
11093
|
+
title,
|
|
11094
|
+
hint,
|
|
11095
|
+
children
|
|
11096
|
+
}) {
|
|
11097
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-3 border-b border-dashed border-zinc-200 pb-4 last:border-b-0 last:pb-0 dark:border-zinc-800 md:flex-row md:items-center md:justify-between", children: [
|
|
11098
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "max-w-xl", children: [
|
|
11099
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: title }),
|
|
11100
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: hint })
|
|
11101
|
+
] }),
|
|
11102
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { children })
|
|
11103
|
+
] });
|
|
11104
|
+
}
|
|
11105
|
+
|
|
11106
|
+
// src/react/fallback-editor/FallbackServiceSidebar.tsx
|
|
11107
|
+
var import_react20 = require("react");
|
|
11108
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
11109
|
+
function FallbackServiceSidebar() {
|
|
11110
|
+
const { activeServiceId, setActiveServiceId, get } = useFallbackEditor();
|
|
11111
|
+
const services = usePrimaryServiceList();
|
|
11112
|
+
const [query, setQuery] = (0, import_react20.useState)("");
|
|
11113
|
+
const filtered = (0, import_react20.useMemo)(() => {
|
|
11114
|
+
const q = query.trim().toLowerCase();
|
|
11115
|
+
if (!q) return services;
|
|
11116
|
+
return services.filter(
|
|
11117
|
+
(service) => {
|
|
11118
|
+
var _a, _b;
|
|
11119
|
+
return String(service.id).includes(q) || String((_a = service.name) != null ? _a : "").toLowerCase().includes(q) || String((_b = service.platform) != null ? _b : "").toLowerCase().includes(q);
|
|
11120
|
+
}
|
|
11121
|
+
);
|
|
11122
|
+
}, [query, services]);
|
|
11123
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("aside", { className: "flex min-h-0 flex-col rounded-2xl border border-zinc-200 bg-white shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
11124
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "border-b border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
11125
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h2", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Primary services" }),
|
|
11126
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: "Services currently active in the builder/runtime context." })
|
|
11127
|
+
] }),
|
|
11128
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex min-h-0 flex-1 flex-col p-4", children: [
|
|
11129
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
11130
|
+
"input",
|
|
11131
|
+
{
|
|
11132
|
+
value: query,
|
|
11133
|
+
onChange: (e) => setQuery(e.target.value),
|
|
11134
|
+
placeholder: "Search primary service...",
|
|
11135
|
+
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm outline-none focus:border-blue-500 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-100"
|
|
11136
|
+
}
|
|
11137
|
+
),
|
|
11138
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-3 flex-1 space-y-2 overflow-auto", children: filtered.map((service) => {
|
|
11139
|
+
var _a, _b;
|
|
11140
|
+
const active = String(service.id) === String(activeServiceId);
|
|
11141
|
+
const count = get(service.id).length;
|
|
11142
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
11143
|
+
"button",
|
|
11144
|
+
{
|
|
11145
|
+
type: "button",
|
|
11146
|
+
onClick: () => setActiveServiceId(service.id),
|
|
11147
|
+
className: [
|
|
11148
|
+
"w-full rounded-2xl border p-3 text-left transition",
|
|
11149
|
+
active ? "border-blue-500 bg-blue-50 dark:bg-blue-950/30" : "border-zinc-200 bg-zinc-50 hover:border-zinc-300 dark:border-zinc-800 dark:bg-zinc-950 dark:hover:border-zinc-700"
|
|
11150
|
+
].join(" "),
|
|
11151
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
|
|
11152
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "min-w-0", children: [
|
|
11153
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "truncate text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: [
|
|
11154
|
+
"#",
|
|
11155
|
+
String(service.id),
|
|
11156
|
+
" \xB7",
|
|
11157
|
+
" ",
|
|
11158
|
+
(_a = service.name) != null ? _a : "Unnamed"
|
|
11159
|
+
] }),
|
|
11160
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: [
|
|
11161
|
+
(_b = service.platform) != null ? _b : "Unknown",
|
|
11162
|
+
typeof service.rate === "number" ? ` \xB7 rate ${service.rate}` : ""
|
|
11163
|
+
] })
|
|
11164
|
+
] }),
|
|
11165
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "rounded-full border border-zinc-200 bg-white px-2 py-1 text-[11px] text-zinc-600 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-300", children: [
|
|
11166
|
+
count,
|
|
11167
|
+
" reg"
|
|
11168
|
+
] })
|
|
11169
|
+
] })
|
|
11170
|
+
},
|
|
11171
|
+
String(service.id)
|
|
11172
|
+
);
|
|
11173
|
+
}) })
|
|
11174
|
+
] })
|
|
11175
|
+
] });
|
|
11176
|
+
}
|
|
11177
|
+
|
|
11178
|
+
// src/react/fallback-editor/FallbackRegistrationsPanel.tsx
|
|
11179
|
+
var import_react23 = __toESM(require("react"), 1);
|
|
11180
|
+
|
|
11181
|
+
// src/react/fallback-editor/FallbackAddCandidatesDialog.tsx
|
|
11182
|
+
var import_react21 = __toESM(require("react"), 1);
|
|
11183
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
11184
|
+
function FallbackAddCandidatesDialog({
|
|
11185
|
+
open,
|
|
11186
|
+
onClose,
|
|
11187
|
+
context,
|
|
11188
|
+
primaryId
|
|
11189
|
+
}) {
|
|
11190
|
+
const { eligible, addMany } = useFallbackEditor();
|
|
11191
|
+
const eligibleServices = useEligibleServiceList();
|
|
11192
|
+
const [query, setQuery] = import_react21.default.useState("");
|
|
11193
|
+
const [filterEligibleOnly, setFilterEligibleOnly] = import_react21.default.useState(true);
|
|
11194
|
+
const [selected, setSelected] = import_react21.default.useState(/* @__PURE__ */ new Set());
|
|
11195
|
+
const [submitting, setSubmitting] = import_react21.default.useState(false);
|
|
11196
|
+
import_react21.default.useEffect(() => {
|
|
11197
|
+
if (!open) {
|
|
11198
|
+
setQuery("");
|
|
11199
|
+
setFilterEligibleOnly(true);
|
|
11200
|
+
setSelected(/* @__PURE__ */ new Set());
|
|
11201
|
+
}
|
|
11202
|
+
}, [open]);
|
|
11203
|
+
const allowedIds = import_react21.default.useMemo(() => {
|
|
11204
|
+
if (!context) return null;
|
|
11205
|
+
if (!filterEligibleOnly) return null;
|
|
11206
|
+
return new Set(eligible(context).map((id) => String(id)));
|
|
11207
|
+
}, [context, filterEligibleOnly, eligible]);
|
|
11208
|
+
const items = import_react21.default.useMemo(() => {
|
|
11209
|
+
const q = query.trim().toLowerCase();
|
|
11210
|
+
return eligibleServices.filter((service) => {
|
|
11211
|
+
var _a, _b;
|
|
11212
|
+
if (primaryId !== void 0 && String(service.id) === String(primaryId)) {
|
|
11213
|
+
return false;
|
|
11214
|
+
}
|
|
11215
|
+
if (allowedIds && !allowedIds.has(String(service.id))) {
|
|
11216
|
+
return false;
|
|
11217
|
+
}
|
|
11218
|
+
if (!q) return true;
|
|
11219
|
+
return String(service.id).includes(q) || String((_a = service.name) != null ? _a : "").toLowerCase().includes(q) || String((_b = service.platform) != null ? _b : "").toLowerCase().includes(q);
|
|
11220
|
+
});
|
|
11221
|
+
}, [eligibleServices, allowedIds, query, primaryId]);
|
|
11222
|
+
function toggle(id) {
|
|
11223
|
+
setSelected((prev) => {
|
|
11224
|
+
const next = new Set(prev);
|
|
11225
|
+
const key = String(id);
|
|
11226
|
+
if (next.has(key)) next.delete(key);
|
|
11227
|
+
else next.add(key);
|
|
11228
|
+
return next;
|
|
11229
|
+
});
|
|
11230
|
+
}
|
|
11231
|
+
async function handleAdd() {
|
|
11232
|
+
if (!context || selected.size === 0) return;
|
|
11233
|
+
setSubmitting(true);
|
|
11234
|
+
try {
|
|
11235
|
+
const ids = items.filter((item) => selected.has(String(item.id))).map((item) => item.id);
|
|
11236
|
+
addMany(context, ids);
|
|
11237
|
+
onClose();
|
|
11238
|
+
} finally {
|
|
11239
|
+
setSubmitting(false);
|
|
11240
|
+
}
|
|
11241
|
+
}
|
|
11242
|
+
if (!open || !context) return null;
|
|
11243
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex max-h-[85vh] w-full max-w-3xl flex-col rounded-2xl border border-zinc-200 bg-white shadow-2xl dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
11244
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "border-b border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
11245
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h3", { className: "text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Add fallback services" }),
|
|
11246
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 text-sm text-zinc-500 dark:text-zinc-400", children: "Search and select one or more eligible fallback candidates." })
|
|
11247
|
+
] }),
|
|
11248
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-col gap-3 p-4", children: [
|
|
11249
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
11250
|
+
"input",
|
|
11251
|
+
{
|
|
11252
|
+
value: query,
|
|
11253
|
+
onChange: (e) => setQuery(e.target.value),
|
|
11254
|
+
placeholder: "Search eligible services...",
|
|
11255
|
+
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm outline-none focus:border-blue-500 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-100"
|
|
11256
|
+
}
|
|
11257
|
+
),
|
|
11258
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "inline-flex items-center gap-2 text-sm text-zinc-700 dark:text-zinc-300", children: [
|
|
11259
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
11260
|
+
"input",
|
|
11261
|
+
{
|
|
11262
|
+
type: "checkbox",
|
|
11263
|
+
checked: filterEligibleOnly,
|
|
11264
|
+
onChange: (e) => setFilterEligibleOnly(e.target.checked),
|
|
11265
|
+
className: "h-4 w-4 rounded border-zinc-300"
|
|
11266
|
+
}
|
|
11267
|
+
),
|
|
11268
|
+
"Filter eligible only"
|
|
11269
|
+
] }),
|
|
11270
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
11271
|
+
VirtualServiceList,
|
|
11272
|
+
{
|
|
11273
|
+
items,
|
|
11274
|
+
selected,
|
|
11275
|
+
onToggle: toggle,
|
|
11276
|
+
emptyText: "No eligible services found."
|
|
11277
|
+
}
|
|
11278
|
+
)
|
|
11279
|
+
] }),
|
|
11280
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center justify-between border-t border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
11281
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "text-sm text-zinc-500 dark:text-zinc-400", children: [
|
|
11282
|
+
selected.size,
|
|
11283
|
+
" selected"
|
|
11284
|
+
] }),
|
|
11285
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex gap-2", children: [
|
|
11286
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
11287
|
+
"button",
|
|
11288
|
+
{
|
|
11289
|
+
type: "button",
|
|
11290
|
+
onClick: onClose,
|
|
11291
|
+
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
11292
|
+
children: "Cancel"
|
|
11293
|
+
}
|
|
11294
|
+
),
|
|
11295
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
11296
|
+
"button",
|
|
11297
|
+
{
|
|
11298
|
+
type: "button",
|
|
11299
|
+
onClick: handleAdd,
|
|
11300
|
+
disabled: selected.size === 0 || submitting,
|
|
11301
|
+
className: "rounded-xl bg-blue-600 px-3 py-2 text-sm font-medium text-white hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-60",
|
|
11302
|
+
children: submitting ? "Adding..." : "Add selected"
|
|
11303
|
+
}
|
|
11304
|
+
)
|
|
11305
|
+
] })
|
|
11306
|
+
] })
|
|
11307
|
+
] }) });
|
|
11308
|
+
}
|
|
11309
|
+
|
|
11310
|
+
// src/react/fallback-editor/FallbackAddRegistrationDialog.tsx
|
|
11311
|
+
var import_react22 = __toESM(require("react"), 1);
|
|
11312
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
11313
|
+
function FallbackAddRegistrationDialog({
|
|
11314
|
+
open,
|
|
11315
|
+
onClose,
|
|
11316
|
+
onSelect
|
|
11317
|
+
}) {
|
|
11318
|
+
const { activeServiceId, serviceProps, snapshot } = useFallbackEditor();
|
|
11319
|
+
const registrations = useActiveFallbackRegistrations();
|
|
11320
|
+
const [scope, setScope] = import_react22.default.useState("global");
|
|
11321
|
+
const [nodeId, setNodeId] = import_react22.default.useState("");
|
|
11322
|
+
const mode = import_react22.default.useMemo(() => {
|
|
11323
|
+
if (snapshot) return "snapshot";
|
|
11324
|
+
if (serviceProps) return "props";
|
|
11325
|
+
return "none";
|
|
11326
|
+
}, [snapshot, serviceProps]);
|
|
11327
|
+
import_react22.default.useEffect(() => {
|
|
11328
|
+
if (open) {
|
|
11329
|
+
setScope("global");
|
|
11330
|
+
setNodeId("");
|
|
11331
|
+
}
|
|
11332
|
+
}, [open]);
|
|
11333
|
+
const hasGlobal = import_react22.default.useMemo(() => {
|
|
11334
|
+
return registrations.some((r) => r.scope === "global");
|
|
11335
|
+
}, [registrations]);
|
|
11336
|
+
const nodeTargets = import_react22.default.useMemo(() => {
|
|
11337
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
11338
|
+
if (activeServiceId === void 0 || activeServiceId === null) {
|
|
11339
|
+
return [];
|
|
11340
|
+
}
|
|
11341
|
+
if (mode === "snapshot" && (snapshot == null ? void 0 : snapshot.serviceMap)) {
|
|
11342
|
+
const out = [];
|
|
11343
|
+
for (const [id, primaryIds] of Object.entries(
|
|
11344
|
+
snapshot.serviceMap
|
|
11345
|
+
)) {
|
|
11346
|
+
const matchesPrimary = (primaryIds != null ? primaryIds : []).some(
|
|
11347
|
+
(serviceId) => String(serviceId) === String(activeServiceId)
|
|
11348
|
+
);
|
|
11349
|
+
if (!matchesPrimary) continue;
|
|
11350
|
+
const meta = resolveNodeMeta(serviceProps, id);
|
|
11351
|
+
out.push({
|
|
11352
|
+
id,
|
|
11353
|
+
kind: meta.kind,
|
|
11354
|
+
label: meta.label,
|
|
11355
|
+
serviceId: activeServiceId
|
|
11356
|
+
});
|
|
11357
|
+
}
|
|
11358
|
+
const activeTagId = (_a = snapshot.selection) == null ? void 0 : _a.tag;
|
|
11359
|
+
out.sort((a, b) => {
|
|
11360
|
+
if (activeTagId && a.id === activeTagId && b.id !== activeTagId) {
|
|
11361
|
+
return -1;
|
|
11362
|
+
}
|
|
11363
|
+
if (activeTagId && b.id === activeTagId && a.id !== activeTagId) {
|
|
11364
|
+
return 1;
|
|
11365
|
+
}
|
|
11366
|
+
return a.label.localeCompare(b.label);
|
|
11367
|
+
});
|
|
11368
|
+
const seen = /* @__PURE__ */ new Set();
|
|
11369
|
+
return out.filter((item) => {
|
|
11370
|
+
if (seen.has(item.id)) return false;
|
|
11371
|
+
seen.add(item.id);
|
|
11372
|
+
return true;
|
|
11373
|
+
});
|
|
11374
|
+
}
|
|
11375
|
+
if (mode === "props" && serviceProps) {
|
|
11376
|
+
const out = [];
|
|
11377
|
+
for (const tag of (_b = serviceProps.filters) != null ? _b : []) {
|
|
11378
|
+
if ((tag == null ? void 0 : tag.service_id) === void 0 || (tag == null ? void 0 : tag.service_id) === null) {
|
|
11379
|
+
continue;
|
|
11380
|
+
}
|
|
11381
|
+
if (String(tag.service_id) !== String(activeServiceId)) {
|
|
11382
|
+
continue;
|
|
11383
|
+
}
|
|
11384
|
+
out.push({
|
|
11385
|
+
id: tag.id,
|
|
11386
|
+
kind: "tag",
|
|
11387
|
+
label: (_d = (_c = tag.label) != null ? _c : tag.title) != null ? _d : tag.id,
|
|
11388
|
+
serviceId: tag.service_id
|
|
11389
|
+
});
|
|
11390
|
+
}
|
|
11391
|
+
for (const field of (_e = serviceProps.fields) != null ? _e : []) {
|
|
11392
|
+
if ((field == null ? void 0 : field.service_id) !== void 0 && (field == null ? void 0 : field.service_id) !== null && String(field.service_id) === String(activeServiceId)) {
|
|
11393
|
+
out.push({
|
|
11394
|
+
id: field.id,
|
|
11395
|
+
kind: "field",
|
|
11396
|
+
label: (_g = (_f = field.label) != null ? _f : field.title) != null ? _g : field.id,
|
|
11397
|
+
serviceId: field.service_id
|
|
11398
|
+
});
|
|
11399
|
+
}
|
|
11400
|
+
for (const option of (_h = field.options) != null ? _h : []) {
|
|
11401
|
+
if ((option == null ? void 0 : option.service_id) === void 0 || (option == null ? void 0 : option.service_id) === null) {
|
|
11402
|
+
continue;
|
|
11403
|
+
}
|
|
11404
|
+
if (String(option.service_id) !== String(activeServiceId)) {
|
|
11405
|
+
continue;
|
|
11406
|
+
}
|
|
11407
|
+
out.push({
|
|
11408
|
+
id: option.id,
|
|
11409
|
+
kind: "option",
|
|
11410
|
+
label: (_k = (_i = option.label) != null ? _i : option.title) != null ? _k : String(
|
|
11411
|
+
(_j = option.value) != null ? _j : option.id
|
|
11412
|
+
),
|
|
11413
|
+
serviceId: option.service_id
|
|
11414
|
+
});
|
|
11415
|
+
}
|
|
11416
|
+
}
|
|
11417
|
+
const seen = /* @__PURE__ */ new Set();
|
|
11418
|
+
return out.filter((item) => {
|
|
11419
|
+
if (seen.has(item.id)) return false;
|
|
11420
|
+
seen.add(item.id);
|
|
11421
|
+
return true;
|
|
11422
|
+
});
|
|
11423
|
+
}
|
|
11424
|
+
return [];
|
|
11425
|
+
}, [mode, snapshot, serviceProps, activeServiceId]);
|
|
11426
|
+
import_react22.default.useEffect(() => {
|
|
11427
|
+
if (hasGlobal && scope === "global") {
|
|
11428
|
+
setScope("node");
|
|
11429
|
+
}
|
|
11430
|
+
}, [hasGlobal, scope]);
|
|
11431
|
+
import_react22.default.useEffect(() => {
|
|
11432
|
+
if (scope === "node" && nodeId) {
|
|
11433
|
+
const exists = nodeTargets.some((node) => node.id === nodeId);
|
|
11434
|
+
if (!exists) setNodeId("");
|
|
11435
|
+
}
|
|
11436
|
+
}, [scope, nodeId, nodeTargets]);
|
|
11437
|
+
function handleContinue() {
|
|
11438
|
+
var _a;
|
|
11439
|
+
if (activeServiceId === void 0 || activeServiceId === null) return;
|
|
11440
|
+
if (scope === "global") {
|
|
11441
|
+
onSelect(
|
|
11442
|
+
{
|
|
11443
|
+
scope: "global",
|
|
11444
|
+
primary: activeServiceId
|
|
11445
|
+
},
|
|
11446
|
+
activeServiceId
|
|
11447
|
+
);
|
|
11448
|
+
return;
|
|
11449
|
+
}
|
|
11450
|
+
if (!nodeId) return;
|
|
11451
|
+
const node = nodeTargets.find((n) => n.id === nodeId);
|
|
11452
|
+
onSelect(
|
|
11453
|
+
{
|
|
11454
|
+
scope: "node",
|
|
11455
|
+
nodeId
|
|
11456
|
+
},
|
|
11457
|
+
(_a = node == null ? void 0 : node.serviceId) != null ? _a : activeServiceId
|
|
11458
|
+
);
|
|
11459
|
+
}
|
|
11460
|
+
if (!open) return null;
|
|
11461
|
+
const nodeScopeDisabled = nodeTargets.length === 0;
|
|
11462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "w-full max-w-lg rounded-2xl border border-zinc-200 bg-white shadow-2xl dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
11463
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "border-b border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
11464
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h3", { className: "text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Add registration" }),
|
|
11465
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "mt-1 text-sm text-zinc-500 dark:text-zinc-400", children: "Choose the registration scope before selecting fallback candidates." })
|
|
11466
|
+
] }),
|
|
11467
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "space-y-4 p-4", children: [
|
|
11468
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "space-y-2", children: [
|
|
11469
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: "Scope" }),
|
|
11470
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "grid gap-2", children: [
|
|
11471
|
+
!hasGlobal && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "flex cursor-pointer items-start gap-3 rounded-xl border border-zinc-200 p-3 dark:border-zinc-800", children: [
|
|
11472
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
11473
|
+
"input",
|
|
11474
|
+
{
|
|
11475
|
+
type: "radio",
|
|
11476
|
+
name: "scope",
|
|
11477
|
+
checked: scope === "global",
|
|
11478
|
+
onChange: () => setScope("global"),
|
|
11479
|
+
className: "mt-1 h-4 w-4"
|
|
11480
|
+
}
|
|
11481
|
+
),
|
|
11482
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
|
|
11483
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: "Global" }),
|
|
11484
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: "Use one global registration for this primary service." })
|
|
11485
|
+
] })
|
|
11486
|
+
] }),
|
|
11487
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
11488
|
+
"label",
|
|
11489
|
+
{
|
|
11490
|
+
className: [
|
|
11491
|
+
"flex items-start gap-3 rounded-xl border p-3",
|
|
11492
|
+
nodeScopeDisabled ? "cursor-not-allowed border-zinc-200 opacity-60 dark:border-zinc-800" : "cursor-pointer border-zinc-200 dark:border-zinc-800"
|
|
11493
|
+
].join(" "),
|
|
11494
|
+
children: [
|
|
11495
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
11496
|
+
"input",
|
|
11497
|
+
{
|
|
11498
|
+
type: "radio",
|
|
11499
|
+
name: "scope",
|
|
11500
|
+
checked: scope === "node",
|
|
11501
|
+
onChange: () => setScope("node"),
|
|
11502
|
+
disabled: nodeScopeDisabled,
|
|
11503
|
+
className: "mt-1 h-4 w-4"
|
|
11504
|
+
}
|
|
11505
|
+
),
|
|
11506
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
|
|
11507
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: "Node" }),
|
|
11508
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: mode === "snapshot" ? "Pick a node currently active in the order snapshot for this primary service." : mode === "props" ? "Pick a tag, field, or option from ServiceProps that maps to this primary service." : "Node-scoped registration is unavailable without OrderSnapshot or ServiceProps." })
|
|
11509
|
+
] })
|
|
11510
|
+
]
|
|
11511
|
+
}
|
|
11512
|
+
)
|
|
11513
|
+
] })
|
|
11514
|
+
] }),
|
|
11515
|
+
scope === "node" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "space-y-2", children: [
|
|
11516
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: "Node id" }),
|
|
11517
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
11518
|
+
"select",
|
|
11519
|
+
{
|
|
11520
|
+
value: nodeId,
|
|
11521
|
+
onChange: (e) => setNodeId(e.target.value),
|
|
11522
|
+
className: "w-full rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm outline-none focus:border-blue-500 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-100",
|
|
11523
|
+
children: [
|
|
11524
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "", children: "Select node\u2026" }),
|
|
11525
|
+
nodeTargets.map((node) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("option", { value: node.id, children: [
|
|
11526
|
+
"[",
|
|
11527
|
+
node.kind,
|
|
11528
|
+
"] ",
|
|
11529
|
+
node.label,
|
|
11530
|
+
" \xB7 #",
|
|
11531
|
+
String(node.serviceId)
|
|
11532
|
+
] }, node.id))
|
|
11533
|
+
]
|
|
11534
|
+
}
|
|
11535
|
+
),
|
|
11536
|
+
nodeScopeDisabled ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "text-xs text-zinc-500 dark:text-zinc-400", children: mode === "snapshot" ? "No active snapshot nodes were found for this primary service." : mode === "props" ? "No ServiceProps nodes were found for this primary service." : "Node-scoped registration requires either OrderSnapshot or ServiceProps." }) : null
|
|
11537
|
+
] })
|
|
11538
|
+
] }),
|
|
11539
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-end gap-2 border-t border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
11540
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
11541
|
+
"button",
|
|
11542
|
+
{
|
|
11543
|
+
type: "button",
|
|
11544
|
+
onClick: onClose,
|
|
11545
|
+
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
11546
|
+
children: "Cancel"
|
|
11547
|
+
}
|
|
11548
|
+
),
|
|
11549
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
11550
|
+
"button",
|
|
11551
|
+
{
|
|
11552
|
+
type: "button",
|
|
11553
|
+
onClick: handleContinue,
|
|
11554
|
+
disabled: activeServiceId === void 0 || scope === "node" && !nodeId,
|
|
11555
|
+
className: "rounded-xl bg-blue-600 px-3 py-2 text-sm font-medium text-white hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-60",
|
|
11556
|
+
children: "Continue"
|
|
11557
|
+
}
|
|
11558
|
+
)
|
|
11559
|
+
] })
|
|
11560
|
+
] }) });
|
|
11561
|
+
}
|
|
11562
|
+
function resolveNodeMeta(props, nodeId) {
|
|
11563
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
11564
|
+
if (!props) {
|
|
11565
|
+
return { kind: "node", label: nodeId };
|
|
11566
|
+
}
|
|
11567
|
+
const tag = (_a = props.filters) == null ? void 0 : _a.find((t) => t.id === nodeId);
|
|
11568
|
+
if (tag) {
|
|
11569
|
+
return {
|
|
11570
|
+
kind: "tag",
|
|
11571
|
+
label: (_c = (_b = tag.label) != null ? _b : tag.title) != null ? _c : tag.id
|
|
11572
|
+
};
|
|
11573
|
+
}
|
|
11574
|
+
const field = (_d = props.fields) == null ? void 0 : _d.find((f) => f.id === nodeId);
|
|
11575
|
+
if (field) {
|
|
11576
|
+
return {
|
|
11577
|
+
kind: "field",
|
|
11578
|
+
label: (_f = (_e = field.label) != null ? _e : field.title) != null ? _f : field.id
|
|
11579
|
+
};
|
|
11580
|
+
}
|
|
11581
|
+
for (const fieldItem of (_g = props.fields) != null ? _g : []) {
|
|
11582
|
+
const option = (_h = fieldItem.options) == null ? void 0 : _h.find((o) => o.id === nodeId);
|
|
11583
|
+
if (option) {
|
|
11584
|
+
return {
|
|
11585
|
+
kind: "option",
|
|
11586
|
+
label: (_k = (_i = option.label) != null ? _i : option.title) != null ? _k : String((_j = option.value) != null ? _j : option.id)
|
|
11587
|
+
};
|
|
11588
|
+
}
|
|
11589
|
+
}
|
|
11590
|
+
return { kind: "node", label: nodeId };
|
|
11591
|
+
}
|
|
11592
|
+
|
|
11593
|
+
// src/react/fallback-editor/FallbackRegistrationsPanel.tsx
|
|
11594
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
11595
|
+
function FallbackRegistrationsPanel() {
|
|
11596
|
+
const { activeServiceId, remove, clear, check } = useFallbackEditor();
|
|
11597
|
+
const registrations = useActiveFallbackRegistrations();
|
|
11598
|
+
const eligibleServices = useEligibleServiceList();
|
|
11599
|
+
const [candidatePickerOpen, setCandidatePickerOpen] = import_react23.default.useState(false);
|
|
11600
|
+
const [candidateContext, setCandidateContext] = import_react23.default.useState(null);
|
|
11601
|
+
const [candidatePrimaryId, setCandidatePrimaryId] = import_react23.default.useState(void 0);
|
|
11602
|
+
const [registrationDialogOpen, setRegistrationDialogOpen] = import_react23.default.useState(false);
|
|
11603
|
+
const makeContext = import_react23.default.useCallback(
|
|
11604
|
+
(registration) => {
|
|
11605
|
+
if (registration.scope === "global") {
|
|
11606
|
+
return {
|
|
11607
|
+
scope: "global",
|
|
11608
|
+
primary: registration.primary
|
|
11609
|
+
};
|
|
11610
|
+
}
|
|
11611
|
+
return {
|
|
11612
|
+
scope: "node",
|
|
11613
|
+
nodeId: registration.scopeId
|
|
11614
|
+
};
|
|
11615
|
+
},
|
|
11616
|
+
[]
|
|
11617
|
+
);
|
|
11618
|
+
const openCandidatePicker = import_react23.default.useCallback(
|
|
11619
|
+
(context, primaryId) => {
|
|
11620
|
+
setCandidateContext(context);
|
|
11621
|
+
setCandidatePrimaryId(primaryId);
|
|
11622
|
+
setCandidatePickerOpen(true);
|
|
11623
|
+
},
|
|
11624
|
+
[]
|
|
11625
|
+
);
|
|
11626
|
+
if (activeServiceId === void 0 || activeServiceId === null) {
|
|
11627
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "rounded-2xl border border-dashed border-zinc-300 p-6 text-sm text-zinc-500 dark:border-zinc-700 dark:text-zinc-400", children: "Select a primary service to start editing." }) });
|
|
11628
|
+
}
|
|
11629
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
11630
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
11631
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "mb-4 flex items-start justify-between gap-3", children: [
|
|
11632
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
|
|
11633
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h3", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Registered fallbacks" }),
|
|
11634
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: "Use eligible services as fallback candidates for the selected primary." })
|
|
11635
|
+
] }),
|
|
11636
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
11637
|
+
"button",
|
|
11638
|
+
{
|
|
11639
|
+
type: "button",
|
|
11640
|
+
onClick: () => setRegistrationDialogOpen(true),
|
|
11641
|
+
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
11642
|
+
children: "Add registration"
|
|
11643
|
+
}
|
|
11644
|
+
)
|
|
11645
|
+
] }),
|
|
11646
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "space-y-4", children: registrations.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "rounded-2xl border border-dashed border-zinc-300 p-6 text-sm text-zinc-500 dark:border-zinc-700 dark:text-zinc-400", children: "No registrations yet for this primary service." }) : registrations.map((reg, index) => {
|
|
11647
|
+
var _a;
|
|
11648
|
+
const context = makeContext(reg);
|
|
11649
|
+
const candidates = reg.services;
|
|
11650
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
11651
|
+
"div",
|
|
11652
|
+
{
|
|
11653
|
+
className: "rounded-2xl border border-zinc-200 bg-zinc-50 p-4 dark:border-zinc-800 dark:bg-zinc-950",
|
|
11654
|
+
children: [
|
|
11655
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
|
|
11656
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
|
|
11657
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: reg.scope === "global" ? "Global registration" : `Node \xB7 ${reg.scopeId}` }),
|
|
11658
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: [
|
|
11659
|
+
"Primary #",
|
|
11660
|
+
String(reg.primary)
|
|
11661
|
+
] })
|
|
11662
|
+
] }),
|
|
11663
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "rounded-full border border-zinc-200 bg-white px-2 py-1 text-[11px] text-zinc-600 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-300", children: [
|
|
11664
|
+
reg.scope,
|
|
11665
|
+
reg.scopeId ? ` \xB7 ${reg.scopeId}` : ""
|
|
11666
|
+
] })
|
|
11667
|
+
] }),
|
|
11668
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "mt-4 flex flex-wrap gap-2", children: candidates.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "No fallback services yet." }) : candidates.map((candidate) => {
|
|
11669
|
+
var _a2;
|
|
11670
|
+
const preview = check(context, [
|
|
11671
|
+
candidate
|
|
11672
|
+
]);
|
|
11673
|
+
const rejected = preview.rejected[0];
|
|
11674
|
+
const tone = rejected ? "border-red-200 bg-red-50 text-red-700 dark:border-red-900/50 dark:bg-red-950/30 dark:text-red-300" : "border-zinc-200 bg-white text-zinc-700 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200";
|
|
11675
|
+
const service = eligibleServices.find(
|
|
11676
|
+
(s) => String(s.id) === String(candidate)
|
|
11677
|
+
);
|
|
11678
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
11679
|
+
"div",
|
|
11680
|
+
{
|
|
11681
|
+
className: `inline-flex items-center gap-2 rounded-xl border px-3 py-2 text-xs ${tone}`,
|
|
11682
|
+
children: [
|
|
11683
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: service ? `#${String(service.id)} \xB7 ${(_a2 = service.name) != null ? _a2 : "Unnamed"}` : `#${String(candidate)}` }),
|
|
11684
|
+
rejected ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "rounded-full border border-current/20 px-2 py-0.5 text-[10px]", children: rejected.reasons.join(
|
|
11685
|
+
", "
|
|
11686
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "rounded-full border border-current/20 px-2 py-0.5 text-[10px]", children: "valid" }),
|
|
11687
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
11688
|
+
"button",
|
|
11689
|
+
{
|
|
11690
|
+
type: "button",
|
|
11691
|
+
onClick: () => remove(
|
|
11692
|
+
context,
|
|
11693
|
+
candidate
|
|
11694
|
+
),
|
|
11695
|
+
className: "text-current/70 hover:text-current",
|
|
11696
|
+
children: "\xD7"
|
|
11697
|
+
}
|
|
11698
|
+
)
|
|
11699
|
+
]
|
|
11700
|
+
},
|
|
11701
|
+
String(candidate)
|
|
11702
|
+
);
|
|
11703
|
+
}) }),
|
|
11704
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "mt-4 flex gap-2", children: [
|
|
11705
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
11706
|
+
"button",
|
|
11707
|
+
{
|
|
11708
|
+
type: "button",
|
|
11709
|
+
onClick: () => openCandidatePicker(
|
|
11710
|
+
context,
|
|
11711
|
+
reg.primary
|
|
11712
|
+
),
|
|
11713
|
+
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
11714
|
+
children: "Add fallback"
|
|
11715
|
+
}
|
|
11716
|
+
),
|
|
11717
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
11718
|
+
"button",
|
|
11719
|
+
{
|
|
11720
|
+
type: "button",
|
|
11721
|
+
onClick: () => clear(context),
|
|
11722
|
+
className: "rounded-xl border border-red-300 bg-white px-3 py-2 text-sm font-medium text-red-600 hover:bg-red-50 dark:border-red-900/50 dark:bg-zinc-900 dark:text-red-300 dark:hover:bg-red-950/20",
|
|
11723
|
+
children: "Clear"
|
|
11724
|
+
}
|
|
11725
|
+
)
|
|
11726
|
+
] })
|
|
11727
|
+
]
|
|
11728
|
+
},
|
|
11729
|
+
`${reg.scope}:${String((_a = reg.scopeId) != null ? _a : "global")}:${index}`
|
|
11730
|
+
);
|
|
11731
|
+
}) })
|
|
11732
|
+
] }),
|
|
11733
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
11734
|
+
FallbackAddRegistrationDialog,
|
|
11735
|
+
{
|
|
11736
|
+
open: registrationDialogOpen,
|
|
11737
|
+
onClose: () => setRegistrationDialogOpen(false),
|
|
11738
|
+
onSelect: (context, primaryId) => {
|
|
11739
|
+
setRegistrationDialogOpen(false);
|
|
11740
|
+
openCandidatePicker(context, primaryId);
|
|
11741
|
+
}
|
|
11742
|
+
}
|
|
11743
|
+
),
|
|
11744
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
11745
|
+
FallbackAddCandidatesDialog,
|
|
11746
|
+
{
|
|
11747
|
+
open: candidatePickerOpen,
|
|
11748
|
+
onClose: () => setCandidatePickerOpen(false),
|
|
11749
|
+
context: candidateContext,
|
|
11750
|
+
primaryId: candidatePrimaryId
|
|
11751
|
+
}
|
|
11752
|
+
)
|
|
11753
|
+
] });
|
|
11754
|
+
}
|
|
9858
11755
|
// Annotate the CommonJS export names for ESM import in node:
|
|
9859
11756
|
0 && (module.exports = {
|
|
9860
11757
|
CanvasAPI,
|
|
9861
11758
|
EventBus,
|
|
11759
|
+
FallbackAddCandidatesDialog,
|
|
11760
|
+
FallbackAddRegistrationDialog,
|
|
11761
|
+
FallbackDetailsPanel,
|
|
11762
|
+
FallbackEditor,
|
|
11763
|
+
FallbackEditorHeader,
|
|
11764
|
+
FallbackEditorProvider,
|
|
11765
|
+
FallbackRegistrationsPanel,
|
|
11766
|
+
FallbackServiceSidebar,
|
|
11767
|
+
FallbackSettingsPanel,
|
|
9862
11768
|
FormProvider,
|
|
9863
11769
|
OrderFlowProvider,
|
|
9864
11770
|
Provider,
|
|
11771
|
+
VirtualServiceList,
|
|
9865
11772
|
Wrapper,
|
|
9866
11773
|
createInputRegistry,
|
|
9867
11774
|
registerEntries,
|
|
9868
11775
|
resolveInputDescriptor,
|
|
11776
|
+
useActiveFallbackRegistrations,
|
|
11777
|
+
useEligibleServiceList,
|
|
11778
|
+
useFallbackEditor,
|
|
11779
|
+
useFallbackEditorContext,
|
|
9869
11780
|
useFormApi,
|
|
9870
11781
|
useInputs,
|
|
9871
11782
|
useOptionalFormApi,
|
|
9872
11783
|
useOrderFlow,
|
|
9873
|
-
useOrderFlowContext
|
|
11784
|
+
useOrderFlowContext,
|
|
11785
|
+
usePrimaryServiceList
|
|
9874
11786
|
});
|
|
9875
11787
|
//# sourceMappingURL=index.cjs.map
|