@vectoriox/iox-ui 5.1.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/actions-core/index.d.ts +86 -0
- package/actions-core/package.json +3 -0
- package/fesm2022/vectoriox-iox-ui-actions-core.mjs +57 -0
- package/fesm2022/vectoriox-iox-ui-actions-core.mjs.map +1 -0
- package/fesm2022/vectoriox-iox-ui-forms-core.mjs +3 -14
- package/fesm2022/vectoriox-iox-ui-forms-core.mjs.map +1 -1
- package/fesm2022/vectoriox-iox-ui.mjs +1 -13
- package/fesm2022/vectoriox-iox-ui.mjs.map +1 -1
- package/forms-core/index.d.ts +4 -17
- package/package.json +5 -1
- package/src/actions-core/action.model.ts +79 -0
- package/src/actions-core/availability.ts +46 -0
- package/src/actions-core/public-api.ts +12 -0
- package/src/forms-core/rule-catalog.ts +6 -25
package/forms-core/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { FORM_SUBMIT_ACTION_DESCRIPTORS as ACTION_DESCRIPTORS, ActionDescriptor, addableActions } from '@vectoriox/iox-ui/actions-core';
|
|
2
|
+
|
|
1
3
|
/** What the visitor actually types into. Chosen by a trait; it also implies a validation rule. */
|
|
2
4
|
declare enum ControlType {
|
|
3
5
|
Text = "text",
|
|
@@ -291,21 +293,6 @@ declare const PATTERN_PRESET_OPTIONS: readonly {
|
|
|
291
293
|
value: PatternPreset;
|
|
292
294
|
labelKey: string;
|
|
293
295
|
}[];
|
|
294
|
-
/** Destinations an author can add to a form, for the After-submit list. */
|
|
295
|
-
interface ActionDescriptor {
|
|
296
|
-
type: string;
|
|
297
|
-
labelKey: string;
|
|
298
|
-
/** Always present and not removable. */
|
|
299
|
-
locked?: boolean;
|
|
300
|
-
/** Not offered yet — shown greyed with a "coming soon" note rather than hidden, so the roadmap
|
|
301
|
-
* is visible rather than the feature looking absent. */
|
|
302
|
-
planned?: boolean;
|
|
303
|
-
}
|
|
304
|
-
declare const ACTION_DESCRIPTORS: readonly ActionDescriptor[];
|
|
305
|
-
/** Destinations that can still be added — each at most once, and never a planned one. */
|
|
306
|
-
declare function addableActions(existing?: readonly {
|
|
307
|
-
type: string;
|
|
308
|
-
}[]): ActionDescriptor[];
|
|
309
296
|
|
|
310
297
|
/**
|
|
311
298
|
* The submit transport CONTRACT — what a host must provide to make a form actually send.
|
|
@@ -372,5 +359,5 @@ declare function withAntiSpamFields(values: Record<string, any>, renderedAt: num
|
|
|
372
359
|
*/
|
|
373
360
|
declare function interpretSubmitResponse(body: any): SubmitResponse;
|
|
374
361
|
|
|
375
|
-
export {
|
|
376
|
-
export type {
|
|
362
|
+
export { ControlType, DEFAULT_EN_MESSAGES, FIELD_NODE_TYPE, FORM_ERROR_KEYS, FORM_NODE_TYPE, FeedbackTiming, HONEYPOT_FIELD, IMPLIED_PATTERN, INITIAL_FORM_STATE, MESSAGE_NAMESPACE, MULTI_VALUE_CONTROLS, PATTERN_MESSAGE_KEYS, PATTERN_PRESETS, PATTERN_PRESET_OPTIONS, PatternPreset, RENDERED_AT_FIELD, RULE_DESCRIPTORS, RULE_MESSAGE_KEYS, RuleName, RuleParamKind, STORE_ACTION, addableRules, applyServerErrors, collectFieldNodes, collectFormSpec, deriveFieldName, firstInvalidField, interpretSubmitResponse, onFieldBlur, onFieldChange, onSubmitAttempt, resetFormState, rulesFor, shouldShowError, submitEndpointPath, uniqueFieldName, validateField, validateForm, withAntiSpamFields };
|
|
363
|
+
export type { FieldError, FieldOption, FieldOptionSource, FieldResult, FieldSpec, FormNodeLike, FormResult, FormRuntimeState, FormSpec, FormTransport, RuleDescriptor, SubmitAction, SubmitRequest, SubmitResponse, ValidationRule };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vectoriox/iox-ui",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.0",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/common": ">=20.0.0",
|
|
6
6
|
"@angular/core": ">=20.0.0",
|
|
@@ -19,6 +19,10 @@
|
|
|
19
19
|
"types": "./index.d.ts",
|
|
20
20
|
"default": "./fesm2022/vectoriox-iox-ui.mjs"
|
|
21
21
|
},
|
|
22
|
+
"./actions-core": {
|
|
23
|
+
"types": "./actions-core/index.d.ts",
|
|
24
|
+
"default": "./fesm2022/vectoriox-iox-ui-actions-core.mjs"
|
|
25
|
+
},
|
|
22
26
|
"./forms-core": {
|
|
23
27
|
"types": "./forms-core/index.d.ts",
|
|
24
28
|
"default": "./fesm2022/vectoriox-iox-ui-forms-core.mjs"
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE descriptor shape for everything an author can put in an ordered action list —
|
|
3
|
+
* a form's after-submit steps today, element behaviour actions (A1) next. Promoted out of
|
|
4
|
+
* `forms-core` because a button action importing from the forms module would be a lie; the
|
|
5
|
+
* forms catalog lives here now and `forms-core` re-exports it unchanged.
|
|
6
|
+
* See iox-ai-guidance `architecture/builder/actions-framework-plan.md` §4 (A0).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** How a step executes — decides which editor fields appear (timing only for `animated`). */
|
|
10
|
+
export type ActionKind = 'animated' | 'instant' | 'server';
|
|
11
|
+
|
|
12
|
+
/** Picker grouping. Flat lists die at ~10 entries; the group is data, never a second list. */
|
|
13
|
+
export type ActionGroup =
|
|
14
|
+
| 'motion' | 'visibility' | 'navigate' | 'dialog' | 'form' | 'data' | 'service';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* What a step does inside the live builder canvas (the canvas RUNS interactions):
|
|
18
|
+
* `run` for real (open the dialog), `simulate` announce-only (navigate), `inert` with a
|
|
19
|
+
* "runs on the live site" note (anything server-side or costing money).
|
|
20
|
+
*/
|
|
21
|
+
export type BuilderBehaviour = 'run' | 'simulate' | 'inert';
|
|
22
|
+
|
|
23
|
+
/** A configurable parameter, same shape ComponentMethodDef.params already uses. */
|
|
24
|
+
export interface ActionParamSpec {
|
|
25
|
+
name: string;
|
|
26
|
+
type: 'number' | 'string' | 'boolean' | 'page' | 'node' | 'form';
|
|
27
|
+
label: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Does this action point at another node — and may it be any node or only certain types? */
|
|
31
|
+
export interface ActionTargetSpec {
|
|
32
|
+
required: boolean;
|
|
33
|
+
types?: string[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* One row of an action catalog. Every field beyond `type`/`labelKey` is optional so the
|
|
38
|
+
* pre-A0 forms descriptors remain valid verbatim.
|
|
39
|
+
*/
|
|
40
|
+
export interface ActionDescriptor {
|
|
41
|
+
type: string;
|
|
42
|
+
labelKey: string;
|
|
43
|
+
kind?: ActionKind;
|
|
44
|
+
group?: ActionGroup;
|
|
45
|
+
builderBehaviour?: BuilderBehaviour;
|
|
46
|
+
target?: ActionTargetSpec;
|
|
47
|
+
params?: ActionParamSpec[];
|
|
48
|
+
/** The connector that must be configured & healthy before this action is offerable. */
|
|
49
|
+
connector?: string;
|
|
50
|
+
/** Plan-entitlement key (AI plan D5). Absent = never gated by plan. */
|
|
51
|
+
entitlement?: string;
|
|
52
|
+
/** Always present in the list and not removable (forms: `store`). */
|
|
53
|
+
locked?: boolean;
|
|
54
|
+
/** Not offered yet — shown greyed with a "coming soon" note, so the roadmap is visible. */
|
|
55
|
+
planned?: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The FORM after-submit catalog (moved verbatim from forms-core; `forms-core` re-exports it
|
|
60
|
+
* under its old name `ACTION_DESCRIPTORS`). A1's element catalog is a SEPARATE constant —
|
|
61
|
+
* the two lists share this shape, never one bucket.
|
|
62
|
+
*/
|
|
63
|
+
export const FORM_SUBMIT_ACTION_DESCRIPTORS: readonly ActionDescriptor[] = Object.freeze([
|
|
64
|
+
{ type: 'store', labelKey: 'forms.actions.store', locked: true, kind: 'server', group: 'data', builderBehaviour: 'inert' },
|
|
65
|
+
{ type: 'email', labelKey: 'forms.actions.email', kind: 'server', group: 'service', builderBehaviour: 'inert', connector: 'mailer' },
|
|
66
|
+
{ type: 'redirect', labelKey: 'forms.actions.redirect', kind: 'instant', group: 'navigate', builderBehaviour: 'simulate' },
|
|
67
|
+
{ type: 'createItem', labelKey: 'forms.actions.createItem', planned: true, kind: 'server', group: 'data', builderBehaviour: 'inert' },
|
|
68
|
+
{ type: 'webhook', labelKey: 'forms.actions.webhook', planned: true, kind: 'server', group: 'service', builderBehaviour: 'inert' },
|
|
69
|
+
{ type: 'autoReply', labelKey: 'forms.actions.autoReply', planned: true, kind: 'server', group: 'service', builderBehaviour: 'inert', connector: 'mailer' },
|
|
70
|
+
]);
|
|
71
|
+
|
|
72
|
+
/** Steps that can still be added to a list — each at most once, and never a planned one. */
|
|
73
|
+
export function addableActions(
|
|
74
|
+
existing: readonly { type: string }[] = [],
|
|
75
|
+
catalog: readonly ActionDescriptor[] = FORM_SUBMIT_ACTION_DESCRIPTORS,
|
|
76
|
+
): ActionDescriptor[] {
|
|
77
|
+
const used = new Set(existing.map(action => action.type));
|
|
78
|
+
return catalog.filter(action => !action.locked && !action.planned && !used.has(action.type));
|
|
79
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ActionDescriptor } from './action.model';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* K4 of the actions plan: four different reasons a catalog row is unavailable, four different
|
|
5
|
+
* sentences — *coming soon* · *always on* · *connect X first* · *upgrade*. One resolver feeds
|
|
6
|
+
* the picker AND the AI composer's validation, so they can never disagree.
|
|
7
|
+
*/
|
|
8
|
+
export type ActionAvailabilityState =
|
|
9
|
+
| 'available'
|
|
10
|
+
| 'planned' // not built yet — greyed, "coming soon"
|
|
11
|
+
| 'locked' // always present, not addable/removable
|
|
12
|
+
| 'connector-missing' // the named connector is not configured/healthy
|
|
13
|
+
| 'entitlement-missing'; // the plan does not include it
|
|
14
|
+
|
|
15
|
+
export interface ActionAvailability {
|
|
16
|
+
state: ActionAvailabilityState;
|
|
17
|
+
/** Set when state is connector-missing / entitlement-missing — what to name in the message. */
|
|
18
|
+
connector?: string;
|
|
19
|
+
entitlement?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ActionAvailabilityContext {
|
|
23
|
+
/** Connector health by name. An absent map, or an absent key, means "not known" → allowed. */
|
|
24
|
+
connectors?: Partial<Record<string, boolean>>;
|
|
25
|
+
/**
|
|
26
|
+
* Plan entitlements by key. `Plan.entitlements` does not exist yet anywhere (the known gap),
|
|
27
|
+
* so an ABSENT map means "no gating" and every entitlement passes — the hook is live the day
|
|
28
|
+
* the control plane starts sending them.
|
|
29
|
+
*/
|
|
30
|
+
entitlements?: Partial<Record<string, boolean>>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function resolveActionAvailability(
|
|
34
|
+
descriptor: ActionDescriptor,
|
|
35
|
+
ctx: ActionAvailabilityContext = {},
|
|
36
|
+
): ActionAvailability {
|
|
37
|
+
if (descriptor.planned) return { state: 'planned' };
|
|
38
|
+
if (descriptor.locked) return { state: 'locked' };
|
|
39
|
+
if (descriptor.connector && ctx.connectors && ctx.connectors[descriptor.connector] === false) {
|
|
40
|
+
return { state: 'connector-missing', connector: descriptor.connector };
|
|
41
|
+
}
|
|
42
|
+
if (descriptor.entitlement && ctx.entitlements && ctx.entitlements[descriptor.entitlement] === false) {
|
|
43
|
+
return { state: 'entitlement-missing', entitlement: descriptor.entitlement };
|
|
44
|
+
}
|
|
45
|
+
return { state: 'available' };
|
|
46
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vectoriox/iox-ui/actions-core — the shared, FRAMEWORK-FREE action vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* One `ActionDescriptor` shape for every ordered action list in the product: the forms
|
|
5
|
+
* after-submit steps (whose catalog moved here; `forms-core` re-exports it unchanged) and
|
|
6
|
+
* the element behaviour actions of A1. Framework-free for the same reason as `forms-core`
|
|
7
|
+
* and `seo-core`: `iox-cms` consumes it under plain Node.
|
|
8
|
+
* ⚠️ Consumers wire the usual trio — ng-package raw-ts assets, jest moduleNameMapper, and
|
|
9
|
+
* tsconfig paths — or `nest start` dies with ERR_REQUIRE_ESM while jest and build pass.
|
|
10
|
+
*/
|
|
11
|
+
export * from './action.model';
|
|
12
|
+
export * from './availability';
|
|
@@ -108,28 +108,9 @@ export const PATTERN_PRESET_OPTIONS: readonly { value: PatternPreset; labelKey:
|
|
|
108
108
|
{ value: PatternPreset.Slug, labelKey: 'forms.rules.preset.slug' },
|
|
109
109
|
]);
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
/** Not offered yet — shown greyed with a "coming soon" note rather than hidden, so the roadmap
|
|
118
|
-
* is visible rather than the feature looking absent. */
|
|
119
|
-
planned?: boolean;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export const ACTION_DESCRIPTORS: readonly ActionDescriptor[] = Object.freeze([
|
|
123
|
-
{ type: 'store', labelKey: 'forms.actions.store', locked: true },
|
|
124
|
-
{ type: 'email', labelKey: 'forms.actions.email' },
|
|
125
|
-
{ type: 'redirect', labelKey: 'forms.actions.redirect' },
|
|
126
|
-
{ type: 'createItem', labelKey: 'forms.actions.createItem', planned: true },
|
|
127
|
-
{ type: 'webhook', labelKey: 'forms.actions.webhook', planned: true },
|
|
128
|
-
{ type: 'autoReply', labelKey: 'forms.actions.autoReply', planned: true },
|
|
129
|
-
]);
|
|
130
|
-
|
|
131
|
-
/** Destinations that can still be added — each at most once, and never a planned one. */
|
|
132
|
-
export function addableActions(existing: readonly { type: string }[] = []): ActionDescriptor[] {
|
|
133
|
-
const used = new Set(existing.map(action => action.type));
|
|
134
|
-
return ACTION_DESCRIPTORS.filter(action => !action.locked && !action.planned && !used.has(action.type));
|
|
135
|
-
}
|
|
111
|
+
// ── MOVED to @vectoriox/iox-ui/actions-core (A0) ─────────────────────────────
|
|
112
|
+
// The descriptor shape and the after-submit catalog are the ONE action vocabulary the whole
|
|
113
|
+
// product shares; element actions (A1) consume the same shape. Re-exported here under the
|
|
114
|
+
// original names so no forms consumer changes a line.
|
|
115
|
+
export type { ActionDescriptor } from '@vectoriox/iox-ui/actions-core';
|
|
116
|
+
export { FORM_SUBMIT_ACTION_DESCRIPTORS as ACTION_DESCRIPTORS, addableActions } from '@vectoriox/iox-ui/actions-core';
|