@vectoriox/iox-ui 5.82.1 → 5.83.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/design-core/index.d.ts +200 -0
- package/fesm2022/vectoriox-iox-ui-design-core.mjs +215 -1
- package/fesm2022/vectoriox-iox-ui-design-core.mjs.map +1 -1
- package/fesm2022/vectoriox-iox-ui-forms-core.mjs +733 -56
- package/fesm2022/vectoriox-iox-ui-forms-core.mjs.map +1 -1
- package/fesm2022/vectoriox-iox-ui-generation-core.mjs +40 -4
- package/fesm2022/vectoriox-iox-ui-generation-core.mjs.map +1 -1
- package/fesm2022/vectoriox-iox-ui.mjs +1547 -135
- package/fesm2022/vectoriox-iox-ui.mjs.map +1 -1
- package/forms-core/index.d.ts +366 -18
- package/generation-core/index.d.ts +3 -0
- package/index.d.ts +303 -25
- package/package.json +1 -1
- package/src/design-core/contrast-audit.ts +4 -0
- package/src/design-core/flavor-spec.generated.ts +209 -1
- package/src/forms-core/channel.ts +85 -0
- package/src/forms-core/collect.ts +63 -30
- package/src/forms-core/dates.ts +299 -0
- package/src/forms-core/field-markup.ts +159 -0
- package/src/forms-core/form-presets.ts +51 -2
- package/src/forms-core/form.model.ts +34 -2
- package/src/forms-core/messages.ts +31 -0
- package/src/forms-core/public-api.ts +3 -0
- package/src/forms-core/rule-catalog.ts +3 -2
- package/src/forms-core/submit-lifecycle.ts +42 -12
- package/src/forms-core/validate.ts +90 -4
- package/src/generation-core/audit-site.ts +9 -1
- package/src/generation-core/compose-site.ts +22 -3
- package/src/generation-core/node-baselines.generated.ts +10 -0
- package/src/generation-core/plan-wire.ts +2 -2
- package/styles/iox-design.css +14 -2
- package/styles/iox-forms.css +349 -10
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NEW_NODE_STYLE_DEFAULTS, defaultElementStyleFor, elementStyleById, ownedTraitsOf, applyElementStyle, flavorPackById, parseHexColor, SPEC_AXES, EntranceParam, staggerDelay, LinkType, COLOR_SCHEMES, setColorScheme, resolveDesignChoices, ANIMATE_IDS, auditDesignContrast } from '@vectoriox/iox-ui/design-core';
|
|
2
|
-
import { formPresetById,
|
|
2
|
+
import { formPresetById, FORM_ACTIONS_ROLE, channelOpensNewTab, FORM_CHANNEL_ROLE, planFormPresetIds, ControlType, FORM_NODE_TYPE, collectFormSpec, FIELD_NODE_TYPE, isChannelFilled } from '@vectoriox/iox-ui/forms-core';
|
|
3
3
|
import { normalizeFrameSequence, filmScreensFor, FILM_PREPARED_PICTURES, FrameExtension } from '@vectoriox/iox-ui/media-core';
|
|
4
4
|
import { SEO_DESCRIPTION_MAX, SEO_TITLE_MAX } from '@vectoriox/iox-ui/seo-core';
|
|
5
5
|
import { pickTabsAutoBinds, pickAccordionAutoBinds, segmentedOptions, ITEM_OPEN_STATE, CardPart, CardRole, CardLayout, CARD_LAYOUTS, CARD_PARTS, BADGE_TONES, buildCardRecipe, findByRole, buildSegmentedRecipe, AccordionRole, buildAccordionRecipe, ACCORDION_WORDS, accordionItems, accordionQuestionOf, accordionAnswerOf, ACCORDION_BIND_PROP, ACCORDION_CONTENT_LIMIT, buildTabsRecipe, TABS_WORDS, tabsTriggers, tabLabelNodeOf, TABS_LABEL_BIND_PROP, tabsPanels, tabPanelTextOf, TABS_TEXT_BIND_PROP, tabPanelImageOf, tabsListOf, tabsPanelsOf, TABS_CONTENT_LIMIT, TABS_IMAGE_BIND_PROP, buildCarouselRecipe, SLIDE_TYPE, buildLightboxRecipe, LIGHTBOX_LABEL, SLIDE_TO_ROW } from '@vectoriox/iox-ui/composite-core';
|
|
@@ -9610,6 +9610,10 @@ const NODE_BASELINES = {
|
|
|
9610
9610
|
"label": "Label",
|
|
9611
9611
|
"control": "text",
|
|
9612
9612
|
"placeholder": "",
|
|
9613
|
+
"multiple": false,
|
|
9614
|
+
"appearance": "chips",
|
|
9615
|
+
"earliest": "",
|
|
9616
|
+
"latest": "",
|
|
9613
9617
|
"help": "",
|
|
9614
9618
|
"rows": 4,
|
|
9615
9619
|
"rangeMin": 0,
|
|
@@ -9713,6 +9717,10 @@ const NODE_BASELINES = {
|
|
|
9713
9717
|
"label",
|
|
9714
9718
|
"control",
|
|
9715
9719
|
"placeholder",
|
|
9720
|
+
"multiple",
|
|
9721
|
+
"appearance",
|
|
9722
|
+
"earliest",
|
|
9723
|
+
"latest",
|
|
9716
9724
|
"help",
|
|
9717
9725
|
"rows",
|
|
9718
9726
|
"rangeMin",
|
|
@@ -10016,6 +10024,7 @@ const NODE_BASELINES = {
|
|
|
10016
10024
|
"props": {
|
|
10017
10025
|
"label": "Send",
|
|
10018
10026
|
"loadingLabel": "Sending…",
|
|
10027
|
+
"sentLabel": "",
|
|
10019
10028
|
"disableWhileSubmitting": true
|
|
10020
10029
|
},
|
|
10021
10030
|
"styleProps": {
|
|
@@ -10107,6 +10116,7 @@ const NODE_BASELINES = {
|
|
|
10107
10116
|
"traits": [
|
|
10108
10117
|
"label",
|
|
10109
10118
|
"loadingLabel",
|
|
10119
|
+
"sentLabel",
|
|
10110
10120
|
"disableWhileSubmitting"
|
|
10111
10121
|
],
|
|
10112
10122
|
"styleTraits": [
|
|
@@ -13186,7 +13196,10 @@ const FORM_SUCCESS = 'FormSuccess';
|
|
|
13186
13196
|
const FORM_ERROR = 'FormError';
|
|
13187
13197
|
const FORM_STATE_BLOCKS = [FORM_SUCCESS, FORM_ERROR];
|
|
13188
13198
|
/** The Field traits a preset field fills, 1:1 (`FormPresetField`). */
|
|
13189
|
-
const PRESET_FIELD_PROPS = ['label', 'control', 'required', 'help', 'placeholder', 'optionsText', 'rows'];
|
|
13199
|
+
const PRESET_FIELD_PROPS = ['label', 'control', 'required', 'help', 'placeholder', 'optionsText', 'rows', 'multiple', 'appearance', 'earliest', 'latest'];
|
|
13200
|
+
const FIELD_GROUP = 'FieldGroup';
|
|
13201
|
+
/** The second channel beside Send (premium N2): the quieter button. */
|
|
13202
|
+
const CHANNEL_STYLE = 'button-secondary';
|
|
13190
13203
|
const LABEL_TAG = 'span';
|
|
13191
13204
|
const TEXT = 'Text';
|
|
13192
13205
|
/** A button's label reads the button's own type and ink (contract element style, W1.1 Q6). */
|
|
@@ -13414,7 +13427,22 @@ function presetChildren(preset, id) {
|
|
|
13414
13427
|
block.children = [create(`${id}-${n + 1 + i}-0`, TEXT, { content: words })];
|
|
13415
13428
|
return block;
|
|
13416
13429
|
});
|
|
13417
|
-
return [...fields, submit, ...blocks];
|
|
13430
|
+
return [...fields, preset.channel ? actionsRow(submit, preset.channel, `${id}-${n}`) : submit, ...blocks];
|
|
13431
|
+
}
|
|
13432
|
+
/**
|
|
13433
|
+
* Send and the second channel in ONE row (premium N2), the way the builder's tray builds it (iox-builder
|
|
13434
|
+
* `buildFormActionsRow`): the channel's address is the studio's own fact and starts EMPTY — the Publishable gate
|
|
13435
|
+
* blocks publishing until it is filled (`auditSite`, empty-channel). Never a number written for it.
|
|
13436
|
+
*/
|
|
13437
|
+
function actionsRow(submit, channel, id) {
|
|
13438
|
+
const row = create(`${id}-row`, FIELD_GROUP);
|
|
13439
|
+
row.role = FORM_ACTIONS_ROLE;
|
|
13440
|
+
Object.assign(row.styleProps, { flexWrap: 'wrap', alignItems: 'center', gap: '12px' });
|
|
13441
|
+
const button = create(`${id}-channel`, BUTTON_BLOCK, { tag: 'a', linkType: LinkType.External, href: '', target: channelOpensNewTab(channel.kind) ? '_blank' : '_self' }, CHANNEL_STYLE);
|
|
13442
|
+
button.role = FORM_CHANNEL_ROLE;
|
|
13443
|
+
button.children = [create(`${id}-channel-0`, TEXT, { content: channel.label }, BUTTON_LABEL_STYLE)];
|
|
13444
|
+
row.children = [submit, button];
|
|
13445
|
+
return row;
|
|
13418
13446
|
}
|
|
13419
13447
|
/** A Form: its stable id, its preset's name and children (or the pattern's own children), and both state
|
|
13420
13448
|
* blocks — never optional (forms plan D7). */
|
|
@@ -14895,7 +14923,7 @@ function wireSectionJsonSchema() {
|
|
|
14895
14923
|
links: jsonListOf(shaped(PlanWireEntry.SlotLink, { slot: closedOrText(unique(patterns.flatMap(patternLinkSlots))), route: jsonText() })),
|
|
14896
14924
|
binding: jsonText(),
|
|
14897
14925
|
without: jsonListOf(closedOrText(unique(patterns.flatMap(patternOptionalParts)))),
|
|
14898
|
-
form: orNone(
|
|
14926
|
+
form: orNone(planFormPresetIds()),
|
|
14899
14927
|
enter: orNone(ANIMATE_IDS),
|
|
14900
14928
|
});
|
|
14901
14929
|
}
|
|
@@ -16138,6 +16166,9 @@ var SiteFindingCode;
|
|
|
16138
16166
|
SiteFindingCode["NoHeader"] = "no-header";
|
|
16139
16167
|
SiteFindingCode["NoPhoneMenu"] = "no-phone-menu";
|
|
16140
16168
|
SiteFindingCode["FormWithoutId"] = "form-without-id";
|
|
16169
|
+
/** Premium N2: a form's second way to reach you (WhatsApp, a phone, an email) has no address yet — the studio's own
|
|
16170
|
+
* fact, never written for it. */
|
|
16171
|
+
SiteFindingCode["EmptyChannel"] = "empty-channel";
|
|
16141
16172
|
SiteFindingCode["EmailNeedsMailer"] = "email-needs-mailer";
|
|
16142
16173
|
SiteFindingCode["TrackerWithoutBanner"] = "tracker-without-banner";
|
|
16143
16174
|
SiteFindingCode["NoTitle"] = "no-title";
|
|
@@ -16161,6 +16192,7 @@ const FINDING_SEVERITY = {
|
|
|
16161
16192
|
[SiteFindingCode.NoHeader]: CheckSeverity.Warn,
|
|
16162
16193
|
[SiteFindingCode.NoPhoneMenu]: CheckSeverity.Warn,
|
|
16163
16194
|
[SiteFindingCode.FormWithoutId]: CheckSeverity.Block,
|
|
16195
|
+
[SiteFindingCode.EmptyChannel]: CheckSeverity.Block,
|
|
16164
16196
|
[SiteFindingCode.EmailNeedsMailer]: CheckSeverity.Warn,
|
|
16165
16197
|
[SiteFindingCode.TrackerWithoutBanner]: CheckSeverity.Warn,
|
|
16166
16198
|
[SiteFindingCode.NoTitle]: CheckSeverity.Warn,
|
|
@@ -16183,6 +16215,7 @@ const CHECK_OF = {
|
|
|
16183
16215
|
[SiteFindingCode.NoHeader]: SiteCheckId.Navigation,
|
|
16184
16216
|
[SiteFindingCode.NoPhoneMenu]: SiteCheckId.Navigation,
|
|
16185
16217
|
[SiteFindingCode.FormWithoutId]: SiteCheckId.Forms,
|
|
16218
|
+
[SiteFindingCode.EmptyChannel]: SiteCheckId.Forms,
|
|
16186
16219
|
[SiteFindingCode.EmailNeedsMailer]: SiteCheckId.Forms,
|
|
16187
16220
|
[SiteFindingCode.TrackerWithoutBanner]: SiteCheckId.Consent,
|
|
16188
16221
|
[SiteFindingCode.NoTitle]: SiteCheckId.Seo,
|
|
@@ -16274,6 +16307,9 @@ function checkForms(ctx, snapshot, pages) {
|
|
|
16274
16307
|
walkSerialized(n.children ?? [], f => {
|
|
16275
16308
|
if (f.type === FIELD_NODE_TYPE && PERSONAL_CONTROLS.has(String(f.props['control'] ?? ControlType.Text)))
|
|
16276
16309
|
personal = true;
|
|
16310
|
+
if (f.role === FORM_CHANNEL_ROLE && !isChannelFilled(f.props['href'])) {
|
|
16311
|
+
add(ctx, SiteFindingCode.EmptyChannel, 'A form\'s second way to reach you has no number or address yet — only you can fill it in.', { ...where, nodeId: f.id });
|
|
16312
|
+
}
|
|
16277
16313
|
});
|
|
16278
16314
|
});
|
|
16279
16315
|
return personal;
|